Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2019-06-14 17:46:31 +0300
committerFilipa Lacerda <filipa@gitlab.com>2019-06-14 17:46:31 +0300
commit6b3de25996e32f9b78cf4dbbad6dfeba346758fd (patch)
treece3f22d9f77be086eaa136ff559b0ec6f6db7262
parentba6e134e2814e6d7616990c7f9aa3a521b4082b3 (diff)
parentc449e35b33c55e2a0c8c3b7c08d0d68870e41ec4 (diff)
Merge branch 'master' into 59532-danger-css59532-danger-css
* master: (1920 commits) Upgrade gitlab-ui and migrate gl-pagination New translations gitlab.pot (Danish) [skip ci] Fix missing deployment rockets in monitor dashboard Add basic support for AsciiDoc include directive Improve the gitea importer test Backport of EE changes from MR 13763 Clarify ED25519 SSH key support Exclude preexisting lint issues for i18n Add back sidekiq metrics exporter Breakup first pass Use scoped routes for labels and milestones AutoDevops fix ensure_namespace() does not explicitly test namespace Speed up commit loads by disabling BatchLoader replace_methods Speed up merge request loads by disabling BatchLoader replace_methods Remove unused selector Disable unnecessary ESLint i18n offences Unquarantine spec in user_edits_files_spec.rb Refactor for cleaner caching in dashboards Update height of -tabs-height Change SLA to target SLO for bugs and defects ...
-rw-r--r--.codeclimate.yml58
-rw-r--r--.eslintrc.yml10
-rw-r--r--.gitignore3
-rw-r--r--.gitlab-ci.yml7
-rw-r--r--.gitlab/CODEOWNERS21
-rw-r--r--.gitlab/CODEOWNERS.disabled20
-rw-r--r--.gitlab/ci/cng.gitlab-ci.yml4
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml32
-rw-r--r--.gitlab/ci/global.gitlab-ci.yml6
-rw-r--r--.gitlab/ci/pages.gitlab-ci.yml1
-rw-r--r--.gitlab/ci/qa.gitlab-ci.yml13
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml97
-rw-r--r--.gitlab/ci/reports.gitlab-ci.yml62
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml127
-rw-r--r--.gitlab/ci/test-metadata.gitlab-ci.yml8
-rw-r--r--.gitlab/ci/yaml.gitlab-ci.yml9
-rw-r--r--.gitlab/issue_templates/Bug.md6
-rw-r--r--.gitlab/issue_templates/Database Reviewer.md8
-rw-r--r--.gitlab/issue_templates/Feature Flag Roll Out.md43
-rw-r--r--.gitlab/issue_templates/Refactoring.md41
-rw-r--r--.gitlab/issue_templates/Security developer workflow.md4
-rw-r--r--.gitlab/route-map.yml4
-rw-r--r--.haml-lint.yml10
-rw-r--r--.haml-lint_todo.yml523
-rw-r--r--.pkgr.yml4
-rw-r--r--.rubocop.yml1
-rw-r--r--.rubocop_todo.yml515
-rw-r--r--.ruby-version2
-rw-r--r--.stylelintrc10
-rw-r--r--.yamllint7
-rw-r--r--CHANGELOG.md697
-rw-r--r--CONTRIBUTING.md6
-rw-r--r--Dangerfile3
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--GITLAB_ELASTICSEARCH_INDEXER_VERSION1
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--GITLAB_WORKHORSE_VERSION2
-rw-r--r--Gemfile63
-rw-r--r--Gemfile.lock329
-rw-r--r--PROCESS.md31
-rw-r--r--VERSION2
-rw-r--r--app/assets/images/favicon-yellow.pngbin1667 -> 1481 bytes
-rw-r--r--app/assets/javascripts/api.js9
-rw-r--r--app/assets/javascripts/awards_handler.js2
-rw-r--r--app/assets/javascripts/batch_comments/mixins/resolved_status.js15
-rw-r--r--app/assets/javascripts/behaviors/copy_to_clipboard.js5
-rw-r--r--app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/table_of_contents.js3
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_mermaid.js2
-rw-r--r--app/assets/javascripts/behaviors/preview_markdown.js4
-rw-r--r--app/assets/javascripts/behaviors/quick_submit.js5
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js2
-rw-r--r--app/assets/javascripts/blob/balsamiq_viewer.js3
-rw-r--r--app/assets/javascripts/blob/blob_file_dropzone.js5
-rw-r--r--app/assets/javascripts/blob/sketch/index.js5
-rw-r--r--app/assets/javascripts/blob/template_selectors/dockerfile_selector.js3
-rw-r--r--app/assets/javascripts/blob/viewer/index.js14
-rw-r--r--app/assets/javascripts/boards/boards_util.js7
-rw-r--r--app/assets/javascripts/boards/components/board_blank_state.vue13
-rw-r--r--app/assets/javascripts/boards/components/board_card.vue4
-rw-r--r--app/assets/javascripts/boards/components/board_delete.js3
-rw-r--r--app/assets/javascripts/boards/components/board_list.vue13
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue.vue10
-rw-r--r--app/assets/javascripts/boards/components/board_sidebar.js2
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner.vue42
-rw-r--r--app/assets/javascripts/boards/components/issue_due_date.vue6
-rw-r--r--app/assets/javascripts/boards/components/issue_time_estimate.vue2
-rw-r--r--app/assets/javascripts/boards/components/modal/empty_state.vue4
-rw-r--r--app/assets/javascripts/boards/components/modal/header.vue6
-rw-r--r--app/assets/javascripts/boards/components/modal/index.vue15
-rw-r--r--app/assets/javascripts/boards/components/modal/list.vue4
-rw-r--r--app/assets/javascripts/boards/components/new_list_dropdown.js3
-rw-r--r--app/assets/javascripts/boards/components/sidebar/remove_issue.vue2
-rw-r--r--app/assets/javascripts/boards/index.js38
-rw-r--r--app/assets/javascripts/boards/mixins/issue_card_inner.js5
-rw-r--r--app/assets/javascripts/boards/models/assignee.js (renamed from app/assets/javascripts/vue_shared/models/assignee.js)0
-rw-r--r--app/assets/javascripts/boards/models/issue.js2
-rw-r--r--app/assets/javascripts/boards/models/label.js11
-rw-r--r--app/assets/javascripts/boards/models/list.js9
-rw-r--r--app/assets/javascripts/boards/stores/actions.js66
-rw-r--r--app/assets/javascripts/boards/stores/boards_store.js43
-rw-r--r--app/assets/javascripts/boards/stores/index.js14
-rw-r--r--app/assets/javascripts/boards/stores/mutation_types.js21
-rw-r--r--app/assets/javascripts/boards/stores/mutations.js92
-rw-r--r--app/assets/javascripts/boards/stores/state.js3
-rw-r--r--app/assets/javascripts/branches/branches_delete_modal.js2
-rw-r--r--app/assets/javascripts/ci_variable_list/ajax_variable_list.js11
-rw-r--r--app/assets/javascripts/ci_variable_list/ci_variable_list.js10
-rw-r--r--app/assets/javascripts/ci_variable_list/native_form_variable_list.js1
-rw-r--r--app/assets/javascripts/clusters/clusters_bundle.js127
-rw-r--r--app/assets/javascripts/clusters/components/application_row.vue302
-rw-r--r--app/assets/javascripts/clusters/components/applications.vue253
-rw-r--r--app/assets/javascripts/clusters/components/knative_domain_editor.vue150
-rw-r--r--app/assets/javascripts/clusters/components/uninstall_application_button.vue33
-rw-r--r--app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue74
-rw-r--r--app/assets/javascripts/clusters/constants.js27
-rw-r--r--app/assets/javascripts/clusters/mixins/track_uninstall_button_click.js5
-rw-r--r--app/assets/javascripts/clusters/services/application_state_machine.js174
-rw-r--r--app/assets/javascripts/clusters/services/clusters_service.js4
-rw-r--r--app/assets/javascripts/clusters/stores/clusters_store.js111
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_table.vue2
-rw-r--r--app/assets/javascripts/commons/polyfills.js32
-rw-r--r--app/assets/javascripts/compare_autocomplete.js2
-rw-r--r--app/assets/javascripts/contextual_sidebar.js5
-rw-r--r--app/assets/javascripts/create_item_dropdown.js2
-rw-r--r--app/assets/javascripts/create_merge_request_dropdown.js6
-rw-r--r--app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js3
-rw-r--r--app/assets/javascripts/diff_notes/components/comment_resolve_btn.js9
-rw-r--r--app/assets/javascripts/diff_notes/components/diff_note_avatars.js3
-rw-r--r--app/assets/javascripts/diff_notes/components/jump_to_discussion.js5
-rw-r--r--app/assets/javascripts/diff_notes/components/resolve_btn.js12
-rw-r--r--app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js5
-rw-r--r--app/assets/javascripts/diff_notes/services/resolve.js4
-rw-r--r--app/assets/javascripts/diffs/components/app.vue12
-rw-r--r--app/assets/javascripts/diffs/components/commit_item.vue7
-rw-r--r--app/assets/javascripts/diffs/components/diff_content.vue18
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue25
-rw-r--r--app/assets/javascripts/diffs/components/diff_gutter_avatars.vue1
-rw-r--r--app/assets/javascripts/diffs/components/diff_line_gutter_content.vue6
-rw-r--r--app/assets/javascripts/diffs/components/diff_line_note_form.vue21
-rw-r--r--app/assets/javascripts/diffs/components/diff_table_cell.vue24
-rw-r--r--app/assets/javascripts/diffs/components/edit_button.vue2
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_table_row.vue15
-rw-r--r--app/assets/javascripts/diffs/components/tree_list.vue9
-rw-r--r--app/assets/javascripts/diffs/constants.js7
-rw-r--r--app/assets/javascripts/diffs/store/actions.js125
-rw-r--r--app/assets/javascripts/diffs/store/mutation_types.js5
-rw-r--r--app/assets/javascripts/diffs/store/mutations.js64
-rw-r--r--app/assets/javascripts/diffs/store/utils.js33
-rw-r--r--app/assets/javascripts/diffs/workers/tree_worker.js5
-rw-r--r--app/assets/javascripts/dirty_submit/dirty_submit_form.js11
-rw-r--r--app/assets/javascripts/dropzone_input.js15
-rw-r--r--app/assets/javascripts/due_date_select.js4
-rw-r--r--app/assets/javascripts/emoji/no_emoji_validator.js44
-rw-r--r--app/assets/javascripts/environments/components/container.vue2
-rw-r--r--app/assets/javascripts/environments/mixins/environments_mixin.js2
-rw-r--r--app/assets/javascripts/error_tracking_settings/store/getters.js4
-rw-r--r--app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js4
-rw-r--r--app/assets/javascripts/filtered_search/available_dropdown_mappings.js16
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_emoji.js3
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_non_user.js3
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_user.js14
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js6
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_manager.js7
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_token_keys.js4
-rw-r--r--app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js21
-rw-r--r--app/assets/javascripts/filtered_search/services/recent_searches_service_error.js4
-rw-r--r--app/assets/javascripts/filtered_search/visual_token_value.js11
-rw-r--r--app/assets/javascripts/fly_out_nav.js3
-rw-r--r--app/assets/javascripts/frequent_items/store/actions.js2
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js16
-rw-r--r--app/assets/javascripts/gl_dropdown.js17
-rw-r--r--app/assets/javascripts/gl_field_error.js3
-rw-r--r--app/assets/javascripts/gl_form.js6
-rw-r--r--app/assets/javascripts/gpg_badges.js2
-rw-r--r--app/assets/javascripts/groups/transfer_dropdown.js3
-rw-r--r--app/assets/javascripts/groups_select.js3
-rw-r--r--app/assets/javascripts/ide/components/activity_bar.vue2
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/actions.vue34
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/message_field.vue1
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/new_merge_request_option.vue43
-rw-r--r--app/assets/javascripts/ide/components/ide.vue42
-rw-r--r--app/assets/javascripts/ide/components/ide_status_bar.vue16
-rw-r--r--app/assets/javascripts/ide/components/ide_status_list.vue23
-rw-r--r--app/assets/javascripts/ide/components/ide_tree_list.vue19
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/modal.vue1
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/upload.vue2
-rw-r--r--app/assets/javascripts/ide/components/preview/clientside.vue2
-rw-r--r--app/assets/javascripts/ide/components/repo_commit_section.vue2
-rw-r--r--app/assets/javascripts/ide/components/repo_editor.vue10
-rw-r--r--app/assets/javascripts/ide/constants.js7
-rw-r--r--app/assets/javascripts/ide/ide_router.js13
-rw-r--r--app/assets/javascripts/ide/lib/editor_options.js2
-rw-r--r--app/assets/javascripts/ide/lib/files.js4
-rw-r--r--app/assets/javascripts/ide/lib/keymap.json8
-rw-r--r--app/assets/javascripts/ide/stores/actions.js63
-rw-r--r--app/assets/javascripts/ide/stores/actions/file.js12
-rw-r--r--app/assets/javascripts/ide/stores/actions/project.js118
-rw-r--r--app/assets/javascripts/ide/stores/actions/tree.js18
-rw-r--r--app/assets/javascripts/ide/stores/getters.js15
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/actions.js36
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/getters.js7
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/mutation_types.js1
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/mutations.js18
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/state.js1
-rw-r--r--app/assets/javascripts/ide/stores/modules/file_templates/actions.js25
-rw-r--r--app/assets/javascripts/ide/stores/modules/file_templates/getters.js5
-rw-r--r--app/assets/javascripts/ide/stores/modules/file_templates/mutations.js3
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/getters.js2
-rw-r--r--app/assets/javascripts/ide/stores/mutation_types.js1
-rw-r--r--app/assets/javascripts/ide/stores/mutations.js6
-rw-r--r--app/assets/javascripts/ide/stores/mutations/branch.js6
-rw-r--r--app/assets/javascripts/ide/stores/mutations/project.js5
-rw-r--r--app/assets/javascripts/ide/stores/utils.js14
-rw-r--r--app/assets/javascripts/image_diff/helpers/comment_indicator_helper.js2
-rw-r--r--app/assets/javascripts/image_diff/image_diff.js4
-rw-r--r--app/assets/javascripts/image_diff/view_types.js2
-rw-r--r--app/assets/javascripts/import_projects/components/import_projects_table.vue2
-rw-r--r--app/assets/javascripts/import_projects/store/getters.js6
-rw-r--r--app/assets/javascripts/import_projects/store/index.js2
-rw-r--r--app/assets/javascripts/integrations/integration_settings_form.js9
-rw-r--r--app/assets/javascripts/issuable_bulk_update_actions.js3
-rw-r--r--app/assets/javascripts/issuable_form.js2
-rw-r--r--app/assets/javascripts/issuable_index.js10
-rw-r--r--app/assets/javascripts/issue.js11
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue2
-rw-r--r--app/assets/javascripts/issue_show/components/description.vue1
-rw-r--r--app/assets/javascripts/issue_show/components/fields/description.vue1
-rw-r--r--app/assets/javascripts/issue_show/components/fields/title.vue1
-rw-r--r--app/assets/javascripts/issue_show/components/title.vue3
-rw-r--r--app/assets/javascripts/issue_status_select.js3
-rw-r--r--app/assets/javascripts/jobs/components/job_app.vue12
-rw-r--r--app/assets/javascripts/jobs/components/sidebar.vue3
-rw-r--r--app/assets/javascripts/jobs/components/stages_dropdown.vue11
-rw-r--r--app/assets/javascripts/jobs/store/actions.js26
-rw-r--r--app/assets/javascripts/jobs/store/mutation_types.js4
-rw-r--r--app/assets/javascripts/jobs/store/mutations.js19
-rw-r--r--app/assets/javascripts/jobs/store/state.js1
-rw-r--r--app/assets/javascripts/label_manager.js22
-rw-r--r--app/assets/javascripts/labels_select.js16
-rw-r--r--app/assets/javascripts/lib/graphql.js34
-rw-r--r--app/assets/javascripts/lib/utils/accessor.js2
-rw-r--r--app/assets/javascripts/lib/utils/autosave.js1
-rw-r--r--app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js9
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js10
-rw-r--r--app/assets/javascripts/lib/utils/datetime_utility.js37
-rw-r--r--app/assets/javascripts/lib/utils/highlight.js6
-rw-r--r--app/assets/javascripts/lib/utils/invalid_url.js6
-rw-r--r--app/assets/javascripts/lib/utils/notify.js2
-rw-r--r--app/assets/javascripts/lib/utils/number_utils.js15
-rw-r--r--app/assets/javascripts/lib/utils/text_markdown.js6
-rw-r--r--app/assets/javascripts/lib/utils/url_utility.js48
-rw-r--r--app/assets/javascripts/lib/utils/webpack.js4
-rw-r--r--app/assets/javascripts/locale/index.js2
-rw-r--r--app/assets/javascripts/main.js23
-rw-r--r--app/assets/javascripts/merge_conflicts/merge_conflict_store.js15
-rw-r--r--app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js3
-rw-r--r--app/assets/javascripts/merge_request_tabs.js5
-rw-r--r--app/assets/javascripts/milestone.js3
-rw-r--r--app/assets/javascripts/milestone_select.js15
-rw-r--r--app/assets/javascripts/mini_pipeline_graph_dropdown.js3
-rw-r--r--app/assets/javascripts/mirrors/mirror_repos.js2
-rw-r--r--app/assets/javascripts/mirrors/ssh_mirror.js114
-rw-r--r--app/assets/javascripts/monitoring/components/charts/area.vue21
-rw-r--r--app/assets/javascripts/monitoring/components/charts/single_stat.vue37
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue279
-rw-r--r--app/assets/javascripts/monitoring/constants.js9
-rw-r--r--app/assets/javascripts/monitoring/monitoring_bundle.js13
-rw-r--r--app/assets/javascripts/monitoring/services/monitoring_service.js75
-rw-r--r--app/assets/javascripts/monitoring/stores/actions.js207
-rw-r--r--app/assets/javascripts/monitoring/stores/index.js21
-rw-r--r--app/assets/javascripts/monitoring/stores/monitoring_store.js112
-rw-r--r--app/assets/javascripts/monitoring/stores/mutation_types.js15
-rw-r--r--app/assets/javascripts/monitoring/stores/mutations.js88
-rw-r--r--app/assets/javascripts/monitoring/stores/state.js17
-rw-r--r--app/assets/javascripts/monitoring/stores/utils.js85
-rw-r--r--app/assets/javascripts/mr_notes/stores/getters.js2
-rw-r--r--app/assets/javascripts/mr_popover/constants.js8
-rw-r--r--app/assets/javascripts/mr_popover/index.js15
-rw-r--r--app/assets/javascripts/namespace_select.js3
-rw-r--r--app/assets/javascripts/namespaces/leave_by_url.js22
-rw-r--r--app/assets/javascripts/new_branch_form.js2
-rw-r--r--app/assets/javascripts/notes.js71
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue3
-rw-r--r--app/assets/javascripts/notes/components/discussion_actions.vue58
-rw-r--r--app/assets/javascripts/notes/components/discussion_counter.vue14
-rw-r--r--app/assets/javascripts/notes/components/discussion_filter.vue4
-rw-r--r--app/assets/javascripts/notes/components/discussion_locked_widget.vue20
-rw-r--r--app/assets/javascripts/notes/components/discussion_notes.vue155
-rw-r--r--app/assets/javascripts/notes/components/note_actions.vue25
-rw-r--r--app/assets/javascripts/notes/components/note_awards_list.vue6
-rw-r--r--app/assets/javascripts/notes/components/note_body.vue7
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue111
-rw-r--r--app/assets/javascripts/notes/components/note_header.vue2
-rw-r--r--app/assets/javascripts/notes/components/noteable_discussion.vue226
-rw-r--r--app/assets/javascripts/notes/components/noteable_note.vue11
-rw-r--r--app/assets/javascripts/notes/components/notes_app.vue7
-rw-r--r--app/assets/javascripts/notes/mixins/autosave.js3
-rw-r--r--app/assets/javascripts/notes/mixins/issuable_state.js15
-rw-r--r--app/assets/javascripts/notes/mixins/note_form.js24
-rw-r--r--app/assets/javascripts/notes/stores/actions.js54
-rw-r--r--app/assets/javascripts/notes/stores/getters.js2
-rw-r--r--app/assets/javascripts/notes/stores/utils.js14
-rw-r--r--app/assets/javascripts/operation_settings/components/external_dashboard.vue67
-rw-r--r--app/assets/javascripts/operation_settings/index.js15
-rw-r--r--app/assets/javascripts/operation_settings/store/actions.js38
-rw-r--r--app/assets/javascripts/operation_settings/store/index.js16
-rw-r--r--app/assets/javascripts/operation_settings/store/mutation_types.js3
-rw-r--r--app/assets/javascripts/operation_settings/store/mutations.js7
-rw-r--r--app/assets/javascripts/operation_settings/store/state.js5
-rw-r--r--app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js2
-rw-r--r--app/assets/javascripts/pages/admin/clusters/destroy/index.js5
-rw-r--r--app/assets/javascripts/pages/admin/clusters/edit/index.js5
-rw-r--r--app/assets/javascripts/pages/admin/clusters/index.js21
-rw-r--r--app/assets/javascripts/pages/admin/clusters/index/index.js6
-rw-r--r--app/assets/javascripts/pages/admin/clusters/show/index.js5
-rw-r--r--app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js1
-rw-r--r--app/assets/javascripts/pages/groups/show/index.js2
-rw-r--r--app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue8
-rw-r--r--app/assets/javascripts/pages/profiles/keys/index.js2
-rw-r--r--app/assets/javascripts/pages/profiles/show/index.js7
-rw-r--r--app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js15
-rw-r--r--app/assets/javascripts/pages/projects/issues/index/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/pages_domains/edit/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/pages_domains/form.js43
-rw-r--r--app/assets/javascripts/pages/projects/pages_domains/new/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue2
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js42
-rw-r--r--app/assets/javascripts/pages/projects/project.js12
-rw-r--r--app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js1
-rw-r--r--app/assets/javascripts/pages/projects/settings/operations/show/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue5
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/constants.js10
-rw-r--r--app/assets/javascripts/pages/projects/show/index.js10
-rw-r--r--app/assets/javascripts/pages/projects/tree/show/index.js8
-rw-r--r--app/assets/javascripts/pages/search/show/search.js7
-rw-r--r--app/assets/javascripts/pages/sessions/new/index.js2
-rw-r--r--app/assets/javascripts/pages/sessions/new/length_validator.js32
-rw-r--r--app/assets/javascripts/pages/users/activity_calendar.js50
-rw-r--r--app/assets/javascripts/pdf/index.vue4
-rw-r--r--app/assets/javascripts/performance_bar/components/detailed_metric.vue34
-rw-r--r--app/assets/javascripts/performance_bar/components/performance_bar_app.vue2
-rw-r--r--app/assets/javascripts/performance_bar/components/request_selector.vue7
-rw-r--r--app/assets/javascripts/pipelines/components/graph/action_component.vue14
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component.vue1
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_name_component.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/stage_column_component.vue25
-rw-r--r--app/assets/javascripts/pipelines/components/header_component.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_triggerer.vue35
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_url.vue20
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_table.vue13
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_table_row.vue7
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_bundle.js1
-rw-r--r--app/assets/javascripts/profile/account/index.js2
-rw-r--r--app/assets/javascripts/profile/profile.js12
-rw-r--r--app/assets/javascripts/project_label_subscription.js4
-rw-r--r--app/assets/javascripts/project_select.js5
-rw-r--r--app/assets/javascripts/projects/gke_cluster_dropdowns/store/actions.js2
-rw-r--r--app/assets/javascripts/projects/gke_cluster_dropdowns/store/getters.js6
-rw-r--r--app/assets/javascripts/projects/project_new.js41
-rw-r--r--app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js4
-rw-r--r--app/assets/javascripts/protected_branches/protected_branch_create.js3
-rw-r--r--app/assets/javascripts/protected_branches/protected_branch_edit.js3
-rw-r--r--app/assets/javascripts/protected_tags/protected_tag_access_dropdown.js4
-rw-r--r--app/assets/javascripts/protected_tags/protected_tag_create.js3
-rw-r--r--app/assets/javascripts/protected_tags/protected_tag_edit.js7
-rw-r--r--app/assets/javascripts/raven/index.js7
-rw-r--r--app/assets/javascripts/raven/raven_config.js11
-rw-r--r--app/assets/javascripts/registry/components/table_registry.vue2
-rw-r--r--app/assets/javascripts/registry/stores/mutations.js4
-rw-r--r--app/assets/javascripts/releases/components/release_block.vue4
-rw-r--r--app/assets/javascripts/reports/components/issues_list.vue22
-rw-r--r--app/assets/javascripts/reports/components/report_item.vue12
-rw-r--r--app/assets/javascripts/reports/components/report_section.vue50
-rw-r--r--app/assets/javascripts/reports/constants.js6
-rw-r--r--app/assets/javascripts/reports/store/state.js5
-rw-r--r--app/assets/javascripts/reports/store/utils.js6
-rw-r--r--app/assets/javascripts/repository/components/app.vue3
-rw-r--r--app/assets/javascripts/repository/components/breadcrumbs.vue61
-rw-r--r--app/assets/javascripts/repository/components/table/header.vue9
-rw-r--r--app/assets/javascripts/repository/components/table/index.vue146
-rw-r--r--app/assets/javascripts/repository/components/table/parent_row.vue37
-rw-r--r--app/assets/javascripts/repository/components/table/row.vue92
-rw-r--r--app/assets/javascripts/repository/fragmentTypes.json1
-rw-r--r--app/assets/javascripts/repository/graphql.js45
-rw-r--r--app/assets/javascripts/repository/index.js59
-rw-r--r--app/assets/javascripts/repository/mixins/get_ref.js14
-rw-r--r--app/assets/javascripts/repository/pages/index.vue18
-rw-r--r--app/assets/javascripts/repository/pages/tree.vue20
-rw-r--r--app/assets/javascripts/repository/queries/getFiles.graphql58
-rw-r--r--app/assets/javascripts/repository/queries/getProjectPath.graphql3
-rw-r--r--app/assets/javascripts/repository/queries/getProjectShortPath.graphql3
-rw-r--r--app/assets/javascripts/repository/queries/getRef.graphql3
-rw-r--r--app/assets/javascripts/repository/router.js29
-rw-r--r--app/assets/javascripts/repository/utils/icon.js99
-rw-r--r--app/assets/javascripts/repository/utils/title.js10
-rw-r--r--app/assets/javascripts/right_sidebar.js11
-rw-r--r--app/assets/javascripts/search_autocomplete.js13
-rw-r--r--app/assets/javascripts/serverless/components/functions.vue36
-rw-r--r--app/assets/javascripts/serverless/components/url.vue2
-rw-r--r--app/assets/javascripts/serverless/constants.js4
-rw-r--r--app/assets/javascripts/serverless/serverless_bundle.js3
-rw-r--r--app/assets/javascripts/serverless/store/actions.js29
-rw-r--r--app/assets/javascripts/serverless/store/mutation_types.js2
-rw-r--r--app/assets/javascripts/serverless/store/mutations.js15
-rw-r--r--app/assets/javascripts/serverless/store/state.js1
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue12
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignees.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue6
-rw-r--r--app/assets/javascripts/sidebar/lib/sidebar_move_issue.js7
-rw-r--r--app/assets/javascripts/sidebar/sidebar_mediator.js3
-rw-r--r--app/assets/javascripts/snippet/snippet_embed.js6
-rw-r--r--app/assets/javascripts/star.js2
-rw-r--r--app/assets/javascripts/subscription_select.js3
-rw-r--r--app/assets/javascripts/templates/issuable_template_selector.js3
-rw-r--r--app/assets/javascripts/terminal/terminal.js4
-rw-r--r--app/assets/javascripts/test_utils/index.js4
-rw-r--r--app/assets/javascripts/u2f/error.js12
-rw-r--r--app/assets/javascripts/usage_ping_consent.js3
-rw-r--r--app/assets/javascripts/users_select.js39
-rw-r--r--app/assets/javascripts/validators/input_validator.js34
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/comment.js132
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/constants.js37
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/index.js23
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/login.js52
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/note.js27
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/utils.js42
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/wrapper.js82
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/wrapper_icons.js15
-rw-r--r--app/assets/javascripts/visual_review_toolbar/index.js37
-rw-r--r--app/assets/javascripts/visual_review_toolbar/store/events.js36
-rw-r--r--app/assets/javascripts/visual_review_toolbar/store/index.js5
-rw-r--r--app/assets/javascripts/visual_review_toolbar/store/state.js77
-rw-r--r--app/assets/javascripts/visual_review_toolbar/store/utils.js15
-rw-r--r--app/assets/javascripts/visual_review_toolbar/styles/toolbar.css149
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment.vue45
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue15
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue38
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/review_app_link.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue134
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue130
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue59
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/constants.js10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mixins/auto_merge.js15
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js19
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue76
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js35
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/ci_pipeline_link.vue32
-rw-r--r--app/assets/javascripts/vue_shared/components/clipboard_button.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/commit.vue12
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue12
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/lib/viewer_utils.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue11
-rw-r--r--app/assets/javascripts/vue_shared/components/droplab_dropdown_button.vue89
-rw-r--r--app/assets/javascripts/vue_shared/components/header_ci_component.vue20
-rw-r--r--app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue13
-rw-r--r--app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue20
-rw-r--r--app/assets/javascripts/vue_shared/components/issue/issue_warning.vue45
-rw-r--r--app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue40
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue20
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar.vue27
-rw-r--r--app/assets/javascripts/vue_shared/components/modal_copy_button.vue121
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/system_note.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/pagination/constants.js13
-rw-r--r--app/assets/javascripts/vue_shared/components/pagination/graphql_pagination.vue47
-rw-r--r--app/assets/javascripts/vue_shared/components/pagination/table_pagination.vue159
-rw-r--r--app/assets/javascripts/vue_shared/components/pagination_links.vue29
-rw-r--r--app/assets/javascripts/vue_shared/components/pikaday.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/select2_select.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/table_pagination.vue159
-rw-r--r--app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue25
-rw-r--r--app/assets/javascripts/vue_shared/directives/tooltip.js1
-rw-r--r--app/assets/javascripts/vue_shared/models/label.js13
-rw-r--r--app/assets/stylesheets/bootstrap_migration.scss9
-rw-r--r--app/assets/stylesheets/components/avatar.scss195
-rw-r--r--app/assets/stylesheets/components/dashboard_skeleton.scss23
-rw-r--r--app/assets/stylesheets/components/popover.scss139
-rw-r--r--app/assets/stylesheets/components/related_items_list.scss406
-rw-r--r--app/assets/stylesheets/components/toast.scss53
-rw-r--r--app/assets/stylesheets/errors.scss2
-rw-r--r--app/assets/stylesheets/framework.scss1
-rw-r--r--app/assets/stylesheets/framework/animations.scss24
-rw-r--r--app/assets/stylesheets/framework/avatar.scss194
-rw-r--r--app/assets/stylesheets/framework/awards.scss8
-rw-r--r--app/assets/stylesheets/framework/blocks.scss23
-rw-r--r--app/assets/stylesheets/framework/buttons.scss40
-rw-r--r--app/assets/stylesheets/framework/ci_variable_list.scss1
-rw-r--r--app/assets/stylesheets/framework/common.scss78
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss8
-rw-r--r--app/assets/stylesheets/framework/feature_highlight.scss7
-rw-r--r--app/assets/stylesheets/framework/files.scss29
-rw-r--r--app/assets/stylesheets/framework/filters.scss2
-rw-r--r--app/assets/stylesheets/framework/flash.scss29
-rw-r--r--app/assets/stylesheets/framework/forms.scss114
-rw-r--r--app/assets/stylesheets/framework/header.scss62
-rw-r--r--app/assets/stylesheets/framework/highlight.scss9
-rw-r--r--app/assets/stylesheets/framework/issue_box.scss4
-rw-r--r--app/assets/stylesheets/framework/lists.scss8
-rw-r--r--app/assets/stylesheets/framework/mixins.scss39
-rw-r--r--app/assets/stylesheets/framework/modal.scss14
-rw-r--r--app/assets/stylesheets/framework/secondary_navigation_elements.scss52
-rw-r--r--app/assets/stylesheets/framework/snippets.scss4
-rw-r--r--app/assets/stylesheets/framework/timeline.scss5
-rw-r--r--app/assets/stylesheets/framework/typography.scss5
-rw-r--r--app/assets/stylesheets/framework/variables.scss32
-rw-r--r--app/assets/stylesheets/framework/variables_overrides.scss1
-rw-r--r--app/assets/stylesheets/page_bundles/_ide_mixins.scss14
-rw-r--r--app/assets/stylesheets/page_bundles/ide.scss17
-rw-r--r--app/assets/stylesheets/pages/boards.scss211
-rw-r--r--app/assets/stylesheets/pages/clusters.scss2
-rw-r--r--app/assets/stylesheets/pages/commits.scss60
-rw-r--r--app/assets/stylesheets/pages/detail_page.scss2
-rw-r--r--app/assets/stylesheets/pages/diff.scss39
-rw-r--r--app/assets/stylesheets/pages/events.scss10
-rw-r--r--app/assets/stylesheets/pages/groups.scss3
-rw-r--r--app/assets/stylesheets/pages/issuable.scss20
-rw-r--r--app/assets/stylesheets/pages/issues.scss11
-rw-r--r--app/assets/stylesheets/pages/labels.scss11
-rw-r--r--app/assets/stylesheets/pages/login.scss16
-rw-r--r--app/assets/stylesheets/pages/members.scss64
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss99
-rw-r--r--app/assets/stylesheets/pages/milestone.scss21
-rw-r--r--app/assets/stylesheets/pages/note_form.scss41
-rw-r--r--app/assets/stylesheets/pages/notes.scss88
-rw-r--r--app/assets/stylesheets/pages/notifications.scss28
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss8
-rw-r--r--app/assets/stylesheets/pages/projects.scss83
-rw-r--r--app/assets/stylesheets/pages/prometheus.scss1
-rw-r--r--app/assets/stylesheets/pages/search.scss15
-rw-r--r--app/assets/stylesheets/pages/todos.scss61
-rw-r--r--app/assets/stylesheets/performance_bar.scss8
-rw-r--r--app/controllers/acme_challenges_controller.rb17
-rw-r--r--app/controllers/admin/application_controller.rb7
-rw-r--r--app/controllers/admin/application_settings_controller.rb23
-rw-r--r--app/controllers/admin/clusters/applications_controller.rb11
-rw-r--r--app/controllers/admin/clusters_controller.rb13
-rw-r--r--app/controllers/admin/logs_controller.rb3
-rw-r--r--app/controllers/admin/projects_controller.rb11
-rw-r--r--app/controllers/application_controller.rb15
-rw-r--r--app/controllers/clusters/applications_controller.rb13
-rw-r--r--app/controllers/clusters/clusters_controller.rb2
-rw-r--r--app/controllers/concerns/authenticates_with_two_factor.rb7
-rw-r--r--app/controllers/concerns/boards_actions.rb8
-rw-r--r--app/controllers/concerns/boards_responses.rb6
-rw-r--r--app/controllers/concerns/enforces_admin_authentication.rb19
-rw-r--r--app/controllers/concerns/enforces_two_factor_authentication.rb2
-rw-r--r--app/controllers/concerns/import_url_params.rb19
-rw-r--r--app/controllers/concerns/issuable_collections.rb6
-rw-r--r--app/controllers/concerns/milestone_actions.rb8
-rw-r--r--app/controllers/concerns/project_unauthorized.rb14
-rw-r--r--app/controllers/concerns/routable_actions.rb18
-rw-r--r--app/controllers/dashboard/projects_controller.rb19
-rw-r--r--app/controllers/graphql_controller.rb47
-rw-r--r--app/controllers/groups/variables_controller.rb2
-rw-r--r--app/controllers/help_controller.rb2
-rw-r--r--app/controllers/import/bitbucket_server_controller.rb4
-rw-r--r--app/controllers/import/fogbugz_controller.rb8
-rw-r--r--app/controllers/import/phabricator_controller.rb35
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb7
-rw-r--r--app/controllers/profiles/accounts_controller.rb2
-rw-r--r--app/controllers/profiles/emails_controller.rb4
-rw-r--r--app/controllers/profiles/groups_controller.rb24
-rw-r--r--app/controllers/profiles/notifications_controller.rb4
-rw-r--r--app/controllers/profiles/passwords_controller.rb10
-rw-r--r--app/controllers/profiles/preferences_controller.rb4
-rw-r--r--app/controllers/profiles/two_factor_auths_controller.rb6
-rw-r--r--app/controllers/profiles_controller.rb7
-rw-r--r--app/controllers/projects/application_controller.rb3
-rw-r--r--app/controllers/projects/branches_controller.rb8
-rw-r--r--app/controllers/projects/clusters/applications_controller.rb4
-rw-r--r--app/controllers/projects/clusters_controller.rb8
-rw-r--r--app/controllers/projects/environments/prometheus_api_controller.rb2
-rw-r--r--app/controllers/projects/environments_controller.rb48
-rw-r--r--app/controllers/projects/git_http_client_controller.rb1
-rw-r--r--app/controllers/projects/imports_controller.rb7
-rw-r--r--app/controllers/projects/issues_controller.rb20
-rw-r--r--app/controllers/projects/merge_requests/application_controller.rb10
-rw-r--r--app/controllers/projects/merge_requests_controller.rb44
-rw-r--r--app/controllers/projects/mirrors_controller.rb1
-rw-r--r--app/controllers/projects/pages_domains_controller.rb4
-rw-r--r--app/controllers/projects/pipeline_schedules_controller.rb2
-rw-r--r--app/controllers/projects/pipelines_controller.rb2
-rw-r--r--app/controllers/projects/repositories_controller.rb2
-rw-r--r--app/controllers/projects/serverless/functions_controller.rb12
-rw-r--r--app/controllers/projects/settings/ci_cd_controller.rb5
-rw-r--r--app/controllers/projects/settings/operations_controller.rb2
-rw-r--r--app/controllers/projects/stages_controller.rb25
-rw-r--r--app/controllers/projects/variables_controller.rb2
-rw-r--r--app/controllers/projects/wikis_controller.rb4
-rw-r--r--app/controllers/projects_controller.rb8
-rw-r--r--app/controllers/registrations_controller.rb25
-rw-r--r--app/controllers/sessions_controller.rb21
-rw-r--r--app/controllers/uploads_controller.rb7
-rw-r--r--app/finders/autocomplete/users_finder.rb10
-rw-r--r--app/finders/clusters/knative_services_finder.rb112
-rw-r--r--app/finders/issuable_finder.rb37
-rw-r--r--app/finders/issues_finder.rb4
-rw-r--r--app/finders/members_finder.rb43
-rw-r--r--app/finders/projects/serverless/functions_finder.rb46
-rw-r--r--app/finders/projects_finder.rb8
-rw-r--r--app/graphql/gitlab_schema.rb82
-rw-r--r--app/graphql/mutations/merge_requests/base.rb2
-rw-r--r--app/graphql/resolvers/base_resolver.rb19
-rw-r--r--app/graphql/resolvers/concerns/resolves_pipelines.rb10
-rw-r--r--app/graphql/resolvers/full_path_resolver.rb6
-rw-r--r--app/graphql/resolvers/group_resolver.rb13
-rw-r--r--app/graphql/resolvers/issues_resolver.rb17
-rw-r--r--app/graphql/resolvers/merge_requests_resolver.rb4
-rw-r--r--app/graphql/resolvers/namespace_projects_resolver.rb33
-rw-r--r--app/graphql/resolvers/namespace_resolver.rb13
-rw-r--r--app/graphql/resolvers/project_resolver.rb4
-rw-r--r--app/graphql/resolvers/tree_resolver.rb26
-rw-r--r--app/graphql/types/base_field.rb37
-rw-r--r--app/graphql/types/base_object.rb5
-rw-r--r--app/graphql/types/ci/pipeline_type.rb2
-rw-r--r--app/graphql/types/group_type.rb23
-rw-r--r--app/graphql/types/issue_type.rb12
-rw-r--r--app/graphql/types/merge_request_type.rb2
-rw-r--r--app/graphql/types/namespace_type.rb24
-rw-r--r--app/graphql/types/permission_types/group.rb11
-rw-r--r--app/graphql/types/project_statistics_type.rb16
-rw-r--r--app/graphql/types/project_type.rb9
-rw-r--r--app/graphql/types/query_type.rb10
-rw-r--r--app/graphql/types/repository_type.rb14
-rw-r--r--app/graphql/types/tree/blob_type.rb17
-rw-r--r--app/graphql/types/tree/entry_type.rb14
-rw-r--r--app/graphql/types/tree/submodule_type.rb10
-rw-r--r--app/graphql/types/tree/tree_entry_type.rb15
-rw-r--r--app/graphql/types/tree/tree_type.rb18
-rw-r--r--app/graphql/types/tree/type_enum.rb14
-rw-r--r--app/helpers/application_settings_helper.rb5
-rw-r--r--app/helpers/auth_helper.rb2
-rw-r--r--app/helpers/blob_helper.rb2
-rw-r--r--app/helpers/broadcast_messages_helper.rb2
-rw-r--r--app/helpers/ci_status_helper.rb2
-rw-r--r--app/helpers/ci_variables_helper.rb13
-rw-r--r--app/helpers/clusters_helper.rb5
-rw-r--r--app/helpers/dashboard_helper.rb4
-rw-r--r--app/helpers/dropdowns_helper.rb2
-rw-r--r--app/helpers/emails_helper.rb29
-rw-r--r--app/helpers/environments_helper.rb6
-rw-r--r--app/helpers/events_helper.rb12
-rw-r--r--app/helpers/groups/group_members_helper.rb7
-rw-r--r--app/helpers/groups_helper.rb2
-rw-r--r--app/helpers/labels_helper.rb115
-rw-r--r--app/helpers/markup_helper.rb10
-rw-r--r--app/helpers/merge_requests_helper.rb2
-rw-r--r--app/helpers/mirror_helper.rb4
-rw-r--r--app/helpers/nav_helper.rb8
-rw-r--r--app/helpers/notes_helper.rb10
-rw-r--r--app/helpers/notifications_helper.rb11
-rw-r--r--app/helpers/page_layout_helper.rb3
-rw-r--r--app/helpers/projects_helper.rb50
-rw-r--r--app/helpers/search_helper.rb8
-rw-r--r--app/helpers/sidekiq_helper.rb2
-rw-r--r--app/helpers/sorting_helper.rb149
-rw-r--r--app/helpers/storage_helper.rb13
-rw-r--r--app/helpers/tracking_helper.rb7
-rw-r--r--app/helpers/visibility_level_helper.rb38
-rw-r--r--app/mailers/devise_mailer.rb1
-rw-r--r--app/mailers/emails/issues.rb11
-rw-r--r--app/mailers/emails/members.rb3
-rw-r--r--app/mailers/emails/merge_requests.rb6
-rw-r--r--app/mailers/emails/notes.rb2
-rw-r--r--app/mailers/emails/pages_domains.rb8
-rw-r--r--app/mailers/emails/projects.rb10
-rw-r--r--app/mailers/emails/remote_mirrors.rb2
-rw-r--r--app/mailers/notify.rb16
-rw-r--r--app/mailers/repository_check_mailer.rb2
-rw-r--r--app/models/active_session.rb49
-rw-r--r--app/models/application_record.rb21
-rw-r--r--app/models/application_setting.rb16
-rw-r--r--app/models/application_setting_implementation.rb19
-rw-r--r--app/models/broadcast_message.rb11
-rw-r--r--app/models/ci/bridge.rb3
-rw-r--r--app/models/ci/build.rb90
-rw-r--r--app/models/ci/job_artifact.rb34
-rw-r--r--app/models/ci/legacy_stage.rb4
-rw-r--r--app/models/ci/pipeline.rb27
-rw-r--r--app/models/ci/pipeline_schedule.rb29
-rw-r--r--app/models/ci/stage.rb4
-rw-r--r--app/models/clusters/applications/cert_manager.rb6
-rw-r--r--app/models/clusters/applications/helm.rb7
-rw-r--r--app/models/clusters/applications/ingress.rb7
-rw-r--r--app/models/clusters/applications/jupyter.rb26
-rw-r--r--app/models/clusters/applications/knative.rb56
-rw-r--r--app/models/clusters/applications/prometheus.rb18
-rw-r--r--app/models/clusters/applications/runner.rb15
-rw-r--r--app/models/clusters/cluster.rb88
-rw-r--r--app/models/clusters/concerns/application_core.rb10
-rw-r--r--app/models/clusters/concerns/application_data.rb74
-rw-r--r--app/models/clusters/concerns/application_status.rb13
-rw-r--r--app/models/clusters/instance.rb17
-rw-r--r--app/models/clusters/platforms/kubernetes.rb70
-rw-r--r--app/models/clusters/project.rb1
-rw-r--r--app/models/commit.rb13
-rw-r--r--app/models/commit_range.rb6
-rw-r--r--app/models/commit_status.rb2
-rw-r--r--app/models/concerns/artifact_migratable.rb58
-rw-r--r--app/models/concerns/avatarable.rb3
-rw-r--r--app/models/concerns/cache_markdown_field.rb88
-rw-r--r--app/models/concerns/ci/contextable.rb8
-rw-r--r--app/models/concerns/ci/pipeline_delegator.rb21
-rw-r--r--app/models/concerns/deployment_platform.rb13
-rw-r--r--app/models/concerns/has_ref.rb3
-rw-r--r--app/models/concerns/has_status.rb4
-rw-r--r--app/models/concerns/has_variable.rb7
-rw-r--r--app/models/concerns/issuable.rb10
-rw-r--r--app/models/concerns/maskable.rb4
-rw-r--r--app/models/concerns/milestoneish.rb20
-rw-r--r--app/models/concerns/noteable.rb14
-rw-r--r--app/models/concerns/prometheus_adapter.rb1
-rw-r--r--app/models/concerns/reactive_caching.rb4
-rw-r--r--app/models/concerns/redactable.rb2
-rw-r--r--app/models/concerns/referable.rb1
-rw-r--r--app/models/concerns/resolvable_note.rb2
-rw-r--r--app/models/concerns/storage/legacy_namespace.rb24
-rw-r--r--app/models/concerns/taskable.rb9
-rw-r--r--app/models/concerns/update_project_statistics.rb72
-rw-r--r--app/models/deployment.rb17
-rw-r--r--app/models/diff_note.rb22
-rw-r--r--app/models/environment.rb8
-rw-r--r--app/models/error_tracking/project_error_tracking_setting.rb2
-rw-r--r--app/models/event.rb54
-rw-r--r--app/models/global_label.rb6
-rw-r--r--app/models/global_milestone.rb4
-rw-r--r--app/models/group.rb20
-rw-r--r--app/models/identity.rb1
-rw-r--r--app/models/internal_id.rb8
-rw-r--r--app/models/issue.rb8
-rw-r--r--app/models/key.rb5
-rw-r--r--app/models/label.rb6
-rw-r--r--app/models/lfs_object.rb2
-rw-r--r--app/models/member.rb6
-rw-r--r--app/models/members/group_member.rb4
-rw-r--r--app/models/members/project_member.rb2
-rw-r--r--app/models/merge_request.rb69
-rw-r--r--app/models/merge_request_diff.rb15
-rw-r--r--app/models/milestone.rb11
-rw-r--r--app/models/namespace.rb47
-rw-r--r--app/models/note_diff_file.rb4
-rw-r--r--app/models/notification_recipient.rb71
-rw-r--r--app/models/notification_setting.rb9
-rw-r--r--app/models/pages_domain.rb29
-rw-r--r--app/models/pages_domain_acme_order.rb24
-rw-r--r--app/models/pool_repository.rb5
-rw-r--r--app/models/project.rb78
-rw-r--r--app/models/project_auto_devops.rb25
-rw-r--r--app/models/project_ci_cd_setting.rb20
-rw-r--r--app/models/project_metrics_setting.rb9
-rw-r--r--app/models/project_services/chat_message/deployment_message.rb77
-rw-r--r--app/models/project_services/chat_notification_service.rb4
-rw-r--r--app/models/project_services/discord_service.rb5
-rw-r--r--app/models/project_services/hangouts_chat_service.rb5
-rw-r--r--app/models/project_services/jira_service.rb1
-rw-r--r--app/models/project_services/kubernetes_service.rb14
-rw-r--r--app/models/project_services/microsoft_teams_service.rb5
-rw-r--r--app/models/project_services/pipelines_email_service.rb18
-rw-r--r--app/models/project_services/youtrack_service.rb6
-rw-r--r--app/models/project_statistics.rb25
-rw-r--r--app/models/project_wiki.rb22
-rw-r--r--app/models/push_event.rb2
-rw-r--r--app/models/release.rb7
-rw-r--r--app/models/remote_mirror.rb14
-rw-r--r--app/models/repository.rb90
-rw-r--r--app/models/route.rb16
-rw-r--r--app/models/service.rb3
-rw-r--r--app/models/storage/legacy_project.rb2
-rw-r--r--app/models/todo.rb3
-rw-r--r--app/models/user.rb22
-rw-r--r--app/models/user_preference.rb4
-rw-r--r--app/policies/clusters/cluster_policy.rb1
-rw-r--r--app/policies/clusters/instance_policy.rb21
-rw-r--r--app/policies/global_policy.rb1
-rw-r--r--app/policies/group_policy.rb6
-rw-r--r--app/policies/personal_snippet_policy.rb13
-rw-r--r--app/policies/project_policy.rb7
-rw-r--r--app/presenters/blob_presenter.rb6
-rw-r--r--app/presenters/ci/build_runner_presenter.rb19
-rw-r--r--app/presenters/ci/pipeline_presenter.rb14
-rw-r--r--app/presenters/clusters/cluster_presenter.rb8
-rw-r--r--app/presenters/instance_clusterable_presenter.rb69
-rw-r--r--app/presenters/issue_presenter.rb12
-rw-r--r--app/presenters/label_presenter.rb51
-rw-r--r--app/presenters/member_presenter.rb5
-rw-r--r--app/presenters/merge_request_presenter.rb22
-rw-r--r--app/presenters/project_presenter.rb4
-rw-r--r--app/presenters/tree_entry_presenter.rb9
-rw-r--r--app/serializers/analytics_stage_entity.rb5
-rw-r--r--app/serializers/board_serializer.rb5
-rw-r--r--app/serializers/board_simple_entity.rb5
-rw-r--r--app/serializers/build_details_entity.rb15
-rw-r--r--app/serializers/cluster_application_entity.rb1
-rw-r--r--app/serializers/concerns/user_status_tooltip.rb2
-rw-r--r--app/serializers/deployment_entity.rb33
-rw-r--r--app/serializers/issue_entity.rb8
-rw-r--r--app/serializers/job_artifact_report_entity.rb13
-rw-r--r--app/serializers/merge_request_widget_entity.rb10
-rw-r--r--app/serializers/pipeline_details_entity.rb5
-rw-r--r--app/serializers/pipeline_entity.rb3
-rw-r--r--app/serializers/test_case_entity.rb1
-rw-r--r--app/services/auto_merge/base_service.rb63
-rw-r--r--app/services/auto_merge/merge_when_pipeline_succeeds_service.rb30
-rw-r--r--app/services/auto_merge_service.rb56
-rw-r--r--app/services/ci/create_pipeline_service.rb8
-rw-r--r--app/services/ci/pipeline_schedule_service.rb13
-rw-r--r--app/services/ci/play_manual_stage_service.rb29
-rw-r--r--app/services/ci/register_job_service.rb7
-rw-r--r--app/services/ci/stop_environments_service.rb16
-rw-r--r--app/services/clusters/applications/base_service.rb2
-rw-r--r--app/services/clusters/applications/check_installation_progress_service.rb6
-rw-r--r--app/services/clusters/applications/check_uninstall_progress_service.rb62
-rw-r--r--app/services/clusters/applications/create_service.rb4
-rw-r--r--app/services/clusters/applications/destroy_service.rb23
-rw-r--r--app/services/clusters/applications/uninstall_service.rb29
-rw-r--r--app/services/clusters/applications/update_service.rb2
-rw-r--r--app/services/clusters/build_service.rb2
-rw-r--r--app/services/clusters/create_service.rb2
-rw-r--r--app/services/clusters/refresh_service.rb2
-rw-r--r--app/services/compare_service.rb4
-rw-r--r--app/services/concerns/users/participable_service.rb2
-rw-r--r--app/services/delete_branch_service.rb24
-rw-r--r--app/services/git/base_hooks_service.rb23
-rw-r--r--app/services/git/branch_hooks_service.rb6
-rw-r--r--app/services/git/branch_push_service.rb3
-rw-r--r--app/services/issuable/clone/content_rewriter.rb1
-rw-r--r--app/services/issues/close_service.rb13
-rw-r--r--app/services/lfs/file_transformer.rb9
-rw-r--r--app/services/members/create_service.rb11
-rw-r--r--app/services/members/destroy_service.rb2
-rw-r--r--app/services/merge_requests/base_service.rb35
-rw-r--r--app/services/merge_requests/close_service.rb2
-rw-r--r--app/services/merge_requests/create_pipeline_service.rb37
-rw-r--r--app/services/merge_requests/merge_when_pipeline_succeeds_service.rb47
-rw-r--r--app/services/merge_requests/post_merge_service.rb1
-rw-r--r--app/services/merge_requests/rebase_service.rb12
-rw-r--r--app/services/merge_requests/refresh_service.rb8
-rw-r--r--app/services/merge_requests/update_service.rb4
-rw-r--r--app/services/notification_recipient_service.rb4
-rw-r--r--app/services/notification_service.rb10
-rw-r--r--app/services/pages_domains/create_acme_order_service.rb31
-rw-r--r--app/services/pages_domains/obtain_lets_encrypt_certificate_service.rb41
-rw-r--r--app/services/preview_markdown_service.rb4
-rw-r--r--app/services/projects/after_import_service.rb2
-rw-r--r--app/services/projects/cleanup_service.rb47
-rw-r--r--app/services/projects/create_service.rb6
-rw-r--r--app/services/projects/fork_service.rb20
-rw-r--r--app/services/projects/git_deduplication_service.rb64
-rw-r--r--app/services/projects/housekeeping_service.rb7
-rw-r--r--app/services/projects/import_error_filter.rb2
-rw-r--r--app/services/projects/import_service.rb13
-rw-r--r--app/services/projects/lfs_pointers/lfs_download_link_list_service.rb16
-rw-r--r--app/services/projects/lfs_pointers/lfs_import_service.rb92
-rw-r--r--app/services/projects/lfs_pointers/lfs_link_service.rb4
-rw-r--r--app/services/projects/lfs_pointers/lfs_object_download_list_service.rb96
-rw-r--r--app/services/projects/operations/update_service.rb11
-rw-r--r--app/services/projects/propagate_service_template.rb2
-rw-r--r--app/services/projects/repository_languages_service.rb2
-rw-r--r--app/services/projects/transfer_service.rb5
-rw-r--r--app/services/projects/update_service.rb6
-rw-r--r--app/services/projects/update_statistics_service.rb2
-rw-r--r--app/services/service_response.rb31
-rw-r--r--app/services/system_hooks_service.rb6
-rw-r--r--app/services/system_note_service.rb12
-rw-r--r--app/services/tags/destroy_service.rb11
-rw-r--r--app/services/test_hooks/project_service.rb2
-rw-r--r--app/services/todos/destroy/base_service.rb2
-rw-r--r--app/services/todos/destroy/confidential_issue_service.rb35
-rw-r--r--app/services/todos/destroy/entity_leave_service.rb13
-rw-r--r--app/uploaders/attachment_uploader.rb2
-rw-r--r--app/uploaders/avatar_uploader.rb2
-rw-r--r--app/uploaders/file_uploader.rb16
-rw-r--r--app/uploaders/import_export_uploader.rb4
-rw-r--r--app/uploaders/legacy_artifact_uploader.rb27
-rw-r--r--app/uploaders/object_storage.rb2
-rw-r--r--app/uploaders/personal_file_uploader.rb70
-rw-r--r--app/views/abuse_reports/new.html.haml14
-rw-r--r--app/views/admin/application_settings/_external_authorization_service_form.html.haml2
-rw-r--r--app/views/admin/application_settings/_logging.html.haml6
-rw-r--r--app/views/admin/application_settings/_outbound.html.haml8
-rw-r--r--app/views/admin/application_settings/_pages.html.haml28
-rw-r--r--app/views/admin/application_settings/_performance_bar.html.haml6
-rw-r--r--app/views/admin/application_settings/_visibility_and_access.html.haml1
-rw-r--r--app/views/admin/application_settings/metrics_and_profiling.html.haml4
-rw-r--r--app/views/admin/applications/_form.html.haml12
-rw-r--r--app/views/admin/applications/show.html.haml4
-rw-r--r--app/views/admin/broadcast_messages/_form.html.haml16
-rw-r--r--app/views/admin/broadcast_messages/index.html.haml4
-rw-r--r--app/views/admin/groups/_form.html.haml5
-rw-r--r--app/views/admin/groups/show.html.haml10
-rw-r--r--app/views/admin/health_check/show.html.haml2
-rw-r--r--app/views/admin/identities/_form.html.haml6
-rw-r--r--app/views/admin/labels/_form.html.haml14
-rw-r--r--app/views/admin/labels/_label.html.haml2
-rw-r--r--app/views/admin/projects/_projects.html.haml6
-rw-r--r--app/views/admin/projects/index.html.haml2
-rw-r--r--app/views/admin/projects/show.html.haml20
-rw-r--r--app/views/admin/users/_access_levels.html.haml24
-rw-r--r--app/views/admin/users/_form.html.haml68
-rw-r--r--app/views/admin/users/_head.html.haml1
-rw-r--r--app/views/admin/users/show.html.haml2
-rw-r--r--app/views/award_emoji/_awards_block.html.haml6
-rw-r--r--app/views/ci/variables/_content.html.haml2
-rw-r--r--app/views/ci/variables/_index.html.haml3
-rw-r--r--app/views/ci/variables/_variable_header.html.haml16
-rw-r--r--app/views/ci/variables/_variable_row.html.haml28
-rw-r--r--app/views/clusters/clusters/_banner.html.haml12
-rw-r--r--app/views/clusters/clusters/gcp/_form.html.haml13
-rw-r--r--app/views/clusters/clusters/show.html.haml7
-rw-r--r--app/views/clusters/clusters/user/_form.html.haml52
-rw-r--r--app/views/clusters/platforms/kubernetes/_form.html.haml15
-rw-r--r--app/views/dashboard/_projects_head.html.haml24
-rw-r--r--app/views/dashboard/projects/_nav.html.haml27
-rw-r--r--app/views/dashboard/projects/_zero_authorized_projects.html.haml15
-rw-r--r--app/views/dashboard/projects/index.html.haml2
-rw-r--r--app/views/dashboard/projects/starred.html.haml2
-rw-r--r--app/views/dashboard/todos/_todo.html.haml2
-rw-r--r--app/views/dashboard/todos/index.html.haml2
-rw-r--r--app/views/devise/confirmations/new.html.haml2
-rw-r--r--app/views/devise/passwords/edit.html.haml2
-rw-r--r--app/views/devise/passwords/new.html.haml2
-rw-r--r--app/views/devise/registrations/edit.html.erb2
-rw-r--r--app/views/devise/shared/_signin_box.html.haml8
-rw-r--r--app/views/devise/shared/_signup_box.html.haml27
-rw-r--r--app/views/devise/shared/_tabs_ldap.html.haml1
-rw-r--r--app/views/devise/shared/_tabs_normal.html.haml2
-rw-r--r--app/views/devise/unlocks/new.html.haml2
-rw-r--r--app/views/discussions/_notes.html.haml20
-rw-r--r--app/views/doorkeeper/applications/show.html.haml4
-rw-r--r--app/views/events/_event.html.haml6
-rw-r--r--app/views/events/event/_common.html.haml3
-rw-r--r--app/views/events/event/_note.html.haml3
-rw-r--r--app/views/events/event/_push.html.haml3
-rw-r--r--app/views/explore/projects/_filter.html.haml10
-rw-r--r--app/views/explore/projects/index.html.haml4
-rw-r--r--app/views/explore/projects/starred.html.haml4
-rw-r--r--app/views/explore/projects/trending.html.haml4
-rw-r--r--app/views/groups/_create_chat_team.html.haml9
-rw-r--r--app/views/groups/_group_admin_settings.html.haml9
-rw-r--r--app/views/groups/edit.html.haml2
-rw-r--r--app/views/groups/group_members/_new_group_member.html.haml2
-rw-r--r--app/views/groups/group_members/index.html.haml2
-rw-r--r--app/views/groups/labels/index.html.haml7
-rw-r--r--app/views/groups/settings/_general.html.haml20
-rw-r--r--app/views/groups/settings/ci_cd/show.html.haml2
-rw-r--r--app/views/groups/show.html.haml2
-rw-r--r--app/views/help/index.html.haml6
-rw-r--r--app/views/help/ui.html.haml2
-rw-r--r--app/views/import/bitbucket_server/status.html.haml2
-rw-r--r--app/views/import/gitea/new.html.haml6
-rw-r--r--app/views/import/gitea/status.html.haml2
-rw-r--r--app/views/import/github/new.html.haml2
-rw-r--r--app/views/import/gitlab_projects/new.html.haml23
-rw-r--r--app/views/import/manifest/new.html.haml6
-rw-r--r--app/views/import/phabricator/new.html.haml25
-rw-r--r--app/views/import/shared/_errors.html.haml4
-rw-r--r--app/views/import/shared/_new_project_form.html.haml21
-rw-r--r--app/views/issues/_issue.atom.builder1
-rw-r--r--app/views/layouts/_head.html.haml1
-rw-r--r--app/views/layouts/_mailer.html.haml2
-rw-r--r--app/views/layouts/_page.html.haml1
-rw-r--r--app/views/layouts/_piwik.html.haml2
-rw-r--r--app/views/layouts/_search.html.haml2
-rw-r--r--app/views/layouts/application.html.haml2
-rw-r--r--app/views/layouts/devise.html.haml15
-rw-r--r--app/views/layouts/header/_default.html.haml6
-rw-r--r--app/views/layouts/header/_help_dropdown.html.haml5
-rw-r--r--app/views/layouts/mailer.text.erb1
-rw-r--r--app/views/layouts/nav/_dashboard.html.haml33
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml24
-rw-r--r--app/views/layouts/nav/sidebar/_group.html.haml4
-rw-r--r--app/views/layouts/nav/sidebar/_profile.html.haml6
-rw-r--r--app/views/layouts/nav/sidebar/_project.html.haml10
-rw-r--r--app/views/layouts/notify.html.haml2
-rw-r--r--app/views/layouts/notify.text.erb1
-rw-r--r--app/views/notify/closed_issue_email.html.haml2
-rw-r--r--app/views/notify/closed_issue_email.text.haml2
-rw-r--r--app/views/notify/links/ci/builds/_build.text.erb2
-rw-r--r--app/views/notify/member_access_granted_email.html.haml11
-rw-r--r--app/views/notify/member_access_granted_email.text.erb7
-rw-r--r--app/views/notify/new_merge_request_email.html.haml2
-rw-r--r--app/views/notify/new_user_email.html.haml3
-rw-r--r--app/views/notify/new_user_email.text.erb11
-rw-r--r--app/views/profiles/_event_table.html.haml6
-rw-r--r--app/views/profiles/active_sessions/_active_session.html.haml11
-rw-r--r--app/views/profiles/active_sessions/index.html.haml4
-rw-r--r--app/views/profiles/audit_log.html.haml4
-rw-r--r--app/views/profiles/chat_names/_chat_name.html.haml4
-rw-r--r--app/views/profiles/chat_names/index.html.haml16
-rw-r--r--app/views/profiles/emails/index.html.haml44
-rw-r--r--app/views/profiles/gpg_keys/_form.html.haml6
-rw-r--r--app/views/profiles/gpg_keys/_key.html.haml16
-rw-r--r--app/views/profiles/gpg_keys/_key_table.html.haml4
-rw-r--r--app/views/profiles/gpg_keys/index.html.haml12
-rw-r--r--app/views/profiles/keys/_form.html.haml8
-rw-r--r--app/views/profiles/keys/_key.html.haml9
-rw-r--r--app/views/profiles/keys/_key_details.html.haml13
-rw-r--r--app/views/profiles/keys/_key_table.html.haml4
-rw-r--r--app/views/profiles/keys/index.html.haml8
-rw-r--r--app/views/profiles/keys/show.html.haml2
-rw-r--r--app/views/profiles/notifications/_group_settings.html.haml23
-rw-r--r--app/views/profiles/notifications/show.html.haml21
-rw-r--r--app/views/profiles/passwords/edit.html.haml25
-rw-r--r--app/views/profiles/passwords/new.html.haml15
-rw-r--r--app/views/profiles/preferences/show.html.haml53
-rw-r--r--app/views/profiles/show.html.haml32
-rw-r--r--app/views/profiles/two_factor_auths/_codes.html.haml10
-rw-r--r--app/views/profiles/two_factor_auths/codes.html.haml5
-rw-r--r--app/views/profiles/two_factor_auths/create.html.haml4
-rw-r--r--app/views/profiles/two_factor_auths/show.html.haml61
-rw-r--r--app/views/projects/_files.html.haml9
-rw-r--r--app/views/projects/_flash_messages.html.haml1
-rw-r--r--app/views/projects/_home_panel.html.haml6
-rw-r--r--app/views/projects/_import_project_pane.html.haml30
-rw-r--r--app/views/projects/_merge_request_merge_checks_settings.html.haml19
-rw-r--r--app/views/projects/_merge_request_merge_method_settings.html.haml49
-rw-r--r--app/views/projects/_merge_request_merge_options_settings.html.haml14
-rw-r--r--app/views/projects/_merge_request_merge_settings.html.haml24
-rw-r--r--app/views/projects/_merge_request_settings.html.haml4
-rw-r--r--app/views/projects/_new_project_fields.html.haml4
-rw-r--r--app/views/projects/_zen.html.haml1
-rw-r--r--app/views/projects/blob/_header_content.html.haml2
-rw-r--r--app/views/projects/branches/_branch.html.haml4
-rw-r--r--app/views/projects/branches/_commit.html.haml4
-rw-r--r--app/views/projects/branches/index.html.haml3
-rw-r--r--app/views/projects/buttons/_download.html.haml45
-rw-r--r--app/views/projects/buttons/_download_links.html.haml5
-rw-r--r--app/views/projects/ci/builds/_build.html.haml7
-rw-r--r--app/views/projects/cleanup/_show.html.haml2
-rw-r--r--app/views/projects/commit/_commit_box.html.haml4
-rw-r--r--app/views/projects/commits/_commit.html.haml8
-rw-r--r--app/views/projects/commits/_inline_commit.html.haml2
-rw-r--r--app/views/projects/commits/show.html.haml2
-rw-r--r--app/views/projects/default_branch/_show.html.haml2
-rw-r--r--app/views/projects/deploy_keys/_index.html.haml2
-rw-r--r--app/views/projects/deployments/_commit.html.haml4
-rw-r--r--app/views/projects/diffs/_content.html.haml2
-rw-r--r--app/views/projects/diffs/_parallel_view.html.haml2
-rw-r--r--app/views/projects/diffs/_text_file.html.haml2
-rw-r--r--app/views/projects/edit.html.haml4
-rw-r--r--app/views/projects/forks/error.html.haml14
-rw-r--r--app/views/projects/forks/index.html.haml13
-rw-r--r--app/views/projects/forks/new.html.haml16
-rw-r--r--app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml4
-rw-r--r--app/views/projects/issues/_issue.html.haml8
-rw-r--r--app/views/projects/issues/_merge_requests_status.html.haml25
-rw-r--r--app/views/projects/issues/_new_branch.html.haml8
-rw-r--r--app/views/projects/issues/new.html.haml9
-rw-r--r--app/views/projects/issues/show.html.haml10
-rw-r--r--app/views/projects/jobs/_table.html.haml2
-rw-r--r--app/views/projects/labels/index.html.haml41
-rw-r--r--app/views/projects/merge_requests/_merge_request.html.haml4
-rw-r--r--app/views/projects/merge_requests/conflicts/components/_inline_conflict_lines.html.haml2
-rw-r--r--app/views/projects/merge_requests/show.html.haml43
-rw-r--r--app/views/projects/milestones/show.html.haml2
-rw-r--r--app/views/projects/mirrors/_authentication_method.html.haml21
-rw-r--r--app/views/projects/mirrors/_disabled_mirror_badge.html.haml1
-rw-r--r--app/views/projects/mirrors/_instructions.html.haml2
-rw-r--r--app/views/projects/mirrors/_mirror_repos.html.haml38
-rw-r--r--app/views/projects/mirrors/_mirror_repos_push.html.haml2
-rw-r--r--app/views/projects/mirrors/_ssh_host_keys.html.haml2
-rw-r--r--app/views/projects/new.html.haml11
-rw-r--r--app/views/projects/notes/_actions.html.haml6
-rw-r--r--app/views/projects/notes/_more_actions_dropdown.html.haml2
-rw-r--r--app/views/projects/pages_domains/_form.html.haml91
-rw-r--r--app/views/projects/pages_domains/_helper_text.html.haml9
-rw-r--r--app/views/projects/pages_domains/edit.html.haml1
-rw-r--r--app/views/projects/pages_domains/new.html.haml1
-rw-r--r--app/views/projects/project_members/_new_project_member.html.haml3
-rw-r--r--app/views/projects/project_members/index.html.haml42
-rw-r--r--app/views/projects/protected_branches/_protected_branch.html.haml2
-rw-r--r--app/views/projects/protected_branches/shared/_create_protected_branch.html.haml4
-rw-r--r--app/views/projects/protected_branches/shared/_index.html.haml2
-rw-r--r--app/views/projects/protected_tags/shared/_create_protected_tag.html.haml4
-rw-r--r--app/views/projects/protected_tags/shared/_index.html.haml2
-rw-r--r--app/views/projects/registry/repositories/_tag.html.haml2
-rw-r--r--app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml40
-rw-r--r--app/views/projects/services/slack_slash_commands/_help.html.haml38
-rw-r--r--app/views/projects/settings/_general.html.haml2
-rw-r--r--app/views/projects/settings/ci_cd/_form.html.haml8
-rw-r--r--app/views/projects/settings/ci_cd/show.html.haml2
-rw-r--r--app/views/projects/settings/operations/_error_tracking.html.haml4
-rw-r--r--app/views/projects/settings/operations/_external_dashboard.html.haml3
-rw-r--r--app/views/projects/settings/operations/show.html.haml3
-rw-r--r--app/views/projects/settings/repository/_protected_branches.html.haml2
-rw-r--r--app/views/projects/settings/repository/show.html.haml7
-rw-r--r--app/views/projects/tags/index.html.haml2
-rw-r--r--app/views/projects/tags/show.html.haml2
-rw-r--r--app/views/projects/tree/_readme.html.haml2
-rw-r--r--app/views/projects/tree/_tree_commit_column.html.haml3
-rw-r--r--app/views/projects/tree/_tree_header.html.haml121
-rw-r--r--app/views/repository_check_mailer/notify.html.haml2
-rw-r--r--app/views/repository_check_mailer/notify.text.haml2
-rw-r--r--app/views/search/_form.html.haml1
-rw-r--r--app/views/search/_results.html.haml8
-rw-r--r--app/views/search/results/_issue.html.haml2
-rw-r--r--app/views/search/results/_merge_request.html.haml2
-rw-r--r--app/views/search/results/_milestone.html.haml2
-rw-r--r--app/views/search/results/_wiki_blob.html.haml2
-rw-r--r--app/views/sent_notifications/unsubscribe.html.haml2
-rw-r--r--app/views/shared/_clone_panel.html.haml5
-rw-r--r--app/views/shared/_delete_label_modal.html.haml4
-rw-r--r--app/views/shared/_email_with_badge.html.haml2
-rw-r--r--app/views/shared/_import_form.html.haml30
-rw-r--r--app/views/shared/_label.html.haml10
-rw-r--r--app/views/shared/_label_row.html.haml17
-rw-r--r--app/views/shared/_mini_pipeline_graph.html.haml6
-rw-r--r--app/views/shared/_old_visibility_level.html.haml2
-rw-r--r--app/views/shared/_remote_mirror_update_button.html.haml2
-rw-r--r--app/views/shared/_sidebar_toggle_button.html.haml6
-rw-r--r--app/views/shared/boards/_show.html.haml10
-rw-r--r--app/views/shared/boards/components/_board.html.haml13
-rw-r--r--app/views/shared/boards/components/_sidebar.html.haml6
-rw-r--r--app/views/shared/boards/components/sidebar/_due_date.html.haml2
-rw-r--r--app/views/shared/boards/components/sidebar/_labels.html.haml2
-rw-r--r--app/views/shared/groups/_dropdown.html.haml6
-rw-r--r--app/views/shared/icons/_emoji_slightly_smiling_face.svg1
-rw-r--r--app/views/shared/icons/_emoji_smile.svg1
-rw-r--r--app/views/shared/icons/_emoji_smiley.svg1
-rw-r--r--app/views/shared/icons/_gitea_logo.svg.erb1
-rw-r--r--app/views/shared/issuable/_label_dropdown.html.haml2
-rw-r--r--app/views/shared/issuable/_label_page_create.html.haml4
-rw-r--r--app/views/shared/issuable/_label_page_default.html.haml2
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml6
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml12
-rw-r--r--app/views/shared/issuable/_sort_dropdown.html.haml15
-rw-r--r--app/views/shared/issuable/form/_contribution.html.haml2
-rw-r--r--app/views/shared/issuable/form/_title.html.haml2
-rw-r--r--app/views/shared/labels/_form.html.haml16
-rw-r--r--app/views/shared/members/_access_request_links.html.haml2
-rw-r--r--app/views/shared/members/_group.html.haml19
-rw-r--r--app/views/shared/members/_member.html.haml41
-rw-r--r--app/views/shared/milestones/_deprecation_message.html.haml1
-rw-r--r--app/views/shared/milestones/_issuable.html.haml2
-rw-r--r--app/views/shared/milestones/_labels_tab.html.haml2
-rw-r--r--app/views/shared/milestones/_top.html.haml27
-rw-r--r--app/views/shared/notes/_hints.html.haml5
-rw-r--r--app/views/shared/notes/_note.html.haml2
-rw-r--r--app/views/shared/notifications/_button.html.haml14
-rw-r--r--app/views/shared/notifications/_new_button.html.haml6
-rw-r--r--app/views/shared/notifications/_notification_dropdown.html.haml2
-rw-r--r--app/views/shared/projects/_dropdown.html.haml21
-rw-r--r--app/views/shared/projects/_search_bar.html.haml28
-rw-r--r--app/views/shared/projects/_search_form.html.haml7
-rw-r--r--app/views/shared/projects/_sort_dropdown.html.haml39
-rw-r--r--app/views/shared/snippets/_form.html.haml6
-rw-r--r--app/views/snippets/_actions.html.haml2
-rw-r--r--app/views/snippets/notes/_actions.html.haml6
-rw-r--r--app/views/users/calendar_activities.html.haml2
-rw-r--r--app/views/users/show.html.haml8
-rw-r--r--app/workers/all_queues.yml6
-rw-r--r--app/workers/auto_merge_process_worker.rb14
-rw-r--r--app/workers/build_finished_worker.rb1
-rw-r--r--app/workers/cluster_configure_worker.rb8
-rw-r--r--app/workers/cluster_project_configure_worker.rb2
-rw-r--r--app/workers/clusters/applications/uninstall_worker.rb17
-rw-r--r--app/workers/clusters/applications/wait_for_uninstall_app_worker.rb20
-rw-r--r--app/workers/deployments/finished_worker.rb13
-rw-r--r--app/workers/detect_repository_languages_worker.rb7
-rw-r--r--app/workers/git_garbage_collect_worker.rb15
-rw-r--r--app/workers/pages_domain_removal_cron_worker.rb14
-rw-r--r--app/workers/pages_domain_verification_cron_worker.rb2
-rw-r--r--app/workers/pages_domain_verification_worker.rb2
-rw-r--r--app/workers/pipeline_schedule_worker.rb37
-rw-r--r--app/workers/pipeline_success_worker.rb8
-rw-r--r--app/workers/post_receive.rb6
-rw-r--r--app/workers/process_commit_worker.rb2
-rw-r--r--app/workers/project_cache_worker.rb4
-rw-r--r--app/workers/run_pipeline_schedule_worker.rb26
-rw-r--r--app/workers/todos_destroyer/confidential_issue_worker.rb4
-rw-r--r--babel.config.js5
-rw-r--r--changelogs/archive.md36
-rw-r--r--changelogs/unreleased/10029-env-item.yml5
-rw-r--r--changelogs/unreleased/10081-env-table.yml5
-rw-r--r--changelogs/unreleased/10088-move-code-differences-EE-to-CE.yml5
-rw-r--r--changelogs/unreleased/10735-geo-gitlab-revision-can-return-not-consistent-results.yml5
-rw-r--r--changelogs/unreleased/10795-add-epic-tree-BE-CE-epic-graphql-support.yml5
-rw-r--r--changelogs/unreleased/10798-remove-dind-req-for-dast.yml5
-rw-r--r--changelogs/unreleased/10842-add-missing-environments-variable-to-the-sast-analyzer-docker-container.yml5
-rw-r--r--changelogs/unreleased/10921-display-scoped-labels-ce.yml5
-rw-r--r--changelogs/unreleased/11105-fix-cs-with-proxy.yml5
-rw-r--r--changelogs/unreleased/11124-update-deployment-service-fails-if-project-is-nil.yml5
-rw-r--r--changelogs/unreleased/11204-turn-off-mask-by-default.yml5
-rw-r--r--changelogs/unreleased/11609-geo-remove-support-for-using-geo-with-an-installation-from-source-docs.yml5
-rw-r--r--changelogs/unreleased/12106-sp-ce.yml5
-rw-r--r--changelogs/unreleased/1340-request-job-with-age.yml5
-rw-r--r--changelogs/unreleased/13453_minimal_atom_fix.yml5
-rw-r--r--changelogs/unreleased/13784-validate-variables-for-masking.yml5
-rw-r--r--changelogs/unreleased/19569-include-information-if-issue-was-closed-via-mr.yml5
-rw-r--r--changelogs/unreleased/237-style-toast-component.yml5
-rw-r--r--changelogs/unreleased/24936-remove-type-from-review-app-name.yml5
-rw-r--r--changelogs/unreleased/24971-align-emailvalidator-to-validate_email-gem-implementation.yml5
-rw-r--r--changelogs/unreleased/24985-align-urlvalidator-to-validate_url-gem-implementation.yml5
-rw-r--r--changelogs/unreleased/25942-remove-fake-repository-path-response.yml5
-rw-r--r--changelogs/unreleased/26021-added-write_repository-scope-for-personal-access-token.yml5
-rw-r--r--changelogs/unreleased/27987-use-findorcreateservice-to-create-labels.yml5
-rw-r--r--changelogs/unreleased/28757-remove-docker-pull-prefix-when-copying-a-tag-from-the-registry.yml5
-rw-r--r--changelogs/unreleased/28996-create-mvc-ui-in-haml.yml5
-rw-r--r--changelogs/unreleased/29249-show-download-diff-even-when-merge-request-is-closed.yml5
-rw-r--r--changelogs/unreleased/30138-display-cycle-analytics-issue.yml5
-rw-r--r--changelogs/unreleased/30157-api-expose-single-environment.yml5
-rw-r--r--changelogs/unreleased/31331-add-time-tracking-issue-boards-sidebar.yml5
-rw-r--r--changelogs/unreleased/33064-add-labels-to-note-event-payload.yml5
-rw-r--r--changelogs/unreleased/37495.yml5
-rw-r--r--changelogs/unreleased/38561-border-radii.yml5
-rw-r--r--changelogs/unreleased/38564-cant-leave-subgroup.yml5
-rw-r--r--changelogs/unreleased/39304-broadcast-message-buttons.yml5
-rw-r--r--changelogs/unreleased/43263-git-push-option-to-create-mr.yml5
-rw-r--r--changelogs/unreleased/43297-authorized-application-count.yml5
-rw-r--r--changelogs/unreleased/45687-web-ide-empty-state.yml5
-rw-r--r--changelogs/unreleased/46787-create-project-label-window-is-cut-off-at-the-bottom.yml5
-rw-r--r--changelogs/unreleased/47234-composable-auto-devops.yml5
-rw-r--r--changelogs/unreleased/47327-fix-github-import-visibility.yml5
-rw-r--r--changelogs/unreleased/47771-highlighting-in-diff.yml5
-rw-r--r--changelogs/unreleased/47846-position-is-off-when-visiting-files-with-anchors.yml5
-rw-r--r--changelogs/unreleased/48090-filter-sensitive-metric-labels.yml5
-rw-r--r--changelogs/unreleased/48132-display-output-from-pre-receive-scripts.yml5
-rw-r--r--changelogs/unreleased/48297-fix-code-selection.yml6
-rw-r--r--changelogs/unreleased/49041-issue-board-input-height.yml5
-rw-r--r--changelogs/unreleased/49517-fix-notes-import-export.yml5
-rw-r--r--changelogs/unreleased/49856-upgrade-bootstrap-form-gem.yml5
-rw-r--r--changelogs/unreleased/49863-ingress-ip-loading-state.yml5
-rw-r--r--changelogs/unreleased/49910-reopening-a-closed-milestone-from-the-closed-milestones-page-fails2.yml5
-rw-r--r--changelogs/unreleased/49915-fix-error-500-admin-projects-nil-storage.yml5
-rw-r--r--changelogs/unreleased/50106-hide-whitespace-changes.yml5
-rw-r--r--changelogs/unreleased/50850-kerrizor-extend-api-to-accept-start_project-option.yml5
-rw-r--r--changelogs/unreleased/51022-added-extended-height-to-labels-dropdown.yml5
-rw-r--r--changelogs/unreleased/51636-task-list-api-pderichs.yml5
-rw-r--r--changelogs/unreleased/51854-api-to-get-all-project-group-members-returns-duplicates.yml5
-rw-r--r--changelogs/unreleased/51988-install-group-runner-on-group-cluster.yml5
-rw-r--r--changelogs/unreleased/52258-labels-with-long-names-overflow-on-metrics-dashboard.yml5
-rw-r--r--changelogs/unreleased/52366-improved-group-lists-ui-spinners.yml5
-rw-r--r--changelogs/unreleased/52447-auto-devops-at-group-level.yml5
-rw-r--r--changelogs/unreleased/52560-fix-duplicate-tag-system-hooks.yml5
-rw-r--r--changelogs/unreleased/53134-multiple-extendes-for-a-job.yml5
-rw-r--r--changelogs/unreleased/53138-add-metrics-usage-ping.yml5
-rw-r--r--changelogs/unreleased/53139-hide-tree-single-file.yml5
-rw-r--r--changelogs/unreleased/53198-git-push-option-merge-when-pipeline-succeeds.yml6
-rw-r--r--changelogs/unreleased/53210-add-uniq-constraints-on-issues-and-mrs-labels.yml5
-rw-r--r--changelogs/unreleased/53279-fix-updated_at-api.yml5
-rw-r--r--changelogs/unreleased/53459-quick-action-adds-multiple-labels-to-issue-if-middle-words-overlap-with-existing-label.yml5
-rw-r--r--changelogs/unreleased/54140-non-ar-cache-commit-markdown.yml5
-rw-r--r--changelogs/unreleased/54169-flash-warning-rebrush.yml5
-rw-r--r--changelogs/unreleased/54417-graphql-type-authorization.yml5
-rw-r--r--changelogs/unreleased/54506-show-error-when-namespace-svc-missing.yml5
-rw-r--r--changelogs/unreleased/54670-external-diffs-when-outdated.yml5
-rw-r--r--changelogs/unreleased/54916-extended-tooltip-for-merge-request-links.yml5
-rw-r--r--changelogs/unreleased/55033-discussion-system-note-alignment.yml5
-rw-r--r--changelogs/unreleased/55125-mr-tab-scrolling.yml5
-rw-r--r--changelogs/unreleased/55253-activity-feed-ui-enhance-line-height.yml5
-rw-r--r--changelogs/unreleased/55268-exclude-system-notes-from-commits-in-mr.yml5
-rw-r--r--changelogs/unreleased/55447-validate-k8s-credentials.yml5
-rw-r--r--changelogs/unreleased/55964-fix-email-encoding.yml5
-rw-r--r--changelogs/unreleased/55980-remove-add-issue-on-blank-list.yml5
-rw-r--r--changelogs/unreleased/56015-remove-remote-timeout.yml5
-rw-r--r--changelogs/unreleased/56089-merge-gitlab-keys.yml5
-rw-r--r--changelogs/unreleased/5615-non-admins-only-archieve-ce.yml5
-rw-r--r--changelogs/unreleased/56762-fix-commit-swipe-view-26968.yml5
-rw-r--r--changelogs/unreleased/56833-project-improve-empty-repository-state-ui-fe.yml5
-rw-r--r--changelogs/unreleased/56864-reopen-locked-mr.yml5
-rw-r--r--changelogs/unreleased/56954-improve-knative-after-installing-tiller.yml5
-rw-r--r--changelogs/unreleased/56959-drop-project_auto_devops_domain.yml5
-rw-r--r--changelogs/unreleased/56959-remove-auto-devops-domain-ci-variable.yml5
-rw-r--r--changelogs/unreleased/57037-fix-mr-checkboxes-mobile-alignment.yml5
-rw-r--r--changelogs/unreleased/57115-just-in-time-k8s-resource-creation.yml5
-rw-r--r--changelogs/unreleased/57131-external_auth_to_core.yml5
-rw-r--r--changelogs/unreleased/57189-css-label-in-forms-with-bootstrap4.yml5
-rw-r--r--changelogs/unreleased/57319-hide-kubernetes-cluster-warning-if-project-has-cluster-related.yml5
-rw-r--r--changelogs/unreleased/57357-automate-base-domain-help-text.yml5
-rw-r--r--changelogs/unreleased/57364-improve-diff-nav-header.yml5
-rw-r--r--changelogs/unreleased/57409-loading-button-transition.yml5
-rw-r--r--changelogs/unreleased/57414-show-pipeline-iid.yml5
-rw-r--r--changelogs/unreleased/57482-shortcut-to-create-merge-request-from-web-ide.yml5
-rw-r--r--changelogs/unreleased/57493-add-limit-to-user-name.yml5
-rw-r--r--changelogs/unreleased/57540-filename-trailing-space.yml5
-rw-r--r--changelogs/unreleased/57602-create-cluster-validations.yml5
-rw-r--r--changelogs/unreleased/57648-make-emoji-picker-full-width-on-mobile.yml5
-rw-r--r--changelogs/unreleased/57655-fix-markdown-tables-border.yml5
-rw-r--r--changelogs/unreleased/57668-create-file-from-url.yml5
-rw-r--r--changelogs/unreleased/57669-fix-bug-clicking-file-header-refreshes-page.yml6
-rw-r--r--changelogs/unreleased/57825-moving-an-issue-results-in-broken-image-links-in-comments.yml5
-rw-r--r--changelogs/unreleased/57894-buttons-on-group-page-are-misaligned.yml5
-rw-r--r--changelogs/unreleased/57984-store-branch-name.yml5
-rw-r--r--changelogs/unreleased/58208-explicitly-set-masterauth.yml6
-rw-r--r--changelogs/unreleased/58269-separate-update-patch.yml5
-rw-r--r--changelogs/unreleased/58297-remove-extraneous-gitaly-calls-from-md-rendering.yml5
-rw-r--r--changelogs/unreleased/58375-api-controller.yml5
-rw-r--r--changelogs/unreleased/58375-reactive-caching-changes.yml5
-rw-r--r--changelogs/unreleased/58404-set-default-max-depth-for-GraphQL.yml5
-rw-r--r--changelogs/unreleased/58405-basic-limiting-complexity-of-graphql-queries.yml5
-rw-r--r--changelogs/unreleased/58410-change-pixel-size-of-instance-header-footer-message-to-16px.yml5
-rw-r--r--changelogs/unreleased/58433-email-notifications-do-not-work-properly-issue-due-date.yml5
-rw-r--r--changelogs/unreleased/58482-update-airminc-clair-local-scan-to-2-0-6.yml5
-rw-r--r--changelogs/unreleased/58538-discussion-top-radius.yml5
-rw-r--r--changelogs/unreleased/58632-fix-mr-widget-padding.yml5
-rw-r--r--changelogs/unreleased/58717-checkbox-cannot-be-checked-if-a-blockquote-is-above.yml5
-rw-r--r--changelogs/unreleased/58739-hashed-storage-prevent-a-migration-and-rollback-running-at-the-same-time.yml5
-rw-r--r--changelogs/unreleased/58748-update-nodejs-to-10-15-3.yml5
-rw-r--r--changelogs/unreleased/58751-fix-project-name-members-page.yml5
-rw-r--r--changelogs/unreleased/58781-silent-progress-in-auto-devops.yml5
-rw-r--r--changelogs/unreleased/58789-some-system-notes-on-issuable-are-folded-on-mobile.yml5
-rw-r--r--changelogs/unreleased/58793-fix-nav-links-archived-project.yml5
-rw-r--r--changelogs/unreleased/58797-broken-ui-on-a-closed-merge-request-from-a-deleted-source-project.yml5
-rw-r--r--changelogs/unreleased/58805-allow-incomplete-commit-data-to-be-fetched-from-collection.yml5
-rw-r--r--changelogs/unreleased/58835-button-run-pipeline.yml5
-rw-r--r--changelogs/unreleased/58839-automatically-set-prometheus-step-interval.yml5
-rw-r--r--changelogs/unreleased/58883-fix-fetching-comments.yml5
-rw-r--r--changelogs/unreleased/58889-spinners-are-active-prematurely-in-bitbucket-cloud-import.yml5
-rw-r--r--changelogs/unreleased/58933-broken-ui-on-commits-on-mobile.yml5
-rw-r--r--changelogs/unreleased/58941-use-gitlab-serverless-with-existing-knative-installation.yml5
-rw-r--r--changelogs/unreleased/58971-sentry-api-keyerror.yml5
-rw-r--r--changelogs/unreleased/58981-migrate-clusters-tests-to-jest.yml5
-rw-r--r--changelogs/unreleased/58984-doc-missing-milestones-and-labels-links.yml5
-rw-r--r--changelogs/unreleased/59026-replace-favicon.yml5
-rw-r--r--changelogs/unreleased/59057-buttons-on-top-from-a-user-profile-page-on-mobile.yml5
-rw-r--r--changelogs/unreleased/59062-update-gitlab-markup-python-3.yml5
-rw-r--r--changelogs/unreleased/59079-fix-jupyter-render-loop.yml5
-rw-r--r--changelogs/unreleased/59105-padding-unclickable-pipeline-job.yml5
-rw-r--r--changelogs/unreleased/59117-inconsistent-hover-behavior-on-navbar-items.yml5
-rw-r--r--changelogs/unreleased/59131-set-the-size-of-instance-system-message-text-12px.yml5
-rw-r--r--changelogs/unreleased/59189-long-names-in-project-path-namespace-dropdown-breaks-past-container.yml5
-rw-r--r--changelogs/unreleased/59273-update-fugit.yml5
-rw-r--r--changelogs/unreleased/59296-add-filter-by-title-milestones-api.yml5
-rw-r--r--changelogs/unreleased/59324-queries-which-return-multiple-series-are-not-working-correctly.yml5
-rw-r--r--changelogs/unreleased/59352-fix-mr-discussion-expansion.yml5
-rw-r--r--changelogs/unreleased/59376-Report-abuse-to-GitLab-should-be-Report-abuse-in-non-gitlab-com-instances.yml5
-rw-r--r--changelogs/unreleased/59441-add-base-domain-to-cluster-api.yml5
-rw-r--r--changelogs/unreleased/59502-fix-breadcrumb-artifacts.yml5
-rw-r--r--changelogs/unreleased/59546-fix-error-handling-for-missing-domain.yml5
-rw-r--r--changelogs/unreleased/59587-add-graphql-logging.yml5
-rw-r--r--changelogs/unreleased/59621-order-labels-alphabetically-in-issue-boards.yml5
-rw-r--r--changelogs/unreleased/59651-remove-unnecessary-decimal-places-on-chart-axes.yml5
-rw-r--r--changelogs/unreleased/59708-vendor-css.yml5
-rw-r--r--changelogs/unreleased/59921-pipeline-schedule.yml5
-rw-r--r--changelogs/unreleased/59987-move-sign-in-2fa-on-users-sign_in-above-intro-content-on-mobile.yml5
-rw-r--r--changelogs/unreleased/60006-add-touch-events-to-image-diff-26971.yml5
-rw-r--r--changelogs/unreleased/60026-group-member-count-bg.yml5
-rw-r--r--changelogs/unreleased/60034-default-web-ide-s-merge-request-checkbox-to-true.yml5
-rw-r--r--changelogs/unreleased/60068-avoid-null-domain-help-text.yml5
-rw-r--r--changelogs/unreleased/60116-fix-button-wrapping.yml5
-rw-r--r--changelogs/unreleased/60149-nameerror-uninitialized-constant-sentry-client-sentryerror.yml5
-rw-r--r--changelogs/unreleased/60180-jira-service-fix-nil-on-find-call.yml5
-rw-r--r--changelogs/unreleased/60224-btn-env.yml5
-rw-r--r--changelogs/unreleased/60241-merge-request-popover-doesn-t-go-away-on-mouse-leave.yml5
-rw-r--r--changelogs/unreleased/60250-remove-mr_push_options-flag.yml5
-rw-r--r--changelogs/unreleased/60261-save-btn-env.yml5
-rw-r--r--changelogs/unreleased/60303-replace-sidekiq-mtail-metrics.yml5
-rw-r--r--changelogs/unreleased/60304-long-file-names-in-mr-diffs-cause-horizontal-scrolling.yml5
-rw-r--r--changelogs/unreleased/60323-inline-validation-for-users-name-and-username-length.yml5
-rw-r--r--changelogs/unreleased/60379-remove-ci-preparing-state-feature-flag.yml5
-rw-r--r--changelogs/unreleased/60425-fix-500-when-accessing-charts-with-anonymous-user.yml5
-rw-r--r--changelogs/unreleased/60750-milestone-header.yml5
-rw-r--r--changelogs/unreleased/60818_yamllint_project_root.yml5
-rw-r--r--changelogs/unreleased/60819_yamllint_gitlabci.yml5
-rw-r--r--changelogs/unreleased/609120-ref-link.yml5
-rw-r--r--changelogs/unreleased/60987-emoji-picker-popup.yml5
-rw-r--r--changelogs/unreleased/61024-update-resolved-icon.yml5
-rw-r--r--changelogs/unreleased/6104-ee-ce-difference.yml5
-rw-r--r--changelogs/unreleased/61045-charts-with-many-overlapping-series-display-incorrectly.yml5
-rw-r--r--changelogs/unreleased/61049-links-activity-stream.yml5
-rw-r--r--changelogs/unreleased/61072-link-to-user-profile-not-distinguishable-on-latest-commit-widget.yml5
-rw-r--r--changelogs/unreleased/61144-style-secondary-button-type-to-be-aligned-with-pattern-library.yml5
-rw-r--r--changelogs/unreleased/61157-reviewer-roulette-shouldn-t-include-the-author-as-a-possibility.yml5
-rw-r--r--changelogs/unreleased/61313-fix-dropdown-searchbar.yml5
-rw-r--r--changelogs/unreleased/61323-snippet-copy-icon-button-is-misaligned.yml5
-rw-r--r--changelogs/unreleased/61324-non-project-snippet-new-snippet-button-should-be-green-outline.yml5
-rw-r--r--changelogs/unreleased/61339-Add-underline-to-attach-a-file.yml5
-rw-r--r--changelogs/unreleased/61393-emoji-button.yml5
-rw-r--r--changelogs/unreleased/61441.yml5
-rw-r--r--changelogs/unreleased/61511-add-expand-collapse-to-project-operation-settings.yml5
-rw-r--r--changelogs/unreleased/61565-merge-request-discussion-text-jumps-when-resolved.yml5
-rw-r--r--changelogs/unreleased/61606-support-string-piwik-website-ids.yml5
-rw-r--r--changelogs/unreleased/61629-dependency-installation-error-on-fsevents-1-2-4-with-node-js-12.yml5
-rw-r--r--changelogs/unreleased/61639-flaky-spec-issue-boards-labels-creates-project-label-spec-features-boards-sidebar_spec-rb-350.yml5
-rw-r--r--changelogs/unreleased/61697-add-project-id-to-le-common-name.yml5
-rw-r--r--changelogs/unreleased/61788-predefined-colours-dont-have-descriptive-labels.yml5
-rw-r--r--changelogs/unreleased/61795-fix-error-when-moving-issues.yml5
-rw-r--r--changelogs/unreleased/61821-tooltip-consistency.yml5
-rw-r--r--changelogs/unreleased/61827-prevent-user-popover-icon-shrink.yml5
-rw-r--r--changelogs/unreleased/61880-download-btn-group.yml5
-rw-r--r--changelogs/unreleased/61914-fix-emojis-urls.yml5
-rw-r--r--changelogs/unreleased/61928-remove-throttle-from-dirty-submit.yml6
-rw-r--r--changelogs/unreleased/61960-translatable-strings-in-issue-closure-emails.yml5
-rw-r--r--changelogs/unreleased/61988-collapse-icon-on-merge-request-diff-larger-than-profile-picture.yml5
-rw-r--r--changelogs/unreleased/61990-spinner.yml5
-rw-r--r--changelogs/unreleased/62061-note-icon-color.yml5
-rw-r--r--changelogs/unreleased/62091-remove-time-windows-flag.yml5
-rw-r--r--changelogs/unreleased/62092-missing-padding-next-to-time-windows-dropdown-on-metrics-dashboard.yml5
-rw-r--r--changelogs/unreleased/62107-fix-detail-page-header-height.yml5
-rw-r--r--changelogs/unreleased/62116-performance-issue-502-errors-on-rendering-of-issues-with-heavy-markdown-contents.yml6
-rw-r--r--changelogs/unreleased/62124-new-threaded-discussion-design.yml5
-rw-r--r--changelogs/unreleased/62134-fix-non-wraping-project-description.yml5
-rw-r--r--changelogs/unreleased/62144-fix-option-dropdown-button-size.yml5
-rw-r--r--changelogs/unreleased/62154-fe-create-fix-long-branch-name-in-dropdown.yml6
-rw-r--r--changelogs/unreleased/62227-webkit-icon-overlap.yml5
-rw-r--r--changelogs/unreleased/62253-add-kubernetes-logs-to-monitoring-ui.yml5
-rw-r--r--changelogs/unreleased/62300-target-area-for-dropdown-list-items-is-too-small-on-metrics-dashboard.yml5
-rw-r--r--changelogs/unreleased/62408-dropdown-truncate.yml5
-rw-r--r--changelogs/unreleased/62418-project-default-git-depth.yml5
-rw-r--r--changelogs/unreleased/62432-fix-participants-wrapping.yml5
-rw-r--r--changelogs/unreleased/62485-label-weights.yml5
-rw-r--r--changelogs/unreleased/62487-external-policy-desc.yml5
-rw-r--r--changelogs/unreleased/62656-adjusted-dropdown-styles.yml5
-rw-r--r--changelogs/unreleased/62684-add-index-public-email-on-users.yml5
-rw-r--r--changelogs/unreleased/62788-clean-up-pagination.yml5
-rw-r--r--changelogs/unreleased/62788-graphql-pagination.yml5
-rw-r--r--changelogs/unreleased/62847-url-for-the-next-request-with-pagination-is-missing-port.yml5
-rw-r--r--changelogs/unreleased/62974-follow-up-from-wip-align-merge-request-icons-and-text.yml5
-rw-r--r--changelogs/unreleased/8723-geo-remove-gitlab-lfstoken-legacyredisdevisetoken-implementation-and-usage-geo.yml5
-rw-r--r--changelogs/unreleased/9121-sort-relative-position.yml5
-rw-r--r--changelogs/unreleased/9186-implement-atmtwps-state-to-mr-widget.yml5
-rw-r--r--changelogs/unreleased/9578-adjust-milestone-completion-rate.yml5
-rw-r--r--changelogs/unreleased/9978-moved-code-differences-from-EE-to-CE.yml5
-rw-r--r--changelogs/unreleased/MaxWinterstein-master-patch-23232.yml5
-rw-r--r--changelogs/unreleased/_acet-related-mrs-widget-rewrite.yml5
-rw-r--r--changelogs/unreleased/abstract-auto-merge.yml5
-rw-r--r--changelogs/unreleased/ac-63020-typeerror-nil-can-t-be-coerced-into-integer.yml5
-rw-r--r--changelogs/unreleased/ac-graphql-stats.yml5
-rw-r--r--changelogs/unreleased/ac-graphql-wikisize.yml5
-rw-r--r--changelogs/unreleased/ac-namespaces-stats-no-coalesce.yml5
-rw-r--r--changelogs/unreleased/add-allow_failure-to-job-api.yml5
-rw-r--r--changelogs/unreleased/add-branch-to-project-search-api.yml5
-rw-r--r--changelogs/unreleased/add-constraint-for-milestone-dates.yml5
-rw-r--r--changelogs/unreleased/add-lfs-blob-ids-to-tree-type.yml5
-rw-r--r--changelogs/unreleased/add-warning-to-backup-rake-task.yml5
-rw-r--r--changelogs/unreleased/add-wiki-size-to-statistics.yml5
-rw-r--r--changelogs/unreleased/add_backtrace_to_kubernetes_log.yml5
-rw-r--r--changelogs/unreleased/allow-emoji-in-references.yml5
-rw-r--r--changelogs/unreleased/allow-filtering-labels-by-a-single-character.yml5
-rw-r--r--changelogs/unreleased/allow-ref-name-caching-projects-controller.yml5
-rw-r--r--changelogs/unreleased/always-link-instance-configuration.yml5
-rw-r--r--changelogs/unreleased/always-show-pipelines-must-succeed-checkbox.yml5
-rw-r--r--changelogs/unreleased/antonyliu-i18n-user-profile.yml5
-rw-r--r--changelogs/unreleased/api_make_protected_boolean_type.yml5
-rw-r--r--changelogs/unreleased/api_masked_variables.yml5
-rw-r--r--changelogs/unreleased/asciidoc-include-directive.yml5
-rw-r--r--changelogs/unreleased/auto-devops-kubernestes-bump1-11-10.yml5
-rw-r--r--changelogs/unreleased/avoid_es_loading_project_ci_status.yml5
-rw-r--r--changelogs/unreleased/backstage-gb-improve-jobs-controller-performance.yml5
-rw-r--r--changelogs/unreleased/bump-auto-devops-helm-2-14-0.yml5
-rw-r--r--changelogs/unreleased/bvl-graphql-multiplex.yml5
-rw-r--r--changelogs/unreleased/bvl-use-global-ids-graphql.yml5
-rw-r--r--changelogs/unreleased/cancel-auto-merge-when-branch-is-changed.yml5
-rw-r--r--changelogs/unreleased/cancel-auto-merge-when-merge-request-is-closed.yml5
-rw-r--r--changelogs/unreleased/ce-4681-autosave.yml5
-rw-r--r--changelogs/unreleased/ce-56153-error-tracking-counts.yml5
-rw-r--r--changelogs/unreleased/ce-57402-add-issues-statistics-api-endpoints.yml5
-rw-r--r--changelogs/unreleased/ce-jej-fix-git-http-with-sso-enforcement.yml5
-rw-r--r--changelogs/unreleased/ce-proj-settings-ok-avatar-only.yml5
-rw-r--r--changelogs/unreleased/ce-proj-settings-ok-mr-settings-only.yml5
-rw-r--r--changelogs/unreleased/ce-quick-fix-58727-collapsed-sidebar-flyout-menu-items-don-t-appear-in-1200px-screen-size.yml5
-rw-r--r--changelogs/unreleased/check-mergeability-in-merge-to-ref-service.yml5
-rw-r--r--changelogs/unreleased/chore-remove-circuit-breaker-api.yml5
-rw-r--r--changelogs/unreleased/ci-lint-ssl-error.yml6
-rw-r--r--changelogs/unreleased/ci-variable-conjunction.yml5
-rw-r--r--changelogs/unreleased/copy-button-in-modals.yml5
-rw-r--r--changelogs/unreleased/create-label-and-list-checkbox.yml5
-rw-r--r--changelogs/unreleased/delay-update-statictics.yml5
-rw-r--r--changelogs/unreleased/delete-release-when-delete-tag.yml5
-rw-r--r--changelogs/unreleased/deploy-keys-ext.yml5
-rw-r--r--changelogs/unreleased/dhiraj-fix-missing-deployment-rockets-in-monitoring-dashboard.yml5
-rw-r--r--changelogs/unreleased/diff-whitespace-setting-changes.yml5
-rw-r--r--changelogs/unreleased/disallow-guests-to-access-releases.yml5
-rw-r--r--changelogs/unreleased/display-junit-classname-in-modal.yml5
-rw-r--r--changelogs/unreleased/dm-http-hostname-override.yml5
-rw-r--r--changelogs/unreleased/do-not-force-2fa.yml6
-rw-r--r--changelogs/unreleased/do-not-reopen-merged-mr.yml5
-rw-r--r--changelogs/unreleased/docs-add-chatops-request-doc.yml5
-rw-r--r--changelogs/unreleased/downloading-expired-artifacts.yml5
-rw-r--r--changelogs/unreleased/drop-usage-of-leagcy-artifacts.yml5
-rw-r--r--changelogs/unreleased/duplicate-related-mrs.yml5
-rw-r--r--changelogs/unreleased/dz-patch-58.yml5
-rw-r--r--changelogs/unreleased/dz-scope-project-routes.yml5
-rw-r--r--changelogs/unreleased/ee-11040-added-conditional-rendering.yml5
-rw-r--r--changelogs/unreleased/ekigbo-extend-timezone-dropdown.yml5
-rw-r--r--changelogs/unreleased/ensure_namespace.yml5
-rw-r--r--changelogs/unreleased/expose-group-id-on-home-panel.yml5
-rw-r--r--changelogs/unreleased/expose-pipeline-variables-via-api.yml5
-rw-r--r--changelogs/unreleased/expose-project-git-depth-via-api.yml5
-rw-r--r--changelogs/unreleased/extend-cte-optimisations-to-projects.yml5
-rw-r--r--changelogs/unreleased/fe-fix-gl-dropdown-scrolling-to-top.yml5
-rw-r--r--changelogs/unreleased/feature-gb-serverless-switch-to-gitlabktl.yml5
-rw-r--r--changelogs/unreleased/feature-gb-use-gitlabktl-to-build-serverless-applications.yml5
-rw-r--r--changelogs/unreleased/feature-require-2fa-for-all-entities-in-group.yml4
-rw-r--r--changelogs/unreleased/feature-users-search-results.yml5
-rw-r--r--changelogs/unreleased/feature-webide_escaping.yml5
-rw-r--r--changelogs/unreleased/filter-merge-requests-by-target-branch.yml5
-rw-r--r--changelogs/unreleased/fix-UI-links-to-route-map-info.yml5
-rw-r--r--changelogs/unreleased/fix-allow-lower-case-issue-ids.yml5
-rw-r--r--changelogs/unreleased/fix-api-group-visibility.yml5
-rw-r--r--changelogs/unreleased/fix-autodevops-postgres-versioning.yml5
-rw-r--r--changelogs/unreleased/fix-container-scanning-on-k8s.yml5
-rw-r--r--changelogs/unreleased/fix-db-migrate-is-failed-on-mysql8.yml5
-rw-r--r--changelogs/unreleased/fix-diverged-branch-locals.yml5
-rw-r--r--changelogs/unreleased/fix-expand-full-file-on-image.yml5
-rw-r--r--changelogs/unreleased/fix-flyout-navs.yml5
-rw-r--r--changelogs/unreleased/fix-format-date-safari-ff.yml5
-rw-r--r--changelogs/unreleased/fix-gb-fix-serverless-apps-deployment-template.yml5
-rw-r--r--changelogs/unreleased/fix-gb-remove-serverless-app-build-policies-from-template.yml5
-rw-r--r--changelogs/unreleased/fix-hidden-statistics.yml5
-rw-r--r--changelogs/unreleased/fix-ide-web-worker-relative-url.yml5
-rw-r--r--changelogs/unreleased/fix-import-member-access.yml5
-rw-r--r--changelogs/unreleased/fix-import-param-ordering.yml5
-rw-r--r--changelogs/unreleased/fix-include-ci-yaml.yml5
-rw-r--r--changelogs/unreleased/fix-issue-mr-badge.yml5
-rw-r--r--changelogs/unreleased/fix-issues-time-counter.yml5
-rw-r--r--changelogs/unreleased/fix-merge-request-relations-with-pipeline-on-mwps.yml5
-rw-r--r--changelogs/unreleased/fix-milestone-references-with-escaped-html-entities.yml5
-rw-r--r--changelogs/unreleased/fix-new-merge-request-diff-headers-sticky-position.yml5
-rw-r--r--changelogs/unreleased/fix-pipeline-entity.yml5
-rw-r--r--changelogs/unreleased/fix-pipeline-schedule-owner-is-nil.yml5
-rw-r--r--changelogs/unreleased/fix-review-app-env-url.yml5
-rw-r--r--changelogs/unreleased/fix-routes-n-plus-one-in-user-autocomplete.yml5
-rw-r--r--changelogs/unreleased/fix-search-dropdown-blur-close.yml5
-rw-r--r--changelogs/unreleased/fix-time-window-default.yml5
-rw-r--r--changelogs/unreleased/fix-too-many-loops-cron-error.yml5
-rw-r--r--changelogs/unreleased/fix-transfer-group-possibilities.yml5
-rw-r--r--changelogs/unreleased/fixed-duplicated-large-text-on-diffs.yml5
-rw-r--r--changelogs/unreleased/fixed-web-ide-merge-request-review.yml5
-rw-r--r--changelogs/unreleased/fj-bump-workhorse-version-8-6-0.yml5
-rw-r--r--changelogs/unreleased/frozen-string-spec-some.yml5
-rw-r--r--changelogs/unreleased/gitaly-version-v1.29.0.yml5
-rw-r--r--changelogs/unreleased/gitaly-version-v1.32.0.yml5
-rw-r--r--changelogs/unreleased/gitaly-version-v1.33.0.yml5
-rw-r--r--changelogs/unreleased/gitaly-version-v1.43.0.yml5
-rw-r--r--changelogs/unreleased/graphql-prometheus.yml5
-rw-r--r--changelogs/unreleased/gt-externalize-app-views-projects-pipelines.yml5
-rw-r--r--changelogs/unreleased/gt-externalize-profiles-preferences.yml5
-rw-r--r--changelogs/unreleased/gt-open-visibility-help-link-in-a-new-tab.yml5
-rw-r--r--changelogs/unreleased/i18n-active_sessions-in-user-profile.yml5
-rw-r--r--changelogs/unreleased/i18n-chat-of-user-profile.yml5
-rw-r--r--changelogs/unreleased/i18n-email-of-user-profile.yml5
-rw-r--r--changelogs/unreleased/i18n-pgp_ssh_keys-of-user-profile.yml5
-rw-r--r--changelogs/unreleased/id-51433-sort-wiki-by-date.yml5
-rw-r--r--changelogs/unreleased/id-bug-suggested-changes-remove-empty-line.yml5
-rw-r--r--changelogs/unreleased/ide-fix-detect-mr-from-fork.yml5
-rw-r--r--changelogs/unreleased/ignore-artifact-attirbutes-in-project-import-export.yml5
-rw-r--r--changelogs/unreleased/improve-email-text-part.yml5
-rw-r--r--changelogs/unreleased/increase-move-issue-dropdown-height.yml5
-rw-r--r--changelogs/unreleased/instance-configuration-artifact-size.yml5
-rw-r--r--changelogs/unreleased/issue-58418-release-notes.yml5
-rw-r--r--changelogs/unreleased/issue_49897.yml5
-rw-r--r--changelogs/unreleased/issue_58547.yml5
-rw-r--r--changelogs/unreleased/jc-guard-against-empty-dereferenced_target.yml5
-rw-r--r--changelogs/unreleased/jc-migration-for-source-project-id.yml5
-rw-r--r--changelogs/unreleased/jc-omit-count-diverging-commits-max.yml5
-rw-r--r--changelogs/unreleased/jivl-migrate-dashboard-store-vuex.yml5
-rw-r--r--changelogs/unreleased/jupyter_pre_spawn_hook_v2.yml5
-rw-r--r--changelogs/unreleased/k8s_new_deployment_labels.yml5
-rw-r--r--changelogs/unreleased/kinolaev-master-patch-13154.yml5
-rw-r--r--changelogs/unreleased/knative-prometheus.yml5
-rw-r--r--changelogs/unreleased/knative-update.yml5
-rw-r--r--changelogs/unreleased/kube_helm_auto_devops_213.yml5
-rw-r--r--changelogs/unreleased/leipert-node-12-compatibility.yml5
-rw-r--r--changelogs/unreleased/limit-amount-of-created-pipelines.yml5
-rw-r--r--changelogs/unreleased/localize-notification-dropdown.yml5
-rw-r--r--changelogs/unreleased/make-autocomplete-faster-with-lots-of-results.yml5
-rw-r--r--changelogs/unreleased/mark-comment-resolved.yml5
-rw-r--r--changelogs/unreleased/minimized-multiple-queries-ce.yml5
-rw-r--r--changelogs/unreleased/mm12935.yml5
-rw-r--r--changelogs/unreleased/move-allow-developers-to-create-projects-in-groups-to-core.yml5
-rw-r--r--changelogs/unreleased/nfriend-css-updates-for-gitlab-design-system-compliance.yml5
-rw-r--r--changelogs/unreleased/nfriend-update-job-detail-view-sidebar.yml5
-rw-r--r--changelogs/unreleased/nfriend-update-merge-request-widget-for-post-merge-pipelines.yml5
-rw-r--r--changelogs/unreleased/nfriend-update-merge-request-widget-pipeline-block.yml6
-rw-r--r--changelogs/unreleased/nfriend-update-pipeline-detail-view.yml5
-rw-r--r--changelogs/unreleased/nfriend-update-pipeline-list-view.yml5
-rw-r--r--changelogs/unreleased/only-counted-active-milestones-as-started.yml5
-rw-r--r--changelogs/unreleased/osw-avoid-500-on-suggestions-check.yml5
-rw-r--r--changelogs/unreleased/osw-avoid-encoding-errors-on-merge-to-ref-service.yml5
-rw-r--r--changelogs/unreleased/osw-fix-post-dep-migration-with-timeout.yml5
-rw-r--r--changelogs/unreleased/osw-multi-line-suggestions-creation-strategy.yml5
-rw-r--r--changelogs/unreleased/osw-multi-line-suggestions-parsing.yml5
-rw-r--r--changelogs/unreleased/osw-reset-merge-status-from-mergeable-mrs.yml5
-rw-r--r--changelogs/unreleased/osw-support-multi-line-suggestions.yml5
-rw-r--r--changelogs/unreleased/patch-55.yml5
-rw-r--r--changelogs/unreleased/patch-65.yml5
-rw-r--r--changelogs/unreleased/patch-issue--56683.yml6
-rw-r--r--changelogs/unreleased/pb-update-gitaly-1-45-0.yml5
-rw-r--r--changelogs/unreleased/persist-fulll-ref-path-for-mr-pipelines.yml5
-rw-r--r--changelogs/unreleased/pipelines-email-default-branch-filter.yml5
-rw-r--r--changelogs/unreleased/pravi-gitlab-ce-update-recaptcha.yml5
-rw-r--r--changelogs/unreleased/prevent-running-mr-pipelines-when-target-updated.yml5
-rw-r--r--changelogs/unreleased/referenced-labels.yml5
-rw-r--r--changelogs/unreleased/related-mr-link-cutoff.yml5
-rw-r--r--changelogs/unreleased/relative-urls-for-system-notes.yml5
-rw-r--r--changelogs/unreleased/remove-ci-charts-undescriptive-header.yml5
-rw-r--r--changelogs/unreleased/remove-disabled-pages-domains.yml5
-rw-r--r--changelogs/unreleased/remove-grafana-dashboard-link-feature-flag.yml5
-rw-r--r--changelogs/unreleased/remove-legacy-artifacts-related-code.yml5
-rw-r--r--changelogs/unreleased/remove-mr-diff-header-height.yml5
-rw-r--r--changelogs/unreleased/require-all-templates-to-include-default-stages.yml5
-rw-r--r--changelogs/unreleased/rewind-iid-on-pipelines.yml5
-rw-r--r--changelogs/unreleased/security-55503-fix-pdf-js-vulnerability.yml5
-rw-r--r--changelogs/unreleased/security-56224.yml5
-rw-r--r--changelogs/unreleased/security-56927-xss-resolve-conflicts-branch-name.yml5
-rw-r--r--changelogs/unreleased/security-58856-persistent-xss-in-note-objects.yml5
-rw-r--r--changelogs/unreleased/security-60039.yml5
-rw-r--r--changelogs/unreleased/security-60143-address-xss-issue-in-wiki-links.yml5
-rw-r--r--changelogs/unreleased/security-exif-migration.yml5
-rw-r--r--changelogs/unreleased/security-fix-confidential-issue-label-visibility-master.yml5
-rw-r--r--changelogs/unreleased/security-fix-project-existence-disclosure-master.yml5
-rw-r--r--changelogs/unreleased/security-fix_milestones_search_api_leak.yml5
-rw-r--r--changelogs/unreleased/security-id-leaked-password-in-import-url-frontend.yml5
-rw-r--r--changelogs/unreleased/security-id-potential-denial-languages.yml5
-rw-r--r--changelogs/unreleased/security-jej-prevent-web-sign-in-bypass.yml5
-rw-r--r--changelogs/unreleased/security-mass-assignment-on-project-update.yml5
-rw-r--r--changelogs/unreleased/security-unsubscribing-from-issue.yml5
-rw-r--r--changelogs/unreleased/set-real-next-run-at-for-preventing-duplciate-pipeline-creations.yml5
-rw-r--r--changelogs/unreleased/sh-add-backtrace-to-sql-queries.yml5
-rw-r--r--changelogs/unreleased/sh-add-gitaly-duration-logs.yml5
-rw-r--r--changelogs/unreleased/sh-add-gitaly-ref-name-caching-tree-controller.yml5
-rw-r--r--changelogs/unreleased/sh-add-header-to-jobs-admin-page.yml5
-rw-r--r--changelogs/unreleased/sh-cache-pipeline-find-commits.yml5
-rw-r--r--changelogs/unreleased/sh-cache-root-ref-asymetrically.yml5
-rw-r--r--changelogs/unreleased/sh-clear-pipeline-status-cache-upon-destroy.yml5
-rw-r--r--changelogs/unreleased/sh-default-visibility-fix.yml5
-rw-r--r--changelogs/unreleased/sh-fix-fogbugz-import.yml5
-rw-r--r--changelogs/unreleased/sh-fix-gitaly-find-commit-caching.yml5
-rw-r--r--changelogs/unreleased/sh-fix-issue-55869.yml5
-rw-r--r--changelogs/unreleased/sh-fix-issue-59065.yml5
-rw-r--r--changelogs/unreleased/sh-fix-merge-requests-api-remove-branch-param.yml5
-rw-r--r--changelogs/unreleased/sh-fix-pipeline-delete-caching.yml5
-rw-r--r--changelogs/unreleased/sh-fix-realtime-changes-with-reserved-words.yml5
-rw-r--r--changelogs/unreleased/sh-fix-rebase-error-clearing.yml5
-rw-r--r--changelogs/unreleased/sh-fix-ref-name-caching.yml5
-rw-r--r--changelogs/unreleased/sh-fix-resolve-button-not-available.yml5
-rw-r--r--changelogs/unreleased/sh-fix-tag-push-remote-mirror.yml5
-rw-r--r--changelogs/unreleased/sh-fix-utf-8-encoding-resolve-conflicts.yml5
-rw-r--r--changelogs/unreleased/sh-git-gc-after-initial-fetch.yml5
-rw-r--r--changelogs/unreleased/sh-improve-find-commit-caching.yml5
-rw-r--r--changelogs/unreleased/sh-omit-blocked-admins-from-notification.yml5
-rw-r--r--changelogs/unreleased/sh-reject-info-refs-head-requests.yml5
-rw-r--r--changelogs/unreleased/sh-skip-sti-tables-reltuples.yml5
-rw-r--r--changelogs/unreleased/sh-speed-up-commit-loading.yml5
-rw-r--r--changelogs/unreleased/sh-update-process-mem.yml5
-rw-r--r--changelogs/unreleased/sh-update-rails-5-0-7-2.yml5
-rw-r--r--changelogs/unreleased/sh-upgrade-ruby-2-6-3-ce.yml5
-rw-r--r--changelogs/unreleased/sh-validate-ref-name-in-commit.yml5
-rw-r--r--changelogs/unreleased/stop-signing-avatar-paths.yml5
-rw-r--r--changelogs/unreleased/t1.yml5
-rw-r--r--changelogs/unreleased/thomas-nilsson-irfu-gitlab-ce-thomas-nilsson-irfu-master-patch-13137.yml5
-rw-r--r--changelogs/unreleased/tpresa-add-highest-role-to-user.yml5
-rw-r--r--changelogs/unreleased/update-babel-to-7-4-4.yml5
-rw-r--r--changelogs/unreleased/update-gitaly-to-v1-42-1.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-3-0.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-0.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-1.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-2.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-shell-9-3-0.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-shell.yml5
-rw-r--r--changelogs/unreleased/update-pages.yml5
-rw-r--r--changelogs/unreleased/update-psd-doc.yml5
-rw-r--r--changelogs/unreleased/update-rack-oauth2.yml5
-rw-r--r--changelogs/unreleased/update-smileys-new.yml5
-rw-r--r--changelogs/unreleased/update-workhorse-8-5-1.yml5
-rw-r--r--changelogs/unreleased/upgrade-pages-to-v1-6-1.yml5
-rw-r--r--changelogs/unreleased/use-only-all-pipelines.yml5
-rw-r--r--changelogs/unreleased/use-untrusted-regexp.yml5
-rw-r--r--changelogs/unreleased/variables-boolean-type.yml5
-rw-r--r--changelogs/unreleased/weimeng-email-routing.yml5
-rw-r--r--changelogs/unreleased/winh-notes-error-handling.yml5
-rw-r--r--changelogs/unreleased/winh-toggle-comment-draft.yml5
-rw-r--r--changelogs/unreleased/xanf-gitlab-ce-move-project-tags.yml5
-rw-r--r--changelogs/unreleased/xanf-gitlab-ce-transfer-disables-js.yml5
-rw-r--r--changelogs/unreleased/zj-fsck-no-timeout.yml5
-rw-r--r--changelogs/unreleased/zj-remove-delta-island-feature-flag.yml3
-rw-r--r--changelogs/unreleased/zj-usage-ping-pool-repository.yml5
-rw-r--r--config/application.rb3
-rw-r--r--config/database.yml.example0
-rw-r--r--config/environments/development.rb3
-rw-r--r--config/environments/test.rb2
-rw-r--r--config/gitlab.yml.example16
-rw-r--r--config/initializers/01_secret_token.rb11
-rw-r--r--config/initializers/1_settings.rb16
-rw-r--r--config/initializers/7_prometheus_metrics.rb8
-rw-r--r--config/initializers/8_devise.rb5
-rw-r--r--config/initializers/action_dispatch_http_mime_negotiation.rb2
-rw-r--r--config/initializers/active_record_avoid_type_casting_in_uniqueness_validator.rb94
-rw-r--r--config/initializers/active_record_build_select.rb24
-rw-r--r--config/initializers/active_record_locking.rb76
-rw-r--r--config/initializers/ar_native_database_types.rb3
-rw-r--r--config/initializers/config_initializers_active_record_locking.rb45
-rw-r--r--config/initializers/gettext_rails_i18n_patch.rb2
-rw-r--r--config/initializers/hipchat_client_patch.rb6
-rw-r--r--config/initializers/http_hostname_override.rb49
-rw-r--r--config/initializers/lograge.rb2
-rw-r--r--config/initializers/peek.rb14
-rw-r--r--config/initializers/postgresql_opclasses_support.rb2
-rw-r--r--config/initializers/rack_attack_logging.rb10
-rw-r--r--config/initializers/rack_timeout.rb23
-rw-r--r--config/initializers/seed_fu.rb4
-rw-r--r--config/initializers/sentry.rb1
-rw-r--r--config/initializers/sidekiq.rb17
-rw-r--r--config/initializers/tracing.rb16
-rw-r--r--config/karma.config.js33
-rw-r--r--config/locales/en.yml2
-rw-r--r--config/prometheus/common_metrics.yml163
-rw-r--r--config/puma.example.development.rb1
-rw-r--r--config/puma.rb.example70
-rw-r--r--config/routes.rb3
-rw-r--r--config/routes/admin.rb5
-rw-r--r--config/routes/import.rb2
-rw-r--r--config/routes/profile.rb6
-rw-r--r--config/routes/project.rb301
-rw-r--r--config/routes/repository.rb2
-rw-r--r--config/sidekiq_queues.yml2
-rw-r--r--config/unicorn.rb.example.development1
-rw-r--r--config/webpack.config.review_toolbar.js58
-rw-r--r--danger/ce_ee_vue_templates/Dangerfile56
-rw-r--r--danger/commit_messages/Dangerfile6
-rw-r--r--danger/gitlab_ui_wg/Dangerfile29
-rw-r--r--danger/plugins/helper.rb3
-rw-r--r--danger/plugins/roulette.rb10
-rw-r--r--danger/roulette/Dangerfile43
-rw-r--r--danger/single_codebase/Dangerfile29
-rw-r--r--db/fixtures/development/09_issues.rb20
-rw-r--r--db/importers/common_metrics_importer.rb26
-rw-r--r--db/migrate/20140414131055_change_state_to_allow_empty_merge_request_diffs.rb1
-rw-r--r--db/migrate/20150509180749_convert_legacy_reference_notes.rb3
-rw-r--r--db/migrate/20161031181638_add_unique_index_to_subscriptions.rb4
-rw-r--r--db/migrate/20170330141723_disable_invalid_service_templates2.rb2
-rw-r--r--db/migrate/20170503140202_turn_nested_groups_into_regular_groups_for_mysql.rb7
-rw-r--r--db/migrate/20180702134423_generate_missing_routes.rb1
-rw-r--r--db/migrate/20190320174702_add_lets_encrypt_notification_email_to_application_settings.rb15
-rw-r--r--db/migrate/20190322164830_add_auto_ssl_enabled_to_pages_domain.rb17
-rw-r--r--db/migrate/20190325105715_add_fields_to_user_preferences.rb24
-rw-r--r--db/migrate/20190327163904_add_notification_email_to_notification_settings.rb11
-rw-r--r--db/migrate/20190329085614_add_lets_encrypt_terms_of_service_accepted_to_application_settings.rb21
-rw-r--r--db/migrate/20190408163745_prometheus_knative05_fix.rb20
-rw-r--r--db/migrate/20190412155659_add_merge_request_blocks.rb25
-rw-r--r--db/migrate/20190415030217_add_variable_type_to_ci_variables.rb17
-rw-r--r--db/migrate/20190415095825_add_packages_size_to_project_statistics.rb11
-rw-r--r--db/migrate/20190416185130_add_merge_train_enabled_to_ci_cd_settings.rb17
-rw-r--r--db/migrate/20190416213556_add_variable_type_to_ci_group_variables.rb17
-rw-r--r--db/migrate/20190416213615_add_variable_type_to_ci_pipeline_variables.rb17
-rw-r--r--db/migrate/20190416213631_add_variable_type_to_ci_pipeline_schedule_variables.rb17
-rw-r--r--db/migrate/20190418182545_create_merge_request_trains_table.rb18
-rw-r--r--db/migrate/20190422082247_create_project_metrics_settings.rb14
-rw-r--r--db/migrate/20190426180107_add_deployment_events_to_services.rb17
-rw-r--r--db/migrate/20190429082448_create_pages_domain_acme_orders.rb28
-rw-r--r--db/migrate/20190506135337_add_temporary_indexes_to_state_id.rb34
-rw-r--r--db/migrate/20190515125613_add_application_settings_elasticsearch_shards.rb10
-rw-r--r--db/migrate/20190516011213_add_build_queued_at_index.rb19
-rw-r--r--db/migrate/20190516151857_add_lets_encrypt_private_key_to_application_settings.rb16
-rw-r--r--db/migrate/20190516155724_change_packages_size_defaults_in_project_statistics.rb24
-rw-r--r--db/migrate/20190523112344_limit_milestone_date_years_to_4_digits.rb38
-rw-r--r--db/migrate/20190524062810_generate_lets_encrypt_private_key.rb18
-rw-r--r--db/migrate/20190524071727_add_ssl_valid_period_to_pages_domain.rb16
-rw-r--r--db/migrate/20190527194830_add_wiki_size_to_statistics.rb9
-rw-r--r--db/migrate/20190529142545_add_dns_rebinding_protection_enabled_to_application_settings.rb23
-rw-r--r--db/migrate/20190530042141_add_default_git_depth_to_ci_cd_settings.rb11
-rw-r--r--db/migrate/20190530154715_add_index_to_merge_requests_state_and_merge_status.rb21
-rw-r--r--db/migrate/20190604184643_fix_pool_repository_source_project_id.rb19
-rw-r--r--db/migrate/20190605104727_add_default_project_deletion_protection_to_application_settings.rb20
-rw-r--r--db/migrate/20190606014128_add_last_ci_minutes_notification_at_to_namespaces.rb12
-rw-r--r--db/migrate/20190607190856_add_index_to_users_public_emails.rb23
-rw-r--r--db/migrate/20190611161641_add_target_project_id_to_merge_trains.rb14
-rw-r--r--db/post_migrate/20190301081611_migrate_project_migrate_sidekiq_queue.rb2
-rw-r--r--db/post_migrate/20190424134256_drop_projects_ci_id.rb33
-rw-r--r--db/post_migrate/20190506135400_schedule_sync_issuables_state_id_where_nil.rb63
-rw-r--r--db/post_migrate/20190522143720_drop_project_auto_devops_domain.rb11
-rw-r--r--db/post_migrate/20190524073827_schedule_fill_valid_time_for_pages_domain_certificates.rb34
-rw-r--r--db/post_migrate/20190527194900_schedule_calculate_wiki_sizes.rb32
-rw-r--r--db/post_migrate/20190528180441_enqueue_reset_merge_status.rb25
-rw-r--r--db/schema.rb370
-rw-r--r--doc/README.md119
-rw-r--r--doc/administration/audit_events.md116
-rw-r--r--doc/administration/audit_log.pngbin0 -> 25767 bytes
-rw-r--r--doc/administration/auditor_access_form.pngbin0 -> 11910 bytes
-rw-r--r--doc/administration/auditor_users.md88
-rw-r--r--doc/administration/auth/README.md2
-rw-r--r--doc/administration/auth/google_secure_ldap.md2
-rw-r--r--doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md6
-rw-r--r--doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/admin_group.pngbin0 -> 17543 bytes
-rw-r--r--doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/group_link_final.pngbin0 -> 14524 bytes
-rw-r--r--doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/group_linking.gifbin0 -> 1504079 bytes
-rw-r--r--doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/manual_permissions.gifbin0 -> 1703084 bytes
-rw-r--r--doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/multi_login.gifbin0 -> 180218 bytes
-rw-r--r--doc/administration/auth/how_to_configure_ldap_gitlab_ee/index.md119
-rw-r--r--doc/administration/auth/ldap-ee.md557
-rw-r--r--doc/administration/auth/ldap.md11
-rw-r--r--doc/administration/auth/oidc.md163
-rw-r--r--doc/administration/auth/smartcard.md186
-rw-r--r--doc/administration/compliance.md10
-rw-r--r--doc/administration/container_registry.md46
-rw-r--r--doc/administration/custom_hooks.md70
-rw-r--r--doc/administration/database_load_balancing.md277
-rw-r--r--doc/administration/dependency_proxy.md150
-rw-r--r--doc/administration/geo/disaster_recovery/background_verification.md182
-rw-r--r--doc/administration/geo/disaster_recovery/bring_primary_back.md61
-rw-r--r--doc/administration/geo/disaster_recovery/img/checksum-differences-admin-project-page.pngbin0 -> 202130 bytes
-rw-r--r--doc/administration/geo/disaster_recovery/img/checksum-differences-admin-projects.pngbin0 -> 85997 bytes
-rw-r--r--doc/administration/geo/disaster_recovery/img/replication-status.pngbin0 -> 7716 bytes
-rw-r--r--doc/administration/geo/disaster_recovery/img/reverification-interval.pngbin0 -> 33620 bytes
-rw-r--r--doc/administration/geo/disaster_recovery/img/verification-status-primary.pngbin0 -> 13329 bytes
-rw-r--r--doc/administration/geo/disaster_recovery/img/verification-status-secondary.pngbin0 -> 12186 bytes
-rw-r--r--doc/administration/geo/disaster_recovery/index.md322
-rw-r--r--doc/administration/geo/disaster_recovery/planned_failover.md227
-rw-r--r--doc/administration/geo/replication/configuration.md308
-rw-r--r--doc/administration/geo/replication/database.md508
-rw-r--r--doc/administration/geo/replication/docker_registry.md23
-rw-r--r--doc/administration/geo/replication/external_database.md219
-rw-r--r--doc/administration/geo/replication/faq.md62
-rw-r--r--doc/administration/geo/replication/high_availability.md295
-rw-r--r--doc/administration/geo/replication/img/geo_architecture.pngbin0 -> 116506 bytes
-rw-r--r--doc/administration/geo/replication/img/geo_node_dashboard.pngbin0 -> 26266 bytes
-rw-r--r--doc/administration/geo/replication/img/geo_node_healthcheck.pngbin0 -> 28285 bytes
-rw-r--r--doc/administration/geo/replication/img/geo_overview.pngbin0 -> 37246 bytes
-rw-r--r--doc/administration/geo/replication/index.md292
-rw-r--r--doc/administration/geo/replication/object_storage.md43
-rw-r--r--doc/administration/geo/replication/remove_geo_node.md50
-rw-r--r--doc/administration/geo/replication/security_review.md284
-rw-r--r--doc/administration/geo/replication/troubleshooting.md514
-rw-r--r--doc/administration/geo/replication/tuning.md17
-rw-r--r--doc/administration/geo/replication/updating_the_geo_nodes.md448
-rw-r--r--doc/administration/geo/replication/using_a_geo_server.md18
-rw-r--r--doc/administration/gitaly/index.md36
-rw-r--r--doc/administration/high_availability/README.md217
-rw-r--r--doc/administration/high_availability/alpha_database.md6
-rw-r--r--doc/administration/high_availability/consul.md105
-rw-r--r--doc/administration/high_availability/database.md1155
-rw-r--r--doc/administration/high_availability/gitaly.md21
-rw-r--r--doc/administration/high_availability/gitlab.md6
-rw-r--r--doc/administration/high_availability/img/fully-distributed.pngbin0 -> 46918 bytes
-rw-r--r--doc/administration/high_availability/img/geo-ha-diagram.pngbin0 -> 43826 bytes
-rw-r--r--doc/administration/high_availability/img/horizontal.pngbin0 -> 18660 bytes
-rw-r--r--doc/administration/high_availability/img/hybrid.pngbin0 -> 20698 bytes
-rw-r--r--doc/administration/high_availability/img/pg_ha_architecture.pngbin0 -> 18412 bytes
-rw-r--r--doc/administration/high_availability/nfs.md25
-rw-r--r--doc/administration/high_availability/nfs_host_client_setup.md135
-rw-r--r--doc/administration/high_availability/pgbouncer.md132
-rw-r--r--doc/administration/high_availability/redis.md160
-rw-r--r--doc/administration/img/db_load_balancing_postgres_stats.pngbin0 -> 21543 bytes
-rw-r--r--doc/administration/img/high_availability/active-active-diagram.pngbin14649 -> 0 bytes
-rw-r--r--doc/administration/img/high_availability/active-passive-diagram.pngbin11699 -> 0 bytes
-rw-r--r--doc/administration/img/instance_review_button.pngbin0 -> 24525 bytes
-rw-r--r--doc/administration/incoming_email.md2
-rw-r--r--doc/administration/index.md50
-rw-r--r--doc/administration/instance_review.md17
-rw-r--r--doc/administration/integration/plantuml.md5
-rw-r--r--doc/administration/integration/terminal.md5
-rw-r--r--doc/administration/job_artifacts.md14
-rw-r--r--doc/administration/logs.md25
-rw-r--r--doc/administration/maven_packages.md5
-rw-r--r--doc/administration/maven_repository.md5
-rw-r--r--doc/administration/monitoring/performance/grafana_configuration.md8
-rw-r--r--doc/administration/monitoring/performance/index.md2
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md73
-rw-r--r--doc/administration/monitoring/prometheus/index.md24
-rw-r--r--doc/administration/monitoring/prometheus/pgbouncer_exporter.md34
-rw-r--r--doc/administration/npm_registry.md5
-rw-r--r--doc/administration/operations/cleaning_up_redis_sessions.md2
-rw-r--r--doc/administration/operations/extra_sidekiq_processes.md218
-rw-r--r--doc/administration/operations/fast_ssh_key_lookup.md15
-rw-r--r--doc/administration/operations/img/sidekiq-cluster.pngbin0 -> 61923 bytes
-rw-r--r--doc/administration/operations/index.md1
-rw-r--r--doc/administration/packages.md174
-rw-r--r--doc/administration/pages/index.md15
-rw-r--r--doc/administration/pseudonymizer.md103
-rw-r--r--doc/administration/raketasks/geo.md57
-rw-r--r--doc/administration/raketasks/maintenance.md19
-rw-r--r--doc/administration/raketasks/project_import_export.md1
-rw-r--r--doc/administration/raketasks/storage.md3
-rw-r--r--doc/administration/repository_storage_paths.md2
-rw-r--r--doc/administration/repository_storage_types.md11
-rw-r--r--doc/analytics/README.md5
-rw-r--r--doc/analytics/contribution_analytics.md5
-rw-r--r--doc/api/README.md140
-rw-r--r--doc/api/boards.md179
-rw-r--r--doc/api/commits.md1
-rw-r--r--doc/api/discussions.md224
-rw-r--r--doc/api/epic_issues.md413
-rw-r--r--doc/api/epic_links.md254
-rw-r--r--doc/api/epics.md360
-rw-r--r--doc/api/geo_nodes.md404
-rw-r--r--doc/api/graphql/index.md28
-rw-r--r--doc/api/group_level_variables.md31
-rw-r--r--doc/api/groups.md1
-rw-r--r--doc/api/issue_links.md215
-rw-r--r--doc/api/issues.md110
-rw-r--r--doc/api/issues_statistics.md177
-rw-r--r--doc/api/jobs.md113
-rw-r--r--doc/api/license.md176
-rw-r--r--doc/api/license_templates.md5
-rw-r--r--doc/api/managed_licenses.md136
-rw-r--r--doc/api/members.md4
-rw-r--r--doc/api/merge_request_approvals.md425
-rw-r--r--doc/api/merge_requests.md164
-rw-r--r--doc/api/milestones.md2
-rw-r--r--doc/api/notes.md132
-rw-r--r--doc/api/packages.md152
-rw-r--r--doc/api/pipeline_schedules.md5
-rw-r--r--doc/api/pipelines.md3
-rw-r--r--doc/api/project_clusters.md3
-rw-r--r--doc/api/project_level_variables.md50
-rw-r--r--doc/api/project_templates.md2
-rw-r--r--doc/api/projects.md20
-rw-r--r--doc/api/repository_files.md2
-rw-r--r--doc/api/repository_storage_health.md5
-rw-r--r--doc/api/resource_label_events.md86
-rw-r--r--doc/api/runners.md1
-rw-r--r--doc/api/scim.md235
-rw-r--r--doc/api/search.md188
-rw-r--r--doc/api/services.md74
-rw-r--r--doc/api/snippets.md10
-rw-r--r--doc/api/users.md8
-rw-r--r--doc/api/vulnerabilities.md113
-rw-r--r--doc/articles/how_to_configure_ldap_gitlab_ee/index.md5
-rw-r--r--doc/ci/README.md251
-rw-r--r--doc/ci/caching/index.md28
-rw-r--r--doc/ci/chatops/README.md27
-rw-r--r--doc/ci/ci_cd_for_external_repos/bitbucket_integration.md166
-rw-r--r--doc/ci/ci_cd_for_external_repos/github_integration.md133
-rw-r--r--doc/ci/ci_cd_for_external_repos/img/bitbucket_app_password.pngbin0 -> 31488 bytes
-rw-r--r--doc/ci/ci_cd_for_external_repos/img/bitbucket_webhook.pngbin0 -> 26142 bytes
-rw-r--r--doc/ci/ci_cd_for_external_repos/img/ci_cd_for_external_repo.pngbin0 -> 66760 bytes
-rw-r--r--doc/ci/ci_cd_for_external_repos/img/external_repository.pngbin0 -> 22832 bytes
-rw-r--r--doc/ci/ci_cd_for_external_repos/img/github_omniauth.pngbin0 -> 29022 bytes
-rw-r--r--doc/ci/ci_cd_for_external_repos/img/github_push_webhook.pngbin0 -> 45725 bytes
-rw-r--r--doc/ci/ci_cd_for_external_repos/img/github_repo_list.pngbin0 -> 14282 bytes
-rw-r--r--doc/ci/ci_cd_for_external_repos/index.md39
-rw-r--r--doc/ci/docker/README.md4
-rw-r--r--doc/ci/docker/using_docker_build.md59
-rw-r--r--doc/ci/docker/using_docker_images.md158
-rw-r--r--doc/ci/docker/using_kaniko.md42
-rw-r--r--doc/ci/enable_or_disable_ci.md61
-rw-r--r--doc/ci/environments.md218
-rw-r--r--doc/ci/environments/protected_environments.md41
-rw-r--r--doc/ci/examples/README.md73
-rw-r--r--doc/ci/examples/artifactory_and_gitlab/index.md7
-rw-r--r--doc/ci/examples/browser_performance.md28
-rw-r--r--doc/ci/examples/code_climate.md3
-rw-r--r--doc/ci/examples/code_quality.md53
-rw-r--r--doc/ci/examples/container_scanning.md122
-rw-r--r--doc/ci/examples/dast.md105
-rw-r--r--doc/ci/examples/dependency_scanning.md5
-rw-r--r--doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md15
-rw-r--r--doc/ci/examples/deployment/README.md14
-rw-r--r--doc/ci/examples/deployment/composer-npm-deploy.md24
-rw-r--r--doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md3
-rw-r--r--doc/ci/examples/end_to_end_testing_webdriverio/index.md5
-rw-r--r--doc/ci/examples/laravel_with_gitlab_and_envoy/img/laravel_with_gitlab_and_envoy.pngbin177704 -> 0 bytes
-rw-r--r--doc/ci/examples/laravel_with_gitlab_and_envoy/index.md1
-rw-r--r--doc/ci/examples/license_management.md5
-rw-r--r--doc/ci/examples/php.md12
-rw-r--r--doc/ci/examples/sast.md5
-rw-r--r--doc/ci/examples/sast_docker.md4
-rw-r--r--doc/ci/examples/test-and-deploy-python-application-to-heroku.md28
-rw-r--r--doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md17
-rw-r--r--doc/ci/examples/test-clojure-application.md20
-rw-r--r--doc/ci/examples/test-scala-application.md21
-rw-r--r--doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/job-succeeded.pngbin23148 -> 0 bytes
-rw-r--r--doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md7
-rw-r--r--doc/ci/git_submodules.md4
-rw-r--r--doc/ci/img/add_file_template_11_10.pngbin0 -> 55910 bytes
-rw-r--r--doc/ci/img/deployments_view.pngbin23352 -> 58498 bytes
-rw-r--r--doc/ci/img/environments_available.pngbin8464 -> 20410 bytes
-rw-r--r--doc/ci/img/environments_mr_review_app.pngbin13394 -> 30140 bytes
-rw-r--r--doc/ci/img/metrics_reports.pngbin0 -> 19450 bytes
-rw-r--r--doc/ci/img/multi_pipeline_mini_graph.gifbin0 -> 11466 bytes
-rw-r--r--doc/ci/img/multi_project_pipeline_graph.pngbin0 -> 10671 bytes
-rw-r--r--doc/ci/interactive_web_terminal/index.md9
-rw-r--r--doc/ci/introduction/img/gitlab_workflow_example_extended_11_11.pngbin0 -> 139184 bytes
-rw-r--r--doc/ci/introduction/index.md67
-rw-r--r--doc/ci/junit_test_reports.md10
-rw-r--r--doc/ci/large_repositories/index.md43
-rw-r--r--doc/ci/merge_request_pipelines/img/pipeline_detail.pngbin15556 -> 0 bytes
-rw-r--r--doc/ci/merge_request_pipelines/index.md35
-rw-r--r--doc/ci/metrics_reports.md49
-rw-r--r--doc/ci/multi_project_pipeline_graphs.md5
-rw-r--r--doc/ci/multi_project_pipelines.md189
-rw-r--r--doc/ci/pipelines.md21
-rw-r--r--doc/ci/quick_start/README.md24
-rw-r--r--doc/ci/review_apps/index.md8
-rw-r--r--doc/ci/runners/README.md4
-rw-r--r--doc/ci/runners/shared_to_specific_admin.pngbin5715 -> 0 bytes
-rw-r--r--doc/ci/services/README.md13
-rw-r--r--doc/ci/services/mysql.md31
-rw-r--r--doc/ci/services/postgres.md4
-rw-r--r--doc/ci/services/redis.md4
-rw-r--r--doc/ci/ssh_keys/README.md1
-rw-r--r--doc/ci/triggers/README.md64
-rw-r--r--doc/ci/variables/README.md130
-rw-r--r--doc/ci/variables/deprecated_variables.md7
-rw-r--r--doc/ci/variables/img/custom_variable_output.pngbin70552 -> 0 bytes
-rw-r--r--doc/ci/variables/img/custom_variables_output.pngbin0 -> 89185 bytes
-rw-r--r--doc/ci/variables/img/new_custom_variable_example.pngbin44164 -> 0 bytes
-rw-r--r--doc/ci/variables/img/new_custom_variables_example.pngbin0 -> 216497 bytes
-rw-r--r--doc/ci/variables/img/override_variable_manual_pipeline.pngbin29090 -> 41714 bytes
-rw-r--r--doc/ci/variables/img/variable_types_usage_example.pngbin0 -> 67003 bytes
-rw-r--r--doc/ci/variables/predefined_variables.md43
-rw-r--r--doc/ci/variables/where_variables_can_be_used.md31
-rw-r--r--doc/ci/yaml/README.md177
-rw-r--r--doc/customization/issue_and_merge_request_template.md5
-rw-r--r--doc/development/README.md15
-rw-r--r--doc/development/api_graphql_styleguide.md21
-rw-r--r--doc/development/architecture.md553
-rw-r--r--doc/development/changelog.md1
-rw-r--r--doc/development/chatops_on_gitlabcom.md21
-rw-r--r--doc/development/code_review.md72
-rw-r--r--doc/development/contributing/index.md2
-rw-r--r--doc/development/contributing/issue_workflow.md61
-rw-r--r--doc/development/contributing/merge_request_workflow.md2
-rw-r--r--doc/development/database_debugging.md2
-rw-r--r--doc/development/distributed_tracing.md2
-rw-r--r--doc/development/documentation/feature-change-workflow.md12
-rw-r--r--doc/development/documentation/index.md64
-rw-r--r--doc/development/documentation/structure.md8
-rw-r--r--doc/development/documentation/styleguide.md143
-rw-r--r--doc/development/ee_features.md116
-rw-r--r--doc/development/elasticsearch.md166
-rw-r--r--doc/development/fe_guide/frontend_faq.md41
-rw-r--r--doc/development/fe_guide/graphql.md14
-rw-r--r--doc/development/fe_guide/index.md4
-rw-r--r--doc/development/fe_guide/style_guide_js.md20
-rw-r--r--doc/development/fe_guide/style_guide_scss.md42
-rw-r--r--doc/development/fe_guide/vue.md2
-rw-r--r--doc/development/fe_guide/vuex.md4
-rw-r--r--doc/development/feature_flags.md12
-rw-r--r--doc/development/geo.md529
-rw-r--r--doc/development/git_object_deduplication.md109
-rw-r--r--doc/development/gitaly.md6
-rw-r--r--doc/development/gitlab_architecture_diagram.pngbin34253 -> 0 bytes
-rw-r--r--doc/development/go_guide/index.md8
-rw-r--r--doc/development/i18n/externalization.md9
-rw-r--r--doc/development/i18n/merging_translations.md2
-rw-r--r--doc/development/i18n/proofreader.md22
-rw-r--r--doc/development/i18n/translation.md8
-rw-r--r--doc/development/img/architecture_simplified.pngbin0 -> 61590 bytes
-rw-r--r--doc/development/import_export.md2
-rw-r--r--doc/development/integrations/jira_connect.md41
-rw-r--r--doc/development/licensed_feature_availability.md37
-rw-r--r--doc/development/licensing.md6
-rw-r--r--doc/development/migration_style_guide.md6
-rw-r--r--doc/development/new_fe_guide/development/accessibility.md1
-rw-r--r--doc/development/new_fe_guide/development/components.md2
-rw-r--r--doc/development/new_fe_guide/tips.md12
-rw-r--r--doc/development/packages.md68
-rw-r--r--doc/development/rake_tasks.md47
-rw-r--r--doc/development/rolling_out_changes_using_feature_flags.md20
-rw-r--r--doc/development/routing.md63
-rw-r--r--doc/development/session.md65
-rw-r--r--doc/development/testing_guide/best_practices.md64
-rw-r--r--doc/development/testing_guide/end_to_end/best_practices.md38
-rw-r--r--doc/development/testing_guide/end_to_end/dynamic_element_validation.md113
-rw-r--r--doc/development/testing_guide/end_to_end/index.md167
-rw-r--r--doc/development/testing_guide/end_to_end/page_objects.md167
-rw-r--r--doc/development/testing_guide/end_to_end/quick_start_guide.md587
-rw-r--r--doc/development/testing_guide/end_to_end/resources.md392
-rw-r--r--doc/development/testing_guide/end_to_end/style_guide.md99
-rw-r--r--doc/development/testing_guide/end_to_end_tests.md162
-rw-r--r--doc/development/testing_guide/frontend_testing.md248
-rw-r--r--doc/development/testing_guide/img/review_apps_cicd_architecture.pngbin73240 -> 136431 bytes
-rw-r--r--doc/development/testing_guide/index.md2
-rw-r--r--doc/development/testing_guide/review_apps.md258
-rw-r--r--doc/development/testing_guide/smoke.md2
-rw-r--r--doc/development/testing_guide/testing_levels.md33
-rw-r--r--doc/development/understanding_explain_plans.md47
-rw-r--r--doc/development/ux_guide/img/animation-autoscroll.gifbin302217 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/animation-dropdown.gifbin22483 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/animation-hover.gifbin247388 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/animation-quickupdate.gifbin6441 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/animation-reorder.gifbin70515 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-close--active.pngbin1120 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-close--hover.pngbin765 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-close--resting.pngbin915 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-danger--active.pngbin1117 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-danger--hover.pngbin797 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-danger--resting.pngbin932 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-info--active.pngbin1109 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-info--hover.pngbin795 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-info--resting.pngbin930 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-primary.pngbin1550 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-secondary.pngbin2683 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-spam--active.pngbin1107 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-spam--hover.pngbin777 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-spam--resting.pngbin941 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-success--active.pngbin1153 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-success--hover.pngbin892 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-success--resting.pngbin1045 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-success-secondary--active.pngbin1107 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-success-secondary--hover.pngbin774 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-success-secondary--resting.pngbin945 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-warning--active.pngbin1124 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-warning--hover.pngbin790 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/button-warning--resting.pngbin925 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/color-blue.pngbin1751 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/color-green.pngbin1916 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/color-grey.pngbin1681 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/color-orange.pngbin2094 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/color-red.pngbin1739 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/color-textprimary.pngbin2553 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/color-textsecondary.pngbin2956 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-alerts.pngbin27342 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-anchorlinks.pngbin16457 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-contentblock.pngbin14190 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-counts.pngbin2438 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-coverblock.pngbin10110 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-dateexact.pngbin4157 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-daterelative.pngbin4189 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-dropdown.pngbin31760 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-fileholder.pngbin3884 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-horizontalform.pngbin4310 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-listinsidepanel.pngbin3380 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-listwithavatar.pngbin5749 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-listwithhover.pngbin2722 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-panels.pngbin21822 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-referencehover.pngbin6890 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-referenceissues.pngbin10002 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-referencelabels.pngbin4099 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-referencemilestone.pngbin2412 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-referencemrs.pngbin8857 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-referencepeople.pngbin5600 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-rowcontentblock.pngbin14315 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-searchbox.pngbin3596 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-searchboxscoped.pngbin6027 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-simplelist.pngbin2776 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-table.pngbin6081 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/components-verticalform.pngbin4964 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/cursors-default.pngbin567 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/cursors-ibeam.pngbin383 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/cursors-move.pngbin276 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/cursors-panclosed.pngbin483 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/cursors-panopened.pngbin622 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/cursors-pointer.pngbin574 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/features-contextualnav.pngbin5911 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/features-emptystates.pngbin61644 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/features-filters.pngbin3924 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/features-globalnav.pngbin5780 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/harry-robison.pngbin10712 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/icon-add.pngbin239 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/icon-close.pngbin301 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/icon-edit.pngbin315 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/icon-notification.pngbin379 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/icon-rss.pngbin528 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/icon-spec.pngbin7523 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/icon-subscribe.pngbin537 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/icon-trash.pngbin281 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/illustration-size-large-horizontal.pngbin55272 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/illustration-size-large-vertical.pngbin59217 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/illustration-size-medium.pngbin20994 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/illustration-size-small.pngbin43536 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/illustrations-border-radius.pngbin7779 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/illustrations-caps-do.pngbin3671 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/illustrations-caps-don't.pngbin3624 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/illustrations-color-grey.pngbin251 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/illustrations-color-orange.pngbin275 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/illustrations-color-purple.pngbin275 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/illustrations-geometric.pngbin5057 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/illustrations-palette-oragne.pngbin10439 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/illustrations-palette-purple.pngbin10002 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/james-mackey.pngbin11869 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/karolina-plaskaty.pngbin10355 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/matthieu-poirier.pngbin11483 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/modals-general-confimation-dialog.pngbin15650 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/modals-layout-for-modals.pngbin20060 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/modals-special-confimation-dialog.pngbin31419 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/modals-three-buttons.pngbin17457 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/monospacefont-sample.pngbin14282 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/nazim-ramesh.pngbin10488 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/popover-placement-above.pngbin20184 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/popover-placement-below.pngbin19967 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/skeleton-loading.gifbin1093917 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/sourcesanspro-sample.pngbin10948 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/steven-lyons.pngbin9323 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/surfaces-contentitemtitle.pngbin5139 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/surfaces-header.pngbin4095 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/surfaces-systeminformationblock.pngbin10422 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/surfaces-ux.pngbin4017 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/tooltip-placement.pngbin2066 -> 0 bytes
-rw-r--r--doc/development/ux_guide/img/tooltip-usage.pngbin5985 -> 0 bytes
-rw-r--r--doc/getting-started/subscription.md3
-rw-r--r--doc/git_hooks/git_hooks.md5
-rw-r--r--doc/gitlab-basics/README.md49
-rw-r--r--doc/gitlab-basics/command-line-commands.md4
-rw-r--r--doc/gitlab-basics/create-project.md3
-rw-r--r--doc/gitlab-basics/create-your-ssh-keys.md30
-rw-r--r--doc/gitlab-basics/img/new_issue_button.pngbin2010 -> 0 bytes
-rw-r--r--doc/gitlab-basics/img/new_issue_page.pngbin21386 -> 0 bytes
-rw-r--r--doc/gitlab-basics/img/profile_settings_ssh_keys_single_key.pngbin10534 -> 0 bytes
-rw-r--r--doc/gitlab-basics/img/public_file_link.pngbin3023 -> 0 bytes
-rw-r--r--doc/gitlab-basics/start-using-git.md24
-rw-r--r--doc/gitlab-geo/README.md5
-rw-r--r--doc/gitlab-geo/after_setup.md5
-rw-r--r--doc/gitlab-geo/bring-primary-back.md5
-rw-r--r--doc/gitlab-geo/configuration.md5
-rw-r--r--doc/gitlab-geo/configuration_source.md5
-rw-r--r--doc/gitlab-geo/database.md5
-rw-r--r--doc/gitlab-geo/database_source.md5
-rw-r--r--doc/gitlab-geo/disaster-recovery.md5
-rw-r--r--doc/gitlab-geo/docker_registry.md5
-rw-r--r--doc/gitlab-geo/faq.md5
-rw-r--r--doc/gitlab-geo/ha.md5
-rw-r--r--doc/gitlab-geo/object_storage.md5
-rw-r--r--doc/gitlab-geo/planned-failover.md5
-rw-r--r--doc/gitlab-geo/security-review.md5
-rw-r--r--doc/gitlab-geo/ssh.md5
-rw-r--r--doc/gitlab-geo/troubleshooting.md5
-rw-r--r--doc/gitlab-geo/tuning.md5
-rw-r--r--doc/gitlab-geo/updating_the_geo_nodes.md5
-rw-r--r--doc/gitlab-geo/using_a_geo_server.md5
-rw-r--r--doc/install/README.md3
-rw-r--r--doc/install/aws/img/add_tags.pngbin17834 -> 0 bytes
-rw-r--r--doc/install/aws/img/create_route_table.pngbin8293 -> 0 bytes
-rw-r--r--doc/install/aws/index.md24
-rw-r--r--doc/install/azure/img/azure-vm-management-settings-network-interfaces.pngbin35849 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-vm-management.pngbin35363 -> 0 bytes
-rw-r--r--doc/install/azure/index.md20
-rw-r--r--doc/install/database_mysql.md16
-rw-r--r--doc/install/digitaloceandocker.md41
-rw-r--r--doc/install/docker.md6
-rw-r--r--doc/install/google-protobuf.md29
-rw-r--r--doc/install/google_cloud_platform/img/gcp_landing.pngbin9978 -> 0 bytes
-rw-r--r--doc/install/google_cloud_platform/index.md24
-rw-r--r--doc/install/installation.md223
-rw-r--r--doc/install/kubernetes/index.md40
-rw-r--r--doc/install/ldap.md5
-rw-r--r--doc/install/openshift_and_gitlab/img/pods-overview.pngbin42617 -> 0 bytes
-rw-r--r--doc/install/openshift_and_gitlab/img/storage-volumes.pngbin20007 -> 0 bytes
-rw-r--r--doc/install/openshift_and_gitlab/index.md5
-rw-r--r--doc/install/pivotal/index.md12
-rw-r--r--doc/install/redis.md63
-rw-r--r--doc/install/relative_url.md29
-rw-r--r--doc/install/requirements.md61
-rw-r--r--doc/install/structure.md22
-rw-r--r--doc/integration/README.md2
-rw-r--r--doc/integration/elasticsearch.md518
-rw-r--r--doc/integration/github.md6
-rw-r--r--doc/integration/img/google_app.pngbin18853 -> 0 bytes
-rw-r--r--doc/integration/img/jenkins_gitlab_plugin_config.pngbin0 -> 10054 bytes
-rw-r--r--doc/integration/img/jenkins_gitlab_service.pngbin0 -> 19235 bytes
-rw-r--r--doc/integration/img/jenkins_gitlab_service_settings.pngbin0 -> 24094 bytes
-rw-r--r--doc/integration/img/jenkins_project.pngbin0 -> 42275 bytes
-rw-r--r--doc/integration/img/jira_dev_panel_gl_setup_1.pngbin0 -> 36145 bytes
-rw-r--r--doc/integration/img/jira_dev_panel_jira_setup_1.pngbin0 -> 29546 bytes
-rw-r--r--doc/integration/img/jira_dev_panel_jira_setup_2.pngbin0 -> 17374 bytes
-rw-r--r--doc/integration/img/jira_dev_panel_jira_setup_3.pngbin0 -> 37257 bytes
-rw-r--r--doc/integration/img/jira_dev_panel_jira_setup_4.pngbin0 -> 21592 bytes
-rw-r--r--doc/integration/img/jira_dev_panel_jira_setup_5.pngbin0 -> 11002 bytes
-rw-r--r--doc/integration/img/jira_dev_panel_manual_refresh.pngbin0 -> 23542 bytes
-rw-r--r--doc/integration/img/limit_namespace_filter.pngbin0 -> 12777 bytes
-rw-r--r--doc/integration/img/limit_namespaces_projects_options.pngbin0 -> 22650 bytes
-rw-r--r--doc/integration/img/salesforce_app_details.pngbin0 -> 116022 bytes
-rw-r--r--doc/integration/img/salesforce_app_secret_details.pngbin0 -> 199643 bytes
-rw-r--r--doc/integration/img/salesforce_oauth_app_details.pngbin0 -> 171542 bytes
-rw-r--r--doc/integration/img/ultra_auth_credentials.pngbin0 -> 53737 bytes
-rw-r--r--doc/integration/img/ultra_auth_edit_callback_url.pngbin0 -> 39410 bytes
-rw-r--r--doc/integration/img/ultra_auth_edit_callback_url_highlighted.pngbin0 -> 68383 bytes
-rw-r--r--doc/integration/jenkins.md134
-rw-r--r--doc/integration/jenkins_deprecated.md53
-rw-r--r--doc/integration/jira_development_panel.md141
-rw-r--r--doc/integration/kerberos.md315
-rw-r--r--doc/integration/omniauth.md3
-rw-r--r--doc/integration/salesforce.md79
-rw-r--r--doc/integration/saml.md330
-rw-r--r--doc/integration/slash_commands.md4
-rw-r--r--doc/integration/ultra_auth.md78
-rw-r--r--doc/legal/corporate_contributor_license_agreement.md32
-rw-r--r--doc/legal/individual_contributor_license_agreement.md28
-rw-r--r--doc/license/README.md5
-rw-r--r--doc/migrate_ci_to_ce/README.md19
-rw-r--r--doc/monitoring/performance/img/grafana_dashboard_dropdown.pngbin7761 -> 0 bytes
-rw-r--r--doc/monitoring/performance/img/grafana_dashboard_import.pngbin11835 -> 0 bytes
-rw-r--r--doc/monitoring/performance/img/grafana_data_source_configuration.pngbin14695 -> 0 bytes
-rw-r--r--doc/monitoring/performance/img/grafana_data_source_empty.pngbin11960 -> 0 bytes
-rw-r--r--doc/monitoring/performance/img/grafana_save_icon.pngbin4598 -> 0 bytes
-rw-r--r--doc/monitoring/performance/img/metrics_gitlab_configuration_settings.pngbin21382 -> 0 bytes
-rw-r--r--doc/policy/maintenance.md25
-rw-r--r--doc/public_access/public_access.md53
-rw-r--r--doc/push_rules/push_rules.md173
-rw-r--r--doc/raketasks/backup_restore.md6
-rw-r--r--doc/raketasks/cleanup.md10
-rw-r--r--doc/raketasks/import.md2
-rw-r--r--doc/security/README.md1
-rw-r--r--doc/security/crime_vulnerability.md36
-rw-r--r--doc/security/img/two_factor_authentication_group_settings.pngbin19495 -> 0 bytes
-rw-r--r--doc/security/img/two_factor_authentication_settings.pngbin9936 -> 0 bytes
-rw-r--r--doc/security/information_exclusivity.md41
-rw-r--r--doc/security/password_length_limits.md21
-rw-r--r--doc/security/rack_attack.md28
-rw-r--r--doc/security/reset_root_password.md19
-rw-r--r--doc/security/ssh_keys_restrictions.md15
-rw-r--r--doc/security/two_factor_authentication.md64
-rw-r--r--doc/security/unlock_user.md20
-rw-r--r--doc/security/user_email_confirmation.md22
-rw-r--r--doc/security/user_file_uploads.md35
-rw-r--r--doc/security/webhooks.md52
-rw-r--r--doc/ssh/README.md44
-rw-r--r--doc/subscriptions/billing_table.pngbin0 -> 28321 bytes
-rw-r--r--doc/subscriptions/index.md128
-rw-r--r--doc/system_hooks/system_hooks.md24
-rw-r--r--doc/tools/email.md48
-rw-r--r--doc/tools/email1.pngbin0 -> 9590 bytes
-rw-r--r--doc/tools/email2.pngbin0 -> 14902 bytes
-rw-r--r--doc/topics/authentication/index.md8
-rw-r--r--doc/topics/autodevops/img/autodevops_domain_variables.pngbin8456 -> 0 bytes
-rw-r--r--doc/topics/autodevops/img/guide_connect_cluster.pngbin15225 -> 0 bytes
-rw-r--r--doc/topics/autodevops/img/guide_create_cluster.pngbin18915 -> 0 bytes
-rw-r--r--doc/topics/autodevops/img/guide_gke_apis_after.pngbin26811 -> 0 bytes
-rw-r--r--doc/topics/autodevops/img/guide_gke_apis_before.pngbin14882 -> 0 bytes
-rw-r--r--doc/topics/autodevops/img/guide_merge_request_ide.pngbin35052 -> 0 bytes
-rw-r--r--doc/topics/autodevops/index.md211
-rw-r--r--doc/topics/autodevops/quick_start_guide.md4
-rw-r--r--doc/topics/git/how_to_install_git/index.md29
-rw-r--r--doc/topics/git/index.md61
-rw-r--r--doc/topics/git/numerous_undo_possibilities_in_git/index.md121
-rw-r--r--doc/topics/git/troubleshooting_git.md48
-rw-r--r--doc/university/README.md108
-rw-r--r--doc/university/bookclub/booklist.md107
-rw-r--r--doc/university/bookclub/index.md11
-rw-r--r--doc/university/glossary/README.md707
-rw-r--r--doc/university/high-availability/aws/README.md393
-rw-r--r--doc/university/high-availability/aws/img/auto-scaling-det.pngbin29967 -> 0 bytes
-rw-r--r--doc/university/high-availability/aws/img/db-subnet-group.pngbin29298 -> 0 bytes
-rw-r--r--doc/university/high-availability/aws/img/ec-subnet.pngbin28405 -> 0 bytes
-rw-r--r--doc/university/high-availability/aws/img/elastic-file-system.pngbin34582 -> 0 bytes
-rw-r--r--doc/university/high-availability/aws/img/ig-rt.pngbin12547 -> 0 bytes
-rw-r--r--doc/university/high-availability/aws/img/ig.pngbin8140 -> 0 bytes
-rw-r--r--doc/university/high-availability/aws/img/instance_specs.pngbin11522 -> 0 bytes
-rw-r--r--doc/university/high-availability/aws/img/new_vpc.pngbin15691 -> 0 bytes
-rw-r--r--doc/university/high-availability/aws/img/policies.pngbin39723 -> 0 bytes
-rw-r--r--doc/university/high-availability/aws/img/rds-net-opt.pngbin16340 -> 0 bytes
-rw-r--r--doc/university/high-availability/aws/img/rds-sec-group.pngbin11579 -> 0 bytes
-rw-r--r--doc/university/high-availability/aws/img/redis-cluster-det.pngbin23761 -> 0 bytes
-rw-r--r--doc/university/high-availability/aws/img/redis-net.pngbin27261 -> 0 bytes
-rw-r--r--doc/university/high-availability/aws/img/reference-arch2.pngbin53510 -> 0 bytes
-rw-r--r--doc/university/high-availability/aws/img/route_table.pngbin12088 -> 0 bytes
-rw-r--r--doc/university/high-availability/aws/img/subnet.pngbin17070 -> 0 bytes
-rw-r--r--doc/university/support/README.md126
-rw-r--r--doc/university/training/gitlab_flow.md15
-rw-r--r--doc/university/training/index.md32
-rw-r--r--doc/university/training/topics/additional_resources.md12
-rw-r--r--doc/university/training/topics/agile_git.md9
-rw-r--r--doc/university/training/topics/bisect.md16
-rw-r--r--doc/university/training/topics/cherry_picking.md6
-rw-r--r--doc/university/training/topics/env_setup.md5
-rw-r--r--doc/university/training/topics/explore_gitlab.md2
-rw-r--r--doc/university/training/topics/feature_branching.md8
-rw-r--r--doc/university/training/topics/getting_started.md21
-rw-r--r--doc/university/training/topics/git_add.md4
-rw-r--r--doc/university/training/topics/git_intro.md4
-rw-r--r--doc/university/training/topics/git_log.md20
-rw-r--r--doc/university/training/topics/merge_conflicts.md11
-rw-r--r--doc/university/training/topics/merge_requests.md8
-rw-r--r--doc/university/training/topics/rollback_commits.md22
-rw-r--r--doc/university/training/topics/stash.md22
-rw-r--r--doc/university/training/topics/subtree.md20
-rw-r--r--doc/university/training/topics/tags.md21
-rw-r--r--doc/university/training/topics/unstage.md12
-rw-r--r--doc/university/training/user_training.md80
-rw-r--r--doc/update/10.0-ce-to-ee.md5
-rw-r--r--doc/update/10.1-ce-to-ee.md5
-rw-r--r--doc/update/10.2-ce-to-ee.md5
-rw-r--r--doc/update/10.3-ce-to-ee.md5
-rw-r--r--doc/update/10.4-ce-to-ee.md5
-rw-r--r--doc/update/10.5-ce-to-ee.md5
-rw-r--r--doc/update/10.6-ce-to-ee.md5
-rw-r--r--doc/update/10.7-ce-to-ee.md5
-rw-r--r--doc/update/10.8-ce-to-ee.md5
-rw-r--r--doc/update/11.0-ce-to-ee.md5
-rw-r--r--doc/update/11.1-ce-to-ee.md5
-rw-r--r--doc/update/11.2-ce-to-ee.md5
-rw-r--r--doc/update/11.3-ce-to-ee.md5
-rw-r--r--doc/update/11.4-ce-to-ee.md5
-rw-r--r--doc/update/11.5-ce-to-ee.md5
-rw-r--r--doc/update/11.6-ce-to-ee.md5
-rw-r--r--doc/update/11.7-ce-to-ee.md5
-rw-r--r--doc/update/11.8-ce-to-ee.md5
-rw-r--r--doc/update/6.0-ce-to-ee.md5
-rw-r--r--doc/update/6.1-ce-to-ee.md5
-rw-r--r--doc/update/6.2-ce-to-ee.md5
-rw-r--r--doc/update/6.3-ce-to-ee.md5
-rw-r--r--doc/update/6.4-ce-to-ee.md5
-rw-r--r--doc/update/6.5-ce-to-ee.md5
-rw-r--r--doc/update/6.6-ce-to-ee.md5
-rw-r--r--doc/update/6.7-ce-to-ee.md5
-rw-r--r--doc/update/6.8-ce-to-ee.md5
-rw-r--r--doc/update/6.9-ce-to-ee.md5
-rw-r--r--doc/update/7.0-ce-to-ee.md5
-rw-r--r--doc/update/7.1-ce-to-ee.md5
-rw-r--r--doc/update/7.10-ce-to-ee.md5
-rw-r--r--doc/update/7.11-ce-to-ee.md5
-rw-r--r--doc/update/7.12-ce-to-ee.md5
-rw-r--r--doc/update/7.13-ce-to-ee.md5
-rw-r--r--doc/update/7.14-ce-to-ee.md5
-rw-r--r--doc/update/7.3-ce-to-ee.md5
-rw-r--r--doc/update/7.4-ce-to-ee.md5
-rw-r--r--doc/update/7.5-ce-to-ee.md5
-rw-r--r--doc/update/7.6-ce-to-ee.md5
-rw-r--r--doc/update/7.7-ce-to-ee.md5
-rw-r--r--doc/update/7.8-ce-to-ee.md5
-rw-r--r--doc/update/7.9-ce-to-ee.md5
-rw-r--r--doc/update/8.0-ce-to-ee.md5
-rw-r--r--doc/update/8.1-ce-to-ee.md5
-rw-r--r--doc/update/8.10-ce-to-ee.md5
-rw-r--r--doc/update/8.11-ce-to-ee.md5
-rw-r--r--doc/update/8.12-ce-to-ee.md5
-rw-r--r--doc/update/8.13-ce-to-ee.md5
-rw-r--r--doc/update/8.14-ce-to-ee.md5
-rw-r--r--doc/update/8.15-ce-to-ee.md5
-rw-r--r--doc/update/8.16-ce-to-ee.md5
-rw-r--r--doc/update/8.17-ce-to-ee.md5
-rw-r--r--doc/update/8.2-ce-to-ee.md5
-rw-r--r--doc/update/8.3-ce-to-ee.md5
-rw-r--r--doc/update/8.4-ce-to-ee.md5
-rw-r--r--doc/update/8.5-ce-to-ee.md5
-rw-r--r--doc/update/8.6-ce-to-ee.md5
-rw-r--r--doc/update/8.7-ce-to-ee.md5
-rw-r--r--doc/update/8.8-ce-to-ee.md5
-rw-r--r--doc/update/8.9-ce-to-ee.md5
-rw-r--r--doc/update/9.0-ce-to-ee.md5
-rw-r--r--doc/update/9.1-ce-to-ee.md5
-rw-r--r--doc/update/9.2-ce-to-ee.md5
-rw-r--r--doc/update/9.3-ce-to-ee.md5
-rw-r--r--doc/update/9.4-ce-to-ee.md5
-rw-r--r--doc/update/9.5-ce-to-ee.md5
-rw-r--r--doc/update/mysql_to_postgresql.md18
-rw-r--r--doc/update/patch_versions.md12
-rw-r--r--doc/update/upgrading_from_ce_to_ee.md7
-rw-r--r--doc/update/upgrading_from_source.md93
-rw-r--r--doc/user/admin_area/diff_limits.md41
-rw-r--r--doc/user/admin_area/geo_nodes.md86
-rw-r--r--doc/user/admin_area/img/admin_wrench.pngbin0 -> 3314 bytes
-rw-r--r--doc/user/admin_area/img/index_runners_search_or_filter.pngbin0 -> 22414 bytes
-rw-r--r--doc/user/admin_area/img/license_admin_area.pngbin0 -> 27826 bytes
-rw-r--r--doc/user/admin_area/img/license_details.pngbin0 -> 119290 bytes
-rw-r--r--doc/user/admin_area/img/license_upload.pngbin0 -> 10043 bytes
-rw-r--r--doc/user/admin_area/index.md224
-rw-r--r--doc/user/admin_area/labels.md22
-rw-r--r--doc/user/admin_area/license.md120
-rw-r--r--doc/user/admin_area/monitoring/health_check.md41
-rw-r--r--doc/user/admin_area/settings/account_and_limit_settings.md62
-rw-r--r--doc/user/admin_area/settings/continuous_integration.md114
-rw-r--r--doc/user/admin_area/settings/email.md40
-rw-r--r--doc/user/admin_area/settings/external_authorization.md128
-rw-r--r--doc/user/admin_area/settings/img/additional_minutes.pngbin0 -> 32045 bytes
-rw-r--r--doc/user/admin_area/settings/img/admin_area_default_artifacts_expiration.pngbin5360 -> 0 bytes
-rw-r--r--doc/user/admin_area/settings/img/admin_area_maximum_artifacts_size.pngbin4771 -> 0 bytes
-rw-r--r--doc/user/admin_area/settings/img/admin_project_quota_view.pngbin0 -> 2670 bytes
-rw-r--r--doc/user/admin_area/settings/img/buy_btn.pngbin0 -> 26960 bytes
-rw-r--r--doc/user/admin_area/settings/img/buy_minutes_card.pngbin0 -> 29329 bytes
-rw-r--r--doc/user/admin_area/settings/img/classification_label_on_project_page.pngbin0 -> 19568 bytes
-rw-r--r--doc/user/admin_area/settings/img/email_settings.pngbin0 -> 53267 bytes
-rw-r--r--doc/user/admin_area/settings/img/external_authorization_service_settings.pngbin0 -> 74753 bytes
-rw-r--r--doc/user/admin_area/settings/img/file_template_admin_area.pngbin0 -> 5624 bytes
-rw-r--r--doc/user/admin_area/settings/img/file_template_user_dropdown.pngbin0 -> 8067 bytes
-rw-r--r--doc/user/admin_area/settings/img/group_pipelines_quota.pngbin0 -> 7088 bytes
-rw-r--r--doc/user/admin_area/settings/img/mirror_settings.pngbin0 -> 9966 bytes
-rw-r--r--doc/user/admin_area/settings/index.md14
-rw-r--r--doc/user/admin_area/settings/instance_template_repository.md79
-rw-r--r--doc/user/admin_area/settings/sign_up_restrictions.md16
-rw-r--r--doc/user/admin_area/settings/terms.md46
-rw-r--r--doc/user/admin_area/settings/third_party_offers.md23
-rw-r--r--doc/user/admin_area/settings/usage_statistics.md20
-rw-r--r--doc/user/admin_area/settings/visibility_and_access_controls.md54
-rw-r--r--doc/user/application_security/container_scanning/img/container_scanning.pngbin0 -> 32549 bytes
-rw-r--r--doc/user/application_security/container_scanning/index.md204
-rw-r--r--doc/user/application_security/dast/img/dast_all.pngbin0 -> 25844 bytes
-rw-r--r--doc/user/application_security/dast/img/dast_single.pngbin0 -> 69353 bytes
-rw-r--r--doc/user/application_security/dast/index.md261
-rw-r--r--doc/user/application_security/dependency_scanning/img/dependency_scanning.pngbin0 -> 16167 bytes
-rw-r--r--doc/user/application_security/dependency_scanning/index.md395
-rw-r--r--doc/user/application_security/img/create_issue_with_list_hover.pngbin0 -> 106954 bytes
-rw-r--r--doc/user/application_security/img/dismissed_info.pngbin0 -> 20244 bytes
-rw-r--r--doc/user/application_security/img/interactive_reports.pngbin0 -> 93910 bytes
-rw-r--r--doc/user/application_security/img/issue.pngbin0 -> 4780 bytes
-rw-r--r--doc/user/application_security/img/vulnerability_solution.pngbin0 -> 3421 bytes
-rw-r--r--doc/user/application_security/index.md114
-rw-r--r--doc/user/application_security/license_management/img/license_management.pngbin0 -> 5184 bytes
-rw-r--r--doc/user/application_security/license_management/img/license_management_decision.pngbin0 -> 5981 bytes
-rw-r--r--doc/user/application_security/license_management/img/license_management_pipeline_tab.pngbin0 -> 12115 bytes
-rw-r--r--doc/user/application_security/license_management/img/license_management_settings.pngbin0 -> 13300 bytes
-rw-r--r--doc/user/application_security/license_management/index.md264
-rw-r--r--doc/user/application_security/sast/img/sast.pngbin0 -> 24876 bytes
-rw-r--r--doc/user/application_security/sast/img/security_report.pngbin0 -> 38475 bytes
-rw-r--r--doc/user/application_security/sast/index.md366
-rw-r--r--doc/user/application_security/security_dashboard/img/dashboard.pngbin0 -> 58585 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/project_security_dashboard.pngbin0 -> 126356 bytes
-rw-r--r--doc/user/application_security/security_dashboard/index.md104
-rw-r--r--doc/user/asciidoc.md372
-rw-r--r--doc/user/clusters/applications.md290
-rw-r--r--doc/user/clusters/img/jupyter-git-extension.gifbin0 -> 2120084 bytes
-rw-r--r--doc/user/clusters/img/jupyter-gitclone.pngbin0 -> 64120 bytes
-rw-r--r--doc/user/discussions/img/mr_review_resolve.pngbin0 -> 21941 bytes
-rw-r--r--doc/user/discussions/img/mr_review_resolve2.pngbin0 -> 9430 bytes
-rw-r--r--doc/user/discussions/img/mr_review_second_comment.pngbin0 -> 11188 bytes
-rw-r--r--doc/user/discussions/img/mr_review_second_comment_added.pngbin0 -> 9673 bytes
-rw-r--r--doc/user/discussions/img/mr_review_start.pngbin0 -> 23491 bytes
-rw-r--r--doc/user/discussions/img/mr_review_unresolve.pngbin0 -> 11302 bytes
-rw-r--r--doc/user/discussions/img/mr_review_unresolve2.pngbin0 -> 8976 bytes
-rw-r--r--doc/user/discussions/img/pending_review_comment.pngbin0 -> 8793 bytes
-rw-r--r--doc/user/discussions/img/review_comment_quickactions.pngbin0 -> 12392 bytes
-rw-r--r--doc/user/discussions/img/review_preview.pngbin0 -> 19769 bytes
-rw-r--r--doc/user/discussions/index.md102
-rw-r--r--doc/user/group/clusters/index.md81
-rw-r--r--doc/user/group/contribution_analytics/img/group_stats_cal.pngbin0 -> 2029 bytes
-rw-r--r--doc/user/group/contribution_analytics/img/group_stats_graph.pngbin0 -> 35400 bytes
-rw-r--r--doc/user/group/contribution_analytics/img/group_stats_table.pngbin0 -> 8473 bytes
-rw-r--r--doc/user/group/contribution_analytics/index.md77
-rw-r--r--doc/user/group/custom_project_templates.md18
-rw-r--r--doc/user/group/dependency_proxy/img/group_dependency_proxy.pngbin0 -> 40162 bytes
-rw-r--r--doc/user/group/dependency_proxy/index.md74
-rw-r--r--doc/user/group/epics/img/button_close_epic.pngbin0 -> 13850 bytes
-rw-r--r--doc/user/group/epics/img/button_reopen_epic.pngbin0 -> 14153 bytes
-rw-r--r--doc/user/group/epics/img/child_epics_roadmap.pngbin0 -> 30149 bytes
-rw-r--r--doc/user/group/epics/img/containing_epic.pngbin0 -> 159939 bytes
-rw-r--r--doc/user/group/epics/img/epic_view.pngbin0 -> 176759 bytes
-rw-r--r--doc/user/group/epics/img/epics_list_view.pngbin0 -> 96826 bytes
-rw-r--r--doc/user/group/epics/img/epics_search.pngbin0 -> 65963 bytes
-rw-r--r--doc/user/group/epics/img/epics_sort.pngbin0 -> 71177 bytes
-rw-r--r--doc/user/group/epics/index.md233
-rw-r--r--doc/user/group/img/group_file_template_dropdown.pngbin0 -> 9519 bytes
-rw-r--r--doc/user/group/img/group_file_template_settings.pngbin0 -> 6217 bytes
-rw-r--r--doc/user/group/img/member_lock.pngbin0 -> 3168 bytes
-rw-r--r--doc/user/group/img/membership_lock.pngbin4820 -> 0 bytes
-rw-r--r--doc/user/group/img/new_group_form.pngbin32510 -> 0 bytes
-rw-r--r--doc/user/group/index.md295
-rw-r--r--doc/user/group/insights/img/insights_example_stacked_bar_chart.pngbin0 -> 86062 bytes
-rw-r--r--doc/user/group/insights/img/insights_group_configuration.pngbin0 -> 24107 bytes
-rw-r--r--doc/user/group/insights/img/insights_sidebar_link.pngbin0 -> 18826 bytes
-rw-r--r--doc/user/group/insights/index.md58
-rw-r--r--doc/user/group/issues_analytics/img/issues_created_per_month.pngbin0 -> 28508 bytes
-rw-r--r--doc/user/group/issues_analytics/index.md43
-rw-r--r--doc/user/group/roadmap/img/epics_state_dropdown.pngbin0 -> 3702 bytes
-rw-r--r--doc/user/group/roadmap/img/roadmap_timeline_months.pngbin0 -> 7551 bytes
-rw-r--r--doc/user/group/roadmap/img/roadmap_timeline_quarters.pngbin0 -> 7493 bytes
-rw-r--r--doc/user/group/roadmap/img/roadmap_timeline_weeks.pngbin0 -> 8008 bytes
-rw-r--r--doc/user/group/roadmap/img/roadmap_view.pngbin0 -> 49774 bytes
-rw-r--r--doc/user/group/roadmap/index.md87
-rw-r--r--doc/user/group/saml_sso/img/group_saml_configuration_information.pngbin0 -> 50435 bytes
-rw-r--r--doc/user/group/saml_sso/img/group_saml_settings.pngbin0 -> 89399 bytes
-rw-r--r--doc/user/group/saml_sso/img/scim_advanced.pngbin0 -> 21568 bytes
-rw-r--r--doc/user/group/saml_sso/img/scim_attribute_mapping.pngbin0 -> 95420 bytes
-rw-r--r--doc/user/group/saml_sso/img/scim_token.pngbin0 -> 154318 bytes
-rw-r--r--doc/user/group/saml_sso/img/unlink_group_saml.pngbin0 -> 27077 bytes
-rw-r--r--doc/user/group/saml_sso/index.md140
-rw-r--r--doc/user/group/saml_sso/scim_setup.md122
-rw-r--r--doc/user/group/security_dashboard/index.md5
-rw-r--r--doc/user/group/subgroups/index.md57
-rw-r--r--doc/user/img/markdown_inline_diffs_tags_rendered.pngbin0 -> 1804 bytes
-rw-r--r--doc/user/img/mermaid_diagram_render_gfm.pngbin2202 -> 0 bytes
-rw-r--r--doc/user/index.md36
-rw-r--r--doc/user/instance/clusters/index.md23
-rw-r--r--doc/user/instance_statistics/convdev.md2
-rw-r--r--doc/user/markdown.md36
-rw-r--r--doc/user/operations_dashboard/img/index_operations_dashboard_top_bar_icon.pngbin0 -> 3948 bytes
-rw-r--r--doc/user/operations_dashboard/img/index_operations_dashboard_with_projects.pngbin0 -> 30837 bytes
-rw-r--r--doc/user/operations_dashboard/index.md37
-rw-r--r--doc/user/permissions.md272
-rw-r--r--doc/user/profile/account/delete_account.md4
-rw-r--r--doc/user/profile/personal_access_tokens.md17
-rw-r--r--doc/user/profile/preferences.md1
-rw-r--r--doc/user/project/canary_deployments.md71
-rw-r--r--doc/user/project/ci_cd_for_external_repo.md5
-rw-r--r--doc/user/project/clusters/img/k8s_cluster_monitoring.pngbin0 -> 43150 bytes
-rw-r--r--doc/user/project/clusters/img/kubernetes_pod_logs.pngbin0 -> 147319 bytes
-rw-r--r--doc/user/project/clusters/img/pod_logs_deploy_board.pngbin0 -> 13291 bytes
-rw-r--r--doc/user/project/clusters/index.md268
-rw-r--r--doc/user/project/clusters/kubernetes_pod_logs.md21
-rw-r--r--doc/user/project/clusters/runbooks/index.md12
-rw-r--r--doc/user/project/clusters/serverless/index.md17
-rw-r--r--doc/user/project/code_owners.md85
-rw-r--r--doc/user/project/container_registry.md4
-rw-r--r--doc/user/project/cycle_analytics.md18
-rw-r--r--doc/user/project/deploy_boards.md126
-rw-r--r--doc/user/project/deploy_tokens/index.md2
-rw-r--r--doc/user/project/description_templates.md49
-rw-r--r--doc/user/project/file_lock.md101
-rw-r--r--doc/user/project/img/deploy_boards_canary_deployments.pngbin0 -> 17380 bytes
-rw-r--r--doc/user/project/img/deploy_boards_kubernetes_label.pngbin0 -> 43978 bytes
-rw-r--r--doc/user/project/img/deploy_boards_landing_page.pngbin0 -> 16107 bytes
-rw-r--r--doc/user/project/img/description_templates_default_settings.pngbin0 -> 26395 bytes
-rw-r--r--doc/user/project/img/file_lock.pngbin0 -> 26973 bytes
-rw-r--r--doc/user/project/img/file_lock_folders.pngbin0 -> 22900 bytes
-rw-r--r--doc/user/project/img/file_lock_list.pngbin0 -> 18243 bytes
-rw-r--r--doc/user/project/img/file_lock_merge_request_error_message.pngbin0 -> 24573 bytes
-rw-r--r--doc/user/project/img/file_lock_repository_view.pngbin0 -> 22947 bytes
-rw-r--r--doc/user/project/img/issue_board.pngbin284759 -> 0 bytes
-rw-r--r--doc/user/project/img/key_value_labels.pngbin0 -> 6208 bytes
-rw-r--r--doc/user/project/img/labels_epic_sidebar.pngbin0 -> 47869 bytes
-rw-r--r--doc/user/project/img/labels_sidebar_inline.pngbin11083 -> 0 bytes
-rw-r--r--doc/user/project/img/priority_sort_order.pngbin69978 -> 0 bytes
-rw-r--r--doc/user/project/img/protected_branches_choose_branch.pngbin7009 -> 0 bytes
-rw-r--r--doc/user/project/img/protected_branches_error_ui.pngbin13117 -> 0 bytes
-rw-r--r--doc/user/project/img/protected_branches_select_roles_and_users.pngbin0 -> 7155 bytes
-rw-r--r--doc/user/project/img/protected_branches_select_roles_and_users_list.pngbin0 -> 7408 bytes
-rw-r--r--doc/user/project/img/service_desk_confirmation_email.pngbin0 -> 24165 bytes
-rw-r--r--doc/user/project/img/service_desk_disabled.pngbin0 -> 18654 bytes
-rw-r--r--doc/user/project/img/service_desk_enabled.pngbin0 -> 33243 bytes
-rw-r--r--doc/user/project/img/service_desk_issue_tracker.pngbin0 -> 95087 bytes
-rw-r--r--doc/user/project/img/service_desk_nav_item.pngbin0 -> 30323 bytes
-rw-r--r--doc/user/project/img/service_desk_reply.pngbin0 -> 15186 bytes
-rw-r--r--doc/user/project/img/service_desk_thread.pngbin0 -> 60850 bytes
-rw-r--r--doc/user/project/import/gemnasium.md102
-rw-r--r--doc/user/project/import/github.md6
-rw-r--r--doc/user/project/import/gitlab_com.md5
-rw-r--r--doc/user/project/import/img/gemnasium/connect_github.pngbin0 -> 49966 bytes
-rw-r--r--doc/user/project/import/img/gemnasium/create_project.pngbin0 -> 85728 bytes
-rw-r--r--doc/user/project/import/img/gemnasium/edit_gitlab-ci.pngbin0 -> 79052 bytes
-rw-r--r--doc/user/project/import/img/gemnasium/pipeline.pngbin0 -> 40872 bytes
-rw-r--r--doc/user/project/import/img/gemnasium/project_connected.pngbin0 -> 21575 bytes
-rw-r--r--doc/user/project/import/img/gemnasium/report.pngbin0 -> 144883 bytes
-rw-r--r--doc/user/project/import/img/gemnasium/select_project.pngbin0 -> 8927 bytes
-rw-r--r--doc/user/project/import/img/import_projects_from_github_select_auth_method.pngbin17611 -> 0 bytes
-rw-r--r--doc/user/project/import/index.md4
-rw-r--r--doc/user/project/import/phabricator.md29
-rw-r--r--doc/user/project/index.md26
-rw-r--r--doc/user/project/insights/img/insights_example_bar_chart.pngbin0 -> 21767 bytes
-rw-r--r--doc/user/project/insights/img/insights_example_bar_time_series_chart.pngbin0 -> 34068 bytes
-rw-r--r--doc/user/project/insights/img/insights_example_line_chart.pngbin0 -> 120678 bytes
-rw-r--r--doc/user/project/insights/img/insights_example_pie_chart.pngbin0 -> 10889 bytes
-rw-r--r--doc/user/project/insights/img/insights_example_stacked_bar_chart.pngbin0 -> 81587 bytes
-rw-r--r--doc/user/project/insights/img/insights_sidebar_link.pngbin0 -> 21463 bytes
-rw-r--r--doc/user/project/insights/img/project_insights.pngbin0 -> 41210 bytes
-rw-r--r--doc/user/project/insights/index.md303
-rw-r--r--doc/user/project/integrations/custom_issue_tracker.md4
-rw-r--r--doc/user/project/integrations/github.md48
-rw-r--r--doc/user/project/integrations/gitlab_slack_application.md65
-rw-r--r--doc/user/project/integrations/img/github_configuration.pngbin0 -> 12515 bytes
-rw-r--r--doc/user/project/integrations/img/github_status_check_pipeline_update.pngbin0 -> 21075 bytes
-rw-r--r--doc/user/project/integrations/img/gitlab_slack_app_landing_page.pngbin0 -> 32992 bytes
-rw-r--r--doc/user/project/integrations/img/jira_add_user_to_group.pngbin24838 -> 266180 bytes
-rw-r--r--doc/user/project/integrations/img/jira_added_user_to_group.pngbin0 -> 82473 bytes
-rw-r--r--doc/user/project/integrations/img/jira_create_new_group.pngbin19127 -> 262453 bytes
-rw-r--r--doc/user/project/integrations/img/jira_create_new_user.pngbin12625 -> 173516 bytes
-rw-r--r--doc/user/project/integrations/img/jira_group_access.pngbin19147 -> 112706 bytes
-rw-r--r--doc/user/project/integrations/img/jira_project_name.pngbin26680 -> 0 bytes
-rw-r--r--doc/user/project/integrations/img/jira_service.pngbin36976 -> 0 bytes
-rw-r--r--doc/user/project/integrations/img/jira_user_management_link.pngbin23906 -> 206155 bytes
-rw-r--r--doc/user/project/integrations/img/mattermost_configuration.pngbin101151 -> 67672 bytes
-rw-r--r--doc/user/project/integrations/img/prometheus_add_metric.pngbin0 -> 53571 bytes
-rw-r--r--doc/user/project/integrations/img/prometheus_alert.pngbin0 -> 24452 bytes
-rw-r--r--doc/user/project/integrations/img/prometheus_service_alerts.pngbin0 -> 40727 bytes
-rw-r--r--doc/user/project/integrations/img/prometheus_yaml_deploy.pngbin9456 -> 0 bytes
-rw-r--r--doc/user/project/integrations/img/slack_configuration.pngbin92179 -> 64873 bytes
-rw-r--r--doc/user/project/integrations/jira.md6
-rw-r--r--doc/user/project/integrations/jira_server_configuration.md45
-rw-r--r--doc/user/project/integrations/mattermost.md2
-rw-r--r--doc/user/project/integrations/project_services.md8
-rw-r--r--doc/user/project/integrations/prometheus.md81
-rw-r--r--doc/user/project/integrations/prometheus_library/kubernetes.md26
-rw-r--r--doc/user/project/integrations/slack_slash_commands.md13
-rw-r--r--doc/user/project/integrations/webhooks.md50
-rw-r--r--doc/user/project/integrations/youtrack.md4
-rw-r--r--doc/user/project/issue_board.md2
-rw-r--r--doc/user/project/issues/create_new_issue.md20
-rw-r--r--doc/user/project/issues/csv_export.md77
-rw-r--r--doc/user/project/issues/csv_import.md20
-rw-r--r--doc/user/project/issues/img/comment-or-discussion.pngbin0 -> 8378 bytes
-rw-r--r--doc/user/project/issues/img/create_issue_from_group_level_issue_tracker.pngbin0 -> 29358 bytes
-rw-r--r--doc/user/project/issues/img/create_mr_from_issue.pngbin0 -> 21286 bytes
-rw-r--r--doc/user/project/issues/img/csv_export_button.pngbin0 -> 7383 bytes
-rw-r--r--doc/user/project/issues/img/csv_export_modal.pngbin0 -> 16825 bytes
-rw-r--r--doc/user/project/issues/img/group_issues_list_view.pngbin46595 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/issue_template.pngbin25019 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/issues_main_view_numbered.jpgbin205803 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/issues_main_view_numbered.pngbin0 -> 278285 bytes
-rw-r--r--doc/user/project/issues/img/multiple_assignees.gifbin0 -> 877551 bytes
-rw-r--r--doc/user/project/issues/img/multiple_assignees_for_issues.pngbin0 -> 39710 bytes
-rw-r--r--doc/user/project/issues/img/related_issues_add.pngbin0 -> 12900 bytes
-rw-r--r--doc/user/project/issues/img/related_issues_remove.pngbin0 -> 5450 bytes
-rw-r--r--doc/user/project/issues/img/reopen-issue.pngbin0 -> 2522 bytes
-rw-r--r--doc/user/project/issues/img/report-abuse.pngbin0 -> 1620 bytes
-rw-r--r--doc/user/project/issues/img/select_project_from_group_level_issue_tracker.pngbin0 -> 23706 bytes
-rw-r--r--doc/user/project/issues/img/show-all-activity.pngbin0 -> 8119 bytes
-rw-r--r--doc/user/project/issues/index.md12
-rw-r--r--doc/user/project/issues/issue_data_and_actions.md260
-rw-r--r--doc/user/project/issues/moving_issues.md25
-rw-r--r--doc/user/project/issues/multiple_assignees_for_issues.md41
-rw-r--r--doc/user/project/issues/related_issues.md40
-rw-r--r--doc/user/project/labels.md63
-rw-r--r--doc/user/project/maven_packages.md5
-rw-r--r--doc/user/project/members/img/add_new_user_to_project_settings.pngbin11004 -> 0 bytes
-rw-r--r--doc/user/project/members/img/add_user_members_menu.pngbin28988 -> 0 bytes
-rw-r--r--doc/user/project/members/img/max_access_level.pngbin34710 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/allow_collaboration.md16
-rw-r--r--doc/user/project/merge_requests/authorization_for_merge_requests.md18
-rw-r--r--doc/user/project/merge_requests/browser_performance_testing.md70
-rw-r--r--doc/user/project/merge_requests/cherry_pick_changes.md26
-rw-r--r--doc/user/project/merge_requests/code_quality.md94
-rw-r--r--doc/user/project/merge_requests/code_quality_diff.md6
-rw-r--r--doc/user/project/merge_requests/container_scanning.md5
-rw-r--r--doc/user/project/merge_requests/dast.md5
-rw-r--r--doc/user/project/merge_requests/dependency_scanning.md5
-rw-r--r--doc/user/project/merge_requests/fast_forward_merge.md35
-rw-r--r--doc/user/project/merge_requests/img/approvals_can_override.pngbin0 -> 7634 bytes
-rw-r--r--doc/user/project/merge_requests/img/approvals_premium_mr_widget.pngbin0 -> 76524 bytes
-rw-r--r--doc/user/project/merge_requests/img/approvals_premium_project_edit.pngbin0 -> 47371 bytes
-rw-r--r--doc/user/project/merge_requests/img/approvals_remove_on_push.pngbin0 -> 6551 bytes
-rw-r--r--doc/user/project/merge_requests/img/approvals_starter_project_edit.pngbin0 -> 52442 bytes
-rw-r--r--doc/user/project/merge_requests/img/approvals_starter_project_empty.pngbin0 -> 50820 bytes
-rw-r--r--doc/user/project/merge_requests/img/approve.pngbin0 -> 19329 bytes
-rw-r--r--doc/user/project/merge_requests/img/approve_additionally.pngbin0 -> 22700 bytes
-rw-r--r--doc/user/project/merge_requests/img/browser_performance_testing.pngbin0 -> 52100 bytes
-rw-r--r--doc/user/project/merge_requests/img/code_quality.gifbin0 -> 2617453 bytes
-rw-r--r--doc/user/project/merge_requests/img/filter_approver_merge_requests.pngbin0 -> 90764 bytes
-rw-r--r--doc/user/project/merge_requests/img/multiple_assignees_for_merge_requests_sidebar.pngbin0 -> 20867 bytes
-rw-r--r--doc/user/project/merge_requests/img/remove_approval.pngbin0 -> 21902 bytes
-rw-r--r--doc/user/project/merge_requests/img/revert_changes_commit.pngbin95647 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/revert_changes_mr.pngbin104954 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/index.md141
-rw-r--r--doc/user/project/merge_requests/license_management.md5
-rw-r--r--doc/user/project/merge_requests/merge_request_approvals.md344
-rw-r--r--doc/user/project/merge_requests/merge_when_pipeline_succeeds.md23
-rw-r--r--doc/user/project/merge_requests/resolve_conflicts.md16
-rw-r--r--doc/user/project/merge_requests/revert_changes.md29
-rw-r--r--doc/user/project/merge_requests/sast.md5
-rw-r--r--doc/user/project/merge_requests/sast_docker.md5
-rw-r--r--doc/user/project/merge_requests/squash_and_merge.md45
-rw-r--r--doc/user/project/merge_requests/versions.md34
-rw-r--r--doc/user/project/merge_requests/work_in_progress_merge_requests.md24
-rw-r--r--doc/user/project/milestones/burndown_charts.md70
-rw-r--r--doc/user/project/milestones/img/burndown_chart.pngbin0 -> 48403 bytes
-rw-r--r--doc/user/project/milestones/index.md39
-rw-r--r--doc/user/project/new_ci_build_permissions_model.md13
-rw-r--r--doc/user/project/operations/feature_flags.md177
-rw-r--r--doc/user/project/operations/img/external_dashboard_link.pngbin0 -> 63282 bytes
-rw-r--r--doc/user/project/operations/img/external_dashboard_settings.pngbin0 -> 103474 bytes
-rw-r--r--doc/user/project/operations/img/feature_flags_list.pngbin0 -> 14963 bytes
-rw-r--r--doc/user/project/operations/img/specs_list.pngbin0 -> 43574 bytes
-rw-r--r--doc/user/project/operations/index.md5
-rw-r--r--doc/user/project/operations/linking_to_an_external_dashboard.md19
-rw-r--r--doc/user/project/operations/tracing.md34
-rw-r--r--doc/user/project/packages/img/maven_package_view.pngbin0 -> 16105 bytes
-rw-r--r--doc/user/project/packages/img/npm_package_view.pngbin0 -> 24443 bytes
-rw-r--r--doc/user/project/packages/maven.md5
-rw-r--r--doc/user/project/packages/maven_packages.md5
-rw-r--r--doc/user/project/packages/maven_repository.md341
-rw-r--r--doc/user/project/packages/npm_registry.md120
-rw-r--r--doc/user/project/pages/getting_started_part_four.md10
-rw-r--r--doc/user/project/pages/getting_started_part_one.md3
-rw-r--r--doc/user/project/pages/getting_started_part_three.md10
-rw-r--r--doc/user/project/pages/getting_started_part_two.md27
-rw-r--r--doc/user/project/pages/img/pages_create_project.pngbin6062 -> 0 bytes
-rw-r--r--doc/user/project/pages/img/pages_create_user_page.pngbin14435 -> 0 bytes
-rw-r--r--doc/user/project/pages/img/pages_dns_details.pngbin5350 -> 0 bytes
-rw-r--r--doc/user/project/pages/img/pages_multiple_domains.pngbin12930 -> 0 bytes
-rw-r--r--doc/user/project/pages/img/pages_new_domain_button.pngbin8763 -> 0 bytes
-rw-r--r--doc/user/project/pages/img/pages_upload_cert.pngbin22888 -> 0 bytes
-rw-r--r--doc/user/project/pages/index.md5
-rw-r--r--doc/user/project/pages/introduction.md193
-rw-r--r--doc/user/project/pages/lets_encrypt_for_gitlab_pages.md6
-rw-r--r--doc/user/project/pipelines/img/pipeline_schedule_variables.pngbin5360 -> 17292 bytes
-rw-r--r--doc/user/project/pipelines/img/pipeline_schedules_new_form.pngbin23290 -> 62141 bytes
-rw-r--r--doc/user/project/pipelines/job_artifacts.md19
-rw-r--r--doc/user/project/pipelines/schedules.md2
-rw-r--r--doc/user/project/pipelines/settings.md16
-rw-r--r--doc/user/project/protected_branches.md24
-rw-r--r--doc/user/project/quick_actions.md13
-rw-r--r--doc/user/project/repository/gpg_signed_commits/index.md2
-rw-r--r--doc/user/project/repository/img/download_source_code.pngbin0 -> 61467 bytes
-rw-r--r--doc/user/project/repository/index.md49
-rw-r--r--doc/user/project/repository/reducing_the_repo_size_using_git.md15
-rw-r--r--doc/user/project/security_dashboard.md5
-rw-r--r--doc/user/project/service_desk.md124
-rw-r--r--doc/user/project/settings/img/import_export_download_export.pngbin24397 -> 25905 bytes
-rw-r--r--doc/user/project/settings/img/import_export_export_button.pngbin24118 -> 25102 bytes
-rw-r--r--doc/user/project/settings/img/import_export_mail_link.pngbin13496 -> 7561 bytes
-rw-r--r--doc/user/project/settings/img/import_export_new_project.pngbin13082 -> 13202 bytes
-rw-r--r--doc/user/project/settings/img/import_export_select_file.pngbin13514 -> 20580 bytes
-rw-r--r--doc/user/project/settings/img/settings_edit_button.pngbin6897 -> 0 bytes
-rw-r--r--doc/user/project/settings/import_export.md28
-rw-r--r--doc/user/project/settings/index.md22
-rw-r--r--doc/user/project/web_ide/img/enable_web_ide.pngbin11364 -> 0 bytes
-rw-r--r--doc/user/project/web_ide/index.md157
-rw-r--r--doc/user/project/wiki/index.md10
-rw-r--r--doc/user/search/advanced_global_search.md75
-rw-r--r--doc/user/search/advanced_search_syntax.md69
-rw-r--r--doc/user/search/img/advanced_global_search.pngbin0 -> 15017 bytes
-rw-r--r--doc/user/search/img/issues_any_assignee.pngbin90455 -> 0 bytes
-rw-r--r--doc/user/search/img/issues_author.pngbin55217 -> 0 bytes
-rw-r--r--doc/user/search/img/multiple_assignees.pngbin0 -> 18897 bytes
-rw-r--r--doc/user/search/index.md21
-rw-r--r--doc/workflow/README.md6
-rw-r--r--doc/workflow/award_emoji.pngbin5268 -> 0 bytes
-rw-r--r--doc/workflow/ff_merge.md5
-rw-r--r--doc/workflow/git_annex.md238
-rw-r--r--doc/workflow/git_lfs.md5
-rw-r--r--doc/workflow/gitlab_flow.md4
-rw-r--r--doc/workflow/img/copy_ssh_public_key_button.pngbin0 -> 11225 bytes
-rw-r--r--doc/workflow/img/new_branch_from_issue.pngbin33584 -> 0 bytes
-rw-r--r--doc/workflow/img/notification_global_settings.pngbin37542 -> 118914 bytes
-rw-r--r--doc/workflow/img/repository_mirroring_pull_settings_upper.pngbin64118 -> 50084 bytes
-rw-r--r--doc/workflow/issue_weight.md22
-rw-r--r--doc/workflow/issue_weight/issue.pngbin0 -> 69564 bytes
-rw-r--r--doc/workflow/lfs/images/git-annex-branches.pngbin0 -> 32164 bytes
-rw-r--r--doc/workflow/lfs/manage_large_binaries_with_git_lfs.md5
-rw-r--r--doc/workflow/lfs/migrate_from_git_annex_to_git_lfs.md255
-rw-r--r--doc/workflow/merge_request_approvals.md5
-rw-r--r--doc/workflow/notifications.md35
-rw-r--r--doc/workflow/rebase_before_merge.md5
-rw-r--r--doc/workflow/repository_mirroring.md14
-rw-r--r--doc/workflow/share_with_group.pngbin50450 -> 0 bytes
-rw-r--r--doc/workflow/shortcuts.md10
-rw-r--r--doc/workflow/timezone.md26
-rw-r--r--doc/workflow/todos.md19
-rw-r--r--fixtures/emojis/index.json2
-rw-r--r--haml_lint/inline_javascript.rb25
-rw-r--r--haml_lint/linter/no_plain_nodes.rb84
-rw-r--r--jest.config.js5
-rw-r--r--lib/api/api.rb4
-rw-r--r--lib/api/branches.rb4
-rw-r--r--lib/api/circuit_breakers.rb39
-rw-r--r--lib/api/commits.rb10
-rw-r--r--lib/api/discussions.rb8
-rw-r--r--lib/api/entities.rb64
-rw-r--r--lib/api/events.rb49
-rw-r--r--lib/api/group_variables.rb2
-rw-r--r--lib/api/groups.rb35
-rw-r--r--lib/api/helpers.rb6
-rw-r--r--lib/api/helpers/events_helpers.rb31
-rw-r--r--lib/api/helpers/groups_helpers.rb33
-rw-r--r--lib/api/helpers/internal_helpers.rb2
-rw-r--r--lib/api/helpers/issues_helpers.rb41
-rw-r--r--lib/api/helpers/members_helpers.rb19
-rw-r--r--lib/api/helpers/pagination.rb2
-rw-r--r--lib/api/helpers/projects_helpers.rb76
-rw-r--r--lib/api/helpers/protected_branches_helpers.rb13
-rw-r--r--lib/api/helpers/related_resources_helpers.rb4
-rw-r--r--lib/api/helpers/services_helpers.rb6
-rw-r--r--lib/api/helpers/settings_helpers.rb19
-rw-r--r--lib/api/helpers/users_helpers.rb16
-rw-r--r--lib/api/helpers/variables_helpers.rb13
-rw-r--r--lib/api/internal.rb6
-rw-r--r--lib/api/issues.rb127
-rw-r--r--lib/api/merge_requests.rb11
-rw-r--r--lib/api/namespaces.rb2
-rw-r--r--lib/api/pipeline_schedules.rb2
-rw-r--r--lib/api/project_clusters.rb1
-rw-r--r--lib/api/project_events.rb29
-rw-r--r--lib/api/project_import.rb3
-rw-r--r--lib/api/projects.rb23
-rw-r--r--lib/api/protected_branches.rb26
-rw-r--r--lib/api/releases.rb16
-rw-r--r--lib/api/runner.rb5
-rw-r--r--lib/api/search.rb3
-rw-r--r--lib/api/settings.rb46
-rw-r--r--lib/api/users.rb12
-rw-r--r--lib/api/validations/check_assignees_count.rb32
-rw-r--r--lib/api/variables.rb18
-rw-r--r--lib/api/wikis.rb3
-rw-r--r--lib/banzai/color_parser.rb20
-rw-r--r--lib/banzai/commit_renderer.rb2
-rw-r--r--lib/banzai/filter/abstract_reference_filter.rb8
-rw-r--r--lib/banzai/filter/autolink_filter.rb2
-rw-r--r--lib/banzai/filter/front_matter_filter.rb2
-rw-r--r--lib/banzai/filter/label_reference_filter.rb14
-rw-r--r--lib/banzai/filter/milestone_reference_filter.rb4
-rw-r--r--lib/banzai/filter/spaced_link_filter.rb2
-rw-r--r--lib/banzai/filter/table_of_contents_filter.rb3
-rw-r--r--lib/banzai/filter/wiki_link_filter/rewriter.rb8
-rw-r--r--lib/banzai/pipeline/gfm_pipeline.rb2
-rw-r--r--lib/banzai/redactor.rb7
-rw-r--r--lib/bitbucket_server/representation/repo.rb2
-rw-r--r--lib/declarative_policy/preferred_scope.rb1
-rw-r--r--lib/gitlab.rb15
-rw-r--r--lib/gitlab/action_view_output/context.rb41
-rw-r--r--lib/gitlab/asciidoc.rb54
-rw-r--r--lib/gitlab/asciidoc/html5_converter.rb32
-rw-r--r--lib/gitlab/asciidoc/include_processor.rb126
-rw-r--r--lib/gitlab/auth/o_auth/auth_hash.rb2
-rw-r--r--lib/gitlab/auth/result.rb1
-rw-r--r--lib/gitlab/auth_logger.rb9
-rw-r--r--lib/gitlab/background_migration/calculate_wiki_sizes.rb18
-rw-r--r--lib/gitlab/background_migration/fill_valid_time_for_pages_domain_certificate.rb40
-rw-r--r--lib/gitlab/background_migration/fix_cross_project_label_links.rb2
-rw-r--r--lib/gitlab/background_migration/populate_untracked_uploads_dependencies.rb4
-rw-r--r--lib/gitlab/background_migration/prepare_untracked_uploads.rb2
-rw-r--r--lib/gitlab/background_migration/reset_merge_status.rb17
-rw-r--r--lib/gitlab/bitbucket_import/importer.rb2
-rw-r--r--lib/gitlab/bitbucket_server_import/importer.rb1
-rw-r--r--lib/gitlab/checks/branch_check.rb6
-rw-r--r--lib/gitlab/checks/lfs_check.rb1
-rw-r--r--lib/gitlab/ci/build/artifacts/metadata.rb4
-rw-r--r--lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb5
-rw-r--r--lib/gitlab/ci/config/entry/image.rb2
-rw-r--r--lib/gitlab/ci/config/entry/job.rb2
-rw-r--r--lib/gitlab/ci/config/entry/service.rb3
-rw-r--r--lib/gitlab/ci/config/extendable/entry.rb59
-rw-r--r--lib/gitlab/ci/pipeline/chain/command.rb1
-rw-r--r--lib/gitlab/ci/pipeline/chain/limit/activity.rb4
-rw-r--r--lib/gitlab/ci/pipeline/chain/limit/size.rb4
-rw-r--r--lib/gitlab/ci/pipeline/chain/skip.rb2
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/and.rb27
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/base.rb6
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/equals.rb9
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/matches.rb25
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/not_equals.rb27
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/not_matches.rb30
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/operator.rb20
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/or.rb27
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/pattern.rb13
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexer.rb23
-rw-r--r--lib/gitlab/ci/pipeline/expression/parser.rb70
-rw-r--r--lib/gitlab/ci/pipeline/expression/statement.rb15
-rw-r--r--lib/gitlab/ci/status/stage/factory.rb3
-rw-r--r--lib/gitlab/ci/status/stage/play_manual.rb43
-rw-r--r--lib/gitlab/ci/templates/.yamllint5
-rw-r--r--lib/gitlab/ci/templates/Android-Fastlane.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/Android.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml8
-rw-r--r--lib/gitlab/ci/templates/C++.gitlab-ci.yml8
-rw-r--r--lib/gitlab/ci/templates/Chef.gitlab-ci.yml34
-rw-r--r--lib/gitlab/ci/templates/Clojure.gitlab-ci.yml8
-rw-r--r--lib/gitlab/ci/templates/Crystal.gitlab-ci.yml6
-rw-r--r--lib/gitlab/ci/templates/Django.gitlab-ci.yml8
-rw-r--r--lib/gitlab/ci/templates/Docker.gitlab-ci.yml21
-rw-r--r--lib/gitlab/ci/templates/Elixir.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Go.gitlab-ci.yml28
-rw-r--r--lib/gitlab/ci/templates/Grails.gitlab-ci.yml36
-rw-r--r--lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml29
-rw-r--r--lib/gitlab/ci/templates/Julia.gitlab-ci.yml15
-rw-r--r--lib/gitlab/ci/templates/Laravel.gitlab-ci.yml20
-rw-r--r--lib/gitlab/ci/templates/Maven.gitlab-ci.yml74
-rw-r--r--lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml10
-rw-r--r--lib/gitlab/ci/templates/OpenShift.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/PHP.gitlab-ci.yml24
-rw-r--r--lib/gitlab/ci/templates/Pages/Brunch.gitlab-ci.yml10
-rw-r--r--lib/gitlab/ci/templates/Pages/Doxygen.gitlab-ci.yml10
-rw-r--r--lib/gitlab/ci/templates/Pages/Gatsby.gitlab-ci.yml10
-rw-r--r--lib/gitlab/ci/templates/Pages/HTML.gitlab-ci.yml10
-rw-r--r--lib/gitlab/ci/templates/Pages/Harp.gitlab-ci.yml10
-rw-r--r--lib/gitlab/ci/templates/Pages/Hexo.gitlab-ci.yml10
-rw-r--r--lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml10
-rw-r--r--lib/gitlab/ci/templates/Pages/Hyde.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/Pages/JBake.gitlab-ci.yml26
-rw-r--r--lib/gitlab/ci/templates/Pages/Jekyll.gitlab-ci.yml15
-rw-r--r--lib/gitlab/ci/templates/Pages/Jigsaw.gitlab-ci.yml12
-rw-r--r--lib/gitlab/ci/templates/Pages/Lektor.gitlab-ci.yml8
-rw-r--r--lib/gitlab/ci/templates/Pages/Metalsmith.gitlab-ci.yml12
-rw-r--r--lib/gitlab/ci/templates/Pages/Middleman.gitlab-ci.yml22
-rw-r--r--lib/gitlab/ci/templates/Pages/Nanoc.gitlab-ci.yml8
-rw-r--r--lib/gitlab/ci/templates/Pages/Octopress.gitlab-ci.yml14
-rw-r--r--lib/gitlab/ci/templates/Pages/Pelican.gitlab-ci.yml6
-rw-r--r--lib/gitlab/ci/templates/Python.gitlab-ci.yml28
-rw-r--r--lib/gitlab/ci/templates/Ruby.gitlab-ci.yml16
-rw-r--r--lib/gitlab/ci/templates/Rust.gitlab-ci.yml18
-rw-r--r--lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml55
-rw-r--r--lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml27
-rw-r--r--lib/gitlab/ci/templates/Security/License-Management.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml43
-rw-r--r--lib/gitlab/ci/templates/Serverless.gitlab-ci.yml18
-rw-r--r--lib/gitlab/ci/templates/Swift.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/dotNET-Core.yml117
-rw-r--r--lib/gitlab/ci/templates/dotNET.gitlab-ci.yml27
-rw-r--r--lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml8
-rw-r--r--lib/gitlab/ci/trace.rb14
-rw-r--r--lib/gitlab/ci/variables/collection/item.rb6
-rw-r--r--lib/gitlab/cluster/lifecycle_events.rb8
-rw-r--r--lib/gitlab/cluster/puma_worker_killer_initializer.rb3
-rw-r--r--lib/gitlab/cluster/puma_worker_killer_observer.rb24
-rw-r--r--lib/gitlab/cluster/rack_timeout_observer.rb51
-rw-r--r--lib/gitlab/config/entry/validators.rb6
-rw-r--r--lib/gitlab/content_disposition.rb4
-rw-r--r--lib/gitlab/danger/helper.rb50
-rw-r--r--lib/gitlab/danger/roulette.rb82
-rw-r--r--lib/gitlab/danger/teammate.rb29
-rw-r--r--lib/gitlab/data_builder/deployment.rb25
-rw-r--r--lib/gitlab/data_builder/note.rb1
-rw-r--r--lib/gitlab/data_builder/pipeline.rb2
-rw-r--r--lib/gitlab/data_builder/push.rb12
-rw-r--r--lib/gitlab/database/migration_helpers.rb6
-rw-r--r--lib/gitlab/diff/suggestion.rb2
-rw-r--r--lib/gitlab/diff/suggestions_parser.rb6
-rw-r--r--lib/gitlab/discussions_diff/highlight_cache.rb13
-rw-r--r--lib/gitlab/file_detector.rb1
-rw-r--r--lib/gitlab/git/object_pool.rb4
-rw-r--r--lib/gitlab/git/pre_receive_error.rb2
-rw-r--r--lib/gitlab/git/repository.rb103
-rw-r--r--lib/gitlab/git/repository_cleaner.rb4
-rw-r--r--lib/gitlab/git/rugged_impl/commit.rb20
-rw-r--r--lib/gitlab/git/rugged_impl/repository.rb2
-rw-r--r--lib/gitlab/git/rugged_impl/tree.rb2
-rw-r--r--lib/gitlab/git/wiki.rb24
-rw-r--r--lib/gitlab/git_access.rb6
-rw-r--r--lib/gitlab/git_ref_validator.rb23
-rw-r--r--lib/gitlab/gitaly_client.rb30
-rw-r--r--lib/gitlab/gitaly_client/blob_service.rb4
-rw-r--r--lib/gitlab/gitaly_client/cleanup_service.rb33
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb4
-rw-r--r--lib/gitlab/gitaly_client/conflicts_service.rb6
-rw-r--r--lib/gitlab/gitaly_client/object_pool_service.rb9
-rw-r--r--lib/gitlab/gitaly_client/operation_service.rb60
-rw-r--r--lib/gitlab/gitaly_client/ref_service.rb6
-rw-r--r--lib/gitlab/gitaly_client/repository_service.rb15
-rw-r--r--lib/gitlab/gitaly_client/wiki_service.rb23
-rw-r--r--lib/gitlab/github_import/importer/issue_importer.rb1
-rw-r--r--lib/gitlab/github_import/importer/pull_request_importer.rb1
-rw-r--r--lib/gitlab/github_import/parallel_importer.rb18
-rw-r--r--lib/gitlab/github_import/representation/diff_note.rb2
-rw-r--r--lib/gitlab/github_import/representation/note.rb2
-rw-r--r--lib/gitlab/gl_repository.rb12
-rw-r--r--lib/gitlab/gl_repository/repo_type.rb2
-rw-r--r--lib/gitlab/gon_helper.rb7
-rw-r--r--lib/gitlab/grape_logging/loggers/correlation_id_logger.rb2
-rw-r--r--lib/gitlab/graphql/authorize.rb2
-rw-r--r--lib/gitlab/graphql/authorize/authorize_field_service.rb90
-rw-r--r--lib/gitlab/graphql/connections/keyset_connection.rb16
-rw-r--r--lib/gitlab/graphql/errors.rb1
-rw-r--r--lib/gitlab/graphql/generic_tracing.rb59
-rw-r--r--lib/gitlab/graphql/loaders/batch_lfs_oid_loader.rb25
-rw-r--r--lib/gitlab/graphql/loaders/batch_model_loader.rb2
-rw-r--r--lib/gitlab/graphql/loaders/batch_project_statistics_loader.rb23
-rw-r--r--lib/gitlab/graphql/query_analyzers/log_query_complexity.rb18
-rw-r--r--lib/gitlab/graphql/query_analyzers/logger_analyzer.rb71
-rw-r--r--lib/gitlab/graphql/representation/tree_entry.rb31
-rw-r--r--lib/gitlab/graphql/tracing.rb43
-rw-r--r--lib/gitlab/graphql_logger.rb9
-rw-r--r--lib/gitlab/group_search_results.rb6
-rw-r--r--lib/gitlab/health_checks/metric.rb1
-rw-r--r--lib/gitlab/health_checks/result.rb1
-rw-r--r--lib/gitlab/hook_data/issue_builder.rb3
-rw-r--r--lib/gitlab/http.rb9
-rw-r--r--lib/gitlab/http_connection_adapter.rb44
-rw-r--r--lib/gitlab/import/set_async_jid.rb27
-rw-r--r--lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb5
-rw-r--r--lib/gitlab/import_export/attribute_cleaner.rb7
-rw-r--r--lib/gitlab/import_export/import_export.yml6
-rw-r--r--lib/gitlab/import_export/members_mapper.rb6
-rw-r--r--lib/gitlab/import_export/project_tree_restorer.rb2
-rw-r--r--lib/gitlab/import_export/relation_factory.rb6
-rw-r--r--lib/gitlab/import_sources.rb3
-rw-r--r--lib/gitlab/json_logger.rb2
-rw-r--r--lib/gitlab/kubernetes/errors.rb23
-rw-r--r--lib/gitlab/kubernetes/helm/api.rb8
-rw-r--r--lib/gitlab/legacy_github_import/importer.rb7
-rw-r--r--lib/gitlab/lets_encrypt/challenge.rb17
-rw-r--r--lib/gitlab/lets_encrypt/client.rb95
-rw-r--r--lib/gitlab/lets_encrypt/order.rb32
-rw-r--r--lib/gitlab/lfs_token.rb42
-rw-r--r--lib/gitlab/markdown_cache.rb12
-rw-r--r--lib/gitlab/markdown_cache/active_record/extension.rb49
-rw-r--r--lib/gitlab/markdown_cache/field_data.rb35
-rw-r--r--lib/gitlab/markdown_cache/redis/extension.rb63
-rw-r--r--lib/gitlab/markdown_cache/redis/store.rb56
-rw-r--r--lib/gitlab/metrics/dashboard/base_service.rb63
-rw-r--r--lib/gitlab/metrics/dashboard/cache.rb44
-rw-r--r--lib/gitlab/metrics/dashboard/finder.rb53
-rw-r--r--lib/gitlab/metrics/dashboard/processor.rb48
-rw-r--r--lib/gitlab/metrics/dashboard/project_dashboard_service.rb39
-rw-r--r--lib/gitlab/metrics/dashboard/stages/base_stage.rb59
-rw-r--r--lib/gitlab/metrics/dashboard/stages/common_metrics_inserter.rb23
-rw-r--r--lib/gitlab/metrics/dashboard/stages/endpoint_inserter.rb42
-rw-r--r--lib/gitlab/metrics/dashboard/stages/project_metrics_inserter.rb106
-rw-r--r--lib/gitlab/metrics/dashboard/stages/sorter.rb34
-rw-r--r--lib/gitlab/metrics/dashboard/system_dashboard_service.rb47
-rw-r--r--lib/gitlab/metrics/metric.rb2
-rw-r--r--lib/gitlab/metrics/samplers/puma_sampler.rb93
-rw-r--r--lib/gitlab/metrics/samplers/ruby_sampler.rb33
-rw-r--r--lib/gitlab/metrics/samplers/unicorn_sampler.rb36
-rw-r--r--lib/gitlab/metrics/system.rb28
-rw-r--r--lib/gitlab/middleware/correlation_id.rb2
-rw-r--r--lib/gitlab/middleware/read_only.rb2
-rw-r--r--lib/gitlab/middleware/release_env.rb1
-rw-r--r--lib/gitlab/namespaced_session_store.rb22
-rw-r--r--lib/gitlab/omniauth_initializer.rb15
-rw-r--r--lib/gitlab/performance_bar/peek_query_tracker.rb13
-rw-r--r--lib/gitlab/phabricator_import.rb12
-rw-r--r--lib/gitlab/phabricator_import/base_worker.rb80
-rw-r--r--lib/gitlab/phabricator_import/cache/map.rb65
-rw-r--r--lib/gitlab/phabricator_import/conduit.rb9
-rw-r--r--lib/gitlab/phabricator_import/conduit/client.rb41
-rw-r--r--lib/gitlab/phabricator_import/conduit/maniphest.rb28
-rw-r--r--lib/gitlab/phabricator_import/conduit/pagination.rb24
-rw-r--r--lib/gitlab/phabricator_import/conduit/response.rb60
-rw-r--r--lib/gitlab/phabricator_import/conduit/tasks_response.rb24
-rw-r--r--lib/gitlab/phabricator_import/import_tasks_worker.rb10
-rw-r--r--lib/gitlab/phabricator_import/importer.rb44
-rw-r--r--lib/gitlab/phabricator_import/issues/importer.rb42
-rw-r--r--lib/gitlab/phabricator_import/issues/task_importer.rb54
-rw-r--r--lib/gitlab/phabricator_import/project_creator.rb78
-rw-r--r--lib/gitlab/phabricator_import/representation/task.rb60
-rw-r--r--lib/gitlab/phabricator_import/worker_state.rb47
-rw-r--r--lib/gitlab/profiler.rb6
-rw-r--r--lib/gitlab/project_search_results.rb10
-rw-r--r--lib/gitlab/prometheus/query_variables.rb5
-rw-r--r--lib/gitlab/proxy_http_connection_adapter.rb36
-rw-r--r--lib/gitlab/push_options.rb2
-rw-r--r--lib/gitlab/quick_actions/issue_and_merge_request_actions.rb2
-rw-r--r--lib/gitlab/quick_actions/spend_time_and_date_separator.rb2
-rw-r--r--lib/gitlab/routing.rb2
-rw-r--r--lib/gitlab/sanitizers/svg.rb2
-rw-r--r--lib/gitlab/search_results.rb114
-rw-r--r--lib/gitlab/sentry.rb15
-rw-r--r--lib/gitlab/session.rb27
-rw-r--r--lib/gitlab/setup_helper.rb7
-rw-r--r--lib/gitlab/sherlock/middleware.rb4
-rw-r--r--lib/gitlab/sherlock/query.rb2
-rw-r--r--lib/gitlab/sidekiq_config.rb4
-rw-r--r--lib/gitlab/sidekiq_middleware/correlation_injector.rb4
-rw-r--r--lib/gitlab/sidekiq_middleware/correlation_logger.rb4
-rw-r--r--lib/gitlab/slash_commands/result.rb1
-rw-r--r--lib/gitlab/sql/pattern.rb2
-rw-r--r--lib/gitlab/tracing/common.rb69
-rw-r--r--lib/gitlab/tracing/factory.rb61
-rw-r--r--lib/gitlab/tracing/grpc_interceptor.rb54
-rw-r--r--lib/gitlab/tracing/jaeger_factory.rb97
-rw-r--r--lib/gitlab/tracing/rack_middleware.rb46
-rw-r--r--lib/gitlab/tracing/rails/action_view_subscriber.rb75
-rw-r--r--lib/gitlab/tracing/rails/active_record_subscriber.rb49
-rw-r--r--lib/gitlab/tracing/rails/rails_common.rb24
-rw-r--r--lib/gitlab/tracing/sidekiq/client_middleware.rb26
-rw-r--r--lib/gitlab/tracing/sidekiq/server_middleware.rb26
-rw-r--r--lib/gitlab/tracing/sidekiq/sidekiq_common.rb22
-rw-r--r--lib/gitlab/url_blocker.rb75
-rw-r--r--lib/gitlab/url_builder.rb4
-rw-r--r--lib/gitlab/url_sanitizer.rb4
-rw-r--r--lib/gitlab/usage_data.rb11
-rw-r--r--lib/gitlab/user_extractor.rb2
-rw-r--r--lib/gitlab/workhorse.rb65
-rw-r--r--lib/haml_lint/inline_javascript.rb26
-rw-r--r--lib/mattermost/session.rb2
-rw-r--r--lib/peek/views/tracing.rb6
-rw-r--r--lib/quality/kubernetes_client.rb2
-rw-r--r--lib/quality/seeders/issues.rb58
-rw-r--r--lib/quality/test_level.rb75
-rwxr-xr-xlib/support/init.d/gitlab37
-rw-r--r--lib/support/init.d/gitlab.default.example3
-rw-r--r--lib/system_check/app/git_version_check.rb2
-rw-r--r--lib/system_check/app/ruby_version_check.rb2
-rw-r--r--lib/system_check/base_check.rb2
-rw-r--r--lib/tasks/gemojione.rake2
-rw-r--r--lib/tasks/gettext.rake1
-rw-r--r--lib/tasks/gitlab/assets.rake6
-rw-r--r--lib/tasks/gitlab/backup.rake8
-rw-r--r--lib/tasks/gitlab/features.rake2
-rw-r--r--lib/tasks/gitlab/seed.rake34
-rw-r--r--lib/tasks/gitlab/shell.rake12
-rw-r--r--lib/tasks/haml-lint.rake2
-rw-r--r--lib/tasks/lint.rake35
-rw-r--r--lib/tasks/spec.rake44
-rw-r--r--locale/ar_SA/gitlab.po3258
-rw-r--r--locale/bg/gitlab.po3226
-rw-r--r--locale/bn_BD/gitlab.po3222
-rw-r--r--locale/bn_IN/gitlab.po3222
-rw-r--r--locale/ca_ES/gitlab.po3224
-rw-r--r--locale/cs_CZ/gitlab.po3240
-rw-r--r--locale/cy_GB/gitlab.po3258
-rw-r--r--locale/da_DK/gitlab.po3222
-rw-r--r--locale/de/gitlab.po3794
-rw-r--r--locale/el_GR/gitlab.po3222
-rw-r--r--locale/eo/gitlab.po3226
-rw-r--r--locale/es/gitlab.po6732
-rw-r--r--locale/et_EE/gitlab.po3222
-rw-r--r--locale/fil_PH/gitlab.po3222
-rw-r--r--locale/fr/gitlab.po3304
-rw-r--r--locale/gitlab.pot1631
-rw-r--r--locale/gl_ES/gitlab.po3222
-rw-r--r--locale/he_IL/gitlab.po3240
-rw-r--r--locale/hi_IN/gitlab.po3222
-rw-r--r--locale/hr_HR/gitlab.po3231
-rw-r--r--locale/hu_HU/gitlab.po3222
-rw-r--r--locale/id_ID/gitlab.po3213
-rw-r--r--locale/it/gitlab.po3376
-rw-r--r--locale/ja/gitlab.po4027
-rw-r--r--locale/ka_GE/gitlab.po3222
-rw-r--r--locale/ko/gitlab.po3263
-rw-r--r--locale/mn_MN/gitlab.po3222
-rw-r--r--locale/nb_NO/gitlab.po3222
-rw-r--r--locale/nl_NL/gitlab.po3244
-rw-r--r--locale/pa_IN/gitlab.po3222
-rw-r--r--locale/pl_PL/gitlab.po3244
-rw-r--r--locale/pt_BR/gitlab.po3734
-rw-r--r--locale/pt_PT/gitlab.po4248
-rw-r--r--locale/ro_RO/gitlab.po3231
-rw-r--r--locale/ru/gitlab.po3356
-rw-r--r--locale/sk_SK/gitlab.po3240
-rw-r--r--locale/sq_AL/gitlab.po3222
-rw-r--r--locale/sr_CS/gitlab.po3231
-rw-r--r--locale/sr_SP/gitlab.po3231
-rw-r--r--locale/sv_SE/gitlab.po3222
-rw-r--r--locale/sw_KE/gitlab.po3222
-rw-r--r--locale/tr_TR/gitlab.po4114
-rw-r--r--locale/uk/gitlab.po4030
-rw-r--r--locale/zh_CN/gitlab.po4739
-rw-r--r--locale/zh_HK/gitlab.po3997
-rw-r--r--locale/zh_TW/gitlab.po3573
-rw-r--r--package.json36
-rw-r--r--qa/Dockerfile2
-rw-r--r--qa/Gemfile3
-rw-r--r--qa/Gemfile.lock7
-rw-r--r--qa/README.md10
-rw-r--r--qa/STYLE_GUIDE.md46
-rw-r--r--qa/knapsack/gitlab-ce/review-qa-all_master_report.json42
-rw-r--r--qa/qa.rb4
-rw-r--r--qa/qa/ce/strategy.rb5
-rw-r--r--qa/qa/fixtures/auto_devops_rack/Dockerfile9
-rw-r--r--qa/qa/git/repository.rb2
-rw-r--r--qa/qa/page/README.md134
-rw-r--r--qa/qa/page/admin/menu.rb9
-rw-r--r--qa/qa/page/admin/settings/component/performance_bar.rb27
-rw-r--r--qa/qa/page/admin/settings/metrics_and_profiling.rb23
-rw-r--r--qa/qa/page/base.rb34
-rw-r--r--qa/qa/page/component/note.rb2
-rw-r--r--qa/qa/page/element.rb25
-rw-r--r--qa/qa/page/file/form.rb2
-rw-r--r--qa/qa/page/layout/performance_bar.rb35
-rw-r--r--qa/qa/page/main/login.rb16
-rw-r--r--qa/qa/page/main/menu.rb8
-rw-r--r--qa/qa/page/project/branches/show.rb18
-rw-r--r--qa/qa/page/project/issue/show.rb49
-rw-r--r--qa/qa/page/project/new.rb5
-rw-r--r--qa/qa/page/project/operations/kubernetes/show.rb4
-rw-r--r--qa/qa/page/project/settings/ci_cd.rb1
-rw-r--r--qa/qa/page/project/settings/ci_variables.rb24
-rw-r--r--qa/qa/page/project/web_ide/edit.rb27
-rw-r--r--qa/qa/page/validatable.rb22
-rw-r--r--qa/qa/page/view.rb4
-rw-r--r--qa/qa/resource/README.md392
-rw-r--r--qa/qa/resource/base.rb64
-rw-r--r--qa/qa/resource/ci_variable.rb32
-rw-r--r--qa/qa/resource/file.rb31
-rw-r--r--qa/qa/resource/issue.rb17
-rw-r--r--qa/qa/resource/label.rb21
-rw-r--r--qa/qa/resource/project.rb8
-rw-r--r--qa/qa/resource/repository/project_push.rb2
-rw-r--r--qa/qa/runtime/api/client.rb9
-rw-r--r--qa/qa/runtime/browser.rb7
-rw-r--r--qa/qa/runtime/env.rb4
-rw-r--r--qa/qa/runtime/key/ecdsa.rb1
-rw-r--r--qa/qa/runtime/key/ed25519.rb1
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb3
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb14
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb3
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb3
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb9
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb7
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb3
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb12
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb9
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb26
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb11
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb10
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_ci_variable_spec.rb15
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb1
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb34
-rw-r--r--qa/qa/specs/helpers/quarantine.rb16
-rw-r--r--qa/qa/specs/runner.rb19
-rw-r--r--qa/qa/support/page/logging.rb44
-rw-r--r--qa/qa/support/waiter.rb4
-rw-r--r--qa/qa/vendor/github/page/login.rb4
-rw-r--r--qa/spec/git/repository_spec.rb9
-rw-r--r--qa/spec/page/element_spec.rb56
-rw-r--r--qa/spec/page/logging_spec.rb25
-rw-r--r--qa/spec/runtime/env_spec.rb24
-rw-r--r--qa/spec/spec_helper.rb13
-rw-r--r--rubocop/cop/code_reuse/active_record.rb3
-rw-r--r--rubocop/cop/gitlab/finder_with_find_by.rb4
-rw-r--r--rubocop/cop/include_action_view_context.rb31
-rw-r--r--rubocop/cop/qa/element_with_pattern.rb20
-rw-r--r--rubocop/qa_helpers.rb2
-rw-r--r--rubocop/rubocop.rb2
-rw-r--r--rubocop/spec_helpers.rb6
-rwxr-xr-xscripts/clean-old-cached-assets4
-rw-r--r--scripts/frontend/stylelint/stylelint-utility-map.js2
-rwxr-xr-xscripts/frontend/test.js114
-rwxr-xr-xscripts/lint-doc.sh2
-rw-r--r--scripts/prepare_build.sh11
-rwxr-xr-xscripts/review_apps/review-apps.sh108
-rw-r--r--scripts/utils.sh136
-rw-r--r--security.txt6
-rw-r--r--spec/controllers/acme_challenges_controller_spec.rb44
-rw-r--r--spec/controllers/admin/clusters/applications_controller_spec.rb149
-rw-r--r--spec/controllers/admin/clusters_controller_spec.rb540
-rw-r--r--spec/controllers/application_controller_spec.rb57
-rw-r--r--spec/controllers/concerns/boards_responses_spec.rb23
-rw-r--r--spec/controllers/concerns/enforces_admin_authentication_spec.rb40
-rw-r--r--spec/controllers/concerns/import_url_params_spec.rb56
-rw-r--r--spec/controllers/concerns/issuable_collections_spec.rb110
-rw-r--r--spec/controllers/concerns/project_unauthorized_spec.rb2
-rw-r--r--spec/controllers/concerns/routable_actions_spec.rb156
-rw-r--r--spec/controllers/concerns/send_file_upload_spec.rb3
-rw-r--r--spec/controllers/groups/clusters_controller_spec.rb27
-rw-r--r--spec/controllers/groups_controller_spec.rb22
-rw-r--r--spec/controllers/import/fogbugz_controller_spec.rb38
-rw-r--r--spec/controllers/import/phabricator_controller_spec.rb92
-rw-r--r--spec/controllers/omniauth_callbacks_controller_spec.rb6
-rw-r--r--spec/controllers/projects/avatars_controller_spec.rb2
-rw-r--r--spec/controllers/projects/ci/lints_controller_spec.rb4
-rw-r--r--spec/controllers/projects/clusters/applications_controller_spec.rb62
-rw-r--r--spec/controllers/projects/clusters_controller_spec.rb35
-rw-r--r--spec/controllers/projects/compare_controller_spec.rb2
-rw-r--r--spec/controllers/projects/environments/prometheus_api_controller_spec.rb4
-rw-r--r--spec/controllers/projects/environments_controller_spec.rb156
-rw-r--r--spec/controllers/projects/graphs_controller_spec.rb15
-rw-r--r--spec/controllers/projects/imports_controller_spec.rb15
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb31
-rw-r--r--spec/controllers/projects/jobs_controller_spec.rb93
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb44
-rw-r--r--spec/controllers/projects/milestones_controller_spec.rb34
-rw-r--r--spec/controllers/projects/pipeline_schedules_controller_spec.rb3
-rw-r--r--spec/controllers/projects/raw_controller_spec.rb2
-rw-r--r--spec/controllers/projects/serverless/functions_controller_spec.rb92
-rw-r--r--spec/controllers/projects/settings/ci_cd_controller_spec.rb26
-rw-r--r--spec/controllers/projects/settings/operations_controller_spec.rb224
-rw-r--r--spec/controllers/projects/stages_controller_spec.rb72
-rw-r--r--spec/controllers/projects/wikis_controller_spec.rb22
-rw-r--r--spec/controllers/projects_controller_spec.rb12
-rw-r--r--spec/controllers/registrations_controller_spec.rb19
-rw-r--r--spec/controllers/search_controller_spec.rb24
-rw-r--r--spec/controllers/sent_notifications_controller_spec.rb109
-rw-r--r--spec/controllers/sessions_controller_spec.rb34
-rw-r--r--spec/db/importers/common_metrics_importer_spec.rb44
-rw-r--r--spec/factories/ci/builds.rb11
-rw-r--r--spec/factories/ci/job_artifacts.rb18
-rw-r--r--spec/factories/ci/pipeline_schedule.rb10
-rw-r--r--spec/factories/ci/pipeline_schedule_variables.rb1
-rw-r--r--spec/factories/clusters/applications/helm.rb19
-rw-r--r--spec/factories/clusters/clusters.rb2
-rw-r--r--spec/factories/deployments.rb2
-rw-r--r--spec/factories/merge_requests.rb9
-rw-r--r--spec/factories/pages_domain_acme_orders.rb17
-rw-r--r--spec/factories/pages_domains.rb4
-rw-r--r--spec/factories/pool_repositories.rb1
-rw-r--r--spec/factories/project_auto_devops.rb1
-rw-r--r--spec/factories/project_metrics_settings.rb8
-rw-r--r--spec/factories/projects.rb1
-rw-r--r--spec/factories/uploads.rb2
-rw-r--r--spec/features/admin/admin_appearance_spec.rb2
-rw-r--r--spec/features/admin/admin_browses_logs_spec.rb1
-rw-r--r--spec/features/admin/admin_sees_project_statistics_spec.rb29
-rw-r--r--spec/features/admin/admin_sees_projects_statistics_spec.rb20
-rw-r--r--spec/features/admin/admin_settings_spec.rb59
-rw-r--r--spec/features/admin/admin_users_spec.rb7
-rw-r--r--spec/features/atom/dashboard_issues_spec.rb2
-rw-r--r--spec/features/boards/sidebar_spec.rb8
-rw-r--r--spec/features/clusters/cluster_detail_page_spec.rb3
-rw-r--r--spec/features/commits_spec.rb12
-rw-r--r--spec/features/contextual_sidebar_spec.rb37
-rw-r--r--spec/features/dashboard/groups_list_spec.rb4
-rw-r--r--spec/features/dashboard/projects_spec.rb14
-rw-r--r--spec/features/dashboard/todos/todos_spec.rb20
-rw-r--r--spec/features/dashboard/user_filters_projects_spec.rb189
-rw-r--r--spec/features/global_search_spec.rb14
-rw-r--r--spec/features/groups/clusters/user_spec.rb1
-rw-r--r--spec/features/groups/members/leave_group_spec.rb26
-rw-r--r--spec/features/groups/merge_requests_spec.rb2
-rw-r--r--spec/features/ics/dashboard_issues_spec.rb2
-rw-r--r--spec/features/ics/group_issues_spec.rb2
-rw-r--r--spec/features/ics/project_issues_spec.rb2
-rw-r--r--spec/features/instance_statistics/conversational_development_index_spec.rb2
-rw-r--r--spec/features/issuables/issuable_list_spec.rb2
-rw-r--r--spec/features/issuables/sorting_list_spec.rb28
-rw-r--r--spec/features/issues/filtered_search/dropdown_hint_spec.rb34
-rw-r--r--spec/features/issues_spec.rb16
-rw-r--r--spec/features/markdown/gitlab_flavored_markdown_spec.rb3
-rw-r--r--spec/features/merge_request/user_accepts_merge_request_spec.rb3
-rw-r--r--spec/features/merge_request/user_creates_image_diff_notes_spec.rb116
-rw-r--r--spec/features/merge_request/user_creates_merge_request_spec.rb2
-rw-r--r--spec/features/merge_request/user_merges_merge_request_spec.rb2
-rw-r--r--spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb25
-rw-r--r--spec/features/merge_request/user_sees_diff_spec.rb3
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb47
-rw-r--r--spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb6
-rw-r--r--spec/features/merge_request/user_suggests_changes_on_diff_spec.rb26
-rw-r--r--spec/features/merge_requests/user_lists_merge_requests_spec.rb2
-rw-r--r--spec/features/oauth_login_spec.rb2
-rw-r--r--spec/features/profiles/user_edit_preferences_spec.rb32
-rw-r--r--spec/features/profiles/user_edit_profile_spec.rb32
-rw-r--r--spec/features/project_variables_spec.rb2
-rw-r--r--spec/features/projects/branches/download_buttons_spec.rb2
-rw-r--r--spec/features/projects/clusters/user_spec.rb1
-rw-r--r--spec/features/projects/clusters_spec.rb2
-rw-r--r--spec/features/projects/commits/user_browses_commits_spec.rb4
-rw-r--r--spec/features/projects/features_visibility_spec.rb3
-rw-r--r--spec/features/projects/files/download_buttons_spec.rb2
-rw-r--r--spec/features/projects/files/files_sort_submodules_with_folders_spec.rb2
-rw-r--r--spec/features/projects/files/project_owner_creates_license_file_spec.rb1
-rw-r--r--spec/features/projects/files/undo_template_spec.rb2
-rw-r--r--spec/features/projects/files/user_browses_files_spec.rb1
-rw-r--r--spec/features/projects/files/user_browses_lfs_files_spec.rb2
-rw-r--r--spec/features/projects/files/user_creates_directory_spec.rb2
-rw-r--r--spec/features/projects/files/user_creates_files_spec.rb2
-rw-r--r--spec/features/projects/files/user_deletes_files_spec.rb2
-rw-r--r--spec/features/projects/files/user_edits_files_spec.rb1
-rw-r--r--spec/features/projects/files/user_replaces_files_spec.rb2
-rw-r--r--spec/features/projects/files/user_uploads_files_spec.rb2
-rw-r--r--spec/features/projects/import_export/export_file_spec.rb2
-rw-r--r--spec/features/projects/import_export/import_file_spec.rb1
-rw-r--r--spec/features/projects/jobs/permissions_spec.rb2
-rw-r--r--spec/features/projects/jobs/user_browses_job_spec.rb4
-rw-r--r--spec/features/projects/jobs/user_browses_jobs_spec.rb6
-rw-r--r--spec/features/projects/jobs_spec.rb12
-rw-r--r--spec/features/projects/labels/update_prioritization_spec.rb20
-rw-r--r--spec/features/projects/labels/user_promotes_label_spec.rb34
-rw-r--r--spec/features/projects/labels/user_removes_labels_spec.rb7
-rw-r--r--spec/features/projects/labels/user_views_labels_spec.rb5
-rw-r--r--spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb9
-rw-r--r--spec/features/projects/members/member_leaves_project_spec.rb13
-rw-r--r--spec/features/projects/new_project_spec.rb30
-rw-r--r--spec/features/projects/pages_lets_encrypt_spec.rb131
-rw-r--r--spec/features/projects/pages_spec.rb36
-rw-r--r--spec/features/projects/pipeline_schedules_spec.rb2
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb62
-rw-r--r--spec/features/projects/serverless/functions_spec.rb59
-rw-r--r--spec/features/projects/settings/forked_project_settings_spec.rb1
-rw-r--r--spec/features/projects/settings/integration_settings_spec.rb2
-rw-r--r--spec/features/projects/settings/operations_settings_spec.rb6
-rw-r--r--spec/features/projects/settings/repository_settings_spec.rb31
-rw-r--r--spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb25
-rw-r--r--spec/features/projects/show/download_buttons_spec.rb3
-rw-r--r--spec/features/projects/show/user_manages_notifications_spec.rb10
-rw-r--r--spec/features/projects/show/user_sees_collaboration_links_spec.rb1
-rw-r--r--spec/features/projects/tags/download_buttons_spec.rb2
-rw-r--r--spec/features/projects/tree/tree_show_spec.rb1
-rw-r--r--spec/features/projects/tree/upload_file_spec.rb2
-rw-r--r--spec/features/projects/wiki/user_creates_wiki_page_spec.rb4
-rw-r--r--spec/features/projects_spec.rb4
-rw-r--r--spec/features/protected_branches_spec.rb26
-rw-r--r--spec/features/protected_tags_spec.rb13
-rw-r--r--spec/features/search/user_searches_for_commits_spec.rb2
-rw-r--r--spec/features/search/user_searches_for_wiki_pages_spec.rb36
-rw-r--r--spec/features/security/profile_access_spec.rb2
-rw-r--r--spec/features/tags/master_creates_tag_spec.rb2
-rw-r--r--spec/features/users/login_spec.rb16
-rw-r--r--spec/features/users/signup_spec.rb44
-rw-r--r--spec/finders/autocomplete/users_finder_spec.rb16
-rw-r--r--spec/finders/cluster_ancestors_finder_spec.rb29
-rw-r--r--spec/finders/clusters/knative_services_finder_spec.rb105
-rw-r--r--spec/finders/issues_finder_spec.rb16
-rw-r--r--spec/finders/members_finder_spec.rb44
-rw-r--r--spec/finders/merge_requests_finder_spec.rb2
-rw-r--r--spec/finders/projects/serverless/functions_finder_spec.rb68
-rw-r--r--spec/fixtures/api/schemas/cluster_status.json3
-rw-r--r--spec/fixtures/api/schemas/entities/issue.json2
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request_basic.json2
-rw-r--r--spec/fixtures/api/schemas/entities/test_case.json1
-rw-r--r--spec/fixtures/api/schemas/environment.json6
-rw-r--r--spec/fixtures/api/schemas/pipeline_schedule.json2
-rw-r--r--spec/fixtures/api/schemas/pipeline_schedule_variable.json10
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/job.json1
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/label_basic.json24
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/release.json35
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/release/release_for_guest.json22
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/release/releases_for_guest.json4
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/release/tag_release.json12
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/releases.json4
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/tag.json2
-rw-r--r--spec/fixtures/lib/gitlab/metrics/dashboard/sample_dashboard.yml36
-rw-r--r--spec/fixtures/lib/gitlab/metrics/dashboard/schemas/dashboard.json13
-rw-r--r--spec/fixtures/lib/gitlab/metrics/dashboard/schemas/metrics.json22
-rw-r--r--spec/fixtures/lib/gitlab/metrics/dashboard/schemas/panel_groups.json17
-rw-r--r--spec/fixtures/lib/gitlab/metrics/dashboard/schemas/panels.json20
-rw-r--r--spec/fixtures/phabricator_responses/auth_failed.json1
-rw-r--r--spec/fixtures/phabricator_responses/maniphest.search.json98
-rw-r--r--spec/fixtures/security-reports/dependency_list/gl-dependency-scanning-report.json422
-rw-r--r--spec/fixtures/security-reports/master/gl-dast-report.json74
-rw-r--r--spec/frontend/activities_spec.js70
-rw-r--r--spec/frontend/api_spec.js477
-rw-r--r--spec/frontend/autosave_spec.js151
-rw-r--r--spec/frontend/boards/modal_store_spec.js4
-rw-r--r--spec/frontend/boards/stores/actions_spec.js67
-rw-r--r--spec/frontend/boards/stores/mutations_spec.js91
-rw-r--r--spec/frontend/boards/stores/state_spec.js11
-rw-r--r--spec/frontend/clusters/clusters_bundle_spec.js155
-rw-r--r--spec/frontend/clusters/components/application_row_spec.js321
-rw-r--r--spec/frontend/clusters/components/applications_spec.js99
-rw-r--r--spec/frontend/clusters/components/knative_domain_editor_spec.js141
-rw-r--r--spec/frontend/clusters/components/uninstall_application_button_spec.js32
-rw-r--r--spec/frontend/clusters/components/uninstall_application_confirmation_modal_spec.js56
-rw-r--r--spec/frontend/clusters/services/application_state_machine_spec.js162
-rw-r--r--spec/frontend/clusters/services/mock_data.js8
-rw-r--r--spec/frontend/clusters/stores/clusters_store_spec.js79
-rw-r--r--spec/frontend/environment.js17
-rw-r--r--spec/frontend/gfm_auto_complete_spec.js58
-rw-r--r--spec/frontend/helpers/fixtures.js4
-rw-r--r--spec/frontend/helpers/jest_helpers.js24
-rw-r--r--spec/frontend/helpers/jquery.js6
-rw-r--r--spec/frontend/helpers/local_storage_helper.js41
-rw-r--r--spec/frontend/helpers/text_helper.js (renamed from spec/frontend/helpers/vue_component_helper.js)0
-rw-r--r--spec/frontend/helpers/timeout.js55
-rw-r--r--spec/frontend/helpers/vue_test_utils_helper.js4
-rw-r--r--spec/frontend/ide/components/ide_status_list_spec.js91
-rw-r--r--spec/frontend/ide/stores/modules/commit/mutations_spec.js15
-rw-r--r--spec/frontend/ide/stores/modules/file_templates/mutations_spec.js41
-rw-r--r--spec/frontend/ide/stores/mutations/branch_spec.js35
-rw-r--r--spec/frontend/ide/stores/mutations/project_spec.js23
-rw-r--r--spec/frontend/import_projects/components/import_projects_table_spec.js185
-rw-r--r--spec/frontend/import_projects/components/imported_project_table_row_spec.js58
-rw-r--r--spec/frontend/import_projects/components/provider_repo_table_row_spec.js104
-rw-r--r--spec/frontend/import_projects/store/actions_spec.js284
-rw-r--r--spec/frontend/jobs/store/mutations_spec.js38
-rw-r--r--spec/frontend/lib/utils/datetime_utility_spec.js436
-rw-r--r--spec/frontend/lib/utils/number_utility_spec.js11
-rw-r--r--spec/frontend/lib/utils/text_utility_spec.js4
-rw-r--r--spec/frontend/lib/utils/url_utility_spec.js226
-rw-r--r--spec/frontend/mr_popover/__snapshots__/mr_popover_spec.js.snap2
-rw-r--r--spec/frontend/mr_popover/index_spec.js20
-rw-r--r--spec/frontend/notes/components/discussion_actions_spec.js104
-rw-r--r--spec/frontend/notes/components/discussion_notes_spec.js139
-rw-r--r--spec/frontend/notes/components/note_app_spec.js322
-rw-r--r--spec/frontend/notes/old_notes_spec.js1045
-rw-r--r--spec/frontend/notes/stores/utils_spec.js17
-rw-r--r--spec/frontend/operation_settings/components/external_dashboard_spec.js166
-rw-r--r--spec/frontend/operation_settings/store/mutations_spec.js19
-rw-r--r--spec/frontend/reports/components/report_item_spec.js33
-rw-r--r--spec/frontend/reports/components/report_section_spec.js40
-rw-r--r--spec/frontend/repository/components/breadcrumbs_spec.js44
-rw-r--r--spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap38
-rw-r--r--spec/frontend/repository/components/table/index_spec.js80
-rw-r--r--spec/frontend/repository/components/table/parent_row_spec.js64
-rw-r--r--spec/frontend/repository/components/table/row_spec.js143
-rw-r--r--spec/frontend/repository/router_spec.js23
-rw-r--r--spec/frontend/repository/utils/icon_spec.js23
-rw-r--r--spec/frontend/repository/utils/title_spec.js15
-rw-r--r--spec/frontend/serverless/components/environment_row_spec.js8
-rw-r--r--spec/frontend/serverless/components/function_row_spec.js29
-rw-r--r--spec/frontend/serverless/components/functions_spec.js36
-rw-r--r--spec/frontend/serverless/components/missing_prometheus_spec.js15
-rw-r--r--spec/frontend/serverless/components/url_spec.js8
-rw-r--r--spec/frontend/serverless/mock_data.js110
-rw-r--r--spec/frontend/serverless/store/getters_spec.js2
-rw-r--r--spec/frontend/serverless/store/mutations_spec.js4
-rw-r--r--spec/frontend/test_setup.js11
-rw-r--r--spec/frontend/vue_mr_widget/stores/get_state_key_spec.js8
-rw-r--r--spec/frontend/vue_shared/components/issue/issue_assignees_spec.js114
-rw-r--r--spec/frontend/vue_shared/components/issue/issue_milestone_spec.js172
-rw-r--r--spec/frontend/vue_shared/components/issue/issue_warning_spec.js65
-rw-r--r--spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js198
-rw-r--r--spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js103
-rw-r--r--spec/frontend/vue_shared/components/modal_copy_button_spec.js40
-rw-r--r--spec/frontend/vue_shared/components/notes/placeholder_note_spec.js51
-rw-r--r--spec/frontend/vue_shared/components/notes/placeholder_system_note_spec.js27
-rw-r--r--spec/frontend/vue_shared/components/notes/system_note_spec.js66
-rw-r--r--spec/frontend/vue_shared/components/pagination_links_spec.js66
-rw-r--r--spec/frontend/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js36
-rw-r--r--spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js86
-rw-r--r--spec/frontend/vue_shared/components/sidebar/date_picker_spec.js121
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/base_spec.js134
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js97
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js107
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js75
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js40
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js42
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js43
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js97
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js139
-rw-r--r--spec/frontend/vue_shared/components/sidebar/toggle_sidebar_spec.js32
-rw-r--r--spec/frontend/vue_shared/droplab_dropdown_button_spec.js136
-rw-r--r--spec/graphql/features/authorization_spec.rb77
-rw-r--r--spec/graphql/gitlab_schema_spec.rb140
-rw-r--r--spec/graphql/resolvers/base_resolver_spec.rb17
-rw-r--r--spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb8
-rw-r--r--spec/graphql/resolvers/group_resolver_spec.rb32
-rw-r--r--spec/graphql/resolvers/issues_resolver_spec.rb160
-rw-r--r--spec/graphql/resolvers/namespace_projects_resolver_spec.rb69
-rw-r--r--spec/graphql/resolvers/project_resolver_spec.rb8
-rw-r--r--spec/graphql/resolvers/tree_resolver_spec.rb35
-rw-r--r--spec/graphql/types/base_field_spec.rb37
-rw-r--r--spec/graphql/types/group_type_spec.rb11
-rw-r--r--spec/graphql/types/issue_type_spec.rb6
-rw-r--r--spec/graphql/types/namespace_type_spec.rb9
-rw-r--r--spec/graphql/types/project_statistics_type_spec.rb11
-rw-r--r--spec/graphql/types/project_type_spec.rb4
-rw-r--r--spec/graphql/types/query_type_spec.rb12
-rw-r--r--spec/graphql/types/repository_type_spec.rb11
-rw-r--r--spec/graphql/types/tree/blob_type_spec.rb9
-rw-r--r--spec/graphql/types/tree/submodule_type_spec.rb9
-rw-r--r--spec/graphql/types/tree/tree_entry_type_spec.rb9
-rw-r--r--spec/graphql/types/tree/tree_type_spec.rb9
-rw-r--r--spec/graphql/types/tree/type_enum_spec.rb11
-rw-r--r--spec/haml_lint/linter/no_plain_nodes_spec.rb56
-rw-r--r--spec/helpers/dashboard_helper_spec.rb6
-rw-r--r--spec/helpers/emails_helper_spec.rb39
-rw-r--r--spec/helpers/environments_helper_spec.rb49
-rw-r--r--spec/helpers/gitlab_routing_helper_spec.rb2
-rw-r--r--spec/helpers/groups/group_members_helper_spec.rb17
-rw-r--r--spec/helpers/labels_helper_spec.rb65
-rw-r--r--spec/helpers/markup_helper_spec.rb3
-rw-r--r--spec/helpers/nav_helper_spec.rb12
-rw-r--r--spec/helpers/page_layout_helper_spec.rb8
-rw-r--r--spec/helpers/projects_helper_spec.rb46
-rw-r--r--spec/helpers/search_helper_spec.rb12
-rw-r--r--spec/helpers/storage_helper_spec.rb25
-rw-r--r--spec/helpers/tracking_helper_spec.rb11
-rw-r--r--spec/helpers/visibility_level_helper_spec.rb45
-rw-r--r--spec/initializers/secret_token_spec.rb4
-rw-r--r--spec/javascripts/activities_spec.js71
-rw-r--r--spec/javascripts/api_spec.js465
-rw-r--r--spec/javascripts/autosave_spec.js154
-rw-r--r--spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js4
-rw-r--r--spec/javascripts/blob/pdf/index_spec.js4
-rw-r--r--spec/javascripts/boards/board_card_spec.js4
-rw-r--r--spec/javascripts/boards/board_list_common_spec.js58
-rw-r--r--spec/javascripts/boards/board_list_spec.js51
-rw-r--r--spec/javascripts/boards/boards_store_spec.js91
-rw-r--r--spec/javascripts/boards/issue_card_spec.js10
-rw-r--r--spec/javascripts/boards/issue_spec.js4
-rw-r--r--spec/javascripts/boards/list_spec.js7
-rw-r--r--spec/javascripts/boards/mock_data.js9
-rw-r--r--spec/javascripts/ci_variable_list/ajax_variable_list_spec.js10
-rw-r--r--spec/javascripts/ci_variable_list/ci_variable_list_spec.js59
-rw-r--r--spec/javascripts/diffs/components/commit_item_spec.js8
-rw-r--r--spec/javascripts/diffs/components/diff_content_spec.js14
-rw-r--r--spec/javascripts/diffs/components/diff_discussions_spec.js111
-rw-r--r--spec/javascripts/diffs/mock_data/diff_file.js1
-rw-r--r--spec/javascripts/diffs/store/actions_spec.js133
-rw-r--r--spec/javascripts/diffs/store/mutations_spec.js94
-rw-r--r--spec/javascripts/dirty_submit/dirty_submit_form_spec.js111
-rw-r--r--spec/javascripts/environments/folder/environments_folder_view_spec.js2
-rw-r--r--spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js4
-rw-r--r--spec/javascripts/filtered_search/visual_token_value_spec.js4
-rw-r--r--spec/javascripts/fixtures/.gitignore2
-rw-r--r--spec/javascripts/fixtures/abuse_reports.rb3
-rw-r--r--spec/javascripts/fixtures/admin_users.rb3
-rw-r--r--spec/javascripts/fixtures/application_settings.rb3
-rw-r--r--spec/javascripts/fixtures/autocomplete_sources.rb3
-rw-r--r--spec/javascripts/fixtures/balsamiq.rb18
-rw-r--r--spec/javascripts/fixtures/blob.rb3
-rw-r--r--spec/javascripts/fixtures/boards.rb3
-rw-r--r--spec/javascripts/fixtures/branches.rb3
-rw-r--r--spec/javascripts/fixtures/clusters.rb3
-rw-r--r--spec/javascripts/fixtures/commit.rb3
-rw-r--r--spec/javascripts/fixtures/deploy_keys.rb3
-rw-r--r--spec/javascripts/fixtures/groups.rb6
-rw-r--r--spec/javascripts/fixtures/issues.rb25
-rw-r--r--spec/javascripts/fixtures/jobs.rb6
-rw-r--r--spec/javascripts/fixtures/labels.rb6
-rw-r--r--spec/javascripts/fixtures/merge_requests.rb43
-rw-r--r--spec/javascripts/fixtures/merge_requests_diffs.rb15
-rw-r--r--spec/javascripts/fixtures/pdf.rb18
-rw-r--r--spec/javascripts/fixtures/pipeline_schedules.rb6
-rw-r--r--spec/javascripts/fixtures/pipelines.rb3
-rw-r--r--spec/javascripts/fixtures/projects.rb15
-rw-r--r--spec/javascripts/fixtures/prometheus_service.rb3
-rw-r--r--spec/javascripts/fixtures/raw.rb27
-rw-r--r--spec/javascripts/fixtures/search.rb3
-rw-r--r--spec/javascripts/fixtures/services.rb3
-rw-r--r--spec/javascripts/fixtures/sessions.rb3
-rw-r--r--spec/javascripts/fixtures/snippet.rb3
-rw-r--r--spec/javascripts/fixtures/static/images/green_box.png (renamed from spec/javascripts/fixtures/images/green_box.png)bin1306 -> 1306 bytes
-rw-r--r--spec/javascripts/fixtures/static/images/one_white_pixel.png (renamed from spec/javascripts/fixtures/one_white_pixel.png)bin68 -> 68 bytes
-rw-r--r--spec/javascripts/fixtures/static/images/red_box.png (renamed from spec/javascripts/fixtures/images/red_box.png)bin1305 -> 1305 bytes
-rw-r--r--spec/javascripts/fixtures/static/projects.json (renamed from spec/javascripts/fixtures/projects.json)0
-rw-r--r--spec/javascripts/fixtures/todos.rb6
-rw-r--r--spec/javascripts/fixtures/u2f.rb6
-rw-r--r--spec/javascripts/fly_out_nav_spec.js5
-rw-r--r--spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js2
-rw-r--r--spec/javascripts/gl_dropdown_spec.js4
-rw-r--r--spec/javascripts/helpers/text_helper.js (renamed from spec/javascripts/helpers/vue_component_helper.js)0
-rw-r--r--spec/javascripts/helpers/vue_test_utils_helper.js4
-rw-r--r--spec/javascripts/ide/components/commit_sidebar/actions_spec.js43
-rw-r--r--spec/javascripts/ide/components/commit_sidebar/list_collapsed_spec.js2
-rw-r--r--spec/javascripts/ide/components/commit_sidebar/new_merge_request_option_spec.js73
-rw-r--r--spec/javascripts/ide/components/ide_review_spec.js2
-rw-r--r--spec/javascripts/ide/components/ide_spec.js92
-rw-r--r--spec/javascripts/ide/components/ide_tree_list_spec.js59
-rw-r--r--spec/javascripts/ide/components/nav_dropdown_button_spec.js2
-rw-r--r--spec/javascripts/ide/components/new_dropdown/upload_spec.js4
-rw-r--r--spec/javascripts/ide/mock_data.js1
-rw-r--r--spec/javascripts/ide/stores/actions/file_spec.js35
-rw-r--r--spec/javascripts/ide/stores/actions/project_spec.js203
-rw-r--r--spec/javascripts/ide/stores/actions/tree_spec.js32
-rw-r--r--spec/javascripts/ide/stores/actions_spec.js69
-rw-r--r--spec/javascripts/ide/stores/getters_spec.js32
-rw-r--r--spec/javascripts/ide/stores/modules/commit/actions_spec.js221
-rw-r--r--spec/javascripts/ide/stores/modules/commit/getters_spec.js29
-rw-r--r--spec/javascripts/ide/stores/modules/file_templates/actions_spec.js54
-rw-r--r--spec/javascripts/ide/stores/utils_spec.js19
-rw-r--r--spec/javascripts/import_projects/components/import_projects_table_spec.js188
-rw-r--r--spec/javascripts/import_projects/components/imported_project_table_row_spec.js51
-rw-r--r--spec/javascripts/import_projects/components/provider_repo_table_row_spec.js96
-rw-r--r--spec/javascripts/import_projects/store/actions_spec.js284
-rw-r--r--spec/javascripts/issue_spec.js1
-rw-r--r--spec/javascripts/jobs/components/artifacts_block_spec.js2
-rw-r--r--spec/javascripts/jobs/components/job_app_spec.js5
-rw-r--r--spec/javascripts/jobs/components/sidebar_spec.js16
-rw-r--r--spec/javascripts/jobs/components/stages_dropdown_spec.js23
-rw-r--r--spec/javascripts/jobs/mock_data.js296
-rw-r--r--spec/javascripts/jobs/store/actions_spec.js105
-rw-r--r--spec/javascripts/lib/utils/common_utils_spec.js16
-rw-r--r--spec/javascripts/lib/utils/datetime_utility_spec.js416
-rw-r--r--spec/javascripts/lib/utils/url_utility_spec.js110
-rw-r--r--spec/javascripts/matchers.js2
-rw-r--r--spec/javascripts/merge_request_spec.js2
-rw-r--r--spec/javascripts/monitoring/charts/area_spec.js28
-rw-r--r--spec/javascripts/monitoring/charts/single_stat_spec.js28
-rw-r--r--spec/javascripts/monitoring/dashboard_spec.js228
-rw-r--r--spec/javascripts/monitoring/helpers.js8
-rw-r--r--spec/javascripts/monitoring/mock_data.js5936
-rw-r--r--spec/javascripts/monitoring/monitoring_store_spec.js35
-rw-r--r--spec/javascripts/monitoring/store/actions_spec.js322
-rw-r--r--spec/javascripts/monitoring/store/mutations_spec.js159
-rw-r--r--spec/javascripts/notes/components/note_actions_spec.js3
-rw-r--r--spec/javascripts/notes/components/note_app_spec.js331
-rw-r--r--spec/javascripts/notes/components/noteable_discussion_spec.js23
-rw-r--r--spec/javascripts/notes/stores/actions_spec.js175
-rw-r--r--spec/javascripts/notes_spec.js1048
-rw-r--r--spec/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js77
-rw-r--r--spec/javascripts/pdf/index_spec.js8
-rw-r--r--spec/javascripts/pdf/page_spec.js8
-rw-r--r--spec/javascripts/performance_bar/components/detailed_metric_spec.js22
-rw-r--r--spec/javascripts/pipelines/graph/action_component_spec.js11
-rw-r--r--spec/javascripts/pipelines/graph/stage_column_component_spec.js49
-rw-r--r--spec/javascripts/pipelines/mock_data.js1
-rw-r--r--spec/javascripts/pipelines/pipeline_triggerer_spec.js54
-rw-r--r--spec/javascripts/pipelines/pipeline_url_spec.js53
-rw-r--r--spec/javascripts/pipelines/pipelines_table_row_spec.js4
-rw-r--r--spec/javascripts/projects/project_new_spec.js14
-rw-r--r--spec/javascripts/raven/index_spec.js10
-rw-r--r--spec/javascripts/raven/raven_config_spec.js10
-rw-r--r--spec/javascripts/reports/components/modal_spec.js2
-rw-r--r--spec/javascripts/reports/components/test_issue_body_spec.js2
-rw-r--r--spec/javascripts/sidebar/assignees_spec.js10
-rw-r--r--spec/javascripts/test_bundle.js2
-rw-r--r--spec/javascripts/test_constants.js10
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_alert_message_spec.js50
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js4
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js43
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js230
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js77
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js178
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js2
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js2
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js148
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js2
-rw-r--r--spec/javascripts/vue_mr_widget/mock_data.js49
-rw-r--r--spec/javascripts/vue_mr_widget/mr_widget_options_spec.js42
-rw-r--r--spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js42
-rw-r--r--spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js3
-rw-r--r--spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js16
-rw-r--r--spec/javascripts/vue_shared/components/issue/issue_assignees_spec.js114
-rw-r--r--spec/javascripts/vue_shared/components/issue/issue_milestone_spec.js234
-rw-r--r--spec/javascripts/vue_shared/components/issue/issue_warning_spec.js55
-rw-r--r--spec/javascripts/vue_shared/components/issue/related_issuable_item_spec.js194
-rw-r--r--spec/javascripts/vue_shared/components/markdown/suggestion_diff_header_spec.js75
-rw-r--r--spec/javascripts/vue_shared/components/notes/placeholder_note_spec.js51
-rw-r--r--spec/javascripts/vue_shared/components/notes/placeholder_system_note_spec.js27
-rw-r--r--spec/javascripts/vue_shared/components/notes/system_note_spec.js59
-rw-r--r--spec/javascripts/vue_shared/components/pagination/graphql_pagination_spec.js70
-rw-r--r--spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js6
-rw-r--r--spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js8
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js36
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js86
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/date_picker_spec.js121
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/base_spec.js130
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js95
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js108
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js76
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js40
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js42
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js43
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js98
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js137
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/mock_data.js4
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/toggle_sidebar_spec.js32
-rw-r--r--spec/javascripts/vue_shared/components/table_pagination_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js18
-rw-r--r--spec/javascripts/vue_shared/translate_spec.js2
-rw-r--r--spec/lib/api/helpers/pagination_spec.rb34
-rw-r--r--spec/lib/api/helpers/related_resources_helpers_spec.rb34
-rw-r--r--spec/lib/api/helpers_spec.rb12
-rw-r--r--spec/lib/banzai/commit_renderer_spec.rb4
-rw-r--r--spec/lib/banzai/filter/external_issue_reference_filter_spec.rb7
-rw-r--r--spec/lib/banzai/filter/milestone_reference_filter_spec.rb21
-rw-r--r--spec/lib/banzai/filter/syntax_highlight_filter_spec.rb2
-rw-r--r--spec/lib/banzai/filter/table_of_contents_filter_spec.rb5
-rw-r--r--spec/lib/banzai/filter/wiki_link_filter_spec.rb42
-rw-r--r--spec/lib/banzai/object_renderer_spec.rb28
-rw-r--r--spec/lib/banzai/pipeline/gfm_pipeline_spec.rb23
-rw-r--r--spec/lib/banzai/redactor_spec.rb32
-rw-r--r--spec/lib/banzai/renderer_spec.rb14
-rw-r--r--spec/lib/gitlab/asciidoc_spec.rb188
-rw-r--r--spec/lib/gitlab/background_migration/delete_diff_files_spec.rb6
-rw-r--r--spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/migrate_build_stage_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/populate_external_pipeline_source_spec.rb3
-rw-r--r--spec/lib/gitlab/background_migration/reset_merge_status_spec.rb48
-rw-r--r--spec/lib/gitlab/background_migration/schedule_calculate_wiki_sizes_spec.rb62
-rw-r--r--spec/lib/gitlab/bitbucket_import/importer_spec.rb41
-rw-r--r--spec/lib/gitlab/bitbucket_server_import/importer_spec.rb1
-rw-r--r--spec/lib/gitlab/checks/branch_check_spec.rb118
-rw-r--r--spec/lib/gitlab/checks/lfs_check_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb16
-rw-r--r--spec/lib/gitlab/ci/config/entry/job_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/entry/service_spec.rb10
-rw-r--r--spec/lib/gitlab/ci/config/extendable/entry_spec.rb46
-rw-r--r--spec/lib/gitlab/ci/config/external/file/remote_spec.rb14
-rw-r--r--spec/lib/gitlab/ci/config/external/mapper_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/config/external/processor_spec.rb20
-rw-r--r--spec/lib/gitlab/ci/config_spec.rb7
-rw-r--r--spec/lib/gitlab/ci/cron_parser_spec.rb7
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/lexeme/and_spec.rb77
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/lexeme/equals_spec.rb55
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/lexeme/matches_spec.rb120
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/lexeme/not_equals_spec.rb73
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/lexeme/not_matches_spec.rb122
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/lexeme/or_spec.rb77
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/lexeme/pattern_spec.rb94
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/lexer_spec.rb50
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/parser_spec.rb48
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb225
-rw-r--r--spec/lib/gitlab/ci/status/stage/factory_spec.rb18
-rw-r--r--spec/lib/gitlab/ci/status/stage/play_manual_spec.rb74
-rw-r--r--spec/lib/gitlab/ci/variables/collection/item_spec.rb14
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb6
-rw-r--r--spec/lib/gitlab/cluster/puma_worker_killer_observer_spec.rb27
-rw-r--r--spec/lib/gitlab/cluster/rack_timeout_observer_spec.rb77
-rw-r--r--spec/lib/gitlab/correlation_id_spec.rb77
-rw-r--r--spec/lib/gitlab/danger/helper_spec.rb128
-rw-r--r--spec/lib/gitlab/danger/roulette_spec.rb144
-rw-r--r--spec/lib/gitlab/danger/teammate_spec.rb51
-rw-r--r--spec/lib/gitlab/data_builder/deployment_spec.rb39
-rw-r--r--spec/lib/gitlab/data_builder/note_spec.rb2
-rw-r--r--spec/lib/gitlab/data_builder/pipeline_spec.rb9
-rw-r--r--spec/lib/gitlab/data_builder/push_spec.rb11
-rw-r--r--spec/lib/gitlab/discussions_diff/highlight_cache_spec.rb110
-rw-r--r--spec/lib/gitlab/favicon_spec.rb2
-rw-r--r--spec/lib/gitlab/git/blob_spec.rb2
-rw-r--r--spec/lib/gitlab/git/commit_spec.rb37
-rw-r--r--spec/lib/gitlab/git/object_pool_spec.rb41
-rw-r--r--spec/lib/gitlab/git/repository_cleaner_spec.rb71
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb262
-rw-r--r--spec/lib/gitlab/git/tree_spec.rb4
-rw-r--r--spec/lib/gitlab/git/wiki_spec.rb16
-rw-r--r--spec/lib/gitlab/git_ref_validator_spec.rb92
-rw-r--r--spec/lib/gitlab/gitaly_client/cleanup_service_spec.rb10
-rw-r--r--spec/lib/gitlab/gitaly_client/conflicts_service_spec.rb21
-rw-r--r--spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb20
-rw-r--r--spec/lib/gitlab/gitaly_client/operation_service_spec.rb18
-rw-r--r--spec/lib/gitlab/gitaly_client/ref_service_spec.rb11
-rw-r--r--spec/lib/gitlab/gitaly_client/repository_service_spec.rb41
-rw-r--r--spec/lib/gitlab/gitaly_client/wiki_service_spec.rb6
-rw-r--r--spec/lib/gitlab/gitaly_client_spec.rb42
-rw-r--r--spec/lib/gitlab/github_import/importer/issue_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb3
-rw-r--r--spec/lib/gitlab/github_import/parallel_importer_spec.rb11
-rw-r--r--spec/lib/gitlab/graphql/authorize/authorize_field_service_spec.rb142
-rw-r--r--spec/lib/gitlab/graphql/connections/keyset_connection_spec.rb5
-rw-r--r--spec/lib/gitlab/graphql/generic_tracing_spec.rb67
-rw-r--r--spec/lib/gitlab/graphql/loaders/batch_lfs_oid_loader_spec.rb23
-rw-r--r--spec/lib/gitlab/graphql/loaders/batch_project_statistics_loader_spec.rb18
-rw-r--r--spec/lib/gitlab/graphql/query_analyzers/logger_analyzer_spec.rb25
-rw-r--r--spec/lib/gitlab/graphql/representation/tree_entry_spec.rb20
-rw-r--r--spec/lib/gitlab/graphql/tracing_spec.rb33
-rw-r--r--spec/lib/gitlab/graphql_logger_spec.rb40
-rw-r--r--spec/lib/gitlab/http_connection_adapter_spec.rb120
-rw-r--r--spec/lib/gitlab/http_spec.rb28
-rw-r--r--spec/lib/gitlab/import/set_async_jid_spec.rb23
-rw-r--r--spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb14
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml5
-rw-r--r--spec/lib/gitlab/import_export/attribute_cleaner_spec.rb6
-rw-r--r--spec/lib/gitlab/import_export/attribute_configuration_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/members_mapper_spec.rb20
-rw-r--r--spec/lib/gitlab/import_export/project.json9
-rw-r--r--spec/lib/gitlab/import_export/project_tree_restorer_spec.rb33
-rw-r--r--spec/lib/gitlab/import_export/project_tree_saver_spec.rb7
-rw-r--r--spec/lib/gitlab/import_export/repo_restorer_spec.rb6
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml7
-rw-r--r--spec/lib/gitlab/import_sources_spec.rb13
-rw-r--r--spec/lib/gitlab/json_logger_spec.rb2
-rw-r--r--spec/lib/gitlab/kubernetes/helm/api_spec.rb46
-rw-r--r--spec/lib/gitlab/legacy_github_import/importer_spec.rb19
-rw-r--r--spec/lib/gitlab/lets_encrypt/challenge_spec.rb17
-rw-r--r--spec/lib/gitlab/lets_encrypt/client_spec.rb162
-rw-r--r--spec/lib/gitlab/lets_encrypt/order_spec.rb41
-rw-r--r--spec/lib/gitlab/lfs_token_spec.rb98
-rw-r--r--spec/lib/gitlab/markdown_cache/active_record/extension_spec.rb179
-rw-r--r--spec/lib/gitlab/markdown_cache/field_data_spec.rb15
-rw-r--r--spec/lib/gitlab/markdown_cache/redis/extension_spec.rb76
-rw-r--r--spec/lib/gitlab/markdown_cache/redis/store_spec.rb68
-rw-r--r--spec/lib/gitlab/metrics/dashboard/finder_spec.rb69
-rw-r--r--spec/lib/gitlab/metrics/dashboard/processor_spec.rb127
-rw-r--r--spec/lib/gitlab/metrics/dashboard/project_dashboard_service_spec.rb62
-rw-r--r--spec/lib/gitlab/metrics/dashboard/system_dashboard_service_spec.rb32
-rw-r--r--spec/lib/gitlab/metrics/samplers/puma_sampler_spec.rb123
-rw-r--r--spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb30
-rw-r--r--spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb25
-rw-r--r--spec/lib/gitlab/metrics/system_spec.rb24
-rw-r--r--spec/lib/gitlab/namespaced_session_store_spec.rb22
-rw-r--r--spec/lib/gitlab/omniauth_initializer_spec.rb22
-rw-r--r--spec/lib/gitlab/path_regex_spec.rb10
-rw-r--r--spec/lib/gitlab/phabricator_import/base_worker_spec.rb74
-rw-r--r--spec/lib/gitlab/phabricator_import/cache/map_spec.rb66
-rw-r--r--spec/lib/gitlab/phabricator_import/conduit/client_spec.rb59
-rw-r--r--spec/lib/gitlab/phabricator_import/conduit/maniphest_spec.rb39
-rw-r--r--spec/lib/gitlab/phabricator_import/conduit/response_spec.rb79
-rw-r--r--spec/lib/gitlab/phabricator_import/conduit/tasks_response_spec.rb27
-rw-r--r--spec/lib/gitlab/phabricator_import/import_tasks_worker_spec.rb16
-rw-r--r--spec/lib/gitlab/phabricator_import/importer_spec.rb32
-rw-r--r--spec/lib/gitlab/phabricator_import/issues/importer_spec.rb53
-rw-r--r--spec/lib/gitlab/phabricator_import/issues/task_importer_spec.rb54
-rw-r--r--spec/lib/gitlab/phabricator_import/project_creator_spec.rb58
-rw-r--r--spec/lib/gitlab/phabricator_import/representation/task_spec.rb33
-rw-r--r--spec/lib/gitlab/phabricator_import/worker_state_spec.rb46
-rw-r--r--spec/lib/gitlab/profiler_spec.rb6
-rw-r--r--spec/lib/gitlab/prometheus/query_variables_spec.rb28
-rw-r--r--spec/lib/gitlab/search_results_spec.rb24
-rw-r--r--spec/lib/gitlab/sentry_spec.rb9
-rw-r--r--spec/lib/gitlab/session_spec.rb27
-rw-r--r--spec/lib/gitlab/shell_spec.rb10
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/correlation_injector_spec.rb2
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/correlation_logger_spec.rb2
-rw-r--r--spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb7
-rw-r--r--spec/lib/gitlab/tracing/factory_spec.rb43
-rw-r--r--spec/lib/gitlab/tracing/grpc_interceptor_spec.rb47
-rw-r--r--spec/lib/gitlab/tracing/jaeger_factory_spec.rb71
-rw-r--r--spec/lib/gitlab/tracing/rack_middleware_spec.rb62
-rw-r--r--spec/lib/gitlab/tracing/rails/action_view_subscriber_spec.rb147
-rw-r--r--spec/lib/gitlab/tracing/rails/active_record_subscriber_spec.rb73
-rw-r--r--spec/lib/gitlab/tracing/sidekiq/client_middleware_spec.rb43
-rw-r--r--spec/lib/gitlab/tracing/sidekiq/server_middleware_spec.rb43
-rw-r--r--spec/lib/gitlab/url_blocker_spec.rb83
-rw-r--r--spec/lib/gitlab/url_builder_spec.rb2
-rw-r--r--spec/lib/gitlab/url_sanitizer_spec.rb34
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb21
-rw-r--r--spec/lib/gitlab/workhorse_spec.rb82
-rw-r--r--spec/lib/gitlab_spec.rb30
-rw-r--r--spec/lib/mattermost/session_spec.rb7
-rw-r--r--spec/lib/quality/kubernetes_client_spec.rb4
-rw-r--r--spec/lib/quality/seeders/issues_spec.rb18
-rw-r--r--spec/lib/quality/test_level_spec.rb105
-rw-r--r--spec/mailers/emails/pages_domains_spec.rb6
-rw-r--r--spec/mailers/notify_spec.rb14
-rw-r--r--spec/mailers/repository_check_mailer_spec.rb10
-rw-r--r--spec/migrations/change_packages_size_defaults_in_project_statistics_spec.rb35
-rw-r--r--spec/migrations/enqueue_reset_merge_status_spec.rb52
-rw-r--r--spec/migrations/enqueue_verify_pages_domain_workers_spec.rb6
-rw-r--r--spec/migrations/fix_pool_repository_source_project_id_spec.rb29
-rw-r--r--spec/migrations/generate_lets_encrypt_private_key_spec.rb12
-rw-r--r--spec/migrations/generate_missing_routes_spec.rb2
-rw-r--r--spec/migrations/migrate_old_artifacts_spec.rb4
-rw-r--r--spec/migrations/remove_orphaned_label_links_spec.rb6
-rw-r--r--spec/migrations/schedule_fill_valid_time_for_pages_domain_certificates_spec.rb46
-rw-r--r--spec/migrations/schedule_sync_issuables_state_id_where_nil_spec.rb57
-rw-r--r--spec/models/active_session_spec.rb46
-rw-r--r--spec/models/application_record_spec.rb25
-rw-r--r--spec/models/application_setting_spec.rb14
-rw-r--r--spec/models/blob_spec.rb15
-rw-r--r--spec/models/broadcast_message_spec.rb8
-rw-r--r--spec/models/ci/bridge_spec.rb4
-rw-r--r--spec/models/ci/build_spec.rb275
-rw-r--r--spec/models/ci/group_variable_spec.rb3
-rw-r--r--spec/models/ci/job_artifact_spec.rb59
-rw-r--r--spec/models/ci/legacy_stage_spec.rb2
-rw-r--r--spec/models/ci/pipeline_schedule_spec.rb156
-rw-r--r--spec/models/ci/pipeline_schedule_variable_spec.rb2
-rw-r--r--spec/models/ci/pipeline_spec.rb119
-rw-r--r--spec/models/ci/pipeline_variable_spec.rb3
-rw-r--r--spec/models/ci/runner_spec.rb5
-rw-r--r--spec/models/ci/stage_spec.rb2
-rw-r--r--spec/models/ci/variable_spec.rb3
-rw-r--r--spec/models/clusters/applications/cert_manager_spec.rb6
-rw-r--r--spec/models/clusters/applications/helm_spec.rb8
-rw-r--r--spec/models/clusters/applications/ingress_spec.rb6
-rw-r--r--spec/models/clusters/applications/jupyter_spec.rb11
-rw-r--r--spec/models/clusters/applications/knative_spec.rb84
-rw-r--r--spec/models/clusters/applications/prometheus_spec.rb53
-rw-r--r--spec/models/clusters/applications/runner_spec.rb30
-rw-r--r--spec/models/clusters/cluster_spec.rb257
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb41
-rw-r--r--spec/models/clusters/project_spec.rb1
-rw-r--r--spec/models/commit_spec.rb8
-rw-r--r--spec/models/commit_status_spec.rb4
-rw-r--r--spec/models/concerns/cache_markdown_field_spec.rb446
-rw-r--r--spec/models/concerns/has_ref_spec.rb4
-rw-r--r--spec/models/concerns/milestoneish_spec.rb78
-rw-r--r--spec/models/concerns/noteable_spec.rb12
-rw-r--r--spec/models/concerns/reactive_caching_spec.rb13
-rw-r--r--spec/models/deployment_spec.rb31
-rw-r--r--spec/models/diff_note_spec.rb8
-rw-r--r--spec/models/environment_spec.rb6
-rw-r--r--spec/models/event_spec.rb2
-rw-r--r--spec/models/group_spec.rb100
-rw-r--r--spec/models/internal_id_spec.rb11
-rw-r--r--spec/models/issue_spec.rb38
-rw-r--r--spec/models/member_spec.rb10
-rw-r--r--spec/models/merge_request_spec.rb125
-rw-r--r--spec/models/milestone_spec.rb71
-rw-r--r--spec/models/namespace_spec.rb68
-rw-r--r--spec/models/note_diff_file_spec.rb27
-rw-r--r--spec/models/notification_recipient_spec.rb273
-rw-r--r--spec/models/pages_domain_acme_order_spec.rb49
-rw-r--r--spec/models/pages_domain_spec.rb39
-rw-r--r--spec/models/pool_repository_spec.rb2
-rw-r--r--spec/models/project_auto_devops_spec.rb60
-rw-r--r--spec/models/project_ci_cd_setting_spec.rb40
-rw-r--r--spec/models/project_metrics_setting_spec.rb55
-rw-r--r--spec/models/project_services/assembla_service_spec.rb6
-rw-r--r--spec/models/project_services/bamboo_service_spec.rb3
-rw-r--r--spec/models/project_services/buildkite_service_spec.rb10
-rw-r--r--spec/models/project_services/campfire_service_spec.rb24
-rw-r--r--spec/models/project_services/chat_message/deployment_message_spec.rb153
-rw-r--r--spec/models/project_services/hipchat_service_spec.rb11
-rw-r--r--spec/models/project_services/jira_service_spec.rb7
-rw-r--r--spec/models/project_services/kubernetes_service_spec.rb22
-rw-r--r--spec/models/project_services/microsoft_teams_service_spec.rb6
-rw-r--r--spec/models/project_services/pipelines_email_service_spec.rb76
-rw-r--r--spec/models/project_services/pivotaltracker_service_spec.rb10
-rw-r--r--spec/models/project_services/pushover_service_spec.rb6
-rw-r--r--spec/models/project_services/teamcity_service_spec.rb3
-rw-r--r--spec/models/project_spec.rb190
-rw-r--r--spec/models/project_statistics_spec.rb122
-rw-r--r--spec/models/project_wiki_spec.rb74
-rw-r--r--spec/models/push_event_spec.rb4
-rw-r--r--spec/models/release_spec.rb5
-rw-r--r--spec/models/remote_mirror_spec.rb16
-rw-r--r--spec/models/repository_spec.rb207
-rw-r--r--spec/models/resource_label_event_spec.rb4
-rw-r--r--spec/models/user_preference_spec.rb6
-rw-r--r--spec/models/user_spec.rb25
-rw-r--r--spec/models/wiki_page_spec.rb66
-rw-r--r--spec/policies/clusters/cluster_policy_spec.rb16
-rw-r--r--spec/policies/clusters/instance_policy_spec.rb36
-rw-r--r--spec/policies/personal_snippet_policy_spec.rb31
-rw-r--r--spec/policies/project_policy_spec.rb6
-rw-r--r--spec/presenters/blob_presenter_spec.rb10
-rw-r--r--spec/presenters/ci/build_runner_presenter_spec.rb66
-rw-r--r--spec/presenters/clusters/cluster_presenter_spec.rb52
-rw-r--r--spec/presenters/issue_presenter_spec.rb29
-rw-r--r--spec/presenters/label_presenter_spec.rb93
-rw-r--r--spec/presenters/merge_request_presenter_spec.rb60
-rw-r--r--spec/presenters/project_presenter_spec.rb19
-rw-r--r--spec/presenters/tree_entry_presenter_spec.rb16
-rw-r--r--spec/rack_servers/configs/puma.rb32
-rw-r--r--spec/rack_servers/puma_spec.rb22
-rw-r--r--spec/requests/api/badges_spec.rb6
-rw-r--r--spec/requests/api/circuit_breakers_spec.rb46
-rw-r--r--spec/requests/api/commits_spec.rb92
-rw-r--r--spec/requests/api/discussions_spec.rb4
-rw-r--r--spec/requests/api/events_spec.rb135
-rw-r--r--spec/requests/api/graphql/gitlab_schema_spec.rb136
-rw-r--r--spec/requests/api/graphql/group_query_spec.rb119
-rw-r--r--spec/requests/api/graphql/multiplexed_queries_spec.rb39
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/set_wip_spec.rb2
-rw-r--r--spec/requests/api/graphql/namespace/projects_spec.rb82
-rw-r--r--spec/requests/api/graphql/project/issues_spec.rb28
-rw-r--r--spec/requests/api/graphql/project/project_statistics_spec.rb43
-rw-r--r--spec/requests/api/graphql/project/repository_spec.rb37
-rw-r--r--spec/requests/api/graphql/project/tree/tree_spec.rb73
-rw-r--r--spec/requests/api/graphql_spec.rb48
-rw-r--r--spec/requests/api/group_variables_spec.rb8
-rw-r--r--spec/requests/api/groups_spec.rb3
-rw-r--r--spec/requests/api/helpers_spec.rb7
-rw-r--r--spec/requests/api/internal_spec.rb18
-rw-r--r--spec/requests/api/issues/get_group_issues_spec.rb652
-rw-r--r--spec/requests/api/issues/get_project_issues_spec.rb807
-rw-r--r--spec/requests/api/issues/issues_spec.rb776
-rw-r--r--spec/requests/api/issues/post_projects_issues_spec.rb549
-rw-r--r--spec/requests/api/issues/put_projects_issues_spec.rb392
-rw-r--r--spec/requests/api/issues_spec.rb2257
-rw-r--r--spec/requests/api/jobs_spec.rb5
-rw-r--r--spec/requests/api/members_spec.rb15
-rw-r--r--spec/requests/api/merge_requests_spec.rb6
-rw-r--r--spec/requests/api/pipeline_schedules_spec.rb7
-rw-r--r--spec/requests/api/pipelines_spec.rb9
-rw-r--r--spec/requests/api/project_clusters_spec.rb4
-rw-r--r--spec/requests/api/project_events_spec.rb156
-rw-r--r--spec/requests/api/projects_spec.rb90
-rw-r--r--spec/requests/api/releases_spec.rb49
-rw-r--r--spec/requests/api/runner_spec.rb78
-rw-r--r--spec/requests/api/search_spec.rb53
-rw-r--r--spec/requests/api/settings_spec.rb1
-rw-r--r--spec/requests/api/system_hooks_spec.rb8
-rw-r--r--spec/requests/api/tags_spec.rb2
-rw-r--r--spec/requests/api/task_completion_status_spec.rb85
-rw-r--r--spec/requests/api/users_spec.rb12
-rw-r--r--spec/requests/api/variables_spec.rb13
-rw-r--r--spec/requests/rack_attack_global_spec.rb26
-rw-r--r--spec/routing/group_routing_spec.rb14
-rw-r--r--spec/routing/import_routing_spec.rb12
-rw-r--r--spec/routing/project_routing_spec.rb84
-rw-r--r--spec/routing/uploads_routing_spec.rb22
-rw-r--r--spec/rubocop/cop/code_reuse/active_record_spec.rb6
-rw-r--r--spec/rubocop/cop/include_action_view_context_spec.rb45
-rw-r--r--spec/rubocop/cop/qa/element_with_pattern_spec.rb11
-rw-r--r--spec/serializers/analytics_stage_serializer_spec.rb30
-rw-r--r--spec/serializers/board_serializer_spec.rb20
-rw-r--r--spec/serializers/build_details_entity_spec.rb33
-rw-r--r--spec/serializers/cluster_application_entity_spec.rb4
-rw-r--r--spec/serializers/deployment_entity_spec.rb41
-rw-r--r--spec/serializers/job_artifact_report_entity_spec.rb28
-rw-r--r--spec/serializers/merge_request_widget_entity_spec.rb46
-rw-r--r--spec/serializers/pipeline_entity_spec.rb20
-rw-r--r--spec/serializers/pipeline_serializer_spec.rb2
-rw-r--r--spec/serializers/stage_entity_spec.rb28
-rw-r--r--spec/serializers/stage_serializer_spec.rb31
-rw-r--r--spec/serializers/test_case_entity_spec.rb2
-rw-r--r--spec/services/auth/container_registry_authentication_service_spec.rb2
-rw-r--r--spec/services/auto_merge/base_service_spec.rb178
-rw-r--r--spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb223
-rw-r--r--spec/services/auto_merge_service_spec.rb164
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb40
-rw-r--r--spec/services/ci/pipeline_schedule_service_spec.rb36
-rw-r--r--spec/services/ci/play_manual_stage_service_spec.rb79
-rw-r--r--spec/services/ci/retry_build_service_spec.rb5
-rw-r--r--spec/services/ci/stop_environments_service_spec.rb76
-rw-r--r--spec/services/clusters/applications/check_installation_progress_service_spec.rb6
-rw-r--r--spec/services/clusters/applications/check_uninstall_progress_service_spec.rb145
-rw-r--r--spec/services/clusters/applications/create_service_spec.rb2
-rw-r--r--spec/services/clusters/applications/destroy_service_spec.rb63
-rw-r--r--spec/services/clusters/applications/uninstall_service_spec.rb77
-rw-r--r--spec/services/clusters/build_service_spec.rb8
-rw-r--r--spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb2
-rw-r--r--spec/services/clusters/refresh_service_spec.rb8
-rw-r--r--spec/services/compare_service_spec.rb13
-rw-r--r--spec/services/delete_branch_service_spec.rb24
-rw-r--r--spec/services/git/base_hooks_service_spec.rb90
-rw-r--r--spec/services/git/branch_hooks_service_spec.rb10
-rw-r--r--spec/services/git/branch_push_service_spec.rb66
-rw-r--r--spec/services/git/tag_hooks_service_spec.rb6
-rw-r--r--spec/services/issuable/clone/content_rewriter_spec.rb16
-rw-r--r--spec/services/issues/close_service_spec.rb44
-rw-r--r--spec/services/lfs/file_transformer_spec.rb19
-rw-r--r--spec/services/members/create_service_spec.rb13
-rw-r--r--spec/services/merge_requests/close_service_spec.rb16
-rw-r--r--spec/services/merge_requests/create_pipeline_service_spec.rb71
-rw-r--r--spec/services/merge_requests/create_service_spec.rb6
-rw-r--r--spec/services/merge_requests/merge_to_ref_service_spec.rb2
-rw-r--r--spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb197
-rw-r--r--spec/services/merge_requests/post_merge_service_spec.rb8
-rw-r--r--spec/services/merge_requests/push_options_handler_service_spec.rb5
-rw-r--r--spec/services/merge_requests/rebase_service_spec.rb44
-rw-r--r--spec/services/merge_requests/refresh_service_spec.rb32
-rw-r--r--spec/services/merge_requests/update_service_spec.rb15
-rw-r--r--spec/services/notification_service_spec.rb62
-rw-r--r--spec/services/pages_domains/create_acme_order_service_spec.rb63
-rw-r--r--spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb146
-rw-r--r--spec/services/preview_markdown_service_spec.rb4
-rw-r--r--spec/services/projects/after_import_service_spec.rb2
-rw-r--r--spec/services/projects/cleanup_service_spec.rb89
-rw-r--r--spec/services/projects/create_service_spec.rb27
-rw-r--r--spec/services/projects/detect_repository_languages_service_spec.rb2
-rw-r--r--spec/services/projects/fork_service_spec.rb24
-rw-r--r--spec/services/projects/git_deduplication_service_spec.rb90
-rw-r--r--spec/services/projects/housekeeping_service_spec.rb3
-rw-r--r--spec/services/projects/import_service_spec.rb45
-rw-r--r--spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb23
-rw-r--r--spec/services/projects/lfs_pointers/lfs_download_service_spec.rb20
-rw-r--r--spec/services/projects/lfs_pointers/lfs_import_service_spec.rb153
-rw-r--r--spec/services/projects/lfs_pointers/lfs_link_service_spec.rb1
-rw-r--r--spec/services/projects/lfs_pointers/lfs_object_download_list_service_spec.rb148
-rw-r--r--spec/services/projects/operations/update_service_spec.rb50
-rw-r--r--spec/services/projects/repository_languages_service_spec.rb4
-rw-r--r--spec/services/projects/transfer_service_spec.rb27
-rw-r--r--spec/services/projects/update_pages_service_spec.rb59
-rw-r--r--spec/services/projects/update_service_spec.rb3
-rw-r--r--spec/services/projects/update_statistics_service_spec.rb12
-rw-r--r--spec/services/service_response_spec.rb57
-rw-r--r--spec/services/submit_usage_ping_service_spec.rb4
-rw-r--r--spec/services/suggestions/apply_service_spec.rb68
-rw-r--r--spec/services/suggestions/create_service_spec.rb22
-rw-r--r--spec/services/system_hooks_service_spec.rb12
-rw-r--r--spec/services/system_note_service_spec.rb4
-rw-r--r--spec/services/todos/destroy/confidential_issue_service_spec.rb58
-rw-r--r--spec/services/todos/destroy/entity_leave_service_spec.rb14
-rw-r--r--spec/services/update_deployment_service_spec.rb1
-rw-r--r--spec/services/users/destroy_service_spec.rb4
-rw-r--r--spec/services/users/migrate_to_ghost_user_service_spec.rb2
-rw-r--r--spec/services/users/update_service_spec.rb9
-rw-r--r--spec/services/verify_pages_domain_service_spec.rb12
-rw-r--r--spec/services/web_hook_service_spec.rb10
-rw-r--r--spec/spec_helper.rb9
-rw-r--r--spec/support/capybara.rb16
-rw-r--r--spec/support/controllers/ldap_omniauth_callbacks_controller_shared_context.rb6
-rw-r--r--spec/support/features/discussion_comments_shared_example.rb2
-rw-r--r--spec/support/features/reportable_note_shared_examples.rb4
-rw-r--r--spec/support/features/variable_list_shared_examples.rb64
-rw-r--r--spec/support/helpers/email_helpers.rb4
-rw-r--r--spec/support/helpers/features/notes_helpers.rb10
-rw-r--r--spec/support/helpers/filtered_search_helpers.rb17
-rw-r--r--spec/support/helpers/git_helpers.rb8
-rw-r--r--spec/support/helpers/graphql_helpers.rb36
-rw-r--r--spec/support/helpers/javascript_fixtures_helpers.rb20
-rw-r--r--spec/support/helpers/kubernetes_helpers.rb66
-rw-r--r--spec/support/helpers/lets_encrypt_helpers.rb59
-rw-r--r--spec/support/helpers/login_helpers.rb3
-rw-r--r--spec/support/helpers/metrics_dashboard_helpers.rb43
-rw-r--r--spec/support/helpers/mobile_helpers.rb2
-rw-r--r--spec/support/helpers/notification_helpers.rb8
-rw-r--r--spec/support/helpers/project_forks_helper.rb23
-rw-r--r--spec/support/helpers/query_recorder.rb2
-rw-r--r--spec/support/helpers/repo_helpers.rb78
-rw-r--r--spec/support/helpers/select2_helper.rb4
-rw-r--r--spec/support/helpers/stub_configuration.rb3
-rw-r--r--spec/support/helpers/stub_requests.rb40
-rw-r--r--spec/support/helpers/test_env.rb14
-rw-r--r--spec/support/helpers/test_request_helpers.rb4
-rw-r--r--spec/support/helpers/wait_for_requests.rb14
-rw-r--r--spec/support/helpers/wait_helpers.rb20
-rw-r--r--spec/support/matchers/eq_pem.rb11
-rw-r--r--spec/support/prometheus/additional_metrics_shared_examples.rb2
-rw-r--r--spec/support/protected_branch_helpers.rb30
-rw-r--r--spec/support/protected_tag_helpers.rb18
-rw-r--r--spec/support/services/migrate_to_ghost_user_service_shared_examples.rb4
-rw-r--r--spec/support/shared_context/policies/project_policy_shared_context.rb89
-rw-r--r--spec/support/shared_contexts/policies/project_policy_shared_context.rb88
-rw-r--r--spec/support/shared_examples/application_setting_examples.rb39
-rw-r--r--spec/support/shared_examples/ci/stage_shared_examples.rb27
-rw-r--r--spec/support/shared_examples/ci_trace_shared_examples.rb39
-rw-r--r--spec/support/shared_examples/controllers/repository_lfs_file_load_examples.rb116
-rw-r--r--spec/support/shared_examples/controllers/variables_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/finders/assignees_filter_shared_examples.rb43
-rw-r--r--spec/support/shared_examples/finders/assignees_filter_spec.rb49
-rw-r--r--spec/support/shared_examples/legacy_path_redirect_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb (renamed from spec/support/shared_examples/models/atomic_internal_id_spec.rb)0
-rw-r--r--spec/support/shared_examples/models/chat_service_shared_examples.rb248
-rw-r--r--spec/support/shared_examples/models/chat_service_spec.rb242
-rw-r--r--spec/support/shared_examples/models/ci_variable_shared_examples.rb29
-rw-r--r--spec/support/shared_examples/models/cluster_application_core_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/models/cluster_application_status_shared_examples.rb65
-rw-r--r--spec/support/shared_examples/models/member_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/models/update_project_statistics_shared_examples.rb77
-rw-r--r--spec/support/shared_examples/notify_shared_examples.rb45
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb7
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/shrug_quick_action_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/tableflip_quick_action_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/quick_actions/issue/remove_due_date_quick_action_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/discussions.rb24
-rw-r--r--spec/support/shared_examples/requests/api/issues_shared_examples.rb44
-rw-r--r--spec/support/shared_examples/slack_mattermost_notifications_shared_examples.rb14
-rw-r--r--spec/support/shoulda/matchers/rails_shim.rb27
-rw-r--r--spec/tasks/gitlab/artifacts/migrate_rake_spec.rb55
-rw-r--r--spec/tasks/gitlab/shell_rake_spec.rb18
-rw-r--r--spec/tasks/tokens_spec.rb4
-rw-r--r--spec/uploaders/import_export_uploader_spec.rb32
-rw-r--r--spec/uploaders/legacy_artifact_uploader_spec.rb61
-rw-r--r--spec/uploaders/object_storage_spec.rb10
-rw-r--r--spec/uploaders/personal_file_uploader_spec.rb60
-rw-r--r--spec/uploaders/workers/object_storage/background_move_worker_spec.rb34
-rw-r--r--spec/views/help/index.html.haml_spec.rb2
-rw-r--r--spec/views/notify/pipeline_failed_email.html.haml_spec.rb4
-rw-r--r--spec/views/notify/pipeline_failed_email.text.erb_spec.rb39
-rw-r--r--spec/views/notify/pipeline_success_email.html.haml_spec.rb4
-rw-r--r--spec/views/profiles/show.html.haml_spec.rb4
-rw-r--r--spec/views/projects/commit/_commit_box.html.haml_spec.rb4
-rw-r--r--spec/views/projects/issues/_merge_requests_status.html.haml_spec.rb28
-rw-r--r--spec/views/projects/issues/show.html.haml_spec.rb27
-rw-r--r--spec/views/projects/jobs/_build.html.haml_spec.rb10
-rw-r--r--spec/views/projects/notes/_more_actions_dropdown.html.haml_spec.rb8
-rw-r--r--spec/views/projects/tree/show.html.haml_spec.rb2
-rw-r--r--spec/views/shared/_label_row.html.haml.rb32
-rw-r--r--spec/workers/auto_merge_process_worker_spec.rb31
-rw-r--r--spec/workers/build_finished_worker_spec.rb1
-rw-r--r--spec/workers/build_success_worker_spec.rb1
-rw-r--r--spec/workers/cluster_configure_worker_spec.rb70
-rw-r--r--spec/workers/cluster_project_configure_worker_spec.rb15
-rw-r--r--spec/workers/clusters/applications/wait_for_uninstall_app_worker_spec.rb32
-rw-r--r--spec/workers/deployments/finished_worker_spec.rb39
-rw-r--r--spec/workers/detect_repository_languages_worker_spec.rb11
-rw-r--r--spec/workers/expire_build_instance_artifacts_worker_spec.rb6
-rw-r--r--spec/workers/git_garbage_collect_worker_spec.rb13
-rw-r--r--spec/workers/pages_domain_removal_cron_worker_spec.rb27
-rw-r--r--spec/workers/pages_domain_verification_cron_worker_spec.rb15
-rw-r--r--spec/workers/pages_domain_verification_worker_spec.rb7
-rw-r--r--spec/workers/pipeline_schedule_worker_spec.rb49
-rw-r--r--spec/workers/pipeline_success_worker_spec.rb26
-rw-r--r--spec/workers/project_cache_worker_spec.rb5
-rw-r--r--spec/workers/run_pipeline_schedule_worker_spec.rb32
-rw-r--r--spec/workers/todos_destroyer/confidential_issue_worker_spec.rb13
-rw-r--r--vendor/assets/javascripts/pdf.js19365
-rw-r--r--vendor/assets/javascripts/pdf.min.js1
-rw-r--r--vendor/assets/javascripts/pdf.worker.js47057
-rw-r--r--vendor/assets/javascripts/pdf.worker.min.js1
-rw-r--r--vendor/assets/javascripts/snowplow/sp.js22
-rw-r--r--vendor/jupyter/values.yaml38
-rw-r--r--yarn.lock2103
4262 files changed, 236960 insertions, 121296 deletions
diff --git a/.codeclimate.yml b/.codeclimate.yml
index 9998ddba643..2be8e63e842 100644
--- a/.codeclimate.yml
+++ b/.codeclimate.yml
@@ -6,35 +6,35 @@ engines:
enabled: true
config:
languages:
- - ruby
- - javascript
+ - ruby
+ - javascript
ratings:
paths:
- - Gemfile.lock
- - "**.erb"
- - "**.haml"
- - "**.rb"
- - "**.rhtml"
- - "**.slim"
- - "**.inc"
- - "**.js"
- - "**.jsx"
- - "**.module"
+ - Gemfile.lock
+ - "**.erb"
+ - "**.haml"
+ - "**.rb"
+ - "**.rhtml"
+ - "**.slim"
+ - "**.inc"
+ - "**.js"
+ - "**.jsx"
+ - "**.module"
exclude_paths:
-- config/
-- db/
-- features/
-- node_modules/
-- spec/
-- vendor/
-- .yarn-cache/
-- tmp/
-- builds/
-- coverage/
-- public/
-- shared/
-- webpack-report/
-- log/
-- backups/
-- coverage-javascript/
-- plugins/
+ - config/
+ - db/
+ - features/
+ - node_modules/
+ - spec/
+ - vendor/
+ - .yarn-cache/
+ - tmp/
+ - builds/
+ - coverage/
+ - public/
+ - shared/
+ - webpack-report/
+ - log/
+ - backups/
+ - coverage-javascript/
+ - plugins/
diff --git a/.eslintrc.yml b/.eslintrc.yml
index 98a497aa12a..2b881d5f201 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -8,11 +8,13 @@ globals:
plugins:
- import
- html
+ - "@gitlab/i18n"
settings:
import/resolver:
webpack:
config: './config/webpack.config.js'
rules:
+ "@gitlab/i18n/no-non-i18n-strings": error
import/no-commonjs: error
no-underscore-dangle:
- error
@@ -31,3 +33,11 @@ rules:
vue/no-use-v-if-with-v-for: off
vue/no-v-html: off
vue/use-v-on-exact: off
+overrides:
+ files:
+ # Vue is temporarily being disabled until the autofix errors are resolved
+ # Follow up issue https://gitlab.com/gitlab-org/gitlab-ce/issues/57969
+ - '*.vue'
+ - '**/spec/**/*'
+ rules:
+ "@gitlab/i18n/no-non-i18n-strings": off
diff --git a/.gitignore b/.gitignore
index 0696dd217af..cb718a6939f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,8 +59,6 @@ eslint-report.html
/public/uploads.*
/public/uploads/
/shared/artifacts/
-/spec/javascripts/fixtures/blob/pdf/
-/spec/javascripts/fixtures/blob/balsamiq/
/rails_best_practices_output.html
/tags
/tmp/*
@@ -81,3 +79,4 @@ package-lock.json
/junit_*.xml
/coverage-frontend/
jsdoc/
+**/tmp/rubocop_cache/** \ No newline at end of file
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 72385b93bd9..d49b620f22c 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,4 +1,4 @@
-image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-golang-1.11-git-2.18-chrome-71.0-node-10.x-yarn-1.12-postgresql-9.6-graphicsmagick-1.3.29"
+image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.21-chrome-73.0-node-10.x-yarn-1.12-postgresql-9.6-graphicsmagick-1.3.29"
variables:
MYSQL_ALLOW_EMPTY_PASSWORD: "1"
@@ -13,10 +13,8 @@ variables:
BUILD_ASSETS_IMAGE: "false"
before_script:
- - bundle --version
- date
- source scripts/utils.sh
- - date
- source scripts/prepare_build.sh
- date
@@ -28,6 +26,8 @@ stages:
- prepare
- merge
- test
+ - review
+ - qa
- post-test
- pages
- post-cleanup
@@ -44,3 +44,4 @@ include:
- local: .gitlab/ci/review.gitlab-ci.yml
- local: .gitlab/ci/setup.gitlab-ci.yml
- local: .gitlab/ci/test-metadata.gitlab-ci.yml
+ - local: .gitlab/ci/yaml.gitlab-ci.yml
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
new file mode 100644
index 00000000000..63ac5a408bd
--- /dev/null
+++ b/.gitlab/CODEOWNERS
@@ -0,0 +1,21 @@
+# Backend Maintainers are the default for all ruby files
+*.rb @ashmckenzie @ayufan @dbalexandre @DouweM @dzaporozhets @godfat @grzesiek @mkozono @mayra-cabrera @nick.thomas @rspeicher @rymai @reprazent @smcgivern @tkuah
+*.rake @ashmckenzie @ayufan @dbalexandre @DouweM @dzaporozhets @godfat @grzesiek @mkozono @mayra-cabrera @nick.thomas @rspeicher @rymai @reprazent @smcgivern @tkuah
+
+# Technical writing team are the default reviewers for everything in `doc/`
+/doc/ @axil @marcia @eread
+
+# Frontend maintainers should see everything in `app/assets/`
+app/assets/ @ClemMakesApps @fatihacet @filipa @iamphill @mikegreiling @timzallmann @kushalpandya
+*.scss @annabeldunstone @ClemMakesApps @fatihacet @filipa @iamphill @mikegreiling @timzallmann @kushalpandya
+
+# Someone from the database team should review changes in `db/`
+db/ @abrandl @NikolayS
+
+# Feature specific owners
+/ee/lib/gitlab/code_owners/ @reprazent
+/ee/lib/ee/gitlab/auth/ldap/ @dblessing @mkozono
+/lib/gitlab/auth/ldap/ @dblessing @mkozono
+/lib/gitlab/ci/templates/ @nolith @zj
+/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml @DylanGriffith @mayra-cabrera @tkuah
+/lib/gitlab/ci/templates/Security/ @plafoucriere @gonzoyumo @twoodham
diff --git a/.gitlab/CODEOWNERS.disabled b/.gitlab/CODEOWNERS.disabled
deleted file mode 100644
index f7e2c06dae5..00000000000
--- a/.gitlab/CODEOWNERS.disabled
+++ /dev/null
@@ -1,20 +0,0 @@
-# Backend Maintainers are the default for all ruby files
-*.rb @ashmckenzie @ayufan @dbalexandre @DouweM @dzaporozhets @godfat @grzesiek @mkozono @nick.thomas @rspeicher @rymai @smcgivern
-*.rake @ashmckenzie @ayufan @dbalexandre @DouweM @dzaporozhets @godfat @grzesiek @mkozono @nick.thomas @rspeicher @rymai @smcgivern
-
-# Technical writing team are the default reviewers for everything in `doc/`
-/doc/ @axil @marcia
-
-# Frontend maintainers should see everything in `app/assets/`
-app/assets/ @ClemMakesApps @fatihacet @filipa @iamphill @mikegreiling @timzallmann @kushalpandya
-*.scss @annabeldunstone @ClemMakesApps @fatihacet @filipa @iamphill @mikegreiling @timzallmann @kushalpandya
-
-# Someone from the database team should review changes in `db/`
-db/ @abrandl @NikolayS
-
-# Feature specific owners
-/ee/lib/gitlab/code_owners/ @reprazent
-/ee/lib/ee/gitlab/auth/ldap/ @dblessing @mkozono
-/lib/gitlab/auth/ldap/ @dblessing @mkozono
-/lib/gitlab/ci/templates/ @nolith @zj
-/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml @DylanGriffith @mayra-cabrera @tkuah
diff --git a/.gitlab/ci/cng.gitlab-ci.yml b/.gitlab/ci/cng.gitlab-ci.yml
index e15f8ed91e0..d624e8d09f6 100644
--- a/.gitlab/ci/cng.gitlab-ci.yml
+++ b/.gitlab/ci/cng.gitlab-ci.yml
@@ -1,5 +1,5 @@
cloud-native-image:
- image: ruby:2.5-alpine
+ image: ruby:2.6-alpine
before_script: []
dependencies: []
stage: post-test
@@ -9,7 +9,7 @@ cloud-native-image:
cache: {}
when: manual
script:
- - gem install gitlab --no-document
+ - install_gitlab_gem
- CNG_PROJECT_PATH="gitlab-org/build/CNG" BUILD_TRIGGER_TOKEN=$CI_JOB_TOKEN ./scripts/trigger-build cng
only:
- tags@gitlab-org/gitlab-ce
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index e38b878972d..fd5733593ef 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -16,7 +16,7 @@
gitlab:assets:compile:
<<: *assets-compile-cache
extends: .dedicated-no-docs-pull-cache-job
- image: dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-git-2.18-chrome-71.0-node-8.x-yarn-1.12-graphicsmagick-1.3.29-docker-18.06.1
+ image: dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-git-2.21-chrome-73.0-node-8.x-yarn-1.12-graphicsmagick-1.3.29-docker-18.06.1
dependencies:
- setup-test-env
services:
@@ -33,11 +33,16 @@ gitlab:assets:compile:
DOCKER_HOST: tcp://docker:2375
script:
- node --version
- - yarn install --frozen-lockfile --production --cache-folder .yarn-cache
+ - retry yarn install --frozen-lockfile --production --cache-folder .yarn-cache
- free -m
- - bundle exec rake gitlab:assets:compile
+ - retry bundle exec rake gitlab:assets:compile
- time scripts/build_assets_image
- scripts/clean-old-cached-assets
+ - rm -f /etc/apt/sources.list.d/google*.list # We don't need to update Chrome here
+ # Play dependent manual jobs
+ - install_api_client_dependencies_with_apt
+ - play_job "review-build-cng" || true # this job might not exist so ignore the failure if it cannot be played
+ - play_job "schedule:review-build-cng" || true # this job might not exist so ignore the failure if it cannot be played
artifacts:
name: webpack-report
expire_in: 31d
@@ -60,9 +65,9 @@ compile-assets:
stage: prepare
script:
- node --version
- - yarn install --frozen-lockfile --cache-folder .yarn-cache
+ - retry yarn install --frozen-lockfile --cache-folder .yarn-cache
- free -m
- - bundle exec rake gitlab:assets:compile
+ - retry bundle exec rake gitlab:assets:compile
- scripts/clean-old-cached-assets
variables:
# we override the max_old_space_size to prevent OOM errors
@@ -103,7 +108,8 @@ gitlab:ui:visual:
- $CI_COMMIT_MESSAGE =~ /\[skip visual\]/i
artifacts:
paths:
- - tests/__image_snapshots__/
+ - gitlab-ui/tests/__image_snapshots__/
+ when: always
karma:
extends: .dedicated-no-docs-pull-cache-job
@@ -135,8 +141,8 @@ jest:
extends: .dedicated-no-docs-and-no-qa-pull-cache-job
<<: *use-pg
dependencies:
- - compile-assets
- - setup-test-env
+ - compile-assets
+ - setup-test-env
script:
- scripts/gitaly-test-spawn
- date
@@ -148,8 +154,8 @@ jest:
expire_in: 31d
when: always
paths:
- - coverage-frontend/
- - junit_jest.xml
+ - coverage-frontend/
+ - junit_jest.xml
reports:
junit: junit_jest.xml
cache:
@@ -214,7 +220,7 @@ lint:javascript:report:
before_script: []
script:
- date
- - yarn run eslint-report || true # ignore exit code
+ - yarn run eslint-report || true # ignore exit code
artifacts:
name: eslint-report
expire_in: 31d
@@ -229,9 +235,9 @@ jsdoc:
before_script: []
script:
- date
- - yarn run jsdoc || true # ignore exit code
+ - yarn run jsdoc || true # ignore exit code
artifacts:
name: jsdoc
expire_in: 31d
paths:
- - jsdoc/ \ No newline at end of file
+ - jsdoc/
diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml
index c48672183b9..aa25bad00e8 100644
--- a/.gitlab/ci/global.gitlab-ci.yml
+++ b/.gitlab/ci/global.gitlab-ci.yml
@@ -1,6 +1,6 @@
.dedicated-runner:
retry:
- max: 1 # This is confusing but this means "2 runs at max".
+ max: 2 # This is confusing but this means "3 runs at max".
when:
- unknown_failure
- api_failure
@@ -9,7 +9,7 @@
- gitlab-org
.default-cache: &default-cache
- key: "debian-stretch-ruby-2.5.3-node-10.x"
+ key: "debian-stretch-ruby-2.6.3-node-10.x"
paths:
- vendor/ruby
- .yarn-cache/
@@ -47,7 +47,7 @@
.single-script-job-dedicated-runner:
extends: .dedicated-runner
- image: ruby:2.5-alpine
+ image: ruby:2.6-alpine
stage: test
cache: {}
dependencies: []
diff --git a/.gitlab/ci/pages.gitlab-ci.yml b/.gitlab/ci/pages.gitlab-ci.yml
index 7d9136b8213..f7b18b809b4 100644
--- a/.gitlab/ci/pages.gitlab-ci.yml
+++ b/.gitlab/ci/pages.gitlab-ci.yml
@@ -1,4 +1,3 @@
-
pages:
extends: .dedicated-no-docs-no-db-pull-cache-job
before_script: []
diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml
index 07b38c9aa85..ee9e467886a 100644
--- a/.gitlab/ci/qa.gitlab-ci.yml
+++ b/.gitlab/ci/qa.gitlab-ci.yml
@@ -1,20 +1,17 @@
package-and-qa:
- image: ruby:2.5-alpine
- stage: test
+ image: ruby:2.6-alpine
+ stage: review # So even if review-deploy failed we can still run this
+ when: manual
before_script: []
dependencies: []
cache: {}
variables:
GIT_DEPTH: "1"
- API_TOKEN: "${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}"
retry: 0
script:
- - apk add --update openssl curl jq
- - gem install gitlab --no-document
- - source ./scripts/review_apps/review-apps.sh
- - wait_for_job_to_be_done "gitlab:assets:compile"
+ - source scripts/utils.sh
+ - install_gitlab_gem
- ./scripts/trigger-build omnibus
- when: manual
only:
- /.+/@gitlab-org/gitlab-ce
- /.+/@gitlab-org/gitlab-ee
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index b926fb77a08..33e7b00784c 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -6,8 +6,9 @@
.use-pg-10: &use-pg-10
services:
- - postgres:10.0
- - redis:alpine
+ - name: postgres:10.7
+ command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
+ - name: redis:alpine
.use-mysql: &use-mysql
services:
@@ -52,8 +53,10 @@
script:
- JOB_NAME=( $CI_JOB_NAME )
- TEST_TOOL=${JOB_NAME[0]}
- - export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${TEST_TOOL}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
- - export KNAPSACK_GENERATE_REPORT=true
+ - TEST_LEVEL=${JOB_NAME[1]}
+ - DATABASE=${JOB_NAME[2]}
+ - export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${TEST_TOOL}_${TEST_LEVEL}_${DATABASE}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
+ - export KNAPSACK_GENERATE_REPORT=true KNAPSACK_LOG_LEVEL=debug KNAPSACK_TEST_DIR=spec
- export SUITE_FLAKY_RSPEC_REPORT_PATH=${FLAKY_RSPEC_SUITE_REPORT_PATH}
- export FLAKY_RSPEC_REPORT_PATH=rspec_flaky/all_${TEST_TOOL}_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
- export NEW_FLAKY_RSPEC_REPORT_PATH=rspec_flaky/new_${TEST_TOOL}_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
@@ -63,7 +66,10 @@
- '[[ -f $FLAKY_RSPEC_REPORT_PATH ]] || echo "{}" > ${FLAKY_RSPEC_REPORT_PATH}'
- '[[ -f $NEW_FLAKY_RSPEC_REPORT_PATH ]] || echo "{}" > ${NEW_FLAKY_RSPEC_REPORT_PATH}'
- scripts/gitaly-test-spawn
- - knapsack rspec "--color --format documentation --format RspecJunitFormatter --out junit_rspec.xml"
+ - date
+ - 'export KNAPSACK_TEST_FILE_PATTERN=$(ruby -r./lib/quality/test_level.rb -e "puts Quality::TestLevel.new.pattern(:${TEST_LEVEL})")'
+ - knapsack rspec "--color --format documentation --format RspecJunitFormatter --out junit_rspec.xml --tag level:${TEST_LEVEL} --tag ~geo"
+ - date
artifacts:
expire_in: 31d
when: always
@@ -86,7 +92,7 @@
.rspec-metadata-pg-10: &rspec-metadata-pg-10
<<: *rspec-metadata
<<: *use-pg-10
- image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-golang-1.11-git-2.18-chrome-71.0-node-10.x-yarn-1.12-postgresql-10-graphicsmagick-1.3.29"
+ image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.21-chrome-73.0-node-10.x-yarn-1.12-postgresql-10-graphicsmagick-1.3.29"
.rspec-metadata-mysql: &rspec-metadata-mysql
<<: *rspec-metadata
@@ -108,7 +114,8 @@
- git fetch https://gitlab.com/gitlab-org/gitlab-ce.git v9.3.0
- git checkout -f FETCH_HEAD
- sed -i "s/gem 'oj', '~> 2.17.4'//" Gemfile
- - bundle update google-protobuf grpc
+ - sed -i "s/gem 'bootsnap', '~> 1.0.0'/gem 'bootsnap'/" Gemfile
+ - bundle update google-protobuf grpc bootsnap
- bundle install $BUNDLE_INSTALL_FLAGS
- date
- cp config/gitlab.yml.example config/gitlab.yml
@@ -129,7 +136,7 @@ setup-test-env:
stage: prepare
script:
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
- - scripts/gitaly-test-build # Do not use 'bundle exec' here
+ - scripts/gitaly-test-build # Do not use 'bundle exec' here
artifacts:
expire_in: 7d
paths:
@@ -139,19 +146,68 @@ setup-test-env:
except:
- /(^docs[\/-].*|.*-docs$)/
-rspec-pg:
+rspec unit pg:
+ <<: *rspec-metadata-pg
+ parallel: 20
+
+rspec integration pg:
<<: *rspec-metadata-pg
- parallel: 50
+ parallel: 6
+
+rspec system pg:
+ <<: *rspec-metadata-pg
+ parallel: 24
+
+rspec unit pg-10:
+ <<: *rspec-metadata-pg-10
+ <<: *only-schedules-master
+ parallel: 20
+
+rspec integration pg-10:
+ <<: *rspec-metadata-pg-10
+ <<: *only-schedules-master
+ parallel: 6
-rspec-pg-10:
+rspec system pg-10:
<<: *rspec-metadata-pg-10
<<: *only-schedules-master
- parallel: 50
+ parallel: 24
-rspec-mysql:
+rspec unit mysql:
<<: *rspec-metadata-mysql
<<: *only-schedules-master
- parallel: 50
+ parallel: 20
+
+rspec integration mysql:
+ <<: *rspec-metadata-mysql
+ <<: *only-schedules-master
+ parallel: 6
+
+rspec system mysql:
+ <<: *rspec-metadata-mysql
+ <<: *only-schedules-master
+ parallel: 24
+
+.rspec-mysql-on-demand: &rspec-mysql-on-demand
+ only:
+ variables:
+ - $CI_COMMIT_MESSAGE =~ /\[run mysql\]/i
+ - $CI_COMMIT_REF_NAME =~ /mysql/
+
+rspec unit mysql on-demand:
+ <<: *rspec-metadata-mysql
+ <<: *rspec-mysql-on-demand
+ parallel: 20
+
+rspec integration mysql on-demand:
+ <<: *rspec-metadata-mysql
+ <<: *rspec-mysql-on-demand
+ parallel: 6
+
+rspec system mysql on-demand:
+ <<: *rspec-metadata-mysql
+ <<: *rspec-mysql-on-demand
+ parallel: 24
rspec-fast-spec-helper:
<<: *rspec-metadata-pg
@@ -163,16 +219,17 @@ rspec-fast-spec-helper:
script:
- export CACHE_CLASSES=true
- scripts/gitaly-test-spawn
- - bin/rspec --color --format documentation --tag quarantine spec/
+ - bin/rspec --color --format documentation --tag quarantine -- spec/
-rspec-pg-quarantine:
+rspec quarantine pg:
<<: *rspec-metadata-pg
<<: *rspec-quarantine
allow_failure: true
-rspec-mysql-quarantine:
+rspec quarantine mysql:
<<: *rspec-metadata-mysql
<<: *rspec-quarantine
+ <<: *only-schedules-master
allow_failure: true
static-analysis:
@@ -183,7 +240,7 @@ static-analysis:
script:
- scripts/static-analysis
cache:
- key: "debian-stretch-ruby-2.5.3-node-10.x-and-rubocop"
+ key: "debian-stretch-ruby-2.6.3-node-10.x-and-rubocop"
paths:
- vendor/ruby
- .yarn-cache/
@@ -285,8 +342,8 @@ coverage:
name: coverage
expire_in: 31d
paths:
- - coverage/index.html
- - coverage/assets/
+ - coverage/index.html
+ - coverage/assets/
except:
- /(^docs[\/-].*|.*-docs$)/
- /(^qa[\/-].*|.*-qa$)/
diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml
index 9655498073e..d0e09dbf2f8 100644
--- a/.gitlab/ci/reports.gitlab-ci.yml
+++ b/.gitlab/ci/reports.gitlab-ci.yml
@@ -1,8 +1,8 @@
include:
- - local: /lib/gitlab/ci/templates/Code-Quality.gitlab-ci.yml
+ - template: Code-Quality.gitlab-ci.yml
code_quality:
- extends: .dedicated-runner
+ extends: .dedicated-no-docs-no-db-pull-cache-job
# gitlab-org runners set `privileged: false` but we need to have it set to true
# since we're using Docker in Docker
tags: []
@@ -13,7 +13,7 @@ code_quality:
SETUP_DB: "false"
sast:
- extends: .dedicated-runner
+ extends: .dedicated-no-docs-no-db-pull-cache-job
image: docker:stable
variables:
SAST_CONFIDENCE_LEVEL: 2
@@ -26,18 +26,38 @@ sast:
services:
- docker:stable-dind
script:
+ - | # this is required to avoid undesirable reset of Docker image ENV variables being set on build stage
+ function propagate_env_vars() {
+ CURRENT_ENV=$(printenv)
+
+ for VAR_NAME; do
+ echo $CURRENT_ENV | grep "${VAR_NAME}=" > /dev/null && echo "--env $VAR_NAME "
+ done
+ }
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
- - docker run
- --env SAST_CONFIDENCE_LEVEL="${SAST_CONFIDENCE_LEVEL:-3}"
- --volume "$PWD:/code"
- --volume /var/run/docker.sock:/var/run/docker.sock
+ - |
+ docker run \
+ $(propagate_env_vars \
+ SAST_ANALYZER_IMAGES \
+ SAST_ANALYZER_IMAGE_PREFIX \
+ SAST_ANALYZER_IMAGE_TAG \
+ SAST_DEFAULT_ANALYZERS \
+ SAST_BRAKEMAN_LEVEL \
+ SAST_GOSEC_LEVEL \
+ SAST_FLAWFINDER_LEVEL \
+ SAST_DOCKER_CLIENT_NEGOTIATION_TIMEOUT \
+ SAST_PULL_ANALYZER_IMAGE_TIMEOUT \
+ SAST_RUN_ANALYZER_TIMEOUT \
+ ) \
+ --volume "$PWD:/code" \
+ --volume /var/run/docker.sock:/var/run/docker.sock \
"registry.gitlab.com/gitlab-org/security-products/sast:$SP_VERSION" /app/bin/run /code
artifacts:
reports:
sast: gl-sast-report.json
dependency_scanning:
- extends: .dedicated-runner
+ extends: .dedicated-no-docs-no-db-pull-cache-job
image: docker:stable
variables:
DOCKER_DRIVER: overlay2
@@ -50,10 +70,28 @@ dependency_scanning:
- docker:stable-dind
script:
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
- - docker run
- --env DEP_SCAN_DISABLE_REMOTE_CHECKS="${DEP_SCAN_DISABLE_REMOTE_CHECKS:-false}"
- --volume "$PWD:/code"
- --volume /var/run/docker.sock:/var/run/docker.sock
+ - | # this is required to avoid undesirable reset of Docker image ENV variables being set on build stage
+ function propagate_env_vars() {
+ CURRENT_ENV=$(printenv)
+
+ for VAR_NAME; do
+ echo $CURRENT_ENV | grep "${VAR_NAME}=" > /dev/null && echo "--env $VAR_NAME "
+ done
+ }
+ - |
+ docker run \
+ $(propagate_env_vars \
+ DS_ANALYZER_IMAGES \
+ DS_ANALYZER_IMAGE_PREFIX \
+ DS_ANALYZER_IMAGE_TAG \
+ DS_DEFAULT_ANALYZERS \
+ DEP_SCAN_DISABLE_REMOTE_CHECKS \
+ DS_DOCKER_CLIENT_NEGOTIATION_TIMEOUT \
+ DS_PULL_ANALYZER_IMAGE_TIMEOUT \
+ DS_RUN_ANALYZER_TIMEOUT \
+ ) \
+ --volume "$PWD:/code" \
+ --volume /var/run/docker.sock:/var/run/docker.sock \
"registry.gitlab.com/gitlab-org/security-products/dependency-scanning:$SP_VERSION" /code
artifacts:
reports:
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index a7f6caedd37..9b764028be9 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -26,13 +26,10 @@
extends: .dedicated-runner
<<: *review-only
image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-charts-build-base
- stage: test
cache: {}
dependencies: []
- environment: &review-environment
- name: review/${CI_COMMIT_REF_NAME}
- url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}
- before_script: []
+ before_script:
+ - source scripts/utils.sh
.review-docker: &review-docker
<<: *review-base
@@ -43,7 +40,6 @@
- gitlab-org
- docker
variables: &review-docker-variables
- GIT_DEPTH: "1"
DOCKER_DRIVER: overlay2
DOCKER_HOST: tcp://docker:2375
LATEST_QA_IMAGE: "gitlab/${CI_PROJECT_NAME}-qa:nightly"
@@ -51,28 +47,23 @@
build-qa-image:
<<: *review-docker
- variables:
- <<: *review-docker-variables
- GIT_DEPTH: "20"
- stage: prepare
+ stage: test
script:
- time docker build --cache-from ${LATEST_QA_IMAGE} --tag ${QA_IMAGE} ./qa/
- echo "${CI_JOB_TOKEN}" | docker login --username gitlab-ci-token --password-stdin ${CI_REGISTRY}
- time docker push ${QA_IMAGE}
.review-build-cng-base: &review-build-cng-base
- image: ruby:2.5-alpine
+ image: ruby:2.6-alpine
stage: test
- before_script: []
+ when: manual
+ before_script:
+ - source scripts/utils.sh
+ - install_api_client_dependencies_with_apk
+ - install_gitlab_gem
dependencies: []
cache: {}
- variables:
- API_TOKEN: "${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}"
script:
- - apk add --update openssl curl jq
- - gem install gitlab --no-document
- - source ./scripts/review_apps/review-apps.sh
- - wait_for_job_to_be_done "gitlab:assets:compile"
- BUILD_TRIGGER_TOKEN=$REVIEW_APPS_BUILD_TRIGGER_TOKEN ./scripts/trigger-build cng
review-build-cng:
@@ -83,28 +74,33 @@ schedule:review-build-cng:
<<: *review-schedules-only
<<: *review-build-cng-base
-
.review-deploy-base: &review-deploy-base
<<: *review-base
allow_failure: true
+ stage: review
variables:
HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}"
DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}"
GITLAB_HELM_CHART_REF: "master"
- API_TOKEN: "${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}"
- environment:
- <<: *review-environment
+ environment: &review-environment
+ name: review/${CI_COMMIT_REF_NAME}
+ url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}
on_stop: review-stop
before_script:
- export GITLAB_SHELL_VERSION=$(<GITLAB_SHELL_VERSION)
- export GITALY_VERSION=$(<GITALY_SERVER_VERSION)
- export GITLAB_WORKHORSE_VERSION=$(<GITLAB_WORKHORSE_VERSION)
- - apk update && apk add jq
- - gem install gitlab --no-document
- - source ./scripts/review_apps/review-apps.sh
+ - echo "${CI_ENVIRONMENT_URL}" > review_app_url.txt
+ - source scripts/utils.sh
+ - install_api_client_dependencies_with_apk
+ - source scripts/review_apps/review-apps.sh
script:
- - wait_for_job_to_be_done "review-build-cng"
- perform_review_app_deployment
+ artifacts:
+ paths:
+ - review_app_url.txt
+ expire_in: 2 days
+ when: always
review-deploy:
<<: *review-deploy-base
@@ -113,15 +109,29 @@ schedule:review-deploy:
<<: *review-deploy-base
<<: *review-schedules-only
script:
- - wait_for_job_to_be_done "schedule:review-build-cng"
- perform_review_app_deployment
+review-stop:
+ <<: *review-base
+ stage: review
+ when: manual
+ allow_failure: true
+ variables:
+ GIT_DEPTH: "1"
+ environment:
+ <<: *review-environment
+ action: stop
+ script:
+ - source scripts/review_apps/review-apps.sh
+ - delete
+ - cleanup
+
.review-qa-base: &review-qa-base
<<: *review-docker
allow_failure: true
+ stage: qa
variables:
<<: *review-docker-variables
- API_TOKEN: "${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}"
QA_ARTIFACTS_DIR: "${CI_PROJECT_DIR}/qa"
QA_CAN_TEST_GIT_PROTOCOL_V2: "false"
GITLAB_USERNAME: "root"
@@ -131,39 +141,48 @@ schedule:review-deploy:
GITHUB_ACCESS_TOKEN: "${REVIEW_APPS_QA_GITHUB_ACCESS_TOKEN}"
EE_LICENSE: "${REVIEW_APPS_EE_LICENSE}"
QA_DEBUG: "true"
+ dependencies:
+ - review-deploy
artifacts:
paths:
- ./qa/gitlab-qa-run-*
expire_in: 7 days
when: always
before_script:
- - echo "${QA_IMAGE}"
+ - export CI_ENVIRONMENT_URL="$(cat review_app_url.txt)"
- echo "${CI_ENVIRONMENT_URL}"
- - apk update && apk add curl jq
- - source ./scripts/review_apps/review-apps.sh
+ - echo "${QA_IMAGE}"
+ - source scripts/utils.sh
+ - install_api_client_dependencies_with_apk
- gem install gitlab-qa --no-document ${GITLAB_QA_VERSION:+ --version ${GITLAB_QA_VERSION}}
review-qa-smoke:
<<: *review-qa-base
script:
- - wait_for_job_to_be_done "review-deploy"
- gitlab-qa Test::Instance::Smoke "${QA_IMAGE}" "${CI_ENVIRONMENT_URL}"
review-qa-all:
<<: *review-qa-base
+ allow_failure: true
+ when: manual
+ parallel: 5
script:
- - wait_for_job_to_be_done "review-deploy"
+ - export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/review-qa-all_master_report.json
+ - export KNAPSACK_TEST_FILE_PATTERN=qa/specs/features/**/*_spec.rb
- gitlab-qa Test::Instance::Any "${QA_IMAGE}" "${CI_ENVIRONMENT_URL}"
- when: manual
.review-performance-base: &review-performance-base
<<: *review-qa-base
- script:
- - wait_for_job_to_be_done "review-deploy"
+ allow_failure: true
+ before_script:
+ - export CI_ENVIRONMENT_URL="$(cat review_app_url.txt)"
+ - echo "${CI_ENVIRONMENT_URL}"
- mkdir -p gitlab-exporter
- wget -O ./gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/master/index.js
- - mkdir sitespeed-results
- - docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io:6.3.1 --plugins.add ./gitlab-exporter --outputFolder sitespeed-results "$CI_ENVIRONMENT_URL"
+ - mkdir -p sitespeed-results
+ script:
+ - docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io:6.3.1 --plugins.add ./gitlab-exporter --outputFolder sitespeed-results "${CI_ENVIRONMENT_URL}"
+ after_script:
- mv sitespeed-results/data/performance.json performance.json
artifacts:
paths:
@@ -174,41 +193,26 @@ review-qa-all:
review-performance:
<<: *review-performance-base
-review-stop:
- extends: .single-script-job-dedicated-runner
- image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-charts-build-base
- allow_failure: true
- variables:
- SCRIPT_NAME: "review_apps/review-apps.sh"
- when: manual
- environment:
- <<: *review-environment
- action: stop
- script:
- - source $(basename "${SCRIPT_NAME}")
- - delete
- - cleanup
+schedule:review-performance:
+ <<: *review-performance-base
+ <<: *review-schedules-only
+ dependencies:
+ - schedule:review-deploy
schedule:review-cleanup:
<<: *review-base
<<: *review-schedules-only
stage: build
allow_failure: true
- variables:
- GIT_DEPTH: "1"
environment:
name: review/auto-cleanup
+ action: stop
before_script:
- - gem install gitlab --no-document
+ - source scripts/utils.sh
+ - install_gitlab_gem
script:
- ruby -rrubygems scripts/review_apps/automated_cleanup.rb
-schedule:review-performance:
- <<: *review-performance-base
- <<: *review-schedules-only
- script:
- - wait_for_job_to_be_done "schedule:review-deploy"
-
danger-review:
extends: .dedicated-pull-cache-job
image: registry.gitlab.com/gitlab-org/gitlab-build-images:danger
@@ -229,4 +233,3 @@ danger-review:
- node --version
- yarn install --frozen-lockfile --cache-folder .yarn-cache
- danger --fail-on-errors=true
-
diff --git a/.gitlab/ci/test-metadata.gitlab-ci.yml b/.gitlab/ci/test-metadata.gitlab-ci.yml
index 3ba7af956b5..c51f825f831 100644
--- a/.gitlab/ci/test-metadata.gitlab-ci.yml
+++ b/.gitlab/ci/test-metadata.gitlab-ci.yml
@@ -40,12 +40,12 @@ update-tests-metadata:
policy: push
script:
- retry gem install fog-aws mime-types activesupport rspec_profiling postgres-copy --no-document
- - scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec-pg_node_*.json
+ - scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec_*_pg_node_*.json
+ - '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $KNAPSACK_RSPEC_SUITE_REPORT_PATH'
+ - rm -f knapsack/${CI_PROJECT_NAME}/*_node_*.json
- scripts/merge-reports ${FLAKY_RSPEC_SUITE_REPORT_PATH} rspec_flaky/all_*_*.json
- FLAKY_RSPEC_GENERATE_REPORT=1 scripts/prune-old-flaky-specs ${FLAKY_RSPEC_SUITE_REPORT_PATH}
- - '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $KNAPSACK_RSPEC_SUITE_REPORT_PATH'
- '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $FLAKY_RSPEC_SUITE_REPORT_PATH'
- - rm -f knapsack/${CI_PROJECT_NAME}/*_node_*.json
- rm -f rspec_flaky/all_*.json rspec_flaky/new_*.json
- scripts/insert-rspec-profiling-data
only:
@@ -56,7 +56,7 @@ update-tests-metadata:
flaky-examples-check:
extends: .dedicated-runner
- image: ruby:2.5-alpine
+ image: ruby:2.6-alpine
services: []
before_script: []
variables:
diff --git a/.gitlab/ci/yaml.gitlab-ci.yml b/.gitlab/ci/yaml.gitlab-ci.yml
new file mode 100644
index 00000000000..401318d2df2
--- /dev/null
+++ b/.gitlab/ci/yaml.gitlab-ci.yml
@@ -0,0 +1,9 @@
+# Yamllint of *.yml for .gitlab-ci.yml.
+# This uses rules from project root `.yamllint`.
+lint-ci-gitlab:
+ extends: .dedicated-runner
+ before_script: []
+ dependencies: []
+ image: sdesbure/yamllint:latest
+ script:
+ - yamllint .gitlab-ci.yml .gitlab/ci lib/gitlab/ci/templates
diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md
index 3e58d2a867e..3adea22b33a 100644
--- a/.gitlab/issue_templates/Bug.md
+++ b/.gitlab/issue_templates/Bug.md
@@ -27,9 +27,9 @@ and verify the issue you're about to submit isn't a duplicate.
### Example Project
-(If possible, please create an example project here on GitLab.com that exhibits the problematic behaviour, and link to it here in the bug report)
+(If possible, please create an example project here on GitLab.com that exhibits the problematic behavior, and link to it here in the bug report)
-(If you are using an older version of GitLab, this will also determine whether the bug has been fixed in a more recent version)
+(If you are using an older version of GitLab, this will also determine whether the bug is fixed in a more recent version)
### What is the current *bug* behavior?
@@ -42,7 +42,7 @@ and verify the issue you're about to submit isn't a duplicate.
### Relevant logs and/or screenshots
(Paste any relevant logs - please use code blocks (```) to format console output,
-logs, and code as it's very hard to read otherwise.)
+logs, and code as it's tough to read otherwise.)
### Output of checks
diff --git a/.gitlab/issue_templates/Database Reviewer.md b/.gitlab/issue_templates/Database Reviewer.md
index a5e7e42fd14..acbaf5c1965 100644
--- a/.gitlab/issue_templates/Database Reviewer.md
+++ b/.gitlab/issue_templates/Database Reviewer.md
@@ -1,6 +1,8 @@
#### Database Reviewer Checklist
-Thank you for becoming a ~database reviewer! Please work on the list below to complete your setup. For any question, reach out to #database an mention @abrandl.
+Thank you for becoming a ~database reviewer! Please work on the list
+below to complete your setup. For any question, reach out to #database
+an mention `@abrandl`.
- [ ] Change issue title to include your name: `Database Reviewer Checklist: Your Name`
- [ ] Review general [code review guide](https://docs.gitlab.com/ee/development/code_review.html)
@@ -12,7 +14,7 @@ Thank you for becoming a ~database reviewer! Please work on the list below to co
- [ ] Read [Understanding EXPLAIN plans](https://docs.gitlab.com/ee/development/understanding_explain_plans.html)
- [ ] Review [database best practices](https://docs.gitlab.com/ee/development/#best-practices)
- [ ] Review how we use [database instances restored from a backup](https://ops.gitlab.net/gitlab-com/gl-infra/gitlab-restore/postgres-gprd) for testing and make sure you're set up to execute pipelines (check [README.md](https://ops.gitlab.net/gitlab-com/gl-infra/gitlab-restore/postgres-gprd/blob/master/README.md) and reach out to @abrandl since this is currently subject to being changed)
-- [ ] Get yourself added to [@gl-database](https://gitlab.com/groups/gl-database/-/group_members) group and respond to @-mentions to the group (reach out to any maintainer on the group to get added). You will get TODOs on gitlab.com for group mentions.
+- [ ] Get yourself added to [`@gl-database`](https://gitlab.com/groups/gl-database/-/group_members) group and respond to @-mentions to the group (reach out to any maintainer on the group to get added). You will get TODOs on gitlab.com for group mentions.
- [ ] Make sure you have proper access to at least a read-only replica in staging and production
- [ ] Indicate in `data/team.yml` your role as a database reviewer ([example MR](https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/19600/diffs)). Assign MR to your manager for merge.
- [ ] Send one MR to improve the [review documentation](https://about.gitlab.com/handbook/engineering/workflow/code-review/database.html) or the [issue template](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab/issue_templates/Database%20Reviewer.md)
@@ -25,7 +27,7 @@ You're all set! Watch out for TODOs on GitLab.com.
###### Where to go for questions?
-Reach out to `#database` on Slack and mention @abrandl for any questions.
+Reach out to `#database` on Slack and mention `@abrandl` for any questions.
cc @abrandl
diff --git a/.gitlab/issue_templates/Feature Flag Roll Out.md b/.gitlab/issue_templates/Feature Flag Roll Out.md
new file mode 100644
index 00000000000..b7db5a33faf
--- /dev/null
+++ b/.gitlab/issue_templates/Feature Flag Roll Out.md
@@ -0,0 +1,43 @@
+<!-- Title suggestion: [Feature flag] Enable description of feature -->
+
+## What
+
+Remove the `:feature_name` feature flag ...
+
+## Owners
+
+- Team: NAME_OF_TEAM
+- Most appropriate slack channel to reach out to: `#g_TEAM_NAME`
+- Best individual to reach out to: NAME
+
+## Expectations
+
+### What are we expecting to happen?
+
+### What might happen if this goes wrong?
+
+### What can we monitor to detect problems with this?
+
+<!-- Which dashboards from https://dashboards.gitlab.net are most relevant? -->
+
+## Beta groups/projects
+
+If applicable, any groups/projects that are happy to have this feature turned on early. Some organizations may wish to test big changes they are interested in with a small subset of users ahead of time for example.
+
+- `gitlab-org/gitlab-ce`/`gitlab-org/gitlab-ee` projects
+- `gitlab-org`/`gitlab-com` groups
+- ...
+
+## Roll Out Steps
+
+- [ ] Enable on staging
+- [ ] Test on staging
+- [ ] Ensure that documentation has been updated
+- [ ] Enable on GitLab.com for individual groups/projects listed above and verify behaviour
+- [ ] Announce on the issue an estimated time this will be enabled on GitLab.com
+- [ ] Enable on GitLab.com by running chatops command in `#production`
+- [ ] Cross post chatops slack command to `#support_gitlab-com` and in your team channel
+- [ ] Announce on the issue that the flag has been enabled
+- [ ] Remove feature flag and add changelog entry
+
+/label ~"feature flag"
diff --git a/.gitlab/issue_templates/Refactoring.md b/.gitlab/issue_templates/Refactoring.md
new file mode 100644
index 00000000000..cd0ce8486f0
--- /dev/null
+++ b/.gitlab/issue_templates/Refactoring.md
@@ -0,0 +1,41 @@
+## Summary
+
+<!--
+Please briefly describe what part of the code base needs to be refactored.
+-->
+
+## Improvements
+
+<!--
+Explain the benefits of refactoring this code.
+See also https://about.gitlab.com/handbook/values/index.html#say-why-not-just-what
+-->
+
+## Risks
+
+<!--
+Please list features that can break because of this refactoring and how you intend to solve that.
+-->
+
+## Involved components
+
+<!--
+List files or directories that will be changed by the refactoring.
+-->
+
+## Optional: Intended side effects
+
+<!--
+If the refactoring involves changes apart from the main improvements (such as a better UI), list them here.
+It may be a good idea to create separate issues and link them here.
+-->
+
+
+## Optional: Missing test coverage
+
+<!--
+If you are aware of tests that need to be written or adjusted apart from unit tests for the changed components,
+please list them here.
+-->
+
+/label ~backstage
diff --git a/.gitlab/issue_templates/Security developer workflow.md b/.gitlab/issue_templates/Security developer workflow.md
index 9946651075f..7857afb66c2 100644
--- a/.gitlab/issue_templates/Security developer workflow.md
+++ b/.gitlab/issue_templates/Security developer workflow.md
@@ -17,10 +17,10 @@ Set the title to: `Description of the original issue`
#### Backports
-- [ ] Once the MR is ready to be merged, create MRs targetting the last 3 releases, plus the current RC if between the 7th and 22nd of the month.
+- [ ] Once the MR is ready to be merged, create MRs targeting the last 3 releases, plus the current RC if between the 7th and 22nd of the month.
- [ ] At this point, it might be easy to squash the commits from the MR into one
- You can use the script `bin/secpick` instead of the following steps, to help you cherry-picking. See the [secpick documentation]
- - [ ] Create each MR targetting the stable branch `X-Y-stable`, using the "Security Release" merge request template.
+ - [ ] Create each MR targeting the stable branch `X-Y-stable`, using the "Security Release" merge request template.
- Every merge request will have its own set of TODOs, so make sure to
complete those.
- [ ] Make sure all MRs have a link in the [links section](#links)
diff --git a/.gitlab/route-map.yml b/.gitlab/route-map.yml
index 0b37dc68f8b..cc0c2856d49 100644
--- a/.gitlab/route-map.yml
+++ b/.gitlab/route-map.yml
@@ -1,3 +1,3 @@
# Documentation
-- source: /doc/(.+?)\.md/ # doc/administration/build_artifacts.md
- public: '\1.html' # doc/administration/build_artifacts.html
+- source: /doc/(.+?)\.md/ # doc/administration/build_artifacts.md
+ public: '\1.html' # doc/administration/build_artifacts.html
diff --git a/.haml-lint.yml b/.haml-lint.yml
index bad918ef35d..0412b24a48c 100644
--- a/.haml-lint.yml
+++ b/.haml-lint.yml
@@ -1,9 +1,13 @@
+inherits_from:
+ - .haml-lint_todo.yml
# Whether to ignore frontmatter at the beginning of HAML documents for
# frameworks such as Jekyll/Middleman
skip_frontmatter: false
exclude:
- 'vendor/**/*'
- 'spec/**/*'
+require:
+ - './haml_lint/linter/no_plain_nodes.rb'
linters:
AltText:
@@ -97,6 +101,7 @@ linters:
- Cop/LineBreakAroundConditionalBlock
- Cop/ProjectPathHelper
- GitlabSecurity/PublicSend
+ - Layout/EmptyLineAfterGuardClause
- Layout/LeadingCommentSpace
- Layout/SpaceAfterColon
- Layout/SpaceAfterComma
@@ -112,11 +117,13 @@ linters:
- Lint/LiteralInInterpolation
- Lint/ParenthesesAsGroupedExpression
- Lint/RedundantWithIndex
+ - Lint/SafeNavigationConsistency
- Lint/Syntax
- Metrics/BlockNesting
- Naming/VariableName
- Performance/RedundantMatch
- Performance/StringReplacement
+ - Rails/LinkToBlank
- Rails/Presence
- Rails/RequestReferer
- Style/AndOr
@@ -134,6 +141,7 @@ linters:
- Style/TernaryParentheses
- Style/TrailingCommaInHashLiteral
- Style/UnlessElse
+ - Style/UnneededCondition
- Style/WordArray
- Style/ZeroLengthPredicate
@@ -149,7 +157,7 @@ linters:
Indentation:
enabled: true
- character: space # or tab
+ character: space # or tab
TagName:
enabled: true
diff --git a/.haml-lint_todo.yml b/.haml-lint_todo.yml
new file mode 100644
index 00000000000..61805c2d8d2
--- /dev/null
+++ b/.haml-lint_todo.yml
@@ -0,0 +1,523 @@
+# This configuration was generated by
+# `haml-lint --auto-gen-config`
+# on 2019-05-07 19:04:08 +0100 using Haml-Lint version 0.30.0.
+# The point is for the user to remove these configuration records
+# one by one as the lints are removed from the code base.
+# Note that changes in the inspected code, or installation of new
+# versions of Haml-Lint, may require this file to be generated again.
+
+linters:
+
+ # Offense count: 2075
+ NoPlainNodes:
+ enabled: true
+ exclude:
+ - "app/views/admin/abuse_reports/_abuse_report.html.haml"
+ - "app/views/admin/abuse_reports/index.html.haml"
+ - "app/views/admin/appearances/_form.html.haml"
+ - "app/views/admin/application_settings/_abuse.html.haml"
+ - "app/views/admin/application_settings/_diff_limits.html.haml"
+ - "app/views/admin/application_settings/_gitaly.html.haml"
+ - "app/views/admin/application_settings/_influx.html.haml"
+ - "app/views/admin/application_settings/_ip_limits.html.haml"
+ - "app/views/admin/application_settings/_logging.html.haml"
+ - "app/views/admin/application_settings/_performance.html.haml"
+ - "app/views/admin/application_settings/_plantuml.html.haml"
+ - "app/views/admin/application_settings/_prometheus.html.haml"
+ - "app/views/admin/application_settings/_realtime.html.haml"
+ - "app/views/admin/application_settings/_repository_check.html.haml"
+ - "app/views/admin/application_settings/_repository_storage.html.haml"
+ - "app/views/admin/application_settings/_signin.html.haml"
+ - "app/views/admin/application_settings/_signup.html.haml"
+ - "app/views/admin/application_settings/_spam.html.haml"
+ - "app/views/admin/application_settings/_terminal.html.haml"
+ - "app/views/admin/application_settings/_usage.html.haml"
+ - "app/views/admin/application_settings/_visibility_and_access.html.haml"
+ - "app/views/admin/applications/_delete_form.html.haml"
+ - "app/views/admin/applications/_form.html.haml"
+ - "app/views/admin/applications/edit.html.haml"
+ - "app/views/admin/applications/index.html.haml"
+ - "app/views/admin/applications/new.html.haml"
+ - "app/views/admin/applications/show.html.haml"
+ - "app/views/admin/background_jobs/show.html.haml"
+ - "app/views/admin/broadcast_messages/index.html.haml"
+ - "app/views/admin/dashboard/index.html.haml"
+ - "app/views/admin/deploy_keys/new.html.haml"
+ - "app/views/admin/groups/show.html.haml"
+ - "app/views/admin/health_check/show.html.haml"
+ - "app/views/admin/hook_logs/_index.html.haml"
+ - "app/views/admin/hook_logs/show.html.haml"
+ - "app/views/admin/hooks/_form.html.haml"
+ - "app/views/admin/hooks/edit.html.haml"
+ - "app/views/admin/hooks/index.html.haml"
+ - "app/views/admin/labels/_form.html.haml"
+ - "app/views/admin/logs/show.html.haml"
+ - "app/views/admin/projects/_projects.html.haml"
+ - "app/views/admin/projects/show.html.haml"
+ - "app/views/admin/requests_profiles/index.html.haml"
+ - "app/views/admin/runners/_runner.html.haml"
+ - "app/views/admin/runners/index.html.haml"
+ - "app/views/admin/runners/show.html.haml"
+ - "app/views/admin/services/_form.html.haml"
+ - "app/views/admin/services/index.html.haml"
+ - "app/views/admin/spam_logs/_spam_log.html.haml"
+ - "app/views/admin/spam_logs/index.html.haml"
+ - "app/views/admin/system_info/show.html.haml"
+ - "app/views/admin/users/_access_levels.html.haml"
+ - "app/views/admin/users/_form.html.haml"
+ - "app/views/admin/users/_head.html.haml"
+ - "app/views/admin/users/_profile.html.haml"
+ - "app/views/admin/users/_projects.html.haml"
+ - "app/views/admin/users/new.html.haml"
+ - "app/views/admin/users/projects.html.haml"
+ - "app/views/admin/users/show.html.haml"
+ - "app/views/clusters/clusters/_cluster.html.haml"
+ - "app/views/clusters/clusters/_form.html.haml"
+ - "app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml"
+ - "app/views/clusters/clusters/gcp/_form.html.haml"
+ - "app/views/clusters/clusters/new.html.haml"
+ - "app/views/dashboard/milestones/index.html.haml"
+ - "app/views/dashboard/projects/_blank_state_admin_welcome.html.haml"
+ - "app/views/dashboard/projects/_blank_state_welcome.html.haml"
+ - "app/views/dashboard/projects/_zero_authorized_projects.html.haml"
+ - "app/views/dashboard/snippets/index.html.haml"
+ - "app/views/dashboard/todos/_todo.html.haml"
+ - "app/views/dashboard/todos/index.html.haml"
+ - "app/views/devise/confirmations/almost_there.haml"
+ - "app/views/devise/mailer/_confirmation_instructions_account.html.haml"
+ - "app/views/devise/mailer/_confirmation_instructions_secondary.html.haml"
+ - "app/views/devise/mailer/email_changed.html.haml"
+ - "app/views/devise/mailer/password_change.html.haml"
+ - "app/views/devise/mailer/reset_password_instructions.html.haml"
+ - "app/views/devise/mailer/unlock_instructions.html.haml"
+ - "app/views/devise/passwords/edit.html.haml"
+ - "app/views/devise/sessions/_new_base.html.haml"
+ - "app/views/devise/sessions/_new_crowd.html.haml"
+ - "app/views/devise/sessions/_new_ldap.html.haml"
+ - "app/views/devise/sessions/new.html.haml"
+ - "app/views/devise/sessions/two_factor.html.haml"
+ - "app/views/devise/shared/_omniauth_box.html.haml"
+ - "app/views/devise/shared/_sign_in_link.html.haml"
+ - "app/views/devise/shared/_signup_box.html.haml"
+ - "app/views/devise/shared/_tabs_normal.html.haml"
+ - "app/views/discussions/_discussion.html.haml"
+ - "app/views/discussions/_headline.html.haml"
+ - "app/views/discussions/_notes.html.haml"
+ - "app/views/discussions/_resolve_all.html.haml"
+ - "app/views/doorkeeper/applications/_delete_form.html.haml"
+ - "app/views/doorkeeper/authorized_applications/_delete_form.html.haml"
+ - "app/views/errors/encoding.html.haml"
+ - "app/views/errors/git_not_found.html.haml"
+ - "app/views/errors/omniauth_error.html.haml"
+ - "app/views/errors/precondition_failed.html.haml"
+ - "app/views/events/_commit.html.haml"
+ - "app/views/events/_event_push.atom.haml"
+ - "app/views/events/event/_push.html.haml"
+ - "app/views/groups/_create_chat_team.html.haml"
+ - "app/views/groups/_group_admin_settings.html.haml"
+ - "app/views/groups/group_members/_new_group_member.html.haml"
+ - "app/views/groups/group_members/index.html.haml"
+ - "app/views/groups/labels/edit.html.haml"
+ - "app/views/groups/labels/new.html.haml"
+ - "app/views/groups/milestones/edit.html.haml"
+ - "app/views/groups/milestones/index.html.haml"
+ - "app/views/groups/milestones/new.html.haml"
+ - "app/views/groups/projects.html.haml"
+ - "app/views/groups/runners/edit.html.haml"
+ - "app/views/groups/settings/_advanced.html.haml"
+ - "app/views/groups/settings/_lfs.html.haml"
+ - "app/views/help/_shortcuts.html.haml"
+ - "app/views/help/index.html.haml"
+ - "app/views/help/instance_configuration.html.haml"
+ - "app/views/help/instance_configuration/_gitlab_ci.html.haml"
+ - "app/views/help/instance_configuration/_gitlab_pages.html.haml"
+ - "app/views/help/instance_configuration/_ssh_info.html.haml"
+ - "app/views/help/ui.html.haml"
+ - "app/views/import/bitbucket/status.html.haml"
+ - "app/views/import/bitbucket_server/status.html.haml"
+ - "app/views/instance_statistics/cohorts/_cohorts_table.html.haml"
+ - "app/views/instance_statistics/cohorts/_usage_ping.html.haml"
+ - "app/views/invites/show.html.haml"
+ - "app/views/layouts/_mailer.html.haml"
+ - "app/views/layouts/header/_default.html.haml"
+ - "app/views/layouts/header/_new_dropdown.haml"
+ - "app/views/layouts/mailer/devise.html.haml"
+ - "app/views/layouts/nav/sidebar/_profile.html.haml"
+ - "app/views/layouts/notify.html.haml"
+ - "app/views/notify/_failed_builds.html.haml"
+ - "app/views/notify/_reassigned_issuable_email.html.haml"
+ - "app/views/notify/_removal_notification.html.haml"
+ - "app/views/notify/autodevops_disabled_email.html.haml"
+ - "app/views/notify/changed_milestone_email.html.haml"
+ - "app/views/notify/import_issues_csv_email.html.haml"
+ - "app/views/notify/issue_moved_email.html.haml"
+ - "app/views/notify/member_access_denied_email.html.haml"
+ - "app/views/notify/member_invite_accepted_email.html.haml"
+ - "app/views/notify/member_invite_declined_email.html.haml"
+ - "app/views/notify/member_invited_email.html.haml"
+ - "app/views/notify/new_gpg_key_email.html.haml"
+ - "app/views/notify/new_mention_in_issue_email.html.haml"
+ - "app/views/notify/new_ssh_key_email.html.haml"
+ - "app/views/notify/new_user_email.html.haml"
+ - "app/views/notify/pages_domain_disabled_email.html.haml"
+ - "app/views/notify/pages_domain_enabled_email.html.haml"
+ - "app/views/notify/pages_domain_verification_failed_email.html.haml"
+ - "app/views/notify/pages_domain_verification_succeeded_email.html.haml"
+ - "app/views/notify/pipeline_failed_email.html.haml"
+ - "app/views/notify/pipeline_success_email.html.haml"
+ - "app/views/notify/project_was_exported_email.html.haml"
+ - "app/views/notify/project_was_moved_email.html.haml"
+ - "app/views/notify/project_was_not_exported_email.html.haml"
+ - "app/views/notify/push_to_merge_request_email.html.haml"
+ - "app/views/notify/remote_mirror_update_failed_email.html.haml"
+ - "app/views/notify/removed_milestone_issue_email.html.haml"
+ - "app/views/notify/removed_milestone_merge_request_email.html.haml"
+ - "app/views/notify/repository_push_email.html.haml"
+ - "app/views/peek/views/_gc.html.haml"
+ - "app/views/peek/views/_redis.html.haml"
+ - "app/views/peek/views/_sidekiq.html.haml"
+ - "app/views/profiles/_event_table.html.haml"
+ - "app/views/profiles/active_sessions/_active_session.html.haml"
+ - "app/views/profiles/active_sessions/index.html.haml"
+ - "app/views/profiles/audit_log.html.haml"
+ - "app/views/profiles/chat_names/_chat_name.html.haml"
+ - "app/views/profiles/chat_names/index.html.haml"
+ - "app/views/profiles/chat_names/new.html.haml"
+ - "app/views/profiles/emails/index.html.haml"
+ - "app/views/profiles/gpg_keys/_key.html.haml"
+ - "app/views/profiles/gpg_keys/index.html.haml"
+ - "app/views/profiles/keys/_key.html.haml"
+ - "app/views/profiles/keys/_key_details.html.haml"
+ - "app/views/profiles/keys/index.html.haml"
+ - "app/views/profiles/notifications/show.html.haml"
+ - "app/views/profiles/passwords/edit.html.haml"
+ - "app/views/profiles/personal_access_tokens/index.html.haml"
+ - "app/views/profiles/preferences/show.html.haml"
+ - "app/views/profiles/show.html.haml"
+ - "app/views/profiles/two_factor_auths/_codes.html.haml"
+ - "app/views/profiles/two_factor_auths/codes.html.haml"
+ - "app/views/profiles/two_factor_auths/create.html.haml"
+ - "app/views/profiles/two_factor_auths/show.html.haml"
+ - "app/views/projects/_bitbucket_import_modal.html.haml"
+ - "app/views/projects/_customize_workflow.html.haml"
+ - "app/views/projects/_deletion_failed.html.haml"
+ - "app/views/projects/_fork_suggestion.html.haml"
+ - "app/views/projects/_gitlab_import_modal.html.haml"
+ - "app/views/projects/_home_panel.html.haml"
+ - "app/views/projects/_import_project_pane.html.haml"
+ - "app/views/projects/_issuable_by_email.html.haml"
+ - "app/views/projects/_md_preview.html.haml"
+ - "app/views/projects/_new_project_fields.html.haml"
+ - "app/views/projects/_readme.html.haml"
+ - "app/views/projects/artifacts/_tree_file.html.haml"
+ - "app/views/projects/artifacts/browse.html.haml"
+ - "app/views/projects/blame/_age_map_legend.html.haml"
+ - "app/views/projects/blame/show.html.haml"
+ - "app/views/projects/blob/_editor.html.haml"
+ - "app/views/projects/blob/_header_content.html.haml"
+ - "app/views/projects/blob/_new_dir.html.haml"
+ - "app/views/projects/blob/_remove.html.haml"
+ - "app/views/projects/blob/_render_error.html.haml"
+ - "app/views/projects/blob/_template_selectors.html.haml"
+ - "app/views/projects/blob/_upload.html.haml"
+ - "app/views/projects/blob/edit.html.haml"
+ - "app/views/projects/blob/new.html.haml"
+ - "app/views/projects/blob/preview.html.haml"
+ - "app/views/projects/blob/viewers/_empty.html.haml"
+ - "app/views/projects/blob/viewers/_stl.html.haml"
+ - "app/views/projects/branches/_branch.html.haml"
+ - "app/views/projects/branches/_commit.html.haml"
+ - "app/views/projects/branches/_delete_protected_modal.html.haml"
+ - "app/views/projects/branches/new.html.haml"
+ - "app/views/projects/ci/builds/_build.html.haml"
+ - "app/views/projects/ci/lints/_create.html.haml"
+ - "app/views/projects/commit/_change.html.haml"
+ - "app/views/projects/commits/_commit.html.haml"
+ - "app/views/projects/commits/_inline_commit.html.haml"
+ - "app/views/projects/compare/_form.html.haml"
+ - "app/views/projects/compare/index.html.haml"
+ - "app/views/projects/cycle_analytics/_empty_stage.html.haml"
+ - "app/views/projects/cycle_analytics/_no_access.html.haml"
+ - "app/views/projects/cycle_analytics/_overview.html.haml"
+ - "app/views/projects/cycle_analytics/show.html.haml"
+ - "app/views/projects/deploy_keys/_form.html.haml"
+ - "app/views/projects/deploy_keys/_index.html.haml"
+ - "app/views/projects/deploy_keys/edit.html.haml"
+ - "app/views/projects/deploy_tokens/_revoke_modal.html.haml"
+ - "app/views/projects/deploy_tokens/_table.html.haml"
+ - "app/views/projects/deployments/_deployment.html.haml"
+ - "app/views/projects/diffs/_file_header.html.haml"
+ - "app/views/projects/diffs/_replaced_image_diff.html.haml"
+ - "app/views/projects/diffs/_stats.html.haml"
+ - "app/views/projects/empty.html.haml"
+ - "app/views/projects/environments/show.html.haml"
+ - "app/views/projects/forks/error.html.haml"
+ - "app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml"
+ - "app/views/projects/graphs/charts.html.haml"
+ - "app/views/projects/hook_logs/_index.html.haml"
+ - "app/views/projects/hook_logs/show.html.haml"
+ - "app/views/projects/hooks/_index.html.haml"
+ - "app/views/projects/hooks/edit.html.haml"
+ - "app/views/projects/imports/new.html.haml"
+ - "app/views/projects/imports/show.html.haml"
+ - "app/views/projects/issues/_issue.html.haml"
+ - "app/views/projects/issues/_new_branch.html.haml"
+ - "app/views/projects/issues/import_csv/_modal.html.haml"
+ - "app/views/projects/issues/show.html.haml"
+ - "app/views/projects/jobs/_header.html.haml"
+ - "app/views/projects/jobs/_table.html.haml"
+ - "app/views/projects/jobs/index.html.haml"
+ - "app/views/projects/labels/edit.html.haml"
+ - "app/views/projects/labels/new.html.haml"
+ - "app/views/projects/mattermosts/_no_teams.html.haml"
+ - "app/views/projects/mattermosts/_team_selection.html.haml"
+ - "app/views/projects/mattermosts/new.html.haml"
+ - "app/views/projects/merge_requests/_commits.html.haml"
+ - "app/views/projects/merge_requests/_discussion.html.haml"
+ - "app/views/projects/merge_requests/_how_to_merge.html.haml"
+ - "app/views/projects/merge_requests/_merge_request.html.haml"
+ - "app/views/projects/merge_requests/_mr_title.html.haml"
+ - "app/views/projects/merge_requests/conflicts/_commit_stats.html.haml"
+ - "app/views/projects/merge_requests/conflicts/_file_actions.html.haml"
+ - "app/views/projects/merge_requests/conflicts/_submit_form.html.haml"
+ - "app/views/projects/merge_requests/conflicts/components/_diff_file_editor.html.haml"
+ - "app/views/projects/merge_requests/conflicts/components/_inline_conflict_lines.html.haml"
+ - "app/views/projects/merge_requests/conflicts/show.html.haml"
+ - "app/views/projects/merge_requests/creations/_diffs.html.haml"
+ - "app/views/projects/merge_requests/creations/_new_compare.html.haml"
+ - "app/views/projects/merge_requests/creations/_new_submit.html.haml"
+ - "app/views/projects/merge_requests/diffs/_different_base.html.haml"
+ - "app/views/projects/merge_requests/diffs/_diffs.html.haml"
+ - "app/views/projects/merge_requests/diffs/_version_controls.html.haml"
+ - "app/views/projects/merge_requests/invalid.html.haml"
+ - "app/views/projects/merge_requests/widget/open/_error.html.haml"
+ - "app/views/projects/mirrors/_regenerate_public_ssh_key_confirm_modal.html.haml"
+ - "app/views/projects/mirrors/_ssh_host_keys.html.haml"
+ - "app/views/projects/new.html.haml"
+ - "app/views/projects/no_repo.html.haml"
+ - "app/views/projects/pages/_access.html.haml"
+ - "app/views/projects/pages/_destroy.haml"
+ - "app/views/projects/pages/_https_only.html.haml"
+ - "app/views/projects/pages/_list.html.haml"
+ - "app/views/projects/pages/_no_domains.html.haml"
+ - "app/views/projects/pages/_use.html.haml"
+ - "app/views/projects/pages/show.html.haml"
+ - "app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml"
+ - "app/views/projects/pipelines/_info.html.haml"
+ - "app/views/projects/pipelines/charts/_pipelines.haml"
+ - "app/views/projects/protected_branches/shared/_branches_list.html.haml"
+ - "app/views/projects/protected_branches/shared/_create_protected_branch.html.haml"
+ - "app/views/projects/protected_branches/shared/_dropdown.html.haml"
+ - "app/views/projects/protected_branches/shared/_index.html.haml"
+ - "app/views/projects/protected_branches/shared/_matching_branch.html.haml"
+ - "app/views/projects/protected_branches/shared/_protected_branch.html.haml"
+ - "app/views/projects/protected_branches/show.html.haml"
+ - "app/views/projects/protected_tags/shared/_create_protected_tag.html.haml"
+ - "app/views/projects/protected_tags/shared/_dropdown.html.haml"
+ - "app/views/projects/protected_tags/shared/_index.html.haml"
+ - "app/views/projects/protected_tags/shared/_matching_tag.html.haml"
+ - "app/views/projects/protected_tags/shared/_protected_tag.html.haml"
+ - "app/views/projects/protected_tags/shared/_tags_list.html.haml"
+ - "app/views/projects/protected_tags/show.html.haml"
+ - "app/views/projects/registry/repositories/_tag.html.haml"
+ - "app/views/projects/repositories/_feed.html.haml"
+ - "app/views/projects/runners/_shared_runners.html.haml"
+ - "app/views/projects/runners/edit.html.haml"
+ - "app/views/projects/services/_form.html.haml"
+ - "app/views/projects/services/_index.html.haml"
+ - "app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml"
+ - "app/views/projects/services/mattermost_slash_commands/_help.html.haml"
+ - "app/views/projects/services/prometheus/_metrics.html.haml"
+ - "app/views/projects/services/slack_slash_commands/_help.html.haml"
+ - "app/views/projects/settings/ci_cd/_badge.html.haml"
+ - "app/views/projects/settings/ci_cd/_form.html.haml"
+ - "app/views/projects/stage/_stage.html.haml"
+ - "app/views/projects/tags/index.html.haml"
+ - "app/views/projects/tags/new.html.haml"
+ - "app/views/projects/tags/releases/edit.html.haml"
+ - "app/views/projects/tree/_tree_row.html.haml"
+ - "app/views/projects/tree/_truncated_notice_tree_row.html.haml"
+ - "app/views/projects/triggers/_content.html.haml"
+ - "app/views/projects/triggers/_form.html.haml"
+ - "app/views/projects/triggers/_index.html.haml"
+ - "app/views/projects/triggers/_trigger.html.haml"
+ - "app/views/projects/triggers/edit.html.haml"
+ - "app/views/projects/wikis/_new.html.haml"
+ - "app/views/projects/wikis/_pages_wiki_page.html.haml"
+ - "app/views/projects/wikis/edit.html.haml"
+ - "app/views/projects/wikis/history.html.haml"
+ - "app/views/repository_check_mailer/notify.html.haml"
+ - "app/views/search/_form.html.haml"
+ - "app/views/search/results/_issue.html.haml"
+ - "app/views/search/results/_note.html.haml"
+ - "app/views/search/results/_snippet_blob.html.haml"
+ - "app/views/search/results/_snippet_title.html.haml"
+ - "app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml"
+ - "app/views/shared/_commit_message_container.html.haml"
+ - "app/views/shared/_confirm_modal.html.haml"
+ - "app/views/shared/_delete_label_modal.html.haml"
+ - "app/views/shared/_group_form.html.haml"
+ - "app/views/shared/_group_tips.html.haml"
+ - "app/views/shared/_milestone_expired.html.haml"
+ - "app/views/shared/_no_password.html.haml"
+ - "app/views/shared/_no_ssh.html.haml"
+ - "app/views/shared/_outdated_browser.html.haml"
+ - "app/views/shared/_personal_access_tokens_created_container.html.haml"
+ - "app/views/shared/_personal_access_tokens_table.html.haml"
+ - "app/views/shared/_ping_consent.html.haml"
+ - "app/views/shared/_project_limit.html.haml"
+ - "app/views/shared/_service_settings.html.haml"
+ - "app/views/shared/boards/components/_board.html.haml"
+ - "app/views/shared/boards/components/_sidebar.html.haml"
+ - "app/views/shared/boards/components/sidebar/_due_date.html.haml"
+ - "app/views/shared/boards/components/sidebar/_labels.html.haml"
+ - "app/views/shared/boards/components/sidebar/_milestone.html.haml"
+ - "app/views/shared/empty_states/_priority_labels.html.haml"
+ - "app/views/shared/hook_logs/_content.html.haml"
+ - "app/views/shared/issuable/_assignees.html.haml"
+ - "app/views/shared/issuable/_board_create_list_dropdown.html.haml"
+ - "app/views/shared/issuable/_bulk_update_sidebar.html.haml"
+ - "app/views/shared/issuable/_close_reopen_report_toggle.html.haml"
+ - "app/views/shared/issuable/_form.html.haml"
+ - "app/views/shared/issuable/_search_bar.html.haml"
+ - "app/views/shared/issuable/_sidebar.html.haml"
+ - "app/views/shared/issuable/form/_default_templates.html.haml"
+ - "app/views/shared/issuable/form/_issue_assignee.html.haml"
+ - "app/views/shared/issuable/form/_template_selector.html.haml"
+ - "app/views/shared/issuable/form/_title.html.haml"
+ - "app/views/shared/labels/_form.html.haml"
+ - "app/views/shared/members/_member.html.haml"
+ - "app/views/shared/milestones/_form_dates.html.haml"
+ - "app/views/shared/milestones/_issuable.html.haml"
+ - "app/views/shared/milestones/_milestone.html.haml"
+ - "app/views/shared/milestones/_sidebar.html.haml"
+ - "app/views/shared/milestones/_top.html.haml"
+ - "app/views/shared/notes/_hints.html.haml"
+ - "app/views/shared/notes/_note.html.haml"
+ - "app/views/shared/notifications/_button.html.haml"
+ - "app/views/shared/notifications/_custom_notifications.html.haml"
+ - "app/views/shared/notifications/_new_button.html.haml"
+ - "app/views/shared/notifications/_notification_dropdown.html.haml"
+ - "app/views/shared/plugins/_index.html.haml"
+ - "app/views/shared/projects/_dropdown.html.haml"
+ - "app/views/shared/projects/_list.html.haml"
+ - "app/views/shared/projects/_project.html.haml"
+ - "app/views/shared/runners/_runner_description.html.haml"
+ - "app/views/shared/runners/show.html.haml"
+ - "app/views/shared/snippets/_embed.html.haml"
+ - "app/views/shared/snippets/_header.html.haml"
+ - "app/views/shared/snippets/_snippet.html.haml"
+ - "app/views/shared/tokens/_scopes_list.html.haml"
+ - "app/views/shared/web_hooks/_form.html.haml"
+ - "app/views/shared/web_hooks/_test_button.html.haml"
+ - "app/views/u2f/_authenticate.html.haml"
+ - "app/views/u2f/_register.html.haml"
+ - "app/views/users/_deletion_guidance.html.haml"
+ - "ee/app/views/admin/_namespace_plan_info.html.haml"
+ - "ee/app/views/admin/application_settings/_elasticsearch_form.html.haml"
+ - "ee/app/views/admin/application_settings/_slack.html.haml"
+ - "ee/app/views/admin/application_settings/_snowplow.html.haml"
+ - "ee/app/views/admin/application_settings/_templates.html.haml"
+ - "ee/app/views/admin/audit_logs/index.html.haml"
+ - "ee/app/views/admin/dashboard/stats.html.haml"
+ - "ee/app/views/admin/emails/show.html.haml"
+ - "ee/app/views/admin/geo/nodes/edit.html.haml"
+ - "ee/app/views/admin/geo/nodes/new.html.haml"
+ - "ee/app/views/admin/geo/projects/_registry_failed.html.haml"
+ - "ee/app/views/admin/geo/projects/_registry_never.html.haml"
+ - "ee/app/views/admin/licenses/_breakdown.html.haml"
+ - "ee/app/views/admin/licenses/_upload_trial_license.html.haml"
+ - "ee/app/views/admin/licenses/missing.html.haml"
+ - "ee/app/views/admin/licenses/new.html.haml"
+ - "ee/app/views/admin/licenses/show.html.haml"
+ - "ee/app/views/admin/monitoring/ee/_nav.html.haml"
+ - "ee/app/views/admin/projects/_shared_runner_status.html.haml"
+ - "ee/app/views/admin/push_rules/show.html.haml"
+ - "ee/app/views/admin/users/_limits.html.haml"
+ - "ee/app/views/admin/users/_user_detail_note.html.haml"
+ - "ee/app/views/dashboard/projects/_blank_state_ee_trial.html.haml"
+ - "ee/app/views/errors/kerberos_denied.html.haml"
+ - "ee/app/views/groups/analytics/show.html.haml"
+ - "ee/app/views/groups/audit_events/index.html.haml"
+ - "ee/app/views/groups/ee/_settings_nav.html.haml"
+ - "ee/app/views/groups/epics/_epic.html.haml"
+ - "ee/app/views/groups/group_members/_ldap_sync.html.haml"
+ - "ee/app/views/groups/group_members/_sync_button.html.haml"
+ - "ee/app/views/groups/hooks/_project_hook.html.haml"
+ - "ee/app/views/groups/hooks/index.html.haml"
+ - "ee/app/views/groups/ldap_group_links/index.html.haml"
+ - "ee/app/views/groups/pipeline_quota/index.html.haml"
+ - "ee/app/views/jira_connect/subscriptions/index.html.haml"
+ - "ee/app/views/layouts/jira_connect.html.haml"
+ - "ee/app/views/layouts/nav/ee/_epic_link.html.haml"
+ - "ee/app/views/layouts/nav/ee/admin/_new_monitoring_sidebar.html.haml"
+ - "ee/app/views/layouts/service_desk.html.haml"
+ - "ee/app/views/ldap_group_links/_form.html.haml"
+ - "ee/app/views/ldap_group_links/_ldap_group_link.html.haml"
+ - "ee/app/views/ldap_group_links/_ldap_group_links.html.haml"
+ - "ee/app/views/ldap_group_links/_ldap_group_links_show.html.haml"
+ - "ee/app/views/ldap_group_links/_ldap_group_links_synchronizations.html.haml"
+ - "ee/app/views/namespaces/_shared_runner_status.html.haml"
+ - "ee/app/views/namespaces/_shared_runners_minutes_setting.html.haml"
+ - "ee/app/views/namespaces/pipelines_quota/_extra_shared_runners_minutes_quota.html.haml"
+ - "ee/app/views/namespaces/pipelines_quota/_list.haml"
+ - "ee/app/views/notify/approved_merge_request_email.html.haml"
+ - "ee/app/views/notify/epic_status_changed_email.html.haml"
+ - "ee/app/views/notify/issues_csv_email.html.haml"
+ - "ee/app/views/notify/new_review_email.html.haml"
+ - "ee/app/views/notify/prometheus_alert_fired_email.html.haml"
+ - "ee/app/views/notify/send_admin_notification.html.haml"
+ - "ee/app/views/notify/send_unsubscribed_notification.html.haml"
+ - "ee/app/views/notify/unapproved_merge_request_email.html.haml"
+ - "ee/app/views/oauth/geo_auth/error.html.haml"
+ - "ee/app/views/profiles/pipeline_quota/index.haml"
+ - "ee/app/views/projects/audit_events/index.html.haml"
+ - "ee/app/views/projects/blob/_owners.html.haml"
+ - "ee/app/views/projects/commits/_mirror_status.html.haml"
+ - "ee/app/views/projects/feature_flags/_configure_feature_flags_modal.html.haml"
+ - "ee/app/views/projects/issues/_issue_weight.html.haml"
+ - "ee/app/views/projects/issues/_related_issues.html.haml"
+ - "ee/app/views/projects/issues/export_csv/_modal.html.haml"
+ - "ee/app/views/projects/jobs/_shared_runner_limit_warning.html.haml"
+ - "ee/app/views/projects/merge_requests/_approvals_count.html.haml"
+ - "ee/app/views/projects/merge_requests/widget/open/_geo.html.haml"
+ - "ee/app/views/projects/mirrors/_mirrored_repositories_count.html.haml"
+ - "ee/app/views/projects/protected_branches/ee/_create_protected_branch.html.haml"
+ - "ee/app/views/projects/protected_branches/ee/_dropdown.html.haml"
+ - "ee/app/views/projects/protected_branches/ee/_fallback_update_protected_branch.html.haml"
+ - "ee/app/views/projects/protected_tags/_protected_tag_extra_create_access_levels.haml"
+ - "ee/app/views/projects/protected_tags/ee/_create_protected_tag.html.haml"
+ - "ee/app/views/projects/push_rules/_index.html.haml"
+ - "ee/app/views/projects/services/gitlab_slack_application/_help.html.haml"
+ - "ee/app/views/projects/services/gitlab_slack_application/_slack_integration_form.html.haml"
+ - "ee/app/views/projects/services/prometheus/_metrics.html.haml"
+ - "ee/app/views/projects/settings/slacks/edit.html.haml"
+ - "ee/app/views/shared/_additional_email_text.html.haml"
+ - "ee/app/views/shared/_geo_info_modal.html.haml"
+ - "ee/app/views/shared/_mirror_update_button.html.haml"
+ - "ee/app/views/shared/_shared_runners_minutes_limit.html.haml"
+ - "ee/app/views/shared/audit_events/_event_table.html.haml"
+ - "ee/app/views/shared/boards/components/_list_weight.html.haml"
+ - "ee/app/views/shared/boards/components/sidebar/_epic.html.haml"
+ - "ee/app/views/shared/ee/_import_form.html.haml"
+ - "ee/app/views/shared/epic/_search_bar.html.haml"
+ - "ee/app/views/shared/issuable/_approvals.html.haml"
+ - "ee/app/views/shared/issuable/_board_create_list_dropdown.html.haml"
+ - "ee/app/views/shared/issuable/_filter_weight.html.haml"
+ - "ee/app/views/shared/issuable/_sidebar_item_epic.haml"
+ - "ee/app/views/shared/members/ee/_ldap_tag.html.haml"
+ - "ee/app/views/shared/members/ee/_override_member_buttons.html.haml"
+ - "ee/app/views/shared/members/ee/_sso_badge.html.haml"
+ - "ee/app/views/shared/milestones/_burndown.html.haml"
+ - "ee/app/views/shared/milestones/_weight.html.haml"
+ - "ee/app/views/shared/promotions/_promote_audit_events.html.haml"
+ - "ee/app/views/shared/promotions/_promote_burndown_charts.html.haml"
+ - "ee/app/views/shared/promotions/_promote_csv_export.html.haml"
+ - "ee/app/views/shared/promotions/_promote_issue_weights.html.haml"
+ - "ee/app/views/shared/promotions/_promote_repository_features.html.haml"
+ - "ee/app/views/shared/promotions/_promote_servicedesk.html.haml"
+ - "ee/app/views/shared/push_rules/_form.html.haml"
+ - "ee/app/views/unsubscribes/show.html.haml"
+ - "ee/app/views/admin/users/_auditor_access_level_radio.html.haml"
+ - "ee/app/views/admin/users/_auditor_user_badge.html.haml"
+ - "ee/app/views/projects/protected_branches/_update_protected_branch.html.haml"
diff --git a/.pkgr.yml b/.pkgr.yml
index 10bcd7bd4bd..2e741f41a9e 100644
--- a/.pkgr.yml
+++ b/.pkgr.yml
@@ -3,8 +3,8 @@ group: git
services:
- postgres
before_precompile: ./bin/pkgr_before_precompile.sh
-env:
- - SKIP_STORAGE_VALIDATION=true
+env:
+ - SKIP_STORAGE_VALIDATION=true
targets:
debian-7: &wheezy
build_dependencies:
diff --git a/.rubocop.yml b/.rubocop.yml
index aa49f41ebf4..e5fe527e611 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -75,6 +75,7 @@ Naming/FileName:
- 'qa/spec/**/*'
- 'qa/qa/specs/**/*'
- 'qa/bin/*'
+ - 'ee/bin/*'
- 'config/**/*'
- 'ee/config/**/*'
- 'lib/generators/**/*'
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 77ad4753c84..63b1685feda 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -1,42 +1,154 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
-# on 2018-01-18 18:23:26 +0100 using RuboCop version 0.52.1.
+# on 2019-05-04 16:01:00 +0000 using RuboCop version 0.68.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
-# Offense count: 181
+# Offense count: 264
Capybara/CurrentPathExpectation:
Enabled: false
-# Offense count: 167
+# Offense count: 1097
# Cop supports --auto-correct.
-Layout/EmptyLinesAroundArguments:
+# Configuration parameters: EnforcedStyle, IndentationWidth.
+# SupportedStyles: with_first_argument, with_fixed_indentation
+Layout/AlignArguments:
Enabled: false
-# Offense count: 83
+# Offense count: 824
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
+# SupportedHashRocketStyles: key, separator, table
+# SupportedColonStyles: key, separator, table
+# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
+Layout/AlignHash:
+ Enabled: false
+
+# Offense count: 13
+# Cop supports --auto-correct.
+Layout/ClosingHeredocIndentation:
+ Exclude:
+ - 'app/graphql/mutations/merge_requests/set_wip.rb'
+ - 'ee/db/geo/migrate/20180322062741_migrate_ci_job_artifacts_to_separate_registry.rb'
+ - 'ee/db/migrate/20160204190809_update_jenkins_service_category.rb'
+ - 'ee/lib/gitlab/background_migration/prune_orphaned_geo_events.rb'
+ - 'ee/lib/gitlab/geo/health_check.rb'
+ - 'lib/gitlab/background_migration/populate_untracked_uploads.rb'
+ - 'qa/qa/service/kubernetes_cluster.rb'
+ - 'spec/features/merge_request/user_sees_diff_spec.rb'
+ - 'spec/lib/gitlab/asciidoc_spec.rb'
+ - 'spec/lib/gitlab/checks/project_moved_spec.rb'
+ - 'spec/rubocop/cop/active_record_association_reload_spec.rb'
+ - 'spec/services/task_list_toggle_service_spec.rb'
+
+# Offense count: 14
+# Cop supports --auto-correct.
+Layout/ClosingParenthesisIndentation:
+ Exclude:
+ - 'db/post_migrate/20180704145007_update_project_indexes.rb'
+ - 'ee/db/geo/migrate/20180405074130_add_partial_index_project_repository_verification.rb'
+ - 'ee/db/migrate/20180308234102_add_partial_index_to_project_repository_states_checksum_columns.rb'
+ - 'ee/db/post_migrate/20180605213516_fix_partial_index_to_project_repository_states_checksum_columns.rb'
+ - 'ee/lib/ee/gitlab/usage_data.rb'
+ - 'spec/services/issues/resolve_discussions_spec.rb'
+ - 'spec/services/projects/update_service_spec.rb'
+ - 'spec/support/helpers/stub_object_storage.rb'
+ - 'spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb'
+
+# Offense count: 2
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: leading, trailing
+Layout/DotPosition:
+ Exclude:
+ - 'app/models/concerns/relative_positioning.rb'
+ - 'app/models/group.rb'
+
+# Offense count: 69
+# Cop supports --auto-correct.
+Layout/EmptyLinesAroundArguments:
+ Exclude:
+ - 'app/models/concerns/discussion_on_diff.rb'
+ - 'app/models/concerns/resolvable_discussion.rb'
+ - 'app/models/diff_discussion.rb'
+ - 'app/models/discussion.rb'
+ - 'ee/app/helpers/license_helper.rb'
+ - 'ee/spec/models/geo/project_registry_spec.rb'
+ - 'lib/banzai/pipeline/broadcast_message_pipeline.rb'
+ - 'lib/banzai/pipeline/gfm_pipeline.rb'
+ - 'lib/banzai/pipeline/single_line_pipeline.rb'
+ - 'spec/features/markdown/copy_as_gfm_spec.rb'
+
+# Offense count: 160
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: special_inside_parentheses, consistent, align_brackets
-Layout/IndentArray:
+Layout/IndentFirstArrayElement:
Enabled: false
-# Offense count: 237
+# Offense count: 631
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: special_inside_parentheses, consistent, align_braces
-Layout/IndentHash:
+Layout/IndentFirstHashElement:
Enabled: false
-# Offense count: 93
+# Offense count: 5
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyle, IndentationWidth.
+# SupportedStyles: consistent, align_parentheses
+Layout/IndentFirstParameter:
+ Exclude:
+ - 'app/models/ci/pipeline_schedule.rb'
+ - 'lib/gitlab/cross_project_access.rb'
+ - 'lib/gitlab/data_builder/push.rb'
+ - 'spec/support/helpers/repo_helpers.rb'
+ - 'spec/support/helpers/stub_object_storage.rb'
+
+# Offense count: 5
+# Cop supports --auto-correct.
+Layout/LeadingBlankLines:
+ Exclude:
+ - 'app/workers/update_project_statistics_worker.rb'
+ - 'db/migrate/20161007073613_create_user_activities.rb'
+ - 'ee/spec/helpers/boards_helper_spec.rb'
+ - 'lib/tasks/yarn.rake'
+ - 'spec/javascripts/fixtures/merge_requests_diffs.rb'
+
+# Offense count: 30
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyle, IndentationWidth.
+# SupportedStyles: aligned, indented
+Layout/MultilineOperationIndentation:
+ Enabled: false
+
+# Offense count: 13
+# Cop supports --auto-correct.
+Layout/RescueEnsureAlignment:
+ Exclude:
+ - 'app/models/blob_viewer/dependency_manager.rb'
+ - 'app/models/ci/pipeline.rb'
+ - 'app/models/project.rb'
+ - 'app/services/prometheus/proxy_service.rb'
+ - 'app/workers/delete_stored_files_worker.rb'
+ - 'app/workers/reactive_caching_worker.rb'
+ - 'config/initializers/1_settings.rb'
+ - 'config/initializers/trusted_proxies.rb'
+ - 'ee/db/migrate/20151113115819_canonicalize_kerberos_identities.rb'
+ - 'lib/gitlab/background_migration/archive_legacy_traces.rb'
+ - 'lib/gitlab/highlight.rb'
+ - 'lib/tasks/gitlab/lfs/migrate.rake'
+
+# Offense count: 344
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: require_no_space, require_space
Layout/SpaceInLambdaLiteral:
Enabled: false
-# Offense count: 327
+# Offense count: 583
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters.
# SupportedStyles: space, no_space
@@ -44,20 +156,27 @@ Layout/SpaceInLambdaLiteral:
Layout/SpaceInsideBlockBraces:
Enabled: false
-# Offense count: 156
+# Offense count: 255
# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: space, no_space
Layout/SpaceInsideParens:
Enabled: false
-# Offense count: 26
+# Offense count: 1
+Lint/DisjunctiveAssignmentInConstructor:
+ Exclude:
+ - 'app/models/uploads/base.rb'
+
+# Offense count: 19
Lint/DuplicateMethods:
Exclude:
- - 'app/models/application_setting.rb'
- 'app/models/commit.rb'
- 'app/models/note.rb'
- - 'app/services/merge_requests/merge_service.rb'
- 'lib/bitbucket/representation/repo.rb'
- 'lib/declarative_policy/base.rb'
+ - 'lib/gitlab/auth/ldap/person.rb'
+ - 'lib/gitlab/auth/o_auth/user.rb'
- 'lib/gitlab/ci/build/artifacts/metadata/entry.rb'
- 'lib/gitlab/cycle_analytics/base_event_fetcher.rb'
- 'lib/gitlab/diff/formatters/base_formatter.rb'
@@ -65,22 +184,34 @@ Lint/DuplicateMethods:
- 'lib/gitlab/git/repository.rb'
- 'lib/gitlab/git/tree.rb'
- 'lib/gitlab/git/wiki_page.rb'
- - 'lib/gitlab/auth/ldap/person.rb'
- - 'lib/gitlab/auth/o_auth/user.rb'
-# Offense count: 4
+# Offense count: 2
Lint/InterpolationCheck:
Exclude:
- 'spec/features/issues/filtered_search/filter_issues_spec.rb'
- - 'spec/features/users_spec.rb'
- 'spec/services/quick_actions/interpret_service_spec.rb'
-# Offense count: 206
+# Offense count: 326
# Configuration parameters: MaximumRangeSize.
Lint/MissingCopEnableDirective:
Enabled: false
-# Offense count: 9
+# Offense count: 2
+# Cop supports --auto-correct.
+# Configuration parameters: Whitelist.
+# Whitelist: present?, blank?, presence, try, try!
+Lint/SafeNavigationConsistency:
+ Exclude:
+ - 'lib/gitlab/gpg/commit.rb'
+
+# Offense count: 2
+# Cop supports --auto-correct.
+Lint/ToJSON:
+ Exclude:
+ - 'lib/gitlab/cycle_analytics/usage_data.rb'
+ - 'lib/gitlab/template/base_template.rb'
+
+# Offense count: 7
Lint/UriEscapeUnescape:
Exclude:
- 'app/controllers/application_controller.rb'
@@ -88,13 +219,25 @@ Lint/UriEscapeUnescape:
- 'spec/lib/google_api/auth_spec.rb'
- 'spec/requests/api/files_spec.rb'
- 'spec/requests/api/internal_spec.rb'
- - 'spec/requests/api/issues_spec.rb'
# Offense count: 1
-# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
+# Configuration parameters: CheckForMethodsWithNoSideEffects.
+Lint/Void:
+ Exclude:
+ - 'lib/gitlab/git/diff_collection.rb'
+
+# Offense count: 158
+# Cop supports --auto-correct.
+# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# URISchemes: http, https
Metrics/LineLength:
- Max: 1310
+ Max: 176
+
+# Offense count: 94
+# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms.
+# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
+Naming/FileName:
+ Enabled: false
# Offense count: 11
# Configuration parameters: EnforcedStyle.
@@ -107,61 +250,85 @@ Naming/HeredocDelimiterCase:
- 'spec/support/helpers/repo_helpers.rb'
- 'spec/support/helpers/seed_repo.rb'
-# Offense count: 112
+# Offense count: 197
# Configuration parameters: Blacklist.
-# Blacklist: END, (?-mix:EO[A-Z]{1})
+# Blacklist: (?-mix:(^|\s)(EO[A-Z]{1}|END)(\s|$))
Naming/HeredocDelimiterNaming:
Enabled: false
+# Offense count: 125
+# Cop supports --auto-correct.
+# Configuration parameters: PreferredName.
+Naming/RescuedExceptionsVariableName:
+ Enabled: false
+
+# Offense count: 6
+# Cop supports --auto-correct.
+Performance/InefficientHashSearch:
+ Exclude:
+ - 'app/controllers/concerns/sessionless_authentication.rb'
+ - 'app/models/note.rb'
+ - 'app/models/user_preference.rb'
+ - 'ee/app/models/ee/project.rb'
+ - 'lib/gitlab/import_export/members_mapper.rb'
+ - 'qa/spec/spec_helper.rb'
+
+# Offense count: 3
+# Cop supports --auto-correct.
+Performance/ReverseEach:
+ Exclude:
+ - 'app/models/commit.rb'
+ - 'db/migrate/20190222051615_add_indexes_for_merge_request_diffs_query.rb'
+ - 'lib/gitlab/profiler.rb'
-# Offense count: 3821
+# Offense count: 7081
# Configuration parameters: Prefixes.
# Prefixes: when, with, without
RSpec/ContextWording:
Enabled: false
-# Offense count: 293
+# Offense count: 407
+# Cop supports --auto-correct.
RSpec/EmptyLineAfterFinalLet:
Enabled: false
-# Offense count: 188
+# Offense count: 232
+# Cop supports --auto-correct.
RSpec/EmptyLineAfterSubject:
Enabled: false
-# Offense count: 258
+# Offense count: 719
+# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: method_call, block
RSpec/ExpectChange:
Enabled: false
-# Offense count: 221
+# Offense count: 512
RSpec/ExpectInHook:
Enabled: false
-# Offense count: 19
+# Offense count: 10
+# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: it_behaves_like, it_should_behave_like
RSpec/ItBehavesLike:
Exclude:
- 'spec/lib/gitlab/git/commit_spec.rb'
- 'spec/lib/gitlab/git/repository_spec.rb'
- - 'spec/lib/gitlab/shell_spec.rb'
- 'spec/services/notification_service_spec.rb'
- - 'spec/workers/git_garbage_collect_worker_spec.rb'
-# Offense count: 5
+# Offense count: 3
RSpec/IteratedExpectation:
Exclude:
- 'spec/features/admin/admin_settings_spec.rb'
- - 'spec/features/merge_requests/diff_notes_resolve_spec.rb'
- - 'spec/features/projects/awards/user_interacts_with_awards_in_issue_spec.rb'
- 'spec/lib/gitlab/gitlab_import/client_spec.rb'
- 'spec/lib/gitlab/legacy_github_import/client_spec.rb'
-# Offense count: 75
+# Offense count: 68
+# Cop supports --auto-correct.
RSpec/LetBeforeExamples:
Exclude:
- - 'spec/controllers/projects/commit_controller_spec.rb'
- 'spec/lib/banzai/filter/issue_reference_filter_spec.rb'
- 'spec/lib/banzai/filter/user_reference_filter_spec.rb'
- 'spec/lib/gitlab/email/handler/create_issue_handler_spec.rb'
@@ -170,12 +337,11 @@ RSpec/LetBeforeExamples:
- 'spec/models/commit_range_spec.rb'
- 'spec/models/milestone_spec.rb'
- 'spec/models/project_services/packagist_service_spec.rb'
- - 'spec/models/repository_spec.rb'
- 'spec/rubocop/cop/migration/update_column_in_batches_spec.rb'
- 'spec/serializers/pipeline_details_entity_spec.rb'
- - 'spec/views/ci/lints/show.html.haml_spec.rb'
# Offense count: 1
+# Cop supports --auto-correct.
RSpec/MultipleSubjects:
Exclude:
- 'spec/services/merge_requests/create_from_issue_service_spec.rb'
@@ -188,95 +354,136 @@ RSpec/OverwritingSetup:
- 'spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb'
- 'spec/services/notes/quick_actions_service_spec.rb'
-# Offense count: 965
+# Offense count: 1828
+# Cop supports --auto-correct.
# Configuration parameters: Strict, EnforcedStyle.
# SupportedStyles: inflected, explicit
RSpec/PredicateMatcher:
Enabled: false
-# Offense count: 35
+# Offense count: 57
RSpec/RepeatedExample:
Enabled: false
-# Offense count: 140
+# Offense count: 474
+# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: and_return, block
RSpec/ReturnFromStub:
Enabled: false
-# Offense count: 112
+# Offense count: 188
RSpec/ScatteredLet:
Enabled: false
-# Offense count: 22
+# Offense count: 10
RSpec/ScatteredSetup:
Exclude:
- 'spec/controllers/projects/templates_controller_spec.rb'
- 'spec/lib/gitlab/bitbucket_import/importer_spec.rb'
- - 'spec/lib/gitlab/git/env_spec.rb'
- 'spec/requests/api/jobs_spec.rb'
- 'spec/services/projects/create_service_spec.rb'
# Offense count: 1
+# Cop supports --auto-correct.
RSpec/SharedContext:
Exclude:
- 'spec/features/admin/admin_groups_spec.rb'
-# Offense count: 5
+# Offense count: 4
RSpec/VoidExpect:
Exclude:
- - 'spec/features/projects/artifacts/download_spec.rb'
- 'spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb'
- 'spec/models/ci/group_spec.rb'
- 'spec/models/ci/runner_spec.rb'
- 'spec/services/users/destroy_service_spec.rb'
-# Offense count: 41
+# Offense count: 8
+# Cop supports --auto-correct.
+Rails/BelongsTo:
+ Exclude:
+ - 'app/models/deployment.rb'
+ - 'app/models/environment.rb'
+ - 'ee/app/models/prometheus_alert.rb'
+ - 'ee/app/models/prometheus_alert_event.rb'
+
+# Offense count: 80
# Configuration parameters: Include.
# Include: db/migrate/*.rb
Rails/CreateTableWithTimestamps:
Enabled: false
-# Offense count: 155
+# Offense count: 222
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: slashes, arguments
Rails/FilePath:
Enabled: false
-# Offense count: 121
+# Offense count: 167
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/HasManyOrHasOneDependent:
Enabled: false
-# Offense count: 157
+# Offense count: 40
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: numeric, symbolic
+Rails/HttpStatus:
+ Enabled: false
+
+# Offense count: 2
+# Configuration parameters: Include.
+# Include: app/controllers/**/*.rb
+Rails/IgnoredSkipActionFilterOption:
+ Exclude:
+ - 'app/controllers/projects/snippets_controller.rb'
+ - 'app/controllers/snippets_controller.rb'
+
+# Offense count: 87
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/InverseOf:
Enabled: false
-# Offense count: 48
+# Offense count: 46
# Configuration parameters: Include.
# Include: app/controllers/**/*.rb
Rails/LexicallyScopedActionFilter:
Enabled: false
-# Offense count: 14
+# Offense count: 4
+# Cop supports --auto-correct.
+Rails/LinkToBlank:
+ Exclude:
+ - 'app/helpers/projects_helper.rb'
+ - 'app/helpers/wiki_helper.rb'
+ - 'ee/app/helpers/ee/user_callouts_helper.rb'
+ - 'ee/app/helpers/license_helper.rb'
+
+# Offense count: 11
# Cop supports --auto-correct.
Rails/Presence:
Exclude:
- - 'app/controllers/projects/blob_controller.rb'
- 'app/models/ci/pipeline.rb'
- 'app/models/clusters/platforms/kubernetes.rb'
- 'app/models/concerns/mentionable.rb'
- - 'app/models/concerns/token_authenticatable.rb'
- 'app/models/project_services/hipchat_service.rb'
- 'app/models/project_services/irker_service.rb'
- 'app/models/project_services/jira_service.rb'
- 'app/models/project_services/kubernetes_service.rb'
- 'app/models/project_services/packagist_service.rb'
- 'app/models/wiki_page.rb'
- - 'lib/gitlab/git/hook.rb'
- 'lib/gitlab/github_import/importer/releases_importer.rb'
+# Offense count: 1
+# Cop supports --auto-correct.
+# Configuration parameters: Include.
+# Include: app/models/**/*.rb
+Rails/RedundantAllowNil:
+ Exclude:
+ - 'app/models/application_setting.rb'
+
# Offense count: 2
# Configuration parameters: Include.
# Include: db/migrate/*.rb
@@ -284,8 +491,8 @@ Rails/ReversibleMigration:
Exclude:
- 'db/migrate/20160824103857_drop_unused_ci_tables.rb'
-# Offense count: 446
-# Configuration parameters: Blacklist.
+# Offense count: 860
+# Configuration parameters: Blacklist, Whitelist.
# Blacklist: decrement!, decrement_counter, increment!, increment_counter, toggle!, touch, update_all, update_attribute, update_column, update_columns, update_counters
Rails/SkipsModelValidations:
Enabled: false
@@ -297,21 +504,25 @@ Rails/UnknownEnv:
Exclude:
- 'db/migrate/20171124125748_populate_missing_merge_request_statuses.rb'
-# Offense count: 13
+# Offense count: 11
# Cop supports --auto-correct.
Security/YAMLLoad:
Exclude:
- - 'config/initializers/carrierwave.rb'
- 'lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb'
- 'lib/gitlab/redis/wrapper.rb'
- 'lib/system_check/incoming_email/imap_authentication_check.rb'
- 'spec/config/mail_room_spec.rb'
- 'spec/initializers/secret_token_spec.rb'
- 'spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb'
- - 'spec/models/clusters/platforms/kubernetes_spec.rb'
- 'spec/models/project_services/kubernetes_service_spec.rb'
-# Offense count: 64
+# Offense count: 34
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: inline, group
+Style/AccessModifierDeclarations:
+ Enabled: false
+
+# Offense count: 121
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: percent_q, bare_percent
@@ -324,17 +535,13 @@ Style/CommentedKeyword:
- 'lib/tasks/gitlab/backup.rake'
- 'spec/tasks/gitlab/backup_rake_spec.rb'
-# Offense count: 30
-Style/DateTime:
- Enabled: false
-
# Offense count: 1
# Cop supports --auto-correct.
Style/Dir:
Exclude:
- 'qa/qa.rb'
-# Offense count: 9
+# Offense count: 7
# Cop supports --auto-correct.
Style/EachWithObject:
Exclude:
@@ -345,46 +552,42 @@ Style/EachWithObject:
- 'lib/gitlab/i18n/po_linter.rb'
- 'lib/gitlab/import_export/members_mapper.rb'
- 'lib/gitlab/import_export/relation_factory.rb'
- - 'scripts/static-analysis'
-# Offense count: 24
+# Offense count: 34
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: empty, nil, both
Style/EmptyElse:
Enabled: false
-# Offense count: 14
+# Offense count: 11
# Cop supports --auto-correct.
Style/EmptyLambdaParameter:
Exclude:
- 'app/models/ci/build.rb'
- 'app/models/ci/runner.rb'
-# Offense count: 12
+# Offense count: 9
# Cop supports --auto-correct.
Style/EmptyLiteral:
Exclude:
- - 'features/steps/project/commits/commits.rb'
- 'lib/gitlab/fogbugz_import/importer.rb'
- 'lib/gitlab/git/diff_collection.rb'
- 'lib/gitlab/gitaly_client.rb'
- - 'scripts/trigger-build'
- - 'spec/features/merge_requests/versions_spec.rb'
- 'spec/helpers/merge_requests_helper_spec.rb'
- 'spec/lib/gitlab/request_context_spec.rb'
- 'spec/lib/gitlab/workhorse_spec.rb'
- 'spec/requests/api/jobs_spec.rb'
- 'spec/support/shared_examples/chat_slash_commands_shared_examples.rb'
-# Offense count: 102
+# Offense count: 180
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: compact, expanded
Style/EmptyMethod:
Enabled: false
-# Offense count: 23
+# Offense count: 40
# Cop supports --auto-correct.
Style/Encoding:
Enabled: false
@@ -394,52 +597,52 @@ Style/EvalWithLocation:
Exclude:
- 'app/models/service.rb'
-# Offense count: 35
+# Offense count: 203
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: format, sprintf, percent
Style/FormatString:
Enabled: false
-# Offense count: 384
+# Offense count: 669
# Configuration parameters: MinBodyLength.
Style/GuardClause:
Enabled: false
-# Offense count: 22
+# Offense count: 27
Style/IfInsideElse:
Enabled: false
-# Offense count: 809
+# Offense count: 1346
# Cop supports --auto-correct.
Style/IfUnlessModifier:
Enabled: false
-# Offense count: 75
+# Offense count: 186
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: line_count_dependent, lambda, literal
Style/Lambda:
Enabled: false
-# Offense count: 11
+# Offense count: 3
# Cop supports --auto-correct.
Style/LineEndConcatenation:
Exclude:
- - 'app/helpers/tree_helper.rb'
- - 'spec/features/issuables/markdown_references_spec.rb'
- - 'spec/lib/gitlab/checks/project_moved_spec.rb'
- 'spec/lib/gitlab/gfm/reference_rewriter_spec.rb'
- 'spec/lib/gitlab/incoming_email_spec.rb'
# Offense count: 18
-Style/MethodMissing:
+Style/MethodMissingSuper:
Enabled: false
-# Offense count: 7
+# Offense count: 18
+Style/MissingRespondToMissing:
+ Enabled: false
+
+# Offense count: 6
Style/MixinUsage:
Exclude:
- - 'features/support/env.rb'
- 'spec/factories/ci/builds.rb'
- 'spec/factories/ci/job_artifacts.rb'
- 'spec/factories/lfs_objects.rb'
@@ -447,59 +650,63 @@ Style/MixinUsage:
- 'spec/lib/gitlab/import_export/project_tree_restorer_spec.rb'
- 'spec/lib/gitlab/import_export/version_checker_spec.rb'
-# Offense count: 6
+# Offense count: 4
# Cop supports --auto-correct.
Style/MultilineIfModifier:
Exclude:
- 'app/helpers/snippets_helper.rb'
- 'app/models/project_wiki.rb'
- 'app/services/ci/process_pipeline_service.rb'
- - 'app/services/create_deployment_service.rb'
- 'lib/api/commit_statuses.rb'
- - 'lib/gitlab/ci/trace.rb'
-# Offense count: 25
+# Offense count: 72
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: literals, strict
+Style/MutableConstant:
+ Enabled: false
+
+# Offense count: 28
# Cop supports --auto-correct.
# Configuration parameters: Whitelist.
# Whitelist: be, be_a, be_an, be_between, be_falsey, be_kind_of, be_instance_of, be_truthy, be_within, eq, eql, end_with, include, match, raise_error, respond_to, start_with
Style/NestedParenthesizedCalls:
Enabled: false
-# Offense count: 19
+# Offense count: 31
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, MinBodyLength.
# SupportedStyles: skip_modifier_ifs, always
Style/Next:
Enabled: false
-# Offense count: 61
+# Offense count: 67
# Cop supports --auto-correct.
# Configuration parameters: EnforcedOctalStyle.
# SupportedOctalStyles: zero_with_o, zero_only
Style/NumericLiteralPrefix:
Enabled: false
-# Offense count: 114
+# Offense count: 186
# Cop supports --auto-correct.
-# Configuration parameters: AutoCorrect, EnforcedStyle.
+# Configuration parameters: AutoCorrect, EnforcedStyle, IgnoredMethods.
# SupportedStyles: predicate, comparison
Style/NumericPredicate:
Enabled: false
-# Offense count: 4
+# Offense count: 2
# Cop supports --auto-correct.
Style/OrAssignment:
Exclude:
- - 'app/models/concerns/token_authenticatable.rb'
- 'lib/api/commit_statuses.rb'
- 'lib/gitlab/project_transfer.rb'
-# Offense count: 50
+# Offense count: 79
# Cop supports --auto-correct.
Style/ParallelAssignment:
Enabled: false
-# Offense count: 917
+# Offense count: 1390
# Cop supports --auto-correct.
# Configuration parameters: PreferredDelimiters.
Style/PercentLiteralDelimiters:
@@ -521,25 +728,20 @@ Style/PerlBackrefs:
- 'lib/gitlab/search_results.rb'
- 'lib/gitlab/sherlock/query.rb'
-# Offense count: 87
+# Offense count: 129
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: compact, exploded
Style/RaiseArgs:
Enabled: false
-# Offense count: 9
+# Offense count: 3
# Cop supports --auto-correct.
Style/RedundantBegin:
Exclude:
- - 'app/controllers/projects/clusters/gcp_controller.rb'
- 'app/models/merge_request.rb'
- 'app/services/projects/import_service.rb'
- - 'lib/api/branches.rb'
- - 'lib/gitlab/current_settings.rb'
- - 'lib/gitlab/git/commit.rb'
- 'lib/gitlab/health_checks/base_abstract_check.rb'
- - 'lib/tasks/gitlab/task_helpers.rb'
# Offense count: 1
# Cop supports --auto-correct.
@@ -547,7 +749,7 @@ Style/RedundantConditional:
Exclude:
- 'lib/system_check/helpers.rb'
-# Offense count: 57
+# Offense count: 360
# Cop supports --auto-correct.
Style/RedundantFreeze:
Enabled: false
@@ -567,41 +769,36 @@ Style/RedundantReturn:
- 'lib/gitlab/utils.rb'
- 'lib/google_api/auth.rb'
-# Offense count: 460
+# Offense count: 700
# Cop supports --auto-correct.
Style/RedundantSelf:
Enabled: false
-# Offense count: 142
+# Offense count: 28
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, AllowInnerSlashes.
# SupportedStyles: slashes, percent_r, mixed
Style/RegexpLiteral:
- Enabled: true
- EnforcedStyle: mixed
- AllowInnerSlashes: false
+ Enabled: false
-# Offense count: 36
+# Offense count: 41
# Cop supports --auto-correct.
Style/RescueModifier:
Enabled: false
-# Offense count: 107
+# Offense count: 197
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: implicit, explicit
Style/RescueStandardError:
Enabled: false
-# Offense count: 8
+# Offense count: 5
# Cop supports --auto-correct.
Style/SelfAssignment:
Exclude:
- 'app/models/concerns/bulk_member_access_load.rb'
- 'app/serializers/base_serializer.rb'
- - 'app/services/notification_service.rb'
- - 'lib/api/runners.rb'
- - 'spec/features/merge_requests/diff_notes_resolve_spec.rb'
- 'spec/features/projects/clusters/interchangeability_spec.rb'
- 'spec/support/import_export/configuration_helper.rb'
@@ -612,7 +809,7 @@ Style/SingleLineMethods:
Exclude:
- 'lib/gitlab/ci/ansi2html.rb'
-# Offense count: 66
+# Offense count: 91
# Cop supports --auto-correct.
# Configuration parameters: .
# SupportedStyles: use_perl_names, use_english_names
@@ -625,21 +822,21 @@ Style/StderrPuts:
Exclude:
- 'config/initializers/rspec_profiling.rb'
-# Offense count: 45
+# Offense count: 65
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: single_quotes, double_quotes
Style/StringLiteralsInInterpolation:
Enabled: false
-# Offense count: 106
+# Offense count: 187
# Cop supports --auto-correct.
# Configuration parameters: IgnoredMethods.
# IgnoredMethods: respond_to, define_method
Style/SymbolProc:
Enabled: false
-# Offense count: 9
+# Offense count: 7
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, AllowSafeAssignment.
# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex
@@ -647,45 +844,65 @@ Style/TernaryParentheses:
Exclude:
- 'app/finders/projects_finder.rb'
- 'app/helpers/namespaces_helper.rb'
- - 'features/support/capybara.rb'
- 'lib/gitlab/ci/build/artifacts/metadata/entry.rb'
- 'spec/requests/api/pipeline_schedules_spec.rb'
- 'spec/support/capybara.rb'
-# Offense count: 17
+# Offense count: 3
# Cop supports --auto-correct.
-# Configuration parameters: AllowNamedUnderscoreVariables.
-Style/TrailingUnderscoreVariable:
+# Configuration parameters: EnforcedStyleForMultiline.
+# SupportedStylesForMultiline: comma, consistent_comma, no_comma
+Style/TrailingCommaInArguments:
Exclude:
- - 'app/controllers/admin/background_jobs_controller.rb'
- - 'app/controllers/invites_controller.rb'
- - 'app/helpers/tab_helper.rb'
- - 'lib/backup/manager.rb'
- - 'lib/gitlab/logger.rb'
- - 'lib/gitlab/upgrader.rb'
- - 'lib/system_check/app/migrations_are_up_check.rb'
- - 'lib/system_check/incoming_email/mail_room_running_check.rb'
- - 'lib/tasks/gitlab/check.rake'
- - 'lib/tasks/gitlab/task_helpers.rb'
- - 'spec/lib/gitlab/etag_caching/middleware_spec.rb'
- - 'spec/services/quick_actions/interpret_service_spec.rb'
+ - 'spec/features/markdown/copy_as_gfm_spec.rb'
-# Offense count: 4
+# Offense count: 10
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyleForMultiline.
+# SupportedStylesForMultiline: comma, consistent_comma, no_comma
+Style/TrailingCommaInArrayLiteral:
+ Exclude:
+ - 'ee/spec/models/project_spec.rb'
+ - 'spec/lib/gitlab/diff/position_tracer_spec.rb'
+ - 'spec/lib/gitlab/metrics/dashboard/processor_spec.rb'
+
+# Offense count: 2
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyleForMultiline.
+# SupportedStylesForMultiline: comma, consistent_comma, no_comma
+Style/TrailingCommaInHashLiteral:
+ Exclude:
+ - 'lib/gitlab/ci/ansi2html.rb'
+ - 'lib/gitlab/kubernetes.rb'
+
+# Offense count: 2
# Cop supports --auto-correct.
Style/UnlessElse:
Exclude:
- 'lib/backup/manager.rb'
- 'lib/gitlab/project_search_results.rb'
- - 'lib/tasks/gitlab/check.rake'
- - 'spec/features/issues/award_emoji_spec.rb'
-# Offense count: 31
+# Offense count: 10
+# Cop supports --auto-correct.
+Style/UnneededCondition:
+ Exclude:
+ - 'app/helpers/button_helper.rb'
+ - 'app/helpers/environment_helper.rb'
+ - 'app/models/project.rb'
+ - 'app/services/issuable/clone/base_service.rb'
+ - 'app/services/prometheus/adapter_service.rb'
+ - 'lib/gitlab/email/message/repository_push.rb'
+ - 'lib/gitlab/prometheus_client.rb'
+ - 'spec/lib/rspec_flaky/flaky_example_spec.rb'
+
+# Offense count: 73
# Cop supports --auto-correct.
Style/UnneededInterpolation:
Enabled: false
-# Offense count: 22840
-# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
-# URISchemes: http, https
-Metrics/LineLength:
- Max: 1310
+# Offense count: 2
+# Cop supports --auto-correct.
+Style/UnneededSort:
+ Exclude:
+ - 'app/models/concerns/resolvable_discussion.rb'
+ - 'lib/gitlab/highlight.rb'
diff --git a/.ruby-version b/.ruby-version
index aedc15bb0c6..ec1cf33c3f6 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-2.5.3
+2.6.3
diff --git a/.stylelintrc b/.stylelintrc
index 241d2c94a88..b0ace93e04f 100644
--- a/.stylelintrc
+++ b/.stylelintrc
@@ -2,7 +2,7 @@
"plugins":[
"./scripts/frontend/stylelint/stylelint-duplicate-selectors.js",
"./scripts/frontend/stylelint/stylelint-utility-classes.js",
- "stylelint-scss",
+ "stylelint-scss"
],
"rules":{
"at-rule-blacklist":[
@@ -64,7 +64,7 @@
"number-leading-zero":"always",
"number-no-trailing-zeros":true,
"property-no-unknown":true,
- "property-no-vendor-prefix":true,
+ "property-no-vendor-prefix": [true, { "ignoreProperties": ["user-select"] }],
"rule-empty-line-before":[
"always-multi-line",
{
@@ -94,7 +94,7 @@
{
"message":"Selector should be written in lowercase with hyphens (selector-class-pattern)",
"severity": "warning"
- },
+ }
],
"selector-list-comma-newline-after":"always",
"selector-max-compound-selectors":[3, { "severity": "warning" }],
@@ -104,8 +104,8 @@
"selector-pseudo-element-no-unknown":true,
"shorthand-property-no-redundant-values":true,
"string-quotes":"single",
- "value-no-vendor-prefix":[true, { ignoreValues: ["sticky"] }],
+ "value-no-vendor-prefix":[true, { "ignoreValues": ["sticky"] }],
"stylelint-gitlab/duplicate-selectors":[true,{ "severity": "warning" }],
- "stylelint-gitlab/utility-classes":[true,{ "severity": "warning" }],
+ "stylelint-gitlab/utility-classes":[true,{ "severity": "warning" }]
}
}
diff --git a/.yamllint b/.yamllint
new file mode 100644
index 00000000000..df7cdf404bc
--- /dev/null
+++ b/.yamllint
@@ -0,0 +1,7 @@
+---
+
+extends: default
+
+rules:
+ line-length: disable
+ document-start: disable
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 41506746c98..623e5d0acb9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,563 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 11.11.3 (2019-06-10)
+
+### Fixed (5 changes)
+
+- Fix invalid visibility string comparison in project import. !28612
+- Remove a default git depth in Pipelines for merge requests. !28926
+- Fix connection to Tiller error while uninstalling. !29131
+- Fix label click scrolling to top. !29202
+- Make OpenID Connect work without requiring a name. !29312
+
+
+## 11.11.2 (2019-06-04)
+
+### Fixed (7 changes)
+
+- Update SAST.gitlab-ci.yml - Add SAST_GITLEAKS_ENTROPY_LEVEL. !28607
+- Fix OmniAuth OAuth2Generic strategy not loading. !28680
+- Use source ref in pipeline webhook. !28772
+- Fix migration failure when groups are missing route. !29022
+- Stop two-step rebase from hanging when errors occur. !29068
+- Fix project settings not being able to update. !29097
+- Fix display of 'Promote to group label' button.
+
+### Other (1 change)
+
+- Fix input group height.
+
+
+## 11.11.0 (2019-05-22)
+
+### Security (1 change)
+
+- Destroy project remote mirrors instead of disabling. !27087
+
+### Fixed (74 changes, 19 of them are from the community)
+
+- Don't create a temp reference for branch comparisons within project. !24038
+- Fix some label links not appearing on group labels page and label title being a link on project labels page. !24060 (Tanya Pazitny)
+- Fix extra emails for custom notifications. !25607
+- Rewind IID on Ci::Pipelines. !26490
+- Fix duplicate merge request pipelines created by Sidekiq worker retry. !26643
+- Catch and report OpenSSL exceptions while fetching external configuration files in CI::Config. !26750 (Drew Cimino)
+- stop rendering download links for expired artifacts on the project tags page. !26753 (Drew Cimino)
+- Format extra help page text like wiki. !26782 (Bastian Blank)
+- Always show instance configuration link. !26783 (Bastian Blank)
+- Display maximum artifact size from runtime config. !26784 (Bastian Blank)
+- Resolve issue where list labels did not have the correct text color on creation. !26794 (Tucker Chapman)
+- Set release name when adding release notes to an existing tag. !26807
+- Fix the bug that the project statistics is not updated. !26854 (Hiroyuki Sato)
+- Client side changes for ListLastCommitsForTree response update. !26880
+- Fix api group visibility. !26896
+- Require all templates to use default stages. !26954
+- Remove a "reopen merge request button" on a "merged" merge request. !26965 (Hiroyuki Sato)
+- Fix misaligned image diff swipe view. !26969 (ftab)
+- Add badge-pill class on group member count. !27019
+- Remove leading / trailing spaces from heading when generating header ids. !27025 (Willian Balmant)
+- Respect updated_at attribute in notes produced by API calls. !27124 (Ben Gamari)
+- Fix GitHub project import visibility. !27133 (Daniel Wyatt)
+- Fixes actions dropdowns in environments page. !27160
+- Fixes create button background for Environments form. !27161
+- Display scoped labels in Issue Boards. !27164
+- Align UrlValidator to validate_url gem implementation. !27194 (Horatiu Eugen Vlad)
+- Resolve Web IDE template dropdown showing duplicates. !27237
+- Update GitLab Workhorse to v8.6.0. !27260
+- Only show in autocomplete when author active. !27292
+- Remove deadline for Git fsck. !27299
+- Show prioritized labels to guests. !27307
+- Properly expire all pipeline caches when pipeline is deleted. !27334
+- Replaced icon for external URL with doc-text icon. !27365
+- Add auto direction for issue title. !27378 (Ahmad Haghighi)
+- fix wiki search result links in titles. !27400 (khm)
+- Fix system notes timestamp when creating issue in the past. !27406
+- Fix approvals sometimes being reset after a merge request is rebased. !27446
+- Fix empty block in MR widget when user doesn't have permission. !27462
+- Fix wrong use of ActiveRecord in PoolRepository. !27464
+- Show proper preview for uploaded images in Web IDE. !27471
+- Resolve Renaming an image via Web IDE corrupts it. !27486
+- Clean up CarrierWave's import/export files. !27487
+- Fix autocomplete dropdown for usernames starting with period. !27533 (Jan Beckmann)
+- Disable password autocomplete in mirror repository form. !27542
+- Always use internal ID tables in development and production. !27544
+- Only show the "target branch has advanced" message when the merge request is open. !27588
+- Resolve Misalignment on suggested changes diff table. !27612
+- Update Workhorse to v8.7.0. !27630
+- Fix FE API and IDE handling of '/' relative_url_root. !27635
+- Hide ScopedBadge overflow notes. !27651
+- Fix base domain help text update. !27746
+- Upgrade letter_opener_web to support Rails 5.1. !27829
+- Fix webpack assets handling when relative url root is '/'. !27909
+- Fix IDE get file data with '/' as relative root. !27911
+- Allow a member to have an access level equal to parent group. !27913
+- Fix issuables state_id nil when importing projects from GitHub. !28027
+- Fix uploading of LFS tracked file through UI. !28052
+- Render Next badge only for gitlab.com. !28056
+- Fix update head pipeline process of Pipelines for merge requests. !28057
+- Fix visual issues in set status modal. !28147
+- Use a path for the related merge requests endpoint. !28171
+- disable SSH key validation in key details view. !28180 (Roger Meier)
+- Fix MR discussion border missing in chrome sometimes. !28185
+- Fix Error 500 when inviting user already present. !28198
+- Remove non-semantic use of `.row` in member listing controls. !28204
+- Properly handle LFS Batch API response in project import. !28223
+- Fix project visibility level validation. !28305 (Peter Marko)
+- Fix incorrect prefix used in new uploads for personal snippets. !28337
+- Fix Rugged get_tree_entries recursive flag not working. !28494
+- Fixes next badge being always visible.
+- Next badge must visible when canary flag is true.
+- Adds arrow icons to select option in CI/CD settings.
+- Vertically aligns the play button for stages.
+- Allow replying to individual notes from API.
+
+### Changed (19 changes, 3 of them are from the community)
+
+- Sort by due date and popularity in both directions for Issues and Merge requests. !25502 (Nermin Vehabovic)
+- Improve pipelines table spacing, add triggerer column. !26136
+- Allow extra arguments in helm commands when deploying the application in Auto-DevOps.gitlab-ci.yml. !26171 (tortuetorche)
+- Switch to sassc-rails for faster stylesheet compilation. !26224
+- Reorganize project merge request settings. !26834
+- Display a toast message when the Kubernetes runner has successfully upgraded. !27206
+- Allow guests users to access project releases. !27247
+- Add help texts to K8 form fields. !27274
+- Support prometheus for group level clusters. !27280
+- Include link to raw job log in plain-text emails. !27409
+- Only escape Markdown emphasis characters in autocomplete when necessary. !27457
+- Move location of charts/auto-deploy-app -> gitlab-org/charts/auto-deploy-app. !27477
+- Make canceled jobs not retryable. !27503
+- Upgrade to Gitaly v1.36.0. !27831
+- Update deployment event chat notification message. !27972
+- Upgrade to Gitaly v1.42.0. !28135
+- Resolve discussion when apply suggestion. !28160
+- Improve expanding diff to full file performance.
+- Knative version bump 0.3 -> 0.5. (Chris Baumbauer <cab@cabnetworks.net>)
+
+### Performance (5 changes)
+
+- Added list_pages method to avoid loading all wiki pages content. !22801
+- Add gitaly session id & catfile-cache feature flag. !27472
+- Add improvements to global search of issues and merge requests. !27817
+- Disable method replacement in avatar loading. !27866
+- Fix Blob.lazy always loading all previously-requested blobs when a new request is made.
+
+### Added (36 changes, 10 of them are from the community)
+
+- Add time preferences for user. !25381
+- Added write_repository scope for personal access token. !26021 (Horatiu Eugen Vlad)
+- Mark disabled pages domains for removal, but don't remove them yet. !26212
+- Remove pages domains if they weren't verified for 1 week. !26227
+- Expose pipeline variables via API. !26501 (Agustin Henze <tin@redhat.com>)
+- Download a folder from repository. !26532 (kiameisomabes)
+- Remove cleaned up OIDs from database and cache. !26555
+- Disables kubernetes resources creation if a cluster is not managed. !26565
+- Add CI_COMMIT_REF_PROTECTED CI variable. !26716 (Jason van den Hurk)
+- Add new API endpoint to expose a single environment. !26887
+- Allow Sentry configuration to be passed on gitlab.yml. !27091 (Roger Meier)
+- CI variables of type file. !27112
+- Allow linking to a private helm repository by providing credentials, and customisation of repository name. !27123 (Stuart Moore @stjm-cc)
+- Add time tracking information to Issue Boards sidebar. !27166
+- Play all manual jobs in a stage. !27188
+- Instance level kubernetes clusters. !27196
+- Adds if InfluxDB and Prometheus metrics are enabled to usage ping data. !27238
+- Autosave description in epics. !27296
+- Add deployment events to chat notification services. !27338
+- Add packages_size to ProjectStatistics. !27373
+- Added OmniAuth OpenID Connect strategy. !27383 (Horatiu Eugen Vlad)
+- Test using Git 2.21. !27418
+- Use official Gitea logo in importer. !27424 (Matti Ranta (@techknowlogick))
+- Add option to set access_level of runners upon registration. !27490 (Zelin L)
+- Add initial GraphQL query for Groups. !27492
+- Enable Sidekiq Reliable Fetcher for background jobs by default. !27530
+- Add backend support for a External Dashboard URL setting. !27550
+- Implement UI for uninstalling Cluster’s managed apps. !27559
+- Resolve Salesforce.com omniauth support. !27834
+- Leave project/group from access granted email. !27892
+- Allow Sentry client-side DSN to be passed on gitlab.yml. !27967
+- GraphQL: improve evaluation of query complexity based on arguments and query limits. !28017
+- Adds badge for Canary environment and help link.
+- Support negative matches.
+- Show category icons in user popover.
+- Added Omniauth UltraAuth strategy to GitLab. (Kartikey Tanna)
+
+### Other (29 changes, 8 of them are from the community)
+
+- Validate refs used in controllers don't have spaces. !24037
+- Migrate correlation and tracing code to LabKit. !25379
+- Update node.js to 10.15.3 in CI template for Hexo. !25943 (Takuya Noguchi)
+- Improve icons and button order in project overview. !26796
+- Add instructions on how to contribute a Built-In template for project. !26976
+- Extract DiscussionNotes component from NoteableDiscussion. !27066
+- Bump gRPC to 1.19.0 and protobuf to 3.7.1. !27086
+- Extract DiscussionActions component from NoteableDiscussion. !27227
+- Show disabled project repo mirrors in settings. !27326
+- Add backtrace to Gitaly performance bar. !27345
+- Moved EE/CE differences for dropdown_value_collapsed into CE. !27367
+- Remove "You are already signed in" banner. !27377
+- Move ee-specific code from boards/components/issue_card_inner.vue. !27394 (Roman Rodionov)
+- Upgrade to Rails 5.1. !27480 (Jasper Maes)
+- Update GitLab Runner Helm Chart to 0.4.0. !27508
+- Update GitLab Runner Helm Chart to 0.4.1. !27627
+- Refactored notes tests from Karma to Jest. !27648 (Martin Hobert)
+- refactor(issue): Refactored issue tests from Karma to Jest. !27673 (Martin Hobert)
+- Refactored Karma spec files to Jest. !27688 (Martin Hobert)
+- Add CSS fix for <wbr> elements on IE11. !27846
+- Update clair-local-scan to v2.0.8 for container scanning. !27977
+- Use PostgreSQL 10.7 in tests. !28020
+- Document EE License Auto Import During Install. !28106
+- Remove the note in the docs that multi-line suggestions are not yet available. !28119 (hardysim)
+- Update gitlab-shell to v9.1.0. !28184
+- Add EE fixtures to SeedFu list. !28241
+- Replaces CSS with BS4 utility class for pipeline schedules.
+- Creates a vendors folder for external CSS.
+- Add some frozen string to spec/**/*.rb. (gfyoung)
+
+
+## 11.10.6 (2019-06-04)
+
+### Fixed (7 changes, 1 of them is from the community)
+
+- Allow a member to have an access level equal to parent group. !27913
+- Fix uploading of LFS tracked file through UI. !28052
+- Use 3-way merge for squashing commits. !28078
+- Use a path for the related merge requests endpoint. !28171
+- Fix project visibility level validation. !28305 (Peter Marko)
+- Fix Rugged get_tree_entries recursive flag not working. !28494
+- Use source ref in pipeline webhook. !28772
+
+### Other (1 change)
+
+- Fix input group height.
+
+
+## 11.10.4 (2019-05-01)
+
+### Fixed (12 changes)
+
+- Fix MR popover on ToDos page. !27382
+- Fix 500 in general pipeline settings when passing an invalid build timeout. !27416
+- Fix bug where system note MR has no popover. !27589
+- Fix bug when project export to remote url fails. !27614
+- `on_stop` is not automatically triggered with pipelines for merge requests. !27618
+- Update Workhorse to v8.5.2. !27631
+- Show proper wiki links in search results. !27634
+- Make `CI_COMMIT_REF_NAME` and `SLUG` variable idempotent. !27663
+- Fix Kubernetes service template deployment jobs broken as of 11.10.0. !27687
+- Prevent text selection when dragging in issue boards. !27724
+- Fix pipelines for merge requests does not show pipeline page when source branch is removed. !27803
+- Fix Metrics Environments dropdown.
+
+### Performance (2 changes)
+
+- Prevent concurrent execution of PipelineScheduleWorker. !27781
+- Fix slow performance with compiling HAML templates. !27782
+
+
+## 11.10.3 (2019-04-30)
+
+### Security (1 change)
+
+- Allow to see project events only with api scope token.
+
+
+## 11.10.2 (2019-04-25)
+
+### Security (4 changes)
+
+- Loosen regex for exception sanitization. !3076
+- Resolve: moving an issue to private repo leaks namespace and project name.
+- Escape path in new merge request mail.
+- Stop sending emails to users who can't read commit.
+
+
+## 11.10.1 (2019-04-23)
+
+### Fixed (2 changes)
+
+- Upgrade Gitaly to 1.34.0. !27494
+- Fix filtering of labels from system note link. !27507
+
+### Changed (1 change)
+
+- Disable just-in-time Kubernetes resource creation for project level clusters. !27352
+
+### Performance (1 change)
+
+- Bring back Rugged implementation of ListCommitsByOid. !27441
+
+### Other (1 change)
+
+- Bump required Ruby version check to 2.5.3. !27495
+
+
+## 11.10.0 (2019-04-22)
+
+### Security (9 changes)
+
+- Update Rails to 5.0.7.2. !27022
+- Disallow guest users from accessing Releases.
+- Return cached languages if they've been detected before.
+- Added rake task for removing EXIF data from existing uploads.
+- Disallow updating namespace when updating a project.
+- Fix XSS in resolve conflicts form.
+- Hide "related branches" when user does not have permission.
+- Fix PDF.js vulnerability.
+- Use UntrustedRegexp for matching refs policy.
+
+### Fixed (81 changes, 21 of them are from the community)
+
+- Update `border-radius` of form controls and remove extra space above page titles. !24497
+- Disallow reopening of a locked merge request. !24882 (Jan Beckmann)
+- Align EmailValidator to validate_email gem implementation. !24971 (Horatiu Eugen Vlad)
+- add a uniq constraints on issues and mrs labels. !25435 (Antoine Huret)
+- Display draft when toggling replies. !25563
+- Fix markdown table header and table content borders. !25666
+- Fix authorized application count. !25715 (moyuru)
+- Added "Add List" checkbox to create label dropdown to make creation of list optional. !25716 (Tucker Chapman)
+- Makes emoji picker full width on mobile. !25883 (Jacopo Beschi @jacopo-beschi)
+- Don't cutoff letters in MR and Issue links. !25910 (gfyoung)
+- Fix unwanted character replacement on project members page caused by usage of sanitize function. !25946 (Elias Werberich)
+- Fix UI for closed MR when source project is removed. !25967 (Takuya Noguchi)
+- Keep inline as much as possible in system notes on issuable. !25968 (Takuya Noguchi)
+- Fixes long review app subdomains. !25990 (walkafwalka)
+- Fix counting of groups in admin dashboard. !26009
+- Disable inaccessible navigation links upon archiving a project. !26020 (Elias Werberich)
+- Fixed - Create project label window is cut off at the bottom. !26049
+- Fix error shown when loading links to specific comments. !26092
+- Fix group transfer selection possibilities. !26123 (Peter Marko)
+- Fix UI layout on Commits on mobile. !26133 (Takuya Noguchi)
+- Fix continuous bitbucket import loading spinner. !26175
+- Resolves Branch name is lost if I change commit mode in Web IDE. !26180
+- Fix removing remote mirror failure which leaves unnecessary refs behind. !26213
+- Fix Error 500 when user commits Wiki page with no commit message. !26247
+- Handle missing keys in sentry api response. !26264
+- Implemented whitespace-trimming for file names in Web IDE. !26270
+- Fix misalignment of group overview page buttons. !26292
+- Reject HEAD requests to info/refs endpoint. !26334
+- Prevent namespace dropdown in new project form from exceeding container. !26343
+- Fix hover animation consistency in top navbar items. !26345
+- Exclude system notes from commits in merge request discussions. !26396
+- Resolve Code in other column of side-by-side diff is highlighted when selecting code on one side. !26423
+- Prevent fade out transition on loading-button component. !26428
+- Fix merge commits being used as default squash commit messages. !26445
+- Expand resolved discussion when linking to a comment in the discussion. !26483
+- Show statistics also when repository is disabled. !26509 (Peter Marko)
+- Fix multiple series queries on metrics dashboard. !26514
+- Releases will now be automatically deleted when deleting corresponding tag. !26530
+- Make stylistic improvements to diff nav header. !26557
+- Clear pipeline status cache after destruction of pipeline. !26575
+- Update fugit which fixes a potential infinite loop. !26579
+- Fixes job link in artifacts page breadcrumb. !26592
+- Fix quick actions add label name middle word overlaps. !26602 (Jacopo Beschi @jacopo-beschi)
+- Fix Auto DevOps missing domain error handling. !26627
+- Fix jupyter rendering bug that ended in an infinite loop. !26656 (ROSPARS Benoit)
+- Use a fixed git abbrev parameter when we fetch a git revision. !26707
+- Enabled text selection highlighting in diffs in Web IDE. !26721 (Isaac Smith)
+- Remove `path` and `branch` labels from metrics. !26744
+- Resolve "Hide Kubernetes cluster warning if project has cluster related". !26749
+- Fix long label overflow on metrics dashboard. !26775
+- Group transfer now properly redirects to edit on failure. !26837
+- Only execute system hooks once when pushing tags. !26888
+- Fix UI anchor links after docs refactor. !26890
+- Fix MWPS does not work for merge request pipelines. !26906
+- Create pipelines for merge requests only when source branch is updated. !26921
+- Fix notfication emails having wrong encoding. !26931
+- Allow task lists that follow a blockquote to work correctly. !26937
+- Fix image diff swipe view on commit and compare pages. !26968 (ftab)
+- Fix IDE detection of MR from fork with same branch name. !26986
+- Fix single string values for the 'include' keyword validation of gitlab-ci.yml. !26998 (Paul Bonaud (@paulrbr))
+- Do not display Ingress IP help text when there isn’t an Ingress IP assigned. !27057
+- Fix real-time updates for projects that contain a reserved word. !27060
+- Remove duplicates from issue related merge requests. !27067
+- Add to white-space nowrap to all buttons. !27069
+- Handle possible HTTP exception for Sentry client. !27080
+- Guard against nil dereferenced_target. !27192
+- Update GitLab Workhorse to v8.5.1. !27217
+- Fix long file header names bug in diffs. !27233
+- Always return the deployment in the UpdateDeploymentService#execute method. !27322
+- Fix remove_source_branch merge request API handling. !27392
+- Fixed bug with hashes in urls in WebIDE. !54376 (Kieran Andrews)
+- Fix bug where MR popover doesn't go away on mouse leave.
+- Only consider active milestones when using the special Started milestone filter.
+- Scroll to diff file content when clicking on file header name and it is not a link to other page.
+- Remove non-functional add issue button on welcome list.
+- Fixed expand full file button showing on images.
+- Fixed Web IDE web workers not working with relative URLs.
+- Fixed Web IDE not loading merge request files.
+- Fixed duplicated diff too large error message.
+- Fixed sticky headers in merge request creation diffs.
+- Fix bug when reopening milestone from index page.
+
+### Deprecated (1 change)
+
+- Allow to use untrusted Regexp via feature flag. !26905
+
+### Changed (35 changes, 4 of them are from the community)
+
+- Create MR pipelines with `refs/merge-requests/:iid/head`. !25504
+- Create Kubernetes resources for projects when their deployment jobs run. !25586
+- Remove unnecessary folder prefix from environment name. !25600
+- Update deploy boards to additionally select on "app.gitlab.com" annotations. !25623
+- Allow failed custom hook script errors to safely appear in GitLab UI by filtering error messages by the prefix GL-HOOK-ERR:. !25625
+- Add link on two-factor authorization settings page to leave group that enforces two-factor authorization. !25731
+- Reduce height of instance system header and footer. !25752
+- Unify behaviour of 'Copy commit SHA to clipboard' to use full commit SHA. !25829 (Max Winterstein)
+- Show loading spinner while Ingress/Knative IP is being assigned. !25912
+- Hashed Storage: Prevent a migration and rollback running at the same time. !25976
+- Make time counters show 'just now' for everything under one minute. !25992 (Sergiu Marton)
+- Allow filtering labels list by one or two characters. !26012
+- Implements the creation strategy for multi-line suggestions. !26057
+- Automate base domain help text on Clusters page. !26124
+- Set user.name limit to 128 characters. !26146
+- Update gitlab-markup to 1.7.0 which requies python3. !26246
+- Update system message banner font size to 12px. !26293
+- Extend timezone dropdown. !26311
+- Upgrade to Gitaly v1.29.0. !26406
+- Automatically set Prometheus step interval. !26441
+- Knative version bump 0.2.2 -> 0.3.0. !26459 (Chris Baumbauer)
+- Display cluster form validation error messages inline. !26502
+- Split Auto-DevOps.gitlab-ci.yml into reusable templates. !26520
+- Update spinners in group list component. !26572
+- Allow removing last owner from subgroup if parent group has owners. !26718
+- Check mergeability in MergeToRefService. !26757
+- Show download diff links for closed MRs. !26772
+- Fix Container Scanning in Kubernetes Runners. !26793
+- Move "Authorize project access with external service" to Core. !26823
+- Localize notifications dropdown. !26844
+- Order labels alphabetically in issue boards. !26927
+- Upgrade to Gitaly v1.32.0. !26989
+- Upgrade to Gitaly v1.33.0. !27065
+- collapse file tree by default if the merge request changes only one file. (Riccardo Padovani <riccardo@rpadovani.com>)
+- Removes the undescriptive CI Charts header.
+
+### Performance (17 changes)
+
+- Drop legacy artifacts usage as there are no leftovers. !24294
+- Cache Repository#root_ref within a request. !25903
+- Allow ref name caching CommitService#find_commit. !26248
+- Avoid loading pipeline status in project search. !26342
+- Fix some N+1s in loading routes and counting members for groups in @-autocomplete. !26491
+- GitHub import: Run housekeeping after initial import. !26600
+- Add initial complexity limits to GraphQL queries. !26629
+- Cache FindCommit results in pipelines view. !26776
+- Fix and expand Gitaly FindCommit caching. !27018
+- Enable FindCommit caching for project and commits pages. !27048
+- Expand FindCommit caching to blob and refs. !27084
+- Enable Gitaly FindCommit caching for TreeController. !27100
+- Improve performance of PR import. !27121
+- Process at most 4 pipelines during push. !27205
+- Disable method instrumentation for diffs. !27235
+- Speed up filtering issues in a project when searching.
+- Speed up generation of avatar URLs when using object storage.
+
+### Added (35 changes, 6 of them are from the community)
+
+- Add users search results to global search. !21197 (Alexis Reigel)
+- Add target branch filter to merge requests search bar. !24380 (Hiroyuki Sato)
+- Add Knative metrics to Prometheus. !24663 (Chris Baumbauer <cab@cabnetworks.net>)
+- Support multi-line suggestions. !25211
+- Allow to sort wiki pages by date and title. !25365
+- Allow external diffs to be used conditionally. !25432
+- Add usage counts for error tracking feature. !25472
+- Enable/disable Auto DevOps at the Group level. !25533
+- Update pipeline list view to accommodate post-merge pipeline information. !25690
+- GraphQL Types can be made to always authorize access to resources of that Type. !25724
+- Update clair-local-scan to 2.0.6. !25743 (Takuya Noguchi)
+- Update pipeline block on merge request page to accommodate post-merge pipeline information. !25745
+- Support multiple queries per chart on metrics dash. !25758
+- Update pipeline detail view to accommodate post-merge pipelines. !25775
+- Update job detail sidebar to accommodate post-merge pipeline information. !25777
+- Add merge request pipeline flag to pipeline entity. !25846
+- Expose group id on home panel. !25897 (Peter Marko)
+- Move allow developers to create projects in groups to Core. !25975
+- Add two new warning messages to the MR widget about merge request pipelines. !25983
+- Support installing Group runner on group-level cluster. !26260
+- Improve the Knative installation on Clusters. !26339
+- Show error when namespace/svc account missing. !26362
+- Add select by title to milestones API. !26573
+- Implemented support for creation of new files from URL in Web IDE. !26622
+- Add control for masking variable values in runner logs. !26751
+- Allow merge requests to be created via git push options. !26752
+- Create a shortcut for a new MR in the Web IDE. !26792
+- Allow reactive caching to be used in services. !26839
+- Add a Prometheus API per environment. !26841
+- Allow merge requests to be set to merge when pipeline succeeds via git push options. !26842
+- Use gitlabktl to build and deploy GitLab Serverless Functions. !26926
+- Make touch events work on image diff swipe view and onion skin. !26971 (ftab)
+- Add extended merge request tooltip.
+- Added prometheus monitoring to GraphQL.
+- Adding highest role property to admin's user details page.
+
+### Other (29 changes, 6 of them are from the community)
+
+- Update rack-oauth2 1.2.1 -> 1.9.3. !17868
+- Merge the gitlab-shell "gitlab-keys" functionality into GitLab CE. !25598
+- Refactor all_pipelines in Merge request. !25676
+- Show error backtrace when logging errors to kubernetes.log. !25726
+- Apply recaptcha API change in 4.0. !25921 (Praveen Arimbrathodiyil)
+- Remove fake repository_path response. !25942 (Fabio Papa)
+- Use curl silent/show-error options on Auto DevOps. !25954 (Takuya Noguchi)
+- Explicitly set master_auth setting to enable basic auth and client certificate for new GKE clusters. !26018
+- Project: Improve empty repository state UI. !26024
+- Externalize strings from `/app/views/projects/pipelines`. !26035 (George Tsiolis)
+- Prepare multi-line suggestions for rendering in Markdown. !26107
+- Improve mobile UI on User Profile page. !26240 (Takuya Noguchi)
+- Update GitLab Runner Helm Chart to 0.3.0/11.9.0. !26467
+- Improve project merge request settings. !26495
+- Bump kubectl to 1.11.9 and Helm to 2.13.1 in Auto-DevOps.gitlab-ci.yml. !26534
+- Upgrade bootstrap_form Gem. !26568
+- Add API access check to Graphql. !26570
+- Change project avatar remove button to a link. !26589
+- Log Gitaly RPC duration to api_json.log and production_json.log. !26652
+- Add cluster domain to Project Cluster API. !26735
+- Move project tags to separate line. !26797
+- Changed button label at /pipelines/new. !26893 (antfobe,leonardofl)
+- Update GitLab Shell to v9.0.0. !27002
+- Migrate clusters tests to jest. !27013
+- Rewrite related MRs widget with Vue. !27027
+- Restore HipChat project service. !27172
+- Externalize admin deploy keys strings.
+- Removes EE differences for environments_table.vue.
+- Removes EE differences for environment_item.vue.
+
+
+## 11.9.12 (2019-05-30)
+
+### Security (12 changes, 1 of them is from the community)
+
+- Protect Gitlab::HTTP against DNS rebinding attack.
+- Fix project visibility level validation. (Peter Marko)
+- Update Knative version.
+- Add DNS rebinding protection settings.
+- Prevent XSS injection in note imports.
+- Prevent invalid branch for merge request.
+- Filter relative links in wiki for XSS.
+- Fix confidential issue label disclosure on milestone view.
+- Fix url redaction for issue links.
+- Resolve: Milestones leaked via search API.
+- Prevent bypass of restriction disabling web password sign in.
+- Hide confidential issue title on unsubscribe for anonymous users.
+
+
+## 11.9.10 (2019-04-26)
+
+### Security (5 changes)
+
+- Loosen regex for exception sanitization. !3077
+- Resolve: moving an issue to private repo leaks namespace and project name.
+- Escape path in new merge request mail.
+- Stop sending emails to users who can't read commit.
+- Upgrade Rails to 5.0.7.2.
+
+
+## 11.9.9 (2019-04-23)
+
+### Performance (1 change)
+
+- Bring back Rugged implementation of ListCommitsByOid. !27441
+
+
## 11.9.8 (2019-04-11)
### Deprecated (1 change)
@@ -103,7 +660,7 @@ entry.
- Forbid creating discussions for users with restricted access.
- Fix leaking private repository information in API.
- Fixed ability to see private groups by users not belonging to given group.
-- Prevent releases links API to leak tag existance.
+- Prevent releases links API to leak tag existence.
- Display the correct number of MRs a user has access to.
- Block local URLs for Kubernetes integration.
- Fix arbitrary file read via diffs during import.
@@ -353,6 +910,35 @@ entry.
- Removes EE differences for jobs/getters.js.
+## 11.8.10 (2019-04-30)
+
+### Security (1 change)
+
+- Allow to see project events only with api scope token.
+
+
+## 11.8.8 (2019-04-23)
+
+### Fixed (5 changes)
+
+- Bring back Rugged implementation of find_commit. !25477
+- Fix bug in BitBucket imports with SHA shorter than 40 chars. !26050
+- Fix health checks not working behind load balancers. !26055
+- Fix error creating a merge request when diff includes a null byte. !26190
+- Avoid excessive recursive calls with Rugged TreeEntries. !26813
+
+### Performance (1 change)
+
+- Bring back Rugged implementation of ListCommitsByOid. !27441
+
+### Other (4 changes)
+
+- Bring back Rugged implementation of GetTreeEntries. !25674
+- Bring back Rugged implementation of CommitIsAncestor. !25702
+- Bring back Rugged implementation of TreeEntry. !25706
+- Bring back Rugged implementation of commit_tree_entry. !25896
+
+
## 11.8.3 (2019-03-19)
### Security (1 change)
@@ -433,7 +1019,7 @@ entry.
- Display SAML failure messages instead of expecting CSRF token. !24509
- Adjust vertical alignment for project visibility icons. !24511 (Martin Hobert)
- Load initUserInternalRegexPlaceholder only when required. !24522
-- Hashed Storage: `AfterRenameService` was receiving the wrong `old_path` under some circunstances. !24526
+- Hashed Storage: `AfterRenameService` was receiving the wrong `old_path` under some circumstances. !24526
- Resolve Runners IPv6 address overlaps other values. !24531
- Fix 404s with snippet uploads in object storage. !24550
- Fixed oversized custom project notification selector dropdown. !24557
@@ -472,7 +1058,7 @@ entry.
- Update CI YAML param table with include.
- Return bottom border on MR Tabs.
- Fixes z-index and margins of archived alert in job page.
-- Fixes archived sticky top bar without perfomance bar.
+- Fixes archived sticky top bar without performance bar.
- Fixed rebase button not showing in merge request widget.
- Fixed double tooltips on note awards buttons.
- Allow suggestions to be copied and pasted as GFM.
@@ -622,6 +1208,25 @@ entry.
- Creates mixin to reduce code duplication between CE and EE in graph component.
+## 11.7.12 (2019-04-23)
+
+### Fixed (2 changes)
+
+- Bring back Rugged implementation of find_commit. !25477
+- Avoid excessive recursive calls with Rugged TreeEntries. !26813
+
+### Performance (1 change)
+
+- Bring back Rugged implementation of ListCommitsByOid. !27441
+
+### Other (4 changes)
+
+- Bring back Rugged implementation of GetTreeEntries. !25674
+- Bring back Rugged implementation of CommitIsAncestor. !25702
+- Bring back Rugged implementation of TreeEntry. !25706
+- Bring back Rugged implementation of commit_tree_entry. !25896
+
+
## 11.7.11 (2019-04-09)
- No changes.
@@ -886,7 +1491,7 @@ entry.
- Fix deprecation: Using positional arguments in integration tests. !24009 (Jasper Maes)
- UI improvements for redesigned project lists. !24011
- Update cert-manager chart from v0.5.0 to v0.5.2. !24025 (Takuya Noguchi)
-- Hide spinner on empty activites list on user profile overview. !24063
+- Hide spinner on empty activities list on user profile overview. !24063
- Don't show Auto DevOps enabled banner for projects with CI file or CI disabled. !24067
- Update GitLab Runner Helm Chart to 0.1.43. !24083
- Fix navigation style in docs. !24090 (Takuya Noguchi)
@@ -897,6 +1502,30 @@ entry.
- Update url placeholder for the sentry configuration page. !24338
+## 11.6.11 (2019-04-23)
+
+### Security (2 changes)
+
+- Fixed ability to see private groups by users not belonging to given group.
+- Fix XSS in resolve conflicts form.
+
+### Fixed (2 changes)
+
+- Bring back Rugged implementation of find_commit. !25477
+- Avoid excessive recursive calls with Rugged TreeEntries. !26813
+
+### Performance (1 change)
+
+- Bring back Rugged implementation of ListCommitsByOid. !27441
+
+### Other (4 changes)
+
+- Bring back Rugged implementation of GetTreeEntries. !25674
+- Bring back Rugged implementation of CommitIsAncestor. !25702
+- Bring back Rugged implementation of TreeEntry. !25706
+- Bring back Rugged implementation of commit_tree_entry. !25896
+
+
## 11.6.10 (2019-02-28)
### Security (21 changes)
@@ -1268,6 +1897,25 @@ entry.
- Enable Rubocop on lib/gitlab. (gfyoung)
+## 11.5.11 (2019-04-23)
+
+### Fixed (2 changes)
+
+- Bring back Rugged implementation of find_commit. !25477
+- Avoid excessive recursive calls with Rugged TreeEntries. !26813
+
+### Performance (1 change)
+
+- Bring back Rugged implementation of ListCommitsByOid. !27441
+
+### Other (4 changes)
+
+- Bring back Rugged implementation of GetTreeEntries. !25674
+- Bring back Rugged implementation of CommitIsAncestor. !25702
+- Bring back Rugged implementation of TreeEntry. !25706
+- Bring back Rugged implementation of commit_tree_entry. !25896
+
+
## 11.5.8 (2019-01-28)
### Security (21 changes)
@@ -1372,7 +2020,7 @@ entry.
- Hide all tables on Pipeline when no Jobs for the Pipeline. !18540 (Takuya Noguchi)
- Fixing count on Milestones. !21446
-- Use case insensitve username lookups. !21728 (William George)
+- Use case insensitive username lookups. !21728 (William George)
- Correctly process Bamboo API result array. !21970 (Alex Lossent)
- Fix 'merged with' UI being displayed when merge request has no merge commit. !22022
- Fix broken file name navigation on MRs. !22109
@@ -2155,7 +2803,7 @@ entry.
- Fixes SVGs for empty states in job page overflowing on mobile.
- Fix checkboxes on runner admin settings - The labels are now clickable.
- Fixed IDE file row scrolling into view when hovering.
-- Accept upload files in public/uplaods/tmp when using accelerated uploads.
+- Accept upload files in public/uploads/tmp when using accelerated uploads.
- Include correct CSS file for xterm in environments page.
- Increase padding in code blocks.
- Fix: Project deletion may not log audit events during user deletion.
@@ -3041,7 +3689,7 @@ entry.
### Fixed (69 changes, 23 of them are from the community)
-- Optimize the upload migration proces. !15947
+- Optimize the upload migration process. !15947
- Import bitbucket issues that are reported by an anonymous user. !18199 (bartl)
- Fix an issue where the notification email address would be set to an unconfirmed email address. !18474
- Stop logging email information when emails are disabled. !18521 (Marc Shaw)
@@ -3169,7 +3817,7 @@ entry.
- Add a cronworker to rescue stale live traces. !18680
- Move SquashBeforeMerge vue component. !18813 (George Tsiolis)
- Add index on runner_type for ci_runners. !18897
-- Fix CarrierWave reads local files into memoery when migrates to ObjectStorage. !19102
+- Fix CarrierWave reads local files into memory when migrates to ObjectStorage. !19102
- Remove double-checked internal id generation. !19181
- Throttle updates to Project#last_repository_updated_at. !19183
- Add background migrations for archiving legacy job traces. !19194
@@ -3260,7 +3908,7 @@ entry.
- Adjust SQL and transaction Prometheus buckets.
- Adding branches through the WebUI is handled by Gitaly.
- Remove shellout implementation for Repository checksums.
-- Refs containting sha checks are done by Gitaly.
+- Refs containing sha checks are done by Gitaly.
- Finding a wiki page is done by Gitaly by default.
- Workhorse will use Gitaly to create archives.
- Workhorse to send raw diff and patch for commits.
@@ -3464,7 +4112,7 @@ entry.
- Display active sessions and allow the user to revoke any of it. !17867 (Alexis Reigel)
- Add cron job to email users on issue due date. !17985 (Stuart Nelson)
- Rubocop rule to avoid returning from a block. !18000 (Jacopo Beschi @jacopo-beschi)
-- Add the signature verfication badge to the compare view. !18245 (Marc Shaw)
+- Add the signature verification badge to the compare view. !18245 (Marc Shaw)
- Expose Deploy Token data as environment varialbes on CI/CD jobs. !18414
- Show group id in group settings. !18482 (George Tsiolis)
- Allow admins to enforce accepting Terms of Service on an instance. !18570
@@ -4202,7 +4850,7 @@ entry.
- Override group sidebar links. !16942 (George Tsiolis)
- Avoid running `PopulateForkNetworksRange`-migration multiple times. !16988
- Resolve PrepareUntrackedUploads PostgreSQL syntax error. !17019
-- Fix monaco editor features which were incompatable with GitLab CDN settings. !17021
+- Fix monaco editor features which were incompatible with GitLab CDN settings. !17021
- Fixed error 500 when removing an identity with synced attributes and visiting the profile page. !17054
- Fix cnacel edit note button reverting changes. !42462
- For issues display time of last edit of title or description instead of time of any attribute change.
@@ -4419,7 +5067,7 @@ entry.
### Performance (2 changes)
- rework indexes on redirect_routes.
-- Remove unecessary query from labels filter.
+- Remove unnecessary query from labels filter.
## 10.4.0 (2018-01-22)
@@ -4550,7 +5198,7 @@ entry.
- Add a gitlab:tcp_check rake task. !15759
- add support for sorting in tags api. !15772 (haseebeqx)
- Add Prometheus to available Cluster applications. !15895
-- Validate file status when commiting multiple files. !15922
+- Validate file status when committing multiple files. !15922
- List of avatars should never show +1. !15972 (Jacopo Beschi @jacopo-beschi)
- Do not generate NPM links for private NPM modules in blob view. !16002 (Mario de la Ossa)
- Backport fast database lookup of SSH authorized_keys from EE. !16014
@@ -4581,7 +5229,7 @@ entry.
- Fix web ide user preferences copy and buttons. !41789
- Update redis-rack to 2.0.4.
- Import some code and functionality from gitlab-shell to improve subprocess handling.
-- Update Browse file to Choose file in all occurences.
+- Update Browse file to Choose file in all occurrences.
- Bump mysql2 gem version from 0.4.5 to 0.4.10. (asaparov)
- Use a background migration for issues.closed_at.
@@ -4716,7 +5364,7 @@ entry.
- Fix graph notes number duplication. !15696 (Vladislav Kaverin)
- Fix updateEndpoint undefined error for issue_show app root. !15698
- Change boards page boards_data absolute urls to paths. !15703
-- Using appropiate services in the API for managing forks. !15709
+- Using appropriate services in the API for managing forks. !15709
- Confirming email with invalid token should no longer generate an error. !15726
- fix #39233 - 500 in merge request. !15774 (Martin Nowak)
- Use Markdown styling for new project guidelines. !15785 (Markus Koller)
@@ -4826,7 +5474,7 @@ entry.
- Stop reloading the page when using pagination and tabs - use API calls - in Pipelines table.
- Clean up schema of the "issues" table.
- Clarify wording of protected branch settings for the default branch.
-- Update svg external depencency.
+- Update svg external dependency.
- Clean up schema of the "merge_requests" table.
@@ -4996,7 +5644,7 @@ entry.
- Fix gitlab:backup rake for hashed storage based repositories. !15400
- Fix issue where clicking a GPG verification badge would scroll to the top of the page. !15407
- Update container repository path reference and allow using double underscore. !15417
-- Fix crash when navigating to second page of the group dashbaord when there are projects and groups on the first page. !15456
+- Fix crash when navigating to second page of the group dashboard when there are projects and groups on the first page. !15456
- Fix flash errors showing up on a non configured prometheus integration. !35652
- Fix timezone bug in Pikaday and upgrade Pikaday version.
- Fix arguments Import/Export error importing project merge requests.
@@ -5546,7 +6194,7 @@ entry.
- [CHANGED] Fire hooks asynchronously when creating a new job to improve performance. !13734
- [CHANGED] Improve performance for AutocompleteController#users.json. !13754 (Hiroyuki Sato)
- [CHANGED] Update the GPG verification semantics: A GPG signature must additionally match the committer in order to be verified. !13771 (Alexis Reigel)
-- [CHANGED] Support a multi-word fuzzy seach issues/merge requests on search bar. !13780 (Hiroyuki Sato)
+- [CHANGED] Support a multi-word fuzzy search issues/merge requests on search bar. !13780 (Hiroyuki Sato)
- [CHANGED] Default LDAP config "verify_certificates" to true for security. !13915
- [CHANGED] "Share with group lock" now applies to subgroups, but owner can override setting on subgroups. !13944
- [CHANGED] Make Gitaly PostUploadPack mandatory. !13953
@@ -6245,7 +6893,7 @@ entry.
## 9.3.2 (2017-06-27)
-- API: Fix optional arugments for POST :id/variables. !12474
+- API: Fix optional arguments for POST :id/variables. !12474
- Bump premailer-rails gem to 1.9.7 and its dependencies to prevent network retrieval of assets.
## 9.3.1 (2017-06-26)
@@ -6262,7 +6910,7 @@ entry.
- Refactored gitlab:app:check into SystemCheck liberary and improve some checks. !9173
- Add an ability to cancel attaching file and redesign attaching files UI. !9431 (blackst0ne)
- Add Aliyun OSS as the backup storage provider. !9721 (Yuanfei Zhu)
-- Add suport for find_local_branches GRPC from Gitaly. !10059
+- Add support for find_local_branches GRPC from Gitaly. !10059
- Allow manual bypass of auto_sign_in_with_provider with a new param. !10187 (Maxime Besson)
- Redirect to user's keys index instead of user's index after a key is deleted in the admin. !10227 (Cyril Jouve)
- Changed Blame to Annotate in the UI to promote blameless culture. !10378 (Ilya Vassilevsky)
@@ -6341,7 +6989,7 @@ entry.
- Add tag_list param to project api. !11799 (Ivan Chernov)
- Add changelog for improved Registry description. !11816
- Automatically adjust project settings to match changes in project visibility. !11831
-- Add slugify project path to CI enviroment variables. !11838 (Ivan Chernov)
+- Add slugify project path to CI environment variables. !11838 (Ivan Chernov)
- Add all pipeline sources as special keywords to 'only' and 'except'. !11844 (Filip Krakowski)
- Allow pulling of container images using personal access tokens. !11845
- Expose import_status in Projects API. !11851 (Robin Bobbitt)
@@ -7256,7 +7904,7 @@ entry.
- Clean-up Project navigation order. !9272
- Add Runner's jobs v4 API. !9273
- Add pipeline trigger API with user permissions. !9277
-- Enhanced filter issues layout for better mobile experiance. !9280 (Pratik Borsadiya)
+- Enhanced filter issues layout for better mobile experience. !9280 (Pratik Borsadiya)
- Move babel config for instanbul to karma config. !9286 (winniehell)
- Document U2F limitations with multiple URLs. !9300
- Wrap long Project and Group titles. !9301
@@ -7437,7 +8085,7 @@ entry.
- Add badges to global dropdown.
- Changed coverage reg expression placeholder text to be more like a placeholder.
- Show members of parent groups on project members page.
-- Fix grammer issue in admin/runners.
+- Fix grammar issue in admin/runners.
- Allow slashes in slash command arguments.
- Adds paginationd and folders view to environments table.
- hide loading spinners for server-rendered sidebar fields.
@@ -7610,7 +8258,7 @@ entry.
- Allows to search within project by commit hash. (YarNayar)
- Show organisation membership and delete comment on smaller viewports, plus change comment author name to username.
- Remove turbolinks.
-- Convert pipeline action icons to svg to have them propperly positioned.
+- Convert pipeline action icons to svg to have them properly positioned.
- Remove rogue scrollbars for issue comments with inline elements.
- Align Segoe UI label text.
- Color + and - signs in diffs to increase code legibility.
@@ -7901,3 +8549,4 @@ entry.
## 8.15.8 through 0.8.0
- See [changelogs/archive.md](changelogs/archive.md)
+
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 82e16b4fbf4..e4c954448a5 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -18,11 +18,11 @@ _This notice should stay as the first item in the CONTRIBUTING.md file._
## Contributing Documentation has been moved
As of July 2018, all the documentation for contributing to the GitLab project has been moved to a new location.
-[View the new documentation](doc/development/contributing/index.md) to find the latest information.
+[View the new documentation](https://about.gitlab.com/community/contribute/) to find the latest information.
## Contribute to GitLab
-This [documentation](doc/development/contributing/index.md#contribute-to-gitlab) has been moved.
+[View the new documentation](https://about.gitlab.com/community/contribute/) to find the latest information.
## Security vulnerability disclosure
@@ -42,7 +42,7 @@ This [documentation](doc/development/contributing/index.md#helping-others) has b
## I want to contribute!
-This [documentation](doc/development/contributing/index.md#i-want-to-contribute) has been moved.
+[View the new documentation](https://about.gitlab.com/community/contribute/) to find the latest information.
## Contribution Flow
diff --git a/Dangerfile b/Dangerfile
index 9265c490654..9633a7b95ed 100644
--- a/Dangerfile
+++ b/Dangerfile
@@ -1,4 +1,6 @@
+# frozen_string_literal: true
danger.import_plugin('danger/plugins/helper.rb')
+danger.import_plugin('danger/plugins/roulette.rb')
unless helper.release_automation?
danger.import_dangerfile(path: 'danger/metadata')
@@ -17,4 +19,5 @@ unless helper.release_automation?
danger.import_dangerfile(path: 'danger/single_codebase')
danger.import_dangerfile(path: 'danger/gitlab_ui_wg')
danger.import_dangerfile(path: 'danger/css')
+ danger.import_dangerfile(path: 'danger/ce_ee_vue_templates')
end
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 7aa332e4163..0a3db35b241 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-1.33.0
+1.46.0
diff --git a/GITLAB_ELASTICSEARCH_INDEXER_VERSION b/GITLAB_ELASTICSEARCH_INDEXER_VERSION
new file mode 100644
index 00000000000..26aaba0e866
--- /dev/null
+++ b/GITLAB_ELASTICSEARCH_INDEXER_VERSION
@@ -0,0 +1 @@
+1.2.0
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index bc80560fad6..9c6d6293b1a 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-1.5.0
+1.6.1
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index f7ee06693c1..b13d146a7b0 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-9.0.0
+9.3.0
diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION
index acd405b1d62..df5119ec64e 100644
--- a/GITLAB_WORKHORSE_VERSION
+++ b/GITLAB_WORKHORSE_VERSION
@@ -1 +1 @@
-8.6.0
+8.7.0
diff --git a/Gemfile b/Gemfile
index c55e6478cb0..a5dccd2ef24 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,6 +1,6 @@
source 'https://rubygems.org'
-gem 'rails', '5.0.7.2'
+gem 'rails', '5.1.7'
# Improves copy-on-write performance for MRI
gem 'nakayoshi_fork', '~> 0.0.4'
@@ -18,12 +18,12 @@ gem 'mysql2', '~> 0.4.10', group: :mysql
gem 'pg', '~> 1.1', group: :postgres
gem 'rugged', '~> 0.28'
-gem 'grape-path-helpers', '~> 1.0'
+gem 'grape-path-helpers', '~> 1.1'
gem 'faraday', '~> 0.12'
# Authentication libraries
-gem 'devise', '~> 4.4'
+gem 'devise', '~> 4.6'
gem 'doorkeeper', '~> 4.3'
gem 'doorkeeper-openid_connect', '~> 1.5'
gem 'omniauth', '~> 1.8'
@@ -41,6 +41,9 @@ gem 'omniauth-shibboleth', '~> 1.3.0'
gem 'omniauth-twitter', '~> 1.4'
gem 'omniauth_crowd', '~> 2.2.0'
gem 'omniauth-authentiq', '~> 0.3.3'
+gem 'omniauth_openid_connect', '~> 0.3.1'
+gem "omniauth-ultraauth", '~> 0.0.2'
+gem 'omniauth-salesforce', '~> 1.0.5'
gem 'rack-oauth2', '~> 1.9.3'
gem 'jwt', '~> 2.1.0'
@@ -57,6 +60,8 @@ gem 'u2f', '~> 0.2.1'
# GitLab Pages
gem 'validates_hostname', '~> 1.0.6'
gem 'rubyzip', '~> 1.2.2', require: 'zip'
+# GitLab Pages letsencrypt support
+gem 'acme-client', '~> 2.0.2'
# Browser detection
gem 'browser', '~> 2.5'
@@ -78,6 +83,7 @@ gem 'rack-cors', '~> 1.0.0', require: 'rack/cors'
# GraphQL API
gem 'graphql', '~> 1.8.0'
gem 'graphiql-rails', '~> 1.4.10'
+gem 'apollo_upload_server', '~> 2.0.0.beta3'
# Disable strong_params so that Mash does not respond to :permitted?
gem 'hashie-forbidden_attributes'
@@ -124,11 +130,12 @@ gem 'org-ruby', '~> 0.9.12'
gem 'creole', '~> 0.5.0'
gem 'wikicloth', '0.8.1'
gem 'asciidoctor', '~> 1.5.8'
+gem 'asciidoctor-include-ext', '~> 0.3.1', require: false
gem 'asciidoctor-plantuml', '0.0.8'
gem 'rouge', '~> 3.1'
gem 'truncato', '~> 0.7.11'
gem 'bootstrap_form', '~> 4.2.0'
-gem 'nokogiri', '~> 1.10.1'
+gem 'nokogiri', '~> 1.10.3'
gem 'escape_utils', '~> 1.1'
# Calendar rendering
@@ -148,6 +155,7 @@ end
group :puma do
gem 'puma', '~> 3.12', require: false
gem 'puma_worker_killer', require: false
+ gem 'rack-timeout', require: false
end
# State machine
@@ -157,13 +165,13 @@ gem 'state_machines-activerecord', '~> 0.5.1'
gem 'acts-as-taggable-on', '~> 6.0'
# Background jobs
-gem 'sidekiq', '~> 5.2.1'
+gem 'sidekiq', '~> 5.2.7'
gem 'sidekiq-cron', '~> 1.0'
gem 'redis-namespace', '~> 1.6.0'
gem 'gitlab-sidekiq-fetcher', '~> 0.4.0', require: 'sidekiq-reliable-fetch'
# Cron Parser
-gem 'fugit', '~> 1.1'
+gem 'fugit', '~> 1.2.1'
# HTTP requests
gem 'httparty', '~> 0.16.4'
@@ -256,8 +264,7 @@ gem 'chronic_duration', '~> 0.10.6'
gem 'webpack-rails', '~> 0.9.10'
gem 'rack-proxy', '~> 0.6.0'
-gem 'sass-rails', '~> 5.0.6'
-gem 'sass', '~> 3.5'
+gem 'sassc-rails', '~> 2.1.0'
gem 'uglifier', '~> 2.7.2'
gem 'addressable', '~> 2.5.2'
@@ -269,10 +276,13 @@ gem 'virtus', '~> 1.0.1'
gem 'base32', '~> 0.3.0'
# Sentry integration
-gem 'sentry-raven', '~> 2.7'
+gem 'sentry-raven', '~> 2.9'
gem 'premailer-rails', '~> 1.9.7'
+# LabKit: Tracing and Correlation
+gem 'gitlab-labkit', '~> 0.2.0'
+
# I18n
gem 'ruby_parser', '~> 3.8', require: false
gem 'rails-i18n', '~> 5.1'
@@ -280,7 +290,7 @@ gem 'gettext_i18n_rails', '~> 1.8.0'
gem 'gettext_i18n_rails_js', '~> 1.3'
gem 'gettext', '~> 3.2.2', require: false, group: :development
-gem 'batch-loader', '~> 1.2.2'
+gem 'batch-loader', '~> 1.4.0'
# Perf bar
gem 'peek', '~> 1.0.1'
@@ -300,17 +310,11 @@ group :metrics do
gem 'raindrops', '~> 0.18'
end
-group :tracing do
- # OpenTracing
- gem 'opentracing', '~> 0.4.3'
- gem 'jaeger-client', '~> 0.10.0'
-end
-
group :development do
gem 'foreman', '~> 0.84.0'
gem 'brakeman', '~> 4.2', require: false
- gem 'letter_opener_web', '~> 1.3.0'
+ gem 'letter_opener_web', '~> 1.3.4'
gem 'rblineprof', '~> 0.3.6', platform: :mri, require: false
# Better errors handler
@@ -333,7 +337,7 @@ group :development, :test do
gem 'database_cleaner', '~> 1.7.0'
gem 'factory_bot_rails', '~> 4.8.2'
gem 'rspec-rails', '~> 3.7.0'
- gem 'rspec-retry', '~> 0.4.5'
+ gem 'rspec-retry', '~> 0.6.1'
gem 'rspec_profiling', '~> 0.0.5'
gem 'rspec-set', '~> 0.1.3'
gem 'rspec-parameterized', require: false
@@ -344,21 +348,22 @@ group :development, :test do
# Generate Fake data
gem 'ffaker', '~> 2.10'
- gem 'capybara', '~> 2.18.0'
+ gem 'capybara', '~> 3.22.0'
gem 'capybara-screenshot', '~> 1.0.22'
gem 'selenium-webdriver', '~> 3.141'
gem 'spring', '~> 2.0.0'
gem 'spring-commands-rspec', '~> 1.0.4'
- gem 'gitlab-styles', '~> 2.5', require: false
+ gem 'gitlab-styles', '~> 2.7', require: false
# Pin these dependencies, otherwise a new rule could break the CI pipelines
- gem 'rubocop', '~> 0.54.0'
+ gem 'rubocop', '~> 0.69.0'
+ gem 'rubocop-performance', '~> 1.1.0'
gem 'rubocop-rspec', '~> 1.22.1'
gem 'scss_lint', '~> 0.56.0', require: false
- gem 'haml_lint', '~> 0.28.0', require: false
- gem 'simplecov', '~> 0.14.0', require: false
+ gem 'haml_lint', '~> 0.31.0', require: false
+ gem 'simplecov', '~> 0.16.1', require: false
gem 'bundler-audit', '~> 0.5.0', require: false
gem 'benchmark-ips', '~> 2.3.0', require: false
@@ -369,6 +374,7 @@ group :development, :test do
gem 'activerecord_sane_schema_dumper', '1.0'
gem 'stackprof', '~> 0.2.10', require: false
+ gem 'derailed_benchmarks', require: false
gem 'simple_po_parser', '~> 1.1.2', require: false
@@ -376,7 +382,7 @@ group :development, :test do
end
group :test do
- gem 'shoulda-matchers', '~> 3.1.2', require: false
+ gem 'shoulda-matchers', '~> 4.0.1', require: false
gem 'email_spec', '~> 2.2.0'
gem 'json-schema', '~> 2.8.0'
gem 'webmock', '~> 3.5.1'
@@ -396,6 +402,9 @@ gem 'html2text'
gem 'ruby-prof', '~> 0.17.0'
gem 'rbtrace', '~> 0.4', require: false
+gem 'memory_profiler', '~> 0.9', require: false
+gem 'benchmark-memory', '~> 0.1', require: false
+gem 'activerecord-explain-analyze', '~> 0.1', require: false
# OAuth
gem 'oauth2', '~> 1.4'
@@ -418,11 +427,11 @@ group :ed25519 do
end
# Gitaly GRPC client
-gem 'gitaly-proto', '~> 1.19.0', require: 'gitaly'
+gem 'gitaly-proto', '~> 1.32.0', require: 'gitaly'
-gem 'grpc', '~> 1.15.0'
+gem 'grpc', '~> 1.19.0'
-gem 'google-protobuf', '~> 3.6'
+gem 'google-protobuf', '~> 3.7.1'
gem 'toml-rb', '~> 1.0.0', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index 109958e2591..0159d1f96e8 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -4,41 +4,46 @@ GEM
RedCloth (4.3.2)
abstract_type (0.0.7)
ace-rails-ap (4.1.2)
- actioncable (5.0.7.2)
- actionpack (= 5.0.7.2)
- nio4r (>= 1.2, < 3.0)
+ acme-client (2.0.2)
+ faraday (~> 0.9, >= 0.9.1)
+ actioncable (5.1.7)
+ actionpack (= 5.1.7)
+ nio4r (~> 2.0)
websocket-driver (~> 0.6.1)
- actionmailer (5.0.7.2)
- actionpack (= 5.0.7.2)
- actionview (= 5.0.7.2)
- activejob (= 5.0.7.2)
+ actionmailer (5.1.7)
+ actionpack (= 5.1.7)
+ actionview (= 5.1.7)
+ activejob (= 5.1.7)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
- actionpack (5.0.7.2)
- actionview (= 5.0.7.2)
- activesupport (= 5.0.7.2)
+ actionpack (5.1.7)
+ actionview (= 5.1.7)
+ activesupport (= 5.1.7)
rack (~> 2.0)
- rack-test (~> 0.6.3)
+ rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
- actionview (5.0.7.2)
- activesupport (= 5.0.7.2)
+ actionview (5.1.7)
+ activesupport (= 5.1.7)
builder (~> 3.1)
- erubis (~> 2.7.0)
+ erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
- activejob (5.0.7.2)
- activesupport (= 5.0.7.2)
+ activejob (5.1.7)
+ activesupport (= 5.1.7)
globalid (>= 0.3.6)
- activemodel (5.0.7.2)
- activesupport (= 5.0.7.2)
- activerecord (5.0.7.2)
- activemodel (= 5.0.7.2)
- activesupport (= 5.0.7.2)
- arel (~> 7.0)
+ activemodel (5.1.7)
+ activesupport (= 5.1.7)
+ activerecord (5.1.7)
+ activemodel (= 5.1.7)
+ activesupport (= 5.1.7)
+ arel (~> 8.0)
+ activerecord-explain-analyze (0.1.0)
+ activerecord (>= 4)
+ pg
activerecord_sane_schema_dumper (1.0)
rails (>= 5, < 6)
- activesupport (5.0.7.2)
+ activesupport (5.1.7)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
@@ -52,13 +57,18 @@ GEM
public_suffix (>= 2.0.2, < 4.0)
aes_key_wrap (1.0.1)
akismet (2.0.0)
- arel (7.1.4)
+ apollo_upload_server (2.0.0.beta.3)
+ graphql (>= 1.8)
+ rails (>= 4.2)
+ arel (8.0.0)
asana (0.8.1)
faraday (~> 0.9)
faraday_middleware (~> 0.9)
faraday_middleware-multi_json (~> 0.0)
oauth2 (~> 1.0)
asciidoctor (1.5.8)
+ asciidoctor-include-ext (0.3.1)
+ asciidoctor (>= 1.5.6, < 3.0.0)
asciidoctor-plantuml (0.0.8)
asciidoctor (~> 1.5)
ast (2.4.0)
@@ -73,16 +83,18 @@ GEM
thread_safe (~> 0.3, >= 0.3.1)
babosa (1.0.2)
base32 (0.3.2)
- batch-loader (1.2.2)
+ batch-loader (1.4.0)
bcrypt (3.1.12)
bcrypt_pbkdf (1.0.0)
benchmark-ips (2.3.0)
+ benchmark-memory (0.1.2)
+ memory_profiler (~> 0.9)
better_errors (2.5.0)
coderay (>= 1.0.0)
erubi (>= 1.0.0)
rack (>= 0.9.0)
bindata (2.4.3)
- binding_ninja (0.2.2)
+ binding_ninja (0.2.3)
binding_of_caller (0.8.0)
debug_inspector (>= 0.0.1)
bootsnap (1.4.1)
@@ -100,13 +112,14 @@ GEM
bundler (~> 1.2)
thor (~> 0.18)
byebug (9.1.0)
- capybara (2.18.0)
+ capybara (3.22.0)
addressable
mini_mime (>= 0.1.3)
- nokogiri (>= 1.3.3)
- rack (>= 1.0.0)
- rack-test (>= 0.5.4)
- xpath (>= 2.0, < 4.0)
+ nokogiri (~> 1.8)
+ rack (>= 1.6.0)
+ rack-test (>= 0.6.3)
+ regexp_parser (~> 1.5)
+ xpath (~> 3.2)
capybara-screenshot (1.0.22)
capybara (>= 1.0, < 4)
launchy
@@ -132,9 +145,9 @@ GEM
concord (0.1.5)
adamantium (~> 0.2.0)
equalizer (~> 0.0.9)
- concurrent-ruby (1.1.3)
- concurrent-ruby-ext (1.1.3)
- concurrent-ruby (= 1.1.3)
+ concurrent-ruby (1.1.5)
+ concurrent-ruby-ext (1.1.5)
+ concurrent-ruby (= 1.1.5)
connection_pool (2.2.2)
crack (0.4.3)
safe_yaml (~> 1.0.0)
@@ -150,10 +163,18 @@ GEM
html-pipeline
declarative (0.0.10)
declarative-option (0.1.0)
+ derailed_benchmarks (1.3.5)
+ benchmark-ips (~> 2)
+ get_process_mem (~> 0)
+ heapy (~> 0)
+ memory_profiler (~> 0)
+ rack (>= 1)
+ rake (> 10, < 13)
+ thor (~> 0.19)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
device_detector (1.0.0)
- devise (4.4.3)
+ devise (4.6.2)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0, < 6.0)
@@ -169,7 +190,7 @@ GEM
diffy (3.1.0)
discordrb-webhooks-blackst0ne (3.3.0)
rest-client (~> 2.0)
- docile (1.1.5)
+ docile (1.3.1)
domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0)
doorkeeper (4.3.2)
@@ -185,10 +206,9 @@ GEM
mail (~> 2.7)
encryptor (3.0.0)
equalizer (0.0.11)
- erubi (1.7.1)
- erubis (2.7.0)
+ erubi (1.8.0)
escape_utils (1.2.1)
- et-orbi (1.1.7)
+ et-orbi (1.2.1)
tzinfo
eventmachine (1.2.7)
excon (0.62.0)
@@ -257,20 +277,20 @@ GEM
fog-xml (0.1.3)
fog-core
nokogiri (>= 1.5.11, < 2.0.0)
- font-awesome-rails (4.7.0.1)
- railties (>= 3.2, < 5.1)
+ font-awesome-rails (4.7.0.4)
+ railties (>= 3.2, < 6.0)
foreman (0.84.0)
thor (~> 0.19.1)
formatador (0.2.5)
- fugit (1.1.9)
- et-orbi (~> 1.1, >= 1.1.7)
+ fugit (1.2.1)
+ et-orbi (~> 1.1, >= 1.1.8)
raabro (~> 1.1)
fuubar (2.2.0)
rspec-core (~> 3.0)
ruby-progressbar (~> 1.4)
gemojione (3.3.0)
json
- get_process_mem (0.2.0)
+ get_process_mem (0.2.3)
gettext (3.2.9)
locale (>= 2.0.5)
text (>= 1.3.0)
@@ -281,17 +301,24 @@ GEM
gettext_i18n_rails (>= 0.7.1)
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
- gitaly-proto (1.19.0)
+ gitaly-proto (1.32.0)
grpc (~> 1.0)
github-markup (1.7.0)
gitlab-default_value_for (3.1.1)
activerecord (>= 3.2.0, < 6.0)
+ gitlab-labkit (0.2.0)
+ actionpack (~> 5)
+ activesupport (~> 5)
+ grpc (~> 1.15)
+ jaeger-client (~> 0.10)
+ opentracing (~> 0.4)
gitlab-markup (1.7.0)
gitlab-sidekiq-fetcher (0.4.0)
sidekiq (~> 5)
- gitlab-styles (2.5.2)
- rubocop (~> 0.54.0)
+ gitlab-styles (2.7.0)
+ rubocop (~> 0.69.0)
rubocop-gitlab-security (~> 0.1.0)
+ rubocop-performance (~> 1.1.0)
rubocop-rspec (~> 1.19)
gitlab_omniauth-ldap (2.1.1)
net-ldap (~> 0.16)
@@ -311,8 +338,8 @@ GEM
mime-types (~> 3.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
- google-protobuf (3.6.1)
- googleapis-common-protos-types (1.0.3)
+ google-protobuf (3.7.1)
+ googleapis-common-protos-types (1.0.4)
google-protobuf (~> 3.0)
googleauth (0.6.6)
faraday (~> 0.12)
@@ -333,8 +360,8 @@ GEM
grape-entity (0.7.1)
activesupport (>= 4.0)
multi_json (>= 1.3.2)
- grape-path-helpers (1.0.6)
- activesupport (>= 4, < 5.1)
+ grape-path-helpers (1.1.0)
+ activesupport
grape (~> 1.0)
rake (~> 12)
grape_logging (1.7.0)
@@ -343,13 +370,13 @@ GEM
railties
sprockets-rails
graphql (1.8.1)
- grpc (1.15.0)
+ grpc (1.19.0)
google-protobuf (~> 3.1)
googleapis-common-protos-types (~> 1.0.0)
haml (5.0.4)
temple (>= 0.8.0)
tilt
- haml_lint (0.28.0)
+ haml_lint (0.31.0)
haml (>= 4.0, < 5.1)
rainbow
rake (>= 10, < 13)
@@ -366,6 +393,7 @@ GEM
hashie (>= 3.0)
health_check (2.6.0)
rails (>= 4.0)
+ heapy (0.1.4)
hipchat (1.5.2)
httparty
mimemagic
@@ -399,6 +427,7 @@ GEM
jaeger-client (0.10.0)
opentracing (~> 0.3)
thrift
+ jaro_winkler (1.5.2)
jira-ruby (1.4.1)
activesupport
multipart-post
@@ -436,9 +465,9 @@ GEM
rest-client (~> 2.0)
launchy (2.4.3)
addressable (~> 2.3)
- letter_opener (1.4.1)
+ letter_opener (1.7.0)
launchy (~> 2.2)
- letter_opener_web (1.3.0)
+ letter_opener_web (1.3.4)
actionmailer (>= 3.2)
letter_opener (~> 1.0)
railties (>= 3.2)
@@ -466,6 +495,7 @@ GEM
memoist (0.16.0)
memoizable (0.4.2)
thread_safe (~> 0.3, >= 0.3.1)
+ memory_profiler (0.9.13)
method_source (0.9.2)
mime-types (3.2.2)
mime-types-data (~> 3.2015)
@@ -488,7 +518,7 @@ GEM
net-ssh (5.0.1)
netrc (0.11.0)
nio4r (2.3.1)
- nokogiri (1.10.2)
+ nokogiri (1.10.3)
mini_portile2 (~> 2.4.0)
nokogumbo (1.5.0)
nokogiri
@@ -543,6 +573,9 @@ GEM
omniauth (~> 1.9)
omniauth-oauth2-generic (0.2.2)
omniauth-oauth2 (~> 1.0)
+ omniauth-salesforce (1.0.5)
+ omniauth (~> 1.0)
+ omniauth-oauth2 (~> 1.0)
omniauth-saml (1.10.0)
omniauth (~> 1.3, >= 1.3.2)
ruby-saml (~> 1.7)
@@ -551,18 +584,34 @@ GEM
omniauth-twitter (1.4.0)
omniauth-oauth (~> 1.1)
rack
+ omniauth-ultraauth (0.0.2)
+ omniauth_openid_connect (~> 0.3.0)
omniauth_crowd (2.2.3)
activesupport
nokogiri (>= 1.4.4)
omniauth (~> 1.0)
- opentracing (0.4.3)
+ omniauth_openid_connect (0.3.1)
+ addressable (~> 2.5)
+ omniauth (~> 1.3)
+ openid_connect (~> 1.1)
+ openid_connect (1.1.6)
+ activemodel
+ attr_required (>= 1.0.0)
+ json-jwt (>= 1.5.0)
+ rack-oauth2 (>= 1.6.1)
+ swd (>= 1.0.0)
+ tzinfo
+ validate_email
+ validate_url
+ webfinger (>= 1.0.1)
+ opentracing (0.5.0)
optimist (3.0.0)
org-ruby (0.9.12)
rubypants (~> 0.2)
orm_adapter (0.5.0)
os (1.0.0)
- parallel (1.12.1)
- parser (2.5.3.0)
+ parallel (1.17.0)
+ parser (2.6.3.0)
ast (~> 2.4.0)
parslet (1.8.2)
peek (1.0.1)
@@ -591,7 +640,6 @@ GEM
pg (1.1.4)
po_to_json (1.0.1)
json (>= 1.6.0)
- powerpack (0.1.1)
premailer (1.10.4)
addressable
css_parser (>= 1.4.10)
@@ -613,7 +661,7 @@ GEM
pry (~> 0.10)
pry-rails (0.3.6)
pry (>= 0.10.4)
- public_suffix (3.0.3)
+ public_suffix (3.1.0)
puma (3.12.0)
puma_worker_killer (0.1.0)
get_process_mem (~> 0.2)
@@ -636,19 +684,20 @@ GEM
rack
rack-proxy (0.6.0)
rack
- rack-test (0.6.3)
- rack (>= 1.0)
- rails (5.0.7.2)
- actioncable (= 5.0.7.2)
- actionmailer (= 5.0.7.2)
- actionpack (= 5.0.7.2)
- actionview (= 5.0.7.2)
- activejob (= 5.0.7.2)
- activemodel (= 5.0.7.2)
- activerecord (= 5.0.7.2)
- activesupport (= 5.0.7.2)
+ rack-test (1.1.0)
+ rack (>= 1.0, < 3)
+ rack-timeout (0.5.1)
+ rails (5.1.7)
+ actioncable (= 5.1.7)
+ actionmailer (= 5.1.7)
+ actionpack (= 5.1.7)
+ actionview (= 5.1.7)
+ activejob (= 5.1.7)
+ activemodel (= 5.1.7)
+ activerecord (= 5.1.7)
+ activesupport (= 5.1.7)
bundler (>= 1.3.0)
- railties (= 5.0.7.2)
+ railties (= 5.1.7)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.2)
actionpack (~> 5.x, >= 5.0.1)
@@ -662,9 +711,9 @@ GEM
rails-i18n (5.1.1)
i18n (>= 0.7, < 2)
railties (>= 5.0, < 6)
- railties (5.0.7.2)
- actionpack (= 5.0.7.2)
- activesupport (= 5.0.7.2)
+ railties (5.1.7)
+ actionpack (= 5.1.7)
+ activesupport (= 5.1.7)
method_source
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
@@ -704,7 +753,7 @@ GEM
redis-store (>= 1.2, < 2)
redis-store (1.6.0)
redis (>= 2.2, < 5)
- regexp_parser (1.4.0)
+ regexp_parser (1.5.1)
regexp_property_values (0.3.4)
representable (3.0.4)
declarative (< 0.1.0)
@@ -738,8 +787,8 @@ GEM
rspec-mocks (3.7.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.7.0)
- rspec-parameterized (0.4.1)
- binding_ninja (>= 0.2.1)
+ rspec-parameterized (0.4.2)
+ binding_ninja (>= 0.2.3)
parser
proc_to_ast
rspec (>= 2.13, < 4)
@@ -752,8 +801,8 @@ GEM
rspec-expectations (~> 3.7.0)
rspec-mocks (~> 3.7.0)
rspec-support (~> 3.7.0)
- rspec-retry (0.4.5)
- rspec-core
+ rspec-retry (0.6.1)
+ rspec-core (> 3.3)
rspec-set (0.1.3)
rspec-support (3.7.1)
rspec_junit_formatter (0.4.1)
@@ -763,15 +812,17 @@ GEM
pg
rails
sqlite3
- rubocop (0.54.0)
+ rubocop (0.69.0)
+ jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
- parser (>= 2.5)
- powerpack (~> 0.1)
+ parser (>= 2.6)
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7)
- unicode-display_width (~> 1.0, >= 1.0.1)
+ unicode-display_width (>= 1.4.0, < 1.7)
rubocop-gitlab-security (0.1.1)
rubocop (>= 0.51)
+ rubocop-performance (1.1.0)
+ rubocop (>= 0.67.0)
rubocop-rspec (1.22.2)
rubocop (>= 0.52.1)
ruby-enum (0.7.2)
@@ -779,10 +830,10 @@ GEM
ruby-fogbugz (0.2.1)
crack (~> 0.4)
ruby-prof (0.17.0)
- ruby-progressbar (1.9.0)
+ ruby-progressbar (1.10.0)
ruby-saml (1.7.2)
nokogiri (>= 1.5.10)
- ruby_parser (3.11.0)
+ ruby_parser (3.13.1)
sexp_processor (~> 4.9)
rubyntlm (0.6.2)
rubypants (0.2.0)
@@ -798,12 +849,15 @@ GEM
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
- sass-rails (5.0.6)
- railties (>= 4.0.0, < 6)
- sass (~> 3.1)
- sprockets (>= 2.8, < 4.0)
- sprockets-rails (>= 2.0, < 4.0)
- tilt (>= 1.1, < 3)
+ sassc (2.0.1)
+ ffi (~> 1.9)
+ rake
+ sassc-rails (2.1.0)
+ railties (>= 4.0.0)
+ sassc (>= 2.0)
+ sprockets (> 3.0)
+ sprockets-rails
+ tilt
sawyer (0.8.1)
addressable (>= 2.3.5, < 2.6)
faraday (~> 0.8, < 1.0)
@@ -819,12 +873,12 @@ GEM
sentry-raven (2.9.0)
faraday (>= 0.7.6, < 1.0)
settingslogic (2.0.9)
- sexp_processor (4.11.0)
+ sexp_processor (4.12.0)
sham_rack (1.3.6)
rack
- shoulda-matchers (3.1.2)
- activesupport (>= 4.0.0)
- sidekiq (5.2.5)
+ shoulda-matchers (4.0.1)
+ activesupport (>= 4.2.0)
+ sidekiq (5.2.7)
connection_pool (~> 2.2, >= 2.2.2)
rack (>= 1.5.0)
rack-protection (>= 1.5.0)
@@ -838,11 +892,11 @@ GEM
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simple_po_parser (1.1.2)
- simplecov (0.14.1)
- docile (~> 1.1.0)
+ simplecov (0.16.1)
+ docile (~> 1.1)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
- simplecov-html (0.10.0)
+ simplecov-html (0.10.2)
slack-notifier (1.5.1)
spring (2.0.2)
activesupport (>= 4.2)
@@ -865,6 +919,10 @@ GEM
state_machines-activerecord (0.5.1)
activerecord (>= 4.1, < 6.0)
state_machines-activemodel (>= 0.5.0)
+ swd (1.1.2)
+ activesupport (>= 3)
+ attr_required (>= 0.0.5)
+ httpclient (>= 2.4)
sys-filesystem (1.1.6)
ffi
sysexits (1.2.0)
@@ -898,7 +956,7 @@ GEM
unf (0.1.4)
unf_ext
unf_ext (0.0.7.5)
- unicode-display_width (1.3.2)
+ unicode-display_width (1.6.0)
unicorn (5.4.1)
kgio (~> 2.6)
raindrops (~> 0.7)
@@ -906,14 +964,20 @@ GEM
get_process_mem (~> 0)
unicorn (>= 4, < 6)
uniform_notifier (1.10.0)
- unparser (0.4.2)
+ unparser (0.4.5)
abstract_type (~> 0.0.7)
adamantium (~> 0.2.0)
concord (~> 0.1.5)
diff-lcs (~> 1.3)
equalizer (~> 0.0.9)
- parser (>= 2.3.1.2, < 2.6)
+ parser (~> 2.6.3)
procto (~> 0.0.2)
+ validate_email (0.1.6)
+ activemodel (>= 3.0)
+ mail (>= 2.2.5)
+ validate_url (1.0.8)
+ activemodel (>= 3.0.0)
+ public_suffix
validates_hostname (1.0.6)
activerecord (>= 3.0)
activesupport (>= 3.0)
@@ -926,6 +990,9 @@ GEM
vmstat (2.3.0)
warden (1.2.7)
rack (>= 1.0)
+ webfinger (1.1.0)
+ activesupport
+ httpclient (>= 2.4)
webmock (3.5.1)
addressable (>= 2.3.6)
crack (>= 0.3.2)
@@ -950,20 +1017,25 @@ PLATFORMS
DEPENDENCIES
RedCloth (~> 4.3.2)
ace-rails-ap (~> 4.1.0)
+ acme-client (~> 2.0.2)
+ activerecord-explain-analyze (~> 0.1)
activerecord_sane_schema_dumper (= 1.0)
acts-as-taggable-on (~> 6.0)
addressable (~> 2.5.2)
akismet (~> 2.0)
+ apollo_upload_server (~> 2.0.0.beta3)
asana (~> 0.8.1)
asciidoctor (~> 1.5.8)
+ asciidoctor-include-ext (~> 0.3.1)
asciidoctor-plantuml (= 0.0.8)
attr_encrypted (~> 3.1.0)
awesome_print
babosa (~> 1.0.2)
base32 (~> 0.3.0)
- batch-loader (~> 1.2.2)
+ batch-loader (~> 1.4.0)
bcrypt_pbkdf (~> 1.0)
benchmark-ips (~> 2.3.0)
+ benchmark-memory (~> 0.1)
better_errors (~> 2.5.0)
binding_of_caller (~> 0.8.0)
bootsnap (~> 1.4)
@@ -972,7 +1044,7 @@ DEPENDENCIES
browser (~> 2.5)
bullet (~> 5.5.0)
bundler-audit (~> 0.5.0)
- capybara (~> 2.18.0)
+ capybara (~> 3.22.0)
capybara-screenshot (~> 1.0.22)
carrierwave (~> 1.3)
charlock_holmes (~> 0.7.5)
@@ -984,8 +1056,9 @@ DEPENDENCIES
creole (~> 0.5.0)
database_cleaner (~> 1.7.0)
deckar01-task_list (= 2.2.0)
+ derailed_benchmarks
device_detector
- devise (~> 4.4)
+ devise (~> 4.6)
devise-two-factor (~> 3.0.0)
diffy (~> 3.1.0)
discordrb-webhooks-blackst0ne (~> 3.3)
@@ -1012,31 +1085,32 @@ DEPENDENCIES
fog-rackspace (~> 0.1.1)
font-awesome-rails (~> 4.7)
foreman (~> 0.84.0)
- fugit (~> 1.1)
+ fugit (~> 1.2.1)
fuubar (~> 2.2.0)
gemojione (~> 3.3)
gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
- gitaly-proto (~> 1.19.0)
+ gitaly-proto (~> 1.32.0)
github-markup (~> 1.7.0)
gitlab-default_value_for (~> 3.1.1)
+ gitlab-labkit (~> 0.2.0)
gitlab-markup (~> 1.7.0)
gitlab-sidekiq-fetcher (~> 0.4.0)
- gitlab-styles (~> 2.5)
+ gitlab-styles (~> 2.7)
gitlab_omniauth-ldap (~> 2.1.1)
gon (~> 6.2)
google-api-client (~> 0.23)
- google-protobuf (~> 3.6)
+ google-protobuf (~> 3.7.1)
gpgme (~> 2.0.18)
grape (~> 1.1.0)
grape-entity (~> 0.7.1)
- grape-path-helpers (~> 1.0)
+ grape-path-helpers (~> 1.1)
grape_logging (~> 1.7)
graphiql-rails (~> 1.4.10)
graphql (~> 1.8.0)
- grpc (~> 1.15.0)
- haml_lint (~> 0.28.0)
+ grpc (~> 1.19.0)
+ haml_lint (~> 0.31.0)
hamlit (~> 2.8.8)
hangouts-chat (~> 0.0.5)
hashie-forbidden_attributes
@@ -1047,7 +1121,6 @@ DEPENDENCIES
httparty (~> 0.16.4)
icalendar
influxdb (~> 0.2)
- jaeger-client (~> 0.10.0)
jira-ruby (~> 1.4)
js_regex (~> 3.1)
json-schema (~> 2.8.0)
@@ -1055,12 +1128,13 @@ DEPENDENCIES
kaminari (~> 1.0)
knapsack (~> 1.17)
kubeclient (~> 4.2.2)
- letter_opener_web (~> 1.3.0)
+ letter_opener_web (~> 1.3.4)
license_finder (~> 5.4)
licensee (~> 8.9)
lograge (~> 0.5)
loofah (~> 2.2)
mail_room (~> 0.9.1)
+ memory_profiler (~> 0.9)
method_source (~> 0.8)
mimemagic (~> 0.3.2)
mini_magick
@@ -1069,7 +1143,7 @@ DEPENDENCIES
nakayoshi_fork (~> 0.0.4)
net-ldap
net-ssh (~> 5.0)
- nokogiri (~> 1.10.1)
+ nokogiri (~> 1.10.3)
oauth2 (~> 1.4)
octokit (~> 4.9)
omniauth (~> 1.8)
@@ -1083,11 +1157,13 @@ DEPENDENCIES
omniauth-google-oauth2 (~> 0.6.0)
omniauth-kerberos (~> 0.3.0)
omniauth-oauth2-generic (~> 0.2.2)
+ omniauth-salesforce (~> 1.0.5)
omniauth-saml (~> 1.10)
omniauth-shibboleth (~> 1.3.0)
omniauth-twitter (~> 1.4)
+ omniauth-ultraauth (~> 0.0.2)
omniauth_crowd (~> 2.2.0)
- opentracing (~> 0.4.3)
+ omniauth_openid_connect (~> 0.3.1)
org-ruby (~> 0.9.12)
peek (~> 1.0.1)
peek-gc (~> 0.0.2)
@@ -1107,7 +1183,8 @@ DEPENDENCIES
rack-cors (~> 1.0.0)
rack-oauth2 (~> 1.9.3)
rack-proxy (~> 0.6.0)
- rails (= 5.0.7.2)
+ rack-timeout
+ rails (= 5.1.7)
rails-controller-testing
rails-i18n (~> 5.1)
rainbow (~> 3.0)
@@ -1126,11 +1203,12 @@ DEPENDENCIES
rqrcode-rails3 (~> 0.1.7)
rspec-parameterized
rspec-rails (~> 3.7.0)
- rspec-retry (~> 0.4.5)
+ rspec-retry (~> 0.6.1)
rspec-set (~> 0.1.3)
rspec_junit_formatter
rspec_profiling (~> 0.0.5)
- rubocop (~> 0.54.0)
+ rubocop (~> 0.69.0)
+ rubocop-performance (~> 1.1.0)
rubocop-rspec (~> 1.22.1)
ruby-fogbugz (~> 0.2.1)
ruby-prof (~> 0.17.0)
@@ -1139,19 +1217,18 @@ DEPENDENCIES
rubyzip (~> 1.2.2)
rugged (~> 0.28)
sanitize (~> 4.6)
- sass (~> 3.5)
- sass-rails (~> 5.0.6)
+ sassc-rails (~> 2.1.0)
scss_lint (~> 0.56.0)
seed-fu (~> 2.3.7)
selenium-webdriver (~> 3.141)
- sentry-raven (~> 2.7)
+ sentry-raven (~> 2.9)
settingslogic (~> 2.0.9)
sham_rack (~> 1.3.6)
- shoulda-matchers (~> 3.1.2)
- sidekiq (~> 5.2.1)
+ shoulda-matchers (~> 4.0.1)
+ sidekiq (~> 5.2.7)
sidekiq-cron (~> 1.0)
simple_po_parser (~> 1.1.2)
- simplecov (~> 0.14.0)
+ simplecov (~> 0.16.1)
slack-notifier (~> 1.5.1)
spring (~> 2.0.0)
spring-commands-rspec (~> 1.0.4)
diff --git a/PROCESS.md b/PROCESS.md
index 1f99cebe081..07b150ea463 100644
--- a/PROCESS.md
+++ b/PROCESS.md
@@ -64,7 +64,7 @@ The milestone of an issue that is currently being worked on by a community contr
should not be set to a named GitLab milestone (e.g. 11.7, 11.8), until the associated
merge request is very close to being merged, and we will likely know in which named
GitLab milestone the issue will land. There are many factors that influence when
-a community contributor finishes an issue, or even at all. So we should set this
+a community contributor finishes an issue, or even at all. So we should set this
milestone only when we have more certainty.
Note this only applies to issues currently assigned to community contributors. For
@@ -86,21 +86,10 @@ star, smile, etc.). Some good tips about code reviews can be found in our
## Feature freeze on the 7th for the release on the 22nd
-After 7th at 23:59 (Pacific Time Zone) of each month, stable branch and RC1
-of the upcoming release (to be shipped on the 22nd) is created and deployed to GitLab.com.
-The stable branch is frozen at the most recent "qualifying commit" on master.
-A "qualifying commit" is one that is pushed before the feature freeze cutoff time
-and that passes all CI jobs (green pipeline).
-
-Merge requests may still be merged into master during this
-period, but they will go into the _next_ release, unless they are manually
-cherry-picked into the stable branch.
-
-By freezing the stable branches 2 weeks prior to a release, we reduce the risk
-of a last minute merge request potentially breaking things.
-
-Any release candidate that gets created after this date can become a final
-release, hence the name release candidate.
+The feature freeze on the 7th has been discontinued. The [transition period overview](https://gitlab.com/gitlab-org/release/docs/blob/21cbd409dd5f157fe252f254f3e897f01908abe2/general/deploy/auto-deploy-transition.md#transition)
+describes the change to this process. During the transition period, the only guarantee that
+a change will be included in the release on the 22nd is if the change has been
+deployed to GitLab.com prior to this date.
### Feature flags
@@ -108,15 +97,15 @@ Merge requests that make changes hidden behind a feature flag, or remove an
existing feature flag because a feature is deemed stable, may be merged (and
picked into the stable branches) up to the 19th of the month. Such merge
requests should have the ~"feature flag" label assigned, and don't require a
-corresponding exception request to be created.
+corresponding exception request to be created.
-A level of common sense should be applied when deciding whether to have a feature
+A level of common sense should be applied when deciding whether to have a feature
behind a feature flag off or on by default.
-The following guideliness can be applied to help make this decision:
+The following guidelines can be applied to help make this decision:
* If the feature is not fully ready or functioning, the feature flag should be disabled by default.
-* If the feature is ready but there are concerns about performance or impact, the feature flag should be enabled by default, but
+* If the feature is ready but there are concerns about performance or impact, the feature flag should be enabled by default, but
disabled via chatops before deployment on GitLab.com environments. If the performance concern is confirmed, the final release should have the feature flag disabled by default.
* In most other cases, the feature flag can be enabled by default.
@@ -125,7 +114,7 @@ For more information on rolling out changes using feature flags, read [through t
In order to build the final package and present the feature for self-hosted
customers, the feature flag should be removed. This should happen before the
22nd, ideally _at least_ 2 days before. That means MRs with feature
-flags being picked at the 19th would have a quite tight schedule, so picking
+flags being picked at the 19th would have quite a tight schedule, so picking
these _earlier_ is preferable.
While rare, release managers may decide to reject picking a change into a stable
diff --git a/VERSION b/VERSION
index 1a954017bf3..11bf1ec035c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-11.10.0-pre
+12.0.0-pre
diff --git a/app/assets/images/favicon-yellow.png b/app/assets/images/favicon-yellow.png
index 2d5289818b4..a80827808fc 100644
--- a/app/assets/images/favicon-yellow.png
+++ b/app/assets/images/favicon-yellow.png
Binary files differ
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index 8754c253881..7cebb88f3a4 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -1,6 +1,7 @@
import $ from 'jquery';
import _ from 'underscore';
import axios from './lib/utils/axios_utils';
+import { joinPaths } from './lib/utils/url_utility';
const Api = {
groupsPath: '/api/:version/groups.json',
@@ -11,7 +12,7 @@ const Api = {
groupProjectsPath: '/api/:version/groups/:id/projects.json',
projectsPath: '/api/:version/projects.json',
projectPath: '/api/:version/projects/:id',
- projectLabelsPath: '/:namespace_path/:project_path/labels',
+ projectLabelsPath: '/:namespace_path/:project_path/-/labels',
projectMergeRequestsPath: '/api/:version/projects/:id/merge_requests',
projectMergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid',
projectMergeRequestChangesPath: '/api/:version/projects/:id/merge_requests/:mrid/changes',
@@ -339,11 +340,7 @@ const Api = {
},
buildUrl(url) {
- let urlRoot = '';
- if (gon.relative_url_root != null) {
- urlRoot = gon.relative_url_root;
- }
- return urlRoot + url.replace(':version', gon.api_version);
+ return joinPaths(gon.relative_url_root || '', url.replace(':version', gon.api_version));
},
};
diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js
index 743f11625bc..aaab217964c 100644
--- a/app/assets/javascripts/awards_handler.js
+++ b/app/assets/javascripts/awards_handler.js
@@ -1,4 +1,4 @@
-/* eslint-disable class-methods-use-this */
+/* eslint-disable class-methods-use-this, @gitlab/i18n/no-non-i18n-strings */
import $ from 'jquery';
import _ from 'underscore';
diff --git a/app/assets/javascripts/batch_comments/mixins/resolved_status.js b/app/assets/javascripts/batch_comments/mixins/resolved_status.js
new file mode 100644
index 00000000000..3bbbaa86b51
--- /dev/null
+++ b/app/assets/javascripts/batch_comments/mixins/resolved_status.js
@@ -0,0 +1,15 @@
+import { sprintf, __ } from '~/locale';
+
+export default {
+ computed: {
+ resolveButtonTitle() {
+ let title = __('Mark comment as resolved');
+
+ if (this.resolvedBy) {
+ title = sprintf(__('Resolved by %{name}'), { name: this.resolvedBy.name });
+ }
+
+ return title;
+ },
+ },
+};
diff --git a/app/assets/javascripts/behaviors/copy_to_clipboard.js b/app/assets/javascripts/behaviors/copy_to_clipboard.js
index 9a33a060c76..c3541e62568 100644
--- a/app/assets/javascripts/behaviors/copy_to_clipboard.js
+++ b/app/assets/javascripts/behaviors/copy_to_clipboard.js
@@ -1,5 +1,6 @@
import $ from 'jquery';
import Clipboard from 'clipboard';
+import { sprintf, __ } from '~/locale';
function showTooltip(target, title) {
const $target = $(target);
@@ -16,7 +17,7 @@ function showTooltip(target, title) {
}
function genericSuccess(e) {
- showTooltip(e.trigger, 'Copied');
+ showTooltip(e.trigger, __('Copied'));
// Clear the selection and blur the trigger so it loses its border
e.clearSelection();
$(e.trigger).blur();
@@ -33,7 +34,7 @@ function genericError(e) {
} else {
key = 'Ctrl';
}
- showTooltip(e.trigger, `Press ${key}-C to copy`);
+ showTooltip(e.trigger, sprintf(__(`Press %{key}-C to copy`), { key }));
}
export default function initCopyToClipboard() {
diff --git a/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js b/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js
index 55c68139ded..b7200150925 100644
--- a/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js
+++ b/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import { parseBoolean } from '~/lib/utils/common_utils';
-import GfmAutoComplete from '~/gfm_auto_complete';
+import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
export default function initGFMInput() {
$('.js-gfm-input:not(.js-vue-textarea)').each((i, el) => {
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/table_of_contents.js b/app/assets/javascripts/behaviors/markdown/nodes/table_of_contents.js
index 20c7fa8a9ab..9a2e2c03213 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/table_of_contents.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/table_of_contents.js
@@ -1,6 +1,7 @@
/* eslint-disable class-methods-use-this */
import { Node } from 'tiptap';
+import { __ } from '~/locale';
// Transforms generated HTML back to GFM for Banzai::Filter::TableOfContentsFilter
export default class TableOfContents extends Node {
@@ -22,7 +23,7 @@ export default class TableOfContents extends Node {
priority: 51,
},
],
- toDOM: () => ['p', { class: 'table-of-contents' }, 'Table of Contents'],
+ toDOM: () => ['p', { class: 'table-of-contents' }, __('Table of Contents')],
};
}
diff --git a/app/assets/javascripts/behaviors/markdown/render_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
index 798114b4b0b..d0b7f3ff7a2 100644
--- a/app/assets/javascripts/behaviors/markdown/render_mermaid.js
+++ b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
@@ -15,7 +15,7 @@ import { sprintf, __ } from '../../locale';
// </pre>
//
-// This is an arbitary number; Can be iterated upon when suitable.
+// This is an arbitrary number; Can be iterated upon when suitable.
const MAX_CHAR_LIMIT = 5000;
export default function renderMermaid($els) {
diff --git a/app/assets/javascripts/behaviors/preview_markdown.js b/app/assets/javascripts/behaviors/preview_markdown.js
index 7adccbb062f..35874140bf9 100644
--- a/app/assets/javascripts/behaviors/preview_markdown.js
+++ b/app/assets/javascripts/behaviors/preview_markdown.js
@@ -22,7 +22,7 @@ function MarkdownPreview() {}
// Minimum number of users referenced before triggering a warning
MarkdownPreview.prototype.referenceThreshold = 10;
-MarkdownPreview.prototype.emptyMessage = 'Nothing to preview.';
+MarkdownPreview.prototype.emptyMessage = __('Nothing to preview.');
MarkdownPreview.prototype.ajaxCache = {};
@@ -40,7 +40,7 @@ MarkdownPreview.prototype.showPreview = function($form) {
preview.text(this.emptyMessage);
this.hideReferencedUsers($form);
} else {
- preview.addClass('md-preview-loading').text('Loading...');
+ preview.addClass('md-preview-loading').text(__('Loading...'));
this.fetchMarkdownPreview(
mdText,
url,
diff --git a/app/assets/javascripts/behaviors/quick_submit.js b/app/assets/javascripts/behaviors/quick_submit.js
index c1ea67f9293..530ab0bd4d9 100644
--- a/app/assets/javascripts/behaviors/quick_submit.js
+++ b/app/assets/javascripts/behaviors/quick_submit.js
@@ -1,6 +1,7 @@
import $ from 'jquery';
import '../commons/bootstrap';
import { isInIssuePage } from '../lib/utils/common_utils';
+import { __ } from '~/locale';
// Quick Submit behavior
//
@@ -65,7 +66,9 @@ $(document).on(
}
const $this = $(this);
- const title = isMac() ? 'You can also press &#8984;-Enter' : 'You can also press Ctrl-Enter';
+ const title = isMac()
+ ? __('You can also press &#8984;-Enter')
+ : __('You can also press Ctrl-Enter');
$this.tooltip({
container: 'body',
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
index 670f66b005e..c8eb96a625c 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
@@ -37,7 +37,7 @@ export default class ShortcutsIssuable extends Shortcuts {
}
// Sanity check: Make sure the selected text comes from a discussion : it can either contain a message...
- let foundMessage = !!documentFragment.querySelector('.md');
+ let foundMessage = Boolean(documentFragment.querySelector('.md'));
// ... Or come from a message
if (!foundMessage) {
diff --git a/app/assets/javascripts/blob/balsamiq_viewer.js b/app/assets/javascripts/blob/balsamiq_viewer.js
index b88e69a07bf..2e537d8c000 100644
--- a/app/assets/javascripts/blob/balsamiq_viewer.js
+++ b/app/assets/javascripts/blob/balsamiq_viewer.js
@@ -1,8 +1,9 @@
import Flash from '../flash';
import BalsamiqViewer from './balsamiq/balsamiq_viewer';
+import { __ } from '~/locale';
function onError() {
- const flash = new Flash('Balsamiq file could not be loaded.');
+ const flash = new Flash(__('Balsamiq file could not be loaded.'));
return flash;
}
diff --git a/app/assets/javascripts/blob/blob_file_dropzone.js b/app/assets/javascripts/blob/blob_file_dropzone.js
index cd3251ad1ca..9010cd0c3c1 100644
--- a/app/assets/javascripts/blob/blob_file_dropzone.js
+++ b/app/assets/javascripts/blob/blob_file_dropzone.js
@@ -5,6 +5,7 @@ import Dropzone from 'dropzone';
import { visitUrl } from '../lib/utils/url_utility';
import { HIDDEN_CLASS } from '../lib/utils/constants';
import csrf from '../lib/utils/csrf';
+import { sprintf, __ } from '~/locale';
Dropzone.autoDiscover = false;
@@ -73,7 +74,7 @@ export default class BlobFileDropzone {
.html(errorMessage)
.text();
$('.dropzone-alerts')
- .html(`Error uploading file: "${stripped}"`)
+ .html(sprintf(__('Error uploading file: %{stripped}'), { stripped }))
.show();
this.removeFile(file);
},
@@ -84,7 +85,7 @@ export default class BlobFileDropzone {
e.stopPropagation();
if (dropzone[0].dropzone.getQueuedFiles().length === 0) {
// eslint-disable-next-line no-alert
- alert('Please select a file');
+ alert(__('Please select a file'));
return false;
}
toggleLoading(submitButton, submitButtonLoadingIcon, true);
diff --git a/app/assets/javascripts/blob/sketch/index.js b/app/assets/javascripts/blob/sketch/index.js
index 57c1baa9886..dbff03dc734 100644
--- a/app/assets/javascripts/blob/sketch/index.js
+++ b/app/assets/javascripts/blob/sketch/index.js
@@ -1,5 +1,6 @@
import JSZip from 'jszip';
import JSZipUtils from 'jszip-utils';
+import { __ } from '~/locale';
export default class SketchLoader {
constructor(container) {
@@ -56,10 +57,10 @@ export default class SketchLoader {
const errorMsg = document.createElement('p');
errorMsg.className = 'prepend-top-default append-bottom-default text-center';
- errorMsg.textContent = `
+ errorMsg.textContent = __(`
Cannot show preview. For previews on sketch files, they must have the file format
introduced by Sketch version 43 and above.
- `;
+ `);
this.container.appendChild(errorMsg);
this.removeLoadingIcon();
diff --git a/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js b/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js
index 4718b642617..659d57e6a6f 100644
--- a/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js
@@ -1,11 +1,12 @@
import FileTemplateSelector from '../file_template_selector';
+import { __ } from '~/locale';
export default class DockerfileSelector extends FileTemplateSelector {
constructor({ mediator }) {
super(mediator);
this.config = {
key: 'dockerfile',
- name: 'Dockerfile',
+ name: __('Dockerfile'),
pattern: /(Dockerfile)/,
type: 'dockerfiles',
dropdown: '.js-dockerfile-selector',
diff --git a/app/assets/javascripts/blob/viewer/index.js b/app/assets/javascripts/blob/viewer/index.js
index d0359fc5fe9..d246a1f6064 100644
--- a/app/assets/javascripts/blob/viewer/index.js
+++ b/app/assets/javascripts/blob/viewer/index.js
@@ -2,6 +2,7 @@ import $ from 'jquery';
import Flash from '../../flash';
import { handleLocationHash } from '../../lib/utils/common_utils';
import axios from '../../lib/utils/axios_utils';
+import { __ } from '~/locale';
export default class BlobViewer {
constructor() {
@@ -26,7 +27,7 @@ export default class BlobViewer {
promise
.then(module => module.default(viewer))
.catch(error => {
- Flash('Error loading file viewer.');
+ Flash(__('Error loading file viewer.'));
throw error;
});
@@ -106,16 +107,19 @@ export default class BlobViewer {
if (!this.copySourceBtn) return;
if (this.simpleViewer.getAttribute('data-loaded')) {
- this.copySourceBtn.setAttribute('title', 'Copy source to clipboard');
+ this.copySourceBtn.setAttribute('title', __('Copy source to clipboard'));
this.copySourceBtn.classList.remove('disabled');
} else if (this.activeViewer === this.simpleViewer) {
this.copySourceBtn.setAttribute(
'title',
- 'Wait for the source to load to copy it to the clipboard',
+ __('Wait for the source to load to copy it to the clipboard'),
);
this.copySourceBtn.classList.add('disabled');
} else {
- this.copySourceBtn.setAttribute('title', 'Switch to the source to copy it to the clipboard');
+ this.copySourceBtn.setAttribute(
+ 'title',
+ __('Switch to the source to copy it to the clipboard'),
+ );
this.copySourceBtn.classList.add('disabled');
}
@@ -158,7 +162,7 @@ export default class BlobViewer {
this.toggleCopyButtonState();
})
- .catch(() => new Flash('Error loading viewer'));
+ .catch(() => new Flash(__('Error loading viewer')));
}
static loadViewer(viewerParam) {
diff --git a/app/assets/javascripts/boards/boards_util.js b/app/assets/javascripts/boards/boards_util.js
new file mode 100644
index 00000000000..3178bda93b8
--- /dev/null
+++ b/app/assets/javascripts/boards/boards_util.js
@@ -0,0 +1,7 @@
+export function getMilestone() {
+ return null;
+}
+
+export default {
+ getMilestone,
+};
diff --git a/app/assets/javascripts/boards/components/board_blank_state.vue b/app/assets/javascripts/boards/components/board_blank_state.vue
index 667eea17d44..1cbd31729cd 100644
--- a/app/assets/javascripts/boards/components/board_blank_state.vue
+++ b/app/assets/javascripts/boards/components/board_blank_state.vue
@@ -1,6 +1,5 @@
<script>
/* global ListLabel */
-import _ from 'underscore';
import Cookies from 'js-cookie';
import boardsStore from '../stores/boards_store';
@@ -29,8 +28,6 @@ export default {
});
});
- boardsStore.state.lists = _.sortBy(boardsStore.state.lists, 'position');
-
// Save the labels
gl.boardService
.generateDefaultLists()
@@ -60,11 +57,15 @@ export default {
</script>
<template>
- <div class="board-blank-state">
+ <div class="board-blank-state p-3">
<p>Add the following default lists to your Issue Board with one click:</p>
- <ul class="board-blank-state-list">
+ <ul class="list-unstyled board-blank-state-list">
<li v-for="(label, index) in predefinedLabels" :key="index">
- <span :style="{ backgroundColor: label.color }" class="label-color"> </span>
+ <span
+ :style="{ backgroundColor: label.color }"
+ class="label-color position-relative d-inline-block rounded"
+ >
+ </span>
{{ label.title }}
</li>
</ul>
diff --git a/app/assets/javascripts/boards/components/board_card.vue b/app/assets/javascripts/boards/components/board_card.vue
index f569322ab70..179148b6887 100644
--- a/app/assets/javascripts/boards/components/board_card.vue
+++ b/app/assets/javascripts/boards/components/board_card.vue
@@ -66,7 +66,7 @@ export default {
eventHub.$emit('clearDetailIssue');
} else {
eventHub.$emit('newDetailIssue', this.issue);
- boardsStore.detail.list = this.list;
+ boardsStore.setListDetail(this.list);
}
}
},
@@ -83,7 +83,7 @@ export default {
}"
:index="index"
:data-issue-id="issue.id"
- class="board-card"
+ class="board-card p-3 rounded"
@mousedown="mouseDown"
@mousemove="mouseMove"
@mouseup="showIssue($event)"
diff --git a/app/assets/javascripts/boards/components/board_delete.js b/app/assets/javascripts/boards/components/board_delete.js
index a5f9d65e4d5..a06db359c94 100644
--- a/app/assets/javascripts/boards/components/board_delete.js
+++ b/app/assets/javascripts/boards/components/board_delete.js
@@ -1,5 +1,6 @@
import $ from 'jquery';
import Vue from 'vue';
+import { __ } from '~/locale';
export default Vue.extend({
props: {
@@ -13,7 +14,7 @@ export default Vue.extend({
$(this.$el).tooltip('hide');
// eslint-disable-next-line no-alert
- if (window.confirm('Are you sure you want to delete this list?')) {
+ if (window.confirm(__('Are you sure you want to delete this list?'))) {
this.list.destroy();
}
},
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue
index f3f341ece5c..b1a8b13f3ac 100644
--- a/app/assets/javascripts/boards/components/board_list.vue
+++ b/app/assets/javascripts/boards/components/board_list.vue
@@ -142,8 +142,10 @@ export default {
const card = this.$refs.issue[e.oldIndex];
card.showDetail = false;
- boardsStore.moving.list = card.list;
- boardsStore.moving.issue = boardsStore.moving.list.findIssue(+e.item.dataset.issueId);
+
+ const { list } = card;
+ const issue = list.findIssue(Number(e.item.dataset.issueId));
+ boardsStore.startMoving(list, issue);
sortableStart();
},
@@ -221,7 +223,10 @@ export default {
</script>
<template>
- <div class="board-list-component">
+ <div
+ :class="{ 'd-none': !list.isExpanded, 'd-flex flex-column': list.isExpanded }"
+ class="board-list-component position-relative h-100"
+ >
<div v-if="loading" class="board-list-loading text-center" aria-label="Loading issues">
<gl-loading-icon />
</div>
@@ -236,7 +241,7 @@ export default {
:data-board="list.id"
:data-board-type="list.type"
:class="{ 'is-smaller': showIssueForm }"
- class="board-list js-board-list"
+ class="board-list w-100 h-100 list-unstyled mb-0 p-1 js-board-list"
>
<board-card
v-for="(issue, index) in issues"
diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue
index 28d96dab605..cc6af8e88cd 100644
--- a/app/assets/javascripts/boards/components/board_new_issue.vue
+++ b/app/assets/javascripts/boards/components/board_new_issue.vue
@@ -1,6 +1,7 @@
<script>
import $ from 'jquery';
import { GlButton } from '@gitlab/ui';
+import { getMilestone } from 'ee_else_ce/boards/boards_util';
import eventHub from '../eventhub';
import ProjectSelect from './project_select.vue';
import ListIssue from '../models/issue';
@@ -51,11 +52,14 @@ export default {
const labels = this.list.label ? [this.list.label] : [];
const assignees = this.list.assignee ? [this.list.assignee] : [];
+ const milestone = getMilestone(this.list);
+
const issue = new ListIssue({
title: this.title,
labels,
subscribed: true,
assignees,
+ milestone,
project_id: this.selectedProject.id,
});
@@ -68,8 +72,8 @@ export default {
// Need this because our jQuery very kindly disables buttons on ALL form submissions
$(this.$refs.submitButton).enable();
- boardsStore.detail.issue = issue;
- boardsStore.detail.list = this.list;
+ boardsStore.setIssueDetail(issue);
+ boardsStore.setListDetail(this.list);
})
.catch(() => {
// Need this because our jQuery very kindly disables buttons on ALL form submissions
@@ -95,7 +99,7 @@ export default {
<template>
<div class="board-new-issue-form">
- <div class="board-card">
+ <div class="board-card position-relative p-3 rounded">
<form @submit="submit($event)">
<div v-if="error" class="flash-container">
<div class="flash-alert">An error occurred. Please try again.</div>
diff --git a/app/assets/javascripts/boards/components/board_sidebar.js b/app/assets/javascripts/boards/components/board_sidebar.js
index 915d1676e62..c587b276fa3 100644
--- a/app/assets/javascripts/boards/components/board_sidebar.js
+++ b/app/assets/javascripts/boards/components/board_sidebar.js
@@ -45,7 +45,7 @@ export default Vue.extend({
return Object.keys(this.issue).length;
},
milestoneTitle() {
- return this.issue.milestone ? this.issue.milestone.title : 'No Milestone';
+ return this.issue.milestone ? this.issue.milestone.title : __('No Milestone');
},
canRemove() {
return !this.list.preset;
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue
index be0de63e772..a8516f178fc 100644
--- a/app/assets/javascripts/boards/components/issue_card_inner.vue
+++ b/app/assets/javascripts/boards/components/issue_card_inner.vue
@@ -4,8 +4,8 @@ import { GlTooltipDirective } from '@gitlab/ui';
import { sprintf, __ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import issueCardInner from 'ee_else_ce/boards/mixins/issue_card_inner';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
-import eventHub from '../eventhub';
import IssueDueDate from './issue_due_date.vue';
import IssueTimeEstimate from './issue_time_estimate.vue';
import boardsStore from '../stores/boards_store';
@@ -19,11 +19,13 @@ export default {
TooltipOnTruncate,
IssueDueDate,
IssueTimeEstimate,
+ IssueCardWeight: () => import('ee_component/boards/components/issue_card_weight.vue'),
IssueCardInnerScopedLabel,
},
directives: {
GlTooltip: GlTooltipDirective,
},
+ mixins: [issueCardInner],
props: {
issue: {
type: Object,
@@ -133,31 +135,7 @@ export default {
const labelTitle = encodeURIComponent(label.title);
const filter = `label_name[]=${labelTitle}`;
- this.applyFilter(filter);
- },
- filterByWeight(weight) {
- if (!this.updateFilters) return;
-
- const issueWeight = encodeURIComponent(weight);
- const filter = `weight=${issueWeight}`;
-
- this.applyFilter(filter);
- },
- applyFilter(filter) {
- const filterPath = boardsStore.filter.path.split('&');
- const filterIndex = filterPath.indexOf(filter);
-
- if (filterIndex === -1) {
- filterPath.push(filter);
- } else {
- filterPath.splice(filterIndex, 1);
- }
-
- boardsStore.filter.path = filterPath.join('&');
-
- boardsStore.updateFiltersUrl();
-
- eventHub.$emit('updateTokens');
+ boardsStore.toggleFilter(filter);
},
labelStyle(label) {
return {
@@ -173,7 +151,7 @@ export default {
</script>
<template>
<div>
- <div class="board-card-header">
+ <div class="d-flex board-card-header" dir="auto">
<h4 class="board-card-title append-bottom-0 prepend-top-0">
<icon
v-if="issue.confidential"
@@ -214,11 +192,11 @@ export default {
</div>
<div class="board-card-footer d-flex justify-content-between align-items-end">
<div
- class="d-flex align-items-start flex-wrap-reverse board-card-number-container js-board-card-number-container"
+ class="d-flex align-items-start flex-wrap-reverse board-card-number-container overflow-hidden js-board-card-number-container"
>
<span
v-if="issue.referencePath"
- class="board-card-number d-flex append-right-8 prepend-top-8"
+ class="board-card-number overflow-hidden d-flex append-right-8 prepend-top-8"
>
<tooltip-on-truncate
v-if="issueReferencePath"
@@ -232,10 +210,14 @@ export default {
<issue-due-date v-if="issue.dueDate" :date="issue.dueDate" /><issue-time-estimate
v-if="issue.timeEstimate"
:estimate="issue.timeEstimate"
+ /><issue-card-weight
+ v-if="issue.weight"
+ :weight="issue.weight"
+ @click="filterByWeight(issue.weight)"
/>
</span>
</div>
- <div class="board-card-assignee">
+ <div class="board-card-assignee d-flex">
<user-avatar-link
v-for="(assignee, index) in issue.assignees"
v-if="shouldRenderAssignee(index)"
diff --git a/app/assets/javascripts/boards/components/issue_due_date.vue b/app/assets/javascripts/boards/components/issue_due_date.vue
index 9bc66978198..3bc7f13a9e6 100644
--- a/app/assets/javascripts/boards/components/issue_due_date.vue
+++ b/app/assets/javascripts/boards/components/issue_due_date.vue
@@ -82,7 +82,11 @@ export default {
<template>
<span>
<span ref="issueDueDate" :class="cssClass" class="board-card-info card-number">
- <icon :class="{ 'text-danger': isPastDue, 'board-card-info-icon': true }" name="calendar" />
+ <icon
+ :class="{ 'text-danger': isPastDue }"
+ class="board-card-info-icon align-top"
+ name="calendar"
+ />
<time :class="{ 'text-danger': isPastDue }" datetime="date" class="board-card-info-text">{{
body
}}</time>
diff --git a/app/assets/javascripts/boards/components/issue_time_estimate.vue b/app/assets/javascripts/boards/components/issue_time_estimate.vue
index 5acc3025b2c..98c1d29db16 100644
--- a/app/assets/javascripts/boards/components/issue_time_estimate.vue
+++ b/app/assets/javascripts/boards/components/issue_time_estimate.vue
@@ -28,7 +28,7 @@ export default {
<template>
<span>
<span ref="issueTimeEstimate" class="board-card-info card-number">
- <icon name="hourglass" css-classes="board-card-info-icon" /><time
+ <icon name="hourglass" css-classes="board-card-info-icon align-top" /><time
class="board-card-info-text"
>{{ timeEstimate }}</time
>
diff --git a/app/assets/javascripts/boards/components/modal/empty_state.vue b/app/assets/javascripts/boards/components/modal/empty_state.vue
index 2a0008467c4..091700de93f 100644
--- a/app/assets/javascripts/boards/components/modal/empty_state.vue
+++ b/app/assets/javascripts/boards/components/modal/empty_state.vue
@@ -42,8 +42,8 @@ export default {
</script>
<template>
- <section class="empty-state">
- <div class="row">
+ <section class="empty-state d-flex mt-0 h-100">
+ <div class="row w-100 my-auto mx-0">
<div class="col-12 col-md-6 order-md-last">
<aside class="svg-content d-none d-md-block"><img :src="emptyStateSvg" /></aside>
</div>
diff --git a/app/assets/javascripts/boards/components/modal/header.vue b/app/assets/javascripts/boards/components/modal/header.vue
index 1f0961e02d8..1cfa6d39362 100644
--- a/app/assets/javascripts/boards/components/modal/header.vue
+++ b/app/assets/javascripts/boards/components/modal/header.vue
@@ -50,8 +50,8 @@ export default {
</script>
<template>
<div>
- <header class="add-issues-header form-actions">
- <h2>
+ <header class="add-issues-header border-top-0 form-actions">
+ <h2 class="m-0">
Add issues
<button
type="button"
@@ -65,7 +65,7 @@ export default {
</h2>
</header>
<modal-tabs v-if="!loading && issuesCount > 0" />
- <div v-if="showSearch" class="add-issues-search append-bottom-10">
+ <div v-if="showSearch" class="d-flex append-bottom-10">
<modal-filters :store="filter" />
<button
ref="selectAllBtn"
diff --git a/app/assets/javascripts/boards/components/modal/index.vue b/app/assets/javascripts/boards/components/modal/index.vue
index 1e5761cf268..defa1f75ba2 100644
--- a/app/assets/javascripts/boards/components/modal/index.vue
+++ b/app/assets/javascripts/boards/components/modal/index.vue
@@ -124,7 +124,7 @@ export default {
data.issues.forEach(issueObj => {
const issue = new ListIssue(issueObj);
const foundSelectedIssue = ModalStore.findSelectedIssue(issue);
- issue.selected = !!foundSelectedIssue;
+ issue.selected = Boolean(foundSelectedIssue);
this.issues.push(issue);
});
@@ -143,8 +143,11 @@ export default {
};
</script>
<template>
- <div v-if="showAddIssuesModal" class="add-issues-modal">
- <div class="add-issues-container">
+ <div
+ v-if="showAddIssuesModal"
+ class="add-issues-modal d-flex position-fixed position-top-0 position-bottom-0 position-left-0 position-right-0 h-100"
+ >
+ <div class="add-issues-container d-flex flex-column m-auto rounded">
<modal-header
:project-id="projectId"
:milestone-path="milestonePath"
@@ -161,8 +164,10 @@ export default {
:new-issue-path="newIssuePath"
:empty-state-svg="emptyStateSvg"
/>
- <section v-if="loading || filterLoading" class="add-issues-list text-center">
- <div class="add-issues-list-loading"><gl-loading-icon /></div>
+ <section v-if="loading || filterLoading" class="add-issues-list d-flex h-100 text-center">
+ <div class="add-issues-list-loading w-100 align-self-center">
+ <gl-loading-icon size="md" />
+ </div>
</section>
<modal-footer />
</div>
diff --git a/app/assets/javascripts/boards/components/modal/list.vue b/app/assets/javascripts/boards/components/modal/list.vue
index e9ed2de859d..28d2019af2f 100644
--- a/app/assets/javascripts/boards/components/modal/list.vue
+++ b/app/assets/javascripts/boards/components/modal/list.vue
@@ -117,7 +117,7 @@ export default {
};
</script>
<template>
- <section ref="list" class="add-issues-list add-issues-list-columns">
+ <section ref="list" class="add-issues-list add-issues-list-columns d-flex h-100">
<div
v-if="issuesCount > 0 && issues.length === 0"
class="empty-state add-issues-empty-state-filter text-center"
@@ -129,7 +129,7 @@ export default {
<div v-for="issue in group" v-if="showIssue(issue)" :key="issue.id" class="board-card-parent">
<div
:class="{ 'is-active': issue.selected }"
- class="board-card"
+ class="board-card position-relative p-3 rounded"
@click="toggleIssue($event, issue)"
>
<issue-card-inner :issue="issue" :issue-link-base="issueLinkBase" :root-path="rootPath" />
diff --git a/app/assets/javascripts/boards/components/new_list_dropdown.js b/app/assets/javascripts/boards/components/new_list_dropdown.js
index a5ed695af35..c8a9cb1c296 100644
--- a/app/assets/javascripts/boards/components/new_list_dropdown.js
+++ b/app/assets/javascripts/boards/components/new_list_dropdown.js
@@ -2,7 +2,6 @@
import $ from 'jquery';
import axios from '~/lib/utils/axios_utils';
-import _ from 'underscore';
import CreateLabelDropdown from '../../create_label';
import boardsStore from '../stores/boards_store';
@@ -78,8 +77,6 @@ export default function initNewListDropdown() {
color: label.color,
},
});
-
- boardsStore.state.lists = _.sortBy(boardsStore.state.lists, 'position');
}
},
});
diff --git a/app/assets/javascripts/boards/components/sidebar/remove_issue.vue b/app/assets/javascripts/boards/components/sidebar/remove_issue.vue
index a2b8a0af236..4ab2b17301f 100644
--- a/app/assets/javascripts/boards/components/sidebar/remove_issue.vue
+++ b/app/assets/javascripts/boards/components/sidebar/remove_issue.vue
@@ -48,7 +48,7 @@ export default Vue.extend({
list.removeIssue(issue);
});
- boardsStore.detail.issue = {};
+ boardsStore.clearDetailIssue();
},
/**
* Build the default patch request.
diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js
index 009ae5dd331..f2f37d22b97 100644
--- a/app/assets/javascripts/boards/index.js
+++ b/app/assets/javascripts/boards/index.js
@@ -1,11 +1,10 @@
import $ from 'jquery';
-import _ from 'underscore';
import Vue from 'vue';
import Flash from '~/flash';
import { __ } from '~/locale';
-import '~/vue_shared/models/label';
-import '~/vue_shared/models/assignee';
+import './models/label';
+import './models/assignee';
import FilteredSearchBoards from './filtered_search_boards';
import eventHub from './eventhub';
@@ -106,24 +105,29 @@ export default () => {
gl.boardService
.all()
.then(res => res.data)
- .then(data => {
- data.forEach(board => {
- const list = boardsStore.addList(board, this.defaultAvatar);
-
- if (list.type === 'closed') {
- list.position = Infinity;
- } else if (list.type === 'backlog') {
- list.position = -1;
+ .then(lists => {
+ lists.forEach(listObj => {
+ let { position } = listObj;
+ if (listObj.list_type === 'closed') {
+ position = Infinity;
+ } else if (listObj.list_type === 'backlog') {
+ position = -1;
}
- });
- this.state.lists = _.sortBy(this.state.lists, 'position');
+ boardsStore.addList(
+ {
+ ...listObj,
+ position,
+ },
+ this.defaultAvatar,
+ );
+ });
boardsStore.addBlankState();
this.loading = false;
})
.catch(() => {
- Flash('An error occurred while fetching the board lists. Please try again.');
+ Flash(__('An error occurred while fetching the board lists. Please try again.'));
});
},
methods: {
@@ -164,10 +168,10 @@ export default () => {
});
}
- boardsStore.detail.issue = newIssue;
+ boardsStore.setIssueDetail(newIssue);
},
clearDetailIssue() {
- boardsStore.detail.issue = {};
+ boardsStore.clearDetailIssue();
},
toggleSubscription(id) {
const { issue } = boardsStore.detail;
@@ -223,7 +227,7 @@ export default () => {
},
tooltipTitle() {
if (this.disabled) {
- return 'Please add a list to your board first';
+ return __('Please add a list to your board first');
}
return '';
diff --git a/app/assets/javascripts/boards/mixins/issue_card_inner.js b/app/assets/javascripts/boards/mixins/issue_card_inner.js
new file mode 100644
index 00000000000..8000237da6d
--- /dev/null
+++ b/app/assets/javascripts/boards/mixins/issue_card_inner.js
@@ -0,0 +1,5 @@
+export default {
+ methods: {
+ filterByWeight() {},
+ },
+};
diff --git a/app/assets/javascripts/vue_shared/models/assignee.js b/app/assets/javascripts/boards/models/assignee.js
index 4a29b0d0581..4a29b0d0581 100644
--- a/app/assets/javascripts/vue_shared/models/assignee.js
+++ b/app/assets/javascripts/boards/models/assignee.js
diff --git a/app/assets/javascripts/boards/models/issue.js b/app/assets/javascripts/boards/models/issue.js
index f8ff20cb0cd..f858b162c6b 100644
--- a/app/assets/javascripts/boards/models/issue.js
+++ b/app/assets/javascripts/boards/models/issue.js
@@ -4,7 +4,7 @@
/* global ListAssignee */
import Vue from 'vue';
-import '~/vue_shared/models/label';
+import './label';
import { isEE, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import IssueProject from './project';
import boardsStore from '../stores/boards_store';
diff --git a/app/assets/javascripts/boards/models/label.js b/app/assets/javascripts/boards/models/label.js
new file mode 100644
index 00000000000..cd2a2c0137f
--- /dev/null
+++ b/app/assets/javascripts/boards/models/label.js
@@ -0,0 +1,11 @@
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+
+export default class ListLabel {
+ constructor(obj) {
+ Object.assign(this, convertObjectPropsToCamelCase(obj, { dropKeys: ['priority'] }), {
+ priority: obj.priority !== null ? obj.priority : Infinity,
+ });
+ }
+}
+
+window.ListLabel = ListLabel;
diff --git a/app/assets/javascripts/boards/models/list.js b/app/assets/javascripts/boards/models/list.js
index 6cf77705847..a9d88f19146 100644
--- a/app/assets/javascripts/boards/models/list.js
+++ b/app/assets/javascripts/boards/models/list.js
@@ -2,8 +2,8 @@
/* global ListIssue */
import { __ } from '~/locale';
-import ListLabel from '~/vue_shared/models/label';
-import ListAssignee from '~/vue_shared/models/assignee';
+import ListLabel from './label';
+import ListAssignee from './assignee';
import { isEE, urlParamsToObject } from '~/lib/utils/common_utils';
import boardsStore from '../stores/boards_store';
import ListMilestone from './milestone';
@@ -37,8 +37,8 @@ class List {
this.type = obj.list_type;
const typeInfo = this.getTypeInfo(this.type);
- this.preset = !!typeInfo.isPreset;
- this.isExpandable = !!typeInfo.isExpandable;
+ this.preset = Boolean(typeInfo.isPreset);
+ this.isExpandable = Boolean(typeInfo.isExpandable);
this.isExpanded = true;
this.page = 1;
this.loading = true;
@@ -90,6 +90,7 @@ class List {
this.id = data.id;
this.type = data.list_type;
this.position = data.position;
+ this.label = data.label;
return this.getIssues();
});
diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js
new file mode 100644
index 00000000000..d4f4df3ad75
--- /dev/null
+++ b/app/assets/javascripts/boards/stores/actions.js
@@ -0,0 +1,66 @@
+const notImplemented = () => {
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
+ throw new Error('Not implemented!');
+};
+
+export default {
+ setEndpoints: () => {
+ notImplemented();
+ },
+
+ fetchLists: () => {
+ notImplemented();
+ },
+
+ generateDefaultLists: () => {
+ notImplemented();
+ },
+
+ createList: () => {
+ notImplemented();
+ },
+
+ updateList: () => {
+ notImplemented();
+ },
+
+ deleteList: () => {
+ notImplemented();
+ },
+
+ fetchIssuesForList: () => {
+ notImplemented();
+ },
+
+ moveIssue: () => {
+ notImplemented();
+ },
+
+ createNewIssue: () => {
+ notImplemented();
+ },
+
+ fetchBacklog: () => {
+ notImplemented();
+ },
+
+ bulkUpdateIssues: () => {
+ notImplemented();
+ },
+
+ fetchIssue: () => {
+ notImplemented();
+ },
+
+ toggleIssueSubscription: () => {
+ notImplemented();
+ },
+
+ showPage: () => {
+ notImplemented();
+ },
+
+ toggleEmptyState: () => {
+ notImplemented();
+ },
+};
diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js
index a34222b6887..4b3b44574a8 100644
--- a/app/assets/javascripts/boards/stores/boards_store.js
+++ b/app/assets/javascripts/boards/stores/boards_store.js
@@ -7,6 +7,8 @@ import Vue from 'vue';
import Cookies from 'js-cookie';
import BoardsStoreEE from 'ee_else_ce/boards/stores/boards_store_ee';
import { getUrlParamsArray, parseBoolean } from '~/lib/utils/common_utils';
+import { __ } from '~/locale';
+import eventHub from '../eventhub';
const boardsStore = {
disabled: false,
@@ -44,7 +46,7 @@ const boardsStore = {
},
addList(listObj, defaultAvatar) {
const list = new List(listObj, defaultAvatar);
- this.state.lists.push(list);
+ this.state.lists = _.sortBy([...this.state.lists, list], 'position');
return list;
},
@@ -78,11 +80,9 @@ const boardsStore = {
this.addList({
id: 'blank',
list_type: 'blank',
- title: 'Welcome to your Issue Board!',
+ title: __('Welcome to your Issue Board!'),
position: 0,
});
-
- this.state.lists = _.sortBy(this.state.lists, 'position');
},
removeBlankState() {
this.removeList('blank');
@@ -110,6 +110,11 @@ const boardsStore = {
});
listFrom.update();
},
+
+ startMoving(list, issue) {
+ Object.assign(this.moving, { list, issue });
+ },
+
moveIssueToList(listFrom, listTo, issue, newIndex) {
const issueTo = listTo.findIssue(issue.id);
const issueLists = issue.getLists();
@@ -184,9 +189,39 @@ const boardsStore = {
findListByLabelId(id) {
return this.state.lists.find(list => list.type === 'label' && list.label.id === id);
},
+
+ toggleFilter(filter) {
+ const filterPath = this.filter.path.split('&');
+ const filterIndex = filterPath.indexOf(filter);
+
+ if (filterIndex === -1) {
+ filterPath.push(filter);
+ } else {
+ filterPath.splice(filterIndex, 1);
+ }
+
+ this.filter.path = filterPath.join('&');
+
+ this.updateFiltersUrl();
+
+ eventHub.$emit('updateTokens');
+ },
+
+ setListDetail(newList) {
+ this.detail.list = newList;
+ },
+
updateFiltersUrl() {
window.history.pushState(null, null, `?${this.filter.path}`);
},
+
+ clearDetailIssue() {
+ this.setIssueDetail({});
+ },
+
+ setIssueDetail(issueDetail) {
+ this.detail.issue = issueDetail;
+ },
};
BoardsStoreEE.initEESpecific(boardsStore);
diff --git a/app/assets/javascripts/boards/stores/index.js b/app/assets/javascripts/boards/stores/index.js
new file mode 100644
index 00000000000..f70395a3771
--- /dev/null
+++ b/app/assets/javascripts/boards/stores/index.js
@@ -0,0 +1,14 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import state from 'ee_else_ce/boards/stores/state';
+import actions from 'ee_else_ce/boards/stores/actions';
+import mutations from 'ee_else_ce/boards/stores/mutations';
+
+Vue.use(Vuex);
+
+export default () =>
+ new Vuex.Store({
+ state,
+ actions,
+ mutations,
+ });
diff --git a/app/assets/javascripts/boards/stores/mutation_types.js b/app/assets/javascripts/boards/stores/mutation_types.js
new file mode 100644
index 00000000000..fcdfa6799b6
--- /dev/null
+++ b/app/assets/javascripts/boards/stores/mutation_types.js
@@ -0,0 +1,21 @@
+export const SET_ENDPOINTS = 'SET_ENDPOINTS';
+export const REQUEST_ADD_LIST = 'REQUEST_ADD_LIST';
+export const RECEIVE_ADD_LIST_SUCCESS = 'RECEIVE_ADD_LIST_SUCCESS';
+export const RECEIVE_ADD_LIST_ERROR = 'RECEIVE_ADD_LIST_ERROR';
+export const REQUEST_UPDATE_LIST = 'REQUEST_UPDATE_LIST';
+export const RECEIVE_UPDATE_LIST_SUCCESS = 'RECEIVE_UPDATE_LIST_SUCCESS';
+export const RECEIVE_UPDATE_LIST_ERROR = 'RECEIVE_UPDATE_LIST_ERROR';
+export const REQUEST_REMOVE_LIST = 'REQUEST_REMOVE_LIST';
+export const RECEIVE_REMOVE_LIST_SUCCESS = 'RECEIVE_REMOVE_LIST_SUCCESS';
+export const RECEIVE_REMOVE_LIST_ERROR = 'RECEIVE_REMOVE_LIST_ERROR';
+export const REQUEST_ADD_ISSUE = 'REQUEST_ADD_ISSUE';
+export const RECEIVE_ADD_ISSUE_SUCCESS = 'RECEIVE_ADD_ISSUE_SUCCESS';
+export const RECEIVE_ADD_ISSUE_ERROR = 'RECEIVE_ADD_ISSUE_ERROR';
+export const REQUEST_MOVE_ISSUE = 'REQUEST_MOVE_ISSUE';
+export const RECEIVE_MOVE_ISSUE_SUCCESS = 'RECEIVE_MOVE_ISSUE_SUCCESS';
+export const RECEIVE_MOVE_ISSUE_ERROR = 'RECEIVE_MOVE_ISSUE_ERROR';
+export const REQUEST_UPDATE_ISSUE = 'REQUEST_UPDATE_ISSUE';
+export const RECEIVE_UPDATE_ISSUE_SUCCESS = 'RECEIVE_UPDATE_ISSUE_SUCCESS';
+export const RECEIVE_UPDATE_ISSUE_ERROR = 'RECEIVE_UPDATE_ISSUE_ERROR';
+export const SET_CURRENT_PAGE = 'SET_CURRENT_PAGE';
+export const TOGGLE_EMPTY_STATE = 'TOGGLE_EMPTY_STATE';
diff --git a/app/assets/javascripts/boards/stores/mutations.js b/app/assets/javascripts/boards/stores/mutations.js
new file mode 100644
index 00000000000..09eb8bb9b98
--- /dev/null
+++ b/app/assets/javascripts/boards/stores/mutations.js
@@ -0,0 +1,92 @@
+import * as mutationTypes from './mutation_types';
+
+const notImplemented = () => {
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
+ throw new Error('Not implemented!');
+};
+
+export default {
+ [mutationTypes.SET_ENDPOINTS]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.REQUEST_ADD_LIST]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.RECEIVE_ADD_LIST_SUCCESS]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.RECEIVE_ADD_LIST_ERROR]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.REQUEST_UPDATE_LIST]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.RECEIVE_UPDATE_LIST_SUCCESS]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.RECEIVE_UPDATE_LIST_ERROR]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.REQUEST_REMOVE_LIST]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.RECEIVE_REMOVE_LIST_SUCCESS]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.RECEIVE_REMOVE_LIST_ERROR]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.REQUEST_ADD_ISSUE]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.RECEIVE_ADD_ISSUE_SUCCESS]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.RECEIVE_ADD_ISSUE_ERROR]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.REQUEST_MOVE_ISSUE]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.RECEIVE_MOVE_ISSUE_SUCCESS]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.RECEIVE_MOVE_ISSUE_ERROR]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.REQUEST_UPDATE_ISSUE]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.RECEIVE_UPDATE_ISSUE_SUCCESS]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.RECEIVE_UPDATE_ISSUE_ERROR]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.SET_CURRENT_PAGE]: () => {
+ notImplemented();
+ },
+
+ [mutationTypes.TOGGLE_EMPTY_STATE]: () => {
+ notImplemented();
+ },
+};
diff --git a/app/assets/javascripts/boards/stores/state.js b/app/assets/javascripts/boards/stores/state.js
new file mode 100644
index 00000000000..dd16abb01a5
--- /dev/null
+++ b/app/assets/javascripts/boards/stores/state.js
@@ -0,0 +1,3 @@
+export default () => ({
+ // ...
+});
diff --git a/app/assets/javascripts/branches/branches_delete_modal.js b/app/assets/javascripts/branches/branches_delete_modal.js
index f34496f84c6..f4c3fa185d8 100644
--- a/app/assets/javascripts/branches/branches_delete_modal.js
+++ b/app/assets/javascripts/branches/branches_delete_modal.js
@@ -23,7 +23,7 @@ class DeleteModal {
const branchData = e.currentTarget.dataset;
this.branchName = branchData.branchName || '';
this.deletePath = branchData.deletePath || '';
- this.isMerged = !!branchData.isMerged;
+ this.isMerged = Boolean(branchData.isMerged);
this.updateModal();
}
diff --git a/app/assets/javascripts/ci_variable_list/ajax_variable_list.js b/app/assets/javascripts/ci_variable_list/ajax_variable_list.js
index 592e1fd1c31..0bba2a2e160 100644
--- a/app/assets/javascripts/ci_variable_list/ajax_variable_list.js
+++ b/app/assets/javascripts/ci_variable_list/ajax_variable_list.js
@@ -27,15 +27,24 @@ function generateErrorBoxContent(errors) {
// Used for the variable list on CI/CD projects/groups settings page
export default class AjaxVariableList {
- constructor({ container, saveButton, errorBox, formField = 'variables', saveEndpoint }) {
+ constructor({
+ container,
+ saveButton,
+ errorBox,
+ formField = 'variables',
+ saveEndpoint,
+ maskableRegex,
+ }) {
this.container = container;
this.saveButton = saveButton;
this.errorBox = errorBox;
this.saveEndpoint = saveEndpoint;
+ this.maskableRegex = maskableRegex;
this.variableList = new VariableList({
container: this.container,
formField,
+ maskableRegex,
});
this.bindEvents();
diff --git a/app/assets/javascripts/ci_variable_list/ci_variable_list.js b/app/assets/javascripts/ci_variable_list/ci_variable_list.js
index da3100b9386..0303e4e51dd 100644
--- a/app/assets/javascripts/ci_variable_list/ci_variable_list.js
+++ b/app/assets/javascripts/ci_variable_list/ci_variable_list.js
@@ -16,9 +16,10 @@ function createEnvironmentItem(value) {
}
export default class VariableList {
- constructor({ container, formField }) {
+ constructor({ container, formField, maskableRegex }) {
this.$container = $(container);
this.formField = formField;
+ this.maskableRegex = new RegExp(maskableRegex);
this.environmentDropdownMap = new WeakMap();
this.inputMap = {
@@ -26,6 +27,10 @@ export default class VariableList {
selector: '.js-ci-variable-input-id',
default: '',
},
+ variable_type: {
+ selector: '.js-ci-variable-input-variable-type',
+ default: 'env_var',
+ },
key: {
selector: '.js-ci-variable-input-key',
default: '',
@@ -192,9 +197,8 @@ export default class VariableList {
validateMaskability($row) {
const invalidInputClass = 'gl-field-error-outline';
- const maskableRegex = /^\w{8,}$/; // Eight or more alphanumeric characters plus underscores
const variableValue = $row.find(this.inputMap.secret_value.selector).val();
- const isValueMaskable = maskableRegex.test(variableValue) || variableValue === '';
+ const isValueMaskable = this.maskableRegex.test(variableValue) || variableValue === '';
const isMaskedChecked = $row.find(this.inputMap.masked.selector).val() === 'true';
// Show a validation error if the user wants to mask an unmaskable variable value
diff --git a/app/assets/javascripts/ci_variable_list/native_form_variable_list.js b/app/assets/javascripts/ci_variable_list/native_form_variable_list.js
index e7111c666a2..fdbefd8c313 100644
--- a/app/assets/javascripts/ci_variable_list/native_form_variable_list.js
+++ b/app/assets/javascripts/ci_variable_list/native_form_variable_list.js
@@ -19,6 +19,7 @@ export default function setupNativeFormVariableList({ container, formField = 'va
const isTouched = variableList.checkIfRowTouched($lastRow);
if (!isTouched) {
$lastRow.find('input, textarea').attr('name', '');
+ $lastRow.find('select').attr('name', '');
}
});
}
diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js
index df855261b3c..aacfa0d87e6 100644
--- a/app/assets/javascripts/clusters/clusters_bundle.js
+++ b/app/assets/javascripts/clusters/clusters_bundle.js
@@ -1,25 +1,21 @@
import Visibility from 'visibilityjs';
import Vue from 'vue';
+import AccessorUtilities from '~/lib/utils/accessor';
+import { GlToast } from '@gitlab/ui';
import PersistentUserCallout from '../persistent_user_callout';
import { s__, sprintf } from '../locale';
import Flash from '../flash';
import Poll from '../lib/utils/poll';
import initSettingsPanels from '../settings_panels';
import eventHub from './event_hub';
-import {
- APPLICATION_STATUS,
- REQUEST_SUBMITTED,
- REQUEST_FAILURE,
- UPGRADE_REQUESTED,
- UPGRADE_REQUEST_FAILURE,
- INGRESS,
- INGRESS_DOMAIN_SUFFIX,
-} from './constants';
+import { APPLICATION_STATUS, INGRESS, INGRESS_DOMAIN_SUFFIX } from './constants';
import ClustersService from './services/clusters_service';
import ClustersStore from './stores/clusters_store';
import Applications from './components/applications.vue';
import setupToggleButtons from '../toggle_buttons';
+Vue.use(GlToast);
+
/**
* Cluster page has 2 separate parts:
* Toggle button and applications section
@@ -48,8 +44,10 @@ export default class Clusters {
helpPath,
ingressHelpPath,
ingressDnsHelpPath,
+ clusterId,
} = document.querySelector('.js-edit-cluster-form').dataset;
+ this.clusterId = clusterId;
this.store = new ClustersStore();
this.store.setHelpPaths(helpPath, ingressHelpPath, ingressDnsHelpPath);
this.store.setManagePrometheusPath(managePrometheusPath);
@@ -74,6 +72,10 @@ export default class Clusters {
this.errorContainer = document.querySelector('.js-cluster-error');
this.successContainer = document.querySelector('.js-cluster-success');
this.creatingContainer = document.querySelector('.js-cluster-creating');
+ this.unreachableContainer = document.querySelector('.js-cluster-api-unreachable');
+ this.authenticationFailureContainer = document.querySelector(
+ '.js-cluster-authentication-failure',
+ );
this.errorReasonContainer = this.errorContainer.querySelector('.js-error-reason');
this.successApplicationContainer = document.querySelector('.js-cluster-application-notice');
this.showTokenButton = document.querySelector('.js-show-cluster-token');
@@ -130,24 +132,32 @@ export default class Clusters {
PersistentUserCallout.factory(callout);
}
+ addBannerCloseHandler(el, status) {
+ el.querySelector('.js-close-banner').addEventListener('click', () => {
+ el.classList.add('hidden');
+ this.setBannerDismissedState(status, true);
+ });
+ }
+
addListeners() {
if (this.showTokenButton) this.showTokenButton.addEventListener('click', this.showToken);
eventHub.$on('installApplication', this.installApplication);
- eventHub.$on('upgradeApplication', data => this.upgradeApplication(data));
- eventHub.$on('upgradeFailed', appId => this.upgradeFailed(appId));
- eventHub.$on('dismissUpgradeSuccess', appId => this.dismissUpgradeSuccess(appId));
+ eventHub.$on('updateApplication', data => this.updateApplication(data));
eventHub.$on('saveKnativeDomain', data => this.saveKnativeDomain(data));
eventHub.$on('setKnativeHostname', data => this.setKnativeHostname(data));
+ eventHub.$on('uninstallApplication', data => this.uninstallApplication(data));
+ // Add event listener to all the banner close buttons
+ this.addBannerCloseHandler(this.unreachableContainer, 'unreachable');
+ this.addBannerCloseHandler(this.authenticationFailureContainer, 'authentication_failure');
}
removeListeners() {
if (this.showTokenButton) this.showTokenButton.removeEventListener('click', this.showToken);
eventHub.$off('installApplication', this.installApplication);
- eventHub.$off('upgradeApplication', this.upgradeApplication);
- eventHub.$off('upgradeFailed', this.upgradeFailed);
- eventHub.$off('dismissUpgradeSuccess', this.dismissUpgradeSuccess);
+ eventHub.$off('updateApplication', this.updateApplication);
eventHub.$off('saveKnativeDomain');
eventHub.$off('setKnativeHostname');
+ eventHub.$off('uninstallApplication');
}
initPolling() {
@@ -210,6 +220,8 @@ export default class Clusters {
this.errorContainer.classList.add('hidden');
this.successContainer.classList.add('hidden');
this.creatingContainer.classList.add('hidden');
+ this.unreachableContainer.classList.add('hidden');
+ this.authenticationFailureContainer.classList.add('hidden');
}
checkForNewInstalls(prevApplicationMap, newApplicationMap) {
@@ -233,9 +245,32 @@ export default class Clusters {
}
}
+ setBannerDismissedState(status, isDismissed) {
+ if (AccessorUtilities.isLocalStorageAccessSafe()) {
+ window.localStorage.setItem(
+ `cluster_${this.clusterId}_banner_dismissed`,
+ `${status}_${isDismissed}`,
+ );
+ }
+ }
+
+ isBannerDismissed(status) {
+ let bannerState;
+ if (AccessorUtilities.isLocalStorageAccessSafe()) {
+ bannerState = window.localStorage.getItem(`cluster_${this.clusterId}_banner_dismissed`);
+ }
+
+ return bannerState === `${status}_true`;
+ }
+
updateContainer(prevStatus, status, error) {
this.hideAll();
+ if (this.isBannerDismissed(status)) {
+ return;
+ }
+ this.setBannerDismissedState(status, false);
+
// We poll all the time but only want the `created` banner to show when newly created
if (this.store.state.status !== 'created' || prevStatus !== this.store.state.status) {
switch (status) {
@@ -246,6 +281,12 @@ export default class Clusters {
this.errorContainer.classList.remove('hidden');
this.errorReasonContainer.textContent = error;
break;
+ case 'unreachable':
+ this.unreachableContainer.classList.remove('hidden');
+ break;
+ case 'authentication_failure':
+ this.authenticationFailureContainer.classList.remove('hidden');
+ break;
case 'scheduled':
case 'creating':
this.creatingContainer.classList.remove('hidden');
@@ -256,14 +297,14 @@ export default class Clusters {
}
}
- installApplication(data) {
- const appId = data.id;
- this.store.updateAppProperty(appId, 'requestStatus', REQUEST_SUBMITTED);
+ installApplication({ id: appId, params }) {
this.store.updateAppProperty(appId, 'requestReason', null);
this.store.updateAppProperty(appId, 'statusReason', null);
- return this.service.installApplication(appId, data.params).catch(() => {
- this.store.updateAppProperty(appId, 'requestStatus', REQUEST_FAILURE);
+ this.store.installApplication(appId);
+
+ return this.service.installApplication(appId, params).catch(() => {
+ this.store.notifyInstallFailure(appId);
this.store.updateAppProperty(
appId,
'requestReason',
@@ -272,36 +313,42 @@ export default class Clusters {
});
}
- upgradeApplication(data) {
- const appId = data.id;
- this.store.updateAppProperty(appId, 'requestStatus', UPGRADE_REQUESTED);
- this.store.updateAppProperty(appId, 'status', APPLICATION_STATUS.UPDATING);
- this.service.installApplication(appId, data.params).catch(() => this.upgradeFailed(appId));
- }
+ uninstallApplication({ id: appId }) {
+ this.store.updateAppProperty(appId, 'requestReason', null);
+ this.store.updateAppProperty(appId, 'statusReason', null);
- upgradeFailed(appId) {
- this.store.updateAppProperty(appId, 'requestStatus', UPGRADE_REQUEST_FAILURE);
- }
+ this.store.uninstallApplication(appId);
- dismissUpgradeSuccess(appId) {
- this.store.updateAppProperty(appId, 'requestStatus', null);
+ return this.service.uninstallApplication(appId).catch(() => {
+ this.store.notifyUninstallFailure(appId);
+ this.store.updateAppProperty(
+ appId,
+ 'requestReason',
+ s__('ClusterIntegration|Request to begin uninstalling failed'),
+ );
+ });
}
- toggleIngressDomainHelpText(ingressPreviousState, ingressNewState) {
- const { externalIp, status } = ingressNewState;
- const helpTextHidden = status !== APPLICATION_STATUS.INSTALLED || !externalIp;
- const domainSnippetText = `${externalIp}${INGRESS_DOMAIN_SUFFIX}`;
+ updateApplication({ id: appId, params }) {
+ this.store.updateApplication(appId);
+ this.service.installApplication(appId, params).catch(() => {
+ this.store.notifyUpdateFailure(appId);
+ });
+ }
- if (ingressPreviousState.status !== status) {
- this.ingressDomainHelpText.classList.toggle('hide', helpTextHidden);
- this.ingressDomainSnippet.textContent = domainSnippetText;
+ toggleIngressDomainHelpText({ externalIp }, { externalIp: newExternalIp }) {
+ if (externalIp !== newExternalIp) {
+ this.ingressDomainHelpText.classList.toggle('hide', !newExternalIp);
+ this.ingressDomainSnippet.textContent = `${newExternalIp}${INGRESS_DOMAIN_SUFFIX}`;
}
}
saveKnativeDomain(data) {
const appId = data.id;
- this.store.updateAppProperty(appId, 'status', APPLICATION_STATUS.UPDATING);
- this.service.updateApplication(appId, data.params);
+ this.store.updateApplication(appId);
+ this.service.updateApplication(appId, data.params).catch(() => {
+ this.store.notifyUpdateFailure(appId);
+ });
}
setKnativeHostname(data) {
diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue
index 19e5ac1567d..4771090aa7e 100644
--- a/app/assets/javascripts/clusters/components/application_row.vue
+++ b/app/assets/javascripts/clusters/components/application_row.vue
@@ -1,17 +1,15 @@
<script>
/* eslint-disable vue/require-default-prop */
-import { GlLink } from '@gitlab/ui';
+import { GlLink, GlModalDirective } from '@gitlab/ui';
import TimeagoTooltip from '../../vue_shared/components/time_ago_tooltip.vue';
-import { s__, sprintf } from '../../locale';
+import { s__, __, sprintf } from '~/locale';
import eventHub from '../event_hub';
import identicon from '../../vue_shared/components/identicon.vue';
import loadingButton from '../../vue_shared/components/loading_button.vue';
-import {
- APPLICATION_STATUS,
- REQUEST_SUBMITTED,
- REQUEST_FAILURE,
- UPGRADE_REQUESTED,
-} from '../constants';
+import UninstallApplicationButton from './uninstall_application_button.vue';
+import UninstallApplicationConfirmationModal from './uninstall_application_confirmation_modal.vue';
+
+import { APPLICATION_STATUS } from '../constants';
export default {
components: {
@@ -19,6 +17,11 @@ export default {
identicon,
TimeagoTooltip,
GlLink,
+ UninstallApplicationButton,
+ UninstallApplicationConfirmationModal,
+ },
+ directives: {
+ GlModalDirective,
},
props: {
id: {
@@ -47,6 +50,11 @@ export default {
required: false,
default: false,
},
+ uninstallable: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
status: {
type: String,
required: false,
@@ -55,13 +63,19 @@ export default {
type: String,
required: false,
},
- requestStatus: {
+ requestReason: {
type: String,
required: false,
},
- requestReason: {
- type: String,
+ installed: {
+ type: Boolean,
required: false,
+ default: false,
+ },
+ installFailed: {
+ type: Boolean,
+ required: false,
+ default: false,
},
version: {
type: String,
@@ -71,9 +85,33 @@ export default {
type: String,
required: false,
},
- upgradeAvailable: {
+ updateAvailable: {
+ type: Boolean,
+ required: false,
+ },
+ updateable: {
+ type: Boolean,
+ default: true,
+ },
+ updateSuccessful: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ updateFailed: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ uninstallFailed: {
type: Boolean,
required: false,
+ default: false,
+ },
+ uninstallSuccessful: {
+ type: Boolean,
+ required: false,
+ default: false,
},
installApplicationRequestParams: {
type: Object,
@@ -89,34 +127,17 @@ export default {
return Object.values(APPLICATION_STATUS).includes(this.status);
},
isInstalling() {
- return (
- this.status === APPLICATION_STATUS.SCHEDULED ||
- this.status === APPLICATION_STATUS.INSTALLING ||
- (this.requestStatus === REQUEST_SUBMITTED && !this.statusReason && !this.isInstalled)
- );
- },
- isInstalled() {
- return (
- this.status === APPLICATION_STATUS.INSTALLED ||
- this.status === APPLICATION_STATUS.UPDATED ||
- this.status === APPLICATION_STATUS.UPDATING ||
- this.status === APPLICATION_STATUS.UPDATE_ERRORED
- );
+ return this.status === APPLICATION_STATUS.INSTALLING;
},
canInstall() {
- if (this.isInstalling) {
- return false;
- }
-
return (
this.status === APPLICATION_STATUS.NOT_INSTALLABLE ||
this.status === APPLICATION_STATUS.INSTALLABLE ||
- this.status === APPLICATION_STATUS.ERROR ||
this.isUnknownStatus
);
},
hasLogo() {
- return !!this.logoUrl;
+ return Boolean(this.logoUrl);
},
identiconId() {
// generate a deterministic integer id for the identicon background
@@ -125,8 +146,14 @@ export default {
rowJsClass() {
return `js-cluster-application-row-${this.id}`;
},
+ displayUninstallButton() {
+ return this.installed && this.uninstallable;
+ },
+ displayInstallButton() {
+ return !this.installed || !this.uninstallable;
+ },
installButtonLoading() {
- return !this.status || this.status === APPLICATION_STATUS.SCHEDULED || this.isInstalling;
+ return !this.status || this.isInstalling;
},
installButtonDisabled() {
// Avoid the potential for the real-time data to say APPLICATION_STATUS.INSTALLABLE but
@@ -142,11 +169,11 @@ export default {
installButtonLabel() {
let label;
if (this.canInstall) {
- label = s__('ClusterIntegration|Install');
+ label = __('Install');
} else if (this.isInstalling) {
- label = s__('ClusterIntegration|Installing');
- } else if (this.isInstalled) {
- label = s__('ClusterIntegration|Installed');
+ label = __('Installing');
+ } else if (this.installed) {
+ label = __('Installed');
}
return label;
@@ -155,81 +182,78 @@ export default {
return this.manageLink && this.status === APPLICATION_STATUS.INSTALLED;
},
manageButtonLabel() {
- return s__('ClusterIntegration|Manage');
+ return __('Manage');
},
hasError() {
- return (
- !this.isInstalling &&
- (this.status === APPLICATION_STATUS.ERROR || this.requestStatus === REQUEST_FAILURE)
- );
+ return this.installFailed || this.uninstallFailed;
},
generalErrorDescription() {
- return sprintf(s__('ClusterIntegration|Something went wrong while installing %{title}'), {
- title: this.title,
- });
- },
- versionLabel() {
- if (this.upgradeFailed) {
- return s__('ClusterIntegration|Upgrade failed');
- } else if (this.isUpgrading) {
- return s__('ClusterIntegration|Upgrading');
+ let errorDescription;
+
+ if (this.installFailed) {
+ errorDescription = s__('ClusterIntegration|Something went wrong while installing %{title}');
+ } else if (this.uninstallFailed) {
+ errorDescription = s__(
+ 'ClusterIntegration|Something went wrong while uninstalling %{title}',
+ );
}
- return s__('ClusterIntegration|Upgraded');
- },
- upgradeRequested() {
- return this.requestStatus === UPGRADE_REQUESTED;
- },
- upgradeSuccessful() {
- return this.status === APPLICATION_STATUS.UPDATED;
+ return sprintf(errorDescription, { title: this.title });
},
- upgradeFailed() {
- if (this.isUpgrading) {
- return false;
+ versionLabel() {
+ if (this.updateFailed) {
+ return __('Update failed');
+ } else if (this.isUpdating) {
+ return __('Updating');
}
- return this.status === APPLICATION_STATUS.UPDATE_ERRORED;
+ return __('Updated');
},
- upgradeFailureDescription() {
+ updateFailureDescription() {
return s__('ClusterIntegration|Update failed. Please check the logs and try again.');
},
- upgradeSuccessDescription() {
- return sprintf(s__('ClusterIntegration|%{title} upgraded successfully.'), {
+ updateSuccessDescription() {
+ return sprintf(s__('ClusterIntegration|%{title} updated successfully.'), {
title: this.title,
});
},
- upgradeButtonLabel() {
+ updateButtonLabel() {
let label;
- if (this.upgradeAvailable && !this.upgradeFailed && !this.isUpgrading) {
- label = s__('ClusterIntegration|Upgrade');
- } else if (this.isUpgrading) {
- label = s__('ClusterIntegration|Updating');
- } else if (this.upgradeFailed) {
- label = s__('ClusterIntegration|Retry update');
+ if (this.updateAvailable && !this.updateFailed && !this.isUpdating) {
+ label = __('Update');
+ } else if (this.isUpdating) {
+ label = __('Updating');
+ } else if (this.updateFailed) {
+ label = __('Retry update');
}
return label;
},
- isUpgrading() {
+ isUpdating() {
// Since upgrading is handled asynchronously on the backend we need this check to prevent any delay on the frontend
- return (
- this.status === APPLICATION_STATUS.UPDATING ||
- (this.upgradeRequested && !this.upgradeSuccessful)
- );
+ return this.status === APPLICATION_STATUS.UPDATING;
},
- shouldShowUpgradeDetails() {
+ shouldShowUpdateDetails() {
// This method only returns true when;
- // Upgrade was successful OR Upgrade failed
- // AND new upgrade is unavailable AND version information is present.
- return (
- (this.upgradeSuccessful || this.upgradeFailed) && !this.upgradeAvailable && this.version
- );
+ // Update was successful OR Update failed
+ // AND new update is unavailable AND version information is present.
+ return (this.updateSuccessful || this.updateFailed) && !this.updateAvailable && this.version;
+ },
+ uninstallSuccessDescription() {
+ return sprintf(s__('ClusterIntegration|%{title} uninstalled successfully.'), {
+ title: this.title,
+ });
},
},
watch: {
- status() {
- if (this.status === APPLICATION_STATUS.UPDATE_ERRORED) {
- eventHub.$emit('upgradeFailed', this.id);
+ updateSuccessful(updateSuccessful) {
+ if (updateSuccessful) {
+ this.$toast.show(this.updateSuccessDescription);
+ }
+ },
+ uninstallSuccessful(uninstallSuccessful) {
+ if (uninstallSuccessful) {
+ this.$toast.show(this.uninstallSuccessDescription);
}
},
},
@@ -240,14 +264,16 @@ export default {
params: this.installApplicationRequestParams,
});
},
- upgradeClicked() {
- eventHub.$emit('upgradeApplication', {
+ updateClicked() {
+ eventHub.$emit('updateApplication', {
id: this.id,
params: this.installApplicationRequestParams,
});
},
- dismissUpgradeSuccess() {
- eventHub.$emit('dismissUpgradeSuccess', this.id);
+ uninstallConfirmed() {
+ eventHub.$emit('uninstallApplication', {
+ id: this.id,
+ });
},
},
};
@@ -257,7 +283,7 @@ export default {
<div
:class="[
rowJsClass,
- isInstalled && 'cluster-application-installed',
+ installed && 'cluster-application-installed',
disabled && 'cluster-application-disabled',
]"
class="cluster-application-row gl-responsive-table-row gl-responsive-table-row-col-span"
@@ -280,16 +306,12 @@ export default {
target="blank"
rel="noopener noreferrer"
class="js-cluster-application-title"
+ >{{ title }}</a
>
- {{ title }}
- </a>
- <span v-else class="js-cluster-application-title"> {{ title }} </span>
+ <span v-else class="js-cluster-application-title">{{ title }}</span>
</strong>
<slot name="description"></slot>
- <div
- v-if="hasError || isUnknownStatus"
- class="cluster-application-error text-danger prepend-top-10"
- >
+ <div v-if="hasError" class="cluster-application-error text-danger prepend-top-10">
<p class="js-cluster-application-general-error-message append-bottom-0">
{{ generalErrorDescription }}
</p>
@@ -303,50 +325,38 @@ export default {
</ul>
</div>
- <div
- v-if="shouldShowUpgradeDetails"
- class="form-text text-muted label p-0 js-cluster-application-upgrade-details"
- >
- {{ versionLabel }}
-
- <span v-if="upgradeSuccessful"> to</span>
-
- <gl-link
- v-if="upgradeSuccessful"
- :href="chartRepo"
- target="_blank"
- class="js-cluster-application-upgrade-version"
+ <div v-if="updateable">
+ <div
+ v-if="shouldShowUpdateDetails"
+ class="form-text text-muted label p-0 js-cluster-application-update-details"
>
- chart v{{ version }}
- </gl-link>
- </div>
+ {{ versionLabel }}
+ <span v-if="updateSuccessful">to</span>
- <div
- v-if="upgradeFailed && !isUpgrading"
- class="bs-callout bs-callout-danger cluster-application-banner mt-2 mb-0 js-cluster-application-upgrade-failure-message"
- >
- {{ upgradeFailureDescription }}
- </div>
-
- <div
- v-if="upgradeRequested && upgradeSuccessful"
- class="bs-callout bs-callout-success cluster-application-banner mt-2 mb-0 p-0 pl-3"
- >
- {{ upgradeSuccessDescription }}
+ <gl-link
+ v-if="updateSuccessful"
+ :href="chartRepo"
+ target="_blank"
+ class="js-cluster-application-update-version"
+ >chart v{{ version }}</gl-link
+ >
+ </div>
- <button class="close cluster-application-banner-close" @click="dismissUpgradeSuccess">
- &times;
- </button>
+ <div
+ v-if="updateFailed && !isUpdating"
+ class="bs-callout bs-callout-danger cluster-application-banner mt-2 mb-0 js-cluster-application-update-details"
+ >
+ {{ updateFailureDescription }}
+ </div>
+ <loading-button
+ v-if="updateAvailable || updateFailed || isUpdating"
+ class="btn btn-primary js-cluster-application-update-button mt-2"
+ :loading="isUpdating"
+ :disabled="isUpdating"
+ :label="updateButtonLabel"
+ @click="updateClicked"
+ />
</div>
-
- <loading-button
- v-if="upgradeAvailable || upgradeFailed || isUpgrading"
- class="btn btn-primary js-cluster-application-upgrade-button mt-2"
- :loading="isUpgrading"
- :disabled="isUpgrading"
- :label="upgradeButtonLabel"
- @click="upgradeClicked"
- />
</div>
<div
:class="{ 'section-25': showManageButton, 'section-15': !showManageButton }"
@@ -354,18 +364,30 @@ export default {
role="gridcell"
>
<div v-if="showManageButton" class="btn-group table-action-buttons">
- <a :href="manageLink" :class="{ disabled: disabled }" class="btn">
- {{ manageButtonLabel }}
- </a>
+ <a :href="manageLink" :class="{ disabled: disabled }" class="btn">{{
+ manageButtonLabel
+ }}</a>
</div>
<div class="btn-group table-action-buttons">
<loading-button
+ v-if="displayInstallButton"
:loading="installButtonLoading"
:disabled="disabled || installButtonDisabled"
:label="installButtonLabel"
class="js-cluster-application-install-button"
@click="installClicked"
/>
+ <uninstall-application-button
+ v-if="displayUninstallButton"
+ v-gl-modal-directive="'uninstall-' + id"
+ :status="status"
+ class="js-cluster-application-uninstall-button"
+ />
+ <uninstall-application-confirmation-modal
+ :application="id"
+ :application-title="title"
+ @confirm="uninstallConfirmed()"
+ />
</div>
</div>
</div>
diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue
index d54f9ce552c..970f5a7b297 100644
--- a/app/assets/javascripts/clusters/components/applications.vue
+++ b/app/assets/javascripts/clusters/components/applications.vue
@@ -15,6 +15,7 @@ import prometheusLogo from 'images/cluster_app_logos/prometheus.png';
import { s__, sprintf } from '../../locale';
import applicationRow from './application_row.vue';
import clipboardButton from '../../vue_shared/components/clipboard_button.vue';
+import KnativeDomainEditor from './knative_domain_editor.vue';
import { CLUSTER_TYPE, APPLICATION_STATUS, INGRESS } from '../constants';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import eventHub from '~/clusters/event_hub';
@@ -25,6 +26,7 @@ export default {
clipboardButton,
LoadingButton,
GlLoadingIcon,
+ KnativeDomainEditor,
},
props: {
type: {
@@ -154,64 +156,21 @@ export default {
knative() {
return this.applications.knative;
},
- knativeInstalled() {
- return (
- this.knative.status === APPLICATION_STATUS.INSTALLED ||
- this.knativeUpgrading ||
- this.knativeUpgradeFailed ||
- this.knative.status === APPLICATION_STATUS.UPDATED
- );
- },
- knativeUpgrading() {
- return (
- this.knative.status === APPLICATION_STATUS.UPDATING ||
- this.knative.status === APPLICATION_STATUS.SCHEDULED
- );
- },
- knativeUpgradeFailed() {
- return this.knative.status === APPLICATION_STATUS.UPDATE_ERRORED;
- },
- knativeExternalEndpoint() {
- return this.knative.externalIp || this.knative.externalHostname;
- },
- knativeDescription() {
- return sprintf(
- _.escape(
- s__(
- `ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}.`,
- ),
- ),
- {
- pricingLink: `<strong><a href="https://cloud.google.com/compute/pricing#lb"
- target="_blank" rel="noopener noreferrer">
- ${_.escape(s__('ClusterIntegration|pricing'))}</a></strong>`,
- },
- false,
- );
- },
- canUpdateKnativeEndpoint() {
- return this.knativeExternalEndpoint && !this.knativeUpgradeFailed && !this.knativeUpgrading;
- },
- knativeHostname: {
- get() {
- return this.knative.hostname;
- },
- set(hostname) {
- eventHub.$emit('setKnativeHostname', {
- id: 'knative',
- hostname,
- });
- },
- },
},
created() {
this.helmInstallIllustration = helmInstallIllustration;
},
methods: {
- saveKnativeDomain() {
+ saveKnativeDomain(hostname) {
eventHub.$emit('saveKnativeDomain', {
id: 'knative',
- params: { hostname: this.knative.hostname },
+ params: { hostname },
+ });
+ },
+ setKnativeHostname(hostname) {
+ eventHub.$emit('setKnativeHostname', {
+ id: 'knative',
+ hostname,
});
},
},
@@ -224,9 +183,9 @@ export default {
<p class="append-bottom-0">
{{
s__(`ClusterIntegration|Choose which applications to install on your Kubernetes cluster.
- Helm Tiller is required to install any of the following applications.`)
+ Helm Tiller is required to install any of the following applications.`)
}}
- <a :href="helpPath"> {{ __('More information') }} </a>
+ <a :href="helpPath">{{ __('More information') }}</a>
</p>
<div class="cluster-application-list prepend-top-10">
@@ -238,15 +197,20 @@ export default {
:status-reason="applications.helm.statusReason"
:request-status="applications.helm.requestStatus"
:request-reason="applications.helm.requestReason"
+ :installed="applications.helm.installed"
+ :install-failed="applications.helm.installFailed"
+ :uninstallable="applications.helm.uninstallable"
+ :uninstall-successful="applications.helm.uninstallSuccessful"
+ :uninstall-failed="applications.helm.uninstallFailed"
class="rounded-top"
title-link="https://docs.helm.sh/"
>
<div slot="description">
{{
s__(`ClusterIntegration|Helm streamlines installing
- and managing Kubernetes applications.
- Tiller runs inside of your Kubernetes Cluster,
- and manages releases of your charts.`)
+ and managing Kubernetes applications.
+ Tiller runs inside of your Kubernetes Cluster,
+ and manages releases of your charts.`)
}}
</div>
</application-row>
@@ -254,7 +218,7 @@ export default {
<div class="svg-container" v-html="helmInstallIllustration"></div>
{{
s__(`ClusterIntegration|You must first install Helm Tiller before
- installing the applications below`)
+ installing the applications below`)
}}
</div>
<application-row
@@ -265,6 +229,11 @@ export default {
:status-reason="applications.ingress.statusReason"
:request-status="applications.ingress.requestStatus"
:request-reason="applications.ingress.requestReason"
+ :installed="applications.ingress.installed"
+ :install-failed="applications.ingress.installFailed"
+ :uninstallable="applications.ingress.uninstallable"
+ :uninstall-successful="applications.ingress.uninstallSuccessful"
+ :uninstall-failed="applications.ingress.uninstallFailed"
:disabled="!helmInstalled"
title-link="https://kubernetes.io/docs/concepts/services-networking/ingress/"
>
@@ -272,16 +241,14 @@ export default {
<p>
{{
s__(`ClusterIntegration|Ingress gives you a way to route
- requests to services based on the request host or path,
- centralizing a number of services into a single entrypoint.`)
+ requests to services based on the request host or path,
+ centralizing a number of services into a single entrypoint.`)
}}
</p>
<template v-if="ingressInstalled">
<div class="form-group">
- <label for="ingress-endpoint">
- {{ s__('ClusterIntegration|Ingress Endpoint') }}
- </label>
+ <label for="ingress-endpoint">{{ s__('ClusterIntegration|Ingress Endpoint') }}</label>
<div v-if="ingressExternalEndpoint" class="input-group">
<input
id="ingress-endpoint"
@@ -307,8 +274,8 @@ export default {
<p class="form-text text-muted">
{{
s__(`ClusterIntegration|Point a wildcard DNS to this
- generated endpoint in order to access
- your application after it has been deployed.`)
+ generated endpoint in order to access
+ your application after it has been deployed.`)
}}
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
{{ __('More information') }}
@@ -319,10 +286,9 @@ export default {
<p v-if="!ingressExternalEndpoint" class="settings-message js-no-endpoint-message">
{{
s__(`ClusterIntegration|The endpoint is in
- the process of being assigned. Please check your Kubernetes
- cluster or Quotas on Google Kubernetes Engine if it takes a long time.`)
+ the process of being assigned. Please check your Kubernetes
+ cluster or Quotas on Google Kubernetes Engine if it takes a long time.`)
}}
-
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
{{ __('More information') }}
</a>
@@ -341,7 +307,12 @@ export default {
:status-reason="applications.cert_manager.statusReason"
:request-status="applications.cert_manager.requestStatus"
:request-reason="applications.cert_manager.requestReason"
+ :installed="applications.cert_manager.installed"
+ :install-failed="applications.cert_manager.installFailed"
:install-application-request-params="{ email: applications.cert_manager.email }"
+ :uninstallable="applications.cert_manager.uninstallable"
+ :uninstall-successful="applications.cert_manager.uninstallSuccessful"
+ :uninstall-failed="applications.cert_manager.uninstallFailed"
:disabled="!helmInstalled"
title-link="https://cert-manager.readthedocs.io/en/latest/#"
>
@@ -363,22 +334,20 @@ export default {
<p class="form-text text-muted">
{{
s__(`ClusterIntegration|Issuers represent a certificate authority.
- You must provide an email address for your Issuer. `)
+ You must provide an email address for your Issuer. `)
}}
<a
href="http://docs.cert-manager.io/en/latest/reference/issuers.html?highlight=email"
target="_blank"
rel="noopener noreferrer"
+ >{{ __('More information') }}</a
>
- {{ __('More information') }}
- </a>
</p>
</div>
</div>
</template>
</application-row>
<application-row
- v-if="isProjectCluster"
id="prometheus"
:logo-url="prometheusLogo"
:title="applications.prometheus.title"
@@ -387,6 +356,11 @@ export default {
:status-reason="applications.prometheus.statusReason"
:request-status="applications.prometheus.requestStatus"
:request-reason="applications.prometheus.requestReason"
+ :installed="applications.prometheus.installed"
+ :install-failed="applications.prometheus.installFailed"
+ :uninstallable="applications.prometheus.uninstallable"
+ :uninstall-successful="applications.prometheus.uninstallSuccessful"
+ :uninstall-failed="applications.prometheus.uninstallFailed"
:disabled="!helmInstalled"
title-link="https://prometheus.io/docs/introduction/overview/"
>
@@ -402,16 +376,23 @@ export default {
:request-reason="applications.runner.requestReason"
:version="applications.runner.version"
:chart-repo="applications.runner.chartRepo"
- :upgrade-available="applications.runner.upgradeAvailable"
+ :update-available="applications.runner.updateAvailable"
+ :installed="applications.runner.installed"
+ :install-failed="applications.runner.installFailed"
+ :update-successful="applications.runner.updateSuccessful"
+ :update-failed="applications.runner.updateFailed"
+ :uninstallable="applications.runner.uninstallable"
+ :uninstall-successful="applications.runner.uninstallSuccessful"
+ :uninstall-failed="applications.runner.uninstallFailed"
:disabled="!helmInstalled"
title-link="https://docs.gitlab.com/runner/"
>
<div slot="description">
{{
s__(`ClusterIntegration|GitLab Runner connects to the
- repository and executes CI/CD jobs,
- pushing results back and deploying
- applications to production.`)
+ repository and executes CI/CD jobs,
+ pushing results back and deploying
+ applications to production.`)
}}
</div>
</application-row>
@@ -424,6 +405,11 @@ export default {
:status-reason="applications.jupyter.statusReason"
:request-status="applications.jupyter.requestStatus"
:request-reason="applications.jupyter.requestReason"
+ :installed="applications.jupyter.installed"
+ :install-failed="applications.jupyter.installFailed"
+ :uninstallable="applications.jupyter.uninstallable"
+ :uninstall-successful="applications.jupyter.uninstallSuccessful"
+ :uninstall-failed="applications.jupyter.uninstallFailed"
:install-application-request-params="{ hostname: applications.jupyter.hostname }"
:disabled="!helmInstalled"
title-link="https://jupyterhub.readthedocs.io/en/stable/"
@@ -432,18 +418,16 @@ export default {
<p>
{{
s__(`ClusterIntegration|JupyterHub, a multi-user Hub, spawns,
- manages, and proxies multiple instances of the single-user
- Jupyter notebook server. JupyterHub can be used to serve
- notebooks to a class of students, a corporate data science group,
- or a scientific research group.`)
+ manages, and proxies multiple instances of the single-user
+ Jupyter notebook server. JupyterHub can be used to serve
+ notebooks to a class of students, a corporate data science group,
+ or a scientific research group.`)
}}
</p>
<template v-if="ingressExternalEndpoint">
<div class="form-group">
- <label for="jupyter-hostname">
- {{ s__('ClusterIntegration|Jupyter Hostname') }}
- </label>
+ <label for="jupyter-hostname">{{ s__('ClusterIntegration|Jupyter Hostname') }}</label>
<div class="input-group">
<input
@@ -464,7 +448,7 @@ export default {
<p v-if="ingressInstalled" class="form-text text-muted">
{{
s__(`ClusterIntegration|Replace this with your own hostname if you want.
- If you do so, point hostname to Ingress IP Address from above.`)
+ If you do so, point hostname to Ingress IP Address from above.`)
}}
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
{{ __('More information') }}
@@ -483,8 +467,15 @@ export default {
:status-reason="applications.knative.statusReason"
:request-status="applications.knative.requestStatus"
:request-reason="applications.knative.requestReason"
+ :installed="applications.knative.installed"
+ :install-failed="applications.knative.installFailed"
:install-application-request-params="{ hostname: applications.knative.hostname }"
+ :uninstallable="applications.knative.uninstallable"
+ :uninstall-successful="applications.knative.uninstallSuccessful"
+ :uninstall-failed="applications.knative.uninstallFailed"
+ :updateable="false"
:disabled="!helmInstalled"
+ v-bind="applications.knative"
title-link="https://github.com/knative/docs"
>
<div slot="description">
@@ -492,7 +483,7 @@ export default {
<p v-if="!rbac" class="rbac-notice bs-callout bs-callout-info append-bottom-0">
{{
s__(`ClusterIntegration|You must have an RBAC-enabled cluster
- to install Knative.`)
+ to install Knative.`)
}}
<a :href="helpPath" target="_blank" rel="noopener noreferrer">
{{ __('More information') }}
@@ -503,93 +494,19 @@ export default {
<p>
{{
s__(`ClusterIntegration|Knative extends Kubernetes to provide
- a set of middleware components that are essential to build modern,
- source-centric, and container-based applications that can run
- anywhere: on premises, in the cloud, or even in a third-party data center.`)
+ a set of middleware components that are essential to build modern,
+ source-centric, and container-based applications that can run
+ anywhere: on premises, in the cloud, or even in a third-party data center.`)
}}
</p>
- <div class="row">
- <template v-if="knativeInstalled || (helmInstalled && rbac)">
- <div
- :class="{ 'col-md-6': knativeInstalled, 'col-12': helmInstalled && rbac }"
- class="form-group col-sm-12 mb-0"
- >
- <label for="knative-domainname">
- <strong>
- {{ s__('ClusterIntegration|Knative Domain Name:') }}
- </strong>
- </label>
- <input
- id="knative-domainname"
- v-model="knativeHostname"
- type="text"
- class="form-control js-knative-domainname"
- />
- </div>
- </template>
- <template v-if="knativeInstalled">
- <div class="form-group col-sm-12 col-md-6 pl-md-0 mb-0 mt-3 mt-md-0">
- <label for="knative-endpoint">
- <strong>
- {{ s__('ClusterIntegration|Knative Endpoint:') }}
- </strong>
- </label>
- <div v-if="knativeExternalEndpoint" class="input-group">
- <input
- id="knative-endpoint"
- :value="knativeExternalEndpoint"
- type="text"
- class="form-control js-knative-endpoint"
- readonly
- />
- <span class="input-group-append">
- <clipboard-button
- :text="knativeExternalEndpoint"
- :title="s__('ClusterIntegration|Copy Knative Endpoint to clipboard')"
- class="input-group-text js-knative-endpoint-clipboard-btn"
- />
- </span>
- </div>
- <div v-else class="input-group">
- <input type="text" class="form-control js-endpoint" readonly />
- <gl-loading-icon
- class="position-absolute align-self-center ml-2 js-knative-ip-loading-icon"
- />
- </div>
- </div>
-
- <p class="form-text text-muted col-12">
- {{
- s__(
- `ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint.`,
- )
- }}
- <a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
- {{ __('More information') }}
- </a>
- </p>
-
- <p
- v-if="!knativeExternalEndpoint"
- class="settings-message js-no-knative-endpoint-message mt-2 mr-3 mb-0 ml-3"
- >
- {{
- s__(`ClusterIntegration|The endpoint is in
- the process of being assigned. Please check your Kubernetes
- cluster or Quotas on Google Kubernetes Engine if it takes a long time.`)
- }}
- </p>
-
- <button
- v-if="canUpdateKnativeEndpoint"
- class="btn btn-success js-knative-save-domain-button mt-3 ml-3"
- @click="saveKnativeDomain"
- >
- {{ s__('ClusterIntegration|Save changes') }}
- </button>
- </template>
- </div>
+ <knative-domain-editor
+ v-if="knative.installed || (helmInstalled && rbac)"
+ :knative="knative"
+ :ingress-dns-help-path="ingressDnsHelpPath"
+ @save="saveKnativeDomain"
+ @set="setKnativeHostname"
+ />
</div>
</application-row>
</div>
diff --git a/app/assets/javascripts/clusters/components/knative_domain_editor.vue b/app/assets/javascripts/clusters/components/knative_domain_editor.vue
new file mode 100644
index 00000000000..480228619a5
--- /dev/null
+++ b/app/assets/javascripts/clusters/components/knative_domain_editor.vue
@@ -0,0 +1,150 @@
+<script>
+import LoadingButton from '~/vue_shared/components/loading_button.vue';
+import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
+import { s__ } from '~/locale';
+
+import { APPLICATION_STATUS } from '~/clusters/constants';
+
+const { UPDATING, UNINSTALLING } = APPLICATION_STATUS;
+
+export default {
+ components: {
+ LoadingButton,
+ ClipboardButton,
+ GlLoadingIcon,
+ },
+ props: {
+ knative: {
+ type: Object,
+ required: true,
+ },
+ ingressDnsHelpPath: {
+ type: String,
+ default: '',
+ },
+ },
+ computed: {
+ saveButtonDisabled() {
+ return [UNINSTALLING, UPDATING].includes(this.knative.status);
+ },
+ saving() {
+ return [UPDATING].includes(this.knative.status);
+ },
+ saveButtonLabel() {
+ return this.saving ? this.__('Saving') : this.__('Save changes');
+ },
+ knativeInstalled() {
+ return this.knative.installed;
+ },
+ knativeExternalEndpoint() {
+ return this.knative.externalIp || this.knative.externalHostname;
+ },
+ knativeUpdateSuccessful() {
+ return this.knative.updateSuccessful;
+ },
+ knativeHostname: {
+ get() {
+ return this.knative.hostname;
+ },
+ set(hostname) {
+ this.$emit('set', hostname);
+ },
+ },
+ },
+ watch: {
+ knativeUpdateSuccessful(updateSuccessful) {
+ if (updateSuccessful) {
+ this.$toast.show(s__('ClusterIntegration|Knative domain name was updated successfully.'));
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="row">
+ <div
+ v-if="knative.updateFailed"
+ class="bs-callout bs-callout-danger cluster-application-banner col-12 mt-2 mb-2 js-cluster-knative-domain-name-failure-message"
+ >
+ {{ s__('ClusterIntegration|Something went wrong while updating Knative domain name.') }}
+ </div>
+
+ <template>
+ <div
+ :class="{ 'col-md-6': knativeInstalled, 'col-12': !knativeInstalled }"
+ class="form-group col-sm-12 mb-0"
+ >
+ <label for="knative-domainname">
+ <strong>{{ s__('ClusterIntegration|Knative Domain Name:') }}</strong>
+ </label>
+ <input
+ id="knative-domainname"
+ v-model="knativeHostname"
+ type="text"
+ class="form-control js-knative-domainname"
+ />
+ </div>
+ </template>
+ <template v-if="knativeInstalled">
+ <div class="form-group col-sm-12 col-md-6 pl-md-0 mb-0 mt-3 mt-md-0">
+ <label for="knative-endpoint">
+ <strong>{{ s__('ClusterIntegration|Knative Endpoint:') }}</strong>
+ </label>
+ <div v-if="knativeExternalEndpoint" class="input-group">
+ <input
+ id="knative-endpoint"
+ :value="knativeExternalEndpoint"
+ type="text"
+ class="form-control js-knative-endpoint"
+ readonly
+ />
+ <span class="input-group-append">
+ <clipboard-button
+ :text="knativeExternalEndpoint"
+ :title="s__('ClusterIntegration|Copy Knative Endpoint to clipboard')"
+ class="input-group-text js-knative-endpoint-clipboard-btn"
+ />
+ </span>
+ </div>
+ <div v-else class="input-group">
+ <input type="text" class="form-control js-endpoint" readonly />
+ <gl-loading-icon
+ class="position-absolute align-self-center ml-2 js-knative-ip-loading-icon"
+ />
+ </div>
+ </div>
+
+ <p class="form-text text-muted col-12">
+ {{
+ s__(
+ `ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint.`,
+ )
+ }}
+ <a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
+ {{ __('More information') }}
+ </a>
+ </p>
+
+ <p
+ v-if="!knativeExternalEndpoint"
+ class="settings-message js-no-knative-endpoint-message mt-2 mr-3 mb-0 ml-3"
+ >
+ {{
+ s__(`ClusterIntegration|The endpoint is in
+ the process of being assigned. Please check your Kubernetes
+ cluster or Quotas on Google Kubernetes Engine if it takes a long time.`)
+ }}
+ </p>
+
+ <loading-button
+ class="btn-success js-knative-save-domain-button mt-3 ml-3"
+ :loading="saving"
+ :disabled="saveButtonDisabled"
+ :label="saveButtonLabel"
+ @click="$emit('save', knativeHostname)"
+ />
+ </template>
+ </div>
+</template>
diff --git a/app/assets/javascripts/clusters/components/uninstall_application_button.vue b/app/assets/javascripts/clusters/components/uninstall_application_button.vue
new file mode 100644
index 00000000000..ef4bcbe14dd
--- /dev/null
+++ b/app/assets/javascripts/clusters/components/uninstall_application_button.vue
@@ -0,0 +1,33 @@
+<script>
+import LoadingButton from '~/vue_shared/components/loading_button.vue';
+import { APPLICATION_STATUS } from '~/clusters/constants';
+
+const { UPDATING, UNINSTALLING } = APPLICATION_STATUS;
+
+export default {
+ components: {
+ LoadingButton,
+ },
+ props: {
+ status: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ disabled() {
+ return [UNINSTALLING, UPDATING].includes(this.status);
+ },
+ loading() {
+ return this.status === UNINSTALLING;
+ },
+ label() {
+ return this.loading ? this.__('Uninstalling') : this.__('Uninstall');
+ },
+ },
+};
+</script>
+
+<template>
+ <loading-button :label="label" :disabled="disabled" :loading="loading" />
+</template>
diff --git a/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue b/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue
new file mode 100644
index 00000000000..65827f1cb6a
--- /dev/null
+++ b/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue
@@ -0,0 +1,74 @@
+<script>
+import { GlModal } from '@gitlab/ui';
+import { sprintf, s__ } from '~/locale';
+import trackUninstallButtonClickMixin from 'ee_else_ce/clusters/mixins/track_uninstall_button_click';
+import { INGRESS, CERT_MANAGER, PROMETHEUS, RUNNER, KNATIVE, JUPYTER } from '../constants';
+
+const CUSTOM_APP_WARNING_TEXT = {
+ [INGRESS]: s__(
+ 'ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored.',
+ ),
+ [CERT_MANAGER]: s__(
+ 'ClusterIntegration|The associated certifcate will be deleted and cannot be restored.',
+ ),
+ [PROMETHEUS]: s__('ClusterIntegration|All data will be deleted and cannot be restored.'),
+ [RUNNER]: s__('ClusterIntegration|Any running pipelines will be canceled.'),
+ [KNATIVE]: s__('ClusterIntegration|The associated IP will be deleted and cannot be restored.'),
+ [JUPYTER]: '',
+};
+
+export default {
+ components: {
+ GlModal,
+ },
+ mixins: [trackUninstallButtonClickMixin],
+ props: {
+ application: {
+ type: String,
+ required: true,
+ },
+ applicationTitle: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ title() {
+ return sprintf(s__('ClusterIntegration|Uninstall %{appTitle}'), {
+ appTitle: this.applicationTitle,
+ });
+ },
+ warningText() {
+ return sprintf(
+ s__('ClusterIntegration|You are about to uninstall %{appTitle} from your cluster.'),
+ {
+ appTitle: this.applicationTitle,
+ },
+ );
+ },
+ customAppWarningText() {
+ return CUSTOM_APP_WARNING_TEXT[this.application];
+ },
+ modalId() {
+ return `uninstall-${this.application}`;
+ },
+ },
+ methods: {
+ confirmUninstall() {
+ this.trackUninstallButtonClick(this.application);
+ this.$emit('confirm');
+ },
+ },
+};
+</script>
+<template>
+ <gl-modal
+ ok-variant="danger"
+ cancel-variant="light"
+ :ok-title="title"
+ :modal-id="modalId"
+ :title="title"
+ @ok="confirmUninstall()"
+ >{{ warningText }} {{ customAppWarningText }}</gl-modal
+ >
+</template>
diff --git a/app/assets/javascripts/clusters/constants.js b/app/assets/javascripts/clusters/constants.js
index 67f481f2afb..8fd752092c9 100644
--- a/app/assets/javascripts/clusters/constants.js
+++ b/app/assets/javascripts/clusters/constants.js
@@ -7,6 +7,7 @@ export const CLUSTER_TYPE = {
// These need to match what is returned from the server
export const APPLICATION_STATUS = {
+ NO_STATUS: null,
NOT_INSTALLABLE: 'not_installable',
INSTALLABLE: 'installable',
SCHEDULED: 'scheduled',
@@ -15,17 +16,35 @@ export const APPLICATION_STATUS = {
UPDATING: 'updating',
UPDATED: 'updated',
UPDATE_ERRORED: 'update_errored',
+ UNINSTALLING: 'uninstalling',
+ UNINSTALL_ERRORED: 'uninstall_errored',
ERROR: 'errored',
};
+/*
+ * The application cannot be in any of the following states without
+ * not being installed.
+ */
+export const APPLICATION_INSTALLED_STATUSES = [
+ APPLICATION_STATUS.INSTALLED,
+ APPLICATION_STATUS.UPDATING,
+ APPLICATION_STATUS.UNINSTALLING,
+];
+
// These are only used client-side
-export const REQUEST_SUBMITTED = 'request-submitted';
-export const REQUEST_FAILURE = 'request-failure';
-export const UPGRADE_REQUESTED = 'upgrade-requested';
-export const UPGRADE_REQUEST_FAILURE = 'upgrade-request-failure';
+
+export const UPDATE_EVENT = 'update';
+export const INSTALL_EVENT = 'install';
+export const UNINSTALL_EVENT = 'uninstall';
+
+export const HELM = 'helm';
export const INGRESS = 'ingress';
export const JUPYTER = 'jupyter';
export const KNATIVE = 'knative';
export const RUNNER = 'runner';
export const CERT_MANAGER = 'cert_manager';
+export const PROMETHEUS = 'prometheus';
+
+export const APPLICATIONS = [HELM, INGRESS, JUPYTER, KNATIVE, RUNNER, CERT_MANAGER, PROMETHEUS];
+
export const INGRESS_DOMAIN_SUFFIX = '.nip.io';
diff --git a/app/assets/javascripts/clusters/mixins/track_uninstall_button_click.js b/app/assets/javascripts/clusters/mixins/track_uninstall_button_click.js
new file mode 100644
index 00000000000..18f65b234d3
--- /dev/null
+++ b/app/assets/javascripts/clusters/mixins/track_uninstall_button_click.js
@@ -0,0 +1,5 @@
+export default {
+ methods: {
+ trackUninstallButtonClick: () => {},
+ },
+};
diff --git a/app/assets/javascripts/clusters/services/application_state_machine.js b/app/assets/javascripts/clusters/services/application_state_machine.js
new file mode 100644
index 00000000000..17ea4d77795
--- /dev/null
+++ b/app/assets/javascripts/clusters/services/application_state_machine.js
@@ -0,0 +1,174 @@
+import { APPLICATION_STATUS, UPDATE_EVENT, INSTALL_EVENT, UNINSTALL_EVENT } from '../constants';
+
+const {
+ NO_STATUS,
+ SCHEDULED,
+ NOT_INSTALLABLE,
+ INSTALLABLE,
+ INSTALLING,
+ INSTALLED,
+ ERROR,
+ UPDATING,
+ UPDATED,
+ UPDATE_ERRORED,
+ UNINSTALLING,
+ UNINSTALL_ERRORED,
+} = APPLICATION_STATUS;
+
+const applicationStateMachine = {
+ /* When the application initially loads, it will have `NO_STATUS`
+ * It will transition from `NO_STATUS` once the async backend call is completed
+ */
+ [NO_STATUS]: {
+ on: {
+ [SCHEDULED]: {
+ target: INSTALLING,
+ },
+ [NOT_INSTALLABLE]: {
+ target: NOT_INSTALLABLE,
+ },
+ [INSTALLABLE]: {
+ target: INSTALLABLE,
+ },
+ [INSTALLING]: {
+ target: INSTALLING,
+ },
+ [INSTALLED]: {
+ target: INSTALLED,
+ },
+ [ERROR]: {
+ target: INSTALLABLE,
+ effects: {
+ installFailed: true,
+ },
+ },
+ [UPDATING]: {
+ target: UPDATING,
+ },
+ [UPDATED]: {
+ target: INSTALLED,
+ },
+ [UPDATE_ERRORED]: {
+ target: INSTALLED,
+ effects: {
+ updateFailed: true,
+ },
+ },
+ [UNINSTALLING]: {
+ target: UNINSTALLING,
+ },
+ [UNINSTALL_ERRORED]: {
+ target: INSTALLED,
+ effects: {
+ uninstallFailed: true,
+ },
+ },
+ },
+ },
+ [NOT_INSTALLABLE]: {
+ on: {
+ [INSTALLABLE]: {
+ target: INSTALLABLE,
+ },
+ },
+ },
+ [INSTALLABLE]: {
+ on: {
+ [INSTALL_EVENT]: {
+ target: INSTALLING,
+ effects: {
+ installFailed: false,
+ },
+ },
+ // This is possible in artificial environments for E2E testing
+ [INSTALLED]: {
+ target: INSTALLED,
+ },
+ },
+ },
+ [INSTALLING]: {
+ on: {
+ [INSTALLED]: {
+ target: INSTALLED,
+ },
+ [ERROR]: {
+ target: INSTALLABLE,
+ effects: {
+ installFailed: true,
+ },
+ },
+ },
+ },
+ [INSTALLED]: {
+ on: {
+ [UPDATE_EVENT]: {
+ target: UPDATING,
+ effects: {
+ updateFailed: false,
+ updateSuccessful: false,
+ },
+ },
+ [UNINSTALL_EVENT]: {
+ target: UNINSTALLING,
+ effects: {
+ uninstallFailed: false,
+ uninstallSuccessful: false,
+ },
+ },
+ },
+ },
+ [UPDATING]: {
+ on: {
+ [UPDATED]: {
+ target: INSTALLED,
+ effects: {
+ updateSuccessful: true,
+ },
+ },
+ [UPDATE_ERRORED]: {
+ target: INSTALLED,
+ effects: {
+ updateFailed: true,
+ },
+ },
+ },
+ },
+ [UNINSTALLING]: {
+ on: {
+ [INSTALLABLE]: {
+ target: INSTALLABLE,
+ effects: {
+ uninstallSuccessful: true,
+ },
+ },
+ [UNINSTALL_ERRORED]: {
+ target: INSTALLED,
+ effects: {
+ uninstallFailed: true,
+ },
+ },
+ },
+ },
+};
+
+/**
+ * Determines an application new state based on the application current state
+ * and an event. If the application current state cannot handle a given event,
+ * the current state is returned.
+ *
+ * @param {*} application
+ * @param {*} event
+ */
+const transitionApplicationState = (application, event) => {
+ const newState = applicationStateMachine[application.status].on[event];
+
+ return newState
+ ? {
+ ...application,
+ status: newState.target,
+ ...newState.effects,
+ }
+ : application;
+};
+
+export default transitionApplicationState;
diff --git a/app/assets/javascripts/clusters/services/clusters_service.js b/app/assets/javascripts/clusters/services/clusters_service.js
index dea33ac44c5..01f3732de7e 100644
--- a/app/assets/javascripts/clusters/services/clusters_service.js
+++ b/app/assets/javascripts/clusters/services/clusters_service.js
@@ -29,6 +29,10 @@ export default class ClusterService {
return axios.patch(this.appUpdateEndpointMap[appId], params);
}
+ uninstallApplication(appId, params) {
+ return axios.delete(this.appInstallEndpointMap[appId], params);
+ }
+
static updateCluster(endpoint, data) {
return axios.put(endpoint, data);
}
diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js
index 92993337f02..f64f0ca616f 100644
--- a/app/assets/javascripts/clusters/stores/clusters_store.js
+++ b/app/assets/javascripts/clusters/stores/clusters_store.js
@@ -1,6 +1,31 @@
import { s__ } from '../../locale';
import { parseBoolean } from '../../lib/utils/common_utils';
-import { INGRESS, JUPYTER, KNATIVE, CERT_MANAGER, RUNNER } from '../constants';
+import {
+ INGRESS,
+ JUPYTER,
+ KNATIVE,
+ CERT_MANAGER,
+ RUNNER,
+ APPLICATION_INSTALLED_STATUSES,
+ APPLICATION_STATUS,
+ INSTALL_EVENT,
+ UPDATE_EVENT,
+ UNINSTALL_EVENT,
+} from '../constants';
+import transitionApplicationState from '../services/application_state_machine';
+
+const isApplicationInstalled = appStatus => APPLICATION_INSTALLED_STATUSES.includes(appStatus);
+
+const applicationInitialState = {
+ status: null,
+ statusReason: null,
+ requestReason: null,
+ installed: false,
+ installFailed: false,
+ uninstallable: false,
+ uninstallFailed: false,
+ uninstallSuccessful: false,
+};
export default class ClusterStore {
constructor() {
@@ -12,64 +37,47 @@ export default class ClusterStore {
statusReason: null,
applications: {
helm: {
+ ...applicationInitialState,
title: s__('ClusterIntegration|Helm Tiller'),
- status: null,
- statusReason: null,
- requestStatus: null,
- requestReason: null,
},
ingress: {
+ ...applicationInitialState,
title: s__('ClusterIntegration|Ingress'),
- status: null,
- statusReason: null,
- requestStatus: null,
- requestReason: null,
externalIp: null,
externalHostname: null,
},
cert_manager: {
+ ...applicationInitialState,
title: s__('ClusterIntegration|Cert-Manager'),
- status: null,
- statusReason: null,
- requestStatus: null,
- requestReason: null,
email: null,
},
runner: {
+ ...applicationInitialState,
title: s__('ClusterIntegration|GitLab Runner'),
- status: null,
- statusReason: null,
- requestStatus: null,
- requestReason: null,
version: null,
chartRepo: 'https://gitlab.com/charts/gitlab-runner',
- upgradeAvailable: null,
+ updateAvailable: null,
+ updateSuccessful: false,
+ updateFailed: false,
},
prometheus: {
+ ...applicationInitialState,
title: s__('ClusterIntegration|Prometheus'),
- status: null,
- statusReason: null,
- requestStatus: null,
- requestReason: null,
},
jupyter: {
+ ...applicationInitialState,
title: s__('ClusterIntegration|JupyterHub'),
- status: null,
- statusReason: null,
- requestStatus: null,
- requestReason: null,
hostname: null,
},
knative: {
+ ...applicationInitialState,
title: s__('ClusterIntegration|Knative'),
- status: null,
- statusReason: null,
- requestStatus: null,
- requestReason: null,
hostname: null,
isEditingHostName: false,
externalIp: null,
externalHostname: null,
+ updateSuccessful: false,
+ updateFailed: false,
},
},
};
@@ -97,6 +105,36 @@ export default class ClusterStore {
this.state.statusReason = reason;
}
+ installApplication(appId) {
+ this.handleApplicationEvent(appId, INSTALL_EVENT);
+ }
+
+ notifyInstallFailure(appId) {
+ this.handleApplicationEvent(appId, APPLICATION_STATUS.ERROR);
+ }
+
+ updateApplication(appId) {
+ this.handleApplicationEvent(appId, UPDATE_EVENT);
+ }
+
+ notifyUpdateFailure(appId) {
+ this.handleApplicationEvent(appId, APPLICATION_STATUS.UPDATE_ERRORED);
+ }
+
+ uninstallApplication(appId) {
+ this.handleApplicationEvent(appId, UNINSTALL_EVENT);
+ }
+
+ notifyUninstallFailure(appId) {
+ this.handleApplicationEvent(appId, APPLICATION_STATUS.UNINSTALL_ERRORED);
+ }
+
+ handleApplicationEvent(appId, event) {
+ const currentAppState = this.state.applications[appId];
+
+ this.state.applications[appId] = transitionApplicationState(currentAppState, event);
+ }
+
updateAppProperty(appId, prop, value) {
this.state.applications[appId][prop] = value;
}
@@ -111,13 +149,18 @@ export default class ClusterStore {
status,
status_reason: statusReason,
version,
- update_available: upgradeAvailable,
+ update_available: updateAvailable,
+ can_uninstall: uninstallable,
} = serverAppEntry;
+ const currentApplicationState = this.state.applications[appId] || {};
+ const nextApplicationState = transitionApplicationState(currentApplicationState, status);
this.state.applications[appId] = {
- ...(this.state.applications[appId] || {}),
- status,
+ ...currentApplicationState,
+ ...nextApplicationState,
statusReason,
+ installed: isApplicationInstalled(nextApplicationState.status),
+ uninstallable,
};
if (appId === INGRESS) {
@@ -143,7 +186,7 @@ export default class ClusterStore {
serverAppEntry.external_hostname || this.state.applications.knative.externalHostname;
} else if (appId === RUNNER) {
this.state.applications.runner.version = version;
- this.state.applications.runner.upgradeAvailable = upgradeAvailable;
+ this.state.applications.runner.updateAvailable = updateAvailable;
}
});
}
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.vue b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
index 3e01841d563..4890f99e9d1 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_table.vue
+++ b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
@@ -2,7 +2,7 @@
import PipelinesService from '../../pipelines/services/pipelines_service';
import PipelineStore from '../../pipelines/stores/pipelines_store';
import pipelinesMixin from '../../pipelines/mixins/pipelines';
-import TablePagination from '../../vue_shared/components/table_pagination.vue';
+import TablePagination from '../../vue_shared/components/pagination/table_pagination.vue';
import { getParameterByName } from '../../lib/utils/common_utils';
import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin';
diff --git a/app/assets/javascripts/commons/polyfills.js b/app/assets/javascripts/commons/polyfills.js
index a0ca44caa07..d0cc4897aeb 100644
--- a/app/assets/javascripts/commons/polyfills.js
+++ b/app/assets/javascripts/commons/polyfills.js
@@ -1,19 +1,21 @@
// ECMAScript polyfills
-import 'core-js/fn/array/fill';
-import 'core-js/fn/array/find';
-import 'core-js/fn/array/find-index';
-import 'core-js/fn/array/from';
-import 'core-js/fn/array/includes';
-import 'core-js/fn/object/assign';
-import 'core-js/fn/object/values';
-import 'core-js/fn/promise';
-import 'core-js/fn/promise/finally';
-import 'core-js/fn/string/code-point-at';
-import 'core-js/fn/string/from-code-point';
-import 'core-js/fn/string/includes';
-import 'core-js/fn/symbol';
-import 'core-js/es6/map';
-import 'core-js/es6/weak-map';
+import 'core-js/es/array/fill';
+import 'core-js/es/array/find';
+import 'core-js/es/array/find-index';
+import 'core-js/es/array/from';
+import 'core-js/es/array/includes';
+import 'core-js/es/object/assign';
+import 'core-js/es/object/values';
+import 'core-js/es/object/entries';
+import 'core-js/es/promise';
+import 'core-js/es/promise/finally';
+import 'core-js/es/string/code-point-at';
+import 'core-js/es/string/from-code-point';
+import 'core-js/es/string/includes';
+import 'core-js/es/symbol';
+import 'core-js/es/map';
+import 'core-js/es/weak-map';
+import 'core-js/modules/web.url';
// Browser polyfills
import 'formdata-polyfill';
diff --git a/app/assets/javascripts/compare_autocomplete.js b/app/assets/javascripts/compare_autocomplete.js
index 37a3ceb5341..5bfe158ceda 100644
--- a/app/assets/javascripts/compare_autocomplete.js
+++ b/app/assets/javascripts/compare_autocomplete.js
@@ -40,7 +40,7 @@ export default function initCompareAutocomplete(limitTo = null, clickHandler = (
},
selectable: true,
filterable: true,
- filterRemote: !!$dropdown.data('refsUrl'),
+ filterRemote: Boolean($dropdown.data('refsUrl')),
fieldName: $dropdown.data('fieldName'),
filterInput: 'input[type="search"]',
renderRow: function(ref) {
diff --git a/app/assets/javascripts/contextual_sidebar.js b/app/assets/javascripts/contextual_sidebar.js
index 03dea1ec0a5..9263e9b27e4 100644
--- a/app/assets/javascripts/contextual_sidebar.js
+++ b/app/assets/javascripts/contextual_sidebar.js
@@ -8,6 +8,8 @@ import { parseBoolean } from '~/lib/utils/common_utils';
// https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24555#note_134136110
const NAV_SIDEBAR_BREAKPOINT = 1200;
+export const SIDEBAR_COLLAPSED_CLASS = 'js-sidebar-collapsed';
+
export default class ContextualSidebar {
constructor() {
this.initDomElements();
@@ -62,6 +64,7 @@ export default class ContextualSidebar {
const breakpoint = bp.getBreakpointSize();
const dbp = ContextualSidebar.isDesktopBreakpoint();
+ this.$sidebar.toggleClass(SIDEBAR_COLLAPSED_CLASS, !show);
this.$sidebar.toggleClass('sidebar-expanded-mobile', !dbp ? show : false);
this.$overlay.toggleClass(
'mobile-nav-open',
@@ -75,7 +78,7 @@ export default class ContextualSidebar {
const dbp = ContextualSidebar.isDesktopBreakpoint();
if (this.$sidebar.length) {
- this.$sidebar.toggleClass('sidebar-collapsed-desktop', collapsed);
+ this.$sidebar.toggleClass(`sidebar-collapsed-desktop ${SIDEBAR_COLLAPSED_CLASS}`, collapsed);
this.$sidebar.toggleClass('sidebar-expanded-mobile', !dbp ? !collapsed : false);
this.$page.toggleClass(
'page-with-icon-sidebar',
diff --git a/app/assets/javascripts/create_item_dropdown.js b/app/assets/javascripts/create_item_dropdown.js
index 916b190f469..fa0f04c7d82 100644
--- a/app/assets/javascripts/create_item_dropdown.js
+++ b/app/assets/javascripts/create_item_dropdown.js
@@ -12,7 +12,7 @@ export default class CreateItemDropdown {
this.fieldName = options.fieldName;
this.onSelect = options.onSelect || (() => {});
this.getDataOption = options.getData;
- this.getDataRemote = !!options.filterRemote;
+ this.getDataRemote = Boolean(options.filterRemote);
this.createNewItemFromValueOption = options.createNewItemFromValue;
this.$dropdown = options.$dropdown;
this.$dropdownContainer = this.$dropdown.parent();
diff --git a/app/assets/javascripts/create_merge_request_dropdown.js b/app/assets/javascripts/create_merge_request_dropdown.js
index 02aa507ba03..8f5cece0788 100644
--- a/app/assets/javascripts/create_merge_request_dropdown.js
+++ b/app/assets/javascripts/create_merge_request_dropdown.js
@@ -118,7 +118,7 @@ export default class CreateMergeRequestDropdown {
this.branchCreated = true;
window.location.href = data.url;
})
- .catch(() => Flash('Failed to create a branch for this issue. Please try again.'));
+ .catch(() => Flash(__('Failed to create a branch for this issue. Please try again.')));
}
createMergeRequest() {
@@ -130,7 +130,7 @@ export default class CreateMergeRequestDropdown {
this.mergeRequestCreated = true;
window.location.href = data.url;
})
- .catch(() => Flash('Failed to create Merge Request. Please try again.'));
+ .catch(() => Flash(__('Failed to create Merge Request. Please try again.')));
}
disable() {
@@ -227,7 +227,7 @@ export default class CreateMergeRequestDropdown {
.catch(() => {
this.unavailable();
this.disable();
- new Flash('Failed to get ref.');
+ new Flash(__('Failed to get ref.'));
this.isGettingRef = false;
diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
index 4de425b48e7..3f0a9f2602c 100644
--- a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
+++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
@@ -12,6 +12,7 @@ import stageStagingComponent from './components/stage_staging_component.vue';
import stageTestComponent from './components/stage_test_component.vue';
import CycleAnalyticsService from './cycle_analytics_service';
import CycleAnalyticsStore from './cycle_analytics_store';
+import { __ } from '~/locale';
Vue.use(Translate);
@@ -61,7 +62,7 @@ export default () => {
methods: {
handleError() {
this.store.setErrorState(true);
- return new Flash('There was an error while fetching cycle analytics data.');
+ return new Flash(__('There was an error while fetching cycle analytics data.'));
},
initDropdown() {
const $dropdown = $('.js-ca-dropdown');
diff --git a/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js b/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js
index 4ae4ceabc21..f66e07ba31a 100644
--- a/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js
+++ b/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js
@@ -3,6 +3,7 @@
import $ from 'jquery';
import Vue from 'vue';
+import { __ } from '~/locale';
const CommentAndResolveBtn = Vue.extend({
props: {
@@ -31,15 +32,15 @@ const CommentAndResolveBtn = Vue.extend({
buttonText: function() {
if (this.isDiscussionResolved) {
if (this.textareaIsEmpty) {
- return 'Unresolve discussion';
+ return __('Unresolve discussion');
} else {
- return 'Comment & unresolve discussion';
+ return __('Comment & unresolve discussion');
}
} else {
if (this.textareaIsEmpty) {
- return 'Resolve discussion';
+ return __('Resolve discussion');
} else {
- return 'Comment & resolve discussion';
+ return __('Comment & resolve discussion');
}
}
},
diff --git a/app/assets/javascripts/diff_notes/components/diff_note_avatars.js b/app/assets/javascripts/diff_notes/components/diff_note_avatars.js
index 5bdeaaade68..b5a781cbc92 100644
--- a/app/assets/javascripts/diff_notes/components/diff_note_avatars.js
+++ b/app/assets/javascripts/diff_notes/components/diff_note_avatars.js
@@ -5,6 +5,7 @@ import Vue from 'vue';
import collapseIcon from '../icons/collapse_icon.svg';
import Notes from '../../notes';
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
+import { n__ } from '~/locale';
const DiffNoteAvatars = Vue.extend({
components: {
@@ -44,7 +45,7 @@ const DiffNoteAvatars = Vue.extend({
if (this.discussion) {
const extra = this.discussion.notesCount() - this.shownAvatars;
- return `${extra} more comment${extra > 1 ? 's' : ''}`;
+ return n__('%d more comment', '%d more comments', extra);
}
return '';
diff --git a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js
index 8542a6e718a..fe4088cadda 100644
--- a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js
+++ b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js
@@ -3,6 +3,7 @@
import $ from 'jquery';
import Vue from 'vue';
+import { __ } from '~/locale';
import DiscussionMixins from '../mixins/discussion';
@@ -23,9 +24,9 @@ const JumpToDiscussion = Vue.extend({
computed: {
buttonText: function() {
if (this.discussionId) {
- return 'Jump to next unresolved discussion';
+ return __('Jump to next unresolved discussion');
} else {
- return 'Jump to first unresolved discussion';
+ return __('Jump to first unresolved discussion');
}
},
allResolved: function() {
diff --git a/app/assets/javascripts/diff_notes/components/resolve_btn.js b/app/assets/javascripts/diff_notes/components/resolve_btn.js
index a69b34b0db8..87e7dd18e0c 100644
--- a/app/assets/javascripts/diff_notes/components/resolve_btn.js
+++ b/app/assets/javascripts/diff_notes/components/resolve_btn.js
@@ -4,6 +4,7 @@
import $ from 'jquery';
import Vue from 'vue';
import Flash from '../../flash';
+import { sprintf, __ } from '~/locale';
const ResolveBtn = Vue.extend({
props: {
@@ -55,12 +56,14 @@ const ResolveBtn = Vue.extend({
},
buttonText() {
if (this.isResolved) {
- return `Resolved by ${this.resolvedByName}`;
+ return sprintf(__('Resolved by %{resolvedByName}'), {
+ resolvedByName: this.resolvedByName,
+ });
} else if (this.canResolve) {
- return 'Mark as resolved';
+ return __('Mark as resolved');
}
- return 'Unable to resolve';
+ return __('Unable to resolve');
},
isResolved() {
if (this.note) {
@@ -132,7 +135,8 @@ const ResolveBtn = Vue.extend({
this.updateTooltip();
})
.catch(
- () => new Flash('An error occurred when trying to resolve a comment. Please try again.'),
+ () =>
+ new Flash(__('An error occurred when trying to resolve a comment. Please try again.')),
);
},
},
diff --git a/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js b/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js
index 6fcad187b35..4b204fdfeb0 100644
--- a/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js
+++ b/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js
@@ -3,6 +3,7 @@
/* global ResolveService */
import Vue from 'vue';
+import { __ } from '~/locale';
const ResolveDiscussionBtn = Vue.extend({
props: {
@@ -41,9 +42,9 @@ const ResolveDiscussionBtn = Vue.extend({
},
buttonText: function() {
if (this.isDiscussionResolved) {
- return 'Unresolve discussion';
+ return __('Unresolve discussion');
} else {
- return 'Resolve discussion';
+ return __('Resolve discussion');
}
},
loading: function() {
diff --git a/app/assets/javascripts/diff_notes/services/resolve.js b/app/assets/javascripts/diff_notes/services/resolve.js
index e69eaad4423..0687028ca54 100644
--- a/app/assets/javascripts/diff_notes/services/resolve.js
+++ b/app/assets/javascripts/diff_notes/services/resolve.js
@@ -3,6 +3,7 @@
import Vue from 'vue';
import Flash from '../../flash';
import '../../vue_shared/vue_resource_interceptor';
+import { __ } from '~/locale';
window.gl = window.gl || {};
@@ -49,7 +50,8 @@ class ResolveServiceClass {
discussion.updateHeadline(data);
})
.catch(
- () => new Flash('An error occurred when trying to resolve a discussion. Please try again.'),
+ () =>
+ new Flash(__('An error occurred when trying to resolve a discussion. Please try again.')),
);
}
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 0ed4dcdcd81..11d6672cacf 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -157,10 +157,12 @@ export default {
this.adjustView();
eventHub.$once('fetchedNotesData', this.setDiscussions);
eventHub.$once('fetchDiffData', this.fetchData);
+ eventHub.$on('refetchDiffData', this.refetchDiffData);
this.CENTERED_LIMITED_CONTAINER_CLASSES = CENTERED_LIMITED_CONTAINER_CLASSES;
},
beforeDestroy() {
eventHub.$off('fetchDiffData', this.fetchData);
+ eventHub.$off('refetchDiffData', this.refetchDiffData);
this.removeEventListeners();
},
methods: {
@@ -175,10 +177,16 @@ export default {
'scrollToFile',
'toggleShowTreeList',
]),
- fetchData() {
+ refetchDiffData() {
+ this.assignedDiscussions = false;
+ this.fetchData(false);
+ },
+ fetchData(toggleTree = true) {
this.fetchDiffFiles()
.then(() => {
- this.hideTreeListIfJustOneFile();
+ if (toggleTree) {
+ this.hideTreeListIfJustOneFile();
+ }
requestIdleCallback(
() => {
diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue
index c02a8740a42..aaa9f8b759a 100644
--- a/app/assets/javascripts/diffs/components/commit_item.vue
+++ b/app/assets/javascripts/diffs/components/commit_item.vue
@@ -69,7 +69,7 @@ export default {
:link-href="authorUrl"
:img-src="authorAvatar"
:img-alt="authorName"
- :img-size="36"
+ :img-size="40"
class="avatar-cell d-none d-sm-block"
/>
<div class="commit-detail flex-list">
@@ -91,7 +91,7 @@ export default {
<icon :size="12" name="ellipsis_h" />
</button>
- <div class="commiter">
+ <div class="committer">
<a
:href="authorUrl"
:class="authorClass"
@@ -113,9 +113,10 @@ export default {
<commit-pipeline-status
v-if="commit.pipeline_status_path"
:endpoint="commit.pipeline_status_path"
+ class="d-inline-flex"
/>
<div class="commit-sha-group">
- <div class="label label-monospace" v-text="commit.short_id"></div>
+ <div class="label label-monospace monospace" v-text="commit.short_id"></div>
<clipboard-button
:text="commit.id"
:title="__('Copy commit SHA to clipboard')"
diff --git a/app/assets/javascripts/diffs/components/diff_content.vue b/app/assets/javascripts/diffs/components/diff_content.vue
index 8d09c2a7399..d59b1136677 100644
--- a/app/assets/javascripts/diffs/components/diff_content.vue
+++ b/app/assets/javascripts/diffs/components/diff_content.vue
@@ -1,5 +1,6 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
+import { GlLoadingIcon } from '@gitlab/ui';
import diffLineNoteFormMixin from 'ee_else_ce/notes/mixins/diff_line_note_form';
import draftCommentsMixin from 'ee_else_ce/diffs/mixins/draft_comments';
import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
@@ -7,6 +8,7 @@ import NotDiffableViewer from '~/vue_shared/components/diff_viewer/viewers/not_d
import NoPreviewViewer from '~/vue_shared/components/diff_viewer/viewers/no_preview.vue';
import InlineDiffView from './inline_diff_view.vue';
import ParallelDiffView from './parallel_diff_view.vue';
+import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import NoteForm from '../../notes/components/note_form.vue';
import ImageDiffOverlay from './image_diff_overlay.vue';
import DiffDiscussions from './diff_discussions.vue';
@@ -16,6 +18,7 @@ import { diffViewerModes } from '~/ide/constants';
export default {
components: {
+ GlLoadingIcon,
InlineDiffView,
ParallelDiffView,
DiffViewer,
@@ -24,6 +27,7 @@ export default {
ImageDiffOverlay,
NotDiffableViewer,
NoPreviewViewer,
+ userAvatarLink,
DiffFileDrafts: () => import('ee_component/batch_comments/components/diff_file_drafts.vue'),
},
mixins: [diffLineNoteFormMixin, draftCommentsMixin],
@@ -45,7 +49,7 @@ export default {
}),
...mapGetters('diffs', ['isInlineView', 'isParallelView']),
...mapGetters('diffs', ['getCommentFormForDiffFile']),
- ...mapGetters(['getNoteableData', 'noteableType']),
+ ...mapGetters(['getNoteableData', 'noteableType', 'getUserData']),
diffMode() {
return getDiffMode(this.diffFile);
},
@@ -70,6 +74,9 @@ export default {
diffFileHash() {
return this.diffFile.file_hash;
},
+ author() {
+ return this.getUserData;
+ },
},
methods: {
...mapActions('diffs', ['saveDiffDiscussion', 'closeDiffFileCommentForm']),
@@ -108,6 +115,7 @@ export default {
:diff-lines="diffFile.parallel_diff_lines || []"
:help-page-path="helpPagePath"
/>
+ <gl-loading-icon v-if="diffFile.renderingLines" size="md" class="mt-3" />
</template>
<not-diffable-viewer v-else-if="notDiffable" />
<no-preview-viewer v-else-if="noPreview" />
@@ -131,6 +139,14 @@ export default {
:can-comment="getNoteableData.current_user.can_create_note"
/>
<div v-if="showNotesContainer" class="note-container">
+ <user-avatar-link
+ v-if="diffFileCommentForm && author"
+ :link-href="author.path"
+ :img-src="author.avatar_url"
+ :img-alt="author.name"
+ :img-size="40"
+ class="d-none d-sm-block new-comment"
+ />
<diff-discussions
v-if="diffFile.discussions.length"
class="diff-file-discussions"
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index 91b802766f8..eb9f1465945 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -240,7 +240,7 @@ export default {
css-class="btn-default btn-transparent btn-clipboard"
/>
- <small v-if="isModeChanged" ref="fileMode">
+ <small v-if="isModeChanged" ref="fileMode" class="mr-1">
{{ diffFile.a_mode }} → {{ diffFile.b_mode }}
</small>
@@ -254,16 +254,17 @@ export default {
<diff-stats :added-lines="diffFile.added_lines" :removed-lines="diffFile.removed_lines" />
<div class="btn-group" role="group">
<template v-if="diffFile.blob && diffFile.blob.readable_text">
- <button
- :disabled="!diffHasDiscussions(diffFile)"
- :class="{ active: hasExpandedDiscussions }"
- :title="s__('MergeRequests|Toggle comments for this file')"
- class="js-btn-vue-toggle-comments btn"
- type="button"
- @click="handleToggleDiscussions"
- >
- <icon name="comment" />
- </button>
+ <span v-gl-tooltip.hover :title="s__('MergeRequests|Toggle comments for this file')">
+ <gl-button
+ :disabled="!diffHasDiscussions(diffFile)"
+ :class="{ active: hasExpandedDiscussions }"
+ class="js-btn-vue-toggle-comments btn"
+ type="button"
+ @click="handleToggleDiscussions"
+ >
+ <icon name="comment" />
+ </gl-button>
+ </span>
<edit-button
v-if="!diffFile.deleted_file"
@@ -301,7 +302,7 @@ export default {
class="view-file js-view-file-button"
:title="viewFileButtonText"
>
- <icon name="external-link" />
+ <icon name="doc-text" />
</gl-button>
<a
diff --git a/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue b/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
index 0c0a0faa59d..7cf3d90d468 100644
--- a/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
+++ b/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
@@ -86,7 +86,6 @@ export default {
:key="note.id"
:img-src="note.author.avatar_url"
:tooltip-text="getTooltipText(note)"
- :size="19"
class="diff-comment-avatar js-diff-comment-avatar"
@click.native="toggleDiscussions"
/>
diff --git a/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue b/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue
index 6709df48637..1281f9b17ef 100644
--- a/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue
+++ b/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue
@@ -84,8 +84,6 @@ export default {
},
shouldShowCommentButton() {
return (
- this.isLoggedIn &&
- this.showCommentButton &&
this.isHover &&
!this.isMatchLine &&
!this.isContextLine &&
@@ -102,6 +100,9 @@ export default {
}
return this.showCommentButton && this.hasDiscussions;
},
+ shouldRenderCommentButton() {
+ return this.isLoggedIn && this.showCommentButton;
+ },
},
methods: {
...mapActions('diffs', ['loadMoreLines', 'showCommentForm', 'setHighlightedRow']),
@@ -167,6 +168,7 @@ export default {
>
<template v-else>
<button
+ v-if="shouldRenderCommentButton"
v-show="shouldShowCommentButton"
type="button"
class="add-diff-note js-add-diff-note-button qa-diff-comment"
diff --git a/app/assets/javascripts/diffs/components/diff_line_note_form.vue b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
index 41670b45798..c209b857652 100644
--- a/app/assets/javascripts/diffs/components/diff_line_note_form.vue
+++ b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
@@ -4,11 +4,13 @@ import { s__ } from '~/locale';
import diffLineNoteFormMixin from 'ee_else_ce/notes/mixins/diff_line_note_form';
import noteForm from '../../notes/components/note_form.vue';
import autosave from '../../notes/mixins/autosave';
+import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import { DIFF_NOTE_TYPE } from '../constants';
export default {
components: {
noteForm,
+ userAvatarLink,
},
mixins: [autosave, diffLineNoteFormMixin],
props: {
@@ -41,7 +43,16 @@ export default {
diffViewType: state => state.diffs.diffViewType,
}),
...mapGetters('diffs', ['getDiffFileByHash']),
- ...mapGetters(['isLoggedIn', 'noteableType', 'getNoteableData', 'getNotesDataByProp']),
+ ...mapGetters([
+ 'isLoggedIn',
+ 'noteableType',
+ 'getNoteableData',
+ 'getNotesDataByProp',
+ 'getUserData',
+ ]),
+ author() {
+ return this.getUserData;
+ },
formData() {
return {
noteableData: this.noteableData,
@@ -99,6 +110,14 @@ export default {
<template>
<div class="content discussion-form discussion-form-container discussion-notes">
+ <user-avatar-link
+ v-if="author"
+ :link-href="author.path"
+ :img-src="author.avatar_url"
+ :img-alt="author.name"
+ :img-size="40"
+ class="d-none d-sm-block"
+ />
<note-form
ref="noteForm"
:is-editing="true"
diff --git a/app/assets/javascripts/diffs/components/diff_table_cell.vue b/app/assets/javascripts/diffs/components/diff_table_cell.vue
index d174b13e133..0f3e9208d21 100644
--- a/app/assets/javascripts/diffs/components/diff_table_cell.vue
+++ b/app/assets/javascripts/diffs/components/diff_table_cell.vue
@@ -89,17 +89,19 @@ export default {
classNameMap() {
const { type } = this.line;
- return {
- hll: this.isHighlighted,
- [type]: type,
- [LINE_UNFOLD_CLASS_NAME]: this.isMatchLine,
- [LINE_HOVER_CLASS_NAME]:
- this.isLoggedIn &&
- this.isHover &&
- !this.isMatchLine &&
- !this.isContextLine &&
- !this.isMetaLine,
- };
+ return [
+ type,
+ {
+ hll: this.isHighlighted,
+ [LINE_UNFOLD_CLASS_NAME]: this.isMatchLine,
+ [LINE_HOVER_CLASS_NAME]:
+ this.isLoggedIn &&
+ this.isHover &&
+ !this.isMatchLine &&
+ !this.isContextLine &&
+ !this.isMetaLine,
+ },
+ ];
},
lineNumber() {
return this.lineType === OLD_LINE_TYPE ? this.line.old_line : this.line.new_line;
diff --git a/app/assets/javascripts/diffs/components/edit_button.vue b/app/assets/javascripts/diffs/components/edit_button.vue
index f0cc5de4b33..dcb79cd5e16 100644
--- a/app/assets/javascripts/diffs/components/edit_button.vue
+++ b/app/assets/javascripts/diffs/components/edit_button.vue
@@ -38,7 +38,7 @@ export default {
<template>
<gl-button
- v-gl-tooltip.bottom
+ v-gl-tooltip.top
:href="editPath"
:title="__('Edit file')"
class="js-edit-blob"
diff --git a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
index c764cbeb8e0..2d5262baeec 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
@@ -1,12 +1,11 @@
<script>
-import { mapGetters, mapActions, mapState } from 'vuex';
+import { mapActions, mapState } from 'vuex';
import DiffTableCell from './diff_table_cell.vue';
import {
NEW_LINE_TYPE,
OLD_LINE_TYPE,
CONTEXT_LINE_TYPE,
CONTEXT_LINE_CLASS_NAME,
- PARALLEL_DIFF_VIEW_TYPE,
LINE_POSITION_LEFT,
LINE_POSITION_RIGHT,
} from '../constants';
@@ -45,16 +44,16 @@ export default {
return this.line.line_code !== null && this.line.line_code === state.diffs.highlightedRow;
},
}),
- ...mapGetters('diffs', ['isInlineView']),
isContextLine() {
return this.line.type === CONTEXT_LINE_TYPE;
},
classNameMap() {
- return {
- [this.line.type]: this.line.type,
- [CONTEXT_LINE_CLASS_NAME]: this.isContextLine,
- [PARALLEL_DIFF_VIEW_TYPE]: this.isParallelView,
- };
+ return [
+ this.line.type,
+ {
+ [CONTEXT_LINE_CLASS_NAME]: this.isContextLine,
+ },
+ ];
},
inlineRowId() {
return this.line.line_code || `${this.fileHash}_${this.line.old_line}_${this.line.new_line}`;
diff --git a/app/assets/javascripts/diffs/components/tree_list.vue b/app/assets/javascripts/diffs/components/tree_list.vue
index 384f33e0983..30be2e68e76 100644
--- a/app/assets/javascripts/diffs/components/tree_list.vue
+++ b/app/assets/javascripts/diffs/components/tree_list.vue
@@ -1,6 +1,7 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import { GlTooltipDirective } from '@gitlab/ui';
+import { s__, sprintf } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import FileRow from '~/vue_shared/components/file_row.vue';
import FileRowStats from './file_row_stats.vue';
@@ -57,6 +58,9 @@ export default {
this.search = '';
},
},
+ searchPlaceholder: sprintf(s__('MergeRequest|Filter files or search with %{modifier_key}+p'), {
+ modifier_key: /Mac/i.test(navigator.userAgent) ? 'cmd' : 'ctrl',
+ }),
};
</script>
@@ -65,10 +69,13 @@ export default {
<div class="append-bottom-8 position-relative tree-list-search d-flex">
<div class="flex-fill d-flex">
<icon name="search" class="position-absolute tree-list-icon" />
+ <label for="diff-tree-search" class="sr-only">{{ $options.searchPlaceholder }}</label>
<input
+ id="diff-tree-search"
v-model="search"
- :placeholder="s__('MergeRequest|Filter files')"
+ :placeholder="$options.searchPlaceholder"
type="search"
+ name="diff-tree-search"
class="form-control"
/>
<button
diff --git a/app/assets/javascripts/diffs/constants.js b/app/assets/javascripts/diffs/constants.js
index 4feb73cfef2..d84e1af11f3 100644
--- a/app/assets/javascripts/diffs/constants.js
+++ b/app/assets/javascripts/diffs/constants.js
@@ -50,3 +50,10 @@ export const LEFT_LINE_KEY = 'left';
export const CENTERED_LIMITED_CONTAINER_CLASSES =
'container-limited limit-container-width mx-lg-auto px-3';
+
+export const MAX_RENDERING_DIFF_LINES = 500;
+export const MAX_RENDERING_BULK_ROWS = 30;
+export const MIN_RENDERING_MS = 2;
+export const START_RENDERING_INDEX = 200;
+export const INLINE_DIFF_LINES_KEY = 'highlighted_diff_lines';
+export const PARALLEL_DIFF_LINES_KEY = 'parallel_diff_lines';
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index b58ae0d248c..479afc50113 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -7,7 +7,12 @@ import { handleLocationHash, historyPushState, scrollToElement } from '~/lib/uti
import { mergeUrlParams, getLocationHash } from '~/lib/utils/url_utility';
import TreeWorker from '../workers/tree_worker';
import eventHub from '../../notes/event_hub';
-import { getDiffPositionByLineCode, getNoteFormData } from './utils';
+import {
+ getDiffPositionByLineCode,
+ getNoteFormData,
+ convertExpandLines,
+ idleCallback,
+} from './utils';
import * as types from './mutation_types';
import {
PARALLEL_DIFF_VIEW_TYPE,
@@ -17,6 +22,16 @@ import {
TREE_LIST_STORAGE_KEY,
WHITESPACE_STORAGE_KEY,
TREE_LIST_WIDTH_STORAGE_KEY,
+ OLD_LINE_KEY,
+ NEW_LINE_KEY,
+ TYPE_KEY,
+ LEFT_LINE_KEY,
+ MAX_RENDERING_DIFF_LINES,
+ MAX_RENDERING_BULK_ROWS,
+ MIN_RENDERING_MS,
+ START_RENDERING_INDEX,
+ INLINE_DIFF_LINES_KEY,
+ PARALLEL_DIFF_LINES_KEY,
} from '../constants';
import { diffViewerModes } from '~/ide/constants';
@@ -37,7 +52,7 @@ export const fetchDiffFiles = ({ state, commit }) => {
});
return axios
- .get(state.endpoint, { params: { w: state.showWhitespace ? null : '1' } })
+ .get(mergeUrlParams({ w: state.showWhitespace ? '0' : '1' }, state.endpoint))
.then(res => {
commit(types.SET_LOADING, false);
commit(types.SET_MERGE_REQUEST_DIFFS, res.data.merge_request_diffs || []);
@@ -110,7 +125,8 @@ export const startRenderDiffsQueue = ({ state, commit }) => {
new Promise(resolve => {
const nextFile = state.diffFiles.find(
file =>
- !file.renderIt && (!file.viewer.collapsed || !file.viewer.name === diffViewerModes.text),
+ !file.renderIt &&
+ (file.viewer && (!file.viewer.collapsed || !file.viewer.name === diffViewerModes.text)),
);
if (nextFile) {
@@ -195,11 +211,12 @@ export const scrollToLineIfNeededParallel = (_, line) => {
}
};
-export const loadCollapsedDiff = ({ commit, getters }, file) =>
+export const loadCollapsedDiff = ({ commit, getters, state }, file) =>
axios
.get(file.load_collapsed_diff_url, {
params: {
commit_id: getters.commitId,
+ w: state.showWhitespace ? '0' : '1',
},
})
.then(res => {
@@ -300,8 +317,10 @@ export const setShowWhitespace = ({ commit }, { showWhitespace, pushState = fals
localStorage.setItem(WHITESPACE_STORAGE_KEY, showWhitespace);
if (pushState) {
- historyPushState(showWhitespace ? '?w=0' : '?w=1');
+ historyPushState(mergeUrlParams({ w: showWhitespace ? '0' : '1' }, window.location.href));
}
+
+ eventHub.$emit('refetchDiffData');
};
export const toggleFileFinder = ({ commit }, visible) => {
@@ -313,13 +332,98 @@ export const cacheTreeListWidth = (_, size) => {
};
export const requestFullDiff = ({ commit }, filePath) => commit(types.REQUEST_FULL_DIFF, filePath);
-export const receiveFullDiffSucess = ({ commit }, { filePath, data }) =>
- commit(types.RECEIVE_FULL_DIFF_SUCCESS, { filePath, data });
+export const receiveFullDiffSucess = ({ commit }, { filePath }) =>
+ commit(types.RECEIVE_FULL_DIFF_SUCCESS, { filePath });
export const receiveFullDiffError = ({ commit }, filePath) => {
commit(types.RECEIVE_FULL_DIFF_ERROR, filePath);
createFlash(s__('MergeRequest|Error loading full diff. Please try again.'));
};
+export const setExpandedDiffLines = ({ commit, state }, { file, data }) => {
+ const expandedDiffLines = {
+ highlighted_diff_lines: convertExpandLines({
+ diffLines: file.highlighted_diff_lines,
+ typeKey: TYPE_KEY,
+ oldLineKey: OLD_LINE_KEY,
+ newLineKey: NEW_LINE_KEY,
+ data,
+ mapLine: ({ line, oldLine, newLine }) =>
+ Object.assign(line, {
+ old_line: oldLine,
+ new_line: newLine,
+ line_code: `${file.file_hash}_${oldLine}_${newLine}`,
+ }),
+ }),
+ parallel_diff_lines: convertExpandLines({
+ diffLines: file.parallel_diff_lines,
+ typeKey: [LEFT_LINE_KEY, TYPE_KEY],
+ oldLineKey: [LEFT_LINE_KEY, OLD_LINE_KEY],
+ newLineKey: [LEFT_LINE_KEY, NEW_LINE_KEY],
+ data,
+ mapLine: ({ line, oldLine, newLine }) => ({
+ left: {
+ ...line,
+ old_line: oldLine,
+ line_code: `${file.file_hash}_${oldLine}_${newLine}`,
+ },
+ right: {
+ ...line,
+ new_line: newLine,
+ line_code: `${file.file_hash}_${newLine}_${oldLine}`,
+ },
+ }),
+ }),
+ };
+ const currentDiffLinesKey =
+ state.diffViewType === INLINE_DIFF_VIEW_TYPE ? INLINE_DIFF_LINES_KEY : PARALLEL_DIFF_LINES_KEY;
+ const hiddenDiffLinesKey =
+ state.diffViewType === INLINE_DIFF_VIEW_TYPE ? PARALLEL_DIFF_LINES_KEY : INLINE_DIFF_LINES_KEY;
+
+ commit(types.SET_HIDDEN_VIEW_DIFF_FILE_LINES, {
+ filePath: file.file_path,
+ lines: expandedDiffLines[hiddenDiffLinesKey],
+ });
+
+ if (expandedDiffLines[currentDiffLinesKey].length > MAX_RENDERING_DIFF_LINES) {
+ let index = START_RENDERING_INDEX;
+ commit(types.SET_CURRENT_VIEW_DIFF_FILE_LINES, {
+ filePath: file.file_path,
+ lines: expandedDiffLines[currentDiffLinesKey].slice(0, index),
+ });
+ commit(types.TOGGLE_DIFF_FILE_RENDERING_MORE, file.file_path);
+
+ const idleCb = t => {
+ const startIndex = index;
+
+ while (
+ t.timeRemaining() >= MIN_RENDERING_MS &&
+ index !== expandedDiffLines[currentDiffLinesKey].length &&
+ index - startIndex !== MAX_RENDERING_BULK_ROWS
+ ) {
+ const line = expandedDiffLines[currentDiffLinesKey][index];
+
+ if (line) {
+ commit(types.ADD_CURRENT_VIEW_DIFF_FILE_LINES, { filePath: file.file_path, line });
+ index += 1;
+ }
+ }
+
+ if (index !== expandedDiffLines[currentDiffLinesKey].length) {
+ idleCallback(idleCb);
+ } else {
+ commit(types.TOGGLE_DIFF_FILE_RENDERING_MORE, file.file_path);
+ }
+ };
+
+ idleCallback(idleCb);
+ } else {
+ commit(types.SET_CURRENT_VIEW_DIFF_FILE_LINES, {
+ filePath: file.file_path,
+ lines: expandedDiffLines[currentDiffLinesKey],
+ });
+ }
+};
+
export const fetchFullDiff = ({ dispatch }, file) =>
axios
.get(file.context_lines_path, {
@@ -328,8 +432,10 @@ export const fetchFullDiff = ({ dispatch }, file) =>
from_merge_request: true,
},
})
- .then(({ data }) => dispatch('receiveFullDiffSucess', { filePath: file.file_path, data }))
- .then(() => scrollToElement(`#${file.file_hash}`))
+ .then(({ data }) => {
+ dispatch('receiveFullDiffSucess', { filePath: file.file_path });
+ dispatch('setExpandedDiffLines', { file, data });
+ })
.catch(() => dispatch('receiveFullDiffError', file.file_path));
export const toggleFullDiff = ({ dispatch, getters, state }, filePath) => {
@@ -340,7 +446,6 @@ export const toggleFullDiff = ({ dispatch, getters, state }, filePath) => {
if (file.isShowingFullFile) {
dispatch('loadCollapsedDiff', file)
.then(() => dispatch('assignDiscussionsToDiff', getters.getDiffFileDiscussions(file)))
- .then(() => scrollToElement(`#${file.file_hash}`))
.catch(() => dispatch('receiveFullDiffError', filePath));
} else {
dispatch('fetchFullDiff', file);
diff --git a/app/assets/javascripts/diffs/store/mutation_types.js b/app/assets/javascripts/diffs/store/mutation_types.js
index adf56eba3f8..6bb24c97139 100644
--- a/app/assets/javascripts/diffs/store/mutation_types.js
+++ b/app/assets/javascripts/diffs/store/mutation_types.js
@@ -28,3 +28,8 @@ export const REQUEST_FULL_DIFF = 'REQUEST_FULL_DIFF';
export const RECEIVE_FULL_DIFF_SUCCESS = 'RECEIVE_FULL_DIFF_SUCCESS';
export const RECEIVE_FULL_DIFF_ERROR = 'RECEIVE_FULL_DIFF_ERROR';
export const SET_FILE_COLLAPSED = 'SET_FILE_COLLAPSED';
+
+export const SET_HIDDEN_VIEW_DIFF_FILE_LINES = 'SET_HIDDEN_VIEW_DIFF_FILE_LINES';
+export const SET_CURRENT_VIEW_DIFF_FILE_LINES = 'SET_CURRENT_VIEW_DIFF_FILE_LINES';
+export const ADD_CURRENT_VIEW_DIFF_FILE_LINES = 'ADD_CURRENT_VIEW_DIFF_FILE_LINES';
+export const TOGGLE_DIFF_FILE_RENDERING_MORE = 'TOGGLE_DIFF_FILE_RENDERING_MORE';
diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js
index 572fbfb5be4..67bc1724738 100644
--- a/app/assets/javascripts/diffs/store/mutations.js
+++ b/app/assets/javascripts/diffs/store/mutations.js
@@ -6,10 +6,8 @@ import {
addContextLines,
prepareDiffData,
isDiscussionApplicableToLine,
- convertExpandLines,
} from './utils';
import * as types from './mutation_types';
-import { OLD_LINE_KEY, NEW_LINE_KEY, TYPE_KEY, LEFT_LINE_KEY } from '../constants';
export default {
[types.SET_BASE_CONFIG](state, options) {
@@ -265,45 +263,11 @@ export default {
file.isLoadingFullFile = false;
},
- [types.RECEIVE_FULL_DIFF_SUCCESS](state, { filePath, data }) {
+ [types.RECEIVE_FULL_DIFF_SUCCESS](state, { filePath }) {
const file = findDiffFile(state.diffFiles, filePath, 'file_path');
file.isShowingFullFile = true;
file.isLoadingFullFile = false;
-
- file.highlighted_diff_lines = convertExpandLines({
- diffLines: file.highlighted_diff_lines,
- typeKey: [TYPE_KEY],
- oldLineKey: [OLD_LINE_KEY],
- newLineKey: [NEW_LINE_KEY],
- data,
- mapLine: ({ line, oldLine, newLine }) => ({
- ...line,
- old_line: oldLine,
- new_line: newLine,
- line_code: `${file.file_hash}_${oldLine}_${newLine}`,
- }),
- });
-
- file.parallel_diff_lines = convertExpandLines({
- diffLines: file.parallel_diff_lines,
- typeKey: [LEFT_LINE_KEY, TYPE_KEY],
- oldLineKey: [LEFT_LINE_KEY, OLD_LINE_KEY],
- newLineKey: [LEFT_LINE_KEY, NEW_LINE_KEY],
- data,
- mapLine: ({ line, oldLine, newLine }) => ({
- left: {
- ...line,
- old_line: oldLine,
- line_code: `${file.file_hash}_${oldLine}_${newLine}`,
- },
- right: {
- ...line,
- new_line: newLine,
- line_code: `${file.file_hash}_${newLine}_${oldLine}`,
- },
- }),
- });
},
[types.SET_FILE_COLLAPSED](state, { filePath, collapsed }) {
const file = state.diffFiles.find(f => f.file_path === filePath);
@@ -312,4 +276,30 @@ export default {
file.viewer.collapsed = collapsed;
}
},
+ [types.SET_HIDDEN_VIEW_DIFF_FILE_LINES](state, { filePath, lines }) {
+ const file = state.diffFiles.find(f => f.file_path === filePath);
+ const hiddenDiffLinesKey =
+ state.diffViewType === 'inline' ? 'parallel_diff_lines' : 'highlighted_diff_lines';
+
+ file[hiddenDiffLinesKey] = lines;
+ },
+ [types.SET_CURRENT_VIEW_DIFF_FILE_LINES](state, { filePath, lines }) {
+ const file = state.diffFiles.find(f => f.file_path === filePath);
+ const currentDiffLinesKey =
+ state.diffViewType === 'inline' ? 'highlighted_diff_lines' : 'parallel_diff_lines';
+
+ file[currentDiffLinesKey] = lines;
+ },
+ [types.ADD_CURRENT_VIEW_DIFF_FILE_LINES](state, { filePath, line }) {
+ const file = state.diffFiles.find(f => f.file_path === filePath);
+ const currentDiffLinesKey =
+ state.diffViewType === 'inline' ? 'highlighted_diff_lines' : 'parallel_diff_lines';
+
+ file[currentDiffLinesKey].push(line);
+ },
+ [types.TOGGLE_DIFF_FILE_RENDERING_MORE](state, filePath) {
+ const file = state.diffFiles.find(f => f.file_path === filePath);
+
+ file.renderingLines = !file.renderingLines;
+ },
};
diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js
index 27a79369a24..71956255eef 100644
--- a/app/assets/javascripts/diffs/store/utils.js
+++ b/app/assets/javascripts/diffs/store/utils.js
@@ -253,6 +253,7 @@ export function prepareDiffData(diffData) {
isShowingFullFile: false,
isLoadingFullFile: false,
discussions: [],
+ renderingLines: false,
});
}
}
@@ -423,27 +424,33 @@ export const convertExpandLines = ({
mapLine,
}) => {
const dataLength = data.length;
+ const lines = [];
+
+ for (let i = 0, diffLinesLength = diffLines.length; i < diffLinesLength; i += 1) {
+ const line = diffLines[i];
- return diffLines.reduce((acc, line, i) => {
if (_.property(typeKey)(line) === 'match') {
const beforeLine = diffLines[i - 1];
const afterLine = diffLines[i + 1];
- const beforeLineIndex = _.property(newLineKey)(beforeLine) || 0;
- const afterLineIndex = _.property(newLineKey)(afterLine) - 1 || dataLength;
-
- acc.push(
- ...data.slice(beforeLineIndex, afterLineIndex).map((l, index) => ({
- ...mapLine({
- line: { ...l, hasForm: false, discussions: [] },
+ const newLineProperty = _.property(newLineKey);
+ const beforeLineIndex = newLineProperty(beforeLine) || 0;
+ const afterLineIndex = newLineProperty(afterLine) - 1 || dataLength;
+
+ lines.push(
+ ...data.slice(beforeLineIndex, afterLineIndex).map((l, index) =>
+ mapLine({
+ line: Object.assign(l, { hasForm: false, discussions: [] }),
oldLine: (_.property(oldLineKey)(beforeLine) || 0) + index + 1,
- newLine: (_.property(newLineKey)(beforeLine) || 0) + index + 1,
+ newLine: (newLineProperty(beforeLine) || 0) + index + 1,
}),
- })),
+ ),
);
} else {
- acc.push(line);
+ lines.push(line);
}
+ }
- return acc;
- }, []);
+ return lines;
};
+
+export const idleCallback = cb => requestIdleCallback(cb);
diff --git a/app/assets/javascripts/diffs/workers/tree_worker.js b/app/assets/javascripts/diffs/workers/tree_worker.js
index 534d737c77e..415c463fd19 100644
--- a/app/assets/javascripts/diffs/workers/tree_worker.js
+++ b/app/assets/javascripts/diffs/workers/tree_worker.js
@@ -4,6 +4,11 @@ import { generateTreeList } from '../store/utils';
// eslint-disable-next-line no-restricted-globals
self.addEventListener('message', e => {
const { data } = e;
+
+ if (data === undefined) {
+ return;
+ }
+
const { treeEntries, tree } = generateTreeList(data);
// eslint-disable-next-line no-restricted-globals
diff --git a/app/assets/javascripts/dirty_submit/dirty_submit_form.js b/app/assets/javascripts/dirty_submit/dirty_submit_form.js
index 765969daa32..0fcaec9531c 100644
--- a/app/assets/javascripts/dirty_submit/dirty_submit_form.js
+++ b/app/assets/javascripts/dirty_submit/dirty_submit_form.js
@@ -21,10 +21,15 @@ class DirtySubmitForm {
}
registerListeners() {
- const throttledUpdateDirtyInput = _.throttle(
- event => this.updateDirtyInput(event),
- DirtySubmitForm.THROTTLE_DURATION,
+ const getThrottledHandlerForInput = _.memoize(() =>
+ _.throttle(event => this.updateDirtyInput(event), DirtySubmitForm.THROTTLE_DURATION),
);
+
+ const throttledUpdateDirtyInput = event => {
+ const throttledHandler = getThrottledHandlerForInput(event.target.name);
+ throttledHandler(event);
+ };
+
this.form.addEventListener('input', throttledUpdateDirtyInput);
this.form.addEventListener('change', throttledUpdateDirtyInput);
$(this.form).on('change.select2', throttledUpdateDirtyInput);
diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js
index 9987fbcb6a7..0ff26445a6a 100644
--- a/app/assets/javascripts/dropzone_input.js
+++ b/app/assets/javascripts/dropzone_input.js
@@ -4,6 +4,7 @@ import _ from 'underscore';
import './behaviors/preview_markdown';
import csrf from './lib/utils/csrf';
import axios from './lib/utils/axios_utils';
+import { n__, __ } from '~/locale';
Dropzone.autoDiscover = false;
@@ -90,7 +91,7 @@ export default function dropzoneInput(form) {
if (!processingFileCount) $attachButton.removeClass('hide');
addFileToForm(response.link.url);
},
- error: (file, errorMessage = 'Attaching the file failed.', xhr) => {
+ error: (file, errorMessage = __('Attaching the file failed.'), xhr) => {
// If 'error' event is fired by dropzone, the second parameter is error message.
// If the 'errorMessage' parameter is empty, the default error message is set.
// If the 'error' event is fired by backend (xhr) error response, the third parameter is
@@ -273,19 +274,11 @@ export default function dropzoneInput(form) {
};
updateAttachingMessage = (files, messageContainer) => {
- let attachingMessage;
const filesCount = files.filter(file => file.status === 'uploading' || file.status === 'queued')
.length;
+ const attachingMessage = n__('Attaching a file', 'Attaching %d files', filesCount);
- // Dinamycally change uploading files text depending on files number in
- // dropzone files queue.
- if (filesCount > 1) {
- attachingMessage = `Attaching ${filesCount} files -`;
- } else {
- attachingMessage = 'Attaching a file -';
- }
-
- messageContainer.text(attachingMessage);
+ messageContainer.text(`${attachingMessage} -`);
};
form.find('.markdown-selector').click(function onMarkdownClick(e) {
diff --git a/app/assets/javascripts/due_date_select.js b/app/assets/javascripts/due_date_select.js
index cb1b1173190..3c650397a19 100644
--- a/app/assets/javascripts/due_date_select.js
+++ b/app/assets/javascripts/due_date_select.js
@@ -104,7 +104,7 @@ class DueDateSelect {
const dateObj = new Date(dateArray[0], dateArray[1] - 1, dateArray[2]);
this.displayedDate = dateFormat(dateObj, 'mmm d, yyyy');
} else {
- this.displayedDate = 'No due date';
+ this.displayedDate = __('None');
}
}
@@ -132,7 +132,7 @@ class DueDateSelect {
submitSelectedDate(isDropdown) {
const selectedDateValue = this.datePayload[this.abilityName].due_date;
- const hasDueDate = this.displayedDate !== 'No due date';
+ const hasDueDate = this.displayedDate !== __('None');
const displayedDateStyle = hasDueDate ? 'bold' : 'no-value';
this.$loading.removeClass('hidden').fadeIn();
diff --git a/app/assets/javascripts/emoji/no_emoji_validator.js b/app/assets/javascripts/emoji/no_emoji_validator.js
index 0fd4dd74953..384d62a133a 100644
--- a/app/assets/javascripts/emoji/no_emoji_validator.js
+++ b/app/assets/javascripts/emoji/no_emoji_validator.js
@@ -1,10 +1,11 @@
import { __ } from '~/locale';
import emojiRegex from 'emoji-regex';
+import InputValidator from '../validators/input_validator';
-const invalidInputClass = 'gl-field-error-outline';
-
-export default class NoEmojiValidator {
+export default class NoEmojiValidator extends InputValidator {
constructor(opts = {}) {
+ super();
+
const container = opts.container || '';
this.noEmojiEmelents = document.querySelectorAll(`${container} .js-block-emoji`);
@@ -19,45 +20,14 @@ export default class NoEmojiValidator {
const { value } = this.inputDomElement;
+ this.errorMessage = __('Invalid input, please avoid emojis');
+
this.validatePattern(value);
this.setValidationStateAndMessage();
}
validatePattern(value) {
const pattern = emojiRegex();
- this.hasEmojis = new RegExp(pattern).test(value);
-
- if (this.hasEmojis) {
- this.inputDomElement.setCustomValidity(__('Invalid input, please avoid emojis'));
- } else {
- this.inputDomElement.setCustomValidity('');
- }
- }
-
- setValidationStateAndMessage() {
- if (!this.inputDomElement.checkValidity()) {
- this.setInvalidState();
- } else {
- this.clearFieldValidationState();
- }
- }
-
- clearFieldValidationState() {
- this.inputDomElement.classList.remove(invalidInputClass);
- this.inputErrorMessage.classList.add('hide');
- }
-
- setInvalidState() {
- this.inputDomElement.classList.add(invalidInputClass);
- this.setErrorMessage();
- }
-
- setErrorMessage() {
- if (this.hasEmojis) {
- this.inputErrorMessage.innerHTML = this.inputDomElement.validationMessage;
- } else {
- this.inputErrorMessage.innerHTML = this.inputDomElement.title;
- }
- this.inputErrorMessage.classList.remove('hide');
+ this.invalidInput = new RegExp(pattern).test(value);
}
}
diff --git a/app/assets/javascripts/environments/components/container.vue b/app/assets/javascripts/environments/components/container.vue
index be80661223c..f8a637138ad 100644
--- a/app/assets/javascripts/environments/components/container.vue
+++ b/app/assets/javascripts/environments/components/container.vue
@@ -1,6 +1,6 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
-import TablePagination from '~/vue_shared/components/table_pagination.vue';
+import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
import containerMixin from 'ee_else_ce/environments/mixins/container_mixin';
import EnvironmentTable from '../components/environments_table.vue';
diff --git a/app/assets/javascripts/environments/mixins/environments_mixin.js b/app/assets/javascripts/environments/mixins/environments_mixin.js
index a5812b173dc..31347d95a25 100644
--- a/app/assets/javascripts/environments/mixins/environments_mixin.js
+++ b/app/assets/javascripts/environments/mixins/environments_mixin.js
@@ -11,7 +11,7 @@ import Flash from '../../flash';
import eventHub from '../event_hub';
import EnvironmentsService from '../services/environments_service';
-import tablePagination from '../../vue_shared/components/table_pagination.vue';
+import tablePagination from '../../vue_shared/components/pagination/table_pagination.vue';
import environmentTable from '../components/environments_table.vue';
import tabs from '../../vue_shared/components/navigation_tabs.vue';
import container from '../components/container.vue';
diff --git a/app/assets/javascripts/error_tracking_settings/store/getters.js b/app/assets/javascripts/error_tracking_settings/store/getters.js
index a008b181907..d77e5f15469 100644
--- a/app/assets/javascripts/error_tracking_settings/store/getters.js
+++ b/app/assets/javascripts/error_tracking_settings/store/getters.js
@@ -2,10 +2,10 @@ import _ from 'underscore';
import { __, s__, sprintf } from '~/locale';
import { getDisplayName } from '../utils';
-export const hasProjects = state => !!state.projects && state.projects.length > 0;
+export const hasProjects = state => Boolean(state.projects) && state.projects.length > 0;
export const isProjectInvalid = (state, getters) =>
- !!state.selectedProject &&
+ Boolean(state.selectedProject) &&
getters.hasProjects &&
!state.projects.some(project => _.isMatch(state.selectedProject, project));
diff --git a/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js b/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js
index 0b24d9fc920..e020628a473 100644
--- a/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js
+++ b/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js
@@ -1,3 +1,5 @@
+import { __ } from '~/locale';
+
export default IssuableTokenKeys => {
const wipToken = {
key: 'wip',
@@ -5,7 +7,7 @@ export default IssuableTokenKeys => {
param: '',
symbol: '',
icon: 'admin',
- tag: 'Yes or No',
+ tag: __('Yes or No'),
lowercaseValueOnSubmit: true,
uppercaseTokenName: true,
capitalizeTokenValue: true,
diff --git a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
index be867a3838d..891086b4142 100644
--- a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
+++ b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
@@ -8,9 +8,19 @@ import DropdownUtils from './dropdown_utils';
import { mergeUrlParams } from '../lib/utils/url_utility';
export default class AvailableDropdownMappings {
- constructor(container, baseEndpoint, groupsOnly, includeAncestorGroups, includeDescendantGroups) {
+ constructor(
+ container,
+ baseEndpoint,
+ labelsEndpoint,
+ milestonesEndpoint,
+ groupsOnly,
+ includeAncestorGroups,
+ includeDescendantGroups,
+ ) {
this.container = container;
this.baseEndpoint = baseEndpoint;
+ this.labelsEndpoint = labelsEndpoint;
+ this.milestonesEndpoint = milestonesEndpoint;
this.groupsOnly = groupsOnly;
this.includeAncestorGroups = includeAncestorGroups;
this.includeDescendantGroups = includeDescendantGroups;
@@ -117,11 +127,11 @@ export default class AvailableDropdownMappings {
}
getMilestoneEndpoint() {
- return `${this.baseEndpoint}/milestones.json`;
+ return `${this.milestonesEndpoint}.json`;
}
getLabelsEndpoint() {
- let endpoint = `${this.baseEndpoint}/labels.json?`;
+ let endpoint = `${this.labelsEndpoint}.json?`;
if (this.groupsOnly) {
endpoint = `${endpoint}only_group_labels=true&`;
diff --git a/app/assets/javascripts/filtered_search/dropdown_emoji.js b/app/assets/javascripts/filtered_search/dropdown_emoji.js
index d9a4d06b549..dad188f6f98 100644
--- a/app/assets/javascripts/filtered_search/dropdown_emoji.js
+++ b/app/assets/javascripts/filtered_search/dropdown_emoji.js
@@ -3,6 +3,7 @@ import Ajax from '../droplab/plugins/ajax';
import Filter from '../droplab/plugins/filter';
import FilteredSearchDropdown from './filtered_search_dropdown';
import DropdownUtils from './dropdown_utils';
+import { __ } from '~/locale';
export default class DropdownEmoji extends FilteredSearchDropdown {
constructor(options = {}) {
@@ -14,7 +15,7 @@ export default class DropdownEmoji extends FilteredSearchDropdown {
loadingTemplate: this.loadingTemplate,
onError() {
/* eslint-disable no-new */
- new Flash('An error occurred fetching the dropdown data.');
+ new Flash(__('An error occurred fetching the dropdown data.'));
/* eslint-enable no-new */
},
},
diff --git a/app/assets/javascripts/filtered_search/dropdown_non_user.js b/app/assets/javascripts/filtered_search/dropdown_non_user.js
index 0264f934914..a2312de289d 100644
--- a/app/assets/javascripts/filtered_search/dropdown_non_user.js
+++ b/app/assets/javascripts/filtered_search/dropdown_non_user.js
@@ -3,6 +3,7 @@ import Ajax from '../droplab/plugins/ajax';
import Filter from '../droplab/plugins/filter';
import FilteredSearchDropdown from './filtered_search_dropdown';
import DropdownUtils from './dropdown_utils';
+import { __ } from '~/locale';
export default class DropdownNonUser extends FilteredSearchDropdown {
constructor(options = {}) {
@@ -17,7 +18,7 @@ export default class DropdownNonUser extends FilteredSearchDropdown {
preprocessing,
onError() {
/* eslint-disable no-new */
- new Flash('An error occurred fetching the dropdown data.');
+ new Flash(__('An error occurred fetching the dropdown data.'));
/* eslint-enable no-new */
},
},
diff --git a/app/assets/javascripts/filtered_search/dropdown_user.js b/app/assets/javascripts/filtered_search/dropdown_user.js
index f1e7be6bde1..a65c0012b4d 100644
--- a/app/assets/javascripts/filtered_search/dropdown_user.js
+++ b/app/assets/javascripts/filtered_search/dropdown_user.js
@@ -18,6 +18,7 @@ export default class DropdownUser extends DropdownAjaxFilter {
group_id: this.getGroupId(),
project_id: this.getProjectId(),
current_user: true,
+ ...this.projectOrGroupId(),
},
onLoadingFinished: () => {
this.hideCurrentUser();
@@ -36,4 +37,17 @@ export default class DropdownUser extends DropdownAjaxFilter {
getProjectId() {
return this.input.getAttribute('data-project-id');
}
+
+ projectOrGroupId() {
+ const projectId = this.getProjectId();
+ const groupId = this.getGroupId();
+ if (groupId) {
+ return {
+ group_id: groupId,
+ };
+ }
+ return {
+ project_id: projectId,
+ };
+ }
}
diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
index cb0a84b490b..1cbfd7f9bb9 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
@@ -9,6 +9,8 @@ import FilteredSearchVisualTokens from './filtered_search_visual_tokens';
export default class FilteredSearchDropdownManager {
constructor({
baseEndpoint = '',
+ labelsEndpoint = '',
+ milestonesEndpoint = '',
tokenizer,
page,
isGroup,
@@ -18,6 +20,8 @@ export default class FilteredSearchDropdownManager {
}) {
this.container = FilteredSearchContainer.container;
this.baseEndpoint = baseEndpoint.replace(/\/$/, '');
+ this.labelsEndpoint = labelsEndpoint.replace(/\/$/, '');
+ this.milestonesEndpoint = milestonesEndpoint.replace(/\/$/, '');
this.tokenizer = tokenizer;
this.filteredSearchTokenKeys = filteredSearchTokenKeys || FilteredSearchTokenKeys;
this.filteredSearchInput = this.container.querySelector('.filtered-search');
@@ -48,6 +52,8 @@ export default class FilteredSearchDropdownManager {
const availableMappings = new AvailableDropdownMappings(
this.container,
this.baseEndpoint,
+ this.labelsEndpoint,
+ this.milestonesEndpoint,
this.groupsOnly,
this.includeAncestorGroups,
this.includeDescendantGroups,
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js
index efd03ec952f..450e0725f2e 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js
@@ -14,6 +14,7 @@ import FilteredSearchTokenizer from './filtered_search_tokenizer';
import FilteredSearchDropdownManager from './filtered_search_dropdown_manager';
import FilteredSearchVisualTokens from './filtered_search_visual_tokens';
import DropdownUtils from './dropdown_utils';
+import { __ } from '~/locale';
export default class FilteredSearchManager {
constructor({
@@ -64,7 +65,7 @@ export default class FilteredSearchManager {
.catch(error => {
if (error.name === 'RecentSearchesServiceError') return undefined;
// eslint-disable-next-line no-new
- new Flash('An error occurred while parsing recent searches');
+ new Flash(__('An error occurred while parsing recent searches'));
// Gracefully fail to empty array
return [];
})
@@ -85,6 +86,8 @@ export default class FilteredSearchManager {
this.tokenizer = FilteredSearchTokenizer;
this.dropdownManager = new FilteredSearchDropdownManager({
baseEndpoint: this.filteredSearchInput.getAttribute('data-base-endpoint') || '',
+ labelsEndpoint: this.filteredSearchInput.getAttribute('data-labels-endpoint') || '',
+ milestonesEndpoint: this.filteredSearchInput.getAttribute('data-milestones-endpoint') || '',
tokenizer: this.tokenizer,
page: this.page,
isGroup: this.isGroup,
@@ -340,7 +343,7 @@ export default class FilteredSearchManager {
handleInputPlaceholder() {
const query = DropdownUtils.getSearchQuery();
- const placeholder = 'Search or filter results...';
+ const placeholder = __('Search or filter results...');
const currentPlaceholder = this.filteredSearchInput.placeholder;
if (query.length === 0 && currentPlaceholder !== placeholder) {
diff --git a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
index 11ed85504ec..0a9579bf491 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
@@ -1,3 +1,5 @@
+import { __ } from '~/locale';
+
export default class FilteredSearchTokenKeys {
constructor(tokenKeys = [], alternativeTokenKeys = [], conditions = []) {
this.tokenKeys = tokenKeys;
@@ -79,7 +81,7 @@ export default class FilteredSearchTokenKeys {
param: '',
symbol: '',
icon: 'eye-slash',
- tag: 'Yes or No',
+ tag: __('Yes or No'),
lowercaseValueOnSubmit: true,
uppercaseTokenName: false,
capitalizeTokenValue: true,
diff --git a/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js b/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js
index fd61030eb13..6c3d9e33420 100644
--- a/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js
+++ b/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js
@@ -1,4 +1,5 @@
import FilteredSearchTokenKeys from './filtered_search_token_keys';
+import { __ } from '~/locale';
export const tokenKeys = [
{
@@ -60,52 +61,52 @@ export const conditions = [
{
url: 'assignee_id=None',
tokenKey: 'assignee',
- value: 'None',
+ value: __('None'),
},
{
url: 'assignee_id=Any',
tokenKey: 'assignee',
- value: 'Any',
+ value: __('Any'),
},
{
url: 'milestone_title=None',
tokenKey: 'milestone',
- value: 'None',
+ value: __('None'),
},
{
url: 'milestone_title=Any',
tokenKey: 'milestone',
- value: 'Any',
+ value: __('Any'),
},
{
url: 'milestone_title=%23upcoming',
tokenKey: 'milestone',
- value: 'Upcoming',
+ value: __('Upcoming'),
},
{
url: 'milestone_title=%23started',
tokenKey: 'milestone',
- value: 'Started',
+ value: __('Started'),
},
{
url: 'label_name[]=None',
tokenKey: 'label',
- value: 'None',
+ value: __('None'),
},
{
url: 'label_name[]=Any',
tokenKey: 'label',
- value: 'Any',
+ value: __('Any'),
},
{
url: 'my_reaction_emoji=None',
tokenKey: 'my-reaction',
- value: 'None',
+ value: __('None'),
},
{
url: 'my_reaction_emoji=Any',
tokenKey: 'my-reaction',
- value: 'Any',
+ value: __('Any'),
},
];
diff --git a/app/assets/javascripts/filtered_search/services/recent_searches_service_error.js b/app/assets/javascripts/filtered_search/services/recent_searches_service_error.js
index 5917b223d63..011b37e218d 100644
--- a/app/assets/javascripts/filtered_search/services/recent_searches_service_error.js
+++ b/app/assets/javascripts/filtered_search/services/recent_searches_service_error.js
@@ -1,7 +1,9 @@
+import { __ } from '~/locale';
+
class RecentSearchesServiceError {
constructor(message) {
this.name = 'RecentSearchesServiceError';
- this.message = message || 'Recent Searches Service is unavailable';
+ this.message = message || __('Recent Searches Service is unavailable');
}
}
diff --git a/app/assets/javascripts/filtered_search/visual_token_value.js b/app/assets/javascripts/filtered_search/visual_token_value.js
index a9d5ba8faa8..a54b445fb0a 100644
--- a/app/assets/javascripts/filtered_search/visual_token_value.js
+++ b/app/assets/javascripts/filtered_search/visual_token_value.js
@@ -5,6 +5,7 @@ import AjaxCache from '~/lib/utils/ajax_cache';
import DropdownUtils from '~/filtered_search/dropdown_utils';
import Flash from '~/flash';
import UsersCache from '~/lib/utils/users_cache';
+import { __ } from '~/locale';
export default class VisualTokenValue {
constructor(tokenValue, tokenType) {
@@ -55,13 +56,13 @@ export default class VisualTokenValue {
updateLabelTokenColor(tokenValueContainer) {
const { tokenValue } = this;
const filteredSearchInput = FilteredSearchContainer.container.querySelector('.filtered-search');
- const { baseEndpoint } = filteredSearchInput.dataset;
- const labelsEndpoint = FilteredSearchVisualTokens.getEndpointWithQueryParams(
- `${baseEndpoint}/labels.json`,
+ const { labelsEndpoint } = filteredSearchInput.dataset;
+ const labelsEndpointWithParams = FilteredSearchVisualTokens.getEndpointWithQueryParams(
+ `${labelsEndpoint}.json`,
filteredSearchInput.dataset.endpointQueryParams,
);
- return AjaxCache.retrieve(labelsEndpoint)
+ return AjaxCache.retrieve(labelsEndpointWithParams)
.then(labels => {
const matchingLabel = (labels || []).find(
label => `~${DropdownUtils.getEscapedText(label.title)}` === tokenValue,
@@ -77,7 +78,7 @@ export default class VisualTokenValue {
matchingLabel.text_color,
);
})
- .catch(() => new Flash('An error occurred while fetching label colors.'));
+ .catch(() => new Flash(__('An error occurred while fetching label colors.')));
}
static setTokenStyle(tokenValueContainer, backgroundColor, textColor) {
diff --git a/app/assets/javascripts/fly_out_nav.js b/app/assets/javascripts/fly_out_nav.js
index 2b6af9060d1..2566ed6b47c 100644
--- a/app/assets/javascripts/fly_out_nav.js
+++ b/app/assets/javascripts/fly_out_nav.js
@@ -1,4 +1,5 @@
import bp from './breakpoints';
+import { SIDEBAR_COLLAPSED_CLASS } from './contextual_sidebar';
const HIDE_INTERVAL_TIMEOUT = 300;
const IS_OVER_CLASS = 'is-over';
@@ -29,7 +30,7 @@ const setHeaderHeight = () => {
};
export const isSidebarCollapsed = () =>
- sidebar && sidebar.classList.contains('sidebar-collapsed-desktop');
+ sidebar && sidebar.classList.contains(SIDEBAR_COLLAPSED_CLASS);
export const canShowActiveSubItems = el => {
if (el.classList.contains('active') && !isSidebarCollapsed()) {
diff --git a/app/assets/javascripts/frequent_items/store/actions.js b/app/assets/javascripts/frequent_items/store/actions.js
index 3dd89a82a42..ba62ab67e50 100644
--- a/app/assets/javascripts/frequent_items/store/actions.js
+++ b/app/assets/javascripts/frequent_items/store/actions.js
@@ -51,7 +51,7 @@ export const fetchSearchedItems = ({ state, dispatch }, searchQuery) => {
const params = {
simple: true,
per_page: 20,
- membership: !!gon.current_user_id,
+ membership: Boolean(gon.current_user_id),
};
if (state.namespace === 'projects') {
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index c81e754df4c..0af9aabd8cf 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -1,4 +1,5 @@
import $ from 'jquery';
+import 'at.js';
import _ from 'underscore';
import glRegexp from './lib/utils/regexp';
import AjaxCache from './lib/utils/ajax_cache';
@@ -461,7 +462,10 @@ class GfmAutoComplete {
// We can ignore this for quick actions because they are processed
// before Markdown.
if (!this.setting.skipMarkdownCharacterTest) {
- withoutAt = withoutAt.replace(/([~\-_*`])/g, '\\$&');
+ withoutAt = withoutAt
+ .replace(/(~~|`|\*)/g, '\\$1')
+ .replace(/(\b)(_+)/g, '$1\\$2') // only escape underscores at the start
+ .replace(/(_+)(\b)/g, '\\$1$2'); // or end of words
}
return `${at}${withoutAt}`;
@@ -474,6 +478,16 @@ class GfmAutoComplete {
}
return null;
},
+ highlighter(li, query) {
+ // override default behaviour to escape dot character
+ // see https://github.com/ichord/At.js/pull/576
+ if (!query) {
+ return li;
+ }
+ const escapedQuery = query.replace(/[.+]/, '\\$&');
+ const regexp = new RegExp(`>\\s*([^<]*?)(${escapedQuery})([^<]*)\\s*<`, 'ig');
+ return li.replace(regexp, (str, $1, $2, $3) => `> ${$1}<strong>${$2}</strong>${$3} <`);
+ },
};
}
diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js
index 1c6b18c0e03..bdb50606a53 100644
--- a/app/assets/javascripts/gl_dropdown.js
+++ b/app/assets/javascripts/gl_dropdown.js
@@ -307,8 +307,8 @@ GitLabDropdown = (function() {
// Set Defaults
this.filterInput = this.options.filterInput || this.getElement(FILTER_INPUT);
this.noFilterInput = this.options.noFilterInput || this.getElement(NO_FILTER_INPUT);
- this.highlight = !!this.options.highlight;
- this.icon = !!this.options.icon;
+ this.highlight = Boolean(this.options.highlight);
+ this.icon = Boolean(this.options.icon);
this.filterInputBlur =
this.options.filterInputBlur != null ? this.options.filterInputBlur : true;
// If no input is passed create a default one
@@ -335,6 +335,10 @@ GitLabDropdown = (function() {
_this.fullData = data;
_this.parseData(_this.fullData);
_this.focusTextInput();
+
+ // Update dropdown position since remote data may have changed dropdown size
+ _this.dropdown.find('.dropdown-menu-toggle').dropdown('update');
+
if (
_this.options.filterable &&
_this.filter &&
@@ -561,6 +565,11 @@ GitLabDropdown = (function() {
!$target.data('isLink')
) {
e.stopPropagation();
+
+ // This prevents automatic scrolling to the top
+ if ($target.closest('a').length) {
+ return false;
+ }
}
return true;
@@ -702,6 +711,10 @@ GitLabDropdown = (function() {
}
html = document.createElement('li');
+ if (rowHidden) {
+ html.style.display = 'none';
+ }
+
if (data === 'divider' || data === 'separator') {
html.className = data;
return html;
diff --git a/app/assets/javascripts/gl_field_error.js b/app/assets/javascripts/gl_field_error.js
index a5b8c357e8a..04301c9ce12 100644
--- a/app/assets/javascripts/gl_field_error.js
+++ b/app/assets/javascripts/gl_field_error.js
@@ -1,4 +1,5 @@
import $ from 'jquery';
+import { __ } from '~/locale';
/**
* This class overrides the browser's validation error bubbles, displaying custom
@@ -61,7 +62,7 @@ export default class GlFieldError {
this.inputElement = $(input);
this.inputDomElement = this.inputElement.get(0);
this.form = formErrors;
- this.errorMessage = this.inputElement.attr('title') || 'This field is required.';
+ this.errorMessage = this.inputElement.attr('title') || __('This field is required.');
this.fieldErrorElement = $(`<p class='${errorMessageClass} hidden'>${this.errorMessage}</p>`);
this.state = {
diff --git a/app/assets/javascripts/gl_form.js b/app/assets/javascripts/gl_form.js
index f5e2e46237f..a66555838ba 100644
--- a/app/assets/javascripts/gl_form.js
+++ b/app/assets/javascripts/gl_form.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import autosize from 'autosize';
-import GfmAutoComplete, * as GFMConfig from './gfm_auto_complete';
+import GfmAutoComplete, { defaultAutocompleteConfig } from 'ee_else_ce/gfm_auto_complete';
import dropzoneInput from './dropzone_input';
import { addMarkdownListeners, removeMarkdownListeners } from './lib/utils/text_markdown';
@@ -8,12 +8,12 @@ export default class GLForm {
constructor(form, enableGFM = {}) {
this.form = form;
this.textarea = this.form.find('textarea.js-gfm-input');
- this.enableGFM = Object.assign({}, GFMConfig.defaultAutocompleteConfig, enableGFM);
+ this.enableGFM = Object.assign({}, defaultAutocompleteConfig, enableGFM);
// Disable autocomplete for keywords which do not have dataSources available
const dataSources = (gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources) || {};
Object.keys(this.enableGFM).forEach(item => {
if (item !== 'emojis') {
- this.enableGFM[item] = !!dataSources[item];
+ this.enableGFM[item] = Boolean(dataSources[item]);
}
});
// Before we start, we should clean up any previous data for this form
diff --git a/app/assets/javascripts/gpg_badges.js b/app/assets/javascripts/gpg_badges.js
index efba6fc1aff..96051b612b5 100644
--- a/app/assets/javascripts/gpg_badges.js
+++ b/app/assets/javascripts/gpg_badges.js
@@ -20,7 +20,7 @@ export default class GpgBadges {
const endpoint = tag.data('signaturesPath');
if (!endpoint) {
displayError();
- return Promise.reject(new Error('Missing commit signatures endpoint!'));
+ return Promise.reject(new Error(__('Missing commit signatures endpoint!')));
}
const params = parseQueryStringIntoObject(tag.serialize());
diff --git a/app/assets/javascripts/groups/transfer_dropdown.js b/app/assets/javascripts/groups/transfer_dropdown.js
index 26510fcdb2a..ce0c9256148 100644
--- a/app/assets/javascripts/groups/transfer_dropdown.js
+++ b/app/assets/javascripts/groups/transfer_dropdown.js
@@ -1,4 +1,5 @@
import $ from 'jquery';
+import { __ } from '~/locale';
export default class TransferDropdown {
constructor() {
@@ -13,7 +14,7 @@ export default class TransferDropdown {
}
buildDropdown() {
- const extraOptions = [{ id: '', text: 'No parent group' }, 'divider'];
+ const extraOptions = [{ id: '', text: __('No parent group') }, 'divider'];
this.groupDropdown.glDropdown({
selectable: true,
diff --git a/app/assets/javascripts/groups_select.js b/app/assets/javascripts/groups_select.js
index bdadbb1bb2a..a1263d1cdab 100644
--- a/app/assets/javascripts/groups_select.js
+++ b/app/assets/javascripts/groups_select.js
@@ -2,6 +2,7 @@ import $ from 'jquery';
import axios from './lib/utils/axios_utils';
import Api from './api';
import { normalizeHeaders } from './lib/utils/common_utils';
+import { __ } from '~/locale';
export default function groupsSelect() {
import(/* webpackChunkName: 'select2' */ 'select2/select2')
@@ -18,7 +19,7 @@ export default function groupsSelect() {
: Api.groupsPath;
$select.select2({
- placeholder: 'Search for a group',
+ placeholder: __('Search for a group'),
allowClear: $select.hasClass('allowClear'),
multiple: $select.hasClass('multiselect'),
minimumInputLength: 0,
diff --git a/app/assets/javascripts/ide/components/activity_bar.vue b/app/assets/javascripts/ide/components/activity_bar.vue
index 7c769ab7fa0..7b4e03be8eb 100644
--- a/app/assets/javascripts/ide/components/activity_bar.vue
+++ b/app/assets/javascripts/ide/components/activity_bar.vue
@@ -78,7 +78,7 @@ export default {
data-container="body"
data-placement="right"
type="button"
- class="ide-sidebar-link js-ide-commit-mode"
+ class="ide-sidebar-link js-ide-commit-mode qa-commit-mode-tab"
@click.prevent="changedActivityView($event, $options.activityBarViews.commit)"
>
<icon name="commit" />
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
index 1824a0f6147..685d8a6b245 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
@@ -1,23 +1,24 @@
<script>
import _ from 'underscore';
-import { mapActions, mapState, mapGetters, createNamespacedHelpers } from 'vuex';
+import { mapState, mapGetters, createNamespacedHelpers } from 'vuex';
import { sprintf, __ } from '~/locale';
import consts from '../../stores/modules/commit/constants';
import RadioGroup from './radio_group.vue';
+import NewMergeRequestOption from './new_merge_request_option.vue';
-const { mapState: mapCommitState, mapGetters: mapCommitGetters } = createNamespacedHelpers(
+const { mapState: mapCommitState, mapActions: mapCommitActions } = createNamespacedHelpers(
'commit',
);
export default {
components: {
RadioGroup,
+ NewMergeRequestOption,
},
computed: {
...mapState(['currentBranchId', 'changedFiles', 'stagedFiles']),
- ...mapCommitState(['commitAction', 'shouldCreateMR', 'shouldDisableNewMrOption']),
- ...mapGetters(['currentProject', 'currentBranch', 'currentMergeRequest']),
- ...mapCommitGetters(['shouldDisableNewMrOption']),
+ ...mapCommitState(['commitAction']),
+ ...mapGetters(['currentBranch']),
commitToCurrentBranchText() {
return sprintf(
__('Commit to %{branchName} branch'),
@@ -25,12 +26,12 @@ export default {
false,
);
},
- disableMergeRequestRadio() {
+ containsStagedChanges() {
return this.changedFiles.length > 0 && this.stagedFiles.length > 0;
},
},
watch: {
- disableMergeRequestRadio() {
+ containsStagedChanges() {
this.updateSelectedCommitAction();
},
},
@@ -38,11 +39,11 @@ export default {
this.updateSelectedCommitAction();
},
methods: {
- ...mapActions('commit', ['updateCommitAction', 'toggleShouldCreateMR']),
+ ...mapCommitActions(['updateCommitAction']),
updateSelectedCommitAction() {
if (this.currentBranch && !this.currentBranch.can_push) {
this.updateCommitAction(consts.COMMIT_TO_NEW_BRANCH);
- } else if (this.disableMergeRequestRadio) {
+ } else if (this.containsStagedChanges) {
this.updateCommitAction(consts.COMMIT_TO_CURRENT_BRANCH);
}
},
@@ -56,7 +57,7 @@ export default {
</script>
<template>
- <div class="append-bottom-15 ide-commit-radios">
+ <div class="append-bottom-15 ide-commit-options">
<radio-group
:value="$options.commitToCurrentBranch"
:disabled="currentBranch && !currentBranch.can_push"
@@ -69,17 +70,6 @@ export default {
:label="__('Create a new branch')"
:show-input="true"
/>
- <hr class="my-2" />
- <label class="mb-0">
- <input
- :checked="shouldCreateMR"
- :disabled="shouldDisableNewMrOption"
- type="checkbox"
- @change="toggleShouldCreateMR"
- />
- <span class="prepend-left-10" :class="{ 'text-secondary': shouldDisableNewMrOption }">
- {{ __('Start a new merge request') }}
- </span>
- </label>
+ <new-merge-request-option />
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue b/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue
index 00b2d236da3..6b0aa5b2b2b 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue
@@ -108,6 +108,7 @@ export default {
:placeholder="placeholder"
:value="text"
class="note-textarea ide-commit-message-textarea"
+ dir="auto"
name="commit-message"
@scroll="handleScroll"
@input="onInput"
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/new_merge_request_option.vue b/app/assets/javascripts/ide/components/commit_sidebar/new_merge_request_option.vue
new file mode 100644
index 00000000000..b2e7b15089c
--- /dev/null
+++ b/app/assets/javascripts/ide/components/commit_sidebar/new_merge_request_option.vue
@@ -0,0 +1,43 @@
+<script>
+import { mapGetters, createNamespacedHelpers } from 'vuex';
+
+const {
+ mapState: mapCommitState,
+ mapGetters: mapCommitGetters,
+ mapActions: mapCommitActions,
+} = createNamespacedHelpers('commit');
+
+export default {
+ computed: {
+ ...mapCommitState(['shouldCreateMR']),
+ ...mapCommitGetters(['isCommittingToCurrentBranch', 'isCommittingToDefaultBranch']),
+ ...mapGetters(['hasMergeRequest', 'isOnDefaultBranch']),
+ currentBranchHasMr() {
+ return this.hasMergeRequest && this.isCommittingToCurrentBranch;
+ },
+ showNewMrOption() {
+ return (
+ this.isCommittingToDefaultBranch || !this.currentBranchHasMr || this.isCommittingToNewBranch
+ );
+ },
+ },
+ mounted() {
+ this.setShouldCreateMR();
+ },
+ methods: {
+ ...mapCommitActions(['toggleShouldCreateMR', 'setShouldCreateMR']),
+ },
+};
+</script>
+
+<template>
+ <div v-if="showNewMrOption">
+ <hr class="my-2" />
+ <label class="mb-0">
+ <input :checked="shouldCreateMR" type="checkbox" @change="toggleShouldCreateMR" />
+ <span class="prepend-left-10">
+ {{ __('Start a new merge request') }}
+ </span>
+ </label>
+ </div>
+</template>
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index 9894ebb0624..363a8f43033 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -1,6 +1,7 @@
<script>
import Vue from 'vue';
import { mapActions, mapState, mapGetters } from 'vuex';
+import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import FindFile from '~/vue_shared/components/file_finder/index.vue';
import NewModal from './new_dropdown/modal.vue';
@@ -22,6 +23,8 @@ export default {
FindFile,
ErrorMessage,
CommitEditorHeader,
+ GlButton,
+ GlLoadingIcon,
},
props: {
rightPaneComponent: {
@@ -47,13 +50,15 @@ export default {
'someUncommittedChanges',
'isCommitModeActive',
'allBlobs',
+ 'emptyRepo',
+ 'currentTree',
]),
},
mounted() {
window.onbeforeunload = e => this.onBeforeUnload(e);
},
methods: {
- ...mapActions(['toggleFileFinder']),
+ ...mapActions(['toggleFileFinder', 'openNewEntryModal']),
onBeforeUnload(e = {}) {
const returnValue = __('Are you sure you want to lose unsaved changes?');
@@ -98,17 +103,40 @@ export default {
<repo-editor :file="activeFile" class="multi-file-edit-pane-content" />
</template>
<template v-else>
- <div v-once class="ide-empty-state">
+ <div class="ide-empty-state">
<div class="row js-empty-state">
<div class="col-12">
<div class="svg-content svg-250"><img :src="emptyStateSvgPath" /></div>
</div>
<div class="col-12">
<div class="text-content text-center">
- <h4>Welcome to the GitLab IDE</h4>
- <p>
- Select a file from the left sidebar to begin editing. Afterwards, you'll be able
- to commit your changes.
+ <h4>
+ {{ __('Make and review changes in the browser with the Web IDE') }}
+ </h4>
+ <template v-if="emptyRepo">
+ <p>
+ {{
+ __(
+ "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes.",
+ )
+ }}
+ </p>
+ <gl-button
+ variant="success"
+ :title="__('New file')"
+ :aria-label="__('New file')"
+ @click="openNewEntryModal({ type: 'blob' })"
+ >
+ {{ __('New file') }}
+ </gl-button>
+ </template>
+ <gl-loading-icon v-else-if="!currentTree || currentTree.loading" size="md" />
+ <p v-else>
+ {{
+ __(
+ "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes.",
+ )
+ }}
</p>
</div>
</div>
@@ -118,7 +146,7 @@ export default {
</div>
<component :is="rightPaneComponent" v-if="currentProjectId" />
</div>
- <ide-status-bar :file="activeFile" />
+ <ide-status-bar />
<new-modal />
</article>
</template>
diff --git a/app/assets/javascripts/ide/components/ide_status_bar.vue b/app/assets/javascripts/ide/components/ide_status_bar.vue
index ce577ae85b0..206b8341aad 100644
--- a/app/assets/javascripts/ide/components/ide_status_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_status_bar.vue
@@ -1,5 +1,6 @@
<script>
import { mapActions, mapState, mapGetters } from 'vuex';
+import IdeStatusList from 'ee_else_ce/ide/components/ide_status_list.vue';
import icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import timeAgoMixin from '~/vue_shared/mixins/timeago';
@@ -12,18 +13,12 @@ export default {
icon,
userAvatarImage,
CiIcon,
+ IdeStatusList,
},
directives: {
tooltip,
},
mixins: [timeAgoMixin],
- props: {
- file: {
- type: Object,
- required: false,
- default: null,
- },
- },
data() {
return {
lastCommitFormatedAge: null,
@@ -125,11 +120,6 @@ export default {
>{{ lastCommitFormatedAge }}</time
>
</div>
- <div v-if="file" class="ide-status-file">{{ file.name }}</div>
- <div v-if="file" class="ide-status-file">{{ file.eol }}</div>
- <div v-if="file && !file.binary" class="ide-status-file">
- {{ file.editorRow }}:{{ file.editorColumn }}
- </div>
- <div v-if="file" class="ide-status-file">{{ file.fileLanguage }}</div>
+ <ide-status-list class="ml-auto" />
</footer>
</template>
diff --git a/app/assets/javascripts/ide/components/ide_status_list.vue b/app/assets/javascripts/ide/components/ide_status_list.vue
new file mode 100644
index 00000000000..364e3f081a1
--- /dev/null
+++ b/app/assets/javascripts/ide/components/ide_status_list.vue
@@ -0,0 +1,23 @@
+<script>
+import { mapGetters } from 'vuex';
+
+export default {
+ computed: {
+ ...mapGetters(['activeFile']),
+ },
+};
+</script>
+
+<template>
+ <div class="ide-status-list d-flex">
+ <template v-if="activeFile">
+ <div class="ide-status-file">{{ activeFile.name }}</div>
+ <div class="ide-status-file">{{ activeFile.eol }}</div>
+ <div v-if="!activeFile.binary" class="ide-status-file">
+ {{ activeFile.editorRow }}:{{ activeFile.editorColumn }}
+ </div>
+ <div class="ide-status-file">{{ activeFile.fileLanguage }}</div>
+ </template>
+ <slot></slot>
+ </div>
+</template>
diff --git a/app/assets/javascripts/ide/components/ide_tree_list.vue b/app/assets/javascripts/ide/components/ide_tree_list.vue
index 81374f26645..95782b2c88a 100644
--- a/app/assets/javascripts/ide/components/ide_tree_list.vue
+++ b/app/assets/javascripts/ide/components/ide_tree_list.vue
@@ -54,14 +54,17 @@ export default {
<slot name="header"></slot>
</header>
<div class="ide-tree-body h-100">
- <file-row
- v-for="file in currentTree.tree"
- :key="file.key"
- :file="file"
- :level="0"
- :extra-component="$options.FileRowExtra"
- @toggleTreeOpen="toggleTreeOpen"
- />
+ <template v-if="currentTree.tree.length">
+ <file-row
+ v-for="file in currentTree.tree"
+ :key="file.key"
+ :file="file"
+ :level="0"
+ :extra-component="$options.FileRowExtra"
+ @toggleTreeOpen="toggleTreeOpen"
+ />
+ </template>
+ <div v-else class="file-row">{{ __('No files') }}</div>
</div>
</template>
</div>
diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
index 412b07553dc..f67666f1fbf 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/modal.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
@@ -134,6 +134,7 @@ export default {
<template>
<gl-modal
id="ide-new-entry"
+ class="qa-new-file-modal"
:header-title-text="modalTitle"
:footer-primary-button-text="buttonLabel"
footer-primary-button-variant="success"
diff --git a/app/assets/javascripts/ide/components/new_dropdown/upload.vue b/app/assets/javascripts/ide/components/new_dropdown/upload.vue
index ec759043efc..188518dd419 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/upload.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/upload.vue
@@ -57,6 +57,8 @@ export default {
type: 'blob',
content: result,
base64: !isText,
+ binary: !isText,
+ rawPath: !isText ? target.result : '',
});
},
readFile(file) {
diff --git a/app/assets/javascripts/ide/components/preview/clientside.vue b/app/assets/javascripts/ide/components/preview/clientside.vue
index c98dda00817..6999746f115 100644
--- a/app/assets/javascripts/ide/components/preview/clientside.vue
+++ b/app/assets/javascripts/ide/components/preview/clientside.vue
@@ -105,7 +105,7 @@ export default {
.then(() => {
this.initManager('#ide-preview', this.sandboxOpts, {
fileResolver: {
- isFile: p => Promise.resolve(!!this.entries[createPathWithExt(p)]),
+ isFile: p => Promise.resolve(Boolean(this.entries[createPathWithExt(p)])),
readFile: p => this.loadFileContent(createPathWithExt(p)).then(content => content),
},
});
diff --git a/app/assets/javascripts/ide/components/repo_commit_section.vue b/app/assets/javascripts/ide/components/repo_commit_section.vue
index 99f1d4a573d..5201c33b1b4 100644
--- a/app/assets/javascripts/ide/components/repo_commit_section.vue
+++ b/app/assets/javascripts/ide/components/repo_commit_section.vue
@@ -30,7 +30,7 @@ export default {
...mapGetters(['lastOpenedFile', 'hasChanges', 'someUncommittedChanges', 'activeFile']),
...mapGetters('commit', ['discardDraftButtonDisabled']),
showStageUnstageArea() {
- return !!(this.someUncommittedChanges || this.lastCommitMsg || !this.unusedSeal);
+ return Boolean(this.someUncommittedChanges || this.lastCommitMsg || !this.unusedSeal);
},
activeFileKey() {
return this.activeFile ? this.activeFile.key : null;
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue
index 94a9e87369c..b0c4969c5e4 100644
--- a/app/assets/javascripts/ide/components/repo_editor.vue
+++ b/app/assets/javascripts/ide/components/repo_editor.vue
@@ -1,5 +1,6 @@
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
+import { viewerInformationForPath } from '~/vue_shared/components/content_viewer/lib/viewer_utils';
import flash from '~/flash';
import ContentViewer from '~/vue_shared/components/content_viewer/content_viewer.vue';
import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
@@ -35,7 +36,7 @@ export default {
]),
...mapGetters('fileTemplates', ['showFileTemplatesBar']),
shouldHideEditor() {
- return this.file && this.file.binary && !this.file.content;
+ return this.file && this.file.binary;
},
showContentViewer() {
return (
@@ -56,6 +57,10 @@ export default {
active: this.file.viewMode === 'preview',
};
},
+ fileType() {
+ const info = viewerInformationForPath(this.file.path);
+ return (info && info.id) || '';
+ },
},
watch: {
file(newVal, oldVal) {
@@ -120,6 +125,7 @@ export default {
'setFileEOL',
'updateViewer',
'removePendingTab',
+ 'triggerFilesChange',
]),
initEditor() {
if (this.shouldHideEditor) return;
@@ -251,6 +257,7 @@ export default {
'is-added': file.tempFile,
}"
class="multi-file-editor-holder"
+ @focusout="triggerFilesChange"
></div>
<content-viewer
v-if="showContentViewer"
@@ -258,6 +265,7 @@ export default {
:path="file.rawPath || file.path"
:file-size="file.size"
:project-path="file.projectId"
+ :type="fileType"
/>
<diff-viewer
v-if="showDiffViewer"
diff --git a/app/assets/javascripts/ide/constants.js b/app/assets/javascripts/ide/constants.js
index 7c560c89695..e30670e119f 100644
--- a/app/assets/javascripts/ide/constants.js
+++ b/app/assets/javascripts/ide/constants.js
@@ -72,4 +72,11 @@ export const modalTypes = {
tree: 'tree',
};
+export const commitActionTypes = {
+ move: 'move',
+ delete: 'delete',
+ create: 'create',
+ update: 'update',
+};
+
export const packageJsonPath = 'package.json';
diff --git a/app/assets/javascripts/ide/ide_router.js b/app/assets/javascripts/ide/ide_router.js
index 229ef168926..8c84b98a108 100644
--- a/app/assets/javascripts/ide/ide_router.js
+++ b/app/assets/javascripts/ide/ide_router.js
@@ -1,8 +1,9 @@
import Vue from 'vue';
import VueRouter from 'vue-router';
-import { join as joinPath } from 'path';
+import { joinPaths } from '~/lib/utils/url_utility';
import flash from '~/flash';
import store from './stores';
+import { __ } from '~/locale';
Vue.use(VueRouter);
@@ -34,7 +35,7 @@ const EmptyRouterComponent = {
const router = new VueRouter({
mode: 'history',
- base: `${gon.relative_url_root}/-/ide/`,
+ base: joinPaths(gon.relative_url_root || '', '/-/ide/'),
routes: [
{
path: '/project/:namespace+/:project',
@@ -46,11 +47,11 @@ const router = new VueRouter({
},
{
path: ':targetmode(edit|tree|blob)/:branchid+/',
- redirect: to => joinPath(to.path, '/-/'),
+ redirect: to => joinPaths(to.path, '/-/'),
},
{
path: ':targetmode(edit|tree|blob)',
- redirect: to => joinPath(to.path, '/master/-/'),
+ redirect: to => joinPaths(to.path, '/master/-/'),
},
{
path: 'merge_requests/:mrid',
@@ -58,7 +59,7 @@ const router = new VueRouter({
},
{
path: '',
- redirect: to => joinPath(to.path, '/edit/master/-/'),
+ redirect: to => joinPaths(to.path, '/edit/master/-/'),
},
],
},
@@ -94,7 +95,7 @@ router.beforeEach((to, from, next) => {
})
.catch(e => {
flash(
- 'Error while loading the project data. Please try again.',
+ __('Error while loading the project data. Please try again.'),
'alert',
document,
null,
diff --git a/app/assets/javascripts/ide/lib/editor_options.js b/app/assets/javascripts/ide/lib/editor_options.js
index e35595ab1fd..dac2a8e8b51 100644
--- a/app/assets/javascripts/ide/lib/editor_options.js
+++ b/app/assets/javascripts/ide/lib/editor_options.js
@@ -11,7 +11,7 @@ export const defaultEditorOptions = {
export default [
{
- readOnly: model => !!model.file.file_lock,
+ readOnly: model => Boolean(model.file.file_lock),
quickSuggestions: model => !(model.language === 'markdown'),
},
];
diff --git a/app/assets/javascripts/ide/lib/files.js b/app/assets/javascripts/ide/lib/files.js
index df100f753d7..b8abaa41f23 100644
--- a/app/assets/javascripts/ide/lib/files.js
+++ b/app/assets/javascripts/ide/lib/files.js
@@ -22,6 +22,8 @@ export const decorateFiles = ({
tempFile = false,
content = '',
base64 = false,
+ binary = false,
+ rawPath = '',
}) => {
const treeList = [];
const entries = {};
@@ -90,6 +92,8 @@ export const decorateFiles = ({
changed: tempFile,
content,
base64,
+ binary,
+ rawPath,
previewMode: viewerInformationForPath(name),
parentPath,
});
diff --git a/app/assets/javascripts/ide/lib/keymap.json b/app/assets/javascripts/ide/lib/keymap.json
index 131abfebbed..2db87c07dde 100644
--- a/app/assets/javascripts/ide/lib/keymap.json
+++ b/app/assets/javascripts/ide/lib/keymap.json
@@ -7,5 +7,13 @@
"name": "toggleFileFinder",
"params": true
}
+ },
+ {
+ "id": "save-files",
+ "label": "Save files",
+ "bindings": ["CtrlCmd+KEY_S"],
+ "action": {
+ "name": "triggerFilesChange"
+ }
}
]
diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js
index 7b660bda081..5429b834708 100644
--- a/app/assets/javascripts/ide/stores/actions.js
+++ b/app/assets/javascripts/ide/stores/actions.js
@@ -1,12 +1,15 @@
import $ from 'jquery';
import Vue from 'vue';
+import { __, sprintf } from '~/locale';
import { visitUrl } from '~/lib/utils/url_utility';
import flash from '~/flash';
+import _ from 'underscore';
import * as types from './mutation_types';
import { decorateFiles } from '../lib/files';
import { stageKeys } from '../constants';
+import service from '../services';
-export const redirectToUrl = (_, url) => visitUrl(url);
+export const redirectToUrl = (self, url) => visitUrl(url);
export const setInitialData = ({ commit }, data) => commit(types.SET_INITIAL_DATA, data);
@@ -53,7 +56,7 @@ export const setResizingStatus = ({ commit }, resizing) => {
export const createTempEntry = (
{ state, commit, dispatch },
- { name, type, content = '', base64 = false },
+ { name, type, content = '', base64 = false, binary = false, rawPath = '' },
) =>
new Promise(resolve => {
const fullName = name.slice(-1) !== '/' && type === 'tree' ? `${name}/` : name;
@@ -79,8 +82,10 @@ export const createTempEntry = (
branchId: state.currentBranchId,
type,
tempFile: true,
- base64,
content,
+ base64,
+ binary,
+ rawPath,
});
const { file, parentPath } = data;
@@ -94,6 +99,7 @@ export const createTempEntry = (
commit(types.TOGGLE_FILE_OPEN, file.path);
commit(types.ADD_FILE_TO_CHANGED, file.path);
dispatch('setFileActive', file.path);
+ dispatch('triggerFilesChange');
}
if (parentPath && !state.entries[parentPath].opened) {
@@ -205,6 +211,8 @@ export const deleteEntry = ({ commit, dispatch, state }, path) => {
if (entry.parentPath && state.entries[entry.parentPath].tree.length === 0) {
dispatch('deleteEntry', entry.parentPath);
}
+
+ dispatch('triggerFilesChange');
};
export const resetOpenFiles = ({ commit }) => commit(types.RESET_OPEN_FILES);
@@ -235,8 +243,57 @@ export const renameEntry = (
if (!entryPath && !entry.tempFile) {
dispatch('deleteEntry', path);
}
+
+ dispatch('triggerFilesChange');
};
+export const getBranchData = ({ commit, state }, { projectId, branchId, force = false } = {}) =>
+ new Promise((resolve, reject) => {
+ const currentProject = state.projects[projectId];
+ if (!currentProject || !currentProject.branches[branchId] || force) {
+ service
+ .getBranchData(projectId, branchId)
+ .then(({ data }) => {
+ const { id } = data.commit;
+ commit(types.SET_BRANCH, {
+ projectPath: projectId,
+ branchName: branchId,
+ branch: data,
+ });
+ commit(types.SET_BRANCH_WORKING_REFERENCE, { projectId, branchId, reference: id });
+ resolve(data);
+ })
+ .catch(e => {
+ if (e.response.status === 404) {
+ reject(e);
+ } else {
+ flash(
+ __('Error loading branch data. Please try again.'),
+ 'alert',
+ document,
+ null,
+ false,
+ true,
+ );
+
+ reject(
+ new Error(
+ sprintf(
+ __('Branch not loaded - %{branchId}'),
+ {
+ branchId: `<strong>${_.escape(projectId)}/${_.escape(branchId)}</strong>`,
+ },
+ false,
+ ),
+ ),
+ );
+ }
+ });
+ } else {
+ resolve(currentProject.branches[branchId]);
+ }
+ });
+
export * from './actions/tree';
export * from './actions/file';
export * from './actions/project';
diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js
index e74b880e02c..dc40a1fa6a2 100644
--- a/app/assets/javascripts/ide/stores/actions/file.js
+++ b/app/assets/javascripts/ide/stores/actions/file.js
@@ -1,5 +1,6 @@
-import { __ } from '../../../locale';
-import { normalizeHeaders } from '../../../lib/utils/common_utils';
+import { joinPaths } from '~/lib/utils/url_utility';
+import { normalizeHeaders } from '~/lib/utils/common_utils';
+import { __ } from '~/locale';
import eventHub from '../../eventhub';
import service from '../../services';
import * as types from '../mutation_types';
@@ -69,7 +70,7 @@ export const getFileData = (
const url = file.prevPath ? file.url.replace(file.path, file.prevPath) : file.url;
return service
- .getFileData(`${gon.relative_url_root ? gon.relative_url_root : ''}${url.replace('/-/', '/')}`)
+ .getFileData(joinPaths(gon.relative_url_root || '', url.replace('/-/', '/')))
.then(({ data, headers }) => {
const normalizedHeaders = normalizeHeaders(headers);
setPageTitle(decodeURI(normalizedHeaders['PAGE-TITLE']));
@@ -264,3 +265,8 @@ export const removePendingTab = ({ commit }, file) => {
eventHub.$emit(`editor.update.model.dispose.${file.key}`);
};
+
+export const triggerFilesChange = () => {
+ // Used in EE for file mirroring
+ eventHub.$emit('ide.files.change');
+};
diff --git a/app/assets/javascripts/ide/stores/actions/project.js b/app/assets/javascripts/ide/stores/actions/project.js
index 4b10d148ebf..dd8f17e4f3a 100644
--- a/app/assets/javascripts/ide/stores/actions/project.js
+++ b/app/assets/javascripts/ide/stores/actions/project.js
@@ -35,48 +35,6 @@ export const getProjectData = ({ commit, state }, { namespace, projectId, force
}
});
-export const getBranchData = (
- { commit, dispatch, state },
- { projectId, branchId, force = false } = {},
-) =>
- new Promise((resolve, reject) => {
- if (
- typeof state.projects[`${projectId}`] === 'undefined' ||
- !state.projects[`${projectId}`].branches[branchId] ||
- force
- ) {
- service
- .getBranchData(`${projectId}`, branchId)
- .then(({ data }) => {
- const { id } = data.commit;
- commit(types.SET_BRANCH, {
- projectPath: `${projectId}`,
- branchName: branchId,
- branch: data,
- });
- commit(types.SET_BRANCH_WORKING_REFERENCE, { projectId, branchId, reference: id });
- resolve(data);
- })
- .catch(e => {
- if (e.response.status === 404) {
- dispatch('showBranchNotFoundError', branchId);
- } else {
- flash(
- __('Error loading branch data. Please try again.'),
- 'alert',
- document,
- null,
- false,
- true,
- );
- }
- reject(new Error(`Branch not loaded - ${projectId}/${branchId}`));
- });
- } else {
- resolve(state.projects[`${projectId}`].branches[branchId]);
- }
- });
-
export const refreshLastCommitData = ({ commit }, { projectId, branchId } = {}) =>
service
.getBranchData(projectId, branchId)
@@ -125,40 +83,66 @@ export const showBranchNotFoundError = ({ dispatch }, branchId) => {
});
};
-export const openBranch = ({ dispatch, state }, { projectId, branchId, basePath }) => {
- dispatch('setCurrentBranchId', branchId);
-
- dispatch('getBranchData', {
- projectId,
- branchId,
+export const showEmptyState = ({ commit, state }, { projectId, branchId }) => {
+ const treePath = `${projectId}/${branchId}`;
+ commit(types.CREATE_TREE, { treePath });
+ commit(types.TOGGLE_LOADING, {
+ entry: state.trees[treePath],
+ forceValue: false,
});
+};
- return dispatch('getFiles', {
+export const openBranch = ({ dispatch, state, getters }, { projectId, branchId, basePath }) => {
+ dispatch('setCurrentBranchId', branchId);
+
+ if (getters.emptyRepo) {
+ return dispatch('showEmptyState', { projectId, branchId });
+ }
+ return dispatch('getBranchData', {
projectId,
branchId,
})
.then(() => {
- if (basePath) {
- const path = basePath.slice(-1) === '/' ? basePath.slice(0, -1) : basePath;
- const treeEntryKey = Object.keys(state.entries).find(
- key => key === path && !state.entries[key].pending,
- );
- const treeEntry = state.entries[treeEntryKey];
-
- if (treeEntry) {
- dispatch('handleTreeEntryAction', treeEntry);
- } else {
- dispatch('createTempEntry', {
- name: path,
- type: 'blob',
- });
- }
- }
- })
- .then(() => {
dispatch('getMergeRequestsForBranch', {
projectId,
branchId,
});
+ dispatch('getFiles', {
+ projectId,
+ branchId,
+ })
+ .then(() => {
+ if (basePath) {
+ const path = basePath.slice(-1) === '/' ? basePath.slice(0, -1) : basePath;
+ const treeEntryKey = Object.keys(state.entries).find(
+ key => key === path && !state.entries[key].pending,
+ );
+ const treeEntry = state.entries[treeEntryKey];
+
+ if (treeEntry) {
+ dispatch('handleTreeEntryAction', treeEntry);
+ } else {
+ dispatch('createTempEntry', {
+ name: path,
+ type: 'blob',
+ });
+ }
+ }
+ })
+ .catch(
+ () =>
+ new Error(
+ sprintf(
+ __('An error occurred whilst getting files for - %{branchId}'),
+ {
+ branchId: `<strong>${_.escape(projectId)}/${_.escape(branchId)}</strong>`,
+ },
+ false,
+ ),
+ ),
+ );
+ })
+ .catch(() => {
+ dispatch('showBranchNotFoundError', branchId);
});
};
diff --git a/app/assets/javascripts/ide/stores/actions/tree.js b/app/assets/javascripts/ide/stores/actions/tree.js
index 3d83e4a9ba5..75511574d3e 100644
--- a/app/assets/javascripts/ide/stores/actions/tree.js
+++ b/app/assets/javascripts/ide/stores/actions/tree.js
@@ -74,17 +74,13 @@ export const getFiles = ({ state, commit, dispatch }, { projectId, branchId } =
resolve();
})
.catch(e => {
- if (e.response.status === 404) {
- dispatch('showBranchNotFoundError', branchId);
- } else {
- dispatch('setErrorMessage', {
- text: __('An error occurred whilst loading all the files.'),
- action: payload =>
- dispatch('getFiles', payload).then(() => dispatch('setErrorMessage', null)),
- actionText: __('Please try again'),
- actionPayload: { projectId, branchId },
- });
- }
+ dispatch('setErrorMessage', {
+ text: __('An error occurred whilst loading all the files.'),
+ action: payload =>
+ dispatch('getFiles', payload).then(() => dispatch('setErrorMessage', null)),
+ actionText: __('Please try again'),
+ actionPayload: { projectId, branchId },
+ });
reject(e);
});
} else {
diff --git a/app/assets/javascripts/ide/stores/getters.js b/app/assets/javascripts/ide/stores/getters.js
index 490658a4543..406903129db 100644
--- a/app/assets/javascripts/ide/stores/getters.js
+++ b/app/assets/javascripts/ide/stores/getters.js
@@ -36,12 +36,16 @@ export const currentMergeRequest = state => {
export const currentProject = state => state.projects[state.currentProjectId];
+export const emptyRepo = state =>
+ state.projects[state.currentProjectId] && state.projects[state.currentProjectId].empty_repo;
+
export const currentTree = state =>
state.trees[`${state.currentProjectId}/${state.currentBranchId}`];
-export const hasChanges = state => !!state.changedFiles.length || !!state.stagedFiles.length;
+export const hasChanges = state =>
+ Boolean(state.changedFiles.length) || Boolean(state.stagedFiles.length);
-export const hasMergeRequest = state => !!state.currentMergeRequestId;
+export const hasMergeRequest = state => Boolean(state.currentMergeRequestId);
export const allBlobs = state =>
Object.keys(state.entries)
@@ -67,7 +71,7 @@ export const isCommitModeActive = state => state.currentActivityView === activit
export const isReviewModeActive = state => state.currentActivityView === activityBarViews.review;
export const someUncommittedChanges = state =>
- !!(state.changedFiles.length || state.stagedFiles.length);
+ Boolean(state.changedFiles.length || state.stagedFiles.length);
export const getChangesInFolder = state => path => {
const changedFilesCount = state.changedFiles.filter(f => filePathMatches(f.path, path)).length;
@@ -93,7 +97,12 @@ export const lastCommit = (state, getters) => {
export const currentBranch = (state, getters) =>
getters.currentProject && getters.currentProject.branches[state.currentBranchId];
+export const branchName = (_state, getters) => getters.currentBranch && getters.currentBranch.name;
+
export const packageJson = state => state.entries[packageJsonPath];
+export const isOnDefaultBranch = (_state, getters) =>
+ getters.currentProject && getters.currentProject.default_branch === getters.branchName;
+
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
diff --git a/app/assets/javascripts/ide/stores/modules/commit/actions.js b/app/assets/javascripts/ide/stores/modules/commit/actions.js
index c2760eb1554..51062f092ad 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/actions.js
@@ -18,15 +18,34 @@ export const discardDraft = ({ commit }) => {
commit(types.UPDATE_COMMIT_MESSAGE, '');
};
-export const updateCommitAction = ({ commit, rootGetters }, commitAction) => {
+export const updateCommitAction = ({ commit, dispatch }, commitAction) => {
commit(types.UPDATE_COMMIT_ACTION, {
commitAction,
- currentMergeRequest: rootGetters.currentMergeRequest,
});
+ dispatch('setShouldCreateMR');
};
export const toggleShouldCreateMR = ({ commit }) => {
commit(types.TOGGLE_SHOULD_CREATE_MR);
+ commit(types.INTERACT_WITH_NEW_MR);
+};
+
+export const setShouldCreateMR = ({
+ commit,
+ getters,
+ rootGetters,
+ state: { interactedWithNewMR },
+}) => {
+ const committingToExistingMR =
+ getters.isCommittingToCurrentBranch &&
+ rootGetters.hasMergeRequest &&
+ !rootGetters.isOnDefaultBranch;
+
+ if ((getters.isCommittingToDefaultBranch && !interactedWithNewMR) || committingToExistingMR) {
+ commit(types.TOGGLE_SHOULD_CREATE_MR, false);
+ } else if (!interactedWithNewMR) {
+ commit(types.TOGGLE_SHOULD_CREATE_MR, true);
+ }
};
export const updateBranchName = ({ commit }, branchName) => {
@@ -102,7 +121,7 @@ export const updateFilesAfterCommit = ({ commit, dispatch, rootState, rootGetter
eventHub.$emit(`editor.update.model.content.${file.key}`, {
content: file.content,
- changed: !!changedFile,
+ changed: Boolean(changedFile),
});
});
};
@@ -135,6 +154,17 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
return null;
}
+ if (!data.parent_ids.length) {
+ commit(
+ rootTypes.TOGGLE_EMPTY_STATE,
+ {
+ projectPath: rootState.currentProjectId,
+ value: false,
+ },
+ { root: true },
+ );
+ }
+
dispatch('setLastCommitMessage', data);
dispatch('updateCommitMessage', '');
return dispatch('updateFilesAfterCommit', {
diff --git a/app/assets/javascripts/ide/stores/modules/commit/getters.js b/app/assets/javascripts/ide/stores/modules/commit/getters.js
index 6aa5d22a4ea..64779e9e4df 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/getters.js
@@ -48,8 +48,11 @@ export const preBuiltCommitMessage = (state, _, rootState) => {
export const isCreatingNewBranch = state => state.commitAction === consts.COMMIT_TO_NEW_BRANCH;
-export const shouldDisableNewMrOption = (state, _getters, _rootState, rootGetters) =>
- rootGetters.currentMergeRequest && state.commitAction === consts.COMMIT_TO_CURRENT_BRANCH;
+export const isCommittingToCurrentBranch = state =>
+ state.commitAction === consts.COMMIT_TO_CURRENT_BRANCH;
+
+export const isCommittingToDefaultBranch = (_state, getters, _rootState, rootGetters) =>
+ getters.isCommittingToCurrentBranch && rootGetters.isOnDefaultBranch;
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
diff --git a/app/assets/javascripts/ide/stores/modules/commit/mutation_types.js b/app/assets/javascripts/ide/stores/modules/commit/mutation_types.js
index 7ad8f3570b7..b81918156b0 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/mutation_types.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/mutation_types.js
@@ -3,3 +3,4 @@ export const UPDATE_COMMIT_ACTION = 'UPDATE_COMMIT_ACTION';
export const UPDATE_NEW_BRANCH_NAME = 'UPDATE_NEW_BRANCH_NAME';
export const UPDATE_LOADING = 'UPDATE_LOADING';
export const TOGGLE_SHOULD_CREATE_MR = 'TOGGLE_SHOULD_CREATE_MR';
+export const INTERACT_WITH_NEW_MR = 'INTERACT_WITH_NEW_MR';
diff --git a/app/assets/javascripts/ide/stores/modules/commit/mutations.js b/app/assets/javascripts/ide/stores/modules/commit/mutations.js
index be0f894c059..14957d283bb 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/mutations.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/mutations.js
@@ -1,5 +1,4 @@
import * as types from './mutation_types';
-import consts from './constants';
export default {
[types.UPDATE_COMMIT_MESSAGE](state, commitMessage) {
@@ -7,14 +6,8 @@ export default {
commitMessage,
});
},
- [types.UPDATE_COMMIT_ACTION](state, { commitAction, currentMergeRequest }) {
- Object.assign(state, {
- commitAction,
- shouldCreateMR:
- commitAction === consts.COMMIT_TO_CURRENT_BRANCH && currentMergeRequest
- ? false
- : state.shouldCreateMR,
- });
+ [types.UPDATE_COMMIT_ACTION](state, { commitAction }) {
+ Object.assign(state, { commitAction });
},
[types.UPDATE_NEW_BRANCH_NAME](state, newBranchName) {
Object.assign(state, {
@@ -26,9 +19,12 @@ export default {
submitCommitLoading,
});
},
- [types.TOGGLE_SHOULD_CREATE_MR](state) {
+ [types.TOGGLE_SHOULD_CREATE_MR](state, shouldCreateMR) {
Object.assign(state, {
- shouldCreateMR: !state.shouldCreateMR,
+ shouldCreateMR: shouldCreateMR === undefined ? !state.shouldCreateMR : shouldCreateMR,
});
},
+ [types.INTERACT_WITH_NEW_MR](state) {
+ Object.assign(state, { interactedWithNewMR: true });
+ },
};
diff --git a/app/assets/javascripts/ide/stores/modules/commit/state.js b/app/assets/javascripts/ide/stores/modules/commit/state.js
index 5c0e6a41ca1..53647a7e3e3 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/state.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/state.js
@@ -4,4 +4,5 @@ export default () => ({
newBranchName: '',
submitCommitLoading: false,
shouldCreateMR: false,
+ interactedWithNewMR: false,
});
diff --git a/app/assets/javascripts/ide/stores/modules/file_templates/actions.js b/app/assets/javascripts/ide/stores/modules/file_templates/actions.js
index b7090e09daf..59ead8a3dcf 100644
--- a/app/assets/javascripts/ide/stores/modules/file_templates/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/file_templates/actions.js
@@ -23,22 +23,27 @@ export const receiveTemplateTypesError = ({ commit, dispatch }) => {
export const receiveTemplateTypesSuccess = ({ commit }, templates) =>
commit(types.RECEIVE_TEMPLATE_TYPES_SUCCESS, templates);
-export const fetchTemplateTypes = ({ dispatch, state, rootState }, page = 1) => {
+export const fetchTemplateTypes = ({ dispatch, state, rootState }) => {
if (!Object.keys(state.selectedTemplateType).length) return Promise.reject();
dispatch('requestTemplateTypes');
- return Api.projectTemplates(rootState.currentProjectId, state.selectedTemplateType.key, { page })
- .then(({ data, headers }) => {
- const nextPage = parseInt(normalizeHeaders(headers)['X-NEXT-PAGE'], 10);
+ const fetchPages = (page = 1, prev = []) =>
+ Api.projectTemplates(rootState.currentProjectId, state.selectedTemplateType.key, {
+ page,
+ per_page: 100,
+ })
+ .then(({ data, headers }) => {
+ const nextPage = parseInt(normalizeHeaders(headers)['X-NEXT-PAGE'], 10);
+ const nextData = prev.concat(data);
- dispatch('receiveTemplateTypesSuccess', data);
+ dispatch('receiveTemplateTypesSuccess', nextData);
- if (nextPage) {
- dispatch('fetchTemplateTypes', nextPage);
- }
- })
- .catch(() => dispatch('receiveTemplateTypesError'));
+ return nextPage ? fetchPages(nextPage, nextData) : nextData;
+ })
+ .catch(() => dispatch('receiveTemplateTypesError'));
+
+ return fetchPages();
};
export const setSelectedTemplateType = ({ commit, dispatch, rootGetters }, type) => {
diff --git a/app/assets/javascripts/ide/stores/modules/file_templates/getters.js b/app/assets/javascripts/ide/stores/modules/file_templates/getters.js
index 628babe6a01..f10891a8e5b 100644
--- a/app/assets/javascripts/ide/stores/modules/file_templates/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/file_templates/getters.js
@@ -1,4 +1,5 @@
import { activityBarViews } from '../../../constants';
+import { __ } from '~/locale';
export const templateTypes = () => [
{
@@ -10,11 +11,11 @@ export const templateTypes = () => [
key: 'gitignores',
},
{
- name: 'LICENSE',
+ name: __('LICENSE'),
key: 'licenses',
},
{
- name: 'Dockerfile',
+ name: __('Dockerfile'),
key: 'dockerfiles',
},
];
diff --git a/app/assets/javascripts/ide/stores/modules/file_templates/mutations.js b/app/assets/javascripts/ide/stores/modules/file_templates/mutations.js
index 25a65b047f1..7fc1c9134a7 100644
--- a/app/assets/javascripts/ide/stores/modules/file_templates/mutations.js
+++ b/app/assets/javascripts/ide/stores/modules/file_templates/mutations.js
@@ -3,13 +3,14 @@ import * as types from './mutation_types';
export default {
[types.REQUEST_TEMPLATE_TYPES](state) {
state.isLoading = true;
+ state.templates = [];
},
[types.RECEIVE_TEMPLATE_TYPES_ERROR](state) {
state.isLoading = false;
},
[types.RECEIVE_TEMPLATE_TYPES_SUCCESS](state, templates) {
state.isLoading = false;
- state.templates = state.templates.concat(templates);
+ state.templates = templates;
},
[types.SET_SELECTED_TEMPLATE_TYPE](state, type) {
state.selectedTemplateType = type;
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/getters.js b/app/assets/javascripts/ide/stores/modules/pipelines/getters.js
index ef7cd4ff8e8..1d127d915d7 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/getters.js
@@ -1,6 +1,6 @@
import { states } from './constants';
-export const hasLatestPipeline = state => !state.isLoadingPipeline && !!state.latestPipeline;
+export const hasLatestPipeline = state => !state.isLoadingPipeline && Boolean(state.latestPipeline);
export const pipelineFailed = state =>
state.latestPipeline && state.latestPipeline.details.status.text === states.failed;
diff --git a/app/assets/javascripts/ide/stores/mutation_types.js b/app/assets/javascripts/ide/stores/mutation_types.js
index a5f8098dc17..86ab76136df 100644
--- a/app/assets/javascripts/ide/stores/mutation_types.js
+++ b/app/assets/javascripts/ide/stores/mutation_types.js
@@ -12,6 +12,7 @@ export const SET_LINKS = 'SET_LINKS';
export const SET_PROJECT = 'SET_PROJECT';
export const SET_CURRENT_PROJECT = 'SET_CURRENT_PROJECT';
export const TOGGLE_PROJECT_OPEN = 'TOGGLE_PROJECT_OPEN';
+export const TOGGLE_EMPTY_STATE = 'TOGGLE_EMPTY_STATE';
// Merge Request Mutation Types
export const SET_MERGE_REQUEST = 'SET_MERGE_REQUEST';
diff --git a/app/assets/javascripts/ide/stores/mutations.js b/app/assets/javascripts/ide/stores/mutations.js
index 9b9f4b21f1c..ae42b87c9a7 100644
--- a/app/assets/javascripts/ide/stores/mutations.js
+++ b/app/assets/javascripts/ide/stores/mutations.js
@@ -142,7 +142,7 @@ export default {
Object.assign(state.entries[file.path], {
raw: file.content,
- changed: !!changedFile,
+ changed: Boolean(changedFile),
staged: false,
prevPath: '',
moved: false,
@@ -213,7 +213,7 @@ export default {
? `${slashedParentPath}${oldEntry.name}`
: `${slashedParentPath}${name}`;
- state.entries[newPath] = {
+ Vue.set(state.entries, newPath, {
...oldEntry,
id: newPath,
key: `${newPath}-${oldEntry.type}-${oldEntry.id}`,
@@ -225,7 +225,7 @@ export default {
tree: [],
parentPath,
raw: '',
- };
+ });
oldEntry.moved = true;
oldEntry.movedPath = newPath;
diff --git a/app/assets/javascripts/ide/stores/mutations/branch.js b/app/assets/javascripts/ide/stores/mutations/branch.js
index e09f88878f4..6afd8de2aa4 100644
--- a/app/assets/javascripts/ide/stores/mutations/branch.js
+++ b/app/assets/javascripts/ide/stores/mutations/branch.js
@@ -19,6 +19,12 @@ export default {
});
},
[types.SET_BRANCH_WORKING_REFERENCE](state, { projectId, branchId, reference }) {
+ if (!state.projects[projectId].branches[branchId]) {
+ Object.assign(state.projects[projectId].branches, {
+ [branchId]: {},
+ });
+ }
+
Object.assign(state.projects[projectId].branches[branchId], {
workingReference: reference,
});
diff --git a/app/assets/javascripts/ide/stores/mutations/project.js b/app/assets/javascripts/ide/stores/mutations/project.js
index 284b39a2c72..9230f3839c1 100644
--- a/app/assets/javascripts/ide/stores/mutations/project.js
+++ b/app/assets/javascripts/ide/stores/mutations/project.js
@@ -21,4 +21,9 @@ export default {
}),
});
},
+ [types.TOGGLE_EMPTY_STATE](state, { projectPath, value }) {
+ Object.assign(state.projects[projectPath], {
+ empty_repo: value,
+ });
+ },
};
diff --git a/app/assets/javascripts/ide/stores/utils.js b/app/assets/javascripts/ide/stores/utils.js
index 3ab8f3f11be..bcc9ca60d9b 100644
--- a/app/assets/javascripts/ide/stores/utils.js
+++ b/app/assets/javascripts/ide/stores/utils.js
@@ -1,3 +1,5 @@
+import { commitActionTypes } from '../constants';
+
export const dataStructure = () => ({
id: '',
// Key will contain a mixture of ID and path
@@ -69,6 +71,8 @@ export const decorateData = entity => {
changed = false,
parentTreeUrl = '',
base64 = false,
+ binary = false,
+ rawPath = '',
previewMode,
file_lock,
html,
@@ -92,6 +96,8 @@ export const decorateData = entity => {
renderError,
content,
base64,
+ binary,
+ rawPath,
previewMode,
file_lock,
html,
@@ -110,14 +116,14 @@ export const setPageTitle = title => {
export const commitActionForFile = file => {
if (file.prevPath) {
- return 'move';
+ return commitActionTypes.move;
} else if (file.deleted) {
- return 'delete';
+ return commitActionTypes.delete;
} else if (file.tempFile) {
- return 'create';
+ return commitActionTypes.create;
}
- return 'update';
+ return commitActionTypes.update;
};
export const getCommitFiles = stagedFiles =>
diff --git a/app/assets/javascripts/image_diff/helpers/comment_indicator_helper.js b/app/assets/javascripts/image_diff/helpers/comment_indicator_helper.js
index 05000c73052..7051a968dac 100644
--- a/app/assets/javascripts/image_diff/helpers/comment_indicator_helper.js
+++ b/app/assets/javascripts/image_diff/helpers/comment_indicator_helper.js
@@ -14,7 +14,7 @@ export function addCommentIndicator(containerEl, { x, y }) {
export function removeCommentIndicator(imageFrameEl) {
const commentIndicatorEl = imageFrameEl.querySelector('.comment-indicator');
const imageEl = imageFrameEl.querySelector('img');
- const willRemove = !!commentIndicatorEl;
+ const willRemove = Boolean(commentIndicatorEl);
let meta = {};
if (willRemove) {
diff --git a/app/assets/javascripts/image_diff/image_diff.js b/app/assets/javascripts/image_diff/image_diff.js
index 3587f073a00..26c1b0ec7be 100644
--- a/app/assets/javascripts/image_diff/image_diff.js
+++ b/app/assets/javascripts/image_diff/image_diff.js
@@ -6,8 +6,8 @@ import { isImageLoaded } from '../lib/utils/image_utility';
export default class ImageDiff {
constructor(el, options) {
this.el = el;
- this.canCreateNote = !!(options && options.canCreateNote);
- this.renderCommentBadge = !!(options && options.renderCommentBadge);
+ this.canCreateNote = Boolean(options && options.canCreateNote);
+ this.renderCommentBadge = Boolean(options && options.renderCommentBadge);
this.$noteContainer = $('.note-container', this.el);
this.imageBadges = [];
}
diff --git a/app/assets/javascripts/image_diff/view_types.js b/app/assets/javascripts/image_diff/view_types.js
index ab0a595571f..1a5123de220 100644
--- a/app/assets/javascripts/image_diff/view_types.js
+++ b/app/assets/javascripts/image_diff/view_types.js
@@ -5,5 +5,5 @@ export const viewTypes = {
};
export function isValidViewType(validate) {
- return !!Object.getOwnPropertyNames(viewTypes).find(viewType => viewType === validate);
+ return Boolean(Object.getOwnPropertyNames(viewTypes).find(viewType => viewType === validate));
}
diff --git a/app/assets/javascripts/import_projects/components/import_projects_table.vue b/app/assets/javascripts/import_projects/components/import_projects_table.vue
index 777f8fa6691..00eb0afb3bf 100644
--- a/app/assets/javascripts/import_projects/components/import_projects_table.vue
+++ b/app/assets/javascripts/import_projects/components/import_projects_table.vue
@@ -74,7 +74,7 @@ export default {
<gl-loading-icon
v-if="isLoadingRepos"
class="js-loading-button-icon import-projects-loading-icon"
- :size="4"
+ size="md"
/>
<div v-else-if="hasProviderRepos || hasImportedProjects" class="table-responsive">
<table class="table import-table">
diff --git a/app/assets/javascripts/import_projects/store/getters.js b/app/assets/javascripts/import_projects/store/getters.js
index f03474a8404..727b80765bd 100644
--- a/app/assets/javascripts/import_projects/store/getters.js
+++ b/app/assets/javascripts/import_projects/store/getters.js
@@ -1,3 +1,5 @@
+import { __ } from '~/locale';
+
export const namespaceSelectOptions = state => {
const serializedNamespaces = state.namespaces.map(({ fullPath }) => ({
id: fullPath,
@@ -5,9 +7,9 @@ export const namespaceSelectOptions = state => {
}));
return [
- { text: 'Groups', children: serializedNamespaces },
+ { text: __('Groups'), children: serializedNamespaces },
{
- text: 'Users',
+ text: __('Users'),
children: [{ id: state.defaultTargetNamespace, text: state.defaultTargetNamespace }],
},
];
diff --git a/app/assets/javascripts/import_projects/store/index.js b/app/assets/javascripts/import_projects/store/index.js
index f666e2ebf33..ff1fd1e598e 100644
--- a/app/assets/javascripts/import_projects/store/index.js
+++ b/app/assets/javascripts/import_projects/store/index.js
@@ -7,6 +7,8 @@ import mutations from './mutations';
Vue.use(Vuex);
+export { state, actions, getters, mutations };
+
export default () =>
new Vuex.Store({
state: state(),
diff --git a/app/assets/javascripts/integrations/integration_settings_form.js b/app/assets/javascripts/integrations/integration_settings_form.js
index 08b858305ab..a7746bb3a0b 100644
--- a/app/assets/javascripts/integrations/integration_settings_form.js
+++ b/app/assets/javascripts/integrations/integration_settings_form.js
@@ -1,6 +1,7 @@
import $ from 'jquery';
import axios from '../lib/utils/axios_utils';
import flash from '../flash';
+import { __ } from '~/locale';
export default class IntegrationSettingsForm {
constructor(formSelector) {
@@ -65,10 +66,10 @@ export default class IntegrationSettingsForm {
* Toggle Submit button label based on Integration status and ability to test service
*/
toggleSubmitBtnLabel(serviceActive) {
- let btnLabel = 'Save changes';
+ let btnLabel = __('Save changes');
if (serviceActive && this.canTestService) {
- btnLabel = 'Test settings and save changes';
+ btnLabel = __('Test settings and save changes');
}
this.$submitBtnLabel.text(btnLabel);
@@ -105,7 +106,7 @@ export default class IntegrationSettingsForm {
if (data.test_failed) {
flashActions = {
- title: 'Save anyway',
+ title: __('Save anyway'),
clickHandler: e => {
e.preventDefault();
this.$form.submit();
@@ -121,7 +122,7 @@ export default class IntegrationSettingsForm {
this.toggleSubmitBtnState(false);
})
.catch(() => {
- flash('Something went wrong on our end.');
+ flash(__('Something went wrong on our end.'));
this.toggleSubmitBtnState(false);
});
}
diff --git a/app/assets/javascripts/issuable_bulk_update_actions.js b/app/assets/javascripts/issuable_bulk_update_actions.js
index ccbe591a63e..bc9d7fcf30d 100644
--- a/app/assets/javascripts/issuable_bulk_update_actions.js
+++ b/app/assets/javascripts/issuable_bulk_update_actions.js
@@ -4,6 +4,7 @@ import $ from 'jquery';
import _ from 'underscore';
import axios from './lib/utils/axios_utils';
import Flash from './flash';
+import { __ } from './locale';
export default {
init({ container, form, issues, prefixId } = {}) {
@@ -32,7 +33,7 @@ export default {
onFormSubmitFailure() {
this.form.find('[type="submit"]').enable();
- return new Flash('Issue update failed');
+ return new Flash(__('Issue update failed'));
},
getSelectedIssues() {
diff --git a/app/assets/javascripts/issuable_form.js b/app/assets/javascripts/issuable_form.js
index 9336b71cfd7..7576d36f27d 100644
--- a/app/assets/javascripts/issuable_form.js
+++ b/app/assets/javascripts/issuable_form.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import Pikaday from 'pikaday';
+import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
import Autosave from './autosave';
import UsersSelect from './users_select';
-import GfmAutoComplete from './gfm_auto_complete';
import ZenMode from './zen_mode';
import AutoWidthDropdownSelect from './issuable/auto_width_dropdown_select';
import { parsePikadayDate, pikadayToString } from './lib/utils/datetime_utility';
diff --git a/app/assets/javascripts/issuable_index.js b/app/assets/javascripts/issuable_index.js
index ffcbd7cf28c..16f88cddce3 100644
--- a/app/assets/javascripts/issuable_index.js
+++ b/app/assets/javascripts/issuable_index.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import axios from './lib/utils/axios_utils';
import flash from './flash';
-import { __ } from './locale';
+import { s__, __ } from './locale';
import IssuableBulkUpdateSidebar from './issuable_bulk_update_sidebar';
import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
@@ -12,7 +12,7 @@ export default class IssuableIndex {
}
initBulkUpdate(pagePrefix) {
const userCanBulkUpdate = $('.issues-bulk-update').length > 0;
- const alreadyInitialized = !!this.bulkUpdateSidebar;
+ const alreadyInitialized = Boolean(this.bulkUpdateSidebar);
if (userCanBulkUpdate && !alreadyInitialized) {
IssuableBulkUpdateActions.init({
@@ -29,7 +29,7 @@ export default class IssuableIndex {
$resetToken.on('click', e => {
e.preventDefault();
- $resetToken.text('resetting...');
+ $resetToken.text(s__('EmailToken|resetting...'));
axios
.put($resetToken.attr('href'))
@@ -38,12 +38,12 @@ export default class IssuableIndex {
.val(data.new_address)
.focus();
- $resetToken.text('reset it');
+ $resetToken.text(s__('EmailToken|reset it'));
})
.catch(() => {
flash(__('There was an error when reseting email token.'));
- $resetToken.text('reset it');
+ $resetToken.text(s__('EmailToken|reset it'));
});
});
}
diff --git a/app/assets/javascripts/issue.js b/app/assets/javascripts/issue.js
index cd1afb6ba83..db4607ca58d 100644
--- a/app/assets/javascripts/issue.js
+++ b/app/assets/javascripts/issue.js
@@ -7,6 +7,7 @@ import flash from './flash';
import TaskList from './task_list';
import CreateMergeRequestDropdown from './create_merge_request_dropdown';
import IssuablesHelper from './helpers/issuables_helper';
+import { __ } from './locale';
export default class Issue {
constructor() {
@@ -44,7 +45,11 @@ export default class Issue {
* @param {Array} data
* @param {String} issueFailMessage
*/
- updateTopState(isClosed, data, issueFailMessage = 'Unable to update this issue at this time.') {
+ updateTopState(
+ isClosed,
+ data,
+ issueFailMessage = __('Unable to update this issue at this time.'),
+ ) {
if ('id' in data) {
const isClosedBadge = $('div.status-box-issue-closed');
const isOpenBadge = $('div.status-box-open');
@@ -81,7 +86,7 @@ export default class Issue {
}
initIssueBtnEventListeners() {
- const issueFailMessage = 'Unable to update this issue at this time.';
+ const issueFailMessage = __('Unable to update this issue at this time.');
return $(document).on(
'click',
@@ -152,6 +157,6 @@ export default class Issue {
$container.html(data.html);
}
})
- .catch(() => flash('Failed to load related branches'));
+ .catch(() => flash(__('Failed to load related branches')));
}
}
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
index ab0b4231255..e88ca4747c5 100644
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ b/app/assets/javascripts/issue_show/components/app.vue
@@ -156,7 +156,7 @@ export default {
return this.store.formState;
},
hasUpdated() {
- return !!this.state.updatedAt;
+ return Boolean(this.state.updatedAt);
},
issueChanged() {
const {
diff --git a/app/assets/javascripts/issue_show/components/description.vue b/app/assets/javascripts/issue_show/components/description.vue
index 385e9543973..f2462e50093 100644
--- a/app/assets/javascripts/issue_show/components/description.vue
+++ b/app/assets/javascripts/issue_show/components/description.vue
@@ -149,6 +149,7 @@ export default {
v-model="descriptionText"
:data-update-url="updateUrl"
class="hidden js-task-list-field"
+ dir="auto"
>
</textarea>
diff --git a/app/assets/javascripts/issue_show/components/fields/description.vue b/app/assets/javascripts/issue_show/components/fields/description.vue
index 299130e56ae..d27dd873125 100644
--- a/app/assets/javascripts/issue_show/components/fields/description.vue
+++ b/app/assets/javascripts/issue_show/components/fields/description.vue
@@ -53,6 +53,7 @@ export default {
v-model="formState.description"
class="note-textarea js-gfm-input js-autosize markdown-area
qa-description-textarea"
+ dir="auto"
data-supports-quick-actions="false"
aria-label="Description"
placeholder="Write a comment or drag your files here…"
diff --git a/app/assets/javascripts/issue_show/components/fields/title.vue b/app/assets/javascripts/issue_show/components/fields/title.vue
index a3371cb9614..ce4baf17d09 100644
--- a/app/assets/javascripts/issue_show/components/fields/title.vue
+++ b/app/assets/javascripts/issue_show/components/fields/title.vue
@@ -20,6 +20,7 @@ export default {
ref="input"
v-model="formState.title"
class="form-control qa-title-input"
+ dir="auto"
type="text"
placeholder="Title"
aria-label="Title"
diff --git a/app/assets/javascripts/issue_show/components/title.vue b/app/assets/javascripts/issue_show/components/title.vue
index 3b5c95ccded..1e1dce5f4fc 100644
--- a/app/assets/javascripts/issue_show/components/title.vue
+++ b/app/assets/javascripts/issue_show/components/title.vue
@@ -71,7 +71,8 @@ export default {
'issue-realtime-pre-pulse': preAnimation,
'issue-realtime-trigger-pulse': pulseAnimation,
}"
- class="title"
+ class="title qa-title"
+ dir="auto"
v-html="titleHtml"
></h2>
<button
diff --git a/app/assets/javascripts/issue_status_select.js b/app/assets/javascripts/issue_status_select.js
index c14803c80e7..75edff41a89 100644
--- a/app/assets/javascripts/issue_status_select.js
+++ b/app/assets/javascripts/issue_status_select.js
@@ -1,4 +1,5 @@
import $ from 'jquery';
+import { __ } from './locale';
export default function issueStatusSelect() {
$('.js-issue-status').each((i, el) => {
@@ -7,7 +8,7 @@ export default function issueStatusSelect() {
selectable: true,
fieldName,
toggleLabel(selected, element, instance) {
- let label = 'Author';
+ let label = __('Author');
const $item = instance.dropdown.find('.is-active');
if ($item.length) {
label = $item.text();
diff --git a/app/assets/javascripts/jobs/components/job_app.vue b/app/assets/javascripts/jobs/components/job_app.vue
index 7594edfac27..79fb67d38cd 100644
--- a/app/assets/javascripts/jobs/components/job_app.vue
+++ b/app/assets/javascripts/jobs/components/job_app.vue
@@ -86,6 +86,7 @@ export default {
'isScrollTopDisabled',
'isScrolledToBottomBeforeReceivingTrace',
'hasError',
+ 'selectedStage',
]),
...mapGetters([
'headerTime',
@@ -121,7 +122,13 @@ export default {
// fetch the stages for the dropdown on the sidebar
job(newVal, oldVal) {
if (_.isEmpty(oldVal) && !_.isEmpty(newVal.pipeline)) {
- this.fetchStages();
+ const stages = this.job.pipeline.details.stages || [];
+
+ const defaultStage = stages.find(stage => stage && stage.name === this.selectedStage);
+
+ if (defaultStage) {
+ this.fetchJobsForStage(defaultStage);
+ }
}
if (newVal.archived) {
@@ -160,7 +167,7 @@ export default {
'setJobEndpoint',
'setTraceOptions',
'fetchJob',
- 'fetchStages',
+ 'fetchJobsForStage',
'hideSidebar',
'showSidebar',
'toggleSidebar',
@@ -269,7 +276,6 @@ export default {
:class="{ 'sticky-top border-bottom-0': hasTrace }"
>
<icon name="lock" class="align-text-bottom" />
-
{{ __('This job is archived. Only the complete pipeline can be retried.') }}
</div>
<!-- job log -->
diff --git a/app/assets/javascripts/jobs/components/sidebar.vue b/app/assets/javascripts/jobs/components/sidebar.vue
index 1691ac62100..24276c06486 100644
--- a/app/assets/javascripts/jobs/components/sidebar.vue
+++ b/app/assets/javascripts/jobs/components/sidebar.vue
@@ -34,7 +34,7 @@ export default {
},
},
computed: {
- ...mapState(['job', 'stages', 'jobs', 'selectedStage', 'isLoadingStages']),
+ ...mapState(['job', 'stages', 'jobs', 'selectedStage']),
coverage() {
return `${this.job.coverage}%`;
},
@@ -208,7 +208,6 @@ export default {
/>
<stages-dropdown
- v-if="!isLoadingStages"
:stages="stages"
:pipeline="job.pipeline"
:selected-stage="selectedStage"
diff --git a/app/assets/javascripts/jobs/components/stages_dropdown.vue b/app/assets/javascripts/jobs/components/stages_dropdown.vue
index 6e92b599b0a..cb073a9b04d 100644
--- a/app/assets/javascripts/jobs/components/stages_dropdown.vue
+++ b/app/assets/javascripts/jobs/components/stages_dropdown.vue
@@ -2,6 +2,7 @@
import _ from 'underscore';
import { GlLink } from '@gitlab/ui';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import PipelineLink from '~/vue_shared/components/ci_pipeline_link.vue';
import Icon from '~/vue_shared/components/icon.vue';
export default {
@@ -9,6 +10,7 @@ export default {
CiIcon,
Icon,
GlLink,
+ PipelineLink,
},
props: {
pipeline: {
@@ -48,9 +50,12 @@ export default {
<ci-icon :status="pipeline.details.status" class="vertical-align-middle" />
<span class="font-weight-bold">{{ s__('Job|Pipeline') }}</span>
- <gl-link :href="pipeline.path" class="js-pipeline-path link-commit qa-pipeline-path"
- >#{{ pipeline.id }}</gl-link
- >
+ <pipeline-link
+ :href="pipeline.path"
+ :pipeline-id="pipeline.id"
+ :pipeline-iid="pipeline.iid"
+ class="js-pipeline-path link-commit qa-pipeline-path"
+ />
<template v-if="hasRef">
{{ s__('Job|for') }}
diff --git a/app/assets/javascripts/jobs/store/actions.js b/app/assets/javascripts/jobs/store/actions.js
index 8045f6dc3ff..12d67a43599 100644
--- a/app/assets/javascripts/jobs/store/actions.js
+++ b/app/assets/javascripts/jobs/store/actions.js
@@ -179,37 +179,13 @@ export const receiveTraceError = ({ commit }) => {
};
/**
- * Stages dropdown on sidebar
- */
-export const requestStages = ({ commit }) => commit(types.REQUEST_STAGES);
-export const fetchStages = ({ state, dispatch }) => {
- dispatch('requestStages');
-
- axios
- .get(`${state.job.pipeline.path}.json`)
- .then(({ data }) => {
- // Set selected stage
- dispatch('receiveStagesSuccess', data.details.stages);
- const selectedStage = data.details.stages.find(stage => stage.name === state.selectedStage);
- dispatch('fetchJobsForStage', selectedStage);
- })
- .catch(() => dispatch('receiveStagesError'));
-};
-export const receiveStagesSuccess = ({ commit }, data) =>
- commit(types.RECEIVE_STAGES_SUCCESS, data);
-export const receiveStagesError = ({ commit }) => {
- commit(types.RECEIVE_STAGES_ERROR);
- flash(__('An error occurred while fetching stages.'));
-};
-
-/**
* Jobs list on sidebar - depend on stages dropdown
*/
export const requestJobsForStage = ({ commit }, stage) =>
commit(types.REQUEST_JOBS_FOR_STAGE, stage);
// On stage click, set selected stage + fetch job
-export const fetchJobsForStage = ({ dispatch }, stage) => {
+export const fetchJobsForStage = ({ dispatch }, stage = {}) => {
dispatch('requestJobsForStage', stage);
axios
diff --git a/app/assets/javascripts/jobs/store/mutation_types.js b/app/assets/javascripts/jobs/store/mutation_types.js
index fd098f13e90..39146b2eefd 100644
--- a/app/assets/javascripts/jobs/store/mutation_types.js
+++ b/app/assets/javascripts/jobs/store/mutation_types.js
@@ -24,10 +24,6 @@ export const STOP_POLLING_TRACE = 'STOP_POLLING_TRACE';
export const RECEIVE_TRACE_SUCCESS = 'RECEIVE_TRACE_SUCCESS';
export const RECEIVE_TRACE_ERROR = 'RECEIVE_TRACE_ERROR';
-export const REQUEST_STAGES = 'REQUEST_STAGES';
-export const RECEIVE_STAGES_SUCCESS = 'RECEIVE_STAGES_SUCCESS';
-export const RECEIVE_STAGES_ERROR = 'RECEIVE_STAGES_ERROR';
-
export const SET_SELECTED_STAGE = 'SET_SELECTED_STAGE';
export const REQUEST_JOBS_FOR_STAGE = 'REQUEST_JOBS_FOR_STAGE';
export const RECEIVE_JOBS_FOR_STAGE_SUCCESS = 'RECEIVE_JOBS_FOR_STAGE_SUCCESS';
diff --git a/app/assets/javascripts/jobs/store/mutations.js b/app/assets/javascripts/jobs/store/mutations.js
index cd440d21c1f..ad08f27b147 100644
--- a/app/assets/javascripts/jobs/store/mutations.js
+++ b/app/assets/javascripts/jobs/store/mutations.js
@@ -65,6 +65,11 @@ export default {
state.isLoading = false;
state.job = job;
+ state.stages =
+ job.pipeline && job.pipeline.details && job.pipeline.details.stages
+ ? job.pipeline.details.stages
+ : [];
+
/**
* We only update it on the first request
* The dropdown can be changed by the user
@@ -101,19 +106,7 @@ export default {
state.isScrolledToBottomBeforeReceivingTrace = toggle;
},
- [types.REQUEST_STAGES](state) {
- state.isLoadingStages = true;
- },
- [types.RECEIVE_STAGES_SUCCESS](state, stages) {
- state.isLoadingStages = false;
- state.stages = stages;
- },
- [types.RECEIVE_STAGES_ERROR](state) {
- state.isLoadingStages = false;
- state.stages = [];
- },
-
- [types.REQUEST_JOBS_FOR_STAGE](state, stage) {
+ [types.REQUEST_JOBS_FOR_STAGE](state, stage = {}) {
state.isLoadingJobs = true;
state.selectedStage = stage.name;
},
diff --git a/app/assets/javascripts/jobs/store/state.js b/app/assets/javascripts/jobs/store/state.js
index 04825187c99..6019214e62c 100644
--- a/app/assets/javascripts/jobs/store/state.js
+++ b/app/assets/javascripts/jobs/store/state.js
@@ -25,7 +25,6 @@ export default () => ({
traceState: null,
// sidebar dropdown & list of jobs
- isLoadingStages: false,
isLoadingJobs: false,
selectedStage: '',
stages: [],
diff --git a/app/assets/javascripts/label_manager.js b/app/assets/javascripts/label_manager.js
index f134a54dd53..7064731a5ea 100644
--- a/app/assets/javascripts/label_manager.js
+++ b/app/assets/javascripts/label_manager.js
@@ -5,22 +5,26 @@ import Sortable from 'sortablejs';
import flash from './flash';
import axios from './lib/utils/axios_utils';
+import { __ } from './locale';
export default class LabelManager {
constructor({ togglePriorityButton, prioritizedLabels, otherLabels } = {}) {
this.togglePriorityButton = togglePriorityButton || $('.js-toggle-priority');
this.prioritizedLabels = prioritizedLabels || $('.js-prioritized-labels');
this.otherLabels = otherLabels || $('.js-other-labels');
- this.errorMessage = 'Unable to update label prioritization at this time';
+ this.errorMessage = __('Unable to update label prioritization at this time');
this.emptyState = document.querySelector('#js-priority-labels-empty-state');
this.$badgeItemTemplate = $('#js-badge-item-template');
- this.sortable = Sortable.create(this.prioritizedLabels.get(0), {
- filter: '.empty-message',
- forceFallback: true,
- fallbackClass: 'is-dragging',
- dataIdAttr: 'data-id',
- onUpdate: this.onPrioritySortUpdate.bind(this),
- });
+
+ if ('sortable' in this.prioritizedLabels.data()) {
+ Sortable.create(this.prioritizedLabels.get(0), {
+ filter: '.empty-message',
+ forceFallback: true,
+ fallbackClass: 'is-dragging',
+ dataIdAttr: 'data-id',
+ onUpdate: this.onPrioritySortUpdate.bind(this),
+ });
+ }
this.bindEvents();
}
@@ -49,7 +53,7 @@ export default class LabelManager {
toggleEmptyState($label, $btn, action) {
this.emptyState.classList.toggle(
'hidden',
- !!this.prioritizedLabels[0].querySelector(':scope > li'),
+ Boolean(this.prioritizedLabels[0].querySelector(':scope > li')),
);
}
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js
index 2c30b4ea587..3f954b43ee3 100644
--- a/app/assets/javascripts/labels_select.js
+++ b/app/assets/javascripts/labels_select.js
@@ -4,7 +4,7 @@
import $ from 'jquery';
import _ from 'underscore';
-import { sprintf, __ } from './locale';
+import { sprintf, s__, __ } from './locale';
import axios from './lib/utils/axios_utils';
import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
import CreateLabelDropdown from './create_label';
@@ -178,7 +178,7 @@ export default class LabelsSelect {
});
}
} else {
- template = '<span class="no-value">None</span>';
+ template = `<span class="no-value">${__('None')}</span>`;
}
$value.removeAttr('style').html(template);
$sidebarCollapsedValue.text(labelCount);
@@ -190,7 +190,9 @@ export default class LabelsSelect {
if (labelTitles.length > 5) {
labelTitles = labelTitles.slice(0, 5);
- labelTitles.push('and ' + (data.labels.length - 5) + ' more');
+ labelTitles.push(
+ sprintf(s__('Labels|and %{count} more'), { count: data.labels.length - 5 }),
+ );
}
labelTooltipTitle = labelTitles.join(', ');
@@ -219,13 +221,13 @@ export default class LabelsSelect {
if (showNo) {
extraData.unshift({
id: 0,
- title: 'No Label',
+ title: __('No Label'),
});
}
if (showAny) {
extraData.unshift({
isAny: true,
- title: 'Any Label',
+ title: __('Any Label'),
});
}
if (extraData.length) {
@@ -341,7 +343,7 @@ export default class LabelsSelect {
if (selected && selected.id === 0) {
this.selected = [];
- return 'No Label';
+ return __('No Label');
} else if (isSelected) {
this.selected.push(title);
} else if (!isSelected && title) {
@@ -579,7 +581,7 @@ export default class LabelsSelect {
if ($('.selected-issuable:checked').length) {
return;
}
- return $('.issues-bulk-update .labels-filter .dropdown-toggle-text').text('Label');
+ return $('.issues-bulk-update .labels-filter .dropdown-toggle-text').text(__('Label'));
}
// eslint-disable-next-line class-methods-use-this
enableBulkLabelDropdown() {
diff --git a/app/assets/javascripts/lib/graphql.js b/app/assets/javascripts/lib/graphql.js
index ae02559415c..5857f9e22ae 100644
--- a/app/assets/javascripts/lib/graphql.js
+++ b/app/assets/javascripts/lib/graphql.js
@@ -1,16 +1,32 @@
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { createUploadLink } from 'apollo-upload-client';
+import { ApolloLink } from 'apollo-link';
+import { BatchHttpLink } from 'apollo-link-batch-http';
import csrf from '~/lib/utils/csrf';
-export default (resolvers = {}) =>
- new ApolloClient({
- link: createUploadLink({
- uri: `${gon.relative_url_root}/api/graphql`,
- headers: {
- [csrf.headerKey]: csrf.token,
- },
- }),
- cache: new InMemoryCache(),
+export default (resolvers = {}, config = {}) => {
+ let uri = `${gon.relative_url_root}/api/graphql`;
+
+ if (config.baseUrl) {
+ // Prepend baseUrl and ensure that `///` are replaced with `/`
+ uri = `${config.baseUrl}${uri}`.replace(/\/{3,}/g, '/');
+ }
+
+ const httpOptions = {
+ uri,
+ headers: {
+ [csrf.headerKey]: csrf.token,
+ },
+ };
+
+ return new ApolloClient({
+ link: ApolloLink.split(
+ operation => operation.getContext().hasUpload,
+ createUploadLink(httpOptions),
+ new BatchHttpLink(httpOptions),
+ ),
+ cache: new InMemoryCache(config.cacheConfig),
resolvers,
});
+};
diff --git a/app/assets/javascripts/lib/utils/accessor.js b/app/assets/javascripts/lib/utils/accessor.js
index 1d18992af63..39cffedcac6 100644
--- a/app/assets/javascripts/lib/utils/accessor.js
+++ b/app/assets/javascripts/lib/utils/accessor.js
@@ -2,7 +2,7 @@ function isPropertyAccessSafe(base, property) {
let safe;
try {
- safe = !!base[property];
+ safe = Boolean(base[property]);
} catch (error) {
safe = false;
}
diff --git a/app/assets/javascripts/lib/utils/autosave.js b/app/assets/javascripts/lib/utils/autosave.js
index 023c336db02..37896626053 100644
--- a/app/assets/javascripts/lib/utils/autosave.js
+++ b/app/assets/javascripts/lib/utils/autosave.js
@@ -29,4 +29,5 @@ export const updateDraft = (autosaveKey, text) => {
};
export const getDiscussionReplyKey = (noteableType, discussionId) =>
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
['Note', capitalizeFirstCharacter(noteableType), discussionId, 'Reply'].join('/');
diff --git a/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js b/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js
index a24c71aeab1..28a7ebfdc69 100644
--- a/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js
+++ b/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js
@@ -51,6 +51,7 @@ export default class LinkedTabs {
this.defaultAction = this.options.defaultAction;
this.action = this.options.action || this.defaultAction;
+ this.hashedTabs = this.options.hashedTabs || false;
if (this.action === 'show') {
this.action = this.defaultAction;
@@ -58,6 +59,10 @@ export default class LinkedTabs {
this.currentLocation = window.location;
+ if (this.hashedTabs) {
+ this.action = this.currentLocation.hash || this.action;
+ }
+
const tabSelector = `${this.options.parentEl} a[data-toggle="tab"]`;
// since this is a custom event we need jQuery :(
@@ -91,7 +96,9 @@ export default class LinkedTabs {
copySource.replace(/\/+$/, '');
- const newState = `${copySource}${this.currentLocation.search}${this.currentLocation.hash}`;
+ const newState = this.hashedTabs
+ ? copySource
+ : `${copySource}${this.currentLocation.search}${this.currentLocation.hash}`;
window.history.replaceState(
{
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index b236daff1e0..cc5e12aa467 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -94,6 +94,8 @@ export const handleLocationHash = () => {
const fixedNav = document.querySelector('.navbar-gitlab');
const performanceBar = document.querySelector('#js-peek');
const topPadding = 8;
+ const diffFileHeader = document.querySelector('.js-file-title');
+ const versionMenusContainer = document.querySelector('.mr-version-menus-container');
let adjustment = 0;
if (fixedNav) adjustment -= fixedNav.offsetHeight;
@@ -114,6 +116,14 @@ export const handleLocationHash = () => {
adjustment -= performanceBar.offsetHeight;
}
+ if (diffFileHeader) {
+ adjustment -= diffFileHeader.offsetHeight;
+ }
+
+ if (versionMenusContainer) {
+ adjustment -= versionMenusContainer.offsetHeight;
+ }
+
if (isInMRPage()) {
adjustment -= topPadding;
}
diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js
index 4d6327840db..d521c462ad8 100644
--- a/app/assets/javascripts/lib/utils/datetime_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime_utility.js
@@ -3,7 +3,7 @@ import _ from 'underscore';
import timeago from 'timeago.js';
import dateFormat from 'dateformat';
import { pluralize } from './text_utility';
-import { languageCode, s__ } from '../../locale';
+import { languageCode, s__, __ } from '../../locale';
window.timeago = timeago;
@@ -63,7 +63,15 @@ export const pad = (val, len = 2) => `0${val}`.slice(-len);
* @returns {String}
*/
export const getDayName = date =>
- ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][date.getDay()];
+ [
+ __('Sunday'),
+ __('Monday'),
+ __('Tuesday'),
+ __('Wednesday'),
+ __('Thursday'),
+ __('Friday'),
+ __('Saturday'),
+ ][date.getDay()];
/**
* @example
@@ -71,7 +79,12 @@ export const getDayName = date =>
* @param {date} datetime
* @returns {String}
*/
-export const formatDate = datetime => dateFormat(datetime, 'mmm d, yyyy h:MMtt Z');
+export const formatDate = datetime => {
+ if (_.isString(datetime) && datetime.match(/\d+-\d+\d+ /)) {
+ throw new Error(__('Invalid date'));
+ }
+ return dateFormat(datetime, 'mmm d, yyyy h:MMtt Z');
+};
/**
* Timeago uses underscores instead of dashes to separate language from country code.
@@ -320,13 +333,13 @@ export const getSundays = date => {
}
const daysToSunday = [
- 'Saturday',
- 'Friday',
- 'Thursday',
- 'Wednesday',
- 'Tuesday',
- 'Monday',
- 'Sunday',
+ __('Saturday'),
+ __('Friday'),
+ __('Thursday'),
+ __('Wednesday'),
+ __('Tuesday'),
+ __('Monday'),
+ __('Sunday'),
];
const month = date.getMonth();
@@ -336,7 +349,7 @@ export const getSundays = date => {
while (dateOfMonth.getMonth() === month) {
const dayName = getDayName(dateOfMonth);
- if (dayName === 'Sunday') {
+ if (dayName === __('Sunday')) {
sundays.push(new Date(dateOfMonth.getTime()));
}
@@ -500,7 +513,7 @@ export const stringifyTime = (timeObject, fullNameFormat = false) => {
const reducedTime = _.reduce(
timeObject,
(memo, unitValue, unitName) => {
- const isNonZero = !!unitValue;
+ const isNonZero = Boolean(unitValue);
if (fullNameFormat && isNonZero) {
// Remove traling 's' if unit value is singular
diff --git a/app/assets/javascripts/lib/utils/highlight.js b/app/assets/javascripts/lib/utils/highlight.js
index 4f7eff2cca1..8f0afa3467d 100644
--- a/app/assets/javascripts/lib/utils/highlight.js
+++ b/app/assets/javascripts/lib/utils/highlight.js
@@ -27,14 +27,14 @@ export default function highlight(string, match = '', matchPrefix = '<b>', match
const sanitizedValue = sanitize(string.toString(), { allowedTags: [] });
- // occurences is an array of character indices that should be
+ // occurrences is an array of character indices that should be
// highlighted in the original string, i.e. [3, 4, 5, 7]
- const occurences = fuzzaldrinPlus.match(sanitizedValue, match.toString());
+ const occurrences = fuzzaldrinPlus.match(sanitizedValue, match.toString());
return sanitizedValue
.split('')
.map((character, i) => {
- if (_.contains(occurences, i)) {
+ if (_.contains(occurrences, i)) {
return `${matchPrefix}${character}${matchSuffix}`;
}
diff --git a/app/assets/javascripts/lib/utils/invalid_url.js b/app/assets/javascripts/lib/utils/invalid_url.js
new file mode 100644
index 00000000000..481bd059fc9
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/invalid_url.js
@@ -0,0 +1,6 @@
+/**
+ * Invalid URL that ensures we don't make a network request
+ * Can be used as a default value for URLs. Using an empty
+ * string can still result in request being made to the current page
+ */
+export default 'https://invalid';
diff --git a/app/assets/javascripts/lib/utils/notify.js b/app/assets/javascripts/lib/utils/notify.js
index d93873e0214..e7f6255e5f1 100644
--- a/app/assets/javascripts/lib/utils/notify.js
+++ b/app/assets/javascripts/lib/utils/notify.js
@@ -12,6 +12,7 @@ function notificationGranted(message, opts, onclick) {
}
function notifyPermissions() {
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
if ('Notification' in window) {
return Notification.requestPermission();
}
@@ -24,6 +25,7 @@ function notifyMe(message, body, icon, onclick) {
icon: icon,
};
// Let's check if the browser supports notifications
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
if (!('Notification' in window)) {
// do nothing
} else if (Notification.permission === 'granted') {
diff --git a/app/assets/javascripts/lib/utils/number_utils.js b/app/assets/javascripts/lib/utils/number_utils.js
index 19c4de6083d..61c8b8803d7 100644
--- a/app/assets/javascripts/lib/utils/number_utils.js
+++ b/app/assets/javascripts/lib/utils/number_utils.js
@@ -1,4 +1,5 @@
import { BYTES_IN_KIB } from './constants';
+import { sprintf, __ } from '~/locale';
/**
* Function that allows a number with an X amount of decimals
@@ -72,13 +73,13 @@ export function bytesToGiB(number) {
*/
export function numberToHumanSize(size) {
if (size < BYTES_IN_KIB) {
- return `${size} bytes`;
+ return sprintf(__('%{size} bytes'), { size });
} else if (size < BYTES_IN_KIB * BYTES_IN_KIB) {
- return `${bytesToKiB(size).toFixed(2)} KiB`;
+ return sprintf(__('%{size} KiB'), { size: bytesToKiB(size).toFixed(2) });
} else if (size < BYTES_IN_KIB * BYTES_IN_KIB * BYTES_IN_KIB) {
- return `${bytesToMiB(size).toFixed(2)} MiB`;
+ return sprintf(__('%{size} MiB'), { size: bytesToMiB(size).toFixed(2) });
}
- return `${bytesToGiB(size).toFixed(2)} GiB`;
+ return sprintf(__('%{size} GiB'), { size: bytesToGiB(size).toFixed(2) });
}
/**
@@ -99,3 +100,9 @@ export function numberToHumanSize(size) {
* @returns {Float} The summed value
*/
export const sum = (a = 0, b = 0) => a + b;
+
+/**
+ * Checks if the provided number is odd
+ * @param {Int} number
+ */
+export const isOdd = (number = 0) => number % 2;
diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js
index 84a617acb42..b7922e29bb0 100644
--- a/app/assets/javascripts/lib/utils/text_markdown.js
+++ b/app/assets/javascripts/lib/utils/text_markdown.js
@@ -223,9 +223,9 @@ export function insertMarkdownText({
return tag.replace(textPlaceholder, val);
}
if (val.indexOf(tag) === 0) {
- return '' + val.replace(tag, '');
+ return String(val.replace(tag, ''));
} else {
- return '' + tag + val;
+ return String(tag) + val;
}
})
.join('\n');
@@ -233,7 +233,7 @@ export function insertMarkdownText({
} else if (tag.indexOf(textPlaceholder) > -1) {
textToInsert = tag.replace(textPlaceholder, selected);
} else {
- textToInsert = '' + startChar + tag + selected + (wrap ? tag : ' ');
+ textToInsert = String(startChar) + tag + selected + (wrap ? tag : ' ');
}
if (removedFirstNewLine) {
diff --git a/app/assets/javascripts/lib/utils/url_utility.js b/app/assets/javascripts/lib/utils/url_utility.js
index 4ba84589705..32fd0990374 100644
--- a/app/assets/javascripts/lib/utils/url_utility.js
+++ b/app/assets/javascripts/lib/utils/url_utility.js
@@ -1,3 +1,5 @@
+import { join as joinPaths } from 'path';
+
// Returns an array containing the value(s) of the
// of the key passed as an argument
export function getParameterValues(sParam) {
@@ -120,3 +122,49 @@ export function webIDEUrl(route = undefined) {
}
return returnUrl;
}
+
+/**
+ * Returns current base URL
+ */
+export function getBaseURL() {
+ const { protocol, host } = window.location;
+ return `${protocol}//${host}`;
+}
+
+/**
+ * Returns true if url is an absolute or root-relative URL
+ *
+ * @param {String} url
+ */
+export function isAbsoluteOrRootRelative(url) {
+ return /^(https?:)?\//.test(url);
+}
+
+/**
+ * Checks if the provided URL is a safe URL (absolute http(s) or root-relative URL)
+ *
+ * @param {String} url that will be checked
+ * @returns {Boolean}
+ */
+export function isSafeURL(url) {
+ if (!isAbsoluteOrRootRelative(url)) {
+ return false;
+ }
+
+ try {
+ const parsedUrl = new URL(url, getBaseURL());
+ return ['http:', 'https:'].includes(parsedUrl.protocol);
+ } catch (e) {
+ return false;
+ }
+}
+
+export function getWebSocketProtocol() {
+ return window.location.protocol.replace('http', 'ws');
+}
+
+export function getWebSocketUrl(path) {
+ return `${getWebSocketProtocol()}//${joinPaths(window.location.host, path)}`;
+}
+
+export { joinPaths };
diff --git a/app/assets/javascripts/lib/utils/webpack.js b/app/assets/javascripts/lib/utils/webpack.js
index 37b5409a51d..37b17f0fe23 100644
--- a/app/assets/javascripts/lib/utils/webpack.js
+++ b/app/assets/javascripts/lib/utils/webpack.js
@@ -1,3 +1,5 @@
+import { joinPaths } from '~/lib/utils/url_utility';
+
// tell webpack to load assets from origin so that web workers don't break
// eslint-disable-next-line import/prefer-default-export
export function resetServiceWorkersPublicPath() {
@@ -5,7 +7,7 @@ export function resetServiceWorkersPublicPath() {
// the webpack publicPath setting at runtime.
// see: https://webpack.js.org/guides/public-path/
const relativeRootPath = (gon && gon.relative_url_root) || '';
- const webpackAssetPath = `${relativeRootPath}/assets/webpack/`;
+ const webpackAssetPath = joinPaths(relativeRootPath, '/assets/webpack/');
__webpack_public_path__ = webpackAssetPath; // eslint-disable-line camelcase
// monaco-editor-webpack-plugin currently (incorrectly) references the
diff --git a/app/assets/javascripts/locale/index.js b/app/assets/javascripts/locale/index.js
index 1ae3362c4bc..41aa0f4ddb9 100644
--- a/app/assets/javascripts/locale/index.js
+++ b/app/assets/javascripts/locale/index.js
@@ -11,7 +11,7 @@ delete window.translations;
@param text The text to be translated
@returns {String} The translated text
*/
-const gettext = text => locale.gettext.bind(locale)(ensureSingleLine(text));
+const gettext = text => locale.gettext(ensureSingleLine(text));
/**
Translate the text with a number
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 1b722c0505a..9f30a989295 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -31,6 +31,7 @@ import initPerformanceBar from './performance_bar';
import initSearchAutocomplete from './search_autocomplete';
import GlFieldErrors from './gl_field_errors';
import initUserPopovers from './user_popovers';
+import { __ } from './locale';
// expose jQuery as global (TODO: remove these)
window.jQuery = jQuery;
@@ -135,6 +136,24 @@ function deferredInitialisation() {
});
loadAwardsHandler();
+
+ /**
+ * Toggle Canary Badge
+ *
+ * For GitLab.com only, when the user is using canary
+ * we render a Next badge and hide the option to switch
+ * to canay
+ */
+ if (Cookies.get('gitlab_canary') && Cookies.get('gitlab_canary') === 'true') {
+ const canaryBadge = document.querySelector('.js-canary-badge');
+ const canaryLink = document.querySelector('.js-canary-link');
+ if (canaryBadge) {
+ canaryBadge.classList.remove('hidden');
+ }
+ if (canaryLink) {
+ canaryLink.classList.add('hidden');
+ }
+ }
}
document.addEventListener('DOMContentLoaded', () => {
@@ -201,9 +220,9 @@ document.addEventListener('DOMContentLoaded', () => {
const ref = xhrObj.status;
if (ref === 401) {
- Flash('You need to be logged in.');
+ Flash(__('You need to be logged in.'));
} else if (ref === 404 || ref === 500) {
- Flash('Something went wrong on our end.');
+ Flash(__('Something went wrong on our end.'));
}
});
diff --git a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
index 0333335de06..88bc0940741 100644
--- a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
+++ b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
@@ -3,15 +3,16 @@
import $ from 'jquery';
import Vue from 'vue';
import Cookies from 'js-cookie';
+import { s__ } from '~/locale';
(global => {
global.mergeConflicts = global.mergeConflicts || {};
const diffViewType = Cookies.get('diff_view');
- const HEAD_HEADER_TEXT = 'HEAD//our changes';
- const ORIGIN_HEADER_TEXT = 'origin//their changes';
- const HEAD_BUTTON_TITLE = 'Use ours';
- const ORIGIN_BUTTON_TITLE = 'Use theirs';
+ const HEAD_HEADER_TEXT = s__('MergeConflict|HEAD//our changes');
+ const ORIGIN_HEADER_TEXT = s__('MergeConflict|origin//their changes');
+ const HEAD_BUTTON_TITLE = s__('MergeConflict|Use ours');
+ const ORIGIN_BUTTON_TITLE = s__('MergeConflict|Use theirs');
const INTERACTIVE_RESOLVE_MODE = 'interactive';
const EDIT_RESOLVE_MODE = 'edit';
const DEFAULT_RESOLVE_MODE = INTERACTIVE_RESOLVE_MODE;
@@ -173,7 +174,7 @@ import Cookies from 'js-cookie';
getConflictsCountText() {
const count = this.getConflictsCount();
- const text = count > 1 ? 'conflicts' : 'conflict';
+ const text = count > 1 ? s__('MergeConflict|conflicts') : s__('MergeConflict|conflict');
return `${count} ${text}`;
},
@@ -348,8 +349,8 @@ import Cookies from 'js-cookie';
},
getCommitButtonText() {
- const initial = 'Commit to source branch';
- const inProgress = 'Committing...';
+ const initial = s__('MergeConflict|Commit to source branch');
+ const inProgress = s__('MergeConflict|Committing...');
return this.state ? (this.state.isSubmitting ? inProgress : initial) : initial;
},
diff --git a/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js b/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
index 7badd68089c..d8d203e0616 100644
--- a/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
+++ b/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
@@ -8,6 +8,7 @@ import './components/diff_file_editor';
import './components/inline_conflict_lines';
import './components/parallel_conflict_lines';
import syntaxHighlight from '../syntax_highlight';
+import { __ } from '~/locale';
export default function initMergeConflicts() {
const INTERACTIVE_RESOLVE_MODE = 'interactive';
@@ -92,7 +93,7 @@ export default function initMergeConflicts() {
})
.catch(() => {
mergeConflictsStore.setSubmitState(false);
- createFlash('Failed to save merge conflicts resolutions. Please try again!');
+ createFlash(__('Failed to save merge conflicts resolutions. Please try again!'));
});
},
},
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index 509f19e6f00..e5cf43e8289 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -21,6 +21,7 @@ import { localTimeAgo } from './lib/utils/datetime_utility';
import syntaxHighlight from './syntax_highlight';
import Notes from './notes';
import { polyfillSticky } from './lib/utils/sticky';
+import { __ } from './locale';
// MergeRequestTabs
//
@@ -326,7 +327,7 @@ export default class MergeRequestTabs {
})
.catch(() => {
this.toggleLoading(false);
- flash('An error occurred while fetching this tab.');
+ flash(__('An error occurred while fetching this tab.'));
});
}
@@ -416,7 +417,7 @@ export default class MergeRequestTabs {
})
.catch(() => {
this.toggleLoading(false);
- flash('An error occurred while fetching this tab.');
+ flash(__('An error occurred while fetching this tab.'));
});
}
diff --git a/app/assets/javascripts/milestone.js b/app/assets/javascripts/milestone.js
index f211632cf24..6aaba4e7c74 100644
--- a/app/assets/javascripts/milestone.js
+++ b/app/assets/javascripts/milestone.js
@@ -2,6 +2,7 @@ import $ from 'jquery';
import axios from './lib/utils/axios_utils';
import flash from './flash';
import { mouseenter, debouncedMouseleave, togglePopover } from './shared/popover';
+import { __ } from './locale';
export default class Milestone {
constructor() {
@@ -42,7 +43,7 @@ export default class Milestone {
$(tabElId).html(data.html);
$target.addClass('is-loaded');
})
- .catch(() => flash('Error loading milestone tab'));
+ .catch(() => flash(__('Error loading milestone tab')));
}
}
diff --git a/app/assets/javascripts/milestone_select.js b/app/assets/javascripts/milestone_select.js
index 75c18a9b6a0..43949d5cc86 100644
--- a/app/assets/javascripts/milestone_select.js
+++ b/app/assets/javascripts/milestone_select.js
@@ -56,14 +56,15 @@ export default class MilestoneSelect {
const $value = $block.find('.value');
const $loading = $block.find('.block-loading').fadeOut();
selectedMilestoneDefault = showAny ? '' : null;
- selectedMilestoneDefault = showNo && defaultNo ? 'No Milestone' : selectedMilestoneDefault;
+ selectedMilestoneDefault =
+ showNo && defaultNo ? __('No Milestone') : selectedMilestoneDefault;
selectedMilestone = $dropdown.data('selected') || selectedMilestoneDefault;
if (issueUpdateURL) {
milestoneLinkTemplate = _.template(
'<a href="<%- web_url %>" class="bold has-tooltip" data-container="body" title="<%- remaining %>"><%- title %></a>',
);
- milestoneLinkNoneTemplate = '<span class="no-value">None</span>';
+ milestoneLinkNoneTemplate = `<span class="no-value">${__('None')}</span>`;
}
return $dropdown.glDropdown({
showMenuAbove: showMenuAbove,
@@ -74,28 +75,28 @@ export default class MilestoneSelect {
extraOptions.push({
id: null,
name: null,
- title: 'Any Milestone',
+ title: __('Any Milestone'),
});
}
if (showNo) {
extraOptions.push({
id: -1,
- name: 'No Milestone',
- title: 'No Milestone',
+ name: __('No Milestone'),
+ title: __('No Milestone'),
});
}
if (showUpcoming) {
extraOptions.push({
id: -2,
name: '#upcoming',
- title: 'Upcoming',
+ title: __('Upcoming'),
});
}
if (showStarted) {
extraOptions.push({
id: -3,
name: '#started',
- title: 'Started',
+ title: __('Started'),
});
}
if (extraOptions.length) {
diff --git a/app/assets/javascripts/mini_pipeline_graph_dropdown.js b/app/assets/javascripts/mini_pipeline_graph_dropdown.js
index 81ab9d8be4b..b39ad764f01 100644
--- a/app/assets/javascripts/mini_pipeline_graph_dropdown.js
+++ b/app/assets/javascripts/mini_pipeline_graph_dropdown.js
@@ -1,6 +1,7 @@
import $ from 'jquery';
import flash from './flash';
import axios from './lib/utils/axios_utils';
+import { __ } from './locale';
/**
* In each pipelines table we have a mini pipeline graph for each pipeline.
@@ -98,7 +99,7 @@ export default class MiniPipelineGraph {
) {
$(button).dropdown('toggle');
}
- flash('An error occurred while fetching the builds.', 'alert');
+ flash(__('An error occurred while fetching the builds.'), 'alert');
});
}
diff --git a/app/assets/javascripts/mirrors/mirror_repos.js b/app/assets/javascripts/mirrors/mirror_repos.js
index 196b84621b6..33e9b1c4e46 100644
--- a/app/assets/javascripts/mirrors/mirror_repos.js
+++ b/app/assets/javascripts/mirrors/mirror_repos.js
@@ -87,7 +87,7 @@ export default class MirrorRepos {
project: {
remote_mirrors_attributes: {
id: $target.data('mirrorId'),
- enabled: 0,
+ _destroy: 1,
},
},
};
diff --git a/app/assets/javascripts/mirrors/ssh_mirror.js b/app/assets/javascripts/mirrors/ssh_mirror.js
index 547c078ec55..bb5ae6ce2d1 100644
--- a/app/assets/javascripts/mirrors/ssh_mirror.js
+++ b/app/assets/javascripts/mirrors/ssh_mirror.js
@@ -24,12 +24,6 @@ export default class SSHMirror {
this.$wellAuthTypeChanging = this.$form.find('.js-well-changing-auth');
this.$wellPasswordAuth = this.$form.find('.js-well-password-auth');
- this.$wellSSHAuth = this.$form.find('.js-well-ssh-auth');
- this.$sshPublicKeyWrap = this.$form.find('.js-ssh-public-key-wrap');
- this.$regeneratePublicSshKeyButton = this.$wellSSHAuth.find('.js-btn-regenerate-ssh-key');
- this.$regeneratePublicSshKeyModal = this.$wellSSHAuth.find(
- '.js-regenerate-public-ssh-key-confirm-modal',
- );
}
init() {
@@ -40,15 +34,6 @@ export default class SSHMirror {
this.$dropdownAuthType.on('change', e => this.handleAuthTypeChange(e));
this.$btnDetectHostKeys.on('click', e => this.handleDetectHostKeys(e));
this.$btnSSHHostsShowAdvanced.on('click', e => this.handleSSHHostsAdvanced(e));
- this.$regeneratePublicSshKeyButton.on('click', () =>
- this.$regeneratePublicSshKeyModal.toggle(true),
- );
- $('.js-confirm', this.$regeneratePublicSshKeyModal).on('click', e =>
- this.regeneratePublicSshKey(e),
- );
- $('.js-cancel', this.$regeneratePublicSshKeyModal).on('click', () =>
- this.$regeneratePublicSshKeyModal.toggle(false),
- );
}
/**
@@ -162,54 +147,11 @@ export default class SSHMirror {
* Authentication method dropdown change event listener
*/
handleAuthTypeChange() {
- const projectMirrorAuthTypeEndpoint = `${this.$form.attr('action')}.json`;
- const $sshPublicKey = this.$sshPublicKeyWrap.find('.ssh-public-key');
const selectedAuthType = this.$dropdownAuthType.val();
this.$wellPasswordAuth.collapse('hide');
- this.$wellSSHAuth.collapse('hide');
this.updateHiddenAuthType(selectedAuthType);
-
- // This request should happen only if selected Auth type was SSH
- // and SSH Public key was not present on page load
- if (selectedAuthType === AUTH_METHOD.SSH && !$sshPublicKey.text().trim()) {
- if (!this.$wellSSHAuth.length) return;
-
- // Construct request body
- const authTypeData = {
- project: {
- ...this.$regeneratePublicSshKeyButton.data().projectData,
- },
- };
-
- this.$wellAuthTypeChanging.collapse('show');
- this.$dropdownAuthType.disable();
-
- axios
- .put(projectMirrorAuthTypeEndpoint, JSON.stringify(authTypeData), {
- headers: {
- 'Content-Type': 'application/json; charset=utf-8',
- },
- })
- .then(({ data }) => {
- // Show SSH public key container and fill in public key
- this.toggleAuthWell(selectedAuthType);
- this.toggleSSHAuthWellMessage(true);
- this.setSSHPublicKey(data.import_data_attributes.ssh_public_key);
-
- this.$wellAuthTypeChanging.collapse('hide');
- this.$dropdownAuthType.enable();
- })
- .catch(() => {
- Flash(__('Something went wrong on our end.'));
-
- this.$wellAuthTypeChanging.collapse('hide');
- this.$dropdownAuthType.enable();
- });
- } else {
- this.toggleAuthWell(selectedAuthType);
- this.$wellSSHAuth.find('.js-ssh-public-key-present').collapse('show');
- }
+ this.toggleAuthWell(selectedAuthType);
}
/**
@@ -235,7 +177,6 @@ export default class SSHMirror {
*/
toggleAuthWell(authType) {
this.$wellPasswordAuth.collapse(authType === AUTH_METHOD.PASSWORD ? 'show' : 'hide');
- this.$wellSSHAuth.collapse(authType === AUTH_METHOD.SSH ? 'show' : 'hide');
this.updateHiddenAuthType(authType);
}
@@ -244,64 +185,11 @@ export default class SSHMirror {
this.$hiddenAuthType.prop('disabled', authType === AUTH_METHOD.SSH);
}
- /**
- * Toggle SSH auth information message
- */
- toggleSSHAuthWellMessage(sshKeyPresent) {
- this.$sshPublicKeyWrap.collapse(sshKeyPresent ? 'show' : 'hide');
- this.$wellSSHAuth.find('.js-ssh-public-key-present').collapse(sshKeyPresent ? 'show' : 'hide');
- this.$regeneratePublicSshKeyButton.collapse(sshKeyPresent ? 'show' : 'hide');
- this.$wellSSHAuth.find('.js-ssh-public-key-pending').collapse(sshKeyPresent ? 'hide' : 'show');
- }
-
- /**
- * Sets SSH Public key to Clipboard button and shows it on UI.
- */
- setSSHPublicKey(sshPublicKey) {
- this.$sshPublicKeyWrap.find('.ssh-public-key').text(sshPublicKey);
- this.$sshPublicKeyWrap
- .find('.btn-copy-ssh-public-key')
- .attr('data-clipboard-text', sshPublicKey);
- }
-
- regeneratePublicSshKey(event) {
- event.preventDefault();
-
- this.$regeneratePublicSshKeyModal.toggle(false);
-
- const button = this.$regeneratePublicSshKeyButton;
- const spinner = $('.js-spinner', button);
- const endpoint = button.data('endpoint');
- const authTypeData = {
- project: {
- ...this.$regeneratePublicSshKeyButton.data().projectData,
- },
- };
-
- button.attr('disabled', 'disabled');
- spinner.removeClass('d-none');
-
- axios
- .patch(endpoint, authTypeData)
- .then(({ data }) => {
- button.removeAttr('disabled');
- spinner.addClass('d-none');
-
- this.setSSHPublicKey(data.import_data_attributes.ssh_public_key);
- })
- .catch(() => {
- Flash(_('Unable to regenerate public ssh key.'));
- });
- }
-
destroy() {
this.$repositoryUrl.off('keyup');
this.$form.find('.js-known-hosts').off('keyup');
this.$dropdownAuthType.off('change');
this.$btnDetectHostKeys.off('click');
this.$btnSSHHostsShowAdvanced.off('click');
- this.$regeneratePublicSshKeyButton.off('click');
- $('.js-confirm', this.$regeneratePublicSshKeyModal).off('click');
- $('.js-cancel', this.$regeneratePublicSshKeyModal).off('click');
}
}
diff --git a/app/assets/javascripts/monitoring/components/charts/area.vue b/app/assets/javascripts/monitoring/components/charts/area.vue
index afe8d87a8d6..9de4e96e4da 100644
--- a/app/assets/javascripts/monitoring/components/charts/area.vue
+++ b/app/assets/javascripts/monitoring/components/charts/area.vue
@@ -1,7 +1,7 @@
<script>
import { GlAreaChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts';
import dateFormat from 'dateformat';
-import { debounceByAnimationFrame } from '~/lib/utils/common_utils';
+import { debounceByAnimationFrame, roundOffFloat } from '~/lib/utils/common_utils';
import { getSvgIconPathContent } from '~/lib/utils/icon_utils';
import Icon from '~/vue_shared/components/icon.vue';
import { chartHeight, graphTypes, lineTypes } from '../../constants';
@@ -111,7 +111,7 @@ export default {
yAxis: {
name: this.yAxisLabel,
axisLabel: {
- formatter: value => value.toFixed(3),
+ formatter: num => roundOffFloat(num, 3).toString(),
},
},
series: this.scatterSeries,
@@ -125,17 +125,17 @@ export default {
},
earliestDatapoint() {
return this.chartData.reduce((acc, series) => {
- if (!series.data.length) {
+ const { data } = series;
+ const { length } = data;
+ if (!length) {
return acc;
}
- const [[timestamp]] = series.data.sort(([a], [b]) => {
- if (a < b) {
- return -1;
- }
- return a > b ? 1 : 0;
- });
- return timestamp < acc || acc === null ? timestamp : acc;
+ const [first] = data[0];
+ const [last] = data[length - 1];
+ const seriesEarliest = first < last ? first : last;
+
+ return seriesEarliest < acc || acc === null ? seriesEarliest : acc;
}, null);
},
isMultiSeries() {
@@ -227,6 +227,7 @@ export default {
[this.primaryColor] = chart.getOption().color;
},
onResize() {
+ if (!this.$refs.areaChart) return;
const { width } = this.$refs.areaChart.$el.getBoundingClientRect();
this.width = width;
},
diff --git a/app/assets/javascripts/monitoring/components/charts/single_stat.vue b/app/assets/javascripts/monitoring/components/charts/single_stat.vue
new file mode 100644
index 00000000000..b03a6ca1806
--- /dev/null
+++ b/app/assets/javascripts/monitoring/components/charts/single_stat.vue
@@ -0,0 +1,37 @@
+<script>
+import { GlSingleStat } from '@gitlab/ui/dist/charts';
+
+export default {
+ components: {
+ GlSingleStat,
+ },
+ inheritAttrs: false,
+ props: {
+ title: {
+ type: String,
+ required: true,
+ },
+ value: {
+ type: Number,
+ required: true,
+ },
+ unit: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ valueWithUnit() {
+ return `${this.value}${this.unit}`;
+ },
+ },
+};
+</script>
+<template>
+ <div class="prometheus-graph col-12 col-lg-6">
+ <div class="prometheus-graph-header">
+ <h5 ref="graphTitle" class="prometheus-graph-title">{{ title }}</h5>
+ </div>
+ <gl-single-stat :value="valueWithUnit" :title="title" variant="success" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index f2bd4150b6d..0a652329dfe 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -1,16 +1,16 @@
<script>
-import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { GlButton, GlDropdown, GlDropdownItem, GlModal, GlModalDirective } from '@gitlab/ui';
import _ from 'underscore';
+import { mapActions, mapState } from 'vuex';
import { s__ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import '~/vue_shared/mixins/is_ee';
-import Flash from '../../flash';
-import MonitoringService from '../services/monitoring_service';
+import { getParameterValues } from '~/lib/utils/url_utility';
+import invalidUrl from '~/lib/utils/invalid_url';
import MonitorAreaChart from './charts/area.vue';
import GraphGroup from './graph_group.vue';
import EmptyState from './empty_state.vue';
-import MonitoringStore from '../stores/monitoring_store';
-import { timeWindows } from '../constants';
+import { timeWindows, timeWindowsKeyNames } from '../constants';
import { getTimeDiff } from '../utils';
const sidebarAnimationDuration = 150;
@@ -22,11 +22,20 @@ export default {
GraphGroup,
EmptyState,
Icon,
+ GlButton,
GlDropdown,
GlDropdownItem,
+ GlModal,
+ },
+ directives: {
+ GlModalDirective,
},
-
props: {
+ externalDashboardUrl: {
+ type: String,
+ required: false,
+ default: '',
+ },
hasMetrics: {
type: Boolean,
required: false,
@@ -61,7 +70,7 @@ export default {
type: String,
required: true,
},
- deploymentEndpoint: {
+ deploymentsEndpoint: {
type: String,
required: false,
default: null,
@@ -90,29 +99,69 @@ export default {
type: String,
required: true,
},
- showTimeWindowDropdown: {
+ customMetricsAvailable: {
type: Boolean,
+ required: false,
+ default: false,
+ },
+ customMetricsPath: {
+ type: String,
required: true,
},
+ validateQueryPath: {
+ type: String,
+ required: true,
+ },
+ dashboardEndpoint: {
+ type: String,
+ required: false,
+ default: invalidUrl,
+ },
},
data() {
return {
- store: new MonitoringStore(),
state: 'gettingStarted',
- showEmptyState: true,
elWidth: 0,
selectedTimeWindow: '',
+ selectedTimeWindowKey: '',
+ formIsValid: null,
};
},
+ computed: {
+ canAddMetrics() {
+ return this.customMetricsAvailable && this.customMetricsPath.length;
+ },
+ ...mapState('monitoringDashboard', [
+ 'groups',
+ 'emptyState',
+ 'showEmptyState',
+ 'environments',
+ 'deploymentData',
+ 'metricsWithData',
+ 'useDashboardEndpoint',
+ ]),
+ groupsWithData() {
+ return this.groups.filter(group => this.chartsWithData(group.metrics).length > 0);
+ },
+ },
created() {
- this.service = new MonitoringService({
+ this.setEndpoints({
metricsEndpoint: this.metricsEndpoint,
- deploymentEndpoint: this.deploymentEndpoint,
environmentsEndpoint: this.environmentsEndpoint,
+ deploymentsEndpoint: this.deploymentsEndpoint,
+ dashboardEndpoint: this.dashboardEndpoint,
});
this.timeWindows = timeWindows;
- this.selectedTimeWindow = this.timeWindows.eightHours;
+ this.selectedTimeWindowKey =
+ _.escape(getParameterValues('time_window')[0]) || timeWindowsKeyNames.eightHours;
+
+ // Set default time window if the selectedTimeWindowKey is bogus
+ if (!Object.keys(this.timeWindows).includes(this.selectedTimeWindowKey)) {
+ this.selectedTimeWindowKey = timeWindowsKeyNames.eightHours;
+ }
+
+ this.selectedTimeWindow = this.timeWindows[this.selectedTimeWindowKey];
},
beforeDestroy() {
if (sidebarMutationObserver) {
@@ -120,30 +169,11 @@ export default {
}
},
mounted() {
- this.servicePromises = [
- this.service
- .getGraphsData()
- .then(data => this.store.storeMetrics(data))
- .catch(() => Flash(s__('Metrics|There was an error while retrieving metrics'))),
- this.service
- .getDeploymentData()
- .then(data => this.store.storeDeploymentData(data))
- .catch(() => Flash(s__('Metrics|There was an error getting deployment information.'))),
- ];
if (!this.hasMetrics) {
- this.state = 'gettingStarted';
+ this.setGettingStartedEmptyState();
} else {
- if (this.environmentsEndpoint) {
- this.servicePromises.push(
- this.service
- .getEnvironmentsData()
- .then(data => this.store.storeEnvironmentsData(data))
- .catch(() =>
- Flash(s__('Metrics|There was an error getting environments information.')),
- ),
- );
- }
- this.getGraphsData();
+ this.fetchData(getTimeDiff(this.selectedTimeWindow));
+
sidebarMutationObserver = new MutationObserver(this.onSidebarMutation);
sidebarMutationObserver.observe(document.querySelector('.layout-page'), {
attributes: true,
@@ -153,6 +183,20 @@ export default {
}
},
methods: {
+ ...mapActions('monitoringDashboard', [
+ 'fetchData',
+ 'setGettingStartedEmptyState',
+ 'setEndpoints',
+ 'setDashboardEnabled',
+ ]),
+ chartsWithData(charts) {
+ if (!this.useDashboardEndpoint) {
+ return charts;
+ }
+ return charts.filter(chart =>
+ chart.metrics.some(metric => this.metricsWithData.includes(metric.metric_id)),
+ );
+ },
getGraphAlerts(queries) {
if (!this.allAlerts) return {};
const metricIdsForChart = queries.map(q => q.metricId);
@@ -161,100 +205,129 @@ export default {
getGraphAlertValues(queries) {
return Object.values(this.getGraphAlerts(queries));
},
- getGraphsData() {
- this.state = 'loading';
- Promise.all(this.servicePromises)
- .then(() => {
- if (this.store.groups.length < 1) {
- this.state = 'noData';
- return;
- }
-
- this.showEmptyState = false;
- })
- .catch(() => {
- this.state = 'unableToConnect';
- });
- },
- getGraphsDataWithTime(timeFrame) {
- this.state = 'loading';
- this.showEmptyState = true;
- this.service
- .getGraphsData(getTimeDiff(this.timeWindows[timeFrame]))
- .then(data => {
- this.store.storeMetrics(data);
- this.selectedTimeWindow = this.timeWindows[timeFrame];
- })
- .catch(() => {
- Flash(s__('Metrics|Not enough data to display'));
- })
- .finally(() => {
- this.showEmptyState = false;
- });
+ hideAddMetricModal() {
+ this.$refs.addMetricModal.hide();
},
onSidebarMutation() {
setTimeout(() => {
this.elWidth = this.$el.clientWidth;
}, sidebarAnimationDuration);
},
+ setFormValidity(isValid) {
+ this.formIsValid = isValid;
+ },
+ submitCustomMetricsForm() {
+ this.$refs.customMetricsForm.submit();
+ },
activeTimeWindow(key) {
return this.timeWindows[key] === this.selectedTimeWindow;
},
+ setTimeWindowParameter(key) {
+ return `?time_window=${key}`;
+ },
+ },
+ addMetric: {
+ title: s__('Metrics|Add metric'),
+ modalId: 'add-metric',
},
};
</script>
<template>
- <div v-if="!showEmptyState" class="prometheus-graphs prepend-top-default">
- <div
- v-if="environmentsEndpoint"
- class="dropdowns d-flex align-items-center justify-content-between"
- >
- <div class="d-flex align-items-center">
- <strong>{{ s__('Metrics|Environment') }}</strong>
- <gl-dropdown
- class="prepend-left-10 js-environments-dropdown"
- toggle-class="dropdown-menu-toggle"
- :text="currentEnvironmentName"
- :disabled="store.environmentsData.length === 0"
- >
- <gl-dropdown-item
- v-for="environment in store.environmentsData"
- :key="environment.id"
- :active="environment.name === currentEnvironmentName"
- active-class="is-active"
- >{{ environment.name }}</gl-dropdown-item
+ <div v-if="!showEmptyState" class="prometheus-graphs">
+ <div class="gl-p-3 border-bottom bg-gray-light d-flex justify-content-between">
+ <div
+ v-if="environmentsEndpoint"
+ class="dropdowns d-flex align-items-center justify-content-between"
+ >
+ <div class="d-flex align-items-center">
+ <strong>{{ s__('Metrics|Environment') }}</strong>
+ <gl-dropdown
+ class="prepend-left-10 js-environments-dropdown"
+ toggle-class="dropdown-menu-toggle"
+ :text="currentEnvironmentName"
+ :disabled="environments.length === 0"
>
- </gl-dropdown>
+ <gl-dropdown-item
+ v-for="environment in environments"
+ :key="environment.id"
+ :active="environment.name === currentEnvironmentName"
+ active-class="is-active"
+ >{{ environment.name }}</gl-dropdown-item
+ >
+ </gl-dropdown>
+ </div>
+ <div class="d-flex align-items-center prepend-left-8">
+ <strong>{{ s__('Metrics|Show last') }}</strong>
+ <gl-dropdown
+ class="prepend-left-10 js-time-window-dropdown"
+ toggle-class="dropdown-menu-toggle"
+ :text="selectedTimeWindow"
+ >
+ <gl-dropdown-item
+ v-for="(value, key) in timeWindows"
+ :key="key"
+ :active="activeTimeWindow(key)"
+ :href="setTimeWindowParameter(key)"
+ active-class="active"
+ >{{ value }}</gl-dropdown-item
+ >
+ </gl-dropdown>
+ </div>
</div>
- <div v-if="showTimeWindowDropdown" class="d-flex align-items-center">
- <strong>{{ s__('Metrics|Show last') }}</strong>
- <gl-dropdown
- class="prepend-left-10 js-time-window-dropdown"
- toggle-class="dropdown-menu-toggle"
- :text="selectedTimeWindow"
- >
- <gl-dropdown-item
- v-for="(value, key) in timeWindows"
- :key="key"
- :active="activeTimeWindow(key)"
- @click="getGraphsDataWithTime(key)"
- >{{ value }}</gl-dropdown-item
+ <div class="d-flex">
+ <div v-if="isEE && canAddMetrics">
+ <gl-button
+ v-gl-modal-directive="$options.addMetric.modalId"
+ class="js-add-metric-button text-success border-success"
+ >{{ $options.addMetric.title }}</gl-button
>
- </gl-dropdown>
+ <gl-modal
+ ref="addMetricModal"
+ :modal-id="$options.addMetric.modalId"
+ :title="$options.addMetric.title"
+ >
+ <form ref="customMetricsForm" :action="customMetricsPath" method="post">
+ <custom-metrics-form-fields
+ :validate-query-path="validateQueryPath"
+ form-operation="post"
+ @formValidation="setFormValidity"
+ />
+ </form>
+ <div slot="modal-footer">
+ <gl-button @click="hideAddMetricModal">{{ __('Cancel') }}</gl-button>
+ <gl-button
+ :disabled="!formIsValid"
+ variant="success"
+ @click="submitCustomMetricsForm"
+ >{{ __('Save changes') }}</gl-button
+ >
+ </div>
+ </gl-modal>
+ </div>
+ <gl-button
+ v-if="externalDashboardUrl.length"
+ class="js-external-dashboard-link prepend-left-8"
+ variant="primary"
+ :href="externalDashboardUrl"
+ target="_blank"
+ >
+ {{ __('View full dashboard') }}
+ <icon name="external-link" />
+ </gl-button>
</div>
</div>
<graph-group
- v-for="(groupData, index) in store.groups"
+ v-for="(groupData, index) in groupsWithData"
:key="index"
:name="groupData.group"
:show-panels="showPanels"
>
<monitor-area-chart
- v-for="(graphData, graphIndex) in groupData.metrics"
+ v-for="(graphData, graphIndex) in chartsWithData(groupData.metrics)"
:key="graphIndex"
:graph-data="graphData"
- :deployment-data="store.deploymentData"
+ :deployment-data="deploymentData"
:thresholds="getGraphAlertValues(graphData.queries)"
:container-width="elWidth"
group-id="monitor-area-chart"
@@ -271,7 +344,7 @@ export default {
</div>
<empty-state
v-else
- :selected-state="state"
+ :selected-state="emptyState"
:documentation-path="documentationPath"
:settings-path="settingsPath"
:clusters-path="clustersPath"
diff --git a/app/assets/javascripts/monitoring/constants.js b/app/assets/javascripts/monitoring/constants.js
index e97320fd682..26f1bf3f68d 100644
--- a/app/assets/javascripts/monitoring/constants.js
+++ b/app/assets/javascripts/monitoring/constants.js
@@ -18,3 +18,12 @@ export const timeWindows = {
threeDays: __('3 days'),
oneWeek: __('1 week'),
};
+
+export const timeWindowsKeyNames = {
+ thirtyMinutes: 'thirtyMinutes',
+ threeHours: 'threeHours',
+ eightHours: 'eightHours',
+ oneDay: 'oneDay',
+ threeDays: 'threeDays',
+ oneWeek: 'oneWeek',
+};
diff --git a/app/assets/javascripts/monitoring/monitoring_bundle.js b/app/assets/javascripts/monitoring/monitoring_bundle.js
index 2b4ddd7afbc..1d33537b3b2 100644
--- a/app/assets/javascripts/monitoring/monitoring_bundle.js
+++ b/app/assets/javascripts/monitoring/monitoring_bundle.js
@@ -1,20 +1,27 @@
import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
-import Dashboard from './components/dashboard.vue';
+import Dashboard from 'ee_else_ce/monitoring/components/dashboard.vue';
+import store from './stores';
-export default () => {
+export default (props = {}) => {
const el = document.getElementById('prometheus-graphs');
if (el && el.dataset) {
+ store.dispatch(
+ 'monitoringDashboard/setDashboardEnabled',
+ gon.features.environmentMetricsUsePrometheusEndpoint,
+ );
+
// eslint-disable-next-line no-new
new Vue({
el,
+ store,
render(createElement) {
return createElement(Dashboard, {
props: {
...el.dataset,
hasMetrics: parseBoolean(el.dataset.hasMetrics),
- showTimeWindowDropdown: gon.features.metricsTimeWindow,
+ ...props,
},
});
},
diff --git a/app/assets/javascripts/monitoring/services/monitoring_service.js b/app/assets/javascripts/monitoring/services/monitoring_service.js
deleted file mode 100644
index 5fcc2c8cfac..00000000000
--- a/app/assets/javascripts/monitoring/services/monitoring_service.js
+++ /dev/null
@@ -1,75 +0,0 @@
-import axios from '../../lib/utils/axios_utils';
-import statusCodes from '../../lib/utils/http_status';
-import { backOff } from '../../lib/utils/common_utils';
-import { s__ } from '../../locale';
-
-const MAX_REQUESTS = 3;
-
-function backOffRequest(makeRequestCallback) {
- let requestCounter = 0;
- return backOff((next, stop) => {
- makeRequestCallback()
- .then(resp => {
- if (resp.status === statusCodes.NO_CONTENT) {
- requestCounter += 1;
- if (requestCounter < MAX_REQUESTS) {
- next();
- } else {
- stop(new Error('Failed to connect to the prometheus server'));
- }
- } else {
- stop(resp);
- }
- })
- .catch(stop);
- });
-}
-
-export default class MonitoringService {
- constructor({ metricsEndpoint, deploymentEndpoint, environmentsEndpoint }) {
- this.metricsEndpoint = metricsEndpoint;
- this.deploymentEndpoint = deploymentEndpoint;
- this.environmentsEndpoint = environmentsEndpoint;
- }
-
- getGraphsData(params = {}) {
- return backOffRequest(() => axios.get(this.metricsEndpoint, { params }))
- .then(resp => resp.data)
- .then(response => {
- if (!response || !response.data || !response.success) {
- throw new Error(s__('Metrics|Unexpected metrics data response from prometheus endpoint'));
- }
- return response.data;
- });
- }
-
- getDeploymentData() {
- if (!this.deploymentEndpoint) {
- return Promise.resolve([]);
- }
- return backOffRequest(() => axios.get(this.deploymentEndpoint))
- .then(resp => resp.data)
- .then(response => {
- if (!response || !response.deployments) {
- throw new Error(
- s__('Metrics|Unexpected deployment data response from prometheus endpoint'),
- );
- }
- return response.deployments;
- });
- }
-
- getEnvironmentsData() {
- return axios
- .get(this.environmentsEndpoint)
- .then(resp => resp.data)
- .then(response => {
- if (!response || !response.environments) {
- throw new Error(
- s__('Metrics|There was an error fetching the environments data, please try again'),
- );
- }
- return response.environments;
- });
- }
-}
diff --git a/app/assets/javascripts/monitoring/stores/actions.js b/app/assets/javascripts/monitoring/stores/actions.js
new file mode 100644
index 00000000000..f41e215cb5d
--- /dev/null
+++ b/app/assets/javascripts/monitoring/stores/actions.js
@@ -0,0 +1,207 @@
+import * as types from './mutation_types';
+import axios from '~/lib/utils/axios_utils';
+import createFlash from '~/flash';
+import statusCodes from '../../lib/utils/http_status';
+import { backOff } from '../../lib/utils/common_utils';
+import { s__, __ } from '../../locale';
+
+const MAX_REQUESTS = 3;
+
+function backOffRequest(makeRequestCallback) {
+ let requestCounter = 0;
+ return backOff((next, stop) => {
+ makeRequestCallback()
+ .then(resp => {
+ if (resp.status === statusCodes.NO_CONTENT) {
+ requestCounter += 1;
+ if (requestCounter < MAX_REQUESTS) {
+ next();
+ } else {
+ stop(new Error(__('Failed to connect to the prometheus server')));
+ }
+ } else {
+ stop(resp);
+ }
+ })
+ .catch(stop);
+ });
+}
+
+export const setGettingStartedEmptyState = ({ commit }) => {
+ commit(types.SET_GETTING_STARTED_EMPTY_STATE);
+};
+
+export const setEndpoints = ({ commit }, endpoints) => {
+ commit(types.SET_ENDPOINTS, endpoints);
+};
+
+export const setDashboardEnabled = ({ commit }, enabled) => {
+ commit(types.SET_DASHBOARD_ENABLED, enabled);
+};
+
+export const requestMetricsDashboard = ({ commit }) => {
+ commit(types.REQUEST_METRICS_DATA);
+};
+export const receiveMetricsDashboardSuccess = ({ commit, dispatch }, { response, params }) => {
+ commit(types.RECEIVE_METRICS_DATA_SUCCESS, response.dashboard.panel_groups);
+ dispatch('fetchPrometheusMetrics', params);
+};
+export const receiveMetricsDashboardFailure = ({ commit }, error) => {
+ commit(types.RECEIVE_METRICS_DATA_FAILURE, error);
+};
+
+export const requestMetricsData = ({ commit }) => commit(types.REQUEST_METRICS_DATA);
+export const receiveMetricsDataSuccess = ({ commit }, data) =>
+ commit(types.RECEIVE_METRICS_DATA_SUCCESS, data);
+export const receiveMetricsDataFailure = ({ commit }, error) =>
+ commit(types.RECEIVE_METRICS_DATA_FAILURE, error);
+export const receiveDeploymentsDataSuccess = ({ commit }, data) =>
+ commit(types.RECEIVE_DEPLOYMENTS_DATA_SUCCESS, data);
+export const receiveDeploymentsDataFailure = ({ commit }) =>
+ commit(types.RECEIVE_DEPLOYMENTS_DATA_FAILURE);
+export const receiveEnvironmentsDataSuccess = ({ commit }, data) =>
+ commit(types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS, data);
+export const receiveEnvironmentsDataFailure = ({ commit }) =>
+ commit(types.RECEIVE_ENVIRONMENTS_DATA_FAILURE);
+
+export const fetchData = ({ dispatch }, params) => {
+ dispatch('fetchMetricsData', params);
+ dispatch('fetchDeploymentsData');
+ dispatch('fetchEnvironmentsData');
+};
+
+export const fetchMetricsData = ({ state, dispatch }, params) => {
+ if (state.useDashboardEndpoint) {
+ return dispatch('fetchDashboard', params);
+ }
+
+ dispatch('requestMetricsData');
+
+ return backOffRequest(() => axios.get(state.metricsEndpoint, { params }))
+ .then(resp => resp.data)
+ .then(response => {
+ if (!response || !response.data || !response.success) {
+ dispatch('receiveMetricsDataFailure', null);
+ createFlash(s__('Metrics|Unexpected metrics data response from prometheus endpoint'));
+ }
+ dispatch('receiveMetricsDataSuccess', response.data);
+ })
+ .catch(error => {
+ dispatch('receiveMetricsDataFailure', error);
+ createFlash(s__('Metrics|There was an error while retrieving metrics'));
+ });
+};
+
+export const fetchDashboard = ({ state, dispatch }, params) => {
+ dispatch('requestMetricsDashboard');
+
+ return axios
+ .get(state.dashboardEndpoint, { params })
+ .then(resp => resp.data)
+ .then(response => {
+ dispatch('receiveMetricsDashboardSuccess', { response, params });
+ })
+ .catch(error => {
+ dispatch('receiveMetricsDashboardFailure', error);
+ createFlash(s__('Metrics|There was an error while retrieving metrics'));
+ });
+};
+
+function fetchPrometheusResult(prometheusEndpoint, params) {
+ return backOffRequest(() => axios.get(prometheusEndpoint, { params }))
+ .then(res => res.data)
+ .then(response => {
+ if (response.status === 'error') {
+ throw new Error(response.error);
+ }
+
+ return response.data.result;
+ });
+}
+
+/**
+ * Returns list of metrics in data.result
+ * {"status":"success", "data":{"resultType":"matrix","result":[]}}
+ *
+ * @param {metric} metric
+ */
+export const fetchPrometheusMetric = ({ commit }, { metric, params }) => {
+ const { start, end } = params;
+ const timeDiff = end - start;
+
+ const minStep = 60;
+ const queryDataPoints = 600;
+ const step = Math.max(minStep, Math.ceil(timeDiff / queryDataPoints));
+
+ const queryParams = {
+ start,
+ end,
+ step,
+ };
+
+ return fetchPrometheusResult(metric.prometheus_endpoint_path, queryParams).then(result => {
+ commit(types.SET_QUERY_RESULT, { metricId: metric.metric_id, result });
+ });
+};
+
+export const fetchPrometheusMetrics = ({ state, commit, dispatch }, params) => {
+ commit(types.REQUEST_METRICS_DATA);
+
+ const promises = [];
+ state.groups.forEach(group => {
+ group.panels.forEach(panel => {
+ panel.metrics.forEach(metric => {
+ promises.push(dispatch('fetchPrometheusMetric', { metric, params }));
+ });
+ });
+ });
+
+ return Promise.all(promises).then(() => {
+ if (state.metricsWithData.length === 0) {
+ commit(types.SET_NO_DATA_EMPTY_STATE);
+ }
+ });
+};
+
+export const fetchDeploymentsData = ({ state, dispatch }) => {
+ if (!state.deploymentsEndpoint) {
+ return Promise.resolve([]);
+ }
+ return backOffRequest(() => axios.get(state.deploymentsEndpoint))
+ .then(resp => resp.data)
+ .then(response => {
+ if (!response || !response.deployments) {
+ createFlash(s__('Metrics|Unexpected deployment data response from prometheus endpoint'));
+ }
+
+ dispatch('receiveDeploymentsDataSuccess', response.deployments);
+ })
+ .catch(() => {
+ dispatch('receiveDeploymentsDataFailure');
+ createFlash(s__('Metrics|There was an error getting deployment information.'));
+ });
+};
+
+export const fetchEnvironmentsData = ({ state, dispatch }) => {
+ if (!state.environmentsEndpoint) {
+ return Promise.resolve([]);
+ }
+ return axios
+ .get(state.environmentsEndpoint)
+ .then(resp => resp.data)
+ .then(response => {
+ if (!response || !response.environments) {
+ createFlash(
+ s__('Metrics|There was an error fetching the environments data, please try again'),
+ );
+ }
+ dispatch('receiveEnvironmentsDataSuccess', response.environments);
+ })
+ .catch(() => {
+ dispatch('receiveEnvironmentsDataFailure');
+ createFlash(s__('Metrics|There was an error getting environments information.'));
+ });
+};
+
+// prevent babel-plugin-rewire from generating an invalid default during karma tests
+export default () => {};
diff --git a/app/assets/javascripts/monitoring/stores/index.js b/app/assets/javascripts/monitoring/stores/index.js
new file mode 100644
index 00000000000..d58398c54ae
--- /dev/null
+++ b/app/assets/javascripts/monitoring/stores/index.js
@@ -0,0 +1,21 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import * as actions from './actions';
+import mutations from './mutations';
+import state from './state';
+
+Vue.use(Vuex);
+
+export const createStore = () =>
+ new Vuex.Store({
+ modules: {
+ monitoringDashboard: {
+ namespaced: true,
+ actions,
+ mutations,
+ state,
+ },
+ },
+ });
+
+export default createStore();
diff --git a/app/assets/javascripts/monitoring/stores/monitoring_store.js b/app/assets/javascripts/monitoring/stores/monitoring_store.js
deleted file mode 100644
index 9761fe168be..00000000000
--- a/app/assets/javascripts/monitoring/stores/monitoring_store.js
+++ /dev/null
@@ -1,112 +0,0 @@
-import _ from 'underscore';
-
-function sortMetrics(metrics) {
- return _.chain(metrics)
- .sortBy('title')
- .sortBy('weight')
- .value();
-}
-
-function checkQueryEmptyData(query) {
- return {
- ...query,
- result: query.result.filter(timeSeries => {
- const newTimeSeries = timeSeries;
- const hasValue = series =>
- !Number.isNaN(series[1]) && (series[1] !== null || series[1] !== undefined);
- const hasNonNullValue = timeSeries.values.find(hasValue);
-
- newTimeSeries.values = hasNonNullValue ? newTimeSeries.values : [];
-
- return newTimeSeries.values.length > 0;
- }),
- };
-}
-
-function removeTimeSeriesNoData(queries) {
- return queries.reduce((series, query) => series.concat(checkQueryEmptyData(query)), []);
-}
-
-// Metrics and queries are currently stored 1:1, so `queries` is an array of length one.
-// We want to group queries onto a single chart by title & y-axis label.
-// This function will no longer be required when metrics:queries are 1:many,
-// though there is no consequence if the function stays in use.
-// @param metrics [Array<Object>]
-// Ex) [
-// { id: 1, title: 'title', y_label: 'MB', queries: [{ ...query1Attrs }] },
-// { id: 2, title: 'title', y_label: 'MB', queries: [{ ...query2Attrs }] },
-// { id: 3, title: 'new title', y_label: 'MB', queries: [{ ...query3Attrs }] }
-// ]
-// @return [Array<Object>]
-// Ex) [
-// { title: 'title', y_label: 'MB', queries: [{ metricId: 1, ...query1Attrs },
-// { metricId: 2, ...query2Attrs }] },
-// { title: 'new title', y_label: 'MB', queries: [{ metricId: 3, ...query3Attrs }]}
-// ]
-function groupQueriesByChartInfo(metrics) {
- const metricsByChart = metrics.reduce((accumulator, metric) => {
- const { id, queries, ...chart } = metric;
-
- const chartKey = `${chart.title}|${chart.y_label}`;
- accumulator[chartKey] = accumulator[chartKey] || { ...chart, queries: [] };
-
- queries.forEach(queryAttrs =>
- accumulator[chartKey].queries.push({ metricId: id.toString(), ...queryAttrs }),
- );
-
- return accumulator;
- }, {});
-
- return Object.values(metricsByChart);
-}
-
-function normalizeMetrics(metrics) {
- const groupedMetrics = groupQueriesByChartInfo(metrics);
-
- return groupedMetrics.map(metric => {
- const queries = metric.queries.map(query => ({
- ...query,
- // custom metrics do not require a label, so we should ensure this attribute is defined
- label: query.label || metric.y_label,
- result: query.result.map(result => ({
- ...result,
- values: result.values.map(([timestamp, value]) => [
- new Date(timestamp * 1000).toISOString(),
- Number(value),
- ]),
- })),
- }));
-
- return {
- ...metric,
- queries: removeTimeSeriesNoData(queries),
- };
- });
-}
-
-export default class MonitoringStore {
- constructor() {
- this.groups = [];
- this.deploymentData = [];
- this.environmentsData = [];
- }
-
- storeMetrics(groups = []) {
- this.groups = groups.map(group => ({
- ...group,
- metrics: normalizeMetrics(sortMetrics(group.metrics)),
- }));
- }
-
- storeDeploymentData(deploymentData = []) {
- this.deploymentData = deploymentData;
- }
-
- storeEnvironmentsData(environmentsData = []) {
- this.environmentsData = environmentsData.filter(environment => !!environment.last_deployment);
- }
-
- getMetricsCount() {
- return this.groups.reduce((count, group) => count + group.metrics.length, 0);
- }
-}
diff --git a/app/assets/javascripts/monitoring/stores/mutation_types.js b/app/assets/javascripts/monitoring/stores/mutation_types.js
new file mode 100644
index 00000000000..63894e83362
--- /dev/null
+++ b/app/assets/javascripts/monitoring/stores/mutation_types.js
@@ -0,0 +1,15 @@
+export const REQUEST_METRICS_DATA = 'REQUEST_METRICS_DATA';
+export const RECEIVE_METRICS_DATA_SUCCESS = 'RECEIVE_METRICS_DATA_SUCCESS';
+export const RECEIVE_METRICS_DATA_FAILURE = 'RECEIVE_METRICS_DATA_FAILURE';
+export const REQUEST_DEPLOYMENTS_DATA = 'REQUEST_DEPLOYMENTS_DATA';
+export const RECEIVE_DEPLOYMENTS_DATA_SUCCESS = 'RECEIVE_DEPLOYMENTS_DATA_SUCCESS';
+export const RECEIVE_DEPLOYMENTS_DATA_FAILURE = 'RECEIVE_DEPLOYMENTS_DATA_FAILURE';
+export const REQUEST_ENVIRONMENTS_DATA = 'REQUEST_ENVIRONMENTS_DATA';
+export const RECEIVE_ENVIRONMENTS_DATA_SUCCESS = 'RECEIVE_ENVIRONMENTS_DATA_SUCCESS';
+export const RECEIVE_ENVIRONMENTS_DATA_FAILURE = 'RECEIVE_ENVIRONMENTS_DATA_FAILURE';
+export const SET_QUERY_RESULT = 'SET_QUERY_RESULT';
+export const SET_TIME_WINDOW = 'SET_TIME_WINDOW';
+export const SET_DASHBOARD_ENABLED = 'SET_DASHBOARD_ENABLED';
+export const SET_ENDPOINTS = 'SET_ENDPOINTS';
+export const SET_GETTING_STARTED_EMPTY_STATE = 'SET_GETTING_STARTED_EMPTY_STATE';
+export const SET_NO_DATA_EMPTY_STATE = 'SET_NO_DATA_EMPTY_STATE';
diff --git a/app/assets/javascripts/monitoring/stores/mutations.js b/app/assets/javascripts/monitoring/stores/mutations.js
new file mode 100644
index 00000000000..d4b816e2717
--- /dev/null
+++ b/app/assets/javascripts/monitoring/stores/mutations.js
@@ -0,0 +1,88 @@
+import Vue from 'vue';
+import * as types from './mutation_types';
+import { normalizeMetrics, sortMetrics, normalizeQueryResult } from './utils';
+
+export default {
+ [types.REQUEST_METRICS_DATA](state) {
+ state.emptyState = 'loading';
+ state.showEmptyState = true;
+ },
+ [types.RECEIVE_METRICS_DATA_SUCCESS](state, groupData) {
+ state.groups = groupData.map(group => {
+ let { metrics } = group;
+
+ // for backwards compatibility, and to limit Vue template changes:
+ // for each group alias panels to metrics
+ // for each panel alias metrics to queries
+ if (state.useDashboardEndpoint) {
+ metrics = group.panels.map(panel => ({
+ ...panel,
+ queries: panel.metrics,
+ }));
+ }
+
+ return {
+ ...group,
+ metrics: normalizeMetrics(sortMetrics(metrics)),
+ };
+ });
+
+ if (!state.groups.length) {
+ state.emptyState = 'noData';
+ } else {
+ state.showEmptyState = false;
+ }
+ },
+ [types.RECEIVE_METRICS_DATA_FAILURE](state, error) {
+ state.emptyState = error ? 'unableToConnect' : 'noData';
+ state.showEmptyState = true;
+ },
+ [types.RECEIVE_DEPLOYMENTS_DATA_SUCCESS](state, deployments) {
+ state.deploymentData = deployments;
+ },
+ [types.RECEIVE_DEPLOYMENTS_DATA_FAILURE](state) {
+ state.deploymentData = [];
+ },
+ [types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS](state, environments) {
+ state.environments = environments;
+ },
+ [types.RECEIVE_ENVIRONMENTS_DATA_FAILURE](state) {
+ state.environments = [];
+ },
+ [types.SET_QUERY_RESULT](state, { metricId, result }) {
+ if (!metricId || !result || result.length === 0) {
+ return;
+ }
+
+ state.showEmptyState = false;
+
+ state.groups.forEach(group => {
+ group.metrics.forEach(metric => {
+ metric.queries.forEach(query => {
+ if (query.metric_id === metricId) {
+ state.metricsWithData.push(metricId);
+ // ensure dates/numbers are correctly formatted for charts
+ const normalizedResults = result.map(normalizeQueryResult);
+ Vue.set(query, 'result', Object.freeze(normalizedResults));
+ }
+ });
+ });
+ });
+ },
+ [types.SET_ENDPOINTS](state, endpoints) {
+ state.metricsEndpoint = endpoints.metricsEndpoint;
+ state.environmentsEndpoint = endpoints.environmentsEndpoint;
+ state.deploymentsEndpoint = endpoints.deploymentsEndpoint;
+ state.dashboardEndpoint = endpoints.dashboardEndpoint;
+ },
+ [types.SET_DASHBOARD_ENABLED](state, enabled) {
+ state.useDashboardEndpoint = enabled;
+ },
+ [types.SET_GETTING_STARTED_EMPTY_STATE](state) {
+ state.emptyState = 'gettingStarted';
+ },
+ [types.SET_NO_DATA_EMPTY_STATE](state) {
+ state.showEmptyState = true;
+ state.emptyState = 'noData';
+ },
+};
diff --git a/app/assets/javascripts/monitoring/stores/state.js b/app/assets/javascripts/monitoring/stores/state.js
new file mode 100644
index 00000000000..c33529cd588
--- /dev/null
+++ b/app/assets/javascripts/monitoring/stores/state.js
@@ -0,0 +1,17 @@
+import invalidUrl from '~/lib/utils/invalid_url';
+
+export default () => ({
+ hasMetrics: false,
+ showPanels: true,
+ metricsEndpoint: null,
+ environmentsEndpoint: null,
+ deploymentsEndpoint: null,
+ dashboardEndpoint: invalidUrl,
+ useDashboardEndpoint: false,
+ emptyState: 'gettingStarted',
+ showEmptyState: true,
+ groups: [],
+ deploymentData: [],
+ environments: [],
+ metricsWithData: [],
+});
diff --git a/app/assets/javascripts/monitoring/stores/utils.js b/app/assets/javascripts/monitoring/stores/utils.js
new file mode 100644
index 00000000000..84e1f1c4c20
--- /dev/null
+++ b/app/assets/javascripts/monitoring/stores/utils.js
@@ -0,0 +1,85 @@
+import _ from 'underscore';
+
+function checkQueryEmptyData(query) {
+ return {
+ ...query,
+ result: query.result.filter(timeSeries => {
+ const newTimeSeries = timeSeries;
+ const hasValue = series =>
+ !Number.isNaN(series[1]) && (series[1] !== null || series[1] !== undefined);
+ const hasNonNullValue = timeSeries.values.find(hasValue);
+
+ newTimeSeries.values = hasNonNullValue ? newTimeSeries.values : [];
+
+ return newTimeSeries.values.length > 0;
+ }),
+ };
+}
+
+function removeTimeSeriesNoData(queries) {
+ return queries.reduce((series, query) => series.concat(checkQueryEmptyData(query)), []);
+}
+
+// Metrics and queries are currently stored 1:1, so `queries` is an array of length one.
+// We want to group queries onto a single chart by title & y-axis label.
+// This function will no longer be required when metrics:queries are 1:many,
+// though there is no consequence if the function stays in use.
+// @param metrics [Array<Object>]
+// Ex) [
+// { id: 1, title: 'title', y_label: 'MB', queries: [{ ...query1Attrs }] },
+// { id: 2, title: 'title', y_label: 'MB', queries: [{ ...query2Attrs }] },
+// { id: 3, title: 'new title', y_label: 'MB', queries: [{ ...query3Attrs }] }
+// ]
+// @return [Array<Object>]
+// Ex) [
+// { title: 'title', y_label: 'MB', queries: [{ metricId: 1, ...query1Attrs },
+// { metricId: 2, ...query2Attrs }] },
+// { title: 'new title', y_label: 'MB', queries: [{ metricId: 3, ...query3Attrs }]}
+// ]
+function groupQueriesByChartInfo(metrics) {
+ const metricsByChart = metrics.reduce((accumulator, metric) => {
+ const { queries, ...chart } = metric;
+ const metricId = chart.id ? chart.id.toString() : null;
+
+ const chartKey = `${chart.title}|${chart.y_label}`;
+ accumulator[chartKey] = accumulator[chartKey] || { ...chart, queries: [] };
+
+ queries.forEach(queryAttrs => accumulator[chartKey].queries.push({ metricId, ...queryAttrs }));
+
+ return accumulator;
+ }, {});
+
+ return Object.values(metricsByChart);
+}
+
+export const sortMetrics = metrics =>
+ _.chain(metrics)
+ .sortBy('title')
+ .sortBy('weight')
+ .value();
+
+export const normalizeQueryResult = timeSeries => ({
+ ...timeSeries,
+ values: timeSeries.values.map(([timestamp, value]) => [
+ new Date(timestamp * 1000).toISOString(),
+ Number(value),
+ ]),
+});
+
+export const normalizeMetrics = metrics => {
+ const groupedMetrics = groupQueriesByChartInfo(metrics);
+
+ return groupedMetrics.map(metric => {
+ const queries = metric.queries.map(query => ({
+ ...query,
+ // custom metrics do not require a label, so we should ensure this attribute is defined
+ label: query.label || metric.y_label,
+ result: (query.result || []).map(normalizeQueryResult),
+ }));
+
+ return {
+ ...metric,
+ queries: removeTimeSeriesNoData(queries),
+ };
+ });
+};
diff --git a/app/assets/javascripts/mr_notes/stores/getters.js b/app/assets/javascripts/mr_notes/stores/getters.js
index b10e9f9f9f1..e48cfcd9564 100644
--- a/app/assets/javascripts/mr_notes/stores/getters.js
+++ b/app/assets/javascripts/mr_notes/stores/getters.js
@@ -1,5 +1,5 @@
export default {
isLoggedIn(state, getters) {
- return !!getters.getUserData.id;
+ return Boolean(getters.getUserData.id);
},
};
diff --git a/app/assets/javascripts/mr_popover/constants.js b/app/assets/javascripts/mr_popover/constants.js
index 433df844c80..c13c417cc18 100644
--- a/app/assets/javascripts/mr_popover/constants.js
+++ b/app/assets/javascripts/mr_popover/constants.js
@@ -1,10 +1,12 @@
+import { __ } from '~/locale';
+
export const mrStates = {
merged: 'merged',
closed: 'closed',
};
export const humanMRStates = {
- merged: 'Merged',
- closed: 'Closed',
- open: 'Open',
+ merged: __('Merged'),
+ closed: __('Closed'),
+ open: __('Open'),
};
diff --git a/app/assets/javascripts/mr_popover/index.js b/app/assets/javascripts/mr_popover/index.js
index 9a97e98f9db..18c0e201300 100644
--- a/app/assets/javascripts/mr_popover/index.js
+++ b/app/assets/javascripts/mr_popover/index.js
@@ -22,13 +22,10 @@ const handleUserPopoverMouseOut = ({ target }) => {
* Adds a MergeRequestPopover component to the body, hands over as much data as the target element has in data attributes.
* loads based on data-project-path and data-iid more data about an MR from the API and sets it on the popover
*/
-const handleMRPopoverMount = apolloProvider => ({ target }) => {
+const handleMRPopoverMount = ({ apolloProvider, projectPath, mrTitle, iid }) => ({ target }) => {
// Add listener to actually remove it again
target.addEventListener('mouseleave', handleUserPopoverMouseOut);
- const { projectPath, mrTitle, iid } = target.dataset;
- const mergeRequest = {};
-
renderFn = setTimeout(() => {
const MRPopoverComponent = Vue.extend(MRPopover);
renderedPopover = new MRPopoverComponent({
@@ -36,7 +33,6 @@ const handleMRPopoverMount = apolloProvider => ({ target }) => {
target,
projectPath,
mergeRequestIID: iid,
- mergeRequest,
mergeRequestTitle: mrTitle,
},
apolloProvider,
@@ -57,8 +53,13 @@ export default elements => {
const listenerAddedAttr = 'data-mr-listener-added';
mrLinks.forEach(el => {
- if (!el.getAttribute(listenerAddedAttr)) {
- el.addEventListener('mouseenter', handleMRPopoverMount(apolloProvider));
+ const { projectPath, mrTitle, iid } = el.dataset;
+
+ if (!el.getAttribute(listenerAddedAttr) && projectPath && mrTitle && iid) {
+ el.addEventListener(
+ 'mouseenter',
+ handleMRPopoverMount({ apolloProvider, projectPath, mrTitle, iid }),
+ );
el.setAttribute(listenerAddedAttr, true);
}
});
diff --git a/app/assets/javascripts/namespace_select.js b/app/assets/javascripts/namespace_select.js
index ee1a5274ff7..03d349ac714 100644
--- a/app/assets/javascripts/namespace_select.js
+++ b/app/assets/javascripts/namespace_select.js
@@ -4,6 +4,7 @@ import $ from 'jquery';
import Api from './api';
import { mergeUrlParams } from './lib/utils/url_utility';
import { parseBoolean } from '~/lib/utils/common_utils';
+import { __ } from './locale';
export default class NamespaceSelect {
constructor(opts) {
@@ -29,7 +30,7 @@ export default class NamespaceSelect {
return Api.namespaces(term, function(namespaces) {
if (isFilter) {
const anyNamespace = {
- text: 'Any namespace',
+ text: __('Any namespace'),
id: null,
};
namespaces.unshift(anyNamespace);
diff --git a/app/assets/javascripts/namespaces/leave_by_url.js b/app/assets/javascripts/namespaces/leave_by_url.js
new file mode 100644
index 00000000000..b817d38960c
--- /dev/null
+++ b/app/assets/javascripts/namespaces/leave_by_url.js
@@ -0,0 +1,22 @@
+import Flash from '~/flash';
+import { __, sprintf } from '~/locale';
+import { getParameterByName } from '~/lib/utils/common_utils';
+
+const PARAMETER_NAME = 'leave';
+const LEAVE_LINK_SELECTOR = '.js-leave-link';
+
+export default function leaveByUrl(namespaceType) {
+ if (!namespaceType) throw new Error('namespaceType not provided');
+
+ const param = getParameterByName(PARAMETER_NAME);
+ if (!param) return;
+
+ const leaveLink = document.querySelector(LEAVE_LINK_SELECTOR);
+ if (leaveLink) {
+ leaveLink.click();
+ } else {
+ Flash(
+ sprintf(__('You do not have permission to leave this %{namespaceType}.'), { namespaceType }),
+ );
+ }
+}
diff --git a/app/assets/javascripts/new_branch_form.js b/app/assets/javascripts/new_branch_form.js
index f338dbbb0a6..98522c67696 100644
--- a/app/assets/javascripts/new_branch_form.js
+++ b/app/assets/javascripts/new_branch_form.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, no-var, one-var, consistent-return, no-return-assign, prefer-arrow-callback, prefer-template, no-shadow, no-else-return */
+/* eslint-disable func-names, no-var, one-var, consistent-return, no-return-assign, prefer-arrow-callback, prefer-template, no-shadow, no-else-return, @gitlab/i18n/no-non-i18n-strings */
import $ from 'jquery';
import RefSelectDropdown from './ref_select_dropdown';
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 36725e22365..a7156bd2406 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -7,6 +7,10 @@ no-unused-vars, no-shadow, no-useless-escape, class-methods-use-this */
/* global ResolveService */
/* global mrRefreshWidgetUrl */
+/*
+old_notes_spec.js is the spec for the legacy, jQuery notes application. It has nothing to do with the new, fancy Vue notes app.
+ */
+
import $ from 'jquery';
import _ from 'underscore';
import Cookies from 'js-cookie';
@@ -35,6 +39,7 @@ import {
} from './lib/utils/common_utils';
import imageDiffHelper from './image_diff/helpers/index';
import { localTimeAgo } from './lib/utils/datetime_utility';
+import { sprintf, s__, __ } from './locale';
window.autosize = Autosize;
@@ -253,7 +258,7 @@ export default class Notes {
discussionNoteForm = $textarea.closest('.js-discussion-note-form');
if (discussionNoteForm.length) {
if ($textarea.val() !== '') {
- if (!window.confirm('Are you sure you want to cancel creating this comment?')) {
+ if (!window.confirm(__('Are you sure you want to cancel creating this comment?'))) {
return;
}
}
@@ -265,7 +270,7 @@ export default class Notes {
originalText = $textarea.closest('form').data('originalNote');
newText = $textarea.val();
if (originalText !== newText) {
- if (!window.confirm('Are you sure you want to cancel editing this comment?')) {
+ if (!window.confirm(__('Are you sure you want to cancel editing this comment?'))) {
return;
}
}
@@ -636,7 +641,7 @@ export default class Notes {
this.glForm = new GLForm(form, enableGFM);
textarea = form.find('.js-note-text');
key = [
- 'Note',
+ s__('NoteForm|Note'),
form.find('#note_noteable_type').val(),
form.find('#note_noteable_id').val(),
form.find('#note_commit_id').val(),
@@ -670,7 +675,9 @@ export default class Notes {
formParentTimeline = $form.closest('.discussion-notes').find('.notes');
}
return this.addFlash(
- 'Your comment could not be submitted! Please check your network connection and try again.',
+ __(
+ 'Your comment could not be submitted! Please check your network connection and try again.',
+ ),
'alert',
formParentTimeline.get(0),
);
@@ -679,7 +686,7 @@ export default class Notes {
updateNoteError($parentTimeline) {
// eslint-disable-next-line no-new
new Flash(
- 'Your comment could not be updated! Please check your network connection and try again.',
+ __('Your comment could not be updated! Please check your network connection and try again.'),
);
}
@@ -983,6 +990,14 @@ export default class Notes {
form.find('#note_position').val(dataHolder.attr('data-position'));
form
+ .prepend(
+ `<div class="avatar-note-form-holder"><div class="content"><a href="${escape(
+ gon.current_username,
+ )}" class="user-avatar-link d-none d-sm-block"><img class="avatar s40" src="${encodeURI(
+ gon.current_user_avatar_url,
+ )}" alt="${escape(gon.current_user_fullname)}" /></a></div></div>`,
+ )
+ .append('</div>')
.find('.js-close-discussion-note-form')
.show()
.removeClass('hide');
@@ -1018,6 +1033,9 @@ export default class Notes {
target: $link,
lineType: link.dataset.lineType,
showReplyInput,
+ currentUsername: gon.current_username,
+ currentUserAvatar: gon.current_user_avatar_url,
+ currentUserFullname: gon.current_user_fullname,
});
}
@@ -1046,7 +1064,15 @@ export default class Notes {
this.setupDiscussionNoteForm($link, newForm);
}
- toggleDiffNote({ target, lineType, forceShow, showReplyInput = false }) {
+ toggleDiffNote({
+ target,
+ lineType,
+ forceShow,
+ showReplyInput = false,
+ currentUsername,
+ currentUserAvatar,
+ currentUserFullname,
+ }) {
var $link,
addForm,
hasNotes,
@@ -1258,12 +1284,19 @@ export default class Notes {
putConflictEditWarningInPlace(noteEntity, $note) {
if ($note.find('.js-conflict-edit-warning').length === 0) {
+ const open_link = `<a href="#note_${
+ noteEntity.id
+ }" target="_blank" rel="noopener noreferrer">`;
const $alert = $(`<div class="js-conflict-edit-warning alert alert-danger">
- This comment has changed since you started editing, please review the
- <a href="#note_${noteEntity.id}" target="_blank" rel="noopener noreferrer">
- updated comment
- </a>
- to ensure information is not lost
+ ${sprintf(
+ s__(
+ 'Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost',
+ ),
+ {
+ open_link,
+ close_link: '</a>',
+ },
+ )}
</div>`);
$alert.insertAfter($note.find('.note-text'));
}
@@ -1491,13 +1524,15 @@ export default class Notes {
if (executedCommands && executedCommands.length) {
if (executedCommands.length > 1) {
- tempFormContent = 'Applying multiple commands';
+ tempFormContent = __('Applying multiple commands');
} else {
const commandDescription = executedCommands[0].description.toLowerCase();
- tempFormContent = `Applying command to ${commandDescription}`;
+ tempFormContent = sprintf(__('Applying command to %{commandDescription}'), {
+ commandDescription,
+ });
}
} else {
- tempFormContent = 'Applying command';
+ tempFormContent = __('Applying command');
}
return tempFormContent;
@@ -1530,7 +1565,9 @@ export default class Notes {
<div class="note-header">
<div class="note-header-info">
<a href="/${_.escape(currentUsername)}">
- <span class="d-none d-sm-inline-block">${_.escape(currentUsername)}</span>
+ <span class="d-none d-sm-inline-block bold">${_.escape(
+ currentUsername,
+ )}</span>
<span class="note-headline-light">${_.escape(currentUsername)}</span>
</a>
</div>
@@ -1817,7 +1854,9 @@ export default class Notes {
$editingNote
.find('.note-headline-meta a')
.html(
- '<i class="fa fa-spinner fa-spin" aria-label="Comment is being updated" aria-hidden="true"></i>',
+ `<i class="fa fa-spinner fa-spin" aria-label="${__(
+ 'Comment is being updated',
+ )}" aria-hidden="true"></i>`,
);
// Make request to update comment on server
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index caf22f71bf9..075c28e8d07 100644
--- a/app/assets/javascripts/notes/components/comment_form.vue
+++ b/app/assets/javascripts/notes/components/comment_form.vue
@@ -337,6 +337,8 @@ Please check your network connection and try again.`;
v-if="hasWarning(getNoteableData)"
:is-locked="isLocked(getNoteableData)"
:is-confidential="isConfidential(getNoteableData)"
+ :locked-issue-docs-path="lockedIssueDocsPath"
+ :confidential-issue-docs-path="confidentialIssueDocsPath"
/>
<markdown-field
@@ -351,6 +353,7 @@ Please check your network connection and try again.`;
ref="textarea"
slot="textarea"
v-model="note"
+ dir="auto"
:disabled="isSubmitting"
name="note[note]"
class="note-textarea js-vue-comment-form js-note-text
diff --git a/app/assets/javascripts/notes/components/discussion_actions.vue b/app/assets/javascripts/notes/components/discussion_actions.vue
new file mode 100644
index 00000000000..22cca756ef6
--- /dev/null
+++ b/app/assets/javascripts/notes/components/discussion_actions.vue
@@ -0,0 +1,58 @@
+<script>
+import ReplyPlaceholder from './discussion_reply_placeholder.vue';
+import ResolveDiscussionButton from './discussion_resolve_button.vue';
+import ResolveWithIssueButton from './discussion_resolve_with_issue_button.vue';
+import JumpToNextDiscussionButton from './discussion_jump_to_next_button.vue';
+
+export default {
+ name: 'DiscussionActions',
+ components: {
+ ReplyPlaceholder,
+ ResolveDiscussionButton,
+ ResolveWithIssueButton,
+ JumpToNextDiscussionButton,
+ },
+ props: {
+ discussion: {
+ type: Object,
+ required: true,
+ },
+ isResolving: {
+ type: Boolean,
+ required: true,
+ },
+ resolveButtonTitle: {
+ type: String,
+ required: true,
+ },
+ resolveWithIssuePath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ shouldShowJumpToNextDiscussion: {
+ type: Boolean,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="discussion-with-resolve-btn">
+ <reply-placeholder class="qa-discussion-reply" @onClick="$emit('showReplyForm')" />
+ <resolve-discussion-button
+ v-if="discussion.resolvable"
+ :is-resolving="isResolving"
+ :button-title="resolveButtonTitle"
+ @onClick="$emit('resolve')"
+ />
+ <div v-if="discussion.resolvable" class="btn-group discussion-actions ml-sm-2" role="group">
+ <resolve-with-issue-button v-if="resolveWithIssuePath" :url="resolveWithIssuePath" />
+ <jump-to-next-discussion-button
+ v-if="shouldShowJumpToNextDiscussion"
+ @onClick="$emit('jumpToNextDiscussion')"
+ />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/notes/components/discussion_counter.vue b/app/assets/javascripts/notes/components/discussion_counter.vue
index c7cfc0f0f3b..efd84f5722c 100644
--- a/app/assets/javascripts/notes/components/discussion_counter.vue
+++ b/app/assets/javascripts/notes/components/discussion_counter.vue
@@ -49,22 +49,26 @@ export default {
</script>
<template>
- <div v-if="resolvableDiscussionsCount > 0" class="line-resolve-all-container prepend-top-8">
- <div>
+ <div v-if="resolvableDiscussionsCount > 0" class="line-resolve-all-container full-width-mobile">
+ <div class="full-width-mobile d-flex d-sm-block">
<div :class="{ 'has-next-btn': hasNextButton }" class="line-resolve-all">
<span
:class="{ 'is-active': allResolved }"
class="line-resolve-btn is-disabled"
type="button"
>
- <icon name="check-circle" />
+ <icon :name="allResolved ? 'check-circle-filled' : 'check-circle'" />
</span>
<span class="line-resolve-text">
{{ resolvedDiscussionsCount }}/{{ resolvableDiscussionsCount }}
{{ n__('discussion resolved', 'discussions resolved', resolvableDiscussionsCount) }}
</span>
</div>
- <div v-if="resolveAllDiscussionsIssuePath && !allResolved" class="btn-group" role="group">
+ <div
+ v-if="resolveAllDiscussionsIssuePath && !allResolved"
+ class="btn-group btn-group-sm"
+ role="group"
+ >
<a
v-gl-tooltip
:href="resolveAllDiscussionsIssuePath"
@@ -74,7 +78,7 @@ export default {
<icon name="issue-new" />
</a>
</div>
- <div v-if="isLoggedIn && !allResolved" class="btn-group" role="group">
+ <div v-if="isLoggedIn && !allResolved" class="btn-group btn-group-sm" role="group">
<button
v-gl-tooltip
title="Jump to first unresolved discussion"
diff --git a/app/assets/javascripts/notes/components/discussion_filter.vue b/app/assets/javascripts/notes/components/discussion_filter.vue
index 47951591e82..eb3fbbe1385 100644
--- a/app/assets/javascripts/notes/components/discussion_filter.vue
+++ b/app/assets/javascripts/notes/components/discussion_filter.vue
@@ -105,12 +105,12 @@ export default {
<template>
<div
v-if="displayFilters"
- class="discussion-filter-container js-discussion-filter-container d-inline-block align-bottom"
+ class="discussion-filter-container js-discussion-filter-container d-inline-block align-bottom full-width-mobile"
>
<button
id="discussion-filter-dropdown"
ref="dropdownToggle"
- class="btn btn-default qa-discussion-filter"
+ class="btn btn-sm qa-discussion-filter"
data-toggle="dropdown"
aria-expanded="false"
>
diff --git a/app/assets/javascripts/notes/components/discussion_locked_widget.vue b/app/assets/javascripts/notes/components/discussion_locked_widget.vue
index c469a6b7bcd..53f509185a8 100644
--- a/app/assets/javascripts/notes/components/discussion_locked_widget.vue
+++ b/app/assets/javascripts/notes/components/discussion_locked_widget.vue
@@ -1,12 +1,24 @@
<script>
+import { GlLink } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
+import { __, sprintf } from '~/locale';
import Issuable from '~/vue_shared/mixins/issuable';
+import issuableStateMixin from '../mixins/issuable_state';
export default {
components: {
Icon,
+ GlLink,
+ },
+ mixins: [Issuable, issuableStateMixin],
+ computed: {
+ lockedIssueWarning() {
+ return sprintf(
+ __('This %{issuableDisplayName} is locked. Only project members can comment.'),
+ { issuableDisplayName: this.issuableDisplayName },
+ );
+ },
},
- mixins: [Issuable],
};
</script>
@@ -15,7 +27,11 @@ export default {
<span class="issuable-note-warning inline">
<icon :size="16" name="lock" class="icon" />
<span>
- This {{ issuableDisplayName }} is locked. Only <b>project members</b> can comment.
+ {{ lockedIssueWarning }}
+
+ <gl-link :href="lockedIssueDocsPath" target="_blank" class="learn-more">
+ {{ __('Learn more') }}
+ </gl-link>
</span>
</span>
</div>
diff --git a/app/assets/javascripts/notes/components/discussion_notes.vue b/app/assets/javascripts/notes/components/discussion_notes.vue
new file mode 100644
index 00000000000..228bb652597
--- /dev/null
+++ b/app/assets/javascripts/notes/components/discussion_notes.vue
@@ -0,0 +1,155 @@
+<script>
+import { mapGetters } from 'vuex';
+import { SYSTEM_NOTE } from '../constants';
+import { __ } from '~/locale';
+import NoteableNote from './noteable_note.vue';
+import PlaceholderNote from '../../vue_shared/components/notes/placeholder_note.vue';
+import PlaceholderSystemNote from '../../vue_shared/components/notes/placeholder_system_note.vue';
+import SystemNote from '~/vue_shared/components/notes/system_note.vue';
+import ToggleRepliesWidget from './toggle_replies_widget.vue';
+import NoteEditedText from './note_edited_text.vue';
+
+export default {
+ name: 'DiscussionNotes',
+ components: {
+ ToggleRepliesWidget,
+ NoteEditedText,
+ },
+ props: {
+ discussion: {
+ type: Object,
+ required: true,
+ },
+ isExpanded: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ diffLine: {
+ type: Object,
+ required: false,
+ default: null,
+ },
+ line: {
+ type: Object,
+ required: false,
+ default: null,
+ },
+ shouldGroupReplies: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ helpPagePath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ computed: {
+ ...mapGetters(['userCanReply']),
+ hasReplies() {
+ return Boolean(this.replies.length);
+ },
+ replies() {
+ return this.discussion.notes.slice(1);
+ },
+ firstNote() {
+ return this.discussion.notes.slice(0, 1)[0];
+ },
+ resolvedText() {
+ return this.discussion.resolved_by_push ? __('Automatically resolved') : __('Resolved');
+ },
+ commit() {
+ if (!this.discussion.for_commit) {
+ return null;
+ }
+
+ return {
+ id: this.discussion.commit_id,
+ url: this.discussion.discussion_path,
+ };
+ },
+ },
+ methods: {
+ componentName(note) {
+ if (note.isPlaceholderNote) {
+ if (note.placeholderType === SYSTEM_NOTE) {
+ return PlaceholderSystemNote;
+ }
+
+ return PlaceholderNote;
+ }
+
+ if (note.system) {
+ return SystemNote;
+ }
+
+ return NoteableNote;
+ },
+ componentData(note) {
+ return note.isPlaceholderNote ? note.notes[0] : note;
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="discussion-notes">
+ <ul class="notes">
+ <template v-if="shouldGroupReplies">
+ <component
+ :is="componentName(firstNote)"
+ :note="componentData(firstNote)"
+ :line="line"
+ :commit="commit"
+ :help-page-path="helpPagePath"
+ :show-reply-button="userCanReply"
+ @handle-delete-note="$emit('deleteNote')"
+ @start-replying="$emit('startReplying')"
+ >
+ <note-edited-text
+ v-if="discussion.resolved"
+ slot="discussion-resolved-text"
+ :edited-at="discussion.resolved_at"
+ :edited-by="discussion.resolved_by"
+ :action-text="resolvedText"
+ class-name="discussion-headline-light js-discussion-headline discussion-resolved-text"
+ />
+ <slot slot="avatar-badge" name="avatar-badge"></slot>
+ </component>
+ <toggle-replies-widget
+ v-if="hasReplies"
+ :collapsed="!isExpanded"
+ :replies="replies"
+ @toggle="$emit('toggleDiscussion')"
+ />
+ <template v-if="isExpanded">
+ <component
+ :is="componentName(note)"
+ v-for="note in replies"
+ :key="note.id"
+ :note="componentData(note)"
+ :help-page-path="helpPagePath"
+ :line="line"
+ @handle-delete-note="$emit('deleteNote')"
+ />
+ </template>
+ </template>
+ <template v-else>
+ <component
+ :is="componentName(note)"
+ v-for="(note, index) in discussion.notes"
+ :key="note.id"
+ :note="componentData(note)"
+ :help-page-path="helpPagePath"
+ :line="diffLine"
+ @handle-delete-note="$emit('deleteNote')"
+ >
+ <slot v-if="index === 0" slot="avatar-badge" name="avatar-badge"></slot>
+ </component>
+ </template>
+ </ul>
+ <slot :show-replies="isExpanded || !hasReplies" name="footer"></slot>
+ </div>
+</template>
diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue
index aabb77f6a85..844d0c3e376 100644
--- a/app/assets/javascripts/notes/components/note_actions.vue
+++ b/app/assets/javascripts/notes/components/note_actions.vue
@@ -2,6 +2,7 @@
import { mapGetters } from 'vuex';
import Icon from '~/vue_shared/components/icon.vue';
import { GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
+import resolvedStatusMixin from 'ee_else_ce/batch_comments/mixins/resolved_status';
import ReplyButton from './note_actions/reply_button.vue';
export default {
@@ -14,6 +15,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
+ mixins: [resolvedStatusMixin],
props: {
authorId: {
type: Number,
@@ -98,15 +100,6 @@ export default {
currentUserId() {
return this.getUserDataByProp('id');
},
- resolveButtonTitle() {
- let title = 'Mark as resolved';
-
- if (this.resolvedBy) {
- title = `Resolved by ${this.resolvedBy.name}`;
- }
-
- return title;
- },
},
methods: {
onEdit() {
@@ -142,7 +135,7 @@ export default {
@click="onResolve"
>
<template v-if="!isResolving">
- <icon name="check-circle" />
+ <icon :name="isResolved ? 'check-circle-filled' : 'check-circle'" />
</template>
<gl-loading-icon v-else inline />
</button>
@@ -154,13 +147,11 @@ export default {
class="note-action-button note-emoji-button js-add-award js-note-emoji"
href="#"
title="Add reaction"
+ data-position="right"
>
- <icon
- css-classes="link-highlight award-control-icon-neutral"
- name="emoji_slightly_smiling_face"
- />
- <icon css-classes="link-highlight award-control-icon-positive" name="emoji_smiley" />
- <icon css-classes="link-highlight award-control-icon-super-positive" name="emoji_smiley" />
+ <icon css-classes="link-highlight award-control-icon-neutral" name="slight-smile" />
+ <icon css-classes="link-highlight award-control-icon-positive" name="smiley" />
+ <icon css-classes="link-highlight award-control-icon-super-positive" name="smiley" />
</a>
</div>
<reply-button
@@ -204,7 +195,7 @@ export default {
</button>
<ul class="dropdown-menu more-actions-dropdown dropdown-open-left">
<li v-if="canReportAsAbuse">
- <a :href="reportAbusePath">{{ __('Report abuse to GitLab') }}</a>
+ <a :href="reportAbusePath">{{ __('Report abuse to admin') }}</a>
</li>
<li v-if="noteUrl">
<button
diff --git a/app/assets/javascripts/notes/components/note_awards_list.vue b/app/assets/javascripts/notes/components/note_awards_list.vue
index 17e5fcab5b7..941b6d5cab3 100644
--- a/app/assets/javascripts/notes/components/note_awards_list.vue
+++ b/app/assets/javascripts/notes/components/note_awards_list.vue
@@ -189,13 +189,13 @@ export default {
type="button"
>
<span class="award-control-icon award-control-icon-neutral">
- <icon name="emoji_slightly_smiling_face" />
+ <icon name="slight-smile" />
</span>
<span class="award-control-icon award-control-icon-positive">
- <icon name="emoji_smiley" />
+ <icon name="smiley" />
</span>
<span class="award-control-icon award-control-icon-super-positive">
- <icon name="emoji_smiley" />
+ <icon name="smiley" />
</span>
<i
aria-hidden="true"
diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue
index fbf75ed0e41..88454c3fb4c 100644
--- a/app/assets/javascripts/notes/components/note_body.vue
+++ b/app/assets/javascripts/notes/components/note_body.vue
@@ -83,10 +83,12 @@ export default {
formCancelHandler(shouldConfirm, isDirty) {
this.$emit('cancelForm', shouldConfirm, isDirty);
},
- applySuggestion({ suggestionId, flashContainer, callback }) {
+ applySuggestion({ suggestionId, flashContainer, callback = () => {} }) {
const { discussion_id: discussionId, id: noteId } = this.note;
- this.submitSuggestion({ discussionId, noteId, suggestionId, flashContainer, callback });
+ return this.submitSuggestion({ discussionId, noteId, suggestionId, flashContainer }).then(
+ callback,
+ );
},
},
};
@@ -122,6 +124,7 @@ export default {
v-model="note.note"
:data-update-url="note.path"
class="hidden js-task-list-field"
+ dir="auto"
></textarea>
<note-edited-text
v-if="note.last_edited_at"
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index 471323bfc83..09ecb695214 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -8,6 +8,7 @@ import issuableStateMixin from '../mixins/issuable_state';
import resolvable from '../mixins/resolvable';
import { __ } from '~/locale';
import { getDraft, updateDraft } from '~/lib/utils/autosave';
+import noteFormMixin from 'ee_else_ce/notes/mixins/note_form';
export default {
name: 'NoteForm',
@@ -15,7 +16,7 @@ export default {
issueWarning,
markdownField,
},
- mixins: [issuableStateMixin, resolvable],
+ mixins: [issuableStateMixin, resolvable, noteFormMixin],
props: {
noteBody: {
type: String,
@@ -195,21 +196,6 @@ export default {
return shouldResolve || shouldToggleState;
},
- handleKeySubmit() {
- this.handleUpdate();
- },
- handleUpdate(shouldResolve) {
- const beforeSubmitDiscussionState = this.discussionResolved;
- this.isSubmitting = true;
-
- this.$emit('handleFormUpdate', this.updatedNoteBody, this.$refs.editNoteForm, () => {
- this.isSubmitting = false;
-
- if (this.shouldToggleResolved(shouldResolve, beforeSubmitDiscussionState)) {
- this.resolveHandler(beforeSubmitDiscussionState);
- }
- });
- },
editMyLastNote() {
if (this.updatedNoteBody === '') {
const lastNoteInDiscussion = this.getDiscussionLastNote(this.discussion);
@@ -248,6 +234,8 @@ export default {
v-if="hasWarning(getNoteableData)"
:is-locked="isLocked(getNoteableData)"
:is-confidential="isConfidential(getNoteableData)"
+ :locked-issue-docs-path="lockedIssueDocsPath"
+ :confidential-issue-docs-path="confidentialIssueDocsPath"
/>
<markdown-field
@@ -268,6 +256,7 @@ export default {
:data-supports-quick-actions="!isEditing"
name="note[note]"
class="note-textarea js-gfm-input js-note-text js-autosize markdown-area js-vue-issue-note-form js-vue-textarea qa-reply-input"
+ dir="auto"
aria-label="Description"
placeholder="Write a comment or drag your files here…"
@keydown.meta.enter="handleKeySubmit()"
@@ -278,28 +267,74 @@ export default {
></textarea>
</markdown-field>
<div class="note-form-actions clearfix">
- <button
- :disabled="isDisabled"
- type="button"
- class="js-vue-issue-save btn btn-success js-comment-button qa-reply-comment-button"
- @click="handleUpdate()"
- >
- {{ saveButtonTitle }}
- </button>
- <button
- v-if="discussion.resolvable"
- class="btn btn-nr btn-default append-right-10 js-comment-resolve-button"
- @click.prevent="handleUpdate(true)"
- >
- {{ resolveButtonTitle }}
- </button>
- <button
- class="btn btn-cancel note-edit-cancel js-close-discussion-note-form"
- type="button"
- @click="cancelHandler()"
- >
- Cancel
- </button>
+ <template v-if="showBatchCommentsActions">
+ <p v-if="showResolveDiscussionToggle">
+ <label>
+ <template v-if="discussionResolved">
+ <input
+ v-model="isUnresolving"
+ type="checkbox"
+ class="qa-unresolve-review-discussion"
+ />
+ {{ __('Unresolve discussion') }}
+ </template>
+ <template v-else>
+ <input v-model="isResolving" type="checkbox" class="qa-resolve-review-discussion" />
+ {{ __('Resolve discussion') }}
+ </template>
+ </label>
+ </p>
+ <div>
+ <button
+ :disabled="isDisabled"
+ type="button"
+ class="btn btn-success qa-start-review"
+ @click="handleAddToReview"
+ >
+ <template v-if="hasDrafts">{{ __('Add to review') }}</template>
+ <template v-else>{{ __('Start a review') }}</template>
+ </button>
+ <button
+ :disabled="isDisabled"
+ type="button"
+ class="btn qa-comment-now"
+ @click="handleUpdate()"
+ >
+ {{ __('Add comment now') }}
+ </button>
+ <button
+ class="btn btn-cancel note-edit-cancel js-close-discussion-note-form"
+ type="button"
+ @click="cancelHandler()"
+ >
+ {{ __('Cancel') }}
+ </button>
+ </div>
+ </template>
+ <template v-else>
+ <button
+ :disabled="isDisabled"
+ type="button"
+ class="js-vue-issue-save btn btn-success js-comment-button qa-reply-comment-button"
+ @click="handleUpdate()"
+ >
+ {{ saveButtonTitle }}
+ </button>
+ <button
+ v-if="discussion.resolvable"
+ class="btn btn-nr btn-default append-right-10 js-comment-resolve-button"
+ @click.prevent="handleUpdate(true)"
+ >
+ {{ resolveButtonTitle }}
+ </button>
+ <button
+ class="btn btn-cancel note-edit-cancel js-close-discussion-note-form"
+ type="button"
+ @click="cancelHandler()"
+ >
+ Cancel
+ </button>
+ </template>
</div>
</form>
</div>
diff --git a/app/assets/javascripts/notes/components/note_header.vue b/app/assets/javascripts/notes/components/note_header.vue
index 5c59c0c32dd..fbf82fab9e9 100644
--- a/app/assets/javascripts/notes/components/note_header.vue
+++ b/app/assets/javascripts/notes/components/note_header.vue
@@ -82,7 +82,7 @@ export default {
:data-username="author.username"
>
<slot name="note-header-info"></slot>
- <span class="note-header-author-name">{{ author.name }}</span>
+ <span class="note-header-author-name bold">{{ author.name }}</span>
<span v-if="author.status_tooltip_html" v-html="author.status_tooltip_html"></span>
<span class="note-headline-light">@{{ author.username }}</span>
</a>
diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue
index a3d664a738f..eb6a4a67fff 100644
--- a/app/assets/javascripts/notes/components/noteable_discussion.vue
+++ b/app/assets/javascripts/notes/components/noteable_discussion.vue
@@ -5,51 +5,36 @@ import { GlTooltipDirective } from '@gitlab/ui';
import { truncateSha } from '~/lib/utils/text_utility';
import { s__, __, sprintf } from '~/locale';
import { clearDraft, getDiscussionReplyKey } from '~/lib/utils/autosave';
-import systemNote from '~/vue_shared/components/notes/system_note.vue';
import icon from '~/vue_shared/components/icon.vue';
import diffLineNoteFormMixin from 'ee_else_ce/notes/mixins/diff_line_note_form';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import Flash from '../../flash';
-import { SYSTEM_NOTE } from '../constants';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
-import noteableNote from './noteable_note.vue';
import noteHeader from './note_header.vue';
-import resolveDiscussionButton from './discussion_resolve_button.vue';
-import toggleRepliesWidget from './toggle_replies_widget.vue';
import noteSignedOutWidget from './note_signed_out_widget.vue';
import noteEditedText from './note_edited_text.vue';
import noteForm from './note_form.vue';
import diffWithNote from './diff_with_note.vue';
-import placeholderNote from '../../vue_shared/components/notes/placeholder_note.vue';
-import placeholderSystemNote from '../../vue_shared/components/notes/placeholder_system_note.vue';
import noteable from '../mixins/noteable';
import resolvable from '../mixins/resolvable';
import discussionNavigation from '../mixins/discussion_navigation';
-import ReplyPlaceholder from './discussion_reply_placeholder.vue';
-import ResolveWithIssueButton from './discussion_resolve_with_issue_button.vue';
-import jumpToNextDiscussionButton from './discussion_jump_to_next_button.vue';
import eventHub from '../event_hub';
+import DiscussionNotes from './discussion_notes.vue';
+import DiscussionActions from './discussion_actions.vue';
export default {
name: 'NoteableDiscussion',
components: {
icon,
- noteableNote,
userAvatarLink,
noteHeader,
noteSignedOutWidget,
noteEditedText,
noteForm,
- resolveDiscussionButton,
- jumpToNextDiscussionButton,
- toggleRepliesWidget,
- ReplyPlaceholder,
- placeholderNote,
- placeholderSystemNote,
- ResolveWithIssueButton,
- systemNote,
DraftNote: () => import('ee_component/batch_comments/components/draft_note.vue'),
TimelineEntryItem,
+ DiscussionNotes,
+ DiscussionActions,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -97,32 +82,28 @@ export default {
...mapGetters([
'convertedDisscussionIds',
'getNoteableData',
+ 'userCanReply',
'nextUnresolvedDiscussionId',
'unresolvedDiscussionsCount',
'hasUnresolvedDiscussions',
'showJumpToNextDiscussion',
+ 'getUserData',
]),
+ currentUser() {
+ return this.getUserData;
+ },
author() {
return this.firstNote.author;
},
autosaveKey() {
return getDiscussionReplyKey(this.firstNote.noteable_type, this.discussion.id);
},
- canReply() {
- return this.getNoteableData.current_user.can_create_note;
- },
newNotePath() {
return this.getNoteableData.create_note_path;
},
- hasReplies() {
- return this.discussion.notes.length > 1;
- },
firstNote() {
return this.discussion.notes.slice(0, 1)[0];
},
- replies() {
- return this.discussion.notes.slice(1);
- },
lastUpdatedBy() {
const { notes } = this.discussion;
@@ -228,18 +209,8 @@ export default {
return null;
},
- commit() {
- if (!this.discussion.for_commit) {
- return null;
- }
-
- return {
- id: this.discussion.commit_id,
- url: this.discussion.discussion_path,
- };
- },
resolveWithIssuePath() {
- return !this.discussionResolved && this.discussion.resolve_with_issue_path;
+ return !this.discussionResolved ? this.discussion.resolve_with_issue_path : '';
},
},
created() {
@@ -258,24 +229,6 @@ export default {
'removeConvertedDiscussion',
]),
truncateSha,
- componentName(note) {
- if (note.isPlaceholderNote) {
- if (note.placeholderType === SYSTEM_NOTE) {
- return placeholderSystemNote;
- }
-
- return placeholderNote;
- }
-
- if (note.system) {
- return systemNote;
- }
-
- return noteableNote;
- },
- componentData(note) {
- return note.isPlaceholderNote ? note.notes[0] : note;
- },
toggleDiscussionHandler() {
this.toggleDiscussion({ discussionId: this.discussion.id });
},
@@ -405,106 +358,73 @@ Please check your network connection and try again.`;
v-bind="wrapperComponentProps"
class="card discussion-wrapper"
>
- <div class="discussion-notes">
- <ul class="notes">
- <template v-if="shouldGroupReplies">
- <component
- :is="componentName(firstNote)"
- :note="componentData(firstNote)"
- :line="line"
- :commit="commit"
- :help-page-path="helpPagePath"
- :show-reply-button="canReply"
- @handleDeleteNote="deleteNoteHandler"
- @startReplying="showReplyForm"
- >
- <note-edited-text
- v-if="discussion.resolved"
- slot="discussion-resolved-text"
- :edited-at="discussion.resolved_at"
- :edited-by="discussion.resolved_by"
- :action-text="resolvedText"
- class-name="discussion-headline-light js-discussion-headline discussion-resolved-text"
- />
- <slot slot="avatar-badge" name="avatar-badge"></slot>
- </component>
- <toggle-replies-widget
- v-if="hasReplies"
- :collapsed="!isExpanded"
- :replies="replies"
- @toggle="toggleDiscussionHandler"
+ <discussion-notes
+ :discussion="discussion"
+ :diff-line="diffLine"
+ :help-page-path="helpPagePath"
+ :is-expanded="isExpanded"
+ :line="line"
+ :should-group-replies="shouldGroupReplies"
+ @startReplying="showReplyForm"
+ @toggleDiscussion="toggleDiscussionHandler"
+ @deleteNote="deleteNoteHandler"
+ >
+ <slot slot="avatar-badge" name="avatar-badge"></slot>
+ <template #footer="{ showReplies }">
+ <draft-note
+ v-if="showDraft(discussion.reply_id)"
+ :key="`draft_${discussion.id}`"
+ :draft="draftForDiscussion(discussion.reply_id)"
+ />
+ <div
+ v-else-if="showReplies"
+ :class="{ 'is-replying': isReplying }"
+ class="discussion-reply-holder"
+ >
+ <user-avatar-link
+ v-if="!isReplying && currentUser"
+ :link-href="currentUser.path"
+ :img-src="currentUser.avatar_url"
+ :img-alt="currentUser.name"
+ :img-size="40"
+ class="d-none d-sm-block"
/>
- <template v-if="isExpanded">
- <component
- :is="componentName(note)"
- v-for="note in replies"
- :key="note.id"
- :note="componentData(note)"
- :help-page-path="helpPagePath"
- :line="line"
- @handleDeleteNote="deleteNoteHandler"
+ <discussion-actions
+ v-if="!isReplying && userCanReply"
+ :discussion="discussion"
+ :is-resolving="isResolving"
+ :resolve-button-title="resolveButtonTitle"
+ :resolve-with-issue-path="resolveWithIssuePath"
+ :should-show-jump-to-next-discussion="shouldShowJumpToNextDiscussion"
+ @showReplyForm="showReplyForm"
+ @resolve="resolveHandler"
+ @jumpToNextDiscussion="jumpToNextDiscussion"
+ />
+ <div v-if="isReplying" class="avatar-note-form-holder">
+ <user-avatar-link
+ v-if="currentUser"
+ :link-href="currentUser.path"
+ :img-src="currentUser.avatar_url"
+ :img-alt="currentUser.name"
+ :img-size="40"
+ class="d-none d-sm-block"
/>
- </template>
- </template>
- <template v-else>
- <component
- :is="componentName(note)"
- v-for="(note, index) in discussion.notes"
- :key="note.id"
- :note="componentData(note)"
- :help-page-path="helpPagePath"
- :line="diffLine"
- @handleDeleteNote="deleteNoteHandler"
- >
- <slot v-if="index === 0" slot="avatar-badge" name="avatar-badge"></slot>
- </component>
- </template>
- </ul>
- <div
- v-if="isExpanded || !hasReplies"
- :class="{ 'is-replying': isReplying }"
- class="discussion-reply-holder"
- >
- <template v-if="!isReplying && canReply">
- <div class="discussion-with-resolve-btn">
- <reply-placeholder class="qa-discussion-reply" @onClick="showReplyForm" />
- <resolve-discussion-button
- v-if="discussion.resolvable"
- :is-resolving="isResolving"
- :button-title="resolveButtonTitle"
- @onClick="resolveHandler"
+ <note-form
+ ref="noteForm"
+ :discussion="discussion"
+ :is-editing="false"
+ :line="diffLine"
+ save-button-title="Comment"
+ :autosave-key="autosaveKey"
+ @handleFormUpdateAddToReview="addReplyToReview"
+ @handleFormUpdate="saveReply"
+ @cancelForm="cancelReplyForm"
/>
- <div
- v-if="discussion.resolvable"
- class="btn-group discussion-actions ml-sm-2"
- role="group"
- >
- <resolve-with-issue-button
- v-if="resolveWithIssuePath"
- :url="resolveWithIssuePath"
- />
- <jump-to-next-discussion-button
- v-if="shouldShowJumpToNextDiscussion"
- @onClick="jumpToNextDiscussion"
- />
- </div>
</div>
- </template>
- <note-form
- v-if="isReplying"
- ref="noteForm"
- :discussion="discussion"
- :is-editing="false"
- :line="diffLine"
- save-button-title="Comment"
- :autosave-key="autosaveKey"
- @handleFormUpdateAddToReview="addReplyToReview"
- @handleFormUpdate="saveReply"
- @cancelForm="cancelReplyForm"
- />
- <note-signed-out-widget v-if="!canReply" />
- </div>
- </div>
+ <note-signed-out-widget v-if="!userCanReply" />
+ </div>
+ </template>
+ </discussion-notes>
</component>
</div>
</div>
diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue
index 47d74c2f892..aa80e25a3e0 100644
--- a/app/assets/javascripts/notes/components/noteable_note.vue
+++ b/app/assets/javascripts/notes/components/noteable_note.vue
@@ -10,7 +10,7 @@ import Flash from '../../flash';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import noteHeader from './note_header.vue';
import noteActions from './note_actions.vue';
-import noteBody from './note_body.vue';
+import NoteBody from './note_body.vue';
import eventHub from '../event_hub';
import noteable from '../mixins/noteable';
import resolvable from '../mixins/resolvable';
@@ -21,7 +21,7 @@ export default {
userAvatarLink,
noteHeader,
noteActions,
- noteBody,
+ NoteBody,
TimelineEntryItem,
},
mixins: [noteable, resolvable, draftMixin],
@@ -75,7 +75,7 @@ export default {
};
},
canReportAsAbuse() {
- return !!this.note.report_abuse_path && this.author.id !== this.getUserData.id;
+ return Boolean(this.note.report_abuse_path) && this.author.id !== this.getUserData.id;
},
noteAnchorId() {
return `note_${this.note.id}`;
@@ -209,7 +209,10 @@ export default {
// we need to do this to prevent noteForm inconsistent content warning
// this is something we intentionally do so we need to recover the content
this.note.note = noteText;
- this.$refs.noteBody.note.note = noteText;
+ const { noteBody } = this.$refs;
+ if (noteBody) {
+ noteBody.note.note = noteText;
+ }
},
},
};
diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue
index e2bd59f7631..4d00e957973 100644
--- a/app/assets/javascripts/notes/components/notes_app.vue
+++ b/app/assets/javascripts/notes/components/notes_app.vue
@@ -67,6 +67,7 @@ export default {
'isLoading',
'commentsDisabled',
'getNoteableData',
+ 'userCanReply',
]),
noteableType() {
return this.noteableData.noteableType;
@@ -83,7 +84,7 @@ export default {
return this.discussions;
},
canReply() {
- return this.getNoteableData.current_user.can_create_note && !this.commentsDisabled;
+ return this.userCanReply && !this.commentsDisabled;
},
},
watch: {
@@ -126,6 +127,9 @@ export default {
initUserPopovers(this.$el.querySelectorAll('.js-user-link'));
});
},
+ beforeDestroy() {
+ this.stopPolling();
+ },
methods: {
...mapActions([
'setLoadingState',
@@ -143,6 +147,7 @@ export default {
'expandDiscussion',
'startTaskList',
'convertToDiscussion',
+ 'stopPolling',
]),
fetchNotes() {
if (this.isFetching) return null;
diff --git a/app/assets/javascripts/notes/mixins/autosave.js b/app/assets/javascripts/notes/mixins/autosave.js
index 4f45f912479..b161773f5f1 100644
--- a/app/assets/javascripts/notes/mixins/autosave.js
+++ b/app/assets/javascripts/notes/mixins/autosave.js
@@ -1,12 +1,13 @@
import $ from 'jquery';
import Autosave from '../../autosave';
import { capitalizeFirstCharacter } from '../../lib/utils/text_utility';
+import { s__ } from '~/locale';
export default {
methods: {
initAutoSave(noteable, extraKeys = []) {
let keys = [
- 'Note',
+ s__('Autosave|Note'),
capitalizeFirstCharacter(noteable.noteable_type || noteable.noteableType),
noteable.id,
];
diff --git a/app/assets/javascripts/notes/mixins/issuable_state.js b/app/assets/javascripts/notes/mixins/issuable_state.js
index 97f3ea0d5de..d97d9f6850a 100644
--- a/app/assets/javascripts/notes/mixins/issuable_state.js
+++ b/app/assets/javascripts/notes/mixins/issuable_state.js
@@ -1,11 +1,22 @@
+import { mapGetters } from 'vuex';
+
export default {
+ computed: {
+ ...mapGetters(['getNoteableDataByProp']),
+ lockedIssueDocsPath() {
+ return this.getNoteableDataByProp('locked_discussion_docs_path');
+ },
+ confidentialIssueDocsPath() {
+ return this.getNoteableDataByProp('confidential_issues_docs_path');
+ },
+ },
methods: {
isConfidential(issue) {
- return !!issue.confidential;
+ return Boolean(issue.confidential);
},
isLocked(issue) {
- return !!issue.discussion_locked;
+ return Boolean(issue.discussion_locked);
},
hasWarning(issue) {
diff --git a/app/assets/javascripts/notes/mixins/note_form.js b/app/assets/javascripts/notes/mixins/note_form.js
new file mode 100644
index 00000000000..b74879f2256
--- /dev/null
+++ b/app/assets/javascripts/notes/mixins/note_form.js
@@ -0,0 +1,24 @@
+export default {
+ data() {
+ return {
+ showBatchCommentsActions: false,
+ };
+ },
+ methods: {
+ handleKeySubmit() {
+ this.handleUpdate();
+ },
+ handleUpdate(shouldResolve) {
+ const beforeSubmitDiscussionState = this.discussionResolved;
+ this.isSubmitting = true;
+
+ this.$emit('handleFormUpdate', this.updatedNoteBody, this.$refs.editNoteForm, () => {
+ this.isSubmitting = false;
+
+ if (this.shouldToggleResolved(shouldResolve, beforeSubmitDiscussionState)) {
+ this.resolveHandler(beforeSubmitDiscussionState);
+ }
+ });
+ },
+ },
+};
diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js
index 1a0dba69a7c..63658d49a05 100644
--- a/app/assets/javascripts/notes/stores/actions.js
+++ b/app/assets/javascripts/notes/stores/actions.js
@@ -142,6 +142,23 @@ export const createNewNote = ({ commit, dispatch }, { endpoint, data }) =>
export const removePlaceholderNotes = ({ commit }) => commit(types.REMOVE_PLACEHOLDER_NOTES);
+export const resolveDiscussion = ({ state, dispatch, getters }, { discussionId }) => {
+ const discussion = utils.findNoteObjectById(state.discussions, discussionId);
+ const isResolved = getters.isDiscussionResolved(discussionId);
+
+ if (!discussion) {
+ return Promise.reject();
+ } else if (isResolved) {
+ return Promise.resolve();
+ }
+
+ return dispatch('toggleResolveNote', {
+ endpoint: discussion.resolve_path,
+ isResolved,
+ discussion: true,
+ });
+};
+
export const toggleResolveNote = ({ commit, dispatch }, { endpoint, isResolved, discussion }) =>
service
.toggleResolveNote(endpoint, isResolved)
@@ -251,11 +268,20 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
const { errors } = res;
const commandsChanges = res.commands_changes;
- if (hasQuickActions && errors && Object.keys(errors).length) {
- eTagPoll.makeRequest();
+ if (errors && Object.keys(errors).length) {
+ /*
+ The following reply means that quick actions have been successfully applied:
+
+ {"commands_changes":{},"valid":false,"errors":{"commands_only":["Commands applied"]}}
+ */
+ if (hasQuickActions) {
+ eTagPoll.makeRequest();
- $('.js-gfm-input').trigger('clear-commands-cache.atwho');
- Flash('Commands applied', 'notice', noteData.flashContainer);
+ $('.js-gfm-input').trigger('clear-commands-cache.atwho');
+ Flash(__('Commands applied'), 'notice', noteData.flashContainer);
+ } else {
+ throw new Error(__('Failed to save comment!'));
+ }
}
if (commandsChanges) {
@@ -269,7 +295,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
})
.catch(() => {
Flash(
- 'Something went wrong while adding your award. Please try again.',
+ __('Something went wrong while adding your award. Please try again.'),
'alert',
noteData.flashContainer,
);
@@ -311,7 +337,7 @@ export const poll = ({ commit, state, getters, dispatch }) => {
data: state,
successCallback: resp =>
resp.json().then(data => pollSuccessCallBack(data, commit, state, getters, dispatch)),
- errorCallback: () => Flash('Something went wrong while fetching latest comments.'),
+ errorCallback: () => Flash(__('Something went wrong while fetching latest comments.')),
});
if (!Visibility.hidden()) {
@@ -347,7 +373,7 @@ export const fetchData = ({ commit, state, getters }) => {
.poll(requestData)
.then(resp => resp.json)
.then(data => pollSuccessCallBack(data, commit, state, getters))
- .catch(() => Flash('Something went wrong while fetching latest comments.'));
+ .catch(() => Flash(__('Something went wrong while fetching latest comments.')));
};
export const toggleAward = ({ commit, getters }, { awardName, noteId }) => {
@@ -420,15 +446,13 @@ export const updateResolvableDiscussonsCounts = ({ commit }) =>
commit(types.UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS);
export const submitSuggestion = (
- { commit },
- { discussionId, noteId, suggestionId, flashContainer, callback },
-) => {
+ { commit, dispatch },
+ { discussionId, noteId, suggestionId, flashContainer },
+) =>
service
.applySuggestion(suggestionId)
- .then(() => {
- commit(types.APPLY_SUGGESTION, { discussionId, noteId, suggestionId });
- callback();
- })
+ .then(() => commit(types.APPLY_SUGGESTION, { discussionId, noteId, suggestionId }))
+ .then(() => dispatch('resolveDiscussion', { discussionId }).catch(() => {}))
.catch(err => {
const defaultMessage = __(
'Something went wrong while applying the suggestion. Please try again.',
@@ -436,9 +460,7 @@ export const submitSuggestion = (
const flashMessage = err.response.data ? `${err.response.data.message}.` : defaultMessage;
Flash(__(flashMessage), 'alert', flashContainer);
- callback();
});
-};
export const convertToDiscussion = ({ commit }, noteId) =>
commit(types.CONVERT_TO_DISCUSSION, noteId);
diff --git a/app/assets/javascripts/notes/stores/getters.js b/app/assets/javascripts/notes/stores/getters.js
index fcc8889b0c7..d7982be3e4b 100644
--- a/app/assets/javascripts/notes/stores/getters.js
+++ b/app/assets/javascripts/notes/stores/getters.js
@@ -20,6 +20,8 @@ export const getNoteableData = state => state.noteableData;
export const getNoteableDataByProp = state => prop => state.noteableData[prop];
+export const userCanReply = state => Boolean(state.noteableData.current_user.can_create_note);
+
export const openState = state => state.noteableData.state;
export const getUserData = state => state.userData || {};
diff --git a/app/assets/javascripts/notes/stores/utils.js b/app/assets/javascripts/notes/stores/utils.js
index 4b0feb0f94d..ed4cef4a917 100644
--- a/app/assets/javascripts/notes/stores/utils.js
+++ b/app/assets/javascripts/notes/stores/utils.js
@@ -1,12 +1,14 @@
import AjaxCache from '~/lib/utils/ajax_cache';
import { trimFirstCharOfLineContent } from '~/diffs/store/utils';
+import { sprintf, __ } from '~/locale';
-const REGEX_QUICK_ACTIONS = /^\/\w+.*$/gm;
+// factory function because global flag makes RegExp stateful
+const createQuickActionsRegex = () => /^\/\w+.*$/gm;
export const findNoteObjectById = (notes, id) => notes.filter(n => n.id === id)[0];
export const getQuickActionText = note => {
- let text = 'Applying command';
+ let text = __('Applying command');
const quickActions = AjaxCache.get(gl.GfmAutoComplete.dataSources.commands) || [];
const executedCommands = quickActions.filter(command => {
@@ -16,19 +18,19 @@ export const getQuickActionText = note => {
if (executedCommands && executedCommands.length) {
if (executedCommands.length > 1) {
- text = 'Applying multiple commands';
+ text = __('Applying multiple commands');
} else {
const commandDescription = executedCommands[0].description.toLowerCase();
- text = `Applying command to ${commandDescription}`;
+ text = sprintf(__('Applying command to %{commandDescription}', { commandDescription }));
}
}
return text;
};
-export const hasQuickActions = note => REGEX_QUICK_ACTIONS.test(note);
+export const hasQuickActions = note => createQuickActionsRegex().test(note);
-export const stripQuickActions = note => note.replace(REGEX_QUICK_ACTIONS, '').trim();
+export const stripQuickActions = note => note.replace(createQuickActionsRegex(), '').trim();
export const prepareDiffLines = diffLines =>
diffLines.map(line => ({ ...trimFirstCharOfLineContent(line) }));
diff --git a/app/assets/javascripts/operation_settings/components/external_dashboard.vue b/app/assets/javascripts/operation_settings/components/external_dashboard.vue
new file mode 100644
index 00000000000..ed518611d0b
--- /dev/null
+++ b/app/assets/javascripts/operation_settings/components/external_dashboard.vue
@@ -0,0 +1,67 @@
+<script>
+import { mapState, mapActions } from 'vuex';
+import { GlButton, GlFormGroup, GlFormInput, GlLink } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlButton,
+ GlFormGroup,
+ GlFormInput,
+ GlLink,
+ },
+ computed: {
+ ...mapState([
+ 'externalDashboardHelpPagePath',
+ 'externalDashboardUrl',
+ 'operationsSettingsEndpoint',
+ ]),
+ userDashboardUrl: {
+ get() {
+ return this.externalDashboardUrl;
+ },
+ set(url) {
+ this.setExternalDashboardUrl(url);
+ },
+ },
+ },
+ methods: {
+ ...mapActions(['setExternalDashboardUrl', 'updateExternalDashboardUrl']),
+ },
+};
+</script>
+
+<template>
+ <section class="settings no-animate">
+ <div class="settings-header">
+ <h4 class="js-section-header">
+ {{ s__('ExternalMetrics|External Dashboard') }}
+ </h4>
+ <gl-button class="js-settings-toggle">{{ __('Expand') }}</gl-button>
+ <p class="js-section-sub-header">
+ {{
+ s__(
+ 'ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards.',
+ )
+ }}
+ <gl-link :href="externalDashboardHelpPagePath">{{ __('Learn more') }}</gl-link>
+ </p>
+ </div>
+ <div class="settings-content">
+ <form>
+ <gl-form-group
+ :label="s__('ExternalMetrics|Full dashboard URL')"
+ :description="s__('ExternalMetrics|Enter the URL of the dashboard you want to link to')"
+ >
+ <gl-form-input
+ v-model="userDashboardUrl"
+ placeholder="https://my-org.gitlab.io/my-dashboards"
+ @keydown.enter.native.prevent="updateExternalDashboardUrl"
+ />
+ </gl-form-group>
+ <gl-button variant="success" @click="updateExternalDashboardUrl">
+ {{ __('Save Changes') }}
+ </gl-button>
+ </form>
+ </div>
+ </section>
+</template>
diff --git a/app/assets/javascripts/operation_settings/index.js b/app/assets/javascripts/operation_settings/index.js
new file mode 100644
index 00000000000..f075291ce98
--- /dev/null
+++ b/app/assets/javascripts/operation_settings/index.js
@@ -0,0 +1,15 @@
+import Vue from 'vue';
+import store from './store';
+import ExternalDashboardForm from './components/external_dashboard.vue';
+
+export default () => {
+ const el = document.querySelector('.js-operation-settings');
+
+ return new Vue({
+ el,
+ store: store(el.dataset),
+ render(createElement) {
+ return createElement(ExternalDashboardForm);
+ },
+ });
+};
diff --git a/app/assets/javascripts/operation_settings/store/actions.js b/app/assets/javascripts/operation_settings/store/actions.js
new file mode 100644
index 00000000000..ec05b0c76cf
--- /dev/null
+++ b/app/assets/javascripts/operation_settings/store/actions.js
@@ -0,0 +1,38 @@
+import axios from '~/lib/utils/axios_utils';
+import { __ } from '~/locale';
+import createFlash from '~/flash';
+import { refreshCurrentPage } from '~/lib/utils/url_utility';
+import * as mutationTypes from './mutation_types';
+
+export const setExternalDashboardUrl = ({ commit }, url) =>
+ commit(mutationTypes.SET_EXTERNAL_DASHBOARD_URL, url);
+
+export const updateExternalDashboardUrl = ({ state, dispatch }) =>
+ axios
+ .patch(state.operationsSettingsEndpoint, {
+ project: {
+ metrics_setting_attributes: {
+ external_dashboard_url: state.externalDashboardUrl,
+ },
+ },
+ })
+ .then(() => dispatch('receiveExternalDashboardUpdateSuccess'))
+ .catch(error => dispatch('receiveExternalDashboardUpdateError', error));
+
+export const receiveExternalDashboardUpdateSuccess = () => {
+ /**
+ * The operations_controller currently handles successful requests
+ * by creating a flash banner messsage to notify the user.
+ */
+ refreshCurrentPage();
+};
+
+export const receiveExternalDashboardUpdateError = (_, error) => {
+ const { response } = error;
+ const message = response.data && response.data.message ? response.data.message : '';
+
+ createFlash(`${__('There was an error saving your changes.')} ${message}`, 'alert');
+};
+
+// prevent babel-plugin-rewire from generating an invalid default during karma tests
+export default () => {};
diff --git a/app/assets/javascripts/operation_settings/store/index.js b/app/assets/javascripts/operation_settings/store/index.js
new file mode 100644
index 00000000000..e96bb1e8aad
--- /dev/null
+++ b/app/assets/javascripts/operation_settings/store/index.js
@@ -0,0 +1,16 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import createState from './state';
+import * as actions from './actions';
+import mutations from './mutations';
+
+Vue.use(Vuex);
+
+export const createStore = initialState =>
+ new Vuex.Store({
+ state: createState(initialState),
+ actions,
+ mutations,
+ });
+
+export default createStore;
diff --git a/app/assets/javascripts/operation_settings/store/mutation_types.js b/app/assets/javascripts/operation_settings/store/mutation_types.js
new file mode 100644
index 00000000000..237d2b6122f
--- /dev/null
+++ b/app/assets/javascripts/operation_settings/store/mutation_types.js
@@ -0,0 +1,3 @@
+/* eslint-disable import/prefer-default-export */
+
+export const SET_EXTERNAL_DASHBOARD_URL = 'SET_EXTERNAL_DASHBOARD_URL';
diff --git a/app/assets/javascripts/operation_settings/store/mutations.js b/app/assets/javascripts/operation_settings/store/mutations.js
new file mode 100644
index 00000000000..64bb33bb89f
--- /dev/null
+++ b/app/assets/javascripts/operation_settings/store/mutations.js
@@ -0,0 +1,7 @@
+import * as types from './mutation_types';
+
+export default {
+ [types.SET_EXTERNAL_DASHBOARD_URL](state, url) {
+ state.externalDashboardUrl = url;
+ },
+};
diff --git a/app/assets/javascripts/operation_settings/store/state.js b/app/assets/javascripts/operation_settings/store/state.js
new file mode 100644
index 00000000000..72167141c48
--- /dev/null
+++ b/app/assets/javascripts/operation_settings/store/state.js
@@ -0,0 +1,5 @@
+export default (initialState = {}) => ({
+ externalDashboardUrl: initialState.externalDashboardUrl || '',
+ operationsSettingsEndpoint: initialState.operationsSettingsEndpoint,
+ externalDashboardHelpPagePath: initialState.externalDashboardHelpPagePath,
+});
diff --git a/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js b/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
index d5ded3f9a79..6e00e31b828 100644
--- a/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
+++ b/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
@@ -22,7 +22,7 @@ export default () => {
_.debounce(function onMessageInput() {
const message = $(this).val();
if (message === '') {
- $('.js-broadcast-message-preview').text('Your message here');
+ $('.js-broadcast-message-preview').text(__('Your message here'));
} else {
axios
.post(previewPath, {
diff --git a/app/assets/javascripts/pages/admin/clusters/destroy/index.js b/app/assets/javascripts/pages/admin/clusters/destroy/index.js
new file mode 100644
index 00000000000..8001d2dd1da
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/clusters/destroy/index.js
@@ -0,0 +1,5 @@
+import ClustersBundle from '~/clusters/clusters_bundle';
+
+document.addEventListener('DOMContentLoaded', () => {
+ new ClustersBundle(); // eslint-disable-line no-new
+});
diff --git a/app/assets/javascripts/pages/admin/clusters/edit/index.js b/app/assets/javascripts/pages/admin/clusters/edit/index.js
new file mode 100644
index 00000000000..8001d2dd1da
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/clusters/edit/index.js
@@ -0,0 +1,5 @@
+import ClustersBundle from '~/clusters/clusters_bundle';
+
+document.addEventListener('DOMContentLoaded', () => {
+ new ClustersBundle(); // eslint-disable-line no-new
+});
diff --git a/app/assets/javascripts/pages/admin/clusters/index.js b/app/assets/javascripts/pages/admin/clusters/index.js
new file mode 100644
index 00000000000..d0c9ae66c6a
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/clusters/index.js
@@ -0,0 +1,21 @@
+import PersistentUserCallout from '~/persistent_user_callout';
+import initGkeDropdowns from '~/projects/gke_cluster_dropdowns';
+
+function initGcpSignupCallout() {
+ const callout = document.querySelector('.gcp-signup-offer');
+ PersistentUserCallout.factory(callout);
+}
+
+document.addEventListener('DOMContentLoaded', () => {
+ const { page } = document.body.dataset;
+ const newClusterViews = [
+ 'admin:clusters:new',
+ 'admin:clusters:create_gcp',
+ 'admin:clusters:create_user',
+ ];
+
+ if (newClusterViews.indexOf(page) > -1) {
+ initGcpSignupCallout();
+ initGkeDropdowns();
+ }
+});
diff --git a/app/assets/javascripts/pages/admin/clusters/index/index.js b/app/assets/javascripts/pages/admin/clusters/index/index.js
new file mode 100644
index 00000000000..30d519d0e37
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/clusters/index/index.js
@@ -0,0 +1,6 @@
+import PersistentUserCallout from '~/persistent_user_callout';
+
+document.addEventListener('DOMContentLoaded', () => {
+ const callout = document.querySelector('.gcp-signup-offer');
+ PersistentUserCallout.factory(callout);
+});
diff --git a/app/assets/javascripts/pages/admin/clusters/show/index.js b/app/assets/javascripts/pages/admin/clusters/show/index.js
new file mode 100644
index 00000000000..8001d2dd1da
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/clusters/show/index.js
@@ -0,0 +1,5 @@
+import ClustersBundle from '~/clusters/clusters_bundle';
+
+document.addEventListener('DOMContentLoaded', () => {
+ new ClustersBundle(); // eslint-disable-line no-new
+});
diff --git a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
index ae0a8c74964..8a5300c9266 100644
--- a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
+++ b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
@@ -12,5 +12,6 @@ document.addEventListener('DOMContentLoaded', () => {
saveButton: variableListEl.querySelector('.js-ci-variables-save-button'),
errorBox: variableListEl.querySelector('.js-ci-variable-error-box'),
saveEndpoint: variableListEl.dataset.saveEndpoint,
+ maskableRegex: variableListEl.dataset.maskableRegex,
});
});
diff --git a/app/assets/javascripts/pages/groups/show/index.js b/app/assets/javascripts/pages/groups/show/index.js
index af924e74f1f..82ee5ead83d 100644
--- a/app/assets/javascripts/pages/groups/show/index.js
+++ b/app/assets/javascripts/pages/groups/show/index.js
@@ -1,5 +1,7 @@
+import leaveByUrl from '~/namespaces/leave_by_url';
import initGroupDetails from '../shared/group_details';
document.addEventListener('DOMContentLoaded', () => {
+ leaveByUrl('group');
initGroupDetails();
});
diff --git a/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue b/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
index a79ef07f1c5..c563514d36b 100644
--- a/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
+++ b/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
@@ -33,8 +33,7 @@ export default {
text() {
return sprintf(
s__(`Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}.
- Existing project milestones with the same title will be merged.
- This action cannot be reversed.`),
+ Existing project milestones with the same title will be merged.`),
{ milestoneTitle: this.milestoneTitle, groupName: this.groupName },
);
},
@@ -72,6 +71,9 @@ export default {
<template slot="title">
{{ title }}
</template>
- {{ text }}
+ <div>
+ <p>{{ text }}</p>
+ <p>{{ s__('Milestones|This action cannot be reversed.') }}</p>
+ </div>
</gl-modal>
</template>
diff --git a/app/assets/javascripts/pages/profiles/keys/index.js b/app/assets/javascripts/pages/profiles/keys/index.js
index 1cd3ee1dfdb..d3dcd21f456 100644
--- a/app/assets/javascripts/pages/profiles/keys/index.js
+++ b/app/assets/javascripts/pages/profiles/keys/index.js
@@ -2,6 +2,8 @@ import AddSshKeyValidation from '~/profile/add_ssh_key_validation';
document.addEventListener('DOMContentLoaded', () => {
const input = document.querySelector('.js-add-ssh-key-validation-input');
+ if (!input) return;
+
const warning = document.querySelector('.js-add-ssh-key-validation-warning');
const originalSubmit = input.form.querySelector('.js-add-ssh-key-validation-original-submit');
const confirmSubmit = warning.querySelector('.js-add-ssh-key-validation-confirm-submit');
diff --git a/app/assets/javascripts/pages/profiles/show/index.js b/app/assets/javascripts/pages/profiles/show/index.js
index 0dd0d5336fc..13cb0d6f74b 100644
--- a/app/assets/javascripts/pages/profiles/show/index.js
+++ b/app/assets/javascripts/pages/profiles/show/index.js
@@ -1,8 +1,9 @@
import $ from 'jquery';
import createFlash from '~/flash';
-import GfmAutoComplete from '~/gfm_auto_complete';
+import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
import emojiRegex from 'emoji-regex';
import EmojiMenu from './emoji_menu';
+import { __ } from '~/locale';
const defaultStatusEmoji = 'speech_balloon';
@@ -48,7 +49,7 @@ document.addEventListener('DOMContentLoaded', () => {
const EMOJI_REGEX = emojiRegex();
if (EMOJI_REGEX.test(userNameInput.value)) {
// set field to invalid so it gets detected by GlFieldErrors
- userNameInput.setCustomValidity('Invalid field');
+ userNameInput.setCustomValidity(__('Invalid field'));
} else {
userNameInput.setCustomValidity('');
}
@@ -81,5 +82,5 @@ document.addEventListener('DOMContentLoaded', () => {
}
});
})
- .catch(() => createFlash('Failed to load emoji list.'));
+ .catch(() => createFlash(__('Failed to load emoji list.')));
});
diff --git a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js
index 377dce6c746..506e6075d16 100644
--- a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js
+++ b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js
@@ -124,11 +124,14 @@ export const ContributorsGraph = (function() {
};
ContributorsGraph.prototype.draw_x_axis = function() {
- return this.svg
- .append('g')
- .attr('class', 'x axis')
- .attr('transform', 'translate(0, ' + this.height + ')')
- .call(this.x_axis);
+ return (
+ this.svg
+ .append('g')
+ .attr('class', 'x axis')
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
+ .attr('transform', 'translate(0, ' + this.height + ')')
+ .call(this.x_axis)
+ );
};
ContributorsGraph.prototype.draw_y_axis = function() {
@@ -205,6 +208,7 @@ export const ContributorsMasterGraph = (function(superClass) {
.attr('height', this.height + this.MARGIN.top + this.MARGIN.bottom)
.attr('class', 'tint-box')
.append('g')
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
.attr('transform', 'translate(' + this.MARGIN.left + ',' + this.MARGIN.top + ')');
return this.svg;
};
@@ -354,6 +358,7 @@ export const ContributorsAuthorGraph = (function(superClass) {
.attr('height', this.height + this.MARGIN.top + this.MARGIN.bottom)
.attr('class', 'spark')
.append('g')
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
.attr('transform', 'translate(' + this.MARGIN.left + ',' + this.MARGIN.top + ')');
return this.svg;
};
diff --git a/app/assets/javascripts/pages/projects/issues/index/index.js b/app/assets/javascripts/pages/projects/issues/index/index.js
index 8bf0c2edc71..c34aff02111 100644
--- a/app/assets/javascripts/pages/projects/issues/index/index.js
+++ b/app/assets/javascripts/pages/projects/issues/index/index.js
@@ -4,9 +4,9 @@ import IssuableIndex from '~/issuable_index';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import UsersSelect from '~/users_select';
import initFilteredSearch from '~/pages/search/init_filtered_search';
-import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
import { FILTERED_SEARCH } from '~/pages/constants';
import { ISSUABLE_INDEX } from '~/pages/projects/constants';
+import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
document.addEventListener('DOMContentLoaded', () => {
IssuableFilteredSearchTokenKeys.addExtraTokensForIssues();
diff --git a/app/assets/javascripts/pages/projects/pages_domains/edit/index.js b/app/assets/javascripts/pages/projects/pages_domains/edit/index.js
new file mode 100644
index 00000000000..27e4433ad4d
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pages_domains/edit/index.js
@@ -0,0 +1,3 @@
+import initForm from '~/pages/projects/pages_domains/form';
+
+document.addEventListener('DOMContentLoaded', initForm);
diff --git a/app/assets/javascripts/pages/projects/pages_domains/form.js b/app/assets/javascripts/pages/projects/pages_domains/form.js
new file mode 100644
index 00000000000..1d0dbfe0406
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pages_domains/form.js
@@ -0,0 +1,43 @@
+import setupToggleButtons from '~/toggle_buttons';
+
+export default () => {
+ const toggleContainer = document.querySelector('.js-auto-ssl-toggle-container');
+
+ if (toggleContainer) {
+ const onToggleButtonClicked = isAutoSslEnabled => {
+ Array.from(document.querySelectorAll('.js-shown-if-auto-ssl')).forEach(el => {
+ if (isAutoSslEnabled) {
+ el.classList.remove('d-none');
+ } else {
+ el.classList.add('d-none');
+ }
+ });
+
+ Array.from(document.querySelectorAll('.js-shown-unless-auto-ssl')).forEach(el => {
+ if (isAutoSslEnabled) {
+ el.classList.add('d-none');
+ } else {
+ el.classList.remove('d-none');
+ }
+ });
+
+ Array.from(document.querySelectorAll('.js-enabled-if-auto-ssl')).forEach(el => {
+ if (isAutoSslEnabled) {
+ el.removeAttribute('disabled');
+ } else {
+ el.setAttribute('disabled', 'disabled');
+ }
+ });
+
+ Array.from(document.querySelectorAll('.js-enabled-unless-auto-ssl')).forEach(el => {
+ if (isAutoSslEnabled) {
+ el.setAttribute('disabled', 'disabled');
+ } else {
+ el.removeAttribute('disabled');
+ }
+ });
+ };
+
+ setupToggleButtons(toggleContainer, onToggleButtonClicked);
+ }
+};
diff --git a/app/assets/javascripts/pages/projects/pages_domains/new/index.js b/app/assets/javascripts/pages/projects/pages_domains/new/index.js
new file mode 100644
index 00000000000..27e4433ad4d
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pages_domains/new/index.js
@@ -0,0 +1,3 @@
+import initForm from '~/pages/projects/pages_domains/form';
+
+document.addEventListener('DOMContentLoaded', initForm);
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
index bd4309e47ad..bb490919a9a 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
@@ -29,7 +29,7 @@ export default {
// The text input is editable when there's a custom interval, or when it's
// a preset interval and the user clicks the 'custom' radio button
isEditable() {
- return !!(this.customInputEnabled || !this.intervalIsPreset);
+ return Boolean(this.customInputEnabled || !this.intervalIsPreset);
},
},
watch: {
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js
index c1f6edf2f27..a20a0526f12 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js
@@ -1,4 +1,10 @@
-const defaultTimezone = 'UTC';
+const defaultTimezone = { name: 'UTC', offset: 0 };
+const defaults = {
+ $inputEl: null,
+ $dropdownEl: null,
+ onSelectTimezone: null,
+ displayFormat: item => item.name,
+};
export const formatUtcOffset = offset => {
const parsed = parseInt(offset, 10);
@@ -11,23 +17,28 @@ export const formatUtcOffset = offset => {
export const formatTimezone = item => `[UTC ${formatUtcOffset(item.offset)}] ${item.name}`;
-const defaults = {
- $inputEl: null,
- $dropdownEl: null,
- onSelectTimezone: null,
+export const findTimezoneByIdentifier = (tzList = [], identifier = null) => {
+ if (tzList && tzList.length && identifier && identifier.length) {
+ return tzList.find(tz => tz.identifier === identifier) || null;
+ }
+ return null;
};
export default class TimezoneDropdown {
- constructor({ $dropdownEl, $inputEl, onSelectTimezone } = defaults) {
+ constructor({ $dropdownEl, $inputEl, onSelectTimezone, displayFormat } = defaults) {
this.$dropdown = $dropdownEl;
this.$dropdownToggle = this.$dropdown.find('.dropdown-toggle-text');
this.$input = $inputEl;
this.timezoneData = this.$dropdown.data('data');
+ this.onSelectTimezone = onSelectTimezone;
+ this.displayFormat = displayFormat || defaults.displayFormat;
+
+ this.initialTimezone =
+ findTimezoneByIdentifier(this.timezoneData, this.$input.val()) || defaultTimezone;
+
this.initDefaultTimezone();
this.initDropdown();
-
- this.onSelectTimezone = onSelectTimezone;
}
initDropdown() {
@@ -35,7 +46,7 @@ export default class TimezoneDropdown {
data: this.timezoneData,
filterable: true,
selectable: true,
- toggleLabel: item => item.name,
+ toggleLabel: this.displayFormat,
search: {
fields: ['name'],
},
@@ -43,20 +54,17 @@ export default class TimezoneDropdown {
text: item => formatTimezone(item),
});
- this.setDropdownToggle();
+ this.setDropdownToggle(this.displayFormat(this.initialTimezone));
}
initDefaultTimezone() {
- const initialValue = this.$input.val();
-
- if (!initialValue) {
- this.$input.val(defaultTimezone);
+ if (!this.$input.val()) {
+ this.$input.val(defaultTimezone.name);
}
}
- setDropdownToggle() {
- const initialValue = this.$input.val();
- this.$dropdownToggle.text(initialValue);
+ setDropdownToggle(dropdownText) {
+ this.$dropdownToggle.text(dropdownText);
}
updateInputValue({ selectedObj, e }) {
diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js
index b288989b252..f0d529758d5 100644
--- a/app/assets/javascripts/pages/projects/project.js
+++ b/app/assets/javascripts/pages/projects/project.js
@@ -39,6 +39,11 @@ export default class Project {
$label.text(activeText);
});
+ $('#modal-geo-info').data({
+ cloneUrlSecondary: $this.attr('href'),
+ cloneUrlPrimary: $this.data('primaryUrl') || '',
+ });
+
if (mobileCloneField) {
mobileCloneField.dataset.clipboardText = url;
} else {
@@ -67,6 +72,13 @@ export default class Project {
.remove();
return e.preventDefault();
});
+ $('.hide-shared-runner-limit-message').on('click', function(e) {
+ var $alert = $(this).parents('.shared-runner-quota-message');
+ var scope = $alert.data('scope');
+ Cookies.set('hide_shared_runner_quota_message', 'false', { path: scope });
+ $alert.remove();
+ e.preventDefault();
+ });
$('.hide-auto-devops-implicitly-enabled-banner').on('click', function(e) {
const projectId = $(this).data('project-id');
const cookieKey = `hide_auto_devops_implicitly_enabled_banner_${projectId}`;
diff --git a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
index 15c6fb550c1..885247335a4 100644
--- a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
@@ -21,6 +21,7 @@ document.addEventListener('DOMContentLoaded', () => {
saveButton: variableListEl.querySelector('.js-ci-variables-save-button'),
errorBox: variableListEl.querySelector('.js-ci-variable-error-box'),
saveEndpoint: variableListEl.dataset.saveEndpoint,
+ maskableRegex: variableListEl.dataset.maskableRegex,
});
// hide extra auto devops settings based checkbox state
diff --git a/app/assets/javascripts/pages/projects/settings/operations/show/index.js b/app/assets/javascripts/pages/projects/settings/operations/show/index.js
index 73c745179be..98e19705976 100644
--- a/app/assets/javascripts/pages/projects/settings/operations/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/operations/show/index.js
@@ -1,5 +1,9 @@
import mountErrorTrackingForm from '~/error_tracking_settings';
+import mountOperationSettings from '~/operation_settings';
+import initSettingsPanels from '~/settings_panels';
document.addEventListener('DOMContentLoaded', () => {
mountErrorTrackingForm();
+ mountOperationSettings();
+ initSettingsPanels();
});
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
index 19d9903c988..dea7c586868 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
@@ -175,11 +175,6 @@ export default {
if (value === 0) toggleHiddenClassBySelector('.merge-requests-feature', true);
else if (oldValue === 0) toggleHiddenClassBySelector('.merge-requests-feature', false);
},
-
- buildsAccessLevel(value, oldValue) {
- if (value === 0) toggleHiddenClassBySelector('.builds-feature', true);
- else if (oldValue === 0) toggleHiddenClassBySelector('.builds-feature', false);
- },
},
methods: {
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/constants.js b/app/assets/javascripts/pages/projects/shared/permissions/constants.js
index bc5c29d12b5..ac0dca31c37 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/constants.js
+++ b/app/assets/javascripts/pages/projects/shared/permissions/constants.js
@@ -1,3 +1,5 @@
+import { __ } from '~/locale';
+
export const visibilityOptions = {
PRIVATE: 0,
INTERNAL: 10,
@@ -5,9 +7,11 @@ export const visibilityOptions = {
};
export const visibilityLevelDescriptions = {
- [visibilityOptions.PRIVATE]:
+ [visibilityOptions.PRIVATE]: __(
'The project is accessible only by members of the project. Access must be granted explicitly to each user.',
- [visibilityOptions.INTERNAL]: 'The project can be accessed by any user who is logged in.',
- [visibilityOptions.PUBLIC]:
+ ),
+ [visibilityOptions.INTERNAL]: __('The project can be accessed by any user who is logged in.'),
+ [visibilityOptions.PUBLIC]: __(
'The project can be accessed by anyone, regardless of authentication.',
+ ),
};
diff --git a/app/assets/javascripts/pages/projects/show/index.js b/app/assets/javascripts/pages/projects/show/index.js
index 7302c1ab202..6aa41d0825b 100644
--- a/app/assets/javascripts/pages/projects/show/index.js
+++ b/app/assets/javascripts/pages/projects/show/index.js
@@ -9,6 +9,7 @@ import Activities from '~/activities';
import { ajaxGet } from '~/lib/utils/common_utils';
import GpgBadges from '~/gpg_badges';
import initReadMore from '~/read_more';
+import leaveByUrl from '~/namespaces/leave_by_url';
import Star from '../../../star';
import notificationsDropdown from '../../../notifications_dropdown';
@@ -44,4 +45,13 @@ document.addEventListener('DOMContentLoaded', () => {
});
GpgBadges.fetch();
+ leaveByUrl('project');
+
+ if (document.getElementById('js-tree-list')) {
+ import('~/repository')
+ .then(m => m.default())
+ .catch(e => {
+ throw e;
+ });
+ }
});
diff --git a/app/assets/javascripts/pages/projects/tree/show/index.js b/app/assets/javascripts/pages/projects/tree/show/index.js
index 400aed35e32..7b90a3a4f6e 100644
--- a/app/assets/javascripts/pages/projects/tree/show/index.js
+++ b/app/assets/javascripts/pages/projects/tree/show/index.js
@@ -40,4 +40,12 @@ document.addEventListener('DOMContentLoaded', () => {
}
GpgBadges.fetch();
+
+ if (document.getElementById('js-tree-list')) {
+ import('~/repository')
+ .then(m => m.default())
+ .catch(e => {
+ throw e;
+ });
+ }
});
diff --git a/app/assets/javascripts/pages/search/show/search.js b/app/assets/javascripts/pages/search/show/search.js
index 0c896c8599e..d5a8e712d6b 100644
--- a/app/assets/javascripts/pages/search/show/search.js
+++ b/app/assets/javascripts/pages/search/show/search.js
@@ -1,6 +1,7 @@
import $ from 'jquery';
import Flash from '~/flash';
import Api from '~/api';
+import { __ } from '~/locale';
export default class Search {
constructor() {
@@ -24,7 +25,7 @@ export default class Search {
data(term, callback) {
return Api.groups(term, {}, data => {
data.unshift({
- full_name: 'Any',
+ full_name: __('Any'),
});
data.splice(1, 0, 'divider');
return callback(data);
@@ -54,14 +55,14 @@ export default class Search {
this.getProjectsData(term)
.then(data => {
data.unshift({
- name_with_namespace: 'Any',
+ name_with_namespace: __('Any'),
});
data.splice(1, 0, 'divider');
return data;
})
.then(data => callback(data))
- .catch(() => new Flash('Error fetching projects'));
+ .catch(() => new Flash(__('Error fetching projects')));
},
id(obj) {
return obj.id;
diff --git a/app/assets/javascripts/pages/sessions/new/index.js b/app/assets/javascripts/pages/sessions/new/index.js
index e1a3f42a71f..3f5a3e15c2c 100644
--- a/app/assets/javascripts/pages/sessions/new/index.js
+++ b/app/assets/javascripts/pages/sessions/new/index.js
@@ -1,4 +1,5 @@
import $ from 'jquery';
+import LengthValidator from './length_validator';
import UsernameValidator from './username_validator';
import NoEmojiValidator from '../../../emoji/no_emoji_validator';
import SigninTabsMemoizer from './signin_tabs_memoizer';
@@ -6,6 +7,7 @@ import OAuthRememberMe from './oauth_remember_me';
import preserveUrlFragment from './preserve_url_fragment';
document.addEventListener('DOMContentLoaded', () => {
+ new LengthValidator(); // eslint-disable-line no-new
new UsernameValidator(); // eslint-disable-line no-new
new SigninTabsMemoizer(); // eslint-disable-line no-new
new NoEmojiValidator(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/sessions/new/length_validator.js b/app/assets/javascripts/pages/sessions/new/length_validator.js
new file mode 100644
index 00000000000..3d687ca08cc
--- /dev/null
+++ b/app/assets/javascripts/pages/sessions/new/length_validator.js
@@ -0,0 +1,32 @@
+import InputValidator from '../../../validators/input_validator';
+
+const errorMessageClass = 'gl-field-error';
+
+export default class LengthValidator extends InputValidator {
+ constructor(opts = {}) {
+ super();
+
+ const container = opts.container || '';
+ const validateLengthElements = document.querySelectorAll(`${container} .js-validate-length`);
+
+ validateLengthElements.forEach(element =>
+ element.addEventListener('input', this.eventHandler.bind(this)),
+ );
+ }
+
+ eventHandler(event) {
+ this.inputDomElement = event.target;
+ this.inputErrorMessage = this.inputDomElement.parentElement.querySelector(
+ `.${errorMessageClass}`,
+ );
+
+ const { value } = this.inputDomElement;
+ const { maxLengthMessage, maxLength } = this.inputDomElement.dataset;
+
+ this.errorMessage = maxLengthMessage;
+
+ this.invalidInput = value.length > parseInt(maxLength, 10);
+
+ this.setValidationStateAndMessage();
+ }
+}
diff --git a/app/assets/javascripts/pages/users/activity_calendar.js b/app/assets/javascripts/pages/users/activity_calendar.js
index 61204c37307..693125f8a38 100644
--- a/app/assets/javascripts/pages/users/activity_calendar.js
+++ b/app/assets/javascripts/pages/users/activity_calendar.js
@@ -6,7 +6,7 @@ import dateFormat from 'dateformat';
import { getDayName, getDayDifference } from '~/lib/utils/datetime_utility';
import axios from '~/lib/utils/axios_utils';
import flash from '~/flash';
-import { __ } from '~/locale';
+import { n__, s__, __ } from '~/locale';
const d3 = { select, scaleLinear, scaleThreshold };
@@ -35,9 +35,9 @@ function formatTooltipText({ date, count }) {
const dateDayName = getDayName(dateObject);
const dateText = dateFormat(dateObject, 'mmm d, yyyy');
- let contribText = 'No contributions';
+ let contribText = __('No contributions');
if (count > 0) {
- contribText = `${count} contribution${count > 1 ? 's' : ''}`;
+ contribText = n__('%d contribution', '%d contributions', count);
}
return `${contribText}<br />${dateDayName} ${dateText}`;
}
@@ -65,18 +65,18 @@ export default class ActivityCalendar {
this.daySize = 15;
this.daySizeWithSpace = this.daySize + this.daySpace * 2;
this.monthNames = [
- 'Jan',
- 'Feb',
- 'Mar',
- 'Apr',
- 'May',
- 'Jun',
- 'Jul',
- 'Aug',
- 'Sep',
- 'Oct',
- 'Nov',
- 'Dec',
+ __('Jan'),
+ __('Feb'),
+ __('Mar'),
+ __('Apr'),
+ __('May'),
+ __('Jun'),
+ __('Jul'),
+ __('Aug'),
+ __('Sep'),
+ __('Oct'),
+ __('Nov'),
+ __('Dec'),
];
this.months = [];
this.firstDayOfWeek = firstDayOfWeek;
@@ -199,27 +199,27 @@ export default class ActivityCalendar {
renderDayTitles() {
const days = [
{
- text: 'M',
+ text: s__('DayTitle|M'),
y: 29 + this.dayYPos(1),
},
{
- text: 'W',
+ text: s__('DayTitle|W'),
y: 29 + this.dayYPos(3),
},
{
- text: 'F',
+ text: s__('DayTitle|F'),
y: 29 + this.dayYPos(5),
},
];
if (this.firstDayOfWeek === firstDayOfWeekChoices.monday) {
days.push({
- text: 'S',
+ text: s__('DayTitle|S'),
y: 29 + this.dayYPos(7),
});
} else if (this.firstDayOfWeek === firstDayOfWeekChoices.saturday) {
days.push({
- text: 'S',
+ text: s__('DayTitle|S'),
y: 29 + this.dayYPos(6),
});
}
@@ -253,11 +253,11 @@ export default class ActivityCalendar {
renderKey() {
const keyValues = [
- 'no contributions',
- '1-9 contributions',
- '10-19 contributions',
- '20-29 contributions',
- '30+ contributions',
+ __('no contributions'),
+ __('1-9 contributions'),
+ __('10-19 contributions'),
+ __('20-29 contributions'),
+ __('30+ contributions'),
];
const keyColors = [
'#ededed',
diff --git a/app/assets/javascripts/pdf/index.vue b/app/assets/javascripts/pdf/index.vue
index dc5f9ba9607..6d39abd4a1f 100644
--- a/app/assets/javascripts/pdf/index.vue
+++ b/app/assets/javascripts/pdf/index.vue
@@ -1,6 +1,6 @@
<script>
-import pdfjsLib from 'vendor/pdf';
-import workerSrc from 'vendor/pdf.worker.min';
+import pdfjsLib from 'pdfjs-dist/build/pdf';
+import workerSrc from 'pdfjs-dist/build/pdf.worker.min';
import page from './page/index.vue';
diff --git a/app/assets/javascripts/performance_bar/components/detailed_metric.vue b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
index c729198c1d3..8f3ba9779fb 100644
--- a/app/assets/javascripts/performance_bar/components/detailed_metric.vue
+++ b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
@@ -1,9 +1,11 @@
<script>
import GlModal from '~/vue_shared/components/gl_modal.vue';
+import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
GlModal,
+ Icon,
},
props: {
currentRequest: {
@@ -38,7 +40,11 @@ export default {
};
</script>
<template>
- <div v-if="currentRequest.details" :id="`peek-view-${metric}`" class="view">
+ <div
+ v-if="currentRequest.details"
+ :id="`peek-view-${metric}`"
+ class="view qa-performance-bar-detailed-metric"
+ >
<button
:data-target="`#modal-peek-${metric}-details`"
class="btn-blank btn-link bold"
@@ -57,9 +63,31 @@ export default {
<template v-if="detailsList.length">
<tr v-for="(item, index) in detailsList" :key="index">
<td>
- <strong>{{ item.duration }}ms</strong>
+ <span>{{ item.duration }}ms</span>
+ </td>
+ <td>
+ <div class="js-toggle-container">
+ <div
+ v-for="(key, keyIndex) in keys"
+ :key="key"
+ class="break-word"
+ :class="{ 'mb-3 bold': keyIndex == 0 }"
+ >
+ {{ item[key] }}
+ <button
+ v-if="keyIndex == 0 && item.backtrace"
+ class="text-expander js-toggle-button"
+ type="button"
+ :aria-label="__('Toggle backtrace')"
+ >
+ <icon :size="12" name="ellipsis_h" />
+ </button>
+ </div>
+ <pre v-if="item.backtrace" class="backtrace-row js-toggle-content mt-2">{{
+ item.backtrace
+ }}</pre>
+ </div>
</td>
- <td v-for="key in keys" :key="key" class="break-word">{{ item[key] }}</td>
</tr>
</template>
<template v-else>
diff --git a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
index 1ec2784cc5a..48515cf785c 100644
--- a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
+++ b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
@@ -92,7 +92,7 @@ export default {
</script>
<template>
<div id="js-peek" :class="env">
- <div v-if="currentRequest" class="d-flex container-fluid container-limited">
+ <div v-if="currentRequest" class="d-flex container-fluid container-limited qa-performance-bar">
<div id="peek-view-host" class="view">
<span
v-if="hasHost"
diff --git a/app/assets/javascripts/performance_bar/components/request_selector.vue b/app/assets/javascripts/performance_bar/components/request_selector.vue
index fdb5c0d6939..297507b85af 100644
--- a/app/assets/javascripts/performance_bar/components/request_selector.vue
+++ b/app/assets/javascripts/performance_bar/components/request_selector.vue
@@ -37,7 +37,12 @@ export default {
<template>
<div id="peek-request-selector">
<select v-model="currentRequestId">
- <option v-for="request in requests" :key="request.id" :value="request.id">
+ <option
+ v-for="request in requests"
+ :key="request.id"
+ :value="request.id"
+ class="qa-performance-bar-request"
+ >
{{ truncatedUrl(request.url) }}
</option>
</select>
diff --git a/app/assets/javascripts/pipelines/components/graph/action_component.vue b/app/assets/javascripts/pipelines/components/graph/action_component.vue
index 8ca539351a7..3c85bb61ce8 100644
--- a/app/assets/javascripts/pipelines/components/graph/action_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/action_component.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTooltipDirective, GlButton } from '@gitlab/ui';
+import { GlTooltipDirective, GlButton, GlLoadingIcon } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
import { dasherize } from '~/lib/utils/text_utility';
import { __ } from '~/locale';
@@ -20,6 +20,7 @@ export default {
components: {
Icon,
GlButton,
+ GlLoadingIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -41,6 +42,7 @@ export default {
data() {
return {
isDisabled: false,
+ isLoading: false,
};
},
computed: {
@@ -59,15 +61,19 @@ export default {
onClickAction() {
this.$root.$emit('bv::hide::tooltip', `js-ci-action-${this.link}`);
this.isDisabled = true;
+ this.isLoading = true;
axios
.post(`${this.link}.json`)
.then(() => {
this.isDisabled = false;
+ this.isLoading = false;
+
this.$emit('pipelineActionRequestComplete');
})
.catch(() => {
this.isDisabled = false;
+ this.isLoading = false;
createFlash(__('An error occurred while making the request.'));
});
@@ -82,10 +88,10 @@ export default {
:title="tooltipText"
:class="cssClass"
:disabled="isDisabled"
- class="js-ci-action btn btn-blank
-btn-transparent ci-action-icon-container ci-action-icon-wrapper"
+ class="js-ci-action btn btn-blank btn-transparent ci-action-icon-container ci-action-icon-wrapper"
@click="onClickAction"
>
- <icon :name="actionIcon" />
+ <gl-loading-icon v-if="isLoading" class="js-action-icon-loading" />
+ <icon v-else :name="actionIcon" />
</gl-button>
</template>
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
index a49dc311bd0..ba0dea626dc 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
@@ -24,6 +24,7 @@ export default {
:groups="stage.groups"
:stage-connector-class="stageConnectorClass(index, stage)"
:is-first-column="isFirstColumn(index)"
+ :action="stage.status.action"
@refreshPipelineGraph="refreshPipelineGraph"
/>
</ul>
diff --git a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
index 482898b80c4..ebd7a17040a 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
@@ -69,7 +69,9 @@ export default {
>
<ci-icon :status="group.status" />
- <span class="ci-status-text"> {{ group.name }} </span>
+ <span class="ci-status-text text-truncate mw-70p gl-pl-1 d-inline-block align-bottom">
+ {{ group.name }}
+ </span>
<span class="dropdown-counter-badge"> {{ group.size }} </span>
</button>
diff --git a/app/assets/javascripts/pipelines/components/graph/job_name_component.vue b/app/assets/javascripts/pipelines/components/graph/job_name_component.vue
index 02451839330..7125790ac3d 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_name_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_name_component.vue
@@ -25,7 +25,7 @@ export default {
};
</script>
<template>
- <span class="ci-job-name-component">
+ <span class="ci-job-name-component mw-100">
<ci-icon :status="status" />
<span class="ci-status-text text-truncate mw-70p gl-pl-1 d-inline-block align-bottom">
{{ name }}
diff --git a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
index 348c407f1b5..d5c124dc0ca 100644
--- a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
@@ -3,11 +3,13 @@ import _ from 'underscore';
import stageColumnMixin from 'ee_else_ce/pipelines/mixins/stage_column_mixin';
import JobItem from './job_item.vue';
import JobGroupDropdown from './job_group_dropdown.vue';
+import ActionComponent from './action_component.vue';
export default {
components: {
JobItem,
JobGroupDropdown,
+ ActionComponent,
},
mixins: [stageColumnMixin],
props: {
@@ -29,6 +31,16 @@ export default {
required: false,
default: '',
},
+ action: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ },
+ computed: {
+ hasAction() {
+ return !_.isEmpty(this.action);
+ },
},
methods: {
groupId(group) {
@@ -42,7 +54,18 @@ export default {
</script>
<template>
<li :class="stageConnectorClass" class="stage-column">
- <div class="stage-name">{{ title }}</div>
+ <div class="stage-name position-relative">
+ {{ title }}
+ <action-component
+ v-if="hasAction"
+ :action-icon="action.icon"
+ :tooltip-text="action.title"
+ :link="action.path"
+ class="js-stage-action stage-action position-absolute position-top-0 rounded"
+ @pipelineActionRequestComplete="pipelineActionRequestComplete"
+ />
+ </div>
+
<div class="builds-container">
<ul>
<li
diff --git a/app/assets/javascripts/pipelines/components/header_component.vue b/app/assets/javascripts/pipelines/components/header_component.vue
index b2e365e5cde..f3a71ee434c 100644
--- a/app/assets/javascripts/pipelines/components/header_component.vue
+++ b/app/assets/javascripts/pipelines/components/header_component.vue
@@ -83,6 +83,8 @@ export default {
v-if="shouldRenderContent"
:status="status"
:item-id="pipeline.id"
+ :item-iid="pipeline.iid"
+ :item-id-tooltip="__('Pipeline ID (IID)')"
:time="pipeline.created_at"
:user="pipeline.user"
:actions="actions"
diff --git a/app/assets/javascripts/pipelines/components/pipeline_triggerer.vue b/app/assets/javascripts/pipelines/components/pipeline_triggerer.vue
new file mode 100644
index 00000000000..740b54cd8e0
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/pipeline_triggerer.vue
@@ -0,0 +1,35 @@
+<script>
+import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+
+export default {
+ components: {
+ UserAvatarLink,
+ },
+ props: {
+ pipeline: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ user() {
+ return this.pipeline.user;
+ },
+ },
+};
+</script>
+<template>
+ <div class="table-section section-10 d-none d-sm-none d-md-block pipeline-triggerer">
+ <user-avatar-link
+ v-if="user"
+ :link-href="user.path"
+ :img-src="user.avatar_url"
+ :img-size="26"
+ :tooltip-text="user.name"
+ class="prepend-left-default js-pipeline-url-user"
+ />
+ <span v-else class="prepend-left-default js-pipeline-url-api api">
+ {{ s__('Pipelines|API') }}
+ </span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/pipeline_url.vue b/app/assets/javascripts/pipelines/components/pipeline_url.vue
index 3e7bf20470c..00c02e15562 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_url.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_url.vue
@@ -2,6 +2,7 @@
import { GlLink, GlTooltipDirective } from '@gitlab/ui';
import _ from 'underscore';
import { __, sprintf } from '~/locale';
+import PipelineLink from '~/vue_shared/components/ci_pipeline_link.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import popover from '~/vue_shared/directives/popover';
@@ -19,6 +20,7 @@ export default {
components: {
UserAvatarLink,
GlLink,
+ PipelineLink,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -59,19 +61,13 @@ export default {
};
</script>
<template>
- <div class="table-section section-15 d-none d-sm-none d-md-block pipeline-tags">
- <gl-link :href="pipeline.path" class="js-pipeline-url-link">
- <span class="pipeline-id">#{{ pipeline.id }}</span>
- </gl-link>
- <span>by</span>
- <user-avatar-link
- v-if="user"
- :link-href="user.path"
- :img-src="user.avatar_url"
- :tooltip-text="user.name"
- class="js-pipeline-url-user"
+ <div class="table-section section-10 d-none d-sm-none d-md-block pipeline-tags section-wrap">
+ <pipeline-link
+ :href="pipeline.path"
+ :pipeline-id="pipeline.id"
+ :pipeline-iid="pipeline.iid"
+ class="js-pipeline-url-link"
/>
- <span v-if="!user" class="js-pipeline-url-api api"> API </span>
<div class="label-container">
<span
v-if="pipeline.flags.latest"
diff --git a/app/assets/javascripts/pipelines/components/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines.vue
index 9dcea557b32..d730ef41b1a 100644
--- a/app/assets/javascripts/pipelines/components/pipelines.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines.vue
@@ -4,7 +4,7 @@ import { __, sprintf, s__ } from '../../locale';
import createFlash from '../../flash';
import PipelinesService from '../services/pipelines_service';
import pipelinesMixin from '../mixins/pipelines';
-import TablePagination from '../../vue_shared/components/table_pagination.vue';
+import TablePagination from '../../vue_shared/components/pagination/table_pagination.vue';
import NavigationTabs from '../../vue_shared/components/navigation_tabs.vue';
import NavigationControls from './nav_controls.vue';
import { getParameterByName } from '../../lib/utils/common_utils';
diff --git a/app/assets/javascripts/pipelines/components/pipelines_table.vue b/app/assets/javascripts/pipelines/components/pipelines_table.vue
index fcd1f119df0..03d332cd430 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_table.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_table.vue
@@ -1,4 +1,5 @@
<script>
+import { GlTooltipDirective } from '@gitlab/ui';
import PipelinesTableRowComponent from './pipelines_table_row.vue';
import PipelineStopModal from './pipeline_stop_modal.vue';
import eventHub from '../event_hub';
@@ -13,6 +14,9 @@ export default {
PipelinesTableRowComponent,
PipelineStopModal,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
props: {
pipelines: {
type: Array,
@@ -62,16 +66,19 @@ export default {
<template>
<div class="ci-table">
<div class="gl-responsive-table-row table-row-header" role="row">
- <div class="table-section section-10 js-pipeline-status pipeline-status" role="rowheader">
+ <div class="table-section section-10 js-pipeline-status" role="rowheader">
{{ s__('Pipeline|Status') }}
</div>
- <div class="table-section section-15 js-pipeline-info pipeline-info" role="rowheader">
+ <div class="table-section section-10 js-pipeline-info pipeline-info" role="rowheader">
{{ s__('Pipeline|Pipeline') }}
</div>
+ <div class="table-section section-10 js-triggerer-info triggerer-info" role="rowheader">
+ {{ s__('Pipeline|Triggerer') }}
+ </div>
<div class="table-section section-20 js-pipeline-commit pipeline-commit" role="rowheader">
{{ s__('Pipeline|Commit') }}
</div>
- <div class="table-section section-20 js-pipeline-stages pipeline-stages" role="rowheader">
+ <div class="table-section section-15 js-pipeline-stages pipeline-stages" role="rowheader">
{{ s__('Pipeline|Stages') }}
</div>
</div>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_table_row.vue b/app/assets/javascripts/pipelines/components/pipelines_table_row.vue
index 1c44427e720..e32e2f785bd 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_table_row.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_table_row.vue
@@ -5,6 +5,7 @@ import PipelinesArtifactsComponent from './pipelines_artifacts.vue';
import CiBadge from '../../vue_shared/components/ci_badge_link.vue';
import PipelineStage from './stage.vue';
import PipelineUrl from './pipeline_url.vue';
+import PipelineTriggerer from './pipeline_triggerer.vue';
import PipelinesTimeago from './time_ago.vue';
import CommitComponent from '../../vue_shared/components/commit.vue';
import LoadingButton from '../../vue_shared/components/loading_button.vue';
@@ -23,6 +24,7 @@ export default {
CommitComponent,
PipelineStage,
PipelineUrl,
+ PipelineTriggerer,
CiBadge,
PipelinesTimeago,
LoadingButton,
@@ -264,8 +266,9 @@ export default {
</div>
<pipeline-url :pipeline="pipeline" :auto-devops-help-path="autoDevopsHelpPath" />
+ <pipeline-triggerer :pipeline="pipeline" />
- <div class="table-section section-20">
+ <div class="table-section section-wrap section-20">
<div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Commit') }}</div>
<div class="table-mobile-content">
<commit-component
@@ -281,7 +284,7 @@ export default {
</div>
</div>
- <div class="table-section section-wrap section-20 stage-cell">
+ <div class="table-section section-wrap section-15 stage-cell">
<div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Stages') }}</div>
<div class="table-mobile-content">
<template v-if="pipeline.details.stages.length > 0">
diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
index 6660f8120f8..b8976f77bac 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
@@ -34,6 +34,7 @@ export default () => {
props: {
isLoading: this.mediator.state.isLoading,
pipeline: this.mediator.store.state.pipeline,
+ mediator: this.mediator,
},
on: {
refreshPipelineGraph: this.requestRefreshPipelineGraph,
diff --git a/app/assets/javascripts/profile/account/index.js b/app/assets/javascripts/profile/account/index.js
index 59c13e1a042..f0d9642a2b2 100644
--- a/app/assets/javascripts/profile/account/index.js
+++ b/app/assets/javascripts/profile/account/index.js
@@ -35,7 +35,7 @@ export default () => {
return createElement('delete-account-modal', {
props: {
actionUrl: deleteAccountModalEl.dataset.actionUrl,
- confirmWithPassword: !!deleteAccountModalEl.dataset.confirmWithPassword,
+ confirmWithPassword: Boolean(deleteAccountModalEl.dataset.confirmWithPassword),
username: deleteAccountModalEl.dataset.username,
},
});
diff --git a/app/assets/javascripts/profile/profile.js b/app/assets/javascripts/profile/profile.js
index deacff5abe7..8dd37aee7e1 100644
--- a/app/assets/javascripts/profile/profile.js
+++ b/app/assets/javascripts/profile/profile.js
@@ -2,6 +2,9 @@ import $ from 'jquery';
import axios from '~/lib/utils/axios_utils';
import flash from '../flash';
import { parseBoolean } from '~/lib/utils/common_utils';
+import TimezoneDropdown, {
+ formatTimezone,
+} from '~/pages/projects/pipeline_schedules/shared/components/timezone_dropdown';
export default class Profile {
constructor({ form } = {}) {
@@ -10,6 +13,14 @@ export default class Profile {
this.setRepoRadio();
this.bindEvents();
this.initAvatarGlCrop();
+
+ this.$inputEl = $('#user_timezone');
+
+ this.timezoneDropdown = new TimezoneDropdown({
+ $inputEl: this.$inputEl,
+ $dropdownEl: $('.js-timezone-dropdown'),
+ displayFormat: selectedItem => formatTimezone(selectedItem),
+ });
}
initAvatarGlCrop() {
@@ -28,6 +39,7 @@ export default class Profile {
bindEvents() {
$('.js-preferences-form').on('change.preference', 'input[type=radio]', this.submitForm);
+ $('.js-group-notification-email').on('change', this.submitForm);
$('#user_notification_email').on('change', this.submitForm);
$('#user_notified_of_own_activity').on('change', this.submitForm);
this.form.on('submit', this.onSubmitForm);
diff --git a/app/assets/javascripts/project_label_subscription.js b/app/assets/javascripts/project_label_subscription.js
index d3c604dcee1..5395e14cc79 100644
--- a/app/assets/javascripts/project_label_subscription.js
+++ b/app/assets/javascripts/project_label_subscription.js
@@ -38,9 +38,9 @@ export default class ProjectLabelSubscription {
let newAction;
if (oldStatus === 'unsubscribed') {
- [newStatus, newAction] = ['subscribed', 'Unsubscribe'];
+ [newStatus, newAction] = ['subscribed', __('Unsubscribe')];
} else {
- [newStatus, newAction] = ['unsubscribed', 'Subscribe'];
+ [newStatus, newAction] = ['unsubscribed', __('Subscribe')];
}
$btn.removeClass('disabled');
diff --git a/app/assets/javascripts/project_select.js b/app/assets/javascripts/project_select.js
index 5ee510eb11d..dbe354a547b 100644
--- a/app/assets/javascripts/project_select.js
+++ b/app/assets/javascripts/project_select.js
@@ -3,6 +3,7 @@
import $ from 'jquery';
import Api from './api';
import ProjectSelectComboButton from './project_select_combo_button';
+import { s__ } from './locale';
export default function projectSelect() {
import(/* webpackChunkName: 'select2' */ 'select2/select2')
@@ -21,9 +22,9 @@ export default function projectSelect() {
this.includeProjectsInSubgroups = $(select).data('includeProjectsInSubgroups') || false;
this.allowClear = $(select).data('allowClear') || false;
- placeholder = 'Search for project';
+ placeholder = s__('ProjectSelect|Search for project');
if (this.includeGroups) {
- placeholder += ' or group';
+ placeholder += s__('ProjectSelect| or group');
}
$(select).select2({
diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/actions.js b/app/assets/javascripts/projects/gke_cluster_dropdowns/store/actions.js
index 4834a856271..f05ad7773a2 100644
--- a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/actions.js
+++ b/app/assets/javascripts/projects/gke_cluster_dropdowns/store/actions.js
@@ -57,7 +57,7 @@ export const validateProjectBilling = ({ dispatch, commit, state }) =>
resp => {
const { billingEnabled } = resp.result;
- commit(types.SET_PROJECT_BILLING_STATUS, !!billingEnabled);
+ commit(types.SET_PROJECT_BILLING_STATUS, Boolean(billingEnabled));
dispatch('setIsValidatingProjectBilling', false);
resolve();
},
diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/getters.js b/app/assets/javascripts/projects/gke_cluster_dropdowns/store/getters.js
index e39f02d0894..f9e2e2f74fb 100644
--- a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/getters.js
+++ b/app/assets/javascripts/projects/gke_cluster_dropdowns/store/getters.js
@@ -1,3 +1,3 @@
-export const hasProject = state => !!state.selectedProject.projectId;
-export const hasZone = state => !!state.selectedZone;
-export const hasMachineType = state => !!state.selectedMachineType;
+export const hasProject = state => Boolean(state.selectedProject.projectId);
+export const hasZone = state => Boolean(state.selectedZone);
+export const hasMachineType = state => Boolean(state.selectedMachineType);
diff --git a/app/assets/javascripts/projects/project_new.js b/app/assets/javascripts/projects/project_new.js
index 784eec1ea55..ea82ff4e340 100644
--- a/app/assets/javascripts/projects/project_new.js
+++ b/app/assets/javascripts/projects/project_new.js
@@ -1,6 +1,7 @@
import $ from 'jquery';
import { addSelectOnFocusBehaviour } from '../lib/utils/common_utils';
import { slugifyWithHyphens } from '../lib/utils/text_utility';
+import { s__ } from '~/locale';
let hasUserDefinedProjectPath = false;
@@ -114,71 +115,71 @@ const bindEvents = () => {
const value = $(this).val();
const templates = {
rails: {
- text: 'Ruby on Rails',
+ text: s__('ProjectTemplates|Ruby on Rails'),
icon: '.template-option .icon-rails',
},
express: {
- text: 'NodeJS Express',
+ text: s__('ProjectTemplates|NodeJS Express'),
icon: '.template-option .icon-express',
},
spring: {
- text: 'Spring',
+ text: s__('ProjectTemplates|Spring'),
icon: '.template-option .icon-spring',
},
iosswift: {
- text: 'iOS (Swift)',
+ text: s__('ProjectTemplates|iOS (Swift)'),
icon: '.template-option svg.icon-gitlab',
},
dotnetcore: {
- text: '.NET Core',
+ text: s__('ProjectTemplates|.NET Core'),
icon: '.template-option .icon-dotnet',
},
android: {
- text: 'Android',
+ text: s__('ProjectTemplates|Android'),
icon: '.template-option svg.icon-android',
},
gomicro: {
- text: 'Go Micro',
+ text: s__('ProjectTemplates|Go Micro'),
icon: '.template-option .icon-gomicro',
},
hugo: {
- text: 'Pages/Hugo',
+ text: s__('ProjectTemplates|Pages/Hugo'),
icon: '.template-option .icon-hugo',
},
jekyll: {
- text: 'Pages/Jekyll',
+ text: s__('ProjectTemplates|Pages/Jekyll'),
icon: '.template-option .icon-jekyll',
},
plainhtml: {
- text: 'Pages/Plain HTML',
+ text: s__('ProjectTemplates|Pages/Plain HTML'),
icon: '.template-option .icon-plainhtml',
},
gitbook: {
- text: 'Pages/GitBook',
+ text: s__('ProjectTemplates|Pages/GitBook'),
icon: '.template-option .icon-gitbook',
},
hexo: {
- text: 'Pages/Hexo',
+ text: s__('ProjectTemplates|Pages/Hexo'),
icon: '.template-option .icon-hexo',
},
nfhugo: {
- text: 'Netlify/Hugo',
+ text: s__('ProjectTemplates|Netlify/Hugo'),
icon: '.template-option .icon-netlify',
},
nfjekyll: {
- text: 'Netlify/Jekyll',
+ text: s__('ProjectTemplates|Netlify/Jekyll'),
icon: '.template-option .icon-netlify',
},
nfplainhtml: {
- text: 'Netlify/Plain HTML',
+ text: s__('ProjectTemplates|Netlify/Plain HTML'),
icon: '.template-option .icon-netlify',
},
nfgitbook: {
- text: 'Netlify/GitBook',
+ text: s__('ProjectTemplates|Netlify/GitBook'),
icon: '.template-option .icon-netlify',
},
nfhexo: {
- text: 'Netlify/Hexo',
+ text: s__('ProjectTemplates|Netlify/Hexo'),
icon: '.template-option .icon-netlify',
},
};
@@ -217,6 +218,12 @@ const bindEvents = () => {
$projectImportUrl.keyup(() => deriveProjectPathFromUrl($projectImportUrl));
+ $('.js-import-git-toggle-button').on('click', () => {
+ const $projectMirror = $('#project_mirror');
+
+ $projectMirror.attr('disabled', !$projectMirror.attr('disabled'));
+ });
+
$projectName.on('keyup change', () => {
onProjectNameChange($projectName, $projectPath);
hasUserDefinedProjectPath = $projectPath.val().trim().length > 0;
diff --git a/app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js b/app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js
index 40a873833e1..41e295387ae 100644
--- a/app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js
+++ b/app/assets/javascripts/protected_branches/protected_branch_access_dropdown.js
@@ -1,3 +1,5 @@
+import { __ } from '~/locale';
+
export default class ProtectedBranchAccessDropdown {
constructor(options) {
this.options = options;
@@ -15,7 +17,7 @@ export default class ProtectedBranchAccessDropdown {
if ($el.is('.is-active')) {
return item.text;
}
- return 'Select';
+ return __('Select');
},
clicked(options) {
options.e.preventDefault();
diff --git a/app/assets/javascripts/protected_branches/protected_branch_create.js b/app/assets/javascripts/protected_branches/protected_branch_create.js
index 48343c8ba0a..16ecd5523d6 100644
--- a/app/assets/javascripts/protected_branches/protected_branch_create.js
+++ b/app/assets/javascripts/protected_branches/protected_branch_create.js
@@ -2,6 +2,7 @@ import $ from 'jquery';
import ProtectedBranchAccessDropdown from './protected_branch_access_dropdown';
import CreateItemDropdown from '../create_item_dropdown';
import AccessorUtilities from '../lib/utils/accessor';
+import { __ } from '~/locale';
export default class ProtectedBranchCreate {
constructor() {
@@ -35,7 +36,7 @@ export default class ProtectedBranchCreate {
this.createItemDropdown = new CreateItemDropdown({
$dropdown: $protectedBranchDropdown,
- defaultToggleLabel: 'Protected Branch',
+ defaultToggleLabel: __('Protected Branch'),
fieldName: 'protected_branch[name]',
onSelect: this.onSelectCallback,
getData: ProtectedBranchCreate.getProtectedBranches,
diff --git a/app/assets/javascripts/protected_branches/protected_branch_edit.js b/app/assets/javascripts/protected_branches/protected_branch_edit.js
index 5bc08f60d16..08d8c9919dd 100644
--- a/app/assets/javascripts/protected_branches/protected_branch_edit.js
+++ b/app/assets/javascripts/protected_branches/protected_branch_edit.js
@@ -1,6 +1,7 @@
import flash from '../flash';
import axios from '../lib/utils/axios_utils';
import ProtectedBranchAccessDropdown from './protected_branch_access_dropdown';
+import { __ } from '~/locale';
export default class ProtectedBranchEdit {
constructor(options) {
@@ -68,7 +69,7 @@ export default class ProtectedBranchEdit {
this.$allowedToPushDropdown.enable();
flash(
- 'Failed to update branch!',
+ __('Failed to update branch!'),
'alert',
document.querySelector('.js-protected-branches-list'),
);
diff --git a/app/assets/javascripts/protected_tags/protected_tag_access_dropdown.js b/app/assets/javascripts/protected_tags/protected_tag_access_dropdown.js
index b803da798d5..def2f091947 100644
--- a/app/assets/javascripts/protected_tags/protected_tag_access_dropdown.js
+++ b/app/assets/javascripts/protected_tags/protected_tag_access_dropdown.js
@@ -1,3 +1,5 @@
+import { __ } from '~/locale';
+
export default class ProtectedTagAccessDropdown {
constructor(options) {
this.options = options;
@@ -15,7 +17,7 @@ export default class ProtectedTagAccessDropdown {
if ($el.is('.is-active')) {
return item.text;
}
- return 'Select';
+ return __('Select');
},
clicked(options) {
options.e.preventDefault();
diff --git a/app/assets/javascripts/protected_tags/protected_tag_create.js b/app/assets/javascripts/protected_tags/protected_tag_create.js
index fddf2674cbb..03a5fe6b353 100644
--- a/app/assets/javascripts/protected_tags/protected_tag_create.js
+++ b/app/assets/javascripts/protected_tags/protected_tag_create.js
@@ -1,6 +1,7 @@
import $ from 'jquery';
import ProtectedTagAccessDropdown from './protected_tag_access_dropdown';
import CreateItemDropdown from '../create_item_dropdown';
+import { __ } from '~/locale';
export default class ProtectedTagCreate {
constructor() {
@@ -27,7 +28,7 @@ export default class ProtectedTagCreate {
// Protected tag dropdown
this.createItemDropdown = new CreateItemDropdown({
$dropdown: this.$form.find('.js-protected-tag-select'),
- defaultToggleLabel: 'Protected Tag',
+ defaultToggleLabel: __('Protected Tag'),
fieldName: 'protected_tag[name]',
onSelect: this.onSelectCallback,
getData: ProtectedTagCreate.getProtectedTags,
diff --git a/app/assets/javascripts/protected_tags/protected_tag_edit.js b/app/assets/javascripts/protected_tags/protected_tag_edit.js
index c52497e62f2..70bfd71abce 100644
--- a/app/assets/javascripts/protected_tags/protected_tag_edit.js
+++ b/app/assets/javascripts/protected_tags/protected_tag_edit.js
@@ -1,6 +1,7 @@
import flash from '../flash';
import axios from '../lib/utils/axios_utils';
import ProtectedTagAccessDropdown from './protected_tag_access_dropdown';
+import { __ } from '~/locale';
export default class ProtectedTagEdit {
constructor(options) {
@@ -47,7 +48,11 @@ export default class ProtectedTagEdit {
.catch(() => {
this.$allowedToCreateDropdownButton.enable();
- flash('Failed to update tag!', 'alert', document.querySelector('.js-protected-tags-list'));
+ flash(
+ __('Failed to update tag!'),
+ 'alert',
+ document.querySelector('.js-protected-tags-list'),
+ );
});
}
}
diff --git a/app/assets/javascripts/raven/index.js b/app/assets/javascripts/raven/index.js
index edc2293915f..4dd0175e528 100644
--- a/app/assets/javascripts/raven/index.js
+++ b/app/assets/javascripts/raven/index.js
@@ -4,8 +4,11 @@ const index = function index() {
RavenConfig.init({
sentryDsn: gon.sentry_dsn,
currentUserId: gon.current_user_id,
- whitelistUrls: [gon.gitlab_url],
- isProduction: process.env.NODE_ENV,
+ whitelistUrls:
+ process.env.NODE_ENV === 'production'
+ ? [gon.gitlab_url]
+ : [gon.gitlab_url, 'webpack-internal://'],
+ environment: gon.sentry_environment,
release: gon.revision,
tags: {
revision: gon.revision,
diff --git a/app/assets/javascripts/raven/raven_config.js b/app/assets/javascripts/raven/raven_config.js
index 338006ce2b9..7259e0df104 100644
--- a/app/assets/javascripts/raven/raven_config.js
+++ b/app/assets/javascripts/raven/raven_config.js
@@ -1,5 +1,6 @@
import Raven from 'raven-js';
import $ from 'jquery';
+import { __ } from '~/locale';
const IGNORE_ERRORS = [
// Random plugins/extensions
@@ -9,9 +10,9 @@ const IGNORE_ERRORS = [
'canvas.contentDocument',
'MyApp_RemoveAllHighlights',
'http://tt.epicplay.com',
- "Can't find variable: ZiteReader",
- 'jigsaw is not defined',
- 'ComboSearch is not defined',
+ __("Can't find variable: ZiteReader"),
+ __('jigsaw is not defined'),
+ __('ComboSearch is not defined'),
'http://loading.retry.widdit.com/',
'atomicFindClose',
// Facebook borked
@@ -61,7 +62,7 @@ const RavenConfig = {
release: this.options.release,
tags: this.options.tags,
whitelistUrls: this.options.whitelistUrls,
- environment: this.options.isProduction ? 'production' : 'development',
+ environment: this.options.environment,
ignoreErrors: this.IGNORE_ERRORS,
ignoreUrls: this.IGNORE_URLS,
shouldSendCallback: this.shouldSendSample.bind(this),
@@ -80,7 +81,7 @@ const RavenConfig = {
handleRavenErrors(event, req, config, err) {
const error = err || req.statusText;
- const responseText = req.responseText || 'Unknown response text';
+ const responseText = req.responseText || __('Unknown response text');
Raven.captureMessage(error, {
extra: {
diff --git a/app/assets/javascripts/registry/components/table_registry.vue b/app/assets/javascripts/registry/components/table_registry.vue
index 81fe0a48c06..1e4dfe76b26 100644
--- a/app/assets/javascripts/registry/components/table_registry.vue
+++ b/app/assets/javascripts/registry/components/table_registry.vue
@@ -4,7 +4,7 @@ import { GlButton, GlTooltipDirective } from '@gitlab/ui';
import { n__ } from '../../locale';
import createFlash from '../../flash';
import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
-import TablePagination from '../../vue_shared/components/table_pagination.vue';
+import TablePagination from '../../vue_shared/components/pagination/table_pagination.vue';
import Icon from '../../vue_shared/components/icon.vue';
import timeagoMixin from '../../vue_shared/mixins/timeago';
import { errorMessages, errorMessagesTypes } from '../constants';
diff --git a/app/assets/javascripts/registry/stores/mutations.js b/app/assets/javascripts/registry/stores/mutations.js
index 1ac699c538f..8ace6657ad1 100644
--- a/app/assets/javascripts/registry/stores/mutations.js
+++ b/app/assets/javascripts/registry/stores/mutations.js
@@ -9,7 +9,7 @@ export default {
[types.SET_REPOS_LIST](state, list) {
Object.assign(state, {
repos: list.map(el => ({
- canDelete: !!el.destroy_path,
+ canDelete: Boolean(el.destroy_path),
destroyPath: el.destroy_path,
id: el.id,
isLoading: false,
@@ -42,7 +42,7 @@ export default {
location: element.location,
createdAt: element.created_at,
destroyPath: element.destroy_path,
- canDelete: !!element.destroy_path,
+ canDelete: Boolean(element.destroy_path),
}));
},
diff --git a/app/assets/javascripts/releases/components/release_block.vue b/app/assets/javascripts/releases/components/release_block.vue
index 7ed1b407ddd..0958b9fa926 100644
--- a/app/assets/javascripts/releases/components/release_block.vue
+++ b/app/assets/javascripts/releases/components/release_block.vue
@@ -86,7 +86,7 @@ export default {
</div>
<div
- v-if="assets.links.length || assets.sources.length"
+ v-if="assets.links.length || (assets.sources && assets.sources.length)"
class="card-text prepend-top-default"
>
<b>
@@ -103,7 +103,7 @@ export default {
</li>
</ul>
- <div v-if="assets.sources.length" class="dropdown">
+ <div v-if="assets.sources && assets.sources.length" class="dropdown">
<button
type="button"
class="btn btn-link"
diff --git a/app/assets/javascripts/reports/components/issues_list.vue b/app/assets/javascripts/reports/components/issues_list.vue
index f4243522ef8..ee07efea3b0 100644
--- a/app/assets/javascripts/reports/components/issues_list.vue
+++ b/app/assets/javascripts/reports/components/issues_list.vue
@@ -52,6 +52,21 @@ export default {
required: false,
default: '',
},
+ showReportSectionStatusIcon: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ issuesUlElementClass: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ issueItemClass: {
+ type: String,
+ required: false,
+ default: null,
+ },
},
computed: {
issuesWithState() {
@@ -62,6 +77,9 @@ export default {
...this.resolvedIssues.map(wrapIssueWithState(STATUS_SUCCESS)),
];
},
+ wclass() {
+ return `report-block-list ${this.issuesUlElementClass}`;
+ },
},
};
</script>
@@ -72,7 +90,7 @@ export default {
:size="$options.typicalReportItemHeight"
class="report-block-container"
wtag="ul"
- wclass="report-block-list"
+ :wclass="wclass"
>
<report-item
v-for="(wrapped, index) in issuesWithState"
@@ -81,6 +99,8 @@ export default {
:status="wrapped.status"
:component="component"
:is-new="wrapped.isNew"
+ :show-report-section-status-icon="showReportSectionStatusIcon"
+ :class="issueItemClass"
/>
</smart-virtual-list>
</template>
diff --git a/app/assets/javascripts/reports/components/report_item.vue b/app/assets/javascripts/reports/components/report_item.vue
index d2106f9ad2e..01a30809e1a 100644
--- a/app/assets/javascripts/reports/components/report_item.vue
+++ b/app/assets/javascripts/reports/components/report_item.vue
@@ -34,12 +34,22 @@ export default {
required: false,
default: false,
},
+ showReportSectionStatusIcon: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
};
</script>
<template>
<li :class="{ 'is-dismissed': issue.isDismissed }" class="report-block-list-issue">
- <issue-status-icon :status="status" :status-icon-size="statusIconSize" class="append-right-5" />
+ <issue-status-icon
+ v-if="showReportSectionStatusIcon"
+ :status="status"
+ :status-icon-size="statusIconSize"
+ class="append-right-5"
+ />
<component :is="component" v-if="component" :issue="issue" :status="status" :is-new="isNew" />
</li>
diff --git a/app/assets/javascripts/reports/components/report_section.vue b/app/assets/javascripts/reports/components/report_section.vue
index d6483e95278..3d576caaf8f 100644
--- a/app/assets/javascripts/reports/components/report_section.vue
+++ b/app/assets/javascripts/reports/components/report_section.vue
@@ -3,10 +3,7 @@ import { __ } from '~/locale';
import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue';
import Popover from '~/vue_shared/components/help_popover.vue';
import IssuesList from './issues_list.vue';
-
-const LOADING = 'LOADING';
-const ERROR = 'ERROR';
-const SUCCESS = 'SUCCESS';
+import { status } from '../constants';
export default {
name: 'ReportSection',
@@ -42,7 +39,8 @@ export default {
},
successText: {
type: String,
- required: true,
+ required: false,
+ default: '',
},
unresolvedIssues: {
type: Array,
@@ -73,6 +71,26 @@ export default {
default: () => ({}),
required: false,
},
+ showReportSectionStatusIcon: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ issuesUlElementClass: {
+ type: String,
+ required: false,
+ default: undefined,
+ },
+ issuesListContainerClass: {
+ type: String,
+ required: false,
+ default: undefined,
+ },
+ issueItemClass: {
+ type: String,
+ required: false,
+ default: undefined,
+ },
},
data() {
@@ -86,13 +104,13 @@ export default {
return this.isCollapsed ? __('Expand') : __('Collapse');
},
isLoading() {
- return this.status === LOADING;
+ return this.status === status.LOADING;
},
loadingFailed() {
- return this.status === ERROR;
+ return this.status === status.ERROR;
},
isSuccess() {
- return this.status === SUCCESS;
+ return this.status === status.SUCCESS;
},
isCollapsible() {
return !this.alwaysOpen && this.hasIssues;
@@ -127,6 +145,15 @@ export default {
hasPopover() {
return Object.keys(this.popoverOptions).length > 0;
},
+ slotName() {
+ if (this.isSuccess) {
+ return 'success';
+ } else if (this.isLoading) {
+ return 'loading';
+ }
+
+ return 'error';
+ },
},
methods: {
toggleCollapsed() {
@@ -142,6 +169,7 @@ export default {
<div class="media-body d-flex flex-align-self-center">
<span class="js-code-text code-text">
{{ headerText }}
+ <slot :name="slotName"></slot>
<popover v-if="hasPopover" :options="popoverOptions" class="prepend-left-5" />
</span>
@@ -151,7 +179,7 @@ export default {
<button
v-if="isCollapsible"
type="button"
- class="js-collapse-btn btn float-right btn-sm"
+ class="js-collapse-btn btn float-right btn-sm qa-expand-report-button"
@click="toggleCollapsed"
>
{{ collapseText }}
@@ -166,6 +194,10 @@ export default {
:resolved-issues="resolvedIssues"
:neutral-issues="neutralIssues"
:component="component"
+ :show-report-section-status-icon="showReportSectionStatusIcon"
+ :issues-ul-element-class="issuesUlElementClass"
+ :class="issuesListContainerClass"
+ :issue-item-class="issueItemClass"
/>
</slot>
</div>
diff --git a/app/assets/javascripts/reports/constants.js b/app/assets/javascripts/reports/constants.js
index c323dc543f3..66ac1af062b 100644
--- a/app/assets/javascripts/reports/constants.js
+++ b/app/assets/javascripts/reports/constants.js
@@ -16,3 +16,9 @@ export const STATUS_NEUTRAL = 'neutral';
export const ICON_WARNING = 'warning';
export const ICON_SUCCESS = 'success';
export const ICON_NOTFOUND = 'notfound';
+
+export const status = {
+ LOADING: 'LOADING',
+ ERROR: 'ERROR',
+ SUCCESS: 'SUCCESS',
+};
diff --git a/app/assets/javascripts/reports/store/state.js b/app/assets/javascripts/reports/store/state.js
index 5484900276c..25f9f70d095 100644
--- a/app/assets/javascripts/reports/store/state.js
+++ b/app/assets/javascripts/reports/store/state.js
@@ -40,6 +40,11 @@ export default () => ({
text: s__('Reports|Class'),
type: fieldTypes.link,
},
+ classname: {
+ value: null,
+ text: s__('Reports|Classname'),
+ type: fieldTypes.text,
+ },
execution_time: {
value: null,
text: s__('Reports|Execution time'),
diff --git a/app/assets/javascripts/reports/store/utils.js b/app/assets/javascripts/reports/store/utils.js
index 35632218269..10560d0ae8e 100644
--- a/app/assets/javascripts/reports/store/utils.js
+++ b/app/assets/javascripts/reports/store/utils.js
@@ -1,4 +1,4 @@
-import { sprintf, n__, s__ } from '~/locale';
+import { sprintf, n__, s__, __ } from '~/locale';
import {
STATUS_FAILED,
STATUS_SUCCESS,
@@ -38,12 +38,12 @@ const textBuilder = results => {
export const summaryTextBuilder = (name = '', results = {}) => {
const resultsString = textBuilder(results);
- return `${name} contained ${resultsString}`;
+ return sprintf(__('%{name} contained %{resultsString}'), { name, resultsString });
};
export const reportTextBuilder = (name = '', results = {}) => {
const resultsString = textBuilder(results);
- return `${name} found ${resultsString}`;
+ return sprintf(__('%{name} found %{resultsString}'), { name, resultsString });
};
export const statusIcon = status => {
diff --git a/app/assets/javascripts/repository/components/app.vue b/app/assets/javascripts/repository/components/app.vue
new file mode 100644
index 00000000000..98240aef810
--- /dev/null
+++ b/app/assets/javascripts/repository/components/app.vue
@@ -0,0 +1,3 @@
+<template>
+ <router-view />
+</template>
diff --git a/app/assets/javascripts/repository/components/breadcrumbs.vue b/app/assets/javascripts/repository/components/breadcrumbs.vue
new file mode 100644
index 00000000000..6eca015036f
--- /dev/null
+++ b/app/assets/javascripts/repository/components/breadcrumbs.vue
@@ -0,0 +1,61 @@
+<script>
+import getRefMixin from '../mixins/get_ref';
+import getProjectShortPath from '../queries/getProjectShortPath.graphql';
+
+export default {
+ apollo: {
+ projectShortPath: {
+ query: getProjectShortPath,
+ },
+ },
+ mixins: [getRefMixin],
+ props: {
+ currentPath: {
+ type: String,
+ required: false,
+ default: '/',
+ },
+ },
+ data() {
+ return {
+ projectShortPath: '',
+ };
+ },
+ computed: {
+ pathLinks() {
+ return this.currentPath
+ .split('/')
+ .filter(p => p !== '')
+ .reduce(
+ (acc, name, i) => {
+ const path = `${i > 0 ? acc[i].path : ''}/${name}`;
+
+ return acc.concat({
+ name,
+ path,
+ to: `/tree/${this.ref}${path}`,
+ });
+ },
+ [{ name: this.projectShortPath, path: '/', to: `/tree/${this.ref}` }],
+ );
+ },
+ },
+ methods: {
+ isLast(i) {
+ return i === this.pathLinks.length - 1;
+ },
+ },
+};
+</script>
+
+<template>
+ <nav :aria-label="__('Files breadcrumb')">
+ <ol class="breadcrumb repo-breadcrumb">
+ <li v-for="(link, i) in pathLinks" :key="i" class="breadcrumb-item">
+ <router-link :to="link.to" :aria-current="isLast(i) ? 'page' : null">
+ {{ link.name }}
+ </router-link>
+ </li>
+ </ol>
+ </nav>
+</template>
diff --git a/app/assets/javascripts/repository/components/table/header.vue b/app/assets/javascripts/repository/components/table/header.vue
new file mode 100644
index 00000000000..9d30aa88155
--- /dev/null
+++ b/app/assets/javascripts/repository/components/table/header.vue
@@ -0,0 +1,9 @@
+<template>
+ <thead>
+ <tr>
+ <th id="name" scope="col">{{ s__('ProjectFileTree|Name') }}</th>
+ <th id="last-commit" scope="col" class="d-none d-sm-table-cell">{{ __('Last commit') }}</th>
+ <th id="last-update" scope="col" class="text-right">{{ __('Last update') }}</th>
+ </tr>
+ </thead>
+</template>
diff --git a/app/assets/javascripts/repository/components/table/index.vue b/app/assets/javascripts/repository/components/table/index.vue
new file mode 100644
index 00000000000..0357a0e44c3
--- /dev/null
+++ b/app/assets/javascripts/repository/components/table/index.vue
@@ -0,0 +1,146 @@
+<script>
+import { GlLoadingIcon } from '@gitlab/ui';
+import createFlash from '~/flash';
+import { sprintf, __ } from '../../../locale';
+import getRefMixin from '../../mixins/get_ref';
+import getFiles from '../../queries/getFiles.graphql';
+import getProjectPath from '../../queries/getProjectPath.graphql';
+import TableHeader from './header.vue';
+import TableRow from './row.vue';
+import ParentRow from './parent_row.vue';
+
+const PAGE_SIZE = 100;
+
+export default {
+ components: {
+ GlLoadingIcon,
+ TableHeader,
+ TableRow,
+ ParentRow,
+ },
+ mixins: [getRefMixin],
+ apollo: {
+ projectPath: {
+ query: getProjectPath,
+ },
+ },
+ props: {
+ path: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ projectPath: '',
+ nextPageCursor: '',
+ entries: {
+ trees: [],
+ submodules: [],
+ blobs: [],
+ },
+ isLoadingFiles: false,
+ };
+ },
+ computed: {
+ tableCaption() {
+ return sprintf(
+ __('Files, directories, and submodules in the path %{path} for commit reference %{ref}'),
+ { path: this.path, ref: this.ref },
+ );
+ },
+ showParentRow() {
+ return !this.isLoadingFiles && ['', '/'].indexOf(this.path) === -1;
+ },
+ },
+ watch: {
+ $route: function routeChange() {
+ this.entries.trees = [];
+ this.entries.submodules = [];
+ this.entries.blobs = [];
+ this.nextPageCursor = '';
+ this.fetchFiles();
+ },
+ },
+ mounted() {
+ // We need to wait for `ref` and `projectPath` to be set
+ this.$nextTick(() => this.fetchFiles());
+ },
+ methods: {
+ fetchFiles() {
+ this.isLoadingFiles = true;
+
+ return this.$apollo
+ .query({
+ query: getFiles,
+ variables: {
+ projectPath: this.projectPath,
+ ref: this.ref,
+ path: this.path,
+ nextPageCursor: this.nextPageCursor,
+ pageSize: PAGE_SIZE,
+ },
+ })
+ .then(({ data }) => {
+ if (!data) return;
+
+ const pageInfo = this.hasNextPage(data.project.repository.tree);
+
+ this.isLoadingFiles = false;
+ this.entries = Object.keys(this.entries).reduce(
+ (acc, key) => ({
+ ...acc,
+ [key]: this.normalizeData(key, data.project.repository.tree[key].edges),
+ }),
+ {},
+ );
+
+ if (pageInfo && pageInfo.hasNextPage) {
+ this.nextPageCursor = pageInfo.endCursor;
+ this.fetchFiles();
+ }
+ })
+ .catch(() => createFlash(__('An error occurred while fetching folder content.')));
+ },
+ normalizeData(key, data) {
+ return this.entries[key].concat(data.map(({ node }) => node));
+ },
+ hasNextPage(data) {
+ return []
+ .concat(data.trees.pageInfo, data.submodules.pageInfo, data.blobs.pageInfo)
+ .find(({ hasNextPage }) => hasNextPage);
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="tree-content-holder">
+ <div class="table-holder bordered-box">
+ <table class="table tree-table qa-file-tree" aria-live="polite">
+ <caption class="sr-only">
+ {{
+ tableCaption
+ }}
+ </caption>
+ <table-header v-once />
+ <tbody>
+ <parent-row v-show="showParentRow" :commit-ref="ref" :path="path" />
+ <template v-for="val in entries">
+ <table-row
+ v-for="entry in val"
+ :id="entry.id"
+ :key="`${entry.flatPath}-${entry.id}`"
+ :current-path="path"
+ :path="entry.flatPath"
+ :type="entry.type"
+ :url="entry.webUrl"
+ :lfs-oid="entry.lfsOid"
+ />
+ </template>
+ </tbody>
+ </table>
+ <gl-loading-icon v-show="isLoadingFiles" class="my-3" size="md" />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/repository/components/table/parent_row.vue b/app/assets/javascripts/repository/components/table/parent_row.vue
new file mode 100644
index 00000000000..3c39f404226
--- /dev/null
+++ b/app/assets/javascripts/repository/components/table/parent_row.vue
@@ -0,0 +1,37 @@
+<script>
+export default {
+ props: {
+ commitRef: {
+ type: String,
+ required: true,
+ },
+ path: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ parentRoute() {
+ const splitArray = this.path.split('/');
+ splitArray.pop();
+
+ return { path: `/tree/${this.commitRef}/${splitArray.join('/')}` };
+ },
+ },
+ methods: {
+ clickRow() {
+ this.$router.push(this.parentRoute);
+ },
+ },
+};
+</script>
+
+<template>
+ <tr class="tree-item">
+ <td colspan="3" class="tree-item-file-name" @click.self="clickRow">
+ <router-link :to="parentRoute" :aria-label="__('Go to parent')">
+ ..
+ </router-link>
+ </td>
+ </tr>
+</template>
diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue
new file mode 100644
index 00000000000..4519f82fc93
--- /dev/null
+++ b/app/assets/javascripts/repository/components/table/row.vue
@@ -0,0 +1,92 @@
+<script>
+import { GlBadge } from '@gitlab/ui';
+import { visitUrl } from '~/lib/utils/url_utility';
+import { getIconName } from '../../utils/icon';
+import getRefMixin from '../../mixins/get_ref';
+
+export default {
+ components: {
+ GlBadge,
+ },
+ mixins: [getRefMixin],
+ props: {
+ id: {
+ type: String,
+ required: true,
+ },
+ currentPath: {
+ type: String,
+ required: true,
+ },
+ path: {
+ type: String,
+ required: true,
+ },
+ type: {
+ type: String,
+ required: true,
+ },
+ url: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ lfsOid: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+ computed: {
+ routerLinkTo() {
+ return this.isFolder ? { path: `/tree/${this.ref}/${this.path}` } : null;
+ },
+ iconName() {
+ return `fa-${getIconName(this.type, this.path)}`;
+ },
+ isFolder() {
+ return this.type === 'tree';
+ },
+ isSubmodule() {
+ return this.type === 'commit';
+ },
+ linkComponent() {
+ return this.isFolder ? 'router-link' : 'a';
+ },
+ fullPath() {
+ return this.path.replace(new RegExp(`^${this.currentPath}/`), '');
+ },
+ shortSha() {
+ return this.id.slice(0, 8);
+ },
+ },
+ methods: {
+ openRow() {
+ if (this.isFolder) {
+ this.$router.push(this.routerLinkTo);
+ } else {
+ visitUrl(this.url);
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <tr v-once :class="`file_${id}`" class="tree-item" @click="openRow">
+ <td class="tree-item-file-name">
+ <i :aria-label="type" role="img" :class="iconName" class="fa fa-fw"></i>
+ <component :is="linkComponent" :to="routerLinkTo" :href="url" class="str-truncated">
+ {{ fullPath }}
+ </component>
+ <gl-badge v-if="lfsOid" variant="default" class="label-lfs ml-1">
+ LFS
+ </gl-badge>
+ <template v-if="isSubmodule">
+ @ <a href="#" class="commit-sha">{{ shortSha }}</a>
+ </template>
+ </td>
+ <td class="d-none d-sm-table-cell tree-commit"></td>
+ <td class="tree-time-ago text-right"></td>
+ </tr>
+</template>
diff --git a/app/assets/javascripts/repository/fragmentTypes.json b/app/assets/javascripts/repository/fragmentTypes.json
new file mode 100644
index 00000000000..949ebca432b
--- /dev/null
+++ b/app/assets/javascripts/repository/fragmentTypes.json
@@ -0,0 +1 @@
+{"__schema":{"types":[{"kind":"INTERFACE","name":"Entry","possibleTypes":[{"name":"Blob"},{"name":"Submodule"},{"name":"TreeEntry"}]}]}}
diff --git a/app/assets/javascripts/repository/graphql.js b/app/assets/javascripts/repository/graphql.js
new file mode 100644
index 00000000000..ef147ec15cb
--- /dev/null
+++ b/app/assets/javascripts/repository/graphql.js
@@ -0,0 +1,45 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
+import createDefaultClient from '~/lib/graphql';
+import introspectionQueryResultData from './fragmentTypes.json';
+
+Vue.use(VueApollo);
+
+// We create a fragment matcher so that we can create a fragment from an interface
+// Without this, Apollo throws a heuristic fragment matcher warning
+const fragmentMatcher = new IntrospectionFragmentMatcher({
+ introspectionQueryResultData,
+});
+
+const defaultClient = createDefaultClient(
+ {},
+ {
+ cacheConfig: {
+ fragmentMatcher,
+ dataIdFromObject: obj => {
+ /* eslint-disable @gitlab/i18n/no-non-i18n-strings */
+ // eslint-disable-next-line no-underscore-dangle
+ switch (obj.__typename) {
+ // We need to create a dynamic ID for each entry
+ // Each entry can have the same ID as the ID is a commit ID
+ // So we create a unique cache ID with the path and the ID
+ case 'TreeEntry':
+ case 'Submodule':
+ case 'Blob':
+ return `${obj.flatPath}-${obj.id}`;
+ default:
+ // If the type doesn't match any of the above we fallback
+ // to using the default Apollo ID
+ // eslint-disable-next-line no-underscore-dangle
+ return obj.id || obj._id;
+ }
+ /* eslint-enable @gitlab/i18n/no-non-i18n-strings */
+ },
+ },
+ },
+);
+
+export default new VueApollo({
+ defaultClient,
+});
diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js
new file mode 100644
index 00000000000..52f53be045b
--- /dev/null
+++ b/app/assets/javascripts/repository/index.js
@@ -0,0 +1,59 @@
+import Vue from 'vue';
+import createRouter from './router';
+import App from './components/app.vue';
+import Breadcrumbs from './components/breadcrumbs.vue';
+import apolloProvider from './graphql';
+import { setTitle } from './utils/title';
+
+export default function setupVueRepositoryList() {
+ const el = document.getElementById('js-tree-list');
+ const { projectPath, projectShortPath, ref, fullName } = el.dataset;
+ const router = createRouter(projectPath, ref);
+
+ apolloProvider.clients.defaultClient.cache.writeData({
+ data: {
+ projectPath,
+ projectShortPath,
+ ref,
+ },
+ });
+
+ router.afterEach(({ params: { pathMatch } }) => {
+ const isRoot = pathMatch === undefined || pathMatch === '/';
+
+ setTitle(pathMatch, ref, fullName);
+
+ if (!isRoot) {
+ document
+ .querySelectorAll('.js-keep-hidden-on-navigation')
+ .forEach(elem => elem.classList.add('hidden'));
+ }
+
+ document
+ .querySelectorAll('.js-hide-on-navigation')
+ .forEach(elem => elem.classList.toggle('hidden', !isRoot));
+ });
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: document.getElementById('js-repo-breadcrumb'),
+ router,
+ apolloProvider,
+ render(h) {
+ return h(Breadcrumbs, {
+ props: {
+ currentPath: this.$route.params.pathMatch,
+ },
+ });
+ },
+ });
+
+ return new Vue({
+ el,
+ router,
+ apolloProvider,
+ render(h) {
+ return h(App);
+ },
+ });
+}
diff --git a/app/assets/javascripts/repository/mixins/get_ref.js b/app/assets/javascripts/repository/mixins/get_ref.js
new file mode 100644
index 00000000000..b06087d6f42
--- /dev/null
+++ b/app/assets/javascripts/repository/mixins/get_ref.js
@@ -0,0 +1,14 @@
+import getRef from '../queries/getRef.graphql';
+
+export default {
+ apollo: {
+ ref: {
+ query: getRef,
+ },
+ },
+ data() {
+ return {
+ ref: '',
+ };
+ },
+};
diff --git a/app/assets/javascripts/repository/pages/index.vue b/app/assets/javascripts/repository/pages/index.vue
new file mode 100644
index 00000000000..2d92e9174ca
--- /dev/null
+++ b/app/assets/javascripts/repository/pages/index.vue
@@ -0,0 +1,18 @@
+<script>
+import FileTable from '../components/table/index.vue';
+
+export default {
+ components: {
+ FileTable,
+ },
+ data() {
+ return {
+ ref: '',
+ };
+ },
+};
+</script>
+
+<template>
+ <file-table path="/" />
+</template>
diff --git a/app/assets/javascripts/repository/pages/tree.vue b/app/assets/javascripts/repository/pages/tree.vue
new file mode 100644
index 00000000000..3b898d1aa91
--- /dev/null
+++ b/app/assets/javascripts/repository/pages/tree.vue
@@ -0,0 +1,20 @@
+<script>
+import FileTable from '../components/table/index.vue';
+
+export default {
+ components: {
+ FileTable,
+ },
+ props: {
+ path: {
+ type: String,
+ required: false,
+ default: '/',
+ },
+ },
+};
+</script>
+
+<template>
+ <file-table :path="path" />
+</template>
diff --git a/app/assets/javascripts/repository/queries/getFiles.graphql b/app/assets/javascripts/repository/queries/getFiles.graphql
new file mode 100644
index 00000000000..ef924fde556
--- /dev/null
+++ b/app/assets/javascripts/repository/queries/getFiles.graphql
@@ -0,0 +1,58 @@
+fragment TreeEntry on Entry {
+ id
+ flatPath
+ type
+}
+
+fragment PageInfo on PageInfo {
+ hasNextPage
+ endCursor
+}
+
+query getFiles(
+ $projectPath: ID!
+ $path: String
+ $ref: String!
+ $pageSize: Int!
+ $nextPageCursor: String
+) {
+ project(fullPath: $projectPath) {
+ repository {
+ tree(path: $path, ref: $ref) {
+ trees(first: $pageSize, after: $nextPageCursor) {
+ edges {
+ node {
+ ...TreeEntry
+ webUrl
+ }
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
+ submodules(first: $pageSize, after: $nextPageCursor) {
+ edges {
+ node {
+ ...TreeEntry
+ }
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
+ blobs(first: $pageSize, after: $nextPageCursor) {
+ edges {
+ node {
+ ...TreeEntry
+ webUrl
+ lfsOid
+ }
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/repository/queries/getProjectPath.graphql b/app/assets/javascripts/repository/queries/getProjectPath.graphql
new file mode 100644
index 00000000000..74e73e07577
--- /dev/null
+++ b/app/assets/javascripts/repository/queries/getProjectPath.graphql
@@ -0,0 +1,3 @@
+query getProjectPath {
+ projectPath
+}
diff --git a/app/assets/javascripts/repository/queries/getProjectShortPath.graphql b/app/assets/javascripts/repository/queries/getProjectShortPath.graphql
new file mode 100644
index 00000000000..34eb26598c2
--- /dev/null
+++ b/app/assets/javascripts/repository/queries/getProjectShortPath.graphql
@@ -0,0 +1,3 @@
+query getProjectShortPath {
+ projectShortPath @client
+}
diff --git a/app/assets/javascripts/repository/queries/getRef.graphql b/app/assets/javascripts/repository/queries/getRef.graphql
new file mode 100644
index 00000000000..58c09844c3f
--- /dev/null
+++ b/app/assets/javascripts/repository/queries/getRef.graphql
@@ -0,0 +1,3 @@
+query getRef {
+ ref @client
+}
diff --git a/app/assets/javascripts/repository/router.js b/app/assets/javascripts/repository/router.js
new file mode 100644
index 00000000000..9322c81ab97
--- /dev/null
+++ b/app/assets/javascripts/repository/router.js
@@ -0,0 +1,29 @@
+import Vue from 'vue';
+import VueRouter from 'vue-router';
+import { joinPaths } from '../lib/utils/url_utility';
+import IndexPage from './pages/index.vue';
+import TreePage from './pages/tree.vue';
+
+Vue.use(VueRouter);
+
+export default function createRouter(base, baseRef) {
+ return new VueRouter({
+ mode: 'history',
+ base: joinPaths(gon.relative_url_root || '', base),
+ routes: [
+ {
+ path: `/tree/${baseRef}(/.*)?`,
+ name: 'treePath',
+ component: TreePage,
+ props: route => ({
+ path: route.params.pathMatch && route.params.pathMatch.replace(/^\//, ''),
+ }),
+ },
+ {
+ path: '/',
+ name: 'projectRoot',
+ component: IndexPage,
+ },
+ ],
+ });
+}
diff --git a/app/assets/javascripts/repository/utils/icon.js b/app/assets/javascripts/repository/utils/icon.js
new file mode 100644
index 00000000000..661ebb6edfc
--- /dev/null
+++ b/app/assets/javascripts/repository/utils/icon.js
@@ -0,0 +1,99 @@
+const entryTypeIcons = {
+ tree: 'folder',
+ commit: 'archive',
+};
+
+const fileTypeIcons = [
+ { extensions: ['pdf'], name: 'file-pdf-o' },
+ {
+ extensions: [
+ 'jpg',
+ 'jpeg',
+ 'jif',
+ 'jfif',
+ 'jp2',
+ 'jpx',
+ 'j2k',
+ 'j2c',
+ 'png',
+ 'gif',
+ 'tif',
+ 'tiff',
+ 'svg',
+ 'ico',
+ 'bmp',
+ ],
+ name: 'file-image-o',
+ },
+ {
+ extensions: ['zip', 'zipx', 'tar', 'gz', 'bz', 'bzip', 'xz', 'rar', '7z'],
+ name: 'file-archive-o',
+ },
+ { extensions: ['mp3', 'wma', 'ogg', 'oga', 'wav', 'flac', 'aac'], name: 'file-audio-o' },
+ {
+ extensions: [
+ 'mp4',
+ 'm4p',
+ 'm4v',
+ 'mpg',
+ 'mp2',
+ 'mpeg',
+ 'mpe',
+ 'mpv',
+ 'm2v',
+ 'avi',
+ 'mkv',
+ 'flv',
+ 'ogv',
+ 'mov',
+ '3gp',
+ '3g2',
+ ],
+ name: 'file-video-o',
+ },
+ { extensions: ['doc', 'dot', 'docx', 'docm', 'dotx', 'dotm', 'docb'], name: 'file-word-o' },
+ {
+ extensions: [
+ 'xls',
+ 'xlt',
+ 'xlm',
+ 'xlsx',
+ 'xlsm',
+ 'xltx',
+ 'xltm',
+ 'xlsb',
+ 'xla',
+ 'xlam',
+ 'xll',
+ 'xlw',
+ ],
+ name: 'file-excel-o',
+ },
+ {
+ extensions: [
+ 'ppt',
+ 'pot',
+ 'pps',
+ 'pptx',
+ 'pptm',
+ 'potx',
+ 'potm',
+ 'ppam',
+ 'ppsx',
+ 'ppsm',
+ 'sldx',
+ 'sldm',
+ ],
+ name: 'file-powerpoint-o',
+ },
+];
+
+// eslint-disable-next-line import/prefer-default-export
+export const getIconName = (type, path) => {
+ if (entryTypeIcons[type]) return entryTypeIcons[type];
+
+ const extension = path.split('.').pop();
+ const file = fileTypeIcons.find(t => t.extensions.some(ext => ext === extension));
+
+ return file ? file.name : 'file-text-o';
+};
diff --git a/app/assets/javascripts/repository/utils/title.js b/app/assets/javascripts/repository/utils/title.js
new file mode 100644
index 00000000000..87d54c01200
--- /dev/null
+++ b/app/assets/javascripts/repository/utils/title.js
@@ -0,0 +1,10 @@
+// eslint-disable-next-line import/prefer-default-export
+export const setTitle = (pathMatch, ref, project) => {
+ if (!pathMatch) return;
+
+ const path = pathMatch.replace(/^\//, '');
+ const isEmpty = path === '';
+
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
+ document.title = `${isEmpty ? 'Files' : path} · ${ref} · ${project}`;
+};
diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js
index 9a0cdc02952..930c0d5e958 100644
--- a/app/assets/javascripts/right_sidebar.js
+++ b/app/assets/javascripts/right_sidebar.js
@@ -5,7 +5,7 @@ import _ from 'underscore';
import Cookies from 'js-cookie';
import flash from './flash';
import axios from './lib/utils/axios_utils';
-import { __ } from './locale';
+import { sprintf, s__, __ } from './locale';
function Sidebar(currentUser) {
this.toggleTodo = this.toggleTodo.bind(this);
@@ -82,9 +82,9 @@ Sidebar.prototype.toggleTodo = function(e) {
ajaxType = $this.data('deletePath') ? 'delete' : 'post';
if ($this.data('deletePath')) {
- url = '' + $this.data('deletePath');
+ url = String($this.data('deletePath'));
} else {
- url = '' + $this.data('createPath');
+ url = String($this.data('createPath'));
}
$this.tooltip('hide');
@@ -101,7 +101,10 @@ Sidebar.prototype.toggleTodo = function(e) {
this.todoUpdateDone(data);
})
.catch(() =>
- flash(`There was an error ${ajaxType === 'post' ? 'adding a' : 'deleting the'} todo.`),
+ flash(sprintf(__('There was an error %{message} todo.')), {
+ message:
+ ajaxType === 'post' ? s__('RightSidebar|adding a') : s__('RightSidebar|deleting the'),
+ }),
);
};
diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js
index 0a4583b5861..842fb5e5b4f 100644
--- a/app/assets/javascripts/search_autocomplete.js
+++ b/app/assets/javascripts/search_autocomplete.js
@@ -2,7 +2,7 @@
import $ from 'jquery';
import { escape, throttle } from 'underscore';
-import { s__, sprintf } from '~/locale';
+import { s__, __, sprintf } from '~/locale';
import { getIdenticonBackgroundClass, getIdenticonTitle } from '~/helpers/avatar_helper';
import axios from './lib/utils/axios_utils';
import DropdownUtils from './filtered_search/dropdown_utils';
@@ -379,7 +379,7 @@ export class SearchAutocomplete {
}
}
}
- this.wrap.toggleClass('has-value', !!e.target.value);
+ this.wrap.toggleClass('has-value', Boolean(e.target.value));
}
onSearchInputFocus() {
@@ -396,7 +396,7 @@ export class SearchAutocomplete {
onClearInputClick(e) {
e.preventDefault();
- this.wrap.toggleClass('has-value', !!e.target.value);
+ this.wrap.toggleClass('has-value', Boolean(e.target.value));
return this.searchInput.val('').focus();
}
@@ -405,8 +405,9 @@ export class SearchAutocomplete {
this.wrap.removeClass('search-active');
// If input is blank then restore state
if (this.searchInput.val() === '') {
- return this.restoreOriginalState();
+ this.restoreOriginalState();
}
+ this.dropdownMenu.removeClass('show');
}
restoreOriginalState() {
@@ -439,16 +440,18 @@ export class SearchAutocomplete {
restoreMenu() {
var html;
- html = '<ul><li class="dropdown-menu-empty-item"><a>Loading...</a></li></ul>';
+ html = `<ul><li class="dropdown-menu-empty-item"><a>${__('Loading...')}</a></li></ul>`;
return this.dropdownContent.html(html);
}
onClick(item, $el, e) {
if (window.location.pathname.indexOf(item.url) !== -1) {
if (!e.metaKey) e.preventDefault();
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
if (item.category === 'Projects') {
this.projectInputEl.val(item.id);
}
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
if (item.category === 'Groups') {
this.groupInputEl.val(item.id);
}
diff --git a/app/assets/javascripts/serverless/components/functions.vue b/app/assets/javascripts/serverless/components/functions.vue
index f9b4e789563..94341050b86 100644
--- a/app/assets/javascripts/serverless/components/functions.vue
+++ b/app/assets/javascripts/serverless/components/functions.vue
@@ -4,6 +4,7 @@ import { GlLoadingIcon } from '@gitlab/ui';
import FunctionRow from './function_row.vue';
import EnvironmentRow from './environment_row.vue';
import EmptyState from './empty_state.vue';
+import { CHECKING_INSTALLED } from '../constants';
export default {
components: {
@@ -13,10 +14,6 @@ export default {
GlLoadingIcon,
},
props: {
- installed: {
- type: Boolean,
- required: true,
- },
clustersPath: {
type: String,
required: true,
@@ -31,8 +28,15 @@ export default {
},
},
computed: {
- ...mapState(['isLoading', 'hasFunctionData']),
+ ...mapState(['installed', 'isLoading', 'hasFunctionData']),
...mapGetters(['getFunctions']),
+
+ checkingInstalled() {
+ return this.installed === CHECKING_INSTALLED;
+ },
+ isInstalled() {
+ return this.installed === true;
+ },
},
created() {
this.fetchFunctions({
@@ -47,15 +51,16 @@ export default {
<template>
<section id="serverless-functions">
- <div v-if="installed">
+ <gl-loading-icon
+ v-if="checkingInstalled"
+ :size="2"
+ class="prepend-top-default append-bottom-default"
+ />
+
+ <div v-else-if="isInstalled">
<div v-if="hasFunctionData">
- <gl-loading-icon
- v-if="isLoading"
- :size="2"
- class="prepend-top-default append-bottom-default"
- />
- <template v-else>
- <div class="groups-list-tree-container">
+ <template>
+ <div class="groups-list-tree-container js-functions-wrapper">
<ul class="content-list group-list-tree">
<environment-row
v-for="(env, index) in getFunctions"
@@ -66,6 +71,11 @@ export default {
</ul>
</div>
</template>
+ <gl-loading-icon
+ v-if="isLoading"
+ :size="2"
+ class="prepend-top-default append-bottom-default js-functions-loader"
+ />
</div>
<div v-else class="empty-state js-empty-state">
<div class="text-content">
diff --git a/app/assets/javascripts/serverless/components/url.vue b/app/assets/javascripts/serverless/components/url.vue
index ca53bf6c52a..e47a03f1939 100644
--- a/app/assets/javascripts/serverless/components/url.vue
+++ b/app/assets/javascripts/serverless/components/url.vue
@@ -20,7 +20,7 @@ export default {
<template>
<div class="clipboard-group">
- <div class="url-text-field label label-monospace">{{ uri }}</div>
+ <div class="url-text-field label label-monospace monospace">{{ uri }}</div>
<clipboard-button
:text="uri"
:title="s__('ServerlessURL|Copy URL to clipboard')"
diff --git a/app/assets/javascripts/serverless/constants.js b/app/assets/javascripts/serverless/constants.js
index 35f77205f2c..2fa15e56ccb 100644
--- a/app/assets/javascripts/serverless/constants.js
+++ b/app/assets/javascripts/serverless/constants.js
@@ -1,3 +1,7 @@
export const MAX_REQUESTS = 3; // max number of times to retry
export const X_INTERVAL = 5; // Reflects the number of verticle bars on the x-axis
+
+export const CHECKING_INSTALLED = 'checking'; // The backend is still determining whether or not Knative is installed
+
+export const TIMEOUT = 'timeout';
diff --git a/app/assets/javascripts/serverless/serverless_bundle.js b/app/assets/javascripts/serverless/serverless_bundle.js
index 2d3f086ffee..ed3b633d766 100644
--- a/app/assets/javascripts/serverless/serverless_bundle.js
+++ b/app/assets/javascripts/serverless/serverless_bundle.js
@@ -45,7 +45,7 @@ export default class Serverless {
},
});
} else {
- const { statusPath, clustersPath, helpPath, installed } = document.querySelector(
+ const { statusPath, clustersPath, helpPath } = document.querySelector(
'.js-serverless-functions-page',
).dataset;
@@ -56,7 +56,6 @@ export default class Serverless {
render(createElement) {
return createElement(Functions, {
props: {
- installed: installed !== undefined,
clustersPath,
helpPath,
statusPath,
diff --git a/app/assets/javascripts/serverless/store/actions.js b/app/assets/javascripts/serverless/store/actions.js
index 826501c9022..a0a9fdf7ace 100644
--- a/app/assets/javascripts/serverless/store/actions.js
+++ b/app/assets/javascripts/serverless/store/actions.js
@@ -3,13 +3,18 @@ import axios from '~/lib/utils/axios_utils';
import statusCodes from '~/lib/utils/http_status';
import { backOff } from '~/lib/utils/common_utils';
import createFlash from '~/flash';
-import { MAX_REQUESTS } from '../constants';
+import { __ } from '~/locale';
+import { MAX_REQUESTS, CHECKING_INSTALLED, TIMEOUT } from '../constants';
export const requestFunctionsLoading = ({ commit }) => commit(types.REQUEST_FUNCTIONS_LOADING);
export const receiveFunctionsSuccess = ({ commit }, data) =>
commit(types.RECEIVE_FUNCTIONS_SUCCESS, data);
-export const receiveFunctionsNoDataSuccess = ({ commit }) =>
- commit(types.RECEIVE_FUNCTIONS_NODATA_SUCCESS);
+export const receiveFunctionsPartial = ({ commit }, data) =>
+ commit(types.RECEIVE_FUNCTIONS_PARTIAL, data);
+export const receiveFunctionsTimeout = ({ commit }, data) =>
+ commit(types.RECEIVE_FUNCTIONS_TIMEOUT, data);
+export const receiveFunctionsNoDataSuccess = ({ commit }, data) =>
+ commit(types.RECEIVE_FUNCTIONS_NODATA_SUCCESS, data);
export const receiveFunctionsError = ({ commit }, error) =>
commit(types.RECEIVE_FUNCTIONS_ERROR, error);
@@ -25,18 +30,25 @@ export const receiveMetricsError = ({ commit }, error) =>
export const fetchFunctions = ({ dispatch }, { functionsPath }) => {
let retryCount = 0;
+ const functionsPartiallyFetched = data => {
+ if (data.functions !== null && data.functions.length) {
+ dispatch('receiveFunctionsPartial', data);
+ }
+ };
+
dispatch('requestFunctionsLoading');
backOff((next, stop) => {
axios
.get(functionsPath)
.then(response => {
- if (response.status === statusCodes.NO_CONTENT) {
+ if (response.data.knative_installed === CHECKING_INSTALLED) {
retryCount += 1;
if (retryCount < MAX_REQUESTS) {
+ functionsPartiallyFetched(response.data);
next();
} else {
- stop(null);
+ stop(TIMEOUT);
}
} else {
stop(response.data);
@@ -45,10 +57,13 @@ export const fetchFunctions = ({ dispatch }, { functionsPath }) => {
.catch(stop);
})
.then(data => {
- if (data !== null) {
+ if (data === TIMEOUT) {
+ dispatch('receiveFunctionsTimeout');
+ createFlash(__('Loading functions timed out. Please reload the page to try again.'));
+ } else if (data.functions !== null && data.functions.length) {
dispatch('receiveFunctionsSuccess', data);
} else {
- dispatch('receiveFunctionsNoDataSuccess');
+ dispatch('receiveFunctionsNoDataSuccess', data);
}
})
.catch(error => {
diff --git a/app/assets/javascripts/serverless/store/mutation_types.js b/app/assets/javascripts/serverless/store/mutation_types.js
index 25b2f7ac38a..b8fa9ea1a01 100644
--- a/app/assets/javascripts/serverless/store/mutation_types.js
+++ b/app/assets/javascripts/serverless/store/mutation_types.js
@@ -1,5 +1,7 @@
export const REQUEST_FUNCTIONS_LOADING = 'REQUEST_FUNCTIONS_LOADING';
export const RECEIVE_FUNCTIONS_SUCCESS = 'RECEIVE_FUNCTIONS_SUCCESS';
+export const RECEIVE_FUNCTIONS_PARTIAL = 'RECEIVE_FUNCTIONS_PARTIAL';
+export const RECEIVE_FUNCTIONS_TIMEOUT = 'RECEIVE_FUNCTIONS_TIMEOUT';
export const RECEIVE_FUNCTIONS_NODATA_SUCCESS = 'RECEIVE_FUNCTIONS_NODATA_SUCCESS';
export const RECEIVE_FUNCTIONS_ERROR = 'RECEIVE_FUNCTIONS_ERROR';
diff --git a/app/assets/javascripts/serverless/store/mutations.js b/app/assets/javascripts/serverless/store/mutations.js
index 991f32a275d..2685a5b11ff 100644
--- a/app/assets/javascripts/serverless/store/mutations.js
+++ b/app/assets/javascripts/serverless/store/mutations.js
@@ -5,12 +5,23 @@ export default {
state.isLoading = true;
},
[types.RECEIVE_FUNCTIONS_SUCCESS](state, data) {
- state.functions = data;
+ state.functions = data.functions;
+ state.installed = data.knative_installed;
state.isLoading = false;
state.hasFunctionData = true;
},
- [types.RECEIVE_FUNCTIONS_NODATA_SUCCESS](state) {
+ [types.RECEIVE_FUNCTIONS_PARTIAL](state, data) {
+ state.functions = data.functions;
+ state.installed = true;
+ state.isLoading = true;
+ state.hasFunctionData = true;
+ },
+ [types.RECEIVE_FUNCTIONS_TIMEOUT](state) {
+ state.isLoading = false;
+ },
+ [types.RECEIVE_FUNCTIONS_NODATA_SUCCESS](state, data) {
state.isLoading = false;
+ state.installed = data.knative_installed;
state.hasFunctionData = false;
},
[types.RECEIVE_FUNCTIONS_ERROR](state, error) {
diff --git a/app/assets/javascripts/serverless/store/state.js b/app/assets/javascripts/serverless/store/state.js
index afc3f37d7ba..fdd29299749 100644
--- a/app/assets/javascripts/serverless/store/state.js
+++ b/app/assets/javascripts/serverless/store/state.js
@@ -1,5 +1,6 @@
export default () => ({
error: null,
+ installed: 'checking',
isLoading: true,
// functions
diff --git a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
index 7f86741ed29..35eba266625 100644
--- a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
+++ b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
@@ -2,7 +2,7 @@
import $ from 'jquery';
import createFlash from '~/flash';
import Icon from '~/vue_shared/components/icon.vue';
-import GfmAutoComplete from '~/gfm_auto_complete';
+import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
import { __, s__ } from '~/locale';
import Api from '~/api';
import { GlModal, GlTooltipDirective } from '@gitlab/ui';
@@ -178,7 +178,7 @@ export default {
/>
<div ref="userStatusForm" class="form-group position-relative m-0">
<div class="input-group">
- <span class="input-group-btn">
+ <span class="input-group-prepend">
<button
ref="toggleEmojiMenuButton"
v-gl-tooltip.bottom
@@ -194,9 +194,9 @@ export default {
v-show="noEmoji"
class="js-no-emoji-placeholder no-emoji-placeholder position-relative"
>
- <icon name="emoji_slightly_smiling_face" css-classes="award-control-icon-neutral" />
- <icon name="emoji_smiley" css-classes="award-control-icon-positive" />
- <icon name="emoji_smile" css-classes="award-control-icon-super-positive" />
+ <icon name="slight-smile" css-classes="award-control-icon-neutral" />
+ <icon name="smiley" css-classes="award-control-icon-positive" />
+ <icon name="smile" css-classes="award-control-icon-super-positive" />
</span>
</button>
</span>
@@ -211,7 +211,7 @@ export default {
@keyup.enter.prevent
@click="hideEmojiMenu"
/>
- <span v-show="isDirty" class="input-group-btn">
+ <span v-show="isDirty" class="input-group-append">
<button
v-gl-tooltip.bottom
:title="s__('SetStatusModal|Clear status')"
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignees.vue b/app/assets/javascripts/sidebar/components/assignees/assignees.vue
index ce378e24289..0074d7099dc 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignees.vue
@@ -153,7 +153,7 @@ export default {
data-placement="left"
data-boundary="viewport"
>
- <i v-if="hasNoUsers" aria-label="No Assignee" class="fa fa-user"> </i>
+ <i v-if="hasNoUsers" aria-label="None" class="fa fa-user"> </i>
<button
v-for="(user, index) in users"
v-if="shouldRenderCollapsedAssignee(index)"
@@ -184,8 +184,8 @@ export default {
<i aria-hidden="true" data-hidden="true" class="fa fa-exclamation-triangle"></i>
</span>
<template v-if="hasNoUsers">
- <span class="assign-yourself no-value">
- No assignee
+ <span class="assign-yourself no-value qa-assign-yourself">
+ None
<template v-if="editable">
- <button type="button" class="btn-link" @click="assignSelf">assign yourself</button>
</template>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
index c03b2a68c78..d84d5344935 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
@@ -49,10 +49,10 @@ export default {
},
computed: {
hasTimeSpent() {
- return !!this.timeSpent;
+ return Boolean(this.timeSpent);
},
hasTimeEstimate() {
- return !!this.timeEstimate;
+ return Boolean(this.timeEstimate);
},
showComparisonState() {
return this.hasTimeEstimate && this.hasTimeSpent;
@@ -67,7 +67,7 @@ export default {
return !this.hasTimeEstimate && !this.hasTimeSpent;
},
showHelpState() {
- return !!this.showHelp;
+ return Boolean(this.showHelp);
},
},
created() {
diff --git a/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js b/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
index 225ebb61195..110175a6779 100644
--- a/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
+++ b/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
@@ -1,5 +1,6 @@
import $ from 'jquery';
import _ from 'underscore';
+import { __ } from '~/locale';
function isValidProjectId(id) {
return id > 0;
@@ -40,7 +41,9 @@ class SidebarMoveIssue {
this.mediator
.fetchAutocompleteProjects(searchTerm)
.then(callback)
- .catch(() => new window.Flash('An error occurred while fetching projects autocomplete.'));
+ .catch(
+ () => new window.Flash(__('An error occurred while fetching projects autocomplete.')),
+ );
},
renderRow: project => `
<li>
@@ -72,7 +75,7 @@ class SidebarMoveIssue {
this.$confirmButton.disable().addClass('is-loading');
this.mediator.moveIssue().catch(() => {
- window.Flash('An error occurred while moving the issue.');
+ window.Flash(__('An error occurred while moving the issue.'));
this.$confirmButton.enable().removeClass('is-loading');
});
}
diff --git a/app/assets/javascripts/sidebar/sidebar_mediator.js b/app/assets/javascripts/sidebar/sidebar_mediator.js
index 3e040ec8428..22ac8df9699 100644
--- a/app/assets/javascripts/sidebar/sidebar_mediator.js
+++ b/app/assets/javascripts/sidebar/sidebar_mediator.js
@@ -2,6 +2,7 @@ import { visitUrl } from '../lib/utils/url_utility';
import Flash from '../flash';
import Service from './services/sidebar_service';
import Store from './stores/sidebar_store';
+import { __ } from '~/locale';
export default class SidebarMediator {
constructor(options) {
@@ -45,7 +46,7 @@ export default class SidebarMediator {
.then(data => {
this.processFetchedData(data);
})
- .catch(() => new Flash('Error occurred when fetching sidebar data'));
+ .catch(() => new Flash(__('Error occurred when fetching sidebar data')));
}
processFetchedData(data) {
diff --git a/app/assets/javascripts/snippet/snippet_embed.js b/app/assets/javascripts/snippet/snippet_embed.js
index 873a506a92f..fe08d2c7ebb 100644
--- a/app/assets/javascripts/snippet/snippet_embed.js
+++ b/app/assets/javascripts/snippet/snippet_embed.js
@@ -1,3 +1,5 @@
+import { __ } from '~/locale';
+
export default () => {
const { protocol, host, pathname } = window.location;
const shareBtn = document.querySelector('.js-share-btn');
@@ -10,7 +12,7 @@ export default () => {
shareBtn.classList.add('is-active');
embedBtn.classList.remove('is-active');
snippetUrlArea.value = url;
- embedAction.innerText = 'Share';
+ embedAction.innerText = __('Share');
});
embedBtn.addEventListener('click', () => {
@@ -18,6 +20,6 @@ export default () => {
shareBtn.classList.remove('is-active');
const scriptTag = `<script src="${url}.js"></script>`;
snippetUrlArea.value = scriptTag;
- embedAction.innerText = 'Embed';
+ embedAction.innerText = __('Embed');
});
};
diff --git a/app/assets/javascripts/star.js b/app/assets/javascripts/star.js
index 7404dfbf22a..70f89152f70 100644
--- a/app/assets/javascripts/star.js
+++ b/app/assets/javascripts/star.js
@@ -31,7 +31,7 @@ export default class Star {
$this.prepend(spriteIcon('star', iconClasses));
}
})
- .catch(() => Flash('Star toggle failed. Try again later.'));
+ .catch(() => Flash(__('Star toggle failed. Try again later.')));
});
}
}
diff --git a/app/assets/javascripts/subscription_select.js b/app/assets/javascripts/subscription_select.js
index ebe1c6dd02d..7206bbd7109 100644
--- a/app/assets/javascripts/subscription_select.js
+++ b/app/assets/javascripts/subscription_select.js
@@ -1,4 +1,5 @@
import $ from 'jquery';
+import { __ } from './locale';
export default function subscriptionSelect() {
$('.js-subscription-event').each((i, element) => {
@@ -8,7 +9,7 @@ export default function subscriptionSelect() {
selectable: true,
fieldName,
toggleLabel(selected, el, instance) {
- let label = 'Subscription';
+ let label = __('Subscription');
const $item = instance.dropdown.find('.is-active');
if ($item.length) {
label = $item.text();
diff --git a/app/assets/javascripts/templates/issuable_template_selector.js b/app/assets/javascripts/templates/issuable_template_selector.js
index 6065770e68d..78609ce0610 100644
--- a/app/assets/javascripts/templates/issuable_template_selector.js
+++ b/app/assets/javascripts/templates/issuable_template_selector.js
@@ -3,6 +3,7 @@
import $ from 'jquery';
import Api from '../api';
import TemplateSelector from '../blob/template_selector';
+import { __ } from '~/locale';
export default class IssuableTemplateSelector extends TemplateSelector {
constructor(...args) {
@@ -25,7 +26,7 @@ export default class IssuableTemplateSelector extends TemplateSelector {
$('.no-template', this.dropdown.parent()).on('click', () => {
this.currentTemplate.content = '';
this.setInputValueToTemplateContent();
- $('.dropdown-toggle-text', this.dropdown).text('Choose a template');
+ $('.dropdown-toggle-text', this.dropdown).text(__('Choose a template'));
});
}
diff --git a/app/assets/javascripts/terminal/terminal.js b/app/assets/javascripts/terminal/terminal.js
index e5dd7a465ea..9c7c10d9864 100644
--- a/app/assets/javascripts/terminal/terminal.js
+++ b/app/assets/javascripts/terminal/terminal.js
@@ -4,6 +4,7 @@ import { Terminal } from 'xterm';
import * as fit from 'xterm/lib/addons/fit/fit';
import * as webLinks from 'xterm/lib/addons/webLinks/webLinks';
import { canScrollUp, canScrollDown } from '~/lib/utils/dom_utils';
+import { __ } from '~/locale';
const SCROLL_MARGIN = 5;
@@ -78,7 +79,8 @@ export default class GLTerminal {
}
handleSocketFailure() {
- this.terminal.write('\r\nConnection failure');
+ this.terminal.write('\r\n');
+ this.terminal.write(__('Connection failure'));
}
addScrollListener(onScrollLimit) {
diff --git a/app/assets/javascripts/test_utils/index.js b/app/assets/javascripts/test_utils/index.js
index a55a338eea8..1e75ee60671 100644
--- a/app/assets/javascripts/test_utils/index.js
+++ b/app/assets/javascripts/test_utils/index.js
@@ -1,5 +1,5 @@
-import 'core-js/es6/map';
-import 'core-js/es6/set';
+import 'core-js/es/map';
+import 'core-js/es/set';
import simulateDrag from './simulate_drag';
import simulateInput from './simulate_input';
diff --git a/app/assets/javascripts/u2f/error.js b/app/assets/javascripts/u2f/error.js
index 1a98564ff55..ca0fc0700ad 100644
--- a/app/assets/javascripts/u2f/error.js
+++ b/app/assets/javascripts/u2f/error.js
@@ -1,3 +1,5 @@
+import { __ } from '~/locale';
+
export default class U2FError {
constructor(errorCode, u2fFlowType) {
this.errorCode = errorCode;
@@ -8,15 +10,17 @@ export default class U2FError {
message() {
if (this.errorCode === window.u2f.ErrorCodes.BAD_REQUEST && this.httpsDisabled) {
- return 'U2F only works with HTTPS-enabled websites. Contact your administrator for more details.';
+ return __(
+ 'U2F only works with HTTPS-enabled websites. Contact your administrator for more details.',
+ );
} else if (this.errorCode === window.u2f.ErrorCodes.DEVICE_INELIGIBLE) {
if (this.u2fFlowType === 'authenticate') {
- return 'This device has not been registered with us.';
+ return __('This device has not been registered with us.');
}
if (this.u2fFlowType === 'register') {
- return 'This device has already been registered with us.';
+ return __('This device has already been registered with us.');
}
}
- return 'There was a problem communicating with your device.';
+ return __('There was a problem communicating with your device.');
}
}
diff --git a/app/assets/javascripts/usage_ping_consent.js b/app/assets/javascripts/usage_ping_consent.js
index d3d745a3c11..1e7a5fb19c2 100644
--- a/app/assets/javascripts/usage_ping_consent.js
+++ b/app/assets/javascripts/usage_ping_consent.js
@@ -2,6 +2,7 @@ import $ from 'jquery';
import axios from './lib/utils/axios_utils';
import Flash, { hideFlash } from './flash';
import { parseBoolean } from './lib/utils/common_utils';
+import { __ } from './locale';
export default () => {
$('body').on('click', '.js-usage-consent-action', e => {
@@ -25,7 +26,7 @@ export default () => {
})
.catch(() => {
hideConsentMessage();
- Flash('Something went wrong. Try again later.');
+ Flash(__('Something went wrong. Try again later.'));
});
});
};
diff --git a/app/assets/javascripts/users_select.js b/app/assets/javascripts/users_select.js
index 8c71615dff2..33cedf78331 100644
--- a/app/assets/javascripts/users_select.js
+++ b/app/assets/javascripts/users_select.js
@@ -5,7 +5,7 @@
import $ from 'jquery';
import _ from 'underscore';
import axios from './lib/utils/axios_utils';
-import { __ } from './locale';
+import { s__, __, sprintf } from './locale';
import ModalStore from './boards/stores/modal_store';
// TODO: remove eventHub hack after code splitting refactor
@@ -157,14 +157,20 @@ function UsersSelect(currentUser, els, options = {}) {
.get(0);
if (selectedUsers.length === 0) {
- return 'Unassigned';
+ return s__('UsersSelect|Unassigned');
} else if (selectedUsers.length === 1) {
return firstUser.name;
} else if (isSelected) {
const otherSelected = selectedUsers.filter(s => s !== selectedUser.id);
- return `${selectedUser.name} + ${otherSelected.length} more`;
+ return sprintf(s__('UsersSelect|%{name} + %{length} more'), {
+ name: selectedUser.name,
+ length: otherSelected.length,
+ });
} else {
- return `${firstUser.name} + ${selectedUsers.length - 1} more`;
+ return sprintf(s__('UsersSelect|%{name} + %{length} more'), {
+ name: firstUser.name,
+ length: selectedUsers.length - 1,
+ });
}
};
@@ -218,11 +224,11 @@ function UsersSelect(currentUser, els, options = {}) {
tooltipTitle = _.escape(user.name);
} else {
user = {
- name: 'Unassigned',
+ name: s__('UsersSelect|Unassigned'),
username: '',
avatar: '',
};
- tooltipTitle = __('Assignee');
+ tooltipTitle = s__('UsersSelect|Assignee');
}
$value.html(assigneeTemplate(user));
$collapsedSidebar.attr('title', tooltipTitle).tooltip('_fixTitle');
@@ -233,7 +239,11 @@ function UsersSelect(currentUser, els, options = {}) {
'<% if( avatar ) { %> <a class="author-link" href="/<%- username %>"> <img width="24" class="avatar avatar-inline s24" alt="" src="<%- avatar %>"> </a> <% } else { %> <i class="fa fa-user"></i> <% } %>',
);
assigneeTemplate = _.template(
- '<% if (username) { %> <a class="author-link bold" href="/<%- username %>"> <% if( avatar ) { %> <img width="32" class="avatar avatar-inline s32" alt="" src="<%- avatar %>"> <% } %> <span class="author"><%- name %></span> <span class="username"> @<%- username %> </span> </a> <% } else { %> <span class="no-value assign-yourself"> No assignee - <a href="#" class="js-assign-yourself"> assign yourself </a> </span> <% } %>',
+ `<% if (username) { %> <a class="author-link bold" href="/<%- username %>"> <% if( avatar ) { %> <img width="32" class="avatar avatar-inline s32" alt="" src="<%- avatar %>"> <% } %> <span class="author"><%- name %></span> <span class="username"> @<%- username %> </span> </a> <% } else { %> <span class="no-value assign-yourself">
+ ${sprintf(s__('UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}'), {
+ openingTag: '<a href="#" class="js-assign-yourself">',
+ closingTag: '</a>',
+ })}</span> <% } %>`,
);
return $dropdown.glDropdown({
showMenuAbove: showMenuAbove,
@@ -302,7 +312,7 @@ function UsersSelect(currentUser, els, options = {}) {
showDivider += 1;
users.unshift({
beforeDivider: true,
- name: 'Unassigned',
+ name: s__('UsersSelect|Unassigned'),
id: 0,
});
}
@@ -310,7 +320,7 @@ function UsersSelect(currentUser, els, options = {}) {
showDivider += 1;
name = showAnyUser;
if (name === true) {
- name = 'Any User';
+ name = s__('UsersSelect|Any User');
}
anyUser = {
beforeDivider: true,
@@ -417,6 +427,7 @@ function UsersSelect(currentUser, els, options = {}) {
const isActive = $el.hasClass('is-active');
const previouslySelected = $dropdown
.closest('.selectbox')
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
.find("input[name='" + $dropdown.data('fieldName') + "'][value!=0]");
// Enables support for limiting the number of users selected
@@ -596,7 +607,7 @@ function UsersSelect(currentUser, els, options = {}) {
showEmailUser = $(select).data('emailUser');
firstUser = $(select).data('firstUser');
return $(select).select2({
- placeholder: 'Search for a user',
+ placeholder: __('Search for a user'),
multiple: $(select).hasClass('multiselect'),
minimumInputLength: 0,
query: function(query) {
@@ -621,7 +632,7 @@ function UsersSelect(currentUser, els, options = {}) {
}
if (showNullUser) {
nullUser = {
- name: 'Unassigned',
+ name: s__('UsersSelect|Unassigned'),
id: 0,
};
data.results.unshift(nullUser);
@@ -629,7 +640,7 @@ function UsersSelect(currentUser, els, options = {}) {
if (showAnyUser) {
name = showAnyUser;
if (name === true) {
- name = 'Any User';
+ name = s__('UsersSelect|Any User');
}
anyUser = {
name: name,
@@ -645,7 +656,7 @@ function UsersSelect(currentUser, els, options = {}) {
) {
var trimmed = query.term.trim();
emailUser = {
- name: 'Invite "' + trimmed + '" by email',
+ name: sprintf(__('Invite "%{trimmed}" by email'), { trimmed }),
username: trimmed,
id: trimmed,
invite: true,
@@ -688,7 +699,7 @@ UsersSelect.prototype.initSelection = function(element, callback) {
id = $(element).val();
if (id === '0') {
nullUser = {
- name: 'Unassigned',
+ name: s__('UsersSelect|Unassigned'),
};
return callback(nullUser);
} else if (id !== '') {
diff --git a/app/assets/javascripts/validators/input_validator.js b/app/assets/javascripts/validators/input_validator.js
new file mode 100644
index 00000000000..f37373977b8
--- /dev/null
+++ b/app/assets/javascripts/validators/input_validator.js
@@ -0,0 +1,34 @@
+const invalidInputClass = 'gl-field-error-outline';
+
+export default class InputValidator {
+ constructor() {
+ this.inputDomElement = {};
+ this.inputErrorMessage = {};
+ this.errorMessage = null;
+ this.invalidInput = null;
+ }
+
+ setValidationStateAndMessage() {
+ this.setValidationMessage();
+
+ const isInvalidInput = !this.inputDomElement.checkValidity();
+ this.inputDomElement.classList.toggle(invalidInputClass, isInvalidInput);
+ this.inputErrorMessage.classList.toggle('hide', !isInvalidInput);
+ }
+
+ setValidationMessage() {
+ if (this.invalidInput) {
+ this.inputDomElement.setCustomValidity(this.errorMessage);
+ this.inputErrorMessage.innerHTML = this.errorMessage;
+ } else {
+ this.resetValidationMessage();
+ }
+ }
+
+ resetValidationMessage() {
+ if (this.inputDomElement.validationMessage === this.errorMessage) {
+ this.inputDomElement.setCustomValidity('');
+ this.inputErrorMessage.innerHTML = this.inputDomElement.title;
+ }
+ }
+}
diff --git a/app/assets/javascripts/visual_review_toolbar/components/comment.js b/app/assets/javascripts/visual_review_toolbar/components/comment.js
new file mode 100644
index 00000000000..2fec96d1435
--- /dev/null
+++ b/app/assets/javascripts/visual_review_toolbar/components/comment.js
@@ -0,0 +1,132 @@
+import { BLACK, COMMENT_BOX, MUTED, LOGOUT } from './constants';
+import { clearNote, note, postError } from './note';
+import { buttonClearStyles, selectCommentBox, selectCommentButton, selectNote } from './utils';
+
+const comment = `
+ <div>
+ <textarea id="${COMMENT_BOX}" name="${COMMENT_BOX}" rows="3" placeholder="Enter your feedback or idea" class="gitlab-input" aria-required="true"></textarea>
+ ${note}
+ <p class="gitlab-metadata-note">Additional metadata will be included: browser, OS, current page, user agent, and viewport dimensions.</p>
+ </div>
+ <div class="gitlab-button-wrapper">
+ <button class="gitlab-button gitlab-button-secondary" style="${buttonClearStyles}" type="button" id="${LOGOUT}"> Logout </button>
+ <button class="gitlab-button gitlab-button-success" style="${buttonClearStyles}" type="button" id="gitlab-comment-button"> Send feedback </button>
+ </div>
+`;
+
+const resetCommentBox = () => {
+ const commentBox = selectCommentBox();
+ const commentButton = selectCommentButton();
+
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
+ commentButton.innerText = 'Send feedback';
+ commentButton.classList.replace('gitlab-button-secondary', 'gitlab-button-success');
+ commentButton.style.opacity = 1;
+
+ commentBox.style.pointerEvents = 'auto';
+ commentBox.style.color = BLACK;
+};
+
+const resetCommentButton = () => {
+ const commentBox = selectCommentBox();
+ const currentNote = selectNote();
+
+ commentBox.value = '';
+ currentNote.innerText = '';
+};
+
+const resetComment = () => {
+ resetCommentBox();
+ resetCommentButton();
+};
+
+const confirmAndClear = mergeRequestId => {
+ const commentButton = selectCommentButton();
+ const currentNote = selectNote();
+
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
+ commentButton.innerText = 'Feedback sent';
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
+ currentNote.innerText = `Your comment was successfully posted to merge request #${mergeRequestId}`;
+ setTimeout(resetComment, 2000);
+};
+
+const setInProgressState = () => {
+ const commentButton = selectCommentButton();
+ const commentBox = selectCommentBox();
+
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
+ commentButton.innerText = 'Sending feedback';
+ commentButton.classList.replace('gitlab-button-success', 'gitlab-button-secondary');
+ commentButton.style.opacity = 0.5;
+ commentBox.style.color = MUTED;
+ commentBox.style.pointerEvents = 'none';
+};
+
+const postComment = ({
+ href,
+ platform,
+ browser,
+ userAgent,
+ innerWidth,
+ innerHeight,
+ projectId,
+ mergeRequestId,
+ mrUrl,
+ token,
+}) => {
+ // Clear any old errors
+ clearNote(COMMENT_BOX);
+
+ setInProgressState();
+
+ const commentText = selectCommentBox().value.trim();
+
+ if (!commentText) {
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
+ postError('Your comment appears to be empty.', COMMENT_BOX);
+ resetCommentBox();
+ return;
+ }
+
+ const detailText = `
+ \n
+<details>
+ <summary>Metadata</summary>
+ Posted from ${href} | ${platform} | ${browser} | ${innerWidth} x ${innerHeight}.
+ <br /><br />
+ <em>User agent: ${userAgent}</em>
+</details>
+ `;
+
+ const url = `
+ ${mrUrl}/api/v4/projects/${projectId}/merge_requests/${mergeRequestId}/discussions`;
+
+ const body = `${commentText} ${detailText}`;
+
+ fetch(url, {
+ method: 'POST',
+ headers: {
+ 'PRIVATE-TOKEN': token,
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({ body }),
+ })
+ .then(response => {
+ if (response.ok) {
+ confirmAndClear(mergeRequestId);
+ return;
+ }
+
+ throw new Error(`${response.status}: ${response.statusText}`);
+ })
+ .catch(err => {
+ postError(
+ `Your comment could not be sent. Please try again. Error: ${err.message}`,
+ COMMENT_BOX,
+ );
+ resetCommentBox();
+ });
+};
+
+export { comment, postComment };
diff --git a/app/assets/javascripts/visual_review_toolbar/components/constants.js b/app/assets/javascripts/visual_review_toolbar/components/constants.js
new file mode 100644
index 00000000000..32ed1153515
--- /dev/null
+++ b/app/assets/javascripts/visual_review_toolbar/components/constants.js
@@ -0,0 +1,37 @@
+// component selectors
+const COLLAPSE_BUTTON = 'gitlab-collapse';
+const COMMENT_BOX = 'gitlab-comment';
+const COMMENT_BUTTON = 'gitlab-comment-button';
+const FORM = 'gitlab-form-wrapper';
+const LOGIN = 'gitlab-login';
+const LOGOUT = 'gitlab-logout-button';
+const NOTE = 'gitlab-validation-note';
+const REMEMBER_TOKEN = 'gitlab-remember_token';
+const REVIEW_CONTAINER = 'gitlab-review-container';
+const TOKEN_BOX = 'gitlab-token';
+
+// colors — these are applied programmatically
+// rest of styles belong in ./styles
+const BLACK = 'rgba(46, 46, 46, 1)';
+const CLEAR = 'rgba(255, 255, 255, 0)';
+const MUTED = 'rgba(223, 223, 223, 0.5)';
+const RED = 'rgba(219, 59, 33, 1)';
+const WHITE = 'rgba(255, 255, 255, 1)';
+
+export {
+ COLLAPSE_BUTTON,
+ COMMENT_BOX,
+ COMMENT_BUTTON,
+ FORM,
+ LOGIN,
+ LOGOUT,
+ NOTE,
+ REMEMBER_TOKEN,
+ REVIEW_CONTAINER,
+ TOKEN_BOX,
+ BLACK,
+ CLEAR,
+ MUTED,
+ RED,
+ WHITE,
+};
diff --git a/app/assets/javascripts/visual_review_toolbar/components/index.js b/app/assets/javascripts/visual_review_toolbar/components/index.js
new file mode 100644
index 00000000000..43581818152
--- /dev/null
+++ b/app/assets/javascripts/visual_review_toolbar/components/index.js
@@ -0,0 +1,23 @@
+import { comment, postComment } from './comment';
+import { COLLAPSE_BUTTON, COMMENT_BUTTON, LOGIN, LOGOUT, REVIEW_CONTAINER } from './constants';
+import { authorizeUser, login } from './login';
+import { selectContainer } from './utils';
+import { form, logoutUser, toggleForm } from './wrapper';
+import { collapseButton } from './wrapper_icons';
+
+export {
+ authorizeUser,
+ collapseButton,
+ comment,
+ form,
+ login,
+ logoutUser,
+ postComment,
+ selectContainer,
+ toggleForm,
+ COLLAPSE_BUTTON,
+ COMMENT_BUTTON,
+ LOGIN,
+ LOGOUT,
+ REVIEW_CONTAINER,
+};
diff --git a/app/assets/javascripts/visual_review_toolbar/components/login.js b/app/assets/javascripts/visual_review_toolbar/components/login.js
new file mode 100644
index 00000000000..ce713cdc520
--- /dev/null
+++ b/app/assets/javascripts/visual_review_toolbar/components/login.js
@@ -0,0 +1,52 @@
+import { LOGIN, REMEMBER_TOKEN, TOKEN_BOX } from './constants';
+import { clearNote, note, postError } from './note';
+import { buttonClearStyles, selectRemember, selectToken } from './utils';
+import { addCommentForm } from './wrapper';
+
+const login = `
+ <div>
+ <label for="${TOKEN_BOX}" class="gitlab-label">Enter your <a class="gitlab-link" href="https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html">personal access token</a></label>
+ <input class="gitlab-input" type="password" id="${TOKEN_BOX}" name="${TOKEN_BOX}" aria-required="true" autocomplete="current-password">
+ ${note}
+ </div>
+ <div class="gitlab-checkbox-wrapper">
+ <input type="checkbox" id="${REMEMBER_TOKEN}" name="${REMEMBER_TOKEN}" value="remember">
+ <label for="${REMEMBER_TOKEN}" class="gitlab-checkbox-label">Remember me</label>
+ </div>
+ <div class="gitlab-button-wrapper">
+ <button class="gitlab-button-wide gitlab-button gitlab-button-success" style="${buttonClearStyles}" type="button" id="${LOGIN}"> Submit </button>
+ </div>
+`;
+
+const storeToken = (token, state) => {
+ const { localStorage } = window;
+ const rememberMe = selectRemember().checked;
+
+ // All the browsers we support have localStorage, so let's silently fail
+ // and go on with the rest of the functionality.
+ try {
+ if (rememberMe) {
+ localStorage.setItem('token', token);
+ }
+ } finally {
+ state.token = token;
+ }
+};
+
+const authorizeUser = state => {
+ // Clear any old errors
+ clearNote(TOKEN_BOX);
+
+ const token = selectToken().value;
+
+ if (!token) {
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
+ postError('Please enter your token.', TOKEN_BOX);
+ return;
+ }
+
+ storeToken(token, state);
+ addCommentForm();
+};
+
+export { authorizeUser, login };
diff --git a/app/assets/javascripts/visual_review_toolbar/components/note.js b/app/assets/javascripts/visual_review_toolbar/components/note.js
new file mode 100644
index 00000000000..dfebf58fd95
--- /dev/null
+++ b/app/assets/javascripts/visual_review_toolbar/components/note.js
@@ -0,0 +1,27 @@
+import { NOTE, RED } from './constants';
+import { selectById, selectNote } from './utils';
+
+const note = `
+ <p id=${NOTE} class='gitlab-message'></p>
+`;
+
+const clearNote = inputId => {
+ const currentNote = selectNote();
+ currentNote.innerText = '';
+ currentNote.style.color = '';
+
+ if (inputId) {
+ const field = document.getElementById(inputId);
+ field.style.borderColor = '';
+ }
+};
+
+const postError = (message, inputId) => {
+ const currentNote = selectNote();
+ const field = selectById(inputId);
+ field.style.borderColor = RED;
+ currentNote.style.color = RED;
+ currentNote.innerText = message;
+};
+
+export { clearNote, note, postError };
diff --git a/app/assets/javascripts/visual_review_toolbar/components/utils.js b/app/assets/javascripts/visual_review_toolbar/components/utils.js
new file mode 100644
index 00000000000..7bc2e5a905b
--- /dev/null
+++ b/app/assets/javascripts/visual_review_toolbar/components/utils.js
@@ -0,0 +1,42 @@
+/* global document */
+
+import {
+ COLLAPSE_BUTTON,
+ COMMENT_BOX,
+ COMMENT_BUTTON,
+ FORM,
+ NOTE,
+ REMEMBER_TOKEN,
+ REVIEW_CONTAINER,
+ TOKEN_BOX,
+} from './constants';
+
+// this style must be applied inline in a handful of components
+/* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
+const buttonClearStyles = `
+ -webkit-appearance: none;
+`;
+
+// selector functions to abstract out a little
+const selectById = id => document.getElementById(id);
+const selectCollapseButton = () => document.getElementById(COLLAPSE_BUTTON);
+const selectCommentBox = () => document.getElementById(COMMENT_BOX);
+const selectCommentButton = () => document.getElementById(COMMENT_BUTTON);
+const selectContainer = () => document.getElementById(REVIEW_CONTAINER);
+const selectForm = () => document.getElementById(FORM);
+const selectNote = () => document.getElementById(NOTE);
+const selectRemember = () => document.getElementById(REMEMBER_TOKEN);
+const selectToken = () => document.getElementById(TOKEN_BOX);
+
+export {
+ buttonClearStyles,
+ selectById,
+ selectCollapseButton,
+ selectContainer,
+ selectCommentBox,
+ selectCommentButton,
+ selectForm,
+ selectNote,
+ selectRemember,
+ selectToken,
+};
diff --git a/app/assets/javascripts/visual_review_toolbar/components/wrapper.js b/app/assets/javascripts/visual_review_toolbar/components/wrapper.js
new file mode 100644
index 00000000000..233b7ec496c
--- /dev/null
+++ b/app/assets/javascripts/visual_review_toolbar/components/wrapper.js
@@ -0,0 +1,82 @@
+import { comment } from './comment';
+import { CLEAR, FORM, WHITE } from './constants';
+import { login } from './login';
+import { selectCollapseButton, selectContainer, selectForm } from './utils';
+import { commentIcon, compressIcon } from './wrapper_icons';
+
+const form = content => `
+ <form id=${FORM}>
+ ${content}
+ </form>
+`;
+
+const addCommentForm = () => {
+ const formWrapper = selectForm();
+ formWrapper.innerHTML = comment;
+};
+
+const addLoginForm = () => {
+ const formWrapper = selectForm();
+ formWrapper.innerHTML = login;
+};
+
+function logoutUser() {
+ const { localStorage } = window;
+
+ // All the browsers we support have localStorage, so let's silently fail
+ // and go on with the rest of the functionality.
+ try {
+ localStorage.removeItem('token');
+ } catch (err) {
+ return;
+ }
+
+ addLoginForm();
+}
+
+function toggleForm() {
+ const container = selectContainer();
+ const collapseButton = selectCollapseButton();
+ const currentForm = selectForm();
+ const OPEN = 'open';
+ const CLOSED = 'closed';
+
+ /*
+ You may wonder why we spread the arrays before we reverse them.
+ In the immortal words of MDN,
+ Careful: reverse is destructive. It also changes the original array
+ */
+
+ const openButtonClasses = ['gitlab-collapse-closed', 'gitlab-collapse-open'];
+ const closedButtonClasses = [...openButtonClasses].reverse();
+ const openContainerClasses = ['gitlab-closed-wrapper', 'gitlab-open-wrapper'];
+ const closedContainerClasses = [...openContainerClasses].reverse();
+
+ const stateVals = {
+ [OPEN]: {
+ buttonClasses: openButtonClasses,
+ containerClasses: openContainerClasses,
+ icon: compressIcon,
+ display: 'flex',
+ backgroundColor: WHITE,
+ },
+ [CLOSED]: {
+ buttonClasses: closedButtonClasses,
+ containerClasses: closedContainerClasses,
+ icon: commentIcon,
+ display: 'none',
+ backgroundColor: CLEAR,
+ },
+ };
+
+ const nextState = collapseButton.classList.contains('gitlab-collapse-open') ? CLOSED : OPEN;
+ const currentVals = stateVals[nextState];
+
+ container.classList.replace(...currentVals.containerClasses);
+ container.style.backgroundColor = currentVals.backgroundColor;
+ currentForm.style.display = currentVals.display;
+ collapseButton.classList.replace(...currentVals.buttonClasses);
+ collapseButton.innerHTML = currentVals.icon;
+}
+
+export { addCommentForm, addLoginForm, form, logoutUser, toggleForm };
diff --git a/app/assets/javascripts/visual_review_toolbar/components/wrapper_icons.js b/app/assets/javascripts/visual_review_toolbar/components/wrapper_icons.js
new file mode 100644
index 00000000000..b686fd4f5c2
--- /dev/null
+++ b/app/assets/javascripts/visual_review_toolbar/components/wrapper_icons.js
@@ -0,0 +1,15 @@
+import { buttonClearStyles } from './utils';
+
+const commentIcon = `
+ <svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>icn/comment</title><path d="M4 11.132l1.446-.964A1 1 0 0 1 6 10h5a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v6.132zM6.303 12l-2.748 1.832A1 1 0 0 1 2 13V5a3 3 0 0 1 3-3h6a3 3 0 0 1 3 3v4a3 3 0 0 1-3 3H6.303z" id="gitlab-comment-icon"/></svg>
+`;
+
+const compressIcon = `
+ <svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>icn/compress</title><path d="M5.27 12.182l-1.562 1.561a1 1 0 0 1-1.414 0h-.001a1 1 0 0 1 0-1.415l1.56-1.56L2.44 9.353a.5.5 0 0 1 .353-.854H7.09a.5.5 0 0 1 .5.5v4.294a.5.5 0 0 1-.853.353l-1.467-1.465zm6.911-6.914l1.464 1.464a.5.5 0 0 1-.353.854H8.999a.5.5 0 0 1-.5-.5V2.793a.5.5 0 0 1 .854-.354l1.414 1.415 1.56-1.561a1 1 0 1 1 1.415 1.414l-1.561 1.56z" id="gitlab-compress-icon"/></svg>
+`;
+
+const collapseButton = `
+ <button id='gitlab-collapse' style='${buttonClearStyles}' class='gitlab-button gitlab-button-secondary gitlab-collapse gitlab-collapse-open'>${compressIcon}</button>
+`;
+
+export { commentIcon, compressIcon, collapseButton };
diff --git a/app/assets/javascripts/visual_review_toolbar/index.js b/app/assets/javascripts/visual_review_toolbar/index.js
new file mode 100644
index 00000000000..941d77e25b4
--- /dev/null
+++ b/app/assets/javascripts/visual_review_toolbar/index.js
@@ -0,0 +1,37 @@
+import './styles/toolbar.css';
+
+import { form, selectContainer, REVIEW_CONTAINER } from './components';
+import { debounce, eventLookup, getInitialView, initializeState, updateWindowSize } from './store';
+
+/*
+
+ Welcome to the visual review toolbar files. A few useful notes:
+
+ - These files build a static script that is served from our webpack
+ assets folder. (https://gitlab.com/assets/webpack/visual_review_toolbar.js)
+
+ - To compile this file, run `yarn webpack-vrt`.
+
+ - Vue is not used in these files because we do not want to ask users to
+ install another library at this time. It's all pure vanilla javascript.
+
+*/
+
+window.addEventListener('load', () => {
+ initializeState(window, document);
+
+ const { content, toggleButton } = getInitialView(window);
+ const container = document.createElement('div');
+
+ container.setAttribute('id', REVIEW_CONTAINER);
+ container.insertAdjacentHTML('beforeend', toggleButton);
+ container.insertAdjacentHTML('beforeend', form(content));
+
+ document.body.insertBefore(container, document.body.firstChild);
+
+ selectContainer().addEventListener('click', event => {
+ eventLookup(event)();
+ });
+
+ window.addEventListener('resize', debounce(updateWindowSize.bind(null, window), 200));
+});
diff --git a/app/assets/javascripts/visual_review_toolbar/store/events.js b/app/assets/javascripts/visual_review_toolbar/store/events.js
new file mode 100644
index 00000000000..93996be8473
--- /dev/null
+++ b/app/assets/javascripts/visual_review_toolbar/store/events.js
@@ -0,0 +1,36 @@
+import {
+ authorizeUser,
+ logoutUser,
+ postComment,
+ toggleForm,
+ COLLAPSE_BUTTON,
+ COMMENT_BUTTON,
+ LOGIN,
+ LOGOUT,
+} from '../components';
+
+import { state } from './state';
+
+const noop = () => {};
+
+const eventLookup = ({ target: { id } }) => {
+ switch (id) {
+ case COLLAPSE_BUTTON:
+ return toggleForm;
+ case COMMENT_BUTTON:
+ return postComment.bind(null, state);
+ case LOGIN:
+ return authorizeUser.bind(null, state);
+ case LOGOUT:
+ return logoutUser;
+ default:
+ return noop;
+ }
+};
+
+const updateWindowSize = wind => {
+ state.innerWidth = wind.innerWidth;
+ state.innerHeight = wind.innerHeight;
+};
+
+export { eventLookup, updateWindowSize };
diff --git a/app/assets/javascripts/visual_review_toolbar/store/index.js b/app/assets/javascripts/visual_review_toolbar/store/index.js
new file mode 100644
index 00000000000..7143588c0bf
--- /dev/null
+++ b/app/assets/javascripts/visual_review_toolbar/store/index.js
@@ -0,0 +1,5 @@
+import { eventLookup, updateWindowSize } from './events';
+import { getInitialView, initializeState } from './state';
+import debounce from './utils';
+
+export { debounce, eventLookup, getInitialView, initializeState, updateWindowSize };
diff --git a/app/assets/javascripts/visual_review_toolbar/store/state.js b/app/assets/javascripts/visual_review_toolbar/store/state.js
new file mode 100644
index 00000000000..f5ede6e85b2
--- /dev/null
+++ b/app/assets/javascripts/visual_review_toolbar/store/state.js
@@ -0,0 +1,77 @@
+import { comment, login, collapseButton } from '../components';
+
+const state = {
+ browser: '',
+ href: '',
+ innerWidth: '',
+ innerHeight: '',
+ mergeRequestId: '',
+ mrUrl: '',
+ platform: '',
+ projectId: '',
+ userAgent: '',
+ token: '',
+};
+
+// adapted from https://developer.mozilla.org/en-US/docs/Web/API/Window/navigator#Example_2_Browser_detect_and_return_an_index
+const getBrowserId = sUsrAg => {
+ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
+ const aKeys = ['MSIE', 'Edge', 'Firefox', 'Safari', 'Chrome', 'Opera'];
+ let nIdx = aKeys.length - 1;
+
+ for (nIdx; nIdx > -1 && sUsrAg.indexOf(aKeys[nIdx]) === -1; nIdx -= 1);
+ return aKeys[nIdx];
+};
+
+const initializeState = (wind, doc) => {
+ const {
+ innerWidth,
+ innerHeight,
+ location: { href },
+ navigator: { platform, userAgent },
+ } = wind;
+
+ const browser = getBrowserId(userAgent);
+
+ const scriptEl = doc.getElementById('review-app-toolbar-script');
+ const { projectId, mergeRequestId, mrUrl } = scriptEl.dataset;
+
+ // This mutates our default state object above. It's weird but it makes the linter happy.
+ Object.assign(state, {
+ browser,
+ href,
+ innerWidth,
+ innerHeight,
+ mergeRequestId,
+ mrUrl,
+ platform,
+ projectId,
+ userAgent,
+ });
+};
+
+function getInitialView({ localStorage }) {
+ const loginView = {
+ content: login,
+ toggleButton: collapseButton,
+ };
+
+ const commentView = {
+ content: comment,
+ toggleButton: collapseButton,
+ };
+
+ try {
+ const token = localStorage.getItem('token');
+
+ if (token) {
+ state.token = token;
+ return commentView;
+ }
+ return loginView;
+ } catch (err) {
+ return loginView;
+ }
+}
+
+export { initializeState, getInitialView, state };
diff --git a/app/assets/javascripts/visual_review_toolbar/store/utils.js b/app/assets/javascripts/visual_review_toolbar/store/utils.js
new file mode 100644
index 00000000000..5cf145351b3
--- /dev/null
+++ b/app/assets/javascripts/visual_review_toolbar/store/utils.js
@@ -0,0 +1,15 @@
+const debounce = (fn, time) => {
+ let current;
+
+ const debounced = () => {
+ if (current) {
+ clearTimeout(current);
+ }
+
+ current = setTimeout(fn, time);
+ };
+
+ return debounced;
+};
+
+export default debounce;
diff --git a/app/assets/javascripts/visual_review_toolbar/styles/toolbar.css b/app/assets/javascripts/visual_review_toolbar/styles/toolbar.css
new file mode 100644
index 00000000000..342b3599a44
--- /dev/null
+++ b/app/assets/javascripts/visual_review_toolbar/styles/toolbar.css
@@ -0,0 +1,149 @@
+/*
+ As a standalone script, the toolbar has its own css
+ */
+
+#gitlab-collapse > * {
+ pointer-events: none;
+}
+
+#gitlab-form-wrapper {
+ display: flex;
+ flex-direction: column;
+ width: 100%
+}
+
+#gitlab-review-container {
+ max-width: 22rem;
+ max-height: 22rem;
+ overflow: scroll;
+ position: fixed;
+ bottom: 1rem;
+ right: 1rem;
+ display: flex;
+ flex-direction: row-reverse;
+ padding: 1rem;
+ background-color: #fff;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell,
+ 'Helvetica Neue', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
+ 'Noto Color Emoji';
+ font-size: .8rem;
+ font-weight: 400;
+ color: #2e2e2e;
+}
+
+.gitlab-open-wrapper {
+ max-width: 22rem;
+ max-height: 22rem;
+}
+
+.gitlab-closed-wrapper {
+ max-width: 3.4rem;
+ max-height: 3.4rem;
+}
+
+.gitlab-button {
+ cursor: pointer;
+ transition: background-color 100ms linear, border-color 100ms linear, color 100ms linear, box-shadow 100ms linear;
+}
+
+.gitlab-button-secondary {
+ background: none #fff;
+ margin: 0 .5rem;
+ border: 1px solid #e3e3e3;
+}
+
+.gitlab-button-secondary:hover {
+ background-color: #f0f0f0;
+ border-color: #e3e3e3;
+ color: #2e2e2e;
+}
+
+.gitlab-button-secondary:active {
+ color: #2e2e2e;
+ background-color: #e1e1e1;
+ border-color: #dadada;
+}
+
+.gitlab-button-success:hover {
+ color: #fff;
+ background-color: #137e3f;
+ border-color: #127339;
+}
+
+.gitlab-button-success:active {
+ background-color: #168f48;
+ border-color: #12753a;
+ color: #fff;
+}
+
+.gitlab-button-success {
+ background-color: #1aaa55;
+ border: 1px solid #168f48;
+ color: #fff;
+}
+
+.gitlab-button-wide {
+ width: 100%;
+}
+
+.gitlab-button-wrapper {
+ margin-top: 1rem;
+ display: flex;
+ align-items: baseline;
+ justify-content: flex-end;
+}
+
+.gitlab-collapse {
+ width: 2.4rem;
+ height: 2.2rem;
+ margin-left: 1rem;
+ padding: .5rem;
+}
+
+.gitlab-collapse-closed {
+ align-self: center;
+}
+
+.gitlab-checkbox-label {
+ padding: 0 .2rem;
+}
+
+.gitlab-checkbox-wrapper {
+ display: flex;
+ align-items: baseline;
+}
+
+.gitlab-label {
+ font-weight: 600;
+ display: inline-block;
+ width: 100%;
+}
+
+.gitlab-link {
+ color: #1b69b6;
+ text-decoration: none;
+ background-color: transparent;
+ background-image: none;
+}
+
+.gitlab-message {
+ padding: .25rem 0;
+ margin: 0;
+ line-height: 1.2rem;
+}
+
+.gitlab-metadata-note {
+ font-size: .7rem;
+ line-height: 1rem;
+ color: #666;
+ margin-bottom: 0;
+}
+
+.gitlab-input {
+ width: 100%;
+ border: 1px solid #dfdfdf;
+ border-radius: 4px;
+ padding: .1rem .2rem;
+ min-height: 2rem;
+ max-width: 17rem;
+}
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
index da0a9483f8e..abe5bdd2901 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
@@ -23,6 +23,8 @@ export default {
TooltipOnTruncate,
FilteredSearchDropdown,
ReviewAppLink,
+ VisualReviewAppLink: () =>
+ import('ee_component/vue_merge_request_widget/components/visual_review_app_link.vue'),
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -37,6 +39,20 @@ export default {
type: Boolean,
required: true,
},
+ showVisualReviewApp: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ visualReviewAppMeta: {
+ type: Object,
+ required: false,
+ default: () => ({
+ sourceProjectId: '',
+ mergeRequestId: '',
+ appUrl: '',
+ }),
+ },
},
deployedTextMap: {
running: __('Deploying to'),
@@ -61,16 +77,16 @@ export default {
return this.deployment.external_url;
},
hasExternalUrls() {
- return !!(this.deployment.external_url && this.deployment.external_url_formatted);
+ return Boolean(this.deployment.external_url && this.deployment.external_url_formatted);
},
hasDeploymentTime() {
- return !!(this.deployment.deployed_at && this.deployment.deployed_at_formatted);
+ return Boolean(this.deployment.deployed_at && this.deployment.deployed_at_formatted);
},
hasDeploymentMeta() {
- return !!(this.deployment.url && this.deployment.name);
+ return Boolean(this.deployment.url && this.deployment.name);
},
hasMetrics() {
- return !!this.deployment.metrics_url;
+ return Boolean(this.deployment.metrics_url);
},
deployedText() {
return this.$options.deployedTextMap[this.deployment.status];
@@ -168,6 +184,11 @@ export default {
:link="deploymentExternalUrl"
:css-class="`deploy-link js-deploy-url inline ${slotProps.className}`"
/>
+ <visual-review-app-link
+ v-if="showVisualReviewApp"
+ :link="deploymentExternalUrl"
+ :app-metadata="visualReviewAppMeta"
+ />
</template>
<template slot="result" slot-scope="slotProps">
@@ -187,11 +208,17 @@ export default {
</a>
</template>
</filtered-search-dropdown>
- <review-app-link
- v-else
- :link="deploymentExternalUrl"
- css-class="js-deploy-url js-deploy-url-feature-flag deploy-link btn btn-default btn-sm inlin"
- />
+ <template v-else>
+ <review-app-link
+ :link="deploymentExternalUrl"
+ css-class="js-deploy-url js-deploy-url-feature-flag deploy-link btn btn-default btn-sm inline"
+ />
+ <visual-review-app-link
+ v-if="showVisualReviewApp"
+ :link="deploymentExternalUrl"
+ :app-metadata="visualReviewAppMeta"
+ />
+ </template>
</template>
<span
v-if="deployment.stop_url"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue
index 040315b3c66..19a222462b3 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue
@@ -37,7 +37,7 @@ export default {
</script>
<template>
- <div class="m-3 ml-5" :class="messageClass">
+ <div class="m-3 ml-7" :class="messageClass">
<slot></slot>
<gl-link v-if="helpPath" :href="helpPath" target="_blank">
<icon :size="16" name="question-o" class="align-middle" />
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
index 361441640e1..e20a16900d4 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
@@ -128,7 +128,7 @@ export default {
:disabled="mr.sourceBranchRemoved"
data-target="#modal_merge_info"
data-toggle="modal"
- class="btn btn-default js-check-out-branch append-right-default"
+ class="btn btn-default js-check-out-branch append-right-8"
type="button"
>
{{ s__('mrWidget|Check out branch') }}
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
index f5a1ff2f6fd..c377c16fb13 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
@@ -5,6 +5,7 @@ import { sprintf, __ } from '~/locale';
import PipelineStage from '~/pipelines/components/stage.vue';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import Icon from '~/vue_shared/components/icon.vue';
+import PipelineLink from '~/vue_shared/components/ci_pipeline_link.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import mrWidgetPipelineMixin from 'ee_else_ce/vue_merge_request_widget/mixins/mr_widget_pipeline';
@@ -16,6 +17,7 @@ export default {
Icon,
TooltipOnTruncate,
GlLink,
+ PipelineLink,
LinkedPipelinesMiniList: () =>
import('ee_component/vue_shared/components/linked_pipelines_mini_list.vue'),
},
@@ -94,8 +96,8 @@ export default {
</script>
<template>
- <div v-if="hasPipeline || hasCIError" class="ci-widget media js-ci-widget">
- <template v-if="hasCIError">
+ <div class="ci-widget media js-ci-widget">
+ <template v-if="!hasPipeline || hasCIError">
<div
class="add-border ci-status-icon ci-status-icon-failed ci-error js-ci-error append-right-default"
>
@@ -112,9 +114,12 @@ export default {
<div class="media-body">
<div class="font-weight-bold js-pipeline-info-container">
{{ s__('Pipeline|Pipeline') }}
- <gl-link :href="pipeline.path" class="pipeline-id font-weight-normal pipeline-number"
- >#{{ pipeline.id }}</gl-link
- >
+ <pipeline-link
+ :href="pipeline.path"
+ :pipeline-id="pipeline.id"
+ :pipeline-iid="pipeline.iid"
+ class="pipeline-id pipeline-iid font-weight-normal"
+ />
{{ pipeline.details.status.label }}
<template v-if="hasCommitInfo">
{{ s__('Pipeline|for') }}
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue
index 5f5fe67b3c1..03a15ba81ed 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue
@@ -30,9 +30,6 @@ export default {
},
},
computed: {
- pipeline() {
- return this.isPostMerge ? this.mr.mergePipeline : this.mr.pipeline;
- },
branch() {
return this.isPostMerge ? this.mr.targetBranch : this.mr.sourceBranch;
},
@@ -48,6 +45,19 @@ export default {
hasDeploymentMetrics() {
return this.isPostMerge;
},
+ visualReviewAppMeta() {
+ return {
+ appUrl: this.mr.appUrl,
+ mergeRequestId: this.mr.iid,
+ sourceProjectId: this.mr.sourceProjectId,
+ };
+ },
+ pipeline() {
+ return this.isPostMerge ? this.mr.mergePipeline : this.mr.pipeline;
+ },
+ showVisualReviewAppLink() {
+ return Boolean(this.mr.visualReviewFF && this.mr.visualReviewAppAvailable);
+ },
},
};
</script>
@@ -61,14 +71,18 @@ export default {
:source-branch-link="branchLink"
:troubleshooting-docs-path="mr.troubleshootingDocsPath"
/>
- <div v-if="deployments.length" slot="footer" class="mr-widget-extension">
- <deployment
- v-for="deployment in deployments"
- :key="deployment.id"
- :class="deploymentClass"
- :deployment="deployment"
- :show-metrics="hasDeploymentMetrics"
- />
- </div>
+ <template v-slot:footer>
+ <div v-if="deployments.length" class="mr-widget-extension">
+ <deployment
+ v-for="deployment in deployments"
+ :key="deployment.id"
+ :class="deploymentClass"
+ :deployment="deployment"
+ :show-metrics="hasDeploymentMetrics"
+ :show-visual-review-app="true"
+ :visual-review-app-meta="visualReviewAppMeta"
+ />
+ </div>
+ </template>
</mr-widget-container>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/review_app_link.vue b/app/assets/javascripts/vue_merge_request_widget/components/review_app_link.vue
index de9c122f268..457a71cab95 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/review_app_link.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/review_app_link.vue
@@ -19,6 +19,6 @@ export default {
</script>
<template>
<a :href="link" target="_blank" rel="noopener noreferrer nofollow" :class="cssClass">
- {{ __('View app') }} <icon name="external-link" />
+ {{ __('View app') }} <icon css-classes="fgray" name="external-link" />
</a>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue b/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
index 780ecdcdac4..6aad2a26a53 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
@@ -14,7 +14,7 @@ export default {
</script>
<template>
- <p v-once class="mr-info-list mr-links source-branch-removal-status append-bottom-0">
+ <p v-once class="mr-info-list mr-links append-bottom-0">
<span class="status-text" v-html="removesBranchText"> </span>
<i v-tooltip :title="tooltipTitle" :aria-label="tooltipTitle" class="fa fa-question-circle">
</i>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue
index a38f25cce35..acd8037cfb2 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue
@@ -30,6 +30,7 @@ export default {
:id="inputId"
:value="value"
class="form-control js-gfm-input append-bottom-default commit-message-edit"
+ dir="auto"
required="required"
rows="7"
@input="$emit('input', $event.target.value)"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
new file mode 100644
index 00000000000..5958c2cf87e
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
@@ -0,0 +1,134 @@
+<script>
+import _ from 'underscore';
+import autoMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/auto_merge';
+import Flash from '../../../flash';
+import statusIcon from '../mr_widget_status_icon.vue';
+import MrWidgetAuthor from '../../components/mr_widget_author.vue';
+import eventHub from '../../event_hub';
+import { AUTO_MERGE_STRATEGIES } from '../../constants';
+
+export default {
+ name: 'MRWidgetAutoMergeEnabled',
+ components: {
+ MrWidgetAuthor,
+ statusIcon,
+ },
+ mixins: [autoMergeMixin],
+ props: {
+ mr: {
+ type: Object,
+ required: true,
+ default: () => ({}),
+ },
+ service: {
+ type: Object,
+ required: true,
+ default: () => ({}),
+ },
+ },
+ data() {
+ return {
+ isCancellingAutoMerge: false,
+ isRemovingSourceBranch: false,
+ };
+ },
+ computed: {
+ canRemoveSourceBranch() {
+ const {
+ shouldRemoveSourceBranch,
+ canRemoveSourceBranch,
+ mergeUserId,
+ currentUserId,
+ } = this.mr;
+
+ return !shouldRemoveSourceBranch && canRemoveSourceBranch && mergeUserId === currentUserId;
+ },
+ },
+ methods: {
+ cancelAutomaticMerge() {
+ this.isCancellingAutoMerge = true;
+ this.service
+ .cancelAutomaticMerge()
+ .then(res => res.data)
+ .then(data => {
+ eventHub.$emit('UpdateWidgetData', data);
+ })
+ .catch(() => {
+ this.isCancellingAutoMerge = false;
+ Flash('Something went wrong. Please try again.');
+ });
+ },
+ removeSourceBranch() {
+ const options = {
+ sha: this.mr.sha,
+ auto_merge_strategy: this.mr.autoMergeStrategy,
+ should_remove_source_branch: true,
+ };
+
+ this.isRemovingSourceBranch = true;
+ this.service
+ .merge(options)
+ .then(res => res.data)
+ .then(data => {
+ if (_.includes(AUTO_MERGE_STRATEGIES, data.status)) {
+ eventHub.$emit('MRWidgetUpdateRequested');
+ }
+ })
+ .catch(() => {
+ this.isRemovingSourceBranch = false;
+ Flash('Something went wrong. Please try again.');
+ });
+ },
+ },
+};
+</script>
+<template>
+ <div class="mr-widget-body media">
+ <status-icon status="success" />
+ <div class="media-body">
+ <h4 class="d-flex align-items-start">
+ <span class="append-right-10">
+ <span class="js-status-text-before-author">{{ statusTextBeforeAuthor }}</span>
+ <mr-widget-author :author="mr.setToAutoMergeBy" />
+ <span class="js-status-text-after-author">{{ statusTextAfterAuthor }}</span>
+ </span>
+ <a
+ v-if="mr.canCancelAutomaticMerge"
+ :disabled="isCancellingAutoMerge"
+ role="button"
+ href="#"
+ class="btn btn-sm btn-default js-cancel-auto-merge"
+ @click.prevent="cancelAutomaticMerge"
+ >
+ <i v-if="isCancellingAutoMerge" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
+ {{ cancelButtonText }}
+ </a>
+ </h4>
+ <section class="mr-info-list">
+ <p>
+ {{ s__('mrWidget|The changes will be merged into') }}
+ <a :href="mr.targetBranchPath" class="label-branch"> {{ mr.targetBranch }} </a>
+ </p>
+ <p v-if="mr.shouldRemoveSourceBranch">
+ {{ s__('mrWidget|The source branch will be deleted') }}
+ </p>
+ <p v-else class="d-flex align-items-start">
+ <span class="append-right-10">
+ {{ s__('mrWidget|The source branch will not be deleted') }}
+ </span>
+ <a
+ v-if="canRemoveSourceBranch"
+ :disabled="isRemovingSourceBranch"
+ role="button"
+ class="btn btn-sm btn-default js-remove-source-branch"
+ href="#"
+ @click.prevent="removeSourceBranch"
+ >
+ <i v-if="isRemovingSourceBranch" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
+ {{ s__('mrWidget|Delete source branch') }}
+ </a>
+ </p>
+ </section>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue
index a3a44dd8e99..83e7d6db9fa 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue
@@ -35,9 +35,7 @@ export default {
<status-icon status="warning" />
<div class="media-body space-children">
<span class="bold">
- <template v-if="mr.mergeError"
- >{{ mr.mergeError }}.</template
- >
+ <template v-if="mr.mergeError">{{ mr.mergeError }}</template>
{{ s__('mrWidget|This merge request failed to be merged automatically') }}
</span>
<button
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
index f6f445c1cef..3df4a777aca 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
@@ -26,7 +26,7 @@ export default {
);
},
showResolveButton() {
- return this.mr.conflictResolutionPath && this.mr.canMerge;
+ return this.mr.conflictResolutionPath && this.mr.canPushToSourceBranch;
},
showPopover() {
return this.showResolveButton && this.mr.sourceBranchProtected;
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue
deleted file mode 100644
index 1b3af2fccf2..00000000000
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue
+++ /dev/null
@@ -1,130 +0,0 @@
-<script>
-import Flash from '../../../flash';
-import statusIcon from '../mr_widget_status_icon.vue';
-import MrWidgetAuthor from '../../components/mr_widget_author.vue';
-import eventHub from '../../event_hub';
-
-export default {
- name: 'MRWidgetMergeWhenPipelineSucceeds',
- components: {
- MrWidgetAuthor,
- statusIcon,
- },
- props: {
- mr: {
- type: Object,
- required: true,
- default: () => ({}),
- },
- service: {
- type: Object,
- required: true,
- default: () => ({}),
- },
- },
- data() {
- return {
- isCancellingAutoMerge: false,
- isRemovingSourceBranch: false,
- };
- },
- computed: {
- canRemoveSourceBranch() {
- const {
- shouldRemoveSourceBranch,
- canRemoveSourceBranch,
- mergeUserId,
- currentUserId,
- } = this.mr;
-
- return !shouldRemoveSourceBranch && canRemoveSourceBranch && mergeUserId === currentUserId;
- },
- },
- methods: {
- cancelAutomaticMerge() {
- this.isCancellingAutoMerge = true;
- this.service
- .cancelAutomaticMerge()
- .then(res => res.data)
- .then(data => {
- eventHub.$emit('UpdateWidgetData', data);
- })
- .catch(() => {
- this.isCancellingAutoMerge = false;
- Flash('Something went wrong. Please try again.');
- });
- },
- removeSourceBranch() {
- const options = {
- sha: this.mr.sha,
- merge_when_pipeline_succeeds: true,
- should_remove_source_branch: true,
- };
-
- this.isRemovingSourceBranch = true;
- this.service
- .merge(options)
- .then(res => res.data)
- .then(data => {
- if (data.status === 'merge_when_pipeline_succeeds') {
- eventHub.$emit('MRWidgetUpdateRequested');
- }
- })
- .catch(() => {
- this.isRemovingSourceBranch = false;
- Flash('Something went wrong. Please try again.');
- });
- },
- },
-};
-</script>
-<template>
- <div class="mr-widget-body media">
- <status-icon status="success" />
- <div class="media-body">
- <h4 class="d-flex align-items-start">
- <span class="append-right-10">
- {{ s__('mrWidget|Set by') }}
- <mr-widget-author :author="mr.setToMWPSBy" />
- {{ s__('mrWidget|to be merged automatically when the pipeline succeeds') }}
- </span>
- <a
- v-if="mr.canCancelAutomaticMerge"
- :disabled="isCancellingAutoMerge"
- role="button"
- href="#"
- class="btn btn-sm btn-default js-cancel-auto-merge"
- @click.prevent="cancelAutomaticMerge"
- >
- <i v-if="isCancellingAutoMerge" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
- {{ s__('mrWidget|Cancel automatic merge') }}
- </a>
- </h4>
- <section class="mr-info-list">
- <p>
- {{ s__('mrWidget|The changes will be merged into') }}
- <a :href="mr.targetBranchPath" class="label-branch"> {{ mr.targetBranch }} </a>
- </p>
- <p v-if="mr.shouldRemoveSourceBranch">
- {{ s__('mrWidget|The source branch will be deleted') }}
- </p>
- <p v-else class="d-flex align-items-start">
- <span class="append-right-10">
- {{ s__('mrWidget|The source branch will not be deleted') }}
- </span>
- <a
- v-if="canRemoveSourceBranch"
- :disabled="isRemovingSourceBranch"
- role="button"
- class="btn btn-sm btn-default js-remove-source-branch"
- href="#"
- @click.prevent="removeSourceBranch"
- >
- <i v-if="isRemovingSourceBranch" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
- {{ s__('mrWidget|Delete source branch') }}
- </a>
- </p>
- </section>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
index bb76eb1030d..ca1b4a57717 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
@@ -1,8 +1,10 @@
<script>
+import _ from 'underscore';
import successSvg from 'icons/_icon_status_success.svg';
import warningSvg from 'icons/_icon_status_warning.svg';
import simplePoll from '~/lib/utils/simple_poll';
import { __ } from '~/locale';
+import readyToMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/ready_to_merge';
import MergeRequest from '../../../merge_request';
import Flash from '../../../flash';
import statusIcon from '../mr_widget_status_icon.vue';
@@ -11,6 +13,7 @@ import SquashBeforeMerge from './squash_before_merge.vue';
import CommitsHeader from './commits_header.vue';
import CommitEdit from './commit_edit.vue';
import CommitMessageDropdown from './commit_message_dropdown.vue';
+import { AUTO_MERGE_STRATEGIES } from '../../constants';
export default {
name: 'ReadyToMerge',
@@ -21,6 +24,7 @@ export default {
CommitEdit,
CommitMessageDropdown,
},
+ mixins: [readyToMergeMixin],
props: {
mr: { type: Object, required: true },
service: { type: Object, required: true },
@@ -28,8 +32,6 @@ export default {
data() {
return {
removeSourceBranch: this.mr.shouldRemoveSourceBranch,
- mergeWhenBuildSucceeds: false,
- setToMergeWhenPipelineSucceeds: false,
isMakingRequest: false,
isMergingImmediately: false,
commitMessage: this.mr.commitMessage,
@@ -40,18 +42,18 @@ export default {
};
},
computed: {
- shouldShowMergeWhenPipelineSucceedsText() {
- return this.mr.isPipelineActive;
+ isAutoMergeAvailable() {
+ return !_.isEmpty(this.mr.availableAutoMergeStrategies);
},
status() {
- const { pipeline, isPipelineActive, isPipelineFailed, hasCI, ciStatus } = this.mr;
+ const { pipeline, isPipelineFailed, hasCI, ciStatus } = this.mr;
if (hasCI && !ciStatus) {
return 'failed';
+ } else if (this.isAutoMergeAvailable) {
+ return 'pending';
} else if (!pipeline) {
return 'success';
- } else if (isPipelineActive) {
- return 'pending';
} else if (isPipelineFailed) {
return 'failed';
}
@@ -85,23 +87,14 @@ export default {
mergeButtonText() {
if (this.isMergingImmediately) {
return __('Merge in progress');
- } else if (this.shouldShowMergeWhenPipelineSucceedsText) {
- return __('Merge when pipeline succeeds');
+ } else if (this.isAutoMergeAvailable) {
+ return this.autoMergeText;
}
- return 'Merge';
+ return __('Merge');
},
shouldShowMergeOptionsDropdown() {
- return this.mr.isPipelineActive && !this.mr.onlyAllowMergeIfPipelineSucceeds;
- },
- isMergeButtonDisabled() {
- const { commitMessage } = this;
- return Boolean(
- !commitMessage.length ||
- !this.shouldShowMergeControls ||
- this.isMakingRequest ||
- this.mr.preventMerge,
- );
+ return this.isAutoMergeAvailable && !this.mr.onlyAllowMergeIfPipelineSucceeds;
},
isRemoveSourceBranchButtonDisabled() {
return this.isMergeButtonDisabled;
@@ -111,7 +104,7 @@ export default {
return enableSquashBeforeMerge && commitsCount > 1;
},
shouldShowMergeControls() {
- return this.mr.isMergeAllowed || this.shouldShowMergeWhenPipelineSucceedsText;
+ return this.mr.isMergeAllowed || this.isAutoMergeAvailable;
},
shouldShowSquashEdit() {
return this.squashBeforeMerge && this.shouldShowSquashBeforeMerge;
@@ -125,20 +118,15 @@ export default {
const { commitMessageWithDescription, commitMessage } = this.mr;
this.commitMessage = includeDescription ? commitMessageWithDescription : commitMessage;
},
- handleMergeButtonClick(mergeWhenBuildSucceeds, mergeImmediately) {
- // TODO: Remove no-param-reassign
- if (mergeWhenBuildSucceeds === undefined) {
- mergeWhenBuildSucceeds = this.mr.isPipelineActive; // eslint-disable-line no-param-reassign
- } else if (mergeImmediately) {
+ handleMergeButtonClick(useAutoMerge, mergeImmediately = false) {
+ if (mergeImmediately) {
this.isMergingImmediately = true;
}
- this.setToMergeWhenPipelineSucceeds = mergeWhenBuildSucceeds === true;
-
const options = {
sha: this.mr.sha,
commit_message: this.commitMessage,
- merge_when_pipeline_succeeds: this.setToMergeWhenPipelineSucceeds,
+ auto_merge_strategy: useAutoMerge ? this.mr.preferredAutoMergeStrategy : undefined,
should_remove_source_branch: this.removeSourceBranch === true,
squash: this.squashBeforeMerge,
squash_commit_message: this.squashCommitMessage,
@@ -151,7 +139,7 @@ export default {
.then(data => {
const hasError = data.status === 'failed' || data.status === 'hook_validation_error';
- if (data.status === 'merge_when_pipeline_succeeds') {
+ if (_.includes(AUTO_MERGE_STRATEGIES, data.status)) {
eventHub.$emit('MRWidgetUpdateRequested');
} else if (data.status === 'success') {
this.initiateMergePolling();
@@ -249,13 +237,13 @@ export default {
:class="mergeButtonClass"
type="button"
class="qa-merge-button"
- @click="handleMergeButtonClick()"
+ @click="handleMergeButtonClick(isAutoMergeAvailable)"
>
<i v-if="isMakingRequest" class="fa fa-spinner fa-spin" aria-hidden="true"></i>
{{ mergeButtonText }}
</button>
<button
- v-if="shouldShowMergeOptionsDropdown"
+ v-if="isAutoMergeAvailable"
:disabled="isMergeButtonDisabled"
type="button"
class="btn btn-sm btn-info dropdown-toggle js-merge-moment"
@@ -271,15 +259,13 @@ export default {
>
<li>
<a
- class="merge_when_pipeline_succeeds qa-merge-when-pipeline-succeeds-option"
+ class="auto_merge_enabled qa-merge-when-pipeline-succeeds-option"
href="#"
@click.prevent="handleMergeButtonClick(true)"
>
<span class="media">
<span class="merge-opt-icon" aria-hidden="true" v-html="successSvg"></span>
- <span class="media-body merge-opt-title">{{
- __('Merge when pipeline succeeds')
- }}</span>
+ <span class="media-body merge-opt-title">{{ autoMergeText }}</span>
</span>
</a>
</li>
@@ -337,6 +323,7 @@ export default {
:commits-count="mr.commitsCount"
:target-branch="mr.targetBranch"
:is-fast-forward-enabled="mr.ffOnlyEnabled"
+ :class="{ 'border-bottom': mr.mergeError }"
>
<ul class="border-top content-list commits-list flex-list">
<commit-edit
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
index b1f5655a15a..accb9d9fef1 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
@@ -29,8 +29,8 @@ export default {
</script>
<template>
- <div class="accept-control inline">
- <label class="merge-param-checkbox">
+ <div class="inline">
+ <label>
<input
:checked="value"
:disabled="isDisabled"
diff --git a/app/assets/javascripts/vue_merge_request_widget/constants.js b/app/assets/javascripts/vue_merge_request_widget/constants.js
index 0a29d55fbd6..3e65bdf0cb0 100644
--- a/app/assets/javascripts/vue_merge_request_widget/constants.js
+++ b/app/assets/javascripts/vue_merge_request_widget/constants.js
@@ -3,3 +3,13 @@ export const DANGER = 'danger';
export const WARNING_MESSAGE_CLASS = 'warning_message';
export const DANGER_MESSAGE_CLASS = 'danger_message';
+
+export const MWPS_MERGE_STRATEGY = 'merge_when_pipeline_succeeds';
+export const ATMTWPS_MERGE_STRATEGY = 'add_to_merge_train_when_pipeline_succeeds';
+export const MT_MERGE_STRATEGY = 'merge_train';
+
+export const AUTO_MERGE_STRATEGIES = [
+ MWPS_MERGE_STRATEGY,
+ ATMTWPS_MERGE_STRATEGY,
+ MT_MERGE_STRATEGY,
+];
diff --git a/app/assets/javascripts/vue_merge_request_widget/mixins/auto_merge.js b/app/assets/javascripts/vue_merge_request_widget/mixins/auto_merge.js
new file mode 100644
index 00000000000..23e140623cc
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/mixins/auto_merge.js
@@ -0,0 +1,15 @@
+import { s__ } from '~/locale';
+
+export default {
+ computed: {
+ statusTextBeforeAuthor() {
+ return s__('mrWidget|Set by');
+ },
+ statusTextAfterAuthor() {
+ return s__('mrWidget|to be merged automatically when the pipeline succeeds');
+ },
+ cancelButtonText() {
+ return s__('mrWidget|Cancel automatic merge');
+ },
+ },
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
new file mode 100644
index 00000000000..116d537c463
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
@@ -0,0 +1,19 @@
+import { __ } from '~/locale';
+
+export default {
+ computed: {
+ isMergeButtonDisabled() {
+ const { commitMessage } = this;
+ return Boolean(
+ !commitMessage.length ||
+ !this.shouldShowMergeControls ||
+ this.isMakingRequest ||
+ this.mr.preventMerge,
+ );
+ },
+ autoMergeText() {
+ // MWPS is currently the only auto merge strategy available in CE
+ return __('Merge when pipeline succeeds');
+ },
+ },
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index aa4ecb0aac3..41386178a1e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -1,6 +1,6 @@
<script>
import _ from 'underscore';
-import { __ } from '~/locale';
+import { sprintf, s__, __ } from '~/locale';
import Project from '~/pages/projects/project';
import SmartInterval from '~/smart_interval';
import MRWidgetStore from 'ee_else_ce/vue_merge_request_widget/stores/mr_widget_store';
@@ -29,7 +29,7 @@ import UnresolvedDiscussionsState from './components/states/unresolved_discussio
import PipelineBlockedState from './components/states/mr_widget_pipeline_blocked.vue';
import PipelineFailedState from './components/states/pipeline_failed.vue';
import FailedToMerge from './components/states/mr_widget_failed_to_merge.vue';
-import MergeWhenPipelineSucceedsState from './components/states/mr_widget_merge_when_pipeline_succeeds.vue';
+import MrWidgetAutoMergeEnabled from './components/states/mr_widget_auto_merge_enabled.vue';
import AutoMergeFailed from './components/states/mr_widget_auto_merge_failed.vue';
import CheckingState from './components/states/mr_widget_checking.vue';
import eventHub from './event_hub';
@@ -64,7 +64,7 @@ export default {
'mr-widget-unresolved-discussions': UnresolvedDiscussionsState,
'mr-widget-pipeline-blocked': PipelineBlockedState,
'mr-widget-pipeline-failed': PipelineFailedState,
- 'mr-widget-merge-when-pipeline-succeeds': MergeWhenPipelineSucceedsState,
+ MrWidgetAutoMergeEnabled,
'mr-widget-auto-merge-failed': AutoMergeFailed,
'mr-widget-rebase': RebaseState,
SourceBranchRemovalStatus,
@@ -97,7 +97,7 @@ export default {
return this.mr.hasCI;
},
shouldRenderRelatedLinks() {
- return !!this.mr.relatedLinks && !this.mr.isNothingToMergeState;
+ return Boolean(this.mr.relatedLinks) && !this.mr.isNothingToMergeState;
},
shouldRenderSourceBranchRemovalStatus() {
return (
@@ -117,12 +117,10 @@ export default {
this.mr.mergePipelinesEnabled && this.mr.sourceProjectId !== this.mr.targetProjectId,
);
},
- showTargetBranchAdvancedError() {
- return Boolean(
- this.mr.pipeline &&
- this.mr.pipeline.target_sha &&
- this.mr.pipeline.target_sha !== this.mr.targetBranchSha,
- );
+ mergeError() {
+ return sprintf(s__('mrWidget|Merge failed: %{mergeError}. Please try again.'), {
+ mergeError: this.mr.mergeError,
+ });
},
},
watch: {
@@ -332,41 +330,37 @@ export default {
<div class="mr-widget-section">
<component :is="componentName" :mr="mr" :service="service" />
- <section v-if="shouldRenderCollaborationStatus" class="mr-info-list mr-links">
- {{ s__('mrWidget|Allows commits from members who can merge to the target branch') }}
- </section>
+ <div class="mr-widget-info">
+ <section v-if="shouldRenderCollaborationStatus" class="mr-info-list mr-links">
+ <p>
+ {{ s__('mrWidget|Allows commits from members who can merge to the target branch') }}
+ </p>
+ </section>
- <mr-widget-related-links
- v-if="shouldRenderRelatedLinks"
- :state="mr.state"
- :related-links="mr.relatedLinks"
- />
+ <mr-widget-related-links
+ v-if="shouldRenderRelatedLinks"
+ :state="mr.state"
+ :related-links="mr.relatedLinks"
+ />
- <mr-widget-alert-message
- v-if="showMergePipelineForkWarning"
- type="warning"
- :help-path="mr.mergeRequestPipelinesHelpPath"
- >
- {{
- s__(
- 'mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result',
- )
- }}
- </mr-widget-alert-message>
+ <mr-widget-alert-message
+ v-if="showMergePipelineForkWarning"
+ type="warning"
+ :help-path="mr.mergeRequestPipelinesHelpPath"
+ >
+ {{
+ s__(
+ 'mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result',
+ )
+ }}
+ </mr-widget-alert-message>
- <mr-widget-alert-message
- v-if="showTargetBranchAdvancedError"
- type="danger"
- :help-path="mr.mergeRequestPipelinesHelpPath"
- >
- {{
- s__(
- 'mrWidget|The target branch has advanced, which invalidates the merge request pipeline. Please update the source branch and retry merging',
- )
- }}
- </mr-widget-alert-message>
+ <mr-widget-alert-message v-if="mr.mergeError" type="danger">
+ {{ mergeError }}
+ </mr-widget-alert-message>
- <source-branch-removal-status v-if="shouldRenderSourceBranchRemovalStatus" />
+ <source-branch-removal-status v-if="shouldRenderSourceBranchRemovalStatus" />
+ </div>
</div>
<div v-if="shouldRenderMergeHelp" class="mr-widget-footer"><mr-widget-merge-help /></div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js b/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
index 0cc4fd59f5e..3ab229567f6 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
@@ -23,8 +23,8 @@ export default function deviseState(data) {
return stateKey.pipelineBlocked;
} else if (this.isSHAMismatch) {
return stateKey.shaMismatch;
- } else if (this.mergeWhenPipelineSucceeds) {
- return this.mergeError ? stateKey.autoMergeFailed : stateKey.mergeWhenPipelineSucceeds;
+ } else if (this.autoMergeEnabled) {
+ return this.mergeError ? stateKey.autoMergeFailed : stateKey.autoMergeEnabled;
} else if (!this.canMerge) {
return stateKey.notAllowedToMerge;
} else if (this.canBeMerged) {
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
index 45708d78886..bfa3e7f4a59 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
@@ -1,7 +1,9 @@
import Timeago from 'timeago.js';
+import _ from 'underscore';
import getStateKey from 'ee_else_ce/vue_merge_request_widget/stores/get_state_key';
import { stateKey } from './state_maps';
import { formatDate } from '../../lib/utils/datetime_utility';
+import { ATMTWPS_MERGE_STRATEGY, MT_MERGE_STRATEGY, MWPS_MERGE_STRATEGY } from '../constants';
export default class MergeRequestStore {
constructor(data) {
@@ -61,7 +63,7 @@ export default class MergeRequestStore {
this.updatedAt = data.updated_at;
this.metrics = MergeRequestStore.buildMetrics(data.metrics);
- this.setToMWPSBy = MergeRequestStore.formatUserObject(data.merge_user || {});
+ this.setToAutoMergeBy = MergeRequestStore.formatUserObject(data.merge_user || {});
this.mergeUserId = data.merge_user_id;
this.currentUserId = gon.current_user_id;
this.sourceBranchPath = data.source_branch_path;
@@ -70,15 +72,20 @@ export default class MergeRequestStore {
this.targetBranchPath = data.target_branch_commits_path;
this.targetBranchTreePath = data.target_branch_tree_path;
this.conflictResolutionPath = data.conflict_resolution_path;
- this.cancelAutoMergePath = data.cancel_merge_when_pipeline_succeeds_path;
+ this.cancelAutoMergePath = data.cancel_auto_merge_path;
this.removeWIPPath = data.remove_wip_path;
this.sourceBranchRemoved = !data.source_branch_exists;
this.shouldRemoveSourceBranch = data.remove_source_branch || false;
this.onlyAllowMergeIfPipelineSucceeds = data.only_allow_merge_if_pipeline_succeeds || false;
- this.mergeWhenPipelineSucceeds = data.merge_when_pipeline_succeeds || false;
+ this.autoMergeEnabled = Boolean(data.auto_merge_enabled);
+ this.autoMergeStrategy = data.auto_merge_strategy;
+ this.availableAutoMergeStrategies = data.available_auto_merge_strategies;
+ this.preferredAutoMergeStrategy = MergeRequestStore.getPreferredAutoMergeStrategy(
+ this.availableAutoMergeStrategies,
+ );
this.mergePath = data.merge_path;
this.ffOnlyEnabled = data.ff_only_enabled;
- this.shouldBeRebased = !!data.should_be_rebased;
+ this.shouldBeRebased = Boolean(data.should_be_rebased);
this.statusPath = data.status_path;
this.emailPatchesPath = data.email_patches_path;
this.plainDiffPath = data.plain_diff_path;
@@ -91,9 +98,9 @@ export default class MergeRequestStore {
this.isOpen = data.state === 'opened';
this.hasMergeableDiscussionsState = data.mergeable_discussions_state === false;
this.canRemoveSourceBranch = currentUser.can_remove_source_branch || false;
- this.canMerge = !!data.merge_path;
+ this.canMerge = Boolean(data.merge_path);
this.canCreateIssue = currentUser.can_create_issue || false;
- this.canCancelAutomaticMerge = !!data.cancel_merge_when_pipeline_succeeds_path;
+ this.canCancelAutomaticMerge = Boolean(data.cancel_auto_merge_path);
this.isSHAMismatch = this.sha !== data.diff_head_sha;
this.canBeMerged = data.can_be_merged || false;
this.isMergeAllowed = data.mergeable || false;
@@ -103,7 +110,9 @@ export default class MergeRequestStore {
this.sourceProjectFullPath = data.source_project_full_path;
this.sourceProjectId = data.source_project_id;
this.targetProjectId = data.target_project_id;
- this.mergePipelinesEnabled = data.merge_pipelines_enabled;
+ this.mergePipelinesEnabled = Boolean(data.merge_pipelines_enabled);
+ this.mergeTrainsCount = data.merge_trains_count || 0;
+ this.mergeTrainIndex = data.merge_train_index;
// Cherry-pick and Revert actions related
this.canCherryPickInCurrentMR = currentUser.can_cherry_pick_on_current_merge_request || false;
@@ -203,4 +212,16 @@ export default class MergeRequestStore {
return timeagoInstance.format(date);
}
+
+ static getPreferredAutoMergeStrategy(availableAutoMergeStrategies) {
+ if (_.includes(availableAutoMergeStrategies, ATMTWPS_MERGE_STRATEGY)) {
+ return ATMTWPS_MERGE_STRATEGY;
+ } else if (_.includes(availableAutoMergeStrategies, MT_MERGE_STRATEGY)) {
+ return MT_MERGE_STRATEGY;
+ } else if (_.includes(availableAutoMergeStrategies, MWPS_MERGE_STRATEGY)) {
+ return MWPS_MERGE_STRATEGY;
+ }
+
+ return undefined;
+ }
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js b/app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js
index e080ce5c229..28507bba3e5 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js
@@ -13,7 +13,7 @@ const stateToComponentMap = {
unresolvedDiscussions: 'mr-widget-unresolved-discussions',
pipelineBlocked: 'mr-widget-pipeline-blocked',
pipelineFailed: 'mr-widget-pipeline-failed',
- mergeWhenPipelineSucceeds: 'mr-widget-merge-when-pipeline-succeeds',
+ autoMergeEnabled: 'mr-widget-auto-merge-enabled',
failedToMerge: 'mr-widget-failed-to-merge',
autoMergeFailed: 'mr-widget-auto-merge-failed',
shaMismatch: 'sha-mismatch',
@@ -45,7 +45,7 @@ export const stateKey = {
pipelineBlocked: 'pipelineBlocked',
shaMismatch: 'shaMismatch',
autoMergeFailed: 'autoMergeFailed',
- mergeWhenPipelineSucceeds: 'mergeWhenPipelineSucceeds',
+ autoMergeEnabled: 'autoMergeEnabled',
notAllowedToMerge: 'notAllowedToMerge',
readyToMerge: 'readyToMerge',
rebase: 'rebase',
diff --git a/app/assets/javascripts/vue_shared/components/ci_pipeline_link.vue b/app/assets/javascripts/vue_shared/components/ci_pipeline_link.vue
new file mode 100644
index 00000000000..eae4c06467c
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/ci_pipeline_link.vue
@@ -0,0 +1,32 @@
+<script>
+import { GlLink, GlTooltipDirective } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlLink,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ href: {
+ type: String,
+ required: true,
+ },
+ pipelineId: {
+ type: Number,
+ required: true,
+ },
+ pipelineIid: {
+ type: Number,
+ required: true,
+ },
+ },
+};
+</script>
+<template>
+ <gl-link v-gl-tooltip :href="href" :title="__('Pipeline ID (IID)')">
+ <span class="pipeline-id">#{{ pipelineId }}</span>
+ <span class="pipeline-iid">(#{{ pipelineIid }})</span>
+ </gl-link>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/clipboard_button.vue b/app/assets/javascripts/vue_shared/components/clipboard_button.vue
index 671b4909839..a620f560b52 100644
--- a/app/assets/javascripts/vue_shared/components/clipboard_button.vue
+++ b/app/assets/javascripts/vue_shared/components/clipboard_button.vue
@@ -7,7 +7,7 @@
*
* @example
* <clipboard-button
- * title="Copy to clipbard"
+ * title="Copy to clipboard"
* text="Content to be copied"
* css-class="btn-transparent"
* />
diff --git a/app/assets/javascripts/vue_shared/components/commit.vue b/app/assets/javascripts/vue_shared/components/commit.vue
index 944b9c0c083..a1168fa0f1e 100644
--- a/app/assets/javascripts/vue_shared/components/commit.vue
+++ b/app/assets/javascripts/vue_shared/components/commit.vue
@@ -1,6 +1,7 @@
<script>
import _ from 'underscore';
import { GlTooltipDirective, GlLink } from '@gitlab/ui';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import UserAvatarLink from './user_avatar/user_avatar_link.vue';
import Icon from '../../vue_shared/components/icon.vue';
@@ -12,6 +13,7 @@ export default {
UserAvatarLink,
Icon,
GlLink,
+ TooltipOnTruncate,
},
props: {
/**
@@ -133,7 +135,7 @@ export default {
};
</script>
<template>
- <div class="branch-commit">
+ <div class="branch-commit cgray">
<template v-if="shouldShowRefInfo">
<div class="icon-container">
<icon v-if="tag" name="tag" />
@@ -165,7 +167,7 @@ export default {
<gl-link :href="commitUrl" class="commit-sha mr-0"> {{ shortSha }} </gl-link>
<div class="commit-title flex-truncate-parent">
- <span v-if="title" class="flex-truncate-child">
+ <tooltip-on-truncate v-if="title" class="flex-truncate-child" :title="title">
<user-avatar-link
v-if="hasAuthor"
:link-href="author.path"
@@ -174,8 +176,10 @@ export default {
:tooltip-text="author.username"
class="avatar-image-container"
/>
- <gl-link :href="commitUrl" class="commit-row-message"> {{ title }} </gl-link>
- </span>
+ <gl-link :href="commitUrl" class="commit-row-message cgray">
+ {{ title }}
+ </gl-link>
+ </tooltip-on-truncate>
<span v-else> Can't find HEAD commit for this branch </span>
</div>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue
index 4155e1bab9c..1e6f4c376c1 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue
@@ -1,5 +1,4 @@
<script>
-import { viewerInformationForPath } from './lib/viewer_utils';
import MarkdownViewer from './viewers/markdown_viewer.vue';
import ImageViewer from './viewers/image_viewer.vue';
import DownloadViewer from './viewers/download_viewer.vue';
@@ -24,15 +23,18 @@ export default {
required: false,
default: '',
},
+ type: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
computed: {
viewer() {
if (!this.path) return null;
+ if (!this.type) return DownloadViewer;
- const previewInfo = viewerInformationForPath(this.path);
- if (!previewInfo) return DownloadViewer;
-
- switch (previewInfo.id) {
+ switch (this.type) {
case 'markdown':
return MarkdownViewer;
case 'image':
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/lib/viewer_utils.js b/app/assets/javascripts/vue_shared/components/content_viewer/lib/viewer_utils.js
index f01a51da0b3..ba63683f5c0 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/lib/viewer_utils.js
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/lib/viewer_utils.js
@@ -1,10 +1,12 @@
+import { __ } from '~/locale';
+
const viewers = {
image: {
id: 'image',
},
markdown: {
id: 'markdown',
- previewTitle: 'Preview Markdown',
+ previewTitle: __('Preview Markdown'),
},
};
diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue
index ad3b3b81ac5..8d77b156aa4 100644
--- a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue
@@ -58,12 +58,11 @@ export default {
const moveX = e.pageX || e.touches[0].pageX;
let leftValue = moveX - this.$refs.swipeFrame.getBoundingClientRect().left;
- const spaceLeft = 20;
const { clientWidth } = this.$refs.swipeFrame;
if (leftValue <= 0) {
leftValue = 0;
- } else if (leftValue > clientWidth - spaceLeft) {
- leftValue = clientWidth - spaceLeft;
+ } else if (leftValue > clientWidth) {
+ leftValue = clientWidth;
}
this.swipeWrapWidth = (leftValue / clientWidth) * 100;
@@ -80,7 +79,7 @@ export default {
document.body.removeEventListener('touchmove', this.dragMove);
},
prepareSwipe() {
- if (this.swipeOldImgInfo && this.swipeNewImgInfo) {
+ if (this.swipeOldImgInfo && this.swipeNewImgInfo && this.swipeOldImgInfo.renderedWidth > 0) {
// Add 2 for border width
this.swipeMaxWidth =
Math.max(this.swipeOldImgInfo.renderedWidth, this.swipeNewImgInfo.renderedWidth) + 2;
@@ -101,6 +100,8 @@ export default {
},
resize: _.throttle(function throttledResize() {
this.swipeBarPos = 0;
+ this.swipeWrapWidth = 0;
+ this.prepareSwipe();
}, 400),
},
};
@@ -111,6 +112,8 @@ export default {
<div
ref="swipeFrame"
:style="{
+ width: swipeMaxPixelWidth,
+ height: swipeMaxPixelHeight,
'user-select': dragging ? 'none' : null,
}"
class="swipe-frame"
diff --git a/app/assets/javascripts/vue_shared/components/droplab_dropdown_button.vue b/app/assets/javascripts/vue_shared/components/droplab_dropdown_button.vue
new file mode 100644
index 00000000000..7d49c87271d
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/droplab_dropdown_button.vue
@@ -0,0 +1,89 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import Icon from './icon.vue';
+
+export default {
+ components: {
+ Icon,
+ GlButton,
+ },
+ props: {
+ size: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ primaryButtonClass: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ dropdownClass: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ actions: {
+ type: Array,
+ required: true,
+ },
+ defaultAction: {
+ type: Number,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ selectedAction: this.defaultAction,
+ };
+ },
+ computed: {
+ selectedActionTitle() {
+ return this.actions[this.selectedAction].title;
+ },
+ buttonSizeClass() {
+ return `btn-${this.size}`;
+ },
+ },
+ methods: {
+ handlePrimaryActionClick() {
+ this.$emit('onActionClick', this.actions[this.selectedAction]);
+ },
+ handleActionClick(selectedAction) {
+ this.selectedAction = selectedAction;
+ this.$emit('onActionSelect', selectedAction);
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="btn-group droplab-dropdown comment-type-dropdown">
+ <gl-button :class="primaryButtonClass" :size="size" @click.prevent="handlePrimaryActionClick">
+ {{ selectedActionTitle }}
+ </gl-button>
+ <button
+ :class="buttonSizeClass"
+ type="button"
+ class="btn dropdown-toggle pl-2 pr-2"
+ data-display="static"
+ data-toggle="dropdown"
+ >
+ <icon name="arrow-down" aria-label="toggle dropdown" />
+ </button>
+ <ul :class="dropdownClass" class="dropdown-menu dropdown-open-top">
+ <template v-for="(action, index) in actions">
+ <li :key="index" :class="{ 'droplab-item-selected': selectedAction === index }">
+ <gl-button class="btn-transparent" @click.prevent="handleActionClick(index)">
+ <i aria-hidden="true" class="fa fa-check icon"> </i>
+ <div class="description">
+ <strong>{{ action.title }}</strong>
+ <p>{{ action.description }}</p>
+ </div>
+ </gl-button>
+ </li>
+ <li v-if="index === 0" :key="`${index}-separator`" class="divider droplab-item-ignore"></li>
+ </template>
+ </ul>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/header_ci_component.vue b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
index 3f45dc7853b..0bac63b1062 100644
--- a/app/assets/javascripts/vue_shared/components/header_ci_component.vue
+++ b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
@@ -37,6 +37,16 @@ export default {
type: Number,
required: true,
},
+ itemIid: {
+ type: Number,
+ required: false,
+ default: null,
+ },
+ itemIdTooltip: {
+ type: String,
+ required: false,
+ default: '',
+ },
time: {
type: String,
required: true,
@@ -85,7 +95,12 @@ export default {
<section class="header-main-content">
<ci-icon-badge :status="status" />
- <strong> {{ itemName }} #{{ itemId }} </strong>
+ <strong v-gl-tooltip :title="itemIdTooltip">
+ {{ itemName }} #{{ itemId }}
+ <template v-if="itemIid"
+ >(#{{ itemIid }})</template
+ >
+ </strong>
<template v-if="shouldRenderTriggeredLabel">
triggered
@@ -96,9 +111,8 @@ export default {
<timeago-tooltip :time="time" />
- by
-
<template v-if="user">
+ by
<gl-link
v-gl-tooltip
:href="user.path"
diff --git a/app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue b/app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue
index 7e79e63aa1e..715cf97f0ac 100644
--- a/app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue
+++ b/app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue
@@ -62,6 +62,15 @@ export default {
assigneeName: assignee.name,
});
},
+ // This method is for backward compat
+ // since Graph query would return camelCase
+ // props while Rails would return snake_case
+ webUrl(assignee) {
+ return assignee.web_url || assignee.webUrl;
+ },
+ avatarUrl(assignee) {
+ return assignee.avatar_url || assignee.avatarUrl;
+ },
},
};
</script>
@@ -70,9 +79,9 @@ export default {
<user-avatar-link
v-for="assignee in assigneesToShow"
:key="assignee.id"
- :link-href="assignee.web_url"
+ :link-href="webUrl(assignee)"
:img-alt="avatarUrlTitle(assignee)"
- :img-src="assignee.avatar_url"
+ :img-src="avatarUrl(assignee)"
:img-size="24"
class="js-no-trigger"
tooltip-placement="bottom"
diff --git a/app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue b/app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue
index d5d967e25bf..9b2ee5062b1 100644
--- a/app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue
+++ b/app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue
@@ -17,15 +17,17 @@ export default {
required: true,
},
},
- data() {
- return {
- milestoneDue: this.milestone.due_date ? parsePikadayDate(this.milestone.due_date) : null,
- milestoneStart: this.milestone.start_date
- ? parsePikadayDate(this.milestone.start_date)
- : null,
- };
- },
computed: {
+ milestoneDue() {
+ const dueDate = this.milestone.due_date || this.milestone.dueDate;
+
+ return dueDate ? parsePikadayDate(dueDate) : null;
+ },
+ milestoneStart() {
+ const startDate = this.milestone.start_date || this.milestone.startDate;
+
+ return startDate ? parsePikadayDate(startDate) : null;
+ },
isMilestoneStarted() {
if (!this.milestoneStart) {
return false;
@@ -72,7 +74,7 @@ export default {
<template>
<div ref="milestoneDetails" class="issue-milestone-details">
<icon :size="16" class="inline icon" name="clock" />
- <span class="milestone-title">{{ milestone.title }}</span>
+ <span class="milestone-title d-inline-block">{{ milestone.title }}</span>
<gl-tooltip :target="() => $refs.milestoneDetails" placement="bottom" class="js-item-milestone">
<span class="bold">{{ __('Milestone') }}</span> <br />
<span>{{ milestone.title }}</span> <br />
diff --git a/app/assets/javascripts/vue_shared/components/issue/issue_warning.vue b/app/assets/javascripts/vue_shared/components/issue/issue_warning.vue
index e92babc499b..e438ff16a41 100644
--- a/app/assets/javascripts/vue_shared/components/issue/issue_warning.vue
+++ b/app/assets/javascripts/vue_shared/components/issue/issue_warning.vue
@@ -1,9 +1,17 @@
<script>
+import { GlLink } from '@gitlab/ui';
+import _ from 'underscore';
+import { sprintf } from '~/locale';
import icon from '../../../vue_shared/components/icon.vue';
+function buildDocsLinkStart(path) {
+ return `<a href="${_.escape(path)}" target="_blank" rel="noopener noreferrer">`;
+}
+
export default {
components: {
icon,
+ GlLink,
},
props: {
isLocked: {
@@ -16,6 +24,16 @@ export default {
default: false,
required: false,
},
+ lockedIssueDocsPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ confidentialIssueDocsPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
computed: {
warningIcon() {
@@ -27,6 +45,17 @@ export default {
isLockedAndConfidential() {
return this.isConfidential && this.isLocked;
},
+ confidentialAndLockedDiscussionText() {
+ return sprintf(
+ 'This issue is %{confidentialLinkStart}confidential%{linkEnd} and %{lockedLinkStart}locked%{linkEnd}.',
+ {
+ confidentialLinkStart: buildDocsLinkStart(this.confidentialIssueDocsPath),
+ lockedLinkStart: buildDocsLinkStart(this.lockedIssueDocsPath),
+ linkEnd: '</a>',
+ },
+ false,
+ );
+ },
},
};
</script>
@@ -35,20 +64,26 @@ export default {
<icon v-if="!isLockedAndConfidential" :name="warningIcon" :size="16" class="icon inline" />
<span v-if="isLockedAndConfidential">
- {{ __('This issue is confidential and locked.') }}
+ <span v-html="confidentialAndLockedDiscussionText"></span>
{{
- __(`People without permission will never
-get a notification and won't be able to comment.`)
+ __(`People without permission will never get a notification and won't be able to comment.`)
}}
</span>
<span v-else-if="isConfidential">
{{ __('This is a confidential issue.') }}
- {{ __('Your comment will not be visible to the public.') }}
+ {{ __('People without permission will never get a notification.') }}
+ <gl-link :href="confidentialIssueDocsPath" target="_blank">
+ {{ __('Learn more') }}
+ </gl-link>
</span>
<span v-else-if="isLocked">
- {{ __('This issue is locked.') }} {{ __('Only project members can comment.') }}
+ {{ __('This issue is locked.') }}
+ {{ __('Only project members can comment.') }}
+ <gl-link :href="lockedIssueDocsPath" target="_blank">
+ {{ __('Learn more') }}
+ </gl-link>
</span>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue b/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue
index d4d18614f93..05ad7710a62 100644
--- a/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue
+++ b/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue
@@ -1,4 +1,5 @@
<script>
+import '~/commons/bootstrap';
import { GlTooltipDirective } from '@gitlab/ui';
import { sprintf } from '~/locale';
import IssueMilestone from '../../components/issue/issue_milestone.vue';
@@ -23,6 +24,11 @@ export default {
required: false,
default: false,
},
+ greyLinkWhenMerged: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
stateTitle() {
@@ -35,6 +41,11 @@ export default {
},
);
},
+ issueableLinkClass() {
+ return this.greyLinkWhenMerged
+ ? `sortable-link ${this.state === 'merged' ? ' text-secondary' : ''}`
+ : 'sortable-link';
+ },
},
};
</script>
@@ -45,10 +56,10 @@ export default {
'issuable-info-container': !canReorder,
'card-body': canReorder,
}"
- class="item-body"
+ class="item-body d-flex align-items-center p-2 p-lg-3 p-xl-2 pl-xl-3"
>
- <div class="item-contents">
- <div class="item-title d-flex align-items-center">
+ <div class="item-contents d-flex align-items-center flex-wrap flex-grow-1 flex-xl-nowrap">
+ <div class="item-title d-flex align-items-center mb-1 mb-xl-0">
<icon
v-if="hasState"
v-tooltip
@@ -65,13 +76,15 @@ export default {
name="eye-slash"
:size="16"
:title="__('Confidential')"
- class="confidential-icon append-right-4"
+ class="confidential-icon append-right-4 align-self-baseline align-self-md-auto mt-xl-0"
:aria-label="__('Confidential')"
/>
- <a :href="computedPath" class="sortable-link">{{ title }}</a>
+ <a :href="computedPath" :class="issueableLinkClass">{{ title }}</a>
</div>
- <div class="item-meta">
- <div class="d-flex align-items-center item-path-id">
+ <div class="item-meta d-flex flex-wrap mt-xl-0 justify-content-xl-end flex-xl-nowrap">
+ <div
+ class="d-flex align-items-center item-path-id order-md-0 mt-md-0 mt-1 ml-xl-2 mr-xl-auto"
+ >
<icon
v-if="hasState"
v-tooltip
@@ -81,11 +94,16 @@ export default {
:title="stateTitle"
:aria-label="state"
data-html="true"
+ class="d-xl-none"
/>
- <span v-tooltip :title="itemPath" class="path-id-text">{{ itemPath }}</span>
+ <span v-tooltip :title="itemPath" class="path-id-text d-inline-block">{{
+ itemPath
+ }}</span>
{{ pathIdSeparator }}{{ itemId }}
</div>
- <div class="item-meta-child d-flex align-items-center">
+ <div
+ class="item-meta-child d-flex align-items-center order-0 flex-wrap mr-md-1 ml-md-auto ml-xl-2 flex-xl-nowrap"
+ >
<span v-if="hasPipeline" class="mr-ci-status pr-2">
<a :href="pipelineStatus.details_path">
<ci-icon v-gl-tooltip :status="pipelineStatus" :title="pipelineStatusTooltip" />
@@ -102,7 +120,7 @@ export default {
<issue-assignees
v-if="assignees.length"
:assignees="assignees"
- class="item-assignees d-inline-flex"
+ class="item-assignees d-inline-flex align-items-center align-self-end ml-auto ml-md-0 mb-md-0 order-2 flex-xl-grow-0 mt-xl-0 mr-xl-1"
/>
</div>
</div>
@@ -112,7 +130,7 @@ export default {
v-tooltip
:disabled="removeDisabled"
type="button"
- class="btn btn-default btn-svg btn-item-remove js-issue-item-remove-button qa-remove-issue-button"
+ class="btn btn-default btn-svg btn-item-remove js-issue-item-remove-button qa-remove-issue-button mr-xl-0 align-self-xl-center"
title="Remove"
aria-label="Remove"
@click="onRemoveRequest"
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
index c5a2aa1f2af..32783b85df4 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
@@ -1,8 +1,10 @@
<script>
import Icon from '~/vue_shared/components/icon.vue';
+import { GlButton, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
export default {
- components: { Icon },
+ components: { Icon, GlButton, GlLoadingIcon },
+ directives: { 'gl-tooltip': GlTooltipDirective },
props: {
canApply: {
type: Boolean,
@@ -21,7 +23,6 @@ export default {
},
data() {
return {
- isAppliedSuccessfully: false,
isApplying: false,
};
},
@@ -47,14 +48,19 @@ export default {
</a>
</div>
<span v-if="isApplied" class="badge badge-success">{{ __('Applied') }}</span>
- <button
- v-if="canApply"
- type="button"
- class="btn qa-apply-btn"
+ <div v-if="isApplying" class="d-flex align-items-center text-secondary">
+ <gl-loading-icon class="d-flex-center mr-2" />
+ <span>{{ __('Applying suggestion') }}</span>
+ </div>
+ <gl-button
+ v-else-if="canApply"
+ v-gl-tooltip.viewport="__('This also resolves the discussion')"
+ class="btn-inverted qa-apply-btn"
:disabled="isApplying"
+ variant="success"
@click="applySuggestion"
>
{{ __('Apply suggestion') }}
- </button>
+ </gl-button>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue
index cafd3a515ea..c09bdfec250 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue
@@ -17,10 +17,10 @@ export default {
<template>
<tr class="line_holder" :class="lineType">
- <td class="diff-line-num old_line" :class="lineType">
+ <td class="diff-line-num old_line border-top-0 border-bottom-0" :class="lineType">
{{ line.old_line }}
</td>
- <td class="diff-line-num new_line" :class="lineType">
+ <td class="diff-line-num new_line border-top-0 border-bottom-0" :class="lineType">
{{ line.new_line }}
</td>
<td class="line_content" :class="lineType">
diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
index 3b57b5e8da4..d6c398c8946 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
@@ -33,37 +33,36 @@ export default {
<div class="comment-toolbar clearfix">
<div class="toolbar-text">
<template v-if="!hasQuickActionsDocsPath && markdownDocsPath">
- <gl-link :href="markdownDocsPath" target="_blank" tabindex="-1">
- Markdown is supported
- </gl-link>
+ <gl-link :href="markdownDocsPath" target="_blank" tabindex="-1"
+ >Markdown is supported</gl-link
+ >
</template>
<template v-if="hasQuickActionsDocsPath && markdownDocsPath">
- <gl-link :href="markdownDocsPath" target="_blank" tabindex="-1"> Markdown </gl-link>
- and
- <gl-link :href="quickActionsDocsPath" target="_blank" tabindex="-1">
- quick actions
- </gl-link>
+ <gl-link :href="markdownDocsPath" target="_blank" tabindex="-1">Markdown</gl-link> and
+ <gl-link :href="quickActionsDocsPath" target="_blank" tabindex="-1">quick actions</gl-link>
are supported
</template>
</div>
<span v-if="canAttachFile" class="uploading-container">
<span class="uploading-progress-container hide">
- <i class="fa fa-file-image-o toolbar-button-icon" aria-hidden="true"> </i>
- <span class="attaching-file-message"></span> <span class="uploading-progress">0%</span>
+ <i class="fa fa-file-image-o toolbar-button-icon" aria-hidden="true"></i>
+ <span class="attaching-file-message"></span>
+ <span class="uploading-progress">0%</span>
<span class="uploading-spinner">
- <i class="fa fa-spinner fa-spin toolbar-button-icon" aria-hidden="true"> </i>
+ <i class="fa fa-spinner fa-spin toolbar-button-icon" aria-hidden="true"></i>
</span>
</span>
<span class="uploading-error-container hide">
<span class="uploading-error-icon">
- <i class="fa fa-file-image-o toolbar-button-icon" aria-hidden="true"> </i>
+ <i class="fa fa-file-image-o toolbar-button-icon" aria-hidden="true"></i>
</span>
<span class="uploading-error-message"></span>
<button class="retry-uploading-link" type="button">Try again</button> or
<button class="attach-new-file markdown-selector" type="button">attach a new file</button>
</span>
- <button class="markdown-selector button-attach-file" tabindex="-1" type="button">
- <i class="fa fa-file-image-o toolbar-button-icon" aria-hidden="true"> </i> Attach a file
+ <button class="markdown-selector button-attach-file btn-link" tabindex="-1" type="button">
+ <i class="fa fa-file-image-o toolbar-button-icon" aria-hidden="true"></i
+ ><span class="text-attach-file">Attach a file</span>
</button>
<button class="btn btn-default btn-sm hide button-cancel-uploading-files" type="button">
Cancel
diff --git a/app/assets/javascripts/vue_shared/components/modal_copy_button.vue b/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
new file mode 100644
index 00000000000..bf59a6abf3f
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
@@ -0,0 +1,121 @@
+<script>
+import $ from 'jquery';
+import { GlButton, GlTooltipDirective } from '@gitlab/ui';
+import { __ } from '~/locale';
+import Icon from '~/vue_shared/components/icon.vue';
+import Clipboard from 'clipboard';
+
+export default {
+ components: {
+ GlButton,
+ Icon,
+ },
+
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+
+ props: {
+ text: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ container: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ modalId: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ target: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ title: {
+ type: String,
+ required: true,
+ },
+ tooltipPlacement: {
+ type: String,
+ required: false,
+ default: 'top',
+ },
+ tooltipContainer: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+
+ copySuccessText: __('Copied'),
+
+ computed: {
+ modalDomId() {
+ return this.modalId ? `#${this.modalId}` : '';
+ },
+ },
+
+ mounted() {
+ this.$nextTick(() => {
+ this.clipboard = new Clipboard(this.$el, {
+ container:
+ document.querySelector(`${this.modalDomId} div.modal-content`) ||
+ document.getElementById(this.container) ||
+ document.body,
+ });
+ this.clipboard
+ .on('success', e => {
+ this.updateTooltip(e.trigger);
+ this.$emit('success', e);
+ // Clear the selection and blur the trigger so it loses its border
+ e.clearSelection();
+ $(e.trigger).blur();
+ })
+ .on('error', e => this.$emit('error', e));
+ });
+ },
+
+ destroyed() {
+ if (this.clipboard) {
+ this.clipboard.destroy();
+ }
+ },
+
+ methods: {
+ updateTooltip(target) {
+ const $target = $(target);
+ const originalTitle = $target.data('originalTitle');
+
+ if ($target.tooltip) {
+ /**
+ * The original tooltip will continue staying there unless we remove it by hand.
+ * $target.tooltip('hide') isn't working.
+ */
+ $('.tooltip').remove();
+ $target.attr('title', this.$options.copySuccessText);
+ $target.tooltip('_fixTitle');
+ $target.tooltip('show');
+ $target.attr('title', originalTitle);
+ $target.tooltip('_fixTitle');
+ }
+ },
+ },
+};
+</script>
+<template>
+ <gl-button
+ v-gl-tooltip="{ placement: tooltipPlacement, container: tooltipContainer }"
+ :data-clipboard-target="target"
+ :data-clipboard-text="text"
+ :title="title"
+ >
+ <slot>
+ <icon name="duplicate" />
+ </slot>
+ </gl-button>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue b/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue
index a50f49c1279..baed26a157c 100644
--- a/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue
@@ -51,7 +51,7 @@ export default {
<div class="note-header">
<div class="note-header-info">
<a :href="getUserData.path">
- <span class="d-none d-sm-inline-block">{{ getUserData.name }}</span>
+ <span class="d-none d-sm-inline-block bold">{{ getUserData.name }}</span>
<span class="note-headline-light">@{{ getUserData.username }}</span>
</a>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/notes/system_note.vue b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
index acc179b3834..3c86b7e4c61 100644
--- a/app/assets/javascripts/vue_shared/components/notes/system_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
@@ -22,6 +22,7 @@ import noteHeader from '~/notes/components/note_header.vue';
import Icon from '~/vue_shared/components/icon.vue';
import TimelineEntryItem from './timeline_entry_item.vue';
import { spriteIcon } from '../../../lib/utils/common_utils';
+import initMRPopovers from '~/mr_popover/';
const MAX_VISIBLE_COMMIT_LIST_COUNT = 3;
@@ -71,6 +72,9 @@ export default {
);
},
},
+ mounted() {
+ initMRPopovers(this.$el.querySelectorAll('.gfm-merge_request'));
+ },
};
</script>
diff --git a/app/assets/javascripts/vue_shared/components/pagination/constants.js b/app/assets/javascripts/vue_shared/components/pagination/constants.js
new file mode 100644
index 00000000000..748ad178c70
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/pagination/constants.js
@@ -0,0 +1,13 @@
+import { s__ } from '~/locale';
+
+export const PAGINATION_UI_BUTTON_LIMIT = 4;
+export const UI_LIMIT = 6;
+export const SPREAD = '...';
+export const PREV = s__('Pagination|Prev');
+export const NEXT = s__('Pagination|Next');
+export const FIRST = s__('Pagination|« First');
+export const LAST = s__('Pagination|Last »');
+export const LABEL_FIRST_PAGE = s__('Pagination|Go to first page');
+export const LABEL_PREV_PAGE = s__('Pagination|Go to previous page');
+export const LABEL_NEXT_PAGE = s__('Pagination|Go to next page');
+export const LABEL_LAST_PAGE = s__('Pagination|Go to last page');
diff --git a/app/assets/javascripts/vue_shared/components/pagination/graphql_pagination.vue b/app/assets/javascripts/vue_shared/components/pagination/graphql_pagination.vue
new file mode 100644
index 00000000000..53e473432db
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/pagination/graphql_pagination.vue
@@ -0,0 +1,47 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import { PREV, NEXT } from '~/vue_shared/components/pagination/constants';
+
+/**
+ * Pagination Component for graphql API
+ */
+export default {
+ name: 'GraphqlPaginationComponent',
+ components: {
+ GlButton,
+ },
+ labels: {
+ prev: PREV,
+ next: NEXT,
+ },
+ props: {
+ hasNextPage: {
+ required: true,
+ type: Boolean,
+ },
+ hasPreviousPage: {
+ required: true,
+ type: Boolean,
+ },
+ },
+};
+</script>
+<template>
+ <div class="justify-content-center d-flex prepend-top-default">
+ <div class="btn-group">
+ <gl-button
+ class="js-prev-btn page-link"
+ :disabled="!hasPreviousPage"
+ @click="$emit('previousClicked')"
+ >{{ $options.labels.prev }}</gl-button
+ >
+
+ <gl-button
+ class="js-next-btn page-link"
+ :disabled="!hasNextPage"
+ @click="$emit('nextClicked')"
+ >{{ $options.labels.next }}</gl-button
+ >
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/pagination/table_pagination.vue b/app/assets/javascripts/vue_shared/components/pagination/table_pagination.vue
new file mode 100644
index 00000000000..1e2d4ffa7e3
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/pagination/table_pagination.vue
@@ -0,0 +1,159 @@
+<script>
+import {
+ PAGINATION_UI_BUTTON_LIMIT,
+ UI_LIMIT,
+ SPREAD,
+ PREV,
+ NEXT,
+ FIRST,
+ LAST,
+} from '~/vue_shared/components/pagination/constants';
+
+export default {
+ props: {
+ /**
+ This function will take the information given by the pagination component
+
+ Here is an example `change` method:
+
+ change(pagenum) {
+ gl.utils.visitUrl(`?page=${pagenum}`);
+ },
+ */
+ change: {
+ type: Function,
+ required: true,
+ },
+
+ /**
+ pageInfo will come from the headers of the API call
+ in the `.then` clause of the VueResource API call
+ there should be a function that contructs the pageInfo for this component
+
+ This is an example:
+
+ const pageInfo = headers => ({
+ perPage: +headers['X-Per-Page'],
+ page: +headers['X-Page'],
+ total: +headers['X-Total'],
+ totalPages: +headers['X-Total-Pages'],
+ nextPage: +headers['X-Next-Page'],
+ previousPage: +headers['X-Prev-Page'],
+ });
+ */
+ pageInfo: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ prev() {
+ return this.pageInfo.previousPage;
+ },
+ next() {
+ return this.pageInfo.nextPage;
+ },
+ getItems() {
+ const { totalPages, nextPage, previousPage, page } = this.pageInfo;
+ const items = [];
+
+ if (page > 1) {
+ items.push({ title: FIRST, first: true });
+ }
+
+ if (previousPage) {
+ items.push({ title: PREV, prev: true });
+ } else {
+ items.push({ title: PREV, disabled: true, prev: true });
+ }
+
+ if (page > UI_LIMIT) items.push({ title: SPREAD, separator: true });
+
+ if (totalPages) {
+ const start = Math.max(page - PAGINATION_UI_BUTTON_LIMIT, 1);
+ const end = Math.min(page + PAGINATION_UI_BUTTON_LIMIT, totalPages);
+
+ for (let i = start; i <= end; i += 1) {
+ const isActive = i === page;
+ items.push({ title: i, active: isActive, page: true });
+ }
+
+ if (totalPages - page > PAGINATION_UI_BUTTON_LIMIT) {
+ items.push({ title: SPREAD, separator: true, page: true });
+ }
+ }
+
+ if (nextPage) {
+ items.push({ title: NEXT, next: true });
+ } else {
+ items.push({ title: NEXT, disabled: true, next: true });
+ }
+
+ if (totalPages && totalPages - page >= 1) {
+ items.push({ title: LAST, last: true });
+ }
+
+ return items;
+ },
+ showPagination() {
+ return this.pageInfo.nextPage || this.pageInfo.previousPage;
+ },
+ },
+ methods: {
+ changePage(text, isDisabled) {
+ if (isDisabled) return;
+
+ const { totalPages, nextPage, previousPage } = this.pageInfo;
+
+ switch (text) {
+ case SPREAD:
+ break;
+ case LAST:
+ this.change(totalPages);
+ break;
+ case NEXT:
+ this.change(nextPage);
+ break;
+ case PREV:
+ this.change(previousPage);
+ break;
+ case FIRST:
+ this.change(1);
+ break;
+ default:
+ this.change(Number(text));
+ break;
+ }
+ },
+ hideOnSmallScreen(item) {
+ return !item.first && !item.last && !item.next && !item.prev && !item.active;
+ },
+ },
+};
+</script>
+<template>
+ <div v-if="showPagination" class="gl-pagination prepend-top-default">
+ <ul class="pagination justify-content-center">
+ <li
+ v-for="(item, index) in getItems"
+ :key="index"
+ :class="{
+ page: item.page,
+ 'js-previous-button': item.prev,
+ 'js-next-button': item.next,
+ 'js-last-button': item.last,
+ 'js-first-button': item.first,
+ 'd-none d-md-block': hideOnSmallScreen(item),
+ separator: item.separator,
+ active: item.active,
+ disabled: item.disabled || item.separator,
+ }"
+ class="page-item"
+ >
+ <button type="button" class="page-link" @click="changePage(item.title, item.disabled)">
+ {{ item.title }}
+ </button>
+ </li>
+ </ul>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/pagination_links.vue b/app/assets/javascripts/vue_shared/components/pagination_links.vue
index 0b44f8578cb..06097913e91 100644
--- a/app/assets/javascripts/vue_shared/components/pagination_links.vue
+++ b/app/assets/javascripts/vue_shared/components/pagination_links.vue
@@ -1,6 +1,13 @@
<script>
import { GlPagination } from '@gitlab/ui';
-import { s__ } from '../../locale';
+import {
+ PREV,
+ NEXT,
+ LABEL_FIRST_PAGE,
+ LABEL_PREV_PAGE,
+ LABEL_NEXT_PAGE,
+ LABEL_LAST_PAGE,
+} from '~/vue_shared/components/pagination/constants';
export default {
components: {
@@ -16,23 +23,27 @@ export default {
required: true,
},
},
- firstText: s__('Pagination|« First'),
- prevText: s__('Pagination|Prev'),
- nextText: s__('Pagination|Next'),
- lastText: s__('Pagination|Last »'),
+ prevText: PREV,
+ nextText: NEXT,
+ labelFirstPage: LABEL_FIRST_PAGE,
+ labelPrevPage: LABEL_PREV_PAGE,
+ labelNextPage: LABEL_NEXT_PAGE,
+ labelLastPage: LABEL_LAST_PAGE,
};
</script>
<template>
<gl-pagination
v-bind="$attrs"
- :change="change"
- :page="pageInfo.page"
+ :value="pageInfo.page"
:per-page="pageInfo.perPage"
:total-items="pageInfo.total"
- :first-text="$options.firstText"
:prev-text="$options.prevText"
:next-text="$options.nextText"
- :last-text="$options.lastText"
+ :label-first-page="$options.labelFirstPage"
+ :label-prev-page="$options.labelPrevPage"
+ :label-next-page="$options.labelNextPage"
+ :label-last-page="$options.labelLastPage"
+ @input="change"
/>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/pikaday.vue b/app/assets/javascripts/vue_shared/components/pikaday.vue
index fa502b9beb9..8104d919bf6 100644
--- a/app/assets/javascripts/vue_shared/components/pikaday.vue
+++ b/app/assets/javascripts/vue_shared/components/pikaday.vue
@@ -34,7 +34,7 @@ export default {
format: 'yyyy-mm-dd',
container: this.$el,
defaultDate: this.selectedDate,
- setDefaultDate: !!this.selectedDate,
+ setDefaultDate: Boolean(this.selectedDate),
minDate: this.minDate,
maxDate: this.maxDate,
parse: dateString => parsePikadayDate(dateString),
diff --git a/app/assets/javascripts/vue_shared/components/select2_select.vue b/app/assets/javascripts/vue_shared/components/select2_select.vue
index 3074ea859cc..6d2612556ff 100644
--- a/app/assets/javascripts/vue_shared/components/select2_select.vue
+++ b/app/assets/javascripts/vue_shared/components/select2_select.vue
@@ -1,6 +1,6 @@
<script>
import $ from 'jquery';
-import 'select2/select2';
+import 'select2';
export default {
name: 'Select2Select',
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
index 373794fb1f2..05446903286 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
@@ -14,10 +14,12 @@ export default {
},
computed: {
labelsList() {
- const labelsString = this.labels
- .slice(0, 5)
- .map(label => label.title)
- .join(', ');
+ const labelsString = this.labels.length
+ ? this.labels
+ .slice(0, 5)
+ .map(label => label.title)
+ .join(', ')
+ : s__('LabelSelect|Labels');
if (this.labels.length > 5) {
return sprintf(s__('LabelSelect|%{labelsString}, and %{remainingLabelCount} more'), {
diff --git a/app/assets/javascripts/vue_shared/components/table_pagination.vue b/app/assets/javascripts/vue_shared/components/table_pagination.vue
deleted file mode 100644
index 8e0b08032f7..00000000000
--- a/app/assets/javascripts/vue_shared/components/table_pagination.vue
+++ /dev/null
@@ -1,159 +0,0 @@
-<script>
-import { s__ } from '../../locale';
-
-const PAGINATION_UI_BUTTON_LIMIT = 4;
-const UI_LIMIT = 6;
-const SPREAD = '...';
-const PREV = s__('Pagination|Prev');
-const NEXT = s__('Pagination|Next');
-const FIRST = s__('Pagination|« First');
-const LAST = s__('Pagination|Last »');
-
-export default {
- props: {
- /**
- This function will take the information given by the pagination component
-
- Here is an example `change` method:
-
- change(pagenum) {
- gl.utils.visitUrl(`?page=${pagenum}`);
- },
- */
- change: {
- type: Function,
- required: true,
- },
-
- /**
- pageInfo will come from the headers of the API call
- in the `.then` clause of the VueResource API call
- there should be a function that contructs the pageInfo for this component
-
- This is an example:
-
- const pageInfo = headers => ({
- perPage: +headers['X-Per-Page'],
- page: +headers['X-Page'],
- total: +headers['X-Total'],
- totalPages: +headers['X-Total-Pages'],
- nextPage: +headers['X-Next-Page'],
- previousPage: +headers['X-Prev-Page'],
- });
- */
- pageInfo: {
- type: Object,
- required: true,
- },
- },
- computed: {
- prev() {
- return this.pageInfo.previousPage;
- },
- next() {
- return this.pageInfo.nextPage;
- },
- getItems() {
- const { totalPages, nextPage, previousPage, page } = this.pageInfo;
- const items = [];
-
- if (page > 1) {
- items.push({ title: FIRST, first: true });
- }
-
- if (previousPage) {
- items.push({ title: PREV, prev: true });
- } else {
- items.push({ title: PREV, disabled: true, prev: true });
- }
-
- if (page > UI_LIMIT) items.push({ title: SPREAD, separator: true });
-
- if (totalPages) {
- const start = Math.max(page - PAGINATION_UI_BUTTON_LIMIT, 1);
- const end = Math.min(page + PAGINATION_UI_BUTTON_LIMIT, totalPages);
-
- for (let i = start; i <= end; i += 1) {
- const isActive = i === page;
- items.push({ title: i, active: isActive, page: true });
- }
-
- if (totalPages - page > PAGINATION_UI_BUTTON_LIMIT) {
- items.push({ title: SPREAD, separator: true, page: true });
- }
- }
-
- if (nextPage) {
- items.push({ title: NEXT, next: true });
- } else {
- items.push({ title: NEXT, disabled: true, next: true });
- }
-
- if (totalPages && totalPages - page >= 1) {
- items.push({ title: LAST, last: true });
- }
-
- return items;
- },
- showPagination() {
- return this.pageInfo.nextPage || this.pageInfo.previousPage;
- },
- },
- methods: {
- changePage(text, isDisabled) {
- if (isDisabled) return;
-
- const { totalPages, nextPage, previousPage } = this.pageInfo;
-
- switch (text) {
- case SPREAD:
- break;
- case LAST:
- this.change(totalPages);
- break;
- case NEXT:
- this.change(nextPage);
- break;
- case PREV:
- this.change(previousPage);
- break;
- case FIRST:
- this.change(1);
- break;
- default:
- this.change(+text);
- break;
- }
- },
- hideOnSmallScreen(item) {
- return !item.first && !item.last && !item.next && !item.prev && !item.active;
- },
- },
-};
-</script>
-<template>
- <div v-if="showPagination" class="gl-pagination prepend-top-default">
- <ul class="pagination justify-content-center">
- <li
- v-for="(item, index) in getItems"
- :key="index"
- :class="{
- page: item.page,
- 'js-previous-button': item.prev,
- 'js-next-button': item.next,
- 'js-last-button': item.last,
- 'js-first-button': item.first,
- 'd-none d-md-block': hideOnSmallScreen(item),
- separator: item.separator,
- active: item.active,
- disabled: item.disabled || item.separator,
- }"
- class="page-item"
- >
- <button type="button" class="page-link" @click="changePage(item.title, item.disabled)">
- {{ item.title }}
- </button>
- </li>
- </ul>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
index f9773622001..a60d5eb491e 100644
--- a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
+++ b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
@@ -1,11 +1,13 @@
<script>
import { GlPopover, GlSkeletonLoading } from '@gitlab/ui';
+import Icon from '~/vue_shared/components/icon.vue';
import UserAvatarImage from '../user_avatar/user_avatar_image.vue';
import { glEmojiTag } from '../../../emoji';
export default {
name: 'UserPopover',
components: {
+ Icon,
GlPopover,
GlSkeletonLoading,
UserAvatarImage,
@@ -68,16 +70,31 @@ export default {
<gl-skeleton-loading v-else :lines="1" class="animation-container-small mb-1" />
</div>
<div class="text-secondary">
- <div v-if="user.bio" class="js-bio">{{ user.bio }}</div>
- <div v-if="user.organization" class="js-organization">{{ user.organization }}</div>
+ <div v-if="user.bio" class="js-bio d-flex mb-1">
+ <icon name="profile" css-classes="category-icon flex-shrink-0" />
+ <span class="ml-1">{{ user.bio }}</span>
+ </div>
+ <div v-if="user.organization" class="js-organization d-flex mb-1">
+ <icon
+ v-show="!jobInfoIsLoading"
+ name="work"
+ css-classes="category-icon flex-shrink-0"
+ />
+ <span class="ml-1">{{ user.organization }}</span>
+ </div>
<gl-skeleton-loading
v-if="jobInfoIsLoading"
:lines="1"
class="animation-container-small mb-1"
/>
</div>
- <div class="text-secondary">
- {{ user.location }}
+ <div class="js-location text-secondary d-flex">
+ <icon
+ v-show="!locationIsLoading && user.location"
+ name="location"
+ css-classes="category-icon flex-shrink-0"
+ />
+ <span class="ml-1">{{ user.location }}</span>
<gl-skeleton-loading
v-if="locationIsLoading"
:lines="1"
diff --git a/app/assets/javascripts/vue_shared/directives/tooltip.js b/app/assets/javascripts/vue_shared/directives/tooltip.js
index 549d27e96d9..2d1f7a1cfd0 100644
--- a/app/assets/javascripts/vue_shared/directives/tooltip.js
+++ b/app/assets/javascripts/vue_shared/directives/tooltip.js
@@ -1,4 +1,5 @@
import $ from 'jquery';
+import '~/commons/bootstrap';
export default {
bind(el) {
diff --git a/app/assets/javascripts/vue_shared/models/label.js b/app/assets/javascripts/vue_shared/models/label.js
deleted file mode 100644
index 2d2732d0661..00000000000
--- a/app/assets/javascripts/vue_shared/models/label.js
+++ /dev/null
@@ -1,13 +0,0 @@
-export default class ListLabel {
- constructor(obj) {
- this.id = obj.id;
- this.title = obj.title;
- this.type = obj.type;
- this.color = obj.color;
- this.textColor = obj.text_color;
- this.description = obj.description;
- this.priority = obj.priority !== null ? obj.priority : Infinity;
- }
-}
-
-window.ListLabel = ListLabel;
diff --git a/app/assets/stylesheets/bootstrap_migration.scss b/app/assets/stylesheets/bootstrap_migration.scss
index 93377b8dd91..802d58779d0 100644
--- a/app/assets/stylesheets/bootstrap_migration.scss
+++ b/app/assets/stylesheets/bootstrap_migration.scss
@@ -22,7 +22,9 @@ body,
.form-control,
.search form {
// Override default font size used in non-csslab UI
- font-size: 14px;
+ // Use rem to keep default font-size at 14px on body so 1rem still
+ // fits 8px grid, but also allow users to change browser font size
+ font-size: .875rem;
}
legend {
@@ -145,11 +147,6 @@ table {
pointer-events: none;
}
-.popover,
-.popover-header {
- font-size: 14px;
-}
-
@each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
diff --git a/app/assets/stylesheets/components/avatar.scss b/app/assets/stylesheets/components/avatar.scss
new file mode 100644
index 00000000000..8e9650cdf34
--- /dev/null
+++ b/app/assets/stylesheets/components/avatar.scss
@@ -0,0 +1,195 @@
+$avatar-sizes: (
+ 16: (
+ font-size: 10px,
+ line-height: 16px,
+ border-radius: $border-radius-small
+ ),
+ 18: (
+ border-radius: $border-radius-small
+ ),
+ 20: (
+ border-radius: $border-radius-small
+ ),
+ 24: (
+ font-size: 12px,
+ line-height: 24px,
+ border-radius: $border-radius-default
+ ),
+ 26: (
+ font-size: 20px,
+ line-height: 1.33,
+ border-radius: $border-radius-default
+ ),
+ 32: (
+ font-size: 14px,
+ line-height: 32px,
+ border-radius: $border-radius-default
+ ),
+ 40: (
+ font-size: 16px,
+ line-height: 38px,
+ border-radius: $border-radius-default
+ ),
+ 48: (
+ font-size: 20px,
+ line-height: 48px,
+ border-radius: $border-radius-large
+ ),
+ 60: (
+ font-size: 32px,
+ line-height: 58px,
+ border-radius: $border-radius-large
+ ),
+ 64: (
+ font-size: 28px,
+ line-height: 64px,
+ border-radius: $border-radius-large
+ ),
+ 90: (
+ font-size: 36px,
+ line-height: 88px,
+ border-radius: $border-radius-large
+ ),
+ 100: (
+ font-size: 36px,
+ line-height: 98px,
+ border-radius: $border-radius-large
+ ),
+ 160: (
+ font-size: 96px,
+ line-height: 158px,
+ border-radius: $border-radius-large
+ )
+);
+
+$identicon-backgrounds: $identicon-red, $identicon-purple, $identicon-indigo, $identicon-blue, $identicon-teal,
+ $identicon-orange, $gray-darker;
+
+.avatar-circle {
+ float: left;
+ margin-right: $gl-padding;
+ border-radius: $avatar-radius;
+ border: 1px solid $gray-normal;
+
+ @each $size, $size-config in $avatar-sizes {
+ &.s#{$size} {
+ @include avatar-size(#{$size}px, if($size < 48, 8px, 16px));
+ }
+ }
+}
+
+.avatar {
+ @extend .avatar-circle;
+ transition-property: none;
+
+ width: 40px;
+ height: 40px;
+ padding: 0;
+ background: $gray-lightest;
+ overflow: hidden;
+ border-color: rgba($black, $gl-avatar-border-opacity);
+
+ &.avatar-inline {
+ float: none;
+ display: inline-block;
+ margin-left: 2px;
+ flex-shrink: 0;
+
+ &.s16 {
+ margin-right: 4px;
+ }
+
+ &.s24 {
+ margin-right: 4px;
+ }
+ }
+
+ &.center {
+ font-size: 14px;
+ line-height: 1.8em;
+ text-align: center;
+ }
+
+ &.avatar-tile {
+ border-radius: 0;
+ border: 0;
+ }
+
+ &.avatar-placeholder {
+ border: 0;
+ }
+}
+
+.identicon {
+ text-align: center;
+ vertical-align: top;
+ color: $gray-800;
+ background-color: $gray-darker;
+
+ // Sizes
+ @each $size, $size-config in $avatar-sizes {
+ $keys: map-keys($size-config);
+
+ &.s#{$size} {
+ @each $key in $keys {
+ // We don't want `border-radius` to be included here.
+ @if ($key != 'border-radius') {
+ #{$key}: map-get($size-config, #{$key});
+ }
+ }
+ }
+ }
+
+ // Background colors
+ @for $i from 1 through length($identicon-backgrounds) {
+ &.bg#{$i} {
+ background-color: nth($identicon-backgrounds, $i);
+ }
+ }
+}
+
+.avatar-container {
+ @extend .avatar-circle;
+ overflow: hidden;
+ display: flex;
+
+ a {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ text-decoration: none;
+ }
+
+ .avatar {
+ border-radius: 0;
+ border: 0;
+ height: auto;
+ width: 100%;
+ margin: 0;
+ align-self: center;
+ }
+
+ &.s40 {
+ min-width: 40px;
+ min-height: 40px;
+ }
+
+ &.s64 {
+ min-width: 64px;
+ min-height: 64px;
+ }
+}
+
+.rect-avatar {
+ border-radius: $border-radius-small;
+
+ @each $size, $size-config in $avatar-sizes {
+ &.s#{$size} {
+ border-radius: map-get($size-config, 'border-radius');
+ }
+ }
+}
+
+.avatar-counter {
+ @include avatar-counter();
+}
diff --git a/app/assets/stylesheets/components/dashboard_skeleton.scss b/app/assets/stylesheets/components/dashboard_skeleton.scss
index 42ede599bc6..a104d035a9a 100644
--- a/app/assets/stylesheets/components/dashboard_skeleton.scss
+++ b/app/assets/stylesheets/components/dashboard_skeleton.scss
@@ -8,14 +8,10 @@
&-warning {
background-color: $orange-100;
}
-
- &-failed {
- background-color: $red-100;
- }
}
&-body {
- height: 120px;
+ min-height: 120px;
&-warning {
background-color: $orange-50;
@@ -26,20 +22,14 @@
}
}
- &-time-ago {
- &-icon {
- color: $gray-500;
- }
+ &-icon {
+ color: $gray-500;
}
&-footer {
border-radius: $gl-padding;
height: $gl-padding-32;
- &-failed {
- background-color: $red-100;
- }
-
&-arrow {
color: $gray-300;
}
@@ -56,6 +46,13 @@
}
}
+ &-header,
+ &-footer {
+ &-failed {
+ background-color: $red-100;
+ }
+ }
+
&-skeleton-info {
border-radius: $gl-padding;
height: $gl-padding;
diff --git a/app/assets/stylesheets/components/popover.scss b/app/assets/stylesheets/components/popover.scss
index 7d46b262a69..58aaca93160 100644
--- a/app/assets/stylesheets/components/popover.scss
+++ b/app/assets/stylesheets/components/popover.scss
@@ -1,16 +1,145 @@
.popover {
- min-width: 300px;
+ max-width: $popover-max-width;
+ border: 1px solid $gray-200;
+ box-shadow: 0 2px 3px 1px $gray-200;
+ font-size: $gl-font-size-small;
- .popover-body .user-popover {
- padding: $gl-padding-8;
- font-size: $gl-font-size-small;
- line-height: $gl-line-height;
+ /**
+ * Blue popover variation
+ */
+ &.blue {
+ background-color: $blue-600;
+ border-color: $blue-600;
+
+ .popover-body {
+ color: $white-light;
+ }
+
+ &.bs-popover-bottom {
+ .arrow::before,
+ .arrow::after {
+ border-bottom-color: $blue-600;
+ }
+ }
+
+ &.bs-popover-top {
+ .arrow::before,
+ .arrow::after {
+ border-top-color: $blue-600;
+ }
+ }
+
+ &.bs-popover-right {
+ .arrow::after,
+ .arrow::before {
+ border-right-color: $blue-600;
+ }
+ }
+
+ &.bs-popover-left {
+ .arrow::before,
+ .arrow::after {
+ border-left-color: $blue-600;
+ }
+ }
+ }
+}
+
+.bs-popover-top {
+ /* When popover position is top, the arrow is translated 1 pixel
+ * due to the box-shadow include in our custom styles.
+ */
+ > .arrow::before {
+ border-top-color: $gray-200;
+ bottom: 1px;
+ }
+
+ > .arrow::after {
+ bottom: 2px;
}
}
+.bs-popover-bottom {
+ > .arrow::before {
+ border-bottom-color: $gray-200;
+ }
+
+ > .popover-header::before {
+ border-color: $white-light;
+ }
+}
+
+.bs-popover-right > .arrow::before {
+ border-right-color: $gray-200;
+}
+
+.bs-popover-left > .arrow::before {
+ border-left-color: $gray-200;
+}
+
+.popover-header {
+ background-color: $white-light;
+ font-size: $gl-font-size-small;
+}
+
+.popover-body {
+ padding: $gl-padding $gl-padding-12;
+
+ > .popover-hr {
+ margin: $gl-padding 0;
+ }
+}
+
+/**
+* mr_popover component
+*/
.mr-popover {
.text-secondary {
font-size: 12px;
line-height: 1.33;
}
}
+
+.onboarding-popover {
+ box-shadow: 0 2px 4px $dropdown-shadow-color;
+
+ .popover-body {
+ font-size: $gl-font-size;
+ line-height: $gl-line-height;
+ padding: $gl-padding;
+ }
+
+ .popover-header {
+ display: none;
+ }
+
+ .accept-mr-label {
+ background-color: $accepting-mr-label-color;
+ color: $white-light;
+ }
+}
+
+/**
+* user_popover component
+*/
+.user-popover {
+ padding: $gl-padding-8;
+ line-height: $gl-line-height;
+
+ .category-icon {
+ color: $gray-600;
+ }
+}
+
+.onboarding-welcome-page {
+ .popover {
+ min-width: auto;
+ max-width: 40%;
+
+ .popover-body {
+ padding-top: $gl-padding;
+ padding-bottom: $gl-padding;
+ font-size: $gl-font-size-small;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/components/related_items_list.scss b/app/assets/stylesheets/components/related_items_list.scss
index 628dffc39f1..7f9cf1266b1 100644
--- a/app/assets/stylesheets/components/related_items_list.scss
+++ b/app/assets/stylesheets/components/related_items_list.scss
@@ -11,20 +11,14 @@ $item-weight-max-width: 48px;
}
}
+.sortable-link {
+ max-width: 85%;
+}
+
.item-body {
- display: flex;
position: relative;
- align-items: center;
- padding: $gl-padding-8;
line-height: $gl-line-height;
- .item-contents {
- display: flex;
- align-items: center;
- flex-wrap: wrap;
- flex-grow: 1;
- }
-
.issue-token-state-icon-open {
color: $green-500;
}
@@ -52,157 +46,130 @@ $item-weight-max-width: 48px;
}
.confidential-icon {
- align-self: baseline;
color: $orange-600;
- margin-right: $gl-padding-4;
}
.item-title {
flex-basis: 100%;
- margin-bottom: $gl-padding-8;
font-size: $gl-font-size-small;
&.mr-title {
font-weight: $gl-font-weight-bold;
}
- .sortable-link {
- max-width: 85%;
- }
-
.issue-token-state-icon-open,
.issue-token-state-icon-closed {
display: none;
}
}
- .item-meta {
- display: flex;
- flex-wrap: wrap;
- flex-basis: 100%;
- font-size: $gl-font-size-small;
+ .item-path-id .path-id-text,
+ .item-milestone .milestone-title,
+ .item-due-date,
+ .item-weight .board-card-info-text {
color: $gl-text-color-secondary;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ }
+}
- .item-meta-child {
- order: 0;
- display: flex;
- flex-wrap: wrap;
- flex-basis: 100%;
-
- .item-due-date,
- .item-weight {
- margin-left: $gl-padding-8;
- }
+.item-meta {
+ flex-basis: 100%;
+ font-size: $gl-font-size-small;
+ color: $gl-text-color-secondary;
- .item-milestone,
- .item-weight {
- cursor: help;
- }
+ .item-meta-child {
+ flex-basis: 100%;
+ }
- .item-milestone {
- text-decoration: none;
- max-width: $item-milestone-max-width;
- }
+ .item-milestone,
+ .item-weight {
+ cursor: help;
+ }
- .item-due-date {
- margin-right: 0;
- }
+ .item-milestone {
+ text-decoration: none;
+ max-width: $item-milestone-max-width;
- .item-weight {
- margin-right: 0;
- max-width: $item-weight-max-width;
- }
+ .ic-clock {
+ color: $gl-text-color-tertiary;
+ margin-right: $gl-padding-4;
}
+ }
- .item-path-id .path-id-text,
- .item-milestone .milestone-title,
- .item-due-date,
- .item-weight .board-card-info-text {
- color: $gl-text-color-secondary;
- display: inline-block;
- text-overflow: ellipsis;
- overflow: hidden;
- white-space: nowrap;
- }
+ .item-weight {
+ max-width: $item-weight-max-width;
+ }
- .item-path-id {
- margin-top: $gl-padding-4;
- font-size: $gl-font-size-xs;
- white-space: nowrap;
+ .item-assignees {
+ .user-avatar-link {
+ margin-right: -$gl-padding-4;
- .path-id-text {
- font-weight: $gl-font-weight-bold;
- max-width: $item-path-max-width;
+ &:nth-of-type(1) {
+ z-index: 2;
}
- .issue-token-state-icon-open,
- .issue-token-state-icon-closed {
- display: block;
+ &:nth-of-type(2) {
+ z-index: 1;
}
- &:not(.mr-item-path) {
- order: 1;
+ &:last-child {
+ margin-right: 0;
}
}
- .item-milestone .ic-clock {
- color: $gl-text-color-tertiary;
- margin-right: $gl-padding-4;
+ .avatar {
+ height: $gl-padding;
+ width: $gl-padding;
+ margin-right: 0;
+ vertical-align: bottom;
}
- .item-assignees {
- order: 2;
- align-self: flex-end;
- align-items: center;
- margin-left: auto;
-
- .user-avatar-link {
- margin-right: -$gl-padding-4;
-
- &:nth-of-type(1) {
- z-index: 2;
- }
+ .avatar-counter {
+ height: $gl-padding;
+ border: 1px solid transparent;
+ background-color: $gl-text-color-tertiary;
+ font-weight: $gl-font-weight-bold;
+ padding: 0 $gl-padding-4;
+ line-height: $gl-padding;
+ }
+ }
+}
- &:nth-of-type(2) {
- z-index: 1;
- }
+.item-path-id {
+ font-size: $gl-font-size-xs;
+ white-space: nowrap;
- &:last-child {
- margin-right: 0;
- }
- }
+ .path-id-text {
+ font-weight: $gl-font-weight-bold;
+ max-width: $item-path-max-width;
+ }
- .avatar {
- height: $gl-padding;
- width: $gl-padding;
- margin-right: 0;
- vertical-align: bottom;
- }
+ .issue-token-state-icon-open,
+ .issue-token-state-icon-closed {
+ display: block;
+ }
- .avatar-counter {
- height: $gl-padding;
- border: 1px solid transparent;
- background-color: $gl-text-color-tertiary;
- font-weight: $gl-font-weight-bold;
- padding: 0 $gl-padding-4;
- line-height: $gl-padding;
- }
+ @include media-breakpoint-down(sm) {
+ &:not(.mr-item-path) {
+ order: 1;
}
}
+}
- .btn-item-remove {
- position: absolute;
- right: 0;
- top: $gl-padding-4 / 2;
- padding: $gl-padding-4;
- margin-right: $gl-padding-4 / 2;
- line-height: 0;
- border-color: transparent;
- color: $gl-text-color-secondary;
+.btn-item-remove {
+ position: absolute;
+ right: 0;
+ top: $gl-padding-4 / 2;
+ padding: $gl-padding-4;
+ margin-right: $gl-padding-4 / 2;
+ line-height: 0;
+ border-color: transparent;
+ color: $gl-text-color-secondary;
- &:hover {
- color: $gl-text-color;
- }
+ &:hover {
+ color: $gl-text-color;
}
}
@@ -212,74 +179,52 @@ $item-weight-max-width: 48px;
}
@include media-breakpoint-up(sm) {
- .item-body {
- .item-contents .item-title {
- .mr-title-link,
- .sortable-link {
- max-width: 90%;
- }
- }
+ .sortable-link {
+ max-width: 90%;
}
}
/* Small devices (landscape phones, 768px and up) */
@include media-breakpoint-up(md) {
+ .sortable-link {
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ max-width: 100%;
+ }
+
.item-body {
.item-contents {
min-width: 0;
+ }
- .item-title {
- flex-basis: unset;
- // 95% because we compensate
- // for remove button which is
- // positioned absolutely
- width: 95%;
- margin-bottom: $gl-padding-4;
-
- .mr-title-link,
- .sortable-link {
- text-overflow: ellipsis;
- overflow: hidden;
- white-space: nowrap;
- max-width: 100%;
- }
- }
-
- .item-meta {
- .item-path-id {
- order: 0;
- margin-top: 0;
- }
-
- .item-meta-child {
- flex-basis: unset;
- margin-left: auto;
- margin-right: $gl-padding-4;
-
- ~ .item-assignees {
- margin-left: $gl-padding-4;
- }
- }
-
- .item-assignees {
- margin-bottom: 0;
- margin-left: 0;
- order: 2;
- }
- }
+ .item-title {
+ flex-basis: unset;
+ // 95% because we compensate
+ // for remove button which is
+ // positioned absolutely
+ width: 95%;
}
.btn-item-remove {
order: 1;
}
}
+
+ .item-meta {
+ .item-meta-child {
+ flex-basis: unset;
+
+ ~ .item-assignees {
+ margin-left: $gl-padding-4;
+ }
+ }
+ }
}
/* Medium devices (desktops, 992px and up) */
@include media-breakpoint-up(lg) {
.item-body {
- padding: $gl-padding;
-
.item-title {
font-size: $gl-font-size;
}
@@ -287,107 +232,60 @@ $item-weight-max-width: 48px;
.item-meta .item-path-id {
font-size: inherit; // Base size given to `item-meta` is `$gl-font-size-small`
}
-
- .issue-token-state-icon-open,
- .issue-token-state-icon-closed {
- margin-right: $gl-padding-4;
- }
}
}
/* Large devices (large desktops, 1200px and up) */
@include media-breakpoint-up(xl) {
.item-body {
- padding: $gl-padding-8;
- padding-left: $gl-padding;
+ .item-title {
+ min-width: 0;
+ width: auto;
+ flex-basis: unset;
+ font-weight: $gl-font-weight-normal;
- .item-contents {
- flex-wrap: nowrap;
- overflow: hidden;
-
- .item-title {
- display: flex;
- margin-bottom: 0;
- min-width: 0;
- width: auto;
- flex-basis: unset;
- font-weight: $gl-font-weight-normal;
-
- .mr-title-link,
- .sortable-link {
- display: block;
- text-overflow: ellipsis;
- white-space: nowrap;
- overflow: hidden;
- line-height: 1.3;
- }
-
- .issue-token-state-icon-open,
- .issue-token-state-icon-closed {
- display: block;
- margin-right: $gl-padding-8;
- }
-
- .confidential-icon {
- align-self: auto;
- margin-top: 0;
- }
+ .issue-token-state-icon-open,
+ .issue-token-state-icon-closed {
+ display: block;
+ margin-right: $gl-padding-8;
}
+ }
+ }
- .item-meta {
- margin-top: 0;
- justify-content: flex-end;
- flex: 1;
- flex-wrap: nowrap;
-
- .item-path-id {
- order: 0;
- margin-top: 0;
- margin-left: $gl-padding-8;
- margin-right: auto;
-
- .issue-token-state-icon-open,
- .issue-token-state-icon-closed {
- display: none;
- }
- }
-
- .item-meta-child {
- margin-left: $gl-padding-8;
- flex-wrap: nowrap;
- }
-
- .item-assignees {
- flex-grow: 0;
- margin-top: 0;
- margin-right: $gl-padding-4;
-
- .avatar {
- height: $gl-padding-24;
- width: $gl-padding-24;
- }
-
- .avatar-counter {
- height: $gl-padding-24;
- min-width: $gl-padding-24;
- line-height: $gl-padding-24;
- border-radius: $gl-padding-24;
- }
- }
- }
+ .item-contents {
+ overflow: hidden;
+ }
+
+ .item-meta {
+ flex: 1;
+ }
+
+ .item-assignees {
+ .avatar {
+ height: $gl-padding-24;
+ width: $gl-padding-24;
}
- .btn-item-remove {
- position: relative;
- align-self: center;
- top: initial;
- right: 0;
- margin-right: 0;
- padding: $btn-sm-side-margin;
+ .avatar-counter {
+ height: $gl-padding-24;
+ min-width: $gl-padding-24;
+ line-height: $gl-padding-24;
+ border-radius: $gl-padding-24;
+ }
+ }
- &:hover {
- border-color: $border-color;
- }
+ .btn-item-remove {
+ position: relative;
+ top: initial;
+ right: 0;
+ padding: $btn-sm-side-margin;
+
+ &:hover {
+ border-color: $border-color;
}
}
+
+ .sortable-link {
+ line-height: 1.3;
+ }
}
diff --git a/app/assets/stylesheets/components/toast.scss b/app/assets/stylesheets/components/toast.scss
new file mode 100644
index 00000000000..33e1c4e5349
--- /dev/null
+++ b/app/assets/stylesheets/components/toast.scss
@@ -0,0 +1,53 @@
+/*
+* These styles are specific to the gl-toast component.
+* Documentation: https://design.gitlab.com/components/toasts
+* Note: Styles below are nested in order to override some of vue-toasted's default styling
+*/
+.toasted-container {
+
+ max-width: $toast-max-width;
+
+ @include media-breakpoint-down(xs) {
+ width: 100%;
+ padding-right: $toast-padding-right;
+ }
+
+ .toasted.gl-toast {
+ border-radius: $border-radius-default;
+ font-size: $gl-font-size;
+ padding: $gl-padding-8 $gl-padding-24;
+ margin-top: $toast-default-margin;
+ line-height: $gl-line-height;
+ background-color: rgba($gray-900, $toast-background-opacity);
+
+ @include media-breakpoint-down(xs) {
+ .action:first-child {
+ // Ensures actions buttons are right aligned on mobile
+ margin-left: auto;
+ }
+ }
+
+ .action {
+ color: $blue-300;
+ margin: 0 0 0 $toast-action-margin-left;
+ text-transform: none;
+ font-size: $gl-font-size;
+
+ &:first-child {
+ padding-right: 0;
+ }
+ }
+
+ .toast-close {
+ font-size: $default-icon-size;
+ margin-left: $toast-default-margin;
+ padding-left: $gl-padding;
+ }
+ }
+}
+
+// Overrides the default positioning of toasts
+body .toasted-container.bottom-left {
+ bottom: $toast-offset;
+ left: $toast-offset;
+}
diff --git a/app/assets/stylesheets/errors.scss b/app/assets/stylesheets/errors.scss
index 658e0ff638e..8c32b6c8985 100644
--- a/app/assets/stylesheets/errors.scss
+++ b/app/assets/stylesheets/errors.scss
@@ -17,7 +17,7 @@ body {
text-align: center;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: auto;
- font-size: 14px;
+ font-size: .875rem;
}
h1 {
diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss
index ab9047c54e4..9b0d19b0ef0 100644
--- a/app/assets/stylesheets/framework.scss
+++ b/app/assets/stylesheets/framework.scss
@@ -8,7 +8,6 @@
@import 'framework/animations';
@import 'framework/vue_transitions';
-@import 'framework/avatar';
@import 'framework/asciidoctor';
@import 'framework/banner';
@import 'framework/blocks';
diff --git a/app/assets/stylesheets/framework/animations.scss b/app/assets/stylesheets/framework/animations.scss
index 257d788873c..6f5a2e561af 100644
--- a/app/assets/stylesheets/framework/animations.scss
+++ b/app/assets/stylesheets/framework/animations.scss
@@ -268,3 +268,27 @@ $skeleton-line-widths: (
@include webkit-prefix(animation-duration, 1s);
transform-origin: 50% 50%;
}
+
+/* ----------------------------------------------
+ * Generated by Animista on 2019-4-26 17:40:41
+ * w: http://animista.net, t: @cssanimista
+ * ---------------------------------------------- */
+@keyframes slide-in-fwd-bottom {
+ 0% {
+ transform: translateZ(-1400px) translateY(800px);
+ opacity: 0;
+ }
+
+ 100% {
+ transform: translateZ(0) translateY(0);
+ opacity: 1;
+ }
+}
+
+.slide-in-fwd-bottom-enter-active {
+ animation: slide-in-fwd-bottom 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
+}
+
+.slide-in-fwd-bottom-leave-active {
+ animation: slide-in-fwd-bottom 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94) both reverse;
+}
diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss
deleted file mode 100644
index 37a729c7a63..00000000000
--- a/app/assets/stylesheets/framework/avatar.scss
+++ /dev/null
@@ -1,194 +0,0 @@
-@mixin avatar-size($size, $margin-right) {
- width: $size;
- height: $size;
- margin-right: $margin-right;
-}
-
-.avatar-circle {
- float: left;
- margin-right: 15px;
- border-radius: $avatar-radius;
- border: 1px solid $gray-normal;
- &.s16 { @include avatar-size(16px, 6px); }
- &.s18 { @include avatar-size(18px, 6px); }
- &.s19 { @include avatar-size(19px, 6px); }
- &.s20 { @include avatar-size(20px, 7px); }
- &.s24 { @include avatar-size(24px, 8px); }
- &.s26 { @include avatar-size(26px, 8px); }
- &.s32 { @include avatar-size(32px, 10px); }
- &.s36 { @include avatar-size(36px, 10px); }
- &.s40 { @include avatar-size(40px, 10px); }
- &.s46 { @include avatar-size(46px, 15px); }
- &.s48 { @include avatar-size(48px, 10px); }
- &.s60 { @include avatar-size(60px, 12px); }
- &.s64 { @include avatar-size(64px, 14px); }
- &.s70 { @include avatar-size(70px, 14px); }
- &.s90 { @include avatar-size(90px, 15px); }
- &.s100 { @include avatar-size(100px, 15px); }
- &.s110 { @include avatar-size(110px, 15px); }
- &.s140 { @include avatar-size(140px, 15px); }
- &.s160 { @include avatar-size(160px, 20px); }
-}
-
-.avatar {
- @extend .avatar-circle;
- transition-property: none;
-
- width: 40px;
- height: 40px;
- padding: 0;
- background: $gray-lightest;
- overflow: hidden;
-
- &.avatar-inline {
- float: none;
- display: inline-block;
- margin-left: 2px;
- flex-shrink: 0;
-
- &.s16 { margin-right: 4px; }
- &.s24 { margin-right: 4px; }
- }
-
- &.center {
- font-size: 14px;
- line-height: 1.8em;
- text-align: center;
- }
-
- &.avatar-tile {
- border-radius: 0;
- border: 0;
- }
-
- &.avatar-placeholder {
- border: 0;
- }
-
- &:not([href]):hover {
- border-color: darken($gray-normal, 10%);
- }
-}
-
-.identicon {
- text-align: center;
- vertical-align: top;
- color: $gl-gray-700;
- background-color: $gray-darker;
-
- // Sizes
- &.s16 { font-size: 12px;
- line-height: 1.33; }
-
- &.s24 { font-size: 13px;
- line-height: 1.8; }
-
- &.s26 { font-size: 20px;
- line-height: 1.33; }
-
- &.s32 { font-size: 20px;
- line-height: 30px; }
-
- &.s40 { font-size: 16px;
- line-height: 38px; }
-
- &.s48 { font-size: 20px;
- line-height: 46px; }
-
- &.s60 { font-size: 32px;
- line-height: 58px; }
-
- &.s64 { font-size: 32px;
- line-height: 64px; }
-
- &.s70 { font-size: 34px;
- line-height: 70px; }
-
- &.s90 { font-size: 36px;
- line-height: 88px; }
-
- &.s100 { font-size: 36px;
- line-height: 98px; }
-
- &.s110 { font-size: 40px;
- line-height: 108px;
- font-weight: $gl-font-weight-normal; }
-
- &.s140 { font-size: 72px;
- line-height: 138px; }
-
- &.s160 { font-size: 96px;
- line-height: 158px; }
-
- // Background colors
- &.bg1 { background-color: $identicon-red; }
- &.bg2 { background-color: $identicon-purple; }
- &.bg3 { background-color: $identicon-indigo; }
- &.bg4 { background-color: $identicon-blue; }
- &.bg5 { background-color: $identicon-teal; }
- &.bg6 { background-color: $identicon-orange; }
- &.bg7 { background-color: $gray-darker; }
-}
-
-.avatar-container {
- @extend .avatar-circle;
- overflow: hidden;
- display: flex;
-
- a {
- width: 100%;
- height: 100%;
- display: flex;
- text-decoration: none;
- }
-
- .avatar {
- border-radius: 0;
- border: 0;
- height: auto;
- width: 100%;
- margin: 0;
- align-self: center;
- }
-
- &.s40 { min-width: 40px;
- min-height: 40px; }
-
- &.s64 { min-width: 64px;
- min-height: 64px; }
-}
-
-.rect-avatar {
- border-radius: $border-radius-small;
- &.s16 { border-radius: $border-radius-small; }
- &.s18 { border-radius: $border-radius-small; }
- &.s19 { border-radius: $border-radius-small; }
- &.s20 { border-radius: $border-radius-small; }
- &.s24 { border-radius: $border-radius-default; }
- &.s26 { border-radius: $border-radius-default; }
- &.s32 { border-radius: $border-radius-default; }
- &.s36 { border-radius: $border-radius-default; }
- &.s40 { border-radius: $border-radius-default; }
- &.s46 { border-radius: $border-radius-default; }
- &.s48 { border-radius: $border-radius-large; }
- &.s60 { border-radius: $border-radius-large; }
- &.s64 { border-radius: $border-radius-large; }
- &.s70 { border-radius: $border-radius-large; }
- &.s90 { border-radius: $border-radius-large; }
- &.s96 { border-radius: $border-radius-large; }
- &.s100 { border-radius: $border-radius-large; }
- &.s110 { border-radius: $border-radius-large; }
- &.s140 { border-radius: $border-radius-large; }
- &.s160 { border-radius: $border-radius-large; }
-}
-
-.avatar-counter {
- background-color: $gray-darkest;
- color: $white-light;
- border: 1px solid $gray-normal;
- border-radius: 1em;
- font-family: $regular-font;
- font-size: 9px;
- line-height: 16px;
- text-align: center;
-}
diff --git a/app/assets/stylesheets/framework/awards.scss b/app/assets/stylesheets/framework/awards.scss
index 648e1944388..7760c48cb92 100644
--- a/app/assets/stylesheets/framework/awards.scss
+++ b/app/assets/stylesheets/framework/awards.scss
@@ -151,8 +151,7 @@
outline: 0;
.award-control-icon svg {
- background: $award-emoji-positive-add-bg;
- fill: $award-emoji-positive-add-lines;
+ fill: $blue-500;
}
.award-control-icon-neutral {
@@ -233,10 +232,7 @@
height: $default-icon-size;
width: $default-icon-size;
border-radius: 50%;
- }
-
- path {
- fill: $border-gray-normal;
+ fill: $gray-700;
}
}
diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss
index e6c55252b24..65c0ee74c60 100644
--- a/app/assets/stylesheets/framework/blocks.scss
+++ b/app/assets/stylesheets/framework/blocks.scss
@@ -22,6 +22,10 @@
}
}
+.oneline {
+ line-height: 35px;
+}
+
.row-content-block {
margin-top: 0;
background-color: $gray-light;
@@ -77,10 +81,6 @@
color: $gl-text-color;
}
- .oneline {
- line-height: 35px;
- }
-
> p:last-child {
margin-bottom: 0;
}
@@ -108,10 +108,6 @@
padding: 11px 0;
margin-bottom: 11px;
- .oneline {
- line-height: 35px;
- }
-
&.no-bottom-space {
border-bottom: 0;
margin-bottom: 0;
@@ -160,8 +156,6 @@
}
.cover-desc {
- color: $gl-text-color;
-
&.username:last-child {
padding-bottom: $gl-padding;
}
@@ -205,6 +199,7 @@
&.user-cover-block {
padding: 24px 0 0;
+ border-bottom: 1px solid $border-color;
.nav-links {
width: 100%;
@@ -238,14 +233,6 @@
margin-top: -1px;
}
-.nav-block {
- .controls {
- float: right;
- margin-top: 8px;
- padding-bottom: 8px;
- }
-}
-
.content-block {
padding: $gl-padding 0;
border-bottom: 1px solid $white-dark;
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index ab8f397f3a0..767832e242c 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -1,12 +1,12 @@
@mixin btn-comment-icon {
border-radius: 50%;
background: $white-light;
- padding: 1px 5px;
+ padding: 1px;
font-size: 12px;
color: $blue-500;
+ border: 1px solid $blue-500;
width: 24px;
height: 24px;
- border: 1px solid $blue-500;
&:hover,
&.inverted {
@@ -21,7 +21,7 @@
}
@mixin btn-default {
- border-radius: 3px;
+ border-radius: $border-radius-default;
font-size: $gl-font-size;
font-weight: $gl-font-weight-normal;
padding: $gl-vert-padding $gl-btn-padding;
@@ -37,7 +37,7 @@
@include btn-default;
}
-@mixin btn-outline($background, $text, $border, $hover-background, $hover-text, $hover-border, $active-background, $active-border) {
+@mixin btn-outline($background, $text, $border, $hover-background, $hover-text, $hover-border, $active-background, $active-border, $active-text) {
background-color: $background;
color: $text;
border-color: $border;
@@ -61,13 +61,22 @@
}
}
+ &:focus {
+ box-shadow: 0 0 4px 1px $blue-300;
+ }
+
&:active {
background-color: $active-background;
border-color: $active-border;
- color: $hover-text;
+ box-shadow: inset 0 2px 4px 0 rgba($black, 0.2);
+ color: $active-text;
> .icon {
- color: $hover-text;
+ color: $active-text;
+ }
+
+ &:focus {
+ box-shadow: inset 0 2px 4px 0 rgba($black, 0.2);
}
}
}
@@ -164,21 +173,21 @@
&.btn-inverted {
&.btn-success {
- @include btn-outline($white-light, $green-600, $green-500, $green-500, $white-light, $green-600, $green-600, $green-700);
+ @include btn-outline($white-light, $green-600, $green-500, $green-100, $green-700, $green-500, $green-200, $green-600, $green-800);
}
&.btn-remove,
&.btn-danger {
- @include btn-outline($white-light, $red-500, $red-500, $red-500, $white-light, $red-600, $red-600, $red-700);
+ @include btn-outline($white-light, $red-500, $red-500, $red-100, $red-700, $red-500, $red-200, $red-600, $red-800);
}
&.btn-warning {
- @include btn-outline($white-light, $orange-500, $orange-500, $orange-500, $white-light, $orange-600, $orange-600, $orange-700);
+ @include btn-outline($white-light, $orange-500, $orange-500, $orange-100, $orange-700, $orange-500, $orange-200, $orange-600, $orange-800);
}
&.btn-primary,
&.btn-info {
- @include btn-outline($white-light, $blue-500, $blue-500, $blue-500, $white-light, $blue-600, $blue-600, $blue-700);
+ @include btn-outline($white-light, $blue-500, $blue-500, $blue-100, $blue-700, $blue-500, $blue-200, $blue-600, $blue-800);
}
}
@@ -193,11 +202,11 @@
&.btn-close,
&.btn-close-color {
- @include btn-outline($white-light, $orange-600, $orange-500, $orange-500, $white-light, $orange-600, $orange-600, $orange-700);
+ @include btn-outline($white-light, $orange-600, $orange-500, $orange-100, $orange-700, $orange-500, $orange-200, $orange-600, $orange-800);
}
&.btn-spam {
- @include btn-outline($white-light, $red-500, $red-500, $red-500, $white-light, $red-600, $red-600, $red-700);
+ @include btn-outline($white-light, $red-500, $red-500, $red-100, $red-700, $red-500, $red-200, $red-600, $red-800);
}
&.btn-danger,
@@ -240,7 +249,7 @@
padding: 6px 16px;
border-color: $border-color;
color: $gray-darkest;
- background-color: $gray-light;
+ background-color: $white-light;
&:hover,
&:active,
@@ -249,7 +258,6 @@
box-shadow: none;
border-color: lighten($blue-300, 20%);
color: $gray-darkest;
- background-color: $gray-light;
}
}
@@ -330,6 +338,8 @@
svg {
top: auto;
+ width: 16px;
+ height: 16px;
}
}
@@ -402,7 +412,7 @@
.btn-inverted {
&-secondary {
- @include btn-outline($white-light, $blue-500, $blue-500, $blue-500, $white-light, $blue-600, $blue-600, $blue-700);
+ @include btn-outline($white-light, $blue-500, $blue-500, $blue-100, $blue-700, $blue-500, $blue-200, $blue-600, $blue-800);
}
}
diff --git a/app/assets/stylesheets/framework/ci_variable_list.scss b/app/assets/stylesheets/framework/ci_variable_list.scss
index d9b0e4558ad..28d7492b99c 100644
--- a/app/assets/stylesheets/framework/ci_variable_list.scss
+++ b/app/assets/stylesheets/framework/ci_variable_list.scss
@@ -47,6 +47,7 @@
display: flex;
align-items: flex-start;
width: 100%;
+ padding-bottom: $gl-padding;
@include media-breakpoint-down(xs) {
display: block;
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index dffd5e70edb..db09118ba15 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -5,6 +5,9 @@
.cgreen { color: $green-600; }
.cdark { color: $common-gray-dark; }
+.fwhite { fill: $white-light; }
+.fgray { fill: $gray-700; }
+
.text-plain,
.text-plain:hover {
color: $gl-text-color;
@@ -48,6 +51,10 @@
color: $brand-info;
}
+.bg-gray-light {
+ background-color: $gray-light;
+}
+
.text-break-word {
word-break: break-all;
}
@@ -435,10 +442,6 @@ img.emoji {
.min-height-0 { min-height: 0; }
-.w-3 { width: #{3 * $grid-size}; }
-
-.h-3 { width: #{3 * $grid-size}; }
-
.svg-w-100 {
svg {
width: 100%;
@@ -446,19 +449,13 @@ img.emoji {
}
/** COMMON SPACING CLASSES **/
-.gl-pl-0 { padding-left: 0; }
-.gl-pl-1 { padding-left: #{0.5 * $grid-size}; }
-.gl-pl-2 { padding-left: $grid-size; }
-.gl-pl-3 { padding-left: #{2 * $grid-size}; }
-.gl-pl-4 { padding-left: #{3 * $grid-size}; }
-.gl-pl-5 { padding-left: #{4 * $grid-size}; }
-
-.gl-pr-0 { padding-right: 0; }
-.gl-pr-1 { padding-right: #{0.5 * $grid-size}; }
-.gl-pr-2 { padding-right: $grid-size; }
-.gl-pr-3 { padding-right: #{2 * $grid-size}; }
-.gl-pr-4 { padding-right: #{3 * $grid-size}; }
-.gl-pr-5 { padding-right: #{4 * $grid-size}; }
+@each $index, $padding in $spacing-scale {
+ #{'.gl-p-#{$index}'} { padding: $padding; }
+ #{'.gl-pl-#{$index}'} { padding-left: $padding; }
+ #{'.gl-pr-#{$index}'} { padding-right: $padding; }
+ #{'.gl-pt-#{$index}'} { padding-top: $padding; }
+ #{'.gl-pb-#{$index}'} { padding-bottom: $padding; }
+}
/**
* Removes browser specific clear icon from input fields in
@@ -492,3 +489,50 @@ img.emoji {
.cursor-pointer {
cursor: pointer;
}
+
+// Make buttons/dropdowns full-width on mobile
+.full-width-mobile {
+ @include media-breakpoint-down(xs) {
+ width: 100%;
+
+ > .dropdown-menu,
+ > .btn {
+ width: 100%;
+ }
+ }
+}
+
+.onboarding-helper-container {
+ bottom: 40px;
+ right: 40px;
+ font-size: $gl-font-size-small;
+ background: $gray-100;
+ width: 200px;
+ border-radius: 24px;
+ box-shadow: 0 2px 4px $issue-boards-card-shadow;
+ z-index: 10000;
+
+ .collapsible {
+ max-height: 0;
+ transition: max-height 0.5s cubic-bezier(0, 1, 0, 1);
+ }
+
+ &.expanded {
+ border-bottom-right-radius: $border-radius-default;
+ border-bottom-left-radius: $border-radius-default;
+
+ .collapsible {
+ max-height: 1000px;
+ transition: max-height 1s ease-in-out;
+ }
+ }
+
+ .avatar {
+ border-color: darken($gray-normal, 10%);
+
+ img {
+ width: 32px;
+ height: 32px;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index b90db135b4a..cd951f67293 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -351,6 +351,10 @@
// Expects up to 3 digits on the badge
margin-right: 40px;
}
+
+ .dropdown-menu-content {
+ padding: $dropdown-item-padding-y $dropdown-item-padding-x;
+ }
}
.droplab-dropdown {
@@ -566,10 +570,10 @@
}
.dropdown-menu-close {
- right: 5px;
+ top: $gl-padding-4;
+ right: $gl-padding-8;
width: 20px;
height: 20px;
- top: -1px;
}
.dropdown-menu-close-icon {
diff --git a/app/assets/stylesheets/framework/feature_highlight.scss b/app/assets/stylesheets/framework/feature_highlight.scss
index 85cabf43e9e..f9b167669a6 100644
--- a/app/assets/stylesheets/framework/feature_highlight.scss
+++ b/app/assets/stylesheets/framework/feature_highlight.scss
@@ -39,7 +39,7 @@
display: none;
hr {
- margin: $gl-padding * 0.5 0;
+ margin: $gl-padding 0;
}
.btn-link {
@@ -71,9 +71,6 @@
.feature-highlight-popover {
width: 240px;
- padding: 0;
- border: 1px solid $border-color;
- box-shadow: 0 2px 4px $dropdown-shadow-color;
&.right > .arrow {
border-right-color: $border-color;
@@ -85,7 +82,7 @@
}
.feature-highlight-popover-sub-content {
- padding: 9px 14px;
+ padding: $gl-padding $gl-padding-12;
}
@include keyframes(pulse-highlight) {
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index 53d3645cd63..536a26a6ffe 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -241,6 +241,7 @@
*/
&.code {
padding: 0;
+ border-radius: 0 0 $border-radius-default $border-radius-default;
}
.list-inline.previews {
@@ -328,7 +329,7 @@ span.idiff {
background-color: $gray-light;
border-bottom: 1px solid $border-color;
border-top: 1px solid $border-color;
- padding: 5px $gl-padding;
+ padding: $gl-padding-8 $gl-padding;
margin: 0;
border-radius: $border-radius-default $border-radius-default 0 0;
@@ -365,10 +366,6 @@ span.idiff {
color: $gl-text-color;
}
- small {
- margin: 0 10px 0 0;
- }
-
.file-actions .btn {
padding: 0 10px;
font-size: 13px;
@@ -456,6 +453,28 @@ span.idiff {
}
}
+ .note-container {
+ .user-avatar-link.new-comment {
+ position: absolute;
+ margin: 40px $gl-padding 0 116px;
+
+ ~ .note-edit-form form.edit-note {
+ @include media-breakpoint-up(sm) {
+ margin-left: $note-icon-gutter-width;
+ }
+ }
+ }
+ }
+
+ .diff-discussions:not(:last-child) .discussion .discussion-body {
+ padding-bottom: $gl-padding;
+
+ .discussion-reply-holder {
+ border-bottom: 1px solid $gray-100;
+ border-radius: 0;
+ }
+ }
+
.md-previewer {
padding: $gl-padding;
}
diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss
index 5bcfd5d1322..26cbb7f5c13 100644
--- a/app/assets/stylesheets/framework/filters.scss
+++ b/app/assets/stylesheets/framework/filters.scss
@@ -218,7 +218,7 @@
min-width: 200px;
padding-right: 25px;
padding-left: 0;
- height: $input-height;
+ height: $input-height - 2;
line-height: inherit;
border-color: transparent;
diff --git a/app/assets/stylesheets/framework/flash.scss b/app/assets/stylesheets/framework/flash.scss
index afa85f0e4ae..e3dd127366d 100644
--- a/app/assets/stylesheets/framework/flash.scss
+++ b/app/assets/stylesheets/framework/flash.scss
@@ -6,6 +6,19 @@
position: relative;
z-index: 1;
+ .flash-notice,
+ .flash-alert,
+ .flash-success,
+ .flash-warning {
+ border-radius: $border-radius-default;
+ color: $white-light;
+
+ .container-fluid,
+ .container-fluid.container-limited {
+ background: transparent;
+ }
+ }
+
.flash-notice {
@extend .alert;
background-color: $blue-500;
@@ -28,7 +41,8 @@
.flash-warning {
@extend .alert;
- background-color: $orange-500;
+ background-color: $orange-100;
+ color: $orange-900;
margin: 0;
}
@@ -60,19 +74,6 @@
margin: 0;
}
- .flash-notice,
- .flash-alert,
- .flash-success,
- .flash-warning {
- border-radius: $border-radius-default;
- color: $white-light;
-
- .container-fluid,
- .container-fluid.container-limited {
- background: transparent;
- }
- }
-
&.flash-container-page {
margin-bottom: 0;
diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss
index be544c0a814..2a601afff53 100644
--- a/app/assets/stylesheets/framework/forms.scss
+++ b/app/assets/stylesheets/framework/forms.scss
@@ -27,10 +27,16 @@ input[type='text'].danger {
}
label {
+ font-weight: $gl-font-weight-bold;
+
&.inline-label {
margin: 0;
}
+ &.form-check-label {
+ font-weight: $gl-font-weight-normal;
+ }
+
&.label-bold {
font-weight: $gl-font-weight-bold;
}
@@ -41,14 +47,6 @@ label {
margin: 0;
}
-.form-label {
- @extend label;
-}
-
-.form-control-label {
- @extend .col-md-2;
-}
-
.inline-input-group {
width: 250px;
}
@@ -81,44 +79,14 @@ label {
margin-left: 0;
margin-right: 0;
- .form-control-label {
- font-weight: $gl-font-weight-bold;
- padding-top: 4px;
- }
-
.form-control {
height: 29px;
background: $white-light;
font-family: $monospace-font;
}
- .input-group-prepend .btn,
- .input-group-append .btn {
- padding: 3px $gl-btn-padding;
- background-color: $gray-light;
- border: 1px solid $border-color;
- }
-
- .text-block {
- line-height: 0.8;
- padding-top: 9px;
-
- code {
- line-height: 1.8;
- }
-
- img {
- margin-right: $gl-padding;
- }
- }
-
@include media-breakpoint-down(xs) {
padding: 0 $gl-padding;
-
- .form-control-label,
- .text-block {
- padding-left: 0;
- }
}
}
@@ -140,19 +108,6 @@ label {
}
}
-.select-wrapper {
- position: relative;
-
- .fa-chevron-down {
- position: absolute;
- font-size: 10px;
- right: 10px;
- top: 12px;
- color: $gray-darkest;
- pointer-events: none;
- }
-}
-
.select-control {
padding-left: 10px;
padding-right: 10px;
@@ -175,12 +130,6 @@ label {
margin-top: 35px;
}
-.form-group .form-control-label,
-.form-group .form-control-label-full-width {
- font-weight: $gl-font-weight-normal;
-}
-
-
.form-control::placeholder {
color: $gl-text-color-tertiary;
}
@@ -206,6 +155,7 @@ label {
.form-text.text-muted {
margin-bottom: 0;
margin-top: #{$grid-size / 2};
+ font-size: $gl-font-size;
}
.gl-field-error,
@@ -223,7 +173,8 @@ label {
border: 1px solid $green-600;
&:focus {
- box-shadow: 0 0 0 1px $green-600 inset, 0 1px 1px $gl-field-focus-shadow inset, 0 0 4px 0 $green-600;
+ box-shadow: 0 0 0 1px $green-600 inset, 0 1px 1px $gl-field-focus-shadow inset,
+ 0 0 4px 0 $green-600;
border: 0 none;
}
}
@@ -232,7 +183,8 @@ label {
border: 1px solid $red-500;
&:focus {
- box-shadow: 0 0 0 1px $red-500 inset, 0 1px 1px $gl-field-focus-shadow inset, 0 0 4px 0 $gl-field-focus-shadow-error;
+ box-shadow: 0 0 0 1px $red-500 inset, 0 1px 1px $gl-field-focus-shadow inset,
+ 0 0 4px 0 $gl-field-focus-shadow-error;
border: 0 none;
}
}
@@ -258,16 +210,26 @@ label {
}
}
-.input-icon-wrapper {
+.input-icon-wrapper,
+.select-wrapper {
position: relative;
+}
- .input-icon-right {
- position: absolute;
- right: 0.8em;
- top: 50%;
- transform: translateY(-50%);
- color: $gray-600;
- }
+.select-wrapper > .fa-chevron-down {
+ position: absolute;
+ font-size: 10px;
+ right: 10px;
+ top: 12px;
+ color: $gray-darkest;
+ pointer-events: none;
+}
+
+.input-icon-wrapper > .input-icon-right {
+ position: absolute;
+ right: 0.8em;
+ top: 50%;
+ transform: translateY(-50%);
+ color: $gray-600;
}
.input-md {
@@ -279,3 +241,21 @@ label {
max-width: $input-lg-width;
width: 100%;
}
+
+.input-group-text {
+ max-height: $input-height;
+}
+
+.gl-form-checkbox {
+ align-items: baseline;
+
+ &.form-check-inline .form-check-input {
+ align-self: flex-start;
+ margin-right: $gl-padding-8;
+ height: 1.5 * $gl-font-size;
+ }
+
+ .help-text {
+ margin-bottom: 0;
+ }
+}
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 1e025b3a67d..1bc597bd4ae 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -447,29 +447,44 @@
}
}
+.title-container,
.navbar-nav {
- li {
- .badge.badge-pill {
- position: inherit;
- font-weight: $gl-font-weight-normal;
- margin-left: -6px;
- font-size: 11px;
- color: $white-light;
- padding: 0 5px;
- line-height: 12px;
- border-radius: 7px;
- box-shadow: 0 1px 0 rgba($gl-header-color, 0.2);
-
- &.issues-count {
- background-color: $green-500;
- }
+ .badge.badge-pill {
+ position: inherit;
+ font-weight: $gl-font-weight-normal;
+ margin-left: -6px;
+ font-size: 11px;
+ color: $white-light;
+ padding: 0 5px;
+ line-height: 12px;
+ border-radius: 7px;
+ box-shadow: 0 1px 0 rgba($gl-header-color, 0.2);
+
+ &.green-badge {
+ background-color: $green-500;
+ }
- &.merge-requests-count {
- background-color: $orange-600;
- }
+ &.merge-requests-count {
+ background-color: $orange-600;
+ }
- &.todos-count {
- background-color: $blue-500;
+ &.todos-count {
+ background-color: $blue-500;
+ }
+ }
+
+ .canary-badge {
+ .badge {
+ font-size: $gl-font-size-small;
+ line-height: $gl-line-height;
+ padding: 0 $grid-size;
+ }
+
+ &:hover {
+ text-decoration: none;
+
+ .badge {
+ text-decoration: none;
}
}
}
@@ -582,10 +597,15 @@
.emoji-menu-toggle-button {
@include emoji-menu-toggle-button;
+ padding: $gl-vert-padding $gl-btn-padding;
}
.input-group {
- height: 34px;
+ &,
+ .input-group-prepend,
+ .input-group-append {
+ height: $input-height;
+ }
}
}
diff --git a/app/assets/stylesheets/framework/highlight.scss b/app/assets/stylesheets/framework/highlight.scss
index 946f575ac13..983bd032da4 100644
--- a/app/assets/stylesheets/framework/highlight.scss
+++ b/app/assets/stylesheets/framework/highlight.scss
@@ -8,10 +8,10 @@
pre {
padding: 10px 0;
border: 0;
- border-radius: 0;
+ border-radius: 0 0 $border-radius-default $border-radius-default;
font-family: $monospace-font;
font-size: $code-font-size;
- line-height: 19px;
+ line-height: 1.5;
margin: 0;
overflow: auto;
overflow-y: hidden;
@@ -30,7 +30,7 @@
.line {
display: block;
width: 100%;
- min-height: 19px;
+ min-height: 1.5em;
padding-left: 10px;
padding-right: 10px;
white-space: pre;
@@ -42,12 +42,13 @@
padding: 10px;
text-align: right;
float: left;
+ border-bottom-left-radius: $border-radius-default;
a {
font-family: $monospace-font;
display: block;
font-size: $code-font-size !important;
- min-height: 19px;
+ min-height: 1.5em;
white-space: nowrap;
i {
diff --git a/app/assets/stylesheets/framework/issue_box.scss b/app/assets/stylesheets/framework/issue_box.scss
index e51f230a680..1a38f3ccce4 100644
--- a/app/assets/stylesheets/framework/issue_box.scss
+++ b/app/assets/stylesheets/framework/issue_box.scss
@@ -16,10 +16,10 @@
margin-top: 5px;
}
- border-radius: 3px;
+ border-radius: $border-radius-default;
display: block;
float: left;
- margin-right: 10px;
+ margin-right: $gl-padding-8;
color: $white-light;
font-size: $gl-font-size;
line-height: $gl-line-height-24;
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index 298610a0631..555a3fe0dc7 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -177,14 +177,6 @@ ul.content-list {
}
}
- .member-controls {
- float: none;
-
- @include media-breakpoint-up(sm) {
- float: right;
- }
- }
-
// When dragging a list item
&.ui-sortable-helper {
border-bottom: 0;
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index 18eb10c1f23..ad5096761cd 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -218,16 +218,22 @@
}
}
-@mixin build-trace-top-bar($height) {
+// Used in EE for Web Terminal
+@mixin build-trace-bar($height) {
height: $height;
min-height: $height;
background: $gray-light;
border: 1px solid $border-color;
color: $gl-text-color;
+ padding: $grid-size;
+}
+
+@mixin build-trace-top-bar($height) {
+ @include build-trace-bar($height);
+
position: -webkit-sticky;
position: sticky;
top: $header-height;
- padding: $grid-size;
.with-performance-bar & {
top: $header-height + $performance-bar-height;
@@ -325,8 +331,8 @@
line-height: 1;
padding: 0;
min-width: 16px;
- color: $gray-darkest;
- fill: $gray-darkest;
+ color: $gray-600;
+ fill: $gray-600;
.fa {
position: relative;
@@ -376,3 +382,28 @@
}
}
}
+
+/*
+* Mixin that handles the size and right margin of avatars.
+*/
+@mixin avatar-size($size, $margin-right) {
+ width: $size;
+ height: $size;
+ margin-right: $margin-right;
+}
+
+@mixin code-icon-size() {
+ width: $gl-font-size * $code-line-height * 0.9;
+ height: $gl-font-size * $code-line-height * 0.9;
+}
+
+@mixin avatar-counter($border-radius: 1em) {
+ background-color: $gray-darkest;
+ color: $white-light;
+ border: 1px solid $gray-normal;
+ border-radius: $border-radius;
+ font-family: $regular-font;
+ font-size: 9px;
+ line-height: 16px;
+ text-align: center;
+}
diff --git a/app/assets/stylesheets/framework/modal.scss b/app/assets/stylesheets/framework/modal.scss
index 53222a2bd4d..f75e5b55506 100644
--- a/app/assets/stylesheets/framework/modal.scss
+++ b/app/assets/stylesheets/framework/modal.scss
@@ -34,10 +34,10 @@
.modal-body {
background-color: $modal-body-bg;
line-height: $line-height-base;
- min-height: $modal-body-height;
position: relative;
padding: #{3 * $grid-size} #{2 * $grid-size};
text-align: left;
+ white-space: normal;
.form-actions {
margin: #{2 * $grid-size} #{-2 * $grid-size} #{-2 * $grid-size};
@@ -53,7 +53,8 @@
flex-direction: row;
.btn + .btn:not(.dropdown-toggle-split),
- .btn + .btn-group {
+ .btn + .btn-group,
+ .btn-group + .btn {
margin-left: $grid-size;
}
@@ -61,17 +62,12 @@
flex-direction: column;
.btn + .btn:not(.dropdown-toggle-split),
- .btn + .btn-group {
+ .btn + .btn-group,
+ .btn-group + .btn {
margin-left: 0;
margin-top: $grid-size;
}
}
-
- @include media-breakpoint-up(sm) {
- .btn:nth-child(1) {
- margin-left: auto;
- }
- }
}
body.modal-open {
diff --git a/app/assets/stylesheets/framework/secondary_navigation_elements.scss b/app/assets/stylesheets/framework/secondary_navigation_elements.scss
index 31297b9d20c..ada8f2fe1a6 100644
--- a/app/assets/stylesheets/framework/secondary_navigation_elements.scss
+++ b/app/assets/stylesheets/framework/secondary_navigation_elements.scss
@@ -13,8 +13,8 @@
a,
button {
- padding: $gl-btn-padding;
- padding-bottom: 11px;
+ padding: $gl-padding-8;
+ padding-bottom: $gl-padding-8 + 1;
font-size: 14px;
line-height: 28px;
color: $gl-text-color-secondary;
@@ -58,8 +58,12 @@
}
.top-area {
- @include clearfix;
border-bottom: 1px solid $border-color;
+ display: flex;
+
+ @include media-breakpoint-down(md) {
+ flex-flow: column-reverse wrap;
+ }
.nav-text {
padding-top: 16px;
@@ -75,9 +79,8 @@
}
.nav-links {
- margin-bottom: 0;
border-bottom: 0;
- float: left;
+ flex: 1;
&.wide {
width: 100%;
@@ -98,16 +101,23 @@
&.mobile-separator {
border-bottom: 1px solid $border-color;
+ margin-bottom: $gl-padding-8;
}
}
}
.nav-controls {
display: inline-block;
- float: right;
text-align: right;
- padding: $gl-padding-8 0;
- margin-bottom: 0;
+
+ @include media-breakpoint-down(sm) {
+ margin-top: $gl-padding-8;
+ }
+
+ @include media-breakpoint-up(md) {
+ display: flex;
+ align-items: center;
+ }
> .btn,
> .btn-container,
@@ -115,8 +125,6 @@
> input,
> form {
margin-right: $gl-padding-top;
- display: inline-block;
- vertical-align: top;
&:last-child {
margin-right: 0;
@@ -143,7 +151,7 @@
@include media-breakpoint-up(lg) { width: 250px; }
}
- @include media-breakpoint-down(xs) {
+ @include media-breakpoint-down(sm) {
padding-bottom: 0;
width: 100%;
@@ -153,7 +161,7 @@
.dropdown-toggle,
.dropdown-menu-toggle,
.form-control {
- margin: 0 0 10px;
+ margin: 0 0 $gl-padding-8;
display: block;
width: 100%;
}
@@ -165,7 +173,7 @@
form {
display: block;
height: auto;
- margin-bottom: 14px;
+ margin-bottom: $gl-padding-8;
input {
width: 100%;
@@ -236,20 +244,11 @@
width: 100%;
}
- @include media-breakpoint-down(xs) {
- flex-flow: row wrap;
-
+ @include media-breakpoint-down(md) {
.nav-controls {
$controls-margin: $btn-margin-5 - 2px;
flex: 0 0 100%;
-
- &.controls-flex {
- display: flex;
- flex-flow: row wrap;
- align-items: center;
- justify-content: center;
- padding: 0 0 $gl-padding-top;
- }
+ margin-top: $gl-padding-8;
.controls-item,
.controls-item-full,
@@ -326,8 +325,8 @@
.fade-right,
.fade-left {
- top: 16px;
- bottom: auto;
+ bottom: $gl-padding;
+ top: auto;
}
&.is-smaller {
@@ -367,6 +366,7 @@
display: flex;
border-bottom: 1px solid $border-color;
overflow: hidden;
+ align-items: center;
.nav-links {
border-bottom: 0;
diff --git a/app/assets/stylesheets/framework/snippets.scss b/app/assets/stylesheets/framework/snippets.scss
index 36ab38f1c9d..3ab83f4c8e6 100644
--- a/app/assets/stylesheets/framework/snippets.scss
+++ b/app/assets/stylesheets/framework/snippets.scss
@@ -22,6 +22,10 @@
.snippet-file-content {
border-radius: 3px;
+
+ .file-title-flex-parent .btn-clipboard {
+ line-height: 28px;
+ }
}
.snippet-header {
diff --git a/app/assets/stylesheets/framework/timeline.scss b/app/assets/stylesheets/framework/timeline.scss
index 3d5208c3db5..42a739e88f7 100644
--- a/app/assets/stylesheets/framework/timeline.scss
+++ b/app/assets/stylesheets/framework/timeline.scss
@@ -42,8 +42,8 @@
}
}
- .avatar {
- margin-right: 15px;
+ img.avatar {
+ margin-right: $gl-padding;
}
.controls {
@@ -55,4 +55,5 @@
.discussion .timeline-entry {
margin: 0;
border-right: 0;
+ border-radius: $border-radius-default $border-radius-default 0 0;
}
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index 244b414d334..9e1431963d9 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -403,6 +403,7 @@ code {
.git-revision-dropdown .dropdown-content ul li a {
@extend .ref-name;
+ word-break: break-all;
}
/**
@@ -473,3 +474,7 @@ textarea {
/* stylelint-enable */
.lh-100 { line-height: 1; }
+
+wbr {
+ display: inline-block;
+}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index da1f196afdb..b6a24247d40 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -11,6 +11,14 @@ $default-transition-duration: 0.15s;
$contextual-sidebar-width: 220px;
$contextual-sidebar-collapsed-width: 50px;
$toggle-sidebar-height: 48px;
+$spacing-scale: (
+ 0: 0,
+ 1: #{0.5 * $grid-size},
+ 2: $grid-size,
+ 3: #{2 * $grid-size},
+ 4: #{3 * $grid-size},
+ 5: #{4 * $grid-size}
+);
/*
* Color schema
@@ -328,6 +336,7 @@ $tooltip-font-size: 12px;
*/
$gl-padding-4: 4px;
$gl-padding-8: 8px;
+$gl-padding-12: 12px;
$gl-padding: 16px;
$gl-padding-24: 24px;
$gl-padding-32: 32px;
@@ -373,6 +382,7 @@ $breadcrumb-min-height: 48px;
$home-panel-title-row-height: 64px;
$home-panel-avatar-mobile-size: 24px;
$gl-line-height: 16px;
+$gl-line-height-20: 20px;
$gl-line-height-24: 24px;
$gl-line-height-14: 14px;
@@ -424,7 +434,7 @@ $diff-jagged-border-gradient-color: darken($white-normal, 8%);
*/
$monospace-font: 'Menlo', 'DejaVu Sans Mono', 'Liberation Mono', 'Consolas', 'Ubuntu Mono',
'Courier New', 'andale mono', 'lucida console', monospace;
-$regular-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell,
+$regular-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Noto Sans', Ubuntu, Cantarell,
'Helvetica Neue', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
'Noto Color Emoji';
@@ -490,6 +500,17 @@ $pagination-line-height: 20px;
$pagination-disabled-color: #cdcdcd;
/*
+* Toasts
+*/
+$toast-offset: 24px;
+$toast-height: 48px;
+$toast-max-width: 586px;
+$toast-padding-right: 42px;
+$toast-default-margin: 8px;
+$toast-action-margin-left: 16px;
+$toast-background-opacity: 0.95;
+
+/*
* Status icons
*/
$status-icon-size: 22px;
@@ -570,6 +591,7 @@ $issue-board-list-difference-md: $issue-board-list-difference-sm + $issue-boards
*/
$avatar-radius: 50%;
$gl-avatar-size: 40px;
+$gl-avatar-border-opacity: 0.1;
/*
* Blame
@@ -620,6 +642,7 @@ $input-lg-width: 320px;
*/
$document-index-color: #888;
$help-shortcut-header-color: #333;
+$accepting-mr-label-color: #69d100;
/*
* Issues
@@ -788,6 +811,11 @@ $modal-border-color: #e9ecef;
$priority-label-empty-state-width: 114px;
/*
+Popovers
+*/
+$popover-max-width: 384px;
+
+/*
Issues Analytics
*/
$issues-analytics-popover-boarder-color: rgba(0, 0, 0, 0.15);
@@ -795,7 +823,7 @@ $issues-analytics-popover-boarder-color: rgba(0, 0, 0, 0.15);
/*
Merge Requests
*/
-$mr-tabs-height: 51px;
+$mr-tabs-height: 48px;
$mr-version-controls-height: 56px;
/*
diff --git a/app/assets/stylesheets/framework/variables_overrides.scss b/app/assets/stylesheets/framework/variables_overrides.scss
index fb4d3f23cd9..ea96381a098 100644
--- a/app/assets/stylesheets/framework/variables_overrides.scss
+++ b/app/assets/stylesheets/framework/variables_overrides.scss
@@ -7,6 +7,7 @@ $secondary: $gray-light;
$input-disabled-bg: $gray-light;
$input-border-color: $gray-200;
$input-color: $gl-text-color;
+$input-font-size: $gl-font-size;
$font-family-sans-serif: $regular-font;
$font-family-monospace: $monospace-font;
$btn-line-height: 20px;
diff --git a/app/assets/stylesheets/page_bundles/_ide_mixins.scss b/app/assets/stylesheets/page_bundles/_ide_mixins.scss
index 896a3466cb4..9465dd5bed6 100644
--- a/app/assets/stylesheets/page_bundles/_ide_mixins.scss
+++ b/app/assets/stylesheets/page_bundles/_ide_mixins.scss
@@ -2,17 +2,17 @@
display: flex;
flex-direction: column;
height: 100%;
- margin-top: -$grid-size;
- margin-bottom: -$grid-size;
- &.build-page .top-bar {
+ .top-bar {
+ @include build-trace-bar(35px);
+
top: 0;
- height: auto;
font-size: 12px;
border-top-right-radius: $border-radius-default;
- }
-
- .top-bar {
margin-left: -$gl-padding;
+
+ .controllers {
+ @include build-controllers(15px, center, false, 0, inline, 0);
+ }
}
}
diff --git a/app/assets/stylesheets/page_bundles/ide.scss b/app/assets/stylesheets/page_bundles/ide.scss
index 0c1067bfacc..cbcd8a474f1 100644
--- a/app/assets/stylesheets/page_bundles/ide.scss
+++ b/app/assets/stylesheets/page_bundles/ide.scss
@@ -396,10 +396,6 @@ $ide-commit-header-height: 48px;
font-size: inherit;
}
- > div + div {
- padding-left: $gl-padding;
- }
-
svg {
vertical-align: sub;
}
@@ -410,13 +406,14 @@ $ide-commit-header-height: 48px;
}
}
+.ide-status-list {
+ > div + div {
+ padding-left: $gl-padding;
+ }
+}
+
.ide-status-file {
text-align: right;
-
- .ide-status-branch + &,
- &:first-child {
- margin-left: auto;
- }
}
// Not great, but this is to deal with our current output
.multi-file-preview-holder {
@@ -719,7 +716,7 @@ $ide-commit-header-height: 48px;
border: 1px solid $white-dark;
}
-.ide-commit-radios {
+.ide-commit-options {
label {
font-weight: normal;
diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss
index fc1c1bd9962..5e3652db48f 100644
--- a/app/assets/stylesheets/pages/boards.scss
+++ b/app/assets/stylesheets/pages/boards.scss
@@ -1,7 +1,3 @@
-[v-cloak] {
- display: none;
-}
-
.user-can-drag {
cursor: grab;
}
@@ -11,6 +7,9 @@
opacity: 1 !important;
* {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
user-select: none;
// !important to make sure no style can override this when dragging
cursor: grabbing !important;
@@ -32,43 +31,24 @@
width: 320px;
.dropdown-content {
- max-height: 162px;
+ max-height: 140px;
}
}
.issue-board-dropdown-content {
- margin: 0 8px 10px;
- padding-bottom: 10px;
- border-bottom: 1px solid $dropdown-divider-bg;
-
- > p {
- margin: 0;
- font-size: 14px;
- }
+ margin: 0;
+ padding: $gl-padding-4 $gl-padding $gl-padding;
+ border-bottom: 0;
+ color: $gl-text-color-secondary;
}
.issue-boards-page {
.content-wrapper {
padding-bottom: 0;
}
-
- .issues-details-filters {
- display: flex;
- }
-
- .filter-form {
- width: 100%;
- }
-}
-
-.board-extra-actions {
- font-size: 0;
- white-space: nowrap;
}
.boards-app {
- position: relative;
-
@include media-breakpoint-up(sm) {
transition: width $sidebar-transition-duration;
width: 100%;
@@ -79,17 +59,9 @@
}
}
-.boards-app-loading {
- width: 100%;
- font-size: 34px;
-}
-
.boards-list {
height: calc(100vh - #{$issue-board-list-difference-xs});
- width: 100%;
- padding: $gl-padding ($gl-padding / 2);
overflow-x: scroll;
- white-space: nowrap;
min-height: 200px;
@include media-breakpoint-only(sm) {
@@ -114,13 +86,7 @@
}
.board {
- display: inline-block;
width: calc(85vw - 15px);
- height: 100%;
- padding-right: ($gl-padding / 2);
- padding-left: ($gl-padding / 2);
- white-space: normal;
- vertical-align: top;
@include media-breakpoint-up(sm) {
width: 400px;
@@ -135,23 +101,7 @@
&.is-collapsed {
width: 50px;
- .board-header {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
-
- button {
- display: none;
- }
- }
-
.board-title {
- padding: 0;
- border-bottom: 0;
- justify-content: center;
-
> span {
width: 100%;
margin-top: -12px;
@@ -167,34 +117,16 @@
left: 50%;
margin-left: -10px;
}
-
- .board-list-component,
- .issue-count-badge {
- display: none;
- }
- }
-
- &:not(.is-collapsed) {
- .board-list-component {
- display: flex;
- flex-direction: column;
- }
}
}
.board-inner {
- position: relative;
- height: 100%;
font-size: $issue-boards-font-size;
background: $gray-light;
border: 1px solid $border-color;
- border-radius: $border-radius-default;
- flex: 1;
}
.board-header {
- position: relative;
-
&.has-border::before {
border-top: 3px solid;
border-color: inherit;
@@ -219,18 +151,9 @@
}
}
-.board-inner-container {
- border-bottom: 1px solid $border-color;
- padding: $gl-padding;
-}
-
.board-title {
- margin: 0;
- padding: $gl-padding-8 $gl-padding;
font-size: 1em;
border-bottom: 1px solid $border-color;
- display: flex;
- align-items: center;
}
.board-title-text {
@@ -239,10 +162,8 @@
.board-delete {
margin-right: 10px;
- padding: 0;
color: $gray-darkest;
background-color: transparent;
- border: 0;
outline: 0;
&:hover {
@@ -252,7 +173,6 @@
.board-blank-state,
.board-promotion-state {
- padding: $gl-padding;
background-color: $white-light;
flex: 1;
overflow-y: auto;
@@ -260,35 +180,23 @@
}
.board-blank-state-list {
- list-style: none;
-
> li:not(:last-child) {
margin-bottom: 8px;
}
.label-color {
- position: relative;
top: 2px;
- display: inline-block;
width: 16px;
height: 16px;
margin-right: 3px;
- border-radius: $border-radius-default;
}
}
.board-list-component {
- position: relative;
- flex: 1;
min-height: 0; // firefox fix
}
.board-list {
- height: 100%;
- width: 100%;
- margin-bottom: 0;
- padding: $gl-padding-4;
- list-style: none;
overflow-y: auto;
overflow-x: hidden;
}
@@ -299,14 +207,11 @@
}
.board-card {
- position: relative;
- padding: $gl-padding;
background: $white-light;
- border-radius: $border-radius-default;
border: 1px solid $gray-200;
box-shadow: 0 1px 2px $issue-boards-card-shadow;
- list-style: none;
line-height: $gl-padding;
+ list-style: none;
&:not(:last-child) {
margin-bottom: $gl-padding-8;
@@ -333,10 +238,6 @@
}
}
- svg {
- vertical-align: top;
- }
-
.confidential-icon {
color: $orange-600;
cursor: help;
@@ -361,11 +262,10 @@
}
.board-card-header {
- display: flex;
+ text-align: initial;
}
.board-card-assignee {
- display: flex;
margin-top: -$gl-padding-4;
margin-bottom: -$gl-padding-4;
@@ -425,34 +325,16 @@
.board-card-number {
font-size: $gl-font-size-xs;
color: $gl-text-color-secondary;
- overflow: hidden;
@include media-breakpoint-up(md) {
font-size: $label-font-size;
}
}
-.board-card-number-container {
- overflow: hidden;
-}
-
-.issue-boards-search {
- width: 395px;
-
- .form-control {
- display: inline-block;
- width: 210px;
- }
-}
-
.board-list-count {
padding: 10px 0;
color: $gl-text-color-secondary;
font-size: 13px;
-
- > .fa {
- margin-right: 5px;
- }
}
.board-new-issue-form {
@@ -460,16 +342,9 @@
margin: 5px;
}
-.page-with-contextual-sidebar.layout-page .issue-boards-sidebar {
- .issuable-sidebar-header {
- position: relative;
- }
-
+.issue-boards-sidebar {
.gutter-toggle {
- position: absolute;
- top: 0;
bottom: 15px;
- right: 0;
width: 22px;
color: $gray-darkest;
@@ -489,10 +364,6 @@
.issuable-header-text {
@include overflow-break-word();
padding-right: 35px;
-
- > strong {
- font-weight: $gl-font-weight-bold;
- }
}
}
@@ -511,44 +382,25 @@
}
.add-issues-modal {
- display: flex;
- position: fixed;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
background-color: rgba($black, 0.3);
z-index: 9999;
}
.add-issues-container {
- display: flex;
- flex-direction: column;
width: 90vw;
height: 85vh;
max-width: 1100px;
min-height: 500px;
- margin: auto;
padding: 25px 15px 0;
background-color: $white-light;
- border-radius: $border-radius-default;
box-shadow: 0 2px 12px rgba($black, 0.5);
.empty-state {
- display: flex;
- flex: 1;
- margin-top: 0;
-
&.add-issues-empty-state-filter {
flex-direction: column;
justify-content: center;
}
- > .row {
- width: 100%;
- margin: auto 0;
- }
-
.svg-content {
margin-top: -40px;
}
@@ -557,25 +409,15 @@
.add-issues-header {
margin: -25px -15px -5px;
- border-top: 0;
border-bottom: 1px solid $border-color;
border-top-right-radius: $border-radius-default;
border-top-left-radius: $border-radius-default;
> h2 {
- margin: 0;
font-size: 18px;
}
}
-.add-issues-search {
- display: flex;
-
- .issues-filters {
- flex: 1;
- }
-}
-
.add-issues-list-column {
width: 100%;
@@ -589,8 +431,6 @@
}
.add-issues-list {
- display: flex;
- flex: 1;
padding-top: 3px;
margin-left: -$gl-vert-padding;
margin-right: -$gl-vert-padding;
@@ -607,14 +447,6 @@
}
}
-.add-issues-list-loading {
- align-self: center;
- width: 100%;
- padding-left: $gl-vert-padding;
- padding-right: $gl-vert-padding;
- font-size: 35px;
-}
-
.add-issues-footer {
margin: auto -15px 0;
padding-left: 15px;
@@ -642,27 +474,6 @@
border-radius: 50%;
}
-.modal-filters {
- display: flex;
-
- > .dropdown {
- display: none;
- margin-right: 10px;
-
- @include media-breakpoint-up(sm) {
- display: block;
- }
- }
-
- .dropdown-menu-toggle {
- width: 100px;
-
- @include media-breakpoint-up(md) {
- width: 140px;
- }
- }
-}
-
.board-card-info {
color: $gl-text-color-secondary;
white-space: nowrap;
diff --git a/app/assets/stylesheets/pages/clusters.scss b/app/assets/stylesheets/pages/clusters.scss
index 809ba6d4953..255383d89c8 100644
--- a/app/assets/stylesheets/pages/clusters.scss
+++ b/app/assets/stylesheets/pages/clusters.scss
@@ -69,6 +69,8 @@
align-self: flex-start;
font-weight: 500;
font-size: 20px;
+ color: $orange-900;
+ opacity: 1;
margin: $gl-padding-8 14px 0 0;
}
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index 670e320dbc2..e12ea6fcb99 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -58,14 +58,6 @@
display: inline-block;
vertical-align: middle;
- .stage-cell .stage-container {
- margin: 0 3px 3px 0;
- }
-
- .stage-container:last-child {
- margin-right: 0;
- }
-
.dropdown-menu {
margin-top: 11px;
}
@@ -128,18 +120,9 @@
}
.commit-row-title {
- .notes_count {
- float: right;
- margin-right: 10px;
- }
-
.str-truncated {
max-width: 70%;
}
-
- .commit-row-message {
- color: $gl-text-color;
- }
}
.text-expander {
@@ -171,8 +154,6 @@
}
.avatar-cell {
- width: 46px;
-
img {
margin-right: 0;
}
@@ -185,7 +166,7 @@
flex-grow: 1;
min-width: 0;
- .project_namespace {
+ .project-namespace {
color: $gl-text-color-secondary;
}
}
@@ -199,6 +180,14 @@
display: flex;
align-items: center;
}
+
+ .committer {
+ color: $gl-text-color-tertiary;
+
+ .commit-author-link {
+ color: $gl-text-color;
+ }
+ }
}
.commit-actions {
@@ -208,10 +197,6 @@
}
}
- .ci-status-link {
- display: inline-flex;
- }
-
.ci-status-icon svg {
vertical-align: text-bottom;
}
@@ -239,7 +224,6 @@
}
.label-monospace {
- @extend .monospace;
user-select: text;
color: $gl-text-color;
background-color: $gray-light;
@@ -266,7 +250,7 @@
}
.commit,
-.generic_commit_status {
+.generic-commit-status {
a,
button {
vertical-align: baseline;
@@ -278,37 +262,22 @@
&.autodevops-badge {
color: $white-light;
}
-
- &.autodevops-link {
- color: $blue-600;
- }
}
.commit-row-description {
@extend %commit-description-base;
display: none;
flex: 1;
-
- a {
- color: $gl-text-color;
- }
}
&.inline-commit {
.commit-row-title {
font-size: 13px;
}
-
- .committed_ago {
- @extend .cgray;
- float: right;
- }
}
}
.branch-commit {
- color: $gl-text-color;
-
.commit-icon {
text-align: center;
display: inline-block;
@@ -320,14 +289,15 @@
fill: $gl-text-color-secondary;
}
}
+}
+.commit,
+.generic-commit-status,
+.branch-commit {
+ .autodevops-link,
.commit-sha {
color: $blue-600;
}
-
- .commit-row-message {
- color: $gl-text-color;
- }
}
.gpg-status-box {
diff --git a/app/assets/stylesheets/pages/detail_page.scss b/app/assets/stylesheets/pages/detail_page.scss
index cb5f1a84005..62fc7311d94 100644
--- a/app/assets/stylesheets/pages/detail_page.scss
+++ b/app/assets/stylesheets/pages/detail_page.scss
@@ -9,7 +9,6 @@
color: $gl-text-color;
}
- .issue_created_ago,
.author-link {
white-space: nowrap;
}
@@ -21,7 +20,6 @@
.detail-page-header-body {
position: relative;
- line-height: 35px;
display: flex;
flex: 1 1;
min-width: 0;
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index 5ea96392afa..4ebf1019456 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -15,7 +15,6 @@
position: sticky;
top: $mr-file-header-top;
z-index: 102;
- height: $mr-version-controls-height;
&::before {
content: '';
@@ -431,9 +430,9 @@ table.code {
&.diff-line-num {
user-select: none;
margin: 0;
- border: 0;
padding: 0 10px 0 5px;
- border-right: 1px solid;
+ border-right-width: 1px;
+ border-right-style: solid;
text-align: right;
width: 50px;
position: relative;
@@ -494,6 +493,12 @@ table.code {
}
}
+ .line_holder:last-of-type {
+ td:first-child {
+ border-bottom-left-radius: $border-radius-default;
+ }
+ }
+
&.left-side-selected {
td.line_content.parallel.right-side {
user-select: none;
@@ -609,10 +614,9 @@ table.code {
.diff-comment-avatar-holders {
position: absolute;
- height: 19px;
- width: 19px;
- margin-left: -15px;
+ margin-left: -$gl-padding;
z-index: 100;
+ @include code-icon-size();
&:hover {
.diff-comment-avatar,
@@ -646,40 +650,45 @@ table.code {
.diff-comments-more-count {
position: absolute;
left: 0;
- width: 19px;
- height: 19px;
margin-right: 0;
border-color: $white-light;
cursor: pointer;
transition: all 0.1s ease-out;
+ @include code-icon-size();
@for $i from 1 through 4 {
&:nth-child(#{$i}) {
z-index: (4 - $i);
}
}
+
+ .avatar {
+ @include code-icon-size();
+ }
}
.diff-comments-more-count {
- width: 19px;
- min-width: 19px;
padding-left: 0;
padding-right: 0;
overflow: hidden;
+ @include code-icon-size();
}
.diff-comments-more-count,
.diff-notes-collapse {
- @extend .avatar-counter;
+ @include avatar-counter(50%);
}
.diff-notes-collapse {
- width: 24px;
- height: 24px;
+ border: 0;
border-radius: 50%;
padding: 0;
transition: transform 0.1s ease-out;
z-index: 100;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ @include code-icon-size();
.collapse-icon {
height: 50%;
@@ -999,6 +1008,10 @@ table.code {
display: block;
}
}
+
+ .note-edit-form {
+ margin-left: $note-icon-gutter-width;
+ }
}
.discussion-body .image .frame {
diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss
index 618f23d81b1..500f5816d38 100644
--- a/app/assets/stylesheets/pages/events.scss
+++ b/app/assets/stylesheets/pages/events.scss
@@ -8,7 +8,7 @@
border-bottom: 1px solid $white-normal;
color: $gl-text-color-secondary;
position: relative;
- line-height: $gl-line-height;
+ line-height: $gl-line-height-20;
.system-note-image {
position: absolute;
@@ -48,7 +48,7 @@
}
.event-user-info {
- margin-bottom: $gl-padding-8;
+ margin-bottom: $gl-padding-4;
.author_name {
a {
@@ -67,7 +67,7 @@
}
.event-body {
- margin-top: $gl-padding-8;
+ margin-top: $gl-padding-4;
margin-right: 174px;
color: $gl-text-color;
@@ -156,6 +156,10 @@
&:hover {
background: none;
}
+
+ a {
+ color: $blue-600;
+ }
}
}
}
diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss
index 0a07747e0d4..656202f4e58 100644
--- a/app/assets/stylesheets/pages/groups.scss
+++ b/app/assets/stylesheets/pages/groups.scss
@@ -35,9 +35,6 @@
}
.group-nav-container .nav-controls {
- align-items: flex-start;
- padding: $gl-padding-top 0 0;
-
.group-filter-form {
flex: 1 1 auto;
margin-right: $gl-padding-8;
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index f8620eec46d..dcbb23684d1 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -60,6 +60,7 @@
overflow-wrap: break-word;
min-width: 0;
width: 100%;
+ text-align: initial;
}
.btn-edit {
@@ -68,7 +69,11 @@
}
.emoji-block {
- padding: 10px 0;
+ padding: $gl-padding-4 0;
+
+ @include media-breakpoint-down(md) {
+ padding: $gl-padding-8 0;
+ }
}
}
@@ -131,6 +136,10 @@
z-index: 200;
overflow: hidden;
+ @include media-breakpoint-down(sm) {
+ z-index: 251;
+ }
+
a:not(.btn) {
color: inherit;
@@ -217,7 +226,7 @@
.title {
color: $gl-text-color;
- margin-bottom: 10px;
+ margin-bottom: $gl-padding-8;
line-height: 1;
.avatar {
@@ -603,7 +612,6 @@
.participants-list {
display: flex;
flex-wrap: wrap;
- margin: -7px;
}
.user-list {
@@ -613,7 +621,7 @@
.participants-author {
display: inline-block;
- padding: 7px;
+ padding: 0 $gl-padding-8 $gl-padding-8 0;
&:nth-of-type(7n) {
padding-right: 0;
@@ -640,7 +648,6 @@
.participants-more,
.user-list-more {
- margin-top: 5px;
margin-left: 5px;
a,
@@ -675,8 +682,7 @@
justify-content: center;
align-items: center;
margin-top: 0;
- padding-left: 9px;
- padding-right: 9px;
+ padding: 0 $gl-padding-8;
@include media-breakpoint-up(sm) {
display: inline-block;
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index c7d2369a6b8..48289c8f381 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -258,8 +258,15 @@ ul.related-merge-requests > li {
}
}
-.discussion-reply-holder .note-edit-form {
- display: block;
+.discussion-reply-holder {
+ .avatar-note-form-holder .note-edit-form {
+ display: block;
+ margin-left: $note-icon-gutter-width;
+
+ @include media-breakpoint-down(xs) {
+ margin-left: 0;
+ }
+ }
}
.issue-sort-dropdown {
diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss
index e3d0d0b0fa2..11e8a32389f 100644
--- a/app/assets/stylesheets/pages/labels.scss
+++ b/app/assets/stylesheets/pages/labels.scss
@@ -75,7 +75,7 @@
padding: 0;
margin-bottom: 0;
- > li:not(.empty-message):not(.is-not-draggable) {
+ > li:not(.empty-message):not(.no-border) {
background-color: $white-light;
margin-bottom: 5px;
display: flex;
@@ -92,7 +92,7 @@
opacity: 0.3;
}
- .prioritized-labels & {
+ .prioritized-labels:not(.is-not-draggable) & {
box-shadow: 0 1px 2px $issue-boards-card-shadow;
cursor: move;
cursor: grab;
@@ -353,7 +353,7 @@
@media (max-width: map-get($grid-breakpoints, md)-1) {
.manage-labels-list {
- > li:not(.empty-message):not(.is-not-draggable) {
+ > li:not(.empty-message):not(.no-border) {
flex-wrap: wrap;
}
@@ -456,7 +456,10 @@
// Don't hide the overflow in system messages
.system-note-message,
-.issuable-detail {
+.issuable-details,
+.md-preview-holder,
+.referenced-commands,
+.note-body {
.scoped-label-wrapper {
.badge {
overflow: initial;
diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss
index 22a515cbdaa..d8aabecc036 100644
--- a/app/assets/stylesheets/pages/login.scss
+++ b/app/assets/stylesheets/pages/login.scss
@@ -21,13 +21,6 @@
color: $login-brand-holder-color;
}
- h1:first-child {
- font-weight: $gl-font-weight-normal;
- margin-bottom: 0.68em;
- margin-top: 0;
- font-size: 34px;
- }
-
h3 {
font-size: 22px;
}
@@ -49,8 +42,8 @@
.login-box,
.omniauth-container {
box-shadow: 0 0 0 1px $border-color;
- border-bottom-right-radius: $border-radius-small;
- border-bottom-left-radius: $border-radius-small;
+ border-bottom-right-radius: $border-radius;
+ border-bottom-left-radius: $border-radius;
padding: 15px;
.login-heading h3 {
@@ -80,7 +73,8 @@
.login-body {
font-size: 13px;
- input + p {
+ input + p,
+ input ~ p.field-validation {
margin-top: 5px;
}
@@ -95,7 +89,7 @@
}
.omniauth-container {
- border-radius: $border-radius-small;
+ border-radius: $border-radius;
font-size: 13px;
p {
diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss
index e0b84e0f92d..68af01f9ccc 100644
--- a/app/assets/stylesheets/pages/members.scss
+++ b/app/assets/stylesheets/pages/members.scss
@@ -14,23 +14,12 @@
}
.member {
- &.is-overriden {
+ &.is-overridden {
.btn-ldap-override {
display: none !important;
}
}
- .list-item-name {
- @include media-breakpoint-up(sm) {
- float: left;
- width: 50%;
- }
-
- strong {
- font-weight: $gl-font-weight-bold;
- }
- }
-
.controls {
@include media-breakpoint-up(sm) {
display: flex;
@@ -43,10 +32,11 @@
.form-group {
margin-bottom: 0;
+ }
- @include media-breakpoint-down(sm) {
- display: block;
- margin-left: 5px;
+ .member-controls {
+ .fa {
+ line-height: inherit;
}
}
@@ -66,23 +56,12 @@
}
.member-form-control {
- @include media-breakpoint-down(sm) {
- width: $dropdown-member-form-control-width;
- margin-left: 0;
- padding-bottom: 5px;
- }
-
@include media-breakpoint-down(xs) {
margin-right: 0;
width: auto;
}
}
-.member-access-text {
- margin-left: auto;
- line-height: 43px;
-}
-
.member-search-form {
position: relative;
@@ -130,9 +109,6 @@
.members-ldap {
align-self: center;
- height: 100%;
- margin-right: 10px;
- margin-left: -49px;
}
.alert-member-ldap {
@@ -224,9 +200,6 @@
}
.content-list.members-list li {
- display: flex;
- justify-content: space-between;
-
.list-item-name {
float: none;
display: flex;
@@ -255,33 +228,24 @@
align-self: flex-start;
}
+ @include media-breakpoint-down(sm) {
+ .member-access-text {
+ margin: 0 0 $gl-padding-4 ($grid-size * 6);
+ }
+ }
+
@include media-breakpoint-down(xs) {
display: block;
- .controls > .btn {
- margin-left: 0;
- margin-right: 0;
+ .controls > .btn,
+ .controls .member-form-control {
+ margin: 0 0 $gl-padding-8;
display: block;
}
- .controls > .btn:last-child {
- margin-left: 5px;
- margin-right: 5px;
- width: auto;
- }
-
.form-control {
width: 100%;
}
-
- .member-access-text {
- line-height: 0;
- margin-left: 50px;
- }
-
- .member-controls {
- margin-top: 5px;
- }
}
}
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 709940ba6c8..8cb3fab74e0 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -87,6 +87,11 @@
padding: $gl-padding;
}
+.mr-widget-info {
+ padding-left: $gl-padding-50 - $gl-padding-32;
+ padding-right: $gl-padding;
+}
+
.mr-state-widget {
color: $gl-text-color;
@@ -180,46 +185,6 @@
}
}
}
-
- .accept-control {
- display: inline-block;
- float: left;
- margin: 0;
- margin-left: 20px;
- padding: 5px;
- padding-top: 8px;
- line-height: 20px;
-
- &.right {
- float: right;
- padding-right: 0;
- }
-
- .modify-merge-commit-link {
- padding: 0;
- background-color: transparent;
- border: 0;
- color: $gl-text-color;
-
- &:hover,
- &:focus {
- text-decoration: underline;
- }
- }
-
- .merge-param-checkbox {
- margin: 0;
- }
-
- a .fa-question-circle {
- color: $gl-text-color-secondary;
-
- &:hover,
- &:focus {
- color: $link-hover-color;
- }
- }
- }
}
.ci-widget {
@@ -402,12 +367,6 @@
width: 100%;
text-align: center;
}
-
- .accept-control {
- width: 100%;
- text-align: center;
- margin: 0;
- }
}
.commit-message-editor {
@@ -560,6 +519,10 @@
.mr-links {
padding-left: $status-icon-size + $gl-btn-padding;
+
+ &:last-child {
+ padding-bottom: $gl-padding;
+ }
}
.mr-info-list {
@@ -883,15 +846,40 @@
display: flex;
justify-content: space-between;
- @include media-breakpoint-down(sm) {
- flex-direction: column-reverse;
+ @include media-breakpoint-down(xs) {
+ .discussion-filter-container,
+ .line-resolve-all-container {
+ margin-bottom: $gl-padding-4;
+ }
}
.discussion-filter-container {
- margin-top: $gl-padding-8;
-
&:not(:only-child) {
- padding-right: $gl-padding-8;
+ margin: $gl-padding-4;
+ }
+ }
+
+ .merge-request-tabs {
+ height: $grid-size * 6;
+ }
+}
+
+// Wrap MR tabs/buttons so you don't have to scroll on desktop
+@include media-breakpoint-down(md) {
+ .merge-request-tabs-container,
+ .epic-tabs-container {
+ flex-direction: column-reverse;
+ padding-top: $gl-padding-8;
+ }
+}
+
+@include media-breakpoint-down(lg) {
+ .right-sidebar-expanded {
+ .merge-request-tabs-container,
+ .epic-tabs-container {
+ flex-direction: column-reverse;
+ align-items: flex-start;
+ padding-top: $gl-padding-8;
}
}
}
@@ -972,10 +960,6 @@
}
}
- .btn svg {
- fill: $gray-700;
- }
-
.dropdown-menu {
width: 400px;
}
@@ -1034,11 +1018,6 @@
background: $black-transparent;
}
-.source-branch-removal-status {
- padding-left: 50px;
- padding-bottom: $gl-padding;
-}
-
.mr-compare {
.diff-file .file-title-flex-parent {
top: $header-height + 51px;
diff --git a/app/assets/stylesheets/pages/milestone.scss b/app/assets/stylesheets/pages/milestone.scss
index 49608a3964f..00d84df1650 100644
--- a/app/assets/stylesheets/pages/milestone.scss
+++ b/app/assets/stylesheets/pages/milestone.scss
@@ -230,27 +230,6 @@ $status-box-line-height: 26px;
background-color: $white-light;
}
-.milestone-deprecation-message {
- .popover {
- padding: 0;
- }
-
- .popover-body,
- .popover-content {
- padding: 0;
- }
-}
-
-.milestone-popover-body {
- padding: $gl-padding-8;
- background-color: $gray-light;
-}
-
-.milestone-popover-footer {
- padding: $gl-padding-8 $gl-padding;
- border-top: 1px solid $white-dark;
-}
-
.milestone-popover-instructions-list {
padding-left: 2em;
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index 3343b55d24b..c6bac33e888 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -59,6 +59,7 @@
border-radius: $border-radius-base;
transition: border-color ease-in-out 0.15s,
box-shadow ease-in-out 0.15s;
+ background-color: $white-light;
&.is-focused {
@extend .form-control:focus;
@@ -103,6 +104,11 @@
margin: auto;
align-items: center;
+ a {
+ color: $orange-600;
+ text-decoration: underline;
+ }
+
.icon {
margin-right: $issuable-warning-icon-margin;
vertical-align: text-bottom;
@@ -168,6 +174,16 @@
.discussion-form {
background-color: $white-light;
+
+ @include media-breakpoint-down(xs) {
+ .user-avatar-link {
+ display: none;
+ }
+
+ .note-edit-form {
+ margin-left: 0;
+ }
+ }
}
table {
@@ -234,13 +250,25 @@ table {
.diff-file,
.commit-diff {
.discussion-reply-holder {
- background-color: $white-light;
+ background-color: $gray-light;
border-radius: 0 0 3px 3px;
padding: $gl-padding;
+ border-top: 1px solid $gray-100;
+
+ + .new-note {
+ background-color: $gray-light;
+ border-top: 1px solid $gray-100;
+ }
&.is-replying {
padding-bottom: $gl-padding;
}
+
+ .user-avatar-link {
+ img {
+ margin-top: -3px;
+ }
+ }
}
}
@@ -334,7 +362,7 @@ table {
.toolbar-button-icon {
position: relative;
top: 1px;
- margin-right: 3px;
+ margin-right: $gl-padding-4;
color: inherit;
font-size: 16px;
}
@@ -461,6 +489,15 @@ table {
border: 0;
font-size: 14px;
line-height: 16px;
+
+ &:hover,
+ &:focus {
+ text-decoration: none;
+
+ .text-attach-file {
+ text-decoration: underline;
+ }
+ }
}
.markdown-selector {
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index 09f75cd827f..5cacd42bf0d 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -80,21 +80,17 @@ $note-form-margin-left: 72px;
}
}
- li.note {
- border-bottom: 1px solid $border-color;
- }
-
.replies-toggle {
background-color: $gray-light;
padding: $gl-padding-8 $gl-padding;
+ border-top: 1px solid $gray-100;
+ border-bottom: 1px solid $gray-100;
.collapse-replies-btn:hover {
color: $blue-600;
}
&.expanded {
- border-bottom: 1px solid $border-color;
-
span {
cursor: pointer;
}
@@ -107,6 +103,7 @@ $note-form-margin-left: 72px;
&.collapsed {
color: $gl-text-color-secondary;
+ border-radius: 0 0 $border-radius-default $border-radius-default;
svg {
float: left;
@@ -210,8 +207,13 @@ $note-form-margin-left: 72px;
display: none;
}
+ .user-avatar-link img {
+ margin-top: $gl-padding-8;
+ }
+
.note-edit-form {
display: block;
+ margin-left: 0;
&.current-note-edit-form + .note-awards {
display: none;
@@ -263,8 +265,8 @@ $note-form-margin-left: 72px;
}
.system-note {
- padding: 6px 21px;
- margin: $gl-padding-24 0;
+ padding: $gl-padding-4 20px;
+ margin: $gl-padding 0;
background-color: transparent;
.note-header-info {
@@ -363,7 +365,7 @@ $note-form-margin-left: 72px;
height: $system-note-icon-size;
border: 1px solid $border-color;
border-radius: $system-note-icon-size;
- margin: -6px $gl-padding 0 0;
+ margin: -6px 20px 0 0;
svg {
width: $system-note-svg-size;
@@ -429,14 +431,16 @@ $note-form-margin-left: 72px;
.notes > .note-discussion li.note.system-note {
border-bottom: 0;
- padding: 0 $gl-padding;
+ padding: 0;
}
}
.diff-file {
.is-over {
.add-diff-note {
- display: inline-block;
+ display: inline-flex;
+ justify-content: center;
+ align-items: center;
}
}
@@ -471,6 +475,11 @@ $note-form-margin-left: 72px;
vertical-align: top;
white-space: normal;
+ // Fixes subpixel rounding issue https://gitlab.com/gitlab-org/gitlab-ce/issues/53973
+ // background-color is needed for dark code preference
+ padding-bottom: 1px;
+ background-color: $white-light;
+
&.parallel {
border-width: 1px;
@@ -511,12 +520,30 @@ $note-form-margin-left: 72px;
}
}
-.commit-diff {
- .notes-content {
- background-color: $white-light;
+.code-commit .notes-content,
+.diff-viewer > .image ~ .note-container {
+ background-color: $white-light;
+
+ .avatar-note-form-holder {
+ .user-avatar-link img {
+ margin: 13px $gl-padding $gl-padding;
+ }
+
+ form,
+ ~ .discussion-form-container {
+ padding: $gl-padding;
+
+ @include media-breakpoint-up(sm) {
+ margin-left: $note-icon-gutter-width;
+ }
+ }
}
}
+.diff-viewer > .image ~ .note-container form.new-note {
+ margin-left: 0;
+}
+
.discussion-header,
.note-header-info {
a {
@@ -542,7 +569,7 @@ $note-form-margin-left: 72px;
}
.discussion-header {
- min-height: 72px;
+ min-height: 74px;
.note-header-info {
padding-bottom: 0;
@@ -555,8 +582,10 @@ $note-form-margin-left: 72px;
}
.unresolved {
- .note-header-info {
- margin-top: $gl-padding-8;
+ .discussion-header {
+ .note-header-info {
+ margin-top: $gl-padding-8;
+ }
}
}
@@ -639,7 +668,7 @@ $note-form-margin-left: 72px;
display: inline-flex;
align-items: center;
margin-left: 10px;
- color: $gray-darkest;
+ color: $gray-600;
@include notes-media('max', map-get($grid-breakpoints, sm) - 1) {
float: none;
@@ -735,7 +764,7 @@ $note-form-margin-left: 72px;
.add-diff-note {
@include btn-comment-icon;
opacity: 0;
- margin-left: -50px;
+ margin-left: -52px;
position: absolute;
top: 50%;
transform: translateY(-50%);
@@ -754,15 +783,13 @@ $note-form-margin-left: 72px;
background-color: $white-light;
}
- a {
+ a:not(.learn-more) {
color: $blue-600;
}
}
.line-resolve-all-container {
- @include notes-media('min', map-get($grid-breakpoints, sm)) {
- margin-right: 0;
- }
+ margin: $gl-padding-4;
> div {
white-space: nowrap;
@@ -778,6 +805,8 @@ $note-form-margin-left: 72px;
}
.btn {
+ line-height: $gl-line-height;
+
svg {
fill: $gray-darkest;
}
@@ -803,10 +832,11 @@ $note-form-margin-left: 72px;
.line-resolve-all {
vertical-align: middle;
display: inline-block;
- padding: 6px 10px;
+ padding: $gl-padding-4 10px;
background-color: $gray-light;
border: 1px solid $border-color;
border-radius: $border-radius-default;
+ font-size: $gl-btn-small-font-size;
&.has-next-btn {
border-top-right-radius: 0;
@@ -816,11 +846,16 @@ $note-form-margin-left: 72px;
.line-resolve-btn {
margin-right: 5px;
+ color: $gray-darkest;
svg {
vertical-align: middle;
}
}
+
+ @include media-breakpoint-down(xs) {
+ flex: 1;
+ }
}
.line-resolve-btn {
@@ -830,7 +865,6 @@ $note-form-margin-left: 72px;
background-color: transparent;
border: 0;
outline: 0;
- color: $gray-darkest;
transition: color $general-hover-transition-duration $general-hover-transition-curve;
&.is-disabled {
@@ -894,10 +928,6 @@ $note-form-margin-left: 72px;
.diff-comment-form {
display: block;
}
-
- .add-diff-note svg {
- margin-top: 4px;
- }
}
.discussion-filter-container {
diff --git a/app/assets/stylesheets/pages/notifications.scss b/app/assets/stylesheets/pages/notifications.scss
index e98cb444f0a..e1cbf0e6654 100644
--- a/app/assets/stylesheets/pages/notifications.scss
+++ b/app/assets/stylesheets/pages/notifications.scss
@@ -4,6 +4,34 @@
.dropdown-menu {
@extend .dropdown-menu-right;
}
+
+ @include media-breakpoint-down(sm) {
+ .notification-dropdown {
+ width: 100%;
+ }
+
+ .notification-form {
+ display: block;
+ }
+
+ .notifications-btn,
+ .btn-group {
+ width: 100%;
+ }
+
+ .table-section {
+ border-top: 0;
+ min-height: unset;
+
+ &:not(:first-child) {
+ padding-top: 0;
+ }
+ }
+
+ .update-notifications {
+ width: 100%;
+ }
+ }
}
.notification {
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index 093fc89a56f..aa6bbc8e473 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -565,6 +565,7 @@
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
+ line-height: 2.2em;
}
.build {
@@ -701,6 +702,11 @@
}
}
}
+
+ .stage-action svg {
+ left: 1px;
+ top: -2px;
+ }
}
// Triggers the dropdown in the big pipeline graph
@@ -897,7 +903,7 @@ button.mini-pipeline-graph-dropdown-toggle {
// Match dropdown.scss for all `a` tags
&.non-details-job-component {
- padding: 8px 16px;
+ padding: $gl-padding-8 $gl-btn-horz-padding;
}
.ci-job-name-component {
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 7778b4aab3d..151af843c95 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -1446,3 +1446,86 @@ pre.light-well {
}
}
}
+
+.project-filters {
+ .btn svg {
+ color: $gl-gray-700;
+ }
+
+ .button-filter-group {
+ .btn {
+ width: 96px;
+ }
+
+ a {
+ color: $black;
+ }
+
+ .active {
+ background: $btn-active-gray;
+ }
+ }
+
+ .filtered-search-dropdown-label {
+ min-width: 68px;
+
+ @include media-breakpoint-down(xs) {
+ min-width: 60px;
+ }
+ }
+
+ .filtered-search {
+ min-width: 30%;
+ flex-basis: 0;
+
+ .project-filter-form .project-filter-form-field {
+ padding-right: $gl-padding-8;
+ }
+
+ .filtered-search,
+ .filtered-search-nav,
+ .filtered-search-dropdown {
+ flex-basis: 0;
+ }
+
+ @include media-breakpoint-down(lg) {
+ min-width: 15%;
+
+ .project-filter-form-field {
+ min-width: 150px;
+ }
+ }
+
+ @include media-breakpoint-down(md) {
+ min-width: 30%;
+ }
+ }
+
+ .filtered-search-box {
+ border-radius: 3px 0 0 3px;
+ }
+
+ .dropdown-menu-toggle {
+ margin-left: $gl-padding-8;
+ }
+
+ @include media-breakpoint-down(md) {
+ .extended-filtered-search-box {
+ min-width: 55%;
+ }
+
+ .filtered-search-dropdown {
+ width: 50%;
+
+ .dropdown-menu-toggle {
+ width: 100%;
+ }
+ }
+ }
+
+ @include media-breakpoint-down(xs) {
+ .filtered-search-dropdown {
+ width: 100%;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/pages/prometheus.scss b/app/assets/stylesheets/pages/prometheus.scss
index c03554b287f..2d600e3aef6 100644
--- a/app/assets/stylesheets/pages/prometheus.scss
+++ b/app/assets/stylesheets/pages/prometheus.scss
@@ -136,7 +136,6 @@
> .popover-header,
> .popover-body {
padding: 8px;
- font-size: 12px;
white-space: nowrap;
position: relative;
}
diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss
index 20bdc6596e9..dbf600df9d6 100644
--- a/app/assets/stylesheets/pages/search.scss
+++ b/app/assets/stylesheets/pages/search.scss
@@ -75,6 +75,8 @@ input[type='checkbox']:hover {
}
.search-input-wrap {
+ width: 100%;
+
.search-icon,
.clear-icon {
position: absolute;
@@ -84,6 +86,9 @@ input[type='checkbox']:hover {
.search-icon {
transition: color $default-transition-duration;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
user-select: none;
}
@@ -256,3 +261,13 @@ input[type='checkbox']:hover {
color: $blue-600;
}
}
+
+// Disable webkit input icons, link to solution: https://stackoverflow.com/questions/9421551/how-do-i-remove-all-default-webkit-search-field-styling
+/* stylelint-disable property-no-vendor-prefix */
+input[type='search']::-webkit-search-decoration,
+input[type='search']::-webkit-search-cancel-button,
+input[type='search']::-webkit-search-results-button,
+input[type='search']::-webkit-search-results-decoration {
+ -webkit-appearance: none;
+}
+/* stylelint-enable */
diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss
index 2a1e8345755..586365eb1ce 100644
--- a/app/assets/stylesheets/pages/todos.scss
+++ b/app/assets/stylesheets/pages/todos.scss
@@ -110,45 +110,38 @@
}
.todo-body {
- .todo-note {
- word-wrap: break-word;
-
- .md {
- color: $gl-grayish-blue;
- font-size: $gl-font-size;
-
- .badge.badge-pill {
- color: $gl-text-color;
- }
+ .badge.badge-pill,
+ p {
+ color: $gl-text-color;
+ }
- p {
- color: $gl-text-color;
- }
- }
+ .md {
+ color: $gl-grayish-blue;
+ font-size: $gl-font-size;
+ }
- code {
- white-space: pre-wrap;
- }
+ code {
+ white-space: pre-wrap;
+ }
- pre {
- border: 0;
- background: $gray-light;
- border-radius: 0;
- color: $gl-gray-500;
- margin: 0 20px;
- overflow: hidden;
- }
+ pre {
+ border: 0;
+ background: $gray-light;
+ border-radius: 0;
+ color: $gl-gray-500;
+ margin: 0 20px;
+ overflow: hidden;
+ }
- .note-image-attach {
- margin-top: 4px;
- margin-left: 0;
- max-width: 200px;
- float: none;
- }
+ .note-image-attach {
+ margin-top: 4px;
+ margin-left: 0;
+ max-width: 200px;
+ float: none;
+ }
- p:last-child {
- margin-bottom: 0;
- }
+ p:last-child {
+ margin-bottom: 0;
}
}
}
diff --git a/app/assets/stylesheets/performance_bar.scss b/app/assets/stylesheets/performance_bar.scss
index 9c01a2f8bda..5a8940ffd6d 100644
--- a/app/assets/stylesheets/performance_bar.scss
+++ b/app/assets/stylesheets/performance_bar.scss
@@ -79,8 +79,12 @@
table {
color: $black;
- strong {
- color: $black;
+ td {
+ vertical-align: top;
+ }
+
+ .backtrace-row {
+ display: none;
}
}
diff --git a/app/controllers/acme_challenges_controller.rb b/app/controllers/acme_challenges_controller.rb
new file mode 100644
index 00000000000..67a39d8870b
--- /dev/null
+++ b/app/controllers/acme_challenges_controller.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AcmeChallengesController < ActionController::Base
+ def show
+ if acme_order
+ render plain: acme_order.challenge_file_content, content_type: 'text/plain'
+ else
+ head :not_found
+ end
+ end
+
+ private
+
+ def acme_order
+ @acme_order ||= PagesDomainAcmeOrder.find_by_domain_and_token(params[:domain], params[:token])
+ end
+end
diff --git a/app/controllers/admin/application_controller.rb b/app/controllers/admin/application_controller.rb
index ef182b981f1..b742b7e19cf 100644
--- a/app/controllers/admin/application_controller.rb
+++ b/app/controllers/admin/application_controller.rb
@@ -4,10 +4,7 @@
#
# Automatically sets the layout and ensures an administrator is logged in
class Admin::ApplicationController < ApplicationController
- before_action :authenticate_admin!
- layout 'admin'
+ include EnforcesAdminAuthentication
- def authenticate_admin!
- render_404 unless current_user.admin?
- end
+ layout 'admin'
end
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index b681949ab36..57b976b9121 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -2,7 +2,9 @@
class Admin::ApplicationSettingsController < Admin::ApplicationController
include InternalRedirect
+
before_action :set_application_setting
+ before_action :whitelist_query_limiting, only: [:usage_data]
def show
end
@@ -89,12 +91,23 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
)
end
+ # Getting ToS url requires `directory` api call to Let's Encrypt
+ # which could result in 500 error/slow rendering on settings page
+ # Because of that we use separate controller action
+ def lets_encrypt_terms_of_service
+ redirect_to ::Gitlab::LetsEncrypt.terms_of_service_url
+ end
+
private
def set_application_setting
@application_setting = Gitlab::CurrentSettings.current_application_settings
end
+ def whitelist_query_limiting
+ Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/63107')
+ end
+
def application_setting_params
params[:application_setting] ||= {}
@@ -127,6 +140,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
[
*::ApplicationSettingsHelper.visible_attributes,
*::ApplicationSettingsHelper.external_authorization_service_attributes,
+ *lets_encrypt_visible_attributes,
:domain_blacklist_file,
disabled_oauth_sign_in_sources: [],
import_sources: [],
@@ -134,4 +148,13 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
restricted_visibility_levels: []
]
end
+
+ def lets_encrypt_visible_attributes
+ return [] unless Feature.enabled?(:pages_auto_ssl)
+
+ [
+ :lets_encrypt_notification_email,
+ :lets_encrypt_terms_of_service_accepted
+ ]
+ end
end
diff --git a/app/controllers/admin/clusters/applications_controller.rb b/app/controllers/admin/clusters/applications_controller.rb
new file mode 100644
index 00000000000..7400cc16175
--- /dev/null
+++ b/app/controllers/admin/clusters/applications_controller.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class Admin::Clusters::ApplicationsController < Clusters::ApplicationsController
+ include EnforcesAdminAuthentication
+
+ private
+
+ def clusterable
+ @clusterable ||= InstanceClusterablePresenter.fabricate(Clusters::Instance.new, current_user: current_user)
+ end
+end
diff --git a/app/controllers/admin/clusters_controller.rb b/app/controllers/admin/clusters_controller.rb
new file mode 100644
index 00000000000..f54933de10f
--- /dev/null
+++ b/app/controllers/admin/clusters_controller.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class Admin::ClustersController < Clusters::ClustersController
+ include EnforcesAdminAuthentication
+
+ layout 'admin'
+
+ private
+
+ def clusterable
+ @clusterable ||= InstanceClusterablePresenter.fabricate(Clusters::Instance.new, current_user: current_user)
+ end
+end
diff --git a/app/controllers/admin/logs_controller.rb b/app/controllers/admin/logs_controller.rb
index 06b0e6a15a3..704e727b1da 100644
--- a/app/controllers/admin/logs_controller.rb
+++ b/app/controllers/admin/logs_controller.rb
@@ -15,7 +15,8 @@ class Admin::LogsController < Admin::ApplicationController
Gitlab::EnvironmentLogger,
Gitlab::SidekiqLogger,
Gitlab::RepositoryCheckLogger,
- Gitlab::ProjectServiceLogger
+ Gitlab::ProjectServiceLogger,
+ Gitlab::Kubernetes::Logger
]
end
end
diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb
index aeff0c96b64..70db15916b9 100644
--- a/app/controllers/admin/projects_controller.rb
+++ b/app/controllers/admin/projects_controller.rb
@@ -3,7 +3,7 @@
class Admin::ProjectsController < Admin::ApplicationController
include MembersPresentation
- before_action :project, only: [:show, :transfer, :repository_check]
+ before_action :project, only: [:show, :transfer, :repository_check, :destroy]
before_action :group, only: [:show, :transfer]
def index
@@ -35,6 +35,15 @@ class Admin::ProjectsController < Admin::ApplicationController
end
# rubocop: enable CodeReuse/ActiveRecord
+ def destroy
+ ::Projects::DestroyService.new(@project, current_user, {}).async_execute
+ flash[:notice] = _("Project '%{project_name}' is in the process of being deleted.") % { project_name: @project.full_name }
+
+ redirect_to admin_projects_path, status: :found
+ rescue Projects::DestroyService::DestroyError => ex
+ redirect_to admin_projects_path, status: 302, alert: ex.message
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def transfer
namespace = Namespace.find_by(id: params[:new_namespace_id])
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index d5f1e35a79b..7321f719deb 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -27,6 +27,7 @@ class ApplicationController < ActionController::Base
before_action :check_impersonation_availability
around_action :set_locale
+ around_action :set_session_storage
after_action :set_page_title_header, if: :json_request?
after_action :limit_unauthenticated_session_times
@@ -41,7 +42,7 @@ class ApplicationController < ActionController::Base
:bitbucket_server_import_enabled?,
:google_code_import_enabled?, :fogbugz_import_enabled?,
:git_import_enabled?, :gitlab_project_import_enabled?,
- :manifest_import_enabled?
+ :manifest_import_enabled?, :phabricator_import_enabled?
# Adds `no-store` to the DEFAULT_CACHE_CONTROL, to prevent security
# concerns due to caching private data.
@@ -128,7 +129,7 @@ class ApplicationController < ActionController::Base
payload[:ua] = request.env["HTTP_USER_AGENT"]
payload[:remote_ip] = request.remote_ip
- payload[Gitlab::CorrelationId::LOG_KEY] = Gitlab::CorrelationId.current_id
+ payload[Labkit::Correlation::CorrelationId::LOG_KEY] = Labkit::Correlation::CorrelationId.current_id
logged_user = auth_user
@@ -423,6 +424,10 @@ class ApplicationController < ActionController::Base
Group.supports_nested_objects? && Gitlab::CurrentSettings.import_sources.include?('manifest')
end
+ def phabricator_import_enabled?
+ Gitlab::PhabricatorImport.available?
+ end
+
# U2F (universal 2nd factor) devices need a unique identifier for the application
# to perform authentication.
# https://developers.yubico.com/U2F/App_ID.html
@@ -434,6 +439,12 @@ class ApplicationController < ActionController::Base
Gitlab::I18n.with_user_locale(current_user, &block)
end
+ def set_session_storage(&block)
+ return yield if sessionless_user?
+
+ Gitlab::Session.with_session(session, &block)
+ end
+
def set_page_title_header
# Per https://tools.ietf.org/html/rfc5987, headers need to be ISO-8859-1, not UTF-8
response.headers['Page-Title'] = URI.escape(page_title('GitLab'))
diff --git a/app/controllers/clusters/applications_controller.rb b/app/controllers/clusters/applications_controller.rb
index 73c744efeba..16c2365f85d 100644
--- a/app/controllers/clusters/applications_controller.rb
+++ b/app/controllers/clusters/applications_controller.rb
@@ -4,6 +4,7 @@ class Clusters::ApplicationsController < Clusters::BaseController
before_action :cluster
before_action :authorize_create_cluster!, only: [:create]
before_action :authorize_update_cluster!, only: [:update]
+ before_action :authorize_admin_cluster!, only: [:destroy]
def create
request_handler do
@@ -21,6 +22,14 @@ class Clusters::ApplicationsController < Clusters::BaseController
end
end
+ def destroy
+ request_handler do
+ Clusters::Applications::DestroyService
+ .new(@cluster, current_user, cluster_application_destroy_params)
+ .execute(request)
+ end
+ end
+
private
def request_handler
@@ -40,4 +49,8 @@ class Clusters::ApplicationsController < Clusters::BaseController
def cluster_application_params
params.permit(:application, :hostname, :email)
end
+
+ def cluster_application_destroy_params
+ params.permit(:application)
+ end
end
diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb
index e82756e4643..80ee7c35906 100644
--- a/app/controllers/clusters/clusters_controller.rb
+++ b/app/controllers/clusters/clusters_controller.rb
@@ -153,6 +153,7 @@ class Clusters::ClustersController < Clusters::BaseController
:enabled,
:name,
:environment_scope,
+ :managed,
provider_gcp_attributes: [
:gcp_project_id,
:zone,
@@ -171,6 +172,7 @@ class Clusters::ClustersController < Clusters::BaseController
:enabled,
:name,
:environment_scope,
+ :managed,
platform_kubernetes_attributes: [
:namespace,
:api_url,
diff --git a/app/controllers/concerns/authenticates_with_two_factor.rb b/app/controllers/concerns/authenticates_with_two_factor.rb
index d5c4712bd78..4926062f9ca 100644
--- a/app/controllers/concerns/authenticates_with_two_factor.rb
+++ b/app/controllers/concerns/authenticates_with_two_factor.rb
@@ -8,13 +8,6 @@
module AuthenticatesWithTwoFactor
extend ActiveSupport::Concern
- included do
- # This action comes from DeviseController, but because we call `sign_in`
- # manually, not skipping this action would cause a "You are already signed
- # in." error message to be shown upon successful login.
- skip_before_action :require_no_authentication, only: [:create], raise: false
- end
-
# Store the user's ID in the session for later retrieval and render the
# two factor code prompt
#
diff --git a/app/controllers/concerns/boards_actions.rb b/app/controllers/concerns/boards_actions.rb
index ed7ea2f0e04..e4123d87137 100644
--- a/app/controllers/concerns/boards_actions.rb
+++ b/app/controllers/concerns/boards_actions.rb
@@ -35,4 +35,12 @@ module BoardsActions
boards.find(params[:id])
end
end
+
+ def serializer
+ BoardSerializer.new(current_user: current_user)
+ end
+
+ def serialize_as_json(resource)
+ serializer.represent(resource, serializer: 'board', include_full_project_path: board.group_board?)
+ end
end
diff --git a/app/controllers/concerns/boards_responses.rb b/app/controllers/concerns/boards_responses.rb
index 8b191c86397..7625600e452 100644
--- a/app/controllers/concerns/boards_responses.rb
+++ b/app/controllers/concerns/boards_responses.rb
@@ -69,7 +69,7 @@ module BoardsResponses
end
def serialize_as_json(resource)
- resource.as_json(only: [:id])
+ serializer.represent(resource).as_json
end
def respond_with(resource)
@@ -80,4 +80,8 @@ module BoardsResponses
end
end
end
+
+ def serializer
+ BoardSerializer.new
+ end
end
diff --git a/app/controllers/concerns/enforces_admin_authentication.rb b/app/controllers/concerns/enforces_admin_authentication.rb
new file mode 100644
index 00000000000..3ef92730df6
--- /dev/null
+++ b/app/controllers/concerns/enforces_admin_authentication.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+# == EnforcesAdminAuthentication
+#
+# Controller concern to enforce that users are authenticated as admins
+#
+# Upon inclusion, adds `authenticate_admin!` as a before_action
+#
+module EnforcesAdminAuthentication
+ extend ActiveSupport::Concern
+
+ included do
+ before_action :authenticate_admin!
+ end
+
+ def authenticate_admin!
+ render_404 unless current_user.admin?
+ end
+end
diff --git a/app/controllers/concerns/enforces_two_factor_authentication.rb b/app/controllers/concerns/enforces_two_factor_authentication.rb
index 71bdef8ce03..0fddf15d197 100644
--- a/app/controllers/concerns/enforces_two_factor_authentication.rb
+++ b/app/controllers/concerns/enforces_two_factor_authentication.rb
@@ -16,7 +16,7 @@ module EnforcesTwoFactorAuthentication
end
def check_two_factor_requirement
- if two_factor_authentication_required? && current_user && !current_user.two_factor_enabled? && !skip_two_factor?
+ if two_factor_authentication_required? && current_user && !current_user.temp_oauth_email? && !current_user.two_factor_enabled? && !skip_two_factor?
redirect_to profile_two_factor_auth_path
end
end
diff --git a/app/controllers/concerns/import_url_params.rb b/app/controllers/concerns/import_url_params.rb
new file mode 100644
index 00000000000..e51e4157f50
--- /dev/null
+++ b/app/controllers/concerns/import_url_params.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module ImportUrlParams
+ def import_url_params
+ return {} unless params.dig(:project, :import_url).present?
+
+ { import_url: import_params_to_full_url(params[:project]) }
+ end
+
+ def import_params_to_full_url(params)
+ Gitlab::UrlSanitizer.new(
+ params[:import_url],
+ credentials: {
+ user: params[:import_url_user],
+ password: params[:import_url_password]
+ }
+ ).full_url
+ end
+end
diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb
index 91e875dca54..9cf25915e92 100644
--- a/app/controllers/concerns/issuable_collections.rb
+++ b/app/controllers/concerns/issuable_collections.rb
@@ -41,6 +41,7 @@ module IssuableCollections
return if pagination_disabled?
@issuables = @issuables.page(params[:page])
+ @issuables = per_page_for_relative_position if params[:sort] == 'relative_position'
@issuable_meta_data = issuable_meta_data(@issuables, collection_type)
@total_pages = issuable_page_count
end
@@ -80,6 +81,11 @@ module IssuableCollections
(row_count.to_f / limit).ceil
end
+ # manual / relative_position sorting allows for 100 items on the page
+ def per_page_for_relative_position
+ @issuables.per(100) # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ end
+
def issuable_finder_for(finder_class)
finder_class.new(current_user, finder_options)
end
diff --git a/app/controllers/concerns/milestone_actions.rb b/app/controllers/concerns/milestone_actions.rb
index c0c0160a827..8b8b7db72f8 100644
--- a/app/controllers/concerns/milestone_actions.rb
+++ b/app/controllers/concerns/milestone_actions.rb
@@ -26,16 +26,22 @@ module MilestoneActions
end
end
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
def labels
respond_to do |format|
format.html { redirect_to milestone_redirect_path }
format.json do
+ milestone_labels = @milestone.issue_labels_visible_by_user(current_user)
+
render json: tabs_json("shared/milestones/_labels_tab", {
- labels: @milestone.labels # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ labels: milestone_labels.map do |label|
+ label.present(issuable_subject: @milestone.parent)
+ end
})
end
end
end
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
private
diff --git a/app/controllers/concerns/project_unauthorized.rb b/app/controllers/concerns/project_unauthorized.rb
index d42363b8b17..7238840440f 100644
--- a/app/controllers/concerns/project_unauthorized.rb
+++ b/app/controllers/concerns/project_unauthorized.rb
@@ -1,10 +1,12 @@
# frozen_string_literal: true
module ProjectUnauthorized
- def project_unauthorized_proc
- lambda do |project|
- if project
- label = project.external_authorization_classification_label
+ module ControllerActions
+ def self.on_routable_not_found
+ lambda do |routable|
+ return unless routable.is_a?(Project)
+
+ label = routable.external_authorization_classification_label
rejection_reason = nil
unless ::Gitlab::ExternalAuthorization.access_allowed?(current_user, label)
@@ -12,9 +14,7 @@ module ProjectUnauthorized
rejection_reason ||= _('External authorization denied access to this project')
end
- if rejection_reason
- access_denied!(rejection_reason)
- end
+ access_denied!(rejection_reason) if rejection_reason
end
end
end
diff --git a/app/controllers/concerns/routable_actions.rb b/app/controllers/concerns/routable_actions.rb
index 5624eb3aa45..ff9b0332c97 100644
--- a/app/controllers/concerns/routable_actions.rb
+++ b/app/controllers/concerns/routable_actions.rb
@@ -3,15 +3,13 @@
module RoutableActions
extend ActiveSupport::Concern
- def find_routable!(routable_klass, requested_full_path, extra_authorization_proc: nil, not_found_or_authorized_proc: nil)
+ def find_routable!(routable_klass, requested_full_path, extra_authorization_proc: nil)
routable = routable_klass.find_by_full_path(requested_full_path, follow_redirects: request.get?)
if routable_authorized?(routable, extra_authorization_proc)
ensure_canonical_path(routable, requested_full_path)
routable
else
- if not_found_or_authorized_proc
- not_found_or_authorized_proc.call(routable)
- end
+ perform_not_found_actions(routable, not_found_actions)
route_not_found unless performed?
@@ -19,6 +17,18 @@ module RoutableActions
end
end
+ def not_found_actions
+ [ProjectUnauthorized::ControllerActions.on_routable_not_found]
+ end
+
+ def perform_not_found_actions(routable, actions)
+ actions.each do |action|
+ break if performed?
+
+ instance_exec(routable, &action)
+ end
+ end
+
def routable_authorized?(routable, extra_authorization_proc)
return false unless routable
diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb
index 70811f5ea59..65d14781d92 100644
--- a/app/controllers/dashboard/projects_controller.rb
+++ b/app/controllers/dashboard/projects_controller.rb
@@ -6,18 +6,14 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) }
before_action :set_non_archived_param
+ before_action :projects, only: [:index]
before_action :default_sorting
skip_cross_project_access_check :index, :starred
def index
- @projects = load_projects(params.merge(non_public: true))
-
respond_to do |format|
format.html do
- # n+1: https://gitlab.com/gitlab-org/gitlab-ce/issues/40260
- Gitlab::GitalyClient.allow_n_plus_1_calls do
- render
- end
+ render_projects
end
format.atom do
load_events
@@ -51,6 +47,17 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
private
+ def projects
+ @projects ||= load_projects(params.merge(non_public: true))
+ end
+
+ def render_projects
+ # n+1: https://gitlab.com/gitlab-org/gitlab-ce/issues/40260
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ render
+ end
+ end
+
def default_sorting
params[:sort] ||= 'latest_activity_desc'
@sort = params[:sort]
diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb
index 7b5dc22815c..1ce0afac83b 100644
--- a/app/controllers/graphql_controller.rb
+++ b/app/controllers/graphql_controller.rb
@@ -16,13 +16,8 @@ class GraphqlController < ApplicationController
before_action(only: [:execute]) { authenticate_sessionless_user!(:api) }
def execute
- variables = Gitlab::Graphql::Variables.new(params[:variables]).to_h
- query = params[:query]
- operation_name = params[:operationName]
- context = {
- current_user: current_user
- }
- result = GitlabSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
+ result = multiplex? ? execute_multiplex : execute_query
+
render json: result
end
@@ -38,6 +33,44 @@ class GraphqlController < ApplicationController
private
+ def execute_multiplex
+ GitlabSchema.multiplex(multiplex_queries, context: context)
+ end
+
+ def execute_query
+ variables = build_variables(params[:variables])
+ operation_name = params[:operationName]
+
+ GitlabSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
+ end
+
+ def query
+ params[:query]
+ end
+
+ def multiplex_queries
+ params[:_json].map do |single_query_info|
+ {
+ query: single_query_info[:query],
+ variables: build_variables(single_query_info[:variables]),
+ operation_name: single_query_info[:operationName],
+ context: context
+ }
+ end
+ end
+
+ def context
+ @context ||= { current_user: current_user }
+ end
+
+ def build_variables(variable_info)
+ Gitlab::Graphql::Variables.new(variable_info).to_h
+ end
+
+ def multiplex?
+ params[:_json].present?
+ end
+
def authorize_access_api!
access_denied!("API not accessible for user.") unless can?(current_user, :access_api)
end
diff --git a/app/controllers/groups/variables_controller.rb b/app/controllers/groups/variables_controller.rb
index b44e3b0fff4..11e3cfb01e4 100644
--- a/app/controllers/groups/variables_controller.rb
+++ b/app/controllers/groups/variables_controller.rb
@@ -41,7 +41,7 @@ module Groups
end
def variable_params_attributes
- %i[id key secret_value protected masked _destroy]
+ %i[id variable_type key secret_value protected masked _destroy]
end
def authorize_admin_build!
diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb
index 10cdce98437..837c26c630a 100644
--- a/app/controllers/help_controller.rb
+++ b/app/controllers/help_controller.rb
@@ -7,7 +7,7 @@ class HelpController < ApplicationController
# Taken from Jekyll
# https://github.com/jekyll/jekyll/blob/3.5-stable/lib/jekyll/document.rb#L13
- YAML_FRONT_MATTER_REGEXP = /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m
+ YAML_FRONT_MATTER_REGEXP = /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m.freeze
def index
# Remove YAML frontmatter so that it doesn't look weird
diff --git a/app/controllers/import/bitbucket_server_controller.rb b/app/controllers/import/bitbucket_server_controller.rb
index 643a3bfed1f..f71ea8642cd 100644
--- a/app/controllers/import/bitbucket_server_controller.rb
+++ b/app/controllers/import/bitbucket_server_controller.rb
@@ -15,8 +15,8 @@ class Import::BitbucketServerController < Import::BaseController
# (https://community.atlassian.com/t5/Answers-Developer-Questions/stash-repository-names/qaq-p/499054)
#
# Bitbucket Server starts personal project names with a tilde.
- VALID_BITBUCKET_PROJECT_CHARS = /\A~?[\w\-\.\s]+\z/
- VALID_BITBUCKET_CHARS = /\A[\w\-\.\s]+\z/
+ VALID_BITBUCKET_PROJECT_CHARS = /\A~?[\w\-\.\s]+\z/.freeze
+ VALID_BITBUCKET_CHARS = /\A[\w\-\.\s]+\z/.freeze
def new
end
diff --git a/app/controllers/import/fogbugz_controller.rb b/app/controllers/import/fogbugz_controller.rb
index a37ba682b91..28ead8d44da 100644
--- a/app/controllers/import/fogbugz_controller.rb
+++ b/app/controllers/import/fogbugz_controller.rb
@@ -11,7 +11,7 @@ class Import::FogbugzController < Import::BaseController
def callback
begin
- res = Gitlab::FogbugzImport::Client.new(import_params.symbolize_keys)
+ res = Gitlab::FogbugzImport::Client.new(import_params.to_h.symbolize_keys)
rescue
# If the URI is invalid various errors can occur
return redirect_to new_import_fogbugz_path, alert: _('Could not connect to FogBugz, check your URL')
@@ -26,7 +26,7 @@ class Import::FogbugzController < Import::BaseController
end
def create_user_map
- user_map = params[:users]
+ user_map = user_map_params.to_h[:users]
unless user_map.is_a?(Hash) && user_map.all? { |k, v| !v[:name].blank? }
flash.now[:alert] = _('All users must have a name.')
@@ -99,6 +99,10 @@ class Import::FogbugzController < Import::BaseController
params.permit(:uri, :email, :password)
end
+ def user_map_params
+ params.permit(users: %w(name email gitlab_user))
+ end
+
def verify_fogbugz_import_enabled
render_404 unless fogbugz_import_enabled?
end
diff --git a/app/controllers/import/phabricator_controller.rb b/app/controllers/import/phabricator_controller.rb
new file mode 100644
index 00000000000..d1c04817689
--- /dev/null
+++ b/app/controllers/import/phabricator_controller.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+class Import::PhabricatorController < Import::BaseController
+ include ImportHelper
+
+ before_action :verify_import_enabled
+
+ def new
+ end
+
+ def create
+ @project = Gitlab::PhabricatorImport::ProjectCreator
+ .new(current_user, import_params).execute
+
+ if @project&.persisted?
+ redirect_to @project
+ else
+ @name = params[:name]
+ @path = params[:path]
+ @errors = @project&.errors&.full_messages || [_("Invalid import params")]
+
+ render :new
+ end
+ end
+
+ def verify_import_enabled
+ render_404 unless phabricator_import_enabled?
+ end
+
+ private
+
+ def import_params
+ params.permit(:path, :phabricator_server_url, :api_token, :name, :namespace_id)
+ end
+end
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index d9b3b4bbbd9..2a8dd997d04 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -86,7 +86,8 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
log_audit_event(current_user, with: oauth['provider'])
identity_linker ||= auth_module::IdentityLinker.new(current_user, oauth)
- identity_linker.link
+
+ link_identity(identity_linker)
if identity_linker.changed?
redirect_identity_linked
@@ -100,6 +101,10 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
end
end
+ def link_identity(identity_linker)
+ identity_linker.link
+ end
+
def redirect_identity_exists
redirect_to after_sign_in_path_for(current_user)
end
diff --git a/app/controllers/profiles/accounts_controller.rb b/app/controllers/profiles/accounts_controller.rb
index 0d2a6145d0e..b03f4b7435f 100644
--- a/app/controllers/profiles/accounts_controller.rb
+++ b/app/controllers/profiles/accounts_controller.rb
@@ -17,7 +17,7 @@ class Profiles::AccountsController < Profiles::ApplicationController
if unlink_provider_allowed?(provider)
identity.destroy
else
- flash[:alert] = "You are not allowed to unlink your primary login account"
+ flash[:alert] = _("You are not allowed to unlink your primary login account")
end
redirect_to profile_account_path
diff --git a/app/controllers/profiles/emails_controller.rb b/app/controllers/profiles/emails_controller.rb
index 503eda250b4..f666a1150a6 100644
--- a/app/controllers/profiles/emails_controller.rb
+++ b/app/controllers/profiles/emails_controller.rb
@@ -28,9 +28,9 @@ class Profiles::EmailsController < Profiles::ApplicationController
def resend_confirmation_instructions
if Emails::ConfirmService.new(current_user, user: current_user).execute(@email)
- flash[:notice] = "Confirmation email sent to #{@email.email}"
+ flash[:notice] = _("Confirmation email sent to %{email}") % { email: @email.email }
else
- flash[:alert] = "There was a problem sending the confirmation email"
+ flash[:alert] = _("There was a problem sending the confirmation email")
end
redirect_to profile_emails_url
diff --git a/app/controllers/profiles/groups_controller.rb b/app/controllers/profiles/groups_controller.rb
new file mode 100644
index 00000000000..c755bcb718a
--- /dev/null
+++ b/app/controllers/profiles/groups_controller.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class Profiles::GroupsController < Profiles::ApplicationController
+ include RoutableActions
+
+ def update
+ group = find_routable!(Group, params[:id])
+ notification_setting = current_user.notification_settings.find_by(source: group) # rubocop: disable CodeReuse/ActiveRecord
+
+ if notification_setting.update(update_params)
+ flash[:notice] = "Notification settings for #{group.name} saved"
+ else
+ flash[:alert] = "Failed to save new settings for #{group.name}"
+ end
+
+ redirect_back_or_default(default: profile_notifications_path)
+ end
+
+ private
+
+ def update_params
+ params.require(:notification_setting).permit(:notification_email)
+ end
+end
diff --git a/app/controllers/profiles/notifications_controller.rb b/app/controllers/profiles/notifications_controller.rb
index b719b70c56e..617e5bb7cb3 100644
--- a/app/controllers/profiles/notifications_controller.rb
+++ b/app/controllers/profiles/notifications_controller.rb
@@ -14,9 +14,9 @@ class Profiles::NotificationsController < Profiles::ApplicationController
result = Users::UpdateService.new(current_user, user_params.merge(user: current_user)).execute
if result[:status] == :success
- flash[:notice] = "Notification settings saved"
+ flash[:notice] = _("Notification settings saved")
else
- flash[:alert] = "Failed to save new settings"
+ flash[:alert] = _("Failed to save new settings")
end
redirect_back_or_default(default: profile_notifications_path)
diff --git a/app/controllers/profiles/passwords_controller.rb b/app/controllers/profiles/passwords_controller.rb
index 7038447581c..d2787c2e450 100644
--- a/app/controllers/profiles/passwords_controller.rb
+++ b/app/controllers/profiles/passwords_controller.rb
@@ -14,7 +14,7 @@ class Profiles::PasswordsController < Profiles::ApplicationController
def create
unless @user.password_automatically_set || @user.valid_password?(user_params[:current_password])
- redirect_to new_profile_password_path, alert: 'You must provide a valid current password'
+ redirect_to new_profile_password_path, alert: _('You must provide a valid current password')
return
end
@@ -29,7 +29,7 @@ class Profiles::PasswordsController < Profiles::ApplicationController
if result[:status] == :success
Users::UpdateService.new(current_user, user: @user, password_expires_at: nil).execute
- redirect_to root_path, notice: 'Password successfully changed'
+ redirect_to root_path, notice: _('Password successfully changed')
else
render :new
end
@@ -45,14 +45,14 @@ class Profiles::PasswordsController < Profiles::ApplicationController
password_attributes[:password_automatically_set] = false
unless @user.password_automatically_set || @user.valid_password?(user_params[:current_password])
- redirect_to edit_profile_password_path, alert: 'You must provide a valid current password'
+ redirect_to edit_profile_password_path, alert: _('You must provide a valid current password')
return
end
result = Users::UpdateService.new(current_user, password_attributes.merge(user: @user)).execute
if result[:status] == :success
- flash[:notice] = "Password was successfully updated. Please login with it"
+ flash[:notice] = _('Password was successfully updated. Please login with it')
redirect_to new_user_session_path
else
@user.reset
@@ -62,7 +62,7 @@ class Profiles::PasswordsController < Profiles::ApplicationController
def reset
current_user.send_reset_password_instructions
- redirect_to edit_profile_password_path, notice: 'We sent you an email with reset password instructions'
+ redirect_to edit_profile_password_path, notice: _('We sent you an email with reset password instructions')
end
private
diff --git a/app/controllers/profiles/preferences_controller.rb b/app/controllers/profiles/preferences_controller.rb
index 0e30df1b15b..62f98d9e549 100644
--- a/app/controllers/profiles/preferences_controller.rb
+++ b/app/controllers/profiles/preferences_controller.rb
@@ -44,7 +44,9 @@ class Profiles::PreferencesController < Profiles::ApplicationController
:project_view,
:theme_id,
:first_day_of_week,
- :preferred_language
+ :preferred_language,
+ :time_display_relative,
+ :time_format_in_24h
]
end
end
diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb
index 83e14275a8b..95b9344c551 100644
--- a/app/controllers/profiles/two_factor_auths_controller.rb
+++ b/app/controllers/profiles/two_factor_auths_controller.rb
@@ -18,7 +18,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
two_factor_authentication_reason(
global: lambda do
flash.now[:alert] =
- s_('The global settings require you to enable Two-Factor Authentication for your account.')
+ _('The global settings require you to enable Two-Factor Authentication for your account.')
end,
group: lambda do |groups|
flash.now[:alert] = groups_notification(groups)
@@ -27,7 +27,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
unless two_factor_grace_period_expired?
grace_period_deadline = current_user.otp_grace_period_started_at + two_factor_grace_period.hours
- flash.now[:alert] = flash.now[:alert] + s_(" You need to do this before %{grace_period_deadline}.") % { grace_period_deadline: l(grace_period_deadline) }
+ flash.now[:alert] = flash.now[:alert] + _(" You need to do this before %{grace_period_deadline}.") % { grace_period_deadline: l(grace_period_deadline) }
end
end
@@ -44,7 +44,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
render 'create'
else
- @error = s_('Invalid pin code')
+ @error = _('Invalid pin code')
@qr_code = build_qr_code
setup_u2f_registration
render 'show'
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index b9c52618d4b..1d16ddb1608 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -15,7 +15,7 @@ class ProfilesController < Profiles::ApplicationController
result = Users::UpdateService.new(current_user, user_params.merge(user: @user)).execute
if result[:status] == :success
- message = "Profile was successfully updated"
+ message = s_("Profiles|Profile was successfully updated")
format.html { redirect_back_or_default(default: { action: 'show' }, options: { notice: message }) }
format.json { render json: { message: message } }
@@ -31,7 +31,7 @@ class ProfilesController < Profiles::ApplicationController
user.reset_incoming_email_token!
end
- flash[:notice] = "Incoming email token was successfully reset"
+ flash[:notice] = s_("Profiles|Incoming email token was successfully reset")
redirect_to profile_personal_access_tokens_path
end
@@ -41,7 +41,7 @@ class ProfilesController < Profiles::ApplicationController
user.reset_feed_token!
end
- flash[:notice] = 'Feed token was successfully reset'
+ flash[:notice] = s_('Profiles|Feed token was successfully reset')
redirect_to profile_personal_access_tokens_path
end
@@ -106,6 +106,7 @@ class ProfilesController < Profiles::ApplicationController
:organization,
:private_profile,
:include_private_contributions,
+ :timezone,
status: [:emoji, :message]
)
end
diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb
index 781eac7f080..80e4f54bbf4 100644
--- a/app/controllers/projects/application_controller.rb
+++ b/app/controllers/projects/application_controller.rb
@@ -3,7 +3,6 @@
class Projects::ApplicationController < ApplicationController
include CookiesHelper
include RoutableActions
- include ProjectUnauthorized
include ChecksCollaboration
skip_before_action :authenticate_user!
@@ -22,7 +21,7 @@ class Projects::ApplicationController < ApplicationController
path = File.join(params[:namespace_id], params[:project_id] || params[:id])
auth_proc = ->(project) { !project.pending_delete? }
- @project = find_routable!(Project, path, extra_authorization_proc: auth_proc, not_found_or_authorized_proc: project_unauthorized_proc)
+ @project = find_routable!(Project, path, extra_authorization_proc: auth_proc)
end
def build_canonical_path(project)
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index e14abbf7c78..fc708400657 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -100,14 +100,14 @@ class Projects::BranchesController < Projects::ApplicationController
respond_to do |format|
format.html do
- flash_type = result[:status] == :error ? :alert : :notice
- flash[flash_type] = result[:message]
+ flash_type = result.error? ? :alert : :notice
+ flash[flash_type] = result.message
redirect_to project_branches_path(@project), status: :see_other
end
- format.js { head result[:return_code] }
- format.json { render json: { message: result[:message] }, status: result[:return_code] }
+ format.js { head result.http_status }
+ format.json { render json: { message: result.message }, status: result.http_status }
end
end
diff --git a/app/controllers/projects/clusters/applications_controller.rb b/app/controllers/projects/clusters/applications_controller.rb
index c7b6218d007..2a04b007304 100644
--- a/app/controllers/projects/clusters/applications_controller.rb
+++ b/app/controllers/projects/clusters/applications_controller.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
class Projects::Clusters::ApplicationsController < Clusters::ApplicationsController
- include ProjectUnauthorized
-
prepend_before_action :project
private
@@ -12,6 +10,6 @@ class Projects::Clusters::ApplicationsController < Clusters::ApplicationsControl
end
def project
- @project ||= find_routable!(Project, File.join(params[:namespace_id], params[:project_id]), not_found_or_authorized_proc: project_unauthorized_proc)
+ @project ||= find_routable!(Project, File.join(params[:namespace_id], params[:project_id]))
end
end
diff --git a/app/controllers/projects/clusters_controller.rb b/app/controllers/projects/clusters_controller.rb
index feda6deeaa6..98cd66cf6f9 100644
--- a/app/controllers/projects/clusters_controller.rb
+++ b/app/controllers/projects/clusters_controller.rb
@@ -1,11 +1,13 @@
# frozen_string_literal: true
class Projects::ClustersController < Clusters::ClustersController
- include ProjectUnauthorized
-
prepend_before_action :project
before_action :repository
+ before_action do
+ push_frontend_feature_flag(:prometheus_computed_alerts)
+ end
+
layout 'project'
private
@@ -15,7 +17,7 @@ class Projects::ClustersController < Clusters::ClustersController
end
def project
- @project ||= find_routable!(Project, File.join(params[:namespace_id], params[:project_id]), not_found_or_authorized_proc: project_unauthorized_proc)
+ @project ||= find_routable!(Project, File.join(params[:namespace_id], params[:project_id]))
end
def repository
diff --git a/app/controllers/projects/environments/prometheus_api_controller.rb b/app/controllers/projects/environments/prometheus_api_controller.rb
index f8ef23cd83e..9c6c6513a78 100644
--- a/app/controllers/projects/environments/prometheus_api_controller.rb
+++ b/app/controllers/projects/environments/prometheus_api_controller.rb
@@ -13,7 +13,7 @@ class Projects::Environments::PrometheusApiController < Projects::ApplicationCon
).execute
if result.nil?
- return render status: :accepted, json: {
+ return render status: :no_content, json: {
status: _('processing'),
message: _('Not ready yet. Try again later.')
}
diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb
index e35f34be23c..ae46a234aa6 100644
--- a/app/controllers/projects/environments_controller.rb
+++ b/app/controllers/projects/environments_controller.rb
@@ -10,8 +10,10 @@ class Projects::EnvironmentsController < Projects::ApplicationController
before_action :environment, only: [:show, :edit, :update, :stop, :terminal, :terminal_websocket_authorize, :metrics]
before_action :verify_api_request!, only: :terminal_websocket_authorize
before_action :expire_etag_cache, only: [:index]
- before_action only: [:metrics, :additional_metrics] do
- push_frontend_feature_flag(:metrics_time_window)
+ before_action only: [:metrics, :additional_metrics, :metrics_dashboard] do
+ push_frontend_feature_flag(:environment_metrics_use_prometheus_endpoint)
+ push_frontend_feature_flag(:environment_metrics_show_multiple_dashboards)
+ push_frontend_feature_flag(:prometheus_computed_alerts)
end
def index
@@ -134,13 +136,13 @@ class Projects::EnvironmentsController < Projects::ApplicationController
end
def metrics
- # Currently, this acts as a hint to load the metrics details into the cache
- # if they aren't there already
- @metrics = environment.metrics || {}
-
respond_to do |format|
format.html
format.json do
+ # Currently, this acts as a hint to load the metrics details into the cache
+ # if they aren't there already
+ @metrics = environment.metrics || {}
+
render json: @metrics, status: @metrics.any? ? :ok : :no_content
end
end
@@ -156,6 +158,33 @@ class Projects::EnvironmentsController < Projects::ApplicationController
end
end
+ def metrics_dashboard
+ return render_403 unless Feature.enabled?(:environment_metrics_use_prometheus_endpoint, project)
+
+ if Feature.enabled?(:environment_metrics_show_multiple_dashboards, project)
+ result = dashboard_finder.find(project, current_user, environment, params[:dashboard])
+
+ result[:all_dashboards] = dashboard_finder.find_all_paths(project)
+ else
+ result = dashboard_finder.find(project, current_user, environment)
+ end
+
+ respond_to do |format|
+ if result[:status] == :success
+ format.json do
+ render status: :ok, json: result.slice(:all_dashboards, :dashboard, :status)
+ end
+ else
+ format.json do
+ render(
+ status: result[:http_status],
+ json: result.slice(:all_dashboards, :message, :status)
+ )
+ end
+ end
+ end
+ end
+
def search
respond_to do |format|
format.json do
@@ -190,12 +219,13 @@ class Projects::EnvironmentsController < Projects::ApplicationController
end
def metrics_params
- return unless Feature.enabled?(:metrics_time_window, project)
- return unless params[:start].present? || params[:end].present?
-
params.require([:start, :end])
end
+ def dashboard_finder
+ Gitlab::Metrics::Dashboard::Finder
+ end
+
def search_environment_names
return [] unless params[:query]
diff --git a/app/controllers/projects/git_http_client_controller.rb b/app/controllers/projects/git_http_client_controller.rb
index 7a80da53025..956093b972b 100644
--- a/app/controllers/projects/git_http_client_controller.rb
+++ b/app/controllers/projects/git_http_client_controller.rb
@@ -15,6 +15,7 @@ class Projects::GitHttpClientController < Projects::ApplicationController
alias_method :authenticated_user, :actor
# Git clients will not know what authenticity token to send along
+ skip_around_action :set_session_storage
skip_before_action :verify_authenticity_token
skip_before_action :repository
before_action :authenticate_user
diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb
index 4640be015de..afbf9fd7720 100644
--- a/app/controllers/projects/imports_controller.rb
+++ b/app/controllers/projects/imports_controller.rb
@@ -2,6 +2,7 @@
class Projects::ImportsController < Projects::ApplicationController
include ContinueParams
+ include ImportUrlParams
# Authorize
before_action :authorize_admin_project!
@@ -67,10 +68,12 @@ class Projects::ImportsController < Projects::ApplicationController
end
def import_params_attributes
- [:import_url]
+ []
end
def import_params
- params.require(:project).permit(import_params_attributes)
+ params.require(:project)
+ .permit(import_params_attributes)
+ .merge(import_url_params)
end
end
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 3d16a368f23..b4d89db20c5 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -10,11 +10,11 @@ class Projects::IssuesController < Projects::ApplicationController
include SpammableActions
include RecordUserLastActivity
- def self.issue_except_actions
+ def issue_except_actions
%i[index calendar new create bulk_update import_csv]
end
- def self.set_issuables_index_only_actions
+ def set_issuables_index_only_actions
%i[index calendar]
end
@@ -25,9 +25,9 @@ class Projects::IssuesController < Projects::ApplicationController
before_action :whitelist_query_limiting, only: [:create, :create_merge_request, :move, :bulk_update]
before_action :check_issues_available!
- before_action :issue, except: issue_except_actions
+ before_action :issue, unless: ->(c) { c.issue_except_actions.include?(c.action_name.to_sym) }
- before_action :set_issuables_index, only: set_issuables_index_only_actions
+ before_action :set_issuables_index, if: ->(c) { c.set_issuables_index_only_actions.include?(c.action_name.to_sym) }
# Allow write(create) issue
before_action :authorize_create_issue!, only: [:new, :create]
@@ -132,18 +132,6 @@ class Projects::IssuesController < Projects::ApplicationController
render_conflict_response
end
- def referenced_merge_requests
- @merge_requests, @closed_by_merge_requests = ::Issues::ReferencedMergeRequestsService.new(project, current_user).execute(issue)
-
- respond_to do |format|
- format.json do
- render json: {
- html: view_to_html_string('projects/issues/_merge_requests')
- }
- end
- end
- end
-
def related_branches
@related_branches = Issues::RelatedBranchesService.new(project, current_user).execute(issue)
diff --git a/app/controllers/projects/merge_requests/application_controller.rb b/app/controllers/projects/merge_requests/application_controller.rb
index eb469d2d714..f2a6268b3e9 100644
--- a/app/controllers/projects/merge_requests/application_controller.rb
+++ b/app/controllers/projects/merge_requests/application_controller.rb
@@ -7,11 +7,15 @@ class Projects::MergeRequests::ApplicationController < Projects::ApplicationCont
private
- # rubocop: disable CodeReuse/ActiveRecord
def merge_request
- @issuable = @merge_request ||= @project.merge_requests.includes(author: :status).find_by!(iid: params[:id])
+ @issuable =
+ @merge_request ||=
+ merge_request_includes(@project.merge_requests).find_by_iid!(params[:id])
+ end
+
+ def merge_request_includes(association)
+ association.includes(:metrics, :assignees, author: :status) # rubocop:disable CodeReuse/ActiveRecord
end
- # rubocop: enable CodeReuse/ActiveRecord
def merge_request_params
params.require(:merge_request).permit(merge_request_params_attributes)
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 8f177895b08..9e7e3ed5afb 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -145,14 +145,12 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
render partial: 'projects/merge_requests/widget/commit_change_content', layout: false
end
- def cancel_merge_when_pipeline_succeeds
- unless @merge_request.can_cancel_merge_when_pipeline_succeeds?(current_user)
+ def cancel_auto_merge
+ unless @merge_request.can_cancel_auto_merge?(current_user)
return access_denied!
end
- ::MergeRequests::MergeWhenPipelineSucceedsService
- .new(@project, current_user)
- .cancel(@merge_request)
+ AutoMergeService.new(project, current_user).cancel(@merge_request)
render json: serialize_widget(@merge_request)
end
@@ -229,12 +227,12 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
end
def merge_params_attributes
- [:should_remove_source_branch, :commit_message, :squash_commit_message, :squash]
+ [:should_remove_source_branch, :commit_message, :squash_commit_message, :squash, :auto_merge_strategy]
end
- def merge_when_pipeline_succeeds_active?
- params[:merge_when_pipeline_succeeds].present? &&
- @merge_request.head_pipeline && @merge_request.head_pipeline.active?
+ def auto_merge_requested?
+ # Support params[:merge_when_pipeline_succeeds] during the transition period
+ params[:auto_merge_strategy].present? || params[:merge_when_pipeline_succeeds].present?
end
def close_merge_request_if_no_source_project
@@ -258,9 +256,9 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
end
def merge!
- # Disable the CI check if merge_when_pipeline_succeeds is enabled since we have
+ # Disable the CI check if auto_merge_strategy is specified since we have
# to wait until CI completes to know
- unless @merge_request.mergeable?(skip_ci_check: merge_when_pipeline_succeeds_active?)
+ unless @merge_request.mergeable?(skip_ci_check: auto_merge_requested?)
return :failed
end
@@ -274,23 +272,15 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
@merge_request.update(merge_error: nil, squash: merge_params.fetch(:squash, false))
- if params[:merge_when_pipeline_succeeds].present?
- return :failed unless @merge_request.actual_head_pipeline
-
- if @merge_request.actual_head_pipeline.active?
- ::MergeRequests::MergeWhenPipelineSucceedsService
- .new(@project, current_user, merge_params)
- .execute(@merge_request)
-
- :merge_when_pipeline_succeeds
- elsif @merge_request.actual_head_pipeline.success?
- # This can be triggered when a user clicks the auto merge button while
- # the tests finish at about the same time
- @merge_request.merge_async(current_user.id, merge_params)
-
- :success
+ if auto_merge_requested?
+ if merge_request.auto_merge_enabled?
+ # TODO: We should have a dedicated endpoint for updating merge params.
+ # See https://gitlab.com/gitlab-org/gitlab-ce/issues/63130.
+ AutoMergeService.new(project, current_user, merge_params).update(merge_request)
else
- :failed
+ AutoMergeService.new(project, current_user, merge_params)
+ .execute(merge_request,
+ params[:auto_merge_strategy] || AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
end
else
@merge_request.merge_async(current_user.id, merge_params)
diff --git a/app/controllers/projects/mirrors_controller.rb b/app/controllers/projects/mirrors_controller.rb
index ef330ae00f4..6c6adc233b7 100644
--- a/app/controllers/projects/mirrors_controller.rb
+++ b/app/controllers/projects/mirrors_controller.rb
@@ -81,6 +81,7 @@ class Projects::MirrorsController < Projects::ApplicationController
password
ssh_known_hosts
regenerate_ssh_private_key
+ _destroy
]
]
end
diff --git a/app/controllers/projects/pages_domains_controller.rb b/app/controllers/projects/pages_domains_controller.rb
index 58b1bc54181..89f21d8dadb 100644
--- a/app/controllers/projects/pages_domains_controller.rb
+++ b/app/controllers/projects/pages_domains_controller.rb
@@ -65,11 +65,11 @@ class Projects::PagesDomainsController < Projects::ApplicationController
private
def create_params
- params.require(:pages_domain).permit(:key, :certificate, :domain)
+ params.require(:pages_domain).permit(:key, :certificate, :domain, :auto_ssl_enabled)
end
def update_params
- params.require(:pages_domain).permit(:key, :certificate)
+ params.require(:pages_domain).permit(:key, :certificate, :auto_ssl_enabled)
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb
index 6b721c8fdf7..72e939a3310 100644
--- a/app/controllers/projects/pipeline_schedules_controller.rb
+++ b/app/controllers/projects/pipeline_schedules_controller.rb
@@ -98,7 +98,7 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController
def schedule_params
params.require(:schedule)
.permit(:description, :cron, :cron_timezone, :ref, :active,
- variables_attributes: [:id, :key, :secret_value, :_destroy] )
+ variables_attributes: [:id, :variable_type, :key, :secret_value, :_destroy] )
end
def authorize_play_pipeline_schedule!
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 22c4b8eef1f..db3b7c8b177 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -169,7 +169,7 @@ class Projects::PipelinesController < Projects::ApplicationController
end
def create_params
- params.require(:pipeline).permit(:ref, variables_attributes: %i[key secret_value])
+ params.require(:pipeline).permit(:ref, variables_attributes: %i[key variable_type secret_value])
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb
index 4eeaeb860ee..3b4215b766e 100644
--- a/app/controllers/projects/repositories_controller.rb
+++ b/app/controllers/projects/repositories_controller.rb
@@ -23,7 +23,7 @@ class Projects::RepositoriesController < Projects::ApplicationController
append_sha = false if @filename == shortname
end
- send_git_archive @repository, ref: @ref, format: params[:format], append_sha: append_sha
+ send_git_archive @repository, ref: @ref, path: params[:path], format: params[:format], append_sha: append_sha
rescue => ex
logger.error("#{self.class.name}: #{ex}")
git_not_found!
diff --git a/app/controllers/projects/serverless/functions_controller.rb b/app/controllers/projects/serverless/functions_controller.rb
index 8c3d141c888..4b0d001fca6 100644
--- a/app/controllers/projects/serverless/functions_controller.rb
+++ b/app/controllers/projects/serverless/functions_controller.rb
@@ -3,8 +3,6 @@
module Projects
module Serverless
class FunctionsController < Projects::ApplicationController
- include ProjectUnauthorized
-
before_action :authorize_read_cluster!
def index
@@ -12,15 +10,13 @@ module Projects
format.json do
functions = finder.execute
- if functions.any?
- render json: serialize_function(functions)
- else
- head :no_content
- end
+ render json: {
+ knative_installed: finder.knative_installed,
+ functions: serialize_function(functions)
+ }.to_json
end
format.html do
- @installed = finder.installed?
render
end
end
diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb
index d1c5cef76fa..1b8d479209b 100644
--- a/app/controllers/projects/settings/ci_cd_controller.rb
+++ b/app/controllers/projects/settings/ci_cd_controller.rb
@@ -19,7 +19,7 @@ module Projects
redirect_to project_settings_ci_cd_path(@project)
else
- render 'show'
+ redirect_to project_settings_ci_cd_path(@project), alert: result[:message]
end
end
end
@@ -50,7 +50,8 @@ module Projects
:runners_token, :builds_enabled, :build_allow_git_fetch,
:build_timeout_human_readable, :build_coverage_regex, :public_builds,
:auto_cancel_pending_pipelines, :ci_config_path,
- auto_devops_attributes: [:id, :domain, :enabled, :deploy_strategy]
+ auto_devops_attributes: [:id, :domain, :enabled, :deploy_strategy],
+ ci_cd_settings_attributes: [:default_git_depth]
)
end
diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb
index 1fafc33e917..5cfb0ac307d 100644
--- a/app/controllers/projects/settings/operations_controller.rb
+++ b/app/controllers/projects/settings/operations_controller.rb
@@ -56,6 +56,8 @@ module Projects
# overridden in EE
def permitted_project_params
{
+ metrics_setting_attributes: [:external_dashboard_url],
+
error_tracking_setting_attributes: [
:enabled,
:api_host,
diff --git a/app/controllers/projects/stages_controller.rb b/app/controllers/projects/stages_controller.rb
new file mode 100644
index 00000000000..c8db5b1277f
--- /dev/null
+++ b/app/controllers/projects/stages_controller.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class Projects::StagesController < Projects::PipelinesController
+ before_action :authorize_update_pipeline!
+
+ def play_manual
+ ::Ci::PlayManualStageService
+ .new(@project, current_user, pipeline: pipeline)
+ .execute(stage)
+
+ respond_to do |format|
+ format.json do
+ render json: StageSerializer
+ .new(project: @project, current_user: @current_user)
+ .represent(stage)
+ end
+ end
+ end
+
+ private
+
+ def stage
+ @pipeline_stage ||= pipeline.find_stage_by_name!(params[:stage_name])
+ end
+end
diff --git a/app/controllers/projects/variables_controller.rb b/app/controllers/projects/variables_controller.rb
index 05a79d59ffd..646728e8167 100644
--- a/app/controllers/projects/variables_controller.rb
+++ b/app/controllers/projects/variables_controller.rb
@@ -38,6 +38,6 @@ class Projects::VariablesController < Projects::ApplicationController
end
def variable_params_attributes
- %i[id key secret_value protected masked _destroy]
+ %i[id variable_type key secret_value protected masked _destroy]
end
end
diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb
index 88910c91763..fa5bdbc7d49 100644
--- a/app/controllers/projects/wikis_controller.rb
+++ b/app/controllers/projects/wikis_controller.rb
@@ -17,7 +17,7 @@ class Projects::WikisController < Projects::ApplicationController
def pages
@wiki_pages = Kaminari.paginate_array(
- @project_wiki.pages(sort: params[:sort], direction: params[:direction])
+ @project_wiki.list_pages(sort: params[:sort], direction: params[:direction])
).page(params[:page])
@wiki_entries = WikiPage.group_by_directory(@wiki_pages)
@@ -118,7 +118,7 @@ class Projects::WikisController < Projects::ApplicationController
@sidebar_page = @project_wiki.find_sidebar(params[:version_id])
unless @sidebar_page # Fallback to default sidebar
- @sidebar_wiki_entries = WikiPage.group_by_directory(@project_wiki.pages(limit: 15))
+ @sidebar_wiki_entries = WikiPage.group_by_directory(@project_wiki.list_pages(limit: 15))
end
rescue ProjectWiki::CouldNotCreateWikiError
flash[:notice] = _("Could not create Wiki Repository at this time. Please try again later.")
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 48f4d7a586d..12db493978b 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -7,6 +7,7 @@ class ProjectsController < Projects::ApplicationController
include PreviewMarkdown
include SendFileUpload
include RecordUserLastActivity
+ include ImportUrlParams
prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) }
@@ -36,10 +37,10 @@ class ProjectsController < Projects::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def new
- namespace = Namespace.find_by(id: params[:namespace_id]) if params[:namespace_id]
- return access_denied! if namespace && !can?(current_user, :create_projects, namespace)
+ @namespace = Namespace.find_by(id: params[:namespace_id]) if params[:namespace_id]
+ return access_denied! if @namespace && !can?(current_user, :create_projects, @namespace)
- @project = Project.new(namespace_id: namespace&.id)
+ @project = Project.new(namespace_id: @namespace&.id)
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -333,6 +334,7 @@ class ProjectsController < Projects::ApplicationController
def project_params(attributes: [])
params.require(:project)
.permit(project_params_attributes + attributes)
+ .merge(import_url_params)
end
def project_params_attributes
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 0fa4677ced1..07b38371ab9 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -4,6 +4,7 @@ class RegistrationsController < Devise::RegistrationsController
include Recaptcha::Verify
include AcceptsPendingInvitations
+ prepend_before_action :check_captcha, only: :create
before_action :whitelist_query_limiting, only: [:destroy]
before_action :ensure_terms_accepted,
if: -> { Gitlab::CurrentSettings.current_application_settings.enforce_terms? },
@@ -21,15 +22,10 @@ class RegistrationsController < Devise::RegistrationsController
params[resource_name] = params.delete(:"new_#{resource_name}")
end
- if !Gitlab::Recaptcha.load_configurations! || verify_recaptcha
- accept_pending_invitations
- super do |new_user|
- persist_accepted_terms_if_required(new_user)
- end
- else
- flash[:alert] = s_('Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.')
- flash.delete :recaptcha_error
- render action: 'new'
+ accept_pending_invitations
+
+ super do |new_user|
+ persist_accepted_terms_if_required(new_user)
end
rescue Gitlab::Access::AccessDeniedError
redirect_to(new_user_session_path)
@@ -89,6 +85,17 @@ class RegistrationsController < Devise::RegistrationsController
private
+ def check_captcha
+ return unless Feature.enabled?(:registrations_recaptcha, default_enabled: true)
+ return unless Gitlab::Recaptcha.load_configurations!
+
+ return if verify_recaptcha
+
+ flash[:alert] = _('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.')
+ flash.delete :recaptcha_error
+ render action: 'new'
+ end
+
def sign_up_params
params.require(:user).permit(:username, :email, :email_confirmation, :name, :password)
end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 6943795e8ac..a841859621e 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -8,6 +8,8 @@ class SessionsController < Devise::SessionsController
include Recaptcha::Verify
skip_before_action :check_two_factor_requirement, only: [:destroy]
+ # replaced with :require_no_authentication_without_flash
+ skip_before_action :require_no_authentication, only: [:new, :create]
prepend_before_action :check_initial_setup, only: [:new]
prepend_before_action :authenticate_with_two_factor,
@@ -15,6 +17,9 @@ class SessionsController < Devise::SessionsController
prepend_before_action :check_captcha, only: [:create]
prepend_before_action :store_redirect_uri, only: [:new]
prepend_before_action :ldap_servers, only: [:new, :create]
+ prepend_before_action :require_no_authentication_without_flash, only: [:new, :create]
+ prepend_before_action :ensure_password_authentication_enabled!, if: :password_based_login?, only: [:create]
+
before_action :auto_sign_in_with_provider, only: [:new]
before_action :load_recaptcha
@@ -54,6 +59,14 @@ class SessionsController < Devise::SessionsController
private
+ def require_no_authentication_without_flash
+ require_no_authentication
+
+ if flash[:alert] == I18n.t('devise.failure.already_authenticated')
+ flash[:alert] = nil
+ end
+ end
+
def captcha_enabled?
request.headers[CAPTCHA_HEADER] && Gitlab::Recaptcha.enabled?
end
@@ -126,6 +139,14 @@ class SessionsController < Devise::SessionsController
end
# rubocop: enable CodeReuse/ActiveRecord
+ def ensure_password_authentication_enabled!
+ render_403 unless Gitlab::CurrentSettings.password_authentication_enabled_for_web?
+ end
+
+ def password_based_login?
+ user_params[:login].present? || user_params[:password].present?
+ end
+
def user_params
params.require(:user).permit(:login, :password, :remember_me, :otp_attempt, :device_response)
end
diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb
index 568c6e2a852..5d28635232b 100644
--- a/app/controllers/uploads_controller.rb
+++ b/app/controllers/uploads_controller.rb
@@ -45,7 +45,7 @@ class UploadsController < ApplicationController
when Appearance
true
else
- permission = "read_#{model.class.to_s.underscore}".to_sym
+ permission = "read_#{model.class.underscore}".to_sym
can?(current_user, permission, model)
end
@@ -56,8 +56,9 @@ class UploadsController < ApplicationController
def authorize_create_access!
return unless model
- # for now we support only personal snippets comments
- authorized = can?(current_user, :comment_personal_snippet, model)
+ # for now we support only personal snippets comments. Only personal_snippet
+ # is allowed as a model to #create through routing.
+ authorized = can?(current_user, :create_note, model)
render_unauthorized unless authorized
end
diff --git a/app/finders/autocomplete/users_finder.rb b/app/finders/autocomplete/users_finder.rb
index 45955783be9..ce7d0b8699c 100644
--- a/app/finders/autocomplete/users_finder.rb
+++ b/app/finders/autocomplete/users_finder.rb
@@ -2,6 +2,8 @@
module Autocomplete
class UsersFinder
+ include Gitlab::Utils::StrongMemoize
+
# The number of users to display in the results is hardcoded to 20, and
# pagination is not supported. This ensures that performance remains
# consistent and removes the need for implementing keyset pagination to
@@ -31,7 +33,7 @@ module Autocomplete
# Include current user if available to filter by "Me"
items.unshift(current_user) if prepend_current_user?
- if prepend_author? && (author = User.find_by_id(author_id))
+ if prepend_author? && author&.active?
items.unshift(author)
end
end
@@ -41,6 +43,12 @@ module Autocomplete
private
+ def author
+ strong_memoize(:author) do
+ User.find_by_id(author_id)
+ end
+ end
+
# Returns the users based on the input parameters, as an Array.
#
# This method is separate so it is easier to extend in EE.
diff --git a/app/finders/clusters/knative_services_finder.rb b/app/finders/clusters/knative_services_finder.rb
new file mode 100644
index 00000000000..7d3b53ef663
--- /dev/null
+++ b/app/finders/clusters/knative_services_finder.rb
@@ -0,0 +1,112 @@
+# frozen_string_literal: true
+module Clusters
+ class KnativeServicesFinder
+ include ReactiveCaching
+ include Gitlab::Utils::StrongMemoize
+
+ KNATIVE_STATES = {
+ 'checking' => 'checking',
+ 'installed' => 'installed',
+ 'not_found' => 'not_found'
+ }.freeze
+
+ self.reactive_cache_key = ->(finder) { finder.model_name }
+ self.reactive_cache_worker_finder = ->(_id, *cache_args) { from_cache(*cache_args) }
+
+ attr_reader :cluster, :project
+
+ def initialize(cluster, project)
+ @cluster = cluster
+ @project = project
+ end
+
+ def with_reactive_cache_memoized(*cache_args, &block)
+ strong_memoize(:reactive_cache) do
+ with_reactive_cache(*cache_args, &block)
+ end
+ end
+
+ def clear_cache!
+ clear_reactive_cache!(*cache_args)
+ end
+
+ def self.from_cache(cluster_id, project_id)
+ cluster = Clusters::Cluster.find(cluster_id)
+ project = ::Project.find(project_id)
+
+ new(cluster, project)
+ end
+
+ def calculate_reactive_cache(*)
+ # read_services calls knative_client.discover implicitily. If we stop
+ # detecting services but still want to detect knative, we'll need to
+ # explicitily call: knative_client.discover
+ #
+ # We didn't create it separately to avoid 2 cluster requests.
+ ksvc = read_services
+ pods = knative_client.discovered ? read_pods : []
+ { services: ksvc, pods: pods, knative_detected: knative_client.discovered }
+ end
+
+ def services
+ return [] unless search_namespace
+
+ cached_data = with_reactive_cache_memoized(*cache_args) { |data| data }
+ cached_data.to_h.fetch(:services, [])
+ end
+
+ def cache_args
+ [cluster.id, project.id]
+ end
+
+ def service_pod_details(service)
+ cached_data = with_reactive_cache_memoized(*cache_args) { |data| data }
+ cached_data.to_h.fetch(:pods, []).select do |pod|
+ filter_pods(pod, service)
+ end
+ end
+
+ def knative_detected
+ cached_data = with_reactive_cache_memoized(*cache_args) { |data| data }
+
+ knative_state = cached_data.to_h[:knative_detected]
+
+ return KNATIVE_STATES['checking'] if knative_state.nil?
+ return KNATIVE_STATES['installed'] if knative_state
+
+ KNATIVE_STATES['uninstalled']
+ end
+
+ def model_name
+ self.class.name.underscore.tr('/', '_')
+ end
+
+ private
+
+ def search_namespace
+ @search_namespace ||= cluster.kubernetes_namespace_for(project)
+ end
+
+ def knative_client
+ cluster.kubeclient.knative_client
+ end
+
+ def filter_pods(pod, service)
+ pod["metadata"]["labels"]["serving.knative.dev/service"] == service
+ end
+
+ def read_services
+ knative_client.get_services(namespace: search_namespace).as_json
+ rescue Kubeclient::ResourceNotFoundError
+ []
+ end
+
+ def read_pods
+ cluster.kubeclient.core_client.get_pods(namespace: search_namespace).as_json
+ end
+
+ def id
+ nil
+ end
+ end
+end
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 88ec77426d5..3592505a977 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -29,6 +29,7 @@
# updated_after: datetime
# updated_before: datetime
# attempt_group_search_optimizations: boolean
+# attempt_project_search_optimizations: boolean
#
class IssuableFinder
prepend FinderWithCrossProjectAccess
@@ -42,7 +43,7 @@ class IssuableFinder
FILTER_NONE = 'none'.freeze
FILTER_ANY = 'any'.freeze
- # This is accepted as a deprecated filter and is also used in unassigning users
+ # This is used in unassigning users
NONE = '0'.freeze
attr_accessor :current_user, :params
@@ -53,6 +54,7 @@ class IssuableFinder
assignee_username
author_id
author_username
+ label_name
milestone_title
my_reaction_emoji
search
@@ -183,7 +185,6 @@ class IssuableFinder
@project = project
end
- # rubocop: disable CodeReuse/ActiveRecord
def projects
return @projects if defined?(@projects)
@@ -191,17 +192,25 @@ class IssuableFinder
projects =
if current_user && params[:authorized_only].presence && !current_user_related?
- current_user.authorized_projects
+ current_user.authorized_projects(min_access_level)
elsif group
- finder_options = { include_subgroups: params[:include_subgroups], only_owned: true }
- GroupProjectsFinder.new(group: group, current_user: current_user, options: finder_options).execute # rubocop: disable CodeReuse/Finder
+ find_group_projects
else
- ProjectsFinder.new(current_user: current_user).execute # rubocop: disable CodeReuse/Finder
+ Project.public_or_visible_to_user(current_user, min_access_level)
end
- @projects = projects.with_feature_available_for_user(klass, current_user).reorder(nil)
+ @projects = projects.with_feature_available_for_user(klass, current_user).reorder(nil) # rubocop: disable CodeReuse/ActiveRecord
+ end
+
+ def find_group_projects
+ return Project.none unless group
+
+ if params[:include_subgroups]
+ Project.where(namespace_id: group.self_and_descendants) # rubocop: disable CodeReuse/ActiveRecord
+ else
+ group.projects
+ end.public_or_visible_to_user(current_user, min_access_level)
end
- # rubocop: enable CodeReuse/ActiveRecord
def search
params[:search].presence
@@ -239,8 +248,7 @@ class IssuableFinder
def filter_by_no_label?
downcased = label_names.map(&:downcase)
- # Label::NONE is deprecated and should be removed in 12.0
- downcased.include?(FILTER_NONE) || downcased.include?(Label::NONE)
+ downcased.include?(FILTER_NONE)
end
def filter_by_any_label?
@@ -337,7 +345,7 @@ class IssuableFinder
def attempt_project_search_optimizations?
params[:attempt_project_search_optimizations] &&
- Feature.enabled?(:attempt_project_search_optimizations)
+ Feature.enabled?(:attempt_project_search_optimizations, default_enabled: true)
end
def count_key(value)
@@ -440,8 +448,7 @@ class IssuableFinder
# rubocop: enable CodeReuse/ActiveRecord
def filter_by_no_assignee?
- # Assignee_id takes precedence over assignee_username
- [NONE, FILTER_NONE].include?(params[:assignee_id].to_s.downcase) || params[:assignee_username].to_s == NONE
+ params[:assignee_id].to_s.downcase == FILTER_NONE
end
def filter_by_any_assignee?
@@ -569,4 +576,8 @@ class IssuableFinder
scope = params[:scope]
scope == 'created_by_me' || scope == 'authored' || scope == 'assigned_to_me'
end
+
+ def min_access_level
+ ProjectFeature.required_minimum_access_level(klass)
+ end
end
diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb
index e6a82f55856..58a01d598ba 100644
--- a/app/finders/issues_finder.rb
+++ b/app/finders/issues_finder.rb
@@ -48,9 +48,9 @@ class IssuesFinder < IssuableFinder
OR (issues.confidential = TRUE
AND (issues.author_id = :user_id
OR EXISTS (SELECT TRUE FROM issue_assignees WHERE user_id = :user_id AND issue_id = issues.id)
- OR issues.project_id IN(:project_ids)))',
+ OR EXISTS (:authorizations)))',
user_id: current_user.id,
- project_ids: current_user.authorized_projects(CONFIDENTIAL_ACCESS_LEVEL).select(:id))
+ authorizations: current_user.authorizations_for_projects(min_access_level: CONFIDENTIAL_ACCESS_LEVEL, related_project_column: "issues.project_id"))
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/finders/members_finder.rb b/app/finders/members_finder.rb
index f90a7868102..917de249104 100644
--- a/app/finders/members_finder.rb
+++ b/app/finders/members_finder.rb
@@ -9,25 +9,18 @@ class MembersFinder
@group = project.group
end
- # rubocop: disable CodeReuse/ActiveRecord
- def execute(include_descendants: false)
+ def execute(include_descendants: false, include_invited_groups_members: false)
project_members = project.project_members
project_members = project_members.non_invite unless can?(current_user, :admin_project, project)
- if group
- group_members = GroupMembersFinder.new(group).execute(include_descendants: include_descendants) # rubocop: disable CodeReuse/Finder
- group_members = group_members.non_invite
+ union_members = group_union_members(include_descendants, include_invited_groups_members)
- union = Gitlab::SQL::Union.new([project_members, group_members], remove_duplicates: false) # rubocop: disable Gitlab/Union
-
- sql = distinct_on(union)
-
- Member.includes(:user).from("(#{sql}) AS #{Member.table_name}")
+ if union_members.any?
+ distinct_union_of_members(union_members << project_members)
else
project_members
end
end
- # rubocop: enable CodeReuse/ActiveRecord
def can?(*args)
Ability.allowed?(*args)
@@ -35,6 +28,34 @@ class MembersFinder
private
+ def group_union_members(include_descendants, include_invited_groups_members)
+ [].tap do |members|
+ members << direct_group_members(include_descendants) if group
+ members << project_invited_groups_members if include_invited_groups_members
+ end
+ end
+
+ def direct_group_members(include_descendants)
+ GroupMembersFinder.new(group).execute(include_descendants: include_descendants).non_invite # rubocop: disable CodeReuse/Finder
+ end
+
+ def project_invited_groups_members
+ invited_groups_ids_including_ancestors = Gitlab::ObjectHierarchy
+ .new(project.invited_groups)
+ .base_and_ancestors
+ .public_or_visible_to_user(current_user)
+ .select(:id)
+
+ GroupMember.with_source_id(invited_groups_ids_including_ancestors)
+ end
+
+ def distinct_union_of_members(union_members)
+ union = Gitlab::SQL::Union.new(union_members, remove_duplicates: false) # rubocop: disable Gitlab/Union
+ sql = distinct_on(union)
+
+ Member.includes(:user).from([Arel.sql("(#{sql}) AS #{Member.table_name}")]) # rubocop: disable CodeReuse/ActiveRecord
+ end
+
def distinct_on(union)
# We're interested in a list of members without duplicates by user_id.
# We prefer project members over group members, project members should go first.
diff --git a/app/finders/projects/serverless/functions_finder.rb b/app/finders/projects/serverless/functions_finder.rb
index d9802598c64..ebe50806ca1 100644
--- a/app/finders/projects/serverless/functions_finder.rb
+++ b/app/finders/projects/serverless/functions_finder.rb
@@ -3,6 +3,8 @@
module Projects
module Serverless
class FunctionsFinder
+ attr_reader :project
+
def initialize(project)
@clusters = project.clusters
@project = project
@@ -12,8 +14,16 @@ module Projects
knative_services.flatten.compact
end
- def installed?
- clusters_with_knative_installed.exists?
+ # Possible return values: Clusters::KnativeServicesFinder::KNATIVE_STATE
+ def knative_installed
+ states = @clusters.map do |cluster|
+ cluster.application_knative
+ cluster.knative_services_finder(project).knative_detected.tap do |state|
+ return state if state == ::Clusters::KnativeServicesFinder::KNATIVE_STATES['checking'] # rubocop:disable Cop/AvoidReturnFromBlocks
+ end
+ end
+
+ states.any? { |state| state == ::Clusters::KnativeServicesFinder::KNATIVE_STATES['installed'] }
end
def service(environment_scope, name)
@@ -23,16 +33,16 @@ module Projects
def invocation_metrics(environment_scope, name)
return unless prometheus_adapter&.can_query?
- cluster = clusters_with_knative_installed.preload_knative.find do |c|
+ cluster = @clusters.find do |c|
environment_scope == c.environment_scope
end
- func = ::Serverless::Function.new(@project, name, cluster.platform_kubernetes&.actual_namespace)
+ func = ::Serverless::Function.new(project, name, cluster.kubernetes_namespace_for(project))
prometheus_adapter.query(:knative_invocation, func)
end
def has_prometheus?(environment_scope)
- clusters_with_knative_installed.preload_knative.to_a.any? do |cluster|
+ @clusters.any? do |cluster|
environment_scope == cluster.environment_scope && cluster.application_prometheus_available?
end
end
@@ -40,10 +50,12 @@ module Projects
private
def knative_service(environment_scope, name)
- clusters_with_knative_installed.preload_knative.map do |cluster|
+ @clusters.map do |cluster|
next if environment_scope != cluster.environment_scope
- services = cluster.application_knative.services_for(ns: cluster.platform_kubernetes&.actual_namespace)
+ services = cluster
+ .knative_services_finder(project)
+ .services
.select { |svc| svc["metadata"]["name"] == name }
add_metadata(cluster, services).first unless services.nil?
@@ -51,8 +63,11 @@ module Projects
end
def knative_services
- clusters_with_knative_installed.preload_knative.map do |cluster|
- services = cluster.application_knative.services_for(ns: cluster.platform_kubernetes&.actual_namespace)
+ @clusters.map do |cluster|
+ services = cluster
+ .knative_services_finder(project)
+ .services
+
add_metadata(cluster, services) unless services.nil?
end
end
@@ -63,20 +78,17 @@ module Projects
s["cluster_id"] = cluster.id
if services.length == 1
- s["podcount"] = cluster.application_knative.service_pod_details(
- cluster.platform_kubernetes&.actual_namespace,
- s["metadata"]["name"]).length
+ s["podcount"] = cluster
+ .knative_services_finder(project)
+ .service_pod_details(s["metadata"]["name"])
+ .length
end
end
end
- def clusters_with_knative_installed
- @clusters.with_knative_installed
- end
-
# rubocop: disable CodeReuse/ServiceClass
def prometheus_adapter
- @prometheus_adapter ||= ::Prometheus::AdapterService.new(@project).prometheus_adapter
+ @prometheus_adapter ||= ::Prometheus::AdapterService.new(project).prometheus_adapter
end
# rubocop: enable CodeReuse/ServiceClass
end
diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb
index 93d3c991846..23b731b1aed 100644
--- a/app/finders/projects_finder.rb
+++ b/app/finders/projects_finder.rb
@@ -62,7 +62,7 @@ class ProjectsFinder < UnionFinder
collection = by_personal(collection)
collection = by_starred(collection)
collection = by_trending(collection)
- collection = by_visibilty_level(collection)
+ collection = by_visibility_level(collection)
collection = by_tags(collection)
collection = by_search(collection)
collection = by_archived(collection)
@@ -71,12 +71,11 @@ class ProjectsFinder < UnionFinder
collection
end
- # rubocop: disable CodeReuse/ActiveRecord
def collection_with_user
if owned_projects?
current_user.owned_projects
elsif min_access_level?
- current_user.authorized_projects.where('project_authorizations.access_level >= ?', params[:min_access_level])
+ current_user.authorized_projects(params[:min_access_level])
else
if private_only?
current_user.authorized_projects
@@ -85,7 +84,6 @@ class ProjectsFinder < UnionFinder
end
end
end
- # rubocop: enable CodeReuse/ActiveRecord
# Builds a collection for an anonymous user.
def collection_without_user
@@ -131,7 +129,7 @@ class ProjectsFinder < UnionFinder
end
# rubocop: disable CodeReuse/ActiveRecord
- def by_visibilty_level(items)
+ def by_visibility_level(items)
params[:visibility_level].present? ? items.where(visibility_level: params[:visibility_level]) : items
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/graphql/gitlab_schema.rb b/app/graphql/gitlab_schema.rb
index 1afe000c5f8..2e5bdbd79c8 100644
--- a/app/graphql/gitlab_schema.rb
+++ b/app/graphql/gitlab_schema.rb
@@ -7,37 +7,91 @@ class GitlabSchema < GraphQL::Schema
AUTHENTICATED_COMPLEXITY = 250
ADMIN_COMPLEXITY = 300
+ DEFAULT_MAX_DEPTH = 10
+ AUTHENTICATED_MAX_DEPTH = 15
+
use BatchLoader::GraphQL
use Gitlab::Graphql::Authorize
use Gitlab::Graphql::Present
use Gitlab::Graphql::Connections
- use Gitlab::Graphql::Tracing
+ use Gitlab::Graphql::GenericTracing
- query_analyzer Gitlab::Graphql::QueryAnalyzers::LogQueryComplexity.analyzer
+ query_analyzer Gitlab::Graphql::QueryAnalyzers::LoggerAnalyzer.new
query(Types::QueryType)
default_max_page_size 100
max_complexity DEFAULT_MAX_COMPLEXITY
+ max_depth DEFAULT_MAX_DEPTH
mutation(Types::MutationType)
- def self.execute(query_str = nil, **kwargs)
- kwargs[:max_complexity] ||= max_query_complexity(kwargs[:context])
+ class << self
+ def multiplex(queries, **kwargs)
+ kwargs[:max_complexity] ||= max_query_complexity(kwargs[:context])
- super(query_str, **kwargs)
- end
+ queries.each do |query|
+ query[:max_depth] = max_query_depth(kwargs[:context])
+ end
+
+ super(queries, **kwargs)
+ end
+
+ def execute(query_str = nil, **kwargs)
+ kwargs[:max_complexity] ||= max_query_complexity(kwargs[:context])
+ kwargs[:max_depth] ||= max_query_depth(kwargs[:context])
+
+ super(query_str, **kwargs)
+ end
+
+ def id_from_object(object)
+ unless object.respond_to?(:to_global_id)
+ # This is an error in our schema and needs to be solved. So raise a
+ # more meaningfull error message
+ raise "#{object} does not implement `to_global_id`. "\
+ "Include `GlobalID::Identification` into `#{object.class}"
+ end
+
+ object.to_global_id
+ end
+
+ def object_from_id(global_id)
+ gid = GlobalID.parse(global_id)
+
+ unless gid
+ raise Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid GitLab id."
+ end
+
+ if gid.model_class < ApplicationRecord
+ Gitlab::Graphql::Loaders::BatchModelLoader.new(gid.model_class, gid.model_id).find
+ else
+ gid.find
+ end
+ end
+
+ private
+
+ def max_query_complexity(ctx)
+ current_user = ctx&.fetch(:current_user, nil)
+
+ if current_user&.admin
+ ADMIN_COMPLEXITY
+ elsif current_user
+ AUTHENTICATED_COMPLEXITY
+ else
+ DEFAULT_MAX_COMPLEXITY
+ end
+ end
- def self.max_query_complexity(ctx)
- current_user = ctx&.fetch(:current_user, nil)
+ def max_query_depth(ctx)
+ current_user = ctx&.fetch(:current_user, nil)
- if current_user&.admin
- ADMIN_COMPLEXITY
- elsif current_user
- AUTHENTICATED_COMPLEXITY
- else
- DEFAULT_MAX_COMPLEXITY
+ if current_user
+ AUTHENTICATED_MAX_DEPTH
+ else
+ DEFAULT_MAX_DEPTH
+ end
end
end
end
diff --git a/app/graphql/mutations/merge_requests/base.rb b/app/graphql/mutations/merge_requests/base.rb
index 7d0cb777ad1..e85d16fc2c5 100644
--- a/app/graphql/mutations/merge_requests/base.rb
+++ b/app/graphql/mutations/merge_requests/base.rb
@@ -10,7 +10,7 @@ module Mutations
required: true,
description: "The project the merge request to mutate is in"
- argument :iid, GraphQL::ID_TYPE,
+ argument :iid, GraphQL::STRING_TYPE,
required: true,
description: "The iid of the merge request to mutate"
diff --git a/app/graphql/resolvers/base_resolver.rb b/app/graphql/resolvers/base_resolver.rb
index 063def75d38..5b7eb57841c 100644
--- a/app/graphql/resolvers/base_resolver.rb
+++ b/app/graphql/resolvers/base_resolver.rb
@@ -9,5 +9,24 @@ module Resolvers
end
end
end
+
+ def self.resolver_complexity(args, child_complexity:)
+ complexity = 1
+ complexity += 1 if args[:sort]
+ complexity += 5 if args[:search]
+
+ complexity
+ end
+
+ def self.complexity_multiplier(args)
+ # When fetching many items, additional complexity is added to the field
+ # depending on how many items is fetched. For each item we add 1% of the
+ # original complexity - this means that loading 100 items (our default
+ # maxp_age_size limit) doubles the original complexity.
+ #
+ # Complexity is not increased when searching by specific ID(s), because
+ # complexity difference is minimal in this case.
+ [args[:iid], args[:iids]].any? ? 0 : 0.01
+ end
end
end
diff --git a/app/graphql/resolvers/concerns/resolves_pipelines.rb b/app/graphql/resolvers/concerns/resolves_pipelines.rb
index 8fd26d85994..a6f82cc8505 100644
--- a/app/graphql/resolvers/concerns/resolves_pipelines.rb
+++ b/app/graphql/resolvers/concerns/resolves_pipelines.rb
@@ -19,6 +19,16 @@ module ResolvesPipelines
description: "Filter pipelines by the sha of the commit they are run for"
end
+ class_methods do
+ def resolver_complexity(args, child_complexity:)
+ complexity = super
+ complexity += 2 if args[:sha]
+ complexity += 2 if args[:ref]
+
+ complexity
+ end
+ end
+
def resolve_pipelines(project, params = {})
PipelinesFinder.new(project, context[:current_user], params).execute
end
diff --git a/app/graphql/resolvers/full_path_resolver.rb b/app/graphql/resolvers/full_path_resolver.rb
index 0f1a64b6c58..972f318c806 100644
--- a/app/graphql/resolvers/full_path_resolver.rb
+++ b/app/graphql/resolvers/full_path_resolver.rb
@@ -7,14 +7,14 @@ module Resolvers
prepended do
argument :full_path, GraphQL::ID_TYPE,
required: true,
- description: 'The full path of the project or namespace, e.g., "gitlab-org/gitlab-ce"'
+ description: 'The full path of the project, group or namespace, e.g., "gitlab-org/gitlab-ce"'
end
def model_by_full_path(model, full_path)
BatchLoader.for(full_path).batch(key: model) do |full_paths, loader, args|
# `with_route` avoids an N+1 calculating full_path
- args[:key].where_full_path_in(full_paths).with_route.each do |project|
- loader.call(project.full_path, project)
+ args[:key].where_full_path_in(full_paths).with_route.each do |model_instance|
+ loader.call(model_instance.full_path, model_instance)
end
end
end
diff --git a/app/graphql/resolvers/group_resolver.rb b/app/graphql/resolvers/group_resolver.rb
new file mode 100644
index 00000000000..4260e18829e
--- /dev/null
+++ b/app/graphql/resolvers/group_resolver.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class GroupResolver < BaseResolver
+ prepend FullPathResolver
+
+ type Types::GroupType, null: true
+
+ def resolve(full_path:)
+ model_by_full_path(Group, full_path)
+ end
+ end
+end
diff --git a/app/graphql/resolvers/issues_resolver.rb b/app/graphql/resolvers/issues_resolver.rb
index b98d8bd1fff..6988b451ec3 100644
--- a/app/graphql/resolvers/issues_resolver.rb
+++ b/app/graphql/resolvers/issues_resolver.rb
@@ -2,11 +2,11 @@
module Resolvers
class IssuesResolver < BaseResolver
- argument :iid, GraphQL::ID_TYPE,
+ argument :iid, GraphQL::STRING_TYPE,
required: false,
description: 'The IID of the issue, e.g., "1"'
- argument :iids, [GraphQL::ID_TYPE],
+ argument :iids, [GraphQL::STRING_TYPE],
required: false,
description: 'The list of IIDs of issues, e.g., [1, 2]'
argument :state, Types::IssuableStateEnum,
@@ -44,6 +44,12 @@ module Resolvers
alias_method :project, :object
def resolve(**args)
+ # The project could have been loaded in batch by `BatchLoader`.
+ # At this point we need the `id` of the project to query for issues, so
+ # make sure it's loaded and not `nil` before continuing.
+ project.sync if project.respond_to?(:sync)
+ return Issue.none if project.nil?
+
# Will need to be be made group & namespace aware with
# https://gitlab.com/gitlab-org/gitlab-ce/issues/54520
args[:project_id] = project.id
@@ -51,5 +57,12 @@ module Resolvers
IssuesFinder.new(context[:current_user], args).execute
end
+
+ def self.resolver_complexity(args, child_complexity:)
+ complexity = super
+ complexity += 2 if args[:labelName]
+
+ complexity
+ end
end
end
diff --git a/app/graphql/resolvers/merge_requests_resolver.rb b/app/graphql/resolvers/merge_requests_resolver.rb
index 90795c797ac..b84e60066e1 100644
--- a/app/graphql/resolvers/merge_requests_resolver.rb
+++ b/app/graphql/resolvers/merge_requests_resolver.rb
@@ -2,11 +2,11 @@
module Resolvers
class MergeRequestsResolver < BaseResolver
- argument :iid, GraphQL::ID_TYPE,
+ argument :iid, GraphQL::STRING_TYPE,
required: false,
description: 'The IID of the merge request, e.g., "1"'
- argument :iids, [GraphQL::ID_TYPE],
+ argument :iids, [GraphQL::STRING_TYPE],
required: false,
description: 'The list of IIDs of issues, e.g., [1, 2]'
diff --git a/app/graphql/resolvers/namespace_projects_resolver.rb b/app/graphql/resolvers/namespace_projects_resolver.rb
new file mode 100644
index 00000000000..677ea808aeb
--- /dev/null
+++ b/app/graphql/resolvers/namespace_projects_resolver.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class NamespaceProjectsResolver < BaseResolver
+ argument :include_subgroups, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ default_value: false,
+ description: 'Include also subgroup projects'
+
+ type Types::ProjectType, null: true
+
+ alias_method :namespace, :object
+
+ def resolve(include_subgroups:)
+ # The namespace could have been loaded in batch by `BatchLoader`.
+ # At this point we need the `id` or the `full_path` of the namespace
+ # to query for projects, so make sure it's loaded and not `nil` before continuing.
+ namespace.sync if namespace.respond_to?(:sync)
+ return Project.none if namespace.nil?
+
+ if include_subgroups
+ namespace.all_projects.with_route
+ else
+ namespace.projects.with_route
+ end
+ end
+
+ def self.resolver_complexity(args, child_complexity:)
+ complexity = super
+ complexity + 10
+ end
+ end
+end
diff --git a/app/graphql/resolvers/namespace_resolver.rb b/app/graphql/resolvers/namespace_resolver.rb
new file mode 100644
index 00000000000..17b3800d151
--- /dev/null
+++ b/app/graphql/resolvers/namespace_resolver.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class NamespaceResolver < BaseResolver
+ prepend FullPathResolver
+
+ type Types::NamespaceType, null: true
+
+ def resolve(full_path:)
+ model_by_full_path(Namespace, full_path)
+ end
+ end
+end
diff --git a/app/graphql/resolvers/project_resolver.rb b/app/graphql/resolvers/project_resolver.rb
index ac7c9b0ce2e..2132447da5e 100644
--- a/app/graphql/resolvers/project_resolver.rb
+++ b/app/graphql/resolvers/project_resolver.rb
@@ -9,5 +9,9 @@ module Resolvers
def resolve(full_path:)
model_by_full_path(Project, full_path)
end
+
+ def self.complexity_multiplier(args)
+ 0
+ end
end
end
diff --git a/app/graphql/resolvers/tree_resolver.rb b/app/graphql/resolvers/tree_resolver.rb
new file mode 100644
index 00000000000..5aad1c71b40
--- /dev/null
+++ b/app/graphql/resolvers/tree_resolver.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class TreeResolver < BaseResolver
+ argument :path, GraphQL::STRING_TYPE,
+ required: false,
+ default_value: '',
+ description: 'The path to get the tree for. Default value is the root of the repository'
+ argument :ref, GraphQL::STRING_TYPE,
+ required: false,
+ default_value: :head,
+ description: 'The commit ref to get the tree for. Default value is HEAD'
+ argument :recursive, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ default_value: false,
+ description: 'Used to get a recursive tree. Default is false'
+
+ alias_method :repository, :object
+
+ def resolve(**args)
+ return unless repository.exists?
+
+ repository.tree(args[:ref], args[:path], recursive: args[:recursive])
+ end
+ end
+end
diff --git a/app/graphql/types/base_field.rb b/app/graphql/types/base_field.rb
index 8c8b8a82d3e..dd0d9105df6 100644
--- a/app/graphql/types/base_field.rb
+++ b/app/graphql/types/base_field.rb
@@ -7,10 +7,43 @@ module Types
DEFAULT_COMPLEXITY = 1
def initialize(*args, **kwargs, &block)
- # complexity is already defaulted to 1, but let's make it explicit
- kwargs[:complexity] ||= DEFAULT_COMPLEXITY
+ kwargs[:complexity] ||= field_complexity(kwargs[:resolver_class])
super(*args, **kwargs, &block)
end
+
+ private
+
+ def field_complexity(resolver_class)
+ if resolver_class
+ field_resolver_complexity
+ else
+ DEFAULT_COMPLEXITY
+ end
+ end
+
+ def field_resolver_complexity
+ # Complexity can be either integer or proc. If proc is used then it's
+ # called when computing a query complexity and context and query
+ # arguments are available for computing complexity. For resolvers we use
+ # proc because we set complexity depending on arguments and number of
+ # items which can be loaded.
+ proc do |ctx, args, child_complexity|
+ # Resolvers may add extra complexity depending on used arguments
+ complexity = child_complexity + self.resolver&.try(:resolver_complexity, args, child_complexity: child_complexity).to_i
+
+ field_defn = to_graphql
+
+ if field_defn.connection?
+ # Resolvers may add extra complexity depending on number of items being loaded.
+ page_size = field_defn.connection_max_page_size || ctx.schema.default_max_page_size
+ limit_value = [args[:first], args[:last], page_size].compact.min
+ multiplier = self.resolver&.try(:complexity_multiplier, args).to_f
+ complexity += complexity * limit_value * multiplier
+ end
+
+ complexity.to_i
+ end
+ end
end
end
diff --git a/app/graphql/types/base_object.rb b/app/graphql/types/base_object.rb
index 82b78abd573..e40059c46bb 100644
--- a/app/graphql/types/base_object.rb
+++ b/app/graphql/types/base_object.rb
@@ -6,5 +6,10 @@ module Types
prepend Gitlab::Graphql::ExposePermissions
field_class Types::BaseField
+
+ # All graphql fields exposing an id, should expose a global id.
+ def id
+ GitlabSchema.id_from_object(object)
+ end
end
end
diff --git a/app/graphql/types/ci/pipeline_type.rb b/app/graphql/types/ci/pipeline_type.rb
index de7d6570a3e..cff81e5670b 100644
--- a/app/graphql/types/ci/pipeline_type.rb
+++ b/app/graphql/types/ci/pipeline_type.rb
@@ -10,7 +10,7 @@ module Types
expose_permissions Types::PermissionTypes::Ci::Pipeline
field :id, GraphQL::ID_TYPE, null: false
- field :iid, GraphQL::ID_TYPE, null: false
+ field :iid, GraphQL::STRING_TYPE, null: false
field :sha, GraphQL::STRING_TYPE, null: false
field :before_sha, GraphQL::STRING_TYPE, null: true
diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb
new file mode 100644
index 00000000000..530aecc2bf9
--- /dev/null
+++ b/app/graphql/types/group_type.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Types
+ class GroupType < NamespaceType
+ graphql_name 'Group'
+
+ authorize :read_group
+
+ expose_permissions Types::PermissionTypes::Group
+
+ field :web_url, GraphQL::STRING_TYPE, null: false
+
+ field :avatar_url, GraphQL::STRING_TYPE, null: true, resolve: -> (group, args, ctx) do
+ group.avatar_url(only_path: false)
+ end
+
+ if ::Group.supports_nested_objects?
+ field :parent, GroupType,
+ null: true,
+ resolve: -> (obj, _args, _ctx) { Gitlab::Graphql::Loaders::BatchModelLoader.new(Group, obj.parent_id).find }
+ end
+ end
+end
diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb
index adb137dfee3..dd5133189dc 100644
--- a/app/graphql/types/issue_type.rb
+++ b/app/graphql/types/issue_type.rb
@@ -15,13 +15,19 @@ module Types
field :description, GraphQL::STRING_TYPE, null: true
field :state, IssueStateEnum, null: false
+ field :reference, GraphQL::STRING_TYPE, null: false, method: :to_reference do
+ argument :full, GraphQL::BOOLEAN_TYPE, required: false, default_value: false
+ end
+
field :author, Types::UserType,
null: false,
resolve: -> (obj, _args, _ctx) { Gitlab::Graphql::Loaders::BatchModelLoader.new(User, obj.author_id).find }
- field :assignees, Types::UserType.connection_type, null: true
+ # Remove complexity when BatchLoader is used
+ field :assignees, Types::UserType.connection_type, null: true, complexity: 5
- field :labels, Types::LabelType.connection_type, null: true
+ # Remove complexity when BatchLoader is used
+ field :labels, Types::LabelType.connection_type, null: true, complexity: 5
field :milestone, Types::MilestoneType,
null: true,
resolve: -> (obj, _args, _ctx) { Gitlab::Graphql::Loaders::BatchModelLoader.new(Milestone, obj.milestone_id).find }
@@ -35,7 +41,9 @@ module Types
field :upvotes, GraphQL::INT_TYPE, null: false
field :downvotes, GraphQL::INT_TYPE, null: false
field :user_notes_count, GraphQL::INT_TYPE, null: false
+ field :web_path, GraphQL::STRING_TYPE, null: false, method: :issue_path
field :web_url, GraphQL::STRING_TYPE, null: false
+ field :relative_position, GraphQL::INT_TYPE, null: true
field :closed_at, Types::TimeType, null: true
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index 120ffe0dfde..85ac3102442 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -11,7 +11,7 @@ module Types
present_using MergeRequestPresenter
field :id, GraphQL::ID_TYPE, null: false
- field :iid, GraphQL::ID_TYPE, null: false
+ field :iid, GraphQL::STRING_TYPE, null: false
field :title, GraphQL::STRING_TYPE, null: false
field :description, GraphQL::STRING_TYPE, null: true
field :state, MergeRequestStateEnum, null: false
diff --git a/app/graphql/types/namespace_type.rb b/app/graphql/types/namespace_type.rb
new file mode 100644
index 00000000000..f6d91320e50
--- /dev/null
+++ b/app/graphql/types/namespace_type.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Types
+ class NamespaceType < BaseObject
+ graphql_name 'Namespace'
+
+ field :id, GraphQL::ID_TYPE, null: false
+
+ field :name, GraphQL::STRING_TYPE, null: false
+ field :path, GraphQL::STRING_TYPE, null: false
+ field :full_name, GraphQL::STRING_TYPE, null: false
+ field :full_path, GraphQL::ID_TYPE, null: false
+
+ field :description, GraphQL::STRING_TYPE, null: true
+ field :visibility, GraphQL::STRING_TYPE, null: true
+ field :lfs_enabled, GraphQL::BOOLEAN_TYPE, null: true, method: :lfs_enabled?
+ field :request_access_enabled, GraphQL::BOOLEAN_TYPE, null: true
+
+ field :projects,
+ Types::ProjectType.connection_type,
+ null: false,
+ resolver: ::Resolvers::NamespaceProjectsResolver
+ end
+end
diff --git a/app/graphql/types/permission_types/group.rb b/app/graphql/types/permission_types/group.rb
new file mode 100644
index 00000000000..29833993ce6
--- /dev/null
+++ b/app/graphql/types/permission_types/group.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Types
+ module PermissionTypes
+ class Group < BasePermissionType
+ graphql_name 'GroupPermissions'
+
+ abilities :read_group
+ end
+ end
+end
diff --git a/app/graphql/types/project_statistics_type.rb b/app/graphql/types/project_statistics_type.rb
new file mode 100644
index 00000000000..62537361918
--- /dev/null
+++ b/app/graphql/types/project_statistics_type.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Types
+ class ProjectStatisticsType < BaseObject
+ graphql_name 'ProjectStatistics'
+
+ field :commit_count, GraphQL::INT_TYPE, null: false
+
+ field :storage_size, GraphQL::INT_TYPE, null: false
+ field :repository_size, GraphQL::INT_TYPE, null: false
+ field :lfs_objects_size, GraphQL::INT_TYPE, null: false
+ field :build_artifacts_size, GraphQL::INT_TYPE, null: false
+ field :packages_size, GraphQL::INT_TYPE, null: false
+ field :wiki_size, GraphQL::INT_TYPE, null: true
+ end
+end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index fbb4eddd13c..2236ffa394d 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -66,6 +66,15 @@ module Types
field :only_allow_merge_if_all_discussions_are_resolved, GraphQL::BOOLEAN_TYPE, null: true
field :printing_merge_request_link_enabled, GraphQL::BOOLEAN_TYPE, null: true
+ field :namespace, Types::NamespaceType, null: false
+ field :group, Types::GroupType, null: true
+
+ field :statistics, Types::ProjectStatisticsType,
+ null: false,
+ resolve: -> (obj, _args, _ctx) { Gitlab::Graphql::Loaders::BatchProjectStatisticsLoader.new(obj.id).find }
+
+ field :repository, Types::RepositoryType, null: false
+
field :merge_requests,
Types::MergeRequestType.connection_type,
null: true,
diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb
index 0f655ab9d03..536bdb077ad 100644
--- a/app/graphql/types/query_type.rb
+++ b/app/graphql/types/query_type.rb
@@ -9,6 +9,16 @@ module Types
resolver: Resolvers::ProjectResolver,
description: "Find a project"
+ field :group, Types::GroupType,
+ null: true,
+ resolver: Resolvers::GroupResolver,
+ description: "Find a group"
+
+ field :namespace, Types::NamespaceType,
+ null: true,
+ resolver: Resolvers::NamespaceResolver,
+ description: "Find a namespace"
+
field :metadata, Types::MetadataType,
null: true,
resolver: Resolvers::MetadataResolver,
diff --git a/app/graphql/types/repository_type.rb b/app/graphql/types/repository_type.rb
new file mode 100644
index 00000000000..5987467e1ea
--- /dev/null
+++ b/app/graphql/types/repository_type.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Types
+ class RepositoryType < BaseObject
+ graphql_name 'Repository'
+
+ authorize :download_code
+
+ field :root_ref, GraphQL::STRING_TYPE, null: true
+ field :empty, GraphQL::BOOLEAN_TYPE, null: false, method: :empty?
+ field :exists, GraphQL::BOOLEAN_TYPE, null: false, method: :exists?
+ field :tree, Types::Tree::TreeType, null: true, resolver: Resolvers::TreeResolver
+ end
+end
diff --git a/app/graphql/types/tree/blob_type.rb b/app/graphql/types/tree/blob_type.rb
new file mode 100644
index 00000000000..760781f3612
--- /dev/null
+++ b/app/graphql/types/tree/blob_type.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+module Types
+ module Tree
+ class BlobType < BaseObject
+ implements Types::Tree::EntryType
+
+ present_using BlobPresenter
+
+ graphql_name 'Blob'
+
+ field :web_url, GraphQL::STRING_TYPE, null: true
+ field :lfs_oid, GraphQL::STRING_TYPE, null: true, resolve: -> (blob, args, ctx) do
+ Gitlab::Graphql::Loaders::BatchLfsOidLoader.new(blob.repository, blob.id).find
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/tree/entry_type.rb b/app/graphql/types/tree/entry_type.rb
new file mode 100644
index 00000000000..d8e8642ddb8
--- /dev/null
+++ b/app/graphql/types/tree/entry_type.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+module Types
+ module Tree
+ module EntryType
+ include Types::BaseInterface
+
+ field :id, GraphQL::ID_TYPE, null: false
+ field :name, GraphQL::STRING_TYPE, null: false
+ field :type, Tree::TypeEnum, null: false
+ field :path, GraphQL::STRING_TYPE, null: false
+ field :flat_path, GraphQL::STRING_TYPE, null: false
+ end
+ end
+end
diff --git a/app/graphql/types/tree/submodule_type.rb b/app/graphql/types/tree/submodule_type.rb
new file mode 100644
index 00000000000..cea76dbfd2a
--- /dev/null
+++ b/app/graphql/types/tree/submodule_type.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+module Types
+ module Tree
+ class SubmoduleType < BaseObject
+ implements Types::Tree::EntryType
+
+ graphql_name 'Submodule'
+ end
+ end
+end
diff --git a/app/graphql/types/tree/tree_entry_type.rb b/app/graphql/types/tree/tree_entry_type.rb
new file mode 100644
index 00000000000..23ec2ef0ec2
--- /dev/null
+++ b/app/graphql/types/tree/tree_entry_type.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+module Types
+ module Tree
+ class TreeEntryType < BaseObject
+ implements Types::Tree::EntryType
+
+ present_using TreeEntryPresenter
+
+ graphql_name 'TreeEntry'
+ description 'Represents a directory'
+
+ field :web_url, GraphQL::STRING_TYPE, null: true
+ end
+ end
+end
diff --git a/app/graphql/types/tree/tree_type.rb b/app/graphql/types/tree/tree_type.rb
new file mode 100644
index 00000000000..1ee93ed9542
--- /dev/null
+++ b/app/graphql/types/tree/tree_type.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+module Types
+ module Tree
+ class TreeType < BaseObject
+ graphql_name 'Tree'
+
+ field :trees, Types::Tree::TreeEntryType.connection_type, null: false, resolve: -> (obj, args, ctx) do
+ Gitlab::Graphql::Representation::TreeEntry.decorate(obj.trees, obj.repository)
+ end
+
+ field :submodules, Types::Tree::SubmoduleType.connection_type, null: false
+
+ field :blobs, Types::Tree::BlobType.connection_type, null: false, resolve: -> (obj, args, ctx) do
+ Gitlab::Graphql::Representation::TreeEntry.decorate(obj.blobs, obj.repository)
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/tree/type_enum.rb b/app/graphql/types/tree/type_enum.rb
new file mode 100644
index 00000000000..6560d91e9e5
--- /dev/null
+++ b/app/graphql/types/tree/type_enum.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Types
+ module Tree
+ class TypeEnum < BaseEnum
+ graphql_name 'EntryType'
+ description 'Type of a tree entry'
+
+ value 'tree', value: :tree
+ value 'blob', value: :blob
+ value 'commit', value: :commit
+ end
+ end
+end
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 5995ef57e26..4469118f065 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -160,6 +160,7 @@ module ApplicationSettingsHelper
:akismet_api_key,
:akismet_enabled,
:allow_local_requests_from_hooks_and_services,
+ :dns_rebinding_protection_enabled,
:archive_builds_in_human_readable,
:authorized_keys_enabled,
:auto_devops_enabled,
@@ -286,4 +287,8 @@ module ApplicationSettingsHelper
def expanded_by_default?
Rails.env.test?
end
+
+ def instance_clusters_enabled?
+ can?(current_user, :read_cluster, Clusters::Instance.new)
+ end
end
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index b4ee648361c..076976175a9 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -2,7 +2,7 @@
module AuthHelper
PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2 facebook azure_oauth2 authentiq).freeze
- LDAP_PROVIDER = /\Aldap/
+ LDAP_PROVIDER = /\Aldap/.freeze
def ldap_enabled?
Gitlab::Auth::LDAP::Config.enabled?
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 7e631053b54..0d6a6496993 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -188,7 +188,7 @@ module BlobHelper
end
def copy_file_path_button(file_path)
- clipboard_button(text: file_path, gfm: "`#{file_path}`", class: 'btn-clipboard btn-transparent prepend-left-5', title: 'Copy file path to clipboard')
+ clipboard_button(text: file_path, gfm: "`#{file_path}`", class: 'btn-clipboard btn-transparent', title: 'Copy file path to clipboard')
end
def copy_blob_source_button(blob)
diff --git a/app/helpers/broadcast_messages_helper.rb b/app/helpers/broadcast_messages_helper.rb
index 289cb44f1e8..495c29d3e24 100644
--- a/app/helpers/broadcast_messages_helper.rb
+++ b/app/helpers/broadcast_messages_helper.rb
@@ -4,7 +4,7 @@ module BroadcastMessagesHelper
def broadcast_message(message)
return unless message.present?
- content_tag :div, class: 'broadcast-message', style: broadcast_message_style(message) do
+ content_tag :div, dir: 'auto', class: 'broadcast-message', style: broadcast_message_style(message) do
icon('bullhorn') << ' ' << render_broadcast_message(message)
end
end
diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb
index 3122d8b5163..f2b5b82b013 100644
--- a/app/helpers/ci_status_helper.rb
+++ b/app/helpers/ci_status_helper.rb
@@ -113,7 +113,7 @@ module CiStatusHelper
end
def render_status_with_link(type, status, path = nil, tooltip_placement: 'left', cssclass: '', container: 'body', icon_size: 16)
- klass = "ci-status-link ci-status-icon-#{status.dasherize} #{cssclass}"
+ klass = "ci-status-link ci-status-icon-#{status.dasherize} d-inline-flex #{cssclass}"
title = "#{type.titleize}: #{ci_label_for_status(status)}"
data = { toggle: 'tooltip', placement: tooltip_placement, container: container }
diff --git a/app/helpers/ci_variables_helper.rb b/app/helpers/ci_variables_helper.rb
index 88ce311a1d4..fc51f00d052 100644
--- a/app/helpers/ci_variables_helper.rb
+++ b/app/helpers/ci_variables_helper.rb
@@ -17,7 +17,18 @@ module CiVariablesHelper
if variable && !only_key_value
variable.masked
else
- true
+ false
end
end
+
+ def ci_variable_type_options
+ [
+ %w(Variable env_var),
+ %w(File file)
+ ]
+ end
+
+ def ci_variable_maskable_regex
+ Maskable::REGEX.inspect.sub('\\A', '^').sub('\\z', '$').sub(/^\//, '').sub(/\/[a-z]*$/, '').gsub('\/', '/')
+ end
end
diff --git a/app/helpers/clusters_helper.rb b/app/helpers/clusters_helper.rb
index 30d8a19ecce..769f75f57c4 100644
--- a/app/helpers/clusters_helper.rb
+++ b/app/helpers/clusters_helper.rb
@@ -20,9 +20,4 @@ module ClustersHelper
!cluster.provider.legacy_abac?
end
-
- # EE overrides this
- def show_cluster_health_graphs?(cluster)
- false
- end
end
diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb
index d90ef8903a7..42732eb93dd 100644
--- a/app/helpers/dashboard_helper.rb
+++ b/app/helpers/dashboard_helper.rb
@@ -21,6 +21,10 @@ module DashboardHelper
links.any? { |link| dashboard_nav_link?(link) }
end
+ def has_start_trial?
+ false
+ end
+
private
def get_dashboard_nav_links
diff --git a/app/helpers/dropdowns_helper.rb b/app/helpers/dropdowns_helper.rb
index 8d8c62f1291..64c5fae7d96 100644
--- a/app/helpers/dropdowns_helper.rb
+++ b/app/helpers/dropdowns_helper.rb
@@ -91,7 +91,7 @@ module DropdownsHelper
def dropdown_filter(placeholder, search_id: nil)
content_tag :div, class: "dropdown-input" do
- filter_output = search_field_tag search_id, nil, class: "dropdown-input-field", placeholder: placeholder, autocomplete: 'off'
+ filter_output = search_field_tag search_id, nil, class: "dropdown-input-field qa-dropdown-input-field", placeholder: placeholder, autocomplete: 'off'
filter_output << icon('search', class: "dropdown-input-search")
filter_output << icon('times', class: "dropdown-input-clear js-dropdown-input-clear", role: "button")
diff --git a/app/helpers/emails_helper.rb b/app/helpers/emails_helper.rb
index 96471d15aac..36122d3a22a 100644
--- a/app/helpers/emails_helper.rb
+++ b/app/helpers/emails_helper.rb
@@ -57,12 +57,6 @@ module EmailsHelper
pluralize(valid_length, unit)
end
- def reset_token_expire_message
- link_tag = link_to('request a new one', new_user_password_url(user_email: @user.email))
- "This link is valid for #{password_reset_token_valid_time}. " \
- "After it expires, you can #{link_tag}."
- end
-
def header_logo
if current_appearance&.header_logo?
image_tag(
@@ -91,6 +85,29 @@ module EmailsHelper
].join(';')
end
+ def closure_reason_text(closed_via, format: nil)
+ case closed_via
+ when MergeRequest
+ merge_request = MergeRequest.find(closed_via[:id]).present
+
+ case format
+ when :html
+ merge_request_link = link_to(merge_request.to_reference, merge_request.web_url)
+ _("via merge request %{link}").html_safe % { link: merge_request_link }
+ else
+ # If it's not HTML nor text then assume it's text to be safe
+ _("via merge request %{link}") % { link: "#{merge_request.to_reference} (#{merge_request.web_url})" }
+ end
+ when String
+ # Technically speaking this should be Commit but per
+ # https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/15610#note_163812339
+ # we can't deserialize Commit without custom serializer for ActiveJob
+ _("via %{closed_via}") % { closed_via: closed_via }
+ else
+ ""
+ end
+ end
+
# "You are receiving this email because #{reason}"
def notification_reason_text(reason)
string = case reason
diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb
index 365b94f5a3e..0f118c235d8 100644
--- a/app/helpers/environments_helper.rb
+++ b/app/helpers/environments_helper.rb
@@ -26,11 +26,13 @@ module EnvironmentsHelper
"empty-no-data-svg-path" => image_path('illustrations/monitoring/no_data.svg'),
"empty-unable-to-connect-svg-path" => image_path('illustrations/monitoring/unable_to_connect.svg'),
"metrics-endpoint" => additional_metrics_project_environment_path(project, environment, format: :json),
- "deployment-endpoint" => project_environment_deployments_path(project, environment, format: :json),
+ "dashboard-endpoint" => metrics_dashboard_project_environment_path(project, environment, format: :json),
+ "deployments-endpoint" => project_environment_deployments_path(project, environment, format: :json),
"environments-endpoint": project_environments_path(project, format: :json),
"project-path" => project_path(project),
"tags-path" => project_tags_path(project),
- "has-metrics" => "#{environment.has_metrics?}"
+ "has-metrics" => "#{environment.has_metrics?}",
+ "external-dashboard-url" => project.metrics_setting_external_dashboard_url
}
end
end
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index 1371e9993b4..e990e425cb6 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -68,7 +68,7 @@ module EventsHelper
end
def event_preposition(event)
- if event.push? || event.commented? || event.target
+ if event.push_action? || event.commented_action? || event.target
"at"
elsif event.milestone?
"in"
@@ -80,11 +80,11 @@ module EventsHelper
words << event.author_name
words << event_action_name(event)
- if event.push?
+ if event.push_action?
words << event.ref_type
words << event.ref_name
words << "at"
- elsif event.commented?
+ elsif event.commented_action?
words << event.note_target_reference
words << "at"
elsif event.milestone?
@@ -121,9 +121,9 @@ module EventsHelper
if event.note_target
event_note_target_url(event)
end
- elsif event.push?
+ elsif event.push_action?
push_event_feed_url(event)
- elsif event.created_project?
+ elsif event.created_project_action?
project_url(event.project)
end
end
@@ -147,7 +147,7 @@ module EventsHelper
def event_feed_summary(event)
if event.issue?
render "events/event_issue", issue: event.issue
- elsif event.push?
+ elsif event.push_action?
render "events/event_push", event: event
elsif event.merge_request?
render "events/event_merge_request", merge_request: event.merge_request
diff --git a/app/helpers/groups/group_members_helper.rb b/app/helpers/groups/group_members_helper.rb
new file mode 100644
index 00000000000..a5d2f76820f
--- /dev/null
+++ b/app/helpers/groups/group_members_helper.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module Groups::GroupMembersHelper
+ def group_member_select_options
+ { multiple: true, class: 'input-clamp', scope: :all, email_user: true }
+ end
+end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index 7af766c8544..a3f53ca8dd6 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -99,7 +99,7 @@ module GroupsHelper
end
def remove_group_message(group)
- _("You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?") %
+ _("You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?") %
{ group_name: group.name }
end
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index a07c3f90a91..db4f29cd996 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -5,7 +5,7 @@ module LabelsHelper
include ActionView::Helpers::TagHelper
def show_label_issuables_link?(label, issuables_type, current_user: nil, project: nil)
- return true if label.is_a?(GroupLabel)
+ return true unless label.project_label?
return true unless project
project.feature_available?(issuables_type, current_user)
@@ -13,9 +13,7 @@ module LabelsHelper
# Link to a Label
#
- # label - Label object to link to
- # subject - Project/Group object which will be used as the context for the
- # label's link. If omitted, defaults to the label's own group/project.
+ # label - LabelPresenter object to link to
# type - The type of item the link will point to (:issue or
# :merge_request). If omitted, defaults to :issue.
# block - An optional block that will be passed to `link_to`, forming the
@@ -40,8 +38,8 @@ module LabelsHelper
# link_to_label(label) { "My Custom Label Text" }
#
# Returns a String
- def link_to_label(label, subject: nil, type: :issue, tooltip: true, css_class: nil, &block)
- link = label_filter_path(subject || label.subject, label, type: type)
+ def link_to_label(label, type: :issue, tooltip: true, css_class: nil, &block)
+ link = label.filter_path(type: type)
if block_given?
link_to link, class: css_class, &block
@@ -50,34 +48,6 @@ module LabelsHelper
end
end
- def label_filter_path(subject, label, type: :issue)
- case subject
- when Group
- send("#{type.to_s.pluralize}_group_path", # rubocop:disable GitlabSecurity/PublicSend
- subject,
- label_name: [label.name])
- when Project
- send("namespace_project_#{type.to_s.pluralize}_path", # rubocop:disable GitlabSecurity/PublicSend
- subject.namespace,
- subject,
- label_name: [label.name])
- end
- end
-
- def edit_label_path(label)
- case label
- when GroupLabel then edit_group_label_path(label.group, label)
- when ProjectLabel then edit_project_label_path(label.project, label)
- end
- end
-
- def destroy_label_path(label)
- case label
- when GroupLabel then group_label_path(label.group, label)
- when ProjectLabel then project_label_path(label.project, label)
- end
- end
-
def render_label(label, tooltip: true, link: nil, css: nil)
# if scoped label is used then EE wraps label tag with scoped label
# doc link
@@ -106,29 +76,39 @@ module LabelsHelper
end
def suggested_colors
- [
- '#0033CC',
- '#428BCA',
- '#44AD8E',
- '#A8D695',
- '#5CB85C',
- '#69D100',
- '#004E00',
- '#34495E',
- '#7F8C8D',
- '#A295D6',
- '#5843AD',
- '#8E44AD',
- '#FFECDB',
- '#AD4363',
- '#D10069',
- '#CC0033',
- '#FF0000',
- '#D9534F',
- '#D1D100',
- '#F0AD4E',
- '#AD8D43'
- ]
+ {
+ '#0033CC' => s_('SuggestedColors|UA blue'),
+ '#428BCA' => s_('SuggestedColors|Moderate blue'),
+ '#44AD8E' => s_('SuggestedColors|Lime green'),
+ '#A8D695' => s_('SuggestedColors|Feijoa'),
+ '#5CB85C' => s_('SuggestedColors|Slightly desaturated green'),
+ '#69D100' => s_('SuggestedColors|Bright green'),
+ '#004E00' => s_('SuggestedColors|Very dark lime green'),
+ '#34495E' => s_('SuggestedColors|Very dark desaturated blue'),
+ '#7F8C8D' => s_('SuggestedColors|Dark grayish cyan'),
+ '#A295D6' => s_('SuggestedColors|Slightly desaturated blue'),
+ '#5843AD' => s_('SuggestedColors|Dark moderate blue'),
+ '#8E44AD' => s_('SuggestedColors|Dark moderate violet'),
+ '#FFECDB' => s_('SuggestedColors|Very pale orange'),
+ '#AD4363' => s_('SuggestedColors|Dark moderate pink'),
+ '#D10069' => s_('SuggestedColors|Strong pink'),
+ '#CC0033' => s_('SuggestedColors|Strong red'),
+ '#FF0000' => s_('SuggestedColors|Pure red'),
+ '#D9534F' => s_('SuggestedColors|Soft red'),
+ '#D1D100' => s_('SuggestedColors|Strong yellow'),
+ '#F0AD4E' => s_('SuggestedColors|Soft orange'),
+ '#AD8D43' => s_('SuggestedColors|Dark moderate orange')
+ }
+ end
+
+ def render_suggested_colors
+ colors_html = suggested_colors.map do |color_hex_value, color_name|
+ link_to('', '#', class: "has-tooltip", style: "background-color: #{color_hex_value}", data: { color: color_hex_value }, title: color_name)
+ end
+
+ content_tag(:div, class: 'suggest-colors') do
+ colors_html.join.html_safe
+ end
end
def text_color_for_bg(bg_color)
@@ -168,10 +148,6 @@ module LabelsHelper
end
end
- def can_subscribe_to_label_in_different_levels?(label)
- defined?(@project) && label.is_a?(GroupLabel)
- end
-
def label_subscription_status(label, project)
return 'group-level' if label.subscribed?(current_user)
return 'project-level' if label.subscribed?(current_user, project)
@@ -193,13 +169,6 @@ module LabelsHelper
label.subscribed?(current_user, project) ? 'Unsubscribe' : 'Subscribe'
end
- def label_deletion_confirm_text(label)
- case label
- when GroupLabel then _('Remove this label? This will affect all projects within the group. Are you sure?')
- when ProjectLabel then _('Remove this label? Are you sure?')
- end
- end
-
def create_label_title(subject)
case subject
when Group
@@ -234,15 +203,15 @@ module LabelsHelper
end
def label_status_tooltip(label, status)
- type = label.is_a?(ProjectLabel) ? 'project' : 'group'
+ type = label.project_label? ? 'project' : 'group'
level = status.unsubscribed? ? type : status.sub('-level', '')
action = status.unsubscribed? ? 'Subscribe' : 'Unsubscribe'
"#{action} at #{level} level"
end
- def labels_sorted_by_title(labels)
- labels.sort_by(&:title)
+ def presented_labels_sorted_by_title(labels, subject)
+ labels.sort_by(&:title).map { |label| label.present(issuable_subject: subject) }
end
def label_dropdown_data(project, opts = {})
@@ -276,6 +245,10 @@ module LabelsHelper
klass.new(hash.slice(:color, :description, :title, :group_id, :project_id))
end
+ def issuable_types
+ ['issues', 'merge requests']
+ end
+
# Required for Banzai::Filter::LabelReferenceFilter
module_function :render_colored_label, :text_color_for_bg, :escape_once, :label_tooltip_title
end
diff --git a/app/helpers/markup_helper.rb b/app/helpers/markup_helper.rb
index be4fc2531ae..bf894360a2e 100644
--- a/app/helpers/markup_helper.rb
+++ b/app/helpers/markup_helper.rb
@@ -4,7 +4,7 @@ require 'nokogiri'
module MarkupHelper
include ActionView::Helpers::TagHelper
- include ActionView::Context
+ include ::Gitlab::ActionViewOutput::Context
def plain?(filename)
Gitlab::MarkupHelper.plain?(filename)
@@ -83,7 +83,8 @@ module MarkupHelper
text = sanitize(
text,
tags: tags,
- attributes: Rails::Html::WhiteListSanitizer.allowed_attributes + ['style', 'data-src', 'data-name', 'data-unicode-version']
+ attributes: Rails::Html::WhiteListSanitizer.allowed_attributes +
+ %w(style data-src data-name data-unicode-version data-iid data-project-path data-mr-title)
)
# since <img> tags are stripped, this can leave empty <a> tags hanging around
@@ -262,6 +263,11 @@ module MarkupHelper
end
def asciidoc_unsafe(text, context = {})
+ context.merge!(
+ commit: @commit,
+ ref: @ref,
+ requested_path: @path
+ )
Gitlab::Asciidoc.render(text, context)
end
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index 991ca42c445..2de4e92e33e 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -103,7 +103,7 @@ module MergeRequestsHelper
def merge_params(merge_request)
{
- merge_when_pipeline_succeeds: true,
+ auto_merge_strategy: AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS,
should_remove_source_branch: true,
sha: merge_request.diff_head_sha,
squash: merge_request.squash
diff --git a/app/helpers/mirror_helper.rb b/app/helpers/mirror_helper.rb
index 65c7cd82832..921c79ab771 100644
--- a/app/helpers/mirror_helper.rb
+++ b/app/helpers/mirror_helper.rb
@@ -7,4 +7,8 @@ module MirrorHelper
project_mirror_endpoint: project_mirror_path(@project, :json)
}
end
+
+ def mirror_lfs_sync_message
+ _('The Git LFS objects will <strong>not</strong> be synced.').html_safe
+ end
end
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index 05da5ebdb22..a57ba5f3a4f 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -58,6 +58,14 @@ module NavHelper
current_path?('milestones#show')
end
+ def admin_monitoring_nav_links
+ %w(system_info background_jobs logs health_check requests_profiles)
+ end
+
+ def group_issues_sub_menu_items
+ %w(groups#issues labels#index milestones#index boards#index boards#show)
+ end
+
private
def get_header_links
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
index a50137bea3d..2e31a5e2ed4 100644
--- a/app/helpers/notes_helper.rb
+++ b/app/helpers/notes_helper.rb
@@ -128,15 +128,9 @@ module NotesHelper
end
def can_create_note?
- issuable = @issue || @merge_request
+ noteable = @issue || @merge_request || @snippet || @project
- if @snippet.is_a?(PersonalSnippet)
- can?(current_user, :comment_personal_snippet, @snippet)
- elsif issuable
- can?(current_user, :create_note, issuable)
- else
- can?(current_user, :create_note, @project)
- end
+ can?(current_user, :create_note, noteable)
end
def initial_notes_data(autocomplete)
diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb
index 5318ab4ddef..11b9cf22142 100644
--- a/app/helpers/notifications_helper.rb
+++ b/app/helpers/notifications_helper.rb
@@ -93,4 +93,15 @@ module NotificationsHelper
s_(event.to_s.humanize)
end
end
+
+ def notification_setting_icon(notification_setting)
+ sprite_icon(
+ notification_setting.disabled? ? "notifications-off" : "notifications",
+ css_class: "icon notifications-icon js-notifications-icon"
+ )
+ end
+
+ def show_unsubscribe_title?(noteable)
+ can?(current_user, "read_#{noteable.to_ability_name}".to_sym, noteable)
+ end
end
diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb
index 5038dcf9746..ec1d8577f36 100644
--- a/app/helpers/page_layout_helper.rb
+++ b/app/helpers/page_layout_helper.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
module PageLayoutHelper
@@ -36,7 +37,7 @@ module PageLayoutHelper
if description.present?
@page_description = description.squish
elsif @page_description.present?
- sanitize(@page_description, tags: []).truncate_words(30)
+ sanitize(@page_description.truncate_words(30), tags: [])
end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 7da51da8473..8dee842a22d 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -239,8 +239,11 @@ module ProjectsHelper
end
# rubocop: enable CodeReuse/ActiveRecord
+ # TODO: Remove this method when removing the feature flag
+ # https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/11209#note_162234863
+ # make sure to remove from the EE specific controller as well: ee/app/controllers/ee/dashboard/projects_controller.rb
def show_projects?(projects, params)
- !!(params[:personal] || params[:name] || any_projects?(projects))
+ Feature.enabled?(:project_list_filter_bar) || !!(params[:personal] || params[:name] || any_projects?(projects))
end
def push_to_create_project_command(user = current_user)
@@ -299,6 +302,10 @@ module ProjectsHelper
}.to_json
end
+ def directory?
+ @path.present?
+ end
+
def external_classification_label_help_message
default_label = ::Gitlab::CurrentSettings.current_application_settings
.external_authorization_service_default_label
@@ -309,13 +316,46 @@ module ProjectsHelper
) % { default_label: default_label }
end
+ def can_import_members?
+ Ability.allowed?(current_user, :admin_project_member, @project)
+ end
+
+ def project_can_be_shared?
+ !membership_locked? || @project.allowed_to_share_with_group?
+ end
+
+ def membership_locked?
+ false
+ end
+
+ def share_project_description(project)
+ share_with_group = project.allowed_to_share_with_group?
+ share_with_members = !membership_locked?
+
+ description =
+ if share_with_group && share_with_members
+ _("You can invite a new member to <strong>%{project_name}</strong> or invite another group.")
+ elsif share_with_group
+ _("You can invite another group to <strong>%{project_name}</strong>.")
+ elsif share_with_members
+ _("You can invite a new member to <strong>%{project_name}</strong>.")
+ end
+
+ description.html_safe % { project_name: project.name }
+ end
+
+ def metrics_external_dashboard_url
+ @project.metrics_setting_external_dashboard_url
+ end
+
private
def get_project_nav_tabs(project, current_user)
nav_tabs = [:home]
- if !project.empty_repo? && can?(current_user, :download_code, project)
- nav_tabs << [:files, :commits, :network, :graphs, :forks, :releases]
+ unless project.empty_repo?
+ nav_tabs << [:files, :commits, :network, :graphs, :forks] if can?(current_user, :download_code, project)
+ nav_tabs << :releases if can?(current_user, :read_release, project)
end
if project.repo_exists? && can?(current_user, :read_merge_request, project)
@@ -620,4 +660,8 @@ module ProjectsHelper
project.builds_enabled? &&
!project.repository.gitlab_ci_yml
end
+
+ def vue_file_list_enabled?
+ Gitlab::Graphql.enabled? && Feature.enabled?(:vue_file_list, @project)
+ end
end
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index a62c00df60b..dfa34ad7020 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -128,7 +128,7 @@ module SearchHelper
# rubocop: disable CodeReuse/ActiveRecord
def projects_autocomplete(term, limit = 5)
current_user.authorized_projects.order_id_desc.search_by_title(term)
- .sorted_by_stars.non_archived.limit(limit).map do |p|
+ .sorted_by_stars_desc.non_archived.limit(limit).map do |p|
{
category: "Projects",
id: p.id,
@@ -172,11 +172,17 @@ module SearchHelper
if @project.present?
opts[:data]['project-id'] = @project.id
opts[:data]['base-endpoint'] = project_path(@project)
+ opts[:data]['labels-endpoint'] = project_labels_path(@project)
+ opts[:data]['milestones-endpoint'] = project_milestones_path(@project)
elsif @group.present?
opts[:data]['group-id'] = @group.id
opts[:data]['base-endpoint'] = group_canonical_path(@group)
+ opts[:data]['labels-endpoint'] = group_labels_path(@group)
+ opts[:data]['milestones-endpoint'] = group_milestones_path(@group)
else
opts[:data]['base-endpoint'] = root_dashboard_path
+ opts[:data]['labels-endpoint'] = dashboard_labels_path
+ opts[:data]['milestones-endpoint'] = dashboard_milestones_path
end
opts
diff --git a/app/helpers/sidekiq_helper.rb b/app/helpers/sidekiq_helper.rb
index 32bf3526571..6326d98461e 100644
--- a/app/helpers/sidekiq_helper.rb
+++ b/app/helpers/sidekiq_helper.rb
@@ -8,7 +8,7 @@ module SidekiqHelper
(?<state>[DIEKNRSTVWXZNLpsl\+<>/\d]+)\s+
(?<start>.+?)\s+
(?<command>(?:ruby\d+:\s+)?sidekiq.*\].*)
- \z}x
+ \z}x.freeze
def parse_sidekiq_ps(line)
match = line.strip.match(SIDEKIQ_PS_REGEXP)
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb
index 07ec129dea3..26692934456 100644
--- a/app/helpers/sorting_helper.rb
+++ b/app/helpers/sorting_helper.rb
@@ -3,40 +3,48 @@
module SortingHelper
def sort_options_hash
{
- sort_value_created_date => sort_title_created_date,
- sort_value_downvotes => sort_title_downvotes,
- sort_value_due_date => sort_title_due_date,
- sort_value_due_date_later => sort_title_due_date_later,
- sort_value_due_date_soon => sort_title_due_date_soon,
- sort_value_label_priority => sort_title_label_priority,
- sort_value_largest_group => sort_title_largest_group,
- sort_value_largest_repo => sort_title_largest_repo,
- sort_value_milestone => sort_title_milestone,
- sort_value_milestone_later => sort_title_milestone_later,
- sort_value_milestone_soon => sort_title_milestone_soon,
- sort_value_name => sort_title_name,
- sort_value_name_desc => sort_title_name_desc,
- sort_value_oldest_created => sort_title_oldest_created,
- sort_value_oldest_signin => sort_title_oldest_signin,
- sort_value_oldest_updated => sort_title_oldest_updated,
- sort_value_recently_created => sort_title_recently_created,
- sort_value_recently_signin => sort_title_recently_signin,
- sort_value_recently_updated => sort_title_recently_updated,
- sort_value_popularity => sort_title_popularity,
- sort_value_priority => sort_title_priority,
- sort_value_upvotes => sort_title_upvotes,
- sort_value_contacted_date => sort_title_contacted_date
+ sort_value_created_date => sort_title_created_date,
+ sort_value_downvotes => sort_title_downvotes,
+ sort_value_due_date => sort_title_due_date,
+ sort_value_due_date_later => sort_title_due_date_later,
+ sort_value_due_date_soon => sort_title_due_date_soon,
+ sort_value_label_priority => sort_title_label_priority,
+ sort_value_largest_group => sort_title_largest_group,
+ sort_value_largest_repo => sort_title_largest_repo,
+ sort_value_milestone => sort_title_milestone,
+ sort_value_milestone_later => sort_title_milestone_later,
+ sort_value_milestone_soon => sort_title_milestone_soon,
+ sort_value_name => sort_title_name,
+ sort_value_name_desc => sort_title_name_desc,
+ sort_value_oldest_created => sort_title_oldest_created,
+ sort_value_oldest_signin => sort_title_oldest_signin,
+ sort_value_oldest_updated => sort_title_oldest_updated,
+ sort_value_recently_created => sort_title_recently_created,
+ sort_value_recently_signin => sort_title_recently_signin,
+ sort_value_recently_updated => sort_title_recently_updated,
+ sort_value_popularity => sort_title_popularity,
+ sort_value_priority => sort_title_priority,
+ sort_value_upvotes => sort_title_upvotes,
+ sort_value_contacted_date => sort_title_contacted_date,
+ sort_value_relative_position => sort_title_relative_position
}
end
def projects_sort_options_hash
+ Feature.enabled?(:project_list_filter_bar) && !current_controller?('admin/projects') ? projects_sort_common_options_hash : old_projects_sort_options_hash
+ end
+
+ # TODO: Simplify these sorting options
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/60798
+ # https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/11209#note_162234858
+ def old_projects_sort_options_hash
options = {
sort_value_latest_activity => sort_title_latest_activity,
sort_value_name => sort_title_name,
sort_value_oldest_activity => sort_title_oldest_activity,
sort_value_oldest_created => sort_title_oldest_created,
sort_value_recently_created => sort_title_recently_created,
- sort_value_most_stars => sort_title_most_stars
+ sort_value_stars_desc => sort_title_most_stars
}
if current_controller?('admin/projects')
@@ -46,6 +54,41 @@ module SortingHelper
options
end
+ def projects_sort_common_options_hash
+ {
+ sort_value_latest_activity => sort_title_latest_activity,
+ sort_value_recently_created => sort_title_created_date,
+ sort_value_name => sort_title_name,
+ sort_value_stars_desc => sort_title_stars
+ }
+ end
+
+ def projects_sort_option_titles
+ {
+ sort_value_latest_activity => sort_title_latest_activity,
+ sort_value_recently_created => sort_title_created_date,
+ sort_value_name => sort_title_name,
+ sort_value_stars_desc => sort_title_stars,
+ sort_value_oldest_activity => sort_title_latest_activity,
+ sort_value_oldest_created => sort_title_created_date,
+ sort_value_name_desc => sort_title_name,
+ sort_value_stars_asc => sort_title_stars
+ }
+ end
+
+ def projects_reverse_sort_options_hash
+ {
+ sort_value_latest_activity => sort_value_oldest_activity,
+ sort_value_recently_created => sort_value_oldest_created,
+ sort_value_name => sort_value_name_desc,
+ sort_value_stars_desc => sort_value_stars_asc,
+ sort_value_oldest_activity => sort_value_latest_activity,
+ sort_value_oldest_created => sort_value_recently_created,
+ sort_value_name_desc => sort_value_name,
+ sort_value_stars_asc => sort_value_stars_desc
+ }
+ end
+
def groups_sort_options_hash
{
sort_value_name => sort_title_name,
@@ -59,7 +102,7 @@ module SortingHelper
def subgroups_sort_options_hash
groups_sort_options_hash.merge(
- sort_value_most_stars => sort_title_most_stars
+ sort_value_stars_desc => sort_title_most_stars
)
end
@@ -142,7 +185,9 @@ module SortingHelper
{
sort_value_oldest_created => sort_value_created_date,
sort_value_oldest_updated => sort_value_recently_updated,
- sort_value_milestone_later => sort_value_milestone
+ sort_value_milestone_later => sort_value_milestone,
+ sort_value_due_date_later => sort_value_due_date,
+ sort_value_least_popular => sort_value_popularity
}
end
@@ -151,7 +196,11 @@ module SortingHelper
sort_value_created_date => sort_value_oldest_created,
sort_value_recently_created => sort_value_oldest_created,
sort_value_recently_updated => sort_value_oldest_updated,
- sort_value_milestone => sort_value_milestone_later
+ sort_value_milestone => sort_value_milestone_later,
+ sort_value_due_date => sort_value_due_date_later,
+ sort_value_due_date_soon => sort_value_due_date_later,
+ sort_value_popularity => sort_value_least_popular,
+ sort_value_most_popular => sort_value_least_popular
}.merge(issuable_sort_option_overrides)
end
@@ -170,6 +219,8 @@ module SortingHelper
end
end
+ # TODO: dedupicate issuable and project sort direction
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/60798
def issuable_sort_direction_button(sort_value)
link_class = 'btn btn-default has-tooltip reverse-sort-btn qa-reverse-sort'
reverse_sort = issuable_reverse_sort_order_hash[sort_value]
@@ -181,7 +232,23 @@ module SortingHelper
link_class += ' disabled'
end
- link_to(reverse_url, type: 'button', class: link_class, title: 'Sort direction') do
+ link_to(reverse_url, type: 'button', class: link_class, title: s_('SortOptions|Sort direction')) do
+ sprite_icon("sort-#{issuable_sort_icon_suffix(sort_value)}", size: 16)
+ end
+ end
+
+ def project_sort_direction_button(sort_value)
+ link_class = 'btn btn-default has-tooltip reverse-sort-btn qa-reverse-sort'
+ reverse_sort = projects_reverse_sort_options_hash[sort_value]
+
+ if reverse_sort
+ reverse_url = filter_projects_path(sort: reverse_sort)
+ else
+ reverse_url = '#'
+ link_class += ' disabled'
+ end
+
+ link_to(reverse_url, type: 'button', class: link_class, title: s_('SortOptions|Sort direction')) do
sprite_icon("sort-#{issuable_sort_icon_suffix(sort_value)}", size: 16)
end
end
@@ -319,6 +386,10 @@ module SortingHelper
s_('SortOptions|Most stars')
end
+ def sort_title_stars
+ s_('SortOptions|Stars')
+ end
+
def sort_title_oldest_last_activity
s_('SortOptions|Oldest last activity')
end
@@ -327,6 +398,10 @@ module SortingHelper
s_('SortOptions|Recent last activity')
end
+ def sort_title_relative_position
+ s_('SortOptions|Manual')
+ end
+
# Values.
def sort_value_access_level_asc
'access_level_asc'
@@ -420,6 +495,14 @@ module SortingHelper
'popularity'
end
+ def sort_value_most_popular
+ 'popularity_desc'
+ end
+
+ def sort_value_least_popular
+ 'popularity_asc'
+ end
+
def sort_value_priority
'priority'
end
@@ -452,10 +535,14 @@ module SortingHelper
'contacted_asc'
end
- def sort_value_most_stars
+ def sort_value_stars_desc
'stars_desc'
end
+ def sort_value_stars_asc
+ 'stars_asc'
+ end
+
def sort_value_oldest_last_activity
'last_activity_on_asc'
end
@@ -463,4 +550,8 @@ module SortingHelper
def sort_value_recently_last_activity
'last_activity_on_desc'
end
+
+ def sort_value_relative_position
+ 'relative_position'
+ end
end
diff --git a/app/helpers/storage_helper.rb b/app/helpers/storage_helper.rb
index be8761db562..ecf37bae6b3 100644
--- a/app/helpers/storage_helper.rb
+++ b/app/helpers/storage_helper.rb
@@ -2,8 +2,21 @@
module StorageHelper
def storage_counter(size_in_bytes)
+ return s_('StorageSize|Unknown') unless size_in_bytes
+
precision = size_in_bytes < 1.megabyte ? 0 : 1
number_to_human_size(size_in_bytes, delimiter: ',', precision: precision, significant: false)
end
+
+ def storage_counters_details(statistics)
+ counters = {
+ counter_repositories: storage_counter(statistics.repository_size),
+ counter_wikis: storage_counter(statistics.wiki_size),
+ counter_build_artifacts: storage_counter(statistics.build_artifacts_size),
+ counter_lfs_objects: storage_counter(statistics.lfs_objects_size)
+ }
+
+ _("%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS") % counters
+ end
end
diff --git a/app/helpers/tracking_helper.rb b/app/helpers/tracking_helper.rb
new file mode 100644
index 00000000000..51ea79d1ddd
--- /dev/null
+++ b/app/helpers/tracking_helper.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module TrackingHelper
+ def tracking_attrs(label, event, property)
+ {} # CE has no tracking features
+ end
+end
diff --git a/app/helpers/visibility_level_helper.rb b/app/helpers/visibility_level_helper.rb
index 9deb783d289..b318b27992a 100644
--- a/app/helpers/visibility_level_helper.rb
+++ b/app/helpers/visibility_level_helper.rb
@@ -165,8 +165,46 @@ module VisibilityLevelHelper
!form_model.visibility_level_allowed?(level)
end
+ # Visibility level can be restricted in two ways:
+ #
+ # 1. The group permissions (e.g. a subgroup is private, which requires
+ # all projects to be private)
+ # 2. The global allowed visibility settings, set by the admin
+ def selected_visibility_level(form_model, requested_level)
+ requested_level =
+ if requested_level.present?
+ requested_level.to_i
+ else
+ default_project_visibility
+ end
+
+ [requested_level, max_allowed_visibility_level(form_model)].min
+ end
+
private
+ def max_allowed_visibility_level(form_model)
+ # First obtain the maximum visibility for the project or group
+ current_level = max_allowed_visibility_level_by_model(form_model)
+
+ # Now limit this by the global setting
+ Gitlab::VisibilityLevel.closest_allowed_level(current_level)
+ end
+
+ def max_allowed_visibility_level_by_model(form_model)
+ current_level = Gitlab::VisibilityLevel::PRIVATE
+
+ Gitlab::VisibilityLevel.values.sort.each do |value|
+ if disallowed_visibility_level?(form_model, value)
+ break
+ else
+ current_level = value
+ end
+ end
+
+ current_level
+ end
+
def visibility_level_errors_for_group(group, level_name)
group_name = link_to group.name, group_path(group)
change_visiblity = link_to 'change the visibility', edit_group_path(group)
diff --git a/app/mailers/devise_mailer.rb b/app/mailers/devise_mailer.rb
index 7aa75ee30e6..cbaf53fced1 100644
--- a/app/mailers/devise_mailer.rb
+++ b/app/mailers/devise_mailer.rb
@@ -7,6 +7,7 @@ class DeviseMailer < Devise::Mailer
layout 'mailer/devise'
helper EmailsHelper
+ helper ApplicationHelper
protected
diff --git a/app/mailers/emails/issues.rb b/app/mailers/emails/issues.rb
index d2e334fb856..f3a3203f7ad 100644
--- a/app/mailers/emails/issues.rb
+++ b/app/mailers/emails/issues.rb
@@ -30,8 +30,8 @@ module Emails
end
# rubocop: enable CodeReuse/ActiveRecord
- def closed_issue_email(recipient_id, issue_id, updated_by_user_id, reason = nil)
- setup_issue_mail(issue_id, recipient_id)
+ def closed_issue_email(recipient_id, issue_id, updated_by_user_id, reason: nil, closed_via: nil)
+ setup_issue_mail(issue_id, recipient_id, closed_via: closed_via)
@updated_by = User.find(updated_by_user_id)
mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id, reason))
@@ -83,7 +83,7 @@ module Emails
@project = Project.find(project_id)
@results = results
- mail(to: @user.notification_email, subject: subject('Imported issues')) do |format|
+ mail(to: recipient(@user.id, @project.group), subject: subject('Imported issues')) do |format|
format.html { render layout: 'mailer' }
format.text { render layout: 'mailer' }
end
@@ -91,10 +91,11 @@ module Emails
private
- def setup_issue_mail(issue_id, recipient_id)
+ def setup_issue_mail(issue_id, recipient_id, closed_via: nil)
@issue = Issue.find(issue_id)
@project = @issue.project
@target_url = project_issue_url(@project, @issue)
+ @closed_via = closed_via
@sent_notification = SentNotification.record(@issue, recipient_id, reply_key)
end
@@ -102,7 +103,7 @@ module Emails
def issue_thread_options(sender_id, recipient_id, reason)
{
from: sender(sender_id),
- to: recipient(recipient_id),
+ to: recipient(recipient_id, @project.group),
subject: subject("#{@issue.title} (##{@issue.iid})"),
'X-GitLab-NotificationReason' => reason
}
diff --git a/app/mailers/emails/members.rb b/app/mailers/emails/members.rb
index 91dfdf58982..2bfa59774d7 100644
--- a/app/mailers/emails/members.rb
+++ b/app/mailers/emails/members.rb
@@ -58,9 +58,8 @@ module Emails
@member_source_type = member_source_type
@member_source = member_source_class.find(source_id)
@invite_email = invite_email
- inviter = User.find(created_by_id)
- mail(to: inviter.notification_email,
+ mail(to: recipient(created_by_id, member_source_type == 'Project' ? @member_source.group : @member_source),
subject: subject('Invitation declined'))
end
diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb
index 63148831a24..864f9e2975a 100644
--- a/app/mailers/emails/merge_requests.rb
+++ b/app/mailers/emails/merge_requests.rb
@@ -58,14 +58,14 @@ module Emails
}))
end
- def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id, reason = nil)
+ def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id, reason: nil, closed_via: nil)
setup_merge_request_mail(merge_request_id, recipient_id)
@updated_by = User.find(updated_by_user_id)
mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
end
- def merged_merge_request_email(recipient_id, merge_request_id, updated_by_user_id, reason = nil)
+ def merged_merge_request_email(recipient_id, merge_request_id, updated_by_user_id, reason: nil, closed_via: nil)
setup_merge_request_mail(merge_request_id, recipient_id)
mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
@@ -110,7 +110,7 @@ module Emails
def merge_request_thread_options(sender_id, recipient_id, reason = nil)
{
from: sender(sender_id),
- to: recipient(recipient_id),
+ to: recipient(recipient_id, @project.group),
subject: subject("#{@merge_request.title} (#{@merge_request.to_reference})"),
'X-GitLab-NotificationReason' => reason
}
diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb
index 1b3c1f9a8a9..70d296fe3b8 100644
--- a/app/mailers/emails/notes.rb
+++ b/app/mailers/emails/notes.rb
@@ -51,7 +51,7 @@ module Emails
def note_thread_options(recipient_id)
{
from: sender(@note.author_id),
- to: recipient(recipient_id),
+ to: recipient(recipient_id, @group),
subject: subject("#{@note.noteable.title} (#{@note.noteable.reference_link_text})")
}
end
diff --git a/app/mailers/emails/pages_domains.rb b/app/mailers/emails/pages_domains.rb
index ce449237ef6..2d390666f65 100644
--- a/app/mailers/emails/pages_domains.rb
+++ b/app/mailers/emails/pages_domains.rb
@@ -7,7 +7,7 @@ module Emails
@project = domain.project
mail(
- to: recipient.notification_email,
+ to: recipient(recipient.id, @project.group),
subject: subject("GitLab Pages domain '#{domain.domain}' has been enabled")
)
end
@@ -17,7 +17,7 @@ module Emails
@project = domain.project
mail(
- to: recipient.notification_email,
+ to: recipient(recipient.id, @project.group),
subject: subject("GitLab Pages domain '#{domain.domain}' has been disabled")
)
end
@@ -27,7 +27,7 @@ module Emails
@project = domain.project
mail(
- to: recipient.notification_email,
+ to: recipient(recipient.id, @project.group),
subject: subject("Verification succeeded for GitLab Pages domain '#{domain.domain}'")
)
end
@@ -37,7 +37,7 @@ module Emails
@project = domain.project
mail(
- to: recipient.notification_email,
+ to: recipient(recipient.id, @project.group),
subject: subject("ACTION REQUIRED: Verification failed for GitLab Pages domain '#{domain.domain}'")
)
end
diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb
index 2500622caa7..f81f76f67f7 100644
--- a/app/mailers/emails/projects.rb
+++ b/app/mailers/emails/projects.rb
@@ -7,20 +7,20 @@ module Emails
@project = Project.find project_id
@target_url = project_url(@project)
@old_path_with_namespace = old_path_with_namespace
- mail(to: @user.notification_email,
+ mail(to: recipient(user_id, @project.group),
subject: subject("Project was moved"))
end
def project_was_exported_email(current_user, project)
@project = project
- mail(to: current_user.notification_email,
+ mail(to: recipient(current_user.id, project.group),
subject: subject("Project was exported"))
end
def project_was_not_exported_email(current_user, project, errors)
@project = project
@errors = errors
- mail(to: current_user.notification_email,
+ mail(to: recipient(current_user.id, @project.group),
subject: subject("Project export error"))
end
@@ -28,7 +28,7 @@ module Emails
@project = project
@user = user
- mail(to: user.notification_email, subject: subject("Project cleanup has completed"))
+ mail(to: recipient(user.id, project.group), subject: subject("Project cleanup has completed"))
end
def repository_cleanup_failure_email(project, user, error)
@@ -36,7 +36,7 @@ module Emails
@user = user
@error = error
- mail(to: user.notification_email, subject: subject("Project cleanup failure"))
+ mail(to: recipient(user.id, project.group), subject: subject("Project cleanup failure"))
end
def repository_push_email(project_id, opts = {})
diff --git a/app/mailers/emails/remote_mirrors.rb b/app/mailers/emails/remote_mirrors.rb
index 2018eb7260b..2d8137843ec 100644
--- a/app/mailers/emails/remote_mirrors.rb
+++ b/app/mailers/emails/remote_mirrors.rb
@@ -6,7 +6,7 @@ module Emails
@remote_mirror = RemoteMirrorFinder.new(id: remote_mirror_id).execute
@project = @remote_mirror.project
- mail(to: recipient(recipient_id), subject: subject('Remote mirror update failed'))
+ mail(to: recipient(recipient_id, @project.group), subject: subject('Remote mirror update failed'))
end
end
end
diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb
index 0b740809f30..576caea4c10 100644
--- a/app/mailers/notify.rb
+++ b/app/mailers/notify.rb
@@ -73,12 +73,22 @@ class Notify < BaseMailer
# Look up a User by their ID and return their email address
#
- # recipient_id - User ID
+ # recipient_id - User ID
+ # notification_group - The parent group of the notification
#
# Returns a String containing the User's email address.
- def recipient(recipient_id)
+ def recipient(recipient_id, notification_group = nil)
@current_user = User.find(recipient_id)
- @current_user.notification_email
+ group_notification_email = nil
+
+ if notification_group
+ notification_settings = notification_group.notification_settings_for(@current_user, hierarchy_order: :asc)
+ group_notification_email = notification_settings.find { |n| n.notification_email.present? }&.notification_email
+ end
+
+ # Return group-specific email address if present, otherwise return global
+ # email address
+ group_notification_email || @current_user.notification_email
end
# Formats arguments into a String suitable for use as an email subject
diff --git a/app/mailers/repository_check_mailer.rb b/app/mailers/repository_check_mailer.rb
index a24d3476d0e..aa56ba1828b 100644
--- a/app/mailers/repository_check_mailer.rb
+++ b/app/mailers/repository_check_mailer.rb
@@ -15,7 +15,7 @@ class RepositoryCheckMailer < BaseMailer
end
mail(
- to: User.admins.pluck(:email),
+ to: User.admins.active.pluck(:email),
subject: "GitLab Admin | #{@message}"
)
end
diff --git a/app/models/active_session.rb b/app/models/active_session.rb
index 1e01f1d17e6..f355b02c428 100644
--- a/app/models/active_session.rb
+++ b/app/models/active_session.rb
@@ -53,7 +53,7 @@ class ActiveSession
def self.list(user)
Gitlab::Redis::SharedState.with do |redis|
- cleaned_up_lookup_entries(redis, user.id).map do |entry|
+ cleaned_up_lookup_entries(redis, user).map do |entry|
# rubocop:disable Security/MarshalLoad
Marshal.load(entry)
# rubocop:enable Security/MarshalLoad
@@ -78,7 +78,7 @@ class ActiveSession
def self.cleanup(user)
Gitlab::Redis::SharedState.with do |redis|
- cleaned_up_lookup_entries(redis, user.id)
+ cleaned_up_lookup_entries(redis, user)
end
end
@@ -90,25 +90,52 @@ class ActiveSession
"#{Gitlab::Redis::SharedState::USER_SESSIONS_LOOKUP_NAMESPACE}:#{user_id}"
end
- def self.cleaned_up_lookup_entries(redis, user_id)
- lookup_key = lookup_key_name(user_id)
+ def self.list_sessions(user)
+ sessions_from_ids(session_ids_for_user(user))
+ end
- session_ids = redis.smembers(lookup_key)
+ def self.session_ids_for_user(user)
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.smembers(lookup_key_name(user.id))
+ end
+ end
- entry_keys = session_ids.map { |session_id| key_name(user_id, session_id) }
- return [] if entry_keys.empty?
+ def self.sessions_from_ids(session_ids)
+ return [] if session_ids.empty?
- entries = redis.mget(entry_keys)
+ Gitlab::Redis::SharedState.with do |redis|
+ session_keys = session_ids.map { |session_id| "#{Gitlab::Redis::SharedState::SESSION_NAMESPACE}:#{session_id}" }
- session_ids_and_entries = session_ids.zip(entries)
+ redis.mget(session_keys).compact.map do |raw_session|
+ # rubocop:disable Security/MarshalLoad
+ Marshal.load(raw_session)
+ # rubocop:enable Security/MarshalLoad
+ end
+ end
+ end
+
+ def self.raw_active_session_entries(session_ids, user_id)
+ return [] if session_ids.empty?
+
+ Gitlab::Redis::SharedState.with do |redis|
+ entry_keys = session_ids.map { |session_id| key_name(user_id, session_id) }
+
+ redis.mget(entry_keys)
+ end
+ end
+
+ def self.cleaned_up_lookup_entries(redis, user)
+ session_ids = session_ids_for_user(user)
+ entries = raw_active_session_entries(session_ids, user.id)
# remove expired keys.
# only the single key entries are automatically expired by redis, the
# lookup entries in the set need to be removed manually.
+ session_ids_and_entries = session_ids.zip(entries)
session_ids_and_entries.reject { |_session_id, entry| entry }.each do |session_id, _entry|
- redis.srem(lookup_key, session_id)
+ redis.srem(lookup_key_name(user.id), session_id)
end
- session_ids_and_entries.select { |_session_id, entry| entry }.map { |_session_id, entry| entry }
+ entries.compact
end
end
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
index 9d71f250466..0979d03f6e6 100644
--- a/app/models/application_record.rb
+++ b/app/models/application_record.rb
@@ -17,6 +17,19 @@ class ApplicationRecord < ActiveRecord::Base
where(nil).pluck(self.primary_key)
end
+ def self.safe_ensure_unique(retries: 0)
+ transaction(requires_new: true) do
+ yield
+ end
+ rescue ActiveRecord::RecordNotUnique
+ if retries > 0
+ retries -= 1
+ retry
+ end
+
+ false
+ end
+
def self.safe_find_or_create_by!(*args)
safe_find_or_create_by(*args).tap do |record|
record.validate! unless record.persisted?
@@ -24,10 +37,12 @@ class ApplicationRecord < ActiveRecord::Base
end
def self.safe_find_or_create_by(*args)
- transaction(requires_new: true) do
+ safe_ensure_unique(retries: 1) do
find_or_create_by(*args)
end
- rescue ActiveRecord::RecordNotUnique
- retry
+ end
+
+ def self.underscore
+ Gitlab::SafeRequestStore.fetch("model:#{self}:underscore") { self.to_s.underscore }
end
end
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 2f9b4c4eaa2..bbe2d2e8fd4 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -229,6 +229,16 @@ class ApplicationSetting < ApplicationRecord
presence: true,
if: -> (setting) { setting.external_auth_client_cert.present? }
+ validates :lets_encrypt_notification_email,
+ devise_email: true,
+ format: { without: /@example\.(com|org|net)\z/,
+ message: N_("Let's Encrypt does not accept emails on example.com") },
+ allow_blank: true
+
+ validates :lets_encrypt_notification_email,
+ presence: true,
+ if: :lets_encrypt_terms_of_service_accepted?
+
validates_with X509CertificateCredentialsValidator,
certificate: :external_auth_client_cert,
pkey: :external_auth_client_key,
@@ -247,6 +257,12 @@ class ApplicationSetting < ApplicationRecord
algorithm: 'aes-256-gcm',
encode: true
+ attr_encrypted :lets_encrypt_private_key,
+ mode: :per_attribute_iv,
+ key: Settings.attr_encrypted_db_key_base_truncated,
+ algorithm: 'aes-256-gcm',
+ encode: true
+
before_validation :ensure_uuid!
before_validation :strip_sentry_values
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index b413ffddb9d..904d650ef96 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -8,7 +8,7 @@ module ApplicationSettingImplementation
\s # any whitespace character
| # or
[\r\n] # any number of newline characters
- }x
+ }x.freeze
# Setting a key restriction to `-1` means that all keys of this type are
# forbidden.
@@ -21,6 +21,7 @@ module ApplicationSettingImplementation
after_sign_up_text: nil,
akismet_enabled: false,
allow_local_requests_from_hooks_and_services: false,
+ dns_rebinding_protection_enabled: true,
authorized_keys_enabled: true, # TODO default to false if the instance is configured to use AuthorizedKeysCommand
container_registry_token_expire_delay: 5,
default_artifacts_expire_in: '30 days',
@@ -183,6 +184,22 @@ module ApplicationSettingImplementation
clientside_sentry_dsn.strip! if clientside_sentry_dsn.present?
end
+ def sentry_enabled
+ Gitlab.config.sentry.enabled || read_attribute(:sentry_enabled)
+ end
+
+ def sentry_dsn
+ Gitlab.config.sentry.dsn || read_attribute(:sentry_dsn)
+ end
+
+ def clientside_sentry_enabled
+ Gitlab.config.sentry.enabled || read_attribute(:clientside_sentry_enabled)
+ end
+
+ def clientside_sentry_dsn
+ Gitlab.config.sentry.clientside_dsn || read_attribute(:clientside_sentry_dsn)
+ end
+
def performance_bar_allowed_group
Group.find_by_id(performance_bar_allowed_group_id)
end
diff --git a/app/models/broadcast_message.rb b/app/models/broadcast_message.rb
index 18fe2a9624f..0fd8dca70b4 100644
--- a/app/models/broadcast_message.rb
+++ b/app/models/broadcast_message.rb
@@ -17,13 +17,11 @@ class BroadcastMessage < ApplicationRecord
default_value_for :font, '#FFFFFF'
CACHE_KEY = 'broadcast_message_current_json'.freeze
- LEGACY_CACHE_KEY = 'broadcast_message_current'.freeze
after_commit :flush_redis_cache
def self.current
messages = cache.fetch(CACHE_KEY, as: BroadcastMessage, expires_in: cache_expires_in) do
- remove_legacy_cache_key
current_and_future_messages
end
@@ -50,14 +48,6 @@ class BroadcastMessage < ApplicationRecord
nil
end
- # This can be removed in GitLab 12.0+
- # The old cache key had an indefinite lifetime, and in an HA
- # environment a one-shot migration would not work because the cache
- # would be repopulated by a node that has not been upgraded.
- def self.remove_legacy_cache_key
- cache.expire(LEGACY_CACHE_KEY)
- end
-
def active?
started? && !ended?
end
@@ -84,6 +74,5 @@ class BroadcastMessage < ApplicationRecord
def flush_redis_cache
self.class.cache.expire(CACHE_KEY)
- self.class.remove_legacy_cache_key
end
end
diff --git a/app/models/ci/bridge.rb b/app/models/ci/bridge.rb
index 0d8d7d95791..644716ba8e7 100644
--- a/app/models/ci/bridge.rb
+++ b/app/models/ci/bridge.rb
@@ -4,6 +4,7 @@ module Ci
class Bridge < CommitStatus
include Ci::Processable
include Ci::Contextable
+ include Ci::PipelineDelegator
include Importable
include AfterCommitQueue
include HasRef
@@ -13,8 +14,6 @@ module Ci
belongs_to :trigger_request
validates :ref, presence: true
- delegate :merge_request_event?, to: :pipeline
-
def self.retry(bridge, current_user)
raise NotImplementedError
end
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 5cf9bb4979a..89cc082d0bc 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -2,10 +2,10 @@
module Ci
class Build < CommitStatus
- prepend ArtifactMigratable
include Ci::Processable
include Ci::Metadatable
include Ci::Contextable
+ include Ci::PipelineDelegator
include TokenAuthenticatable
include AfterCommitQueue
include ObjectStorage::BackgroundMove
@@ -19,6 +19,11 @@ module Ci
BuildArchivedError = Class.new(StandardError)
ignore_column :commands
+ ignore_column :artifacts_file
+ ignore_column :artifacts_metadata
+ ignore_column :artifacts_file_store
+ ignore_column :artifacts_metadata_store
+ ignore_column :artifacts_size
belongs_to :project, inverse_of: :builds
belongs_to :runner
@@ -48,8 +53,6 @@ module Ci
delegate :terminal_specification, to: :runner_session, allow_nil: true
delegate :gitlab_deploy_token, to: :project
delegate :trigger_short_token, to: :trigger_request, allow_nil: true
- delegate :merge_request_event?, :merge_request_ref?,
- :legacy_detached_merge_request_pipeline?, to: :pipeline
##
# Since Gitlab 11.5, deployments records started being created right after
@@ -83,13 +86,7 @@ module Ci
scope :unstarted, ->() { where(runner_id: nil) }
scope :ignore_failures, ->() { where(allow_failure: false) }
scope :with_artifacts_archive, ->() do
- if Feature.enabled?(:ci_enable_legacy_artifacts)
- where('(artifacts_file IS NOT NULL AND artifacts_file <> ?) OR EXISTS (?)',
- '', Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id').archive)
- else
- where('EXISTS (?)',
- Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id').archive)
- end
+ where('EXISTS (?)', Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id').archive)
end
scope :with_existing_job_artifacts, ->(query) do
@@ -111,8 +108,8 @@ module Ci
scope :eager_load_job_artifacts, -> { includes(:job_artifacts) }
- scope :with_artifacts_stored_locally, -> { with_artifacts_archive.where(artifacts_file_store: [nil, LegacyArtifactUploader::Store::LOCAL]) }
- scope :with_archived_trace_stored_locally, -> { with_archived_trace.where(artifacts_file_store: [nil, LegacyArtifactUploader::Store::LOCAL]) }
+ scope :with_artifacts_stored_locally, -> { with_existing_job_artifacts(Ci::JobArtifact.archive.with_files_stored_locally) }
+ scope :with_archived_trace_stored_locally, -> { with_existing_job_artifacts(Ci::JobArtifact.trace.with_files_stored_locally) }
scope :with_artifacts_not_expired, ->() { with_artifacts_archive.where('artifacts_expire_at IS NULL OR artifacts_expire_at > ?', Time.now) }
scope :with_expired_artifacts, ->() { with_artifacts_archive.where('artifacts_expire_at < ?', Time.now) }
scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) }
@@ -140,16 +137,12 @@ module Ci
where("EXISTS (?)", matcher)
end
- ##
- # TODO: Remove these mounters when we remove :ci_enable_legacy_artifacts feature flag
- mount_uploader :legacy_artifacts_file, LegacyArtifactUploader, mount_on: :artifacts_file
- mount_uploader :legacy_artifacts_metadata, LegacyArtifactUploader, mount_on: :artifacts_metadata
+ scope :queued_before, ->(time) { where(arel_table[:queued_at].lt(time)) }
acts_as_taggable
add_authentication_token_field :token, encrypted: :optional
- before_save :update_artifacts_size, if: :artifacts_file_changed?
before_save :ensure_token
before_destroy { unscoped_project }
@@ -157,9 +150,6 @@ module Ci
run_after_commit { BuildHooksWorker.perform_async(build.id) }
end
- after_save :update_project_statistics_after_save, if: :artifacts_size_changed?
- after_destroy :update_project_statistics_after_destroy, unless: :project_destroyed?
-
class << self
# This is needed for url_for to work,
# as the controller is JobsController
@@ -379,8 +369,6 @@ module Ci
end
def any_unmet_prerequisites?
- return false unless Feature.enabled?(:ci_preparing_state, default_enabled: true)
-
prerequisites.present?
end
@@ -543,6 +531,26 @@ module Ci
trace.exist?
end
+ def artifacts_file
+ job_artifacts_archive&.file
+ end
+
+ def artifacts_size
+ job_artifacts_archive&.size
+ end
+
+ def artifacts_metadata
+ job_artifacts_metadata&.file
+ end
+
+ def artifacts?
+ !artifacts_expired? && artifacts_file&.exists?
+ end
+
+ def artifacts_metadata?
+ artifacts? && artifacts_metadata&.exists?
+ end
+
def has_job_artifacts?
job_artifacts.any?
end
@@ -611,14 +619,12 @@ module Ci
# and use that for `ExpireBuildInstanceArtifactsWorker`?
def erase_erasable_artifacts!
job_artifacts.erasable.destroy_all # rubocop: disable DestroyAll
- erase_old_artifacts!
end
def erase(opts = {})
return false unless erasable?
job_artifacts.destroy_all # rubocop: disable DestroyAll
- erase_old_artifacts!
erase_trace!
update_erased!(opts[:erased_by])
end
@@ -656,10 +662,7 @@ module Ci
end
def artifacts_file_for_type(type)
- file = job_artifacts.find_by(file_type: Ci::JobArtifact.file_types[type])&.file
- # TODO: to be removed once legacy artifacts is removed
- file ||= legacy_artifacts_file if type == :archive
- file
+ job_artifacts.find_by(file_type: Ci::JobArtifact.file_types[type])&.file
end
def coverage_regex
@@ -766,6 +769,10 @@ module Ci
end
end
+ def report_artifacts
+ job_artifacts.with_reports
+ end
+
# Virtual deployment status depending on the environment status.
def deployment_status
return unless starts_environment?
@@ -781,13 +788,6 @@ module Ci
private
- def erase_old_artifacts!
- # TODO: To be removed once we get rid of ci_enable_legacy_artifacts feature flag
- remove_artifacts_file!
- remove_artifacts_metadata!
- save
- end
-
def successful_deployment_status
if deployment&.last?
:last
@@ -809,10 +809,6 @@ module Ci
job_artifacts.select { |artifact| artifact.file_type.in?(report_types) }
end
- def update_artifacts_size
- self.artifacts_size = legacy_artifacts_file&.size
- end
-
def erase_trace!
trace.erase!
end
@@ -847,21 +843,5 @@ module Ci
pipeline.config_processor.build_attributes(name)
end
-
- def update_project_statistics_after_save
- update_project_statistics(read_attribute(:artifacts_size).to_i - artifacts_size_was.to_i)
- end
-
- def update_project_statistics_after_destroy
- update_project_statistics(-artifacts_size)
- end
-
- def update_project_statistics(difference)
- ProjectStatistics.increment_statistic(project_id, :build_artifacts_size, difference)
- end
-
- def project_destroyed?
- project.pending_delete?
- end
end
end
diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb
index 9695d49d18b..f80e98e5bca 100644
--- a/app/models/ci/job_artifact.rb
+++ b/app/models/ci/job_artifact.rb
@@ -4,6 +4,7 @@ module Ci
class JobArtifact < ApplicationRecord
include AfterCommitQueue
include ObjectStorage::BackgroundMove
+ include UpdateProjectStatistics
extend Gitlab::Ci::Model
NotSupportedAdapterError = Class.new(StandardError)
@@ -25,10 +26,13 @@ module Ci
metrics: 'metrics.txt'
}.freeze
- TYPE_AND_FORMAT_PAIRS = {
+ INTERNAL_TYPES = {
archive: :zip,
metadata: :gzip,
- trace: :raw,
+ trace: :raw
+ }.freeze
+
+ REPORT_TYPES = {
junit: :gzip,
metrics: :gzip,
@@ -44,6 +48,8 @@ module Ci
performance: :raw
}.freeze
+ TYPE_AND_FORMAT_PAIRS = INTERNAL_TYPES.merge(REPORT_TYPES).freeze
+
belongs_to :project
belongs_to :job, class_name: "Ci::Build", foreign_key: :job_id
@@ -52,10 +58,10 @@ module Ci
validates :file_format, presence: true, unless: :trace?, on: :create
validate :valid_file_format?, unless: :trace?, on: :create
before_save :set_size, if: :file_changed?
- after_save :update_project_statistics_after_save, if: :size_changed?
- after_destroy :update_project_statistics_after_destroy, unless: :project_destroyed?
- after_save :update_file_store, if: :file_changed?
+ update_project_statistics project_statistics_name: :build_artifacts_size
+
+ after_save :update_file_store, if: :saved_change_to_file?
scope :with_files_stored_locally, -> { where(file_store: [nil, ::JobArtifactUploader::Store::LOCAL]) }
@@ -65,6 +71,10 @@ module Ci
where(file_type: types)
end
+ scope :with_reports, -> do
+ with_file_types(REPORT_TYPES.keys.map(&:to_s))
+ end
+
scope :test_reports, -> do
with_file_types(TEST_REPORT_FILE_TYPES)
end
@@ -98,7 +108,7 @@ module Ci
raw: 1,
zip: 2,
gzip: 3
- }
+ }, _suffix: true
# `file_location` indicates where actual files are stored.
# Ideally, actual files should be stored in the same directory, and use the same
@@ -176,18 +186,6 @@ module Ci
self.size = file.size
end
- def update_project_statistics_after_save
- update_project_statistics(size.to_i - size_was.to_i)
- end
-
- def update_project_statistics_after_destroy
- update_project_statistics(-self.size.to_i)
- end
-
- def update_project_statistics(difference)
- ProjectStatistics.increment_statistic(project_id, :build_artifacts_size, difference)
- end
-
def project_destroyed?
# Use job.project to avoid extra DB query for project
job.project.pending_delete?
diff --git a/app/models/ci/legacy_stage.rb b/app/models/ci/legacy_stage.rb
index 96dbc7b6895..930c8a71453 100644
--- a/app/models/ci/legacy_stage.rb
+++ b/app/models/ci/legacy_stage.rb
@@ -58,5 +58,9 @@ module Ci
statuses.latest.failed_but_allowed.any?
end
end
+
+ def manual_playable?
+ %[manual scheduled skipped].include?(status.to_s)
+ end
end
end
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index b8edaf82c3d..3727a9861aa 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -166,6 +166,16 @@ module Ci
end
end
+ after_transition any => ::Ci::Pipeline.completed_statuses do |pipeline|
+ pipeline.run_after_commit do
+ pipeline.all_merge_requests.each do |merge_request|
+ next unless merge_request.auto_merge_enabled?
+
+ AutoMergeProcessWorker.perform_async(merge_request.id)
+ end
+ end
+ end
+
after_transition any => [:success, :failed] do |pipeline|
pipeline.run_after_commit do
PipelineNotificationWorker.perform_async(pipeline.id)
@@ -642,6 +652,7 @@ module Ci
variables.append(key: 'CI_COMMIT_MESSAGE', value: git_commit_message.to_s)
variables.append(key: 'CI_COMMIT_TITLE', value: git_commit_full_title.to_s)
variables.append(key: 'CI_COMMIT_DESCRIPTION', value: git_commit_description.to_s)
+ variables.append(key: 'CI_COMMIT_REF_PROTECTED', value: (!!protected_ref?).to_s)
if merge_request_event? && merge_request
variables.append(key: 'CI_MERGE_REQUEST_SOURCE_BRANCH_SHA', value: source_sha.to_s)
@@ -758,6 +769,22 @@ module Ci
user == current_user
end
+ def source_ref
+ if triggered_by_merge_request?
+ merge_request.source_branch
+ else
+ ref
+ end
+ end
+
+ def source_ref_slug
+ Gitlab::Utils.slugify(source_ref.to_s)
+ end
+
+ def find_stage_by_name!(name)
+ stages.find_by!(name: name)
+ end
+
private
def ci_yaml_from_repo
diff --git a/app/models/ci/pipeline_schedule.rb b/app/models/ci/pipeline_schedule.rb
index 1454b2dfb39..6a4241c94bc 100644
--- a/app/models/ci/pipeline_schedule.rb
+++ b/app/models/ci/pipeline_schedule.rb
@@ -5,6 +5,7 @@ module Ci
extend Gitlab::Ci::Model
include Importable
include IgnorableColumn
+ include StripAttribute
ignore_column :deleted_at
@@ -22,11 +23,17 @@ module Ci
before_save :set_next_run_at
+ strip_attributes :cron
+
scope :active, -> { where(active: true) }
scope :inactive, -> { where(active: false) }
+ scope :runnable_schedules, -> { active.where("next_run_at < ?", Time.now) }
+ scope :preloaded, -> { preload(:owner, :project) }
accepts_nested_attributes_for :variables, allow_destroy: true
+ alias_attribute :real_next_run, :next_run_at
+
def owned_by?(current_user)
owner == current_user
end
@@ -43,8 +50,14 @@ module Ci
update_attribute(:active, false)
end
+ ##
+ # The `next_run_at` column is set to the actual execution date of `PipelineScheduleWorker`.
+ # This way, a schedule like `*/1 * * * *` won't be triggered in a short interval
+ # when PipelineScheduleWorker runs irregularly by Sidekiq Memory Killer.
def set_next_run_at
- self.next_run_at = Gitlab::Ci::CronParser.new(cron, cron_timezone).next_time_from(Time.now)
+ self.next_run_at = Gitlab::Ci::CronParser.new(Settings.cron_jobs['pipeline_schedule_worker']['cron'],
+ Time.zone.name)
+ .next_time_from(ideal_next_run_at)
end
def schedule_next_run!
@@ -53,15 +66,15 @@ module Ci
update_attribute(:next_run_at, nil) # update without validation
end
- def real_next_run(
- worker_cron: Settings.cron_jobs['pipeline_schedule_worker']['cron'],
- worker_time_zone: Time.zone.name)
- Gitlab::Ci::CronParser.new(worker_cron, worker_time_zone)
- .next_time_from(next_run_at)
- end
-
def job_variables
variables&.map(&:to_runner_variable) || []
end
+
+ private
+
+ def ideal_next_run_at
+ Gitlab::Ci::CronParser.new(cron, cron_timezone)
+ .next_time_from(Time.zone.now)
+ end
end
end
diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb
index b25b0369666..d90339d90dc 100644
--- a/app/models/ci/stage.rb
+++ b/app/models/ci/stage.rb
@@ -120,5 +120,9 @@ module Ci
.new(self, current_user)
.fabricate!
end
+
+ def manual_playable?
+ blocked? || skipped?
+ end
end
end
diff --git a/app/models/clusters/applications/cert_manager.rb b/app/models/clusters/applications/cert_manager.rb
index ac0e7eb03bc..d6a7d1d2bdd 100644
--- a/app/models/clusters/applications/cert_manager.rb
+++ b/app/models/clusters/applications/cert_manager.rb
@@ -24,6 +24,12 @@ module Clusters
'stable/cert-manager'
end
+ # We will implement this in future MRs.
+ # Need to reverse postinstall step
+ def allowed_to_uninstall?
+ false
+ end
+
def install_command
Gitlab::Kubernetes::Helm::InstallCommand.new(
name: 'certmanager',
diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb
index 71aff00077d..a83d06c4b00 100644
--- a/app/models/clusters/applications/helm.rb
+++ b/app/models/clusters/applications/helm.rb
@@ -29,6 +29,13 @@ module Clusters
self.status = 'installable' if cluster&.platform_kubernetes_active?
end
+ # We will implement this in future MRs.
+ # Basically we need to check all other applications are not installed
+ # first.
+ def allowed_to_uninstall?
+ false
+ end
+
def install_command
Gitlab::Kubernetes::Helm::InitCommand.new(
name: name,
diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb
index 376d54aab2c..a1023f44049 100644
--- a/app/models/clusters/applications/ingress.rb
+++ b/app/models/clusters/applications/ingress.rb
@@ -35,6 +35,13 @@ module Clusters
'stable/nginx-ingress'
end
+ # We will implement this in future MRs.
+ # Basically we need to check all dependent applications are not installed
+ # first.
+ def allowed_to_uninstall?
+ false
+ end
+
def install_command
Gitlab::Kubernetes::Helm::InstallCommand.new(
name: name,
diff --git a/app/models/clusters/applications/jupyter.rb b/app/models/clusters/applications/jupyter.rb
index f86ff3551a1..4aaa1f941e5 100644
--- a/app/models/clusters/applications/jupyter.rb
+++ b/app/models/clusters/applications/jupyter.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require 'securerandom'
+
module Clusters
module Applications
class Jupyter < ApplicationRecord
@@ -38,6 +40,12 @@ module Clusters
content_values.to_yaml
end
+ # Will be addressed in future MRs
+ # We need to investigate and document what will be permanently deleted.
+ def allowed_to_uninstall?
+ false
+ end
+
def install_command
Gitlab::Kubernetes::Helm::InstallCommand.new(
name: name,
@@ -53,6 +61,10 @@ module Clusters
"http://#{hostname}/hub/oauth_callback"
end
+ def oauth_scopes
+ 'api read_repository write_repository'
+ end
+
private
def specification
@@ -74,6 +86,9 @@ module Clusters
"secretToken" => secret_token
},
"auth" => {
+ "state" => {
+ "cryptoKey" => crypto_key
+ },
"gitlab" => {
"clientId" => oauth_application.uid,
"clientSecret" => oauth_application.secret,
@@ -83,12 +98,17 @@ module Clusters
},
"singleuser" => {
"extraEnv" => {
- "GITLAB_CLUSTER_ID" => cluster.id.to_s
+ "GITLAB_CLUSTER_ID" => cluster.id.to_s,
+ "GITLAB_HOST" => gitlab_host
}
}
}
end
+ def crypto_key
+ @crypto_key ||= SecureRandom.hex(32)
+ end
+
def project_id
cluster&.project&.id
end
@@ -97,6 +117,10 @@ module Clusters
Gitlab.config.gitlab.url
end
+ def gitlab_host
+ Gitlab.config.gitlab.host
+ end
+
def content_values
YAML.load_file(chart_values_file).deep_merge!(specification)
end
diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb
index f7e54833296..d5a3bd62e3d 100644
--- a/app/models/clusters/applications/knative.rb
+++ b/app/models/clusters/applications/knative.rb
@@ -3,7 +3,7 @@
module Clusters
module Applications
class Knative < ApplicationRecord
- VERSION = '0.3.0'.freeze
+ VERSION = '0.5.0'.freeze
REPOSITORY = 'https://storage.googleapis.com/triggermesh-charts'.freeze
METRICS_CONFIG = 'https://storage.googleapis.com/triggermesh-charts/istio-metrics.yaml'.freeze
FETCH_IP_ADDRESS_DELAY = 30.seconds
@@ -15,9 +15,6 @@ module Clusters
include ::Clusters::Concerns::ApplicationVersion
include ::Clusters::Concerns::ApplicationData
include AfterCommitQueue
- include ReactiveCaching
-
- self.reactive_cache_key = ->(knative) { [knative.class.model_name.singular, knative.id] }
def set_initial_status
return unless not_installable?
@@ -41,8 +38,6 @@ module Clusters
scope :for_cluster, -> (cluster) { where(cluster: cluster) }
- after_save :clear_reactive_cache!
-
def chart
'knative/knative'
end
@@ -51,6 +46,12 @@ module Clusters
{ "domain" => hostname }.to_yaml
end
+ # Handled in a new issue:
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/59369
+ def allowed_to_uninstall?
+ false
+ end
+
def install_command
Gitlab::Kubernetes::Helm::InstallCommand.new(
name: name,
@@ -71,55 +72,12 @@ module Clusters
ClusterWaitForIngressIpAddressWorker.perform_async(name, id)
end
- def client
- cluster.kubeclient.knative_client
- end
-
- def services
- with_reactive_cache do |data|
- data[:services]
- end
- end
-
- def calculate_reactive_cache
- { services: read_services, pods: read_pods }
- end
-
def ingress_service
cluster.kubeclient.get_service('istio-ingressgateway', 'istio-system')
end
- def services_for(ns: namespace)
- return [] unless services
- return [] unless ns
-
- services.select do |service|
- service.dig('metadata', 'namespace') == ns
- end
- end
-
- def service_pod_details(ns, service)
- with_reactive_cache do |data|
- data[:pods].select { |pod| filter_pods(pod, ns, service) }
- end
- end
-
private
- def read_pods
- cluster.kubeclient.core_client.get_pods.as_json
- end
-
- def filter_pods(pod, namespace, service)
- pod["metadata"]["namespace"] == namespace && pod["metadata"]["labels"]["serving.knative.dev/service"] == service
- end
-
- def read_services
- client.get_services.as_json
- rescue Kubeclient::ResourceNotFoundError
- []
- end
-
def install_knative_metrics
["kubectl apply -f #{METRICS_CONFIG}"] if cluster.application_prometheus_available?
end
diff --git a/app/models/clusters/applications/prometheus.rb b/app/models/clusters/applications/prometheus.rb
index 954c29da196..a6b7617b830 100644
--- a/app/models/clusters/applications/prometheus.rb
+++ b/app/models/clusters/applications/prometheus.rb
@@ -16,10 +16,12 @@ module Clusters
default_value_for :version, VERSION
+ after_destroy :disable_prometheus_integration
+
state_machine :status do
after_transition any => [:installed] do |application|
application.cluster.projects.each do |project|
- project.find_or_initialize_service('prometheus').update(active: true)
+ project.find_or_initialize_service('prometheus').update!(active: true)
end
end
end
@@ -47,6 +49,14 @@ module Clusters
)
end
+ def uninstall_command
+ Gitlab::Kubernetes::Helm::DeleteCommand.new(
+ name: name,
+ rbac: cluster.platform_kubernetes_rbac?,
+ files: files
+ )
+ end
+
def upgrade_command(values)
::Gitlab::Kubernetes::Helm::InstallCommand.new(
name: name,
@@ -82,6 +92,12 @@ module Clusters
private
+ def disable_prometheus_integration
+ cluster.projects.each do |project|
+ project.prometheus_service&.update!(active: false)
+ end
+ end
+
def kube_client
cluster&.kubeclient&.core_client
end
diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb
index 8cb81bfcbe4..db7fd8524c2 100644
--- a/app/models/clusters/applications/runner.rb
+++ b/app/models/clusters/applications/runner.rb
@@ -3,7 +3,7 @@
module Clusters
module Applications
class Runner < ApplicationRecord
- VERSION = '0.3.0'.freeze
+ VERSION = '0.5.2'.freeze
self.table_name = 'clusters_applications_runners'
@@ -29,6 +29,13 @@ module Clusters
content_values.to_yaml
end
+ # Need to investigate if pipelines run by this runner will stop upon the
+ # executor pod stopping
+ # I.e.run a pipeline, and uninstall runner while pipeline is running
+ def allowed_to_uninstall?
+ false
+ end
+
def install_command
Gitlab::Kubernetes::Helm::InstallCommand.new(
name: name,
@@ -62,10 +69,12 @@ module Clusters
}
if cluster.group_type?
- attributes.merge(groups: [group])
+ attributes[:groups] = [group]
elsif cluster.project_type?
- attributes.merge(projects: [project])
+ attributes[:projects] = [project]
end
+
+ attributes
end
def gitlab_url
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index 4262c03498d..ccc877fb924 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -5,19 +5,20 @@ module Clusters
include Presentable
include Gitlab::Utils::StrongMemoize
include FromUnion
+ include ReactiveCaching
self.table_name = 'clusters'
PROJECT_ONLY_APPLICATIONS = {
Applications::Jupyter.application_name => Applications::Jupyter,
- Applications::Knative.application_name => Applications::Knative,
- Applications::Prometheus.application_name => Applications::Prometheus
+ Applications::Knative.application_name => Applications::Knative
}.freeze
APPLICATIONS = {
Applications::Helm.application_name => Applications::Helm,
Applications::Ingress.application_name => Applications::Ingress,
Applications::CertManager.application_name => Applications::CertManager,
- Applications::Runner.application_name => Applications::Runner
+ Applications::Runner.application_name => Applications::Runner,
+ Applications::Prometheus.application_name => Applications::Prometheus
}.merge(PROJECT_ONLY_APPLICATIONS).freeze
DEFAULT_ENVIRONMENT = '*'.freeze
KUBE_INGRESS_BASE_DOMAIN = 'KUBE_INGRESS_BASE_DOMAIN'.freeze
@@ -45,7 +46,6 @@ module Clusters
has_one :application_knative, class_name: 'Clusters::Applications::Knative'
has_many :kubernetes_namespaces
- has_one :kubernetes_namespace, -> { order(id: :desc) }, class_name: 'Clusters::KubernetesNamespace'
accepts_nested_attributes_for :provider_gcp, update_only: true
accepts_nested_attributes_for :platform_kubernetes, update_only: true
@@ -58,6 +58,8 @@ module Clusters
validate :no_groups, unless: :group_type?
validate :no_projects, unless: :project_type?
+ after_save :clear_reactive_cache!
+
delegate :status, to: :provider, allow_nil: true
delegate :status_reason, to: :provider, allow_nil: true
delegate :on_creation?, to: :provider, allow_nil: true
@@ -94,6 +96,7 @@ module Clusters
scope :user_provided, -> { where(provider_type: ::Clusters::Cluster.provider_types[:user]) }
scope :gcp_provided, -> { where(provider_type: ::Clusters::Cluster.provider_types[:gcp]) }
scope :gcp_installed, -> { gcp_provided.includes(:provider_gcp).where(cluster_providers_gcp: { status: ::Clusters::Providers::Gcp.state_machines[:status].states[:created].value }) }
+ scope :managed, -> { where(managed: true) }
scope :default_environment, -> { where(environment_scope: DEFAULT_ENVIRONMENT) }
@@ -107,29 +110,35 @@ module Clusters
scope :preload_knative, -> {
preload(
- :kubernetes_namespace,
+ :kubernetes_namespaces,
:platform_kubernetes,
:application_knative
)
}
def self.ancestor_clusters_for_clusterable(clusterable, hierarchy_order: :asc)
+ return [] if clusterable.is_a?(Instance)
+
hierarchy_groups = clusterable.ancestors_upto(hierarchy_order: hierarchy_order).eager_load(:clusters)
hierarchy_groups = hierarchy_groups.merge(current_scope) if current_scope
- hierarchy_groups.flat_map(&:clusters)
+ hierarchy_groups.flat_map(&:clusters) + Instance.new.clusters
end
def status_name
- if provider
- provider.status_name
- else
- :created
+ provider&.status_name || connection_status.presence || :created
+ end
+
+ def connection_status
+ with_reactive_cache do |data|
+ data[:connection_status]
end
end
- def created?
- status_name == :created
+ def calculate_reactive_cache
+ return unless enabled?
+
+ { connection_status: retrieve_connection_status }
end
def applications
@@ -176,20 +185,24 @@ module Clusters
end
alias_method :group, :first_group
+ def instance
+ Instance.new if instance_type?
+ end
+
def kubeclient
platform_kubernetes.kubeclient if kubernetes?
end
+ def kubernetes_namespace_for(project)
+ find_or_initialize_kubernetes_namespace_for_project(project).namespace
+ end
+
def find_or_initialize_kubernetes_namespace_for_project(project)
- if project_type?
- kubernetes_namespaces.find_or_initialize_by(
- project: project,
- cluster_project: cluster_project
- )
- else
- kubernetes_namespaces.find_or_initialize_by(
- project: project
- )
+ attributes = { project: project }
+ attributes[:cluster_project] = cluster_project if project_type?
+
+ kubernetes_namespaces.find_or_initialize_by(attributes).tap do |namespace|
+ namespace.set_defaults
end
end
@@ -198,7 +211,7 @@ module Clusters
end
def kube_ingress_domain
- @kube_ingress_domain ||= domain.presence || instance_domain || legacy_auto_devops_domain
+ @kube_ingress_domain ||= domain.presence || instance_domain
end
def predefined_variables
@@ -209,12 +222,43 @@ module Clusters
end
end
+ def knative_services_finder(project)
+ @knative_services_finder ||= KnativeServicesFinder.new(self, project)
+ end
+
private
def instance_domain
@instance_domain ||= Gitlab::CurrentSettings.auto_devops_domain
end
+ def retrieve_connection_status
+ kubeclient.core_client.discover
+ rescue *Gitlab::Kubernetes::Errors::CONNECTION
+ :unreachable
+ rescue *Gitlab::Kubernetes::Errors::AUTHENTICATION
+ :authentication_failure
+ rescue Kubeclient::HttpError => e
+ kubeclient_error_status(e.message)
+ rescue => e
+ Gitlab::Sentry.track_acceptable_exception(e, extra: { cluster_id: id })
+
+ :unknown_failure
+ else
+ :connected
+ end
+
+ # KubeClient uses the same error class
+ # For connection errors (eg. timeout) and
+ # for Kubernetes errors.
+ def kubeclient_error_status(message)
+ if message&.match?(/timed out|timeout/i)
+ :unreachable
+ else
+ :authentication_failure
+ end
+ end
+
# To keep backward compatibility with AUTO_DEVOPS_DOMAIN
# environment variable, we need to ensure KUBE_INGRESS_BASE_DOMAIN
# is set if AUTO_DEVOPS_DOMAIN is set on any of the following options:
diff --git a/app/models/clusters/concerns/application_core.rb b/app/models/clusters/concerns/application_core.rb
index ee964fb7c93..4514498b84b 100644
--- a/app/models/clusters/concerns/application_core.rb
+++ b/app/models/clusters/concerns/application_core.rb
@@ -18,6 +18,16 @@ module Clusters
self.status = 'installable' if cluster&.application_helm_available?
end
+ def can_uninstall?
+ allowed_to_uninstall?
+ end
+
+ # All new applications should uninstall by default
+ # Override if there's dependencies that needs to be uninstalled first
+ def allowed_to_uninstall?
+ true
+ end
+
def self.application_name
self.to_s.demodulize.underscore
end
diff --git a/app/models/clusters/concerns/application_data.rb b/app/models/clusters/concerns/application_data.rb
index a48ee340fac..3479fea415e 100644
--- a/app/models/clusters/concerns/application_data.rb
+++ b/app/models/clusters/concerns/application_data.rb
@@ -3,56 +3,52 @@
module Clusters
module Concerns
module ApplicationData
- extend ActiveSupport::Concern
-
- included do
- def uninstall_command
- Gitlab::Kubernetes::Helm::DeleteCommand.new(
- name: name,
- rbac: cluster.platform_kubernetes_rbac?,
- files: files
- )
- end
+ def uninstall_command
+ Gitlab::Kubernetes::Helm::DeleteCommand.new(
+ name: name,
+ rbac: cluster.platform_kubernetes_rbac?,
+ files: files
+ )
+ end
- def repository
- nil
- end
+ def repository
+ nil
+ end
- def values
- File.read(chart_values_file)
- end
+ def values
+ File.read(chart_values_file)
+ end
- def files
- @files ||= begin
- files = { 'values.yaml': values }
+ def files
+ @files ||= begin
+ files = { 'values.yaml': values }
- files.merge!(certificate_files) if cluster.application_helm.has_ssl?
+ files.merge!(certificate_files) if cluster.application_helm.has_ssl?
- files
- end
+ files
end
+ end
- private
+ private
- def certificate_files
- {
- 'ca.pem': ca_cert,
- 'cert.pem': helm_cert.cert_string,
- 'key.pem': helm_cert.key_string
- }
- end
+ def certificate_files
+ {
+ 'ca.pem': ca_cert,
+ 'cert.pem': helm_cert.cert_string,
+ 'key.pem': helm_cert.key_string
+ }
+ end
- def ca_cert
- cluster.application_helm.ca_cert
- end
+ def ca_cert
+ cluster.application_helm.ca_cert
+ end
- def helm_cert
- @helm_cert ||= cluster.application_helm.issue_client_cert
- end
+ def helm_cert
+ @helm_cert ||= cluster.application_helm.issue_client_cert
+ end
- def chart_values_file
- "#{Rails.root}/vendor/#{name}/values.yaml"
- end
+ def chart_values_file
+ "#{Rails.root}/vendor/#{name}/values.yaml"
end
end
end
diff --git a/app/models/clusters/concerns/application_status.rb b/app/models/clusters/concerns/application_status.rb
index 1273ed83abe..54a3dda6d75 100644
--- a/app/models/clusters/concerns/application_status.rb
+++ b/app/models/clusters/concerns/application_status.rb
@@ -25,9 +25,11 @@ module Clusters
state :updating, value: 4
state :updated, value: 5
state :update_errored, value: 6
+ state :uninstalling, value: 7
+ state :uninstall_errored, value: 8
event :make_scheduled do
- transition [:installable, :errored, :installed, :updated, :update_errored] => :scheduled
+ transition [:installable, :errored, :installed, :updated, :update_errored, :uninstall_errored] => :scheduled
end
event :make_installing do
@@ -40,8 +42,9 @@ module Clusters
end
event :make_errored do
- transition any - [:updating] => :errored
+ transition any - [:updating, :uninstalling] => :errored
transition [:updating] => :update_errored
+ transition [:uninstalling] => :uninstall_errored
end
event :make_updating do
@@ -52,6 +55,10 @@ module Clusters
transition any => :update_errored
end
+ event :make_uninstalling do
+ transition [:scheduled] => :uninstalling
+ end
+
before_transition any => [:scheduled] do |app_status, _|
app_status.status_reason = nil
end
@@ -65,7 +72,7 @@ module Clusters
app_status.status_reason = nil
end
- before_transition any => [:update_errored] do |app_status, transition|
+ before_transition any => [:update_errored, :uninstall_errored] do |app_status, transition|
status_reason = transition.args.first
app_status.status_reason = status_reason if status_reason
end
diff --git a/app/models/clusters/instance.rb b/app/models/clusters/instance.rb
new file mode 100644
index 00000000000..d8a888d53ba
--- /dev/null
+++ b/app/models/clusters/instance.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Clusters
+ class Instance
+ def clusters
+ Clusters::Cluster.instance_type
+ end
+
+ def feature_available?(feature)
+ ::Feature.enabled?(feature, default_enabled: true)
+ end
+
+ def self.enabled?
+ ::Feature.enabled?(:instance_clusters, default_enabled: true)
+ end
+ end
+end
diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb
index 2ae141190a8..8e06156c73d 100644
--- a/app/models/clusters/platforms/kubernetes.rb
+++ b/app/models/clusters/platforms/kubernetes.rb
@@ -11,7 +11,6 @@ module Clusters
RESERVED_NAMESPACES = %w(gitlab-managed-apps).freeze
self.table_name = 'cluster_platforms_kubernetes'
- self.reactive_cache_key = ->(kubernetes) { [kubernetes.class.model_name.singular, kubernetes.id] }
belongs_to :cluster, inverse_of: :platform_kubernetes, class_name: 'Clusters::Cluster'
@@ -52,11 +51,14 @@ module Clusters
alias_attribute :ca_pem, :ca_cert
- delegate :project, to: :cluster, allow_nil: true
delegate :enabled?, to: :cluster, allow_nil: true
delegate :provided_by_user?, to: :cluster, allow_nil: true
delegate :allow_user_defined_namespace?, to: :cluster, allow_nil: true
- delegate :kubernetes_namespace, to: :cluster
+
+ # This is just to maintain compatibility with KubernetesService, which
+ # will be removed in https://gitlab.com/gitlab-org/gitlab-ce/issues/39217.
+ # It can be removed once KubernetesService is gone.
+ delegate :kubernetes_namespace_for, to: :cluster, allow_nil: true
alias_method :active?, :enabled?
@@ -68,14 +70,6 @@ module Clusters
default_value_for :authorization_type, :rbac
- def actual_namespace
- if namespace.present?
- namespace
- else
- default_namespace
- end
- end
-
def predefined_variables(project:)
Gitlab::Ci::Variables::Collection.new.tap do |variables|
variables.append(key: 'KUBE_URL', value: api_url)
@@ -88,16 +82,19 @@ module Clusters
if kubernetes_namespace = cluster.kubernetes_namespaces.has_service_account_token.find_by(project: project)
variables.concat(kubernetes_namespace.predefined_variables)
- elsif cluster.project_type?
- # From 11.5, every Clusters::Project should have at least one
- # Clusters::KubernetesNamespace, so once migration has been completed,
- # this 'else' branch will be removed. For more information, please see
- # https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22433
+ elsif cluster.project_type? || !cluster.managed?
+ # As of 11.11 a user can create a cluster that they manage themselves,
+ # which replicates the existing project-level cluster behaviour.
+ # Once we have marked all project-level clusters that make use of this
+ # behaviour as "unmanaged", we can remove the `cluster.project_type?`
+ # check here.
+ project_namespace = cluster.kubernetes_namespace_for(project)
+
variables
.append(key: 'KUBE_URL', value: api_url)
.append(key: 'KUBE_TOKEN', value: token, public: false, masked: true)
- .append(key: 'KUBE_NAMESPACE', value: actual_namespace)
- .append(key: 'KUBECONFIG', value: kubeconfig, public: false, file: true)
+ .append(key: 'KUBE_NAMESPACE', value: project_namespace)
+ .append(key: 'KUBECONFIG', value: kubeconfig(project_namespace), public: false, file: true)
end
variables.concat(cluster.predefined_variables)
@@ -110,8 +107,10 @@ module Clusters
# short time later
def terminals(environment)
with_reactive_cache do |data|
+ project = environment.project
+
pods = filter_by_project_environment(data[:pods], project.full_path_slug, environment.slug)
- terminals = pods.flat_map { |pod| terminals_for_pod(api_url, actual_namespace, pod) }.compact
+ terminals = pods.flat_map { |pod| terminals_for_pod(api_url, cluster.kubernetes_namespace_for(project), pod) }.compact
terminals.each { |terminal| add_terminal_auth(terminal, terminal_auth) }
end
end
@@ -119,7 +118,7 @@ module Clusters
# Caches resources in the namespace so other calls don't need to block on
# network access
def calculate_reactive_cache
- return unless enabled? && project && !project.pending_delete?
+ return unless enabled?
# We may want to cache extra things in the future
{ pods: read_pods }
@@ -131,33 +130,16 @@ module Clusters
private
- def kubeconfig
+ def kubeconfig(namespace)
to_kubeconfig(
url: api_url,
- namespace: actual_namespace,
+ namespace: namespace,
token: token,
ca_pem: ca_pem)
end
- def default_namespace
- kubernetes_namespace&.namespace.presence || fallback_default_namespace
- end
-
- # DEPRECATED
- #
- # On 11.4 Clusters::KubernetesNamespace was introduced, this model will allow to
- # have multiple namespaces per project. This method will be removed after migration
- # has been completed.
- def fallback_default_namespace
- return unless project
-
- slug = "#{project.path}-#{project.id}".downcase
- Gitlab::NamespaceSanitizer.sanitize(slug)
- end
-
def build_kube_client!
raise "Incomplete settings" unless api_url
- raise "No namespace" if cluster.project_type? && actual_namespace.empty? # can probably remove this line once we remove #actual_namespace
unless (username && password) || token
raise "Either username/password or token is required to access API"
@@ -173,9 +155,13 @@ module Clusters
# Returns a hash of all pods in the namespace
def read_pods
- kubeclient = build_kube_client!
+ # TODO: The project lookup here should be moved (to environment?),
+ # which will enable reading pods from the correct namespace for group
+ # and instance clusters.
+ # This will be done in https://gitlab.com/gitlab-org/gitlab-ce/issues/61156
+ return [] unless cluster.project_type?
- kubeclient.get_pods(namespace: actual_namespace).as_json
+ kubeclient.get_pods(namespace: cluster.kubernetes_namespace_for(cluster.first_project)).as_json
rescue Kubeclient::ResourceNotFoundError
[]
end
@@ -230,7 +216,7 @@ module Clusters
end
def update_kubernetes_namespace
- return unless namespace_changed?
+ return unless saved_change_to_namespace?
run_after_commit do
ClusterConfigureWorker.perform_async(cluster_id)
diff --git a/app/models/clusters/project.rb b/app/models/clusters/project.rb
index d2b68b3f117..e0bf60164ba 100644
--- a/app/models/clusters/project.rb
+++ b/app/models/clusters/project.rb
@@ -8,6 +8,5 @@ module Clusters
belongs_to :project, class_name: '::Project'
has_many :kubernetes_namespaces, class_name: 'Clusters::KubernetesNamespace', foreign_key: :cluster_project_id
- has_one :kubernetes_namespace, -> { order(id: :desc) }, class_name: 'Clusters::KubernetesNamespace', foreign_key: :cluster_project_id
end
end
diff --git a/app/models/commit.rb b/app/models/commit.rb
index f412d252e5c..be37fa2e76f 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -13,6 +13,7 @@ class Commit
include StaticModel
include Presentable
include ::Gitlab::Utils::StrongMemoize
+ include CacheMarkdownField
attr_mentionable :safe_message, pipeline: :single_line
@@ -37,13 +38,9 @@ class Commit
# Used by GFM to match and present link extensions on node texts and hrefs.
LINK_EXTENSION_PATTERN = /(patch)/.freeze
- def banzai_render_context(field)
- pipeline = field == :description ? :commit_description : :single_line
- context = { pipeline: pipeline, project: self.project }
- context[:author] = self.author if self.author
-
- context
- end
+ cache_markdown_field :title, pipeline: :single_line
+ cache_markdown_field :full_title, pipeline: :single_line
+ cache_markdown_field :description, pipeline: :commit_description
class << self
def decorate(commits, project)
@@ -97,7 +94,7 @@ class Commit
end
def lazy(project, oid)
- BatchLoader.for({ project: project, oid: oid }).batch do |items, loader|
+ BatchLoader.for({ project: project, oid: oid }).batch(replace_methods: false) do |items, loader|
items_by_project = items.group_by { |i| i[:project] }
items_by_project.each do |project, commit_ids|
diff --git a/app/models/commit_range.rb b/app/models/commit_range.rb
index 920b1d092dd..08ca86bc902 100644
--- a/app/models/commit_range.rb
+++ b/app/models/commit_range.rb
@@ -28,12 +28,12 @@ class CommitRange
# The beginning and ending refs can be named or SHAs, and
# the range notation can be double- or triple-dot.
- REF_PATTERN = /[0-9a-zA-Z][0-9a-zA-Z_.-]*[0-9a-zA-Z\^]/
- PATTERN = /#{REF_PATTERN}\.{2,3}#{REF_PATTERN}/
+ REF_PATTERN = /[0-9a-zA-Z][0-9a-zA-Z_.-]*[0-9a-zA-Z\^]/.freeze
+ PATTERN = /#{REF_PATTERN}\.{2,3}#{REF_PATTERN}/.freeze
# In text references, the beginning and ending refs can only be SHAs
# between 7 and 40 hex characters.
- STRICT_PATTERN = /\h{7,40}\.{2,3}\h{7,40}/
+ STRICT_PATTERN = /\h{7,40}\.{2,3}\h{7,40}/.freeze
def self.reference_prefix
'@'
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index f97dc38dab7..be6f3e9c5b0 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -140,7 +140,7 @@ class CommitStatus < ApplicationRecord
end
def locking_enabled?
- status_changed?
+ will_save_change_to_status?
end
def before_sha
diff --git a/app/models/concerns/artifact_migratable.rb b/app/models/concerns/artifact_migratable.rb
deleted file mode 100644
index 7c9f579b480..00000000000
--- a/app/models/concerns/artifact_migratable.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-# Adapter class to unify the interface between mounted uploaders and the
-# Ci::Artifact model
-# Meant to be prepended so the interface can stay the same
-module ArtifactMigratable
- def artifacts_file
- job_artifacts_archive&.file || legacy_artifacts_file
- end
-
- def artifacts_metadata
- job_artifacts_metadata&.file || legacy_artifacts_metadata
- end
-
- def artifacts?
- !artifacts_expired? && artifacts_file&.exists?
- end
-
- def artifacts_metadata?
- artifacts? && artifacts_metadata.exists?
- end
-
- def artifacts_file_changed?
- job_artifacts_archive&.file_changed? || attribute_changed?(:artifacts_file)
- end
-
- def remove_artifacts_file!
- if job_artifacts_archive
- job_artifacts_archive.destroy
- else
- remove_legacy_artifacts_file!
- end
- end
-
- def remove_artifacts_metadata!
- if job_artifacts_metadata
- job_artifacts_metadata.destroy
- else
- remove_legacy_artifacts_metadata!
- end
- end
-
- def artifacts_size
- read_attribute(:artifacts_size).to_i + job_artifacts.sum(:size).to_i
- end
-
- def legacy_artifacts_file
- return unless Feature.enabled?(:ci_enable_legacy_artifacts)
-
- super
- end
-
- def legacy_artifacts_metadata
- return unless Feature.enabled?(:ci_enable_legacy_artifacts)
-
- super
- end
-end
diff --git a/app/models/concerns/avatarable.rb b/app/models/concerns/avatarable.rb
index 4687ec7d166..80278e07e65 100644
--- a/app/models/concerns/avatarable.rb
+++ b/app/models/concerns/avatarable.rb
@@ -91,7 +91,8 @@ module Avatarable
private
def retrieve_upload_from_batch(identifier)
- BatchLoader.for(identifier: identifier, model: self).batch(key: self.class) do |upload_params, loader, args|
+ BatchLoader.for(identifier: identifier, model: self)
+ .batch(key: self.class, cache: true, replace_methods: false) do |upload_params, loader, args|
model_class = args[:key]
paths = upload_params.flat_map do |params|
params[:model].upload_paths(params[:identifier])
diff --git a/app/models/concerns/cache_markdown_field.rb b/app/models/concerns/cache_markdown_field.rb
index 28ea51d6769..42203a5f214 100644
--- a/app/models/concerns/cache_markdown_field.rb
+++ b/app/models/concerns/cache_markdown_field.rb
@@ -13,43 +13,9 @@
module CacheMarkdownField
extend ActiveSupport::Concern
- # Increment this number every time the renderer changes its output
- CACHE_COMMONMARK_VERSION_START = 10
- CACHE_COMMONMARK_VERSION = 15
-
# changes to these attributes cause the cache to be invalidates
INVALIDATED_BY = %w[author project].freeze
- # Knows about the relationship between markdown and html field names, and
- # stores the rendering contexts for the latter
- class FieldData
- def initialize
- @data = {}
- end
-
- delegate :[], :[]=, to: :@data
-
- def markdown_fields
- @data.keys
- end
-
- def html_field(markdown_field)
- "#{markdown_field}_html"
- end
-
- def html_fields
- markdown_fields.map { |field| html_field(field) }
- end
-
- def html_fields_whitelisted
- markdown_fields.each_with_object([]) do |field, fields|
- if @data[field].fetch(:whitelisted, false)
- fields << html_field(field)
- end
- end
- end
- end
-
def skip_project_check?
false
end
@@ -85,24 +51,22 @@ module CacheMarkdownField
end.to_h
updates['cached_markdown_version'] = latest_cached_markdown_version
- updates.each {|html_field, data| write_attribute(html_field, data) }
+ updates.each { |field, data| write_markdown_field(field, data) }
end
def refresh_markdown_cache!
updates = refresh_markdown_cache
- return unless persisted? && Gitlab::Database.read_write?
-
- update_columns(updates)
+ save_markdown(updates)
end
def cached_html_up_to_date?(markdown_field)
- html_field = cached_markdown_fields.html_field(markdown_field)
+ return false if cached_html_for(markdown_field).nil? && __send__(markdown_field).present? # rubocop:disable GitlabSecurity/PublicSend
- return false if cached_html_for(markdown_field).nil? && !__send__(markdown_field).nil? # rubocop:disable GitlabSecurity/PublicSend
+ html_field = cached_markdown_fields.html_field(markdown_field)
- markdown_changed = attribute_changed?(markdown_field) || false
- html_changed = attribute_changed?(html_field) || false
+ markdown_changed = markdown_field_changed?(markdown_field)
+ html_changed = markdown_field_changed?(html_field)
latest_cached_markdown_version == cached_markdown_version &&
(html_changed || markdown_changed == html_changed)
@@ -117,21 +81,21 @@ module CacheMarkdownField
end
def cached_html_for(markdown_field)
- raise ArgumentError.new("Unknown field: #{field}") unless
+ raise ArgumentError.new("Unknown field: #{markdown_field}") unless
cached_markdown_fields.markdown_fields.include?(markdown_field)
__send__(cached_markdown_fields.html_field(markdown_field)) # rubocop:disable GitlabSecurity/PublicSend
end
def latest_cached_markdown_version
- @latest_cached_markdown_version ||= (CacheMarkdownField::CACHE_COMMONMARK_VERSION << 16) | local_version
+ @latest_cached_markdown_version ||= (Gitlab::MarkdownCache::CACHE_COMMONMARK_VERSION << 16) | local_version
end
def local_version
# because local_markdown_version is stored in application_settings which
# uses cached_markdown_version too, we check explicitly to avoid
# endless loop
- return local_markdown_version if has_attribute?(:local_markdown_version)
+ return local_markdown_version if respond_to?(:has_attribute?) && has_attribute?(:local_markdown_version)
settings = Gitlab::CurrentSettings.current_application_settings
@@ -150,32 +114,14 @@ module CacheMarkdownField
included do
cattr_reader :cached_markdown_fields do
- FieldData.new
+ Gitlab::MarkdownCache::FieldData.new
end
- # Always exclude _html fields from attributes (including serialization).
- # They contain unredacted HTML, which would be a security issue
- alias_method :attributes_before_markdown_cache, :attributes
- def attributes
- attrs = attributes_before_markdown_cache
- html_fields = cached_markdown_fields.html_fields
- whitelisted = cached_markdown_fields.html_fields_whitelisted
- exclude_fields = html_fields - whitelisted
-
- exclude_fields.each do |field|
- attrs.delete(field)
- end
-
- if whitelisted.empty?
- attrs.delete('cached_markdown_version')
- end
-
- attrs
+ if self < ActiveRecord::Base
+ include Gitlab::MarkdownCache::ActiveRecord::Extension
+ else
+ prepend Gitlab::MarkdownCache::Redis::Extension
end
-
- # Using before_update here conflicts with elasticsearch-model somehow
- before_create :refresh_markdown_cache, if: :invalidated_markdown_cache?
- before_update :refresh_markdown_cache, if: :invalidated_markdown_cache?
end
class_methods do
@@ -193,10 +139,8 @@ module CacheMarkdownField
# The HTML becomes invalid if any dependent fields change. For now, assume
# author and project invalidate the cache in all circumstances.
define_method(invalidation_method) do
- changed_fields = changed_attributes.keys
- invalidations = changed_fields & [markdown_field.to_s, *INVALIDATED_BY]
- invalidations.delete(markdown_field.to_s) if changed_fields.include?("#{markdown_field}_html")
-
+ invalidations = changed_markdown_fields & [markdown_field.to_s, *INVALIDATED_BY]
+ invalidations.delete(markdown_field.to_s) if changed_markdown_fields.include?("#{markdown_field}_html")
!invalidations.empty? || !cached_html_up_to_date?(markdown_field)
end
end
diff --git a/app/models/concerns/ci/contextable.rb b/app/models/concerns/ci/contextable.rb
index 4986a42dbd2..e1d5ce7f7d4 100644
--- a/app/models/concerns/ci/contextable.rb
+++ b/app/models/concerns/ci/contextable.rb
@@ -70,8 +70,8 @@ module Ci
variables.append(key: 'CI_COMMIT_SHA', value: sha)
variables.append(key: 'CI_COMMIT_SHORT_SHA', value: short_sha)
variables.append(key: 'CI_COMMIT_BEFORE_SHA', value: before_sha)
- variables.append(key: 'CI_COMMIT_REF_NAME', value: ref)
- variables.append(key: 'CI_COMMIT_REF_SLUG', value: ref_slug)
+ variables.append(key: 'CI_COMMIT_REF_NAME', value: source_ref)
+ variables.append(key: 'CI_COMMIT_REF_SLUG', value: source_ref_slug)
variables.append(key: "CI_COMMIT_TAG", value: ref) if tag?
variables.append(key: "CI_PIPELINE_TRIGGERED", value: 'true') if trigger_request
variables.append(key: "CI_JOB_MANUAL", value: 'true') if action?
@@ -85,8 +85,8 @@ module Ci
Gitlab::Ci::Variables::Collection.new.tap do |variables|
variables.append(key: 'CI_BUILD_REF', value: sha)
variables.append(key: 'CI_BUILD_BEFORE_SHA', value: before_sha)
- variables.append(key: 'CI_BUILD_REF_NAME', value: ref)
- variables.append(key: 'CI_BUILD_REF_SLUG', value: ref_slug)
+ variables.append(key: 'CI_BUILD_REF_NAME', value: source_ref)
+ variables.append(key: 'CI_BUILD_REF_SLUG', value: source_ref_slug)
variables.append(key: 'CI_BUILD_NAME', value: name)
variables.append(key: 'CI_BUILD_STAGE', value: stage)
variables.append(key: "CI_BUILD_TAG", value: ref) if tag?
diff --git a/app/models/concerns/ci/pipeline_delegator.rb b/app/models/concerns/ci/pipeline_delegator.rb
new file mode 100644
index 00000000000..dbc5ed1bc9a
--- /dev/null
+++ b/app/models/concerns/ci/pipeline_delegator.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+##
+# This module is mainly used by child associations of `Ci::Pipeline` that needs to look up
+# single source of truth. For example, `Ci::Build` has `git_ref` method, which behaves
+# slightly different from `Ci::Pipeline`'s `git_ref`. This is very confusing as
+# the system could behave differently time to time.
+# We should have a single interface in `Ci::Pipeline` and access the method always.
+module Ci
+ module PipelineDelegator
+ extend ActiveSupport::Concern
+
+ included do
+ delegate :merge_request_event?,
+ :merge_request_ref?,
+ :source_ref,
+ :source_ref_slug,
+ :legacy_detached_merge_request_pipeline?, to: :pipeline
+ end
+ end
+end
diff --git a/app/models/concerns/deployment_platform.rb b/app/models/concerns/deployment_platform.rb
index 0107af5f8ec..9ac0d612db3 100644
--- a/app/models/concerns/deployment_platform.rb
+++ b/app/models/concerns/deployment_platform.rb
@@ -14,6 +14,7 @@ module DeploymentPlatform
def find_deployment_platform(environment)
find_cluster_platform_kubernetes(environment: environment) ||
find_group_cluster_platform_kubernetes_with_feature_guard(environment: environment) ||
+ find_instance_cluster_platform_kubernetes_with_feature_guard(environment: environment) ||
find_kubernetes_service_integration ||
build_cluster_and_deployment_platform
end
@@ -36,6 +37,18 @@ module DeploymentPlatform
.first&.platform_kubernetes
end
+ def find_instance_cluster_platform_kubernetes_with_feature_guard(environment: nil)
+ return unless Clusters::Instance.enabled?
+
+ find_instance_cluster_platform_kubernetes(environment: environment)
+ end
+
+ # EE would override this and utilize environment argument
+ def find_instance_cluster_platform_kubernetes(environment: nil)
+ Clusters::Instance.new.clusters.enabled.default_environment
+ .first&.platform_kubernetes
+ end
+
def find_kubernetes_service_integration
services.deployment.reorder(nil).find_by(active: true)
end
diff --git a/app/models/concerns/has_ref.rb b/app/models/concerns/has_ref.rb
index 413cd36dcaa..fa0cf5ddfd2 100644
--- a/app/models/concerns/has_ref.rb
+++ b/app/models/concerns/has_ref.rb
@@ -1,5 +1,8 @@
# frozen_string_literal: true
+##
+# We will disable `ref` and `sha` attributes in `Ci::Build` in the future
+# and remove this module in favor of Ci::PipelineDelegator.
module HasRef
extend ActiveSupport::Concern
diff --git a/app/models/concerns/has_status.rb b/app/models/concerns/has_status.rb
index 8882f48c281..78bcce2f592 100644
--- a/app/models/concerns/has_status.rb
+++ b/app/models/concerns/has_status.rb
@@ -66,6 +66,10 @@ module HasStatus
def all_state_names
state_machines.values.flat_map(&:states).flat_map { |s| s.map(&:name) }
end
+
+ def completed_statuses
+ COMPLETED_STATUSES.map(&:to_sym)
+ end
end
included do
diff --git a/app/models/concerns/has_variable.rb b/app/models/concerns/has_variable.rb
index 2ec42a1029b..b4e99569071 100644
--- a/app/models/concerns/has_variable.rb
+++ b/app/models/concerns/has_variable.rb
@@ -4,6 +4,11 @@ module HasVariable
extend ActiveSupport::Concern
included do
+ enum variable_type: {
+ env_var: 1,
+ file: 2
+ }
+
validates :key,
presence: true,
length: { maximum: 255 },
@@ -24,6 +29,6 @@ module HasVariable
end
def to_runner_variable
- { key: key, value: value, public: false }
+ { key: key, value: value, public: false, file: file? }
end
end
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index 3232c51bfbd..127430cc68f 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -117,7 +117,7 @@ module Issuable
# We want to use optimistic lock for cases when only title or description are involved
# http://api.rubyonrails.org/classes/ActiveRecord/Locking/Optimistic.html
def locking_enabled?
- title_changed? || description_changed?
+ will_save_change_to_title? || will_save_change_to_description?
end
def allows_multiple_assignees?
@@ -128,10 +128,6 @@ module Issuable
assignees.count > 1
end
- def milestone_available?
- project_id == milestone&.project_id || project.ancestors_upto.compact.include?(milestone&.group)
- end
-
private
def milestone_is_valid
@@ -277,6 +273,10 @@ module Issuable
end
end
+ def milestone_available?
+ project_id == milestone&.project_id || project.ancestors_upto.compact.include?(milestone&.group)
+ end
+
def assignee_or_author?(user)
author_id == user.id || assignees.exists?(user.id)
end
diff --git a/app/models/concerns/maskable.rb b/app/models/concerns/maskable.rb
index 8793f0ec965..e0f2c41b836 100644
--- a/app/models/concerns/maskable.rb
+++ b/app/models/concerns/maskable.rb
@@ -7,9 +7,9 @@ module Maskable
# * No escape characters
# * No variables
# * No spaces
- # * Minimal length of 8 characters
+ # * Minimal length of 8 characters from the Base64 alphabets (RFC4648)
# * Absolutely no fun is allowed
- REGEX = /\A\w{8,}\z/
+ REGEX = /\A[a-zA-Z0-9_+=\/-]{8,}\z/.freeze
included do
validates :masked, inclusion: { in: [true, false] }
diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb
index e65bbb8ca07..3deb86da6cf 100644
--- a/app/models/concerns/milestoneish.rb
+++ b/app/models/concerns/milestoneish.rb
@@ -1,28 +1,20 @@
# frozen_string_literal: true
module Milestoneish
- def closed_items_count(user)
- memoize_per_user(user, :closed_items_count) do
- (count_issues_by_state(user)['closed'] || 0) + merge_requests.closed_and_merged.size
- end
- end
-
- def total_items_count(user)
- memoize_per_user(user, :total_items_count) do
- total_issues_count(user) + merge_requests.size
- end
- end
-
def total_issues_count(user)
count_issues_by_state(user).values.sum
end
+ def closed_issues_count(user)
+ count_issues_by_state(user)['closed'].to_i
+ end
+
def complete?(user)
- total_items_count(user) > 0 && total_items_count(user) == closed_items_count(user)
+ total_issues_count(user) > 0 && total_issues_count(user) == closed_issues_count(user)
end
def percent_complete(user)
- ((closed_items_count(user) * 100) / total_items_count(user)).abs
+ closed_issues_count(user) * 100 / total_issues_count(user)
rescue ZeroDivisionError
0
end
diff --git a/app/models/concerns/noteable.rb b/app/models/concerns/noteable.rb
index 423ce7e7db1..4b428b0af83 100644
--- a/app/models/concerns/noteable.rb
+++ b/app/models/concerns/noteable.rb
@@ -3,17 +3,19 @@
module Noteable
extend ActiveSupport::Concern
- # `Noteable` class names that support resolvable notes.
- RESOLVABLE_TYPES = %w(MergeRequest).freeze
-
class_methods do
# `Noteable` class names that support replying to individual notes.
def replyable_types
%w(Issue MergeRequest)
end
+
+ # `Noteable` class names that support resolvable notes.
+ def resolvable_types
+ %w(MergeRequest)
+ end
end
- # The timestamp of the note (e.g. the :updated_at attribute if provided via
+ # The timestamp of the note (e.g. the :created_at or :updated_at attribute if provided via
# API call)
def system_note_timestamp
@system_note_timestamp || Time.now # rubocop:disable Gitlab/ModuleWithInstanceVariables
@@ -36,7 +38,7 @@ module Noteable
end
def supports_resolvable_notes?
- RESOLVABLE_TYPES.include?(base_class_name)
+ self.class.resolvable_types.include?(base_class_name)
end
def supports_discussions?
@@ -131,3 +133,5 @@ module Noteable
)
end
end
+
+Noteable.extend(Noteable::ClassMethods)
diff --git a/app/models/concerns/prometheus_adapter.rb b/app/models/concerns/prometheus_adapter.rb
index 258c819f243..c2542dbe743 100644
--- a/app/models/concerns/prometheus_adapter.rb
+++ b/app/models/concerns/prometheus_adapter.rb
@@ -6,7 +6,6 @@ module PrometheusAdapter
included do
include ReactiveCaching
- self.reactive_cache_key = ->(adapter) { [adapter.class.model_name.singular, adapter.id] }
self.reactive_cache_lease_timeout = 30.seconds
self.reactive_cache_refresh_interval = 30.seconds
self.reactive_cache_lifetime = 1.minute
diff --git a/app/models/concerns/reactive_caching.rb b/app/models/concerns/reactive_caching.rb
index 1e09cd89550..6c3962b4c4f 100644
--- a/app/models/concerns/reactive_caching.rb
+++ b/app/models/concerns/reactive_caching.rb
@@ -10,8 +10,6 @@
# class Foo < ApplicationRecord
# include ReactiveCaching
#
-# self.reactive_cache_key = ->(thing) { ["foo", thing.id] }
-#
# after_save :clear_reactive_cache!
#
# def calculate_reactive_cache
@@ -89,6 +87,8 @@ module ReactiveCaching
class_attribute :reactive_cache_worker_finder
# defaults
+ self.reactive_cache_key = -> (record) { [model_name.singular, record.id] }
+
self.reactive_cache_lease_timeout = 2.minutes
self.reactive_cache_refresh_interval = 1.minute
diff --git a/app/models/concerns/redactable.rb b/app/models/concerns/redactable.rb
index 5ad96d6cc46..53ae300ee2d 100644
--- a/app/models/concerns/redactable.rb
+++ b/app/models/concerns/redactable.rb
@@ -10,7 +10,7 @@
module Redactable
extend ActiveSupport::Concern
- UNSUBSCRIBE_PATTERN = %r{/sent_notifications/\h{32}/unsubscribe}
+ UNSUBSCRIBE_PATTERN = %r{/sent_notifications/\h{32}/unsubscribe}.freeze
class_methods do
def redact_field(field)
diff --git a/app/models/concerns/referable.rb b/app/models/concerns/referable.rb
index 58143a32fdc..4a506146de3 100644
--- a/app/models/concerns/referable.rb
+++ b/app/models/concerns/referable.rb
@@ -73,6 +73,7 @@ module Referable
(?<url>
#{Regexp.escape(Gitlab.config.gitlab.url)}
\/#{Project.reference_pattern}
+ (?:\/\-)?
\/#{Regexp.escape(route)}
\/#{pattern}
(?<path>
diff --git a/app/models/concerns/resolvable_note.rb b/app/models/concerns/resolvable_note.rb
index 16ea330701d..2d2d5fb7168 100644
--- a/app/models/concerns/resolvable_note.rb
+++ b/app/models/concerns/resolvable_note.rb
@@ -12,7 +12,7 @@ module ResolvableNote
validates :resolved_by, presence: true, if: :resolved?
# Keep this scope in sync with `#potentially_resolvable?`
- scope :potentially_resolvable, -> { where(type: RESOLVABLE_TYPES).where(noteable_type: Noteable::RESOLVABLE_TYPES) }
+ scope :potentially_resolvable, -> { where(type: RESOLVABLE_TYPES).where(noteable_type: Noteable.resolvable_types) }
# Keep this scope in sync with `#resolvable?`
scope :resolvable, -> { potentially_resolvable.user }
diff --git a/app/models/concerns/storage/legacy_namespace.rb b/app/models/concerns/storage/legacy_namespace.rb
index 498996f4f80..a15dc19e07a 100644
--- a/app/models/concerns/storage/legacy_namespace.rb
+++ b/app/models/concerns/storage/legacy_namespace.rb
@@ -13,20 +13,20 @@ module Storage
raise Gitlab::UpdatePathError.new("Namespace #{name} (#{id}) cannot be moved because at least one project (e.g. #{proj_with_tags.name} (#{proj_with_tags.id})) has tags in container registry")
end
- parent_was = if parent_changed? && parent_id_was.present?
- Namespace.find(parent_id_was) # raise NotFound early if needed
+ parent_was = if saved_change_to_parent? && parent_id_before_last_save.present?
+ Namespace.find(parent_id_before_last_save) # raise NotFound early if needed
end
move_repositories
- if parent_changed?
+ if saved_change_to_parent?
former_parent_full_path = parent_was&.full_path
parent_full_path = parent&.full_path
Gitlab::UploadsTransfer.new.move_namespace(path, former_parent_full_path, parent_full_path)
Gitlab::PagesTransfer.new.move_namespace(path, former_parent_full_path, parent_full_path)
else
- Gitlab::UploadsTransfer.new.rename_namespace(full_path_was, full_path)
- Gitlab::PagesTransfer.new.rename_namespace(full_path_was, full_path)
+ Gitlab::UploadsTransfer.new.rename_namespace(full_path_before_last_save, full_path)
+ Gitlab::PagesTransfer.new.rename_namespace(full_path_before_last_save, full_path)
end
# If repositories moved successfully we need to
@@ -38,7 +38,7 @@ module Storage
write_projects_repository_config
rescue => e
# Raise if development/test environment, else just notify Sentry
- Gitlab::Sentry.track_exception(e, extra: { full_path_was: full_path_was, full_path: full_path, action: 'move_dir' })
+ Gitlab::Sentry.track_exception(e, extra: { full_path_before_last_save: full_path_before_last_save, full_path: full_path, action: 'move_dir' })
end
true # false would cancel later callbacks but not rollback
@@ -57,14 +57,14 @@ module Storage
# Move the namespace directory in all storages used by member projects
repository_storages.each do |repository_storage|
# Ensure old directory exists before moving it
- gitlab_shell.add_namespace(repository_storage, full_path_was)
+ gitlab_shell.add_namespace(repository_storage, full_path_before_last_save)
# Ensure new directory exists before moving it (if there's a parent)
gitlab_shell.add_namespace(repository_storage, parent.full_path) if parent
- unless gitlab_shell.mv_namespace(repository_storage, full_path_was, full_path)
+ unless gitlab_shell.mv_namespace(repository_storage, full_path_before_last_save, full_path)
- Rails.logger.error "Exception moving path #{repository_storage} from #{full_path_was} to #{full_path}"
+ Rails.logger.error "Exception moving path #{repository_storage} from #{full_path_before_last_save} to #{full_path}"
# if we cannot move namespace directory we should rollback
# db changes in order to prevent out of sync between db and fs
@@ -104,11 +104,5 @@ module Storage
end
end
end
-
- def remove_legacy_exports!
- legacy_export_path = File.join(Gitlab::ImportExport.storage_path, full_path_was)
-
- FileUtils.rm_rf(legacy_export_path)
- end
end
end
diff --git a/app/models/concerns/taskable.rb b/app/models/concerns/taskable.rb
index f147ce8ad6b..b42adad94ba 100644
--- a/app/models/concerns/taskable.rb
+++ b/app/models/concerns/taskable.rb
@@ -19,7 +19,7 @@ module Taskable
\s+ # whitespace prefix has to be always presented for a list item
(\[\s\]|\[[xX]\]) # checkbox
(\s.+) # followed by whitespace and some text.
- }x
+ }x.freeze
def self.get_tasks(content)
content.to_s.scan(ITEM_PATTERN).map do |checkbox, label|
@@ -75,4 +75,11 @@ module Taskable
def task_status_short
task_status(short: true)
end
+
+ def task_completion_status
+ @task_completion_status ||= {
+ count: tasks.summary.item_count,
+ completed_count: tasks.summary.complete_count
+ }
+ end
end
diff --git a/app/models/concerns/update_project_statistics.rb b/app/models/concerns/update_project_statistics.rb
new file mode 100644
index 00000000000..1f881249322
--- /dev/null
+++ b/app/models/concerns/update_project_statistics.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+# This module is providing helpers for updating `ProjectStatistics` with `after_save` and `before_destroy` hooks.
+#
+# It deals with `ProjectStatistics.increment_statistic` making sure not to update statistics on a cascade delete from the
+# project, and keeping track of value deltas on each save. It updates the DB only when a change is needed.
+#
+# Example:
+#
+# module Ci
+# class JobArtifact < ApplicationRecord
+# include UpdateProjectStatistics
+#
+# update_project_statistics project_statistics_name: :build_artifacts_size
+# end
+# end
+#
+# Expectation:
+#
+# - `statistic_attribute` must be an ActiveRecord attribute
+# - The model must implement `project` and `project_id`. i.e. direct Project relationship or delegation
+#
+module UpdateProjectStatistics
+ extend ActiveSupport::Concern
+
+ class_methods do
+ attr_reader :project_statistics_name, :statistic_attribute
+
+ # Configure the model to update `project_statistics_name` on ProjectStatistics,
+ # when `statistic_attribute` changes
+ #
+ # - project_statistics_name: A column of `ProjectStatistics` to update
+ # - statistic_attribute: An attribute of the current model, default to `size`
+ #
+ def update_project_statistics(project_statistics_name:, statistic_attribute: :size)
+ @project_statistics_name = project_statistics_name
+ @statistic_attribute = statistic_attribute
+
+ after_save(:update_project_statistics_after_save, if: :update_project_statistics_attribute_changed?)
+ after_destroy(:update_project_statistics_after_destroy, unless: :project_destroyed?)
+ end
+
+ private :update_project_statistics
+ end
+
+ included do
+ private
+
+ def update_project_statistics_after_save
+ attr = self.class.statistic_attribute
+ delta = read_attribute(attr).to_i - attribute_before_last_save(attr).to_i
+
+ update_project_statistics(delta)
+ end
+
+ def update_project_statistics_attribute_changed?
+ saved_change_to_attribute?(self.class.statistic_attribute)
+ end
+
+ def update_project_statistics_after_destroy
+ update_project_statistics(-read_attribute(self.class.statistic_attribute).to_i)
+ end
+
+ def project_destroyed?
+ project.pending_delete?
+ end
+
+ def update_project_statistics(delta)
+ ProjectStatistics.increment_statistic(project_id, self.class.project_statistics_name, delta)
+ end
+ end
+end
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index d847a0a11e4..92c7311014a 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -47,6 +47,12 @@ class Deployment < ApplicationRecord
Deployments::SuccessWorker.perform_async(id)
end
end
+
+ after_transition any => [:success, :failed, :canceled] do |deployment|
+ deployment.run_after_commit do
+ Deployments::FinishedWorker.perform_async(id)
+ end
+ end
end
enum status: {
@@ -79,7 +85,16 @@ class Deployment < ApplicationRecord
end
def cluster
- project.deployment_platform(environment: environment.name)&.cluster
+ platform = project.deployment_platform(environment: environment.name)
+
+ if platform.present? && platform.respond_to?(:cluster)
+ platform.cluster
+ end
+ end
+
+ def execute_hooks
+ deployment_data = Gitlab::DataBuilder::Deployment.build(self)
+ project.execute_services(deployment_data, :deployment_hooks)
end
def last?
diff --git a/app/models/diff_note.rb b/app/models/diff_note.rb
index feabea9b8ba..f75c32633b1 100644
--- a/app/models/diff_note.rb
+++ b/app/models/diff_note.rb
@@ -15,7 +15,9 @@ class DiffNote < Note
validates :original_position, presence: true
validates :position, presence: true
validates :line_code, presence: true, line_code: true, if: :on_text?
- validates :noteable_type, inclusion: { in: noteable_types }
+ # We need to evaluate the `noteable` types when running the validation since
+ # EE might have added a type when the module was prepended
+ validates :noteable_type, inclusion: { in: -> (_note) { noteable_types } }
validate :positions_complete
validate :verify_supported
validate :diff_refs_match_commit, if: :for_commit?
@@ -44,7 +46,7 @@ class DiffNote < Note
# Returns the diff file from `position`
def latest_diff_file
strong_memoize(:latest_diff_file) do
- position.diff_file(project.repository)
+ position.diff_file(repository)
end
end
@@ -75,7 +77,7 @@ class DiffNote < Note
end
def supports_suggestion?
- return false unless noteable.supports_suggestion? && on_text?
+ return false unless noteable&.supports_suggestion? && on_text?
# We don't want to trigger side-effects of `diff_file` call.
return false unless file = latest_diff_file
return false unless line = file.line_for_position(self.position)
@@ -88,7 +90,7 @@ class DiffNote < Note
end
def banzai_render_context(field)
- super.merge(project: project, suggestions_filter_enabled: supports_suggestion?)
+ super.merge(suggestions_filter_enabled: true)
end
private
@@ -111,7 +113,7 @@ class DiffNote < Note
if note_diff_file
diff = Gitlab::Git::Diff.new(note_diff_file.to_hash)
Gitlab::Diff::File.new(diff,
- repository: project.repository,
+ repository: repository,
diff_refs: original_position.diff_refs)
elsif created_at_diff?(noteable.diff_refs)
# We're able to use the already persisted diffs (Postgres) if we're
@@ -122,7 +124,7 @@ class DiffNote < Note
# `Diff::FileCollection::MergeRequestDiff`.
noteable.diffs(original_position.diff_options).diff_files.first
else
- original_position.diff_file(self.project.repository)
+ original_position.diff_file(repository)
end
# Since persisted diff files already have its content "unfolded"
@@ -137,7 +139,7 @@ class DiffNote < Note
end
def set_line_code
- self.line_code = self.position.line_code(self.project.repository)
+ self.line_code = self.position.line_code(repository)
end
def verify_supported
@@ -171,6 +173,10 @@ class DiffNote < Note
shas << self.position.head_sha
end
- project.repository.keep_around(*shas)
+ repository.keep_around(*shas)
+ end
+
+ def repository
+ noteable.respond_to?(:repository) ? noteable.repository : project.repository
end
end
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 69224635e34..aff20dae09b 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -3,8 +3,8 @@
class Environment < ApplicationRecord
include Gitlab::Utils::StrongMemoize
# Used to generate random suffixes for the slug
- LETTERS = 'a'..'z'
- NUMBERS = '0'..'9'
+ LETTERS = ('a'..'z').freeze
+ NUMBERS = ('0'..'9').freeze
SUFFIX_CHARS = LETTERS.to_a + NUMBERS.to_a
belongs_to :project, required: true
@@ -155,11 +155,11 @@ class Environment < ApplicationRecord
end
def has_terminals?
- project.deployment_platform.present? && available? && last_deployment.present?
+ deployment_platform.present? && available? && last_deployment.present?
end
def terminals
- project.deployment_platform.terminals(self) if has_terminals?
+ deployment_platform.terminals(self) if has_terminals?
end
def has_metrics?
diff --git a/app/models/error_tracking/project_error_tracking_setting.rb b/app/models/error_tracking/project_error_tracking_setting.rb
index 72270ee8b4f..0b4fef5eac1 100644
--- a/app/models/error_tracking/project_error_tracking_setting.rb
+++ b/app/models/error_tracking/project_error_tracking_setting.rb
@@ -16,7 +16,7 @@ module ErrorTracking
(?<project>[^/]+)/*
)?
\z
- }x
+ }x.freeze
self.reactive_cache_key = ->(setting) { [setting.class.model_name.singular, setting.project_id] }
diff --git a/app/models/event.rb b/app/models/event.rb
index 593acf5edfe..738080eb584 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -68,7 +68,7 @@ class Event < ApplicationRecord
# Callbacks
after_create :reset_project_activity
- after_create :set_last_repository_updated_at, if: :push?
+ after_create :set_last_repository_updated_at, if: :push_action?
after_create :track_user_interacted_projects
# Scopes
@@ -138,11 +138,11 @@ class Event < ApplicationRecord
# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/PerceivedComplexity
def visible_to_user?(user = nil)
- if push? || commit_note?
+ if push_action? || commit_note?
Ability.allowed?(user, :download_code, project)
elsif membership_changed?
Ability.allowed?(user, :read_project, project)
- elsif created_project?
+ elsif created_project_action?
Ability.allowed?(user, :read_project, project)
elsif issue? || issue_note?
Ability.allowed?(user, :read_issue, note? ? note_target : target)
@@ -173,56 +173,56 @@ class Event < ApplicationRecord
target.try(:title)
end
- def created?
+ def created_action?
action == CREATED
end
- def push?
+ def push_action?
false
end
- def merged?
+ def merged_action?
action == MERGED
end
- def closed?
+ def closed_action?
action == CLOSED
end
- def reopened?
+ def reopened_action?
action == REOPENED
end
- def joined?
+ def joined_action?
action == JOINED
end
- def left?
+ def left_action?
action == LEFT
end
- def expired?
+ def expired_action?
action == EXPIRED
end
- def destroyed?
+ def destroyed_action?
action == DESTROYED
end
- def commented?
+ def commented_action?
action == COMMENTED
end
def membership_changed?
- joined? || left? || expired?
+ joined_action? || left_action? || expired_action?
end
- def created_project?
- created? && !target && target_type.nil?
+ def created_project_action?
+ created_action? && !target && target_type.nil?
end
def created_target?
- created? && target
+ created_action? && target
end
def milestone?
@@ -258,23 +258,23 @@ class Event < ApplicationRecord
end
def action_name
- if push?
+ if push_action?
push_action_name
- elsif closed?
+ elsif closed_action?
"closed"
- elsif merged?
+ elsif merged_action?
"accepted"
- elsif joined?
+ elsif joined_action?
'joined'
- elsif left?
+ elsif left_action?
'left'
- elsif expired?
+ elsif expired_action?
'removed due to membership expiration from'
- elsif destroyed?
+ elsif destroyed_action?
'destroyed'
- elsif commented?
+ elsif commented_action?
"commented on"
- elsif created_project?
+ elsif created_project_action?
created_project_action_name
else
"opened"
@@ -337,7 +337,7 @@ class Event < ApplicationRecord
end
def body?
- if push?
+ if push_action?
push_with_commits?
elsif note?
true
diff --git a/app/models/global_label.rb b/app/models/global_label.rb
index 572cb12b26a..7c020dd3b3d 100644
--- a/app/models/global_label.rb
+++ b/app/models/global_label.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class GlobalLabel
+ include Presentable
+
attr_accessor :title, :labels
alias_attribute :name, :title
@@ -23,4 +25,8 @@ class GlobalLabel
@labels = labels
@first_label = labels.find { |lbl| lbl.description.present? } || labels.first
end
+
+ def present(attributes)
+ super(attributes.merge(presenter_class: ::LabelPresenter))
+ end
end
diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb
index fd17745b035..59f5a7703e2 100644
--- a/app/models/global_milestone.rb
+++ b/app/models/global_milestone.rb
@@ -8,7 +8,9 @@ class GlobalMilestone
attr_reader :milestone
alias_attribute :name, :title
- delegate :title, :state, :due_date, :start_date, :participants, :project, :group, :expires_at, :closed?, :iid, :group_milestone?, :safe_title, :milestoneish_id, to: :milestone
+ delegate :title, :state, :due_date, :start_date, :participants, :project,
+ :group, :expires_at, :closed?, :iid, :group_milestone?, :safe_title,
+ :milestoneish_id, :parent, to: :milestone
def to_hash
{
diff --git a/app/models/group.rb b/app/models/group.rb
index 8bc9b75f0a9..dbec211935d 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -61,7 +61,7 @@ class Group < Namespace
after_create :post_create_hook
after_destroy :post_destroy_hook
after_save :update_two_factor_requirement
- after_update :path_changed_hook, if: :path_changed?
+ after_update :path_changed_hook, if: :saved_change_to_path?
class << self
def sort_by_attribute(method)
@@ -126,10 +126,20 @@ class Group < Namespace
# Overrides notification_settings has_many association
# This allows to apply notification settings from parent groups
# to child groups and projects.
- def notification_settings
+ def notification_settings(hierarchy_order: nil)
source_type = self.class.base_class.name
+ settings = NotificationSetting.where(source_type: source_type, source_id: self_and_ancestors_ids)
- NotificationSetting.where(source_type: source_type, source_id: self_and_ancestors_ids)
+ return settings unless hierarchy_order && self_and_ancestors_ids.length > 1
+
+ settings
+ .joins("LEFT JOIN (#{self_and_ancestors(hierarchy_order: hierarchy_order).to_sql}) AS ordered_groups ON notification_settings.source_id = ordered_groups.id")
+ .select('notification_settings.*, ordered_groups.depth AS depth')
+ .order("ordered_groups.depth #{hierarchy_order}")
+ end
+
+ def notification_settings_for(user, hierarchy_order: nil)
+ notification_settings(hierarchy_order: hierarchy_order).where(user: user)
end
def to_reference(_from = nil, full: nil)
@@ -411,9 +421,9 @@ class Group < Namespace
private
def update_two_factor_requirement
- return unless require_two_factor_authentication_changed? || two_factor_grace_period_changed?
+ return unless saved_change_to_require_two_factor_authentication? || saved_change_to_two_factor_grace_period?
- users.find_each(&:update_two_factor_requirement)
+ members_with_descendants.find_each(&:update_two_factor_requirement)
end
def path_changed_hook
diff --git a/app/models/identity.rb b/app/models/identity.rb
index 8322b9bf35f..1cbd50205ed 100644
--- a/app/models/identity.rb
+++ b/app/models/identity.rb
@@ -13,6 +13,7 @@ class Identity < ApplicationRecord
before_save :ensure_normalized_extern_uid, if: :extern_uid_changed?
after_destroy :clear_user_synced_attributes, if: :user_synced_attributes_metadata_from_provider?
+ scope :for_user, ->(user) { where(user: user) }
scope :with_provider, ->(provider) { where(provider: provider) }
scope :with_extern_uid, ->(provider, extern_uid) do
iwhere(extern_uid: normalize_uid(provider, extern_uid)).with_provider(provider)
diff --git a/app/models/internal_id.rb b/app/models/internal_id.rb
index 401b94d36e5..237401899db 100644
--- a/app/models/internal_id.rb
+++ b/app/models/internal_id.rb
@@ -87,12 +87,16 @@ class InternalId < ApplicationRecord
end
def available?
- @available_flag ||= ActiveRecord::Migrator.current_version >= REQUIRED_SCHEMA_VERSION # rubocop:disable Gitlab/PredicateMemoization
+ return true unless Rails.env.test?
+
+ Gitlab::SafeRequestStore.fetch(:internal_ids_available_flag) do
+ ActiveRecord::Migrator.current_version >= REQUIRED_SCHEMA_VERSION
+ end
end
# Flushes cached information about schema
def reset_column_information
- @available_flag = nil
+ Gitlab::SafeRequestStore[:internal_ids_available_flag] = nil
super
end
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index eb5544f2a12..6da6fbe55cb 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -58,6 +58,7 @@ class Issue < ApplicationRecord
scope :order_due_date_asc, -> { reorder('issues.due_date IS NULL, issues.due_date ASC') }
scope :order_due_date_desc, -> { reorder('issues.due_date IS NULL, issues.due_date DESC') }
scope :order_closest_future_date, -> { reorder('CASE WHEN issues.due_date >= CURRENT_DATE THEN 0 ELSE 1 END ASC, ABS(CURRENT_DATE - issues.due_date) ASC') }
+ scope :order_relative_position_asc, -> { reorder(::Gitlab::Database.nulls_last_order('relative_position', 'ASC')) }
scope :preload_associations, -> { preload(:labels, project: :namespace) }
scope :with_api_entity_associations, -> { preload(:timelogs, :assignees, :author, :notes, :labels, project: [:route, { namespace: :route }] ) }
@@ -130,9 +131,10 @@ class Issue < ApplicationRecord
def self.sort_by_attribute(method, excluded_labels: [])
case method.to_s
when 'closest_future_date' then order_closest_future_date
- when 'due_date' then order_due_date_asc
- when 'due_date_asc' then order_due_date_asc
- when 'due_date_desc' then order_due_date_desc
+ when 'due_date' then order_due_date_asc
+ when 'due_date_asc' then order_due_date_asc
+ when 'due_date_desc' then order_due_date_desc
+ when 'relative_position' then order_relative_position_asc
else
super
end
diff --git a/app/models/key.rb b/app/models/key.rb
index b097be8cc89..8aa25924c28 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -59,6 +59,11 @@ class Key < ApplicationRecord
"key-#{id}"
end
+ # EE overrides this
+ def can_delete?
+ true
+ end
+
# rubocop: disable CodeReuse/ServiceClass
def update_last_used_at
Keys::LastUsedService.new(self).execute
diff --git a/app/models/label.rb b/app/models/label.rb
index c7fff0d393e..b83e0862bab 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -8,11 +8,11 @@ class Label < ApplicationRecord
include OptionallySearch
include Sortable
include FromUnion
+ include Presentable
cache_markdown_field :description, pipeline: :single_line
DEFAULT_COLOR = '#428BCA'
- NONE = 'no label'
default_value_for :color, DEFAULT_COLOR
@@ -233,6 +233,10 @@ class Label < ApplicationRecord
attributes
end
+ def present(attributes)
+ super(attributes.merge(presenter_class: ::LabelPresenter))
+ end
+
private
def issues_count(user, params = {})
diff --git a/app/models/lfs_object.rb b/app/models/lfs_object.rb
index e1aac691a64..5245dbc8d15 100644
--- a/app/models/lfs_object.rb
+++ b/app/models/lfs_object.rb
@@ -13,7 +13,7 @@ class LfsObject < ApplicationRecord
mount_uploader :file, LfsObjectUploader
- after_save :update_file_store, if: :file_changed?
+ after_save :update_file_store, if: :saved_change_to_file?
def update_file_store
# The file.object_store is set during `uploader.store!`
diff --git a/app/models/member.rb b/app/models/member.rb
index 8a06bff51b5..c7583434148 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -80,6 +80,8 @@ class Member < ApplicationRecord
scope :owners_and_masters, -> { owners_and_maintainers } # @deprecated
scope :with_user, -> (user) { where(user: user) }
+ scope :with_source_id, ->(source_id) { where(source_id: source_id) }
+
scope :order_name_asc, -> { left_join_users.reorder(Gitlab::Database.nulls_last_order('users.name', 'ASC')) }
scope :order_name_desc, -> { left_join_users.reorder(Gitlab::Database.nulls_last_order('users.name', 'DESC')) }
scope :order_recent_sign_in, -> { left_join_users.reorder(Gitlab::Database.nulls_last_order('users.last_sign_in_at', 'DESC')) }
@@ -446,10 +448,10 @@ class Member < ApplicationRecord
end
def higher_access_level_than_group
- if highest_group_member && highest_group_member.access_level >= access_level
+ if highest_group_member && highest_group_member.access_level > access_level
error_parameters = { access: highest_group_member.human_access, group_name: highest_group_member.group.name }
- errors.add(:access_level, s_("should be higher than %{access} inherited membership from group %{group_name}") % error_parameters)
+ errors.add(:access_level, s_("should be greater than or equal to %{access} inherited membership from group %{group_name}") % error_parameters)
end
end
end
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
index 510f856087d..4cba69069bb 100644
--- a/app/models/members/group_member.rb
+++ b/app/models/members/group_member.rb
@@ -12,7 +12,7 @@ class GroupMember < Member
validates :source_type, format: { with: /\ANamespace\z/ }
default_scope { where(source_type: SOURCE_TYPE) }
- scope :in_groups, ->(groups) { where(source_id: groups.select(:id)) }
+ scope :of_groups, ->(groups) { where(source_id: groups.select(:id)) }
scope :count_users_by_group_id, -> { joins(:user).group(:source_id).count }
@@ -55,7 +55,7 @@ class GroupMember < Member
end
def post_update_hook
- if access_level_changed?
+ if saved_change_to_access_level?
run_after_commit { notification_service.update_group_member(self) }
end
diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb
index 5372c6084f4..c64e2669b6a 100644
--- a/app/models/members/project_member.rb
+++ b/app/models/members/project_member.rb
@@ -111,7 +111,7 @@ class ProjectMember < Member
end
def post_update_hook
- if access_level_changed?
+ if saved_change_to_access_level?
run_after_commit { notification_service.update_project_member(self) }
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 251a7ff41f5..f07636e8f77 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -66,7 +66,7 @@ class MergeRequest < ApplicationRecord
dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
has_many :cached_closes_issues, through: :merge_requests_closing_issues, source: :issue
- has_many :merge_request_pipelines, foreign_key: 'merge_request_id', class_name: 'Ci::Pipeline'
+ has_many :pipelines_for_merge_request, foreign_key: 'merge_request_id', class_name: 'Ci::Pipeline'
has_many :suggestions, through: :notes
has_many :merge_request_assignees
@@ -165,7 +165,7 @@ class MergeRequest < ApplicationRecord
validates :source_branch, presence: true
validates :target_project, presence: true
validates :target_branch, presence: true
- validates :merge_user, presence: true, if: :merge_when_pipeline_succeeds?, unless: :importing?
+ validates :merge_user, presence: true, if: :auto_merge_enabled?, unless: :importing?
validate :validate_branches, unless: [:allow_broken, :importing?, :closed_without_fork?]
validate :validate_fork, unless: :closed_without_fork?
validate :validate_target_project, on: :create
@@ -196,6 +196,7 @@ class MergeRequest < ApplicationRecord
alias_attribute :project, :target_project
alias_attribute :project_id, :target_project_id
+ alias_attribute :auto_merge_enabled, :merge_when_pipeline_succeeds
def self.reference_prefix
'!'
@@ -391,7 +392,7 @@ class MergeRequest < ApplicationRecord
def merge_participants
participants = [author]
- if merge_when_pipeline_succeeds? && !participants.include?(merge_user)
+ if auto_merge_enabled? && !participants.include?(merge_user)
participants << merge_user
end
@@ -581,11 +582,15 @@ class MergeRequest < ApplicationRecord
end
def validate_branches
+ return unless target_project && source_project
+
if target_project == source_project && target_branch == source_branch
errors.add :branch_conflict, "You can't use same project/branch for source and target"
return
end
+ [:source_branch, :target_branch].each { |attr| validate_branch_name(attr) }
+
if opened?
similar_mrs = target_project
.merge_requests
@@ -606,6 +611,16 @@ class MergeRequest < ApplicationRecord
end
end
+ def validate_branch_name(attr)
+ return unless changes_include?(attr)
+
+ branch = read_attribute(attr)
+
+ return unless branch
+
+ errors.add(attr) unless Gitlab::GitRefValidator.validate_merge_request_branch(branch)
+ end
+
def validate_target_project
return true if target_project.merge_requests_enabled?
@@ -653,7 +668,7 @@ class MergeRequest < ApplicationRecord
# n+1: https://gitlab.com/gitlab-org/gitlab-ce/issues/37435
Gitlab::GitalyClient.allow_n_plus_1_calls do
- merge_request_diffs.create
+ merge_request_diffs.create!
reload_merge_request_diff
end
end
@@ -698,7 +713,7 @@ class MergeRequest < ApplicationRecord
end
def reload_diff_if_branch_changed
- if (source_branch_changed? || target_branch_changed?) &&
+ if (saved_change_to_source_branch? || saved_change_to_target_branch?) &&
(source_branch_head && target_branch_head)
reload_diff
end
@@ -780,7 +795,7 @@ class MergeRequest < ApplicationRecord
project.ff_merge_must_be_possible? && !ff_merge_possible?
end
- def can_cancel_merge_when_pipeline_succeeds?(current_user)
+ def can_cancel_auto_merge?(current_user)
can_be_merged_by?(current_user) || self.author == current_user
end
@@ -799,6 +814,16 @@ class MergeRequest < ApplicationRecord
Gitlab::Utils.to_boolean(merge_params['force_remove_source_branch'])
end
+ def auto_merge_strategy
+ return unless auto_merge_enabled?
+
+ merge_params['auto_merge_strategy'] || AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS
+ end
+
+ def auto_merge_strategy=(strategy)
+ merge_params['auto_merge_strategy'] = strategy
+ end
+
def remove_source_branch?
should_remove_source_branch? || force_remove_source_branch?
end
@@ -971,20 +996,6 @@ class MergeRequest < ApplicationRecord
end
end
- def reset_merge_when_pipeline_succeeds
- return unless merge_when_pipeline_succeeds?
-
- self.merge_when_pipeline_succeeds = false
- self.merge_user = nil
- if merge_params
- merge_params.delete('should_remove_source_branch')
- merge_params.delete('commit_message')
- merge_params.delete('squash_commit_message')
- end
-
- self.save
- end
-
# Return array of possible target branches
# depends on target project of MR
def target_branches
@@ -1054,6 +1065,16 @@ class MergeRequest < ApplicationRecord
@environments[current_user]
end
+ ##
+ # This method is for looking for active environments which created via pipelines for merge requests.
+ # Since deployments run on a merge request ref (e.g. `refs/merge-requests/:iid/head`),
+ # we cannot look up environments with source branch name.
+ def environments
+ return Environment.none unless actual_head_pipeline&.triggered_by_merge_request?
+
+ actual_head_pipeline.environments
+ end
+
def state_human_name
if merged?
"Merged"
@@ -1147,10 +1168,6 @@ class MergeRequest < ApplicationRecord
end
end
- def merge_request_pipeline_exists?
- merge_request_pipelines.exists?(sha: diff_head_sha)
- end
-
def has_test_reports?
actual_head_pipeline&.has_reports?(Ci::JobArtifact.test_reports)
end
@@ -1369,12 +1386,12 @@ class MergeRequest < ApplicationRecord
source_project.repository.squash_in_progress?(id)
end
- private
-
def find_actual_head_pipeline
all_pipelines.for_sha_or_source_sha(diff_head_sha).first
end
+ private
+
def source_project_variables
Gitlab::Ci::Variables::Collection.new.tap do |variables|
break variables unless source_project
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index 0b787217410..f45bd0e03de 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -51,6 +51,10 @@ class MergeRequestDiff < ApplicationRecord
joins(:merge_request_diff_commits).where(merge_request_diff_commits: { sha: sha }).reorder(nil)
end
+ scope :by_project_id, -> (project_id) do
+ joins(:merge_request).where(merge_requests: { target_project_id: project_id })
+ end
+
scope :recent, -> { order(id: :desc).limit(100) }
scope :files_in_database, -> { where(stored_externally: [false, nil]) }
@@ -134,7 +138,7 @@ class MergeRequestDiff < ApplicationRecord
# It allows you to override variables like head_commit_sha before getting diff.
after_create :save_git_content, unless: :importing?
- after_save :update_external_diff_store, if: -> { !importing? && external_diff_changed? }
+ after_save :update_external_diff_store, if: -> { !importing? && saved_change_to_external_diff? }
def self.find_by_diff_refs(diff_refs)
find_by(start_commit_sha: diff_refs.start_sha, head_commit_sha: diff_refs.head_sha, base_commit_sha: diff_refs.base_sha)
@@ -154,7 +158,14 @@ class MergeRequestDiff < ApplicationRecord
ensure_commit_shas
save_commits
save_diffs
+
+ # Another set of `after_save` hooks will be called here when we update the record
save
+ # We need to reset so that dirty tracking is reset when running the original set
+ # of `after_save` hooks that come after this `after_create` hook. Otherwise, the
+ # hooks that run when an attribute was changed are run twice.
+ reset
+
keep_around_commits
end
@@ -348,7 +359,7 @@ class MergeRequestDiff < ApplicationRecord
has_attribute?(:external_diff_store)
end
- def external_diff_changed?
+ def saved_change_to_external_diff?
super if has_attribute?(:external_diff)
end
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 787600569fa..37c129e843a 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -58,6 +58,7 @@ class Milestone < ApplicationRecord
validate :uniqueness_of_title, if: :title_changed?
validate :milestone_type_check
validate :start_date_should_be_less_than_due_date, if: proc { |m| m.start_date.present? && m.due_date.present? }
+ validate :dates_within_4_digits
strip_attributes :title
@@ -326,6 +327,16 @@ class Milestone < ApplicationRecord
end
end
+ def dates_within_4_digits
+ if start_date && start_date > Date.new(9999, 12, 31)
+ errors.add(:start_date, _("date must not be after 9999-12-31"))
+ end
+
+ if due_date && due_date > Date.new(9999, 12, 31)
+ errors.add(:due_date, _("date must not be after 9999-12-31"))
+ end
+ end
+
def issues_finder_params
{ project_id: project_id }
end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index dea34e812ca..3c270c7396a 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -50,17 +50,20 @@ class Namespace < ApplicationRecord
validate :nesting_level_allowed
+ validates_associated :runners
+
delegate :name, to: :owner, allow_nil: true, prefix: true
+ delegate :avatar_url, to: :owner, allow_nil: true
after_commit :refresh_access_of_projects_invited_groups, on: :update, if: -> { previous_changes.key?('share_with_group_lock') }
before_create :sync_share_with_group_lock_with_parent
before_update :sync_share_with_group_lock_with_parent, if: :parent_changed?
- after_update :force_share_with_group_lock_on_descendants, if: -> { share_with_group_lock_changed? && share_with_group_lock? }
+ after_update :force_share_with_group_lock_on_descendants, if: -> { saved_change_to_share_with_group_lock? && share_with_group_lock? }
# Legacy Storage specific hooks
- after_update :move_dir, if: :path_or_parent_changed?
+ after_update :move_dir, if: :saved_change_to_path_or_parent?
before_destroy(prepend: true) { prepare_for_destroy }
after_destroy :rm_dir
@@ -73,8 +76,10 @@ class Namespace < ApplicationRecord
'namespaces.*',
'COALESCE(SUM(ps.storage_size), 0) AS storage_size',
'COALESCE(SUM(ps.repository_size), 0) AS repository_size',
+ 'COALESCE(SUM(ps.wiki_size), 0) AS wiki_size',
'COALESCE(SUM(ps.lfs_objects_size), 0) AS lfs_objects_size',
- 'COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size'
+ 'COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size',
+ 'COALESCE(SUM(ps.packages_size), 0) AS packages_size'
)
end
@@ -141,7 +146,7 @@ class Namespace < ApplicationRecord
def send_update_instructions
projects.each do |project|
- project.send_move_instructions("#{full_path_was}/#{project.path}")
+ project.send_move_instructions("#{full_path_before_last_save}/#{project.path}")
end
end
@@ -149,6 +154,10 @@ class Namespace < ApplicationRecord
type == 'Group' ? 'group' : 'user'
end
+ def user?
+ kind == 'user'
+ end
+
def find_fork_of(project)
return unless project.fork_network
@@ -197,12 +206,12 @@ class Namespace < ApplicationRecord
.ancestors(upto: top, hierarchy_order: hierarchy_order)
end
- def self_and_ancestors
+ def self_and_ancestors(hierarchy_order: nil)
return self.class.where(id: id) unless parent_id
Gitlab::ObjectHierarchy
.new(self.class.where(id: id))
- .base_and_ancestors
+ .base_and_ancestors(hierarchy_order: hierarchy_order)
end
# Returns all the descendants of the current namespace.
@@ -222,10 +231,6 @@ class Namespace < ApplicationRecord
[owner_id]
end
- def parent_changed?
- parent_id_changed?
- end
-
# Includes projects from this namespace and projects from all subgroups
# that belongs to this namespace
def all_projects
@@ -255,12 +260,12 @@ class Namespace < ApplicationRecord
false
end
- def full_path_was
- if parent_id_was.nil?
- path_was
+ def full_path_before_last_save
+ if parent_id_before_last_save.nil?
+ path_before_last_save
else
- previous_parent = Group.find_by(id: parent_id_was)
- previous_parent.full_path + '/' + path_was
+ previous_parent = Group.find_by(id: parent_id_before_last_save)
+ previous_parent.full_path + '/' + path_before_last_save
end
end
@@ -286,8 +291,16 @@ class Namespace < ApplicationRecord
private
- def path_or_parent_changed?
- path_changed? || parent_changed?
+ def parent_changed?
+ parent_id_changed?
+ end
+
+ def saved_change_to_parent?
+ saved_change_to_parent_id?
+ end
+
+ def saved_change_to_path_or_parent?
+ saved_change_to_path? || saved_change_to_parent_id?
end
def refresh_access_of_projects_invited_groups
diff --git a/app/models/note_diff_file.rb b/app/models/note_diff_file.rb
index 9afb94c869a..fcc9e2b3fd8 100644
--- a/app/models/note_diff_file.rb
+++ b/app/models/note_diff_file.rb
@@ -7,6 +7,10 @@ class NoteDiffFile < ApplicationRecord
joins(:diff_note).where("resolved_at IS NULL OR noteable_type = 'Commit'")
end
+ scope :referencing_sha, -> (oids, project_id:) do
+ joins(:diff_note).where(notes: { project_id: project_id, commit_id: oids })
+ end
+
delegate :original_position, :project, to: :diff_note
belongs_to :diff_note, inverse_of: :note_diff_file
diff --git a/app/models/notification_recipient.rb b/app/models/notification_recipient.rb
index 793cce191fa..a7f73c0f29c 100644
--- a/app/models/notification_recipient.rb
+++ b/app/models/notification_recipient.rb
@@ -47,14 +47,14 @@ class NotificationRecipient
def suitable_notification_level?
case notification_level
- when :disabled, nil
- false
- when :custom
- custom_enabled? || %i[participating mention].include?(@type)
- when :watch, :participating
- !action_excluded?
when :mention
@type == :mention
+ when :participating
+ @custom_action == :failed_pipeline || %i[participating mention].include?(@type)
+ when :custom
+ custom_enabled? || %i[participating mention].include?(@type)
+ when :watch
+ !excluded_watcher_action?
else
false
end
@@ -100,22 +100,13 @@ class NotificationRecipient
end
end
- def action_excluded?
- excluded_watcher_action? || excluded_participating_action?
- end
-
def excluded_watcher_action?
- return false unless @custom_action && notification_level == :watch
+ return false unless @type == :watch
+ return false unless @custom_action
NotificationSetting::EXCLUDED_WATCHER_EVENTS.include?(@custom_action)
end
- def excluded_participating_action?
- return false unless @custom_action && notification_level == :participating
-
- NotificationSetting::EXCLUDED_PARTICIPATING_EVENTS.include?(@custom_action)
- end
-
private
def read_ability
@@ -123,15 +114,19 @@ class NotificationRecipient
return @read_ability if instance_variable_defined?(:@read_ability)
@read_ability =
- case @target
- when Issuable
- :"read_#{@target.to_ability_name}"
- when Ci::Pipeline
+ if @target.is_a?(Ci::Pipeline)
:read_build # We have build trace in pipeline emails
- when ActiveRecord::Base
- :"read_#{@target.class.model_name.name.underscore}"
- else
- nil
+ elsif default_ability_for_target
+ :"read_#{default_ability_for_target}"
+ end
+ end
+
+ def default_ability_for_target
+ @default_ability_for_target ||=
+ if @target.respond_to?(:to_ability_name)
+ @target.to_ability_name
+ elsif @target.class.respond_to?(:model_name)
+ @target.class.model_name.name.underscore
end
end
@@ -146,7 +141,7 @@ class NotificationRecipient
return project_setting unless project_setting.nil? || project_setting.global?
- group_setting = closest_non_global_group_notification_settting
+ group_setting = closest_non_global_group_notification_setting
return group_setting unless group_setting.nil?
@@ -154,25 +149,13 @@ class NotificationRecipient
end
# Returns the notification_setting of the lowest group in hierarchy with non global level
- def closest_non_global_group_notification_settting
+ def closest_non_global_group_notification_setting
return unless @group
- return if indexed_group_notification_settings.empty?
- notification_setting = nil
-
- @group.self_and_ancestors_ids.each do |id|
- notification_setting = indexed_group_notification_settings[id]
- break if notification_setting
- end
-
- notification_setting
- end
-
- def indexed_group_notification_settings
- strong_memoize(:indexed_group_notification_settings) do
- @group.notification_settings.where(user_id: user.id)
- .where.not(level: NotificationSetting.levels[:global])
- .index_by(&:source_id)
- end
+ @group
+ .notification_settings(hierarchy_order: :asc)
+ .where(user: user)
+ .where.not(level: NotificationSetting.levels[:global])
+ .first
end
end
diff --git a/app/models/notification_setting.rb b/app/models/notification_setting.rb
index 61af5c09ae4..8306b11a7b6 100644
--- a/app/models/notification_setting.rb
+++ b/app/models/notification_setting.rb
@@ -54,14 +54,11 @@ class NotificationSetting < ApplicationRecord
self.class.email_events(source)
end
- EXCLUDED_PARTICIPATING_EVENTS = [
- :success_pipeline
- ].freeze
-
EXCLUDED_WATCHER_EVENTS = [
:push_to_merge_request,
- :issue_due
- ].push(*EXCLUDED_PARTICIPATING_EVENTS).freeze
+ :issue_due,
+ :success_pipeline
+ ].freeze
def self.find_or_create_for(source)
setting = find_or_initialize_by(source: source)
diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb
index 82901ceec01..524df30289e 100644
--- a/app/models/pages_domain.rb
+++ b/app/models/pages_domain.rb
@@ -5,6 +5,7 @@ class PagesDomain < ApplicationRecord
VERIFICATION_THRESHOLD = 3.days.freeze
belongs_to :project
+ has_many :acme_orders, class_name: "PagesDomainAcmeOrder"
validates :domain, hostname: { allow_numeric_hostname: true }
validates :domain, uniqueness: { case_sensitive: false }
@@ -26,7 +27,7 @@ class PagesDomain < ApplicationRecord
after_initialize :set_verification_code
after_create :update_daemon
- after_update :update_daemon, if: :pages_config_changed?
+ after_update :update_daemon, if: :saved_change_to_pages_config?
after_destroy :update_daemon
scope :enabled, -> { where('enabled_until >= ?', Time.now ) }
@@ -38,6 +39,8 @@ class PagesDomain < ApplicationRecord
where(verified_at.eq(nil).or(enabled_until.eq(nil).or(enabled_until.lt(threshold))))
end
+ scope :for_removal, -> { where("remove_at < ?", Time.now) }
+
def verified?
!!verified_at
end
@@ -132,6 +135,14 @@ class PagesDomain < ApplicationRecord
"#{VERIFICATION_KEY}=#{verification_code}"
end
+ def certificate=(certificate)
+ super(certificate)
+
+ # set nil, if certificate is nil
+ self.certificate_valid_not_before = x509&.not_before
+ self.certificate_valid_not_after = x509&.not_after
+ end
+
private
def set_verification_code
@@ -146,21 +157,21 @@ class PagesDomain < ApplicationRecord
end
# rubocop: enable CodeReuse/ServiceClass
- def pages_config_changed?
- project_id_changed? ||
- domain_changed? ||
- certificate_changed? ||
- key_changed? ||
+ def saved_change_to_pages_config?
+ saved_change_to_project_id? ||
+ saved_change_to_domain? ||
+ saved_change_to_certificate? ||
+ saved_change_to_key? ||
became_enabled? ||
became_disabled?
end
def became_enabled?
- enabled_until.present? && !enabled_until_was.present?
+ enabled_until.present? && !enabled_until_before_last_save.present?
end
def became_disabled?
- !enabled_until.present? && enabled_until_was.present?
+ !enabled_until.present? && enabled_until_before_last_save.present?
end
def validate_matching_key
@@ -184,7 +195,7 @@ class PagesDomain < ApplicationRecord
end
def x509
- return unless certificate
+ return unless certificate.present?
@x509 ||= OpenSSL::X509::Certificate.new(certificate)
rescue OpenSSL::X509::CertificateError
diff --git a/app/models/pages_domain_acme_order.rb b/app/models/pages_domain_acme_order.rb
new file mode 100644
index 00000000000..63d7fbc8206
--- /dev/null
+++ b/app/models/pages_domain_acme_order.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class PagesDomainAcmeOrder < ApplicationRecord
+ belongs_to :pages_domain
+
+ scope :expired, -> { where("expires_at < ?", Time.now) }
+
+ validates :pages_domain, presence: true
+ validates :expires_at, presence: true
+ validates :url, presence: true
+ validates :challenge_token, presence: true
+ validates :challenge_file_content, presence: true
+ validates :private_key, presence: true
+
+ attr_encrypted :private_key,
+ mode: :per_attribute_iv,
+ key: Settings.attr_encrypted_db_key_base_truncated,
+ algorithm: 'aes-256-gcm',
+ encode: true
+
+ def self.find_by_domain_and_token(domain_name, challenge_token)
+ joins(:pages_domain).find_by(pages_domains: { domain: domain_name }, challenge_token: challenge_token)
+ end
+end
diff --git a/app/models/pool_repository.rb b/app/models/pool_repository.rb
index 7934118761e..50eed7344bd 100644
--- a/app/models/pool_repository.rb
+++ b/app/models/pool_repository.rb
@@ -7,7 +7,7 @@ class PoolRepository < ApplicationRecord
include Shardable
include AfterCommitQueue
- has_one :source_project, class_name: 'Project'
+ belongs_to :source_project, class_name: 'Project'
validates :source_project, presence: true
has_many :member_projects, class_name: 'Project'
@@ -99,7 +99,8 @@ class PoolRepository < ApplicationRecord
end
def inspect
- "#<#{self.class.name} id:#{id} state:#{state} disk_path:#{disk_path} source_project: #{source_project.full_path}>"
+ source = source_project ? source_project.full_path : 'nil'
+ "#<#{self.class.name} id:#{id} state:#{state} disk_path:#{disk_path} source_project: #{source}>"
end
private
diff --git a/app/models/project.rb b/app/models/project.rb
index 2fb6f5cb6a7..9d17d68eee2 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -90,7 +90,7 @@ class Project < ApplicationRecord
before_save :ensure_runners_token
- after_save :update_project_statistics, if: :namespace_id_changed?
+ after_save :update_project_statistics, if: :saved_change_to_namespace_id?
after_save :create_import_state, if: ->(project) { project.import? && project.import_state.nil? }
@@ -116,7 +116,7 @@ class Project < ApplicationRecord
after_initialize :use_hashed_storage
after_create :check_repository_absence!
after_create :ensure_storage_path_exists
- after_save :ensure_storage_path_exists, if: :namespace_id_changed?
+ after_save :ensure_storage_path_exists, if: :saved_change_to_namespace_id?
acts_as_ordered_taggable
@@ -188,6 +188,7 @@ class Project < ApplicationRecord
has_one :import_export_upload, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_one :project_repository, inverse_of: :project
has_one :error_tracking_setting, inverse_of: :project, class_name: 'ErrorTracking::ProjectErrorTrackingSetting'
+ has_one :metrics_setting, inverse_of: :project, class_name: 'ProjectMetricsSetting'
# Merge Requests for target project should be removed with it
has_many :merge_requests, foreign_key: 'target_project_id', inverse_of: :target_project
@@ -291,12 +292,14 @@ class Project < ApplicationRecord
accepts_nested_attributes_for :project_feature, update_only: true
accepts_nested_attributes_for :import_data
accepts_nested_attributes_for :auto_devops, update_only: true
+ accepts_nested_attributes_for :ci_cd_settings, update_only: true
accepts_nested_attributes_for :remote_mirrors,
allow_destroy: true,
reject_if: ->(attrs) { attrs[:id].blank? && attrs[:url].blank? }
accepts_nested_attributes_for :error_tracking_setting, update_only: true
+ accepts_nested_attributes_for :metrics_setting, update_only: true, allow_destroy: true
delegate :name, to: :owner, allow_nil: true, prefix: true
delegate :members, to: :team, prefix: true
@@ -307,6 +310,8 @@ class Project < ApplicationRecord
delegate :group_clusters_enabled?, to: :group, allow_nil: true
delegate :root_ancestor, to: :namespace, allow_nil: true
delegate :last_pipeline, to: :commit, allow_nil: true
+ delegate :external_dashboard_url, to: :metrics_setting, allow_nil: true, prefix: true
+ delegate :default_git_depth, :default_git_depth=, to: :ci_cd_settings, prefix: :ci
# Validations
validates :creator, presence: true, on: :create
@@ -334,8 +339,8 @@ class Project < ApplicationRecord
validates :star_count, numericality: { greater_than_or_equal_to: 0 }
validate :check_personal_projects_limit, on: :create
validate :check_repository_path_availability, on: :update, if: ->(project) { project.renamed? }
- validate :visibility_level_allowed_by_group, if: -> { changes.has_key?(:visibility_level) }
- validate :visibility_level_allowed_as_fork, if: -> { changes.has_key?(:visibility_level) }
+ validate :visibility_level_allowed_by_group, if: :should_validate_visibility_level?
+ validate :visibility_level_allowed_as_fork, if: :should_validate_visibility_level?
validate :check_wiki_path_conflict
validate :validate_pages_https_only, if: -> { changes.has_key?(:pages_https_only) }
validates :repository_storage,
@@ -354,7 +359,8 @@ class Project < ApplicationRecord
# last_activity_at is throttled every minute, but last_repository_updated_at is updated with every push
scope :sorted_by_activity, -> { reorder("GREATEST(COALESCE(last_activity_at, '1970-01-01'), COALESCE(last_repository_updated_at, '1970-01-01')) DESC") }
- scope :sorted_by_stars, -> { reorder(star_count: :desc) }
+ scope :sorted_by_stars_desc, -> { reorder(star_count: :desc) }
+ scope :sorted_by_stars_asc, -> { reorder(star_count: :asc) }
scope :in_namespace, ->(namespace_ids) { where(namespace_id: namespace_ids) }
scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
@@ -403,6 +409,7 @@ class Project < ApplicationRecord
scope :with_builds_enabled, -> { with_feature_enabled(:builds) }
scope :with_issues_enabled, -> { with_feature_enabled(:issues) }
scope :with_issues_available_for_user, ->(current_user) { with_feature_available_for_user(:issues, current_user) }
+ scope :with_merge_requests_available_for_user, ->(current_user) { with_feature_available_for_user(:merge_requests, current_user) }
scope :with_merge_requests_enabled, -> { with_feature_enabled(:merge_requests) }
scope :with_remote_mirrors, -> { joins(:remote_mirrors).where(remote_mirrors: { enabled: true }).distinct }
@@ -460,10 +467,12 @@ class Project < ApplicationRecord
# Returns a collection of projects that is either public or visible to the
# logged in user.
- def self.public_or_visible_to_user(user = nil)
+ def self.public_or_visible_to_user(user = nil, min_access_level = nil)
+ min_access_level = nil if user&.admin?
+
if user
where('EXISTS (?) OR projects.visibility_level IN (?)',
- user.authorizations_for_projects,
+ user.authorizations_for_projects(min_access_level: min_access_level),
Gitlab::VisibilityLevel.levels_for_user(user))
else
public_to_user
@@ -473,30 +482,32 @@ class Project < ApplicationRecord
# project features may be "disabled", "internal", "enabled" or "public". If "internal",
# they are only available to team members. This scope returns projects where
# the feature is either public, enabled, or internal with permission for the user.
+ # Note: this scope doesn't enforce that the user has access to the projects, it just checks
+ # that the user has access to the feature. It's important to use this scope with others
+ # that checks project authorizations first.
#
# This method uses an optimised version of `with_feature_access_level` for
# logged in users to more efficiently get private projects with the given
# feature.
def self.with_feature_available_for_user(feature, user)
visible = [ProjectFeature::ENABLED, ProjectFeature::PUBLIC]
- min_access_level = ProjectFeature.required_minimum_access_level(feature)
if user&.admin?
with_feature_enabled(feature)
elsif user
+ min_access_level = ProjectFeature.required_minimum_access_level(feature)
column = ProjectFeature.quoted_access_level_column(feature)
with_project_feature
- .where(
- "(projects.visibility_level > :private AND (#{column} IS NULL OR #{column} >= (:public_visible) OR (#{column} = :private_visible AND EXISTS(:authorizations))))"\
- " OR (projects.visibility_level = :private AND (#{column} IS NULL OR #{column} >= :private_visible) AND EXISTS(:authorizations))",
- {
- private: Gitlab::VisibilityLevel::PRIVATE,
- public_visible: ProjectFeature::ENABLED,
- private_visible: ProjectFeature::PRIVATE,
- authorizations: user.authorizations_for_projects(min_access_level: min_access_level)
- })
+ .where("#{column} IS NULL OR #{column} IN (:public_visible) OR (#{column} = :private_visible AND EXISTS (:authorizations))",
+ {
+ public_visible: visible,
+ private_visible: ProjectFeature::PRIVATE,
+ authorizations: user.authorizations_for_projects(min_access_level: min_access_level)
+ })
else
+ # This has to be added to include features whose value is nil in the db
+ visible << nil
with_feature_access_level(feature, visible)
end
end
@@ -541,7 +552,9 @@ class Project < ApplicationRecord
when 'latest_activity_asc'
reorder(last_activity_at: :asc)
when 'stars_desc'
- sorted_by_stars
+ sorted_by_stars_desc
+ when 'stars_asc'
+ sorted_by_stars_asc
else
order_by(method)
end
@@ -587,6 +600,17 @@ class Project < ApplicationRecord
def group_ids
joins(:namespace).where(namespaces: { type: 'Group' }).select(:namespace_id)
end
+
+ # Returns ids of projects with milestones available for given user
+ #
+ # Used on queries to find milestones which user can see
+ # For example: Milestone.where(project_id: ids_with_milestone_available_for(user))
+ def ids_with_milestone_available_for(user)
+ with_issues_enabled = with_issues_available_for_user(user).select(:id)
+ with_merge_requests_enabled = with_merge_requests_available_for_user(user).select(:id)
+
+ from_union([with_issues_enabled, with_merge_requests_enabled]).select(:id)
+ end
end
def all_pipelines
@@ -882,6 +906,10 @@ class Project < ApplicationRecord
self.errors.add(:limit_reached, error % { limit: limit })
end
+ def should_validate_visibility_level?
+ new_record? || changes.has_key?(:visibility_level)
+ end
+
def visibility_level_allowed_by_group
return if visibility_level_allowed_by_group?
@@ -1430,7 +1458,7 @@ class Project < ApplicationRecord
# update visibility_level of forks
def update_forks_visibility_level
- return unless visibility_level < visibility_level_was
+ return unless visibility_level < visibility_level_before_last_save
forks.each do |forked_project|
if forked_project.visibility_level > visibility_level
@@ -1910,8 +1938,8 @@ class Project < ApplicationRecord
false
end
- def full_path_was
- File.join(namespace.full_path, previous_changes['path'].first)
+ def full_path_before_last_save
+ File.join(namespace.full_path, path_before_last_save)
end
alias_method :name_with_namespace, :full_name
@@ -2131,13 +2159,11 @@ class Project < ApplicationRecord
end
def create_new_pool_repository
- pool = begin
- create_pool_repository!(shard: Shard.by_name(repository_storage), source_project: self)
- rescue ActiveRecord::RecordNotUnique
- pool_repository(true)
- end
+ pool = PoolRepository.safe_find_or_create_by!(shard: Shard.by_name(repository_storage), source_project: self)
+ update!(pool_repository: pool)
pool.schedule unless pool.scheduled?
+
pool
end
diff --git a/app/models/project_auto_devops.rb b/app/models/project_auto_devops.rb
index f972c40f317..67c12363a3c 100644
--- a/app/models/project_auto_devops.rb
+++ b/app/models/project_auto_devops.rb
@@ -1,6 +1,10 @@
# frozen_string_literal: true
class ProjectAutoDevops < ApplicationRecord
+ include IgnorableColumn
+
+ ignore_column :domain
+
belongs_to :project
enum deploy_strategy: {
@@ -12,31 +16,10 @@ class ProjectAutoDevops < ApplicationRecord
scope :enabled, -> { where(enabled: true) }
scope :disabled, -> { where(enabled: false) }
- validates :domain, allow_blank: true, hostname: { allow_numeric_hostname: true }
-
after_save :create_gitlab_deploy_token, if: :needs_to_create_deploy_token?
- def instance_domain
- Gitlab::CurrentSettings.auto_devops_domain
- end
-
- def has_domain?
- domain.present? || instance_domain.present?
- end
-
- # From 11.8, AUTO_DEVOPS_DOMAIN has been replaced by KUBE_INGRESS_BASE_DOMAIN.
- # See Clusters::Cluster#predefined_variables and https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24580
- # for more info.
- #
- # Suppport AUTO_DEVOPS_DOMAIN is scheduled to be removed on
- # https://gitlab.com/gitlab-org/gitlab-ce/issues/52363
def predefined_variables
Gitlab::Ci::Variables::Collection.new.tap do |variables|
- if has_domain?
- variables.append(key: 'AUTO_DEVOPS_DOMAIN',
- value: domain.presence || instance_domain)
- end
-
variables.concat(deployment_strategy_default_variables)
end
end
diff --git a/app/models/project_ci_cd_setting.rb b/app/models/project_ci_cd_setting.rb
index 1414164b703..821e022f51b 100644
--- a/app/models/project_ci_cd_setting.rb
+++ b/app/models/project_ci_cd_setting.rb
@@ -6,6 +6,18 @@ class ProjectCiCdSetting < ApplicationRecord
# The version of the schema that first introduced this model/table.
MINIMUM_SCHEMA_VERSION = 20180403035759
+ DEFAULT_GIT_DEPTH = 50
+
+ before_create :set_default_git_depth
+
+ validates :default_git_depth,
+ numericality: {
+ only_integer: true,
+ greater_than_or_equal_to: 0,
+ less_than_or_equal_to: 1000
+ },
+ allow_nil: true
+
def self.available?
@available ||=
ActiveRecord::Migrator.current_version >= MINIMUM_SCHEMA_VERSION
@@ -15,4 +27,12 @@ class ProjectCiCdSetting < ApplicationRecord
@available = nil
super
end
+
+ private
+
+ def set_default_git_depth
+ return unless Feature.enabled?(:ci_set_project_default_git_depth, default_enabled: true)
+
+ self.default_git_depth ||= DEFAULT_GIT_DEPTH
+ end
end
diff --git a/app/models/project_metrics_setting.rb b/app/models/project_metrics_setting.rb
new file mode 100644
index 00000000000..a2a7dc571a4
--- /dev/null
+++ b/app/models/project_metrics_setting.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class ProjectMetricsSetting < ApplicationRecord
+ belongs_to :project
+
+ validates :external_dashboard_url,
+ length: { maximum: 255 },
+ addressable_url: { enforce_sanitization: true, ascii_only: true }
+end
diff --git a/app/models/project_services/chat_message/deployment_message.rb b/app/models/project_services/chat_message/deployment_message.rb
new file mode 100644
index 00000000000..dae3a56116e
--- /dev/null
+++ b/app/models/project_services/chat_message/deployment_message.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+module ChatMessage
+ class DeploymentMessage < BaseMessage
+ attr_reader :commit_title
+ attr_reader :commit_url
+ attr_reader :deployable_id
+ attr_reader :deployable_url
+ attr_reader :environment
+ attr_reader :short_sha
+ attr_reader :status
+ attr_reader :user_url
+
+ def initialize(data)
+ super
+
+ @commit_title = data[:commit_title]
+ @commit_url = data[:commit_url]
+ @deployable_id = data[:deployable_id]
+ @deployable_url = data[:deployable_url]
+ @environment = data[:environment]
+ @short_sha = data[:short_sha]
+ @status = data[:status]
+ @user_url = data[:user_url]
+ end
+
+ def attachments
+ [{
+ text: "#{project_link} with job #{deployment_link} by #{user_link}\n#{commit_link}: #{commit_title}",
+ color: color
+ }]
+ end
+
+ def activity
+ {}
+ end
+
+ private
+
+ def message
+ "Deploy to #{environment} #{humanized_status}"
+ end
+
+ def color
+ case status
+ when 'success'
+ 'good'
+ when 'canceled'
+ 'warning'
+ when 'failed'
+ 'danger'
+ else
+ '#334455'
+ end
+ end
+
+ def project_link
+ link(project_name, project_url)
+ end
+
+ def deployment_link
+ link("##{deployable_id}", deployable_url)
+ end
+
+ def user_link
+ link(user_combined_name, user_url)
+ end
+
+ def commit_link
+ link(short_sha, commit_url)
+ end
+
+ def humanized_status
+ status == 'success' ? 'succeeded' : status
+ end
+ end
+end
diff --git a/app/models/project_services/chat_notification_service.rb b/app/models/project_services/chat_notification_service.rb
index c10ee07ccf4..7c9ecc6b821 100644
--- a/app/models/project_services/chat_notification_service.rb
+++ b/app/models/project_services/chat_notification_service.rb
@@ -33,7 +33,7 @@ class ChatNotificationService < Service
def self.supported_events
%w[push issue confidential_issue merge_request note confidential_note tag_push
- pipeline wiki_page]
+ pipeline wiki_page deployment]
end
def fields
@@ -122,6 +122,8 @@ class ChatNotificationService < Service
ChatMessage::PipelineMessage.new(data) if should_pipeline_be_notified?(data)
when "wiki_page"
ChatMessage::WikiPageMessage.new(data)
+ when "deployment"
+ ChatMessage::DeploymentMessage.new(data)
end
end
diff --git a/app/models/project_services/discord_service.rb b/app/models/project_services/discord_service.rb
index 405676792de..4385834ed0a 100644
--- a/app/models/project_services/discord_service.rb
+++ b/app/models/project_services/discord_service.rb
@@ -33,6 +33,11 @@ class DiscordService < ChatNotificationService
# No-op.
end
+ def self.supported_events
+ %w[push issue confidential_issue merge_request note confidential_note tag_push
+ pipeline wiki_page]
+ end
+
def default_fields
[
{ type: "text", name: "webhook", placeholder: "e.g. https://discordapp.com/api/webhooks/…" },
diff --git a/app/models/project_services/hangouts_chat_service.rb b/app/models/project_services/hangouts_chat_service.rb
index 272cd0f4e47..699cf1659d1 100644
--- a/app/models/project_services/hangouts_chat_service.rb
+++ b/app/models/project_services/hangouts_chat_service.rb
@@ -35,6 +35,11 @@ class HangoutsChatService < ChatNotificationService
'https://chat.googleapis.com/v1/spaces…'
end
+ def self.supported_events
+ %w[push issue confidential_issue merge_request note confidential_note tag_push
+ pipeline wiki_page]
+ end
+
def default_fields
[
{ type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}" },
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
index ebf28dc842c..7b4832b84a8 100644
--- a/app/models/project_services/jira_service.rb
+++ b/app/models/project_services/jira_service.rb
@@ -265,6 +265,7 @@ class JiraService < IssueTrackerService
def find_remote_link(issue, url)
links = jira_request { issue.remotelink.all }
+ return unless links
links.find { |link| link.object["url"] == url }
end
diff --git a/app/models/project_services/kubernetes_service.rb b/app/models/project_services/kubernetes_service.rb
index f650dbd3726..aa6b4aa1d5e 100644
--- a/app/models/project_services/kubernetes_service.rb
+++ b/app/models/project_services/kubernetes_service.rb
@@ -86,7 +86,7 @@ class KubernetesService < DeploymentService
]
end
- def actual_namespace
+ def kubernetes_namespace_for(project)
if namespace.present?
namespace
else
@@ -114,7 +114,7 @@ class KubernetesService < DeploymentService
variables
.append(key: 'KUBE_URL', value: api_url)
.append(key: 'KUBE_TOKEN', value: token, public: false, masked: true)
- .append(key: 'KUBE_NAMESPACE', value: actual_namespace)
+ .append(key: 'KUBE_NAMESPACE', value: kubernetes_namespace_for(project))
.append(key: 'KUBECONFIG', value: kubeconfig, public: false, file: true)
if ca_pem.present?
@@ -131,8 +131,10 @@ class KubernetesService < DeploymentService
# short time later
def terminals(environment)
with_reactive_cache do |data|
+ project = environment.project
+
pods = filter_by_project_environment(data[:pods], project.full_path_slug, environment.slug)
- terminals = pods.flat_map { |pod| terminals_for_pod(api_url, actual_namespace, pod) }.compact
+ terminals = pods.flat_map { |pod| terminals_for_pod(api_url, kubernetes_namespace_for(project), pod) }.compact
terminals.each { |terminal| add_terminal_auth(terminal, terminal_auth) }
end
end
@@ -169,7 +171,7 @@ class KubernetesService < DeploymentService
def kubeconfig
to_kubeconfig(
url: api_url,
- namespace: actual_namespace,
+ namespace: kubernetes_namespace_for(project),
token: token,
ca_pem: ca_pem)
end
@@ -186,7 +188,7 @@ class KubernetesService < DeploymentService
end
def build_kube_client!
- raise "Incomplete settings" unless api_url && actual_namespace && token
+ raise "Incomplete settings" unless api_url && kubernetes_namespace_for(project) && token
Gitlab::Kubernetes::KubeClient.new(
api_url,
@@ -200,7 +202,7 @@ class KubernetesService < DeploymentService
def read_pods
kubeclient = build_kube_client!
- kubeclient.get_pods(namespace: actual_namespace).as_json
+ kubeclient.get_pods(namespace: kubernetes_namespace_for(project)).as_json
rescue Kubeclient::ResourceNotFoundError
[]
end
diff --git a/app/models/project_services/microsoft_teams_service.rb b/app/models/project_services/microsoft_teams_service.rb
index c34078f13c1..c22a6dc26f6 100644
--- a/app/models/project_services/microsoft_teams_service.rb
+++ b/app/models/project_services/microsoft_teams_service.rb
@@ -33,6 +33,11 @@ class MicrosoftTeamsService < ChatNotificationService
def default_channel_placeholder
end
+ def self.supported_events
+ %w[push issue confidential_issue merge_request note confidential_note tag_push
+ pipeline wiki_page]
+ end
+
def default_fields
[
{ type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}" },
diff --git a/app/models/project_services/pipelines_email_service.rb b/app/models/project_services/pipelines_email_service.rb
index 7ba69370f14..ae5d5038099 100644
--- a/app/models/project_services/pipelines_email_service.rb
+++ b/app/models/project_services/pipelines_email_service.rb
@@ -2,11 +2,11 @@
class PipelinesEmailService < Service
prop_accessor :recipients
- boolean_accessor :notify_only_broken_pipelines
+ boolean_accessor :notify_only_broken_pipelines, :notify_only_default_branch
validates :recipients, presence: true, if: :valid_recipients?
def initialize_properties
- self.properties ||= { notify_only_broken_pipelines: true }
+ self.properties ||= { notify_only_broken_pipelines: true, notify_only_default_branch: false }
end
def title
@@ -54,7 +54,9 @@ class PipelinesEmailService < Service
placeholder: _('Emails separated by comma'),
required: true },
{ type: 'checkbox',
- name: 'notify_only_broken_pipelines' }
+ name: 'notify_only_broken_pipelines' },
+ { type: 'checkbox',
+ name: 'notify_only_default_branch' }
]
end
@@ -67,6 +69,16 @@ class PipelinesEmailService < Service
end
def should_pipeline_be_notified?(data)
+ notify_for_pipeline_branch?(data) && notify_for_pipeline?(data)
+ end
+
+ def notify_for_pipeline_branch?(data)
+ return true unless notify_only_default_branch?
+
+ data[:object_attributes][:ref] == data[:project][:default_branch]
+ end
+
+ def notify_for_pipeline?(data)
case data[:object_attributes][:status]
when 'success'
!notify_only_broken_pipelines?
diff --git a/app/models/project_services/youtrack_service.rb b/app/models/project_services/youtrack_service.rb
index 957be685aea..175c2ebf197 100644
--- a/app/models/project_services/youtrack_service.rb
+++ b/app/models/project_services/youtrack_service.rb
@@ -5,12 +5,12 @@ class YoutrackService < IssueTrackerService
prop_accessor :description, :project_url, :issues_url
- # {PROJECT-KEY}-{NUMBER} Examples: YT-1, PRJ-1
+ # {PROJECT-KEY}-{NUMBER} Examples: YT-1, PRJ-1, gl-030
def self.reference_pattern(only_long: false)
if only_long
- /(?<issue>\b[A-Z][A-Za-z0-9_]*-\d+)/
+ /(?<issue>\b[A-Za-z][A-Za-z0-9_]*-\d+)/
else
- /(?<issue>\b[A-Z][A-Za-z0-9_]*-\d+)|(#{Issue.reference_prefix}(?<issue>\d+))/
+ /(?<issue>\b[A-Za-z][A-Za-z0-9_]*-\d+)|(#{Issue.reference_prefix}(?<issue>\d+))/
end
end
diff --git a/app/models/project_statistics.rb b/app/models/project_statistics.rb
index c020e72908c..8a179b4d56d 100644
--- a/app/models/project_statistics.rb
+++ b/app/models/project_statistics.rb
@@ -4,10 +4,19 @@ class ProjectStatistics < ApplicationRecord
belongs_to :project
belongs_to :namespace
+ default_value_for :wiki_size, 0
+
+ # older migrations fail due to non-existent attribute without this
+ def wiki_size
+ has_attribute?(:wiki_size) ? super : 0
+ end
+
before_save :update_storage_size
- COLUMNS_TO_REFRESH = [:repository_size, :lfs_objects_size, :commit_count].freeze
- INCREMENTABLE_COLUMNS = { build_artifacts_size: %i[storage_size] }.freeze
+ COLUMNS_TO_REFRESH = [:repository_size, :wiki_size, :lfs_objects_size, :commit_count].freeze
+ INCREMENTABLE_COLUMNS = { build_artifacts_size: %i[storage_size], packages_size: %i[storage_size] }.freeze
+
+ scope :for_project_ids, ->(project_ids) { where(project_id: project_ids) }
def total_repository_size
repository_size + lfs_objects_size
@@ -27,17 +36,25 @@ class ProjectStatistics < ApplicationRecord
self.commit_count = project.repository.commit_count
end
- # Repository#size needs to be converted from MB to Byte.
def update_repository_size
self.repository_size = project.repository.size * 1.megabyte
end
+ def update_wiki_size
+ self.wiki_size = project.wiki.repository.size * 1.megabyte
+ end
+
def update_lfs_objects_size
self.lfs_objects_size = project.lfs_objects.sum(:size)
end
+ # older migrations fail due to non-existent attribute without this
+ def packages_size
+ has_attribute?(:packages_size) ? super : 0
+ end
+
def update_storage_size
- self.storage_size = repository_size + lfs_objects_size + build_artifacts_size
+ self.storage_size = repository_size + wiki_size.to_i + lfs_objects_size + build_artifacts_size + packages_size
end
# Since this incremental update method does not call update_storage_size above,
diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb
index 23ddd708396..c91add6439f 100644
--- a/app/models/project_wiki.rb
+++ b/app/models/project_wiki.rb
@@ -82,17 +82,25 @@ class ProjectWiki
end
def empty?
- pages(limit: 1).empty?
+ list_pages(limit: 1).empty?
end
+ # Lists wiki pages of the repository.
+ #
+ # limit - max number of pages returned by the method.
+ # sort - criterion by which the pages are sorted.
+ # direction - order of the sorted pages.
+ # load_content - option, which specifies whether the content inside the page
+ # will be loaded.
+ #
# Returns an Array of GitLab WikiPage instances or an
# empty Array if this Wiki has no pages.
- def pages(limit: 0, sort: nil, direction: DIRECTION_ASC)
- sort ||= TITLE_ORDER
- direction_desc = direction == DIRECTION_DESC
-
- wiki.pages(
- limit: limit, sort: sort, direction_desc: direction_desc
+ def list_pages(limit: 0, sort: nil, direction: DIRECTION_ASC, load_content: false)
+ wiki.list_pages(
+ limit: limit,
+ sort: sort,
+ direction_desc: direction == DIRECTION_DESC,
+ load_content: load_content
).map do |page|
WikiPage.new(self, page, true)
end
diff --git a/app/models/push_event.rb b/app/models/push_event.rb
index 9c0267c3140..4698df39730 100644
--- a/app/models/push_event.rb
+++ b/app/models/push_event.rb
@@ -69,7 +69,7 @@ class PushEvent < Event
PUSHED
end
- def push?
+ def push_action?
true
end
diff --git a/app/models/release.rb b/app/models/release.rb
index 0f9e94373c7..7bbeb3c9976 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -31,8 +31,11 @@ class Release < ApplicationRecord
actual_tag.nil?
end
- def assets_count
- links.count + sources.count
+ def assets_count(except: [])
+ links_count = links.count
+ sources_count = except.include?(:sources) ? 0 : sources.count
+
+ links_count + sources_count
end
def sources
diff --git a/app/models/remote_mirror.rb b/app/models/remote_mirror.rb
index b2fd5394a03..af705b29f7a 100644
--- a/app/models/remote_mirror.rb
+++ b/app/models/remote_mirror.rb
@@ -22,8 +22,8 @@ class RemoteMirror < ApplicationRecord
before_save :set_new_remote_name, if: :mirror_url_changed?
after_save :set_override_remote_mirror_available, unless: -> { Gitlab::CurrentSettings.current_application_settings.mirror_available }
- after_save :refresh_remote, if: :mirror_url_changed?
- after_update :reset_fields, if: :mirror_url_changed?
+ after_save :refresh_remote, if: :saved_change_to_mirror_url?
+ after_update :reset_fields, if: :saved_change_to_mirror_url?
after_commit :remove_remote, on: :destroy
@@ -133,6 +133,10 @@ class RemoteMirror < ApplicationRecord
end
alias_method :enabled?, :enabled
+ def disabled?
+ !enabled?
+ end
+
def updated_since?(timestamp)
last_update_started_at && last_update_started_at > timestamp && !update_failed?
end
@@ -248,7 +252,7 @@ class RemoteMirror < ApplicationRecord
# Before adding a new remote we have to delete the data from
# the previous remote name
- prev_remote_name = remote_name_was || fallback_remote_name
+ prev_remote_name = remote_name_before_last_save || fallback_remote_name
run_after_commit do
project.repository.async_remove_remote(prev_remote_name)
end
@@ -265,4 +269,8 @@ class RemoteMirror < ApplicationRecord
def mirror_url_changed?
url_changed? || credentials_changed?
end
+
+ def saved_change_to_mirror_url?
+ saved_change_to_url? || saved_change_to_credentials?
+ end
end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 574ce12b309..e05d3dd58ac 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -39,7 +39,8 @@ class Repository
changelog license_blob license_key gitignore
gitlab_ci_yml branch_names tag_names branch_count
tag_count avatar exists? root_ref has_visible_content?
- issue_template_names merge_request_template_names xcode_project?).freeze
+ issue_template_names merge_request_template_names
+ metrics_dashboard_paths xcode_project?).freeze
# Methods that use cache_method but only memoize the value
MEMOIZED_CACHED_METHODS = %i(license).freeze
@@ -57,6 +58,7 @@ class Repository
avatar: :avatar,
issue_template: :issue_template_names,
merge_request_template: :merge_request_template_names,
+ metrics_dashboard: :metrics_dashboard_paths,
xcode_config: :xcode_project?
}.freeze
@@ -281,14 +283,19 @@ class Repository
end
def diverging_commit_counts(branch)
+ return diverging_commit_counts_without_max(branch) if Feature.enabled?('gitaly_count_diverging_commits_no_max')
+
+ ## TODO: deprecate the below code after 12.0
@root_ref_hash ||= raw_repository.commit(root_ref).id
cache.fetch(:"diverging_commit_counts_#{branch.name}") do
# Rugged seems to throw a `ReferenceError` when given branch_names rather
# than SHA-1 hashes
+ branch_sha = branch.dereferenced_target.sha
+
number_commits_behind, number_commits_ahead =
raw_repository.diverging_commit_count(
@root_ref_hash,
- branch.dereferenced_target.sha,
+ branch_sha,
max_count: MAX_DIVERGING_COUNT)
if number_commits_behind + number_commits_ahead >= MAX_DIVERGING_COUNT
@@ -299,13 +306,30 @@ class Repository
end
end
- def archive_metadata(ref, storage_path, format = "tar.gz", append_sha:)
+ def diverging_commit_counts_without_max(branch)
+ @root_ref_hash ||= raw_repository.commit(root_ref).id
+ cache.fetch(:"diverging_commit_counts_without_max_#{branch.name}") do
+ # Rugged seems to throw a `ReferenceError` when given branch_names rather
+ # than SHA-1 hashes
+ branch_sha = branch.dereferenced_target.sha
+
+ number_commits_behind, number_commits_ahead =
+ raw_repository.diverging_commit_count(
+ @root_ref_hash,
+ branch_sha)
+
+ { behind: number_commits_behind, ahead: number_commits_ahead }
+ end
+ end
+
+ def archive_metadata(ref, storage_path, format = "tar.gz", append_sha:, path: nil)
raw_repository.archive_metadata(
ref,
storage_path,
project.path,
format,
- append_sha: append_sha
+ append_sha: append_sha,
+ path: path
)
end
@@ -462,7 +486,7 @@ class Repository
def after_import
expire_content_cache
- DetectRepositoryLanguagesWorker.perform_async(project.id, project.owner.id)
+ DetectRepositoryLanguagesWorker.perform_async(project.id)
end
# Runs code after a new commit has been pushed.
@@ -601,6 +625,11 @@ class Repository
end
cache_method :merge_request_template_names, fallback: []
+ def metrics_dashboard_paths
+ Gitlab::Metrics::Dashboard::Finder.find_all_paths_from_source(project)
+ end
+ cache_method :metrics_dashboard_paths
+
def readme
head_tree&.readme
end
@@ -1029,11 +1058,41 @@ class Repository
raw_repository.fetch_ref(source_repository.raw_repository, source_ref: source_ref, target_ref: target_ref)
end
+ # DEPRECATED: https://gitlab.com/gitlab-org/gitaly/issues/1628
+ def rebase_deprecated(user, merge_request)
+ rebase_sha = raw.rebase_deprecated(
+ user,
+ merge_request.id,
+ branch: merge_request.source_branch,
+ branch_sha: merge_request.source_branch_sha,
+ remote_repository: merge_request.target_project.repository.raw,
+ remote_branch: merge_request.target_branch
+ )
+
+ # To support the full deprecated behaviour, set the
+ # `rebase_commit_sha` for the merge_request here and return the value
+ merge_request.update(rebase_commit_sha: rebase_sha, merge_error: nil)
+
+ rebase_sha
+ end
+
def rebase(user, merge_request)
- raw.rebase(user, merge_request.id, branch: merge_request.source_branch,
- branch_sha: merge_request.source_branch_sha,
- remote_repository: merge_request.target_project.repository.raw,
- remote_branch: merge_request.target_branch)
+ if Feature.disabled?(:two_step_rebase, default_enabled: true)
+ return rebase_deprecated(user, merge_request)
+ end
+
+ MergeRequest.transaction do
+ raw.rebase(
+ user,
+ merge_request.id,
+ branch: merge_request.source_branch,
+ branch_sha: merge_request.source_branch_sha,
+ remote_repository: merge_request.target_project.repository.raw,
+ remote_branch: merge_request.target_branch
+ ) do |commit_id|
+ merge_request.update!(rebase_commit_sha: commit_id, merge_error: nil)
+ end
+ end
end
def squash(user, merge_request, message)
@@ -1064,6 +1123,19 @@ class Repository
blob.data
end
+ def create_if_not_exists
+ return if exists?
+
+ raw.create_repository
+ after_create
+ end
+
+ def blobs_metadata(paths, ref = 'HEAD')
+ references = Array.wrap(paths).map { |path| [ref, path] }
+
+ Gitlab::Git::Blob.batch_metadata(raw, references).map { |raw_blob| Blob.decorate(raw_blob) }
+ end
+
private
# TODO Generice finder, later split this on finders by Ref or Oid
diff --git a/app/models/route.rb b/app/models/route.rb
index 7e3db54d4fe..91ea2966013 100644
--- a/app/models/route.rb
+++ b/app/models/route.rb
@@ -14,26 +14,26 @@ class Route < ApplicationRecord
before_validation :delete_conflicting_orphaned_routes
after_create :delete_conflicting_redirects
- after_update :delete_conflicting_redirects, if: :path_changed?
+ after_update :delete_conflicting_redirects, if: :saved_change_to_path?
after_update :create_redirect_for_old_path
after_update :rename_descendants
scope :inside_path, -> (path) { where('routes.path LIKE ?', "#{sanitize_sql_like(path)}/%") }
def rename_descendants
- return unless path_changed? || name_changed?
+ return unless saved_change_to_path? || saved_change_to_name?
- descendant_routes = self.class.inside_path(path_was)
+ descendant_routes = self.class.inside_path(path_before_last_save)
descendant_routes.each do |route|
attributes = {}
- if path_changed? && route.path.present?
- attributes[:path] = route.path.sub(path_was, path)
+ if saved_change_to_path? && route.path.present?
+ attributes[:path] = route.path.sub(path_before_last_save, path)
end
- if name_changed? && name_was.present? && route.name.present?
- attributes[:name] = route.name.sub(name_was, name)
+ if saved_change_to_name? && name_before_last_save.present? && route.name.present?
+ attributes[:name] = route.name.sub(name_before_last_save, name)
end
if attributes.present?
@@ -65,7 +65,7 @@ class Route < ApplicationRecord
private
def create_redirect_for_old_path
- create_redirect(path_was) if path_changed?
+ create_redirect(path_before_last_save) if saved_change_to_path?
end
def delete_conflicting_orphaned_routes
diff --git a/app/models/service.rb b/app/models/service.rb
index de549becf71..9896aa12e90 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -50,6 +50,7 @@ class Service < ApplicationRecord
scope :job_hooks, -> { where(job_events: true, active: true) }
scope :pipeline_hooks, -> { where(pipeline_events: true, active: true) }
scope :wiki_page_hooks, -> { where(wiki_page_events: true, active: true) }
+ scope :deployment_hooks, -> { where(deployment_events: true, active: true) }
scope :external_issue_trackers, -> { issue_trackers.active.without_defaults }
scope :deployment, -> { where(category: 'deployment') }
@@ -335,6 +336,8 @@ class Service < ApplicationRecord
"Event will be triggered when a wiki page is created/updated"
when "commit", "commit_events"
"Event will be triggered when a commit is created/updated"
+ when "deployment"
+ "Event will be triggered when a deployment finishes"
end
end
diff --git a/app/models/storage/legacy_project.rb b/app/models/storage/legacy_project.rb
index 76ac5c13c18..b483c677be9 100644
--- a/app/models/storage/legacy_project.rb
+++ b/app/models/storage/legacy_project.rb
@@ -30,7 +30,7 @@ module Storage
end
def rename_repo(old_full_path: nil, new_full_path: nil)
- old_full_path ||= project.full_path_was
+ old_full_path ||= project.full_path_before_last_save
new_full_path ||= project.build_full_path
if gitlab_shell.mv_repository(repository_storage, old_full_path, new_full_path)
diff --git a/app/models/todo.rb b/app/models/todo.rb
index 5dcc3e9945a..f1fc5e599eb 100644
--- a/app/models/todo.rb
+++ b/app/models/todo.rb
@@ -38,7 +38,9 @@ class Todo < ApplicationRecord
self
end
}, polymorphic: true, touch: true # rubocop:disable Cop/PolymorphicAssociations
+
belongs_to :user
+ belongs_to :issue, -> { where("target_type = 'Issue'") }, foreign_key: :target_id
delegate :name, :email, to: :author, prefix: true, allow_nil: true
@@ -59,6 +61,7 @@ class Todo < ApplicationRecord
scope :for_target, -> (id) { where(target_id: id) }
scope :for_commit, -> (id) { where(commit_id: id) }
scope :with_api_entity_associations, -> { preload(:target, :author, :note, group: :route, project: [:route, { namespace: :route }]) }
+ scope :joins_issue_and_assignees, -> { left_joins(issue: :assignees) }
state_machine :state, initial: :pending do
event :done do
diff --git a/app/models/user.rb b/app/models/user.rb
index 551eb58a4de..2eb5c63a4cc 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -194,7 +194,7 @@ class User < ApplicationRecord
before_validation :ensure_namespace_correct
before_save :ensure_namespace_correct # in case validation is skipped
after_validation :set_username_errors
- after_update :username_changed_hook, if: :username_changed?
+ after_update :username_changed_hook, if: :saved_change_to_username?
after_destroy :post_destroy_hook
after_destroy :remove_key_cache
after_commit(on: :update) do
@@ -230,6 +230,9 @@ class User < ApplicationRecord
delegate :notes_filter_for, to: :user_preference
delegate :set_notes_filter, to: :user_preference
delegate :first_day_of_week, :first_day_of_week=, to: :user_preference
+ delegate :timezone, :timezone=, to: :user_preference
+ delegate :time_display_relative, :time_display_relative=, to: :user_preference
+ delegate :time_format_in_24h, :time_format_in_24h=, to: :user_preference
accepts_nested_attributes_for :user_preference, update_only: true
@@ -757,11 +760,15 @@ class User < ApplicationRecord
# Typically used in conjunction with projects table to get projects
# a user has been given access to.
+ # The param `related_project_column` is the column to compare to the
+ # project_authorizations. By default is projects.id
#
# Example use:
# `Project.where('EXISTS(?)', user.authorizations_for_projects)`
- def authorizations_for_projects(min_access_level: nil)
- authorizations = project_authorizations.select(1).where('project_authorizations.project_id = projects.id')
+ def authorizations_for_projects(min_access_level: nil, related_project_column: 'projects.id')
+ authorizations = project_authorizations
+ .select(1)
+ .where("project_authorizations.project_id = #{related_project_column}")
return authorizations unless min_access_level.present?
@@ -1490,15 +1497,6 @@ class User < ApplicationRecord
devise_mailer.__send__(notification, self, *args).deliver_later # rubocop:disable GitlabSecurity/PublicSend
end
- # This works around a bug in Devise 4.2.0 that erroneously causes a user to
- # be considered active in MySQL specs due to a sub-second comparison
- # issue. For more details, see: https://gitlab.com/gitlab-org/gitlab-ee/issues/2362#note_29004709
- def confirmation_period_valid?
- return false if self.class.allow_unconfirmed_access_for == 0.days
-
- super
- end
-
def ensure_user_rights_and_limits
if external?
self.can_create_group = false
diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb
index 282b192167f..f1326f4c8cb 100644
--- a/app/models/user_preference.rb
+++ b/app/models/user_preference.rb
@@ -10,6 +10,10 @@ class UserPreference < ApplicationRecord
validates :issue_notes_filter, :merge_request_notes_filter, inclusion: { in: NOTES_FILTERS.values }, presence: true
+ default_value_for :timezone, value: Time.zone.tzinfo.name, allows_nil: false
+ default_value_for :time_display_relative, value: true, allows_nil: false
+ default_value_for :time_format_in_24h, value: false, allows_nil: false
+
class << self
def notes_filters
{
diff --git a/app/policies/clusters/cluster_policy.rb b/app/policies/clusters/cluster_policy.rb
index d6d590687e2..316bd39f7a3 100644
--- a/app/policies/clusters/cluster_policy.rb
+++ b/app/policies/clusters/cluster_policy.rb
@@ -6,5 +6,6 @@ module Clusters
delegate { cluster.group }
delegate { cluster.project }
+ delegate { cluster.instance }
end
end
diff --git a/app/policies/clusters/instance_policy.rb b/app/policies/clusters/instance_policy.rb
new file mode 100644
index 00000000000..e1045c85e6d
--- /dev/null
+++ b/app/policies/clusters/instance_policy.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Clusters
+ class InstancePolicy < BasePolicy
+ include ClusterableActions
+
+ condition(:has_clusters, scope: :subject) { clusterable_has_clusters? }
+ condition(:can_have_multiple_clusters) { multiple_clusters_available? }
+ condition(:instance_clusters_enabled) { Instance.enabled? }
+
+ rule { admin & instance_clusters_enabled }.policy do
+ enable :read_cluster
+ enable :add_cluster
+ enable :create_cluster
+ enable :update_cluster
+ enable :admin_cluster
+ end
+
+ rule { ~can_have_multiple_clusters & has_clusters }.prevent :add_cluster
+ end
+end
diff --git a/app/policies/global_policy.rb b/app/policies/global_policy.rb
index d412a591fdc..e85397422e6 100644
--- a/app/policies/global_policy.rb
+++ b/app/policies/global_policy.rb
@@ -44,7 +44,6 @@ class GlobalPolicy < BasePolicy
prevent :access_api
prevent :access_git
prevent :receive_notifications
- prevent :use_quick_actions
end
rule { required_terms_not_accepted }.policy do
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index eb2e536e8e9..ea86858181d 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -129,6 +129,10 @@ class GroupPolicy < BasePolicy
def access_level
return GroupMember::NO_ACCESS if @user.nil?
- @access_level ||= @subject.max_member_access_for_user(@user)
+ @access_level ||= lookup_access_level!
+ end
+
+ def lookup_access_level!
+ @subject.max_member_access_for_user(@user)
end
end
diff --git a/app/policies/personal_snippet_policy.rb b/app/policies/personal_snippet_policy.rb
index 2b5cca76c20..40dd49b4afd 100644
--- a/app/policies/personal_snippet_policy.rb
+++ b/app/policies/personal_snippet_policy.rb
@@ -7,7 +7,7 @@ class PersonalSnippetPolicy < BasePolicy
rule { public_snippet }.policy do
enable :read_personal_snippet
- enable :comment_personal_snippet
+ enable :create_note
end
rule { is_author }.policy do
@@ -15,7 +15,7 @@ class PersonalSnippetPolicy < BasePolicy
enable :update_personal_snippet
enable :destroy_personal_snippet
enable :admin_personal_snippet
- enable :comment_personal_snippet
+ enable :create_note
end
rule { ~anonymous }.enable :create_personal_snippet
@@ -23,15 +23,12 @@ class PersonalSnippetPolicy < BasePolicy
rule { internal_snippet & ~external_user }.policy do
enable :read_personal_snippet
- enable :comment_personal_snippet
+ enable :create_note
end
- rule { anonymous }.prevent :comment_personal_snippet
+ rule { anonymous }.prevent :create_note
- rule { can?(:comment_personal_snippet) }.policy do
- enable :create_note
- enable :award_emoji
- end
+ rule { can?(:create_note) }.enable :award_emoji
rule { full_private_access }.enable :read_personal_snippet
end
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index ba38af9c529..728a3040227 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -164,6 +164,7 @@ class ProjectPolicy < BasePolicy
enable :set_issue_iid
enable :set_issue_created_at
+ enable :set_issue_updated_at
enable :set_note_created_at
end
@@ -186,6 +187,7 @@ class ProjectPolicy < BasePolicy
enable :read_cycle_analytics
enable :award_emoji
enable :read_pages_content
+ enable :read_release
end
# These abilities are not allowed to admins that are not members of the project,
@@ -212,7 +214,6 @@ class ProjectPolicy < BasePolicy
enable :read_deployment
enable :read_merge_request
enable :read_sentry_issue
- enable :read_release
enable :read_prometheus
end
@@ -488,6 +489,10 @@ class ProjectPolicy < BasePolicy
def team_access_level
return -1 if @user.nil?
+ lookup_access_level!
+ end
+
+ def lookup_access_level!
# NOTE: max_member_access has its own cache
project.team.max_member_access(@user.id)
end
diff --git a/app/presenters/blob_presenter.rb b/app/presenters/blob_presenter.rb
index 6323c1b3389..91c9abe750b 100644
--- a/app/presenters/blob_presenter.rb
+++ b/app/presenters/blob_presenter.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class BlobPresenter < Gitlab::View::Presenter::Simple
+class BlobPresenter < Gitlab::View::Presenter::Delegated
presents :blob
def highlight(plain: nil)
@@ -13,4 +13,8 @@ class BlobPresenter < Gitlab::View::Presenter::Simple
plain: plain
)
end
+
+ def web_url
+ Gitlab::Routing.url_helpers.project_blob_url(blob.repository.project, File.join(blob.commit_id, blob.path))
+ end
end
diff --git a/app/presenters/ci/build_runner_presenter.rb b/app/presenters/ci/build_runner_presenter.rb
index ed3daf6585b..b928988ed8c 100644
--- a/app/presenters/ci/build_runner_presenter.rb
+++ b/app/presenters/ci/build_runner_presenter.rb
@@ -4,7 +4,6 @@ module Ci
class BuildRunnerPresenter < SimpleDelegator
include Gitlab::Utils::StrongMemoize
- DEFAULT_GIT_DEPTH_MERGE_REQUEST = 10
RUNNER_REMOTE_TAG_PREFIX = 'refs/tags/'.freeze
RUNNER_REMOTE_BRANCH_PREFIX = 'refs/remotes/origin/'.freeze
@@ -26,20 +25,20 @@ module Ci
end
def git_depth
- strong_memoize(:git_depth) do
- git_depth = variables&.find { |variable| variable[:key] == 'GIT_DEPTH' }&.dig(:value)
- git_depth ||= DEFAULT_GIT_DEPTH_MERGE_REQUEST if merge_request_ref?
- git_depth.to_i
- end
+ if git_depth_variable
+ git_depth_variable[:value]
+ elsif Feature.enabled?(:ci_project_git_depth, default_enabled: true)
+ project.ci_default_git_depth
+ end.to_i
end
def refspecs
specs = []
+ specs << refspec_for_merge_request_ref if merge_request_ref?
if git_depth > 0
specs << refspec_for_branch(ref) if branch? || legacy_detached_merge_request_pipeline?
specs << refspec_for_tag(ref) if tag?
- specs << refspec_for_merge_request_ref if merge_request_ref?
else
specs << refspec_for_branch
specs << refspec_for_tag
@@ -90,5 +89,11 @@ module Ci
def refspec_for_merge_request_ref
"+#{ref}:#{ref}"
end
+
+ def git_depth_variable
+ strong_memoize(:git_depth_variable) do
+ variables&.find { |variable| variable[:key] == 'GIT_DEPTH' }
+ end
+ end
end
end
diff --git a/app/presenters/ci/pipeline_presenter.rb b/app/presenters/ci/pipeline_presenter.rb
index 1c1347c5a57..358473d0a74 100644
--- a/app/presenters/ci/pipeline_presenter.rb
+++ b/app/presenters/ci/pipeline_presenter.rb
@@ -43,7 +43,7 @@ module Ci
if pipeline.ref_exists?
_("for %{link_to_pipeline_ref}").html_safe % { link_to_pipeline_ref: link_to_pipeline_ref }
else
- _("for %{ref}") % { ref: content_tag(:span, pipeline.ref, class: 'ref-name') }
+ _("for %{ref}").html_safe % { ref: content_tag(:span, pipeline.ref, class: 'ref-name') }
end
end
end
@@ -63,19 +63,11 @@ module Ci
end
def link_to_merge_request_source_branch
- return unless merge_request_presenter
-
- link_to(merge_request_presenter.source_branch,
- merge_request_presenter.source_branch_commits_path,
- class: 'ref-name')
+ merge_request_presenter&.source_branch_link
end
def link_to_merge_request_target_branch
- return unless merge_request_presenter
-
- link_to(merge_request_presenter.target_branch,
- merge_request_presenter.target_branch_commits_path,
- class: 'ref-name')
+ merge_request_presenter&.target_branch_link
end
private
diff --git a/app/presenters/clusters/cluster_presenter.rb b/app/presenters/clusters/cluster_presenter.rb
index 81994bbce7d..1634d2479a0 100644
--- a/app/presenters/clusters/cluster_presenter.rb
+++ b/app/presenters/clusters/cluster_presenter.rb
@@ -22,10 +22,6 @@ module Clusters
"https://console.cloud.google.com/kubernetes/clusters/details/#{provider.zone}/#{name}" if gcp?
end
- def can_toggle_cluster?
- can?(current_user, :update_cluster, cluster) && created?
- end
-
def can_read_cluster?
can?(current_user, :read_cluster, cluster)
end
@@ -35,6 +31,8 @@ module Clusters
s_("ClusterIntegration|Project cluster")
elsif cluster.group_type?
s_("ClusterIntegration|Group cluster")
+ elsif cluster.instance_type?
+ s_("ClusterIntegration|Instance cluster")
end
end
@@ -43,6 +41,8 @@ module Clusters
project_cluster_path(project, cluster)
elsif cluster.group_type?
group_cluster_path(group, cluster)
+ elsif cluster.instance_type?
+ admin_cluster_path(cluster)
else
raise NotImplementedError
end
diff --git a/app/presenters/instance_clusterable_presenter.rb b/app/presenters/instance_clusterable_presenter.rb
new file mode 100644
index 00000000000..f8bbe5216f1
--- /dev/null
+++ b/app/presenters/instance_clusterable_presenter.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+class InstanceClusterablePresenter < ClusterablePresenter
+ extend ::Gitlab::Utils::Override
+ include ActionView::Helpers::UrlHelper
+
+ def self.fabricate(clusterable, **attributes)
+ attributes_with_presenter_class = attributes.merge(presenter_class: InstanceClusterablePresenter)
+
+ Gitlab::View::Presenter::Factory
+ .new(clusterable, attributes_with_presenter_class)
+ .fabricate!
+ end
+
+ override :index_path
+ def index_path
+ admin_clusters_path
+ end
+
+ override :new_path
+ def new_path
+ new_admin_cluster_path
+ end
+
+ override :cluster_status_cluster_path
+ def cluster_status_cluster_path(cluster, params = {})
+ cluster_status_admin_cluster_path(cluster, params)
+ end
+
+ override :install_applications_cluster_path
+ def install_applications_cluster_path(cluster, application)
+ install_applications_admin_cluster_path(cluster, application)
+ end
+
+ override :update_applications_cluster_path
+ def update_applications_cluster_path(cluster, application)
+ update_applications_admin_cluster_path(cluster, application)
+ end
+
+ override :cluster_path
+ def cluster_path(cluster, params = {})
+ admin_cluster_path(cluster, params)
+ end
+
+ override :create_user_clusters_path
+ def create_user_clusters_path
+ create_user_admin_clusters_path
+ end
+
+ override :create_gcp_clusters_path
+ def create_gcp_clusters_path
+ create_gcp_admin_clusters_path
+ end
+
+ override :empty_state_help_text
+ def empty_state_help_text
+ s_('ClusterIntegration|Adding an integration will share the cluster across all projects.')
+ end
+
+ override :sidebar_text
+ def sidebar_text
+ s_('ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster.')
+ end
+
+ override :learn_more_link
+ def learn_more_link
+ link_to(s_('ClusterIntegration|Learn more about instance Kubernetes clusters'), help_page_path('user/instance/clusters/index'), target: '_blank', rel: 'noopener noreferrer')
+ end
+end
diff --git a/app/presenters/issue_presenter.rb b/app/presenters/issue_presenter.rb
index c12a202efbc..c9dc0dbf443 100644
--- a/app/presenters/issue_presenter.rb
+++ b/app/presenters/issue_presenter.rb
@@ -4,6 +4,16 @@ class IssuePresenter < Gitlab::View::Presenter::Delegated
presents :issue
def web_url
- Gitlab::UrlBuilder.build(issue)
+ url_builder.url
+ end
+
+ def issue_path
+ url_builder.issue_path(issue)
+ end
+
+ private
+
+ def url_builder
+ @url_builder ||= Gitlab::UrlBuilder.new(issue)
end
end
diff --git a/app/presenters/label_presenter.rb b/app/presenters/label_presenter.rb
new file mode 100644
index 00000000000..1077bf543d9
--- /dev/null
+++ b/app/presenters/label_presenter.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+class LabelPresenter < Gitlab::View::Presenter::Delegated
+ presents :label
+
+ def edit_path
+ case label
+ when GroupLabel then edit_group_label_path(label.group, label)
+ when ProjectLabel then edit_project_label_path(label.project, label)
+ end
+ end
+
+ def destroy_path
+ case label
+ when GroupLabel then group_label_path(label.group, label)
+ when ProjectLabel then project_label_path(label.project, label)
+ end
+ end
+
+ def filter_path(type: :issue)
+ case context_subject
+ when Group
+ send("#{type.to_s.pluralize}_group_path", # rubocop:disable GitlabSecurity/PublicSend
+ context_subject,
+ label_name: [label.name])
+ when Project
+ send("namespace_project_#{type.to_s.pluralize}_path", # rubocop:disable GitlabSecurity/PublicSend
+ context_subject.namespace,
+ context_subject,
+ label_name: [label.name])
+ end
+ end
+
+ def can_subscribe_to_label_in_different_levels?
+ issuable_subject.is_a?(Project) && label.is_a?(GroupLabel)
+ end
+
+ def project_label?
+ label.is_a?(ProjectLabel)
+ end
+
+ def subject_name
+ label.subject.name
+ end
+
+ private
+
+ def context_subject
+ issuable_subject || label.try(:subject)
+ end
+end
diff --git a/app/presenters/member_presenter.rb b/app/presenters/member_presenter.rb
index 9e9b6973b8e..2561c3f0244 100644
--- a/app/presenters/member_presenter.rb
+++ b/app/presenters/member_presenter.rb
@@ -32,6 +32,11 @@ class MemberPresenter < Gitlab::View::Presenter::Delegated
request? && can_update?
end
+ # This functionality is only available in EE.
+ def can_override?
+ false
+ end
+
private
def admin_member_permission
diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb
index 3f7b5bebb74..9c44ed711a6 100644
--- a/app/presenters/merge_request_presenter.rb
+++ b/app/presenters/merge_request_presenter.rb
@@ -22,9 +22,9 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
end
end
- def cancel_merge_when_pipeline_succeeds_path
- if can_cancel_merge_when_pipeline_succeeds?(current_user)
- cancel_merge_when_pipeline_succeeds_project_merge_request_path(project, merge_request)
+ def cancel_auto_merge_path
+ if can_cancel_auto_merge?(current_user)
+ cancel_auto_merge_project_merge_request_path(project, merge_request)
end
end
@@ -216,6 +216,22 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
help_page_path('ci/merge_request_pipelines/index.md')
end
+ def source_branch_link
+ if source_branch_exists?
+ link_to(source_branch, source_branch_commits_path, class: 'ref-name')
+ else
+ content_tag(:span, source_branch, class: 'ref-name')
+ end
+ end
+
+ def target_branch_link
+ if target_branch_exists?
+ link_to(target_branch, target_branch_commits_path, class: 'ref-name')
+ else
+ content_tag(:span, target_branch, class: 'ref-name')
+ end
+ end
+
private
def cached_can_be_reverted?
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index 161eebcfb3f..9afbaf035c7 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -37,7 +37,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
autodevops_anchor_data(show_auto_devops_callout: show_auto_devops_callout),
kubernetes_cluster_anchor_data,
gitlab_ci_anchor_data
- ].compact.reject(&:is_link)
+ ].compact.reject(&:is_link).sort_by.with_index { |item, idx| [item.class_modifier ? 0 : 1, idx] }
end
def empty_repo_statistics_anchors
@@ -259,7 +259,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
if current_user && can?(current_user, :admin_pipeline, project) && repository.gitlab_ci_yml.blank? && !show_auto_devops_callout
if auto_devops_enabled?
AnchorData.new(false,
- statistic_icon('doc-text') + _('Auto DevOps enabled'),
+ statistic_icon('settings') + _('Auto DevOps enabled'),
project_settings_ci_cd_path(project, anchor: 'autodevops-settings'),
'default')
else
diff --git a/app/presenters/tree_entry_presenter.rb b/app/presenters/tree_entry_presenter.rb
new file mode 100644
index 00000000000..7bb10cd1455
--- /dev/null
+++ b/app/presenters/tree_entry_presenter.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class TreeEntryPresenter < Gitlab::View::Presenter::Delegated
+ presents :tree
+
+ def web_url
+ Gitlab::Routing.url_helpers.project_tree_url(tree.repository.project, File.join(tree.commit_id, tree.path))
+ end
+end
diff --git a/app/serializers/analytics_stage_entity.rb b/app/serializers/analytics_stage_entity.rb
index ae7c20c3bba..8bc6da5aeeb 100644
--- a/app/serializers/analytics_stage_entity.rb
+++ b/app/serializers/analytics_stage_entity.rb
@@ -9,7 +9,8 @@ class AnalyticsStageEntity < Grape::Entity
expose :description
expose :median, as: :value do |stage|
- # median returns a BatchLoader instance which we first have to unwrap by using to_i
- !stage.median.to_i.zero? ? distance_of_time_in_words(stage.median) : nil
+ # median returns a BatchLoader instance which we first have to unwrap by using to_f
+ # we use to_f to make sure results below 1 are presented to the end-user
+ stage.median.to_f.nonzero? ? distance_of_time_in_words(stage.median) : nil
end
end
diff --git a/app/serializers/board_serializer.rb b/app/serializers/board_serializer.rb
new file mode 100644
index 00000000000..70a4c9ae282
--- /dev/null
+++ b/app/serializers/board_serializer.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class BoardSerializer < BaseSerializer
+ entity BoardSimpleEntity
+end
diff --git a/app/serializers/board_simple_entity.rb b/app/serializers/board_simple_entity.rb
new file mode 100644
index 00000000000..f297d993e27
--- /dev/null
+++ b/app/serializers/board_simple_entity.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class BoardSimpleEntity < Grape::Entity
+ expose :id
+end
diff --git a/app/serializers/build_details_entity.rb b/app/serializers/build_details_entity.rb
index 62c26809eeb..67e44ee9d10 100644
--- a/app/serializers/build_details_entity.rb
+++ b/app/serializers/build_details_entity.rb
@@ -8,16 +8,18 @@ class BuildDetailsEntity < JobEntity
expose :stuck?, as: :stuck
expose :user, using: UserEntity
expose :runner, using: RunnerEntity
+ expose :metadata, using: BuildMetadataEntity
expose :pipeline, using: PipelineEntity
expose :deployment_status, if: -> (*) { build.starts_environment? } do
expose :deployment_status, as: :status
-
- expose :persisted_environment, as: :environment, with: EnvironmentEntity
+ expose :persisted_environment, as: :environment do |build, options|
+ options.merge(deployment_details: false).yield_self do |opts|
+ EnvironmentEntity.represent(build.persisted_environment, opts)
+ end
+ end
end
- expose :metadata, using: BuildMetadataEntity
-
expose :artifact, if: -> (*) { can?(current_user, :read_build, build) } do
expose :download_path, if: -> (*) { build.artifacts? } do |build|
download_project_job_artifacts_path(project, build)
@@ -40,6 +42,11 @@ class BuildDetailsEntity < JobEntity
end
end
+ expose :report_artifacts,
+ as: :reports,
+ using: JobArtifactReportEntity,
+ if: -> (*) { can?(current_user, :read_build, build) }
+
expose :erased_by, if: -> (*) { build.erased? }, using: UserEntity
expose :erase_path, if: -> (*) { build.erasable? && can?(current_user, :erase_build, build) } do |build|
erase_project_job_path(project, build)
diff --git a/app/serializers/cluster_application_entity.rb b/app/serializers/cluster_application_entity.rb
index a4a2c015c4e..2a916b13f52 100644
--- a/app/serializers/cluster_application_entity.rb
+++ b/app/serializers/cluster_application_entity.rb
@@ -10,4 +10,5 @@ class ClusterApplicationEntity < Grape::Entity
expose :hostname, if: -> (e, _) { e.respond_to?(:hostname) }
expose :email, if: -> (e, _) { e.respond_to?(:email) }
expose :update_available?, as: :update_available, if: -> (e, _) { e.respond_to?(:update_available?) }
+ expose :can_uninstall?, as: :can_uninstall
end
diff --git a/app/serializers/concerns/user_status_tooltip.rb b/app/serializers/concerns/user_status_tooltip.rb
index 633b117d392..a81e377691e 100644
--- a/app/serializers/concerns/user_status_tooltip.rb
+++ b/app/serializers/concerns/user_status_tooltip.rb
@@ -3,7 +3,7 @@
module UserStatusTooltip
extend ActiveSupport::Concern
include ActionView::Helpers::TagHelper
- include ActionView::Context
+ include ::Gitlab::ActionViewOutput::Context
include EmojiHelper
include UsersHelper
diff --git a/app/serializers/deployment_entity.rb b/app/serializers/deployment_entity.rb
index 34ae06278c8..943c707218d 100644
--- a/app/serializers/deployment_entity.rb
+++ b/app/serializers/deployment_entity.rb
@@ -20,16 +20,39 @@ class DeploymentEntity < Grape::Entity
expose :created_at
expose :tag
expose :last?
-
expose :user, using: UserEntity
- expose :commit, using: CommitEntity
- expose :deployable, using: JobEntity
- expose :manual_actions, using: JobEntity, if: -> (*) { can_create_deployment? }
- expose :scheduled_actions, using: JobEntity, if: -> (*) { can_create_deployment? }
+
+ expose :deployable do |deployment, opts|
+ deployment.deployable.yield_self do |deployable|
+ if include_details?
+ JobEntity.represent(deployable, opts)
+ elsif can_read_deployables?
+ { name: deployable.name,
+ build_path: project_job_path(deployable.project, deployable) }
+ end
+ end
+ end
+
+ expose :commit, using: CommitEntity, if: -> (*) { include_details? }
+ expose :manual_actions, using: JobEntity, if: -> (*) { include_details? && can_create_deployment? }
+ expose :scheduled_actions, using: JobEntity, if: -> (*) { include_details? && can_create_deployment? }
private
+ def include_details?
+ options.fetch(:deployment_details, true)
+ end
+
def can_create_deployment?
can?(request.current_user, :create_deployment, request.project)
end
+
+ def can_read_deployables?
+ ##
+ # We intentionally do not check `:read_build, deployment.deployable`
+ # because it triggers a policy evaluation that involves multiple
+ # Gitaly calls that might not be cached.
+ #
+ can?(request.current_user, :read_build, request.project)
+ end
end
diff --git a/app/serializers/issue_entity.rb b/app/serializers/issue_entity.rb
index 914ad628a99..36e601f45c5 100644
--- a/app/serializers/issue_entity.rb
+++ b/app/serializers/issue_entity.rb
@@ -44,4 +44,12 @@ class IssueEntity < IssuableEntity
expose :preview_note_path do |issue|
preview_markdown_path(issue.project, target_type: 'Issue', target_id: issue.iid)
end
+
+ expose :confidential_issues_docs_path, if: -> (issue) { issue.confidential? } do |issue|
+ help_page_path('user/project/issues/confidential_issues.md')
+ end
+
+ expose :locked_discussion_docs_path, if: -> (issue) { issue.discussion_locked? } do |issue|
+ help_page_path('user/discussions/index.md', anchor: 'lock-discussions')
+ end
end
diff --git a/app/serializers/job_artifact_report_entity.rb b/app/serializers/job_artifact_report_entity.rb
new file mode 100644
index 00000000000..4280351a6b0
--- /dev/null
+++ b/app/serializers/job_artifact_report_entity.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class JobArtifactReportEntity < Grape::Entity
+ include RequestAwareEntity
+
+ expose :file_type
+ expose :file_format
+ expose :size
+
+ expose :download_path do |artifact|
+ download_project_job_artifacts_path(artifact.job.project, artifact.job, file_type: artifact.file_format)
+ end
+end
diff --git a/app/serializers/merge_request_widget_entity.rb b/app/serializers/merge_request_widget_entity.rb
index b130f447cce..a428930dbbf 100644
--- a/app/serializers/merge_request_widget_entity.rb
+++ b/app/serializers/merge_request_widget_entity.rb
@@ -9,7 +9,11 @@ class MergeRequestWidgetEntity < IssuableEntity
expose :merge_params
expose :merge_status
expose :merge_user_id
- expose :merge_when_pipeline_succeeds
+ expose :auto_merge_enabled
+ expose :auto_merge_strategy
+ expose :available_auto_merge_strategies do |merge_request|
+ AutoMergeService.new(merge_request.project, current_user).available_strategies(merge_request) # rubocop: disable CodeReuse/ServiceClass
+ end
expose :source_branch
expose :source_branch_protected do |merge_request|
merge_request.source_project.present? && ProtectedBranch.protected?(merge_request.source_project, merge_request.source_branch)
@@ -182,8 +186,8 @@ class MergeRequestWidgetEntity < IssuableEntity
presenter(merge_request).remove_wip_path
end
- expose :cancel_merge_when_pipeline_succeeds_path do |merge_request|
- presenter(merge_request).cancel_merge_when_pipeline_succeeds_path
+ expose :cancel_auto_merge_path do |merge_request|
+ presenter(merge_request).cancel_auto_merge_path
end
expose :create_issue_to_resolve_discussions_path do |merge_request|
diff --git a/app/serializers/pipeline_details_entity.rb b/app/serializers/pipeline_details_entity.rb
index d78ad4af4dc..dfef4364965 100644
--- a/app/serializers/pipeline_details_entity.rb
+++ b/app/serializers/pipeline_details_entity.rb
@@ -1,8 +1,11 @@
# frozen_string_literal: true
class PipelineDetailsEntity < PipelineEntity
+ expose :flags do
+ expose :latest?, as: :latest
+ end
+
expose :details do
- expose :ordered_stages, as: :stages, using: StageEntity
expose :artifacts, using: BuildArtifactEntity
expose :manual_actions, using: BuildActionEntity
expose :scheduled_actions, using: BuildActionEntity
diff --git a/app/serializers/pipeline_entity.rb b/app/serializers/pipeline_entity.rb
index 8fe5df81e6c..ec2698ecbe3 100644
--- a/app/serializers/pipeline_entity.rb
+++ b/app/serializers/pipeline_entity.rb
@@ -4,6 +4,7 @@ class PipelineEntity < Grape::Entity
include RequestAwareEntity
expose :id
+ expose :iid
expose :user, using: UserEntity
expose :active?, as: :active
@@ -20,7 +21,6 @@ class PipelineEntity < Grape::Entity
end
expose :flags do
- expose :latest?, as: :latest
expose :stuck?, as: :stuck
expose :auto_devops_source?, as: :auto_devops
expose :merge_request_event?, as: :merge_request
@@ -34,6 +34,7 @@ class PipelineEntity < Grape::Entity
expose :details do
expose :detailed_status, as: :status, with: DetailedStatusEntity
+ expose :ordered_stages, as: :stages, using: StageEntity
expose :duration
expose :finished_at
end
diff --git a/app/serializers/test_case_entity.rb b/app/serializers/test_case_entity.rb
index ec60055ba5b..5c915c1302c 100644
--- a/app/serializers/test_case_entity.rb
+++ b/app/serializers/test_case_entity.rb
@@ -3,6 +3,7 @@
class TestCaseEntity < Grape::Entity
expose :status
expose :name
+ expose :classname
expose :execution_time
expose :system_output
expose :stack_trace
diff --git a/app/services/auto_merge/base_service.rb b/app/services/auto_merge/base_service.rb
new file mode 100644
index 00000000000..d726085b89a
--- /dev/null
+++ b/app/services/auto_merge/base_service.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+module AutoMerge
+ class BaseService < ::BaseService
+ include Gitlab::Utils::StrongMemoize
+
+ def execute(merge_request)
+ merge_request.merge_params.merge!(params)
+ merge_request.auto_merge_enabled = true
+ merge_request.merge_user = current_user
+ merge_request.auto_merge_strategy = strategy
+
+ return :failed unless merge_request.save
+
+ yield if block_given?
+
+ # Notify the event that auto merge is enabled or merge param is updated
+ AutoMergeProcessWorker.perform_async(merge_request.id)
+
+ strategy.to_sym
+ end
+
+ def update(merge_request)
+ merge_request.merge_params.merge!(params)
+
+ return :failed unless merge_request.save
+
+ strategy.to_sym
+ end
+
+ def cancel(merge_request)
+ if cancel_auto_merge(merge_request)
+ yield if block_given?
+
+ success
+ else
+ error("Can't cancel the automatic merge", 406)
+ end
+ end
+
+ private
+
+ def strategy
+ strong_memoize(:strategy) do
+ self.class.name.demodulize.remove('Service').underscore
+ end
+ end
+
+ def cancel_auto_merge(merge_request)
+ merge_request.auto_merge_enabled = false
+ merge_request.merge_user = nil
+
+ merge_request.merge_params&.except!(
+ 'should_remove_source_branch',
+ 'commit_message',
+ 'squash_commit_message',
+ 'auto_merge_strategy'
+ )
+
+ merge_request.save
+ end
+ end
+end
diff --git a/app/services/auto_merge/merge_when_pipeline_succeeds_service.rb b/app/services/auto_merge/merge_when_pipeline_succeeds_service.rb
new file mode 100644
index 00000000000..c41073a73e9
--- /dev/null
+++ b/app/services/auto_merge/merge_when_pipeline_succeeds_service.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module AutoMerge
+ class MergeWhenPipelineSucceedsService < AutoMerge::BaseService
+ def execute(merge_request)
+ super do
+ if merge_request.saved_change_to_auto_merge_enabled?
+ SystemNoteService.merge_when_pipeline_succeeds(merge_request, project, current_user, merge_request.diff_head_commit)
+ end
+ end
+ end
+
+ def process(merge_request)
+ return unless merge_request.actual_head_pipeline&.success?
+ return unless merge_request.mergeable?
+
+ merge_request.merge_async(merge_request.merge_user_id, merge_request.merge_params)
+ end
+
+ def cancel(merge_request)
+ super do
+ SystemNoteService.cancel_merge_when_pipeline_succeeds(merge_request, @project, @current_user)
+ end
+ end
+
+ def available_for?(merge_request)
+ merge_request.actual_head_pipeline&.active?
+ end
+ end
+end
diff --git a/app/services/auto_merge_service.rb b/app/services/auto_merge_service.rb
new file mode 100644
index 00000000000..926d2f5fc66
--- /dev/null
+++ b/app/services/auto_merge_service.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+class AutoMergeService < BaseService
+ STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS = 'merge_when_pipeline_succeeds'.freeze
+ STRATEGIES = [STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS].freeze
+
+ class << self
+ def all_strategies
+ STRATEGIES
+ end
+
+ def get_service_class(strategy)
+ return unless all_strategies.include?(strategy)
+
+ "::AutoMerge::#{strategy.camelize}Service".constantize
+ end
+ end
+
+ def execute(merge_request, strategy)
+ service = get_service_instance(strategy)
+
+ return :failed unless service&.available_for?(merge_request)
+
+ service.execute(merge_request)
+ end
+
+ def update(merge_request)
+ return :failed unless merge_request.auto_merge_enabled?
+
+ get_service_instance(merge_request.auto_merge_strategy).update(merge_request)
+ end
+
+ def process(merge_request)
+ return unless merge_request.auto_merge_enabled?
+
+ get_service_instance(merge_request.auto_merge_strategy).process(merge_request)
+ end
+
+ def cancel(merge_request)
+ return error("Can't cancel the automatic merge", 406) unless merge_request.auto_merge_enabled?
+
+ get_service_instance(merge_request.auto_merge_strategy).cancel(merge_request)
+ end
+
+ def available_strategies(merge_request)
+ self.class.all_strategies.select do |strategy|
+ get_service_instance(strategy).available_for?(merge_request)
+ end
+ end
+
+ private
+
+ def get_service_instance(strategy)
+ self.class.get_service_class(strategy)&.new(project, current_user, params)
+ end
+end
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index 252f5778644..c17712355af 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -104,17 +104,11 @@ module Ci
end
def schedule_head_pipeline_update
- related_merge_requests.each do |merge_request|
+ pipeline.all_merge_requests.opened.each do |merge_request|
UpdateHeadPipelineForMergeRequestWorker.perform_async(merge_request.id)
end
end
- # rubocop: disable CodeReuse/ActiveRecord
- def related_merge_requests
- pipeline.project.source_of_merge_requests.opened.where(source_branch: pipeline.ref)
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
def extra_options(options = {})
# In Ruby 2.4, even when options is empty, f(**options) doesn't work when f
# doesn't have any parameters. We reproduce the Ruby 2.5 behavior by
diff --git a/app/services/ci/pipeline_schedule_service.rb b/app/services/ci/pipeline_schedule_service.rb
new file mode 100644
index 00000000000..5b5e9a26520
--- /dev/null
+++ b/app/services/ci/pipeline_schedule_service.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Ci
+ class PipelineScheduleService < BaseService
+ def execute(schedule)
+ # Ensure `next_run_at` is set properly before creating a pipeline.
+ # Otherwise, multiple pipelines could be created in a short interval.
+ schedule.schedule_next_run!
+
+ RunPipelineScheduleWorker.perform_async(schedule.id, schedule.owner&.id)
+ end
+ end
+end
diff --git a/app/services/ci/play_manual_stage_service.rb b/app/services/ci/play_manual_stage_service.rb
new file mode 100644
index 00000000000..2497fc52e6b
--- /dev/null
+++ b/app/services/ci/play_manual_stage_service.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Ci
+ class PlayManualStageService < BaseService
+ def initialize(project, current_user, params)
+ super
+
+ @pipeline = params[:pipeline]
+ end
+
+ def execute(stage)
+ stage.builds.manual.each do |build|
+ next unless build.playable?
+
+ build.play(current_user)
+ rescue Gitlab::Access::AccessDeniedError
+ logger.error(message: 'Unable to play manual action', build_id: build.id)
+ end
+ end
+
+ private
+
+ attr_reader :pipeline, :current_user
+
+ def logger
+ Gitlab::AppLogger
+ end
+ end
+end
diff --git a/app/services/ci/register_job_service.rb b/app/services/ci/register_job_service.rb
index 6707a1363d0..dedab98b56d 100644
--- a/app/services/ci/register_job_service.rb
+++ b/app/services/ci/register_job_service.rb
@@ -6,7 +6,7 @@ module Ci
class RegisterJobService
attr_reader :runner
- JOB_QUEUE_DURATION_SECONDS_BUCKETS = [1, 3, 10, 30].freeze
+ JOB_QUEUE_DURATION_SECONDS_BUCKETS = [1, 3, 10, 30, 60, 300].freeze
JOBS_RUNNING_FOR_PROJECT_MAX_BUCKET = 5.freeze
Result = Struct.new(:build, :valid?)
@@ -36,6 +36,11 @@ module Ci
builds = builds.with_any_tags
end
+ # pick builds that older than specified age
+ if params.key?(:job_age)
+ builds = builds.queued_before(params[:job_age].seconds.ago)
+ end
+
builds.each do |build|
next unless runner.can_pick?(build)
diff --git a/app/services/ci/stop_environments_service.rb b/app/services/ci/stop_environments_service.rb
index 973ae5ce5aa..d9a800791f2 100644
--- a/app/services/ci/stop_environments_service.rb
+++ b/app/services/ci/stop_environments_service.rb
@@ -9,12 +9,11 @@ module Ci
return unless @ref.present?
- environments.each do |environment|
- next unless environment.stop_action_available?
- next unless can?(current_user, :stop_environment, environment)
+ environments.each { |environment| stop(environment) }
+ end
- environment.stop_with_action!(current_user)
- end
+ def execute_for_merge_request(merge_request)
+ merge_request.environments.each { |environment| stop(environment) }
end
private
@@ -24,5 +23,12 @@ module Ci
.new(project, current_user, ref: @ref, recently_updated: true)
.execute
end
+
+ def stop(environment)
+ return unless environment.stop_action_available?
+ return unless can?(current_user, :stop_environment, environment)
+
+ environment.stop_with_action!(current_user)
+ end
end
end
diff --git a/app/services/clusters/applications/base_service.rb b/app/services/clusters/applications/base_service.rb
index 14a45437287..a9feb60be6e 100644
--- a/app/services/clusters/applications/base_service.rb
+++ b/app/services/clusters/applications/base_service.rb
@@ -81,7 +81,7 @@ module Clusters
oauth_application_params = {
name: params[:application],
redirect_uri: application.callback_url,
- scopes: 'api read_user openid',
+ scopes: application.oauth_scopes,
owner: current_user
}
diff --git a/app/services/clusters/applications/check_installation_progress_service.rb b/app/services/clusters/applications/check_installation_progress_service.rb
index c592d608b89..3c6803d24e6 100644
--- a/app/services/clusters/applications/check_installation_progress_service.rb
+++ b/app/services/clusters/applications/check_installation_progress_service.rb
@@ -37,7 +37,7 @@ module Clusters
end
def check_timeout
- if timeouted?
+ if timed_out?
begin
app.make_errored!("Operation timed out. Check pod logs for #{pod_name} for more details.")
end
@@ -51,8 +51,8 @@ module Clusters
install_command.pod_name
end
- def timeouted?
- Time.now.utc - app.updated_at.to_time.utc > ClusterWaitForAppInstallationWorker::TIMEOUT
+ def timed_out?
+ Time.now.utc - app.updated_at.utc > ClusterWaitForAppInstallationWorker::TIMEOUT
end
def remove_installation_pod
diff --git a/app/services/clusters/applications/check_uninstall_progress_service.rb b/app/services/clusters/applications/check_uninstall_progress_service.rb
new file mode 100644
index 00000000000..8786d295d6a
--- /dev/null
+++ b/app/services/clusters/applications/check_uninstall_progress_service.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Applications
+ class CheckUninstallProgressService < BaseHelmService
+ def execute
+ return unless app.uninstalling?
+
+ case installation_phase
+ when Gitlab::Kubernetes::Pod::SUCCEEDED
+ on_success
+ when Gitlab::Kubernetes::Pod::FAILED
+ on_failed
+ else
+ check_timeout
+ end
+ rescue Kubeclient::HttpError => e
+ log_error(e)
+
+ app.make_errored!(_('Kubernetes error: %{error_code}') % { error_code: e.error_code })
+ end
+
+ private
+
+ def on_success
+ app.destroy!
+ rescue StandardError => e
+ app.make_errored!(_('Application uninstalled but failed to destroy: %{error_message}') % { error_message: e.message })
+ ensure
+ remove_installation_pod
+ end
+
+ def on_failed
+ app.make_errored!(_('Operation failed. Check pod logs for %{pod_name} for more details.') % { pod_name: pod_name })
+ end
+
+ def check_timeout
+ if timed_out?
+ app.make_errored!(_('Operation timed out. Check pod logs for %{pod_name} for more details.') % { pod_name: pod_name })
+ else
+ WaitForUninstallAppWorker.perform_in(WaitForUninstallAppWorker::INTERVAL, app.name, app.id)
+ end
+ end
+
+ def pod_name
+ app.uninstall_command.pod_name
+ end
+
+ def timed_out?
+ Time.now.utc - app.updated_at.utc > WaitForUninstallAppWorker::TIMEOUT
+ end
+
+ def remove_installation_pod
+ helm_api.delete_pod!(pod_name)
+ end
+
+ def installation_phase
+ helm_api.status(pod_name)
+ end
+ end
+ end
+end
diff --git a/app/services/clusters/applications/create_service.rb b/app/services/clusters/applications/create_service.rb
index ae36da7b3dd..f723c42c049 100644
--- a/app/services/clusters/applications/create_service.rb
+++ b/app/services/clusters/applications/create_service.rb
@@ -10,8 +10,8 @@ module Clusters
end
def builder
- cluster.method("application_#{application_name}").call ||
- cluster.method("build_application_#{application_name}").call
+ cluster.public_send(:"application_#{application_name}") || # rubocop:disable GitlabSecurity/PublicSend
+ cluster.public_send(:"build_application_#{application_name}") # rubocop:disable GitlabSecurity/PublicSend
end
end
end
diff --git a/app/services/clusters/applications/destroy_service.rb b/app/services/clusters/applications/destroy_service.rb
new file mode 100644
index 00000000000..f3a4c4f754a
--- /dev/null
+++ b/app/services/clusters/applications/destroy_service.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Applications
+ class DestroyService < ::Clusters::Applications::BaseService
+ def execute(_request)
+ instantiate_application.tap do |application|
+ break unless application.can_uninstall?
+
+ application.make_scheduled!
+
+ Clusters::Applications::UninstallWorker.perform_async(application.name, application.id)
+ end
+ end
+
+ private
+
+ def builder
+ cluster.public_send(:"application_#{application_name}") # rubocop:disable GitlabSecurity/PublicSend
+ end
+ end
+ end
+end
diff --git a/app/services/clusters/applications/uninstall_service.rb b/app/services/clusters/applications/uninstall_service.rb
new file mode 100644
index 00000000000..50c8d806c14
--- /dev/null
+++ b/app/services/clusters/applications/uninstall_service.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Applications
+ class UninstallService < BaseHelmService
+ def execute
+ return unless app.scheduled?
+
+ app.make_uninstalling!
+ uninstall
+ end
+
+ private
+
+ def uninstall
+ helm_api.uninstall(app.uninstall_command)
+
+ Clusters::Applications::WaitForUninstallAppWorker.perform_in(
+ Clusters::Applications::WaitForUninstallAppWorker::INTERVAL, app.name, app.id)
+ rescue Kubeclient::HttpError => e
+ log_error(e)
+ app.make_errored!("Kubernetes error: #{e.error_code}")
+ rescue StandardError => e
+ log_error(e)
+ app.make_errored!('Failed to uninstall.')
+ end
+ end
+ end
+end
diff --git a/app/services/clusters/applications/update_service.rb b/app/services/clusters/applications/update_service.rb
index 5071c31839c..0fa937da865 100644
--- a/app/services/clusters/applications/update_service.rb
+++ b/app/services/clusters/applications/update_service.rb
@@ -10,7 +10,7 @@ module Clusters
end
def builder
- cluster.method("application_#{application_name}").call
+ cluster.public_send(:"application_#{application_name}") # rubocop:disable GitlabSecurity/PublicSend
end
end
end
diff --git a/app/services/clusters/build_service.rb b/app/services/clusters/build_service.rb
index 8de73831164..b1ac5549e30 100644
--- a/app/services/clusters/build_service.rb
+++ b/app/services/clusters/build_service.rb
@@ -12,6 +12,8 @@ module Clusters
cluster.cluster_type = :project_type
when ::Group
cluster.cluster_type = :group_type
+ when Instance
+ cluster.cluster_type = :instance_type
else
raise NotImplementedError
end
diff --git a/app/services/clusters/create_service.rb b/app/services/clusters/create_service.rb
index 5a9da053780..886e484caaf 100644
--- a/app/services/clusters/create_service.rb
+++ b/app/services/clusters/create_service.rb
@@ -38,6 +38,8 @@ module Clusters
{ cluster_type: :project_type, projects: [clusterable] }
when ::Group
{ cluster_type: :group_type, groups: [clusterable] }
+ when Instance
+ { cluster_type: :instance_type }
else
raise NotImplementedError
end
diff --git a/app/services/clusters/refresh_service.rb b/app/services/clusters/refresh_service.rb
index 7c82b98a33f..3752a306793 100644
--- a/app/services/clusters/refresh_service.rb
+++ b/app/services/clusters/refresh_service.rb
@@ -21,7 +21,7 @@ module Clusters
private_class_method :projects_with_missing_kubernetes_namespaces_for_cluster
def self.clusters_with_missing_kubernetes_namespaces_for_project(project)
- project.all_clusters.missing_kubernetes_namespace(project.kubernetes_namespaces)
+ project.clusters.managed.missing_kubernetes_namespace(project.kubernetes_namespaces)
end
private_class_method :clusters_with_missing_kubernetes_namespaces_for_project
diff --git a/app/services/compare_service.rb b/app/services/compare_service.rb
index 3adf8a0c1a1..3f0aedfbfb2 100644
--- a/app/services/compare_service.rb
+++ b/app/services/compare_service.rb
@@ -3,7 +3,7 @@
require 'securerandom'
# Compare 2 refs for one repo or between repositories
-# and return Gitlab::Git::Compare object that responds to commits and diffs
+# and return Compare object that responds to commits and diffs
class CompareService
attr_reader :start_project, :start_ref_name
@@ -15,7 +15,7 @@ class CompareService
def execute(target_project, target_ref, base_sha: nil, straight: false)
raw_compare = target_project.repository.compare_source_branch(target_ref, start_project.repository, start_ref_name, straight: straight)
- return unless raw_compare
+ return unless raw_compare && raw_compare.base && raw_compare.head
Compare.new(raw_compare,
target_project,
diff --git a/app/services/concerns/users/participable_service.rb b/app/services/concerns/users/participable_service.rb
index a3cc6014fd3..1c828234f1b 100644
--- a/app/services/concerns/users/participable_service.rb
+++ b/app/services/concerns/users/participable_service.rb
@@ -29,7 +29,7 @@ module Users
def groups
group_counts = GroupMember
- .in_groups(current_user.authorized_groups)
+ .of_groups(current_user.authorized_groups)
.non_request
.count_users_by_group_id
diff --git a/app/services/delete_branch_service.rb b/app/services/delete_branch_service.rb
index 4c3ac19f754..fd41ce54486 100644
--- a/app/services/delete_branch_service.rb
+++ b/app/services/delete_branch_service.rb
@@ -6,27 +6,25 @@ class DeleteBranchService < BaseService
branch = repository.find_branch(branch_name)
unless current_user.can?(:push_code, project)
- return error('You dont have push access to repo', 405)
+ return ServiceResponse.error(
+ message: 'You dont have push access to repo',
+ http_status: 405)
end
unless branch
- return error('No such branch', 404)
+ return ServiceResponse.error(
+ message: 'No such branch',
+ http_status: 404)
end
if repository.rm_branch(current_user, branch_name)
- success('Branch was deleted')
+ ServiceResponse.success(message: 'Branch was deleted')
else
- error('Failed to remove branch')
+ ServiceResponse.error(
+ message: 'Failed to remove branch',
+ http_status: 400)
end
rescue Gitlab::Git::PreReceiveError => ex
- error(ex.message)
- end
-
- def error(message, return_code = 400)
- super(message).merge(return_code: return_code)
- end
-
- def success(message)
- super().merge(message: message)
+ ServiceResponse.error(message: ex.message, http_status: 400)
end
end
diff --git a/app/services/git/base_hooks_service.rb b/app/services/git/base_hooks_service.rb
index a8478e3a904..d30df34e54b 100644
--- a/app/services/git/base_hooks_service.rb
+++ b/app/services/git/base_hooks_service.rb
@@ -17,6 +17,8 @@ module Git
# Not a hook, but it needs access to the list of changed commits
enqueue_invalidate_cache
+ update_remote_mirrors
+
push_data
end
@@ -73,13 +75,13 @@ module Git
def push_data
@push_data ||= Gitlab::DataBuilder::Push.build(
- project,
- current_user,
- params[:oldrev],
- params[:newrev],
- params[:ref],
- limited_commits,
- event_message,
+ project: project,
+ user: current_user,
+ oldrev: params[:oldrev],
+ newrev: params[:newrev],
+ ref: params[:ref],
+ commits: limited_commits,
+ message: event_message,
commits_count: commits_count,
push_options: params[:push_options] || {}
)
@@ -92,5 +94,12 @@ module Git
def pipeline_options
{}
end
+
+ def update_remote_mirrors
+ return unless project.has_remote_mirror?
+
+ project.mark_stuck_remote_mirrors_as_failed!
+ project.update_remote_mirrors
+ end
end
end
diff --git a/app/services/git/branch_hooks_service.rb b/app/services/git/branch_hooks_service.rb
index d21a6bb1b9a..4aee48f22e7 100644
--- a/app/services/git/branch_hooks_service.rb
+++ b/app/services/git/branch_hooks_service.rb
@@ -20,8 +20,7 @@ module Git
strong_memoize(:commits) do
if creating_default_branch?
# The most recent PROCESS_COMMIT_LIMIT commits in the default branch
- offset = [count_commits_in_branch - PROCESS_COMMIT_LIMIT, 0].max
- project.repository.commits(params[:newrev], offset: offset, limit: PROCESS_COMMIT_LIMIT)
+ project.repository.commits(params[:newrev], limit: PROCESS_COMMIT_LIMIT)
elsif creating_branch?
# Use the pushed commits that aren't reachable by the default branch
# as a heuristic. This may include more commits than are actually
@@ -84,9 +83,6 @@ module Git
# Schedules processing of commit messages
def enqueue_process_commit_messages
- # don't process commits for the initial push to the default branch
- return if creating_default_branch?
-
limited_commits.each do |commit|
next unless commit.matches_cross_reference_regex?
diff --git a/app/services/git/branch_push_service.rb b/app/services/git/branch_push_service.rb
index da053ce80c7..c4910180787 100644
--- a/app/services/git/branch_push_service.rb
+++ b/app/services/git/branch_push_service.rb
@@ -27,7 +27,6 @@ module Git
execute_related_hooks
perform_housekeeping
- update_remote_mirrors
stop_environments
true
@@ -48,7 +47,7 @@ module Git
def enqueue_detect_repository_languages
return unless default_branch?
- DetectRepositoryLanguagesWorker.perform_async(project.id, current_user.id)
+ DetectRepositoryLanguagesWorker.perform_async(project.id)
end
# Only stop environments if the ref is a branch that is being deleted
diff --git a/app/services/issuable/clone/content_rewriter.rb b/app/services/issuable/clone/content_rewriter.rb
index e1e0b75085d..00d7078859d 100644
--- a/app/services/issuable/clone/content_rewriter.rb
+++ b/app/services/issuable/clone/content_rewriter.rb
@@ -28,6 +28,7 @@ module Issuable
new_params = {
project: new_entity.project, noteable: new_entity,
note: rewrite_content(new_note.note),
+ note_html: nil,
created_at: note.created_at,
updated_at: note.updated_at
}
diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb
index e5cc12e6082..805721212ba 100644
--- a/app/services/issues/close_service.rb
+++ b/app/services/issues/close_service.rb
@@ -7,7 +7,7 @@ module Issues
return issue unless can?(current_user, :update_issue, issue)
close_issue(issue,
- commit: commit,
+ closed_via: commit,
notifications: notifications,
system_note: system_note)
end
@@ -17,9 +17,9 @@ module Issues
#
# The code calling this method is responsible for ensuring that a user is
# allowed to close the given issue.
- def close_issue(issue, commit: nil, notifications: true, system_note: true)
+ def close_issue(issue, closed_via: nil, notifications: true, system_note: true)
if project.jira_tracker? && project.jira_service.active && issue.is_a?(ExternalIssue)
- project.jira_service.close_issue(commit, issue)
+ project.jira_service.close_issue(closed_via, issue)
todo_service.close_issue(issue, current_user)
return issue
end
@@ -27,8 +27,11 @@ module Issues
if project.issues_enabled? && issue.close
issue.update(closed_by: current_user)
event_service.close_issue(issue, current_user)
- create_note(issue, commit) if system_note
- notification_service.async.close_issue(issue, current_user) if notifications
+ create_note(issue, closed_via) if system_note
+
+ closed_via = _("commit %{commit_id}") % { commit_id: closed_via.id } if closed_via.is_a?(Commit)
+
+ notification_service.async.close_issue(issue, current_user, closed_via: closed_via) if notifications
todo_service.close_issue(issue, current_user)
execute_hooks(issue, 'close')
invalidate_cache_counts(issue, users: issue.assignees)
diff --git a/app/services/lfs/file_transformer.rb b/app/services/lfs/file_transformer.rb
index 6ecf583cb6a..5239fe1b6e3 100644
--- a/app/services/lfs/file_transformer.rb
+++ b/app/services/lfs/file_transformer.rb
@@ -24,7 +24,7 @@ module Lfs
def new_file(file_path, file_content, encoding: nil)
if project.lfs_enabled? && lfs_file?(file_path)
- file_content = Base64.decode64(file_content) if encoding == 'base64'
+ file_content = parse_file_content(file_content, encoding: encoding)
lfs_pointer_file = Gitlab::Git::LfsPointerFile.new(file_content)
lfs_object = create_lfs_object!(lfs_pointer_file, file_content)
@@ -66,5 +66,12 @@ module Lfs
def link_lfs_object!(lfs_object)
project.lfs_objects << lfs_object
end
+
+ def parse_file_content(file_content, encoding: nil)
+ return file_content.read if file_content.respond_to?(:read)
+ return Base64.decode64(file_content) if encoding == 'base64'
+
+ file_content
+ end
end
end
diff --git a/app/services/members/create_service.rb b/app/services/members/create_service.rb
index f6bad74736c..d6b17ec10be 100644
--- a/app/services/members/create_service.rb
+++ b/app/services/members/create_service.rb
@@ -23,7 +23,16 @@ module Members
members.each do |member|
if member.errors.any?
- errors << "#{member.user.username}: #{member.errors.full_messages.to_sentence}"
+ current_error =
+ # Invited users may not have an associated user
+ if member.user.present?
+ "#{member.user.username}: "
+ else
+ ""
+ end
+
+ current_error += member.errors.full_messages.to_sentence
+ errors << current_error
else
after_execute(member: member)
end
diff --git a/app/services/members/destroy_service.rb b/app/services/members/destroy_service.rb
index f9717a9426b..c8d5e563cd8 100644
--- a/app/services/members/destroy_service.rb
+++ b/app/services/members/destroy_service.rb
@@ -45,7 +45,7 @@ module Members
def delete_subgroup_members(member)
groups = member.group.descendants
- GroupMember.in_groups(groups).with_user(member.user).each do |group_member|
+ GroupMember.of_groups(groups).with_user(member.user).each do |group_member|
self.class.new(current_user).execute(group_member, skip_authorization: @skip_auth, skip_subresources: true)
end
end
diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb
index b8334a87f6d..c34fbeb2adb 100644
--- a/app/services/merge_requests/base_service.rb
+++ b/app/services/merge_requests/base_service.rb
@@ -24,6 +24,11 @@ module MergeRequests
end
end
+ def cleanup_environments(merge_request)
+ Ci::StopEnvironmentsService.new(merge_request.source_project, current_user)
+ .execute_for_merge_request(merge_request)
+ end
+
private
def handle_wip_event(merge_request)
@@ -55,31 +60,7 @@ module MergeRequests
end
def create_pipeline_for(merge_request, user)
- return unless can_create_pipeline_for?(merge_request)
-
- create_detached_merge_request_pipeline(merge_request, user)
- end
-
- def create_detached_merge_request_pipeline(merge_request, user)
- if can_use_merge_request_ref?(merge_request)
- Ci::CreatePipelineService.new(merge_request.source_project, user,
- ref: merge_request.ref_path)
- .execute(:merge_request_event, merge_request: merge_request)
- else
- Ci::CreatePipelineService.new(merge_request.source_project, user,
- ref: merge_request.source_branch)
- .execute(:merge_request_event, merge_request: merge_request)
- end
- end
-
- def can_create_pipeline_for?(merge_request)
- ##
- # UpdateMergeRequestsWorker could be retried by an exception.
- # pipelines for merge request should not be recreated in such case.
- return false if merge_request.merge_request_pipeline_exists?
- return false if merge_request.has_no_commits?
-
- true
+ MergeRequests::CreatePipelineService.new(project, user).execute(merge_request)
end
def can_use_merge_request_ref?(merge_request)
@@ -87,6 +68,10 @@ module MergeRequests
!merge_request.for_fork?
end
+ def cancel_auto_merge(merge_request)
+ AutoMergeService.new(project, current_user).cancel(merge_request)
+ end
+
# Returns all origin and fork merge requests from `@project` satisfying passed arguments.
# rubocop: disable CodeReuse/ActiveRecord
def merge_requests_for(source_branch, mr_states: [:opened])
diff --git a/app/services/merge_requests/close_service.rb b/app/services/merge_requests/close_service.rb
index 04527bb9713..b81a4dd81d2 100644
--- a/app/services/merge_requests/close_service.rb
+++ b/app/services/merge_requests/close_service.rb
@@ -17,6 +17,8 @@ module MergeRequests
execute_hooks(merge_request, 'close')
invalidate_cache_counts(merge_request, users: merge_request.assignees)
merge_request.update_project_counter_caches
+ cleanup_environments(merge_request)
+ cancel_auto_merge(merge_request)
end
merge_request
diff --git a/app/services/merge_requests/create_pipeline_service.rb b/app/services/merge_requests/create_pipeline_service.rb
new file mode 100644
index 00000000000..03246cc1920
--- /dev/null
+++ b/app/services/merge_requests/create_pipeline_service.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class CreatePipelineService < MergeRequests::BaseService
+ def execute(merge_request)
+ return unless can_create_pipeline_for?(merge_request)
+
+ create_detached_merge_request_pipeline(merge_request)
+ end
+
+ def create_detached_merge_request_pipeline(merge_request)
+ if can_use_merge_request_ref?(merge_request)
+ Ci::CreatePipelineService.new(merge_request.source_project, current_user,
+ ref: merge_request.ref_path)
+ .execute(:merge_request_event, merge_request: merge_request)
+ else
+ Ci::CreatePipelineService.new(merge_request.source_project, current_user,
+ ref: merge_request.source_branch)
+ .execute(:merge_request_event, merge_request: merge_request)
+ end
+ end
+
+ def can_create_pipeline_for?(merge_request)
+ ##
+ # UpdateMergeRequestsWorker could be retried by an exception.
+ # pipelines for merge request should not be recreated in such case.
+ return false if !allow_duplicate && merge_request.find_actual_head_pipeline&.triggered_by_merge_request?
+ return false if merge_request.has_no_commits?
+
+ true
+ end
+
+ def allow_duplicate
+ params[:allow_duplicate]
+ end
+ end
+end
diff --git a/app/services/merge_requests/merge_when_pipeline_succeeds_service.rb b/app/services/merge_requests/merge_when_pipeline_succeeds_service.rb
deleted file mode 100644
index 973e5b64e88..00000000000
--- a/app/services/merge_requests/merge_when_pipeline_succeeds_service.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-module MergeRequests
- class MergeWhenPipelineSucceedsService < MergeRequests::BaseService
- # Marks the passed `merge_request` to be merged when the pipeline succeeds or
- # updates the params for the automatic merge
- def execute(merge_request)
- merge_request.merge_params.merge!(params)
-
- # The service is also called when the merge params are updated.
- already_approved = merge_request.merge_when_pipeline_succeeds?
-
- unless already_approved
- merge_request.merge_when_pipeline_succeeds = true
- merge_request.merge_user = @current_user
-
- SystemNoteService.merge_when_pipeline_succeeds(merge_request, @project, @current_user, merge_request.diff_head_commit)
- end
-
- merge_request.save
- end
-
- # Triggers the automatic merge of merge_request once the pipeline succeeds
- def trigger(pipeline)
- return unless pipeline.success?
-
- pipeline_merge_requests(pipeline) do |merge_request|
- next unless merge_request.merge_when_pipeline_succeeds?
- next unless merge_request.mergeable?
-
- merge_request.merge_async(merge_request.merge_user_id, merge_request.merge_params)
- end
- end
-
- # Cancels the automatic merge
- def cancel(merge_request)
- if merge_request.merge_when_pipeline_succeeds? && merge_request.open?
- merge_request.reset_merge_when_pipeline_succeeds
- SystemNoteService.cancel_merge_when_pipeline_succeeds(merge_request, @project, @current_user)
-
- success
- else
- error("Can't cancel the automatic merge", 406)
- end
- end
- end
-end
diff --git a/app/services/merge_requests/post_merge_service.rb b/app/services/merge_requests/post_merge_service.rb
index f26e3bee06f..c13f7dd5088 100644
--- a/app/services/merge_requests/post_merge_service.rb
+++ b/app/services/merge_requests/post_merge_service.rb
@@ -18,6 +18,7 @@ module MergeRequests
invalidate_cache_counts(merge_request, users: merge_request.assignees)
merge_request.update_project_counter_caches
delete_non_latest_diffs(merge_request)
+ cleanup_environments(merge_request)
end
private
diff --git a/app/services/merge_requests/rebase_service.rb b/app/services/merge_requests/rebase_service.rb
index 31b3ebf311e..4b9921c28ba 100644
--- a/app/services/merge_requests/rebase_service.rb
+++ b/app/services/merge_requests/rebase_service.rb
@@ -20,17 +20,7 @@ module MergeRequests
return false
end
- log_prefix = "#{self.class.name} info (#{merge_request.to_reference(full: true)}):"
-
- Gitlab::GitLogger.info("#{log_prefix} rebase started")
-
- rebase_sha = repository.rebase(current_user, merge_request)
-
- Gitlab::GitLogger.info("#{log_prefix} rebased to #{rebase_sha}")
-
- merge_request.update(rebase_commit_sha: rebase_sha)
-
- Gitlab::GitLogger.info("#{log_prefix} rebase SHA saved: #{rebase_sha}")
+ repository.rebase(current_user, merge_request)
true
rescue => e
diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb
index 3abea1ad1ae..4b199bd8fa8 100644
--- a/app/services/merge_requests/refresh_service.rb
+++ b/app/services/merge_requests/refresh_service.rb
@@ -24,7 +24,7 @@ module MergeRequests
reload_merge_requests
outdate_suggestions
refresh_pipelines_on_merge_requests
- reset_merge_when_pipeline_succeeds
+ cancel_auto_merges
mark_pending_todos_done
cache_merge_requests_closing_issues
@@ -142,8 +142,10 @@ module MergeRequests
end
end
- def reset_merge_when_pipeline_succeeds
- merge_requests_for_source_branch.each(&:reset_merge_when_pipeline_succeeds)
+ def cancel_auto_merges
+ merge_requests_for_source_branch.each do |merge_request|
+ cancel_auto_merge(merge_request)
+ end
end
def mark_pending_todos_done
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index 55546432ce4..0066cd0491f 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -43,6 +43,8 @@ module MergeRequests
create_branch_change_note(merge_request, 'target',
merge_request.previous_changes['target_branch'].first,
merge_request.target_branch)
+
+ cancel_auto_merge(merge_request)
end
if merge_request.assignees != old_assignees
@@ -89,7 +91,7 @@ module MergeRequests
merge_request.update(merge_error: nil)
if merge_request.head_pipeline && merge_request.head_pipeline.active?
- MergeRequests::MergeWhenPipelineSucceedsService.new(project, current_user).execute(merge_request)
+ AutoMergeService.new(project, current_user).execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
else
merge_request.merge_async(current_user.id, {})
end
diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb
index 760962346fb..ca3f0b73096 100644
--- a/app/services/notification_recipient_service.rb
+++ b/app/services/notification_recipient_service.rb
@@ -135,7 +135,7 @@ module NotificationRecipientService
global_users_ids = user_ids_with_project_level_global.concat(user_ids_with_group_level_global)
user_ids += user_ids_with_global_level_custom(global_users_ids, custom_action)
- add_recipients(user_scope.where(id: user_ids), :watch, nil)
+ add_recipients(user_scope.where(id: user_ids), :custom, nil)
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -391,7 +391,7 @@ module NotificationRecipientService
def build!
return [] unless project
- add_recipients(project.team.maintainers, :watch, nil)
+ add_recipients(project.team.maintainers, :mention, nil)
end
def acting_user
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 8d3b569498f..5aa804666f0 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -89,8 +89,8 @@ class NotificationService
# * project team members with notification level higher then Participating
# * users with custom level checked with "close issue"
#
- def close_issue(issue, current_user)
- close_resource_email(issue, current_user, :closed_issue_email)
+ def close_issue(issue, current_user, closed_via: nil)
+ close_resource_email(issue, current_user, :closed_issue_email, closed_via: closed_via)
end
# When we reassign an issue we should send an email to:
@@ -238,7 +238,7 @@ class NotificationService
merge_request,
current_user,
:merged_merge_request_email,
- skip_current_user: !merge_request.merge_when_pipeline_succeeds?
+ skip_current_user: !merge_request.auto_merge_enabled?
)
end
@@ -504,7 +504,7 @@ class NotificationService
end
end
- def close_resource_email(target, current_user, method, skip_current_user: true)
+ def close_resource_email(target, current_user, method, skip_current_user: true, closed_via: nil)
action = method == :merged_merge_request_email ? "merge" : "close"
recipients = NotificationRecipientService.build_recipients(
@@ -515,7 +515,7 @@ class NotificationService
)
recipients.each do |recipient|
- mailer.send(method, recipient.user.id, target.id, current_user.id, recipient.reason).deliver_later
+ mailer.send(method, recipient.user.id, target.id, current_user.id, reason: recipient.reason, closed_via: closed_via).deliver_later
end
end
diff --git a/app/services/pages_domains/create_acme_order_service.rb b/app/services/pages_domains/create_acme_order_service.rb
new file mode 100644
index 00000000000..c600f497fa5
--- /dev/null
+++ b/app/services/pages_domains/create_acme_order_service.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module PagesDomains
+ class CreateAcmeOrderService
+ attr_reader :pages_domain
+
+ def initialize(pages_domain)
+ @pages_domain = pages_domain
+ end
+
+ def execute
+ lets_encrypt_client = Gitlab::LetsEncrypt::Client.new
+ order = lets_encrypt_client.new_order(pages_domain.domain)
+
+ challenge = order.new_challenge
+
+ private_key = OpenSSL::PKey::RSA.new(4096)
+ saved_order = pages_domain.acme_orders.create!(
+ url: order.url,
+ expires_at: order.expires,
+ private_key: private_key.to_pem,
+
+ challenge_token: challenge.token,
+ challenge_file_content: challenge.file_content
+ )
+
+ challenge.request_validation
+ saved_order
+ end
+ end
+end
diff --git a/app/services/pages_domains/obtain_lets_encrypt_certificate_service.rb b/app/services/pages_domains/obtain_lets_encrypt_certificate_service.rb
new file mode 100644
index 00000000000..2dfe1a3d8ca
--- /dev/null
+++ b/app/services/pages_domains/obtain_lets_encrypt_certificate_service.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module PagesDomains
+ class ObtainLetsEncryptCertificateService
+ attr_reader :pages_domain
+
+ def initialize(pages_domain)
+ @pages_domain = pages_domain
+ end
+
+ def execute
+ pages_domain.acme_orders.expired.delete_all
+ acme_order = pages_domain.acme_orders.first
+
+ unless acme_order
+ ::PagesDomains::CreateAcmeOrderService.new(pages_domain).execute
+ return
+ end
+
+ api_order = ::Gitlab::LetsEncrypt::Client.new.load_order(acme_order.url)
+
+ # https://tools.ietf.org/html/rfc8555#section-7.1.6 - statuses diagram
+ case api_order.status
+ when 'ready'
+ api_order.request_certificate(private_key: acme_order.private_key, domain: pages_domain.domain)
+ when 'valid'
+ save_certificate(acme_order.private_key, api_order)
+ acme_order.destroy!
+ # when 'invalid'
+ # TODO: implement error handling
+ end
+ end
+
+ private
+
+ def save_certificate(private_key, api_order)
+ certificate = api_order.certificate
+ pages_domain.update!(key: private_key, certificate: certificate)
+ end
+ end
+end
diff --git a/app/services/preview_markdown_service.rb b/app/services/preview_markdown_service.rb
index 7386530f45f..2b4c4ae68e2 100644
--- a/app/services/preview_markdown_service.rb
+++ b/app/services/preview_markdown_service.rb
@@ -38,7 +38,9 @@ class PreviewMarkdownService < BaseService
head_sha: params[:head_sha],
start_sha: params[:start_sha])
- Gitlab::Diff::SuggestionsParser.parse(text, position: position, project: project)
+ Gitlab::Diff::SuggestionsParser.parse(text, position: position,
+ project: project,
+ supports_suggestion: params[:preview_suggestions])
end
def preview_sugestions?
diff --git a/app/services/projects/after_import_service.rb b/app/services/projects/after_import_service.rb
index afb9048e87b..bbdde4408d2 100644
--- a/app/services/projects/after_import_service.rb
+++ b/app/services/projects/after_import_service.rb
@@ -9,7 +9,7 @@ module Projects
end
def execute
- Projects::HousekeepingService.new(@project, :gc).execute do
+ Projects::HousekeepingService.new(@project).execute do
repository.delete_all_refs_except(RESERVED_REF_PREFIXES)
end
rescue Projects::HousekeepingService::LeaseTaken => e
diff --git a/app/services/projects/cleanup_service.rb b/app/services/projects/cleanup_service.rb
index 12103ea34b5..5972bfd4071 100644
--- a/app/services/projects/cleanup_service.rb
+++ b/app/services/projects/cleanup_service.rb
@@ -18,9 +18,6 @@ module Projects
# per rewritten object, with the old and new SHAs space-separated. It can be
# used to update or remove content that references the objects that BFG has
# altered
- #
- # Currently, only the project repository is modified by this service, but we
- # may wish to modify other data sources in the future.
def execute
apply_bfg_object_map!
@@ -41,10 +38,52 @@ module Projects
raise NoUploadError unless project.bfg_object_map.exists?
project.bfg_object_map.open do |io|
- repository_cleaner.apply_bfg_object_map(io)
+ repository_cleaner.apply_bfg_object_map_stream(io) do |response|
+ cleanup_diffs(response)
+ end
+ end
+ end
+
+ def cleanup_diffs(response)
+ old_commit_shas = extract_old_commit_shas(response.entries)
+
+ ActiveRecord::Base.transaction do
+ cleanup_merge_request_diffs(old_commit_shas)
+ cleanup_note_diff_files(old_commit_shas)
end
end
+ def extract_old_commit_shas(batch)
+ batch.lazy.select { |entry| entry.type == :COMMIT }.map(&:old_oid).force
+ end
+
+ def cleanup_merge_request_diffs(old_commit_shas)
+ merge_request_diffs = MergeRequestDiff
+ .by_project_id(project.id)
+ .by_commit_sha(old_commit_shas)
+
+ # It's important to run the ActiveRecord callbacks here
+ merge_request_diffs.destroy_all # rubocop:disable Cop/DestroyAll
+
+ # TODO: ensure the highlight cache is removed immediately. It's too hard
+ # to calculate the Redis keys at present.
+ #
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/61115
+ end
+
+ def cleanup_note_diff_files(old_commit_shas)
+ # Pluck the IDs instead of running the query twice to ensure we clear the
+ # cache for exactly the note diffs we remove
+ ids = NoteDiffFile
+ .referencing_sha(old_commit_shas, project_id: project.id)
+ .pluck_primary_key
+
+ NoteDiffFile.id_in(ids).delete_all
+
+ # A highlighted version of the diff is stored in redis. Remove it now.
+ Gitlab::DiscussionsDiff::HighlightCache.clear_multiple(ids)
+ end
+
def repository_cleaner
@repository_cleaner ||= Gitlab::Git::RepositoryCleaner.new(repository.raw)
end
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index 4ea40e3c8ce..9f335cceb67 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -100,8 +100,6 @@ module Projects
current_user.invalidate_personal_projects_count
create_readme if @initialize_with_readme
-
- configure_group_clusters_for_project
end
# Refresh the current user's authorizations inline (so they can access the
@@ -127,10 +125,6 @@ module Projects
Files::CreateService.new(@project, current_user, commit_attrs).execute
end
- def configure_group_clusters_for_project
- ClusterProjectConfigureWorker.perform_async(@project.id)
- end
-
def skip_wiki?
!@project.feature_available?(:wiki, current_user) || @skip_wiki
end
diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb
index fc234bafc57..d8fa9d37359 100644
--- a/app/services/projects/fork_service.rb
+++ b/app/services/projects/fork_service.rb
@@ -36,18 +36,22 @@ module Projects
def fork_new_project
new_params = {
- visibility_level: allowed_visibility_level,
- description: @project.description,
- name: target_name,
- path: target_path,
- shared_runners_enabled: @project.shared_runners_enabled,
- namespace_id: target_namespace.id,
- fork_network: fork_network,
+ visibility_level: allowed_visibility_level,
+ description: @project.description,
+ name: target_name,
+ path: target_path,
+ shared_runners_enabled: @project.shared_runners_enabled,
+ namespace_id: target_namespace.id,
+ fork_network: fork_network,
+ # We need to set ci_default_git_depth to 0 for the forked project when
+ # @project.ci_default_git_depth is nil in order to keep the same behaviour
+ # and not get ProjectCiCdSetting::DEFAULT_GIT_DEPTH set on create
+ ci_cd_settings_attributes: { default_git_depth: @project.ci_default_git_depth || 0 },
# We need to assign the fork network membership after the project has
# been instantiated to avoid ActiveRecord trying to create it when
# initializing the project, as that would cause a foreign key constraint
# exception.
- relations_block: -> (project) { build_fork_network_member(project) }
+ relations_block: -> (project) { build_fork_network_member(project) }
}
if @project.avatar.present? && @project.avatar.image?
diff --git a/app/services/projects/git_deduplication_service.rb b/app/services/projects/git_deduplication_service.rb
new file mode 100644
index 00000000000..74d469ecf37
--- /dev/null
+++ b/app/services/projects/git_deduplication_service.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+module Projects
+ class GitDeduplicationService < BaseService
+ include ExclusiveLeaseGuard
+
+ LEASE_TIMEOUT = 86400
+
+ delegate :pool_repository, to: :project
+ attr_reader :project
+
+ def initialize(project)
+ @project = project
+ end
+
+ def execute
+ try_obtain_lease do
+ unless project.has_pool_repository?
+ disconnect_git_alternates
+ break
+ end
+
+ if source_project? && pool_can_fetch_from_source?
+ fetch_from_source
+ end
+
+ project.link_pool_repository if same_storage_as_pool?(project.repository)
+ end
+ end
+
+ private
+
+ def disconnect_git_alternates
+ project.repository.disconnect_alternates
+ end
+
+ def pool_can_fetch_from_source?
+ project.git_objects_poolable? &&
+ same_storage_as_pool?(pool_repository.source_project.repository)
+ end
+
+ def same_storage_as_pool?(repository)
+ pool_repository.object_pool.repository.storage == repository.storage
+ end
+
+ def fetch_from_source
+ project.pool_repository.object_pool.fetch
+ end
+
+ def source_project?
+ return unless project.has_pool_repository?
+
+ project.pool_repository.source_project == project
+ end
+
+ def lease_timeout
+ LEASE_TIMEOUT
+ end
+
+ def lease_key
+ "git_deduplication:#{project.id}"
+ end
+ end
+end
diff --git a/app/services/projects/housekeeping_service.rb b/app/services/projects/housekeeping_service.rb
index 10bd5363b51..9428575591e 100644
--- a/app/services/projects/housekeeping_service.rb
+++ b/app/services/projects/housekeeping_service.rb
@@ -11,6 +11,7 @@ module Projects
class HousekeepingService < BaseService
# Timeout set to 24h
LEASE_TIMEOUT = 86400
+ PACK_REFS_PERIOD = 6
class LeaseTaken < StandardError
def to_s
@@ -76,13 +77,15 @@ module Projects
:gc
elsif pushes_since_gc % full_repack_period == 0
:full_repack
- else
+ elsif pushes_since_gc % repack_period == 0
:incremental_repack
+ else
+ :pack_refs
end
end
def period_match?
- [gc_period, full_repack_period, repack_period].any? { |period| pushes_since_gc % period == 0 }
+ [gc_period, full_repack_period, repack_period, PACK_REFS_PERIOD].any? { |period| pushes_since_gc % period == 0 }
end
def housekeeping_enabled?
diff --git a/app/services/projects/import_error_filter.rb b/app/services/projects/import_error_filter.rb
index a0fc5149bb4..737b794484d 100644
--- a/app/services/projects/import_error_filter.rb
+++ b/app/services/projects/import_error_filter.rb
@@ -4,7 +4,7 @@ module Projects
# Used by project imports, it removes any potential paths
# included in an error message that could be stored in the DB
class ImportErrorFilter
- ERROR_MESSAGE_FILTER = /[^\s]*#{File::SEPARATOR}[^\s]*(?=(\s|\z))/
+ ERROR_MESSAGE_FILTER = /[^\s]*#{File::SEPARATOR}[^\s]*(?=(\s|\z))/.freeze
FILTER_MESSAGE = '[FILTERED]'
def self.filter_message(message)
diff --git a/app/services/projects/import_service.rb b/app/services/projects/import_service.rb
index 642465551c9..073c14040ce 100644
--- a/app/services/projects/import_service.rb
+++ b/app/services/projects/import_service.rb
@@ -94,16 +94,13 @@ module Projects
return unless project.lfs_enabled?
- lfs_objects_to_download = Projects::LfsPointers::LfsImportService.new(project).execute
+ result = Projects::LfsPointers::LfsImportService.new(project).execute
- lfs_objects_to_download.each do |lfs_download_object|
- Projects::LfsPointers::LfsDownloadService.new(project, lfs_download_object)
- .execute
+ if result[:status] == :error
+ # To avoid aborting the importing process, we silently fail
+ # if any exception raises.
+ Gitlab::AppLogger.error("The Lfs import process failed. #{result[:message]}")
end
- rescue => e
- # Right now, to avoid aborting the importing process, we silently fail
- # if any exception raises.
- Rails.logger.error("The Lfs import process failed. #{e.message}")
end
def import_data
diff --git a/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb b/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb
index a9570176e81..9b72480d18b 100644
--- a/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb
+++ b/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb
@@ -21,9 +21,9 @@ module Projects
# This method accepts two parameters:
# - oids: hash of oids to query. The structure is { lfs_file_oid => lfs_file_size }
#
- # Returns a hash with the structure { lfs_file_oids => download_link }
+ # Returns an array of LfsDownloadObject
def execute(oids)
- return {} unless project&.lfs_enabled? && remote_uri && oids.present?
+ return [] unless project&.lfs_enabled? && remote_uri && oids.present?
get_download_links(oids)
end
@@ -37,7 +37,17 @@ module Projects
raise DownloadLinksError, response.message unless response.success?
- parse_response_links(response['objects'])
+ # Since the LFS Batch API may return a Content-Ttpe of
+ # application/vnd.git-lfs+json
+ # (https://github.com/git-lfs/git-lfs/blob/master/docs/api/batch.md#requests),
+ # HTTParty does not know this is actually JSON.
+ data = JSON.parse(response.body)
+
+ raise DownloadLinksError, "LFS Batch API did return any objects" unless data.is_a?(Hash) && data.key?('objects')
+
+ parse_response_links(data['objects'])
+ rescue JSON::ParserError
+ raise DownloadLinksError, "LFS Batch API response is not JSON"
end
def parse_response_links(objects_response)
diff --git a/app/services/projects/lfs_pointers/lfs_import_service.rb b/app/services/projects/lfs_pointers/lfs_import_service.rb
index 9215fa0a7bf..2afcce7099b 100644
--- a/app/services/projects/lfs_pointers/lfs_import_service.rb
+++ b/app/services/projects/lfs_pointers/lfs_import_service.rb
@@ -1,95 +1,23 @@
# frozen_string_literal: true
-# This service manages the whole worflow of discovering the Lfs files in a
-# repository, linking them to the project and downloading (and linking) the non
-# existent ones.
+# This service is responsible of managing the retrieval of the lfs objects,
+# and call the service LfsDownloadService, which performs the download
+# for each of the retrieved lfs objects
module Projects
module LfsPointers
class LfsImportService < BaseService
- include Gitlab::Utils::StrongMemoize
-
- HEAD_REV = 'HEAD'.freeze
- LFS_ENDPOINT_PATTERN = /^\t?url\s*=\s*(.+)$/.freeze
- LFS_BATCH_API_ENDPOINT = '/info/lfs/objects/batch'.freeze
-
- LfsImportError = Class.new(StandardError)
-
def execute
- return {} unless project&.lfs_enabled?
+ return success unless project&.lfs_enabled?
- if external_lfs_endpoint?
- # If the endpoint host is different from the import_url it means
- # that the repo is using a third party service for storing the LFS files.
- # In this case, we have to disable lfs in the project
- disable_lfs!
+ lfs_objects_to_download = LfsObjectDownloadListService.new(project).execute
- return {}
+ lfs_objects_to_download.each do |lfs_download_object|
+ LfsDownloadService.new(project, lfs_download_object).execute
end
- get_download_links
- rescue LfsDownloadLinkListService::DownloadLinksError => e
- raise LfsImportError, "The LFS objects download list couldn't be imported. Error: #{e.message}"
- end
-
- private
-
- def external_lfs_endpoint?
- lfsconfig_endpoint_uri && lfsconfig_endpoint_uri.host != import_uri.host
- end
-
- def disable_lfs!
- project.update(lfs_enabled: false)
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def get_download_links
- existent_lfs = LfsListService.new(project).execute
- linked_oids = LfsLinkService.new(project).execute(existent_lfs.keys)
-
- # Retrieving those oids not linked and which we need to download
- not_linked_lfs = existent_lfs.except(*linked_oids)
-
- LfsDownloadLinkListService.new(project, remote_uri: current_endpoint_uri).execute(not_linked_lfs)
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def lfsconfig_endpoint_uri
- strong_memoize(:lfsconfig_endpoint_uri) do
- # Retrieveing the blob data from the .lfsconfig file
- data = project.repository.lfsconfig_for(HEAD_REV)
- # Parsing the data to retrieve the url
- parsed_data = data&.match(LFS_ENDPOINT_PATTERN)
-
- if parsed_data
- URI.parse(parsed_data[1]).tap do |endpoint|
- endpoint.user ||= import_uri.user
- endpoint.password ||= import_uri.password
- end
- end
- end
- rescue URI::InvalidURIError
- raise LfsImportError, 'Invalid URL in .lfsconfig file'
- end
-
- def import_uri
- @import_uri ||= URI.parse(project.import_url)
- rescue URI::InvalidURIError
- raise LfsImportError, 'Invalid project import URL'
- end
-
- def current_endpoint_uri
- (lfsconfig_endpoint_uri || default_endpoint_uri)
- end
-
- # The import url must end with '.git' here we ensure it is
- def default_endpoint_uri
- @default_endpoint_uri ||= begin
- import_uri.dup.tap do |uri|
- path = uri.path.gsub(%r(/$), '')
- path += '.git' unless path.ends_with?('.git')
- uri.path = path + LFS_BATCH_API_ENDPOINT
- end
- end
+ success
+ rescue => e
+ error(e.message)
end
end
end
diff --git a/app/services/projects/lfs_pointers/lfs_link_service.rb b/app/services/projects/lfs_pointers/lfs_link_service.rb
index 8401f3d1d89..e3c956250f0 100644
--- a/app/services/projects/lfs_pointers/lfs_link_service.rb
+++ b/app/services/projects/lfs_pointers/lfs_link_service.rb
@@ -6,9 +6,9 @@ module Projects
class LfsLinkService < BaseService
# Accept an array of oids to link
#
- # Returns a hash with the same structure with oids linked
+ # Returns an array with the oid of the existent lfs objects
def execute(oids)
- return {} unless project&.lfs_enabled?
+ return [] unless project&.lfs_enabled?
# Search and link existing LFS Object
link_existing_lfs_objects(oids)
diff --git a/app/services/projects/lfs_pointers/lfs_object_download_list_service.rb b/app/services/projects/lfs_pointers/lfs_object_download_list_service.rb
new file mode 100644
index 00000000000..5ba0f50f2ff
--- /dev/null
+++ b/app/services/projects/lfs_pointers/lfs_object_download_list_service.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+# This service manages the whole worflow of discovering the Lfs files in a
+# repository, linking them to the project and downloading (and linking) the non
+# existent ones.
+module Projects
+ module LfsPointers
+ class LfsObjectDownloadListService < BaseService
+ include Gitlab::Utils::StrongMemoize
+
+ HEAD_REV = 'HEAD'.freeze
+ LFS_ENDPOINT_PATTERN = /^\t?url\s*=\s*(.+)$/.freeze
+ LFS_BATCH_API_ENDPOINT = '/info/lfs/objects/batch'.freeze
+
+ LfsObjectDownloadListError = Class.new(StandardError)
+
+ def execute
+ return [] unless project&.lfs_enabled?
+
+ if external_lfs_endpoint?
+ # If the endpoint host is different from the import_url it means
+ # that the repo is using a third party service for storing the LFS files.
+ # In this case, we have to disable lfs in the project
+ disable_lfs!
+
+ return []
+ end
+
+ # Getting all Lfs pointers already in the database and linking them to the project
+ linked_oids = LfsLinkService.new(project).execute(lfs_pointers_in_repository.keys)
+ # Retrieving those oids not present in the database which we need to download
+ missing_oids = lfs_pointers_in_repository.except(*linked_oids) # rubocop: disable CodeReuse/ActiveRecord
+ # Downloading the required information and gathering it inside a LfsDownloadObject for each oid
+ LfsDownloadLinkListService.new(project, remote_uri: current_endpoint_uri).execute(missing_oids)
+ rescue LfsDownloadLinkListService::DownloadLinksError => e
+ raise LfsObjectDownloadListError, "The LFS objects download list couldn't be imported. Error: #{e.message}"
+ end
+
+ private
+
+ def external_lfs_endpoint?
+ lfsconfig_endpoint_uri && lfsconfig_endpoint_uri.host != import_uri.host
+ end
+
+ def disable_lfs!
+ unless project.update(lfs_enabled: false)
+ raise LfsDownloadLinkListService::DownloadLinksError, "Invalid project state"
+ end
+ end
+
+ # Retrieves all lfs pointers in the repository
+ def lfs_pointers_in_repository
+ @lfs_pointers_in_repository ||= LfsListService.new(project).execute
+ end
+
+ def lfsconfig_endpoint_uri
+ strong_memoize(:lfsconfig_endpoint_uri) do
+ # Retrieveing the blob data from the .lfsconfig file
+ data = project.repository.lfsconfig_for(HEAD_REV)
+ # Parsing the data to retrieve the url
+ parsed_data = data&.match(LFS_ENDPOINT_PATTERN)
+
+ if parsed_data
+ URI.parse(parsed_data[1]).tap do |endpoint|
+ endpoint.user ||= import_uri.user
+ endpoint.password ||= import_uri.password
+ end
+ end
+ end
+ rescue URI::InvalidURIError
+ raise LfsObjectDownloadListError, 'Invalid URL in .lfsconfig file'
+ end
+
+ def import_uri
+ @import_uri ||= URI.parse(project.import_url)
+ rescue URI::InvalidURIError
+ raise LfsObjectDownloadListError, 'Invalid project import URL'
+ end
+
+ def current_endpoint_uri
+ (lfsconfig_endpoint_uri || default_endpoint_uri)
+ end
+
+ # The import url must end with '.git' here we ensure it is
+ def default_endpoint_uri
+ @default_endpoint_uri ||= begin
+ import_uri.dup.tap do |uri|
+ path = uri.path.gsub(%r(/$), '')
+ path += '.git' unless path.ends_with?('.git')
+ uri.path = path + LFS_BATCH_API_ENDPOINT
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/projects/operations/update_service.rb b/app/services/projects/operations/update_service.rb
index aedf79c86d7..48eddb0e8d0 100644
--- a/app/services/projects/operations/update_service.rb
+++ b/app/services/projects/operations/update_service.rb
@@ -12,7 +12,16 @@ module Projects
private
def project_update_params
- error_tracking_params
+ error_tracking_params.merge(metrics_setting_params)
+ end
+
+ def metrics_setting_params
+ attribs = params[:metrics_setting_attributes]
+ return {} unless attribs
+
+ destroy = attribs[:external_dashboard_url].blank?
+
+ { metrics_setting_attributes: attribs.merge(_destroy: destroy) }
end
def error_tracking_params
diff --git a/app/services/projects/propagate_service_template.rb b/app/services/projects/propagate_service_template.rb
index 633a263af7b..a2f36d2bd1b 100644
--- a/app/services/projects/propagate_service_template.rb
+++ b/app/services/projects/propagate_service_template.rb
@@ -80,7 +80,7 @@ module Projects
value = value.is_a?(Hash) ? value.to_json : value
service_hash[ActiveRecord::Base.connection.quote_column_name(key)] =
- ActiveRecord::Base.sanitize(value)
+ ActiveRecord::Base.connection.quote(value)
end
end
end
diff --git a/app/services/projects/repository_languages_service.rb b/app/services/projects/repository_languages_service.rb
index e75851c7da4..05f43c2264b 100644
--- a/app/services/projects/repository_languages_service.rb
+++ b/app/services/projects/repository_languages_service.rb
@@ -11,7 +11,7 @@ module Projects
def perform_language_detection
if persisted_repository_languages.blank?
- ::DetectRepositoryLanguagesWorker.perform_async(project.id, current_user.id)
+ ::DetectRepositoryLanguagesWorker.perform_async(project.id)
else
project.update_column(:detected_repository_languages, true)
end
diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb
index 91c01eca75c..233dcf37e35 100644
--- a/app/services/projects/transfer_service.rb
+++ b/app/services/projects/transfer_service.rb
@@ -54,7 +54,6 @@ module Projects
end
attempt_transfer_transaction
- configure_group_clusters_for_project
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -164,9 +163,5 @@ module Projects
@new_namespace.full_path
)
end
-
- def configure_group_clusters_for_project
- ClusterProjectConfigureWorker.perform_async(project.id)
- end
end
end
diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb
index 864ce4fa9f5..2bc04470342 100644
--- a/app/services/projects/update_service.rb
+++ b/app/services/projects/update_service.rb
@@ -64,6 +64,7 @@ module Projects
if project.previous_changes.include?(:visibility_level) && project.private?
# don't enqueue immediately to prevent todos removal in case of a mistake
+ TodosDestroyer::ConfidentialIssueWorker.perform_in(Todo::WAIT_FOR_DELETE, nil, project.id)
TodosDestroyer::ProjectPrivateWorker.perform_in(Todo::WAIT_FOR_DELETE, project.id)
elsif (project_changed_feature_keys & todos_features_changes).present?
TodosDestroyer::PrivateFeaturesWorker.perform_in(Todo::WAIT_FOR_DELETE, project.id)
@@ -79,10 +80,7 @@ module Projects
end
def after_rename_service(project)
- # The path slug the project was using, before the rename took place.
- path_before = project.previous_changes['path'].first
-
- AfterRenameService.new(project, path_before: path_before, full_path_before: project.full_path_was)
+ AfterRenameService.new(project, path_before: project.path_before_last_save, full_path_before: project.full_path_before_last_save)
end
def changing_pages_related_config?
diff --git a/app/services/projects/update_statistics_service.rb b/app/services/projects/update_statistics_service.rb
index f32a779fab0..28677a398f3 100644
--- a/app/services/projects/update_statistics_service.rb
+++ b/app/services/projects/update_statistics_service.rb
@@ -3,7 +3,7 @@
module Projects
class UpdateStatisticsService < BaseService
def execute
- return unless project && project.repository.exists?
+ return unless project
Rails.logger.info("Updating statistics for project #{project.id}")
diff --git a/app/services/service_response.rb b/app/services/service_response.rb
new file mode 100644
index 00000000000..1de30e68d87
--- /dev/null
+++ b/app/services/service_response.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class ServiceResponse
+ def self.success(message: nil)
+ new(status: :success, message: message)
+ end
+
+ def self.error(message:, http_status: nil)
+ new(status: :error, message: message, http_status: http_status)
+ end
+
+ attr_reader :status, :message, :http_status
+
+ def initialize(status:, message: nil, http_status: nil)
+ self.status = status
+ self.message = message
+ self.http_status = http_status
+ end
+
+ def success?
+ status == :success
+ end
+
+ def error?
+ status == :error
+ end
+
+ private
+
+ attr_writer :status, :message, :http_status
+end
diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb
index bd3907cdf8e..858e04f43b2 100644
--- a/app/services/system_hooks_service.rb
+++ b/app/services/system_hooks_service.rb
@@ -47,7 +47,7 @@ class SystemHooksService
case event
when :rename
- data[:old_username] = model.username_was
+ data[:old_username] = model.username_before_last_save
when :failed_login
data[:state] = model.state
end
@@ -58,8 +58,8 @@ class SystemHooksService
if event == :rename
data.merge!(
- old_path: model.path_was,
- old_full_path: model.full_path_was
+ old_path: model.path_before_last_save,
+ old_full_path: model.full_path_before_last_save
)
end
when GroupMember
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index a39ff76b798..1390f7cdf46 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -25,7 +25,7 @@ module SystemNoteService
text_parts = ["added #{commits_text}"]
text_parts << commits_list(noteable, new_commits, existing_commits, oldrev)
- text_parts << "[Compare with previous version](#{diff_comparison_url(noteable, project, oldrev)})"
+ text_parts << "[Compare with previous version](#{diff_comparison_path(noteable, project, oldrev)})"
body = text_parts.join("\n\n")
@@ -41,7 +41,7 @@ module SystemNoteService
#
# Returns the created Note object
def tag_commit(noteable, project, author, tag_name)
- link = url_helpers.project_tag_url(project, id: tag_name)
+ link = url_helpers.project_tag_path(project, id: tag_name)
body = "tagged commit #{noteable.sha} to [`#{tag_name}`](#{link})"
create_note(NoteSummary.new(noteable, project, author, body, action: 'tag'))
@@ -272,7 +272,7 @@ module SystemNoteService
text_parts = ["changed this line in"]
if version_params = merge_request.version_params_for(diff_refs)
line_code = change_position.line_code(project.repository)
- url = url_helpers.diffs_project_merge_request_url(project, merge_request, version_params.merge(anchor: line_code))
+ url = url_helpers.diffs_project_merge_request_path(project, merge_request, version_params.merge(anchor: line_code))
text_parts << "[version #{version_index} of the diff](#{url})"
else
@@ -405,7 +405,7 @@ module SystemNoteService
#
# "created branch `201-issue-branch-button`"
def new_issue_branch(issue, project, author, branch)
- link = url_helpers.project_compare_url(project, from: project.default_branch, to: branch)
+ link = url_helpers.project_compare_path(project, from: project.default_branch, to: branch)
body = "created branch [`#{branch}`](#{link}) to address this issue"
@@ -668,10 +668,10 @@ module SystemNoteService
@url_helpers ||= Gitlab::Routing.url_helpers
end
- def diff_comparison_url(merge_request, project, oldrev)
+ def diff_comparison_path(merge_request, project, oldrev)
diff_id = merge_request.merge_request_diff.id
- url_helpers.diffs_project_merge_request_url(
+ url_helpers.diffs_project_merge_request_path(
project,
merge_request,
diff_id: diff_id,
diff --git a/app/services/tags/destroy_service.rb b/app/services/tags/destroy_service.rb
index cab507946b4..4f6ae07be7d 100644
--- a/app/services/tags/destroy_service.rb
+++ b/app/services/tags/destroy_service.rb
@@ -41,12 +41,11 @@ module Tags
def build_push_data(tag)
Gitlab::DataBuilder::Push.build(
- project,
- current_user,
- tag.dereferenced_target.sha,
- Gitlab::Git::BLANK_SHA,
- "#{Gitlab::Git::TAG_REF_PREFIX}#{tag.name}",
- [])
+ project: project,
+ user: current_user,
+ oldrev: tag.dereferenced_target.sha,
+ newrev: Gitlab::Git::BLANK_SHA,
+ ref: "#{Gitlab::Git::TAG_REF_PREFIX}#{tag.name}")
end
end
end
diff --git a/app/services/test_hooks/project_service.rb b/app/services/test_hooks/project_service.rb
index 6607f5b2418..a71278e8b8b 100644
--- a/app/services/test_hooks/project_service.rb
+++ b/app/services/test_hooks/project_service.rb
@@ -56,7 +56,7 @@ module TestHooks
end
def wiki_page_events_data
- page = project.wiki.pages.first
+ page = project.wiki.list_pages(limit: 1).first
if !project.wiki_enabled? || page.blank?
throw(:validation_error, s_('TestHooks|Ensure the wiki is enabled and has pages.'))
end
diff --git a/app/services/todos/destroy/base_service.rb b/app/services/todos/destroy/base_service.rb
index f3f1dbb5698..7378f10e7c4 100644
--- a/app/services/todos/destroy/base_service.rb
+++ b/app/services/todos/destroy/base_service.rb
@@ -13,7 +13,7 @@ module Todos
# rubocop: disable CodeReuse/ActiveRecord
def without_authorized(items)
- items.where('user_id NOT IN (?)', authorized_users)
+ items.where('todos.user_id NOT IN (?)', authorized_users)
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/todos/destroy/confidential_issue_service.rb b/app/services/todos/destroy/confidential_issue_service.rb
index 6276e332448..6cdd8c16894 100644
--- a/app/services/todos/destroy/confidential_issue_service.rb
+++ b/app/services/todos/destroy/confidential_issue_service.rb
@@ -2,36 +2,55 @@
module Todos
module Destroy
+ # Service class for deleting todos that belongs to confidential issues.
+ # It deletes todos for users that are not at least reporters, issue author or assignee.
+ #
+ # Accepts issue_id or project_id as argument.
+ # When issue_id is passed it deletes matching todos for one confidential issue.
+ # When project_id is passed it deletes matching todos for all confidential issues of the project.
class ConfidentialIssueService < ::Todos::Destroy::BaseService
extend ::Gitlab::Utils::Override
- attr_reader :issue
+ attr_reader :issues
# rubocop: disable CodeReuse/ActiveRecord
- def initialize(issue_id)
- @issue = Issue.find_by(id: issue_id)
+ def initialize(issue_id: nil, project_id: nil)
+ @issues =
+ if issue_id
+ Issue.where(id: issue_id)
+ elsif project_id
+ project_confidential_issues(project_id)
+ end
end
# rubocop: enable CodeReuse/ActiveRecord
private
+ def project_confidential_issues(project_id)
+ project = Project.find(project_id)
+
+ project.issues.confidential_only
+ end
+
override :todos
# rubocop: disable CodeReuse/ActiveRecord
def todos
- Todo.where(target: issue)
- .where('user_id != ?', issue.author_id)
- .where('user_id NOT IN (?)', issue.assignees.select(:id))
+ Todo.joins_issue_and_assignees
+ .where(target: issues)
+ .where('issues.confidential = ?', true)
+ .where('todos.user_id != issues.author_id')
+ .where('todos.user_id != issue_assignees.user_id')
end
# rubocop: enable CodeReuse/ActiveRecord
override :todos_to_remove?
def todos_to_remove?
- issue&.confidential?
+ issues&.any?(&:confidential?)
end
override :project_ids
def project_ids
- issue.project_id
+ issues&.distinct&.select(:project_id)
end
override :authorized_users
diff --git a/app/services/todos/destroy/entity_leave_service.rb b/app/services/todos/destroy/entity_leave_service.rb
index ebfb20132d0..4743e9b02ce 100644
--- a/app/services/todos/destroy/entity_leave_service.rb
+++ b/app/services/todos/destroy/entity_leave_service.rb
@@ -37,8 +37,8 @@ module Todos
private
def enqueue_private_features_worker
- project_ids.each do |project_id|
- TodosDestroyer::PrivateFeaturesWorker.perform_async(project_id, user.id)
+ projects.each do |project|
+ TodosDestroyer::PrivateFeaturesWorker.perform_async(project.id, user.id)
end
end
@@ -62,9 +62,8 @@ module Todos
end
# rubocop: enable CodeReuse/ActiveRecord
- override :project_ids
# rubocop: disable CodeReuse/ActiveRecord
- def project_ids
+ def projects
condition = case entity
when Project
{ id: entity.id }
@@ -72,13 +71,13 @@ module Todos
{ namespace_id: non_member_groups }
end
- Project.where(condition).select(:id)
+ Project.where(condition)
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def non_authorized_projects
- project_ids.where('id NOT IN (?)', user.authorized_projects.select(:id))
+ projects.where('id NOT IN (?)', user.authorized_projects.select(:id))
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -110,7 +109,7 @@ module Todos
authorized_reporter_projects = user
.authorized_projects(Gitlab::Access::REPORTER).select(:id)
- Issue.where(project_id: project_ids, confidential: true)
+ Issue.where(project_id: projects, confidential: true)
.where('project_id NOT IN(?)', authorized_reporter_projects)
.where('author_id != ?', user.id)
.where('id NOT IN (?)', assigned_ids)
diff --git a/app/uploaders/attachment_uploader.rb b/app/uploaders/attachment_uploader.rb
index 0a166335b4e..b488bba00e9 100644
--- a/app/uploaders/attachment_uploader.rb
+++ b/app/uploaders/attachment_uploader.rb
@@ -9,6 +9,6 @@ class AttachmentUploader < GitlabUploader
private
def dynamic_segment
- File.join(model.class.to_s.underscore, mounted_as.to_s, model.id.to_s)
+ File.join(model.class.underscore, mounted_as.to_s, model.id.to_s)
end
end
diff --git a/app/uploaders/avatar_uploader.rb b/app/uploaders/avatar_uploader.rb
index c0165759203..9af59b0aceb 100644
--- a/app/uploaders/avatar_uploader.rb
+++ b/app/uploaders/avatar_uploader.rb
@@ -25,6 +25,6 @@ class AvatarUploader < GitlabUploader
private
def dynamic_segment
- File.join(model.class.to_s.underscore, mounted_as.to_s, model.id.to_s)
+ File.join(model.class.underscore, mounted_as.to_s, model.id.to_s)
end
end
diff --git a/app/uploaders/file_uploader.rb b/app/uploaders/file_uploader.rb
index e90599f2505..1c7582533ad 100644
--- a/app/uploaders/file_uploader.rb
+++ b/app/uploaders/file_uploader.rb
@@ -14,8 +14,8 @@ class FileUploader < GitlabUploader
include ObjectStorage::Concern
prepend ObjectStorage::Extension::RecordsUploads
- MARKDOWN_PATTERN = %r{\!?\[.*?\]\(/uploads/(?<secret>[0-9a-f]{32})/(?<file>.*?)\)}
- DYNAMIC_PATH_PATTERN = %r{.*(?<secret>\h{32})/(?<identifier>.*)}
+ MARKDOWN_PATTERN = %r{\!?\[.*?\]\(/uploads/(?<secret>[0-9a-f]{32})/(?<file>.*?)\)}.freeze
+ DYNAMIC_PATH_PATTERN = %r{.*(?<secret>\h{32})/(?<identifier>.*)}.freeze
after :remove, :prune_store_dir
@@ -109,12 +109,20 @@ class FileUploader < GitlabUploader
def upload_path
if file_storage?
# Legacy path relative to project.full_path
- File.join(dynamic_segment, identifier)
+ local_storage_path(identifier)
else
- File.join(store_dir, identifier)
+ remote_storage_path(identifier)
end
end
+ def local_storage_path(file_identifier)
+ File.join(dynamic_segment, file_identifier)
+ end
+
+ def remote_storage_path(file_identifier)
+ File.join(store_dir, file_identifier)
+ end
+
def store_dirs
{
Store::LOCAL => File.join(base_dir, dynamic_segment),
diff --git a/app/uploaders/import_export_uploader.rb b/app/uploaders/import_export_uploader.rb
index 716922bc017..104d5d3b3dd 100644
--- a/app/uploaders/import_export_uploader.rb
+++ b/app/uploaders/import_export_uploader.rb
@@ -7,10 +7,6 @@ class ImportExportUploader < AttachmentUploader
EXTENSION_WHITELIST
end
- def move_to_store
- true
- end
-
def move_to_cache
false
end
diff --git a/app/uploaders/legacy_artifact_uploader.rb b/app/uploaders/legacy_artifact_uploader.rb
deleted file mode 100644
index fac3c3dcb8f..00000000000
--- a/app/uploaders/legacy_artifact_uploader.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-##
-# TODO: Remove this uploader when we remove :ci_enable_legacy_artifacts feature flag
-# See https://gitlab.com/gitlab-org/gitlab-ce/issues/58595
-class LegacyArtifactUploader < GitlabUploader
- extend Workhorse::UploadPath
- include ObjectStorage::Concern
-
- ObjectNotReadyError = Class.new(StandardError)
-
- storage_options Gitlab.config.artifacts
-
- alias_method :upload, :model
-
- def store_dir
- dynamic_segment
- end
-
- private
-
- def dynamic_segment
- raise ObjectNotReadyError, 'Build is not ready' unless model.id
-
- File.join(model.created_at.utc.strftime('%Y_%m'), model.project_id.to_s, model.id.to_s)
- end
-end
diff --git a/app/uploaders/object_storage.rb b/app/uploaders/object_storage.rb
index 5f8b89f2a24..0a44d60778d 100644
--- a/app/uploaders/object_storage.rb
+++ b/app/uploaders/object_storage.rb
@@ -117,7 +117,7 @@ module ObjectStorage
next unless uploader
next unless uploader.exists?
- next unless send(:"#{mounted_as}_changed?") # rubocop:disable GitlabSecurity/PublicSend
+ next unless send(:"saved_change_to_#{mounted_as}?") # rubocop:disable GitlabSecurity/PublicSend
mount
end.keys
diff --git a/app/uploaders/personal_file_uploader.rb b/app/uploaders/personal_file_uploader.rb
index 272837aa6ce..b43162f0935 100644
--- a/app/uploaders/personal_file_uploader.rb
+++ b/app/uploaders/personal_file_uploader.rb
@@ -6,21 +6,18 @@ class PersonalFileUploader < FileUploader
options.storage_path
end
- def self.base_dir(model, store = nil)
- base_dirs(model)[store || Store::LOCAL]
- end
-
- def self.base_dirs(model)
- {
- Store::LOCAL => File.join(options.base_dir, model_path_segment(model)),
- Store::REMOTE => model_path_segment(model)
- }
+ def self.base_dir(model, _store = nil)
+ # base_dir is the path seen by the user when rendering Markdown, so
+ # it should be the same for both local and object storage. It is
+ # typically prefaced with uploads/-/system, but that prefix
+ # is omitted in the path stored on disk.
+ File.join(options.base_dir, model_path_segment(model))
end
def self.model_path_segment(model)
return 'temp/' unless model
- File.join(model.class.to_s.underscore, model.id.to_s)
+ File.join(model.class.underscore, model.id.to_s)
end
def object_store
@@ -40,8 +37,61 @@ class PersonalFileUploader < FileUploader
store_dirs[object_store]
end
+ # A personal snippet path is stored using FileUploader#upload_path.
+ #
+ # The format for the path:
+ #
+ # Local storage: :random_hex/:filename.
+ # Object storage: personal_snippet/:id/:random_hex/:filename.
+ #
+ # upload_paths represent the possible paths for a given identifier,
+ # which will vary depending on whether the file is stored in local or
+ # object storage. upload_path should match an element in upload_paths.
+ #
+ # base_dir represents the path seen by the user in Markdown, and it
+ # should always be prefixed with uploads/-/system.
+ #
+ # store_dirs represent the paths that are actually used on disk. For
+ # object storage, this should omit the prefix /uploads/-/system.
+ #
+ # For example, consider the requested path /uploads/-/system/personal_snippet/172/ff4ad5c2e40b39ae57cda51577317d20/file.png.
+ #
+ # For local storage:
+ #
+ # File on disk: /opt/gitlab/embedded/service/gitlab-rails/public/uploads/-/system/personal_snippet/172/ff4ad5c2e40b39ae57cda51577317d20/file.png.
+ #
+ # base_dir: uploads/-/system/personal_snippet/172
+ # upload_path: ff4ad5c2e40b39ae57cda51577317d20/file.png
+ # upload_paths: ["ff4ad5c2e40b39ae57cda51577317d20/file.png", "personal_snippet/172/ff4ad5c2e40b39ae57cda51577317d20/file.png"].
+ # store_dirs:
+ # => {1=>"uploads/-/system/personal_snippet/172/ff4ad5c2e40b39ae57cda51577317d20", 2=>"personal_snippet/172/ff4ad5c2e40b39ae57cda51577317d20"}
+ #
+ # For object storage:
+ #
+ # upload_path: personal_snippet/172/ff4ad5c2e40b39ae57cda51577317d20/file.png
+ def upload_paths(identifier)
+ [
+ local_storage_path(identifier),
+ File.join(remote_storage_base_path, identifier)
+ ]
+ end
+
+ def store_dirs
+ {
+ Store::LOCAL => File.join(base_dir, dynamic_segment),
+ Store::REMOTE => remote_storage_base_path
+ }
+ end
+
private
+ # To avoid prefacing the remote storage path with `/uploads/-/system`,
+ # we just drop that part so that the destination path will be
+ # personal_snippet/:id/:random_hex/:filename.
+ def remote_storage_base_path
+ File.join(self.class.model_path_segment(model), dynamic_segment)
+ end
+
def secure_url
File.join('/', base_dir, secret, file.filename)
end
diff --git a/app/views/abuse_reports/new.html.haml b/app/views/abuse_reports/new.html.haml
index 92ae40512c5..c6781e91cfd 100644
--- a/app/views/abuse_reports/new.html.haml
+++ b/app/views/abuse_reports/new.html.haml
@@ -1,22 +1,24 @@
-- page_title _("Report abuse to GitLab")
+- page_title _("Report abuse to admin")
%h3.page-title
- = _("Report abuse to GitLab")
+ = _("Report abuse to admin")
%p
- = _("Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately.")
+ = _("Please use this form to report to the admin users who create spam issues, comments or behave inappropriately.")
%p
- = _("A member of GitLab's abuse team will review your report as soon as possible.")
+ = _("A member of the abuse team will review your report as soon as possible.")
%hr
= form_for @abuse_report, html: { class: 'js-quick-submit js-requires-input'} do |f|
= form_errors(@abuse_report)
= f.hidden_field :user_id
.form-group.row
- = f.label :user_id, class: 'col-sm-2 col-form-label'
+ .col-sm-2.col-form-label
+ = f.label :user_id
.col-sm-10
- name = "#{@abuse_report.user.name} (@#{@abuse_report.user.username})"
= text_field_tag :user_name, name, class: "form-control", readonly: true
.form-group.row
- = f.label :message, class: 'col-sm-2 col-form-label'
+ .col-sm-2.col-form-label
+ = f.label :message
.col-sm-10
= f.text_area :message, class: "form-control", rows: 2, required: true, value: sanitize(@ref_url)
.form-text.text-muted
diff --git a/app/views/admin/application_settings/_external_authorization_service_form.html.haml b/app/views/admin/application_settings/_external_authorization_service_form.html.haml
index 01f6c7afe61..7587ecbf9d3 100644
--- a/app/views/admin/application_settings/_external_authorization_service_form.html.haml
+++ b/app/views/admin/application_settings/_external_authorization_service_form.html.haml
@@ -5,7 +5,7 @@
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? 'Collapse' : 'Expand'
%p
- = _('External Classification Policy Authorization')
+ = _('External Classification Policy Authorization')
.settings-content
= form_for @application_setting, url: admin_application_settings_path(anchor: 'js-external-auth-settings'), html: { class: 'fieldset-form' } do |f|
diff --git a/app/views/admin/application_settings/_logging.html.haml b/app/views/admin/application_settings/_logging.html.haml
index 41b787515b5..1da5f6fccd6 100644
--- a/app/views/admin/application_settings/_logging.html.haml
+++ b/app/views/admin/application_settings/_logging.html.haml
@@ -1,6 +1,12 @@
= form_for @application_setting, url: admin_application_settings_path(anchor: 'js-logging-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
+ %p
+ %strong
+ NOTE:
+ These settings will be removed from the UI in a GitLab 12.0 release and made available within gitlab.yml.
+ In addition, you will be able to define a Sentry Environment to differentiate between multiple deployments. For example, development, staging, and production.
+
%fieldset
.form-group
.form-check
diff --git a/app/views/admin/application_settings/_outbound.html.haml b/app/views/admin/application_settings/_outbound.html.haml
index f4bfb5af385..dd56bb99a06 100644
--- a/app/views/admin/application_settings/_outbound.html.haml
+++ b/app/views/admin/application_settings/_outbound.html.haml
@@ -8,4 +8,12 @@
= f.label :allow_local_requests_from_hooks_and_services, class: 'form-check-label' do
Allow requests to the local network from hooks and services
+ .form-group
+ .form-check
+ = f.check_box :dns_rebinding_protection_enabled, class: 'form-check-input'
+ = f.label :dns_rebinding_protection_enabled, class: 'form-check-label' do
+ = _('Enforce DNS rebinding attack protection')
+ %span.form-text.text-muted
+ = _('Resolves IP addresses once and uses them to submit requests')
+
= f.submit 'Save changes', class: "btn btn-success"
diff --git a/app/views/admin/application_settings/_pages.html.haml b/app/views/admin/application_settings/_pages.html.haml
index ad5c8d4da22..77795dbf913 100644
--- a/app/views/admin/application_settings/_pages.html.haml
+++ b/app/views/admin/application_settings/_pages.html.haml
@@ -5,16 +5,32 @@
.form-group
= f.label :max_pages_size, 'Maximum size of pages (MB)', class: 'label-bold'
= f.number_field :max_pages_size, class: 'form-control'
- .form-text.text-muted 0 for unlimited
+ .form-text.text-muted
+ = _("0 for unlimited")
.form-group
.form-check
= f.check_box :pages_domain_verification_enabled, class: 'form-check-input'
= f.label :pages_domain_verification_enabled, class: 'form-check-label' do
- Require users to prove ownership of custom domains
+ = _("Require users to prove ownership of custom domains")
.form-text.text-muted
- Domain verification is an essential security measure for public GitLab
- sites. Users are required to demonstrate they control a domain before
- it is enabled
+ = _("Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled")
= link_to icon('question-circle'), help_page_path('user/project/pages/getting_started_part_three.md', anchor: 'dns-txt-record')
+ - if Feature.enabled?(:pages_auto_ssl)
+ %h5
+ = _("Configure Let's Encrypt")
+ %p
+ - lets_encrypt_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: "https://letsencrypt.org/" }
+ = _("%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites.").html_safe % { lets_encrypt_link_start: lets_encrypt_link_start, lets_encrypt_link_end: '</a>'.html_safe }
+ .form-group
+ = f.label :lets_encrypt_notification_email, _("Email"), class: 'label-bold'
+ = f.text_field :lets_encrypt_notification_email, class: 'form-control'
+ .form-text.text-muted
+ = _("A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates.")
+ .form-group
+ .form-check
+ = f.check_box :lets_encrypt_terms_of_service_accepted, class: 'form-check-input'
+ = f.label :lets_encrypt_terms_of_service_accepted, class: 'form-check-label' do
+ - terms_of_service_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: lets_encrypt_terms_of_service_admin_application_settings_path }
+ = _("I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}").html_safe % { link_start: terms_of_service_link_start, link_end: '</a>'.html_safe }
- = f.submit 'Save changes', class: "btn btn-success"
+ = f.submit _('Save changes'), class: "btn btn-success"
diff --git a/app/views/admin/application_settings/_performance_bar.html.haml b/app/views/admin/application_settings/_performance_bar.html.haml
index 44ac8d94764..1e66b635038 100644
--- a/app/views/admin/application_settings/_performance_bar.html.haml
+++ b/app/views/admin/application_settings/_performance_bar.html.haml
@@ -5,10 +5,10 @@
.form-group
.form-check
= f.check_box :performance_bar_enabled, class: 'form-check-input'
- = f.label :performance_bar_enabled, class: 'form-check-label' do
- Enable the Performance Bar
+ = f.label :performance_bar_enabled, class: 'form-check-label qa-enable-performance-bar-checkbox' do
+ Enable access to the Performance Bar
.form-group
= f.label :performance_bar_allowed_group_path, 'Allowed group', class: 'label-bold'
= f.text_field :performance_bar_allowed_group_path, class: 'form-control', placeholder: 'my-org/my-group', value: @application_setting.performance_bar_allowed_group&.full_path
- = f.submit 'Save changes', class: "btn btn-success"
+ = f.submit 'Save changes', class: 'btn btn-success qa-save-changes-button'
diff --git a/app/views/admin/application_settings/_visibility_and_access.html.haml b/app/views/admin/application_settings/_visibility_and_access.html.haml
index 03ef2924617..c07bafbe302 100644
--- a/app/views/admin/application_settings/_visibility_and_access.html.haml
+++ b/app/views/admin/application_settings/_visibility_and_access.html.haml
@@ -8,6 +8,7 @@
.form-group
= f.label s_('ProjectCreationLevel|Default project creation protection'), class: 'label-bold'
= f.select :default_project_creation, options_for_select(Gitlab::Access.project_creation_options, @application_setting.default_project_creation), {}, class: 'form-control'
+ = render_if_exists 'admin/application_settings/default_project_deletion_protection_setting', form: f
.form-group.visibility-level-setting
= f.label :default_project_visibility, class: 'label-bold'
= render('shared/visibility_radios', model_method: :default_project_visibility, form: f, selected_level: @application_setting.default_project_visibility, form_model: Project.new)
diff --git a/app/views/admin/application_settings/metrics_and_profiling.html.haml b/app/views/admin/application_settings/metrics_and_profiling.html.haml
index f50aca32bdf..01d61beaf53 100644
--- a/app/views/admin/application_settings/metrics_and_profiling.html.haml
+++ b/app/views/admin/application_settings/metrics_and_profiling.html.haml
@@ -24,14 +24,14 @@
.settings-content
= render 'prometheus'
-%section.settings.as-performance-bar.no-animate#js-performance-bar-settings{ class: ('expanded' if expanded_by_default?) }
+%section.settings.qa-performance-bar-settings.as-performance-bar.no-animate#js-performance-bar-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
%h4
= _('Profiling - Performance bar')
%button.btn.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
- = _('Enable the Performance Bar for a given group.')
+ = _('Enable access to the Performance Bar for a given group.')
= link_to icon('question-circle'), help_page_path('administration/monitoring/performance/performance_bar')
.settings-content
= render 'performance_bar'
diff --git a/app/views/admin/applications/_form.html.haml b/app/views/admin/applications/_form.html.haml
index 12690343f6e..21e84016c66 100644
--- a/app/views/admin/applications/_form.html.haml
+++ b/app/views/admin/applications/_form.html.haml
@@ -2,13 +2,15 @@
= form_errors(application)
= content_tag :div, class: 'form-group row' do
- = f.label :name, class: 'col-sm-2 col-form-label'
+ .col-sm-2.col-form-label
+ = f.label :name
.col-sm-10
= f.text_field :name, class: 'form-control'
= doorkeeper_errors_for application, :name
= content_tag :div, class: 'form-group row' do
- = f.label :redirect_uri, class: 'col-sm-2 col-form-label'
+ .col-sm-2.col-form-label
+ = f.label :redirect_uri
.col-sm-10
= f.text_area :redirect_uri, class: 'form-control'
= doorkeeper_errors_for application, :redirect_uri
@@ -21,14 +23,16 @@
for local tests
= content_tag :div, class: 'form-group row' do
- = f.label :trusted, class: 'col-sm-2 col-form-label pt-0'
+ .col-sm-2.col-form-label.pt-0
+ = f.label :trusted
.col-sm-10
= f.check_box :trusted
%span.form-text.text-muted
Trusted applications are automatically authorized on GitLab OAuth flow.
.form-group.row
- = f.label :scopes, class: 'col-sm-2 col-form-label pt-0'
+ .col-sm-2.col-form-label.pt-0
+ = f.label :scopes
.col-sm-10
= render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: application, scopes: @scopes
diff --git a/app/views/admin/applications/show.html.haml b/app/views/admin/applications/show.html.haml
index df3eeba907c..180066723f1 100644
--- a/app/views/admin/applications/show.html.haml
+++ b/app/views/admin/applications/show.html.haml
@@ -11,7 +11,7 @@
%td
.clipboard-group
.input-group
- %input.label.label-monospace{ id: "application_id", type: "text", autocomplete: 'off', value: @application.uid, readonly: true }
+ %input.label.label-monospace.monospace{ id: "application_id", type: "text", autocomplete: 'off', value: @application.uid, readonly: true }
.input-group-append
= clipboard_button(target: '#application_id', title: _("Copy ID to clipboard"), class: "btn btn btn-default")
%tr
@@ -20,7 +20,7 @@
%td
.clipboard-group
.input-group
- %input.label.label-monospace{ id: "secret", type: "text", autocomplete: 'off', value: @application.secret, readonly: true }
+ %input.label.label-monospace.monospace{ id: "secret", type: "text", autocomplete: 'off', value: @application.secret, readonly: true }
.input-group-append
= clipboard_button(target: '#secret', title: _("Copy secret to clipboard"), class: "btn btn btn-default")
%tr
diff --git a/app/views/admin/broadcast_messages/_form.html.haml b/app/views/admin/broadcast_messages/_form.html.haml
index c465d9f51d6..c8ee87c6212 100644
--- a/app/views/admin/broadcast_messages/_form.html.haml
+++ b/app/views/admin/broadcast_messages/_form.html.haml
@@ -10,28 +10,34 @@
= form_errors(@broadcast_message)
.form-group.row
- = f.label :message, class: 'col-form-label col-sm-2'
+ .col-sm-2.col-form-label
+ = f.label :message
.col-sm-10
= f.text_area :message, class: "form-control js-autosize",
required: true,
+ dir: 'auto',
data: { preview_path: preview_admin_broadcast_messages_path }
.form-group.row.js-toggle-colors-container
.col-sm-10.offset-sm-2
= link_to 'Customize colors', '#', class: 'js-toggle-colors-link'
.form-group.row.js-toggle-colors-container.toggle-colors.hide
- = f.label :color, "Background Color", class: 'col-form-label col-sm-2'
+ .col-sm-2.col-form-label
+ = f.label :color, "Background Color"
.col-sm-10
= f.color_field :color, class: "form-control"
.form-group.row.js-toggle-colors-container.toggle-colors.hide
- = f.label :font, "Font Color", class: 'col-form-label col-sm-2'
+ .col-sm-2.col-form-label
+ = f.label :font, "Font Color"
.col-sm-10
= f.color_field :font, class: "form-control"
.form-group.row
- = f.label :starts_at, _("Starts at (UTC)"), class: 'col-form-label col-sm-2'
+ .col-sm-2.col-form-label
+ = f.label :starts_at, _("Starts at (UTC)")
.col-sm-10.datetime-controls
= f.datetime_select :starts_at, {}, class: 'form-control form-control-inline'
.form-group.row
- = f.label :ends_at, _("Ends at (UTC)"), class: 'col-form-label col-sm-2'
+ .col-sm-2.col-form-label
+ = f.label :ends_at, _("Ends at (UTC)")
.col-sm-10.datetime-controls
= f.datetime_select :ends_at, {}, class: 'form-control form-control-inline'
.form-actions
diff --git a/app/views/admin/broadcast_messages/index.html.haml b/app/views/admin/broadcast_messages/index.html.haml
index 9ef58faf8cc..eb4dfdf2858 100644
--- a/app/views/admin/broadcast_messages/index.html.haml
+++ b/app/views/admin/broadcast_messages/index.html.haml
@@ -32,7 +32,7 @@
%td
= message.ends_at
%td
- = link_to icon('pencil-square-o'), edit_admin_broadcast_message_path(message), title: 'Edit', class: 'btn btn-sm'
- = link_to icon('times'), admin_broadcast_message_path(message), method: :delete, remote: true, title: 'Remove', class: 'js-remove-tr btn btn-sm btn-danger'
+ = link_to sprite_icon('pencil-square'), edit_admin_broadcast_message_path(message), title: 'Edit', class: 'btn'
+ = link_to sprite_icon('remove'), admin_broadcast_message_path(message), method: :delete, remote: true, title: 'Remove', class: 'js-remove-tr btn btn-danger'
= paginate @broadcast_messages, theme: 'gitlab'
diff --git a/app/views/admin/groups/_form.html.haml b/app/views/admin/groups/_form.html.haml
index 8fb38f6a690..dd01ef8a29f 100644
--- a/app/views/admin/groups/_form.html.haml
+++ b/app/views/admin/groups/_form.html.haml
@@ -2,11 +2,12 @@
= form_errors(@group)
= render 'shared/group_form', f: f
- = render_if_exists 'shared/repository_size_limit_setting', form: f, type: :group
+ = render_if_exists 'shared/old_repository_size_limit_setting', form: f, type: :group
= render_if_exists 'admin/namespace_plan', f: f
.form-group.row.group-description-holder
- = f.label :avatar, _("Group avatar"), class: 'col-form-label col-sm-2'
+ .col-sm-2.col-form-label
+ = f.label :avatar, _("Group avatar")
.col-sm-10
= render 'shared/choose_avatar_button', f: f
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index 00d255846f9..f524d35d79e 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -44,12 +44,10 @@
%li
%span.light= _('Storage:')
- - counter_storage = storage_counter(@group.storage_size)
- - counter_repositories = storage_counter(@group.repository_size)
- - counter_build_artifacts = storage_counter(@group.build_artifacts_size)
- - counter_lfs_objects = storage_counter(@group.lfs_objects_size)
- %strong
- = _("%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)") % { counter_storage: counter_storage, counter_repositories: counter_repositories, counter_build_artifacts: counter_build_artifacts, counter_lfs_objects: counter_lfs_objects }
+ %strong= storage_counter(@group.storage_size)
+ (
+ = storage_counters_details(@group)
+ )
%li
%span.light= _('Group Git LFS status:')
diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml
index 0f5e97e288a..ac56e354a4d 100644
--- a/app/views/admin/health_check/show.html.haml
+++ b/app/views/admin/health_check/show.html.haml
@@ -23,7 +23,7 @@
%code= liveness_url(token: Gitlab::CurrentSettings.health_check_access_token)
%li
%code= metrics_url(token: Gitlab::CurrentSettings.health_check_access_token)
-
+ = render_if_exists 'admin/health_check/health_check_url'
%hr
.card
.card-header
diff --git a/app/views/admin/identities/_form.html.haml b/app/views/admin/identities/_form.html.haml
index 3ab7990d9e2..40a7014e143 100644
--- a/app/views/admin/identities/_form.html.haml
+++ b/app/views/admin/identities/_form.html.haml
@@ -2,12 +2,14 @@
= form_errors(@identity)
.form-group.row
- = f.label :provider, class: 'col-form-label col-sm-2'
+ .col-sm-2.col-form-label
+ = f.label :provider
.col-sm-10
- values = Gitlab::Auth::OAuth::Provider.providers.map { |name| ["#{Gitlab::Auth::OAuth::Provider.label_for(name)} (#{name})", name] }
= f.select :provider, values, { allow_blank: false }, class: 'form-control'
.form-group.row
- = f.label :extern_uid, _("Identifier"), class: 'col-form-label col-sm-2'
+ .col-sm-2.col-form-label
+ = f.label :extern_uid, _("Identifier")
.col-sm-10
= f.text_field :extern_uid, class: 'form-control', required: true
diff --git a/app/views/admin/labels/_form.html.haml b/app/views/admin/labels/_form.html.haml
index 5e7b4817461..299d0a12e6c 100644
--- a/app/views/admin/labels/_form.html.haml
+++ b/app/views/admin/labels/_form.html.haml
@@ -2,15 +2,18 @@
= form_errors(@label)
.form-group.row
- = f.label :title, class: 'col-form-label col-sm-2'
+ .col-sm-2.col-form-label
+ = f.label :title
.col-sm-10
= f.text_field :title, class: "form-control", required: true
.form-group.row
- = f.label :description, class: 'col-form-label col-sm-2'
+ .col-sm-2.col-form-label
+ = f.label :description
.col-sm-10
= f.text_field :description, class: "form-control js-quick-submit"
.form-group.row
- = f.label :color, _("Background color"), class: 'col-form-label col-sm-2'
+ .col-sm-2.col-form-label
+ = f.label :color, _("Background color")
.col-sm-10
.input-group
.input-group-prepend
@@ -21,10 +24,7 @@
%br
= _("Or you can choose one of the suggested colors below")
- .suggest-colors
- - suggested_colors.each do |color|
- = link_to '#', style: "background-color: #{color}", data: { color: color } do
- &nbsp;
+ = render_suggested_colors
.form-actions
= f.submit _('Save'), class: 'btn btn-success js-save-button'
diff --git a/app/views/admin/labels/_label.html.haml b/app/views/admin/labels/_label.html.haml
index dbb7224f5f9..6d934654c5d 100644
--- a/app/views/admin/labels/_label.html.haml
+++ b/app/views/admin/labels/_label.html.haml
@@ -1,5 +1,5 @@
%li.label-list-item{ id: dom_id(label) }
- = render "shared/label_row", label: label
+ = render "shared/label_row", label: label.present(issuable_subject: nil)
.label-actions-list
= link_to edit_admin_label_path(label), class: 'btn btn-transparent label-action has-tooltip', title: _('Edit'), data: { placement: 'bottom' }, aria_label: _('Edit') do
= sprite_icon('pencil')
diff --git a/app/views/admin/projects/_projects.html.haml b/app/views/admin/projects/_projects.html.haml
index 5bc695aa7b5..2f7ad35eb3e 100644
--- a/app/views/admin/projects/_projects.html.haml
+++ b/app/views/admin/projects/_projects.html.haml
@@ -7,17 +7,17 @@
= link_to 'Edit', edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn"
%button.delete-project-button.btn.btn-danger{ data: { toggle: 'modal',
target: '#delete-project-modal',
- delete_project_url: project_path(project),
+ delete_project_url: admin_project_path(project),
project_name: project.name }, type: 'button' }
= s_('AdminProjects|Delete')
.stats
%span.badge.badge-pill
- = storage_counter(project.statistics.storage_size)
+ = storage_counter(project.statistics&.storage_size)
- if project.archived
%span.badge.badge-warning archived
.title
- = link_to(admin_namespace_project_path(project.namespace, project)) do
+ = link_to(admin_project_path(project)) do
.dash-project-avatar
.avatar-container.rect-avatar.s40
= project_icon(project, alt: '', class: 'avatar project-avatar s40', width: 40, height: 40)
diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml
index 46bb57c78a8..b88b760536d 100644
--- a/app/views/admin/projects/index.html.haml
+++ b/app/views/admin/projects/index.html.haml
@@ -7,7 +7,7 @@
.top-area.scrolling-tabs-container.inner-page-scroll-tabs
.prepend-top-default
.search-holder
- = render 'shared/projects/search_form', autofocus: true, icon: true
+ = render 'shared/projects/search_form', autofocus: true, icon: true, admin_view: true
.dropdown
- toggle_text = 'Namespace'
- if params[:namespace_id].present?
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 03cce4745aa..e23accc1ea9 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -73,16 +73,11 @@
= @project.repository.relative_path
%li
- %span.light Storage used:
- %strong= storage_counter(@project.statistics.storage_size)
- (
- = storage_counter(@project.statistics.repository_size)
- repository,
- = storage_counter(@project.statistics.build_artifacts_size)
- build artifacts,
- = storage_counter(@project.statistics.lfs_objects_size)
- LFS
- )
+ %span.light= _('Storage:')
+ %strong= storage_counter(@project.statistics&.storage_size)
+ - if @project.statistics
+ = surround '(', ')' do
+ = storage_counters_details(@project.statistics)
%li
%span.light last commit:
@@ -105,6 +100,8 @@
%span.light archived:
%strong project is read-only
+ = render_if_exists "shared_runner_status", project: @project
+
%li
%span.light access:
%strong
@@ -120,7 +117,8 @@
.card-body
= form_for @project, url: transfer_admin_project_path(@project), method: :put do |f|
.form-group.row
- = f.label :new_namespace_id, "Namespace", class: 'col-form-label col-sm-3'
+ .col-sm-3.col-form-label
+ = f.label :new_namespace_id, "Namespace"
.col-sm-9
.dropdown
= dropdown_toggle('Search for Namespace', { toggle: 'dropdown', field_name: 'new_namespace_id' }, { toggle_class: 'js-namespace-select large' })
diff --git a/app/views/admin/users/_access_levels.html.haml b/app/views/admin/users/_access_levels.html.haml
index 12e24ddef02..77729636f9d 100644
--- a/app/views/admin/users/_access_levels.html.haml
+++ b/app/views/admin/users/_access_levels.html.haml
@@ -1,18 +1,20 @@
%fieldset
%legend Access
.form-group.row
- .col-sm-2.text-right
- = f.label :projects_limit, class: 'col-form-label'
- .col-sm-10= f.number_field :projects_limit, min: 0, max: Gitlab::Database::MAX_INT_VALUE, class: 'form-control'
+ .col-sm-2.col-form-label
+ = f.label :projects_limit
+ .col-sm-10
+ = f.number_field :projects_limit, min: 0, max: Gitlab::Database::MAX_INT_VALUE, class: 'form-control'
.form-group.row
- .col-sm-2.text-right
- = f.label :can_create_group, class: 'col-form-label'
- .col-sm-10= f.check_box :can_create_group
+ .col-sm-2.col-form-label
+ = f.label :can_create_group
+ .col-sm-10
+ = f.check_box :can_create_group
.form-group.row
- .col-sm-2.text-right
- = f.label :access_level, class: 'col-form-label'
+ .col-sm-2.col-form-label
+ = f.label :access_level
.col-sm-10
- editing_current_user = (current_user == @user)
@@ -22,6 +24,8 @@
%p.light
Regular users have access to their groups and projects
+ = render_if_exists 'admin/users/auditor_access_level_radio', f: f, disabled: editing_current_user
+
= f.radio_button :access_level, :admin, disabled: editing_current_user
= label_tag :admin, class: 'font-weight-bold' do
Admin
@@ -32,8 +36,8 @@
You cannot remove your own admin rights.
.form-group.row
- .col-sm-2.text-right
- = f.label :external, class: 'col-form-label'
+ .col-sm-2.col-form-label
+ = f.label :external
.hidden{ data: user_internal_regex_data }
.col-sm-10
= f.check_box :external do
diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml
index 296ef073144..3281718071c 100644
--- a/app/views/admin/users/_form.html.haml
+++ b/app/views/admin/users/_form.html.haml
@@ -5,20 +5,20 @@
%fieldset
%legend Account
.form-group.row
- .col-sm-2.text-right
- = f.label :name, class: 'col-form-label'
+ .col-sm-2.col-form-label
+ = f.label :name
.col-sm-10
= f.text_field :name, required: true, autocomplete: 'off', class: 'form-control'
%span.help-inline * required
.form-group.row
- .col-sm-2.text-right
- = f.label :username, class: 'col-form-label'
+ .col-sm-2.col-form-label
+ = f.label :username
.col-sm-10
= f.text_field :username, required: true, autocomplete: 'off', autocorrect: 'off', autocapitalize: 'off', spellcheck: false, class: 'form-control'
%span.help-inline * required
.form-group.row
- .col-sm-2.text-right
- = f.label :email, class: 'col-form-label'
+ .col-sm-2.col-form-label
+ = f.label :email
.col-sm-10
= f.text_field :email, required: true, autocomplete: 'off', class: 'form-control'
%span.help-inline * required
@@ -27,8 +27,8 @@
%fieldset
%legend Password
.form-group.row
- .col-sm-2.text-right
- = f.label :password, class: 'col-form-label'
+ .col-sm-2.col-form-label
+ = f.label :password
.col-sm-10
%strong
Reset link will be generated and sent to the user.
@@ -38,40 +38,52 @@
%fieldset
%legend Password
.form-group.row
- .col-sm-2.text-right
- = f.label :password, class: 'col-form-label'
- .col-sm-10= f.password_field :password, disabled: f.object.force_random_password, class: 'form-control'
+ .col-sm-2.col-form-label
+ = f.label :password
+ .col-sm-10
+ = f.password_field :password, disabled: f.object.force_random_password, class: 'form-control'
.form-group.row
- .col-sm-2.text-right
- = f.label :password_confirmation, class: 'col-form-label'
- .col-sm-10= f.password_field :password_confirmation, disabled: f.object.force_random_password, class: 'form-control'
+ .col-sm-2.col-form-label
+ = f.label :password_confirmation
+ .col-sm-10
+ = f.password_field :password_confirmation, disabled: f.object.force_random_password, class: 'form-control'
= render partial: 'access_levels', locals: { f: f }
+ = render_if_exists 'admin/users/namespace_plan_fieldset', f: f
+
+ = render_if_exists 'admin/users/limits', f: f
+
%fieldset
%legend Profile
.form-group.row
- .col-sm-2.text-right
- = f.label :avatar, class: 'col-form-label'
+ .col-sm-2.col-form-label
+ = f.label :avatar
.col-sm-10
= f.file_field :avatar
.form-group.row
- .col-sm-2.text-right
- = f.label :skype, class: 'col-form-label'
- .col-sm-10= f.text_field :skype, class: 'form-control'
+ .col-sm-2.col-form-label
+ = f.label :skype
+ .col-sm-10
+ = f.text_field :skype, class: 'form-control'
.form-group.row
- .col-sm-2.text-right
- = f.label :linkedin, class: 'col-form-label'
- .col-sm-10= f.text_field :linkedin, class: 'form-control'
+ .col-sm-2.col-form-label
+ = f.label :linkedin
+ .col-sm-10
+ = f.text_field :linkedin, class: 'form-control'
.form-group.row
- .col-sm-2.text-right
- = f.label :twitter, class: 'col-form-label'
- .col-sm-10= f.text_field :twitter, class: 'form-control'
+ .col-sm-2.col-form-label
+ = f.label :twitter
+ .col-sm-10
+ = f.text_field :twitter, class: 'form-control'
.form-group.row
- .col-sm-2.text-right
- = f.label :website_url, 'Website', class: 'col-form-label'
- .col-sm-10= f.text_field :website_url, class: 'form-control'
+ .col-sm-2.col-form-label
+ = f.label :website_url
+ .col-sm-10
+ = f.text_field :website_url, class: 'form-control'
+
+ = render_if_exists 'admin/users/admin_notes', f: f
.form-actions
- if @user.new_record?
diff --git a/app/views/admin/users/_head.html.haml b/app/views/admin/users/_head.html.haml
index a733f420d11..e7dde7985fd 100644
--- a/app/views/admin/users/_head.html.haml
+++ b/app/views/admin/users/_head.html.haml
@@ -6,6 +6,7 @@
%span.cred (Internal)
- if @user.admin
%span.cred (Admin)
+ = render_if_exists 'admin/users/audtior_user_badge'
.float-right
- if impersonation_enabled? && @user != current_user && @user.can?(:log_in)
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index c4178296e67..dcd6f7c8078 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -124,6 +124,8 @@
%strong
= Gitlab::Access.human_access_with_none(@user.highest_role)
+ = render_if_exists 'admin/users/using_license_seat', user: @user
+
- if @user.ldap_user?
%li
%span.light LDAP uid:
diff --git a/app/views/award_emoji/_awards_block.html.haml b/app/views/award_emoji/_awards_block.html.haml
index 8d9c083d223..60ca7e4e267 100644
--- a/app/views/award_emoji/_awards_block.html.haml
+++ b/app/views/award_emoji/_awards_block.html.haml
@@ -13,7 +13,7 @@
%button.btn.award-control.has-tooltip.js-add-award{ type: 'button',
'aria-label': _('Add reaction'),
data: { title: _('Add reaction') } }
- %span{ class: "award-control-icon award-control-icon-neutral" }= custom_icon('emoji_slightly_smiling_face')
- %span{ class: "award-control-icon award-control-icon-positive" }= custom_icon('emoji_smiley')
- %span{ class: "award-control-icon award-control-icon-super-positive" }= custom_icon('emoji_smile')
+ %span{ class: "award-control-icon award-control-icon-neutral" }= sprite_icon('slight-smile')
+ %span{ class: "award-control-icon award-control-icon-positive" }= sprite_icon('smiley')
+ %span{ class: "award-control-icon award-control-icon-super-positive" }= sprite_icon('smile')
= icon('spinner spin', class: "award-control-icon award-control-icon-loading")
diff --git a/app/views/ci/variables/_content.html.haml b/app/views/ci/variables/_content.html.haml
index d07cbe4589c..0b5c1a806b2 100644
--- a/app/views/ci/variables/_content.html.haml
+++ b/app/views/ci/variables/_content.html.haml
@@ -1,3 +1,3 @@
-= _('Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want.')
+= _('Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want.')
= _('You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>.').html_safe
= link_to _('More information'), help_page_path('ci/variables/README', anchor: 'variables')
diff --git a/app/views/ci/variables/_index.html.haml b/app/views/ci/variables/_index.html.haml
index dc9ccb6cc39..94102b4dcd0 100644
--- a/app/views/ci/variables/_index.html.haml
+++ b/app/views/ci/variables/_index.html.haml
@@ -6,10 +6,11 @@
= s_('Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
.row
- .col-lg-12.js-ci-variable-list-section{ data: { save_endpoint: save_endpoint } }
+ .col-lg-12.js-ci-variable-list-section{ data: { save_endpoint: save_endpoint, maskable_regex: ci_variable_maskable_regex } }
.hide.alert.alert-danger.js-ci-variable-error-box
%ul.ci-variable-list
+ = render 'ci/variables/variable_header'
- @variables.each.each do |variable|
= render 'ci/variables/variable_row', form_field: 'variables', variable: variable
= render 'ci/variables/variable_row', form_field: 'variables'
diff --git a/app/views/ci/variables/_variable_header.html.haml b/app/views/ci/variables/_variable_header.html.haml
new file mode 100644
index 00000000000..d3b7a5ae883
--- /dev/null
+++ b/app/views/ci/variables/_variable_header.html.haml
@@ -0,0 +1,16 @@
+- only_key_value = local_assigns.fetch(:only_key_value, false)
+
+%li.ci-variable-row.m-0.d-none.d-sm-block
+ .d-flex.w-100.align-items-center.pb-2
+ .bold.table-section.section-15.append-right-10
+ = s_('CiVariables|Type')
+ .bold.table-section.section-15.append-right-10
+ = s_('CiVariables|Key')
+ .bold.table-section.section-15.append-right-10
+ = s_('CiVariables|Value')
+ - unless only_key_value
+ .bold.table-section.section-20
+ = s_('CiVariables|State')
+ .bold.table-section.section-20
+ = s_('CiVariables|Masked')
+ = render_if_exists 'ci/variables/environment_scope_header'
diff --git a/app/views/ci/variables/_variable_row.html.haml b/app/views/ci/variables/_variable_row.html.haml
index aecfdea10d9..ed4bd5ae19e 100644
--- a/app/views/ci/variables/_variable_row.html.haml
+++ b/app/views/ci/variables/_variable_row.html.haml
@@ -3,39 +3,45 @@
- only_key_value = local_assigns.fetch(:only_key_value, false)
- id = variable&.id
+- variable_type = variable&.variable_type
- key = variable&.key
- value = variable&.value
- is_protected_default = ci_variable_protected_by_default?
- is_protected = ci_variable_protected?(variable, only_key_value)
-- is_masked_default = true
+- is_masked_default = false
- is_masked = ci_variable_masked?(variable, only_key_value)
- id_input_name = "#{form_field}[variables_attributes][][id]"
- destroy_input_name = "#{form_field}[variables_attributes][][_destroy]"
+- variable_type_input_name = "#{form_field}[variables_attributes][][variable_type]"
- key_input_name = "#{form_field}[variables_attributes][][key]"
- value_input_name = "#{form_field}[variables_attributes][][secret_value]"
- protected_input_name = "#{form_field}[variables_attributes][][protected]"
- masked_input_name = "#{form_field}[variables_attributes][][masked]"
%li.js-row.ci-variable-row{ data: { is_persisted: "#{!id.nil?}" } }
- .ci-variable-row-body
+ .ci-variable-row-body.border-bottom
%input.js-ci-variable-input-id{ type: "hidden", name: id_input_name, value: id }
%input.js-ci-variable-input-destroy{ type: "hidden", name: destroy_input_name }
- %input.js-ci-variable-input-key.ci-variable-body-item.qa-ci-variable-input-key.form-control{ type: "text",
+ %select.js-ci-variable-input-variable-type.ci-variable-body-item.form-control.select-control.custom-select.table-section.section-15{ name: variable_type_input_name }
+ = options_for_select(ci_variable_type_options, variable_type)
+ %input.js-ci-variable-input-key.ci-variable-body-item.qa-ci-variable-input-key.form-control.table-section.section-15{ type: "text",
name: key_input_name,
value: key,
placeholder: s_('CiVariables|Input variable key') }
- .ci-variable-body-item.gl-show-field-errors
+ .ci-variable-body-item.gl-show-field-errors.table-section.section-15.border-top-0.p-0
.form-control.js-secret-value-placeholder.qa-ci-variable-input-value{ class: ('hide' unless id) }
- = '*' * 20
+ = '*' * 17
%textarea.js-ci-variable-input-value.js-secret-value.qa-ci-variable-input-value.form-control{ class: ('hide' if id),
rows: 1,
name: value_input_name,
placeholder: s_('CiVariables|Input variable value') }
= value
- %p.masking-validation-error.gl-field-error.hide= s_("CiVariables|This variable will not be masked")
+ %p.masking-validation-error.gl-field-error.hide
+ = s_("CiVariables|Cannot use Masked Variable with current value")
+ = link_to icon('question-circle'), help_page_path('ci/variables/README', anchor: 'masked-variables'), target: '_blank', rel: 'noopener noreferrer'
- unless only_key_value
- .ci-variable-body-item.ci-variable-protected-item
+ .ci-variable-body-item.ci-variable-protected-item.table-section.section-20.mr-0.border-top-0
.append-right-default
= s_("CiVariable|Protected")
%button{ type: 'button',
@@ -49,11 +55,11 @@
%span.toggle-icon
= sprite_icon('status_success_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-checked')
= sprite_icon('status_failed_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-unchecked')
- .ci-variable-body-item.ci-variable-masked-item
+ .ci-variable-body-item.ci-variable-masked-item.table-section.section-20.mr-0.border-top-0
.append-right-default
= s_("CiVariable|Masked")
%button{ type: 'button',
- class: "js-project-feature-toggle project-feature-toggle #{'is-checked' if is_masked}",
+ class: "js-project-feature-toggle project-feature-toggle qa-variable-masked #{'is-checked' if is_masked}",
"aria-label": s_("CiVariable|Toggle masked") }
%input{ type: "hidden",
class: 'js-ci-variable-input-masked js-project-feature-toggle-input',
@@ -64,5 +70,5 @@
= sprite_icon('status_success_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-checked')
= sprite_icon('status_failed_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-unchecked')
= render_if_exists 'ci/variables/environment_scope', form_field: form_field, variable: variable
- %button.js-row-remove-button.ci-variable-row-remove-button{ type: 'button', 'aria-label': s_('CiVariables|Remove variable row') }
- = icon('minus-circle')
+ %button.js-row-remove-button.ci-variable-row-remove-button.table-section.section-5.border-top-0{ type: 'button', 'aria-label': s_('CiVariables|Remove variable row') }
+ = icon('minus-circle')
diff --git a/app/views/clusters/clusters/_banner.html.haml b/app/views/clusters/clusters/_banner.html.haml
index 160c5f009a7..a5de67be96b 100644
--- a/app/views/clusters/clusters/_banner.html.haml
+++ b/app/views/clusters/clusters/_banner.html.haml
@@ -5,5 +5,17 @@
.hidden.js-cluster-creating.bs-callout.bs-callout-info{ role: 'alert' }
= s_('ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine...')
+.hidden.row.js-cluster-api-unreachable.bs-callout.bs-callout-warning{ role: 'alert' }
+ .col-11
+ = s_('ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct.')
+ .col-1.p-0
+ %button.js-close-banner.close.cluster-application-banner-close.h-100.m-0= "×"
+
+.hidden.js-cluster-authentication-failure.row.js-cluster-api-unreachable.bs-callout.bs-callout-warning{ role: 'alert' }
+ .col-11
+ = s_('ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid.')
+ .col-1.p-0
+ %button.js-close-banner.close.cluster-application-banner-close.h-100.m-0= "×"
+
.hidden.js-cluster-success.bs-callout.bs-callout-success{ role: 'alert' }
= s_("ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details")
diff --git a/app/views/clusters/clusters/gcp/_form.html.haml b/app/views/clusters/clusters/gcp/_form.html.haml
index 3e0f8955081..70e2eaeaf3b 100644
--- a/app/views/clusters/clusters/gcp/_form.html.haml
+++ b/app/views/clusters/clusters/gcp/_form.html.haml
@@ -74,6 +74,13 @@
= link_to _('More information'), help_page_path('user/project/clusters/index.md',
anchor: 'role-based-access-control-rbac-core-only'), target: '_blank'
- .form-group
- = field.submit s_('ClusterIntegration|Create Kubernetes cluster'),
- class: 'js-gke-cluster-creation-submit btn btn-success', disabled: true
+ .form-group
+ = field.check_box :managed, { label: s_('ClusterIntegration|GitLab-managed cluster'),
+ label_class: 'label-bold' }
+ .form-text.text-muted
+ = s_('ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster.')
+ = link_to _('More information'), help_page_path('user/project/clusters/index.md', anchor: 'gitlab-managed-clusters'), target: '_blank'
+
+ .form-group
+ = field.submit s_('ClusterIntegration|Create Kubernetes cluster'),
+ class: 'js-gke-cluster-creation-submit btn btn-success', disabled: true
diff --git a/app/views/clusters/clusters/show.html.haml b/app/views/clusters/clusters/show.html.haml
index e38a16e7a1a..4dfbb310142 100644
--- a/app/views/clusters/clusters/show.html.haml
+++ b/app/views/clusters/clusters/show.html.haml
@@ -4,7 +4,7 @@
- page_title _('Kubernetes Cluster')
- manage_prometheus_path = edit_project_service_path(@cluster.project, 'prometheus') if @project
-- expanded = Rails.env.test?
+- expanded = expanded_by_default?
- status_path = clusterable.cluster_status_cluster_path(@cluster.id, format: :json) if can?(current_user, :admin_cluster, @cluster)
.edit-cluster-form.js-edit-cluster-form{ data: { status_path: status_path,
@@ -24,7 +24,8 @@
help_path: help_page_path('user/project/clusters/index.md', anchor: 'installing-applications'),
ingress_help_path: help_page_path('user/project/clusters/index.md', anchor: 'getting-the-external-endpoint'),
ingress_dns_help_path: help_page_path('user/project/clusters/index.md', anchor: 'manually-determining-the-external-endpoint'),
- manage_prometheus_path: manage_prometheus_path } }
+ manage_prometheus_path: manage_prometheus_path,
+ cluster_id: @cluster.id } }
.js-cluster-application-notice
.flash-container
@@ -34,7 +35,7 @@
= render 'banner'
= render 'form'
- = render_if_exists 'projects/clusters/prometheus_graphs' if show_cluster_health_graphs?(@cluster)
+ = render_if_exists 'projects/clusters/prometheus_graphs'
.cluster-applications-table#js-cluster-applications
diff --git a/app/views/clusters/clusters/user/_form.html.haml b/app/views/clusters/clusters/user/_form.html.haml
index 27b11e8469f..f2fc5ac93fb 100644
--- a/app/views/clusters/clusters/user/_form.html.haml
+++ b/app/views/clusters/clusters/user/_form.html.haml
@@ -1,39 +1,55 @@
+- more_info_link = link_to _('More information'), help_page_path('user/project/clusters/index.md',
+ anchor: 'adding-an-existing-kubernetes-cluster'), target: '_blank'
+- rbac_help_link = link_to _('More information'), help_page_path('user/project/clusters/index.md',
+ anchor: 'role-based-access-control-rbac-core-only'), target: '_blank'
+
+- api_url_help_text = s_('ClusterIntegration|The URL used to access the Kubernetes API.')
+- ca_cert_help_text = s_('ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster.')
+- token_help_text = s_('ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges.').html_safe % { code: '<code>'.html_safe, end_code: '</code>'.html_safe }
+- rbac_help_text = s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).') + ' '
+- rbac_help_text << s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
+
= bootstrap_form_for @user_cluster, html: { class: 'gl-show-field-errors' },
url: clusterable.create_user_clusters_path, as: :cluster do |field|
= field.text_field :name, required: true, title: s_('ClusterIntegration|Cluster name is required.'),
label: s_('ClusterIntegration|Kubernetes cluster name'), label_class: 'label-bold'
- if has_multiple_clusters?
- = field.form_group :environment_scope, label: { text: s_('ClusterIntegration|Environment scope'),
- class: 'label-bold' } do
- = field.text_field :environment_scope, required: true,
- title: 'Environment scope is required.', wrapper: false
- .form-text.text-muted
- = s_("ClusterIntegration|Choose which of your environments will use this cluster.")
+ = field.text_field :environment_scope, required: true, title: 'Environment scope is required.',
+ label: s_('ClusterIntegration|Environment scope'), label_class: 'label-bold',
+ help: s_("ClusterIntegration|Choose which of your environments will use this cluster.")
= field.fields_for :platform_kubernetes, @user_cluster.platform_kubernetes do |platform_kubernetes_field|
= platform_kubernetes_field.url_field :api_url, required: true,
title: s_('ClusterIntegration|API URL should be a valid http/https url.'),
- label: s_('ClusterIntegration|API URL'), label_class: 'label-bold'
+ label: s_('ClusterIntegration|API URL'), label_class: 'label-bold',
+ help: '%{help_text} %{help_link}'.html_safe % { help_text: api_url_help_text, help_link: more_info_link }
+
= platform_kubernetes_field.text_area :ca_cert,
placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)'),
- label: s_('ClusterIntegration|CA Certificate'), label_class: 'label-bold'
+ label: s_('ClusterIntegration|CA Certificate'), label_class: 'label-bold',
+ help: '%{help_text} %{help_link}'.html_safe % { help_text: ca_cert_help_text, help_link: more_info_link }
+
= platform_kubernetes_field.text_field :token, required: true,
title: s_('ClusterIntegration|Service token is required.'), label: s_('ClusterIntegration|Service Token'),
- autocomplete: 'off', label_class: 'label-bold'
+ autocomplete: 'off', label_class: 'label-bold',
+ help: '%{help_text} %{help_link}'.html_safe % { help_text: token_help_text, help_link: more_info_link }
- if @user_cluster.allow_user_defined_namespace?
= platform_kubernetes_field.text_field :namespace,
label: s_('ClusterIntegration|Project namespace (optional, unique)'), label_class: 'label-bold'
- = platform_kubernetes_field.form_group :authorization_type do
+ = platform_kubernetes_field.form_group :authorization_type,
+ { help: '%{help_text} %{help_link}'.html_safe % { help_text: rbac_help_text, help_link: rbac_help_link } } do
= platform_kubernetes_field.check_box :authorization_type,
{ class: 'qa-rbac-checkbox', label: s_('ClusterIntegration|RBAC-enabled cluster'),
label_class: 'label-bold', inline: true }, 'rbac', 'abac'
- .form-text.text-muted
- = s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
- = s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
- = link_to _('More information'), help_page_path('user/project/clusters/index.md',
- anchor: 'role-based-access-control-rbac-core-only'), target: '_blank'
-
- .form-group
- = field.submit s_('ClusterIntegration|Add Kubernetes cluster'), class: 'btn btn-success'
+
+ .form-group
+ = field.check_box :managed, { label: s_('ClusterIntegration|GitLab-managed cluster'),
+ label_class: 'label-bold' }
+ .form-text.text-muted
+ = s_('ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster.')
+ = link_to _('More information'), help_page_path('user/project/clusters/index.md', anchor: 'gitlab-managed-clusters'), target: '_blank'
+
+ .form-group
+ = field.submit s_('ClusterIntegration|Add Kubernetes cluster'), class: 'btn btn-success'
diff --git a/app/views/clusters/platforms/kubernetes/_form.html.haml b/app/views/clusters/platforms/kubernetes/_form.html.haml
index f9f8097cb38..c1727cf9079 100644
--- a/app/views/clusters/platforms/kubernetes/_form.html.haml
+++ b/app/views/clusters/platforms/kubernetes/_form.html.haml
@@ -1,7 +1,7 @@
= bootstrap_form_for cluster, url: update_cluster_url_path, html: { class: 'gl-show-field-errors' },
as: :cluster do |field|
- copy_name_btn = clipboard_button(text: cluster.name, title: s_('ClusterIntegration|Copy Kubernetes cluster name'),
- class: 'input-group-text btn-default') unless !cluster.read_only_kubernetes_platform_fields?
+ class: 'input-group-text btn-default') if cluster.read_only_kubernetes_platform_fields?
= field.text_field :name, class: 'js-select-on-focus cluster-name', required: true,
title: s_('ClusterIntegration|Cluster name is required.'),
readonly: cluster.read_only_kubernetes_platform_fields?,
@@ -10,7 +10,7 @@
= field.fields_for :platform_kubernetes, platform do |platform_field|
- copy_api_url = clipboard_button(text: platform.api_url, title: s_('ClusterIntegration|Copy API URL'),
- class: 'input-group-text btn-default') unless !cluster.read_only_kubernetes_platform_fields?
+ class: 'input-group-text btn-default') if cluster.read_only_kubernetes_platform_fields?
= platform_field.text_field :api_url, class: 'js-select-on-focus', required: true,
title: s_('ClusterIntegration|API URL should be a valid http/https url.'),
readonly: cluster.read_only_kubernetes_platform_fields?,
@@ -18,7 +18,7 @@
input_group_class: 'gl-field-error-anchor', append: copy_api_url
- copy_ca_cert_btn = clipboard_button(text: platform.ca_cert, title: s_('ClusterIntegration|Copy CA Certificate'),
- class: 'input-group-text btn-default') unless !cluster.read_only_kubernetes_platform_fields?
+ class: 'input-group-text btn-default') if cluster.read_only_kubernetes_platform_fields?
= platform_field.text_area :ca_cert, class: 'js-select-on-focus', rows: '5',
readonly: cluster.read_only_kubernetes_platform_fields?,
placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)'),
@@ -28,7 +28,7 @@
- show_token_btn = (platform_field.button s_('ClusterIntegration|Show'),
type: 'button', class: 'js-show-cluster-token btn btn-default')
- copy_token_btn = clipboard_button(text: platform.token, title: s_('ClusterIntegration|Copy Service Token'),
- class: 'input-group-text btn-default') unless !cluster.read_only_kubernetes_platform_fields?
+ class: 'input-group-text btn-default') if cluster.read_only_kubernetes_platform_fields?
= platform_field.text_field :token, type: 'password', class: 'js-select-on-focus js-cluster-token',
required: true, title: s_('ClusterIntegration|Service token is required.'),
@@ -47,5 +47,12 @@
= s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
= s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
+ .form-group
+ = field.check_box :managed, { disabled: true, label: s_('ClusterIntegration|GitLab-managed cluster'),
+ label_class: 'label-bold' }
+ .form-text.text-muted
+ = s_('ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster.')
+ = link_to _('More information'), help_page_path('user/project/clusters/index.md', anchor: 'gitlab-managed-clusters'), target: '_blank'
+
.form-group
= field.submit s_('ClusterIntegration|Save changes'), class: 'btn btn-success'
diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml
index ca2822e2b29..97a446dbeec 100644
--- a/app/views/dashboard/_projects_head.html.haml
+++ b/app/views/dashboard/_projects_head.html.haml
@@ -1,3 +1,6 @@
+- project_tab_filter = local_assigns.fetch(:project_tab_filter, "")
+- feature_project_list_filter_bar = Feature.enabled?(:project_list_filter_bar)
+
= content_for :flash_message do
= render 'shared/project_limit'
@@ -6,24 +9,27 @@
- if current_user.can_create_project?
.page-title-controls
- = link_to "New project", new_project_path, class: "btn btn-success"
+ = link_to _("New project"), new_project_path, class: "btn btn-success"
.top-area.scrolling-tabs-container.inner-page-scroll-tabs
.fade-left= icon('angle-left')
.fade-right= icon('angle-right')
- %ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs
+ %ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs{ class: ('border-0' if feature_project_list_filter_bar) }
= nav_link(page: [dashboard_projects_path, root_path]) do
= link_to dashboard_projects_path, class: 'shortcuts-activity', data: {placement: 'right'} do
- Your projects
+ = _("Your projects")
%span.badge.badge-pill= limited_counter_with_delimiter(@total_user_projects_count)
= nav_link(page: starred_dashboard_projects_path) do
= link_to starred_dashboard_projects_path, data: {placement: 'right'} do
- Starred projects
+ = _("Starred projects")
%span.badge.badge-pill= limited_counter_with_delimiter(@total_starred_projects_count)
= nav_link(page: [explore_root_path, trending_explore_projects_path, starred_explore_projects_path, explore_projects_path]) do
= link_to explore_root_path, data: {placement: 'right'} do
- Explore projects
-
- .nav-controls
- = render 'shared/projects/search_form'
- = render 'shared/projects/dropdown'
+ = _("Explore projects")
+ - unless feature_project_list_filter_bar
+ .nav-controls
+ = render 'shared/projects/search_form'
+ = render 'shared/projects/dropdown'
+- if feature_project_list_filter_bar
+ .project-filters
+ = render 'shared/projects/search_bar', project_tab_filter: project_tab_filter
diff --git a/app/views/dashboard/projects/_nav.html.haml b/app/views/dashboard/projects/_nav.html.haml
index da3cf5807b0..f9b61bf1f3e 100644
--- a/app/views/dashboard/projects/_nav.html.haml
+++ b/app/views/dashboard/projects/_nav.html.haml
@@ -1,6 +1,21 @@
-.nav-block
- %ul.nav-links.mobile-separator.nav.nav-tabs
- = nav_link(html_options: { class: ("active" unless params[:personal].present?) }) do
- = link_to s_('DashboardProjects|All'), dashboard_projects_path
- = nav_link(html_options: { class: ("active" if params[:personal].present?) }) do
- = link_to s_('DashboardProjects|Personal'), filter_projects_path(personal: true)
+- inactive_class = 'btn p-2'
+- active_class = 'btn p-2 active'
+- project_tab_filter = local_assigns.fetch(:project_tab_filter, "")
+- is_explore_trending = project_tab_filter == :explore_trending
+- feature_project_list_filter_bar = Feature.enabled?(:project_list_filter_bar)
+
+.nav-block{ class: ("w-100" if feature_project_list_filter_bar) }
+ - if feature_project_list_filter_bar
+ .btn-group.button-filter-group.d-flex.m-0.p-0
+ - if project_tab_filter == :explore || is_explore_trending
+ = link_to s_('DashboardProjects|Trending'), trending_explore_projects_path, class: is_explore_trending ? active_class : inactive_class
+ = link_to s_('DashboardProjects|All'), explore_projects_path, class: is_explore_trending ? inactive_class : active_class
+ - else
+ = link_to s_('DashboardProjects|All'), dashboard_projects_path, class: params[:personal].present? ? inactive_class : active_class
+ = link_to s_('DashboardProjects|Personal'), filter_projects_path(personal: true), class: params[:personal].present? ? active_class : inactive_class
+ - else
+ %ul.nav-links.mobile-separator.nav.nav-tabs
+ = nav_link(html_options: { class: ("active" unless params[:personal].present?) }) do
+ = link_to s_('DashboardProjects|All'), dashboard_projects_path
+ = nav_link(html_options: { class: ("active" if params[:personal].present?) }) do
+ = link_to s_('DashboardProjects|Personal'), filter_projects_path(personal: true)
diff --git a/app/views/dashboard/projects/_zero_authorized_projects.html.haml b/app/views/dashboard/projects/_zero_authorized_projects.html.haml
index 18a82feb189..8933c5d7227 100644
--- a/app/views/dashboard/projects/_zero_authorized_projects.html.haml
+++ b/app/views/dashboard/projects/_zero_authorized_projects.html.haml
@@ -1,4 +1,4 @@
-.blank-state-parent-container
+.blank-state-parent-container{ class: ('has-start-trial-container' if has_start_trial?) }
.section-container.section-welcome{ class: "#{ 'section-admin-welcome' if current_user.admin? }" }
.container.section-body
.row
@@ -7,7 +7,12 @@
Welcome to GitLab
%p.blank-state-text
Code, test, and deploy together
- - if current_user.admin?
- = render "blank_state_admin_welcome"
- - else
- = render "blank_state_welcome"
+ .blank-state-row
+ %div{ class: ('column-large' if has_start_trial?) }
+ - if current_user.admin?
+ = render "blank_state_admin_welcome"
+ - else
+ = render "blank_state_welcome"
+ - if has_start_trial?
+ .column-small
+ = render_if_exists "blank_state_ee_trial"
diff --git a/app/views/dashboard/projects/index.html.haml b/app/views/dashboard/projects/index.html.haml
index dc9468b3368..0298f539b4b 100644
--- a/app/views/dashboard/projects/index.html.haml
+++ b/app/views/dashboard/projects/index.html.haml
@@ -13,7 +13,7 @@
= render "projects/last_push"
- if show_projects?(@projects, params)
= render 'dashboard/projects_head'
- = render 'nav'
+ = render 'nav' unless Feature.enabled?(:project_list_filter_bar)
= render 'projects'
- else
= render "zero_authorized_projects"
diff --git a/app/views/dashboard/projects/starred.html.haml b/app/views/dashboard/projects/starred.html.haml
index a0d85446e5f..0fcc6894b68 100644
--- a/app/views/dashboard/projects/starred.html.haml
+++ b/app/views/dashboard/projects/starred.html.haml
@@ -8,7 +8,7 @@
%div{ class: container_class }
= render "projects/last_push"
- = render 'dashboard/projects_head'
+ = render 'dashboard/projects_head', project_tab_filter: :starred
- if params[:filter_projects] || any_projects?(@projects)
= render 'projects'
diff --git a/app/views/dashboard/todos/_todo.html.haml b/app/views/dashboard/todos/_todo.html.haml
index efe1fb99efc..db6e40a6fd0 100644
--- a/app/views/dashboard/todos/_todo.html.haml
+++ b/app/views/dashboard/todos/_todo.html.haml
@@ -34,7 +34,7 @@
= todo_due_date(todo)
.todo-body
- .todo-note
+ .todo-note.break-word
.md
= first_line_in_markdown(todo, :body, 150, project: todo.project)
diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml
index 214630d245a..8212fb8bb33 100644
--- a/app/views/dashboard/todos/index.html.haml
+++ b/app/views/dashboard/todos/index.html.haml
@@ -34,7 +34,7 @@
= icon('spinner spin')
.todos-filters
- .row-content-block.second-block
+ .issues-details-filters.row-content-block.second-block
= form_tag todos_filter_path(without: [:project_id, :author_id, :type, :action_id]), method: :get, class: 'filter-form d-sm-flex' do
.filter-categories.flex-fill
.filter-item.inline
diff --git a/app/views/devise/confirmations/new.html.haml b/app/views/devise/confirmations/new.html.haml
index 73e70dc63e5..f8aa3cf98dc 100644
--- a/app/views/devise/confirmations/new.html.haml
+++ b/app/views/devise/confirmations/new.html.haml
@@ -3,7 +3,7 @@
.login-body
= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post, class: 'gl-show-field-errors' }) do |f|
.devise-errors
- = devise_error_messages!
+ = render "devise/shared/error_messages", resource: resource
.form-group
= f.label :email
= f.email_field :email, class: "form-control", required: true, title: 'Please provide a valid email address.'
diff --git a/app/views/devise/passwords/edit.html.haml b/app/views/devise/passwords/edit.html.haml
index dd1edb5fdc9..09ea7716a47 100644
--- a/app/views/devise/passwords/edit.html.haml
+++ b/app/views/devise/passwords/edit.html.haml
@@ -3,7 +3,7 @@
.login-body
= form_for(resource, as: resource_name, url: password_path(:user), html: { method: :put, class: 'gl-show-field-errors' }) do |f|
.devise-errors
- = devise_error_messages!
+ = render "devise/shared/error_messages", resource: resource
= f.hidden_field :reset_password_token
.form-group
= f.label 'New password', for: "user_password"
diff --git a/app/views/devise/passwords/new.html.haml b/app/views/devise/passwords/new.html.haml
index 99ce13adf74..fe999851605 100644
--- a/app/views/devise/passwords/new.html.haml
+++ b/app/views/devise/passwords/new.html.haml
@@ -3,7 +3,7 @@
.login-body
= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post, class: 'gl-show-field-errors' }) do |f|
.devise-errors
- = devise_error_messages!
+ = render "devise/shared/error_messages", resource: resource
.form-group
= f.label :email
= f.email_field :email, class: "form-control", required: true, value: params[:user_email], autofocus: true, title: 'Please provide a valid email address.'
diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb
index f379e71ae5b..5a1388ac7a1 100644
--- a/app/views/devise/registrations/edit.html.erb
+++ b/app/views/devise/registrations/edit.html.erb
@@ -1,7 +1,7 @@
<h2>Edit <%= resource_name.to_s.humanize %></h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
- <%= devise_error_messages! %>
+ <%= render "devise/shared/error_messages", resource: resource %>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
diff --git a/app/views/devise/shared/_signin_box.html.haml b/app/views/devise/shared/_signin_box.html.haml
index ec968e435cd..f8f36a8bfff 100644
--- a/app/views/devise/shared/_signin_box.html.haml
+++ b/app/views/devise/shared/_signin_box.html.haml
@@ -3,17 +3,21 @@
.login-box.tab-pane{ id: "crowd", role: 'tabpanel', class: active_when(form_based_auth_provider_has_active_class?(:crowd)) }
.login-body
= render 'devise/sessions/new_crowd'
+
+ = render_if_exists 'devise/sessions/new_kerberos_tab'
+
- @ldap_servers.each_with_index do |server, i|
.login-box.tab-pane{ id: "#{server['provider_name']}", role: 'tabpanel', class: active_when(i.zero? && form_based_auth_provider_has_active_class?(:ldapmain)) }
.login-body
= render 'devise/sessions/new_ldap', server: server
+
+ = render_if_exists 'devise/sessions/new_smartcard'
+
- if password_authentication_enabled_for_web?
.login-box.tab-pane{ id: 'login-pane', role: 'tabpanel' }
.login-body
= render 'devise/sessions/new_base'
- = render_if_exists 'devise/sessions/new_smartcard'
-
- elsif password_authentication_enabled_for_web?
.login-box.tab-pane.active{ id: 'login-pane', role: 'tabpanel' }
.login-body
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
index 9c7ca6ebbd4..5eba819172b 100644
--- a/app/views/devise/shared/_signup_box.html.haml
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -1,27 +1,29 @@
+- max_name_length = 128
+- max_username_length = 255
#register-pane.tab-pane.login-box{ role: 'tabpanel' }
.login-body
= form_for(resource, as: "new_#{resource_name}", url: registration_path(resource_name), html: { class: "new_new_user gl-show-field-errors", "aria-live" => "assertive" }) do |f|
.devise-errors
- = devise_error_messages!
+ = render "devise/shared/error_messages", resource: resource
.name.form-group
- = f.label :name, 'Full name', class: 'label-bold'
- = f.text_field :name, class: "form-control top qa-new-user-name js-block-emoji", required: true, title: _("This field is required.")
+ = f.label :name, _('Full name'), class: 'label-bold'
+ = f.text_field :name, class: "form-control top qa-new-user-name js-block-emoji js-validate-length", :data => { :max_length => max_name_length, :max_length_message => s_("SignUp|Name is too long (maximum is %{max_length} characters).") % { max_length: max_name_length } }, required: true, title: _("This field is required.")
.username.form-group
= f.label :username, class: 'label-bold'
- = f.text_field :username, class: "form-control middle qa-new-user-username js-block-emoji", pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _("Please create a username with only alphanumeric characters.")
- %p.validation-error.hide Username is already taken.
- %p.validation-success.hide Username is available.
- %p.validation-pending.hide Checking username availability...
+ = f.text_field :username, class: "form-control middle qa-new-user-username js-block-emoji js-validate-length", :data => { :max_length => max_username_length, :max_length_message => s_("SignUp|Username is too long (maximum is %{max_length} characters).") % { max_length: max_username_length } }, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _("Please create a username with only alphanumeric characters.")
+ %p.validation-error.field-validation.hide= _('Username is already taken.')
+ %p.validation-success.field-validation.hide= _('Username is available.')
+ %p.validation-pending.field-validation.hide= _('Checking username availability...')
.form-group
= f.label :email, class: 'label-bold'
- = f.email_field :email, class: "form-control middle qa-new-user-email", required: true, title: "Please provide a valid email address."
+ = f.email_field :email, class: "form-control middle qa-new-user-email", required: true, title: _("Please provide a valid email address.")
.form-group
= f.label :email_confirmation, class: 'label-bold'
- = f.email_field :email_confirmation, class: "form-control middle qa-new-user-email-confirmation", required: true, title: "Please retype the email address."
+ = f.email_field :email_confirmation, class: "form-control middle qa-new-user-email-confirmation", required: true, title: _("Please retype the email address.")
.form-group.append-bottom-20#password-strength
= f.label :password, class: 'label-bold'
- = f.password_field :password, class: "form-control bottom qa-new-user-password", required: true, pattern: ".{#{@minimum_password_length},}", title: "Minimum length is #{@minimum_password_length} characters."
- %p.gl-field-hint.text-secondary Minimum length is #{@minimum_password_length} characters
+ = f.password_field :password, class: "form-control bottom qa-new-user-password", required: true, pattern: ".{#{@minimum_password_length},}", title: _("Minimum length is %{minimum_password_length} characters.") % { minimum_password_length: @minimum_password_length }
+ %p.gl-field-hint.text-secondary= _('Minimum length is %{minimum_password_length} characters') % { minimum_password_length: @minimum_password_length }
- if Gitlab::CurrentSettings.current_application_settings.enforce_terms?
.form-group
= check_box_tag :terms_opt_in, '1', false, required: true, class: 'qa-new-user-accept-terms'
@@ -29,8 +31,9 @@
- terms_link = link_to s_("I accept the|Terms of Service and Privacy Policy"), terms_path, target: "_blank"
- accept_terms_label = _("I accept the %{terms_link}") % { terms_link: terms_link }
= accept_terms_label.html_safe
+ = render_if_exists 'devise/shared/email_opted_in', f: f
%div
- if Gitlab::Recaptcha.enabled?
= recaptcha_tags
.submit-container
- = f.submit "Register", class: "btn-register btn qa-new-user-register-button"
+ = f.submit _("Register"), class: "btn-register btn qa-new-user-register-button"
diff --git a/app/views/devise/shared/_tabs_ldap.html.haml b/app/views/devise/shared/_tabs_ldap.html.haml
index aee05b6c81c..b1a9470cf1c 100644
--- a/app/views/devise/shared/_tabs_ldap.html.haml
+++ b/app/views/devise/shared/_tabs_ldap.html.haml
@@ -2,6 +2,7 @@
- if crowd_enabled?
%li.nav-item
= link_to "Crowd", "#crowd", class: "nav-link #{active_when(form_based_auth_provider_has_active_class?(:crowd))}", 'data-toggle' => 'tab'
+ = render_if_exists "devise/shared/kerberos_tab"
- @ldap_servers.each_with_index do |server, i|
%li.nav-item
= link_to server['label'], "##{server['provider_name']}", class: "nav-link #{active_when(i.zero? && form_based_auth_provider_has_active_class?(:ldapmain))} qa-ldap-tab", 'data-toggle' => 'tab'
diff --git a/app/views/devise/shared/_tabs_normal.html.haml b/app/views/devise/shared/_tabs_normal.html.haml
index 8745a4e9d3e..4cd03be572f 100644
--- a/app/views/devise/shared/_tabs_normal.html.haml
+++ b/app/views/devise/shared/_tabs_normal.html.haml
@@ -3,4 +3,4 @@
%a.nav-link.qa-sign-in-tab.active{ href: '#login-pane', data: { toggle: 'tab' }, role: 'tab' } Sign in
- if allow_signup?
%li.nav-item{ role: 'presentation' }
- %a.nav-link.qa-register-tab{ href: '#register-pane', data: { toggle: 'tab' }, role: 'tab' } Register
+ %a.nav-link.qa-register-tab{ href: '#register-pane', data: { track_label: 'sign_in_register', track_property: 'sign_in', track_event: 'click_button', track_value: 'register', toggle: 'tab' }, role: 'tab' } Register
diff --git a/app/views/devise/unlocks/new.html.haml b/app/views/devise/unlocks/new.html.haml
index b2f48a4e0bf..1167f1718d6 100644
--- a/app/views/devise/unlocks/new.html.haml
+++ b/app/views/devise/unlocks/new.html.haml
@@ -3,7 +3,7 @@
.login-body
= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post, class: 'gl-show-field-errors' }) do |f|
.devise-errors
- = devise_error_messages!
+ = render "devise/shared/error_messages", resource: resource
.form-group.append-bottom-20
= f.label :email
= f.email_field :email, class: 'form-control', autofocus: 'autofocus', autocapitalize: 'off', autocorrect: 'off', title: 'Please provide a valid email address.'
diff --git a/app/views/discussions/_notes.html.haml b/app/views/discussions/_notes.html.haml
index 30b00ca86b3..0a5541c3e82 100644
--- a/app/views/discussions/_notes.html.haml
+++ b/app/views/discussions/_notes.html.haml
@@ -19,20 +19,24 @@
.discussion-reply-holder
- if can_create_note?
+ %a.user-avatar-link.d-none.d-sm-block{ href: user_path(current_user) }
+ = image_tag avatar_icon_for_user(current_user), alt: current_user.to_reference, class: 'avatar s40'
- if discussion.potentially_resolvable?
- line_type = local_assigns.fetch(:line_type, nil)
- .btn-group.discussion-with-resolve-btn{ role: "group" }
- .btn-group{ role: "group" }
- = link_to_reply_discussion(discussion, line_type)
+ .discussion-with-resolve-btn
+ .btn-group.discussion-with-resolve-btn{ role: "group" }
+ .btn-group{ role: "group" }
+ = link_to_reply_discussion(discussion, line_type)
- = render "discussions/resolve_all", discussion: discussion
+ = render "discussions/resolve_all", discussion: discussion
- .btn-group.discussion-actions
- = render "discussions/new_issue_for_discussion", discussion: discussion, merge_request: discussion.noteable
- = render "discussions/jump_to_next", discussion: discussion
+ .btn-group.discussion-actions
+ = render "discussions/new_issue_for_discussion", discussion: discussion, merge_request: discussion.noteable
+ = render "discussions/jump_to_next", discussion: discussion
- else
- = link_to_reply_discussion(discussion)
+ .discussion-with-resolve-btn
+ = link_to_reply_discussion(discussion)
- elsif !current_user
.disabled-comment.text-center
Please
diff --git a/app/views/doorkeeper/applications/show.html.haml b/app/views/doorkeeper/applications/show.html.haml
index cac00f9c854..6750732ab67 100644
--- a/app/views/doorkeeper/applications/show.html.haml
+++ b/app/views/doorkeeper/applications/show.html.haml
@@ -14,7 +14,7 @@
%td
.clipboard-group
.input-group
- %input.label.label-monospace{ id: "application_id", type: "text", autocomplete: 'off', value: @application.uid, readonly: true }
+ %input.label.label-monospace.monospace{ id: "application_id", type: "text", autocomplete: 'off', value: @application.uid, readonly: true }
.input-group-append
= clipboard_button(target: '#application_id', title: _("Copy ID to clipboard"), class: "btn btn btn-default")
%tr
@@ -23,7 +23,7 @@
%td
.clipboard-group
.input-group
- %input.label.label-monospace{ id: "secret", type: "text", autocomplete: 'off', value: @application.secret, readonly: true }
+ %input.label.label-monospace.monospace{ id: "secret", type: "text", autocomplete: 'off', value: @application.secret, readonly: true }
.input-group-append
= clipboard_button(target: '#secret', title: _("Copy secret to clipboard"), class: "btn btn btn-default")
%tr
diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml
index 2fcb1d1fd2b..222175c818a 100644
--- a/app/views/events/_event.html.haml
+++ b/app/views/events/_event.html.haml
@@ -3,11 +3,11 @@
.event-item-timestamp
#{time_ago_with_tooltip(event.created_at)}
- - if event.created_project?
+ - if event.created_project_action?
= render "events/event/created_project", event: event
- - elsif event.push?
+ - elsif event.push_action?
= render "events/event/push", event: event
- - elsif event.commented?
+ - elsif event.commented_action?
= render "events/event/note", event: event
- else
= render "events/event/common", event: event
diff --git a/app/views/events/event/_common.html.haml b/app/views/events/event/_common.html.haml
index 96d6553a2ac..b02fdb4b638 100644
--- a/app/views/events/event/_common.html.haml
+++ b/app/views/events/event/_common.html.haml
@@ -11,7 +11,8 @@
= link_to [event.project.namespace.becomes(Namespace), event.project, event.target], class: 'has-tooltip event-target-link append-right-4', title: event.target_title do
= event.target.reference_link_text
- unless event.milestone?
- %span.event-target-title.append-right-4= "&quot;".html_safe + event.target.title + "&quot".html_safe
+ %span.event-target-title.append-right-4{ dir: "auto" }
+ = "&quot;".html_safe + event.target.title + "&quot".html_safe
- else
%span.event-type.d-inline-block.append-right-4{ class: event.action_name }
= event_action_name(event)
diff --git a/app/views/events/event/_note.html.haml b/app/views/events/event/_note.html.haml
index 90ed8e41d32..7e2103287f7 100644
--- a/app/views/events/event/_note.html.haml
+++ b/app/views/events/event/_note.html.haml
@@ -7,7 +7,8 @@
%span.event-type.d-inline-block.append-right-4{ class: event.action_name }
= event.action_name
= event_note_title_html(event)
- %span.event-target-title.append-right-4= "&quot;".html_safe + event.target.title + "&quot".html_safe
+ %span.event-target-title.append-right-4{ dir: "auto" }
+ = "&quot;".html_safe + event.target.title + "&quot".html_safe
= render "events/event_scope", event: event
diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml
index 69914fccc48..21c418cb0e4 100644
--- a/app/views/events/event/_push.html.haml
+++ b/app/views/events/event/_push.html.haml
@@ -32,7 +32,8 @@
- from_label = from
= link_to project_compare_path(project, from: from, to: event.commit_to) do
- Compare #{from_label}...#{truncate_sha(event.commit_to)}
+ %span Compare
+ %span.commit-sha #{from_label}...#{truncate_sha(event.commit_to)}
- if create_mr
%span
diff --git a/app/views/explore/projects/_filter.html.haml b/app/views/explore/projects/_filter.html.haml
index f518205f14c..d00a3d266d8 100644
--- a/app/views/explore/projects/_filter.html.haml
+++ b/app/views/explore/projects/_filter.html.haml
@@ -1,8 +1,12 @@
+- has_label = local_assigns.fetch(:has_label, false)
+- feature_project_list_filter_bar = Feature.enabled?(:project_list_filter_bar)
+
- if current_user
- .dropdown
+ .dropdown.js-project-filter-dropdown-wrap{ class: ('d-flex flex-grow-1 flex-shrink-1' if feature_project_list_filter_bar) }
%button.dropdown-menu-toggle{ href: '#', "data-toggle" => "dropdown", 'data-display' => 'static' }
- = icon('globe', class: 'mt-1')
- %span.light.ml-3= _("Visibility:")
+ - unless has_label
+ = icon('globe', class: 'mt-1')
+ %span.light.ml-3= _("Visibility:")
- if params[:visibility_level].present?
= visibility_level_label(params[:visibility_level].to_i)
- else
diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml
index dd2bf6a5ef8..341ad681c7c 100644
--- a/app/views/explore/projects/index.html.haml
+++ b/app/views/explore/projects/index.html.haml
@@ -5,9 +5,9 @@
= render_dashboard_gold_trial(current_user)
- if current_user
- = render 'dashboard/projects_head'
+ = render 'dashboard/projects_head', project_tab_filter: :explore
- else
= render 'explore/head'
-= render 'explore/projects/nav'
+= render 'explore/projects/nav' unless Feature.enabled?(:project_list_filter_bar) && current_user
= render 'projects', projects: @projects
diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml
index dd2bf6a5ef8..ec92852ddde 100644
--- a/app/views/explore/projects/starred.html.haml
+++ b/app/views/explore/projects/starred.html.haml
@@ -5,9 +5,9 @@
= render_dashboard_gold_trial(current_user)
- if current_user
- = render 'dashboard/projects_head'
+ = render 'dashboard/projects_head', project_tab_filter: :starred
- else
= render 'explore/head'
-= render 'explore/projects/nav'
+= render 'explore/projects/nav' unless Feature.enabled?(:project_list_filter_bar) && current_user
= render 'projects', projects: @projects
diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml
index dd2bf6a5ef8..ed508fa2506 100644
--- a/app/views/explore/projects/trending.html.haml
+++ b/app/views/explore/projects/trending.html.haml
@@ -5,9 +5,9 @@
= render_dashboard_gold_trial(current_user)
- if current_user
- = render 'dashboard/projects_head'
+ = render 'dashboard/projects_head', project_tab_filter: :explore_trending
- else
= render 'explore/head'
-= render 'explore/projects/nav'
+= render 'explore/projects/nav' unless Feature.enabled?(:project_list_filter_bar) && current_user
= render 'projects', projects: @projects
diff --git a/app/views/groups/_create_chat_team.html.haml b/app/views/groups/_create_chat_team.html.haml
index f950968030f..561e68a9155 100644
--- a/app/views/groups/_create_chat_team.html.haml
+++ b/app/views/groups/_create_chat_team.html.haml
@@ -1,8 +1,9 @@
.form-group
- = f.label :create_chat_team, class: 'col-form-label' do
- %span.mattermost-icon
- = custom_icon('icon_mattermost')
- Mattermost
+ .col-sm-2.col-form-label
+ = f.label :create_chat_team do
+ %span.mattermost-icon
+ = custom_icon('icon_mattermost')
+ Mattermost
.col-sm-10
.form-check.js-toggle-container
.js-toggle-button.form-check-input= f.check_box(:create_chat_team, { checked: true }, true, false)
diff --git a/app/views/groups/_group_admin_settings.html.haml b/app/views/groups/_group_admin_settings.html.haml
index 7390c42aba2..b8f632d11d3 100644
--- a/app/views/groups/_group_admin_settings.html.haml
+++ b/app/views/groups/_group_admin_settings.html.haml
@@ -1,5 +1,6 @@
.form-group.row
- = f.label :lfs_enabled, 'Large File Storage', class: 'col-form-label col-sm-2 pt-0'
+ .col-sm-2.col-form-label.pt-0
+ = f.label :lfs_enabled, 'Large File Storage'
.col-sm-10
.form-check
= f.check_box :lfs_enabled, checked: @group.lfs_enabled?, class: 'form-check-input'
@@ -10,12 +11,14 @@
%br/
%span.descr This setting can be overridden in each project.
.form-group.row
- = f.label s_('ProjectCreationLevel|Allowed to create projects'), class: 'col-form-label col-sm-2'
+ .col-sm-2.col-form-label
+ = f.label s_('ProjectCreationLevel|Allowed to create projects')
.col-sm-10
= f.select :project_creation_level, options_for_select(::Gitlab::Access.project_creation_options, @group.project_creation_level), {}, class: 'form-control'
.form-group.row
- = f.label :require_two_factor_authentication, 'Two-factor authentication', class: 'col-form-label col-sm-2 pt-0'
+ .col-sm-2.col-form-label.pt-0
+ = f.label :require_two_factor_authentication, 'Two-factor authentication'
.col-sm-10
.form-check
= f.check_box :require_two_factor_authentication, class: 'form-check-input'
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index 2f635757902..0c8f86c2822 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -1,6 +1,6 @@
- breadcrumb_title "General Settings"
- @content_class = "limit-container-width" unless fluid_layout
-- expanded = Rails.env.test?
+- expanded = expanded_by_default?
%section.settings.gs-general.no-animate#js-general-settings{ class: ('expanded') }
diff --git a/app/views/groups/group_members/_new_group_member.html.haml b/app/views/groups/group_members/_new_group_member.html.haml
index c8cdc2cc3e4..8b511f6866f 100644
--- a/app/views/groups/group_members/_new_group_member.html.haml
+++ b/app/views/groups/group_members/_new_group_member.html.haml
@@ -1,7 +1,7 @@
= form_for @group_member, url: group_group_members_path(@group), html: { class: 'users-project-form users-group-form' } do |f|
.row
.col-md-4.col-lg-6
- = users_select_tag(:user_ids, multiple: true, class: 'input-clamp', scope: :all, email_user: true)
+ = users_select_tag(:user_ids, group_member_select_options)
.form-text.text-muted.append-bottom-10
Search for members by name, username, or email, or invite new ones using their email address.
diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml
index 09cc713e3af..021c0b6c429 100644
--- a/app/views/groups/group_members/index.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -14,6 +14,8 @@
= render 'shared/members/requests', membership_source: @group, requesters: @requesters
+ = render_if_exists 'groups/group_members/ldap_sync'
+
.clearfix
%h5.member.existing-title
Existing members
diff --git a/app/views/groups/labels/index.html.haml b/app/views/groups/labels/index.html.haml
index 5cf3193bc62..a8358704b03 100644
--- a/app/views/groups/labels/index.html.haml
+++ b/app/views/groups/labels/index.html.haml
@@ -1,7 +1,6 @@
- @no_container = true
-- page_title "Labels"
+- page_title 'Labels'
- can_admin_label = can?(current_user, :admin_label, @group)
-- issuables = ['issues', 'merge requests']
- search = params[:search]
- subscribed = params[:subscribed]
- labels_or_filters = @labels.exists? || search.present? || subscribed.present?
@@ -14,11 +13,11 @@
.labels-container.prepend-top-5
- if @labels.any?
.text-muted
- = _('Labels can be applied to %{features}. Group labels are available for any project within the group.') % { features: issuables.to_sentence }
+ = _('Labels can be applied to %{features}. Group labels are available for any project within the group.') % { features: issuable_types.to_sentence }
.other-labels
%h5= _('Labels')
%ul.content-list.manage-labels-list.js-other-labels
- = render partial: 'shared/label', subject: @group, collection: @labels, as: :label, locals: { use_label_priority: false }
+ = render partial: 'shared/label', collection: @labels, as: :label, locals: { use_label_priority: false, subject: @group }
= paginate @labels, theme: 'gitlab'
- elsif search.present?
.nothing-here-block
diff --git a/app/views/groups/settings/_general.html.haml b/app/views/groups/settings/_general.html.haml
index c382a1ed168..e12748666c8 100644
--- a/app/views/groups/settings/_general.html.haml
+++ b/app/views/groups/settings/_general.html.haml
@@ -17,17 +17,17 @@
= f.label :description, _('Group description (optional)'), class: 'label-bold'
= f.text_area :description, class: 'form-control', rows: 3, maxlength: 250
- = render_if_exists 'shared/repository_size_limit_setting', form: f, type: :group
+ = render_if_exists 'shared/repository_size_limit_setting', form: f, type: :group
- .form-group.prepend-top-default.append-bottom-20
- .avatar-container.rect-avatar.s90
- = group_icon(@group, alt: '', class: 'avatar group-avatar s90')
- = f.label :avatar, _('Group avatar'), class: 'label-bold d-block'
- = render 'shared/choose_avatar_button', f: f
- - if @group.avatar?
- %hr
- = link_to _('Remove avatar'), group_avatar_path(@group.to_param), data: { confirm: _('Avatar will be removed. Are you sure?')}, method: :delete, class: 'btn btn-link'
+ .form-group.prepend-top-default.append-bottom-20
+ .avatar-container.rect-avatar.s90
+ = group_icon(@group, alt: '', class: 'avatar group-avatar s90')
+ = f.label :avatar, _('Group avatar'), class: 'label-bold d-block'
+ = render 'shared/choose_avatar_button', f: f
+ - if @group.avatar?
+ %hr
+ = link_to _('Remove avatar'), group_avatar_path(@group.to_param), data: { confirm: _('Avatar will be removed. Are you sure?')}, method: :delete, class: 'btn btn-link'
- = render 'shared/visibility_level', f: f, visibility_level: @group.visibility_level, can_change_visibility_level: can_change_group_visibility_level?(@group), form_model: @group
+ = render 'shared/visibility_level', f: f, visibility_level: @group.visibility_level, can_change_visibility_level: can_change_group_visibility_level?(@group), form_model: @group
= f.submit _('Save changes'), class: 'btn btn-success mt-4 js-dirty-submit'
diff --git a/app/views/groups/settings/ci_cd/show.html.haml b/app/views/groups/settings/ci_cd/show.html.haml
index d0f5cd94002..d21496ee0aa 100644
--- a/app/views/groups/settings/ci_cd/show.html.haml
+++ b/app/views/groups/settings/ci_cd/show.html.haml
@@ -1,7 +1,7 @@
- breadcrumb_title "CI / CD Settings"
- page_title "CI / CD"
-- expanded = Rails.env.test?
+- expanded = expanded_by_default?
%section.settings#ci-variables.no-animate{ class: ('expanded' if expanded) }
.settings-header
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index 77fe88dacb7..255a9ad038c 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -9,7 +9,7 @@
= render 'groups/home_panel'
.groups-listing{ data: { endpoints: { default: group_children_path(@group, format: :json), shared: group_shared_projects_path(@group, format: :json) } } }
- .top-area.group-nav-container
+ .top-area.group-nav-container.justify-content-between
.scrolling-tabs-container.inner-page-scroll-tabs
.fade-left= icon('angle-left')
.fade-right= icon('angle-right')
diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml
index 916f98a62d1..50933c7d434 100644
--- a/app/views/help/index.html.haml
+++ b/app/views/help/index.html.haml
@@ -1,11 +1,11 @@
%div
- if Gitlab::CurrentSettings.help_page_text.present?
- = markdown_field(Gitlab::CurrentSettings.current_application_settings, :help_page_text)
+ .prepend-top-default.md
+ = markdown_field(Gitlab::CurrentSettings.current_application_settings, :help_page_text)
%hr
%h1
- GitLab
- Community Edition
+ = default_brand_title
- if user_signed_in?
%span= link_to_version
= version_status_badge
diff --git a/app/views/help/ui.html.haml b/app/views/help/ui.html.haml
index 969df69aafb..cdc894ee5a0 100644
--- a/app/views/help/ui.html.haml
+++ b/app/views/help/ui.html.haml
@@ -70,7 +70,7 @@
.cover-title
John Smith
- .cover-desc
+ .cover-desc.cgray
= lorem
.cover-controls
diff --git a/app/views/import/bitbucket_server/status.html.haml b/app/views/import/bitbucket_server/status.html.haml
index 9280f12e187..40609fddbde 100644
--- a/app/views/import/bitbucket_server/status.html.haml
+++ b/app/views/import/bitbucket_server/status.html.haml
@@ -29,7 +29,7 @@
%tr
%th= _('From Bitbucket Server')
%th= _('To GitLab')
- %th= _(' Status')
+ %th= _('Status')
%tbody
- @already_added_projects.each do |project|
%tr{ id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}" }
diff --git a/app/views/import/gitea/new.html.haml b/app/views/import/gitea/new.html.haml
index a88b04eccbb..c4670869c93 100644
--- a/app/views/import/gitea/new.html.haml
+++ b/app/views/import/gitea/new.html.haml
@@ -2,18 +2,18 @@
- header_title _("Projects"), root_path
%h3.page-title
- = custom_icon('go_logo')
+ = custom_icon('gitea_logo')
= _('Import Projects from Gitea')
%p
- - link_to_personal_token = link_to(_('Personal Access Token'), 'https://github.com/gogits/go-gogs-client/wiki#access-token')
+ - link_to_personal_token = link_to(_('Personal Access Token'), 'https://docs.gitea.io/en-us/api-usage/#authentication-via-the-api')
= _('To get started, please enter your Gitea Host URL and a %{link_to_personal_token}.').html_safe % { link_to_personal_token: link_to_personal_token }
= form_tag personal_access_token_import_gitea_path do
.form-group.row
= label_tag :gitea_host_url, _('Gitea Host URL'), class: 'col-form-label col-sm-2'
.col-sm-4
- = text_field_tag :gitea_host_url, nil, placeholder: 'https://try.gitea.io', class: 'form-control'
+ = text_field_tag :gitea_host_url, nil, placeholder: 'https://gitea.com', class: 'form-control'
.form-group.row
= label_tag :personal_access_token, _('Personal Access Token'), class: 'col-form-label col-sm-2'
.col-sm-4
diff --git a/app/views/import/gitea/status.html.haml b/app/views/import/gitea/status.html.haml
index 88244fde16b..ef0693e73c3 100644
--- a/app/views/import/gitea/status.html.haml
+++ b/app/views/import/gitea/status.html.haml
@@ -1,7 +1,7 @@
- page_title _("Gitea Import")
- header_title _("Projects"), root_path
%h3.page-title
- = custom_icon('go_logo')
+ = custom_icon('gitea_logo')
= _('Import Projects from Gitea')
= render 'import/githubish_status', provider: 'gitea'
diff --git a/app/views/import/github/new.html.haml b/app/views/import/github/new.html.haml
index cf32c5c9387..72e5934574a 100644
--- a/app/views/import/github/new.html.haml
+++ b/app/views/import/github/new.html.haml
@@ -22,6 +22,8 @@
= text_field_tag :personal_access_token, '', class: 'form-control append-right-8', placeholder: _('Personal Access Token'), size: 40
= submit_tag _('List your GitHub repositories'), class: 'btn btn-success'
+ = render_if_exists 'import/github/ci_cd_only'
+
- unless github_import_configured?
%hr
%p
diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml
index 5e4595d930b..a19c8911559 100644
--- a/app/views/import/gitlab_projects/new.html.haml
+++ b/app/views/import/gitlab_projects/new.html.haml
@@ -7,28 +7,7 @@
%hr
= form_tag import_gitlab_project_path, class: 'new_project', multipart: true do
- .row
- .form-group.project-name.col-sm-12
- = label_tag :name, _('Project name'), class: 'label-bold'
- = text_field_tag :name, @name, placeholder: "My awesome project", class: "js-project-name form-control input-lg", autofocus: true
- .form-group.col-12.col-sm-6
- = label_tag :namespace_id, _('Project URL'), class: 'label-bold'
- .form-group
- .input-group
- - if current_user.can_select_namespace?
- .input-group-prepend.has-tooltip{ title: root_url }
- .input-group-text
- = root_url
- = select_tag :namespace_id, namespaces_options(namespace_id_from(params) || :current_user, display_path: true, extra_group: namespace_id_from(params)), class: 'select2 js-select-namespace', tabindex: 1
-
- - else
- .input-group-prepend.static-namespace.has-tooltip{ title: user_url(current_user.username) + '/' }
- .input-group-text.border-0
- #{user_url(current_user.username)}/
- = hidden_field_tag :namespace_id, value: current_user.namespace_id
- .form-group.col-12.col-sm-6.project-path
- = label_tag :path, _('Project slug'), class: 'label-bold'
- = text_field_tag :path, @path, placeholder: "my-awesome-project", class: "js-path-name form-control", tabindex: 2, required: true
+ = render 'import/shared/new_project_form'
.row
.form-group.col-md-12
diff --git a/app/views/import/manifest/new.html.haml b/app/views/import/manifest/new.html.haml
index 056e4922b9e..df00c4d2179 100644
--- a/app/views/import/manifest/new.html.haml
+++ b/app/views/import/manifest/new.html.haml
@@ -4,9 +4,5 @@
%h3.page-title
= _('Manifest file import')
-- if @errors.present?
- .alert.alert-danger
- - @errors.each do |error|
- = error
-
+= render 'import/shared/errors'
= render 'form'
diff --git a/app/views/import/phabricator/new.html.haml b/app/views/import/phabricator/new.html.haml
new file mode 100644
index 00000000000..811e126579e
--- /dev/null
+++ b/app/views/import/phabricator/new.html.haml
@@ -0,0 +1,25 @@
+- title = _('Phabricator Server Import')
+- page_title title
+- breadcrumb_title title
+- header_title _("Projects"), root_path
+
+%h3.page-title
+ = icon 'issues', text: _('Import tasks from Phabricator into issues')
+
+= render 'import/shared/errors'
+
+= form_tag import_phabricator_path, class: 'new_project', method: :post do
+ = render 'import/shared/new_project_form'
+
+ %h4.prepend-top-0= _('Enter in your Phabricator Server URL and personal access token below')
+
+ .form-group.row
+ = label_tag :phabricator_server_url, _('Phabricator Server URL'), class: 'col-form-label col-md-2'
+ .col-md-4
+ = text_field_tag :phabricator_server_url, params[:phabricator_server_url], class: 'form-control append-right-8', placeholder: 'https://your-phabricator-server', size: 40
+ .form-group.row
+ = label_tag :api_token, _('API Token'), class: 'col-form-label col-md-2'
+ .col-md-4
+ = password_field_tag :api_token, params[:api_token], class: 'form-control append-right-8', placeholder: _('Personal Access Token'), size: 40
+ .form-actions
+ = submit_tag _('Import tasks'), class: 'btn btn-success'
diff --git a/app/views/import/shared/_errors.html.haml b/app/views/import/shared/_errors.html.haml
new file mode 100644
index 00000000000..de60c15351f
--- /dev/null
+++ b/app/views/import/shared/_errors.html.haml
@@ -0,0 +1,4 @@
+- if @errors.present?
+ .alert.alert-danger
+ - @errors.each do |error|
+ = error
diff --git a/app/views/import/shared/_new_project_form.html.haml b/app/views/import/shared/_new_project_form.html.haml
new file mode 100644
index 00000000000..4d13d4f2869
--- /dev/null
+++ b/app/views/import/shared/_new_project_form.html.haml
@@ -0,0 +1,21 @@
+.row
+ .form-group.project-name.col-sm-12
+ = label_tag :name, _('Project name'), class: 'label-bold'
+ = text_field_tag :name, @name, placeholder: "My awesome project", class: "js-project-name form-control input-lg", autofocus: true
+ .form-group.col-12.col-sm-6
+ = label_tag :namespace_id, _('Project URL'), class: 'label-bold'
+ .form-group
+ .input-group.flex-nowrap
+ - if current_user.can_select_namespace?
+ .input-group-prepend.flex-shrink-0.has-tooltip{ title: root_url }
+ .input-group-text
+ = root_url
+ = select_tag :namespace_id, namespaces_options(namespace_id_from(params) || :current_user, display_path: true, extra_group: namespace_id_from(params)), class: 'select2 js-select-namespace', tabindex: 1
+ - else
+ .input-group-prepend.static-namespace.has-tooltip{ title: user_url(current_user.username) + '/' }
+ .input-group-text.border-0
+ #{user_url(current_user.username)}/
+ = hidden_field_tag :namespace_id, value: current_user.namespace_id
+ .form-group.col-12.col-sm-6.project-path
+ = label_tag :path, _('Project slug'), class: 'label-bold'
+ = text_field_tag :path, @path, placeholder: "my-awesome-project", class: "js-path-name form-control", tabindex: 2, required: true
diff --git a/app/views/issues/_issue.atom.builder b/app/views/issues/_issue.atom.builder
index 21cf6d0dd65..94c32df7c60 100644
--- a/app/views/issues/_issue.atom.builder
+++ b/app/views/issues/_issue.atom.builder
@@ -12,6 +12,7 @@ xml.entry do
xml.summary issue.title
xml.description issue.description if issue.description
+ xml.content issue.description if issue.description
xml.milestone issue.milestone.title if issue.milestone
xml.due_date issue.due_date if issue.due_date
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index 11e83ddfe64..c357207054b 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -77,3 +77,4 @@
= render 'layouts/google_analytics' if extra_config.has_key?('google_analytics_id')
= render 'layouts/piwik' if extra_config.has_key?('piwik_url') && extra_config.has_key?('piwik_site_id')
+ = render_if_exists 'layouts/snowplow'
diff --git a/app/views/layouts/_mailer.html.haml b/app/views/layouts/_mailer.html.haml
index e13490ed410..6e8294d6adc 100644
--- a/app/views/layouts/_mailer.html.haml
+++ b/app/views/layouts/_mailer.html.haml
@@ -64,6 +64,8 @@
%tbody
= yield
+ = render_if_exists 'layouts/mailer/additional_text'
+
%tr.footer
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:25px 0;font-size:13px;line-height:1.6;color:#5c5c5c;" }
%img{ alt: "GitLab", height: "33", src: image_url('mailers/gitlab_footer_logo.gif'), style: "display:block;margin:0 auto 1em;", width: "90" }/
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index 26a1f1e119c..006334ade07 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -5,6 +5,7 @@
= render 'shared/outdated_browser'
.mobile-overlay
.alert-wrapper
+ = render_if_exists "layouts/header/ee_license_banner"
= render "layouts/broadcast"
= render "layouts/header/read_only_banner"
= render "layouts/nav/classification_level_banner"
diff --git a/app/views/layouts/_piwik.html.haml b/app/views/layouts/_piwik.html.haml
index a888e8ae187..473b14ce626 100644
--- a/app/views/layouts/_piwik.html.haml
+++ b/app/views/layouts/_piwik.html.haml
@@ -7,7 +7,7 @@
(function() {
var u="//#{extra_config.piwik_url}/";
_paq.push(['setTrackerUrl', u+'piwik.php']);
- _paq.push(['setSiteId', #{extra_config.piwik_site_id}]);
+ _paq.push(['setSiteId', "#{extra_config.piwik_site_id}"]);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
})();
diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml
index a6023a1cbb9..496ec3c78b0 100644
--- a/app/views/layouts/_search.html.haml
+++ b/app/views/layouts/_search.html.haml
@@ -16,7 +16,7 @@
mr_path: merge_requests_dashboard_path },
aria: { label: _('Search or jump to…') }
%button.hidden.js-dropdown-search-toggle{ type: 'button', data: { toggle: 'dropdown' } }
- .dropdown-menu.dropdown-select
+ .dropdown-menu.dropdown-select.js-dashboard-search-options
= dropdown_content do
%ul
%li.dropdown-menu-empty-item
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 043cca6ad38..c38f96f302a 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -10,4 +10,6 @@
= render 'layouts/page', sidebar: sidebar, nav: nav
= footer_message
+ = render_if_exists "shared/onboarding_guide"
+
= yield :scripts_body
diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml
index 2f3c13aaf6e..ff3410f6268 100644
--- a/app/views/layouts/devise.html.haml
+++ b/app/views/layouts/devise.html.haml
@@ -10,15 +10,17 @@
.container.navless-container
.content
= render "layouts/flash"
- .row.append-bottom-15
- .col-sm-7.brand-holder
- %h1
+ .row.mt-3
+ .col-sm-12
+ %h1.mb-3.font-weight-normal
= brand_title
+ .row.mb-3
+ .col-sm-7.order-12.order-sm-1.brand-holder
= brand_image
- if current_appearance&.description?
= brand_text
- else
- %h3
+ %h3.mt-sm-0
= _('Open source software to collaborate on code')
%p
@@ -26,7 +28,10 @@
- if Gitlab::CurrentSettings.sign_in_text.present?
= markdown_field(Gitlab::CurrentSettings.current_application_settings, :sign_in_text)
- .col-sm-5.new-session-forms-container
+
+ = render_if_exists 'layouts/devise_help_text'
+
+ .col-sm-5.order-1.order-sm-12.new-session-forms-container
= yield
%hr.footer-fixed
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index a9b85889846..f8b7d0c530a 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -17,6 +17,10 @@
- if logo_text.present?
%span.logo-text.d-none.d-lg-block.prepend-left-8
= logo_text
+ - if Gitlab.com?
+ = link_to 'https://next.gitlab.com', class: 'label-link js-canary-badge canary-badge bg-transparent hidden', target: :_blank do
+ %span.color-label.has-tooltip.badge.badge-pill.green-badge
+ = _('Next')
- if current_user
= render "layouts/nav/dashboard"
@@ -38,7 +42,7 @@
= link_to assigned_issues_dashboard_path, title: _('Issues'), class: 'dashboard-shortcuts-issues', aria: { label: _('Issues') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= sprite_icon('issues', size: 16)
- issues_count = assigned_issuables_count(:issues)
- %span.badge.badge-pill.issues-count{ class: ('hidden' if issues_count.zero?) }
+ %span.badge.badge-pill.issues-count.green-badge{ class: ('hidden' if issues_count.zero?) }
= number_with_delimiter(issues_count)
- if header_link?(:merge_requests)
= nav_link(path: 'dashboard#merge_requests', html_options: { class: "user-counter" }) do
diff --git a/app/views/layouts/header/_help_dropdown.html.haml b/app/views/layouts/header/_help_dropdown.html.haml
index cd9128c452b..5643a508ddc 100644
--- a/app/views/layouts/header/_help_dropdown.html.haml
+++ b/app/views/layouts/header/_help_dropdown.html.haml
@@ -2,8 +2,13 @@
- if current_user_menu?(:help)
%li
= link_to _("Help"), help_path
+ = render_if_exists "shared/learn_gitlab_menu_item"
%li.divider
%li
= link_to _("Submit feedback"), "https://about.gitlab.com/submit-feedback"
- if current_user_menu?(:help) || current_user_menu?(:settings) || current_user_menu?(:profile)
= render 'shared/user_dropdown_contributing_link'
+ = render_if_exists 'shared/user_dropdown_instance_review'
+ - if Gitlab.com?
+ %li.js-canary-link
+ = link_to _("Switch to GitLab Next"), "https://next.gitlab.com/"
diff --git a/app/views/layouts/mailer.text.erb b/app/views/layouts/mailer.text.erb
index f8032f3262b..1a06ea68bcd 100644
--- a/app/views/layouts/mailer.text.erb
+++ b/app/views/layouts/mailer.text.erb
@@ -4,5 +4,6 @@
-- <%# signature marker %>
<%= _("You're receiving this email because of your account on %{host}.") % { host: Gitlab.config.gitlab.host } %>
+<%= render_if_exists 'layouts/mailer/additional_text' %>
<%= text_footer_message %>
diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml
index 5a27237bf76..54028dc8554 100644
--- a/app/views/layouts/nav/_dashboard.html.haml
+++ b/app/views/layouts/nav/_dashboard.html.haml
@@ -19,17 +19,17 @@
- if dashboard_nav_link?(:activity)
= nav_link(path: 'dashboard#activity', html_options: { class: ["d-none d-xl-block", ("d-lg-block" unless has_extra_nav_icons?)] }) do
- = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: _('Activity') do
+ = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity' do
= _('Activity')
- if dashboard_nav_link?(:milestones)
= nav_link(controller: 'dashboard/milestones', html_options: { class: ["d-none d-xl-block", ("d-lg-block" unless has_extra_nav_icons?)] }) do
- = link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones', title: _('Milestones') do
+ = link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones' do
= _('Milestones')
- if dashboard_nav_link?(:snippets)
= nav_link(controller: 'dashboard/snippets', html_options: { class: ["d-none d-xl-block", ("d-lg-block" unless has_extra_nav_icons?)] }) do
- = link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets qa-snippets-link', title: _('Snippets') do
+ = link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets qa-snippets-link' do
= _('Snippets')
- if any_dashboard_nav_link?([:groups, :milestones, :activity, :snippets])
@@ -41,47 +41,47 @@
%ul
- if dashboard_nav_link?(:activity)
= nav_link(path: 'dashboard#activity') do
- = link_to activity_dashboard_path, title: _('Activity') do
+ = link_to activity_dashboard_path do
= _('Activity')
- if dashboard_nav_link?(:milestones)
= nav_link(controller: 'dashboard/milestones') do
- = link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones', title: _('Milestones') do
+ = link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones' do
= _('Milestones')
- if dashboard_nav_link?(:snippets)
= nav_link(controller: 'dashboard/snippets') do
- = link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets', title: _('Snippets') do
+ = link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets' do
= _('Snippets')
-
- = render_if_exists 'dashboard/operations/nav_link'
+ %li.dropdown.d-lg-none
+ = render_if_exists 'dashboard/operations/nav_link_list'
- if can?(current_user, :read_instance_statistics)
- = nav_link(controller: [:conversational_development_index, :cohorts]) do
- = link_to instance_statistics_root_path, title: _('Instance Statistics'), aria: { label: _('Instance Statistics') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = nav_link(controller: [:conversational_development_index, :cohorts], html_options: { class: 'd-lg-none' }) do
+ = link_to instance_statistics_root_path do
= _('Instance Statistics')
- if current_user.admin?
= nav_link(controller: 'admin/dashboard') do
- = link_to admin_root_path, class: 'admin-icon qa-admin-area-link', title: _('Admin Area'), aria: { label: _('Admin Area') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = link_to admin_root_path, class: 'd-lg-none admin-icon qa-admin-area-link' do
= _('Admin Area')
- if Gitlab::Sherlock.enabled?
%li
- = link_to sherlock_transactions_path, class: 'admin-icon', title: _('Sherlock Transactions'),
- data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = link_to sherlock_transactions_path, class: 'd-lg-none admin-icon' do
= _('Sherlock Transactions')
-# Shortcut to Dashboard > Projects
- if dashboard_nav_link?(:projects)
%li.hidden
- = link_to dashboard_projects_path, title: _('Projects'), class: 'dashboard-shortcuts-projects' do
+ = link_to dashboard_projects_path, class: 'dashboard-shortcuts-projects' do
= _('Projects')
- if current_controller?('ide')
%li.line-separator.d-none.d-sm-block
= nav_link(controller: 'ide') do
- = link_to '#', class: 'dashboard-shortcuts-web-ide', title: _('Web IDE') do
+ = link_to '#', class: 'dashboard-shortcuts-web-ide' do
= _('Web IDE')
- = render_if_exists 'dashboard/operations/nav_link'
+ %li.dropdown{ class: 'd-none d-lg-block' }
+ = render_if_exists 'dashboard/operations/nav_link'
- if can?(current_user, :read_instance_statistics)
= nav_link(controller: [:conversational_development_index, :cohorts], html_options: { class: "d-none d-lg-block d-xl-block"}) do
= link_to instance_statistics_root_path, title: _('Instance Statistics'), aria: { label: _('Instance Statistics') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
@@ -95,3 +95,4 @@
= link_to sherlock_transactions_path, class: 'admin-icon d-none d-lg-block d-xl-block', title: _('Sherlock Transactions'),
data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('tachometer fw')
+ = render_if_exists 'layouts/nav/geo_primary_node_url'
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index bb2d206ba91..83fe871285a 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -48,7 +48,7 @@
%span
= _('Gitaly Servers')
- = nav_link(controller: %w(system_info background_jobs logs health_check requests_profiles)) do
+ = nav_link(controller: admin_monitoring_nav_links) do
= link_to admin_system_info_path do
.nav-icon-container
= sprite_icon('monitor')
@@ -81,6 +81,7 @@
= link_to admin_requests_profiles_path, title: _('Requests Profiles') do
%span
= _('Requests Profiles')
+ = render_if_exists 'layouts/nav/ee/admin/new_monitoring_sidebar'
= nav_link(controller: :broadcast_messages) do
= link_to admin_broadcast_messages_path do
@@ -132,6 +133,21 @@
= _('Abuse Reports')
%span.badge.badge-pill.count.merge_counter.js-merge-counter.fly-out-badge= number_with_delimiter(AbuseReport.count(:all))
+ = render_if_exists 'layouts/nav/sidebar/licenses_link'
+
+ - if instance_clusters_enabled?
+ = nav_link(controller: :clusters) do
+ = link_to admin_clusters_path do
+ .nav-icon-container
+ = sprite_icon('cloud-gear')
+ %span.nav-item-name
+ = _('Kubernetes')
+ %ul.sidebar-sub-level-items.is-fly-out-only
+ = nav_link(controller: :clusters, html_options: { class: "fly-out-top-item" } ) do
+ = link_to admin_clusters_path do
+ %strong.fly-out-top-item-name
+ = _('Kubernetes')
+
- if akismet_enabled?
= nav_link(controller: :spam_logs) do
= link_to admin_spam_logs_path do
@@ -145,6 +161,10 @@
%strong.fly-out-top-item-name
= _('Spam Logs')
+ = render_if_exists 'layouts/nav/sidebar/push_rules_link'
+
+ = render_if_exists 'layouts/nav/ee/admin/geo_sidebar'
+
= nav_link(controller: :deploy_keys) do
= link_to admin_deploy_keys_path do
.nav-icon-container
@@ -232,7 +252,7 @@
%span
= _('Reporting')
= nav_link(path: 'application_settings#metrics_and_profiling') do
- = link_to metrics_and_profiling_admin_application_settings_path, title: _('Metrics and profiling') do
+ = link_to metrics_and_profiling_admin_application_settings_path, title: _('Metrics and profiling'), class: 'qa-admin-settings-metrics-and-profiling-item' do
%span
= _('Metrics and profiling')
= nav_link(path: 'application_settings#network') do
diff --git a/app/views/layouts/nav/sidebar/_group.html.haml b/app/views/layouts/nav/sidebar/_group.html.haml
index b950e53639a..0fc5ebbea7e 100644
--- a/app/views/layouts/nav/sidebar/_group.html.haml
+++ b/app/views/layouts/nav/sidebar/_group.html.haml
@@ -1,6 +1,5 @@
- issues_count = group_issues_count(state: 'opened')
- merge_requests_count = group_merge_requests_count(state: 'opened')
-- issues_sub_menu_items = ['groups#issues', 'labels#index', 'milestones#index', 'boards#index', 'boards#show']
.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?) }
.nav-sidebar-inner-scroll
@@ -46,11 +45,12 @@
= _('Contribution Analytics')
= render_if_exists 'layouts/nav/group_insights_link'
+ = render_if_exists 'groups/sidebar/dependency_proxy' # EE-specific
= render_if_exists "layouts/nav/ee/epic_link", group: @group
- if group_sidebar_link?(:issues)
- = nav_link(path: issues_sub_menu_items) do
+ = nav_link(path: group_issues_sub_menu_items) do
= link_to issues_group_path(@group) do
.nav-icon-container
= sprite_icon('issues')
diff --git a/app/views/layouts/nav/sidebar/_profile.html.haml b/app/views/layouts/nav/sidebar/_profile.html.haml
index 1e3bb8f1224..7dd33f3c641 100644
--- a/app/views/layouts/nav/sidebar/_profile.html.haml
+++ b/app/views/layouts/nav/sidebar/_profile.html.haml
@@ -4,7 +4,7 @@
= link_to profile_path, title: _('Profile Settings') do
.avatar-container.s40.settings-avatar
= image_tag avatar_icon_for_user(current_user, 40), class: "avatar s40 avatar-tile", alt: current_user.name
- .sidebar-context-title User Settings
+ .sidebar-context-title= _('User Settings')
%ul.sidebar-top-level-items
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
= link_to profile_path do
@@ -28,6 +28,8 @@
= link_to profile_account_path do
%strong.fly-out-top-item-name
= _('Account')
+
+ = render_if_exists 'layouts/nav/sidebar/profile_billing_link'
= nav_link(controller: 'oauth/applications') do
= link_to applications_profile_path do
.nav-icon-container
@@ -151,4 +153,6 @@
%strong.fly-out-top-item-name
= _('Authentication Log')
+ = render_if_exists 'layouts/nav/sidebar/profile_pipeline_quota_link'
+
= render 'shared/sidebar_toggle_button'
diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml
index 3a0c2b9c284..49ff976f8e8 100644
--- a/app/views/layouts/nav/sidebar/_project.html.haml
+++ b/app/views/layouts/nav/sidebar/_project.html.haml
@@ -9,7 +9,7 @@
= @project.name
%ul.sidebar-top-level-items
= nav_link(path: sidebar_projects_paths, html_options: { class: 'home' }) do
- = link_to project_path(@project), class: 'shortcuts-project' do
+ = link_to project_path(@project), class: 'shortcuts-project qa-link-project' do
.nav-icon-container
= sprite_icon('home')
%span.nav-item-name
@@ -36,6 +36,8 @@
= render_if_exists 'projects/sidebar/security_dashboard'
+ = render_if_exists 'projects/sidebar/dependencies'
+
- if can?(current_user, :read_cycle_analytics, @project)
= nav_link(path: 'cycle_analytics#show') do
= link_to project_cycle_analytics_path(@project), title: _('Cycle Analytics'), class: 'shortcuts-project-cycle-analytics' do
@@ -270,6 +272,8 @@
%span= _("Got it!")
= sprite_icon('thumb-up')
+ = render_if_exists 'layouts/nav/sidebar/project_feature_flags_link'
+
- if project_nav_tab? :container_registry
= nav_link(controller: %w[projects/registry/repositories]) do
= link_to project_container_registry_index_path(@project), class: 'shortcuts-container-registry' do
@@ -283,7 +287,9 @@
%strong.fly-out-top-item-name
= _('Registry')
- - if project_nav_tab?(:wiki)
+ = render_if_exists 'layouts/nav/sidebar/project_packages_link'
+
+ - if project_nav_tab? :wiki
- wiki_url = project_wiki_path(@project, :home)
= nav_link(controller: :wikis) do
= link_to wiki_url, class: 'shortcuts-wiki qa-wiki-link' do
diff --git a/app/views/layouts/notify.html.haml b/app/views/layouts/notify.html.haml
index 8dff12c1b7f..de487a94d40 100644
--- a/app/views/layouts/notify.html.haml
+++ b/app/views/layouts/notify.html.haml
@@ -31,4 +31,6 @@
adjust your notification settings.
= email_action @target_url
+
+ = render_if_exists 'layouts/email_additional_text'
= html_footer_message
diff --git a/app/views/layouts/notify.text.erb b/app/views/layouts/notify.text.erb
index 248916fba63..0ee30c2a6cf 100644
--- a/app/views/layouts/notify.text.erb
+++ b/app/views/layouts/notify.text.erb
@@ -12,5 +12,6 @@
<% end -%>
<%= "You're receiving this email because #{notification_reason_text(@reason)}." %>
+<%= render_if_exists 'layouts/mailer/additional_text' %>
<%= text_footer_message -%>
diff --git a/app/views/notify/closed_issue_email.html.haml b/app/views/notify/closed_issue_email.html.haml
index eb148d72da1..d3733ab3a09 100644
--- a/app/views/notify/closed_issue_email.html.haml
+++ b/app/views/notify/closed_issue_email.html.haml
@@ -1,2 +1,2 @@
%p
- Issue was closed by #{sanitize_name(@updated_by.name)}
+ = _("Issue was closed by %{name} %{reason}").html_safe % { name: sanitize_name(@updated_by.name), reason: closure_reason_text(@closed_via, format: formats.first) }
diff --git a/app/views/notify/closed_issue_email.text.haml b/app/views/notify/closed_issue_email.text.haml
index b1f0a3f37ec..ff2548a4b42 100644
--- a/app/views/notify/closed_issue_email.text.haml
+++ b/app/views/notify/closed_issue_email.text.haml
@@ -1,3 +1,3 @@
-Issue was closed by #{sanitize_name(@updated_by.name)}
+= _("Issue was closed by %{name} %{reason}").html_safe % { name: sanitize_name(@updated_by.name), reason: closure_reason_text(@closed_via, format: formats.first) }
Issue ##{@issue.iid}: #{project_issue_url(@issue.project, @issue)}
diff --git a/app/views/notify/links/ci/builds/_build.text.erb b/app/views/notify/links/ci/builds/_build.text.erb
index 773ae8174e9..afb02f97e5a 100644
--- a/app/views/notify/links/ci/builds/_build.text.erb
+++ b/app/views/notify/links/ci/builds/_build.text.erb
@@ -1 +1 @@
-Job #<%= build.id %> ( <%= pipeline_job_url(pipeline, build) %> )
+Job #<%= build.id %> ( <%= raw_project_job_url(pipeline.project, build) %> )
diff --git a/app/views/notify/member_access_granted_email.html.haml b/app/views/notify/member_access_granted_email.html.haml
index 18dec806539..1c50dba9c97 100644
--- a/app/views/notify/member_access_granted_email.html.haml
+++ b/app/views/notify/member_access_granted_email.html.haml
@@ -1,3 +1,10 @@
+- link_end = '</a>'.html_safe
+- source_type = member_source.model_name.singular
+- leave_link = polymorphic_url([member_source], leave: 1)
+- source_link = link_to(member_source.human_name, member_source.web_url, target: '_blank', rel: 'noopener noreferrer')
+
%p
- You have been granted #{member.human_access} access to the
- #{link_to member_source.human_name, member_source.web_url} #{member_source.model_name.singular}.
+ = _('You have been granted %{access_level} access to the %{source_link} %{source_type}.').html_safe % { access_level: member.human_access, source_link: source_link, source_type: source_type }
+%p
+ - leave_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: leave_link }
+ = _('If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}.').html_safe % { source_type: source_type, leave_link_start: leave_link_start, link_end: link_end }
diff --git a/app/views/notify/member_access_granted_email.text.erb b/app/views/notify/member_access_granted_email.text.erb
index a9fb3a589a5..445009bb413 100644
--- a/app/views/notify/member_access_granted_email.text.erb
+++ b/app/views/notify/member_access_granted_email.text.erb
@@ -1,3 +1,8 @@
-You have been granted <%= member.human_access %> access to the <%= member_source.human_name %> <%= member_source.model_name.singular %>.
+<% source_type = member_source.model_name.singular %>
+<%= _('You have been granted %{access_level} access to the %{source_name} %{source_type}.') % { access_level: member.human_access, source_name: member_source.human_name, source_type: source_type } %>
<%= member_source.web_url %>
+
+<%= _('If this was a mistake you can leave the %{source_type}.') % { source_type: source_type } %>
+
+<%= polymorphic_url([member_source], leave: 1) %>
diff --git a/app/views/notify/new_merge_request_email.html.haml b/app/views/notify/new_merge_request_email.html.haml
index 77d2e65d285..9ab648e2a64 100644
--- a/app/views/notify/new_merge_request_email.html.haml
+++ b/app/views/notify/new_merge_request_email.html.haml
@@ -3,7 +3,7 @@
#{link_to @merge_request.author_name, user_url(@merge_request.author)} created a merge request:
%p.details
- != merge_path_description(@merge_request, '&rarr;')
+ = merge_path_description(@merge_request, '→')
- if @merge_request.assignees.any?
%p
diff --git a/app/views/notify/new_user_email.html.haml b/app/views/notify/new_user_email.html.haml
index dfbb5c75bd3..ec135ae994f 100644
--- a/app/views/notify/new_user_email.html.haml
+++ b/app/views/notify/new_user_email.html.haml
@@ -13,4 +13,5 @@
%p
= link_to "Click here to set your password", edit_password_url(@user, reset_password_token: @token)
%p
- = raw reset_token_expire_message
+ This link is valid for #{password_reset_token_valid_time}.
+ After it expires, you can #{link_to("request a new one", new_user_password_url(user_email: @user.email))}.
diff --git a/app/views/notify/new_user_email.text.erb b/app/views/notify/new_user_email.text.erb
index f3f20f3bfba..7e0db75472d 100644
--- a/app/views/notify/new_user_email.text.erb
+++ b/app/views/notify/new_user_email.text.erb
@@ -1,10 +1,17 @@
Hi <%= sanitize_name(@user.name) %>!
+<% if Gitlab::CurrentSettings.allow_signup? %>
+Your account has been created successfully.
+<% else %>
The Administrator created an account for you. Now you are a member of the company GitLab application.
+<% end %>
login.................. <%= @user.email %>
+
<% if @user.created_by_id %>
- <%= link_to "Click here to set your password", edit_password_url(@user, :reset_password_token => @token) %>
+Click here to set your password:
+<%= edit_password_url(@user, :reset_password_token => @token) %>
- <%= reset_token_expire_message %>
+This link is valid for <%= password_reset_token_valid_time %>. After it expires, you can request a new one here:
+<%= new_user_password_url(user_email: @user.email) %>
<% end %>
diff --git a/app/views/profiles/_event_table.html.haml b/app/views/profiles/_event_table.html.haml
index 9f525547dd9..977ff30d5a6 100644
--- a/app/views/profiles/_event_table.html.haml
+++ b/app/views/profiles/_event_table.html.haml
@@ -1,14 +1,12 @@
%h5.prepend-top-0
- History of authentications
+ = _('History of authentications')
%ul.content-list
- events.each do |event|
%li
%span.description
= audit_icon(event.details[:with], class: "append-right-5")
- Signed in with
- = event.details[:with]
- authentication
+ = _('Signed in with %{authentication} authentication') % { authentication: event.details[:with]}
%span.float-right= time_ago_with_tooltip(event.created_at)
= paginate events, theme: "gitlab"
diff --git a/app/views/profiles/active_sessions/_active_session.html.haml b/app/views/profiles/active_sessions/_active_session.html.haml
index 2bf514d72a5..bb31049111c 100644
--- a/app/views/profiles/active_sessions/_active_session.html.haml
+++ b/app/views/profiles/active_sessions/_active_session.html.haml
@@ -8,18 +8,19 @@
%div
%strong= active_session.ip_address
- if is_current_session
- %div This is your current session
+ %div
+ = _('This is your current session')
- else
%div
- Last accessed on
+ = _('Last accessed on')
= l(active_session.updated_at, format: :short)
%div
%strong= active_session.browser
- on
+ = s_('ProfileSession|on')
%strong= active_session.os
%div
- %strong Signed in
- on
+ %strong= _('Signed in')
+ = s_('ProfileSession|on')
= l(active_session.created_at, format: :short)
diff --git a/app/views/profiles/active_sessions/index.html.haml b/app/views/profiles/active_sessions/index.html.haml
index 8688a52843d..d651319fc3f 100644
--- a/app/views/profiles/active_sessions/index.html.haml
+++ b/app/views/profiles/active_sessions/index.html.haml
@@ -1,4 +1,4 @@
-- page_title 'Active Sessions'
+- page_title _('Active Sessions')
- @content_class = "limit-container-width" unless fluid_layout
.row.prepend-top-default
@@ -6,7 +6,7 @@
%h4.prepend-top-0
= page_title
%p
- This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize.
+ = _('This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize.')
.col-lg-8
.append-bottom-default
diff --git a/app/views/profiles/audit_log.html.haml b/app/views/profiles/audit_log.html.haml
index a924369050b..275c0428d34 100644
--- a/app/views/profiles/audit_log.html.haml
+++ b/app/views/profiles/audit_log.html.haml
@@ -1,4 +1,4 @@
-- page_title "Authentication log"
+- page_title _('Authentication log')
- @content_class = "limit-container-width" unless fluid_layout
.row.prepend-top-default
@@ -6,6 +6,6 @@
%h4.prepend-top-0
= page_title
%p
- This is a security log of important events involving your account.
+ = _('This is a security log of important events involving your account.')
.col-lg-8
= render 'event_table', events: @events
diff --git a/app/views/profiles/chat_names/_chat_name.html.haml b/app/views/profiles/chat_names/_chat_name.html.haml
index 9e82e47c1e1..ff67f92ad07 100644
--- a/app/views/profiles/chat_names/_chat_name.html.haml
+++ b/app/views/profiles/chat_names/_chat_name.html.haml
@@ -21,7 +21,7 @@
- if chat_name.last_used_at
= time_ago_with_tooltip(chat_name.last_used_at)
- else
- Never
+ = _('Never')
%td
- = link_to 'Remove', profile_chat_name_path(chat_name), method: :delete, class: 'btn btn-danger float-right', data: { confirm: 'Are you sure you want to revoke this nickname?' }
+ = link_to _('Remove'), profile_chat_name_path(chat_name), method: :delete, class: 'btn btn-danger float-right', data: { confirm: _('Are you sure you want to revoke this nickname?') }
diff --git a/app/views/profiles/chat_names/index.html.haml b/app/views/profiles/chat_names/index.html.haml
index 4b6e419af50..0c8098a97d5 100644
--- a/app/views/profiles/chat_names/index.html.haml
+++ b/app/views/profiles/chat_names/index.html.haml
@@ -1,4 +1,4 @@
-- page_title 'Chat'
+- page_title _('Chat')
- @content_class = "limit-container-width" unless fluid_layout
.row.prepend-top-default
@@ -6,7 +6,7 @@
%h4.prepend-top-0
= page_title
%p
- You can see your Chat accounts.
+ = _('You can see your chat accounts.')
.col-lg-8
%h5 Active chat names (#{@chat_names.size})
@@ -16,15 +16,15 @@
%table.table.chat-names
%thead
%tr
- %th Project
- %th Service
- %th Team domain
- %th Nickname
- %th Last used
+ %th= _('Project')
+ %th= _('Service')
+ %th= _('Team domain')
+ %th= _('Nickname')
+ %th= _('Last used')
%th
%tbody
= render @chat_names
- else
.settings-message.text-center
- You don't have any active chat names.
+ = _("You don't have any active chat names.")
diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml
index 1823f191fb3..3c20518c038 100644
--- a/app/views/profiles/emails/index.html.haml
+++ b/app/views/profiles/emails/index.html.haml
@@ -1,4 +1,4 @@
-- page_title "Emails"
+- page_title _('Emails')
- @content_class = "limit-container-width" unless fluid_layout
.row.prepend-top-default
@@ -6,56 +6,58 @@
%h4.prepend-top-0
= page_title
%p
- Control emails linked to your account
+ = _('Control emails linked to your account')
.col-lg-8
%h4.prepend-top-0
- Add email address
+ = _('Add email address')
= form_for 'email', url: profile_emails_path do |f|
.form-group
- = f.label :email, class: 'label-bold'
+ = f.label :email, _('Email'), class: 'label-bold'
= f.text_field :email, class: 'form-control'
.prepend-top-default
- = f.submit 'Add email address', class: 'btn btn-success'
+ = f.submit _('Add email address'), class: 'btn btn-success'
%hr
%h4.prepend-top-0
- Linked emails (#{@emails.count + 1})
+ = _('Linked emails (%{email_count})') % { email_count: @emails.count + 1 }
.account-well.append-bottom-default
%ul
%li
- Your Primary Email will be used for avatar detection.
+ = _('Your Primary Email will be used for avatar detection.')
%li
- Your Commit Email will be used for web based operations, such as edits and merges.
+ = _('Your Commit Email will be used for web based operations, such as edits and merges.')
%li
- Your Notification Email will be used for account notifications.
+ - address = profile_notifications_path
+ - notification_message = _('Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set.') % { openingTag: "<a href='#{address}'>".html_safe, closingTag: '</a>'.html_safe}
+ = notification_message.html_safe
%li
- Your Public Email will be displayed on your public profile.
+ = _('Your Public Email will be displayed on your public profile.')
%li
- All email addresses will be used to identify your commits.
+ = _('All email addresses will be used to identify your commits.')
%ul.content-list
%li
= render partial: 'shared/email_with_badge', locals: { email: @primary_email, verified: current_user.confirmed? }
%span.float-right
- %span.badge.badge-success Primary email
+ %span.badge.badge-success= s_('Profiles|Primary email')
- if @primary_email === current_user.commit_email
- %span.badge.badge-info Commit email
+ %span.badge.badge-info= s_('Profiles|Commit email')
- if @primary_email === current_user.public_email
- %span.badge.badge-info Public email
+ %span.badge.badge-info= s_('Profiles|Public email')
- if @primary_email === current_user.notification_email
- %span.badge.badge-info Notification email
+ %span.badge.badge-info= s_('Profiles|Default notification email')
- @emails.each do |email|
%li
= render partial: 'shared/email_with_badge', locals: { email: email.email, verified: email.confirmed? }
%span.float-right
- if email.email === current_user.commit_email
- %span.badge.badge-info Commit email
+ %span.badge.badge-info= s_('Profiles|Commit email')
- if email.email === current_user.public_email
- %span.badge.badge-info Public email
+ %span.badge.badge-info= s_('Profiles|Public email')
- if email.email === current_user.notification_email
- %span.badge.badge-info Notification email
+ %span.badge.badge-info= s_('Profiles|Notification email')
- unless email.confirmed?
- - confirm_title = "#{email.confirmation_sent_at ? 'Resend' : 'Send'} confirmation email"
+ - confirm_title = "#{email.confirmation_sent_at ? _('Resend confirmation email') : _('Send confirmation email')}"
= link_to confirm_title, resend_confirmation_instructions_profile_email_path(email), method: :put, class: 'btn btn-sm btn-warning prepend-left-10'
- = link_to profile_email_path(email), data: { confirm: 'Are you sure?'}, method: :delete, class: 'btn btn-sm btn-danger prepend-left-10' do
- %span.sr-only Remove
+ = link_to profile_email_path(email), data: { confirm: _('Are you sure?')}, method: :delete, class: 'btn btn-sm btn-danger prepend-left-10' do
+ %span.sr-only= _('Remove')
= icon('trash')
diff --git a/app/views/profiles/gpg_keys/_form.html.haml b/app/views/profiles/gpg_keys/_form.html.haml
index 6c4cb614a2b..225487b2638 100644
--- a/app/views/profiles/gpg_keys/_form.html.haml
+++ b/app/views/profiles/gpg_keys/_form.html.haml
@@ -3,8 +3,8 @@
= form_errors(@gpg_key)
.form-group
- = f.label :key, class: 'label-bold'
- = f.text_area :key, class: "form-control", rows: 8, required: true, placeholder: "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+ = f.label :key, s_('Profiles|Key'), class: 'label-bold'
+ = f.text_area :key, class: "form-control", rows: 8, required: true, placeholder: _("Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'.")
.prepend-top-default
- = f.submit 'Add key', class: "btn btn-success"
+ = f.submit s_('Profiles|Add key'), class: "btn btn-success"
diff --git a/app/views/profiles/gpg_keys/_key.html.haml b/app/views/profiles/gpg_keys/_key.html.haml
index d1fd7bc8e71..f8351644df5 100644
--- a/app/views/profiles/gpg_keys/_key.html.haml
+++ b/app/views/profiles/gpg_keys/_key.html.haml
@@ -9,17 +9,19 @@
%code= key.fingerprint
- if key.subkeys.present?
.subkeys
- %span.bold Subkeys:
+ %span.bold
+ = _('Subkeys')
+ = ':'
%ul.subkeys-list
- key.subkeys.each do |subkey|
%li
%code= subkey.fingerprint
.float-right
%span.key-created-at
- created #{time_ago_with_tooltip(key.created_at)}
- = link_to profile_gpg_key_path(key), data: { confirm: 'Are you sure? Removing this GPG key does not affect already signed commits.' }, method: :delete, class: "btn btn-danger prepend-left-10" do
- %span.sr-only Remove
+ = s_('Profiles|Created %{time_ago}'.html_safe) % { time_ago:time_ago_with_tooltip(key.created_at)}
+ = link_to profile_gpg_key_path(key), data: { confirm: _('Are you sure? Removing this GPG key does not affect already signed commits.') }, method: :delete, class: "btn btn-danger prepend-left-10" do
+ %span.sr-only= _('Remove')
= icon('trash')
- = link_to revoke_profile_gpg_key_path(key), data: { confirm: 'Are you sure? All commits that were signed with this GPG key will be unverified.' }, method: :put, class: "btn btn-danger prepend-left-10" do
- %span.sr-only Revoke
- Revoke
+ = link_to revoke_profile_gpg_key_path(key), data: { confirm: _('Are you sure? All commits that were signed with this GPG key will be unverified.') }, method: :put, class: "btn btn-danger prepend-left-10" do
+ %span.sr-only= _('Revoke')
+ = _('Revoke')
diff --git a/app/views/profiles/gpg_keys/_key_table.html.haml b/app/views/profiles/gpg_keys/_key_table.html.haml
index b9b60c218fd..ebbd1c8f672 100644
--- a/app/views/profiles/gpg_keys/_key_table.html.haml
+++ b/app/views/profiles/gpg_keys/_key_table.html.haml
@@ -6,6 +6,6 @@
- else
%p.settings-message.text-center
- if is_admin
- There are no GPG keys associated with this account.
+ = _('There are no GPG keys associated with this account.')
- else
- There are no GPG keys with access to your account.
+ = _('There are no GPG keys with access to your account.')
diff --git a/app/views/profiles/gpg_keys/index.html.haml b/app/views/profiles/gpg_keys/index.html.haml
index 1d2e41cb437..f9f898a9225 100644
--- a/app/views/profiles/gpg_keys/index.html.haml
+++ b/app/views/profiles/gpg_keys/index.html.haml
@@ -1,4 +1,4 @@
-- page_title "GPG Keys"
+- page_title _('GPG Keys')
- @content_class = "limit-container-width" unless fluid_layout
.row.prepend-top-default
@@ -6,16 +6,16 @@
%h4.prepend-top-0
= page_title
%p
- GPG keys allow you to verify signed commits.
+ = _('GPG keys allow you to verify signed commits.')
.col-lg-8
%h5.prepend-top-0
- Add a GPG key
+ = _('Add a GPG key')
%p.profile-settings-content
- Before you can add a GPG key you need to
- = link_to 'generate it.', help_page_path('user/project/repository/gpg_signed_commits/index.md')
+ - help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/project/repository/gpg_signed_commits/index.md') }
+ = _('Before you can add a GPG key you need to %{help_link_start}Generate it.%{help_link_end}'.html_safe) % {help_link_start: help_link_start, help_link_end:'</a>'.html_safe }
= render 'form'
%hr
%h5
- Your GPG keys (#{@gpg_keys.count})
+ = _('Your GPG keys (%{count})') % { count:@gpg_keys.count}
.append-bottom-default
= render 'key_table'
diff --git a/app/views/profiles/keys/_form.html.haml b/app/views/profiles/keys/_form.html.haml
index 21eef08983c..63ef5eaa172 100644
--- a/app/views/profiles/keys/_form.html.haml
+++ b/app/views/profiles/keys/_form.html.haml
@@ -3,11 +3,11 @@
= form_errors(@key)
.form-group
- = f.label :key, class: 'label-bold'
- %p= _("Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key.")
- = f.text_area :key, class: "form-control js-add-ssh-key-validation-input qa-key-public-key-field", rows: 8, required: true, placeholder: s_('Profiles|Typically starts with "ssh-rsa …"')
+ = f.label :key, s_('Profiles|Key'), class: 'label-bold'
+ %p= _("Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key.")
+ = f.text_area :key, class: "form-control js-add-ssh-key-validation-input qa-key-public-key-field", rows: 8, required: true, placeholder: s_('Profiles|Typically starts with "ssh-ed25519 …" or "ssh-rsa …"')
.form-group
- = f.label :title, class: 'label-bold'
+ = f.label :title, _('Title'), class: 'label-bold'
= f.text_field :title, class: "form-control input-lg qa-key-title-field", required: true, placeholder: s_('Profiles|e.g. My MacBook key')
%p.form-text.text-muted= _('Name your individual key via a title')
diff --git a/app/views/profiles/keys/_key.html.haml b/app/views/profiles/keys/_key.html.haml
index ce20994b0f4..b9d73d89334 100644
--- a/app/views/profiles/keys/_key.html.haml
+++ b/app/views/profiles/keys/_key.html.haml
@@ -17,7 +17,8 @@
= key.last_used_at ? time_ago_with_tooltip(key.last_used_at) : 'n/a'
.float-right
%span.key-created-at
- created #{time_ago_with_tooltip(key.created_at)}
- = link_to path_to_key(key, is_admin), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-transparent prepend-left-10" do
- %span.sr-only Remove
- = icon('trash')
+ = s_('Profiles|Created %{time_ago}'.html_safe) % { time_ago:time_ago_with_tooltip(key.created_at)}
+ - if key.can_delete?
+ = link_to path_to_key(key, is_admin), data: { confirm: _('Are you sure?')}, method: :delete, class: "btn btn-transparent prepend-left-10" do
+ %span.sr-only= _('Remove')
+ = icon('trash')
diff --git a/app/views/profiles/keys/_key_details.html.haml b/app/views/profiles/keys/_key_details.html.haml
index 88473c7f72d..0ef01dec493 100644
--- a/app/views/profiles/keys/_key_details.html.haml
+++ b/app/views/profiles/keys/_key_details.html.haml
@@ -3,25 +3,26 @@
.col-md-4
.card
.card-header
- SSH Key
+ = _('SSH Key')
%ul.content-list
%li
- %span.light Title:
+ %span.light= _('Title:')
%strong= @key.title
%li
- %span.light Created on:
+ %span.light= _('Created on:')
%strong= @key.created_at.to_s(:medium)
%li
- %span.light Last used on:
+ %span.light= _('Last used on:')
%strong= @key.last_used_at.try(:to_s, :medium) || 'N/A'
.col-md-8
= form_errors(@key, type: 'key') unless @key.valid?
%p
- %span.light Fingerprint:
+ %span.light= _('Fingerprint:')
%code.key-fingerprint= @key.fingerprint
%pre.well-pre
= @key.key
.col-md-12
.float-right
- = link_to 'Remove', path_to_key(@key, is_admin), data: {confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove delete-key qa-delete-key-button"
+ - if @key.can_delete?
+ = link_to _('Remove'), path_to_key(@key, is_admin), data: {confirm: _('Are you sure?')}, method: :delete, class: "btn btn-remove delete-key qa-delete-key-button"
diff --git a/app/views/profiles/keys/_key_table.html.haml b/app/views/profiles/keys/_key_table.html.haml
index e088140fdd2..4a6d8a1870d 100644
--- a/app/views/profiles/keys/_key_table.html.haml
+++ b/app/views/profiles/keys/_key_table.html.haml
@@ -6,6 +6,6 @@
- else
%p.settings-message.text-center
- if is_admin
- There are no SSH keys associated with this account.
+ = _('There are no SSH keys associated with this account.')
- else
- There are no SSH keys with access to your account.
+ = _('There are no SSH keys with access to your account.')
diff --git a/app/views/profiles/keys/index.html.haml b/app/views/profiles/keys/index.html.haml
index 55ca8d0ebd4..da6aa0fce3a 100644
--- a/app/views/profiles/keys/index.html.haml
+++ b/app/views/profiles/keys/index.html.haml
@@ -1,4 +1,4 @@
-- page_title "SSH Keys"
+- page_title _('SSH Keys')
- @content_class = "limit-container-width" unless fluid_layout
.row.prepend-top-default
@@ -6,10 +6,10 @@
%h4.prepend-top-0
= page_title
%p
- SSH keys allow you to establish a secure connection between your computer and GitLab.
+ = _('SSH keys allow you to establish a secure connection between your computer and GitLab.')
.col-lg-8
%h5.prepend-top-0
- Add an SSH key
+ = _('Add an SSH key')
%p.profile-settings-content
- generate_link_url = help_page_path("ssh/README", anchor: 'generating-a-new-ssh-key-pair')
- existing_link_url = help_page_path("ssh/README", anchor: 'locating-an-existing-ssh-key-pair')
@@ -19,6 +19,6 @@
= render 'form'
%hr
%h5
- Your SSH keys (#{@keys.count})
+ = _('Your SSH keys (%{count})') % { count:@keys.count }
.append-bottom-default
= render 'key_table'
diff --git a/app/views/profiles/keys/show.html.haml b/app/views/profiles/keys/show.html.haml
index 28be6172219..360de7a0c11 100644
--- a/app/views/profiles/keys/show.html.haml
+++ b/app/views/profiles/keys/show.html.haml
@@ -1,5 +1,5 @@
- add_to_breadcrumbs "SSH Keys", profile_keys_path
- breadcrumb_title @key.title
-- page_title @key.title, "SSH Keys"
+- page_title @key.title, _('SSH Keys')
- @content_class = "limit-container-width" unless fluid_layout
= render "key_details"
diff --git a/app/views/profiles/notifications/_group_settings.html.haml b/app/views/profiles/notifications/_group_settings.html.haml
index a12246bcdcc..cf17ee44145 100644
--- a/app/views/profiles/notifications/_group_settings.html.haml
+++ b/app/views/profiles/notifications/_group_settings.html.haml
@@ -1,12 +1,17 @@
-%li.notification-list-item
- %span.notification.fa.fa-holder.append-right-5
- - if setting.global?
- = notification_icon(current_user.global_notification_setting.level)
- - else
- = notification_icon(setting.level)
+.gl-responsive-table-row.notification-list-item
+ .table-section.section-40
+ %span.notification.fa.fa-holder.append-right-5
+ - if setting.global?
+ = notification_icon(current_user.global_notification_setting.level)
+ - else
+ = notification_icon(setting.level)
- %span.str-truncated
- = link_to group.name, group_path(group)
+ %span.str-truncated
+ = link_to group.name, group_path(group)
- .float-right
+ .table-section.section-30.text-right
= render 'shared/notifications/button', notification_setting: setting
+
+ .table-section.section-30
+ = form_for @user.notification_settings.find { |ns| ns.source == group }, url: profile_notifications_group_path(group), method: :put, html: { class: 'update-notifications' } do |f|
+ = f.select :notification_email, @user.all_emails, { include_blank: 'Global notification email' }, class: 'select2 js-group-notification-email'
diff --git a/app/views/profiles/notifications/show.html.haml b/app/views/profiles/notifications/show.html.haml
index e616e5546b3..1f311e9a4a4 100644
--- a/app/views/profiles/notifications/show.html.haml
+++ b/app/views/profiles/notifications/show.html.haml
@@ -1,4 +1,4 @@
-- page_title "Notifications"
+- page_title _('Notifications')
- @content_class = "limit-container-width" unless fluid_layout
%div
@@ -14,12 +14,12 @@
%h4.prepend-top-0
= page_title
%p
- You can specify notification level per group or per project.
+ = _('You can specify notification level per group or per project.')
%p
- By default, all projects and groups will use the global notifications setting.
+ = _('By default, all projects and groups will use the global notifications setting.')
.col-lg-8
%h5.prepend-top-0
- Global notification settings
+ = _('Global notification settings')
= form_for @user, url: profile_notifications_path, method: :put, html: { class: 'update-notifications prepend-top-default' } do |f|
= render_if_exists 'profiles/notifications/email_settings', form: f
@@ -35,19 +35,18 @@
= form_for @user, url: profile_notifications_path, method: :put do |f|
%label{ for: 'user_notified_of_own_activity' }
= f.check_box :notified_of_own_activity
- %span Receive notifications about your own activity
+ %span= _('Receive notifications about your own activity')
%hr
%h5
- Groups (#{@group_notifications.count})
+ = _('Groups (%{count})') % { count: @group_notifications.count }
%div
- %ul.bordered-list
- - @group_notifications.each do |setting|
- = render 'group_settings', setting: setting, group: setting.source
+ - @group_notifications.each do |setting|
+ = render 'group_settings', setting: setting, group: setting.source
%h5
- Projects (#{@project_notifications.count})
+ = _('Projects (%{count})') % { count: @project_notifications.count }
%p.account-well
- To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there.
+ = _('To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there.')
.append-bottom-default
%ul.bordered-list
- @project_notifications.each do |setting|
diff --git a/app/views/profiles/passwords/edit.html.haml b/app/views/profiles/passwords/edit.html.haml
index 0b4b9841ea1..ac8c31189d0 100644
--- a/app/views/profiles/passwords/edit.html.haml
+++ b/app/views/profiles/passwords/edit.html.haml
@@ -1,5 +1,5 @@
-- breadcrumb_title "Edit Password"
-- page_title "Password"
+- breadcrumb_title _('Edit Password')
+- page_title _('Password')
- @content_class = "limit-container-width" unless fluid_layout
.row.prepend-top-default
@@ -7,28 +7,29 @@
%h4.prepend-top-0
= page_title
%p
- After a successful password update, you will be redirected to the login page where you can log in with your new password.
+ = _('After a successful password update, you will be redirected to the login page where you can log in with your new password.')
.col-lg-8
%h5.prepend-top-0
- Change your password
- - unless @user.password_automatically_set?
- or recover your current one
+ - if @user.password_automatically_set
+ = _('Change your password')
+ - else
+ = _('Change your password or recover your current one')
= form_for @user, url: profile_password_path, method: :put, html: {class: "update-password"} do |f|
= form_errors(@user)
- unless @user.password_automatically_set?
.form-group
- = f.label :current_password, class: 'label-bold'
+ = f.label :current_password, _('Current password'), class: 'label-bold'
= f.password_field :current_password, required: true, class: 'form-control'
%p.form-text.text-muted
- You must provide your current password in order to change it.
+ = _('You must provide your current password in order to change it.')
.form-group
- = f.label :password, 'New password', class: 'label-bold'
+ = f.label :password, _('New password'), class: 'label-bold'
= f.password_field :password, required: true, class: 'form-control'
.form-group
- = f.label :password_confirmation, class: 'label-bold'
+ = f.label :password_confirmation, _('Password confirmation'), class: 'label-bold'
= f.password_field :password_confirmation, required: true, class: 'form-control'
.prepend-top-default.append-bottom-default
- = f.submit 'Save password', class: "btn btn-success append-right-10"
+ = f.submit _('Save password'), class: "btn btn-success append-right-10"
- unless @user.password_automatically_set?
- = link_to "I forgot my password", reset_profile_password_path, method: :put, class: "account-btn-link"
+ = link_to _('I forgot my password'), reset_profile_password_path, method: :put, class: "account-btn-link"
diff --git a/app/views/profiles/passwords/new.html.haml b/app/views/profiles/passwords/new.html.haml
index 4b84835429c..ce60455ab89 100644
--- a/app/views/profiles/passwords/new.html.haml
+++ b/app/views/profiles/passwords/new.html.haml
@@ -13,13 +13,18 @@
- unless @user.password_automatically_set?
.form-group.row
- = f.label :current_password, class: 'col-form-label col-sm-2'
- .col-sm-10= f.password_field :current_password, required: true, class: 'form-control'
+ .col-sm-2.col-form-label
+ = f.label :current_password, _('Current password')
+ .col-sm-10
+ = f.password_field :current_password, required: true, class: 'form-control'
.form-group.row
- = f.label :password, class: 'col-form-label col-sm-2'
- .col-sm-10= f.password_field :password, required: true, class: 'form-control'
+ .col-sm-2.col-form-label
+ = f.label :password, _('New password')
+ .col-sm-10
+ = f.password_field :password, required: true, class: 'form-control'
.form-group.row
- = f.label :password_confirmation, class: 'col-form-label col-sm-2'
+ .col-sm-2.col-form-label
+ = f.label :password_confirmation, _('Password confirmation')
.col-sm-10
= f.password_field :password_confirmation, required: true, class: 'form-control'
.form-actions
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index bfe1c3ddf33..4ebfaff0860 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -1,11 +1,12 @@
-- page_title 'Preferences'
+- page_title _('Preferences')
- @content_class = "limit-container-width" unless fluid_layout
= form_for @user, url: profile_preferences_path, remote: true, method: :put, html: { class: 'row prepend-top-default js-preferences-form' } do |f|
.col-lg-4.application-theme
%h4.prepend-top-0
= s_('Preferences|Navigation theme')
- %p Customize the appearance of the application header and navigation sidebar.
+ %p
+ = s_('Preferences|Customize the appearance of the application header and navigation sidebar.')
.col-lg-8.application-theme
- Gitlab::Themes.each do |theme|
= label_tag do
@@ -18,11 +19,11 @@
.col-lg-4.profile-settings-sidebar
%h4.prepend-top-0
- Syntax highlighting theme
+ = s_('Preferences|Syntax highlighting theme')
%p
- This setting allows you to customize the appearance of the syntax.
+ = s_('Preferences|This setting allows you to customize the appearance of the syntax.')
= succeed '.' do
- = link_to 'Learn more', help_page_path('user/profile/preferences', anchor: 'syntax-highlighting-theme'), target: '_blank'
+ = link_to _('Learn more'), help_page_path('user/profile/preferences', anchor: 'syntax-highlighting-theme'), target: '_blank'
.col-lg-8.syntax-theme
- Gitlab::ColorSchemes.each do |scheme|
= label_tag do
@@ -35,31 +36,31 @@
.col-lg-4.profile-settings-sidebar
%h4.prepend-top-0
- Behavior
+ = s_('Preferences|Behavior')
%p
- This setting allows you to customize the behavior of the system layout and default views.
+ = s_('Preferences|This setting allows you to customize the behavior of the system layout and default views.')
= succeed '.' do
- = link_to 'Learn more', help_page_path('user/profile/preferences', anchor: 'behavior'), target: '_blank'
+ = link_to _('Learn more'), help_page_path('user/profile/preferences', anchor: 'behavior'), target: '_blank'
.col-lg-8
.form-group
= f.label :layout, class: 'label-bold' do
- Layout width
+ = s_('Preferences|Layout width')
= f.select :layout, layout_choices, {}, class: 'form-control'
.form-text.text-muted
- Choose between fixed (max. 1280px) and fluid (100%) application layout.
+ = s_('Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout.')
.form-group
= f.label :dashboard, class: 'label-bold' do
- Default dashboard
+ = s_('Preferences|Default dashboard')
= f.select :dashboard, dashboard_choices, {}, class: 'form-control'
= render_if_exists 'profiles/preferences/group_overview_selector', f: f # EE-specific
.form-group
= f.label :project_view, class: 'label-bold' do
- Project overview content
+ = s_('Preferences|Project overview content')
= f.select :project_view, project_view_choices, {}, class: 'form-control'
.form-text.text-muted
- Choose what content you want to see on a project’s overview page.
+ = s_('Preferences|Choose what content you want to see on a project’s overview page.')
.col-sm-12
%hr
@@ -82,5 +83,31 @@
= f.label :first_day_of_week, class: 'label-bold' do
= _('First day of the week')
= f.select :first_day_of_week, first_day_of_week_choices_with_default, {}, class: 'form-control'
+ - if Feature.enabled?(:user_time_settings)
+ .col-sm-12
+ %hr
+ .col-lg-4.profile-settings-sidebar
+ %h4.prepend-top-0= s_('Preferences|Time preferences')
+ %p= s_('Preferences|These settings will update how dates and times are displayed for you.')
+ .col-lg-8
+ .form-group
+ %h5= s_('Preferences|Time format')
+ .checkbox-icon-inline-wrapper.form-check
+ - time_format_label = capture do
+ = s_('Preferences|Display time in 24-hour format')
+ = f.check_box :time_format_in_24h, class: 'form-check-input'
+ = f.label :time_format_in_24h do
+ = time_format_label
+ %h5= s_('Preferences|Time display')
+ .checkbox-icon-inline-wrapper.form-check
+ - time_display_label = capture do
+ = s_('Preferences|Use relative times')
+ = f.check_box :time_display_relative, class: 'form-check-input'
+ = f.label :time_display_relative do
+ = time_display_label
+ .text-muted
+ = s_('Preferences|For example: 30 mins ago.')
+ .col-lg-4.profile-settings-sidebar
+ .col-lg-8
.form-group
= f.submit _('Save changes'), class: 'btn btn-success'
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 02c750a92c3..e36d5192a29 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -47,9 +47,9 @@
- if @user.status
= emoji_icon @user.status.emoji
%span#js-no-emoji-placeholder.no-emoji-placeholder{ class: ('hidden' if @user.status) }
- = sprite_icon('emoji_slightly_smiling_face', css_class: 'award-control-icon-neutral')
- = sprite_icon('emoji_smiley', css_class: 'award-control-icon-positive')
- = sprite_icon('emoji_smile', css_class: 'award-control-icon-super-positive')
+ = sprite_icon('slight-smile', css_class: 'award-control-icon-neutral')
+ = sprite_icon('smiley', css_class: 'award-control-icon-positive')
+ = sprite_icon('smile', css_class: 'award-control-icon-super-positive')
- reset_message_button = button_tag type: :button,
id: 'js-clear-user-status-button',
class: 'clear-user-status btn has-tooltip',
@@ -64,6 +64,18 @@
prepend: emoji_button,
append: reset_message_button,
placeholder: s_("Profiles|What's your status?")
+ - if Feature.enabled?(:user_time_settings)
+ %hr
+ .row.user-time-preferences
+ .col-lg-4.profile-settings-sidebar
+ %h4.prepend-top-0= s_("Profiles|Time settings")
+ %p= s_("Profiles|You can set your current timezone here")
+ .col-lg-8
+ -# TODO: might need an entry in user/profile.md to describe some of these settings
+ -# https://gitlab.com/gitlab-org/gitlab-ce/issues/60070
+ %h5= ("Time zone")
+ = dropdown_tag(_("Select a timezone"), options: { toggle_class: 'btn js-timezone-dropdown input-lg', title: _("Select a timezone"), filter: true, placeholder: s_("OfSearchInADropdown|Filter"), data: { data: timezone_data } } )
+ %input.hidden{ :type => 'hidden', :id => 'user_timezone', :name => 'user[timezone]', value: @user.timezone }
%hr
.row
@@ -80,8 +92,8 @@
= f.text_field :name, required: true, readonly: true, wrapper: { class: 'col-md-9 qa-full-name' },
help: s_("Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you") % { provider_label: attribute_provider_label(:name) }
- else
- = f.text_field :name, label: 'Full name', required: true, title: s_("Profiles|Using emojis in names seems fun, but please try to set a status message instead"), wrapper: { class: 'col-md-9 qa-full-name' }, help: s_("Profiles|Enter your name, so people you know can recognize you")
- = f.text_field :id, readonly: true, label: 'User ID', wrapper: { class: 'col-md-3' }
+ = f.text_field :name, label: s_('Profiles|Full name'), required: true, title: s_("Profiles|Using emojis in names seems fun, but please try to set a status message instead"), wrapper: { class: 'col-md-9 qa-full-name' }, help: s_("Profiles|Enter your name, so people you know can recognize you")
+ = f.text_field :id, readonly: true, label: s_('Profiles|User ID'), wrapper: { class: 'col-md-3' }
= render_if_exists 'profiles/email_settings', form: f
= f.text_field :skype, class: 'input-md', placeholder: s_("Profiles|username")
@@ -91,18 +103,18 @@
- if @user.read_only_attribute?(:location)
= f.text_field :location, readonly: true, help: s_("Profiles|Your location was automatically set based on your %{provider_label} account") % { provider_label: attribute_provider_label(:location) }
- else
- = f.text_field :location, class: 'input-lg', placeholder: s_("Profiles|City, country")
- = f.text_field :organization, class: 'input-md', help: s_("Profiles|Who you represent or work for")
- = f.text_area :bio, rows: 4, maxlength: 250, help: s_("Profiles|Tell us about yourself in fewer than 250 characters")
+ = f.text_field :location, label: s_('Profiles|Location'), class: 'input-lg', placeholder: s_("Profiles|City, country")
+ = f.text_field :organization, label: s_('Profiles|Organization'), class: 'input-md', help: s_("Profiles|Who you represent or work for")
+ = f.text_area :bio, label: s_('Profiles|Bio'), rows: 4, maxlength: 250, help: s_("Profiles|Tell us about yourself in fewer than 250 characters")
%hr
- %h5= ("Private profile")
+ %h5= s_("Private profile")
.checkbox-icon-inline-wrapper
- private_profile_label = capture do
= s_("Profiles|Don't display activity-related personal information on your profiles")
= f.check_box :private_profile, label: private_profile_label, inline: true, wrapper_class: 'mr-0'
= link_to icon('question-circle'), help_page_path('user/profile/index.md', anchor: 'private-profile')
%h5= s_("Profiles|Private contributions")
- = f.check_box :include_private_contributions, label: 'Include private contributions on my profile', wrapper_class: 'mb-2', inline: true
+ = f.check_box :include_private_contributions, label: s_('Profiles|Include private contributions on my profile'), wrapper_class: 'mb-2', inline: true
.help-block
= s_("Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information")
.prepend-top-default.append-bottom-default
diff --git a/app/views/profiles/two_factor_auths/_codes.html.haml b/app/views/profiles/two_factor_auths/_codes.html.haml
index 759d39cf5f5..be0af977011 100644
--- a/app/views/profiles/two_factor_auths/_codes.html.haml
+++ b/app/views/profiles/two_factor_auths/_codes.html.haml
@@ -1,8 +1,6 @@
%p.slead
- Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one
- time each to regain access to your account. Please save them in a safe place, or you
- %b will
- lose access to your account.
+ - lose_2fa_message = _('Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account.') % { b_start:'<b>', b_end:'</b>' }
+ = lose_2fa_message.html_safe
.codes.card
%ul
@@ -11,5 +9,5 @@
%span.monospace= code
.d-flex
- = link_to 'Proceed', profile_account_path, class: 'btn btn-success append-right-10'
- = link_to 'Download codes', "data:text/plain;charset=utf-8,#{CGI.escape(@codes.join("\n"))}", download: "gitlab-recovery-codes.txt", class: 'btn btn-default'
+ = link_to _('Proceed'), profile_account_path, class: 'btn btn-success append-right-10'
+ = link_to _('Download codes'), "data:text/plain;charset=utf-8,#{CGI.escape(@codes.join("\n"))}", download: "gitlab-recovery-codes.txt", class: 'btn btn-default'
diff --git a/app/views/profiles/two_factor_auths/codes.html.haml b/app/views/profiles/two_factor_auths/codes.html.haml
index addf356697a..53907ebffab 100644
--- a/app/views/profiles/two_factor_auths/codes.html.haml
+++ b/app/views/profiles/two_factor_auths/codes.html.haml
@@ -1,5 +1,6 @@
-- page_title 'Recovery Codes', 'Two-factor Authentication'
+- page_title _('Recovery Codes'), _('Two-factor Authentication')
-%h3.page-title Two-factor Authentication Recovery codes
+%h3.page-title
+ = _('Two-factor Authentication Recovery codes')
%hr
= render 'codes'
diff --git a/app/views/profiles/two_factor_auths/create.html.haml b/app/views/profiles/two_factor_auths/create.html.haml
index e330aadac13..973eb8136c4 100644
--- a/app/views/profiles/two_factor_auths/create.html.haml
+++ b/app/views/profiles/two_factor_auths/create.html.haml
@@ -1,6 +1,6 @@
-- page_title 'Two-factor Authentication', 'Account'
+- page_title _('Two-factor Authentication'), _('Account')
.alert.alert-success
- Congratulations! You have enabled Two-factor Authentication!
+ = _('Congratulations! You have enabled Two-factor Authentication!')
= render 'codes'
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index d986c566928..5501e63e027 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -1,72 +1,68 @@
-- page_title 'Two-Factor Authentication', 'Account'
-- add_to_breadcrumbs("Two-Factor Authentication", profile_account_path)
+- page_title _('Two-Factor Authentication'), _('Account')
+- add_to_breadcrumbs(_('Two-Factor Authentication'), profile_account_path)
- @content_class = "limit-container-width" unless fluid_layout
.js-two-factor-auth{ 'data-two-factor-skippable' => "#{two_factor_skippable?}", 'data-two_factor_skip_url' => skip_profile_two_factor_auth_path }
.row.prepend-top-default
.col-lg-4
%h4.prepend-top-0
- Register Two-Factor Authenticator
+ = _('Register Two-Factor Authenticator')
%p
- Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA).
+ = _('Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA).')
.col-lg-8
- if current_user.two_factor_otp_enabled?
%p
- You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication.
+ = _("You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication.")
%p
- If you lose your recovery codes you can generate new ones, invalidating all previous codes.
+ = _('If you lose your recovery codes you can generate new ones, invalidating all previous codes.')
%div
- = link_to 'Disable two-factor authentication', profile_two_factor_auth_path,
+ = link_to _('Disable two-factor authentication'), profile_two_factor_auth_path,
method: :delete,
- data: { confirm: "Are you sure? This will invalidate your registered applications and U2F devices." },
+ data: { confirm: _('Are you sure? This will invalidate your registered applications and U2F devices.') },
class: 'btn btn-danger append-right-10'
= form_tag codes_profile_two_factor_auth_path, {style: 'display: inline-block', method: :post} do |f|
- = submit_tag 'Regenerate recovery codes', class: 'btn'
+ = submit_tag _('Regenerate recovery codes'), class: 'btn'
- else
%p
- Install a soft token authenticator like <a href="https://freeotp.github.io/">FreeOTP</a>
- or Google Authenticator from your application repository and scan this QR code.
- More information is available in the #{link_to('documentation', help_page_path('user/profile/account/two_factor_authentication'))}.
+ - help_link_start = '<a href="%{url}" target="_blank">' % { url: help_page_path('user/profile/account/two_factor_authentication') }
+ - register_2fa_token = _('Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}.') % { free_otp_link:'<a href="https://freeotp.github.io/">FreeOTP</a>', help_link_start:help_link_start, help_link_end:'</a>' }
+ = register_2fa_token.html_safe
.row.append-bottom-10
.col-md-4
= raw @qr_code
.col-md-8
.account-well
%p.prepend-top-0.append-bottom-0
- Can't scan the code?
+ = _("Can't scan the code?")
%p.prepend-top-0.append-bottom-0
- To add the entry manually, provide the following details to the application on your phone.
+ = _('To add the entry manually, provide the following details to the application on your phone.')
%p.prepend-top-0.append-bottom-0
- Account:
- = @account_string
+ = _('Account: %{account}') % { account: @account_string }
%p.prepend-top-0.append-bottom-0
- Key:
- = current_user.otp_secret.scan(/.{4}/).join(' ')
+ = _('Key: %{key}') %{ key: current_user.otp_secret.scan(/.{4}/).join(' ') }
%p.two-factor-new-manual-content
- Time based: Yes
+ = _('Time based: Yes')
= form_tag profile_two_factor_auth_path, method: :post do |f|
- if @error
.alert.alert-danger
= @error
.form-group
- = label_tag :pin_code, nil, class: "label-bold"
+ = label_tag :pin_code, _('Pin code'), class: "label-bold"
= text_field_tag :pin_code, nil, class: "form-control", required: true
.prepend-top-default
- = submit_tag 'Register with two-factor app', class: 'btn btn-success'
+ = submit_tag _('Register with two-factor app'), class: 'btn btn-success'
%hr
.row.prepend-top-default
.col-lg-4
%h4.prepend-top-0
- Register Universal Two-Factor (U2F) Device
+ = _('Register Universal Two-Factor (U2F) Device')
%p
- Use a hardware device to add the second factor of authentication.
+ = _('Use a hardware device to add the second factor of authentication.')
%p
- As U2F devices are only supported by a few browsers, we require that you set up a
- two-factor authentication app before a U2F device. That way you'll always be able to
- log in - even when you're using an unsupported browser.
+ = _("As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser.")
.col-lg-8
- if @u2f_registration.errors.present?
= form_errors(@u2f_registration)
@@ -74,7 +70,8 @@
%hr
- %h5 U2F Devices (#{@u2f_registrations.length})
+ %h5
+ = _('U2F Devices (%{length})') % { length: @u2f_registrations.length }
- if @u2f_registrations.present?
.table-responsive
@@ -85,16 +82,16 @@
%col{ width: "20%" }
%thead
%tr
- %th Name
- %th Registered On
+ %th= _('Name')
+ %th= s_('2FADevice|Registered On')
%th
%tbody
- @u2f_registrations.each do |registration|
%tr
- %td= registration.name.presence || "<no name set>"
+ %td= registration.name.presence || _("<no name set>")
%td= registration.created_at.to_date.to_s(:medium)
- %td= link_to "Delete", profile_u2f_registration_path(registration), method: :delete, class: "btn btn-danger float-right", data: { confirm: "Are you sure you want to delete this device? This action cannot be undone." }
+ %td= link_to _('Delete'), profile_u2f_registration_path(registration), method: :delete, class: "btn btn-danger float-right", data: { confirm: _('Are you sure you want to delete this device? This action cannot be undone.') }
- else
.settings-message.text-center
- You don't have any U2F devices registered yet.
+ = _("You don't have any U2F devices registered yet.")
diff --git a/app/views/projects/_files.html.haml b/app/views/projects/_files.html.haml
index 22a721ee9ad..2b0c3985755 100644
--- a/app/views/projects/_files.html.haml
+++ b/app/views/projects/_files.html.haml
@@ -13,7 +13,12 @@
= render 'shared/commit_well', commit: commit, ref: ref, project: project
- if is_project_overview
- .project-buttons.append-bottom-default
+ .project-buttons.append-bottom-default{ class: ("js-keep-hidden-on-navigation" if vue_file_list_enabled?) }
= render 'stat_anchor_list', anchors: @project.statistics_buttons(show_auto_devops_callout: show_auto_devops_callout)
- = render 'projects/tree/tree_content', tree: @tree, content_url: content_url
+ - if vue_file_list_enabled?
+ #js-tree-list{ data: { project_path: @project.full_path, project_short_path: @project.path, ref: ref, full_name: @project.name_with_namespace } }
+ - if @tree.readme
+ = render "projects/tree/readme", readme: @tree.readme
+ - else
+ = render 'projects/tree/tree_content', tree: @tree, content_url: content_url
diff --git a/app/views/projects/_flash_messages.html.haml b/app/views/projects/_flash_messages.html.haml
index b72f0e39b23..b2dab0b5348 100644
--- a/app/views/projects/_flash_messages.html.haml
+++ b/app/views/projects/_flash_messages.html.haml
@@ -7,3 +7,4 @@
= render 'shared/no_password'
- unless project.empty_repo?
= render 'shared/auto_devops_implicitly_enabled_banner', project: project
+ = render_if_exists 'projects/above_size_limit_warning', project: project
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index 50adc19f524..824fe3c791d 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -1,7 +1,7 @@
- empty_repo = @project.empty_repo?
- show_auto_devops_callout = show_auto_devops_callout?(@project)
- max_project_topic_length = 15
-.project-home-panel{ class: ("empty-project" if empty_repo) }
+.project-home-panel{ class: [("empty-project" if empty_repo), ("js-keep-hidden-on-navigation" if vue_file_list_enabled?)] }
.row.append-bottom-8
.home-panel-title-row.col-md-12.col-lg-6.d-flex
.avatar-container.rect-avatar.s64.home-panel-avatar.append-right-default.float-none
@@ -64,7 +64,7 @@
.home-panel-home-desc.mt-1
- if @project.description.present?
- .home-panel-description
+ .home-panel-description.text-break
.home-panel-description-markdown.read-more-container
= markdown_field(@project, :description)
%button.btn.btn-blank.btn-link.js-read-more-trigger.d-lg-none{ type: "button" }
@@ -80,6 +80,8 @@
- deleted_message = s_('ForkedFromProjectPath|Forked from %{project_name} (deleted)')
= deleted_message % { project_name: fork_source_name(@project) }
+ = render_if_exists "projects/home_mirror"
+
- if @project.badges.present?
.project-badges.mb-2
- @project.badges.each do |badge|
diff --git a/app/views/projects/_import_project_pane.html.haml b/app/views/projects/_import_project_pane.html.haml
index 2b425f18389..28d4f8eb201 100644
--- a/app/views/projects/_import_project_pane.html.haml
+++ b/app/views/projects/_import_project_pane.html.haml
@@ -8,61 +8,67 @@
.import-buttons
- if gitlab_project_import_enabled?
.import_gitlab_project.has-tooltip{ data: { container: 'body' } }
- = link_to new_import_gitlab_project_path, class: 'btn btn_import_gitlab_project project-submit', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "gitlab_export" } do
+ = link_to new_import_gitlab_project_path, class: 'btn btn_import_gitlab_project project-submit', **tracking_attrs(track_label, 'click_button', 'gitlab_export') do
= icon('gitlab', text: 'GitLab export')
- if github_import_enabled?
%div
- = link_to new_import_github_path, class: 'btn js-import-github', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "github" } do
+ = link_to new_import_github_path, class: 'btn js-import-github', **tracking_attrs(track_label, 'click_button', 'github') do
= icon('github', text: 'GitHub')
- if bitbucket_import_enabled?
%div
= link_to status_import_bitbucket_path, class: "btn import_bitbucket #{'how_to_import_link' unless bitbucket_import_configured?}",
- data: { track_label: "#{track_label}", track_event: "click_button", track_property: "bitbucket_cloud" } do
+ **tracking_attrs(track_label, 'click_button', 'bitbucket_cloud') do
= icon('bitbucket', text: 'Bitbucket Cloud')
- unless bitbucket_import_configured?
= render 'bitbucket_import_modal'
- if bitbucket_server_import_enabled?
%div
- = link_to status_import_bitbucket_server_path, class: "btn import_bitbucket",
- data: { track_label: "#{track_label}", track_event: "click_button", track_property: "bitbucket_server" } do
+ = link_to status_import_bitbucket_server_path, class: "btn import_bitbucket", **tracking_attrs(track_label, 'click_button', 'bitbucket_server') do
= icon('bitbucket-square', text: 'Bitbucket Server')
%div
- if gitlab_import_enabled?
%div
= link_to status_import_gitlab_path, class: "btn import_gitlab #{'how_to_import_link' unless gitlab_import_configured?}",
- data: { track_label: "#{track_label}", track_event: "click_button", track_property: "gitlab_com" } do
+ **tracking_attrs(track_label, 'click_button', 'gitlab_com') do
= icon('gitlab', text: 'GitLab.com')
- unless gitlab_import_configured?
= render 'gitlab_import_modal'
- if google_code_import_enabled?
%div
- = link_to new_import_google_code_path, class: 'btn import_google_code', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "google_code" } do
+ = link_to new_import_google_code_path, class: 'btn import_google_code', **tracking_attrs(track_label, 'click_button', 'google_code') do
= icon('google', text: 'Google Code')
- if fogbugz_import_enabled?
%div
- = link_to new_import_fogbugz_path, class: 'btn import_fogbugz', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "fogbugz" } do
+ = link_to new_import_fogbugz_path, class: 'btn import_fogbugz', **tracking_attrs(track_label, 'click_button', 'fogbugz') do
= icon('bug', text: 'Fogbugz')
- if gitea_import_enabled?
%div
- = link_to new_import_gitea_path, class: 'btn import_gitea', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "gitea" } do
- = custom_icon('go_logo')
+ = link_to new_import_gitea_path, class: 'btn import_gitea', **tracking_attrs(track_label, 'click_button', 'gitea') do
+ = custom_icon('gitea_logo')
Gitea
- if git_import_enabled?
%div
- %button.btn.js-toggle-button.js-import-git-toggle-button{ type: "button", data: { toggle_open_class: 'active', data: { toggle_open_class: 'active', track_label: "#{track_label}" , track_event: "click_button", track_property: "repo_url" } } }
+ %button.btn.js-toggle-button.js-import-git-toggle-button{ type: "button", data: { toggle_open_class: 'active' }, **tracking_attrs(track_label, 'click_button', 'repo_url') }
= icon('git', text: 'Repo by URL')
- if manifest_import_enabled?
%div
- = link_to new_import_manifest_path, class: 'btn import_manifest', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "manifest_file" } do
+ = link_to new_import_manifest_path, class: 'btn import_manifest', **tracking_attrs(track_label, 'click_button', 'manifest_file') do
= icon('file-text-o', text: 'Manifest file')
+ - if phabricator_import_enabled?
+ %div
+ = link_to new_import_phabricator_path, class: 'btn import_phabricator', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "phabricator" } do
+ = custom_icon('issues')
+ = _("Phabricator Tasks")
+
+
.js-toggle-content.toggle-import-form{ class: ('hide' if active_tab != 'import') }
= form_for @project, html: { class: 'new_project' } do |f|
%hr
diff --git a/app/views/projects/_merge_request_merge_checks_settings.html.haml b/app/views/projects/_merge_request_merge_checks_settings.html.haml
new file mode 100644
index 00000000000..c21d333f21a
--- /dev/null
+++ b/app/views/projects/_merge_request_merge_checks_settings.html.haml
@@ -0,0 +1,19 @@
+- form = local_assigns.fetch(:form)
+
+.form-group
+ %b= s_('ProjectSettings|Merge checks')
+ %p.text-secondary= s_('ProjectSettings|These checks must pass before merge requests can be merged')
+ .form-check.mb-2.builds-feature
+ = form.check_box :only_allow_merge_if_pipeline_succeeds, class: 'form-check-input'
+ = form.label :only_allow_merge_if_pipeline_succeeds, class: 'form-check-label' do
+ = s_('ProjectSettings|Pipelines must succeed')
+ .descr.text-secondary
+ = s_('ProjectSettings|Pipelines need to be configured to enable this feature.')
+ = link_to icon('question-circle'),
+ help_page_path('ci/merge_request_pipelines/index.md',
+ anchor: 'pipelines-for-merge-requests'),
+ target: '_blank'
+ .form-check.mb-2
+ = form.check_box :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-input'
+ = form.label :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-label' do
+ = s_('ProjectSettings|All discussions must be resolved')
diff --git a/app/views/projects/_merge_request_merge_method_settings.html.haml b/app/views/projects/_merge_request_merge_method_settings.html.haml
index 9082bfc409d..47c311f42d0 100644
--- a/app/views/projects/_merge_request_merge_method_settings.html.haml
+++ b/app/views/projects/_merge_request_merge_method_settings.html.haml
@@ -1,30 +1,33 @@
- form = local_assigns.fetch(:form)
.form-group
- = label_tag :merge_method_merge, class: 'label-bold' do
- = _('Merge method')
- .form-check
+ %b= s_('ProjectSettings|Merge method')
+ %p.text-secondary= s_('ProjectSettings|This will dictate the commit history when you merge a merge request')
+ .form-check.mb-2
= form.radio_button :merge_method, :merge, class: "js-merge-method-radio form-check-input"
= label_tag :project_merge_method_merge, class: 'form-check-label' do
- .mb-3
- = _('Merge commit')
- .text-secondary
- = _('A merge commit is created for every merge, and merging is allowed as long as there are no conflicts.')
+ = s_('ProjectSettings|Merge commit')
+ .descr.text-secondary
+ = s_('ProjectSettings|Every merge creates a merge commit')
-.form-check
- = form.radio_button :merge_method, :rebase_merge, class: "js-merge-method-radio form-check-input"
- = label_tag :project_merge_method_rebase_merge, class: 'form-check-label' do
- .mb-3
- = _('Merge commit with semi-linear history')
- .text-secondary
- = _('A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build.')
- .text-secondary
- = _('When fast-forward merge is not possible, the user is given the option to rebase.')
+ .form-check.mb-2
+ = form.radio_button :merge_method, :rebase_merge, class: "js-merge-method-radio form-check-input"
+ = label_tag :project_merge_method_rebase_merge, class: 'form-check-label' do
+ = s_('ProjectSettings|Merge commit with semi-linear history')
+ .descr.text-secondary
+ = s_('ProjectSettings|Every merge creates a merge commit')
+ %br
+ = s_('ProjectSettings|Fast-forward merges only')
+ %br
+ = s_('ProjectSettings|When conflicts arise the user is given the option to rebase')
-.form-check
- = form.radio_button :merge_method, :ff, class: "js-merge-method-radio qa-radio-button-merge-ff form-check-input"
- = label_tag :project_merge_method_ff, class: 'form-check-label' do
- .mb-3
- = _('Fast-forward merge')
- .text-secondary
- = _('No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase.')
+ .form-check.mb-2
+ = form.radio_button :merge_method, :ff, class: "js-merge-method-radio qa-radio-button-merge-ff form-check-input"
+ = label_tag :project_merge_method_ff, class: 'form-check-label' do
+ = s_('ProjectSettings|Fast-forward merge')
+ .descr.text-secondary
+ = s_('ProjectSettings|No merge commits are created')
+ %br
+ = s_('ProjectSettings|Fast-forward merges only')
+ %br
+ = s_('ProjectSettings|When conflicts arise the user is given the option to rebase')
diff --git a/app/views/projects/_merge_request_merge_options_settings.html.haml b/app/views/projects/_merge_request_merge_options_settings.html.haml
new file mode 100644
index 00000000000..5ab475822de
--- /dev/null
+++ b/app/views/projects/_merge_request_merge_options_settings.html.haml
@@ -0,0 +1,14 @@
+- form = local_assigns.fetch(:form)
+
+.form-group
+ %b= s_('ProjectSettings|Merge options')
+ %p.text-secondary= s_('ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed')
+ = render_if_exists 'projects/merge_pipelines_settings', form: form
+ .form-check.mb-2
+ = form.check_box :resolve_outdated_diff_discussions, class: 'form-check-input'
+ = form.label :resolve_outdated_diff_discussions, class: 'form-check-label' do
+ = s_('ProjectSettings|Automatically resolve merge request diff discussions when they become outdated')
+ .form-check.mb-2
+ = form.check_box :printing_merge_request_link_enabled, class: 'form-check-input'
+ = form.label :printing_merge_request_link_enabled, class: 'form-check-label' do
+ = s_('ProjectSettings|Show link to create/view merge request when pushing from the command line')
diff --git a/app/views/projects/_merge_request_merge_settings.html.haml b/app/views/projects/_merge_request_merge_settings.html.haml
deleted file mode 100644
index 3a9f7ca42db..00000000000
--- a/app/views/projects/_merge_request_merge_settings.html.haml
+++ /dev/null
@@ -1,24 +0,0 @@
-- form = local_assigns.fetch(:form)
-
-.form-group
- .form-check.builds-feature{ class: ("hidden" if @project && @project.project_feature.send(:builds_access_level) == 0) }
- = form.check_box :only_allow_merge_if_pipeline_succeeds, class: 'form-check-input'
- = form.label :only_allow_merge_if_pipeline_succeeds, class: 'form-check-label' do
- .mb-3
- = _('Only allow merge requests to be merged if the pipeline succeeds')
- .text-secondary
- = _('Pipelines need to be configured to enable this feature.')
- = link_to icon('question-circle'), help_page_path('user/project/merge_requests/merge_when_pipeline_succeeds', anchor: 'only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds'), target: '_blank'
- = render_if_exists 'projects/merge_pipelines_settings', form: form
- .form-check
- = form.check_box :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-input'
- = form.label :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-label' do
- %p= _('Only allow merge requests to be merged if all discussions are resolved')
- .form-check
- = form.check_box :resolve_outdated_diff_discussions, class: 'form-check-input'
- = form.label :resolve_outdated_diff_discussions, class: 'form-check-label' do
- %p= _('Automatically resolve merge request diff discussions when they become outdated')
- .form-check
- = form.check_box :printing_merge_request_link_enabled, class: 'form-check-input'
- = form.label :printing_merge_request_link_enabled, class: 'form-check-label' do
- %p= _('Show link to create/view merge request when pushing from the command line')
diff --git a/app/views/projects/_merge_request_settings.html.haml b/app/views/projects/_merge_request_settings.html.haml
index c80e831dd33..f2ba38387a3 100644
--- a/app/views/projects/_merge_request_settings.html.haml
+++ b/app/views/projects/_merge_request_settings.html.haml
@@ -2,4 +2,6 @@
= render 'projects/merge_request_merge_method_settings', project: @project, form: form
-= render 'projects/merge_request_merge_settings', form: form
+= render 'projects/merge_request_merge_options_settings', project: @project, form: form
+
+= render 'projects/merge_request_merge_checks_settings', project: @project, form: form
diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml
index 1c1c7d832bd..e423631ec99 100644
--- a/app/views/projects/_new_project_fields.html.haml
+++ b/app/views/projects/_new_project_fields.html.haml
@@ -1,4 +1,4 @@
-- visibility_level = params.dig(:project, :visibility_level) || default_project_visibility
+- visibility_level = selected_visibility_level(@project, params.dig(:project, :visibility_level))
- ci_cd_only = local_assigns.fetch(:ci_cd_only, false)
- hide_init_with_readme = local_assigns.fetch(:hide_init_with_readme, false)
- track_label = local_assigns.fetch(:track_label, 'blank_project')
@@ -54,7 +54,7 @@
.form-group.row.initialize-with-readme-setting
%div{ :class => "col-sm-12" }
.form-check
- = check_box_tag 'project[initialize_with_readme]', '1', false, class: 'form-check-input', data: { track_label: "#{track_label}", track_event: "activate_form_input", track_property: "init_with_readme" }
+ = check_box_tag 'project[initialize_with_readme]', '1', false, class: 'form-check-input qa-initialize-with-readme-checkbox', data: { track_label: "#{track_label}", track_event: "activate_form_input", track_property: "init_with_readme" }
= label_tag 'project[initialize_with_readme]', class: 'form-check-label' do
.option-title
%strong Initialize repository with a README
diff --git a/app/views/projects/_zen.html.haml b/app/views/projects/_zen.html.haml
index afc40ca4eab..c502b392384 100644
--- a/app/views/projects/_zen.html.haml
+++ b/app/views/projects/_zen.html.haml
@@ -8,6 +8,7 @@
= f.text_area attr,
class: classes,
placeholder: placeholder,
+ dir: 'auto',
data: { supports_quick_actions: supports_quick_actions,
supports_autocomplete: supports_autocomplete }
- else
diff --git a/app/views/projects/blob/_header_content.html.haml b/app/views/projects/blob/_header_content.html.haml
index 88fa31a73b0..7ed71a7d43c 100644
--- a/app/views/projects/blob/_header_content.html.haml
+++ b/app/views/projects/blob/_header_content.html.haml
@@ -6,7 +6,7 @@
= copy_file_path_button(blob.path)
- %small
+ %small.mr-1
= number_to_human_size(blob.raw_size)
- if blob.stored_externally? && blob.external_storage == :lfs
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index 91c51d5e091..a5eaae2dff4 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -10,7 +10,7 @@
.branch-info
.branch-title
= sprite_icon('fork', size: 12)
- = link_to project_tree_path(@project, branch.name), class: 'item-title str-truncated-100 ref-name prepend-left-8' do
+ = link_to project_tree_path(@project, branch.name), class: 'item-title str-truncated-100 ref-name prepend-left-8 qa-branch-name' do
= branch.name
- if branch.name == @repository.root_ref
%span.badge.badge-primary.prepend-left-5 default
@@ -22,6 +22,8 @@
%span.badge.badge-success.prepend-left-5
= s_('Branches|protected')
+ = render_if_exists 'projects/branches/diverged_from_upstream', branch: branch
+
.block-truncated
- if commit
= render 'projects/branches/commit', commit: commit, project: @project
diff --git a/app/views/projects/branches/_commit.html.haml b/app/views/projects/branches/_commit.html.haml
index 7892019bb15..e33e9509e3a 100644
--- a/app/views/projects/branches/_commit.html.haml
+++ b/app/views/projects/branches/_commit.html.haml
@@ -1,9 +1,9 @@
-.branch-commit
+.branch-commit.cgray
.icon-container.commit-icon
= custom_icon("icon_commit")
= link_to commit.short_id, project_commit_path(project, commit.id), class: "commit-sha"
&middot;
%span.str-truncated
- = link_to_markdown commit.title, project_commit_path(project, commit.id), class: "commit-row-message"
+ = link_to_markdown commit.title, project_commit_path(project, commit.id), class: "commit-row-message cgray"
&middot;
#{time_ago_with_tooltip(commit.committed_date)}
diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml
index 43f1cd01b67..d270e461ac8 100644
--- a/app/views/projects/branches/index.html.haml
+++ b/app/views/projects/branches/index.html.haml
@@ -1,5 +1,6 @@
- @no_container = true
- page_title _('Branches')
+- add_to_breadcrumbs(_('Repository'), project_tree_path(@project))
%div{ class: container_class }
.top-area.adjust
@@ -44,6 +45,8 @@
= link_to new_project_branch_path(@project), class: 'btn btn-success' do
= s_('Branches|New branch')
+ = render_if_exists 'projects/commits/mirror_status'
+
- if can?(current_user, :admin_project, @project)
- project_settings_link = link_to s_('Branches|project settings'), project_protected_branches_path(@project)
.row-content-block
diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml
index 4eb53faa6ff..4762045ee96 100644
--- a/app/views/projects/buttons/_download.html.haml
+++ b/app/views/projects/buttons/_download.html.haml
@@ -7,31 +7,22 @@
= sprite_icon('download')
%span.sr-only= _('Select Archive Format')
= sprite_icon("arrow-down")
- %ul.dropdown-menu.dropdown-menu-right{ role: 'menu' }
- %li.dropdown-header
- #{ _('Source code') }
- %li
- = link_to project_archive_path(project, id: tree_join(ref, archive_prefix), format: 'zip'), rel: 'nofollow', download: '' do
- %span= _('Download zip')
- %li
- = link_to project_archive_path(project, id: tree_join(ref, archive_prefix), format: 'tar.gz'), rel: 'nofollow', download: '' do
- %span= _('Download tar.gz')
- %li
- = link_to project_archive_path(project, id: tree_join(ref, archive_prefix), format: 'tar.bz2'), rel: 'nofollow', download: '' do
- %span= _('Download tar.bz2')
- %li
- = link_to project_archive_path(project, id: tree_join(ref, archive_prefix), format: 'tar'), rel: 'nofollow', download: '' do
- %span= _('Download tar')
-
+ .dropdown-menu.dropdown-menu-right{ role: 'menu' }
+ %section
+ %h5.m-0.dropdown-bold-header= _('Download source code')
+ .dropdown-menu-content
+ = render 'projects/buttons/download_links', project: project, ref: ref, archive_prefix: archive_prefix, path: nil
+ - if directory? && Feature.enabled?(:git_archive_path, default_enabled: true)
+ %section.border-top.pt-1.mt-1
+ %h5.m-0.dropdown-bold-header= _('Download this directory')
+ .dropdown-menu-content
+ = render 'projects/buttons/download_links', project: project, ref: ref, archive_prefix: archive_prefix, path: @path
- if pipeline && pipeline.latest_builds_with_artifacts.any?
- %li.dropdown-header Artifacts
- - unless pipeline.latest?
- - latest_pipeline = project.pipeline_for(ref)
- %li
- .unclickable= ci_status_for_statuseable(latest_pipeline)
- %li.dropdown-header Previous Artifacts
- - pipeline.latest_builds_with_artifacts.each do |job|
- %li
- = link_to latest_succeeded_project_artifacts_path(project, "#{ref}/download", job: job.name), rel: 'nofollow', download: '' do
- %span
- #{s_('DownloadArtifacts|Download')} '#{job.name}'
+ %section.border-top.pt-1.mt-1
+ %h5.m-0.dropdown-bold-header= _('Download artifacts')
+ - unless pipeline.latest?
+ %span.unclickable= ci_status_for_statuseable(project.pipeline_for(ref))
+ %h6.m-0.dropdown-header= _('Previous Artifacts')
+ %ul
+ - pipeline.latest_builds_with_artifacts.each do |job|
+ %li= link_to job.name, latest_succeeded_project_artifacts_path(project, "#{ref}/download", job: job.name), rel: 'nofollow', download: ''
diff --git a/app/views/projects/buttons/_download_links.html.haml b/app/views/projects/buttons/_download_links.html.haml
new file mode 100644
index 00000000000..d344167a6c5
--- /dev/null
+++ b/app/views/projects/buttons/_download_links.html.haml
@@ -0,0 +1,5 @@
+- formats = [['zip', 'btn-primary'], ['tar.gz'], ['tar.bz2'], ['tar']]
+
+.btn-group.ml-0.w-100
+ - formats.each do |(fmt, extra_class)|
+ = link_to fmt, project_archive_path(project, id: tree_join(ref, archive_prefix), path: path, format: fmt), rel: 'nofollow', download: '', class: "btn btn-xs #{extra_class}"
diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml
index 6d48475d505..bdf7b933ab8 100644
--- a/app/views/projects/ci/builds/_build.html.haml
+++ b/app/views/projects/ci/builds/_build.html.haml
@@ -12,7 +12,7 @@
%td.status
= render "ci/status/badge", status: job.detailed_status(current_user), title: job.status_title
- %td.branch-commit
+ %td.branch-commit.cgray
- if can?(current_user, :read_build, job)
= link_to project_job_path(job.project, job) do
%span.build-link ##{job.id}
@@ -53,9 +53,10 @@
%span.badge.badge-info= _('manual')
- if pipeline_link
- %td
- = link_to pipeline_path(pipeline) do
+ %td.pipeline-link
+ = link_to pipeline_path(pipeline), class: 'has-tooltip', title: _('Pipeline ID (IID)') do
%span.pipeline-id ##{pipeline.id}
+ %span.pipeline-iid (##{pipeline.iid})
%span by
- if pipeline.user
= user_avatar(user: pipeline.user, size: 20)
diff --git a/app/views/projects/cleanup/_show.html.haml b/app/views/projects/cleanup/_show.html.haml
index 888be4ee282..ed3c9890efd 100644
--- a/app/views/projects/cleanup/_show.html.haml
+++ b/app/views/projects/cleanup/_show.html.haml
@@ -1,4 +1,4 @@
-- expanded = Rails.env.test?
+- expanded = expanded_by_default?
%section.settings.no-animate#cleanup{ class: ('expanded' if expanded) }
.settings-header
diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml
index a0db48bf8ff..77ea2c04b28 100644
--- a/app/views/projects/commit/_commit_box.html.haml
+++ b/app/views/projects/commit/_commit_box.html.haml
@@ -28,7 +28,7 @@
= link_to project_tree_path(@project, @commit), class: "btn btn-default append-right-10 d-none d-sm-none d-md-inline" do
#{ _('Browse files') }
.dropdown.inline
- %a.btn.btn-default.dropdown-toggle.qa-options-button{ data: { toggle: "dropdown" } }
+ %a.btn.btn-default.dropdown-toggle.qa-options-button.d-md-inline{ data: { toggle: "dropdown" } }
%span= _('Options')
= icon('caret-down')
%ul.dropdown-menu.dropdown-menu-right
@@ -81,7 +81,7 @@
= link_to project_pipeline_path(@project, last_pipeline.id), class: "ci-status-icon-#{last_pipeline.status}" do
= ci_icon_for_status(last_pipeline.status)
#{ _('Pipeline') }
- = link_to "##{last_pipeline.id}", project_pipeline_path(@project, last_pipeline.id)
+ = link_to "##{last_pipeline.id} (##{last_pipeline.iid})", project_pipeline_path(@project, last_pipeline.id), class: "has-tooltip", title: _('Pipeline ID (IID)')
= ci_label_for_status(last_pipeline.status)
- if last_pipeline.stages_count.nonzero?
#{ n_(s_('Pipeline|with stage'), s_('Pipeline|with stages'), last_pipeline.stages_count) }
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index ce55dd78747..87b9920e8b4 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -9,10 +9,13 @@
- commit_status = commit.present(current_user: current_user).status_for(ref)
- link = commit_path(project, commit, merge_request: merge_request)
+
+- show_project_name = local_assigns.fetch(:show_project_name, false)
+
%li.commit.flex-row.js-toggle-container{ id: "commit-#{commit.short_id}" }
.avatar-cell.d-none.d-sm-block
- = author_avatar(commit, size: 36, has_tooltip: false)
+ = author_avatar(commit, size: 40, has_tooltip: false)
.commit-detail.flex-list
.commit-content.qa-commit-content
@@ -32,6 +35,7 @@
- commit_timeago = time_ago_with_tooltip(commit.authored_date, placement: 'bottom')
- commit_text = _('%{commit_author_link} authored %{commit_timeago}') % { commit_author_link: commit_author_link, commit_timeago: commit_timeago }
#{ commit_text.html_safe }
+ = render_if_exists 'projects/commits/project_namespace', show_project_name: show_project_name, project: project
- if commit.description?
%pre.commit-row-description.js-toggle-content.append-bottom-8
@@ -49,7 +53,7 @@
.js-commit-pipeline-status{ data: { endpoint: pipelines_project_commit_path(project, commit.id, ref: ref) } }
.commit-sha-group.d-none.d-sm-flex
- .label.label-monospace
+ .label.label-monospace.monospace
= commit.short_id
= clipboard_button(text: commit.id, title: _("Copy commit SHA to clipboard"), class: "btn btn-default", container: "body")
= link_to_browse_code(project, commit)
diff --git a/app/views/projects/commits/_inline_commit.html.haml b/app/views/projects/commits/_inline_commit.html.haml
index caaff082cc3..56bebeca581 100644
--- a/app/views/projects/commits/_inline_commit.html.haml
+++ b/app/views/projects/commits/_inline_commit.html.haml
@@ -3,6 +3,6 @@
= link_to commit.short_id, project_commit_path(project, commit), class: "commit-sha"
&nbsp;
%span.str-truncated
- = link_to_markdown_field(commit, :title, project_commit_path(project, commit.id), class: "commit-row-message")
+ = link_to_markdown_field(commit, :title, project_commit_path(project, commit.id), class: "commit-row-message cgray")
.float-right
#{time_ago_with_tooltip(commit.committed_date)}
diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml
index 9d254463fb6..2db1efdd52f 100644
--- a/app/views/projects/commits/show.html.haml
+++ b/app/views/projects/commits/show.html.haml
@@ -30,6 +30,8 @@
= link_to project_commits_path(@project, @ref, rss_url_options), title: _("Commits feed"), class: 'btn' do
= icon("rss")
+ = render_if_exists 'projects/commits/mirror_status'
+
%div{ id: dom_id(@project) }
%ol#commits-list.list-unstyled.content_list
= render 'commits', project: @project, ref: @ref
diff --git a/app/views/projects/default_branch/_show.html.haml b/app/views/projects/default_branch/_show.html.haml
index ff6a9d49a61..59efcde5825 100644
--- a/app/views/projects/default_branch/_show.html.haml
+++ b/app/views/projects/default_branch/_show.html.haml
@@ -1,4 +1,4 @@
-- expanded = Rails.env.test?
+- expanded = expanded_by_default?
%section.settings.no-animate#default-branch-settings{ class: ('expanded' if expanded) }
.settings-header
diff --git a/app/views/projects/deploy_keys/_index.html.haml b/app/views/projects/deploy_keys/_index.html.haml
index 24d665761cc..fcf27351a21 100644
--- a/app/views/projects/deploy_keys/_index.html.haml
+++ b/app/views/projects/deploy_keys/_index.html.haml
@@ -1,4 +1,4 @@
-- expanded = Rails.env.test?
+- expanded = expanded_by_default?
%section.qa-deploy-keys-settings.settings.no-animate#js-deploy-keys-settings{ class: ('expanded' if expanded) }
.settings-header
%h4
diff --git a/app/views/projects/deployments/_commit.html.haml b/app/views/projects/deployments/_commit.html.haml
index 9774b797928..743aa60b3ba 100644
--- a/app/views/projects/deployments/_commit.html.haml
+++ b/app/views/projects/deployments/_commit.html.haml
@@ -1,5 +1,5 @@
.table-mobile-content
- .branch-commit
+ .branch-commit.cgray
- if deployment.ref
%span.icon-container
= deployment.tag? ? icon('tag') : sprite_icon('fork', css_class: 'sprite')
@@ -12,6 +12,6 @@
%span.flex-truncate-child
- if commit_title = deployment.commit_title
= author_avatar(deployment.commit, size: 20)
- = link_to_markdown commit_title, project_commit_path(@project, deployment.sha), class: "commit-row-message"
+ = link_to_markdown commit_title, project_commit_path(@project, deployment.sha), class: "commit-row-message cgray"
- else
= _("Can't find HEAD commit for this branch")
diff --git a/app/views/projects/diffs/_content.html.haml b/app/views/projects/diffs/_content.html.haml
index 68f74f702ea..590fcdb0234 100644
--- a/app/views/projects/diffs/_content.html.haml
+++ b/app/views/projects/diffs/_content.html.haml
@@ -1,2 +1,2 @@
.diff-content
- = render 'projects/diffs/viewer', viewer: diff_file.rich_viewer || diff_file.simple_viewer
+ = render 'projects/diffs/viewer', viewer: diff_file.viewer
diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml
index 311b0be19ab..9587ea4696b 100644
--- a/app/views/projects/diffs/_parallel_view.html.haml
+++ b/app/views/projects/diffs/_parallel_view.html.haml
@@ -1,7 +1,7 @@
/ Side-by-side diff view
.text-file{ data: diff_view_data }
- %table.diff-wrap-lines.code.js-syntax-highlight
+ %table.diff-wrap-lines.code.code-commit.js-syntax-highlight
- diff_file.parallel_diff_lines.each do |line|
- left = line[:left]
- right = line[:right]
diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml
index 018c5b38536..641a0689c26 100644
--- a/app/views/projects/diffs/_text_file.html.haml
+++ b/app/views/projects/diffs/_text_file.html.haml
@@ -3,7 +3,7 @@
.suppressed-container
%a.show-suppressed-diff.cursor-pointer.js-show-suppressed-diff= _("Changes suppressed. Click to show.")
-%table.text-file.diff-wrap-lines.code.js-syntax-highlight.commit-diff{ data: diff_view_data, class: too_big ? 'hide' : '' }
+%table.text-file.diff-wrap-lines.code.code-commit.js-syntax-highlight.commit-diff{ data: diff_view_data, class: too_big ? 'hide' : '' }
= render partial: "projects/diffs/line",
collection: diff_file.highlighted_diff_lines,
as: :line,
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 1a3e4a5d608..c15b84d0aac 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -1,7 +1,7 @@
- breadcrumb_title _("General Settings")
- page_title _("General")
- @content_class = "limit-container-width" unless fluid_layout
-- expanded = Rails.env.test?
+- expanded = expanded_by_default?
%section.settings.general-settings.no-animate.expanded#js-general-settings
.settings-header
@@ -27,7 +27,7 @@
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Merge requests')
%button.btn.btn-default.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
- %p= _('Choose your merge method, set up a default merge request description template.')
+ %p= _('Choose your merge method, options, checks, and set up a default merge request description template.')
.settings-content
= render_if_exists 'shared/promotions/promote_mr_features'
diff --git a/app/views/projects/forks/error.html.haml b/app/views/projects/forks/error.html.haml
index e8a89b8c6fc..b37dba8b35d 100644
--- a/app/views/projects/forks/error.html.haml
+++ b/app/views/projects/forks/error.html.haml
@@ -1,24 +1,20 @@
-- page_title "Fork project"
+- page_title _("Fork project")
- if @forked_project && !@forked_project.saved?
.alert.alert-danger.alert-block
%h4
= sprite_icon('fork', size: 16)
- Fork Error!
+ = _("Fork Error!")
%p
- You tried to fork
- = link_to_project @project
- but it failed for the following reason:
-
+ = _("You tried to fork %{link_to_the_project} but it failed for the following reason:").html_safe % { link_to_the_project: link_to_project(@project) }
- if @forked_project && @forked_project.errors.any?
%p
&ndash;
- error = @forked_project.errors.full_messages.first
- if error.include?("already been taken")
- Name has already been taken
+ = _("Name has already been taken")
- else
= error
%p
- = link_to new_project_fork_path(@project), title: "Fork", class: "btn" do
- Try to fork again
+ = link_to _("Try to fork again"), new_project_fork_path(@project), title: _("Fork"), class: "btn"
diff --git a/app/views/projects/forks/index.html.haml b/app/views/projects/forks/index.html.haml
index c63c34c4ebb..0397a7034c7 100644
--- a/app/views/projects/forks/index.html.haml
+++ b/app/views/projects/forks/index.html.haml
@@ -5,12 +5,12 @@
.nav-controls
= form_tag request.original_url, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f|
- = search_field_tag :filter_projects, nil, placeholder: 'Search forks', class: 'projects-list-filter project-filter-form-field form-control input-short',
+ = search_field_tag :filter_projects, nil, placeholder: _('Search forks'), class: 'projects-list-filter project-filter-form-field form-control input-short',
spellcheck: false, data: { 'filter-selector' => 'span.namespace-name' }
.dropdown
%button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
- %span.light sort:
+ %span.light= _("sort:")
- if @sort.present?
= sort_options_hash[@sort]
- else
@@ -30,13 +30,12 @@
- if current_user && can?(current_user, :fork_project, @project)
- if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
- = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn btn-success' do
+ = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: _('Go to your fork'), class: 'btn btn-success' do
= sprite_icon('fork', size: 12)
- %span Fork
+ %span= _('Fork')
- else
- = link_to new_project_fork_path(@project), title: "Fork project", class: 'btn btn-success' do
+ = link_to new_project_fork_path(@project), title: _("Fork project"), class: 'btn btn-success' do
= sprite_icon('fork', size: 12)
- %span Fork
-
+ %span= _('Fork')
= render 'projects', projects: @forks
diff --git a/app/views/projects/forks/new.html.haml b/app/views/projects/forks/new.html.haml
index a603b1024eb..bf03353a565 100644
--- a/app/views/projects/forks/new.html.haml
+++ b/app/views/projects/forks/new.html.haml
@@ -1,13 +1,11 @@
-- page_title "Fork project"
+- page_title _("Fork project")
.row.prepend-top-default
.col-lg-3
%h4.prepend-top-0
- Fork project
+ = _("Fork project")
%p
- A fork is a copy of a project.
- %br
- Forking a repository allows you to make changes without affecting the original project.
+ = _("A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project.").html_safe
.col-lg-9
- if @namespaces.present?
.fork-thumbnail-container.js-fork-content
@@ -17,13 +15,13 @@
= render 'fork_button', namespace: namespace
- else
%strong
- No available namespaces to fork the project.
+ = _("No available namespaces to fork the project.")
%p.prepend-top-default
- You must have permission to create a project in a namespace before forking.
+ = _("You must have permission to create a project in a namespace before forking.")
.save-project-loader.hide.js-fork-content
%h2.text-center
= icon('spinner spin')
- Forking repository
+ = _("Forking repository")
%p.text-center
- Please wait a moment, this page will automatically refresh when ready.
+ = _("Please wait a moment, this page will automatically refresh when ready.")
diff --git a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
index 7614d40ba1f..1118b44d7a2 100644
--- a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
+++ b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
@@ -5,11 +5,11 @@
- pipeline_link = local_assigns.fetch(:pipeline_link, false)
- stage = local_assigns.fetch(:stage, false)
-%tr.generic_commit_status{ class: ('retried' if retried) }
+%tr.generic-commit-status{ class: ('retried' if retried) }
%td.status
= render 'ci/status/badge', status: generic_commit_status.detailed_status(current_user)
- %td.generic_commit_status-link
+ %td.generic-commit-status-link
- if can?(current_user, :read_commit_status, generic_commit_status) && generic_commit_status.target_url
= link_to generic_commit_status.target_url do
%span.build-link ##{generic_commit_status.id}
diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml
index 377b2a6d8d9..9293aa1b309 100644
--- a/app/views/projects/issues/_issue.html.haml
+++ b/app/views/projects/issues/_issue.html.haml
@@ -6,7 +6,7 @@
.issuable-info-container
.issuable-main-info
.issue-title.title
- %span.issue-title-text
+ %span.issue-title-text{ dir: "auto" }
- if issue.confidential?
%span.has-tooltip{ title: _('Confidential') }
= confidential_icon(issue)
@@ -36,8 +36,10 @@
= issue.due_date.to_s(:medium)
- if issue.labels.any?
&nbsp;
- - labels_sorted_by_title(issue.labels).each do |label|
- = link_to_label(label, subject: issue.project, css_class: 'label-link')
+ - presented_labels_sorted_by_title(issue.labels, issue.project).each do |label|
+ = link_to_label(label, css_class: 'label-link')
+
+ = render_if_exists "projects/issues/issue_weight", issue: issue
.issuable-meta
%ul.controls
diff --git a/app/views/projects/issues/_merge_requests_status.html.haml b/app/views/projects/issues/_merge_requests_status.html.haml
deleted file mode 100644
index 90838a75214..00000000000
--- a/app/views/projects/issues/_merge_requests_status.html.haml
+++ /dev/null
@@ -1,25 +0,0 @@
-- time_format = '%b %e, %Y %l:%M%P %Z%z'
-
-- if merge_request.merged?
- - mr_status_date = merge_request.merged_at
- - mr_status_title = _('Merged')
- - mr_status_icon = 'merge'
- - mr_status_class = 'merged'
-- elsif merge_request.closed?
- - mr_status_date = merge_request.closed_event&.created_at
- - mr_status_title = _('Closed')
- - mr_status_icon = 'issue-close'
- - mr_status_class = 'closed'
-- else
- - mr_status_date = merge_request.created_at
- - mr_status_title = mr_status_date ? _('Opened') : _('Open')
- - mr_status_icon = 'issue-open-m'
- - mr_status_class = 'open'
-
-- if mr_status_date
- - mr_status_tooltip = "<div><span class=\"bold\">#{mr_status_title}</span> #{time_ago_in_words(mr_status_date)} ago</div><span class=\"text-tertiary\">#{l(mr_status_date.to_time, format: time_format)}</span>"
-- else
- - mr_status_tooltip = "<div><span class=\"bold\">#{mr_status_title}</span></div>"
-
-%span.mr-status-wrapper.suggestion-help-hover{ class: css_class, data: { toggle: 'tooltip', placement: 'bottom', html: 'true', title: mr_status_tooltip } }
- = sprite_icon(mr_status_icon, size: 16, css_class: "merge-request-status #{mr_status_class}")
diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml
index fbd70cd1906..457b2936278 100644
--- a/app/views/projects/issues/_new_branch.html.haml
+++ b/app/views/projects/issues/_new_branch.html.haml
@@ -8,18 +8,18 @@
- create_branch_path = project_branches_path(@project, branch_name: @issue.to_branch_name, ref: @project.default_branch, issue_iid: @issue.iid)
- refs_path = refs_namespace_project_path(@project.namespace, @project, search: '')
- .create-mr-dropdown-wrap.d-inline-block{ data: { can_create_path: can_create_path, create_mr_path: create_mr_path, create_branch_path: create_branch_path, refs_path: refs_path } }
- .btn-group.unavailable
+ .create-mr-dropdown-wrap.d-inline-block.full-width-mobile{ data: { can_create_path: can_create_path, create_mr_path: create_mr_path, create_branch_path: create_branch_path, refs_path: refs_path } }
+ .btn-group.btn-group-sm.unavailable
%button.btn.btn-grouped{ type: 'button', disabled: 'disabled' }
= icon('spinner', class: 'fa-spin')
%span.text
Checking branch availability…
- .btn-group.available.hidden
+ .btn-group.btn-group-sm.available.hidden
%button.btn.js-create-merge-request.btn-success.btn-inverted{ type: 'button', data: { action: data_action } }
= value
- %button.btn.create-merge-request-dropdown-toggle.dropdown-toggle.btn-success.btn-inverted.js-dropdown-toggle{ type: 'button', data: { dropdown: { trigger: '#create-merge-request-dropdown' }, display: 'static' } }
+ %button.btn.create-merge-request-dropdown-toggle.dropdown-toggle.btn-success.btn-inverted.js-dropdown-toggle.flex-grow-0{ type: 'button', data: { dropdown: { trigger: '#create-merge-request-dropdown' }, display: 'static' } }
= icon('caret-down')
.droplab-dropdown
diff --git a/app/views/projects/issues/new.html.haml b/app/views/projects/issues/new.html.haml
index 9a081a42b6f..d1601d7fd10 100644
--- a/app/views/projects/issues/new.html.haml
+++ b/app/views/projects/issues/new.html.haml
@@ -1,9 +1,8 @@
-- add_to_breadcrumbs "Issues", project_issues_path(@project)
-- breadcrumb_title "New"
-- page_title "New Issue"
+- add_to_breadcrumbs _("Issues"), project_issues_path(@project)
+- breadcrumb_title _("New")
+- page_title _("New Issue")
-%h3.page-title
- New Issue
+%h3.page-title= _("New Issue")
%hr
= render "form"
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index 2c95ac6dbb3..d55afee4523 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -1,7 +1,7 @@
- @content_class = "limit-container-width" unless fluid_layout
-- add_to_breadcrumbs "Issues", project_issues_path(@project)
+- add_to_breadcrumbs _("Issues"), project_issues_path(@project)
- breadcrumb_title @issue.to_reference
-- page_title "#{@issue.title} (#{@issue.to_reference})", "Issues"
+- page_title "#{@issue.title} (#{@issue.to_reference})", _("Issues")
- page_description @issue.description
- page_card_attributes @issue.card_attributes
@@ -15,7 +15,7 @@
.issuable-status-box.status-box.status-box-issue-closed{ class: issue_button_visibility(@issue, false) }
= sprite_icon('mobile-issue-close', size: 16, css_class: 'd-block d-sm-none')
.d-none.d-sm-block
- - if @issue.moved?
+ - if @issue.moved? && can?(current_user, :read_issue, @issue.moved_to)
- moved_link_start = "<a href=\"#{issue_path(@issue.moved_to)}\" class=\"text-white text-underline\">".html_safe
- moved_link_end = '</a>'.html_safe
= s_('IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})').html_safe % {moved_link_start: moved_link_start,
@@ -77,7 +77,9 @@
= edited_time_ago_with_tooltip(@issue, placement: 'bottom', html_class: 'issue-edited-ago js-issue-edited-ago')
- #js-related-merge-requests{ data: { endpoint: api_v4_projects_issues_related_merge_requests_path(id: @project.id, issue_iid: @issue.iid), project_namespace: @project.namespace.path, project_path: @project.path } }
+ = render_if_exists 'projects/issues/related_issues'
+
+ #js-related-merge-requests{ data: { endpoint: expose_path(api_v4_projects_issues_related_merge_requests_path(id: @project.id, issue_iid: @issue.iid)), project_namespace: @project.namespace.path, project_path: @project.path } }
- if can?(current_user, :download_code, @project)
#related-branches{ data: { url: related_branches_project_issue_path(@project, @issue) } }
diff --git a/app/views/projects/jobs/_table.html.haml b/app/views/projects/jobs/_table.html.haml
index d124d3ebfc1..b08223546f7 100644
--- a/app/views/projects/jobs/_table.html.haml
+++ b/app/views/projects/jobs/_table.html.haml
@@ -16,7 +16,7 @@
%th Runner
%th Stage
%th Name
- %th
+ %th Timing
%th Coverage
%th
diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml
index bb7c297ba1f..511d7a82d1b 100644
--- a/app/views/projects/labels/index.html.haml
+++ b/app/views/projects/labels/index.html.haml
@@ -11,31 +11,30 @@
= render 'shared/labels/nav', labels_or_filters: labels_or_filters, can_admin_label: can_admin_label
.labels-container.prepend-top-10
- - if can_admin_label
- - if search.blank?
- %p.text-muted
- = _('Labels can be applied to issues and merge requests.')
- %br
- = _('Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging.')
- -# Only show it in the first page
- - hide = @available_labels.empty? || (params[:page].present? && params[:page] != '1')
- .prioritized-labels{ class: ('hide' if hide) }
- %h5.prepend-top-10= _('Prioritized Labels')
- .content-list.manage-labels-list.js-prioritized-labels{ "data-url" => set_priorities_project_labels_path(@project) }
- #js-priority-labels-empty-state.priority-labels-empty-state{ class: "#{'hidden' unless @prioritized_labels.empty? && search.blank?}" }
- = render 'shared/empty_states/priority_labels'
- - if @prioritized_labels.present?
- = render partial: 'shared/label', subject: @project, collection: @prioritized_labels, as: :label, locals: { force_priority: true }
- - elsif search.present?
- .nothing-here-block
- = _('No prioritised labels with such name or description')
+ - if can_admin_label && search.blank?
+ %p.text-muted
+ = _('Labels can be applied to issues and merge requests.')
+ %br
+ = _('Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging.')
+
+ -# Only show it in the first page
+ - hide = @available_labels.empty? || (params[:page].present? && params[:page] != '1')
+ .prioritized-labels{ class: [('hide' if hide), ('is-not-draggable' unless can_admin_label)] }
+ %h5.prepend-top-10= _('Prioritized Labels')
+ .content-list.manage-labels-list.js-prioritized-labels{ data: { url: set_priorities_project_labels_path(@project), sortable: can_admin_label } }
+ #js-priority-labels-empty-state.priority-labels-empty-state{ class: "#{'hidden' unless @prioritized_labels.empty? && search.blank?}" }
+ = render 'shared/empty_states/priority_labels'
+ - if @prioritized_labels.present?
+ = render partial: 'shared/label', collection: @prioritized_labels, as: :label, locals: { force_priority: true, subject: @project }
+ - elsif search.present?
+ .nothing-here-block
+ = _('No prioritised labels with such name or description')
- if @labels.present?
.other-labels
- - if can_admin_label
- %h5{ class: ('hide' if hide) }= _('Other Labels')
+ %h5{ class: ('hide' if hide) }= _('Other Labels')
.content-list.manage-labels-list.js-other-labels
- = render partial: 'shared/label', subject: @project, collection: @labels, as: :label
+ = render partial: 'shared/label', collection: @labels, as: :label, locals: { subject: @project }
= paginate @labels, theme: 'gitlab'
- elsif search.present?
.other-labels
diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml
index 47c8e3d73f5..67e5e4ca62d 100644
--- a/app/views/projects/merge_requests/_merge_request.html.haml
+++ b/app/views/projects/merge_requests/_merge_request.html.haml
@@ -34,8 +34,8 @@
= merge_request.target_branch
- if merge_request.labels.any?
&nbsp;
- - labels_sorted_by_title(merge_request.labels).each do |label|
- = link_to_label(label, subject: merge_request.project, type: :merge_request, css_class: 'label-link')
+ - presented_labels_sorted_by_title(merge_request.labels, merge_request.project).each do |label|
+ = link_to_label(label, type: :merge_request, css_class: 'label-link')
.issuable-meta
%ul.controls
diff --git a/app/views/projects/merge_requests/conflicts/components/_inline_conflict_lines.html.haml b/app/views/projects/merge_requests/conflicts/components/_inline_conflict_lines.html.haml
index 03226de120d..7bd5c437942 100644
--- a/app/views/projects/merge_requests/conflicts/components/_inline_conflict_lines.html.haml
+++ b/app/views/projects/merge_requests/conflicts/components/_inline_conflict_lines.html.haml
@@ -1,5 +1,5 @@
%inline-conflict-lines{ "inline-template" => "true", ":file" => "file" }
- %table.diff-wrap-lines.code.js-syntax-highlight
+ %table.diff-wrap-lines.code.code-commit.js-syntax-highlight
%tr.line_holder.diff-inline{ "v-for" => "line in file.inlineLines" }
%td.diff-line-num.new_line{ ":class" => "lineCssClass(line)", "v-if" => "!line.isHeader" }
%a {{line.new_line}}
diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml
index 79c586eef73..a201fafb949 100644
--- a/app/views/projects/merge_requests/show.html.haml
+++ b/app/views/projects/merge_requests/show.html.haml
@@ -31,29 +31,26 @@
.merge-request-tabs-holder{ class: ("js-tabs-affix" unless ENV['RAILS_ENV'] == 'test') }
.merge-request-tabs-container
- .scrolling-tabs-container.inner-page-scroll-tabs.is-smaller
- .fade-left= icon('angle-left')
- .fade-right= icon('angle-right')
- %ul.merge-request-tabs.nav-tabs.nav.nav-links.scrolling-tabs
- %li.notes-tab.qa-notes-tab
- = tab_link_for @merge_request, :show, force_link: @commit.present? do
- Discussion
- %span.badge.badge-pill= @merge_request.related_notes.user.count
- - if @merge_request.source_project
- %li.commits-tab
- = tab_link_for @merge_request, :commits do
- Commits
- %span.badge.badge-pill= @commits_count
- - if @pipelines.any?
- %li.pipelines-tab
- = tab_link_for @merge_request, :pipelines do
- Pipelines
- %span.badge.badge-pill.js-pipelines-mr-count= @pipelines.size
- %li.diffs-tab.qa-diffs-tab
- = tab_link_for @merge_request, :diffs do
- Changes
- %span.badge.badge-pill= @merge_request.diff_size
- .d-inline-flex.flex-wrap
+ %ul.merge-request-tabs.nav-tabs.nav.nav-links
+ %li.notes-tab.qa-notes-tab
+ = tab_link_for @merge_request, :show, force_link: @commit.present? do
+ = _("Discussion")
+ %span.badge.badge-pill= @merge_request.related_notes.user.count
+ - if @merge_request.source_project
+ %li.commits-tab
+ = tab_link_for @merge_request, :commits do
+ = _("Commits")
+ %span.badge.badge-pill= @commits_count
+ - if @pipelines.any?
+ %li.pipelines-tab
+ = tab_link_for @merge_request, :pipelines do
+ = _("Pipelines")
+ %span.badge.badge-pill.js-pipelines-mr-count= @pipelines.size
+ %li.diffs-tab.qa-diffs-tab
+ = tab_link_for @merge_request, :diffs do
+ = _("Changes")
+ %span.badge.badge-pill= @merge_request.diff_size
+ .d-flex.flex-wrap.align-items-center.justify-content-lg-end
#js-vue-discussion-filter{ data: { default_filter: current_user&.notes_filter_for(@merge_request),
notes_filters: UserPreference.notes_filters.to_json } }
#js-vue-discussion-counter
diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml
index 78b416edd5c..1cee8be604a 100644
--- a/app/views/projects/milestones/show.html.haml
+++ b/app/views/projects/milestones/show.html.haml
@@ -59,7 +59,7 @@
= render_if_exists 'shared/milestones/burndown', milestone: @milestone, project: @project
- - if can?(current_user, :read_issue, @project) && @milestone.total_items_count(current_user).zero?
+ - if can?(current_user, :read_issue, @project) && @milestone.total_issues_count(current_user).zero?
.alert.alert-success.prepend-top-default
%span= _('Assign some issues to this milestone.')
- elsif @milestone.complete?(current_user) && @milestone.active?
diff --git a/app/views/projects/mirrors/_authentication_method.html.haml b/app/views/projects/mirrors/_authentication_method.html.haml
index ef6db07a1bb..ee82d68d398 100644
--- a/app/views/projects/mirrors/_authentication_method.html.haml
+++ b/app/views/projects/mirrors/_authentication_method.html.haml
@@ -1,8 +1,5 @@
- mirror = f.object
-- is_push = local_assigns.fetch(:is_push, false)
- auth_options = [[_('Password'), 'password'], [_('SSH public key'), 'ssh_public_key']]
-- regen_data = { auth_method: 'ssh_public_key', regenerate_ssh_private_key: true }
-- ssh_public_key_present = mirror.ssh_public_key.present?
.form-group
= f.label :auth_method, _('Authentication method'), class: 'label-bold'
@@ -17,21 +14,3 @@
.well-password-auth.collapse.js-well-password-auth
= f.label :password, _("Password"), class: "label-bold"
= f.password_field :password, value: mirror.password, class: 'form-control qa-password', autocomplete: 'new-password'
- - unless is_push
- .well-ssh-auth.collapse.js-well-ssh-auth
- %p.js-ssh-public-key-present{ class: ('collapse' unless ssh_public_key_present) }
- = _('Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation.')
- %p.js-ssh-public-key-pending{ class: ('collapse' if ssh_public_key_present) }
- = _('An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation.')
-
- .clearfix.js-ssh-public-key-wrap{ class: ('collapse' unless ssh_public_key_present) }
- %code.prepend-top-10.ssh-public-key
- = mirror.ssh_public_key
- = clipboard_button(text: mirror.ssh_public_key, title: _("Copy SSH public key to clipboard"), class: 'prepend-top-10 btn-copy-ssh-public-key')
-
- = button_tag type: 'button',
- data: { endpoint: project_mirror_path(@project), project_data: { import_data_attributes: regen_data } },
- class: "btn btn-inverted btn-warning prepend-top-10 js-btn-regenerate-ssh-key#{ ' collapse' unless ssh_public_key_present }" do
- = icon('spinner spin', class: 'js-spinner d-none')
- = _('Regenerate key')
- = render 'projects/mirrors/regenerate_public_ssh_key_confirm_modal'
diff --git a/app/views/projects/mirrors/_disabled_mirror_badge.html.haml b/app/views/projects/mirrors/_disabled_mirror_badge.html.haml
new file mode 100644
index 00000000000..356cb43f07f
--- /dev/null
+++ b/app/views/projects/mirrors/_disabled_mirror_badge.html.haml
@@ -0,0 +1 @@
+.badge.badge-warning.qa-disabled-mirror-badge{ data: { toggle: 'tooltip', html: 'true' }, title: _('Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them.') }= _('Disabled')
diff --git a/app/views/projects/mirrors/_instructions.html.haml b/app/views/projects/mirrors/_instructions.html.haml
index 35a6885318a..33e5a6e67c3 100644
--- a/app/views/projects/mirrors/_instructions.html.haml
+++ b/app/views/projects/mirrors/_instructions.html.haml
@@ -7,7 +7,7 @@
%li
- minutes = Gitlab.config.gitlab_shell.git_timeout / 60
= _("The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination.") % { number_of_minutes: minutes }
- %li= _('The Git LFS objects will <strong>not</strong> be synced.').html_safe
+ %li= mirror_lfs_sync_message
%li
= _('This user will be the author of all events in the activity feed that are the result of an update,
like new branches being created or new commits being pushed to existing branches.')
diff --git a/app/views/projects/mirrors/_mirror_repos.html.haml b/app/views/projects/mirrors/_mirror_repos.html.haml
index c031815200b..e68fa5d08c7 100644
--- a/app/views/projects/mirrors/_mirror_repos.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos.html.haml
@@ -1,4 +1,4 @@
-- expanded = Rails.env.test?
+- expanded = expanded_by_default?
- protocols = Gitlab::UrlSanitizer::ALLOWED_SCHEMES.join('|')
%section.settings.project-mirror-settings.js-mirror-settings.no-animate.qa-mirroring-repositories-settings#js-push-remote-settings{ class: ('expanded' if expanded) }
@@ -11,7 +11,7 @@
= link_to _('Read more'), help_page_path('workflow/repository_mirroring'), target: '_blank'
.settings-content
- = form_for @project, url: project_mirror_path(@project), html: { class: 'gl-show-field-errors js-mirror-form', autocomplete: 'false', data: mirrors_form_data_attributes } do |f|
+ = form_for @project, url: project_mirror_path(@project), html: { class: 'gl-show-field-errors js-mirror-form', autocomplete: 'new-password', data: mirrors_form_data_attributes } do |f|
.panel.panel-default
.panel-heading
%h3.panel-title= _('Mirror a repository')
@@ -20,7 +20,7 @@
.form-group.has-feedback
= label_tag :url, _('Git repository URL'), class: 'label-light'
- = text_field_tag :url, nil, class: 'form-control js-mirror-url js-repo-url qa-mirror-repository-url-input', placeholder: _('Input your repository URL'), required: true, pattern: "(#{protocols}):\/\/.+"
+ = text_field_tag :url, nil, class: 'form-control js-mirror-url js-repo-url qa-mirror-repository-url-input', placeholder: _('Input your repository URL'), required: true, pattern: "(#{protocols}):\/\/.+", autocomplete: 'new-password'
= render 'projects/mirrors/instructions'
@@ -29,7 +29,7 @@
.form-check.append-bottom-10
= check_box_tag :only_protected_branches, '1', false, class: 'js-mirror-protected form-check-input'
= label_tag :only_protected_branches, _('Only mirror protected branches'), class: 'form-check-label'
- = link_to icon('question-circle'), help_page_path('user/project/protected_branches')
+ = link_to icon('question-circle'), help_page_path('user/project/protected_branches'), target: '_blank'
.panel-footer
= f.submit _('Mirror repository'), class: 'btn btn-success js-mirror-submit qa-mirror-repository-button', name: :update_remote_mirror
@@ -49,17 +49,19 @@
%tbody.js-mirrors-table-body
= render_if_exists 'projects/mirrors/table_pull_row'
- @project.remote_mirrors.each_with_index do |mirror, index|
- - if mirror.enabled
- %tr.qa-mirrored-repository-row
- %td.qa-mirror-repository-url= mirror.safe_url
- %td= _('Push')
- %td.qa-mirror-last-update-at= mirror.last_update_at.present? ? time_ago_with_tooltip(mirror.last_update_at) : _('Never')
- %td
- - if mirror.last_error.present?
- .badge.mirror-error-badge{ data: { toggle: 'tooltip', html: 'true' }, title: html_escape(mirror.last_error.try(:strip)) }= _('Error')
- %td
- .btn-group.mirror-actions-group.pull-right{ role: 'group' }
- - if mirror.ssh_key_auth?
- = clipboard_button(text: mirror.ssh_public_key, class: 'btn btn-default', title: _('Copy SSH public key'))
- = render 'shared/remote_mirror_update_button', remote_mirror: mirror
- %button.js-delete-mirror.btn.btn-danger{ type: 'button', data: { mirror_id: mirror.id, toggle: 'tooltip', container: 'body' }, title: _('Remove') }= icon('trash-o')
+ - next if mirror.new_record?
+ %tr.qa-mirrored-repository-row{ class: ('bg-secondary' if mirror.disabled?) }
+ %td.qa-mirror-repository-url= mirror.safe_url
+ %td= _('Push')
+ %td.qa-mirror-last-update-at= mirror.last_update_at.present? ? time_ago_with_tooltip(mirror.last_update_at) : _('Never')
+ %td
+ - if mirror.disabled?
+ = render 'projects/mirrors/disabled_mirror_badge'
+ - if mirror.last_error.present?
+ .badge.mirror-error-badge{ data: { toggle: 'tooltip', html: 'true' }, title: html_escape(mirror.last_error.try(:strip)) }= _('Error')
+ %td
+ .btn-group.mirror-actions-group.pull-right{ role: 'group' }
+ - if mirror.ssh_key_auth?
+ = clipboard_button(text: mirror.ssh_public_key, class: 'btn btn-default', title: _('Copy SSH public key'))
+ = render 'shared/remote_mirror_update_button', remote_mirror: mirror
+ %button.js-delete-mirror.qa-delete-mirror.btn.btn-danger{ type: 'button', data: { mirror_id: mirror.id, toggle: 'tooltip', container: 'body' }, title: _('Remove') }= icon('trash-o')
diff --git a/app/views/projects/mirrors/_mirror_repos_push.html.haml b/app/views/projects/mirrors/_mirror_repos_push.html.haml
index 1d9c83653fe..b7c885b4a63 100644
--- a/app/views/projects/mirrors/_mirror_repos_push.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos_push.html.haml
@@ -5,4 +5,4 @@
= rm_f.hidden_field :url, class: 'js-mirror-url-hidden', required: true, pattern: "(#{protocols}):\/\/.+"
= rm_f.hidden_field :only_protected_branches, class: 'js-mirror-protected-hidden'
= render partial: 'projects/mirrors/ssh_host_keys', locals: { f: rm_f }
- = render partial: 'projects/mirrors/authentication_method', locals: { f: rm_f, is_push: true }
+ = render partial: 'projects/mirrors/authentication_method', locals: { f: rm_f }
diff --git a/app/views/projects/mirrors/_ssh_host_keys.html.haml b/app/views/projects/mirrors/_ssh_host_keys.html.haml
index f61aa6ecd11..7762fb4b844 100644
--- a/app/views/projects/mirrors/_ssh_host_keys.html.haml
+++ b/app/views/projects/mirrors/_ssh_host_keys.html.haml
@@ -3,7 +3,7 @@
- verified_at = mirror.ssh_known_hosts_verified_at
.form-group.js-ssh-host-keys-section{ class: ('collapse' unless mirror.ssh_mirror_url?) }
- %button.btn.btn-inverted.btn-success.inline.js-detect-host-keys.append-right-10{ type: 'button' }
+ %button.btn.btn-inverted.btn-secondary.inline.js-detect-host-keys.append-right-10{ type: 'button' }
= icon('spinner spin', class: 'js-spinner d-none')
= _('Detect host keys')
.fingerprint-ssh-info.js-fingerprint-ssh-info.prepend-top-10.append-bottom-10{ class: ('collapse' unless mirror.ssh_mirror_url?) }
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index ff7c36c2d5b..d7e16dbd40c 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -16,6 +16,7 @@
= _('A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}.').html_safe % { among_other_things_link: among_other_things_link }
%p
= _('All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings.')
+ = render_if_exists 'projects/new_ci_cd_banner_external_repo'
%p
- pages_getting_started_guide = link_to _('Pages getting started guide'), help_page_path("user/project/pages/getting_started_part_two", anchor: "fork-a-project-to-get-started-from"), target: '_blank'
= _('Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}.').html_safe % { pages_getting_started_guide: pages_getting_started_guide }
@@ -42,13 +43,19 @@
%a.nav-link{ href: '#import-project-pane', id: 'import-project-tab', data: { toggle: 'tab', track_label: 'import_project', track_event: "click_tab" }, role: 'tab' }
%span.d-none.d-sm-block Import project
%span.d-block.d-sm-none Import
+ = render_if_exists 'projects/new_ci_cd_only_project_tab', active_tab: active_tab
.tab-content.gitlab-tab-content
.tab-pane{ id: 'blank-project-pane', class: active_when(active_tab == 'blank'), role: 'tabpanel' }
= form_for @project, html: { class: 'new_project' } do |f|
= render 'new_project_fields', f: f, project_name_id: "blank-project-name"
- .tab-pane.no-padding{ id: 'create-from-template-pane', class: active_when(active_tab == 'template'), role: 'tabpanel' }
+ #create-from-template-pane.tab-pane.px-0.pb-0{ class: active_when(active_tab == 'template'), role: 'tabpanel' }
+ .card-slim.m-4.p-4
+ %div
+ - contributing_templates_url = 'https://gitlab.com/gitlab-org/project-templates/contributing'
+ - link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: contributing_templates_url }
+ = _('Learn how to %{link_start}contribute to the built-in templates%{link_end}').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
= form_for @project, html: { class: 'new_project' } do |f|
.project-template
.form-group
@@ -63,6 +70,8 @@
%h4 No import options available
%p Contact an administrator to enable options for importing your project.
+ = render_if_exists 'projects/new_ci_cd_only_project_pane', active_tab: active_tab
+
.save-project-loader.d-none
.center
%h2
diff --git a/app/views/projects/notes/_actions.html.haml b/app/views/projects/notes/_actions.html.haml
index eb6838cec8d..044adb75bea 100644
--- a/app/views/projects/notes/_actions.html.haml
+++ b/app/views/projects/notes/_actions.html.haml
@@ -41,9 +41,9 @@
.note-actions-item
= button_tag title: 'Add reaction', class: "note-action-button note-emoji-button js-add-award js-note-emoji} has-tooltip btn btn-transparent", data: { position: 'right', container: 'body' } do
= icon('spinner spin')
- %span{ class: 'link-highlight award-control-icon-neutral' }= custom_icon('emoji_slightly_smiling_face')
- %span{ class: 'link-highlight award-control-icon-positive' }= custom_icon('emoji_smiley')
- %span{ class: 'link-highlight award-control-icon-super-positive' }= custom_icon('emoji_smile')
+ %span{ class: 'link-highlight award-control-icon-neutral' }= sprite_icon('slight-smile')
+ %span{ class: 'link-highlight award-control-icon-positive' }= sprite_icon('smiley')
+ %span{ class: 'link-highlight award-control-icon-super-positive' }= sprite_icon('smile')
- if note_editable
.note-actions-item
diff --git a/app/views/projects/notes/_more_actions_dropdown.html.haml b/app/views/projects/notes/_more_actions_dropdown.html.haml
index 8de84f82e9f..8a6e5fde99b 100644
--- a/app/views/projects/notes/_more_actions_dropdown.html.haml
+++ b/app/views/projects/notes/_more_actions_dropdown.html.haml
@@ -11,7 +11,7 @@
- unless is_current_user
%li
= link_to new_abuse_report_path(user_id: note.author.id, ref_url: noteable_note_url(note)) do
- = _('Report abuse to GitLab')
+ = _('Report abuse to admin')
- if note_editable
%li
= link_to note_url(note), method: :delete, data: { confirm: 'Are you sure you want to delete this comment?' }, remote: true, class: 'js-note-delete' do
diff --git a/app/views/projects/pages_domains/_form.html.haml b/app/views/projects/pages_domains/_form.html.haml
index b7b46c56c37..33f2166480b 100644
--- a/app/views/projects/pages_domains/_form.html.haml
+++ b/app/views/projects/pages_domains/_form.html.haml
@@ -1,29 +1,80 @@
- if @domain.errors.any?
- #error_explanation
- .alert.alert-danger
- - @domain.errors.full_messages.each do |msg|
- %p= msg
+ .alert.alert-danger
+ - @domain.errors.full_messages.each do |msg|
+ = msg
.form-group.row
- = f.label :domain, class: 'col-form-label col-sm-2' do
- = _("Domain")
+ .col-sm-2.col-form-label
+ = f.label :domain, _("Domain")
.col-sm-10
- = f.text_field :domain, required: true, autocomplete: 'off', class: 'form-control', disabled: @domain.persisted?
+ = f.text_field :domain, required: true, autocomplete: "off", class: "form-control", disabled: @domain.persisted?
- if Gitlab.config.pages.external_https
- .form-group.row
- = f.label :certificate, class: 'col-form-label col-sm-2' do
- = _("Certificate (PEM)")
- .col-sm-10
- = f.text_area :certificate, rows: 5, class: 'form-control'
- %span.help-inline= _("Upload a certificate for your domain with all intermediates")
-
- .form-group.row
- = f.label :key, class: 'col-form-label col-sm-2' do
- = _("Key (PEM)")
- .col-sm-10
- = f.text_area :key, rows: 5, class: 'form-control'
- %span.help-inline= _("Upload a private key for your certificate")
+
+ - auto_ssl_available = Feature.enabled?(:pages_auto_ssl)
+ - auto_ssl_enabled = @domain.auto_ssl_enabled?
+ - auto_ssl_available_and_enabled = auto_ssl_available && auto_ssl_enabled
+
+ - if auto_ssl_available
+ .form-group.row
+ .col-sm-2.col-form-label
+ %label{ for: "pages_domain_auto_ssl_enabled_button" }
+ - lets_encrypt_link_url = "https://letsencrypt.org/"
+ - lets_encrypt_link_start = "<a href=\"%{lets_encrypt_link_url}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-nowrap\">".html_safe % { lets_encrypt_link_url: lets_encrypt_link_url }
+ - lets_encrypt_link_end = "</a>".html_safe
+ = _("Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}").html_safe % { lets_encrypt_link_start: lets_encrypt_link_start, lets_encrypt_link_end: lets_encrypt_link_end }
+
+ .col-sm-10.js-auto-ssl-toggle-container
+ %button{ type: "button", id: "pages_domain_auto_ssl_enabled_button",
+ class: "js-project-feature-toggle project-feature-toggle mt-2 #{"is-checked" if auto_ssl_available_and_enabled}",
+ "aria-label": _("Automatic certificate management using Let's Encrypt") }
+ = f.hidden_field :auto_ssl_enabled?, class: "js-project-feature-toggle-input"
+ %span.toggle-icon
+ = sprite_icon("status_success_borderless", size: 16, css_class: "toggle-icon-svg toggle-status-checked")
+ = sprite_icon("status_failed_borderless", size: 16, css_class: "toggle-icon-svg toggle-status-unchecked")
+ %p.text-secondary.mt-3
+ - docs_link_url = help_page_path("user/project/pages/lets_encrypt_for_gitlab_pages.md", anchor: "lets-encrypt-for-gitlab-pages")
+ - docs_link_start = "<a href=\"%{docs_link_url}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-nowrap\">".html_safe % { docs_link_url: docs_link_url }
+ - docs_link_end = "</a>".html_safe
+ = _("Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}.").html_safe % { docs_link_url: docs_link_url, docs_link_start: docs_link_start, docs_link_end: docs_link_end }
+
+ .js-shown-if-auto-ssl{ class: ("d-none" unless auto_ssl_available_and_enabled) }
+ .form-group.row
+ .col-sm-2.col-form-label
+ = f.label :certificate, _("Certificate (PEM)")
+ .col-sm-10
+ - if auto_ssl_available_and_enabled && !@domain.certificate.empty?
+ = f.text_area :certificate,
+ rows: 5,
+ class: "form-control",
+ disabled: true
+ %span.help-inline.text-muted= _("This certificate is automatically managed by Let's Encrypt")
+ - else
+ %p.text-secondary.form-control-plaintext= _("The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete.")
+
+ .js-shown-unless-auto-ssl{ class: ("d-none" if auto_ssl_available_and_enabled) }
+ .form-group.row
+ .col-sm-2.col-form-label
+ = f.label :certificate, _("Certificate (PEM)")
+ .col-sm-10
+ = f.text_area :certificate,
+ rows: 5,
+ class: "form-control js-enabled-unless-auto-ssl",
+ value: (@domain.certificate unless auto_ssl_available_and_enabled),
+ disabled: auto_ssl_available_and_enabled
+ %span.help-inline.text-muted= _("Upload a certificate for your domain with all intermediates")
+
+ .form-group.row
+ .col-sm-2.col-form-label
+ = f.label :key, _("Key (PEM)")
+ .col-sm-10
+ = f.text_area :key,
+ rows: 5,
+ class: "form-control js-enabled-unless-auto-ssl",
+ value: (@domain.key unless auto_ssl_available_and_enabled),
+ disabled: auto_ssl_available_and_enabled
+ %span.help-inline.text-muted= _("Upload a private key for your certificate")
+
- else
.nothing-here-block
= _("Support for custom certificates is disabled. Ask your system's administrator to enable it.")
diff --git a/app/views/projects/pages_domains/_helper_text.html.haml b/app/views/projects/pages_domains/_helper_text.html.haml
new file mode 100644
index 00000000000..5a79fefabfc
--- /dev/null
+++ b/app/views/projects/pages_domains/_helper_text.html.haml
@@ -0,0 +1,9 @@
+- docs_link_url = help_page_path("user/project/pages/getting_started_part_three.md", anchor: "adding-certificates-to-your-project")
+- docs_link_start = "<a href=\"%{docs_link_url}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-nowrap\">".html_safe % { docs_link_url: docs_link_url }
+- docs_link_end = "</a>".html_safe
+
+-# Hiding behind a feature flag to avoid any changes to this feature's implemention
+-# when the :pages_auto_ssl feature flag is disabled. This check should be removed
+-# once the :pages_auto_ssl feature flag is removed.
+- if Feature.enabled?(:pages_auto_ssl)
+ %p= _("Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}.").html_safe % { docs_link_url: docs_link_url, docs_link_start: docs_link_start, docs_link_end: docs_link_end }
diff --git a/app/views/projects/pages_domains/edit.html.haml b/app/views/projects/pages_domains/edit.html.haml
index e11387ae742..7c0777e5496 100644
--- a/app/views/projects/pages_domains/edit.html.haml
+++ b/app/views/projects/pages_domains/edit.html.haml
@@ -3,6 +3,7 @@
- page_title @domain.domain
%h3.page-title
= @domain.domain
+= render 'projects/pages_domains/helper_text'
%hr.clearfix
%div
= form_for [@project.namespace.becomes(Namespace), @project, @domain], html: { class: 'fieldset-form' } do |f|
diff --git a/app/views/projects/pages_domains/new.html.haml b/app/views/projects/pages_domains/new.html.haml
index c7cefa87c76..e23ccb5d4c6 100644
--- a/app/views/projects/pages_domains/new.html.haml
+++ b/app/views/projects/pages_domains/new.html.haml
@@ -2,6 +2,7 @@
- page_title _('New Pages Domain')
%h3.page-title
= _("New Pages Domain")
+= render 'projects/pages_domains/helper_text'
%hr.clearfix
%div
= form_for [@project.namespace.becomes(Namespace), @project, @domain], html: { class: 'fieldset-form' } do |f|
diff --git a/app/views/projects/project_members/_new_project_member.html.haml b/app/views/projects/project_members/_new_project_member.html.haml
index 0590578c3fe..efabb7f7b19 100644
--- a/app/views/projects/project_members/_new_project_member.html.haml
+++ b/app/views/projects/project_members/_new_project_member.html.haml
@@ -19,4 +19,5 @@
= text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date', placeholder: 'Expiration date'
%i.clear-icon.js-clear-input
= f.submit _("Add to project"), class: "btn btn-success qa-add-member-button"
- = link_to _("Import"), import_project_project_members_path(@project), class: "btn btn-default", title: _("Import members from another project")
+ - if can_import_members?
+ = link_to _("Import"), import_project_project_members_path(@project), class: "btn btn-default", title: _("Import members from another project")
diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml
index 8373903443e..cc98ba64f08 100644
--- a/app/views/projects/project_members/index.html.haml
+++ b/app/views/projects/project_members/index.html.haml
@@ -1,29 +1,35 @@
- page_title _("Members")
+- can_admin_project_members = can?(current_user, :admin_project_member, @project)
.row.prepend-top-default
.col-lg-12
- %h4
- = _("Project members")
- - if can?(current_user, :admin_project_member, @project)
- %p
- = _("You can invite a new member to <strong>%{project_name}</strong> or invite another group.").html_safe % { project_name: sanitize(@project.name, tags: []) }
- - else
- %p
- = _("Members can be added by project <i>Maintainers</i> or <i>Owners</i>").html_safe
+ - if project_can_be_shared?
+ %h4
+ = _("Project members")
+ - if can_admin_project_members
+ %p= share_project_description(@project)
+ - else
+ %p
+ = _("Members can be added by project <i>Maintainers</i> or <i>Owners</i>").html_safe
+
.light
- - if can?(current_user, :admin_project_member, @project)
- %ul.nav-links.nav.nav-tabs.gitlab-tabs{ role: 'tablist' }
- %li.nav-tab{ role: 'presentation' }
- %a.nav-link.active{ href: '#invite-member-pane', id: 'invite-member-tab', data: { toggle: 'tab' }, role: 'tab' }= _("Invite member")
- - if @project.allowed_to_share_with_group?
+ - if can_admin_project_members && project_can_be_shared?
+ - if !membership_locked? && @project.allowed_to_share_with_group?
+ %ul.nav-links.nav.nav-tabs.gitlab-tabs{ role: 'tablist' }
%li.nav-tab{ role: 'presentation' }
+ %a.nav-link.active{ href: '#invite-member-pane', id: 'invite-member-tab', data: { toggle: 'tab' }, role: 'tab' }= _("Invite member")
+ %li.nav-tab{ role: 'presentation', class: ('active' if membership_locked?) }
%a.nav-link{ href: '#invite-group-pane', id: 'invite-group-tab', data: { toggle: 'tab' }, role: 'tab' }= _("Invite group")
- .tab-content.gitlab-tab-content
- .tab-pane.active{ id: 'invite-member-pane', role: 'tabpanel' }
- = render 'projects/project_members/new_project_member', tab_title: _('Invite member')
- .tab-pane{ id: 'invite-group-pane', role: 'tabpanel' }
- = render 'projects/project_members/new_project_group', tab_title: _('Invite group')
+ .tab-content.gitlab-tab-content
+ .tab-pane.active{ id: 'invite-member-pane', role: 'tabpanel' }
+ = render 'projects/project_members/new_project_member', tab_title: _('Invite member')
+ .tab-pane{ id: 'invite-group-pane', role: 'tabpanel', class: ('active' if membership_locked?) }
+ = render 'projects/project_members/new_project_group', tab_title: _('Invite group')
+ - elsif !membership_locked?
+ .invite-member= render 'projects/project_members/new_project_member', tab_title: _('Invite member')
+ - elsif @project.allowed_to_share_with_group?
+ .invite-group= render 'projects/project_members/new_project_group', tab_title: _('Invite group')
= render 'shared/members/requests', membership_source: @project, requesters: @requesters
.clearfix
diff --git a/app/views/projects/protected_branches/_protected_branch.html.haml b/app/views/projects/protected_branches/_protected_branch.html.haml
index b12ae995ece..366d7a7a2eb 100644
--- a/app/views/projects/protected_branches/_protected_branch.html.haml
+++ b/app/views/projects/protected_branches/_protected_branch.html.haml
@@ -1,2 +1,2 @@
= render layout: 'projects/protected_branches/shared/protected_branch', locals: { protected_branch: protected_branch } do
- = render partial: 'projects/protected_branches/update_protected_branch', locals: { protected_branch: protected_branch }
+ = render_if_exists 'projects/protected_branches/update_protected_branch', protected_branch: protected_branch
diff --git a/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml b/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
index d617d85afc2..3644a623d2c 100644
--- a/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
+++ b/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
@@ -6,8 +6,8 @@
.card-body
= form_errors(@protected_branch)
.form-group.row
- = f.label :name, class: 'col-md-2 text-right' do
- Branch:
+ .col-md-2.text-right
+ = f.label :name, 'Branch:'
.col-md-10
= render partial: "projects/protected_branches/shared/dropdown", locals: { f: f }
.form-text.text-muted
diff --git a/app/views/projects/protected_branches/shared/_index.html.haml b/app/views/projects/protected_branches/shared/_index.html.haml
index 539b184e5c2..63748d8d85f 100644
--- a/app/views/projects/protected_branches/shared/_index.html.haml
+++ b/app/views/projects/protected_branches/shared/_index.html.haml
@@ -1,4 +1,4 @@
-- expanded = Rails.env.test?
+- expanded = expanded_by_default?
%section.qa-protected-branches-settings.settings.no-animate#js-protected-branches-settings{ class: ('expanded' if expanded) }
.settings-header
diff --git a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
index cbf1938664c..020e6e187a6 100644
--- a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
+++ b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
@@ -6,8 +6,8 @@
.card-body
= form_errors(@protected_tag)
.form-group.row
- = f.label :name, class: 'col-md-2 text-right' do
- Tag:
+ .col-md-2.text-right
+ = f.label :name, 'Tag:'
.col-md-10.protected-tags-dropdown
= render partial: "projects/protected_tags/shared/dropdown", locals: { f: f }
.form-text.text-muted
diff --git a/app/views/projects/protected_tags/shared/_index.html.haml b/app/views/projects/protected_tags/shared/_index.html.haml
index 9a50a51e4be..b0c87ac8c17 100644
--- a/app/views/projects/protected_tags/shared/_index.html.haml
+++ b/app/views/projects/protected_tags/shared/_index.html.haml
@@ -1,4 +1,4 @@
-- expanded = Rails.env.test?
+- expanded = expanded_by_default?
%section.settings.no-animate#js-protected-tags-settings{ class: ('expanded' if expanded) }
.settings-header
diff --git a/app/views/projects/registry/repositories/_tag.html.haml b/app/views/projects/registry/repositories/_tag.html.haml
index a4cde53e8c6..9594c9184a2 100644
--- a/app/views/projects/registry/repositories/_tag.html.haml
+++ b/app/views/projects/registry/repositories/_tag.html.haml
@@ -1,7 +1,7 @@
%tr.tag
%td
= escape_once(tag.name)
- = clipboard_button(text: "docker pull #{tag.location}")
+ = clipboard_button(text: "#{tag.location}")
%td
- if tag.revision
%span.has-tooltip{ title: "#{tag.revision}" }
diff --git a/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml b/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml
index 9409418bbcc..82c1d57c97e 100644
--- a/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml
+++ b/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml
@@ -18,22 +18,22 @@
.help-form
.form-group
- = label_tag :display_name, 'Display name', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.input-group
+ = label_tag :display_name, 'Display name', class: 'col-12 col-form-label label-bold'
+ .col-12.input-group
= text_field_tag :display_name, "GitLab / #{@project.full_name}", class: 'form-control form-control-sm', readonly: 'readonly'
.input-group-append
= clipboard_button(target: '#display_name', class: 'input-group-text')
.form-group
- = label_tag :description, 'Description', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.input-group
+ = label_tag :description, 'Description', class: 'col-12 col-form-label label-bold'
+ .col-12.input-group
= text_field_tag :description, run_actions_text, class: 'form-control form-control-sm', readonly: 'readonly'
.input-group-append
= clipboard_button(target: '#description', class: 'input-group-text')
.form-group
- = label_tag nil, 'Command trigger word', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.text-block
+ = label_tag nil, 'Command trigger word', class: 'col-12 col-form-label label-bold'
+ .col-12
%p Fill in the word that works best for your team.
%p
Suggestions:
@@ -42,44 +42,44 @@
%code= @project.full_path
.form-group
- = label_tag :request_url, 'Request URL', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.input-group
+ = label_tag :request_url, 'Request URL', class: 'col-12 col-form-label label-bold'
+ .col-12.input-group
= text_field_tag :request_url, service_trigger_url(subject), class: 'form-control form-control-sm', readonly: 'readonly'
.input-group-append
= clipboard_button(target: '#request_url', class: 'input-group-text')
.form-group
- = label_tag nil, 'Request method', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.text-block POST
+ = label_tag nil, 'Request method', class: 'col-12 col-form-label label-bold'
+ .col-12 POST
.form-group
- = label_tag :response_username, 'Response username', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.input-group
+ = label_tag :response_username, 'Response username', class: 'col-12 col-form-label label-bold'
+ .col-12.input-group
= text_field_tag :response_username, 'GitLab', class: 'form-control form-control-sm', readonly: 'readonly'
.input-group-append
= clipboard_button(target: '#response_username', class: 'input-group-text')
.form-group
- = label_tag :response_icon, 'Response icon', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.input-group
+ = label_tag :response_icon, 'Response icon', class: 'col-12 col-form-label label-bold'
+ .col-12.input-group
= text_field_tag :response_icon, asset_url('gitlab_logo.png'), class: 'form-control form-control-sm', readonly: 'readonly'
.input-group-append
= clipboard_button(target: '#response_icon', class: 'input-group-text')
.form-group
- = label_tag nil, 'Autocomplete', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.text-block Yes
+ = label_tag nil, 'Autocomplete', class: 'col-12 col-form-label label-bold'
+ .col-12 Yes
.form-group
- = label_tag :autocomplete_hint, 'Autocomplete hint', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.input-group
+ = label_tag :autocomplete_hint, 'Autocomplete hint', class: 'col-12 col-12 col-form-label label-bold'
+ .col-12.input-group
= text_field_tag :autocomplete_hint, '[help]', class: 'form-control form-control-sm', readonly: 'readonly'
.input-group-append
= clipboard_button(target: '#autocomplete_hint', class: 'input-group-text')
.form-group
- = label_tag :autocomplete_description, 'Autocomplete description', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.input-group
+ = label_tag :autocomplete_description, 'Autocomplete description', class: 'col-12 col-form-label label-bold'
+ .col-12.input-group
= text_field_tag :autocomplete_description, run_actions_text, class: 'form-control form-control-sm', readonly: 'readonly'
.input-group-append
= clipboard_button(target: '#autocomplete_description', class: 'input-group-text')
diff --git a/app/views/projects/services/slack_slash_commands/_help.html.haml b/app/views/projects/services/slack_slash_commands/_help.html.haml
index 9a7004f89c0..9b7732abc62 100644
--- a/app/views/projects/services/slack_slash_commands/_help.html.haml
+++ b/app/views/projects/services/slack_slash_commands/_help.html.haml
@@ -27,8 +27,8 @@
.help-form
.form-group
- = label_tag nil, 'Command', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.text-block
+ = label_tag nil, 'Command', class: 'col-12 col-form-label label-bold'
+ .col-12
%p Fill in the word that works best for your team.
%p
Suggestions:
@@ -37,50 +37,50 @@
%code= @project.full_path
.form-group
- = label_tag :url, 'URL', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.input-group
+ = label_tag :url, 'URL', class: 'col-12 col-form-label label-bold'
+ .col-12.input-group
= text_field_tag :url, service_trigger_url(subject), class: 'form-control form-control-sm', readonly: 'readonly'
.input-group-append
= clipboard_button(target: '#url', class: 'input-group-text')
.form-group
- = label_tag nil, 'Method', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.text-block POST
+ = label_tag nil, 'Method', class: 'col-12 col-form-label label-bold'
+ .col-12 POST
.form-group
- = label_tag :customize_name, 'Customize name', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.input-group
+ = label_tag :customize_name, 'Customize name', class: 'col-12 col-form-label label-bold'
+ .col-12.input-group
= text_field_tag :customize_name, 'GitLab', class: 'form-control form-control-sm', readonly: 'readonly'
.input-group-append
= clipboard_button(target: '#customize_name', class: 'input-group-text')
.form-group
- = label_tag nil, 'Customize icon', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.text-block
- = image_tag(asset_url('slash-command-logo.png'), width: 36, height: 36)
+ = label_tag nil, 'Customize icon', class: 'col-12 col-form-label label-bold'
+ .col-12
+ = image_tag(asset_url('slash-command-logo.png'), width: 36, height: 36, class: 'mr-3')
= link_to('Download image', asset_url('gitlab_logo.png'), class: 'btn btn-sm', target: '_blank', rel: 'noopener noreferrer')
.form-group
- = label_tag nil, 'Autocomplete', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.text-block Show this command in the autocomplete list
+ = label_tag nil, 'Autocomplete', class: 'col-12 col-form-label label-bold'
+ .col-12 Show this command in the autocomplete list
.form-group
- = label_tag :autocomplete_description, 'Autocomplete description', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.input-group
+ = label_tag :autocomplete_description, 'Autocomplete description', class: 'col-12 col-form-label label-bold'
+ .col-12.input-group
= text_field_tag :autocomplete_description, run_actions_text, class: 'form-control form-control-sm', readonly: 'readonly'
.input-group-append
= clipboard_button(target: '#autocomplete_description', class: 'input-group-text')
.form-group
- = label_tag :autocomplete_usage_hint, 'Autocomplete usage hint', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.input-group
+ = label_tag :autocomplete_usage_hint, 'Autocomplete usage hint', class: 'col-12 col-form-label label-bold'
+ .col-12.input-group
= text_field_tag :autocomplete_usage_hint, '[help]', class: 'form-control form-control-sm', readonly: 'readonly'
.input-group-append
= clipboard_button(target: '#autocomplete_usage_hint', class: 'input-group-text')
.form-group
- = label_tag :descriptive_label, 'Descriptive label', class: 'col-sm-2 col-12 col-form-label'
- .col-sm-10.col-12.input-group
+ = label_tag :descriptive_label, 'Descriptive label', class: 'col-12 col-form-label label-bold'
+ .col-12.input-group
= text_field_tag :descriptive_label, 'Perform common operations on GitLab project', class: 'form-control form-control-sm', readonly: 'readonly'
.input-group-append
= clipboard_button(target: '#descriptive_label', class: 'input-group-text')
diff --git a/app/views/projects/settings/_general.html.haml b/app/views/projects/settings/_general.html.haml
index 380430ff52b..520f342f567 100644
--- a/app/views/projects/settings/_general.html.haml
+++ b/app/views/projects/settings/_general.html.haml
@@ -27,7 +27,7 @@
.row= render_if_exists 'projects/classification_policy_settings', f: f
- .row= render_if_exists 'shared/repository_size_limit_setting', form: f, type: :project
+ = render_if_exists 'shared/repository_size_limit_setting', form: f, type: :project
.form-group.prepend-top-default.append-bottom-20
.avatar-container.s90
diff --git a/app/views/projects/settings/ci_cd/_form.html.haml b/app/views/projects/settings/ci_cd/_form.html.haml
index b38b8e3f686..2d108a1cba5 100644
--- a/app/views/projects/settings/ci_cd/_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_form.html.haml
@@ -26,6 +26,14 @@
%hr
.form-group
+ = f.fields_for :ci_cd_settings_attributes, @project.ci_cd_settings do |form|
+ = form.label :default_git_depth, _('Git shallow clone'), class: 'label-bold'
+ = form.number_field :default_git_depth, { class: 'form-control', min: 0, max: 1000 }
+ %p.form-text.text-muted
+ = _('The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time.')
+
+ %hr
+ .form-group
= f.label :build_timeout_human_readable, _('Timeout'), class: 'label-bold'
= f.text_field :build_timeout_human_readable, class: 'form-control'
%p.form-text.text-muted
diff --git a/app/views/projects/settings/ci_cd/show.html.haml b/app/views/projects/settings/ci_cd/show.html.haml
index 548b7c06867..5e3e1076c2c 100644
--- a/app/views/projects/settings/ci_cd/show.html.haml
+++ b/app/views/projects/settings/ci_cd/show.html.haml
@@ -2,7 +2,7 @@
- page_title _("CI / CD Settings")
- page_title _("CI / CD")
-- expanded = Rails.env.test?
+- expanded = expanded_by_default?
- general_expanded = @project.errors.empty? ? expanded : true
%section.settings#js-general-pipeline-settings.no-animate{ class: ('expanded' if general_expanded) }
diff --git a/app/views/projects/settings/operations/_error_tracking.html.haml b/app/views/projects/settings/operations/_error_tracking.html.haml
index 451a79becc3..583fc08f375 100644
--- a/app/views/projects/settings/operations/_error_tracking.html.haml
+++ b/app/views/projects/settings/operations/_error_tracking.html.haml
@@ -2,10 +2,12 @@
- setting = error_tracking_setting
-%section.settings.expanded.no-animate
+%section.settings.no-animate.js-error-tracking-settings
.settings-header
%h4
= _('Error Tracking')
+ %button.btn.js-settings-toggle{ type: 'button' }
+ = _('Expand')
%p
= _('To link Sentry to GitLab, enter your Sentry URL and Auth Token.')
= link_to _('More information'), help_page_path('user/project/operations/error_tracking'), target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/projects/settings/operations/_external_dashboard.html.haml b/app/views/projects/settings/operations/_external_dashboard.html.haml
new file mode 100644
index 00000000000..a124283921d
--- /dev/null
+++ b/app/views/projects/settings/operations/_external_dashboard.html.haml
@@ -0,0 +1,3 @@
+.js-operation-settings{ data: { operations_settings_endpoint: project_settings_operations_path(@project),
+ external_dashboard: { url: metrics_external_dashboard_url,
+ help_page_path: help_page_path('user/project/operations/link_to_external_dashboard') } } }
diff --git a/app/views/projects/settings/operations/show.html.haml b/app/views/projects/settings/operations/show.html.haml
index 6f777305a54..0a7a155bc12 100644
--- a/app/views/projects/settings/operations/show.html.haml
+++ b/app/views/projects/settings/operations/show.html.haml
@@ -3,5 +3,6 @@
- breadcrumb_title _('Operations Settings')
= render_if_exists 'projects/settings/operations/incidents'
-= render 'projects/settings/operations/error_tracking', expanded: true
+= render 'projects/settings/operations/error_tracking'
+= render 'projects/settings/operations/external_dashboard'
= render_if_exists 'projects/settings/operations/tracing'
diff --git a/app/views/projects/settings/repository/_protected_branches.html.haml b/app/views/projects/settings/repository/_protected_branches.html.haml
new file mode 100644
index 00000000000..31630828571
--- /dev/null
+++ b/app/views/projects/settings/repository/_protected_branches.html.haml
@@ -0,0 +1,2 @@
+= render "projects/protected_branches/index"
+= render "projects/protected_tags/index"
diff --git a/app/views/projects/settings/repository/show.html.haml b/app/views/projects/settings/repository/show.html.haml
index cb3a035c49e..ff30cc4f6db 100644
--- a/app/views/projects/settings/repository/show.html.haml
+++ b/app/views/projects/settings/repository/show.html.haml
@@ -3,14 +3,17 @@
- @content_class = "limit-container-width" unless fluid_layout
= render "projects/default_branch/show"
+= render_if_exists "projects/push_rules/index"
= render "projects/mirrors/mirror_repos"
-# Protected branches & tags use a lot of nested partials.
-# The shared parts of the views can be found in the `shared` directory.
-# Those are used throughout the actual views. These `shared` views are then
-# reused in EE.
-= render "projects/protected_branches/index"
-= render "projects/protected_tags/index"
+= render "projects/settings/repository/protected_branches"
+
= render @deploy_keys
= render "projects/deploy_tokens/index"
= render "projects/cleanup/show"
+
+= render_if_exists 'shared/promotions/promote_repository_features'
diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml
index 458096f9dd6..2e78b0bff3e 100644
--- a/app/views/projects/tags/index.html.haml
+++ b/app/views/projects/tags/index.html.haml
@@ -9,7 +9,7 @@
.nav-text.row-main-content
= s_('TagsPage|Tags give the ability to mark specific points in history as being important')
- .nav-controls.row-fixed-content
+ .nav-controls
= form_tag(filter_tags_path, method: :get) do
= search_field_tag :search, params[:search], { placeholder: s_('TagsPage|Filter by tag name'), id: 'tag-search', class: 'form-control search-text-input input-short', spellcheck: false }
diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml
index 0be62bc5612..59232372150 100644
--- a/app/views/projects/tags/show.html.haml
+++ b/app/views/projects/tags/show.html.haml
@@ -18,7 +18,7 @@
- else
= s_("TagsPage|Can't find HEAD commit for this tag")
- .nav-controls.controls-flex
+ .nav-controls
- if can?(current_user, :push_code, @project)
= link_to edit_project_tag_release_path(@project, @tag.name), class: 'btn btn-edit controls-item has-tooltip', title: s_('TagsPage|Edit release notes') do
= icon("pencil")
diff --git a/app/views/projects/tree/_readme.html.haml b/app/views/projects/tree/_readme.html.haml
index 4daacbe157c..4f6c7e1f9a6 100644
--- a/app/views/projects/tree/_readme.html.haml
+++ b/app/views/projects/tree/_readme.html.haml
@@ -1,5 +1,5 @@
- if readme.rich_viewer
- %article.file-holder.readme-holder{ id: 'readme', class: ("limited-width-container" unless fluid_layout) }
+ %article.file-holder.readme-holder{ id: 'readme', class: [("limited-width-container" unless fluid_layout), ("js-hide-on-navigation" if vue_file_list_enabled?)] }
.js-file-title.file-title
= blob_icon readme.mode, readme.name
= link_to project_blob_path(@project, tree_join(@ref, readme.path)) do
diff --git a/app/views/projects/tree/_tree_commit_column.html.haml b/app/views/projects/tree/_tree_commit_column.html.haml
index e37fd7624be..065fef606d5 100644
--- a/app/views/projects/tree/_tree_commit_column.html.haml
+++ b/app/views/projects/tree/_tree_commit_column.html.haml
@@ -1,2 +1,3 @@
+- full_title = markdown_field(commit, :full_title)
%span.str-truncated
- = link_to_html commit.redacted_full_title_html, project_commit_path(@project, commit.id), title: commit.redacted_full_title_html, class: 'tree-commit-link'
+ = link_to_html full_title, project_commit_path(@project, commit.id), title: full_title, class: 'tree-commit-link'
diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml
index ec8e5234bd4..ea6349f2f57 100644
--- a/app/views/projects/tree/_tree_header.html.haml
+++ b/app/views/projects/tree/_tree_header.html.haml
@@ -6,71 +6,74 @@
= render 'shared/ref_switcher', destination: 'tree', path: @path, show_create: true
- if on_top_of_branch?
- - addtotree_toggle_attributes = { href: '#', 'data-toggle': 'dropdown', 'data-target': '.add-to-tree-dropdown', 'data-boundary': 'window' }
+ - addtotree_toggle_attributes = { 'data-toggle': 'dropdown', 'data-target': '.add-to-tree-dropdown', 'data-boundary': 'window' }
- else
- addtotree_toggle_attributes = { title: _("You can only add files when you are on a branch"), data: { container: 'body' }, class: 'disabled has-tooltip' }
- %ul.breadcrumb.repo-breadcrumb
- %li.breadcrumb-item
- = link_to project_tree_path(@project, @ref) do
- = @project.path
- - path_breadcrumbs do |title, path|
+ - if vue_file_list_enabled?
+ #js-repo-breadcrumb
+ - else
+ %ul.breadcrumb.repo-breadcrumb
%li.breadcrumb-item
- = link_to truncate(title, length: 40), project_tree_path(@project, tree_join(@ref, path))
+ = link_to project_tree_path(@project, @ref) do
+ = @project.path
+ - path_breadcrumbs do |title, path|
+ %li.breadcrumb-item
+ = link_to truncate(title, length: 40), project_tree_path(@project, tree_join(@ref, path))
- - if can_collaborate || can_create_mr_from_fork
- %li.breadcrumb-item
- %a.btn.add-to-tree.qa-add-to-tree{ addtotree_toggle_attributes }
- = sprite_icon('plus', size: 16, css_class: 'float-left')
- = sprite_icon('arrow-down', size: 16, css_class: 'float-left')
- - if on_top_of_branch?
- .add-to-tree-dropdown
- %ul.dropdown-menu
- - if can_edit_tree?
- %li.dropdown-header
- #{ _('This directory') }
- %li
- = link_to project_new_blob_path(@project, @id), class: 'qa-new-file-option' do
- #{ _('New file') }
- %li
- = link_to '#modal-upload-blob', { 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal' } do
- #{ _('Upload file') }
- %li
- = link_to '#modal-create-new-dir', { 'data-target' => '#modal-create-new-dir', 'data-toggle' => 'modal' } do
- #{ _('New directory') }
- - elsif can?(current_user, :fork_project, @project) && can?(current_user, :create_merge_request_in, @project)
- %li
- - continue_params = { to: project_new_blob_path(@project, @id),
- notice: edit_in_new_fork_notice,
- notice_now: edit_in_new_fork_notice_now }
- - fork_path = project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_params)
- = link_to fork_path, method: :post do
- #{ _('New file') }
- %li
- - continue_params = { to: request.fullpath,
- notice: edit_in_new_fork_notice + " Try to upload a file again.",
- notice_now: edit_in_new_fork_notice_now }
- - fork_path = project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_params)
- = link_to fork_path, method: :post do
- #{ _('Upload file') }
- %li
- - continue_params = { to: request.fullpath,
- notice: edit_in_new_fork_notice + " Try to create a new directory again.",
- notice_now: edit_in_new_fork_notice_now }
- - fork_path = project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_params)
- = link_to fork_path, method: :post do
- #{ _('New directory') }
+ - if can_collaborate || can_create_mr_from_fork
+ %li.breadcrumb-item
+ %button.btn.add-to-tree.qa-add-to-tree{ addtotree_toggle_attributes, type: 'button' }
+ = sprite_icon('plus', size: 16, css_class: 'float-left')
+ = sprite_icon('arrow-down', size: 16, css_class: 'float-left')
+ - if on_top_of_branch?
+ .add-to-tree-dropdown
+ %ul.dropdown-menu
+ - if can_edit_tree?
+ %li.dropdown-header
+ #{ _('This directory') }
+ %li
+ = link_to project_new_blob_path(@project, @id), class: 'qa-new-file-option' do
+ #{ _('New file') }
+ %li
+ = link_to '#modal-upload-blob', { 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal' } do
+ #{ _('Upload file') }
+ %li
+ = link_to '#modal-create-new-dir', { 'data-target' => '#modal-create-new-dir', 'data-toggle' => 'modal' } do
+ #{ _('New directory') }
+ - elsif can?(current_user, :fork_project, @project) && can?(current_user, :create_merge_request_in, @project)
+ %li
+ - continue_params = { to: project_new_blob_path(@project, @id),
+ notice: edit_in_new_fork_notice,
+ notice_now: edit_in_new_fork_notice_now }
+ - fork_path = project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_params)
+ = link_to fork_path, method: :post do
+ #{ _('New file') }
+ %li
+ - continue_params = { to: request.fullpath,
+ notice: edit_in_new_fork_notice + " Try to upload a file again.",
+ notice_now: edit_in_new_fork_notice_now }
+ - fork_path = project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_params)
+ = link_to fork_path, method: :post do
+ #{ _('Upload file') }
+ %li
+ - continue_params = { to: request.fullpath,
+ notice: edit_in_new_fork_notice + " Try to create a new directory again.",
+ notice_now: edit_in_new_fork_notice_now }
+ - fork_path = project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_params)
+ = link_to fork_path, method: :post do
+ #{ _('New directory') }
- - if can?(current_user, :push_code, @project)
- %li.divider
- %li.dropdown-header
- #{ _('This repository') }
- %li
- = link_to new_project_branch_path(@project) do
- #{ _('New branch') }
- %li
- = link_to new_project_tag_path(@project) do
- #{ _('New tag') }
+ - if can?(current_user, :push_code, @project)
+ %li.divider
+ %li.dropdown-header
+ #{ _('This repository') }
+ %li
+ = link_to new_project_branch_path(@project) do
+ #{ _('New branch') }
+ %li
+ = link_to new_project_tag_path(@project) do
+ #{ _('New tag') }
.tree-controls
= link_to s_('Commits|History'), project_commits_path(@project, @id), class: 'btn'
diff --git a/app/views/repository_check_mailer/notify.html.haml b/app/views/repository_check_mailer/notify.html.haml
index d5327a2b4cc..dfcd1c6b19f 100644
--- a/app/views/repository_check_mailer/notify.html.haml
+++ b/app/views/repository_check_mailer/notify.html.haml
@@ -6,3 +6,5 @@
%p
= _("You are receiving this message because you are a GitLab administrator for %{url}.") % { url: Gitlab.config.gitlab.url }
+
+= render_if_exists 'repository_check_mailer/email_additional_text'
diff --git a/app/views/repository_check_mailer/notify.text.haml b/app/views/repository_check_mailer/notify.text.haml
index 6b64b337b0e..a2e04fa710f 100644
--- a/app/views/repository_check_mailer/notify.text.haml
+++ b/app/views/repository_check_mailer/notify.text.haml
@@ -3,3 +3,5 @@
= _("View details: %{details_url}") % { details_url: admin_projects_url(last_repository_check_failed: 1) }
= _("You are receiving this message because you are a GitLab administrator for %{url}.") % { url: Gitlab.config.gitlab.url }
+
+= render_if_exists 'repository_check_mailer/email_additional_text'
diff --git a/app/views/search/_form.html.haml b/app/views/search/_form.html.haml
index 4af0c6bf84a..db0dcc8adfb 100644
--- a/app/views/search/_form.html.haml
+++ b/app/views/search/_form.html.haml
@@ -13,3 +13,4 @@
- unless params[:snippets].eql? 'true'
= render 'filter'
= button_tag _("Search"), class: "btn btn-success btn-search"
+ = render_if_exists 'search/form_elasticsearch'
diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml
index 5b25a67bc87..cb8a8a24be8 100644
--- a/app/views/search/_results.html.haml
+++ b/app/views/search/_results.html.haml
@@ -1,5 +1,6 @@
- if @search_objects.to_a.empty?
= render partial: "search/results/empty"
+ = render_if_exists 'shared/promotions/promote_advanced_search'
- else
.row-content-block
- unless @search_objects.is_a?(Kaminari::PaginatableWithoutCount)
@@ -11,7 +12,7 @@
- elsif @group
- link_to_group = link_to(@group.name, @group)
= _("in group %{link_to_group}").html_safe % { link_to_group: link_to_group }
-
+ = render_if_exists 'shared/promotions/promote_advanced_search'
.results.prepend-top-10
- if @scope == 'commits'
%ul.content-list.commit-list
@@ -21,10 +22,9 @@
- if @scope == 'projects'
.term
= render 'shared/projects/list', projects: @search_objects, pipeline_status: false
- - elsif %w[blobs wiki_blobs].include?(@scope)
- = render partial: 'search/results/blob', collection: @search_objects, locals: { projects: blob_projects(@search_objects) }
- else
- = render partial: "search/results/#{@scope.singularize}", collection: @search_objects
+ - locals = { projects: blob_projects(@search_objects) } if %w[blobs wiki_blobs].include?(@scope)
+ = render partial: "search/results/#{@scope.singularize}", collection: @search_objects, locals: locals
- if @scope != 'projects'
= paginate_collection(@search_objects)
diff --git a/app/views/search/results/_issue.html.haml b/app/views/search/results/_issue.html.haml
index 796782035f2..1f055cdfa31 100644
--- a/app/views/search/results/_issue.html.haml
+++ b/app/views/search/results/_issue.html.haml
@@ -1,7 +1,7 @@
.search-result-row
%h4
= confidential_icon(issue)
- = link_to [issue.project.namespace.becomes(Namespace), issue.project, issue] do
+ = link_to namespace_project_issue_path(issue.project.namespace.becomes(Namespace), issue.project, issue) do
%span.term.str-truncated= issue.title
- if issue.closed?
%span.badge.badge-danger.prepend-left-5= _("Closed")
diff --git a/app/views/search/results/_merge_request.html.haml b/app/views/search/results/_merge_request.html.haml
index f0e0af11f27..074bb9bce8d 100644
--- a/app/views/search/results/_merge_request.html.haml
+++ b/app/views/search/results/_merge_request.html.haml
@@ -1,6 +1,6 @@
.search-result-row
%h4
- = link_to [merge_request.target_project.namespace.becomes(Namespace), merge_request.target_project, merge_request] do
+ = link_to namespace_project_merge_request_path(merge_request.target_project.namespace.becomes(Namespace), merge_request.target_project, merge_request) do
%span.term.str-truncated= merge_request.title
- if merge_request.merged?
%span.badge.badge-primary.prepend-left-5= _("Merged")
diff --git a/app/views/search/results/_milestone.html.haml b/app/views/search/results/_milestone.html.haml
index 2daa96e34d1..3201f1a7815 100644
--- a/app/views/search/results/_milestone.html.haml
+++ b/app/views/search/results/_milestone.html.haml
@@ -1,6 +1,6 @@
.search-result-row
%h4
- = link_to [milestone.project.namespace.becomes(Namespace), milestone.project, milestone] do
+ = link_to namespace_project_milestone_path(milestone.project.namespace.becomes(Namespace), milestone.project, milestone) do
%span.term.str-truncated= milestone.title
- if milestone.description.present?
diff --git a/app/views/search/results/_wiki_blob.html.haml b/app/views/search/results/_wiki_blob.html.haml
index b351ecd4edf..5847751b268 100644
--- a/app/views/search/results/_wiki_blob.html.haml
+++ b/app/views/search/results/_wiki_blob.html.haml
@@ -1,5 +1,5 @@
- project = find_project_for_result_blob(projects, wiki_blob)
- wiki_blob = parse_search_result(wiki_blob)
-- wiki_blob_link = project_wiki_path(project, wiki_blob.basename)
+- wiki_blob_link = project_wiki_path(project, Pathname.new(wiki_blob.filename).sub_ext(''))
= render partial: 'search/results/blob_data', locals: { blob: wiki_blob, project: project, file_name: wiki_blob.filename, blob_link: wiki_blob_link }
diff --git a/app/views/sent_notifications/unsubscribe.html.haml b/app/views/sent_notifications/unsubscribe.html.haml
index ca392e1adfc..22fcfcda297 100644
--- a/app/views/sent_notifications/unsubscribe.html.haml
+++ b/app/views/sent_notifications/unsubscribe.html.haml
@@ -1,6 +1,6 @@
- noteable = @sent_notification.noteable
- noteable_type = @sent_notification.noteable_type.titleize.downcase
-- noteable_text = %(#{noteable.title} (#{noteable.to_reference}))
+- noteable_text = show_unsubscribe_title?(noteable) ? %(#{noteable.title} (#{noteable.to_reference})) : %(#{noteable.to_reference})
- page_title _("Unsubscribe"), noteable_text, noteable_type.pluralize, @sent_notification.project.full_name
%h3.page-title
diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml
index a2df0347fd6..1e509ea0d1f 100644
--- a/app/views/shared/_clone_panel.html.haml
+++ b/app/views/shared/_clone_panel.html.haml
@@ -16,7 +16,12 @@
= ssh_clone_button(project)
%li
= http_clone_button(project)
+ = render_if_exists 'shared/kerberos_clone_button', project: project
= text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true, aria: { label: 'Project clone URL' }
.input-group-append
= clipboard_button(target: '#project_clone', title: _("Copy URL to clipboard"), class: "input-group-text btn-default btn-clipboard")
+
+ = render_if_exists 'shared/geo_modal_button'
+
+= render_if_exists 'shared/geo_modal', project: project
diff --git a/app/views/shared/_delete_label_modal.html.haml b/app/views/shared/_delete_label_modal.html.haml
index dbd3bbb43af..f37dd2cdf02 100644
--- a/app/views/shared/_delete_label_modal.html.haml
+++ b/app/views/shared/_delete_label_modal.html.haml
@@ -9,13 +9,13 @@
.modal-body
%p
%strong= label.name
- %span will be permanently deleted from #{label.is_a?(ProjectLabel)? label.project.name : label.group.name}. This cannot be undone.
+ %span will be permanently deleted from #{label.subject_name}. This cannot be undone.
.modal-footer
%a{ href: '#', data: { dismiss: 'modal' }, class: 'btn btn-default' } Cancel
= link_to 'Delete label',
- destroy_label_path(label),
+ label.destroy_path,
title: 'Delete',
method: :delete,
class: 'btn btn-remove'
diff --git a/app/views/shared/_email_with_badge.html.haml b/app/views/shared/_email_with_badge.html.haml
index ad863b1967d..294fe74a5ca 100644
--- a/app/views/shared/_email_with_badge.html.haml
+++ b/app/views/shared/_email_with_badge.html.haml
@@ -1,6 +1,6 @@
- css_classes = %w(badge badge-verification-status)
- css_classes << (verified ? 'verified': 'unverified')
-- text = verified ? 'Verified' : 'Unverified'
+- text = verified ? _('Verified') : _('Unverified')
.email-badge
.email-badge-email= email
diff --git a/app/views/shared/_import_form.html.haml b/app/views/shared/_import_form.html.haml
index 7b593ca4f76..d0f9374e832 100644
--- a/app/views/shared/_import_form.html.haml
+++ b/app/views/shared/_import_form.html.haml
@@ -1,11 +1,26 @@
- ci_cd_only = local_assigns.fetch(:ci_cd_only, false)
+- import_url = Gitlab::UrlSanitizer.new(f.object.import_url)
-.form-group.import-url-data
- = f.label :import_url, class: 'label-bold' do
- %span
- = _('Git repository URL')
+.import-url-data
+ .form-group
+ = f.label :import_url, class: 'label-bold' do
+ %span
+ = _('Git repository URL')
+ = f.text_field :import_url, value: import_url.sanitized_url,
+ autocomplete: 'off', class: 'form-control', placeholder: 'https://gitlab.company.com/group/project.git', required: true
- = f.text_field :import_url, autocomplete: 'off', class: 'form-control', placeholder: 'https://username:password@gitlab.company.com/group/project.git', required: true
+ .row
+ .form-group.col-md-6
+ = f.label :import_url_user, class: 'label-bold' do
+ %span
+ = _('Username (optional)')
+ = f.text_field :import_url_user, value: import_url.user, class: 'form-control', required: false, autocomplete: 'new-password'
+
+ .form-group.col-md-6
+ = f.label :import_url_password, class: 'label-bold' do
+ %span
+ = _('Password (optional)')
+ = f.password_field :import_url_password, class: 'form-control', required: false, autocomplete: 'new-password'
.info-well.prepend-top-20
.well-segment
@@ -13,8 +28,11 @@
%li
= _('The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>.').html_safe
%li
- = _('If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>.').html_safe
+ = _('If your HTTP repository is not publicly accessible, add your credentials.')
%li
= import_will_timeout_message(ci_cd_only)
%li
= import_svn_message(ci_cd_only)
+ = render_if_exists 'shared/ci_cd_only_link', ci_cd_only: ci_cd_only
+
+= render_if_exists 'shared/ee/import_form', f: f, ci_cd_only: ci_cd_only
diff --git a/app/views/shared/_label.html.haml b/app/views/shared/_label.html.haml
index 21ea188d7b3..c4b7ef481fd 100644
--- a/app/views/shared/_label.html.haml
+++ b/app/views/shared/_label.html.haml
@@ -1,13 +1,13 @@
+- label = label.present(issuable_subject: local_assigns[:subject])
- label_css_id = dom_id(label)
- status = label_subscription_status(label, @project).inquiry if current_user
-- subject = local_assigns[:subject]
- use_label_priority = local_assigns.fetch(:use_label_priority, false)
- force_priority = local_assigns.fetch(:force_priority, use_label_priority ? label.priority.present? : false)
- toggle_subscription_path = toggle_subscription_label_path(label, @project) if current_user
- tooltip_title = label_status_tooltip(label, status) if status
%li.label-list-item{ id: label_css_id, data: { id: label.id } }
- = render "shared/label_row", label: label, subject: subject, force_priority: force_priority
+ = render "shared/label_row", label: label, force_priority: force_priority
%ul.label-actions-list
- if @project
%li.inline
@@ -21,7 +21,7 @@
= sprite_icon('star')
- if can?(current_user, :admin_label, label)
%li.inline
- = link_to edit_label_path(label), class: 'btn btn-transparent label-action edit has-tooltip', title: _('Edit'), data: { placement: 'bottom' }, aria_label: _('Edit') do
+ = link_to label.edit_path, class: 'btn btn-transparent label-action edit has-tooltip', title: _('Edit'), data: { placement: 'bottom' }, aria_label: _('Edit') do
= sprite_icon('pencil')
- if can?(current_user, :admin_label, label)
%li.inline
@@ -30,7 +30,7 @@
= sprite_icon('ellipsis_v')
.dropdown-menu.dropdown-open-left
%ul
- - if label.is_a?(ProjectLabel) && label.project.group && can?(current_user, :admin_label, label.project.group)
+ - if label.project_label? && label.project.group && can?(current_user, :admin_label, label.project.group)
%li
%button.js-promote-project-label-button.btn.btn-transparent.btn-action{ disabled: true, type: 'button',
data: { url: promote_project_label_path(label.project, label),
@@ -48,7 +48,7 @@
%button.text-danger.remove-row{ type: 'button' }= _('Delete')
- if current_user
%li.inline.label-subscription
- - if can_subscribe_to_label_in_different_levels?(label)
+ - if label.can_subscribe_to_label_in_different_levels?
%button.js-unsubscribe-button.label-subscribe-button.btn.btn-default{ class: ('hidden' if status.unsubscribed?), data: { url: toggle_subscription_path, toggle: 'tooltip' }, title: tooltip_title }
%span= _('Unsubscribe')
.dropdown.dropdown-group-label{ class: ('hidden' unless status.unsubscribed?) }
diff --git a/app/views/shared/_label_row.html.haml b/app/views/shared/_label_row.html.haml
index 6651f12f6de..af11ce94ec5 100644
--- a/app/views/shared/_label_row.html.haml
+++ b/app/views/shared/_label_row.html.haml
@@ -1,13 +1,10 @@
-- subject = local_assigns[:subject]
- force_priority = local_assigns.fetch(:force_priority, false)
-- show_label_issues_link = defined?(@project) && show_label_issuables_link?(label, :issues, project: @project)
-- show_label_merge_requests_link = defined?(@project) && show_label_issuables_link?(label, :merge_requests, project: @project)
+- subject_or_group_defined = defined?(@project) || defined?(@group)
+- show_label_issues_link = subject_or_group_defined && show_label_issuables_link?(label, :issues, project: @project)
+- show_label_merge_requests_link = subject_or_group_defined && show_label_issuables_link?(label, :merge_requests, project: @project)
.label-name
- - if defined?(@project)
- = link_to_label(label, subject: @project, tooltip: false)
- - else
- = render_label(label, tooltip: false)
+ = render_label(label, tooltip: false)
.label-description
.append-right-default.prepend-left-default
- if label.description.present?
@@ -16,11 +13,13 @@
%ul.label-links
- if show_label_issues_link
%li.label-link-item.inline
- = link_to_label(label, subject: subject) { 'Issues' }
+ = link_to_label(label) { 'Issues' }
- if show_label_merge_requests_link
&middot;
%li.label-link-item.inline
- = link_to_label(label, subject: subject, type: :merge_request) { _('Merge requests') }
+ = link_to_label(label, type: :merge_request) { _('Merge requests') }
- if force_priority
+ &middot;
%li.label-link-item.priority-badge.js-priority-badge.inline.prepend-left-10
.label-badge.label-badge-blue= _('Prioritized label')
+ = render_if_exists 'shared/label_row_epics_link', label: label
diff --git a/app/views/shared/_mini_pipeline_graph.html.haml b/app/views/shared/_mini_pipeline_graph.html.haml
index 8607f87ce0b..a1f21c2a83e 100644
--- a/app/views/shared/_mini_pipeline_graph.html.haml
+++ b/app/views/shared/_mini_pipeline_graph.html.haml
@@ -4,7 +4,7 @@
- detailed_status = stage.detailed_status(current_user)
- icon_status = "#{detailed_status.icon}_borderless"
- .stage-container.dropdown{ class: klass }
+ .stage-container.mt-0.ml-1.dropdown{ class: klass }
%button.mini-pipeline-graph-dropdown-toggle.has-tooltip.js-builds-dropdown-button{ class: "ci-status-icon-#{detailed_status.group}", type: 'button', data: { toggle: 'dropdown', title: "#{stage.name}: #{detailed_status.label}", placement: 'top', "stage-endpoint" => stage_ajax_project_pipeline_path(pipeline.project, pipeline, stage: stage.name) } }
= sprite_icon(icon_status)
@@ -13,5 +13,5 @@
%ul
%li.js-builds-dropdown-loading.hidden
- .text-center
- %i.fa.fa-spinner.fa-spin{ 'aria-hidden': 'true', 'aria-label': 'Loading' }
+ .loading-container.text-center
+ %span.spinner{ 'aria-label': 'Loading' }
diff --git a/app/views/shared/_old_visibility_level.html.haml b/app/views/shared/_old_visibility_level.html.haml
index fd576e4fbea..e8f3d888cce 100644
--- a/app/views/shared/_old_visibility_level.html.haml
+++ b/app/views/shared/_old_visibility_level.html.haml
@@ -1,6 +1,6 @@
.form-group.row
.col-sm-2.col-form-label
= _('Visibility level')
- = link_to icon('question-circle'), help_page_path("public_access/public_access")
+ = link_to icon('question-circle'), help_page_path("public_access/public_access"), target: '_blank'
.col-sm-10
= render 'shared/visibility_level', f: f, visibility_level: visibility_level, can_change_visibility_level: can_change_visibility_level, form_model: form_model, with_label: with_label
diff --git a/app/views/shared/_remote_mirror_update_button.html.haml b/app/views/shared/_remote_mirror_update_button.html.haml
index 721a2af8069..8da2ae5111a 100644
--- a/app/views/shared/_remote_mirror_update_button.html.haml
+++ b/app/views/shared/_remote_mirror_update_button.html.haml
@@ -1,6 +1,6 @@
- if remote_mirror.update_in_progress?
%button.btn.disabled{ type: 'button', data: { toggle: 'tooltip', container: 'body' }, title: _('Updating') }
= icon("refresh spin")
-- else
+- elsif remote_mirror.enabled?
= link_to update_now_project_mirror_path(@project, sync_remote: true), method: :post, class: "btn qa-update-now-button", data: { toggle: 'tooltip', container: 'body' }, title: _('Update now') do
= icon("refresh")
diff --git a/app/views/shared/_sidebar_toggle_button.html.haml b/app/views/shared/_sidebar_toggle_button.html.haml
index 2530db986e0..d499bc0a253 100644
--- a/app/views/shared/_sidebar_toggle_button.html.haml
+++ b/app/views/shared/_sidebar_toggle_button.html.haml
@@ -1,8 +1,8 @@
-%a.toggle-sidebar-button.js-toggle-sidebar{ role: "button", type: "button", title: "Toggle sidebar" }
+%a.toggle-sidebar-button.js-toggle-sidebar.qa-toggle-sidebar{ role: "button", type: "button", title: "Toggle sidebar" }
= sprite_icon('angle-double-left', css_class: 'icon-angle-double-left')
= sprite_icon('angle-double-right', css_class: 'icon-angle-double-right')
- %span.collapse-text Collapse sidebar
+ %span.collapse-text= _("Collapse sidebar")
= button_tag class: 'close-nav-button', type: 'button' do
= sprite_icon('close', size: 16)
- %span.collapse-text Close sidebar
+ %span.collapse-text= _("Close sidebar")
diff --git a/app/views/shared/boards/_show.html.haml b/app/views/shared/boards/_show.html.haml
index f0d1dd162df..813fccd217b 100644
--- a/app/views/shared/boards/_show.html.haml
+++ b/app/views/shared/boards/_show.html.haml
@@ -13,14 +13,14 @@
%script#js-board-modal-filter{ type: "text/x-template" }= render "shared/issuable/search_bar", type: :boards_modal, show_sorting_dropdown: false
%script#js-board-promotion{ type: "text/x-template" }= render_if_exists "shared/promotions/promote_issue_board"
-#board-app.boards-app{ "v-cloak" => true, data: board_data, ":class" => "{ 'is-compact': detailIssueVisible }" }
+#board-app.boards-app.position-relative{ "v-cloak" => "true", data: board_data, ":class" => "{ 'is-compact': detailIssueVisible }" }
.d-none.d-sm-none.d-md-block
= render 'shared/issuable/search_bar', type: :boards, board: board
- .boards-list
- .boards-app-loading.text-center{ "v-if" => "loading" }
- = icon("spinner spin")
- %board{ "v-cloak" => true,
+ .boards-list.w-100.py-3.px-2.text-nowrap
+ .boards-app-loading.w-100.text-center{ "v-if" => "loading" }
+ = icon("spinner spin 2x")
+ %board{ "v-cloak" => "true",
"v-for" => "list in state.lists",
"ref" => "board",
":list" => "list",
diff --git a/app/views/shared/boards/components/_board.html.haml b/app/views/shared/boards/components/_board.html.haml
index 307a0919a4c..f9cfcabc015 100644
--- a/app/views/shared/boards/components/_board.html.haml
+++ b/app/views/shared/boards/components/_board.html.haml
@@ -1,8 +1,8 @@
-.board{ ":class" => '{ "is-draggable": !list.preset, "is-expandable": list.isExpandable, "is-collapsed": !list.isExpanded, "board-type-assignee": list.type === "assignee" }',
+.board.d-inline-block.h-100.px-2.align-top.ws-normal{ ":class" => '{ "is-draggable": !list.preset, "is-expandable": list.isExpandable, "is-collapsed": !list.isExpanded, "board-type-assignee": list.type === "assignee" }',
":data-id" => "list.id" }
- .board-inner.d-flex.flex-column
- %header.board-header{ ":class" => '{ "has-border": list.label && list.label.color }', ":style" => "{ borderTopColor: (list.label && list.label.color ? list.label.color : null) }", "@click" => "toggleExpanded($event)" }
- %h3.board-title.js-board-handle{ ":class" => '{ "user-can-drag": (!disabled && !list.preset) }' }
+ .board-inner.d-flex.flex-column.position-relative.h-100.rounded
+ %header.board-header{ ":class" => '{ "has-border": list.label && list.label.color, "position-relative": list.isExpanded, "position-absolute position-top-0 position-left-0 w-100 h-100": !list.isExpanded }', ":style" => "{ borderTopColor: (list.label && list.label.color ? list.label.color : null) }", "@click" => "toggleExpanded($event)" }
+ %h3.board-title.m-0.d-flex.align-items-center.py-2.px-3.js-board-handle{ ":class" => '{ "user-can-drag": (!disabled && !list.preset), "p-0 border-bottom-0 justify-content-center": !list.isExpanded }' }
%i.fa.fa-fw.board-title-expandable-toggle{ "v-if": "list.isExpandable",
":class": "{ \"fa-caret-down\": list.isExpanded, \"fa-caret-right\": !list.isExpanded }",
"aria-hidden": "true" }
@@ -31,9 +31,9 @@
%board-delete{ "inline-template" => true,
":list" => "list",
"v-if" => "!list.preset && list.id" }
- %button.board-delete.has-tooltip.float-right{ type: "button", title: _("Delete list"), "aria-label" => _("Delete list"), data: { placement: "bottom" }, "@click.stop" => "deleteBoard" }
+ %button.board-delete.p-0.border-0.has-tooltip.float-right{ type: "button", title: _("Delete list"), ":class": "{ 'd-none': !list.isExpanded }", "aria-label" => _("Delete list"), data: { placement: "bottom" }, "@click.stop" => "deleteBoard" }
= icon("trash")
- .issue-count-badge.text-secondary{ "v-if" => 'list.type !== "blank" && list.type !== "promotion"', ":title": "counterTooltip", "v-tooltip": true, data: { placement: "top" } }
+ .issue-count-badge.text-secondary{ "v-if" => 'list.type !== "blank" && list.type !== "promotion"', ":title": "counterTooltip", ":class": "{ 'd-none': !list.isExpanded }", "v-tooltip": true, data: { placement: "top" } }
%span.issue-count-badge-count
%icon.mr-1{ name: "issues" }
{{ list.issuesSize }}
@@ -42,6 +42,7 @@
%button.issue-count-badge-add-button.btn.btn-sm.btn-default.ml-1.has-tooltip.js-no-trigger-collapse{ type: "button",
"@click" => "showNewIssueForm",
"v-if" => "isNewIssueShown",
+ ":class": "{ 'd-none': !list.isExpanded }",
"aria-label" => _("New issue"),
"title" => _("New issue"),
data: { placement: "top", container: "body" } }
diff --git a/app/views/shared/boards/components/_sidebar.html.haml b/app/views/shared/boards/components/_sidebar.html.haml
index 30e51ecc261..b4f75967a67 100644
--- a/app/views/shared/boards/components/_sidebar.html.haml
+++ b/app/views/shared/boards/components/_sidebar.html.haml
@@ -2,16 +2,16 @@
%transition{ name: "boards-sidebar-slide" }
%aside.right-sidebar.right-sidebar-expanded.issue-boards-sidebar{ "v-show" => "showSidebar" }
.issuable-sidebar
- .block.issuable-sidebar-header
+ .block.issuable-sidebar-header.position-relative
%span.issuable-header-text.hide-collapsed.float-left
- %strong
+ %strong.bold
{{ issue.title }}
%br/
%span
= render_if_exists "shared/boards/components/sidebar/issue_project_path"
= precede "#" do
{{ issue.iid }}
- %a.gutter-toggle.float-right{ role: "button",
+ %a.gutter-toggle.position-absolute.position-top-0.position-right-0{ role: "button",
href: "#",
"@click.prevent" => "closeSidebar",
"aria-label" => "Toggle sidebar" }
diff --git a/app/views/shared/boards/components/sidebar/_due_date.html.haml b/app/views/shared/boards/components/sidebar/_due_date.html.haml
index 5630375f428..117d56b30f5 100644
--- a/app/views/shared/boards/components/sidebar/_due_date.html.haml
+++ b/app/views/shared/boards/components/sidebar/_due_date.html.haml
@@ -7,7 +7,7 @@
.value
.value-content
%span.no-value{ "v-if" => "!issue.dueDate" }
- = _("No due date")
+ = _("None")
%span.bold{ "v-if" => "issue.dueDate" }
{{ issue.dueDate | due-date }}
- if can_admin_issue?
diff --git a/app/views/shared/boards/components/sidebar/_labels.html.haml b/app/views/shared/boards/components/sidebar/_labels.html.haml
index 311dc69d213..c50826a7cda 100644
--- a/app/views/shared/boards/components/sidebar/_labels.html.haml
+++ b/app/views/shared/boards/components/sidebar/_labels.html.haml
@@ -32,7 +32,7 @@
%span.dropdown-toggle-text
{{ labelDropdownTitle }}
= icon('chevron-down')
- .dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable
+ .dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable.dropdown-extended-height
= render partial: "shared/issuable/label_page_default"
- if can?(current_user, :admin_label, current_board_parent)
= render partial: "shared/issuable/label_page_create", locals: { show_add_list: true }
diff --git a/app/views/shared/groups/_dropdown.html.haml b/app/views/shared/groups/_dropdown.html.haml
index 1ae6d1f5ee3..f4915440cb2 100644
--- a/app/views/shared/groups/_dropdown.html.haml
+++ b/app/views/shared/groups/_dropdown.html.haml
@@ -24,10 +24,10 @@
%li.divider
%li.js-filter-archived-projects
= link_to filter_groups_path(archived: nil), class: ("is-active" unless params[:archived].present?) do
- Hide archived projects
+ = _("Hide archived projects")
%li.js-filter-archived-projects
= link_to filter_groups_path(archived: true), class: ("is-active" if Gitlab::Utils.to_boolean(params[:archived])) do
- Show archived projects
+ = _("Show archived projects")
%li.js-filter-archived-projects
= link_to filter_groups_path(archived: 'only'), class: ("is-active" if params[:archived] == 'only') do
- Show archived projects only
+ = _("Show archived projects only")
diff --git a/app/views/shared/icons/_emoji_slightly_smiling_face.svg b/app/views/shared/icons/_emoji_slightly_smiling_face.svg
deleted file mode 100644
index 56dbad91554..00000000000
--- a/app/views/shared/icons/_emoji_slightly_smiling_face.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><path d="M13.29 11.098a4.328 4.328 0 0 1-1.618 2.285c-.79.578-1.68.867-2.672.867-.992 0-1.883-.29-2.672-.867a4.328 4.328 0 0 1-1.617-2.285.721.721 0 0 1 .047-.569.715.715 0 0 1 .445-.369.721.721 0 0 1 .568.047.715.715 0 0 1 .37.445c.195.625.556 1.131 1.084 1.518A2.93 2.93 0 0 0 9 12.75a2.93 2.93 0 0 0 1.775-.58 2.913 2.913 0 0 0 1.084-1.518.711.711 0 0 1 .375-.445.737.737 0 0 1 .575-.047c.195.063.34.186.433.37.094.183.11.372.047.568zM7.5 6c0 .414-.146.768-.44 1.06-.292.294-.646.44-1.06.44-.414 0-.768-.146-1.06-.44A1.445 1.445 0 0 1 4.5 6c0-.414.146-.768.44-1.06.292-.294.646-.44 1.06-.44.414 0 .768.146 1.06.44.294.292.44.646.44 1.06zm6 0c0 .414-.146.768-.44 1.06-.292.294-.646.44-1.06.44-.414 0-.768-.146-1.06-.44A1.445 1.445 0 0 1 10.5 6c0-.414.146-.768.44-1.06.292-.294.646-.44 1.06-.44.414 0 .768.146 1.06.44.294.292.44.646.44 1.06zm3 3a7.29 7.29 0 0 0-.598-2.912 7.574 7.574 0 0 0-1.6-2.39 7.574 7.574 0 0 0-2.39-1.6A7.29 7.29 0 0 0 9 1.5a7.29 7.29 0 0 0-2.912.598 7.574 7.574 0 0 0-2.39 1.6 7.574 7.574 0 0 0-1.6 2.39A7.29 7.29 0 0 0 1.5 9c0 1.016.2 1.986.598 2.912a7.574 7.574 0 0 0 1.6 2.39 7.574 7.574 0 0 0 2.39 1.6A7.29 7.29 0 0 0 9 16.5a7.29 7.29 0 0 0 2.912-.598 7.574 7.574 0 0 0 2.39-1.6 7.574 7.574 0 0 0 1.6-2.39A7.29 7.29 0 0 0 16.5 9zM18 9a8.804 8.804 0 0 1-1.207 4.518 8.96 8.96 0 0 1-3.275 3.275A8.804 8.804 0 0 1 9 18a8.804 8.804 0 0 1-4.518-1.207 8.96 8.96 0 0 1-3.275-3.275A8.804 8.804 0 0 1 0 9c0-1.633.402-3.139 1.207-4.518a8.96 8.96 0 0 1 3.275-3.275A8.804 8.804 0 0 1 9 0c1.633 0 3.139.402 4.518 1.207a8.96 8.96 0 0 1 3.275 3.275A8.804 8.804 0 0 1 18 9z" fill-rule="evenodd"/></svg>
diff --git a/app/views/shared/icons/_emoji_smile.svg b/app/views/shared/icons/_emoji_smile.svg
deleted file mode 100644
index ce645fee46f..00000000000
--- a/app/views/shared/icons/_emoji_smile.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><path d="M13.29 11.098a4.328 4.328 0 0 1-1.618 2.285c-.79.578-1.68.867-2.672.867-.992 0-1.883-.29-2.672-.867a4.328 4.328 0 0 1-1.617-2.285.721.721 0 0 1 .047-.569.715.715 0 0 1 .445-.369c.195-.062 7.41-.062 7.606 0 .195.063.34.186.433.37.094.183.11.372.047.568zM14 6.37c0 .398-.04.755-.513.755-.473 0-.498-.272-1.237-.272-.74 0-.74.215-1.165.215-.425 0-.585-.3-.585-.698 0-.397.17-.736.513-1.017.341-.281.754-.422 1.237-.422.483 0 .896.14 1.237.422.342.28.513.62.513 1.017zm-6.5 0c0 .398-.04.755-.513.755-.473 0-.498-.272-1.237-.272-.74 0-.74.215-1.165.215-.425 0-.585-.3-.585-.698 0-.397.17-.736.513-1.017.341-.281.754-.422 1.237-.422.483 0 .896.14 1.237.422.342.28.513.62.513 1.017zm9 2.63a7.29 7.29 0 0 0-.598-2.912 7.574 7.574 0 0 0-1.6-2.39 7.574 7.574 0 0 0-2.39-1.6A7.29 7.29 0 0 0 9 1.5a7.29 7.29 0 0 0-2.912.598 7.574 7.574 0 0 0-2.39 1.6 7.574 7.574 0 0 0-1.6 2.39A7.29 7.29 0 0 0 1.5 9c0 1.016.2 1.986.598 2.912a7.574 7.574 0 0 0 1.6 2.39 7.574 7.574 0 0 0 2.39 1.6A7.29 7.29 0 0 0 9 16.5a7.29 7.29 0 0 0 2.912-.598 7.574 7.574 0 0 0 2.39-1.6 7.574 7.574 0 0 0 1.6-2.39A7.29 7.29 0 0 0 16.5 9zM18 9a8.804 8.804 0 0 1-1.207 4.518 8.96 8.96 0 0 1-3.275 3.275A8.804 8.804 0 0 1 9 18a8.804 8.804 0 0 1-4.518-1.207 8.96 8.96 0 0 1-3.275-3.275A8.804 8.804 0 0 1 0 9c0-1.633.402-3.139 1.207-4.518a8.96 8.96 0 0 1 3.275-3.275A8.804 8.804 0 0 1 9 0c1.633 0 3.139.402 4.518 1.207a8.96 8.96 0 0 1 3.275 3.275A8.804 8.804 0 0 1 18 9z" fill-rule="evenodd"/></svg>
diff --git a/app/views/shared/icons/_emoji_smiley.svg b/app/views/shared/icons/_emoji_smiley.svg
deleted file mode 100644
index ddfae50e566..00000000000
--- a/app/views/shared/icons/_emoji_smiley.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><path d="M13.29 11.098a4.328 4.328 0 0 1-1.618 2.285c-.79.578-1.68.867-2.672.867-.992 0-1.883-.29-2.672-.867a4.328 4.328 0 0 1-1.617-2.285.721.721 0 0 1 .047-.569.715.715 0 0 1 .445-.369c.195-.062 7.41-.062 7.606 0 .195.063.34.186.433.37.094.183.11.372.047.568h.001zM7.5 6c0 .414-.146.768-.44 1.06A1.44 1.44 0 0 1 6 7.5a1.44 1.44 0 0 1-1.06-.44A1.445 1.445 0 0 1 4.5 6c0-.414.146-.768.44-1.06A1.44 1.44 0 0 1 6 4.5c.414 0 .768.146 1.06.44.294.292.44.646.44 1.06zm6 0c0 .414-.146.768-.44 1.06A1.44 1.44 0 0 1 12 7.5a1.44 1.44 0 0 1-1.06-.44A1.445 1.445 0 0 1 10.5 6c0-.414.146-.768.44-1.06A1.44 1.44 0 0 1 12 4.5c.414 0 .768.146 1.06.44.294.292.44.646.44 1.06zm3 3a7.29 7.29 0 0 0-.598-2.912 7.574 7.574 0 0 0-1.6-2.39 7.574 7.574 0 0 0-2.39-1.6A7.29 7.29 0 0 0 9 1.5a7.29 7.29 0 0 0-2.912.598 7.574 7.574 0 0 0-2.39 1.6 7.574 7.574 0 0 0-1.6 2.39A7.29 7.29 0 0 0 1.5 9c0 1.016.2 1.986.598 2.912a7.574 7.574 0 0 0 1.6 2.39 7.574 7.574 0 0 0 2.39 1.6c.92.397 1.91.6 2.912.598a7.29 7.29 0 0 0 2.912-.598 7.574 7.574 0 0 0 2.39-1.6 7.574 7.574 0 0 0 1.6-2.39c.397-.92.6-1.91.598-2.912zM18 9a8.804 8.804 0 0 1-1.207 4.518 8.96 8.96 0 0 1-3.275 3.275A8.804 8.804 0 0 1 9 18a8.804 8.804 0 0 1-4.518-1.207 8.96 8.96 0 0 1-3.275-3.275A8.804 8.804 0 0 1 0 9c0-1.633.402-3.139 1.207-4.518a8.96 8.96 0 0 1 3.275-3.275A8.804 8.804 0 0 1 9 0c1.633 0 3.139.402 4.518 1.207a8.96 8.96 0 0 1 3.275 3.275A8.804 8.804 0 0 1 18 9z" fill-rule="nonzero"/></svg>
diff --git a/app/views/shared/icons/_gitea_logo.svg.erb b/app/views/shared/icons/_gitea_logo.svg.erb
new file mode 100644
index 00000000000..c8ddbc5535e
--- /dev/null
+++ b/app/views/shared/icons/_gitea_logo.svg.erb
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><!-- Created with Inkscape (http://www.inkscape.org/) --><svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="<%= size %>" height="<%= size %>" viewBox="0 0 135.46667 135.46667" version="1.1" id="svg8" sodipodi:docname="logo.svg" inkscape:version="0.92.1 r15371" inkscape:export-filename="" inkscape:export-xdpi="48.000004" inkscape:export-ydpi="48.000004" style="zoom: 1;"><defs id="defs2"></defs><sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:zoom="0.70710678" inkscape:cx="418.13805" inkscape:cy="177.57445" inkscape:document-units="mm" inkscape:current-layer="layer2" showgrid="false" units="px" width="256px" showguides="false" inkscape:window-width="1920" inkscape:window-height="1137" inkscape:window-x="1912" inkscape:window-y="-8" inkscape:window-maximized="1" inkscape:pagecheckerboard="false" inkscape:measure-start="283.373,243.952" inkscape:measure-end="290.267,236.527"><sodipodi:guide position="0,0" orientation="0,512" id="guide3699" inkscape:locked="false"></sodipodi:guide><sodipodi:guide position="135.46667,0" orientation="-512,0" id="guide3701" inkscape:locked="false"></sodipodi:guide><sodipodi:guide position="135.46667,135.46667" orientation="0,-512" id="guide3703" inkscape:locked="false"></sodipodi:guide><sodipodi:guide position="0,135.46667" orientation="512,0" id="guide3705" inkscape:locked="false"></sodipodi:guide></sodipodi:namedview><metadata id="metadata5"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"></dc:type><dc:title></dc:title></cc:Work></rdf:RDF></metadata><g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" transform="translate(0,-161.53334)" style="display:inline"><path d="M27.709937,195.15095 c-9.546573,-0.0272 -22.3392732,6.79805 -21.6317552,23.90397 c1.105534,26.72889 25.4565952,29.20839 35.1916502,29.42301 c1.068023,5.01357 12.521798,22.30563 21.001818,23.21667 h37.15277 c22.27763,-1.66785 38.9607,-75.75671 26.59321,-76.03825 c-46.781583,2.47691 -49.995146,2.13838 -88.599758,0 c-2.495053,-0.0266 -5.972321,-0.49474 -9.707935,-0.5054 z m2.491319,9.45886 c1.351378,13.69267 3.555849,21.70359 8.018216,33.94345 c-11.382872,-1.50473 -21.069822,-5.22443 -22.851515,-19.10984 c-0.950962,-7.4112 2.390428,-15.16769 14.833299,-14.83361 z " id="path3722" sodipodi:nodetypes="sscccccsccsc" inkscape:connector-curvature="0" style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"></path></g><g inkscape:groupmode="layer" id="layer2" inkscape:label="Layer 2" style="display:inline"><rect style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.24757317;stroke-opacity:1" id="rect4599" width="34.762054" height="34.762054" x="87.508659" y="18.291576" transform="rotate(25.914715)" ry="5.4825778"></rect><path style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26644793px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 79.804947,57.359056 3.241146,1.609954 V 35.255731 h -3.262698 z" id="path4525" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc"></path></g><g inkscape:groupmode="layer" id="layer3" inkscape:label="Layer 3" style="display:inline"><g style="display:inline" id="g4539"><circle style="fill:#000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1" id="path4606" cy="90.077766" r="3.4745038" cx="49.064713" transform="rotate(-19.796137)"></circle><circle style="fill:#000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1" id="path4606-3" cy="102.1049" r="3.4745038" cx="36.810425" transform="rotate(-19.796137)"></circle><circle style="fill:#000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1" id="path4606-1" cy="111.43928" r="3.4745038" cx="46.484283" transform="rotate(-19.796137)"></circle><rect height="27.261492" style="fill:#000;fill-opacity:1;stroke:none;stroke-width:0.27444693;stroke-opacity:1" x="97.333458" y="18.061695" id="rect4629-8" width="2.6726954" transform="rotate(26.024158)"></rect><path d="M76.558096,68.116343 c12.97589,6.395378 13.012989,4.101862 4.890858,20.907244 " id="path4514" sodipodi:nodetypes="cc" inkscape:connector-curvature="0" style="fill:none;stroke:#000;stroke-width:2.68000007;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"></path></g></g></svg> \ No newline at end of file
diff --git a/app/views/shared/issuable/_label_dropdown.html.haml b/app/views/shared/issuable/_label_dropdown.html.haml
index f2c0c77a583..483652852b6 100644
--- a/app/views/shared/issuable/_label_dropdown.html.haml
+++ b/app/views/shared/issuable/_label_dropdown.html.haml
@@ -25,7 +25,7 @@
%span.dropdown-toggle-text{ class: ("is-default" if apply_is_default_styles) }
= multi_label_name(selected, label_name)
= icon('chevron-down')
- .dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable
+ .dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable.dropdown-extended-height
= render partial: "shared/issuable/label_page_default", locals: { title: dropdown_title, show_footer: show_footer, show_create: show_create }
- if show_create && project && can?(current_user, :admin_label, project)
= render partial: "shared/issuable/label_page_create"
diff --git a/app/views/shared/issuable/_label_page_create.html.haml b/app/views/shared/issuable/_label_page_create.html.haml
index d173e3c0192..a0d3bc64f1f 100644
--- a/app/views/shared/issuable/_label_page_create.html.haml
+++ b/app/views/shared/issuable/_label_page_create.html.haml
@@ -9,9 +9,7 @@
.dropdown-labels-error.js-label-error
%input#new_label_name.default-dropdown-input{ type: "text", placeholder: _('Name new label') }
.suggest-colors.suggest-colors-dropdown
- - suggested_colors.each do |color|
- = link_to '#', style: "background-color: #{color}", data: { color: color } do
- &nbsp
+ = render_suggested_colors
.dropdown-label-color-input
.dropdown-label-color-preview.js-dropdown-label-color-preview
%input#new_label_color.default-dropdown-input{ type: "text", placeholder: _('Assign custom color like #FF0000') }
diff --git a/app/views/shared/issuable/_label_page_default.html.haml b/app/views/shared/issuable/_label_page_default.html.haml
index aa4a5f0e0d3..a0fb5229fc3 100644
--- a/app/views/shared/issuable/_label_page_default.html.haml
+++ b/app/views/shared/issuable/_label_page_default.html.haml
@@ -11,7 +11,7 @@
= dropdown_title(title)
- if show_boards_content
.issue-board-dropdown-content
- %p
+ %p.m-0
= content_title
= dropdown_filter(filter_placeholder)
= dropdown_content
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 2bcfcb6fa7c..3d6c5d29d44 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -3,11 +3,11 @@
- block_css_class = type != :boards_modal ? 'row-content-block second-block' : ''
- user_can_admin_list = board && can?(current_user, :admin_list, board.parent)
-.issues-filters
- .issues-details-filters.filtered-search-block{ class: block_css_class, "v-pre" => type == :boards_modal }
+.issues-filters{ class: ("w-100" if type == :boards_modal) }
+ .issues-details-filters.filtered-search-block.d-flex{ class: block_css_class, "v-pre" => type == :boards_modal }
- if type == :boards
= render_if_exists "shared/boards/switcher", board: board
- = form_tag page_filter_path, method: :get, class: 'filter-form js-filter-form' do
+ = form_tag page_filter_path, method: :get, class: 'filter-form js-filter-form w-100' do
- if params[:search].present?
= hidden_field_tag :search, params[:search]
- if @can_bulk_update
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index 0798b1da4b7..e87e560266f 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -73,7 +73,7 @@
%span.bold= issuable_sidebar[:due_date].to_s(:medium)
- else
%span.no-value
- = _('No due date')
+ = _('None')
- if can_edit_issuable
%span.no-value.js-remove-due-date-holder{ class: ("hidden" if issuable_sidebar[:due_date].nil?) }
\-
@@ -102,11 +102,11 @@
= _('Labels')
= icon('spinner spin', class: 'hidden block-loading', 'aria-hidden': 'true')
- if can_edit_issuable
- = link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right'
+ = link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link qa-edit-link-labels float-right'
.value.issuable-show-labels.dont-hide.hide-collapsed.qa-labels-block{ class: ("has-labels" if selected_labels.any?) }
- if selected_labels.any?
- selected_labels.each do |label_hash|
- = render_label(label_from_hash(label_hash), link: sidebar_label_filter_path(issuable_sidebar[:project_issuables_path], label_hash[:title]))
+ = render_label(label_from_hash(label_hash).present(issuable_subject: nil), link: sidebar_label_filter_path(issuable_sidebar[:project_issuables_path], label_hash[:title]))
- else
%span.no-value
= _('None')
@@ -118,7 +118,7 @@
%span.dropdown-toggle-text{ class: ("is-default" if selected_labels.empty?) }
= multi_label_name(selected_labels, "Labels")
= icon('chevron-down', 'aria-hidden': 'true')
- .dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable
+ .dropdown-menu.dropdown-select.dropdown-menu-paging.qa-dropdown-menu-labels.dropdown-menu-labels.dropdown-menu-selectable.dropdown-extended-height
= render partial: "shared/issuable/label_page_default"
- if issuable_sidebar.dig(:current_user, :can_admin_label)
= render partial: "shared/issuable/label_page_create"
@@ -158,13 +158,13 @@
%button.btn.btn-default.btn-block.js-sidebar-dropdown-toggle.js-move-issue{ type: 'button',
data: { toggle: 'dropdown', display: 'static' } }
= _('Move issue')
- .dropdown-menu.dropdown-menu-selectable
+ .dropdown-menu.dropdown-menu-selectable.dropdown-extended-height
= dropdown_title(_('Move issue'))
= dropdown_filter(_('Search project'), search_id: 'sidebar-move-issue-dropdown-search')
= dropdown_content
= dropdown_loading
= dropdown_footer add_content_class: true do
- %button.btn.btn-success.sidebar-move-issue-confirmation-button.js-move-issue-confirmation-button{ disabled: true }
+ %button.btn.btn-success.sidebar-move-issue-confirmation-button.js-move-issue-confirmation-button{ type: 'button', disabled: true }
= _('Move')
= icon('spinner spin', class: 'sidebar-move-issue-confirmation-loading-icon')
diff --git a/app/views/shared/issuable/_sort_dropdown.html.haml b/app/views/shared/issuable/_sort_dropdown.html.haml
index 967f31c8325..1dd97bc4ed1 100644
--- a/app/views/shared/issuable/_sort_dropdown.html.haml
+++ b/app/views/shared/issuable/_sort_dropdown.html.haml
@@ -10,12 +10,13 @@
= icon('chevron-down')
%ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable.dropdown-menu-sort
%li
- = sortable_item(sort_title_priority, page_filter_path(sort: sort_value_priority), sort_title)
- = sortable_item(sort_title_created_date, page_filter_path(sort: sort_value_created_date), sort_title)
- = sortable_item(sort_title_recently_updated, page_filter_path(sort: sort_value_recently_updated), sort_title)
- = sortable_item(sort_title_milestone, page_filter_path(sort: sort_value_milestone), sort_title)
- = sortable_item(sort_title_due_date, page_filter_path(sort: sort_value_due_date), sort_title) if viewing_issues
- = sortable_item(sort_title_popularity, page_filter_path(sort: sort_value_popularity), sort_title)
- = sortable_item(sort_title_label_priority, page_filter_path(sort: sort_value_label_priority), sort_title)
+ = sortable_item(sort_title_priority, page_filter_path(sort: sort_value_priority), sort_title)
+ = sortable_item(sort_title_created_date, page_filter_path(sort: sort_value_created_date), sort_title)
+ = sortable_item(sort_title_recently_updated, page_filter_path(sort: sort_value_recently_updated), sort_title)
+ = sortable_item(sort_title_milestone, page_filter_path(sort: sort_value_milestone), sort_title)
+ = sortable_item(sort_title_due_date, page_filter_path(sort: sort_value_due_date), sort_title) if viewing_issues
+ = sortable_item(sort_title_popularity, page_filter_path(sort: sort_value_popularity), sort_title)
+ = sortable_item(sort_title_label_priority, page_filter_path(sort: sort_value_label_priority), sort_title)
+ = sortable_item(sort_title_relative_position, page_filter_path(sort: sort_value_relative_position), sort_title) if viewing_issues && Feature.enabled?(:manual_sorting)
= render_if_exists('shared/ee/issuable/sort_dropdown', viewing_issues: viewing_issues, sort_title: sort_title)
= issuable_sort_direction_button(sort_value)
diff --git a/app/views/shared/issuable/form/_contribution.html.haml b/app/views/shared/issuable/form/_contribution.html.haml
index bc9a1edc39c..a78231b37ce 100644
--- a/app/views/shared/issuable/form/_contribution.html.haml
+++ b/app/views/shared/issuable/form/_contribution.html.haml
@@ -15,6 +15,6 @@
= form.check_box :allow_collaboration, disabled: !issuable.can_allow_collaboration?(current_user), class: 'form-check-input'
= form.label :allow_collaboration, class: 'form-check-label' do
= _('Allow commits from members who can merge to the target branch.')
- = link_to 'About this feature', help_page_path('user/project/merge_requests/allow_collaboration')
+ = link_to 'About this feature', help_page_path('user/project/merge_requests/allow_collaboration'), target: '_blank', rel: 'noopener noreferrer nofollow'
.form-text.text-muted
= allow_collaboration_unavailable_reason(issuable)
diff --git a/app/views/shared/issuable/form/_title.html.haml b/app/views/shared/issuable/form/_title.html.haml
index 56c4b021eab..75e9ab547ce 100644
--- a/app/views/shared/issuable/form/_title.html.haml
+++ b/app/views/shared/issuable/form/_title.html.haml
@@ -6,7 +6,7 @@
%div{ class: div_class }
= form.text_field :title, required: true, maxlength: 255, autofocus: true,
- autocomplete: 'off', class: 'form-control pad qa-issuable-form-title', placeholder: _('Title')
+ autocomplete: 'off', class: 'form-control pad qa-issuable-form-title', placeholder: _('Title'), dir: 'auto'
- if issuable.respond_to?(:work_in_progress?)
.form-text.text-muted
diff --git a/app/views/shared/labels/_form.html.haml b/app/views/shared/labels/_form.html.haml
index 743ee1435e8..78ff225daad 100644
--- a/app/views/shared/labels/_form.html.haml
+++ b/app/views/shared/labels/_form.html.haml
@@ -2,17 +2,20 @@
= form_errors(@label)
.form-group.row
- = f.label :title, class: 'col-form-label col-sm-2'
+ .col-sm-2.col-form-label
+ = f.label :title
.col-sm-10
= f.text_field :title, class: "form-control js-label-title qa-label-title", required: true, autofocus: true
= render_if_exists 'shared/labels/create_label_help_text'
.form-group.row
- = f.label :description, class: 'col-form-label col-sm-2'
+ .col-sm-2.col-form-label
+ = f.label :description
.col-sm-10
= f.text_field :description, class: "form-control js-quick-submit qa-label-description"
.form-group.row
- = f.label :color, "Background color", class: 'col-form-label col-sm-2'
+ .col-sm-2.col-form-label
+ = f.label :color, "Background color"
.col-sm-10
.input-group
.input-group-prepend
@@ -22,12 +25,7 @@
Choose any color.
%br
Or you can choose one of the suggested colors below
-
- .suggest-colors
- - suggested_colors.each do |color|
- = link_to '#', style: "background-color: #{color}", data: { color: color } do
- &nbsp;
-
+ = render_suggested_colors
.form-actions
- if @label.persisted?
= f.submit 'Save changes', class: 'btn btn-success js-save-button'
diff --git a/app/views/shared/members/_access_request_links.html.haml b/app/views/shared/members/_access_request_links.html.haml
index f7227b9101e..eac743b5206 100644
--- a/app/views/shared/members/_access_request_links.html.haml
+++ b/app/views/shared/members/_access_request_links.html.haml
@@ -5,7 +5,7 @@
= link_to link_text, polymorphic_path([:leave, source, :members]),
method: :delete,
data: { confirm: leave_confirmation_message(source) },
- class: 'access-request-link'
+ class: 'access-request-link js-leave-link'
- elsif requester = source.requesters.find_by(user_id: current_user.id) # rubocop: disable CodeReuse/ActiveRecord
= link_to _('Withdraw Access Request'), polymorphic_path([:leave, source, :members]),
method: :delete,
diff --git a/app/views/shared/members/_group.html.haml b/app/views/shared/members/_group.html.haml
index 9ec76d82d18..e83ca5eaab8 100644
--- a/app/views/shared/members/_group.html.haml
+++ b/app/views/shared/members/_group.html.haml
@@ -2,9 +2,12 @@
- group = group_link.group
- can_admin_member = can?(current_user, :admin_project_member, @project)
- dom_id = "group_member_#{group_link.id}"
-%li.member.group_member{ id: dom_id }
- %span.list-item-name
- = group_icon(group, class: "avatar s40", alt: '')
+
+-# Note this is just for groups. For individual members please see shared/members/_member
+
+%li.member.group_member.py-2.px-3.d-flex.flex-column.flex-md-row{ id: dom_id }
+ %span.list-item-name.mb-2.m-md-0
+ = group_icon(group, class: "avatar s40 flex-shrink-0 flex-grow-0", alt: '')
.user-info
= link_to group.full_name, group_path(group), class: 'member'
.cgray
@@ -13,10 +16,10 @@
·
%span{ class: ('text-warning' if group_link.expires_soon?) }
= _("Expires in %{expires_at}").html_safe % { expires_at: distance_of_time_in_words_to_now(group_link.expires_at) }
- .controls.member-controls
- = form_tag project_group_link_path(@project, group_link), method: :put, remote: true, class: 'js-edit-member-form form-group row append-right-5' do
+ .controls.member-controls.align-items-center
+ = form_tag project_group_link_path(@project, group_link), method: :put, remote: true, class: 'js-edit-member-form form-group d-sm-flex' do
= hidden_field_tag "group_link[group_access]", group_link.group_access
- .member-form-control.dropdown.append-right-5
+ .member-form-control.dropdown.mr-sm-2.d-sm-inline-block
%button.dropdown-menu-toggle.js-member-permissions-dropdown{ type: "button",
disabled: !can_admin_member,
data: { toggle: "dropdown", field_name: "group_link[group_access]" } }
@@ -32,14 +35,14 @@
= link_to role, "javascript:void(0)",
class: ("is-active" if group_link.group_access == role_id),
data: { id: role_id, el_id: dom_id }
- .prepend-left-5.clearable-input.member-form-control
+ .clearable-input.member-form-control.d-sm-inline-block
= text_field_tag 'group_link[expires_at]', group_link.expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: _('Expiration date'), id: "member_expires_at_#{group.id}", disabled: !can_admin_member
%i.clear-icon.js-clear-input
- if can_admin_member
= link_to project_group_link_path(@project, group_link),
method: :delete,
data: { confirm: _("Are you sure you want to remove %{group_name}?") % { group_name: group.name } },
- class: 'btn btn-remove prepend-left-10' do
+ class: 'btn btn-remove m-0 ml-sm-2 align-self-center' do
%span.d-block.d-sm-none
= _("Delete")
= icon('trash', class: 'd-none d-sm-block')
diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml
index 2db1f67a793..331283f7eec 100644
--- a/app/views/shared/members/_member.html.haml
+++ b/app/views/shared/members/_member.html.haml
@@ -4,11 +4,14 @@
- member = local_assigns.fetch(:member)
- user = local_assigns.fetch(:user, member.user)
- source = member.source
+- override = member.try(:override)
-%li.member{ class: dom_class(member), id: dom_id(member) }
- %span.list-item-name
+-# Note this is just for individual members. For groups please see shared/members/_group
+
+%li.member.py-2.px-3.d-flex.flex-column{ class: [dom_class(member), ("is-overridden" if override), ("flex-md-row" unless force_mobile_view)], id: dom_id(member) }
+ %span.list-item-name.mb-2.m-md-0
- if user
- = image_tag avatar_icon_for_user(user, 40), class: "avatar s40", alt: ''
+ = image_tag avatar_icon_for_user(user, 40), class: "avatar s40 flex-shrink-0 flex-grow-0", alt: ''
.user-info
= link_to user.name, user_path(user), class: 'member js-user-link', data: { user_id: user.id }
= user_status(user)
@@ -42,7 +45,7 @@
= _("Expires in %{expires_at}").html_safe % { expires_at: distance_of_time_in_words_to_now(member.expires_at) }
- else
- = image_tag avatar_icon_for_email(member.invite_email, 40), class: "avatar s40", alt: ''
+ = image_tag avatar_icon_for_email(member.invite_email, 40), class: "avatar s40 flex-shrink-0 flex-grow-0", alt: ''
.user-info
.member= member.invite_email
.cgray
@@ -53,20 +56,22 @@
= time_ago_with_tooltip(member.created_at)
- if show_roles
- current_resource = @project || @group
- .controls.member-controls
+ .controls.member-controls.align-items-center
+ = render_if_exists 'shared/members/ee/ldap_tag', can_override: member.can_override?
- if show_controls && member.source == current_resource
- if member.can_resend_invite?
= link_to icon('paper-plane'), polymorphic_path([:resend_invite, member]),
method: :post,
- class: 'btn btn-default prepend-left-10 d-none d-sm-block',
+ class: 'btn btn-default align-self-center mr-sm-2',
title: _('Resend invite')
- if user != current_user && member.can_update?
- = form_for member, remote: true, html: { class: 'js-edit-member-form form-group row append-right-5' } do |f|
+ = form_for member, remote: true, html: { class: "js-edit-member-form form-group #{'d-sm-flex' unless force_mobile_view}" } do |f|
= f.hidden_field :access_level
- .member-form-control.dropdown.append-right-5
+ .member-form-control.dropdown{ class: [("mr-sm-2 d-sm-inline-block" unless force_mobile_view)] }
%button.dropdown-menu-toggle.js-member-permissions-dropdown{ type: "button",
+ disabled: member.can_override? && !override,
data: { toggle: "dropdown", field_name: "#{f.object_name}[access_level]" } }
%span.dropdown-toggle-text
= member.human_access
@@ -80,20 +85,25 @@
= link_to role, "javascript:void(0)",
class: ("is-active" if member.access_level == role_id),
data: { id: role_id, el_id: dom_id(member) }
- .prepend-left-5.clearable-input.member-form-control
+ = render_if_exists 'shared/members/ee/revert_ldap_group_sync_option',
+ group: @group,
+ member: member,
+ can_override: member.can_override?
+ .clearable-input.member-form-control{ class: [("d-sm-inline-block" unless force_mobile_view)] }
= f.text_field :expires_at,
+ disabled: member.can_override? && !override,
class: 'form-control js-access-expiration-date js-member-update-control',
placeholder: _('Expiration date'),
id: "member_expires_at_#{member.id}",
data: { el_id: dom_id(member) }
%i.clear-icon.js-clear-input
- else
- %span.member-access-text= member.human_access
+ %span.member-access-text.user-access-role= member.human_access
- if member.can_approve?
= link_to polymorphic_path([:approve_access_request, member]),
method: :post,
- class: 'btn btn-success prepend-left-10',
+ class: "btn btn-success align-self-center m-0 mb-2 #{'mb-sm-0 ml-sm-2' unless force_mobile_view}",
title: _('Grant access') do
%span{ class: ('d-block d-sm-none' unless force_mobile_view) }
= _('Grant access')
@@ -105,16 +115,19 @@
= link_to icon('sign-out', text: _('Leave')), polymorphic_path([:leave, member.source, :members]),
method: :delete,
data: { confirm: leave_confirmation_message(member.source) },
- class: 'btn btn-remove prepend-left-10'
+ class: "btn btn-remove align-self-center m-0 #{'ml-sm-2' unless force_mobile_view}"
- else
= link_to member,
method: :delete,
data: { confirm: remove_member_message(member) },
- class: 'btn btn-remove prepend-left-10',
+ class: "btn btn-remove align-self-center m-0 #{'ml-sm-2' unless force_mobile_view}",
title: remove_member_title(member) do
%span{ class: ('d-block d-sm-none' unless force_mobile_view) }
= _("Delete")
- unless force_mobile_view
= icon('trash', class: 'd-none d-sm-block')
+ = render_if_exists 'shared/members/ee/override_member_buttons', group: @group, member: member, user: user, action: :edit, can_override: member.can_override?
- else
- %span.member-access-text= member.human_access
+ %span.member-access-text.user-access-role= member.human_access
+
+= render_if_exists 'shared/members/ee/override_member_buttons', group: @group, member: member, user: user, action: :confirm, can_override: member.can_override?
diff --git a/app/views/shared/milestones/_deprecation_message.html.haml b/app/views/shared/milestones/_deprecation_message.html.haml
index 4a8f90937ea..acd90fa9178 100644
--- a/app/views/shared/milestones/_deprecation_message.html.haml
+++ b/app/views/shared/milestones/_deprecation_message.html.haml
@@ -11,4 +11,5 @@
%ol.milestone-popover-instructions-list.append-bottom-0
%li= _('Click any <strong>project name</strong> in the project list below to navigate to the project milestone.').html_safe
%li= _('Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone.').html_safe
+ %hr.popover-hr
.milestone-popover-footer= link_to _('Learn more'), help_page_url('user/project/milestones/index', anchor: 'promoting-project-milestones-to-group-milestones'), class: 'btn btn-link prepend-left-0', target: '_blank'
diff --git a/app/views/shared/milestones/_issuable.html.haml b/app/views/shared/milestones/_issuable.html.haml
index 5863f52aa78..ae3ab2adfd0 100644
--- a/app/views/shared/milestones/_issuable.html.haml
+++ b/app/views/shared/milestones/_issuable.html.haml
@@ -21,7 +21,7 @@
%span.issuable-number= issuable.to_reference
- labels.each do |label|
- = render_label(label, link: polymorphic_path(issuable_type_args, { milestone_title: @milestone.title, label_name: label.title, state: 'all' }))
+ = render_label(label.present(issuable_subject: project), link: polymorphic_path(issuable_type_args, { milestone_title: @milestone.title, label_name: label.title, state: 'all' }))
%span.assignee-icon
- assignees.each do |assignee|
diff --git a/app/views/shared/milestones/_labels_tab.html.haml b/app/views/shared/milestones/_labels_tab.html.haml
index 6b0640bd8cb..ecab037e378 100644
--- a/app/views/shared/milestones/_labels_tab.html.haml
+++ b/app/views/shared/milestones/_labels_tab.html.haml
@@ -2,7 +2,7 @@
- labels.each do |label|
- options = { milestone_title: @milestone.title, label_name: label.title }
- %li.is-not-draggable
+ %li.no-border
%span.label-row
%span.label-name
= render_label(label, tooltip: false, link: milestones_label_path(options))
diff --git a/app/views/shared/milestones/_top.html.haml b/app/views/shared/milestones/_top.html.haml
index edaeff782de..43503e1d08a 100644
--- a/app/views/shared/milestones/_top.html.haml
+++ b/app/views/shared/milestones/_top.html.haml
@@ -4,10 +4,7 @@
- group = local_assigns[:group]
- is_dynamic_milestone = milestone.legacy_group_milestone? || milestone.dashboard_milestone?
-.detail-page-header
- %a.btn.btn-default.btn-grouped.float-right.d-block.d-sm-none.js-sidebar-toggle{ href: "#" }
- = icon('angle-double-left')
-
+.detail-page-header.milestone-page-header
.status-box{ class: "status-box-#{milestone.closed? ? 'closed' : 'open'}" }
- if milestone.closed?
Closed
@@ -15,14 +12,17 @@
Expired
- else
Open
- %span.identifier
- Milestone #{milestone.title}
- - if milestone.due_date || milestone.start_date
- %span.creator
- &nbsp;&middot;
- = milestone_date_range(milestone)
- - if group
- .float-right
+
+ .header-text-content
+ %span.identifier
+ Milestone #{milestone.title}
+ - if milestone.due_date || milestone.start_date
+ %span.creator
+ &nbsp;&middot;
+ = milestone_date_range(milestone)
+
+ .milestone-buttons
+ - if group
- if can?(current_user, :admin_milestone, group)
- if milestone.group_milestone?
= link_to edit_group_milestone_path(group, milestone), class: "btn btn btn-grouped" do
@@ -35,6 +35,9 @@
- unless is_dynamic_milestone
= render 'shared/milestones/delete_button'
+ %a.btn.btn-default.btn-grouped.float-right.d-block.d-sm-none.js-sidebar-toggle{ href: "#" }
+ = icon('angle-double-left')
+
= render 'shared/milestones/deprecation_message' if is_dynamic_milestone
.detail-page-description.milestone-detail
diff --git a/app/views/shared/notes/_hints.html.haml b/app/views/shared/notes/_hints.html.haml
index 46f3f8428f1..fae7d6526e8 100644
--- a/app/views/shared/notes/_hints.html.haml
+++ b/app/views/shared/notes/_hints.html.haml
@@ -28,8 +28,9 @@
or
%button.attach-new-file.markdown-selector{ type: 'button' }= _("attach a new file")
- %button.markdown-selector.button-attach-file{ type: 'button', tabindex: '-1' }
+ %button.markdown-selector.button-attach-file.btn-link{ type: 'button', tabindex: '-1' }
= icon('file-image-o', class: 'toolbar-button-icon')
- = _("Attach a file")
+ %span.text-attach-file<>
+ = _("Attach a file")
%button.btn.btn-default.btn-sm.hide.button-cancel-uploading-files{ type: 'button' }= _("Cancel")
diff --git a/app/views/shared/notes/_note.html.haml b/app/views/shared/notes/_note.html.haml
index 6fec435cc87..5c9dd72418e 100644
--- a/app/views/shared/notes/_note.html.haml
+++ b/app/views/shared/notes/_note.html.haml
@@ -31,7 +31,7 @@
.note-header
.note-header-info
%a{ href: user_path(note.author) }
- %span.note-header-author-name
+ %span.note-header-author-name.bold
= sanitize(note.author.name)
= user_status(note.author)
%span.note-headline-light
diff --git a/app/views/shared/notifications/_button.html.haml b/app/views/shared/notifications/_button.html.haml
index 2ece7b7f701..749aa258af6 100644
--- a/app/views/shared/notifications/_button.html.haml
+++ b/app/views/shared/notifications/_button.html.haml
@@ -1,24 +1,26 @@
- btn_class = local_assigns.fetch(:btn_class, nil)
- if notification_setting
- .js-notification-dropdown.notification-dropdown.home-panel-action-button.dropdown.inline
+ .js-notification-dropdown.notification-dropdown.mr-md-2.home-panel-action-button.dropdown.inline
= form_for notification_setting, remote: true, html: { class: "inline notification-form" } do |f|
= hidden_setting_source_input(notification_setting)
= f.hidden_field :level, class: "notification_setting_level"
.js-notification-toggle-btns
%div{ class: ("btn-group" if notification_setting.custom?) }
- if notification_setting.custom?
- %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: _("Notification setting"), class: "#{btn_class}", "aria-label" => _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, data: { container: "body", toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } }
+ %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn.text-left#notifications-button{ type: "button", title: _("Notification setting"), class: "#{btn_class}", "aria-label" => _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, data: { container: "body", toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } }
= icon("bell", class: "js-notification-loading")
= notification_title(notification_setting.level)
%button.btn.dropdown-toggle{ data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
= icon('caret-down')
.sr-only Toggle dropdown
- else
- %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: "Notification setting", class: "#{btn_class}", "aria-label" => "Notification setting: #{notification_title(notification_setting.level)}", data: { container: "body", toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
- = icon("bell", class: "js-notification-loading")
- = notification_title(notification_setting.level)
- = icon("caret-down")
+ %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: _("Notification setting"), class: "#{btn_class}", "aria-label" => _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, data: { container: "body", toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
+ .float-left
+ = icon("bell", class: "js-notification-loading")
+ = notification_title(notification_setting.level)
+ .float-right
+ = icon("caret-down")
= render "shared/notifications/notification_dropdown", notification_setting: notification_setting
diff --git a/app/views/shared/notifications/_new_button.html.haml b/app/views/shared/notifications/_new_button.html.haml
index 6d26dbebbc8..052e6da5bae 100644
--- a/app/views/shared/notifications/_new_button.html.haml
+++ b/app/views/shared/notifications/_new_button.html.haml
@@ -10,14 +10,14 @@
%div{ class: ("btn-group" if notification_setting.custom?) }
- if notification_setting.custom?
%button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, class: "#{btn_class}", "aria-label" => _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, data: { container: "body", placement: 'top', toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } }
- = sprite_icon("notifications", css_class: "icon notifications-icon js-notifications-icon")
+ = notification_setting_icon(notification_setting)
%span.js-notification-loading.fa.hidden
%button.btn.dropdown-toggle{ data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" }, class: "#{btn_class}" }
= sprite_icon("arrow-down", css_class: "icon mr-0")
.sr-only Toggle dropdown
- else
- %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: "Notification setting - #{notification_title(notification_setting.level)}", class: "#{btn_class}", "aria-label" => "Notification setting: #{notification_title(notification_setting.level)}", data: { container: "body", placement: 'top', toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
- = sprite_icon("notifications", css_class: "icon notifications-icon js-notifications-icon")
+ %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, class: "#{btn_class}", "aria-label" => _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, data: { container: "body", placement: 'top', toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
+ = notification_setting_icon(notification_setting)
%span.js-notification-loading.fa.hidden
= sprite_icon("arrow-down", css_class: "icon")
diff --git a/app/views/shared/notifications/_notification_dropdown.html.haml b/app/views/shared/notifications/_notification_dropdown.html.haml
index 85ad74f9a39..a6ef2d51171 100644
--- a/app/views/shared/notifications/_notification_dropdown.html.haml
+++ b/app/views/shared/notifications/_notification_dropdown.html.haml
@@ -8,5 +8,5 @@
%li.divider
%li
%a.update-notification{ href: "#", role: "button", class: ("is-active" if notification_setting.custom?), data: { toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), notification_level: "custom", notification_title: "Custom" } }
- %strong.dropdown-menu-inner-title Custom
+ %strong.dropdown-menu-inner-title= s_('NotificationSetting|Custom')
%span.dropdown-menu-inner-content= notification_description("custom")
diff --git a/app/views/shared/projects/_dropdown.html.haml b/app/views/shared/projects/_dropdown.html.haml
index 98b258d9275..88ac03bf9e3 100644
--- a/app/views/shared/projects/_dropdown.html.haml
+++ b/app/views/shared/projects/_dropdown.html.haml
@@ -1,10 +1,9 @@
- @sort ||= sort_value_latest_activity
.dropdown.js-project-filter-dropdown-wrap
- - toggle_text = projects_sort_options_hash[@sort]
- = dropdown_toggle(toggle_text, { toggle: 'dropdown', display: 'static' }, { id: 'sort-projects-dropdown' })
+ = dropdown_toggle(projects_sort_options_hash[@sort], { toggle: 'dropdown', display: 'static' }, { id: 'sort-projects-dropdown' })
%ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable
%li.dropdown-header
- Sort by
+ = _("Sort by")
- projects_sort_options_hash.each do |value, title|
%li
= link_to filter_projects_path(sort: value), class: ("is-active" if @sort == value) do
@@ -13,29 +12,29 @@
%li.divider
%li
= link_to filter_projects_path(archived: nil), class: ("is-active" unless params[:archived].present?) do
- Hide archived projects
+ = _("Hide archived projects")
%li
= link_to filter_projects_path(archived: true), class: ("is-active" if Gitlab::Utils.to_boolean(params[:archived])) do
- Show archived projects
+ = _("Show archived projects")
%li
= link_to filter_projects_path(archived: 'only'), class: ("is-active" if params[:archived] == 'only') do
- Show archived projects only
+ = _("Show archived projects only")
- if current_user
%li.divider
%li
= link_to filter_projects_path(personal: nil), class: ("is-active" unless params[:personal].present?) do
- Owned by anyone
+ = _("Owned by anyone")
%li
= link_to filter_projects_path(personal: true), class: ("is-active" if params[:personal].present?) do
- Owned by me
+ = _("Owned by me")
- if @group && @group.shared_projects.present?
%li.divider
%li
= link_to filter_projects_path(shared: nil), class: ("is-active" unless params[:shared].present?) do
- All projects
+ = _("All projects")
%li
= link_to filter_projects_path(shared: 0), class: ("is-active" if params[:shared] == '0') do
- Hide shared projects
+ = _("Hide shared projects")
%li
= link_to filter_projects_path(shared: 1), class: ("is-active" if params[:shared] == '1') do
- Hide group projects
+ = _("Hide group projects")
diff --git a/app/views/shared/projects/_search_bar.html.haml b/app/views/shared/projects/_search_bar.html.haml
new file mode 100644
index 00000000000..c1f2eaba284
--- /dev/null
+++ b/app/views/shared/projects/_search_bar.html.haml
@@ -0,0 +1,28 @@
+- @sort ||= sort_value_latest_activity
+- project_tab_filter = local_assigns.fetch(:project_tab_filter, "")
+- flex_grow_and_shrink_xs = 'd-flex flex-xs-grow-1 flex-xs-shrink-1 flex-grow-0 flex-shrink-0'
+
+.filtered-search-block.row-content-block.bt-0
+ .filtered-search-wrapper.d-flex.flex-nowrap.flex-column.flex-sm-wrap.flex-sm-row.flex-xl-nowrap
+ - unless project_tab_filter == :starred
+ .filtered-search-nav.mb-2.mb-lg-0{ class: flex_grow_and_shrink_xs }
+ = render 'dashboard/projects/nav', project_tab_filter: project_tab_filter
+ .filtered-search.d-flex.flex-grow-1.flex-shrink-1.w-100.mb-2.mb-lg-0.ml-0{ class: project_tab_filter == :starred ? "extended-filtered-search-box mb-2 mb-lg-0" : "ml-sm-3" }
+ .btn-group.w-100{ role: "group" }
+ .btn-group.w-100{ role: "group" }
+ .filtered-search-box.m-0
+ .filtered-search-box-input-container.pl-2
+ = render 'shared/projects/search_form', admin_view: false, search_form_placeholder: _("Search projects...")
+ %button.btn.btn-secondary{ type: 'submit', form: 'project-filter-form' }
+ = sprite_icon('search', size: 16, css_class: 'search-icon ')
+ .filtered-search-dropdown.flex-row.align-items-center.mb-2.m-sm-0#filtered-search-visibility-dropdown{ class: flex_grow_and_shrink_xs }
+ .filtered-search-dropdown-label.p-0.pl-sm-3.font-weight-bold
+ %span
+ = _("Visibility")
+ = render 'explore/projects/filter', has_label: true
+ .filtered-search-dropdown.flex-row.align-items-center.m-sm-0#filtered-search-sorting-dropdown{ class: flex_grow_and_shrink_xs }
+ .filtered-search-dropdown-label.p-0.pl-sm-3.font-weight-bold
+ %span
+ = _("Sort by")
+ = render 'shared/projects/sort_dropdown'
+
diff --git a/app/views/shared/projects/_search_form.html.haml b/app/views/shared/projects/_search_form.html.haml
index 3b5c13ed93a..7c7c0a363ac 100644
--- a/app/views/shared/projects/_search_form.html.haml
+++ b/app/views/shared/projects/_search_form.html.haml
@@ -1,7 +1,10 @@
+- form_field_classes = local_assigns[:admin_view] || !Feature.enabled?(:project_list_filter_bar) ? 'input-short js-projects-list-filter' : ''
+- placeholder = local_assigns[:search_form_placeholder] ? search_form_placeholder : 'Filter by name...'
+
= form_tag filter_projects_path, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f|
= search_field_tag :name, params[:name],
- placeholder: 'Filter by name...',
- class: 'project-filter-form-field form-control input-short js-projects-list-filter',
+ placeholder: placeholder,
+ class: "project-filter-form-field form-control #{form_field_classes}",
spellcheck: false,
id: 'project-filter-form-field',
tabindex: "2",
diff --git a/app/views/shared/projects/_sort_dropdown.html.haml b/app/views/shared/projects/_sort_dropdown.html.haml
new file mode 100644
index 00000000000..f5f940db189
--- /dev/null
+++ b/app/views/shared/projects/_sort_dropdown.html.haml
@@ -0,0 +1,39 @@
+- @sort ||= sort_value_latest_activity
+- toggle_text = projects_sort_option_titles[@sort]
+
+.btn-group.w-100{ role: "group" }
+ .btn-group.w-100.dropdown.js-project-filter-dropdown-wrap{ role: "group" }
+ %button#sort-projects-dropdown.btn.btn-default.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' } }
+ = toggle_text
+ = icon('chevron-down')
+ %ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable
+ %li.dropdown-header
+ = _("Sort by")
+ - projects_sort_options_hash.each do |value, title|
+ %li
+ = link_to title, filter_projects_path(sort: value), class: ("is-active" if toggle_text == title)
+
+ %li.divider
+ %li
+ = link_to filter_projects_path(archived: nil), class: ("is-active" unless params[:archived].present?) do
+ = _("Hide archived projects")
+ %li
+ = link_to filter_projects_path(archived: true), class: ("is-active" if Gitlab::Utils.to_boolean(params[:archived])) do
+ = _("Show archived projects")
+ %li
+ = link_to filter_projects_path(archived: 'only'), class: ("is-active" if params[:archived] == 'only') do
+ = _("Show archived projects only")
+
+ - if current_user && @group && @group.shared_projects.present?
+ %li.divider
+ %li
+ = link_to filter_projects_path(shared: nil), class: ("is-active" unless params[:shared].present?) do
+ = _("All projects")
+ %li
+ = link_to filter_projects_path(shared: 0), class: ("is-active" if params[:shared] == '0') do
+ = _("Hide shared projects")
+ %li
+ = link_to filter_projects_path(shared: 1), class: ("is-active" if params[:shared] == '1') do
+ = _("Hide group projects")
+
+ = project_sort_direction_button(@sort)
diff --git a/app/views/shared/snippets/_form.html.haml b/app/views/shared/snippets/_form.html.haml
index 6f2ddc5bdba..2d2382e469a 100644
--- a/app/views/shared/snippets/_form.html.haml
+++ b/app/views/shared/snippets/_form.html.haml
@@ -7,7 +7,8 @@
= form_errors(@snippet)
.form-group.row
- = f.label :title, class: 'col-form-label col-sm-2'
+ .col-sm-2.col-form-label
+ = f.label :title
.col-sm-10
= f.text_field :title, class: 'form-control qa-snippet-title', required: true, autofocus: true
@@ -17,7 +18,8 @@
.file-editor
.form-group.row
- = f.label :file_name, "File", class: 'col-form-label col-sm-2'
+ .col-sm-2.col-form-label
+ = f.label :file_name, "File"
.col-sm-10
.file-holder.snippet
.js-file-title.file-title
diff --git a/app/views/snippets/_actions.html.haml b/app/views/snippets/_actions.html.haml
index ef8664e6f47..9952f373156 100644
--- a/app/views/snippets/_actions.html.haml
+++ b/app/views/snippets/_actions.html.haml
@@ -7,7 +7,7 @@
- if can?(current_user, :admin_personal_snippet, @snippet)
= link_to snippet_path(@snippet), method: :delete, data: { confirm: _("Are you sure?") }, class: "btn btn-grouped btn-inverted btn-remove", title: _('Delete Snippet') do
= _("Delete")
- = link_to new_snippet_path, class: "btn btn-grouped btn-inverted btn-create", title: _("New snippet") do
+ = link_to new_snippet_path, class: "btn btn-grouped btn-success btn-inverted", title: _("New snippet") do
= _("New snippet")
- if @snippet.submittable_as_spam_by?(current_user)
= link_to _('Submit as spam'), mark_as_spam_snippet_path(@snippet), method: :post, class: 'btn btn-grouped btn-spam', title: _('Submit as spam')
diff --git a/app/views/snippets/notes/_actions.html.haml b/app/views/snippets/notes/_actions.html.haml
index 01b95145937..6e20890a47f 100644
--- a/app/views/snippets/notes/_actions.html.haml
+++ b/app/views/snippets/notes/_actions.html.haml
@@ -3,9 +3,9 @@
.note-actions-item
= link_to '#', title: _('Add reaction'), class: "note-action-button note-emoji-button js-add-award js-note-emoji has-tooltip", data: { position: 'right' } do
= icon('spinner spin')
- %span{ class: 'link-highlight award-control-icon-neutral' }= custom_icon('emoji_slightly_smiling_face')
- %span{ class: 'link-highlight award-control-icon-positive' }= custom_icon('emoji_smiley')
- %span{ class: 'link-highlight award-control-icon-super-positive' }= custom_icon('emoji_smile')
+ %span{ class: 'link-highlight award-control-icon-neutral' }= sprite_icon('slight-smile')
+ %span{ class: 'link-highlight award-control-icon-positive' }= sprite_icon('smiley')
+ %span{ class: 'link-highlight award-control-icon-super-positive' }= sprite_icon('smile')
- if note_editable
.note-actions-item
diff --git a/app/views/users/calendar_activities.html.haml b/app/views/users/calendar_activities.html.haml
index 01acbf8eadd..3191eaa1e2c 100644
--- a/app/views/users/calendar_activities.html.haml
+++ b/app/views/users/calendar_activities.html.haml
@@ -9,7 +9,7 @@
%i.fa.fa-clock-o
= event.created_at.to_time.in_time_zone.strftime('%-I:%M%P')
- if event.visible_to_user?(current_user)
- - if event.push?
+ - if event.push_action?
#{event.action_name} #{event.ref_type}
%strong
- commits_path = project_commits_path(event.project, event.ref_name)
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 211e3eafac6..a71bfd624e4 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -9,7 +9,7 @@
= auto_discovery_link_tag(:atom, user_url(@user, format: :atom), title: "#{@user.name} activity")
.user-profile
- .cover-block.user-cover-block.top-area
+ .cover-block.user-cover-block
.cover-controls
- if @user == current_user
= link_to profile_path, class: 'btn btn-default has-tooltip', title: s_('UserProfile|Edit profile'), 'aria-label': 'Edit profile' do
@@ -45,7 +45,7 @@
= emoji_icon(@user.status.emoji)
= markdown_field(@user.status, :message)
- .cover-desc.member-date
+ .cover-desc.member-date.cgray
%p
%span.middle-dot-divider
@#{@user.username}
@@ -53,7 +53,7 @@
%span.middle-dot-divider
= s_('Member since %{date}') % { date: @user.created_at.to_date.to_s(:long) }
- .cover-desc
+ .cover-desc.cgray
- unless @user.public_email.blank?
.profile-link-holder.middle-dot-divider
= link_to @user.public_email, "mailto:#{@user.public_email}", class: 'text-link'
@@ -82,7 +82,7 @@
= @user.organization
- if @user.bio.present?
- .cover-desc
+ .cover-desc.cgray
%p.profile-user-bio
= @user.bio
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index f9b2e698fc9..fd0cc5fb24e 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -1,11 +1,14 @@
---
- auto_devops:auto_devops_disable
+- auto_merge:auto_merge_process
+
- cronjob:admin_email
- cronjob:expire_build_artifacts
- cronjob:gitlab_usage_ping
- cronjob:import_export_project_cleanup
- cronjob:pages_domain_verification_cron
+- cronjob:pages_domain_removal_cron
- cronjob:pipeline_schedule
- cronjob:prune_old_events
- cronjob:remove_expired_group_links
@@ -32,6 +35,8 @@
- gcp_cluster:cluster_wait_for_ingress_ip_address
- gcp_cluster:cluster_configure
- gcp_cluster:cluster_project_configure
+- gcp_cluster:clusters_applications_wait_for_uninstall_app
+- gcp_cluster:clusters_applications_uninstall
- github_import_advance_stage
- github_importer:github_import_import_diff_note
@@ -83,6 +88,7 @@
- pipeline_processing:ci_build_schedule
- deployment:deployments_success
+- deployment:deployments_finished
- repository_check:repository_check_clear
- repository_check:repository_check_batch
diff --git a/app/workers/auto_merge_process_worker.rb b/app/workers/auto_merge_process_worker.rb
new file mode 100644
index 00000000000..cd81cdbc60c
--- /dev/null
+++ b/app/workers/auto_merge_process_worker.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class AutoMergeProcessWorker
+ include ApplicationWorker
+
+ queue_namespace :auto_merge
+
+ def perform(merge_request_id)
+ MergeRequest.find_by_id(merge_request_id).try do |merge_request|
+ AutoMergeService.new(merge_request.project, merge_request.merge_user)
+ .process(merge_request)
+ end
+ end
+end
diff --git a/app/workers/build_finished_worker.rb b/app/workers/build_finished_worker.rb
index adc38226405..8e2a18a8fd8 100644
--- a/app/workers/build_finished_worker.rb
+++ b/app/workers/build_finished_worker.rb
@@ -30,6 +30,7 @@ class BuildFinishedWorker
# We execute these async as these are independent operations.
BuildHooksWorker.perform_async(build.id)
ArchiveTraceWorker.perform_async(build.id)
+ ExpirePipelineCacheWorker.perform_async(build.pipeline_id)
ChatNotificationWorker.perform_async(build.id) if build.pipeline.chat?
end
end
diff --git a/app/workers/cluster_configure_worker.rb b/app/workers/cluster_configure_worker.rb
index b984dee5b21..6f64b7ea0ab 100644
--- a/app/workers/cluster_configure_worker.rb
+++ b/app/workers/cluster_configure_worker.rb
@@ -5,10 +5,10 @@ class ClusterConfigureWorker
include ClusterQueue
def perform(cluster_id)
- return if Feature.enabled?(:ci_preparing_state, default_enabled: true)
-
- Clusters::Cluster.find_by_id(cluster_id).try do |cluster|
- Clusters::RefreshService.create_or_update_namespaces_for_cluster(cluster)
+ Clusters::Cluster.managed.find_by_id(cluster_id).try do |cluster|
+ if cluster.project_type?
+ Clusters::RefreshService.create_or_update_namespaces_for_cluster(cluster)
+ end
end
end
end
diff --git a/app/workers/cluster_project_configure_worker.rb b/app/workers/cluster_project_configure_worker.rb
index d7bea69a01c..497e57c0d0b 100644
--- a/app/workers/cluster_project_configure_worker.rb
+++ b/app/workers/cluster_project_configure_worker.rb
@@ -5,8 +5,6 @@ class ClusterProjectConfigureWorker
include ClusterQueue
def perform(project_id)
- return if Feature.enabled?(:ci_preparing_state, default_enabled: true)
-
project = Project.find(project_id)
::Clusters::RefreshService.create_or_update_namespaces_for_project(project)
diff --git a/app/workers/clusters/applications/uninstall_worker.rb b/app/workers/clusters/applications/uninstall_worker.rb
new file mode 100644
index 00000000000..85e8ecc4ad5
--- /dev/null
+++ b/app/workers/clusters/applications/uninstall_worker.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Applications
+ class UninstallWorker
+ include ApplicationWorker
+ include ClusterQueue
+ include ClusterApplications
+
+ def perform(app_name, app_id)
+ find_application(app_name, app_id) do |app|
+ Clusters::Applications::UninstallService.new(app).execute
+ end
+ end
+ end
+ end
+end
diff --git a/app/workers/clusters/applications/wait_for_uninstall_app_worker.rb b/app/workers/clusters/applications/wait_for_uninstall_app_worker.rb
new file mode 100644
index 00000000000..163c99d3c3c
--- /dev/null
+++ b/app/workers/clusters/applications/wait_for_uninstall_app_worker.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Applications
+ class WaitForUninstallAppWorker
+ include ApplicationWorker
+ include ClusterQueue
+ include ClusterApplications
+
+ INTERVAL = 10.seconds
+ TIMEOUT = 20.minutes
+
+ def perform(app_name, app_id)
+ find_application(app_name, app_id) do |app|
+ Clusters::Applications::CheckUninstallProgressService.new(app).execute
+ end
+ end
+ end
+ end
+end
diff --git a/app/workers/deployments/finished_worker.rb b/app/workers/deployments/finished_worker.rb
new file mode 100644
index 00000000000..c9d448d5d18
--- /dev/null
+++ b/app/workers/deployments/finished_worker.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Deployments
+ class FinishedWorker
+ include ApplicationWorker
+
+ queue_namespace :deployment
+
+ def perform(deployment_id)
+ Deployment.find_by_id(deployment_id).try(:execute_hooks)
+ end
+ end
+end
diff --git a/app/workers/detect_repository_languages_worker.rb b/app/workers/detect_repository_languages_worker.rb
index 64bc9776d48..838c3be78f0 100644
--- a/app/workers/detect_repository_languages_worker.rb
+++ b/app/workers/detect_repository_languages_worker.rb
@@ -12,13 +12,12 @@ class DetectRepositoryLanguagesWorker
attr_reader :project
# rubocop: disable CodeReuse/ActiveRecord
- def perform(project_id, user_id)
+ def perform(project_id, user_id = nil)
@project = Project.find_by(id: project_id)
- user = User.find_by(id: user_id)
- return unless project && user
+ return unless project
try_obtain_lease do
- ::Projects::DetectRepositoryLanguagesService.new(project, user).execute
+ ::Projects::DetectRepositoryLanguagesService.new(project).execute
end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/workers/git_garbage_collect_worker.rb b/app/workers/git_garbage_collect_worker.rb
index b33e9b1f718..489d6215774 100644
--- a/app/workers/git_garbage_collect_worker.rb
+++ b/app/workers/git_garbage_collect_worker.rb
@@ -23,13 +23,15 @@ class GitGarbageCollectWorker
end
task = task.to_sym
- project.link_pool_repository
+
+ ::Projects::GitDeduplicationService.new(project).execute
+
gitaly_call(task, project.repository.raw_repository)
# Refresh the branch cache in case garbage collection caused a ref lookup to fail
flush_ref_caches(project) if task == :gc
- project.repository.expire_statistics_caches
+ project.repository.expire_statistics_caches if task != :pack_refs
# In case pack files are deleted, release libgit2 cache and open file
# descriptors ASAP instead of waiting for Ruby garbage collection
@@ -58,7 +60,12 @@ class GitGarbageCollectWorker
## `repository` has to be a Gitlab::Git::Repository
def gitaly_call(task, repository)
- client = Gitlab::GitalyClient::RepositoryService.new(repository)
+ client = if task == :pack_refs
+ Gitlab::GitalyClient::RefService.new(repository)
+ else
+ Gitlab::GitalyClient::RepositoryService.new(repository)
+ end
+
case task
when :gc
client.garbage_collect(bitmaps_enabled?)
@@ -66,6 +73,8 @@ class GitGarbageCollectWorker
client.repack_full(bitmaps_enabled?)
when :incremental_repack
client.repack_incremental
+ when :pack_refs
+ client.pack_refs
end
rescue GRPC::NotFound => e
Gitlab::GitLogger.error("#{__method__} failed:\nRepository not found")
diff --git a/app/workers/pages_domain_removal_cron_worker.rb b/app/workers/pages_domain_removal_cron_worker.rb
new file mode 100644
index 00000000000..79f38e1b89f
--- /dev/null
+++ b/app/workers/pages_domain_removal_cron_worker.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class PagesDomainRemovalCronWorker
+ include ApplicationWorker
+ include CronjobQueue
+
+ def perform
+ PagesDomain.for_removal.find_each do |domain|
+ domain.destroy!
+ rescue => e
+ Raven.capture_exception(e)
+ end
+ end
+end
diff --git a/app/workers/pages_domain_verification_cron_worker.rb b/app/workers/pages_domain_verification_cron_worker.rb
index 92d62a15aee..60703c83e9e 100644
--- a/app/workers/pages_domain_verification_cron_worker.rb
+++ b/app/workers/pages_domain_verification_cron_worker.rb
@@ -5,6 +5,8 @@ class PagesDomainVerificationCronWorker
include CronjobQueue
def perform
+ return if Gitlab::Database.read_only?
+
PagesDomain.needs_verification.find_each do |domain|
PagesDomainVerificationWorker.perform_async(domain.id)
end
diff --git a/app/workers/pages_domain_verification_worker.rb b/app/workers/pages_domain_verification_worker.rb
index b3319ff5a13..7817b2ee5fc 100644
--- a/app/workers/pages_domain_verification_worker.rb
+++ b/app/workers/pages_domain_verification_worker.rb
@@ -5,6 +5,8 @@ class PagesDomainVerificationWorker
# rubocop: disable CodeReuse/ActiveRecord
def perform(domain_id)
+ return if Gitlab::Database.read_only?
+
domain = PagesDomain.find_by(id: domain_id)
return unless domain
diff --git a/app/workers/pipeline_schedule_worker.rb b/app/workers/pipeline_schedule_worker.rb
index 02a69ea3b54..9410fd1a786 100644
--- a/app/workers/pipeline_schedule_worker.rb
+++ b/app/workers/pipeline_schedule_worker.rb
@@ -4,40 +4,11 @@ class PipelineScheduleWorker
include ApplicationWorker
include CronjobQueue
- # rubocop: disable CodeReuse/ActiveRecord
def perform
- Ci::PipelineSchedule.active.where("next_run_at < ?", Time.now)
- .preload(:owner, :project).find_each do |schedule|
-
- Ci::CreatePipelineService.new(schedule.project,
- schedule.owner,
- ref: schedule.ref)
- .execute!(:schedule, ignore_skip_ci: true, save_on_errors: true, schedule: schedule)
- rescue => e
- error(schedule, e)
- ensure
- schedule.schedule_next_run!
+ Ci::PipelineSchedule.runnable_schedules.preloaded.find_in_batches do |schedules|
+ schedules.each do |schedule|
+ Ci::PipelineScheduleService.new(schedule.project, schedule.owner).execute(schedule)
+ end
end
end
- # rubocop: enable CodeReuse/ActiveRecord
-
- private
-
- def error(schedule, error)
- failed_creation_counter.increment
-
- Rails.logger.error "Failed to create a scheduled pipeline. " \
- "schedule_id: #{schedule.id} message: #{error.message}"
-
- Gitlab::Sentry
- .track_exception(error,
- issue_url: 'https://gitlab.com/gitlab-org/gitlab-ce/issues/41231',
- extra: { schedule_id: schedule.id })
- end
-
- def failed_creation_counter
- @failed_creation_counter ||=
- Gitlab::Metrics.counter(:pipeline_schedule_creation_failed_total,
- "Counter of failed attempts of pipeline schedule creation")
- end
end
diff --git a/app/workers/pipeline_success_worker.rb b/app/workers/pipeline_success_worker.rb
index 4f349ed922c..666331e6cd4 100644
--- a/app/workers/pipeline_success_worker.rb
+++ b/app/workers/pipeline_success_worker.rb
@@ -6,13 +6,7 @@ class PipelineSuccessWorker
queue_namespace :pipeline_processing
- # rubocop: disable CodeReuse/ActiveRecord
def perform(pipeline_id)
- Ci::Pipeline.find_by(id: pipeline_id).try do |pipeline|
- MergeRequests::MergeWhenPipelineSucceedsService
- .new(pipeline.project, nil)
- .trigger(pipeline)
- end
+ # no-op
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index 337efa7919b..3f1639ec2ed 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -21,8 +21,10 @@ class PostReceive
if repo_type.wiki?
process_wiki_changes(post_received)
- else
+ elsif repo_type.project?
process_project_changes(post_received)
+ else
+ # Other repos don't have hooks for now
end
end
@@ -72,6 +74,8 @@ class PostReceive
def process_wiki_changes(post_received)
post_received.project.touch(:last_activity_at, :last_repository_updated_at)
+ post_received.project.wiki.repository.expire_statistics_caches
+ ProjectCacheWorker.perform_async(post_received.project.id, [], [:wiki_size])
end
def log(message)
diff --git a/app/workers/process_commit_worker.rb b/app/workers/process_commit_worker.rb
index 29a7f8e691a..3efb5343a96 100644
--- a/app/workers/process_commit_worker.rb
+++ b/app/workers/process_commit_worker.rb
@@ -48,7 +48,7 @@ class ProcessCommitWorker
# Issues::CloseService#execute.
IssueCollection.new(issues).updatable_by_user(user).each do |issue|
Issues::CloseService.new(project, author)
- .close_issue(issue, commit: commit)
+ .close_issue(issue, closed_via: commit)
end
end
diff --git a/app/workers/project_cache_worker.rb b/app/workers/project_cache_worker.rb
index b2e0701008a..4e8ea903139 100644
--- a/app/workers/project_cache_worker.rb
+++ b/app/workers/project_cache_worker.rb
@@ -16,10 +16,12 @@ class ProjectCacheWorker
def perform(project_id, files = [], statistics = [])
project = Project.find_by(id: project_id)
- return unless project && project.repository.exists?
+ return unless project
update_statistics(project, statistics)
+ return unless project.repository.exists?
+
project.repository.refresh_method_caches(files.map(&:to_sym))
project.cleanup
diff --git a/app/workers/run_pipeline_schedule_worker.rb b/app/workers/run_pipeline_schedule_worker.rb
index f72331c003a..43e0b9db22f 100644
--- a/app/workers/run_pipeline_schedule_worker.rb
+++ b/app/workers/run_pipeline_schedule_worker.rb
@@ -21,6 +21,30 @@ class RunPipelineScheduleWorker
Ci::CreatePipelineService.new(schedule.project,
user,
ref: schedule.ref)
- .execute(:schedule, ignore_skip_ci: true, save_on_errors: false, schedule: schedule)
+ .execute!(:schedule, ignore_skip_ci: true, save_on_errors: false, schedule: schedule)
+ rescue Ci::CreatePipelineService::CreateError
+ # no-op. This is a user operation error such as corrupted .gitlab-ci.yml.
+ rescue => e
+ error(schedule, e)
+ end
+
+ private
+
+ def error(schedule, error)
+ failed_creation_counter.increment
+
+ Rails.logger.error "Failed to create a scheduled pipeline. " \
+ "schedule_id: #{schedule.id} message: #{error.message}"
+
+ Gitlab::Sentry
+ .track_exception(error,
+ issue_url: 'https://gitlab.com/gitlab-org/gitlab-ce/issues/41231',
+ extra: { schedule_id: schedule.id })
+ end
+
+ def failed_creation_counter
+ @failed_creation_counter ||=
+ Gitlab::Metrics.counter(:pipeline_schedule_creation_failed_total,
+ "Counter of failed attempts of pipeline schedule creation")
end
end
diff --git a/app/workers/todos_destroyer/confidential_issue_worker.rb b/app/workers/todos_destroyer/confidential_issue_worker.rb
index 481fde8c83d..240a5f98ad5 100644
--- a/app/workers/todos_destroyer/confidential_issue_worker.rb
+++ b/app/workers/todos_destroyer/confidential_issue_worker.rb
@@ -5,8 +5,8 @@ module TodosDestroyer
include ApplicationWorker
include TodosDestroyerQueue
- def perform(issue_id)
- ::Todos::Destroy::ConfidentialIssueService.new(issue_id).execute
+ def perform(issue_id = nil, project_id = nil)
+ ::Todos::Destroy::ConfidentialIssueService.new(issue_id: issue_id, project_id: project_id).execute
end
end
end
diff --git a/babel.config.js b/babel.config.js
index 78d14095b0b..05554e8763e 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -38,8 +38,9 @@ if (BABEL_ENV === 'karma' || BABEL_ENV === 'coverage') {
plugins.push('babel-plugin-rewire');
}
-// Jest is running in node environment
-if (BABEL_ENV === 'jest') {
+// Jest is running in node environment, so we need additional plugins
+const isJest = Boolean(process.env.JEST_WORKER_ID);
+if (isJest) {
plugins.push('@babel/plugin-transform-modules-commonjs');
/*
without the following, babel-plugin-istanbul throws an error:
diff --git a/changelogs/archive.md b/changelogs/archive.md
index dd7c21dabd6..e36e859a351 100644
--- a/changelogs/archive.md
+++ b/changelogs/archive.md
@@ -274,7 +274,7 @@
- Pass variables from deployment project services to CI runner. !8107
- New Gitea importer. !8116
- Introduce "Set up autodeploy" button to help configure GitLab CI for deployment. !8135
-- Prevent enviroment table to overflow when name has underscores. !8142
+- Prevent environment table to overflow when name has underscores. !8142
- Fix missing service error importing from EE to CE. !8144
- Milestoneish SQL performance partially improved and memoized. !8146
- Allow unauthenticated access to Repositories API GET endpoints. !8148
@@ -562,7 +562,7 @@
- Fix broken issue/merge request links in JIRA comments. !6143 (Brian Kintz)
- Fix filtering of milestones with quotes in title (airatshigapov)
- Fix issue boards dragging bug in Safari
-- Refactor less readable existance checking code from CoffeeScript !6289 (jlogandavison)
+- Refactor less readable existence checking code from CoffeeScript !6289 (jlogandavison)
- Update mail_room and enable sentinel support to Reply By Email (!7101)
- Add task completion status in Issues and Merge Requests tabs: "X of Y tasks completed" (!6527, @gmesalazar)
- Simpler arguments passed to named_route on toggle_award_url helper method
@@ -956,7 +956,7 @@
## 8.12.0 (2016-09-22)
- - Removes inconsistency regarding tagging immediatelly as merged once you create a new branch. !6408
+ - Removes inconsistency regarding tagging immediately as merged once you create a new branch. !6408
- Update the rouge gem to 2.0.6, which adds highlighting support for JSX, Prometheus, and others. !6251
- Only check :can_resolve permission if the note is resolvable
- Bump fog-aws to v0.11.0 to support ap-south-1 region
@@ -1389,7 +1389,7 @@
- Fix notification_service argument error of declined invitation emails
- Fix a memory leak caused by Banzai::Filter::SanitizationFilter
- Speed up todos queries by limiting the projects set we join with
- - Ensure file editing in UI does not overwrite commited changes without warning user
+ - Ensure file editing in UI does not overwrite committed changes without warning user
- Eliminate unneeded calls to Repository#blob_at when listing commits with no path
- Update gitlab_git gem to 10.4.7
- Simplify SQL queries of marking a todo as done
@@ -2076,7 +2076,7 @@
- Don't show forks button when user can't view forks
- Fix atom feed links and rendering
- Files over 5MB can only be viewed in their raw form, files over 1MB without highlighting !3718
- - Add support for supressing text diffs using .gitattributes on the default branch (Matt Oakes)
+ - Add support for suppressing text diffs using .gitattributes on the default branch (Matt Oakes)
- Add eager load paths to help prevent dependency load issues in Sidekiq workers. !3724
- Added multiple colors for labels in dropdowns when dups happen.
- Show commits in the same order as `git log`
@@ -2194,7 +2194,7 @@
- All images in discussions and wikis now link to their source files !3464 (Connor Shea).
- Return status code 303 after a branch DELETE operation to avoid project deletion (Stan Hu)
- Add setting for customizing the list of trusted proxies !3524
- - Allow projects to be transfered to a lower visibility level group
+ - Allow projects to be transferred to a lower visibility level group
- Fix `signed_in_ip` being set to 127.0.0.1 when using a reverse proxy !3524
- Improved Markdown rendering performance !3389
- Make shared runners text in box configurable
@@ -2209,7 +2209,7 @@
- API: Ability to update a group (Robert Schilling)
- API: Ability to move issues (Robert Schilling)
- Fix Error 500 after renaming a project path (Stan Hu)
- - Fix a bug whith trailing slash in teamcity_url (Charles May)
+ - Fix a bug with trailing slash in teamcity_url (Charles May)
- Allow back dating on issues when created or updated through the API
- Allow back dating on issue notes when created through the API
- Propose license template when creating a new LICENSE file
@@ -2219,7 +2219,7 @@
- Allow SAML to handle external users based on user's information !3530
- Allow Omniauth providers to be marked as `external` !3657
- Add endpoints to archive or unarchive a project !3372
- - Fix a bug whith trailing slash in bamboo_url
+ - Fix a bug with trailing slash in bamboo_url
- Add links to CI setup documentation from project settings and builds pages
- Display project members page to all members
- Handle nil descriptions in Slack issue messages (Stan Hu)
@@ -2610,7 +2610,7 @@
- Fixed logo animation on Safari (Roman Rott)
- Fix Merge When Succeeded when multiple stages
- Hide remove source branch button when the MR is merged but new commits are pushed (Zeger-Jan van de Weg)
- - In seach autocomplete show only groups and projects you are member of
+ - In search autocomplete show only groups and projects you are member of
- Don't process cross-reference notes from forks
- Fix: init.d script not working on OS X
- Faster snippet search
@@ -2870,7 +2870,7 @@
- Bump Redis requirement to 2.8 for Sidekiq 4 (Stan Hu)
- Fix: Assignee selector is empty when 'Unassigned' is selected (Jose Corcuera)
- WIP identifier on merge requests no longer requires trailing space
- - Add rake tasks for git repository maintainance (Zeger-Jan van de Weg)
+ - Add rake tasks for git repository maintenance (Zeger-Jan van de Weg)
- Fix 500 error when update group member permission
- Fix: As an admin, cannot add oneself as a member to a group/project
- Trim leading and trailing whitespace of milestone and issueable titles (Jose Corcuera)
@@ -3199,7 +3199,7 @@
- Sort issues by creation date in Bitbucket importer (Stan Hu)
- Prevent too many redirects upon login when home page URL is set to external_url (Stan Hu)
- Improve dropdown positioning on the project home page (Hannes Rosenögger)
- - Upgrade browser gem to 1.0.0 to avoid warning in IE11 compatibilty mode (Stan Hu)
+ - Upgrade browser gem to 1.0.0 to avoid warning in IE11 compatibility mode (Stan Hu)
- Remove user OAuth tokens from the database and request new tokens each session (Stan Hu)
- Restrict users API endpoints to use integer IDs (Stan Hu)
- Only show recent push event if the branch still exists or a recent merge request has not been created (Stan Hu)
@@ -3209,7 +3209,7 @@
- Ability to fetch merge requests from refs/merge-requests/:id
- Allow displaying of archived projects in the admin interface (Artem Sidorenko)
- Allow configuration of import sources for new projects (Artem Sidorenko)
- - Search for comments should be case insensetive
+ - Search for comments should be case insensitive
- Create cross-reference for closing references on commits pushed to non-default branches (Maël Valais)
- Ability to search milestones
- Gracefully handle SMTP user input errors (e.g. incorrect email addresses) to prevent Sidekiq retries (Stan Hu)
@@ -3477,7 +3477,7 @@
- Update Asciidoctor gem to version 1.5.2. (Jakub Jirutka)
- Fix resolving of relative links to repository files in AsciiDoc documents. (Jakub Jirutka)
- Use the user list from the target project in a merge request (Stan Hu)
-- Default extention for wiki pages is now .md instead of .markdown (Jeroen van Baarsen)
+- Default extension for wiki pages is now .md instead of .markdown (Jeroen van Baarsen)
- Add validation to wiki page creation (only [a-zA-Z0-9/_-] are allowed) (Jeroen van Baarsen)
- Fix new/empty milestones showing 100% completion value (Jonah Bishop)
- Add a note when an Issue or Merge Request's title changes
@@ -3613,7 +3613,7 @@
- Set EmailsOnPush reply-to address to committer email when enabled.
- Fix broken file browsing with a submodule that contains a relative link (Stan Hu)
- Fix persistent XSS vulnerability around profile website URLs.
-- Fix project import URL regex to prevent arbitary local repos from being imported.
+- Fix project import URL regex to prevent arbitrary local repos from being imported.
- Fix directory traversal vulnerability around uploads routes.
- Fix directory traversal vulnerability around help pages.
- Don't leak existence of project via search autocomplete.
@@ -3676,7 +3676,7 @@
- Don't show commit comment button when user is not signed in.
- Fix admin user projects lists.
- Don't leak private group existence by redirecting from namespace controller to group controller.
-- Ability to skip some items from backup (database, respositories or uploads)
+- Ability to skip some items from backup (database, repositories or uploads)
- Archive repositories in background worker.
- Import GitHub, Bitbucket or GitLab.com projects owned by authenticated user into current namespace.
- Project labels are now available over the API under the "tag_list" field (Cristian Medina)
@@ -3701,7 +3701,7 @@
## 7.9.4
-- Security: Fix project import URL regex to prevent arbitary local repos from being imported
+- Security: Fix project import URL regex to prevent arbitrary local repos from being imported
- Fixed issue where only 25 commits would load in file listings
- Fix LDAP identities after config update
@@ -4199,7 +4199,7 @@
- Only masters can rewrite/remove git tags
- Add X-Frame-Options SAMEORIGIN to Nginx config so Sidekiq admin is visible
- UI improvements
-- Case-insensetive search for issues
+- Case-insensitive search for issues
- Update to rails 4.1
- Improve performance of application for projects and groups with a lot of members
- Formally support Ruby 2.1
@@ -4358,7 +4358,7 @@
- Group avatar
- Pygments.rb replaced with highlight.js
- Improve Merge request diff store logic
-- Improve render performnace for MR show page
+- Improve render performances for MR show page
- Fixed Assembla hardcoded project name
- Jira integration documentation
- Refactored app/services
diff --git a/changelogs/unreleased/10029-env-item.yml b/changelogs/unreleased/10029-env-item.yml
deleted file mode 100644
index f4e742d3e17..00000000000
--- a/changelogs/unreleased/10029-env-item.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Removes EE differences for environment_item.vue
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/10081-env-table.yml b/changelogs/unreleased/10081-env-table.yml
deleted file mode 100644
index b27a1be8cca..00000000000
--- a/changelogs/unreleased/10081-env-table.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Removes EE differences for environments_table.vue
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/10088-move-code-differences-EE-to-CE.yml b/changelogs/unreleased/10088-move-code-differences-EE-to-CE.yml
new file mode 100644
index 00000000000..1297e9712fa
--- /dev/null
+++ b/changelogs/unreleased/10088-move-code-differences-EE-to-CE.yml
@@ -0,0 +1,5 @@
+---
+title: "Added code differnces from EE in file 'app/assets/javascripts/pages/projects/project.js' to CE"
+merge_request: 29271
+author: Michel Engelen
+type: other
diff --git a/changelogs/unreleased/10735-geo-gitlab-revision-can-return-not-consistent-results.yml b/changelogs/unreleased/10735-geo-gitlab-revision-can-return-not-consistent-results.yml
deleted file mode 100644
index 2360295b022..00000000000
--- a/changelogs/unreleased/10735-geo-gitlab-revision-can-return-not-consistent-results.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use a fixed git abbrev parameter when we fetch a git revision
-merge_request: 26707
-author:
-type: fixed
diff --git a/changelogs/unreleased/10795-add-epic-tree-BE-CE-epic-graphql-support.yml b/changelogs/unreleased/10795-add-epic-tree-BE-CE-epic-graphql-support.yml
new file mode 100644
index 00000000000..4c85d4f9acb
--- /dev/null
+++ b/changelogs/unreleased/10795-add-epic-tree-BE-CE-epic-graphql-support.yml
@@ -0,0 +1,5 @@
+---
+title: Added reference, web_path, and relative_position fields to GraphQL Issue
+merge_request: 28998
+author:
+type: changed
diff --git a/changelogs/unreleased/10798-remove-dind-req-for-dast.yml b/changelogs/unreleased/10798-remove-dind-req-for-dast.yml
new file mode 100644
index 00000000000..33545fc7cfd
--- /dev/null
+++ b/changelogs/unreleased/10798-remove-dind-req-for-dast.yml
@@ -0,0 +1,5 @@
+---
+title: Remove dind from DAST template
+merge_request: 28083
+author:
+type: changed
diff --git a/changelogs/unreleased/10842-add-missing-environments-variable-to-the-sast-analyzer-docker-container.yml b/changelogs/unreleased/10842-add-missing-environments-variable-to-the-sast-analyzer-docker-container.yml
new file mode 100644
index 00000000000..112b472aa3b
--- /dev/null
+++ b/changelogs/unreleased/10842-add-missing-environments-variable-to-the-sast-analyzer-docker-container.yml
@@ -0,0 +1,5 @@
+---
+title: 'Fix: propagate all documented ENV vars to CI when using SAST'
+merge_request: 29564
+author:
+type: fixed
diff --git a/changelogs/unreleased/10921-display-scoped-labels-ce.yml b/changelogs/unreleased/10921-display-scoped-labels-ce.yml
deleted file mode 100644
index 7a0e7fec41b..00000000000
--- a/changelogs/unreleased/10921-display-scoped-labels-ce.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Display scoped labels in Issue Boards
-merge_request: 27164
-author:
-type: fixed
diff --git a/changelogs/unreleased/11105-fix-cs-with-proxy.yml b/changelogs/unreleased/11105-fix-cs-with-proxy.yml
new file mode 100644
index 00000000000..ee32427d20e
--- /dev/null
+++ b/changelogs/unreleased/11105-fix-cs-with-proxy.yml
@@ -0,0 +1,5 @@
+---
+title: Fix proxy support in Container Scanning
+merge_request: 27246
+author:
+type: fixed
diff --git a/changelogs/unreleased/11124-update-deployment-service-fails-if-project-is-nil.yml b/changelogs/unreleased/11124-update-deployment-service-fails-if-project-is-nil.yml
deleted file mode 100644
index 355743f4cb0..00000000000
--- a/changelogs/unreleased/11124-update-deployment-service-fails-if-project-is-nil.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Always return the deployment in the UpdateDeploymentService#execute method
-merge_request: 27322
-author:
-type: fixed
diff --git a/changelogs/unreleased/11204-turn-off-mask-by-default.yml b/changelogs/unreleased/11204-turn-off-mask-by-default.yml
new file mode 100644
index 00000000000..5c554e04d45
--- /dev/null
+++ b/changelogs/unreleased/11204-turn-off-mask-by-default.yml
@@ -0,0 +1,5 @@
+---
+title: Default masked to false for new variables
+merge_request: 28186
+author:
+type: changed
diff --git a/changelogs/unreleased/11609-geo-remove-support-for-using-geo-with-an-installation-from-source-docs.yml b/changelogs/unreleased/11609-geo-remove-support-for-using-geo-with-an-installation-from-source-docs.yml
new file mode 100644
index 00000000000..6570cb3e2a3
--- /dev/null
+++ b/changelogs/unreleased/11609-geo-remove-support-for-using-geo-with-an-installation-from-source-docs.yml
@@ -0,0 +1,5 @@
+---
+title: Remove support for using Geo with an installation from source
+merge_request: 28737
+author:
+type: other
diff --git a/changelogs/unreleased/12106-sp-ce.yml b/changelogs/unreleased/12106-sp-ce.yml
new file mode 100644
index 00000000000..2d073401b45
--- /dev/null
+++ b/changelogs/unreleased/12106-sp-ce.yml
@@ -0,0 +1,5 @@
+---
+title: Moves snowplow to CE repo
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/1340-request-job-with-age.yml b/changelogs/unreleased/1340-request-job-with-age.yml
new file mode 100644
index 00000000000..766ac008c2e
--- /dev/null
+++ b/changelogs/unreleased/1340-request-job-with-age.yml
@@ -0,0 +1,5 @@
+---
+title: "Added option to filter jobs by age in the /job/request API endpoint."
+merge_request: 1340
+author: Dmitry Chepurovskiy
+type: added
diff --git a/changelogs/unreleased/13453_minimal_atom_fix.yml b/changelogs/unreleased/13453_minimal_atom_fix.yml
new file mode 100644
index 00000000000..e0c18de3b1f
--- /dev/null
+++ b/changelogs/unreleased/13453_minimal_atom_fix.yml
@@ -0,0 +1,5 @@
+---
+title: Added a content field to atom feed
+merge_request: 27652
+author:
+type: fixed
diff --git a/changelogs/unreleased/13784-validate-variables-for-masking.yml b/changelogs/unreleased/13784-validate-variables-for-masking.yml
deleted file mode 100644
index e8e97fac3d2..00000000000
--- a/changelogs/unreleased/13784-validate-variables-for-masking.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add control for masking variable values in runner logs
-merge_request: 26751
-author:
-type: added
diff --git a/changelogs/unreleased/19569-include-information-if-issue-was-closed-via-mr.yml b/changelogs/unreleased/19569-include-information-if-issue-was-closed-via-mr.yml
new file mode 100644
index 00000000000..bb2fc9af2a1
--- /dev/null
+++ b/changelogs/unreleased/19569-include-information-if-issue-was-closed-via-mr.yml
@@ -0,0 +1,5 @@
+---
+title: Include information if issue was clossed via merge request or commit
+merge_request: 15610
+author: Michał Zając
+type: changed
diff --git a/changelogs/unreleased/237-style-toast-component.yml b/changelogs/unreleased/237-style-toast-component.yml
new file mode 100644
index 00000000000..2420df0ee55
--- /dev/null
+++ b/changelogs/unreleased/237-style-toast-component.yml
@@ -0,0 +1,5 @@
+---
+title: Style the toast component according to design specs.
+merge_request: 27734
+author:
+type: added
diff --git a/changelogs/unreleased/24936-remove-type-from-review-app-name.yml b/changelogs/unreleased/24936-remove-type-from-review-app-name.yml
deleted file mode 100644
index 639333264f6..00000000000
--- a/changelogs/unreleased/24936-remove-type-from-review-app-name.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove unnecessary folder prefix from environment name
-merge_request: 25600
-author:
-type: changed
diff --git a/changelogs/unreleased/24971-align-emailvalidator-to-validate_email-gem-implementation.yml b/changelogs/unreleased/24971-align-emailvalidator-to-validate_email-gem-implementation.yml
deleted file mode 100644
index 04dbc3a1d5a..00000000000
--- a/changelogs/unreleased/24971-align-emailvalidator-to-validate_email-gem-implementation.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Align EmailValidator to validate_email gem implementation
-merge_request: 24971
-author: Horatiu Eugen Vlad
-type: fixed
diff --git a/changelogs/unreleased/24985-align-urlvalidator-to-validate_url-gem-implementation.yml b/changelogs/unreleased/24985-align-urlvalidator-to-validate_url-gem-implementation.yml
deleted file mode 100644
index 1143e4effea..00000000000
--- a/changelogs/unreleased/24985-align-urlvalidator-to-validate_url-gem-implementation.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Align UrlValidator to validate_url gem implementation"
-merge_request: 27194
-author: Horatiu Eugen Vlad
-type: fixed
diff --git a/changelogs/unreleased/25942-remove-fake-repository-path-response.yml b/changelogs/unreleased/25942-remove-fake-repository-path-response.yml
deleted file mode 100644
index e1da28ab03c..00000000000
--- a/changelogs/unreleased/25942-remove-fake-repository-path-response.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove fake repository_path response
-merge_request: 25942
-author: Fabio Papa
-type: other
diff --git a/changelogs/unreleased/26021-added-write_repository-scope-for-personal-access-token.yml b/changelogs/unreleased/26021-added-write_repository-scope-for-personal-access-token.yml
deleted file mode 100644
index da550d35f12..00000000000
--- a/changelogs/unreleased/26021-added-write_repository-scope-for-personal-access-token.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Added write_repository scope for personal access token
-merge_request: 26021
-author: Horatiu Eugen Vlad
-type: added
diff --git a/changelogs/unreleased/27987-use-findorcreateservice-to-create-labels.yml b/changelogs/unreleased/27987-use-findorcreateservice-to-create-labels.yml
new file mode 100644
index 00000000000..8d3501e0171
--- /dev/null
+++ b/changelogs/unreleased/27987-use-findorcreateservice-to-create-labels.yml
@@ -0,0 +1,5 @@
+---
+title: Use FindOrCreateService to create labels and check for existing ones
+merge_request: 27987
+author: Matt Duren
+type: fixed
diff --git a/changelogs/unreleased/28757-remove-docker-pull-prefix-when-copying-a-tag-from-the-registry.yml b/changelogs/unreleased/28757-remove-docker-pull-prefix-when-copying-a-tag-from-the-registry.yml
new file mode 100644
index 00000000000..e954b97f05b
--- /dev/null
+++ b/changelogs/unreleased/28757-remove-docker-pull-prefix-when-copying-a-tag-from-the-registry.yml
@@ -0,0 +1,5 @@
+---
+title: Remove `docker pull` prefix when copying a tag from the registry
+merge_request: 28757
+author: Benedikt Franke
+type: changed
diff --git a/changelogs/unreleased/28996-create-mvc-ui-in-haml.yml b/changelogs/unreleased/28996-create-mvc-ui-in-haml.yml
new file mode 100644
index 00000000000..9c6897babb4
--- /dev/null
+++ b/changelogs/unreleased/28996-create-mvc-ui-in-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Add auto SSL toggle option to Pages domain settings page
+merge_request: 26438
+author:
+type: added
diff --git a/changelogs/unreleased/29249-show-download-diff-even-when-merge-request-is-closed.yml b/changelogs/unreleased/29249-show-download-diff-even-when-merge-request-is-closed.yml
deleted file mode 100644
index 5942860a20f..00000000000
--- a/changelogs/unreleased/29249-show-download-diff-even-when-merge-request-is-closed.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Show download diff links for closed MRs
-merge_request: 26772
-author:
-type: changed
diff --git a/changelogs/unreleased/30138-display-cycle-analytics-issue.yml b/changelogs/unreleased/30138-display-cycle-analytics-issue.yml
new file mode 100644
index 00000000000..c7faa0480bd
--- /dev/null
+++ b/changelogs/unreleased/30138-display-cycle-analytics-issue.yml
@@ -0,0 +1,5 @@
+---
+title: Show data on Cycle Analytics page when value is less than a second
+merge_request: 28507
+author:
+type: fixed
diff --git a/changelogs/unreleased/30157-api-expose-single-environment.yml b/changelogs/unreleased/30157-api-expose-single-environment.yml
deleted file mode 100644
index f9619dbcc7d..00000000000
--- a/changelogs/unreleased/30157-api-expose-single-environment.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Add new API endpoint to expose a single environment.'
-merge_request: 26887
-author:
-type: added
diff --git a/changelogs/unreleased/31331-add-time-tracking-issue-boards-sidebar.yml b/changelogs/unreleased/31331-add-time-tracking-issue-boards-sidebar.yml
deleted file mode 100644
index b3ffb77ccad..00000000000
--- a/changelogs/unreleased/31331-add-time-tracking-issue-boards-sidebar.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add time tracking information to Issue Boards sidebar
-merge_request: 27166
-author:
-type: added
diff --git a/changelogs/unreleased/33064-add-labels-to-note-event-payload.yml b/changelogs/unreleased/33064-add-labels-to-note-event-payload.yml
new file mode 100644
index 00000000000..e0a6253e1ef
--- /dev/null
+++ b/changelogs/unreleased/33064-add-labels-to-note-event-payload.yml
@@ -0,0 +1,5 @@
+---
+title: Add labels to note event payload
+merge_request: 29384
+author: Sujay Patel
+type: added
diff --git a/changelogs/unreleased/37495.yml b/changelogs/unreleased/37495.yml
new file mode 100644
index 00000000000..f6d421fc45b
--- /dev/null
+++ b/changelogs/unreleased/37495.yml
@@ -0,0 +1,5 @@
+---
+title: Add documentation links for confidental and locked discussions
+merge_request: 29073
+author:
+type: changed
diff --git a/changelogs/unreleased/38561-border-radii.yml b/changelogs/unreleased/38561-border-radii.yml
new file mode 100644
index 00000000000..510af18d651
--- /dev/null
+++ b/changelogs/unreleased/38561-border-radii.yml
@@ -0,0 +1,5 @@
+---
+title: Fix border radii on diff files and repo files
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/38564-cant-leave-subgroup.yml b/changelogs/unreleased/38564-cant-leave-subgroup.yml
deleted file mode 100644
index a6397062343..00000000000
--- a/changelogs/unreleased/38564-cant-leave-subgroup.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow removing last owner from subgroup if parent group has owners
-merge_request: 26718
-author:
-type: changed
diff --git a/changelogs/unreleased/39304-broadcast-message-buttons.yml b/changelogs/unreleased/39304-broadcast-message-buttons.yml
new file mode 100644
index 00000000000..7eb289fca1f
--- /dev/null
+++ b/changelogs/unreleased/39304-broadcast-message-buttons.yml
@@ -0,0 +1,5 @@
+---
+title: Update broadcast message action icons
+merge_request: 28496
+author: Jarek Ostrowski @jareko
+type: fixed
diff --git a/changelogs/unreleased/43263-git-push-option-to-create-mr.yml b/changelogs/unreleased/43263-git-push-option-to-create-mr.yml
deleted file mode 100644
index d50c33da162..00000000000
--- a/changelogs/unreleased/43263-git-push-option-to-create-mr.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow merge requests to be created via git push options
-merge_request: 26752
-author:
-type: added
diff --git a/changelogs/unreleased/43297-authorized-application-count.yml b/changelogs/unreleased/43297-authorized-application-count.yml
deleted file mode 100644
index d22e155fb14..00000000000
--- a/changelogs/unreleased/43297-authorized-application-count.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix authorized application count
-merge_request: 25715
-author: moyuru
-type: fixed
diff --git a/changelogs/unreleased/45687-web-ide-empty-state.yml b/changelogs/unreleased/45687-web-ide-empty-state.yml
new file mode 100644
index 00000000000..9ef148275ab
--- /dev/null
+++ b/changelogs/unreleased/45687-web-ide-empty-state.yml
@@ -0,0 +1,5 @@
+---
+title: Empty project state for Web IDE
+merge_request: 26556
+author:
+type: added
diff --git a/changelogs/unreleased/46787-create-project-label-window-is-cut-off-at-the-bottom.yml b/changelogs/unreleased/46787-create-project-label-window-is-cut-off-at-the-bottom.yml
deleted file mode 100644
index dca1d57d14e..00000000000
--- a/changelogs/unreleased/46787-create-project-label-window-is-cut-off-at-the-bottom.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed - Create project label window is cut off at the bottom
-merge_request: 26049
-author:
-type: fixed
diff --git a/changelogs/unreleased/47234-composable-auto-devops.yml b/changelogs/unreleased/47234-composable-auto-devops.yml
deleted file mode 100644
index 9403c5ae6d3..00000000000
--- a/changelogs/unreleased/47234-composable-auto-devops.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Split Auto-DevOps.gitlab-ci.yml into reusable templates
-merge_request: 26520
-author:
-type: changed
diff --git a/changelogs/unreleased/47327-fix-github-import-visibility.yml b/changelogs/unreleased/47327-fix-github-import-visibility.yml
deleted file mode 100644
index b02318f0e89..00000000000
--- a/changelogs/unreleased/47327-fix-github-import-visibility.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix GitHub project import visibility
-merge_request: 27133
-author: Daniel Wyatt
-type: fixed
diff --git a/changelogs/unreleased/47771-highlighting-in-diff.yml b/changelogs/unreleased/47771-highlighting-in-diff.yml
deleted file mode 100644
index a8e8cbf0174..00000000000
--- a/changelogs/unreleased/47771-highlighting-in-diff.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enabled text selection highlighting in diffs in Web IDE
-merge_request: 26721
-author: Isaac Smith
-type: fixed
diff --git a/changelogs/unreleased/47846-position-is-off-when-visiting-files-with-anchors.yml b/changelogs/unreleased/47846-position-is-off-when-visiting-files-with-anchors.yml
new file mode 100644
index 00000000000..21dc170f1ca
--- /dev/null
+++ b/changelogs/unreleased/47846-position-is-off-when-visiting-files-with-anchors.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve Position is off when visiting files with anchors
+merge_request: 28913
+author:
+type: fixed
diff --git a/changelogs/unreleased/48090-filter-sensitive-metric-labels.yml b/changelogs/unreleased/48090-filter-sensitive-metric-labels.yml
deleted file mode 100644
index e588fa79619..00000000000
--- a/changelogs/unreleased/48090-filter-sensitive-metric-labels.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove `path` and `branch` labels from metrics
-merge_request: 26744
-author:
-type: fixed
diff --git a/changelogs/unreleased/48132-display-output-from-pre-receive-scripts.yml b/changelogs/unreleased/48132-display-output-from-pre-receive-scripts.yml
deleted file mode 100644
index e06a4d5ee75..00000000000
--- a/changelogs/unreleased/48132-display-output-from-pre-receive-scripts.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Allow failed custom hook script errors to safely appear in GitLab UI by filtering error messages by the prefix GL-HOOK-ERR:"
-merge_request: 25625
-author:
-type: changed
diff --git a/changelogs/unreleased/48297-fix-code-selection.yml b/changelogs/unreleased/48297-fix-code-selection.yml
deleted file mode 100644
index 14841b00969..00000000000
--- a/changelogs/unreleased/48297-fix-code-selection.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Resolve Code in other column of side-by-side diff is highlighted when selecting
- code on one side
-merge_request: 26423
-author:
-type: fixed
diff --git a/changelogs/unreleased/49041-issue-board-input-height.yml b/changelogs/unreleased/49041-issue-board-input-height.yml
new file mode 100644
index 00000000000..de3fbb2ee11
--- /dev/null
+++ b/changelogs/unreleased/49041-issue-board-input-height.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce height of issue board input to align with buttons
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/49517-fix-notes-import-export.yml b/changelogs/unreleased/49517-fix-notes-import-export.yml
new file mode 100644
index 00000000000..a9f4d736e0b
--- /dev/null
+++ b/changelogs/unreleased/49517-fix-notes-import-export.yml
@@ -0,0 +1,5 @@
+---
+title: Fix diff notes and discussion notes being exported as regular notes
+merge_request: 28401
+author:
+type: fixed
diff --git a/changelogs/unreleased/49856-upgrade-bootstrap-form-gem.yml b/changelogs/unreleased/49856-upgrade-bootstrap-form-gem.yml
deleted file mode 100644
index 1dc8d5b4179..00000000000
--- a/changelogs/unreleased/49856-upgrade-bootstrap-form-gem.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Upgrade bootstrap_form Gem
-merge_request: 26568
-author:
-type: other
diff --git a/changelogs/unreleased/49863-ingress-ip-loading-state.yml b/changelogs/unreleased/49863-ingress-ip-loading-state.yml
deleted file mode 100644
index 51bb27d3153..00000000000
--- a/changelogs/unreleased/49863-ingress-ip-loading-state.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Show loading spinner while Ingress/Knative IP is being assigned
-merge_request: 25912
-author:
-type: changed
diff --git a/changelogs/unreleased/49910-reopening-a-closed-milestone-from-the-closed-milestones-page-fails2.yml b/changelogs/unreleased/49910-reopening-a-closed-milestone-from-the-closed-milestones-page-fails2.yml
deleted file mode 100644
index 68d38cd56c5..00000000000
--- a/changelogs/unreleased/49910-reopening-a-closed-milestone-from-the-closed-milestones-page-fails2.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix bug when reopening milestone from index page
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/49915-fix-error-500-admin-projects-nil-storage.yml b/changelogs/unreleased/49915-fix-error-500-admin-projects-nil-storage.yml
new file mode 100644
index 00000000000..307c2bfb49d
--- /dev/null
+++ b/changelogs/unreleased/49915-fix-error-500-admin-projects-nil-storage.yml
@@ -0,0 +1,5 @@
+---
+title: Fix an error in projects admin when statistics are missing
+merge_request: 28355
+author:
+type: fixed
diff --git a/changelogs/unreleased/50106-hide-whitespace-changes.yml b/changelogs/unreleased/50106-hide-whitespace-changes.yml
new file mode 100644
index 00000000000..e95953c8665
--- /dev/null
+++ b/changelogs/unreleased/50106-hide-whitespace-changes.yml
@@ -0,0 +1,5 @@
+---
+title: Fix whitespace changes visibility when the related file was initially collapsed
+merge_request: 28950
+author: Ondřej Budai
+type: fixed
diff --git a/changelogs/unreleased/50850-kerrizor-extend-api-to-accept-start_project-option.yml b/changelogs/unreleased/50850-kerrizor-extend-api-to-accept-start_project-option.yml
new file mode 100644
index 00000000000..45770e1012c
--- /dev/null
+++ b/changelogs/unreleased/50850-kerrizor-extend-api-to-accept-start_project-option.yml
@@ -0,0 +1,5 @@
+---
+title: Add API support for committing changes to different projects in same fork network
+merge_request: 27915
+author:
+type: added
diff --git a/changelogs/unreleased/51022-added-extended-height-to-labels-dropdown.yml b/changelogs/unreleased/51022-added-extended-height-to-labels-dropdown.yml
new file mode 100644
index 00000000000..07bf8b04bbe
--- /dev/null
+++ b/changelogs/unreleased/51022-added-extended-height-to-labels-dropdown.yml
@@ -0,0 +1,5 @@
+---
+title: "Added the `.extended-height` class to the labels-dropdown"
+merge_request: 28659
+author: Michel Engelen
+type: other
diff --git a/changelogs/unreleased/51636-task-list-api-pderichs.yml b/changelogs/unreleased/51636-task-list-api-pderichs.yml
new file mode 100644
index 00000000000..f18a0936ab2
--- /dev/null
+++ b/changelogs/unreleased/51636-task-list-api-pderichs.yml
@@ -0,0 +1,5 @@
+---
+title: Add task count and completed count to responses of Issue and MR
+merge_request: 28859
+author:
+type: added
diff --git a/changelogs/unreleased/51854-api-to-get-all-project-group-members-returns-duplicates.yml b/changelogs/unreleased/51854-api-to-get-all-project-group-members-returns-duplicates.yml
new file mode 100644
index 00000000000..4e16b95ec11
--- /dev/null
+++ b/changelogs/unreleased/51854-api-to-get-all-project-group-members-returns-duplicates.yml
@@ -0,0 +1,5 @@
+---
+title: Removes duplicated members from api/projects/:id/members/all
+merge_request: 24005
+author: Jacopo Beschi @jacopo-beschi
+type: changed
diff --git a/changelogs/unreleased/51988-install-group-runner-on-group-cluster.yml b/changelogs/unreleased/51988-install-group-runner-on-group-cluster.yml
deleted file mode 100644
index 86f08dd1798..00000000000
--- a/changelogs/unreleased/51988-install-group-runner-on-group-cluster.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Support installing Group runner on group-level cluster
-merge_request: 26260
-author:
-type: added
diff --git a/changelogs/unreleased/52258-labels-with-long-names-overflow-on-metrics-dashboard.yml b/changelogs/unreleased/52258-labels-with-long-names-overflow-on-metrics-dashboard.yml
deleted file mode 100644
index 5dd25d0ffc1..00000000000
--- a/changelogs/unreleased/52258-labels-with-long-names-overflow-on-metrics-dashboard.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix long label overflow on metrics dashboard
-merge_request: 26775
-author:
-type: fixed
diff --git a/changelogs/unreleased/52366-improved-group-lists-ui-spinners.yml b/changelogs/unreleased/52366-improved-group-lists-ui-spinners.yml
deleted file mode 100644
index ab09272eaf4..00000000000
--- a/changelogs/unreleased/52366-improved-group-lists-ui-spinners.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update spinners in group list component
-merge_request: 26572
-author:
-type: changed
diff --git a/changelogs/unreleased/52447-auto-devops-at-group-level.yml b/changelogs/unreleased/52447-auto-devops-at-group-level.yml
deleted file mode 100644
index 0a21c6a2b7b..00000000000
--- a/changelogs/unreleased/52447-auto-devops-at-group-level.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable/disable Auto DevOps at the Group level
-merge_request: 25533
-author:
-type: added
diff --git a/changelogs/unreleased/52560-fix-duplicate-tag-system-hooks.yml b/changelogs/unreleased/52560-fix-duplicate-tag-system-hooks.yml
deleted file mode 100644
index b8d58d6bd30..00000000000
--- a/changelogs/unreleased/52560-fix-duplicate-tag-system-hooks.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Only execute system hooks once when pushing tags
-merge_request: 26888
-author:
-type: fixed
diff --git a/changelogs/unreleased/53134-multiple-extendes-for-a-job.yml b/changelogs/unreleased/53134-multiple-extendes-for-a-job.yml
new file mode 100644
index 00000000000..e09de8ac8fc
--- /dev/null
+++ b/changelogs/unreleased/53134-multiple-extendes-for-a-job.yml
@@ -0,0 +1,5 @@
+---
+title: Add support for multiple job parents in GitLab CI YAML.
+merge_request: 26801
+author: Wolphin (Nikita)
+type: added
diff --git a/changelogs/unreleased/53138-add-metrics-usage-ping.yml b/changelogs/unreleased/53138-add-metrics-usage-ping.yml
deleted file mode 100644
index db6af77a647..00000000000
--- a/changelogs/unreleased/53138-add-metrics-usage-ping.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adds if InfluxDB and Prometheus metrics are enabled to usage ping data
-merge_request: 27238
-author:
-type: added
diff --git a/changelogs/unreleased/53139-hide-tree-single-file.yml b/changelogs/unreleased/53139-hide-tree-single-file.yml
deleted file mode 100644
index 17fe957e42e..00000000000
--- a/changelogs/unreleased/53139-hide-tree-single-file.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: collapse file tree by default if the merge request changes only one file
-merge_request:
-author: Riccardo Padovani <riccardo@rpadovani.com>
-type: changed
diff --git a/changelogs/unreleased/53198-git-push-option-merge-when-pipeline-succeeds.yml b/changelogs/unreleased/53198-git-push-option-merge-when-pipeline-succeeds.yml
deleted file mode 100644
index 6fefd05049c..00000000000
--- a/changelogs/unreleased/53198-git-push-option-merge-when-pipeline-succeeds.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Allow merge requests to be set to merge when pipeline succeeds via git push
- options
-merge_request: 26842
-author:
-type: added
diff --git a/changelogs/unreleased/53210-add-uniq-constraints-on-issues-and-mrs-labels.yml b/changelogs/unreleased/53210-add-uniq-constraints-on-issues-and-mrs-labels.yml
deleted file mode 100644
index f9cd8716b92..00000000000
--- a/changelogs/unreleased/53210-add-uniq-constraints-on-issues-and-mrs-labels.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: add a uniq constraints on issues and mrs labels
-merge_request: 25435
-author: Antoine Huret
-type: fixed
diff --git a/changelogs/unreleased/53279-fix-updated_at-api.yml b/changelogs/unreleased/53279-fix-updated_at-api.yml
deleted file mode 100644
index c64dada7eaa..00000000000
--- a/changelogs/unreleased/53279-fix-updated_at-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Respect updated_at attribute in notes produced by API calls"
-merge_request: 27124
-author: Ben Gamari
-type: fixed
diff --git a/changelogs/unreleased/53459-quick-action-adds-multiple-labels-to-issue-if-middle-words-overlap-with-existing-label.yml b/changelogs/unreleased/53459-quick-action-adds-multiple-labels-to-issue-if-middle-words-overlap-with-existing-label.yml
deleted file mode 100644
index 30d8c0e95d7..00000000000
--- a/changelogs/unreleased/53459-quick-action-adds-multiple-labels-to-issue-if-middle-words-overlap-with-existing-label.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix quick actions add label name middle word overlaps
-merge_request: 26602
-author: Jacopo Beschi @jacopo-beschi
-type: fixed
diff --git a/changelogs/unreleased/54140-non-ar-cache-commit-markdown.yml b/changelogs/unreleased/54140-non-ar-cache-commit-markdown.yml
new file mode 100644
index 00000000000..efda07380a4
--- /dev/null
+++ b/changelogs/unreleased/54140-non-ar-cache-commit-markdown.yml
@@ -0,0 +1,5 @@
+---
+title: Use Redis for CacheMarkDownField on non AR models
+merge_request: 29054
+author:
+type: performance
diff --git a/changelogs/unreleased/54169-flash-warning-rebrush.yml b/changelogs/unreleased/54169-flash-warning-rebrush.yml
new file mode 100644
index 00000000000..420cc26a8cc
--- /dev/null
+++ b/changelogs/unreleased/54169-flash-warning-rebrush.yml
@@ -0,0 +1,5 @@
+---
+title: "Rebrush of flash-warning according to the new design (brighter background and darker font)"
+merge_request: 28916
+author: Michel Engelen
+type: changed
diff --git a/changelogs/unreleased/54417-graphql-type-authorization.yml b/changelogs/unreleased/54417-graphql-type-authorization.yml
deleted file mode 100644
index 528b58a858a..00000000000
--- a/changelogs/unreleased/54417-graphql-type-authorization.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: GraphQL Types can be made to always authorize access to resources of that Type
-merge_request: 25724
-author:
-type: added
diff --git a/changelogs/unreleased/54506-show-error-when-namespace-svc-missing.yml b/changelogs/unreleased/54506-show-error-when-namespace-svc-missing.yml
deleted file mode 100644
index 3e3784d5413..00000000000
--- a/changelogs/unreleased/54506-show-error-when-namespace-svc-missing.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Show error when namespace/svc account missing
-merge_request: 26362
-author:
-type: added
diff --git a/changelogs/unreleased/54670-external-diffs-when-outdated.yml b/changelogs/unreleased/54670-external-diffs-when-outdated.yml
deleted file mode 100644
index 2a0b9e75cb4..00000000000
--- a/changelogs/unreleased/54670-external-diffs-when-outdated.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Allow external diffs to be used conditionally'
-merge_request: 25432
-author:
-type: added
diff --git a/changelogs/unreleased/54916-extended-tooltip-for-merge-request-links.yml b/changelogs/unreleased/54916-extended-tooltip-for-merge-request-links.yml
deleted file mode 100644
index 7fd0bcd1c00..00000000000
--- a/changelogs/unreleased/54916-extended-tooltip-for-merge-request-links.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add extended merge request tooltip
-merge_request: !25221
-author:
-type: added
diff --git a/changelogs/unreleased/55033-discussion-system-note-alignment.yml b/changelogs/unreleased/55033-discussion-system-note-alignment.yml
new file mode 100644
index 00000000000..27072ec7e12
--- /dev/null
+++ b/changelogs/unreleased/55033-discussion-system-note-alignment.yml
@@ -0,0 +1,5 @@
+---
+title: Align system note within discussion with other notes
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/55125-mr-tab-scrolling.yml b/changelogs/unreleased/55125-mr-tab-scrolling.yml
new file mode 100644
index 00000000000..e03ff6c5060
--- /dev/null
+++ b/changelogs/unreleased/55125-mr-tab-scrolling.yml
@@ -0,0 +1,5 @@
+---
+title: Update merge request tabs so they no longer scroll
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/55253-activity-feed-ui-enhance-line-height.yml b/changelogs/unreleased/55253-activity-feed-ui-enhance-line-height.yml
new file mode 100644
index 00000000000..f7dd8c59a7c
--- /dev/null
+++ b/changelogs/unreleased/55253-activity-feed-ui-enhance-line-height.yml
@@ -0,0 +1,5 @@
+---
+title: Enhance line-height of Activity feed UI
+merge_request: 28856
+author: Jacopo Beschi @jacopo-beschi
+type: changed
diff --git a/changelogs/unreleased/55268-exclude-system-notes-from-commits-in-mr.yml b/changelogs/unreleased/55268-exclude-system-notes-from-commits-in-mr.yml
deleted file mode 100644
index 7af4739136b..00000000000
--- a/changelogs/unreleased/55268-exclude-system-notes-from-commits-in-mr.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Exclude system notes from commits in merge request discussions
-merge_request: 26396
-author:
-type: fixed
diff --git a/changelogs/unreleased/55447-validate-k8s-credentials.yml b/changelogs/unreleased/55447-validate-k8s-credentials.yml
new file mode 100644
index 00000000000..81f0efdb325
--- /dev/null
+++ b/changelogs/unreleased/55447-validate-k8s-credentials.yml
@@ -0,0 +1,5 @@
+---
+title: Validate Kubernetes credentials at cluster creation
+merge_request: 27403
+author:
+type: added
diff --git a/changelogs/unreleased/55964-fix-email-encoding.yml b/changelogs/unreleased/55964-fix-email-encoding.yml
deleted file mode 100644
index 2195a853702..00000000000
--- a/changelogs/unreleased/55964-fix-email-encoding.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix notfication emails having wrong encoding
-merge_request: 26931
-author:
-type: fixed
diff --git a/changelogs/unreleased/55980-remove-add-issue-on-blank-list.yml b/changelogs/unreleased/55980-remove-add-issue-on-blank-list.yml
deleted file mode 100644
index 4c16b635297..00000000000
--- a/changelogs/unreleased/55980-remove-add-issue-on-blank-list.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove non-functional add issue button on welcome list
-merge_request: !26742
-author:
-type: fixed
diff --git a/changelogs/unreleased/56015-remove-remote-timeout.yml b/changelogs/unreleased/56015-remove-remote-timeout.yml
deleted file mode 100644
index 9b40ada5291..00000000000
--- a/changelogs/unreleased/56015-remove-remote-timeout.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix removing remote mirror failure which leaves unnecessary refs behind
-merge_request: 26213
-author:
-type: fixed
diff --git a/changelogs/unreleased/56089-merge-gitlab-keys.yml b/changelogs/unreleased/56089-merge-gitlab-keys.yml
deleted file mode 100644
index 5e2cafd3254..00000000000
--- a/changelogs/unreleased/56089-merge-gitlab-keys.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Merge the gitlab-shell "gitlab-keys" functionality into GitLab CE
-merge_request: 25598
-author:
-type: other
diff --git a/changelogs/unreleased/5615-non-admins-only-archieve-ce.yml b/changelogs/unreleased/5615-non-admins-only-archieve-ce.yml
new file mode 100644
index 00000000000..ac1aa249b82
--- /dev/null
+++ b/changelogs/unreleased/5615-non-admins-only-archieve-ce.yml
@@ -0,0 +1,5 @@
+---
+title: Add deletion protection setting column to application_settings table
+merge_request: 29268
+author:
+type: other
diff --git a/changelogs/unreleased/56762-fix-commit-swipe-view-26968.yml b/changelogs/unreleased/56762-fix-commit-swipe-view-26968.yml
deleted file mode 100644
index 18bd51711d9..00000000000
--- a/changelogs/unreleased/56762-fix-commit-swipe-view-26968.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Fix image diff swipe view on commit and compare pages"
-merge_request: 26968
-author: ftab
-type: fixed \ No newline at end of file
diff --git a/changelogs/unreleased/56833-project-improve-empty-repository-state-ui-fe.yml b/changelogs/unreleased/56833-project-improve-empty-repository-state-ui-fe.yml
deleted file mode 100644
index 19cf3d69db1..00000000000
--- a/changelogs/unreleased/56833-project-improve-empty-repository-state-ui-fe.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Project: Improve empty repository state UI'
-merge_request: 26024
-author:
-type: other
diff --git a/changelogs/unreleased/56864-reopen-locked-mr.yml b/changelogs/unreleased/56864-reopen-locked-mr.yml
deleted file mode 100644
index d1d71531ac8..00000000000
--- a/changelogs/unreleased/56864-reopen-locked-mr.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Disallow reopening of a locked merge request
-merge_request: 24882
-author: Jan Beckmann
-type: fixed
diff --git a/changelogs/unreleased/56954-improve-knative-after-installing-tiller.yml b/changelogs/unreleased/56954-improve-knative-after-installing-tiller.yml
deleted file mode 100644
index b9fb27c3218..00000000000
--- a/changelogs/unreleased/56954-improve-knative-after-installing-tiller.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improve the Knative installation on Clusters
-merge_request: 26339
-author:
-type: added
diff --git a/changelogs/unreleased/56959-drop-project_auto_devops_domain.yml b/changelogs/unreleased/56959-drop-project_auto_devops_domain.yml
new file mode 100644
index 00000000000..c529749670d
--- /dev/null
+++ b/changelogs/unreleased/56959-drop-project_auto_devops_domain.yml
@@ -0,0 +1,5 @@
+---
+title: Removes project_auto_devops#domain column
+merge_request: 28574
+author:
+type: other
diff --git a/changelogs/unreleased/56959-remove-auto-devops-domain-ci-variable.yml b/changelogs/unreleased/56959-remove-auto-devops-domain-ci-variable.yml
new file mode 100644
index 00000000000..c1c1708f935
--- /dev/null
+++ b/changelogs/unreleased/56959-remove-auto-devops-domain-ci-variable.yml
@@ -0,0 +1,5 @@
+---
+title: Removes support for AUTO_DEVOPS_DOMAIN
+merge_request: 28460
+author:
+type: removed
diff --git a/changelogs/unreleased/57037-fix-mr-checkboxes-mobile-alignment.yml b/changelogs/unreleased/57037-fix-mr-checkboxes-mobile-alignment.yml
new file mode 100644
index 00000000000..a2de6cd6d45
--- /dev/null
+++ b/changelogs/unreleased/57037-fix-mr-checkboxes-mobile-alignment.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Merge Request merge checkbox alignment on mobile view
+merge_request: 28845
+author:
+type: fixed
diff --git a/changelogs/unreleased/57115-just-in-time-k8s-resource-creation.yml b/changelogs/unreleased/57115-just-in-time-k8s-resource-creation.yml
deleted file mode 100644
index 2141c75ec72..00000000000
--- a/changelogs/unreleased/57115-just-in-time-k8s-resource-creation.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Create Kubernetes resources for projects when their deployment jobs run.
-merge_request: 25586
-author:
-type: changed
diff --git a/changelogs/unreleased/57131-external_auth_to_core.yml b/changelogs/unreleased/57131-external_auth_to_core.yml
deleted file mode 100644
index aacd3916c82..00000000000
--- a/changelogs/unreleased/57131-external_auth_to_core.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Move "Authorize project access with external service" to Core
-merge_request: 26823
-author:
-type: changed
diff --git a/changelogs/unreleased/57189-css-label-in-forms-with-bootstrap4.yml b/changelogs/unreleased/57189-css-label-in-forms-with-bootstrap4.yml
new file mode 100644
index 00000000000..86b6bb20253
--- /dev/null
+++ b/changelogs/unreleased/57189-css-label-in-forms-with-bootstrap4.yml
@@ -0,0 +1,5 @@
+---
+title: Fix col-sm-* in forms to keep layout
+merge_request: 24885
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/57319-hide-kubernetes-cluster-warning-if-project-has-cluster-related.yml b/changelogs/unreleased/57319-hide-kubernetes-cluster-warning-if-project-has-cluster-related.yml
deleted file mode 100644
index a6953a68a76..00000000000
--- a/changelogs/unreleased/57319-hide-kubernetes-cluster-warning-if-project-has-cluster-related.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Resolve "Hide Kubernetes cluster warning if project has cluster related"
-merge_request: 26749
-author:
-type: fixed
diff --git a/changelogs/unreleased/57357-automate-base-domain-help-text.yml b/changelogs/unreleased/57357-automate-base-domain-help-text.yml
deleted file mode 100644
index fa1831b66ea..00000000000
--- a/changelogs/unreleased/57357-automate-base-domain-help-text.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Automate base domain help text on Clusters page
-merge_request: 26124
-author:
-type: changed
diff --git a/changelogs/unreleased/57364-improve-diff-nav-header.yml b/changelogs/unreleased/57364-improve-diff-nav-header.yml
deleted file mode 100644
index 95d119b949c..00000000000
--- a/changelogs/unreleased/57364-improve-diff-nav-header.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Make stylistic improvements to diff nav header
-merge_request: 26557
-author:
-type: fixed
diff --git a/changelogs/unreleased/57409-loading-button-transition.yml b/changelogs/unreleased/57409-loading-button-transition.yml
deleted file mode 100644
index 3cf169d79de..00000000000
--- a/changelogs/unreleased/57409-loading-button-transition.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prevent fade out transition on loading-button component.
-merge_request: 26428
-author:
-type: fixed
diff --git a/changelogs/unreleased/57414-show-pipeline-iid.yml b/changelogs/unreleased/57414-show-pipeline-iid.yml
new file mode 100644
index 00000000000..596ae00e5a3
--- /dev/null
+++ b/changelogs/unreleased/57414-show-pipeline-iid.yml
@@ -0,0 +1,5 @@
+---
+title: Show Pipeline IID everywhere Pipeline ID is shown
+merge_request: 57414
+author: Mike Scott
+type: added
diff --git a/changelogs/unreleased/57482-shortcut-to-create-merge-request-from-web-ide.yml b/changelogs/unreleased/57482-shortcut-to-create-merge-request-from-web-ide.yml
deleted file mode 100644
index c188d59fe94..00000000000
--- a/changelogs/unreleased/57482-shortcut-to-create-merge-request-from-web-ide.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Create a shortcut for a new MR in the Web IDE
-merge_request: 26792
-author:
-type: added
diff --git a/changelogs/unreleased/57493-add-limit-to-user-name.yml b/changelogs/unreleased/57493-add-limit-to-user-name.yml
deleted file mode 100644
index e6c78572d23..00000000000
--- a/changelogs/unreleased/57493-add-limit-to-user-name.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Set user.name limit to 128 characters
-merge_request: 26146
-author:
-type: changed
diff --git a/changelogs/unreleased/57540-filename-trailing-space.yml b/changelogs/unreleased/57540-filename-trailing-space.yml
deleted file mode 100644
index db85fb350db..00000000000
--- a/changelogs/unreleased/57540-filename-trailing-space.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Implemented whitespace-trimming for file names in Web IDE
-merge_request: 26270
-author:
-type: fixed
diff --git a/changelogs/unreleased/57602-create-cluster-validations.yml b/changelogs/unreleased/57602-create-cluster-validations.yml
deleted file mode 100644
index 35349c1e9f4..00000000000
--- a/changelogs/unreleased/57602-create-cluster-validations.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Display cluster form validation error messages inline
-merge_request: 26502
-author:
-type: changed
diff --git a/changelogs/unreleased/57648-make-emoji-picker-full-width-on-mobile.yml b/changelogs/unreleased/57648-make-emoji-picker-full-width-on-mobile.yml
deleted file mode 100644
index d92fd2a762e..00000000000
--- a/changelogs/unreleased/57648-make-emoji-picker-full-width-on-mobile.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Makes emoji picker full width on mobile.
-merge_request: 25883
-author: Jacopo Beschi @jacopo-beschi
-type: fixed
diff --git a/changelogs/unreleased/57655-fix-markdown-tables-border.yml b/changelogs/unreleased/57655-fix-markdown-tables-border.yml
deleted file mode 100644
index 6a8ba8c4353..00000000000
--- a/changelogs/unreleased/57655-fix-markdown-tables-border.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix markdown table header and table content borders
-merge_request: 25666
-author:
-type: fixed
diff --git a/changelogs/unreleased/57668-create-file-from-url.yml b/changelogs/unreleased/57668-create-file-from-url.yml
deleted file mode 100644
index b6033fa24ca..00000000000
--- a/changelogs/unreleased/57668-create-file-from-url.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Implemented support for creation of new files from URL in Web IDE
-merge_request: 26622
-author:
-type: added
diff --git a/changelogs/unreleased/57669-fix-bug-clicking-file-header-refreshes-page.yml b/changelogs/unreleased/57669-fix-bug-clicking-file-header-refreshes-page.yml
deleted file mode 100644
index c6161870096..00000000000
--- a/changelogs/unreleased/57669-fix-bug-clicking-file-header-refreshes-page.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Scroll to diff file content when clicking on file header name and it is not
- a link to other page
-merge_request: !26422
-author:
-type: fixed
diff --git a/changelogs/unreleased/57825-moving-an-issue-results-in-broken-image-links-in-comments.yml b/changelogs/unreleased/57825-moving-an-issue-results-in-broken-image-links-in-comments.yml
new file mode 100644
index 00000000000..faa1784ea21
--- /dev/null
+++ b/changelogs/unreleased/57825-moving-an-issue-results-in-broken-image-links-in-comments.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve moving an issue results in broken image links in comments
+merge_request: 28654
+author:
+type: fixed
diff --git a/changelogs/unreleased/57894-buttons-on-group-page-are-misaligned.yml b/changelogs/unreleased/57894-buttons-on-group-page-are-misaligned.yml
deleted file mode 100644
index ca0f529df6c..00000000000
--- a/changelogs/unreleased/57894-buttons-on-group-page-are-misaligned.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix misalignment of group overview page buttons
-merge_request: 26292
-author:
-type: fixed
diff --git a/changelogs/unreleased/57984-store-branch-name.yml b/changelogs/unreleased/57984-store-branch-name.yml
deleted file mode 100644
index 26dfdb7a5d6..00000000000
--- a/changelogs/unreleased/57984-store-branch-name.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Resolves Branch name is lost if I change commit mode in Web IDE
-merge_request: 26180
-author:
-type: fixed
diff --git a/changelogs/unreleased/58208-explicitly-set-masterauth.yml b/changelogs/unreleased/58208-explicitly-set-masterauth.yml
deleted file mode 100644
index e3512d11113..00000000000
--- a/changelogs/unreleased/58208-explicitly-set-masterauth.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Explicitly set master_auth setting to enable basic auth and client certificate
- for new GKE clusters
-merge_request: 26018
-author:
-type: other
diff --git a/changelogs/unreleased/58269-separate-update-patch.yml b/changelogs/unreleased/58269-separate-update-patch.yml
new file mode 100644
index 00000000000..e9b44257b07
--- /dev/null
+++ b/changelogs/unreleased/58269-separate-update-patch.yml
@@ -0,0 +1,5 @@
+---
+title: Do not display Update app button when saving Knative domain name
+merge_request: 28904
+author:
+type: changed
diff --git a/changelogs/unreleased/58297-remove-extraneous-gitaly-calls-from-md-rendering.yml b/changelogs/unreleased/58297-remove-extraneous-gitaly-calls-from-md-rendering.yml
new file mode 100644
index 00000000000..25cc973159f
--- /dev/null
+++ b/changelogs/unreleased/58297-remove-extraneous-gitaly-calls-from-md-rendering.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce Gitaly calls to improve performance when rendering suggestions
+merge_request: 29027
+author:
+type: performance
diff --git a/changelogs/unreleased/58375-api-controller.yml b/changelogs/unreleased/58375-api-controller.yml
deleted file mode 100644
index 60f21b37ae7..00000000000
--- a/changelogs/unreleased/58375-api-controller.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add a Prometheus API per environment
-merge_request: 26841
-author:
-type: added
diff --git a/changelogs/unreleased/58375-reactive-caching-changes.yml b/changelogs/unreleased/58375-reactive-caching-changes.yml
deleted file mode 100644
index cf73736b8ef..00000000000
--- a/changelogs/unreleased/58375-reactive-caching-changes.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow reactive caching to be used in services
-merge_request: 26839
-author:
-type: added
diff --git a/changelogs/unreleased/58404-set-default-max-depth-for-GraphQL.yml b/changelogs/unreleased/58404-set-default-max-depth-for-GraphQL.yml
new file mode 100644
index 00000000000..7e95158a0e0
--- /dev/null
+++ b/changelogs/unreleased/58404-set-default-max-depth-for-GraphQL.yml
@@ -0,0 +1,5 @@
+---
+title: 58404 - setup max depth for GraphQL
+merge_request: 25737
+author: Ken Ding
+type: added
diff --git a/changelogs/unreleased/58405-basic-limiting-complexity-of-graphql-queries.yml b/changelogs/unreleased/58405-basic-limiting-complexity-of-graphql-queries.yml
deleted file mode 100644
index 058a120b500..00000000000
--- a/changelogs/unreleased/58405-basic-limiting-complexity-of-graphql-queries.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add initial complexity limits to GraphQL queries
-merge_request: 26629
-author:
-type: performance
diff --git a/changelogs/unreleased/58410-change-pixel-size-of-instance-header-footer-message-to-16px.yml b/changelogs/unreleased/58410-change-pixel-size-of-instance-header-footer-message-to-16px.yml
deleted file mode 100644
index 3e494847e75..00000000000
--- a/changelogs/unreleased/58410-change-pixel-size-of-instance-header-footer-message-to-16px.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Reduce height of instance system header and footer
-merge_request: 25752
-author:
-type: changed
diff --git a/changelogs/unreleased/58433-email-notifications-do-not-work-properly-issue-due-date.yml b/changelogs/unreleased/58433-email-notifications-do-not-work-properly-issue-due-date.yml
new file mode 100644
index 00000000000..4579721446a
--- /dev/null
+++ b/changelogs/unreleased/58433-email-notifications-do-not-work-properly-issue-due-date.yml
@@ -0,0 +1,5 @@
+---
+title: Fix email notifications for user excluded actions
+merge_request: 28835
+author:
+type: fixed
diff --git a/changelogs/unreleased/58482-update-airminc-clair-local-scan-to-2-0-6.yml b/changelogs/unreleased/58482-update-airminc-clair-local-scan-to-2-0-6.yml
deleted file mode 100644
index be9c38aba1e..00000000000
--- a/changelogs/unreleased/58482-update-airminc-clair-local-scan-to-2-0-6.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update clair-local-scan to 2.0.6
-merge_request: 25743
-author: Takuya Noguchi
-type: added
diff --git a/changelogs/unreleased/58538-discussion-top-radius.yml b/changelogs/unreleased/58538-discussion-top-radius.yml
new file mode 100644
index 00000000000..0fb16055623
--- /dev/null
+++ b/changelogs/unreleased/58538-discussion-top-radius.yml
@@ -0,0 +1,5 @@
+---
+title: Fix border radius of discussions
+merge_request: 28490
+author:
+type: fixed
diff --git a/changelogs/unreleased/58632-fix-mr-widget-padding.yml b/changelogs/unreleased/58632-fix-mr-widget-padding.yml
new file mode 100644
index 00000000000..fb4e1791359
--- /dev/null
+++ b/changelogs/unreleased/58632-fix-mr-widget-padding.yml
@@ -0,0 +1,5 @@
+---
+title: Fix padding in MR widget
+merge_request: 28472
+author:
+type: fixed
diff --git a/changelogs/unreleased/58717-checkbox-cannot-be-checked-if-a-blockquote-is-above.yml b/changelogs/unreleased/58717-checkbox-cannot-be-checked-if-a-blockquote-is-above.yml
deleted file mode 100644
index 9f5881966c7..00000000000
--- a/changelogs/unreleased/58717-checkbox-cannot-be-checked-if-a-blockquote-is-above.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow task lists that follow a blockquote to work correctly
-merge_request: 26937
-author:
-type: fixed
diff --git a/changelogs/unreleased/58739-hashed-storage-prevent-a-migration-and-rollback-running-at-the-same-time.yml b/changelogs/unreleased/58739-hashed-storage-prevent-a-migration-and-rollback-running-at-the-same-time.yml
deleted file mode 100644
index 765a991bb6a..00000000000
--- a/changelogs/unreleased/58739-hashed-storage-prevent-a-migration-and-rollback-running-at-the-same-time.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Hashed Storage: Prevent a migration and rollback running at the same time'
-merge_request: 25976
-author:
-type: changed
diff --git a/changelogs/unreleased/58748-update-nodejs-to-10-15-3.yml b/changelogs/unreleased/58748-update-nodejs-to-10-15-3.yml
deleted file mode 100644
index 4c7e4b5c604..00000000000
--- a/changelogs/unreleased/58748-update-nodejs-to-10-15-3.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update node.js to 10.15.3 in CI template for Hexo
-merge_request: 25943
-author: Takuya Noguchi
-type: other
diff --git a/changelogs/unreleased/58751-fix-project-name-members-page.yml b/changelogs/unreleased/58751-fix-project-name-members-page.yml
deleted file mode 100644
index a295afc5c48..00000000000
--- a/changelogs/unreleased/58751-fix-project-name-members-page.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Fix unwanted character replacement on project members page caused by usage of sanitize function"
-merge_request: 25946
-author: Elias Werberich
-type: fixed
diff --git a/changelogs/unreleased/58781-silent-progress-in-auto-devops.yml b/changelogs/unreleased/58781-silent-progress-in-auto-devops.yml
deleted file mode 100644
index e45db8eafc3..00000000000
--- a/changelogs/unreleased/58781-silent-progress-in-auto-devops.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use curl silent/show-error options on Auto DevOps
-merge_request: 25954
-author: Takuya Noguchi
-type: other
diff --git a/changelogs/unreleased/58789-some-system-notes-on-issuable-are-folded-on-mobile.yml b/changelogs/unreleased/58789-some-system-notes-on-issuable-are-folded-on-mobile.yml
deleted file mode 100644
index ebfb7aeaa1f..00000000000
--- a/changelogs/unreleased/58789-some-system-notes-on-issuable-are-folded-on-mobile.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Keep inline as much as possible in system notes on issuable
-merge_request: 25968
-author: Takuya Noguchi
-type: fixed
diff --git a/changelogs/unreleased/58793-fix-nav-links-archived-project.yml b/changelogs/unreleased/58793-fix-nav-links-archived-project.yml
deleted file mode 100644
index a8250804c34..00000000000
--- a/changelogs/unreleased/58793-fix-nav-links-archived-project.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Disable inaccessible navigation links upon archiving a project"
-merge_request: 26020
-author: Elias Werberich
-type: fixed
diff --git a/changelogs/unreleased/58797-broken-ui-on-a-closed-merge-request-from-a-deleted-source-project.yml b/changelogs/unreleased/58797-broken-ui-on-a-closed-merge-request-from-a-deleted-source-project.yml
deleted file mode 100644
index e30f48ed1a8..00000000000
--- a/changelogs/unreleased/58797-broken-ui-on-a-closed-merge-request-from-a-deleted-source-project.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix UI for closed MR when source project is removed
-merge_request: 25967
-author: Takuya Noguchi
-type: fixed
diff --git a/changelogs/unreleased/58805-allow-incomplete-commit-data-to-be-fetched-from-collection.yml b/changelogs/unreleased/58805-allow-incomplete-commit-data-to-be-fetched-from-collection.yml
deleted file mode 100644
index 4377ebfdbdf..00000000000
--- a/changelogs/unreleased/58805-allow-incomplete-commit-data-to-be-fetched-from-collection.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix merge commits being used as default squash commit messages
-merge_request: 26445
-author:
-type: fixed
diff --git a/changelogs/unreleased/58835-button-run-pipeline.yml b/changelogs/unreleased/58835-button-run-pipeline.yml
deleted file mode 100644
index 39407a60780..00000000000
--- a/changelogs/unreleased/58835-button-run-pipeline.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Changed button label at /pipelines/new
-merge_request: 26893
-author: antfobe,leonardofl
-type: other
diff --git a/changelogs/unreleased/58839-automatically-set-prometheus-step-interval.yml b/changelogs/unreleased/58839-automatically-set-prometheus-step-interval.yml
deleted file mode 100644
index 2c6edf45ae2..00000000000
--- a/changelogs/unreleased/58839-automatically-set-prometheus-step-interval.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Automatically set Prometheus step interval
-merge_request: 26441
-author:
-type: changed
diff --git a/changelogs/unreleased/58883-fix-fetching-comments.yml b/changelogs/unreleased/58883-fix-fetching-comments.yml
deleted file mode 100644
index 14c0f1687f2..00000000000
--- a/changelogs/unreleased/58883-fix-fetching-comments.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix error shown when loading links to specific comments
-merge_request: 26092
-author:
-type: fixed
diff --git a/changelogs/unreleased/58889-spinners-are-active-prematurely-in-bitbucket-cloud-import.yml b/changelogs/unreleased/58889-spinners-are-active-prematurely-in-bitbucket-cloud-import.yml
deleted file mode 100644
index ec357d9a832..00000000000
--- a/changelogs/unreleased/58889-spinners-are-active-prematurely-in-bitbucket-cloud-import.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix continuous bitbucket import loading spinner
-merge_request: 26175
-author:
-type: fixed
diff --git a/changelogs/unreleased/58933-broken-ui-on-commits-on-mobile.yml b/changelogs/unreleased/58933-broken-ui-on-commits-on-mobile.yml
deleted file mode 100644
index ca9f9dd21c9..00000000000
--- a/changelogs/unreleased/58933-broken-ui-on-commits-on-mobile.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix UI layout on Commits on mobile
-merge_request: 26133
-author: Takuya Noguchi
-type: fixed
diff --git a/changelogs/unreleased/58941-use-gitlab-serverless-with-existing-knative-installation.yml b/changelogs/unreleased/58941-use-gitlab-serverless-with-existing-knative-installation.yml
new file mode 100644
index 00000000000..53be008816d
--- /dev/null
+++ b/changelogs/unreleased/58941-use-gitlab-serverless-with-existing-knative-installation.yml
@@ -0,0 +1,5 @@
+---
+title: Enable function features for external Knative installations
+merge_request: 27173
+author:
+type: changed
diff --git a/changelogs/unreleased/58971-sentry-api-keyerror.yml b/changelogs/unreleased/58971-sentry-api-keyerror.yml
deleted file mode 100644
index 0f195c4b4f7..00000000000
--- a/changelogs/unreleased/58971-sentry-api-keyerror.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Handle missing keys in sentry api response
-merge_request: 26264
-author:
-type: fixed
diff --git a/changelogs/unreleased/58981-migrate-clusters-tests-to-jest.yml b/changelogs/unreleased/58981-migrate-clusters-tests-to-jest.yml
deleted file mode 100644
index 3df13dbb960..00000000000
--- a/changelogs/unreleased/58981-migrate-clusters-tests-to-jest.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Migrate clusters tests to jest
-merge_request: 27013
-author:
-type: other
diff --git a/changelogs/unreleased/58984-doc-missing-milestones-and-labels-links.yml b/changelogs/unreleased/58984-doc-missing-milestones-and-labels-links.yml
new file mode 100644
index 00000000000..6b74303c16e
--- /dev/null
+++ b/changelogs/unreleased/58984-doc-missing-milestones-and-labels-links.yml
@@ -0,0 +1,5 @@
+---
+title: Document when milestones and labels links are missing
+merge_request: 29355
+author:
+type: other
diff --git a/changelogs/unreleased/59026-replace-favicon.yml b/changelogs/unreleased/59026-replace-favicon.yml
new file mode 100644
index 00000000000..34228bb8438
--- /dev/null
+++ b/changelogs/unreleased/59026-replace-favicon.yml
@@ -0,0 +1,5 @@
+---
+title: Update favicon from next
+merge_request: 28601
+author: Jarek Ostrowski @jareko
+type: fixed
diff --git a/changelogs/unreleased/59057-buttons-on-top-from-a-user-profile-page-on-mobile.yml b/changelogs/unreleased/59057-buttons-on-top-from-a-user-profile-page-on-mobile.yml
deleted file mode 100644
index febbbce2139..00000000000
--- a/changelogs/unreleased/59057-buttons-on-top-from-a-user-profile-page-on-mobile.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improve mobile UI on User Profile page
-merge_request: 26240
-author: Takuya Noguchi
-type: other
diff --git a/changelogs/unreleased/59062-update-gitlab-markup-python-3.yml b/changelogs/unreleased/59062-update-gitlab-markup-python-3.yml
deleted file mode 100644
index 265a7e36841..00000000000
--- a/changelogs/unreleased/59062-update-gitlab-markup-python-3.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update gitlab-markup to 1.7.0 which requies python3
-merge_request: 26246
-author:
-type: changed
diff --git a/changelogs/unreleased/59079-fix-jupyter-render-loop.yml b/changelogs/unreleased/59079-fix-jupyter-render-loop.yml
deleted file mode 100644
index 29264b33dfa..00000000000
--- a/changelogs/unreleased/59079-fix-jupyter-render-loop.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix jupyter rendering bug that ended in an infinite loop
-merge_request: 26656
-author: ROSPARS Benoit
-type: fixed
diff --git a/changelogs/unreleased/59105-padding-unclickable-pipeline-job.yml b/changelogs/unreleased/59105-padding-unclickable-pipeline-job.yml
new file mode 100644
index 00000000000..95f08af3cb1
--- /dev/null
+++ b/changelogs/unreleased/59105-padding-unclickable-pipeline-job.yml
@@ -0,0 +1,5 @@
+---
+title: Fix padding of unclickable pipeline dropdown items to match links
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/59117-inconsistent-hover-behavior-on-navbar-items.yml b/changelogs/unreleased/59117-inconsistent-hover-behavior-on-navbar-items.yml
deleted file mode 100644
index eb9dcef4a89..00000000000
--- a/changelogs/unreleased/59117-inconsistent-hover-behavior-on-navbar-items.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix hover animation consistency in top navbar items
-merge_request: 26345
-author:
-type: fixed
diff --git a/changelogs/unreleased/59131-set-the-size-of-instance-system-message-text-12px.yml b/changelogs/unreleased/59131-set-the-size-of-instance-system-message-text-12px.yml
deleted file mode 100644
index 688190f4458..00000000000
--- a/changelogs/unreleased/59131-set-the-size-of-instance-system-message-text-12px.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update system message banner font size to 12px
-merge_request: 26293
-author:
-type: changed
diff --git a/changelogs/unreleased/59189-long-names-in-project-path-namespace-dropdown-breaks-past-container.yml b/changelogs/unreleased/59189-long-names-in-project-path-namespace-dropdown-breaks-past-container.yml
deleted file mode 100644
index bed7fcf2651..00000000000
--- a/changelogs/unreleased/59189-long-names-in-project-path-namespace-dropdown-breaks-past-container.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prevent namespace dropdown in new project form from exceeding container
-merge_request: 26343
-author:
-type: fixed
diff --git a/changelogs/unreleased/59273-update-fugit.yml b/changelogs/unreleased/59273-update-fugit.yml
deleted file mode 100644
index 3a1c64d87ef..00000000000
--- a/changelogs/unreleased/59273-update-fugit.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update fugit which fixes a potential infinite loop
-merge_request: 26579
-author:
-type: fixed
diff --git a/changelogs/unreleased/59296-add-filter-by-title-milestones-api.yml b/changelogs/unreleased/59296-add-filter-by-title-milestones-api.yml
deleted file mode 100644
index 440b24a548c..00000000000
--- a/changelogs/unreleased/59296-add-filter-by-title-milestones-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add select by title to milestones API
-merge_request: 26573
-author:
-type: added
diff --git a/changelogs/unreleased/59324-queries-which-return-multiple-series-are-not-working-correctly.yml b/changelogs/unreleased/59324-queries-which-return-multiple-series-are-not-working-correctly.yml
deleted file mode 100644
index 9ab8d2b8596..00000000000
--- a/changelogs/unreleased/59324-queries-which-return-multiple-series-are-not-working-correctly.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix multiple series queries on metrics dashboard
-merge_request: 26514
-author:
-type: fixed
diff --git a/changelogs/unreleased/59352-fix-mr-discussion-expansion.yml b/changelogs/unreleased/59352-fix-mr-discussion-expansion.yml
deleted file mode 100644
index ab9ad53835c..00000000000
--- a/changelogs/unreleased/59352-fix-mr-discussion-expansion.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Expand resolved discussion when linking to a comment in the discussion
-merge_request: 26483
-author:
-type: fixed
diff --git a/changelogs/unreleased/59376-Report-abuse-to-GitLab-should-be-Report-abuse-in-non-gitlab-com-instances.yml b/changelogs/unreleased/59376-Report-abuse-to-GitLab-should-be-Report-abuse-in-non-gitlab-com-instances.yml
new file mode 100644
index 00000000000..0904f788b6f
--- /dev/null
+++ b/changelogs/unreleased/59376-Report-abuse-to-GitLab-should-be-Report-abuse-in-non-gitlab-com-instances.yml
@@ -0,0 +1,5 @@
+---
+title: Change "Report abuse to GitLab" to more generic wording
+merge_request: 28884
+author: Marc Schwede
+type: other
diff --git a/changelogs/unreleased/59441-add-base-domain-to-cluster-api.yml b/changelogs/unreleased/59441-add-base-domain-to-cluster-api.yml
deleted file mode 100644
index cb5cbba4e92..00000000000
--- a/changelogs/unreleased/59441-add-base-domain-to-cluster-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add cluster domain to Project Cluster API
-merge_request: 26735
-author:
-type: other
diff --git a/changelogs/unreleased/59502-fix-breadcrumb-artifacts.yml b/changelogs/unreleased/59502-fix-breadcrumb-artifacts.yml
deleted file mode 100644
index da65c3bc870..00000000000
--- a/changelogs/unreleased/59502-fix-breadcrumb-artifacts.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixes job link in artifacts page breadcrumb
-merge_request: 26592
-author:
-type: fixed
diff --git a/changelogs/unreleased/59546-fix-error-handling-for-missing-domain.yml b/changelogs/unreleased/59546-fix-error-handling-for-missing-domain.yml
deleted file mode 100644
index 8f0ce5d57c5..00000000000
--- a/changelogs/unreleased/59546-fix-error-handling-for-missing-domain.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix Auto DevOps missing domain error handling
-merge_request: 26627
-author:
-type: fixed
diff --git a/changelogs/unreleased/59587-add-graphql-logging.yml b/changelogs/unreleased/59587-add-graphql-logging.yml
new file mode 100644
index 00000000000..74c2a734f37
--- /dev/null
+++ b/changelogs/unreleased/59587-add-graphql-logging.yml
@@ -0,0 +1,5 @@
+---
+title: Add dedicated logging for GraphQL queries
+merge_request: 27885
+author:
+type: other
diff --git a/changelogs/unreleased/59621-order-labels-alphabetically-in-issue-boards.yml b/changelogs/unreleased/59621-order-labels-alphabetically-in-issue-boards.yml
deleted file mode 100644
index 8b82d757303..00000000000
--- a/changelogs/unreleased/59621-order-labels-alphabetically-in-issue-boards.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Order labels alphabetically in issue boards
-merge_request: 26927
-author:
-type: changed
diff --git a/changelogs/unreleased/59651-remove-unnecessary-decimal-places-on-chart-axes.yml b/changelogs/unreleased/59651-remove-unnecessary-decimal-places-on-chart-axes.yml
new file mode 100644
index 00000000000..fea34099135
--- /dev/null
+++ b/changelogs/unreleased/59651-remove-unnecessary-decimal-places-on-chart-axes.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unnecessary decimals on Metrics chart axis
+merge_request: 29468
+author:
+type: fixed
diff --git a/changelogs/unreleased/59708-vendor-css.yml b/changelogs/unreleased/59708-vendor-css.yml
deleted file mode 100644
index ec7def7a9e6..00000000000
--- a/changelogs/unreleased/59708-vendor-css.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Creates a vendors folder for external CSS
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/59921-pipeline-schedule.yml b/changelogs/unreleased/59921-pipeline-schedule.yml
deleted file mode 100644
index 4227a047913..00000000000
--- a/changelogs/unreleased/59921-pipeline-schedule.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Replaces CSS with BS4 utility class for pipeline schedules
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/59987-move-sign-in-2fa-on-users-sign_in-above-intro-content-on-mobile.yml b/changelogs/unreleased/59987-move-sign-in-2fa-on-users-sign_in-above-intro-content-on-mobile.yml
new file mode 100644
index 00000000000..7863f1f7bbe
--- /dev/null
+++ b/changelogs/unreleased/59987-move-sign-in-2fa-on-users-sign_in-above-intro-content-on-mobile.yml
@@ -0,0 +1,5 @@
+---
+title: Prioritize login form on mobile breakpoint
+merge_request: 28360
+author:
+type: changed
diff --git a/changelogs/unreleased/60006-add-touch-events-to-image-diff-26971.yml b/changelogs/unreleased/60006-add-touch-events-to-image-diff-26971.yml
deleted file mode 100644
index bfea3ac52af..00000000000
--- a/changelogs/unreleased/60006-add-touch-events-to-image-diff-26971.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Make touch events work on image diff swipe view and onion skin"
-merge_request: 26971
-author: ftab
-type: added
diff --git a/changelogs/unreleased/60026-group-member-count-bg.yml b/changelogs/unreleased/60026-group-member-count-bg.yml
deleted file mode 100644
index 0a1f6eac2ea..00000000000
--- a/changelogs/unreleased/60026-group-member-count-bg.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add badge-pill class on group member count
-merge_request: 27019
-author:
-type: fixed
diff --git a/changelogs/unreleased/60034-default-web-ide-s-merge-request-checkbox-to-true.yml b/changelogs/unreleased/60034-default-web-ide-s-merge-request-checkbox-to-true.yml
new file mode 100644
index 00000000000..fdf80c660f7
--- /dev/null
+++ b/changelogs/unreleased/60034-default-web-ide-s-merge-request-checkbox-to-true.yml
@@ -0,0 +1,5 @@
+---
+title: Default MR checkbox to true in most cases
+merge_request: !28665
+author:
+type: changed
diff --git a/changelogs/unreleased/60068-avoid-null-domain-help-text.yml b/changelogs/unreleased/60068-avoid-null-domain-help-text.yml
deleted file mode 100644
index 5305b8584a8..00000000000
--- a/changelogs/unreleased/60068-avoid-null-domain-help-text.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Do not display Ingress IP help text when there isn’t an Ingress IP assigned
-merge_request: 27057
-author:
-type: fixed
diff --git a/changelogs/unreleased/60116-fix-button-wrapping.yml b/changelogs/unreleased/60116-fix-button-wrapping.yml
deleted file mode 100644
index d6df920b51d..00000000000
--- a/changelogs/unreleased/60116-fix-button-wrapping.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add to white-space nowrap to all buttons
-merge_request: 27069
-author:
-type: fixed
diff --git a/changelogs/unreleased/60149-nameerror-uninitialized-constant-sentry-client-sentryerror.yml b/changelogs/unreleased/60149-nameerror-uninitialized-constant-sentry-client-sentryerror.yml
deleted file mode 100644
index 8c3a47cf62c..00000000000
--- a/changelogs/unreleased/60149-nameerror-uninitialized-constant-sentry-client-sentryerror.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Handle possible HTTP exception for Sentry client
-merge_request: 27080
-author:
-type: fixed
diff --git a/changelogs/unreleased/60180-jira-service-fix-nil-on-find-call.yml b/changelogs/unreleased/60180-jira-service-fix-nil-on-find-call.yml
new file mode 100644
index 00000000000..6891a9ca83c
--- /dev/null
+++ b/changelogs/unreleased/60180-jira-service-fix-nil-on-find-call.yml
@@ -0,0 +1,5 @@
+---
+title: 'Resolved JIRA service: NoMethodError: undefined method ''find'' for nil:NilClass'
+merge_request: 28206
+author:
+type: fixed
diff --git a/changelogs/unreleased/60224-btn-env.yml b/changelogs/unreleased/60224-btn-env.yml
deleted file mode 100644
index 5053ddb31fa..00000000000
--- a/changelogs/unreleased/60224-btn-env.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixes actions dropdowns in environments page
-merge_request: 27160
-author:
-type: fixed
diff --git a/changelogs/unreleased/60241-merge-request-popover-doesn-t-go-away-on-mouse-leave.yml b/changelogs/unreleased/60241-merge-request-popover-doesn-t-go-away-on-mouse-leave.yml
deleted file mode 100644
index ce942777dca..00000000000
--- a/changelogs/unreleased/60241-merge-request-popover-doesn-t-go-away-on-mouse-leave.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix bug where MR popover doesn't go away on mouse leave
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/60250-remove-mr_push_options-flag.yml b/changelogs/unreleased/60250-remove-mr_push_options-flag.yml
new file mode 100644
index 00000000000..b429d83dcc7
--- /dev/null
+++ b/changelogs/unreleased/60250-remove-mr_push_options-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Remove the mr_push_options feature flag
+merge_request: 28278
+author:
+type: changed
diff --git a/changelogs/unreleased/60261-save-btn-env.yml b/changelogs/unreleased/60261-save-btn-env.yml
deleted file mode 100644
index b0936198d2e..00000000000
--- a/changelogs/unreleased/60261-save-btn-env.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixes create button background for Environments form
-merge_request: 27161
-author:
-type: fixed
diff --git a/changelogs/unreleased/60303-replace-sidekiq-mtail-metrics.yml b/changelogs/unreleased/60303-replace-sidekiq-mtail-metrics.yml
new file mode 100644
index 00000000000..90b72ec05c7
--- /dev/null
+++ b/changelogs/unreleased/60303-replace-sidekiq-mtail-metrics.yml
@@ -0,0 +1,5 @@
+---
+title: Replaces sidekiq mtail metrics with ruby instrumentation metrics
+merge_request: 29215
+author:
+type: changed
diff --git a/changelogs/unreleased/60304-long-file-names-in-mr-diffs-cause-horizontal-scrolling.yml b/changelogs/unreleased/60304-long-file-names-in-mr-diffs-cause-horizontal-scrolling.yml
deleted file mode 100644
index ec5e9e4703b..00000000000
--- a/changelogs/unreleased/60304-long-file-names-in-mr-diffs-cause-horizontal-scrolling.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix long file header names bug in diffs
-merge_request: 27233
-author:
-type: fixed
diff --git a/changelogs/unreleased/60323-inline-validation-for-users-name-and-username-length.yml b/changelogs/unreleased/60323-inline-validation-for-users-name-and-username-length.yml
new file mode 100644
index 00000000000..83b7bd3433e
--- /dev/null
+++ b/changelogs/unreleased/60323-inline-validation-for-users-name-and-username-length.yml
@@ -0,0 +1,5 @@
+---
+title: Update registration form to indicate invalid name or username length on input
+merge_request: 28095
+author: Jiaan Louw
+type: changed
diff --git a/changelogs/unreleased/60379-remove-ci-preparing-state-feature-flag.yml b/changelogs/unreleased/60379-remove-ci-preparing-state-feature-flag.yml
new file mode 100644
index 00000000000..a9b7aeb3024
--- /dev/null
+++ b/changelogs/unreleased/60379-remove-ci-preparing-state-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Remove ability for group clusters to be automatically configured on creation
+merge_request: 27245
+author:
+type: removed
diff --git a/changelogs/unreleased/60425-fix-500-when-accessing-charts-with-anonymous-user.yml b/changelogs/unreleased/60425-fix-500-when-accessing-charts-with-anonymous-user.yml
new file mode 100644
index 00000000000..4274dc5918c
--- /dev/null
+++ b/changelogs/unreleased/60425-fix-500-when-accessing-charts-with-anonymous-user.yml
@@ -0,0 +1,5 @@
+---
+title: "Fix 500 error when accessing charts with an anonymous user"
+merge_request: 28091
+author: Diego Silva
+type: fixed
diff --git a/changelogs/unreleased/60750-milestone-header.yml b/changelogs/unreleased/60750-milestone-header.yml
new file mode 100644
index 00000000000..62cfdaf6ea7
--- /dev/null
+++ b/changelogs/unreleased/60750-milestone-header.yml
@@ -0,0 +1,5 @@
+---
+title: Fix layout of group milestone header
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/60818_yamllint_project_root.yml b/changelogs/unreleased/60818_yamllint_project_root.yml
new file mode 100644
index 00000000000..b34a50e6a9c
--- /dev/null
+++ b/changelogs/unreleased/60818_yamllint_project_root.yml
@@ -0,0 +1,5 @@
+---
+title: Fix yaml linting for project root *.yml files
+merge_request: 27579
+author: Will Hall
+type: fixed
diff --git a/changelogs/unreleased/60819_yamllint_gitlabci.yml b/changelogs/unreleased/60819_yamllint_gitlabci.yml
new file mode 100644
index 00000000000..aba3b206f7e
--- /dev/null
+++ b/changelogs/unreleased/60819_yamllint_gitlabci.yml
@@ -0,0 +1,5 @@
+---
+title: Fix yaml linting for GitLab CI inside project (.gitlab/ci) *.yml files and CI template files
+merge_request: 27576
+author: Will Hall
+type: fixed
diff --git a/changelogs/unreleased/609120-ref-link.yml b/changelogs/unreleased/609120-ref-link.yml
new file mode 100644
index 00000000000..97c93b7ff53
--- /dev/null
+++ b/changelogs/unreleased/609120-ref-link.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes Ref link being displayed as raw HTML in the Pipelines page
+merge_request: 28823
+author:
+type: fixed
diff --git a/changelogs/unreleased/60987-emoji-picker-popup.yml b/changelogs/unreleased/60987-emoji-picker-popup.yml
new file mode 100644
index 00000000000..3bccec8e164
--- /dev/null
+++ b/changelogs/unreleased/60987-emoji-picker-popup.yml
@@ -0,0 +1,5 @@
+---
+title: Fix emoji picker visibility issue
+merge_request: 28984
+author:
+type: fixed
diff --git a/changelogs/unreleased/61024-update-resolved-icon.yml b/changelogs/unreleased/61024-update-resolved-icon.yml
new file mode 100644
index 00000000000..4a4de9eb13a
--- /dev/null
+++ b/changelogs/unreleased/61024-update-resolved-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Add check circle filled icon for resolved comments
+merge_request: 28663
+author:
+type: changed
diff --git a/changelogs/unreleased/6104-ee-ce-difference.yml b/changelogs/unreleased/6104-ee-ce-difference.yml
new file mode 100644
index 00000000000..59d31daf0eb
--- /dev/null
+++ b/changelogs/unreleased/6104-ee-ce-difference.yml
@@ -0,0 +1,5 @@
+---
+title: Unified EE/CS differences in repository/show.html
+merge_request: 13562
+author:
+type: other
diff --git a/changelogs/unreleased/61045-charts-with-many-overlapping-series-display-incorrectly.yml b/changelogs/unreleased/61045-charts-with-many-overlapping-series-display-incorrectly.yml
new file mode 100644
index 00000000000..53cc0a15417
--- /dev/null
+++ b/changelogs/unreleased/61045-charts-with-many-overlapping-series-display-incorrectly.yml
@@ -0,0 +1,5 @@
+---
+title: Eliminate color inconsistencies in metric graphs
+merge_request: 29127
+author:
+type: fixed
diff --git a/changelogs/unreleased/61049-links-activity-stream.yml b/changelogs/unreleased/61049-links-activity-stream.yml
new file mode 100644
index 00000000000..3aac84adc31
--- /dev/null
+++ b/changelogs/unreleased/61049-links-activity-stream.yml
@@ -0,0 +1,5 @@
+---
+title: Use blue for activity stream links; use monospace font for commit sha
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/61072-link-to-user-profile-not-distinguishable-on-latest-commit-widget.yml b/changelogs/unreleased/61072-link-to-user-profile-not-distinguishable-on-latest-commit-widget.yml
new file mode 100644
index 00000000000..5285ac767cc
--- /dev/null
+++ b/changelogs/unreleased/61072-link-to-user-profile-not-distinguishable-on-latest-commit-widget.yml
@@ -0,0 +1,5 @@
+---
+title: User link styling for commits
+merge_request: 29150
+author:
+type: other
diff --git a/changelogs/unreleased/61144-style-secondary-button-type-to-be-aligned-with-pattern-library.yml b/changelogs/unreleased/61144-style-secondary-button-type-to-be-aligned-with-pattern-library.yml
new file mode 100644
index 00000000000..ed4cf0507c7
--- /dev/null
+++ b/changelogs/unreleased/61144-style-secondary-button-type-to-be-aligned-with-pattern-library.yml
@@ -0,0 +1,5 @@
+---
+title: Bring secondary button styles up to design standard
+merge_request: 27920
+author:
+type: fixed
diff --git a/changelogs/unreleased/61157-reviewer-roulette-shouldn-t-include-the-author-as-a-possibility.yml b/changelogs/unreleased/61157-reviewer-roulette-shouldn-t-include-the-author-as-a-possibility.yml
new file mode 100644
index 00000000000..8d1a38b3db5
--- /dev/null
+++ b/changelogs/unreleased/61157-reviewer-roulette-shouldn-t-include-the-author-as-a-possibility.yml
@@ -0,0 +1,5 @@
+---
+title: Excludes MR author from Review roulette
+merge_request: 28886
+author: Jacopo Beschi @jacopo-beschi
+type: fixed
diff --git a/changelogs/unreleased/61313-fix-dropdown-searchbar.yml b/changelogs/unreleased/61313-fix-dropdown-searchbar.yml
new file mode 100644
index 00000000000..ba191a89da2
--- /dev/null
+++ b/changelogs/unreleased/61313-fix-dropdown-searchbar.yml
@@ -0,0 +1,5 @@
+---
+title: Fix loading.. dropdown at search field
+merge_request: 28275
+author: Pavel Chausov
+type: fixed
diff --git a/changelogs/unreleased/61323-snippet-copy-icon-button-is-misaligned.yml b/changelogs/unreleased/61323-snippet-copy-icon-button-is-misaligned.yml
new file mode 100644
index 00000000000..94666ac12ec
--- /dev/null
+++ b/changelogs/unreleased/61323-snippet-copy-icon-button-is-misaligned.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve Snippet icon button is misaligned
+merge_request: 28522
+author:
+type: other
diff --git a/changelogs/unreleased/61324-non-project-snippet-new-snippet-button-should-be-green-outline.yml b/changelogs/unreleased/61324-non-project-snippet-new-snippet-button-should-be-green-outline.yml
new file mode 100644
index 00000000000..a7f5706058d
--- /dev/null
+++ b/changelogs/unreleased/61324-non-project-snippet-new-snippet-button-should-be-green-outline.yml
@@ -0,0 +1,5 @@
+---
+title: Give New Snippet button green outline
+merge_request: 28559
+author:
+type: other
diff --git a/changelogs/unreleased/61339-Add-underline-to-attach-a-file.yml b/changelogs/unreleased/61339-Add-underline-to-attach-a-file.yml
new file mode 100644
index 00000000000..e446459ffc8
--- /dev/null
+++ b/changelogs/unreleased/61339-Add-underline-to-attach-a-file.yml
@@ -0,0 +1,5 @@
+---
+title: Add hover and focus to Attach a file
+merge_request: 28682
+author:
+type: fixed
diff --git a/changelogs/unreleased/61393-emoji-button.yml b/changelogs/unreleased/61393-emoji-button.yml
new file mode 100644
index 00000000000..2bcfde308db
--- /dev/null
+++ b/changelogs/unreleased/61393-emoji-button.yml
@@ -0,0 +1,5 @@
+---
+title: Change default color of award emoji button
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/61441.yml b/changelogs/unreleased/61441.yml
new file mode 100644
index 00000000000..2ad0c6f62d3
--- /dev/null
+++ b/changelogs/unreleased/61441.yml
@@ -0,0 +1,5 @@
+---
+title: Allow user to set primary email first when 2FA is required
+merge_request: 28097
+author: Kartikey Tanna
+type: fixed
diff --git a/changelogs/unreleased/61511-add-expand-collapse-to-project-operation-settings.yml b/changelogs/unreleased/61511-add-expand-collapse-to-project-operation-settings.yml
new file mode 100644
index 00000000000..1a3a019e1f4
--- /dev/null
+++ b/changelogs/unreleased/61511-add-expand-collapse-to-project-operation-settings.yml
@@ -0,0 +1,5 @@
+---
+title: Add expand/collapse to error tracking settings
+merge_request: 28619
+author:
+type: added
diff --git a/changelogs/unreleased/61565-merge-request-discussion-text-jumps-when-resolved.yml b/changelogs/unreleased/61565-merge-request-discussion-text-jumps-when-resolved.yml
new file mode 100644
index 00000000000..718604c9ceb
--- /dev/null
+++ b/changelogs/unreleased/61565-merge-request-discussion-text-jumps-when-resolved.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve Merge request discussion text jumps when resolved
+merge_request: 28995
+author:
+type: fixed
diff --git a/changelogs/unreleased/61606-support-string-piwik-website-ids.yml b/changelogs/unreleased/61606-support-string-piwik-website-ids.yml
new file mode 100644
index 00000000000..5c525294132
--- /dev/null
+++ b/changelogs/unreleased/61606-support-string-piwik-website-ids.yml
@@ -0,0 +1,5 @@
+---
+title: "Supports Matomo/Piwik string website ID (\"Protect Track ID\" plugin)"
+merge_request: 28214
+author: DUVERGIER Claude
+type: fixed \ No newline at end of file
diff --git a/changelogs/unreleased/61629-dependency-installation-error-on-fsevents-1-2-4-with-node-js-12.yml b/changelogs/unreleased/61629-dependency-installation-error-on-fsevents-1-2-4-with-node-js-12.yml
new file mode 100644
index 00000000000..bbe43760953
--- /dev/null
+++ b/changelogs/unreleased/61629-dependency-installation-error-on-fsevents-1-2-4-with-node-js-12.yml
@@ -0,0 +1,5 @@
+---
+title: Update indirect dependency fsevents from 1.2.4 to 1.2.9
+merge_request: 28220
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/61639-flaky-spec-issue-boards-labels-creates-project-label-spec-features-boards-sidebar_spec-rb-350.yml b/changelogs/unreleased/61639-flaky-spec-issue-boards-labels-creates-project-label-spec-features-boards-sidebar_spec-rb-350.yml
new file mode 100644
index 00000000000..9b4f13353f5
--- /dev/null
+++ b/changelogs/unreleased/61639-flaky-spec-issue-boards-labels-creates-project-label-spec-features-boards-sidebar_spec-rb-350.yml
@@ -0,0 +1,5 @@
+---
+title: Fix dropdown position when loading remote data
+merge_request: 28526
+author:
+type: fixed
diff --git a/changelogs/unreleased/61697-add-project-id-to-le-common-name.yml b/changelogs/unreleased/61697-add-project-id-to-le-common-name.yml
new file mode 100644
index 00000000000..8ffa8d0a51a
--- /dev/null
+++ b/changelogs/unreleased/61697-add-project-id-to-le-common-name.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent common name collisions when requesting multiple Let's Encrypt certificates concurrently
+merge_request: 28373
+author:
+type: fixed
diff --git a/changelogs/unreleased/61788-predefined-colours-dont-have-descriptive-labels.yml b/changelogs/unreleased/61788-predefined-colours-dont-have-descriptive-labels.yml
new file mode 100644
index 00000000000..25c83d24007
--- /dev/null
+++ b/changelogs/unreleased/61788-predefined-colours-dont-have-descriptive-labels.yml
@@ -0,0 +1,5 @@
+---
+title: Adds a text label to color pickers to improve accessibility.
+merge_request: 28343
+author: Chris Toynbee
+type: changed
diff --git a/changelogs/unreleased/61795-fix-error-when-moving-issues.yml b/changelogs/unreleased/61795-fix-error-when-moving-issues.yml
new file mode 100644
index 00000000000..6812baa07c3
--- /dev/null
+++ b/changelogs/unreleased/61795-fix-error-when-moving-issues.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unintended error message shown when moving issues
+merge_request: 28317
+author:
+type: fixed
diff --git a/changelogs/unreleased/61821-tooltip-consistency.yml b/changelogs/unreleased/61821-tooltip-consistency.yml
new file mode 100644
index 00000000000..9b131907ebf
--- /dev/null
+++ b/changelogs/unreleased/61821-tooltip-consistency.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve Tooltip Consistency
+merge_request: 28839
+author:
+type: fixed
diff --git a/changelogs/unreleased/61827-prevent-user-popover-icon-shrink.yml b/changelogs/unreleased/61827-prevent-user-popover-icon-shrink.yml
new file mode 100644
index 00000000000..4d6464eed52
--- /dev/null
+++ b/changelogs/unreleased/61827-prevent-user-popover-icon-shrink.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent icons from shrinking in User popover when contents exceed container
+merge_request: 28696
+author:
+type: fixed
diff --git a/changelogs/unreleased/61880-download-btn-group.yml b/changelogs/unreleased/61880-download-btn-group.yml
new file mode 100644
index 00000000000..c1f6b2767c6
--- /dev/null
+++ b/changelogs/unreleased/61880-download-btn-group.yml
@@ -0,0 +1,5 @@
+---
+title: Group download buttons into a .btn-group
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/61914-fix-emojis-urls.yml b/changelogs/unreleased/61914-fix-emojis-urls.yml
new file mode 100644
index 00000000000..578edf4a063
--- /dev/null
+++ b/changelogs/unreleased/61914-fix-emojis-urls.yml
@@ -0,0 +1,5 @@
+---
+title: Fix emojis URLs
+merge_request: 28371
+author:
+type: fixed
diff --git a/changelogs/unreleased/61928-remove-throttle-from-dirty-submit.yml b/changelogs/unreleased/61928-remove-throttle-from-dirty-submit.yml
new file mode 100644
index 00000000000..f8ef5dbb53b
--- /dev/null
+++ b/changelogs/unreleased/61928-remove-throttle-from-dirty-submit.yml
@@ -0,0 +1,6 @@
+---
+title: Fix issue that causes "Save changes" button in project settings pages to be
+ enabled/disabled incorrectly when changes are made to the form
+merge_request: 28377
+author:
+type: fixed
diff --git a/changelogs/unreleased/61960-translatable-strings-in-issue-closure-emails.yml b/changelogs/unreleased/61960-translatable-strings-in-issue-closure-emails.yml
new file mode 100644
index 00000000000..50b3efba0a5
--- /dev/null
+++ b/changelogs/unreleased/61960-translatable-strings-in-issue-closure-emails.yml
@@ -0,0 +1,5 @@
+---
+title: I18n for issue closure reason in emails
+merge_request: 28489
+author: Michał Zając
+type: changed
diff --git a/changelogs/unreleased/61988-collapse-icon-on-merge-request-diff-larger-than-profile-picture.yml b/changelogs/unreleased/61988-collapse-icon-on-merge-request-diff-larger-than-profile-picture.yml
new file mode 100644
index 00000000000..4d2f73ce2ff
--- /dev/null
+++ b/changelogs/unreleased/61988-collapse-icon-on-merge-request-diff-larger-than-profile-picture.yml
@@ -0,0 +1,5 @@
+---
+title: Change collapse icon size to size of profile picture
+merge_request: 28512
+author:
+type: other
diff --git a/changelogs/unreleased/61990-spinner.yml b/changelogs/unreleased/61990-spinner.yml
new file mode 100644
index 00000000000..27d35e56cc9
--- /dev/null
+++ b/changelogs/unreleased/61990-spinner.yml
@@ -0,0 +1,5 @@
+---
+title: Updates loading icon in commits page
+merge_request: 28475
+author:
+type: fixed
diff --git a/changelogs/unreleased/62061-note-icon-color.yml b/changelogs/unreleased/62061-note-icon-color.yml
new file mode 100644
index 00000000000..5bfea1a9ed3
--- /dev/null
+++ b/changelogs/unreleased/62061-note-icon-color.yml
@@ -0,0 +1,5 @@
+---
+title: Update icon color to match design system, pass accessibility
+merge_request: 28498
+author: Jarek Ostrowski @jareko
+type: fixed
diff --git a/changelogs/unreleased/62091-remove-time-windows-flag.yml b/changelogs/unreleased/62091-remove-time-windows-flag.yml
new file mode 100644
index 00000000000..c6c11328312
--- /dev/null
+++ b/changelogs/unreleased/62091-remove-time-windows-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Allow users to specify a time range on metrics dashboard
+merge_request: 28670
+author:
+type: added
diff --git a/changelogs/unreleased/62092-missing-padding-next-to-time-windows-dropdown-on-metrics-dashboard.yml b/changelogs/unreleased/62092-missing-padding-next-to-time-windows-dropdown-on-metrics-dashboard.yml
new file mode 100644
index 00000000000..3317d505924
--- /dev/null
+++ b/changelogs/unreleased/62092-missing-padding-next-to-time-windows-dropdown-on-metrics-dashboard.yml
@@ -0,0 +1,5 @@
+---
+title: Added padding to time window dropdown in monitor dashboard
+merge_request: 28897
+author:
+type: fixed
diff --git a/changelogs/unreleased/62107-fix-detail-page-header-height.yml b/changelogs/unreleased/62107-fix-detail-page-header-height.yml
new file mode 100644
index 00000000000..3723f323bcc
--- /dev/null
+++ b/changelogs/unreleased/62107-fix-detail-page-header-height.yml
@@ -0,0 +1,5 @@
+---
+title: Fix the height of the page headers on issues/merge request/snippets pages
+merge_request: 28650
+author: Erik van der Gaag
+type: fixed
diff --git a/changelogs/unreleased/62116-performance-issue-502-errors-on-rendering-of-issues-with-heavy-markdown-contents.yml b/changelogs/unreleased/62116-performance-issue-502-errors-on-rendering-of-issues-with-heavy-markdown-contents.yml
new file mode 100644
index 00000000000..9596f487116
--- /dev/null
+++ b/changelogs/unreleased/62116-performance-issue-502-errors-on-rendering-of-issues-with-heavy-markdown-contents.yml
@@ -0,0 +1,6 @@
+---
+title: Fix performance issue with large Markdown content in issue or merge request
+ description
+merge_request: 28597
+author:
+type: performance
diff --git a/changelogs/unreleased/62124-new-threaded-discussion-design.yml b/changelogs/unreleased/62124-new-threaded-discussion-design.yml
new file mode 100644
index 00000000000..6614e05be74
--- /dev/null
+++ b/changelogs/unreleased/62124-new-threaded-discussion-design.yml
@@ -0,0 +1,5 @@
+---
+title: Implement borderless discussion design with new reply field
+merge_request: 28580
+author:
+type: added
diff --git a/changelogs/unreleased/62134-fix-non-wraping-project-description.yml b/changelogs/unreleased/62134-fix-non-wraping-project-description.yml
new file mode 100644
index 00000000000..8c734c526fe
--- /dev/null
+++ b/changelogs/unreleased/62134-fix-non-wraping-project-description.yml
@@ -0,0 +1,5 @@
+---
+title: Correctly word-wrapping project descriptions with very long words
+merge_request: 28695
+author: Erik van der Gaag
+type: fixed
diff --git a/changelogs/unreleased/62144-fix-option-dropdown-button-size.yml b/changelogs/unreleased/62144-fix-option-dropdown-button-size.yml
new file mode 100644
index 00000000000..86d8f4536f9
--- /dev/null
+++ b/changelogs/unreleased/62144-fix-option-dropdown-button-size.yml
@@ -0,0 +1,5 @@
+---
+title: Fix inconsistent option dropdown button height to match adjacent button
+merge_request: 29096
+author:
+type: fixed
diff --git a/changelogs/unreleased/62154-fe-create-fix-long-branch-name-in-dropdown.yml b/changelogs/unreleased/62154-fe-create-fix-long-branch-name-in-dropdown.yml
new file mode 100644
index 00000000000..1d951c1dc24
--- /dev/null
+++ b/changelogs/unreleased/62154-fe-create-fix-long-branch-name-in-dropdown.yml
@@ -0,0 +1,6 @@
+---
+title: Add support to view entirety of long branch name in dropdown instead of it
+ being cut off
+merge_request: 29069
+author:
+type: fixed
diff --git a/changelogs/unreleased/62227-webkit-icon-overlap.yml b/changelogs/unreleased/62227-webkit-icon-overlap.yml
new file mode 100644
index 00000000000..47d7583f4c2
--- /dev/null
+++ b/changelogs/unreleased/62227-webkit-icon-overlap.yml
@@ -0,0 +1,5 @@
+---
+title: Add style to disable webkit icons for search inputs
+merge_request: 28833
+author: Jarek Ostrowski @jareko
+type: fixed
diff --git a/changelogs/unreleased/62253-add-kubernetes-logs-to-monitoring-ui.yml b/changelogs/unreleased/62253-add-kubernetes-logs-to-monitoring-ui.yml
new file mode 100644
index 00000000000..c01106a15ec
--- /dev/null
+++ b/changelogs/unreleased/62253-add-kubernetes-logs-to-monitoring-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Add Kubernetes logs to Admin Logs UI
+merge_request: 28685
+author:
+type: added
diff --git a/changelogs/unreleased/62300-target-area-for-dropdown-list-items-is-too-small-on-metrics-dashboard.yml b/changelogs/unreleased/62300-target-area-for-dropdown-list-items-is-too-small-on-metrics-dashboard.yml
new file mode 100644
index 00000000000..7944e6faa27
--- /dev/null
+++ b/changelogs/unreleased/62300-target-area-for-dropdown-list-items-is-too-small-on-metrics-dashboard.yml
@@ -0,0 +1,5 @@
+---
+title: Enlarge metrics time-window dropdown links
+merge_request: 29458
+author:
+type: fixed
diff --git a/changelogs/unreleased/62408-dropdown-truncate.yml b/changelogs/unreleased/62408-dropdown-truncate.yml
new file mode 100644
index 00000000000..7204016efdf
--- /dev/null
+++ b/changelogs/unreleased/62408-dropdown-truncate.yml
@@ -0,0 +1,5 @@
+---
+title: Fix job name in graph dropdown overflowing
+merge_request: 28824
+author:
+type: fixed
diff --git a/changelogs/unreleased/62418-project-default-git-depth.yml b/changelogs/unreleased/62418-project-default-git-depth.yml
new file mode 100644
index 00000000000..b5647cd0859
--- /dev/null
+++ b/changelogs/unreleased/62418-project-default-git-depth.yml
@@ -0,0 +1,5 @@
+---
+title: Add project level git depth CI/CD setting
+merge_request: 28919
+author:
+type: added
diff --git a/changelogs/unreleased/62432-fix-participants-wrapping.yml b/changelogs/unreleased/62432-fix-participants-wrapping.yml
new file mode 100644
index 00000000000..a7e4bd372de
--- /dev/null
+++ b/changelogs/unreleased/62432-fix-participants-wrapping.yml
@@ -0,0 +1,5 @@
+---
+title: Fix participants list wrapping
+merge_request: 28873
+author:
+type: fixed
diff --git a/changelogs/unreleased/62485-label-weights.yml b/changelogs/unreleased/62485-label-weights.yml
new file mode 100644
index 00000000000..354b18be11e
--- /dev/null
+++ b/changelogs/unreleased/62485-label-weights.yml
@@ -0,0 +1,5 @@
+---
+title: Give labels consistent weight
+merge_request: 28895
+author:
+type: fixed
diff --git a/changelogs/unreleased/62487-external-policy-desc.yml b/changelogs/unreleased/62487-external-policy-desc.yml
new file mode 100644
index 00000000000..2e787b89db1
--- /dev/null
+++ b/changelogs/unreleased/62487-external-policy-desc.yml
@@ -0,0 +1,5 @@
+---
+title: Move text under p tag
+merge_request: 28901
+author:
+type: fixed
diff --git a/changelogs/unreleased/62656-adjusted-dropdown-styles.yml b/changelogs/unreleased/62656-adjusted-dropdown-styles.yml
new file mode 100644
index 00000000000..36f14ae2741
--- /dev/null
+++ b/changelogs/unreleased/62656-adjusted-dropdown-styles.yml
@@ -0,0 +1,5 @@
+---
+title: "changed the styles on `Add List` dropdown to look more like the EE vesion"
+merge_request: 29338
+author: Michel Engelen
+type: changed
diff --git a/changelogs/unreleased/62684-add-index-public-email-on-users.yml b/changelogs/unreleased/62684-add-index-public-email-on-users.yml
new file mode 100644
index 00000000000..56b5f91da21
--- /dev/null
+++ b/changelogs/unreleased/62684-add-index-public-email-on-users.yml
@@ -0,0 +1,5 @@
+---
+title: Add index on public_email for users
+merge_request: 29430
+author:
+type: performance
diff --git a/changelogs/unreleased/62788-clean-up-pagination.yml b/changelogs/unreleased/62788-clean-up-pagination.yml
new file mode 100644
index 00000000000..05e3a4527b8
--- /dev/null
+++ b/changelogs/unreleased/62788-clean-up-pagination.yml
@@ -0,0 +1,5 @@
+---
+title: Moves the table pagination shared component
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/62788-graphql-pagination.yml b/changelogs/unreleased/62788-graphql-pagination.yml
new file mode 100644
index 00000000000..a7bc317a08f
--- /dev/null
+++ b/changelogs/unreleased/62788-graphql-pagination.yml
@@ -0,0 +1,5 @@
+---
+title: Adds pagination component for graphql api
+merge_request: 29277
+author:
+type: added
diff --git a/changelogs/unreleased/62847-url-for-the-next-request-with-pagination-is-missing-port.yml b/changelogs/unreleased/62847-url-for-the-next-request-with-pagination-is-missing-port.yml
new file mode 100644
index 00000000000..fca92a0d4dc
--- /dev/null
+++ b/changelogs/unreleased/62847-url-for-the-next-request-with-pagination-is-missing-port.yml
@@ -0,0 +1,5 @@
+---
+title: Include the port in the URLs of the API Link headers
+merge_request: 29267
+author:
+type: fixed
diff --git a/changelogs/unreleased/62974-follow-up-from-wip-align-merge-request-icons-and-text.yml b/changelogs/unreleased/62974-follow-up-from-wip-align-merge-request-icons-and-text.yml
new file mode 100644
index 00000000000..811986e6857
--- /dev/null
+++ b/changelogs/unreleased/62974-follow-up-from-wip-align-merge-request-icons-and-text.yml
@@ -0,0 +1,5 @@
+---
+title: 'Make margin between buttons consistent'
+merge_request: 29378
+author:
+type: other
diff --git a/changelogs/unreleased/8723-geo-remove-gitlab-lfstoken-legacyredisdevisetoken-implementation-and-usage-geo.yml b/changelogs/unreleased/8723-geo-remove-gitlab-lfstoken-legacyredisdevisetoken-implementation-and-usage-geo.yml
new file mode 100644
index 00000000000..173c7d9383e
--- /dev/null
+++ b/changelogs/unreleased/8723-geo-remove-gitlab-lfstoken-legacyredisdevisetoken-implementation-and-usage-geo.yml
@@ -0,0 +1,5 @@
+---
+title: 'Geo: Remove Gitlab::LfsToken::LegacyRedisDeviseToken implementation and usage'
+merge_request: 28546
+author:
+type: changed
diff --git a/changelogs/unreleased/9121-sort-relative-position.yml b/changelogs/unreleased/9121-sort-relative-position.yml
new file mode 100644
index 00000000000..adc9e87e5bb
--- /dev/null
+++ b/changelogs/unreleased/9121-sort-relative-position.yml
@@ -0,0 +1,5 @@
+---
+title: Allow issue list to be sorted by relative order
+merge_request: 28566
+author:
+type: added
diff --git a/changelogs/unreleased/9186-implement-atmtwps-state-to-mr-widget.yml b/changelogs/unreleased/9186-implement-atmtwps-state-to-mr-widget.yml
new file mode 100644
index 00000000000..2c1d56f197e
--- /dev/null
+++ b/changelogs/unreleased/9186-implement-atmtwps-state-to-mr-widget.yml
@@ -0,0 +1,5 @@
+---
+title: Update the merge request widget's "Merge" button to support merge trains
+merge_request: 27594
+author:
+type: added
diff --git a/changelogs/unreleased/9578-adjust-milestone-completion-rate.yml b/changelogs/unreleased/9578-adjust-milestone-completion-rate.yml
new file mode 100644
index 00000000000..0694e1462cf
--- /dev/null
+++ b/changelogs/unreleased/9578-adjust-milestone-completion-rate.yml
@@ -0,0 +1,5 @@
+---
+title: Adjust milestone completion rate to be based on issues count.
+merge_request: 28777
+author:
+type: changed
diff --git a/changelogs/unreleased/9978-moved-code-differences-from-EE-to-CE.yml b/changelogs/unreleased/9978-moved-code-differences-from-EE-to-CE.yml
new file mode 100644
index 00000000000..821e5d70dca
--- /dev/null
+++ b/changelogs/unreleased/9978-moved-code-differences-from-EE-to-CE.yml
@@ -0,0 +1,5 @@
+---
+title: "Moved EE/CE code differences for `app/assets/javascripts/gl_dropdown.js` into CE"
+merge_request: 28711
+author: Michel Engelen
+type: other
diff --git a/changelogs/unreleased/MaxWinterstein-master-patch-23232.yml b/changelogs/unreleased/MaxWinterstein-master-patch-23232.yml
deleted file mode 100644
index 8fb9f1057fe..00000000000
--- a/changelogs/unreleased/MaxWinterstein-master-patch-23232.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Unify behaviour of 'Copy commit SHA to clipboard' to use full commit SHA.
-merge_request: 25829
-author: Max Winterstein
-type: changed
diff --git a/changelogs/unreleased/_acet-related-mrs-widget-rewrite.yml b/changelogs/unreleased/_acet-related-mrs-widget-rewrite.yml
deleted file mode 100644
index b773eb2720c..00000000000
--- a/changelogs/unreleased/_acet-related-mrs-widget-rewrite.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Rewrite related MRs widget with Vue
-merge_request: 27027
-author:
-type: other
diff --git a/changelogs/unreleased/abstract-auto-merge.yml b/changelogs/unreleased/abstract-auto-merge.yml
new file mode 100644
index 00000000000..d3069a3e500
--- /dev/null
+++ b/changelogs/unreleased/abstract-auto-merge.yml
@@ -0,0 +1,5 @@
+---
+title: Refactor and abstract Auto Merge Processes
+merge_request: 28595
+author:
+type: other
diff --git a/changelogs/unreleased/ac-63020-typeerror-nil-can-t-be-coerced-into-integer.yml b/changelogs/unreleased/ac-63020-typeerror-nil-can-t-be-coerced-into-integer.yml
new file mode 100644
index 00000000000..51ac2358fba
--- /dev/null
+++ b/changelogs/unreleased/ac-63020-typeerror-nil-can-t-be-coerced-into-integer.yml
@@ -0,0 +1,5 @@
+---
+title: Fix nil coercion updating storage size on project statistics
+merge_request: 29425
+author:
+type: fixed
diff --git a/changelogs/unreleased/ac-graphql-stats.yml b/changelogs/unreleased/ac-graphql-stats.yml
new file mode 100644
index 00000000000..8837dce4d89
--- /dev/null
+++ b/changelogs/unreleased/ac-graphql-stats.yml
@@ -0,0 +1,5 @@
+---
+title: Add Namespace and ProjectStatistics to GraphQL API
+merge_request: 28277
+author:
+type: added
diff --git a/changelogs/unreleased/ac-graphql-wikisize.yml b/changelogs/unreleased/ac-graphql-wikisize.yml
new file mode 100644
index 00000000000..be9c347ec21
--- /dev/null
+++ b/changelogs/unreleased/ac-graphql-wikisize.yml
@@ -0,0 +1,5 @@
+---
+title: Expose wiki_size on GraphQL API
+merge_request: 29123
+author:
+type: added
diff --git a/changelogs/unreleased/ac-namespaces-stats-no-coalesce.yml b/changelogs/unreleased/ac-namespaces-stats-no-coalesce.yml
new file mode 100644
index 00000000000..bd005206d4e
--- /dev/null
+++ b/changelogs/unreleased/ac-namespaces-stats-no-coalesce.yml
@@ -0,0 +1,5 @@
+---
+title: Forbid NULL in project_statistics.packages_size
+merge_request: 28400
+author:
+type: other
diff --git a/changelogs/unreleased/add-allow_failure-to-job-api.yml b/changelogs/unreleased/add-allow_failure-to-job-api.yml
new file mode 100644
index 00000000000..5dd2b9708c5
--- /dev/null
+++ b/changelogs/unreleased/add-allow_failure-to-job-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add allow_failure attribute to Job API
+merge_request: 28406
+author:
+type: added
diff --git a/changelogs/unreleased/add-branch-to-project-search-api.yml b/changelogs/unreleased/add-branch-to-project-search-api.yml
new file mode 100644
index 00000000000..74cff94ab76
--- /dev/null
+++ b/changelogs/unreleased/add-branch-to-project-search-api.yml
@@ -0,0 +1,5 @@
+---
+title: Added ref querystring parameter to project search API to allow searching on branches/tags other than the default
+merge_request: 28069
+author: Lee Tickett
+type: added
diff --git a/changelogs/unreleased/add-constraint-for-milestone-dates.yml b/changelogs/unreleased/add-constraint-for-milestone-dates.yml
new file mode 100644
index 00000000000..485149cf62e
--- /dev/null
+++ b/changelogs/unreleased/add-constraint-for-milestone-dates.yml
@@ -0,0 +1,5 @@
+---
+title: Limit milestone dates to before year 9999
+merge_request: 28742
+author: Luke Picciau
+type: fixed
diff --git a/changelogs/unreleased/add-lfs-blob-ids-to-tree-type.yml b/changelogs/unreleased/add-lfs-blob-ids-to-tree-type.yml
new file mode 100644
index 00000000000..14a5ef1cef3
--- /dev/null
+++ b/changelogs/unreleased/add-lfs-blob-ids-to-tree-type.yml
@@ -0,0 +1,5 @@
+---
+title: Add LFS oid to GraphQL blob type
+merge_request: 28666
+author:
+type: added
diff --git a/changelogs/unreleased/add-warning-to-backup-rake-task.yml b/changelogs/unreleased/add-warning-to-backup-rake-task.yml
new file mode 100644
index 00000000000..7ddeae3f9fd
--- /dev/null
+++ b/changelogs/unreleased/add-warning-to-backup-rake-task.yml
@@ -0,0 +1,5 @@
+---
+title: Add warning that gitlab-secrets isn't included in backup
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/add-wiki-size-to-statistics.yml b/changelogs/unreleased/add-wiki-size-to-statistics.yml
new file mode 100644
index 00000000000..85b6d7a1774
--- /dev/null
+++ b/changelogs/unreleased/add-wiki-size-to-statistics.yml
@@ -0,0 +1,5 @@
+---
+title: Add wiki size to project statistics
+merge_request: 25321
+author: Peter Marko
+type: added
diff --git a/changelogs/unreleased/add_backtrace_to_kubernetes_log.yml b/changelogs/unreleased/add_backtrace_to_kubernetes_log.yml
deleted file mode 100644
index 26b8ac4b1ef..00000000000
--- a/changelogs/unreleased/add_backtrace_to_kubernetes_log.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Show error backtrace when logging errors to kubernetes.log
-merge_request: 25726
-author:
-type: other
diff --git a/changelogs/unreleased/allow-emoji-in-references.yml b/changelogs/unreleased/allow-emoji-in-references.yml
new file mode 100644
index 00000000000..3116b346c00
--- /dev/null
+++ b/changelogs/unreleased/allow-emoji-in-references.yml
@@ -0,0 +1,5 @@
+---
+title: Allow references to labels and milestones to contain emoji
+merge_request: 29284
+author:
+type: changed
diff --git a/changelogs/unreleased/allow-filtering-labels-by-a-single-character.yml b/changelogs/unreleased/allow-filtering-labels-by-a-single-character.yml
deleted file mode 100644
index 31165bbadb7..00000000000
--- a/changelogs/unreleased/allow-filtering-labels-by-a-single-character.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow filtering labels list by one or two characters
-merge_request: 26012
-author:
-type: changed
diff --git a/changelogs/unreleased/allow-ref-name-caching-projects-controller.yml b/changelogs/unreleased/allow-ref-name-caching-projects-controller.yml
deleted file mode 100644
index 61236b9b82b..00000000000
--- a/changelogs/unreleased/allow-ref-name-caching-projects-controller.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable FindCommit caching for project and commits pages
-merge_request: 27048
-author:
-type: performance
diff --git a/changelogs/unreleased/always-link-instance-configuration.yml b/changelogs/unreleased/always-link-instance-configuration.yml
deleted file mode 100644
index 3f08747edf7..00000000000
--- a/changelogs/unreleased/always-link-instance-configuration.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Always show instance configuration link
-merge_request: 26783
-author: Bastian Blank
-type: fixed
diff --git a/changelogs/unreleased/always-show-pipelines-must-succeed-checkbox.yml b/changelogs/unreleased/always-show-pipelines-must-succeed-checkbox.yml
new file mode 100644
index 00000000000..d60dd65be8a
--- /dev/null
+++ b/changelogs/unreleased/always-show-pipelines-must-succeed-checkbox.yml
@@ -0,0 +1,5 @@
+---
+title: Always show "Pipelines must succeed" checkbox
+merge_request: 28651
+author:
+type: fixed
diff --git a/changelogs/unreleased/antonyliu-i18n-user-profile.yml b/changelogs/unreleased/antonyliu-i18n-user-profile.yml
new file mode 100644
index 00000000000..f9065ee5697
--- /dev/null
+++ b/changelogs/unreleased/antonyliu-i18n-user-profile.yml
@@ -0,0 +1,5 @@
+---
+title: 'i18n: externalize strings from user profile settings'
+merge_request: 28088
+author: Antony Liu
+type: other
diff --git a/changelogs/unreleased/api_make_protected_boolean_type.yml b/changelogs/unreleased/api_make_protected_boolean_type.yml
new file mode 100644
index 00000000000..765edea6427
--- /dev/null
+++ b/changelogs/unreleased/api_make_protected_boolean_type.yml
@@ -0,0 +1,5 @@
+---
+title: 'API: change protected attribute type to Boolean'
+merge_request: 28766
+author:
+type: other
diff --git a/changelogs/unreleased/api_masked_variables.yml b/changelogs/unreleased/api_masked_variables.yml
new file mode 100644
index 00000000000..3605339cb91
--- /dev/null
+++ b/changelogs/unreleased/api_masked_variables.yml
@@ -0,0 +1,5 @@
+---
+title: 'API: Allow to get and set "masked" attribute for variables'
+merge_request: 28381
+author: Mathieu Parent
+type: added
diff --git a/changelogs/unreleased/asciidoc-include-directive.yml b/changelogs/unreleased/asciidoc-include-directive.yml
new file mode 100644
index 00000000000..58fe3666727
--- /dev/null
+++ b/changelogs/unreleased/asciidoc-include-directive.yml
@@ -0,0 +1,5 @@
+---
+title: Add support for AsciiDoc include directive
+merge_request: 28417
+author: "Jakub Jirutka & Guillaume Grossetie"
+type: added
diff --git a/changelogs/unreleased/auto-devops-kubernestes-bump1-11-10.yml b/changelogs/unreleased/auto-devops-kubernestes-bump1-11-10.yml
new file mode 100644
index 00000000000..9ba55719bdf
--- /dev/null
+++ b/changelogs/unreleased/auto-devops-kubernestes-bump1-11-10.yml
@@ -0,0 +1,5 @@
+---
+title: Bumps Kubernetes in Auto DevOps to 1.11.10
+merge_request: 28525
+author:
+type: other
diff --git a/changelogs/unreleased/avoid_es_loading_project_ci_status.yml b/changelogs/unreleased/avoid_es_loading_project_ci_status.yml
deleted file mode 100644
index 514909c730d..00000000000
--- a/changelogs/unreleased/avoid_es_loading_project_ci_status.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Avoid loading pipeline status in project search
-merge_request: 26342
-author:
-type: performance
diff --git a/changelogs/unreleased/backstage-gb-improve-jobs-controller-performance.yml b/changelogs/unreleased/backstage-gb-improve-jobs-controller-performance.yml
new file mode 100644
index 00000000000..2b5a3592775
--- /dev/null
+++ b/changelogs/unreleased/backstage-gb-improve-jobs-controller-performance.yml
@@ -0,0 +1,5 @@
+---
+title: Improve performance of jobs controller
+merge_request: 28093
+author:
+type: performance
diff --git a/changelogs/unreleased/bump-auto-devops-helm-2-14-0.yml b/changelogs/unreleased/bump-auto-devops-helm-2-14-0.yml
new file mode 100644
index 00000000000..ecfbc97a8c5
--- /dev/null
+++ b/changelogs/unreleased/bump-auto-devops-helm-2-14-0.yml
@@ -0,0 +1,5 @@
+---
+title: Bump Helm version in Auto-DevOps.gitlab-ci.yml to 2.14.0
+merge_request: 28527
+author:
+type: other
diff --git a/changelogs/unreleased/bvl-graphql-multiplex.yml b/changelogs/unreleased/bvl-graphql-multiplex.yml
new file mode 100644
index 00000000000..56d39e447a5
--- /dev/null
+++ b/changelogs/unreleased/bvl-graphql-multiplex.yml
@@ -0,0 +1,5 @@
+---
+title: Support multiplex GraphQL queries
+merge_request: 28273
+author:
+type: added
diff --git a/changelogs/unreleased/bvl-use-global-ids-graphql.yml b/changelogs/unreleased/bvl-use-global-ids-graphql.yml
new file mode 100644
index 00000000000..34cb65e6001
--- /dev/null
+++ b/changelogs/unreleased/bvl-use-global-ids-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Use global IDs when exposing GraphQL resources
+merge_request: 29080
+author:
+type: added
diff --git a/changelogs/unreleased/cancel-auto-merge-when-branch-is-changed.yml b/changelogs/unreleased/cancel-auto-merge-when-branch-is-changed.yml
new file mode 100644
index 00000000000..c3c6e4322a2
--- /dev/null
+++ b/changelogs/unreleased/cancel-auto-merge-when-branch-is-changed.yml
@@ -0,0 +1,5 @@
+---
+title: Cancel Auto Merge when target branch is changed
+merge_request: 29416
+author:
+type: fixed
diff --git a/changelogs/unreleased/cancel-auto-merge-when-merge-request-is-closed.yml b/changelogs/unreleased/cancel-auto-merge-when-merge-request-is-closed.yml
new file mode 100644
index 00000000000..d38046ebcbf
--- /dev/null
+++ b/changelogs/unreleased/cancel-auto-merge-when-merge-request-is-closed.yml
@@ -0,0 +1,5 @@
+---
+title: Cancel auto merge when merge request is closed
+merge_request: 28782
+author:
+type: fixed
diff --git a/changelogs/unreleased/ce-4681-autosave.yml b/changelogs/unreleased/ce-4681-autosave.yml
deleted file mode 100644
index 029954ec92b..00000000000
--- a/changelogs/unreleased/ce-4681-autosave.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Autosave description in epics
-merge_request: 27296
-author:
-type: added
diff --git a/changelogs/unreleased/ce-56153-error-tracking-counts.yml b/changelogs/unreleased/ce-56153-error-tracking-counts.yml
deleted file mode 100644
index fc3d8c01d7f..00000000000
--- a/changelogs/unreleased/ce-56153-error-tracking-counts.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add usage counts for error tracking feature
-merge_request: 25472
-author:
-type: added
diff --git a/changelogs/unreleased/ce-57402-add-issues-statistics-api-endpoints.yml b/changelogs/unreleased/ce-57402-add-issues-statistics-api-endpoints.yml
new file mode 100644
index 00000000000..a626193dc27
--- /dev/null
+++ b/changelogs/unreleased/ce-57402-add-issues-statistics-api-endpoints.yml
@@ -0,0 +1,5 @@
+---
+title: Add issues_statistics api endpoints and extend issues search api
+merge_request: 27366
+author:
+type: added
diff --git a/changelogs/unreleased/ce-jej-fix-git-http-with-sso-enforcement.yml b/changelogs/unreleased/ce-jej-fix-git-http-with-sso-enforcement.yml
new file mode 100644
index 00000000000..a795e33b00d
--- /dev/null
+++ b/changelogs/unreleased/ce-jej-fix-git-http-with-sso-enforcement.yml
@@ -0,0 +1,5 @@
+---
+title: Avoid setting Gitlab::Session on sessionless requests and Git HTTP
+merge_request: 29146
+author:
+type: fixed
diff --git a/changelogs/unreleased/ce-proj-settings-ok-avatar-only.yml b/changelogs/unreleased/ce-proj-settings-ok-avatar-only.yml
deleted file mode 100644
index 10475824a75..00000000000
--- a/changelogs/unreleased/ce-proj-settings-ok-avatar-only.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Change project avatar remove button to a link
-merge_request: 26589
-author:
-type: other
diff --git a/changelogs/unreleased/ce-proj-settings-ok-mr-settings-only.yml b/changelogs/unreleased/ce-proj-settings-ok-mr-settings-only.yml
deleted file mode 100644
index 4bbbc706e62..00000000000
--- a/changelogs/unreleased/ce-proj-settings-ok-mr-settings-only.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improve project merge request settings
-merge_request: 26495
-author:
-type: other
diff --git a/changelogs/unreleased/ce-quick-fix-58727-collapsed-sidebar-flyout-menu-items-don-t-appear-in-1200px-screen-size.yml b/changelogs/unreleased/ce-quick-fix-58727-collapsed-sidebar-flyout-menu-items-don-t-appear-in-1200px-screen-size.yml
new file mode 100644
index 00000000000..332105bb269
--- /dev/null
+++ b/changelogs/unreleased/ce-quick-fix-58727-collapsed-sidebar-flyout-menu-items-don-t-appear-in-1200px-screen-size.yml
@@ -0,0 +1,5 @@
+---
+title: Fix flyout nav on small viewports
+merge_request: 25998
+author:
+type: fixed
diff --git a/changelogs/unreleased/check-mergeability-in-merge-to-ref-service.yml b/changelogs/unreleased/check-mergeability-in-merge-to-ref-service.yml
deleted file mode 100644
index 9f615bbb54a..00000000000
--- a/changelogs/unreleased/check-mergeability-in-merge-to-ref-service.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Check mergeability in MergeToRefService
-merge_request: 26757
-author:
-type: changed
diff --git a/changelogs/unreleased/chore-remove-circuit-breaker-api.yml b/changelogs/unreleased/chore-remove-circuit-breaker-api.yml
new file mode 100644
index 00000000000..f9532be04c8
--- /dev/null
+++ b/changelogs/unreleased/chore-remove-circuit-breaker-api.yml
@@ -0,0 +1,5 @@
+---
+title: Remove the circuit breaker API
+merge_request: 28669
+author:
+type: removed
diff --git a/changelogs/unreleased/ci-lint-ssl-error.yml b/changelogs/unreleased/ci-lint-ssl-error.yml
deleted file mode 100644
index d59b9204357..00000000000
--- a/changelogs/unreleased/ci-lint-ssl-error.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Catch and report OpenSSL exceptions while fetching external configuration files
- in CI::Config
-merge_request: 26750
-author: Drew Cimino
-type: fixed
diff --git a/changelogs/unreleased/ci-variable-conjunction.yml b/changelogs/unreleased/ci-variable-conjunction.yml
new file mode 100644
index 00000000000..839c4285f3a
--- /dev/null
+++ b/changelogs/unreleased/ci-variable-conjunction.yml
@@ -0,0 +1,5 @@
+---
+title: Add support for && and || to CI Pipeline Expressions. Change CI variable expression matching for Lexeme::Pattern to eagerly return tokens.
+merge_request: 27925
+author: Martin Manelli
+type: added
diff --git a/changelogs/unreleased/copy-button-in-modals.yml b/changelogs/unreleased/copy-button-in-modals.yml
new file mode 100644
index 00000000000..bc18eb9ab26
--- /dev/null
+++ b/changelogs/unreleased/copy-button-in-modals.yml
@@ -0,0 +1,5 @@
+---
+title: Add a New Copy Button That Works in Modals
+merge_request: 28676
+author:
+type: added
diff --git a/changelogs/unreleased/create-label-and-list-checkbox.yml b/changelogs/unreleased/create-label-and-list-checkbox.yml
deleted file mode 100644
index 330372df1be..00000000000
--- a/changelogs/unreleased/create-label-and-list-checkbox.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Added "Add List" checkbox to create label dropdown to make creation of list optional'
-merge_request: 25716
-author: Tucker Chapman
-type: fixed
diff --git a/changelogs/unreleased/delay-update-statictics.yml b/changelogs/unreleased/delay-update-statictics.yml
deleted file mode 100644
index d0201fb6db8..00000000000
--- a/changelogs/unreleased/delay-update-statictics.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix the bug that the project statistics is not updated
-merge_request: 26854
-author: Hiroyuki Sato
-type: fixed
diff --git a/changelogs/unreleased/delete-release-when-delete-tag.yml b/changelogs/unreleased/delete-release-when-delete-tag.yml
deleted file mode 100644
index 58acd449bf1..00000000000
--- a/changelogs/unreleased/delete-release-when-delete-tag.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Releases will now be automatically deleted when deleting corresponding tag
-merge_request: 26530
-author:
-type: fixed
diff --git a/changelogs/unreleased/deploy-keys-ext.yml b/changelogs/unreleased/deploy-keys-ext.yml
deleted file mode 100644
index e1d2fe08425..00000000000
--- a/changelogs/unreleased/deploy-keys-ext.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Externalize admin deploy keys strings
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/dhiraj-fix-missing-deployment-rockets-in-monitoring-dashboard.yml b/changelogs/unreleased/dhiraj-fix-missing-deployment-rockets-in-monitoring-dashboard.yml
new file mode 100644
index 00000000000..12a21e818b4
--- /dev/null
+++ b/changelogs/unreleased/dhiraj-fix-missing-deployment-rockets-in-monitoring-dashboard.yml
@@ -0,0 +1,5 @@
+---
+title: Fix missing deployment rockets in monitor dashboard
+merge_request: 29574
+author:
+type: fixed
diff --git a/changelogs/unreleased/diff-whitespace-setting-changes.yml b/changelogs/unreleased/diff-whitespace-setting-changes.yml
new file mode 100644
index 00000000000..640e9e589df
--- /dev/null
+++ b/changelogs/unreleased/diff-whitespace-setting-changes.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed show whitespace button not refetching diff content
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/disallow-guests-to-access-releases.yml b/changelogs/unreleased/disallow-guests-to-access-releases.yml
deleted file mode 100644
index f2d518108d2..00000000000
--- a/changelogs/unreleased/disallow-guests-to-access-releases.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Disallow guest users from accessing Releases
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/display-junit-classname-in-modal.yml b/changelogs/unreleased/display-junit-classname-in-modal.yml
new file mode 100644
index 00000000000..c5140456e4e
--- /dev/null
+++ b/changelogs/unreleased/display-junit-classname-in-modal.yml
@@ -0,0 +1,5 @@
+---
+title: Display classname JUnit attribute in report modal
+merge_request: 28376
+author:
+type: added
diff --git a/changelogs/unreleased/dm-http-hostname-override.yml b/changelogs/unreleased/dm-http-hostname-override.yml
new file mode 100644
index 00000000000..f84f36a0010
--- /dev/null
+++ b/changelogs/unreleased/dm-http-hostname-override.yml
@@ -0,0 +1,5 @@
+---
+title: Protect Gitlab::HTTP against DNS rebinding attack
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/do-not-force-2fa.yml b/changelogs/unreleased/do-not-force-2fa.yml
deleted file mode 100644
index f9be40e8f37..00000000000
--- a/changelogs/unreleased/do-not-force-2fa.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Add link on two-factor authorization settings page to leave group that enforces
- two-factor authorization
-merge_request: 25731
-author:
-type: changed
diff --git a/changelogs/unreleased/do-not-reopen-merged-mr.yml b/changelogs/unreleased/do-not-reopen-merged-mr.yml
deleted file mode 100644
index 14d1455cca4..00000000000
--- a/changelogs/unreleased/do-not-reopen-merged-mr.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove a "reopen merge request button" on a "merged" merge request
-merge_request: 26965
-author: Hiroyuki Sato
-type: fixed
diff --git a/changelogs/unreleased/docs-add-chatops-request-doc.yml b/changelogs/unreleased/docs-add-chatops-request-doc.yml
new file mode 100644
index 00000000000..85ba86a73af
--- /dev/null
+++ b/changelogs/unreleased/docs-add-chatops-request-doc.yml
@@ -0,0 +1,5 @@
+---
+title: Add section to dev docs on accessing chatops
+merge_request: 28623
+author:
+type: other
diff --git a/changelogs/unreleased/downloading-expired-artifacts.yml b/changelogs/unreleased/downloading-expired-artifacts.yml
deleted file mode 100644
index 2f4b79ca106..00000000000
--- a/changelogs/unreleased/downloading-expired-artifacts.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: stop rendering download links for expired artifacts on the project tags page
-merge_request: 26753
-author: Drew Cimino
-type: fixed
diff --git a/changelogs/unreleased/drop-usage-of-leagcy-artifacts.yml b/changelogs/unreleased/drop-usage-of-leagcy-artifacts.yml
deleted file mode 100644
index d99187d8d41..00000000000
--- a/changelogs/unreleased/drop-usage-of-leagcy-artifacts.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Drop legacy artifacts usage as there are no leftovers
-merge_request: 24294
-author:
-type: performance
diff --git a/changelogs/unreleased/duplicate-related-mrs.yml b/changelogs/unreleased/duplicate-related-mrs.yml
deleted file mode 100644
index 0f5f6ede9f8..00000000000
--- a/changelogs/unreleased/duplicate-related-mrs.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove duplicates from issue related merge requests
-merge_request: 27067
-author:
-type: fixed
diff --git a/changelogs/unreleased/dz-patch-58.yml b/changelogs/unreleased/dz-patch-58.yml
new file mode 100644
index 00000000000..97ceadd303d
--- /dev/null
+++ b/changelogs/unreleased/dz-patch-58.yml
@@ -0,0 +1,5 @@
+---
+title: Replace Oxygen-Sans font with Noto Sans
+merge_request: 28322
+author:
+type: changed
diff --git a/changelogs/unreleased/dz-scope-project-routes.yml b/changelogs/unreleased/dz-scope-project-routes.yml
new file mode 100644
index 00000000000..66eb5d928f0
--- /dev/null
+++ b/changelogs/unreleased/dz-scope-project-routes.yml
@@ -0,0 +1,5 @@
+---
+title: Move some project routes under /-/ scope
+merge_request: 28435
+author:
+type: changed
diff --git a/changelogs/unreleased/ee-11040-added-conditional-rendering.yml b/changelogs/unreleased/ee-11040-added-conditional-rendering.yml
new file mode 100644
index 00000000000..7b06e43830f
--- /dev/null
+++ b/changelogs/unreleased/ee-11040-added-conditional-rendering.yml
@@ -0,0 +1,5 @@
+---
+title: "Added conditional rendering to `app/views/search/_form.html.haml` for CE/EE code base consistency"
+merge_request: 28883
+author: Michel Engelen
+type: other
diff --git a/changelogs/unreleased/ekigbo-extend-timezone-dropdown.yml b/changelogs/unreleased/ekigbo-extend-timezone-dropdown.yml
deleted file mode 100644
index 42bc320a542..00000000000
--- a/changelogs/unreleased/ekigbo-extend-timezone-dropdown.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Extend timezone dropdown
-merge_request: 26311
-author:
-type: changed
diff --git a/changelogs/unreleased/ensure_namespace.yml b/changelogs/unreleased/ensure_namespace.yml
new file mode 100644
index 00000000000..ce2a615af1f
--- /dev/null
+++ b/changelogs/unreleased/ensure_namespace.yml
@@ -0,0 +1,5 @@
+---
+title: AutoDevops function ensure_namespace() now explicitly tests the namespace
+merge_request: 29567
+author: Jack Lei
+type: fixed
diff --git a/changelogs/unreleased/expose-group-id-on-home-panel.yml b/changelogs/unreleased/expose-group-id-on-home-panel.yml
deleted file mode 100644
index 1efe15a6e1a..00000000000
--- a/changelogs/unreleased/expose-group-id-on-home-panel.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Expose group id on home panel
-merge_request: 25897
-author: Peter Marko
-type: added
diff --git a/changelogs/unreleased/expose-pipeline-variables-via-api.yml b/changelogs/unreleased/expose-pipeline-variables-via-api.yml
deleted file mode 100644
index f37bf0c5cd8..00000000000
--- a/changelogs/unreleased/expose-pipeline-variables-via-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Expose pipeline variables via API
-merge_request: 26501
-author: Agustin Henze <tin@redhat.com>
-type: added
diff --git a/changelogs/unreleased/expose-project-git-depth-via-api.yml b/changelogs/unreleased/expose-project-git-depth-via-api.yml
new file mode 100644
index 00000000000..e9d158fda16
--- /dev/null
+++ b/changelogs/unreleased/expose-project-git-depth-via-api.yml
@@ -0,0 +1,5 @@
+---
+title: Get and edit ci_default_git_depth via project API
+merge_request: 29353
+author:
+type: added
diff --git a/changelogs/unreleased/extend-cte-optimisations-to-projects.yml b/changelogs/unreleased/extend-cte-optimisations-to-projects.yml
deleted file mode 100644
index e5407127b2f..00000000000
--- a/changelogs/unreleased/extend-cte-optimisations-to-projects.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Speed up filtering issues in a project when searching
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/fe-fix-gl-dropdown-scrolling-to-top.yml b/changelogs/unreleased/fe-fix-gl-dropdown-scrolling-to-top.yml
new file mode 100644
index 00000000000..4125b4241e6
--- /dev/null
+++ b/changelogs/unreleased/fe-fix-gl-dropdown-scrolling-to-top.yml
@@ -0,0 +1,5 @@
+---
+title: Fix scrolling to top on assignee change
+merge_request: 29500
+author:
+type: fixed
diff --git a/changelogs/unreleased/feature-gb-serverless-switch-to-gitlabktl.yml b/changelogs/unreleased/feature-gb-serverless-switch-to-gitlabktl.yml
deleted file mode 100644
index 81cf5cb810d..00000000000
--- a/changelogs/unreleased/feature-gb-serverless-switch-to-gitlabktl.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use gitlabktl to build and deploy GitLab Serverless Functions
-merge_request: 26926
-author:
-type: added
diff --git a/changelogs/unreleased/feature-gb-use-gitlabktl-to-build-serverless-applications.yml b/changelogs/unreleased/feature-gb-use-gitlabktl-to-build-serverless-applications.yml
new file mode 100644
index 00000000000..443fff92f55
--- /dev/null
+++ b/changelogs/unreleased/feature-gb-use-gitlabktl-to-build-serverless-applications.yml
@@ -0,0 +1,5 @@
+---
+title: Use to 'gitlabktl' build serverless applications
+merge_request: 29258
+author:
+type: added
diff --git a/changelogs/unreleased/feature-require-2fa-for-all-entities-in-group.yml b/changelogs/unreleased/feature-require-2fa-for-all-entities-in-group.yml
new file mode 100644
index 00000000000..0abe777fb69
--- /dev/null
+++ b/changelogs/unreleased/feature-require-2fa-for-all-entities-in-group.yml
@@ -0,0 +1,4 @@
+title: Apply the group setting "require 2FA" across all subgroup members as well when changing the group setting
+merge_request: 24965
+author: rroger
+type: changed
diff --git a/changelogs/unreleased/feature-users-search-results.yml b/changelogs/unreleased/feature-users-search-results.yml
deleted file mode 100644
index 151d08bce12..00000000000
--- a/changelogs/unreleased/feature-users-search-results.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add users search results to global search
-merge_request: 21197
-author: Alexis Reigel
-type: added
diff --git a/changelogs/unreleased/feature-webide_escaping.yml b/changelogs/unreleased/feature-webide_escaping.yml
deleted file mode 100644
index 88fa1bd948e..00000000000
--- a/changelogs/unreleased/feature-webide_escaping.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed bug with hashes in urls in WebIDE
-merge_request: 54376
-author: Kieran Andrews
-type: fixed
diff --git a/changelogs/unreleased/filter-merge-requests-by-target-branch.yml b/changelogs/unreleased/filter-merge-requests-by-target-branch.yml
deleted file mode 100644
index d0aba631c96..00000000000
--- a/changelogs/unreleased/filter-merge-requests-by-target-branch.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add target branch filter to merge requests search bar
-merge_request: 24380
-author: Hiroyuki Sato
-type: added
diff --git a/changelogs/unreleased/fix-UI-links-to-route-map-info.yml b/changelogs/unreleased/fix-UI-links-to-route-map-info.yml
deleted file mode 100644
index bb506507080..00000000000
--- a/changelogs/unreleased/fix-UI-links-to-route-map-info.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix UI anchor links after docs refactor
-merge_request: 26890
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-allow-lower-case-issue-ids.yml b/changelogs/unreleased/fix-allow-lower-case-issue-ids.yml
new file mode 100644
index 00000000000..46fa90ccda0
--- /dev/null
+++ b/changelogs/unreleased/fix-allow-lower-case-issue-ids.yml
@@ -0,0 +1,5 @@
+---
+title: Allow lowercase prefix for Youtrack issue ids
+merge_request: 29057
+author: Matthias Baur
+type: fixed
diff --git a/changelogs/unreleased/fix-api-group-visibility.yml b/changelogs/unreleased/fix-api-group-visibility.yml
deleted file mode 100644
index 7fbdcd729c6..00000000000
--- a/changelogs/unreleased/fix-api-group-visibility.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix api group visibility
-merge_request: 26896
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-autodevops-postgres-versioning.yml b/changelogs/unreleased/fix-autodevops-postgres-versioning.yml
new file mode 100644
index 00000000000..8ddc70f6314
--- /dev/null
+++ b/changelogs/unreleased/fix-autodevops-postgres-versioning.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed ignored postgres version that occurs after the first autodevops deploy when specifying custom $POSTGRES_VERSION
+merge_request: 28735
+author: Brandon Dimcheff
+type: fixed
diff --git a/changelogs/unreleased/fix-container-scanning-on-k8s.yml b/changelogs/unreleased/fix-container-scanning-on-k8s.yml
deleted file mode 100644
index f4500370a0b..00000000000
--- a/changelogs/unreleased/fix-container-scanning-on-k8s.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix Container Scanning in Kubernetes Runners
-merge_request: 26793
-author:
-type: changed
diff --git a/changelogs/unreleased/fix-db-migrate-is-failed-on-mysql8.yml b/changelogs/unreleased/fix-db-migrate-is-failed-on-mysql8.yml
new file mode 100644
index 00000000000..63f134808e3
--- /dev/null
+++ b/changelogs/unreleased/fix-db-migrate-is-failed-on-mysql8.yml
@@ -0,0 +1,5 @@
+---
+title: Fix. `db:migrate` is failed on MySQL 8
+merge_request: 28351
+author: sue445
+type: fixed
diff --git a/changelogs/unreleased/fix-diverged-branch-locals.yml b/changelogs/unreleased/fix-diverged-branch-locals.yml
new file mode 100644
index 00000000000..719d669fad3
--- /dev/null
+++ b/changelogs/unreleased/fix-diverged-branch-locals.yml
@@ -0,0 +1,5 @@
+---
+title: Fix diverged branch locals
+merge_request: 29508
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-expand-full-file-on-image.yml b/changelogs/unreleased/fix-expand-full-file-on-image.yml
deleted file mode 100644
index a88d30cfa38..00000000000
--- a/changelogs/unreleased/fix-expand-full-file-on-image.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed expand full file button showing on images
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-flyout-navs.yml b/changelogs/unreleased/fix-flyout-navs.yml
new file mode 100644
index 00000000000..c21f1037f09
--- /dev/null
+++ b/changelogs/unreleased/fix-flyout-navs.yml
@@ -0,0 +1,5 @@
+---
+title: Fix sidebar flyout navigation
+merge_request: 29571
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-format-date-safari-ff.yml b/changelogs/unreleased/fix-format-date-safari-ff.yml
new file mode 100644
index 00000000000..e71ea2867f3
--- /dev/null
+++ b/changelogs/unreleased/fix-format-date-safari-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Throw an error when formatDate's input is invalid
+merge_request: 28713
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-gb-fix-serverless-apps-deployment-template.yml b/changelogs/unreleased/fix-gb-fix-serverless-apps-deployment-template.yml
new file mode 100644
index 00000000000..88656b7ef4c
--- /dev/null
+++ b/changelogs/unreleased/fix-gb-fix-serverless-apps-deployment-template.yml
@@ -0,0 +1,5 @@
+---
+title: Fix serverless apps deployments by bumping 'tm' version
+merge_request: 29254
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-gb-remove-serverless-app-build-policies-from-template.yml b/changelogs/unreleased/fix-gb-remove-serverless-app-build-policies-from-template.yml
new file mode 100644
index 00000000000..f51ec273a57
--- /dev/null
+++ b/changelogs/unreleased/fix-gb-remove-serverless-app-build-policies-from-template.yml
@@ -0,0 +1,5 @@
+---
+title: Remove build policies from serverless app template
+merge_request: 29253
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-hidden-statistics.yml b/changelogs/unreleased/fix-hidden-statistics.yml
deleted file mode 100644
index 4d99bd00136..00000000000
--- a/changelogs/unreleased/fix-hidden-statistics.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Show statistics also when repository is disabled
-merge_request: 26509
-author: Peter Marko
-type: fixed
diff --git a/changelogs/unreleased/fix-ide-web-worker-relative-url.yml b/changelogs/unreleased/fix-ide-web-worker-relative-url.yml
deleted file mode 100644
index 2accad68c4e..00000000000
--- a/changelogs/unreleased/fix-ide-web-worker-relative-url.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed Web IDE web workers not working with relative URLs
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-import-member-access.yml b/changelogs/unreleased/fix-import-member-access.yml
new file mode 100644
index 00000000000..5dc4ae738f8
--- /dev/null
+++ b/changelogs/unreleased/fix-import-member-access.yml
@@ -0,0 +1,5 @@
+---
+title: Fix issue importing members with owner access
+merge_request: 28636
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-import-param-ordering.yml b/changelogs/unreleased/fix-import-param-ordering.yml
new file mode 100644
index 00000000000..47e32cda977
--- /dev/null
+++ b/changelogs/unreleased/fix-import-param-ordering.yml
@@ -0,0 +1,5 @@
+---
+title: Fix order dependency with user params during imports
+merge_request: 28719
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-include-ci-yaml.yml b/changelogs/unreleased/fix-include-ci-yaml.yml
deleted file mode 100644
index 042413b89aa..00000000000
--- a/changelogs/unreleased/fix-include-ci-yaml.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix single string values for the 'include' keyword validation of gitlab-ci.yml.
-merge_request: 26998
-author: Paul Bonaud (@paulrbr)
-type: fixed
diff --git a/changelogs/unreleased/fix-issue-mr-badge.yml b/changelogs/unreleased/fix-issue-mr-badge.yml
new file mode 100644
index 00000000000..e777f52f173
--- /dev/null
+++ b/changelogs/unreleased/fix-issue-mr-badge.yml
@@ -0,0 +1,5 @@
+---
+title: Use grid and correct border radius for status badge
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/fix-issues-time-counter.yml b/changelogs/unreleased/fix-issues-time-counter.yml
deleted file mode 100644
index 76f17063db5..00000000000
--- a/changelogs/unreleased/fix-issues-time-counter.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Make time counters show 'just now' for everything under one minute
-merge_request: 25992
-author: Sergiu Marton
-type: changed
diff --git a/changelogs/unreleased/fix-merge-request-relations-with-pipeline-on-mwps.yml b/changelogs/unreleased/fix-merge-request-relations-with-pipeline-on-mwps.yml
deleted file mode 100644
index 9ccc79109d8..00000000000
--- a/changelogs/unreleased/fix-merge-request-relations-with-pipeline-on-mwps.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix MWPS does not work for merge request pipelines
-merge_request: 26906
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-milestone-references-with-escaped-html-entities.yml b/changelogs/unreleased/fix-milestone-references-with-escaped-html-entities.yml
new file mode 100644
index 00000000000..1041943f9c4
--- /dev/null
+++ b/changelogs/unreleased/fix-milestone-references-with-escaped-html-entities.yml
@@ -0,0 +1,5 @@
+---
+title: Fix milestone references containing &, <, or >
+merge_request: 28667
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-new-merge-request-diff-headers-sticky-position.yml b/changelogs/unreleased/fix-new-merge-request-diff-headers-sticky-position.yml
deleted file mode 100644
index dadbd5c940f..00000000000
--- a/changelogs/unreleased/fix-new-merge-request-diff-headers-sticky-position.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed sticky headers in merge request creation diffs
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-pipeline-entity.yml b/changelogs/unreleased/fix-pipeline-entity.yml
deleted file mode 100644
index b429139402c..00000000000
--- a/changelogs/unreleased/fix-pipeline-entity.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add merge request pipeline flag to pipeline entity
-merge_request: 25846
-author:
-type: added
diff --git a/changelogs/unreleased/fix-pipeline-schedule-owner-is-nil.yml b/changelogs/unreleased/fix-pipeline-schedule-owner-is-nil.yml
new file mode 100644
index 00000000000..5c8644d2860
--- /dev/null
+++ b/changelogs/unreleased/fix-pipeline-schedule-owner-is-nil.yml
@@ -0,0 +1,5 @@
+---
+title: Fix pipeline schedules when owner is nil
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-review-app-env-url.yml b/changelogs/unreleased/fix-review-app-env-url.yml
deleted file mode 100644
index 963cd0c2992..00000000000
--- a/changelogs/unreleased/fix-review-app-env-url.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixes long review app subdomains
-merge_request: 25990
-author: walkafwalka
-type: fixed
diff --git a/changelogs/unreleased/fix-routes-n-plus-one-in-user-autocomplete.yml b/changelogs/unreleased/fix-routes-n-plus-one-in-user-autocomplete.yml
deleted file mode 100644
index ae097e859d9..00000000000
--- a/changelogs/unreleased/fix-routes-n-plus-one-in-user-autocomplete.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix some N+1s in loading routes and counting members for groups in @-autocomplete
-merge_request: 26491
-author:
-type: performance
diff --git a/changelogs/unreleased/fix-search-dropdown-blur-close.yml b/changelogs/unreleased/fix-search-dropdown-blur-close.yml
new file mode 100644
index 00000000000..1ac9dc674fe
--- /dev/null
+++ b/changelogs/unreleased/fix-search-dropdown-blur-close.yml
@@ -0,0 +1,5 @@
+---
+title: Fix search dropdown not closing on blur if empty
+merge_request: 28730
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-time-window-default.yml b/changelogs/unreleased/fix-time-window-default.yml
new file mode 100644
index 00000000000..147f82eb6c9
--- /dev/null
+++ b/changelogs/unreleased/fix-time-window-default.yml
@@ -0,0 +1,5 @@
+---
+title: Use the selected time window for metrics dashboard
+merge_request: 29152
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-too-many-loops-cron-error.yml b/changelogs/unreleased/fix-too-many-loops-cron-error.yml
new file mode 100644
index 00000000000..a9b5b761439
--- /dev/null
+++ b/changelogs/unreleased/fix-too-many-loops-cron-error.yml
@@ -0,0 +1,5 @@
+---
+title: Fix "too many loops" error by handling gracefully cron schedules for non existent days
+merge_request: 28002
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-transfer-group-possibilities.yml b/changelogs/unreleased/fix-transfer-group-possibilities.yml
deleted file mode 100644
index ebefb47b3da..00000000000
--- a/changelogs/unreleased/fix-transfer-group-possibilities.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix group transfer selection possibilities
-merge_request: 26123
-author: Peter Marko
-type: fixed
diff --git a/changelogs/unreleased/fixed-duplicated-large-text-on-diffs.yml b/changelogs/unreleased/fixed-duplicated-large-text-on-diffs.yml
deleted file mode 100644
index 770186a64b0..00000000000
--- a/changelogs/unreleased/fixed-duplicated-large-text-on-diffs.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed duplicated diff too large error message
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/fixed-web-ide-merge-request-review.yml b/changelogs/unreleased/fixed-web-ide-merge-request-review.yml
deleted file mode 100644
index 2799f5ee38a..00000000000
--- a/changelogs/unreleased/fixed-web-ide-merge-request-review.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed Web IDE not loading merge request files
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/fj-bump-workhorse-version-8-6-0.yml b/changelogs/unreleased/fj-bump-workhorse-version-8-6-0.yml
deleted file mode 100644
index e53499e21ba..00000000000
--- a/changelogs/unreleased/fj-bump-workhorse-version-8-6-0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update GitLab Workhorse to v8.6.0
-merge_request: 27260
-author:
-type: fixed
diff --git a/changelogs/unreleased/frozen-string-spec-some.yml b/changelogs/unreleased/frozen-string-spec-some.yml
deleted file mode 100644
index 55381d7ccbe..00000000000
--- a/changelogs/unreleased/frozen-string-spec-some.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add some frozen string to spec/**/*.rb
-merge_request:
-author: gfyoung
-type: other
diff --git a/changelogs/unreleased/gitaly-version-v1.29.0.yml b/changelogs/unreleased/gitaly-version-v1.29.0.yml
deleted file mode 100644
index b6ce14c33a2..00000000000
--- a/changelogs/unreleased/gitaly-version-v1.29.0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Upgrade to Gitaly v1.29.0
-merge_request: 26406
-author:
-type: changed
diff --git a/changelogs/unreleased/gitaly-version-v1.32.0.yml b/changelogs/unreleased/gitaly-version-v1.32.0.yml
deleted file mode 100644
index 8413f31278e..00000000000
--- a/changelogs/unreleased/gitaly-version-v1.32.0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Upgrade to Gitaly v1.32.0
-merge_request: 26989
-author:
-type: changed
diff --git a/changelogs/unreleased/gitaly-version-v1.33.0.yml b/changelogs/unreleased/gitaly-version-v1.33.0.yml
deleted file mode 100644
index d21e521a0bb..00000000000
--- a/changelogs/unreleased/gitaly-version-v1.33.0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Upgrade to Gitaly v1.33.0
-merge_request: 27065
-author:
-type: changed
diff --git a/changelogs/unreleased/gitaly-version-v1.43.0.yml b/changelogs/unreleased/gitaly-version-v1.43.0.yml
new file mode 100644
index 00000000000..67acd2725e1
--- /dev/null
+++ b/changelogs/unreleased/gitaly-version-v1.43.0.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade to Gitaly v1.43.0
+merge_request: 28867
+author:
+type: changed
diff --git a/changelogs/unreleased/graphql-prometheus.yml b/changelogs/unreleased/graphql-prometheus.yml
deleted file mode 100644
index 180577f3aec..00000000000
--- a/changelogs/unreleased/graphql-prometheus.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Added prometheus monitoring to GraphQL
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/gt-externalize-app-views-projects-pipelines.yml b/changelogs/unreleased/gt-externalize-app-views-projects-pipelines.yml
deleted file mode 100644
index 094cd3ab751..00000000000
--- a/changelogs/unreleased/gt-externalize-app-views-projects-pipelines.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Externalize strings from `/app/views/projects/pipelines`
-merge_request: 26035
-author: George Tsiolis
-type: other
diff --git a/changelogs/unreleased/gt-externalize-profiles-preferences.yml b/changelogs/unreleased/gt-externalize-profiles-preferences.yml
new file mode 100644
index 00000000000..1a72e92a241
--- /dev/null
+++ b/changelogs/unreleased/gt-externalize-profiles-preferences.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize profiles preferences
+merge_request: 28470
+author: George Tsiolis
+type: other
diff --git a/changelogs/unreleased/gt-open-visibility-help-link-in-a-new-tab.yml b/changelogs/unreleased/gt-open-visibility-help-link-in-a-new-tab.yml
new file mode 100644
index 00000000000..35515c9d639
--- /dev/null
+++ b/changelogs/unreleased/gt-open-visibility-help-link-in-a-new-tab.yml
@@ -0,0 +1,5 @@
+---
+title: Open visibility help link in a new tab
+merge_request: 28603
+author: George Tsiolis
+type: fixed
diff --git a/changelogs/unreleased/i18n-active_sessions-in-user-profile.yml b/changelogs/unreleased/i18n-active_sessions-in-user-profile.yml
new file mode 100644
index 00000000000..fe6eb3a2bf7
--- /dev/null
+++ b/changelogs/unreleased/i18n-active_sessions-in-user-profile.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings of active sessions page in user profile
+merge_request: 28590
+author: antony liu
+type: other
diff --git a/changelogs/unreleased/i18n-chat-of-user-profile.yml b/changelogs/unreleased/i18n-chat-of-user-profile.yml
new file mode 100644
index 00000000000..663b4ffc1a1
--- /dev/null
+++ b/changelogs/unreleased/i18n-chat-of-user-profile.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings of chat page in user profile
+merge_request: 28632
+author:
+type: other
diff --git a/changelogs/unreleased/i18n-email-of-user-profile.yml b/changelogs/unreleased/i18n-email-of-user-profile.yml
new file mode 100644
index 00000000000..6cb718843d5
--- /dev/null
+++ b/changelogs/unreleased/i18n-email-of-user-profile.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings of email page in user profile
+merge_request: 28587
+author: antony liu
+type: other
diff --git a/changelogs/unreleased/i18n-pgp_ssh_keys-of-user-profile.yml b/changelogs/unreleased/i18n-pgp_ssh_keys-of-user-profile.yml
new file mode 100644
index 00000000000..4dc45b35976
--- /dev/null
+++ b/changelogs/unreleased/i18n-pgp_ssh_keys-of-user-profile.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings of PGP Keys and SSH Keys page in user profile
+merge_request: 28653
+author: Antony Liu
+type: other
diff --git a/changelogs/unreleased/id-51433-sort-wiki-by-date.yml b/changelogs/unreleased/id-51433-sort-wiki-by-date.yml
deleted file mode 100644
index 86fcf195fa7..00000000000
--- a/changelogs/unreleased/id-51433-sort-wiki-by-date.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow to sort wiki pages by date and title
-merge_request: 25365
-author:
-type: added
diff --git a/changelogs/unreleased/id-bug-suggested-changes-remove-empty-line.yml b/changelogs/unreleased/id-bug-suggested-changes-remove-empty-line.yml
new file mode 100644
index 00000000000..eae2d5f9b2a
--- /dev/null
+++ b/changelogs/unreleased/id-bug-suggested-changes-remove-empty-line.yml
@@ -0,0 +1,5 @@
+---
+title: Allow removal of empty lines via suggestions
+merge_request: 28703
+author:
+type: fixed
diff --git a/changelogs/unreleased/ide-fix-detect-mr-from-fork.yml b/changelogs/unreleased/ide-fix-detect-mr-from-fork.yml
deleted file mode 100644
index 8f4f49896d7..00000000000
--- a/changelogs/unreleased/ide-fix-detect-mr-from-fork.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix IDE detection of MR from fork with same branch name
-merge_request: 26986
-author:
-type: fixed
diff --git a/changelogs/unreleased/ignore-artifact-attirbutes-in-project-import-export.yml b/changelogs/unreleased/ignore-artifact-attirbutes-in-project-import-export.yml
new file mode 100644
index 00000000000..536aae03f59
--- /dev/null
+++ b/changelogs/unreleased/ignore-artifact-attirbutes-in-project-import-export.yml
@@ -0,0 +1,5 @@
+---
+title: Ignore legacy artifact columns in Project Import/Export
+merge_request: 29427
+author:
+type: fixed
diff --git a/changelogs/unreleased/improve-email-text-part.yml b/changelogs/unreleased/improve-email-text-part.yml
new file mode 100644
index 00000000000..ce506cb1507
--- /dev/null
+++ b/changelogs/unreleased/improve-email-text-part.yml
@@ -0,0 +1,5 @@
+---
+title: Improve new user email markup unconsistency between text and html parts
+merge_request: 29111
+author: Haunui Saint-sevin
+type: fixed
diff --git a/changelogs/unreleased/increase-move-issue-dropdown-height.yml b/changelogs/unreleased/increase-move-issue-dropdown-height.yml
new file mode 100644
index 00000000000..bb67e9341b2
--- /dev/null
+++ b/changelogs/unreleased/increase-move-issue-dropdown-height.yml
@@ -0,0 +1,5 @@
+---
+title: Increase height of move issue dropdown
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/instance-configuration-artifact-size.yml b/changelogs/unreleased/instance-configuration-artifact-size.yml
deleted file mode 100644
index 077f8631af5..00000000000
--- a/changelogs/unreleased/instance-configuration-artifact-size.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Display maximum artifact size from runtime config
-merge_request: 26784
-author: Bastian Blank
-type: fixed
diff --git a/changelogs/unreleased/issue-58418-release-notes.yml b/changelogs/unreleased/issue-58418-release-notes.yml
deleted file mode 100644
index 80e6529eb12..00000000000
--- a/changelogs/unreleased/issue-58418-release-notes.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Set release name when adding release notes to an existing tag
-merge_request: 26807
-author:
-type: fixed
diff --git a/changelogs/unreleased/issue_49897.yml b/changelogs/unreleased/issue_49897.yml
new file mode 100644
index 00000000000..b630b5143c6
--- /dev/null
+++ b/changelogs/unreleased/issue_49897.yml
@@ -0,0 +1,5 @@
+---
+title: Delete unauthorized Todos when project is made private
+merge_request: 28560
+author:
+type: fixed
diff --git a/changelogs/unreleased/issue_58547.yml b/changelogs/unreleased/issue_58547.yml
deleted file mode 100644
index 553c752e72d..00000000000
--- a/changelogs/unreleased/issue_58547.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add API access check to Graphql
-merge_request: 26570
-author:
-type: other
diff --git a/changelogs/unreleased/jc-guard-against-empty-dereferenced_target.yml b/changelogs/unreleased/jc-guard-against-empty-dereferenced_target.yml
deleted file mode 100644
index 94e5b4a81b7..00000000000
--- a/changelogs/unreleased/jc-guard-against-empty-dereferenced_target.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Guard against nil dereferenced_target
-merge_request: 27192
-author:
-type: fixed
diff --git a/changelogs/unreleased/jc-migration-for-source-project-id.yml b/changelogs/unreleased/jc-migration-for-source-project-id.yml
new file mode 100644
index 00000000000..3e2e8ebfcc5
--- /dev/null
+++ b/changelogs/unreleased/jc-migration-for-source-project-id.yml
@@ -0,0 +1,5 @@
+---
+title: Fix null source_project_id in pool_repositories
+merge_request: 29157
+author:
+type: other
diff --git a/changelogs/unreleased/jc-omit-count-diverging-commits-max.yml b/changelogs/unreleased/jc-omit-count-diverging-commits-max.yml
new file mode 100644
index 00000000000..23235060a98
--- /dev/null
+++ b/changelogs/unreleased/jc-omit-count-diverging-commits-max.yml
@@ -0,0 +1,5 @@
+---
+title: Omit max-count for diverging_commit_counts behind feature flag
+merge_request: 28157
+author:
+type: other
diff --git a/changelogs/unreleased/jivl-migrate-dashboard-store-vuex.yml b/changelogs/unreleased/jivl-migrate-dashboard-store-vuex.yml
new file mode 100644
index 00000000000..dc4edbc058f
--- /dev/null
+++ b/changelogs/unreleased/jivl-migrate-dashboard-store-vuex.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate the monitoring dashboard store to vuex
+merge_request: 28555
+author:
+type: other
diff --git a/changelogs/unreleased/jupyter_pre_spawn_hook_v2.yml b/changelogs/unreleased/jupyter_pre_spawn_hook_v2.yml
new file mode 100644
index 00000000000..c5918df8193
--- /dev/null
+++ b/changelogs/unreleased/jupyter_pre_spawn_hook_v2.yml
@@ -0,0 +1,5 @@
+---
+title: Pass user's identity and token from JupyterHub to user's Jupyter environment
+merge_request: 27314
+author: Amit Rathi
+type: added
diff --git a/changelogs/unreleased/k8s_new_deployment_labels.yml b/changelogs/unreleased/k8s_new_deployment_labels.yml
deleted file mode 100644
index e9ef3ee0082..00000000000
--- a/changelogs/unreleased/k8s_new_deployment_labels.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update deploy boards to additionally select on "app.gitlab.com" annotations
-merge_request: 25623
-author:
-type: changed
diff --git a/changelogs/unreleased/kinolaev-master-patch-13154.yml b/changelogs/unreleased/kinolaev-master-patch-13154.yml
new file mode 100644
index 00000000000..3292ff797e2
--- /dev/null
+++ b/changelogs/unreleased/kinolaev-master-patch-13154.yml
@@ -0,0 +1,5 @@
+---
+title: 'Auto-DevOps: allow to disable rollout status check'
+merge_request: 28130
+author: Sergej Nikolaev <kinolaev@gmail.com>
+type: fixed
diff --git a/changelogs/unreleased/knative-prometheus.yml b/changelogs/unreleased/knative-prometheus.yml
deleted file mode 100644
index e24f53b7225..00000000000
--- a/changelogs/unreleased/knative-prometheus.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add Knative metrics to Prometheus
-merge_request: 24663
-author: Chris Baumbauer <cab@cabnetworks.net>
-type: added
diff --git a/changelogs/unreleased/knative-update.yml b/changelogs/unreleased/knative-update.yml
deleted file mode 100644
index e84940ae7e0..00000000000
--- a/changelogs/unreleased/knative-update.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Knative version bump 0.2.2 -> 0.3.0
-merge_request: 26459
-author: Chris Baumbauer
-type: changed
diff --git a/changelogs/unreleased/kube_helm_auto_devops_213.yml b/changelogs/unreleased/kube_helm_auto_devops_213.yml
deleted file mode 100644
index 3c718d4a22c..00000000000
--- a/changelogs/unreleased/kube_helm_auto_devops_213.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Bump kubectl to 1.11.9 and Helm to 2.13.1 in Auto-DevOps.gitlab-ci.yml
-merge_request: 26534
-author:
-type: other
diff --git a/changelogs/unreleased/leipert-node-12-compatibility.yml b/changelogs/unreleased/leipert-node-12-compatibility.yml
new file mode 100644
index 00000000000..18025d33a6d
--- /dev/null
+++ b/changelogs/unreleased/leipert-node-12-compatibility.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade dependencies for node 12 compatibility
+merge_request: 28323
+author:
+type: fixed
diff --git a/changelogs/unreleased/limit-amount-of-created-pipelines.yml b/changelogs/unreleased/limit-amount-of-created-pipelines.yml
deleted file mode 100644
index 51fdbb4d7ff..00000000000
--- a/changelogs/unreleased/limit-amount-of-created-pipelines.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Process at most 4 pipelines during push
-merge_request: 27205
-author:
-type: performance
diff --git a/changelogs/unreleased/localize-notification-dropdown.yml b/changelogs/unreleased/localize-notification-dropdown.yml
deleted file mode 100644
index 9599aaf344b..00000000000
--- a/changelogs/unreleased/localize-notification-dropdown.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Localize notifications dropdown
-merge_request: 26844
-author:
-type: changed
diff --git a/changelogs/unreleased/make-autocomplete-faster-with-lots-of-results.yml b/changelogs/unreleased/make-autocomplete-faster-with-lots-of-results.yml
new file mode 100644
index 00000000000..daeefd3ffd7
--- /dev/null
+++ b/changelogs/unreleased/make-autocomplete-faster-with-lots-of-results.yml
@@ -0,0 +1,5 @@
+---
+title: Improve performance of users autocomplete when there are lots of results
+merge_request:
+author:
+type: performance
diff --git a/changelogs/unreleased/mark-comment-resolved.yml b/changelogs/unreleased/mark-comment-resolved.yml
new file mode 100644
index 00000000000..3343d18d16f
--- /dev/null
+++ b/changelogs/unreleased/mark-comment-resolved.yml
@@ -0,0 +1,5 @@
+---
+title: Change resolve button text to mark comment as resolved
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/minimized-multiple-queries-ce.yml b/changelogs/unreleased/minimized-multiple-queries-ce.yml
deleted file mode 100644
index d8c20d492d6..00000000000
--- a/changelogs/unreleased/minimized-multiple-queries-ce.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Support multiple queries per chart on metrics dash
-merge_request: 25758
-author:
-type: added
diff --git a/changelogs/unreleased/mm12935.yml b/changelogs/unreleased/mm12935.yml
new file mode 100644
index 00000000000..782586c514e
--- /dev/null
+++ b/changelogs/unreleased/mm12935.yml
@@ -0,0 +1,5 @@
+---
+title: Remove Content-Type override for Mattermost OAuth login
+merge_request:
+author: Harrison Healey
+type: removed
diff --git a/changelogs/unreleased/move-allow-developers-to-create-projects-in-groups-to-core.yml b/changelogs/unreleased/move-allow-developers-to-create-projects-in-groups-to-core.yml
deleted file mode 100644
index 34fd0c1b787..00000000000
--- a/changelogs/unreleased/move-allow-developers-to-create-projects-in-groups-to-core.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Move allow developers to create projects in groups to Core
-merge_request: 25975
-author:
-type: added
diff --git a/changelogs/unreleased/nfriend-css-updates-for-gitlab-design-system-compliance.yml b/changelogs/unreleased/nfriend-css-updates-for-gitlab-design-system-compliance.yml
deleted file mode 100644
index 8cde0958f7a..00000000000
--- a/changelogs/unreleased/nfriend-css-updates-for-gitlab-design-system-compliance.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update `border-radius` of form controls and remove extra space above page titles
-merge_request: 24497
-author:
-type: fixed
diff --git a/changelogs/unreleased/nfriend-update-job-detail-view-sidebar.yml b/changelogs/unreleased/nfriend-update-job-detail-view-sidebar.yml
deleted file mode 100644
index 5364d29710a..00000000000
--- a/changelogs/unreleased/nfriend-update-job-detail-view-sidebar.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update job detail sidebar to accommodate post-merge pipeline information
-merge_request: 25777
-author:
-type: added
diff --git a/changelogs/unreleased/nfriend-update-merge-request-widget-for-post-merge-pipelines.yml b/changelogs/unreleased/nfriend-update-merge-request-widget-for-post-merge-pipelines.yml
deleted file mode 100644
index 420c8f2923c..00000000000
--- a/changelogs/unreleased/nfriend-update-merge-request-widget-for-post-merge-pipelines.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add two new warning messages to the MR widget about merge request pipelines
-merge_request: 25983
-author:
-type: added
diff --git a/changelogs/unreleased/nfriend-update-merge-request-widget-pipeline-block.yml b/changelogs/unreleased/nfriend-update-merge-request-widget-pipeline-block.yml
deleted file mode 100644
index bd4120eb06f..00000000000
--- a/changelogs/unreleased/nfriend-update-merge-request-widget-pipeline-block.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Update pipeline block on merge request page to accommodate post-merge pipeline
- information
-merge_request: 25745
-author:
-type: added
diff --git a/changelogs/unreleased/nfriend-update-pipeline-detail-view.yml b/changelogs/unreleased/nfriend-update-pipeline-detail-view.yml
deleted file mode 100644
index a24325c4eb6..00000000000
--- a/changelogs/unreleased/nfriend-update-pipeline-detail-view.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update pipeline detail view to accommodate post-merge pipelines
-merge_request: 25775
-author:
-type: added
diff --git a/changelogs/unreleased/nfriend-update-pipeline-list-view.yml b/changelogs/unreleased/nfriend-update-pipeline-list-view.yml
deleted file mode 100644
index 34e43162b5c..00000000000
--- a/changelogs/unreleased/nfriend-update-pipeline-list-view.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update pipeline list view to accommodate post-merge pipeline information
-merge_request: 25690
-author:
-type: added
diff --git a/changelogs/unreleased/only-counted-active-milestones-as-started.yml b/changelogs/unreleased/only-counted-active-milestones-as-started.yml
deleted file mode 100644
index 1a9c4b9023b..00000000000
--- a/changelogs/unreleased/only-counted-active-milestones-as-started.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Only consider active milestones when using the special Started milestone filter
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/osw-avoid-500-on-suggestions-check.yml b/changelogs/unreleased/osw-avoid-500-on-suggestions-check.yml
new file mode 100644
index 00000000000..d0a09385d4c
--- /dev/null
+++ b/changelogs/unreleased/osw-avoid-500-on-suggestions-check.yml
@@ -0,0 +1,5 @@
+---
+title: Avoid 500 when rendering users ATOM data
+merge_request: 25408
+author:
+type: fixed
diff --git a/changelogs/unreleased/osw-avoid-encoding-errors-on-merge-to-ref-service.yml b/changelogs/unreleased/osw-avoid-encoding-errors-on-merge-to-ref-service.yml
new file mode 100644
index 00000000000..176c8bf36f7
--- /dev/null
+++ b/changelogs/unreleased/osw-avoid-encoding-errors-on-merge-to-ref-service.yml
@@ -0,0 +1,5 @@
+---
+title: Handle encoding errors for MergeToRefService
+merge_request: 29440
+author:
+type: fixed
diff --git a/changelogs/unreleased/osw-fix-post-dep-migration-with-timeout.yml b/changelogs/unreleased/osw-fix-post-dep-migration-with-timeout.yml
new file mode 100644
index 00000000000..6b37bb11ad5
--- /dev/null
+++ b/changelogs/unreleased/osw-fix-post-dep-migration-with-timeout.yml
@@ -0,0 +1,5 @@
+---
+title: Avoid DB timeouts when scheduling migrations
+merge_request: 29437
+author:
+type: fixed
diff --git a/changelogs/unreleased/osw-multi-line-suggestions-creation-strategy.yml b/changelogs/unreleased/osw-multi-line-suggestions-creation-strategy.yml
deleted file mode 100644
index 01bd7ede270..00000000000
--- a/changelogs/unreleased/osw-multi-line-suggestions-creation-strategy.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Implements the creation strategy for multi-line suggestions
-merge_request: 26057
-author:
-type: changed
diff --git a/changelogs/unreleased/osw-multi-line-suggestions-parsing.yml b/changelogs/unreleased/osw-multi-line-suggestions-parsing.yml
deleted file mode 100644
index 985b01e9254..00000000000
--- a/changelogs/unreleased/osw-multi-line-suggestions-parsing.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prepare multi-line suggestions for rendering in Markdown
-merge_request: 26107
-author:
-type: other
diff --git a/changelogs/unreleased/osw-reset-merge-status-from-mergeable-mrs.yml b/changelogs/unreleased/osw-reset-merge-status-from-mergeable-mrs.yml
new file mode 100644
index 00000000000..6b5f97f24b3
--- /dev/null
+++ b/changelogs/unreleased/osw-reset-merge-status-from-mergeable-mrs.yml
@@ -0,0 +1,5 @@
+---
+title: Reset merge status from mergeable MRs
+merge_request: 28843
+author:
+type: other
diff --git a/changelogs/unreleased/osw-support-multi-line-suggestions.yml b/changelogs/unreleased/osw-support-multi-line-suggestions.yml
deleted file mode 100644
index 8c8206c3822..00000000000
--- a/changelogs/unreleased/osw-support-multi-line-suggestions.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Support multi-line suggestions
-merge_request: 25211
-author:
-type: added
diff --git a/changelogs/unreleased/patch-55.yml b/changelogs/unreleased/patch-55.yml
new file mode 100644
index 00000000000..7a6d6bfed2f
--- /dev/null
+++ b/changelogs/unreleased/patch-55.yml
@@ -0,0 +1,5 @@
+---
+title: Better isolated `Docker.gitlab-ci.yml` to avoid interference with other job configurations.
+merge_request: 28213
+author: lrkwz
+type: changed
diff --git a/changelogs/unreleased/patch-65.yml b/changelogs/unreleased/patch-65.yml
new file mode 100644
index 00000000000..9ce628a6541
--- /dev/null
+++ b/changelogs/unreleased/patch-65.yml
@@ -0,0 +1,5 @@
+---
+title: Show tooltip on truncated commit title
+merge_request: 28865
+author: Timofey Trofimov
+type: other
diff --git a/changelogs/unreleased/patch-issue--56683.yml b/changelogs/unreleased/patch-issue--56683.yml
new file mode 100644
index 00000000000..9b82c6c1459
--- /dev/null
+++ b/changelogs/unreleased/patch-issue--56683.yml
@@ -0,0 +1,6 @@
+---
+title: Process up to 100 commit messages for references when pushing to a new default
+ branch
+merge_request: 29511
+author: Fabio Papa
+type: fixed
diff --git a/changelogs/unreleased/pb-update-gitaly-1-45-0.yml b/changelogs/unreleased/pb-update-gitaly-1-45-0.yml
new file mode 100644
index 00000000000..eaad7a8378b
--- /dev/null
+++ b/changelogs/unreleased/pb-update-gitaly-1-45-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update GITALY_SERVER_VERSION to 1.45.0
+merge_request: 29109
+author:
+type: changed
diff --git a/changelogs/unreleased/persist-fulll-ref-path-for-mr-pipelines.yml b/changelogs/unreleased/persist-fulll-ref-path-for-mr-pipelines.yml
deleted file mode 100644
index ca42a26e8ff..00000000000
--- a/changelogs/unreleased/persist-fulll-ref-path-for-mr-pipelines.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Create MR pipelines with `refs/merge-requests/:iid/head`
-merge_request: 25504
-author:
-type: changed
diff --git a/changelogs/unreleased/pipelines-email-default-branch-filter.yml b/changelogs/unreleased/pipelines-email-default-branch-filter.yml
new file mode 100644
index 00000000000..4c2a54af0bf
--- /dev/null
+++ b/changelogs/unreleased/pipelines-email-default-branch-filter.yml
@@ -0,0 +1,5 @@
+---
+title: Add notify_only_default_branch option to PipelinesEmailService
+merge_request: 28271
+author: Peter Marko
+type: added
diff --git a/changelogs/unreleased/pravi-gitlab-ce-update-recaptcha.yml b/changelogs/unreleased/pravi-gitlab-ce-update-recaptcha.yml
deleted file mode 100644
index 95379fb2ec1..00000000000
--- a/changelogs/unreleased/pravi-gitlab-ce-update-recaptcha.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Apply recaptcha API change in 4.0
-merge_request: 25921
-author: Praveen Arimbrathodiyil
-type: other
diff --git a/changelogs/unreleased/prevent-running-mr-pipelines-when-target-updated.yml b/changelogs/unreleased/prevent-running-mr-pipelines-when-target-updated.yml
deleted file mode 100644
index d003ca55feb..00000000000
--- a/changelogs/unreleased/prevent-running-mr-pipelines-when-target-updated.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Create pipelines for merge requests only when source branch is updated
-merge_request: 26921
-author:
-type: fixed
diff --git a/changelogs/unreleased/referenced-labels.yml b/changelogs/unreleased/referenced-labels.yml
new file mode 100644
index 00000000000..c39ef4c2478
--- /dev/null
+++ b/changelogs/unreleased/referenced-labels.yml
@@ -0,0 +1,5 @@
+---
+title: Add referenced-commands in no overflow list
+merge_request: 28858
+author:
+type: fixed
diff --git a/changelogs/unreleased/related-mr-link-cutoff.yml b/changelogs/unreleased/related-mr-link-cutoff.yml
deleted file mode 100644
index 8cf77b6231a..00000000000
--- a/changelogs/unreleased/related-mr-link-cutoff.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Don't cutoff letters in MR and Issue links
-merge_request: 25910
-author: gfyoung
-type: fixed
diff --git a/changelogs/unreleased/relative-urls-for-system-notes.yml b/changelogs/unreleased/relative-urls-for-system-notes.yml
new file mode 100644
index 00000000000..ec834e9f277
--- /dev/null
+++ b/changelogs/unreleased/relative-urls-for-system-notes.yml
@@ -0,0 +1,5 @@
+---
+title: Change links in system notes to use relative paths
+merge_request: 28588
+author: Luke Picciau
+type: fixed
diff --git a/changelogs/unreleased/remove-ci-charts-undescriptive-header.yml b/changelogs/unreleased/remove-ci-charts-undescriptive-header.yml
deleted file mode 100644
index 0e090592101..00000000000
--- a/changelogs/unreleased/remove-ci-charts-undescriptive-header.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Removes the undescriptive CI Charts header
-merge_request: !26869
-author:
-type: changed
diff --git a/changelogs/unreleased/remove-disabled-pages-domains.yml b/changelogs/unreleased/remove-disabled-pages-domains.yml
deleted file mode 100644
index e23561329ef..00000000000
--- a/changelogs/unreleased/remove-disabled-pages-domains.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Mark disabled pages domains for removal, but don't remove them yet
-merge_request: 26212
-author:
-type: added
diff --git a/changelogs/unreleased/remove-grafana-dashboard-link-feature-flag.yml b/changelogs/unreleased/remove-grafana-dashboard-link-feature-flag.yml
new file mode 100644
index 00000000000..24b5fb50e40
--- /dev/null
+++ b/changelogs/unreleased/remove-grafana-dashboard-link-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Link to an external dashboard from metrics dashboard
+merge_request: 29369
+author:
+type: added
diff --git a/changelogs/unreleased/remove-legacy-artifacts-related-code.yml b/changelogs/unreleased/remove-legacy-artifacts-related-code.yml
new file mode 100644
index 00000000000..acde65af2d4
--- /dev/null
+++ b/changelogs/unreleased/remove-legacy-artifacts-related-code.yml
@@ -0,0 +1,5 @@
+---
+title: Remove legacy artifact related code
+merge_request: 26475
+author:
+type: other
diff --git a/changelogs/unreleased/remove-mr-diff-header-height.yml b/changelogs/unreleased/remove-mr-diff-header-height.yml
new file mode 100644
index 00000000000..c06c7281c58
--- /dev/null
+++ b/changelogs/unreleased/remove-mr-diff-header-height.yml
@@ -0,0 +1,5 @@
+---
+title: Remove fixed height from MR diff headers
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/require-all-templates-to-include-default-stages.yml b/changelogs/unreleased/require-all-templates-to-include-default-stages.yml
deleted file mode 100644
index de8b07160ba..00000000000
--- a/changelogs/unreleased/require-all-templates-to-include-default-stages.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Require all templates to use default stages
-merge_request: 26954
-author:
-type: fixed
diff --git a/changelogs/unreleased/rewind-iid-on-pipelines.yml b/changelogs/unreleased/rewind-iid-on-pipelines.yml
deleted file mode 100644
index b5738860024..00000000000
--- a/changelogs/unreleased/rewind-iid-on-pipelines.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Rewind IID on Ci::Pipelines
-merge_request: 26490
-author:
-type: fixed
diff --git a/changelogs/unreleased/security-55503-fix-pdf-js-vulnerability.yml b/changelogs/unreleased/security-55503-fix-pdf-js-vulnerability.yml
deleted file mode 100644
index e5d0cd4fee1..00000000000
--- a/changelogs/unreleased/security-55503-fix-pdf-js-vulnerability.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix PDF.js vulnerability
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-56224.yml b/changelogs/unreleased/security-56224.yml
deleted file mode 100644
index a4e274e6ca5..00000000000
--- a/changelogs/unreleased/security-56224.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Hide "related branches" when user does not have permission
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-56927-xss-resolve-conflicts-branch-name.yml b/changelogs/unreleased/security-56927-xss-resolve-conflicts-branch-name.yml
deleted file mode 100644
index f92d2c0dcb1..00000000000
--- a/changelogs/unreleased/security-56927-xss-resolve-conflicts-branch-name.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix XSS in resolve conflicts form
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-58856-persistent-xss-in-note-objects.yml b/changelogs/unreleased/security-58856-persistent-xss-in-note-objects.yml
new file mode 100644
index 00000000000..d9ad5af256a
--- /dev/null
+++ b/changelogs/unreleased/security-58856-persistent-xss-in-note-objects.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent XSS injection in note imports
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-60039.yml b/changelogs/unreleased/security-60039.yml
new file mode 100644
index 00000000000..5edbf32ec97
--- /dev/null
+++ b/changelogs/unreleased/security-60039.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent invalid branch for merge request
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-60143-address-xss-issue-in-wiki-links.yml b/changelogs/unreleased/security-60143-address-xss-issue-in-wiki-links.yml
new file mode 100644
index 00000000000..5b79258af54
--- /dev/null
+++ b/changelogs/unreleased/security-60143-address-xss-issue-in-wiki-links.yml
@@ -0,0 +1,5 @@
+---
+title: Filter relative links in wiki for XSS
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-exif-migration.yml b/changelogs/unreleased/security-exif-migration.yml
deleted file mode 100644
index cc529099df5..00000000000
--- a/changelogs/unreleased/security-exif-migration.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Added rake task for removing EXIF data from existing uploads.
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-fix-confidential-issue-label-visibility-master.yml b/changelogs/unreleased/security-fix-confidential-issue-label-visibility-master.yml
new file mode 100644
index 00000000000..adfd8e1298f
--- /dev/null
+++ b/changelogs/unreleased/security-fix-confidential-issue-label-visibility-master.yml
@@ -0,0 +1,5 @@
+---
+title: Fix confidential issue label disclosure on milestone view
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-fix-project-existence-disclosure-master.yml b/changelogs/unreleased/security-fix-project-existence-disclosure-master.yml
new file mode 100644
index 00000000000..084439c71d9
--- /dev/null
+++ b/changelogs/unreleased/security-fix-project-existence-disclosure-master.yml
@@ -0,0 +1,5 @@
+---
+title: Fix url redaction for issue links
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-fix_milestones_search_api_leak.yml b/changelogs/unreleased/security-fix_milestones_search_api_leak.yml
new file mode 100644
index 00000000000..5691550b602
--- /dev/null
+++ b/changelogs/unreleased/security-fix_milestones_search_api_leak.yml
@@ -0,0 +1,5 @@
+---
+title: 'Resolve: Milestones leaked via search API'
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-id-leaked-password-in-import-url-frontend.yml b/changelogs/unreleased/security-id-leaked-password-in-import-url-frontend.yml
new file mode 100644
index 00000000000..df636ec37fb
--- /dev/null
+++ b/changelogs/unreleased/security-id-leaked-password-in-import-url-frontend.yml
@@ -0,0 +1,5 @@
+---
+title: Add extra fields for handling basic auth on import by url page
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-id-potential-denial-languages.yml b/changelogs/unreleased/security-id-potential-denial-languages.yml
deleted file mode 100644
index 2194ecb97dc..00000000000
--- a/changelogs/unreleased/security-id-potential-denial-languages.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Return cached languages if they've been detected before
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-jej-prevent-web-sign-in-bypass.yml b/changelogs/unreleased/security-jej-prevent-web-sign-in-bypass.yml
new file mode 100644
index 00000000000..02773fa1d7c
--- /dev/null
+++ b/changelogs/unreleased/security-jej-prevent-web-sign-in-bypass.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent bypass of restriction disabling web password sign in
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-mass-assignment-on-project-update.yml b/changelogs/unreleased/security-mass-assignment-on-project-update.yml
deleted file mode 100644
index 93561cd91b3..00000000000
--- a/changelogs/unreleased/security-mass-assignment-on-project-update.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Disallow updating namespace when updating a project
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-unsubscribing-from-issue.yml b/changelogs/unreleased/security-unsubscribing-from-issue.yml
new file mode 100644
index 00000000000..3a33a457c69
--- /dev/null
+++ b/changelogs/unreleased/security-unsubscribing-from-issue.yml
@@ -0,0 +1,5 @@
+---
+title: Hide confidential issue title on unsubscribe for anonymous users
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/set-real-next-run-at-for-preventing-duplciate-pipeline-creations.yml b/changelogs/unreleased/set-real-next-run-at-for-preventing-duplciate-pipeline-creations.yml
new file mode 100644
index 00000000000..04eb035b157
--- /dev/null
+++ b/changelogs/unreleased/set-real-next-run-at-for-preventing-duplciate-pipeline-creations.yml
@@ -0,0 +1,5 @@
+---
+title: Make pipeline schedule worker resilient
+merge_request: 28407
+author:
+type: performance
diff --git a/changelogs/unreleased/sh-add-backtrace-to-sql-queries.yml b/changelogs/unreleased/sh-add-backtrace-to-sql-queries.yml
new file mode 100644
index 00000000000..d4ca027d1b9
--- /dev/null
+++ b/changelogs/unreleased/sh-add-backtrace-to-sql-queries.yml
@@ -0,0 +1,5 @@
+---
+title: Add backtraces to Peek performance bar for SQL calls
+merge_request:
+author:
+type: added
diff --git a/changelogs/unreleased/sh-add-gitaly-duration-logs.yml b/changelogs/unreleased/sh-add-gitaly-duration-logs.yml
deleted file mode 100644
index eea50384278..00000000000
--- a/changelogs/unreleased/sh-add-gitaly-duration-logs.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Log Gitaly RPC duration to api_json.log and production_json.log
-merge_request: 26652
-author:
-type: other
diff --git a/changelogs/unreleased/sh-add-gitaly-ref-name-caching-tree-controller.yml b/changelogs/unreleased/sh-add-gitaly-ref-name-caching-tree-controller.yml
deleted file mode 100644
index a051c1f70a8..00000000000
--- a/changelogs/unreleased/sh-add-gitaly-ref-name-caching-tree-controller.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable Gitaly FindCommit caching for TreeController
-merge_request: 27100
-author:
-type: performance
diff --git a/changelogs/unreleased/sh-add-header-to-jobs-admin-page.yml b/changelogs/unreleased/sh-add-header-to-jobs-admin-page.yml
new file mode 100644
index 00000000000..b089e6e4f37
--- /dev/null
+++ b/changelogs/unreleased/sh-add-header-to-jobs-admin-page.yml
@@ -0,0 +1,5 @@
+---
+title: Add a column header to admin/jobs page
+merge_request: 28837
+author:
+type: other
diff --git a/changelogs/unreleased/sh-cache-pipeline-find-commits.yml b/changelogs/unreleased/sh-cache-pipeline-find-commits.yml
deleted file mode 100644
index 2acf180d6fa..00000000000
--- a/changelogs/unreleased/sh-cache-pipeline-find-commits.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Cache FindCommit results in pipelines view
-merge_request: 26776
-author:
-type: performance
diff --git a/changelogs/unreleased/sh-cache-root-ref-asymetrically.yml b/changelogs/unreleased/sh-cache-root-ref-asymetrically.yml
deleted file mode 100644
index 106d070cc05..00000000000
--- a/changelogs/unreleased/sh-cache-root-ref-asymetrically.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Cache Repository#root_ref within a request
-merge_request: 25903
-author:
-type: performance
diff --git a/changelogs/unreleased/sh-clear-pipeline-status-cache-upon-destroy.yml b/changelogs/unreleased/sh-clear-pipeline-status-cache-upon-destroy.yml
deleted file mode 100644
index 55779f0f9d3..00000000000
--- a/changelogs/unreleased/sh-clear-pipeline-status-cache-upon-destroy.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Clear pipeline status cache after destruction of pipeline
-merge_request: 26575
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-default-visibility-fix.yml b/changelogs/unreleased/sh-default-visibility-fix.yml
new file mode 100644
index 00000000000..8308f310150
--- /dev/null
+++ b/changelogs/unreleased/sh-default-visibility-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Set project default visibility to max allowed
+merge_request: 28754
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-fogbugz-import.yml b/changelogs/unreleased/sh-fix-fogbugz-import.yml
new file mode 100644
index 00000000000..1ac730fca24
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-fogbugz-import.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Fogbugz Importer not working
+merge_request: 29383
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-gitaly-find-commit-caching.yml b/changelogs/unreleased/sh-fix-gitaly-find-commit-caching.yml
deleted file mode 100644
index 16d349c407c..00000000000
--- a/changelogs/unreleased/sh-fix-gitaly-find-commit-caching.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow ref name caching CommitService#find_commit
-merge_request: 26248
-author:
-type: performance
diff --git a/changelogs/unreleased/sh-fix-issue-55869.yml b/changelogs/unreleased/sh-fix-issue-55869.yml
new file mode 100644
index 00000000000..7935cffc13b
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-issue-55869.yml
@@ -0,0 +1,5 @@
+---
+title: Fix alignment of resend button in members page
+merge_request: 28202
+author:
+type: other
diff --git a/changelogs/unreleased/sh-fix-issue-59065.yml b/changelogs/unreleased/sh-fix-issue-59065.yml
deleted file mode 100644
index 41cd5ce0960..00000000000
--- a/changelogs/unreleased/sh-fix-issue-59065.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix Error 500 when user commits Wiki page with no commit message
-merge_request: 26247
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-merge-requests-api-remove-branch-param.yml b/changelogs/unreleased/sh-fix-merge-requests-api-remove-branch-param.yml
deleted file mode 100644
index d13c972ccc9..00000000000
--- a/changelogs/unreleased/sh-fix-merge-requests-api-remove-branch-param.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix remove_source_branch merge request API handling
-merge_request: 27392
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-pipeline-delete-caching.yml b/changelogs/unreleased/sh-fix-pipeline-delete-caching.yml
deleted file mode 100644
index 98846ea9825..00000000000
--- a/changelogs/unreleased/sh-fix-pipeline-delete-caching.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Properly expire all pipeline caches when pipeline is deleted
-merge_request: 27334
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-realtime-changes-with-reserved-words.yml b/changelogs/unreleased/sh-fix-realtime-changes-with-reserved-words.yml
deleted file mode 100644
index 3d1501cd667..00000000000
--- a/changelogs/unreleased/sh-fix-realtime-changes-with-reserved-words.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix real-time updates for projects that contain a reserved word
-merge_request: 27060
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-rebase-error-clearing.yml b/changelogs/unreleased/sh-fix-rebase-error-clearing.yml
new file mode 100644
index 00000000000..4f5f2779e7f
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-rebase-error-clearing.yml
@@ -0,0 +1,5 @@
+---
+title: Properly clear the merge error upon rebase failure
+merge_request: 28319
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-ref-name-caching.yml b/changelogs/unreleased/sh-fix-ref-name-caching.yml
deleted file mode 100644
index 6abd86688b4..00000000000
--- a/changelogs/unreleased/sh-fix-ref-name-caching.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix and expand Gitaly FindCommit caching
-merge_request: 27018
-author:
-type: performance
diff --git a/changelogs/unreleased/sh-fix-resolve-button-not-available.yml b/changelogs/unreleased/sh-fix-resolve-button-not-available.yml
new file mode 100644
index 00000000000..85a9007f570
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-resolve-button-not-available.yml
@@ -0,0 +1,5 @@
+---
+title: Fix "Resolve conflicts" button not appearing for some users
+merge_request: 29535
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-tag-push-remote-mirror.yml b/changelogs/unreleased/sh-fix-tag-push-remote-mirror.yml
new file mode 100644
index 00000000000..7f33ab28e3d
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-tag-push-remote-mirror.yml
@@ -0,0 +1,5 @@
+---
+title: Fix remote mirrors not updating after tag push
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-utf-8-encoding-resolve-conflicts.yml b/changelogs/unreleased/sh-fix-utf-8-encoding-resolve-conflicts.yml
new file mode 100644
index 00000000000..31039099788
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-utf-8-encoding-resolve-conflicts.yml
@@ -0,0 +1,5 @@
+---
+title: Fix UTF-8 conversion issues when resolving conflicts
+merge_request: 29453
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-git-gc-after-initial-fetch.yml b/changelogs/unreleased/sh-git-gc-after-initial-fetch.yml
deleted file mode 100644
index 867d7e6b9df..00000000000
--- a/changelogs/unreleased/sh-git-gc-after-initial-fetch.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'GitHub import: Run housekeeping after initial import'
-merge_request: 26600
-author:
-type: performance
diff --git a/changelogs/unreleased/sh-improve-find-commit-caching.yml b/changelogs/unreleased/sh-improve-find-commit-caching.yml
deleted file mode 100644
index 1b38684d018..00000000000
--- a/changelogs/unreleased/sh-improve-find-commit-caching.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Expand FindCommit caching to blob and refs
-merge_request: 27084
-author:
-type: performance
diff --git a/changelogs/unreleased/sh-omit-blocked-admins-from-notification.yml b/changelogs/unreleased/sh-omit-blocked-admins-from-notification.yml
new file mode 100644
index 00000000000..82c5505892f
--- /dev/null
+++ b/changelogs/unreleased/sh-omit-blocked-admins-from-notification.yml
@@ -0,0 +1,5 @@
+---
+title: Omit blocked admins from repository check e-mails
+merge_request: 29507
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-reject-info-refs-head-requests.yml b/changelogs/unreleased/sh-reject-info-refs-head-requests.yml
deleted file mode 100644
index 0dca18e2fd8..00000000000
--- a/changelogs/unreleased/sh-reject-info-refs-head-requests.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Reject HEAD requests to info/refs endpoint
-merge_request: 26334
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-skip-sti-tables-reltuples.yml b/changelogs/unreleased/sh-skip-sti-tables-reltuples.yml
deleted file mode 100644
index 5bf0ccf3e9d..00000000000
--- a/changelogs/unreleased/sh-skip-sti-tables-reltuples.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix counting of groups in admin dashboard
-merge_request: 26009
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-speed-up-commit-loading.yml b/changelogs/unreleased/sh-speed-up-commit-loading.yml
new file mode 100644
index 00000000000..db408708385
--- /dev/null
+++ b/changelogs/unreleased/sh-speed-up-commit-loading.yml
@@ -0,0 +1,5 @@
+---
+title: Speed up commit loads by disabling BatchLoader replace_methods
+merge_request: 29633
+author:
+type: performance
diff --git a/changelogs/unreleased/sh-update-process-mem.yml b/changelogs/unreleased/sh-update-process-mem.yml
new file mode 100644
index 00000000000..51b22fb0f00
--- /dev/null
+++ b/changelogs/unreleased/sh-update-process-mem.yml
@@ -0,0 +1,5 @@
+---
+title: Update get_process_mem to 0.2.3
+merge_request: 28248
+author:
+type: other
diff --git a/changelogs/unreleased/sh-update-rails-5-0-7-2.yml b/changelogs/unreleased/sh-update-rails-5-0-7-2.yml
deleted file mode 100644
index b0bc08d4760..00000000000
--- a/changelogs/unreleased/sh-update-rails-5-0-7-2.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update Rails to 5.0.7.2
-merge_request: 27022
-author:
-type: security
diff --git a/changelogs/unreleased/sh-upgrade-ruby-2-6-3-ce.yml b/changelogs/unreleased/sh-upgrade-ruby-2-6-3-ce.yml
new file mode 100644
index 00000000000..9ad5c9ebb64
--- /dev/null
+++ b/changelogs/unreleased/sh-upgrade-ruby-2-6-3-ce.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade Ruby version to 2.6.3
+merge_request: 28117
+author:
+type: performance
diff --git a/changelogs/unreleased/sh-validate-ref-name-in-commit.yml b/changelogs/unreleased/sh-validate-ref-name-in-commit.yml
deleted file mode 100644
index 399529556bc..00000000000
--- a/changelogs/unreleased/sh-validate-ref-name-in-commit.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Validate refs used in controllers don't have spaces
-merge_request: 24037
-author:
-type: other
diff --git a/changelogs/unreleased/stop-signing-avatar-paths.yml b/changelogs/unreleased/stop-signing-avatar-paths.yml
deleted file mode 100644
index 2c2493f0f21..00000000000
--- a/changelogs/unreleased/stop-signing-avatar-paths.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Speed up generation of avatar URLs when using object storage
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/t1.yml b/changelogs/unreleased/t1.yml
new file mode 100644
index 00000000000..6740375485d
--- /dev/null
+++ b/changelogs/unreleased/t1.yml
@@ -0,0 +1,5 @@
+---
+title: Set up git client in Jupyter installtion
+merge_request: 28783
+author: Amit Rathi
+type: added
diff --git a/changelogs/unreleased/thomas-nilsson-irfu-gitlab-ce-thomas-nilsson-irfu-master-patch-13137.yml b/changelogs/unreleased/thomas-nilsson-irfu-gitlab-ce-thomas-nilsson-irfu-master-patch-13137.yml
new file mode 100644
index 00000000000..3391fcc9537
--- /dev/null
+++ b/changelogs/unreleased/thomas-nilsson-irfu-gitlab-ce-thomas-nilsson-irfu-master-patch-13137.yml
@@ -0,0 +1,5 @@
+---
+title: Allow masking if 8 or more characters in base64.
+merge_request: 29143
+author: thomas-nilsson-irfu
+type: changed
diff --git a/changelogs/unreleased/tpresa-add-highest-role-to-user.yml b/changelogs/unreleased/tpresa-add-highest-role-to-user.yml
deleted file mode 100644
index 9714d8dcc99..00000000000
--- a/changelogs/unreleased/tpresa-add-highest-role-to-user.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adding highest role property to admin's user details page
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/update-babel-to-7-4-4.yml b/changelogs/unreleased/update-babel-to-7-4-4.yml
new file mode 100644
index 00000000000..0d4b4700bb2
--- /dev/null
+++ b/changelogs/unreleased/update-babel-to-7-4-4.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade babel to 7.4.4
+merge_request: 28437
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/update-gitaly-to-v1-42-1.yml b/changelogs/unreleased/update-gitaly-to-v1-42-1.yml
new file mode 100644
index 00000000000..ff42bdd9c0b
--- /dev/null
+++ b/changelogs/unreleased/update-gitaly-to-v1-42-1.yml
@@ -0,0 +1,5 @@
+---
+title: "Update Gitaly to v1.42.1"
+merge_request: 28425
+author:
+type: other
diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-3-0.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-3-0.yml
deleted file mode 100644
index 2e1adb1e1e9..00000000000
--- a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-3-0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update GitLab Runner Helm Chart to 0.3.0/11.9.0
-merge_request: 26467
-author:
-type: other
diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-0.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-0.yml
new file mode 100644
index 00000000000..494331158fb
--- /dev/null
+++ b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Runner Helm Chart to 0.5.0
+merge_request: 28497
+author:
+type: other
diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-1.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-1.yml
new file mode 100644
index 00000000000..dd71aa7d461
--- /dev/null
+++ b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-1.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Runner Helm Chart to 0.5.1
+merge_request: 28720
+author:
+type: other
diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-2.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-2.yml
new file mode 100644
index 00000000000..9ca6d18c2a8
--- /dev/null
+++ b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-2.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Runner Helm Chart to 0.5.2
+merge_request: 29050
+author:
+type: other
diff --git a/changelogs/unreleased/update-gitlab-shell-9-3-0.yml b/changelogs/unreleased/update-gitlab-shell-9-3-0.yml
new file mode 100644
index 00000000000..781ff31c7d8
--- /dev/null
+++ b/changelogs/unreleased/update-gitlab-shell-9-3-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update to GitLab Shell v9.3.0
+merge_request: 29283
+author:
+type: other
diff --git a/changelogs/unreleased/update-gitlab-shell.yml b/changelogs/unreleased/update-gitlab-shell.yml
deleted file mode 100644
index 446a5fe1ea9..00000000000
--- a/changelogs/unreleased/update-gitlab-shell.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update GitLab Shell to v9.0.0
-merge_request: 27002
-author:
-type: other
diff --git a/changelogs/unreleased/update-pages.yml b/changelogs/unreleased/update-pages.yml
new file mode 100644
index 00000000000..97a20b6b8fa
--- /dev/null
+++ b/changelogs/unreleased/update-pages.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Pages to v1.6.0
+merge_request: 29048
+author:
+type: other
diff --git a/changelogs/unreleased/update-psd-doc.yml b/changelogs/unreleased/update-psd-doc.yml
new file mode 100644
index 00000000000..38c8d1c0d68
--- /dev/null
+++ b/changelogs/unreleased/update-psd-doc.yml
@@ -0,0 +1,5 @@
+---
+title: Update project security dashboard documentation
+merge_request: 28681
+author:
+type: changed
diff --git a/changelogs/unreleased/update-rack-oauth2.yml b/changelogs/unreleased/update-rack-oauth2.yml
deleted file mode 100644
index dc2e7017695..00000000000
--- a/changelogs/unreleased/update-rack-oauth2.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update rack-oauth2 1.2.1 -> 1.9.3
-merge_request: 17868
-author:
-type: other
diff --git a/changelogs/unreleased/update-smileys-new.yml b/changelogs/unreleased/update-smileys-new.yml
new file mode 100644
index 00000000000..0e3f606c81b
--- /dev/null
+++ b/changelogs/unreleased/update-smileys-new.yml
@@ -0,0 +1,5 @@
+---
+title: Update new smiley icons, find n replace old names with new ones
+merge_request: 28338
+author: Jarek Ostrowski
+type: changed
diff --git a/changelogs/unreleased/update-workhorse-8-5-1.yml b/changelogs/unreleased/update-workhorse-8-5-1.yml
deleted file mode 100644
index 18193701678..00000000000
--- a/changelogs/unreleased/update-workhorse-8-5-1.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update GitLab Workhorse to v8.5.1
-merge_request: 27217
-author:
-type: fixed
diff --git a/changelogs/unreleased/upgrade-pages-to-v1-6-1.yml b/changelogs/unreleased/upgrade-pages-to-v1-6-1.yml
new file mode 100644
index 00000000000..0ab58bb50d8
--- /dev/null
+++ b/changelogs/unreleased/upgrade-pages-to-v1-6-1.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Pages to v1.6.1
+merge_request: 29559
+author:
+type: other
diff --git a/changelogs/unreleased/use-only-all-pipelines.yml b/changelogs/unreleased/use-only-all-pipelines.yml
deleted file mode 100644
index 68364d2a923..00000000000
--- a/changelogs/unreleased/use-only-all-pipelines.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Refactor all_pipelines in Merge request
-merge_request: 25676
-author:
-type: other
diff --git a/changelogs/unreleased/use-untrusted-regexp.yml b/changelogs/unreleased/use-untrusted-regexp.yml
deleted file mode 100644
index dd7f1bcaca1..00000000000
--- a/changelogs/unreleased/use-untrusted-regexp.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use UntrustedRegexp for matching refs policy
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/variables-boolean-type.yml b/changelogs/unreleased/variables-boolean-type.yml
new file mode 100644
index 00000000000..7776657f60a
--- /dev/null
+++ b/changelogs/unreleased/variables-boolean-type.yml
@@ -0,0 +1,5 @@
+---
+title: 'API: change masked attribute type to Boolean'
+merge_request: 28758
+author:
+type: other
diff --git a/changelogs/unreleased/weimeng-email-routing.yml b/changelogs/unreleased/weimeng-email-routing.yml
new file mode 100644
index 00000000000..6536433bd03
--- /dev/null
+++ b/changelogs/unreleased/weimeng-email-routing.yml
@@ -0,0 +1,5 @@
+---
+title: Add ability to define notification email addresses for groups you belong to.
+merge_request: 25299
+author:
+type: added
diff --git a/changelogs/unreleased/winh-notes-error-handling.yml b/changelogs/unreleased/winh-notes-error-handling.yml
new file mode 100644
index 00000000000..6f23dd459d4
--- /dev/null
+++ b/changelogs/unreleased/winh-notes-error-handling.yml
@@ -0,0 +1,5 @@
+---
+title: Handle errors in successful notes reply
+merge_request: 28082
+author:
+type: fixed
diff --git a/changelogs/unreleased/winh-toggle-comment-draft.yml b/changelogs/unreleased/winh-toggle-comment-draft.yml
deleted file mode 100644
index 6b4aad55a05..00000000000
--- a/changelogs/unreleased/winh-toggle-comment-draft.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Display draft when toggling replies
-merge_request: 25563
-author:
-type: fixed
diff --git a/changelogs/unreleased/xanf-gitlab-ce-move-project-tags.yml b/changelogs/unreleased/xanf-gitlab-ce-move-project-tags.yml
deleted file mode 100644
index 124584c9bd4..00000000000
--- a/changelogs/unreleased/xanf-gitlab-ce-move-project-tags.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Move project tags to separate line
-merge_request: 26797
-author:
-type: other
diff --git a/changelogs/unreleased/xanf-gitlab-ce-transfer-disables-js.yml b/changelogs/unreleased/xanf-gitlab-ce-transfer-disables-js.yml
deleted file mode 100644
index 57c9a1aaa48..00000000000
--- a/changelogs/unreleased/xanf-gitlab-ce-transfer-disables-js.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Group transfer now properly redirects to edit on failure
-merge_request: 26837
-author:
-type: fixed
diff --git a/changelogs/unreleased/zj-fsck-no-timeout.yml b/changelogs/unreleased/zj-fsck-no-timeout.yml
deleted file mode 100644
index 044f269bb4d..00000000000
--- a/changelogs/unreleased/zj-fsck-no-timeout.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove deadline for Git fsck
-merge_request: 27299
-author:
-type: fixed
diff --git a/changelogs/unreleased/zj-remove-delta-island-feature-flag.yml b/changelogs/unreleased/zj-remove-delta-island-feature-flag.yml
new file mode 100644
index 00000000000..e752e01b701
--- /dev/null
+++ b/changelogs/unreleased/zj-remove-delta-island-feature-flag.yml
@@ -0,0 +1,3 @@
+merge_request: 28871
+title: Improve clone performance by using delta islands
+type: performance
diff --git a/changelogs/unreleased/zj-usage-ping-pool-repository.yml b/changelogs/unreleased/zj-usage-ping-pool-repository.yml
new file mode 100644
index 00000000000..62044a933d0
--- /dev/null
+++ b/changelogs/unreleased/zj-usage-ping-pool-repository.yml
@@ -0,0 +1,5 @@
+---
+title: Add Pool repository to the usage ping
+merge_request: 28267
+author:
+type: other
diff --git a/config/application.rb b/config/application.rb
index cbcfef34e01..cddd91f267a 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -164,9 +164,6 @@ module Gitlab
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
- # Can be removed once upgraded to Rails 5.1 or higher
- config.action_controller.raise_on_unfiltered_parameters = true
-
# Nokogiri is significantly faster and uses less memory than REXML
ActiveSupport::XmlMini.backend = 'Nokogiri'
diff --git a/config/database.yml.example b/config/database.yml.example
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/config/database.yml.example
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 494ddd72556..ac9b02b08d5 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -47,4 +47,7 @@ Rails.application.configure do
config.assets.quiet = true
config.allow_concurrency = defined?(::Puma)
+
+ # BetterErrors live shell (REPL) on every stack frame
+ BetterErrors::Middleware.allow_ip!("127.0.0.1/0")
end
diff --git a/config/environments/test.rb b/config/environments/test.rb
index 3461099253a..e7166882eea 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -11,7 +11,7 @@ Rails.application.configure do
# and recreated between test runs. Don't rely on the data there!
# Enabling caching of classes slows start-up time because all controllers
- # are loaded at initalization, but it reduces memory and load because files
+ # are loaded at initialization, but it reduces memory and load because files
# are not reloaded with every request. For example, caching is not necessary
# for loading database migrations but useful for handling Knapsack specs.
config.cache_classes = ENV['CACHE_CLASSES'] == 'true'
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index bdac5b2a6a1..c83f569d885 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -245,7 +245,7 @@ production: &base
host: example.com
port: 80 # Set to 443 if you serve the pages with HTTPS
https: false # Set to true if you serve the pages with HTTPS
- artifacts_server: true
+ artifacts_server: true # Set to false if you want to disable online view of HTML artifacts
# external_http: ["1.1.1.1:80", "[2001::1]:80"] # If defined, enables custom domain support in GitLab Pages
# external_https: ["1.1.1.1:443", "[2001::1]:443"] # If defined, enables custom domain and certificate support in GitLab Pages
admin:
@@ -315,6 +315,14 @@ production: &base
# path: shared/registry
# issuer: gitlab-issuer
+
+ ## Error Reporting and Logging with Sentry
+ sentry:
+ # enabled: false
+ # dsn: https://<key>@sentry.io/<project>
+ # clientside_dsn: https://<key>@sentry.io/<project>
+ # environment: 'production' # e.g. development, staging, production
+
#
# 2. GitLab CI settings
# ==========================
@@ -744,6 +752,8 @@ production: &base
monitoring:
# Time between sampling of unicorn socket metrics, in seconds
# unicorn_sampler_interval: 10
+ # Time between sampling of Puma metrics, in seconds
+ # puma_sampler_interval: 5
# IP whitelist to access monitoring endpoints
ip_whitelist:
- 127.0.0.0/8
@@ -932,6 +942,10 @@ test:
app_id: 'YOUR_CLIENT_ID',
app_secret: 'YOUR_CLIENT_SECRET',
args: { scope: 'aq:name email~rs address aq:push' } }
+ - { name: 'salesforce',
+ app_id: 'YOUR_CLIENT_ID',
+ app_secret: 'YOUR_CLIENT_SECRET'
+ }
ldap:
enabled: false
servers:
diff --git a/config/initializers/01_secret_token.rb b/config/initializers/01_secret_token.rb
index 02bded43083..9225a99a584 100644
--- a/config/initializers/01_secret_token.rb
+++ b/config/initializers/01_secret_token.rb
@@ -1,3 +1,14 @@
+# WARNING: If you add a new secret to this file, make sure you also
+# update Omnibus GitLab or updates will fail. Omnibus is responsible for
+# writing the `secrets.yml` file. If Omnibus doesn't know about a
+# secret, Rails will attempt to write to the file, but this will fail
+# because Rails doesn't have write access.
+#
+# As an example:
+# * https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27581
+# * https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/3267
+#
+#
# This file needs to be loaded BEFORE any initializers that attempt to
# prepend modules that require access to secrets (e.g. EE's 0_as_concern.rb).
#
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 3c426cdb969..0c8d94ccaed 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -136,6 +136,8 @@ Settings.gitlab['ssh_host'] ||= Settings.gitlab.host
Settings.gitlab['https'] = false if Settings.gitlab['https'].nil?
Settings.gitlab['port'] ||= ENV['GITLAB_PORT'] || (Settings.gitlab.https ? 443 : 80)
Settings.gitlab['relative_url_root'] ||= ENV['RAILS_RELATIVE_URL_ROOT'] || ''
+# / is not a valid relative URL root
+Settings.gitlab['relative_url_root'] = '' if Settings.gitlab['relative_url_root'] == '/'
Settings.gitlab['protocol'] ||= Settings.gitlab.https ? "https" : "http"
Settings.gitlab['email_enabled'] ||= true if Settings.gitlab['email_enabled'].nil?
Settings.gitlab['email_from'] ||= ENV['GITLAB_EMAIL_FROM'] || "gitlab@#{Settings.gitlab.host}"
@@ -216,6 +218,15 @@ Settings.registry['host_port'] ||= [Settings.registry['host'], Settings.regi
Settings.registry['path'] = Settings.absolute(Settings.registry['path'] || File.join(Settings.shared['path'], 'registry'))
#
+# Error Reporting and Logging with Sentry
+#
+Settings['sentry'] ||= Settingslogic.new({})
+Settings.sentry['enabled'] ||= false
+Settings.sentry['dsn'] ||= nil
+Settings.sentry['environment'] ||= nil
+Settings.sentry['clientside_dsn'] ||= nil
+
+#
# Pages
#
Settings['pages'] ||= Settingslogic.new({})
@@ -338,6 +349,10 @@ Settings.cron_jobs['pages_domain_verification_cron_worker'] ||= Settingslogic.ne
Settings.cron_jobs['pages_domain_verification_cron_worker']['cron'] ||= '*/15 * * * *'
Settings.cron_jobs['pages_domain_verification_cron_worker']['job_class'] = 'PagesDomainVerificationCronWorker'
+Settings.cron_jobs['pages_domain_removal_cron_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['pages_domain_removal_cron_worker']['cron'] ||= '47 0 * * *'
+Settings.cron_jobs['pages_domain_removal_cron_worker']['job_class'] = 'PagesDomainRemovalCronWorker'
+
Settings.cron_jobs['issue_due_scheduler_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['issue_due_scheduler_worker']['cron'] ||= '50 00 * * *'
Settings.cron_jobs['issue_due_scheduler_worker']['job_class'] = 'IssueDueSchedulerWorker'
@@ -476,6 +491,7 @@ Settings.webpack.dev_server['port'] ||= 3808
Settings['monitoring'] ||= Settingslogic.new({})
Settings.monitoring['ip_whitelist'] ||= ['127.0.0.1/8']
Settings.monitoring['unicorn_sampler_interval'] ||= 10
+Settings.monitoring['puma_sampler_interval'] ||= 5
Settings.monitoring['ruby_sampler_interval'] ||= 60
Settings.monitoring['sidekiq_exporter'] ||= Settingslogic.new({})
Settings.monitoring.sidekiq_exporter['enabled'] ||= false
diff --git a/config/initializers/7_prometheus_metrics.rb b/config/initializers/7_prometheus_metrics.rb
index 8052880cc3d..68f8487d377 100644
--- a/config/initializers/7_prometheus_metrics.rb
+++ b/config/initializers/7_prometheus_metrics.rb
@@ -29,12 +29,18 @@ if !Rails.env.test? && Gitlab::Metrics.prometheus_metrics_enabled?
Gitlab::Cluster::LifecycleEvents.on_worker_start do
defined?(::Prometheus::Client.reinitialize_on_pid_change) && Prometheus::Client.reinitialize_on_pid_change
- unless Sidekiq.server?
+ if defined?(::Unicorn)
Gitlab::Metrics::Samplers::UnicornSampler.initialize_instance(Settings.monitoring.unicorn_sampler_interval).start
end
Gitlab::Metrics::Samplers::RubySampler.initialize_instance(Settings.monitoring.ruby_sampler_interval).start
end
+
+ if defined?(::Puma)
+ Gitlab::Cluster::LifecycleEvents.on_master_start do
+ Gitlab::Metrics::Samplers::PumaSampler.initialize_instance(Settings.monitoring.puma_sampler_interval).start
+ end
+ end
end
Gitlab::Cluster::LifecycleEvents.on_master_restart do
diff --git a/config/initializers/8_devise.rb b/config/initializers/8_devise.rb
index 4683b02f300..3dd12c7e64d 100644
--- a/config/initializers/8_devise.rb
+++ b/config/initializers/8_devise.rb
@@ -100,6 +100,11 @@ Devise.setup do |config|
# secure: true in order to force SSL only cookies.
# config.cookie_options = {}
+ # When set to false, does not sign a user in automatically after their password is
+ # changed. Defaults to true, so a user is signed in automatically after a password
+ # is changed.
+ config.sign_in_after_change_password = false
+
# Send a notification email when the user's password is changed
config.send_password_change_notification = true
diff --git a/config/initializers/action_dispatch_http_mime_negotiation.rb b/config/initializers/action_dispatch_http_mime_negotiation.rb
index bdf5b0babfb..6c31de2de55 100644
--- a/config/initializers/action_dispatch_http_mime_negotiation.rb
+++ b/config/initializers/action_dispatch_http_mime_negotiation.rb
@@ -2,7 +2,7 @@
# the extension of the full URL path if no explicit `format` param or `Accept`
# header is provided, like when simply browsing to a page in your browser.
#
-# This is undesireable in GitLab, because many of our paths will end in a ref or
+# This is undesirable in GitLab, because many of our paths will end in a ref or
# blob name that can end with any extension, while these pages should still be
# presented as HTML unless otherwise specified.
diff --git a/config/initializers/active_record_avoid_type_casting_in_uniqueness_validator.rb b/config/initializers/active_record_avoid_type_casting_in_uniqueness_validator.rb
deleted file mode 100644
index 228ced32188..00000000000
--- a/config/initializers/active_record_avoid_type_casting_in_uniqueness_validator.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-# This is a monkey patch which must be removed when migrating to Rails 5.1 from 5.0.
-#
-# In Rails 5.0 there was introduced a bug which casts types in the uniqueness validator.
-# https://github.com/rails/rails/pull/23523/commits/811a4fa8eb6ceea841e61e8ac05747ffb69595ae
-#
-# That causes to bugs like this:
-#
-# 1) API::Users POST /user/:id/gpg_keys/:key_id/revoke when authenticated revokes existing key
-# Failure/Error: let(:gpg_key) { create(:gpg_key, user: user) }
-#
-# TypeError:
-# can't cast Hash
-# # ./spec/requests/api/users_spec.rb:7:in `block (2 levels) in <top (required)>'
-# # ./spec/requests/api/users_spec.rb:908:in `block (4 levels) in <top (required)>'
-# # ------------------
-# # --- Caused by: ---
-# # TypeError:
-# # TypeError
-# # ./spec/requests/api/users_spec.rb:7:in `block (2 levels) in <top (required)>'
-#
-# This bug was fixed in Rails 5.1 by https://github.com/rails/rails/pull/24745/commits/aa062318c451512035c10898a1af95943b1a3803
-
-if Rails.gem_version >= Gem::Version.new("5.1")
- raise "Remove this monkey patch: #{__FILE__}"
-end
-
-# Copy-paste from https://github.com/kamipo/rails/blob/aa062318c451512035c10898a1af95943b1a3803/activerecord/lib/active_record/validations/uniqueness.rb
-# including local fixes to make Rubocop happy again.
-module ActiveRecord
- module Validations
- class UniquenessValidator < ActiveModel::EachValidator # :nodoc:
- def validate_each(record, attribute, value)
- finder_class = find_finder_class_for(record)
- table = finder_class.arel_table
- value = map_enum_attribute(finder_class, attribute, value)
-
- relation = build_relation(finder_class, table, attribute, value)
-
- if record.persisted?
- if finder_class.primary_key
- relation = relation.where.not(finder_class.primary_key => record.id_was || record.id)
- else
- raise UnknownPrimaryKey.new(finder_class, "Can not validate uniqueness for persisted record without primary key.")
- end
- end
-
- relation = scope_relation(record, table, relation)
- relation = relation.merge(options[:conditions]) if options[:conditions]
-
- if relation.exists?
- error_options = options.except(:case_sensitive, :scope, :conditions)
- error_options[:value] = value
-
- record.errors.add(attribute, :taken, error_options)
- end
- rescue RangeError
- end
-
- protected
-
- def build_relation(klass, table, attribute, value) #:nodoc:
- if reflection = klass._reflect_on_association(attribute)
- attribute = reflection.foreign_key
- value = value.attributes[reflection.klass.primary_key] unless value.nil?
- end
-
- # the attribute may be an aliased attribute
- if klass.attribute_alias?(attribute)
- attribute = klass.attribute_alias(attribute)
- end
-
- attribute_name = attribute.to_s
-
- column = klass.columns_hash[attribute_name]
- cast_type = klass.type_for_attribute(attribute_name)
-
- comparison =
- if !options[:case_sensitive] && !value.nil?
- # will use SQL LOWER function before comparison, unless it detects a case insensitive collation
- klass.connection.case_insensitive_comparison(table, attribute, column, value)
- else
- klass.connection.case_sensitive_comparison(table, attribute, column, value)
- end
-
- if value.nil?
- klass.unscoped.where(comparison)
- else
- bind = Relation::QueryAttribute.new(attribute_name, value, cast_type)
- klass.unscoped.where(comparison, bind)
- end
- end
- end
- end
-end
diff --git a/config/initializers/active_record_build_select.rb b/config/initializers/active_record_build_select.rb
new file mode 100644
index 00000000000..ab5a872cac6
--- /dev/null
+++ b/config/initializers/active_record_build_select.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+# rubocop:disable Gitlab/ModuleWithInstanceVariables
+
+# build_select only selects the required fields if the model has ignored_columns.
+# This is incompatible with some migrations or background migration specs because
+# rails keeps a statement cache in memory. So if a model with ignored_columns in a
+# migration is used, the query with select table.col1, table.col2 is stored in the
+# statement cache. If a different migration is then run and one of these columns is
+# removed in the meantime, the query is invalid.
+
+module ActiveRecord
+ module QueryMethods
+ private
+
+ def build_select(arel)
+ if select_values.any?
+ arel.project(*arel_columns(select_values.uniq))
+ else
+ arel.project(@klass.arel_table[Arel.star])
+ end
+ end
+ end
+end
diff --git a/config/initializers/active_record_locking.rb b/config/initializers/active_record_locking.rb
deleted file mode 100644
index 1bd1a12e4b7..00000000000
--- a/config/initializers/active_record_locking.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-# rubocop:disable Lint/RescueException
-
-# Remove this monkey patch when we move to Rails 5.1, because the bug has been fixed in https://github.com/rails/rails/pull/26050.
-if Rails.gem_version >= Gem::Version.new("5.1")
- raise "Remove this monkey patch: #{__FILE__}"
-end
-
-module ActiveRecord
- module Locking
- module Optimistic
- # We overwrite this method because we don't want to have default value
- # for newly created records
- def _create_record(attribute_names = self.attribute_names, *) # :nodoc:
- super
- end
-
- def _update_record(attribute_names = self.attribute_names) #:nodoc:
- return super unless locking_enabled?
- return 0 if attribute_names.empty?
-
- lock_col = self.class.locking_column
- previous_lock_value = send(lock_col).to_i
- increment_lock
-
- attribute_names += [lock_col]
- attribute_names.uniq!
-
- begin
- relation = self.class.unscoped
-
- affected_rows = relation.where(
- self.class.primary_key => id,
- # Patched because when `lock_version` is read as `0`, it may actually be `NULL` in the DB.
- lock_col => previous_lock_value == 0 ? [nil, 0] : previous_lock_value
- ).update_all(
- attributes_for_update(attribute_names).map do |name|
- [name, _read_attribute(name)]
- end.to_h
- )
-
- unless affected_rows == 1
- raise ActiveRecord::StaleObjectError.new(self, "update")
- end
-
- affected_rows
-
- # If something went wrong, revert the version.
- rescue Exception
- send(lock_col + '=', previous_lock_value)
- raise
- end
- end
-
- # This is patched because we need it to query `lock_version IS NULL`
- # rather than `lock_version = 0` whenever lock_version is NULL.
- def relation_for_destroy
- return super unless locking_enabled?
-
- column_name = self.class.locking_column
- super.where(self.class.arel_table[column_name].eq(self[column_name]))
- end
- end
-
- # This is patched because we want `lock_version` default to `NULL`
- # rather than `0`
- class LockingType
- def deserialize(value)
- super
- end
-
- def serialize(value)
- super
- end
- end
- end
-end
diff --git a/config/initializers/ar_native_database_types.rb b/config/initializers/ar_native_database_types.rb
index 3522b1db536..6d397661f75 100644
--- a/config/initializers/ar_native_database_types.rb
+++ b/config/initializers/ar_native_database_types.rb
@@ -4,7 +4,8 @@ module ActiveRecord
module ConnectionAdapters
class AbstractMysqlAdapter
NATIVE_DATABASE_TYPES.merge!(
- bigserial: { name: 'bigint(20) auto_increment PRIMARY KEY' }
+ bigserial: { name: 'bigint(20) auto_increment PRIMARY KEY' },
+ serial: { name: 'int auto_increment PRIMARY KEY' }
)
end
end
diff --git a/config/initializers/config_initializers_active_record_locking.rb b/config/initializers/config_initializers_active_record_locking.rb
new file mode 100644
index 00000000000..608d63223a3
--- /dev/null
+++ b/config/initializers/config_initializers_active_record_locking.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+# ensure ActiveRecord's version has been required already
+require 'active_record/locking/optimistic'
+
+# rubocop:disable Lint/RescueException
+module ActiveRecord
+ module Locking
+ module Optimistic
+ private
+
+ def _update_row(attribute_names, attempted_action = "update")
+ return super unless locking_enabled?
+
+ begin
+ locking_column = self.class.locking_column
+ previous_lock_value = read_attribute_before_type_cast(locking_column)
+ attribute_names << locking_column
+
+ self[locking_column] += 1
+
+ # Patched because when `lock_version` is read as `0`, it may actually be `NULL` in the DB.
+ possible_previous_lock_value = previous_lock_value.to_i == 0 ? [nil, 0] : previous_lock_value
+
+ affected_rows = self.class.unscoped._update_record(
+ arel_attributes_with_values(attribute_names),
+ self.class.primary_key => id_in_database,
+ locking_column => possible_previous_lock_value
+ )
+
+ if affected_rows != 1
+ raise ActiveRecord::StaleObjectError.new(self, attempted_action)
+ end
+
+ affected_rows
+
+ # If something went wrong, revert the locking_column value.
+ rescue Exception
+ self[locking_column] = previous_lock_value.to_i
+ raise
+ end
+ end
+ end
+ end
+end
diff --git a/config/initializers/gettext_rails_i18n_patch.rb b/config/initializers/gettext_rails_i18n_patch.rb
index c1342f48ebd..714dd505824 100644
--- a/config/initializers/gettext_rails_i18n_patch.rb
+++ b/config/initializers/gettext_rails_i18n_patch.rb
@@ -2,7 +2,7 @@ require 'gettext_i18n_rails/haml_parser'
require 'gettext_i18n_rails_js/parser/javascript'
require 'json'
-VUE_TRANSLATE_REGEX = /((%[\w.-]+)(?:\s))?{{ (N|n|s)?__\((.*)\) }}/
+VUE_TRANSLATE_REGEX = /((%[\w.-]+)(?:\s))?{{ (N|n|s)?__\((.*)\) }}/.freeze
module GettextI18nRails
class HamlParser
diff --git a/config/initializers/hipchat_client_patch.rb b/config/initializers/hipchat_client_patch.rb
index 1879ecb15fb..51bd48af320 100644
--- a/config/initializers/hipchat_client_patch.rb
+++ b/config/initializers/hipchat_client_patch.rb
@@ -2,14 +2,14 @@
# This monkey patches the HTTParty used in https://github.com/hipchat/hipchat-rb.
module HipChat
class Client
- connection_adapter ::Gitlab::ProxyHTTPConnectionAdapter
+ connection_adapter ::Gitlab::HTTPConnectionAdapter
end
class Room
- connection_adapter ::Gitlab::ProxyHTTPConnectionAdapter
+ connection_adapter ::Gitlab::HTTPConnectionAdapter
end
class User
- connection_adapter ::Gitlab::ProxyHTTPConnectionAdapter
+ connection_adapter ::Gitlab::HTTPConnectionAdapter
end
end
diff --git a/config/initializers/http_hostname_override.rb b/config/initializers/http_hostname_override.rb
new file mode 100644
index 00000000000..58dd380326f
--- /dev/null
+++ b/config/initializers/http_hostname_override.rb
@@ -0,0 +1,49 @@
+# This override allows passing `@hostname_override` to the SNI protocol,
+# which is used to lookup the correct SSL certificate in the
+# request handshake process.
+#
+# Given we've forced the HTTP request to be sent to the resolved
+# IP address in a few scenarios (e.g.: `Gitlab::HTTP` through
+# `Gitlab::UrlBlocker.validate!`), we need to provide the _original_
+# hostname via SNI in order to have a clean connection setup.
+#
+# This is ultimately needed in order to avoid DNS rebinding attacks
+# through HTTP requests.
+#
+class OpenSSL::SSL::SSLContext
+ attr_accessor :hostname_override
+end
+
+class OpenSSL::SSL::SSLSocket
+ module HostnameOverride
+ # rubocop: disable Gitlab/ModuleWithInstanceVariables
+ def hostname=(hostname)
+ super(@context.hostname_override || hostname)
+ end
+
+ def post_connection_check(hostname)
+ super(@context.hostname_override || hostname)
+ end
+ # rubocop: enable Gitlab/ModuleWithInstanceVariables
+ end
+
+ prepend HostnameOverride
+end
+
+class Net::HTTP
+ attr_accessor :hostname_override
+ SSL_IVNAMES << :@hostname_override
+ SSL_ATTRIBUTES << :hostname_override
+
+ module HostnameOverride
+ def addr_port
+ return super unless hostname_override
+
+ addr = hostname_override
+ default_port = use_ssl? ? Net::HTTP.https_default_port : Net::HTTP.http_default_port
+ default_port == port ? addr : "#{addr}:#{port}"
+ end
+ end
+
+ prepend HostnameOverride
+end
diff --git a/config/initializers/lograge.rb b/config/initializers/lograge.rb
index 5e790a9eccb..1ad93e14f7e 100644
--- a/config/initializers/lograge.rb
+++ b/config/initializers/lograge.rb
@@ -35,7 +35,7 @@ unless Sidekiq.server?
end
payload[:response] = event.payload[:response] if event.payload[:response]
- payload[Gitlab::CorrelationId::LOG_KEY] = Gitlab::CorrelationId.current_id
+ payload[Labkit::Correlation::CorrelationId::LOG_KEY] = Labkit::Correlation::CorrelationId.current_id
payload
end
diff --git a/config/initializers/peek.rb b/config/initializers/peek.rb
index e051e5c68c4..cb108416b10 100644
--- a/config/initializers/peek.rb
+++ b/config/initializers/peek.rb
@@ -10,6 +10,18 @@ elsif Gitlab::Database.postgresql?
require 'peek-pg'
PEEK_DB_CLIENT = ::PG::Connection
PEEK_DB_VIEW = Peek::Views::PG
+
+ # Remove once we have https://github.com/peek/peek-pg/pull/10
+ module ::Peek::PGInstrumented
+ def exec_params(*args)
+ start = Time.now
+ super(*args)
+ ensure
+ duration = (Time.now - start)
+ PEEK_DB_CLIENT.query_time.update { |value| value + duration }
+ PEEK_DB_CLIENT.query_count.update { |value| value + 1 }
+ end
+ end
else
raise "Unsupported database adapter for peek!"
end
@@ -19,7 +31,7 @@ Peek.into Peek::Views::Gitaly
Peek.into Peek::Views::Rblineprof
Peek.into Peek::Views::Redis
Peek.into Peek::Views::GC
-Peek.into Peek::Views::Tracing if Gitlab::Tracing.tracing_url_enabled?
+Peek.into Peek::Views::Tracing if Labkit::Tracing.tracing_url_enabled?
# rubocop:disable Naming/ClassAndModuleCamelCase
class PEEK_DB_CLIENT
diff --git a/config/initializers/postgresql_opclasses_support.rb b/config/initializers/postgresql_opclasses_support.rb
index b066f3788ec..7e912180820 100644
--- a/config/initializers/postgresql_opclasses_support.rb
+++ b/config/initializers/postgresql_opclasses_support.rb
@@ -78,7 +78,7 @@ module ActiveRecord
if index_name.length > max_index_length
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{max_index_length} characters"
end
- if data_source_exists?(table_name) && index_name_exists?(table_name, index_name, false)
+ if data_source_exists?(table_name) && index_name_exists?(table_name, index_name)
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
end
index_columns = quoted_columns_for_index(column_names, options).join(", ")
diff --git a/config/initializers/rack_attack_logging.rb b/config/initializers/rack_attack_logging.rb
index 8bb9ea29c33..2a3fdc8de5f 100644
--- a/config/initializers/rack_attack_logging.rb
+++ b/config/initializers/rack_attack_logging.rb
@@ -1,7 +1,15 @@
+# frozen_string_literal: true
+#
# Adds logging for all Rack Attack blocks and throttling events.
ActiveSupport::Notifications.subscribe('rack.attack') do |name, start, finish, request_id, req|
if [:throttle, :blacklist].include? req.env['rack.attack.match_type']
- Rails.logger.info("Rack_Attack: #{req.env['rack.attack.match_type']} #{req.ip} #{req.request_method} #{req.fullpath}")
+ Gitlab::AuthLogger.error(
+ message: 'Rack_Attack',
+ env: req.env['rack.attack.match_type'],
+ ip: req.ip,
+ request_method: req.request_method,
+ fullpath: req.fullpath
+ )
end
end
diff --git a/config/initializers/rack_timeout.rb b/config/initializers/rack_timeout.rb
new file mode 100644
index 00000000000..58f46b55725
--- /dev/null
+++ b/config/initializers/rack_timeout.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+# Unicorn terminates any request which runs longer than 60 seconds.
+# Puma doesn't have any timeout mechanism for terminating long-running
+# requests, to make sure that server is not paralyzed by long-running
+# or stuck queries, we add a request timeout which terminates the
+# request after 60 seconds. This may be dangerous in some situations
+# (https://github.com/heroku/rack-timeout/blob/master/doc/exceptions.md)
+# and it's used only as the last resort. In such case this termination is
+# logged and we should fix the potential timeout issue in the code itself.
+
+if defined?(::Puma) && !Rails.env.test?
+ require 'rack/timeout/base'
+
+ Gitlab::Application.configure do |config|
+ config.middleware.insert_before(Rack::Runtime, Rack::Timeout,
+ service_timeout: 60,
+ wait_timeout: 90)
+ end
+
+ observer = Gitlab::Cluster::RackTimeoutObserver.new
+ Rack::Timeout.register_state_change_observer(:gitlab_rack_timeout, &observer.callback)
+end
diff --git a/config/initializers/seed_fu.rb b/config/initializers/seed_fu.rb
new file mode 100644
index 00000000000..2e48e41a311
--- /dev/null
+++ b/config/initializers/seed_fu.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+if Gitlab.ee?
+ SeedFu.fixture_paths += %W[ee/db/fixtures ee/db/fixtures/#{Rails.env}]
+end
diff --git a/config/initializers/sentry.rb b/config/initializers/sentry.rb
index 680cfa6f0ed..e5589ce0ad1 100644
--- a/config/initializers/sentry.rb
+++ b/config/initializers/sentry.rb
@@ -14,6 +14,7 @@ def configure_sentry
Raven.configure do |config|
config.dsn = Gitlab::CurrentSettings.current_application_settings.sentry_dsn
config.release = Gitlab.revision
+ config.current_environment = Gitlab.config.sentry.environment.presence
# Sanitize fields based on those sanitized from Rails.
config.sanitize_fields = Rails.application.config.filter_parameters.map(&:to_s)
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index 2e4aa9c1053..7b69cf11288 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -1,5 +1,17 @@
require 'sidekiq/web'
+def enable_reliable_fetch?
+ return true unless Feature::FlipperFeature.table_exists?
+
+ Feature.enabled?(:gitlab_sidekiq_reliable_fetcher, default_enabled: true)
+end
+
+def enable_semi_reliable_fetch_mode?
+ return true unless Feature::FlipperFeature.table_exists?
+
+ Feature.enabled?(:gitlab_sidekiq_enable_semi_reliable_fetcher, default_enabled: true)
+end
+
# Disable the Sidekiq Rack session since GitLab already has its own session store.
# CSRF protection still works (https://github.com/mperham/sidekiq/commit/315504e766c4fd88a29b7772169060afc4c40329).
Sidekiq::Web.set :sessions, false
@@ -45,9 +57,8 @@ Sidekiq.configure_server do |config|
ActiveRecord::Base.clear_all_connections!
end
- if Feature::FlipperFeature.table_exists? && Feature.enabled?(:gitlab_sidekiq_reliable_fetcher)
- # By default we're going to use Semi Reliable Fetch
- config.options[:semi_reliable_fetch] = Feature.enabled?(:gitlab_sidekiq_enable_semi_reliable_fetcher, default_enabled: true)
+ if enable_reliable_fetch?
+ config.options[:semi_reliable_fetch] = enable_semi_reliable_fetch_mode?
Sidekiq::ReliableFetch.setup_reliable_fetch!(config)
end
diff --git a/config/initializers/tracing.rb b/config/initializers/tracing.rb
index ddd91150c90..3c8779f238f 100644
--- a/config/initializers/tracing.rb
+++ b/config/initializers/tracing.rb
@@ -1,16 +1,14 @@
# frozen_string_literal: true
-if Gitlab::Tracing.enabled?
- require 'opentracing'
-
+if Labkit::Tracing.enabled?
Rails.application.configure do |config|
- config.middleware.insert_after Gitlab::Middleware::CorrelationId, ::Gitlab::Tracing::RackMiddleware
+ config.middleware.insert_after Gitlab::Middleware::CorrelationId, ::Labkit::Tracing::RackMiddleware
end
# Instrument the Sidekiq client
Sidekiq.configure_client do |config|
config.client_middleware do |chain|
- chain.add Gitlab::Tracing::Sidekiq::ClientMiddleware
+ chain.add Labkit::Tracing::Sidekiq::ClientMiddleware
end
end
@@ -18,20 +16,20 @@ if Gitlab::Tracing.enabled?
if Sidekiq.server?
Sidekiq.configure_server do |config|
config.server_middleware do |chain|
- chain.add Gitlab::Tracing::Sidekiq::ServerMiddleware
+ chain.add Labkit::Tracing::Sidekiq::ServerMiddleware
end
end
end
# Instrument Rails
- Gitlab::Tracing::Rails::ActiveRecordSubscriber.instrument
- Gitlab::Tracing::Rails::ActionViewSubscriber.instrument
+ Labkit::Tracing::Rails::ActiveRecordSubscriber.instrument
+ Labkit::Tracing::Rails::ActionViewSubscriber.instrument
# In multi-processed clustered architectures (puma, unicorn) don't
# start tracing until the worker processes are spawned. This works
# around issues when the opentracing implementation spawns threads
Gitlab::Cluster::LifecycleEvents.on_worker_start do
- tracer = Gitlab::Tracing::Factory.create_tracer(Gitlab.process_name, Gitlab::Tracing.connection_string)
+ tracer = Labkit::Tracing::Factory.create_tracer(Gitlab.process_name, Labkit::Tracing.connection_string)
OpenTracing.global_tracer = tracer if tracer
end
end
diff --git a/config/karma.config.js b/config/karma.config.js
index 7e1e89f3c10..2a5bf3581e0 100644
--- a/config/karma.config.js
+++ b/config/karma.config.js
@@ -4,15 +4,27 @@ const chalk = require('chalk');
const webpack = require('webpack');
const argumentsParser = require('commander');
const webpackConfig = require('./webpack.config.js');
+const IS_EE = require('./helpers/is_ee_env');
const ROOT_PATH = path.resolve(__dirname, '..');
const SPECS_PATH = /^(?:\.[\\\/])?(ee[\\\/])?spec[\\\/]javascripts[\\\/]/;
-function fatalError(message) {
+function exitError(message) {
console.error(chalk.red(`\nError: ${message}\n`));
process.exit(1);
}
+function exitWarn(message) {
+ console.error(chalk.yellow(`\nWarn: ${message}\n`));
+ process.exit(0);
+}
+
+function exit(message, isError = true) {
+ const fn = isError ? exitError : exitWarn;
+
+ fn(message);
+}
+
// disable problematic options
webpackConfig.entry = undefined;
webpackConfig.mode = 'development';
@@ -30,7 +42,8 @@ webpackConfig.plugins.push(
}),
);
-const specFilters = argumentsParser
+const options = argumentsParser
+ .option('--no-fail-on-empty-test-suite')
.option(
'-f, --filter-spec [filter]',
'Filter run spec files by path. Multiple filters are like a logical OR.',
@@ -40,7 +53,9 @@ const specFilters = argumentsParser
},
[],
)
- .parse(process.argv).filterSpec;
+ .parse(process.argv);
+
+const specFilters = options.filterSpec;
const createContext = (specFiles, regex, suffix) => {
const newContext = specFiles.reduce((context, file) => {
@@ -72,11 +87,13 @@ if (specFilters.length) {
filteredSpecFiles = [...new Set(filteredSpecFiles)];
if (filteredSpecFiles.length < 1) {
- fatalError('Your filter did not match any test files.');
+ const isError = options.failOnEmptyTestSuite;
+
+ exit('Your filter did not match any test files.', isError);
}
if (!filteredSpecFiles.every(file => SPECS_PATH.test(file))) {
- fatalError('Test files must be located within /spec/javascripts.');
+ exitError('Test files must be located within /spec/javascripts.');
}
const CE_FILES = filteredSpecFiles.filter(file => !file.startsWith('ee'));
@@ -90,6 +107,8 @@ if (specFilters.length) {
module.exports = function(config) {
process.env.TZ = 'Etc/UTC';
+ const fixturesPath = `${IS_EE ? 'ee/' : ''}spec/javascripts/fixtures`;
+
const karmaConfig = {
basePath: ROOT_PATH,
browsers: ['ChromeHeadlessCustom'],
@@ -104,13 +123,15 @@ module.exports = function(config) {
// chrome cannot run in sandboxed mode inside a docker container unless it is run with
// escalated kernel privileges (e.g. docker run --cap-add=CAP_SYS_ADMIN)
'--no-sandbox',
+ // https://bugs.chromium.org/p/chromedriver/issues/detail?id=2870
+ '--enable-features=NetworkService,NetworkServiceInProcess',
],
},
},
frameworks: ['jasmine'],
files: [
{ pattern: 'spec/javascripts/test_bundle.js', watched: false },
- { pattern: 'spec/javascripts/fixtures/**/*@(.json|.html|.png)', included: false },
+ { pattern: `${fixturesPath}/**/*@(.json|.html|.png|.bmpr|.pdf)`, included: false },
],
preprocessors: {
'spec/javascripts/**/*.js': ['webpack', 'sourcemap'],
diff --git a/config/locales/en.yml b/config/locales/en.yml
index eb3b7771968..a3dceb2fb62 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -14,6 +14,8 @@ en:
token: "Auth Token"
project: "Project"
api_url: "Sentry API URL"
+ project/metrics_setting:
+ external_dashboard_url: "External dashboard URL"
errors:
messages:
label_already_exists_at_group_level: "already exists at group level for %{group}. Please choose another one."
diff --git a/config/prometheus/common_metrics.yml b/config/prometheus/common_metrics.yml
index 884868c6336..3c67ca36791 100644
--- a/config/prometheus/common_metrics.yml
+++ b/config/prometheus/common_metrics.yml
@@ -1,42 +1,33 @@
- # NGINX Ingress metrics for pre-0.16.0 versions
+dashboard: 'Environment metrics'
+priority: 1
+panel_groups:
+# NGINX Ingress metrics for pre-0.16.0 versions
- group: Response metrics (NGINX Ingress VTS)
priority: 10
- metrics:
+ panels:
- title: "Throughput"
+ type: "area-chart"
y_label: "Requests / Sec"
- required_metrics:
- - nginx_upstream_responses_total
weight: 1
- queries:
+ metrics:
- id: response_metrics_nginx_ingress_throughput_status_code
query_range: 'sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) by (status_code)'
unit: req / sec
label: Status Code
- series:
- - label: status_code
- when:
- - value: 2xx
- color: green
- - value: 4xx
- color: orange
- - value: 5xx
- color: red
- title: "Latency"
+ type: "area-chart"
y_label: "Latency (ms)"
- required_metrics:
- - nginx_upstream_response_msecs_avg
weight: 1
- queries:
+ metrics:
- id: response_metrics_nginx_ingress_latency_pod_average
query_range: 'avg(nginx_upstream_response_msecs_avg{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"})'
label: Pod average
unit: ms
- title: "HTTP Error Rate"
+ type: "area-chart"
y_label: "HTTP Errors"
- required_metrics:
- - nginx_upstream_responses_total
weight: 1
- queries:
+ metrics:
- id: response_metrics_nginx_ingress_http_error_rate
query_range: 'sum(rate(nginx_upstream_responses_total{status_code="5xx", upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) / sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) * 100'
label: 5xx Errors
@@ -44,228 +35,180 @@
# NGINX Ingress metrics for post-0.16.0 versions
- group: Response metrics (NGINX Ingress)
priority: 10
- metrics:
+ panels:
- title: "Throughput"
+ type: "area-chart"
y_label: "Requests / Sec"
- required_metrics:
- - nginx_ingress_controller_requests
weight: 1
- queries:
+ metrics:
- id: response_metrics_nginx_ingress_16_throughput_status_code
query_range: 'sum(label_replace(rate(nginx_ingress_controller_requests{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m]), "status_code", "${1}xx", "status", "(.)..")) by (status_code)'
unit: req / sec
label: Status Code
- series:
- - label: status_code
- when:
- - value: 2xx
- color: green
- - value: 3xx
- color: blue
- - value: 4xx
- color: orange
- - value: 5xx
- color: red
- title: "Latency"
+ type: "area-chart"
y_label: "Latency (ms)"
- required_metrics:
- - nginx_ingress_controller_ingress_upstream_latency_seconds_sum
weight: 1
- queries:
+ metrics:
- id: response_metrics_nginx_ingress_16_latency_pod_average
query_range: 'sum(rate(nginx_ingress_controller_ingress_upstream_latency_seconds_sum{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) / sum(rate(nginx_ingress_controller_ingress_upstream_latency_seconds_count{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) * 1000'
label: Pod average
unit: ms
- title: "HTTP Error Rate"
+ type: "area-chart"
y_label: "HTTP Errors"
- required_metrics:
- - nginx_ingress_controller_requests
weight: 1
- queries:
+ metrics:
- id: response_metrics_nginx_ingress_16_http_error_rate
query_range: 'sum(rate(nginx_ingress_controller_requests{status=~"5.*",namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) / sum(rate(nginx_ingress_controller_requests{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) * 100'
label: 5xx Errors
unit: "%"
- group: Response metrics (HA Proxy)
priority: 10
- metrics:
+ panels:
- title: "Throughput"
+ type: "area-chart"
y_label: "Requests / Sec"
- required_metrics:
- - haproxy_frontend_http_requests_total
weight: 1
- queries:
+ metrics:
- id: response_metrics_ha_proxy_throughput_status_code
query_range: 'sum(rate(haproxy_frontend_http_requests_total{%{environment_filter}}[2m])) by (code)'
unit: req / sec
label: Status Code
- series:
- - label: status_code
- when:
- - value: 2xx
- color: green
- - value: 4xx
- color: yellow
- - value: 5xx
- color: red
- title: "HTTP Error Rate"
+ type: "area-chart"
y_label: "Error Rate (%)"
- required_metrics:
- - haproxy_frontend_http_responses_total
weight: 1
- queries:
+ metrics:
- id: response_metrics_ha_proxy_http_error_rate
query_range: 'sum(rate(haproxy_frontend_http_responses_total{code="5xx",%{environment_filter}}[2m])) / sum(rate(haproxy_frontend_http_responses_total{%{environment_filter}}[2m]))'
label: HTTP Errors
unit: "%"
- group: Response metrics (AWS ELB)
priority: 10
- metrics:
+ panels:
- title: "Throughput"
+ type: "area-chart"
y_label: "Requests / Sec"
- required_metrics:
- - aws_elb_request_count_sum
weight: 1
- queries:
+ metrics:
- id: response_metrics_aws_elb_throughput_requests
query_range: 'sum(aws_elb_request_count_sum{%{environment_filter}}) / 60'
label: Total
unit: req / sec
- title: "Latency"
+ type: "area-chart"
y_label: "Latency (ms)"
- required_metrics:
- - aws_elb_latency_average
weight: 1
- queries:
+ metrics:
- id: response_metrics_aws_elb_latency_average
query_range: 'avg(aws_elb_latency_average{%{environment_filter}}) * 1000'
label: Average
unit: ms
- title: "HTTP Error Rate"
+ type: "area-chart"
y_label: "Error Rate (%)"
- required_metrics:
- - aws_elb_request_count_sum
- - aws_elb_httpcode_backend_5_xx_sum
weight: 1
- queries:
+ metrics:
- id: response_metrics_aws_elb_http_error_rate
query_range: 'sum(aws_elb_httpcode_backend_5_xx_sum{%{environment_filter}}) / sum(aws_elb_request_count_sum{%{environment_filter}})'
label: HTTP Errors
unit: "%"
- group: Response metrics (NGINX)
priority: 10
- metrics:
+ panels:
- title: "Throughput"
+ type: "area-chart"
y_label: "Requests / Sec"
- required_metrics:
- - nginx_server_requests
weight: 1
- queries:
+ metrics:
- id: response_metrics_nginx_throughput_status_code
query_range: 'sum(rate(nginx_server_requests{server_zone!="*", server_zone!="_", %{environment_filter}}[2m])) by (code)'
unit: req / sec
label: Status Code
- series:
- - label: status_code
- when:
- - value: 2xx
- color: green
- - value: 4xx
- color: orange
- - value: 5xx
- color: red
- title: "Latency"
+ type: "area-chart"
y_label: "Latency (ms)"
- required_metrics:
- - nginx_server_requestMsec
weight: 1
- queries:
+ metrics:
- id: response_metrics_nginx_latency
query_range: 'avg(nginx_server_requestMsec{%{environment_filter}})'
label: Upstream
unit: ms
- title: "HTTP Error Rate"
+ type: "area-chart"
y_label: "HTTP 500 Errors / Sec"
- required_metrics:
- - nginx_server_requests
weight: 1
- queries:
+ metrics:
- id: response_metrics_nginx_http_error_rate
query_range: 'sum(rate(nginx_server_requests{code="5xx", %{environment_filter}}[2m]))'
label: HTTP Errors
unit: "errors / sec"
- group: System metrics (Kubernetes)
priority: 5
- metrics:
+ panels:
- title: "Memory Usage (Total)"
+ type: "area-chart"
y_label: "Total Memory Used"
- required_metrics:
- - container_memory_usage_bytes
weight: 4
- queries:
+ metrics:
- id: system_metrics_kubernetes_container_memory_total
query_range: 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) /1024/1024/1024'
label: Total
unit: GB
- title: "Core Usage (Total)"
+ type: "area-chart"
y_label: "Total Cores"
- required_metrics:
- - container_cpu_usage_seconds_total
weight: 3
- queries:
+ metrics:
- id: system_metrics_kubernetes_container_cores_total
query_range: 'avg(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}[15m])) by (job)) without (job)'
label: Total
unit: "cores"
- title: "Memory Usage (Pod average)"
+ type: "area-chart"
y_label: "Memory Used per Pod"
- required_metrics:
- - container_memory_usage_bytes
weight: 2
- queries:
+ metrics:
- id: system_metrics_kubernetes_container_memory_average
query_range: 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024'
label: Pod average
unit: MB
- title: "Canary: Memory Usage (Pod Average)"
+ type: "area-chart"
y_label: "Memory Used per Pod"
- required_metrics:
- - container_memory_usage_bytes
weight: 2
- queries:
+ metrics:
- id: system_metrics_kubernetes_container_memory_average_canary
query_range: 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024'
label: Pod average
unit: MB
track: canary
- title: "Core Usage (Pod Average)"
+ type: "area-chart"
y_label: "Cores per Pod"
- required_metrics:
- - container_cpu_usage_seconds_total
weight: 1
- queries:
+ metrics:
- id: system_metrics_kubernetes_container_core_usage
query_range: 'avg(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}[15m])) by (job)) without (job) / count(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}[15m])) by (pod_name))'
label: Pod average
unit: "cores"
- title: "Canary: Core Usage (Pod Average)"
+ type: "area-chart"
y_label: "Cores per Pod"
- required_metrics:
- - container_cpu_usage_seconds_total
weight: 1
- queries:
+ metrics:
- id: system_metrics_kubernetes_container_core_usage_canary
query_range: 'avg(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}[15m])) by (job)) without (job) / count(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}[15m])) by (pod_name))'
label: Pod average
unit: "cores"
track: canary
- title: "Knative function invocations"
+ type: "area-chart"
y_label: "Invocations"
- required_metrics:
- - istio_revision_request_count
weight: 1
- queries:
+ metrics:
- id: system_metrics_knative_function_invocation_count
- query_range: 'floor(sum(rate(istio_revision_request_count{destination_configuration="%{function_name}", destination_namespace="%{kube_namespace}"}[1m])*30))'
+ query_range: 'floor(sum(rate(istio_revision_request_count{destination_configuration="%{function_name}", destination_namespace="%{kube_namespace}"}[1m])/3))'
label: invocations / minute
unit: requests
diff --git a/config/puma.example.development.rb b/config/puma.example.development.rb
index 490c940077a..9df24bf74e3 100644
--- a/config/puma.example.development.rb
+++ b/config/puma.example.development.rb
@@ -42,7 +42,6 @@ bind 'unix:///home/git/gitlab.socket'
workers 2
require_relative "/home/git/gitlab/lib/gitlab/cluster/lifecycle_events"
-require_relative "/home/git/gitlab/lib/gitlab/cluster/puma_worker_killer_initializer"
on_restart do
# Signal application hooks that we're about to restart
diff --git a/config/puma.rb.example b/config/puma.rb.example
new file mode 100644
index 00000000000..6558dbc6cfe
--- /dev/null
+++ b/config/puma.rb.example
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+# Load "path" as a rackup file.
+#
+# The default is "config.ru".
+#
+rackup 'config.ru'
+pidfile '/home/git/gitlab/tmp/pids/puma.pid'
+state_path '/home/git/gitlab/tmp/pids/puma.state'
+
+stdout_redirect '/home/git/gitlab/log/puma.stdout.log',
+ '/home/git/gitlab/log/puma.stderr.log',
+ true
+
+# Configure "min" to be the minimum number of threads to use to answer
+# requests and "max" the maximum.
+#
+# The default is "0, 16".
+#
+threads 1, 16
+
+# By default, workers accept all requests and queue them to pass to handlers.
+# When false, workers accept the number of simultaneous requests configured.
+#
+# Queueing requests generally improves performance, but can cause deadlocks if
+# the app is waiting on a request to itself. See https://github.com/puma/puma/issues/612
+#
+# When set to false this may require a reverse proxy to handle slow clients and
+# queue requests before they reach puma. This is due to disabling HTTP keepalive
+queue_requests false
+
+# Bind the server to "url". "tcp://", "unix://" and "ssl://" are the only
+# accepted protocols.
+bind 'unix:///home/git/gitlab/tmp/sockets/gitlab.socket'
+
+workers 3
+
+require_relative "/home/git/gitlab/lib/gitlab/cluster/lifecycle_events"
+require_relative "/home/git/gitlab/lib/gitlab/cluster/puma_worker_killer_initializer"
+
+on_restart do
+ # Signal application hooks that we're about to restart
+ Gitlab::Cluster::LifecycleEvents.do_master_restart
+end
+
+before_fork do
+ # Signal to the puma killer
+ Gitlab::Cluster::PumaWorkerKillerInitializer.start @config.options unless ENV['DISABLE_PUMA_WORKER_KILLER']
+
+ # Signal application hooks that we're about to fork
+ Gitlab::Cluster::LifecycleEvents.do_before_fork
+end
+
+Gitlab::Cluster::LifecycleEvents.set_puma_options @config.options
+on_worker_boot do
+ # Signal application hooks of worker start
+ Gitlab::Cluster::LifecycleEvents.do_worker_start
+end
+
+# Preload the application before starting the workers; this conflicts with
+# phased restart feature. (off by default)
+preload_app!
+
+tag 'gitlab-puma-worker'
+
+# Verifies that all workers have checked in to the master process within
+# the given timeout. If not the worker process will be restarted. Default
+# value is 60 seconds.
+#
+worker_timeout 60
diff --git a/config/routes.rb b/config/routes.rb
index bbf00208545..cb90a0134c4 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -75,6 +75,8 @@ Rails.application.routes.draw do
resources :issues, module: :boards, only: [:index, :update]
end
+ get 'acme-challenge/' => 'acme_challenges#show'
+
# UserCallouts
resources :user_callouts, only: [:create]
@@ -103,6 +105,7 @@ Rails.application.routes.draw do
scope :applications do
post '/:application', to: 'clusters/applications#create', as: :install_applications
patch '/:application', to: 'clusters/applications#update', as: :update_applications
+ delete '/:application', to: 'clusters/applications#destroy', as: :uninstall_applications
end
get :cluster_status, format: :json
diff --git a/config/routes/admin.rb b/config/routes/admin.rb
index a01003b6039..ae79beb1dba 100644
--- a/config/routes/admin.rb
+++ b/config/routes/admin.rb
@@ -83,7 +83,7 @@ namespace :admin do
resources(:projects,
path: '/',
constraints: { id: Gitlab::PathRegex.project_route_regex },
- only: [:show]) do
+ only: [:show, :destroy]) do
member do
put :transfer
@@ -111,6 +111,7 @@ namespace :admin do
put :reset_health_check_token
put :clear_repository_check_states
get :integrations, :repository, :templates, :ci_cd, :reporting, :metrics_and_profiling, :network, :geo, :preferences
+ get :lets_encrypt_terms_of_service
end
resources :labels
@@ -132,5 +133,7 @@ namespace :admin do
end
end
+ concerns :clusterable
+
root to: 'dashboard#index'
end
diff --git a/config/routes/import.rb b/config/routes/import.rb
index 24013eb2c88..9fe2688de1e 100644
--- a/config/routes/import.rb
+++ b/config/routes/import.rb
@@ -67,4 +67,6 @@ namespace :import do
get :jobs
post :upload
end
+
+ resource :phabricator, only: [:create, :new], controller: :phabricator
end
diff --git a/config/routes/profile.rb b/config/routes/profile.rb
index c1cac3905f1..0e213b0b989 100644
--- a/config/routes/profile.rb
+++ b/config/routes/profile.rb
@@ -17,7 +17,11 @@ resource :profile, only: [:show, :update] do
delete :unlink
end
end
- resource :notifications, only: [:show, :update]
+
+ resource :notifications, only: [:show, :update] do
+ resources :groups, only: :update
+ end
+
resource :password, only: [:new, :create, :edit, :update] do
member do
put :reset
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 93d168fc595..a1e769f6ca3 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -26,24 +26,150 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
module: :projects,
as: :project) do
- resources :autocomplete_sources, only: [] do
- collection do
- get 'members'
- get 'issues'
- get 'merge_requests'
- get 'labels'
- get 'milestones'
- get 'commands'
- get 'snippets'
+ # Begin of the /-/ scope.
+ # Use this scope for all new project routes.
+ scope '-' do
+ get 'archive/*id', constraints: { format: Gitlab::PathRegex.archive_formats_regex, id: /.+?/ }, to: 'repositories#archive', as: 'archive'
+
+ resources :jobs, only: [:index, :show], constraints: { id: /\d+/ } do
+ collection do
+ resources :artifacts, only: [] do
+ collection do
+ get :latest_succeeded,
+ path: '*ref_name_and_path',
+ format: false
+ end
+ end
+ end
+
+ member do
+ get :status
+ post :cancel
+ post :unschedule
+ post :retry
+ post :play
+ post :erase
+ get :trace, defaults: { format: 'json' }
+ get :raw
+ get :terminal
+ get '/terminal.ws/authorize', to: 'jobs#terminal_websocket_authorize', constraints: { format: nil }
+ end
+
+ resource :artifacts, only: [] do
+ get :download
+ get :browse, path: 'browse(/*path)', format: false
+ get :file, path: 'file/*path', format: false
+ get :raw, path: 'raw/*path', format: false
+ post :keep
+ end
+ end
+
+ namespace :ci do
+ resource :lint, only: [:show, :create]
+ end
+
+ namespace :settings do
+ get :members, to: redirect("%{namespace_id}/%{project_id}/project_members")
+
+ resource :ci_cd, only: [:show, :update], controller: 'ci_cd' do
+ post :reset_cache
+ put :reset_registration_token
+ end
+
+ resource :operations, only: [:show, :update]
+ resource :integrations, only: [:show]
+
+ resource :repository, only: [:show], controller: :repository do
+ post :create_deploy_token, path: 'deploy_token/create'
+ post :cleanup
+ end
end
+
+ resources :autocomplete_sources, only: [] do
+ collection do
+ get 'members'
+ get 'issues'
+ get 'merge_requests'
+ get 'labels'
+ get 'milestones'
+ get 'commands'
+ get 'snippets'
+ end
+ end
+
+ resources :project_members, except: [:show, :new, :edit], constraints: { id: %r{[a-zA-Z./0-9_\-#%+]+} }, concerns: :access_requestable do
+ collection do
+ delete :leave
+
+ # Used for import team
+ # from another project
+ get :import
+ post :apply_import
+ end
+
+ member do
+ post :resend_invite
+ end
+ end
+
+ resources :deploy_keys, constraints: { id: /\d+/ }, only: [:index, :new, :create, :edit, :update] do
+ member do
+ put :enable
+ put :disable
+ end
+ end
+
+ resources :deploy_tokens, constraints: { id: /\d+/ }, only: [] do
+ member do
+ put :revoke
+ end
+ end
+
+ resources :milestones, constraints: { id: /\d+/ } do
+ member do
+ post :promote
+ put :sort_issues
+ put :sort_merge_requests
+ get :merge_requests
+ get :participants
+ get :labels
+ end
+ end
+
+ resources :labels, except: [:show], constraints: { id: /\d+/ } do
+ collection do
+ post :generate
+ post :set_priorities
+ end
+
+ member do
+ post :promote
+ post :toggle_subscription
+ delete :remove_priority
+ end
+ end
+
+ resources :services, constraints: { id: %r{[^/]+} }, only: [:edit, :update] do
+ member do
+ put :test
+ end
+ end
+
+ resources :boards, only: [:index, :show], constraints: { id: /\d+/ }
+ resources :releases, only: [:index]
+ resources :forks, only: [:index, :new, :create]
+ resources :group_links, only: [:index, :create, :update, :destroy], constraints: { id: /\d+/ }
+
+ resource :import, only: [:new, :create, :show]
+ resource :avatar, only: [:show, :destroy]
end
+ # End of the /-/ scope.
#
# Templates
#
get '/templates/:template_type/:key' => 'templates#show', as: :template, constraints: { key: %r{[^/]+} }
- resource :avatar, only: [:show, :destroy]
resources :commit, only: [:show], constraints: { id: /\h{7,40}/ } do
member do
get :branches
@@ -70,12 +196,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
- resources :services, constraints: { id: %r{[^/]+} }, only: [:edit, :update] do
- member do
- put :test
- end
- end
-
resource :mattermost, only: [:new, :create]
namespace :prometheus do
@@ -84,28 +204,11 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
- resources :deploy_keys, constraints: { id: /\d+/ }, only: [:index, :new, :create, :edit, :update] do
- member do
- put :enable
- put :disable
- end
- end
-
- resources :deploy_tokens, constraints: { id: /\d+/ }, only: [] do
- member do
- put :revoke
- end
- end
-
- resources :releases, only: [:index]
- resources :forks, only: [:index, :new, :create]
- resource :import, only: [:new, :create, :show]
-
resources :merge_requests, concerns: :awardable, except: [:new, :create], constraints: { id: /\d+/ } do
member do
get :commit_change_content
post :merge
- post :cancel_merge_when_pipeline_succeeds
+ post :cancel_auto_merge
get :pipeline_status
get :ci_environments_status
post :toggle_subscription
@@ -201,6 +304,12 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
get :failures
get :status
end
+
+ member do
+ resources :stages, only: [], param: :name do
+ post :play_manual
+ end
+ end
end
resources :pipeline_schedules, except: [:show] do
@@ -218,9 +327,10 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
get :terminal
get :metrics
get :additional_metrics
+ get :metrics_dashboard
get '/terminal.ws/authorize', to: 'environments#terminal_websocket_authorize', constraints: { format: nil }
- get '/prometheus/api/v1/*proxy_path', to: 'environments/prometheus_api#proxy'
+ get '/prometheus/api/v1/*proxy_path', to: 'environments/prometheus_api#proxy', as: :prometheus_api
end
collection do
@@ -260,47 +370,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resources :functions, only: [:index]
end
- scope '-' do
- get 'archive/*id', constraints: { format: Gitlab::PathRegex.archive_formats_regex, id: /.+?/ }, to: 'repositories#archive', as: 'archive'
-
- resources :jobs, only: [:index, :show], constraints: { id: /\d+/ } do
- collection do
- resources :artifacts, only: [] do
- collection do
- get :latest_succeeded,
- path: '*ref_name_and_path',
- format: false
- end
- end
- end
-
- member do
- get :status
- post :cancel
- post :unschedule
- post :retry
- post :play
- post :erase
- get :trace, defaults: { format: 'json' }
- get :raw
- get :terminal
- get '/terminal.ws/authorize', to: 'jobs#terminal_websocket_authorize', constraints: { format: nil }
- end
-
- resource :artifacts, only: [] do
- get :download
- get :browse, path: 'browse(/*path)', format: false
- get :file, path: 'file/*path', format: false
- get :raw, path: 'raw/*path', format: false
- post :keep
- end
- end
-
- namespace :ci do
- resource :lint, only: [:show, :create]
- end
- end
-
draw :legacy_builds
resources :hooks, only: [:index, :create, :edit, :update, :destroy], constraints: { id: /\d+/ } do
@@ -330,66 +399,26 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
- resources :milestones, constraints: { id: /\d+/ } do
- member do
- post :promote
- put :sort_issues
- put :sort_merge_requests
- get :merge_requests
- get :participants
- get :labels
- end
- end
-
- resources :labels, except: [:show], constraints: { id: /\d+/ } do
- collection do
- post :generate
- post :set_priorities
- end
-
- member do
- post :promote
- post :toggle_subscription
- delete :remove_priority
- end
- end
-
get :issues, to: 'issues#calendar', constraints: lambda { |req| req.format == :ics }
+
resources :issues, concerns: :awardable, constraints: { id: /\d+/ } do
member do
post :toggle_subscription
post :mark_as_spam
post :move
- get :referenced_merge_requests
get :related_branches
get :can_create_branch
get :realtime_changes
post :create_merge_request
get :discussions, format: :json
end
+
collection do
post :bulk_update
post :import_csv
end
end
- resources :project_members, except: [:show, :new, :edit], constraints: { id: %r{[a-zA-Z./0-9_\-#%+]+} }, concerns: :access_requestable do
- collection do
- delete :leave
-
- # Used for import team
- # from another project
- get :import
- post :apply_import
- end
-
- member do
- post :resend_invite
- end
- end
-
- resources :group_links, only: [:index, :create, :update, :destroy], constraints: { id: /\d+/ }
-
resources :notes, only: [:create, :destroy, :update], concerns: :awardable, constraints: { id: /\d+/ } do
member do
delete :delete_attachment
@@ -400,8 +429,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
get 'noteable/:target_type/:target_id/notes' => 'notes#index', as: 'noteable_notes'
- resources :boards, only: [:index, :show], constraints: { id: /\d+/ }
-
resources :todos, only: [:create]
resources :uploads, only: [:create] do
@@ -436,18 +463,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
end
- namespace :settings do
- get :members, to: redirect("%{namespace_id}/%{project_id}/project_members")
- resource :ci_cd, only: [:show, :update], controller: 'ci_cd' do
- post :reset_cache
- put :reset_registration_token
- end
- resource :integrations, only: [:show]
- resource :repository, only: [:show], controller: :repository do
- post :create_deploy_token, path: 'deploy_token/create'
- post :cleanup
- end
- end
resources :error_tracking, only: [:index], controller: :error_tracking do
collection do
@@ -459,10 +474,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
# its preferable to keep it below all other project routes
draw :wiki
draw :repository
-
- namespace :settings do
- resource :operations, only: [:show, :update]
- end
end
resources(:projects,
@@ -487,4 +498,22 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
end
+
+ # Legacy routes.
+ # Introduced in 12.0.
+ # Should be removed after 12.1
+ scope(path: '*namespace_id',
+ as: :namespace,
+ namespace_id: Gitlab::PathRegex.full_namespace_route_regex) do
+ scope(path: ':project_id',
+ constraints: { project_id: Gitlab::PathRegex.project_route_regex },
+ module: :projects,
+ as: :project) do
+ Gitlab::Routing.redirect_legacy_paths(self, :settings, :branches, :tags,
+ :network, :graphs, :autocomplete_sources,
+ :project_members, :deploy_keys, :deploy_tokens,
+ :labels, :milestones, :services, :boards, :releases,
+ :forks, :group_links, :import, :avatar)
+ end
+ end
end
diff --git a/config/routes/repository.rb b/config/routes/repository.rb
index f5201b9ddbb..b96315bfe8b 100644
--- a/config/routes/repository.rb
+++ b/config/routes/repository.rb
@@ -39,7 +39,7 @@ scope format: false do
end
end
- scope constraints: { id: Gitlab::PathRegex.git_reference_regex } do
+ scope path: '-', constraints: { id: Gitlab::PathRegex.git_reference_regex } do
resources :network, only: [:show]
resources :graphs, only: [:show] do
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 8bc2426ec4c..fd9ce4d3374 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -30,6 +30,7 @@
- [pipeline_default, 3]
- [pipeline_cache, 3]
- [deployment, 3]
+ - [auto_merge, 3]
- [pipeline_hooks, 2]
- [gitlab_shell, 2]
- [email_receiver, 2]
@@ -91,3 +92,4 @@
- [chat_notification, 2]
- [migrate_external_diffs, 1]
- [update_project_statistics, 1]
+ - [phabricator_import_import_tasks, 1]
diff --git a/config/unicorn.rb.example.development b/config/unicorn.rb.example.development
index f7541bb9d55..ae3dc2e37e1 100644
--- a/config/unicorn.rb.example.development
+++ b/config/unicorn.rb.example.development
@@ -58,4 +58,3 @@ after_fork do |server, worker|
# addr = "127.0.0.1:#{9293 + worker.nr}"
# server.listen(addr, :tries => -1, :delay => 5, :tcp_nopush => true)
end
-
diff --git a/config/webpack.config.review_toolbar.js b/config/webpack.config.review_toolbar.js
new file mode 100644
index 00000000000..baaba7ed387
--- /dev/null
+++ b/config/webpack.config.review_toolbar.js
@@ -0,0 +1,58 @@
+const path = require('path');
+const CompressionPlugin = require('compression-webpack-plugin');
+
+const ROOT_PATH = path.resolve(__dirname, '..');
+const CACHE_PATH = process.env.WEBPACK_CACHE_PATH || path.join(ROOT_PATH, 'tmp/cache');
+const NO_SOURCEMAPS = process.env.NO_SOURCEMAPS;
+const IS_PRODUCTION = process.env.NODE_ENV === 'production';
+
+const devtool = IS_PRODUCTION ? 'source-map' : 'cheap-module-eval-source-map';
+
+const alias = {
+ vendor: path.join(ROOT_PATH, 'vendor/assets/javascripts'),
+ spec: path.join(ROOT_PATH, 'spec/javascripts'),
+};
+
+module.exports = {
+ mode: IS_PRODUCTION ? 'production' : 'development',
+
+ context: path.join(ROOT_PATH, 'app/assets/javascripts'),
+
+ name: 'visual_review_toolbar',
+
+ entry: './visual_review_toolbar',
+
+ output: {
+ path: path.join(ROOT_PATH, 'public/assets/webpack'),
+ filename: 'visual_review_toolbar.js',
+ library: 'VisualReviewToolbar',
+ libraryTarget: 'var',
+ },
+
+ resolve: {
+ alias,
+ },
+
+ module: {
+ rules: [
+ {
+ test: /\.js$/,
+ loader: 'babel-loader',
+ options: {
+ cacheDirectory: path.join(CACHE_PATH, 'babel-loader'),
+ },
+ },
+ {
+ test: /\.css$/,
+ use: ['style-loader', 'css-loader'],
+ },
+ ],
+ },
+
+ plugins: [
+ // compression can require a lot of compute time and is disabled in CI
+ new CompressionPlugin(),
+ ].filter(Boolean),
+
+ devtool: NO_SOURCEMAPS ? false : devtool,
+};
diff --git a/danger/ce_ee_vue_templates/Dangerfile b/danger/ce_ee_vue_templates/Dangerfile
new file mode 100644
index 00000000000..f7715eb2a89
--- /dev/null
+++ b/danger/ce_ee_vue_templates/Dangerfile
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+require 'cgi'
+
+def get_vue_files_with_ce_and_ee_versions(files)
+ files.select do |file|
+ if file.end_with?('.vue')
+ counterpart_path = if file.start_with?('ee/')
+ file.delete_prefix('ee/')
+ else
+ "ee/#{file}"
+ end
+
+ escaped_path = CGI.escape(counterpart_path)
+ api_endpoint = "https://gitlab.com/api/v4/projects/gitlab-org%2Fgitlab-ee/repository/files/#{escaped_path}?ref=master"
+ response = HTTParty.get(api_endpoint) # rubocop:disable Gitlab/HTTParty
+ response.code != 404
+ else
+ false
+ end
+ end
+end
+
+vue_candidates = get_vue_files_with_ce_and_ee_versions(helper.all_changed_files)
+
+return if vue_candidates.empty?
+
+message 'This merge request includes changes to Vue files that have both CE and EE versions.'
+
+markdown(<<~MARKDOWN)
+ ## Vue `<template>` in CE and EE
+
+ Some Vue files in CE have a counterpart in EE.
+ (For example, `path/to/file.vue` and `ee/path/to/file.vue`.)
+
+ When run in the context of CE, the `<template>` of the CE Vue file is used.
+ When run in the context of EE, the `<template>` of the EE Vue file is used.
+
+ It's easy to accidentally make a change to a CE `<template>` that _should_
+ appear in both CE and EE without making the change in both places.
+ When this happens, the change only takes effect in CE.
+
+ The following Vue files were changed as part of this merge request that
+ include both a CE and EE version of the file:
+
+ * #{vue_candidates.map { |path| "`#{path}`" }.join("\n* ")}
+
+ If you made a change to the `<template>` of any of these Vue files that
+ should be visible in both CE and EE, please ensure you have made your
+ change to both versions of the file.
+
+ ### A better alternative
+
+ An even _better_ alternative is to refactor this component to only use
+ a single template for both CE and EE. More info on this approach here:
+ https://docs.gitlab.com/ee/development/ee_features.html#template-tag
+MARKDOWN
diff --git a/danger/commit_messages/Dangerfile b/danger/commit_messages/Dangerfile
index 9be1ce2ff86..bdb4343b1d6 100644
--- a/danger/commit_messages/Dangerfile
+++ b/danger/commit_messages/Dangerfile
@@ -21,7 +21,7 @@ class EmojiChecker
# alone is not enough, as we'd match `:foo:bar:baz`. Instead, we use this
# regex to save us from having to check for all possible emoji names when we
# know one definitely is not included.
- LIKELY_EMOJI = /:[\+a-z0-9_\-]+:/
+ LIKELY_EMOJI = /:[\+a-z0-9_\-]+:/.freeze
def initialize
names = JSON.parse(File.read(DIGESTS)).keys +
@@ -163,10 +163,10 @@ def lint_commit(commit)
end
if emoji_checker.includes_emoji?(commit.message)
- fail_commit(
+ warn_commit(
commit,
'Avoid the use of Markdown Emoji such as `:+1:`. ' \
- 'These add no value to the commit message, ' \
+ 'These add limited value to the commit message, ' \
'and are displayed as plain text outside of GitLab'
)
diff --git a/danger/gitlab_ui_wg/Dangerfile b/danger/gitlab_ui_wg/Dangerfile
index 02d94fa5ab7..672b1deecb3 100644
--- a/danger/gitlab_ui_wg/Dangerfile
+++ b/danger/gitlab_ui_wg/Dangerfile
@@ -1,29 +1,36 @@
+FRONTEND_MAINTAINERS = %w[filipa iamphill psimyn sarahghp mishunov].freeze
+UX_MAINTAINERS = %w[tauriedavis rverissimo].freeze
+NO_REVIEWER = 'No reviewer available'.freeze
+
def mention_single_codebase_approvers
- frontend_maintainers = %w(@filipa @iamphill @psimyn @sarahghp @mishunov)
- ux_maintainers = %w(@tauriedavis @rverissimo)
+ canonical_branch_name =
+ roulette.canonical_branch_name(gitlab.mr_json['source_branch'])
+
+ random = roulette.new_random(canonical_branch_name)
+
+ frontend_maintainers = helper.new_teammates(FRONTEND_MAINTAINERS)
+ ux_maintainers = helper.new_teammates(UX_MAINTAINERS)
rows = []
- users = []
if gitlab.mr_labels.include?('frontend')
- frontend_maintainer = frontend_maintainers.sample
+ frontend_maintainer =
+ roulette.spin_for_person(frontend_maintainers, random: random)
- rows << "| ~frontend | `#{frontend_maintainer}`"
- users << frontend_maintainer
+ rows << "| ~frontend | #{frontend_maintainer&.markdown_name || NO_REVIEWER}"
end
if gitlab.mr_labels.include?('UX')
- ux_maintainers = ux_maintainers.sample
+ ux_maintainers =
+ roulette.spin_for_person(ux_maintainers, random: random)
- rows << "| ~UX | `#{ux_maintainers}`"
- users << ux_maintainers
+ rows << "| ~UX | #{ux_maintainers&.markdown_name || NO_REVIEWER}"
end
if rows.empty?
backup_maintainer = frontend_maintainers.sample
- rows << "| ~frontend / ~UX | `#{backup_maintainer}`"
- users << backup_maintainer
+ rows << "| ~frontend / ~UX | #{backup_maintainer.markdown_name}"
end
markdown(<<~MARKDOWN.strip)
diff --git a/danger/plugins/helper.rb b/danger/plugins/helper.rb
index 581c0720083..2d7a933e801 100644
--- a/danger/plugins/helper.rb
+++ b/danger/plugins/helper.rb
@@ -1,8 +1,5 @@
# frozen_string_literal: true
-require 'net/http'
-require 'yaml'
-
require_relative '../../lib/gitlab/danger/helper'
module Danger
diff --git a/danger/plugins/roulette.rb b/danger/plugins/roulette.rb
new file mode 100644
index 00000000000..7c62cff0c92
--- /dev/null
+++ b/danger/plugins/roulette.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+require_relative '../../lib/gitlab/danger/roulette'
+
+module Danger
+ class Roulette < Plugin
+ # Put the helper code somewhere it can be tested
+ include Gitlab::Danger::Roulette
+ end
+end
diff --git a/danger/roulette/Dangerfile b/danger/roulette/Dangerfile
index e6820f49ee2..6718e218233 100644
--- a/danger/roulette/Dangerfile
+++ b/danger/roulette/Dangerfile
@@ -31,24 +31,28 @@ Please consider creating a merge request to
for them.
MARKDOWN
-def spin(team, project, category, branch_name)
- rng = Random.new(Digest::MD5.hexdigest(branch_name).to_i(16))
-
- reviewers = team.select { |member| member.reviewer?(project, category) }
- traintainers = team.select { |member| member.traintainer?(project, category) }
- maintainers = team.select { |member| member.maintainer?(project, category) }
+NO_REVIEWER = 'No reviewer available'.freeze
+NO_MAINTAINER = 'No maintainer available'.freeze
+
+def spin_for_category(team, project, category, branch_name)
+ random = roulette.new_random(branch_name)
+ labels = gitlab.mr_labels
+
+ reviewers, traintainers, maintainers =
+ %i[reviewer? traintainer? maintainer?].map do |kind|
+ team.select do |member|
+ member.public_send(kind, project, category, labels) # rubocop:disable GitlabSecurity/PublicSend
+ end
+ end
- # TODO: filter out people who are currently not in the office
- # https://gitlab.com/gitlab-org/gitlab-ce/issues/57652
- #
# TODO: take CODEOWNERS into account?
# https://gitlab.com/gitlab-org/gitlab-ce/issues/57653
# Make traintainers have triple the chance to be picked as a reviewer
- reviewer = (reviewers + traintainers + traintainers).sample(random: rng)
- maintainer = maintainers.sample(random: rng)
+ reviewer = roulette.spin_for_person(reviewers + traintainers + traintainers, random: random)
+ maintainer = roulette.spin_for_person(maintainers, random: random)
- "| #{helper.label_for_category(category)} | #{reviewer&.markdown_name} | #{maintainer&.markdown_name} |"
+ "| #{helper.label_for_category(category)} | #{reviewer&.markdown_name || NO_REVIEWER} | #{maintainer&.markdown_name || NO_MAINTAINER} |"
end
def build_list(items)
@@ -63,7 +67,7 @@ end
changes = helper.changes_by_category
-# Ignore any files that are known but uncategoried. Prompt for any unknown files
+# Ignore any files that are known but uncategorized. Prompt for any unknown files
changes.delete(:none)
categories = changes.keys - [:unknown]
@@ -73,26 +77,21 @@ categories = changes.keys - [:unknown]
# disable the review roulette for such MRs.
if changes.any? && !gitlab.mr_labels.include?('single codebase') && !gitlab.mr_labels.include?('CSS cleanup')
# Strip leading and trailing CE/EE markers
- canonical_branch_name = gitlab
- .mr_json['source_branch']
- .gsub(/^[ce]e-/, '')
- .gsub(/-[ce]e$/, '')
+ canonical_branch_name =
+ roulette.canonical_branch_name(gitlab.mr_json['source_branch'])
team =
begin
- helper.project_team
+ roulette.project_team(helper.project_name)
rescue => err
warn("Reviewer roulette failed to load team data: #{err.message}")
[]
end
- # Exclude the MR author from the team for selection purposes
- team.delete_if { |teammate| teammate.username == gitlab.mr_author }
-
project = helper.project_name
unknown = changes.fetch(:unknown, [])
- rows = categories.map { |category| spin(team, project, category, canonical_branch_name) }
+ rows = categories.map { |category| spin_for_category(team, project, category, canonical_branch_name) }
markdown(MESSAGE)
markdown(CATEGORY_TABLE_HEADER + rows.join("\n")) unless rows.empty?
diff --git a/danger/single_codebase/Dangerfile b/danger/single_codebase/Dangerfile
index a5938cd6783..f371a42e9b1 100644
--- a/danger/single_codebase/Dangerfile
+++ b/danger/single_codebase/Dangerfile
@@ -1,29 +1,36 @@
+FRONTEND_MAINTAINERS = %w[filipa iamphill].freeze
+BACKEND_MAINTAINERS = %w[rspeicher rymai yorickpeterse godfat].freeze
+NO_REVIEWER = 'No reviewer available'.freeze
+
def mention_single_codebase_approvers
- frontend_maintainers = %w(@filipa @iamphill)
- backend_maintainers = %w(@rspeicher @rymai @yorickpeterse @godfat)
+ canonical_branch_name =
+ roulette.canonical_branch_name(gitlab.mr_json['source_branch'])
+
+ random = roulette.new_random(canonical_branch_name)
+
+ frontend_maintainers = helper.new_teammates(FRONTEND_MAINTAINERS)
+ backend_maintainers = helper.new_teammates(BACKEND_MAINTAINERS)
rows = []
- users = []
if gitlab.mr_labels.include?('frontend')
- frontend_maintainer = frontend_maintainers.sample
+ frontend_maintainer =
+ roulette.spin_for_person(frontend_maintainers, random: random)
- rows << "| ~frontend | `#{frontend_maintainer}`"
- users << frontend_maintainer
+ rows << "| ~frontend | #{frontend_maintainer&.markdown_name || NO_REVIEWER}"
end
if gitlab.mr_labels.include?('backend')
- backend_maintainer = backend_maintainers.sample
+ backend_maintainer =
+ roulette.spin_for_person(backend_maintainers, random: random)
- rows << "| ~backend | `#{backend_maintainer}`"
- users << backend_maintainer
+ rows << "| ~backend | #{backend_maintainer&.markdown_name || NO_REVIEWER}"
end
if rows.empty?
backup_maintainer = backend_maintainers.sample
- rows << "| ~frontend / ~backend | `#{backup_maintainer}`"
- users << backup_maintainer
+ rows << "| ~frontend / ~backend | #{backup_maintainer.markdown_name}"
end
markdown(<<~MARKDOWN.strip)
diff --git a/db/fixtures/development/09_issues.rb b/db/fixtures/development/09_issues.rb
index 926401d8b9e..582a5203d1d 100644
--- a/db/fixtures/development/09_issues.rb
+++ b/db/fixtures/development/09_issues.rb
@@ -1,23 +1,5 @@
require './spec/support/sidekiq'
Gitlab::Seeder.quiet do
- Project.all.each do |project|
- 10.times do
- label_ids = project.labels.pluck(:id).sample(3)
- label_ids += project.group.labels.sample(3) if project.group
-
- issue_params = {
- title: FFaker::Lorem.sentence(6),
- description: FFaker::Lorem.sentence,
- state: ['opened', 'closed'].sample,
- milestone: project.milestones.sample,
- assignees: [project.team.users.sample],
- created_at: rand(12).months.ago,
- label_ids: label_ids
- }
-
- Issues::CreateService.new(project, project.team.users.sample, issue_params).execute
- print '.'
- end
- end
+ Rake::Task["gitlab:seed:issues"].invoke
end
diff --git a/db/importers/common_metrics_importer.rb b/db/importers/common_metrics_importer.rb
index deadd653ae9..195bde8f34a 100644
--- a/db/importers/common_metrics_importer.rb
+++ b/db/importers/common_metrics_importer.rb
@@ -53,7 +53,7 @@ module Importers
private
def process_content(&blk)
- content.map do |group|
+ content['panel_groups'].map do |group|
process_group(group, &blk)
end
end
@@ -63,28 +63,28 @@ module Importers
group: find_group_title_key(group['group'])
}
- group['metrics'].map do |metric|
- process_metric(metric, attributes, &blk)
+ group['panels'].map do |panel|
+ process_panel(panel, attributes, &blk)
end
end
- def process_metric(metric, attributes, &blk)
+ def process_panel(panel, attributes, &blk)
attributes = attributes.merge(
- title: metric['title'],
- y_label: metric['y_label'])
+ title: panel['title'],
+ y_label: panel['y_label'])
- metric['queries'].map do |query|
- process_metric_query(query, attributes, &blk)
+ panel['metrics'].map do |metric_details|
+ process_metric_details(metric_details, attributes, &blk)
end
end
- def process_metric_query(query, attributes, &blk)
+ def process_metric_details(metric_details, attributes, &blk)
attributes = attributes.merge(
- legend: query['label'],
- query: query['query_range'],
- unit: query['unit'])
+ legend: metric_details['label'],
+ query: metric_details['query_range'],
+ unit: metric_details['unit'])
- yield(query['id'], attributes)
+ yield(metric_details['id'], attributes)
end
def find_or_build_metric!(id)
diff --git a/db/migrate/20140414131055_change_state_to_allow_empty_merge_request_diffs.rb b/db/migrate/20140414131055_change_state_to_allow_empty_merge_request_diffs.rb
index 148b46f8830..1f9ae3f0080 100644
--- a/db/migrate/20140414131055_change_state_to_allow_empty_merge_request_diffs.rb
+++ b/db/migrate/20140414131055_change_state_to_allow_empty_merge_request_diffs.rb
@@ -1,4 +1,3 @@
-# rubocop:disable all
class ChangeStateToAllowEmptyMergeRequestDiffs < ActiveRecord::Migration[4.2]
def up
change_column :merge_request_diffs, :state, :string, null: true,
diff --git a/db/migrate/20150509180749_convert_legacy_reference_notes.rb b/db/migrate/20150509180749_convert_legacy_reference_notes.rb
index a44a908c2f5..84d4eb9e51f 100644
--- a/db/migrate/20150509180749_convert_legacy_reference_notes.rb
+++ b/db/migrate/20150509180749_convert_legacy_reference_notes.rb
@@ -7,7 +7,8 @@
# mentioned in 54f7727c850972f0401c1312a7c4a6a380de5666
class ConvertLegacyReferenceNotes < ActiveRecord::Migration[4.2]
def up
- execute %q{UPDATE notes SET note = trim(both '_' from note) WHERE system = true AND note LIKE '\_%\_'}
+ quoted_column_name = ActiveRecord::Base.connection.quote_column_name('system')
+ execute %Q{UPDATE notes SET note = trim(both '_' from note) WHERE #{quoted_column_name} = true AND note LIKE '\_%\_'}
end
def down
diff --git a/db/migrate/20161031181638_add_unique_index_to_subscriptions.rb b/db/migrate/20161031181638_add_unique_index_to_subscriptions.rb
index 23a775d6282..9005b42b41f 100644
--- a/db/migrate/20161031181638_add_unique_index_to_subscriptions.rb
+++ b/db/migrate/20161031181638_add_unique_index_to_subscriptions.rb
@@ -9,11 +9,11 @@ class AddUniqueIndexToSubscriptions < ActiveRecord::Migration[4.2]
def up
add_concurrent_index :subscriptions, [:subscribable_id, :subscribable_type, :user_id, :project_id], { unique: true, name: 'index_subscriptions_on_subscribable_and_user_id_and_project_id' }
- remove_index :subscriptions, name: 'subscriptions_user_id_and_ref_fields' if index_name_exists?(:subscriptions, 'subscriptions_user_id_and_ref_fields', false)
+ remove_index :subscriptions, name: 'subscriptions_user_id_and_ref_fields' if index_name_exists?(:subscriptions, 'subscriptions_user_id_and_ref_fields')
end
def down
add_concurrent_index :subscriptions, [:subscribable_id, :subscribable_type, :user_id], { unique: true, name: 'subscriptions_user_id_and_ref_fields' }
- remove_index :subscriptions, name: 'index_subscriptions_on_subscribable_and_user_id_and_project_id' if index_name_exists?(:subscriptions, 'index_subscriptions_on_subscribable_and_user_id_and_project_id', false)
+ remove_index :subscriptions, name: 'index_subscriptions_on_subscribable_and_user_id_and_project_id' if index_name_exists?(:subscriptions, 'index_subscriptions_on_subscribable_and_user_id_and_project_id')
end
end
diff --git a/db/migrate/20170330141723_disable_invalid_service_templates2.rb b/db/migrate/20170330141723_disable_invalid_service_templates2.rb
index 91ec19dfa87..f09f3b3e355 100644
--- a/db/migrate/20170330141723_disable_invalid_service_templates2.rb
+++ b/db/migrate/20170330141723_disable_invalid_service_templates2.rb
@@ -1,5 +1,5 @@
# This is the same as DisableInvalidServiceTemplates. Later migrations may have
-# inadventently enabled some invalid templates again.
+# inadvertently enabled some invalid templates again.
#
class DisableInvalidServiceTemplates2 < ActiveRecord::Migration[4.2]
DOWNTIME = false
diff --git a/db/migrate/20170503140202_turn_nested_groups_into_regular_groups_for_mysql.rb b/db/migrate/20170503140202_turn_nested_groups_into_regular_groups_for_mysql.rb
index cfa63b65df4..65b2c6a57be 100644
--- a/db/migrate/20170503140202_turn_nested_groups_into_regular_groups_for_mysql.rb
+++ b/db/migrate/20170503140202_turn_nested_groups_into_regular_groups_for_mysql.rb
@@ -46,13 +46,6 @@ class TurnNestedGroupsIntoRegularGroupsForMysql < ActiveRecord::Migration[4.2]
bulk_insert_members(rows)
- # This method relies on the parent to determine the proper path.
- # Because we reset "parent_id" this method will not return the right path
- # when moving namespaces.
- full_path_was = namespace.send(:full_path_was)
-
- namespace.define_singleton_method(:full_path_was) { full_path_was }
-
namespace.update!(parent_id: nil, path: new_path_for(namespace))
end
end
diff --git a/db/migrate/20180702134423_generate_missing_routes.rb b/db/migrate/20180702134423_generate_missing_routes.rb
index a440bc3179c..dd1106c9e6a 100644
--- a/db/migrate/20180702134423_generate_missing_routes.rb
+++ b/db/migrate/20180702134423_generate_missing_routes.rb
@@ -98,6 +98,7 @@ class GenerateMissingRoutes < ActiveRecord::Migration[4.2]
class Namespace < ActiveRecord::Base
self.table_name = 'namespaces'
+ self.inheritance_column = :_type_disabled
include EachBatch
include GenerateMissingRoutes::Routable
diff --git a/db/migrate/20190320174702_add_lets_encrypt_notification_email_to_application_settings.rb b/db/migrate/20190320174702_add_lets_encrypt_notification_email_to_application_settings.rb
new file mode 100644
index 00000000000..e9cf2af84a5
--- /dev/null
+++ b/db/migrate/20190320174702_add_lets_encrypt_notification_email_to_application_settings.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddLetsEncryptNotificationEmailToApplicationSettings < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ def change
+ add_column :application_settings, :lets_encrypt_notification_email, :string
+ end
+end
diff --git a/db/migrate/20190322164830_add_auto_ssl_enabled_to_pages_domain.rb b/db/migrate/20190322164830_add_auto_ssl_enabled_to_pages_domain.rb
new file mode 100644
index 00000000000..e74a9535ddf
--- /dev/null
+++ b/db/migrate/20190322164830_add_auto_ssl_enabled_to_pages_domain.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddAutoSslEnabledToPagesDomain < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default :pages_domains, :auto_ssl_enabled, :boolean, default: false
+ end
+
+ def down
+ remove_column :pages_domains, :auto_ssl_enabled
+ end
+end
diff --git a/db/migrate/20190325105715_add_fields_to_user_preferences.rb b/db/migrate/20190325105715_add_fields_to_user_preferences.rb
new file mode 100644
index 00000000000..9ea3b4f9cd8
--- /dev/null
+++ b/db/migrate/20190325105715_add_fields_to_user_preferences.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddFieldsToUserPreferences < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ DOWNTIME = false
+
+ def up
+ add_column(:user_preferences, :timezone, :string)
+ add_column(:user_preferences, :time_display_relative, :boolean)
+ add_column(:user_preferences, :time_format_in_24h, :boolean)
+ end
+
+ def down
+ remove_column(:user_preferences, :timezone)
+ remove_column(:user_preferences, :time_display_relative)
+ remove_column(:user_preferences, :time_format_in_24h)
+ end
+end
diff --git a/db/migrate/20190327163904_add_notification_email_to_notification_settings.rb b/db/migrate/20190327163904_add_notification_email_to_notification_settings.rb
new file mode 100644
index 00000000000..2f3069032a1
--- /dev/null
+++ b/db/migrate/20190327163904_add_notification_email_to_notification_settings.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddNotificationEmailToNotificationSettings < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :notification_settings, :notification_email, :string
+ end
+end
diff --git a/db/migrate/20190329085614_add_lets_encrypt_terms_of_service_accepted_to_application_settings.rb b/db/migrate/20190329085614_add_lets_encrypt_terms_of_service_accepted_to_application_settings.rb
new file mode 100644
index 00000000000..16de63f207f
--- /dev/null
+++ b/db/migrate/20190329085614_add_lets_encrypt_terms_of_service_accepted_to_application_settings.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddLetsEncryptTermsOfServiceAcceptedToApplicationSettings < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default(:application_settings, :lets_encrypt_terms_of_service_accepted, :boolean, default: false)
+ end
+
+ def down
+ remove_column :application_settings, :lets_encrypt_terms_of_service_accepted
+ end
+end
diff --git a/db/migrate/20190408163745_prometheus_knative05_fix.rb b/db/migrate/20190408163745_prometheus_knative05_fix.rb
new file mode 100644
index 00000000000..c11f6f0e29b
--- /dev/null
+++ b/db/migrate/20190408163745_prometheus_knative05_fix.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class PrometheusKnative05Fix < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ require Rails.root.join('db/importers/common_metrics_importer.rb')
+
+ DOWNTIME = false
+
+ def up
+ Importers::CommonMetricsImporter.new.execute
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/migrate/20190412155659_add_merge_request_blocks.rb b/db/migrate/20190412155659_add_merge_request_blocks.rb
new file mode 100644
index 00000000000..9e7f370d1cf
--- /dev/null
+++ b/db/migrate/20190412155659_add_merge_request_blocks.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class AddMergeRequestBlocks < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :merge_request_blocks, id: :bigserial do |t|
+ t.references :blocking_merge_request,
+ index: false, null: false,
+ foreign_key: { to_table: :merge_requests, on_delete: :cascade }
+
+ t.references :blocked_merge_request,
+ index: true, null: false,
+ foreign_key: { to_table: :merge_requests, on_delete: :cascade }
+
+ t.index [:blocking_merge_request_id, :blocked_merge_request_id],
+ unique: true,
+ name: 'index_mr_blocks_on_blocking_and_blocked_mr_ids'
+
+ t.timestamps_with_timezone
+ end
+ end
+end
diff --git a/db/migrate/20190415030217_add_variable_type_to_ci_variables.rb b/db/migrate/20190415030217_add_variable_type_to_ci_variables.rb
new file mode 100644
index 00000000000..433f510299a
--- /dev/null
+++ b/db/migrate/20190415030217_add_variable_type_to_ci_variables.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddVariableTypeToCiVariables < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+ disable_ddl_transaction!
+
+ DOWNTIME = false
+ ENV_VAR_VARIABLE_TYPE = 1
+
+ def up
+ add_column_with_default(:ci_variables, :variable_type, :smallint, default: ENV_VAR_VARIABLE_TYPE)
+ end
+
+ def down
+ remove_column(:ci_variables, :variable_type)
+ end
+end
diff --git a/db/migrate/20190415095825_add_packages_size_to_project_statistics.rb b/db/migrate/20190415095825_add_packages_size_to_project_statistics.rb
new file mode 100644
index 00000000000..99625981563
--- /dev/null
+++ b/db/migrate/20190415095825_add_packages_size_to_project_statistics.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddPackagesSizeToProjectStatistics < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :project_statistics, :packages_size, :bigint
+ end
+end
diff --git a/db/migrate/20190416185130_add_merge_train_enabled_to_ci_cd_settings.rb b/db/migrate/20190416185130_add_merge_train_enabled_to_ci_cd_settings.rb
new file mode 100644
index 00000000000..eb0e7c41f98
--- /dev/null
+++ b/db/migrate/20190416185130_add_merge_train_enabled_to_ci_cd_settings.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddMergeTrainEnabledToCiCdSettings < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default :project_ci_cd_settings, :merge_trains_enabled, :boolean, default: false, allow_null: false
+ end
+
+ def down
+ remove_column :project_ci_cd_settings, :merge_trains_enabled
+ end
+end
diff --git a/db/migrate/20190416213556_add_variable_type_to_ci_group_variables.rb b/db/migrate/20190416213556_add_variable_type_to_ci_group_variables.rb
new file mode 100644
index 00000000000..dce73caeb5e
--- /dev/null
+++ b/db/migrate/20190416213556_add_variable_type_to_ci_group_variables.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddVariableTypeToCiGroupVariables < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+ disable_ddl_transaction!
+
+ DOWNTIME = false
+ ENV_VAR_VARIABLE_TYPE = 1
+
+ def up
+ add_column_with_default(:ci_group_variables, :variable_type, :smallint, default: ENV_VAR_VARIABLE_TYPE)
+ end
+
+ def down
+ remove_column(:ci_group_variables, :variable_type)
+ end
+end
diff --git a/db/migrate/20190416213615_add_variable_type_to_ci_pipeline_variables.rb b/db/migrate/20190416213615_add_variable_type_to_ci_pipeline_variables.rb
new file mode 100644
index 00000000000..1010d9bd29e
--- /dev/null
+++ b/db/migrate/20190416213615_add_variable_type_to_ci_pipeline_variables.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddVariableTypeToCiPipelineVariables < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+ disable_ddl_transaction!
+
+ DOWNTIME = false
+ ENV_VAR_VARIABLE_TYPE = 1
+
+ def up
+ add_column_with_default(:ci_pipeline_variables, :variable_type, :smallint, default: ENV_VAR_VARIABLE_TYPE)
+ end
+
+ def down
+ remove_column(:ci_pipeline_variables, :variable_type)
+ end
+end
diff --git a/db/migrate/20190416213631_add_variable_type_to_ci_pipeline_schedule_variables.rb b/db/migrate/20190416213631_add_variable_type_to_ci_pipeline_schedule_variables.rb
new file mode 100644
index 00000000000..3079b2afd9c
--- /dev/null
+++ b/db/migrate/20190416213631_add_variable_type_to_ci_pipeline_schedule_variables.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddVariableTypeToCiPipelineScheduleVariables < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+ disable_ddl_transaction!
+
+ DOWNTIME = false
+ ENV_VAR_VARIABLE_TYPE = 1
+
+ def up
+ add_column_with_default(:ci_pipeline_schedule_variables, :variable_type, :smallint, default: ENV_VAR_VARIABLE_TYPE)
+ end
+
+ def down
+ remove_column(:ci_pipeline_schedule_variables, :variable_type)
+ end
+end
diff --git a/db/migrate/20190418182545_create_merge_request_trains_table.rb b/db/migrate/20190418182545_create_merge_request_trains_table.rb
new file mode 100644
index 00000000000..ac927c9c6b9
--- /dev/null
+++ b/db/migrate/20190418182545_create_merge_request_trains_table.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class CreateMergeRequestTrainsTable < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :merge_trains, id: :bigserial do |t|
+ t.references :merge_request, foreign_key: { on_delete: :cascade }, type: :integer, index: false, null: false
+ t.references :user, foreign_key: { on_delete: :cascade }, type: :integer, null: false
+ t.references :pipeline, foreign_key: { to_table: :ci_pipelines, on_delete: :nullify }, type: :integer
+ t.timestamps_with_timezone null: false
+
+ t.index [:merge_request_id], unique: true
+ end
+ end
+end
diff --git a/db/migrate/20190422082247_create_project_metrics_settings.rb b/db/migrate/20190422082247_create_project_metrics_settings.rb
new file mode 100644
index 00000000000..3e21dd0a934
--- /dev/null
+++ b/db/migrate/20190422082247_create_project_metrics_settings.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class CreateProjectMetricsSettings < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :project_metrics_settings, id: :int, primary_key: :project_id, default: nil do |t|
+ t.string :external_dashboard_url, null: false
+ t.foreign_key :projects, column: :project_id, on_delete: :cascade
+ end
+ end
+end
diff --git a/db/migrate/20190426180107_add_deployment_events_to_services.rb b/db/migrate/20190426180107_add_deployment_events_to_services.rb
new file mode 100644
index 00000000000..1fb137fb5f9
--- /dev/null
+++ b/db/migrate/20190426180107_add_deployment_events_to_services.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddDeploymentEventsToServices < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default(:services, :deployment_events, :boolean, default: false, allow_null: false)
+ end
+
+ def down
+ remove_column(:services, :deployment_events)
+ end
+end
diff --git a/db/migrate/20190429082448_create_pages_domain_acme_orders.rb b/db/migrate/20190429082448_create_pages_domain_acme_orders.rb
new file mode 100644
index 00000000000..af811e83518
--- /dev/null
+++ b/db/migrate/20190429082448_create_pages_domain_acme_orders.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class CreatePagesDomainAcmeOrders < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ def change
+ create_table :pages_domain_acme_orders do |t|
+ t.references :pages_domain, null: false, index: true, foreign_key: { on_delete: :cascade }, type: :integer
+
+ t.datetime_with_timezone :expires_at, null: false
+ t.timestamps_with_timezone null: false
+
+ t.string :url, null: false
+
+ t.string :challenge_token, null: false, index: true
+ t.text :challenge_file_content, null: false
+
+ t.text :encrypted_private_key, null: false
+ t.text :encrypted_private_key_iv, null: false
+ end
+ end
+end
diff --git a/db/migrate/20190506135337_add_temporary_indexes_to_state_id.rb b/db/migrate/20190506135337_add_temporary_indexes_to_state_id.rb
new file mode 100644
index 00000000000..8e9838e1afb
--- /dev/null
+++ b/db/migrate/20190506135337_add_temporary_indexes_to_state_id.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+# This migration adds temporary indexes to state_id column of issues
+# and merge_requests tables. It will be used only to peform the scheduling
+# for populating state_id in a post migrate and will be removed after it.
+# Check: ScheduleSyncIssuablesStateIdWhereNil.
+
+class AddTemporaryIndexesToStateId < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ %w(issues merge_requests).each do |table|
+ add_concurrent_index(
+ table,
+ 'id',
+ name: index_name_for(table),
+ where: "state_id IS NULL"
+ )
+ end
+ end
+
+ def down
+ remove_concurrent_index_by_name(:issues, index_name_for("issues"))
+ remove_concurrent_index_by_name(:merge_requests, index_name_for("merge_requests"))
+ end
+
+ def index_name_for(table)
+ "idx_on_#{table}_where_state_id_is_null"
+ end
+end
diff --git a/db/migrate/20190515125613_add_application_settings_elasticsearch_shards.rb b/db/migrate/20190515125613_add_application_settings_elasticsearch_shards.rb
new file mode 100644
index 00000000000..9cebc0f8db4
--- /dev/null
+++ b/db/migrate/20190515125613_add_application_settings_elasticsearch_shards.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class AddApplicationSettingsElasticsearchShards < ActiveRecord::Migration[5.1]
+ DOWNTIME = false
+
+ def change
+ add_column :application_settings, :elasticsearch_shards, :integer, null: false, default: 5
+ add_column :application_settings, :elasticsearch_replicas, :integer, null: false, default: 1
+ end
+end
diff --git a/db/migrate/20190516011213_add_build_queued_at_index.rb b/db/migrate/20190516011213_add_build_queued_at_index.rb
new file mode 100644
index 00000000000..77ffa7cd4e9
--- /dev/null
+++ b/db/migrate/20190516011213_add_build_queued_at_index.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+# This migration make queued_at field indexed to speed up builds filtering by job_age
+
+class AddBuildQueuedAtIndex < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_builds, :queued_at
+ end
+
+ def down
+ remove_concurrent_index :ci_builds, :queued_at
+ end
+end
diff --git a/db/migrate/20190516151857_add_lets_encrypt_private_key_to_application_settings.rb b/db/migrate/20190516151857_add_lets_encrypt_private_key_to_application_settings.rb
new file mode 100644
index 00000000000..e1d3cca48d6
--- /dev/null
+++ b/db/migrate/20190516151857_add_lets_encrypt_private_key_to_application_settings.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddLetsEncryptPrivateKeyToApplicationSettings < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ def change
+ add_column :application_settings, :encrypted_lets_encrypt_private_key, :text
+ add_column :application_settings, :encrypted_lets_encrypt_private_key_iv, :text
+ end
+end
diff --git a/db/migrate/20190516155724_change_packages_size_defaults_in_project_statistics.rb b/db/migrate/20190516155724_change_packages_size_defaults_in_project_statistics.rb
new file mode 100644
index 00000000000..eba154df496
--- /dev/null
+++ b/db/migrate/20190516155724_change_packages_size_defaults_in_project_statistics.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class ChangePackagesSizeDefaultsInProjectStatistics < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ change_column_default :project_statistics, :packages_size, 0
+
+ update_column_in_batches(:project_statistics, :packages_size, 0) do |table, query|
+ query.where(table[:packages_size].eq(nil))
+ end
+
+ change_column_null :project_statistics, :packages_size, false
+ end
+
+ def down
+ change_column_null :project_statistics, :packages_size, true
+ change_column_default :project_statistics, :packages_size, nil
+ end
+end
diff --git a/db/migrate/20190523112344_limit_milestone_date_years_to_4_digits.rb b/db/migrate/20190523112344_limit_milestone_date_years_to_4_digits.rb
new file mode 100644
index 00000000000..86fe09d7573
--- /dev/null
+++ b/db/migrate/20190523112344_limit_milestone_date_years_to_4_digits.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class LimitMilestoneDateYearsTo4Digits < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ # When a migration requires downtime you **must** uncomment the following
+ # constant and define a short and easy to understand explanation as to why the
+ # migration requires downtime.
+ # DOWNTIME_REASON = ''
+
+ # When using the methods "add_concurrent_index", "remove_concurrent_index" or
+ # "add_column_with_default" you must disable the use of transactions
+ # as these methods can not run in an existing transaction.
+ # When using "add_concurrent_index" or "remove_concurrent_index" methods make sure
+ # that either of them is the _only_ method called in the migration,
+ # any other changes should go in a separate migration.
+ # This ensures that upon failure _only_ the index creation or removing fails
+ # and can be retried or reverted easily.
+ #
+ # To disable transactions uncomment the following line and remove these
+ # comments:
+ # disable_ddl_transaction!
+
+ def change
+ Milestone.where("start_date > '9999-12-31'").update_all(
+ "start_date = '9999-12-31'"
+ )
+ Milestone.where("due_date > '9999-12-31'").update_all(
+ "due_date = '9999-12-31'"
+ )
+ end
+end
diff --git a/db/migrate/20190524062810_generate_lets_encrypt_private_key.rb b/db/migrate/20190524062810_generate_lets_encrypt_private_key.rb
new file mode 100644
index 00000000000..ae93a76575a
--- /dev/null
+++ b/db/migrate/20190524062810_generate_lets_encrypt_private_key.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class GenerateLetsEncryptPrivateKey < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ # we now generate this key on the fly, but since this migration was merged to master, we don't remove it
+ def up
+ end
+
+ def down
+ end
+end
diff --git a/db/migrate/20190524071727_add_ssl_valid_period_to_pages_domain.rb b/db/migrate/20190524071727_add_ssl_valid_period_to_pages_domain.rb
new file mode 100644
index 00000000000..18544dcb6d3
--- /dev/null
+++ b/db/migrate/20190524071727_add_ssl_valid_period_to_pages_domain.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddSslValidPeriodToPagesDomain < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ def change
+ add_column :pages_domains, :certificate_valid_not_before, :datetime_with_timezone
+ add_column :pages_domains, :certificate_valid_not_after, :datetime_with_timezone
+ end
+end
diff --git a/db/migrate/20190527194830_add_wiki_size_to_statistics.rb b/db/migrate/20190527194830_add_wiki_size_to_statistics.rb
new file mode 100644
index 00000000000..d4f16cdec18
--- /dev/null
+++ b/db/migrate/20190527194830_add_wiki_size_to_statistics.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddWikiSizeToStatistics < ActiveRecord::Migration[5.0]
+ DOWNTIME = false
+
+ def change
+ add_column :project_statistics, :wiki_size, :bigint
+ end
+end
diff --git a/db/migrate/20190529142545_add_dns_rebinding_protection_enabled_to_application_settings.rb b/db/migrate/20190529142545_add_dns_rebinding_protection_enabled_to_application_settings.rb
new file mode 100644
index 00000000000..8835dc8b7ba
--- /dev/null
+++ b/db/migrate/20190529142545_add_dns_rebinding_protection_enabled_to_application_settings.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddDnsRebindingProtectionEnabledToApplicationSettings < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default(:application_settings, :dns_rebinding_protection_enabled,
+ :boolean,
+ default: true,
+ allow_null: false)
+ end
+
+ def down
+ remove_column(:application_settings, :dns_rebinding_protection_enabled)
+ end
+end
diff --git a/db/migrate/20190530042141_add_default_git_depth_to_ci_cd_settings.rb b/db/migrate/20190530042141_add_default_git_depth_to_ci_cd_settings.rb
new file mode 100644
index 00000000000..8abea05def4
--- /dev/null
+++ b/db/migrate/20190530042141_add_default_git_depth_to_ci_cd_settings.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddDefaultGitDepthToCiCdSettings < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :project_ci_cd_settings, :default_git_depth, :integer
+ end
+end
diff --git a/db/migrate/20190530154715_add_index_to_merge_requests_state_and_merge_status.rb b/db/migrate/20190530154715_add_index_to_merge_requests_state_and_merge_status.rb
new file mode 100644
index 00000000000..e669f81ca35
--- /dev/null
+++ b/db/migrate/20190530154715_add_index_to_merge_requests_state_and_merge_status.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddIndexToMergeRequestsStateAndMergeStatus < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :merge_requests, [:state, :merge_status],
+ where: "state = 'opened' AND merge_status = 'can_be_merged'"
+ end
+
+ def down
+ remove_concurrent_index :merge_requests, [:state, :merge_status]
+ end
+end
diff --git a/db/migrate/20190604184643_fix_pool_repository_source_project_id.rb b/db/migrate/20190604184643_fix_pool_repository_source_project_id.rb
new file mode 100644
index 00000000000..30244760e6b
--- /dev/null
+++ b/db/migrate/20190604184643_fix_pool_repository_source_project_id.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class FixPoolRepositorySourceProjectId < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ def up
+ execute "UPDATE pool_repositories SET source_project_id = (SELECT MIN(id) FROM projects WHERE pool_repository_id = pool_repositories.id) WHERE pool_repositories.source_project_id IS NULL"
+ end
+
+ def down
+ # nothing to do her
+ end
+end
diff --git a/db/migrate/20190605104727_add_default_project_deletion_protection_to_application_settings.rb b/db/migrate/20190605104727_add_default_project_deletion_protection_to_application_settings.rb
new file mode 100644
index 00000000000..ee04b49813b
--- /dev/null
+++ b/db/migrate/20190605104727_add_default_project_deletion_protection_to_application_settings.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddDefaultProjectDeletionProtectionToApplicationSettings < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default :application_settings, :default_project_deletion_protection, :boolean, default: false, allow_null: false
+ end
+
+ def down
+ remove_column :application_settings, :default_project_deletion_protection
+ end
+end
diff --git a/db/migrate/20190606014128_add_last_ci_minutes_notification_at_to_namespaces.rb b/db/migrate/20190606014128_add_last_ci_minutes_notification_at_to_namespaces.rb
new file mode 100644
index 00000000000..c264a23cda0
--- /dev/null
+++ b/db/migrate/20190606014128_add_last_ci_minutes_notification_at_to_namespaces.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddLastCiMinutesNotificationAtToNamespaces < ActiveRecord::Migration[5.1]
+ DOWNTIME = false
+
+ def change
+ add_column :namespaces, :last_ci_minutes_notification_at, :datetime_with_timezone
+ end
+end
diff --git a/db/migrate/20190607190856_add_index_to_users_public_emails.rb b/db/migrate/20190607190856_add_index_to_users_public_emails.rb
new file mode 100644
index 00000000000..81ec38b8b32
--- /dev/null
+++ b/db/migrate/20190607190856_add_index_to_users_public_emails.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddIndexToUsersPublicEmails < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :users, [:public_email],
+ where: "public_email != ''"
+ end
+
+ def down
+ remove_concurrent_index :users, [:public_email],
+ where: "public_email != ''"
+ end
+end
diff --git a/db/migrate/20190611161641_add_target_project_id_to_merge_trains.rb b/db/migrate/20190611161641_add_target_project_id_to_merge_trains.rb
new file mode 100644
index 00000000000..c200208e4c3
--- /dev/null
+++ b/db/migrate/20190611161641_add_target_project_id_to_merge_trains.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class AddTargetProjectIdToMergeTrains < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ # rubocop: disable Rails/NotNullColumn
+ add_reference :merge_trains, :target_project, null: false, index: true, foreign_key: { on_delete: :cascade, to_table: :projects }, type: :integer
+ add_column :merge_trains, :target_branch, :text, null: false
+ # rubocop: enable Rails/NotNullColumn
+ end
+end
diff --git a/db/post_migrate/20190301081611_migrate_project_migrate_sidekiq_queue.rb b/db/post_migrate/20190301081611_migrate_project_migrate_sidekiq_queue.rb
index 6af7902e0c4..46108d142b5 100644
--- a/db/post_migrate/20190301081611_migrate_project_migrate_sidekiq_queue.rb
+++ b/db/post_migrate/20190301081611_migrate_project_migrate_sidekiq_queue.rb
@@ -5,8 +5,6 @@ class MigrateProjectMigrateSidekiqQueue < ActiveRecord::Migration[5.0]
DOWNTIME = false
- DOWNTIME = false
-
def up
sidekiq_queue_migrate 'project_migrate_hashed_storage', to: 'hashed_storage:hashed_storage_project_migrate'
end
diff --git a/db/post_migrate/20190424134256_drop_projects_ci_id.rb b/db/post_migrate/20190424134256_drop_projects_ci_id.rb
new file mode 100644
index 00000000000..44e8f316393
--- /dev/null
+++ b/db/post_migrate/20190424134256_drop_projects_ci_id.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class DropProjectsCiId < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ if index_exists?(:projects, :ci_id)
+ remove_concurrent_index :projects, :ci_id
+ end
+
+ if column_exists?(:projects, :ci_id)
+ remove_column :projects, :ci_id
+ end
+ end
+
+ def down
+ unless column_exists?(:projects, :ci_id)
+ add_column :projects, :ci_id, :integer
+ end
+
+ unless index_exists?(:projects, :ci_id)
+ add_concurrent_index :projects, :ci_id
+ end
+ end
+end
diff --git a/db/post_migrate/20190506135400_schedule_sync_issuables_state_id_where_nil.rb b/db/post_migrate/20190506135400_schedule_sync_issuables_state_id_where_nil.rb
new file mode 100644
index 00000000000..4c31b5968ff
--- /dev/null
+++ b/db/post_migrate/20190506135400_schedule_sync_issuables_state_id_where_nil.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+class ScheduleSyncIssuablesStateIdWhereNil < ActiveRecord::Migration[5.1]
+ # Issues and MergeRequests imported by GitHub are being created with
+ # state_id = null, this fixes them.
+ #
+ # Part of a bigger plan: https://gitlab.com/gitlab-org/gitlab-ce/issues/51789
+
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ # 2019-05-02 gitlab.com issuable numbers
+ # issues with state_id nil: ~40000
+ # merge requests with state_id nil: ~200000
+ #
+ # Using 5000 as batch size and 120 seconds interval will create:
+ # ~8 jobs for issues - taking ~16 minutes
+ # ~40 jobs for merge requests - taking ~1.34 hours
+ #
+ BATCH_SIZE = 5000
+ DELAY_INTERVAL = 120.seconds.to_i
+ ISSUES_MIGRATION = 'SyncIssuesStateId'.freeze
+ MERGE_REQUESTS_MIGRATION = 'SyncMergeRequestsStateId'.freeze
+
+ disable_ddl_transaction!
+
+ class Issue < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'issues'
+ end
+
+ class MergeRequest < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'merge_requests'
+ end
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ Issue.where(state_id: nil),
+ ISSUES_MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE
+ )
+
+ queue_background_migration_jobs_by_range_at_intervals(
+ MergeRequest.where(state_id: nil),
+ MERGE_REQUESTS_MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE
+ )
+
+ # Remove temporary indexes added on "AddTemporaryIndexesToStateId"
+ remove_concurrent_index_by_name(:issues, "idx_on_issues_where_state_id_is_null")
+ remove_concurrent_index_by_name(:merge_requests, "idx_on_merge_requests_where_state_id_is_null")
+ end
+
+ def down
+ # No op
+ end
+end
diff --git a/db/post_migrate/20190522143720_drop_project_auto_devops_domain.rb b/db/post_migrate/20190522143720_drop_project_auto_devops_domain.rb
new file mode 100644
index 00000000000..36278d83927
--- /dev/null
+++ b/db/post_migrate/20190522143720_drop_project_auto_devops_domain.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class DropProjectAutoDevopsDomain < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ remove_column :project_auto_devops, :domain, :string
+ end
+end
diff --git a/db/post_migrate/20190524073827_schedule_fill_valid_time_for_pages_domain_certificates.rb b/db/post_migrate/20190524073827_schedule_fill_valid_time_for_pages_domain_certificates.rb
new file mode 100644
index 00000000000..1d8510e4514
--- /dev/null
+++ b/db/post_migrate/20190524073827_schedule_fill_valid_time_for_pages_domain_certificates.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class ScheduleFillValidTimeForPagesDomainCertificates < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ MIGRATION = 'FillValidTimeForPagesDomainCertificate'
+ BATCH_SIZE = 500
+ BATCH_TIME = 5.minutes
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ class PagesDomain < ActiveRecord::Base
+ include ::EachBatch
+
+ self.table_name = 'pages_domains'
+ end
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ PagesDomain.where.not(certificate: [nil, '']),
+ MIGRATION,
+ BATCH_TIME,
+ batch_size: BATCH_SIZE)
+ end
+
+ def down
+ end
+end
diff --git a/db/post_migrate/20190527194900_schedule_calculate_wiki_sizes.rb b/db/post_migrate/20190527194900_schedule_calculate_wiki_sizes.rb
new file mode 100644
index 00000000000..04cf5906b61
--- /dev/null
+++ b/db/post_migrate/20190527194900_schedule_calculate_wiki_sizes.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+class ScheduleCalculateWikiSizes < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ MIGRATION = 'CalculateWikiSizes'
+ BATCH_SIZE = 100000
+ BATCH_TIME = 5.minutes
+
+ class ProjectStatistics < ActiveRecord::Base
+ self.table_name = 'project_statistics'
+
+ scope :without_wiki_size, -> { where(wiki_size: nil) }
+
+ include ::EachBatch
+ end
+
+ disable_ddl_transaction!
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ ::ScheduleCalculateWikiSizes::ProjectStatistics.without_wiki_size,
+ MIGRATION,
+ BATCH_TIME,
+ batch_size: BATCH_SIZE)
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20190528180441_enqueue_reset_merge_status.rb b/db/post_migrate/20190528180441_enqueue_reset_merge_status.rb
new file mode 100644
index 00000000000..a3d2f497806
--- /dev/null
+++ b/db/post_migrate/20190528180441_enqueue_reset_merge_status.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class EnqueueResetMergeStatus < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ BATCH_SIZE = 10_000
+ MIGRATION = 'ResetMergeStatus'
+ DELAY_INTERVAL = 5.minutes.to_i
+
+ disable_ddl_transaction!
+
+ def up
+ say 'Scheduling `ResetMergeStatus` jobs'
+
+ # We currently have more than ~5_000_000 merge request records on GitLab.com.
+ # This means it'll schedule ~500 jobs (10k MRs each) with a 5 minutes gap,
+ # so this should take ~41 hours for all background migrations to complete.
+ # ((5_000_000 / 10_000) * 5) / 60 => 41.6666..
+ queue_background_migration_jobs_by_range_at_intervals(MergeRequest, MIGRATION, DELAY_INTERVAL, batch_size: BATCH_SIZE)
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index d1b3672725d..86a099d28b2 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,13 +10,13 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20190326164045) do
+ActiveRecord::Schema.define(version: 20190611161641) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
enable_extension "pg_trgm"
- create_table "abuse_reports", force: :cascade do |t|
+ create_table "abuse_reports", id: :serial, force: :cascade do |t|
t.integer "reporter_id"
t.integer "user_id"
t.text "message"
@@ -26,7 +26,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.integer "cached_markdown_version"
end
- create_table "appearances", force: :cascade do |t|
+ create_table "appearances", id: :serial, force: :cascade do |t|
t.string "title", null: false
t.text "description", null: false
t.string "header_logo"
@@ -47,13 +47,13 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.boolean "email_header_and_footer_enabled", default: false, null: false
end
- create_table "application_setting_terms", force: :cascade do |t|
+ create_table "application_setting_terms", id: :serial, force: :cascade do |t|
t.integer "cached_markdown_version"
t.text "terms", null: false
t.text "terms_html"
end
- create_table "application_settings", force: :cascade do |t|
+ create_table "application_settings", id: :serial, force: :cascade do |t|
t.integer "default_projects_limit"
t.boolean "signup_enabled"
t.boolean "gravatar_enabled"
@@ -187,10 +187,18 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.string "encrypted_external_auth_client_key_iv"
t.string "encrypted_external_auth_client_key_pass"
t.string "encrypted_external_auth_client_key_pass_iv"
+ t.string "lets_encrypt_notification_email"
+ t.boolean "lets_encrypt_terms_of_service_accepted", default: false, null: false
+ t.integer "elasticsearch_shards", default: 5, null: false
+ t.integer "elasticsearch_replicas", default: 1, null: false
+ t.text "encrypted_lets_encrypt_private_key"
+ t.text "encrypted_lets_encrypt_private_key_iv"
+ t.boolean "dns_rebinding_protection_enabled", default: true, null: false
+ t.boolean "default_project_deletion_protection", default: false, null: false
t.index ["usage_stats_set_by_user_id"], name: "index_application_settings_on_usage_stats_set_by_user_id", using: :btree
end
- create_table "audit_events", force: :cascade do |t|
+ create_table "audit_events", id: :serial, force: :cascade do |t|
t.integer "author_id", null: false
t.string "type", null: false
t.integer "entity_id", null: false
@@ -201,7 +209,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["entity_id", "entity_type"], name: "index_audit_events_on_entity_id_and_entity_type", using: :btree
end
- create_table "award_emoji", force: :cascade do |t|
+ create_table "award_emoji", id: :serial, force: :cascade do |t|
t.string "name"
t.integer "user_id"
t.integer "awardable_id"
@@ -212,7 +220,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id", "name"], name: "index_award_emoji_on_user_id_and_name", using: :btree
end
- create_table "badges", force: :cascade do |t|
+ create_table "badges", id: :serial, force: :cascade do |t|
t.string "link_url", null: false
t.string "image_url", null: false
t.integer "project_id"
@@ -224,7 +232,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_badges_on_project_id", using: :btree
end
- create_table "board_group_recent_visits", id: :bigserial, force: :cascade do |t|
+ create_table "board_group_recent_visits", force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.integer "user_id"
@@ -236,7 +244,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_board_group_recent_visits_on_user_id", using: :btree
end
- create_table "board_project_recent_visits", id: :bigserial, force: :cascade do |t|
+ create_table "board_project_recent_visits", force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.integer "user_id"
@@ -248,7 +256,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_board_project_recent_visits_on_user_id", using: :btree
end
- create_table "boards", force: :cascade do |t|
+ create_table "boards", id: :serial, force: :cascade do |t|
t.integer "project_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
@@ -257,7 +265,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_boards_on_project_id", using: :btree
end
- create_table "broadcast_messages", force: :cascade do |t|
+ create_table "broadcast_messages", id: :serial, force: :cascade do |t|
t.text "message", null: false
t.datetime "starts_at", null: false
t.datetime "ends_at", null: false
@@ -270,7 +278,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["starts_at", "ends_at", "id"], name: "index_broadcast_messages_on_starts_at_and_ends_at_and_id", using: :btree
end
- create_table "chat_names", force: :cascade do |t|
+ create_table "chat_names", id: :serial, force: :cascade do |t|
t.integer "user_id", null: false
t.integer "service_id", null: false
t.string "team_id", null: false
@@ -284,7 +292,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id", "service_id"], name: "index_chat_names_on_user_id_and_service_id", unique: true, using: :btree
end
- create_table "chat_teams", force: :cascade do |t|
+ create_table "chat_teams", id: :serial, force: :cascade do |t|
t.integer "namespace_id", null: false
t.string "team_id"
t.string "name"
@@ -293,7 +301,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["namespace_id"], name: "index_chat_teams_on_namespace_id", unique: true, using: :btree
end
- create_table "ci_build_trace_chunks", id: :bigserial, force: :cascade do |t|
+ create_table "ci_build_trace_chunks", force: :cascade do |t|
t.integer "build_id", null: false
t.integer "chunk_index", null: false
t.integer "data_store", null: false
@@ -301,13 +309,13 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["build_id", "chunk_index"], name: "index_ci_build_trace_chunks_on_build_id_and_chunk_index", unique: true, using: :btree
end
- create_table "ci_build_trace_section_names", force: :cascade do |t|
+ create_table "ci_build_trace_section_names", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.string "name", null: false
t.index ["project_id", "name"], name: "index_ci_build_trace_section_names_on_project_id_and_name", unique: true, using: :btree
end
- create_table "ci_build_trace_sections", force: :cascade do |t|
+ create_table "ci_build_trace_sections", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.datetime_with_timezone "date_start", null: false
t.datetime_with_timezone "date_end", null: false
@@ -320,7 +328,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["section_name_id"], name: "index_ci_build_trace_sections_on_section_name_id", using: :btree
end
- create_table "ci_builds", force: :cascade do |t|
+ create_table "ci_builds", id: :serial, force: :cascade do |t|
t.string "status"
t.datetime "finished_at"
t.text "trace"
@@ -376,6 +384,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id", "id"], name: "index_ci_builds_on_project_id_and_id", using: :btree
t.index ["project_id", "status"], name: "index_ci_builds_project_id_and_status_for_live_jobs_partial2", where: "(((type)::text = 'Ci::Build'::text) AND ((status)::text = ANY (ARRAY[('running'::character varying)::text, ('pending'::character varying)::text, ('created'::character varying)::text])))", using: :btree
t.index ["protected"], name: "index_ci_builds_on_protected", using: :btree
+ t.index ["queued_at"], name: "index_ci_builds_on_queued_at", using: :btree
t.index ["runner_id"], name: "index_ci_builds_on_runner_id", using: :btree
t.index ["scheduled_at"], name: "partial_index_ci_builds_on_scheduled_at_with_scheduled_jobs", where: "((scheduled_at IS NOT NULL) AND ((type)::text = 'Ci::Build'::text) AND ((status)::text = 'scheduled'::text))", using: :btree
t.index ["stage_id", "stage_idx"], name: "tmp_build_stage_position_index", where: "(stage_idx IS NOT NULL)", using: :btree
@@ -387,7 +396,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_ci_builds_on_user_id", using: :btree
end
- create_table "ci_builds_metadata", force: :cascade do |t|
+ create_table "ci_builds_metadata", id: :serial, force: :cascade do |t|
t.integer "build_id", null: false
t.integer "project_id", null: false
t.integer "timeout"
@@ -398,7 +407,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_ci_builds_metadata_on_project_id", using: :btree
end
- create_table "ci_builds_runner_session", id: :bigserial, force: :cascade do |t|
+ create_table "ci_builds_runner_session", force: :cascade do |t|
t.integer "build_id", null: false
t.string "url", null: false
t.string "certificate"
@@ -406,7 +415,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["build_id"], name: "index_ci_builds_runner_session_on_build_id", unique: true, using: :btree
end
- create_table "ci_group_variables", force: :cascade do |t|
+ create_table "ci_group_variables", id: :serial, force: :cascade do |t|
t.string "key", null: false
t.text "value"
t.text "encrypted_value"
@@ -417,10 +426,11 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.boolean "masked", default: false, null: false
+ t.integer "variable_type", limit: 2, default: 1, null: false
t.index ["group_id", "key"], name: "index_ci_group_variables_on_group_id_and_key", unique: true, using: :btree
end
- create_table "ci_job_artifacts", force: :cascade do |t|
+ create_table "ci_job_artifacts", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.integer "job_id", null: false
t.integer "file_type", null: false
@@ -439,7 +449,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_ci_job_artifacts_on_project_id", using: :btree
end
- create_table "ci_pipeline_chat_data", id: :bigserial, force: :cascade do |t|
+ create_table "ci_pipeline_chat_data", force: :cascade do |t|
t.integer "pipeline_id", null: false
t.integer "chat_name_id", null: false
t.text "response_url", null: false
@@ -456,10 +466,11 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.integer "pipeline_schedule_id", null: false
t.datetime_with_timezone "created_at"
t.datetime_with_timezone "updated_at"
+ t.integer "variable_type", limit: 2, default: 1, null: false
t.index ["pipeline_schedule_id", "key"], name: "index_ci_pipeline_schedule_variables_on_schedule_id_and_key", unique: true, using: :btree
end
- create_table "ci_pipeline_schedules", force: :cascade do |t|
+ create_table "ci_pipeline_schedules", id: :serial, force: :cascade do |t|
t.string "description"
t.string "ref"
t.string "cron"
@@ -475,17 +486,18 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_ci_pipeline_schedules_on_project_id", using: :btree
end
- create_table "ci_pipeline_variables", force: :cascade do |t|
+ create_table "ci_pipeline_variables", id: :serial, force: :cascade do |t|
t.string "key", null: false
t.text "value"
t.text "encrypted_value"
t.string "encrypted_value_salt"
t.string "encrypted_value_iv"
t.integer "pipeline_id", null: false
+ t.integer "variable_type", limit: 2, default: 1, null: false
t.index ["pipeline_id", "key"], name: "index_ci_pipeline_variables_on_pipeline_id_and_key", unique: true, using: :btree
end
- create_table "ci_pipelines", force: :cascade do |t|
+ create_table "ci_pipelines", id: :serial, force: :cascade do |t|
t.string "ref"
t.string "sha"
t.string "before_sha"
@@ -525,14 +537,14 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_ci_pipelines_on_user_id", using: :btree
end
- create_table "ci_runner_namespaces", force: :cascade do |t|
+ create_table "ci_runner_namespaces", id: :serial, force: :cascade do |t|
t.integer "runner_id"
t.integer "namespace_id"
t.index ["namespace_id"], name: "index_ci_runner_namespaces_on_namespace_id", using: :btree
t.index ["runner_id", "namespace_id"], name: "index_ci_runner_namespaces_on_runner_id_and_namespace_id", unique: true, using: :btree
end
- create_table "ci_runner_projects", force: :cascade do |t|
+ create_table "ci_runner_projects", id: :serial, force: :cascade do |t|
t.integer "runner_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
@@ -541,7 +553,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["runner_id"], name: "index_ci_runner_projects_on_runner_id", using: :btree
end
- create_table "ci_runners", force: :cascade do |t|
+ create_table "ci_runners", id: :serial, force: :cascade do |t|
t.string "token"
t.datetime "created_at"
t.datetime "updated_at"
@@ -569,7 +581,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["token_encrypted"], name: "index_ci_runners_on_token_encrypted", using: :btree
end
- create_table "ci_stages", force: :cascade do |t|
+ create_table "ci_stages", id: :serial, force: :cascade do |t|
t.integer "project_id"
t.integer "pipeline_id"
t.datetime "created_at"
@@ -584,7 +596,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_ci_stages_on_project_id", using: :btree
end
- create_table "ci_trigger_requests", force: :cascade do |t|
+ create_table "ci_trigger_requests", id: :serial, force: :cascade do |t|
t.integer "trigger_id", null: false
t.text "variables"
t.datetime "created_at"
@@ -594,7 +606,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["trigger_id"], name: "index_ci_trigger_requests_on_trigger_id", using: :btree
end
- create_table "ci_triggers", force: :cascade do |t|
+ create_table "ci_triggers", id: :serial, force: :cascade do |t|
t.string "token"
t.datetime "created_at"
t.datetime "updated_at"
@@ -606,7 +618,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_ci_triggers_on_project_id", using: :btree
end
- create_table "ci_variables", force: :cascade do |t|
+ create_table "ci_variables", id: :serial, force: :cascade do |t|
t.string "key", null: false
t.text "value"
t.text "encrypted_value"
@@ -616,17 +628,18 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.boolean "protected", default: false, null: false
t.string "environment_scope", default: "*", null: false
t.boolean "masked", default: false, null: false
+ t.integer "variable_type", limit: 2, default: 1, null: false
t.index ["project_id", "key", "environment_scope"], name: "index_ci_variables_on_project_id_and_key_and_environment_scope", unique: true, using: :btree
end
- create_table "cluster_groups", force: :cascade do |t|
+ create_table "cluster_groups", id: :serial, force: :cascade do |t|
t.integer "cluster_id", null: false
t.integer "group_id", null: false
t.index ["cluster_id", "group_id"], name: "index_cluster_groups_on_cluster_id_and_group_id", unique: true, using: :btree
t.index ["group_id"], name: "index_cluster_groups_on_group_id", using: :btree
end
- create_table "cluster_platforms_kubernetes", force: :cascade do |t|
+ create_table "cluster_platforms_kubernetes", id: :serial, force: :cascade do |t|
t.integer "cluster_id", null: false
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
@@ -642,7 +655,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["cluster_id"], name: "index_cluster_platforms_kubernetes_on_cluster_id", unique: true, using: :btree
end
- create_table "cluster_projects", force: :cascade do |t|
+ create_table "cluster_projects", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.integer "cluster_id", null: false
t.datetime_with_timezone "created_at", null: false
@@ -651,7 +664,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_cluster_projects_on_project_id", using: :btree
end
- create_table "cluster_providers_gcp", force: :cascade do |t|
+ create_table "cluster_providers_gcp", id: :serial, force: :cascade do |t|
t.integer "cluster_id", null: false
t.integer "status"
t.integer "num_nodes", null: false
@@ -669,7 +682,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["cluster_id"], name: "index_cluster_providers_gcp_on_cluster_id", unique: true, using: :btree
end
- create_table "clusters", force: :cascade do |t|
+ create_table "clusters", id: :serial, force: :cascade do |t|
t.integer "user_id"
t.integer "provider_type"
t.integer "platform_type"
@@ -685,7 +698,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_clusters_on_user_id", using: :btree
end
- create_table "clusters_applications_cert_managers", force: :cascade do |t|
+ create_table "clusters_applications_cert_managers", id: :serial, force: :cascade do |t|
t.integer "cluster_id", null: false
t.integer "status", null: false
t.string "version", null: false
@@ -696,7 +709,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["cluster_id"], name: "index_clusters_applications_cert_managers_on_cluster_id", unique: true, using: :btree
end
- create_table "clusters_applications_helm", force: :cascade do |t|
+ create_table "clusters_applications_helm", id: :serial, force: :cascade do |t|
t.integer "cluster_id", null: false
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
@@ -709,7 +722,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["cluster_id"], name: "index_clusters_applications_helm_on_cluster_id", unique: true, using: :btree
end
- create_table "clusters_applications_ingress", force: :cascade do |t|
+ create_table "clusters_applications_ingress", id: :serial, force: :cascade do |t|
t.integer "cluster_id", null: false
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
@@ -723,7 +736,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["cluster_id"], name: "index_clusters_applications_ingress_on_cluster_id", unique: true, using: :btree
end
- create_table "clusters_applications_jupyter", force: :cascade do |t|
+ create_table "clusters_applications_jupyter", id: :serial, force: :cascade do |t|
t.integer "cluster_id", null: false
t.integer "oauth_application_id"
t.integer "status", null: false
@@ -736,7 +749,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["oauth_application_id"], name: "index_clusters_applications_jupyter_on_oauth_application_id", using: :btree
end
- create_table "clusters_applications_knative", force: :cascade do |t|
+ create_table "clusters_applications_knative", id: :serial, force: :cascade do |t|
t.integer "cluster_id", null: false
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
@@ -749,7 +762,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["cluster_id"], name: "index_clusters_applications_knative_on_cluster_id", unique: true, using: :btree
end
- create_table "clusters_applications_prometheus", force: :cascade do |t|
+ create_table "clusters_applications_prometheus", id: :serial, force: :cascade do |t|
t.integer "cluster_id", null: false
t.integer "status", null: false
t.string "version", null: false
@@ -759,7 +772,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["cluster_id"], name: "index_clusters_applications_prometheus_on_cluster_id", unique: true, using: :btree
end
- create_table "clusters_applications_runners", force: :cascade do |t|
+ create_table "clusters_applications_runners", id: :serial, force: :cascade do |t|
t.integer "cluster_id", null: false
t.integer "runner_id"
t.integer "status", null: false
@@ -772,7 +785,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["runner_id"], name: "index_clusters_applications_runners_on_runner_id", using: :btree
end
- create_table "clusters_kubernetes_namespaces", id: :bigserial, force: :cascade do |t|
+ create_table "clusters_kubernetes_namespaces", force: :cascade do |t|
t.integer "cluster_id", null: false
t.integer "project_id"
t.integer "cluster_project_id"
@@ -788,7 +801,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_clusters_kubernetes_namespaces_on_project_id", using: :btree
end
- create_table "container_repositories", force: :cascade do |t|
+ create_table "container_repositories", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.string "name", null: false
t.datetime "created_at", null: false
@@ -797,7 +810,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_container_repositories_on_project_id", using: :btree
end
- create_table "conversational_development_index_metrics", force: :cascade do |t|
+ create_table "conversational_development_index_metrics", id: :serial, force: :cascade do |t|
t.float "leader_issues", null: false
t.float "instance_issues", null: false
t.float "leader_notes", null: false
@@ -832,7 +845,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.float "percentage_service_desk_issues", default: 0.0, null: false
end
- create_table "deploy_keys_projects", force: :cascade do |t|
+ create_table "deploy_keys_projects", id: :serial, force: :cascade do |t|
t.integer "deploy_key_id", null: false
t.integer "project_id", null: false
t.datetime "created_at"
@@ -841,7 +854,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_deploy_keys_projects_on_project_id", using: :btree
end
- create_table "deploy_tokens", force: :cascade do |t|
+ create_table "deploy_tokens", id: :serial, force: :cascade do |t|
t.boolean "revoked", default: false
t.boolean "read_repository", default: false, null: false
t.boolean "read_registry", default: false, null: false
@@ -853,7 +866,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["token"], name: "index_deploy_tokens_on_token", unique: true, using: :btree
end
- create_table "deployments", force: :cascade do |t|
+ create_table "deployments", id: :serial, force: :cascade do |t|
t.integer "iid", null: false
t.integer "project_id", null: false
t.integer "environment_id", null: false
@@ -879,7 +892,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id", "status"], name: "index_deployments_on_project_id_and_status", using: :btree
end
- create_table "emails", force: :cascade do |t|
+ create_table "emails", id: :serial, force: :cascade do |t|
t.integer "user_id", null: false
t.string "email", null: false
t.datetime "created_at"
@@ -892,7 +905,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_emails_on_user_id", using: :btree
end
- create_table "environments", force: :cascade do |t|
+ create_table "environments", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.string "name", null: false
t.datetime "created_at"
@@ -905,7 +918,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id", "slug"], name: "index_environments_on_project_id_and_slug", unique: true, using: :btree
end
- create_table "events", force: :cascade do |t|
+ create_table "events", id: :serial, force: :cascade do |t|
t.integer "project_id"
t.integer "author_id", null: false
t.integer "target_id"
@@ -920,7 +933,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["target_type", "target_id"], name: "index_events_on_target_type_and_target_id", using: :btree
end
- create_table "feature_gates", force: :cascade do |t|
+ create_table "feature_gates", id: :serial, force: :cascade do |t|
t.string "feature_key", null: false
t.string "key", null: false
t.string "value"
@@ -929,14 +942,14 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["feature_key", "key", "value"], name: "index_feature_gates_on_feature_key_and_key_and_value", unique: true, using: :btree
end
- create_table "features", force: :cascade do |t|
+ create_table "features", id: :serial, force: :cascade do |t|
t.string "key", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["key"], name: "index_features_on_key", unique: true, using: :btree
end
- create_table "fork_network_members", force: :cascade do |t|
+ create_table "fork_network_members", id: :serial, force: :cascade do |t|
t.integer "fork_network_id", null: false
t.integer "project_id", null: false
t.integer "forked_from_project_id"
@@ -945,13 +958,13 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_fork_network_members_on_project_id", unique: true, using: :btree
end
- create_table "fork_networks", force: :cascade do |t|
+ create_table "fork_networks", id: :serial, force: :cascade do |t|
t.integer "root_project_id"
t.string "deleted_root_project_name"
t.index ["root_project_id"], name: "index_fork_networks_on_root_project_id", unique: true, using: :btree
end
- create_table "forked_project_links", force: :cascade do |t|
+ create_table "forked_project_links", id: :serial, force: :cascade do |t|
t.integer "forked_to_project_id", null: false
t.integer "forked_from_project_id", null: false
t.datetime "created_at"
@@ -959,7 +972,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree
end
- create_table "gpg_key_subkeys", force: :cascade do |t|
+ create_table "gpg_key_subkeys", id: :serial, force: :cascade do |t|
t.integer "gpg_key_id", null: false
t.binary "keyid"
t.binary "fingerprint"
@@ -968,7 +981,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["keyid"], name: "index_gpg_key_subkeys_on_keyid", unique: true, using: :btree
end
- create_table "gpg_keys", force: :cascade do |t|
+ create_table "gpg_keys", id: :serial, force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.integer "user_id"
@@ -980,7 +993,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_gpg_keys_on_user_id", using: :btree
end
- create_table "gpg_signatures", force: :cascade do |t|
+ create_table "gpg_signatures", id: :serial, force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.integer "project_id"
@@ -998,7 +1011,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_gpg_signatures_on_project_id", using: :btree
end
- create_table "group_custom_attributes", force: :cascade do |t|
+ create_table "group_custom_attributes", id: :serial, force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.integer "group_id", null: false
@@ -1008,7 +1021,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["key", "value"], name: "index_group_custom_attributes_on_key_and_value", using: :btree
end
- create_table "identities", force: :cascade do |t|
+ create_table "identities", id: :serial, force: :cascade do |t|
t.string "extern_uid"
t.string "provider"
t.integer "user_id"
@@ -1017,7 +1030,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_identities_on_user_id", using: :btree
end
- create_table "import_export_uploads", force: :cascade do |t|
+ create_table "import_export_uploads", id: :serial, force: :cascade do |t|
t.datetime_with_timezone "updated_at", null: false
t.integer "project_id"
t.text "import_file"
@@ -1026,7 +1039,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["updated_at"], name: "index_import_export_uploads_on_updated_at", using: :btree
end
- create_table "internal_ids", id: :bigserial, force: :cascade do |t|
+ create_table "internal_ids", force: :cascade do |t|
t.integer "project_id"
t.integer "usage", null: false
t.integer "last_value", null: false
@@ -1044,7 +1057,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_issue_assignees_on_user_id", using: :btree
end
- create_table "issue_metrics", force: :cascade do |t|
+ create_table "issue_metrics", id: :serial, force: :cascade do |t|
t.integer "issue_id", null: false
t.datetime "first_mentioned_in_commit_at"
t.datetime "first_associated_with_milestone_at"
@@ -1054,7 +1067,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["issue_id"], name: "index_issue_metrics", using: :btree
end
- create_table "issues", force: :cascade do |t|
+ create_table "issues", id: :serial, force: :cascade do |t|
t.string "title"
t.integer "author_id"
t.integer "project_id"
@@ -1097,7 +1110,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["updated_by_id"], name: "index_issues_on_updated_by_id", where: "(updated_by_id IS NOT NULL)", using: :btree
end
- create_table "keys", force: :cascade do |t|
+ create_table "keys", id: :serial, force: :cascade do |t|
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
@@ -1111,7 +1124,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_keys_on_user_id", using: :btree
end
- create_table "label_links", force: :cascade do |t|
+ create_table "label_links", id: :serial, force: :cascade do |t|
t.integer "label_id"
t.integer "target_id"
t.string "target_type"
@@ -1121,7 +1134,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["target_id", "target_type"], name: "index_label_links_on_target_id_and_target_type", using: :btree
end
- create_table "label_priorities", force: :cascade do |t|
+ create_table "label_priorities", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.integer "label_id", null: false
t.integer "priority", null: false
@@ -1132,7 +1145,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id", "label_id"], name: "index_label_priorities_on_project_id_and_label_id", unique: true, using: :btree
end
- create_table "labels", force: :cascade do |t|
+ create_table "labels", id: :serial, force: :cascade do |t|
t.string "title"
t.string "color"
t.integer "project_id"
@@ -1151,7 +1164,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["type", "project_id"], name: "index_labels_on_type_and_project_id", using: :btree
end
- create_table "lfs_file_locks", force: :cascade do |t|
+ create_table "lfs_file_locks", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.integer "user_id", null: false
t.datetime "created_at", null: false
@@ -1160,7 +1173,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_lfs_file_locks_on_user_id", using: :btree
end
- create_table "lfs_objects", force: :cascade do |t|
+ create_table "lfs_objects", id: :serial, force: :cascade do |t|
t.string "oid", null: false
t.bigint "size", null: false
t.datetime "created_at"
@@ -1171,7 +1184,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["oid"], name: "index_lfs_objects_on_oid", unique: true, using: :btree
end
- create_table "lfs_objects_projects", force: :cascade do |t|
+ create_table "lfs_objects_projects", id: :serial, force: :cascade do |t|
t.integer "lfs_object_id", null: false
t.integer "project_id", null: false
t.datetime "created_at"
@@ -1179,7 +1192,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_lfs_objects_projects_on_project_id", using: :btree
end
- create_table "lists", force: :cascade do |t|
+ create_table "lists", id: :serial, force: :cascade do |t|
t.integer "board_id", null: false
t.integer "label_id"
t.integer "list_type", default: 1, null: false
@@ -1191,7 +1204,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["list_type"], name: "index_lists_on_list_type", using: :btree
end
- create_table "members", force: :cascade do |t|
+ create_table "members", id: :serial, force: :cascade do |t|
t.integer "access_level", null: false
t.integer "source_id", null: false
t.string "source_type", null: false
@@ -1221,6 +1234,15 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_merge_request_assignees_on_user_id", using: :btree
end
+ create_table "merge_request_blocks", force: :cascade do |t|
+ t.integer "blocking_merge_request_id", null: false
+ t.integer "blocked_merge_request_id", null: false
+ t.datetime_with_timezone "created_at", null: false
+ t.datetime_with_timezone "updated_at", null: false
+ t.index ["blocked_merge_request_id"], name: "index_merge_request_blocks_on_blocked_merge_request_id", using: :btree
+ t.index ["blocking_merge_request_id", "blocked_merge_request_id"], name: "index_mr_blocks_on_blocking_and_blocked_mr_ids", unique: true, using: :btree
+ end
+
create_table "merge_request_diff_commits", id: false, force: :cascade do |t|
t.datetime_with_timezone "authored_date"
t.datetime_with_timezone "committed_date"
@@ -1254,7 +1276,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["merge_request_diff_id", "relative_order"], name: "index_merge_request_diff_files_on_mr_diff_id_and_order", unique: true, using: :btree
end
- create_table "merge_request_diffs", force: :cascade do |t|
+ create_table "merge_request_diffs", id: :serial, force: :cascade do |t|
t.string "state"
t.integer "merge_request_id", null: false
t.datetime "created_at"
@@ -1271,7 +1293,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["merge_request_id", "id"], name: "index_merge_request_diffs_on_merge_request_id_and_id_partial", where: "((NOT stored_externally) OR (stored_externally IS NULL))", using: :btree
end
- create_table "merge_request_metrics", force: :cascade do |t|
+ create_table "merge_request_metrics", id: :serial, force: :cascade do |t|
t.integer "merge_request_id", null: false
t.datetime "latest_build_started_at"
t.datetime "latest_build_finished_at"
@@ -1292,7 +1314,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["pipeline_id"], name: "index_merge_request_metrics_on_pipeline_id", using: :btree
end
- create_table "merge_requests", force: :cascade do |t|
+ create_table "merge_requests", id: :serial, force: :cascade do |t|
t.string "target_branch", null: false
t.string "source_branch", null: false
t.integer "source_project_id"
@@ -1341,6 +1363,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["source_branch"], name: "index_merge_requests_on_source_branch", using: :btree
t.index ["source_project_id", "source_branch"], name: "index_merge_requests_on_source_project_and_branch_state_opened", where: "((state)::text = 'opened'::text)", using: :btree
t.index ["source_project_id", "source_branch"], name: "index_merge_requests_on_source_project_id_and_source_branch", using: :btree
+ t.index ["state", "merge_status"], name: "index_merge_requests_on_state_and_merge_status", where: "(((state)::text = 'opened'::text) AND ((merge_status)::text = 'can_be_merged'::text))", using: :btree
t.index ["target_branch"], name: "index_merge_requests_on_target_branch", using: :btree
t.index ["target_project_id", "iid"], name: "index_merge_requests_on_target_project_id_and_iid", unique: true, using: :btree
t.index ["target_project_id", "iid"], name: "index_merge_requests_on_target_project_id_and_iid_opened", where: "((state)::text = 'opened'::text)", using: :btree
@@ -1350,7 +1373,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["updated_by_id"], name: "index_merge_requests_on_updated_by_id", where: "(updated_by_id IS NOT NULL)", using: :btree
end
- create_table "merge_requests_closing_issues", force: :cascade do |t|
+ create_table "merge_requests_closing_issues", id: :serial, force: :cascade do |t|
t.integer "merge_request_id", null: false
t.integer "issue_id", null: false
t.datetime "created_at", null: false
@@ -1359,7 +1382,21 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["merge_request_id"], name: "index_merge_requests_closing_issues_on_merge_request_id", using: :btree
end
- create_table "milestones", force: :cascade do |t|
+ create_table "merge_trains", force: :cascade do |t|
+ t.integer "merge_request_id", null: false
+ t.integer "user_id", null: false
+ t.integer "pipeline_id"
+ t.datetime_with_timezone "created_at", null: false
+ t.datetime_with_timezone "updated_at", null: false
+ t.integer "target_project_id", null: false
+ t.text "target_branch", null: false
+ t.index ["merge_request_id"], name: "index_merge_trains_on_merge_request_id", unique: true, using: :btree
+ t.index ["pipeline_id"], name: "index_merge_trains_on_pipeline_id", using: :btree
+ t.index ["target_project_id"], name: "index_merge_trains_on_target_project_id", using: :btree
+ t.index ["user_id"], name: "index_merge_trains_on_user_id", using: :btree
+ end
+
+ create_table "milestones", id: :serial, force: :cascade do |t|
t.string "title", null: false
t.integer "project_id"
t.text "description"
@@ -1381,7 +1418,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["title"], name: "index_milestones_on_title_trigram", using: :gin, opclasses: {"title"=>"gin_trgm_ops"}
end
- create_table "namespaces", force: :cascade do |t|
+ create_table "namespaces", id: :serial, force: :cascade do |t|
t.string "name", null: false
t.string "path", null: false
t.integer "owner_id"
@@ -1403,6 +1440,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.string "runners_token_encrypted"
t.integer "project_creation_level"
t.boolean "auto_devops_enabled"
+ t.datetime_with_timezone "last_ci_minutes_notification_at"
t.index ["created_at"], name: "index_namespaces_on_created_at", using: :btree
t.index ["name", "parent_id"], name: "index_namespaces_on_name_and_parent_id", unique: true, using: :btree
t.index ["name"], name: "index_namespaces_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"}
@@ -1416,7 +1454,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["type"], name: "index_namespaces_on_type", using: :btree
end
- create_table "note_diff_files", force: :cascade do |t|
+ create_table "note_diff_files", id: :serial, force: :cascade do |t|
t.integer "diff_note_id", null: false
t.text "diff", null: false
t.boolean "new_file", null: false
@@ -1429,7 +1467,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["diff_note_id"], name: "index_note_diff_files_on_diff_note_id", unique: true, using: :btree
end
- create_table "notes", force: :cascade do |t|
+ create_table "notes", id: :serial, force: :cascade do |t|
t.text "note"
t.string "noteable_type"
t.integer "author_id"
@@ -1464,7 +1502,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id", "noteable_type"], name: "index_notes_on_project_id_and_noteable_type", using: :btree
end
- create_table "notification_settings", force: :cascade do |t|
+ create_table "notification_settings", id: :serial, force: :cascade do |t|
t.integer "user_id", null: false
t.integer "source_id"
t.string "source_type"
@@ -1485,12 +1523,13 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.boolean "success_pipeline"
t.boolean "push_to_merge_request"
t.boolean "issue_due"
+ t.string "notification_email"
t.index ["source_id", "source_type"], name: "index_notification_settings_on_source_id_and_source_type", using: :btree
t.index ["user_id", "source_id", "source_type"], name: "index_notifications_on_user_id_and_source_id_and_source_type", unique: true, using: :btree
t.index ["user_id"], name: "index_notification_settings_on_user_id", using: :btree
end
- create_table "oauth_access_grants", force: :cascade do |t|
+ create_table "oauth_access_grants", id: :serial, force: :cascade do |t|
t.integer "resource_owner_id", null: false
t.integer "application_id", null: false
t.string "token", null: false
@@ -1502,7 +1541,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["token"], name: "index_oauth_access_grants_on_token", unique: true, using: :btree
end
- create_table "oauth_access_tokens", force: :cascade do |t|
+ create_table "oauth_access_tokens", id: :serial, force: :cascade do |t|
t.integer "resource_owner_id"
t.integer "application_id"
t.string "token", null: false
@@ -1516,7 +1555,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["token"], name: "index_oauth_access_tokens_on_token", unique: true, using: :btree
end
- create_table "oauth_applications", force: :cascade do |t|
+ create_table "oauth_applications", id: :serial, force: :cascade do |t|
t.string "name", null: false
t.string "uid", null: false
t.string "secret", null: false
@@ -1531,13 +1570,27 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true, using: :btree
end
- create_table "oauth_openid_requests", force: :cascade do |t|
+ create_table "oauth_openid_requests", id: :serial, force: :cascade do |t|
t.integer "access_grant_id", null: false
t.string "nonce", null: false
t.index ["access_grant_id"], name: "index_oauth_openid_requests_on_access_grant_id", using: :btree
end
- create_table "pages_domains", force: :cascade do |t|
+ create_table "pages_domain_acme_orders", force: :cascade do |t|
+ t.integer "pages_domain_id", null: false
+ t.datetime_with_timezone "expires_at", null: false
+ t.datetime_with_timezone "created_at", null: false
+ t.datetime_with_timezone "updated_at", null: false
+ t.string "url", null: false
+ t.string "challenge_token", null: false
+ t.text "challenge_file_content", null: false
+ t.text "encrypted_private_key", null: false
+ t.text "encrypted_private_key_iv", null: false
+ t.index ["challenge_token"], name: "index_pages_domain_acme_orders_on_challenge_token", using: :btree
+ t.index ["pages_domain_id"], name: "index_pages_domain_acme_orders_on_pages_domain_id", using: :btree
+ end
+
+ create_table "pages_domains", id: :serial, force: :cascade do |t|
t.integer "project_id"
t.text "certificate"
t.text "encrypted_key"
@@ -1548,6 +1601,9 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.string "verification_code", null: false
t.datetime_with_timezone "enabled_until"
t.datetime_with_timezone "remove_at"
+ t.boolean "auto_ssl_enabled", default: false, null: false
+ t.datetime_with_timezone "certificate_valid_not_before"
+ t.datetime_with_timezone "certificate_valid_not_after"
t.index ["domain"], name: "index_pages_domains_on_domain", unique: true, using: :btree
t.index ["project_id", "enabled_until"], name: "index_pages_domains_on_project_id_and_enabled_until", using: :btree
t.index ["project_id"], name: "index_pages_domains_on_project_id", using: :btree
@@ -1556,7 +1612,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["verified_at"], name: "index_pages_domains_on_verified_at", using: :btree
end
- create_table "personal_access_tokens", force: :cascade do |t|
+ create_table "personal_access_tokens", id: :serial, force: :cascade do |t|
t.integer "user_id", null: false
t.string "name", null: false
t.boolean "revoked", default: false
@@ -1570,7 +1626,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_personal_access_tokens_on_user_id", using: :btree
end
- create_table "pool_repositories", id: :bigserial, force: :cascade do |t|
+ create_table "pool_repositories", force: :cascade do |t|
t.integer "shard_id", null: false
t.string "disk_path"
t.string "state"
@@ -1580,7 +1636,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["source_project_id"], name: "index_pool_repositories_on_source_project_id", unique: true, using: :btree
end
- create_table "programming_languages", force: :cascade do |t|
+ create_table "programming_languages", id: :serial, force: :cascade do |t|
t.string "name", null: false
t.string "color", null: false
t.datetime_with_timezone "created_at", null: false
@@ -1595,24 +1651,25 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id", "project_id", "access_level"], name: "index_project_authorizations_on_user_id_project_id_access_level", unique: true, using: :btree
end
- create_table "project_auto_devops", force: :cascade do |t|
+ create_table "project_auto_devops", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.boolean "enabled"
- t.string "domain"
t.integer "deploy_strategy", default: 0, null: false
t.index ["project_id"], name: "index_project_auto_devops_on_project_id", unique: true, using: :btree
end
- create_table "project_ci_cd_settings", force: :cascade do |t|
+ create_table "project_ci_cd_settings", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.boolean "group_runners_enabled", default: true, null: false
t.boolean "merge_pipelines_enabled"
+ t.boolean "merge_trains_enabled", default: false, null: false
+ t.integer "default_git_depth"
t.index ["project_id"], name: "index_project_ci_cd_settings_on_project_id", unique: true, using: :btree
end
- create_table "project_custom_attributes", force: :cascade do |t|
+ create_table "project_custom_attributes", id: :serial, force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.integer "project_id", null: false
@@ -1622,14 +1679,14 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id", "key"], name: "index_project_custom_attributes_on_project_id_and_key", unique: true, using: :btree
end
- create_table "project_daily_statistics", id: :bigserial, force: :cascade do |t|
+ create_table "project_daily_statistics", force: :cascade do |t|
t.integer "project_id", null: false
t.integer "fetch_count", null: false
t.date "date"
t.index ["project_id", "date"], name: "index_project_daily_statistics_on_project_id_and_date", unique: true, order: { date: :desc }, using: :btree
end
- create_table "project_deploy_tokens", force: :cascade do |t|
+ create_table "project_deploy_tokens", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.integer "deploy_token_id", null: false
t.datetime_with_timezone "created_at", null: false
@@ -1637,7 +1694,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id", "deploy_token_id"], name: "index_project_deploy_tokens_on_project_id_and_deploy_token_id", unique: true, using: :btree
end
- create_table "project_error_tracking_settings", primary_key: "project_id", id: :integer, force: :cascade do |t|
+ create_table "project_error_tracking_settings", primary_key: "project_id", id: :integer, default: nil, force: :cascade do |t|
t.boolean "enabled", default: false, null: false
t.string "api_url"
t.string "encrypted_token"
@@ -1646,7 +1703,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.string "organization_name"
end
- create_table "project_features", force: :cascade do |t|
+ create_table "project_features", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.integer "merge_requests_access_level"
t.integer "issues_access_level"
@@ -1660,7 +1717,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_project_features_on_project_id", unique: true, using: :btree
end
- create_table "project_group_links", force: :cascade do |t|
+ create_table "project_group_links", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.integer "group_id", null: false
t.datetime "created_at"
@@ -1671,7 +1728,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_project_group_links_on_project_id", using: :btree
end
- create_table "project_import_data", force: :cascade do |t|
+ create_table "project_import_data", id: :serial, force: :cascade do |t|
t.integer "project_id"
t.text "data"
t.text "encrypted_credentials"
@@ -1680,7 +1737,11 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_project_import_data_on_project_id", using: :btree
end
- create_table "project_mirror_data", force: :cascade do |t|
+ create_table "project_metrics_settings", primary_key: "project_id", id: :integer, default: nil, force: :cascade do |t|
+ t.string "external_dashboard_url", null: false
+ end
+
+ create_table "project_mirror_data", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.string "status"
t.string "jid"
@@ -1690,7 +1751,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["status"], name: "index_project_mirror_data_on_status", using: :btree
end
- create_table "project_repositories", id: :bigserial, force: :cascade do |t|
+ create_table "project_repositories", force: :cascade do |t|
t.integer "shard_id", null: false
t.string "disk_path", null: false
t.integer "project_id", null: false
@@ -1699,7 +1760,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["shard_id"], name: "index_project_repositories_on_shard_id", using: :btree
end
- create_table "project_statistics", force: :cascade do |t|
+ create_table "project_statistics", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.integer "namespace_id", null: false
t.bigint "commit_count", default: 0, null: false
@@ -1707,11 +1768,13 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.bigint "repository_size", default: 0, null: false
t.bigint "lfs_objects_size", default: 0, null: false
t.bigint "build_artifacts_size", default: 0, null: false
+ t.bigint "packages_size", default: 0, null: false
+ t.bigint "wiki_size"
t.index ["namespace_id"], name: "index_project_statistics_on_namespace_id", using: :btree
t.index ["project_id"], name: "index_project_statistics_on_project_id", unique: true, using: :btree
end
- create_table "projects", force: :cascade do |t|
+ create_table "projects", id: :serial, force: :cascade do |t|
t.string "name"
t.string "path"
t.text "description"
@@ -1729,7 +1792,6 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.string "import_type"
t.string "import_source"
t.text "import_error"
- t.integer "ci_id"
t.boolean "shared_runners_enabled", default: true, null: false
t.string "runners_token"
t.string "build_coverage_regex"
@@ -1768,7 +1830,6 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.string "bfg_object_map"
t.boolean "detected_repository_languages"
t.string "external_authorization_classification_label"
- t.index ["ci_id"], name: "index_projects_on_ci_id", using: :btree
t.index ["created_at"], name: "index_projects_on_created_at", using: :btree
t.index ["creator_id"], name: "index_projects_on_creator_id", using: :btree
t.index ["description"], name: "index_projects_on_description_trigram", using: :gin, opclasses: {"description"=>"gin_trgm_ops"}
@@ -1791,7 +1852,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["visibility_level"], name: "index_projects_on_visibility_level", using: :btree
end
- create_table "prometheus_metrics", force: :cascade do |t|
+ create_table "prometheus_metrics", id: :serial, force: :cascade do |t|
t.integer "project_id"
t.string "title", null: false
t.string "query", null: false
@@ -1809,7 +1870,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_prometheus_metrics_on_project_id", using: :btree
end
- create_table "protected_branch_merge_access_levels", force: :cascade do |t|
+ create_table "protected_branch_merge_access_levels", id: :serial, force: :cascade do |t|
t.integer "protected_branch_id", null: false
t.integer "access_level", default: 40, null: false
t.datetime "created_at", null: false
@@ -1817,7 +1878,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["protected_branch_id"], name: "index_protected_branch_merge_access", using: :btree
end
- create_table "protected_branch_push_access_levels", force: :cascade do |t|
+ create_table "protected_branch_push_access_levels", id: :serial, force: :cascade do |t|
t.integer "protected_branch_id", null: false
t.integer "access_level", default: 40, null: false
t.datetime "created_at", null: false
@@ -1825,7 +1886,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["protected_branch_id"], name: "index_protected_branch_push_access", using: :btree
end
- create_table "protected_branches", force: :cascade do |t|
+ create_table "protected_branches", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.string "name", null: false
t.datetime "created_at"
@@ -1833,7 +1894,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_protected_branches_on_project_id", using: :btree
end
- create_table "protected_tag_create_access_levels", force: :cascade do |t|
+ create_table "protected_tag_create_access_levels", id: :serial, force: :cascade do |t|
t.integer "protected_tag_id", null: false
t.integer "access_level", default: 40
t.integer "user_id"
@@ -1845,7 +1906,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_protected_tag_create_access_levels_on_user_id", using: :btree
end
- create_table "protected_tags", force: :cascade do |t|
+ create_table "protected_tags", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.string "name", null: false
t.datetime "created_at", null: false
@@ -1866,7 +1927,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["event_id"], name: "index_push_event_payloads_on_event_id", unique: true, using: :btree
end
- create_table "redirect_routes", force: :cascade do |t|
+ create_table "redirect_routes", id: :serial, force: :cascade do |t|
t.integer "source_id", null: false
t.string "source_type", null: false
t.string "path", null: false
@@ -1876,7 +1937,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["source_type", "source_id"], name: "index_redirect_routes_on_source_type_and_source_id", using: :btree
end
- create_table "release_links", id: :bigserial, force: :cascade do |t|
+ create_table "release_links", force: :cascade do |t|
t.integer "release_id", null: false
t.string "url", null: false
t.string "name", null: false
@@ -1886,7 +1947,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["release_id", "url"], name: "index_release_links_on_release_id_and_url", unique: true, using: :btree
end
- create_table "releases", force: :cascade do |t|
+ create_table "releases", id: :serial, force: :cascade do |t|
t.string "tag"
t.text "description"
t.integer "project_id"
@@ -1902,7 +1963,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id"], name: "index_releases_on_project_id", using: :btree
end
- create_table "remote_mirrors", force: :cascade do |t|
+ create_table "remote_mirrors", id: :serial, force: :cascade do |t|
t.integer "project_id"
t.string "url"
t.boolean "enabled", default: false
@@ -1930,7 +1991,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["project_id", "programming_language_id"], name: "index_repository_languages_on_project_and_languages_id", unique: true, using: :btree
end
- create_table "resource_label_events", id: :bigserial, force: :cascade do |t|
+ create_table "resource_label_events", force: :cascade do |t|
t.integer "action", null: false
t.integer "issue_id"
t.integer "merge_request_id"
@@ -1946,7 +2007,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_resource_label_events_on_user_id", using: :btree
end
- create_table "routes", force: :cascade do |t|
+ create_table "routes", id: :serial, force: :cascade do |t|
t.integer "source_id", null: false
t.string "source_type", null: false
t.string "path", null: false
@@ -1958,7 +2019,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["source_type", "source_id"], name: "index_routes_on_source_type_and_source_id", unique: true, using: :btree
end
- create_table "sent_notifications", force: :cascade do |t|
+ create_table "sent_notifications", id: :serial, force: :cascade do |t|
t.integer "project_id"
t.integer "noteable_id"
t.string "noteable_type"
@@ -1972,7 +2033,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["reply_key"], name: "index_sent_notifications_on_reply_key", unique: true, using: :btree
end
- create_table "services", force: :cascade do |t|
+ create_table "services", id: :serial, force: :cascade do |t|
t.string "type"
t.string "title"
t.integer "project_id"
@@ -1994,17 +2055,18 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.boolean "commit_events", default: true, null: false
t.boolean "job_events", default: false, null: false
t.boolean "confidential_note_events", default: true
+ t.boolean "deployment_events", default: false, null: false
t.index ["project_id"], name: "index_services_on_project_id", using: :btree
t.index ["template"], name: "index_services_on_template", using: :btree
t.index ["type"], name: "index_services_on_type", using: :btree
end
- create_table "shards", force: :cascade do |t|
+ create_table "shards", id: :serial, force: :cascade do |t|
t.string "name", null: false
t.index ["name"], name: "index_shards_on_name", unique: true, using: :btree
end
- create_table "snippets", force: :cascade do |t|
+ create_table "snippets", id: :serial, force: :cascade do |t|
t.string "title"
t.text "content"
t.integer "author_id", null: false
@@ -2027,7 +2089,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["visibility_level"], name: "index_snippets_on_visibility_level", using: :btree
end
- create_table "spam_logs", force: :cascade do |t|
+ create_table "spam_logs", id: :serial, force: :cascade do |t|
t.integer "user_id"
t.string "source_ip"
t.string "user_agent"
@@ -2041,7 +2103,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.boolean "recaptcha_verified", default: false, null: false
end
- create_table "subscriptions", force: :cascade do |t|
+ create_table "subscriptions", id: :serial, force: :cascade do |t|
t.integer "user_id"
t.integer "subscribable_id"
t.string "subscribable_type"
@@ -2053,7 +2115,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["subscribable_id", "subscribable_type", "user_id", "project_id"], name: "index_subscriptions_on_subscribable_and_user_id_and_project_id", unique: true, using: :btree
end
- create_table "suggestions", id: :bigserial, force: :cascade do |t|
+ create_table "suggestions", force: :cascade do |t|
t.integer "note_id", null: false
t.integer "relative_order", limit: 2, null: false
t.boolean "applied", default: false, null: false
@@ -2066,7 +2128,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["note_id", "relative_order"], name: "index_suggestions_on_note_id_and_relative_order", unique: true, using: :btree
end
- create_table "system_note_metadata", force: :cascade do |t|
+ create_table "system_note_metadata", id: :serial, force: :cascade do |t|
t.integer "note_id", null: false
t.integer "commit_count"
t.string "action"
@@ -2075,7 +2137,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["note_id"], name: "index_system_note_metadata_on_note_id", unique: true, using: :btree
end
- create_table "taggings", force: :cascade do |t|
+ create_table "taggings", id: :serial, force: :cascade do |t|
t.integer "tag_id"
t.integer "taggable_id"
t.string "taggable_type"
@@ -2089,14 +2151,14 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["taggable_id", "taggable_type"], name: "index_taggings_on_taggable_id_and_taggable_type", using: :btree
end
- create_table "tags", force: :cascade do |t|
+ create_table "tags", id: :serial, force: :cascade do |t|
t.string "name"
t.integer "taggings_count", default: 0
t.index ["name"], name: "index_tags_on_name", unique: true, using: :btree
t.index ["name"], name: "index_tags_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"}
end
- create_table "term_agreements", force: :cascade do |t|
+ create_table "term_agreements", id: :serial, force: :cascade do |t|
t.integer "term_id", null: false
t.integer "user_id", null: false
t.boolean "accepted", default: false, null: false
@@ -2107,7 +2169,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_term_agreements_on_user_id", using: :btree
end
- create_table "timelogs", force: :cascade do |t|
+ create_table "timelogs", id: :serial, force: :cascade do |t|
t.integer "time_spent", null: false
t.integer "user_id"
t.datetime "created_at", null: false
@@ -2120,7 +2182,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_timelogs_on_user_id", using: :btree
end
- create_table "todos", force: :cascade do |t|
+ create_table "todos", id: :serial, force: :cascade do |t|
t.integer "user_id", null: false
t.integer "project_id"
t.integer "target_id"
@@ -2144,12 +2206,12 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_todos_on_user_id", using: :btree
end
- create_table "trending_projects", force: :cascade do |t|
+ create_table "trending_projects", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.index ["project_id"], name: "index_trending_projects_on_project_id", unique: true, using: :btree
end
- create_table "u2f_registrations", force: :cascade do |t|
+ create_table "u2f_registrations", id: :serial, force: :cascade do |t|
t.text "certificate"
t.string "key_handle"
t.string "public_key"
@@ -2162,7 +2224,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_u2f_registrations_on_user_id", using: :btree
end
- create_table "uploads", force: :cascade do |t|
+ create_table "uploads", id: :serial, force: :cascade do |t|
t.bigint "size", null: false
t.string "path", limit: 511, null: false
t.string "checksum", limit: 64
@@ -2179,7 +2241,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["uploader", "path"], name: "index_uploads_on_uploader_and_path", using: :btree
end
- create_table "user_agent_details", force: :cascade do |t|
+ create_table "user_agent_details", id: :serial, force: :cascade do |t|
t.string "user_agent", null: false
t.string "ip_address", null: false
t.integer "subject_id", null: false
@@ -2190,14 +2252,14 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["subject_id", "subject_type"], name: "index_user_agent_details_on_subject_id_and_subject_type", using: :btree
end
- create_table "user_callouts", force: :cascade do |t|
+ create_table "user_callouts", id: :serial, force: :cascade do |t|
t.integer "feature_name", null: false
t.integer "user_id", null: false
t.index ["user_id", "feature_name"], name: "index_user_callouts_on_user_id_and_feature_name", unique: true, using: :btree
t.index ["user_id"], name: "index_user_callouts_on_user_id", using: :btree
end
- create_table "user_custom_attributes", force: :cascade do |t|
+ create_table "user_custom_attributes", id: :serial, force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.integer "user_id", null: false
@@ -2214,7 +2276,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_user_interacted_projects_on_user_id", using: :btree
end
- create_table "user_preferences", force: :cascade do |t|
+ create_table "user_preferences", id: :serial, force: :cascade do |t|
t.integer "user_id", null: false
t.integer "issue_notes_filter", limit: 2, default: 0, null: false
t.integer "merge_request_notes_filter", limit: 2, default: 0, null: false
@@ -2223,10 +2285,13 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.integer "first_day_of_week"
t.string "issues_sort"
t.string "merge_requests_sort"
+ t.string "timezone"
+ t.boolean "time_display_relative"
+ t.boolean "time_format_in_24h"
t.index ["user_id"], name: "index_user_preferences_on_user_id", unique: true, using: :btree
end
- create_table "user_statuses", primary_key: "user_id", force: :cascade do |t|
+ create_table "user_statuses", primary_key: "user_id", id: :serial, force: :cascade do |t|
t.integer "cached_markdown_version"
t.string "emoji", default: "speech_balloon", null: false
t.string "message", limit: 100
@@ -2234,7 +2299,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_user_statuses_on_user_id", using: :btree
end
- create_table "user_synced_attributes_metadata", force: :cascade do |t|
+ create_table "user_synced_attributes_metadata", id: :serial, force: :cascade do |t|
t.boolean "name_synced", default: false
t.boolean "email_synced", default: false
t.boolean "location_synced", default: false
@@ -2243,7 +2308,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id"], name: "index_user_synced_attributes_metadata_on_user_id", unique: true, using: :btree
end
- create_table "users", force: :cascade do |t|
+ create_table "users", id: :serial, force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
@@ -2323,13 +2388,14 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["incoming_email_token"], name: "index_users_on_incoming_email_token", using: :btree
t.index ["name"], name: "index_users_on_name", using: :btree
t.index ["name"], name: "index_users_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"}
+ t.index ["public_email"], name: "index_users_on_public_email", where: "((public_email)::text <> ''::text)", using: :btree
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
t.index ["state"], name: "index_users_on_state", using: :btree
t.index ["username"], name: "index_users_on_username", using: :btree
t.index ["username"], name: "index_users_on_username_trigram", using: :gin, opclasses: {"username"=>"gin_trgm_ops"}
end
- create_table "users_star_projects", force: :cascade do |t|
+ create_table "users_star_projects", id: :serial, force: :cascade do |t|
t.integer "project_id", null: false
t.integer "user_id", null: false
t.datetime "created_at"
@@ -2338,7 +2404,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["user_id", "project_id"], name: "index_users_star_projects_on_user_id_and_project_id", unique: true, using: :btree
end
- create_table "web_hook_logs", force: :cascade do |t|
+ create_table "web_hook_logs", id: :serial, force: :cascade do |t|
t.integer "web_hook_id", null: false
t.string "trigger"
t.string "url"
@@ -2355,7 +2421,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
t.index ["web_hook_id"], name: "index_web_hook_logs_on_web_hook_id", using: :btree
end
- create_table "web_hooks", force: :cascade do |t|
+ create_table "web_hooks", id: :serial, force: :cascade do |t|
t.integer "project_id"
t.datetime "created_at"
t.datetime "updated_at"
@@ -2488,6 +2554,8 @@ ActiveRecord::Schema.define(version: 20190326164045) do
add_foreign_key "members", "users", name: "fk_2e88fb7ce9", on_delete: :cascade
add_foreign_key "merge_request_assignees", "merge_requests", on_delete: :cascade
add_foreign_key "merge_request_assignees", "users", on_delete: :cascade
+ add_foreign_key "merge_request_blocks", "merge_requests", column: "blocked_merge_request_id", on_delete: :cascade
+ add_foreign_key "merge_request_blocks", "merge_requests", column: "blocking_merge_request_id", on_delete: :cascade
add_foreign_key "merge_request_diff_commits", "merge_request_diffs", on_delete: :cascade
add_foreign_key "merge_request_diff_files", "merge_request_diffs", on_delete: :cascade
add_foreign_key "merge_request_diffs", "merge_requests", name: "fk_8483f3258f", on_delete: :cascade
@@ -2506,12 +2574,17 @@ ActiveRecord::Schema.define(version: 20190326164045) do
add_foreign_key "merge_requests", "users", column: "updated_by_id", name: "fk_641731faff", on_delete: :nullify
add_foreign_key "merge_requests_closing_issues", "issues", on_delete: :cascade
add_foreign_key "merge_requests_closing_issues", "merge_requests", on_delete: :cascade
+ add_foreign_key "merge_trains", "ci_pipelines", column: "pipeline_id", on_delete: :nullify
+ add_foreign_key "merge_trains", "merge_requests", on_delete: :cascade
+ add_foreign_key "merge_trains", "projects", column: "target_project_id", on_delete: :cascade
+ add_foreign_key "merge_trains", "users", on_delete: :cascade
add_foreign_key "milestones", "namespaces", column: "group_id", name: "fk_95650a40d4", on_delete: :cascade
add_foreign_key "milestones", "projects", name: "fk_9bd0a0c791", on_delete: :cascade
add_foreign_key "note_diff_files", "notes", column: "diff_note_id", on_delete: :cascade
add_foreign_key "notes", "projects", name: "fk_99e097b079", on_delete: :cascade
add_foreign_key "notification_settings", "users", name: "fk_0c95e91db7", on_delete: :cascade
add_foreign_key "oauth_openid_requests", "oauth_access_grants", column: "access_grant_id", name: "fk_oauth_openid_requests_oauth_access_grants_access_grant_id"
+ add_foreign_key "pages_domain_acme_orders", "pages_domains", on_delete: :cascade
add_foreign_key "pages_domains", "projects", name: "fk_ea2f6dfc6f", on_delete: :cascade
add_foreign_key "personal_access_tokens", "users"
add_foreign_key "pool_repositories", "projects", column: "source_project_id", on_delete: :nullify
@@ -2528,6 +2601,7 @@ ActiveRecord::Schema.define(version: 20190326164045) do
add_foreign_key "project_features", "projects", name: "fk_18513d9b92", on_delete: :cascade
add_foreign_key "project_group_links", "projects", name: "fk_daa8cee94c", on_delete: :cascade
add_foreign_key "project_import_data", "projects", name: "fk_ffb9ee3a10", on_delete: :cascade
+ add_foreign_key "project_metrics_settings", "projects", on_delete: :cascade
add_foreign_key "project_mirror_data", "projects", on_delete: :cascade
add_foreign_key "project_repositories", "projects", on_delete: :cascade
add_foreign_key "project_repositories", "shards", on_delete: :restrict
diff --git a/doc/README.md b/doc/README.md
index 14a1eeffda0..3863e17c268 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -4,7 +4,7 @@ description: 'Learn how to use and administer GitLab, the most scalable Git-base
---
<div class="display-none">
- <em>Visit <a href="https://docs.gitlab.com/ce/">docs.gitlab.com</a> for optimized
+ <em>Visit <a href="https://docs.gitlab.com/ee/">docs.gitlab.com</a> for optimized
navigation, discoverability, and readability.</em>
</div>
<!-- the div above will not display on the docs site but will display on /help -->
@@ -107,13 +107,18 @@ The following documentation relates to the DevOps **Plan** stage:
| Plan Topics | Description |
|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------|
+| [Burndown Charts](user/project/milestones/burndown_charts.md) **[STARTER]** | Watch your project's progress throughout a specific milestone. |
| [Discussions](user/discussions/index.md) | Threads, comments, and resolvable discussions in issues, commits, and merge requests. |
| [Due Dates](user/project/issues/due_dates.md) | Keep track of issue deadlines. |
-| [Quick Actions](user/project/quick_actions.md) | Shortcuts for common actions on issues or merge requests, replacing the need to click buttons or use dropdowns in GitLab's UI. |
+| [Epics](user/group/epics/index.md) **[ULTIMATE]** | Tracking groups of issues that share a theme. |
| [Issues](user/project/issues/index.md), including [confidential issues](user/project/issues/confidential_issues.md),<br/>[issue and merge request templates](user/project/description_templates.md),<br/>and [moving issues](user/project/issues/moving_issues.md) | Project issues, restricting access to issues, create templates for submitting new issues and merge requests, and moving issues between projects. |
| [Labels](user/project/labels.md) | Categorize issues or merge requests with descriptive labels. |
| [Milestones](user/project/milestones/index.md) | Set milestones for delivery of issues and merge requests, with optional due date. |
| [Project Issue Board](user/project/issue_board.md) | Display issues on a Scrum or Kanban board. |
+| [Quick Actions](user/project/quick_actions.md) | Shortcuts for common actions on issues or merge requests, replacing the need to click buttons or use dropdowns in GitLab's UI. |
+| [Related Issues](user/project/issues/related_issues.md) **[STARTER]** | Create a relationship between issues. |
+| [Roadmap](user/group/roadmap/index.md) **[ULTIMATE]** | Visualize epic timelines. |
+| [Service Desk](user/project/service_desk.md) **[PREMIUM]** | A simple way to allow people to create issues in your GitLab instance without needing their own user account. |
| [Time Tracking](workflow/time_tracking.md) | Track time spent on issues and merge requests. |
| [Todos](workflow/todos.md) | Keep track of work requiring attention with a chronological list displayed on a simple dashboard. |
@@ -136,16 +141,21 @@ The following documentation relates to the DevOps **Create** stage:
#### Projects and Groups
-| Create Topics - Projects and Groups | Description |
-|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------|
-| [Create](gitlab-basics/create-project.md) and [fork](gitlab-basics/fork-project.md) projects, and<br/>[import and export<br/>projects between instances](user/project/settings/import_export.md) | Create, duplicate, and move projects. |
-| [GitLab Pages](user/project/pages/index.md) | Build, test, and deploy your static website with GitLab Pages. |
-| [Groups](user/group/index.md) and [Subgroups](user/group/subgroups/index.md) | Organize your projects in groups. |
-| [Projects](user/project/index.md), including [project access](public_access/public_access.md)<br/>and [settings](user/project/settings/index.md) | Host source code, and control your project's visibility and set configuration. |
-| [Search through GitLab](user/search/index.md) | Search for issues, merge requests, projects, groups, and todos. |
-| [Snippets](user/snippets.md) | Snippets allow you to create little bits of code. |
-| [Web IDE](user/project/web_ide/index.md) | Edit files within GitLab's user interface. |
-| [Wikis](user/project/wiki/index.md) | Enhance your repository documentation with built-in wikis. |
+| Create Topics - Projects and Groups | Description |
+|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------|
+| [Advanced global search](user/search/advanced_global_search.md) **[STARTER]** | Leverage Elasticsearch for faster, more advanced code search across your entire GitLab instance. |
+| [Advanced syntax search](user/search/advanced_search_syntax.md) **[STARTER]** | Use advanced queries for more targeted search results. |
+| [Contribution analytics](user/group/contribution_analytics/index.md) **[STARTER]** | See detailed statistics of group contributors. |
+| [Create](gitlab-basics/create-project.md) and [fork](gitlab-basics/fork-project.md) projects, and<br/>[import and export projects<br/>between instances](user/project/settings/import_export.md) | Create, duplicate, and move projects. |
+| [File locking](user/project/file_lock.md) **[PREMIUM]** | Lock files to avoid merge conflicts. |
+| [GitLab Pages](user/project/pages/index.md) | Build, test, and deploy your static website with GitLab Pages. |
+| [Groups](user/group/index.md) and [Subgroups](user/group/subgroups/index.md) | Organize your projects in groups. |
+| [Issues Analytics](user/group/issues_analytics/index.md) **[PREMIUM]** | Check how many issues were created per month. |
+| [Projects](user/project/index.md), including [project access](public_access/public_access.md)<br/>and [settings](user/project/settings/index.md) | Host source code, and control your project's visibility and set configuration. |
+| [Search through GitLab](user/search/index.md) | Search for issues, merge requests, projects, groups, and todos. |
+| [Snippets](user/snippets.md) | Snippets allow you to create little bits of code. |
+| [Web IDE](user/project/web_ide/index.md) | Edit files within GitLab's user interface. |
+| [Wikis](user/project/wiki/index.md) | Enhance your repository documentation with built-in wikis. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -165,7 +175,9 @@ The following documentation relates to the DevOps **Create** stage:
| [Files](user/project/repository/index.md#files) | Files management. |
| [Jupyter Notebook files](user/project/repository/index.md#jupyter-notebook-files) | GitLab's support for `.ipynb` files. |
| [Protected branches](user/project/protected_branches.md) | Use protected branches. |
+| [Push rules](push_rules/push_rules.md) **[STARTER]** | Additional control over pushes to your projects. |
| [Repositories](user/project/repository/index.md) | Manage source code repositories in GitLab's user interface. |
+| [Repository mirroring](workflow/repository_mirroring.md) **[STARTER]** | Push to or pull from repositories outside of GitLab |
| [Start a merge request](user/project/repository/web_editor.md#tips) | Start merge request when committing via GitLab's user interface. |
<div align="right">
@@ -192,13 +204,14 @@ The following documentation relates to the DevOps **Create** stage:
#### Integration and Automation
-| Create Topics - Integration and Automation | Description |
-|:------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------|
-| [GitLab API](api/README.md) | Integrate GitLab via a simple and powerful API. |
-| [GitLab Integration](integration/README.md) | Integrate with multiple third-party services with GitLab to allow external issue trackers and external authentication. |
-| [GitLab Webhooks](user/project/integrations/webhooks.md) | Let GitLab notify you when new code has been pushed to your project. |
-| [Project Services](user/project/integrations/project_services.md) | Integrate a project with external services, such as CI and chat. |
-| [Trello Power-Up](integration/trello_power_up.md) | Integrate with GitLab's Trello Power-Up. |
+| Create Topics - Integration and Automation | Description |
+|:------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------|
+| [GitLab API](api/README.md) | Integrate GitLab via a simple and powerful API. |
+| [GitLab Integration](integration/README.md) | Integrate with multiple third-party services with GitLab to allow external issue trackers and external authentication. |
+| [GitLab Webhooks](user/project/integrations/webhooks.md) | Let GitLab notify you when new code has been pushed to your project. |
+| [JIRA Development Panel](integration/jira_development_panel.md) **[PREMIUM]** | See GitLab information in the JIRA Development Panel. |
+| [Project Services](user/project/integrations/project_services.md) | Integrate a project with external services, such as CI and chat. |
+| [Trello Power-Up](integration/trello_power_up.md) | Integrate with GitLab's Trello Power-Up. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -218,12 +231,14 @@ scales to run your tests faster.
The following documentation relates to the DevOps **Verify** stage:
-| Verify Topics | Description |
-|:---------------------------------------------------|:-----------------------------------------------------------------------------|
-| [GitLab CI/CD](ci/README.md) | Explore the features and capabilities of Continuous Integration with GitLab. |
-| [JUnit test reports](ci/junit_test_reports.md) | Display JUnit test reports on merge requests. |
-| [Pipeline Graphs](ci/pipelines.md#visualizing-pipelines) | Visualize builds. |
-| [Review Apps](ci/review_apps/index.md) | Preview changes to your application right from a merge request. |
+| Verify Topics | Description |
+|:----------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------|
+| [Code Quality reports](user/project/merge_requests/code_quality.md) **[STARTER]** | Analyze source code quality. |
+| [GitLab CI/CD](ci/README.md) | Explore the features and capabilities of Continuous Integration with GitLab. |
+| [JUnit test reports](ci/junit_test_reports.md) | Display JUnit test reports on merge requests. |
+| [Multi-project pipelines](ci/multi_project_pipelines.md) **[PREMIUM]** | Visualize entire pipelines that span multiple projects, including all cross-project inter-dependencies. |
+| [Pipeline Graphs](ci/pipelines.md#visualizing-pipelines) | Visualize builds. |
+| [Review Apps](ci/review_apps/index.md) | Preview changes to your application right from a merge request. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -242,6 +257,7 @@ The following documentation relates to the DevOps **Package** stage:
| Package Topics | Description |
|:----------------------------------------------------------------|:-------------------------------------------------------|
| [GitLab Container Registry](user/project/container_registry.md) | Learn how to use GitLab's built-in Container Registry. |
+| [GitLab Packages](administration/packages.md) **[PREMIUM]** | Use GitLab as an NPM registry or Maven repository. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -257,14 +273,17 @@ confidently and securely with GitLab’s built-in Continuous Delivery and Deploy
The following documentation relates to the DevOps **Release** stage:
-| Release Topics | Description |
-|:------------------------------------------------------------|:---------------------------------------------------------------------------------------------|
-| [Auto Deploy](topics/autodevops/index.md#auto-deploy) | Configure GitLab for the deployment of your application. |
-| [Environments and deployments](ci/environments.md) | With environments, you can control the continuous deployment of your software within GitLab. |
-| [GitLab CI/CD](ci/README.md) | Explore the features and capabilities of Continuous Deployment and Delivery with GitLab. |
-| [GitLab Pages](user/project/pages/index.md) | Build, test, and deploy a static site directly from GitLab. |
-| [Protected Runners](ci/runners/README.md#protected-runners) | Select Runners to only pick jobs for protected branches and tags. |
-| [Scheduled Pipelines](user/project/pipelines/schedules.md) | Execute pipelines on a schedule. |
+| Release Topics | Description |
+|:------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------|
+| [Auto Deploy](topics/autodevops/index.md#auto-deploy) | Configure GitLab for the deployment of your application. |
+| [Canary Deployments](user/project/canary_deployments.md) **[PREMIUM]** | Employ a popular CI strategy where a small portion of the fleet is updated to the new version first. |
+| [Deploy Boards](user/project/deploy_boards.md) **[PREMIUM]** | View the current health and status of each CI environment running on Kubernetes, displaying the status of the pods in the deployment. |
+| [Environments and deployments](ci/environments.md) | With environments, you can control the continuous deployment of your software within GitLab. |
+| [Environment-specific variables](ci/variables/README.md#limiting-environment-scopes-of-environment-variables-premium) **[PREMIUM]** | Limit scope of variables to specific environments. |
+| [GitLab CI/CD](ci/README.md) | Explore the features and capabilities of Continuous Deployment and Delivery with GitLab. |
+| [GitLab Pages](user/project/pages/index.md) | Build, test, and deploy a static site directly from GitLab. |
+| [Protected Runners](ci/runners/README.md#protected-runners) | Select Runners to only pick jobs for protected branches and tags. |
+| [Scheduled Pipelines](user/project/pipelines/schedules.md) | Execute pipelines on a schedule. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -288,7 +307,8 @@ The following documentation relates to the DevOps **Configure** stage:
| [GitLab ChatOps](ci/chatops/README.md) | Interact with CI/CD jobs through chat services. |
| [Installing Applications](user/project/clusters/index.md#installing-applications) | Deploy Helm, Ingress, and Prometheus on Kubernetes. |
| [Mattermost slash commands](user/project/integrations/mattermost_slash_commands.md) | Enable and use slash commands from within Mattermost. |
-| [Protected variables](ci/variables/README.md#protected-environment-variables) | Restrict variables to protected branches and tags. |
+| [Multiple Kubernetes Clusters](user/project/clusters/index.md#multiple-kubernetes-clusters-premium) **[PREMIUM]** | Associate more than one Kubernetes clusters to your project. |
+| [Protected variables](ci/variables/README.md#protected-environment-variables) | Restrict variables to protected branches and tags. |
| [Serverless](user/project/clusters/serverless/index.md) | Run serverless workloads on Kubernetes. |
| [Slack slash commands](user/project/integrations/slack_slash_commands.md) | Enable and use slash commands from within Slack. |
@@ -323,16 +343,23 @@ The following documentation relates to the DevOps **Monitor** stage:
### Secure
-GitLab can help you secure your applications from within your development lifecycle.
+Check your application for security vulnerabilities that may lead to unauthorized access,
+data leaks, and denial of services. GitLab will perform static and dynamic tests on the
+code of your application, looking for known flaws and report them in the merge request
+so you can fix them before merging. Security teams can use dashboards to get a
+high-level view on projects and groups, and start remediation processes when needed.
The following documentation relates to the DevOps **Secure** stage:
-| Monitor Topics | Description |
-|:----------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------|
-| [Container Scanning example](ci/examples/container_scanning.md) | `.gitlab-ci.yml` example of using Clair and clair-scanner to scan docker images for known vulnerabilities. |
-
-NOTE: **Note:**
-Viewing [Container Scanning reports](https://docs.gitlab.com/ee/user/project/merge_requests/container_scanning.html) within merge requests requires [GitLab Ultimate](https://about.gitlab.com/pricing/).
+| Secure Topics | Description |
+|:------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------|
+| [Container Scanning](user/application_security/container_scanning/index.md) **[ULTIMATE]** | Use Clair to scan docker images for known vulnerabilities. |
+| [Dependency Scanning](user/application_security/dependency_scanning/index.md) **[ULTIMATE]** | Analyze your dependencies for known vulnerabilities. |
+| [Dynamic Application Security Testing (DAST)](user/application_security/dast/index.md) **[ULTIMATE]** | Analyze running web applications for known vulnerabilities. |
+| [Group Security Dashboard](user/application_security/security_dashboard/index.md) **[ULTIMATE]** | View vulnerabilities in all the projects in a group and its subgroups. |
+| [License Management](user/application_security/license_management/index.md) **[ULTIMATE]** | Search your project's dependencies for their licenses. |
+| [Project Security Dashboard](user/application_security/security_dashboard/index.md) **[ULTIMATE]** | View the latest security reports for your project. |
+| [Static Application Security Testing (SAST)](user/application_security/sast/index.md) **[ULTIMATE]** | Analyze source code for known vulnerabilities. |
## Subscribe to GitLab
@@ -342,6 +369,8 @@ There are two ways to use GitLab:
- [GitLab.com](#gitlabcom): GitLab's SaaS offering. You don't need to install anything to use GitLab.com,
you only need to [sign up](https://gitlab.com/users/sign_in) and start using GitLab straight away.
+For more information on managing your subscription and [Customers Portal](https://customers.gitlab.com) account, please see [Getting Started with Subscriptions](getting-started/subscription.md).
+
The following sections outline tiers and features within GitLab self-managed and GitLab.com.
<div align="right">
@@ -393,6 +422,12 @@ GitLab.com subscriptions grant access
to the same features available in GitLab self-managed, **except
[administration](administration/index.md) tools and settings**.
+GitLab.com allows you to apply your subscription to a group or your personal user.
+
+When applied to a **group**, the group, all subgroups, and all projects under the selected group on GitLab.com will have the features of the associated plan. It is recommended to go with a group plan when managing projects and users of an organization.
+
+When associated with a **personal userspace** instead, all projects will have features with the subscription applied, but as it is not a group, group features will not be available.
+
TIP: **Tip:**
To support the open source community and encourage the development of open source projects, GitLab grants access to **Gold** features for all GitLab.com **public** projects, regardless of the subscription.
@@ -418,7 +453,7 @@ We have the following documentation to rapidly uplift your GitLab knowledge:
| Topic | Description |
|:-----------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------|
-| [GitLab Basics](gitlab-basics/README.md) | Start working on the command line and with GitLab. |
+| [GitLab basics guides](gitlab-basics/README.md) | Start working on the command line and with GitLab. |
| [GitLab Workflow](workflow/README.md) and [overview](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/) | Enhance your workflow with the best of GitLab Workflow. |
| [Get started with GitLab CI/CD](ci/quick_start/README.md) | Quickly implement GitLab CI/CD. |
| [Auto DevOps](topics/autodevops/index.md) | Learn more about GitLab's Auto DevOps. |
diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md
new file mode 100644
index 00000000000..d7a2e13b53e
--- /dev/null
+++ b/doc/administration/audit_events.md
@@ -0,0 +1,116 @@
+---
+last_updated: 2019-02-04
+---
+
+# Audit Events **[STARTER]**
+
+GitLab offers a way to view the changes made within the GitLab server for owners and administrators on a [paid plan][ee].
+
+GitLab system administrators can also take advantage of the logs located on the
+filesystem, see [the logs system documentation](logs.md) for more details.
+
+## Overview
+
+**Audit Events** is a tool for GitLab owners and administrators to be
+able to track important events such as who performed certain actions and the
+time they happened. These actions could be, for example, change a user
+permission level, who added a new user, or who removed a user.
+
+## Use-cases
+
+- Check who was the person who changed the permission level of a particular
+ user for a project in GitLab.
+- Use it to track which users have access to a certain group of projects
+ in GitLab, and who gave them that permission level.
+
+## List of events
+
+There are two kinds of events logged:
+
+- Events scoped to the group or project, used by group / project managers
+ to look up who made what change.
+- Instance events scoped to the whole GitLab instance, used by your Compliance team to
+ perform formal audits.
+
+### Group events **[STARTER]**
+
+NOTE: **Note:**
+You need Owner [permissions] to view the group Audit Events page.
+
+To view a group's audit events, navigate to **Group > Settings > Audit Events**.
+From there, you can see the following actions:
+
+- Group name/path changed
+- Group repository size limit changed
+- Group created/deleted
+- Group changed visibility
+- User was added to group and with which [permissions]
+- Permissions changes of a user assigned to a group
+- Removed user from group
+- Project added to group and with which visibility level
+- Project removed from group
+- [Project shared with group](../user/project/members/share_project_with_groups.md)
+ and with which [permissions]
+- Removal of a previously shared group with a project
+- LFS enabled/disabled
+- Shared runners minutes limit changed
+- Membership lock enabled/disabled
+- Request access enabled/disabled
+- 2FA enforcement/grace period changed
+- Roles allowed to create project changed
+
+### Project events **[STARTER]**
+
+NOTE: **Note:**
+You need Maintainer [permissions] or higher to view the project Audit Events page.
+
+To view a project's audit events, navigate to **Project > Settings > Audit Events**.
+From there, you can see the following actions:
+
+- Added/removed deploy keys
+- Project created/deleted/renamed/moved(transferred)/changed path
+- Project changed visibility level
+- User was added to project and with which [permissions]
+- Permission changes of a user assigned to a project
+- User was removed from project
+
+### Instance events **[PREMIUM ONLY]**
+
+> [Introduced][ee-2336] in [GitLab Premium][ee] 9.3.
+
+Server-wide audit logging introduces the ability to observe user actions across
+the entire instance of your GitLab server, making it easy to understand who
+changed what and when for audit purposes.
+
+To view the server-wide admin log, visit **Admin Area > Monitoring > Audit Log**.
+
+In addition to the group and project events, the following user actions are also
+recorded:
+
+- Failed Logins
+- Sign-in events and the authentication type (standard, LDAP, OmniAuth, etc.)
+- Added SSH key
+- Added/removed email
+- Changed password
+- Ask for password reset
+- Grant OAuth access
+
+It is possible to filter particular actions by choosing an audit data type from
+the filter drop-down. You can further filter by specific group, project or user
+(for authentication events).
+
+![audit log](audit_log.png)
+
+### Missing events
+
+Some events are not being tracked in Audit Events. Please see the following
+epics for more detail on which events are not being tracked and our progress
+on adding these events into GitLab:
+
+- [Project settings and activity](https://gitlab.com/groups/gitlab-org/-/epics/474)
+- [Group settings and activity](https://gitlab.com/groups/gitlab-org/-/epics/475)
+- [Instance-level settings and activity](https://gitlab.com/groups/gitlab-org/-/epics/476)
+
+[ee-2336]: https://gitlab.com/gitlab-org/gitlab-ee/issues/2336
+[ee]: https://about.gitlab.com/pricing/
+[permissions]: ../user/permissions.md
diff --git a/doc/administration/audit_log.png b/doc/administration/audit_log.png
new file mode 100644
index 00000000000..d4f4c2abf38
--- /dev/null
+++ b/doc/administration/audit_log.png
Binary files differ
diff --git a/doc/administration/auditor_access_form.png b/doc/administration/auditor_access_form.png
new file mode 100644
index 00000000000..c179a7d3b0a
--- /dev/null
+++ b/doc/administration/auditor_access_form.png
Binary files differ
diff --git a/doc/administration/auditor_users.md b/doc/administration/auditor_users.md
new file mode 100644
index 00000000000..ef8c8197d6d
--- /dev/null
+++ b/doc/administration/auditor_users.md
@@ -0,0 +1,88 @@
+# Auditor users **[PREMIUM ONLY]**
+
+>[Introduced][ee-998] in [GitLab Premium][eep] 8.17.
+
+Auditor users are given read-only access to all projects, groups, and other
+resources on the GitLab instance.
+
+## Overview
+
+Auditor users can have full access to their own resources (projects, groups,
+snippets, etc.), and read-only access to **all** other resources, except the
+Admin area. To put another way, they are just regular users (who can be added
+to projects, create personal snippets, create milestones on their groups, etc.)
+who also happen to have read-only access to all projects on the system that
+they haven't been explicitly [given access][permissions] to.
+
+The Auditor role is _not_ a read-only version of the Admin role. Auditor users
+will not be able to access the project/group settings pages, or the Admin Area.
+
+To sum up, assuming you have logged-in as an Auditor user:
+
+- For a project the Auditor is not member of, the Auditor should have
+ read-only access. If the project is public or internal, they would have the
+ same access as the users that are not members of that project/group.
+- For a project the Auditor owns, the Auditor should have full access to
+ everything.
+- For a project the Auditor has been added to as a member, the Auditor should
+ have the same access as the [permissions] they were given to. For example, if
+ they were added as a Developer, they could then push commits or comment on
+ issues.
+- The Auditor cannot view the Admin area, or perform any admin actions.
+
+For more information about what an Auditor can or can't do, see the
+[Permissions and restrictions of an Auditor user](#permissions-and-restrictions-of-an-auditor-user)
+section.
+
+## Use cases
+
+1. Your compliance department wants to run tests against the entire GitLab base
+ to ensure users are complying with password, credit card, and other sensitive
+ data policies. With Auditor users, this can be achieved very easily without
+ resulting to tactics like giving a user admin rights or having to use the API
+ to add them to all projects.
+1. If particular users need visibility or access to most of all projects in
+ your GitLab instance, instead of manually adding the user to all projects,
+ you can simply create an Auditor user and share the credentials with those
+ that you want to grant access to.
+
+## Adding an Auditor user
+
+1. Create a new user or edit an existing one by navigating to
+ **Admin Area > Users**. You will find the option of the access level under
+ the 'Access' section.
+
+ ![Admin Area Form](auditor_access_form.png)
+
+1. Click **Save changes** or **Create user** for the changes to take effect.
+
+To revoke the Auditor permissions from a user, simply make them a Regular user
+following the same steps as above.
+
+## Permissions and restrictions of an Auditor user
+
+An Auditor user should be able to access all projects and groups of a GitLab
+instance, with the following permissions/restrictions:
+
+- Has read-only access to the API
+- Can access projects that are:
+ - Private
+ - Public
+ - Internal
+- Can read all files in a repository
+- Can read issues / MRs
+- Can read project snippets
+- Cannot be Admin and Auditor at the same time
+- Cannot access the Admin area
+- In a group / project they're not a member of:
+ - Cannot access project settings
+ - Cannot access group settings
+ - Cannot commit to repository
+ - Cannot create / comment on issues / MRs
+ - Cannot create/modify files from the Web UI
+ - Cannot merge a merge request
+ - Cannot create project snippets
+
+[ee-998]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/998
+[eep]: https://about.gitlab.com/pricing/
+[permissions]: ../user/permissions.md
diff --git a/doc/administration/auth/README.md b/doc/administration/auth/README.md
index 54be7b616cc..e215a0df6ec 100644
--- a/doc/administration/auth/README.md
+++ b/doc/administration/auth/README.md
@@ -9,9 +9,11 @@ providers.
- [LDAP](ldap.md) Includes Active Directory, Apple Open Directory, Open LDAP,
and 389 Server
+ - [LDAP for GitLab EE](ldap-ee.md): LDAP additions to GitLab Enterprise Editions **[STARTER ONLY]**
- [OmniAuth](../../integration/omniauth.md) Sign in via Twitter, GitHub, GitLab.com, Google,
Bitbucket, Facebook, Shibboleth, Crowd, Azure, Authentiq ID, and JWT
- [CAS](../../integration/cas.md) Configure GitLab to sign in using CAS
- [SAML](../../integration/saml.md) Configure GitLab as a SAML 2.0 Service Provider
- [Okta](okta.md) Configure GitLab to sign in using Okta
- [Authentiq](authentiq.md): Enable the Authentiq OmniAuth provider for passwordless authentication
+- [Smartcard](smartcard.md) Smartcard authentication **[PREMIUM ONLY]**
diff --git a/doc/administration/auth/google_secure_ldap.md b/doc/administration/auth/google_secure_ldap.md
index 65a51fc4aa0..760af0cfd1a 100644
--- a/doc/administration/auth/google_secure_ldap.md
+++ b/doc/administration/auth/google_secure_ldap.md
@@ -27,7 +27,7 @@ The steps below cover:
'Entire domain (GitLab)' or 'Selected organizational units' for both 'Verify user
credentials' and 'Read user information'. Select 'Add LDAP Client'
- TIP: **Tip:** If you plan to use GitLab [LDAP Group Sync](https://docs.gitlab.com/ee/administration/auth/ldap-ee.html#group-sync)
+ TIP: **Tip:** If you plan to use GitLab [LDAP Group Sync](ldap-ee.md#group-sync)
, turn on 'Read group information'.
![Add LDAP Client Step 2](img/google_secure_ldap_add_step_2.png)
diff --git a/doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md b/doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md
index 8d81b32e721..1f67e8f5744 100644
--- a/doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md
+++ b/doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md
@@ -14,7 +14,7 @@ Managing a large number of users in GitLab can become a burden for system admini
In this guide we will focus on configuring GitLab with Active Directory. [Active Directory](https://en.wikipedia.org/wiki/Active_Directory) is a popular LDAP compatible directory service provided by Microsoft, included in all modern Windows Server operating systems.
-GitLab has supported LDAP integration since [version 2.2](https://about.gitlab.com/2012/02/22/gitlab-version-2-2/). With GitLab LDAP [group syncing](https://docs.gitlab.com/ee/administration/auth/how_to_configure_ldap_gitlab_ee/index.html#group-sync) being added to GitLab Enterprise Edition in [version 6.0](https://about.gitlab.com/2013/08/20/gitlab-6-dot-0-released/). LDAP integration has become one of the most popular features in GitLab.
+GitLab has supported LDAP integration since [version 2.2](https://about.gitlab.com/2012/02/22/gitlab-version-2-2/). With GitLab LDAP [group syncing](../how_to_configure_ldap_gitlab_ee/index.html#group-sync) being added to GitLab Enterprise Edition in [version 6.0](https://about.gitlab.com/2013/08/20/gitlab-6-dot-0-released/). LDAP integration has become one of the most popular features in GitLab.
## Getting started
@@ -111,7 +111,7 @@ The initial configuration of LDAP in GitLab requires changes to the `gitlab.rb`
The two Active Directory specific values are `active_directory: true` and `uid: 'sAMAccountName'`. `sAMAccountName` is an attribute returned by Active Directory used for GitLab usernames. See the example output from `ldapsearch` for a full list of attributes a "person" object (user) has in **AD** - [`ldapsearch` example](#using-ldapsearch-unix)
-> Both group_base and admin_group configuration options are only available in GitLab Enterprise Edition. See [GitLab EE - LDAP Features](https://docs.gitlab.com/ee/administration/auth/how_to_configure_ldap_gitlab_ee/index.html#gitlab-enterprise-edition---ldap-features)
+> Both group_base and admin_group configuration options are only available in GitLab Enterprise Edition. See [GitLab EE - LDAP Features](../how_to_configure_ldap_gitlab_ee/index.html#gitlab-enterprise-edition---ldap-features) **[STARTER ONLY]**
### Example `gitlab.rb` LDAP
@@ -267,4 +267,4 @@ have extended functionalities with LDAP, such as:
- Updating user permissions
- Multiple LDAP servers
-Read through the article on [LDAP for GitLab EE](https://docs.gitlab.com/ee/administration/auth/how_to_configure_ldap_gitlab_ee/) for an overview.
+Read through the article on [LDAP for GitLab EE](../how_to_configure_ldap_gitlab_ee/index.md) **[STARTER ONLY]** for an overview.
diff --git a/doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/admin_group.png b/doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/admin_group.png
new file mode 100644
index 00000000000..9896379d669
--- /dev/null
+++ b/doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/admin_group.png
Binary files differ
diff --git a/doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/group_link_final.png b/doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/group_link_final.png
new file mode 100644
index 00000000000..21fb5a7d0ce
--- /dev/null
+++ b/doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/group_link_final.png
Binary files differ
diff --git a/doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/group_linking.gif b/doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/group_linking.gif
new file mode 100644
index 00000000000..d35cf55804f
--- /dev/null
+++ b/doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/group_linking.gif
Binary files differ
diff --git a/doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/manual_permissions.gif b/doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/manual_permissions.gif
new file mode 100644
index 00000000000..29b28df1cbd
--- /dev/null
+++ b/doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/manual_permissions.gif
Binary files differ
diff --git a/doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/multi_login.gif b/doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/multi_login.gif
new file mode 100644
index 00000000000..d317add9837
--- /dev/null
+++ b/doc/administration/auth/how_to_configure_ldap_gitlab_ee/img/multi_login.gif
Binary files differ
diff --git a/doc/administration/auth/how_to_configure_ldap_gitlab_ee/index.md b/doc/administration/auth/how_to_configure_ldap_gitlab_ee/index.md
new file mode 100644
index 00000000000..4d82a7370bb
--- /dev/null
+++ b/doc/administration/auth/how_to_configure_ldap_gitlab_ee/index.md
@@ -0,0 +1,119 @@
+---
+author: Chris Wilson
+author_gitlab: MrChrisW
+level: intermediary
+article_type: admin guide
+date: 2017-05-03
+---
+
+# How to configure LDAP with GitLab EE **[STARTER ONLY]**
+
+## Introduction
+
+The present article follows [How to Configure LDAP with GitLab CE](../how_to_configure_ldap_gitlab_ce/index.md). Make sure to read through it before moving forward.
+
+## GitLab Enterprise Edition - LDAP features
+
+[GitLab Enterprise Edition (EE)](https://about.gitlab.com/pricing/) has a number of advantages when it comes to integrating with Active Directory (LDAP):
+
+- [Administrator Sync](../ldap-ee.md#administrator-sync): As an extension of group sync, you can automatically manage your global GitLab administrators. Specify a group CN for `admin_group` and all members of the LDAP group will be given administrator privileges.
+- [Group Sync](#group-sync): This allows GitLab group membership to be automatically updated based on LDAP group members.
+- [Multiple LDAP servers](#multiple-ldap-servers): The ability to configure multiple LDAP servers. This is useful if an organization has different LDAP servers within departments. This is not designed for failover. We're working on [supporting LDAP failover](https://gitlab.com/gitlab-org/gitlab-ee/issues/139) in GitLab.
+
+- Daily user synchronization: Once a day, GitLab will run a synchronization to check and update GitLab users against LDAP. This process updates all user details automatically.
+
+On the following section, you'll find a description for each of these features. Read through [LDAP GitLab EE docs](../ldap-ee.md) for complementary information.
+
+![GitLab OU Structure](img/admin_group.png)
+
+All members of the group `Global Admins` will be given **administrator** access to GitLab, allowing them to view the `/admin` dashboard.
+
+### Group Sync
+
+Group syncing allows AD (LDAP) groups to be mapped to GitLab groups. This provides more control over per-group user management. To configure group syncing edit the `group_base` **DN** (`'OU=Global Groups,OU=GitLab INT,DC=GitLab,DC=org'`). This **OU** contains all groups that will be associated with [GitLab groups](../../../user/group/index.md).
+
+#### Creating group links - example
+
+As an example, let's suppose we have a "UKGov" GitLab group, which deals with confidential government information. Therefore, it is important that users of this group are given the correct permissions to projects contained within the group. Granular group permissions can be applied based on the AD group.
+
+**UK Developers** of our "UKGov" group are given **"developer"** permissions.
+
+_The developer permission allows the development staff to effectively manage all project code, issues, and merge requests._
+
+**UK Support** staff of our "UKGov" group are given **"reporter"** permissions.
+
+_The reporter permission allows support staff to manage issues, labels, and review project code._
+
+**US People Ops** of our "UKGov" group are given **"guest"** permissions.
+
+![Creating group links](img/group_linking.gif)
+
+> Guest permissions allows people ops staff to review and lodge new issues while allowing no read or write access to project code or [confidential issues](../../../user/project/issues/confidential_issues.md#permissions-and-access-to-confidential-issues) created by other users.
+
+See the [permission list](../../../user/permissions.md) for complementary info.
+
+#### Group permissions - example
+
+Considering the previous example, our staff will have
+access to our GitLab instance with the following structure:
+
+![GitLab OU Structure](img/group_link_final.png)
+
+Using this permission structure in our example allows only UK staff access to sensitive information stored in the projects code, while still allowing other teams to work effectively. As all permissions are controlled via AD groups new users can be quickly added to existing groups. New group members will then automatically inherit the required permissions.
+
+> [More information](../ldap-ee.md#group-sync) on group syncing.
+
+### Updating user permissions - new feature
+
+Since GitLab [v8.15](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/822) LDAP user permissions can now be manually overridden by an admin user. To override a user's permissions visit the groups **Members** page and select **Edit permissions**.
+
+![Setting manual permissions](img/manual_permissions.gif)
+
+### Multiple LDAP servers
+
+GitLab EE can support multiple LDAP servers. Simply configure another server in the `gitlab.rb` file within the `ldap_servers` block. In the example below we configure a new secondary server with the label **GitLab Secondary AD**. This is shown on the GitLab login screen. Large enterprises often utilize multiple LDAP servers for segregating organizational departments.
+
+![Multiple LDAP Servers Login](img/multi_login.gif)
+
+Considering the example illustrated on the image above,
+our `gitlab.rb` configuration would look like:
+
+```ruby
+gitlab_rails['ldap_enabled'] = true
+gitlab_rails['ldap_servers'] = {
+'main' => {
+ 'label' => 'GitLab AD',
+ 'host' => 'ad.example.org',
+ 'port' => 636,
+ 'uid' => 'sAMAccountName',
+ 'method' => 'ssl',
+ 'bind_dn' => 'CN=GitLabSRV,CN=Users,DC=GitLab,DC=org',
+ 'password' => 'Password1',
+ 'active_directory' => true,
+ 'base' => 'OU=GitLab INT,DC=GitLab,DC=org',
+ 'group_base' => 'OU=Global Groups,OU=GitLab INT,DC=GitLab,DC=org',
+ 'admin_group' => 'Global Admins'
+ },
+
+'secondary' => {
+ 'label' => 'GitLab Secondary AD',
+ 'host' => 'ad-secondary.example.net',
+ 'port' => 636,
+ 'uid' => 'sAMAccountName',
+ 'method' => 'ssl',
+ 'bind_dn' => 'CN=GitLabSRV,CN=Users,DC=GitLab,DC=com',
+ 'password' => 'Password1',
+ 'active_directory' => true,
+ 'base' => 'OU=GitLab Secondary,DC=GitLab,DC=com',
+ 'group_base' => 'OU=Global Groups,OU=GitLab INT,DC=GitLab,DC=com',
+ 'admin_group' => 'Global Admins'
+ }
+}
+```
+
+## Conclusion
+
+Integration of GitLab with Active Directory (LDAP) reduces the complexity of user management.
+It has the advantage of improving user permission controls, whilst easing the deployment of GitLab into an existing [IT environment](https://www.techopedia.com/definition/29199/it-infrastructure). GitLab EE offers advanced group management and multiple LDAP servers.
+
+With the assistance of the [GitLab Support](https://about.gitlab.com/support) team, setting up GitLab with an existing AD/LDAP solution will be a smooth and painless process.
diff --git a/doc/administration/auth/ldap-ee.md b/doc/administration/auth/ldap-ee.md
new file mode 100644
index 00000000000..30095d35705
--- /dev/null
+++ b/doc/administration/auth/ldap-ee.md
@@ -0,0 +1,557 @@
+# LDAP Additions in GitLab EE **[STARTER ONLY]**
+
+This is a continuation of the main [LDAP documentation](ldap.md), detailing LDAP
+features specific to GitLab Enterprise Edition Starter, Premium and Ultimate.
+
+## Overview
+
+[LDAP](https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol)
+stands for **Lightweight Directory Access Protocol**, which
+is a standard application protocol for
+accessing and maintaining distributed directory information services
+over an Internet Protocol (IP) network.
+
+GitLab integrates with LDAP to support **user authentication**. This integration
+works with most LDAP-compliant directory servers, including Microsoft Active
+Directory, Apple Open Directory, Open LDAP, and 389 Server.
+**GitLab Enterprise Edition** includes enhanced integration, including group
+membership syncing.
+
+## Use cases
+
+- User sync: Once a day, GitLab will update users against LDAP
+- Group sync: Once an hour, GitLab will update group membership
+ based on LDAP group members
+
+## Multiple LDAP servers
+
+With GitLab Enterprise Edition Starter, you can configure multiple LDAP servers
+that your GitLab instance will connect to.
+
+To add another LDAP server, you can start by duplicating the settings under
+[the main configuration](ldap.md#configuration) and edit them to match the
+additional LDAP server.
+
+Be sure to choose a different provider ID made of letters a-z and numbers 0-9.
+This ID will be stored in the database so that GitLab can remember which LDAP
+server a user belongs to.
+
+## User sync
+
+Once per day, GitLab will run a worker to check and update GitLab
+users against LDAP.
+
+The process will execute the following access checks:
+
+1. Ensure the user is still present in LDAP
+1. If the LDAP server is Active Directory, ensure the user is active (not
+ blocked/disabled state). This will only be checked if
+ `active_directory: true` is set in the LDAP configuration [^1]
+
+The user will be set to `ldap_blocked` state in GitLab if the above conditions
+fail. This means the user will not be able to login or push/pull code.
+
+The process will also update the following user information:
+
+1. Email address
+1. If `sync_ssh_keys` is set, SSH public keys
+1. If Kerberos is enabled, Kerberos identity
+
+NOTE: **Note:**
+The LDAP sync process updates existing users while new users will
+be created on first sign in.
+
+## Group Sync
+
+If your LDAP supports the `memberof` property, when the user signs in for the
+first time GitLab will trigger a sync for groups the user should be a member of.
+That way they don't need to wait for the hourly sync to be granted
+access to their groups and projects.
+
+In GitLab Premium, we can also add a GitLab group to sync with one or multiple LDAP groups or we can
+also add a filter. The filter must comply with the syntax defined in [RFC 2254](https://tools.ietf.org/search/rfc2254).
+
+A group sync process will run every hour on the hour, and `group_base` must be set
+in LDAP configuration for LDAP synchronizations based on group CN to work. This allows
+GitLab group membership to be automatically updated based on LDAP group members.
+
+The `group_base` configuration should be a base LDAP 'container', such as an
+'organization' or 'organizational unit', that contains LDAP groups that should
+be available to GitLab. For example, `group_base` could be
+`ou=groups,dc=example,dc=com`. In the config file it will look like the
+following.
+
+**Omnibus configuration**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['ldap_servers'] = YAML.load <<-EOS
+ main:
+ ## snip...
+ ##
+ ## Base where we can search for groups
+ ##
+ ## Ex. ou=groups,dc=gitlab,dc=example
+ ##
+ ##
+ group_base: ou=groups,dc=example,dc=com
+ EOS
+ ```
+
+1. [Reconfigure GitLab][reconfigure] for the changes to take effect.
+
+**Source configuration**
+
+1. Edit `/home/git/gitlab/config/gitlab.yml`:
+
+ ```yaml
+ production:
+ ldap:
+ servers:
+ main:
+ # snip...
+ group_base: ou=groups,dc=example,dc=com
+ ```
+
+1. [Restart GitLab][restart] for the changes to take effect.
+
+---
+
+To take advantage of group sync, group owners or maintainers will need to create an
+LDAP group link in their group **Settings > LDAP Groups** page. Multiple LDAP
+groups and/or filters can be linked with a single GitLab group. When the link is
+created, an access level/role is specified (Guest, Reporter, Developer, Maintainer,
+or Owner).
+
+## Administrator sync
+
+As an extension of group sync, you can automatically manage your global GitLab
+administrators. Specify a group CN for `admin_group` and all members of the
+LDAP group will be given administrator privileges. The configuration will look
+like the following.
+
+NOTE: **Note:**
+Administrators will not be synced unless `group_base` is also
+specified alongside `admin_group`. Also, only specify the CN of the admin
+group, as opposed to the full DN.
+
+**Omnibus configuration**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['ldap_servers'] = YAML.load <<-EOS
+ main:
+ ## snip...
+ ##
+ ## Base where we can search for groups
+ ##
+ ## Ex. ou=groups,dc=gitlab,dc=example
+ ##
+ ##
+ group_base: ou=groups,dc=example,dc=com
+
+ ##
+ ## The CN of a group containing GitLab administrators
+ ##
+ ## Ex. administrators
+ ##
+ ## Note: Not `cn=administrators` or the full DN
+ ##
+ ##
+ admin_group: my_admin_group
+
+ EOS
+ ```
+
+1. [Reconfigure GitLab][reconfigure] for the changes to take effect.
+
+**Source configuration**
+
+1. Edit `/home/git/gitlab/config/gitlab.yml`:
+
+ ```yaml
+ production:
+ ldap:
+ servers:
+ main:
+ # snip...
+ group_base: ou=groups,dc=example,dc=com
+ admin_group: my_admin_group
+ ```
+
+1. [Restart GitLab][restart] for the changes to take effect.
+
+## Adjusting LDAP user sync schedule
+
+> Introduced in GitLab Enterprise Edition Starter.
+
+NOTE: **Note:**
+These are cron formatted values. You can use a crontab generator to create
+these values, for example http://www.crontabgenerator.com/.
+
+By default, GitLab will run a worker once per day at 01:30 a.m. server time to
+check and update GitLab users against LDAP.
+
+You can manually configure LDAP user sync times by setting the
+following configuration values. The example below shows how to set LDAP user
+sync to run once every 12 hours at the top of the hour.
+
+**Omnibus installations**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['ldap_sync_worker_cron'] = "0 */12 * * *"
+ ```
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
+**Source installations**
+
+1. Edit `config/gitlab.yaml`:
+
+ ```yaml
+ cron_jobs:
+ ldap_sync_worker_cron:
+ "0 */12 * * *"
+ ```
+
+1. [Restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
+
+## Adjusting LDAP group sync schedule
+
+NOTE: **Note:**
+These are cron formatted values. You can use a crontab generator to create
+these values, for example http://www.crontabgenerator.com/.
+
+By default, GitLab will run a group sync process every hour, on the hour.
+
+CAUTION: **Important:**
+It's recommended that you do not run too short intervals as this
+could lead to multiple syncs running concurrently. This is primarily a concern
+for installations with a large number of LDAP users. Please review the
+[LDAP group sync benchmark metrics](#benchmarks) to see how
+your installation compares before proceeding.
+
+You can manually configure LDAP group sync times by setting the
+following configuration values. The example below shows how to set group
+sync to run once every 2 hours at the top of the hour.
+
+**Omnibus installations**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['ldap_group_sync_worker_cron'] = "0 */2 * * * *"
+ ```
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
+**Source installations**
+
+1. Edit `config/gitlab.yaml`:
+
+ ```yaml
+ cron_jobs:
+ ldap_group_sync_worker_cron:
+ "*/30 * * * *"
+ ```
+
+1. [Restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
+
+## External groups
+
+> Introduced in GitLab Enterprise Edition Starter 8.9.
+
+Using the `external_groups` setting will allow you to mark all users belonging
+to these groups as [external users](../../user/permissions.md#external-users-permissions).
+Group membership is checked periodically through the `LdapGroupSync` background
+task.
+
+**Omnibus configuration**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['ldap_servers'] = YAML.load <<-EOS
+ main:
+ ## snip...
+ ##
+ ## An array of CNs of groups containing users that should be considered external
+ ##
+ ## Ex. ['interns', 'contractors']
+ ##
+ ## Note: Not `cn=interns` or the full DN
+ ##
+ external_groups: ['interns', 'contractors']
+ EOS
+ ```
+
+1. [Reconfigure GitLab][reconfigure] for the changes to take effect.
+
+**Source configuration**
+
+1. Edit `config/gitlab.yaml`:
+
+ ```yaml
+ production:
+ ldap:
+ servers:
+ main:
+ # snip...
+ external_groups: ['interns', 'contractors']
+ ```
+
+1. [Restart GitLab][restart] for the changes to take effect.
+
+## Group sync technical details
+
+There is a lot going on with group sync 'under the hood'. This section
+outlines what LDAP queries are executed and what behavior you can expect
+from group sync.
+
+Group member access will be downgraded from a higher level if their LDAP group
+membership changes. For example, if a user has 'Owner' rights in a group and the
+next group sync reveals they should only have 'Developer' privileges, their
+access will be adjusted accordingly. The only exception is if the user is the
+*last* owner in a group. Groups need at least one owner to fulfill
+administrative duties.
+
+### Supported LDAP group types/attributes
+
+GitLab supports LDAP groups that use member attributes `member`, `submember`,
+`uniquemember`, `memberof` and `memberuid`. This means group sync supports, at
+least, LDAP groups with object class `groupOfNames`, `posixGroup`, and
+`groupOfUniqueName`. Other object classes should work fine as long as members
+are defined as one of the mentioned attributes. This also means GitLab supports
+Microsoft Active Directory, Apple Open Directory, Open LDAP, and 389 Server.
+Other LDAP servers should work, too.
+
+Active Directory also supports nested groups. Group sync will recursively
+resolve membership if `active_directory: true` is set in the configuration file.
+
+> **Note:** Nested group membership will only be resolved if the nested group
+ also falls within the configured `group_base`. For example, if GitLab sees a
+ nested group with DN `cn=nested_group,ou=special_groups,dc=example,dc=com` but
+ the configured `group_base` is `ou=groups,dc=example,dc=com`, `cn=nested_group`
+ will be ignored.
+
+### Queries
+
+- Each LDAP group is queried a maximum of one time with base `group_base` and
+ filter `(cn=<cn_from_group_link>)`.
+- If the LDAP group has the `memberuid` attribute, GitLab will execute another
+ LDAP query per member to obtain each user's full DN. These queries are
+ executed with base `base`, scope 'base object', and a filter depending on
+ whether `user_filter` is set. Filter may be `(uid=<uid_from_group>)` or a
+ joining of `user_filter`.
+
+### Benchmarks
+
+Group sync was written to be as performant as possible. Data is cached, database
+queries are optimized, and LDAP queries are minimized. The last benchmark run
+revealed the following metrics:
+
+For 20,000 LDAP users, 11,000 LDAP groups and 1,000 GitLab groups with 10
+LDAP group links each:
+
+- Initial sync (no existing members assigned in GitLab) took 1.8 hours
+- Subsequent syncs (checking membership, no writes) took 15 minutes
+
+These metrics are meant to provide a baseline and performance may vary based on
+any number of factors. This was a pretty extreme benchmark and most instances will
+not have near this many users or groups. Disk speed, database performance,
+network and LDAP server response time will affect these metrics.
+
+## Troubleshooting
+
+### Referral error
+
+If you see `LDAP search error: Referral` in the logs, or when troubleshooting
+LDAP Group Sync, this error may indicate a configuration problem. The LDAP
+configuration `/etc/gitlab/gitlab.rb` (Omnibus) or `config/gitlab.yml` (source)
+is in YAML format and is sensitive to indentation. Check that `group_base` and
+`admin_group` configuration keys are indented 2 spaces past the server
+identifier. The default identifier is `main` and an example snippet looks like
+the following:
+
+```yaml
+main: # 'main' is the GitLab 'provider ID' of this LDAP server
+ label: 'LDAP'
+ host: 'ldap.example.com'
+ ...
+ group_base: 'cn=my_group,ou=groups,dc=example,dc=com'
+ admin_group: 'my_admin_group'
+```
+
+[reconfigure]: ../restart_gitlab.md#omnibus-gitlab-reconfigure
+[restart]: ../restart_gitlab.md#installations-from-source
+
+[^1]: In Active Directory, a user is marked as disabled/blocked if the user
+ account control attribute (`userAccountControl:1.2.840.113556.1.4.803`)
+ has bit 2 set. See https://ctogonewild.com/2009/09/03/bitmask-searches-in-ldap/
+ for more information.
+
+### User DN has changed
+
+When an LDAP user is created in GitLab, their LDAP DN is stored for later reference.
+
+If GitLab cannot find a user by their DN, it will attempt to fallback
+to finding the user by their email. If the lookup is successful, GitLab will
+update the stored DN to the new value.
+
+### User is not being added to a group
+
+Sometimes you may think a particular user should be added to a GitLab group via
+LDAP group sync, but for some reason it's not happening. There are several
+things to check to debug the situation.
+
+- Ensure LDAP configuration has a `group_base` specified. This configuration is
+ required for group sync to work properly.
+- Ensure the correct LDAP group link is added to the GitLab group. Check group
+ links by visiting the GitLab group, then **Settings dropdown -> LDAP groups**.
+- Check that the user has an LDAP identity
+ 1. Sign in to GitLab as an administrator user.
+ 1. Navigate to **Admin area -> Users**.
+ 1. Search for the user
+ 1. Open the user, by clicking on their name. Do not click 'Edit'.
+ 1. Navigate to the **Identities** tab. There should be an LDAP identity with
+ an LDAP DN as the 'Identifier'.
+
+If all of the above looks good, jump in to a little more advanced debugging.
+Often, the best way to learn more about why group sync is behaving a certain
+way is to enable debug logging. There is verbose output that details every
+step of the sync.
+
+1. Start a Rails console
+
+ ```bash
+ # For Omnibus installations
+ sudo gitlab-rails console
+
+ # For installations from source
+ sudo -u git -H bundle exec rails console production
+ ```
+1. Set the log level to debug (only for this session):
+
+ ```ruby
+ Rails.logger.level = Logger::DEBUG
+ ```
+1. Choose a GitLab group to test with. This group should have an LDAP group link
+ already configured. If the output is `nil`, the group could not be found.
+ If a bunch of group attributes are output, your group was found successfully.
+
+ ```ruby
+ group = Group.find_by(name: 'my_group')
+
+ # Output
+ => #<Group:0x007fe825196558 id: 1234, name: "my_group"...>
+ ```
+1. Run a group sync for this particular group.
+
+ ```ruby
+ EE::Gitlab::Auth::LDAP::Sync::Group.execute_all_providers(group)
+ ```
+1. Look through the output of the sync. See [example log output](#example-log-output)
+ below for more information about the output.
+1. If you still aren't able to see why the user isn't being added, query the
+ LDAP group directly to see what members are listed. Still in the Rails console,
+ run the following query:
+
+ ```ruby
+ adapter = Gitlab::Auth::LDAP::Adapter.new('ldapmain') # If `main` is the LDAP provider
+ ldap_group = EE::Gitlab::Auth::LDAP::Group.find_by_cn('group_cn_here', adapter)
+
+ # Output
+ => #<EE::Gitlab::Auth::LDAP::Group:0x007fcbdd0bb6d8
+ ```
+1. Query the LDAP group's member DNs and see if the user's DN is in the list.
+ One of the DNs here should match the 'Identifier' from the LDAP identity
+ checked earlier. If it doesn't, the user does not appear to be in the LDAP
+ group.
+
+ ```ruby
+ ldap_group.member_dns
+
+ # Output
+ => ["uid=john,ou=people,dc=example,dc=com", "uid=mary,ou=people,dc=example,dc=com"]
+ ```
+1. Some LDAP servers don't store members by DN. Rather, they use UIDs instead.
+ If you didn't see results from the last query, try querying by UIDs instead.
+
+ ```ruby
+ ldap_group.member_uids
+
+ # Output
+ => ['john','mary']
+ ```
+
+#### Example log output
+
+The output of the last command will be very verbose, but contains lots of
+helpful information. For the most part you can ignore log entries that are SQL
+statements.
+
+Indicates the point where syncing actually begins:
+
+```bash
+Started syncing all providers for 'my_group' group
+```
+
+The follow entry shows an array of all user DNs GitLab sees in the LDAP server.
+Note that these are the users for a single LDAP group, not a GitLab group. If
+you have multiple LDAP groups linked to this GitLab group, you will see multiple
+log entries like this - one for each LDAP group. If you don't see an LDAP user
+DN in this log entry, LDAP is not returning the user when we do the lookup.
+Verify the user is actually in the LDAP group.
+
+```bash
+Members in 'ldap_group_1' LDAP group: ["uid=john0,ou=people,dc=example,dc=com",
+"uid=mary0,ou=people,dc=example,dc=com", "uid=john1,ou=people,dc=example,dc=com",
+"uid=mary1,ou=people,dc=example,dc=com", "uid=john2,ou=people,dc=example,dc=com",
+"uid=mary2,ou=people,dc=example,dc=com", "uid=john3,ou=people,dc=example,dc=com",
+"uid=mary3,ou=people,dc=example,dc=com", "uid=john4,ou=people,dc=example,dc=com",
+"uid=mary4,ou=people,dc=example,dc=com"]
+```
+
+Shortly after each of the above entries, you will see a hash of resolved member
+access levels. This hash represents all user DNs GitLab thinks should have
+access to this group, and at which access level (role). This hash is additive,
+and more DNs may be added, or existing entries modified, based on additional
+LDAP group lookups. The very last occurrence of this entry should indicate
+exactly which users GitLab believes should be added to the group.
+
+> **Note:** 10 is 'Guest', 20 is 'Reporter', 30 is 'Developer', 40 is 'Maintainer'
+ and 50 is 'Owner'
+
+```bash
+Resolved 'my_group' group member access: {"uid=john0,ou=people,dc=example,dc=com"=>30,
+"uid=mary0,ou=people,dc=example,dc=com"=>30, "uid=john1,ou=people,dc=example,dc=com"=>30,
+"uid=mary1,ou=people,dc=example,dc=com"=>30, "uid=john2,ou=people,dc=example,dc=com"=>30,
+"uid=mary2,ou=people,dc=example,dc=com"=>30, "uid=john3,ou=people,dc=example,dc=com"=>30,
+"uid=mary3,ou=people,dc=example,dc=com"=>30, "uid=john4,ou=people,dc=example,dc=com"=>30,
+"uid=mary4,ou=people,dc=example,dc=com"=>30}
+```
+
+It's not uncommon to see warnings like the following. These indicate that GitLab
+would have added the user to a group, but the user could not be found in GitLab.
+Usually this is not a cause for concern.
+
+If you think a particular user should already exist in GitLab, but you're seeing
+this entry, it could be due to a mismatched DN stored in GitLab. See
+[User DN has changed](#User-DN-has-changed) to update the user's LDAP identity.
+
+```bash
+User with DN `uid=john0,ou=people,dc=example,dc=com` should have access
+to 'my_group' group but there is no user in GitLab with that
+identity. Membership will be updated once the user signs in for
+the first time.
+```
+
+Finally, the following entry says syncing has finished for this group:
+
+```bash
+Finished syncing all providers for 'my_group' group
+```
diff --git a/doc/administration/auth/ldap.md b/doc/administration/auth/ldap.md
index 2d057dc7509..54279897e04 100644
--- a/doc/administration/auth/ldap.md
+++ b/doc/administration/auth/ldap.md
@@ -14,7 +14,7 @@ including group membership syncing as well as multiple LDAP servers support.
The information on this page is relevant for both GitLab CE and EE. For more
details about EE-specific LDAP features, see the
-[LDAP Enterprise Edition documentation](https://docs.gitlab.com/ee/administration/auth/ldap-ee.html).
+[LDAP Enterprise Edition documentation](ldap-ee.md). **[STARTER ONLY]**
## Security
@@ -30,16 +30,16 @@ the LDAP server.
### User deletion
-If a user is deleted from the LDAP server, they will be blocked in GitLab, as
+If a user is deleted from the LDAP server, they will be blocked in GitLab as
well. Users will be immediately blocked from logging in. However, there is an
-LDAP check cache time (sync time) of one hour (see note). This means users that
+LDAP check cache time of one hour (see note) which means users that
are already logged in or are using Git over SSH will still be able to access
GitLab for up to one hour. Manually block the user in the GitLab Admin area to
immediately block all access.
NOTE: **Note**:
GitLab Enterprise Edition Starter supports a
-[configurable sync time](https://docs.gitlab.com/ee/administration/auth/ldap-ee.html#adjusting-ldap-user-and-group-sync-schedules),
+[configurable sync time](ldap-ee.md#adjusting-ldap-user-sync-schedule),
with a default of one hour.
## Git password authentication
@@ -64,6 +64,7 @@ to connect to one GitLab server.
For a complete guide on configuring LDAP with GitLab Community Edition, please check
the admin guide [How to configure LDAP with GitLab CE](how_to_configure_ldap_gitlab_ce/index.md).
+For GitLab Enterprise Editions, see also [How to configure LDAP with GitLab EE](how_to_configure_ldap_gitlab_ee/index.md). **[STARTER ONLY]**
To enable LDAP integration you need to add your LDAP server settings in
`/etc/gitlab/gitlab.rb` or `/home/git/gitlab/config/gitlab.yml` for Omnibus
@@ -388,7 +389,7 @@ group, you can use the following syntax:
Find more information about this "LDAP_MATCHING_RULE_IN_CHAIN" filter at
<https://docs.microsoft.com/en-us/windows/desktop/ADSI/search-filter-syntax>. Support for
nested members in the user filter should not be confused with
-[group sync nested groups support (EE only)](https://docs.gitlab.com/ee/administration/auth/ldap-ee.html#supported-ldap-group-types-attributes).
+[group sync nested groups support](ldap-ee.md#supported-ldap-group-typesattributes). **[STARTER ONLY]**
Please note that GitLab does not support the custom filter syntax used by
omniauth-ldap.
diff --git a/doc/administration/auth/oidc.md b/doc/administration/auth/oidc.md
new file mode 100644
index 00000000000..00422ec347c
--- /dev/null
+++ b/doc/administration/auth/oidc.md
@@ -0,0 +1,163 @@
+# OpenID Connect OmniAuth provider
+
+GitLab can use [OpenID Connect](https://openid.net/specs/openid-connect-core-1_0.html) as an OmniAuth provider.
+
+To enable the OpenID Connect OmniAuth provider, you must register your application with an OpenID Connect provider.
+The OpenID Connect will provide you with a client details and secret for you to use.
+
+1. On your GitLab server, open the configuration file.
+
+ For Omnibus GitLab:
+
+ ```sh
+ sudo editor /etc/gitlab/gitlab.rb
+ ```
+
+ For installations from source:
+
+ ```sh
+ cd /home/git/gitlab
+ sudo -u git -H editor config/gitlab.yml
+ ```
+
+ See [Initial OmniAuth Configuration](../../integration/omniauth.md#initial-omniauth-configuration) for initial settings.
+
+1. Add the provider configuration.
+
+ For Omnibus GitLab:
+
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+ { 'name' => 'openid_connect',
+ 'label' => '<your_oidc_label>',
+ 'args' => {
+ "name' => 'openid_connect',
+ 'scope' => ['openid','profile'],
+ 'response_type' => 'code',
+ 'issuer' => '<your_oidc_url>',
+ 'discovery' => true,
+ 'client_auth_method' => 'query',
+ 'uid_field' => '<uid_field>',
+ 'client_options' => {
+ 'identifier' => '<your_oidc_client_id>',
+ 'secret' => '<your_oidc_client_secret>',
+ 'redirect_uri' => '<your_gitlab_url>/users/auth/openid_connect/callback'
+ }
+ }
+ }
+ ]
+ ```
+
+ For installation from source:
+
+ ```yaml
+ - { name: 'openid_connect',
+ label: '<your_oidc_label>',
+ args: {
+ name: 'openid_connect',
+ scope: ['openid','profile'],
+ response_type: 'code',
+ issuer: '<your_oidc_url>',
+ discovery: true,
+ client_auth_method: 'query',
+ uid_field: '<uid_field>',
+ client_options: {
+ identifier: '<your_oidc_client_id>',
+ secret: '<your_oidc_client_secret>',
+ redirect_uri: '<your_gitlab_url>/users/auth/openid_connect/callback'
+ }
+ }
+ }
+ ```
+
+ > **Note:**
+ >
+ > - For more information on each configuration option refer to
+ the [OmniAuth OpenID Connect usage documentation](https://github.com/m0n9oose/omniauth_openid_connect#usage) and
+ the [OpenID Connect Core 1.0 specification](https://openid.net/specs/openid-connect-core-1_0.html).
+
+1. For the configuration above, change the values for the provider to match your OpenID Connect client setup. Use the following as a guide:
+ - `<your_oidc_label>` is the label that will be displayed on the login page.
+ - `<your_oidc_url>` (optional) is the URL that points to the OpenID Connect provider. For example, `https://example.com/auth/realms/your-realm`.
+ If this value is not provided, the URL is constructed from the `client_options` in the following format: `<client_options.scheme>://<client_options.host>:<client_options.port>`.
+ - If `discovery` is set to `true`, the OpenID Connect provider will try to auto discover the client options using `<your_oidc_url>/.well-known/openid-configuration`. Defaults to `false`.
+ - `<uid_field>` (optional) is the field name from the `user_info` details that will be used as `uid` value. For example, `preferred_username`.
+ If this value is not provided or the field with the configured value is missing from the `user_info` details, the `uid` will use the `sub` field.
+ - `client_options` are the OpenID Connect client-specific options. Specifically:
+
+ - `identifier` is the client identifier as configured in the OpenID Connect service provider.
+ - `secret` is the client secret as configured in the OpenID Connect service provider.
+ - `redirect_uri` is the GitLab URL to redirect the user to after successful login. For example, `http://example.com/users/auth/openid_connect/callback`.
+ - `end_session_endpoint` (optional) is the URL to the endpoint that end the session (logout). Can be provided if auto-discovery disabled or unsuccessful.
+
+ The following `client_options` are optional unless auto-discovery is disabled or unsuccessful:
+
+ - `authorization_endpoint` is the URL to the endpoint that authorizes the end user.
+ - `token_endpoint` is the URL to the endpoint that provides Access Token.
+ - `userinfo_endpoint` is the URL to the endpoint that provides the user information.
+ - `jwks_uri` is the URL to the endpoint where the Token signer publishes its keys.
+
+1. Save the configuration file.
+1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../restart_gitlab.md#installations-from-source)
+ for the changes to take effect if you installed GitLab via Omnibus or from source respectively.
+
+On the sign in page, there should now be an OpenID Connect icon below the regular sign in form.
+Click the icon to begin the authentication process. The OpenID Connect provider will ask the user to
+sign in and authorize the GitLab application (if confirmation required by the client). If everything goes well, the user
+will be redirected to GitLab and will be signed in.
+
+## Example configurations
+
+The following configurations illustrate how to set up OpenID with
+different providers with Omnibus GitLab.
+
+### Google
+
+See the [Google
+documentation](https://developers.google.com/identity/protocols/OpenIDConnect)
+for more details:
+
+```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ 'name' => 'openid_connect',
+ 'label' => 'Google OpenID',
+ 'args' => {
+ 'name' => 'openid_connect',
+ 'scope' => ['openid', 'profile', 'email'],
+ 'response_type' => 'code',
+ 'issuer' => 'https://accounts.google.com',
+ 'client_auth_method' => 'query',
+ 'discovery' => true,
+ 'uid_field' => 'preferred_username',
+ 'client_options' => {
+ 'identifier' => '<YOUR PROJECT CLIENT ID>',
+ 'secret' => '<YOUR PROJECT CLIENT SECRET>',
+ 'redirect_uri' => 'https://example.com/users/auth/openid_connect/callback',
+ }
+ }
+ }
+```
+
+### Troubleshooting
+
+If you're having trouble, here are some tips:
+
+1. Ensure `discovery` is set to `true`. Setting it to `false` requires
+specifying all the URLs and keys required to make OpenID work.
+
+1. Check your system clock to ensure the time is synchronized properly.
+
+1. As mentioned in [the
+documentation](https://github.com/m0n9oose/omniauth_openid_connect),
+make sure `issuer` corresponds to the base URL of the Discovery URL. For
+example, `https://accounts.google.com` is used for the URL
+`https://accounts.google.com/.well-known/openid-configuration`.
+
+1. The OpenID Connect client uses HTTP Basic Authentication to send the
+OAuth2 access token. For example, if you are seeing 401 errors upon
+retrieving the `userinfo` endpoint, you may want to check your OpenID
+Web server configuration. For example, for
+[oauth2-server-php](https://github.com/bshaffer/oauth2-server-php), you
+may need to [add a configuration parameter to
+Apache](https://github.com/bshaffer/oauth2-server-php/issues/926#issuecomment-387502778).
diff --git a/doc/administration/auth/smartcard.md b/doc/administration/auth/smartcard.md
new file mode 100644
index 00000000000..b33c5359b44
--- /dev/null
+++ b/doc/administration/auth/smartcard.md
@@ -0,0 +1,186 @@
+# Smartcard authentication **[PREMIUM ONLY]**
+
+GitLab supports authentication using smartcards.
+
+## Authentication methods
+
+GitLab supports two authentication methods:
+
+- X.509 certificates with local databases.
+- LDAP servers.
+
+### Authentication against a local database with X.509 certificates
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/726) in
+[GitLab Premium](https://about.gitlab.com/pricing/) 11.6 as an experimental
+feature. Smartcard authentication against local databases may change or be
+removed completely in future releases.
+
+Smartcards with X.509 certificates can be used to authenticate with GitLab.
+
+To use a smartcard with an X.509 certificate to authenticate against a local
+database with GitLab, `CN` and `emailAddress` must be defined in the
+certificate. For example:
+
+```
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number: 12856475246677808609 (0xb26b601ecdd555e1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: O=Random Corp Ltd, CN=Random Corp
+ Validity
+ Not Before: Oct 30 12:00:00 2018 GMT
+ Not After : Oct 30 12:00:00 2019 GMT
+ Subject: CN=Gitlab User, emailAddress=gitlab-user@example.com
+```
+
+### Authentication against an LDAP server
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/7693) in
+[GitLab Premium](https://about.gitlab.com/pricing/) 11.8 as an experimental
+feature. Smartcard authentication against an LDAP server may change or be
+removed completely in future releases.
+
+GitLab implements a standard way of certificate matching following
+[RFC4523](https://tools.ietf.org/html/rfc4523). It uses the
+`certificateExactMatch` certificate matching rule against the `userCertificate`
+attribute. As a prerequisite, you must use an LDAP server that:
+
+- Supports the `certificateExactMatch` matching rule.
+- Has the certificate stored in the `userCertificate` attribute.
+
+## Configure GitLab for smartcard authentication
+
+**For Omnibus installations**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['smartcard_enabled'] = true
+ gitlab_rails['smartcard_ca_file'] = "/etc/ssl/certs/CA.pem"
+ gitlab_rails['smartcard_client_certificate_required_port'] = 3444
+ ```
+
+1. Save the file and [reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure)
+ GitLab for the changes to take effect.
+
+---
+
+**For installations from source**
+
+1. Configure NGINX to request a client side certificate
+
+ In NGINX configuration, an **additional** server context must be defined with
+ the same configuration except:
+
+ - The additional NGINX server context must be configured to run on a different
+ port:
+
+ ```
+ listen *:3444 ssl;
+ ```
+
+ - The additional NGINX server context must be configured to require the client
+ side certificate:
+
+ ```
+ ssl_verify_depth 2;
+ ssl_client_certificate /etc/ssl/certs/CA.pem;
+ ssl_verify_client on;
+ ```
+
+ - The additional NGINX server context must be configured to forward the client
+ side certificate:
+
+ ```
+ proxy_set_header X-SSL-Client-Certificate $ssl_client_escaped_cert;
+ ```
+
+ For example, the following is an example server context in an NGINX
+ configuration file (eg. in `/etc/nginx/sites-available/gitlab-ssl`):
+
+ ```
+ server {
+ listen *:3444 ssl;
+
+ # certificate for configuring SSL
+ ssl_certificate /path/to/example.com.crt;
+ ssl_certificate_key /path/to/example.com.key;
+
+ ssl_verify_depth 2;
+ # CA certificate for client side certificate verification
+ ssl_client_certificate /etc/ssl/certs/CA.pem;
+ ssl_verify_client on;
+
+ location / {
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection $connection_upgrade;
+
+ proxy_set_header X-SSL-Client-Certificate $ssl_client_escaped_cert;
+
+ proxy_read_timeout 300;
+
+ proxy_pass http://gitlab-workhorse;
+ }
+ }
+ ```
+
+1. Edit `config/gitlab.yml`:
+
+ ```yaml
+ ## Smartcard authentication settings
+ smartcard:
+ # Allow smartcard authentication
+ enabled: true
+
+ # Path to a file containing a CA certificate
+ ca_file: '/etc/ssl/certs/CA.pem'
+
+ # Port where the client side certificate is requested by NGINX
+ client_certificate_required_port: 3444
+ ```
+
+1. Save the file and [restart](../restart_gitlab.md#installations-from-source)
+ GitLab for the changes to take effect.
+
+### Additional steps when authenticating against an LDAP server
+
+**For Omnibus installations**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['ldap_servers'] = YAML.load <<-EOS
+ main:
+ # snip...
+ # Enable smartcard authentication against the LDAP server. Valid values
+ # are "false", "optional", and "required".
+ smartcard_auth: optional
+ EOS
+ ```
+
+1. Save the file and [reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure)
+ GitLab for the changes to take effect.
+
+**For installations from source**
+
+1. Edit `config/gitlab.yml`:
+
+ ```yaml
+ production:
+ ldap:
+ servers:
+ main:
+ # snip...
+ # Enable smartcard authentication against the LDAP server. Valid values
+ # are "false", "optional", and "required".
+ smartcard_auth: optional
+ ```
+
+1. Save the file and [restart](../restart_gitlab.md#installations-from-source)
+ GitLab for the changes to take effect.
diff --git a/doc/administration/compliance.md b/doc/administration/compliance.md
index 72cb57fb36c..246addb6dc9 100644
--- a/doc/administration/compliance.md
+++ b/doc/administration/compliance.md
@@ -11,8 +11,8 @@ GitLab’s [security features](../security/README.md) may also help you meet rel
|**[Enforce TOS acceptance](../user/admin_area/settings/terms.md)**<br>Enforce your users accepting new terms of service by blocking GitLab traffic.|Core+||
|**[Email all users of a project, group, or entire server](../user/admin_area/settings/terms.md)**<br>An admin can email groups of users based on project or group membership, or email everyone using the GitLab instance. This is great for scheduled maintenance or upgrades.|Starter+||
|**[Omnibus package supports log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-forwarding)**<br>Forward your logs to a central system.|Starter+||
-|**[Lock project membership to group](https://docs.gitlab.com/ee/user/group/index.html#member-lock-starter)**<br>Group owners can prevent new members from being added to projects within a group.|Starter+|✓|
-|**[LDAP group sync](https://docs.gitlab.com/ee/administration/auth/ldap-ee.html#group-sync)**<br>GitLab Enterprise Edition gives admins the ability to automatically sync groups and manage SSH keys, permissions, and authentication, so you can focus on building your product, not configuring your tools.|Starter+||
-|**[LDAP group sync filters](https://docs.gitlab.com/ee/administration/auth/ldap-ee.html#group-sync)**<br>GitLab Enterprise Edition Premium gives more flexibility to synchronize with LDAP based on filters, meaning you can leverage LDAP attributes to map GitLab permissions.|Premium+||
-|**[Audit logs](https://docs.gitlab.com/ee/administration/audit_events.html)**<br>To maintain the integrity of your code, GitLab Enterprise Edition Premium gives admins the ability to view any modifications made within the GitLab server in an advanced audit log system, so you can control, analyze and track every change.|Premium+||
-|**[Auditor users](https://docs.gitlab.com/ee/administration/auditor_users.html)**<br>Auditor users are users who are given read-only access to all projects, groups, and other resources on the GitLab instance.|Premium+|| \ No newline at end of file
+|**[Lock project membership to group](../user/group/index.md#member-lock-starter)**<br>Group owners can prevent new members from being added to projects within a group.|Starter+|✓|
+|**[LDAP group sync](auth/ldap-ee.md#group-sync)**<br>GitLab Enterprise Edition gives admins the ability to automatically sync groups and manage SSH keys, permissions, and authentication, so you can focus on building your product, not configuring your tools.|Starter+||
+|**[LDAP group sync filters](auth/ldap-ee.md#group-sync)**<br>GitLab Enterprise Edition Premium gives more flexibility to synchronize with LDAP based on filters, meaning you can leverage LDAP attributes to map GitLab permissions.|Premium+||
+|**[Audit logs](audit_events.md)**<br>To maintain the integrity of your code, GitLab Enterprise Edition Premium gives admins the ability to view any modifications made within the GitLab server in an advanced audit log system, so you can control, analyze and track every change.|Premium+||
+|**[Auditor users](auditor_users.md)**<br>Auditor users are users who are given read-only access to all projects, groups, and other resources on the GitLab instance.|Premium+||
diff --git a/doc/administration/container_registry.md b/doc/administration/container_registry.md
index 05beb724d4d..4d55f2357c1 100644
--- a/doc/administration/container_registry.md
+++ b/doc/administration/container_registry.md
@@ -384,11 +384,12 @@ CAUTION: **Warning:** GitLab will not backup Docker images that are not stored o
filesystem. Remember to enable backups with your object storage provider if
desired.
----
+NOTE: **Note:**
+`regionendpoint` is only required when configuring an S3 compatible service such as Minio. It takes a URL such as `http://127.0.0.1:9000`.
**Omnibus GitLab installations**
-To configure the storage driver in Omnibus:
+To configure the `s3` storage driver in Omnibus:
1. Edit `/etc/gitlab/gitlab.rb`:
@@ -398,29 +399,29 @@ To configure the storage driver in Omnibus:
'accesskey' => 's3-access-key',
'secretkey' => 's3-secret-key-for-access-key',
'bucket' => 'your-s3-bucket',
- 'region' => 'your-s3-region'
+ 'region' => 'your-s3-region',
+ 'regionendpoint' => 'your-s3-regionendpoint'
}
}
```
1. Save the file and [reconfigure GitLab][] for the changes to take effect.
----
-
**Installations from source**
Configuring the storage driver is done in your registry config YML file created
when you [deployed your docker registry][registry-deploy].
-Example:
+`s3` storage driver example:
-```
+```yml
storage:
s3:
accesskey: 'AKIAKIAKI'
secretkey: 'secret123'
bucket: 'gitlab-registry-bucket-AKIAKIAKI'
region: 'your-s3-region'
+ regionendpoint: 'your-s3-regionendpoint'
cache:
blobdescriptor: inmemory
delete:
@@ -658,6 +659,37 @@ Start with a value between `25000000` (25MB) and `50000000` (50MB).
1. Save the file and [restart GitLab][] for the changes to take effect.
+### Supporting older Docker clients
+
+As of GitLab 11.9, we began shipping version 2.7.1 of the Docker container registry, which disables the schema1 manifest by default. If you are still using older Docker clients (1.9 or older), you may experience an error pushing images. See [omnibus-4145](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/4145) for more details.
+
+You can add a configuration option for backwards compatibility.
+
+**For Omnibus installations**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ registry['compatibility_schema1_enabled'] = true
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+---
+
+**For installations from source**
+
+1. Edit the YML configuration file you created when you [deployed the registry][registry-deploy]. Add the following snippet:
+
+ ```yaml
+ compatibility:
+ schema1:
+ enabled: true
+ ```
+
+1. Restart the registry for the changes to take affect.
+
+
[ce-18239]: https://gitlab.com/gitlab-org/gitlab-ce/issues/18239
[docker-insecure-self-signed]: https://docs.docker.com/registry/insecure/#use-self-signed-certificates
[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure
diff --git a/doc/administration/custom_hooks.md b/doc/administration/custom_hooks.md
index 28afaf84f5a..113514e1ee8 100644
--- a/doc/administration/custom_hooks.md
+++ b/doc/administration/custom_hooks.md
@@ -1,12 +1,16 @@
-# Custom Git Hooks
+# Custom server-side Git hooks
-> **Note:** Custom Git hooks must be configured on the filesystem of the GitLab
+NOTE: **Note:**
+Custom Git hooks must be configured on the filesystem of the GitLab
server. Only GitLab server administrators will be able to complete these tasks.
Please explore [webhooks] and [CI] as an option if you do not
have filesystem access. For a user configurable Git hook interface, see
-[Push Rules](https://docs.gitlab.com/ee/push_rules/push_rules.html),
+[Push Rules](../push_rules/push_rules.md),
available in GitLab Enterprise Edition.
+NOTE: **Note:**
+Custom Git hooks won't be replicated to secondary nodes if you use [GitLab Geo](geo/replication/index.md)
+
Git natively supports hooks that are executed on different actions.
Examples of server-side git hooks include pre-receive, post-receive, and update.
See [Git SCM Server-Side Hooks][hooks] for more information about each hook type.
@@ -14,15 +18,14 @@ See [Git SCM Server-Side Hooks][hooks] for more information about each hook type
As of gitlab-shell version 2.2.0 (which requires GitLab 7.5+), GitLab
administrators can add custom git hooks to any GitLab project.
-## Setup
-
-Normally, Git hooks are placed in the repository or project's `hooks` directory.
-GitLab creates a symlink from each project's `hooks` directory to the
-gitlab-shell `hooks` directory for ease of maintenance between gitlab-shell
-upgrades. As such, custom hooks are implemented a little differently. Behavior
-is exactly the same once the hook is created, though.
+## Create a custom Git hook for a repository
-Follow the steps below to set up a custom hook:
+Server-side Git hooks are typically placed in the repository's `hooks`
+subdirectory. In GitLab, hook directories are are symlinked to the gitlab-shell
+`hooks` directory for ease of maintenance between gitlab-shell upgrades.
+Custom hooks are implemented differently, but the behavior is exactly the same
+once the hook is created. Follow the steps below to set up a custom hook for a
+repository:
1. Pick a project that needs a custom Git hook.
1. On the GitLab server, navigate to the project's repository directory.
@@ -42,33 +45,56 @@ Follow the steps below to set up a custom hook:
That's it! Assuming the hook code is properly implemented the hook will fire
as appropriate.
+## Set a global Git hook for all repositories
+
+To create a Git hook that applies to all of your repositories in
+your instance, set a global Git hook. Since all the repositories' `hooks`
+directories are symlinked to gitlab-shell's `hooks` directory, adding any hook
+to the gitlab-shell `hooks` directory will also apply it to all repositories. Follow
+the steps below to properly set up a custom hook for all repositories:
+
+1. On the GitLab server, navigate to the configured custom hook directory. The
+ default is in the gitlab-shell directory. The gitlab-shell `hook` directory
+ for an installation from source the path is usually
+ `/home/git/gitlab-shell/hooks`. For Omnibus installs the path is usually
+ `/opt/gitlab/embedded/service/gitlab-shell/hooks`.
+ To look in a different directory for the global custom hooks,
+ set `custom_hooks_dir` in the gitlab-shell config. For
+ Omnibus installations, this can be set in `gitlab.rb`; and in source
+ installations, this can be set in `gitlab-shell/config.yml`.
+1. Create a new directory in this location. Depending on your hook, it will be
+ either a `pre-receive.d`, `post-receive.d`, or `update.d` directory.
+1. Inside this new directory, add your hook. Hooks can be
+ in any language. Ensure the 'shebang' at the top properly reflects the language
+ type. For example, if the script is in Ruby the shebang will probably be
+ `#!/usr/bin/env ruby`.
+1. Make the hook file executable and make sure it's owned by Git.
+
+Now test the hook to see that it's functioning properly.
+
## Chained hooks support
> [Introduced][93] in GitLab Shell 4.1.0 and GitLab 8.15.
-Hooks can be also placed in `hooks/<hook_name>.d` (global) or
-`custom_hooks/<hook_name>.d` (per project) directories supporting chained
+Hooks can be also global or be set per project directories and support a chained
execution of the hooks.
-NOTE: **Note:** `<hook_name>.d` would need to be either `pre-receive.d`,
+NOTE: **Note:**
+`<hook_name>.d` would need to be either `pre-receive.d`,
`post-receive.d`, or `update.d` to work properly. Any other names will be ignored.
-To look in a different directory for the global custom hooks (those in
-`hooks/<hook_name.d>`), set `custom_hooks_dir` in gitlab-shell config. For
-Omnibus installations, this can be set in `gitlab.rb`; and in source
-installations, this can be set in `gitlab-shell/config.yml`.
+NOTE: **Note:**
+Files in `.d` directories need to be executable and not match the backup file
+pattern (`*~`).
The hooks are searched and executed in this order:
1. `gitlab-shell/hooks` directory as known to Gitaly
-1. `<project>.git/hooks/<hook_name>` - executed by `git` itself, this is `gitlab-shell/hooks/<hook_name>`
+1. `<project>.git/hooks/<hook_name>` - executed by `git` itself, this is symlinked to `gitlab-shell/hooks/<hook_name>`
1. `<project>.git/custom_hooks/<hook_name>` - per project hook (this is already existing behavior)
1. `<project>.git/custom_hooks/<hook_name>.d/*` - per project hooks
1. `<project>.git/hooks/<hook_name>.d/*` OR `<custom_hooks_dir>/<hook_name.d>/*` - global hooks: all executable files (minus editor backup files)
-Files in `.d` directories need to be executable and not match the backup file
-pattern (`*~`).
-
The hooks of the same type are executed in order and execution stops on the
first script exiting with a non-zero value.
diff --git a/doc/administration/database_load_balancing.md b/doc/administration/database_load_balancing.md
new file mode 100644
index 00000000000..7f3be402b84
--- /dev/null
+++ b/doc/administration/database_load_balancing.md
@@ -0,0 +1,277 @@
+# Database Load Balancing **[PREMIUM ONLY]**
+
+> [Introduced][ee-1283] in [GitLab Premium][eep] 9.0.
+
+Distribute read-only queries among multiple database servers.
+
+## Overview
+
+Database load balancing improves the distribution of database workloads across
+multiple computing resources. Load balancing aims to optimize resource use,
+maximize throughput, minimize response time, and avoid overload of any single
+resource. Using multiple components with load balancing instead of a single
+component may increase reliability and availability through redundancy.
+[_Wikipedia article_][wikipedia]
+
+When database load balancing is enabled in GitLab, the load is balanced using
+a simple round-robin algorithm, without any external dependencies such as Redis.
+Load balancing is not enabled for Sidekiq as this would lead to consistency
+problems, and Sidekiq mostly performs writes anyway.
+
+In the following image, you can see the load is balanced rather evenly among
+all the secondaries (`db4`, `db5`, `db6`). Because `SELECT` queries are not
+sent to the primary (unless necessary), the primary (`db3`) hardly has any load.
+
+![DB load balancing graph](img/db_load_balancing_postgres_stats.png)
+
+## Requirements
+
+For load balancing to work you will need at least PostgreSQL 9.2 or newer,
+[**MySQL is not supported**][db-req]. You also need to make sure that you have
+at least 1 secondary in [hot standby][hot-standby] mode.
+
+Load balancing also requires that the configured hosts **always** point to the
+primary, even after a database failover. Furthermore, the additional hosts to
+balance load among must **always** point to secondary databases. This means that
+you should put a load balance in front of every database, and have GitLab connect
+to those load balancers.
+
+For example, say you have a primary (`db1.gitlab.com`) and two secondaries,
+`db2.gitlab.com` and `db3.gitlab.com`. For this setup you will need to have 3
+load balancers, one for every host. For example:
+
+* `primary.gitlab.com` forwards to `db1.gitlab.com`
+* `secondary1.gitlab.com` forwards to `db2.gitlab.com`
+* `secondary2.gitlab.com` forwards to `db3.gitlab.com`
+
+Now let's say that a failover happens and db2 becomes the new primary. This
+means forwarding should now happen as follows:
+
+* `primary.gitlab.com` forwards to `db2.gitlab.com`
+* `secondary1.gitlab.com` forwards to `db1.gitlab.com`
+* `secondary2.gitlab.com` forwards to `db3.gitlab.com`
+
+GitLab does not take care of this for you, so you will need to do so yourself.
+
+Finally, load balancing requires that GitLab can connect to all hosts using the
+same credentials and port as configured in the
+[Enabling load balancing](#enabling-load-balancing) section. Using
+different ports or credentials for different hosts is not supported.
+
+## Use cases
+
+- For GitLab instances with thousands of users and high traffic, you can use
+ database load balancing to reduce the load on the primary database and
+ increase responsiveness, thus resulting in faster page load inside GitLab.
+
+## Enabling load balancing
+
+For the environment in which you want to use load balancing, you'll need to add
+the following. This will balance the load between `host1.example.com` and
+`host2.example.com`.
+
+**In Omnibus installations:**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
+
+ ```ruby
+ gitlab_rails['db_load_balancing'] = { 'hosts' => ['host1.example.com', 'host2.example.com'] }
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+---
+
+**In installations from source:**
+
+1. Edit `/home/git/gitlab/config/database.yml` and add or amend the following lines:
+
+ ```yaml
+ production:
+ username: gitlab
+ database: gitlab
+ encoding: unicode
+ load_balancing:
+ hosts:
+ - host1.example.com
+ - host2.example.com
+ ```
+
+1. Save the file and [restart GitLab][] for the changes to take effect.
+
+## Service Discovery
+
+> [Introduced][ee-5883] in [GitLab Premium][eep] 11.0.
+
+Service discovery allows GitLab to automatically retrieve a list of secondary
+databases to use, instead of having to manually specify these in the
+`database.yml` configuration file. Service discovery works by periodically
+checking a DNS A record, using the IPs returned by this record as the addresses
+for the secondaries. For service discovery to work, all you need is a DNS server
+and an A record containing the IP addresses of your secondaries.
+
+To use service discovery you need to change your `database.yml` configuration
+file so it looks like the following:
+
+```yaml
+production:
+ username: gitlab
+ database: gitlab
+ encoding: unicode
+ load_balancing:
+ discover:
+ nameserver: localhost
+ record: secondary.postgresql.service.consul
+ port: 8600
+ interval: 60
+ disconnect_timeout: 120
+```
+
+Here the `discover:` section specifies the configuration details to use for
+service discovery.
+
+### Configuration
+
+The following options can be set:
+
+| Option | Description | Default |
+|----------------------|---------------------------------------------------------------------------------------------------|-----------|
+| `nameserver` | The nameserver to use for looking up the DNS record. | localhost |
+| `record` | The A record to look up. This option is required for service discovery to work. | |
+| `port` | The port of the nameserver. | 8600 |
+| `interval` | The minimum time in seconds between checking the DNS record. | 60 |
+| `disconnect_timeout` | The time in seconds after which an old connection is closed, after the list of hosts was updated. | 120 |
+| `use_tcp` | Lookup DNS resources using TCP instead of UDP | false |
+
+The `interval` value specifies the _minimum_ time between checks. If the A
+record has a TTL greater than this value, then service discovery will honor said
+TTL. For example, if the TTL of the A record is 90 seconds, then service
+discovery will wait at least 90 seconds before checking the A record again.
+
+When the list of hosts is updated, it might take a while for the old connections
+to be terminated. The `disconnect_timeout` setting can be used to enforce an
+upper limit on the time it will take to terminate all old database connections.
+
+Some nameservers (like [Consul][consul-udp]) can return a truncated list of hosts when
+queried over UDP. To overcome this issue, you can use TCP for querying by setting
+`use_tcp` to `true`.
+
+### Forking
+
+If you use an application server that forks, such as Unicorn, you _have to_
+update your Unicorn configuration to start service discovery _after_ a fork.
+Failure to do so will lead to service discovery only running in the parent
+process. If you are using Unicorn, then you can add the following to your
+Unicorn configuration file:
+
+```ruby
+after_fork do |server, worker|
+ defined?(Gitlab::Database::LoadBalancing) &&
+ Gitlab::Database::LoadBalancing.start_service_discovery
+end
+```
+
+This will ensure that service discovery is started in both the parent and all
+child processes.
+
+## Balancing queries
+
+Read-only `SELECT` queries will be balanced among all the secondary hosts.
+Everything else (including transactions) will be executed on the primary.
+Queries such as `SELECT ... FOR UPDATE` are also executed on the primary.
+
+## Prepared statements
+
+Prepared statements don't work well with load balancing and are disabled
+automatically when load balancing is enabled. This should have no impact on
+response timings.
+
+## Primary sticking
+
+After a write has been performed, GitLab will stick to using the primary for a
+certain period of time, scoped to the user that performed the write. GitLab will
+revert back to using secondaries when they have either caught up, or after 30
+seconds.
+
+## Failover handling
+
+In the event of a failover or an unresponsive database, the load balancer will
+try to use the next available host. If no secondaries are available the
+operation is performed on the primary instead.
+
+In the event of a connection error being produced when writing data, the
+operation will be retried up to 3 times using an exponential back-off.
+
+When using load balancing, you should be able to safely restart a database server
+without it immediately leading to errors being presented to the users.
+
+## Logging
+
+The load balancer logs various messages, such as:
+
+* When a host is marked as offline
+* When a host comes back online
+* When all secondaries are offline
+
+Each log message contains the tag `[DB-LB]` to make searching/filtering of such
+log entries easier. For example:
+
+```
+[DB-LB] Host 10.123.2.5 came back online
+[DB-LB] Marking host 10.123.2.7 as offline
+[DB-LB] Marking host 10.123.2.7 as offline
+[DB-LB] Marking host 10.123.2.7 as offline
+[DB-LB] Marking host 10.123.2.7 as offline
+[DB-LB] Marking host 10.123.2.7 as offline
+[DB-LB] Host 10.123.2.6 came back online
+[DB-LB] Marking host 10.123.2.7 as offline
+[DB-LB] Marking host 10.123.2.7 as offline
+[DB-LB] Marking host 10.123.2.7 as offline
+[DB-LB] Host 10.123.2.7 came back online
+[DB-LB] Host 10.123.2.7 came back online
+```
+
+## Handling Stale Reads
+
+> [Introduced][ee-3526] in [GitLab Premium][eep] 10.3.
+
+To prevent reading from an outdated secondary the load balancer will check if it
+is in sync with the primary. If the data is determined to be recent enough the
+secondary can be used, otherwise it will be ignored. To reduce the overhead of
+these checks we only perform these checks at certain intervals.
+
+There are three configuration options that influence this behaviour:
+
+| Option | Description | Default |
+|------------------------------|----------------------------------------------------------------------------------------------------------------|------------|
+| `max_replication_difference` | The amount of data (in bytes) a secondary is allowed to lag behind when it hasn't replicated data for a while. | 8 MB |
+| `max_replication_lag_time` | The maximum number of seconds a secondary is allowed to lag behind before we stop using it. | 60 seconds |
+| `replica_check_interval` | The minimum number of seconds we have to wait before checking the status of a secondary. | 60 seconds |
+
+The defaults should be sufficient for most users. Should you want to change them
+you can specify them in `config/database.yml` like so:
+
+```yaml
+production:
+ username: gitlab
+ database: gitlab
+ encoding: unicode
+ load_balancing:
+ hosts:
+ - host1.example.com
+ - host2.example.com
+ max_replication_difference: 16777216 # 16 MB
+ max_replication_lag_time: 30
+ replica_check_interval: 30
+```
+
+[hot-standby]: https://www.postgresql.org/docs/9.6/static/hot-standby.html
+[ee-1283]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1283
+[eep]: https://about.gitlab.com/pricing/
+[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab"
+[restart gitlab]: restart_gitlab.md#installations-from-source "How to restart GitLab"
+[wikipedia]: https://en.wikipedia.org/wiki/Load_balancing_(computing)
+[db-req]: ../install/requirements.md#database
+[ee-3526]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3526
+[ee-5883]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/5883
+[consul-udp]: https://www.consul.io/docs/agent/dns.html#udp-based-dns-queries
diff --git a/doc/administration/dependency_proxy.md b/doc/administration/dependency_proxy.md
new file mode 100644
index 00000000000..4dc1f4dcba4
--- /dev/null
+++ b/doc/administration/dependency_proxy.md
@@ -0,0 +1,150 @@
+# GitLab Dependency Proxy administration **[PREMIUM ONLY]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/7934) in [GitLab Premium](https://about.gitlab.com/pricing) 11.11.
+
+GitLab can be utilized as a dependency proxy for a variety of common package managers.
+
+This is the administration documentation. If you want to learn how to use the
+dependency proxies, see the [user guide](../user/group/dependency_proxy/index.md).
+
+## Enabling the Dependency Proxy feature
+
+NOTE: **Note:**
+Dependency proxy requires the Puma web server to be enabled.
+Puma support is EXPERIMENTAL at this time.
+
+To enable the Dependency proxy feature:
+
+**Omnibus GitLab installations**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
+
+ ```ruby
+ gitlab_rails['dependency_proxy_enabled'] = true
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+1. Enable the [Puma web server](https://docs.gitlab.com/omnibus/settings/puma.html).
+
+**Installations from source**
+
+1. After the installation is complete, you will have to configure the `dependency_proxy`
+ section in `config/gitlab.yml`. Set to `true` to enable it:
+
+ ```yaml
+ dependency_proxy:
+ enabled: true
+ ```
+
+1. [Restart GitLab] for the changes to take effect.
+1. Enable the [Puma web server](../install/installation.md#using-puma).
+
+## Changing the storage path
+
+By default, the dependency proxy files are stored locally, but you can change the default
+local location or even use object storage.
+
+### Changing the local storage path
+
+The dependency proxy files for Omnibus GitLab installations are stored under
+`/var/opt/gitlab/gitlab-rails/shared/dependency_proxy/` and for source
+installations under `shared/dependency_proxy/` (relative to the git home directory).
+To change the local storage path:
+
+**Omnibus GitLab installations**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
+
+ ```ruby
+ gitlab_rails['dependency_proxy_storage_path'] = "/mnt/dependency_proxy"
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**Installations from source**
+
+1. Edit the `dependency_proxy` section in `config/gitlab.yml`:
+
+ ```yaml
+ dependency_proxy:
+ enabled: true
+ storage_path: shared/dependency_proxy
+ ```
+1. [Restart GitLab] for the changes to take effect.
+
+### Using object storage
+
+Instead of relying on the local storage, you can use an object storage to
+upload the blobs of the dependency proxy:
+
+**Omnibus GitLab installations**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following lines (uncomment where
+ necessary):
+
+ ```ruby
+ gitlab_rails['dependency_proxy_enabled'] = true
+ gitlab_rails['dependency_proxy_storage_path'] = "/var/opt/gitlab/gitlab-rails/shared/dependency_proxy"
+ gitlab_rails['dependency_proxy_object_store_enabled'] = true
+ gitlab_rails['dependency_proxy_object_store_remote_directory'] = "dependency_proxy" # The bucket name.
+ gitlab_rails['dependency_proxy_object_store_direct_upload'] = false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false).
+ gitlab_rails['dependency_proxy_object_store_background_upload'] = true # Temporary option to limit automatic upload (Default: true).
+ gitlab_rails['dependency_proxy_object_store_proxy_download'] = false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage.
+ gitlab_rails['dependency_proxy_object_store_connection'] = {
+ ##
+ ## If the provider is AWS S3, uncomment the following
+ ##
+ #'provider' => 'AWS',
+ #'region' => 'eu-west-1',
+ #'aws_access_key_id' => 'AWS_ACCESS_KEY_ID',
+ #'aws_secret_access_key' => 'AWS_SECRET_ACCESS_KEY',
+ ##
+ ## If the provider is other than AWS (an S3-compatible one), uncomment the following
+ ##
+ #'host' => 's3.amazonaws.com',
+ #'aws_signature_version' => 4 # For creation of signed URLs. Set to 2 if provider does not support v4.
+ #'endpoint' => 'https://s3.amazonaws.com' # Useful for S3-compliant services such as DigitalOcean Spaces.
+ #'path_style' => false # If true, use 'host/bucket_name/object' instead of 'bucket_name.host/object'.
+ }
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**Installations from source**
+
+1. Edit the `dependency_proxy` section in `config/gitlab.yml` (uncomment where necessary):
+
+ ```yaml
+ dependency_proxy:
+ enabled: true
+ ##
+ ## The location where build dependency_proxy are stored (default: shared/dependency_proxy).
+ ##
+ #storage_path: shared/dependency_proxy
+ object_store:
+ enabled: false
+ remote_directory: dependency_proxy # The bucket name.
+ #direct_upload: false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false).
+ #background_upload: true # Temporary option to limit automatic upload (Default: true).
+ #proxy_download: false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage.
+ connection:
+ ##
+ ## If the provider is AWS S3, uncomment the following
+ ##
+ #provider: AWS
+ #region: us-east-1
+ #aws_access_key_id: AWS_ACCESS_KEY_ID
+ #aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+ ##
+ ## If the provider is other than AWS (an S3-compatible one), uncomment the following
+ ##
+ #host: 's3.amazonaws.com' # default: s3.amazonaws.com.
+ #aws_signature_version: 4 # For creation of signed URLs. Set to 2 if provider does not support v4.
+ #endpoint: 'https://s3.amazonaws.com' # Useful for S3-compliant services such as DigitalOcean Spaces.
+ #path_style: false # If true, use 'host/bucket_name/object' instead of 'bucket_name.host/object'.
+ ```
+
+1. [Restart GitLab] for the changes to take effect.
+
+[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab"
+[restart gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab"
diff --git a/doc/administration/geo/disaster_recovery/background_verification.md b/doc/administration/geo/disaster_recovery/background_verification.md
new file mode 100644
index 00000000000..d4c8c2d3624
--- /dev/null
+++ b/doc/administration/geo/disaster_recovery/background_verification.md
@@ -0,0 +1,182 @@
+# Automatic background verification **[PREMIUM ONLY]**
+
+NOTE: **Note:**
+Automatic background verification of repositories and wikis was added in
+GitLab EE 10.6 but is enabled by default only on GitLab EE 11.1. You can
+disable or enable this feature manually by following
+[these instructions](#disabling-or-enabling-the-automatic-background-verification).
+
+Automatic background verification ensures that the transferred data matches a
+calculated checksum. If the checksum of the data on the **primary** node matches checksum of the
+data on the **secondary** node, the data transferred successfully. Following a planned failover,
+any corrupted data may be **lost**, depending on the extent of the corruption.
+
+If verification fails on the **primary** node, this indicates that Geo is
+successfully replicating a corrupted object; restore it from backup or remove it
+it from the **primary** node to resolve the issue.
+
+If verification succeeds on the **primary** node but fails on the **secondary** node,
+this indicates that the object was corrupted during the replication process.
+Geo actively try to correct verification failures marking the repository to
+be resynced with a backoff period. If you want to reset the verification for
+these failures, so you should follow [these instructions][reset-verification].
+
+If verification is lagging significantly behind replication, consider giving
+the node more time before scheduling a planned failover.
+
+## Disabling or enabling the automatic background verification
+
+Run the following commands in a Rails console on the **primary** node:
+
+```sh
+gitlab-rails console
+```
+
+To check if automatic background verification is enabled:
+
+```ruby
+Gitlab::Geo.repository_verification_enabled?
+```
+
+To disable automatic background verification:
+
+```ruby
+Feature.disable('geo_repository_verification')
+```
+
+To enable automatic background verification:
+
+```ruby
+Feature.enable('geo_repository_verification')
+```
+
+## Repository verification
+
+Navigate to the **Admin Area > Geo** dashboard on the **primary** node and expand
+the **Verification information** tab for that node to view automatic checksumming
+status for repositories and wikis. Successes are shown in green, pending work
+in grey, and failures in red.
+
+![Verification status](img/verification-status-primary.png)
+
+Navigate to the **Admin Area > Geo** dashboard on the **secondary** node and expand
+the **Verification information** tab for that node to view automatic verification
+status for repositories and wikis. As with checksumming, successes are shown in
+green, pending work in grey, and failures in red.
+
+![Verification status](img/verification-status-secondary.png)
+
+## Using checksums to compare Geo nodes
+
+To check the health of Geo **secondary** nodes, we use a checksum over the list of
+Git references and their values. The checksum includes `HEAD`, `heads`, `tags`,
+`notes`, and GitLab-specific references to ensure true consistency. If two nodes
+have the same checksum, then they definitely hold the same references. We compute
+the checksum for every node after every update to make sure that they are all
+in sync.
+
+## Repository re-verification
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8550) in GitLab Enterprise Edition 11.6. Available in [GitLab Premium](https://about.gitlab.com/pricing/).
+
+Due to bugs or transient infrastructure failures, it is possible for Git
+repositories to change unexpectedly without being marked for verification.
+Geo constantly reverifies the repositories to ensure the integrity of the
+data. The default and recommended re-verification interval is 7 days, though
+an interval as short as 1 day can be set. Shorter intervals reduce risk but
+increase load and vice versa.
+
+Navigate to the **Admin Area > Geo** dashboard on the **primary** node, and
+click the **Edit** button for the **primary** node to customize the minimum
+re-verification interval:
+
+![Re-verification interval](img/reverification-interval.png)
+
+The automatic background re-verification is enabled by default, but you can
+disable if you need. Run the following commands in a Rails console on the
+**primary** node:
+
+```sh
+gitlab-rails console
+```
+
+To disable automatic background re-verification:
+
+```ruby
+Feature.disable('geo_repository_reverification')
+```
+
+To enable automatic background re-verification:
+
+```ruby
+Feature.enable('geo_repository_reverification')
+```
+
+## Reset verification for projects where verification has failed
+
+Geo actively try to correct verification failures marking the repository to
+be resynced with a backoff period. If you want to reset them manually, this
+rake task marks projects where verification has failed or the checksum mismatch
+to be resynced without the backoff period:
+
+For repositories:
+
+```sh
+sudo gitlab-rake geo:verification:repository:reset
+```
+
+For wikis:
+
+```sh
+sudo gitlab-rake geo:verification:wiki:reset
+```
+
+## Reconcile differences with checksum mismatches
+
+If the **primary** and **secondary** nodes have a checksum verification mismatch, the cause may not be apparent. To find the cause of a checksum mismatch:
+
+1. Navigate to the **Admin Area > Projects** dashboard on the **primary** node, find the
+ project that you want to check the checksum differences and click on the
+ **Edit** button:
+ ![Projects dashboard](img/checksum-differences-admin-projects.png)
+
+1. On the project admin page get the **Gitaly storage name**, and **Gitaly relative path**:
+ ![Project admin page](img/checksum-differences-admin-project-page.png)
+
+1. Navigate to the project's repository directory on both **primary** and **secondary** nodes (the path is usually `/var/opt/gitlab/git-data/repositories`). Note that if `git_data_dirs` is customized, check the directory layout on your server to be sure.
+
+ ```sh
+ cd /var/opt/gitlab/git-data/repositories
+ ```
+
+1. Run the following command on the **primary** node, redirecting the output to a file:
+
+ ```sh
+ git show-ref --head | grep -E "HEAD|(refs/(heads|tags|keep-around|merge-requests|environments|notes)/)" > primary-node-refs
+ ```
+
+1. Run the following command on the **secondary** node, redirecting the output to a file:
+
+ ```sh
+ git show-ref --head | grep -E "HEAD|(refs/(heads|tags|keep-around|merge-requests|environments|notes)/)" > secondary-node-refs
+ ```
+
+1. Copy the files from the previous steps on the same system, and do a diff between the contents:
+
+ ```sh
+ diff primary-node-refs secondary-node-refs
+ ```
+
+## Current limitations
+
+Until [issue #5064][ee-5064] is completed, background verification doesn't cover
+CI job artifacts and traces, LFS objects, or user uploads in file storage.
+Verify their integrity manually by following [these instructions][foreground-verification]
+on both nodes, and comparing the output between them.
+
+Data in object storage is **not verified**, as the object store is responsible
+for ensuring the integrity of the data.
+
+[reset-verification]: background_verification.md#reset-verification-for-projects-where-verification-has-failed
+[foreground-verification]: ../../raketasks/check.md
+[ee-5064]: https://gitlab.com/gitlab-org/gitlab-ee/issues/5064
diff --git a/doc/administration/geo/disaster_recovery/bring_primary_back.md b/doc/administration/geo/disaster_recovery/bring_primary_back.md
new file mode 100644
index 00000000000..f4d31a98080
--- /dev/null
+++ b/doc/administration/geo/disaster_recovery/bring_primary_back.md
@@ -0,0 +1,61 @@
+# Bring a demoted primary node back online **[PREMIUM ONLY]**
+
+After a failover, it is possible to fail back to the demoted **primary** node to
+restore your original configuration. This process consists of two steps:
+
+1. Making the old **primary** node a **secondary** node.
+1. Promoting a **secondary** node to a **primary** node.
+
+CAUTION: **Caution:**
+If you have any doubts about the consistency of the data on this node, we recommend setting it up from scratch.
+
+## Configure the former **primary** node to be a **secondary** node
+
+Since the former **primary** node will be out of sync with the current **primary** node, the first step is to bring the former **primary** node up to date. Note, deletion of data stored on disk like
+repositories and uploads will not be replayed when bringing the former **primary** node back
+into sync, which may result in increased disk usage.
+Alternatively, you can [set up a new **secondary** GitLab instance][setup-geo] to avoid this.
+
+To bring the former **primary** node up to date:
+
+1. SSH into the former **primary** node that has fallen behind.
+1. Make sure all the services are up:
+
+ ```sh
+ sudo gitlab-ctl start
+ ```
+
+ > **Note 1:** If you [disabled the **primary** node permanently][disaster-recovery-disable-primary],
+ > you need to undo those steps now. For Debian/Ubuntu you just need to run
+ > `sudo systemctl enable gitlab-runsvdir`. For CentOS 6, you need to install
+ > the GitLab instance from scratch and set it up as a **secondary** node by
+ > following [Setup instructions][setup-geo]. In this case, you don't need to follow the next step.
+ >
+ > **Note 2:** If you [changed the DNS records](index.md#step-4-optional-updating-the-primary-domain-dns-record)
+ > for this node during disaster recovery procedure you may need to [block
+ > all the writes to this node](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/doc/gitlab-geo/planned-failover.md#block-primary-traffic)
+ > during this procedure.
+
+1. [Setup database replication][database-replication]. Note that in this
+ case, **primary** node refers to the current **primary** node, and **secondary** node refers to the
+ former **primary** node.
+
+If you have lost your original **primary** node, follow the
+[setup instructions][setup-geo] to set up a new **secondary** node.
+
+## Promote the **secondary** node to **primary** node
+
+When the initial replication is complete and the **primary** node and **secondary** node are
+closely in sync, you can do a [planned failover].
+
+## Restore the **secondary** node
+
+If your objective is to have two nodes again, you need to bring your **secondary**
+node back online as well by repeating the first step
+([configure the former **primary** node to be a **secondary** node](#configure-the-former-primary-node-to-be-a-secondary-node))
+for the **secondary** node.
+
+[setup-geo]: ../replication/index.md#setup-instructions
+[database-replication]: ../replication/database.md
+[disaster-recovery-disable-primary]: index.md#step-2-permanently-disable-the-primary-node
+[planned failover]: planned_failover.md
diff --git a/doc/administration/geo/disaster_recovery/img/checksum-differences-admin-project-page.png b/doc/administration/geo/disaster_recovery/img/checksum-differences-admin-project-page.png
new file mode 100644
index 00000000000..fd51523104b
--- /dev/null
+++ b/doc/administration/geo/disaster_recovery/img/checksum-differences-admin-project-page.png
Binary files differ
diff --git a/doc/administration/geo/disaster_recovery/img/checksum-differences-admin-projects.png b/doc/administration/geo/disaster_recovery/img/checksum-differences-admin-projects.png
new file mode 100644
index 00000000000..b2a6da69d3d
--- /dev/null
+++ b/doc/administration/geo/disaster_recovery/img/checksum-differences-admin-projects.png
Binary files differ
diff --git a/doc/administration/geo/disaster_recovery/img/replication-status.png b/doc/administration/geo/disaster_recovery/img/replication-status.png
new file mode 100644
index 00000000000..d7085927c75
--- /dev/null
+++ b/doc/administration/geo/disaster_recovery/img/replication-status.png
Binary files differ
diff --git a/doc/administration/geo/disaster_recovery/img/reverification-interval.png b/doc/administration/geo/disaster_recovery/img/reverification-interval.png
new file mode 100644
index 00000000000..ad4597a4f49
--- /dev/null
+++ b/doc/administration/geo/disaster_recovery/img/reverification-interval.png
Binary files differ
diff --git a/doc/administration/geo/disaster_recovery/img/verification-status-primary.png b/doc/administration/geo/disaster_recovery/img/verification-status-primary.png
new file mode 100644
index 00000000000..2503408ec5d
--- /dev/null
+++ b/doc/administration/geo/disaster_recovery/img/verification-status-primary.png
Binary files differ
diff --git a/doc/administration/geo/disaster_recovery/img/verification-status-secondary.png b/doc/administration/geo/disaster_recovery/img/verification-status-secondary.png
new file mode 100644
index 00000000000..462274d8b14
--- /dev/null
+++ b/doc/administration/geo/disaster_recovery/img/verification-status-secondary.png
Binary files differ
diff --git a/doc/administration/geo/disaster_recovery/index.md b/doc/administration/geo/disaster_recovery/index.md
new file mode 100644
index 00000000000..71dc797f281
--- /dev/null
+++ b/doc/administration/geo/disaster_recovery/index.md
@@ -0,0 +1,322 @@
+# Disaster Recovery **[PREMIUM ONLY]**
+
+Geo replicates your database, your Git repositories, and few other assets.
+We will support and replicate more data in the future, that will enable you to
+failover with minimal effort, in a disaster situation.
+
+See [Geo current limitations][geo-limitations] for more information.
+
+CAUTION: **Warning:**
+Disaster recovery for multi-secondary configurations is in **Alpha**.
+For the latest updates, check the multi-secondary [Disaster Recovery epic][gitlab-org&65].
+
+## Promoting a **secondary** Geo node in single-secondary configurations
+
+We don't currently provide an automated way to promote a Geo replica and do a
+failover, but you can do it manually if you have `root` access to the machine.
+
+This process promotes a **secondary** Geo node to a **primary** node. To regain
+geographic redundancy as quickly as possible, you should add a new **secondary** node
+immediately after following these instructions.
+
+### Step 1. Allow replication to finish if possible
+
+If the **secondary** node is still replicating data from the **primary** node, follow
+[the planned failover docs][planned-failover] as closely as possible in
+order to avoid unnecessary data loss.
+
+### Step 2. Permanently disable the **primary** node
+
+CAUTION: **Warning:**
+If the **primary** node goes offline, there may be data saved on the **primary** node
+that has not been replicated to the **secondary** node. This data should be treated
+as lost if you proceed.
+
+If an outage on the **primary** node happens, you should do everything possible to
+avoid a split-brain situation where writes can occur in two different GitLab
+instances, complicating recovery efforts. So to prepare for the failover, we
+must disable the **primary** node.
+
+1. SSH into the **primary** node to stop and disable GitLab, if possible:
+
+ ```sh
+ sudo gitlab-ctl stop
+ ```
+
+ Prevent GitLab from starting up again if the server unexpectedly reboots:
+
+ ```sh
+ sudo systemctl disable gitlab-runsvdir
+ ```
+
+ > **CentOS only**: In CentOS 6 or older, there is no easy way to prevent GitLab from being
+ > started if the machine reboots isn't available (see [gitlab-org/omnibus-gitlab#3058]).
+ > It may be safest to uninstall the GitLab package completely:
+
+ ```sh
+ yum remove gitlab-ee
+ ```
+
+ > **Ubuntu 14.04 LTS**: If you are using an older version of Ubuntu
+ > or any other distro based on the Upstart init system, you can prevent GitLab
+ > from starting if the machine reboots by doing the following:
+
+ ```sh
+ initctl stop gitlab-runsvvdir
+ echo 'manual' > /etc/init/gitlab-runsvdir.override
+ initctl reload-configuration
+ ```
+
+1. If you do not have SSH access to the **primary** node, take the machine offline and
+ prevent it from rebooting by any means at your disposal.
+ Since there are many ways you may prefer to accomplish this, we will avoid a
+ single recommendation. You may need to:
+ - Reconfigure the load balancers.
+ - Change DNS records (e.g., point the primary DNS record to the **secondary**
+ node in order to stop usage of the **primary** node).
+ - Stop the virtual servers.
+ - Block traffic through a firewall.
+ - Revoke object storage permissions from the **primary** node.
+ - Physically disconnect a machine.
+
+1. If you plan to
+ [update the primary domain DNS record](#step-4-optional-updating-the-primary-domain-dns-record),
+ you may wish to lower the TTL now to speed up propagation.
+
+### Step 3. Promoting a **secondary** node
+
+NOTE: **Note:**
+A new **secondary** should not be added at this time. If you want to add a new
+**secondary**, do this after you have completed the entire process of promoting
+the **secondary** to the **primary**.
+
+#### Promoting a **secondary** node running on a single machine
+
+1. SSH in to your **secondary** node and login as root:
+
+ ```sh
+ sudo -i
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` to reflect its new status as **primary** by
+ removing any lines that enabled the `geo_secondary_role`:
+
+ ```ruby
+ ## In pre-11.5 documentation, the role was enabled as follows. Remove this line.
+ geo_secondary_role['enable'] = true
+
+ ## In 11.5+ documentation, the role was enabled as follows. Remove this line.
+ roles ['geo_secondary_role']
+ ```
+
+1. Promote the **secondary** node to the **primary** node. Execute:
+
+ ```sh
+ gitlab-ctl promote-to-primary-node
+ ```
+
+1. Verify you can connect to the newly promoted **primary** node using the URL used
+ previously for the **secondary** node.
+1. If successful, the **secondary** node has now been promoted to the **primary** node.
+
+#### Promoting a **secondary** node with HA
+
+The `gitlab-ctl promote-to-primary-node` command cannot be used yet in
+conjunction with High Availability or with multiple machines, as it can only
+perform changes on a **secondary** with only a single machine. Instead, you must
+do this manually.
+
+1. SSH in to the database node in the **secondary** and trigger PostgreSQL to
+ promote to read-write:
+
+ ```bash
+ sudo gitlab-pg-ctl promote
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` on every machine in the **secondary** to
+ reflect its new status as **primary** by removing any lines that enabled the
+ `geo_secondary_role`:
+
+ ```ruby
+ ## In pre-11.5 documentation, the role was enabled as follows. Remove this line.
+ geo_secondary_role['enable'] = true
+
+ ## In 11.5+ documentation, the role was enabled as follows. Remove this line.
+ roles ['geo_secondary_role']
+ ```
+
+ After making these changes [Reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) each
+ machine so the changes take effect.
+
+1. Promote the **secondary** to **primary**. SSH into a single application
+ server and execute:
+
+ ```bash
+ sudo gitlab-rake geo:set_secondary_as_primary
+ ```
+
+1. Verify you can connect to the newly promoted **primary** using the URL used
+ previously for the **secondary**.
+1. Success! The **secondary** has now been promoted to **primary**.
+
+### Step 4. (Optional) Updating the primary domain DNS record
+
+Updating the DNS records for the primary domain to point to the **secondary** node
+will prevent the need to update all references to the primary domain to the
+secondary domain, like changing Git remotes and API URLs.
+
+1. SSH into the **secondary** node and login as root:
+
+ ```sh
+ sudo -i
+ ```
+
+1. Update the primary domain's DNS record. After updating the primary domain's
+ DNS records to point to the **secondary** node, edit `/etc/gitlab/gitlab.rb` on the
+ **secondary** node to reflect the new URL:
+
+ ```ruby
+ # Change the existing external_url configuration
+ external_url 'https://<new_external_url>'
+ ```
+
+ NOTE: **Note**
+ Changing `external_url` won't prevent access via the old secondary URL, as
+ long as the secondary DNS records are still intact.
+
+1. Reconfigure the **secondary** node for the change to take effect:
+
+ ```sh
+ gitlab-ctl reconfigure
+ ```
+
+1. Execute the command below to update the newly promoted **primary** node URL:
+
+ ```sh
+ gitlab-rake geo:update_primary_node_url
+ ```
+
+ This command will use the changed `external_url` configuration defined
+ in `/etc/gitlab/gitlab.rb`.
+
+1. Verify you can connect to the newly promoted **primary** using its URL.
+ If you updated the DNS records for the primary domain, these changes may
+ not have yet propagated depending on the previous DNS records TTL.
+
+### Step 5. (Optional) Add **secondary** Geo node to a promoted **primary** node
+
+Promoting a **secondary** node to **primary** node using the process above does not enable
+Geo on the new **primary** node.
+
+To bring a new **secondary** node online, follow the [Geo setup instructions][setup-geo].
+
+### Step 6. (Optional) Removing the secondary's tracking database
+
+Every **secondary** has a special tracking database that is used to save the status of the synchronization of all the items from the **primary**.
+Because the **secondary** is already promoted, that data in the tracking database is no longer required.
+
+The data can be removed with the following command:
+
+```sh
+sudo rm -rf /var/opt/gitlab/geo-postgresql
+```
+
+## Promoting secondary Geo replica in multi-secondary configurations
+
+If you have more than one **secondary** node and you need to promote one of them, we suggest you follow
+[Promoting a **secondary** Geo node in single-secondary configurations](#promoting-a-secondary-geo-node-in-single-secondary-configurations)
+and after that you also need two extra steps.
+
+### Step 1. Prepare the new **primary** node to serve one or more **secondary** nodes
+
+1. SSH into the new **primary** node and login as root:
+
+ ```sh
+ sudo -i
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb`
+
+ ```ruby
+ ## Enable a Geo Primary role (if you haven't yet)
+ roles ['geo_primary_role']
+
+ ##
+ # Allow PostgreSQL client authentication from the primary and secondary IPs. These IPs may be
+ # public or VPC addresses in CIDR format, for example ['198.51.100.1/32', '198.51.100.2/32']
+ ##
+ postgresql['md5_auth_cidr_addresses'] = ['<primary_node_ip>/32', '<secondary_node_ip>/32']
+
+ # Every secondary server needs to have its own slot so specify the number of secondary nodes you're going to have
+ postgresql['max_replication_slots'] = 1
+
+ ##
+ ## Disable automatic database migrations temporarily
+ ## (until PostgreSQL is restarted and listening on the private address).
+ ##
+ gitlab_rails['auto_migrate'] = false
+
+ ```
+
+ (For more details about these settings you can read [Configure the primary server][configure-the-primary-server])
+
+1. Save the file and reconfigure GitLab for the database listen changes and
+ the replication slot changes to be applied.
+
+ ```sh
+ gitlab-ctl reconfigure
+ ```
+
+ Restart PostgreSQL for its changes to take effect:
+
+ ```sh
+ gitlab-ctl restart postgresql
+ ```
+
+1. Re-enable migrations now that PostgreSQL is restarted and listening on the
+ private address.
+
+ Edit `/etc/gitlab/gitlab.rb` and **change** the configuration to `true`:
+
+ ```ruby
+ gitlab_rails['auto_migrate'] = true
+ ```
+
+ Save the file and reconfigure GitLab:
+
+ ```sh
+ gitlab-ctl reconfigure
+ ```
+
+### Step 2. Initiate the replication process
+
+Now we need to make each **secondary** node listen to changes on the new **primary** node. To do that you need
+to [initiate the replication process][initiate-the-replication-process] again but this time
+for another **primary** node. All the old replication settings will be overwritten.
+
+## Troubleshooting
+
+### I followed the disaster recovery instructions and now two-factor auth is broken!
+
+The setup instructions for Geo prior to 10.5 failed to replicate the
+`otp_key_base` secret, which is used to encrypt the two-factor authentication
+secrets stored in the database. If it differs between **primary** and **secondary**
+nodes, users with two-factor authentication enabled won't be able to log in
+after a failover.
+
+If you still have access to the old **primary** node, you can follow the
+instructions in the
+[Upgrading to GitLab 10.5][updating-geo]
+section to resolve the error. Otherwise, the secret is lost and you'll need to
+[reset two-factor authentication for all users][sec-tfa].
+
+[gitlab-org&65]: https://gitlab.com/groups/gitlab-org/-/epics/65
+[geo-limitations]: ../replication/index.md#current-limitations
+[planned-failover]: planned_failover.md
+[setup-geo]: ../replication/index.md#setup-instructions
+[updating-geo]: ../replication/updating_the_geo_nodes.md#upgrading-to-gitlab-105
+[sec-tfa]: ../../../security/two_factor_authentication.md#disabling-2fa-for-everyone
+[gitlab-org/omnibus-gitlab#3058]: https://gitlab.com/gitlab-org/omnibus-gitlab/issues/3058
+[gitlab-org/gitlab-ee#4284]: https://gitlab.com/gitlab-org/gitlab-ee/issues/4284
+[initiate-the-replication-process]: ../replication/database.html#step-3-initiate-the-replication-process
+[configure-the-primary-server]: ../replication/database.html#step-1-configure-the-primary-server
diff --git a/doc/administration/geo/disaster_recovery/planned_failover.md b/doc/administration/geo/disaster_recovery/planned_failover.md
new file mode 100644
index 00000000000..b8071b5993f
--- /dev/null
+++ b/doc/administration/geo/disaster_recovery/planned_failover.md
@@ -0,0 +1,227 @@
+# Disaster recovery for planned failover **[PREMIUM ONLY]**
+
+The primary use-case of Disaster Recovery is to ensure business continuity in
+the event of unplanned outage, but it can be used in conjunction with a planned
+failover to migrate your GitLab instance between regions without extended
+downtime.
+
+As replication between Geo nodes is asynchronous, a planned failover requires
+a maintenance window in which updates to the **primary** node are blocked. The
+length of this window is determined by your replication capacity - once the
+**secondary** node is completely synchronized with the **primary** node, the failover can occur without
+data loss.
+
+This document assumes you already have a fully configured, working Geo setup.
+Please read it and the [Disaster Recovery][disaster-recovery] failover
+documentation in full before proceeding. Planned failover is a major operation,
+and if performed incorrectly, there is a high risk of data loss. Consider
+rehearsing the procedure until you are comfortable with the necessary steps and
+have a high degree of confidence in being able to perform them accurately.
+
+## Not all data is automatically replicated
+
+If you are using any GitLab features that Geo [doesn't support][limitations],
+you must make separate provisions to ensure that the **secondary** node has an
+up-to-date copy of any data associated with that feature. This may extend the
+required scheduled maintenance period significantly.
+
+A common strategy for keeping this period as short as possible for data stored
+in files is to use `rsync` to transfer the data. An initial `rsync` can be
+performed ahead of the maintenance window; subsequent `rsync`s (including a
+final transfer inside the maintenance window) will then transfer only the
+*changes* between the **primary** node and the **secondary** nodes.
+
+Repository-centric strategies for using `rsync` effectively can be found in the
+[moving repositories][moving-repositories] documentation; these strategies can
+be adapted for use with any other file-based data, such as GitLab Pages (to
+be found in `/var/opt/gitlab/gitlab-rails/shared/pages` if using Omnibus).
+
+## Pre-flight checks
+
+Follow these steps before scheduling a planned failover to ensure the process
+will go smoothly.
+
+### Object storage
+
+Some classes of non-repository data can use object storage in preference to
+file storage. Geo [does not replicate data in object storage](../replication/object_storage.md),
+leaving that task up to the object store itself. For a planned failover, this
+means you can decouple the replication of this data from the failover of the
+GitLab service.
+
+If you're already using object storage, simply verify that your **secondary**
+node has access to the same data as the **primary** node - they must either they share the
+same object storage configuration, or the **secondary** node should be configured to
+access a [geographically-replicated][os-repl] copy provided by the object store
+itself.
+
+If you have a large GitLab installation or cannot tolerate downtime, consider
+[migrating to Object Storage][os-conf] **before** scheduling a planned failover.
+Doing so reduces both the length of the maintenance window, and the risk of data
+loss as a result of a poorly executed planned failover.
+
+### Review the configuration of each **secondary** node
+
+Database settings are automatically replicated to the **secondary** node, but the
+`/etc/gitlab/gitlab.rb` file must be set up manually, and differs between
+nodes. If features such as Mattermost, OAuth or LDAP integration are enabled
+on the **primary** node but not the **secondary** node, they will be lost during failover.
+
+Review the `/etc/gitlab/gitlab.rb` file for both nodes and ensure the **secondary** node
+supports everything the **primary** node does **before** scheduling a planned failover.
+
+### Run system checks
+
+Run the following on both **primary** and **secondary** nodes:
+
+```sh
+gitlab-rake gitlab:check
+gitlab-rake gitlab:geo:check
+```
+
+If any failures are reported on either node, they should be resolved **before**
+scheduling a planned failover.
+
+### Check that secrets match between nodes
+
+The SSH host keys and `/etc/gitlab/gitlab-secrets.json` files should be
+identical on all nodes. Check this by running the following on all nodes and
+comparing the output:
+
+```sh
+sudo sha256sum /etc/ssh/ssh_host* /etc/gitlab/gitlab-secrets.json
+```
+
+If any files differ, replace the content on the **secondary** node with the
+content from the **primary** node.
+
+### Ensure Geo replication is up-to-date
+
+The maintenance window won't end until Geo replication and verification is
+completely finished. To keep the window as short as possible, you should
+ensure these processes are close to 100% as possible during active use.
+
+Navigate to the **Admin Area > Geo** dashboard on the **secondary** node to
+review status. Replicated objects (shown in green) should be close to 100%,
+and there should be no failures (shown in red). If a large proportion of
+objects aren't yet replicated (shown in grey), consider giving the node more
+time to complete
+
+![Replication status](img/replication-status.png)
+
+If any objects are failing to replicate, this should be investigated before
+scheduling the maintenance window. Following a planned failover, anything that
+failed to replicate will be **lost**.
+
+You can use the [Geo status API](../../../api/geo_nodes.md#retrieve-project-sync-or-verification-failures-that-occurred-on-the-current-node) to review failed objects and
+the reasons for failure.
+
+A common cause of replication failures is the data being missing on the
+**primary** node - you can resolve these failures by restoring the data from backup,
+or removing references to the missing data.
+
+### Verify the integrity of replicated data
+
+This [content was moved to another location][background-verification].
+
+### Notify users of scheduled maintenance
+
+On the **primary** node, navigate to **Admin Area > Messages**, add a broadcast
+message. You can check under **Admin Area > Geo** to estimate how long it
+will take to finish syncing. An example message would be:
+
+> A scheduled maintenance will take place at XX:XX UTC. We expect it to take
+> less than 1 hour.
+
+## Prevent updates to the **primary** node
+
+Until a [read-only mode][ce-19739] is implemented, updates must be prevented
+from happening manually. Note that your **secondary** node still needs read-only
+access to the **primary** node during the maintenance window.
+
+1. At the scheduled time, using your cloud provider or your node's firewall, block
+ all HTTP, HTTPS and SSH traffic to/from the **primary** node, **except** for your IP and
+ the **secondary** node's IP.
+
+ For instance, you might run the following commands on the server(s) making up your **primary** node:
+
+ ```sh
+ sudo iptables -A INPUT -p tcp -s <secondary_node_ip> --destination-port 22 -j ACCEPT
+ sudo iptables -A INPUT -p tcp -s <your_ip> --destination-port 22 -j ACCEPT
+ sudo iptables -A INPUT --destination-port 22 -j REJECT
+
+ sudo iptables -A INPUT -p tcp -s <secondary_node_ip> --destination-port 80 -j ACCEPT
+ sudo iptables -A INPUT -p tcp -s <your_ip> --destination-port 80 -j ACCEPT
+ sudo iptables -A INPUT --tcp-dport 80 -j REJECT
+
+ sudo iptables -A INPUT -p tcp -s <secondary_node_ip> --destination-port 443 -j ACCEPT
+ sudo iptables -A INPUT -p tcp -s <your_ip> --destination-port 443 -j ACCEPT
+ sudo iptables -A INPUT --tcp-dport 443 -j REJECT
+ ```
+
+ From this point, users will be unable to view their data or make changes on the
+ **primary** node. They will also be unable to log in to the **secondary** node.
+ However, existing sessions will work for the remainder of the maintenance period, and
+ public data will be accessible throughout.
+
+1. Verify the **primary** node is blocked to HTTP traffic by visiting it in browser via
+ another IP. The server should refuse connection.
+
+1. Verify the **primary** node is blocked to Git over SSH traffic by attempting to pull an
+ existing Git repository with an SSH remote URL. The server should refuse
+ connection.
+
+1. Disable non-Geo periodic background jobs on the primary node by navigating
+ to **Admin Area > Monitoring > Background Jobs > Cron** , pressing `Disable All`,
+ and then pressing `Enable` for the `geo_sidekiq_cron_config_worker` cron job.
+ This job will re-enable several other cron jobs that are essential for planned
+ failover to complete successfully.
+
+## Finish replicating and verifying all data
+
+1. If you are manually replicating any data not managed by Geo, trigger the
+ final replication process now.
+1. On the **primary** node, navigate to **Admin Area > Monitoring > Background Jobs > Queues**
+ and wait for all queues except those with `geo` in the name to drop to 0.
+ These queues contain work that has been submitted by your users; failing over
+ before it is completed will cause the work to be lost.
+1. On the **primary** node, navigate to **Admin Area > Geo** and wait for the
+ following conditions to be true of the **secondary** node you are failing over to:
+ - All replication meters to each 100% replicated, 0% failures.
+ - All verification meters reach 100% verified, 0% failures.
+ - Database replication lag is 0ms.
+ - The Geo log cursor is up to date (0 events behind).
+
+1. On the **secondary** node, navigate to **Admin Area > Monitoring > Background Jobs > Queues**
+ and wait for all the `geo` queues to drop to 0 queued and 0 running jobs.
+1. On the **secondary** node, use [these instructions][foreground-verification]
+ to verify the integrity of CI artifacts, LFS objects and uploads in file
+ storage.
+
+At this point, your **secondary** node will contain an up-to-date copy of everything the
+**primary** node has, meaning nothing will be lost when you fail over.
+
+## Promote the **secondary** node
+
+Finally, follow the [Disaster Recovery docs][disaster-recovery] to promote the
+**secondary** node to a **primary** node. This process will cause a brief outage on the **secondary** node, and users may need to log in again.
+
+Once it is completed, the maintenance window is over! Your new **primary** node will now
+begin to diverge from the old one. If problems do arise at this point, failing
+back to the old **primary** node [is possible][bring-primary-back], but likely to result
+in the loss of any data uploaded to the new primary in the meantime.
+
+Don't forget to remove the broadcast message after failover is complete.
+
+[bring-primary-back]: bring_primary_back.md
+[ce-19739]: https://gitlab.com/gitlab-org/gitlab-ce/issues/19739
+[container-registry]: ../replication/container_registry.md
+[disaster-recovery]: index.md
+[ee-4930]: https://gitlab.com/gitlab-org/gitlab-ee/issues/4930
+[ee-5064]: https://gitlab.com/gitlab-org/gitlab-ee/issues/5064
+[foreground-verification]: ../../raketasks/check.md
+[background-verification]: background_verification.md
+[limitations]: ../replication/index.md#current-limitations
+[moving-repositories]: ../../operations/moving_repositories.md
+[os-conf]: ../replication/object_storage.md#configuration
+[os-repl]: ../replication/object_storage.md#replication
diff --git a/doc/administration/geo/replication/configuration.md b/doc/administration/geo/replication/configuration.md
new file mode 100644
index 00000000000..3d4f69d3abe
--- /dev/null
+++ b/doc/administration/geo/replication/configuration.md
@@ -0,0 +1,308 @@
+# Geo configuration **[PREMIUM ONLY]**
+
+## Configuring a new **secondary** node
+
+NOTE: **Note:**
+This is the final step in setting up a **secondary** Geo node. Stages of the
+setup process must be completed in the documented order.
+Before attempting the steps in this stage, [complete all prior stages][setup-geo-omnibus].
+
+The basic steps of configuring a **secondary** node are to:
+
+- Replicate required configurations between the **primary** node and the **secondary** nodes.
+- Configure a tracking database on each **secondary** node.
+- Start GitLab on each **secondary** node.
+
+You are encouraged to first read through all the steps before executing them
+in your testing/production environment.
+
+> **Notes:**
+> - **Do not** setup any custom authentication for the **secondary** nodes. This will be
+ handled by the **primary** node.
+> - Any change that requires access to the **Admin Area** needs to be done in the
+ **primary** node because the **secondary** node is a read-only replica.
+
+### Step 1. Manually replicate secret GitLab values
+
+GitLab stores a number of secret values in the `/etc/gitlab/gitlab-secrets.json`
+file which *must* be the same on all nodes. Until there is
+a means of automatically replicating these between nodes (see issue [gitlab-org/gitlab-ee#3789]),
+they must be manually replicated to the **secondary** node.
+
+1. SSH into the **primary** node, and execute the command below:
+
+ ```sh
+ sudo cat /etc/gitlab/gitlab-secrets.json
+ ```
+
+ This will display the secrets that need to be replicated, in JSON format.
+
+1. SSH into the **secondary** node and login as the `root` user:
+
+ ```sh
+ sudo -i
+ ```
+
+1. Make a backup of any existing secrets:
+
+ ```sh
+ mv /etc/gitlab/gitlab-secrets.json /etc/gitlab/gitlab-secrets.json.`date +%F`
+ ```
+
+1. Copy `/etc/gitlab/gitlab-secrets.json` from the **primary** node to the **secondary** node, or
+ copy-and-paste the file contents between nodes:
+
+ ```sh
+ sudo editor /etc/gitlab/gitlab-secrets.json
+
+ # paste the output of the `cat` command you ran on the primary
+ # save and exit
+ ```
+
+1. Ensure the file permissions are correct:
+
+ ```sh
+ chown root:root /etc/gitlab/gitlab-secrets.json
+ chmod 0600 /etc/gitlab/gitlab-secrets.json
+ ```
+
+1. Reconfigure the **secondary** node for the change to take effect:
+
+ ```sh
+ gitlab-ctl reconfigure
+ gitlab-ctl restart
+ ```
+
+### Step 2. Manually replicate the **primary** node's SSH host keys
+
+GitLab integrates with the system-installed SSH daemon, designating a user
+(typically named git) through which all access requests are handled.
+
+In a [Disaster Recovery] situation, GitLab system
+administrators will promote a **secondary** node to the **primary** node. DNS records for the
+**primary** domain should also be updated to point to the new **primary** node
+(previously a **secondary** node). Doing so will avoid the need to update Git remotes and API URLs.
+
+This will cause all SSH requests to the newly promoted **primary** node to
+fail due to SSH host key mismatch. To prevent this, the primary SSH host
+keys must be manually replicated to the **secondary** node.
+
+1. SSH into the **secondary** node and login as the `root` user:
+
+ ```sh
+ sudo -i
+ ```
+
+1. Make a backup of any existing SSH host keys:
+
+ ```sh
+ find /etc/ssh -iname ssh_host_* -exec cp {} {}.backup.`date +%F` \;
+ ```
+
+1. Copy OpenSSH host keys from the **primary** node:
+
+ If you can access your **primary** node using the **root** user:
+
+ ```sh
+ # Run this from the secondary node, change `<primary_node_fqdn>` for the IP or FQDN of the server
+ scp root@<primary_node_fqdn>:/etc/ssh/ssh_host_*_key* /etc/ssh
+ ```
+
+ If you only have access through a user with **sudo** privileges:
+
+ ```sh
+ # Run this from your primary node:
+ sudo tar --transform 's/.*\///g' -zcvf ~/geo-host-key.tar.gz /etc/ssh/ssh_host_*_key*
+
+ # Run this from your secondary node:
+ scp <user_with_sudo>@<primary_node_fqdn>:geo-host-key.tar.gz .
+ tar zxvf ~/geo-host-key.tar.gz -C /etc/ssh
+ ```
+
+1. On your **secondary** node, ensure the file permissions are correct:
+
+ ```sh
+ chown root:root /etc/ssh/ssh_host_*_key*
+ chmod 0600 /etc/ssh/ssh_host_*_key*
+ ```
+
+1. To verify key fingerprint matches, execute the following command on both nodes:
+
+ ```sh
+ for file in /etc/ssh/ssh_host_*_key; do ssh-keygen -lf $file; done
+ ```
+
+ You should get an output similar to this one and they should be identical on both nodes:
+
+ ```sh
+ 1024 SHA256:FEZX2jQa2bcsd/fn/uxBzxhKdx4Imc4raXrHwsbtP0M root@serverhostname (DSA)
+ 256 SHA256:uw98R35Uf+fYEQ/UnJD9Br4NXUFPv7JAUln5uHlgSeY root@serverhostname (ECDSA)
+ 256 SHA256:sqOUWcraZQKd89y/QQv/iynPTOGQxcOTIXU/LsoPmnM root@serverhostname (ED25519)
+ 2048 SHA256:qwa+rgir2Oy86QI+PZi/QVR+MSmrdrpsuH7YyKknC+s root@serverhostname (RSA)
+ ```
+
+1. Verify that you have the correct public keys for the existing private keys:
+
+ ```sh
+ # This will print the fingerprint for private keys:
+ for file in /etc/ssh/ssh_host_*_key; do ssh-keygen -lf $file; done
+
+ # This will print the fingerprint for public keys:
+ for file in /etc/ssh/ssh_host_*_key.pub; do ssh-keygen -lf $file; done
+ ```
+
+ NOTE: **Note**:
+ The output for private keys and public keys command should generate the same fingerprint.
+
+1. Restart sshd on your **secondary** node:
+
+ ```sh
+ # Debian or Ubuntu installations
+ sudo service ssh reload
+
+ # CentOS installations
+ sudo service sshd reload
+ ```
+
+### Step 3. Add the **secondary** node
+
+1. Visit the **primary** node's **Admin Area > Geo**
+ (`/admin/geo/nodes`) in your browser.
+1. Add the **secondary** node by providing its full URL. **Do NOT** check the
+ **This is a primary node** checkbox.
+1. Optionally, choose which groups or storage shards should be replicated by the
+ **secondary** node. Leave blank to replicate all. Read more in
+ [selective synchronization](#selective-synchronization).
+1. Click the **Add node** button.
+1. SSH into your GitLab **secondary** server and restart the services:
+
+ ```sh
+ gitlab-ctl restart
+ ```
+
+ Check if there are any common issue with your Geo setup by running:
+
+ ```sh
+ gitlab-rake gitlab:geo:check
+ ```
+
+1. SSH into your **primary** server and login as root to verify the
+ **secondary** node is reachable or there are any common issue with your Geo setup:
+
+ ```sh
+ gitlab-rake gitlab:geo:check
+ ```
+
+Once added to the admin panel and restarted, the **secondary** node will automatically start
+replicating missing data from the **primary** node in a process known as **backfill**.
+Meanwhile, the **primary** node will start to notify each **secondary** node of any changes, so
+that the **secondary** node can act on those notifications immediately.
+
+Make sure the **secondary** node is running and accessible.
+You can login to the **secondary** node with the same credentials as used for the **primary** node.
+
+### Step 4. Enabling Hashed Storage
+
+Using Hashed Storage significantly improves Geo replication. Project and group
+renames no longer require synchronization between nodes.
+
+1. Visit the **primary** node's **Admin Area > Settings > Repository**
+ (`/admin/application_settings/repository`) in your browser.
+1. In the **Repository storage** section, check **Use hashed storage paths for newly created and renamed projects**.
+
+### Step 5. (Optional) Configuring the **secondary** node to trust the **primary** node
+
+You can safely skip this step if your **primary** node uses a CA-issued HTTPS certificate.
+
+If your **primary** node is using a self-signed certificate for *HTTPS* support, you will
+need to add that certificate to the **secondary** node's trust store. Retrieve the
+certificate from the **primary** node and follow
+[these instructions][omnibus-ssl]
+on the **secondary** node.
+
+### Step 6. Enable Git access over HTTP/HTTPS
+
+Geo synchronizes repositories over HTTP/HTTPS, and therefore requires this clone
+method to be enabled. Navigate to **Admin Area > Settings**
+(`/admin/application_settings`) on the **primary** node, and set
+`Enabled Git access protocols` to `Both SSH and HTTP(S)` or `Only HTTP(S)`.
+
+### Step 7. Verify proper functioning of the **secondary** node
+
+Your **secondary** node is now configured!
+
+You can login to the **secondary** node with the same credentials you used for the
+**primary** node. Visit the **secondary** node's **Admin Area > Geo**
+(`/admin/geo/nodes`) in your browser to check if it's correctly identified as a
+**secondary** Geo node and if Geo is enabled.
+
+The initial replication, or 'backfill', will probably still be in progress. You
+can monitor the synchronization process on each geo node from the **primary**
+node's Geo Nodes dashboard in your browser.
+
+![Geo dashboard](img/geo_node_dashboard.png)
+
+If your installation isn't working properly, check the
+[troubleshooting document].
+
+The two most obvious issues that can become apparent in the dashboard are:
+
+1. Database replication not working well.
+1. Instance to instance notification not working. In that case, it can be
+ something of the following:
+ - You are using a custom certificate or custom CA (see the
+ [troubleshooting document]).
+ - The instance is firewalled (check your firewall rules).
+
+Please note that disabling a **secondary** node will stop the synchronization process.
+
+Please note that if `git_data_dirs` is customized on the **primary** node for multiple
+repository shards you must duplicate the same configuration on each **secondary** node.
+
+Point your users to the ["Using a Geo Server" guide][using-geo].
+
+Currently, this is what is synced:
+
+- Git repositories.
+- Wikis.
+- LFS objects.
+- Issues, merge requests, snippets, and comment attachments.
+- Users, groups, and project avatars.
+
+## Selective synchronization
+
+Geo supports selective synchronization, which allows admins to choose
+which projects should be synchronized by **secondary** nodes.
+A subset of projects can be chosen, either by group or by storage shard. The
+former is ideal for replicating data belonging to a subset of users, while the
+latter is more suited to progressively rolling out Geo to a large GitLab
+instance.
+
+It is important to note that selective synchronization:
+
+1. Does not restrict permissions from **secondary** nodes.
+1. Does not hide project metadata from **secondary** nodes.
+ - Since Geo currently relies on PostgreSQL replication, all project metadata
+ gets replicated to **secondary** nodes, but repositories that have not been
+ selected will be empty.
+1. Does not reduce the number of events generated for the Geo event log.
+ - The **primary** node generates events as long as any **secondary** nodes are present.
+ Selective synchronization restrictions are implemented on the **secondary** nodes,
+ not the **primary** node.
+
+## Upgrading Geo
+
+See the [updating the Geo nodes document](updating_the_geo_nodes.md).
+
+## Troubleshooting
+
+See the [troubleshooting document](troubleshooting.md).
+
+[setup-geo-omnibus]: index.md#using-omnibus-gitlab
+[Hashed Storage]: ../../repository_storage_types.md
+[Disaster Recovery]: ../disaster_recovery/index.md
+[gitlab-org/gitlab-ee#3789]: https://gitlab.com/gitlab-org/gitlab-ee/issues/3789
+[gitlab-com/infrastructure#2821]: https://gitlab.com/gitlab-com/infrastructure/issues/2821
+[omnibus-ssl]: https://docs.gitlab.com/omnibus/settings/ssl.html
+[troubleshooting document]: troubleshooting.md
+[using-geo]: using_a_geo_server.md
diff --git a/doc/administration/geo/replication/database.md b/doc/administration/geo/replication/database.md
new file mode 100644
index 00000000000..1e5a56c3f4e
--- /dev/null
+++ b/doc/administration/geo/replication/database.md
@@ -0,0 +1,508 @@
+# Geo database replication **[PREMIUM ONLY]**
+
+NOTE: **Note:**
+The following steps are for Omnibus installs only. Using Geo with source-based installs was **deprecated** in GitLab 11.5.
+
+NOTE: **Note:**
+If your GitLab installation uses external (not managed by Omnibus) PostgreSQL
+instances, the Omnibus roles will not be able to perform all necessary
+configuration steps. In this case,
+[follow the Geo with external PostgreSQL instances document instead](external_database.md).
+
+NOTE: **Note:**
+The stages of the setup process must be completed in the documented order.
+Before attempting the steps in this stage, [complete all prior stages][toc].
+
+This document describes the minimal steps you have to take in order to
+replicate your **primary** GitLab database to a **secondary** node's database. You may
+have to change some values according to your database setup, how big it is, etc.
+
+You are encouraged to first read through all the steps before executing them
+in your testing/production environment.
+
+## PostgreSQL replication
+
+The GitLab **primary** node where the write operations happen will connect to
+the **primary** database server, and **secondary** nodes will
+connect to their own database servers (which are also read-only).
+
+NOTE: **Note:**
+In database documentation, you may see "**primary**" being referenced as "master"
+and "**secondary**" as either "slave" or "standby" server (read-only).
+
+We recommend using [PostgreSQL replication slots][replication-slots-article]
+to ensure that the **primary** node retains all the data necessary for the **secondary** nodes to
+recover. See below for more details.
+
+The following guide assumes that:
+
+- You are using Omnibus and therefore you are using PostgreSQL 9.6 or later
+ which includes the [`pg_basebackup` tool][pgback] and improved
+ [Foreign Data Wrapper][FDW] support.
+- You have a **primary** node already set up (the GitLab server you are
+ replicating from), running Omnibus' PostgreSQL (or equivalent version), and
+ you have a new **secondary** server set up with the same versions of the OS,
+ PostgreSQL, and GitLab on all nodes.
+
+CAUTION: **Warning:**
+Geo works with streaming replication. Logical replication is not supported at this time.
+There is an [issue where support is being discussed](https://gitlab.com/gitlab-org/gitlab-ee/issues/7420).
+
+### Step 1. Configure the **primary** server
+
+1. SSH into your GitLab **primary** server and login as root:
+
+ ```sh
+ sudo -i
+ ```
+
+1. Execute the command below to define the node as **primary** node:
+
+ ```sh
+ gitlab-ctl set-geo-primary-node
+ ```
+
+ This command will use your defined `external_url` in `/etc/gitlab/gitlab.rb`.
+
+1. GitLab 10.4 and up only: Do the following to make sure the `gitlab` database user has a password defined:
+
+ Generate a MD5 hash of the desired password:
+
+ ```sh
+ gitlab-ctl pg-password-md5 gitlab
+ # Enter password: <your_password_here>
+ # Confirm password: <your_password_here>
+ # fca0b89a972d69f00eb3ec98a5838484
+ ```
+
+ Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ # Fill with the hash generated by `gitlab-ctl pg-password-md5 gitlab`
+ postgresql['sql_user_password'] = '<md5_hash_of_your_password>'
+
+ # Every node that runs Unicorn or Sidekiq needs to have the database
+ # password specified as below. If you have a high-availability setup, this
+ # must be present in all application nodes.
+ gitlab_rails['db_password'] = '<your_password_here>'
+ ```
+
+1. Omnibus GitLab already has a [replication user]
+ called `gitlab_replicator`. You must set the password for this user manually.
+ You will be prompted to enter a password:
+
+ ```sh
+ gitlab-ctl set-replication-password
+ ```
+
+ This command will also read the `postgresql['sql_replication_user']` Omnibus
+ setting in case you have changed `gitlab_replicator` username to something
+ else.
+
+ If you are using an external database not managed by Omnibus GitLab, you need
+ to create the replicator user and define a password to it manually:
+
+ ```sql
+ --- Create a new user 'replicator'
+ CREATE USER gitlab_replicator;
+
+ --- Set/change a password and grants replication privilege
+ ALTER USER gitlab_replicator WITH REPLICATION ENCRYPTED PASSWORD '<replication_password>';
+ ```
+
+1. Configure PostgreSQL to listen on network interfaces:
+
+ For security reasons, PostgreSQL does not listen on any network interfaces
+ by default. However, Geo requires the **secondary** node to be able to
+ connect to the **primary** node's database. For this reason, we need the address of
+ each node. Note: For external PostgreSQL instances, see [additional instructions](external_database.md).
+
+ If you are using a cloud provider, you can lookup the addresses for each
+ Geo node through your cloud provider's management console.
+
+ To lookup the address of a Geo node, SSH in to the Geo node and execute:
+
+ ```sh
+ ##
+ ## Private address
+ ##
+ ip route get 255.255.255.255 | awk '{print "Private address:", $NF; exit}'
+
+ ##
+ ## Public address
+ ##
+ echo "External address: $(curl --silent ipinfo.io/ip)"
+ ```
+
+ In most cases, the following addresses will be used to configure GitLab
+ Geo:
+
+ | Configuration | Address |
+ |:----------------------------------------|:------------------------------------------------------|
+ | `postgresql['listen_address']` | **Primary** node's public or VPC private address. |
+ | `postgresql['md5_auth_cidr_addresses']` | **Secondary** node's public or VPC private addresses. |
+
+ If you are using Google Cloud Platform, SoftLayer, or any other vendor that
+ provides a virtual private cloud (VPC) you can use the **secondary** node's private
+ address (corresponds to "internal address" for Google Cloud Platform) for
+ `postgresql['md5_auth_cidr_addresses']` and `postgresql['listen_address']`.
+
+ The `listen_address` option opens PostgreSQL up to network connections
+ with the interface corresponding to the given address. See [the PostgreSQL
+ documentation][pg-docs-runtime-conn] for more details.
+
+ Depending on your network configuration, the suggested addresses may not
+ be correct. If your **primary** node and **secondary** nodes connect over a local
+ area network, or a virtual network connecting availability zones like
+ [Amazon's VPC](https://aws.amazon.com/vpc/) or [Google's VPC](https://cloud.google.com/vpc/)
+ you should use the **secondary** node's private address for `postgresql['md5_auth_cidr_addresses']`.
+
+ Edit `/etc/gitlab/gitlab.rb` and add the following, replacing the IP
+ addresses with addresses appropriate to your network configuration:
+
+ ```ruby
+ ##
+ ## Geo Primary role
+ ## - configure dependent flags automatically to enable Geo
+ ##
+ roles ['geo_primary_role']
+
+ ##
+ ## Primary address
+ ## - replace '<primary_node_ip>' with the public or VPC address of your Geo primary node
+ ##
+ postgresql['listen_address'] = '<primary_node_ip>'
+
+ ##
+ # Allow PostgreSQL client authentication from the primary and secondary IPs. These IPs may be
+ # public or VPC addresses in CIDR format, for example ['198.51.100.1/32', '198.51.100.2/32']
+ ##
+ postgresql['md5_auth_cidr_addresses'] = ['<primary_node_ip>/32', '<secondary_node_ip>/32']
+
+ ##
+ ## Replication settings
+ ## - set this to be the number of Geo secondary nodes you have
+ ##
+ postgresql['max_replication_slots'] = 1
+ # postgresql['max_wal_senders'] = 10
+ # postgresql['wal_keep_segments'] = 10
+
+ ##
+ ## Disable automatic database migrations temporarily
+ ## (until PostgreSQL is restarted and listening on the private address).
+ ##
+ gitlab_rails['auto_migrate'] = false
+ ```
+
+1. Optional: If you want to add another **secondary** node, the relevant setting would look like:
+
+ ```ruby
+ postgresql['md5_auth_cidr_addresses'] = ['<primary_node_ip>/32', '<secondary_node_ip>/32', '<another_secondary_node_ip>/32']
+ ```
+
+ You may also want to edit the `wal_keep_segments` and `max_wal_senders` to
+ match your database replication requirements. Consult the [PostgreSQL -
+ Replication documentation][pg-docs-runtime-replication]
+ for more information.
+
+1. Save the file and reconfigure GitLab for the database listen changes and
+ the replication slot changes to be applied:
+
+ ```sh
+ gitlab-ctl reconfigure
+ ```
+
+ Restart PostgreSQL for its changes to take effect:
+
+ ```sh
+ gitlab-ctl restart postgresql
+ ```
+
+1. Re-enable migrations now that PostgreSQL is restarted and listening on the
+ private address.
+
+ Edit `/etc/gitlab/gitlab.rb` and **change** the configuration to `true`:
+
+ ```ruby
+ gitlab_rails['auto_migrate'] = true
+ ```
+
+ Save the file and reconfigure GitLab:
+
+ ```sh
+ gitlab-ctl reconfigure
+ ```
+
+1. Now that the PostgreSQL server is set up to accept remote connections, run
+ `netstat -plnt | grep 5432` to make sure that PostgreSQL is listening on port
+ `5432` to the **primary** server's private address.
+
+1. A certificate was automatically generated when GitLab was reconfigured. This
+ will be used automatically to protect your PostgreSQL traffic from
+ eavesdroppers, but to protect against active ("man-in-the-middle") attackers,
+ the **secondary** node needs a copy of the certificate. Make a copy of the PostgreSQL
+ `server.crt` file on the **primary** node by running this command:
+
+ ```sh
+ cat ~gitlab-psql/data/server.crt
+ ```
+
+ Copy the output into a clipboard or into a local file. You
+ will need it when setting up the **secondary** node! The certificate is not sensitive
+ data.
+
+### Step 2. Configure the **secondary** server
+
+1. SSH into your GitLab **secondary** server and login as root:
+
+ ```
+ sudo -i
+ ```
+
+1. Stop application server and Sidekiq
+
+ ```
+ gitlab-ctl stop unicorn
+ gitlab-ctl stop sidekiq
+ ```
+
+ NOTE: **Note**:
+ This step is important so we don't try to execute anything before the node is fully configured.
+
+1. [Check TCP connectivity][rake-maintenance] to the **primary** node's PostgreSQL server:
+
+ ```sh
+ gitlab-rake gitlab:tcp_check[<primary_node_ip>,5432]
+ ```
+
+ NOTE: **Note**:
+ If this step fails, you may be using the wrong IP address, or a firewall may
+ be preventing access to the server. Check the IP address, paying close
+ attention to the difference between public and private addresses and ensure
+ that, if a firewall is present, the **secondary** node is permitted to connect to the
+ **primary** node on port 5432.
+
+1. Create a file `server.crt` in the **secondary** server, with the content you got on the last step of the **primary** node's setup:
+
+ ```
+ editor server.crt
+ ```
+
+1. Set up PostgreSQL TLS verification on the **secondary** node:
+
+ Install the `server.crt` file:
+
+ ```sh
+ install \
+ -D \
+ -o gitlab-psql \
+ -g gitlab-psql \
+ -m 0400 \
+ -T server.crt ~gitlab-psql/.postgresql/root.crt
+ ```
+
+ PostgreSQL will now only recognize that exact certificate when verifying TLS
+ connections. The certificate can only be replicated by someone with access
+ to the private key, which is **only** present on the **primary** node.
+
+1. Test that the `gitlab-psql` user can connect to the **primary** node's database
+ (the default Omnibus database name is gitlabhq_production):
+
+ ```sh
+ sudo \
+ -u gitlab-psql /opt/gitlab/embedded/bin/psql \
+ --list \
+ -U gitlab_replicator \
+ -d "dbname=gitlabhq_production sslmode=verify-ca" \
+ -W \
+ -h <primary_node_ip>
+ ```
+
+ When prompted enter the password you set in the first step for the
+ `gitlab_replicator` user. If all worked correctly, you should see
+ the list of **primary** node's databases.
+
+ A failure to connect here indicates that the TLS configuration is incorrect.
+ Ensure that the contents of `~gitlab-psql/data/server.crt` on the **primary** node
+ match the contents of `~gitlab-psql/.postgresql/root.crt` on the **secondary** node.
+
+1. Configure PostgreSQL to enable FDW support:
+
+ This step is similar to how we configured the **primary** instance.
+ We need to enable this, to enable FDW support, even if using a single node.
+
+ Edit `/etc/gitlab/gitlab.rb` and add the following, replacing the IP
+ addresses with addresses appropriate to your network configuration:
+
+ ```ruby
+ ##
+ ## Geo Secondary role
+ ## - configure dependent flags automatically to enable Geo
+ ##
+ roles ['geo_secondary_role']
+
+ ##
+ ## Secondary address
+ ## - replace '<secondary_node_ip>' with the public or VPC address of your Geo secondary node
+ ##
+ postgresql['listen_address'] = '<secondary_node_ip>'
+ postgresql['md5_auth_cidr_addresses'] = ['<secondary_node_ip>/32']
+
+ ##
+ ## Database credentials password (defined previously in primary node)
+ ## - replicate same values here as defined in primary node
+ ##
+ postgresql['sql_user_password'] = '<md5_hash_of_your_password>'
+ gitlab_rails['db_password'] = '<your_password_here>'
+
+ ##
+ ## Enable FDW support for the Geo Tracking Database (improves performance)
+ ##
+ geo_secondary['db_fdw'] = true
+ ```
+
+ For external PostgreSQL instances, see [additional instructions](external_database.md).
+ If you bring a former **primary** node back online to serve as a **secondary** node, then you also need to remove `roles ['geo_primary_role']` or `geo_primary_role['enable'] = true`.
+
+1. Reconfigure GitLab for the changes to take effect:
+
+ ```sh
+ gitlab-ctl reconfigure
+ ```
+
+1. Restart PostgreSQL for the IP change to take effect and reconfigure again:
+
+ ```sh
+ gitlab-ctl restart postgresql
+ gitlab-ctl reconfigure
+ ```
+
+ This last reconfigure will provision the FDW configuration and enable it.
+
+### Step 3. Initiate the replication process
+
+Below we provide a script that connects the database on the **secondary** node to
+the database on the **primary** node, replicates the database, and creates the
+needed files for streaming replication.
+
+The directories used are the defaults that are set up in Omnibus. If you have
+changed any defaults, configure it as you see fit replacing the directories and paths.
+
+CAUTION: **Warning:**
+Make sure to run this on the **secondary** server as it removes all PostgreSQL's
+data before running `pg_basebackup`.
+
+1. SSH into your GitLab **secondary** server and login as root:
+
+ ```sh
+ sudo -i
+ ```
+
+1. Choose a database-friendly name to use for your **secondary** node to
+ use as the replication slot name. For example, if your domain is
+ `secondary.geo.example.com`, you may use `secondary_example` as the slot
+ name as shown in the commands below.
+
+1. Execute the command below to start a backup/restore and begin the replication
+ CAUTION: **Warning:** Each Geo **secondary** node must have its own unique replication slot name.
+ Using the same slot name between two secondaries will break PostgreSQL replication.
+
+ ```sh
+ gitlab-ctl replicate-geo-database \
+ --slot-name=<secondary_node_name> \
+ --host=<primary_node_ip>
+ ```
+
+ When prompted, enter the _plaintext_ password you set up for the `gitlab_replicator`
+ user in the first step.
+
+ This command also takes a number of additional options. You can use `--help`
+ to list them all, but here are a couple of tips:
+ - If PostgreSQL is listening on a non-standard port, add `--port=` as well.
+ - If your database is too large to be transferred in 30 minutes, you will need
+ to increase the timeout, e.g., `--backup-timeout=3600` if you expect the
+ initial replication to take under an hour.
+ - Pass `--sslmode=disable` to skip PostgreSQL TLS authentication altogether
+ (e.g., you know the network path is secure, or you are using a site-to-site
+ VPN). This is **not** safe over the public Internet!
+ - You can read more details about each `sslmode` in the
+ [PostgreSQL documentation][pg-docs-ssl];
+ the instructions above are carefully written to ensure protection against
+ both passive eavesdroppers and active "man-in-the-middle" attackers.
+ - Change the `--slot-name` to the name of the replication slot
+ to be used on the **primary** database. The script will attempt to create the
+ replication slot automatically if it does not exist.
+ - If you're repurposing an old server into a Geo **secondary** node, you'll need to
+ add `--force` to the command line.
+ - When not in a production machine you can disable backup step if you
+ really sure this is what you want by adding `--skip-backup`
+
+The replication process is now complete.
+
+## PGBouncer support (optional)
+
+[PGBouncer](http://pgbouncer.github.io/) may be used with GitLab Geo to pool
+PostgreSQL connections. We recommend using PGBouncer if you use GitLab in a
+high-availability configuration with a cluster of nodes supporting a Geo
+**primary** node and another cluster of nodes supporting a Geo **secondary** node. For more
+information, see [High Availability with GitLab Omnibus](../../high_availability/database.md#high-availability-with-gitlab-omnibus-premium-only).
+
+For a Geo **secondary** node to work properly with PGBouncer in front of the database,
+it will need a separate read-only user to make [PostgreSQL FDW queries][FDW]
+work:
+
+1. On the **primary** Geo database, enter the PostgreSQL on the console as an
+ admin user. If you are using an Omnibus-managed database, log onto the **primary**
+ node that is running the PostgreSQL database (the default Omnibus database name is gitlabhq_production):
+
+ ```sh
+ sudo \
+ -u gitlab-psql /opt/gitlab/embedded/bin/psql \
+ -h /var/opt/gitlab/postgresql gitlabhq_production
+ ```
+
+1. Then create the read-only user:
+
+ ```sql
+ -- NOTE: Use the password defined earlier
+ CREATE USER gitlab_geo_fdw WITH password 'mypassword';
+ GRANT CONNECT ON DATABASE gitlabhq_production to gitlab_geo_fdw;
+ GRANT USAGE ON SCHEMA public TO gitlab_geo_fdw;
+ GRANT SELECT ON ALL TABLES IN SCHEMA public TO gitlab_geo_fdw;
+ GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO gitlab_geo_fdw;
+
+ -- Tables created by "gitlab" should be made read-only for "gitlab_geo_fdw"
+ -- automatically.
+ ALTER DEFAULT PRIVILEGES FOR USER gitlab IN SCHEMA public GRANT SELECT ON TABLES TO gitlab_geo_fdw;
+ ALTER DEFAULT PRIVILEGES FOR USER gitlab IN SCHEMA public GRANT SELECT ON SEQUENCES TO gitlab_geo_fdw;
+ ```
+
+1. On the **secondary** nodes, change `/etc/gitlab/gitlab.rb`:
+
+ ```
+ geo_postgresql['fdw_external_user'] = 'gitlab_geo_fdw'
+ ```
+
+1. Save the file and reconfigure GitLab for the changes to be applied:
+
+ ```sh
+ gitlab-ctl reconfigure
+ ```
+
+## MySQL replication
+
+MySQL replication is not supported for Geo.
+
+## Troubleshooting
+
+Read the [troubleshooting document](troubleshooting.md).
+
+[replication-slots-article]: https://medium.com/@tk512/replication-slots-in-postgresql-b4b03d277c75
+[pgback]: http://www.postgresql.org/docs/9.2/static/app-pgbasebackup.html
+[replication user]:https://wiki.postgresql.org/wiki/Streaming_Replication
+[FDW]: https://www.postgresql.org/docs/9.6/static/postgres-fdw.html
+[toc]: index.md#using-omnibus-gitlab
+[rake-maintenance]: ../../raketasks/maintenance.md
+[pg-docs-ssl]: https://www.postgresql.org/docs/9.6/static/libpq-ssl.html#LIBPQ-SSL-PROTECTION
+[pg-docs-runtime-conn]: https://www.postgresql.org/docs/9.6/static/runtime-config-connection.html
+[pg-docs-runtime-replication]: https://www.postgresql.org/docs/9.6/static/runtime-config-replication.html
diff --git a/doc/administration/geo/replication/docker_registry.md b/doc/administration/geo/replication/docker_registry.md
new file mode 100644
index 00000000000..5b02b861c61
--- /dev/null
+++ b/doc/administration/geo/replication/docker_registry.md
@@ -0,0 +1,23 @@
+# Docker Registry for a secondary node **[PREMIUM ONLY]**
+
+You can set up a [Docker Registry] on your
+**secondary** Geo node that mirrors the one on the **primary** Geo node.
+
+## Storage support
+
+CAUTION: **Warning:**
+If you use [local storage][registry-storage]
+for the Container Registry you **cannot** replicate it to a **secondary** node.
+
+Docker Registry currently supports a few types of storages. If you choose a
+distributed storage (`azure`, `gcs`, `s3`, `swift`, or `oss`) for your Docker
+Registry on the **primary** node, you can use the same storage for a **secondary**
+Docker Registry as well. For more information, read the
+[Load balancing considerations][registry-load-balancing]
+when deploying the Registry, and how to set up the storage driver for GitLab's
+integrated [Container Registry][registry-storage].
+
+[ee]: https://about.gitlab.com/pricing/
+[Docker Registry]: https://docs.docker.com/registry/
+[registry-storage]: ../../container_registry.md#container-registry-storage-driver
+[registry-load-balancing]: https://docs.docker.com/registry/deploying/#load-balancing-considerations
diff --git a/doc/administration/geo/replication/external_database.md b/doc/administration/geo/replication/external_database.md
new file mode 100644
index 00000000000..177ca68613e
--- /dev/null
+++ b/doc/administration/geo/replication/external_database.md
@@ -0,0 +1,219 @@
+# Geo with external PostgreSQL instances **[PREMIUM ONLY]**
+
+This document is relevant if you are using a PostgreSQL instance that is *not
+managed by Omnibus*. This includes cloud-managed instances like AWS RDS, or
+manually installed and configured PostgreSQL instances.
+
+NOTE: **Note**:
+We strongly recommend running Omnibus-managed instances as they are actively
+developed and tested. We aim to be compatible with most external
+(not managed by Omnibus) databases but we do not guarantee compatibility.
+
+## **Primary** node
+
+1. SSH into a GitLab **primary** application server and login as root:
+
+ ```sh
+ sudo -i
+ ```
+
+1. Execute the command below to define the node as **primary** node:
+
+ ```sh
+ gitlab-ctl set-geo-primary-node
+ ```
+
+ This command will use your defined `external_url` in `/etc/gitlab/gitlab.rb`.
+
+
+### Configure the external database to be replicated
+
+To set up an external database, you can either:
+
+- Set up streaming replication yourself (for example, in AWS RDS).
+- Perform the Omnibus configuration manually as follows.
+
+#### Leverage your cloud provider's tools to replicate the primary database
+
+Given you have a primary node set up on AWS EC2 that uses RDS.
+You can now just create a read-only replica in a different region and the
+replication process will be managed by AWS. Make sure you've set Network ACL, Subnet, and
+Security Group according to your needs, so the secondary application node can access the database.
+Skip to the [Configure secondary application node](#configure-secondary-application-nodes-to-use-the-external-read-replica) section below.
+
+#### Manually configure the primary database for replication
+
+The [geo_primary_role](https://docs.gitlab.com/omnibus/roles/#gitlab-geo-roles)
+configures the **primary** node's database to be replicated by making changes to
+`pg_hba.conf` and `postgresql.conf`. Make the following configuration changes
+manually to your external database configuration:
+
+```
+##
+## Geo Primary Role
+## - pg_hba.conf
+##
+host replication gitlab_replicator <trusted secondary IP>/32 md5
+```
+
+```
+##
+## Geo Primary Role
+## - postgresql.conf
+##
+sql_replication_user = gitlab_replicator
+wal_level = hot_standby
+max_wal_senders = 10
+wal_keep_segments = 50
+max_replication_slots = 1 # number of secondary instances
+hot_standby = on
+```
+
+## **Secondary** nodes
+
+### Manually configure the replica database
+
+Make the following configuration changes manually to your `postgresql.conf`
+of external replica database:
+
+```
+##
+## Geo Secondary Role
+## - postgresql.conf
+##
+wal_level = hot_standby
+max_wal_senders = 10
+wal_keep_segments = 10
+hot_standby = on
+```
+
+### Configure **secondary** application nodes to use the external read-replica
+
+With Omnibus, the
+[geo_secondary_role](https://docs.gitlab.com/omnibus/roles/#gitlab-geo-roles)
+has three main functions:
+
+1. Configure the replica database.
+1. Configure the tracking database.
+1. Enable the [Geo Log Cursor](index.md#geo-log-cursor) (not covered in this section).
+
+To configure the connection to the external read-replica database and enable Log Cursor:
+
+1. SSH into a GitLab **secondary** application server and login as root:
+
+ ```bash
+ sudo -i
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following
+
+ ```ruby
+ ##
+ ## Geo Secondary role
+ ## - configure dependent flags automatically to enable Geo
+ ##
+ roles ['geo_secondary_role']
+
+ # note this is shared between both databases,
+ # make sure you define the same password in both
+ gitlab_rails['db_password'] = '<your_password_here>'
+
+ gitlab_rails['db_username'] = 'gitlab'
+ gitlab_rails['db_host'] = '<database_read_replica_host>'
+ ```
+1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure)
+
+### Configure the tracking database
+
+**Secondary** nodes use a separate PostgreSQL installation as a tracking
+database to keep track of replication status and automatically recover from
+potential replication issues. Omnibus automatically configures a tracking database
+when `roles ['geo_secondary_role']` is set. For high availability,
+refer to [Geo High Availability](../../high_availability/README.md).
+If you want to run this database external to Omnibus, please follow the instructions below.
+
+The tracking database requires an [FDW](https://www.postgresql.org/docs/9.6/static/postgres-fdw.html)
+connection with the **secondary** replica database for improved performance.
+
+If you have an external database ready to be used as the tracking database,
+follow the instructions below to use it:
+
+NOTE: **Note:**
+If you want to use AWS RDS as a tracking database, make sure it has access to
+the secondary database. Unfortunately, just assigning the same security group is not enough as
+outbound rules do not apply to RDS PostgreSQL databases. Therefore, you need to explicitly add an inbound
+rule to the read-replica's security group allowing any TCP traffic from
+the tracking database on port 5432.
+
+1. SSH into a GitLab **secondary** server and login as root:
+
+ ```bash
+ sudo -i
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` with the connection params and credentials for
+ the machine with the PostgreSQL instance:
+
+ ```ruby
+ geo_secondary['db_username'] = 'gitlab_geo'
+ geo_secondary['db_password'] = '<your_password_here>'
+
+ geo_secondary['db_host'] = '<tracking_database_host>'
+ geo_secondary['db_port'] = <tracking_database_port> # change to the correct port
+ geo_secondary['db_fdw'] = true # enable FDW
+ geo_postgresql['enable'] = false # don't use internal managed instance
+ ```
+
+1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure)
+
+1. Run the tracking database migrations:
+
+ ```bash
+ gitlab-rake geo:db:create
+ gitlab-rake geo:db:migrate
+ ```
+
+1. Configure the
+ [PostgreSQL FDW](https://www.postgresql.org/docs/9.6/static/postgres-fdw.html)
+ connection and credentials:
+
+ Save the script below in a file, ex. `/tmp/geo_fdw.sh` and modify the connection
+ params to match your environment. Execute it to set up the FDW connection.
+
+ ```bash
+ #!/bin/bash
+
+ # Secondary Database connection params:
+ DB_HOST="<public_ip_or_vpc_private_ip>"
+ DB_NAME="gitlabhq_production"
+ DB_USER="gitlab"
+ DB_PASS="<your_password_here>"
+ DB_PORT="5432"
+
+ # Tracking Database connection params:
+ GEO_DB_HOST="<public_ip_or_vpc_private_ip>"
+ GEO_DB_NAME="gitlabhq_geo_production"
+ GEO_DB_USER="gitlab_geo"
+ GEO_DB_PORT="5432"
+
+ query_exec () {
+ gitlab-psql -h $GEO_DB_HOST -d $GEO_DB_NAME -p $GEO_DB_PORT -c "${1}"
+ }
+
+ query_exec "CREATE EXTENSION postgres_fdw;"
+ query_exec "CREATE SERVER gitlab_secondary FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host '${DB_HOST}', dbname '${DB_NAME}', port '${DB_PORT}');"
+ query_exec "CREATE USER MAPPING FOR ${GEO_DB_USER} SERVER gitlab_secondary OPTIONS (user '${DB_USER}', password '${DB_PASS}');"
+ query_exec "CREATE SCHEMA gitlab_secondary;"
+ query_exec "GRANT USAGE ON FOREIGN SERVER gitlab_secondary TO ${GEO_DB_USER};"
+ ```
+
+ NOTE: **Note:** The script template above uses `gitlab-psql` as it's intended to be executed from the Geo machine,
+ but you can change it to `psql` and run it from any machine that has access to the database. We also recommend using
+ `psql` for AWS RDS.
+
+1. Save the file and [restart GitLab](../../restart_gitlab.md#omnibus-gitlab-restart)
+1. Populate the FDW tables:
+
+ ```bash
+ gitlab-rake geo:db:refresh_foreign_tables
+ ```
diff --git a/doc/administration/geo/replication/faq.md b/doc/administration/geo/replication/faq.md
new file mode 100644
index 00000000000..dd1af0dbf9c
--- /dev/null
+++ b/doc/administration/geo/replication/faq.md
@@ -0,0 +1,62 @@
+# Geo Frequently Asked Questions **[PREMIUM ONLY]**
+
+## What are the minimum requirements to run Geo?
+
+The requirements are listed [on the index page](index.md#requirements-for-running-geo)
+
+## How does Geo know which projects to sync?
+
+On each **secondary** node, there is a read-only replicated copy of the GitLab database.
+A **secondary** node also has a tracking database where it stores which projects have been synced.
+Geo compares the two databases to find projects that are not yet tracked.
+
+At the start, this tracking database is empty, so Geo will start trying to update from every project that it can see in the GitLab database.
+
+For each project to sync:
+
+1. Geo will issue a `git fetch geo --mirror` to get the latest information from the **primary** node.
+If there are no changes, the sync will be fast and end quickly. Otherwise, it will pull the latest commits.
+1. The **secondary** node will update the tracking database to store the fact that it has synced projects A, B, C, etc.
+1. Repeat until all projects are synced.
+
+When someone pushes a commit to the **primary** node, it generates an event in the GitLab database that the repository has changed.
+The **secondary** node sees this event, marks the project in question as dirty, and schedules the project to be resynced.
+
+To ensure that problems with pipelines (for example, syncs failing too many times or jobs being lost) don't permanently stop projects syncing, Geo also periodically checks the tracking database for projects that are marked as dirty. This check happens when
+the number of concurrent syncs falls below `repos_max_capacity` and there are no new projects waiting to be synced.
+
+Geo also has a checksum feature which runs a SHA256 sum across all the Git references to the SHA values.
+If the refs don't match between the **primary** node and the **secondary** node, then the **secondary** node will mark that project as dirty and try to resync it.
+So even if we have an outdated tracking database, the validation should activate and find discrepancies in the repository state and resync.
+
+## Can I use Geo in a disaster recovery situation?
+
+Yes, but there are limitations to what we replicate (see
+[What data is replicated to a **secondary** node?](#what-data-is-replicated-to-a-secondary-node)).
+
+Read the documentation for [Disaster Recovery](../disaster_recovery/index.md).
+
+## What data is replicated to a **secondary** node?
+
+We currently replicate project repositories, LFS objects, generated
+attachments / avatars and the whole database. This means user accounts,
+issues, merge requests, groups, project data, etc., will be available for
+query.
+
+## Can I git push to a **secondary** node?
+
+Yes! Pushing directly to a **secondary** node (for both HTTP and SSH, including git-lfs) was [introduced](https://about.gitlab.com/2018/09/22/gitlab-11-3-released/) in [GitLab Premium](https://about.gitlab.com/pricing/#self-managed) 11.3.
+
+## How long does it take to have a commit replicated to a **secondary** node?
+
+All replication operations are asynchronous and are queued to be dispatched. Therefore, it depends on a lot of
+factors including the amount of traffic, how big your commit is, the
+connectivity between your nodes, your hardware, etc.
+
+## What if the SSH server runs at a different port?
+
+That's totally fine. We use HTTP(s) to fetch repository changes from the **primary** node to all **secondary** nodes.
+
+## Is this possible to set up a Docker Registry for a **secondary** node that mirrors the one on the **primary** node?
+
+Yes. See [Docker Registry for a **secondary** node](docker_registry.md).
diff --git a/doc/administration/geo/replication/high_availability.md b/doc/administration/geo/replication/high_availability.md
new file mode 100644
index 00000000000..921a3ef1c7a
--- /dev/null
+++ b/doc/administration/geo/replication/high_availability.md
@@ -0,0 +1,295 @@
+# Geo High Availability **[PREMIUM ONLY]**
+
+This document describes a minimal reference architecture for running Geo
+in a high availability configuration. If your HA setup differs from the one
+described, it is possible to adapt these instructions to your needs.
+
+## Architecture overview
+
+![Geo HA Diagram](../../high_availability/img/geo-ha-diagram.png)
+
+_[diagram source - gitlab employees only][diagram-source]_
+
+The topology above assumes that the **primary** and **secondary** Geo clusters
+are located in two separate locations, on their own virtual network
+with private IP addresses. The network is configured such that all machines within
+one geographic location can communicate with each other using their private IP addresses.
+The IP addresses given are examples and may be different depending on the
+network topology of your deployment.
+
+The only external way to access the two Geo deployments is by HTTPS at
+`gitlab.us.example.com` and `gitlab.eu.example.com` in the example above.
+
+NOTE: **Note:**
+The **primary** and **secondary** Geo deployments must be able to communicate to each other over HTTPS.
+
+## Redis and PostgreSQL High Availability
+
+The **primary** and **secondary** Redis and PostgreSQL should be configured
+for high availability. Because of the additional complexity involved
+in setting up this configuration for PostgreSQL and Redis,
+it is not covered by this Geo HA documentation.
+
+For more information about setting up a highly available PostgreSQL cluster and Redis cluster using the omnibus package see the high availability documentation for
+[PostgreSQL](../../high_availability/database.md) and
+[Redis](../../high_availability/redis.md), respectively.
+
+NOTE: **Note:**
+It is possible to use cloud hosted services for PostgreSQL and Redis, but this is beyond the scope of this document.
+
+## Prerequisites: A working GitLab HA cluster
+
+This cluster will serve as the **primary** node. Use the
+[GitLab HA documentation](../../high_availability/README.md) to set this up.
+
+## Configure the GitLab cluster to be the **primary** node
+
+The following steps enable a GitLab cluster to serve as the **primary** node.
+
+### Step 1: Configure the **primary** frontend servers
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following:
+
+ ```ruby
+ ##
+ ## Enable the Geo primary role
+ ##
+ roles ['geo_primary_role']
+
+ ##
+ ## Disable automatic migrations
+ ##
+ gitlab_rails['auto_migrate'] = false
+ ```
+
+After making these changes, [reconfigure GitLab][gitlab-reconfigure] so the changes take effect.
+
+NOTE: **Note:** PostgreSQL and Redis should have already been disabled on the
+application servers, and connections from the application servers to those
+services on the backend servers configured, during normal GitLab HA set up. See
+high availability configuration documentation for
+[PostgreSQL](../../high_availability/database.md#configuring-the-application-nodes)
+and [Redis](../../high_availability/redis.md#example-configuration-for-the-gitlab-application).
+
+The **primary** database will require modification later, as part of
+[step 2](#step-2-configure-the-main-read-only-replica-postgresql-database-on-the-secondary-node).
+
+## Configure a **secondary** node
+
+A **secondary** cluster is similar to any other GitLab HA cluster, with two
+major differences:
+
+* The main PostgreSQL database is a read-only replica of the **primary** node's
+ PostgreSQL database.
+* There is also a single PostgreSQL database for the **secondary** cluster,
+ called the "tracking database", which tracks the synchronization state of
+ various resources.
+
+Therefore, we will set up the HA components one-by-one, and include deviations
+from the normal HA setup.
+
+### Step 1: Configure the Redis and NFS services on the **secondary** node
+
+Configure the following services, again using the non-Geo high availability
+documentation:
+
+* [Configuring Redis for GitLab HA](../../high_availability/redis.md) for high
+ availability.
+* [NFS](../../high_availability/nfs.md) which will store data that is
+ synchronized from the **primary** node.
+
+### Step 2: Configure the main read-only replica PostgreSQL database on the **secondary** node
+
+NOTE: **Note:** The following documentation assumes the database will be run on
+a single node only, rather than as a PostgreSQL cluster.
+
+Configure the [**secondary** database](database.md) as a read-only replica of
+the **primary** database. Use the following as a guide.
+
+1. Edit `/etc/gitlab/gitlab.rb` in the replica database machine, and add the
+ following:
+
+ ```ruby
+ ##
+ ## Configure the PostgreSQL role
+ ##
+ roles ['postgres_role']
+
+ ##
+ ## Secondary address
+ ## - replace '<secondary_node_ip>' with the public or VPC address of your Geo secondary node
+ ## - replace '<tracking_database_ip>' with the public or VPC address of your Geo tracking database node
+ ##
+ postgresql['listen_address'] = '<secondary_node_ip>'
+ postgresql['md5_auth_cidr_addresses'] = ['<secondary_node_ip>/32', '<tracking_database_ip>/32']
+
+ ##
+ ## Database credentials password (defined previously in primary node)
+ ## - replicate same values here as defined in primary node
+ ##
+ postgresql['sql_user_password'] = '<md5_hash_of_your_password>'
+ gitlab_rails['db_password'] = '<your_password_here>'
+
+ ##
+ ## When running the Geo tracking database on a separate machine, disable it
+ ## here and allow connections from the tracking database host. And ensure
+ ## the tracking database IP is in postgresql['md5_auth_cidr_addresses'] above.
+ ##
+ geo_postgresql['enable'] = false
+ ```
+
+After making these changes, [reconfigure GitLab][gitlab-reconfigure] so the changes take effect.
+
+If using an external PostgreSQL instance, refer also to
+[Geo with external PostgreSQL instances](external_database.md).
+
+### Step 3: Configure the tracking database on the **secondary** node
+
+NOTE: **Note:** This documentation assumes the tracking database will be run on
+only a single machine, rather than as a PostgreSQL cluster.
+
+Configure the tracking database.
+
+1. Edit `/etc/gitlab/gitlab.rb` in the tracking database machine, and add the
+ following:
+
+ ```ruby
+ ##
+ ## Enable the Geo secondary tracking database
+ ##
+ geo_postgresql['enable'] = true
+ geo_postgresql['listen_address'] = '<ip_address_of_this_host>'
+ geo_postgresql['sql_user_password'] = '<tracking_database_password_md5_hash>'
+
+ ##
+ ## Configure FDW connection to the replica database
+ ##
+ geo_secondary['db_fdw'] = true
+ geo_postgresql['fdw_external_password'] = '<replica_database_password_plaintext>'
+ geo_postgresql['md5_auth_cidr_addresses'] = ['<replica_database_ip>/32']
+ gitlab_rails['db_host'] = '<replica_database_ip>'
+
+ # Prevent reconfigure from attempting to run migrations on the replica DB
+ gitlab_rails['auto_migrate'] = false
+
+ ##
+ ## Disable all other services that aren't needed, since we don't have a role
+ ## that does this.
+ ##
+ alertmanager['enable'] = false
+ consul['enable'] = false
+ gitaly['enable'] = false
+ gitlab_monitor['enable'] = false
+ gitlab_workhorse['enable'] = false
+ nginx['enable'] = false
+ node_exporter['enable'] = false
+ pgbouncer_exporter['enable'] = false
+ postgresql['enable'] = false
+ prometheus['enable'] = false
+ redis['enable'] = false
+ redis_exporter['enable'] = false
+ repmgr['enable'] = false
+ sidekiq['enable'] = false
+ unicorn['enable'] = false
+ ```
+
+After making these changes, [reconfigure GitLab][gitlab-reconfigure] so the changes take effect.
+
+If using an external PostgreSQL instance, refer also to
+[Geo with external PostgreSQL instances](external_database.md).
+
+### Step 4: Configure the frontend application servers on the **secondary** node
+
+In the architecture overview, there are two machines running the GitLab
+application services. These services are enabled selectively in the
+configuration.
+
+Configure the application servers following
+[Configuring GitLab for HA](../../high_availability/gitlab.md), then make the
+following modifications:
+
+1. Edit `/etc/gitlab/gitlab.rb` on each application server in the **secondary**
+ cluster, and add the following:
+
+ ```ruby
+ ##
+ ## Enable the Geo secondary role
+ ##
+ roles ['geo_secondary_role', 'application_role']
+
+ ##
+ ## Disable automatic migrations
+ ##
+ gitlab_rails['auto_migrate'] = false
+
+ ##
+ ## Configure the connection to the tracking DB. And disable application
+ ## servers from running tracking databases.
+ ##
+ geo_secondary['db_host'] = '<geo_tracking_db_host>'
+ geo_secondary['db_password'] = '<geo_tracking_db_password>'
+ geo_postgresql['enable'] = false
+
+ ##
+ ## Configure connection to the streaming replica database, if you haven't
+ ## already
+ ##
+ gitlab_rails['db_host'] = '<replica_database_host>'
+ gitlab_rails['db_password'] = '<replica_database_password>'
+
+ ##
+ ## Configure connection to Redis, if you haven't already
+ ##
+ gitlab_rails['redis_host'] = '<redis_host>'
+ gitlab_rails['redis_password'] = '<redis_password>'
+
+ ##
+ ## If you are using custom users not managed by Omnibus, you need to specify
+ ## UIDs and GIDs like below, and ensure they match between servers in a
+ ## cluster to avoid permissions issues
+ ##
+ user['uid'] = 9000
+ user['gid'] = 9000
+ web_server['uid'] = 9001
+ web_server['gid'] = 9001
+ registry['uid'] = 9002
+ registry['gid'] = 9002
+ ```
+
+NOTE: **Note:**
+If you had set up PostgreSQL cluster using the omnibus package and you had set
+up `postgresql['sql_user_password'] = 'md5 digest of secret'` setting, keep in
+mind that `gitlab_rails['db_password']` and `geo_secondary['db_password']`
+mentioned above contains the plaintext passwords. This is used to let the Rails
+servers connect to the databases.
+
+NOTE: **Note:**
+Make sure that current node IP is listed in `postgresql['md5_auth_cidr_addresses']` setting of your remote database.
+
+After making these changes [Reconfigure GitLab][gitlab-reconfigure] so the changes take effect.
+
+On the secondary the following GitLab frontend services will be enabled:
+
+* geo-logcursor
+* gitlab-pages
+* gitlab-workhorse
+* logrotate
+* nginx
+* registry
+* remote-syslog
+* sidekiq
+* unicorn
+
+Verify these services by running `sudo gitlab-ctl status` on the frontend
+application servers.
+
+### Step 5: Set up the LoadBalancer for the **secondary** node
+
+In this topology, a load balancer is required at each geographic location to
+route traffic to the application servers.
+
+See [Load Balancer for GitLab HA](../../high_availability/load_balancer.md) for
+more information.
+
+[diagram-source]: https://docs.google.com/drawings/d/1z0VlizKiLNXVVVaERFwgsIOuEgjcUqDTWPdQYsE7Z4c/edit
+[gitlab-reconfigure]: ../../restart_gitlab.md#omnibus-gitlab-reconfigure
diff --git a/doc/administration/geo/replication/img/geo_architecture.png b/doc/administration/geo/replication/img/geo_architecture.png
new file mode 100644
index 00000000000..d318cd5d0f4
--- /dev/null
+++ b/doc/administration/geo/replication/img/geo_architecture.png
Binary files differ
diff --git a/doc/administration/geo/replication/img/geo_node_dashboard.png b/doc/administration/geo/replication/img/geo_node_dashboard.png
new file mode 100644
index 00000000000..99792d0770d
--- /dev/null
+++ b/doc/administration/geo/replication/img/geo_node_dashboard.png
Binary files differ
diff --git a/doc/administration/geo/replication/img/geo_node_healthcheck.png b/doc/administration/geo/replication/img/geo_node_healthcheck.png
new file mode 100644
index 00000000000..33a31f7ab49
--- /dev/null
+++ b/doc/administration/geo/replication/img/geo_node_healthcheck.png
Binary files differ
diff --git a/doc/administration/geo/replication/img/geo_overview.png b/doc/administration/geo/replication/img/geo_overview.png
new file mode 100644
index 00000000000..01c1615212c
--- /dev/null
+++ b/doc/administration/geo/replication/img/geo_overview.png
Binary files differ
diff --git a/doc/administration/geo/replication/index.md b/doc/administration/geo/replication/index.md
new file mode 100644
index 00000000000..54377f7ae4e
--- /dev/null
+++ b/doc/administration/geo/replication/index.md
@@ -0,0 +1,292 @@
+# Geo Replication **[PREMIUM ONLY]**
+
+Geo is the solution for widely distributed development teams.
+
+## Overview
+
+Fetching large repositories can take a long time for teams located far from a single GitLab instance.
+
+Geo provides local, read-only instances of your GitLab instances, reducing the time it takes to clone and fetch large repositories and speeding up development.
+
+> - Geo is part of [GitLab Premium](https://about.gitlab.com/pricing/#self-managed).
+> - Introduced in GitLab Enterprise Edition 8.9.
+> - We recommend you use:
+> - At least GitLab Enterprise Edition 10.0 for basic Geo features.
+> - The latest version for a better experience.
+> - Make sure that all nodes run the same GitLab version.
+> - Geo requires PostgreSQL 9.6 and Git 2.9, in addition to GitLab's usual [minimum requirements](../../../install/requirements.md).
+> - Using Geo in combination with [High Availability](../../high_availability/README.md) is considered **Generally Available** (GA) in GitLab [GitLab Premium](https://about.gitlab.com/pricing/) 10.4.
+
+For a video introduction to Geo, see [Introduction to GitLab Geo - GitLab Features](https://www.youtube.com/watch?v=-HDLxSjEh6w).
+
+CAUTION: **Caution:**
+Geo undergoes significant changes from release to release. Upgrades **are** supported and [documented](#updating-geo), but you should ensure that you're using the right version of the documentation for your installation.
+
+To make sure you're using the right version of the documentation, navigate to [the source version of this page on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/doc/administration/geo/replication/index.md) and choose the appropriate release from the **Switch branch/tag** dropdown. For example, [`v11.2.3-ee`](https://gitlab.com/gitlab-org/gitlab-ee/blob/v11.2.3-ee/doc/administration/geo/replication/index.md).
+
+## Use cases
+
+Implementing Geo provides the following benefits:
+
+- Reduce from minutes to seconds the time taken for your distributed developers to clone and fetch large repositories and projects.
+- Enable all of your developers to contribute ideas and work in parallel, no matter where they are.
+- Balance the load between your **primary** and **secondary** nodes, or offload your automated tests to a **secondary** node.
+
+In addition, it:
+
+- Can be used for cloning and fetching projects, in addition to reading any data available in the GitLab web interface (see [current limitations](#current-limitations)).
+- Overcomes slow connections between distant offices, saving time by improving speed for distributed teams.
+- Helps reducing the loading time for automated tasks, custom integrations, and internal workflows.
+- Can quickly fail over to a **secondary** node in a [disaster recovery](../disaster_recovery/index.md) scenario.
+- Allows [planned failover](../disaster_recovery/planned_failover.md) to a **secondary** node.
+
+Geo provides:
+
+- Read-only **secondary** nodes: Maintain one **primary** GitLab node while still enabling read-only **secondary** nodes for each of your distributed teams.
+- Authentication system hooks: **Secondary** nodes receives all authentication data (like user accounts and logins) from the **primary** instance.
+- An intuitive UI: **Secondary** nodes utilize the same web interface your team has grown accustomed to. In addition, there are visual notifications that block write operations and make it clear that a user is on a **secondary** node.
+
+## How it works
+
+Your Geo instance can be used for cloning and fetching projects, in addition to reading any data. This will make working with large repositories over large distances much faster.
+
+![Geo overview](img/geo_overview.png)
+
+When Geo is enabled, the:
+
+- Original instance is known as the **primary** node.
+- Replicated read-only nodes are known as **secondary** nodes.
+
+Keep in mind that:
+
+- **Secondary** nodes talk to the **primary** node to:
+ - Get user data for logins (API).
+ - Replicate repositories, LFS Objects, and Attachments (HTTPS + JWT).
+- Since GitLab Premium 10.0, the **primary** node no longer talks to **secondary** nodes to notify for changes (API).
+- Pushing directly to a **secondary** node (for both HTTP and SSH, including git-lfs) was [introduced](https://about.gitlab.com/2018/09/22/gitlab-11-3-released/) in [GitLab Premium](https://about.gitlab.com/pricing/#self-managed) 11.3.
+- There are [limitations](#current-limitations) in the current implementation.
+
+### Architecture
+
+The following diagram illustrates the underlying architecture of Geo.
+
+![Geo architecture](img/geo_architecture.png)
+
+In this diagram:
+
+- There is the **primary** node and the details of one **secondary** node.
+- Writes to the database can only be performed on the **primary** node. A **secondary** node receives database
+ updates via PostgreSQL streaming replication.
+- If present, the [LDAP server](#ldap) should be configured to replicate for [Disaster Recovery](../disaster_recovery/index.md) scenarios.
+- A **secondary** node performs different type of synchronizations against the **primary** node, using a special
+ authorization protected by JWT:
+ - Repositories are cloned/updated via Git over HTTPS.
+ - Attachments, LFS objects, and other files are downloaded via HTTPS using a private API endpoint.
+
+From the perspective of a user performing Git operations:
+
+- The **primary** node behaves as a full read-write GitLab instance.
+- **Secondary** nodes are read-only but proxy Git push operations to the **primary** node. This makes **secondary** nodes appear to support push operations themselves.
+
+To simplify the diagram, some necessary components are omitted. Note that:
+
+- Git over SSH requires [`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell) and OpenSSH.
+- Git over HTTPS required [`gitlab-workhorse`](https://gitlab.com/gitlab-org/gitlab-workhorse).
+
+Note that a **secondary** node needs two different PostgreSQL databases:
+
+- A read-only database instance that streams data from the main GitLab database.
+- [Another database instance](#geo-tracking-database) used internally by the **secondary** node to record what data has been replicated.
+
+In **secondary** nodes, there is an additional daemon: [Geo Log Cursor](#geo-log-cursor).
+
+## Requirements for running Geo
+
+The following are required to run Geo:
+
+- An operating system that supports OpenSSH 6.9+ (needed for
+ [fast lookup of authorized SSH keys in the database](../../operations/fast_ssh_key_lookup.md))
+ The following operating systems are known to ship with a current version of OpenSSH:
+ - [CentOS](https://www.centos.org) 7.4+
+ - [Ubuntu](https://www.ubuntu.com) 16.04+
+- PostgreSQL 9.6+ with [FDW](https://www.postgresql.org/docs/9.6/postgres-fdw.html) support and [Streaming Replication](https://wiki.postgresql.org/wiki/Streaming_Replication)
+- Git 2.9+
+
+### Firewall rules
+
+The following table lists basic ports that must be open between the **primary** and **secondary** nodes for Geo.
+
+| **Primary** node | **Secondary** node | Protocol |
+|:-----------------|:-------------------|:-------------|
+| 80 | 80 | HTTP |
+| 443 | 443 | TCP or HTTPS |
+| 22 | 22 | TCP |
+| 5432 | | PostgreSQL |
+
+See the full list of ports used by GitLab in [Package defaults](https://docs.gitlab.com/omnibus/package-information/defaults.html)
+
+NOTE: **Note:**
+[Web terminal](../../../ci/environments.md#web-terminals) support requires your load balancer to correctly handle WebSocket connections.
+When using HTTP or HTTPS proxying, your load balancer must be configured to pass through the `Connection` and `Upgrade` hop-by-hop headers. See the [web terminal](../../integration/terminal.md) integration guide for more details.
+
+NOTE: **Note:**
+When using HTTPS protocol for port 443, you will need to add an SSL certificate to the load balancers.
+If you wish to terminate SSL at the GitLab application server instead, use TCP protocol.
+
+### LDAP
+
+We recommend that if you use LDAP on your **primary** node, you also set up secondary LDAP servers on each **secondary** node. Otherwise, users will not be able to perform Git operations over HTTP(s) on the **secondary** node using HTTP Basic Authentication. However, Git via SSH and personal access tokens will still work.
+
+NOTE: **Note:**
+It is possible for all **secondary** nodes to share an LDAP server, but additional latency can be an issue. Also, consider what LDAP server will be available in a [disaster recovery](../disaster_recovery/index.md) scenario if a **secondary** node is promoted to be a **primary** node.
+
+Check for instructions on how to set up replication in your LDAP service. Instructions will be different depending on the software or service used. For example, OpenLDAP provides [these instructions](https://www.openldap.org/doc/admin24/replication.html).
+
+### Geo Tracking Database
+
+The tracking database instance is used as metadata to control what needs to be updated on the disk of the local instance. For example:
+
+- Download new assets.
+- Fetch new LFS Objects.
+- Fetch changes from a repository that has recently been updated.
+
+Because the replicated database instance is read-only, we need this additional database instance for each **secondary** node.
+The tracking database requires the `postgres_fdw` extension.
+
+### Geo Log Cursor
+
+This daemon:
+
+- Reads a log of events replicated by the **primary** node to the **secondary** database instance.
+- Updates the Geo Tracking Database instance with changes that need to be executed.
+
+When something is marked to be updated in the tracking database instance, asynchronous jobs running on the **secondary** node will execute the required operations and update the state.
+
+This new architecture allows GitLab to be resilient to connectivity issues between the nodes. It doesn't matter how long the **secondary** node is disconnected from the **primary** node as it will be able to replay all the events in the correct order and become synchronized with the **primary** node again.
+
+## Setup instructions
+
+These instructions assume you have a working instance of GitLab. They guide you through:
+
+1. Making your existing instance the **primary** node.
+1. Adding **secondary** nodes.
+
+CAUTION: **Caution:**
+The steps below should be followed in the order they appear. **Make sure the GitLab version is the same on all nodes.**
+
+### Using Omnibus GitLab
+
+If you installed GitLab using the Omnibus packages (highly recommended):
+
+1. [Install GitLab Enterprise Edition](https://about.gitlab.com/installation/) on the server that will serve as the **secondary** node. Do not create an account or log in to the new **secondary** node.
+1. [Upload the GitLab License](../../../user/admin_area/license.md) on the **primary** node to unlock Geo. The license must be for [GitLab Premium](https://about.gitlab.com/pricing/) or higher.
+1. [Set up the database replication](database.md) (`primary (read-write) <-> secondary (read-only)` topology).
+1. [Configure fast lookup of authorized SSH keys in the database](../../operations/fast_ssh_key_lookup.md). This step is required and needs to be done on **both** the **primary** and **secondary** nodes.
+1. [Configure GitLab](configuration.md) to set the **primary** and **secondary** nodes.
+1. Optional: [Configure a secondary LDAP server](../../auth/ldap.md) for the **secondary** node. See [notes on LDAP](#ldap).
+1. [Follow the "Using a Geo Server" guide](using_a_geo_server.md).
+
+## Post-installation documentation
+
+After installing GitLab on the **secondary** nodes and performing the initial configuration, see the following documentation for post-installation information.
+
+### Configuring Geo
+
+For information on configuring Geo, see [Geo configuration](configuration.md).
+
+### Updating Geo
+
+For information on how to update your Geo nodes to the latest GitLab version, see [Updating the Geo nodes](updating_the_geo_nodes.md).
+
+### Configuring Geo high availability
+
+For information on configuring Geo for high availability, see [Geo High Availability](high_availability.md).
+
+### Configuring Geo with Object Storage
+
+For information on configuring Geo with object storage, see [Geo with Object storage](object_storage.md).
+
+### Disaster Recovery
+
+For information on using Geo in disaster recovery situations to mitigate data-loss and restore services, see [Disaster Recovery](../disaster_recovery/index.md).
+
+### Replicating the Container Registry
+
+For more information on how to replicate the Container Registry, see [Docker Registry for a **secondary** node](docker_registry.md).
+
+### Security Review
+
+For more information on Geo security, see [Geo security review](security_review.md).
+
+### Tuning Geo
+
+For more information on tuning Geo, see [Tuning Geo](tuning.md).
+
+## Remove Geo node
+
+For more information on removing a Geo node, see [Removing **secondary** Geo nodes](remove_geo_node.md).
+
+## Current limitations
+
+CAUTION: **Caution:**
+This list of limitations only reflects the latest version of GitLab. If you are using an older version, extra limitations may be in place.
+
+- Pushing directly to a **secondary** node redirects (for HTTP) or proxies (for SSH) the request to the **primary** node instead of [handling it directly](https://gitlab.com/gitlab-org/gitlab-ee/issues/1381), except when using Git over HTTP with credentials embedded within the URI. For example, `https://user:password@secondary.tld`.
+- The **primary** node has to be online for OAuth login to happen. Existing sessions and Git are not affected.
+- The installation takes multiple manual steps that together can take about an hour depending on circumstances. We are working on improving this experience. See [gitlab-org/omnibus-gitlab#2978](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/2978) for details.
+- Real-time updates of issues/merge requests (for example, via long polling) doesn't work on the **secondary** node.
+- [Selective synchronization](configuration.md#selective-synchronization) applies only to files and repositories. Other datasets are replicated to the **secondary** node in full, making it inappropriate for use as an access control mechanism.
+- Object pools for forked project deduplication work only on the **primary** node, and are duplicated on the **secondary** node.
+- [External merge request diffs](../../merge_request_diffs.md) will not be replicated if they are on-disk, and viewing merge requests will fail. However, external MR diffs in object storage **are** supported. The default configuration (in-database) does work.
+
+### Limitations on replication
+
+Only the following items are replicated to the **secondary** node:
+
+- All database content. For example, snippets, epics, issues, merge requests, groups, and project metadata.
+- Project repositories.
+- Project wiki repositories.
+- User uploads. For example, attachments to issues, merge requests, epics, and avatars.
+- CI job artifacts and traces.
+
+DANGER: **DANGER**
+Data not on this list is unavailable on the **secondary** node. Failing over without manually replicating data not on this list will cause the data to be **lost**.
+
+### Examples of data not replicated
+
+Take special note that these examples of GitLab features are both:
+
+- Commonly used.
+- **Not** replicated by Geo at present.
+
+Examples include:
+
+- [Elasticsearch integration](../../../integration/elasticsearch.md).
+- [Container Registry](../../container_registry.md). [Object Storage](object_storage.md) can mitigate this.
+- [GitLab Pages](../../pages/index.md).
+- [Mattermost integration](https://docs.gitlab.com/omnibus/gitlab-mattermost/).
+
+CAUTION: **Caution:**
+If you wish to use them on a **secondary** node, or to execute a failover successfully, you will need to replicate their data using some other means.
+
+## Frequently Asked Questions
+
+For answers to common questions, see the [Geo FAQ](faq.md).
+
+## Log files
+
+Since GitLab 9.5, Geo stores structured log messages in a `geo.log` file. For Omnibus installations, this file is at `/var/log/gitlab/gitlab-rails/geo.log`.
+
+This file contains information about when Geo attempts to sync repositories and files. Each line in the file contains a separate JSON entry that can be ingested into Elasticsearch, Splunk, etc.
+
+For example:
+
+```json
+{"severity":"INFO","time":"2017-08-06T05:40:16.104Z","message":"Repository update","project_id":1,"source":"repository","resync_repository":true,"resync_wiki":true,"class":"Gitlab::Geo::LogCursor::Daemon","cursor_delay_s":0.038}
+```
+
+This message shows that Geo detected that a repository update was needed for project `1`.
+
+## Troubleshooting
+
+For troubleshooting steps, see [Geo Troubleshooting](troubleshooting.md).
diff --git a/doc/administration/geo/replication/object_storage.md b/doc/administration/geo/replication/object_storage.md
new file mode 100644
index 00000000000..c3c11dbaf1e
--- /dev/null
+++ b/doc/administration/geo/replication/object_storage.md
@@ -0,0 +1,43 @@
+# Geo with Object storage **[PREMIUM ONLY]**
+
+Geo can be used in combination with Object Storage (AWS S3, or
+other compatible object storage).
+
+## Configuration
+
+At this time it is required that if object storage is enabled on the
+**primary** node, it must also be enabled on each **secondary** node.
+
+**Secondary** nodes can use the same storage bucket as the **primary** node, or
+they can use a replicated storage bucket. At this time GitLab does not
+take care of content replication in object storage.
+
+For LFS, follow the documentation to
+[set up LFS object storage](../../../workflow/lfs/lfs_administration.md#storing-lfs-objects-in-remote-object-storage).
+
+For CI job artifacts, there is similar documentation to configure
+[jobs artifact object storage](../../job_artifacts.md#using-object-storage)
+
+For user uploads, there is similar documentation to configure [upload object storage](../../uploads.md#using-object-storage-core-only)
+
+You should enable and configure object storage on both **primary** and **secondary**
+nodes. Migrating existing data to object storage should be performed on the
+**primary** node only. **Secondary** nodes will automatically notice that the migrated
+files are now in object storage.
+
+## Replication
+
+When using Amazon S3, you can use
+[CRR](https://docs.aws.amazon.com/AmazonS3/latest/dev/crr.html) to
+have automatic replication between the bucket used by the **primary** node and
+the bucket used by **secondary** nodes.
+
+If you are using Google Cloud Storage, consider using
+[Multi-Regional Storage](https://cloud.google.com/storage/docs/storage-classes#multi-regional).
+Or you can use the [Storage Transfer Service](https://cloud.google.com/storage/transfer/),
+although this only supports daily synchronization.
+
+For manual synchronization, or scheduled by `cron`, please have a look at:
+
+- [`s3cmd sync`](http://s3tools.org/s3cmd-sync)
+- [`gsutil rsync`](https://cloud.google.com/storage/docs/gsutil/commands/rsync)
diff --git a/doc/administration/geo/replication/remove_geo_node.md b/doc/administration/geo/replication/remove_geo_node.md
new file mode 100644
index 00000000000..b190fe7d42d
--- /dev/null
+++ b/doc/administration/geo/replication/remove_geo_node.md
@@ -0,0 +1,50 @@
+# Removing secondary Geo nodes **[PREMIUM ONLY]**
+
+**Secondary** nodes can be removed from the Geo cluster using the Geo admin page of the **primary** node. To remove a **secondary** node:
+
+1. Navigate to **Admin Area > Geo** (`/admin/geo/nodes`).
+1. Click the **Remove** button for the **secondary** node you want to remove.
+1. Confirm by clicking **Remove** when the prompt appears.
+
+Once removed from the Geo admin page, you must stop and uninstall the **secondary** node:
+
+1. On the **secondary** node, stop GitLab:
+
+ ```bash
+ sudo gitlab-ctl stop
+ ```
+1. On the **secondary** node, uninstall GitLab:
+
+ ```bash
+ # Stop gitlab and remove its supervision process
+ sudo gitlab-ctl uninstall
+
+ # Debian/Ubuntu
+ sudo dpkg --remove gitlab-ee
+
+ # Redhat/Centos
+ sudo rpm --erase gitlab-ee
+ ```
+
+Once GitLab has been uninstalled from the **secondary** node, the replication slot must be dropped from the **primary** node's database as follows:
+
+1. On the **primary** node, start a PostgreSQL console session:
+
+ ```bash
+ sudo gitlab-psql
+ ```
+
+ NOTE: **Note:**
+ Using `gitlab-rails dbconsole` will not work, because managing replication slots requires superuser permissions.
+
+1. Find the name of the relevant replication slot. This is the slot that is specified with `--slot-name` when running the replicate command: `gitlab-ctl replicate-geo-database`.
+
+ ```sql
+ SELECT * FROM pg_replication_slots;
+ ```
+
+1. Remove the replication slot for the **secondary** node:
+
+ ```sql
+ SELECT pg_drop_replication_slot('<name_of_slot>');
+ ```
diff --git a/doc/administration/geo/replication/security_review.md b/doc/administration/geo/replication/security_review.md
new file mode 100644
index 00000000000..cd54e2dc8c4
--- /dev/null
+++ b/doc/administration/geo/replication/security_review.md
@@ -0,0 +1,284 @@
+# Geo security review (Q&A) **[PREMIUM ONLY]**
+
+The following security review of the Geo feature set focuses on security
+aspects of the feature as they apply to customers running their own GitLab
+instances. The review questions are based in part on the [application security architecture](https://www.owasp.org/index.php/Application_Security_Architecture_Cheat_Sheet)
+questions from [owasp.org](https://www.owasp.org).
+
+## Business Model
+
+### What geographic areas does the application service?
+
+- This varies by customer. Geo allows customers to deploy to multiple areas,
+ and they get to choose where they are.
+- Region and node selection is entirely manual.
+
+## Data Essentials
+
+### What data does the application receive, produce, and process?
+
+- Geo streams almost all data held by a GitLab instance between sites. This
+ includes full database replication, most files (user-uploaded attachments,
+ etc) and repository + wiki data. In a typical configuration, this will
+ happen across the public Internet, and be TLS-encrypted.
+- PostgreSQL replication is TLS-encrypted.
+- See also: [only TLSv1.2 should be supported](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/2948)
+
+### How can the data be classified into categories according to its sensitivity?
+
+- GitLab’s model of sensitivity is centered around public vs. internal vs.
+ private projects. Geo replicates them all indiscriminately. “Selective syncâ€
+ exists for files and repositories (but not database content), which would permit
+ only less-sensitive projects to be replicated to a **secondary** node if desired.
+- See also: [developing a data classification policy](https://gitlab.com/gitlab-com/security/issues/4).
+
+### What data backup and retention requirements have been defined for the application?
+
+- Geo is designed to provide replication of a certain subset of the application
+ data. It is part of the solution, rather than part of the problem.
+
+## End-Users
+
+### Who are the application's endâ€users?
+
+- **Secondary** nodes are created in regions that are distant (in terms of
+ Internet latency) from the main GitLab installation (the **primary** node). They are
+ intended to be used by anyone who would ordinarily use the **primary** node, who finds
+ that the **secondary** node is closer to them (in terms of Internet latency).
+
+### How do the endâ€users interact with the application?
+
+- **Secondary** nodes provide all the interfaces a **primary** node does
+ (notably a HTTP/HTTPS web application, and HTTP/HTTPS or SSH git repository
+ access), but is constrained to read-only activities. The principal use case is
+ envisioned to be cloning git repositories from the **secondary** node in favor of the
+ **primary** node, but end-users may use the GitLab web interface to view projects,
+ issues, merge requests, snippets, etc.
+
+### What security expectations do the endâ€users have?
+
+- The replication process must be secure. It would typically be unacceptable to
+ transmit the entire database contents or all files and repositories across the
+ public Internet in plaintext, for instance.
+- **Secondary** nodes must have the same access controls over its content as the
+ **primary** node - unauthenticated users must not be able to gain access to privileged
+ information on the **primary** node by querying the **secondary** node.
+- Attackers must not be able to impersonate the **secondary** node to the **primary** node, and
+ thus gain access to privileged information.
+
+## Administrators
+
+### Who has administrative capabilities in the application?
+
+- Nothing Geo-specific. Any user where `admin: true` is set in the database is
+ considered an admin with super-user privileges.
+- See also: [more granular access control](https://gitlab.com/gitlab-org/gitlab-ce/issues/32730)
+ (not geo-specific)
+- Much of Geo’s integration (database replication, for instance) must be
+ configured with the application, typically by system administrators.
+
+### What administrative capabilities does the application offer?
+
+- **Secondary** nodes may be added, modified, or removed by users with
+ administrative access.
+- The replication process may be controlled (start/stop) via the Sidekiq
+ administrative controls.
+
+## Network
+
+### What details regarding routing, switching, firewalling, and loadâ€balancing have been defined?
+
+- Geo requires the **primary** node and **secondary** node to be able to communicate with each
+ other across a TCP/IP network. In particular, the **secondary** nodes must be able to
+ access HTTP/HTTPS and PostgreSQL services on the **primary** node.
+
+### What core network devices support the application?
+
+- Varies from customer to customer.
+
+### What network performance requirements exist?
+
+- Maximum replication speeds between **primary** node and **secondary** node is limited by the
+ available bandwidth between sites. No hard requirements exist - time to complete
+ replication (and ability to keep up with changes on the **primary** node) is a function
+ of the size of the data set, tolerance for latency, and available network
+ capacity.
+
+### What private and public network links support the application?
+
+- Customers choose their own networks. As sites are intended to be
+ geographically separated, it is envisioned that replication traffic will pass
+ over the public Internet in a typical deployment, but this is not a requirement.
+
+## Systems
+
+### What operating systems support the application?
+
+- Geo imposes no additional restrictions on operating system (see the
+ [GitLab installation](https://about.gitlab.com/installation/) page for more
+ details), however we recommend using the operating systems listed in the [Geo documentation](index.md#requirements-for-running-geo).
+
+### What details regarding required OS components and lockâ€down needs have been defined?
+
+- The supported installation method (Omnibus) packages most components itself.
+- There are significant dependencies on the system-installed OpenSSH daemon (Geo
+ requires users to set up custom authentication methods) and the omnibus or
+ system-provided PostgreSQL daemon (it must be configured to listen on TCP,
+ additional users and replication slots must be added, etc).
+- The process for dealing with security updates (for example, if there is a
+ significant vulnerability in OpenSSH or other services, and the customer
+ wants to patch those services on the OS) is identical to the non-Geo
+ situation: security updates to OpenSSH would be provided to the user via the
+ usual distribution channels. Geo introduces no delay there.
+
+## Infrastructure Monitoring
+
+### What network and system performance monitoring requirements have been defined?
+
+- None specific to Geo.
+
+### What mechanisms exist to detect malicious code or compromised application components?
+
+- None specific to Geo.
+
+### What network and system security monitoring requirements have been defined?
+
+- None specific to Geo.
+
+## Virtualization and Externalization
+
+### What aspects of the application lend themselves to virtualization?
+
+- All.
+
+## What virtualization requirements have been defined for the application?
+
+- Nothing Geo-specific, but everything in GitLab needs to have full
+ functionality in such an environment.
+
+### What aspects of the product may or may not be hosted via the cloud computing model?
+
+- GitLab is “cloud native†and this applies to Geo as much as to the rest of the
+ product. Deployment in clouds is a common and supported scenario.
+
+## If applicable, what approach(es) to cloud computing will be taken (Managed Hosting versus "Pure" Cloud, a "full machine" approach such as AWS-EC2 versus a "hosted database" approach such as AWS-RDS and Azure, etc)?
+
+- To be decided by our customers, according to their operational needs.
+
+## Environment
+
+### What frameworks and programming languages have been used to create the application?
+
+- Ruby on Rails, Ruby.
+
+### What process, code, or infrastructure dependencies have been defined for the application?
+
+- Nothing specific to Geo.
+
+### What databases and application servers support the application?
+
+- PostgreSQL >= 9.6, Redis, Sidekiq, Unicorn.
+
+### How will database connection strings, encryption keys, and other sensitive components be stored, accessed, and protected from unauthorized detection?
+
+- There are some Geo-specific values. Some are shared secrets which must be
+ securely transmitted from the **primary** node to the **secondary** node at setup time. Our
+ documentation recommends transmitting them from the **primary** node to the system
+ administrator via SSH, and then back out to the **secondary** node in the same manner.
+ In particular, this includes the PostgreSQL replication credentials and a secret
+ key (`db_key_base`) which is used to decrypt certain columns in the database.
+ The `db_key_base` secret is stored unencrypted on the filesystem, in
+ `/etc/gitlab/gitlab-secrets.json`, along with a number of other secrets. There is
+ no at-rest protection for them.
+
+## Data Processing
+
+### What data entry paths does the application support?
+
+- Data is entered via the web application exposed by GitLab itself. Some data is
+ also entered using system administration commands on the GitLab servers (e.g.,
+ `gitlab-ctl set-primary-node`).
+- **Secondary** nodes also receive inputs via PostgreSQL streaming replication from the **primary** node.
+
+### What data output paths does the application support?
+
+- **Primary** nodes output via PostgreSQL streaming replication to the **secondary** node.
+ Otherwise, principally via the web application exposed by GitLab itself, and via
+ SSH `git clone` operations initiated by the end-user.
+
+### How does data flow across the application's internal components?
+
+- **Secondary** nodes and **primary** nodes interact via HTTP/HTTPS (secured with JSON web
+ tokens) and via PostgreSQL streaming replication.
+- Within a **primary** node or **secondary** node, the SSOT is the filesystem and the database
+ (including Geo tracking database on **secondary** node). The various internal components
+ are orchestrated to make alterations to these stores.
+
+### What data input validation requirements have been defined?
+
+- **Secondary** nodes must have a faithful replication of the **primary** node’s data.
+
+### What data does the application store and how?
+
+- Git repositories and files, tracking information related to the them, and the GitLab database contents.
+
+### What data is or may need to be encrypted and what key management requirements have been defined?
+
+- Neither **primary** nodes or **secondary** nodes encrypt Git repository or filesystem data at
+ rest. A subset of database columns are encrypted at rest using the `db_otp_key`.
+- A static secret shared across all hosts in a GitLab deployment.
+- In transit, data should be encrypted, although the application does permit
+ communication to proceed unencrypted. The two main transits are the **secondary** node’s
+ replication process for PostgreSQL, and for git repositories/files. Both should
+ be protected using TLS, with the keys for that managed via Omnibus per existing
+ configuration for end-user access to GitLab.
+
+### What capabilities exist to detect the leakage of sensitive data?
+
+- Comprehensive system logs exist, tracking every connection to GitLab and PostgreSQL.
+
+### What encryption requirements have been defined for data in transit - including transmission over WAN, LAN, SecureFTP, or publicly accessible protocols such as http: and https:?
+
+- Data must have the option to be encrypted in transit, and be secure against
+ both passive and active attack (e.g., MITM attacks should not be possible).
+
+## Access
+
+### What user privilege levels does the application support?
+
+- Geo adds one type of privilege: **secondary** nodes can access a special Geo API to
+ download files over HTTP/HTTPS, and to clone repositories using HTTP/HTTPS.
+
+### What user identification and authentication requirements have been defined?
+
+- **Secondary** nodes identify to Geo **primary** nodes via OAuth or JWT authentication
+ based on the shared database (HTTP access) or a PostgreSQL replication user (for
+ database replication). The database replication also requires IP-based access
+ controls to be defined.
+
+### What user authorization requirements have been defined?
+
+- **Secondary** nodes must only be able to *read* data. They are not currently able to mutate data on the **primary** node.
+
+### What session management requirements have been defined?
+
+- Geo JWTs are defined to last for only two minutes before needing to be regenerated.
+- Geo JWTs are generated for one of the following specific scopes:
+ - Geo API access.
+ - Git access.
+ - LFS and File ID.
+ - Upload and File ID.
+ - Job Artifact and File ID.
+
+### What access requirements have been defined for URI and Service calls?
+
+- **Secondary** nodes make many calls to the **primary** node's API. This is how file
+ replication proceeds, for instance. This endpoint is only accessible with a JWT token.
+- The **primary** node also makes calls to the **secondary** node to get status information.
+
+## Application Monitoring
+
+### What application auditing requirements have been defined? How are audit and debug logs accessed, stored, and secured?
+
+- Structured JSON log is written to the filesystem, and can also be ingested
+ into a Kibana installation for further analysis.
diff --git a/doc/administration/geo/replication/troubleshooting.md b/doc/administration/geo/replication/troubleshooting.md
new file mode 100644
index 00000000000..c5bdd36ba70
--- /dev/null
+++ b/doc/administration/geo/replication/troubleshooting.md
@@ -0,0 +1,514 @@
+# Geo Troubleshooting **[PREMIUM ONLY]**
+
+NOTE: **Note:**
+This list is an attempt to document all the moving parts that can go wrong.
+We are working into getting all this steps verified automatically in a
+rake task in the future.
+
+Setting up Geo requires careful attention to details and sometimes it's easy to
+miss a step. Here is a list of questions you should ask to try to detect
+what you need to fix (all commands and path locations are for Omnibus installs):
+
+## First check the health of the **secondary** node
+
+Visit the **primary** node's **Admin Area > Geo** (`/admin/geo/nodes`) in
+your browser. We perform the following health checks on each **secondary** node
+to help identify if something is wrong:
+
+- Is the node running?
+- Is the node's secondary database configured for streaming replication?
+- Is the node's secondary tracking database configured?
+- Is the node's secondary tracking database connected?
+- Is the node's secondary tracking database up-to-date?
+
+![Geo health check](img/geo_node_healthcheck.png)
+
+For information on how to resolve common errors reported from the UI, see [common errors](#common-errors).
+
+If the UI is not working, or you are unable to log in, you can run the Geo
+health check manually to get this information as well as a few more details.
+This rake task can be run on an app node in the **primary** or **secondary**
+Geo nodes:
+
+```sh
+sudo gitlab-rake gitlab:geo:check
+```
+
+Example output:
+
+```
+Checking Geo ...
+
+GitLab Geo is available ... yes
+GitLab Geo is enabled ... yes
+GitLab Geo secondary database is correctly configured ... yes
+Database replication enabled? ... yes
+Database replication working? ... yes
+GitLab Geo tracking database is configured to use Foreign Data Wrapper? ... yes
+GitLab Geo tracking database Foreign Data Wrapper schema is up-to-date? ... yes
+GitLab Geo HTTP(S) connectivity ...
+* Can connect to the primary node ... yes
+HTTP/HTTPS repository cloning is enabled ... yes
+Machine clock is synchronized ... yes
+Git user has default SSH configuration? ... yes
+OpenSSH configured to use AuthorizedKeysCommand ... yes
+GitLab configured to disable writing to authorized_keys file ... yes
+GitLab configured to store new projects in hashed storage? ... yes
+All projects are in hashed storage? ... yes
+
+Checking Geo ... Finished
+```
+
+Current sync information can be found manually by running this rake task on any
+**secondary** app node:
+
+```sh
+sudo gitlab-rake geo:status
+```
+
+Example output:
+
+```
+http://secondary.example.com/
+-----------------------------------------------------
+ GitLab Version: 11.10.4-ee
+ Geo Role: Secondary
+ Health Status: Healthy
+ Repositories: 289/289 (100%)
+ Verified Repositories: 289/289 (100%)
+ Wikis: 289/289 (100%)
+ Verified Wikis: 289/289 (100%)
+ LFS Objects: 8/8 (100%)
+ Attachments: 5/5 (100%)
+ CI job artifacts: 0/0 (0%)
+ Repositories Checked: 0/289 (0%)
+ Sync Settings: Full
+ Database replication lag: 0 seconds
+ Last event ID seen from primary: 10215 (about 2 minutes ago)
+ Last event ID processed by cursor: 10215 (about 2 minutes ago)
+ Last status report was: 2 minutes ago
+```
+
+## Is Postgres replication working?
+
+### Are my nodes pointing to the correct database instance?
+
+You should make sure your **primary** Geo node points to the instance with
+writing permissions.
+
+Any **secondary** nodes should point only to read-only instances.
+
+### Can Geo detect my current node correctly?
+
+Geo uses the defined node from the **Admin Area > Geo** screen, and tries to match
+it with the value defined in the `/etc/gitlab/gitlab.rb` configuration file.
+The relevant line looks like: `external_url "http://gitlab.example.com"`.
+
+To check if the node on the current machine is correctly detected type:
+
+```sh
+sudo gitlab-rails runner "puts Gitlab::Geo.current_node.inspect"
+```
+
+and expect something like:
+
+```
+#<GeoNode id: 2, schema: "https", host: "gitlab.example.com", port: 443, relative_url_root: "", primary: false, ...>
+```
+
+By running the command above, `primary` should be `true` when executed in
+the **primary** node, and `false` on any **secondary** node.
+
+## How do I fix the message, "ERROR: replication slots can only be used if max_replication_slots > 0"?
+
+This means that the `max_replication_slots` PostgreSQL variable needs to
+be set on the **primary** database. In GitLab 9.4, we have made this setting
+default to 1. You may need to increase this value if you have more
+**secondary** nodes. Be sure to restart PostgreSQL for this to take
+effect. See the [PostgreSQL replication
+setup][database-pg-replication] guide for more details.
+
+## How do I fix the message, "FATAL: could not start WAL streaming: ERROR: replication slot "geo_secondary_my_domain_com" does not exist"?
+
+This occurs when PostgreSQL does not have a replication slot for the
+**secondary** node by that name. You may want to rerun the [replication
+process](database.md) on the **secondary** node .
+
+## How do I fix the message, "Command exceeded allowed execution time" when setting up replication?
+
+This may happen while [initiating the replication process][database-start-replication] on the **secondary** node,
+and indicates that your initial dataset is too large to be replicated in the default timeout (30 minutes).
+
+Re-run `gitlab-ctl replicate-geo-database`, but include a larger value for
+`--backup-timeout`:
+
+```sh
+sudo gitlab-ctl \
+ replicate-geo-database \
+ --host=<primary_node_hostname> \
+ --slot-name=<secondary_slot_name> \
+ --backup-timeout=21600
+```
+
+This will give the initial replication up to six hours to complete, rather than
+the default thirty minutes. Adjust as required for your installation.
+
+## How do I fix the message, "PANIC: could not write to file 'pg_xlog/xlogtemp.123': No space left on device"
+
+Determine if you have any unused replication slots in the **primary** database. This can cause large amounts of
+log data to build up in `pg_xlog`. Removing the unused slots can reduce the amount of space used in the `pg_xlog`.
+
+1. Start a PostgreSQL console session:
+
+ ```sh
+ sudo gitlab-psql gitlabhq_production
+ ```
+
+ > Note that using `gitlab-rails dbconsole` will not work, because managing replication slots requires superuser permissions.
+
+1. View your replication slots with:
+
+ ```sql
+ SELECT * FROM pg_replication_slots;
+ ```
+
+Slots where `active` is `f` are not active.
+
+- When this slot should be active, because you have a **secondary** node configured using that slot,
+ log in to that **secondary** node and check the PostgreSQL logs why the replication is not running.
+
+- If you are no longer using the slot (e.g. you no longer have Geo enabled), you can remove it with in the
+ PostgreSQL console session:
+
+ ```sql
+ SELECT pg_drop_replication_slot('<name_of_extra_slot>');
+ ```
+
+## Very large repositories never successfully synchronize on the **secondary** node
+
+GitLab places a timeout on all repository clones, including project imports
+and Geo synchronization operations. If a fresh `git clone` of a repository
+on the primary takes more than a few minutes, you may be affected by this.
+To increase the timeout, add the following line to `/etc/gitlab/gitlab.rb`
+on the **secondary** node:
+
+```ruby
+gitlab_rails['gitlab_shell_git_timeout'] = 10800
+```
+
+Then reconfigure GitLab:
+
+```sh
+sudo gitlab-ctl reconfigure
+```
+
+This will increase the timeout to three hours (10800 seconds). Choose a time
+long enough to accommodate a full clone of your largest repositories.
+
+## How to reset Geo **secondary** node replication
+
+If you get a **secondary** node in a broken state and want to reset the replication state,
+to start again from scratch, there are a few steps that can help you:
+
+1. Stop Sidekiq and the Geo LogCursor
+
+ It's possible to make Sidekiq stop gracefully, but making it stop getting new jobs and
+ wait until the current jobs to finish processing.
+
+ You need to send a **SIGTSTP** kill signal for the first phase and them a **SIGTERM**
+ when all jobs have finished. Otherwise just use the `gitlab-ctl stop` commands.
+
+ ```sh
+ gitlab-ctl status sidekiq
+ # run: sidekiq: (pid 10180) <- this is the PID you will use
+ kill -TSTP 10180 # change to the correct PID
+
+ gitlab-ctl stop sidekiq
+ gitlab-ctl stop geo-logcursor
+ ```
+
+ You can watch sidekiq logs to know when sidekiq jobs processing have finished:
+
+ ```sh
+ gitlab-ctl tail sidekiq
+ ```
+
+1. Rename repository storage folders and create new ones
+
+ ```sh
+ mv /var/opt/gitlab/git-data/repositories /var/opt/gitlab/git-data/repositories.old
+ mkdir -p /var/opt/gitlab/git-data/repositories
+ chown git:git /var/opt/gitlab/git-data/repositories
+ ```
+
+ TIP: **Tip**
+ You may want to remove the `/var/opt/gitlab/git-data/repositories.old` in the future
+ as soon as you confirmed that you don't need it anymore, to save disk space.
+
+1. _(Optional)_ Rename other data folders and create new ones
+
+ CAUTION: **Caution**:
+ You may still have files on the **secondary** node that have been removed from **primary** node but
+ removal have not been reflected. If you skip this step, they will never be removed
+ from this Geo node.
+
+ Any uploaded content like file attachments, avatars or LFS objects are stored in a
+ subfolder in one of the two paths below:
+
+ 1. /var/opt/gitlab/gitlab-rails/shared
+ 1. /var/opt/gitlab/gitlab-rails/uploads
+
+ To rename all of them:
+
+ ```sh
+ gitlab-ctl stop
+
+ mv /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-rails/shared.old
+ mkdir -p /var/opt/gitlab/gitlab-rails/shared
+
+ mv /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/uploads.old
+ mkdir -p /var/opt/gitlab/gitlab-rails/uploads
+ ```
+
+ Reconfigure in order to recreate the folders and make sure permissions and ownership
+ are correctly
+
+ ```sh
+ gitlab-ctl reconfigure
+ ```
+
+1. Reset the Tracking Database
+
+ ```sh
+ gitlab-rake geo:db:reset
+ ```
+
+1. Restart previously stopped services
+
+ ```sh
+ gitlab-ctl start
+ ```
+
+## How do I fix a "Foreign Data Wrapper (FDW) is not configured" error?
+
+When setting up Geo, you might see this warning in the `gitlab-rake
+gitlab:geo:check` output:
+
+```
+GitLab Geo tracking database Foreign Data Wrapper schema is up-to-date? ... foreign data wrapper is not configured
+```
+
+There are a few key points to remember:
+
+1. The FDW settings are configured on the Geo **tracking** database.
+1. The configured foreign server enables a login to the Geo
+**secondary**, read-only database.
+
+By default, the Geo secondary and tracking database are running on the
+same host on different ports. That is, 5432 and 5431 respectively.
+
+### Checking configuration
+
+NOTE: **Note:**
+The following steps are for Omnibus installs only. Using Geo with source-based installs was **deprecated** in GitLab 11.5.
+
+To check the configuration:
+
+1. Enter the database console:
+
+ ```sh
+ gitlab-geo-psql
+ ```
+
+1. Check whether any tables are present. If everything is working, you
+should see something like this:
+
+ ```sql
+ gitlabhq_geo_production=# SELECT * from information_schema.foreign_tables;
+ foreign_table_catalog | foreign_table_schema | foreign_table_name | foreign_server_catalog | foreign_server_n
+ ame
+ -------------------------+----------------------+-------------------------------------------------+-------------------------+-----------------
+ ----
+ gitlabhq_geo_production | gitlab_secondary | abuse_reports | gitlabhq_geo_production | gitlab_secondary
+ gitlabhq_geo_production | gitlab_secondary | appearances | gitlabhq_geo_production | gitlab_secondary
+ gitlabhq_geo_production | gitlab_secondary | application_setting_terms | gitlabhq_geo_production | gitlab_secondary
+ gitlabhq_geo_production | gitlab_secondary | application_settings | gitlabhq_geo_production | gitlab_secondary
+ <snip>
+ ```
+
+ However, if the query returns with `0 rows`, then continue onto the next steps.
+
+1. Check that the foreign server mapping is correct via `\des+`. The
+ results should look something like this:
+
+ ```sql
+ gitlabhq_geo_production=# \des+
+ List of foreign servers
+ -[ RECORD 1 ]--------+------------------------------------------------------------
+ Name | gitlab_secondary
+ Owner | gitlab-psql
+ Foreign-data wrapper | postgres_fdw
+ Access privileges | "gitlab-psql"=U/"gitlab-psql" +
+ | gitlab_geo=U/"gitlab-psql"
+ Type |
+ Version |
+ FDW Options | (host '0.0.0.0', port '5432', dbname 'gitlabhq_production')
+ Description |
+ ```
+
+ NOTE: **Note:** Pay particular attention to the host and port under
+ FDW options. That configuration should point to the Geo secondary
+ database.
+
+ If you need to experiment with changing the host or password, the
+ following queries demonstrate how:
+
+ ```sql
+ ALTER SERVER gitlab_secondary OPTIONS (SET host '<my_new_host>');
+ ALTER SERVER gitlab_secondary OPTIONS (SET port 5432);
+ ```
+
+ If you change the host and/or port, you will also have to adjust the
+ following settings in `/etc/gitlab/gitlab.rb` and run `gitlab-ctl
+ reconfigure`:
+
+ - `gitlab_rails['db_host']`
+ - `gitlab_rails['db_port']`
+
+1. Check that the user mapping is configured properly via `\deu+`:
+
+ ```sql
+ gitlabhq_geo_production=# \deu+
+ List of user mappings
+ Server | User name | FDW Options
+ ------------------+------------+--------------------------------------------------------------------------------
+ gitlab_secondary | gitlab_geo | ("user" 'gitlab', password 'YOUR-PASSWORD-HERE')
+ (1 row)
+ ```
+
+ Make sure the password is correct. You can test that logins work by running `psql`:
+
+ ```sh
+ # Connect to the tracking database as the `gitlab_geo` user
+ sudo \
+ -u git /opt/gitlab/embedded/bin/psql \
+ -h /var/opt/gitlab/geo-postgresql \
+ -p 5431 \
+ -U gitlab_geo \
+ -W \
+ -d gitlabhq_geo_production
+ ```
+
+ If you need to correct the password, the following query shows how:
+
+ ```sql
+ ALTER USER MAPPING FOR gitlab_geo SERVER gitlab_secondary OPTIONS (SET password '<my_new_password>');
+ ```
+
+ If you change the user or password, you will also have to adjust the
+ following settings in `/etc/gitlab/gitlab.rb` and run `gitlab-ctl
+ reconfigure`:
+
+ - `gitlab_rails['db_username']`
+ - `gitlab_rails['db_password']`
+
+ If you are using [PgBouncer in front of the secondary
+ database](database.md#pgbouncer-support-optional), be sure to update
+ the following settings:
+
+ - `geo_postgresql['fdw_external_user']`
+ - `geo_postgresql['fdw_external_password']`
+
+### Manual reload of FDW schema
+
+If you're still unable to get FDW working, you may want to try a manual
+reload of the FDW schema. To manually reload the FDW schema:
+
+1. On the node running the Geo tracking database, enter the PostgreSQL console via
+ the `gitlab_geo` user:
+
+ ```sh
+ sudo \
+ -u git /opt/gitlab/embedded/bin/psql \
+ -h /var/opt/gitlab/geo-postgresql \
+ -p 5431 \
+ -U gitlab_geo \
+ -W \
+ -d gitlabhq_geo_production
+ ```
+
+ Be sure to adjust the port and hostname for your configuration. You
+ may be asked to enter a password.
+
+1. Reload the schema via:
+
+ ```sql
+ DROP SCHEMA IF EXISTS gitlab_secondary CASCADE;
+ CREATE SCHEMA gitlab_secondary;
+ GRANT USAGE ON FOREIGN SERVER gitlab_secondary TO gitlab_geo;
+ IMPORT FOREIGN SCHEMA public FROM SERVER gitlab_secondary INTO gitlab_secondary;
+ ```
+
+1. Test that queries work:
+
+ ```sql
+ SELECT * from information_schema.foreign_tables;
+ SELECT * FROM gitlab_secondary.projects limit 1;
+ ```
+
+[database-start-replication]: database.md#step-3-initiate-the-replication-process
+[database-pg-replication]: database.md#postgresql-replication
+
+## Common errors
+
+This section documents common errors reported in the admin UI and how to fix them.
+
+### Geo database configuration file is missing
+
+GitLab cannot find or doesn't have permission to access the `database_geo.yml` configuration file.
+
+In an Omnibus GitLab installation, the file should be in `/var/opt/gitlab/gitlab-rails/etc`.
+If it doesn't exist or inadvertent changes have been made to it, run `sudo gitlab-ctl reconfigure` to restore it to its correct state.
+
+
+If this path is mounted on a remote volume, please check your volume configuration and that it has correct permissions.
+
+### Geo node has a database that is writable which is an indication it is not configured for replication with the primary node.
+
+This error refers to a problem with the database replica on a **secondary** node,
+which Geo expects to have access to. It usually means, either:
+
+- An unsupported replication method was used (for example, logical replication).
+- The instructions to setup a [Geo database replication](database.md) were not followed correctly.
+
+A common source of confusion with **secondary** nodes is that it requires two separate
+PostgreSQL instances:
+
+- A read-only replica of the **primary** node.
+- A regular, writable instance that holds replication metadata. That is, the Geo tracking database.
+
+### Geo node does not appear to be replicating the database from the primary node.
+
+The most common problems that prevent the database from replicating correctly are:
+
+- **Secondary** nodes cannot reach the **primary** node. Check credentials, firewall rules, etc.
+- SSL certificate problems. Make sure you copied `/etc/gitlab/gitlab-secrets.json` from the **primary** node.
+- Database storage disk is full.
+- Database replication slot is misconfigured.
+- Database is not using a replication slot or another alternative and cannot catch-up because WAL files were purged.
+
+Make sure you follow the [Geo database replication](database.md) instructions for supported configuration.
+
+### Geo database version (...) does not match latest migration (...)
+
+If you are using GitLab Omnibus installation, something might have failed during upgrade. You can:
+
+- Run `sudo gitlab-ctl reconfigure`.
+- Manually trigger the database migration by running: `sudo gitlab-rake geo:db:migrate` as root on the **secondary** node.
+
+### Geo database is not configured to use Foreign Data Wrapper
+
+This error means the Geo Tracking Database doesn't have the FDW server and credentials
+configured.
+
+See [How do I fix a "Foreign Data Wrapper (FDW) is not configured" error?](#how-do-i-fix-a-foreign-data-wrapper-fdw-is-not-configured-error).
diff --git a/doc/administration/geo/replication/tuning.md b/doc/administration/geo/replication/tuning.md
new file mode 100644
index 00000000000..1943f2230df
--- /dev/null
+++ b/doc/administration/geo/replication/tuning.md
@@ -0,0 +1,17 @@
+# Tuning Geo **[PREMIUM ONLY]**
+
+## Changing the sync capacity values
+
+In the Geo admin page (`/admin/geo/nodes`), there are several variables that
+can be tuned to improve performance of Geo:
+
+- Repository sync capacity.
+- File sync capacity.
+
+Increasing these values will increase the number of jobs that are scheduled.
+However, this may not lead to more downloads in parallel unless the number of
+available Sidekiq threads is also increased. For example, if repository sync
+capacity is increased from 25 to 50, you may also want to increase the number
+of Sidekiq threads from 25 to 50. See the
+[Sidekiq concurrency documentation](../../operations/extra_sidekiq_processes.md#number-of-threads)
+for more details.
diff --git a/doc/administration/geo/replication/updating_the_geo_nodes.md b/doc/administration/geo/replication/updating_the_geo_nodes.md
new file mode 100644
index 00000000000..933a75c47d8
--- /dev/null
+++ b/doc/administration/geo/replication/updating_the_geo_nodes.md
@@ -0,0 +1,448 @@
+# Updating the Geo nodes **[PREMIUM ONLY]**
+
+Depending on which version of Geo you are updating to/from, there may be
+different steps.
+
+## General update steps
+
+In order to update the Geo nodes when a new GitLab version is released,
+all you need to do is update GitLab itself:
+
+1. Log into each node (**primary** and **secondary** nodes).
+1. [Update GitLab][update].
+1. [Update tracking database on **secondary** node](#update-tracking-database-on-secondary-node) when
+ the tracking database is enabled.
+1. [Test](#check-status-after-updating) **primary** and **secondary** nodes, and check version in each.
+
+## Upgrading to GitLab 10.8
+
+Before 10.8, broadcast messages would not propagate without flushing the cache on the **secondary** nodes. This has been fixed in 10.8, but requires one last cache flush on each **secondary** node:
+
+```sh
+sudo gitlab-rake cache:clear
+```
+
+## Upgrading to GitLab 10.6
+
+In 10.4, we started to recommend that you define a password for database user (`gitlab`).
+
+We now require this change as we use this password to enable the Foreign Data Wrapper, as a way to optimize
+the Geo Tracking Database. We are also improving security by disabling the use of **trust**
+authentication method.
+
+1. **[primary]** Login to your **primary** node and run:
+
+ ```sh
+ gitlab-ctl pg-password-md5 gitlab
+ # Enter password: <your_password_here>
+ # Confirm password: <your_password_here>
+ # fca0b89a972d69f00eb3ec98a5838484
+ ```
+
+ Copy the generated hash and edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ # Fill with the hash generated by `gitlab-ctl pg-password-md5 gitlab`
+ postgresql['sql_user_password'] = '<md5_hash_of_your_password>'
+
+ # Every node that runs Unicorn or Sidekiq needs to have the database
+ # password specified as below. If you have a high-availability setup, this
+ # must be present in all application nodes.
+ gitlab_rails['db_password'] = '<your_password_here>'
+ ```
+
+ Still in the configuration file, locate and remove the `trust_auth_cidr_address`:
+
+ ```ruby
+ postgresql['trust_auth_cidr_addresses'] = ['127.0.0.1/32','1.2.3.4/32'] # <- Remove this
+ ```
+
+1. **[primary]** Reconfigure and restart:
+
+ ```sh
+ sudo gitlab-ctl reconfigure
+ sudo gitlab-ctl restart
+ ```
+
+1. **[secondary]** Login to all **secondary** nodes and edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ # Fill with the hash generated by `gitlab-ctl pg-password-md5 gitlab`
+ postgresql['sql_user_password'] = '<md5_hash_of_your_password>'
+
+ # Every node that runs Unicorn or Sidekiq needs to have the database
+ # password specified as below. If you have a high-availability setup, this
+ # must be present in all application nodes.
+ gitlab_rails['db_password'] = '<your_password_here>'
+
+ # Enable Foreign Data Wrapper
+ geo_secondary['db_fdw'] = true
+
+ # Secondary address in CIDR format, for example '5.6.7.8/32'
+ postgresql['md5_auth_cidr_addresses'] = ['<secondary_node_ip>/32']
+ ```
+
+ Still in the configuration file, locate and remove the `trust_auth_cidr_address`:
+
+ ```ruby
+ postgresql['trust_auth_cidr_addresses'] = ['127.0.0.1/32','5.6.7.8/32'] # <- Remove this
+ ```
+
+1. **[secondary]** Reconfigure and restart:
+
+ ```sh
+ sudo gitlab-ctl reconfigure
+ sudo gitlab-ctl restart
+ ```
+
+## Upgrading to GitLab 10.5
+
+For Geo Disaster Recovery to work with minimum downtime, your **secondary** node
+should use the same set of secrets as the **primary** node. However, setup instructions
+prior to the 10.5 release only synchronized the `db_key_base` secret.
+
+To rectify this error on existing installations, you should **overwrite** the
+contents of `/etc/gitlab/gitlab-secrets.json` on each **secondary** node with the
+contents of `/etc/gitlab/gitlab-secrets.json` on the **primary** node, then run the
+following command on each **secondary** node:
+
+```sh
+sudo gitlab-ctl reconfigure
+```
+
+If you do not perform this step, you may find that two-factor authentication
+[is broken following DR](../disaster_recovery/index.html#i-followed-the-disaster-recovery-instructions-and-now-two-factor-auth-is-broken).
+
+To prevent SSH requests to the newly promoted **primary** node from failing
+due to SSH host key mismatch when updating the **primary** node domain's DNS record
+you should perform the step to [Manually replicate **primary** SSH host keys](configuration.md#step-2-manually-replicate-the-primary-nodes-ssh-host-keys) in each
+**secondary** node.
+
+## Upgrading to GitLab 10.4
+
+There are no Geo-specific steps to take!
+
+## Upgrading to GitLab 10.3
+
+### Support for SSH repository synchronization removed
+
+In GitLab 10.2, synchronizing secondaries over SSH was deprecated. In 10.3,
+support is removed entirely. All installations will switch to the HTTP/HTTPS
+cloning method instead. Before upgrading, ensure that all your Geo nodes are
+configured to use this method and that it works for your installation. In
+particular, ensure that [Git access over HTTP/HTTPS is enabled](configuration.md#step-6-enable-git-access-over-httphttps).
+
+Synchronizing repositories over the public Internet using HTTP is insecure, so
+you should ensure that you have HTTPS configured before upgrading. Note that
+file synchronization is **also** insecure in these cases!
+
+## Upgrading to GitLab 10.2
+
+### Secure PostgreSQL replication
+
+Support for TLS-secured PostgreSQL replication has been added. If you are
+currently using PostgreSQL replication across the open internet without an
+external means of securing the connection (e.g., a site-to-site VPN), then you
+should immediately reconfigure your **primary** and **secondary** PostgreSQL instances
+according to the [updated instructions][database].
+
+If you *are* securing the connections externally and wish to continue doing so,
+ensure you include the new option `--sslmode=prefer` in future invocations of
+`gitlab-ctl replicate-geo-database`.
+
+### HTTPS repository sync
+
+Support for replicating repositories and wikis over HTTP/HTTPS has been added.
+Replicating over SSH has been deprecated, and support for this option will be
+removed in a future release.
+
+To switch to HTTP/HTTPS replication, log into the **primary** node as an admin and visit
+**Admin Area > Geo** (`/admin/geo/nodes`). For each **secondary** node listed,
+press the "Edit" button, change the "Repository cloning" setting from
+"SSH (deprecated)" to "HTTP/HTTPS", and press "Save changes". This should take
+effect immediately.
+
+Any new secondaries should be created using HTTP/HTTPS replication - this is the
+default setting.
+
+After you've verified that HTTP/HTTPS replication is working, you should remove
+the now-unused SSH keys from your secondaries, as they may cause problems if the
+**secondary** node if ever promoted to a **primary** node:
+
+1. **[secondary]** Login to **all** your **secondary** nodes and run:
+
+ ```ruby
+ sudo -u git -H rm ~git/.ssh/id_rsa ~git/.ssh/id_rsa.pub
+ ```
+
+### Hashed Storage
+
+CAUTION: **Warning:**
+Hashed storage is in **Alpha**. It is considered experimental and not
+production-ready. See [Hashed Storage] for more detail.
+
+If you previously enabled Hashed Storage and migrated all your existing
+projects to Hashed Storage, disabling hashed storage will not migrate projects
+to their previous project based storage path. As such, once enabled and
+migrated we recommend leaving Hashed Storage enabled.
+
+## Upgrading to GitLab 10.1
+
+CAUTION: **Warning:**
+Hashed storage is in **Alpha**. It is considered experimental and not
+production-ready. See [Hashed Storage] for more detail.
+
+[Hashed storage] was introduced in GitLab 10.0, and a [migration path][hashed-migration]
+for existing repositories was added in GitLab 10.1.
+
+## Upgrading to GitLab 10.0
+
+Since GitLab 10.0, we require all **Geo** systems to [use SSH key lookups via
+the database][ssh-fast-lookup] to avoid having to maintain consistency of the
+`authorized_keys` file for SSH access. Failing to do this will prevent users
+from being able to clone via SSH.
+
+Note that in older versions of Geo, attachments downloaded on the **secondary**
+nodes would be saved to the wrong directory. We recommend that you do the
+following to clean this up.
+
+On the **secondary** Geo nodes, run as root:
+
+```sh
+mv /var/opt/gitlab/gitlab-rails/working /var/opt/gitlab/gitlab-rails/working.old
+mkdir /var/opt/gitlab/gitlab-rails/working
+chmod 700 /var/opt/gitlab/gitlab-rails/working
+chown git:git /var/opt/gitlab/gitlab-rails/working
+```
+
+You may delete `/var/opt/gitlab/gitlab-rails/working.old` any time.
+
+Once this is done, we advise restarting GitLab on the **secondary** nodes for the
+new working directory to be used:
+
+```sh
+sudo gitlab-ctl restart
+```
+
+## Upgrading from GitLab 9.3 or older
+
+If you started running Geo on GitLab 9.3 or older, we recommend that you
+resync your **secondary** PostgreSQL databases to use replication slots. If you
+started using Geo with GitLab 9.4 or 10.x, no further action should be
+required because replication slots are used by default. However, if you
+started with GitLab 9.3 and upgraded later, you should still follow the
+instructions below.
+
+When in doubt, it does not hurt to do a resync. The easiest way to do this in
+Omnibus is the following:
+
+ 1. Make sure you have Omnibus GitLab on the **primary** server.
+ 1. Run `gitlab-ctl reconfigure` and `gitlab-ctl restart postgresql`. This will enable replication slots on the **primary** database.
+ 1. Check the steps about defining `postgresql['sql_user_password']`, `gitlab_rails['db_password']`.
+ 1. Make sure `postgresql['max_replication_slots']` matches the number of **secondary** Geo nodes locations.
+ 1. Install GitLab on the **secondary** server.
+ 1. Re-run the [database replication process][database-replication].
+
+## Special update notes for 9.0.x
+
+> **IMPORTANT**:
+With GitLab 9.0, the PostgreSQL version is upgraded to 9.6 and manual steps are
+required in order to update the **secondary** nodes and keep the Streaming
+Replication working. Downtime is required, so plan ahead.
+
+The following steps apply only if you upgrade from a 8.17 GitLab version to
+9.0+. For previous versions, update to GitLab 8.17 first before attempting to
+upgrade to 9.0+.
+
+---
+
+Make sure to follow the steps in the exact order as they appear below and pay
+extra attention in what node (either **primary** or **secondary**) you execute them! Each step
+is prepended with the relevant node for better clarity:
+
+1. **[secondary]** Login to **all** your **secondary** nodes and stop all services:
+
+ ```ruby
+ sudo gitlab-ctl stop
+ ```
+
+1. **[secondary]** Make a backup of the `recovery.conf` file on **all**
+ **secondary** nodes to preserve PostgreSQL's credentials:
+
+ ```sh
+ sudo cp /var/opt/gitlab/postgresql/data/recovery.conf /var/opt/gitlab/
+ ```
+
+1. **[primary]** Update the **primary** node to GitLab 9.0 following the
+ [regular update docs][update]. At the end of the update, the **primary** node
+ will be running with PostgreSQL 9.6.
+
+1. **[primary]** To prevent a de-synchronization of the repository replication,
+ stop all services except `postgresql` as we will use it to re-initialize the
+ **secondary** node's database:
+
+ ```sh
+ sudo gitlab-ctl stop
+ sudo gitlab-ctl start postgresql
+ ```
+
+1. **[secondary]** Run the following steps on each of the **secondary** nodes:
+
+ 1. **[secondary]** Stop all services:
+
+ ```sh
+ sudo gitlab-ctl stop
+ ```
+
+ 1. **[secondary]** Prevent running database migrations:
+
+ ```sh
+ sudo touch /etc/gitlab/skip-auto-migrations
+ ```
+
+ 1. **[secondary]** Move the old database to another directory:
+
+ ```sh
+ sudo mv /var/opt/gitlab/postgresql{,.bak}
+ ```
+
+ 1. **[secondary]** Update to GitLab 9.0 following the [regular update docs][update].
+ At the end of the update, the node will be running with PostgreSQL 9.6.
+
+ 1. **[secondary]** Make sure all services are up:
+
+ ```sh
+ sudo gitlab-ctl start
+ ```
+
+ 1. **[secondary]** Reconfigure GitLab:
+
+ ```sh
+ sudo gitlab-ctl reconfigure
+ ```
+
+ 1. **[secondary]** Run the PostgreSQL upgrade command:
+
+ ```sh
+ sudo gitlab-ctl pg-upgrade
+ ```
+
+ 1. **[secondary]** See the stored credentials for the database that you will
+ need to re-initialize the replication:
+
+ ```sh
+ sudo grep -s primary_conninfo /var/opt/gitlab/recovery.conf
+ ```
+
+ 1. **[secondary]** Create the `replica.sh` script as described in the
+ [database configuration document][database-source-replication].
+
+ 1. 1. **[secondary]** Save the snippet below in a file, let's say `/tmp/replica.sh`. Modify the
+ embedded paths if necessary:
+
+ ```
+ #!/bin/bash
+
+ PORT="5432"
+ USER="gitlab_replicator"
+ echo ---------------------------------------------------------------
+ echo WARNING: Make sure this script is run from the secondary server
+ echo ---------------------------------------------------------------
+ echo
+ echo Enter the IP or FQDN of the primary PostgreSQL server
+ read HOST
+ echo Enter the password for $USER@$HOST
+ read -s PASSWORD
+ echo Enter the required sslmode
+ read SSLMODE
+
+ echo Stopping PostgreSQL and all GitLab services
+ sudo service gitlab stop
+ sudo service postgresql stop
+
+ echo Backing up postgresql.conf
+ sudo -u postgres mv /var/opt/gitlab/postgresql/data/postgresql.conf /var/opt/gitlab/postgresql/
+
+ echo Cleaning up old cluster directory
+ sudo -u postgres rm -rf /var/opt/gitlab/postgresql/data
+
+ echo Starting base backup as the replicator user
+ echo Enter the password for $USER@$HOST
+ sudo -u postgres /opt/gitlab/embedded/bin/pg_basebackup -h $HOST -D /var/opt/gitlab/postgresql/data -U gitlab_replicator -v -x -P
+
+ echo Writing recovery.conf file
+ sudo -u postgres bash -c "cat > /var/opt/gitlab/postgresql/data/recovery.conf <<- _EOF1_
+ standby_mode = 'on'
+ primary_conninfo = 'host=$HOST port=$PORT user=$USER password=$PASSWORD sslmode=$SSLMODE'
+ _EOF1_
+ "
+
+ echo Restoring postgresql.conf
+ sudo -u postgres mv /var/opt/gitlab/postgresql/postgresql.conf /var/opt/gitlab/postgresql/data/
+
+ echo Starting PostgreSQL
+ sudo service postgresql start
+ ```
+
+ 1. **[secondary]** Run the recovery script using the credentials from the
+ previous step:
+
+ ```sh
+ sudo bash /tmp/replica.sh
+ ```
+
+ 1. **[secondary]** Reconfigure GitLab:
+
+ ```sh
+ sudo gitlab-ctl reconfigure
+ ```
+
+ 1. **[secondary]** Start all services:
+
+ ```sh
+ sudo gitlab-ctl start
+ ```
+
+ 1. **[secondary]** Repeat the steps for the remaining **secondary** nodes.
+
+1. **[primary]** After all **secondary** nodes are updated, start all services in
+ **primary** node:
+
+ ```sh
+ sudo gitlab-ctl start
+ ```
+
+## Check status after updating
+
+Now that the update process is complete, you may want to check whether
+everything is working correctly:
+
+1. Run the Geo raketask on all nodes, everything should be green:
+
+ ```sh
+ sudo gitlab-rake gitlab:geo:check
+ ```
+
+1. Check the **primary** node's Geo dashboard for any errors.
+1. Test the data replication by pushing code to the **primary** node and see if it
+ is received by **secondary** nodes.
+
+## Update tracking database on **secondary** node
+
+After updating a **secondary** node, you might need to run migrations on
+the tracking database. The tracking database was added in GitLab 9.1,
+and it is required since 10.0.
+
+1. Run database migrations on tracking database:
+
+ ```sh
+ sudo gitlab-rake geo:db:migrate
+ ```
+
+1. Repeat this step for each **secondary** node.
+
+[update]: ../../../update/README.md
+[database]: database.md
+[Hashed Storage]: ../../repository_storage_types.md
+[hashed-migration]: ../../raketasks/storage.md
+[ssh-fast-lookup]: ../../operations/fast_ssh_key_lookup.md
diff --git a/doc/administration/geo/replication/using_a_geo_server.md b/doc/administration/geo/replication/using_a_geo_server.md
new file mode 100644
index 00000000000..f1f1fe48748
--- /dev/null
+++ b/doc/administration/geo/replication/using_a_geo_server.md
@@ -0,0 +1,18 @@
+[//]: # (Please update EE::GitLab::GeoGitAccess::GEO_SERVER_DOCS_URL if this file is moved)
+
+# Using a Geo Server **[PREMIUM ONLY]**
+
+After you set up the [database replication and configure the Geo nodes][req], use your closest GitLab node as you would a normal standalone GitLab instance.
+
+Pushing directly to a **secondary** node (for both HTTP, SSH including git-lfs) was [introduced](https://about.gitlab.com/2018/09/22/gitlab-11-3-released/) in [GitLab Premium](https://about.gitlab.com/pricing/#self-managed) 11.3.
+
+Example of the output you will see when pushing to a **secondary** node:
+
+```bash
+$ git push
+> GitLab: You're pushing to a Geo secondary.
+> GitLab: We'll help you by proxying this request to the primary: ssh://git@primary.geo/user/repo.git
+Everything up-to-date
+```
+
+[req]: index.md#setup-instructions
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index f1cedb85455..53a85dfad6c 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -53,6 +53,10 @@ But since 11.8 the indexer uses Gitaly for data access as well. NFS can still
be leveraged for redudancy on block level of the Git data. But only has to
be mounted on the Gitaly server.
+NOTE: **Note:** While Gitaly can be used as a replacement for NFS, we do not recommend
+using EFS as it may impact GitLab's performance. Please review the [relevant documentation](../high_availability/nfs.md#avoid-using-awss-elastic-file-system-efs)
+for more details.
+
### Network architecture
- gitlab-rails shards repositories into "repository storages"
@@ -73,18 +77,29 @@ be mounted on the Gitaly server.
- Gitaly servers must not be exposed to the public internet
Gitaly network traffic is unencrypted by default, but supports
-[TLS](#tls-support). Authentication is done through a static token. For
-security in depth, its recommended to use a firewall to restrict access
-to your Gitaly server.
+[TLS](#tls-support). Authentication is done through a static token.
+
+NOTE: **Note:** Gitaly network traffic is unencrypted so we recommend a firewall to
+restrict access to your Gitaly server.
Below we describe how to configure a Gitaly server at address
`gitaly.internal:8075` with secret token `abc123secret`. We assume
your GitLab installation has two repository storages, `default` and
`storage1`.
+### Installation
+
+First install Gitaly using either Omnibus or from source.
+
+Omnibus: [Download/install](https://about.gitlab.com/installation) the Omnibus GitLab
+package you want using **steps 1 and 2** from the GitLab downloads page but
+**_do not_** provide the `EXTERNAL_URL=` value.
+
+Source: [Install Gitaly](../../install/installation.md#install-gitaly)
+
### Client side token configuration
-Start by configuring a token on the client side.
+Configure a token on the client side.
Omnibus installations:
@@ -110,7 +125,7 @@ changes to be picked up.
Next, on the Gitaly server, we need to configure storage paths, enable
the network listener and configure the token.
-Note: if you want to reduce the risk of downtime when you enable
+NOTE: **Note:** if you want to reduce the risk of downtime when you enable
authentication you can temporarily disable enforcement, see [the
documentation on configuring Gitaly
authentication](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/configuration/README.md#authentication)
@@ -122,12 +137,17 @@ the Gitaly server. The easiest way to accomplish this is to copy `/etc/gitlab/gi
from an existing GitLab server to the Gitaly server. Without this shared secret,
Git operations in GitLab will result in an API error.
-> **NOTE:** In most or all cases the storage paths below end in `/repositories` which is
+NOTE: **Note:** In most or all cases the storage paths below end in `/repositories` which is
different than `path` in `git_data_dirs` of Omnibus installations. Check the
directory layout on your Gitaly server to be sure.
Omnibus installations:
+<!--
+updates to following example must also be made at
+https://gitlab.com/charts/gitlab/blob/master/doc/advanced/external-gitaly/external-omnibus-gitaly.md#configure-omnibus-gitlab
+-->
+
```ruby
# /etc/gitlab/gitlab.rb
@@ -147,6 +167,7 @@ gitlab_rails['auto_migrate'] = false
# Configure the gitlab-shell API callback URL. Without this, `git push` will
# fail. This can be your 'front door' GitLab URL or an internal load
# balancer.
+# Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from web server to Gitaly server.
gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
# Make Gitaly accept connections on all network interfaces. You must use
@@ -199,6 +220,9 @@ network, firewall, or name resolution problem preventing your GitLab
server from reaching the Gitaly server then all Gitaly requests will
fail.
+Additionally, you need to
+[disable Rugged if previously manually enabled](../high_availability/nfs.md#improving-nfs-performance-with-gitlab).
+
We assume that your Gitaly server can be reached at
`gitaly.internal:8075` from your GitLab server, and that Gitaly can read and
write to `/mnt/gitlab/default` and `/mnt/gitlab/storage1` respectively.
diff --git a/doc/administration/high_availability/README.md b/doc/administration/high_availability/README.md
index 49fe80fb2a6..d9c80b1ec59 100644
--- a/doc/administration/high_availability/README.md
+++ b/doc/administration/high_availability/README.md
@@ -1,4 +1,4 @@
-# High Availability
+# Scaling and High Availability
GitLab supports several different types of clustering and high-availability.
The solution you choose will be based on the level of scalability and
@@ -13,51 +13,196 @@ of Git, developers can still commit code locally even when GitLab is not
available. However, some GitLab features such as the issue tracker and
Continuous Integration are not available when GitLab is down.
-**Keep in mind that all Highly Available solutions come with a trade-off between
+**Keep in mind that all highly-available solutions come with a trade-off between
cost/complexity and uptime**. The more uptime you want, the more complex the
solution. And the more complex the solution, the more work is involved in
setting up and maintaining it. High availability is not free and every HA
solution should balance the costs against the benefits.
-## Architecture
-
-There are two kinds of setups:
-
-- active/active
-- active/passive
-
-### Active/Active
-
-This architecture scales easily because all application servers handle
-user requests simultaneously. The database, Redis, and GitLab application are
-all deployed on separate servers. The configuration is **only** highly-available
-if the database, Redis and storage are also configured as such.
-
-Follow the steps below to configure an active/active setup:
+There are many options when choosing a highly-available GitLab architecture. We
+recommend engaging with GitLab Support to choose the best architecture for your
+use-case. This page contains some various options and guidelines based on
+experience with GitLab.com and Enterprise Edition on-premises customers.
+
+For a detailed insight into how GitLab scales and configures GitLab.com, you can
+watch [this 1 hour Q&A](https://www.youtube.com/watch?v=uCU8jdYzpac)
+with [John Northrup](https://gitlab.com/northrup), and live questions coming in from some of our customers.
+
+## GitLab Components
+
+The following components need to be considered for a scaled or highly-available
+environment. In many cases components can be combined on the same nodes to reduce
+complexity.
+
+- Unicorn/Workhorse - Web-requests (UI, API, Git over HTTP)
+- Sidekiq - Asynchronous/Background jobs
+- PostgreSQL - Database
+ - Consul - Database service discovery and health checks/failover
+ - PGBouncer - Database pool manager
+- Redis - Key/Value store (User sessions, cache, queue for Sidekiq)
+ - Sentinel - Redis health check/failover manager
+- Gitaly - Provides high-level RPC access to Git repositories
+
+## Scalable Architecture Examples
+
+When an organization reaches a certain threshold it will be necessary to scale
+the GitLab instance. Still, true high availability may not be necessary. There
+are options for scaling GitLab instances relatively easily without incurring the
+infrastructure and maintenance costs of full high availability.
+
+### Basic Scaling
+
+This is the simplest form of scaling and will work for the majority of
+cases. Backend components such as PostgreSQL, Redis and storage are offloaded
+to their own nodes while the remaining GitLab components all run on 2 or more
+application nodes.
+
+This form of scaling also works well in a cloud environment when it is more
+cost-effective to deploy several small nodes rather than a single
+larger one.
+
+- 1 PostgreSQL node
+- 1 Redis node
+- 1 NFS/Gitaly storage server
+- 2 or more GitLab application nodes (Unicorn, Workhorse, Sidekiq)
+
+#### Installation Instructions
+
+Complete the following installation steps in order. A link at the end of each
+section will bring you back to the Scalable Architecture Examples section so
+you can continue with the next step.
+
+1. [PostgreSQL](database.md#postgresql-in-a-scaled-environment)
+1. [Redis](redis.md#redis-in-a-scaled-environment)
+1. [Gitaly](gitaly.md) (recommended) or [NFS](nfs.md)
+1. [GitLab application nodes](gitlab.md)
+
+### Full Scaling
+
+For very large installations it may be necessary to further split components
+for maximum scalability. In a fully-scaled architecture the application node
+is split into separate Sidekiq and Unicorn/Workhorse nodes. One indication that
+this architecture is required is if Sidekiq queues begin to periodically increase
+in size, indicating that there is contention or not enough resources.
+
+- 1 PostgreSQL node
+- 1 Redis node
+- 2 or more NFS/Gitaly storage servers
+- 2 or more Sidekiq nodes
+- 2 or more GitLab application nodes (Unicorn, Workhorse)
+
+## High Availability Architecture Examples
+
+When organizations require scaling *and* high availability the following
+architectures can be utilized. As the introduction section at the top of this
+page mentions, there is a tradeoff between cost/complexity and uptime. Be sure
+this complexity is absolutely required before taking the step into full
+high availability.
+
+For all examples below, we recommend running Consul and Redis Sentinel on
+dedicated nodes. If Consul is running on PostgreSQL nodes or Sentinel on
+Redis nodes there is a potential that high resource usage by PostgreSQL or
+Redis could prevent communication between the other Consul and Sentinel nodes.
+This may lead to the other nodes believing a failure has occurred and automated
+failover is necessary. Isolating them from the services they monitor reduces
+the chances of split-brain.
+
+The examples below do not really address high availability of NFS. Some enterprises
+have access to NFS appliances that manage availability. This is the best case
+scenario. In the future, GitLab may offer a more user-friendly solution to
+[GitLab HA Storage](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/2472).
+
+There are many options in between each of these examples. Work with GitLab Support
+to understand the best starting point for your workload and adapt from there.
+
+### Horizontal
+
+This is the simplest form of high availability and scaling. It requires the
+fewest number of individual servers (virtual or physical) but does have some
+trade-offs and limits.
+
+This architecture will work well for many GitLab customers. Larger customers
+may begin to notice certain events cause contention/high load - for example,
+cloning many large repositories with binary files, high API usage, a large
+number of enqueued Sidekiq jobs, etc. If this happens you should consider
+moving to a hybrid or fully distributed architecture depending on what is causing
+the contention.
+
+- 3 PostgreSQL nodes
+- 2 Redis nodes
+- 3 Consul/Sentinel nodes
+- 2 or more GitLab application nodes (Unicorn, Workhorse, Sidekiq, PGBouncer)
+- 1 NFS/Gitaly server
+
+![Horizontal architecture diagram](img/horizontal.png)
+
+### Hybrid
+
+In this architecture, certain components are split on dedicated nodes so high
+resource usage of one component does not interfere with others. In larger
+environments this is a good architecture to consider if you foresee or do have
+contention due to certain workloads.
+
+- 3 PostgreSQL nodes
+- 1 PgBouncer node
+- 2 Redis nodes
+- 3 Consul/Sentinel nodes
+- 2 or more Sidekiq nodes
+- 2 or more GitLab application nodes (Unicorn, Workhorse)
+- 1 or more NFS/Gitaly servers
+- 1 Monitoring node (Prometheus, Grafana)
+
+![Hybrid architecture diagram](img/hybrid.png)
+
+#### Reference Architecture
+
+- **Status:** Work-in-progress
+- **Supported Users (approximate):** 10,000
+- **Related Issues:** [gitlab-com/support/support-team-meta#1513](https://gitlab.com/gitlab-com/support/support-team-meta/issues/1513),
+ [gitlab-org/quality/team-tasks#110](https://gitlab.com/gitlab-org/quality/team-tasks/issues/110)
+
+The Support and Quality teams are in the process of building and performance testing
+an environment that will support about 10,000 users. The specifications below
+are a work-in-progress representation of the work so far. Quality will be
+certifying this environment in FY20-Q2. The specifications may be adjusted
+prior to certification based on performance testing.
+
+- 3 PostgreSQL - 4 CPU, 8GB RAM
+- 1 PgBouncer - 2 CPU, 4GB RAM
+- 2 Redis - 2 CPU, 8GB RAM
+- 3 Consul/Sentinel - 2 CPU, 2GB RAM
+- 4 Sidekiq - 4 CPU, 8GB RAM
+- 5 GitLab application nodes - 20 CPU, 64GB RAM
+- 1 Gitaly - 20 CPU, 64GB RAM
+- 1 Monitoring node - 4 CPU, 8GB RAM
+
+### Fully Distributed
+
+This architecture scales to hundreds of thousands of users and projects and is
+the basis of the GitLab.com architecture. While this scales well it also comes
+with the added complexity of many more nodes to configure, manage and monitor.
+
+- 3 PostgreSQL nodes
+- 4 or more Redis nodes (2 separate clusters for persistent and cache data)
+- 3 Consul nodes
+- 3 Sentinel nodes
+- Multiple dedicated Sidekiq nodes (Split into real-time, best effort, ASAP,
+ CI Pipeline and Pull Mirror sets)
+- 2 or more Git nodes (Git over SSH/Git over HTTP)
+- 2 or more API nodes (All requests to `/api`)
+- 2 or more Web nodes (All other web requests)
+- 2 or more NFS/Gitaly servers
+
+![Fully Distributed architecture diagram](img/fully-distributed.png)
+
+The following pages outline the steps necessary to configure each component
+separately:
1. [Configure the database](database.md)
1. [Configure Redis](redis.md)
1. [Configure Redis for GitLab source installations](redis_source.md)
1. [Configure NFS](nfs.md)
+ 1. [NFS Client and Host setup](nfs_host_client_setup.md)
1. [Configure the GitLab application servers](gitlab.md)
1. [Configure the load balancers](load_balancer.md)
-![Active/Active HA Diagram](../img/high_availability/active-active-diagram.png)
-
-### Active/Passive
-
-For pure high-availability/failover with no scaling you can use an
-active/passive configuration. This utilizes DRBD (Distributed Replicated
-Block Device) to keep all data in sync. DRBD requires a low latency link to
-remain in sync. It is not advisable to attempt to run DRBD between data centers
-or in different cloud availability zones.
-
-> **Note:** GitLab recommends against choosing this HA method because of the
- complexity of managing DRBD and crafting automatic failover. This is
- *compatible* with GitLab, but not officially *supported*. If you are
- an EE customer, support will help you with GitLab related problems, but if the
- root cause is identified as DRBD, we will not troubleshoot further.
-
-Components/Servers Required: 2 servers/virtual machines (one active/one passive)
-
-![Active/Passive HA Diagram](../img/high_availability/active-passive-diagram.png)
diff --git a/doc/administration/high_availability/alpha_database.md b/doc/administration/high_availability/alpha_database.md
new file mode 100644
index 00000000000..7bf20be60e6
--- /dev/null
+++ b/doc/administration/high_availability/alpha_database.md
@@ -0,0 +1,6 @@
+---
+redirect_to: 'database.md'
+---
+
+This documentation has been moved to the main
+[database documentation](database.md#configure_using_omnibus_for_high_availability).
diff --git a/doc/administration/high_availability/consul.md b/doc/administration/high_availability/consul.md
new file mode 100644
index 00000000000..056b7fc15d9
--- /dev/null
+++ b/doc/administration/high_availability/consul.md
@@ -0,0 +1,105 @@
+# Working with the bundled Consul service **[PREMIUM ONLY]**
+
+## Overview
+
+As part of its High Availability stack, GitLab Premium includes a bundled version of [Consul](http://consul.io) that can be managed through `/etc/gitlab/gitlab.rb`.
+
+A Consul cluster consists of multiple server agents, as well as client agents that run on other nodes which need to talk to the consul cluster.
+
+## Operations
+
+### Checking cluster membership
+
+To see which nodes are part of the cluster, run the following on any member in the cluster
+```
+# /opt/gitlab/embedded/bin/consul members
+Node Address Status Type Build Protocol DC
+consul-b XX.XX.X.Y:8301 alive server 0.9.0 2 gitlab_consul
+consul-c XX.XX.X.Y:8301 alive server 0.9.0 2 gitlab_consul
+consul-c XX.XX.X.Y:8301 alive server 0.9.0 2 gitlab_consul
+db-a XX.XX.X.Y:8301 alive client 0.9.0 2 gitlab_consul
+db-b XX.XX.X.Y:8301 alive client 0.9.0 2 gitlab_consul
+```
+
+Ideally all nodes will have a `Status` of `alive`.
+
+### Restarting the server cluster
+
+**Note**: This section only applies to server agents. It is safe to restart client agents whenever needed.
+
+If it is necessary to restart the server cluster, it is important to do this in a controlled fashion in order to maintain quorum. If quorum is lost, you will need to follow the consul [outage recovery](#outage-recovery) process to recover the cluster.
+
+To be safe, we recommend you only restart one server agent at a time to ensure the cluster remains intact.
+
+For larger clusters, it is possible to restart multiple agents at a time. See the [Consul consensus document](https://www.consul.io/docs/internals/consensus.html#deployment-table) for how many failures it can tolerate. This will be the number of simulateneous restarts it can sustain.
+
+## Troubleshooting
+
+### Consul server agents unable to communicate
+
+By default, the server agents will attempt to [bind](https://www.consul.io/docs/agent/options.html#_bind) to '0.0.0.0', but they will advertise the first private IP address on the node for other agents to communicate with them. If the other nodes cannot communicate with a node on this address, then the cluster will have a failed status.
+
+You will see messages like the following in `gitlab-ctl tail consul` output if you are running into this issue:
+
+```
+2017-09-25_19:53:39.90821 2017/09/25 19:53:39 [WARN] raft: no known peers, aborting election
+2017-09-25_19:53:41.74356 2017/09/25 19:53:41 [ERR] agent: failed to sync remote state: No cluster leader
+```
+
+
+To fix this:
+
+1. Pick an address on each node that all of the other nodes can reach this node through.
+1. Update your `/etc/gitlab/gitlab.rb`
+
+ ```ruby
+ consul['configuration'] = {
+ ...
+ bind_addr: 'IP ADDRESS'
+ }
+ ```
+1. Run `gitlab-ctl reconfigure`
+
+If you still see the errors, you may have to [erase the consul database and reinitialize](#recreate-from-scratch) on the affected node.
+
+### Consul agents do not start - Multiple private IPs
+
+In the case that a node has multiple private IPs the agent be confused as to which of the private addresses to advertise, and then immediately exit on start.
+
+You will see messages like the following in `gitlab-ctl tail consul` output if you are running into this issue:
+
+```
+2017-11-09_17:41:45.52876 ==> Starting Consul agent...
+2017-11-09_17:41:45.53057 ==> Error creating agent: Failed to get advertise address: Multiple private IPs found. Please configure one.
+```
+
+To fix this:
+
+1. Pick an address on the node that all of the other nodes can reach this node through.
+1. Update your `/etc/gitlab/gitlab.rb`
+
+ ```ruby
+ consul['configuration'] = {
+ ...
+ bind_addr: 'IP ADDRESS'
+ }
+ ```
+1. Run `gitlab-ctl reconfigure`
+
+### Outage recovery
+
+If you lost enough server agents in the cluster to break quorum, then the cluster is considered failed, and it will not function without manual intervenetion.
+
+#### Recreate from scratch
+By default, GitLab does not store anything in the consul cluster that cannot be recreated. To erase the consul database and reinitialize
+
+```
+# gitlab-ctl stop consul
+# rm -rf /var/opt/gitlab/consul/data
+# gitlab-ctl start consul
+```
+
+After this, the cluster should start back up, and the server agents rejoin. Shortly after that, the client agents should rejoin as well.
+
+#### Recover a failed cluster
+If you have taken advantage of consul to store other data, and want to restore the failed cluster, please follow the [Consul guide](https://www.consul.io/docs/guides/outage.html) to recover a failed cluster.
diff --git a/doc/administration/high_availability/database.md b/doc/administration/high_availability/database.md
index c1eeb40b98f..3b874e5d312 100644
--- a/doc/administration/high_availability/database.md
+++ b/doc/administration/high_availability/database.md
@@ -1,11 +1,6 @@
-# Configuring a Database for GitLab HA
+# Configuring PostgreSQL for Scaling and High Availability
-You can choose to install and manage a database server (PostgreSQL/MySQL)
-yourself, or you can use GitLab Omnibus packages to help. GitLab recommends
-PostgreSQL. This is the database that will be installed if you use the
-Omnibus package to manage your database.
-
-## Configure your own database server
+## Provide your own PostgreSQL instance **[CORE ONLY]**
If you're hosting GitLab on a cloud provider, you can optionally use a
managed service for PostgreSQL. For example, AWS offers a managed Relational
@@ -20,93 +15,1144 @@ If you use a cloud-managed service, or provide your own PostgreSQL:
1. Configure the GitLab application servers with the appropriate details.
This step is covered in [Configuring GitLab for HA](gitlab.md).
-## Configure using Omnibus
+## PostgreSQL in a Scaled Environment
-1. Download/install GitLab Omnibus using **steps 1 and 2** from
- [GitLab downloads](https://about.gitlab.com/downloads). Do not complete other
- steps on the download page.
-1. Create/edit `/etc/gitlab/gitlab.rb` and use the following configuration.
- Be sure to change the `external_url` to match your eventual GitLab front-end
- URL. If there is a directive listed below that you do not see in the configuration, be sure to add it.
+This section is relevant for [Scaled Architecture](README.md#scalable-architecture-examples)
+environments including [Basic Scaling](README.md#basic-scaling) and
+[Full Scaling](README.md#full-scaling).
- ```ruby
- external_url 'https://gitlab.example.com'
+### Provide your own PostgreSQL instance **[CORE ONLY]**
+
+If you want to use your own deployed PostgreSQL instance(s),
+see [Provide your own PostgreSQL instance](#provide-your-own-postgresql-instance-core-only)
+for more details. However, you can use the GitLab Omnibus package to easily
+deploy the bundled PostgreSQL.
+
+### Standalone PostgreSQL using GitLab Omnibus **[CORE ONLY]**
+
+1. SSH into the PostgreSQL server.
+1. [Download/install](https://about.gitlab.com/installation) the Omnibus GitLab
+ package you want using **steps 1 and 2** from the GitLab downloads page.
+ - Do not complete any other steps on the download page.
+1. Generate a password hash for PostgreSQL. This assumes you will use the default
+ username of `gitlab` (recommended). The command will request a password
+ and confirmation. Use the value that is output by this command in the next
+ step as the value of `POSTGRESQL_PASSWORD_HASH`.
+ ```sh
+ sudo gitlab-ctl pg-password-md5 gitlab
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the contents below, updating placeholder
+ values appropriately.
+
+ - `POSTGRESQL_PASSWORD_HASH` - The value output from the previous step
+ - `APPLICATION_SERVER_IP_BLOCKS` - A space delimited list of IP subnets or IP
+ addresses of the GitLab application servers that will connect to the
+ database. Example: `%w(123.123.123.123/32 123.123.123.234/32)`
+
+ ```ruby
# Disable all components except PostgreSQL
roles ['postgres_role']
+ repmgr['enable'] = false
+ consul['enable'] = false
+ prometheus['enable'] = false
+ alertmanager['enable'] = false
+ pgbouncer_exporter['enable'] = false
+ redis_exporter['enable'] = false
+ gitlab_monitor['enable'] = false
+
+ postgresql['listen_address'] = '0.0.0.0'
+ postgresql['port'] = 5432
+
+ # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
+ postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH'
+
+ # Replace XXX.XXX.XXX.XXX/YY with Network Address
+ # ????
+ postgresql['trust_auth_cidr_addresses'] = %w(APPLICATION_SERVER_IP_BLOCKS)
+
+ # Disable automatic database migrations
+ gitlab_rails['auto_migrate'] = false
+ ```
+
+ NOTE: **Note:** The role `postgres_role` was introduced with GitLab 10.3
+
+1. [Reconfigure GitLab] for the changes to take effect.
+1. Note the PostgreSQL node's IP address or hostname, port, and
+ plain text password. These will be necessary when configuring the GitLab
+ application servers later.
+
+Advanced configuration options are supported and can be added if
+needed.
+
+Continue configuration of other components by going
+[back to Scaled Architectures](README.md#scalable-architecture-examples)
+
+## PostgreSQL with High Availability
+
+This section is relevant for [High Availability Architecture](README.md#high-availability-architecture-examples)
+environments including [Horizontal](README.md#horizontal),
+[Hybrid](README.md#hybrid), and
+[Fully Distributed](README.md#fully-distributed).
+
+### Provide your own PostgreSQL instance **[CORE ONLY]**
+
+If you want to use your own deployed PostgreSQL instance(s),
+see [Provide your own PostgreSQL instance](#provide-your-own-postgresql-instance-core-only)
+for more details. However, you can use the GitLab Omnibus package to easily
+deploy the bundled PostgreSQL.
+
+### High Availability with GitLab Omnibus **[PREMIUM ONLY]**
+
+> Important notes:
+>
+> - This document will focus only on configuration supported with [GitLab Premium](https://about.gitlab.com/pricing/), using the Omnibus GitLab package.
+> - If you are a Community Edition or Starter user, consider using a cloud hosted solution.
+> - This document will not cover installations from source.
+>
+> - If HA setup is not what you were looking for, see the [database configuration document](http://docs.gitlab.com/omnibus/settings/database.html)
+> for the Omnibus GitLab packages.
+>
+> Please read this document fully before attempting to configure PostgreSQL HA
+> for GitLab.
+>
+> This configuration is GA in EE 10.2.
+
+The recommended configuration for a PostgreSQL HA requires:
+
+- A minimum of three database nodes
+ - Each node will run the following services:
+ - `PostgreSQL` - The database itself
+ - `repmgrd` - A service to monitor, and handle failover in case of a failure
+ - `Consul` agent - Used for service discovery, to alert other nodes when failover occurs
+- A minimum of three `Consul` server nodes
+- A minimum of one `pgbouncer` service node
+
+You also need to take into consideration the underlying network topology,
+making sure you have redundant connectivity between all Database and GitLab instances,
+otherwise the networks will become a single point of failure.
+
+#### Architecture
+
+![PG HA Architecture](img/pg_ha_architecture.png)
+
+Database nodes run two services with PostgreSQL:
+
+- Repmgrd. Monitors the cluster and handles failover when issues with the master occur. The failover consists of:
+ - Selecting a new master for the cluster.
+ - Promoting the new node to master.
+ - Instructing remaining servers to follow the new master node.
+
+ On failure, the old master node is automatically evicted from the cluster, and should be rejoined manually once recovered.
+- Consul. Monitors the status of each node in the database cluster and tracks its health in a service definition on the consul cluster.
+
+Alongside pgbouncer, there is a consul agent that watches the status of the PostgreSQL service. If that status changes, consul runs a script which updates the configuration and reloads pgbouncer
+
+##### Connection flow
+
+Each service in the package comes with a set of [default ports](https://docs.gitlab.com/omnibus/package-information/defaults.html#ports). You may need to make specific firewall rules for the connections listed below:
+
+- Application servers connect to [PgBouncer default port](https://docs.gitlab.com/omnibus/package-information/defaults.html#pgbouncer)
+- PgBouncer connects to the primary database servers [PostgreSQL default port](https://docs.gitlab.com/omnibus/package-information/defaults.html#postgresql)
+- Repmgr connects to the database servers [PostgreSQL default port](https://docs.gitlab.com/omnibus/package-information/defaults.html#postgresql)
+- Postgres secondaries connect to the primary database servers [PostgreSQL default port](https://docs.gitlab.com/omnibus/package-information/defaults.html#postgresql)
+- Consul servers and agents connect to each others [Consul default ports](https://docs.gitlab.com/omnibus/package-information/defaults.html#consul)
+
+#### Required information
+
+Before proceeding with configuration, you will need to collect all the necessary
+information.
+
+##### Network information
+
+PostgreSQL does not listen on any network interface by default. It needs to know
+which IP address to listen on in order to be accessible to other services.
+Similarly, PostgreSQL access is controlled based on the network source.
+
+This is why you will need:
+
+- IP address of each nodes network interface. This can be set to `0.0.0.0` to
+ listen on all interfaces. It cannot be set to the loopack address `127.0.0.1`.
+- Network Address. This can be in subnet (i.e. `192.168.0.0/255.255.255.0`)
+ or CIDR (i.e. `192.168.0.0/24`) form.
+
+##### User information
+
+Various services require different configuration to secure
+the communication as well as information required for running the service.
+Bellow you will find details on each service and the minimum required
+information you need to provide.
+
+##### Consul information
+
+When using default setup, minimum configuration requires:
+
+- `CONSUL_USERNAME`. Defaults to `gitlab-consul`
+- `CONSUL_DATABASE_PASSWORD`. Password for the database user.
+- `CONSUL_PASSWORD_HASH`. This is a hash generated out of consul username/password pair.
+ Can be generated with:
+
+ ```sh
+ sudo gitlab-ctl pg-password-md5 CONSUL_USERNAME
+ ```
+
+- `CONSUL_SERVER_NODES`. The IP addresses or DNS records of the Consul server nodes.
+
+Few notes on the service itself:
+
+- The service runs under a system account, by default `gitlab-consul`.
+ - If you are using a different username, you will have to specify it. We
+will refer to it with `CONSUL_USERNAME`,
+- There will be a database user created with read only access to the repmgr
+database
+- Passwords will be stored in the following locations:
+ - `/etc/gitlab/gitlab.rb`: hashed
+ - `/var/opt/gitlab/pgbouncer/pg_auth`: hashed
+ - `/var/opt/gitlab/gitlab-consul/.pgpass`: plaintext
+
+##### PostgreSQL information
+
+When configuring PostgreSQL, we will set `max_wal_senders` to one more than
+the number of database nodes in the cluster.
+This is used to prevent replication from using up all of the
+available database connections.
+
+In this document we are assuming 3 database nodes, which makes this configuration:
+
+```
+postgresql['max_wal_senders'] = 4
+```
+
+As previously mentioned, you'll have to prepare the network subnets that will
+be allowed to authenticate with the database.
+You'll also need to supply the IP addresses or DNS records of Consul
+server nodes.
+
+We will need the following password information for the application's database user:
+
+- `POSTGRESQL_USERNAME`. Defaults to `gitlab`
+- `POSTGRESQL_USER_PASSWORD`. The password for the database user
+- `POSTGRESQL_PASSWORD_HASH`. This is a hash generated out of the username/password pair.
+ Can be generated with:
+
+ ```sh
+ sudo gitlab-ctl pg-password-md5 POSTGRESQL_USERNAME
+ ```
+
+##### Pgbouncer information
+
+When using default setup, minimum configuration requires:
+
+- `PGBOUNCER_USERNAME`. Defaults to `pgbouncer`
+- `PGBOUNCER_PASSWORD`. This is a password for pgbouncer service.
+- `PGBOUNCER_PASSWORD_HASH`. This is a hash generated out of pgbouncer username/password pair.
+ Can be generated with:
+
+ ```sh
+ sudo gitlab-ctl pg-password-md5 PGBOUNCER_USERNAME
+ ```
+
+- `PGBOUNCER_NODE`, is the IP address or a FQDN of the node running Pgbouncer.
+
+Few notes on the service itself:
+
+- The service runs as the same system account as the database
+ - In the package, this is by default `gitlab-psql`
+- If you use a non-default user account for Pgbouncer service (by default `pgbouncer`), you will have to specify this username. We will refer to this requirement with `PGBOUNCER_USERNAME`.
+- The service will have a regular database user account generated for it
+ - This defaults to `repmgr`
+- Passwords will be stored in the following locations:
+ - `/etc/gitlab/gitlab.rb`: hashed, and in plain text
+ - `/var/opt/gitlab/pgbouncer/pg_auth`: hashed
+
+##### Repmgr information
+
+When using default setup, you will only have to prepare the network subnets that will
+be allowed to authenticate with the service.
+
+Few notes on the service itself:
+
+- The service runs under the same system account as the database
+ - In the package, this is by default `gitlab-psql`
+- The service will have a superuser database user account generated for it
+ - This defaults to `gitlab_repmgr`
+
+#### Installing Omnibus GitLab
+
+First, make sure to [download/install](https://about.gitlab.com/installation)
+GitLab Omnibus **on each node**.
+
+Make sure you install the necessary dependencies from step 1,
+add GitLab package repository from step 2.
+When installing the GitLab package, do not supply `EXTERNAL_URL` value.
+
+#### Configuring the Consul nodes
+
+On each Consul node perform the following:
+
+1. Make sure you collect [`CONSUL_SERVER_NODES`](#consul-information) before executing the next step.
+
+1. Edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
+
+ ```ruby
+ # Disable all components except Consul
+ roles ['consul_role']
+
+ # START user configuration
+ # Replace placeholders:
+ #
+ # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z
+ # with the addresses gathered for CONSUL_SERVER_NODES
+ consul['configuration'] = {
+ server: true,
+ retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z)
+ }
+
+ # Disable auto migrations
+ gitlab_rails['auto_migrate'] = false
+ #
+ # END user configuration
+ ```
+
+ > `consul_role` was introduced with GitLab 10.3
+
+1. [Reconfigure GitLab] for the changes to take effect.
+
+##### Consul Checkpoint
+
+Before moving on, make sure Consul is configured correctly. Run the following
+command to verify all server nodes are communicating:
+
+```sh
+/opt/gitlab/embedded/bin/consul members
+```
+
+The output should be similar to:
+
+```
+Node Address Status Type Build Protocol DC
+CONSUL_NODE_ONE XXX.XXX.XXX.YYY:8301 alive server 0.9.2 2 gitlab_consul
+CONSUL_NODE_TWO XXX.XXX.XXX.YYY:8301 alive server 0.9.2 2 gitlab_consul
+CONSUL_NODE_THREE XXX.XXX.XXX.YYY:8301 alive server 0.9.2 2 gitlab_consul
+```
+
+If any of the nodes isn't `alive` or if any of the three nodes are missing,
+check the [Troubleshooting section](#troubleshooting) before proceeding.
+
+#### Configuring the Database nodes
+
+1. Make sure you collect [`CONSUL_SERVER_NODES`](#consul-information), [`PGBOUNCER_PASSWORD_HASH`](#pgbouncer-information), [`POSTGRESQL_PASSWORD_HASH`](#postgresql-information), the [number of db nodes](#postgresql-information), and the [network address](#network-information) before executing the next step.
+
+1. On the master database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
+
+ ```ruby
+ # Disable all components except PostgreSQL and Repmgr and Consul
+ roles ['postgres_role']
# PostgreSQL configuration
- gitlab_rails['db_password'] = 'DB password'
- postgresql['md5_auth_cidr_addresses'] = ['0.0.0.0/0']
postgresql['listen_address'] = '0.0.0.0'
+ postgresql['hot_standby'] = 'on'
+ postgresql['wal_level'] = 'replica'
+ postgresql['shared_preload_libraries'] = 'repmgr_funcs'
# Disable automatic database migrations
gitlab_rails['auto_migrate'] = false
+
+ # Configure the consul agent
+ consul['services'] = %w(postgresql)
+
+ # START user configuration
+ # Please set the real values as explained in Required Information section
+ #
+ # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
+ postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH'
+ # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
+ postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH'
+ # Replace X with value of number of db nodes + 1
+ postgresql['max_wal_senders'] = X
+
+ # Replace XXX.XXX.XXX.XXX/YY with Network Address
+ postgresql['trust_auth_cidr_addresses'] = %w(XXX.XXX.XXX.XXX/YY)
+ repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 XXX.XXX.XXX.XXX/YY)
+
+ # Replace placeholders:
+ #
+ # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z
+ # with the addresses gathered for CONSUL_SERVER_NODES
+ consul['configuration'] = {
+ retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z)
+ }
+ #
+ # END user configuration
```
-1. Run `sudo gitlab-ctl reconfigure` to install and configure PostgreSQL.
+ > `postgres_role` was introduced with GitLab 10.3
+
+1. On secondary nodes, add all the configuration specified above for primary node
+ to `/etc/gitlab/gitlab.rb`. In addition, append the following configuration
+ to inform gitlab-ctl that they are standby nodes initially and it need not
+ attempt to register them as primary node
+ ```
+ # HA setting to specify if a node should attempt to be master on initialization
+ repmgr['master_on_initialization'] = false
+ ```
+
+1. [Reconfigure GitLab] for the changes to take effect.
+
+> Please note:
+>
+> - If you want your database to listen on a specific interface, change the config:
+> `postgresql['listen_address'] = '0.0.0.0'`.
+> - If your Pgbouncer service runs under a different user account,
+> you also need to specify: `postgresql['pgbouncer_user'] = PGBOUNCER_USERNAME` in
+> your configuration.
+
+##### Database nodes post-configuration
- > **Note**: This `reconfigure` step will result in some errors.
- That's OK - don't be alarmed.
+###### Primary node
+
+Select one node as a primary node.
1. Open a database prompt:
+ ```sh
+ gitlab-psql -d gitlabhq_production
```
- su - gitlab-psql
- /bin/bash
- psql -h /var/opt/gitlab/postgresql -d template1
- # Output:
+1. Enable the `pg_trgm` extension:
+
+ ```sh
+ CREATE EXTENSION pg_trgm;
+ ```
- psql (9.2.15)
- Type "help" for help.
+1. Exit the database prompt by typing `\q` and Enter.
- template1=#
+1. Verify the cluster is initialized with one node:
+
+ ```sh
+ gitlab-ctl repmgr cluster show
+ ```
+
+ The output should be similar to the following:
+
+ ```
+ Role | Name | Upstream | Connection String
+ ----------+----------|----------|----------------------------------------
+ * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr
```
-1. Run the following command at the database prompt and you will be asked to
- enter the new password for the PostgreSQL superuser.
+1. Note down the hostname/ip in the connection string: `host=HOSTNAME`. We will
+ refer to the hostname in the next section as `MASTER_NODE_NAME`. If the value
+ is not an IP address, it will need to be a resolvable name (via DNS or
+ `/etc/hosts`)
+###### Secondary nodes
+
+1. Set up the repmgr standby:
+
+ ```sh
+ gitlab-ctl repmgr standby setup MASTER_NODE_NAME
```
- \password
- # Output:
+ Do note that this will remove the existing data on the node. The command
+ has a wait time.
+
+ The output should be similar to the following:
- Enter new password:
- Enter it again:
+ ```console
+ # gitlab-ctl repmgr standby setup MASTER_NODE_NAME
+ Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data
+ If this is not what you want, hit Ctrl-C now to exit
+ To skip waiting, rerun with the -w option
+ Sleeping for 30 seconds
+ Stopping the database
+ Removing the data
+ Cloning the data
+ Starting the database
+ Registering the node with the cluster
+ ok: run: repmgrd: (pid 19068) 0s
```
-1. Similarly, set the password for the `gitlab` database user. Use the same
- password that you specified in the `/etc/gitlab/gitlab.rb` file for
- `gitlab_rails['db_password']`.
+1. Verify the node now appears in the cluster:
+ ```sh
+ gitlab-ctl repmgr cluster show
```
- \password gitlab
- # Output:
+ The output should be similar to the following:
- Enter new password:
- Enter it again:
```
-1. Exit from editing `template1` prompt by typing `\q` and Enter.
-1. Enable the `pg_trgm` extension within the `gitlabhq_production` database:
-
+ Role | Name | Upstream | Connection String
+ ----------+---------|-----------|------------------------------------------------
+ * master | MASTER | | host=MASTER_NODE_NAME user=gitlab_repmgr dbname=gitlab_repmgr
+ standby | STANDBY | MASTER | host=STANDBY_HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr
```
+
+Repeat the above steps on all secondary nodes.
+
+##### Database checkpoint
+
+Before moving on, make sure the databases are configured correctly. Run the
+following command on the **primary** node to verify that replication is working
+properly:
+
+```sh
+gitlab-ctl repmgr cluster show
+```
+
+The output should be similar to:
+
+```
+Role | Name | Upstream | Connection String
+----------+--------------|--------------|--------------------------------------------------------------------
+* master | MASTER | | host=MASTER port=5432 user=gitlab_repmgr dbname=gitlab_repmgr
+ standby | STANDBY | MASTER | host=STANDBY port=5432 user=gitlab_repmgr dbname=gitlab_repmgr
+```
+
+If the 'Role' column for any node says "FAILED", check the
+[Troubleshooting section](#troubleshooting) before proceeding.
+
+Also, check that the check master command works successfully on each node:
+
+```sh
+su - gitlab-consul
+gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node'
+```
+
+This command relies on exit codes to tell Consul whether a particular node is a master
+or secondary. The most important thing here is that this command does not produce errors.
+If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions.
+Check the [Troubleshooting section](#troubleshooting) before proceeding.
+
+#### Configuring the Pgbouncer node
+
+1. Make sure you collect [`CONSUL_SERVER_NODES`](#consul-information), [`CONSUL_PASSWORD_HASH`](#consul-information), and [`PGBOUNCER_PASSWORD_HASH`](#pgbouncer-information) before executing the next step.
+
+1. Edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
+
+ ```ruby
+ # Disable all components except Pgbouncer and Consul agent
+ roles ['pgbouncer_role']
+
+ # Configure Pgbouncer
+ pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
+
+ # Configure Consul agent
+ consul['watchers'] = %w(postgresql)
+
+ # START user configuration
+ # Please set the real values as explained in Required Information section
+ # Replace CONSUL_PASSWORD_HASH with with a generated md5 value
+ # Replace PGBOUNCER_PASSWORD_HASH with with a generated md5 value
+ pgbouncer['users'] = {
+ 'gitlab-consul': {
+ password: 'CONSUL_PASSWORD_HASH'
+ },
+ 'pgbouncer': {
+ password: 'PGBOUNCER_PASSWORD_HASH'
+ }
+ }
+ # Replace placeholders:
+ #
+ # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z
+ # with the addresses gathered for CONSUL_SERVER_NODES
+ consul['configuration'] = {
+ retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z)
+ }
+ #
+ # END user configuration
+ ```
+
+ > `pgbouncer_role` was introduced with GitLab 10.3
+
+1. [Reconfigure GitLab] for the changes to take effect.
+
+1. Create a `.pgpass` file so Consule is able to
+ reload pgbouncer. Enter the `PGBOUNCER_PASSWORD` twice when asked:
+
+ ```sh
+ gitlab-ctl write-pgpass --host 127.0.0.1 --database pgbouncer --user pgbouncer --hostuser gitlab-consul
+ ```
+
+##### PGBouncer Checkpoint
+
+1. Ensure the node is talking to the current master:
+
+ ```sh
+ gitlab-ctl pgb-console # You will be prompted for PGBOUNCER_PASSWORD
+ ```
+
+ If there is an error `psql: ERROR: Auth failed` after typing in the
+ password, ensure you previously generated the MD5 password hashes with the correct
+ format. The correct format is to concatenate the password and the username:
+ `PASSWORDUSERNAME`. For example, `Sup3rS3cr3tpgbouncer` would be the text
+ needed to generate an MD5 password hash for the `pgbouncer` user.
+
+1. Once the console prompt is available, run the following queries:
+
+ ```sh
+ show databases ; show clients ;
+ ```
+
+ The output should be similar to the following:
+
+ ```
+ name | host | port | database | force_user | pool_size | reserve_pool | pool_mode | max_connections | current_connections
+ ---------------------+-------------+------+---------------------+------------+-----------+--------------+-----------+-----------------+---------------------
+ gitlabhq_production | MASTER_HOST | 5432 | gitlabhq_production | | 20 | 0 | | 0 | 0
+ pgbouncer | | 6432 | pgbouncer | pgbouncer | 2 | 0 | statement | 0 | 0
+ (2 rows)
+
+ type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link | remote_pid | tls
+ ------+-----------+---------------------+---------+----------------+-------+------------+------------+---------------------+---------------------+-----------+------+------------+-----
+ C | pgbouncer | pgbouncer | active | 127.0.0.1 | 56846 | 127.0.0.1 | 6432 | 2017-08-21 18:09:59 | 2017-08-21 18:10:48 | 0x22b3880 | | 0 |
+ (2 rows)
+ ```
+
+#### Configuring the Application nodes
+
+These will be the nodes running the `gitlab-rails` service. You may have other
+attributes set, but the following need to be set.
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ # Disable PostgreSQL on the application node
+ postgresql['enable'] = false
+
+ gitlab_rails['db_host'] = 'PGBOUNCER_NODE'
+ gitlab_rails['db_port'] = 6432
+ gitlab_rails['db_password'] = 'POSTGRESQL_USER_PASSWORD'
+ gitlab_rails['auto_migrate'] = false
+ ```
+
+1. [Reconfigure GitLab] for the changes to take effect.
+
+##### Application node post-configuration
+
+Ensure that all migrations ran:
+
+```sh
+gitlab-rake gitlab:db:configure
+```
+
+> **Note**: If you encounter a `rake aborted!` error stating that PGBouncer is failing to connect to
+PostgreSQL it may be that your PGBouncer node's IP address is missing from
+PostgreSQL's `trust_auth_cidr_addresses` in `gitlab.rb` on your database nodes. See
+[PGBouncer error `ERROR: pgbouncer cannot connect to server`](#pgbouncer-error-error-pgbouncer-cannot-connect-to-server)
+in the Troubleshooting section before proceeding.
+
+##### Ensure GitLab is running
+
+At this point, your GitLab instance should be up and running. Verify you are
+able to login, and create issues and merge requests. If you have troubles check
+the [Troubleshooting section](#troubleshooting).
+
+#### Example configuration
+
+Here we'll show you some fully expanded example configurations.
+
+##### Example recommended setup
+
+This example uses 3 consul servers, 3 postgresql servers, and 1 application node.
+
+We start with all servers on the same 10.6.0.0/16 private network range, they
+can connect to each freely other on those addresses.
+
+Here is a list and description of each machine and the assigned IP:
+
+- `10.6.0.11`: Consul 1
+- `10.6.0.12`: Consul 2
+- `10.6.0.13`: Consul 3
+- `10.6.0.21`: PostgreSQL master
+- `10.6.0.22`: PostgreSQL secondary
+- `10.6.0.23`: PostgreSQL secondary
+- `10.6.0.31`: GitLab application
+
+All passwords are set to `toomanysecrets`, please do not use this password or derived hashes.
+
+The external_url for GitLab is `http://gitlab.example.com`
+
+Please note that after the initial configuration, if a failover occurs, the PostgresSQL master will change to one of the available secondaries until it is failed back.
+
+##### Example recommended setup for Consul servers
+
+On each server edit `/etc/gitlab/gitlab.rb`:
+
+```ruby
+# Disable all components except Consul
+roles ['consul_role']
+
+consul['configuration'] = {
+ server: true,
+ retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
+}
+```
+
+[Reconfigure Omnibus GitLab][reconfigure GitLab] for the changes to take effect.
+
+##### Example recommended setup for PostgreSQL servers
+
+###### Primary node
+
+On primary node edit `/etc/gitlab/gitlab.rb`:
+
+```ruby
+# Disable all components except PostgreSQL and Repmgr and Consul
+roles ['postgres_role']
+
+# PostgreSQL configuration
+postgresql['listen_address'] = '0.0.0.0'
+postgresql['hot_standby'] = 'on'
+postgresql['wal_level'] = 'replica'
+postgresql['shared_preload_libraries'] = 'repmgr_funcs'
+
+# Disable automatic database migrations
+gitlab_rails['auto_migrate'] = false
+
+# Configure the consul agent
+consul['services'] = %w(postgresql)
+
+postgresql['pgbouncer_user_password'] = '771a8625958a529132abe6f1a4acb19c'
+postgresql['sql_user_password'] = '450409b85a0223a214b5fb1484f34d0f'
+postgresql['max_wal_senders'] = 4
+
+postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/16)
+repmgr['trust_auth_cidr_addresses'] = %w(10.6.0.0/16)
+
+consul['configuration'] = {
+ retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
+}
+```
+
+[Reconfigure Omnibus GitLab][reconfigure GitLab] for the changes to take effect.
+
+###### Secondary nodes
+
+On secondary nodes, edit `/etc/gitlab/gitlab.rb` and add all the configuration
+added to primary node, noted above. In addition, append the following
+configuration:
+
+```
+# HA setting to specify if a node should attempt to be master on initialization
+repmgr['master_on_initialization'] = false
+```
+
+[Reconfigure Omnibus GitLab][reconfigure GitLab] for the changes to take effect.
+
+##### Example recommended setup for application server
+
+On the server edit `/etc/gitlab/gitlab.rb`:
+
+```ruby
+external_url 'http://gitlab.example.com'
+
+gitlab_rails['db_host'] = '127.0.0.1'
+gitlab_rails['db_port'] = 6432
+gitlab_rails['db_password'] = 'toomanysecrets'
+gitlab_rails['auto_migrate'] = false
+
+postgresql['enable'] = false
+pgbouncer['enable'] = true
+consul['enable'] = true
+
+# Configure Pgbouncer
+pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
+
+# Configure Consul agent
+consul['watchers'] = %w(postgresql)
+
+pgbouncer['users'] = {
+ 'gitlab-consul': {
+ password: '5e0e3263571e3704ad655076301d6ebe'
+ },
+ 'pgbouncer': {
+ password: '771a8625958a529132abe6f1a4acb19c'
+ }
+}
+
+consul['configuration'] = {
+ retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
+}
+```
+
+[Reconfigure Omnibus GitLab][reconfigure GitLab] for the changes to take effect.
+
+##### Example recommended setup manual steps
+
+After deploying the configuration follow these steps:
+
+1. On `10.6.0.21`, our primary database
+
+ Enable the `pg_trgm` extension
+
+ ```sh
gitlab-psql -d gitlabhq_production
-
+ ```
+
+ ```
CREATE EXTENSION pg_trgm;
+ ```
+
+1. On `10.6.0.22`, our first standby database
- # Output:
+ Make this node a standby of the primary
- CREATE EXTENSION
+ ```sh
+ gitlab-ctl repmgr standby setup 10.6.0.21
```
-1. Exit the database prompt by typing `\q` and Enter.
-1. Exit the `gitlab-psql` user by running `exit` twice.
-1. Run `sudo gitlab-ctl reconfigure` a final time.
-1. Configure the GitLab application servers with the appropriate details.
- This step is covered in [Configuring GitLab for HA](gitlab.md).
----
+1. On `10.6.0.23`, our second standby database
+
+ Make this node a standby of the primary
+
+ ```sh
+ gitlab-ctl repmgr standby setup 10.6.0.21
+ ```
+
+1. On `10.6.0.31`, our application server
+
+ Set gitlab-consul's pgbouncer password to `toomanysecrets`
+
+ ```sh
+ gitlab-ctl write-pgpass --host 127.0.0.1 --database pgbouncer --user pgbouncer --hostuser gitlab-consul
+ ```
+
+ Run database migrations
+
+ ```sh
+ gitlab-rake gitlab:db:configure
+ ```
+
+#### Example minimal setup
+
+This example uses 3 postgresql servers, and 1 application node.
+
+It differs from the [recommended setup](#example-recommended-setup) by moving the consul servers into the same servers we use for PostgreSQL.
+The trade-off is between reducing server counts, against the increased operational complexity of needing to deal with postgres [failover](#failover-procedure) and [restore](#restore-procedure) procedures in addition to [consul outage recovery](consul.md#outage-recovery) on the same set of machines.
+
+In this example we start with all servers on the same 10.6.0.0/16 private network range, they can connect to each freely other on those addresses.
+
+Here is a list and description of each machine and the assigned IP:
+
+- `10.6.0.21`: PostgreSQL master
+- `10.6.0.22`: PostgreSQL secondary
+- `10.6.0.23`: PostgreSQL secondary
+- `10.6.0.31`: GitLab application
+
+All passwords are set to `toomanysecrets`, please do not use this password or derived hashes.
+
+The external_url for GitLab is `http://gitlab.example.com`
+
+Please note that after the initial configuration, if a failover occurs, the PostgresSQL master will change to one of the available secondaries until it is failed back.
+
+##### Example minimal configuration for database servers
+
+##### Primary node
+
+On primary database node edit `/etc/gitlab/gitlab.rb`:
+
+```ruby
+# Disable all components except PostgreSQL, Repmgr, and Consul
+roles ['postgres_role']
+
+# PostgreSQL configuration
+postgresql['listen_address'] = '0.0.0.0'
+postgresql['hot_standby'] = 'on'
+postgresql['wal_level'] = 'replica'
+postgresql['shared_preload_libraries'] = 'repmgr_funcs'
+
+# Disable automatic database migrations
+gitlab_rails['auto_migrate'] = false
+
+# Configure the consul agent
+consul['services'] = %w(postgresql)
+
+postgresql['pgbouncer_user_password'] = '771a8625958a529132abe6f1a4acb19c'
+postgresql['sql_user_password'] = '450409b85a0223a214b5fb1484f34d0f'
+postgresql['max_wal_senders'] = 4
+
+postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/16)
+repmgr['trust_auth_cidr_addresses'] = %w(10.6.0.0/16)
+
+consul['configuration'] = {
+ server: true,
+ retry_join: %w(10.6.0.21 10.6.0.22 10.6.0.23)
+}
+```
+
+[Reconfigure Omnibus GitLab][reconfigure GitLab] for the changes to take effect.
+
+###### Secondary nodes
+
+On secondary nodes, edit `/etc/gitlab/gitlab.rb` and add all the information added
+to primary node, noted above. In addition, append the following configuration
+
+```
+# HA setting to specify if a node should attempt to be master on initialization
+repmgr['master_on_initialization'] = false
+```
+
+##### Example minimal configuration for application server
+
+On the server edit `/etc/gitlab/gitlab.rb`:
+
+```ruby
+external_url 'http://gitlab.example.com'
+
+gitlab_rails['db_host'] = '127.0.0.1'
+gitlab_rails['db_port'] = 6432
+gitlab_rails['db_password'] = 'toomanysecrets'
+gitlab_rails['auto_migrate'] = false
+
+postgresql['enable'] = false
+pgbouncer['enable'] = true
+consul['enable'] = true
+
+# Configure Pgbouncer
+pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
+
+# Configure Consul agent
+consul['watchers'] = %w(postgresql)
+
+pgbouncer['users'] = {
+ 'gitlab-consul': {
+ password: '5e0e3263571e3704ad655076301d6ebe'
+ },
+ 'pgbouncer': {
+ password: '771a8625958a529132abe6f1a4acb19c'
+ }
+}
+
+consul['configuration'] = {
+ retry_join: %w(10.6.0.21 10.6.0.22 10.6.0.23)
+}
+```
+
+[Reconfigure Omnibus GitLab][reconfigure GitLab] for the changes to take effect.
+
+##### Example minimal setup manual steps
+
+The manual steps for this configuration are the same as for the [example recommended setup](#example-recommended-setup-manual-steps).
+
+#### Failover procedure
+
+By default, if the master database fails, `repmgrd` should promote one of the
+standby nodes to master automatically, and consul will update pgbouncer with
+the new master.
+
+If you need to failover manually, you have two options:
+
+**Shutdown the current master database**
+
+Run:
+
+```sh
+gitlab-ctl stop postgresql
+```
+
+The automated failover process will see this and failover to one of the
+standby nodes.
+
+**Or perform a manual failover**
+
+1. Ensure the old master node is not still active.
+1. Login to the server that should become the new master and run:
+
+ ```sh
+ gitlab-ctl repmgr standby promote
+ ```
+
+1. If there are any other standby servers in the cluster, have them follow
+ the new master server:
+
+ ```sh
+ gitlab-ctl repmgr standby follow NEW_MASTER
+ ```
+
+#### Restore procedure
+
+If a node fails, it can be removed from the cluster, or added back as a standby
+after it has been restored to service.
+
+- If you want to remove the node from the cluster, on any other node in the
+ cluster, run:
+
+ ```sh
+ gitlab-ctl repmgr standby unregister --node=X
+ ```
+
+ where X is the value of node in `repmgr.conf` on the old server.
+
+ To find this, you can use:
+
+ ```sh
+ awk -F = '$1 == "node" { print $2 }' /var/opt/gitlab/postgresql/repmgr.conf
+ ```
+
+ It will output something like:
+
+ ```
+ 959789412
+ ```
+
+ Then you will use this id to unregister the node:
+
+ ```sh
+ gitlab-ctl repmgr standby unregister --node=959789412
+ ```
+
+- To add the node as a standby server:
+
+ ```sh
+ gitlab-ctl repmgr standby follow NEW_MASTER
+ gitlab-ctl restart repmgrd
+ ```
+
+ CAUTION: **Warning:** When the server is brought back online, and before
+ you switch it to a standby node, repmgr will report that there are two masters.
+ If there are any clients that are still attempting to write to the old master,
+ this will cause a split, and the old master will need to be resynced from
+ scratch by performing a `gitlab-ctl repmgr standby setup NEW_MASTER`.
+
+#### Alternate configurations
+
+##### Database authorization
+
+By default, we give any host on the database network the permission to perform
+repmgr operations using PostgreSQL's `trust` method. If you do not want this
+level of trust, there are alternatives.
+
+You can trust only the specific nodes that will be database clusters, or you
+can require md5 authentication.
+
+##### Trust specific addresses
+
+If you know the IP address, or FQDN of all database and pgbouncer nodes in the
+cluster, you can trust only those nodes.
+
+In `/etc/gitlab/gitlab.rb` on all of the database nodes, set
+`repmgr['trust_auth_cidr_addresses']` to an array of strings containing all of
+the addresses.
+
+If setting to a node's FQDN, they must have a corresponding PTR record in DNS.
+If setting to a node's IP address, specify it as `XXX.XXX.XXX.XXX/32`.
+
+For example:
+
+```ruby
+repmgr['trust_auth_cidr_addresses'] = %w(192.168.1.44/32 db2.example.com)
+```
+
+##### MD5 Authentication
+
+If you are running on an untrusted network, repmgr can use md5 authentication
+with a [.pgpass file](https://www.postgresql.org/docs/9.6/static/libpq-pgpass.html)
+to authenticate.
+
+You can specify by IP address, FQDN, or by subnet, using the same format as in
+the previous section:
+
+1. On the current master node, create a password for the `gitlab` and
+ `gitlab_repmgr` user:
+
+ ```sh
+ gitlab-psql -d template1
+ template1=# \password gitlab_repmgr
+ Enter password: ****
+ Confirm password: ****
+ template1=# \password gitlab
+ ```
+
+1. On each database node:
+
+ 1. Edit `/etc/gitlab/gitlab.rb`:
+ 1. Ensure `repmgr['trust_auth_cidr_addresses']` is **not** set
+ 1. Set `postgresql['md5_auth_cidr_addresses']` to the desired value
+ 1. Set `postgresql['sql_replication_user'] = 'gitlab_repmgr'`
+ 1. Reconfigure with `gitlab-ctl reconfigure`
+ 1. Restart postgresql with `gitlab-ctl restart postgresql`
+
+ 1. Create a `.pgpass` file. Enter the `gitlab_repmgr` password twice to
+ when asked:
+
+ ```sh
+ gitlab-ctl write-pgpass --user gitlab_repmgr --hostuser gitlab-psql --database '*'
+ ```
+
+1. On each pgbouncer node, edit `/etc/gitlab/gitlab.rb`:
+ 1. Ensure `gitlab_rails['db_password']` is set to the plaintext password for
+ the `gitlab` database user
+ 1. [Reconfigure GitLab] for the changes to take effect
+
+## Troubleshooting
+
+#### Consul and PostgreSQL changes not taking effect.
+
+Due to the potential impacts, `gitlab-ctl reconfigure` only reloads Consul and PostgreSQL, it will not restart the services. However, not all changes can be activated by reloading.
+
+To restart either service, run `gitlab-ctl restart SERVICE`
+
+For PostgreSQL, it is usually safe to restart the master node by default. Automatic failover defaults to a 1 minute timeout. Provided the database returns before then, nothing else needs to be done. To be safe, you can stop `repmgrd` on the standby nodes first with `gitlab-ctl stop repmgrd`, then start afterwards with `gitlab-ctl start repmgrd`.
+
+On the consul server nodes, it is important to restart the consul service in a controlled fashion. Read our [consul documentation](consul.md#restarting-the-server-cluster) for instructions on how to restart the service.
+
+#### `gitlab-ctl repmgr-check-master` command produces errors
+
+If this command displays errors about database permissions it is likely that something failed during
+install, resulting in the `gitlab-consul` database user getting incorrect permissions. Follow these
+steps to fix the problem:
+
+1. On the master database node, connect to the database prompt - `gitlab-psql -d template1`
+1. Delete the `gitlab-consul` user - `DROP USER "gitlab-consul";`
+1. Exit the database prompt - `\q`
+1. [Reconfigure GitLab] and the user will be re-added with the proper permissions.
+1. Change to the `gitlab-consul` user - `su - gitlab-consul`
+1. Try the check command again - `gitlab-ctl repmgr-check-master`.
+
+Now there should not be errors. If errors still occur then there is another problem.
+
+#### PGBouncer error `ERROR: pgbouncer cannot connect to server`
+
+You may get this error when running `gitlab-rake gitlab:db:configure` or you
+may see the error in the PGBouncer log file.
+
+```
+PG::ConnectionBad: ERROR: pgbouncer cannot connect to server
+```
+
+The problem may be that your PGBouncer node's IP address is not included in the
+`trust_auth_cidr_addresses` setting in `/etc/gitlab/gitlab.rb` on the database nodes.
+
+You can confirm that this is the issue by checking the PostgreSQL log on the master
+database node. If you see the following error then `trust_auth_cidr_addresses`
+is the problem.
+
+```
+2018-03-29_13:59:12.11776 FATAL: no pg_hba.conf entry for host "123.123.123.123", user "pgbouncer", database "gitlabhq_production", SSL off
+```
+
+To fix the problem, add the IP address to `/etc/gitlab/gitlab.rb`.
+
+```
+postgresql['trust_auth_cidr_addresses'] = %w(123.123.123.123/32 <other_cidrs>)
+```
+
+[Reconfigure GitLab] for the changes to take effect.
+
+#### Issues with other components
+
+If you're running into an issue with a component not outlined here, be sure to check the troubleshooting section of their specific documentation page.
+
+- [Consul](consul.md#troubleshooting)
+- [PostgreSQL](http://docs.gitlab.com/omnibus/settings/database.html#troubleshooting)
+- [GitLab application](gitlab.md#troubleshooting)
+
+## Configure using Omnibus
+
+**Note**: We recommend that you follow the instructions here for a full [PostgreSQL cluster](#high-availability-with-gitlab-omnibus-premium-only).
+If you are reading this section due to an old bookmark, you can find that old documentation [in the repository](https://gitlab.com/gitlab-org/gitlab-ce/blob/v10.1.4/doc/administration/high_availability/database.md#configure-using-omnibus).
Read more on high-availability configuration:
@@ -114,3 +1160,6 @@ Read more on high-availability configuration:
1. [Configure NFS](nfs.md)
1. [Configure the GitLab application servers](gitlab.md)
1. [Configure the load balancers](load_balancer.md)
+1. [Manage the bundled Consul cluster](consul.md)
+
+[reconfigure GitLab]: ../restart_gitlab.md#omnibus-gitlab-reconfigure
diff --git a/doc/administration/high_availability/gitaly.md b/doc/administration/high_availability/gitaly.md
new file mode 100644
index 00000000000..1d8e6c999cb
--- /dev/null
+++ b/doc/administration/high_availability/gitaly.md
@@ -0,0 +1,21 @@
+# Configuring Gitaly for Scaled and High Availability
+
+Gitaly does not yet support full high availability. However, Gitaly is quite
+stable and is in use on GitLab.com. Scaled and highly available GitLab environments
+should consider using Gitaly on a separate node.
+
+See the [Gitaly HA Epic](https://gitlab.com/groups/gitlab-org/-/epics/289) to
+track plans and progress toward high availability support.
+
+This document is relevant for [Scaled Architecture](README.md#scalable-architecture-examples)
+environments and [High Availability Architecture](README.md#high-availability-architecture-examples).
+
+## Running Gitaly on its own server
+
+See [Running Gitaly on its own server](../gitaly/index.md#running-gitaly-on-its-own-server)
+in Gitaly documentation.
+
+Continue configuration of other components by going back to:
+
+- [Scaled Architectures](README.md#scalable-architecture-examples)
+- [High Availability Architectures](README.md#high-availability-architecture-examples)
diff --git a/doc/administration/high_availability/gitlab.md b/doc/administration/high_availability/gitlab.md
index d95c3acec54..888426ece5c 100644
--- a/doc/administration/high_availability/gitlab.md
+++ b/doc/administration/high_availability/gitlab.md
@@ -1,8 +1,4 @@
-# Configuring GitLab for HA
-
-Assuming you have already configured a [database](database.md), [Redis](redis.md), and [NFS](nfs.md), you can
-configure the GitLab application server(s) now. Complete the steps below
-for each GitLab application server in your environment.
+# Configuring GitLab Scaling and High Availability
> **Note:** There is some additional configuration near the bottom for
additional GitLab application servers. It's important to read and understand
diff --git a/doc/administration/high_availability/img/fully-distributed.png b/doc/administration/high_availability/img/fully-distributed.png
new file mode 100644
index 00000000000..ad23207134e
--- /dev/null
+++ b/doc/administration/high_availability/img/fully-distributed.png
Binary files differ
diff --git a/doc/administration/high_availability/img/geo-ha-diagram.png b/doc/administration/high_availability/img/geo-ha-diagram.png
new file mode 100644
index 00000000000..da5d612827c
--- /dev/null
+++ b/doc/administration/high_availability/img/geo-ha-diagram.png
Binary files differ
diff --git a/doc/administration/high_availability/img/horizontal.png b/doc/administration/high_availability/img/horizontal.png
new file mode 100644
index 00000000000..c3bd489d96f
--- /dev/null
+++ b/doc/administration/high_availability/img/horizontal.png
Binary files differ
diff --git a/doc/administration/high_availability/img/hybrid.png b/doc/administration/high_availability/img/hybrid.png
new file mode 100644
index 00000000000..7d4a56bf0ea
--- /dev/null
+++ b/doc/administration/high_availability/img/hybrid.png
Binary files differ
diff --git a/doc/administration/high_availability/img/pg_ha_architecture.png b/doc/administration/high_availability/img/pg_ha_architecture.png
new file mode 100644
index 00000000000..ef870f652ae
--- /dev/null
+++ b/doc/administration/high_availability/img/pg_ha_architecture.png
Binary files differ
diff --git a/doc/administration/high_availability/nfs.md b/doc/administration/high_availability/nfs.md
index 72341a5c777..3013ce63bd5 100644
--- a/doc/administration/high_availability/nfs.md
+++ b/doc/administration/high_availability/nfs.md
@@ -37,9 +37,18 @@ options:
circumstances it could lead to data loss if a failure occurs before data has
synced.
+Due to the complexities of running Omnibus with LDAP and the complexities of
+maintaining ID mapping without LDAP, in most cases you should enable numeric UIDs
+and GIDs (which is off by default in some cases) for simplified permission
+management between systems:
+
+ - [NetApp instructions](https://library.netapp.com/ecmdocs/ECMP1401220/html/GUID-24367A9F-E17B-4725-ADC1-02D86F56F78E.html)
+ - For non-NetApp devices, disable NFSv4 `idmapping` by performing opposite of [enable NFSv4 idmapper](https://wiki.archlinux.org/index.php/NFS#Enabling_NFSv4_idmapping)
+
### Improving NFS performance with GitLab
-NOTE: **Note:** This is only available with GitLab 11.9 and up.
+NOTE: **Note:** This is only available starting in certain versions of GitLab: 11.5.11,
+11.6.11, 11.7.12, 11.8.8, 11.9.0 and up (e.g. 11.10, 11.11, etc.)
If you are using NFS to share Git data, we recommend that you enable a
number of feature flags that will allow GitLab application processes to
@@ -52,13 +61,14 @@ details.
To do this, run the Rake task:
```sh
-gitlab-rake gitlab:features:enable_rugged
+sudo gitlab-rake gitlab:features:enable_rugged
```
-If you need to undo this setting for some reason, run:
+If you need to undo this setting for some reason such as switching to [Gitaly without NFS](gitaly.md)
+(recommended), run:
```sh
-gitlab-rake gitlab:features:disable_rugged
+sudo gitlab-rake gitlab:features:disable_rugged
```
### Known issues
@@ -101,6 +111,11 @@ stored on a local volume.
For more details on another person's experience with EFS, see
[Amazon's Elastic File System: Burst Credits](https://rawkode.com/2017/04/16/amazons-elastic-file-system-burst-credits/)
+## Avoid using CephFS and GlusterFS
+
+GitLab strongly recommends against using CephFS and GlusterFS.
+These distributed file systems are not well-suited for GitLab's input/output access patterns because git uses many small files and access times and file locking times to propagate will make git activity very slow.
+
## Avoid using PostgreSQL with NFS
GitLab strongly recommends against running your PostgreSQL database
@@ -116,7 +131,7 @@ Additionally, this configuration is specifically warned against in the
>to the NFS server can cause data corruption problems.
For supported database architecture, please see our documentation on
-[Configuring a Database for GitLab HA](https://docs.gitlab.com/ee/administration/high_availability/database.html).
+[Configuring a Database for GitLab HA](database.md).
## NFS Client mount options
diff --git a/doc/administration/high_availability/nfs_host_client_setup.md b/doc/administration/high_availability/nfs_host_client_setup.md
new file mode 100644
index 00000000000..a8d69b9ab0a
--- /dev/null
+++ b/doc/administration/high_availability/nfs_host_client_setup.md
@@ -0,0 +1,135 @@
+# Configuring NFS for GitLab HA
+
+Setting up NFS for a GitLab HA setup allows all applications nodes in a cluster
+to share the same files and maintain data consistency. Application nodes in an HA
+setup act as clients while the NFS server plays host.
+
+> Note: The instructions provided in this documentation allow for setting a quick
+proof of concept but will leave NFS as potential single point of failure and
+therefore not recommended for use in production. Explore options such as [Pacemaker
+and Corosync](http://clusterlabs.org/) for highly available NFS in production.
+
+Below are instructions for setting up an application node(client) in an HA cluster
+to read from and write to a central NFS server(host).
+
+NOTE: **Note:**
+Using EFS may negatively impact performance. Please review the [relevant documentation](nfs.md#avoid-using-awss-elastic-file-system-efs) for additional details.
+
+## NFS Server Setup
+
+> Follow the instructions below to set up and configure your NFS server.
+
+### Step 1 - Install NFS Server on Host
+
+Installing the nfs-kernel-server package allows you to share directories with the clients running the GitLab application.
+
+```sh
+apt-get update
+apt-get install nfs-kernel-server
+```
+
+### Step 2 - Export Host's Home Directory to Client
+
+In this setup we will share the home directory on the host with the client. Edit the exports file as below to share the host's home directory with the client. If you have multiple clients running GitLab you must enter the client IP addresses in line in the `/etc/exports` file.
+
+```text
+#/etc/exports for one client
+/home <client-ip-address>(rw,sync,no_root_squash,no_subtree_check)
+
+#/etc/exports for three clients
+/home <client-ip-address>(rw,sync,no_root_squash,no_subtree_check) <client-2-ip-address>(rw,sync,no_root_squash,no_subtree_check) <client-3-ip-address>(rw,sync,no_root_squash,no_subtree_check)
+```
+
+Restart the NFS server after making changes to the `exports` file for the changes
+to take effect.
+
+```sh
+systemctl restart nfs-kernel-server
+```
+
+NOTE: **Note:**
+You may need to update your server's firewall. See the [firewall section](#nfs-in-a-firewalled-environment) at the end of this guide.
+
+## Client/ GitLab application node Setup
+
+> Follow the instructions below to connect any GitLab rails application node running
+inside your HA environment to the NFS server configured above.
+
+### Step 1 - Install NFS Common on Client
+
+The nfs-common provides NFS functionality without installing server components which
+we don't need running on the application nodes.
+
+```sh
+apt-get update
+apt-get install nfs-common
+```
+
+### Step 2 - Create Mount Points on Client
+
+Create a directory on the client that we can mount the shared directory from the host.
+Please note that if your mount point directory contains any files they will be hidden
+once the remote shares are mounted. An empty/new directory on the client is recommended
+for this purpose.
+
+```sh
+mkdir -p /nfs/home
+```
+
+Confirm that the mount point works by mounting it on the client and checking that
+it is mounted with the command below:
+
+```sh
+mount <host_ip_address>:/home
+df -h
+```
+
+### Step 3 - Set up Automatic Mounts on Boot
+
+Edit `/etc/fstab` on client as below to mount the remote shares automatically at boot.
+Note that GitLab requires advisory file locking, which is only supported natively in
+NFS version 4. NFSv3 also supports locking as long as Linux Kernel 2.6.5+ is used.
+We recommend using version 4 and do not specifically test NFSv3.
+
+```text
+#/etc/fstab
+165.227.159.85:/home /nfs/home nfs4 defaults,soft,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2
+```
+
+Reboot the client and confirm that the mount point is mounted automatically.
+
+### Step 4 - Set up GitLab to Use NFS mounts
+
+When using the default Omnibus configuration you will need to share 5 data locations
+between all GitLab cluster nodes. No other locations should be shared. Changing the
+default file locations in `gitlab.rb` on the client allows you to have one main mount
+point and have all the required locations as subdirectories to use the NFS mount for
+git-data.
+
+```text
+git_data_dirs({"default" => {"path" => "/nfs/home/var/opt/gitlab-data/git-data"}})
+gitlab_rails['uploads_directory'] = '/nfs/home/var/opt/gitlab-data/uploads'
+gitlab_rails['shared_path'] = '/nfs/home/var/opt/gitlab-data/shared'
+gitlab_ci['builds_directory'] = '/nfs/home/var/opt/gitlab-data/builds'
+```
+
+Save the changes in `gitlab.rb` and run `gitlab-ctl reconfigure`.
+
+## NFS in a Firewalled Environment
+
+If the traffic between your NFS server and NFS client(s) is subject to port filtering
+by a firewall, then you will need to reconfigure that firewall to allow NFS communication.
+
+[This guide from TDLP](http://tldp.org/HOWTO/NFS-HOWTO/security.html#FIREWALLS)
+covers the basics of using NFS in a firewalled environment. Additionally, we encourage you to
+search for and review the specific documentation for your OS/distro and your firewall software.
+
+Example for Ubuntu:
+
+Check that NFS traffic from the client is allowed by the firewall on the host by running
+the command: `sudo ufw status`. If it's being blocked, then you can allow traffic from a specific
+client with the command below.
+
+```sh
+sudo ufw allow from <client-ip-address> to any port nfs
+```
diff --git a/doc/administration/high_availability/pgbouncer.md b/doc/administration/high_availability/pgbouncer.md
new file mode 100644
index 00000000000..762179cf756
--- /dev/null
+++ b/doc/administration/high_availability/pgbouncer.md
@@ -0,0 +1,132 @@
+# Working with the bundle Pgbouncer service
+
+## Overview
+
+As part of its High Availability stack, GitLab Premium includes a bundled version of [Pgbouncer](https://pgbouncer.github.io/) that can be managed through `/etc/gitlab/gitlab.rb`.
+
+In a High Availability setup, Pgbouncer is used to seamlessly migrate database connections between servers in a failover scenario.
+
+Additionally, it can be used in a non-HA setup to pool connections, speeding up response time while reducing resource usage.
+
+It is recommended to run pgbouncer alongside the `gitlab-rails` service, or on its own dedicated node in a cluster.
+
+## Operations
+
+### Running Pgbouncer as part of an HA GitLab installation
+
+See our [HA documentation for PostgreSQL](database.md) for information on running pgbouncer as part of a HA setup
+
+### Running Pgbouncer as part of a non-HA GitLab installation
+
+1. Generate PGBOUNCER_USER_PASSWORD_HASH with the command `gitlab-ctl pg-password-md5 pgbouncer`
+
+1. Generate SQL_USER_PASSWORD_HASH with the command `gitlab-ctl pg-password-md5 gitlab`. We'll also need to enter the plaintext SQL_USER_PASSWORD later
+
+1. On your database node, ensure the following is set in your `/etc/gitlab/gitlab.rb`
+
+ ```ruby
+ postgresql['pgbouncer_user_password'] = 'PGBOUNCER_USER_PASSWORD_HASH'
+ postgresql['sql_user_password'] = 'SQL_USER_PASSWORD_HASH'
+ postgresql['listen_address'] = 'XX.XX.XX.Y' # Where XX.XX.XX.Y is the ip address on the node postgresql should listen on
+ postgresql['md5_auth_cidr_addresses'] = %w(AA.AA.AA.B/32) # Where AA.AA.AA.B is the IP address of the pgbouncer node
+ ```
+
+1. Run `gitlab-ctl reconfigure`
+
+ **Note:** If the database was already running, it will need to be restarted after reconfigure by running `gitlab-ctl restart postgresql`.
+
+1. On the node you are running pgbouncer on, make sure the following is set in `/etc/gitlab/gitlab.rb`
+
+ ```ruby
+ pgbouncer['enable'] = true
+ pgbouncer['databases'] = {
+ gitlabhq_production: {
+ host: 'DATABASE_HOST',
+ user: 'pgbouncer',
+ password: 'PGBOUNCER_USER_PASSWORD_HASH'
+ }
+ }
+ ```
+
+1. Run `gitlab-ctl reconfigure`
+
+1. On the node running unicorn, make sure the following is set in `/etc/gitlab/gitlab.rb`
+
+ ```ruby
+ gitlab_rails['db_host'] = 'PGBOUNCER_HOST'
+ gitlab_rails['db_port'] = '6432'
+ gitlab_rails['db_password'] = 'SQL_USER_PASSWORD'
+ ```
+
+1. Run `gitlab-ctl reconfigure`
+
+1. At this point, your instance should connect to the database through pgbouncer. If you are having issues, see the [Troubleshooting](#troubleshooting) section
+
+### Interacting with pgbouncer
+
+#### Administrative console
+
+As part of omnibus-gitlab, we provide a command `gitlab-ctl pgb-console` to automatically connect to the pgbouncer administrative console. Please see the [pgbouncer documentation](https://pgbouncer.github.io/usage.html#admin-console) for detailed instructions on how to interact with the console.
+
+To start a session, run
+
+```shell
+# gitlab-ctl pgb-console
+Password for user pgbouncer:
+psql (9.6.8, server 1.7.2/bouncer)
+Type "help" for help.
+
+pgbouncer=#
+```
+
+The password you will be prompted for is the PGBOUNCER_USER_PASSWORD
+
+To get some basic information about the instance, run
+```shell
+pgbouncer=# show databases; show clients; show servers;
+ name | host | port | database | force_user | pool_size | reserve_pool | pool_mode | max_connections | current_connections
+---------------------+-----------+------+---------------------+------------+-----------+--------------+-----------+-----------------+---------------------
+ gitlabhq_production | 127.0.0.1 | 5432 | gitlabhq_production | | 100 | 5 | | 0 | 1
+ pgbouncer | | 6432 | pgbouncer | pgbouncer | 2 | 0 | statement | 0 | 0
+(2 rows)
+
+ type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link
+| remote_pid | tls
+------+-----------+---------------------+--------+-----------+-------+------------+------------+---------------------+---------------------+-----------+------
++------------+-----
+ C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44590 | 127.0.0.1 | 6432 | 2018-04-24 22:13:10 | 2018-04-24 22:17:10 | 0x12444c0 |
+| 0 |
+ C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44592 | 127.0.0.1 | 6432 | 2018-04-24 22:13:10 | 2018-04-24 22:17:10 | 0x12447c0 |
+| 0 |
+ C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44594 | 127.0.0.1 | 6432 | 2018-04-24 22:13:10 | 2018-04-24 22:17:10 | 0x1244940 |
+| 0 |
+ C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44706 | 127.0.0.1 | 6432 | 2018-04-24 22:14:22 | 2018-04-24 22:16:31 | 0x1244ac0 |
+| 0 |
+ C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44708 | 127.0.0.1 | 6432 | 2018-04-24 22:14:22 | 2018-04-24 22:15:15 | 0x1244c40 |
+| 0 |
+ C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44794 | 127.0.0.1 | 6432 | 2018-04-24 22:15:15 | 2018-04-24 22:15:15 | 0x1244dc0 |
+| 0 |
+ C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44798 | 127.0.0.1 | 6432 | 2018-04-24 22:15:15 | 2018-04-24 22:16:31 | 0x1244f40 |
+| 0 |
+ C | pgbouncer | pgbouncer | active | 127.0.0.1 | 44660 | 127.0.0.1 | 6432 | 2018-04-24 22:13:51 | 2018-04-24 22:17:12 | 0x1244640 |
+| 0 |
+(8 rows)
+
+ type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link | rem
+ote_pid | tls
+------+--------+---------------------+-------+-----------+------+------------+------------+---------------------+---------------------+-----------+------+----
+--------+-----
+ S | gitlab | gitlabhq_production | idle | 127.0.0.1 | 5432 | 127.0.0.1 | 35646 | 2018-04-24 22:15:15 | 2018-04-24 22:17:10 | 0x124dca0 | |
+ 19980 |
+(1 row)
+```
+
+## Troubleshooting
+
+In case you are experiencing any issues connecting through pgbouncer, the first place to check is always the logs:
+
+```shell
+# gitlab-ctl tail pgbouncer
+```
+
+Additionally, you can check the output from `show databases` in the [Administrative console](#administrative-console). In the output, you would expect to see values in the `host` field for the `gitlabhq_production` database. Additionally, `current_connections` should be greater than 1.
diff --git a/doc/administration/high_availability/redis.md b/doc/administration/high_availability/redis.md
index 3daebc4d84b..1aaa709fc8f 100644
--- a/doc/administration/high_availability/redis.md
+++ b/doc/administration/high_availability/redis.md
@@ -1,6 +1,103 @@
-# Configuring Redis for GitLab HA
+# Configuring Redis for Scaling and High Availability
-> Experimental Redis Sentinel support was [Introduced][ce-1877] in GitLab 8.11.
+## Provide your own Redis instance **[CORE ONLY]**
+
+The following are the requirements for providing your own Redis instance:
+
+- Redis version 2.8 or higher. Version 3.2 or higher is recommend as this is
+ what ships with the GitLab Omnibus package.
+- Standalone Redis or Redis high availability with Sentinel are supported. Redis
+ Cluster is not supported.
+- Managed Redis from cloud providers such as AWS Elasticache will work. If these
+ services support high availability, be sure it is not the Redis Cluster type.
+
+Note the Redis node's IP address or hostname, port, and password (if required).
+These will be necessary when configuring the GitLab application servers later.
+
+## Redis in a Scaled Environment
+
+This section is relevant for [Scaled Architecture](README.md#scalable-architecture-examples)
+environments including [Basic Scaling](README.md#basic-scaling) and
+[Full Scaling](README.md#full-scaling).
+
+### Provide your own Redis instance **[CORE ONLY]**
+
+If you want to use your own deployed Redis instance(s),
+see [Provide your own Redis instance](#provide-your-own-redis-instance-core-only)
+for more details. However, you can use the GitLab Omnibus package to easily
+deploy the bundled Redis.
+
+### Standalone Redis using GitLab Omnibus **[CORE ONLY]**
+
+The GitLab Omnibus package can be used to configure a standalone Redis server.
+In this configuration Redis is not highly available, and represents a single
+point of failure. However, in a scaled environment the objective is to allow
+the environment to handle more users or to increase throughput. Redis itself
+is generally stable and can handle many requests so it is an acceptable
+trade off to have only a single instance. See [Scaling and High Availability](README.md)
+for an overview of GitLab scaling and high availability options.
+
+The steps below are the minimum necessary to configure a Redis server with
+Omnibus:
+
+1. SSH into the Redis server.
+1. [Download/install](https://about.gitlab.com/installation) the Omnibus GitLab
+ package you want using **steps 1 and 2** from the GitLab downloads page.
+ - Do not complete any other steps on the download page.
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
+
+ ```ruby
+ ## Enable Redis
+ redis['enable'] = true
+
+ ## Disable all other services
+ sidekiq['enable'] = false
+ gitlab_workhorse['enable'] = false
+ unicorn['enable'] = false
+ postgresql['enable'] = false
+ nginx['enable'] = false
+ prometheus['enable'] = false
+ alertmanager['enable'] = false
+ pgbouncer_exporter['enable'] = false
+ gitlab_monitor['enable'] = false
+ gitaly['enable'] = false
+
+ redis['bind'] = '0.0.0.0'
+ redis['port'] = '6379'
+ redis['password'] = 'SECRET_PASSWORD_HERE'
+
+ gitlab_rails['auto_migrate'] = false
+ ```
+
+1. [Reconfigure Omnibus GitLab][reconfigure] for the changes to take effect.
+1. Note the Redis node's IP address or hostname, port, and
+ Redis password. These will be necessary when configuring the GitLab
+ application servers later.
+
+Advanced configuration options are supported and can be added if
+needed.
+
+Continue configuration of other components by going
+[back to Scaled Architectures](README.md#scalable-architecture-examples)
+
+## Redis with High Availability
+
+This section is relevant for [High Availability Architecture](README.md#high-availability-architecture-examples)
+environments including [Horizontal](README.md#horizontal),
+[Hybrid](README.md#hybrid), and
+[Fully Distributed](README.md#fully-distributed).
+
+### Provide your own Redis instance **[CORE ONLY]**
+
+If you want to use your own deployed Redis instance(s),
+see [Provide your own Redis instance](#provide-your-own-redis-instance-core-only)
+for more details. However, you can use the GitLab Omnibus package to easily
+deploy the bundled Redis.
+
+### High Availability with GitLab Omnibus **[PREMIUM ONLY]**
+
+> Experimental Redis Sentinel support was [introduced in GitLab 8.11][ce-1877].
Starting with 8.14, Redis Sentinel is no longer experimental.
If you've used it with versions `< 8.14` before, please check the updated
documentation here.
@@ -53,8 +150,6 @@ failure.
Make sure that you read this document once as a whole before configuring the
components below.
-### High Availability with Sentinel
-
> **Notes:**
>
> - Starting with GitLab `8.11`, you can configure a list of Redis Sentinel
@@ -270,10 +365,9 @@ The prerequisites for a HA Redis setup are the following:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- # Enable the master role and disable all other services in the machine
- # (you can still enable Sentinel).
- redis_master_role['enable'] = true
-
+ # Specify server role as 'redis_master_role'
+ roles ['redis_master_role']
+
# IP address pointing to a local IP that the other machines can reach to.
# You can also set bind to '0.0.0.0' which listen in all interfaces.
# If you really need to bind to an external accessible IP, make
@@ -287,6 +381,7 @@ The prerequisites for a HA Redis setup are the following:
# Set up password authentication for Redis (use the same password in all nodes).
redis['password'] = 'redis-password-goes-here'
```
+
1. Only the primary GitLab application server should handle migrations. To
prevent database migrations from running on upgrade, add the following
@@ -298,6 +393,10 @@ The prerequisites for a HA Redis setup are the following:
1. [Reconfigure Omnibus GitLab][reconfigure] for the changes to take effect.
+> Note: You can specify multiple roles like sentinel and redis as:
+> roles ['redis_sentinel_role', 'redis_master_role']. Read more about high
+> availability roles at https://docs.gitlab.com/omnibus/roles/
+
### Step 2. Configuring the slave Redis instances
1. SSH into the **slave** Redis server.
@@ -310,11 +409,9 @@ The prerequisites for a HA Redis setup are the following:
1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
```ruby
- # Enable the slave role and disable all other services in the machine
- # (you can still enable Sentinel). This will also set automatically
- # `redis['master'] = false`.
- redis_slave_role['enable'] = true
-
+ # Specify server role as 'redis_slave_role'
+ roles ['redis_slave_role']
+
# IP address pointing to a local IP that the other machines can reach to.
# You can also set bind to '0.0.0.0' which listen in all interfaces.
# If you really need to bind to an external accessible IP, make
@@ -336,17 +433,19 @@ The prerequisites for a HA Redis setup are the following:
#redis['master_port'] = 6379
```
-1. To prevent database migrations from running on upgrade, run:
+1. To prevent reconfigure from running automatically on upgrade, run:
```
sudo touch /etc/gitlab/skip-auto-reconfigure
```
- Only the primary GitLab application server should handle migrations.
-
1. [Reconfigure Omnibus GitLab][reconfigure] for the changes to take effect.
1. Go through the steps again for all the other slave nodes.
+> Note: You can specify multiple roles like sentinel and redis as:
+> roles ['redis_sentinel_role', 'redis_slave_role']. Read more about high
+> availability roles at https://docs.gitlab.com/omnibus/roles/
+
---
These values don't have to be changed again in `/etc/gitlab/gitlab.rb` after
@@ -400,13 +499,13 @@ multiple machines with the Sentinel daemon.
be duplicate below):
```ruby
- redis_sentinel_role['enable'] = true
+ roles ['redis_sentinel_role']
# Must be the same in every sentinel node
redis['master_name'] = 'gitlab-redis'
# The same password for Redis authentication you set up for the master node.
- redis['password'] = 'redis-password-goes-here'
+ redis['master_password'] = 'redis-password-goes-here'
# The IP of the master Redis node.
redis['master_ip'] = '10.0.0.1'
@@ -573,8 +672,7 @@ or a failover promotes a different **Master** node.
In `/etc/gitlab/gitlab.rb`:
```ruby
-redis_master_role['enable'] = true
-redis_sentinel_role['enable'] = true
+roles ['redis_sentinel_role', 'redis_master_role']
redis['bind'] = '10.0.0.1'
redis['port'] = 6379
redis['password'] = 'redis-password-goes-here'
@@ -596,8 +694,7 @@ sentinel['quorum'] = 2
In `/etc/gitlab/gitlab.rb`:
```ruby
-redis_slave_role['enable'] = true
-redis_sentinel_role['enable'] = true
+roles ['redis_sentinel_role', 'redis_slave_role']
redis['bind'] = '10.0.0.2'
redis['port'] = 6379
redis['password'] = 'redis-password-goes-here'
@@ -619,8 +716,7 @@ sentinel['quorum'] = 2
In `/etc/gitlab/gitlab.rb`:
```ruby
-redis_slave_role['enable'] = true
-redis_sentinel_role['enable'] = true
+roles ['redis_sentinel_role', 'redis_slave_role']
redis['bind'] = '10.0.0.3'
redis['port'] = 6379
redis['password'] = 'redis-password-goes-here'
@@ -643,7 +739,7 @@ In `/etc/gitlab/gitlab.rb`:
```ruby
redis['master_name'] = 'gitlab-redis'
-redis['password'] = 'redis-password-goes-here'
+redis['master_password'] = 'redis-password-goes-here'
gitlab_rails['redis_sentinels'] = [
{'host' => '10.0.0.1', 'port' => 26379},
{'host' => '10.0.0.2', 'port' => 26379},
@@ -764,15 +860,11 @@ Before proceeding with the troubleshooting below, check your firewall rules:
### Troubleshooting Redis replication
You can check if everything is correct by connecting to each server using
-`redis-cli` application, and sending the `INFO` command.
+`redis-cli` application, and sending the `info replication` command as below.
-If authentication was correctly defined, it should fail with:
-`NOAUTH Authentication required` error. Try to authenticate with the
-previous defined password with `AUTH redis-password-goes-here` and
-try the `INFO` command again.
-
-Look for the `# Replication` section where you should see some important
-information like the `role` of the server.
+```
+/opt/gitlab/embedded/bin/redis-cli -h <redis-host-or-ip> -a '<redis-password>' info replication
+```
When connected to a `master` redis, you will see the number of connected
`slaves`, and a list of each with connection details:
@@ -842,7 +934,7 @@ To make sure your configuration is correct:
1. Run in the console:
```ruby
- redis = Redis.new(Gitlab::Redis.params)
+ redis = Redis.new(Gitlab::Redis::SharedState.params)
redis.info
```
diff --git a/doc/administration/img/db_load_balancing_postgres_stats.png b/doc/administration/img/db_load_balancing_postgres_stats.png
new file mode 100644
index 00000000000..8b311616e7b
--- /dev/null
+++ b/doc/administration/img/db_load_balancing_postgres_stats.png
Binary files differ
diff --git a/doc/administration/img/high_availability/active-active-diagram.png b/doc/administration/img/high_availability/active-active-diagram.png
deleted file mode 100644
index 4f5984b88fe..00000000000
--- a/doc/administration/img/high_availability/active-active-diagram.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/img/high_availability/active-passive-diagram.png b/doc/administration/img/high_availability/active-passive-diagram.png
deleted file mode 100644
index 3b42ce5911c..00000000000
--- a/doc/administration/img/high_availability/active-passive-diagram.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/img/instance_review_button.png b/doc/administration/img/instance_review_button.png
new file mode 100644
index 00000000000..b7604d7c7e5
--- /dev/null
+++ b/doc/administration/img/instance_review_button.png
Binary files differ
diff --git a/doc/administration/incoming_email.md b/doc/administration/incoming_email.md
index 658b2f55d30..8271c579f5b 100644
--- a/doc/administration/incoming_email.md
+++ b/doc/administration/incoming_email.md
@@ -10,6 +10,8 @@ GitLab has several features based on receiving incoming emails:
- [New merge request by email](../user/project/merge_requests/index.md#create-new-merge-requests-by-email):
allow GitLab users to create a new merge request by sending an email to a
user-specific email address.
+- [Service Desk](../user/project/service_desk.md): provide e-mail support to
+ your customers through GitLab. **[PREMIUM]**
## Requirements
diff --git a/doc/administration/index.md b/doc/administration/index.md
index 5f368ea8d49..06d900b152d 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -20,7 +20,7 @@ GitLab Community Edition installations only have access to Core features.
GitLab.com is administered by GitLab, Inc., therefore, only GitLab team members have
access to its admin configurations. If you're a GitLab.com user, please check the
-[user documentation](../user/index.html).
+[user documentation](../user/index.md).
NOTE: **Note:**
Non-administrator users don’t have access to GitLab administration tools and settings.
@@ -32,8 +32,15 @@ Learn how to install, configure, update, and maintain your GitLab instance.
### Installing GitLab
- [Install](../install/README.md): Requirements, directory structures, and installation methods.
+ - [Database load balancing](database_load_balancing.md): Distribute database queries among multiple database servers. **[STARTER ONLY]**
+ - [Omnibus support for external MySQL DB](https://docs.gitlab.com/omnibus/settings/database.html#using-a-mysql-database-management-server-enterprise-edition-only): Omnibus package supports configuring an external MySQL database. **[STARTER ONLY]**
+ - [Omnibus support for log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-shipping-gitlab-enterprise-edition-only) **[STARTER ONLY]**
- [High Availability](high_availability/README.md): Configure multiple servers for scaling or high availability.
- - [High Availability on AWS](../university/high-availability/aws/README.md): Set up GitLab HA on Amazon AWS.
+ - [Installing GitLab HA on Amazon Web Services (AWS)](../install/aws/index.md): Set up GitLab High Availability on Amazon AWS.
+- [Geo](geo/replication/index.md): Replicate your GitLab instance to other geographic locations as a read-only fully operational version. **[PREMIUM ONLY]**
+- [Disaster Recovery](geo/disaster_recovery/index.md): Quickly fail-over to a different site with minimal effort in a disaster situation. **[PREMIUM ONLY]**
+- [Pivotal Tile](../install/pivotal/index.md): Deploy GitLab as a pre-configured appliance using Ops Manager (BOSH) for Pivotal Cloud Foundry. **[PREMIUM ONLY]**
+- [Add License](../user/admin_area/license.md): Upload a license at install time to unlock features that are in paid tiers of GitLab. **[STARTER ONLY]**
### Configuring GitLab
@@ -44,8 +51,8 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Global user settings](user_settings.md): Configure instance-wide user permissions.
- [Polling](polling.md): Configure how often the GitLab UI polls for updates.
- [GitLab Pages configuration](pages/index.md): Enable and configure GitLab Pages.
-- [GitLab Pages configuration for GitLab source installations](pages/source.md): Enable and configure GitLab Pages on
- [source installations](../install/installation.md#installation-from-source).
+- [GitLab Pages configuration for GitLab source installations](pages/source.md): Enable and configure GitLab Pages on [source installations](../install/installation.md#installation-from-source).
+- [Uploads configuration](uploads.md): Configure GitLab uploads storage.
- [Environment variables](environment_variables.md): Supported environment variables that can be used to override their defaults values in order to configure GitLab.
- [Plugins](plugins.md): With custom plugins, GitLab administrators can introduce custom integrations without modifying GitLab's source code.
- [Enforcing Terms of Service](../user/admin_area/settings/terms.md)
@@ -54,6 +61,9 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Diff limits](../user/admin_area/diff_limits.md): Configure the diff rendering size limits of branch comparison pages.
- [Merge request diffs storage](merge_request_diffs.md): Configure merge requests diffs external storage.
- [Broadcast Messages](../user/admin_area/broadcast_messages.md): Send messages to GitLab users through the UI.
+- [Elasticsearch](../integration/elasticsearch.md): Enable Elasticsearch to empower GitLab's Advanced Global Search. Useful when you deal with a huge amount of data. **[STARTER ONLY]**
+- [External Classification Policy Authorization](../user/admin_area/settings/external_authorization.md) **[PREMIUM ONLY]**
+- [Upload a license](../user/admin_area/license.md): Upload a license to unlock features that are in paid tiers of GitLab. **[STARTER ONLY]**
- [Admin Area](../user/admin_area/index.md): for self-managed instance-wide configuration and maintenance.
#### Customizing GitLab's appearance
@@ -63,6 +73,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Branded login page](../customization/branded_login_page.md): Customize the login page with your own logo, title, and description.
- [Welcome message](../customization/welcome_message.md): Add a custom welcome message to the sign-in page.
- ["New Project" page](../customization/new_project_page.md): Customize the text to be displayed on the page that opens whenever your users create a new project.
+- [Additional custom email text](../user/admin_area/settings/email.md#custom-additional-text-premium-only): Add additional custom text to emails sent from GitLab. **[PREMIUM ONLY]**
### Maintaining GitLab
@@ -96,33 +107,40 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Libravatar](../customization/libravatar.md): Use Libravatar instead of Gravatar for user avatars.
- [Sign-up restrictions](../user/admin_area/settings/sign_up_restrictions.md): block email addresses of specific domains, or whitelist only specific domains.
- [Access restrictions](../user/admin_area/settings/visibility_and_access_controls.md#enabled-git-access-protocols): Define which Git access protocols can be used to talk to GitLab (SSH, HTTP, HTTPS).
-- [Authentication and Authorization](auth/README.md): Configure external authentication with LDAP, SAML, CAS and additional providers. See also other [authentication](../topics/authentication/index.md#gitlab-administrators) topics (for example, enforcing 2FA).
+- [Authentication and Authorization](auth/README.md): Configure external authentication with LDAP, SAML, CAS and additional providers.
+ - [Sync LDAP](auth/ldap-ee.md) **[STARTER ONLY]**
+ - [Kerberos authentication](../integration/kerberos.md) **[STARTER ONLY]**
+ - See also other [authentication](../topics/authentication/index.md#gitlab-administrators) topics (for example, enforcing 2FA).
+- [Email users](../tools/email.md): Email GitLab users from within GitLab. **[STARTER ONLY]**
+- [User Cohorts](../user/admin_area/user_cohorts.md): Display the monthly cohorts of new users and their activities over time.
+- [Audit logs and events](audit_events.md): View the changes made within the GitLab server for:
+ - Groups and projects. **[STARTER]**
+ - Instances. **[PREMIUM ONLY]**
+- [Auditor users](auditor_users.md): Users with read-only access to all projects, groups, and other resources on the GitLab instance. **[PREMIUM ONLY]**
- [Incoming email](incoming_email.md): Configure incoming emails to allow
- users to [reply by email], create [issues by email] and
- [merge requests by email], and to enable [Service Desk].
+ users to [reply by email](reply_by_email.md), create [issues by email](../user/project/issues/create_new_issue.md#new-issue-via-email) and
+ [merge requests by email](../user/project/merge_requests/index.md#create-new-merge-requests-by-email), and to enable [Service Desk](../user/project/service_desk.md).
- [Postfix for incoming email](reply_by_email_postfix_setup.md): Set up a
basic Postfix mail server with IMAP authentication on Ubuntu for incoming
emails.
- [Abuse reports](../user/admin_area/abuse_reports.md): View and resolve abuse reports from your users.
-[reply by email]: reply_by_email.md
-[issues by email]: ../user/project/issues/create_new_issue.md#new-issue-via-email
-[merge requests by email]: ../user/project/merge_requests/index.md#create-new-merge-requests-by-email
-
## Project settings
- [Container Registry](container_registry.md): Configure Container Registry with GitLab.
- [Issue closing pattern](issue_closing_pattern.md): Customize how to close an issue from commit messages.
- [Gitaly](gitaly/index.md): Configuring Gitaly, GitLab's Git repository storage service.
-- [Default labels](../user/admin_area/labels.html): Create labels that will be automatically added to every new project.
+- [Default labels](../user/admin_area/labels.md): Create labels that will be automatically added to every new project.
- [Restrict the use of public or internal projects](../public_access/public_access.md#restricting-the-use-of-public-or-internal-projects): Restrict the use of visibility levels for users when they create a project or a snippet.
-- [Custom project templates](https://docs.gitlab.com/ee/user/admin_area/custom_project_templates.html): Configure a set of projects to be used as custom templates when creating a new project. **[PREMIUM ONLY]**
+- [Custom project templates](../user/admin_area/custom_project_templates.md): Configure a set of projects to be used as custom templates when creating a new project. **[PREMIUM ONLY]**
+- [Packages](packages.md): Enable GitLab to act as a Maven repository or NPM registry. **[PREMIUM ONLY]**
### Repository settings
- [Repository checks](repository_checks.md): Periodic Git repository checks.
- [Repository storage paths](repository_storage_paths.md): Manage the paths used to store repositories.
- [Repository storage rake tasks](raketasks/storage.md): A collection of rake tasks to list and migrate existing projects and attachments associated with it from Legacy storage to Hashed storage.
+- [Limit repository size](../user/admin_area/settings/account_and_limit_settings.md): Set a hard limit for your repositories' size. **[STARTER ONLY]**
## Continuous Integration settings
@@ -131,7 +149,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Job artifacts](job_artifacts.md): Enable, disable, and configure job artifacts (a set of files and directories which are outputted by a job when it completes successfully).
- [Job traces](job_traces.md): Information about the job traces (logs).
- [Register Shared and specific Runners](../ci/runners/README.md#registering-a-shared-runner): Learn how to register and configure Shared and specific Runners to your own instance.
-- [Shared Runners pipelines quota](https://docs.gitlab.com/ee/user/admin_area/settings/continuous_integration.html#shared-runners-pipeline-minutes-quota-starter-only): Limit the usage of pipeline minutes for Shared Runners. **[STARTER ONLY]**
+- [Shared Runners pipelines quota](../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota-starter-only): Limit the usage of pipeline minutes for Shared Runners. **[STARTER ONLY]**
- [Enable/disable Auto DevOps](../topics/autodevops/index.md#enablingdisabling-auto-devops): Enable or disable Auto DevOps for your instance.
## Git configuration options
@@ -159,6 +177,10 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Request Profiling](monitoring/performance/request_profiling.md): Get a detailed profile on slow requests.
- [Performance Bar](monitoring/performance/performance_bar.md): Get performance information for the current page.
+## Analytics
+
+- [Pseudonymizer](pseudonymizer.md): Export data from GitLab's database to CSV files in a secure way. **[ULTIMATE]**
+
## Troubleshooting
- [Debugging tips](troubleshooting/debug.md): Tips to debug problems when things go wrong
diff --git a/doc/administration/instance_review.md b/doc/administration/instance_review.md
new file mode 100644
index 00000000000..b1244f44e95
--- /dev/null
+++ b/doc/administration/instance_review.md
@@ -0,0 +1,17 @@
+# Instance Review **[CORE ONLY]**
+
+> [Introduced][6995] in [GitLab Core][ee] 11.3.
+
+If you are running a medium size instance of GitLab Core edition you are qualified for a free Instance Review. You can find the button in the User menu.
+
+![Instance Review button](img/instance_review_button.png)
+
+When you click the button you will be redirected to a form with prefilled data obtained from your instance.
+
+Once you submit the data to GitLab Inc. you can see the initial report.
+
+Additionally you will be contacted by our team for further review which should help you to improve your usage of GitLab.
+
+[6995]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6995
+[ee]: https://about.gitlab.com/pricing/
+
diff --git a/doc/administration/integration/plantuml.md b/doc/administration/integration/plantuml.md
index d383d1efe70..82e0c14ffc2 100644
--- a/doc/administration/integration/plantuml.md
+++ b/doc/administration/integration/plantuml.md
@@ -27,7 +27,7 @@ own PlantUML server is easy in Debian/Ubuntu distributions using Tomcat.
First you need to create a `plantuml.war` file from the source code:
```
-sudo apt-get install graphviz openjdk-7-jdk git-core maven
+sudo apt-get install graphviz openjdk-8-jdk git-core maven
git clone https://github.com/plantuml/plantuml-server.git
cd plantuml-server
mvn package
@@ -57,8 +57,7 @@ you can change these defaults by editing the `/etc/tomcat7/server.xml` file.
You need to enable PlantUML integration from Settings under Admin Area. To do
that, login with an Admin account and do following:
- - in GitLab go to **Admin Area** and then **Settings**
- - scroll to bottom of the page until PlantUML section
+ - in GitLab go to **Admin Area**->**Settings**->**Integrations**->**PlantUML**
- check **Enable PlantUML** checkbox
- set the PlantUML instance as **PlantUML URL**
diff --git a/doc/administration/integration/terminal.md b/doc/administration/integration/terminal.md
index 2596e3fe68b..c34858cd0db 100644
--- a/doc/administration/integration/terminal.md
+++ b/doc/administration/integration/terminal.md
@@ -43,6 +43,11 @@ detail below.
## Enabling and disabling terminal support
+NOTE: **Note:** AWS Elastic Load Balancers (ELBs) do not support web sockets.
+AWS Application Load Balancers (ALBs) must be used if you want web terminals
+to work. See [AWS Elastic Load Balancing Product Comparison](https://aws.amazon.com/elasticloadbalancing/features/#compare)
+for more information.
+
As web terminals use WebSockets, every HTTP/HTTPS reverse proxy in front of
Workhorse needs to be configured to pass the `Connection` and `Upgrade` headers
through to the next one in the chain. If you installed GitLab using Omnibus, or
diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md
index e7792106f81..05e15fc303b 100644
--- a/doc/administration/job_artifacts.md
+++ b/doc/administration/job_artifacts.md
@@ -7,9 +7,9 @@
> - Starting with GitLab 8.17, builds are renamed to jobs.
> - This is the administration documentation. For the user guide see [pipelines/job_artifacts](../user/project/pipelines/job_artifacts.md).
-Artifacts is a list of files and directories which are attached to a job
-after it completes successfully. This feature is enabled by default in all
-GitLab installations. Keep reading if you want to know how to disable it.
+Artifacts is a list of files and directories which are attached to a job after it
+finishes. This feature is enabled by default in all GitLab installations. Keep reading
+if you want to know how to disable it.
## Disabling job artifacts
@@ -42,8 +42,9 @@ To disable artifacts site-wide, follow the steps below.
## Storing job artifacts
-After a successful job, GitLab Runner uploads an archive containing the job
-artifacts to GitLab.
+GitLab Runner can upload an archive containing the job artifacts to GitLab. By default,
+this is done when the job succeeds, but can also be done on failure, or always, via the
+[`artifacts:when`](../ci/yaml/README.md#artifactswhen) parameter.
### Using local storage
@@ -100,6 +101,9 @@ artifacts, you can use an object storage like AWS S3 instead.
This configuration relies on valid AWS credentials to be configured already.
Use an object storage option like AWS S3 to store job artifacts.
+DANGER: **Danger:**
+If you're enabling S3 in [GitLab HA](high_availability/README.md), you will need to have an [NFS mount set up for CI traces and artifacts](high_availability/nfs.md#a-single-nfs-mount) or enable [live tracing](job_traces.md#new-live-trace-architecture). If these settings are not set, you will risk job traces disappearing or not being saved.
+
### Object Storage Settings
For source installations the following settings are nested under `artifacts:` and then `object_store:`. On omnibus installs they are prefixed by `artifacts_object_store_`.
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index 3d40cda491a..c5cfb8d5016 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -129,7 +129,7 @@ It contains information about [integrations](../user/project/integrations/projec
``` json
{"severity":"ERROR","time":"2018-09-06T14:56:20.439Z","service_class":"JiraService","project_id":8,"project_path":"h5bp/html5-boilerplate","message":"Error sending message","client_url":"http://jira.gitlap.com:8080","error":"execution expired"}
-{"severity":"INFO","time":"2018-09-06T17:15:16.365Z","service_class":"JiraService","project_id":3,"project_path":"namespace2/project2","message":"Successfully posted","client_url":"http://jira.example.net"}
+{"severity":"INFO","time":"2018-09-06T17:15:16.365Z","service_class":"JiraService","project_id":3,"project_path":"namespace2/project2","message":"Successfully posted","client_url":"http://jira.example.com"}
```
## `kubernetes.log`
@@ -280,6 +280,28 @@ installations from source.
Currently it logs the progress of project imports from the Bitbucket Server
importer. Future importers may use this file.
+## `auth.log`
+
+Introduced in GitLab 12.0. This file lives in `/var/log/gitlab/gitlab-rails/auth.log` for
+Omnibus GitLab packages or in `/home/git/gitlab/log/auth.log` for
+installations from source.
+
+It logs information whenever [Rack Attack] registers an abusive request.
+
+## `graphql_json.log`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/59587) in GitLab 12.0.
+
+This file lives in `/var/log/gitlab/gitlab-rails/graphql_json.log` for
+Omnibus GitLab packages or in `/home/git/gitlab/log/graphql_json.log` for
+installations from source.
+
+GraphQL queries are recorded in that file. For example:
+
+```json
+{"query_string":"query IntrospectionQuery{__schema {queryType { name },mutationType { name }}}...(etc)","variables":{"a":1,"b":2},"complexity":181,"depth":1,"duration":7}
+```
+
## Reconfigure Logs
Reconfigure log files live in `/var/log/gitlab/reconfigure` for Omnibus GitLab
@@ -298,3 +320,4 @@ Omnibus GitLab packages or in `/home/git/gitlab/log/sidekiq_exporter.log` for
installations from source.
[repocheck]: repository_checks.md
+[Rack Attack]: ../security/rack_attack.md
diff --git a/doc/administration/maven_packages.md b/doc/administration/maven_packages.md
new file mode 100644
index 00000000000..d8551f64ece
--- /dev/null
+++ b/doc/administration/maven_packages.md
@@ -0,0 +1,5 @@
+---
+redirect_to: 'packages.md'
+---
+
+This document was moved to [another location](packages.md).
diff --git a/doc/administration/maven_repository.md b/doc/administration/maven_repository.md
new file mode 100644
index 00000000000..d8551f64ece
--- /dev/null
+++ b/doc/administration/maven_repository.md
@@ -0,0 +1,5 @@
+---
+redirect_to: 'packages.md'
+---
+
+This document was moved to [another location](packages.md).
diff --git a/doc/administration/monitoring/performance/grafana_configuration.md b/doc/administration/monitoring/performance/grafana_configuration.md
index ab43ec2cc4f..187fb2f73a1 100644
--- a/doc/administration/monitoring/performance/grafana_configuration.md
+++ b/doc/administration/monitoring/performance/grafana_configuration.md
@@ -3,7 +3,7 @@
[Grafana](http://grafana.org/) is a tool that allows you to visualize time
series metrics through graphs and dashboards. It supports several backend
data stores, including InfluxDB. GitLab writes performance data to InfluxDB
-and Grafana will allow you to query InfluxDB to display useful graphs.
+and Grafana will allow you to query to display useful graphs.
For the easiest installation and configuration, install Grafana on the same
server as InfluxDB. For larger installations, you may want to split out these
@@ -11,11 +11,13 @@ services.
## Installation
-Grafana supplies package repositories (Yum/Apt) for easy installation.
+[GitLab Omnibus can help you install Grafana (recommended)](https://docs.gitlab.com/omnibus/settings/grafana.html)
+or Grafana supplies package repositories (Yum/Apt) for easy installation.
See [Grafana installation documentation](http://docs.grafana.org/installation/)
for detailed steps.
-> **Note**: Before starting Grafana for the first time, set the admin user
+NOTE: **Note:**
+Before starting Grafana for the first time, set the admin user
and password in `/etc/grafana/grafana.ini`. Otherwise, the default password
will be `admin`.
diff --git a/doc/administration/monitoring/performance/index.md b/doc/administration/monitoring/performance/index.md
index f5f0363ed38..ef71ca1d6c3 100644
--- a/doc/administration/monitoring/performance/index.md
+++ b/doc/administration/monitoring/performance/index.md
@@ -14,7 +14,7 @@ documents in order to understand and properly configure GitLab Performance Monit
- [Performance bar](performance_bar.md)
- [Request profiling](request_profiling.md)
->**Note:**
+NOTE: **Note:**
Omnibus GitLab 8.16 includes Prometheus as an additional tool to collect
metrics. It will eventually replace InfluxDB when their metrics collection is
on par. Read more in the [Prometheus documentation](../prometheus/index.md).
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index 3bfcc9a289e..84b71ae6f1c 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -43,10 +43,52 @@ The following metrics are available:
| redis_ping_latency_seconds | Gauge | 9.4 | Round trip time of the redis ping |
| user_session_logins_total | Counter | 9.4 | Counter of how many users have logged in |
| upload_file_does_not_exist | Counter | 10.7 in EE, 11.5 in CE | Number of times an upload record could not find its file |
-| failed_login_captcha_total | Gauge | 11.0 | Counter of failed CAPTCHA attempts during login |
-| successful_login_captcha_total | Gauge | 11.0 | Counter of successful CAPTCHA attempts during login |
-| unicorn_active_connections | Gauge | 11.0 | The number of active Unicorn connections (workers) |
-| unicorn_queued_connections | Gauge | 11.0 | The number of queued Unicorn connections |
+| failed_login_captcha_total | Gauge | 11.0 | Counter of failed CAPTCHA attempts during login |
+| successful_login_captcha_total | Gauge | 11.0 | Counter of successful CAPTCHA attempts during login |
+| unicorn_active_connections | Gauge | 11.0 | The number of active Unicorn connections (workers) |
+| unicorn_queued_connections | Gauge | 11.0 | The number of queued Unicorn connections |
+| unicorn_workers | Gauge | 12.0 | The number of Unicorn workers |
+
+## Sidekiq Metrics available for Geo **[PREMIUM]**
+
+Sidekiq jobs may also gather metrics, and these metrics can be accessed if the Sidekiq exporter is enabled (e.g. via
+the `monitoring.sidekiq_exporter` configuration option in `gitlab.yml`.
+
+| Metric | Type | Since | Description | Labels |
+|:-------------------------------------------- |:------- |:----- |:----------- |:------ |
+| geo_db_replication_lag_seconds | Gauge | 10.2 | Database replication lag (seconds) | url
+| geo_repositories | Gauge | 10.2 | Total number of repositories available on primary | url
+| geo_repositories_synced | Gauge | 10.2 | Number of repositories synced on secondary | url
+| geo_repositories_failed | Gauge | 10.2 | Number of repositories failed to sync on secondary | url
+| geo_lfs_objects | Gauge | 10.2 | Total number of LFS objects available on primary | url
+| geo_lfs_objects_synced | Gauge | 10.2 | Number of LFS objects synced on secondary | url
+| geo_lfs_objects_failed | Gauge | 10.2 | Number of LFS objects failed to sync on secondary | url
+| geo_attachments | Gauge | 10.2 | Total number of file attachments available on primary | url
+| geo_attachments_synced | Gauge | 10.2 | Number of attachments synced on secondary | url
+| geo_attachments_failed | Gauge | 10.2 | Number of attachments failed to sync on secondary | url
+| geo_last_event_id | Gauge | 10.2 | Database ID of the latest event log entry on the primary | url
+| geo_last_event_timestamp | Gauge | 10.2 | UNIX timestamp of the latest event log entry on the primary | url
+| geo_cursor_last_event_id | Gauge | 10.2 | Last database ID of the event log processed by the secondary | url
+| geo_cursor_last_event_timestamp | Gauge | 10.2 | Last UNIX timestamp of the event log processed by the secondary | url
+| geo_status_failed_total | Counter | 10.2 | Number of times retrieving the status from the Geo Node failed | url
+| geo_last_successful_status_check_timestamp | Gauge | 10.2 | Last timestamp when the status was successfully updated | url
+| geo_lfs_objects_synced_missing_on_primary | Gauge | 10.7 | Number of LFS objects marked as synced due to the file missing on the primary | url
+| geo_job_artifacts_synced_missing_on_primary | Gauge | 10.7 | Number of job artifacts marked as synced due to the file missing on the primary | url
+| geo_attachments_synced_missing_on_primary | Gauge | 10.7 | Number of attachments marked as synced due to the file missing on the primary | url
+| geo_repositories_checksummed_count | Gauge | 10.7 | Number of repositories checksummed on primary | url
+| geo_repositories_checksum_failed_count | Gauge | 10.7 | Number of repositories failed to calculate the checksum on primary | url
+| geo_wikis_checksummed_count | Gauge | 10.7 | Number of wikis checksummed on primary | url
+| geo_wikis_checksum_failed_count | Gauge | 10.7 | Number of wikis failed to calculate the checksum on primary | url
+| geo_repositories_verified_count | Gauge | 10.7 | Number of repositories verified on secondary | url
+| geo_repositories_verification_failed_count | Gauge | 10.7 | Number of repositories failed to verify on secondary | url
+| geo_repositories_checksum_mismatch_count | Gauge | 10.7 | Number of repositories that checksum mismatch on secondary | url
+| geo_wikis_verified_count | Gauge | 10.7 | Number of wikis verified on secondary | url
+| geo_wikis_verification_failed_count | Gauge | 10.7 | Number of wikis failed to verify on secondary | url
+| geo_wikis_checksum_mismatch_count | Gauge | 10.7 | Number of wikis that checksum mismatch on secondary | url
+| geo_repositories_checked_count | Gauge | 11.1 | Number of repositories that have been checked via `git fsck` | url
+| geo_repositories_checked_failed_count | Gauge | 11.1 | Number of repositories that have a failure from `git fsck` | url
+| geo_repositories_retrying_verification_count | Gauge | 11.2 | Number of repositories verification failures that Geo is actively trying to correct on secondary | url
+| geo_wikis_retrying_verification_count | Gauge | 11.2 | Number of wikis verification failures that Geo is actively trying to correct on secondary | url
### Ruby metrics
@@ -59,9 +101,32 @@ Some basic Ruby runtime metrics are available:
| ruby_file_descriptors | Gauge | 11.1 | File descriptors per process |
| ruby_memory_bytes | Gauge | 11.1 | Memory usage by process |
| ruby_sampler_duration_seconds_total | Counter | 11.1 | Time spent collecting stats |
+| ruby_process_cpu_seconds_total | Gauge | 12.0 | Total amount of CPU time per process |
+| ruby_process_max_fds | Gauge | 12.0 | Maximum number of open file descriptors per process |
+| ruby_process_resident_memory_bytes | Gauge | 12.0 | Memory usage by process, measured in bytes |
+| ruby_process_start_time_seconds | Gauge | 12.0 | The elapsed time between system boot and the process started, measured in seconds |
[GC.stat]: https://ruby-doc.org/core-2.3.0/GC.html#method-c-stat
+## Puma Metrics **[EXPERIMENTAL]**
+
+When Puma is used instead of Unicorn, following metrics are available:
+
+| Metric | Type | Since | Description |
+|:-------------------------------------------- |:------- |:----- |:----------- |
+| puma_workers | Gauge | 12.0 | Total number of workers |
+| puma_running_workers | Gauge | 12.0 | Number of booted workers |
+| puma_stale_workers | Gauge | 12.0 | Number of old workers |
+| puma_phase | Gauge | 12.0 | Phase number (increased during phased restarts) |
+| puma_running | Gauge | 12.0 | Number of running threads |
+| puma_queued_connections | Gauge | 12.0 | Number of connections in that worker's "todo" set waiting for a worker thread |
+| puma_active_connections | Gauge | 12.0 | Number of threads processing a request |
+| puma_pool_capacity | Gauge | 12.0 | Number of requests the worker is capable of taking right now |
+| puma_max_threads | Gauge | 12.0 | Maximum number of worker threads |
+| puma_idle_threads | Gauge | 12.0 | Number of spawned threads which are not processing a request |
+| rack_state_total | Gauge | 12.0 | Number of requests in a given rack state |
+| puma_killer_terminations_total | Gauge | 12.0 | Number of workers terminated by PumaWorkerKiller |
+
## Metrics shared directory
GitLab's Prometheus client requires a directory to store metrics data shared between multi-process services.
diff --git a/doc/administration/monitoring/prometheus/index.md b/doc/administration/monitoring/prometheus/index.md
index f2ac155a694..ce65d77274b 100644
--- a/doc/administration/monitoring/prometheus/index.md
+++ b/doc/administration/monitoring/prometheus/index.md
@@ -96,13 +96,15 @@ To use an external Prometheus server:
1. Set each bundled service's [exporter](#bundled-software-metrics) to listen on a network address, for example:
- ```ruby
+ ```ruby
gitlab_monitor['listen_address'] = '0.0.0.0'
+ sidekiq['listen_address'] = '0.0.0.0'
gitlab_monitor['listen_port'] = '9168'
- gitaly['prometheus_listen_addr'] = "0.0.0.0:9236"
node_exporter['listen_address'] = '0.0.0.0:9100'
redis_exporter['listen_address'] = '0.0.0.0:9121'
postgres_exporter['listen_address'] = '0.0.0.0:9187'
+ gitaly['prometheus_listen_addr'] = "0.0.0.0:9236"
+ gitlab_workhorse['prometheus_listen_addr'] = "0.0.0.0:9229"
```
1. Install and set up a dedicated Prometheus instance, if necessary, using the [official installation instructions](https://prometheus.io/docs/prometheus/latest/installation/).
@@ -112,6 +114,18 @@ To use an external Prometheus server:
gitlab_rails['monitoring_whitelist'] = ['127.0.0.0/8', '192.168.0.1']
```
+1. To scrape nginx metrics, you'll also need to configure nginx to allow the Prometheus server
+ IP. For example:
+
+ ```ruby
+ nginx['status']['options'] = {
+ "server_tokens" => "off",
+ "access_log" => "off",
+ "allow" => "192.168.0.1",
+ "deny" => "all",
+ }
+ ```
+
1. [Reconfigure GitLab][reconfigure] to apply the changes
1. Edit the Prometheus server's configuration file.
1. Add each node's exporters to the Prometheus server's
@@ -203,6 +217,12 @@ The Postgres exporter allows you to measure various PostgreSQL metrics.
[âž” Read more about the Postgres exporter.](postgres_exporter.md)
+### PgBouncer exporter
+
+The PgBouncer exporter allows you to measure various PgBouncer metrics.
+
+[âž” Read more about the PgBouncer exporter.](pgbouncer_exporter.md)
+
### GitLab monitor exporter
The GitLab monitor exporter allows you to measure various GitLab metrics, pulled from Redis and the database.
diff --git a/doc/administration/monitoring/prometheus/pgbouncer_exporter.md b/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
new file mode 100644
index 00000000000..d76834fdbea
--- /dev/null
+++ b/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
@@ -0,0 +1,34 @@
+# PgBouncer exporter
+
+>**Note:**
+Available since [Omnibus GitLab 11.0][2493]. For installations from source
+you'll have to install and configure it yourself.
+
+The [PgBouncer exporter] allows you to measure various PgBouncer metrics.
+
+To enable the PgBouncer exporter:
+
+1. [Enable Prometheus](index.md#configuring-prometheus)
+1. Edit `/etc/gitlab/gitlab.rb`
+1. Add or find and uncomment the following line, making sure it's set to `true`:
+
+ ```ruby
+ pgbouncer_exporter['enable'] = true
+ ```
+
+1. Save the file and [reconfigure GitLab][reconfigure] for the changes to
+ take effect.
+
+Prometheus will now automatically begin collecting performance data from
+the PgBouncer exporter exposed under `localhost:9188`.
+
+The PgBouncer exporter will also be enabled by default if the [pgbouncer_role][postgres roles]
+is enabled.
+
+[↠Back to the main Prometheus page](index.md)
+
+[2493]: https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/2493
+[PgBouncer exporter]: https://github.com/stanhu/pgbouncer_exporter
+[postgres roles]: https://docs.gitlab.com/omnibus/roles/#postgres-roles
+[prometheus]: https://prometheus.io
+[reconfigure]: ../../restart_gitlab.md#omnibus-gitlab-reconfigure
diff --git a/doc/administration/npm_registry.md b/doc/administration/npm_registry.md
new file mode 100644
index 00000000000..d8551f64ece
--- /dev/null
+++ b/doc/administration/npm_registry.md
@@ -0,0 +1,5 @@
+---
+redirect_to: 'packages.md'
+---
+
+This document was moved to [another location](packages.md).
diff --git a/doc/administration/operations/cleaning_up_redis_sessions.md b/doc/administration/operations/cleaning_up_redis_sessions.md
index b45ca99fd80..20c19445404 100644
--- a/doc/administration/operations/cleaning_up_redis_sessions.md
+++ b/doc/administration/operations/cleaning_up_redis_sessions.md
@@ -27,7 +27,7 @@ rcli() {
# This example works for Omnibus installations of GitLab 7.3 or newer. For an
# installation from source you will have to change the socket path and the
# path to redis-cli.
- sudo /opt/gitlab/embedded/bin/redis-cli -s /var/opt/gitlab/redis/redis.socket "$@"
+ sudo /opt/gitlab/embedded/bin/redis-cli -s /var/opt/gitlab/redis/redis.shared_state.socket "$@"
}
# test the new shell function; the response should be PONG
diff --git a/doc/administration/operations/extra_sidekiq_processes.md b/doc/administration/operations/extra_sidekiq_processes.md
new file mode 100644
index 00000000000..286b99aceb5
--- /dev/null
+++ b/doc/administration/operations/extra_sidekiq_processes.md
@@ -0,0 +1,218 @@
+# Extra Sidekiq processes **[STARTER ONLY]**
+
+GitLab Enterprise Edition allows one to start an extra set of Sidekiq processes
+besides the default one. These processes can be used to consume a dedicated set
+of queues. This can be used to ensure certain queues always have dedicated
+workers, no matter the number of jobs that need to be processed.
+
+## Starting extra processes via Omnibus GitLab
+
+To enable `sidekiq-cluster`, you must apply the `sidekiq_cluster['enable'] = true`
+setting `/etc/gitlab/gitlab.rb`:
+
+```ruby
+sidekiq_cluster['enable'] = true
+```
+
+You will then specify how many additional processes to create via `sidekiq-cluster`
+as well as which queues for them to handle. This is done via the
+`sidekiq_cluster['queue_groups']` setting. This is an array whose items contain
+which queues to process. Each item in the array will equate to one additional
+sidekiq process.
+
+As an example, to make additional sidekiq processes that process the
+`elastic_indexer` and `mailers` queues, you would apply the following:
+
+```ruby
+sidekiq_cluster['queue_groups'] = [
+ "elastic_indexer",
+ "mailers"
+]
+```
+
+To have an additional sidekiq process handle multiple queues, you simply put a
+comma after the first queue name and then put the next queue name:
+
+```ruby
+sidekiq_cluster['queue_groups'] = [
+ "elastic_indexer,elastic_commit_indexer",
+ "mailers"
+]
+```
+
+Keep in mind, all changes must be followed by reconfiguring your GitLab
+application via `sudo gitlab-ctl reconfigure`.
+
+### Monitoring
+
+Once the Sidekiq processes are added, you can visit the "Background Jobs"
+section under the admin area in GitLab (`/admin/background_jobs`).
+
+![Extra sidekiq processes](img/sidekiq-cluster.png)
+
+### All queues with exceptions
+
+To have the additional sidekiq processes work on every queue EXCEPT the ones
+you list:
+
+1. Edit `/etc/gitlab/gitlab.rb` and add:
+
+ ```ruby
+ sidekiq_cluster['negate'] = true
+ ```
+
+1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
+
+### Limiting concurrency
+
+1. Edit `/etc/gitlab/gitlab.rb` and add:
+
+ ```ruby
+ sidekiq_cluster['concurrency'] = 25
+ ```
+
+1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
+Keep in mind, this normally would not exceed the number of CPU cores available.
+
+### Modifying the check interval
+
+To modify the check interval for the additional Sidekiq processes:
+
+1. Edit `/etc/gitlab/gitlab.rb` and add:
+
+ ```ruby
+ sidekiq_cluster['interval'] = 5
+ ```
+
+1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
+This tells the additional processes how often to check for enqueued jobs.
+
+## Starting extra processes via command line
+
+Starting extra Sidekiq processes can be done using the command
+`/opt/gitlab/embedded/service/gitlab-rails/ee/bin/sidekiq-cluster`. This command
+takes arguments using the following syntax:
+
+```bash
+/opt/gitlab/embedded/service/gitlab-rails/ee/bin/sidekiq-cluster [QUEUE,QUEUE,...] [QUEUE, ...]
+```
+
+Each separate argument denotes a group of queues that have to be processed by a
+Sidekiq process. Multiple queues can be processed by the same process by
+separating them with a comma instead of a space.
+
+Instead of a queue, a queue namespace can also be provided, to have the process
+automatically listen on all queues in that namespace without needing to
+explicitly list all the queue names. For more information about queue namespaces,
+see the relevant section in the
+[Sidekiq style guide](../../development/sidekiq_style_guide.md#queue-namespaces).
+
+For example, say you want to start 2 extra processes: one to process the
+"process_commit" queue, and one to process the "post_receive" queue. This can be
+done as follows:
+
+```bash
+/opt/gitlab/embedded/service/gitlab-rails/ee/bin/sidekiq-cluster process_commit post_receive
+```
+
+If you instead want to start one process processing both queues you'd use the
+following syntax:
+
+```bash
+/opt/gitlab/embedded/service/gitlab-rails/ee/bin/sidekiq-cluster process_commit,post_receive
+```
+
+If you want to have one Sidekiq process process the "process_commit" and
+"post_receive" queues, and one process to process the "gitlab_shell" queue,
+you'd use the following:
+
+```bash
+/opt/gitlab/embedded/service/gitlab-rails/ee/bin/sidekiq-cluster process_commit,post_receive gitlab_shell
+```
+
+### Monitoring
+
+The `sidekiq-cluster` command will not terminate once it has started the desired
+amount of Sidekiq processes. Instead, the process will continue running and
+forward any signals to the child processes. This makes it easy to stop all
+Sidekiq processes as you simply send a signal to the `sidekiq-cluster` process,
+instead of having to send it to the individual processes.
+
+If the `sidekiq-cluster` process crashes or receives a `SIGKILL`, the child
+processes will terminate themselves after a few seconds. This ensures you don't
+end up with zombie Sidekiq processes.
+
+All of this makes monitoring the processes fairly easy. Simply hook up
+`sidekiq-cluster` to your supervisor of choice (e.g. runit) and you're good to
+go.
+
+If a child process died the `sidekiq-cluster` command will signal all remaining
+process to terminate, then terminate itself. This removes the need for
+`sidekiq-cluster` to re-implement complex process monitoring/restarting code.
+Instead you should make sure your supervisor restarts the `sidekiq-cluster`
+process whenever necessary.
+
+### PID files
+
+The `sidekiq-cluster` command can store its PID in a file. By default no PID
+file is written, but this can be changed by passing the `--pidfile` option to
+`sidekiq-cluster`. For example:
+
+```bash
+/opt/gitlab/embedded/service/gitlab-rails/ee/bin/sidekiq-cluster --pidfile /var/run/gitlab/sidekiq_cluster.pid process_commit
+```
+
+Keep in mind that the PID file will contain the PID of the `sidekiq-cluster`
+command and not the PID(s) of the started Sidekiq processes.
+
+### Environment
+
+The Rails environment can be set by passing the `--environment` flag to the
+`sidekiq-cluster` command, or by setting `RAILS_ENV` to a non-empty value. The
+default value is "development".
+
+### All queues with exceptions
+
+You're able to run all queues in `sidekiq_queues.yml` file on a single or
+multiple processes with exceptions using the `--negate` flag.
+
+For example, say you want to run a single process for all queues,
+except "process_commit" and "post_receive". You can do so by executing:
+
+```bash
+sidekiq-cluster process_commit,post_receive --negate
+```
+
+For multiple processes of all queues (except "process_commit" and "post_receive"):
+
+```bash
+sidekiq-cluster process_commit,post_receive process_commit,post_receive --negate
+```
+
+### Limiting concurrency
+
+By default, `sidekiq-cluster` will spin up extra Sidekiq processes that use
+one thread per queue up to a maximum of 50. If you wish to change the cap, use
+the `-m N` option. For example, this would cap the maximum number of threads to 1:
+
+```bash
+/opt/gitlab/embedded/service/gitlab-rails/ee/bin/sidekiq-cluster process_commit,post_receive -m 1
+```
+
+For each queue group, the concurrency factor will be set to min(number of
+queues, N). Setting the value to 0 will disable the limit.
+
+Note that each thread requires a Redis connection, so adding threads may
+increase Redis latency and potentially cause client timeouts. See the [Sidekiq
+documentation about Redis](https://github.com/mperham/sidekiq/wiki/Using-Redis)
+for more details.
+
+## Number of threads
+
+Each process started using `sidekiq-cluster` (whether it be via command line or
+via the gitlab.rb file) starts with a number of threads that equals the number
+of queues, plus one spare thread. For example, a process that handles the
+"process_commit" and "post_receive" queues will use 3 threads in total.
diff --git a/doc/administration/operations/fast_ssh_key_lookup.md b/doc/administration/operations/fast_ssh_key_lookup.md
index f8d58c6ce28..3631ea0822f 100644
--- a/doc/administration/operations/fast_ssh_key_lookup.md
+++ b/doc/administration/operations/fast_ssh_key_lookup.md
@@ -30,6 +30,19 @@ instructions will break installations using older versions of OpenSSH, such as
those included with CentOS 6 as of September 2017. If you want to use this
feature for CentOS 6, follow [the instructions on how to build and install a custom OpenSSH package](#compiling-a-custom-version-of-openssh-for-centos-6) before continuing.
+## Fast lookup is required for Geo **[PREMIUM]**
+
+By default, GitLab manages an `authorized_keys` file, which contains all the
+public SSH keys for users allowed to access GitLab. However, to maintain a
+single source of truth, [Geo](../geo/replication/index.md) needs to be configured to perform SSH fingerprint
+lookups via database lookup.
+
+As part of [setting up Geo](../geo/replication/index.md#setup-instructions),
+you will be required to follow the steps outlined below for both the primary and
+secondary nodes, but note that the `Write to "authorized keys" file` checkbox
+only needs to be unchecked on the primary node since it will be reflected
+automatically on the secondary if database replication is working.
+
## Setting up fast lookup via GitLab Shell
GitLab Shell provides a way to authorize SSH users via a fast, indexed lookup
@@ -69,7 +82,7 @@ file will still be scanned. So git SSH performance will still be slow for many
users as long as a large file exists.
You can disable any more writes to the `authorized_keys` file by unchecking
-`Write to "authorized_keys" file` in the Application Settings of your GitLab
+`Write to "authorized_keys" file` in the **Admin Area > Settings > Network > Performance optimization** of your GitLab
installation.
![Write to authorized keys setting](img/write_to_authorized_keys_setting.png)
diff --git a/doc/administration/operations/img/sidekiq-cluster.png b/doc/administration/operations/img/sidekiq-cluster.png
new file mode 100644
index 00000000000..4eb1849010e
--- /dev/null
+++ b/doc/administration/operations/img/sidekiq-cluster.png
Binary files differ
diff --git a/doc/administration/operations/index.md b/doc/administration/operations/index.md
index 32f36d68c50..df795a48169 100644
--- a/doc/administration/operations/index.md
+++ b/doc/administration/operations/index.md
@@ -11,6 +11,7 @@ Keep your GitLab instance up and running smoothly.
by GitLab to another file system or another server.
- [Sidekiq MemoryKiller](sidekiq_memory_killer.md): Configure Sidekiq MemoryKiller
to restart Sidekiq.
+- [Extra Sidekiq operations](extra_sidekiq_processes.md): Configure an extra set of Sidekiq processes to ensure certain queues always have dedicated workers, no matter the amount of jobs that need to be processed. **[STARTER ONLY]**
- [Unicorn](unicorn.md): Understand Unicorn and unicorn-worker-killer.
- Speed up SSH operations by [Authorizing SSH users via a fast,
indexed lookup to the GitLab database](fast_ssh_key_lookup.md), and/or
diff --git a/doc/administration/packages.md b/doc/administration/packages.md
new file mode 100644
index 00000000000..0d5f784b71e
--- /dev/null
+++ b/doc/administration/packages.md
@@ -0,0 +1,174 @@
+# GitLab Packages administration **[PREMIUM ONLY]**
+
+GitLab Packages allows organizations to utilize GitLab as a private repository
+for a variety of common package managers. Users are able to build and publish
+packages, which can be easily consumed as a dependency in downstream projects.
+
+The Packages feature allows GitLab to act as a repository for the following:
+
+| Software repository | Description | Available in GitLab version |
+| ------------------- | ----------- | --------------------------- |
+| [Maven Repository](../user/project/packages/maven_repository.md) | The GitLab Maven Repository enables every project in GitLab to have its own space to store [Maven](https://maven.apache.org/) packages. | 11.3+ |
+| [NPM Registry](../user/project/packages/npm_registry.md) | The GitLab NPM Registry enables every project in GitLab to have its own space to store [NPM](https://www.npmjs.com/) packages. | 11.7+ |
+
+Don't you see your package management system supported yet?
+Please consider contributing
+to GitLab. This [development documentation](../development/packages.md) will guide you through the process.
+
+## Enabling the Packages feature
+
+NOTE: **Note:**
+After the Packages feature is enabled, the repositories are available
+for all new projects by default. To enable it for existing projects, users will
+have to explicitly do so in the project's settings.
+
+To enable the Packages feature:
+
+**Omnibus GitLab installations**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
+
+ ```ruby
+ gitlab_rails['packages_enabled'] = true
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**Installations from source**
+
+1. After the installation is complete, you will have to configure the `packages`
+ section in `config/gitlab.yml`. Set to `true` to enable it:
+
+ ```yaml
+ packages:
+ enabled: true
+ ```
+1. [Restart GitLab] for the changes to take effect.
+
+## Changing the storage path
+
+By default, the packages are stored locally, but you can change the default
+local location or even use object storage.
+
+### Changing the local storage path
+
+The packages for Omnibus GitLab installations are stored under
+`/var/opt/gitlab/gitlab-rails/shared/packages/` and for source
+installations under `shared/packages/` (relative to the git homedir).
+To change the local storage path:
+
+**Omnibus GitLab installations**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
+
+ ```ruby
+ gitlab_rails['packages_storage_path'] = "/mnt/packages"
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**Installations from source**
+
+1. Edit the `packages` section in `config/gitlab.yml`:
+
+ ```yaml
+ packages:
+ enabled: true
+ storage_path: shared/packages
+ ```
+1. [Restart GitLab] for the changes to take effect.
+
+### Using object storage
+
+Instead of relying on the local storage, you can use an object storage to
+upload packages:
+
+**Omnibus GitLab installations**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following lines (uncomment where
+ necessary):
+
+ ```ruby
+ gitlab_rails['packages_enabled'] = true
+ gitlab_rails['packages_storage_path'] = "/var/opt/gitlab/gitlab-rails/shared/packages"
+ gitlab_rails['packages_object_store_enabled'] = true
+ gitlab_rails['packages_object_store_remote_directory'] = "packages" # The bucket name.
+ gitlab_rails['packages_object_store_direct_upload'] = false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false).
+ gitlab_rails['packages_object_store_background_upload'] = true # Temporary option to limit automatic upload (Default: true).
+ gitlab_rails['packages_object_store_proxy_download'] = false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage.
+ gitlab_rails['packages_object_store_connection'] = {
+ ##
+ ## If the provider is AWS S3, uncomment the following
+ ##
+ #'provider' => 'AWS',
+ #'region' => 'eu-west-1',
+ #'aws_access_key_id' => 'AWS_ACCESS_KEY_ID',
+ #'aws_secret_access_key' => 'AWS_SECRET_ACCESS_KEY',
+ ##
+ ## If the provider is other than AWS (an S3-compatible one), uncomment the following
+ ##
+ #'host' => 's3.amazonaws.com',
+ #'aws_signature_version' => 4 # For creation of signed URLs. Set to 2 if provider does not support v4.
+ #'endpoint' => 'https://s3.amazonaws.com' # Useful for S3-compliant services such as DigitalOcean Spaces.
+ #'path_style' => false # If true, use 'host/bucket_name/object' instead of 'bucket_name.host/object'.
+ }
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**Installations from source**
+
+1. Edit the `packages` section in `config/gitlab.yml` (uncomment where necessary):
+
+ ```yaml
+ packages:
+ enabled: true
+ ##
+ ## The location where build packages are stored (default: shared/packages).
+ ##
+ #storage_path: shared/packages
+ object_store:
+ enabled: false
+ remote_directory: packages # The bucket name.
+ #direct_upload: false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false).
+ #background_upload: true # Temporary option to limit automatic upload (Default: true).
+ #proxy_download: false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage.
+ connection:
+ ##
+ ## If the provider is AWS S3, uncomment the following
+ ##
+ #provider: AWS
+ #region: us-east-1
+ #aws_access_key_id: AWS_ACCESS_KEY_ID
+ #aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+ ##
+ ## If the provider is other than AWS (an S3-compatible one), uncomment the following
+ ##
+ #host: 's3.amazonaws.com' # default: s3.amazonaws.com.
+ #aws_signature_version: 4 # For creation of signed URLs. Set to 2 if provider does not support v4.
+ #endpoint: 'https://s3.amazonaws.com' # Useful for S3-compliant services such as DigitalOcean Spaces.
+ #path_style: false # If true, use 'host/bucket_name/object' instead of 'bucket_name.host/object'.
+ ```
+
+1. [Restart GitLab] for the changes to take effect.
+
+### Migrating local packages to object storage
+
+After [configuring the object storage](#using-object-storage), you may use the
+following task to migrate existing packages from the local storage to the remote one.
+The processing will be done in a background worker and requires **no downtime**.
+
+For Omnibus GitLab:
+
+```sh
+sudo gitlab-rake "gitlab:packages:migrate"
+```
+
+For installations from source:
+
+```bash
+RAILS_ENV=production sudo -u git -H bundle exec rake gitlab:packages:migrate
+```
+
+[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab"
+[restart gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab"
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index 1373bd56fe3..3a7ca517d56 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -291,6 +291,20 @@ Pages access control is disabled by default. To enable it:
1. [Reconfigure GitLab][reconfigure].
1. Users can now configure it in their [projects' settings](../../user/project/pages/introduction.md#gitlab-pages-access-control-core-only).
+### Running behind a proxy
+
+Like the rest of GitLab, Pages can be used in those environments where external
+internet connectivity is gated by a proxy. In order to use a proxy for GitLab
+pages:
+
+1. Configure in `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_pages['http_proxy'] = 'http://example:8080'
+ ```
+
+1. [Reconfigure Gitlab][reconfigure] for the changes to take effect.
+
## Activate verbose logging for daemon
Verbose logging was [introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/2533) in
@@ -376,6 +390,7 @@ Follow the steps below to configure GitLab Pages in a separate server.
gitaly['enable'] = false
alertmanager['enable'] = false
node_exporter['enable'] = false
+ gitlab_rails['auto_migrate'] = false
```
1. Run `sudo gitlab-ctl reconfigure`.
1. On `app1` apply the following changes to `/etc/gitlab/gitlab.rb`:
diff --git a/doc/administration/pseudonymizer.md b/doc/administration/pseudonymizer.md
new file mode 100644
index 00000000000..036e1d3fe61
--- /dev/null
+++ b/doc/administration/pseudonymizer.md
@@ -0,0 +1,103 @@
+# Pseudonymizer **[ULTIMATE]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/5532) in [GitLab Ultimate][ee] 11.1.
+
+As GitLab's database hosts sensitive information, using it unfiltered for analytics
+implies high security requirements. To help alleviate this constraint, the Pseudonymizer
+service is used to export GitLab's data in a pseudonymized way.
+
+CAUTION: **Warning:**
+This process is not impervious. If the source data is available, it's possible for
+a user to correlate data to the pseudonymized version.
+
+The Pseudonymizer currently uses `HMAC(SHA256)` to mutate fields that shouldn't
+be textually exported. This ensures that:
+
+- the end-user of the data source cannot infer/revert the pseudonymized fields
+- the referential integrity is maintained
+
+## Configuration
+
+To configure the pseudonymizer, you need to:
+
+- Provide a manifest file that describes which fields should be included or
+ pseudonymized ([example `manifest.yml` file](https://gitlab.com/gitlab-org/gitlab-ee/tree/master/config/pseudonymizer.yml)).
+ A default manifest is provided with the GitLab installation. Using a relative file path will be resolved from the Rails root.
+ Alternatively, you can use an absolute file path.
+- Use an object storage and specify the connection parameters in the `pseudonymizer.upload.connection` configuration option.
+
+**For Omnibus installations:**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following lines by replacing with
+ the values you want:
+
+ ```ruby
+ gitlab_rails['pseudonymizer_manifest'] = 'config/pseudonymizer.yml'
+ gitlab_rails['pseudonymizer_upload_remote_directory'] = 'gitlab-elt' # bucket name
+ gitlab_rails['pseudonymizer_upload_connection'] = {
+ 'provider' => 'AWS',
+ 'region' => 'eu-central-1',
+ 'aws_access_key_id' => 'AWS_ACCESS_KEY_ID',
+ 'aws_secret_access_key' => 'AWS_SECRET_ACCESS_KEY'
+ }
+ ```
+
+ NOTE: **Note:**
+ If you are using AWS IAM profiles, be sure to omit the AWS access key and secret access key/value pairs.
+
+ ```ruby
+ gitlab_rails['pseudonymizer_upload_connection'] = {
+ 'provider' => 'AWS',
+ 'region' => 'eu-central-1',
+ 'use_iam_profile' => true
+ }
+ ```
+
+1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure)
+ for the changes to take effect.
+
+---
+
+**For installations from source:**
+
+1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following
+ lines:
+
+ ```yaml
+ pseudonymizer:
+ manifest: config/pseudonymizer.yml
+ upload:
+ remote_directory: 'gitlab-elt' # bucket name
+ connection:
+ provider: AWS
+ aws_access_key_id: AWS_ACCESS_KEY_ID
+ aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+ region: eu-central-1
+ ```
+
+1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source)
+ for the changes to take effect.
+
+## Usage
+
+You can optionally run the pseudonymizer using the following environment variables:
+
+- `PSEUDONYMIZER_OUTPUT_DIR` - where to store the output CSV files (defaults to `/tmp`)
+- `PSEUDONYMIZER_BATCH` - the batch size when querying the DB (defaults to `100000`)
+
+```bash
+## Omnibus
+sudo gitlab-rake gitlab:db:pseudonymizer
+
+## Source
+sudo -u git -H bundle exec rake gitlab:db:pseudonymizer RAILS_ENV=production
+```
+
+This will produce some CSV files that might be very large, so make sure the
+`PSEUDONYMIZER_OUTPUT_DIR` has sufficient space. As a rule of thumb, at least
+10% of the database size is recommended.
+
+After the pseudonymizer has run, the output CSV files should be uploaded to the
+configured object storage and deleted from the local disk.
+
+[ee]: https://about.gitlab.com/pricing/
diff --git a/doc/administration/raketasks/geo.md b/doc/administration/raketasks/geo.md
new file mode 100644
index 00000000000..9f3b31442f3
--- /dev/null
+++ b/doc/administration/raketasks/geo.md
@@ -0,0 +1,57 @@
+# Geo Rake Tasks **[PREMIUM ONLY]**
+
+## Git housekeeping
+
+There are few tasks you can run to schedule a git housekeeping to start at the
+next repository sync in a **Secondary node**:
+
+### Incremental Repack
+
+This is equivalent of running `git repack -d` on a _bare_ repository.
+
+**Omnibus Installation**
+
+```
+sudo gitlab-rake geo:git:housekeeping:incremental_repack
+```
+
+**Source Installation**
+
+```bash
+sudo -u git -H bundle exec rake geo:git:housekeeping:incremental_repack RAILS_ENV=production
+```
+
+### Full Repack
+
+This is equivalent of running `git repack -d -A --pack-kept-objects` on a
+_bare_ repository which will optionally, write a reachability bitmap index
+when this is enabled in GitLab.
+
+**Omnibus Installation**
+
+```
+sudo gitlab-rake geo:git:housekeeping:full_repack
+```
+
+**Source Installation**
+
+```bash
+sudo -u git -H bundle exec rake geo:git:housekeeping:full_repack RAILS_ENV=production
+```
+
+### GC
+
+This is equivalent of running `git gc` on a _bare_ repository, optionally writing
+a reachability bitmap index when this is enabled in GitLab.
+
+**Omnibus Installation**
+
+```
+sudo gitlab-rake geo:git:housekeeping:gc
+```
+
+**Source Installation**
+
+```bash
+sudo -u git -H bundle exec rake geo:git:housekeeping:gc RAILS_ENV=production
+```
diff --git a/doc/administration/raketasks/maintenance.md b/doc/administration/raketasks/maintenance.md
index b295b7d5dc4..0b4c1ae15d6 100644
--- a/doc/administration/raketasks/maintenance.md
+++ b/doc/administration/raketasks/maintenance.md
@@ -205,25 +205,6 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:track_deployment RAILS_ENV=production
```
-## Create or repair repository hooks symlink
-
-If the GitLab shell hooks directory location changes or another circumstance
-leads to the hooks symlink becoming missing or invalid, run this Rake task
-to create or repair the symlinks.
-
-**Omnibus Installation**
-
-```
-sudo gitlab-rake gitlab:shell:create_hooks
-```
-
-**Source Installation**
-
-```
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:shell:create_hooks RAILS_ENV=production
-```
-
## Check TCP connectivity to a remote site
Sometimes you need to know if your GitLab installation can connect to a TCP
diff --git a/doc/administration/raketasks/project_import_export.md b/doc/administration/raketasks/project_import_export.md
index f43bba0a7a7..6ca23aabdec 100644
--- a/doc/administration/raketasks/project_import_export.md
+++ b/doc/administration/raketasks/project_import_export.md
@@ -32,5 +32,4 @@ bundle exec rake gitlab:import_export:data RAILS_ENV=production
```
[ce-3050]: https://gitlab.com/gitlab-org/gitlab-ce/issues/3050
-[feature-flags]: https://docs.gitlab.com/ee/api/features.html
[tmp]: ../../development/shared_files.md
diff --git a/doc/administration/raketasks/storage.md b/doc/administration/raketasks/storage.md
index c39fef907db..42a1a1c2e60 100644
--- a/doc/administration/raketasks/storage.md
+++ b/doc/administration/raketasks/storage.md
@@ -43,6 +43,9 @@ If you find it necessary, you can run this migration script again to schedule mi
Any error or warning will be logged in Sidekiq's log file.
+NOTE: **Note:**
+If Geo is enabled, each project that is successfully migrated generates an event to replicate the changes on any **secondary** nodes.
+
You only need the `gitlab:storage:migrate_to_hashed` rake task to migrate your repositories, but we have additional
commands below that helps you inspect projects and attachments in both legacy and hashed storage.
diff --git a/doc/administration/repository_storage_paths.md b/doc/administration/repository_storage_paths.md
index 1689b0a57d6..4aafc06cfdc 100644
--- a/doc/administration/repository_storage_paths.md
+++ b/doc/administration/repository_storage_paths.md
@@ -62,7 +62,7 @@ files and add the full paths of the alternative repository storage paths. In
the example below, we add two more mountpoints that are named `nfs` and `cephfs`
respectively.
-NOTE: **Note:** This example uses NFS and CephFS. We do not recommend using EFS for storage as it may impact GitLab's performance. See the [relevant documentation](./high_availability/nfs.md#avoid-using-awss-elastic-file-system-efs) for more details.
+NOTE: **Note:** This example uses NFS and CephFS. We do not recommend using EFS for storage as it may impact GitLab's performance. See the [relevant documentation](high_availability/nfs.md#avoid-using-awss-elastic-file-system-efs) for more details.
**For installations from source**
diff --git a/doc/administration/repository_storage_types.md b/doc/administration/repository_storage_types.md
index 88bf55296b2..38842693d73 100644
--- a/doc/administration/repository_storage_types.md
+++ b/doc/administration/repository_storage_types.md
@@ -47,15 +47,15 @@ Any change in the URL will need to be reflected on disk (when groups / users or
projects are renamed). This can add a lot of load in big installations,
especially if using any type of network based filesystem.
-For GitLab Geo in particular: Geo does work with legacy storage, but in some
+CAUTION: **Caution:**
+For Geo in particular: Geo does work with legacy storage, but in some
edge cases due to race conditions it can lead to errors when a project is
renamed multiple times in short succession, or a project is deleted and
recreated under the same name very quickly. We expect these race events to be
rare, and we have not observed a race condition side-effect happening yet.
-
This pattern also exists in other objects stored in GitLab, like issue
Attachments, GitLab Pages artifacts, Docker Containers for the integrated
-Registry, etc.
+Registry, etc. Hashed storage is a requirement for Geo.
## Hashed Storage
@@ -106,6 +106,11 @@ enabled for individual projects by executing
be on hashed storage, should not be a fork itself, and hashed storage should be
enabled for all new projects.
+DANGER: **Danger:**
+Do not run `git prune` or `git gc` in pool repositories! This can
+cause data loss in "real" repositories that depend on the pool in
+question.
+
### How to migrate to Hashed Storage
To start a migration, enable Hashed Storage for new projects:
diff --git a/doc/analytics/README.md b/doc/analytics/README.md
new file mode 100644
index 00000000000..bfb15f6c4f3
--- /dev/null
+++ b/doc/analytics/README.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../user/group/index.md#user-contribution-analysis-starter'
+---
+
+This document was moved to [another location](../user/group/index.md#user-contribution-analysis-starter)
diff --git a/doc/analytics/contribution_analytics.md b/doc/analytics/contribution_analytics.md
new file mode 100644
index 00000000000..e36f55071a4
--- /dev/null
+++ b/doc/analytics/contribution_analytics.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../user/group/contribution_analytics/index.md'
+---
+
+This document was moved to [another location](../user/group/contribution_analytics/index.md).
diff --git a/doc/api/README.md b/doc/api/README.md
index 7ec7955c596..3a1064b787e 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -21,72 +21,83 @@ See also:
The following API resources are available in the project context:
-| Resource | Available endpoints |
-|:------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| [Access requests](access_requests.md) | `/projects/:id/access_requests` (also available for groups) |
-| [Award emoji](award_emoji.md) | `/projects/:id/issues/.../award_emoji`, `/projects/:id/merge_requests/.../award_emoji`, `/projects/:id/snippets/.../award_emoji` |
-| [Branches](branches.md) | `/projects/:id/repository/branches/`, `/projects/:id/repository/merged_branches` |
-| [Commits](commits.md) | `/projects/:id/repository/commits`, `/projects/:id/statuses` |
-| [Container Registry](container_registry.md) | `/projects/:id/registry/repositories` |
-| [Custom attributes](custom_attributes.md) | `/projects/:id/custom_attributes` (also available for groups and users) |
-| [Deploy keys](deploy_keys.md) | `/projects/:id/deploy_keys` (also available standalone) |
-| [Deployments](deployments.md) | `/projects/:id/deployments` |
-| [Discussions](discussions.md) (threaded comments) | `/projects/:id/issues/.../discussions`, `/projects/:id/snippets/.../discussions`, `/projects/:id/merge_requests/.../discussions`, `/projects/:id/commits/.../discussions` |
-| [Environments](environments.md) | `/projects/:id/environments` |
-| [Events](events.md) | `/projects/:id/events` (also available for users and standalone) |
-| [Issues](issues.md) | `/projects/:id/issues` (also available for groups and standalone) |
-| [Issue boards](boards.md) | `/projects/:id/boards` |
-| [Jobs](jobs.md) | `/projects/:id/jobs`, `/projects/:id/pipelines/.../jobs` |
-| [Labels](labels.md) | `/projects/:id/labels` |
-| [Members](members.md) | `/projects/:id/members` (also available for groups) |
-| [Merge requests](merge_requests.md) | `/projects/:id/merge_requests` (also available for groups and standalone) |
-| [Notes](notes.md) (comments) | `/projects/:id/issues/.../notes`, `/projects/:id/snippets/.../notes`, `/projects/:id/merge_requests/.../notes` |
-| [Notification settings](notification_settings.md) | `/projects/:id/notification_settings` (also available for groups and standalone) |
-| [Pages domains](pages_domains.md) | `/projects/:id/pages` (also available standalone) |
-| [Pipelines](pipelines.md) | `/projects/:id/pipelines` |
-| [Pipeline schedules](pipeline_schedules.md) | `/projects/:id/pipeline_schedules` |
-| [Pipeline triggers](pipeline_triggers.md) | `/projects/:id/triggers` |
-| [Projects](projects.md) including setting Webhooks | `/projects`, `/projects/:id/hooks` (also available for users) |
-| [Project badges](project_badges.md) | `/projects/:id/badges` |
-| [Project clusters](project_clusters.md) | `/projects/:id/clusters` |
-| [Project-level variables](project_level_variables.md) | `/projects/:id/variables` |
-| [Project import/export](project_import_export.md) | `/projects/:id/export`, `/projects/import`, `/projects/:id/import` |
-| [Project milestones](milestones.md) | `/projects/:id/milestones` |
-| [Project snippets](project_snippets.md) | `/projects/:id/snippets` |
-| [Project templates](project_templates.md) | `/projects/:id/templates` |
-| [Protected branches](protected_branches.md) | `/projects/:id/protected_branches` |
-| [Protected tags](protected_tags.md) | `/projects/:id/protected_tags` |
-| [Releases](releases/index.md) | `/projects/:id/releases` |
-| [Release links](releases/links.md) | `/projects/:id/releases/.../assets/links` |
-| [Repositories](repositories.md) | `/projects/:id/repository` |
-| [Repository files](repository_files.md) | `/projects/:id/repository/files` |
-| [Repository submodules](repository_submodules.md) | `/projects/:id/repository/submodules` |
-| [Resource label events](resource_label_events.md) | `/projects/:id/issues/.../resource_label_events`, `/projects/:id/merge_requests/.../resource_label_events` |
-| [Runners](runners.md) | `/projects/:id/runners` (also available standalone) |
-| [Search](search.md) | `/projects/:id/search` (also available for groups and standalone) |
-| [Services](services.md) | `/projects/:id/services` |
-| [Tags](tags.md) | `/projects/:id/repository/tags` |
-| [Wikis](wikis.md) | `/projects/:id/wikis` |
+| Resource | Available endpoints |
+|:--------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [Access requests](access_requests.md) | `/projects/:id/access_requests` (also available for groups) |
+| [Award emoji](award_emoji.md) | `/projects/:id/issues/.../award_emoji`, `/projects/:id/merge_requests/.../award_emoji`, `/projects/:id/snippets/.../award_emoji` |
+| [Branches](branches.md) | `/projects/:id/repository/branches/`, `/projects/:id/repository/merged_branches` |
+| [Commits](commits.md) | `/projects/:id/repository/commits`, `/projects/:id/statuses` |
+| [Container Registry](container_registry.md) | `/projects/:id/registry/repositories` |
+| [Custom attributes](custom_attributes.md) | `/projects/:id/custom_attributes` (also available for groups and users) |
+| [Deploy keys](deploy_keys.md) | `/projects/:id/deploy_keys` (also available standalone) |
+| [Deployments](deployments.md) | `/projects/:id/deployments` |
+| [Discussions](discussions.md) (threaded comments) | `/projects/:id/issues/.../discussions`, `/projects/:id/snippets/.../discussions`, `/projects/:id/merge_requests/.../discussions`, `/projects/:id/commits/.../discussions` (also available for groups) |
+| [Environments](environments.md) | `/projects/:id/environments` |
+| [Events](events.md) | `/projects/:id/events` (also available for users and standalone) |
+| [Issues](issues.md) | `/projects/:id/issues` (also available for groups and standalone) |
+| [Issue boards](boards.md) | `/projects/:id/boards` |
+| [Issue links](issue_links.md) **[STARTER]** | `/projects/:id/issues/.../links` |
+| [Jobs](jobs.md) | `/projects/:id/jobs`, `/projects/:id/pipelines/.../jobs` |
+| [Labels](labels.md) | `/projects/:id/labels` |
+| [Managed licenses](managed_licenses.md) **[ULTIMATE]** | `/projects/:id/managed_licenses` |
+| [Members](members.md) | `/projects/:id/members` (also available for groups) |
+| [Merge request approvals](merge_request_approvals.md) **[STARTER]** | `/projects/:id/approvals`, `/projects/:id/merge_requests/.../approvals` |
+| [Merge requests](merge_requests.md) | `/projects/:id/merge_requests` (also available for groups and standalone) |
+| [Notes](notes.md) (comments) | `/projects/:id/issues/.../notes`, `/projects/:id/snippets/.../notes`, `/projects/:id/merge_requests/.../notes` (also available for groups) |
+| [Notification settings](notification_settings.md) | `/projects/:id/notification_settings` (also available for groups and standalone) |
+| [Packages](packages.md) **[PREMIUM]** | `/projects/:id/packages` |
+| [Pages domains](pages_domains.md) | `/projects/:id/pages` (also available standalone) |
+| [Pipelines](pipelines.md) | `/projects/:id/pipelines` |
+| [Pipeline schedules](pipeline_schedules.md) | `/projects/:id/pipeline_schedules` |
+| [Pipeline triggers](pipeline_triggers.md) | `/projects/:id/triggers` |
+| [Projects](projects.md) including setting Webhooks | `/projects`, `/projects/:id/hooks` (also available for users) |
+| [Project badges](project_badges.md) | `/projects/:id/badges` |
+| [Project clusters](project_clusters.md) | `/projects/:id/clusters` |
+| [Project-level variables](project_level_variables.md) | `/projects/:id/variables` |
+| [Project import/export](project_import_export.md) | `/projects/:id/export`, `/projects/import`, `/projects/:id/import` |
+| [Project milestones](milestones.md) | `/projects/:id/milestones` |
+| [Project snippets](project_snippets.md) | `/projects/:id/snippets` |
+| [Project templates](project_templates.md) | `/projects/:id/templates` |
+| [Protected branches](protected_branches.md) | `/projects/:id/protected_branches` |
+| [Protected tags](protected_tags.md) | `/projects/:id/protected_tags` |
+| [Releases](releases/index.md) | `/projects/:id/releases` |
+| [Release links](releases/links.md) | `/projects/:id/releases/.../assets/links` |
+| [Repositories](repositories.md) | `/projects/:id/repository` |
+| [Repository files](repository_files.md) | `/projects/:id/repository/files` |
+| [Repository submodules](repository_submodules.md) | `/projects/:id/repository/submodules` |
+| [Resource label events](resource_label_events.md) | `/projects/:id/issues/.../resource_label_events`, `/projects/:id/merge_requests/.../resource_label_events` (also available for groups) |
+| [Runners](runners.md) | `/projects/:id/runners` (also available standalone) |
+| [Search](search.md) | `/projects/:id/search` (also available for groups and standalone) |
+| [Services](services.md) | `/projects/:id/services` |
+| [Tags](tags.md) | `/projects/:id/repository/tags` |
+| [Vulnerabilities](vulnerabilities.md) **[ULTIMATE]** | `/projects/:id/vulnerabilities` (also available for groups) |
+| [Wikis](wikis.md) | `/projects/:id/wikis` |
### Group resources
The following API resources are available in the group context:
-| Resource | Available endpoints |
-|:--------------------------------------------------|:---------------------------------------------------------------------------------|
-| [Access requests](access_requests.md) | `/groups/:id/access_requests/` (also available for projects) |
-| [Custom attributes](custom_attributes.md) | `/groups/:id/custom_attributes` (also available for projects and users) |
-| [Groups](groups.md) | `/groups`, `/groups/.../subgroups` |
-| [Group badges](group_badges.md) | `/groups/:id/badges` |
-| [Group issue boards](group_boards.md) | `/groups/:id/boards` |
-| [Group labels](group_labels.md) | `/groups/:id/labels` |
-| [Group-level variables](group_level_variables.md) | `/groups/:id/variables` |
-| [Group milestones](group_milestones.md) | `/groups/:id/milestones` |
-| [Issues](issues.md) | `/groups/:id/issues` (also available for projects and standalone) |
-| [Members](members.md) | `/groups/:id/members` (also available for projects) |
-| [Merge requests](merge_requests.md) | `/groups/:id/merge_requests` (also available for projects and standalone) |
-| [Notification settings](notification_settings.md) | `/groups/:id/notification_settings` (also available for projects and standalone) |
-| [Search](search.md) | `/groups/:id/search` (also available for projects and standalone) |
+| Resource | Available endpoints |
+|:-----------------------------------------------------------------|:---------------------------------------------------------------------------------|
+| [Access requests](access_requests.md) | `/groups/:id/access_requests/` (also available for projects) |
+| [Custom attributes](custom_attributes.md) | `/groups/:id/custom_attributes` (also available for projects and users) |
+| [Discussions](discussions.md) (threaded comments) **[ULTIMATE]** | `/groups/:id/epics/.../discussions` (also available for projects) |
+| [Epic issues](epic_issues.md) **[ULTIMATE]** | `/groups/:id/epics/.../issues` |
+| [Epic links](epic_links.md) **[ULTIMATE]** | `/groups/:id/epics/.../epics` |
+| [Epics](epics.md) **[ULTIMATE]** | `/groups/:id/epics` |
+| [Groups](groups.md) | `/groups`, `/groups/.../subgroups` |
+| [Group badges](group_badges.md) | `/groups/:id/badges` |
+| [Group issue boards](group_boards.md) | `/groups/:id/boards` |
+| [Group labels](group_labels.md) | `/groups/:id/labels` |
+| [Group-level variables](group_level_variables.md) | `/groups/:id/variables` |
+| [Group milestones](group_milestones.md) | `/groups/:id/milestones` |
+| [Issues](issues.md) | `/groups/:id/issues` (also available for projects and standalone) |
+| [Members](members.md) | `/groups/:id/members` (also available for projects) |
+| [Merge requests](merge_requests.md) | `/groups/:id/merge_requests` (also available for projects and standalone) |
+| [Notes](notes.md) (comments) | `/groups/:id/epics/.../notes` (also available for projects) |
+| [Notification settings](notification_settings.md) | `/groups/:id/notification_settings` (also available for projects and standalone) |
+| [Resource label events](resource_label_events.md) | `/groups/:id/epics/.../resource_label_events` (also available for projects) |
+| [Search](search.md) | `/groups/:id/search` (also available for projects and standalone) |
### Standalone resources
@@ -102,9 +113,11 @@ The following API resources are available outside of project and group contexts
| [Deploy keys](deploy_keys.md) | `/deploy_keys` (also available for projects) |
| [Events](events.md) | `/events`, `/users/:id/events` (also available for projects) |
| [Feature flags](features.md) | `/features` |
+| [Geo Nodes](geo_nodes.md) **[PREMIUM ONLY]** | `/geo_nodes` |
| [Import repository from GitHub](import.md) | `/import/github` |
| [Issues](issues.md) | `/issues` (also available for groups and projects) |
| [Keys](keys.md) | `/keys` |
+| [License](license.md) **[CORE ONLY]** | `/license` |
| [Markdown](markdown.md) | `/markdown` |
| [Merge requests](merge_requests.md) | `/merge_requests` (also available for groups and projects) |
| [Namespaces](namespaces.md) | `/namespaces` |
@@ -131,6 +144,11 @@ Endpoints are available for:
- [GitLab CI YAML templates](templates/gitlab_ci_ymls.md).
- [Open source license templates](templates/licenses.md).
+## SCIM **[SILVER ONLY]**
+
+[GitLab.com Silver and above](https://about.gitlab.com/pricing/) provides an [SCIM API](scim.md) that implements [the RFC7644 protocol](https://tools.ietf.org/html/rfc7644) and provides
+the `/Users` endpoint. The base URL is: `/api/scim/v2/groups/:group_path/Users/`.
+
## Road to GraphQL
Going forward, we will start on moving to
diff --git a/doc/api/boards.md b/doc/api/boards.md
index 28c73db6b98..a96206f5df3 100644
--- a/doc/api/boards.md
+++ b/doc/api/boards.md
@@ -141,6 +141,173 @@ Example response:
}
```
+## Create a board **[STARTER]**
+
+Creates a board.
+
+```
+POST /projects/:id/boards
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `name` | string | yes | The name of the new board |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/boards?name=newboard
+```
+
+Example response:
+
+```json
+ {
+ "id": 1,
+ "project": {
+ "id": 5,
+ "name": "Diaspora Project Site",
+ "name_with_namespace": "Diaspora / Diaspora Project Site",
+ "path": "diaspora-project-site",
+ "path_with_namespace": "diaspora/diaspora-project-site",
+ "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
+ "web_url": "http://example.com/diaspora/diaspora-project-site"
+ },
+ "name": "newboard",
+ "milestone": {
+ "id": 12
+ "title": "10.0"
+ },
+ "lists" : [
+ {
+ "id" : 1,
+ "label" : {
+ "name" : "Testing",
+ "color" : "#F0AD4E",
+ "description" : null
+ },
+ "position" : 1
+ },
+ {
+ "id" : 2,
+ "label" : {
+ "name" : "Ready",
+ "color" : "#FF0000",
+ "description" : null
+ },
+ "position" : 2
+ },
+ {
+ "id" : 3,
+ "label" : {
+ "name" : "Production",
+ "color" : "#FF5F00",
+ "description" : null
+ },
+ "position" : 3
+ }
+ ]
+ }
+```
+
+## Update a board **[STARTER]**
+
+> [Introduced][ee-5954] in [GitLab Starter](https://about.gitlab.com/pricing/) 11.1.
+
+Updates a board.
+
+```
+PUT /projects/:id/boards/:board_id
+```
+
+| Attribute | Type | Required | Description |
+| ------------------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `board_id` | integer | yes | The ID of a board |
+| `name` | string | no | The new name of the board |
+| `assignee_id` | integer | no | The assignee the board should be scoped to |
+| `milestone_id` | integer | no | The milestone the board should be scoped to |
+| `labels` | string | no | Comma-separated list of label names which the board should be scoped to |
+| `weight` | integer | no | The weight range from 0 to 9, to which the board should be scoped to |
+
+
+```bash
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/boards/1?name=new_name&milestone_id=43&assignee_id=1&labels=Doing&weight=4
+```
+
+Example response:
+
+```json
+ {
+ "id": 1,
+ "project": {
+ "id": 5,
+ "name": "Diaspora Project Site",
+ "name_with_namespace": "Diaspora / Diaspora Project Site",
+ "path": "diaspora-project-site",
+ "path_with_namespace": "diaspora/diaspora-project-site",
+ "created_at": "2018-07-03T05:48:49.982Z",
+ "default_branch": null,
+ "tag_list": [],
+ "ssh_url_to_repo": "ssh://user@example.com/diaspora/diaspora-project-site.git",
+ "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git",
+ "web_url": "http://example.com/diaspora/diaspora-project-site",
+ "readme_url": null,
+ "avatar_url": null,
+ "star_count": 0,
+ "forks_count": 0,
+ "last_activity_at": "2018-07-03T05:48:49.982Z"
+ },
+ "lists": [],
+ "name": "new_name",
+ "group": null,
+ "milestone": {
+ "id": 43,
+ "iid": 1,
+ "project_id": 15,
+ "title": "Milestone 1",
+ "description": "Milestone 1 desc",
+ "state": "active",
+ "created_at": "2018-07-03T06:36:42.618Z",
+ "updated_at": "2018-07-03T06:36:42.618Z",
+ "due_date": null,
+ "start_date": null,
+ "web_url": "http://example.com/root/board1/milestones/1"
+ },
+ "assignee": {
+ "id": 1,
+ "name": "Administrator",
+ "username": "root",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "web_url": "http://example.com/root"
+ },
+ "labels": [{
+ "id": 10,
+ "name": "Doing",
+ "color": "#5CB85C",
+ "description": null
+ }],
+ "weight": 4
+ }
+```
+
+## Delete a board **[STARTER]**
+
+Deletes a board.
+
+```
+DELETE /projects/:id/boards/:board_id
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `board_id` | integer | yes | The ID of a board |
+
+```bash
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/boards/1
+```
+
## List board lists
Get a list of the board's lists.
@@ -237,7 +404,15 @@ POST /projects/:id/boards/:board_id/lists
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `board_id` | integer | yes | The ID of a board |
-| `label_id` | integer | yes | The ID of a label |
+| `label_id` | integer | no | The ID of a label |
+| `assignee_id` **[PREMIUM]** | integer | no | The ID of a user |
+| `milestone_id` **[PREMIUM]** | integer | no | The ID of a milestone |
+
+NOTE: **Note**:
+Label, assignee and milestone arguments are mutually exclusive,
+that is, only one of them are accepted in a request.
+Check the [Issue Board docs](../user/project/issue_board.md#summary-of-features-per-tier)
+for more information regarding the required license for each list type.
```bash
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/boards/1/lists?label_id=5
@@ -307,3 +482,5 @@ DELETE /projects/:id/boards/:board_id/lists/:list_id
```bash
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/boards/1/lists/1
```
+
+[ee-5954]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/5954
diff --git a/doc/api/commits.md b/doc/api/commits.md
index 92f53c7b5e6..25015fad9e3 100644
--- a/doc/api/commits.md
+++ b/doc/api/commits.md
@@ -75,6 +75,7 @@ POST /projects/:id/repository/commits
| `branch` | string | yes | Name of the branch to commit into. To create a new branch, also provide `start_branch`. |
| `commit_message` | string | yes | Commit message |
| `start_branch` | string | no | Name of the branch to start the new commit from |
+| `start_project` | integer/string | no | The project ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) to start the commit from. Defaults to the value of `id`. |
| `actions[]` | array | yes | An array of action hashes to commit as a batch. See the next table for what attributes it can take. |
| `author_email` | string | no | Specify the commit author's email address |
| `author_name` | string | no | Specify the commit author's name |
diff --git a/doc/api/discussions.md b/doc/api/discussions.md
index 3f575f432d0..9defef4fd53 100644
--- a/doc/api/discussions.md
+++ b/doc/api/discussions.md
@@ -1,6 +1,14 @@
# Discussions API
-Discussions are set of related notes on snippets, issues, merge requests or commits.
+Discussions are a set of related notes on:
+
+- Snippets
+- Issues
+- Epics **[ULTIMATE]**
+- Merge requests
+- Commits
+
+This includes system notes, which are notes about changes to the object (for example, when a milestone changes, there will be a corresponding system note). Label notes are not part of this API, but recorded as separate events in [resource label events](resource_label_events.md).
## Discussions pagination
@@ -151,7 +159,8 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab
### Add note to existing issue discussion
-Adds a new note to the discussion.
+Adds a new note to the discussion. This can also
+[create a discussion from a single comment](../user/discussions/#start-a-discussion-by-replying-to-a-standard-comment).
```
POST /projects/:id/issues/:issue_iid/discussions/:discussion_id/notes
@@ -421,6 +430,214 @@ Parameters:
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/636
```
+## Epics **[ULTIMATE]**
+
+### List group epic discussions
+
+Gets a list of all discussions for a single epic.
+
+```
+GET /groups/:id/epics/:epic_id/discussions
+```
+
+| Attribute | Type | Required | Description |
+| ------------------- | ---------------- | ---------- | ------------ |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
+| `epic_id` | integer | yes | The ID of an epic |
+
+```json
+[
+ {
+ "id": "6a9c1750b37d513a43987b574953fceb50b03ce7",
+ "individual_note": false,
+ "notes": [
+ {
+ "id": 1126,
+ "type": "DiscussionNote",
+ "body": "discussion text",
+ "attachment": null,
+ "author": {
+ "id": 1,
+ "name": "root",
+ "username": "root",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon",
+ "web_url": "http://localhost:3000/root"
+ },
+ "created_at": "2018-03-03T21:54:39.668Z",
+ "updated_at": "2018-03-03T21:54:39.668Z",
+ "system": false,
+ "noteable_id": 3,
+ "noteable_type": "Epic",
+ "noteable_id": null,
+ "resolvable": false
+ },
+ {
+ "id": 1129,
+ "type": "DiscussionNote",
+ "body": "reply to the discussion",
+ "attachment": null,
+ "author": {
+ "id": 1,
+ "name": "root",
+ "username": "root",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon",
+ "web_url": "http://localhost:3000/root"
+ },
+ "created_at": "2018-03-04T13:38:02.127Z",
+ "updated_at": "2018-03-04T13:38:02.127Z",
+ "system": false,
+ "noteable_id": 3,
+ "noteable_type": "Epic",
+ "noteable_id": null,
+ "resolvable": false
+ }
+ ]
+ },
+ {
+ "id": "87805b7c09016a7058e91bdbe7b29d1f284a39e6",
+ "individual_note": true,
+ "notes": [
+ {
+ "id": 1128,
+ "type": null,
+ "body": "a single comment",
+ "attachment": null,
+ "author": {
+ "id": 1,
+ "name": "root",
+ "username": "root",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/00afb8fb6ab07c3ee3e9c1f38777e2f4?s=80&d=identicon",
+ "web_url": "http://localhost:3000/root"
+ },
+ "created_at": "2018-03-04T09:17:22.520Z",
+ "updated_at": "2018-03-04T09:17:22.520Z",
+ "system": false,
+ "noteable_id": 3,
+ "noteable_type": "Epic",
+ "noteable_id": null,
+ "resolvable": false
+ }
+ ]
+ }
+]
+```
+
+```bash
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/epics/11/discussions
+```
+
+### Get single epic discussion
+
+Returns a single discussion for a specific group epic
+
+```
+GET /groups/:id/epics/:epic_id/discussions/:discussion_id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
+| `epic_id` | integer | yes | The ID of an epic |
+| `discussion_id` | integer | yes | The ID of a discussion |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/epics/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7
+```
+
+### Create new epic discussion
+
+Creates a new discussion to a single group epic. This is similar to creating
+a note but but another comments (replies) can be added to it later.
+
+```
+POST /groups/:id/epics/:epic_id/discussions
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
+| `epic_id` | integer | yes | The ID of an epic |
+| `body` | string | yes | The content of a discussion |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/epics/11/discussions?body=comment
+```
+
+### Add note to existing epic discussion
+
+Adds a new note to the discussion. This can also
+[create a discussion from a single comment](../user/discussions/#start-a-discussion-by-replying-to-a-standard-comment).
+
+```
+POST /groups/:id/epics/:epic_id/discussions/:discussion_id/notes
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
+| `epic_id` | integer | yes | The ID of an epic |
+| `discussion_id` | integer | yes | The ID of a discussion |
+| `note_id` | integer | yes | The ID of a discussion note |
+| `body` | string | yes | The content of a discussion |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/epics/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment
+```
+
+### Modify existing epic discussion note
+
+Modify existing discussion note of an epic.
+
+```
+PUT /groups/:id/epics/:epic_id/discussions/:discussion_id/notes/:note_id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
+| `epic_id` | integer | yes | The ID of an epic |
+| `discussion_id` | integer | yes | The ID of a discussion |
+| `note_id` | integer | yes | The ID of a discussion note |
+| `body` | string | yes | The content of a discussion |
+
+```bash
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/epics/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes/1108?body=comment
+```
+
+### Delete an epic discussion note
+
+Deletes an existing discussion note of an epic.
+
+```
+DELETE /groups/:id/epics/:epic_id/discussions/:discussion_id/notes/:note_id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
+| `epic_id` | integer | yes | The ID of an epic |
+| `discussion_id` | integer | yes | The ID of a discussion |
+| `note_id` | integer | yes | The ID of a discussion note |
+
+```bash
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/epics/11/discussions/636
+```
+
## Merge requests
### List project merge request discussions
@@ -650,7 +867,8 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.
### Add note to existing merge request discussion
-Adds a new note to the discussion.
+Adds a new note to the discussion. This can also
+[create a discussion from a single comment](../user/discussions/#start-a-discussion-by-replying-to-a-standard-comment).
```
POST /projects/:id/merge_requests/:merge_request_iid/discussions/:discussion_id/notes
diff --git a/doc/api/epic_issues.md b/doc/api/epic_issues.md
new file mode 100644
index 00000000000..ec59ea7068e
--- /dev/null
+++ b/doc/api/epic_issues.md
@@ -0,0 +1,413 @@
+# Epic Issues API **[ULTIMATE]**
+
+Every API call to epic_issues must be authenticated.
+
+If a user is not a member of a group and the group is private, a `GET` request on that group will result to a `404` status code.
+
+Epics are available only in Ultimate. If epics feature is not available a `403` status code will be returned.
+
+## List issues for an epic
+
+Gets all issues that are assigned to an epic and the authenticated user has access to.
+
+```
+GET /groups/:id/epics/:epic_iid/issues
+```
+
+| Attribute | Type | Required | Description |
+| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `epic_iid` | integer/string | yes | The internal ID of the epic. |
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5/issues/
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 76,
+ "iid": 6,
+ "project_id": 8,
+ "title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.",
+ "description" : "Ratione dolores corrupti mollitia soluta quia.",
+ "state": "opened",
+ "created_at": "2017-11-15T13:39:24.670Z",
+ "updated_at": "2018-01-04T10:49:19.506Z",
+ "closed_at": null,
+ "labels": [],
+ "milestone": {
+ "id": 38,
+ "iid": 3,
+ "project_id": 8,
+ "title": "v2.0",
+ "description": "In tempore culpa inventore quo accusantium.",
+ "state": "closed",
+ "created_at": "2017-11-15T13:39:13.825Z",
+ "updated_at": "2017-11-15T13:39:13.825Z",
+ "due_date": null,
+ "start_date": null
+ },
+ "assignees": [{
+ "id": 7,
+ "name": "Pamella Huel",
+ "username": "arnita",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon",
+ "web_url": "http://localhost:3001/arnita"
+ }],
+ "assignee": {
+ "id": 7,
+ "name": "Pamella Huel",
+ "username": "arnita",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon",
+ "web_url": "http://localhost:3001/arnita"
+ },
+ "author": {
+ "id": 13,
+ "name": "Michell Johns",
+ "username": "chris_hahn",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/30e3b2122ccd6b8e45e8e14a3ffb58fc?s=80&d=identicon",
+ "web_url": "http://localhost:3001/chris_hahn"
+ },
+ "user_notes_count": 8,
+ "upvotes": 0,
+ "downvotes": 0,
+ "due_date": null,
+ "confidential": false,
+ "weight": null,
+ "discussion_locked": null,
+ "web_url": "http://localhost:3001/h5bp/html5-boilerplate/issues/6",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ },
+ "_links":{
+ "self": "http://localhost:3001/api/v4/projects/8/issues/6",
+ "notes": "http://localhost:3001/api/v4/projects/8/issues/6/notes",
+ "award_emoji": "http://localhost:3001/api/v4/projects/8/issues/6/award_emoji",
+ "project": "http://localhost:3001/api/v4/projects/8"
+ },
+ "subscribed": true,
+ "epic_issue_id": 2
+ }
+]
+```
+
+**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+
+## Assign an issue to the epic
+
+Creates an epic - issue association. If the issue in question belongs to another epic it is unassigned from that epic.
+
+```
+POST /groups/:id/epics/:epic_iid/issues/:issue_id
+```
+
+| Attribute | Type | Required | Description |
+| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `epic_iid` | integer/string | yes | The internal ID of the epic. |
+| `issue_id` | integer/string | yes | The ID of the issue. |
+
+```bash
+curl --header POST "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5/issues/55
+```
+
+Example response:
+
+```json
+{
+ "id": 11,
+ "epic": {
+ "id": 30,
+ "iid": 5,
+ "title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.",
+ "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.",
+ "author": {
+ "id": 7,
+ "name": "Pamella Huel",
+ "username": "arnita",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon",
+ "web_url": "http://localhost:3001/arnita"
+ },
+ "start_date": null,
+ "end_date": null
+ },
+ "issue": {
+ "id": 55,
+ "iid": 13,
+ "project_id": 8,
+ "title": "Beatae laborum voluptatem voluptate eligendi ex accusamus.",
+ "description": "Quam veritatis debitis omnis aliquam sit.",
+ "state": "opened",
+ "created_at": "2017-11-05T13:59:12.782Z",
+ "updated_at": "2018-01-05T10:33:03.900Z",
+ "closed_at": null,
+ "labels": [],
+ "milestone": {
+ "id": 48,
+ "iid": 6,
+ "project_id": 8,
+ "title": "Sprint - Sed sed maxime temporibus ipsa ullam qui sit.",
+ "description": "Quos veritatis qui expedita sunt deleniti accusamus.",
+ "state": "active",
+ "created_at": "2017-11-05T13:59:12.445Z",
+ "updated_at": "2017-11-05T13:59:12.445Z",
+ "due_date": "2017-11-13",
+ "start_date": "2017-11-05"
+ },
+ "assignees": [{
+ "id": 10,
+ "name": "Lu Mayer",
+ "username": "kam",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon",
+ "web_url": "http://localhost:3001/kam"
+ }],
+ "assignee": {
+ "id": 10,
+ "name": "Lu Mayer",
+ "username": "kam",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon",
+ "web_url": "http://localhost:3001/kam"
+ },
+ "author": {
+ "id": 25,
+ "name": "User 3",
+ "username": "user3",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/97d6d9441ff85fdc730e02a6068d267b?s=80&d=identicon",
+ "web_url": "http://localhost:3001/user3"
+ },
+ "user_notes_count": 0,
+ "upvotes": 0,
+ "downvotes": 0,
+ "due_date": null,
+ "confidential": false,
+ "weight": null,
+ "discussion_locked": null,
+ "web_url": "http://localhost:3001/h5bp/html5-boilerplate/issues/13",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ }
+ }
+}
+```
+
+**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+
+## Remove an issue from the epic
+
+Removes an epic - issue association.
+
+```
+DELETE /groups/:id/epics/:epic_iid/issues/:epic_issue_id
+```
+
+| Attribute | Type | Required | Description |
+| ------------------- | ---------------- | ---------- | -----------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `epic_iid` | integer/string | yes | The internal ID of the epic. |
+| `epic_issue_id` | integer/string | yes | The ID of the issue - epic association. |
+
+```bash
+curl --header DELETE "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5/issues/11
+```
+
+Example response:
+
+```json
+{
+ "id": 11,
+ "epic": {
+ "id": 30,
+ "iid": 5,
+ "title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.",
+ "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.",
+ "author": {
+ "id": 7,
+ "name": "Pamella Huel",
+ "username": "arnita",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon",
+ "web_url": "http://localhost:3001/arnita"
+ },
+ "start_date": null,
+ "end_date": null
+ },
+ "issue": {
+ "id": 223,
+ "iid": 13,
+ "project_id": 8,
+ "title": "Beatae laborum voluptatem voluptate eligendi ex accusamus.",
+ "description": "Quam veritatis debitis omnis aliquam sit.",
+ "state": "opened",
+ "created_at": "2017-11-05T13:59:12.782Z",
+ "updated_at": "2018-01-05T10:33:03.900Z",
+ "closed_at": null,
+ "labels": [],
+ "milestone": {
+ "id": 48,
+ "iid": 6,
+ "project_id": 8,
+ "title": "Sprint - Sed sed maxime temporibus ipsa ullam qui sit.",
+ "description": "Quos veritatis qui expedita sunt deleniti accusamus.",
+ "state": "active",
+ "created_at": "2017-11-05T13:59:12.445Z",
+ "updated_at": "2017-11-05T13:59:12.445Z",
+ "due_date": "2017-11-13",
+ "start_date": "2017-11-05"
+ },
+ "assignees": [{
+ "id": 10,
+ "name": "Lu Mayer",
+ "username": "kam",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon",
+ "web_url": "http://localhost:3001/kam"
+ }],
+ "assignee": {
+ "id": 10,
+ "name": "Lu Mayer",
+ "username": "kam",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon",
+ "web_url": "http://localhost:3001/kam"
+ },
+ "author": {
+ "id": 25,
+ "name": "User 3",
+ "username": "user3",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/97d6d9441ff85fdc730e02a6068d267b?s=80&d=identicon",
+ "web_url": "http://localhost:3001/user3"
+ },
+ "user_notes_count": 0,
+ "upvotes": 0,
+ "downvotes": 0,
+ "due_date": null,
+ "confidential": false,
+ "weight": null,
+ "discussion_locked": null,
+ "web_url": "http://localhost:3001/h5bp/html5-boilerplate/issues/13",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ }
+ }
+}
+```
+
+**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+
+## Update epic - issue association
+
+Updates an epic - issue association.
+
+```
+PUT /groups/:id/epics/:epic_iid/issues/:epic_issue_id
+```
+
+| Attribute | Type | Required | Description |
+| ------------------- | ---------------- | ---------- | -----------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `epic_iid` | integer/string | yes | The internal ID of the epic. |
+| `epic_issue_id` | integer/string | yes | The ID of the issue - epic association. |
+| `move_before_id` | integer/string | no | The ID of the issue - epic association that should be placed before the link in the question. |
+| `move_after_id` | integer/string | no | The ID of the issue - epic association that should be placed after the link in the question. |
+
+```bash
+curl --header PUT "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5/issues/11?move_before_id=20
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 30,
+ "iid": 6,
+ "project_id": 8,
+ "title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.",
+ "description" : "Ratione dolores corrupti mollitia soluta quia.",
+ "state": "opened",
+ "created_at": "2017-11-15T13:39:24.670Z",
+ "updated_at": "2018-01-04T10:49:19.506Z",
+ "closed_at": null,
+ "labels": [],
+ "milestone": {
+ "id": 38,
+ "iid": 3,
+ "project_id": 8,
+ "title": "v2.0",
+ "description": "In tempore culpa inventore quo accusantium.",
+ "state": "closed",
+ "created_at": "2017-11-15T13:39:13.825Z",
+ "updated_at": "2017-11-15T13:39:13.825Z",
+ "due_date": null,
+ "start_date": null
+ },
+ "assignees": [{
+ "id": 7,
+ "name": "Pamella Huel",
+ "username": "arnita",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon",
+ "web_url": "http://localhost:3001/arnita"
+ }],
+ "assignee": {
+ "id": 7,
+ "name": "Pamella Huel",
+ "username": "arnita",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon",
+ "web_url": "http://localhost:3001/arnita"
+ },
+ "author": {
+ "id": 13,
+ "name": "Michell Johns",
+ "username": "chris_hahn",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/30e3b2122ccd6b8e45e8e14a3ffb58fc?s=80&d=identicon",
+ "web_url": "http://localhost:3001/chris_hahn"
+ },
+ "user_notes_count": 8,
+ "upvotes": 0,
+ "downvotes": 0,
+ "due_date": null,
+ "confidential": false,
+ "weight": null,
+ "discussion_locked": null,
+ "web_url": "http://localhost:3001/h5bp/html5-boilerplate/issues/6",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ },
+ "_links":{
+ "self": "http://localhost:3001/api/v4/projects/8/issues/6",
+ "notes": "http://localhost:3001/api/v4/projects/8/issues/6/notes",
+ "award_emoji": "http://localhost:3001/api/v4/projects/8/issues/6/award_emoji",
+ "project": "http://localhost:3001/api/v4/projects/8"
+ },
+ "subscribed": true,
+ "epic_issue_id": 11,
+ "relative_position": 55
+ }
+]
+```
diff --git a/doc/api/epic_links.md b/doc/api/epic_links.md
new file mode 100644
index 00000000000..9ad90a6d0f1
--- /dev/null
+++ b/doc/api/epic_links.md
@@ -0,0 +1,254 @@
+# Epic Links API **[ULTIMATE]**
+
+>**Note:**
+> This endpoint was [introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9188) in GitLab 11.8.
+
+Manages parent-child [epic relationships](../user/group/epics/index.md#multi-level-child-epics).
+
+Every API call to `epic_links` must be authenticated.
+
+If a user is not a member of a group and the group is private, a `GET` request on that group will result to a `404` status code.
+
+Epics are available only in the [Ultimate/Gold tier](https://about.gitlab.com/pricing/). If the epics feature is not available, a `403` status code will be returned.
+
+## List epics related to a given epic
+
+Gets all child epics of an epic.
+
+```
+GET /groups/:id/epics/:epic_iid/epics
+```
+
+| Attribute | Type | Required | Description |
+| ---------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `epic_iid` | integer | yes | The internal ID of the epic. |
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5/epics/
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 29,
+ "iid": 6,
+ "group_id": 1,
+ "parent_id": 5,
+ "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.",
+ "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.",
+ "author": {
+ "id": 10,
+ "name": "Lu Mayer",
+ "username": "kam",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon",
+ "web_url": "http://localhost:3001/kam"
+ },
+ "start_date": null,
+ "start_date_is_fixed": false,
+ "start_date_fixed": null,
+ "start_date_from_milestones": null,
+ "end_date": "2018-07-31",
+ "due_date": "2018-07-31",
+ "due_date_is_fixed": false,
+ "due_date_fixed": null,
+ "due_date_from_milestones": "2018-07-31",
+ "created_at": "2018-07-17T13:36:22.770Z",
+ "updated_at": "2018-07-18T12:22:05.239Z",
+ "labels": []
+ }
+]
+```
+
+## Assign a child epic
+
+Creates an association between two epics, designating one as the parent epic and the other as the child epic. A parent epic can have multiple child epics. If the new child epic already belonged to another epic, it is unassigned from that previous parent.
+
+```
+POST /groups/:id/epics/:epic_iid/epics
+```
+
+| Attribute | Type | Required | Description |
+| --------------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------ |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `epic_iid` | integer | yes | The internal ID of the epic. |
+| `child_epic_id` | integer | yes | The global ID of the child epic. Internal ID can't be used because they can conflict with epics from other groups. |
+
+```bash
+curl --header POST "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5/epics/6
+```
+
+Example response:
+
+```json
+{
+ "id": 6,
+ "iid": 38,
+ "group_id": 1,
+ "parent_id": 5
+ "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.",
+ "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.",
+ "author": {
+ "id": 10,
+ "name": "Lu Mayer",
+ "username": "kam",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon",
+ "web_url": "http://localhost:3001/kam"
+ },
+ "start_date": null,
+ "start_date_is_fixed": false,
+ "start_date_fixed": null,
+ "start_date_from_milestones": null,
+ "end_date": "2018-07-31",
+ "due_date": "2018-07-31",
+ "due_date_is_fixed": false,
+ "due_date_fixed": null,
+ "due_date_from_milestones": "2018-07-31",
+ "created_at": "2018-07-17T13:36:22.770Z",
+ "updated_at": "2018-07-18T12:22:05.239Z",
+ "labels": []
+}
+```
+
+## Create and assign a child epic
+
+Creates a a new epic and associates it with provided parent epic. The response is LinkedEpic object.
+
+```
+POST /groups/:id/epics/:epic_iid/epics
+```
+
+| Attribute | Type | Required | Description |
+| --------------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------ |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `epic_iid` | integer | yes | The internal ID of the (future parent) epic. |
+| `title` | string | yes | The title of a newly created epic. |
+
+```bash
+curl --header POST "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5/epics?title=Newpic
+```
+
+Example response:
+
+```json
+{
+ "id": 24,
+ "iid": 2,
+ "title": "child epic",
+ "group_id": 49,
+ "parent_id": 23,
+ "has_children": false,
+ "has_issues": false,
+ "reference": "&2",
+ "url": "http://localhost/groups/group16/-/epics/2",
+ "relation_url": "http://localhost/groups/group16/-/epics/1/links/24"
+}
+```
+
+## Re-order a child epic
+
+```
+PUT /groups/:id/epics/:epic_iid/epics/:child_epic_id
+```
+
+| Attribute | Type | Required | Description |
+| ---------------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------ |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `epic_iid` | integer | yes | The internal ID of the epic. |
+| `child_epic_id` | integer | yes | The global ID of the child epic. Internal ID can't be used because they can conflict with epics from other groups. |
+| `move_before_id` | integer | no | The global ID of a sibling epic that should be placed before the child epic. |
+| `move_after_id` | integer | no | The global ID of a sibling epic that should be placed after the child epic. |
+
+```bash
+curl --header PUT "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/4/epics/5
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 29,
+ "iid": 6,
+ "group_id": 1,
+ "parent_id": 5,
+ "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.",
+ "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.",
+ "author": {
+ "id": 10,
+ "name": "Lu Mayer",
+ "username": "kam",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon",
+ "web_url": "http://localhost:3001/kam"
+ },
+ "start_date": null,
+ "start_date_is_fixed": false,
+ "start_date_fixed": null,
+ "start_date_from_milestones": null,
+ "end_date": "2018-07-31",
+ "due_date": "2018-07-31",
+ "due_date_is_fixed": false,
+ "due_date_fixed": null,
+ "due_date_from_milestones": "2018-07-31",
+ "created_at": "2018-07-17T13:36:22.770Z",
+ "updated_at": "2018-07-18T12:22:05.239Z",
+ "labels": []
+ }
+]
+```
+
+## Unassign a child epic
+
+Unassigns a child epic from a parent epic.
+
+```
+DELETE /groups/:id/epics/:epic_iid/epics/:child_epic_id
+```
+
+| Attribute | Type | Required | Description |
+| --------------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------ |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `epic_iid` | integer | yes | The internal ID of the epic. |
+| `child_epic_id` | integer | yes | The global ID of the child epic. Internal ID can't be used because they can conflict with epics from other groups. |
+
+```bash
+curl --header DELETE "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/4/epics/5
+```
+
+Example response:
+
+```json
+{
+ "id": 5,
+ "iid": 38,
+ "group_id": 1,
+ "parent_id": null,
+ "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.",
+ "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.",
+ "author": {
+ "id": 10,
+ "name": "Lu Mayer",
+ "username": "kam",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon",
+ "web_url": "http://localhost:3001/kam"
+ },
+ "start_date": null,
+ "start_date_is_fixed": false,
+ "start_date_fixed": null,
+ "start_date_from_milestones": null,
+ "end_date": "2018-07-31",
+ "due_date": "2018-07-31",
+ "due_date_is_fixed": false,
+ "due_date_fixed": null,
+ "due_date_from_milestones": "2018-07-31",
+ "created_at": "2018-07-17T13:36:22.770Z",
+ "updated_at": "2018-07-18T12:22:05.239Z",
+ "labels": []
+}
+```
diff --git a/doc/api/epics.md b/doc/api/epics.md
new file mode 100644
index 00000000000..0541cfaa715
--- /dev/null
+++ b/doc/api/epics.md
@@ -0,0 +1,360 @@
+# Epics API **[ULTIMATE]**
+
+Every API call to epic must be authenticated.
+
+If a user is not a member of a group and the group is private, a `GET` request on that group will result to a `404` status code.
+
+If epics feature is not available a `403` status code will be returned.
+
+## Epic issues API
+
+The [epic issues API](epic_issues.md) allows you to interact with issues associated with an epic.
+
+# Milestone dates integration
+
+> [Introduced][ee-6448] in GitLab 11.3.
+
+Since start date and due date can be dynamically sourced from related issue milestones, when user has edit permission, additional fields will be shown. These include two boolean fields `start_date_is_fixed` and `due_date_is_fixed`, and four date fields `start_date_fixed`, `start_date_from_milestones`, `due_date_fixed` and `due_date_from_milestones`.
+
+`end_date` has been deprecated in favor of `due_date`.
+
+## Epics pagination
+
+By default, `GET` requests return 20 results at a time because the API results
+are paginated.
+
+Read more on [pagination](README.md#pagination).
+
+## List epics for a group
+
+Gets all epics of the requested group and its subgroups.
+
+```
+GET /groups/:id/epics
+GET /groups/:id/epics?author_id=5
+GET /groups/:id/epics?labels=bug,reproduced
+GET /groups/:id/epics?state=opened
+```
+
+| Attribute | Type | Required | Description |
+| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `author_id` | integer | no | Return epics created by the given user `id` |
+| `labels` | string | no | Return epics matching a comma separated list of labels names. Label names from the epic group or a parent group can be used |
+| `order_by` | string | no | Return epics ordered by `created_at` or `updated_at` fields. Default is `created_at` |
+| `sort` | string | no | Return epics sorted in `asc` or `desc` order. Default is `desc` |
+| `search` | string | no | Search epics against their `title` and `description` |
+| `state` | string | no | Search epics against their `state`, possible filters: `opened`, `closed` and `all`, default: `all` |
+| `created_after` | datetime | no | Return epics created on or after the given time |
+| `created_before` | datetime | no | Return epics created on or before the given time |
+| `updated_after` | datetime | no | Return epics updated on or after the given time |
+| `updated_before` | datetime | no | Return epics updated on or before the given time |
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 29,
+ "iid": 4,
+ "group_id": 7,
+ "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.",
+ "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.",
+ "state": "opened",
+ "author": {
+ "id": 10,
+ "name": "Lu Mayer",
+ "username": "kam",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon",
+ "web_url": "http://localhost:3001/kam"
+ },
+ "start_date": null,
+ "start_date_is_fixed": false,
+ "start_date_fixed": null,
+ "start_date_from_milestones": null,
+ "end_date": "2018-07-31",
+ "due_date": "2018-07-31",
+ "due_date_is_fixed": false,
+ "due_date_fixed": null,
+ "due_date_from_milestones": "2018-07-31",
+ "created_at": "2018-07-17T13:36:22.770Z",
+ "updated_at": "2018-07-18T12:22:05.239Z",
+ "labels": [],
+ "upvotes": 4,
+ "downvotes": 0
+ }
+]
+```
+
+## Single epic
+
+Gets a single epic
+
+```
+GET /groups/:id/epics/:epic_iid
+```
+
+| Attribute | Type | Required | Description |
+| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `epic_iid` | integer/string | yes | The internal ID of the epic. |
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5
+```
+
+Example response:
+
+```json
+{
+ "id": 30,
+ "iid": 5,
+ "group_id": 7,
+ "title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.",
+ "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.",
+ "state": "opened",
+ "author":{
+ "id": 7,
+ "name": "Pamella Huel",
+ "username": "arnita",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon",
+ "web_url": "http://localhost:3001/arnita"
+ },
+ "start_date": null,
+ "start_date_is_fixed": false,
+ "start_date_fixed": null,
+ "start_date_from_milestones": null,
+ "end_date": "2018-07-31",
+ "due_date": "2018-07-31",
+ "due_date_is_fixed": false,
+ "due_date_fixed": null,
+ "due_date_from_milestones": "2018-07-31",
+ "created_at": "2018-07-17T13:36:22.770Z",
+ "updated_at": "2018-07-18T12:22:05.239Z",
+ "labels": [],
+ "upvotes": 4,
+ "downvotes": 0
+}
+```
+
+## New epic
+
+Creates a new epic.
+
+NOTE: **Note:**
+Starting with GitLab [11.3][ee-6448], `start_date` and `end_date` should no longer be assigned
+directly, as they now represent composite values. You can configure it via the `*_is_fixed` and
+`*_fixed` fields instead.
+
+```
+POST /groups/:id/epics
+```
+
+| Attribute | Type | Required | Description |
+| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `title` | string | yes | The title of the epic |
+| `labels` | string | no | The comma separated list of labels |
+| `description` | string | no | The description of the epic |
+| `start_date_is_fixed` | boolean | no | Whether start date should be sourced from `start_date_fixed` or from milestones (since 11.3) |
+| `start_date_fixed` | string | no | The fixed start date of an epic (since 11.3) |
+| `due_date_is_fixed` | boolean | no | Whether due date should be sourced from `due_date_fixed` or from milestones (since 11.3) |
+| `due_date_fixed` | string | no | The fixed due date of an epic (since 11.3) |
+| `parent_id` | integer/string | no | The id of a parent epic (since 11.11) |
+
+```bash
+curl --header POST "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics?title=Epic&description=Epic%20description
+```
+
+Example response:
+
+```json
+{
+ "id": 33,
+ "iid": 6,
+ "group_id": 7,
+ "title": "Epic",
+ "description": "Epic description",
+ "state": "opened",
+ "author": {
+ "name" : "Alexandra Bashirian",
+ "avatar_url" : null,
+ "state" : "active",
+ "web_url" : "https://gitlab.example.com/eileen.lowe",
+ "id" : 18,
+ "username" : "eileen.lowe"
+ },
+ "start_date": null,
+ "start_date_is_fixed": false,
+ "start_date_fixed": null,
+ "start_date_from_milestones": null,
+ "end_date": "2018-07-31",
+ "due_date": "2018-07-31",
+ "due_date_is_fixed": false,
+ "due_date_fixed": null,
+ "due_date_from_milestones": "2018-07-31",
+ "created_at": "2018-07-17T13:36:22.770Z",
+ "updated_at": "2018-07-18T12:22:05.239Z",
+ "labels": [],
+ "upvotes": 4,
+ "downvotes": 0
+}
+```
+
+## Update epic
+
+Updates an epic.
+
+NOTE: **Note:**
+Starting with GitLab [11.3][ee-6448], `start_date` and `end_date` should no longer be assigned
+directly, as they now represent composite values. You can configure it via the `*_is_fixed` and
+`*_fixed` fields instead.
+
+```
+PUT /groups/:id/epics/:epic_iid
+```
+
+| Attribute | Type | Required | Description |
+| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `epic_iid` | integer/string | yes | The internal ID of the epic |
+| `title` | string | no | The title of an epic |
+| `description` | string | no | The description of an epic |
+| `labels` | string | no | The comma separated list of labels |
+| `start_date_is_fixed` | boolean | no | Whether start date should be sourced from `start_date_fixed` or from milestones (since 11.3) |
+| `start_date_fixed` | string | no | The fixed start date of an epic (since 11.3) |
+| `due_date_is_fixed` | boolean | no | Whether due date should be sourced from `due_date_fixed` or from milestones (since 11.3) |
+| `due_date_fixed` | string | no | The fixed due date of an epic (since 11.3) |
+| `state_event` | string | no | State event for an epic. Set `close` to close the epic and `reopen` to reopen it (since 11.4) |
+
+```bash
+curl --header PUT "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5?title=New%20Title
+```
+
+Example response:
+
+```json
+{
+ "id": 33,
+ "iid": 6,
+ "group_id": 7,
+ "title": "New Title",
+ "description": "Epic description",
+ "state": "opened",
+ "author": {
+ "name" : "Alexandra Bashirian",
+ "avatar_url" : null,
+ "state" : "active",
+ "web_url" : "https://gitlab.example.com/eileen.lowe",
+ "id" : 18,
+ "username" : "eileen.lowe"
+ },
+ "start_date": null,
+ "start_date_is_fixed": false,
+ "start_date_fixed": null,
+ "start_date_from_milestones": null,
+ "end_date": "2018-07-31",
+ "due_date": "2018-07-31",
+ "due_date_is_fixed": false,
+ "due_date_fixed": null,
+ "due_date_from_milestones": "2018-07-31",
+ "created_at": "2018-07-17T13:36:22.770Z",
+ "updated_at": "2018-07-18T12:22:05.239Z",
+ "labels": [],
+ "upvotes": 4,
+ "downvotes": 0
+}
+```
+
+## Delete epic
+
+Deletes an epic
+
+```
+DELETE /groups/:id/epics/:epic_iid
+```
+
+| Attribute | Type | Required | Description |
+| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `epic_iid` | integer/string | yes | The internal ID of the epic. |
+
+```bash
+curl --header DELETE "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5
+```
+
+## Create a todo
+
+Manually creates a todo for the current user on an epic. If
+there already exists a todo for the user on that epic, status code `304` is
+returned.
+
+```
+POST /groups/:id/epics/:epic_iid/todo
+```
+
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|--------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `epic_iid ` | integer | yes | The internal ID of a group's epic |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/5/todo
+```
+
+Example response:
+
+```json
+{
+ "id": 112,
+ "group": {
+ "id": 1,
+ "name": "Gitlab",
+ "path": "gitlab",
+ "kind": "group",
+ "full_path": "base/gitlab",
+ "parent_id": null
+ },
+ "author": {
+ "name": "Administrator",
+ "username": "root",
+ "id": 1,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/root"
+ },
+ "action_name": "marked",
+ "target_type": "epic",
+ "target": {
+ "id": 30,
+ "iid": 5,
+ "group_id": 1,
+ "title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.",
+ "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.",
+ "author":{
+ "id": 7,
+ "name": "Pamella Huel",
+ "username": "arnita",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon",
+ "web_url": "http://localhost:3001/arnita"
+ },
+ "start_date": null,
+ "end_date": null,
+ "created_at": "2018-01-21T06:21:13.165Z",
+ "updated_at": "2018-01-22T12:41:41.166Z"
+ },
+ "target_url": "https://gitlab.example.com/groups/epics/5",
+ "body": "Vel voluptas atque dicta mollitia adipisci qui at.",
+ "state": "pending",
+ "created_at": "2016-07-01T11:09:13.992Z"
+}
+```
+
+[ee-6448]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/6448
diff --git a/doc/api/geo_nodes.md b/doc/api/geo_nodes.md
new file mode 100644
index 00000000000..ea31abdd87e
--- /dev/null
+++ b/doc/api/geo_nodes.md
@@ -0,0 +1,404 @@
+# Geo Nodes API **[PREMIUM ONLY]**
+
+In order to interact with Geo node endpoints, you need to authenticate yourself
+as an admin.
+
+## Retrieve configuration about all Geo nodes
+
+```
+GET /geo_nodes
+```
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/geo_nodes
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 1,
+ "name": "us-node",
+ "url": "https://primary.example.com/",
+ "internal_url": "https://internal.example.com/",
+ "primary": true,
+ "enabled": true,
+ "current": true,
+ "files_max_capacity": 10,
+ "repos_max_capacity": 25,
+ "verification_max_capacity": 100,
+ "clone_protocol": "http"
+ },
+ {
+ "id": 2,
+ "name": "cn-node",
+ "url": "https://secondary.example.com/",
+ "internal_url": "https://secondary.example.com/",
+ "primary": false,
+ "enabled": true,
+ "current": false,
+ "files_max_capacity": 10,
+ "repos_max_capacity": 25,
+ "verification_max_capacity": 100,
+ "clone_protocol": "http"
+ }
+]
+```
+
+## Retrieve configuration about a specific Geo node
+
+```
+GET /geo_nodes/:id
+```
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/geo_nodes/1
+```
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "name": "us-node",
+ "url": "https://primary.example.com/",
+ "internal_url": "https://primary.example.com/",
+ "primary": true,
+ "enabled": true,
+ "current": true,
+ "files_max_capacity": 10,
+ "repos_max_capacity": 25,
+ "verification_max_capacity": 100,
+ "clone_protocol": "http"
+}
+```
+
+## Edit a Geo node
+
+Updates settings of an existing Geo node.
+
+_This can only be run against a primary Geo node._
+
+```
+PUT /geo_nodes/:id
+```
+
+| Attribute | Type | Required | Description |
+|----------------------|---------|-----------|---------------------------------------------------------------------------|
+| `id` | integer | yes | The ID of the Geo node. |
+| `enabled` | boolean | no | Flag indicating if the Geo node is enabled. |
+| `name` | string | yes | The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`. |
+| `url` | string | yes | The user-facing URL of the Geo node. |
+| `internal_url` | string | no | The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set.|
+| `files_max_capacity` | integer | no | Control the maximum concurrency of LFS/attachment backfill for this secondary node. |
+| `repos_max_capacity` | integer | no | Control the maximum concurrency of repository backfill for this secondary node. |
+| `verification_max_capacity` | integer | no | Control the maximum concurrency of verification for this node. |
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "name": "cn-node",
+ "url": "https://secondary.example.com/",
+ "internal_url": "https://secondary.example.com/",
+ "primary": false,
+ "enabled": true,
+ "current": true,
+ "files_max_capacity": 10,
+ "repos_max_capacity": 25,
+ "verification_max_capacity": 100,
+ "clone_protocol": "http"
+}
+```
+
+## Delete a Geo node
+
+Removes the Geo node.
+
+NOTE: **Note:**
+Only a Geo primary node will accept this request.
+
+```
+DELETE /geo_nodes/:id
+```
+
+| Attribute | Type | Required | Description |
+|-----------|---------|----------|-------------------------|
+| `id` | integer | yes | The ID of the Geo node. |
+
+## Repair a Geo node
+
+To repair the OAuth authentication of a Geo node.
+
+_This can only be run against a primary Geo node._
+
+```
+POST /geo_nodes/:id/repair
+```
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "name": "us-node",
+ "url": "https://primary.example.com/",
+ "internal_url": "https://primary.example.com/",
+ "primary": true,
+ "enabled": true,
+ "current": true,
+ "files_max_capacity": 10,
+ "repos_max_capacity": 25,
+ "verification_max_capacity": 100,
+ "clone_protocol": "http"
+}
+```
+
+## Retrieve status about all Geo nodes
+
+```
+GET /geo_nodes/status
+```
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/geo_nodes/status
+```
+
+Example response:
+
+```json
+[
+ {
+ "geo_node_id": 1,
+ "healthy": true,
+ "health": "Healthy",
+ "health_status": "Healthy",
+ "missing_oauth_application": false,
+ "attachments_count": 1,
+ "attachments_synced_count": nil,
+ "attachments_failed_count": nil,
+ "attachments_synced_missing_on_primary_count": 0,
+ "attachments_synced_in_percentage": "0.00%",
+ "db_replication_lag_seconds": nil,
+ "lfs_objects_count": 0,
+ "lfs_objects_synced_count": nil,
+ "lfs_objects_failed_count": nil,
+ "lfs_objects_synced_missing_on_primary_count": 0,
+ "lfs_objects_synced_in_percentage": "0.00%",
+ "job_artifacts_count": 2,
+ "job_artifacts_synced_count": nil,
+ "job_artifacts_failed_count": nil,
+ "job_artifacts_synced_missing_on_primary_count": 0,
+ "job_artifacts_synced_in_percentage": "0.00%",
+ "projects_count": 41,
+ "repositories_failed_count": nil,
+ "repositories_synced_count": nil,
+ "repositories_synced_in_percentage": "0.00%",
+ "wikis_failed_count": nil,
+ "wikis_synced_count": nil,
+ "wikis_synced_in_percentage": "0.00%",
+ "replication_slots_count": 1,
+ "replication_slots_used_count": 1,
+ "replication_slots_used_in_percentage": "100.00%",
+ "replication_slots_max_retained_wal_bytes": 0,
+ "repositories_checked_count": 20,
+ "repositories_checked_failed_count": 20,
+ "repositories_checked_in_percentage": "100.00%",
+ "repositories_checksummed_count": 20,
+ "repositories_checksum_failed_count": 5,
+ "repositories_checksummed_in_percentage": "48.78%",
+ "wikis_checksummed_count": 10,
+ "wikis_checksum_failed_count": 3,
+ "wikis_checksummed_in_percentage": "24.39%",
+ "repositories_verified_count": 20,
+ "repositories_verification_failed_count": 5,
+ "repositories_verified_in_percentage": "48.78%",
+ "repositories_checksum_mismatch_count": 3,
+ "wikis_verified_count": 10,
+ "wikis_verification_failed_count": 3,
+ "wikis_verified_in_percentage": "24.39%",
+ "wikis_checksum_mismatch_count": 1,
+ "repositories_retrying_verification_count": 1,
+ "wikis_retrying_verification_count": 3,
+ "repositories_checked_count": 7,
+ "repositories_checked_failed_count": 2,
+ "repositories_checked_in_percentage": "17.07%",
+ "last_event_id": 23,
+ "last_event_timestamp": 1509681166,
+ "cursor_last_event_id": nil,
+ "cursor_last_event_timestamp": 0,
+ "last_successful_status_check_timestamp": 1510125024,
+ "version": "10.3.0",
+ "revision": "33d33a096a",
+ },
+ {
+ "geo_node_id": 2,
+ "healthy": true,
+ "health": "Healthy",
+ "health_status": "Healthy",
+ "missing_oauth_application": false,
+ "attachments_count": 1,
+ "attachments_synced_count": 1,
+ "attachments_failed_count": 0,
+ "attachments_synced_missing_on_primary_count": 0,
+ "attachments_synced_in_percentage": "100.00%",
+ "db_replication_lag_seconds": 0,
+ "lfs_objects_count": 0,
+ "lfs_objects_synced_count": 0,
+ "lfs_objects_failed_count": 0,
+ "lfs_objects_synced_missing_on_primary_count": 0,
+ "lfs_objects_synced_in_percentage": "0.00%",
+ "job_artifacts_count": 2,
+ "job_artifacts_synced_count": 1,
+ "job_artifacts_failed_count": 1,
+ "job_artifacts_synced_missing_on_primary_count": 0,
+ "job_artifacts_synced_in_percentage": "50.00%",
+ "projects_count": 41,
+ "repositories_failed_count": 1,
+ "repositories_synced_count": 40,
+ "repositories_synced_in_percentage": "97.56%",
+ "wikis_failed_count": 0,
+ "wikis_synced_count": 41,
+ "wikis_synced_in_percentage": "100.00%",
+ "replication_slots_count": nil,
+ "replication_slots_used_count": nil,
+ "replication_slots_used_in_percentage": "0.00%",
+ "replication_slots_max_retained_wal_bytes": nil,
+ "repositories_checksummed_count": 20,
+ "repositories_checksum_failed_count": 5,
+ "repositories_checksummed_in_percentage": "48.78%",
+ "wikis_checksummed_count": 10,
+ "wikis_checksum_failed_count": 3,
+ "wikis_checksummed_in_percentage": "24.39%",
+ "repositories_verified_count": 20,
+ "repositories_verification_failed_count": 5,
+ "repositories_verified_in_percentage": "48.78%",
+ "repositories_checksum_mismatch_count": 3,
+ "wikis_verified_count": 10,
+ "wikis_verification_failed_count": 3,
+ "wikis_verified_in_percentage": "24.39%",
+ "wikis_checksum_mismatch_count": 1,
+ "repositories_retrying_verification_count": 4,
+ "wikis_retrying_verification_count": 2,
+ "repositories_checked_count": 5,
+ "repositories_checked_failed_count": 1,
+ "repositories_checked_in_percentage": "12.20%",
+ "last_event_id": 23,
+ "last_event_timestamp": 1509681166,
+ "cursor_last_event_id": 23,
+ "cursor_last_event_timestamp": 1509681166,
+ "last_successful_status_check_timestamp": 1510125024,
+ "version": "10.3.0",
+ "revision": "33d33a096a"
+ }
+]
+```
+
+NOTE: **Note:**
+In GitLab 12.0, deprecated fields `wikis_count` and `repositories_count` were removed. Use `projects_count` instead.
+
+## Retrieve status about a specific Geo node
+
+```
+GET /geo_nodes/:id/status
+```
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/geo_nodes/2/status
+```
+
+Example response:
+
+```json
+{
+ "geo_node_id": 2,
+ "healthy": true,
+ "health": "Healthy",
+ "health_status": "Healthy",
+ "missing_oauth_application": false,
+ "attachments_count": 1,
+ "attachments_synced_count": 1,
+ "attachments_failed_count": 0,
+ "attachments_synced_missing_on_primary_count": 0,
+ "attachments_synced_in_percentage": "100.00%",
+ "db_replication_lag_seconds": 0,
+ "lfs_objects_count": 0,
+ "lfs_objects_synced_count": 0,
+ "lfs_objects_failed_count": 0,
+ "lfs_objects_synced_missing_on_primary_count": 0,
+ "lfs_objects_synced_in_percentage": "0.00%",
+ "job_artifacts_count": 2,
+ "job_artifacts_synced_count": 1,
+ "job_artifacts_failed_count": 1,
+ "job_artifacts_synced_missing_on_primary_count": 0,
+ "job_artifacts_synced_in_percentage": "50.00%",
+ "projects_count": 41,
+ "repositories_failed_count": 1,
+ "repositories_synced_count": 40,
+ "repositories_synced_in_percentage": "97.56%",
+ "wikis_failed_count": 0,
+ "wikis_synced_count": 41,
+ "wikis_synced_in_percentage": "100.00%",
+ "replication_slots_count": nil,
+ "replication_slots_used_count": nil,
+ "replication_slots_used_in_percentage": "0.00%",
+ "replication_slots_max_retained_wal_bytes": nil,
+ "last_event_id": 23,
+ "last_event_timestamp": 1509681166,
+ "cursor_last_event_id": 23,
+ "cursor_last_event_timestamp": 1509681166,
+ "last_successful_status_check_timestamp": 1510125268,
+ "version": "10.3.0",
+ "revision": "33d33a096a"
+}
+```
+
+Note: The `health_status` parameter can only be in an "Healthy" or "Unhealthy" state, while the `health` parameter can be empty, "Healthy", or contain the actual error message.
+
+NOTE: **Note:**
+In GitLab 12.0, deprecated fields `wikis_count` and `repositories_count` were removed. Use `projects_count` instead.
+
+## Retrieve project sync or verification failures that occurred on the current node
+
+This only works on a secondary node.
+
+```
+GET /geo_nodes/current/failures
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `type` | string | no | Type of failed objects (`repository`/`wiki`) |
+| `failure_type` | string | no | Type of failures (`sync`/`checksum_mismatch`/`verification`) |
+
+This endpoint uses [Pagination](README.md#pagination).
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/geo_nodes/current/failures
+```
+
+Example response:
+
+```json
+[
+ {
+ "project_id": 3,
+ "last_repository_synced_at": "2017-10-31 14:25:55 UTC",
+ "last_repository_successful_sync_at": "2017-10-31 14:26:04 UTC",
+ "last_wiki_synced_at": "2017-10-31 14:26:04 UTC",
+ "last_wiki_successful_sync_at": "2017-10-31 14:26:11 UTC",
+ "repository_retry_count": null,
+ "wiki_retry_count": 1,
+ "last_repository_sync_failure": null,
+ "last_wiki_sync_failure": "Error syncing Wiki repository",
+ "last_repository_verification_failure": "",
+ "last_wiki_verification_failure": "",
+ "repository_verification_checksum_sha": "da39a3ee5e6b4b0d32e5bfef9a601890afd80709",
+ "wiki_verification_checksum_sha": "da39a3ee5e6b4b0d3255bfef9ef0189aafd80709",
+ "repository_checksum_mismatch": false,
+ "wiki_checksum_mismatch": false
+ }
+]
+```
diff --git a/doc/api/graphql/index.md b/doc/api/graphql/index.md
index ec48bf4940b..88e657a5d2f 100644
--- a/doc/api/graphql/index.md
+++ b/doc/api/graphql/index.md
@@ -16,6 +16,20 @@ added to the API without creating breaking changes. This allows us to
have a versionless API as described in [the GraphQL
documentation](https://graphql.org/learn/best-practices/#versioning).
+## Vision
+
+We want the GraphQL API to be the **primary** means of interacting
+programmatically with GitLab. To achieve this, it needs full coverage - anything
+possible in the REST API should also be possible in the GraphQL API.
+
+To help us meet this vision, the frontend should use GraphQL in preference to
+the REST API for new features, although the alpha status of GraphQL may prevent
+this from being a possibility at times.
+
+There are no plans to deprecate the REST API. To reduce the technical burden of
+supporting two APIs in parallel, they should share implementations as much as
+possible.
+
## Enabling the GraphQL feature
The GraphQL API itself is currently in Alpha, and therefore hidden behind a
@@ -29,7 +43,19 @@ curl --data "value=100" --header "PRIVATE-TOKEN: <your_access_token>" https://gi
## Available queries
-A first iteration of a GraphQL API includes a query for: `project`. Within a project it is also possible to fetch a `mergeRequest` by IID.
+A first iteration of a GraphQL API includes the following queries
+
+1. `project` : Within a project it is also possible to fetch a `mergeRequest` by IID.
+1. `group` : Only basic group information is currently supported.
+1. `namespace` : Within a namespace it is also possible to fetch `projects`.
+
+### Multiplex queries
+
+GitLab supports batching queries into a single request using
+[apollo-link-batch-http](https://www.apollographql.com/docs/link/links/batch-http). More
+info about multiplexed queries is also available for
+[graphql-ruby](https://graphql-ruby.org/queries/multiplex.html) the
+library GitLab uses on the backend.
## GraphiQL
diff --git a/doc/api/group_level_variables.md b/doc/api/group_level_variables.md
index 3551bfa3f8b..7b00df6d775 100644
--- a/doc/api/group_level_variables.md
+++ b/doc/api/group_level_variables.md
@@ -22,10 +22,12 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
[
{
"key": "TEST_VARIABLE_1",
+ "variable_type": "env_var",
"value": "TEST_1"
},
{
"key": "TEST_VARIABLE_2",
+ "variable_type": "env_var",
"value": "TEST_2"
}
]
@@ -51,6 +53,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
```json
{
"key": "TEST_VARIABLE_1",
+ "variable_type": "env_var",
"value": "TEST_1"
}
```
@@ -63,12 +66,13 @@ Create a new variable.
POST /groups/:id/variables
```
-| Attribute | Type | required | Description |
-|-------------|---------|----------|-----------------------|
-| `id` | integer/string | yes | The ID of a group or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `key` | string | yes | The `key` of a variable; must have no more than 255 characters; only `A-Z`, `a-z`, `0-9`, and `_` are allowed |
-| `value` | string | yes | The `value` of a variable |
-| `protected` | boolean | no | Whether the variable is protected |
+| Attribute | Type | required | Description |
+|-----------------|---------|----------|-----------------------|
+| `id` | integer/string | yes | The ID of a group or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `key` | string | yes | The `key` of a variable; must have no more than 255 characters; only `A-Z`, `a-z`, `0-9`, and `_` are allowed |
+| `value` | string | yes | The `value` of a variable |
+| `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file` |
+| `protected` | boolean | no | Whether the variable is protected |
```
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/variables" --form "key=NEW_VARIABLE" --form "value=new value"
@@ -78,6 +82,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla
{
"key": "NEW_VARIABLE",
"value": "new value",
+ "variable_type": "env_var",
"protected": false
}
```
@@ -90,12 +95,13 @@ Update a group's variable.
PUT /groups/:id/variables/:key
```
-| Attribute | Type | required | Description |
-|-------------|---------|----------|-------------------------|
-| `id` | integer/string | yes | The ID of a group or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `key` | string | yes | The `key` of a variable |
-| `value` | string | yes | The `value` of a variable |
-| `protected` | boolean | no | Whether the variable is protected |
+| Attribute | Type | required | Description |
+|-----------------|---------|----------|-------------------------|
+| `id` | integer/string | yes | The ID of a group or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `key` | string | yes | The `key` of a variable |
+| `value` | string | yes | The `value` of a variable |
+| `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file` |
+| `protected` | boolean | no | Whether the variable is protected |
```
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/variables/NEW_VARIABLE" --form "value=updated value"
@@ -105,6 +111,7 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab
{
"key": "NEW_VARIABLE",
"value": "updated value",
+ "variable_type": "env_var",
"protected": true
}
```
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 907b443d355..20789a1d4a4 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -68,6 +68,7 @@ GET /groups?statistics=true
"statistics": {
"storage_size" : 212,
"repository_size" : 33,
+ "wiki_size" : 100,
"lfs_objects_size" : 123,
"job_artifacts_size" : 57
diff --git a/doc/api/issue_links.md b/doc/api/issue_links.md
new file mode 100644
index 00000000000..1c7db6a8e4c
--- /dev/null
+++ b/doc/api/issue_links.md
@@ -0,0 +1,215 @@
+# Issue links API **[STARTER]**
+
+## List issue relations
+
+Get a list of related issues of a given issue, sorted by the relationship creation datetime (ascending).
+Issues will be filtered according to the user authorizations.
+
+```
+GET /projects/:id/issues/:issue_iid/links
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|--------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of a project's issue |
+
+```json
+[
+ {
+ "id" : 84,
+ "iid" : 14,
+ "issue_link_id": 1
+ "project_id" : 4,
+ "created_at" : "2016-01-07T12:44:33.959Z",
+ "title" : "Issues with auth",
+ "state" : "opened",
+ "assignees" : [],
+ "assignee" : null,
+ "labels" : [
+ "bug"
+ ],
+ "author" : {
+ "name" : "Alexandra Bashirian",
+ "avatar_url" : null,
+ "state" : "active",
+ "web_url" : "https://gitlab.example.com/eileen.lowe",
+ "id" : 18,
+ "username" : "eileen.lowe"
+ },
+ "description" : null,
+ "updated_at" : "2016-01-07T12:44:33.959Z",
+ "milestone" : null,
+ "subscribed" : true,
+ "user_notes_count": 0,
+ "due_date": null,
+ "web_url": "http://example.com/example/example/issues/14",
+ "confidential": false,
+ "weight": null,
+ }
+]
+```
+
+## Create an issue link
+
+Creates a two-way relation between two issues. User must be allowed to update both issues in order to succeed.
+
+```
+POST /projects/:id/issues/:issue_iid/links
+```
+
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|--------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of a project's issue |
+| `target_project_id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) of a target project |
+| `target_issue_iid` | integer/string | yes | The internal ID of a target project's issue |
+
+
+```json
+{
+ "source_issue" : {
+ "id" : 83,
+ "iid" : 11,
+ "project_id" : 4,
+ "created_at" : "2016-01-07T12:44:33.959Z",
+ "title" : "Issues with auth",
+ "state" : "opened",
+ "assignees" : [],
+ "assignee" : null,
+ "labels" : [
+ "bug"
+ ],
+ "author" : {
+ "name" : "Alexandra Bashirian",
+ "avatar_url" : null,
+ "state" : "active",
+ "web_url" : "https://gitlab.example.com/eileen.lowe",
+ "id" : 18,
+ "username" : "eileen.lowe"
+ },
+ "description" : null,
+ "updated_at" : "2016-01-07T12:44:33.959Z",
+ "milestone" : null,
+ "subscribed" : true,
+ "user_notes_count": 0,
+ "due_date": null,
+ "web_url": "http://example.com/example/example/issues/11",
+ "confidential": false,
+ "weight": null,
+ },
+ "target_issue" : {
+ "id" : 84,
+ "iid" : 14,
+ "project_id" : 4,
+ "created_at" : "2016-01-07T12:44:33.959Z",
+ "title" : "Issues with auth",
+ "state" : "opened",
+ "assignees" : [],
+ "assignee" : null,
+ "labels" : [
+ "bug"
+ ],
+ "author" : {
+ "name" : "Alexandra Bashirian",
+ "avatar_url" : null,
+ "state" : "active",
+ "web_url" : "https://gitlab.example.com/eileen.lowe",
+ "id" : 18,
+ "username" : "eileen.lowe"
+ },
+ "description" : null,
+ "updated_at" : "2016-01-07T12:44:33.959Z",
+ "milestone" : null,
+ "subscribed" : true,
+ "user_notes_count": 0,
+ "due_date": null,
+ "web_url": "http://example.com/example/example/issues/14",
+ "confidential": false,
+ "weight": null,
+ }
+}
+```
+
+## Delete an issue link
+
+Deletes an issue link, thus removes the two-way relationship.
+
+```
+DELETE /projects/:id/issues/:issue_iid/links/:issue_link_id
+```
+
+
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|--------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of a project's issue |
+| `issue_link_id` | integer/string | yes | The ID of an issue relationship |
+
+
+```json
+{
+ "source_issue" : {
+ "id" : 83,
+ "iid" : 11,
+ "project_id" : 4,
+ "created_at" : "2016-01-07T12:44:33.959Z",
+ "title" : "Issues with auth",
+ "state" : "opened",
+ "assignees" : [],
+ "assignee" : null,
+ "labels" : [
+ "bug"
+ ],
+ "author" : {
+ "name" : "Alexandra Bashirian",
+ "avatar_url" : null,
+ "state" : "active",
+ "web_url" : "https://gitlab.example.com/eileen.lowe",
+ "id" : 18,
+ "username" : "eileen.lowe"
+ },
+ "description" : null,
+ "updated_at" : "2016-01-07T12:44:33.959Z",
+ "milestone" : null,
+ "subscribed" : true,
+ "user_notes_count": 0,
+ "due_date": null,
+ "web_url": "http://example.com/example/example/issues/11",
+ "confidential": false,
+ "weight": null,
+ },
+ "target_issue" : {
+ "id" : 84,
+ "iid" : 14,
+ "project_id" : 4,
+ "created_at" : "2016-01-07T12:44:33.959Z",
+ "title" : "Issues with auth",
+ "state" : "opened",
+ "assignees" : [],
+ "assignee" : null,
+ "labels" : [
+ "bug"
+ ],
+ "author" : {
+ "name" : "Alexandra Bashirian",
+ "avatar_url" : null,
+ "state" : "active",
+ "web_url" : "https://gitlab.example.com/eileen.lowe",
+ "id" : 18,
+ "username" : "eileen.lowe"
+ },
+ "description" : null,
+ "updated_at" : "2016-01-07T12:44:33.959Z",
+ "milestone" : null,
+ "subscribed" : true,
+ "user_notes_count": 0,
+ "due_date": null,
+ "web_url": "http://example.com/example/example/issues/14",
+ "confidential": false,
+ "weight": null,
+ }
+}
+```
diff --git a/doc/api/issues.md b/doc/api/issues.md
index cb5789e76b7..0d96cfa1b21 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -37,23 +37,26 @@ GET /issues?confidential=true
| Attribute | Type | Required | Description |
| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
+| `state` | string | no | Return `all` issues or just those that are `opened` or `closed` |
| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. |
+| `with_labels_details`| Boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:text_color`. Default is `false`. |
| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`. Defaults to `created_by_me`<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced][ce-13004] in GitLab 9.5. [Changed to snake_case][ce-18935] in GitLab 11.0)_ |
-| `author_id` | integer | no | Return issues created by the given user `id`. Combine with `scope=all` or `scope=assigned_to_me`. _([Introduced][ce-13004] in GitLab 9.5)_ |
-| `assignee_id` | integer | no | Return issues assigned to the given user `id`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced][ce-13004] in GitLab 9.5)_ |
+| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. _([Introduced][ce-13004] in GitLab 9.5)_ |
+| `author_username` | string | no | Return issues created by the given `username`. Simillar to `author_id` and mutually exclusive with `author_id`. |
+| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced][ce-13004] in GitLab 9.5)_ |
+| `assignee_username` | Array[String] | no | Return issues assigned to the given `username`. Simillar to `assignee_id` and mutually exclusive with `assignee_id`. In CE version `assignee_username` array should only contain a single value or an invalid param error will be returned otherwise. |
| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced][ce-14016] in GitLab 10.0)_ |
| `iids[]` | Array[integer] | no | Return only the issues having the given `iid` |
| `order_by` | string | no | Return issues ordered by `created_at` or `updated_at` fields. Default is `created_at` |
| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
| `search` | string | no | Search issues against their `title` and `description` |
-| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` |
+| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` |
| `created_after` | datetime | no | Return issues created on or after the given time |
| `created_before` | datetime | no | Return issues created on or before the given time |
| `updated_after` | datetime | no | Return issues updated on or after the given time |
| `updated_before` | datetime | no | Return issues updated on or before the given time |
-| `confidential ` | Boolean | no | Filter confidential or public issues. |
+| `confidential ` | Boolean | no | Filter confidential or public issues. |
```bash
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/issues
@@ -109,7 +112,7 @@ Example response:
"title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.",
"created_at" : "2016-01-04T15:31:51.081Z",
"iid" : 6,
- "labels" : [],
+ "labels" : ["foo", "bar"],
"upvotes": 4,
"downvotes": 0,
"merge_requests_count": 0,
@@ -122,8 +125,21 @@ Example response:
"human_time_estimate": null,
"human_total_time_spent": null
},
+ "has_tasks": true,
+ "task_status": "10 of 15 tasks completed",
"confidential": false,
- "discussion_locked": false
+ "discussion_locked": false,
+ "_links":{
+ "self":"http://example.com/api/v4/projects/1/issues/76",
+ "notes":"`http://example.com/`api/v4/projects/1/issues/76/notes",
+ "award_emoji":"http://example.com/api/v4/projects/1/issues/76/award_emoji",
+ "project":"http://example.com/api/v4/projects/1"
+ },
+ "subscribed": false,
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
+ }
}
]
```
@@ -158,11 +174,14 @@ GET /groups/:id/issues?confidential=true
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. |
+| `with_labels_details`| Boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:text_color`. Default is `false`. |
| `iids[]` | Array[integer] | no | Return only the issues having the given `iid` |
| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced][ce-13004] in GitLab 9.5. [Changed to snake_case][ce-18935] in GitLab 11.0)_ |
-| `author_id` | integer | no | Return issues created by the given user `id` _([Introduced][ce-13004] in GitLab 9.5)_ |
-| `assignee_id` | integer | no | Return issues assigned to the given user `id`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced][ce-13004] in GitLab 9.5)_ |
+| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. _([Introduced][ce-13004] in GitLab 9.5)_ |
+| `author_username` | string | no | Return issues created by the given `username`. Simillar to `author_id` and mutually exclusive with `author_id`. |
+| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced][ce-13004] in GitLab 9.5)_ |
+| `assignee_username` | Array[String] | no | Return issues assigned to the given `username`. Simillar to `assignee_id` and mutually exclusive with `assignee_id`. In CE version `assignee_username` array should only contain a single value or an invalid param error will be returned otherwise. |
| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced][ce-14016] in GitLab 10.0)_ |
| `order_by` | string | no | Return issues ordered by `created_at` or `updated_at` fields. Default is `created_at` |
| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
@@ -221,7 +240,7 @@ Example response:
"id" : 9,
"name" : "Dr. Luella Kovacek"
},
- "labels" : [],
+ "labels" : ["foo", "bar"],
"upvotes": 4,
"downvotes": 0,
"merge_requests_count": 0,
@@ -240,8 +259,21 @@ Example response:
"human_time_estimate": null,
"human_total_time_spent": null
},
+ "has_tasks": true,
+ "task_status": "10 of 15 tasks completed",
"confidential": false,
- "discussion_locked": false
+ "discussion_locked": false,
+ "_links":{
+ "self":"http://example.com/api/v4/projects/4/issues/41",
+ "notes":"`http://example.com/`api/v4/projects/4/issues/41/notes",
+ "award_emoji":"http://example.com/api/v4/projects/4/issues/41/award_emoji",
+ "project":"http://example.com/api/v4/projects/4"
+ },
+ "subscribed": false,
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
+ }
}
]
```
@@ -277,10 +309,13 @@ GET /projects/:id/issues?confidential=true
| `iids[]` | Array[integer] | no | Return only the milestone having the given `iid` |
| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. |
+| `with_labels_details`| Boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:text_color`. Default is `false`. |
| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced][ce-13004] in GitLab 9.5. [Changed to snake_case][ce-18935] in GitLab 11.0)_ |
-| `author_id` | integer | no | Return issues created by the given user `id` _([Introduced][ce-13004] in GitLab 9.5)_ |
-| `assignee_id` | integer | no | Return issues assigned to the given user `id`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced][ce-13004] in GitLab 9.5)_ |
+| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. _([Introduced][ce-13004] in GitLab 9.5)_ |
+| `author_username` | string | no | Return issues created by the given `username`. Simillar to `author_id` and mutually exclusive with `author_id`. |
+| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced][ce-13004] in GitLab 9.5)_ |
+| `assignee_username` | Array[String] | no | Return issues assigned to the given `username`. Simillar to `assignee_id` and mutually exclusive with `assignee_id`. In CE version `assignee_username` array should only contain a single value or an invalid param error will be returned otherwise. |
| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced][ce-14016] in GitLab 10.0)_ |
| `order_by` | string | no | Return issues ordered by `created_at` or `updated_at` fields. Default is `created_at` |
| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
@@ -340,7 +375,7 @@ Example response:
"id" : 9,
"name" : "Dr. Luella Kovacek"
},
- "labels" : [],
+ "labels" : ["foo", "bar"],
"upvotes": 4,
"downvotes": 0,
"merge_requests_count": 0,
@@ -366,8 +401,21 @@ Example response:
"human_time_estimate": null,
"human_total_time_spent": null
},
+ "has_tasks": true,
+ "task_status": "10 of 15 tasks completed",
"confidential": false,
- "discussion_locked": false
+ "discussion_locked": false,
+ "_links":{
+ "self":"http://example.com/api/v4/projects/4/issues/41",
+ "notes":"`http://example.com/`api/v4/projects/4/issues/41/notes",
+ "award_emoji":"http://example.com/api/v4/projects/4/issues/41/award_emoji",
+ "project":"http://example.com/api/v4/projects/4"
+ },
+ "subscribed": false,
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
+ }
}
]
```
@@ -464,6 +512,10 @@ Example response:
"notes": "http://example.com/api/v4/projects/1/issues/2/notes",
"award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji",
"project": "http://example.com/api/v4/projects/1"
+ },
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
}
}
```
@@ -547,6 +599,10 @@ Example response:
"notes": "http://example.com/api/v4/projects/1/issues/2/notes",
"award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji",
"project": "http://example.com/api/v4/projects/1"
+ },
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
}
}
```
@@ -638,6 +694,10 @@ Example response:
"notes": "http://example.com/api/v4/projects/1/issues/2/notes",
"award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji",
"project": "http://example.com/api/v4/projects/1"
+ },
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
}
}
```
@@ -744,6 +804,10 @@ Example response:
"notes": "http://example.com/api/v4/projects/1/issues/2/notes",
"award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji",
"project": "http://example.com/api/v4/projects/1"
+ },
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
}
}
```
@@ -829,6 +893,10 @@ Example response:
"notes": "http://example.com/api/v4/projects/1/issues/2/notes",
"award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji",
"project": "http://example.com/api/v4/projects/1"
+ },
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
}
}
```
@@ -895,7 +963,11 @@ Example response:
"due_date": null,
"web_url": "http://example.com/example/example/issues/12",
"confidential": false,
- "discussion_locked": false
+ "discussion_locked": false,
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
+ }
}
```
@@ -993,7 +1065,11 @@ Example response:
"due_date": null,
"web_url": "http://example.com/example/example/issues/110",
"confidential": false,
- "discussion_locked": false
+ "discussion_locked": false,
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
+ }
},
"target_url": "https://gitlab.example.com/gitlab-org/gitlab-ci/issues/10",
"body": "Vel voluptas atque dicta mollitia adipisci qui at.",
diff --git a/doc/api/issues_statistics.md b/doc/api/issues_statistics.md
new file mode 100644
index 00000000000..82bc9c142cc
--- /dev/null
+++ b/doc/api/issues_statistics.md
@@ -0,0 +1,177 @@
+# Issues Statistics API
+
+Every API call to issues_statistics must be authenticated.
+
+If a user is not a member of a project and the project is private, a `GET`
+request on that project will result to a `404` status code.
+
+## Get issues statistics
+
+Gets issues count statistics on all issues the authenticated user has access to. By default it
+returns only issues created by the current user. To get all issues,
+use parameter `scope=all`.
+
+```
+GET /issues_statistics
+GET /issues_statistics?labels=foo
+GET /issues_statistics?labels=foo,bar
+GET /issues_statistics?labels=foo,bar&state=opened
+GET /issues_statistics?milestone=1.0.0
+GET /issues_statistics?milestone=1.0.0&state=opened
+GET /issues_statistics?iids[]=42&iids[]=43
+GET /issues_statistics?author_id=5
+GET /issues_statistics?assignee_id=5
+GET /issues_statistics?my_reaction_emoji=star
+GET /issues_statistics?search=foo&in=title
+GET /issues_statistics?confidential=true
+```
+
+| Attribute | Type | Required | Description |
+| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. |
+| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
+| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`. Defaults to `created_by_me` |
+| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. |
+| `author_username` | string | no | Return issues created by the given `username`. Similar to `author_id` and mutually exclusive with `author_id`. |
+| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. |
+| `assignee_username` | Array[String] | no | Return issues assigned to the given `username`. Similar to `assignee_id` and mutually exclusive with `assignee_id`. In CE version `assignee_username` array should only contain a single value or an invalid param error will be returned otherwise. |
+| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. |
+| `iids[]` | Array[integer] | no | Return only the issues having the given `iid` |
+| `search` | string | no | Search issues against their `title` and `description` |
+| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` |
+| `created_after` | datetime | no | Return issues created on or after the given time |
+| `created_before` | datetime | no | Return issues created on or before the given time |
+| `updated_after` | datetime | no | Return issues updated on or after the given time |
+| `updated_before` | datetime | no | Return issues updated on or before the given time |
+| `confidential ` | Boolean | no | Filter confidential or public issues. |
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/issues_statistics
+```
+
+Example response:
+
+```json
+{
+ "statistics": {
+ "counts": {
+ "all": 20,
+ "closed": 5,
+ "opened": 15
+ }
+ }
+}
+```
+
+## Get group issues statistics
+
+Gets issues count statistics for given group.
+
+```
+GET /groups/:id/issues_statistics
+GET /groups/:id/issues_statistics?labels=foo
+GET /groups/:id/issues_statistics?labels=foo,bar
+GET /groups/:id/issues_statistics?labels=foo,bar&state=opened
+GET /groups/:id/issues_statistics?milestone=1.0.0
+GET /groups/:id/issues_statistics?milestone=1.0.0&state=opened
+GET /groups/:id/issues_statistics?iids[]=42&iids[]=43
+GET /groups/:id/issues_statistics?search=issue+title+or+description
+GET /groups/:id/issues_statistics?author_id=5
+GET /groups/:id/issues_statistics?assignee_id=5
+GET /groups/:id/issues_statistics?my_reaction_emoji=star
+GET /groups/:id/issues_statistics?confidential=true
+```
+
+| Attribute | Type | Required | Description |
+| ------------------- | ---------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. |
+| `iids[]` | Array[integer] | no | Return only the issues having the given `iid` |
+| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
+| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`. |
+| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. |
+| `author_username` | string | no | Return issues created by the given `username`. Similar to `author_id` and mutually exclusive with `author_id`. |
+| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. |
+| `assignee_username` | Array[String] | no | Return issues assigned to the given `username`. Similar to `assignee_id` and mutually exclusive with `assignee_id`. In CE version `assignee_username` array should only contain a single value or an invalid param error will be returned otherwise. |
+| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. |
+| `search` | string | no | Search group issues against their `title` and `description` |
+| `created_after` | datetime | no | Return issues created on or after the given time |
+| `created_before` | datetime | no | Return issues created on or before the given time |
+| `updated_after` | datetime | no | Return issues updated on or after the given time |
+| `updated_before` | datetime | no | Return issues updated on or before the given time |
+| `confidential ` | Boolean | no | Filter confidential or public issues. |
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/4/issues_statistics
+```
+
+Example response:
+
+```json
+{
+ "statistics": {
+ "counts": {
+ "all": 20,
+ "closed": 5,
+ "opened": 15
+ }
+ }
+}
+```
+
+## Get project issues statistics
+
+Gets issues count statistics for given project.
+
+```
+GET /projects/:id/issues_statistics
+GET /projects/:id/issues_statistics?labels=foo
+GET /projects/:id/issues_statistics?labels=foo,bar
+GET /projects/:id/issues_statistics?labels=foo,bar&state=opened
+GET /projects/:id/issues_statistics?milestone=1.0.0
+GET /projects/:id/issues_statistics?milestone=1.0.0&state=opened
+GET /projects/:id/issues_statistics?iids[]=42&iids[]=43
+GET /projects/:id/issues_statistics?search=issue+title+or+description
+GET /projects/:id/issues_statistics?author_id=5
+GET /projects/:id/issues_statistics?assignee_id=5
+GET /projects/:id/issues_statistics?my_reaction_emoji=star
+GET /projects/:id/issues_statistics?confidential=true
+```
+
+| Attribute | Type | Required | Description |
+| ------------------- | ---------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `iids[]` | Array[integer] | no | Return only the milestone having the given `iid` |
+| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. |
+| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
+| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`. |
+| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. |
+| `author_username` | string | no | Return issues created by the given `username`. Similar to `author_id` and mutually exclusive with `author_id`. |
+| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. |
+| `assignee_username` | Array[String] | no | Return issues assigned to the given `username`. Similar to `assignee_id` and mutually exclusive with `assignee_id`. In CE version `assignee_username` array should only contain a single value or an invalid param error will be returned otherwise. |
+| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. |
+| `search` | string | no | Search project issues against their `title` and `description` |
+| `created_after` | datetime | no | Return issues created on or after the given time |
+| `created_before` | datetime | no | Return issues created on or before the given time |
+| `updated_after` | datetime | no | Return issues updated on or after the given time |
+| `updated_before` | datetime | no | Return issues updated on or before the given time |
+| `confidential ` | Boolean | no | Filter confidential or public issues. |
+
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/4/issues_statistics
+```
+
+Example response:
+
+```json
+{
+ "statistics": {
+ "counts": {
+ "all": 20,
+ "closed": 5,
+ "opened": 15
+ }
+ }
+}
+```
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
index 877cd99723a..72973b69117 100644
--- a/doc/api/jobs.md
+++ b/doc/api/jobs.md
@@ -32,6 +32,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "allow_failure": false,
"created_at": "2015-12-24T15:51:21.727Z",
"started_at": "2015-12-24T17:54:24.729Z",
"finished_at": "2015-12-24T17:54:24.921Z",
@@ -81,6 +82,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "allow_failure": false,
"created_at": "2015-12-24T15:51:21.802Z",
"started_at": "2015-12-24T17:54:27.722Z",
"finished_at": "2015-12-24T17:54:27.895Z",
@@ -165,6 +167,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "allow_failure": false,
"created_at": "2015-12-24T15:51:21.727Z",
"started_at": "2015-12-24T17:54:24.729Z",
"finished_at": "2015-12-24T17:54:24.921Z",
@@ -214,6 +217,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "allow_failure": false,
"created_at": "2015-12-24T15:51:21.802Z",
"started_at": "2015-12-24T17:54:27.722Z",
"finished_at": "2015-12-24T17:54:27.895Z",
@@ -296,6 +300,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "allow_failure": false,
"created_at": "2015-12-24T15:51:21.880Z",
"started_at": "2015-12-24T17:54:30.733Z",
"finished_at": "2015-12-24T17:54:31.198Z",
@@ -341,30 +346,58 @@ Example of response
> **Notes**:
>
> - [Introduced][ce-2893] in GitLab 8.5.
+> - The use of `CI_JOB_TOKEN` in the artifacts download API was [introduced][ee-2346]
+> in [GitLab Premium][ee] 9.5.
-Get job artifacts of a project.
+Get the job's artifacts zipped archive of a project.
```
GET /projects/:id/jobs/:job_id/artifacts
```
-| Attribute | Type | Required | Description |
-|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
-| `job_id` | integer | yes | ID of a job. |
+| Attribute | Type | Required | Description |
+|-------------|----------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | yes | ID of a job. |
+| `job_token` **[PREMIUM]** | string | no | To be used with [triggers] for multi-project pipelines. It should be invoked only inside `.gitlab-ci.yml`. Its value is always `$CI_JOB_TOKEN`. |
-Example requests:
+Example request using the `PRIVATE-TOKEN` header:
```sh
-curl --location --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/8/artifacts"
+curl --output artifacts.zip --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/42/artifacts"
```
+To use this in a [`script` definition](../ci/yaml/README.md#script) inside
+`.gitlab-ci.yml` **[PREMIUM]**, you can use either:
+
+- The `JOB-TOKEN` header with the GitLab-provided `CI_JOB_TOKEN` variable.
+ For example, the following job will download the artifacts of the job with ID
+ `42`. Note that the command is wrapped into single quotes since it contains a
+ colon (`:`):
+
+ ```yaml
+ artifact_download:
+ stage: test
+ script:
+ - 'curl --location --output artifacts.zip --header "JOB-TOKEN: $CI_JOB_TOKEN" "https://gitlab.example.com/api/v4/projects/1/jobs/42/artifacts"'
+ ```
+
+- Or the `job_token` attribute with the GitLab-provided `CI_JOB_TOKEN` variable.
+ For example, the following job will download the artifacts of the job with ID `42`:
+
+ ```yaml
+ artifact_download:
+ stage: test
+ script:
+ - 'curl --location --output artifacts.zip "https://gitlab.example.com/api/v4/projects/1/jobs/42/artifacts?job_token=$CI_JOB_TOKEN"'
+ ```
+
Possible response status codes:
| Status | Description |
|-----------|---------------------------------|
-| 200 | Serves the artifacts file |
-| 404 | Build not found or no artifacts |
+| 200 | Serves the artifacts file. |
+| 404 | Build not found or no artifacts.|
[ce-2893]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2893
@@ -373,9 +406,13 @@ Possible response status codes:
> **Notes**:
>
> - [Introduced][ce-5347] in GitLab 8.10.
+> - The use of `CI_JOB_TOKEN` in the artifacts download API was [introduced][ee-2346]
+> in [GitLab Premium][ee] 9.5.
-Download the artifacts archive from the given reference name and job provided the
-job finished successfully.
+Download the artifacts zipped archive from the given reference name and job,
+provided the job finished successfully. This is the same as
+[getting the job's artifacts](#get-job-artifacts), but by defining the job's
+name instead of its ID.
```
GET /projects/:id/jobs/artifacts/:ref_name/download?job=name
@@ -383,24 +420,51 @@ GET /projects/:id/jobs/artifacts/:ref_name/download?job=name
Parameters
-| Attribute | Type | Required | Description |
-|------------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
-| `ref_name` | string | yes | Branch or tag name in repository. HEAD or SHA references are not supported. |
-| `job` | string | yes | The name of the job. |
+| Attribute | Type | Required | Description |
+|-------------|----------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `ref_name` | string | yes | Branch or tag name in repository. HEAD or SHA references are not supported. |
+| `job` | string | yes | The name of the job. |
+| `job_token` **[PREMIUM]** | string | no | To be used with [triggers] for multi-project pipelines. It should be invoked only inside `.gitlab-ci.yml`. Its value is always `$CI_JOB_TOKEN`. |
-Example requests:
+Example request using the `PRIVATE-TOKEN` header:
```sh
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/download?job=test"
```
+To use this in a [`script` definition](../ci/yaml/README.md#script) inside
+`.gitlab-ci.yml` **[PREMIUM]**, you can use either:
+
+- The `JOB-TOKEN` header with the GitLab-provided `CI_JOB_TOKEN` variable.
+ For example, the following job will download the artifacts of the `test` job
+ of the `master` branch. Note that the command is wrapped into single quotes
+ since it contains a colon (`:`):
+
+ ```yaml
+ artifact_download:
+ stage: test
+ script:
+ - 'curl --location --output artifacts.zip --header "JOB-TOKEN: $CI_JOB_TOKEN" "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/jobs/artifacts/master/download?job=test"'
+ ```
+
+- Or the `job_token` attribute with the GitLab-provided `CI_JOB_TOKEN` variable.
+ For example, the following job will download the artifacts of the `test` job
+ of the `master` branch:
+
+ ```yaml
+ artifact_download:
+ stage: test
+ script:
+ - 'curl --location --output artifacts.zip "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/jobs/artifacts/master/download?job=test&job_token=$CI_JOB_TOKEN"'
+ ```
+
Possible response status codes:
| Status | Description |
|-----------|---------------------------------|
-| 200 | Serves the artifacts file |
-| 404 | Build not found or no artifacts |
+| 200 | Serves the artifacts file. |
+| 404 | Build not found or no artifacts.|
[ce-5347]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5347
@@ -409,7 +473,7 @@ Possible response status codes:
> Introduced in GitLab 10.0
Download a single artifact file from a job with a specified ID from within
-the job's artifacts archive. The file is extracted from the archive and
+the job's artifacts zipped archive. The file is extracted from the archive and
streamed to the client.
```
@@ -528,6 +592,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "allow_failure": false,
"created_at": "2016-01-11T10:13:33.506Z",
"started_at": "2016-01-11T10:14:09.526Z",
"finished_at": null,
@@ -576,6 +641,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "allow_failure": false,
"created_at": "2016-01-11T10:13:33.506Z",
"started_at": null,
"finished_at": null,
@@ -628,6 +694,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "allow_failure": false,
"download_url": null,
"id": 42,
"name": "rubocop",
@@ -681,6 +748,7 @@ Example response:
"title": "Test the CI integration."
},
"coverage": null,
+ "allow_failure": false,
"download_url": null,
"id": 42,
"name": "rubocop",
@@ -757,6 +825,7 @@ Example of response
"title": "Test the CI integration."
},
"coverage": null,
+ "allow_failure": false,
"created_at": "2016-01-11T10:13:33.506Z",
"started_at": null,
"finished_at": null,
@@ -773,3 +842,7 @@ Example of response
"user": null
}
```
+
+[ee]: https://about.gitlab.com/pricing/
+[ee-2346]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2346
+[triggers]: ../ci/triggers/README.md#when-a-pipeline-depends-on-the-artifacts-of-another-pipeline-premium
diff --git a/doc/api/license.md b/doc/api/license.md
new file mode 100644
index 00000000000..2a8de64bdbf
--- /dev/null
+++ b/doc/api/license.md
@@ -0,0 +1,176 @@
+# License **[CORE ONLY]**
+
+In order to interact with license endpoints, you need to authenticate yourself
+as an admin.
+
+## Retrieve information about the current license
+
+```
+GET /license
+```
+
+```json
+{
+ "id": 2,
+ "plan": "gold",
+ "created_at": "2018-02-27T23:21:58.674Z",
+ "starts_at": "2018-01-27",
+ "expires_at": "2022-01-27",
+ "historical_max": 300,
+ "expired": false,
+ "overage": 200,
+ "user_limit": 100,
+ "active_users": 300,
+ "licensee": {
+ "Name": "John Doe1"
+ },
+ "add_ons": {
+ "GitLab_FileLocks": 1,
+ "GitLab_Auditor_User": 1
+ }
+}
+```
+
+## Retrieve information about all licenses
+
+```
+GET /licenses
+```
+
+```json
+[
+ {
+ "id": 1,
+ "plan": "silver",
+ "created_at": "2018-02-27T23:21:58.674Z",
+ "starts_at": "2018-01-27",
+ "expires_at": "2022-01-27",
+ "historical_max": 300,
+ "expired": false,
+ "overage": 200,
+ "user_limit": 100,
+ "licensee": {
+ "Name": "John Doe1"
+ },
+ "add_ons": {
+ "GitLab_FileLocks": 1,
+ "GitLab_Auditor_User": 1
+ }
+ },
+ {
+ "id": 2,
+ "plan": "gold",
+ "created_at": "2018-02-27T23:21:58.674Z",
+ "starts_at": "2018-01-27",
+ "expires_at": "2022-01-27",
+ "historical_max": 300,
+ "expired": false,
+ "overage": 200,
+ "user_limit": 100,
+ "licensee": {
+ "Name": "Doe John"
+ },
+ "add_ons": {
+ "GitLab_FileLocks": 1,
+ }
+ }
+]
+```
+
+Overage is the difference between the number of active users and the licensed number of users.
+This is calculated differently depending on whether the license has expired or not.
+
+- If the license has expired, it uses the historical maximum active user count (`historical_max`).
+- If the license has not expired, it uses the current active users count.
+
+Returns:
+
+- `200 OK` with response containing the licenses in JSON format. This will be an empty JSON array if there are no licenses.
+- `403 Forbidden` if the current user in not permitted to read the licenses.
+
+## Add a new license
+
+```
+POST /license
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `license` | string | yes | The license string |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/license?license=eyJkYXRhIjoiMHM5Q...S01Udz09XG4ifQ=="
+```
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "plan": "gold",
+ "created_at": "2018-02-27T23:21:58.674Z",
+ "starts_at": "2018-01-27",
+ "expires_at": "2022-01-27",
+ "historical_max": 300,
+ "expired": false,
+ "overage": 200,
+ "user_limit": 100,
+ "active_users": 300,
+ "licensee": {
+ "Name": "John Doe1"
+ },
+ "add_ons": {
+ "GitLab_FileLocks": 1,
+ "GitLab_Auditor_User": 1
+ }
+}
+```
+
+Returns:
+
+- `201 Created` if the license is successfully added.
+- `400 Bad Request` if the license couldn't be added, with an error message explaining the reason.
+
+
+## Delete a license
+
+```
+DELETE /license/:id
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer | yes | ID of the GitLab license. |
+
+```bash
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/license/:id"
+```
+
+Example response:
+
+```json
+{
+ "id": 2,
+ "plan": "gold",
+ "created_at": "2018-02-27T23:21:58.674Z",
+ "starts_at": "2018-01-27",
+ "expires_at": "2022-01-27",
+ "historical_max": 300,
+ "expired": false,
+ "overage": 200,
+ "user_limit": 100,
+ "licensee": {
+ "Name": "John Doe"
+ },
+ "add_ons": {
+ "GitLab_FileLocks": 1,
+ "GitLab_Auditor_User": 1
+ }
+}
+```
+
+Returns:
+
+- `204 No Content` if the license is successfully deleted.
+- `403 Forbidden` if the current user in not permitted to delete the license.
+- `404 Not Found` if the license to delete could not be found.
diff --git a/doc/api/license_templates.md b/doc/api/license_templates.md
new file mode 100644
index 00000000000..1b68af9ce31
--- /dev/null
+++ b/doc/api/license_templates.md
@@ -0,0 +1,5 @@
+---
+redirect_to: 'templates/licenses.md'
+---
+
+This document was moved to [another location](templates/licenses.md).
diff --git a/doc/api/managed_licenses.md b/doc/api/managed_licenses.md
new file mode 100644
index 00000000000..47b193111b6
--- /dev/null
+++ b/doc/api/managed_licenses.md
@@ -0,0 +1,136 @@
+# Managed Licenses API **[ULTIMATE]**
+
+## List managed licenses
+
+Get all managed licenses for a given project.
+
+```
+GET /projects/:id/managed_licenses
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ------- | -------- | --------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/managed_licenses
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 1,
+ "name": "MIT",
+ "approval_status": "approved"
+ },
+ {
+ "id": 3,
+ "name": "ISC",
+ "approval_status": "blacklisted"
+ }
+]
+```
+
+## Show an existing managed license
+
+Shows an existing managed license.
+
+```
+GET /projects/:id/managed_licenses/:managed_license_id
+```
+
+| Attribute | Type | Required | Description |
+| --------------- | ------- | --------------------------------- | ------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `managed_license_id` | integer/string | yes | The ID or URL-encoded name of the license belonging to the project |
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/managed_licenses/6"
+```
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "name": "MIT",
+ "approval_status": "blacklisted"
+}
+```
+
+## Create a new managed license
+
+Creates a new managed license for the given project with the given name and approval status.
+
+```
+POST /projects/:id/managed_licenses
+```
+
+| Attribute | Type | Required | Description |
+| ------------- | ------- | -------- | ---------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `name` | string | yes | The name of the managed license |
+| `approval_status` | string | yes | The approval status. "approved" or "blacklisted" |
+
+```bash
+curl --data "name=MIT&approval_status=blacklisted" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/managed_licenses"
+```
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "name": "MIT",
+ "approval_status": "approved"
+}
+```
+
+## Delete a managed license
+
+Deletes a managed license with a given id.
+
+```
+DELETE /projects/:id/managed_licenses/:managed_license_id
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ------- | -------- | --------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `managed_license_id` | integer/string | yes | The ID or URL-encoded name of the license belonging to the project |
+
+```bash
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/managed_licenses/4"
+```
+
+When successful, it replies with an HTTP 204 response.
+
+## Edit an existing managed license
+
+Updates an existing managed license with a new approval status.
+
+```
+PATCH /projects/:id/managed_licenses/:managed_license_id
+```
+
+| Attribute | Type | Required | Description |
+| --------------- | ------- | --------------------------------- | ------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `managed_license_id` | integer/string | yes | The ID or URL-encoded name of the license belonging to the project |
+| `approval_status` | string | yes | The approval status. "approved" or "blacklisted" |
+
+```bash
+curl --request PATCH --data "approval_status=blacklisted" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/managed_licenses/6"
+```
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "name": "MIT",
+ "approval_status": "blacklisted"
+}
+```
diff --git a/doc/api/members.md b/doc/api/members.md
index 0593d2c20ea..8784d577f99 100644
--- a/doc/api/members.md
+++ b/doc/api/members.md
@@ -62,7 +62,9 @@ Example response:
## List all members of a group or project including inherited members
Gets a list of group or project members viewable by the authenticated user, including inherited members through ancestor groups.
-Returns multiple times the same user (with different member attributes) when the user is a member of the project/group and of one or more ancestor group.
+When a user is a member of the project/group and of one or more ancestor groups the user is returned only once with the project access_level (if exists)
+or the access_level for the user in the first group which he belongs to in the project groups ancestors chain.
+**Note:** We plan to [change](https://gitlab.com/gitlab-org/gitlab-ce/issues/62284) this behavior to return highest access_level instead.
```
GET /groups/:id/members/all
diff --git a/doc/api/merge_request_approvals.md b/doc/api/merge_request_approvals.md
new file mode 100644
index 00000000000..ddac81328b9
--- /dev/null
+++ b/doc/api/merge_request_approvals.md
@@ -0,0 +1,425 @@
+# Merge request approvals API **[STARTER]**
+
+Configuration for approvals on all Merge Requests (MR) in the project. Must be authenticated for all endpoints.
+
+## Project-level MR approvals
+
+### Get Configuration
+
+>**Note:** This API endpoint is only available on 10.6 Starter and above.
+
+You can request information about a project's approval configuration using the
+following endpoint:
+
+```
+GET /projects/:id/approvals
+```
+
+**Parameters:**
+
+| Attribute | Type | Required | Description |
+| --------- | ------- | -------- | ------------------- |
+| `id` | integer | yes | The ID of a project |
+
+```json
+{
+ "approvers": [
+ {
+ "user": {
+ "id": 5,
+ "name": "John Doe6",
+ "username": "user5",
+ "state":"active","avatar_url":"https://www.gravatar.com/avatar/4aea8cf834ed91844a2da4ff7ae6b491?s=80\u0026d=identicon","web_url":"http://localhost/user5"
+ }
+ }
+ ],
+ "approver_groups": [
+ {
+ "group": {
+ "id": 1,
+ "name": "group1",
+ "path": "group1",
+ "description": "",
+ "visibility": "public",
+ "lfs_enabled": false,
+ "avatar_url": null,
+ "web_url": "http://localhost/groups/group1",
+ "request_access_enabled": false,
+ "full_name": "group1",
+ "full_path": "group1",
+ "parent_id": null,
+ "ldap_cn": null,
+ "ldap_access": null
+ }
+ }
+ ],
+ "approvals_before_merge": 2,
+ "reset_approvals_on_push": true,
+ "disable_overriding_approvers_per_merge_request": false
+}
+```
+
+### Change configuration
+
+>**Note:** This API endpoint is only available on 10.6 Starter and above.
+
+If you are allowed to, you can change approval configuration using the following
+endpoint:
+
+```
+POST /projects/:id/approvals
+```
+
+**Parameters:**
+
+| Attribute | Type | Required | Description |
+| ------------------------------------------------ | ------- | -------- | ---------------------------------------------------------- |
+| `id` | integer | yes | The ID of a project |
+| `approvals_before_merge` | integer | no | How many approvals are required before an MR can be merged |
+| `reset_approvals_on_push` | boolean | no | Reset approvals on a new push |
+| `disable_overriding_approvers_per_merge_request` | boolean | no | Allow/Disallow overriding approvers per MR |
+| `merge_requests_author_approval` | boolean | no | Allow/Disallow authors be able to self approve merge requests |
+
+```json
+{
+ "approvers": [
+ {
+ "user": {
+ "id": 5,
+ "name": "John Doe6",
+ "username": "user5",
+ "state":"active","avatar_url":"https://www.gravatar.com/avatar/4aea8cf834ed91844a2da4ff7ae6b491?s=80\u0026d=identicon","web_url":"http://localhost/user5"
+ }
+ }
+ ],
+ "approver_groups": [
+ {
+ "group": {
+ "id": 1,
+ "name": "group1",
+ "path": "group1",
+ "description": "",
+ "visibility": "public",
+ "lfs_enabled": false,
+ "avatar_url": null,
+ "web_url": "http://localhost/groups/group1",
+ "request_access_enabled": false,
+ "full_name": "group1",
+ "full_path": "group1",
+ "parent_id": null,
+ "ldap_cn": null,
+ "ldap_access": null
+ }
+ }
+ ],
+ "approvals_before_merge": 2,
+ "reset_approvals_on_push": true,
+ "disable_overriding_approvers_per_merge_request": false,
+ "merge_requests_author_approval": false
+}
+```
+
+### Change allowed approvers
+
+>**Note:** This API endpoint is only available on 10.6 Starter and above.
+
+If you are allowed to, you can change approvers and approver groups using
+the following endpoint:
+
+```
+PUT /projects/:id/approvers
+```
+
+**Important:** Approvers and groups not in the request will be **removed**
+
+**Parameters:**
+
+| Attribute | Type | Required | Description |
+| -------------------- | ------- | -------- | --------------------------------------------------- |
+| `id` | integer | yes | The ID of a project |
+| `approver_ids` | Array | yes | An array of User IDs that can approve MRs |
+| `approver_group_ids` | Array | yes | An array of Group IDs whose members can approve MRs |
+
+```json
+{
+ "approvers": [
+ {
+ "user": {
+ "id": 5,
+ "name": "John Doe6",
+ "username": "user5",
+ "state":"active","avatar_url":"https://www.gravatar.com/avatar/4aea8cf834ed91844a2da4ff7ae6b491?s=80\u0026d=identicon","web_url":"http://localhost/user5"
+ }
+ }
+ ],
+ "approver_groups": [
+ {
+ "group": {
+ "id": 1,
+ "name": "group1",
+ "path": "group1",
+ "description": "",
+ "visibility": "public",
+ "lfs_enabled": false,
+ "avatar_url": null,
+ "web_url": "http://localhost/groups/group1",
+ "request_access_enabled": false,
+ "full_name": "group1",
+ "full_path": "group1",
+ "parent_id": null,
+ "ldap_cn": null,
+ "ldap_access": null
+ }
+ }
+ ],
+ "approvals_before_merge": 2,
+ "reset_approvals_on_push": true,
+ "disable_overriding_approvers_per_merge_request": false
+}
+```
+
+
+## Merge Request-level MR approvals
+
+Configuration for approvals on a specific Merge Request. Must be authenticated for all endpoints.
+
+### Get Configuration
+
+>**Note:** This API endpoint is only available on 8.9 Starter and above.
+
+You can request information about a merge request's approval status using the
+following endpoint:
+
+```
+GET /projects/:id/merge_requests/:merge_request_iid/approvals
+```
+
+**Parameters:**
+
+| Attribute | Type | Required | Description |
+|---------------------|---------|----------|---------------------|
+| `id` | integer | yes | The ID of a project |
+| `merge_request_iid` | integer | yes | The IID of MR |
+
+```json
+{
+ "id": 5,
+ "iid": 5,
+ "project_id": 1,
+ "title": "Approvals API",
+ "description": "Test",
+ "state": "opened",
+ "created_at": "2016-06-08T00:19:52.638Z",
+ "updated_at": "2016-06-08T21:20:42.470Z",
+ "merge_status": "cannot_be_merged",
+ "approvals_required": 2,
+ "approvals_left": 1,
+ "approved_by": [
+ {
+ "user": {
+ "name": "Administrator",
+ "username": "root",
+ "id": 1,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
+ "web_url": "http://localhost:3000/u/root"
+ }
+ }
+ ],
+ "approvers": [],
+ "approver_groups": []
+}
+```
+
+### Change approval configuration
+
+>**Note:** This API endpoint is only available on 10.6 Starter and above.
+
+If you are allowed to, you can change `approvals_required` using the following
+endpoint:
+
+```
+POST /projects/:id/merge_requests/:merge_request_iid/approvals
+```
+
+**Parameters:**
+
+| Attribute | Type | Required | Description |
+|----------------------|---------|----------|--------------------------------------------|
+| `id` | integer | yes | The ID of a project |
+| `merge_request_iid` | integer | yes | The IID of MR |
+| `approvals_required` | integer | yes | Approvals required before MR can be merged |
+
+
+```json
+{
+ "id": 5,
+ "iid": 5,
+ "project_id": 1,
+ "title": "Approvals API",
+ "description": "Test",
+ "state": "opened",
+ "created_at": "2016-06-08T00:19:52.638Z",
+ "updated_at": "2016-06-08T21:20:42.470Z",
+ "merge_status": "cannot_be_merged",
+ "approvals_required": 2,
+ "approvals_left": 2,
+ "approved_by": [],
+ "approvers": [],
+ "approver_groups": []
+}
+```
+
+### Change allowed approvers for Merge Request
+
+>**Note:** This API endpoint is only available on 10.6 Starter and above.
+
+If you are allowed to, you can change approvers and approver groups using
+the following endpoint:
+
+```
+PUT /projects/:id/merge_requests/:merge_request_iid/approvers
+```
+
+**Important:** Approvers and groups not in the request will be **removed**
+
+**Parameters:**
+
+| Attribute | Type | Required | Description |
+|----------------------|---------|----------|-----------------------------------------------------------|
+| `id` | integer | yes | The ID of a project |
+| `merge_request_iid` | integer | yes | The IID of MR |
+| `approver_ids` | Array | yes | An array of User IDs that can approve the MR |
+| `approver_group_ids` | Array | yes | An array of Group IDs whose members can approve the MR |
+
+```json
+{
+ "id": 5,
+ "iid": 5,
+ "project_id": 1,
+ "title": "Approvals API",
+ "description": "Test",
+ "state": "opened",
+ "created_at": "2016-06-08T00:19:52.638Z",
+ "updated_at": "2016-06-08T21:20:42.470Z",
+ "merge_status": "cannot_be_merged",
+ "approvals_required": 2,
+ "approvals_left": 2,
+ "approved_by": [],
+ "approvers": [
+ {
+ "user": {
+ "name": "Administrator",
+ "username": "root",
+ "id": 1,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
+ "web_url": "http://localhost:3000/u/root"
+ }
+ }
+ ],
+ "approver_groups": [
+ {
+ "group": {
+ "id": 5,
+ "name": "group1",
+ "path": "group1",
+ "description": "",
+ "visibility": "public",
+ "lfs_enabled": false,
+ "avatar_url": null,
+ "web_url": "http://localhost/groups/group1",
+ "request_access_enabled": false,
+ "full_name": "group1",
+ "full_path": "group1",
+ "parent_id": null,
+ "ldap_cn": null,
+ "ldap_access": null
+ }
+ }
+ ]
+}
+```
+
+## Approve Merge Request
+
+>**Note:** This API endpoint is only available on 8.9 Starter and above.
+
+If you are allowed to, you can approve a merge request using the following
+endpoint:
+
+```
+POST /projects/:id/merge_requests/:merge_request_iid/approve
+```
+
+**Parameters:**
+
+| Attribute | Type | Required | Description |
+|---------------------|---------|----------|-------------------------|
+| `id` | integer | yes | The ID of a project |
+| `merge_request_iid` | integer | yes | The IID of MR |
+| `sha` | string | no | The HEAD of the MR |
+| `approval_password` **[STARTER]** | string | no | Current user's password. Required if [**Require user password to approve**](../user/project/merge_requests/merge_request_approvals.md#require-authentication-when-approving-a-merge-request-starter) is enabled in the project settings. |
+
+The `sha` parameter works in the same way as
+when [accepting a merge request](merge_requests.md#accept-mr): if it is passed, then it must
+match the current HEAD of the merge request for the approval to be added. If it
+does not match, the response code will be `409`.
+
+```json
+{
+ "id": 5,
+ "iid": 5,
+ "project_id": 1,
+ "title": "Approvals API",
+ "description": "Test",
+ "state": "opened",
+ "created_at": "2016-06-08T00:19:52.638Z",
+ "updated_at": "2016-06-09T21:32:14.105Z",
+ "merge_status": "can_be_merged",
+ "approvals_required": 2,
+ "approvals_left": 0,
+ "approved_by": [
+ {
+ "user": {
+ "name": "Administrator",
+ "username": "root",
+ "id": 1,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
+ "web_url": "http://localhost:3000/u/root"
+ }
+ },
+ {
+ "user": {
+ "name": "Nico Cartwright",
+ "username": "ryley",
+ "id": 2,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/cf7ad14b34162a76d593e3affca2adca?s=80\u0026d=identicon",
+ "web_url": "http://localhost:3000/u/ryley"
+ }
+ }
+ ],
+ "approvers": [],
+ "approver_groups": []
+}
+```
+
+## Unapprove Merge Request
+
+>**Note:** This API endpoint is only available on 9.0 Starter and above.
+
+If you did approve a merge request, you can unapprove it using the following
+endpoint:
+
+```
+POST /projects/:id/merge_requests/:merge_request_iid/unapprove
+```
+
+**Parameters:**
+
+| Attribute | Type | Required | Description |
+|---------------------|---------|----------|---------------------|
+| `id` | integer | yes | The ID of a project |
+| `merge_request_iid` | integer | yes | The IID of MR |
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index ed4b6281acc..dd7810c3403 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -93,6 +93,14 @@ Parameters:
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
+ "assignees": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"source_project_id": 2,
"target_project_id": 3,
"labels": [
@@ -130,7 +138,11 @@ Parameters:
"human_time_estimate": null,
"human_total_time_spent": null
},
- "squash": false
+ "squash": false,
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
+ }
}
]
```
@@ -227,6 +239,14 @@ Parameters:
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
+ "assignees": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"source_project_id": 2,
"target_project_id": 3,
"labels": [
@@ -264,7 +284,11 @@ Parameters:
"human_time_estimate": null,
"human_total_time_spent": null
},
- "squash": false
+ "squash": false,
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
+ }
}
]
```
@@ -351,6 +375,14 @@ Parameters:
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
+ "assignees": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"source_project_id": 2,
"target_project_id": 3,
"labels": [
@@ -386,7 +418,11 @@ Parameters:
"human_time_estimate": null,
"human_total_time_spent": null
},
- "squash": false
+ "squash": false,
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
+ }
}
]
```
@@ -445,6 +481,14 @@ Parameters:
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
+ "assignees": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"source_project_id": 2,
"target_project_id": 3,
"labels": [
@@ -513,7 +557,11 @@ Parameters:
"start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
},
"diverged_commits_count": 2,
- "rebase_in_progress": false
+ "rebase_in_progress": false,
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
+ }
}
```
@@ -547,7 +595,7 @@ Parameters:
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/10fc7f102be8de7657fb4d80898bbfe3?s=80&d=identicon",
"web_url": "http://localhost/user2"
- },
+ }
]
```
@@ -629,6 +677,14 @@ Parameters:
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40&d=identicon",
"web_url" : "https://gitlab.example.com/root"
},
+ "assignees": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"source_project_id": 4,
"target_project_id": 4,
"labels": [ ],
@@ -662,7 +718,11 @@ Parameters:
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
- }
+ },
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
+ },
"changes": [
{
"old_path": "VERSION",
@@ -718,6 +778,7 @@ POST /projects/:id/merge_requests
| `target_branch` | string | yes | The target branch |
| `title` | string | yes | Title of MR |
| `assignee_id` | integer | no | Assignee user ID |
+| `assignee_ids` | Array[integer] | no | The ID of the user(s) to assign the MR to. Set to `0` or provide an empty value to unassign all assignees. |
| `description` | string | no | Description of MR |
| `target_project_id` | integer | no | The target project (numeric id) |
| `labels` | string | no | Labels for MR as a comma-separated list |
@@ -824,7 +885,11 @@ POST /projects/:id/merge_requests
"head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
"start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
},
- "diverged_commits_count": 2
+ "diverged_commits_count": 2,
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
+ }
}
```
@@ -843,6 +908,7 @@ PUT /projects/:id/merge_requests/:merge_request_iid
| `target_branch` | string | no | The target branch |
| `title` | string | no | Title of MR |
| `assignee_id` | integer | no | The ID of the user to assign the merge request to. Set to `0` or provide an empty value to unassign all assignees. |
+| `assignee_ids` | Array[integer] | no | The ID of the user(s) to assign the MR to. Set to `0` or provide an empty value to unassign all assignees. |
| `milestone_id` | integer | no | The global ID of a milestone to assign the merge request to. Set to `0` or provide an empty value to unassign a milestone.|
| `labels` | string | no | Comma-separated label names for a merge request. Set to an empty string to unassign all labels. |
| `description` | string | no | Description of MR |
@@ -885,6 +951,14 @@ Must include at least one non-required attribute from above.
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
+ "assignees": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"source_project_id": 2,
"target_project_id": 3,
"labels": [
@@ -952,7 +1026,11 @@ Must include at least one non-required attribute from above.
"head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
"start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
},
- "diverged_commits_count": 2
+ "diverged_commits_count": 2,
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
+ }
}
```
@@ -1030,6 +1108,14 @@ Parameters:
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
+ "assignees": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"source_project_id": 2,
"target_project_id": 3,
"labels": [
@@ -1097,7 +1183,11 @@ Parameters:
"head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
"start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
},
- "diverged_commits_count": 2
+ "diverged_commits_count": 2,
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
+ }
}
```
@@ -1180,6 +1270,14 @@ Parameters:
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
+ "assignees": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"source_project_id": 2,
"target_project_id": 3,
"labels": [
@@ -1247,7 +1345,11 @@ Parameters:
"head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
"start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
},
- "diverged_commits_count": 2
+ "diverged_commits_count": 2,
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
+ }
}
```
@@ -1283,7 +1385,7 @@ If the rebase operation is ongoing, the response will include the following:
```json
{
- "rebase_in_progress": true
+ "rebase_in_progress": true,
"merge_error": null
}
```
@@ -1294,7 +1396,7 @@ the following:
```json
{
"rebase_in_progress": false,
- "merge_error": null,
+ "merge_error": null
}
```
@@ -1303,7 +1405,7 @@ If the rebase operation fails, the response will include the following:
```json
{
"rebase_in_progress": false,
- "merge_error": "Rebase failed. Please rebase locally",
+ "merge_error": "Rebase failed. Please rebase locally"
}
```
@@ -1436,6 +1538,14 @@ Example response:
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
+ "assignees": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"source_project_id": 2,
"target_project_id": 3,
"labels": [
@@ -1502,7 +1612,11 @@ Example response:
"head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
"start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
},
- "diverged_commits_count": 2
+ "diverged_commits_count": 2,
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
+ }
}
```
@@ -1557,6 +1671,14 @@ Example response:
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
+ "assignees": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"source_project_id": 2,
"target_project_id": 3,
"labels": [
@@ -1623,7 +1745,11 @@ Example response:
"head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
"start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
},
- "diverged_commits_count": 2
+ "diverged_commits_count": 2,
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
+ }
}
```
@@ -1698,6 +1824,14 @@ Example response:
"avatar_url": "http://www.gravatar.com/avatar/733005fcd7e6df12d2d8580171ccb966?s=80&d=identicon",
"web_url": "https://gitlab.example.com/barrett.krajcik"
},
+ "assignees": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"source_project_id": 3,
"target_project_id": 3,
"labels": [],
diff --git a/doc/api/milestones.md b/doc/api/milestones.md
index 3b76c19dc07..90d8c033cd6 100644
--- a/doc/api/milestones.md
+++ b/doc/api/milestones.md
@@ -92,7 +92,7 @@ Parameters:
- `description` (optional) - The description of a milestone
- `due_date` (optional) - The due date of the milestone
- `start_date` (optional) - The start date of the milestone
-- `state_event` (optional) - The state event of the milestone (close|activate)
+- `state_event` (optional) - The state event of the milestone (close or activate)
## Delete project milestone
diff --git a/doc/api/notes.md b/doc/api/notes.md
index c351ee13d9a..c09129c22d4 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -1,6 +1,13 @@
# Notes API
-Notes are comments on snippets, issues or merge requests.
+Notes are comments on:
+
+- Snippets
+- Issues
+- Merge requests
+- Epics **[ULTIMATE]**
+
+This includes system notes, which are notes about changes to the object (for example, when a milestone changes, there will be a corresponding system note). Label notes are not part of this API, but recorded as separate events in [resource label events](resource_label_events.md).
## Notes pagination
@@ -388,3 +395,126 @@ Parameters:
```bash
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/7/notes/1602
```
+
+## Epics **[ULTIMATE]**
+
+### List all epic notes
+
+Gets a list of all notes for a single epic. Epic notes are comments users can post to an epic.
+
+```
+GET /groups/:id/epics/:epic_id/notes
+GET /groups/:id/epics/:epic_id/notes?sort=asc&order_by=updated_at
+```
+
+| Attribute | Type | Required | Description |
+| ------------------- | ---------------- | ---------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
+| `epic_id` | integer | yes | The ID of a group epic |
+| `sort` | string | no | Return epic notes sorted in `asc` or `desc` order. Default is `desc` |
+| `order_by` | string | no | Return epic notes ordered by `created_at` or `updated_at` fields. Default is `created_at` |
+
+```bash
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/epics/11/notes
+```
+
+### Get single epic note
+
+Returns a single note for a given epic.
+
+```
+GET /groups/:id/epics/:epic_id/notes/:note_id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
+| `epic_id` | integer | yes | The ID of an epic |
+| `note_id` | integer | yes | The ID of a note |
+
+```json
+{
+ "id": 52,
+ "title": "Epic",
+ "file_name": "epic.rb",
+ "author": {
+ "id": 1,
+ "username": "pipin",
+ "email": "admin@example.com",
+ "name": "Pip",
+ "state": "active",
+ "created_at": "2013-09-30T13:46:01Z"
+ },
+ "expires_at": null,
+ "updated_at": "2013-10-02T07:34:20Z",
+ "created_at": "2013-10-02T07:34:20Z"
+}
+```
+
+```bash
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/epics/11/notes/1
+```
+
+### Create new epic note
+
+Creates a new note for a single epic. Epic notes are comments users can post to an epic.
+If you create a note where the body only contains an Award Emoji, you'll receive this object back.
+
+```
+POST /groups/:id/epics/:epic_id/notes
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
+| `epic_id` | integer | yes | The ID of an epic |
+| `body` | string | yes | The content of a note |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/snippet/11/notes?body=note
+```
+
+### Modify existing epic note
+
+Modify existing note of an epic.
+
+```
+PUT /groups/:id/epics/:epic_id/notes/:note_id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
+| `epic_id` | integer | yes | The ID of an epic |
+| `note_id` | integer | yes | The ID of a note |
+| `body` | string | yes | The content of a note |
+
+```bash
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/snippet/11/notes?body=note
+```
+
+### Delete an epic note
+
+Deletes an existing note of an epic.
+
+```
+DELETE /groups/:id/epics/:epic_id/notes/:note_id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
+| `epic_id` | integer | yes | The ID of an epic |
+| `note_id` | integer | yes | The ID of a note |
+
+```bash
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/epics/52/notes/1659
+```
diff --git a/doc/api/packages.md b/doc/api/packages.md
new file mode 100644
index 00000000000..618e5c3056a
--- /dev/null
+++ b/doc/api/packages.md
@@ -0,0 +1,152 @@
+# Packages API **[PREMIUM]**
+
+This is the API docs of [GitLab Packages](../administration/packages.md).
+
+## List project packages
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9259) in GitLab 11.8.
+
+Get a list of project packages. Both Maven and NPM packages are included in results.
+When accessed without authentication, only packages of public projects are returned.
+
+```
+GET /projects/:id/packages
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/packages
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 1,
+ "name": "com/mycompany/my-app",
+ "version": "1.0-SNAPSHOT",
+ "package_type": "maven"
+ },
+ {
+ "id": 2,
+ "name": "@foo/bar",
+ "version": "1.0.3",
+ "package_type": "npm"
+ }
+]
+```
+
+By default, the `GET` request will return 20 results, since the API is [paginated](README.md#pagination).
+
+## Get a project package
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9667) in GitLab 11.9.
+
+Get a single project package.
+
+```
+GET /projects/:id/packages/:package_id
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
+| `package_id` | integer | yes | ID of a package. |
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/packages/:package_id
+```
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "name": "com/mycompany/my-app",
+ "version": "1.0-SNAPSHOT",
+ "package_type": "maven"
+}
+```
+
+## List package files
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9305) in GitLab 11.8.
+
+Get a list of package files of a single package.
+
+```
+GET /projects/:id/packages/:package_id/package_files
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| `package_id` | integer | yes | ID of a package. |
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/packages/4/package_files
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 25,
+ "package_id": 4,
+ "created_at": "2018-11-07T15:25:52.199Z",
+ "file_name": "my-app-1.5-20181107.152550-1.jar",
+ "size": 2421,
+ "file_md5": "58e6a45a629910c6ff99145a688971ac",
+ "file_sha1": "ebd193463d3915d7e22219f52740056dfd26cbfe"
+ },
+ {
+ "id": 26,
+ "package_id": 4,
+ "created_at": "2018-11-07T15:25:56.776Z",
+ "file_name": "my-app-1.5-20181107.152550-1.pom",
+ "size": 1122,
+ "file_md5": "d90f11d851e17c5513586b4a7e98f1b2",
+ "file_sha1": "9608d068fe88aff85781811a42f32d97feb440b5"
+ },
+ {
+ "id": 27,
+ "package_id": 4,
+ "created_at": "2018-11-07T15:26:00.556Z",
+ "file_name": "maven-metadata.xml",
+ "size": 767,
+ "file_md5": "6dfd0cce1203145a927fef5e3a1c650c",
+ "file_sha1": "d25932de56052d320a8ac156f745ece73f6a8cd2"
+ }
+]
+```
+
+By default, the `GET` request will return 20 results, since the API is [paginated](README.md#pagination).
+
+## Delete a project package
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9623) in GitLab 11.9.
+
+Deletes a project package.
+
+```
+DELETE /projects/:id/packages/:package_id
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| `package_id` | integer | yes | ID of a package. |
+
+```bash
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/packages/:package_id
+```
+
+Can return the following status codes:
+
+- `204 No Content`, if the package was deleted successfully.
+- `404 Not Found`, if the package was not found.
diff --git a/doc/api/pipeline_schedules.md b/doc/api/pipeline_schedules.md
index 50d9e007ecc..470e55425f8 100644
--- a/doc/api/pipeline_schedules.md
+++ b/doc/api/pipeline_schedules.md
@@ -88,6 +88,7 @@ curl --header "PRIVATE-TOKEN: k5ESFgWY2Qf5xEvDcFxZ" "https://gitlab.example.com/
"variables": [
{
"key": "TEST_VARIABLE_1",
+ "variable_type": "env_var",
"value": "TEST_1"
}
]
@@ -296,6 +297,7 @@ POST /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables
| `pipeline_schedule_id` | integer | yes | The pipeline schedule id |
| `key` | string | yes | The `key` of a variable; must have no more than 255 characters; only `A-Z`, `a-z`, `0-9`, and `_` are allowed |
| `value` | string | yes | The `value` of a variable |
+| `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file` |
```sh
curl --request POST --header "PRIVATE-TOKEN: k5ESFgWY2Qf5xEvDcFxZ" --form "key=NEW_VARIABLE" --form "value=new value" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/variables"
@@ -304,6 +306,7 @@ curl --request POST --header "PRIVATE-TOKEN: k5ESFgWY2Qf5xEvDcFxZ" --form "key=N
```json
{
"key": "NEW_VARIABLE",
+ "variable_type": "env_var",
"value": "new value"
}
```
@@ -322,6 +325,7 @@ PUT /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables/:key
| `pipeline_schedule_id` | integer | yes | The pipeline schedule id |
| `key` | string | yes | The `key` of a variable |
| `value` | string | yes | The `value` of a variable |
+| `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file` |
```sh
curl --request PUT --header "PRIVATE-TOKEN: k5ESFgWY2Qf5xEvDcFxZ" --form "value=updated value" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/variables/NEW_VARIABLE"
@@ -331,6 +335,7 @@ curl --request PUT --header "PRIVATE-TOKEN: k5ESFgWY2Qf5xEvDcFxZ" --form "value=
{
"key": "NEW_VARIABLE",
"value": "updated value"
+ "variable_type": "env_var",
}
```
diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md
index 1a4310ef328..753faec3cc8 100644
--- a/doc/api/pipelines.md
+++ b/doc/api/pipelines.md
@@ -114,6 +114,7 @@ Example of response
[
{
"key": "RUN_NIGHTLY_BUILD",
+ "variable_type": "env_var",
"value": "true"
},
{
@@ -135,7 +136,7 @@ POST /projects/:id/pipeline
|------------|---------|----------|---------------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `ref` | string | yes | Reference to commit |
-| `variables` | array | no | An array containing the variables available in the pipeline, matching the structure [{ 'key' => 'UPLOAD_TO_S3', 'value' => 'true' }] |
+| `variables` | array | no | An array containing the variables available in the pipeline, matching the structure [{ 'key' => 'UPLOAD_TO_S3', 'variable_type' => 'file', 'value' => 'true' }] |
```
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/pipeline?ref=master"
diff --git a/doc/api/project_clusters.md b/doc/api/project_clusters.md
index f36e352da67..327781f6c93 100644
--- a/doc/api/project_clusters.md
+++ b/doc/api/project_clusters.md
@@ -161,11 +161,13 @@ Parameters:
| `name` | String | yes | The name of the cluster |
| `domain` | String | no | The [base domain](../user/project/clusters/index.md#base-domain) of the cluster |
| `enabled` | Boolean | no | Determines if cluster is active or not, defaults to true |
+| `managed` | Boolean | no | Determines if GitLab will manage namespaces and service accounts for this cluster, defaults to true |
| `platform_kubernetes_attributes[api_url]` | String | yes | The URL to access the Kubernetes API |
| `platform_kubernetes_attributes[token]` | String | yes | The token to authenticate against Kubernetes |
| `platform_kubernetes_attributes[ca_cert]` | String | no | TLS certificate (needed if API is using a self-signed TLS certificate |
| `platform_kubernetes_attributes[namespace]` | String | no | The unique namespace related to the project |
| `platform_kubernetes_attributes[authorization_type]` | String | no | The cluster authorization type: `rbac`, `abac` or `unknown_authorization`. Defaults to `rbac`. |
+| `environment_scope` | String | no | The associated environment to the cluster. Defaults to `*` **[PREMIUM]** |
Example request:
@@ -255,6 +257,7 @@ Parameters:
| `platform_kubernetes_attributes[token]` | String | no | The token to authenticate against Kubernetes |
| `platform_kubernetes_attributes[ca_cert]` | String | no | TLS certificate (needed if API is using a self-signed TLS certificate |
| `platform_kubernetes_attributes[namespace]` | String | no | The unique namespace related to the project |
+| `environment_scope` | String | no | The associated environment to the cluster **[PREMIUM]** |
NOTE: **Note:**
`name`, `api_url`, `ca_cert` and `token` can only be updated if the cluster was added
diff --git a/doc/api/project_level_variables.md b/doc/api/project_level_variables.md
index 438bebe62f5..66a749e4811 100644
--- a/doc/api/project_level_variables.md
+++ b/doc/api/project_level_variables.md
@@ -1,4 +1,4 @@
-# Project-level Variables API
+# Project-level Variables API
## List project variables
@@ -20,10 +20,12 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
[
{
"key": "TEST_VARIABLE_1",
+ "variable_type": "env_var",
"value": "TEST_1"
},
{
"key": "TEST_VARIABLE_2",
+ "variable_type": "env_var",
"value": "TEST_2"
}
]
@@ -49,7 +51,10 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
```json
{
"key": "TEST_VARIABLE_1",
- "value": "TEST_1"
+ "variable_type": "env_var",
+ "value": "TEST_1",
+ "protected": false,
+ "masked": true
}
```
@@ -61,12 +66,15 @@ Create a new variable.
POST /projects/:id/variables
```
-| Attribute | Type | required | Description |
-|-------------|---------|----------|-----------------------|
-| `id` | integer/string | yes | The ID of a project or [urlencoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `key` | string | yes | The `key` of a variable; must have no more than 255 characters; only `A-Z`, `a-z`, `0-9`, and `_` are allowed |
-| `value` | string | yes | The `value` of a variable |
-| `protected` | boolean | no | Whether the variable is protected |
+| Attribute | Type | required | Description |
+|---------------------|---------|----------|-----------------------|
+| `id` | integer/string | yes | The ID of a project or [urlencoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `key` | string | yes | The `key` of a variable; must have no more than 255 characters; only `A-Z`, `a-z`, `0-9`, and `_` are allowed |
+| `value` | string | yes | The `value` of a variable |
+| `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file` |
+| `protected` | boolean | no | Whether the variable is protected |
+| `masked` | boolean | no | Whether the variable is masked |
+| `environment_scope` | string | no | The `environment_scope` of the variable **[PREMIUM]** |
```
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/variables" --form "key=NEW_VARIABLE" --form "value=new value"
@@ -76,7 +84,11 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla
{
"key": "NEW_VARIABLE",
"value": "new value",
- "protected": false
+ "protected": false,
+ "variable_type": "env_var",
+ "protected": false,
+ "masked": false,
+ "environment_scope": "*"
}
```
@@ -88,12 +100,15 @@ Update a project's variable.
PUT /projects/:id/variables/:key
```
-| Attribute | Type | required | Description |
-|-------------|---------|----------|-------------------------|
-| `id` | integer/string | yes | The ID of a project or [urlencoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `key` | string | yes | The `key` of a variable |
-| `value` | string | yes | The `value` of a variable |
-| `protected` | boolean | no | Whether the variable is protected |
+| Attribute | Type | required | Description |
+|---------------------|---------|----------|-------------------------|
+| `id` | integer/string | yes | The ID of a project or [urlencoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `key` | string | yes | The `key` of a variable |
+| `value` | string | yes | The `value` of a variable |
+| `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file` |
+| `protected` | boolean | no | Whether the variable is protected |
+| `masked` | boolean | no | Whether the variable is masked |
+| `environment_scope` | string | no | The `environment_scope` of the variable **[PREMIUM]** |
```
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/variables/NEW_VARIABLE" --form "value=updated value"
@@ -103,7 +118,10 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab
{
"key": "NEW_VARIABLE",
"value": "updated value",
- "protected": true
+ "variable_type": "env_var",
+ "protected": true,
+ "masked": false,
+ "environment_scope": "*"
}
```
diff --git a/doc/api/project_templates.md b/doc/api/project_templates.md
index 3b5b12c8da3..0a94a8d47ae 100644
--- a/doc/api/project_templates.md
+++ b/doc/api/project_templates.md
@@ -15,7 +15,7 @@ templates are also available from this API endpoint.
Support will be added for [Issue and Merge Request templates](../user/project/description_templates.md)
in a future release.
-Support for [Group-level file templates](../user/group/index.md#group-level-file-templates-premium)
+Support for [Group-level file templates](../user/group/index.md#group-file-templates-premium)
**[PREMIUM]** was [added](https://gitlab.com/gitlab-org/gitlab-ee/issues/5987)
in GitLab 11.5
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 0a950352ecf..1d58e390d9e 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -143,6 +143,7 @@ When the user is authenticated and `simple` is not set this returns something li
"forks_count": 0,
"star_count": 0,
"runners_token": "b8547b1dc37721d05889db52fa2f02",
+ "ci_default_git_depth": 50,
"public_jobs": true,
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
@@ -153,6 +154,7 @@ When the user is authenticated and `simple` is not set this returns something li
"commit_count": 37,
"storage_size": 1038090,
"repository_size": 1038090,
+ "wiki_size" : 0,
"lfs_objects_size": 0,
"job_artifacts_size": 0
},
@@ -224,6 +226,7 @@ When the user is authenticated and `simple` is not set this returns something li
"forks_count": 0,
"star_count": 0,
"runners_token": "b8547b1dc37721d05889db52fa2f02",
+ "ci_default_git_depth": 0,
"public_jobs": true,
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
@@ -234,6 +237,7 @@ When the user is authenticated and `simple` is not set this returns something li
"commit_count": 12,
"storage_size": 2066080,
"repository_size": 2066080,
+ "wiki_size" : 0,
"lfs_objects_size": 0,
"job_artifacts_size": 0
},
@@ -332,6 +336,7 @@ GET /users/:user_id/projects
"forks_count": 0,
"star_count": 0,
"runners_token": "b8547b1dc37721d05889db52fa2f02",
+ "ci_default_git_depth": 50,
"public_jobs": true,
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
@@ -342,6 +347,7 @@ GET /users/:user_id/projects
"commit_count": 37,
"storage_size": 1038090,
"repository_size": 1038090,
+ "wiki_size" : 0,
"lfs_objects_size": 0,
"job_artifacts_size": 0
},
@@ -413,6 +419,7 @@ GET /users/:user_id/projects
"forks_count": 0,
"star_count": 0,
"runners_token": "b8547b1dc37721d05889db52fa2f02",
+ "ci_default_git_depth": 0,
"public_jobs": true,
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
@@ -423,6 +430,7 @@ GET /users/:user_id/projects
"commit_count": 12,
"storage_size": 2066080,
"repository_size": 2066080,
+ "wiki_size" : 0,
"lfs_objects_size": 0,
"job_artifacts_size": 0
},
@@ -494,7 +502,9 @@ GET /projects/:id
"name": "Diaspora",
"path": "diaspora",
"kind": "group",
- "full_path": "diaspora"
+ "full_path": "diaspora",
+ "avatar_url": "http://localhost:3000/uploads/group/avatar/3/foo.jpg",
+ "web_url": "http://localhost:3000/groups/diaspora"
},
"import_status": "none",
"import_error": null,
@@ -522,6 +532,7 @@ GET /projects/:id
"forks_count": 0,
"star_count": 0,
"runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
+ "ci_default_git_depth": 50,
"public_jobs": true,
"shared_with_groups": [
{
@@ -546,6 +557,7 @@ GET /projects/:id
"commit_count": 37,
"storage_size": 1038090,
"repository_size": 1038090,
+ "wiki_size" : 0,
"lfs_objects_size": 0,
"job_artifacts_size": 0
},
@@ -561,6 +573,8 @@ GET /projects/:id
}
```
+**Note**: The `web_url` and `avatar_url` attributes on `namespace` were [introduced][ce-27427] in GitLab 11.11.
+
If the project is a fork, and you provide a valid token to authenticate, the
`forked_from_project` field will appear in the response.
@@ -754,6 +768,7 @@ PUT /projects/:id
| `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project |
| `avatar` | mixed | no | Image file for avatar of the project |
| `ci_config_path` | string | no | The path to CI config file |
+| `ci_default_git_depth` | integer | no | Default number of revisions for [shallow cloning](../user/project/pipelines/settings.md#git-shallow-clone) |
## Fork project
@@ -1151,6 +1166,7 @@ Example response:
"forks_count": 0,
"star_count": 0,
"runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
+ "ci_default_git_depth": 50,
"public_jobs": true,
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
@@ -1255,6 +1271,7 @@ Example response:
"forks_count": 0,
"star_count": 0,
"runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
+ "ci_default_git_depth": 50,
"public_jobs": true,
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
@@ -1587,3 +1604,4 @@ GET /projects/:id/snapshot
[eep]: https://about.gitlab.com/pricing/ "Available only in GitLab Premium"
[ee-6137]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/6137
+[ce-27427]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27427
diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md
index 6fcc06ea8cd..87c7f371de1 100644
--- a/doc/api/repository_files.md
+++ b/doc/api/repository_files.md
@@ -181,7 +181,7 @@ Currently gitlab-shell has a boolean return code, preventing GitLab from specify
## Delete existing file in repository
-This allows you to delete a single file. For deleting multiple files with a singleh request see the [commits API](commits.html#create-a-commit-with-multiple-files-and-actions).
+This allows you to delete a single file. For deleting multiple files with a single request, see the [commits API](commits.html#create-a-commit-with-multiple-files-and-actions).
```
DELETE /projects/:id/repository/files/:file_path
diff --git a/doc/api/repository_storage_health.md b/doc/api/repository_storage_health.md
deleted file mode 100644
index edf4b04acea..00000000000
--- a/doc/api/repository_storage_health.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Circuitbreaker API
-
-NOTE: **Deprecated:**
-Support of the circuit breaker is removed, as Gitaly can be configured to
-to work without NFS and [communicate solely over HTTP](../administration/gitaly/index.md).
diff --git a/doc/api/resource_label_events.md b/doc/api/resource_label_events.md
index e1f9ffa9472..f0a7ac4e41d 100644
--- a/doc/api/resource_label_events.md
+++ b/doc/api/resource_label_events.md
@@ -88,6 +88,92 @@ Parameters:
curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/issues/11/resource_label_events/1
```
+## Epics **[ULTIMATE]**
+
+### List group epic label events
+
+Gets a list of all label events for a single epic.
+
+```
+GET /groups/:id/epics/:epic_id/resource_label_events
+```
+
+| Attribute | Type | Required | Description |
+| ------------------- | ---------------- | ---------- | ------------ |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
+| `epic_id` | integer | yes | The ID of an epic |
+
+```json
+[
+ {
+ "id": 106,
+ "user": {
+ "id": 1,
+ "name": "Administrator",
+ "username": "root",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "web_url": "http://gitlab.example.com/root"
+ },
+ "created_at": "2018-08-19T11:43:01.746Z",
+ "resource_type": "Epic",
+ "resource_id": 33,
+ "label": {
+ "id": 73,
+ "name": "a1",
+ "color": "#34495E",
+ "description": ""
+ },
+ "action": "add"
+ },
+ {
+ "id": 107,
+ "user": {
+ "id": 1,
+ "name": "Administrator",
+ "username": "root",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "web_url": "http://gitlab.example.com/root"
+ },
+ "created_at": "2018-08-19T11:43:01.746Z",
+ "resource_type": "Epic",
+ "resource_id": 33,
+ "label": {
+ "id": 37,
+ "name": "glabel2",
+ "color": "#A8D695",
+ "description": ""
+ },
+ "action": "add"
+ }
+]
+```
+
+```bash
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/11/resource_label_events
+```
+
+### Get single epic label event
+
+Returns a single label event for a specific group epic
+
+```
+GET /groups/:id/epics/:epic_id/resource_label_events/:resource_label_event_id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
+| `epic_id` | integer | yes | The ID of an epic |
+| `resource_label_event_id` | integer | yes | The ID of a label event |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics/11/resource_label_events/107
+```
+
## Merge requests
### List project merge request label events
diff --git a/doc/api/runners.md b/doc/api/runners.md
index 46f7b1d2a25..2d91428d1c1 100644
--- a/doc/api/runners.md
+++ b/doc/api/runners.md
@@ -486,6 +486,7 @@ POST /runners
| `locked` | boolean| no | Whether the Runner should be locked for current project |
| `run_untagged` | boolean | no | Whether the Runner should handle untagged jobs |
| `tag_list` | Array[String] | no | List of Runner's tags |
+| `access_level` | string | no | The access_level of the runner; `not_protected` or `ref_protected` |
| `maximum_timeout` | integer | no | Maximum timeout set when this Runner will handle the job |
```
diff --git a/doc/api/scim.md b/doc/api/scim.md
new file mode 100644
index 00000000000..3870ea788e7
--- /dev/null
+++ b/doc/api/scim.md
@@ -0,0 +1,235 @@
+# SCIM API **[SILVER ONLY]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9388) in [GitLab Silver](https://about.gitlab.com/pricing/) 11.10.
+
+The SCIM API implements the [the RFC7644 protocol](https://tools.ietf.org/html/rfc7644).
+
+NOTE: **Note:**
+[Group SSO](../user/group/saml_sso/index.md) and the feature
+flag `:group_scim` must be enabled for the group. For more information, see [SCIM setup documentation](../user/group/saml_sso/scim_setup.md#requirements).
+
+## Get a list of SAML users
+
+NOTE: **Note:**
+This endpoint is used as part of the SCIM syncing mechanism and it only returns
+a single user based on a unique ID which should match the `extern_uid` of the user.
+
+```text
+GET /api/scim/v2/groups/:group_path/Users
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------|
+| `filter` | string | yes | A [filter](#available-filters) expression. |
+| `group_path` | string | yes | Full path to the group. |
+
+Example request:
+
+```sh
+curl 'https://example.gitlab.com/api/scim/v2/groups/test_group/Users?filter=id%20eq%20"0b1d561c-21ff-4092-beab-8154b17f82f2"' --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
+```
+
+Example response:
+
+```json
+{
+ "schemas": [
+ "urn:ietf:params:scim:api:messages:2.0:ListResponse"
+ ],
+ "totalResults": 1,
+ "itemsPerPage": 20,
+ "startIndex": 1,
+ "Resources": [
+ {
+ "schemas": [
+ "urn:ietf:params:scim:schemas:core:2.0:User"
+ ],
+ "id": "0b1d561c-21ff-4092-beab-8154b17f82f2",
+ "active": true,
+ "name.formatted": "Test User",
+ "userName": "username",
+ "meta": { "resourceType":"User" },
+ "emails": [
+ {
+ "type": "work",
+ "value": "name@example.com",
+ "primary": true
+ }
+ ]
+ }
+ ]
+}
+```
+
+## Get a single SAML user
+
+```text
+GET /api/scim/v2/groups/:group_path/Users/:id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------|
+| `id` | string | yes | External UID of the user. |
+| `group_path` | string | yes | Full path to the group. |
+
+Example request:
+
+```sh
+curl 'https://example.gitlab.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2' --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
+```
+
+Example response:
+
+```json
+{
+ "schemas": [
+ "urn:ietf:params:scim:schemas:core:2.0:User"
+ ],
+ "id": "0b1d561c-21ff-4092-beab-8154b17f82f2",
+ "active": true,
+ "name.formatted": "Test User",
+ "userName": "username",
+ "meta": { "resourceType":"User" },
+ "emails": [
+ {
+ "type": "work",
+ "value": "name@example.com",
+ "primary": true
+ }
+ ]
+}
+```
+
+## Create a SAML user
+
+```text
+POST /api/scim/v2/groups/:group_path/Users/
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:---------------|:----------|:----|:--------------------------|
+| `externalId` | string | yes | External UID of the user. |
+| `userName` | string | yes | Username of the user. |
+| `emails` | JSON string | yes | Work email. |
+| `name` | JSON string | yes | Name of the user. |
+| `meta` | string | no | Resource type (`User'). |
+
+Example request:
+
+```sh
+curl --verbose --request POST 'https://example.gitlab.com/api/scim/v2/groups/test_group/Users' --data '{"externalId":"test_uid","active":null,"userName":"username","emails":[{"primary":true,"type":"work","value":"name@example.com"}],"name":{"formatted":"Test User","familyName":"User","givenName":"Test"},"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"meta":{"resourceType":"User"}}' --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
+```
+
+Example response:
+
+```json
+{
+ "schemas": [
+ "urn:ietf:params:scim:schemas:core:2.0:User"
+ ],
+ "id": "0b1d561c-21ff-4092-beab-8154b17f82f2",
+ "active": true,
+ "name.formatted": "Test User",
+ "userName": "username",
+ "meta": { "resourceType":"User" },
+ "emails": [
+ {
+ "type": "work",
+ "value": "name@example.com",
+ "primary": true
+ }
+ ]
+}
+```
+
+Returns a `201` status code if successful.
+
+## Update a single SAML user
+
+Fields that can be updated are:
+
+| SCIM/IdP field | GitLab field |
+|:----------|:--------|
+| id/externalId | extern_uid |
+| name.formatted | name |
+| emails\[type eq "work"\].value | email |
+| active | Identity removal if `active = false` |
+| userName | username |
+
+```text
+PATCH /api/scim/v2/groups/:group_path/Users/:id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------|
+| `id` | string | yes | External UID of the user. |
+| `group_path` | string | yes | Full path to the group. |
+| `Operations` | JSON string | yes | An [operations](#available-operations) expression. |
+
+Example request:
+
+```sh
+curl --verbose --request PATCH 'https://example.gitlab.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2' --data '{ "Operations": [{"op":"Add","path":"name.formatted","value":"New Name"}] }' --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
+```
+
+Returns an empty response with a `204` status code if successful.
+
+## Remove a single SAML user
+
+Removes the user's SSO identity and group membership.
+
+```text
+DELETE /api/scim/v2/groups/:group_path/Users/:id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------|
+| `id` | string | yes | External UID of the user. |
+| `group_path` | string | yes | Full path to the group. |
+
+Example request:
+
+```sh
+curl --verbose --request DELETE 'https://example.gitlab.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2' --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
+```
+
+Returns an empty response with a `204` status code if successful.
+
+## Available filters
+
+They match an expression as specified in [the RFC7644 filtering section](https://tools.ietf.org/html/rfc7644#section-3.4.2.2).
+
+| Filter | Description |
+| ----- | ----------- |
+| `eq` | The attribute matches exactly the specified value. |
+
+Example:
+
+```
+id eq a-b-c-d
+```
+
+## Available operations
+
+They perform an operation as specified in [the RFC7644 update section](https://tools.ietf.org/html/rfc7644#section-3.5.2).
+
+| Operator | Description |
+| ----- | ----------- |
+| `Replace` | The attribute's value is updated. |
+| `Add` | The attribute has a new value. |
+
+Example:
+
+```json
+{ "op": "Add", "path": "name.formatted", "value": "New Name" }
+```
diff --git a/doc/api/search.md b/doc/api/search.md
index 6ee3d32d8bc..da81c8321c9 100644
--- a/doc/api/search.md
+++ b/doc/api/search.md
@@ -19,6 +19,8 @@ GET /search
Search the expression within the specified scope. Currently these scopes are supported: projects, issues, merge_requests, milestones, snippet_titles, snippet_blobs, users.
+If Elasticsearch is enabled additional scopes available are blobs, wiki_blobs and commits. Find more about [the feature](../integration/elasticsearch.md). **[STARTER]**
+
The response depends on the requested scope.
### Scope: projects
@@ -281,6 +283,98 @@ Example response:
]
```
+### Scope: wiki_blobs **[STARTER]**
+
+This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
+
+```bash
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/search?scope=wiki_blobs&search=bye
+```
+
+Example response:
+
+```json
+
+[
+ {
+ "basename": "home",
+ "data": "hello\n\nand bye\n\nend",
+ "filename": "home.md",
+ "id": null,
+ "ref": "master",
+ "startline": 5,
+ "project_id": 6
+ }
+]
+```
+
+### Scope: commits **[STARTER]**
+
+This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
+
+```bash
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/search?scope=commits&search=bye
+```
+
+Example response:
+
+```json
+
+[
+ {
+ "id": "4109c2d872d5fdb1ed057400d103766aaea97f98",
+ "short_id": "4109c2d8",
+ "title": "goodbye $.browser",
+ "created_at": "2013-02-18T22:02:54.000Z",
+ "parent_ids": [
+ "59d05353ab575bcc2aa958fe1782e93297de64c9"
+ ],
+ "message": "goodbye $.browser\n",
+ "author_name": "angus croll",
+ "author_email": "anguscroll@gmail.com",
+ "authored_date": "2013-02-18T22:02:54.000Z",
+ "committer_name": "angus croll",
+ "committer_email": "anguscroll@gmail.com",
+ "committed_date": "2013-02-18T22:02:54.000Z",
+ "project_id": 6
+ }
+]
+```
+
+### Scope: blobs **[STARTER]**
+
+This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
+
+Filters are available for this scope:
+- filename
+- path
+- extension
+
+to use a filter simply include it in your query like so: `a query filename:some_name*`.
+
+You may use wildcards (`*`) to use glob matching.
+
+```bash
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/search?scope=blobs&search=installation
+```
+
+Example response:
+
+```json
+
+[
+ {
+ "basename": "README",
+ "data": "```\n\n## Installation\n\nQuick start using the [pre-built",
+ "filename": "README.md",
+ "id": null,
+ "ref": "master",
+ "startline": 46,
+ "project_id": 6
+ }
+]
+```
+
### Scope: users
```bash
@@ -320,6 +414,8 @@ GET /groups/:id/search
Search the expression within the specified scope. Currently these scopes are supported: projects, issues, merge_requests, milestones, users.
+If Elasticsearch is enabled additional scopes available are blobs, wiki_blobs and commits. Find more about [the feature](../integration/elasticsearch.md). **[STARTER]**
+
The response depends on the requested scope.
### Scope: projects
@@ -520,6 +616,98 @@ Example response:
]
```
+### Scope: wiki_blobs **[STARTER]**
+
+This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
+
+```bash
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/6/search?scope=wiki_blobs&search=bye
+```
+
+Example response:
+
+```json
+
+[
+ {
+ "basename": "home",
+ "data": "hello\n\nand bye\n\nend",
+ "filename": "home.md",
+ "id": null,
+ "ref": "master",
+ "startline": 5,
+ "project_id": 6
+ }
+]
+```
+
+### Scope: commits **[STARTER]**
+
+This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
+
+```bash
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/6/search?scope=commits&search=bye
+```
+
+Example response:
+
+```json
+
+[
+ {
+ "id": "4109c2d872d5fdb1ed057400d103766aaea97f98",
+ "short_id": "4109c2d8",
+ "title": "goodbye $.browser",
+ "created_at": "2013-02-18T22:02:54.000Z",
+ "parent_ids": [
+ "59d05353ab575bcc2aa958fe1782e93297de64c9"
+ ],
+ "message": "goodbye $.browser\n",
+ "author_name": "angus croll",
+ "author_email": "anguscroll@gmail.com",
+ "authored_date": "2013-02-18T22:02:54.000Z",
+ "committer_name": "angus croll",
+ "committer_email": "anguscroll@gmail.com",
+ "committed_date": "2013-02-18T22:02:54.000Z",
+ "project_id": 6
+ }
+]
+```
+
+### Scope: blobs **[STARTER]**
+
+This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
+
+Filters are available for this scope:
+- filename
+- path
+- extension
+
+to use a filter simply include it in your query like so: `a query filename:some_name*`.
+
+You may use wildcards (`*`) to use glob matching.
+
+```bash
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/6/search?scope=blobs&search=installation
+```
+
+Example response:
+
+```json
+
+[
+ {
+ "basename": "README",
+ "data": "```\n\n## Installation\n\nQuick start using the [pre-built",
+ "filename": "README.md",
+ "id": null,
+ "ref": "master",
+ "startline": 46,
+ "project_id": 6
+ }
+]
+```
+
### Scope: users
```bash
diff --git a/doc/api/services.md b/doc/api/services.md
index e8ae7ff78f4..898cfad7254 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -545,7 +545,7 @@ GET /projects/:id/services/jira
Set JIRA service for a project.
> Starting with GitLab 8.14, `api_url`, `issues_url`, `new_issue_url` and
-> `project_url` are replaced by `project_key`, `url`. If you are using an
+> `project_url` are replaced by `url`. If you are using an
> older version, [follow this documentation][old-jira-api].
```
@@ -557,7 +557,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `url` | string | yes | The URL to the JIRA project which is being linked to this GitLab project. For example, `https://jira.example.com`. |
-| `project_key` | string | yes | The short identifier for your JIRA project, all uppercase, e.g., `PROJ`. |
+| `api_url` | string | no | The base URL to the JIRA instance API. Web URL value will be used if not set. For example, `https://jira-api.example.com`. |
| `username` | string | yes | The username of the user created to be used with GitLab/JIRA. |
| `password` | string | yes | The password of the user created to be used with GitLab/JIRA. |
| `active` | boolean | no | Activates or deactivates the service. Defaults to false (deactivated). |
@@ -754,6 +754,7 @@ Parameters:
| `recipients` | string | yes | Comma-separated list of recipient email addresses |
| `add_pusher` | boolean | no | Add pusher to recipients list |
| `notify_only_broken_pipelines` | boolean | no | Notify only broken pipelines |
+| `notify_only_default_branch` | boolean | no | Send notifications only for the default branch ([introduced in GitLab 12.0](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/28271)) |
### Delete Pipeline-Emails service
@@ -1100,6 +1101,75 @@ Get JetBrains TeamCity CI service settings for a project.
GET /projects/:id/services/teamcity
```
+## Jenkins CI **[STARTER]**
+
+A continuous integration and build server
+
+### Create/Edit Jenkins CI service
+
+Set Jenkins CI service for a project.
+
+```
+PUT /projects/:id/services/jenkins
+```
+
+Parameters:
+
+- `jenkins_url` (**required**) - Jenkins URL like http://jenkins.example.com
+- `project_name` (**required**) - The URL-friendly project name. Example: my_project_name
+- `username` (optional) - A user with access to the Jenkins server, if applicable
+- `password` (optional) - The password of the user
+
+### Delete Jenkins CI service
+
+Delete Jenkins CI service for a project.
+
+```
+DELETE /projects/:id/services/jenkins
+```
+
+### Get Jenkins CI service settings
+
+Get Jenkins CI service settings for a project.
+
+```
+GET /projects/:id/services/jenkins
+```
+
+## Jenkins CI (Deprecated) Service
+
+A continuous integration and build server
+
+### Create/Edit Jenkins CI (Deprecated) service
+
+Set Jenkins CI (Deprecated) service for a project.
+
+```
+PUT /projects/:id/services/jenkins-deprecated
+```
+
+Parameters:
+
+- `project_url` (**required**) - Jenkins project URL like http://jenkins.example.com/job/my-project/
+- `multiproject_enabled` (optional) - Multi-project mode is configured in Jenkins GitLab Hook plugin
+- `pass_unstable` (optional) - Unstable builds will be treated as passing
+
+### Delete Jenkins CI (Deprecated) service
+
+Delete Jenkins CI (Deprecated) service for a project.
+
+```
+DELETE /projects/:id/services/jenkins-deprecated
+```
+
+### Get Jenkins CI (Deprecated) service settings
+
+Get Jenkins CI (Deprecated) service settings for a project.
+
+```
+GET /projects/:id/services/jenkins-deprecated
+```
+
[jira-doc]: ../user/project/integrations/jira.md
[old-jira-api]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-13-stable/doc/api/services.md#jira
diff --git a/doc/api/snippets.md b/doc/api/snippets.md
index f90447e124e..1ce0b1e7a62 100644
--- a/doc/api/snippets.md
+++ b/doc/api/snippets.md
@@ -165,15 +165,15 @@ Parameters:
|:--------------|:-------|:---------|:---------------------------------------------------|
| `title` | string | yes | Title of a snippet. |
| `file_name` | string | yes | Name of a snippet file. |
-| `content` | string | yes | Content of a snippet. |
+| `code` | string | yes | Content of a snippet. |
| `description` | string | no | Description of a snippet. |
-| `visibility` | string | no | Snippet's [visibility](#snippet-visibility-level). |
+| `visibility` | string | yes | Snippet's [visibility](#snippet-visibility-level). |
Example request:
```sh
curl --request POST \
- --data '{"title": "This is a snippet", "content": "Hello world", "description": "Hello World snippet", "file_name": "test.txt", "visibility": "internal" }' \
+ --data '{"title": "This is a snippet", "code": "Hello world", "description": "Hello World snippet", "file_name": "test.txt", "visibility": "internal" }' \
--header 'Content-Type: application/json' \
--header "PRIVATE-TOKEN: valid_api_token" \
https://gitlab.example.com/api/v4/snippets
@@ -222,14 +222,14 @@ Parameters:
| `title` | string | no | Title of a snippet. |
| `file_name` | string | no | Name of a snippet file. |
| `description` | string | no | Description of a snippet. |
-| `content` | string | no | Content of a snippet. |
+| `code` | string | no | Content of a snippet. |
| `visibility` | string | no | Snippet's [visibility](#snippet-visibility-level). |
Example request:
```sh
curl --request PUT \
- --data '{"title": "foo", "content": "bar"}' \
+ --data '{"title": "foo", "code": "bar"}' \
--header 'Content-Type: application/json' \
--header "PRIVATE-TOKEN: valid_api_token" \
https://gitlab.example.com/api/v4/snippets/1
diff --git a/doc/api/users.md b/doc/api/users.md
index 606003a75e2..47028c679b8 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -33,7 +33,7 @@ GET /users
]
```
-You can also search for users by email or username with: `/users?search=John`
+You can also search for users by name or primary email using `?search=`. For example. `/users?search=John`.
In addition, you can lookup users by username:
@@ -140,8 +140,7 @@ GET /users
"can_create_project": true,
"two_factor_enabled": true,
"external": false,
- "private_profile": false,
- "highest_role":10
+ "private_profile": false
}
]
```
@@ -257,7 +256,8 @@ Parameters:
"can_create_project": true,
"two_factor_enabled": true,
"external": false,
- "private_profile": false
+ "private_profile": false,
+ "highest_role":10
}
```
diff --git a/doc/api/vulnerabilities.md b/doc/api/vulnerabilities.md
new file mode 100644
index 00000000000..390d0966244
--- /dev/null
+++ b/doc/api/vulnerabilities.md
@@ -0,0 +1,113 @@
+# Vulnerabilities API **[ULTIMATE]**
+
+Every API call to vulnerabilities must be authenticated.
+
+If a user is not a member of a project and the project is private, a `GET`
+request on that project will result in a `404` status code.
+
+CAUTION: **Caution:**
+This API is in an alpha stage and considered unstable.
+The response payload may be subject to change or breakage
+across GitLab releases.
+
+## Vulnerabilities pagination
+
+By default, `GET` requests return 20 results at a time because the API results
+are paginated.
+
+Read more on [pagination](README.md#pagination).
+
+## List project vulnerabilities
+
+List all of a project's vulnerabilities.
+
+```
+GET /projects/:id/vulnerabilities
+GET /projects/:id/vulnerabilities?report_type=sast
+GET /projects/:id/vulnerabilities?report_type=container_scanning
+GET /projects/:id/vulnerabilities?report_type=sast,dast
+GET /projects/:id/vulnerabilities?scope=all
+GET /projects/:id/vulnerabilities?scope=dismissed
+GET /projects/:id/vulnerabilities?severity=high
+GET /projects/:id/vulnerabilities?confidence=unknown,experimental
+```
+
+| Attribute | Type | Required | Description |
+| ------------------- | ---------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `report_type` | Array[string] | no | Returns vulnerabilities belonging to specified report type. Valid values: `sast`, `dast`, `dependency_scanning`, or `container_scanning`. |
+| `scope` | string | no | Returns vulnerabilities for the given scope: `all` or `dismissed`. Defaults to `dismissed` |
+| `severity` | Array[string] | no | Returns vulnerabilities belonging to specified severity level: `undefined`, `info`, `unknown`, `low`, `medium`, `high`, or `critical`. Defaults to all' |
+| `confidence` | Array[string] | no | Returns vulnerabilities belonging to specified confidence level: `undefined`, `ignore`, `unknown`, `experimental`, `low`, `medium`, `high`, or `confirmed`. Defaults to all |
+
+```bash
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/4/vulnerabilities
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": null,
+ "report_type": "dependency_scanning",
+ "name": "Authentication bypass via incorrect DOM traversal and canonicalization in saml2-js",
+ "severity": "unknown",
+ "confidence": "undefined",
+ "scanner": {
+ "external_id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "identifiers": [
+ {
+ "external_type": "gemnasium",
+ "external_id": "9952e574-7b5b-46fa-a270-aeb694198a98",
+ "name": "Gemnasium-9952e574-7b5b-46fa-a270-aeb694198a98",
+ "url": "https://deps.sec.gitlab.com/packages/npm/saml2-js/versions/1.5.0/advisories"
+ },
+ {
+ "external_type": "cve",
+ "external_id": "CVE-2017-11429",
+ "name": "CVE-2017-11429",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-11429"
+ }
+ ],
+ "project_fingerprint": "fa6f5b6c5d240b834ac5e901dc69f9484cef89ec",
+ "create_vulnerability_feedback_issue_path": "/tests/yarn-remediation-test/vulnerability_feedback",
+ "create_vulnerability_feedback_merge_request_path": "/tests/yarn-remediation-test/vulnerability_feedback",
+ "create_vulnerability_feedback_dismissal_path": "/tests/yarn-remediation-test/vulnerability_feedback",
+ "project": {
+ "id": 31,
+ "name": "yarn-remediation-test",
+ "full_path": "/tests/yarn-remediation-test",
+ "full_name": "tests / yarn-remediation-test"
+ },
+ "dismissal_feedback": null,
+ "issue_feedback": null,
+ "merge_request_feedback": null,
+ "description": "Some XML DOM traversal and canonicalization APIs may be inconsistent in handling of comments within XML nodes. Incorrect use of these APIs by some SAML libraries results in incorrect parsing of the inner text of XML nodes such that any inner text after the comment is lost prior to cryptographically signing the SAML message. Text after the comment therefore has no impact on the signature on the SAML message.\r\n\r\nA remote attacker can modify SAML content for a SAML service provider without invalidating the cryptographic signature, which may allow attackers to bypass primary authentication for the affected SAML service provider.",
+ "links": [
+ {
+ "url": "https://github.com/Clever/saml2/commit/3546cb61fd541f219abda364c5b919633609ef3d#diff-af730f9f738de1c9ad87596df3f6de84R279"
+ },
+ {
+ "url": "https://www.kb.cert.org/vuls/id/475445"
+ },
+ {
+ "url": "https://github.com/Clever/saml2/issues/127"
+ }
+ ],
+ "location": {
+ "file": "yarn.lock",
+ "dependency": {
+ "package": {
+ "name": "saml2-js"
+ },
+ "version": "1.5.0"
+ }
+ },
+ "solution": "Upgrade to fixed version.\r\n",
+ "blob_path": "/tests/yarn-remediation-test/blob/cc6c4a0778460455ae5d16ca7025ca9ca1ca75ac/yarn.lock"
+ }
+]
+```
diff --git a/doc/articles/how_to_configure_ldap_gitlab_ee/index.md b/doc/articles/how_to_configure_ldap_gitlab_ee/index.md
new file mode 100644
index 00000000000..3e6f3130437
--- /dev/null
+++ b/doc/articles/how_to_configure_ldap_gitlab_ee/index.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../../administration/auth/how_to_configure_ldap_gitlab_ee/index.md'
+---
+
+This document was moved to [another location](../../administration/auth/how_to_configure_ldap_gitlab_ee/index.md).
diff --git a/doc/ci/README.md b/doc/ci/README.md
index 123a5e50f14..1743c38eb46 100644
--- a/doc/ci/README.md
+++ b/doc/ci/README.md
@@ -1,86 +1,141 @@
---
comments: false
description: "Learn how to use GitLab CI/CD, the GitLab built-in Continuous Integration, Continuous Deployment, and Continuous Delivery toolset to build, test, and deploy your application."
+type: index
---
-# GitLab Continuous Integration (GitLab CI/CD)
+# GitLab CI/CD
-GitLab CI/CD is GitLab's built-in tool for software development using continuous methodology:
+GitLab CI/CD is a tool built into GitLab for software development
+through the [continuous methodologies](introduction/index.md#introduction-to-cicd-methodologies):
-- Continuous integration (CI).
-- Continuous delivery and deployment (CD).
-
-Within the [DevOps lifecycle](../README.md#the-entire-devops-lifecycle), GitLab CI/CD spans
-the [Verify (CI)](../README.md#verify) and [Release (CD)](../README.md#release) stages.
+- Continuous Integration (CI)
+- Continuous Delivery (CD)
+- Continuous Deployment (CD)
## Overview
-CI/CD is a vast area, so GitLab provides documentation for all levels of expertise. Consult the following table to find the right documentation for you:
-
-| Level of expertise | Resource |
-|:------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------|
-| New to the concepts of CI and CD | For a high-level overview, read an [introduction to CI/CD with GitLab](introduction/index.md). |
-| Familiar with GitLab CI/CD concepts | After getting familiar with GitLab CI/CD, let us walk you through a simple example in our [getting started guide](quick_start/README.md). |
-| A GitLab CI/CD expert | Jump straight to our [`.gitlab.yml`](yaml/README.md) reference. |
-
-Familiarity with GitLab Runner is also useful because it is responsible for running the jobs in your
-CI/CD pipeline. On GitLab.com, shared Runners are enabled by default so you won't need to set this up to get started.
-
-## CI/CD with Auto DevOps
-
-[Auto DevOps](../topics/autodevops/index.md) is the default minimum-configuration method for
-implementing CI/CD. Auto DevOps:
-
-- Provides simplified setup and execution of CI/CD.
-- Allows GitLab to automatically detect, build, test, deploy, and monitor your applications.
-
-## Manually configured CI/CD
-
-For complete control, you can manually configure GitLab CI/CD.
-
-### Configuration and Usage
-
-The following topics contain configuration and usage information for all features of GitLab CI/CD:
-
-| Topic | Description |
-|:--------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------|
-| [Creating and using CI/CD pipelines](pipelines.md) | Understand, visualize, create, and use CI/CD pipelines. |
-| [CI/CD Variables](variables/README.md) | Configuring and using environment variables in pipelines. |
-| [Where variables can be used](variables/where_variables_can_be_used.md) | Where and how CI/CD variables can be used. |
-| [User](../user/permissions.md#gitlab-cicd-permissions) and [job](../user/permissions.md#job-permissions) permissions | User access levels for performing certain CI actions. |
-| [Configuring GitLab Runners](runners/README.md) | Configuring [GitLab Runner](https://docs.gitlab.com/runner/). |
-| [Environments and deployments](environments.md) | Deploy the output of jobs into environments for reviewing, staging, and production. |
-| [Review Apps](review_apps/index.md) | Configure GitLab CI/CD to preview code changes. |
-| [Job artifacts](../user/project/pipelines/job_artifacts.md) | Using the output of jobs. |
-| [Cache dependencies in GitLab CI/CD](caching/index.md) | Speed up pipelines using caching. |
-| [Using Git submodules with GitLab CI](git_submodules.md) | How to run your CI jobs when using Git submodules. |
-| [Using SSH keys with GitLab CI/CD](ssh_keys/README.md) | Use SSH keys in your build environment. |
-| [Triggering pipelines through the API](triggers/README.md) | Use the GitLab API to trigger a pipeline. |
-| [Connecting GitLab with a Kubernetes cluster](../user/project/clusters/index.md) | Integrate one or more Kubernetes clusters to your project. |
-| [ChatOps](chatops/README.md) | Trigger CI jobs from chat, with results sent back to the channel. |
-| [Interactive web terminals](interactive_web_terminal/index.md) | Open an interactive web terminal to debug the running jobs. |
-| [Optimizing GitLab for large repositories](large_repositories/index.md) | Useful tips on how to optimize GitLab and GitLab Runner for big repositories. |
-| [Deploy Boards](https://docs.gitlab.com/ee/user/project/deploy_boards.html) **[PREMIUM]** | Check the current health and status of each CI/CD environment running on Kubernetes. |
-| [GitLab CI/CD for external repositories](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/index.html) **[PREMIUM]** | Get the benefits of GitLab CI/CD combined with repositories in GitHub and BitBucket Cloud. |
-
-### GitLab Pages
-
-GitLab CI/CD can be used to build and host static websites. For more information, see the
-documentation on [GitLab Pages](../user/project/pages/index.md),
-or dive right into the [CI/CD step-by-step guide for Pages](../user/project/pages/getting_started_part_four.md).
-
-### Examples
-
-GitLab provides examples of configuring GitLab CI/CD in the form of:
-
-- A collection of [examples and other resources](examples/README.md).
-- Example projects that are available at the [`gitlab-examples`](https://gitlab.com/gitlab-examples) group. For example, see:
- - [`multi-project-pipelines`](https://gitlab.com/gitlab-examples/multi-project-pipelines) for examples of implementing multi-project pipelines.
- - [`review-apps-nginx`](https://gitlab.com/gitlab-examples/review-apps-nginx/) provides an example of using Review Apps.
-
-### Administration
-
-As a GitLab administrator, you can change the default behavior of GitLab CI/CD for:
+Continuous Integration works by pushing small code chunks to your
+application's code base hosted in a Git repository, and, to every
+push, run a pipeline of scripts to build, test, and validate the
+code changes before merging them into the main branch.
+
+Continuous Delivery and Deployment consist of a step further CI,
+deploying your application to production at every
+push to the default branch of the repository.
+
+These methodologies allow you to catch bugs and errors early in
+the development cycle, ensuring that all the code deployed to
+production complies with the code standards you established for
+your app.
+
+For a complete overview of these methodologies and GitLab CI/CD,
+read the [Introduction to CI/CD with GitLab](introduction/index.md).
+
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+For a video demonstration of GitLab CI/CD, see [Demo: CI/CD with GitLab](https://www.youtube.com/watch?v=1iXFbchozdY).
+
+## Getting started
+
+GitLab CI/CD is configured by a file called `.gitlab-ci.yml` placed
+at the repository's root. The scripts set in this file are executed
+by the [GitLab Runner](https://docs.gitlab.com/runner/).
+
+To get started with GitLab CI/CD, we recommend you read through
+the following documents:
+
+- [How GitLab CI/CD works](introduction/index.md#how-gitlab-cicd-works).
+- [GitLab CI/CD basic workflow](introduction/index.md#basic-cicd-workflow).
+- [Step-by-step guide for writing `.gitlab-ci.yml` for the first time](../user/project/pages/getting_started_part_four.md).
+
+You can also get started by using one of the
+[`.gitlab-ci.yml` templates](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/gitlab/ci/templates)
+available through the UI. You can use them by creating a new file,
+choosing a template that suits your application, and adjusting it
+to your needs:
+
+![Use a .gitlab-ci.yml template](img/add_file_template_11_10.png)
+
+For a broader overview, see the [CI/CD getting started](quick_start/README.md) guide.
+
+Once you're familiar with how GitLab CI/CD works, see the
+[`. gitlab-ci.yml` full reference](yaml/README.md)
+for all the attributes you can set and use.
+
+NOTE: **Note:**
+GitLab CI/CD and [shared runners](runners/README.md#shared-specific-and-group-runners) are enabled in GitLab.com and available for all users, limited only to the [user's pipelines quota](../user/admin_area/settings/continuous_integration.md#extra-shared-runners-pipeline-minutes-quota).
+
+## Configuration
+
+GitLab CI/CD supports numerous configuration options:
+
+| Configuration | Description |
+|:--------------|:-------------|
+| [Pipelines](pipelines.md) | Structure your CI/CD process through pipelines. |
+| [Environment variables](variables/README.md) | Reuse values based on a variable/value key pair. |
+| [Environments](environments.md) | Deploy your application to different environments (e.g., staging, production). |
+| [Job artifacts](../user/project/pipelines/job_artifacts.md) | Output, use, and reuse job artifacts. |
+| [Cache dependencies](caching/index.md) | Cache your dependencies for a faster execution. |
+| [Schedule pipelines](../user/project/pipelines/schedules.md) | Schedule pipelines to run as often as you need. |
+| [Custom path for `.gitlab-ci.yml`](../user/project/pipelines/settings.md#custom-ci-config-path) | Define a custom path for the CI/CD configuration file. |
+| [Git submodules for CI/CD](git_submodules.md) | Configure jobs for using Git submodules.|
+| [SSH keys for CI/CD](ssh_keys/README.md) | Using SSH keys in your CI pipelines. |
+| [Pipelines triggers](triggers/README.md) | Trigger pipelines through the API. |
+| [Integrate with Kubernetes clusters](../user/project/clusters/index.md) | Connect your project to Google Kubernetes Engine (GKE) or an existing Kubernetes cluster. |
+| [GitLab Runner](https://docs.gitlab.com/runner/) | Configure your own GitLab Runners to execute your scripts. |
+| [Optimize GitLab and Runner for large repositories](large_repositories/index.md) | Recommended strategies for handling large repos. |
+| [`.gitlab-ci.yml` full reference](yaml/README.md) | All the attributes you can use with GitLab CI/CD. |
+
+Note that certain operations can only be performed according to the
+[user](../user/permissions.md#gitlab-cicd-permissions) and [job](../user/permissions.md#job-permissions) permissions.
+
+## Feature set
+
+Use the vast GitLab CI/CD to easily configure it for specific purposes.
+Its feature set is listed on the table below according to DevOps stages.
+
+| Feature | Description |
+|:--------|:------------|
+| **Configure** ||
+| [Auto DevOps](../topics/autodevops/index.md) | Set up your app's entire lifecycle. |
+| [ChatOps](chatops/README.md) | Trigger CI jobs from chat, with results sent back to the channel. |
+|---+---|
+| **Verify** ||
+| [Browser Performance Testing](../user/project/merge_requests/browser_performance_testing.md) | Quickly determine the performance impact of pending code changes. |
+| [CI services](services/README.md) | Link Docker containers with your base image.|
+| [Code Quality](../user/project/merge_requests/code_quality.md) **[STARTER]** | Analyze your source code quality. |
+| [GitLab CI/CD for external repositories](ci_cd_for_external_repos/index.md) **[PREMIUM]** | Get the benefits of GitLab CI/CD combined with repositories in GitHub and BitBucket Cloud. |
+| [Interactive Web Terminals](interactive_web_terminal/index.md) **[CORE ONLY]** | Open an interactive web terminal to debug the running jobs. |
+| [JUnit tests](junit_test_reports.md) | Identify script failures directly on merge requests. |
+| [Using Docker images](docker/using_docker_images.md) | Use GitLab and GitLab Runner with Docker to build and test applications. |
+|---+---|
+| **Release** ||
+| [Auto Deploy](../topics/autodevops/index.md#auto-deploy) | Deploy your application to a production environment in a Kubernetes cluster. |
+| [Building Docker images](docker/using_docker_build.md) | Maintain Docker-based projects using GitLab CI/CD. |
+| [Canary Deployments](../user/project/canary_deployments.md) **[PREMIUM]** | Ship features to only a portion of your pods and let a percentage of your user base to visit the temporarily deployed feature. |
+| [Deploy Boards](../user/project/deploy_boards.md) **[PREMIUM]** | Check the current health and status of each CI/CD environment running on Kubernetes. |
+| [Feature Flags](../user/project/operations/feature_flags.md) **[PREMIUM]** | Deploy your features behind Feature Flags. |
+| [GitLab Pages](../user/project/pages/index.md) | Deploy static websites. |
+| [GitLab Releases](../user/project/releases/index.md) | Add release notes to Git tags. |
+| [Review Apps](review_apps/index.md) | Configure GitLab CI/CD to preview code changes. |
+|---+---|
+| **Secure** ||
+| [Container Scanning](../user/application_security/container_scanning/index.md) **[ULTIMATE]** | Check your Docker containers for known vulnerabilities.|
+| [Dependency Scanning](../user/application_security/dependency_scanning/index.md) **[ULTIMATE]** | Analyze your dependencies for known vulnerabilities. |
+| [License Management](../user/application_security/license_management/index.md) **[ULTIMATE]** | Search your project dependencies for their licenses. |
+| [Security Test reports](../user/project/merge_requests/index.md#security-reports-ultimate) **[ULTIMATE]** | Check for app vulnerabilities. |
+
+## Examples
+
+Find example project code and tutorials for using GitLab CI/CD with a variety of app frameworks, languages, and platforms
+on the [CI Examples](examples/README.md) page.
+
+GitLab also provides [example projects](https://gitlab.com/gitlab-examples) pre-configured to use GitLab CI/CD.
+
+## Administration **[CORE ONLY]**
+
+As a GitLab administrator, you can change the default behavior
+of GitLab CI/CD for:
- An [entire GitLab instance](../user/admin_area/settings/continuous_integration.md).
- Specific projects, using [pipelines settings](../user/project/pipelines/settings.md).
@@ -90,33 +145,49 @@ See also:
- [How to enable or disable GitLab CI/CD](enable_or_disable_ci.md).
- Other [CI administration settings](../administration/index.md#continuous-integration-settings).
-### Using Docker
+## References
-Docker is commonly used with GitLab CI/CD. Learn more about how to to accomplish this with the following
-documentation:
+### Why GitLab CI/CD?
-| Topic | Description |
-|:-------------------------------------------------------------------------|:-------------------------------------------------------------------------|
-| [Using Docker images](docker/using_docker_images.md) | Use GitLab and GitLab Runner with Docker to build and test applications. |
-| [Building Docker images with GitLab CI/CD](docker/using_docker_build.md) | Maintain Docker-based projects using GitLab CI/CD. |
+The following articles explain reasons to use GitLab CI/CD
+for your CI/CD infrastructure:
-Related topics include:
+- [Why we chose GitLab CI for our CI/CD solution](https://about.gitlab.com/2016/10/17/gitlab-ci-oohlala/)
+- [Building our web-app on GitLab CI](https://about.gitlab.com/2016/07/22/building-our-web-app-on-gitlab-ci/)
-- [Docker integration](docker/README.md).
-- [CI services (linked Docker containers)](services/README.md).
+See also the [Why CI/CD?](https://docs.google.com/presentation/d/1OGgk2Tcxbpl7DJaIOzCX4Vqg3dlwfELC3u2jEeCBbDk) presentation.
-## Why GitLab CI/CD?
+### Breaking changes
-The following articles explain reasons to use GitLab CI/CD for your CI/CD infrastructure:
+As GitLab CI/CD has evolved, certain breaking changes have
+been necessary. These are:
-- [Why we chose GitLab CI for our CI/CD solution](https://about.gitlab.com/2016/10/17/gitlab-ci-oohlala/)
-- [Building our web-app on GitLab CI](https://about.gitlab.com/2016/07/22/building-our-web-app-on-gitlab-ci/)
+#### 12.0
-See also the [Why CI/CD?](https://docs.google.com/presentation/d/1OGgk2Tcxbpl7DJaIOzCX4Vqg3dlwfELC3u2jEeCBbDk) presentation.
+- [Use refspec to clone/fetch git
+ repository](https://gitlab.com/gitlab-org/gitlab-runner/issues/4069).
+- [Old cache
+ configuration](https://gitlab.com/gitlab-org/gitlab-runner/issues/4070).
+- [Old metrics server
+ configuration](https://gitlab.com/gitlab-org/gitlab-runner/issues/4072).
+- [Remove
+ `FF_K8S_USE_ENTRYPOINT_OVER_COMMAND`](https://gitlab.com/gitlab-org/gitlab-runner/issues/4073).
+- [Remove Linux distributions that reach
+ EOL](https://gitlab.com/gitlab-org/gitlab-runner/merge_requests/1130).
+- [Update command line API for helper
+ images](https://gitlab.com/gitlab-org/gitlab-runner/issues/4013).
+- [Remove old `git clean`
+ flow](https://gitlab.com/gitlab-org/gitlab-runner/issues/4175).
+
+#### 11.0
+
+- No breaking changes.
+
+#### 10.0
-## Breaking changes
+- No breaking changes.
-As GitLab CI/CD has evolved, certain breaking changes have been necessary. These are:
+#### 9.0
- [CI variables renaming for GitLab 9.0](variables/deprecated_variables.md#gitlab-90-renamed-variables). Read about the
deprecated CI variables and what you should use for GitLab 9.0+.
diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md
index e079483e2b5..9a5a3624c73 100644
--- a/doc/ci/caching/index.md
+++ b/doc/ci/caching/index.md
@@ -1,3 +1,7 @@
+---
+type: index, concepts, howto
+---
+
# Cache dependencies in GitLab CI/CD
GitLab CI/CD provides a caching mechanism that can be used to save time
@@ -60,7 +64,7 @@ In summary:
- Caches are disabled if not defined globally or per job (using `cache:`).
- Caches are available for all jobs in your `.gitlab-ci.yml` if enabled globally.
-- Caches can be used by subsequent pipelines of that very same job (a script in
+- Caches can be used by subsequent pipelines of that same job (a script in
a stage) in which the cache was created (if not defined globally).
- Caches are stored where the Runner is installed **and** uploaded to S3 if
[distributed cache is enabled](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching).
@@ -87,7 +91,7 @@ cache, when declaring `cache` in your jobs, use one or a mix of the following:
that share their cache.
- [Use sticky Runners](../runners/README.md#locking-a-specific-runner-from-being-enabled-for-other-projects)
that will be only available to a particular project.
-- [Use a `key`](../yaml/README.md#cachekey) that fits your workflow (e.g.,
+- [Use a `key`](../yaml/README.md#cachekey) that fits your workflow (for example,
different caches on each branch). For that, you can take advantage of the
[CI/CD predefined variables](../variables/README.md#predefined-environment-variables).
@@ -100,7 +104,7 @@ From the perspective of the Runner, in order for cache to work effectively, one
of the following must be true:
- Use a single Runner for all your jobs.
-- Use multiple Runners (in autoscale mode or not) that use.
+- Use multiple Runners (in autoscale mode or not) that use
[distributed caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching),
where the cache is stored in S3 buckets (like shared Runners on GitLab.com).
- Use multiple Runners (not in autoscale mode) of the same architecture that
@@ -289,7 +293,7 @@ jobs inherit it. Gems are installed in `vendor/ruby/` and are cached per-branch:
#
# https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
#
-image: ruby:2.5
+image: ruby:2.6
# Cache gems in between builds
cache:
@@ -420,7 +424,7 @@ mismatch and a few ideas how to fix it.
Let's explore some examples.
----
+#### Examples
Let's assume you have only one Runner assigned to your project, so the cache
will be stored in the Runner's machine by default. If two jobs, A and B,
@@ -462,8 +466,6 @@ job B:
To fix that, use different `keys` for each job.
----
-
In another case, let's assume you have more than one Runners assigned to your
project, but the distributed cache is not enabled. We want the second time the
pipeline is run, `job A` and `job B` to re-use their cache (which in this case
@@ -526,3 +528,15 @@ Behind the scenes, this works by increasing a counter in the database, and the
value of that counter is used to create the key for the cache by appending an
integer to it: `-1`, `-2`, etc. After a push, a new key is generated and the
old cache is not valid anymore.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/ci/chatops/README.md b/doc/ci/chatops/README.md
index 5ecdf0f8c54..241134783da 100644
--- a/doc/ci/chatops/README.md
+++ b/doc/ci/chatops/README.md
@@ -1,3 +1,7 @@
+---
+type: index, concepts, howto
+---
+
# GitLab ChatOps
> **Notes:**
@@ -10,7 +14,10 @@ GitLab ChatOps provides a method to interact with CI/CD jobs through chat servic
## How it works
-GitLab ChatOps is built upon two existing features, [GitLab CI/CD](../README.md) and [Slack Slash Commmands](../../user/project/integrations/slack_slash_commands.md).
+GitLab ChatOps is built upon two existing features:
+
+- [GitLab CI/CD](../README.md).
+- [Slack Slash Commands](../../user/project/integrations/slack_slash_commands.md).
A new `run` action has been added to the [slash commands](../../integration/slash_commands.md), which takes two arguments: a `<job name>` to execute and the `<job arguments>`. When executed, ChatOps will look up the specified job name and attempt to match it to a corresponding job in [.gitlab-ci.yml](../yaml/README.md). If a matching job is found on `master`, a pipeline containing just that job is scheduled. Two additional [CI/CD variables](../variables/README.md#predefined-environment-variables) are passed to the job: `CHAT_INPUT` contains any additional arguments, and `CHAT_CHANNEL` is set to the name of channel the action was triggered in.
@@ -22,9 +29,9 @@ After the job has finished, its output is sent back to Slack provided it has com
Since ChatOps is built upon GitLab CI/CD, the job has all the same features and functions available. There a few best practices to consider however when creating ChatOps jobs:
-* It is strongly recommended to set `only: [chat]` so the job does not run as part of the standard CI pipeline.
-* If the job is set to `when: manual`, the pipeline will be created however the job will wait to be started.
-* It is important to keep in mind that there is very limited support for access control. If the user who triggered the slash command is a developer in the project, the job will run. The job itself can utilize existing [CI/CD variables](../variables/README.html#predefined-environment-variables) like `GITLAB_USER_ID` to perform additional rights validation, however these variables can be [overridden](../variables/README.html#priority-of-environment-variables).
+- It is strongly recommended to set `only: [chat]` so the job does not run as part of the standard CI pipeline.
+- If the job is set to `when: manual`, the pipeline will be created however the job will wait to be started.
+- It is important to keep in mind that there is limited support for access control. If the user who triggered the slash command is a developer in the project, the job will run. The job itself can utilize existing [CI/CD variables](../variables/README.html#predefined-environment-variables) like `GITLAB_USER_ID` to perform additional rights validation, however these variables can be [overridden](../variables/README.html#priority-of-environment-variables).
### Controlling the ChatOps reply
@@ -59,3 +66,15 @@ You can find and download the official GitLab ChatOps icon here.
![GitLab ChatOps bot icon](img/gitlab-chatops-icon-small.png)
[Download bigger image](img/gitlab-chatops-icon.png)
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md b/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
new file mode 100644
index 00000000000..bbb25c78ec5
--- /dev/null
+++ b/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
@@ -0,0 +1,166 @@
+---
+type: howto
+---
+
+# Using GitLab CI/CD with a Bitbucket Cloud repository **[PREMIUM]**
+
+GitLab CI/CD can be used with Bitbucket Cloud by:
+
+1. Creating a [CI/CD project](../../user/project/ci_cd_for_external_repo.md).
+1. Connecting your Git repository via URL.
+
+To use GitLab CI/CD with a Bitbucket Cloud repository:
+
+1. In GitLab create a **CI/CD for external repo**, select **Repo by URL** and
+ create the project.
+
+ ![Create project](img/external_repository.png)
+
+ GitLab will import the repository and enable [Pull Mirroring][pull-mirroring].
+
+1. In GitLab create a
+ [Personal Access Token](../../user/profile/personal_access_tokens.md)
+ with `api` scope. This will be used to authenticate requests from the web
+ hook that will be created in Bitbucket to notify GitLab of new commits.
+
+1. In Bitbucket, from **Settings > Webhooks**, create a new web hook to notify
+ GitLab of new commits.
+
+ The web hook URL should be set to the GitLab API to trigger pull mirroring,
+ using the Personal Access Token we just generated for authentication.
+
+ ```text
+ https://gitlab.com/api/v4/projects/<NAMESPACE>%2F<PROJECT>/mirror/pull?private_token=<PERSONAL_ACCESS_TOKEN>
+ ```
+
+ The web hook Trigger should be set to 'Repository Push'.
+
+ ![Bitbucket Cloud webhook](img/bitbucket_webhook.png)
+
+ After saving, test the web hook by pushing a change to your Bitbucket
+ repository.
+
+1. In Bitbucket, create an **App Password** from **Bitbucket Settings > App
+ Passwords** to authenticate the build status script setting commit build
+ statuses in Bitbucket. Repository write permissions are required.
+
+ ![Bitbucket Cloud webhook](img/bitbucket_app_password.png)
+
+1. In GitLab, from **Settings > CI/CD > Environment variables**, add variables to allow
+ communication with Bitbucket via the Bitbucket API:
+
+ `BITBUCKET_ACCESS_TOKEN`: the Bitbucket app password created above.
+
+ `BITBUCKET_USERNAME`: the username of the Bitbucket account.
+
+ `BITBUCKET_NAMESPACE`: set this if your GitLab and Bitbucket namespaces differ.
+
+ `BITBUCKET_REPOSITORY`: set this if your GitLab and Bitbucket project names differ.
+
+1. In Bitbucket, add a script to push the pipeline status to Bitbucket.
+
+ > Note: changes made in GitLab will be overwritten by any changes made
+ > upstream in Bitbucket.
+
+ Create a file `build_status` and insert the script below and run
+ `chmod +x build_status` in your terminal to make the script executable.
+
+ ```bash
+ #!/usr/bin/env bash
+
+ # Push GitLab CI/CD build status to Bitbucket Cloud
+
+ if [ -z "$BITBUCKET_ACCESS_TOKEN" ]; then
+ echo "ERROR: BITBUCKET_ACCESS_TOKEN is not set"
+ exit 1
+ fi
+ if [ -z "$BITBUCKET_USERNAME" ]; then
+ echo "ERROR: BITBUCKET_USERNAME is not set"
+ exit 1
+ fi
+ if [ -z "$BITBUCKET_NAMESPACE" ]; then
+ echo "Setting BITBUCKET_NAMESPACE to $CI_PROJECT_NAMESPACE"
+ BITBUCKET_NAMESPACE=$CI_PROJECT_NAMESPACE
+ fi
+ if [ -z "$BITBUCKET_REPOSITORY" ]; then
+ echo "Setting BITBUCKET_REPOSITORY to $CI_PROJECT_NAME"
+ BITBUCKET_REPOSITORY=$CI_PROJECT_NAME
+ fi
+
+ BITBUCKET_API_ROOT="https://api.bitbucket.org/2.0"
+ BITBUCKET_STATUS_API="$BITBUCKET_API_ROOT/repositories/$BITBUCKET_NAMESPACE/$BITBUCKET_REPOSITORY/commit/$CI_COMMIT_SHA/statuses/build"
+ BITBUCKET_KEY="ci/gitlab-ci/$CI_JOB_NAME"
+
+ case "$BUILD_STATUS" in
+ running)
+ BITBUCKET_STATE="INPROGRESS"
+ BITBUCKET_DESCRIPTION="The build is running!"
+ ;;
+ passed)
+ BITBUCKET_STATE="SUCCESSFUL"
+ BITBUCKET_DESCRIPTION="The build passed!"
+ ;;
+ failed)
+ BITBUCKET_STATE="FAILED"
+ BITBUCKET_DESCRIPTION="The build failed."
+ ;;
+ esac
+
+ echo "Pushing status to $BITBUCKET_STATUS_API..."
+ curl --request POST $BITBUCKET_STATUS_API \
+ --user $BITBUCKET_USERNAME:$BITBUCKET_ACCESS_TOKEN \
+ --header "Content-Type:application/json" \
+ --silent \
+ --data "{ \"state\": \"$BITBUCKET_STATE\", \"key\": \"$BITBUCKET_KEY\", \"description\":
+ \"$BITBUCKET_DESCRIPTION\",\"url\": \"$CI_PROJECT_URL/-/jobs/$CI_JOB_ID\" }"
+ ```
+
+1. Still in Bitbucket, create a `.gitlab-ci.yml` file to use the script to push
+ pipeline success and failures to Bitbucket.
+
+ ```yaml
+ stages:
+ - test
+ - ci_status
+
+ unit-tests:
+ script:
+ - echo "Success. Add your tests!"
+
+ success:
+ stage: ci_status
+ before_script:
+ - ""
+ after_script:
+ - ""
+ script:
+ - BUILD_STATUS=passed BUILD_KEY=push ./build_status
+ when: on_success
+
+ failure:
+ stage: ci_status
+ before_script:
+ - ""
+ after_script:
+ - ""
+ script:
+ - BUILD_STATUS=failed BUILD_KEY=push ./build_status
+ when: on_failure
+ ```
+
+GitLab is now configured to mirror changes from Bitbucket, run CI/CD pipelines
+configured in `.gitlab-ci.yml` and push the status to Bitbucket.
+
+[pull-mirroring]: ../../workflow/repository_mirroring.md#pulling-from-a-remote-repository-starter
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/ci/ci_cd_for_external_repos/github_integration.md b/doc/ci/ci_cd_for_external_repos/github_integration.md
new file mode 100644
index 00000000000..53b36181062
--- /dev/null
+++ b/doc/ci/ci_cd_for_external_repos/github_integration.md
@@ -0,0 +1,133 @@
+---
+type: howto
+---
+
+# Using GitLab CI/CD with a GitHub repository **[PREMIUM]**
+
+GitLab CI/CD can be used with **GitHub.com** and **GitHub Enterprise** by
+creating a [CI/CD project](index.md) to connect your GitHub repository to
+GitLab.
+
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+Watch a video on [Using GitLab CI/CD pipelines with GitHub repositories](https://www.youtube.com/watch?v=qgl3F2j-1cI).
+
+## Connect with GitHub integration
+
+If the [GitHub integration](../../integration/github.md) has been enabled by your GitLab
+administrator:
+
+1. In GitLab create a **CI/CD for external repo** project and select
+ **GitHub**.
+
+ ![Create project](img/github_omniauth.png)
+
+1. Once authenticated, you will be redirected to a list of your repositories to
+ connect. Click **Connect** to select the repository.
+
+ ![Create project](img/github_repo_list.png)
+
+1. In GitHub, add a `.gitlab-ci.yml` to [configure GitLab CI/CD](../quick_start/README.md).
+
+GitLab will:
+
+1. Import the project.
+1. Enable [Pull Mirroring](../../workflow/repository_mirroring.md#pulling-from-a-remote-repository-starter).
+1. Enable [GitHub project integration](../../user/project/integrations/github.md).
+1. Create a web hook on GitHub to notify GitLab of new commits.
+
+CAUTION: **Caution:**
+Due to a 10-token limitation on the [GitHub OAuth Implementation](https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/#creating-multiple-tokens-for-oauth-apps),
+if you import more than 10 times, your oldest imported project's token will be
+revoked. See issue [#9147](https://gitlab.com/gitlab-org/gitlab-ee/issues/9147)
+for more information.
+
+## Connect with Personal Access Token
+
+NOTE: **Note:**
+Personal access tokens can only be used to connect GitHub.com
+repositories to GitLab.
+
+If you are not using the [GitHub integration](../../integration/github.md), you can
+still perform a one-off authorization with GitHub to grant GitLab access your
+repositories:
+
+1. Open <https://github.com/settings/tokens/new> to create a **Personal Access
+ Token**. This token with be used to access your repository and push commit
+ statuses to GitHub.
+
+ The `repo` and `admin:repo_hook` should be enable to allow GitLab access to
+ your project, update commit statuses, and create a web hook to notify
+ GitLab of new commits.
+
+1. In GitLab create a **CI/CD for external repo** project and select
+ **GitHub**.
+
+ ![Create project](img/github_omniauth.png)
+
+1. Paste the token into the **Personal access token** field and click **List
+ Repositories**. Click **Connect** to select the repository.
+
+1. In GitHub, add a `.gitlab-ci.yml` to [configure GitLab CI/CD](../quick_start/README.md).
+
+GitLab will import the project, enable [Pull Mirroring](../../workflow/repository_mirroring.md#pulling-from-a-remote-repository-starter), enable
+[GitHub project integration](../../user/project/integrations/github.md), and create a web hook
+on GitHub to notify GitLab of new commits.
+
+## Connect manually
+
+NOTE: **Note:**
+To use **GitHub Enterprise** with **GitLab.com** use this method.
+
+If the [GitHub integration](../../integration/github.md) is not enabled, or is enabled
+for a different GitHub instance, you GitLab CI/CD can be manually enabled for
+your repository:
+
+1. In GitHub open <https://github.com/settings/tokens/new> create a **Personal
+ Access Token.** GitLab will use this token to access your repository and
+ push commit statuses.
+
+ Enter a **Token description** and update the scope to allow:
+
+ `repo` so that GitLab can access your project and update commit statuses
+
+1. In GitLab create a **CI/CD project** using the Git URL option and the HTTPS
+ URL for your GitHub repository. If your project is private, use the personal
+ access token you just created for authentication.
+
+ GitLab will automatically configure polling-based pull mirroring.
+
+1. Still in GitLab, enable the [GitHub project integration](../../user/project/integrations/github.md)
+ from **Settings > Integrations.**
+
+ Check the **Active** checkbox to enable the integration, paste your
+ personal access token and HTTPS repository URL into the form, and **Save.**
+
+1. Still in GitLab create a **Personal Access Token** with `API` scope to
+ authenticate the GitHub web hook notifying GitLab of new commits.
+
+1. In GitHub from **Settings > Webhooks** create a web hook to notify GitLab of
+ new commits.
+
+ The web hook URL should be set to the GitLab API to
+ [trigger pull mirroring](https://docs.gitlab.com/ee/api/projects.html#start-the-pull-mirroring-process-for-a-project-starter),
+ using the GitLab personal access token we just created.
+
+ ```
+ https://gitlab.com/api/v4/projects/<NAMESPACE>%2F<PROJECT>/mirror/pull?private_token=<PERSONAL_ACCESS_TOKEN>
+ ```
+
+ ![Create web hook](img/github_push_webhook.png)
+
+1. In GitHub add a `.gitlab-ci.yml` to configure GitLab CI/CD.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/ci/ci_cd_for_external_repos/img/bitbucket_app_password.png b/doc/ci/ci_cd_for_external_repos/img/bitbucket_app_password.png
new file mode 100644
index 00000000000..ac5be3c3058
--- /dev/null
+++ b/doc/ci/ci_cd_for_external_repos/img/bitbucket_app_password.png
Binary files differ
diff --git a/doc/ci/ci_cd_for_external_repos/img/bitbucket_webhook.png b/doc/ci/ci_cd_for_external_repos/img/bitbucket_webhook.png
new file mode 100644
index 00000000000..0a3476d9035
--- /dev/null
+++ b/doc/ci/ci_cd_for_external_repos/img/bitbucket_webhook.png
Binary files differ
diff --git a/doc/ci/ci_cd_for_external_repos/img/ci_cd_for_external_repo.png b/doc/ci/ci_cd_for_external_repos/img/ci_cd_for_external_repo.png
new file mode 100644
index 00000000000..f068688146b
--- /dev/null
+++ b/doc/ci/ci_cd_for_external_repos/img/ci_cd_for_external_repo.png
Binary files differ
diff --git a/doc/ci/ci_cd_for_external_repos/img/external_repository.png b/doc/ci/ci_cd_for_external_repos/img/external_repository.png
new file mode 100644
index 00000000000..b850d91f56b
--- /dev/null
+++ b/doc/ci/ci_cd_for_external_repos/img/external_repository.png
Binary files differ
diff --git a/doc/ci/ci_cd_for_external_repos/img/github_omniauth.png b/doc/ci/ci_cd_for_external_repos/img/github_omniauth.png
new file mode 100644
index 00000000000..71a3a057a41
--- /dev/null
+++ b/doc/ci/ci_cd_for_external_repos/img/github_omniauth.png
Binary files differ
diff --git a/doc/ci/ci_cd_for_external_repos/img/github_push_webhook.png b/doc/ci/ci_cd_for_external_repos/img/github_push_webhook.png
new file mode 100644
index 00000000000..e8c17d664e1
--- /dev/null
+++ b/doc/ci/ci_cd_for_external_repos/img/github_push_webhook.png
Binary files differ
diff --git a/doc/ci/ci_cd_for_external_repos/img/github_repo_list.png b/doc/ci/ci_cd_for_external_repos/img/github_repo_list.png
new file mode 100644
index 00000000000..73579dd3cf1
--- /dev/null
+++ b/doc/ci/ci_cd_for_external_repos/img/github_repo_list.png
Binary files differ
diff --git a/doc/ci/ci_cd_for_external_repos/index.md b/doc/ci/ci_cd_for_external_repos/index.md
new file mode 100644
index 00000000000..d46e451c609
--- /dev/null
+++ b/doc/ci/ci_cd_for_external_repos/index.md
@@ -0,0 +1,39 @@
+---
+type: index, howto
+---
+
+# GitLab CI/CD for external repositories **[PREMIUM]**
+
+>[Introduced][ee-4642] in [GitLab Premium][eep] 10.6.
+
+NOTE: **Note:**
+This feature [is available for free](https://about.gitlab.com/2019/03/21/six-more-months-ci-cd-github/) to
+GitLab.com users until September 22nd, 2019.
+
+GitLab CI/CD can be used with:
+
+- [GitHub](github_integration.md).
+- [Bitbucket Cloud](bitbucket_integration.md).
+- Any other Git server.
+
+Instead of moving your entire project to GitLab, you can connect your
+external repository to get the benefits of GitLab CI/CD.
+
+Connecting an external repository will set up [repository mirroring][mirroring]
+and create a lightweight project where issues, merge requests, wiki, and
+snippets disabled. These features
+[can be re-enabled later][settings].
+
+To connect to an external repository:
+
+1. From your GitLab dashboard, click **New project**.
+1. Switch to the **CI/CD for external repo** tab.
+1. Choose **GitHub** or **Repo by URL**.
+1. The next steps are similar to the [import flow](../../user/project/import/index.md).
+
+![CI/CD for external repository project creation](img/ci_cd_for_external_repo.png)
+
+[ee-4642]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/4642
+[eep]: https://about.gitlab.com/pricing/
+[mirroring]: ../../workflow/repository_mirroring.md
+[settings]: ../../user/project/settings/index.md#sharing-and-permissions
diff --git a/doc/ci/docker/README.md b/doc/ci/docker/README.md
index 446f5b54f0c..f76471b50f2 100644
--- a/doc/ci/docker/README.md
+++ b/doc/ci/docker/README.md
@@ -1,9 +1,13 @@
---
comments: false
+type: index
---
# Docker integration
+GitLab CI/CD can be combined with [Docker](https://www.docker.com) to enable
+integration between the two.
+
The following documentation is available for using GitLab CI/CD with Docker:
- [Using Docker images](using_docker_images.md).
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index 5222cc45bc4..b4c4bea6447 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -1,16 +1,18 @@
+---
+type: concepts, howto
+---
+
# Building Docker images with GitLab CI/CD
GitLab CI/CD allows you to use Docker Engine to build and test docker-based projects.
-TIP: **Tip:**
-This also allows to you to use `docker-compose` and other docker-enabled tools.
One of the new trends in Continuous Integration/Deployment is to:
-1. Create an application image
-1. Run tests against the created image
-1. Push image to a remote registry
-1. Deploy to a server from the pushed image
+1. Create an application image.
+1. Run tests against the created image.
+1. Push image to a remote registry.
+1. Deploy to a server from the pushed image.
It's also useful when your application already has the `Dockerfile` that can be
used to create and test an image:
@@ -75,7 +77,7 @@ GitLab Runner then executes job scripts as the `gitlab-runner` user.
- docker run my-docker-image /script/to/run/tests
```
-1. You can now use `docker` command and install `docker-compose` if needed.
+1. You can now use `docker` command (and **install** `docker-compose` if needed).
NOTE: **Note:**
By adding `gitlab-runner` to the `docker` group you are effectively granting `gitlab-runner` full root permissions.
@@ -85,8 +87,10 @@ For more information please read [On Docker security: `docker` group considered
The second approach is to use the special docker-in-docker (dind)
[Docker image](https://hub.docker.com/_/docker/) with all tools installed
-(`docker` and `docker-compose`) and run the job script in context of that
-image in privileged mode.
+(`docker`) and run the job script in context of that
+image in privileged mode.
+
+NOTE: **Note:** `docker-compose` is not part of docker-in-docker (dind). In case you'd like to use `docker-compose` in your CI builds, please follow the [installation instructions for docker-compose](https://docs.docker.com/compose/install/) provided by docker.
In order to do that, follow the steps:
@@ -113,7 +117,7 @@ In order to do that, follow the steps:
The above command will create a `config.toml` entry similar to this:
- ```
+ ```toml
[[runners]]
url = "https://gitlab.com/"
token = TOKEN
@@ -142,9 +146,12 @@ In order to do that, follow the steps:
# The 'docker' hostname is the alias of the service container as described at
# https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services
#
- # Note that if you're using Kubernetes executor, the variable should be set to
- # tcp://localhost:2375 because of how Kubernetes executor connects services
+ # Note that if you're using the Kubernetes executor, the variable should be set to
+ # tcp://localhost:2375/ because of how the Kubernetes executor connects services
# to the job container
+ # DOCKER_HOST: tcp://localhost:2375/
+ #
+ # For non-Kubernetes executors, we use tcp://docker:2375/
DOCKER_HOST: tcp://docker:2375/
# When using dind, it's wise to use the overlayfs driver for
# improved performance.
@@ -224,7 +231,7 @@ In order to do that, follow the steps:
The above command will create a `config.toml` entry similar to this:
- ```
+ ```toml
[[runners]]
url = "https://gitlab.com/"
token = REGISTRATION_TOKEN
@@ -267,9 +274,9 @@ aware of the following implications:
create containers with specific names, they may conflict with each other.
- Sharing files and directories from the source repo into containers may not
work as expected since volume mounting is done in the context of the host
- machine, not the build container, e.g.:
+ machine, not the build container. For example:
- ```
+ ```sh
docker run --rm -t -i -v $(pwd)/src:/home/app/src test-image:latest run_app_tests
```
@@ -334,7 +341,7 @@ NOTE: **Note:**
The shared Runners on GitLab.com use the `overlay2` driver by default.
By default, when using `docker:dind`, Docker uses the `vfs` storage driver which
-copies the filesystem on every run. This is a very disk-intensive operation
+copies the filesystem on every run. This is a disk-intensive operation
which can be avoided if a different driver is used, for example `overlay2`.
### Requirements
@@ -342,13 +349,13 @@ which can be avoided if a different driver is used, for example `overlay2`.
1. Make sure a recent kernel is used, preferably `>= 4.2`.
1. Check whether the `overlay` module is loaded:
- ```
+ ```sh
sudo lsmod | grep overlay
```
If you see no result, then it isn't loaded. To load it use:
- ```
+ ```sh
sudo modprobe overlay
```
@@ -356,7 +363,7 @@ which can be avoided if a different driver is used, for example `overlay2`.
On Ubuntu systems, this is done by editing `/etc/modules`. Just add the
following line into it:
- ```
+ ```text
overlay
```
@@ -364,7 +371,7 @@ which can be avoided if a different driver is used, for example `overlay2`.
You can enable the driver for each project individually by editing the project's `.gitlab-ci.yml`:
-```
+```yaml
variables:
DOCKER_DRIVER: overlay2
```
@@ -568,3 +575,15 @@ deploy:
[docker-cap]: https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities
[2fa]: ../../user/profile/account/two_factor_authentication.md
[pat]: ../../user/profile/personal_access_tokens.md
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index 13c26bc5f47..29578efacbb 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -1,3 +1,7 @@
+---
+type: concepts, howto
+---
+
# Using Docker images
GitLab CI in conjunction with [GitLab Runner](../runners/README.md) can use
@@ -45,10 +49,10 @@ The `image` keyword is the name of the Docker image the Docker executor
will run to perform the CI tasks.
By default, the executor will only pull images from [Docker Hub][hub],
-but this can be configured in the `gitlab-runner/config.toml` by setting
+however this can be configured in the `gitlab-runner/config.toml` by setting
the [Docker pull policy][] to allow using local images.
-For more information about images and Docker Hub please read
+For more information about images and Docker Hub, please read
the [Docker Fundamentals][] documentation.
## What is a service
@@ -95,8 +99,8 @@ required for the CI/CD job to proceed and is accessed by network.
To make sure this works, the Runner:
-1. checks which ports are exposed from the container by default
-1. starts a special container that waits for these ports to be accessible
+1. Checks which ports are exposed from the container by default.
+1. Starts a special container that waits for these ports to be accessible.
When the second stage of the check fails, either because there is no opened port in the
service, or the service was not started properly before the timeout and the port is not
@@ -106,7 +110,7 @@ In most cases it will affect the job, but there may be situations when the job
will still succeed even if that warning was printed. For example:
- The service was started a little after the warning was raised, and the job is
- not using the linked service from the very beginning. In that case, when the
+ not using the linked service from the beginning. In that case, when the
job needed to access the service, it may have been already there waiting for
connections.
- The service container is not providing any networking service, but it's doing
@@ -143,9 +147,9 @@ job:
If you need to have `php`, `node` and `go` available for your script, you should
either:
-- choose an existing Docker image that contains all required tools, or
-- create your own Docker image, which will have all the required tools included
- and use that in your job
+- Choose an existing Docker image that contains all required tools.
+- Create your own Docker image, which will have all the required tools included
+ and use that in your job.
### Accessing the services
@@ -167,18 +171,18 @@ access to it from your build container under two hostnames to choose from:
- `tutum-wordpress`
- `tutum__wordpress`
->**Note:**
+NOTE: **Note:**
Hostnames with underscores are not RFC valid and may cause problems in 3rd party
applications.
The default aliases for the service's hostname are created from its image name
following these rules:
-- Everything after the colon (`:`) is stripped
+- Everything after the colon (`:`) is stripped.
- Slash (`/`) is replaced with double underscores (`__`) and the primary alias
- is created
+ is created.
- Slash (`/`) is replaced with a single dash (`-`) and the secondary alias is
- created (requires GitLab Runner v1.1.0 or higher)
+ created (requires GitLab Runner v1.1.0 or higher).
To override the default behavior, you can
[specify a service alias](#available-settings-for-services).
@@ -333,7 +337,7 @@ services:
```
The Runner will still start two containers using the `mysql:latest` image,
-but now each of them will also be accessible with the alias configured
+however now each of them will also be accessible with the alias configured
in `.gitlab-ci.yml` file.
### Setting a command for the service
@@ -408,8 +412,6 @@ you should check which one your Runner is using. Specifically:
The syntax of `image:entrypoint` is similar to [Dockerfile's `ENTRYPOINT`][entrypoint].
-----
-
Let's assume you have a `super/sql:experimental` image with some SQL database
inside it and you would like to use it as a base image for your job because you
want to execute some tests with this database binary. Let's also assume that
@@ -443,7 +445,7 @@ image:
Look for the `[runners.docker]` section:
-```
+```toml
[runners.docker]
image = "ruby:2.1"
services = ["mysql:latest", "postgres:latest"]
@@ -464,16 +466,39 @@ that runner.
> - If the repository is private you need to authenticate your GitLab Runner in the
> registry. Learn more about how [GitLab Runner works in this case][runner-priv-reg].
+To access private container registries, the GitLab Runner process can use:
+
+- [Statically defined credentials](#using-statically-defined-credentials). That is, a username and password for a specific registry.
+- [Credentials Store](#using-credentials-store). For more information, see [the relevant Docker documentation](https://docs.docker.com/engine/reference/commandline/login/#credentials-store).
+- [Credential Helpers](#using-credential-helpers). For more information, see [the relevant Docker documentation](https://docs.docker.com/engine/reference/commandline/login/#credential-helpers).
+
+To define which should be used, the GitLab Runner process reads the configuration in the following order:
+
+- `DOCKER_AUTH_CONFIG` variable provided as either:
+ - A [variable](../variables/README.md#gitlab-cicd-environment-variables) in `.gitlab-ci.yml`.
+ - A project's variables stored on the projects **Settings > CI/CD** page.
+- `DOCKER_AUTH_CONFIG` variable provided as environment variable in `config.toml` of the Runner.
+- `config.json` file placed in `$HOME/docker` directory of the user running GitLab Runner process.
+ If the `--user` flag is provided to run the GitLab Runner child processes as unprivileged user,
+ the home directory of the main GitLab Runner process user will be used.
+
+NOTE: **Note:**
+GitLab Runner reads this configuration **only** from `config.toml` and ignores it if
+it's provided as an environment variable. This is because GitLab Runnner uses **only**
+`config.toml` configuration and doesn't interpolate **ANY** environment variables at
+runtime.
+
+### Using statically-defined credentials
As an example, let's assume that you want to use the `registry.example.com:5000/private/image:latest`
image which is private and requires you to login into a private container registry.
Let's also assume that these are the login credentials:
-| Key | Value |
-|----------|---------------------------|
-| registry | registry.example.com:5000 |
-| username | my_username |
-| password | my_password |
+| Key | Value |
+|:---------|:----------------------------|
+| registry | `registry.example.com:5000` |
+| username | `my_username` |
+| password | `my_password` |
To configure access for `registry.example.com:5000`, follow these steps:
@@ -534,12 +559,85 @@ To configure access for `registry.example.com:5000`, follow these steps:
You can add configuration for as many registries as you want, adding more
registries to the `"auths"` hash as described above.
-NOTE: **Note:** The full `hostname:port` combination is required everywhere
+NOTE: **Note:**
+The full `hostname:port` combination is required everywhere
for the Runner to match the `DOCKER_AUTH_CONFIG`. For example, if
`registry.example.com:5000/namespace/image:tag` is specified in `.gitlab-ci.yml`,
then the `DOCKER_AUTH_CONFIG` must also specify `registry.example.com:5000`.
Specifying only `registry.example.com` will not work.
+
+### Using Credentials Store
+
+> Support for using Credentials Store was added in GitLab Runner 9.5.
+
+To configure credentials store, follow these steps:
+
+1. To use a credentials store, you need an external helper program to interact with a specific keychain or external store.
+Make sure helper program is available in GitLab Runner `$PATH`.
+
+1. Make GitLab Runner use it. There are two ways to accomplish this. Either:
+ - Create a
+ [variable](../variables/README.md#gitlab-cicd-environment-variables)
+ `DOCKER_AUTH_CONFIG` with the content of the
+ Docker configuration file as the value:
+
+ ```json
+ {
+ "credsStore": "osxkeychain"
+ }
+ ```
+
+ - Or, if you are running self-hosted Runners, add the above JSON to
+ `${GITLAB_RUNNER_HOME}/.docker/config.json`. GitLab Runner will read this config file
+ and will use the needed helper for this specific repository.
+
+NOTE: **Note:** `credsStore` is used to access ALL the registries.
+If you will want to use both images from private registry and public images from DockerHub,
+pulling from DockerHub will fail, because Docker daemon will try to use the same credentials for **ALL** the registries.
+
+### Using Credential Helpers
+
+> Support for using Credential Helpers was added in GitLab Runner 12.0
+
+As an example, let's assume that you want to use the `aws_account_id.dkr.ecr.region.amazonaws.com/private/image:latest`
+image which is private and requires you to log in into a private container registry.
+
+To configure access for `aws_account_id.dkr.ecr.region.amazonaws.com`, follow these steps:
+
+1. Make sure `docker-credential-ecr-login` is available in GitLab Runner's `$PATH`.
+
+1. Make GitLab Runner use it. There are two ways to accomplish this. Either:
+ - Create a [variable](../variables/README.md#gitlab-cicd-environment-variables)
+ `DOCKER_AUTH_CONFIG` with the content of the
+ Docker configuration file as the value:
+
+ ```json
+ {
+ "credHelpers": {
+ "aws_account_id.dkr.ecr.region.amazonaws.com": "ecr-login"
+ }
+ }
+ ```
+
+ - Or, if you are running self-hosted Runners,
+ add the above JSON to `${GITLAB_RUNNER_HOME}/.docker/config.json`.
+ GitLab Runner will read this config file and will use the needed helper for this
+ specific repository.
+
+1. You can now use any private image from `aws_account_id.dkr.ecr.region.amazonaws.com` defined in
+ `image` and/or `services` in your `.gitlab-ci.yml` file:
+
+ ```yaml
+ image: aws_account_id.dkr.ecr.region.amazonaws.com/private/image:latest
+ ```
+
+ In the example above, GitLab Runner will look at `aws_account_id.dkr.ecr.region.amazonaws.com` for the
+ image `private/image:latest`.
+
+You can add configuration for as many registries as you want, adding more
+registries to the `"credHelpers"` hash as described above.
+
## Configuring services
Many services accept environment variables which allow you to easily change
@@ -551,8 +649,9 @@ service containers.
For all possible configuration variables check the documentation of each image
provided in their corresponding Docker hub page.
-*Note: All variables will be passed to all services containers. It's not
-designed to distinguish which variable should go where.*
+NOTE: **Note:**
+All variables will be passed to all services containers. It's not
+designed to distinguish which variable should go where.
### PostgreSQL service example
@@ -582,8 +681,9 @@ time.
## How to debug a job locally
-*Note: The following commands are run without root privileges. You should be
-able to run Docker with your regular user account.*
+NOTE: **Note:**
+The following commands are run without root privileges. You should be
+able to run Docker with your regular user account.
First start with creating a file named `build_script`:
@@ -602,7 +702,7 @@ is specific to your project.
Then create some service containers:
-```
+```sh
docker run -d --name service-mysql mysql:latest
docker run -d --name service-postgres postgres:latest
```
@@ -614,7 +714,7 @@ respectively. They will both run in the background (`-d`).
Finally, create a build container by executing the `build_script` file we
created earlier:
-```
+```sh
docker run --name build -i --link=service-mysql:mysql --link=service-postgres:postgres ruby:2.1 /bin/bash < build_script
```
@@ -626,7 +726,7 @@ piped using STDIN to the bash interpreter which in turn executes the
When you finish testing and no longer need the containers, you can remove them
with:
-```
+```sh
docker rm -f -v build service-mysql service-postgres
```
diff --git a/doc/ci/docker/using_kaniko.md b/doc/ci/docker/using_kaniko.md
index f354cdb398e..50f1ac3d54a 100644
--- a/doc/ci/docker/using_kaniko.md
+++ b/doc/ci/docker/using_kaniko.md
@@ -1,3 +1,7 @@
+---
+type: howto
+---
+
# Building images with kaniko and GitLab CI/CD
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/45512) in GitLab 11.2.
@@ -9,17 +13,18 @@ container images from a Dockerfile, inside a container or Kubernetes cluster.
kaniko solves two problems with using the
[docker-in-docker build](using_docker_build.md#use-docker-in-docker-executor) method:
-1. Docker-in-docker requires [privileged mode](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities)
- in order to function, which is a significant security concern.
-1. Docker-in-docker generally incurs a performance penalty and can be quite slow.
+- Docker-in-docker requires [privileged mode](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities)
+ in order to function, which is a significant security concern.
+- Docker-in-docker generally incurs a performance penalty and can be quite slow.
## Requirements
In order to utilize kaniko with GitLab, a [GitLab Runner](https://docs.gitlab.com/runner/)
-using either the [Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes.html),
-[Docker](https://docs.gitlab.com/runner/executors/docker.html), or
-[Docker Machine](https://docs.gitlab.com/runner/executors/docker_machine.html)
-executors is required.
+using one of the following executors is required:
+
+- [Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes.html).
+- [Docker](https://docs.gitlab.com/runner/executors/docker.html).
+- [Docker Machine](https://docs.gitlab.com/runner/executors/docker_machine.html).
## Building a Docker image with kaniko
@@ -34,14 +39,17 @@ few important details:
- A Docker `config.json` file needs to be created with the authentication
information for the desired container registry.
----
+In the following example, kaniko is used to:
+
+1. Build a Docker image.
+1. Then push it to [GitLab Container Registry](../../user/project/container_registry.md).
-In the following example, kaniko is used to build a Docker image and then push
-it to [GitLab Container Registry](../../user/project/container_registry.md).
The job will run only when a tag is pushed. A `config.json` file is created under
`/kaniko/.docker` with the needed GitLab Container Registry credentials taken from the
[environment variables](../variables/README.md#predefined-environment-variables)
-GitLab CI/CD provides. In the last step, kaniko uses the `Dockerfile` under the
+GitLab CI/CD provides.
+
+In the last step, kaniko uses the `Dockerfile` under the
root directory of the project, builds the Docker image and pushes it to the
project's Container Registry while tagging it with the Git tag:
@@ -80,3 +88,15 @@ store:
...
-----END CERTIFICATE-----" >> /kaniko/ssl/certs/ca-certificates.crt
```
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/ci/enable_or_disable_ci.md b/doc/ci/enable_or_disable_ci.md
index 7aa7de97c43..56200142055 100644
--- a/doc/ci/enable_or_disable_ci.md
+++ b/doc/ci/enable_or_disable_ci.md
@@ -1,25 +1,32 @@
+---
+type: howto
+---
+
# How to enable or disable GitLab CI/CD
-To effectively use GitLab CI/CD, you need a valid [`.gitlab-ci.yml`](yaml/README.md)
-file present at the root directory of your project and a
-[runner](runners/README.md) properly set up. You can read our
-[quick start guide](quick_start/README.md) to get you started.
+To effectively use GitLab CI/CD, you need:
+
+- A valid [`.gitlab-ci.yml`](yaml/README.md) file present at the root directory
+ of your project.
+- A [runner](runners/README.md) properly set up.
+
+You can read our [quick start guide](quick_start/README.md) to get you started.
If you are using an external CI/CD server like Jenkins or Drone CI, it is advised
to disable GitLab CI/CD in order to not have any conflicts with the commits status
API.
----
-
GitLab CI/CD is exposed via the `/pipelines` and `/jobs` pages of a project.
Disabling GitLab CI/CD in a project does not delete any previous jobs.
In fact, the `/pipelines` and `/jobs` pages can still be accessed, although
it's hidden from the left sidebar menu.
-GitLab CI/CD is enabled by default on new installations and can be disabled either
-individually under each project's settings, or site-wide by modifying the
-settings in `gitlab.yml` and `gitlab.rb` for source and Omnibus installations
-respectively.
+GitLab CI/CD is enabled by default on new installations and can be disabled
+either:
+
+- Individually under each project's settings.
+- Site-wide by modifying the settings in `gitlab.yml` and `gitlab.rb` for source
+ and Omnibus installations respectively.
## Per-project user setting
@@ -36,10 +43,10 @@ and `gitlab.rb` for source and Omnibus installations respectively.
Two things to note:
-1. Disabling GitLab CI/CD, will affect only newly-created projects. Projects that
- had it enabled prior to this modification, will work as before.
-1. Even if you disable GitLab CI/CD, users will still be able to enable it in the
- project's settings.
+- Disabling GitLab CI/CD, will affect only newly-created projects. Projects that
+ had it enabled prior to this modification, will work as before.
+- Even if you disable GitLab CI/CD, users will still be able to enable it in the
+ project's settings.
For installations from source, open `gitlab.yml` with your editor and set
`builds` to `false`:
@@ -54,12 +61,32 @@ default_projects_features:
builds: false
```
-Save the file and restart GitLab: `sudo service gitlab restart`.
+Save the file and restart GitLab:
+
+```sh
+sudo service gitlab restart
+```
For Omnibus installations, edit `/etc/gitlab/gitlab.rb` and add the line:
-```
+```ruby
gitlab_rails['gitlab_default_projects_features_builds'] = false
```
-Save the file and reconfigure GitLab: `sudo gitlab-ctl reconfigure`.
+Save the file and reconfigure GitLab:
+
+```sh
+sudo gitlab-ctl reconfigure
+```
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/ci/environments.md b/doc/ci/environments.md
index 3e52cc786dd..a32dbc11a33 100644
--- a/doc/ci/environments.md
+++ b/doc/ci/environments.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# Environments and deployments
> Introduced in GitLab 8.9.
@@ -16,11 +20,11 @@ For example:
1. Test your code.
1. Deploy your code into a testing or staging environment before you release it to the public.
-This helps prevent bugs not only in your software, but in the deployment process as well.
+This helps find bugs in your software, and also in the deployment process as well.
GitLab CI/CD is capable of not only testing or building your projects, but also
deploying them in your infrastructure, with the added benefit of giving you a
-way to track your deployments. In other words, you can always know what is
+way to track your deployments. In other words, you will always know what is
currently being deployed or has been deployed on your servers.
It's important to know that:
@@ -31,12 +35,12 @@ It's important to know that:
GitLab:
-- Provides a full history of your deployments per every environment.
+- Provides a full history of your deployments for each environment.
- Keeps track of your deployments, so you always know what is currently being deployed on your
servers.
If you have a deployment service such as [Kubernetes](../user/project/clusters/index.md)
-enabled for your project, you can use it to assist with your deployments, and
+associated with your project, you can use it to assist with your deployments, and
can even access a [web terminal](#web-terminals) for your environment from within GitLab!
## Configuring environments
@@ -46,8 +50,8 @@ Configuring environments involves:
1. Understanding how [pipelines](pipelines.md) work.
1. Defining environments in your project's [`.gitlab-ci.yml`](yaml/README.md) file.
-The rest of this section illustrates how to configure environments and deployments using an example.
-It assumes you have already:
+The rest of this section illustrates how to configure environments and deployments using
+an example scenario. It assumes you have already:
- Created a [project](../gitlab-basics/create-project.md) in GitLab.
- Set up [a Runner](runners/README.md).
@@ -88,15 +92,14 @@ deploy_staging:
- master
```
-We have defined 3 [stages](yaml/README.md#stages):
+We have defined three [stages](yaml/README.md#stages):
- `test`
- `build`
- `deploy`
-The jobs assigned to these stages will run in this order. If a job fails, then
-the jobs that are assigned to the next stage won't run, rendering the pipeline
-as failed.
+The jobs assigned to these stages will run in this order. If any job fails, then
+the pipeline fails and jobs that are assigned to the next stage won't run.
In our case:
@@ -104,15 +107,15 @@ In our case:
- Then the `build` job.
- Lastly the `deploy_staging` job.
-With this configuration, we ensure that:
+With this configuration, we:
-- The tests pass.
-- Our app is able to be built successfully.
+- Check that the tests pass.
+- Ensure that our app is able to be built successfully.
- Lastly we deploy to the staging server.
NOTE: **Note:**
The `environment` keyword is just a hint for GitLab that this job actually
-deploys to this environment's `name`. It can also have a `url` that is
+deploys to the `name` environment. It can also have a `url` that is
exposed in various places within GitLab. Each time a job that
has an environment specified succeeds, a deployment is recorded, storing
the Git SHA and environment name.
@@ -132,16 +135,15 @@ In summary, with the above `.gitlab-ci.yml` we have achieved the following:
> the name given in `.gitlab-ci.yml` (with any variables expanded), while the
> second is a "cleaned-up" version of the name, suitable for use in URLs, DNS,
> etc.
-
+>
> Starting with GitLab 9.3, the environment URL is exposed to the Runner via
-> `$CI_ENVIRONMENT_URL`. The URL would be expanded from `.gitlab-ci.yml`, or if
-> the URL was not defined there, the external URL from the environment would be
-> used.
+> `$CI_ENVIRONMENT_URL`. The URL is expanded from `.gitlab-ci.yml`, or if
+> the URL was not defined there, the external URL from the environment is used.
### Configuring manual deployments
-Converting automatically executed job into jobs requiring to a manual action involves
-adding `when: manual` to the job's configuration.
+Adding `when: manual` to an automatically executed job's configuration converts it to
+a job requiring manual action.
To expand on the [previous example](#defining-environments), the following includes
another job that deploys our app to a production server and is
@@ -187,7 +189,7 @@ deploy_prod:
The `when: manual` action:
-- Exposes a "play" button in GitLab's UI.
+- Exposes a "play" button in GitLab's UI for that job.
- Means the `deploy_prod` job will only be triggered when the "play" button is clicked.
You can find the "play" button in the pipelines, environments, deployments, and jobs views.
@@ -200,8 +202,8 @@ You can find the "play" button in the pipelines, environments, deployments, and
| Deployments | ![Deployments manual action](img/environments_manual_action_deployments.png) |
| Jobs | ![Builds manual action](img/environments_manual_action_jobs.png) |
-Clicking on the play button in any view will trigger the `deploy_prod` job, and the deployment will be recorded under a new
-environment named `production`.
+Clicking on the play button in any view will trigger the `deploy_prod` job, and the
+deployment will be recorded as a new environment named `production`.
NOTE: **Note:**
If your environment's name is `production` (all lowercase),
@@ -209,14 +211,13 @@ it will get recorded in [Cycle Analytics](../user/project/cycle_analytics.md).
### Configuring dynamic environments
-Other environments are good for deploying to stable environments like staging or production.
-
-However, what about environments for branches other than `master`? Dynamic environments can be used to achieve these.
+Regular environments are good when deploying to "stable" environments like staging or production.
-Dynamic environments make it possible to create environments on the fly by
+However, for environments for branches other than `master`, dynamic environments
+can be used. Dynamic environments make it possible to create environments on the fly by
declaring their names dynamically in `.gitlab-ci.yml`.
-Dynamic environments form the basis of [Review apps](review_apps/index.md).
+Dynamic environments are a fundamental part of [Review apps](review_apps/index.md).
#### Allowed variables
@@ -237,10 +238,10 @@ For more information, see [Where variables can be used](variables/where_variable
#### Example configuration
-GitLab Runner exposes various [environment variables](variables/README.md) when a job runs and so
+GitLab Runner exposes various [environment variables](variables/README.md) when a job runs, so
you can use them as environment names.
-In the following example, a job will deploy to all branches except `master`:
+In the following example, the job will deploy to all branches except `master`:
```yaml
deploy_review:
@@ -261,28 +262,33 @@ In this example:
- The job's name is `deploy_review` and it runs on the `deploy` stage.
- We set the `environment` with the `environment:name` as `review/$CI_COMMIT_REF_NAME`.
Since the [environment name](yaml/README.md#environmentname) can contain slashes (`/`), we can
- use this pattern to distinguish between dynamic environments and the regular ones.
-- We tell the job to run [`only`](yaml/README.md#onlyexcept-basic) on branches [`except`](yaml/README.md#onlyexcept-basic) `master`.
+ use this pattern to distinguish between dynamic and regular environments.
+- We tell the job to run [`only`](yaml/README.md#onlyexcept-basic) on branches,
+ [`except`](yaml/README.md#onlyexcept-basic) `master`.
For the value of:
- `environment:name`, the first part is `review`, followed by a `/` and then `$CI_COMMIT_REF_NAME`,
- which takes the value of the branch name.
-- `environment:url`, since `$CI_COMMIT_REF_NAME` itself may also contain `/`, or other characters that
- would be invalid in a domain name or URL, we use `$CI_ENVIRONMENT_SLUG` so that the environment can get a specific and distinct URL for each branch.
+ which receives the value of the branch name.
+- `environment:url`, we want a specific and distinct URL for each branch. `$CI_COMMIT_REF_NAME`
+ may contain a `/` or other characters that would be invalid in a domain name or URL,
+ so we use `$CI_ENVIRONMENT_SLUG` to guarantee that we get a valid URL.
For example, given a `$CI_COMMIT_REF_NAME` of `100-Do-The-Thing`, the URL will be something
like `https://100-do-the-4f99a2.example.com`. Again, the way you set up
the web server to serve these requests is based on your setup.
- You could also use `$CI_COMMIT_REF_SLUG` in `environment:url`. For example, `https://$CI_COMMIT_REF_SLUG.example.com`.
- We have used `$CI_ENVIRONMENT_SLUG` here because it is guaranteed to be unique. If you're using a workflow like
- [GitLab Flow](../workflow/gitlab_flow.md), collisions are unlikely and you may prefer environment names to be more closely based on the branch name. The example
- above would give you an URL like `https://100-do-the-thing.example.com`.
+ We have used `$CI_ENVIRONMENT_SLUG` here because it is guaranteed to be unique. If
+ you're using a workflow like [GitLab Flow](../workflow/gitlab_flow.md), collisions
+ are unlikely and you may prefer environment names to be more closely based on the
+ branch name. In that case, you could use `$CI_COMMIT_REF_SLUG` in `environment:url` in
+ the example above: `https://$CI_COMMIT_REF_SLUG.example.com`, which would give a URL
+ of `https://100-do-the-thing.example.com`.
NOTE: **Note:**
-You are not bound to use the same prefix or only slashes in the dynamic
-environments' names (`/`). However, this will enable the [grouping similar environments](#grouping-similar-environments) feature.
+You are not required to use the same prefix or only slashes (`/`) in the dynamic environments'
+names. However, using this format will enable the [grouping similar environments](#grouping-similar-environments)
+feature.
### Complete example
@@ -292,7 +298,7 @@ The configuration in this section provides a full development workflow where you
- Built.
- Deployed as a Review App.
- Deployed to a staging server once the merge request is merged.
-- Finally, manually deployed to the production server.
+- Finally, able to be manually deployed to the production server.
The following combines the previous configuration examples, including:
@@ -348,8 +354,8 @@ deploy_prod:
- master
```
-A more realistic example would include copying files to a location where a
-webserver (for example, NGINX) could then read and serve.
+A more realistic example would also include copying files to a location where a
+webserver (for example, NGINX) could then access and serve them.
The example below will copy the `public` directory to `/srv/nginx/$CI_COMMIT_REF_SLUG/public`:
@@ -366,32 +372,33 @@ review_app:
This example requires that NGINX and GitLab Runner are set up on the server this job will run on.
NOTE: **Note:**
-See the [limitations](#limitations) section for some edge cases regarding naming of your branches and Review Apps.
+See the [limitations](#limitations) section for some edge cases regarding the naming of
+your branches and Review Apps.
-The complete example provides the following workflow for developers:
+The complete example provides the following workflow to developers:
- Create a branch locally.
-- Make changes and commit them
+- Make changes and commit them.
- Push the branch to GitLab.
- Create a merge request.
-Behind the scenes, GitLab runner will:
+Behind the scenes, GitLab Runner will:
- Pick up the changes and start running the jobs.
- Run the jobs sequentially as defined in `stages`:
- First, run the tests.
- If the tests succeed, build the app.
- - If the build succeeds, the app will be is deployed to an environment with a name specific to the
+ - If the build succeeds, the app is deployed to an environment with a name specific to the
branch.
So now, every branch:
- Gets its own environment.
-- Is deployed to its own location, with the added benefit of:
+- Is deployed to its own unique location, with the added benefit of:
- Having a [history of deployments](#viewing-deployment-history).
- Being able to [rollback changes](#retrying-and-rolling-back) if needed.
-For more information on using the URL, see [Using the environment URL](#using-the-environment-url).
+For more information, see [Using the environment URL](#using-the-environment-url).
### Protected environments
@@ -401,11 +408,12 @@ For more information, see [Protected environments](environments/protected_enviro
## Working with environments
-Having configured environments, GitLab provides many features to work with them. These are documented below.
+Once environments are configured, GitLab provides many features for working with them,
+as documented below.
### Viewing environments and deployments
-A list of environments and deployment statuses is available on project's **Operations > Environments** page.
+A list of environments and deployment statuses is available on each project's **Operations > Environments** page.
For example:
@@ -416,11 +424,11 @@ This example shows:
- The environment's name with a link to its deployments.
- The last deployment ID number and who performed it.
- The job ID of the last deployment with its respective job name.
-- The commit information of the last deployment such as who committed, to what
+- The commit information of the last deployment, such as who committed it, to what
branch, and the Git SHA of the commit.
- The exact time the last deployment was performed.
-- A button that takes you to the URL that you have defined under the
- `environment` keyword in `.gitlab-ci.yml`.
+- A button that takes you to the URL that you defined under the `environment` keyword
+ in `.gitlab-ci.yml`.
- A button that re-deploys the latest deployment, meaning it runs the job
defined by the environment name for that specific commit.
@@ -432,8 +440,8 @@ deployments, but an environment can have multiple deployments.
> - While you can create environments manually in the web interface, we recommend
> that you define your environments in `.gitlab-ci.yml` first. They will
> be automatically created for you after the first deploy.
-> - The environments page can only be viewed by Reporters and above. For more
-> information on the permissions, see the [permissions documentation](../user/permissions.md).
+> - The environments page can only be viewed by users with [Reporter permission](../user/permissions.md#project-members-permissions)
+> and above. For more information on permissions, see the [permissions documentation](../user/permissions.md).
> - Only deploys that happen after your `.gitlab-ci.yml` is properly configured
> will show up in the **Environment** and **Last deployment** lists.
@@ -442,7 +450,7 @@ deployments, but an environment can have multiple deployments.
GitLab keeps track of your deployments, so you:
- Always know what is currently being deployed on your servers.
-- Can have the full history of your deployments per every environment.
+- Can have the full history of your deployments for every environment.
Clicking on an environment shows the history of its deployments. Here's an example **Environments** page
with multiple deployments:
@@ -460,9 +468,9 @@ To retry or rollback a deployment:
1. Navigate to **Operations > Environments**.
1. Click on the environment.
-1. On the page that lists the deployment history for the environment, click the:
- - **Rollback** button against a previously successful deployment, to roll back to that deployment.
- - **Retry** button against the last deployment, to retry that deployment.
+1. In the deployment history list for the environment, click the:
+ - **Retry** button next to the last deployment, to retry that deployment.
+ - **Rollback** button next to a previously successful deployment, to roll back to that deployment.
NOTE: **Note:**
The defined deployment process in the job's `script` determines whether the rollback succeeds or not.
@@ -470,9 +478,7 @@ The defined deployment process in the job's `script` determines whether the roll
### Using the environment URL
The [environment URL](yaml/README.md#environmenturl) is exposed in a few
-places within GitLab.
-
-These are:
+places within GitLab:
- In a merge request widget as a link:
![Environment URL in merge request](img/environments_mr_review_app.png)
@@ -493,27 +499,28 @@ For example:
#### Going from source files to public pages
With GitLab's [Route Maps](review_apps/index.md#route-maps) you can go directly
-from source files to public pages on the environment set for Review Apps.
+from source files to public pages in the environment set for Review Apps.
### Stopping an environment
Stopping an environment:
-- Moves it from the list of **Available** environments to the list of **Stopped** environments on the [**Environments** page](#viewing-environments-and-deployments).
+- Moves it from the list of **Available** environments to the list of **Stopped**
+ environments on the [**Environments** page](#viewing-environments-and-deployments).
- Executes an [`on_stop` action](yaml/README.md#environmenton_stop), if defined.
This is often used when multiple developers are working on a project at the same time,
each of them pushing to their own branches, causing many dynamic environments to be created.
NOTE: **Note:**
-Starting with GitLab 8.14, dynamic environments will be stopped automatically
+Starting with GitLab 8.14, dynamic environments are stopped automatically
when their associated branch is deleted.
#### Automatically stopping an environment
Environments can be stopped automatically using special configuration.
-Consider the following example where the `deploy_review` calls the `stop_review`
+Consider the following example where the `deploy_review` job calls `stop_review`
to clean up and stop the environment:
```yaml
@@ -542,14 +549,14 @@ stop_review:
action: stop
```
-Setting the [`GIT_STRATEGY`](yaml/README.md#git-strategy) to `none` is necessary on the
-`stop_review` job so that the [GitLab Runner](https://docs.gitlab.com/runner/) won't try to check out the code
-after the branch is deleted.
+Setting the [`GIT_STRATEGY`](yaml/README.md#git-strategy) to `none` is necessary in the
+`stop_review` job so that the [GitLab Runner](https://docs.gitlab.com/runner/) won't
+try to check out the code after the branch is deleted.
When you have an environment that has a stop action defined (typically when
the environment describes a Review App), GitLab will automatically trigger a
stop action when the associated branch is deleted. The `stop_review` job must
-be in the same `stage` as the `deploy_review` one in order for the environment
+be in the same `stage` as the `deploy_review` job in order for the environment
to automatically stop.
You can read more in the [`.gitlab-ci.yml` reference](yaml/README.md#environmenton_stop).
@@ -562,8 +569,8 @@ As documented in [Configuring dynamic environments](#configuring-dynamic-environ
prepend environment name with a word, followed by a `/`, and finally the branch
name, which is automatically defined by the `CI_COMMIT_REF_NAME` variable.
-In short, environments that are named like `type/foo` are presented under a
-group named `type`.
+In short, environments that are named like `type/foo` are all presented under the same
+group, named `type`.
In our [minimal example](#example-configuration), we named the environments `review/$CI_COMMIT_REF_NAME`
where `$CI_COMMIT_REF_NAME` is the branch name. Here is a snippet of the example:
@@ -588,13 +595,14 @@ exist, you should see something like:
>
> - For the monitoring dashboard to appear, you need to:
> - Enable the [Prometheus integration](../user/project/integrations/prometheus.md).
-> - Configure Prometheus to collect at least one [supported metric](../user/project/integrations/prometheus_library/index.md)
+> - Configure Prometheus to collect at least one [supported metric](../user/project/integrations/prometheus_library/index.md).
> - With GitLab 9.2, all deployments to an environment are shown directly on the monitoring dashboard.
-If you have enabled [Prometheus for monitoring system and response metrics](../user/project/integrations/prometheus.md), you can monitor the performance behavior of your app running in each environment.
+If you have enabled [Prometheus for monitoring system and response metrics](../user/project/integrations/prometheus.md),
+you can monitor the behavior of your app running in each environment.
-Once configured, GitLab will attempt to retrieve [supported performance metrics](../user/project/integrations/prometheus_library/index.md) for any
-environment that has had a successful deployment. If monitoring data was
+Once configured, GitLab will attempt to retrieve [supported performance metrics](../user/project/integrations/prometheus_library/index.md)
+for any environment that has had a successful deployment. If monitoring data was
successfully retrieved, a **Monitoring** button will appear for each environment.
![Environment Detail with Metrics](img/deployments_view.png)
@@ -604,11 +612,15 @@ Clicking on the **Monitoring** button will display a new page showing up to the
after initial deployment.
All deployments to an environment are shown directly on the monitoring dashboard,
-which allows easy correlation between any changes in performance and a new
-version of the app, all without leaving GitLab.
+which allows easy correlation between any changes in performance and new
+versions of the app, all without leaving GitLab.
![Monitoring dashboard](img/environments_monitoring.png)
+#### Linking to external dashboard
+
+Add a [button to the Monitoring dashboard](../user/project/operations/linking_to_an_external_dashboard.md) linking directly to your existing external dashboards.
+
### Web terminals
> Web terminals were added in GitLab 8.15 and are only available to project Maintainers and Owners.
@@ -617,8 +629,8 @@ If you deploy to your environments with the help of a deployment service (for ex
the [Kubernetes integration](../user/project/clusters/index.md)), GitLab can open
a terminal session to your environment.
-This is a powerful feature that allows you to debug issues without leaving the comfort of your web browser. To
-enable it, just follow the instructions given in the service integration
+This is a powerful feature that allows you to debug issues without leaving the comfort
+of your web browser. To enable it, just follow the instructions given in the service integration
documentation.
Once enabled, your environments will gain a "terminal" button:
@@ -663,8 +675,24 @@ fetch = +refs/environments/*:refs/remotes/origin/environments/*
### Scoping environments with specs **[PREMIUM]**
-Some GitLab [Enterprise Edition](https://about.gitlab.com/pricing/) features can behave differently for each
-environment. For example, you can [create a secret variable to be injected only into a production environment](https://docs.gitlab.com/ee/ci/variables/#limiting-environment-scopes-of-environment-variables-premium).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2112) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.4.
+
+You can limit the environment scope of a variable by
+defining which environments it can be available for.
+
+Wildcards can be used, and the default environment scope is `*`, which means
+any jobs will have this variable, not matter if an environment is defined or
+not.
+
+For example, if the environment scope is `production`, then only the jobs
+having the environment `production` defined would have this specific variable.
+Wildcards (`*`) can be used along with the environment name, therefore if the
+environment scope is `review/*` then any jobs with environment names starting
+with `review/` would have that particular variable.
+
+Some GitLab features can behave differently for each environment.
+For example, you can
+[create a secret variable to be injected only into a production environment](variables/README.md#limiting-environment-scopes-of-environment-variables-premium). **[PREMIUM]**
In most cases, these features use the _environment specs_ mechanism, which offers
an efficient way to implement scoping within each environment group.
@@ -688,7 +716,7 @@ Each environment can be matched with the following environment spec:
As you can see, you can use specific matching for selecting a particular environment,
and also use wildcard matching (`*`) for selecting a particular environment group,
-such as [Review apps](review_apps/index.md) (`review/*`).
+such as [Review Apps](review_apps/index.md) (`review/*`).
NOTE: **Note:**
The most _specific_ spec takes precedence over the other wildcard matching.
@@ -696,9 +724,8 @@ In this case, `review/feature-1` spec takes precedence over `review/*` and `*` s
## Limitations
-You are limited to use only the [CI predefined variables](variables/README.md) in the
-`environment: name`. If you try to re-use variables defined inside `script`
-as part of the environment name, it will not work.
+In the `environment: name`, you are limited to only the [predefined environment variables](variables/predefined_variables.md).
+Re-using variables defined inside `script` as part of the environment name will not work.
## Further reading
@@ -707,3 +734,16 @@ Below are some links you may find interesting:
- [The `.gitlab-ci.yml` definition of environments](yaml/README.md#environment)
- [A blog post on Deployments & Environments](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/)
- [Review Apps - Use dynamic environments to deploy your code for every branch](review_apps/index.md)
+- [Deploy Boards for your applications running on Kubernetes](../user/project/deploy_boards.md) **[PREMIUM]**
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/ci/environments/protected_environments.md b/doc/ci/environments/protected_environments.md
index 219af4ced9d..b72ebe838b8 100644
--- a/doc/ci/environments/protected_environments.md
+++ b/doc/ci/environments/protected_environments.md
@@ -1,3 +1,7 @@
+---
+type: concepts, howto
+---
+
# Protected Environments **[PREMIUM]**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/6303) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.3.
@@ -9,8 +13,8 @@
- Some of them are just for testing.
- Others are for production.
-Because deploy jobs can be raised by different users with different roles, it is important that
-specific environments are "protected" to avoid unauthorized people affecting them.
+Since deploy jobs can be raised by different users with different roles, it is important that
+specific environments are "protected" to prevent unauthorized people from affecting them.
By default, a protected environment does one thing: it ensures that only people
with the right privileges can deploy to it, thus keeping it safe.
@@ -28,14 +32,14 @@ To protect an environment:
1. Navigate to your project's **Settings > CI/CD**.
1. Expand the **Protected Environments** section.
1. From the **Environment** dropdown menu, select the environment you want to protect.
-1. In the **Allowed to Deploy** dropdown menu, select the role, users, or groups you want to have deploy access.
- There are some considerations to have in mind:
- - There are two roles to choose from:
- - **Maintainers**: will allow access to all maintainers in the project.
- - **Developers**: will allow access to all maintainers and all developers in the project.
- - You can only select groups that are associated with the project.
- - Only users that have at least Developer permission level will appear on
- the **Allowed to Deploy** dropdown menu.
+1. In the **Allowed to Deploy** dropdown menu, select the role, users, or groups you
+ want to give deploy access to. Keep in mind that:
+ - There are two roles to choose from:
+ - **Maintainers**: will allow access to all maintainers in the project.
+ - **Developers**: will allow access to all maintainers and all developers in the project.
+ - You can only select groups that are already associated with the project.
+ - Only users that have at least Developer permission level will appear in
+ the **Allowed to Deploy** dropdown menu.
1. Click the **Protect** button.
The protected environment will now appear in the list of protected environments.
@@ -44,5 +48,18 @@ The protected environment will now appear in the list of protected environments.
Maintainers can:
-- Update existing protected environments at any time by changing the access on **Allowed to deploy** dropdown menu.
-- Unprotect a protected environment by clicking the **Unprotect** button of the environment to unprotect.
+- Update existing protected environments at any time by changing the access in the
+ **Allowed to Deploy** dropdown menu.
+- Unprotect a protected environment by clicking the **Unprotect** button for that environment.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/ci/examples/README.md b/doc/ci/examples/README.md
index 7f686781e3c..2b4fe321cb3 100644
--- a/doc/ci/examples/README.md
+++ b/doc/ci/examples/README.md
@@ -1,47 +1,42 @@
---
comments: false
+type: index
---
# GitLab CI/CD Examples
-Examples are a useful way of understanding how to implement GitLab CI/CD for your specific use case.
+This page contains links to a variety of examples that can help you understand how to
+implement [GitLab CI/CD](../README.md) for your specific use case.
Examples are available in several forms. As a collection of:
- `.gitlab-ci.yml` [template files](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/gitlab/ci/templates) maintained in GitLab. When you create a new file via the UI,
GitLab will give you the option to choose one of these templates. This will allow you to quickly bootstrap your project for CI/CD.
If your favorite programming language or framework are missing, we would love your help by sending a merge request with a new `.gitlab-ci.yml` to this project.
-- Repositories with [example projects](https://gitlab.com/gitlab-examples) for various languages. You can fork and adjust them to your own needs.
+- Repositories with [example projects](https://gitlab.com/gitlab-examples) for various languages. You can fork and adjust them to your own needs. Projects include demonstrations of [multi-project pipelines](https://gitlab.com/gitlab-examples/multi-project-pipelines) and using [Review Apps with a static site served by nginx](https://gitlab.com/gitlab-examples/review-apps-nginx/).
- Examples and [other resources](#other-resources) listed below.
## CI/CD examples
-The following table lists examples for different use cases:
-
-| Use case | Resource |
-|:-----------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------|
-| Browser performance testing | [Browser Performance Testing with the Sitespeed.io container](browser_performance.md). |
-| Clojure | [Test a Clojure application with GitLab CI/CD](test-clojure-application.md). |
-| Code quality analysis | [Analyze your project's Code Quality](code_quality.md). **[STARTER]** |
-| Container scanning | [Container Scanning with GitLab CI/CD](container_scanning.md). |
-| Dependency scanning | [Dependency Scanning with GitLab CI/CD](https://docs.gitlab.com/ee/ci/examples/dependency_scanning.html). **[ULTIMATE]** |
-| Deployment with `dpl` | [Using `dpl` as deployment tool](deployment/README.md). |
-| Dynamic application<br>security testing (DAST) | [Dynamic Application Security Testing with GitLab CI/CD](dast.md) **[ULTIMATE]** |
-| Elixir | [Testing a Phoenix application with GitLab CI/CD](test_phoenix_app_with_gitlab_ci_cd/index.md). |
-| Game development | [DevOps and Game Dev with GitLab CI/CD](devops_and_game_dev_with_gitlab_ci_cd/index.md). |
-| GitLab Pages | See the [GitLab Pages](../../user/project/pages/index.md) documentation for a complete example. |
-| Java | [Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD](deploy_spring_boot_to_cloud_foundry/index.md). |
-| JUnit | [JUnit test reports](../junit_test_reports.md). |
-| License management | [Dependencies license management with GitLab CI/CD](https://docs.gitlab.com/ee/ci/examples/license_management.html) **[ULTIMATE]** |
-| Maven | [How to deploy Maven projects to Artifactory with GitLab CI/CD](artifactory_and_gitlab/index.md). |
-| PHP | [Testing PHP projects](php.md). |
-| PHP | [Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD](deployment/composer-npm-deploy.md). |
-| PHP | [Test and deploy Laravel applications with GitLab CI/CD and Envoy](laravel_with_gitlab_and_envoy/index.md). |
-| Python | [Test and deploy a Python application with GitLab CI/CD](test-and-deploy-python-application-to-heroku.md). |
-| Ruby | [Test and deploy a Ruby application with GitLab CI/CD](test-and-deploy-ruby-application-to-heroku.md). |
-| Scala | [Test and deploy a Scala application to Heroku](test-scala-application.md). |
-| Static application<br>security testing (SAST) | [Static Application Security Testing with GitLab CI/CD](https://docs.gitlab.com/ee/ci/examples/sast.html) **[ULTIMATE]** |
-| Testing | [End-to-end testing with GitLab CI/CD and WebdriverIO](end_to_end_testing_webdriverio/index.md). |
+The following table lists examples with step-by-step tutorials that are contained in this section.
+
+| Use case | Resource |
+|:----------------------------|:---------------------------------------------------------------------------------------------------------------------------|
+| Browser performance testing | [Browser Performance Testing with the Sitespeed.io container](browser_performance.md). |
+| Clojure | [Test a Clojure application with GitLab CI/CD](test-clojure-application.md). |
+| Deployment with Dpl | [Using `dpl` as deployment tool](deployment/README.md). |
+| Elixir | [Testing a Phoenix application with GitLab CI/CD](test_phoenix_app_with_gitlab_ci_cd/index.md). |
+| End-to-end testing | [End-to-end testing with GitLab CI/CD and WebdriverIO](end_to_end_testing_webdriverio/index.md). |
+| Game development | [DevOps and Game Dev with GitLab CI/CD](devops_and_game_dev_with_gitlab_ci_cd/index.md). |
+| GitLab Pages | See the [GitLab Pages](../../user/project/pages/index.md) documentation for a complete example of deploying a static site. |
+| Java with Spring Boot | [Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD](deploy_spring_boot_to_cloud_foundry/index.md). |
+| Java with Maven | [How to deploy Maven projects to Artifactory with GitLab CI/CD](artifactory_and_gitlab/index.md). |
+| PHP with PHPunit, atoum | [Testing PHP projects](php.md). |
+| PHP with NPM, SCP | [Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD](deployment/composer-npm-deploy.md). |
+| PHP with Laravel, Ennvoy | [Test and deploy Laravel applications with GitLab CI/CD and Envoy](laravel_with_gitlab_and_envoy/index.md). |
+| Python on Heroku | [Test and deploy a Python application with GitLab CI/CD](test-and-deploy-python-application-to-heroku.md). |
+| Ruby on Heroku | [Test and deploy a Ruby application with GitLab CI/CD](test-and-deploy-ruby-application-to-heroku.md). |
+| Scala on Heroku | [Test and deploy a Scala application to Heroku](test-scala-application.md). |
### Contributing examples
@@ -50,24 +45,29 @@ language users and GitLab by sending a merge request with a guide for that langu
You may want to apply for the [GitLab Community Writers Program](https://about.gitlab.com/community-writers/)
to get paid for writing complete articles for GitLab.
-### Adding templates to your GitLab installation **[PREMIUM ONLY]**
+## Adding templates to your GitLab installation **[PREMIUM ONLY]**
-If you want to have customized examples and templates for your own self-managed GitLab instance available to your team, your GitLab administrator can [designate an instance template repository](https://docs.gitlab.com/ee/user/admin_area/settings/instance_template_repository.html) that contains examples and templates specific to your enterprise.
+If you want to have customized examples and templates for your own self-managed GitLab instance available to your team, your GitLab administrator can [designate an instance template repository](../../user/admin_area/settings/instance_template_repository.md) that contains examples and templates specific to your enterprise.
## Other resources
-This section provides further resources to help you get familiar with different aspects of GitLab CI/CD.
-
-NOTE: **Note:**
-These resources may no longer reflect the current state of GitLab CI/CD.
+This section provides further resources to help you get familiar with various uses of GitLab CI/CD.
+Note that older articles and videos may not reflect the state of the latest GitLab release.
### CI/CD in the cloud
For examples of setting up GitLab CI/CD for cloud-based environments, see:
- [How to set up multi-account AWS SAM deployments with GitLab CI](https://about.gitlab.com/2019/02/04/multi-account-aws-sam-deployments-with-gitlab-ci/)
+- [Automating Kubernetes Deployments with GitLab CI/CD](https://www.youtube.com/watch?v=wEDRfAz6_Uw)
- [How to autoscale continuous deployment with GitLab Runner on DigitalOcean](https://about.gitlab.com/2018/06/19/autoscale-continuous-deployment-gitlab-runner-digital-ocean/)
- [How to create a CI/CD pipeline with Auto Deploy to Kubernetes using GitLab and Helm](https://about.gitlab.com/2017/09/21/how-to-create-ci-cd-pipeline-with-autodeploy-to-kubernetes-using-gitlab-and-helm/)
+- [Demo - Deploying from GitLab to OpenShift Container Cluster](https://youtu.be/EwbhA53Jpp4)
+
+See also the following video overviews:
+
+- [Containers, Schedulers, and GitLab CI](https://www.youtube.com/watch?v=d-9awBxEbvQ).
+- [Deploying to IBM Cloud with GitLab CI/CD](https://www.youtube.com/watch?v=6ZF4vgKMd-g).
### Customer stories
@@ -83,7 +83,6 @@ For some examples to help get you started, see:
- [GitLab CI/CD's 2018 highlights](https://about.gitlab.com/2019/01/21/gitlab-ci-cd-features-improvements/)
- [A beginner's guide to continuous integration](https://about.gitlab.com/2018/01/22/a-beginners-guide-to-continuous-integration/)
-- [Making CI easier with GitLab](https://about.gitlab.com/2017/07/13/making-ci-easier-with-gitlab/)
### Implementing GitLab CI/CD
@@ -101,6 +100,10 @@ For examples of others who have implemented GitLab CI/CD, see:
- [Fast and natural continuous integration with GitLab CI](https://about.gitlab.com/2017/05/22/fast-and-natural-continuous-integration-with-gitlab-ci/)
- [Demo: CI/CD with GitLab in action](https://about.gitlab.com/2017/03/13/ci-cd-demo/)
+### Migrating to GitLab from third-party CI tools
+
+- [Migrating from Jenkins to GitLab](https://youtu.be/RlEVGOpYF5Y)
+
### Integrating GitLab CI/CD with other systems
To see how you can integrate GitLab CI/CD with third-party systems, see:
diff --git a/doc/ci/examples/artifactory_and_gitlab/index.md b/doc/ci/examples/artifactory_and_gitlab/index.md
index 589912e7a2a..2117b342903 100644
--- a/doc/ci/examples/artifactory_and_gitlab/index.md
+++ b/doc/ci/examples/artifactory_and_gitlab/index.md
@@ -4,6 +4,7 @@ author: Fabio Busatto
author_gitlab: bikebilly
level: intermediate
article_type: tutorial
+type: tutorial
date: 2017-08-15
---
@@ -16,8 +17,8 @@ to build a [Maven](https://maven.apache.org/) project, deploy it to [Artifactory
You'll create two different projects:
-- `simple-maven-dep`: the app built and deployed to Artifactory (available at <https://gitlab.com/gitlab-examples/maven/simple-maven-dep>)
-- `simple-maven-app`: the app using the previous one as a dependency (available at <https://gitlab.com/gitlab-examples/maven/simple-maven-app>)
+- `simple-maven-dep`: the app built and deployed to Artifactory (see the [simple-maven-dep](https://gitlab.com/gitlab-examples/maven/simple-maven-dep) example project)
+- `simple-maven-app`: the app using the previous one as a dependency (see the [simple-maven-app](https://gitlab.com/gitlab-examples/maven/simple-maven-app) example project)
We assume that you already have a GitLab account on [GitLab.com](https://gitlab.com/), and that you know the basic usage of Git and [GitLab CI/CD](https://about.gitlab.com/product/continuous-integration/).
We also assume that an Artifactory instance is available and reachable from the internet, and that you have valid credentials to deploy on it.
@@ -105,7 +106,7 @@ parameter in `.gitlab-ci.yml` to use the custom location instead of the default
Now it's time we set up [GitLab CI/CD](https://about.gitlab.com/product/continuous-integration/) to automatically build, test and deploy the dependency!
GitLab CI/CD uses a file in the root of the repo, named `.gitlab-ci.yml`, to read the definitions for jobs
-that will be executed by the configured GitLab Runners. You can read more about this file in the [GitLab Documentation](https://docs.gitlab.com/ee/ci/yaml/).
+that will be executed by the configured GitLab Runners. You can read more about this file in the [GitLab Documentation](../../yaml/README.md).
First of all, remember to set up variables for your deployment. Navigate to your project's **Settings > CI/CD > Environment variables** page
and add the following ones (replace them with your current values, of course):
diff --git a/doc/ci/examples/browser_performance.md b/doc/ci/examples/browser_performance.md
index b47038011de..8ecac4a5a4f 100644
--- a/doc/ci/examples/browser_performance.md
+++ b/doc/ci/examples/browser_performance.md
@@ -1,13 +1,17 @@
-# Browser Performance Testing with the Sitespeed.io container
+---
+type: howto
+---
-CAUTION: **Caution:**
+# Browser Performance Testing with the sitespeed.io container
+
+NOTE: **Note:**
The job definition shown below is supported on GitLab 11.5 and later versions.
It also requires the GitLab Runner 11.5 or later.
For earlier versions, use the [previous job definitions](#previous-job-definitions).
This example shows how to run the
-[Sitespeed.io container](https://hub.docker.com/r/sitespeedio/sitespeed.io/) on
-your code by using GitLab CI/CD and [Sitespeed.io](https://www.sitespeed.io)
+[sitespeed.io container](https://hub.docker.com/r/sitespeedio/sitespeed.io/) on
+your code by using GitLab CI/CD and [sitespeed.io](https://www.sitespeed.io)
using Docker-in-Docker.
First, you need GitLab Runner with
@@ -38,25 +42,25 @@ performance:
```
The above example will create a `performance` job in your CI/CD pipeline and will run
-Sitespeed.io against the webpage you defined in `URL` to gather key metrics.
+sitespeed.io against the webpage you defined in `URL` to gather key metrics.
The [GitLab plugin](https://gitlab.com/gitlab-org/gl-performance) for
-Sitespeed.io is downloaded in order to save the report as a
+sitespeed.io is downloaded in order to save the report as a
[Performance report artifact](../yaml/README.md#artifactsreportsperformance-premium)
that you can later download and analyze.
Due to implementation limitations we always take the latest Performance artifact available.
-The full HTML Sitespeed.io report will also be saved as an artifact, and if you have
+The full HTML sitespeed.io report will also be saved as an artifact, and if you have
[GitLab Pages](../../user/project/pages/index.md) enabled, it can be viewed
directly in your browser.
-For further customization options of Sitespeed.io, including the ability to
-provide a list of URLs to test, please consult
-[their documentation](https://www.sitespeed.io/documentation/sitespeed.io/configuration/).
+For further customization options for sitespeed.io, including the ability to
+provide a list of URLs to test, please see the
+[Sitespeed.io Configuration](https://www.sitespeed.io/documentation/sitespeed.io/configuration/) documentation.
TIP: **Tip:**
For [GitLab Premium](https://about.gitlab.com/pricing/) users, key metrics are automatically
extracted and shown right in the merge request widget.
-[Learn more on Browser Performance Testing in merge requests](https://docs.gitlab.com/ee//user/project/merge_requests/browser_performance_testing.html).
+[Learn more on Browser Performance Testing in merge requests](../../user/project/merge_requests/browser_performance_testing.md).
## Performance testing on Review Apps
@@ -73,7 +77,7 @@ set this up:
1. In the `performance` job, read the previous artifact into an environment
variable, like `$CI_ENVIRONMENT_URL`, and use it to parameterize the test
URLs.
-1. You can now run the Sitespeed.io container against the desired hostname and
+1. You can now run the sitespeed.io container against the desired hostname and
paths.
Your `.gitlab-ci.yml` file would look like:
diff --git a/doc/ci/examples/code_climate.md b/doc/ci/examples/code_climate.md
index b34637efc8d..0aa108a2e73 100644
--- a/doc/ci/examples/code_climate.md
+++ b/doc/ci/examples/code_climate.md
@@ -1,6 +1,5 @@
---
-redirect_from: 'https://docs.gitlab.com/ee/ci/examples/code_climate.html'
-redirect_to: code_quality.md
+redirect_to: 'code_quality.md'
---
This document was moved to [another location](code_quality.md).
diff --git a/doc/ci/examples/code_quality.md b/doc/ci/examples/code_quality.md
index 3e7d6e7e3f7..43f773dab7c 100644
--- a/doc/ci/examples/code_quality.md
+++ b/doc/ci/examples/code_quality.md
@@ -1,7 +1,12 @@
+---
+redirect_from: 'https://docs.gitlab.com/ee/ci/examples/code_climate.html'
+type: reference, howto
+---
+
# Analyze your project's Code Quality
CAUTION: **Caution:**
-The job definition shown below is supported on GitLab 11.5 and later versions.
+The job definition shown below is supported on GitLab 11.11 and later versions.
It also requires the GitLab Runner 11.5 or later.
For earlier versions, use the [previous job definitions](#previous-job-definitions).
@@ -11,27 +16,11 @@ and Docker.
First, you need GitLab Runner with
[docker-in-docker executor](../docker/using_docker_build.md#use-docker-in-docker-executor).
-Once you set up the Runner, add a new job to `.gitlab-ci.yml` that
-generates the expected report:
+Once you set up the Runner, include the CodeQuality template in your CI config:
```yaml
-code_quality:
- image: docker:stable
- variables:
- DOCKER_DRIVER: overlay2
- allow_failure: true
- services:
- - docker:stable-dind
- script:
- - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
- - docker run
- --env SOURCE_CODE="$PWD"
- --volume "$PWD":/code
- --volume /var/run/docker.sock:/var/run/docker.sock
- "registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
- artifacts:
- reports:
- codequality: gl-code-quality-report.json
+include:
+ - template: Code-Quality.gitlab-ci.yml
```
The above example will create a `code_quality` job in your CI/CD pipeline which
@@ -43,7 +32,7 @@ Due to implementation limitations we always take the latest Code Quality artifac
TIP: **Tip:**
For [GitLab Starter][ee] users, this information will be automatically
extracted and shown right in the merge request widget.
-[Learn more on Code Quality in merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html).
+[Learn more on Code Quality in merge requests](../../user/project/merge_requests/code_quality.md).
## Previous job definitions
@@ -54,6 +43,28 @@ While these old job definitions are still maintained they have been deprecated
and may be removed in next major release, GitLab 12.0.
You are advised to update your current `.gitlab-ci.yml` configuration to reflect that change.
+For GitLab 11.5 and earlier, the job should look like:
+
+```yaml
+code_quality:
+ image: docker:stable
+ variables:
+ DOCKER_DRIVER: overlay2
+ allow_failure: true
+ services:
+ - docker:stable-dind
+ script:
+ - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
+ - docker run
+ --env SOURCE_CODE="$PWD"
+ --volume "$PWD":/code
+ --volume /var/run/docker.sock:/var/run/docker.sock
+ "registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
+ artifacts:
+ reports:
+ codequality: gl-code-quality-report.json
+```
+
For GitLab 11.4 and earlier, the job should look like:
```yaml
diff --git a/doc/ci/examples/container_scanning.md b/doc/ci/examples/container_scanning.md
index 36fdc29fe65..6570f6b2d98 100644
--- a/doc/ci/examples/container_scanning.md
+++ b/doc/ci/examples/container_scanning.md
@@ -1,119 +1,5 @@
-# Container Scanning with GitLab CI/CD
+---
+redirect_to: '../../user/application_security/container_scanning/index.md'
+---
-CAUTION: **Caution:**
-The job definition shown below is supported on GitLab 11.5 and later versions.
-It also requires the GitLab Runner 11.5 or later.
-For earlier versions, use the [previous job definitions](#previous-job-definitions).
-
-You can check your Docker images (or more precisely the containers) for known
-vulnerabilities by using [Clair](https://github.com/coreos/clair) and
-[clair-scanner](https://github.com/arminc/clair-scanner), two open source tools
-for Vulnerability Static Analysis for containers.
-
-First, you need GitLab Runner with
-[docker-in-docker executor](../docker/using_docker_build.md#use-docker-in-docker-executor).
-
-Once you set up the Runner, add a new job to `.gitlab-ci.yml` that
-generates the expected report:
-
-```yaml
-container_scanning:
- image: docker:stable
- variables:
- DOCKER_DRIVER: overlay2
- ## Define two new variables based on GitLab's CI/CD predefined variables
- ## https://docs.gitlab.com/ee/ci/variables/#predefined-environment-variables
- CI_APPLICATION_REPOSITORY: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
- CI_APPLICATION_TAG: $CI_COMMIT_SHA
- allow_failure: true
- services:
- - docker:stable-dind
- script:
- - docker run -d --name db arminc/clair-db:latest
- - docker run -p 6060:6060 --link db:postgres -d --name clair --restart on-failure arminc/clair-local-scan:v2.0.6
- - apk add -U wget ca-certificates
- - docker pull ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG}
- - wget https://github.com/arminc/clair-scanner/releases/download/v8/clair-scanner_linux_amd64
- - mv clair-scanner_linux_amd64 clair-scanner
- - chmod +x clair-scanner
- - touch clair-whitelist.yml
- - while( ! wget -q -O /dev/null http://docker:6060/v1/namespaces ) ; do sleep 1 ; done
- - retries=0
- - echo "Waiting for clair daemon to start"
- - while( ! wget -T 10 -q -O /dev/null http://docker:6060/v1/namespaces ) ; do sleep 1 ; echo -n "." ; if [ $retries -eq 10 ] ; then echo " Timeout, aborting." ; exit 1 ; fi ; retries=$(($retries+1)) ; done
- - ./clair-scanner -c http://docker:6060 --ip $(hostname -i) -r gl-container-scanning-report.json -l clair.log -w clair-whitelist.yml ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG} || true
- artifacts:
- reports:
- container_scanning: gl-container-scanning-report.json
-```
-
-The above example will create a `container_scanning` job in your CI/CD pipeline, pull
-the image from the [Container Registry](../../user/project/container_registry.md)
-(whose name is defined from the two `CI_APPLICATION_` variables) and scan it
-for possible vulnerabilities. The report will be saved as a
-[Container Scanning report artifact](../yaml/README.md#artifactsreportscontainer_scanning-ultimate)
-that you can later download and analyze.
-Due to implementation limitations we always take the latest Container Scanning artifact available.
-
-If you want to whitelist some specific vulnerabilities, you can do so by defining
-them in a [YAML file](https://github.com/arminc/clair-scanner/blob/master/README.md#example-whitelist-yaml-file),
-in our case its named `clair-whitelist.yml`.
-
-TIP: **Tip:**
-For [GitLab Ultimate][ee] users, this information will
-be automatically extracted and shown right in the merge request widget.
-[Learn more on Container Scanning in merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/container_scanning.html).
-
-CAUTION: **Caution:**
-Starting with GitLab 11.5, Container Scanning feature is licensed under the name `container_scanning`.
-While the old name `sast_container` is still maintained, it has been deprecated with GitLab 11.5 and
-may be removed in next major release, GitLab 12.0. You are advised to update your current `.gitlab-ci.yml`
-configuration to reflect that change if you are using the `$GITLAB_FEATURES` environment variable.
-
-## Previous job definitions
-
-CAUTION: **Caution:**
-Before GitLab 11.5, Container Scanning job and artifact had to be named specifically
-to automatically extract report data and show it in the merge request widget.
-While these old job definitions are still maintained they have been deprecated
-and may be removed in next major release, GitLab 12.0.
-You are advised to update your current `.gitlab-ci.yml` configuration to reflect that change.
-
-For GitLab 11.4 and earlier, the job should look like:
-
-```yaml
-container_scanning:
- image: docker:stable
- variables:
- DOCKER_DRIVER: overlay2
- ## Define two new variables based on GitLab's CI/CD predefined variables
- ## https://docs.gitlab.com/ee/ci/variables/#predefined-environment-variables
- CI_APPLICATION_REPOSITORY: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
- CI_APPLICATION_TAG: $CI_COMMIT_SHA
- allow_failure: true
- services:
- - docker:stable-dind
- script:
- - docker run -d --name db arminc/clair-db:latest
- - docker run -p 6060:6060 --link db:postgres -d --name clair --restart on-failure arminc/clair-local-scan:v2.0.6
- - apk add -U wget ca-certificates
- - docker pull ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG}
- - wget https://github.com/arminc/clair-scanner/releases/download/v8/clair-scanner_linux_amd64
- - mv clair-scanner_linux_amd64 clair-scanner
- - chmod +x clair-scanner
- - touch clair-whitelist.yml
- - while( ! wget -q -O /dev/null http://docker:6060/v1/namespaces ) ; do sleep 1 ; done
- - retries=0
- - echo "Waiting for clair daemon to start"
- - while( ! wget -T 10 -q -O /dev/null http://docker:6060/v1/namespaces ) ; do sleep 1 ; echo -n "." ; if [ $retries -eq 10 ] ; then echo " Timeout, aborting." ; exit 1 ; fi ; retries=$(($retries+1)) ; done
- - ./clair-scanner -c http://docker:6060 --ip $(hostname -i) -r gl-container-scanning-report.json -l clair.log -w clair-whitelist.yml ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG} || true
- artifacts:
- paths: [gl-container-scanning-report.json]
-```
-
-Alternatively the job name could be `sast:container`
-and the artifact name could be `gl-sast-container-report.json`.
-These names have been deprecated with GitLab 11.0
-and may be removed in next major release, GitLab 12.0.
-
-[ee]: https://about.gitlab.com/pricing/
+This document was moved to [another location](../../user/application_security/container_scanning/index.md).
diff --git a/doc/ci/examples/dast.md b/doc/ci/examples/dast.md
index ab0ca13d2cf..9591abfc276 100644
--- a/doc/ci/examples/dast.md
+++ b/doc/ci/examples/dast.md
@@ -1,102 +1,5 @@
-# Dynamic Application Security Testing with GitLab CI/CD
+---
+redirect_to: '../../user/application_security/dast/index.md'
+---
-CAUTION: **Caution:**
-The job definition shown below is supported on GitLab 11.5 and later versions.
-It also requires the GitLab Runner 11.5 or later.
-For earlier versions, use the [previous job definitions](#previous-job-definitions).
-
-[Dynamic Application Security Testing (DAST)](https://en.wikipedia.org/wiki/Dynamic_program_analysis)
-is using the popular open source tool [OWASP ZAProxy](https://github.com/zaproxy/zaproxy)
-to perform an analysis on your running web application.
-Since it is based on [ZAP Baseline](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan)
-DAST will perform passive scanning only;
-it will not actively attack your application.
-
-It can be very useful combined with [Review Apps](../review_apps/index.md).
-
-## Example
-
-First, you need GitLab Runner with
-[docker-in-docker executor](../docker/using_docker_build.md#use-docker-in-docker-executor).
-
-Once you set up the Runner, add a new job to `.gitlab-ci.yml` that
-generates the expected report:
-
-```yaml
-dast:
- image: registry.gitlab.com/gitlab-org/security-products/zaproxy
- variables:
- website: "https://example.com"
- allow_failure: true
- script:
- - mkdir /zap/wrk/
- - /zap/zap-baseline.py -J gl-dast-report.json -t $website || true
- - cp /zap/wrk/gl-dast-report.json .
- artifacts:
- reports:
- dast: gl-dast-report.json
-```
-
-The above example will create a `dast` job in your CI/CD pipeline which will run
-the tests on the URL defined in the `website` variable (change it to use your
-own) and scan it for possible vulnerabilities. The report will be saved as a
-[DAST report artifact](../yaml/README.md#artifactsreportsdast-ultimate)
-that you can later download and analyze.
-Due to implementation limitations we always take the latest DAST artifact available.
-
-It's also possible to authenticate the user before performing DAST checks:
-
-```yaml
-dast:
- image: registry.gitlab.com/gitlab-org/security-products/zaproxy
- variables:
- website: "https://example.com"
- login_url: "https://example.com/sign-in"
- username: "john.doe@example.com"
- password: "john-doe-password"
- allow_failure: true
- script:
- - mkdir /zap/wrk/
- - /zap/zap-baseline.py -J gl-dast-report.json -t $website
- --auth-url $login_url
- --auth-username $username
- --auth-password $password || true
- - cp /zap/wrk/gl-dast-report.json .
- artifacts:
- reports:
- dast: gl-dast-report.json
-```
-See [zaproxy documentation](https://gitlab.com/gitlab-org/security-products/zaproxy)
-to learn more about authentication settings.
-
-TIP: **Tip:**
-For [GitLab Ultimate][ee] users, this information will
-be automatically extracted and shown right in the merge request widget.
-[Learn more on DAST in merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/dast.html).
-
-## Previous job definitions
-
-CAUTION: **Caution:**
-Before GitLab 11.5, DAST job and artifact had to be named specifically
-to automatically extract report data and show it in the merge request widget.
-While these old job definitions are still maintained they have been deprecated
-and may be removed in next major release, GitLab 12.0.
-You are advised to update your current `.gitlab-ci.yml` configuration to reflect that change.
-
-For GitLab 11.4 and earlier, the job should look like:
-
-```yaml
-dast:
- image: registry.gitlab.com/gitlab-org/security-products/zaproxy
- variables:
- website: "https://example.com"
- allow_failure: true
- script:
- - mkdir /zap/wrk/
- - /zap/zap-baseline.py -J gl-dast-report.json -t $website || true
- - cp /zap/wrk/gl-dast-report.json .
- artifacts:
- paths: [gl-dast-report.json]
-```
-
-[ee]: https://about.gitlab.com/pricing/
+This document was moved to [another location](../../user/application_security/dast/index.md).
diff --git a/doc/ci/examples/dependency_scanning.md b/doc/ci/examples/dependency_scanning.md
new file mode 100644
index 00000000000..dc234a3489f
--- /dev/null
+++ b/doc/ci/examples/dependency_scanning.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../../user/application_security/dependency_scanning/index.md'
+---
+
+This document was moved to [another location](../../user/application_security/dependency_scanning/index.md).
diff --git a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md b/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md
index cf281605f5e..538843ab8dc 100644
--- a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md
+++ b/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md
@@ -3,7 +3,9 @@ author: Dylan Griffith
author_gitlab: DylanGriffith
level: intermediate
article_type: tutorial
+type: tutorial
date: 2018-06-07
+last_updated: 2019-04-08
description: "Continuous Deployment of a Spring Boot application to Cloud Foundry with GitLab CI/CD"
---
@@ -25,13 +27,13 @@ using GitLab CI/CD, read through the blog post [Continuous Delivery of a Spring
## Requirements
-_We assume you are familiar with Java, GitLab, Cloud Foundry, and GitLab CI/CD._
+This tutorial assumes you are familiar with Java, GitLab, Cloud Foundry, and GitLab CI/CD.
-To follow along with this tutorial you will need the following:
+To follow along, you will need:
- An account on [Pivotal Web Services (PWS)](https://run.pivotal.io/) or any
- other Cloud Foundry instance
-- An account on GitLab
+ other Cloud Foundry (CF) instance.
+- An account on GitLab.
NOTE: **Note:**
You will need to replace the `api.run.pivotal.io` URL in the all below
@@ -77,7 +79,10 @@ image: java:8
stages:
- build
- deploy
-
+
+before_script:
+ - chmod +x mvnw
+
build:
stage: build
script: ./mvnw package
diff --git a/doc/ci/examples/deployment/README.md b/doc/ci/examples/deployment/README.md
index 010ba6b66a2..26b10c7eeaf 100644
--- a/doc/ci/examples/deployment/README.md
+++ b/doc/ci/examples/deployment/README.md
@@ -1,12 +1,14 @@
+---
+type: tutorial
+---
+
# Using Dpl as deployment tool
-[Dpl](https://github.com/travis-ci/dpl) (dee-pee-ell) is a deploy tool made for
+[Dpl](https://github.com/travis-ci/dpl) (prouncounced like the letters D-P-L) is a deploy tool made for
continuous deployment that's developed and used by Travis CI, but can also be
used with GitLab CI.
->**Note:**
-We recommend to use Dpl if you're deploying to any of these services:
-<https://github.com/travis-ci/dpl#supported-providers>.
+Dpl can be used to deploy to any of the [supported providers](https://github.com/travis-ci/dpl#supported-providers).
## Requirements
@@ -50,8 +52,8 @@ To use different provider take a look at long list of [Supported Providers](http
## Using Dpl with Docker
-When you use GitLab Runner you most likely configured it to use your server's shell commands.
-This means that all commands are run in context of local user (ie. gitlab_runner or gitlab_ci_multi_runner).
+In most cases, you will have configured [GitLab Runner](https://docs.gitlab.com/runner/) to use your server's shell commands.
+This means that all commands are run in the context of local user (e.g. gitlab_runner or gitlab_ci_multi_runner).
It also means that most probably in your Docker container you don't have the Ruby runtime installed.
You will have to install it:
diff --git a/doc/ci/examples/deployment/composer-npm-deploy.md b/doc/ci/examples/deployment/composer-npm-deploy.md
index 4758ccad5aa..79b3cbd0c69 100644
--- a/doc/ci/examples/deployment/composer-npm-deploy.md
+++ b/doc/ci/examples/deployment/composer-npm-deploy.md
@@ -1,8 +1,12 @@
+---
+type: tutorial
+---
+
# Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD
-This guide covers the building dependencies of a PHP project while compiling assets via an NPM script.
+This guide covers the building of dependencies of a PHP project while compiling assets via an NPM script using [GitLab CI/CD](../../README.md).
-While is possible to create your own image with custom PHP and Node JS versions, for brevity, we will use an existing [Docker image](https://hub.docker.com/r/tetraweb/php/) that contains both PHP and NodeJS installed.
+While it is possible to create your own image with custom PHP and Node JS versions, for brevity, we will use an existing [Docker image](https://hub.docker.com/r/tetraweb/php/) that contains both PHP and NodeJS installed.
```yaml
image: tetraweb/php
@@ -46,9 +50,9 @@ To make this work, you need to add a GitLab CI/CD Variable (accessible on _gitla
### Security tip
-Create a user that has access **only** to the folder that needs to be updated!
+Create a user that has access **only** to the folder that needs to be updated.
-After you create that variable, you need to make sure that key will be added to the docker container on run:
+After you create that variable, you need to make sure that key will be added to the Docker container on run:
```yaml
before_script:
@@ -68,7 +72,7 @@ In order, this means that:
And this is basically all you need in the `before_script` section.
-## How to deploy things
+## How to deploy
As we stated above, we need to deploy the `build` folder from the docker image to our server. To do so, we create a new job:
@@ -93,7 +97,7 @@ Here's the breakdown:
1. `ssh-add ...` we will add that private key you added on the web UI to the docker container
1. We will connect via `ssh` and create a new `_tmp` folder
1. We will connect via `scp` and upload the `build` folder (which was generated by a `npm` script) to our previously created `_tmp` folder
-1. We will connect again to `ssh` and move the `live` folder to an `_old` folder, then move `_tmp` to `live`.
+1. We will connect again via `ssh` and move the `live` folder to an `_old` folder, then move `_tmp` to `live`.
1. We connect to ssh and remove the `_old` folder
What's the deal with the artifacts? We just tell GitLab CI to keep the `build` directory (later on, you can download that as needed).
@@ -109,14 +113,14 @@ If you're using this only for stage server, you could do this in two steps:
The problem is that there will be a small period of time when you won't have the app on your server.
-So we use so many steps because we want to make sure that at any given time we have a functional app in place.
+Therefore, for a production environment we use additional steps to ensure that at any given time, a functional app is in place.
## Where to go next
-Since this was a WordPress project, I gave real life code snippets. Some ideas you can pursuit:
+Since this was a WordPress project, I gave real life code snippets. Some further ideas you can pursue:
-- Having a slightly different script for `master` branch will allow you to deploy to a production server from that branch and to a stage server from any other branches;
-- Instead of pushing it live, you can push it to WordPress official repo (with creating a SVN commit & stuff);
+- Having a slightly different script for `master` branch will allow you to deploy to a production server from that branch and to a stage server from any other branches.
+- Instead of pushing it live, you can push it to WordPress official repo (with creating a SVN commit, etc.).
- You could generate i18n text domains on the fly.
---
diff --git a/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md b/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md
index d6ad00a77da..50e61cafeb9 100644
--- a/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md
+++ b/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md
@@ -3,6 +3,7 @@ author: Ryan Hall
author_gitlab: blitzgren
level: intermediate
article_type: tutorial
+type: tutorial
date: 2018-03-07
last_updated: 2019-03-11
---
@@ -14,7 +15,7 @@ platforms without the use of plugins like Adobe Flash. Furthermore, by using Git
single game developers, as well as game dev teams, can easily host browser-based games online.
In this tutorial, we'll focus on DevOps, as well as testing and hosting games with Continuous
-Integration/Deployment methods. We assume you are familiar with GitLab, javascript,
+Integration/Deployment methods using [GitLab CI/CD](../../README.md). We assume you are familiar with GitLab, JavaScript,
and the basics of game development.
## The game
diff --git a/doc/ci/examples/end_to_end_testing_webdriverio/index.md b/doc/ci/examples/end_to_end_testing_webdriverio/index.md
index bd221b7145e..7f1beb96bbf 100644
--- a/doc/ci/examples/end_to_end_testing_webdriverio/index.md
+++ b/doc/ci/examples/end_to_end_testing_webdriverio/index.md
@@ -3,6 +3,7 @@ author: Vincent Tunru
author_gitlab: Vinnl
level: advanced
article_type: user guide
+type: tutorial
date: 2019-02-18
description: 'Confidence checking your entire app every time a new feature is added can quickly become repetitive. Learn how to automate it with GitLab CI/CD.'
---
@@ -22,7 +23,9 @@ However, looking at the freshly deployed code to check whether it still looks an
expected is repetitive manual work, which means it is a prime candidate for automation. This is
where automated [end-to-end testing](https://martinfowler.com/bliki/BroadStackTest.html) comes in:
having the computer run through a few simple scenarios that requires the proper functioning of all
-layers of your application, from the frontend to the database. In this article, we will discuss how
+layers of your application, from the frontend to the database.
+
+In this article, we will discuss how
to write such end-to-end tests, and how to set up GitLab CI/CD to automatically run these tests
against your new code, on a branch-by-branch basis. For the scope of this article, we will walk you
through the process of setting up GitLab CI/CD for end-to-end testing Javascript-based applications
diff --git a/doc/ci/examples/laravel_with_gitlab_and_envoy/img/laravel_with_gitlab_and_envoy.png b/doc/ci/examples/laravel_with_gitlab_and_envoy/img/laravel_with_gitlab_and_envoy.png
deleted file mode 100644
index bc188f83fb1..00000000000
--- a/doc/ci/examples/laravel_with_gitlab_and_envoy/img/laravel_with_gitlab_and_envoy.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
index f56d5429fb7..d7308a3a5ec 100644
--- a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
+++ b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
@@ -4,6 +4,7 @@ author: Mehran Rasulian
author_gitlab: mehranrasulian
level: intermediate
article_type: tutorial
+type: tutorial
date: 2017-08-31
last_updated: 2019-03-06
---
diff --git a/doc/ci/examples/license_management.md b/doc/ci/examples/license_management.md
new file mode 100644
index 00000000000..53e38111bf3
--- /dev/null
+++ b/doc/ci/examples/license_management.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../../user/application_security/license_management/index.md'
+---
+
+This document was moved to [another location](../../user/application_security/license_management/index.md).
diff --git a/doc/ci/examples/php.md b/doc/ci/examples/php.md
index c1048f3d2e3..c459bb7001f 100644
--- a/doc/ci/examples/php.md
+++ b/doc/ci/examples/php.md
@@ -1,8 +1,12 @@
+---
+type: tutorial
+---
+
# Testing PHP projects
This guide covers basic building instructions for PHP projects.
-There are covered two cases: testing using the Docker executor and testing
+Two testing scenarios are covered: using the Docker executor and
using the Shell executor.
## Test PHP projects using the Docker executor
@@ -245,7 +249,7 @@ before_script:
...
```
-## Access private packages / dependencies
+## Access private packages or dependencies
If your test suite needs to access a private repository, you need to configure
[the SSH keys](../ssh_keys/README.md) in order to be able to clone it.
@@ -254,7 +258,7 @@ If your test suite needs to access a private repository, you need to configure
Most of the time you will need a running database in order for your tests to
run. If you are using the Docker executor you can leverage Docker's ability to
-link to other containers. In GitLab Runner lingo, this can be achieved by
+link to other containers. With GitLab Runner, this can be achieved by
defining a `service`.
This functionality is covered in [the CI services](../services/README.md)
@@ -279,7 +283,7 @@ We have set up an [Example PHP Project][php-example-repo] for your convenience
that runs on [GitLab.com](https://gitlab.com) using our publicly available
[shared runners](../runners/README.md).
-Want to hack on it? Simply fork it, commit and push your changes. Within a few
+Want to hack on it? Simply fork it, commit, and push your changes. Within a few
moments the changes will be picked by a public runner and the job will begin.
[php-hub]: https://hub.docker.com/r/_/php/
diff --git a/doc/ci/examples/sast.md b/doc/ci/examples/sast.md
new file mode 100644
index 00000000000..7c644ac833d
--- /dev/null
+++ b/doc/ci/examples/sast.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../../user/application_security/sast/index.md'
+---
+
+This document was moved to [another location](../../user/application_security/sast/index.md).
diff --git a/doc/ci/examples/sast_docker.md b/doc/ci/examples/sast_docker.md
index 70b269046e5..6570f6b2d98 100644
--- a/doc/ci/examples/sast_docker.md
+++ b/doc/ci/examples/sast_docker.md
@@ -1,5 +1,5 @@
---
-redirect_to: 'container_scanning.md'
+redirect_to: '../../user/application_security/container_scanning/index.md'
---
-This document was moved to [another location](container_scanning.md).
+This document was moved to [another location](../../user/application_security/container_scanning/index.md).
diff --git a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
index 99a4316ab0d..f9d185f187c 100644
--- a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
+++ b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
@@ -1,15 +1,24 @@
+---
+type: tutorial
+---
+
# Test and deploy a Python application with GitLab CI/CD
This example will guide you how to run tests in your Python application and deploy it automatically as Heroku application.
-You can checkout the [example source](https://gitlab.com/ayufan/python-getting-started).
+You can also view or fork the complete [example source](https://gitlab.com/ayufan/python-getting-started).
## Configure project
This is what the `.gitlab-ci.yml` file looks like for this project:
```yaml
+stages:
+ - test
+ - deploy
+
test:
+ stage: test
script:
# this configures Django application to use attached postgres database that is run on `postgres` host
- export DATABASE_URL=postgres://postgres:@postgres:5432/python-test-app
@@ -19,7 +28,7 @@ test:
- python manage.py test
staging:
- type: deploy
+ stage: deploy
script:
- apt-get update -qy
- apt-get install -y ruby-dev
@@ -29,7 +38,7 @@ staging:
- master
production:
- type: deploy
+ stage: deploy
script:
- apt-get update -qy
- apt-get install -y ruby-dev
@@ -41,9 +50,9 @@ production:
This project has three jobs:
-- `test` - used to test Django application,
-- `staging` - used to automatically deploy staging environment every push to `master` branch
-- `production` - used to automatically deploy production environment for every created tag
+- `test` - used to test Django application.
+- `staging` - used to automatically deploy staging environment every push to `master` branch.
+- `production` - used to automatically deploy production environment for every created tag.
## Store API keys
@@ -62,8 +71,9 @@ You can do this through the [Dashboard](https://dashboard.heroku.com/).
## Create Runner
First install [Docker Engine](https://docs.docker.com/installation/).
+
To build this project you also need to have [GitLab Runner](https://docs.gitlab.com/runner).
-You can use public runners available on `gitlab.com`, but you can register your own:
+You can use public runners available on `gitlab.com` or you can register your own:
```sh
gitlab-runner register \
@@ -76,6 +86,6 @@ gitlab-runner register \
--docker-postgres latest
```
-With the command above, you create a runner that uses [python:3.5](https://hub.docker.com/r/_/python/) image and uses [postgres](https://hub.docker.com/r/_/postgres/) database.
+With the command above, you create a runner that uses the [python:3.5](https://hub.docker.com/r/_/python/) image and uses a [postgres](https://hub.docker.com/r/_/postgres/) database.
-To access PostgreSQL database you need to connect to `host: postgres` as user `postgres` without password.
+To access the PostgreSQL database, connect to `host: postgres` as user `postgres` with no password.
diff --git a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
index 3a0ddf001b8..79d54b52b5a 100644
--- a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
+++ b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
@@ -1,8 +1,12 @@
+---
+type: tutorial
+---
+
# Test and deploy a Ruby application with GitLab CI/CD
-This example will guide you how to run tests in your Ruby on Rails application and deploy it automatically as Heroku application.
+This example will guide you through how to run tests in your Ruby on Rails application and deploy it automatically as a Heroku application.
-You can checkout the example [source](https://gitlab.com/ayufan/ruby-getting-started) and check [CI status](https://gitlab.com/ayufan/ruby-getting-started/builds?scope=all).
+You can also view or fork the complete [example source](https://gitlab.com/ayufan/ruby-getting-started) and view the logs of its past [CI jobs](https://gitlab.com/ayufan/ruby-getting-started/-/jobs?scope=finished).
## Configure the project
@@ -53,13 +57,14 @@ Find your Heroku API key in [Manage Account](https://dashboard.heroku.com/accoun
## Create Heroku application
For each of your environments, you'll need to create a new Heroku application.
-You can do this through the [Dashboard](https://dashboard.heroku.com/).
+You can do this through the [Heroku Dashboard](https://dashboard.heroku.com/).
## Create Runner
First install [Docker Engine](https://docs.docker.com/installation/).
+
To build this project you also need to have [GitLab Runner](https://docs.gitlab.com/runner/).
-You can use public runners available on `gitlab.com`, but you can register your own:
+You can use public runners available on `gitlab.com` or register your own:
```sh
gitlab-runner register \
@@ -72,6 +77,6 @@ gitlab-runner register \
--docker-postgres latest
```
-With the command above, you create a Runner that uses [ruby:2.2](https://hub.docker.com/r/_/ruby/) image and uses [postgres](https://hub.docker.com/r/_/postgres/) database.
+With the command above, you create a Runner that uses the [ruby:2.2](https://hub.docker.com/r/_/ruby/) image and uses a [postgres](https://hub.docker.com/r/_/postgres/) database.
-To access PostgreSQL database you need to connect to `host: postgres` as user `postgres` without password.
+To access the PostgreSQL database, connect to `host: postgres` as user `postgres` with no password.
diff --git a/doc/ci/examples/test-clojure-application.md b/doc/ci/examples/test-clojure-application.md
index 3b1026d174f..5cda8702b56 100644
--- a/doc/ci/examples/test-clojure-application.md
+++ b/doc/ci/examples/test-clojure-application.md
@@ -1,8 +1,15 @@
+---
+type: tutorial
+---
+
+NOTE: **Note:**
+This document has not been updated recently and could be out of date. For the latest documentation, see the [GitLab CI/CD](../README.md) page and the [GitLab CI/CD Pipeline Configuration Reference](../yaml/README.md).
+
# Test a Clojure application with GitLab CI/CD
-This example will guide you how to run tests in your Clojure application.
+This example will guide you how to run tests on your Clojure application.
-You can checkout the example [source](https://gitlab.com/dzaporozhets/clojure-web-application) and check [CI status](https://gitlab.com/dzaporozhets/clojure-web-application/builds?scope=all).
+You can view or fork the [example source](https://gitlab.com/dzaporozhets/clojure-web-application) and view the logs of its past [CI jobs](https://gitlab.com/dzaporozhets/clojure-web-application/builds?scope=finished).
## Configure the project
@@ -28,8 +35,9 @@ test:
- lein test
```
-In before script we install JRE and [Leiningen](http://leiningen.org/).
-Sample project uses [migratus](https://github.com/yogthos/migratus) library to manage database migrations.
-So we added database migration as last step of `before_script` section
+In `before_script`, we install JRE and [Leiningen](http://leiningen.org/).
+
+The sample project uses the [migratus](https://github.com/yogthos/migratus) library to manage database migrations, and
+we have added a database migration as the last step of `before_script`.
-You can use public runners available on `gitlab.com` for testing your application with such configuration.
+You can use public runners available on `gitlab.com` for testing your application with this configuration.
diff --git a/doc/ci/examples/test-scala-application.md b/doc/ci/examples/test-scala-application.md
index e1164b8d03a..0e33a1ba060 100644
--- a/doc/ci/examples/test-scala-application.md
+++ b/doc/ci/examples/test-scala-application.md
@@ -1,9 +1,12 @@
+---
+type: tutorial
+---
+
# Test and deploy a Scala application to Heroku
This example demonstrates the integration of GitLab CI with Scala
-applications using SBT. Checkout the example
-[project](https://gitlab.com/gitlab-examples/scala-sbt) and
-[build status](https://gitlab.com/gitlab-examples/scala-sbt/builds).
+applications using SBT. You can view or fork the [example project](https://gitlab.com/gitlab-examples/scala-sbt)
+and view the logs of its past [CI jobs](https://gitlab.com/gitlab-examples/scala-sbt/-/jobs?scope=finished).
## Add `.gitlab-ci.yml` file to project
@@ -41,12 +44,14 @@ deploy:
- dpl --provider=heroku --app=gitlab-play-sample-app --api-key=$HEROKU_API_KEY
```
-The `before_script` installs [SBT](http://www.scala-sbt.org/) and
-displays the version that is being used. The `test` stage executes SBT
-to compile and test the project.
-[scoverage](https://github.com/scoverage/sbt-scoverage) is used as an SBT
+In the above configuration:
+
+- The `before_script` installs [SBT](http://www.scala-sbt.org/) and
+displays the version that is being used.
+- The `test` stage executes SBT to compile and test the project.
+ - [sbt-scoverage](https://github.com/scoverage/sbt-scoverage) is used as an SBT
plugin to measure test coverage.
-The `deploy` stage automatically deploys the project to Heroku using dpl.
+- The `deploy` stage automatically deploys the project to Heroku using dpl.
You can use other versions of Scala and SBT by defining them in
`build.sbt`.
diff --git a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/job-succeeded.png b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/job-succeeded.png
deleted file mode 100644
index 77b05f55f88..00000000000
--- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/job-succeeded.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md
index 4a5fda661df..ec25ca1bfc3 100644
--- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md
+++ b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md
@@ -3,6 +3,7 @@ author: Alexandre S Hostert
author_gitlab: Hostert
level: beginner
article_type: tutorial
+type: tutorial
date: 2018-02-20
last_updated: 2019-03-06
---
@@ -16,11 +17,11 @@ simultaneous users.
That's why we're hearing so much about Phoenix today.
-In this tutorial, we'll teach you how to set up GitLab CI/CD to build and test a Phoenix
+In this tutorial, we'll teach you how to set up [GitLab CI/CD](../../README.md) to build and test a Phoenix
application.
-_We assume that you know how to create a Phoenix app, run tests locally, and how to work with Git
-and GitLab UI._
+The tutorial assumes that you know how to create a Phoenix app, run tests locally, and how to work with Git
+and the GitLab UI.
## Introduction
diff --git a/doc/ci/git_submodules.md b/doc/ci/git_submodules.md
index 37078230b34..551044dd76f 100644
--- a/doc/ci/git_submodules.md
+++ b/doc/ci/git_submodules.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# Using Git submodules with GitLab CI
> **Notes:**
diff --git a/doc/ci/img/add_file_template_11_10.png b/doc/ci/img/add_file_template_11_10.png
new file mode 100644
index 00000000000..ca04d72615b
--- /dev/null
+++ b/doc/ci/img/add_file_template_11_10.png
Binary files differ
diff --git a/doc/ci/img/deployments_view.png b/doc/ci/img/deployments_view.png
index 45d882b536c..12090434bef 100644
--- a/doc/ci/img/deployments_view.png
+++ b/doc/ci/img/deployments_view.png
Binary files differ
diff --git a/doc/ci/img/environments_available.png b/doc/ci/img/environments_available.png
index 7ab92838ece..48fc6effc2d 100644
--- a/doc/ci/img/environments_available.png
+++ b/doc/ci/img/environments_available.png
Binary files differ
diff --git a/doc/ci/img/environments_mr_review_app.png b/doc/ci/img/environments_mr_review_app.png
index 61b7e9fe77c..6a7b7ce5679 100644
--- a/doc/ci/img/environments_mr_review_app.png
+++ b/doc/ci/img/environments_mr_review_app.png
Binary files differ
diff --git a/doc/ci/img/metrics_reports.png b/doc/ci/img/metrics_reports.png
new file mode 100644
index 00000000000..ffd9f6830a2
--- /dev/null
+++ b/doc/ci/img/metrics_reports.png
Binary files differ
diff --git a/doc/ci/img/multi_pipeline_mini_graph.gif b/doc/ci/img/multi_pipeline_mini_graph.gif
new file mode 100644
index 00000000000..de49ba5aa12
--- /dev/null
+++ b/doc/ci/img/multi_pipeline_mini_graph.gif
Binary files differ
diff --git a/doc/ci/img/multi_project_pipeline_graph.png b/doc/ci/img/multi_project_pipeline_graph.png
new file mode 100644
index 00000000000..723a455cb4a
--- /dev/null
+++ b/doc/ci/img/multi_project_pipeline_graph.png
Binary files differ
diff --git a/doc/ci/interactive_web_terminal/index.md b/doc/ci/interactive_web_terminal/index.md
index 2a4160f62b0..1387d4df500 100644
--- a/doc/ci/interactive_web_terminal/index.md
+++ b/doc/ci/interactive_web_terminal/index.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# Interactive Web Terminals
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/50144) in GitLab 11.3.
@@ -54,3 +58,8 @@ terminal will block the job from finishing for the duration configured in
close the terminal window.
![finished job with terminal open](img/finished_job_with_terminal_open.png)
+
+## Interactive Web Terminals for the Web IDE **[ULTIMATE ONLY]**
+
+Read the Web IDE docs to learn how to run [Interactive Terminals through the Web IDE](../../user/project/web_ide/index.md).
+
diff --git a/doc/ci/introduction/img/gitlab_workflow_example_extended_11_11.png b/doc/ci/introduction/img/gitlab_workflow_example_extended_11_11.png
new file mode 100644
index 00000000000..5089a1088c5
--- /dev/null
+++ b/doc/ci/introduction/img/gitlab_workflow_example_extended_11_11.png
Binary files differ
diff --git a/doc/ci/introduction/index.md b/doc/ci/introduction/index.md
index 6055d8c282a..ef9f9a9973c 100644
--- a/doc/ci/introduction/index.md
+++ b/doc/ci/introduction/index.md
@@ -1,5 +1,6 @@
---
description: "An overview of Continuous Integration, Continuous Delivery, and Continuous Deployment, as well as an introduction to GitLab CI/CD."
+type: concepts
---
# Introduction to CI/CD with GitLab
@@ -133,8 +134,8 @@ At the end, if anything goes wrong, you can easily
### Basic CI/CD workflow
-This is a very simple example for how GitLab CI/CD fits in a common
-development workflow.
+Consider the following example for how GitLab CI/CD fits in a
+common development workflow.
Assume that you have discussed a code implementation in an issue
and worked locally on your proposed changes. Once you push your
@@ -154,14 +155,59 @@ Once you're happy with your implementation:
- GitLab CI/CD deploys your changes automatically to a production environment.
- And finally, you and your team can easily roll it back if something goes wrong.
-<img src="img/gitlab_workflow_example_11_9.png" alt="GitLab workflow example" class="image-noshadow">
+![GitLab workflow example](img/gitlab_workflow_example_11_9.png)
-GitLab CI/CD is capable of a doing a lot more, but this workflow
+GitLab CI/CD is capable of doing a lot more, but this workflow
exemplifies GitLab's ability to track the entire process,
without the need of any external tool to deliver your software.
And, most usefully, you can visualize all the steps through
the GitLab UI.
+#### A deeper look into the CI/CD basic workflow
+
+If we take a deeper look into the basic workflow, we can see
+the features available in GitLab at each stage of the DevOps
+lifecycle, as shown on the illustration below.
+
+![Deeper look into the basic CI/CD workflow](img/gitlab_workflow_example_extended_11_11.png)
+
+If you look at the image from the left to the right,
+you'll see some of the features available in GitLab
+according to each stage (Verify, Package, Release).
+
+1. **Verify**:
+ - Automatically build and test your application with Continuous Integration.
+ - Analyze your source code quality with [GitLab Code Quality](../../user/project/merge_requests/code_quality.md). **[STARTER]**
+ - Determine the performance impact of code changes with [Browser Performance Testing](../../user/project/merge_requests/browser_performance_testing.md). **[PREMIUM]**
+ - Perform a series of tests, such as [Container Scanning](../../user/application_security/container_scanning/index.md) **[ULTIMATE]**, [Dependency Scanning](../../user/application_security/dependency_scanning/index.md) **[ULTIMATE]**, and [JUnit tests](../junit_test_reports.md).
+ - Deploy your changes with [Review Apps](../review_apps/index.md) to preview the app changes on every branch.
+1. **Package**:
+ - Store Docker images with [Container Registry](../../user/project/container_registry.md).
+ - Store NPM packages with [NPM Registry](../../user/project/packages/npm_registry.md). **[PREMIUM]**
+ - Store Maven artifacts with [Maven Repository](../../user/project/packages/maven_repository.md). **[PREMIUM]**
+1. **Release**:
+ - Continuous Deployment, automatically deploying your app to production.
+ - Continuous Delivery, manually click to deploy your app to production.
+ - Deploy static websites with [GitLab Pages](../../user/project/pages/index.md).
+ - Ship features to only a portion of your pods and let a percentage of your user base to visit the temporarily deployed feature with [Canary Deployments](../../user/project/canary_deployments.md). **[PREMIUM]**
+ - Deploy your features behind [Feature Flags](../../user/project/operations/feature_flags.md). **[PREMIUM]**
+ - Add release notes to any Git tag with [GitLab Releases](../../user/project/releases/index.md).
+ - View of the current health and status of each CI environment running on Kubernetes with [Deploy Boards](../../user/project/deploy_boards.md). **[PREMIUM]**
+ - Deploy your application to a production environment in a Kubernetes cluster with [Auto Deploy](../../topics/autodevops/index.md#auto-deploy).
+
+With GitLab CI/CD you can also:
+
+- Easily set up your app's entire lifecycle with [Auto DevOps](../../topics/autodevops/index.md).
+- Deploy your app to different [environments](../environments.md).
+- Install your own [GitLab Runner](https://docs.gitlab.com/runner/).
+- [Schedule pipelines](../../user/project/pipelines/schedules.md).
+- Check for app vulnerabilities with [Security Test reports](../../user/project/merge_requests/index.md#security-reports-ultimate). **[ULTIMATE]**
+
+To see all CI/CD features, navigate back to the [CI/CD index](../README.md).
+
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+Watch the video [GitLab CI Live Demo](https://www.youtube.com/watch?v=pBe4t1CD8Fc) with a deeper overview of GitLab CI/CD.
+
### Setting up GitLab CI/CD for the first time
To get started with GitLab CI/CD, you need to familiarize yourself
@@ -178,16 +224,3 @@ existing one) for any application.
For a deep view of GitLab's CI/CD configuration options, check the
[`.gitlab-ci.yml` full reference](../yaml/README.md).
-
-### GitLab CI/CD feature set
-
-- Easily set up your app's entire lifecycle with [Auto DevOps](../../topics/autodevops/index.md).
-- Deploy static websites with [GitLab Pages](../../user/project/pages/index.md).
-- Deploy your app to different [environments](../environments.md).
-- Preview changes per merge request with [Review Apps](../review_apps/index.md).
-- Develop secure and private Docker images with [Container Registry](../../user/project/container_registry.md).
-- Install your own [GitLab Runner](https://docs.gitlab.com/runner/).
-- [Schedule pipelines](../../user/project/pipelines/schedules.md).
-- Check for app vulnerabilities with [Security Test reports](https://docs.gitlab.com/ee/user/project/merge_requests/#security-reports-ultimate). **[ULTIMATE]**
-
-To see all CI/CD features, navigate back to the [CI/CD index](../README.md).
diff --git a/doc/ci/junit_test_reports.md b/doc/ci/junit_test_reports.md
index d03c0b68daf..fa78f53f563 100644
--- a/doc/ci/junit_test_reports.md
+++ b/doc/ci/junit_test_reports.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# JUnit test reports
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/45318) in GitLab 11.2.
@@ -71,11 +75,11 @@ merge request widget.
NOTE: **Note:**
If you also want the ability to browse JUnit output files, include the
-[`artifacts:paths`](yaml/README.md#artifactspaths) keyword.
+[`artifacts:paths`](yaml/README.md#artifactspaths) keyword. An example of this is shown in the Ruby example below.
### Ruby example
-Use the following job in `.gitlab-ci.yml`:
+Use the following job in `.gitlab-ci.yml`. This includes the `artifacts:paths` keyword to provide a link to the JUnit output file.
```yaml
## Use https://github.com/sj26/rspec_junit_formatter to generate a JUnit report with rspec
@@ -85,6 +89,8 @@ ruby:
- bundle install
- rspec spec/lib/ --format RspecJunitFormatter --out rspec.xml
artifacts:
+ paths:
+ - rspec.xml
reports:
junit: rspec.xml
```
diff --git a/doc/ci/large_repositories/index.md b/doc/ci/large_repositories/index.md
index cfe638c0a22..29d649ad717 100644
--- a/doc/ci/large_repositories/index.md
+++ b/doc/ci/large_repositories/index.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# Optimizing GitLab for large repositories
Large repositories consisting of more than 50k files in a worktree
@@ -72,8 +76,9 @@ done by GitLab, requiring you to do them.
> Introduced in GitLab Runner 11.10.
-`GIT_CLONE_PATH` allows you to control where you clone your sources.
-This can have implications if you heavily use big repositories with fork workflow.
+[`GIT_CLONE_PATH`](../yaml/README.md#custom-build-directories) allows you to
+control where you clone your sources. This can have implications if you
+heavily use big repositories with fork workflow.
Fork workflow from GitLab Runner's perspective is stored as a separate repository
with separate worktree. That means that GitLab Runner cannot optimize the usage
@@ -83,29 +88,31 @@ In such cases, ideally you want to make the GitLab Runner executor be used only
for the given project and not shared across different projects to make this
process more efficient.
-The `GIT_CLONE_PATH` has to be within the `$CI_BUILDS_DIR`. Currently,
-it is impossible to pick any path from disk.
+The [`GIT_CLONE_PATH`](../yaml/README.md#custom-build-directories) has to be
+within the `$CI_BUILDS_DIR`. Currently, it is impossible to pick any path
+from disk.
## Git clean flags
> Introduced in GitLab Runner 11.10.
-`GIT_CLEAN_FLAGS` allows you to control whether or not you require
-the `git clean` command to be executed for each CI job.
-By default, GitLab ensures that you have your worktree on the given SHA,
+[`GIT_CLEAN_FLAGS`](../yaml/README.md#git-clean-flags) allows you to control
+whether or not you require the `git clean` command to be executed for each CI
+job. By default, GitLab ensures that you have your worktree on the given SHA,
and that your repository is clean.
-`GIT_CLEAN_FLAGS` is disabled when set to `none`. On very big repositories, this
-might be desired because `git clean` is disk I/O intensive. Controlling that
-with `GIT_CLEAN_FLAGS: -ffdx -e .build/`, for example, allows you to control and
-disable removal of some directories within the worktree between subsequent runs,
-which can speed-up the incremental builds. This has the biggest effect
-if you re-use existing machines, and have an existing worktree that you can re-use
-for builds.
-
-For exact parameters accepted by `GIT_CLEAN_FLAGS`, see the documentation
-for [git clean](https://git-scm.com/docs/git-clean). The
-available parameters are dependent on Git version.
+[`GIT_CLEAN_FLAGS`](../yaml/README.md#git-clean-flags) is disabled when set
+to `none`. On very big repositories, this might be desired because `git
+clean` is disk I/O intensive. Controlling that with `GIT_CLEAN_FLAGS: -ffdx
+-e .build/`, for example, allows you to control and disable removal of some
+directories within the worktree between subsequent runs, which can speed-up
+the incremental builds. This has the biggest effect if you re-use existing
+machines, and have an existing worktree that you can re-use for builds.
+
+For exact parameters accepted by
+[`GIT_CLEAN_FLAGS`](../yaml/README.md#git-clean-flags), see the documentation
+for [git clean](https://git-scm.com/docs/git-clean). The available parameters
+are dependent on Git version.
## Fork-based workflow
diff --git a/doc/ci/merge_request_pipelines/img/pipeline_detail.png b/doc/ci/merge_request_pipelines/img/pipeline_detail.png
deleted file mode 100644
index 90e7c449a66..00000000000
--- a/doc/ci/merge_request_pipelines/img/pipeline_detail.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/merge_request_pipelines/index.md b/doc/ci/merge_request_pipelines/index.md
index 4f61e97bd8a..fe2fc790505 100644
--- a/doc/ci/merge_request_pipelines/index.md
+++ b/doc/ci/merge_request_pipelines/index.md
@@ -1,5 +1,15 @@
+---
+type: reference
+---
+
# Pipelines for merge requests
+NOTE: **Note**:
+As of GitLab 11.10, pipelines for merge requests require GitLab Runner 11.9
+or higher due to the [recent refspecs
+changes](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/25504).
+Anything lower will cause the pipeline to fail.
+
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/15310) in GitLab 11.6.
Usually, when you create a new merge request, a pipeline runs with the
@@ -61,18 +71,21 @@ when a merge request was created or updated. For example:
![Merge request page](img/merge_request.png)
-## Combined ref pipelines **[PREMIUM]**
+## Pipelines for Merged Results **[PREMIUM]**
-> [GitLab Premium](https://about.gitlab.com/pricing/) 11.10.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/7380) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.10.
+> This feature is disabled by default until we resolve issues with [contention handling](https://gitlab.com/gitlab-org/gitlab-ee/issues/9186), but [can be enabled manually](#enabling-pipelines-for-merged-results).
It's possible for your source and target branches to diverge, which can result
in the scenario that source branch's pipeline was green, the target's pipeline was green,
-but the combined output fails. By having your merge request pipeline automatically
-create a new ref that contains the merge result of the source and target branch
+but the combined output fails.
+
+By having your merge request pipeline automatically
+create a new ref that contains the merge result of the source and target branch
(then running a pipeline on that ref), we can better test that the combined result
is also valid.
-From GitLab 11.10, pipelines for merge requests run by default
+GitLab can run pipelines for merge requests
on this merged result. That is, where the source and target branches are combined into a
new ref and a pipeline for this ref validates the result prior to merging.
@@ -87,9 +100,9 @@ The detached state serves to warn you that you are working in a situation
subjected to merge problems, and helps to highlight that you should
get out of WIP status or resolve merge conflicts as soon as possible.
-### Enabling combined ref pipelines
+### Enabling Pipelines for Merged Results
-This feature disabled by default until we resolve issues with [contention handling](https://gitlab.com/gitlab-org/gitlab-ee/issues/9186). It can be enabled at the project level:
+To enable pipelines on merged results at the project level:
1. Visit your project's **Settings > General** and expand **Merge requests**.
1. Check **Merge pipelines will try to validate the post-merge result prior to merging**.
@@ -97,7 +110,11 @@ This feature disabled by default until we resolve issues with [contention handli
![Merge request pipeline config](img/merge_request_pipeline_config.png)
-### Combined ref pipeline's limitations
+CAUTION: **Warning:**
+Make sure your `gitlab-ci.yml` file is [configured properly for pipelines for merge requests](#configuring-pipelines-for-merge-requests),
+otherwise pipelines for merged results won't run and your merge requests will be stuck in an unresolved state.
+
+### Pipelines for Merged Result's limitations
- This feature requires [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) 11.9 or newer.
- This feature requires [Gitaly](https://gitlab.com/gitlab-org/gitaly) 1.21.0 or newer.
@@ -187,5 +204,5 @@ By using pipelines for merge requests, GitLab exposes additional predefined vari
Those variables contain information of the associated merge request, so that it's useful
to integrate your job with [GitLab Merge Request API](../../api/merge_requests.md).
-You can find the list of avilable variables in [the reference sheet](../variables/predefined_variables.md).
+You can find the list of available variables in [the reference sheet](../variables/predefined_variables.md).
The variable names begin with the `CI_MERGE_REQUEST_` prefix.
diff --git a/doc/ci/metrics_reports.md b/doc/ci/metrics_reports.md
new file mode 100644
index 00000000000..f9cfc0892a7
--- /dev/null
+++ b/doc/ci/metrics_reports.md
@@ -0,0 +1,49 @@
+---
+type: reference
+---
+
+# Metrics Reports **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9788) in [GitLab Premium](https://about.gitlab.com/pricing) 11.10.
+Requires GitLab Runner 11.10 and above.
+
+## Overview
+
+GitLab provides a lot of great reporting tools for [merge requests](../user/project/merge_requests/index.md) - [JUnit reports](junit_test_reports.md), [codequality](../user/project/merge_requests/code_quality.md), performance tests, etc. While JUnit is a great open framework for tests that "pass" or "fail", it is also important to see other types of metrics from a given change.
+
+You can configure your job to use custom Metrics Reports, and GitLab will display a report on the merge request so that it's easier and faster to identify changes without having to check the entire log.
+
+![Metrics Reports](img/metrics_reports.png)
+
+## Use cases
+
+Consider the following examples of data that can utilize Metrics Reports:
+
+1. Memory usage
+1. Load testing results
+1. Code complexity
+1. Code coverage stats
+
+## How it works
+
+Metrics are read from the metrics report (default: `metrics.txt`). They are parsed and displayed in the MR widget.
+
+All values are considered strings and string compare is used to find differences between the latest available `metrics` artifact from:
+
+- `master`
+- The feature branch
+
+## How to set it up
+
+Add a job that creates a [metrics report](yaml/README.md#artifactsreportsmetrics-premium) (default filename: `metrics.txt`). The file should conform to the [OpenMetrics](https://openmetrics.io/) format.
+
+For example:
+
+```yaml
+metrics:
+ script:
+ - echo 'metric_name metric_value' > metrics.txt
+ artifacts:
+ reports:
+ metrics: metrics.txt
+```
diff --git a/doc/ci/multi_project_pipeline_graphs.md b/doc/ci/multi_project_pipeline_graphs.md
new file mode 100644
index 00000000000..af10e5b6126
--- /dev/null
+++ b/doc/ci/multi_project_pipeline_graphs.md
@@ -0,0 +1,5 @@
+---
+redirect_to: 'multi_project_pipelines.md'
+---
+
+This document was moved to [another location](multi_project_pipelines.md).
diff --git a/doc/ci/multi_project_pipelines.md b/doc/ci/multi_project_pipelines.md
new file mode 100644
index 00000000000..50c8d82602b
--- /dev/null
+++ b/doc/ci/multi_project_pipelines.md
@@ -0,0 +1,189 @@
+---
+type: reference
+---
+
+# Multi-project pipelines **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/2121) in
+[GitLab Premium 9.3](https://about.gitlab.com/2017/06/22/gitlab-9-3-released/#multi-project-pipeline-graphs).
+
+When you set up [GitLab CI/CD](README.md) across multiple projects, you can visualize
+the entire pipeline, including all cross-project inter-dependencies.
+
+## Overview
+
+GitLab CI/CD is a powerful continuous integration tool that works not only per project, but also across projects. When you
+configure GitLab CI for your project, you can visualize the stages
+of your [jobs](pipelines.md#configuring-pipelines) on a [pipeline graph](pipelines.md#visualizing-pipelines).
+
+![Multi-project pipeline graph](img/multi_project_pipeline_graph.png)
+
+In the Merge Request Widget, multi-project pipeline mini-graphs are displayed,
+and when hovering or tapping (on touchscreen devices) they will expand and be shown adjacent to each other.
+
+![Multi-project mini graph](img/multi_pipeline_mini_graph.gif)
+
+Multi-project pipelines are useful for larger products that require cross-project inter-dependencies, such as those
+adopting a [microservices architecture](https://about.gitlab.com/2016/08/16/trends-in-version-control-land-microservices/).
+
+For a demonstration of how cross-functional development teams can use cross-pipeline
+triggering to trigger multiple pipelines for different microservices projects, see
+[Cross-project Pipeline Triggering and Visualization](https://about.gitlab.com/handbook/marketing/product-marketing/demo/#cross-project-pipeline-triggering-and-visualization-may-2019---1110).
+
+## Use cases
+
+Let's assume you deploy your web app from different projects in GitLab:
+
+- One for the free version, which has its own pipeline that builds and tests your app
+- One for the paid version add-ons, which also pass through builds and tests
+- One for the documentation, which also builds, tests, and deploys with an SSG
+
+With Multi-Project Pipelines, you can visualize the entire pipeline, including all stages of builds and tests for the three projects.
+
+## Triggering multi-project pipelines through API
+
+When you use the [`CI_JOB_TOKEN` to trigger pipelines](triggers/README.md#ci-job-token), GitLab
+recognizes the source of the job token, and thus internally ties these pipelines
+together, allowing you to visualize their relationships on pipeline graphs.
+
+These relationships are displayed in the pipeline graph by showing inbound and
+outbound connections for upstream and downstream pipeline dependencies.
+
+## Creating multi-project pipelines from `.gitlab-ci.yml`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/8997) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.8.
+
+### Triggering a downstream pipeline using a bridge job
+
+Before GitLab 11.8, it was necessary to implement a pipeline job that was
+responsible for making the API request [to trigger a pipeline](#triggering-multi-project-pipelines-through-api)
+in a different project.
+
+In GitLab 11.8, GitLab provides a new CI/CD configuration syntax to make this
+task easier, and avoid needing GitLab Runner for triggering cross-project
+pipelines. The following illustrates configuring a bridge job:
+
+```yaml
+rspec:
+ stage: test
+ script: bundle exec rspec
+
+staging:
+ variables:
+ ENVIRONMENT: staging
+ stage: deploy
+ trigger: my/deployment
+```
+
+In the example above, as soon as `rspec` job succeeds in the `test` stage,
+the `staging` bridge job is going to be started. The initial status of this
+job will be `pending`. GitLab will create a downstream pipeline in the
+`my/deployment` project and, as soon as the pipeline gets created, the
+`staging` job will succeed. `my/deployment` is a full path to that project.
+
+The user that created the upstream pipeline needs to have access rights to the
+downstream project (`my/deployment` in this case). If a downstream project can
+not be found, or a user does not have access rights to create pipeline there,
+the `staging` job is going to be marked as _failed_.
+
+CAUTION: **Caution:**
+`staging` will succeed as soon as a downstream pipeline gets created.
+GitLab does not support status attribution yet, however adding first-class
+`trigger` configuration syntax is ground work for implementing
+[status attribution](https://gitlab.com/gitlab-org/gitlab-ce/issues/39640).
+
+NOTE: **Note:**
+Bridge jobs do not support every configuration entry that a user can use
+in the case of regular jobs. Bridge jobs will not to be picked by a Runner,
+thus there is no point in adding support for `script`, for example. If a user
+tries to use unsupported configuration syntax, YAML validation will fail upon
+pipeline creation.
+
+### Specifying a downstream pipeline branch
+
+It is possible to specify a branch name that a downstream pipeline will use:
+
+```yaml
+rspec:
+ stage: test
+ script: bundle exec rspec
+
+staging:
+ stage: deploy
+ trigger:
+ project: my/deployment
+ branch: stable-11-2
+```
+
+Use a `project` keyword to specify full path to a downstream project. Use
+a `branch` keyword to specify a branch name.
+
+GitLab will use a commit that is currently on the HEAD of the branch when
+creating a downstream pipeline.
+
+### Passing variables to a downstream pipeline
+
+Sometimes you might want to pass variables to a downstream pipeline.
+You can do that using the `variables` keyword, just like you would when
+defining a regular job.
+
+```yaml
+rspec:
+ stage: test
+ script: bundle exec rspec
+
+staging:
+ variables:
+ ENVIRONMENT: staging
+ stage: deploy
+ trigger: my/deployment
+```
+
+The `ENVIRONMENT` variable will be passed to every job defined in a downstream
+pipeline. It will be available as an environment variable when GitLab Runner picks a job.
+
+In the following configuration, the `MY_VARIABLE` variable will be passed to the downstream pipeline
+that is created when the `trigger-downstream` job is queued. This is because `trigger-downstream`
+job inherits variables declared in global variables blocks, and then we pass these variables to a downstream pipeline.
+
+```yaml
+variables:
+ MY_VARIABLE: my-value
+
+trigger-downstream:
+ variables:
+ ENVIRONMENT: something
+ trigger: my/project
+```
+
+You might want to pass some information about the upstream pipeline using, for
+example, predefined variables. In order to do that, you can use interpolation
+to pass any variable. For example:
+
+```yaml
+downstream-job:
+ variables:
+ UPSTREAM_BRANCH: $CI_COMMIT_REF_NAME
+ trigger: my/project
+```
+
+In this scenario, the `UPSTREAM_BRANCH` variable with a value related to the
+upstream pipeline will be passed to the `downstream-job` job, and will be available
+within the context of all downstream builds.
+
+### Limitations
+
+Because bridge jobs are a little different to regular jobs, it is not
+possible to use exactly the same configuration syntax here, as one would
+normally do when defining a regular job that will be picked by a runner.
+
+Some features are not implemented yet. For example, support for environments.
+
+[Configuration keywords](yaml/README.md) available for bridge jobs are:
+
+- `trigger` (to define a downstream pipeline trigger)
+- `stage`
+- `allow_failure`
+- `only` and `except`
+- `when`
+- `extends`
diff --git a/doc/ci/pipelines.md b/doc/ci/pipelines.md
index 2ffa3d4edc7..1ad3d516df9 100644
--- a/doc/ci/pipelines.md
+++ b/doc/ci/pipelines.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# Creating and using CI/CD pipelines
> Introduced in GitLab 8.8.
@@ -19,7 +23,7 @@ If all the jobs in a stage:
- Fail, the next stage is not (usually) executed and the pipeline ends early.
NOTE: **Note:**
-If you have a [mirrored repository that GitLab pulls from](https://docs.gitlab.com/ee/workflow/repository_mirroring.html#pulling-from-a-remote-repository-starter),
+If you have a [mirrored repository that GitLab pulls from](../workflow/repository_mirroring.md#pulling-from-a-remote-repository-starter),
you may need to enable pipeline triggering in your project's
**Settings > Repository > Pull from a remote repository > Trigger pipelines for mirror updates**.
@@ -220,7 +224,7 @@ For information on adding pipeline badges to projects, see [Pipeline badges](../
Pipelines for different projects can be combined and visualized together.
-For more information, see [Multi-project pipelines](https://docs.gitlab.com/ee/ci/multi_project_pipelines.html).
+For more information, see [Multi-project pipelines](multi_project_pipelines.md).
## Working with pipelines
@@ -327,6 +331,19 @@ GitLab provides API endpoints to:
- [Triggering pipelines through the API](triggers/README.md).
- [Pipeline triggers API](../api/pipeline_triggers.md).
+### Start multiple manual actions in a stage
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27188) in GitLab 11.11.
+
+Multiple manual actions in a single stage can be started at the same time using the "Play all manual" button.
+Once the user clicks this button, each individual manual action will be triggered and refreshed
+to an updated status.
+
+This functionality is only available:
+
+- For users with at least Developer access.
+- If the the stage contains [manual actions](#manual-actions-from-pipeline-graphs).
+
## Security on protected branches
A strict security model is enforced when pipelines are executed on
diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md
index 65886400c64..11bcfd5dc2c 100644
--- a/doc/ci/quick_start/README.md
+++ b/doc/ci/quick_start/README.md
@@ -1,9 +1,18 @@
+---
+type: reference
+---
+
# Getting started with GitLab CI/CD
->**Note:** Starting from version 8.0, GitLab [Continuous Integration][ci] (CI)
+NOTE: **Note:**
+Starting from version 8.0, GitLab [Continuous Integration][ci] (CI)
is fully integrated into GitLab itself and is [enabled] by default on all
projects.
+NOTE: **Note:**
+Please keep in mind that only project Maintainers and Admin users have
+the permissions to access a project's settings.
+
GitLab offers a [continuous integration][ci] service. If you
[add a `.gitlab-ci.yml` file][yaml] to the root directory of your repository,
and configure your GitLab project to use a [Runner], then each commit or
@@ -35,11 +44,12 @@ project's **Pipelines** page.
---
-This guide assumes that you:
+This guide assumes that you have:
-- have a working GitLab instance of version 8.0+r or are using
- [GitLab.com](https://gitlab.com)
-- have a project in GitLab that you would like to use CI for
+- A working GitLab instance of version 8.0+r or are using
+ [GitLab.com](https://gitlab.com).
+- A project in GitLab that you would like to use CI for.
+- Maintainer or owner access to the project
Let's break it down to pieces and work on solving the GitLab CI puzzle.
@@ -73,6 +83,8 @@ You need to create a file named `.gitlab-ci.yml` in the root directory of your
repository. Below is an example for a Ruby on Rails project.
```yaml
+image: "ruby:2.5"
+
before_script:
- apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- ruby -v
@@ -127,7 +139,7 @@ Now if you go to the **Pipelines** page you will see that the pipeline is
pending.
NOTE: **Note:**
-If you have a [mirrored repository where GitLab pulls from](https://docs.gitlab.com/ee/workflow/repository_mirroring.html#pulling-from-a-remote-repository-starter),
+If you have a [mirrored repository where GitLab pulls from](../../workflow/repository_mirroring.md#pulling-from-a-remote-repository-starter),
you may need to enable pipeline triggering in your project's
**Settings > Repository > Pull from a remote repository > Trigger pipelines for mirror updates**.
diff --git a/doc/ci/review_apps/index.md b/doc/ci/review_apps/index.md
index 1a71c5fd258..7b039fe6654 100644
--- a/doc/ci/review_apps/index.md
+++ b/doc/ci/review_apps/index.md
@@ -1,9 +1,13 @@
+---
+type: reference
+---
+
# Review Apps
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/21971) in GitLab 8.12. Further additions were made in GitLab 8.13 and 8.14.
> - Inspired by [Heroku's Review Apps](https://devcenter.heroku.com/articles/github-integration-review-apps), which itself was inspired by [Fourchette](https://github.com/rainforestapp/fourchette).
-Review Apps are a collaboration tool that takes the hard work out of providing an environment to showcase product changes.
+Review Apps is a collaboration tool that takes the hard work out of providing an environment to showcase product changes.
## Introduction
@@ -18,7 +22,7 @@ Review Apps:
In the above example:
-- A Review App is built every time a commit is pushed to`topic branch`.
+- A Review App is built every time a commit is pushed to `topic branch`.
- The reviewer fails two reviews before passing the third review.
- Once the review as passed, `topic branch` is merged into `master` where it's deploy to staging.
- After been approved in staging, the changes that were merged into `master` are deployed in to production.
diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md
index ce55b231666..b089229ab58 100644
--- a/doc/ci/runners/README.md
+++ b/doc/ci/runners/README.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# Configuring GitLab Runners
In GitLab CI, Runners run the code defined in [`.gitlab-ci.yml`](../yaml/README.md).
diff --git a/doc/ci/runners/shared_to_specific_admin.png b/doc/ci/runners/shared_to_specific_admin.png
deleted file mode 100644
index 8f4010a5849..00000000000
--- a/doc/ci/runners/shared_to_specific_admin.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/services/README.md b/doc/ci/services/README.md
index 2eda5d23976..7fe12eb53e7 100644
--- a/doc/ci/services/README.md
+++ b/doc/ci/services/README.md
@@ -1,13 +1,18 @@
---
comments: false
+type: index
---
-# GitLab CI Services
+# GitLab CI services examples
-GitLab CI uses the `services` keyword to define what docker containers should
-be linked with your base image. Below is a list of examples you may use.
+The [`services`](../docker/using_docker_images.md#what-is-a-service)
+keyword defines a Docker image that runs during a `job` linked to the
+Docker image that the image keyword defines. This allows you to access
+the service image during build time.
+
+The service image can run any application, but the most common use
+case is to run a database container, for example:
- [Using MySQL](mysql.md)
- [Using PostgreSQL](postgres.md)
- [Using Redis](redis.md)
-- [Using Other Services](../docker/using_docker_images.md#what-is-a-service)
diff --git a/doc/ci/services/mysql.md b/doc/ci/services/mysql.md
index 2902c30c7c0..697452cee83 100644
--- a/doc/ci/services/mysql.md
+++ b/doc/ci/services/mysql.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# Using MySQL
As many applications depend on MySQL as their database, you will eventually
@@ -17,8 +21,8 @@ services:
variables:
# Configure mysql environment variables (https://hub.docker.com/_/mysql/)
- MYSQL_DATABASE: el_duderino
- MYSQL_ROOT_PASSWORD: mysql_strong_password
+ MYSQL_DATABASE: "<your_mysql_database>"
+ MYSQL_ROOT_PASSWORD: "<your_mysql_password>"
```
And then configure your application to use the database, for example:
@@ -26,18 +30,18 @@ And then configure your application to use the database, for example:
```yaml
Host: mysql
User: root
-Password: mysql_strong_password
-Database: el_duderino
+Password: <your_mysql_password>
+Database: <your_mysql_database>
```
If you are wondering why we used `mysql` for the `Host`, read more at
[How services are linked to the job](../docker/using_docker_images.md#how-services-are-linked-to-the-job).
-You can also use any other docker image available on [Docker Hub][hub-mysql].
+You can also use any other docker image available on [Docker Hub](https://hub.docker.com/_/mysql/).
For example, to use MySQL 5.5 the service becomes `mysql:5.5`.
The `mysql` image can accept some environment variables. For more details
-check the documentation on [Docker Hub][hub-mysql].
+check the documentation on [Docker Hub](https://hub.docker.com/_/mysql/).
## Use MySQL with the Shell executor
@@ -74,13 +78,13 @@ mysql> CREATE USER 'runner'@'localhost' IDENTIFIED BY '$password';
Create the database:
```bash
-mysql> CREATE DATABASE IF NOT EXISTS `el_duderino` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`;
+mysql> CREATE DATABASE IF NOT EXISTS `<your_mysql_database>` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`;
```
Grant the necessary permissions on the database:
```bash
-mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, CREATE TEMPORARY TABLES, DROP, INDEX, ALTER, LOCK TABLES ON `el_duderino`.* TO 'runner'@'localhost';
+mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, CREATE TEMPORARY TABLES, DROP, INDEX, ALTER, LOCK TABLES ON `<your_mysql_database>`.* TO 'runner'@'localhost';
```
If all went well you can now quit the database session:
@@ -93,7 +97,7 @@ Now, try to connect to the newly created database to check that everything is
in place:
```bash
-mysql -u runner -p -D el_duderino
+mysql -u runner -p -D <your_mysql_database>
```
As a final step, configure your application to use the database, for example:
@@ -102,17 +106,14 @@ As a final step, configure your application to use the database, for example:
Host: localhost
User: runner
Password: $password
-Database: el_duderino
+Database: <your_mysql_database>
```
## Example project
-We have set up an [Example MySQL Project][mysql-example-repo] for your
+We have set up an [Example MySQL Project](https://gitlab.com/gitlab-examples/mysql) for your
convenience that runs on [GitLab.com](https://gitlab.com) using our publicly
available [shared runners](../runners/README.md).
-Want to hack on it? Simply fork it, commit and push your changes. Within a few
+Want to hack on it? Simply fork it, commit and push your changes. Within a few
moments the changes will be picked by a public runner and the job will begin.
-
-[hub-mysql]: https://hub.docker.com/_/mysql/
-[mysql-example-repo]: https://gitlab.com/gitlab-examples/mysql
diff --git a/doc/ci/services/postgres.md b/doc/ci/services/postgres.md
index 2e6d7ae94d2..211eea26eb0 100644
--- a/doc/ci/services/postgres.md
+++ b/doc/ci/services/postgres.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# Using PostgreSQL
As many applications depend on PostgreSQL as their database, you will
diff --git a/doc/ci/services/redis.md b/doc/ci/services/redis.md
index 36f71427ae7..8b227154b06 100644
--- a/doc/ci/services/redis.md
+++ b/doc/ci/services/redis.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# Using Redis
As many applications depend on Redis as their key-value store, you will
diff --git a/doc/ci/ssh_keys/README.md b/doc/ci/ssh_keys/README.md
index 9ed1ec5aa5c..69591ed605c 100644
--- a/doc/ci/ssh_keys/README.md
+++ b/doc/ci/ssh_keys/README.md
@@ -1,5 +1,6 @@
---
last_updated: 2017-12-13
+type: tutorial
---
# Using SSH keys with GitLab CI/CD
diff --git a/doc/ci/triggers/README.md b/doc/ci/triggers/README.md
index 0e72bdddee7..04c541fefe7 100644
--- a/doc/ci/triggers/README.md
+++ b/doc/ci/triggers/README.md
@@ -1,3 +1,7 @@
+---
+type: tutorial
+---
+
# Triggering pipelines through the API
> **Notes**:
@@ -23,6 +27,63 @@ attackers can impersonate the user that exposed their trigger token publicly in
their `.gitlab-ci.yml` file. Use [variables](../variables/README.md#gitlab-cicd-environment-variables)
to protect trigger tokens.
+### CI job token
+
+You can use the `CI_JOB_TOKEN` [variable][predef] (used to authenticate
+with the [GitLab Container Registry][registry]) in the following cases.
+
+#### When used with multi-project pipelines **[PREMIUM]**
+
+> **Note**:
+The use of `CI_JOB_TOKEN` for multi-project pipelines was [introduced][ee-2017]
+in [GitLab Premium][ee] 9.3.
+
+This way of triggering can only be used when invoked inside `.gitlab-ci.yml`,
+and it creates a dependent pipeline relation visible on the
+[pipeline graph](../multi_project_pipelines.md#overview). For example:
+
+```yaml
+build_docs:
+ stage: deploy
+ script:
+ - curl --request POST --form "token=$CI_JOB_TOKEN" --form ref=master https://gitlab.example.com/api/v4/projects/9/trigger/pipeline
+ only:
+ - tags
+```
+
+Pipelines triggered that way also expose a special variable:
+`CI_PIPELINE_SOURCE=pipeline`.
+
+Read more about the [pipelines trigger API][trigapi].
+
+#### When a pipeline depends on the artifacts of another pipeline **[PREMIUM]**
+
+> The use of `CI_JOB_TOKEN` in the artifacts download API was [introduced][ee-2346]
+ in [GitLab Premium][ee] 9.5.
+
+With the introduction of dependencies between different projects, one of
+them may need to access artifacts created by a previous one. This process
+must be granted for authorized accesses, and it can be done using the
+`CI_JOB_TOKEN` variable that identifies a specific job. For example:
+
+```yaml
+build_submodule:
+ image: debian
+ stage: test
+ script:
+ - apt update && apt install -y unzip
+ - curl --location --output artifacts.zip "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/download?job=test&job_token=$CI_JOB_TOKEN"
+ - unzip artifacts.zip
+ only:
+ - tags
+```
+
+This allows you to use that for multi-project pipelines and download artifacts
+from any project to which you have access as this follows the same principles
+with the [permission model][permissions].
+
+Read more about the [jobs API](../../api/jobs.md#download-the-artifacts-archive).
+
## Adding a new trigger
You can add a new trigger by going to your project's
@@ -225,7 +286,10 @@ removed with one of the future versions of GitLab. You are advised to
[take ownership](#taking-ownership-of-a-trigger) of any legacy triggers.
[ee-2017]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2017
+[ee-2346]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2346
[ee]: https://about.gitlab.com/pricing/
[variables]: ../variables/README.md
[predef]: ../variables/README.md#predefined-environment-variables
[registry]: ../../user/project/container_registry.md
+[permissions]: ../../user/permissions.md#job-permissions
+[trigapi]: ../../api/pipeline_triggers.md
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 61d1a904f76..df455857dee 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -1,5 +1,6 @@
---
table_display_block: true
+type: reference
---
# GitLab CI/CD environment variables
@@ -52,6 +53,53 @@ or directly in the `.gitlab-ci.yml` file and reuse them as you wish.
That can be very powerful as it can be used for scripting without
the need to specify the value itself.
+#### Variable types
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/46806) in GitLab 11.11.
+
+There are two types of variables supported by GitLab:
+
+- "Variable": the Runner will create an environment variable named same as the variable key and set its value to the variable value.
+- "File": the Runner will write the variable value to a temporary file and set the path to this file as the value of an environment variable named same as the variable key.
+
+Many tools (like [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html) and [kubectl](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/#the-kubeconfig-environment-variable)) provide the ability to customise configuration using files by either providing the file path as a command line argument or an environment variable. Prior to the introduction of variable types, the common pattern was to use the value of a CI variable, save it in a file, and then use the newly created file in your script:
+
+```bash
+# Save the content of variable in a file
+echo "$KUBE_CA_PEM" > "$(pwd)/kube.ca.pem"
+ # Use the newly created file
+kubectl config set-cluster e2e --server="$KUBE_URL" --certificate-authority="$(pwd)/kube.ca.pem"
+```
+
+This can be simplified by creating a variable of type "File" and using it directly. For example, let's say we have the following variables.
+
+![CI/CD settings - variable types usage example](img/variable_types_usage_example.png)
+
+We can then call them from `.gitlab-ci.yml` like this:
+
+```bash
+kubectl config set-cluster e2e --server="$KUBE_URL" --certificate-authority="$KUBE_CA_PEM"
+```
+
+Variable types can be set via the [UI](#via-the-ui) or the [API](../../api/project_level_variables.md#create-variable), but not in `.gitlab-ci.yml`.
+
+#### Masked variables
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/13784) in GitLab 11.10
+
+Variables can be created as masked variables.
+This means that the value of the variable will be hidden in job logs,
+though it must match certain requirements to do so:
+
+- The value must be in a single line.
+- The value must only consist of characters from the Base64 alphabet, defined in [RFC4648](https://tools.ietf.org/html/rfc4648).
+- The value must be at least 8 characters long.
+- The value must not use variables.
+
+If the value does not meet the requirements above, then the CI variable will fail to save.
+In order to save, either alter the value to meet the masking requirements
+or disable **Masked** for the variable.
+
## Getting started
To get started with environment variables in the scope of GitLab
@@ -104,7 +152,10 @@ let's say you want to output `HELLO WORLD` for a `TEST` variable.
You can either set the variable directly in the `.gitlab-ci.yml`
file or through the UI.
-#### Via [`.gitlab-ci.yml`](../yaml/README.md#variables)
+#### Via `.gitlab-ci.yml`
+
+To create a new custom `env_var` variable via [`.gitlab-ci.yml`](../yaml/README.md#variables), define their variable/value pair under
+`variables`:
```yaml
variables:
@@ -116,11 +167,13 @@ For a deeper look into them, see [`.gitlab-ci.yml` defined variables](#gitlab-ci
#### Via the UI
From the UI, navigate to your project's **Settings > CI/CD** and
-expand **Environment variables**. Create a new variable by naming
-it in the field **Input variable key**, and define its value in the
+expand **Variables**. Create a new variable by choosing its **type**, naming
+it in the field **Input variable key**, and defining its value in the
**Input variable value** field:
-![CI/CD settings - new variable](img/new_custom_variable_example.png)
+![CI/CD settings - new variable](img/new_custom_variables_example.png)
+
+You'll also see the option to mask and/or protect your variables.
Once you've set the variables, call them from the `.gitlab-ci.yml` file:
@@ -129,19 +182,14 @@ test_variable:
stage: test
script:
- echo $CI_JOB_STAGE # calls a predefined variable
- - echo $TEST # calls a custom variable
+ - echo $TEST # calls a custom variable of type `env_var`
+ - echo $GREETING # calls a custom variable of type `file` that contains the path to the temp file
+ - cat $GREETING # the temp file itself contains the variable value
```
The output will be:
-![Output custom variable](img/custom_variable_output.png)
-
-CAUTION: **Important:**
-Be aware that variables are not masked, and their values can be shown
-in the job logs if explicitly asked to do so. If your project is public or
-internal, you can set the pipelines private from your [project's Pipelines
-settings](../../user/project/pipelines/settings.md#visibility-of-pipelines).
-Follow the discussion in issue [#13784][ce-13784] for masking the variables.
+![Output custom variable](img/custom_variables_output.png)
### Syntax of environment variables in job scripts
@@ -288,7 +336,7 @@ use for storing things like passwords, SSH keys, and credentials.
Group-level variables can be added by:
1. Navigating to your group's **Settings > CI/CD** page.
-1. Inputing variable keys and values in the **Environment variables** section.
+1. Inputing variable types, keys, and values in the **Variables** section.
Any variables of [subgroups](../../user/group/subgroups/index.md) will be inherited recursively.
Once you set them, they will be available for all subsequent pipelines.
@@ -339,6 +387,13 @@ Protected variables can be added by going to your project's
Once you set them, they will be available for all subsequent pipelines.
+### Limiting environment scopes of environment variables **[PREMIUM]**
+
+You can limit the environment scope of a variable by
+[defining which environments][envs] it can be available for.
+
+To learn more about about scoping environments, see [Scoping environments with specs](../environments.md#scoping-environments-with-specs-premium).
+
### Deployment environment variables
> Introduced in GitLab 8.15.
@@ -379,8 +434,7 @@ For instance, suppose you added a
[custom variable `$TEST`](#creating-a-custom-environment-variable)
as exemplified above and you want to override it in a manual pipeline.
Navigate to your project's **CI/CD > Pipelines** and click **Run pipeline**.
-Choose the branch you want to run the pipeline for, then add a new variable
-pair through the UI:
+Choose the branch you want to run the pipeline for, then add a new variable through the UI:
![Override variable value](img/override_variable_manual_pipeline.png)
@@ -426,7 +480,9 @@ Below you can find supported syntax reference:
> Example: `$VARIABLE == "some value"`
- You can use equality operator `==` to compare a variable content to a
+ > Example: `$VARIABLE != "some value"` _(added in 11.11)_
+
+ You can use equality operator `==` or `!=` to compare a variable content to a
string. We support both, double quotes and single quotes to define a string
value, so both `$VARIABLE == "some value"` and `$VARIABLE == 'some value'`
are supported. `"some value" == $VARIABLE` is correct too.
@@ -435,22 +491,29 @@ Below you can find supported syntax reference:
> Example: `$VARIABLE == null`
+ > Example: `$VARIABLE != null` _(added in 11.11)_
+
It sometimes happens that you want to check whether a variable is defined
or not. To do that, you can compare a variable to `null` keyword, like
`$VARIABLE == null`. This expression is going to evaluate to truth if
- variable is not defined.
+ variable is not defined when `==` is used, or to falsey if `!=` is used.
1. Checking for an empty variable
> Example: `$VARIABLE == ""`
+ > Example: `$VARIABLE != ""` _(added in 11.11)_
+
If you want to check whether a variable is defined, but is empty, you can
- simply compare it against an empty string, like `$VAR == ''`.
+ simply compare it against an empty string, like `$VAR == ''` or non-empty
+ string `$VARIABLE != ""`.
1. Comparing two variables
> Example: `$VARIABLE_1 == $VARIABLE_2`
+ > Example: `$VARIABLE_1 != $VARIABLE_2` _(added in 11.11)_
+
It is possible to compare two variables. This is going to compare values
of these variables.
@@ -469,12 +532,28 @@ Below you can find supported syntax reference:
> Example: `$VARIABLE =~ /^content.*/`
+ > Example: `$VARIABLE_1 !~ /^content.*/` _(added in 11.11)_
+
It is possible perform pattern matching against a variable and regular
- expression. Expression like this evaluates to truth if matches are found.
+ expression. Expression like this evaluates to truth if matches are found
+ when using `=~`. It evaluates to truth if matches are not found when `!~` is used.
Pattern matching is case-sensitive by default. Use `i` flag modifier, like
`/pattern/i` to make a pattern case-insensitive.
+1. Conjunction / Disjunction
+
+ > Example: `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 == "something"`
+
+ > Example: `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 =~ /thing$/ && $VARIABLE3`
+
+ > Example: `$VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/ && $VARIABLE3`
+
+ It is possible to join multiple conditions using `&&` or `||`. Any of the otherwise
+ supported syntax may be used in a conjunctive or disjunctive statement.
+ Precedence of operators follows standard Ruby 2.5 operation
+ [precedence](https://ruby-doc.org/core-2.5.0/doc/syntax/precedence_rdoc.html).
+
## Debug tracing
> Introduced in GitLab Runner 1.7.
@@ -539,8 +618,8 @@ $'\''git'\'' "checkout" "-f" "-q" "dd648b2e48ce6518303b0bb580b2ee32fadaf045"
Running on runner-8a2f473d-project-1796893-concurrent-0 via runner-8a2f473d-machine-1480971377-317a7d0f-digital-ocean-4gb...
++ export CI=true
++ CI=true
-++ export CI_API_V4_API_URL=https://example.com:3000/api/v4
-++ CI_API_V4_API_URL=https://example.com:3000/api/v4
+++ export CI_API_V4_URL=https://example.com:3000/api/v4
+++ CI_API_V4_URL=https://example.com:3000/api/v4
++ export CI_DEBUG_TRACE=false
++ CI_DEBUG_TRACE=false
++ export CI_COMMIT_SHA=dd648b2e48ce6518303b0bb580b2ee32fadaf045
@@ -579,8 +658,8 @@ Running on runner-8a2f473d-project-1796893-concurrent-0 via runner-8a2f473d-mach
++ GITLAB_CI=true
++ export CI=true
++ CI=true
-++ export CI_API_V4_API_URL=https://example.com:3000/api/v4
-++ CI_API_V4_API_URL=https://example.com:3000/api/v4
+++ export CI_API_V4_URL=https://example.com:3000/api/v4
+++ CI_API_V4_URL=https://example.com:3000/api/v4
++ export GITLAB_CI=true
++ GITLAB_CI=true
++ export CI_JOB_ID=7046507
@@ -645,12 +724,13 @@ MIIFQzCCBCugAwIBAgIRAL/ElDjuf15xwja1ZnCocWAwDQYJKoZIhvcNAQELBQAw'
```
[ce-13784]: https://gitlab.com/gitlab-org/gitlab-ce/issues/13784 "Simple protection of CI variables"
-[eep]: https://about.gitlab.com/pricing/ "Available only in GitLab Premium"
[envs]: ../environments.md
[protected branches]: ../../user/project/protected_branches.md
[protected tags]: ../../user/project/protected_tags.md
[shellexecutors]: https://docs.gitlab.com/runner/executors/
[triggered]: ../triggers/README.md
+[trigger-job-token]: ../triggers/README.md#ci-job-token
[gitlab-deploy-token]: ../../user/project/deploy_tokens/index.md#gitlab-deploy-token
[registry]: ../../user/project/container_registry.md
[dependent-repositories]: ../../user/project/new_ci_build_permissions_model.md#dependent-repositories
+[get-job-artifacts]: ../../api/jobs.html#get-job-artifacts
diff --git a/doc/ci/variables/deprecated_variables.md b/doc/ci/variables/deprecated_variables.md
index 2642c9b0eb4..cdca5bf27fc 100644
--- a/doc/ci/variables/deprecated_variables.md
+++ b/doc/ci/variables/deprecated_variables.md
@@ -1,5 +1,12 @@
+---
+type: reference
+---
+
# Deprecated GitLab CI/CD variables
+Read through this document to learn what predefined variables
+were deprecated and their new references.
+
## GitLab 9.0 renamed variables
To follow conventions of naming across GitLab, and to further move away from the
diff --git a/doc/ci/variables/img/custom_variable_output.png b/doc/ci/variables/img/custom_variable_output.png
deleted file mode 100644
index 50f3bceff9a..00000000000
--- a/doc/ci/variables/img/custom_variable_output.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/variables/img/custom_variables_output.png b/doc/ci/variables/img/custom_variables_output.png
new file mode 100644
index 00000000000..29f5c63b3d9
--- /dev/null
+++ b/doc/ci/variables/img/custom_variables_output.png
Binary files differ
diff --git a/doc/ci/variables/img/new_custom_variable_example.png b/doc/ci/variables/img/new_custom_variable_example.png
deleted file mode 100644
index d169c5f1806..00000000000
--- a/doc/ci/variables/img/new_custom_variable_example.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/variables/img/new_custom_variables_example.png b/doc/ci/variables/img/new_custom_variables_example.png
new file mode 100644
index 00000000000..efe104efe4c
--- /dev/null
+++ b/doc/ci/variables/img/new_custom_variables_example.png
Binary files differ
diff --git a/doc/ci/variables/img/override_variable_manual_pipeline.png b/doc/ci/variables/img/override_variable_manual_pipeline.png
index 3bcd354e096..3c8c59720cf 100644
--- a/doc/ci/variables/img/override_variable_manual_pipeline.png
+++ b/doc/ci/variables/img/override_variable_manual_pipeline.png
Binary files differ
diff --git a/doc/ci/variables/img/variable_types_usage_example.png b/doc/ci/variables/img/variable_types_usage_example.png
new file mode 100644
index 00000000000..0e8bde891fe
--- /dev/null
+++ b/doc/ci/variables/img/variable_types_usage_example.png
Binary files differ
diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md
index 846c539daab..4655eec51de 100644
--- a/doc/ci/variables/predefined_variables.md
+++ b/doc/ci/variables/predefined_variables.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# Predefined environment variables reference
For an introduction on this subject, read through the
@@ -49,23 +53,23 @@ future GitLab releases.**
| `CI_JOB_STAGE` | 9.0 | 0.5 | The name of the stage as defined in `.gitlab-ci.yml` |
| `CI_JOB_TOKEN` | 9.0 | 1.2 | Token used for authenticating with the [GitLab Container Registry][registry] and downloading [dependent repositories][dependent-repositories] |
| `CI_JOB_URL` | 11.1 | 0.5 | Job details URL |
-| `CI_MERGE_REQUEST_ID` | 11.6 | all | The ID of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
-| `CI_MERGE_REQUEST_IID` | 11.6 | all | The IID of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
-| `CI_MERGE_REQUEST_PROJECT_ID` | 11.6 | all | The ID of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
-| `CI_MERGE_REQUEST_PROJECT_PATH` | 11.6 | all | The path of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) (e.g. `namespace/awesome-project`) |
-| `CI_MERGE_REQUEST_PROJECT_URL` | 11.6 | all | The URL of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) (e.g. `http://192.168.10.15:3000/namespace/awesome-project`) |
-| `CI_MERGE_REQUEST_REF_PATH` | 11.6 | all | The ref path of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). (e.g. `refs/merge-requests/1/head`) |
-| `CI_MERGE_REQUEST_SOURCE_BRANCH_NAME` | 11.6 | all | The source branch name of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
-| `CI_MERGE_REQUEST_SOURCE_BRANCH_SHA` | 11.9 | all | The HEAD sha of the source branch of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
-| `CI_MERGE_REQUEST_SOURCE_PROJECT_ID` | 11.6 | all | The ID of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
-| `CI_MERGE_REQUEST_SOURCE_PROJECT_PATH` | 11.6 | all | The path of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
-| `CI_MERGE_REQUEST_SOURCE_PROJECT_URL` | 11.6 | all | The URL of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
-| `CI_MERGE_REQUEST_TARGET_BRANCH_NAME` | 11.6 | all | The target branch name of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
-| `CI_MERGE_REQUEST_TARGET_BRANCH_SHA` | 11.9 | all | The HEAD sha of the target branch of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
-| `CI_MERGE_REQUEST_TITLE` | 11.9 | all | The title of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
-| `CI_MERGE_REQUEST_ASSIGNEES` | 11.9 | all | Comma-separated list of usernames of assignees for the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). [Multiple assignees for merge requests](https://gitlab.com/gitlab-org/gitlab-ee/issues/2004) is scheduled for a future release |
-| `CI_MERGE_REQUEST_MILESTONE` | 11.9 | all | The milestone title of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
-| `CI_MERGE_REQUEST_LABELS` | 11.9 | all | Comma-separated label names of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) |
+| `CI_MERGE_REQUEST_ID` | 11.6 | all | The ID of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` is used and the merge request is created. |
+| `CI_MERGE_REQUEST_IID` | 11.6 | all | The IID of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` is used and the merge request is created. |
+| `CI_MERGE_REQUEST_PROJECT_ID` | 11.6 | all | The ID of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` is used and the merge request is created. |
+| `CI_MERGE_REQUEST_PROJECT_PATH` | 11.6 | all | The path of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) (e.g. `namespace/awesome-project`). Available only if `only: [merge_requests]` is used and the merge request is created. |
+| `CI_MERGE_REQUEST_PROJECT_URL` | 11.6 | all | The URL of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) (e.g. `http://192.168.10.15:3000/namespace/awesome-project`). Available only if `only: [merge_requests]` is used and the merge request is created. |
+| `CI_MERGE_REQUEST_REF_PATH` | 11.6 | all | The ref path of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). (e.g. `refs/merge-requests/1/head`). Available only if `only: [merge_requests]` is used and the merge request is created. |
+| `CI_MERGE_REQUEST_SOURCE_BRANCH_NAME` | 11.6 | all | The source branch name of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` is used and the merge request is created. |
+| `CI_MERGE_REQUEST_SOURCE_BRANCH_SHA` | 11.9 | all | The HEAD sha of the source branch of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` is used and the merge request is created. |
+| `CI_MERGE_REQUEST_SOURCE_PROJECT_ID` | 11.6 | all | The ID of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` is used and the merge request is created. |
+| `CI_MERGE_REQUEST_SOURCE_PROJECT_PATH` | 11.6 | all | The path of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` is used and the merge request is created. |
+| `CI_MERGE_REQUEST_SOURCE_PROJECT_URL` | 11.6 | all | The URL of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` is used and the merge request is created. |
+| `CI_MERGE_REQUEST_TARGET_BRANCH_NAME` | 11.6 | all | The target branch name of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` is used and the merge request is created. |
+| `CI_MERGE_REQUEST_TARGET_BRANCH_SHA` | 11.9 | all | The HEAD sha of the target branch of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` is used and the merge request is created. |
+| `CI_MERGE_REQUEST_TITLE` | 11.9 | all | The title of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` is used and the merge request is created. |
+| `CI_MERGE_REQUEST_ASSIGNEES` | 11.9 | all | Comma-separated list of username(s) of assignee(s) for the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` is used and the merge request is created. |
+| `CI_MERGE_REQUEST_MILESTONE` | 11.9 | all | The milestone title of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` is used and the merge request is created. |
+| `CI_MERGE_REQUEST_LABELS` | 11.9 | all | Comma-separated label names of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` is used and the merge request is created. |
| `CI_NODE_INDEX` | 11.5 | all | Index of the job in the job set. If the job is not parallelized, this variable is not set. |
| `CI_NODE_TOTAL` | 11.5 | all | Total number of instances of this job running in parallel. If the job is not parallelized, this variable is set to `1`. |
| `CI_API_V4_URL` | 11.7 | all | The GitLab API v4 root URL |
@@ -84,6 +88,7 @@ future GitLab releases.**
| `CI_PROJECT_PATH_SLUG` | 9.3 | all | `$CI_PROJECT_PATH` lowercased and with everything except `0-9` and `a-z` replaced with `-`. Use in URLs and domain names. |
| `CI_PROJECT_URL` | 8.10 | 0.5 | The HTTP(S) address to access project |
| `CI_PROJECT_VISIBILITY` | 10.3 | all | The project visibility (internal, private, public) |
+| `CI_COMMIT_REF_PROTECTED` | 11.11 | all | If the job is running on a protected branch |
| `CI_REGISTRY` | 8.10 | 0.5 | If the Container Registry is enabled it returns the address of GitLab's Container Registry |
| `CI_REGISTRY_IMAGE` | 8.10 | 0.5 | If the Container Registry is enabled for the project it returns the address of the registry tied to the specific project |
| `CI_REGISTRY_PASSWORD` | 9.0 | all | The password to use to push containers to the GitLab Container Registry |
@@ -111,3 +116,7 @@ future GitLab releases.**
| `GITLAB_USER_NAME` | 10.0 | all | The real name of the user who started the job |
| `RESTORE_CACHE_ATTEMPTS` | 8.15 | 1.9 | Number of attempts to restore the cache running a job |
| `GITLAB_FEATURES` | 10.6 | all | The comma separated list of licensed features available for your instance and plan |
+
+[gitlab-deploy-token]: ../../user/project/deploy_tokens/index.md#gitlab-deploy-token
+[registry]: ../../user/project/container_registry.md
+[dependent-repositories]: ../../user/project/new_ci_build_permissions_model.md#dependent-repositories
diff --git a/doc/ci/variables/where_variables_can_be_used.md b/doc/ci/variables/where_variables_can_be_used.md
index 091ddcb0bae..7d3f39a8c19 100644
--- a/doc/ci/variables/where_variables_can_be_used.md
+++ b/doc/ci/variables/where_variables_can_be_used.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# Where variables can be used
As it's described in the [CI/CD variables](README.md) docs, you can
@@ -85,6 +89,14 @@ Supported:
- In `script`, it will work in the following lines of `script`.
- In `after_script`, it will work in following lines of `after_script`.
+Please notice the specific case of `after_script` scripts, that can:
+
+- Only use variables defined before the script within the same `after_script` section.
+- Not use variables defined in `before_script` and `script`.
+
+Both restrictions are caused by the fact, that `after_script` script is executed in a
+[separated shell context](https://docs.gitlab.com/ee/ci/yaml/README.html#before_script-and-after_script).
+
## Persisted variables
NOTE: **Note:**
@@ -112,3 +124,22 @@ They are:
- Not supported:
- For definitions where the ["Expansion place"](#gitlab-ciyml-file) is GitLab.
- In the `only` and `except` [variables expressions](README.md#environment-variables-expressions).
+
+## Variables with an environment scope
+
+Variables defined with an environment scope are supported. Given that
+there is a variable `$STAGING_SECRET` defined in a scope of
+`review/staging/*`, the following job that is using dynamic environments
+is going to be created, based on the matching variable expression:
+
+```yaml
+my-job:
+ stage: staging
+ environment:
+ name: review/$CI_JOB_STAGE/deploy
+ script:
+ - 'deploy staging'
+ only:
+ variables:
+ - $STAGING_SECRET == 'something'
+```
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 36a0bf10416..b3aa1bcfad2 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# GitLab CI/CD Pipeline Configuration Reference
GitLab CI/CD [pipelines](../pipelines.md) are configured using a YAML file called `.gitlab-ci.yml` within each project.
@@ -19,7 +23,7 @@ We have complete examples of configuring pipelines:
- To see a large `.gitlab-ci.yml` file used in an enterprise, see the [`.gitlab-ci.yml` file for `gitlab-ce`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab-ci.yml).
NOTE: **Note:**
-If you have a [mirrored repository where GitLab pulls from](https://docs.gitlab.com/ee/workflow/repository_mirroring.html#pulling-from-a-remote-repository-starter),
+If you have a [mirrored repository where GitLab pulls from](../../workflow/repository_mirroring.md#pulling-from-a-remote-repository-starter),
you may need to enable pipeline triggering in your project's
**Settings > Repository > Pull from a remote repository > Trigger pipelines for mirror updates**.
@@ -56,7 +60,7 @@ independently from each other.
Each instance of GitLab CI has an embedded debug tool called Lint, which validates the
content of your `.gitlab-ci.yml` files. You can find the Lint under the page `ci/lint` of your
-project namespace. For example, `http://gitlab.example.com/gitlab-org/project-123/-/ci/lint`.
+project namespace. For example, `https://gitlab.example.com/gitlab-org/project-123/-/ci/lint`.
### Unavailable names for jobs
@@ -101,14 +105,14 @@ The following table lists available parameters for jobs:
| [`when`](#when) | When to run job. Also available: `when:manual` and `when:delayed`. |
| [`environment`](#environment) | Name of an environment to which the job deploys. Also available: `environment:name`, `environment:url`, `environment:on_stop`, and `environment:action`. |
| [`cache`](#cache) | List of files that should be cached between subsequent runs. Also available: `cache:paths`, `cache:key`, `cache:untracked`, and `cache:policy`. |
-| [`artifacts`](#artifacts) | List of files and directories to attach to a job on success. Also available: `artifacts:paths`, `artifacts:name`, `artifacts:untracked`, `artifacts:when`, `artifacts:expire_in`, `artifacts:reports`, and `artifacts:reports:junit`.<br><br>In GitLab [Enterprise Edition](https://about.gitlab.com/pricing/), these are available: `artifacts:reports:codequality`, `artifacts:reports:sast`, `artifacts:reports:dependency_scanning`, `artifacts:reports:container_scanning`, `artifacts:reports:dast`, `artifacts:reports:license_management`, and `artifacts:reports:performance`. |
+| [`artifacts`](#artifacts) | List of files and directories to attach to a job on success. Also available: `artifacts:paths`, `artifacts:name`, `artifacts:untracked`, `artifacts:when`, `artifacts:expire_in`, `artifacts:reports`, and `artifacts:reports:junit`.<br><br>In GitLab [Enterprise Edition](https://about.gitlab.com/pricing/), these are available: `artifacts:reports:codequality`, `artifacts:reports:sast`, `artifacts:reports:dependency_scanning`, `artifacts:reports:container_scanning`, `artifacts:reports:dast`, `artifacts:reports:license_management`, `artifacts:reports:performance` and `artifacts:reports:metrics`. |
| [`dependencies`](#dependencies) | Other jobs that a job depends on so that you can pass artifacts between them. |
| [`coverage`](#coverage) | Code coverage settings for a given job. |
| [`retry`](#retry) | When and how many times a job can be auto-retried in case of a failure. |
| [`parallel`](#parallel) | How many instances of a job should be run in parallel. |
| [`trigger`](#trigger-premium) | Defines a downstream pipeline trigger. |
| [`include`](#include) | Allows this job to include external YAML files. Also available: `include:local`, `include:file`, `include:template`, and `include:remote`. |
-| [`extends`](#extends) | Configuration entry that this job is going to inherit from. |
+| [`extends`](#extends) | Configuration entries that this job is going to inherit from. |
| [`pages`](#pages) | Upload the result of a job to use with GitLab Pages. |
| [`variables`](#variables) | Define job variables on a job level. |
@@ -211,10 +215,20 @@ This can be an array or a multi-line string.
`after_script` is used to define the command that will be run after all
jobs, including failed ones. This has to be an array or a multi-line string.
-The `before_script` and the main `script` are concatenated and run in a single context/container.
-The `after_script` is run separately. The current working directory is set back to
-default. Depending on the executor, changes done outside of the working tree might
-not be visible, e.g. software installed in the `before_script`.
+Script specified in `before_script` is:
+
+- Concatenated with script specified in the main `script`. Job-level `before_script` definition
+ override global-level `before_script` definition when concatenated with `script` definition.
+- Executed together with main `script` script as one script in a single shell context.
+
+Script specified in `after_script`:
+
+- Have a current working directory set back to the default.
+- Is executed in a shell context separated from `before_script` and `script` scripts.
+- Because of separated context, cannot see changes done by scripts defined in `before_script` or `script` scripts:
+ - in shell - for example, command aliases and variables exported in `script` script,
+ - outside of the working tree (depending on the Runner executor) - for example, software installed
+ by a `before_script` or `script` script.
It's possible to overwrite the globally defined `before_script` and `after_script`
if you set it per-job:
@@ -337,6 +351,7 @@ In addition, `only` and `except` allow the use of special keywords:
| `triggers` | For pipelines created using a trigger token. |
| `web` | For pipelines created using **Run pipeline** button in GitLab UI (under your project's **Pipelines**). |
| `merge_requests` | When a merge request is created or updated (See [pipelines for merge requests](../merge_request_pipelines/index.md)). |
+| `chats` | For jobs created using a [GitLab ChatOps](../chatops/README.md) command. |
In the example below, `job` will run only for refs that start with `issue-`,
whereas all branches will be skipped:
@@ -385,17 +400,12 @@ job:
- branches@gitlab-org/gitlab-ce
except:
- master@gitlab-org/gitlab-ce
- - release/.*@gitlab-org/gitlab-ce
+ - /^release/.*$/@gitlab-org/gitlab-ce
```
The above example will run `job` for all branches on `gitlab-org/gitlab-ce`,
except `master` and those with names prefixed with `release/`.
-NOTE: **Note:**
-Because `@` is used to denote the beginning of a ref's repository path,
-matching a ref name containing the `@` character in a regular expression
-requires the use of the hex character code match `\x40`.
-
If a job does not have an `only` rule, `only: ['branches', 'tags']` is set by
default. If it doesn't have an `except` rule, it is empty.
@@ -414,6 +424,28 @@ job:
only: ['branches', 'tags']
```
+#### Regular expressions
+
+Because `@` is used to denote the beginning of a ref's repository path,
+matching a ref name containing the `@` character in a regular expression
+requires the use of the hex character code match `\x40`.
+
+Only the tag or branch name can be matched by a regular expression.
+The repository path, if given, is always matched literally.
+
+If a regular expression shall be used to match the tag or branch name,
+the entire ref name part of the pattern has to be a regular expression,
+and must be surrounded by `/`.
+(With regular expression flags appended after the closing `/`.)
+So `issue-/.*/` won't work to match all tag names or branch names
+that begin with `issue-`.
+
+TIP: **Tip**
+Use anchors `^` and `$` to avoid the regular expression
+matching only a substring of the tag name or branch name.
+For example, `/^issue-.*$/` is equivalent to `/^issue-/`,
+while just `/issue/` would also match a branch called `severe-issues`.
+
### Supported `only`/`except` regexp syntax
CAUTION: **Warning:**
@@ -1167,9 +1199,9 @@ skip the download step.
> - Job artifacts are only collected for successful jobs by default.
`artifacts` is used to specify a list of files and directories which should be
-attached to the job after success.
+attached to the job when it [succeeds, fails, or always](#artifactswhen).
-The artifacts will be sent to GitLab after the job finishes successfully and will
+The artifacts will be sent to GitLab after the job finishes and will
be available for download in the GitLab UI.
[Read more about artifacts](../../user/project/pipelines/job_artifacts.md).
@@ -1436,7 +1468,7 @@ combination thereof (`junit: [rspec.xml, test-results/TEST-*.xml]`).
> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
-The `codequality` report collects [CodeQuality issues](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html)
+The `codequality` report collects [CodeQuality issues](../../user/project/merge_requests/code_quality.md)
as artifacts.
The collected Code Quality report will be uploaded to GitLab as an artifact and will
@@ -1446,7 +1478,7 @@ be automatically shown in merge requests.
> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
-The `sast` report collects [SAST vulnerabilities](https://docs.gitlab.com/ee/user/project/merge_requests/sast.html)
+The `sast` report collects [SAST vulnerabilities](../../user/application_security/sast/index.md)
as artifacts.
The collected SAST report will be uploaded to GitLab as an artifact and will
@@ -1457,7 +1489,7 @@ dashboards.
> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
-The `dependency_scanning` report collects [Dependency Scanning vulnerabilities](https://docs.gitlab.com/ee/user/project/merge_requests/dependency_scanning.html)
+The `dependency_scanning` report collects [Dependency Scanning vulnerabilities](../../user/application_security/dependency_scanning/index.md)
as artifacts.
The collected Dependency Scanning report will be uploaded to GitLab as an artifact and will
@@ -1468,7 +1500,7 @@ dashboards.
> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
-The `container_scanning` report collects [Container Scanning vulnerabilities](https://docs.gitlab.com/ee/user/project/merge_requests/container_scanning.html)
+The `container_scanning` report collects [Container Scanning vulnerabilities](../../user/application_security/container_scanning/index.md)
as artifacts.
The collected Container Scanning report will be uploaded to GitLab as an artifact and will
@@ -1479,7 +1511,7 @@ dashboards.
> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
-The `dast` report collects [DAST vulnerabilities](https://docs.gitlab.com/ee/user/project/merge_requests/dast.html)
+The `dast` report collects [DAST vulnerabilities](../../user/application_security/dast/index.md)
as artifacts.
The collected DAST report will be uploaded to GitLab as an artifact and will
@@ -1490,7 +1522,7 @@ dashboards.
> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
-The `license_management` report collects [Licenses](https://docs.gitlab.com/ee/user/project/merge_requests/license_management.html)
+The `license_management` report collects [Licenses](../../user/project/merge_requests/license_management.md)
as artifacts.
The collected License Management report will be uploaded to GitLab as an artifact and will
@@ -1501,12 +1533,22 @@ dashboards.
> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
-The `performance` report collects [Performance metrics](https://docs.gitlab.com/ee//user/project/merge_requests/browser_performance_testing.html)
+The `performance` report collects [Performance metrics](../../user/project/merge_requests/browser_performance_testing.md)
as artifacts.
The collected Performance report will be uploaded to GitLab as an artifact and will
be automatically shown in merge requests.
+##### `artifacts:reports:metrics` **[PREMIUM]**
+
+> Introduced in GitLab 11.10.
+
+The `metrics` report collects [Metrics](../../ci/metrics_reports.md)
+as artifacts.
+
+The collected Metrics report will be uploaded to GitLab as an artifact and will
+be automatically shown in merge requests.
+
### `dependencies`
> Introduced in GitLab 8.6 and GitLab Runner v1.1.1.
@@ -1684,7 +1726,7 @@ parallel. This value has to be greater than or equal to two (2) and less than or
This creates N instances of the same job that run in parallel. They're named
sequentially from `job_name 1/N` to `job_name N/N`.
-For every job, `CI_NODE_INDEX` and `CI_NODE_TOTAL` [environment variables](../variables/README.html#predefined-environment-variables) are set.
+For every job, `CI_NODE_INDEX` and `CI_NODE_TOTAL` [environment variables](../variables/README.md#predefined-environment-variables) are set.
A simple example:
@@ -1702,7 +1744,7 @@ test:
from `trigger` definition is started by GitLab, a downstream pipeline gets
created.
-Learn more about [multi-project pipelines](https://docs.gitlab.com/ee/ci/multi_project_pipelines.html#creating-cross-project-pipelines-from-gitlab-ci-yml).
+Learn more about [multi-project pipelines](../multi_project_pipelines.md#creating-multi-project-pipelines-from-gitlab-ciyml).
#### Simple `trigger` syntax
@@ -1756,9 +1798,6 @@ TIP: **Tip:**
Use merging to customize and override included CI/CD configurations with local
definitions.
-Recursive includes are not supported. Your external files should not use the
-`include` keyword as it will be ignored.
-
NOTE: **Note:**
Using YAML aliases across different YAML files sourced by `include` is not
supported. You must only refer to aliases in the same file. Instead
@@ -1978,7 +2017,7 @@ production:
- deploy
environment:
name: production
- url: https://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN
+ url: https://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN
only:
- master
```
@@ -2061,27 +2100,27 @@ from another project:
```yaml
include:
- template: Bash.gitlab-ci.yml
- - project: /group/my-project
+ - project: group/my-project
file: /templates/docker-workflow.yml
```
-The `/templates/docker-workflow.yml` present in `/group/my-project` includes two local files
-of the `/group/my-project`:
+The `/templates/docker-workflow.yml` present in `group/my-project` includes two local files
+of the `group/my-project`:
```yaml
include:
- - local: : /templates/docker-build.yml
- - local: : /templates/docker-testing.yml
+ - local: /templates/docker-build.yml
+ - local: /templates/docker-testing.yml
```
-Our `/templates/docker-build.yml` present in `/group/my-project` adds a `docker-build` job:
+Our `/templates/docker-build.yml` present in `group/my-project` adds a `docker-build` job:
```yaml
docker-build:
script: docker build -t my-image .
```
-Our second `/templates/docker-test.yml` present in `/group/my-project` adds a `docker-test` job:
+Our second `/templates/docker-test.yml` present in `group/my-project` adds a `docker-test` job:
```yaml
docker-test:
@@ -2092,7 +2131,7 @@ docker-test:
> Introduced in GitLab 11.3.
-`extends` defines an entry name that a job that uses `extends` is going to
+`extends` defines entry names that a job that uses `extends` is going to
inherit from.
It is an alternative to using [YAML anchors](#anchors) and is a little
@@ -2169,6 +2208,46 @@ spinach:
script: rake spinach
```
+It's also possible to use multiple parents for `extends`.
+The algorithm used for merge is "closest scope wins", so keys
+from the last member will always shadow anything defined on other levels.
+For example:
+
+```yaml
+.only-important:
+ only:
+ - master
+ - stable
+ tags:
+ - production
+
+.in-docker:
+ tags:
+ - docker
+ image: alpine
+
+rspec:
+ extends:
+ - .only-important
+ - .in-docker
+ script:
+ - rake rspec
+```
+
+This results in the following `rspec` job:
+
+```yaml
+rspec:
+ only:
+ - master
+ - stable
+ tags:
+ - docker
+ image: alpine
+ script:
+ - rake rspec
+```
+
### Using `extends` and `include` together
`extends` works across configuration files combined with `include`.
@@ -2472,18 +2551,18 @@ Use [`stage`](#stage) instead.
## Custom build directories
-> [Introduced][https://gitlab.com/gitlab-org/gitlab-runner/merge_requests/1267] in Gitlab Runner 11.10
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/merge_requests/1267) in Gitlab Runner 11.10
NOTE: **Note:**
This can only be used when `custom_build_dir` is enabled in the [Runner's
configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnerscustom_build_dir-section).
This is the default configuration for `docker` and `kubernetes` executor.
-By default, GitLab Runner clones the repository in a unique subpath of the `$CI_BUILDS_DIR` directory.
-However, sometimes your project might require the code in a specific directory,
-but sometimes your project might require to have the code in a specific directory,
-like Go projects, for example. In that case, you can specify the `GIT_CLONE_PATH` variable
-to tell the Runner in which directory to clone the repository:
+By default, GitLab Runner clones the repository in a unique subpath of the
+`$CI_BUILDS_DIR` directory. However, your project might require the code in a
+specific directory (Go projects, for example). In that case, you can specify
+the `GIT_CLONE_PATH` variable to tell the Runner in which directory to clone the
+repository:
```yml
variables:
@@ -2722,6 +2801,18 @@ using Git 2.10 or newer:
git push -o ci.skip
```
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
+
[ce-6323]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6323
[ce-6669]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6669
[ce-7983]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7983
diff --git a/doc/customization/issue_and_merge_request_template.md b/doc/customization/issue_and_merge_request_template.md
new file mode 100644
index 00000000000..adaa120a37e
--- /dev/null
+++ b/doc/customization/issue_and_merge_request_template.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../user/project/description_templates.md#setting-a-default-template-for-issues-and-merge-requests--starter'
+---
+
+This document was moved to [description_templates](../user/project/description_templates.md#setting-a-default-template-for-issues-and-merge-requests--starter).
diff --git a/doc/development/README.md b/doc/development/README.md
index 5a33c46c620..d2f09fc01de 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -20,6 +20,7 @@ description: 'Learn how to contribute to GitLab.'
- [Automatic CE->EE merge](automatic_ce_ee_merge.md)
- [Guidelines for implementing Enterprise Edition features](ee_features.md)
- [Security process for developers](https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md#security-releases-critical-non-critical-as-a-developer)
+- [Requesting access to Chatops on GitLab.com](chatops_on_gitlabcom.md#requesting-access) (for GitLabbers)
## UX and frontend guides
@@ -38,16 +39,19 @@ description: 'Learn how to contribute to GitLab.'
- [Sidekiq guidelines](sidekiq_style_guide.md) for working with Sidekiq workers
- [Working with Gitaly](gitaly.md)
- [Manage feature flags](feature_flags.md)
+- [Licensed feature availability](licensed_feature_availability.md)
- [View sent emails or preview mailers](emails.md)
- [Shell commands](shell_commands.md) in the GitLab codebase
- [`Gemfile` guidelines](gemfile.md)
- [Pry debugging](pry_debugging.md)
- [Sidekiq debugging](sidekiq_debugging.md)
+- [Accessing session data](session.md)
- [Gotchas](gotchas.md) to avoid
- [Avoid modules with instance variables](module_with_instance_variables.md) if possible
- [How to dump production data to staging](db_dump.md)
- [Working with the GitHub importer](github_importer.md)
- [Import/Export development documentation](import_export.md)
+- [Elasticsearch integration docs](elasticsearch.md)
- [Working with Merge Request diffs](diffs.md)
- [Kubernetes integration guidelines](kubernetes.md)
- [Permissions](permissions.md)
@@ -55,6 +59,8 @@ description: 'Learn how to contribute to GitLab.'
- [Guidelines for reusing abstractions](reusing_abstractions.md)
- [DeclarativePolicy framework](policies.md)
- [How Git object deduplication works in GitLab](git_object_deduplication.md)
+- [Geo development](geo.md)
+- [Routing](routing.md)
## Performance guides
@@ -101,6 +107,10 @@ description: 'Learn how to contribute to GitLab.'
- [Query Count Limits](query_count_limits.md)
- [Database helper modules](database_helpers.md)
+## Integration guides
+
+- [Jira Connect app](integrations/jira_connect.md)
+
## Testing guides
- [Testing standards and style guidelines](testing_guide/index.md)
@@ -129,3 +139,8 @@ description: 'Learn how to contribute to GitLab.'
## Go guides
- [Go Guidelines](go_guide/index.md)
+
+## Other GitLab Development Kit (GDK) guides
+
+- [Run full Auto DevOps cycle in a GDK instance](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/auto_devops.md)
+- [Using GitLab Runner with GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/runner.md)
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md
index 8d2bfff3a5d..38270af682e 100644
--- a/doc/development/api_graphql_styleguide.md
+++ b/doc/development/api_graphql_styleguide.md
@@ -32,6 +32,21 @@ a new presenter specifically for GraphQL.
The presenter is initialized using the object resolved by a field, and
the context.
+### Exposing Global ids
+
+When exposing an `id` field on a type, we will by default try to
+expose a global id by calling `to_global_id` on the resource being
+rendered.
+
+To override this behaviour, you can implement an `id` method on the
+type for which you are exposing an id. Please make sure that when
+exposing a `GraphQL::ID_TYPE` using a custom method that it is
+globally unique.
+
+The records that are exposing a `full_path` as an `ID_TYPE` are one of
+these exceptions. Since the full path is a unique identifier for a
+`Project` or `Namespace`.
+
### Connection Types
GraphQL uses [cursor based
@@ -79,14 +94,14 @@ look like this:
{
"cursor": "Nzc=",
"node": {
- "id": "77",
+ "id": "gid://gitlab/Pipeline/77",
"status": "FAILED"
}
},
{
"cursor": "Njc=",
"node": {
- "id": "67",
+ "id": "gid://gitlab/Pipeline/67",
"status": "FAILED"
}
}
@@ -330,7 +345,7 @@ argument :project_path, GraphQL::ID_TYPE,
required: true,
description: "The project the merge request to mutate is in"
-argument :iid, GraphQL::ID_TYPE,
+argument :iid, GraphQL::STRING_TYPE,
required: true,
description: "The iid of the merge request to mutate"
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index 115c8cfb9ff..5f32cd7eba2 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -1,3 +1,7 @@
+---
+table_display_block: true
+---
+
# GitLab Architecture Overview
## Software delivery
@@ -10,34 +14,162 @@ For information, see the [GitLab Release Process](https://gitlab.com/gitlab-org/
Both EE and CE require some add-on components called gitlab-shell and Gitaly. These components are available from the [gitlab-shell](https://gitlab.com/gitlab-org/gitlab-shell/tree/master) and [gitaly](https://gitlab.com/gitlab-org/gitaly/tree/master) repositories respectively. New versions are usually tags but staying on the master branch will give you the latest stable version. New releases are generally around the same time as GitLab CE releases with exception for informal security updates deemed critical.
-## GitLab Omnibus Component by Component
+## Components
+
+A typical install of GitLab will be on GNU/Linux. It uses Nginx or Apache as a web front end to proxypass the Unicorn web server. By default, communication between Unicorn and the front end is via a Unix domain socket but forwarding requests via TCP is also supported. The web front end accesses `/home/git/gitlab/public` bypassing the Unicorn server to serve static pages, uploads (e.g. avatar images or attachments), and precompiled assets. GitLab serves web pages and a [GitLab API](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/api) using the Unicorn web server. It uses Sidekiq as a job queue which, in turn, uses redis as a non-persistent database backend for job information, meta data, and incoming jobs.
-This document is designed to be consumed by systems adminstrators and GitLab Support Engineers who want to understand more about the internals of GitLab and how they work together.
+We also support deploying GitLab on Kubernetes using our [gitlab Helm chart](https://docs.gitlab.com/charts/).
-When deployed, GitLab should be considered the amalgamation of the below processes. When troubleshooting or debugging, be as specific as possible as to which component you are referencing. That should increase clarity and reduce confusion.
+The GitLab web app uses MySQL or PostgreSQL for persistent database information (e.g. users, permissions, issues, other meta data). GitLab stores the bare git repositories it serves in `/home/git/repositories` by default. It also keeps default branch and hook information with the bare repository.
-### GitLab Process Descriptions
+When serving repositories over HTTP/HTTPS GitLab utilizes the GitLab API to resolve authorization and access as well as serving git objects.
-As of this writing, a fresh GitLab 11.3.0 install will show the following processes with `gitlab-ctl status`:
+The add-on component gitlab-shell serves repositories over SSH. It manages the SSH keys within `/home/git/.ssh/authorized_keys` which should not be manually edited. gitlab-shell accesses the bare repositories through Gitaly to serve git objects and communicates with redis to submit jobs to Sidekiq for GitLab to process. gitlab-shell queries the GitLab API to determine authorization and access.
+Gitaly executes git operations from gitlab-shell and the GitLab web app, and provides an API to the GitLab web app to get attributes from git (e.g. title, branches, tags, other meta data), and to get blobs (e.g. diffs, commits, files).
+
+You may also be interested in the [production architecture of GitLab.com](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/).
+
+### Simplified Component Overview
+
+This is a simplified architecture diagram that can be used to
+understand GitLab's architecture.
+
+A complete architecture diagram is available in our
+[component diagram](#component-diagram) below.
+
+![Simplified Component Overview](img/architecture_simplified.png)
+
+<!--
+To update this diagram, GitLab team members can edit this source file:
+https://docs.google.com/drawings/d/1fBzAyklyveF-i-2q-OHUIqDkYfjjxC4mq5shwKSZHLs/edit.
+ -->
+
+### Component diagram
+
+```mermaid
+graph TB
+
+ HTTP[HTTP/HTTPS] -- TCP 80, 443 --> NGINX[NGINX]
+ SSH -- TCP 22 --> GitLabShell[GitLab Shell]
+ SMTP[SMTP Gateway]
+ Geo[GitLab Geo Node] -- TCP 22, 80, 443 --> NGINX
+
+ GitLabShell --TCP 8080 -->Unicorn["Unicorn (GitLab Rails)"]
+ GitLabShell --> Gitaly
+ GitLabShell --> Redis
+ Unicorn --> PgBouncer[PgBouncer]
+ Unicorn --> Redis
+ Unicorn --> Gitaly
+ Redis --> Sidekiq
+ Sidekiq["Sidekiq (GitLab Rails, ES Indexer)"] --> PgBouncer
+ GitLabWorkhorse[GitLab Workhorse] --> Unicorn
+ GitLabWorkhorse --> Redis
+ GitLabWorkhorse --> Gitaly
+ Gitaly --> Redis
+ NGINX --> GitLabWorkhorse
+ NGINX -- TCP 8090 --> GitLabPages[GitLab Pages]
+ NGINX --> Grafana[Grafana]
+ Grafana -- TCP 9090 --> Prometheus[Prometheus]
+ Prometheus -- TCP 80, 443 --> Unicorn
+ RedisExporter[Redis Exporter] --> Redis
+ Prometheus -- TCP 9121 --> RedisExporter
+ PostgreSQLExporter[PostgreSQL Exporter] --> PostgreSQL
+ PgBouncerExporter[PgBouncer Exporter] --> PgBouncer
+ Prometheus -- TCP 9187 --> PostgreSQLExporter
+ Prometheus -- TCP 9100 --> NodeExporter[Node Exporter]
+ Prometheus -- TCP 9168 --> GitLabMonitor[GitLab Monitor]
+ Prometheus -- TCP 9127 --> PgBouncerExporter
+ GitLabMonitor --> PostgreSQL
+ GitLabMonitor --> GitLabShell
+ GitLabMonitor --> Sidekiq
+ PgBouncer --> Consul
+ PostgreSQL --> Consul
+ PgBouncer --> PostgreSQL
+ NGINX --> Registry
+ Unicorn --> Registry
+ NGINX --> Mattermost
+ Mattermost --- Unicorn
+ Prometheus --> Alertmanager
+ Migrations --> PostgreSQL
+ Runner -- TCP 443 --> NGINX
+ Unicorn -- TCP 9200 --> ElasticSearch
+ Sidekiq -- TCP 9200 --> ElasticSearch
+ Sidekiq -- TCP 80, 443 --> Sentry
+ Unicorn -- TCP 80, 443 --> Sentry
+ Sidekiq -- UDP 6831 --> Jaeger
+ Unicorn -- UDP 6831 --> Jaeger
+ Gitaly -- UDP 6831 --> Jaeger
+ GitLabShell -- UDP 6831 --> Jaeger
+ GitLabWorkhorse -- UDP 6831 --> Jaeger
+ Alertmanager -- TCP 25 --> SMTP
+ Sidekiq -- TCP 25 --> SMTP
+ Unicorn -- TCP 25 --> SMTP
+ Unicorn -- TCP 369 --> LDAP
+ Sidekiq -- TCP 369 --> LDAP
+ Unicorn -- TCP 443 --> ObjectStorage["Object Storage"]
+ Sidekiq -- TCP 443 --> ObjectStorage
+ GitLabWorkhorse -- TCP 443 --> ObjectStorage
+ Registry -- TCP 443 --> ObjectStorage
+ Geo -- TCP 5432 --> PostgreSQL
```
-run: alertmanager: (pid 30829) 14207s; run: log: (pid 13906) 2432044s
-run: gitaly: (pid 30771) 14210s; run: log: (pid 13843) 2432046s
-run: gitlab-monitor: (pid 30788) 14209s; run: log: (pid 13868) 2432045s
-run: gitlab-workhorse: (pid 30758) 14210s; run: log: (pid 13855) 2432046s
-run: logrotate: (pid 30246) 3407s; run: log: (pid 13825) 2432047s
-run: nginx: (pid 30849) 14207s; run: log: (pid 13856) 2432046s
-run: node-exporter: (pid 30929) 14206s; run: log: (pid 13877) 2432045s
-run: postgres-exporter: (pid 30935) 14206s; run: log: (pid 13931) 2432044s
-run: postgresql: (pid 13133) 2432214s; run: log: (pid 13848) 2432046s
-run: prometheus: (pid 30807) 14209s; run: log: (pid 13884) 2432045s
-run: redis: (pid 30560) 14274s; run: log: (pid 13807) 2432047s
-run: redis-exporter: (pid 30946) 14205s; run: log: (pid 13869) 2432045s
-run: sidekiq: (pid 30953) 14205s; run: log: (pid 13810) 2432047s
-run: unicorn: (pid 30960) 14204s; run: log: (pid 13809) 2432047s
-```
-### Layers
+### Component legend
+
+* ✅ - Installed by default
+* âš™ - Requires additional configuration, or GitLab Managed Apps
+* ⤓ - Manual installation required
+* ⌠- Not supported or no instructions available
+
+Component statuses are linked to configuration documentation for each component.
+
+### Component list
+
+| Component | Description | [Omnibus GitLab](https://docs.gitlab.com/omnibus/) | [GitLab chart](https://docs.gitlab.com/charts/) | [Minikube Minimal](https://docs.gitlab.com/charts/development/minikube/#deploying-gitlab-with-minimal-settings) | [GitLab.com](https://gitlab.com) | [Source](../install/installation.md) | [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit) | CE/EE |
+| --------- | ----------- |:--------------------:|:------------------:|:-----:|:--------:|:--------:|:-------:|:-------:|
+| [NGINX](#nginx) | Routes requests to appropriate components, terminates SSL | [✅][nginx-omnibus] | [✅][nginx-charts] | [⚙][nginx-charts] | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#service-architecture) | [⤓][nginx-source] | ⌠| CE & EE |
+| [Unicorn (GitLab Rails)](#unicorn) | Handles requests for the web interface and API | [✅][unicorn-omnibus] | [✅][unicorn-charts] | [✅][unicorn-charts] | [✅](../user/gitlab_com/index.md#unicorn) | [⚙][unicorn-source] | [✅][gitlab-yml] | CE & EE |
+| [Sidekiq](#sidekiq) | Background jobs processor | [✅][sidekiq-omnibus] | [✅][sidekiq-charts] | [✅](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/index.html) | [✅](../user/gitlab_com/index.md#sidekiq) | [✅][gitlab-yml] | [✅][gitlab-yml] | CE & EE |
+| [Gitaly](#gitaly) | Git RPC service for handling all git calls made by GitLab | [✅][gitaly-omnibus] | [✅][gitaly-charts] | [✅][gitaly-charts] | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#service-architecture) | [⚙][gitaly-source] | ✅ | CE & EE |
+| [GitLab Workhorse](#gitlab-workhorse) | Smart reverse proxy, handles large HTTP requests | [✅][workhorse-omnibus] | [✅][workhorse-charts] | [✅][workhorse-charts] | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#service-architecture) | [⚙][workhorse-source] | ✅ | CE & EE |
+| [GitLab Shell](#gitlab-shell) | Handles `git` over SSH sessions | [✅][shell-omnibus] | [✅][shell-charts] | [✅][shell-charts] | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#service-architecture) | [⚙][shell-source] | [✅][gitlab-yml] | CE & EE |
+| [GitLab Pages](#gitlab-pages) | Hosts static websites | [âš™][pages-omnibus] | [âŒ][pages-charts] | [âŒ][pages-charts] | [✅](../user/gitlab_com/index.md#gitlab-pages) | [âš™][pages-source] | [âš™][pages-gdk] | CE & EE |
+| [Registry](#registry) | Container registry, allows pushing and pulling of images | [⚙][registry-omnibus] | [✅][registry-charts] | [✅][registry-charts] | [✅](../user/project/container_registry.md#build-and-push-images) | [⤓][registry-source] | [⚙][registry-gdk] | CE & EE |
+| [Redis](#redis) | Caching service | [✅][redis-omnibus] | [✅][redis-omnibus] | [✅][redis-charts] | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#service-architecture) | [⤓][redis-source] | ✅ | CE & EE |
+| [PostgreSQL](#postgresql) | Database | [✅][postgres-omnibus] | [✅][postgres-charts] | [✅][postgres-charts] | [✅](../user/gitlab_com/index.md#postgresql) | [⤓][postgres-source] | ✅ | CE & EE |
+| [PgBouncer](#pgbouncer) | Database connection pooling, failover | [âš™][pgbouncer-omnibus] | [âŒ][pgbouncer-charts] | [âŒ][pgbouncer-charts] | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#database-architecture) | ⌠| ⌠| EE Only |
+| [Consul](#consul) | Database node discovery, failover | [âš™][consul-omnibus] | [âŒ][consul-charts] | [âŒ][consul-charts] | [✅](../user/gitlab_com/index.md#consul) | ⌠| ⌠| EE Only |
+| [GitLab self-monitoring: Prometheus](#prometheus) | Time-series database, metrics collection, and query service | [✅][prometheus-omnibus] | [✅][prometheus-charts] | [⚙][prometheus-charts] | [✅](../user/gitlab_com/index.md#prometheus) | ⌠| ⌠| CE & EE |
+| [GitLab self-monitoring: Alertmanager](#alertmanager) | Deduplicates, groups, and routes alerts from Prometheus | [⚙][alertmanager-omnibus] | [✅][alertmanager-charts] | [⚙][alertmanager-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ⌠| ⌠| CE & EE |
+| [GitLab self-monitoring: Grafana](#grafana) | Metrics dashboard | [⚙][grafana-omnibus] | [⤓][grafana-charts] | [⤓][grafana-charts] | [✅](https://dashboards.gitlab.com/d/RZmbBr7mk/gitlab-triage?refresh=30s) | ⌠| ⌠| CE & EE |
+| [GitLab self-monitoring: Sentry](#sentry) | Track errors generated by the GitLab instance | [⤓][sentry-omnibus] | [âŒ][sentry-charts] | [âŒ][sentry-charts] | [✅](https://about.gitlab.com/handbook/support/workflows/services/gitlab_com/500_errors.html#searching-sentry) | [⤓][gitlab-yml] | [⤓][gitlab-yml] | CE & EE |
+| [GitLab self-monitoring: Jaeger](#jaeger) | View traces generated by the GitLab instance | [âŒ][jaeger-omnibus] | [âŒ][jaeger-charts] | [âŒ][jaeger-charts] | [âŒ](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/4104) | [⤓][jaeger-source] | [âš™][jaeger-gdk] | CE & EE |
+| [Redis Exporter](#redis-exporter) | Prometheus endpoint with Redis metrics | [✅][redis-exporter-omnibus] | [✅][redis-exporter-charts] | [✅][redis-exporter-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ⌠| ⌠| CE & EE |
+| [Postgres Exporter](#postgres-exporter) | Prometheus endpoint with PostgreSQL metrics | [✅][postgres-exporter-omnibus] | [✅][postgres-exporter-charts] | [✅][postgres-exporter-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ⌠| ⌠| CE & EE |
+| [PgBouncer Exporter](#pgbouncer-exporter) | Prometheus endpoint with PgBouncer metrics | [âš™][pgbouncer-exporter-omnibus] | [âŒ][pgbouncer-exporter-charts] | [âŒ][pgbouncer-exporter-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ⌠| ⌠| CE & EE |
+| [GitLab Monitor](#gitlab-monitor) | Generates a variety of GitLab metrics | [✅][gitlab-monitor-omnibus] | [âŒ][gitab-monitor-charts] | [âŒ][gitab-monitor-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ⌠| ⌠| CE & EE |
+| [Node Exporter](#node-exporter) | Prometheus endpoint with system metrics | [✅][node-exporter-omnibus] | [âŒ][node-exporter-charts] | [âŒ][node-exporter-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ⌠| ⌠| CE & EE |
+| [Mattermost](#mattermost) | Open-source Slack alternative | [⚙][mattermost-omnibus] | [⤓][mattermost-charts] | [⤓][mattermost-charts] | [⤓](../user/project/integrations/mattermost_slash_commands.md#manual-configuration), [⤓](../user/project/integrations/mattermost.html) | ⌠| ⌠| CE & EE |
+| [MinIO](#minio) | Object storage service | [⤓][minio-omnibus] | [✅][minio-charts] | [✅][minio-charts] | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#storage-architecture) | ⌠| [⚙][minio-gdk] | CE & EE |
+| [Runner](#gitlab-runner) | Executes GitLab CI jobs | [⤓][runner-omnibus] | [✅][runner-charts] | [⚙][runner-charts] | [✅](../user/gitlab_com/index.md#shared-runners) | [⚙][runner-source] | [⚙][runner-gdk] | CE & EE |
+| [Database Migrations](#database-migrations) | Database migrations | [✅][database-migrations-omnibus] | [✅][database-migrations-charts] | [✅][database-migrations-charts] | ✅ | [⚙][database-migrations-source] | ✅ | CE & EE |
+| [Certificate Management](#certificate-management) | TLS Settings, Let's Encrypt | [✅][certificate-management-omnibus] | [✅][certificate-management-charts] | [⚙][certificate-management-charts] | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#secrets-management) | [⚙][certificate-management-source] | [⚙][certificate-management-gdk] | CE & EE |
+| [GitLab Geo Node](#gitlab-geo) | Geographically distributed GitLab nodes | [âš™][geo-omnibus] | [âŒ][geo-charts] | [âŒ][geo-charts] | ✅ | ⌠| [âš™][geo-gdk] | EE Only |
+| [LDAP Authentication](#ldap-authentication) | Authenticate users against centralized LDAP directory | [⤓][ldap-omnibus] | [⤓][ldap-charts] | [⤓][ldap-charts] | [âŒ](https://about.gitlab.com/pricing/#gitlab-com) | [⤓][gitlab-yml] | [⤓][ldap-gdk] | CE & EE |
+| [Outbound email (SMTP)](#outbound-email) | Send email messages to users | [⤓][outbound-email-omnibus] | [⤓][outbound-email-charts] | [⤓][outbound-email-charts] | [✅](../user/gitlab_com/index.md#mail-configuration) | [⤓][gitlab-yml] | [⤓][gitlab-yml] | CE & EE |
+| [Inbound email (SMTP)](#inbound-email) | Receive messages to update issues | [⤓][inbound-email-omnibus] | [⤓][inbound-email-charts] | [⤓][inbound-email-charts] | [✅](../user/gitlab_com/index.md#mail-configuration) | [⤓][gitlab-yml] | [⤓][gitlab-yml] | CE & EE |
+| [ElasticSearch](#elasticsearch) | Improved search within GitLab | [⤓][elasticsearch-omnibus] | [⤓][elasticsearch-charts] | [⤓][elasticsearch-charts] | [âŒ](https://gitlab.com/groups/gitlab-org/-/epics/153) | [⤓][elasticsearch-source] | [⤓][elasticsearch-gdk] | EE Only |
+| [Sentry integration](#sentry) | Error tracking for deployed apps | [⤓][sentry-integration] | [⤓][sentry-integration] | [⤓][sentry-integration] | [⤓][sentry-integration] | [⤓][sentry-integration] | [⤓][sentry-integration] | CE & EE |
+| [Jaeger integration](#jaeger) | Distributed tracing for deployed apps | [⤓][jaeger-integration] | [⤓][jaeger-integration] | [⤓][jaeger-integration] | [⤓][jaeger-integration] | [⤓][jaeger-integration] | [⤓][jaeger-integration] | EE Only |
+| [GitLab Managed Apps](#gitlab-managed-apps) | Deploy [Helm](https://docs.helm.sh/), [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/), [Cert-Manager](https://docs.cert-manager.io/en/latest/), [Prometheus](https://prometheus.io/docs/introduction/overview/), a [Runner](https://docs.gitlab.com/runner/), [JupyterHub](http://jupyter.org/), [Knative](https://cloud.google.com/knative) to a cluster | [⤓][managed-k8s-apps] | [⤓][managed-k8s-apps] | [⤓][managed-k8s-apps] | [⤓][managed-k8s-apps] | [⤓][managed-k8s-apps] | [⤓][managed-k8s-apps] | CE & EE |
+
+### Component details
+
+This document is designed to be consumed by systems administrators and GitLab Support Engineers who want to understand more about the internals of GitLab and how they work together.
+
+When deployed, GitLab should be considered the amalgamation of the below processes. When troubleshooting or debugging, be as specific as possible as to which component you are referencing. That should increase clarity and reduce confusion.
+
+**Layers**
GitLab can be considered to have two layers from a process perspective:
@@ -46,129 +178,288 @@ GitLab can be considered to have two layers from a process perspective:
- **Processors**: These processes are responsible for actually performing operations and presenting the service.
- **Data**: These services store/expose structured data for the GitLab service.
-### alertmanager
+#### Alertmanager
-- Omnibus configuration options
+- [Project page](https://github.com/prometheus/alertmanager/blob/master/README.md)
+- Configuration: [Omnibus][alertmanager-omnibus], [Charts][alertmanager-charts]
- Layer: Monitoring
+- Process: `alertmanager`
-[Alert manager](https://prometheus.io/docs/alerting/alertmanager/) is a tool provided by prometheus that _"handles alerts sent by client applications such as the Prometheus server. It takes care of deduplicating, grouping, and routing them to the correct receiver integration such as email, PagerDuty, or OpsGenie. It also takes care of silencing and inhibition of alerts."_ You can read more in [issue gitlab-ce#45740](https://gitlab.com/gitlab-org/gitlab-ce/issues/45740) about what we will be alerting on.
+[Alert manager](https://prometheus.io/docs/alerting/alertmanager/) is a tool provided by Prometheus that _"handles alerts sent by client applications such as the Prometheus server. It takes care of deduplicating, grouping, and routing them to the correct receiver integration such as email, PagerDuty, or OpsGenie. It also takes care of silencing and inhibition of alerts."_ You can read more in [issue gitlab-ce#45740](https://gitlab.com/gitlab-org/gitlab-ce/issues/45740) about what we will be alerting on.
-### gitaly
+#### Certificate management
-- [Omnibus configuration options](https://gitlab.com/gitlab-org/gitaly/tree/master/doc/configuration)
+- Project page: [Omnibus](https://github.com/certbot/certbot/blob/master/README.rst), [Charts](https://github.com/jetstack/cert-manager/blob/master/README.md)
+- Configuration: [Omnibus][certificate-management-omnibus], [Charts][certificate-management-charts], [Source][certificate-management-source], [GDK][certificate-management-gdk]
+- Layer: Core Service (Processor)
+
+#### Consul
+
+- [Project page](https://github.com/hashicorp/consul/blob/master/README.md)
+- Configuration: [Omnibus][consul-omnibus], [Charts][consul-charts]
+- Layer: Core Service (Data)
+
+Consul is a tool for service discovery and configuration. Consul is distributed, highly available, and extremely scalable.
+
+#### Database migrations
+
+- Configuration: [Omnibus][registry-omnibus], [Charts][registry-charts], [Source][database-migrations-source]
- Layer: Core Service (Data)
-Gitaly is a service designed by GitLab to remove our need for NFS for Git storage in distributed deployments of GitLab (Think GitLab.com or High Availability Deployments). As of 11.3.0, this service handles all Git level access in GitLab. You can read more about the project [in the project's readme](https://gitlab.com/gitlab-org/gitaly).
+#### Elasticsearch
-### gitlab-monitor
+- [Project page](https://github.com/elastic/elasticsearch/blob/master/README.textile)
+- Configuration: [Omnibus][elasticsearch-omnibus], [Charts][elasticsearch-charts], [Source][elasticsearch-source], [GDK][elasticsearch-gdk]
+- Layer: Core Service (Data)
-- Omnibus configuration options
+Elasticsearch is a distributed RESTful search engine built for the cloud.
+
+#### Gitaly
+
+- [Project page](https://gitlab.com/gitlab-org/gitaly/blob/master/README.md)
+- Configuration: [Omnibus][gitaly-omnibus], [Charts][gitaly-charts], [Source][gitaly-source]
+- Layer: Core Service (Data)
+- Process: `gitaly`
+
+Gitaly is a service designed by GitLab to remove our need for NFS for Git storage in distributed deployments of GitLab (think GitLab.com or High Availability Deployments). As of 11.3.0, this service handles all Git level access in GitLab. You can read more about the project [in the project's readme](https://gitlab.com/gitlab-org/gitaly).
+
+#### Gitlab Geo
+
+- Configuration: [Omnibus][geo-omnibus], [Charts][geo-charts], [GDK][geo-gdk]
+- Layer: Core Service (Processor)
+
+#### Gitlab Monitor
+
+- [Project page](https://gitlab.com/gitlab-org/gitlab-monitor)
+- Configuration: [Omnibus][gitlab-monitor-omnibus], [Charts][gitlab-monitor-charts]
- Layer: Monitoring
+- Process: `gitlab-monitor`
+
+GitLab Monitor is a process designed in house that allows us to export metrics about GitLab application internals to Prometheus. You can read more [in the project's readme](https://gitlab.com/gitlab-org/gitlab-monitor).
+
+#### Gitlab Pages
-GitLab Monitor is a process designed in house that allows us to export metrics about GitLab application internals to prometheus. You can read more [in the project's readme](https://gitlab.com/gitlab-org/gitlab-monitor)
+- Configuration: [Omnibus][pages-omnibus], [Charts][pages-charts], [Source][pages-source], [GDK][pages-gdk]
+- Layer: Core Service (Processor)
+
+GitLab Pages is a feature that allows you to publish static websites directly from a repository in GitLab.
-### gitlab-workhorse
+You can use it either for personal or business websites, such as portfolios, documentation, manifestos, and business presentations. You can also attribute any license to your content.
-- Omnibus configuration options
+#### Gitlab Runner
+
+- [Project page](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/README.md)
+- Configuration: [Omnibus][runner-omnibus], [Charts][runner-charts], [Source][runner-source], [GDK][runner-gdk]
- Layer: Core Service (Processor)
-[GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse) is a program designed at GitLab to help alleviate pressure from unicorn. You can read more about the [historical reasons for developing](https://about.gitlab.com/2016/04/12/a-brief-history-of-gitlab-workhorse/). It's designed to act as a smart reverse proxy to help speed up GitLab as a whole.
+GitLab Runner runs tests and sends the results to GitLab.
+
+GitLab CI is the open-source continuous integration service included with GitLab that coordinates the testing. The old name of this project was GitLab CI Multi Runner but please use "GitLab Runner" (without CI) from now on.
+
+#### Gitlab Shell
+
+- [Project page](https://gitlab.com/gitlab-org/gitlab-shell/blob/master/README.md)
+- Configuration: [Omnibus][shell-omnibus], [Charts][shell-charts], [Source][shell-source], [GDK][gitlab-yml]
+- Layer: Core Service (Processor)
+
+[GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell) is a program designed at GitLab to handle ssh-based `git` sessions, and modifies the list of authorized keys. GitLab Shell is not a Unix shell nor a replacement for Bash or Zsh.
+
+#### Gitlab Workhorse
+
+- [Project page](https://gitlab.com/gitlab-org/gitlab-workhorse/blob/master/README.md)
+- Configuration: [Omnibus][gitlab-workhorse-omnibus], [Charts][gitlab-workhorse-charts], [Source][workhorse-source]
+- Layer: Core Service (Processor)
+- Process: `gitlab-workhorse`
-### logrotate
+[GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse) is a program designed at GitLab to help alleviate pressure from Unicorn. You can read more about the [historical reasons for developing](https://about.gitlab.com/2016/04/12/a-brief-history-of-gitlab-workhorse/). It's designed to act as a smart reverse proxy to help speed up GitLab as a whole.
-- [Omnibus configuration options](https://docs.gitlab.com/omnibus/settings/logs.html#logrotate)
+#### Grafana
+
+- [Project page](https://github.com/grafana/grafana/blob/master/README.md)
+- Configuration: [Omnibus][grafana-omnibus], [Charts][grafana-charts]
+- Layer: Monitoring
+
+Grafana is an open source, feature rich metrics dashboard and graph editor for Graphite, Elasticsearch, OpenTSDB, Prometheus and InfluxDB.
+
+#### Jaeger
+
+- [Project page](https://github.com/jaegertracing/jaeger/blob/master/README.md)
+- Configuration: [Omnibus][jaeger-omnibus], [Charts][jaeger-charts], [Source][jaeger-source], [GDK][jaeger-gdk]
+- Layer: Monitoring
+
+Jaeger, inspired by Dapper and OpenZipkin, is a distributed tracing system. It can be used for monitoring microservices-based distributed systems.
+
+#### Logrotate
+
+- [Project page](https://github.com/logrotate/logrotate/blob/master/README.md)
+- Configuration: [Omnibus](https://docs.gitlab.com/omnibus/settings/logs.html#logrotate)
- Layer: Core Service
+- Process: `logrotate`
+
+GitLab is comprised of a large number of services that all log. We started bundling our own logrotate as of 7.4 to make sure we were logging responsibly. This is just a packaged version of the common open source offering.
+
+#### Mattermost
+
+- [Project page](https://github.com/mattermost/mattermost-server/blob/master/README.md)
+- Configuration: [Omnibus][mattermost-omnibus], [Charts][mattermost-charts]
+- Layer: Core Service (Processor)
+
+Mattermost is an open source, private cloud, Slack-alternative from https://mattermost.com.
-GitLab is comprised of a large number of services that all log. We started bundling our own logrotate as of 7.4 to make sure we were logging responsibly. This is just a packaged version of the common opensource offering.
+#### MinIO
-### nginx
+- [Project page](https://github.com/minio/minio/blob/master/README.md)
+- Configuration: [Omnibus][minio-omnibus], [Charts][minio-charts], [GDK][minio-gdk]
+- Layer: Core Service (Data)
+
+MinIO is an object storage server released under Apache License v2.0. It is compatible with Amazon S3 cloud storage service. It is best suited for storing unstructured data such as photos, videos, log files, backups and container / VM images. Size of an object can range from a few KBs to a maximum of 5TB.
-- [Omnibus configuration options](https://docs.gitlab.com/omnibus/settings/nginx.html)
+#### NGINX
+
+- Project page: [Omnibus](https://github.com/nginx/nginx), [Charts](https://github.com/kubernetes/ingress-nginx/blob/master/README.md)
+- Configuration: [Omnibus][nginx-omnibus], [Charts][nginx-charts], [Source][nginx-source]
- Layer: Core Service (Processor)
+- Process: `nginx`
Nginx as an ingress port for all HTTP requests and routes them to the approriate sub-systems within GitLab. We are bundling an unmodified version of the popular open source webserver.
-### node-exporter
+#### Node Exporter
-- [Omnibus configuration options](https://docs.gitlab.com/ee/administration/monitoring/prometheus/node_exporter.html)
+- [Project page](https://github.com/prometheus/node_exporter/blob/master/README.md)
+- Configuration: [Omnibus][node-exporter-omnibus], [Charts][node-exporter-charts]
- Layer: Monitoring
+- Process: `node-exporter`
+
+[Node Exporter](https://github.com/prometheus/node_exporter) is a Prometheus tool that gives us metrics on the underlying machine (think CPU/Disk/Load). It's just a packaged version of the common open source offering from the Prometheus project.
-[Node Exporter](https://github.com/prometheus/node_exporter) is a Prometheus tool that gives us metrics on the underlying machine. (Think CPU/Disk/Load) It's just a packaged version of the common open source offering from the Prometheus project.
+#### PgBouncer
-### postgres-exporter
+- [Project page](https://github.com/pgbouncer/pgbouncer/blob/master/README.md)
+- Configuration: [Omnibus][pgbouncer-omnibus], [Charts][pgbouncer-charts]
+- Layer: Core Service (Data)
+
+Lightweight connection pooler for PostgreSQL.
-- [Omnibus configuration options](https://docs.gitlab.com/ee/administration/monitoring/prometheus/postgres_exporter.html)
+#### PgBouncer Exporter
+
+- [Project page](https://github.com/stanhu/pgbouncer_exporter/blob/master/README.md)
+- Configuration: [Omnibus][pgbouncer-exporter-omnibus], [Charts][pgbouncer-exporter-charts]
- Layer: Monitoring
-[Postgres-exporter](https://github.com/wrouesnel/postgres_exporter) is the community provided Prometheus exporter that will deliver data about Postgres to prometheus for use in Grafana Dashboards.
+Prometheus exporter for PgBouncer. Exports metrics at 9127/metrics.
-### postgresql
+#### Postgresql
-- [Omnibus configuration options](https://docs.gitlab.com/omnibus/settings/database.html)
+- [Project page](https://github.com/postgres/postgres/blob/master/README)
+- Configuration: [Omnibus][postgres-omnibus], [Charts][postgres-charts], [Source][postgres-source]
- Layer: Core Service (Data)
+- Process: `postgresql`
GitLab packages the popular Database to provide storage for Application meta data and user information.
-### prometheus
+#### Postgres Exporter
-- [Omnibus configuration options](https://docs.gitlab.com/ee/administration/monitoring/prometheus/)
+- [Project page](https://github.com/wrouesnel/postgres_exporter/blob/master/README.md)
+- Configuration: [Omnibus][postgres-exporter-omnibus], [Charts][postgres-exporter-charts]
- Layer: Monitoring
+- Process: `postgres-exporter`
+
+[Postgres-exporter](https://github.com/wrouesnel/postgres_exporter) is the community provided Prometheus exporter that will deliver data about Postgres to Prometheus for use in Grafana Dashboards.
+
+#### Prometheus
+
+- [Project page](https://github.com/prometheus/prometheus/blob/master/README.md)
+- Configuration: [Omnibus][prometheus-omnibus], [Charts][prometheus-charts]
+- Layer: Monitoring
+- Process: `prometheus`
Prometheus is a time-series tool that helps GitLab administrators expose metrics about the individual processes used to provide GitLab the service.
-### redis
+#### Redis
-- [Omnibus configuration options](https://docs.gitlab.com/omnibus/settings/redis.html)
+- [Project page](https://github.com/antirez/redis/blob/unstable/README.md)
+- Configuration: [Omnibus][redis-omnibus], [Charts][redis-charts], [Source][redis-source]
- Layer: Core Service (Data)
+- Process: `redis`
Redis is packaged to provide a place to store:
- session data
- temporary cache information
-- background job queues.
+- background job queues
+
+#### Redis Exporter
+
+- [Project page](https://github.com/oliver006/redis_exporter/blob/master/README.md)
+- Configuration: [Omnibus][redis-exporter-omnibus], [Charts][redis-exporter-charts]
+- Layer: Monitoring
+- Process: `redis-exporter`
+
+[Redis Exporter](https://github.com/oliver006/redis_exporter) is designed to give specific metrics about the Redis process to Prometheus so that we can graph these metrics in Grafana.
-### redis-exporter
+#### Registry
-- [Omnibus configuration options](https://docs.gitlab.com/ee/administration/monitoring/prometheus/redis_exporter.html)
+- [Project page](https://github.com/docker/distribution/blob/master/README.md)
+- Configuration: [Omnibus][registry-omnibus], [Charts][registry-charts], [Source][registry-source], [GDK][registry-gdk]
+- Layer: Core Service (Processor)
+
+The registry is what users use to store their own Docker images. The bundled
+registry uses nginx as a load balancer and GitLab as an authentication manager.
+Whenever a client requests to pull or push an image from the registry, it will
+return a `401` response along with a header detailing where to get an
+authentication token, in this case the GitLab instance. The client will then
+request a pull or push auth token from GitLab and retry the original request
+to the registry. Learn more about [token authentication](https://docs.docker.com/registry/spec/auth/token/).
+
+An external registry can also be configured to use GitLab as an auth endpoint.
+
+#### Sentry
+
+- [Project page](https://github.com/getsentry/sentry/blob/master/README.rst)
+- Configuration: [Omnibus][sentry-omnibus], [Charts][sentry-charts], [Source][gitlab-yml], [GDK][gitlab-yml]
- Layer: Monitoring
-[Redis Exporter](https://github.com/oliver006/redis_exporter) is designed to give specific metrics about the Redis process to Prometheus so that we can graph these metrics in Graphana.
+Sentry fundamentally is a service that helps you monitor and fix crashes in realtime. The server is in Python, but it contains a full API for sending events from any language, in any application.
-### sidekiq
+#### Sidekiq
-- Omnibus configuration options
+- [Project page](https://github.com/mperham/sidekiq/blob/master/README.md)
+- Configuration: [Omnibus][sidekiq-omnibus], [Charts][sidekiq-charts], [Source][gitlab-yml], [GDK][gitlab-yml]
- Layer: Core Service (Processor)
+- Process: `sidekiq`
Sidekiq is a Ruby background job processor that pulls jobs from the redis queue and processes them. Background jobs allow GitLab to provide a faster request/response cycle by moving work into the background.
-### unicorn
+#### Unicorn
-- [Omnibus configuration options](https://docs.gitlab.com/omnibus/settings/unicorn.html)
+- [Project page](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/README.md)
+- Configuration: [Omnibus][unicorn-omnibus], [Charts][unicorn-charts], [Source][unicorn-source], [GDK][gitlab-yml]
- Layer: Core Service (Processor)
+- Process: `unicorn`
[Unicorn](https://bogomips.org/unicorn/) is a Ruby application server that is used to run the core Rails Application that provides the user facing features in GitLab. Often process output you will see this as `bundle` or `config.ru` depending on the GitLab version.
-### Additional Processes
+#### LDAP Authentication
-### GitLab Pages
+- Configuration: [Omnibus][ldap-omnibus], [Charts][ldap-charts], [Source][gitlab-yml], [GDK][ldap-gdk]
+- Layer: Core Service (Processor)
-TODO
+#### Outbound Email
-### Mattermost
+- Configuration: [Omnibus][outbound-email-omnibus], [Charts][outbound-email-charts], [Source][gitlab-yml], [GDK][gitlab-yml]
+- Layer: Core Service (Processor)
-TODO
+#### Inbound Email
-### Registry
+- Configuration: [Omnibus][inbound-email-omnibus], [Charts][inbound-email-charts], [Source][gitlab-yml], [GDK][gitlab-yml]
+- Layer: Core Service (Processor)
-The registry is what users use to store their own Docker images. The bundled
-registry uses nginx as a load balancer and GitLab as an authentication manager.
-Whenever a client requests to pull or push an image from the registry, it will
-return a `401` response along with a header detailing where to get an
-authentication token, in this case the GitLab instance. The client will then
-request a pull or push auth token from GitLab and retry the original request
-to the registry. Learn more about [token authentication](https://docs.docker.com/registry/spec/auth/token/).
+#### GitLab Managed Apps
-An external registry can also be configured to use GitLab as an auth endpoint.
+- Configuration: [Omnibus][managed-k8s-apps], [Charts][managed-k8s-apps], [Source][managed-k8s-apps], [GDK][managed-k8s-apps]
+- Layer: Core Service (Processor)
+
+GitLab provides [GitLab Managed Apps](../user/project/clusters/index.md#installing-applications), a one-click install for various applications which can be added directly to your configured cluster. These applications are needed for Review Apps and deployments when using Auto DevOps. You can install them after you create a cluster.
## GitLab by Request Type
@@ -181,10 +472,10 @@ It's important to understand the distinction as some processes are used in both
### GitLab Web HTTP Request Cycle
-When making a request to an HTTP Endpoint (Think `/users/sign_in`) the request will take the following path through the GitLab Service:
+When making a request to an HTTP Endpoint (think `/users/sign_in`) the request will take the following path through the GitLab Service:
-- nginx - Acts as our first line reverse proxy
-- gitlab-workhorse - This determines if it needs to go to the Rails application or somewhere else to reduce load on unicorn.
+- nginx - Acts as our first line reverse proxy.
+- gitlab-workhorse - This determines if it needs to go to the Rails application or somewhere else to reduce load on Unicorn.
- unicorn - Since this is a web request, and it needs to access the application it will go to Unicorn.
- Postgres/Gitaly/Redis - Depending on the type of request, it may hit these services to store or retrieve data.
@@ -200,7 +491,7 @@ TODO
## System Layout
-When referring to `~git` in the pictures it means the home directory of the git user which is typically /home/git.
+When referring to `~git` in the pictures it means the home directory of the git user which is typically `/home/git`.
GitLab is primarily installed within the `/home/git` user home directory as `git` user. Within the home directory is where the gitlabhq server software resides as well as the repositories (though the repository location is configurable).
@@ -208,24 +499,6 @@ The bare repositories are located in `/home/git/repositories`. GitLab is a ruby
To serve repositories over SSH there's an add-on application called gitlab-shell which is installed in `/home/git/gitlab-shell`.
-### Components
-
-<img src="https://docs.google.com/drawings/d/1fBzAyklyveF-i-2q-OHUIqDkYfjjxC4mq5shwKSZHLs/pub?w=987&amp;h=797">
-
-_[edit diagram (for GitLab team members only)](https://docs.google.com/drawings/d/1fBzAyklyveF-i-2q-OHUIqDkYfjjxC4mq5shwKSZHLs/edit)_
-
-A typical install of GitLab will be on GNU/Linux. It uses Nginx or Apache as a web front end to proxypass the Unicorn web server. By default, communication between Unicorn and the front end is via a Unix domain socket but forwarding requests via TCP is also supported. The web front end accesses `/home/git/gitlab/public` bypassing the Unicorn server to serve static pages, uploads (e.g. avatar images or attachments), and precompiled assets. GitLab serves web pages and a [GitLab API](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/api) using the Unicorn web server. It uses Sidekiq as a job queue which, in turn, uses redis as a non-persistent database backend for job information, meta data, and incoming jobs.
-
-The GitLab web app uses MySQL or PostgreSQL for persistent database information (e.g. users, permissions, issues, other meta data). GitLab stores the bare git repositories it serves in `/home/git/repositories` by default. It also keeps default branch and hook information with the bare repository.
-
-When serving repositories over HTTP/HTTPS GitLab utilizes the GitLab API to resolve authorization and access as well as serving git objects.
-
-The add-on component gitlab-shell serves repositories over SSH. It manages the SSH keys within `/home/git/.ssh/authorized_keys` which should not be manually edited. gitlab-shell accesses the bare repositories through Gitaly to serve git objects and communicates with redis to submit jobs to Sidekiq for GitLab to process. gitlab-shell queries the GitLab API to determine authorization and access.
-
-Gitaly executes git operations from gitlab-shell and the GitLab web app, and provides an API to the GitLab web app to get attributes from git (e.g. title, branches, tags, other meta data), and to get blobs (e.g. diffs, commits, files).
-
-You may also be interested in the [production architecture of GitLab.com](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/).
-
### Installation Folder Summary
To summarize here's the [directory structure of the `git` user home directory](../install/structure.md).
@@ -352,3 +625,95 @@ Note: It is recommended to log into the `git` user using `sudo -i -u git` or `su
## GitLab.com
We've also detailed [our architecture of GitLab.com](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/) but this is probably over the top unless you have millions of users.
+
+[alertmanager-omnibus]: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template
+[alertmanager-charts]: https://github.com/helm/charts/tree/master/stable/prometheus
+[nginx-omnibus]: https://docs.gitlab.com/omnibus/settings/
+[nginx-charts]: https://docs.gitlab.com/charts/charts/nginx/
+[nginx-source]: ../install/installation.md#9-nginx
+[unicorn-omnibus]: https://docs.gitlab.com/omnibus/settings/unicorn.html
+[unicorn-charts]: https://docs.gitlab.com/charts/charts/gitlab/unicorn/
+[unicorn-source]: ../install/installation.md#configure-it
+[gitlab-yml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/gitlab.yml.example
+[sidekiq-omnibus]: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template
+[sidekiq-charts]: https://docs.gitlab.com/charts/charts/gitlab/sidekiq/
+[gitaly-omnibus]: ../administration/gitaly/index.md
+[gitaly-charts]: https://docs.gitlab.com/charts/charts/gitlab/gitaly/
+[gitaly-source]: ../install/installation.md#install-gitaly
+[workhorse-omnibus]: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template
+[workhorse-charts]: https://docs.gitlab.com/charts/charts/gitlab/unicorn/
+[workhorse-source]: ../install/installation.md#install-gitlab-workhorse
+[shell-omnibus]: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template
+[shell-charts]: https://docs.gitlab.com/charts/charts/gitlab/gitlab-shell/
+[shell-source]: ../install/installation.md#install-gitlab-shell
+[pages-omnibus]: ../administration/pages/index.md
+[pages-charts]: https://gitlab.com/charts/gitlab/issues/37
+[pages-source]: ../install/installation.md#install-gitlab-pages
+[pages-gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/pages.md
+[registry-omnibus]: ../administration/container_registry.md#container-registry-domain-configuration
+[registry-charts]: https://docs.gitlab.com/charts/charts/registry/
+[registry-source]: ../administration/container_registry.md#enable-the-container-registry
+[registry-gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/registry.md
+[redis-omnibus]: https://docs.gitlab.com/omnibus/settings/redis.html
+[redis-charts]: https://docs.gitlab.com/charts/charts/redis/
+[redis-source]: ../install/installation.md#7-redis
+[postgres-omnibus]: https://docs.gitlab.com/omnibus/settings/database.html
+[postgres-charts]: https://github.com/helm/charts/tree/master/stable/postgresql
+[postgres-source]: ../install/installation.md#6-database
+[pgbouncer-omnibus]: ../administration/high_availability/pgbouncer.md
+[pgbouncer-charts]: https://docs.gitlab.com/charts/installation/deployment.html#postgresql
+[consul-omnibus]: ../administration/high_availability/consul.md
+[consul-charts]: https://docs.gitlab.com/charts/installation/deployment.html#postgresql
+[prometheus-omnibus]: ../administration/monitoring/prometheus/index.md
+[prometheus-charts]: https://github.com/helm/charts/tree/master/stable/prometheus
+[grafana-omnibus]: ../administration/monitoring/performance/grafana_configuration.md
+[grafana-charts]: https://github.com/helm/charts/tree/master/stable/grafana
+[sentry-omnibus]: https://docs.gitlab.com/omnibus/settings/configuration.html#error-reporting-and-logging-with-sentry
+[sentry-charts]: https://gitlab.com/charts/gitlab/issues/1319
+[jaeger-omnibus]: https://gitlab.com/gitlab-org/omnibus-gitlab/issues/4104
+[jaeger-charts]: https://gitlab.com/charts/gitlab/issues/1320
+[jaeger-source]: ../development/distributed_tracing.md#enabling-distributed-tracing
+[jaeger-gdk]: ../development/distributed_tracing.html#using-jaeger-in-the-gitlab-development-kit
+[redis-exporter-omnibus]: ../administration/monitoring/prometheus/redis_exporter.md
+[redis-exporter-charts]: https://docs.gitlab.com/charts/charts/redis/
+[postgres-exporter-omnibus]: ../administration/monitoring/prometheus/postgres_exporter.md
+[postgres-exporter-charts]: https://github.com/helm/charts/tree/master/stable/postgresql
+[pgbouncer-exporter-omnibus]: ../administration/monitoring/prometheus/pgbouncer_exporter.md
+[pgbouncer-exporter-charts]: https://docs.gitlab.com/charts/installation/deployment.html#postgresql
+[gitlab-monitor-omnibus]: ../administration/monitoring/prometheus/gitlab_monitor_exporter.md
+[gitab-monitor-charts]: https://gitlab.com/charts/gitlab/issues/319
+[node-exporter-omnibus]: ../administration/monitoring/prometheus/node_exporter.md
+[node-exporter-charts]: https://gitlab.com/charts/gitlab/issues/1332
+[mattermost-omnibus]: https://docs.gitlab.com/omnibus/gitlab-mattermost/
+[mattermost-charts]: https://docs.mattermost.com/install/install-mmte-helm-gitlab-helm.html
+[minio-omnibus]: https://min.io/download
+[minio-charts]: https://docs.gitlab.com/charts/charts/minio/
+[minio-gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/object_storage.md
+[runner-omnibus]: https://docs.gitlab.com/runner/
+[runner-charts]: https://docs.gitlab.com/runner/install/kubernetes.html
+[runner-source]: https://docs.gitlab.com/runner/
+[runner-gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/runner.md
+[database-migrations-omnibus]: https://docs.gitlab.com/omnibus/settings/database.html#disabling-automatic-database-migration
+[database-migrations-charts]: https://docs.gitlab.com/charts/charts/gitlab/migrations/
+[database-migrations-source]: ../update/upgrading_from_source.md#14-install-libs-migrations-etc
+[certificate-management-omnibus]: https://docs.gitlab.com/omnibus/settings/ssl.html
+[certificate-management-charts]: https://docs.gitlab.com/charts/installation/tls.html
+[certificate-management-source]: ../install/installation.md#using-https
+[certificate-management-gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/https.md
+[geo-omnibus]: ../administration/geo/replication/index.md#setup-instructions
+[geo-charts]: https://gitlab.com/charts/gitlab/issues/8
+[geo-gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/geo.md
+[ldap-omnibus]: ../administration/auth/ldap.md
+[ldap-charts]: https://docs.gitlab.com/charts/charts/globals.html#ldap
+[ldap-gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/ldap.md
+[outbound-email-omnibus]: https://docs.gitlab.com/omnibus/settings/smtp.html
+[outbound-email-charts]: https://docs.gitlab.com/charts/installation/command-line-options.html#outgoing-email-configuration
+[inbound-email-omnibus]: ../administration/incoming_email.md
+[inbound-email-charts]: https://docs.gitlab.com/charts/installation/command-line-options.html#incoming-email-configuration
+[elasticsearch-omnibus]: ../integration/elasticsearch.md
+[elasticsearch-charts]: ../integration/elasticsearch.md
+[elasticsearch-source]: ../integration/elasticsearch.md
+[elasticsearch-gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/elasticsearch.md
+[sentry-integration]: ../user/project/operations/error_tracking.md
+[jaeger-integration]: ../user/project/operations/tracing.md
+[managed-k8s-apps]: ../user/project/clusters/index.md#installing-applications
diff --git a/doc/development/changelog.md b/doc/development/changelog.md
index 273a7fceaf5..45b3d5a23a1 100644
--- a/doc/development/changelog.md
+++ b/doc/development/changelog.md
@@ -35,6 +35,7 @@ the `author` field. GitLab team members **should not**.
- Any user-facing change **should** have a changelog entry. Example: "GitLab now
uses system fonts for all text."
+- Any change behind a feature flag **should not** have a changelog entry. The entry should be added [in the merge request removing the feature flags](https://docs.gitlab.com/ee/development/feature_flags.html#developing-with-feature-flags).
- A fix for a regression introduced and then fixed in the same release (i.e.,
fixing a bug introduced during a monthly release candidate) **should not**
have a changelog entry.
diff --git a/doc/development/chatops_on_gitlabcom.md b/doc/development/chatops_on_gitlabcom.md
new file mode 100644
index 00000000000..c63ec53414c
--- /dev/null
+++ b/doc/development/chatops_on_gitlabcom.md
@@ -0,0 +1,21 @@
+# Chatops on GitLab.com
+
+Chatops on GitLab.com allows GitLabbers to run various automation tasks on GitLab.com using Slack.
+
+## Requesting access
+
+GitLabbers may need access to Chatops on GitLab.com for administration tasks such as:
+
+- Configuring feature flags on staging.
+- Running `EXPLAIN` queries against the GitLab.com production replica.
+
+To request access to Chatops on GitLab.com:
+
+1. Log into <https://ops.gitlab.net/users/sign_in> using the same username as for GitLab.com.
+1. Ask [anyone in the `chatops` project](https://gitlab.com/gitlab-com/chatops/project_members) to add you by running `/chatops run member add <username> gitlab-com/chatops --ops`.
+
+## See also
+
+ - [Chatops Usage](https://docs.gitlab.com/ee/ci/chatops/README.html)
+ - [Understanding EXPLAIN plans](understanding_explain_plans.md)
+ - [Feature Groups](feature_flags.md#feature-groups)
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index b1a32e0ed26..29e2aa1a581 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -23,20 +23,35 @@ one of the [Merge request coaches][team].
If you need assistance with security scans or comments, feel free to include the
Security Team (`@gitlab-com/gl-security`) in the review.
-The `danger-review` CI job will randomly pick a reviewer and a maintainer for
-each area of the codebase that your merge request seems to touch. It only makes
-recommendations - feel free to override it if you think someone else is a better
-fit!
-
Depending on the areas your merge request touches, it must be **approved** by one
or more [maintainers](https://about.gitlab.com/handbook/engineering/workflow/code-review/#maintainer):
For approvals, we use the approval functionality found in the merge request
-widget. Reviewers can add their approval by [approving additionally](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html#adding-or-removing-an-approval).
+widget. Reviewers can add their approval by [approving additionally](../user/project/merge_requests/merge_request_approvals.md#adding-or-removing-an-approval).
Getting your merge request **merged** also requires a maintainer. If it requires
more than one approval, the last maintainer to review and approve it will also merge it.
+### Reviewer roulette
+
+The `danger-review` CI job will randomly pick a reviewer and a maintainer for
+each area of the codebase that your merge request seems to touch. It only makes
+recommendations - feel free to override it if you think someone else is a better
+fit!
+
+It picks reviewers and maintainers from the list at the
+[engineering projects](https://about.gitlab.com/handbook/engineering/projects/)
+page, with these behaviours:
+
+1. It will not pick people whose [GitLab status](../user/profile/index.md#current-status)
+ contains the string 'OOO'.
+2. [Trainee maintainers](https://about.gitlab.com/handbook/engineering/workflow/code-review/#trainee-maintainer)
+ are three times as likely to be picked as other reviewers.
+3. It always picks the same reviewers and maintainers for the same
+ branch name (unless their OOO status changes, as in point 1). It
+ removes leading `ce-` and `ee-`, and trailing `-ce` and `-ee`, so
+ that it can be stable for backport branches.
+
### Approval guidelines
As described in the section on the responsibility of the maintainer below, you
@@ -132,20 +147,12 @@ If a developer who happens to also be a maintainer was involved in a merge reque
as a domain expert and/or reviewer, it is recommended that they are not also picked
as the maintainer to ultimately approve and merge it.
-Try to review in a timely manner; doing so allows everyone involved in the merge
-request to iterate faster as the context is fresh in memory. Further, this
-improves contributors' experiences significantly. Reviewers should aim to review
-within two working days from the date they were assigned the merge request. If
-you don't think you'll be able to review a merge request within that time, let
-the author know as soon as possible. When the author of the merge request has not
-heard anything after two days, a new reviewer should be assigned.
-
Maintainers should check before merging if the merge request is approved by the
required approvers.
Maintainers must check before merging if the merge request is introducing new
vulnerabilities, by inspecting the list in the Merge Request [Security
-Widget](https://docs.gitlab.com/ee/user/project/merge_requests/#security-reports-ultimate).
+Widget](../user/project/merge_requests/index.md#security-reports-ultimate).
When in doubt, a [Security Engineer][team] can be involved. The list of detected
vulnerabilities must be either empty or containing:
@@ -220,6 +227,37 @@ It is responsibility of the author of a merge request that the merge request is
Developers who have capacity can regularly check the list of [merge requests to review](https://gitlab.com/groups/gitlab-org/-/merge_requests?scope=all&utf8=%E2%9C%93&state=opened&label_name%5B%5D=ready%20for%20review) and assign any merge request they want to review.
+### Review turnaround time
+
+Since [unblocking others is always a top priority](https://about.gitlab.com/handbook/values/#global-optimization),
+reviewers are expected to review assigned merge requests in a timely manner,
+even when this may negatively impact their other tasks and priorities.
+Doing so allows everyone involved in the merge request to iterate faster as the
+context is fresh in memory, improves contributors' experiences significantly,
+and gives authors more time to address feedback and iterate on their work before
+the [feature freeze](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/PROCESS.md#feature-freeze-on-the-7th-for-the-release-on-the-22nd).
+
+A turnaround time of two working days is usually acceptable, since engineers
+will typically have other things to work on while they're waiting for review,
+but don't hesitate to ask the author if it's unclear what time frame would be
+acceptable, how urgent the review is, or how significant the blockage. Authors
+are also encouraged to provide this information up-front to reviewers, but are
+expected to be mindful of the [guidelines on when to ask for review on MRs that
+are intended to go in before the feature freeze](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/PROCESS.md#between-the-1st-and-the-7th),
+and realistic in their expectations if these were not followed.
+
+If you don't think you'll be able to review a merge request within a reasonable
+time frame, let the author know as soon as possible and try to help them find
+another reviewer or maintainer who will be able to, so that they can be unblocked
+and get on with their work quickly. Of course, if you are out of office and have
+[communicated](https://about.gitlab.com/handbook/paid-time-off/#communicating-your-time-off)
+this through your GitLab.com Status, authors are expected to realize this and
+find a different reviewer themselves.
+
+When a merge request author feels like they have been blocked for longer than
+is reasonable, they are free to remind the reviewer through Slack or assign
+another reviewer.
+
### Reviewing code
Understand why the change is necessary (fixes a bug, improves the user
@@ -248,7 +286,7 @@ experience, refactors the existing code). Then:
author has already set this option or if the merge request clearly contains a
messy commit history that is intended to be squashed.
-[squash-and-merge]: https://docs.gitlab.com/ee/user/project/merge_requests/squash_and_merge.html#squash-and-merge
+[squash-and-merge]: ../user/project/merge_requests/squash_and_merge.md#squash-and-merge
### The right balance
@@ -281,7 +319,7 @@ reviewee.
GitLab is used in a lot of places. Many users use
our [Omnibus packages](https://about.gitlab.com/installation/), but some use
the [Docker images](https://docs.gitlab.com/omnibus/docker/), some are
-[installed from source](https://docs.gitlab.com/ce/install/installation.html),
+[installed from source](../install/installation.md),
and there are other installation methods available. GitLab.com itself is a large
Enterprise Edition instance. This has some implications:
diff --git a/doc/development/contributing/index.md b/doc/development/contributing/index.md
index 8b1d014e101..59cf5014da4 100644
--- a/doc/development/contributing/index.md
+++ b/doc/development/contributing/index.md
@@ -87,7 +87,7 @@ Sometimes style guides will be followed but the code will lack structural integr
GitLab will do its best to review community contributions as quickly as possible. Specially appointed developers review community contributions daily. You may take a look at the [team page](https://about.gitlab.com/team/) for the merge request coach who specializes in the type of code you have written and mention them in the merge request. For example, if you have written some JavaScript in your code then you should mention the frontend merge request coach. If your code has multiple disciplines you may mention multiple merge request coaches.
-GitLab receives a lot of community contributions, so if your code has not been reviewed within 4 days of its initial submission feel free to re-mention the appropriate merge request coach.
+GitLab receives a lot of community contributions, so if your code has not been reviewed within two days (excluding weekend and public holidays) of its initial submission feel free to re-mention the appropriate merge request coach.
When submitting code to GitLab, you may feel that your contribution requires the aid of an external library. If your code includes an external library please provide a link to the library, as well as reasons for including it.
diff --git a/doc/development/contributing/issue_workflow.md b/doc/development/contributing/issue_workflow.md
index 827b3d7681a..0396f7ebc45 100644
--- a/doc/development/contributing/issue_workflow.md
+++ b/doc/development/contributing/issue_workflow.md
@@ -7,7 +7,7 @@ scheduling into milestones. Labelling is a task for everyone.
Most issues will have labels for at least one of the following:
- Type: ~feature, ~bug, ~customer, etc.
-- Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc.
+- Subject: ~wiki, ~"Container Registry", ~ldap, ~api, ~frontend, etc.
- Team: ~Plan, ~Manage, ~Quality, etc.
- Stage: ~"devops:plan", ~"devops:create", etc.
- Release Scoping: ~Deliverable, ~Stretch, ~"Next Patch Release"
@@ -44,7 +44,7 @@ Subject labels are labels that define what area or feature of GitLab this issue
hits. They are not always necessary, but very convenient.
Examples of subject labels are ~wiki, ~ldap, ~api,
-~issues, ~"merge requests", ~labels, and ~"container registry".
+~issues, ~"merge requests", ~labels, and ~"Container Registry".
If you are an expert in a particular area, it makes it easier to find issues to
work on. You can also subscribe to those labels to receive an email each time an
@@ -92,20 +92,21 @@ Stage labels specify which [DevOps stage][devops-stages] the issue belongs to.
The current stage labels are:
-- ~"devops:manage"
-- ~"devops:plan"
-- ~"devops:create"
-- ~"devops:verify"
-- ~"devops:package"
-- ~"devops:release"
-- ~"devops:configure"
-- ~"devops:monitor"
-- ~"devops:secure"
-- ~"devops:defend"
-- ~"devops:enablement"
-
-These labels should be mutually exclusive. If an issue belongs to multiple
-stages, the most relevant should be used.
+- ~"devops::manage"
+- ~"devops::plan"
+- ~"devops::create"
+- ~"devops::verify"
+- ~"devops::package"
+- ~"devops::release"
+- ~"devops::configure"
+- ~"devops::monitor"
+- ~"devops::secure"
+- ~"devops::defend"
+- ~"devops::growth"
+- ~"devops::enablement"
+
+These labels are [scoped labels](../../user/project/labels.md#scoped-labels-premium)
+and thus are mutually exclusive.
They differ from the [Team labels](#team-labels) because teams may work on
issues outside their stage.
@@ -121,6 +122,25 @@ The Stage labels are used to generate the [direction pages][direction-pages] aut
[devops-stages]: https://about.gitlab.com/direction/#devops-stages
[direction-pages]: https://about.gitlab.com/direction/
+## Group labels
+
+Group labels specify which [groups][structure-groups] the issue belongs to.
+
+Examples include:
+
+- ~"group::control"
+- ~"group::editor"
+
+These labels are [scoped labels](../../user/project/labels.md#scoped-labels-premium)
+and thus are mutually exclusive.
+
+Groups are nested beneath a particular stage, so only one stage label and one group label
+can be applied to a single issue. You can find the groups listed in the
+[Product Categories pages][product-categories].
+
+[structure-groups]: https://about.gitlab.com/company/team/structure/#groups
+[product-categories]: https://about.gitlab.com/handbook/product/categories/
+
## Release Scoping labels
Release Scoping labels help us clearly communicate expectations of the work for the
@@ -143,9 +163,9 @@ or ~"Stretch". Any open issue for a previous milestone should be labeled
Priority labels help us define the time a ~bug fix should be completed. Priority determines how quickly the defect turnaround time must be.
If there are multiple defects, the priority decides which defect has to be fixed immediately versus later.
-This label documents the planned timeline & urgency which is used to measure against our actual SLA on delivering ~bug fixes.
+This label documents the planned timeline & urgency which is used to measure against our target SLO on delivering ~bug fixes.
-| Label | Meaning | Defect SLA (applies only to ~bug and ~security defects) |
+| Label | Meaning | Target SLO (applies only to ~bug and ~security defects) |
|-------|-----------------|----------------------------------------------------------------------------|
| ~P1 | Urgent Priority | The current release + potentially immediate hotfix to GitLab.com (30 days) |
| ~P2 | High Priority | The next release (60 days) |
@@ -340,13 +360,14 @@ addressed.
In order to track things that can be improved in GitLab's codebase,
we use the ~"technical debt" label in [GitLab's issue tracker][ce-tracker].
-For user experience improvements, we use the ~"UX debt" label.
+For missed user experience requirements, we use the ~"UX debt" label.
These labels should be added to issues that describe things that can be improved,
shortcuts that have been taken, features that need additional attention, and all
other things that have been left behind due to high velocity of development.
For example, code that needs refactoring should use the ~"technical debt" label,
-user experience refinements should use the ~"UX debt" label.
+something that didn't ship according to our Design System guidelines should
+use the ~"UX debt" label.
Everyone can create an issue, though you may need to ask for adding a specific
label, if you do not have permissions to do it by yourself. Additional labels
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index 5e310092a6e..8a4aa5dfa7f 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -155,7 +155,7 @@ the contribution acceptance criteria below:
restarting the failing CI job, rebasing from master to bring in updates that
may resolve the failure, or if it has not been fixed yet, ask a developer to
help you fix the test.
-1. The MR initially contains a a few logically organized commits.
+1. The MR initially contains a few logically organized commits.
1. The changes can merge without problems. If not, you should rebase if you're the
only one working on your feature branch, otherwise merge `master`.
1. Only one specific issue is fixed or one specific feature is implemented. Do not
diff --git a/doc/development/database_debugging.md b/doc/development/database_debugging.md
index f00c5ccb9e9..68d33a9d8e0 100644
--- a/doc/development/database_debugging.md
+++ b/doc/development/database_debugging.md
@@ -56,7 +56,7 @@ bundle exec rails db RAILS_ENV=development
### `ActiveRecord::PendingMigrationError` with Spring
-When running specs with the [Spring preloader](./rake_tasks.md#speed-up-tests-rake-tasks-and-migrations),
+When running specs with the [Spring preloader](rake_tasks.md#speed-up-tests-rake-tasks-and-migrations),
the test database can get into a corrupted state. Trying to run the migration or
dropping/resetting the test database has no effect.
diff --git a/doc/development/distributed_tracing.md b/doc/development/distributed_tracing.md
index 038e3de10d7..bfce7488a8d 100644
--- a/doc/development/distributed_tracing.md
+++ b/doc/development/distributed_tracing.md
@@ -34,7 +34,7 @@ GITLAB_TRACING=opentracing://<driver>?<param_name>=<param_value>&<param_name_2>=
In this example, we have the following hypothetical values:
- `driver`: the driver. [GitLab supports
- `jaeger`](https://docs.gitlab.com/ee/user/project/operations/tracing.html). In future, other
+ `jaeger`](../user/project/operations/tracing.md). In future, other
tracing implementations may also be supported.
- `param_name`, `param_value`: these are driver specific configuration values. Configuration
parameters for Jaeger are documented [further on in this
diff --git a/doc/development/documentation/feature-change-workflow.md b/doc/development/documentation/feature-change-workflow.md
index 1f68b6a6a70..ca29353ecbe 100644
--- a/doc/development/documentation/feature-change-workflow.md
+++ b/doc/development/documentation/feature-change-workflow.md
@@ -86,7 +86,7 @@ Everyone is encouraged to draft the requirements in the issue, but a product man
do the following:
- When the issue is assigned a release milestone, review and update the Documentation details.
-- By the kickoff, finalizie the Documentation details.
+- By the kickoff, finalize the Documentation details.
### Developer and maintainer roles
@@ -117,7 +117,7 @@ Follow the process below unless otherwise agreed with the product manager and te
#### Reviews and merging
-All reviewers can help ensure accuracy, clarity, completeness, and adherence to the plans in the issue, as well as the [Documentation Guidelines](https://docs.gitlab.com/ee/development/documentation/) and [Style Guide](https://docs.gitlab.com/ee/development/documentation/styleguide.html).
+All reviewers can help ensure accuracy, clarity, completeness, and adherence to the plans in the issue, as well as the [Documentation Guidelines](index.md) and [Style Guide](styleguide.md).
- **Prior to merging**, documentation changes committed by the developer must be reviewed by:
@@ -136,7 +136,7 @@ All reviewers can help ensure accuracy, clarity, completeness, and adherence to
1. **The maintainer** who is assigned to merge the MR, to verify clarity, completeness, and quality, to the best of their ability.
- Upon merging, if a technical writer review has not been performed and there is not yet a linked issue for a follow-up review, the maintainer should [create an issue using the Doc Review template](https://gitlab.com/gitlab-org/gitlab-ce/issues/new?issuable_template=Doc%20Review), link it from the MR, and
- mention the original MR author in the new issue. Alternatively, the mainitainer can ask the MR author to create and link this issue before the MR is merged.
+ mention the original MR author in the new issue. Alternatively, the maintainer can ask the MR author to create and link this issue before the MR is merged.
- After merging, documentation changes are reviewed by:
@@ -157,14 +157,14 @@ All reviewers can help ensure accuracy, clarity, completeness, and adherence to
#### Collaboration
By default, the developer will work on documentation changes independently, but
-the developer, PM, or technicial writer can propose a broader collaboration for
+the developer, PM, or technical writer can propose a broader collaboration for
any given issue.
Additionally, technical writers are available for questions at any time.
#### Review
-- Techncial writers provide non-blocking reviews of all documentation changes,
+- Technical writers provide non-blocking reviews of all documentation changes,
before or after the change is merged. However, if the docs are ready in the MR while
there's time before the freeze, the technical writer's review can commence early, on request.
- The technical writer will confirm that the doc is clear, grammatically correct,
@@ -173,7 +173,7 @@ Additionally, technical writers are available for questions at any time.
the developer and code reviewer should have already made a good-faith effort to ensure:
- Clarity.
- Adherence to the plans and goals in the issue.
- - Location (make sure the docs are in the correct directorkes and has the correct name).
+ - Location (make sure the docs are in the correct directories and has the correct name).
- Syntax, typos, and broken links.
- Improvements to the content.
- Accordance with the [Documentation Style Guide](styleguide.md), and [Structure and Template](structure.md) doc.
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index 3a6f4bd8ed2..c7fa40af930 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -50,9 +50,63 @@ Adhere to the [Documentation Style Guide](styleguide.md). If a style standard is
## Folder structure and files
-Beyond the top-level directories under /doc, which mainly pertain to audiences (`user`, `administration`, `development`), we organize by product area and subject, not type.
+See the [Structure](styleguide.md#structure) section of the [Documentation Style Guide](styleguide.md).
-For complete details, see the [Content](styleguide.md#content) section of the [Documentation Style Guide](styleguide.md).
+## Single codebase
+
+We currently maintain two sets of docs: one in the
+[gitlab-ce](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc) repo and
+one in [gitlab-ee](https://gitlab.com/gitlab-org/gitlab-ee/tree/master/doc).
+They are similar, and most pages are identical, but they are different repositories.
+With the single codebase effort, we want to make those two sets identical, so when the
+time comes to have only one codebase, we'll be ready.
+
+Here are some links to get you up to speed with the current effort:
+
+- [CE/EE codebases blueprint](https://about.gitlab.com/handbook/engineering/infrastructure/blueprint/ce-ee-codebases/)
+- [CE/EE codebases merge design](https://about.gitlab.com/handbook/engineering/infrastructure/design/merge-ce-ee-codebases/)
+- [Single docs codebase epic](https://gitlab.com/groups/gitlab-org/-/epics/199)
+- [Issue board of related issues](https://gitlab.com/groups/gitlab-org/-/boards/981090?&label_name[]=Documentation&label_name[]=single%20codebase)
+- [Related merge requests](https://gitlab.com/groups/gitlab-org/-/merge_requests?scope=all&utf8=%E2%9C%93&state=all&label_name[]=Documentation&label_name[]=single%20codebase)
+- [Visualize the existing diffs](https://leipert-projects.gitlab.io/is-gitlab-pretty-yet/diff/?search=%5Edoc)
+
+### CE first
+
+After a given documentation path is aligned across CE and EE, all merge requests
+affecting that path must be submitted to CE, regardless of the content it has.
+This means that:
+
+* For **EE-only docs changes**, you only have to submit a CE MR.
+* For **EE-only features** that touch both the code and the docs, you have to submit
+an EE MR containing all changes, and a CE MR containing only the docs changes
+and without a changelog entry.
+
+This might seem like a duplicate effort, but it's only for the short term.
+A list of the already aligned docs can be found in
+[the epic description](https://gitlab.com/groups/gitlab-org/-/epics/199#ee-specific-lines-check).
+
+Since the docs will be combined, it's crucial to add the relevant
+[product badges](styleguide.md#product-badges) for all EE documentation, so that
+we can discern which features belong to which tier.
+
+### EE specific lines check
+
+There's a special test in place
+([`ee_specific_check.rb`](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/scripts/ee_specific_check/ee_specific_check.rb)),
+which, among others, checks and prevents creating/editing new files and directories
+in EE under `doc/`.
+
+We have a long list of documentation paths that are either whitelisted or not.
+Paths in the whitelist (not commented out) will not be subject to the test,
+which means you are allowed to create/change docs content in EE for the time
+being. The goal is to not have any doc whitelisted.
+
+At the time of this writing, the only items left to be aligned are the API docs:
+
+- `doc/api/*` ([issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/60045) / [merge request](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27491))
+
+Eventually, once all docs are aligned, we'll remove any doc reference from that
+script, so it catches everything.
## Changing document location
@@ -417,7 +471,7 @@ If you want to know the in-depth details, here's what's really happening:
The following GitLab features are used among others:
- [Manual actions](../../ci/yaml/README.md#whenmanual)
-- [Multi project pipelines](https://docs.gitlab.com/ee/ci/multi_project_pipeline_graphs.html)
+- [Multi project pipelines](../../ci/multi_project_pipeline_graphs.md)
- [Review Apps](../../ci/review_apps/index.md)
- [Artifacts](../../ci/yaml/README.md#artifacts)
- [Specific Runner](../../ci/runners/README.md#locking-a-specific-runner-from-being-enabled-for-other-projects)
@@ -440,6 +494,10 @@ Currently, the following tests are in place:
As CE is merged into EE once a day, it's important to avoid merge conflicts.
Submitting an EE-equivalent merge request cherry-picking all commits from CE to EE is
essential to avoid them.
+1. [`ee-files-location-check`/`ee-specific-lines-check`](#ee-specific-lines-check) (runs on EE only):
+ This test ensures that no new files/directories are created/changed in EE.
+ All docs should be submitted in CE instead, regardless the tier they are on.
+ This is for the [single codebase](#single-codebase) effort.
1. In a full pipeline, tests for [`/help`](#gitlab-help-tests).
### Linting
diff --git a/doc/development/documentation/structure.md b/doc/development/documentation/structure.md
index 95b5fcd99a1..fe676efa94d 100644
--- a/doc/development/documentation/structure.md
+++ b/doc/development/documentation/structure.md
@@ -77,8 +77,8 @@ for use (e.g. variations on the main use case), but if that's not applicable, th
Examples of use cases on feature pages:
- CE and EE: [Issues](../../user/project/issues/index.md#use-cases)
- CE and EE: [Merge Requests](../../user/project/merge_requests/index.md)
-- EE-only: [Geo](https://docs.gitlab.com/ee/administration/geo/replication/index.html)
-- EE-only: [Jenkins integration](https://docs.gitlab.com/ee/integration/jenkins.html)
+- EE-only: [Geo](../../administration/geo/replication/index.md)
+- EE-only: [Jenkins integration](../../integration/jenkins.md)
## Requirements
@@ -121,8 +121,8 @@ but commented out to help encourage others to add to it in the future. -->
Notes:
-- (1): Apply the [tier badges](https://docs.gitlab.com/ee/development/documentation/styleguide.html#product-badges) accordingly
-- (2): Apply the correct format for the [GitLab version introducing the feature](https://docs.gitlab.com/ee/development/documentation/styleguide.html#gitlab-versions-and-tiers)
+- (1): Apply the [tier badges](styleguide.md#product-badges) accordingly
+- (2): Apply the correct format for the [GitLab version introducing the feature](styleguide.md#gitlab-versions-and-tiers)
```
## Help and feedback section
diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md
index d16a8243def..5caca846cc9 100644
--- a/doc/development/documentation/styleguide.md
+++ b/doc/development/documentation/styleguide.md
@@ -6,19 +6,16 @@ description: 'Writing styles, markup, formatting, and other standards for GitLab
This document defines the standards for GitLab's documentation content and files.
-For broader information about the documentation, see the [Documentation guidelines](index.md).
+For broader information about the documentation, see the [Documentation guidelines](index.md).
For programmatic help adhering to the guidelines, see [linting](index.md#linting).
See the GitLab handbook for further [writing style guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines)
that apply to all GitLab content, not just documentation.
-## Content
+## Documentation is the single source of truth (SSOT)
-These guidelines help toward the goal of having every user's search of documentation
-yield a useful result, and ensuring content is consistent, helpful, and easy to consume.
-
-### Single source of truth (SSOT) on the GitLab product
+### Why a single source of truth
The documentation is the SSOT for all information related to the implementation, usage, and troubleshooting of GitLab products and features. It evolves continually, in keeping with new products and features, and with improvements for clarity, accuracy, and completeness.
@@ -26,31 +23,43 @@ This policy prevents information silos, ensuring that it remains easy to find in
It also informs decisions about the kinds of content we include in our documentation.
-### All helpful information
+The documentation is a continually evolving SSOT for all information related to the implementation, usage, and troubleshooting of GitLab products and features.
+
+### All information
Include problem-solving actions that may address rare cases or be considered 'risky', so long as proper context is provided in the form of fully detailed warnings and caveats. This kind of content should be included as it could be helpful to others and, when properly explained, its benefits outweigh the risks. If you think you have found an exception to this rule, contact the Technical Writing team.
-### All helpful media types and sources
+We will add all troubleshooting information to the documentation, no matter how unlikely a user is to encounter a situation.
+For the Troubleshooting sections, people in GitLab Support can merge additions themselves.
+
+### All media types
Include any media types/sources if the content is relevant to readers. You can freely include or link presentations, diagrams, videos, etc.; no matter who it was originally composed for, if it is helpful to any of our audiences, we can include it.
- If you use an image that has a separate source file (for example, a vector or diagram format), link the image to the source file so that it may be reused or updated by anyone.
- Do not copy and paste content from other sources unless it is a limited quotation with the source cited. Typically it is better to either rephrase relevant information in your own words or link out to the other source.
-### Markdown
+### No special types
-All GitLab documentation is written using [Markdown](https://en.wikipedia.org/wiki/Markdown).
+In the software industry, it is a best practice to organize documentatioin in different types. For example, [Divio recommends](https://www.divio.com/blog/documentation/):
-The [documentation website](https://docs.gitlab.com) uses GitLab Kramdown as its Markdown rendering engine. For a complete Kramdown reference, see the [GitLab Markdown Kramdown Guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/).
+1. Tutorials
+2. How-to guides
+3. Explanation
+4. Reference (for example, a glossary)
-The [`gitlab-kramdown`](https://gitlab.com/gitlab-org/gitlab_kramdown)
-Ruby gem will support all [GFM markup](../../user/markdown.md) in the future. That is,
-all markup that is supported for display in the GitLab application itself. For now,
-use regular Markdown markup, following the rules in the linked style guide.
+At GitLab, we have so many product changes in our monthly releases that we can't afford to continually update multiple types of information.
+If we have multiple types, the information will become outdated. Therefore, we have a [single template](structure.md) for documentation.
-Note that Kramdown-specific markup (e.g., `{:.class}`) will not render properly on GitLab instances under [`/help`](index.md#gitlab-help).
+We currently do not distinguish specific document types, although we are open to reconsidering this policy
+once the documentation has reached a future stage of maturity and quality. If you are reading this, then despite our
+continual improvement efforts, that point hasn't been reached.
-## Structure
+### Link instead of summarize
+
+There is a temptation to summarize the information on another page.
+This will cause the information to live in two places.
+Instead, link to the SSOT and explain why it is important to consume the information.
### Organize by topic, not by type
@@ -63,6 +72,40 @@ it difficult to browse for the information you need and difficult to maintain up
Instead, organize content by its subject (e.g. everything related to CI goes together)
and cross-link between any related content.
+### Docs-first methodology
+
+We employ a **docs-first methodology** to help ensure that the docs remain a complete and trusted resource, and to make communicating about the use of GitLab more efficient.
+
+* If the answer to a question exists in documentation, share the link to the docs instead of rephrasing the information.
+* When you encounter new information not available in GitLab’s documentation (for example, when working on a support case or testing a feature), your first step should be to create a merge request to add this information to the docs. You can then share the MR in order to communicate this information.
+
+New information that would be useful toward the future usage or troubleshooting of GitLab should not be written directly in a forum or other messaging system, but added to a docs MR and then referenced, as described above. Note that among any other doc changes, you can always add a Troubleshooting section to a doc if none exists, or un-comment and use the placeholder Troubleshooting section included as part of our [doc template](structure.md#template-for-new-docs), if present.
+
+The more we reflexively add useful information to the docs, the more (and more successfully) the docs will be used to efficiently accomplish tasks and solve problems.
+
+If you have questions when considering, authoring, or editing docs, ask the Technical Writing team on Slack in `#docs` or in GitLab by mentioning the writer for the applicable [DevOps stage](https://about.gitlab.com/handbook/product/categories/#devops-stages). Otherwise, forge ahead with your best effort. It does not need to be perfect; the team is happy to review and improve upon your content. Please review the [Documentation guidelines](index.md) before you begin your first documentation MR.
+
+Having a knowledge base is any form that is separate from the documentation would be against the docs-first methodology because the content would overlap with the documentation.
+
+## Markdown
+
+All GitLab documentation is written using [Markdown](https://en.wikipedia.org/wiki/Markdown).
+
+The [documentation website](https://docs.gitlab.com) uses GitLab Kramdown as its Markdown rendering engine. For a complete Kramdown reference, see the [GitLab Markdown Kramdown Guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/).
+
+The [`gitlab-kramdown`](https://gitlab.com/gitlab-org/gitlab_kramdown)
+Ruby gem will support all [GFM markup](../../user/markdown.md) in the future. That is,
+all markup that is supported for display in the GitLab application itself. For now,
+use regular Markdown markup, following the rules in the linked style guide.
+
+Note that Kramdown-specific markup (e.g., `{:.class}`) will not render properly on GitLab instances under [`/help`](index.md#gitlab-help).
+
+## Structure
+
+### Organize by topic, not by type
+
+Because we want documentation to be a SSOT, we should [organize by topic, not by type](#organize-by-topic-not-by-type).
+
### Folder structure overview
The documentation is separated by top-level audience folders [`user`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/user),
@@ -133,7 +176,7 @@ changes, regardless, and can move content if there is a better place for it.
### Avoid duplication
-Do not include the same information in multiple places. Instead, choose one single-source-of-truth location and link from other relevant locations.
+Do not include the same information in multiple places. [Link to a SSOT instead.](#link-instead-of-summarize)
### References across documents
@@ -319,16 +362,23 @@ For other punctuation rules, please refer to the
E.g., instead of writing something like `Read more about GitLab Issue Boards [here](LINK)`,
write `Read more about [GitLab Issue Boards](LINK)`.
-### Links to confidential issues
+### Links requiring permissions
+
+Don't link directly to:
+
+- [Confidential issues](../../user/project/issues/confidential_issues.md).
+- Project features that require [special permissions](../../user/permissions.md) to view.
-Don't link directly to [confidential issues](../../user/project/issues/confidential_issues.md). These will fail for:
+These will fail for:
- Those without sufficient permissions.
- Automated link checkers.
Instead:
-- Mention in the text that the information is contained in a confidential issue. This will reduce confusion.
+- To reduce confusion, mention in the text that the information is either:
+ - Contained in a confidential issue.
+ - Requires special permission to a project to view.
- Provide a link in back ticks (`` ` ``) so that those with access to the issue can easily navigate to it.
Example:
@@ -554,41 +604,49 @@ The following are recommended verbs for specific uses.
## GitLab versions and tiers
-- Every piece of documentation that comes with a new feature should declare the
- GitLab version that feature got introduced. Right below the heading add a
- blockquote:
+Tagged and released versions of GitLab documentation are available:
+
+- In the [documentation archives](https://docs.gitlab.com/archives/).
+- At the `/help` URL for any GitLab installation.
+
+The version introducing a new feature is added to the top of the topic in the documentation to provide
+a helpful link back to how the feature was developed.
+
+### Text for documentation requiring version text
+
+- For features that need to declare the GitLab version that the feature was introduced. Text similar
+ to the following should be added immediately below the heading as a blockquote:
```md
- > Introduced in GitLab 8.3.
+ > Introduced in GitLab 11.3.
```
-- Whenever possible, every feature should have a link to the issue, MR or epic
- (in that order) that introduced it. The above quote would be then transformed to:
+- Whenever possible, version text should have a link to the issue, merge request, or epic that introduced the feature.
+ An issue is preferred over a merge request, and a merge request is preferred over an epic. For example:
```md
- > [Introduced](<link-to-issue>) in GitLab 8.3.
+ > [Introduced](<link-to-issue>) in GitLab 11.3.
```
-- If the feature is only available in GitLab Enterprise Edition, don't forget to mention
+- If the feature is only available in GitLab Enterprise Edition, mention
the [paid tier](https://about.gitlab.com/handbook/marketing/product-marketing/#tiers)
the feature is available in:
```md
- > [Introduced](<link-to-issue>) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3.
+ > [Introduced](<link-to-issue>) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.3.
```
-### Early versions of EE
-
-If the feature was created before GitLab 9.2 (before [different EE tiers were introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1851)):
+### Removing version text
-- Declare it as "Introduced in GitLab Enterprise Edition X.Y".
-- Note which tier the feature is available in.
+Over time, version text will reference a progressively older version of GitLab. In cases where version text
+refers to versions of GitLab four or more major versions back, consider removing the text.
-For example:
+For example, if the current major version is 11.x, version text referencing versions of GitLab 7.x
+and older are candidates for removal.
-```md
-> [Introduced](<link-to-issue>) in GitLab Enterprise Edition 9.0. Available in [GitLab Premium](https://about.gitlab.com/pricing/).
-```
+NOTE: **Note:**
+This guidance applies to any text that mentions a GitLab version, not just "Introduced in... " text.
+Other text includes deprecation notices and version-specific how-to information.
## Product badges
@@ -608,6 +666,12 @@ keyword "only":
- For GitLab Premium: `**[PREMIUM ONLY]**`.
- For GitLab Ultimate: `**[ULTIMATE ONLY]**`.
+For GitLab.com only tiers (when the feature is not available for self-hosted instances):
+
+- For GitLab Bronze and higher tiers: `**[BRONZE ONLY]**`.
+- For GitLab Silver and higher tiers: `**[SILVER ONLY]**`.
+- For GitLab Gold: `**[GOLD ONLY]**`.
+
The tier should be ideally added to headers, so that the full badge will be displayed.
However, it can be also mentioned from paragraphs, list items, and table cells. For these cases,
the tier mention will be represented by an orange question mark that will show the tiers on hover.
@@ -616,6 +680,7 @@ For example:
- `**[STARTER]**` renders as **[STARTER]**
- `**[STARTER ONLY]**` renders as **[STARTER ONLY]**
+- `**[SILVER ONLY]**` renders as **[SILVER ONLY]**
The absence of tiers' mentions mean that the feature is available in GitLab Core,
GitLab.com Free, and all higher tiers.
diff --git a/doc/development/ee_features.md b/doc/development/ee_features.md
index c5a1d915be6..cca52706ddc 100644
--- a/doc/development/ee_features.md
+++ b/doc/development/ee_features.md
@@ -446,6 +446,19 @@ The disadvantage of this:
port `render_if_exists` to CE.
- If we have typos in the partial name, it would be silently ignored.
+
+##### Caveats
+
+The `render_if_exists` view path argument must be relative to `app/views/` and `ee/app/views`.
+Resolving an EE template path that is relative to the CE view path will not work.
+
+```haml
+- # app/views/projects/index.html.haml
+
+= render_if_exists 'button' # Will not render `ee/app/views/projects/_button` and will quietly fail
+= render_if_exists 'projects/button' # Will render `ee/app/views/projects/_button`
+```
+
#### Using `render_ce`
For `render` and `render_if_exists`, they search for the EE partial first,
@@ -535,40 +548,56 @@ due to `prepend`, but Grape is complex internally and we couldn't easily do
that, so we'll follow regular object-oriented practices that we define the
interface first here.
-For example, suppose we have a few more optional params for EE, given this CE
-API code:
+For example, suppose we have a few more optional params for EE. We can move the
+params out of the `Grape::API` class to a helper module, so we can `prepend` it
+before it would be used in the class.
```ruby
module API
- class MergeRequests < Grape::API
- # EE::API::MergeRequests would override the following helpers
- helpers do
- params :optional_params_ee do
+ class Projects < Grape::API
+ helpers Helpers::ProjectsHelpers
+ end
+end
+```
+
+Given this CE API `params`:
+
+```ruby
+module API
+ module Helpers
+ module ProjectsHelpers
+ extend ActiveSupport::Concern
+ extend Grape::API::Helpers
+
+ params :optional_project_params_ce do
+ # CE specific params go here...
end
- end
- params :optional_params do
- # CE specific params go here...
+ params :optional_project_params_ee do
+ end
- use :optional_params_ee
+ params :optional_project_params do
+ use :optional_project_params_ce
+ use :optional_project_params_ee
+ end
end
end
end
-API::MergeRequests.prepend(EE::API::MergeRequests)
+API::Helpers::ProjectsHelpers.prepend(EE::API::Helpers::ProjectsHelpers)
```
-And then we could override it in EE module:
+We could override it in EE module:
```ruby
module EE
module API
- module MergeRequests
- extend ActiveSupport::Concern
+ module Helpers
+ module ProjectsHelpers
+ extend ActiveSupport::Concern
- prepended do
- helpers do
- params :optional_params_ee do
+ prepended do
+ params :optional_project_params_ee do
# EE specific params go here...
end
end
@@ -578,9 +607,6 @@ module EE
end
```
-This way, the only difference between CE and EE for that API file would be
-`prepend EE::API::MergeRequests`.
-
#### EE helpers
To make it easy for an EE module to override the CE helpers, we need to define
@@ -880,7 +906,7 @@ import bundle from 'ee/protected_branches/protected_branches_bundle.js';
import bundle from 'ee_else_ce/protected_branches/protected_branches_bundle.js';
```
-See the frontend guide [performance section](./fe_guide/performance.md) for
+See the frontend guide [performance section](fe_guide/performance.md) for
information on managing page-specific javascript within EE.
@@ -888,7 +914,7 @@ information on managing page-specific javascript within EE.
### script tag
#### Child Component only used in EE
-To seperate Vue template differences we should [async import the components](https://vuejs.org/v2/guide/components-dynamic-async.html#Async-Components).
+To separate Vue template differences we should [async import the components](https://vuejs.org/v2/guide/components-dynamic-async.html#Async-Components).
Doing this allows for us to load the correct component in EE whilst in CE
we can load a empty component that renders nothing. This code **should**
@@ -911,7 +937,7 @@ export default {
```
#### For JS code that is EE only, like props, computed properties, methods, etc, we will keep the current approach
- - Since we [can't async load a mixin](https://github.com/vuejs/vue-loader/issues/418#issuecomment-254032223) we will use the [`ee_else_ce`](https://docs.gitlab.com/ee/development/ee_features.html#javascript-code-in-assetsjavascripts) alias we already have for webpack.
+ - Since we [can't async load a mixin](https://github.com/vuejs/vue-loader/issues/418#issuecomment-254032223) we will use the [`ee_else_ce`](../development/ee_features.md#javascript-code-in-assetsjavascripts) alias we already have for webpack.
- This means all the EE specific props, computed properties, methods, etc that are EE only should be in a mixin in the `ee/` folder and we need to create a CE counterpart of the mixin
##### Example:
@@ -922,7 +948,7 @@ import mixin from 'ee_else_ce/path/mixin';
mixins: [mixin]
}
```
-
+
- Computed Properties/methods and getters only used in the child import still need a counterpart in CE
- For store modules, we will need a CE counterpart too.
@@ -933,47 +959,27 @@ import mixin from 'ee_else_ce/path/mixin';
- Since we are using the async loading to check which component to load, we'd still use the component's name, check [this example](#child-component-only-used-in-ee).
* **EE extra HTML**
- - For the templates that have extra HTML in EE we will use the `ifEE` mixin with the `v-if` directive.
- - You can either use the `template` tag as a wrapper or directly in the element, if there is only one element to be rendered in EE:
-
-```html
- <template v-if="ifEE">
- <p>Several</p>
- <p>non wrapper</p>
- <p>elements</p>
- <p>that are rendered</p>
- <p>in EE only</p>
- </template>
-```
-
-
-```html
- <ul v-if="ifEE">
- <li>One wrapped</li>
- <li>element</li>
- <li>that is rendered</li>
- <li>in EE only</li>
- </template>
-```
+ - For the templates that have extra HTML in EE we should move it into a new component and use the `ee_else_ce` dynamic import
### Non Vue Files
For regular JS files, the approach is similar.
-1. We will keep using the [`ee_else_ce`](https://docs.gitlab.com/ee/development/ee_features.html#javascript-code-in-assetsjavascripts) helper, this means that EE only code should be inside the `ee/` folder.
+1. We will keep using the [`ee_else_ce`](../development/ee_features.md#javascript-code-in-assetsjavascripts) helper, this means that EE only code should be inside the `ee/` folder.
1. An EE file should be created with the EE only code, and it should extend the CE counterpart.
-1. For code inside functions that can't be extended, we will use an `if` statement with the `ifEE` helper
+ 1. For code inside functions that can't be extended, the code should be moved into a new file and we should use `ee_else_ce` helper:
##### Example:
```javascript
-import { ifEE } from '~/lib/utils/common_utils'
-if (ifEE) {
- $('.js-import-git-toggle-button').on('click', () => {
- const $projectMirror = $('#project_mirror');
+ import eeCode from 'ee_else_ce/ee_code';
- $projectMirror.attr('disabled', !$projectMirror.attr('disabled'));
- });
-}
+ function test() {
+ const test = 'a';
+
+ eeCode();
+
+ return test;
+ }
```
## SCSS code in `assets/stylesheets`
diff --git a/doc/development/elasticsearch.md b/doc/development/elasticsearch.md
new file mode 100644
index 00000000000..8b0f4f02d19
--- /dev/null
+++ b/doc/development/elasticsearch.md
@@ -0,0 +1,166 @@
+# Elasticsearch knowledge **[STARTER ONLY]**
+
+This area is to maintain a compendium of useful information when working with elasticsearch.
+
+Information on how to enable ElasticSearch and perform the initial indexing is kept in ../integration/elasticsearch.md#enabling-elasticsearch
+
+## Initial installation on OS X
+
+It is recommended to use the Docker image. After installing docker you can immediately spin up an instance with
+
+```
+docker run --name elastic56 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:5.6.12
+```
+
+and use `docker stop elastic56` and `docker start elastic56` to stop/start it.
+
+### Installing on the host
+
+We currently only support Elasticsearch [5.6 to 6.x](../integration/elasticsearch.md#version-requirements)
+
+Version 5.6 is available on homebrew and is the recommended version to use in order to test compatibility.
+
+```
+brew install elasticsearch@5.6
+```
+
+There is no need to install any plugins
+
+## New repo indexer (beta)
+
+If you're interested on working with the new beta repo indexer, all you need to do is:
+
+- git clone git@gitlab.com:gitlab-org/gitlab-elasticsearch-indexer.git
+- make
+- make install
+
+this adds `gitlab-elasticsearch-indexer` to `$GOPATH/bin`, please make sure that is in your `$PATH`. After that GitLab will find it and you'll be able to enable it in the admin settings area.
+
+**note:** `make` will not recompile the executable unless you do `make clean` beforehand
+
+## Helpful rake tasks
+
+- `gitlab:elastic:test:index_size`: Tells you how much space the current index is using, as well as how many documents are in the index.
+- `gitlab:elastic:test:index_size_change`: Outputs index size, reindexes, and outputs index size again. Useful when testing improvements to indexing size.
+
+Additionally, if you need large repos or multiple forks for testing, please consider [following these instructions](rake_tasks.md#extra-project-seed-options)
+
+## How does it work?
+
+The ElasticSearch integration depends on an external indexer. We ship a [ruby indexer](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/bin/elastic_repo_indexer) by default but are also working on an [indexer written in Go](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer). The user must trigger the initial indexing via a rake task, but after this is done GitLab itself will trigger reindexing when required via `after_` callbacks on create, update, and destroy that are inherited from [/ee/app/models/concerns/elastic/application_search.rb](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/app/models/concerns/elastic/application_search.rb).
+
+All indexing after the initial one is done via `ElasticIndexerWorker` (sidekiq jobs).
+
+Search queries are generated by the concerns found in [ee/app/models/concerns/elastic](https://gitlab.com/gitlab-org/gitlab-ee/tree/master/ee/app/models/concerns/elastic). These concerns are also in charge of access control, and have been a historic source of security bugs so please pay close attention to them!
+
+## Existing Analyzers/Tokenizers/Filters
+These are all defined in https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/elasticsearch/git/model.rb
+
+### Analyzers
+#### `path_analyzer`
+Used when indexing blobs' paths. Uses the `path_tokenizer` and the `lowercase` and `asciifolding` filters.
+
+Please see the `path_tokenizer` explanation below for an example.
+
+#### `sha_analyzer`
+Used in blobs and commits. Uses the `sha_tokenizer` and the `lowercase` and `asciifolding` filters.
+
+Please see the `sha_tokenizer` explanation later below for an example.
+
+#### `code_analyzer`
+Used when indexing a blob's filename and content. Uses the `whitespace` tokenizer and the filters: `code`, `edgeNGram_filter`, `lowercase`, and `asciifolding`
+
+The `whitespace` tokenizer was selected in order to have more control over how tokens are split. For example the string `Foo::bar(4)` needs to generate tokens like `Foo` and `bar(4)` in order to be properly searched.
+
+Please see the `code` filter for an explanation on how tokens are split.
+
+#### `code_search_analyzer`
+Not directly used for indexing, but rather used to transform a search input. Uses the `whitespace` tokenizer and the `lowercase` and `asciifolding` filters.
+
+### Tokenizers
+#### `sha_tokenizer`
+This is a custom tokenizer that uses the [`edgeNGram` tokenizer](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/analysis-edgengram-tokenizer.html) to allow SHAs to be searcheable by any sub-set of it (minimum of 5 chars).
+
+example:
+
+`240c29dc7e` becomes:
+- `240c2`
+- `240c29`
+- `240c29d`
+- `240c29dc`
+- `240c29dc7`
+- `240c29dc7e`
+
+#### `path_tokenizer`
+This is a custom tokenizer that uses the [`path_hierarchy` tokenizer](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/analysis-pathhierarchy-tokenizer.html) with `reverse: true` in order to allow searches to find paths no matter how much or how little of the path is given as input.
+
+example:
+
+`'/some/path/application.js'` becomes:
+- `'/some/path/application.js'`
+- `'some/path/application.js'`
+- `'path/application.js'`
+- `'application.js'`
+
+### Filters
+#### `code`
+Uses a [Pattern Capture token filter](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/analysis-pattern-capture-tokenfilter.html) to split tokens into more easily searched versions of themselves.
+
+Patterns:
+- `"(\\p{Ll}+|\\p{Lu}\\p{Ll}+|\\p{Lu}+)"`: captures CamelCased and lowedCameCased strings as separate tokens
+- `"(\\d+)"`: extracts digits
+- `"(?=([\\p{Lu}]+[\\p{L}]+))"`: captures CamelCased strings recursively. Ex: `ThisIsATest` => `[ThisIsATest, IsATest, ATest, Test]`
+- `'"((?:\\"|[^"]|\\")*)"'`: captures terms inside quotes, removing the quotes
+- `"'((?:\\'|[^']|\\')*)'"`: same as above, for single-quotes
+- `'\.([^.]+)(?=\.|\s|\Z)'`: separate terms with periods in-between
+- `'\/?([^\/]+)(?=\/|\b)'`: separate path terms `like/this/one`
+
+#### `edgeNGram_filter`
+Uses an [Edge NGram token filter](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/analysis-edgengram-tokenfilter.html) to allow inputs with only parts of a token to find the token. For example it would turn `glasses` into permutations starting with `gl` and ending with `glasses`, which would allow a search for "`glass`" to find the original token `glasses`
+
+## Gotchas
+
+- Searches can have their own analyzers. Remember to check when editing analyzers
+- `Character` filters (as opposed to token filters) always replace the original character, so they're not a good choice as they can hinder exact searches
+
+## Troubleshooting
+
+### Getting "flood stage disk watermark [95%] exceeded"
+
+You might get an error such as
+
+```
+[2018-10-31T15:54:19,762][WARN ][o.e.c.r.a.DiskThresholdMonitor] [pval5Ct]
+ flood stage disk watermark [95%] exceeded on
+ [pval5Ct7SieH90t5MykM5w][pval5Ct][/usr/local/var/lib/elasticsearch/nodes/0] free: 56.2gb[3%],
+ all indices on this node will be marked read-only
+```
+
+This is because you've exceeded the disk space threshold - it thinks you don't have enough disk space left, based on the default 95% threshold.
+
+In addition, the `read_only_allow_delete` setting will be set to `true`. It will block indexing, `forcemerge`, etc
+
+```
+curl "http://localhost:9200/gitlab-development/_settings?pretty"
+```
+
+Add this to your `elasticsearch.yml` file:
+
+```
+# turn off the disk allocator
+cluster.routing.allocation.disk.threshold_enabled: false
+```
+
+_or_
+
+```
+# set your own limits
+cluster.routing.allocation.disk.threshold_enabled: true
+cluster.routing.allocation.disk.watermark.flood_stage: 5gb # ES 6.x only
+cluster.routing.allocation.disk.watermark.low: 15gb
+cluster.routing.allocation.disk.watermark.high: 10gb
+```
+
+Restart ElasticSearch, and the `read_only_allow_delete` will clear on it's own.
+
+_from "Disk-based Shard Allocation | Elasticsearch Reference" [5.6](https://www.elastic.co/guide/en/elasticsearch/reference/5.6/disk-allocator.html#disk-allocator) and [6.x](https://www.elastic.co/guide/en/elasticsearch/reference/6.x/disk-allocator.html)_
diff --git a/doc/development/fe_guide/frontend_faq.md b/doc/development/fe_guide/frontend_faq.md
new file mode 100644
index 00000000000..e4225f2bc39
--- /dev/null
+++ b/doc/development/fe_guide/frontend_faq.md
@@ -0,0 +1,41 @@
+# Frontend FAQ
+
+## Rules of Frontend FAQ
+
+1. **You talk about Frontend FAQ.**
+ Please share links to it whenever applicable, so more eyes catch when content
+ gets outdated.
+2. **Keep it short and simple.**
+ Whenever an answer needs more than two sentences it does not belong here.
+3. **Provide background when possible.**
+ Linking to relevant source code, issue / epic, or other documentation helps
+ to understand the answer.
+4. **If you see something, do something.**
+ Please remove or update any content that is outdated as soon as you see it.
+
+## FAQ
+
+### How do I find the Rails route for a page?
+
+The easiest way is to type the following in the browser while on the page in
+question:
+
+```javascript
+document.body.dataset.page
+```
+
+Find here the [source code setting the attribute](https://gitlab.com/gitlab-org/gitlab-ce/blob/cc5095edfce2b4d4083a4fb1cdc7c0a1898b9921/app/views/layouts/application.html.haml#L4).
+
+### `modal_copy_button` vs `clipboard_button`
+
+The `clipboard_button` uses the `copy_to_clipboard.js` behaviour, which is
+initialized on page load, so if there are vue-based clipboard buttons that
+don't exist at page load (such as ones in a `GlModal`), they do not have the
+click handlers associated with the clipboard package.
+
+`modal_copy_button` was added that manages an instance of the
+[`clipboard` plugin](https://www.npmjs.com/package/clipboard) specific to
+the instance of that component, which means that clipboard events are
+bound on mounting and destroyed when the button is, mitigating the above
+issue. It also has bindings to a particular container or modal ID
+available, to work with the focus trap created by our GlModal.
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index 5f6123b5f9b..9fcd32fddfa 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -18,6 +18,12 @@ To save query compilation at runtime, webpack can directly import `.graphql`
files. This allows webpack to preprocess the query at compile time instead
of the client doing compilation of queries.
+To distinguish queries from mutations and fragments, the following naming convention is recommended:
+
+- `allUsers.query.graphql` for queries;
+- `addUser.mutation.graphql` for mutations;
+- `basicUser.fragment.graphql` for fragments.
+
## Usage in Vue
To use Vue Apollo, import the [Vue Apollo][vue-apollo] plugin as well
@@ -43,9 +49,9 @@ new Vue({
Read more about [Vue Apollo][vue-apollo] in the [Vue Apollo documentation][vue-apollo-docs].
-### Local state with `apollo-link-state`
+### Local state with Apollo
-It is possible to use our Apollo setup with [apollo-link-state][apollo-link-state] by passing
+It is possible to manage an application state with Apollo by passing
in a resolvers object when creating the default client. The default state can be set by writing
to the cache after setting up the default client.
@@ -76,6 +82,8 @@ const apolloProvider = new VueApollo({
});
```
+Read more about local state management with Apollo in the [Vue Apollo documentation](https://vue-apollo.netlify.com/guide/local-state.html#local-state).
+
### Testing
With [Vue test utils][vue-test-utils] it is easy to quickly test components that
@@ -92,6 +100,8 @@ it('tests apollo component', () => {
});
```
+Another possible way is testing queries with mocked GraphQL schema. Read more about this way in [Vue Apollo testing documentation](https://vue-apollo.netlify.com/guide/testing.html#tests-with-mocked-graqhql-schema)
+
## Usage outside of Vue
It is also possible to use GraphQL outside of Vue by directly importing
diff --git a/doc/development/fe_guide/index.md b/doc/development/fe_guide/index.md
index d5cc28dc00c..36d5e4ab96b 100644
--- a/doc/development/fe_guide/index.md
+++ b/doc/development/fe_guide/index.md
@@ -73,6 +73,10 @@ How we use UI components.
How we use Snowplow to track custom events.
+## Frontend FAQ
+
+Read the [frontend's FAQ](frontend_faq.md) for common small pieces of helpful information.
+
---
## Style Guides
diff --git a/doc/development/fe_guide/style_guide_js.md b/doc/development/fe_guide/style_guide_js.md
index 060cd8baf7f..b50159c2b75 100644
--- a/doc/development/fe_guide/style_guide_js.md
+++ b/doc/development/fe_guide/style_guide_js.md
@@ -95,6 +95,7 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/
#### Modules, Imports, and Exports
1. Use ES module syntax to import modules
+
```javascript
// bad
const SomeClass = require('some_class');
@@ -168,6 +169,7 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/
Do not use them anymore and feel free to remove them when refactoring legacy code.
1. Avoid adding to the global namespace.
+
```javascript
// bad
window.MyClass = class { /* ... */ };
@@ -176,7 +178,8 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/
export default class MyClass { /* ... */ }
```
-1. Side effects are forbidden in any script which contains exports
+1. Side effects are forbidden in any script which contains export
+
```javascript
// bad
export default class MyClass { /* ... */ }
@@ -449,6 +452,7 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
#### Props
1. Props should be declared as an object
+
```javascript
// bad
props: ['foo']
@@ -544,14 +548,24 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
<component @click="eventHandler"/>
```
-1. Shorthand `:` is preferable over `v-bind`
+2. Shorthand `:` is preferable over `v-bind`
```javascript
// bad
<component v-bind:class="btn"/>
// good
- <component :class="btsn"/>
+ <component :class="btn"/>
+ ```
+
+3. Shorthand `#` is preferable over `v-slot`
+
+ ```javascript
+ // bad
+ <template v-slot:header></template>
+
+ // good
+ <template #header></template>
```
#### Closing tags
diff --git a/doc/development/fe_guide/style_guide_scss.md b/doc/development/fe_guide/style_guide_scss.md
index 548d72bea93..b25dce65ffe 100644
--- a/doc/development/fe_guide/style_guide_scss.md
+++ b/doc/development/fe_guide/style_guide_scss.md
@@ -9,18 +9,44 @@ easy to maintain, and performant for the end-user.
As part of the effort for [cleaning up our CSS and moving our components into GitLab-UI](https://gitlab.com/groups/gitlab-org/-/epics/950)
led by the [GitLab UI WG](https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/20623) we prefer the use of utility classes over adding new CSS. However, complex CSS can be addressed by adding component classes.
-We have a few internal utility classes in [`common.scss`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/stylesheets/framework/common.scss)
-and we use [Bootstrap's Utility Classes](https://getbootstrap.com/docs/4.3/utilities/)
+#### Where are utility classes defined?
+
+- [Bootstrap's Utility Classes](https://getbootstrap.com/docs/4.3/utilities/)
+- [`common.scss`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/stylesheets/framework/common.scss) (old)
+- [`utilities.scss`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/stylesheets/utilities.scss) (new)
+
+#### Where should I put new utility classes?
New utility classes should be added to [`utilities.scss`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/stylesheets/utilities.scss). Existing classes include:
-**Background color**: `.bg-variant-shade` e.g. `.bg-warning-400`
-**Text color**: `.text-variant-shade` e.g. `.text-success-500`
-- variant is one of 'primary', 'secondary', 'success', 'warning', 'error'
-- shade is on of the shades listed on [colors](https://design.gitlab.com/foundations/colors/)
+| Name | Pattern | Example |
+|------|---------|---------|
+| Background color | `.bg-{variant}-{shade}` | `.bg-warning-400` |
+| Text color | `.text-{variant}-{shade}` | `.text-success-500` |
+| Font size | `.text-{size}` | `.text-2` |
+
+- `{variant}` is one of 'primary', 'secondary', 'success', 'warning', 'error'
+- `{shade}` is on of the shades listed on [colors](https://design.gitlab.com/foundations/colors/)
+- `{size}` is a number from 1-6 from our [Type scale](https://design.gitlab.com/foundations/typography)
+
+#### When should I create component classes?
+
+We recommend a "utility-first" approach.
+
+1. Start with utility classes.
+2. If composing utility classes into a component class removes code duplication and encapsulates a clear responsibility, do it.
+
+This encourages an organic growth of component classes and prevents the creation of one-off unreusable classes. Also, the kind of classes that emerge from "utility-first" tend to be design-centered (e.g. `.button`, `.alert`, `.card`) rather than domain-centered (e.g. `.security-report-widget`, `.commit-header-icon`).
+
+Examples of component classes that were created using "utility-first" include:
+
+- [`.circle-icon-container`](https://gitlab.com/gitlab-org/gitlab-ce/blob/579fa8b8ec7eb38d40c96521f517c9dab8c3b97a/app/assets/stylesheets/framework/icons.scss#L85)
+- [`.d-flex-center`](https://gitlab.com/gitlab-org/gitlab-ce/blob/900083d89cd6af391d26ab7922b3f64fa2839bef/app/assets/stylesheets/framework/common.scss#L425)
+
+Inspiration:
-**Font size**: `.text-size` e.g. `.text-2`
-- **size** is number from 1-6 from our [Type scale](https://design.gitlab.com/foundations/typography)
+- https://tailwindcss.com/docs/utility-first
+- https://tailwindcss.com/docs/extracting-components
### Naming
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md
index 437ce9abc7d..8c6a73c6824 100644
--- a/doc/development/fe_guide/vue.md
+++ b/doc/development/fe_guide/vue.md
@@ -234,7 +234,7 @@ One should apply to be a Vue.js expert by opening an MR when the Merge Request's
- Deep understanding of Vue and Vuex reactivy
- Vue and Vuex code are structured according to both official and our guidelines
- Full understanding of testing a Vue and Vuex application
-- Vuex code follows the [documented pattern](./vuex.md#actions-pattern-request-and-receive-namespaces)
+- Vuex code follows the [documented pattern](vuex.md#actions-pattern-request-and-receive-namespaces)
- Knowledge about the existing Vue and Vuex applications and existing reusable components
[vue-docs]: http://vuejs.org/guide/index.html
diff --git a/doc/development/fe_guide/vuex.md b/doc/development/fe_guide/vuex.md
index 7d52cac5f7e..bf248b7f8af 100644
--- a/doc/development/fe_guide/vuex.md
+++ b/doc/development/fe_guide/vuex.md
@@ -186,7 +186,7 @@ Remember that actions only describe that something happened, they don't describe
state.users.push(user);
},
[types.REQUEST_ADD_USER_ERROR](state, error) {
- state.isAddingUser = true;
+ state.isAddingUser = false;
state.errorAddingUser = error;
},
};
@@ -231,7 +231,7 @@ The store should be included in the main component of your application:
```javascript
// app.vue
- import store from 'store'; // it will include the index.js file
+ import store from './store'; // it will include the index.js file
export default {
name: 'application',
diff --git a/doc/development/feature_flags.md b/doc/development/feature_flags.md
index 3271f9a7fb3..13f0c5cc33e 100644
--- a/doc/development/feature_flags.md
+++ b/doc/development/feature_flags.md
@@ -20,7 +20,7 @@ dynamic (querying the DB etc.).
Once defined in `lib/feature.rb`, you will be able to activate a
feature for a given feature group via the [`feature_group` param of the features API](../api/features.md#set-or-create-a-feature)
-For GitLab.com, team members have access to feature flags through chatops. Only
+For GitLab.com, [team members have access to feature flags through Chatops](chatops_on_gitlabcom.md). Only
percentage gates are supported at this time. Setting a feature to be used 50% of
the time, you should execute `/chatops run feature set my_feature_flag 50`.
@@ -28,7 +28,7 @@ the time, you should execute `/chatops run feature set my_feature_flag 50`.
This document only covers feature flags used in the development of GitLab
itself. Feature flags in deployed user applications can be found at
-[Feature Flags](https://docs.gitlab.com/ee/user/project/operations/feature_flags.html)
+[Feature Flags](../user/project/operations/feature_flags.md)
## Developing with feature flags
@@ -108,11 +108,11 @@ so we make sure behavior under feature flag doesn't go untested in some non-spec
contexts.
Whenever a feature flag is present, make sure to test _both_ states of the
-feature flag. You can stub a feature flag as follows:
+feature flag.
-```ruby
-stub_feature_flags(my_feature_flag: false)
-```
+See the
+[testing guide](testing_guide/best_practices.md#feature-flags-in-tests)
+for information and examples on how to stub feature flags in tests.
## Enabling a feature flag (in development)
diff --git a/doc/development/geo.md b/doc/development/geo.md
new file mode 100644
index 00000000000..6e59fab34c7
--- /dev/null
+++ b/doc/development/geo.md
@@ -0,0 +1,529 @@
+# Geo (development) **[PREMIUM ONLY]**
+
+Geo connects GitLab instances together. One GitLab instance is
+designated as a **primary** node and can be run with multiple
+**secondary** nodes. Geo orchestrates quite a few components that can be seen on
+the diagram below and are described in more detail within this document.
+
+![Geo Architecture Diagram](../administration/geo/replication/img/geo_architecture.png)
+
+## Replication layer
+
+Geo handles replication for different components:
+
+- [Database](#database-replication): includes the entire application, except cache and jobs.
+- [Git repositories](#repository-replication): includes both projects and wikis.
+- [Uploaded blobs](#uploads-replication): includes anything from images attached on issues
+to raw logs and assets from CI.
+
+With the exception of the Database replication, on a *secondary* node, everything is coordinated
+by the [Geo Log Cursor](#geo-log-cursor).
+
+### Geo Log Cursor daemon
+
+The [Geo Log Cursor daemon](#geo-log-cursor-daemon) is a separate process running on
+each **secondary** node. It monitors the [Geo Event Log](#geo-event-log)
+for new events and creates background jobs for each specific event type.
+
+For example when a repository is updated, the Geo **primary** node creates
+a Geo event with an associated repository updated event. The Geo Log Cursor daemon
+picks the event up and schedules a `Geo::ProjectSyncWorker` job which will
+use the `Geo::RepositorySyncService` and `Geo::WikiSyncService` classes
+to update the repository and the wiki respectively.
+
+The Geo Log Cursor daemon can operate in High Availability mode automatically.
+The daemon will try to acquire a lock from time to time and once acquired, it
+will behave as the *active* daemon.
+
+Any additional running daemons on the same node, will be in standby
+mode, ready to resume work if the *active* daemon releases its lock.
+
+We use the [`ExclusiveLease`](https://www.rubydoc.info/github/gitlabhq/gitlabhq/Gitlab/ExclusiveLease) lock type with a small TTL, that is renewed at every
+pooling cycle. That allows us to implement this global lock with a timeout.
+
+At the end of the pooling cycle, if the daemon can't renew and/or reacquire
+the lock, it switches to standby mode.
+
+### Database replication
+
+Geo uses [streaming replication](#streaming-replication) to replicate
+the database from the **primary** to the **secondary** nodes. This
+replication gives the **secondary** nodes access to all the data saved
+in the database. So users can log in on the **secondary** and read all
+the issues, merge requests, etc. on the **secondary** node.
+
+### Repository replication
+
+Geo also replicates repositories. Each **secondary** node keeps track of
+the state of every repository in the [tracking database](#tracking-database).
+
+There are a few ways a repository gets replicated by the:
+
+- [Repository Sync worker](#repository-sync-worker).
+- [Geo Log Cursor](#geo-log-cursor).
+
+#### Project Registry
+
+The `Geo::ProjectRegistry` class defines the model used to track the
+state of repository replication. For each project in the main
+database, one record in the tracking database is kept.
+
+It records the following about repositories:
+
+- The last time they were synced.
+- The last time they were successfully synced.
+- If they need to be resynced.
+- When a retry should be attempted.
+- The number of retries.
+- If and when they were verified.
+
+It also stores these attributes for project wikis in dedicated columns.
+
+#### Repository Sync worker
+
+The `Geo::RepositorySyncWorker` class runs periodically in the
+background and it searches the `Geo::ProjectRegistry` model for
+projects that need updating. Those projects can be:
+
+- Unsynced: Projects that have never been synced on the **secondary**
+ node and so do not exist yet.
+- Updated recently: Projects that have a `last_repository_updated_at`
+ timestamp that is more recent than the `last_repository_successful_sync_at`
+ timestamp in the `Geo::ProjectRegistry` model.
+- Manual: The admin can manually flag a repository to resync in the
+ [Geo admin panel](../user/admin_area/geo_nodes.md).
+
+When we fail to fetch a repository on the secondary `RETRIES_BEFORE_REDOWNLOAD`
+times, Geo does a so-called _redownload_. It will do a clean clone
+into the `@geo-temporary` directory in the root of the storage. When
+it's successful, we replace the main repo with the newly cloned one.
+
+### Uploads replication
+
+File uploads are also being replicated to the **secondary** node. To
+track the state of syncing, the `Geo::FileRegistry` model is used.
+
+#### File Registry
+
+Similar to the [Project Registry](#project-registry), there is a
+`Geo::FileRegistry` model that tracks the synced uploads.
+
+CI Job Artifacts are synced in a similar way as uploads or LFS
+objects, but they are tracked by `Geo::JobArtifactRegistry` model.
+
+#### File Download Dispatch worker
+
+Also similar to the [Repository Sync worker](#repository-sync-worker),
+there is a `Geo::FileDownloadDispatchWorker` class that is run
+periodically to sync all uploads that aren't synced to the Geo
+**secondary** node yet.
+
+Files are copied via HTTP(s) and initiated via the
+`/api/v4/geo/transfers/:type/:id` endpoint,
+e.g. `/api/v4/geo/transfers/lfs/123`.
+
+## Authentication
+
+To authenticate file transfers, each `GeoNode` record has two fields:
+
+- A public access key (`access_key` field).
+- A secret access key (`secret_access_key` field).
+
+The **secondary** node authenticates itself via a [JWT request](https://jwt.io/).
+When the **secondary** node wishes to download a file, it sends an
+HTTP request with the `Authorization` header:
+
+```
+Authorization: GL-Geo <access_key>:<JWT payload>
+```
+
+The **primary** node uses the `access_key` field to look up the
+corresponding **secondary** node and decrypts the JWT payload,
+which contains additional information to identify the file
+request. This ensures that the **secondary** node downloads the right
+file for the right database ID. For example, for an LFS object, the
+request must also include the SHA256 sum of the file. An example JWT
+payload looks like:
+
+```
+{ "data": { sha256: "31806bb23580caab78040f8c45d329f5016b0115" }, iat: "1234567890" }
+```
+
+If the requested file matches the requested SHA256 sum, then the Geo
+**primary** node sends data via the [X-Sendfile](https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/)
+feature, which allows NGINX to handle the file transfer without tying
+up Rails or Workhorse.
+
+NOTE: **Note:**
+JWT requires synchronized clocks between the machines
+involved, otherwise it may fail with an encryption error.
+
+## Git Push to Geo secondary
+
+The Git Push Proxy exists as a functionality built inside the `gitlab-shell` component.
+It is active on a **secondary** node only. It allows the user that has cloned a repository
+from the secondary node to push to the same URL.
+
+Git `push` requests directed to a **secondary** node will be sent over to the **primary** node,
+while `pull` requests will continue to be served by the **secondary** node for maximum efficiency.
+
+HTTPS and SSH requests are handled differently:
+
+- With HTTPS, we will give the user a `HTTP 302 Redirect` pointing to the project on the **primary** node.
+The git client is wise enough to understand that status code and process the redirection.
+- With SSH, because there is no equivalent way to perform a redirect, we have to proxy the request.
+This is done inside [`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell), by first translating the request
+to the HTTP protocol, and then proxying it to the **primary** node.
+
+The [`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell) daemon knows when to proxy based on the response
+from `/api/v4/allowed`. A special `HTTP 300` status code is returned and we execute a "custom action",
+specified in the response body. The response contains additional data that allows the proxied `push` operation
+to happen on the **primary** node.
+
+## Using the Tracking Database
+
+Along with the main database that is replicated, a Geo **secondary**
+node has its own separate [Tracking database](#tracking-database).
+
+The tracking database contains the state of the **secondary** node.
+
+Any database migration that needs to be run as part of an upgrade
+needs to be applied to the tracking database on each **secondary** node.
+
+### Configuration
+
+The database configuration is set in [`config/database_geo.yml`](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/config/database_geo.yml.postgresql).
+The directory [`ee/db/geo`](https://gitlab.com/gitlab-org/gitlab-ee/tree/master/ee/db/geo)
+contains the schema and migrations for this database.
+
+To write a migration for the database, use the `GeoMigrationGenerator`:
+
+```
+rails g geo_migration [args] [options]
+```
+
+To migrate the tracking database, run:
+
+```
+bundle exec rake geo:db:migrate
+```
+
+### Foreign Data Wrapper
+
+> Introduced in GitLab 10.1.
+
+Foreign Data Wrapper ([FDW](#fdw)) is used by the [Geo Log Cursor](#geo-log-cursor) and improves
+the performance of many synchronization operations.
+
+FDW is a PostgreSQL extension ([`postgres_fdw`](https://www.postgresql.org/docs/current/postgres-fdw.html)) that is enabled within
+the Geo Tracking Database (on a **secondary** node), which allows it
+to connect to the readonly database replica and perform queries and filter
+data from both instances.
+
+While FDW is available in older versions of PostgreSQL, we needed to
+raise the minimum required version to 9.6 as this includes many
+performance improvements to the FDW implementation.
+
+This persistent connection is configured as an FDW server
+named `gitlab_secondary`. This configuration exists within the database's user
+context only. To access the `gitlab_secondary`, GitLab needs to use the
+same database user that had previously been configured.
+
+The Geo Tracking Database accesses the readonly database replica via FDW as a regular user,
+limited by its own restrictions. The credentials are configured as a
+`USER MAPPING` associated with the `SERVER` mapped previously
+(`gitlab_secondary`).
+
+FDW configuration and credentials definition are managed automatically by the
+Omnibus GitLab `gitlab-ctl reconfigure` command.
+
+#### Refeshing the Foreign Tables
+
+Whenever a new Geo node is configured or the database schema changes on the
+**primary** node, you must refresh the foreign tables on the **secondary** node
+by running the following:
+
+```sh
+bundle exec rake geo:db:refresh_foreign_tables
+```
+
+Failure to do this will prevent the **secondary** node from
+functioning properly. The **secondary** node will generate error
+messages, as the following PostgreSQL error:
+
+```
+ERROR: relation "gitlab_secondary.ci_job_artifacts" does not exist at character 323
+STATEMENT: SELECT a.attname, format_type(a.atttypid, a.atttypmod),
+ pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
+ FROM pg_attribute a LEFT JOIN pg_attrdef d
+ ON a.attrelid = d.adrelid AND a.attnum = d.adnum
+ WHERE a.attrelid = '"gitlab_secondary"."ci_job_artifacts"'::regclass
+ AND a.attnum > 0 AND NOT a.attisdropped
+ ORDER BY a.attnum
+```
+
+#### Accessing data from a Foreign Table
+
+At the SQL level, all you have to do is `SELECT` data from `gitlab_secondary.*`.
+
+Here's an example of how to access all projects from the Geo Tracking Database's FDW:
+
+```sql
+SELECT * FROM gitlab_secondary.projects;
+```
+
+As a more real-world example, this is how you filter for unarchived projects
+on the Tracking Database:
+
+```sql
+SELECT project_registry.*
+ FROM project_registry
+ JOIN gitlab_secondary.projects
+ ON (project_registry.project_id = gitlab_secondary.projects.id
+ AND gitlab_secondary.projects.archived IS FALSE)
+```
+
+At the ActiveRecord level, we have additional Models that represent the
+foreign tables. They must be mapped in a slightly different way, and they are read-only.
+
+Check the existing FDW models in `ee/app/models/geo/fdw` for reference.
+
+From a developer's perspective, it's no different than creating a model that
+represents a Database View.
+
+With the examples above, you can access the projects with:
+
+```ruby
+Geo::Fdw::Project.all
+```
+
+and to access the `ProjectRegistry` filtering by unarchived projects:
+
+```ruby
+# We have to use Arel here:
+project_registry_table = Geo::ProjectRegistry.arel_table
+fdw_project_table = Geo::Fdw::Project.arel_table
+
+project_registry_table.join(fdw_project_table)
+ .on(project_registry_table[:project_id].eq(fdw_project_table[:id]))
+ .where((fdw_project_table[:archived]).eq(true)) # if you append `.to_sql` you can check generated query
+```
+
+## Finders
+
+Geo uses [Finders](https://gitlab.com/gitlab-org/gitlab-ee/tree/master/app/finders),
+which are classes take care of the heavy lifting of looking up
+projects/attachments/etc. in the tracking database and main database.
+
+### Finders Performance
+
+The Finders need to compare data from the main database with data in
+the tracking database. For example, counting the number of synced
+projects normally involves retrieving the project IDs from one
+database and checking their state in the other database. This is slow
+and requires a lot of memory.
+
+To overcome this, the Finders use [FDW](#fdw), or Foreign Data
+Wrappers. This allows a regular `JOIN` between the main database and
+the tracking database.
+
+## Redis
+
+Redis on the **secondary** node works the same as on the **primary**
+node. It is used for caching, storing sessions, and other persistent
+data.
+
+Redis data replication between **primary** and **secondary** node is
+not used, so sessions etc. aren't shared between nodes.
+
+## Object Storage
+
+GitLab can optionally use Object Storage to store data it would
+otherwise store on disk. These things can be:
+
+ - LFS Objects
+ - CI Job Artifacts
+ - Uploads
+
+Objects that are stored in object storage, are not handled by Geo. Geo
+ignores items in object storage. Either:
+
+- The object storage layer should take care of its own geographical
+ replication.
+- All secondary nodes should use the same storage node.
+
+## Verification
+
+### Repository verification
+
+Repositories are verified with a checksum.
+
+The **primary** node calculates a checksum on the repository. It
+basically hashes all Git refs together and stores that hash in the
+`project_repository_states` table of the database.
+
+The **secondary** node does the same to calculate the hash of its
+clone, and compares the hash with the value the **primary** node
+calculated. If there is a mismatch, Geo will mark this as a mismatch
+and the administrator can see this in the [Geo admin panel](../user/admin_area/geo_nodes.md).
+
+## Glossary
+
+### Primary node
+
+A **primary** node is the single node in a Geo setup that read-write
+capabilities. It's the single source of truth and the Geo
+**secondary** nodes replicate their data from there.
+
+In a Geo setup, there can only be one **primary** node. All
+**secondary** nodes connect to that **primary**.
+
+### Secondary node
+
+A **secondary** node is a read-only replica of the **primary** node
+running in a different geographical location.
+
+### Streaming replication
+
+Geo depends on the streaming replication feature of PostgreSQL. It
+completely replicates the database data and the database schema. The
+database replica is a read-only copy.
+
+Streaming replication depends on the Write Ahead Logs, or WAL. Those
+logs are copied over to the replica and replayed there.
+
+Since streaming replication also replicates the schema, the database
+migration do not need to run on the secondary nodes.
+
+### Tracking database
+
+A database on each Geo **secondary** node that keeps state for the node
+on which it resides. Read more in [Using the Tracking database](#using-the-tracking-database).
+
+### FDW
+
+Foreign Data Wrapper, or FDW, is a feature built-in in PostgreSQL. It
+allows data to be queried from different data sources. In Geo, it's
+used to query data from different PostgreSQL instances.
+
+## Geo Event Log
+
+The Geo **primary** stores events in the `geo_event_log` table. Each
+entry in the log contains a specific type of event. These type of
+events include:
+
+ - Repository Deleted event
+ - Repository Renamed event
+ - Repositories Changed event
+ - Repository Created event
+ - Hashed Storage Migrated event
+ - Lfs Object Deleted event
+ - Hashed Storage Attachments event
+ - Job Artifact Deleted event
+ - Upload Deleted event
+
+### Geo Log Cursor
+
+The process running on the **secondary** node that looks for new
+`Geo::EventLog` rows.
+
+## Code features
+
+### `Gitlab::Geo` utilities
+
+Small utility methods related to Geo go into the
+[`ee/lib/gitlab/geo.rb`](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/gitlab/geo.rb)
+file.
+
+Many of these methods are cached using the `RequestStore` class, to
+reduce the performance impact of using the methods throughout the
+codebase.
+
+#### Current node
+
+The class method `.current_node` returns the `GeoNode` record for the
+current node.
+
+We use the `host`, `port`, and `relative_url_root` values from
+`gitlab.yml` and search in the database to identify which node we are
+in (see `GeoNode.current_node`).
+
+#### Primary or secondary
+
+To determine whether the current node is a **primary** node or a
+**secondary** node use the `.primary?` and `.secondary?` class
+methods.
+
+It is possible for these methods to both return `false` on a node when
+the node is not enabled. See [Enablement](#enablement).
+
+#### Geo Database configured?
+
+There is also an additional gotcha when dealing with things that
+happen during initialization time. In a few places, we use the
+`Gitlab::Geo.geo_database_configured?` method to check if the node has
+the tracking database, which only exists on the **secondary**
+node. This overcomes race conditions that could happen during
+bootstrapping of a new node.
+
+#### Enablement
+
+We consider Geo feature enabled when the user has a valid license with the
+feature included, and they have at least one node defined at the Geo Nodes
+screen.
+
+See `Gitlab::Geo.enabled?` and `Gitlab::Geo.license_allows?` methods.
+
+#### Read-only
+
+All Geo **secondary** nodes are read-only.
+
+The general principle of a [read-only database](verifying_database_capabilities.md#read-only-database)
+applies to all Geo **secondary** nodes. So the
+`Gitlab::Database.read_only?` method will always return `true` on a
+**secondary** node.
+
+When some write actions are not allowed because the node is a
+**secondary**, consider adding the `Gitlab::Database.read_only?` or
+`Gitlab::Database.read_write?` guard, instead of `Gitlab::Geo.secondary?`.
+
+The database itself will already be read-only in a replicated setup,
+so we don't need to take any extra step for that.
+
+## History of communication channel
+
+The communication channel has changed since first iteration, you can
+check here historic decisions and why we moved to new implementations.
+
+### Custom code (GitLab 8.6 and earlier)
+
+In GitLab versions before 8.6, custom code is used to handle
+notification from **primary** node to **secondary** nodes by HTTP
+requests.
+
+### System hooks (GitLab 8.7 to 9.5)
+
+Later, it was decided to move away from custom code and begin using
+system hooks. More people were using them, so
+many would benefit from improvements made to this communication layer.
+
+There is a specific **internal** endpoint in our API code (Grape),
+that receives all requests from this System Hooks:
+`/api/v4/geo/receive_events`.
+
+We switch and filter from each event by the `event_name` field.
+
+### Geo Log Cursor (GitLab 10.0 and up)
+
+Since GitLab 10.0, [System Webhooks](#system-hooks-gitlab-87-to-95) are no longer
+used and Geo Log Cursor is used instead. The Log Cursor traverses the
+`Geo::EventLog` rows to see if there are changes since the last time
+the log was checked and will handle repository updates, deletes,
+changes, and renames.
+
+The table is within the replicated database. This has two advantages over the
+old method:
+
+- Replication is synchronous and we preserve the order of events.
+- Replication of the events happen at the same time as the changes in the
+ database.
diff --git a/doc/development/git_object_deduplication.md b/doc/development/git_object_deduplication.md
index 81c5f69c7b8..b512d7611d3 100644
--- a/doc/development/git_object_deduplication.md
+++ b/doc/development/git_object_deduplication.md
@@ -10,10 +10,10 @@ GitLab implements Git object deduplication.
## Enabling Git object deduplication via feature flags
-As of GitLab 11.9, Git object deduplication in GitLab is in beta. In this
-document, you can read about the caveats of enabling the feature. Also,
-note that Git object deduplication is limited to forks of public
-projects on hashed repository storage.
+As of GitLab 12.0, Git object deduplication in GitLab is still behind a
+feature flag. In this document, you can read about the effects of
+enabling the feature. Also, note that Git object deduplication is
+limited to forks of public projects on hashed repository storage.
You can enable deduplication globally by setting the `object_pools`
feature flag to `true`:
@@ -51,6 +51,15 @@ configuration. Objects in A that are not in B will remain in A. For this
to work, it is of course critical that **no objects ever get deleted from
B** because A might need them.
+DANGER: **Danger:**
+Do not run `git prune` or `git gc` in pool repositories! This can
+cause data loss in "real" repositories that depend on the pool in
+question.
+
+The danger lies in `git prune`, and `git gc` calls `git prune`. The
+problem is that `git prune`, when running in a pool repository, cannot
+reliable decide if an object is no longer needed.
+
### Git alternates in GitLab: pool repositories
GitLab organizes this object borrowing by creating special **pool
@@ -80,43 +89,10 @@ across a collection of GitLab project repositories at the Git level:
The effectiveness of Git object deduplication in GitLab depends on the
amount of overlap between the pool repository and each of its
-participants. As of GitLab 11.9, we have a somewhat optimistic system.
-The only data that will be deduplicated is the data in the source
-project repository at the time the pool repository is created. That is,
-the data in the source project at the time of the first fork *after* the
-deduplication feature has been enabled.
-
-When we enable the object deduplication feature for
-gitlab.com/gitlab-org/gitlab-ce, which is about 1GB at the time of
-writing, all new forks of that project would be 1GB smaller than they
-would have been without Git object deduplication. So even in its current
-optimistic form, we expect Git object deduplication in GitLab to make a
-difference.
-
-However, if a lot of Git objects get added to the project repositories
-in a pool after the pool repository was created these new Git objects
-will currently (GitLab 11.9) not get deduplicated. Over time, the
-deduplication factor of the pool will get worse and worse.
-
-As an extreme example, if we create an empty repository A, and fork that
-to repository B, behind the scenes we get an object pool P with no
-objects in it at all. If we then push 1GB of Git data to A, and push the
-same Git data to B, it will not get deduplicated, because that data was
-not in A at the time P was created.
-
-This also matters in less extreme examples. Consider a pool P with
-source project A and 500 active forks B1, B2,...,B500. Suppose,
-optimistically, that the forks are fully deduplicated at the start of
-our scenario. Now some time passes and 200MB of new Git data gets added
-to project A. Because of the forking workflow, this data makes also its way
-into the forks B1, ..., B500. That means we would now have 100GB of Git
-data sitting around (500 \* 200MB) across the forks, that could have
-been deduplicated. But because of the way we do deduplication this new
-data will not be deduplicated.
-
-> TODO Add periodic maintenance of object pools to prevent gradual loss
-> of deduplication over time.
-> https://gitlab.com/groups/gitlab-org/-/epics/524
+participants. Each time garbage collection runs on the source project,
+Git objects from the source project will get migrated to the pool
+repository. One by one, as garbage collection runs, other member
+projects will benefit from the new objects that got added to the pool.
## SQL model
@@ -136,6 +112,9 @@ are as follows:
- a `PoolRepository` has exactly one "source `Project`"
(`pool.source_project`)
+> TODO Fix invalid SQL data for pools created prior to GitLab 11.11
+> https://gitlab.com/gitlab-org/gitaly/issues/1653.
+
### Assumptions
- All repositories in a pool must use [hashed
@@ -146,10 +125,6 @@ are as follows:
The Git alternates mechanism relies on direct disk access across
multiple repositories, and we can only assume direct disk access to
be possible within a Gitaly storage shard.
-- All project repositories in a pool must have "Public" visibility in
- GitLab at the time they join. There are gotchas around visibility of
- Git objects across alternates links. This restriction is a defense
- against accidentally leaking private Git data.
- The only two ways to remove a member project from a pool are (1) to
delete the project or (2) to move the project to another Gitaly
storage shard.
@@ -187,17 +162,14 @@ are as follows:
### Consequences
- If a normal Project participating in a pool gets moved to another
- Gitaly storage shard, its "belongs to PoolRepository" relation must
+ Gitaly storage shard, its "belongs to PoolRepository" relation will
be broken. Because of the way moving repositories between shard is
implemented, we will automatically get a fresh self-contained copy
of the project's repository on the new storage shard.
- If the source project of a pool gets moved to another Gitaly storage
- shard or is deleted, we may have to break the "PoolRepository has
- one source Project" relation?
-
-> TODO What happens, or should happen, if a source project changes
-> visibility, is deleted, or moves to another storage shard?
-> https://gitlab.com/gitlab-org/gitaly/issues/1488
+ shard or is deleted the "source project" relation is not broken.
+ However, as of GitLab 12.0 a pool will not fetch from a source
+ unless the source is on the same Gitaly shard.
## Consistency between the SQL pool relation and Gitaly
@@ -209,16 +181,8 @@ repository and a pool.
### Pool existence
If GitLab thinks a pool repository exists (i.e. it exists according to
-SQL), but it does not on the Gitaly server, then certain RPC calls that
-take the object pool as an argument will fail.
-
-> TODO What happens if SQL says the pool repo exists but Gitaly says it
-> does not? https://gitlab.com/gitlab-org/gitaly/issues/1533
-
-If GitLab thinks a pool does not exist, while it does exist on disk,
-that has no direct consequences on its own. However, if other
-repositories on disk borrow objects from this unknown pool repository
-then we risk data loss, see below.
+SQL), but it does not on the Gitaly server, then it will be created on
+the fly by Gitaly.
### Pool relation existence
@@ -226,26 +190,19 @@ There are three different things that can go wrong here.
#### 1. SQL says repo A belongs to pool P but Gitaly says A has no alternate objects
-In this case, we miss out on disk space savings but all RPC's on A itself
-will function fine. As long as Git can find all its objects, it does not
-matter exactly where those objects are.
+In this case, we miss out on disk space savings but all RPC's on A
+itself will function fine. The next time garbage collection runs on A,
+the alternates connection gets established in Gitaly. This is done by
+`Projects::GitDeduplicationService` in gitlab-rails.
#### 2. SQL says repo A belongs to pool P1 but Gitaly says A has alternate objects in pool P2
-If we are not careful, this situation can lead to data loss. During some
-operations (repository maintenance), GitLab will try to re-link A to its
-pool P1. If this clobbers the existing link to P2, then A will loose Git
-objects and become invalid.
-
-Also, keep in mind that if GitLab's database got messed up, it may not
-even know that P2 exists.
-
-> TODO Ensure that Gitaly will not clobber existing, unexpected
-> alternates links. https://gitlab.com/gitlab-org/gitaly/issues/1534
+In this case `Projects::GitDeduplicationService` will throw an exception.
#### 3. SQL says repo A does not belong to any pool but Gitaly says A belongs to P
-This has the same data loss possibility as scenario 2 above.
+In this case `Projects::GitDeduplicationService` will try to
+"re-duplicate" the repository A using the DisconnectGitAlternates RPC.
## Git object deduplication and GitLab Geo
diff --git a/doc/development/gitaly.md b/doc/development/gitaly.md
index bfde26dbe4a..c8beb808a54 100644
--- a/doc/development/gitaly.md
+++ b/doc/development/gitaly.md
@@ -63,6 +63,8 @@ If your test-suite is failing with Gitaly issues, as a first step, try running:
rm -rf tmp/tests/gitaly
```
+During rspec tests, the Gitaly instance will write logs to `gitlab/log/gitaly-test.log`.
+
## Legacy Rugged code
While Gitaly can handle all Git access, many of GitLab customers still
@@ -80,6 +82,8 @@ most commonly-used RPCs can be enabled via feature flags:
* `rugged_get_tree_entries`
* `rugged_tree_entry`
* `rugged_commit_is_ancestor`
+* `rugged_commit_tree_entry`
+* `rugged_list_commits_by_oid`
A convenience Rake task can be used to enable or disable these flags
all together. To enable:
@@ -241,7 +245,7 @@ Here are the steps to gate a new feature in Gitaly behind a feature flag.
// go implementation
} else {
findAllTagsRequests.WithLabelValues("ruby").Inc()
- // ruby impelmentation
+ // ruby implementation
}
```
diff --git a/doc/development/gitlab_architecture_diagram.png b/doc/development/gitlab_architecture_diagram.png
deleted file mode 100644
index 90e27d5462a..00000000000
--- a/doc/development/gitlab_architecture_diagram.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md
index 6dcade3bb51..4dad8815fcb 100644
--- a/doc/development/go_guide/index.md
+++ b/doc/development/go_guide/index.md
@@ -40,7 +40,7 @@ of possible security breaches in our code:
- SQL injections
Remember to run
-[SAST](https://docs.gitlab.com/ee/user/project/merge_requests/sast.html)
+[SAST](../../user/application_security/sast/index.md)
**[ULTIMATE]** on your project (or at least the [gosec
analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/gosec)),
and to follow our [Security
@@ -93,10 +93,10 @@ become available, you will be able to share job templates like this
Dependencies should be kept to the minimum. The introduction of a new
dependency should be argued in the merge request, as per our [Approval
-Guidelines](../code_review.html#approval-guidelines). Both [License
-Management](https://docs.gitlab.com/ee/user/project/merge_requests/license_management.html)
+Guidelines](../code_review.md#approval-guidelines). Both [License
+Management](../../user/project/merge_requests/license_management.md)
**[ULTIMATE]** and [Dependency
-Scanning](https://docs.gitlab.com/ee/user/project/merge_requests/dependency_scanning.html)
+Scanning](../../user/application_security/dependency_scanning/index.md)
**[ULTIMATE]** should be activated on all projects to ensure new dependencies
security status and license compatibility.
diff --git a/doc/development/i18n/externalization.md b/doc/development/i18n/externalization.md
index 223585ebb55..9fb8ea542d9 100644
--- a/doc/development/i18n/externalization.md
+++ b/doc/development/i18n/externalization.md
@@ -174,7 +174,7 @@ For example use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript.
# => When size == 2: 'There are 2 mice.'
```
- Avoid using `%d` or count variables in sigular strings. This allows more natural translation in some languages.
+ Avoid using `%d` or count variables in singular strings. This allows more natural translation in some languages.
- In JavaScript:
@@ -195,6 +195,7 @@ For example use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript.
Sometimes you need to add some context to the text that you want to translate
(if the word occurs in a sentence and/or the word is ambiguous).
+Namespaces should be PascalCase.
- In Ruby/HAML:
@@ -211,7 +212,7 @@ Sometimes you need to add some context to the text that you want to translate
```
Note: The namespace should be removed from the translation. See the [translation
-guidelines for more details](./translation.md#namespaced-strings).
+guidelines for more details](translation.md#namespaced-strings).
### Dates / times
@@ -300,7 +301,7 @@ file in. Once the changes are on master, they will be picked up by
[Crowdin](http://translate.gitlab.com) and be presented for translation.
If there are merge conflicts in the `gitlab.pot` file, you can delete the file
-and regenerate it using the same command. Confirm that you are not deleting any strings accidentally by looking over the diff.
+and regenerate it using the same command.
### Validating PO files
@@ -331,7 +332,7 @@ Errors in `locale/zh_HK/gitlab.po`:
Syntax error in msgstr
Syntax error in message_line
There should be only whitespace until the end of line after the double quote character of a message text.
- Parseing result before error: '{:msgid=>["", "You are going to remove %{project_name_with_namespace}.\\n", "Removed project CANNOT be restored!\\n", "Are you ABSOLUTELY sure?"]}'
+ Parsing result before error: '{:msgid=>["", "You are going to remove %{project_name_with_namespace}.\\n", "Removed project CANNOT be restored!\\n", "Are you ABSOLUTELY sure?"]}'
SimplePoParser filtered backtrace: SimplePoParser::ParserError
Errors in `locale/zh_TW/gitlab.po`:
1 pipeline
diff --git a/doc/development/i18n/merging_translations.md b/doc/development/i18n/merging_translations.md
index 85284d8c714..eadf1cd74c5 100644
--- a/doc/development/i18n/merging_translations.md
+++ b/doc/development/i18n/merging_translations.md
@@ -32,7 +32,7 @@ clicking `Pause sync` on the [Crowdin integration settings
page](https://translate.gitlab.com/project/gitlab-ee/settings#integration).
When all failures are resolved, the translations need to be double
-checked once more as discussed in [confidential issue](https://docs.gitlab.com/ee/user/project/issues/confidential_issues.html) `https://gitlab.com/gitlab-org/gitlab-ce/issues/37850`.
+checked once more as discussed in [confidential issue](../../user/project/issues/confidential_issues.md) `https://gitlab.com/gitlab-org/gitlab-ce/issues/37850`.
## Merging translations
diff --git a/doc/development/i18n/proofreader.md b/doc/development/i18n/proofreader.md
index 131e3edf35e..35c5b155594 100644
--- a/doc/development/i18n/proofreader.md
+++ b/doc/development/i18n/proofreader.md
@@ -13,18 +13,21 @@ are very appreciative of the work done by translators and proofreaders!
- Lyubomir Vasilev - [Crowdin](https://crowdin.com/profile/lyubomirv)
- Catalan
- David Planella - [GitLab](https://gitlab.com/dplanella), [Crowdin](https://crowdin.com/profile/dplanella)
-- Chinese Simplified
- - Huang Tao - [GitLab](https://gitlab.com/htve), [Crowdin](https://crowdin.com/profile/htve)
-- Chinese Traditional
+- Chinese Simplified 简体中文
- Huang Tao - [GitLab](https://gitlab.com/htve), [Crowdin](https://crowdin.com/profile/htve)
+ - Victor Wu - [GitLab](https://gitlab.com/victorwuky), [Crowdin](https://crowdin.com/profile/victorwu)
+ - Xiaogang Wen - [GitLab](https://gitlab.com/xiaogang_gitlab), [Crowdin](https://crowdin.com/profile/xiaogang_gitlab)
+- Chinese Traditional ç¹é«”中文
- Weizhe Ding - [GitLab](https://gitlab.com/d.weizhe), [Crowdin](https://crowdin.com/profile/d.weizhe)
- Yi-Jyun Pan - [GitLab](https://gitlab.com/pan93412), [Crowdin](https://crowdin.com/profile/pan93412)
-- Chinese Traditional, Hong Kong
- - Huang Tao - [GitLab](https://gitlab.com/htve), [Crowdin](https://crowdin.com/profile/htve)
+ - Victor Wu - [GitLab](https://gitlab.com/victorwuky), [Crowdin](https://crowdin.com/profile/victorwu)
+- Chinese Traditional, Hong Kong ç¹é«”中文 (香港)
+ - Victor Wu - [GitLab](https://gitlab.com/victorwuky), [Crowdin](https://crowdin.com/profile/victorwu)
+ - Ivan Ip - [GitLab](https://gitlab.com/lifehome), [Crowdin](https://crowdin.com/profile/lifehome)
- Czech
- Proofreaders needed.
- Danish
- - Proofreaders needed.
+ - Saederup92 - [GitLab](https://gitlab.com/Saederup92), [Crowdin](https://crowdin.com/profile/Saederup92)
- Dutch
- Emily Hendle - [GitLab](https://gitlab.com/pundachan), [Crowdin](https://crowdin.com/profile/pandachan)
- Esperanto
@@ -40,6 +43,7 @@ are very appreciative of the work done by translators and proofreaders!
- Pedro Garcia - [GitLab](https://gitlab.com/pedgarrod), [Crowdin](https://crowdin.com/profile/breaking_pitt)
- German
- Michael Hahnle - [GitLab](https://gitlab.com/mhah), [Crowdin](https://crowdin.com/profile/mhah)
+ - Katrin Leinweber - [GitLab](https://gitlab.com/katrinleinweber/), [Crowdin](https://crowdin.com/profile/katrinleinweber)
- Greek
- Proofreaders needed.
- Hebrew
@@ -52,11 +56,10 @@ are very appreciative of the work done by translators and proofreaders!
- Italian
- Paolo Falomo - [GitLab](https://gitlab.com/paolofalomo), [Crowdin](https://crowdin.com/profile/paolo.falomo)
- Japanese
- - Yamana Tokiuji - [GitLab](https://gitlab.com/tokiuji), [Crowdin](https://crowdin.com/profile/yamana)
- Hiroyuki Sato - [GitLab](https://gitlab.com/hiroponz), [Crowdin](https://crowdin.com/profile/hiroponz)
+ - Tomo Dote - [Gitlab](https://gitlab.com/fu7mu4), [Crowdin](https://crowdin.com/profile/fu7mu4)
- Korean
- Chang-Ho Cha - [GitLab](https://gitlab.com/changho-cha), [Crowdin](https://crowdin.com/profile/zzazang)
- - Huang Tao - [GitLab](https://gitlab.com/htve), [Crowdin](https://crowdin.com/profile/htve)
- Ji Hun Oh - [GitLab](https://gitlab.com/Baw-Appie), [Crowdin](https://crowdin.com/profile/BawAppie)
- Jeongwhan Choi - [GitLab](https://gitlab.com/jeongwhanchoi), [Crowdin](https://crowdin.com/profile/jeongwhanchoi)
- Mongolian
@@ -68,6 +71,7 @@ are very appreciative of the work done by translators and proofreaders!
- Maksymilian Roman - [GitLab](https://gitlab.com/villaincandle), [Crowdin](https://crowdin.com/profile/villaincandle)
- Portuguese
- Proofreaders needed.
+ - Diogo Trindade - [GitLab](https://gitlab.com/luisdiogo2071317), [Crowdin](https://crowdin.com/profile/ldiogotrindade)
- Portuguese, Brazilian
- Paulo George Gomes Bezerra - [GitLab](https://gitlab.com/paulobezerra), [Crowdin](https://crowdin.com/profile/paulogomes.rep)
- André Gama - [GitLab](https://gitlab.com/andregamma), [Crowdin](https://crowdin.com/profile/ToeOficial)
@@ -126,7 +130,7 @@ are very appreciative of the work done by translators and proofreaders!
your previous translations by [GitLab team members](https://about.gitlab.com/team/)
or [Core team members](https://about.gitlab.com/core-team/) who are fluent in
the language or current proofreaders.
- - When a request is made for the first proofreader for a lanuguage and there are no [GitLab team members](https://about.gitlab.com/team/)
+ - When a request is made for the first proofreader for a language and there are no [GitLab team members](https://about.gitlab.com/team/)
or [Core team members](https://about.gitlab.com/core-team/) who speak the language, we will request links to previous translation work in other communities or projects.
diff --git a/doc/development/i18n/translation.md b/doc/development/i18n/translation.md
index 99c0fe6db1d..62be3786549 100644
--- a/doc/development/i18n/translation.md
+++ b/doc/development/i18n/translation.md
@@ -89,9 +89,7 @@ To propose additions to the glossary please
### Inclusive language in French
-In French, we should follow the guidelines from [ecriture-inclusive.fr]. For
-instance:
+In French, the "écriture inclusive" is now over (see on [Legifrance](https://www.legifrance.gouv.fr/affichTexte.do?cidTexte=JORFTEXT000036068906&categorieLien=id)).
+So, to include both genders, write “Utilisateurs et utilisatrices†instead of “Utilisateur·rice·sâ€.
+When space is missing, the male gender should be used alone.
-- Utilisateur•rice•s
-
-[ecriture-inclusive.fr]: http://www.ecriture-inclusive.fr/
diff --git a/doc/development/img/architecture_simplified.png b/doc/development/img/architecture_simplified.png
new file mode 100644
index 00000000000..1698c167c5e
--- /dev/null
+++ b/doc/development/img/architecture_simplified.png
Binary files differ
diff --git a/doc/development/import_export.md b/doc/development/import_export.md
index f7f48b03651..fd067b80c16 100644
--- a/doc/development/import_export.md
+++ b/doc/development/import_export.md
@@ -27,7 +27,7 @@ Read through the current performance problems using the Import/Export below.
### OOM errors
-Out of memory (OOM) errors are normally caused by the [Sidekiq Memory Killer](https://docs.gitlab.com/ee/administration/operations/sidekiq_memory_killer.html):
+Out of memory (OOM) errors are normally caused by the [Sidekiq Memory Killer](../administration/operations/sidekiq_memory_killer.md):
```bash
SIDEKIQ_MEMORY_KILLER_MAX_RSS = 2GB in GitLab.com
diff --git a/doc/development/integrations/jira_connect.md b/doc/development/integrations/jira_connect.md
new file mode 100644
index 00000000000..5bf43d320c6
--- /dev/null
+++ b/doc/development/integrations/jira_connect.md
@@ -0,0 +1,41 @@
+# Setting up a development environment
+
+The following are required to install and test the app:
+
+1. A Jira Cloud instance
+
+ Atlassian provides free instances for development and testing. [Click here to sign up](http://go.atlassian.com/cloud-dev).
+
+1. A GitLab instance available over the internet
+
+ For the app to work, Jira Cloud should be able to connect to the GitLab instance through the internet.
+
+ To easily expose your local development environment, you can use tools like [serveo](https://serveo.net) or [ngrok](https://ngrok.com).
+ These also take care of SSL for you because Jira requires all connections to the app host to be over SSL.
+
+> This feature is currently behind the `:jira_connect_app` feature flag
+
+# Installing the app in Jira
+
+1. Enable Jira development mode to install apps that are not from the Atlassian Marketplace
+
+ 1. Navigate to **Jira settings** (cog icon) > **Apps** > **Manage apps**.
+ 1. Scroll to the bottom of the **Manage apps** page and click **Settings**.
+ 1. Select **Enable development mode** and click **Apply**.
+
+1. Install the app
+
+ 1. Navigate to Jira, then choose **Jira settings** (cog icon) > **Apps** > **Manage apps**.
+ 1. Click **Upload app**.
+ 1. In the **From this URL** field, provide a link to the app descriptor. The host and port must point to your GitLab instance.
+
+ For example:
+ ```
+ https://xxxx.serveo.net/-/jira_connect/app_descriptor.json
+ ```
+ 1. Click **Upload**.
+
+ If the install was successful, you should see the **GitLab for Jira** app under **Manage apps**.
+ You can also click **Getting Started** to open the configuration page rendered from your GitLab instance.
+
+ _Note that any changes to the app descriptor requires you to uninstall then reinstall the app._
diff --git a/doc/development/licensed_feature_availability.md b/doc/development/licensed_feature_availability.md
new file mode 100644
index 00000000000..6f3dd59b2c3
--- /dev/null
+++ b/doc/development/licensed_feature_availability.md
@@ -0,0 +1,37 @@
+# Licensed feature availability **[STARTER]**
+
+As of GitLab 9.4, we've been supporting a simplified version of licensed
+feature availability checks via `ee/app/models/license.rb`, both for
+on-premise or GitLab.com plans and features.
+
+## Restricting features scoped by namespaces or projects
+
+GitLab.com plans are persisted on user groups and namespaces, therefore, if you're adding a
+feature such as [Related issues](../user/project/issues/related_issues.md) or
+[Service desk](../user/project/service_desk.md),
+it should be restricted on namespace scope.
+
+1. Add the feature symbol on `EES_FEATURES`, `EEP_FEATURES` or `EEU_FEATURES` constants in
+ `ee/app/models/license.rb`. Note on `ee/app/models/ee/namespace.rb` that _Bronze_ GitLab.com
+ features maps to on-premise _EES_, _Silver_ to _EEP_ and _Gold_ to _EEU_.
+2. Check using:
+
+```ruby
+project.feature_available?(:feature_symbol)
+```
+
+## Restricting global features (instance)
+
+However, for features such as [Geo](../administration/geo/replication/index.md) and
+[Load balancing](../administration/database_load_balancing.md), which cannot be restricted
+to only a subset of projects or namespaces, the check will be made directly in
+the instance license.
+
+1. Add the feature symbol on `EES_FEATURES`, `EEP_FEATURES` or `EEU_FEATURES` constants in
+ `ee/app/models/license.rb`.
+2. Add the same feature symbol to `GLOBAL_FEATURES`
+3. Check using:
+
+```ruby
+License.feature_available?(:feature_symbol)
+```
diff --git a/doc/development/licensing.md b/doc/development/licensing.md
index 0e71cd47481..0db90d2872f 100644
--- a/doc/development/licensing.md
+++ b/doc/development/licensing.md
@@ -88,9 +88,11 @@ Definitions
GitLab means GitLab Inc. and its affiliates and subsidiaries.
-## Requesting Approval for Licenses
+## Requesting Approval for Licenses or any other Intellectual Property
-Libraries that are not listed in the [Acceptable Licenses][Acceptable-Licenses] or [Unacceptable Licenses][Unacceptable-Licenses] list can be submitted to the legal team for review. Please email `legal@gitlab.com` with the details. After a decision has been made, the original requestor is responsible for updating this document.
+Libraries that are not already approved and listed on the [Acceptable Licenses][Acceptable-Licenses] list or that may be listed on the [Unacceptable Licenses][Unacceptable-Licenses] list may be submitted to the legal team for review and use on a case-by-case basis. Please email `legal@gitlab.com` with the details of how the software will be used, whether or not it will be modified, and how it will be distributed (if at all). After a decision has been made, the original requestor is responsible for updating this document, if applicable. Not all approvals will be approved for universal use and may continue to remain on the Unacceptable License list.
+
+All inquiries relating to patents should be directed to the Legal team.
## Notes
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index 0c326eeb851..9b26f691b55 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -186,7 +186,11 @@ end
When adding a foreign-key constraint to either an existing or new
column remember to also add a index on the column.
-This is _required_ for all foreign-keys.
+This is **required** for all foreign-keys, e.g., to support efficient cascading
+deleting: when a lot of rows in a table get deleted, the referenced records need
+to be deleted too. The database has to look for corresponding records in the
+referenced table. Without an index, this will result in a sequential scan on the
+table which can take a long time.
Here's an example where we add a new column with a foreign key
constraint. Note it includes `index: true` to create an index for it.
diff --git a/doc/development/new_fe_guide/development/accessibility.md b/doc/development/new_fe_guide/development/accessibility.md
index 8420a504ec4..81a29170129 100644
--- a/doc/development/new_fe_guide/development/accessibility.md
+++ b/doc/development/new_fe_guide/development/accessibility.md
@@ -21,6 +21,7 @@ On the other hand, if an icon is crucial to understand the context we should do
## Form inputs
In forms we should use the `for` attribute in the label statement:
+
```
<div>
<label for="name">Fill in your name:</label>
diff --git a/doc/development/new_fe_guide/development/components.md b/doc/development/new_fe_guide/development/components.md
index 8ae58d30c35..963ce53423b 100644
--- a/doc/development/new_fe_guide/development/components.md
+++ b/doc/development/new_fe_guide/development/components.md
@@ -17,5 +17,5 @@ D3 is very popular across many projects outside of GitLab:
Within GitLab, D3 has been used for the following notable features
-- [Prometheus graphs](https://docs.gitlab.com/ee/user/project/integrations/prometheus.html)
+- [Prometheus graphs](../../../user/project/integrations/prometheus.md)
- Contribution calendars
diff --git a/doc/development/new_fe_guide/tips.md b/doc/development/new_fe_guide/tips.md
index 889a5aab2b7..4564f678ec0 100644
--- a/doc/development/new_fe_guide/tips.md
+++ b/doc/development/new_fe_guide/tips.md
@@ -10,16 +10,16 @@ yarn clean
## Creating feature flags in development
-The process for creating a feature flag is the same as [enabling a feature flag in development](https://docs.gitlab.com/ee/development/feature_flags.html#enabling-a-feature-flag-in-development).
+The process for creating a feature flag is the same as [enabling a feature flag in development](../feature_flags.md#enabling-a-feature-flag-in-development).
Your feature flag can now be:
-- [made available to the frontend](https://docs.gitlab.com/ee/development/feature_flags.html#frontend) via the `gon`
-- queried in [tests](https://docs.gitlab.com/ee/development/feature_flags.html#specs)
+- [made available to the frontend](../feature_flags.md#frontend) via the `gon`
+- queried in [tests](../feature_flags.md#specs)
- queried in HAML templates and ruby files via the `Feature.enabled?(:my_shiny_new_feature_flag)` method
### More on feature flags
-- [Deleting a feature flag](https://docs.gitlab.com/ee/api/features.html#delete-a-feature)
-- [Manage feature flags](https://docs.gitlab.com/ee/development/feature_flags.html)
-- [Feature flags API](https://docs.gitlab.com/ee/api/features.html)
+- [Deleting a feature flag](../../api/features.md#delete-a-feature)
+- [Manage feature flags](../feature_flags.md)
+- [Feature flags API](../../api/features.md)
diff --git a/doc/development/packages.md b/doc/development/packages.md
new file mode 100644
index 00000000000..ab0c5f9904d
--- /dev/null
+++ b/doc/development/packages.md
@@ -0,0 +1,68 @@
+# Packages **[PREMIUM]**
+
+This document will guide you through adding another [package management system](../administration/packages.md) support to GitLab.
+
+See already supported package types in [Packages documentation](../administration/packages.md)
+
+Since GitLab packages' UI is pretty generic, it is possible to add new
+package system support by solely backend changes. This guide is superficial and does
+not cover the way the code should be written. However, you can find a good example
+by looking at existing merge requests with Maven and NPM support:
+
+- [NPM registry support](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8673).
+- [Maven repository](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/6607).
+- [Instance level endpoint for Maven repository](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8757)
+
+## General information
+
+The existing database model requires the following:
+
+- Every package belongs to a project.
+- Every package file belongs to a package.
+- A package can have one or more package files.
+- The package model is based on storing information about the package and its version.
+
+## API endpoints
+
+Package systems work with GitLab via API. For example `ee/lib/api/npm_packages.rb`
+implements API endpoints to work with NPM clients. So, the first thing to do is to
+add a new `ee/lib/api/your_name_packages.rb` file with API endpoints that are
+necessary to make the package system client to work. Usually that means having
+endpoints like:
+
+- GET package information.
+- GET package file content.
+- PUT upload package.
+
+Since the packages belong to a project, it's expected to have project-level endpoint
+for uploading and downloading them. For example:
+
+```
+GET https://gitlab.com/api/v4/projects/<your_project_id>/packages/npm/
+PUT https://gitlab.com/api/v4/projects/<your_project_id>/packages/npm/
+```
+
+Group-level and instance-level endpoints are good to have but are optional.
+
+NOTE: **Note:**
+To avoid name conflict for instance-level endpoints we use
+[the package naming convention](../user/project/packages/npm_registry.md#package-naming-convention)
+
+## Configuration
+
+GitLab has a `packages` section in its configuration file (`gitlab.rb`).
+It applies to all package systems supported by GitLab. Usually you don't need
+to add anything there.
+
+Packages can be configured to use object storage, therefore your code must support it.
+
+## Database
+
+The current database model allows you to store a name and a version for each package.
+Every time you upload a new package, you can either create a new record of `Package`
+or add files to existing record. `PackageFile` should be able to store all file-related
+information like the file `name`, `side`, `sha1`, etc.
+
+If there is specific data necessary to be stored for only one package system support,
+consider creating a separate metadata model. See `packages_maven_metadata` table
+and `Packages::MavenMetadatum` model as example for package specific data.
diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md
index dcb32c89f65..28a12572961 100644
--- a/doc/development/rake_tasks.md
+++ b/doc/development/rake_tasks.md
@@ -12,6 +12,40 @@ The `setup` task is an alias for `gitlab:setup`.
This tasks calls `db:reset` to create the database, calls `add_limits_mysql` that adds limits to the database schema in case of a MySQL database and finally it calls `db:seed_fu` to seed the database.
Note: `db:setup` calls `db:seed` but this does nothing.
+### Seeding issues for all or a given project
+
+You can seed issues for all or a given project with the `gitlab:seed:issues`
+task:
+
+```shell
+# All projects
+bin/rake gitlab:seed:issues
+
+# A specific project
+bin/rake "gitlab:seed:issues[group-path/project-path]"
+```
+
+By default, this seeds an average of 2 issues per week for the last 5 weeks per
+project.
+
+#### Seeding issues for Insights charts **[ULTIMATE]**
+
+You can seed issues specifically for working with the
+[Insights charts](../user/group/insights/index.md) with the
+`gitlab:seed:insights:issues` task:
+
+```shell
+# All projects
+bin/rake gitlab:seed:insights:issues
+
+# A specific project
+bin/rake "gitlab:seed:insights:issues[group-path/project-path]"
+```
+
+By default, this seeds an average of 10 issues per week for the last 52 weeks
+per project. All issues will also be randomly labeled with team, type, severity,
+and priority.
+
### Automation
If you're very sure that you want to **wipe the current database** and refill
@@ -74,11 +108,13 @@ To make sure that indices still fit. You could find great details in:
In order to run the test you can use the following commands:
-- `rake spec` to run the rspec suite
-- `rake karma` to run the karma test suite
-- `rake gitlab:test` to run all the tests
+- `bin/rake spec` to run the rspec suite
+- `bin/rake spec:unit` to run the only the unit tests
+- `bin/rake spec:integration` to run the only the integration tests
+- `bin/rake spec:system` to run the only the system tests
+- `bin/rake karma` to run the karma test suite
-Note: `rake spec` takes significant time to pass.
+Note: `bin/rake spec` takes significant time to pass.
Instead of running full test suite locally you can save a lot of time by running
a single test or directory related to your changes. After you submit merge request
CI will run full test suite for you. Green CI status in the merge request means
@@ -87,6 +123,9 @@ full test suite is passed.
Note: You can't run `rspec .` since this will try to run all the `_spec.rb`
files it can find, also the ones in `/tmp`
+Note: You can pass RSpec command line options to the `spec:unit`,
+`spec:integration`, and `spec:system` tasks, e.g. `bin/rake "spec:unit[--tag ~geo --dry-run]"`.
+
To run a single test file you can use:
- `bin/rspec spec/controllers/commit_controller_spec.rb` for a rspec test
diff --git a/doc/development/rolling_out_changes_using_feature_flags.md b/doc/development/rolling_out_changes_using_feature_flags.md
index 8d35a4ecee2..84028b1b342 100644
--- a/doc/development/rolling_out_changes_using_feature_flags.md
+++ b/doc/development/rolling_out_changes_using_feature_flags.md
@@ -65,15 +65,14 @@ the worst case scenario, which we should optimise for, our total cost is now 20.
If we had used a feature flag, things would have been very different. We don't
need to revert a release, and because feature flags are disabled by default we
don't need to revert and pick any Git commits. In fact, all we have to do is
-disable the feature, and _maybe_ perform some cleanup. Let's say that the cost
-of this is 1. In this case, our best case cost is 11: 10 to build the feature,
-and 1 to add the feature flag. The worst case cost is now 12: 10 to build the
-feature, 1 to add the feature flag, and 1 to disable it.
+disable the feature, and in the worst case, perform cleanup. Let's say that
+the cost of this is 2. In this case, our best case cost is 11: 10 to build the
+feature, and 1 to add the feature flag. The worst case cost is now 13: 10 to
+build the feature, 1 to add the feature flag, and 2 to disable and clean up.
Here we can see that in the best case scenario the work necessary is only a tiny
bit more compared to not using a feature flag. Meanwhile, the process of
-reverting our changes has been made significantly cheaper, to the point of being
-trivial.
+reverting our changes has been made significantly and reliably cheaper.
In other words, feature flags do not slow down the development process. Instead,
they speed up the process as managing incidents now becomes _much_ easier. Once
@@ -103,7 +102,7 @@ GitLab's feature library (using
[Flipper](https://github.com/jnunemaker/flipper), and covered in the [Feature
Flags](feature_flags.md) guide) supports rolling out changes to a percentage of
users. This in turn can be controlled using [GitLab
-chatops](https://docs.gitlab.com/ee/ci/chatops/).
+chatops](../ci/chatops/README.md).
For an up to date list of feature flag commands please see [the source
code](https://gitlab.com/gitlab-com/chatops/blob/master/lib/chatops/commands/feature.rb).
@@ -201,10 +200,9 @@ isn't gated by a License or Plan.
### Undefined feature flags default to "on"
-An important side-effect of the [implicit feature
-flags][#implicit-feature-flags] mentioned above is that unless the feature is
-explicitly disabled or limited to a percentage of users, the feature flag check
-will default to `true`.
+An important side-effect of the [implicit feature flags](#implicit-feature-flags)
+mentioned above is that unless the feature is explicitly disabled or limited to a
+percentage of users, the feature flag check will default to `true`.
As an example, if you were to ship the backend half of a feature behind a flag,
you'd want to explicitly disable that flag until the frontend half is also ready
diff --git a/doc/development/routing.md b/doc/development/routing.md
new file mode 100644
index 00000000000..e9c0ad8d4e8
--- /dev/null
+++ b/doc/development/routing.md
@@ -0,0 +1,63 @@
+# Routing
+
+The GitLab backend is written primarily with Rails so it uses [Rails
+routing](https://guides.rubyonrails.org/routing.html). Beside Rails best
+practices, there are few rules unique to the GitLab application. To
+support subgroups, GitLab project and group routes use the wildcard
+character to match project and group routes. For example, we might have
+a path such as:
+
+ /gitlab-com/customer-success/north-america/west/customerA
+
+However, paths can be ambiguous. Consider the following example:
+
+ /gitlab-com/edit
+
+It's ambiguous whether there is a subgroup named `edit` or whether
+this is a special endpoint to edit the `gitlab-com` group.
+
+To eliminate the ambiguity and to make the backend easier to maintain,
+we introduced the `/-/` scope. The purpose of it is to separate group or
+project paths from the rest of the routes. Also it helps to reduce the
+number of [reserved names](../user/reserved_names.md).
+
+## Global routes
+
+We have a number of global routes. For example:
+
+ /-/health
+ /-/metrics
+
+## Group routes
+
+Every group route must be under the `/-/` scope.
+
+Examples:
+
+ gitlab-org/-/edit
+ gitlab-org/-/activity
+ gitlab-org/-/security/dashboard
+ gitlab-org/serverless/-/activity
+
+To achieve that, use the `scope '-'` method.
+
+## Project routes
+
+Every project route must be under the `/-/` scope, except cases where a Git
+client or other software requires something different.
+
+Examples:
+
+ gitlab-org/gitlab-ce/-/activity
+ gitlab-org/gitlab-ce/-/jobs/123
+ gitlab-org/gitlab-ce/-/settings/repository
+ gitlab-org/serverless/runtimes/-/settings/repository
+
+Currently, only some project routes are placed under the `/-/` scope. However,
+you can help us migrate more of them! To migrate project routes:
+
+1. Modify existing routes by adding `-` scope.
+1. Add redirects for legacy routes by using `Gitlab::Routing.redirect_legacy_paths`.
+1. Create a technical debt issue to remove deprecated routes in later releases.
+
+To get started, see an [example merge request](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/28435).
diff --git a/doc/development/session.md b/doc/development/session.md
new file mode 100644
index 00000000000..9edce3dbda0
--- /dev/null
+++ b/doc/development/session.md
@@ -0,0 +1,65 @@
+# Accessing session data
+
+Session data in GitLab is stored in Redis and can be accessed in a variety of ways.
+
+During a web request, for example:
+
+- Rails provides access to the session from within controllers through [`ActionDispatch::Session`](https://guides.rubyonrails.org/action_controller_overview.html#session).
+- Outside of controllers, it is possible to access the session through `Gitlab::Session`.
+
+Outside of a web request it is still possible to access sessions stored in Redis. For example:
+
+- Session IDs and contents can be [looked up directly in Redis](#redis).
+- Data about the UserAgent associated with the session can be accessed through `ActiveSession`.
+
+When storing values in a session it is best to:
+
+- Use simple primitives and avoid storing objects to avoid marshaling complications.
+- Clean up after unneeded variables to keep memory usage in Redis down.
+
+## Gitlab::Session
+
+Sometimes you might want to persist data in the session instead of another store like the database. `Gitlab::Session` lets you access this without passing the session around extensively. For example, you could access it from within a policy without having to pass the session through to each place permissions are checked from.
+
+The session has a hash-like interface, just like when using it from a controller. There is also `NamespacedSessionStore` for storing key-value data in a hash.
+
+```ruby
+# Lookup a value stored in the current session
+Gitlab::Session.current[:my_feature]
+
+# Modify the current session stored in redis
+Gitlab::Session.current[:my_feature] = value
+
+# Store key-value data namespaced under a key
+Gitlab::NamespacedSessionStore.new(:my_feature)[some_key] = value
+
+# Set the session for a block of code, such as for tests
+Gitlab::Session.with_session(my_feature: value) do
+ # Code that uses Session.current[:my_feature]
+end
+```
+
+## Redis
+
+Session data can be accessed directly through Redis. This can let you check up on a browser session when debugging.
+
+```ruby
+# Get a list of sessions
+session_ids = Gitlab::Redis::SharedState.with do |redis|
+ redis.smembers("#{Gitlab::Redis::SharedState::USER_SESSIONS_LOOKUP_NAMESPACE}:#{user.id}")
+end
+
+# Retrieve a specific session
+session_data = Gitlab::Redis::SharedState.with { |redis| redis.get("#{Gitlab::Redis::SharedState::SESSION_NAMESPACE}:#{session_id}") }
+Marshal.load(session_data)
+```
+
+## Getting device information with ActiveSession
+
+The [**Active Sessions** page on a user's profile](../user/profile/active_sessions.md) displays information about the device used to access each session. The methods used there to list sessions can also be useful for development.
+
+```ruby
+# Get list of sessions for a given user
+# Includes session_id and data from the UserAgent
+ActiveSession.list(user)
+```
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index e41148360f2..71e3b7740cb 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -2,19 +2,29 @@
## Test Design
-Testing at GitLab is a first class citizen, not an afterthought. It's important we consider the design of our tests
-as we do the design of our features.
+Testing at GitLab is a first class citizen, not an afterthought. It's important we consider the design of our tests
+as we do the design of our features.
-When implementing a feature, we think about developing the right capabilities the right way, which helps us
-narrow our scope to a manageable level. When implementing tests for a feature, we must think about developing
-the right tests, but then cover _all_ the important ways the test may fail, which can quickly widen our scope to
+When implementing a feature, we think about developing the right capabilities the right way, which helps us
+narrow our scope to a manageable level. When implementing tests for a feature, we must think about developing
+the right tests, but then cover _all_ the important ways the test may fail, which can quickly widen our scope to
a level that is difficult to manage.
-Test heuristics can help solve this problem. They concisely address many of the common ways bugs
-manifest themselves within our code. When designing our tests, take time to review known test heuristics to inform
-our test design. We can find some helpful heuristics documented in the Handbook in the
+Test heuristics can help solve this problem. They concisely address many of the common ways bugs
+manifest themselves within our code. When designing our tests, take time to review known test heuristics to inform
+our test design. We can find some helpful heuristics documented in the Handbook in the
[Test Design](https://about.gitlab.com/handbook/engineering/quality/guidelines/test-engineering/test-design/) section.
+## Run tests against MySQL
+
+By default, tests are only run against PostgreSQL, but you can run them on
+demand against MySQL by following one of the following conventions:
+
+| Convention | Valid example |
+|:----------------------|:-----------------------------|
+| Include `mysql` in your branch name | `enhance-mysql-support` |
+| Include `[run mysql]` in your commit message | `Fix MySQL support<br><br>[run mysql]` |
+
## Test speed
GitLab has a massive test suite that, without [parallelization], can take hours
@@ -184,11 +194,11 @@ instead of 30+ seconds in case of a regular `spec_helper`.
### `let` variables
GitLab's RSpec suite has made extensive use of `let`(along with it strict, non-lazy
-version `let!`) variables to reduce duplication. However, this sometimes [comes at the cost of clarity][lets-not],
+version `let!`) variables to reduce duplication. However, this sometimes [comes at the cost of clarity][lets-not],
so we need to set some guidelines for their use going forward:
- `let!` variables are preferable to instance variables. `let` variables
- are preferable to `let!` variables. Local variables are preferable to
+ are preferable to `let!` variables. Local variables are preferable to
`let` variables.
- Use `let` to reduce duplication throughout an entire spec file.
- Don't use `let` to define variables used by a single test; define them as
@@ -199,8 +209,8 @@ so we need to set some guidelines for their use going forward:
- Try to avoid overriding the definition of one `let` variable with another.
- Don't define a `let` variable that's only used by the definition of another.
Use a helper method instead.
-- `let!` variables should be used only in case if strict evaluation with defined
- order is required, otherwise `let` will suffice. Remember that `let` is lazy and won't
+- `let!` variables should be used only in case if strict evaluation with defined
+ order is required, otherwise `let` will suffice. Remember that `let` is lazy and won't
be evaluated until it is referenced.
[lets-not]: https://robots.thoughtbot.com/lets-not
@@ -240,6 +250,36 @@ it 'is overdue' do
end
```
+### Feature flags in tests
+
+All feature flags are stubbed to be enabled by default in our Ruby-based
+tests.
+
+To disable a feature flag in a test, use the `stub_feature_flags`
+helper. For example, to globally disable the `ci_live_trace` feature
+flag in a test:
+
+```ruby
+stub_feature_flags(ci_live_trace: false)
+
+Feature.enabled?(:ci_live_trace) # => false
+```
+
+If you wish to set up a test where a feature flag is disabled for some
+actors and not others, you can specify this in options passed to the
+helper. For example, to disable the `ci_live_trace` feature flag for a
+specifc project:
+
+```ruby
+project1, project2 = build_list(:project, 2)
+
+# Feature will only be disabled for project1
+stub_feature_flags(ci_live_trace: { enabled: false, thing: project1 })
+
+Feature.enabled?(:ci_live_trace, project1) # => false
+Feature.enabled?(:ci_live_trace, project2) # => true
+```
+
### Pristine test environments
The code exercised by a single GitLab test may access and modify many items of
diff --git a/doc/development/testing_guide/end_to_end/best_practices.md b/doc/development/testing_guide/end_to_end/best_practices.md
new file mode 100644
index 00000000000..89500ef9a90
--- /dev/null
+++ b/doc/development/testing_guide/end_to_end/best_practices.md
@@ -0,0 +1,38 @@
+# Best practices when writing end-to-end tests
+
+The majority of the end-to-end tests require some state to be built in the application for the tests to happen.
+
+A good example is a user being logged in as a pre-condition for testing the feature.
+
+But if the login feature is already covered with end-to-end tests through the GUI, there is no reason to perform such an expensive task to test the functionality of creating a project, or importing a repo, even if these features depend on a user being logged in. Let's see an example to make things clear.
+
+Let's say that, on average, the process to perform a successful login through the GUI takes 2 seconds.
+
+Now, realize that almost all tests need the user to be logged in, and that we need every test to run in isolation, meaning that tests cannot interfere with each other. This would mean that for every test the user needs to log in, and "waste 2 seconds".
+
+Now, multiply the number of tests per 2 seconds, and as your test suite grows, the time to run it grows with it, and this is not sustainable.
+
+An alternative to perform a login in a cheaper way would be having an endpoint (available only for testing) where we could pass the user's credentials as encrypted values as query strings, and then we would be redirected to the logged in home page if the credentials are valid. Let's say that, on average, this process takes only 200 miliseconds.
+
+You see the point right?
+
+Performing a login through the GUI for every test would cost a lot in terms of tests' execution.
+
+And there is another reason.
+
+Let's say that you don't follow the above suggestion, and depend on the GUI for the creation of every application state in order to test a specific feature. In this case we could be talking about the **Issues** feature, that depends on a project to exist, and the user to be logged in.
+
+What would happen if there was a bug in the project creation page, where the 'Create' button is disabled, not allowing for the creation of a project through the GUI, but the API logic is still working?
+
+In this case, instead of having only the project creation test failing, we would have many tests that depend on a project to be failing too.
+
+But, if we were following the best practices, only one test would be failing, and tests for other features that depend on a project to exist would continue to pass, since they could be creating the project behind the scenes interacting directly with the public APIs, ensuring a more reliable metric of test failure rate.
+
+Finally, interacting with the application only by its GUI generates a higher rate of test flakiness, and we want to avoid that at max.
+
+**The takeaways here are:**
+
+- Building state through the GUI is time consuming and it's not sustainable as the test suite grows.
+- When depending only on the GUI to create the application's state and tests fail due to front-end issues, we can't rely on the test failures rate, and we generate a higher rate of test flakiness.
+
+Now that we are aware of all of it, [let's go create some tests](quick_start_guide.md).
diff --git a/doc/development/testing_guide/end_to_end/dynamic_element_validation.md b/doc/development/testing_guide/end_to_end/dynamic_element_validation.md
new file mode 100644
index 00000000000..f7b3ca8bc89
--- /dev/null
+++ b/doc/development/testing_guide/end_to_end/dynamic_element_validation.md
@@ -0,0 +1,113 @@
+# Dynamic Element Validation
+
+We devised a solution to solve common test automation problems such as the dreaded `NoSuchElementException`.
+
+Other problems that dynamic element validations solve are...
+
+- When we perform an action with the mouse, we expect something to occur.
+- When our test is navigating to (or from) a page, we ensure that we are on the page we expect before
+test continuation.
+
+## How it works
+
+We interpret user actions on the page to have some sort of effect. These actions are
+
+- [Navigation](#navigation)
+- [Clicks](#clicks)
+
+### Navigation
+
+When a page is navigated to, there are elements that will always appear on the page unconditionally.
+
+Dynamic element validation is instituted when using
+
+```ruby
+Runtime::Browser.visit(:gitlab, Some::Page)
+```
+
+### Clicks
+
+When we perform a click within our tests, we expect something to occur. That something could be a component to now
+appear on the webpage, or the test to navigate away from the page entirely.
+
+Dynamic element validation is instituted when using
+
+```ruby
+click_element :my_element, Some::Page
+```
+
+### Required Elements
+
+#### Definition
+
+First it is important to define what a "required element" is.
+
+Simply put, a required element is a visible HTML element that appears on a UI component without any user input.
+
+"Visible" can be defined as
+
+- Not having any CSS preventing its display. E.g.: `display: none` or `width: 0px; height: 0px;`
+- Being able to be interacted with by the user
+
+"UI component" can be defined as
+
+- Anything the user sees
+- A button, a text field
+- A layer that sits atop the page
+
+#### Application
+
+Requiring elements is very easy. By adding `required: true` as a parameter to an `element`, you've now made it
+a requirement that the element appear on the page upon navigation.
+
+## Examples
+
+Given ...
+
+```ruby
+class MyPage < Page::Base
+ view 'app/views/view.html.haml' do
+ element :my_element, required: true
+ element :another_element, required: true
+ element :conditional_element
+ end
+
+ def open_layer
+ click_element :my_element, Layer::MyLayer
+ end
+end
+
+class Layer < Page::Component
+ view 'app/views/mylayer/layer.html.haml' do
+ element :message_content, required: true
+ end
+end
+```
+
+### Navigating
+
+Given the [source](#examples) ...
+
+```ruby
+Runtime::Browser.visit(:gitlab, Page::MyPage)
+
+execute_stuff
+```
+
+will invoke GitLab QA to scan `MyPage` for `my_element` and `another_element` to be on the page before continuing to
+`execute_stuff`
+
+### Clicking
+
+Given the [source](#examples) ...
+
+```ruby
+def open_layer
+ click_element :my_element, Layer::MyLayer
+end
+```
+
+will invoke GitLab QA to ensure that `message_content` appears on
+the Layer upon clicking `my_element`.
+
+This will imply that the Layer is indeed rendered before we continue our test.
diff --git a/doc/development/testing_guide/end_to_end/index.md b/doc/development/testing_guide/end_to_end/index.md
new file mode 100644
index 00000000000..afd81ff00b2
--- /dev/null
+++ b/doc/development/testing_guide/end_to_end/index.md
@@ -0,0 +1,167 @@
+# End-to-end Testing
+
+## What is end-to-end testing?
+
+End-to-end testing is a strategy used to check whether your application works
+as expected across the entire software stack and architecture, including
+integration of all micro-services and components that are supposed to work
+together.
+
+## Branch naming
+
+If your contribution contains **only** changes under the
+[`qa/` folder](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa), you can
+speed up the CI process by following some branch naming conventions. You have
+three choices:
+
+| Branch name | Valid example |
+|:----------------------|:-----------------------------|
+| Starting with `qa/` | `qa/new-oauth-login-test` |
+| Starting with `qa-` | `qa-new-oauth-login-test` |
+| Ending in `-qa` | `123-new-oauth-login-test-qa` |
+
+If your branch name matches any of the above, it will run only the QA-related
+jobs.
+If it does not, the whole application test suite will run (including QA-related
+jobs).
+
+## How do we test GitLab?
+
+We use [Omnibus GitLab][omnibus-gitlab] to build GitLab packages and then we
+test these packages using the [GitLab QA orchestrator][gitlab-qa] tool, which is
+a black-box testing framework for the API and the UI.
+
+### Testing nightly builds
+
+We run scheduled pipeline each night to test nightly builds created by Omnibus.
+You can find these nightly pipelines at [gitlab-org/quality/nightly/pipelines][quality-nightly-pipelines].
+Results are reported in the `#qa-nightly` Slack channel.
+
+### Testing staging
+
+We run scheduled pipeline each night to test staging.
+You can find these nightly pipelines at [gitlab-org/quality/staging/pipelines][quality-staging-pipelines].
+Results are reported in the `#qa-staging` Slack channel.
+
+### Testing code in merge requests
+
+#### Using the `package-and-qa` job
+
+It is possible to run end-to-end tests for a merge request, eventually being run in
+a pipeline in the [`gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/) project,
+by triggering the `package-and-qa` manual action in the `test` stage (not
+available for forks).
+
+**This runs end-to-end tests against a custom Omnibus package built from your
+merge request's changes.**
+
+Manual action that starts end-to-end tests is also available in merge requests
+in [Omnibus GitLab][omnibus-gitlab].
+
+Below you can read more about how to use it and how does it work.
+
+#### How does it work?
+
+Currently, we are using _multi-project pipeline_-like approach to run QA
+pipelines.
+
+![QA on merge requests CI/CD architecture](../img/qa_on_merge_requests_cicd_architecture.png)
+
+<details>
+<summary>Show mermaid source</summary>
+<pre>
+graph LR
+ A1 -.->|1. Triggers an omnibus-gitlab pipeline and wait for it to be done| A2
+ B2[<b>`Trigger-qa` stage</b><br />`Trigger:qa-test` job] -.->|2. Triggers a gitlab-qa pipeline and wait for it to be done| A3
+
+subgraph gitlab-ce/ee pipeline
+ A1[<b>`test` stage</b><br />`package-and-qa` job]
+ end
+
+subgraph omnibus-gitlab pipeline
+ A2[<b>`Trigger-docker` stage</b></b><br />`Trigger:gitlab-docker` job] -->|once done| B2
+ end
+
+subgraph gitlab-qa pipeline
+ A3>QA jobs run] -.->|3. Reports back the pipeline result to the `package-and-qa` job<br />and post the result on the original commit tested| A1
+ end
+</pre>
+</details>
+
+1. Developer triggers a manual action, that can be found in CE / EE merge
+ requests. This starts a chain of pipelines in multiple projects.
+
+1. The script being executed triggers a pipeline in [Omnibus GitLab][omnibus-gitlab]
+ and waits for the resulting status. We call this a _status attribution_.
+
+1. GitLab packages are being built in the [Omnibus GitLab][omnibus-gitlab]
+ pipeline. Packages are then pushed to its Container Registry.
+
+1. When packages are ready, and available in the registry, a final step in the
+ [Omnibus GitLab][omnibus-gitlab] pipeline, triggers a new
+ GitLab QA pipeline (those with access can view them at `https://gitlab.com/gitlab-org/gitlab-qa/pipelines`). It also waits for a resulting status.
+
+1. GitLab QA pulls images from the registry, spins-up containers and runs tests
+ against a test environment that has been just orchestrated by the `gitlab-qa`
+ tool.
+
+1. The result of the GitLab QA pipeline is being
+ propagated upstream, through Omnibus, back to the CE / EE merge request.
+
+#### Using the `review-qa-all` jobs
+
+On every pipeline during the `test` stage, the `review-qa-smoke` job is
+automatically started: it runs the QA smoke suite against the
+[Review App][review-apps].
+
+You can also manually start the `review-qa-all`: it runs the full QA suite
+against the [Review App][review-apps].
+
+**This runs end-to-end tests against a Review App based on [the official GitLab
+Helm chart][helm-chart], itself deployed with custom
+[Cloud Native components][cng] built from your merge request's changes.**
+
+See [Review Apps][review-apps] for more details about Review Apps.
+
+[helm-chart]: https://gitlab.com/charts/gitlab/
+[cng]: https://gitlab.com/gitlab-org/build/CNG
+
+## How do I write tests?
+
+In order to write new tests, you first need to learn more about GitLab QA
+architecture. See the [documentation about it][gitlab-qa-architecture].
+
+Once you decided where to put [test environment orchestration scenarios] and
+[instance-level scenarios], take a look at the [GitLab QA README][instance-qa-readme],
+the [GitLab QA orchestrator README][gitlab-qa-readme], and [the already existing
+instance-level scenarios][instance-level scenarios].
+
+Continued reading:
+
+- [Quick Start Guide](quick_start_guide.md)
+- [Style Guide](style_guide.md)
+- [Best Practices](best_practices.md)
+
+## Where can I ask for help?
+
+You can ask question in the `#quality` channel on Slack (GitLab internal) or
+you can find an issue you would like to work on in
+[the `gitlab-ce` issue tracker][gitlab-ce-issues],
+[the `gitlab-ee` issue tracker][gitlab-ce-issues], or
+[the `gitlab-qa` issue tracker][gitlab-qa-issues].
+
+[omnibus-gitlab]: https://gitlab.com/gitlab-org/omnibus-gitlab
+[gitlab-qa]: https://gitlab.com/gitlab-org/gitlab-qa
+[gitlab-qa-readme]: https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md
+[quality-nightly-pipelines]: https://gitlab.com/gitlab-org/quality/nightly/pipelines
+[quality-staging-pipelines]: https://gitlab.com/gitlab-org/quality/staging/pipelines
+[review-apps]: ../review_apps.md
+[gitlab-qa-architecture]: https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/architecture.md
+[gitlab-qa-issues]: https://gitlab.com/gitlab-org/gitlab-qa/issues?label_name%5B%5D=new+scenario
+[gitlab-ce-issues]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name[]=QA&label_name[]=test
+[gitlab-ee-issues]: https://gitlab.com/gitlab-org/gitlab-ee/issues?label_name[]=QA&label_name[]=test
+[test environment orchestration scenarios]: https://gitlab.com/gitlab-org/gitlab-qa/tree/master/lib/gitlab/qa/scenario
+[instance-level scenarios]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/qa/specs/features
+[Page objects documentation]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/qa/page/README.md
+[instance-qa-readme]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/README.md
+[instance-qa-examples]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/qa
diff --git a/doc/development/testing_guide/end_to_end/page_objects.md b/doc/development/testing_guide/end_to_end/page_objects.md
new file mode 100644
index 00000000000..73e1fd862c1
--- /dev/null
+++ b/doc/development/testing_guide/end_to_end/page_objects.md
@@ -0,0 +1,167 @@
+# Page objects in GitLab QA
+
+In GitLab QA we are using a known pattern, called _Page Objects_.
+
+This means that we have built an abstraction for all GitLab pages that we use
+to drive GitLab QA scenarios. Whenever we do something on a page, like filling
+in a form, or clicking a button, we do that only through a page object
+associated with this area of GitLab.
+
+For example, when GitLab QA test harness signs in into GitLab, it needs to fill
+in a user login and user password. In order to do that, we have a class, called
+`Page::Main::Login` and `sign_in_using_credentials` methods, that is the only
+piece of the code, that has knowledge about `user_login` and `user_password`
+fields.
+
+## Why do we need that?
+
+We need page objects, because we need to reduce duplication and avoid problems
+whenever someone changes some selectors in GitLab's source code.
+
+Imagine that we have a hundred specs in GitLab QA, and we need to sign into
+GitLab each time, before we make assertions. Without a page object one would
+need to rely on volatile helpers or invoke Capybara methods directly. Imagine
+invoking `fill_in :user_login` in every `*_spec.rb` file / test example.
+
+When someone later changes `t.text_field :login` in the view associated with
+this page to `t.text_field :username` it will generate a different field
+identifier, what would effectively break all tests.
+
+Because we are using `Page::Main::Login.act { sign_in_using_credentials }`
+everywhere, when we want to sign into GitLab, the page object is the single
+source of truth, and we will need to update `fill_in :user_login`
+to `fill_in :user_username` only in a one place.
+
+## What problems did we have in the past?
+
+We do not run QA tests for every commit, because of performance reasons, and
+the time it would take to build packages and test everything.
+
+That is why when someone changes `t.text_field :login` to
+`t.text_field :username` in the _new session_ view we won't know about this
+change until our GitLab QA nightly pipeline fails, or until someone triggers
+`package-and-qa` action in their merge request.
+
+Obviously such a change would break all tests. We call this problem a _fragile
+tests problem_.
+
+In order to make GitLab QA more reliable and robust, we had to solve this
+problem by introducing coupling between GitLab CE / EE views and GitLab QA.
+
+## How did we solve fragile tests problem?
+
+Currently, when you add a new `Page::Base` derived class, you will also need to
+define all selectors that your page objects depends on.
+
+Whenever you push your code to CE / EE repository, `qa:selectors` sanity test
+job is going to be run as a part of a CI pipeline.
+
+This test is going to validate all page objects that we have implemented in
+`qa/page` directory. When it fails, you will be notified about missing
+or invalid views / selectors definition.
+
+## How to properly implement a page object?
+
+We have built a DSL to define coupling between a page object and GitLab views
+it is actually implemented by. See an example below.
+
+```ruby
+module Page
+ module Main
+ class Login < Page::Base
+ view 'app/views/devise/passwords/edit.html.haml' do
+ element :password_field
+ element :password_confirmation
+ element :change_password_button
+ end
+
+ view 'app/views/devise/sessions/_new_base.html.haml' do
+ element :login_field
+ element :password_field
+ element :sign_in_button
+ end
+
+ # ...
+ end
+ end
+end
+```
+
+### Defining Elements
+
+The `view` DSL method will correspond to the rails View, partial, or vue component that renders the elements.
+
+The `element` DSL method in turn declares an element for which a corresponding
+`qa-element-name-dasherized` CSS class will need to be added to the view file.
+
+You can also define a value (String or Regexp) to match to the actual view
+code but **this is deprecated** in favor of the above method for two reasons:
+
+- Consistency: there is only one way to define an element
+- Separation of concerns: QA uses dedicated CSS classes instead of reusing code
+ or classes used by other components (e.g. `js-*` classes etc.)
+
+```ruby
+view 'app/views/my/view.html.haml' do
+ # Implicitly require `.qa-logout-button` CSS class to be present in the view
+ element :logout_button
+
+ ## This is deprecated and forbidden by the `QA/ElementWithPattern` RuboCop cop.
+ # Require `f.submit "Sign in"` to be present in `my/view.html.haml
+ element :my_button, 'f.submit "Sign in"' # rubocop:disable QA/ElementWithPattern
+
+ ## This is deprecated and forbidden by the `QA/ElementWithPattern` RuboCop cop.
+ # Match every line in `my/view.html.haml` against
+ # `/link_to .* "My Profile"/` regexp.
+ element :profile_link, /link_to .* "My Profile"/ # rubocop:disable QA/ElementWithPattern
+end
+```
+
+### Adding Elements to a View
+
+Given the following elements...
+
+```ruby
+view 'app/views/my/view.html.haml' do
+ element :login_field
+ element :password_field
+ element :sign_in_button
+end
+```
+
+To add these elements to the view, you must change the rails View, partial, or vue component by adding a `qa-element-descriptor` class
+for each element defined.
+
+In our case, `qa-login-field`, `qa-password-field` and `qa-sign-in-button`
+
+**app/views/my/view.html.haml**
+
+```haml
+= f.text_field :login, class: "form-control top qa-login-field", autofocus: "autofocus", autocapitalize: "off", autocorrect: "off", required: true, title: "This field is required."
+= f.password_field :password, class: "form-control bottom qa-password-field", required: true, title: "This field is required."
+= f.submit "Sign in", class: "btn btn-success qa-sign-in-button"
+```
+
+Things to note:
+
+- The CSS class must be `kebab-cased` (separated with hyphens "`-`")
+- If the element appears on the page unconditionally, add `required: true` to the element. See
+[Dynamic element validation](dynamic_element_validation.md)
+
+## Running the test locally
+
+During development, you can run the `qa:selectors` test by running
+
+```shell
+bin/qa Test::Sanity::Selectors
+```
+
+from within the `qa` directory.
+
+## Where to ask for help?
+
+If you need more information, ask for help on `#quality` channel on Slack
+(internal, GitLab Team only).
+
+If you are not a Team Member, and you still need help to contribute, please
+open an issue in GitLab CE issue tracker with the `~QA` label.
diff --git a/doc/development/testing_guide/end_to_end/quick_start_guide.md b/doc/development/testing_guide/end_to_end/quick_start_guide.md
new file mode 100644
index 00000000000..1802f4792e0
--- /dev/null
+++ b/doc/development/testing_guide/end_to_end/quick_start_guide.md
@@ -0,0 +1,587 @@
+# Writing end-to-end tests step-by-step
+
+In this tutorial, you will find different examples, and the steps involved, in the creation of end-to-end (_e2e_) tests for GitLab CE and GitLab EE, using GitLab QA.
+
+> When referring to end-to-end tests in this document, this means testing a specific feature end-to-end, such as a user logging in, the creation of a project, the management of labels, breaking down epics into sub-epics and issues, etc.
+
+## Important information before we start writing tests
+
+It's important to understand that end-to-end tests of isolated features, such as the ones described in the above note, doesn't mean that everything needs to happen through the GUI.
+
+If you don't exactly understand what we mean by **not everything needs to happen through the GUI,** please make sure you've read the [best practices](best_practices.md) before moving on.
+
+## This document covers the following items:
+
+- [0.](#0-are-end-to-end-tests-needed) Identifying if end-to-end tests are really needed
+- [1.](#1-identifying-the-devops-stage) Identifying the [DevOps stage](https://about.gitlab.com/stages-devops-lifecycle/) of the feature that you are going to cover with end-to-end tests
+- [2.](#2-test-skeleton) Creating the skeleton of the test file (`*_spec.rb`)
+- [3.](#3-test-cases-mvc) The [MVC](https://about.gitlab.com/handbook/values/#minimum-viable-change-mvc) of the test cases' logic
+- [4.](#4-extracting-duplicated-code) Extracting duplicated code into methods
+- [5.](#5-tests-pre-conditions-using-resources-and-page-objects) Tests' pre-conditions (`before :context` and `before`) using resources and [Page Objects]
+- [6.](#6-optimization) Optimizing the test suite
+- [7.](#7-resources) Using and implementing resources
+- [8.](#8-page-objects) Moving element definitions and methods to [Page Objects]
+
+### 0. Are end-to-end tests needed?
+
+At GitLab we respect the [test pyramid](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/testing_guide/testing_levels.md), and so, we recommend you check the code coverage of a specific feature before writing end-to-end tests, for both [CE](https://gitlab-org.gitlab.io/gitlab-ce/coverage-ruby/#_AllFiles) and [EE](https://gitlab-org.gitlab.io/gitlab-ee/coverage-ruby/#_AllFiles) projects.
+
+Sometimes you may notice that there is already good coverage in other test levels, and we can stay confident that if we break a feature, we will still have quick feedback about it, even without having end-to-end tests.
+
+If after this analysis you still think that end-to-end tests are needed, keep reading.
+
+### 1. Identifying the DevOps stage
+
+The GitLab QA end-to-end tests are organized by the different [stages in the DevOps lifecycle](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/qa/specs/features/browser_ui), and so, if you are creating tests for issue creation, for instance, you would locate the spec files under the `qa/qa/specs/features/browser_ui/2_plan/` directory since issue creation is part of the Plan stage.
+
+ In another case of a test for listing merged merge requests (MRs), the test should go under the `qa/qa/specs/features/browser_ui/3_create/` directory since merge requests are a feature from the Create stage.
+
+> There may be sub-directories inside the stages directories, for different features. For example: `.../browser_ui/2_plan/ee_epics/` and `.../browser_ui/2_plan/issues/`.
+
+Now, let's say we want to create tests for the [scoped labels](https://about.gitlab.com/2019/04/22/gitlab-11-10-released/#scoped-labels) feature, available on GitLab EE Premium (this feature is part of the Plan stage.)
+
+> Because these tests are for a feature available only on GitLab EE, we need to create them in the [EE repository](https://gitlab.com/gitlab-org/gitlab-ee).
+
+Since [there is no specific directory for this feature](https://gitlab.com/gitlab-org/gitlab-ee/tree/master/qa/qa/specs/features/browser_ui/2_plan), we should create a sub-directory for it.
+
+Under `.../browser_ui/2_plan/`, let's create a sub-directory called `ee_scoped_labels/`.
+
+> Notice that since this feature is only available for GitLab EE we prefix the sub-directory with `ee_`.
+
+### 2. Test skeleton
+
+Inside the newly created sub-directory, let's create a file describing the test suite (e.g. `editing_scoped_labels_spec.rb`.)
+
+#### The `context` and `describe` blocks
+
+Specs have an outer `context` that indicates the DevOps stage. The next level is the `describe` block, that briefly states the subject of the test suite. See the following example:
+
+```ruby
+module QA
+ context 'Plan' do
+ describe 'Editing scoped labels on issues' do
+ end
+ end
+end
+```
+
+#### The `it` blocks
+
+Every test suite is composed of at least one `it` block, and a good way to start writing end-to-end tests is by writing test cases descriptions as `it` blocks. These might help you to think of different test scenarios. Take a look at the following example:
+
+```ruby
+module QA
+ context 'Plan' do
+ describe 'Editing scoped labels on issues' do
+ it 'replaces an existing label if it has the same key' do
+ end
+
+ it 'keeps both scoped labels when adding a label with a different key' do
+ end
+ end
+ end
+end
+```
+
+### 3. Test cases MVC
+
+For the [MVC](https://about.gitlab.com/handbook/values/#minimum-viable-change-mvc) of our test cases, let's say that we already have the application in the state needed for the tests, and then let's focus on the logic of the test cases only.
+
+To evolve the test cases drafted on step 2, let's imagine that the user is already logged into a GitLab EE instance, they already have at least a Premium license in use, there is already a project created, there is already an issue opened in the project, the issue already has a scoped label (e.g. `animal::fox`), there are other scoped labels (for the same scope and for a different scope (e.g. `animal::dolphin` and `plant::orchid`), and finally, the user is already on the issue's page. Let's also suppose that for every test case the application is in a clean state, meaning that one test case won't affect another.
+
+> Note: there are different approaches to creating an application state for end-to-end tests. Some of them are very time consuming and subject to failures, such as when using the GUI for all the pre-conditions of the tests. On the other hand, other approaches are more efficient, such as using the public APIs. The latter is more efficient since it doesn't depend on the GUI. We won't focus on this part yet, but it's good to keep it in mind.
+
+Let's now focus on the first test case.
+
+```ruby
+it 'replaces an existing label if it has the same key' do
+ # This implementation is only for tutorial purposes. We normally encapsulate elements in Page Objects (which we cover on section 8).
+ page.find('.block.labels .edit-link').click
+ page.find('.dropdown-menu-labels .dropdown-input-field').send_keys ['animal::dolphin', :enter]
+ page.find('#content-body').click
+ page.refresh
+
+ labels_block = page.find('.qa-labels-block')
+
+ expect(labels_block).to have_content('animal::dolphin')
+ expect(labels_block).not_to have_content('animal::fox')
+ expect(page).to have_content('added animal::dolphin label and removed animal::fox')
+end
+```
+
+> Notice that the test itself is simple. The most challenging part is the creation of the application state, which will be covered later.
+
+> The exemplified test case's MVC is not enough for the change to be merged, but it helps to build up the test logic. The reason is that we do not want to use locators directly in the tests, and tests **must** use [Page Objects] before they can be merged. This way we better separate the responsibilities, where the Page Objects encapsulate elements and methods that allow us to interact with pages, while the spec files describe the test cases in more business-related language.
+
+Below are the steps that the test covers:
+
+1. The test finds the 'Edit' link for the labels and clicks on it.
+2. Then it fills in the 'Assign labels' input field with the value 'animal::dolphin' and press enters.
+3. Then it clicks in the content body to apply the label and refreshes the page.
+4. Finally, the expectations check that the previous scoped label was removed and that the new one was added.
+
+Let's now see how the second test case would look.
+
+```ruby
+it 'keeps both scoped labels when adding a label with a different key' do
+ # This implementation is only for tutorial purposes. We normally encapsulate elements in Page Objects (which we cover on section 8).
+ page.find('.block.labels .edit-link').click
+ page.find('.dropdown-menu-labels .dropdown-input-field').send_keys ['plant::orchid', :enter]
+ page.find('#content-body').click
+ page.refresh
+
+ labels_block = page.find('.qa-labels-block')
+
+ expect(labels_block).to have_content('animal::fox')
+ expect(labels_block).to have_content('plant::orchid')
+ expect(page).to have_content('added animal::fox')
+ expect(page).to have_content('added plant::orchid')
+end
+```
+
+> Note that elements are always located using CSS selectors, and a good practice is to add test-specific selectors (this is called adding testability to the application and we will talk more about it later.) For example, the `labels_block` element uses the selector `.qa-labels-block`, which was added specifically for testing purposes.
+
+Below are the steps that the test covers:
+
+1. The test finds the 'Edit' link for the labels and clicks on it.
+2. Then it fills in the 'Assign labels' input field with the value 'plant::orchid' and press enters.
+3. Then it clicks in the content body to apply the label and refreshes the page.
+4. Finally, the expectations check that both scoped labels are present.
+
+> Similar to the previous test, this one is also very straightforward, but there is some code duplication. Let's address it.
+
+### 4. Extracting duplicated code
+
+If we refactor the tests created on step 3 we could come up with something like this:
+
+```ruby
+before do
+ ...
+
+ @initial_label = 'animal::fox'
+ @new_label_same_scope = 'animal::dolphin'
+ @new_label_different_scope = 'plant::orchid'
+
+ ...
+end
+
+it 'replaces an existing label if it has the same key' do
+ select_label_and_refresh @new_label_same_scope
+
+ labels_block = page.find('.qa-labels-block')
+
+ expect(labels_block).to have_content(@new_label_same_scope)
+ expect(labels_block).not_to have_content(@initial_label)
+ expect(page).to have_content("added #{@new_label_same_scope}")
+ expect(page).to have_content("and removed #{@initial_label}")
+end
+
+it 'keeps both scoped label when adding a label with a different key' do
+ select_label_and_refresh @new_label_different_scope
+
+ labels_block = page.find('.qa-labels-block')
+
+ expect(labels_blocks).to have_content(@new_label_different_scope)
+ expect(labels_blocks).to have_content(@initial_label)
+ expect(page).to have_content("added #{@new_label_different_scope}")
+ expect(page).to have_content("added #{@initial_label}")
+end
+
+def select_label_and_refresh(label)
+ page.find('.block.labels .edit-link').click
+ page.find('.dropdown-menu-labels .dropdown-input-field').send_keys [label, :enter]
+ page.find('#content-body').click
+ page.refresh
+end
+```
+
+First, we remove the duplication of strings by defining the global variables `@initial_label`, `@new_label_same_scope` and `@new_label_different_scope` in the `before` block, and by using them in the expectations.
+
+Then, by creating a reusable `select_label_and_refresh` method, we remove the code duplication of this action, and later we can move this method to a Page Object class that will be created for easier maintenance purposes.
+
+> Notice that the reusable method is created at the bottom of the file. The reason for that is that reading the code should be similar to reading a newspaper, where high-level information is at the top, like the title and summary of the news, while low level, or more specific information, is at the bottom (this helps readability).
+
+### 5. Tests' pre-conditions using resources and Page Objects
+
+In this section, we will address the previously mentioned subject of creating the application state for the tests, using the `before :context` and `before` blocks, together with resources and Page Objects.
+
+#### `before :context`
+
+A pre-condition for the entire test suite is defined in the `before :context` block.
+
+> For our test suite, due to the need of the tests being completely independent of each other, we won't use the `before :context` block. The `before :context` block would make the tests dependent on each other because the first test changes the label of the issue, and the second one depends on the `'animal::fox'` label being set.
+
+> **Tip:** In case of a test suite with only one `it` block it's ok to use only the `before` block (see below) with all the test's pre-conditions.
+
+#### `before`
+
+As the pre-conditions for our test suite, the things that needs to happen before each test starts are:
+
+- The user logging in;
+- A premium license already being set;
+- A project being created with an issue and labels already set;
+- The issue page being opened with only one scoped label applied to it.
+
+> When running end-to-end tests as part of the GitLab's continuous integration process [a license is already set as an environment variable](https://gitlab.com/gitlab-org/gitlab-ee/blob/1a60d926740db10e3b5724713285780a4f470531/qa/qa/ee/strategy.rb#L20). For running tests locally you can set up such license by following the document [what tests can be run?](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md#supported-remote-grid-environment-variables), based on the [supported GitLab environment variables](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md#supported-gitlab-environment-variables).
+
+#### Implementation
+
+In the following code we will focus only on the test suite's pre-conditions:
+
+```ruby
+module QA
+ context 'Plan' do
+ describe 'Editing scoped labels on issues' do
+ before do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.perform(&:sign_in_using_credentials)
+
+ @initial_label = 'animal::fox'
+ @new_label_same_scope = 'animal::dolphin'
+ @new_label_different_scope = 'plant::orchid'
+
+ issue = Resource::Issue.fabricate_via_api! do |issue|
+ issue.title = 'Issue to test the scoped labels'
+ issue.labels = @initial_label
+ end
+
+ [@new_label_same_scope, @new_label_different_scope].each do |label|
+ Resource::Label.fabricate_via_api! do |l|
+ l.project = issue.project.id
+ l.title = label
+ end
+ end
+
+ issue.visit!
+ end
+
+ it 'replaces an existing label if it has the same key' do
+ ...
+ end
+
+ it 'keeps both scoped labels when adding a label with a different key' do
+ ...
+ end
+
+ def select_label_and_refresh(label)
+ ...
+ end
+ end
+ end
+end
+```
+
+In the `before` block we create all the application state needed for the tests to run. We do that by using the `Runtime::Browser.visit` method to go to the login page, by performing a `sign_in_using_credentials` from the `Login` Page Object, by fabricating resources via APIs (`issue`, and `Resource::Label`), and by using the `issue.visit!` to visit the issue page.
+
+> A project is created in the background by creating the `issue` resource.
+
+> When creating the [Resources], notice that when calling the `fabricate_via_api` method, we pass some attribute:values, like `title`, and `labels` for the `issue` resource; and `project` and `title` for the `label` resource.
+
+> What's important to understand here is that by creating the application state mostly using the public APIs we save a lot of time in the test suite setup stage.
+
+> Soon we will cover the use of the already existing resources' methods and the creation of your own `fabricate_via_api` methods for resources where this is still not available, but first, let's optimize our implementation.
+
+### 6. Optimization
+
+As already mentioned in the [best practices](best_practices.md) document, end-to-end tests are very costly in terms of execution time, and it's our responsibility as software engineers to ensure that we optimize them as much as possible.
+
+> Note that end-to-end tests are slow to run and so they can have several actions and assertions in a single test, which helps us get feedback from the tests sooner. In comparison, unit tests are much faster to run and can exercise every little piece of the application in isolation, and so they usually have only one assertion per test.
+
+Some improvements that we could make in our test suite to optimize its time to run are:
+
+1. Having a single test case (an `it` block) that exercises both scenarios to avoid "wasting" time in the tests' pre-conditions, instead of having two different test cases.
+2. Making the selection of labels more performant by allowing for the selection of more than one label in the same reusable method.
+
+Let's look at a suggestion that addresses the above points, one by one:
+
+```ruby
+module QA
+ context 'Plan' do
+ describe 'Editing scoped labels on issues' do
+ before do
+ ...
+ end
+
+ it 'correctly applies scoped labels depending on if they are from the same or a different scope' do
+ select_labels_and_refresh [@new_label_same_scope, @new_label_different_scope]
+
+ labels_block = page.all('.qa-labels-block')
+
+ expect(labels_block).to have_content(@new_label_same_scope)
+ expect(labels_block).to have_content(@new_label_different_scope)
+ expect(labels_block).not_to have_content(@initial_label)
+ expect(page).to have_content("added #{@initial_label}")
+ expect(page).to have_content("added #{@new_label_same_scope} #{@new_label_different_scope} labels and removed #{@initial_label}")
+ end
+
+ def select_labels_and_refresh(labels)
+ find('.block.labels .edit-link').click
+ labels.each do |label|
+ find('.dropdown-menu-labels .dropdown-input-field').send_keys [label, :enter]
+ end
+ find('#content-body').click
+ refresh
+ end
+ end
+ end
+ end
+```
+
+To address point 1, we changed the test implementation from two `it` blocks into a single one that exercises both scenarios. Now the new test description is: `'correctly applies the scoped labels depending if they are from the same or a different scope'`. It's a long description, but it describes well what the test does.
+
+> Notice that the implementation of the new and unique `it` block had to change a little bit. Below we describe in details what it does.
+
+1. It selects two scoped labels simultaneously, one from the same scope of the one already applied in the issue during the setup phase (in the `before` block), and another one from a different scope.
+2. It asserts that the correct labels are visible in the `labels_block`, and that the labels were correctly added and removed;
+3. Finally, the `select_label_and_refresh` method is changed to `select_labels_and_refresh`, which accepts an array of labels instead of a single label, and it iterates on them for faster label selection (this is what is used in step 1 explained above.)
+
+### 7. Resources
+
+**Note:** When writing this document, some code that is now merged to master was not implemented yet, but we left them here for the readers to understand the whole process of end-to-end test creation.
+
+You can think of [Resources] as anything that can be created on GitLab CE or EE, either through the GUI, the API, or the CLI.
+
+With that in mind, resources can be a project, an epic, an issue, a label, a commit, etc.
+
+As you saw in the tests' pre-conditions and the optimization sections, we're already creating some of these resources, and we are doing that by calling the `fabricate_via_api!` method.
+
+> We could be using the `fabricate!` method instead, which would use the `fabricate_via_api!` method if it exists, and fallback to GUI fabrication otherwise, but we recommend being explicit to make it clear what the test does. Also, we always recommend fabricating resources via API since this makes tests faster and more reliable.
+
+For our test suite example, the resources that we need to create don't have the necessary code for the `fabricate_via_api!` method to correctly work (e.g., the issue and label resources), so we will have to create them.
+
+#### Implementation
+
+In the following we describe the changes needed in each of the resource files mentioned above.
+
+**Issue resource**
+
+Now, let's make it possible to create an issue resource through the API.
+
+First, in the [issue resource](https://gitlab.com/gitlab-org/gitlab-ee/blob/d3584e80b4236acdf393d815d604801573af72cc/qa/qa/resource/issue.rb), let's expose its id and labels attributes.
+
+Add the following `attribute :id` and `attribute :labels` right above the [`attribute :title`](https://gitlab.com/gitlab-org/gitlab-ee/blob/d3584e80b4236acdf393d815d604801573af72cc/qa/qa/resource/issue.rb#L15).
+
+> This line is needed to allow for the issue fabrication, and for labels to be automatically added to the issue when fabricating it via API.
+
+> We add the attributes above the existing attribute to keep them alphabetically organized.
+
+Next, add the following code right below the [`fabricate!`](https://gitlab.com/gitlab-org/gitlab-ee/blob/d3584e80b4236acdf393d815d604801573af72cc/qa/qa/resource/issue.rb#L27) method.
+
+```ruby
+def api_get_path
+ "/projects/#{project.id}/issues/#{id}"
+end
+
+def api_post_path
+ "/projects/#{project.id}/issues"
+end
+
+def api_post_body
+ {
+ labels: [labels],
+ title: title
+ }
+end
+```
+
+By defining the `api_get_path` method, we allow the [`ApiFabricator`](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/qa/qa/resource/api_fabricator.rb) module to know which path to use to get a single issue.
+
+> This `GET` path can be found in the [public API documentation](https://docs.gitlab.com/ee/api/issues.html#single-issue).
+
+By defining the `api_post_path` method, we allow the [`ApiFabricator`](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/qa/qa/resource/api_fabricator.rb) module to know which path to use to create a new issue in a specific project.
+
+> This `POST` path can be found in the [public API documentation](https://docs.gitlab.com/ee/api/issues.html#new-issue).
+
+By defining the `api_post_body` method, we allow the [`ApiFabricator.api_post`](https://gitlab.com/gitlab-org/gitlab-ee/blob/a9177ca1812bac57e2b2fa4560e1d5dd8ffac38b/qa/qa/resource/api_fabricator.rb#L68) method to know which data to send when making the `POST` request.
+
+> Notice that we pass both `labels` and `title` attributes in the `api_post_body`, where `labels` receives an array of labels, and [`title` is required](https://docs.gitlab.com/ee/api/issues.html#new-issue). Also, notice that we keep them alphabetically organized.
+
+**Label resource**
+
+Finally, let's make it possible to create label resources through the API.
+
+Add the following code right below the [`fabricate!`](https://gitlab.com/gitlab-org/gitlab-ee/blob/a9177ca1812bac57e2b2fa4560e1d5dd8ffac38b/qa/qa/resource/label.rb#L36) method.
+
+```ruby
+def resource_web_url(resource)
+ super
+rescue ResourceURLMissingError
+ # this particular resource does not expose a web_url property
+end
+
+def api_get_path
+ raise NotImplementedError, "The Labels API doesn't expose a single-resource endpoint so this method cannot be properly implemented."
+end
+
+def api_post_path
+ "/projects/#{project}/labels"
+end
+
+def api_post_body
+ {
+ color: @color,
+ name: @title
+ }
+end
+```
+
+By defining the `resource_web_url(resource)` method, we override the one from the [`ApiFabricator`](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/qa/qa/resource/api_fabricator.rb#L44) module. We do that to avoid failing the test due to this particular resource not exposing a `web_url` property.
+
+By defining the `api_get_path` method, we **would** allow for the [`ApiFabricator`](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/qa/qa/resource/api_fabricator.rb) module to know which path to use to get a single label, but since there's no path available for that in the publich API, we raise a `NotImplementedError` instead.
+
+By defining the `api_post_path` method, we allow for the [`ApiFabricator `](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/qa/qa/resource/api_fabricator.rb) module to know which path to use to create a new label in a specific project.
+
+By defining the `api_post_body` method, we we allow for the [`ApiFabricator.api_post`](https://gitlab.com/gitlab-org/gitlab-ee/blob/a9177ca1812bac57e2b2fa4560e1d5dd8ffac38b/qa/qa/resource/api_fabricator.rb#L68) method to know which data to send when making the `POST` request.
+
+> Notice that we pass both `color` and `name` attributes in the `api_post_body` since [those are required](https://docs.gitlab.com/ee/api/labels.html#create-a-new-label). Also, notice that we keep them alphabetically organized.
+
+### 8. Page Objects
+
+Page Objects are used in end-to-end tests for maintenance reasons, where a page's elements and methods are defined to be reused in any test.
+
+> Page Objects are auto-loaded in the [`qa/qa.rb`](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/qa/qa.rb) file and available in all the test files (`*_spec.rb`).
+
+Take a look at the [Page Objects] documentation.
+
+Now, let's go back to our example.
+
+As you may have noticed, we are defining elements with CSS selectors and the `select_labels_and_refresh` method directly in the test file, and this is an anti-pattern since we need to better separate the responsibilities.
+
+To address this issue, we will move the implementation to Page Objects, and the test suite will only focus on the business rules that we are testing.
+
+#### Updates in the test file
+
+As in a test-driven development approach, let's start changing the test file even before the Page Object implementation is in place.
+
+Replace the code of the `it` block in the test file by the following:
+
+```ruby
+module QA
+ context 'Plan' do
+ describe 'Editing scoped labels on issues' do
+ before do
+ ...
+ end
+
+ it 'correctly applies scoped labels depending on if they are from the same or a different scope' do
+ Page::Project::Issue::Show.perform do |issue_page|
+ issue_page.select_labels_and_refresh [@new_label_same_scope, @new_label_different_scope]
+
+ expect(page).to have_content("added #{@initial_label}")
+ expect(page).to have_content("added #{@new_label_same_scope} #{@new_label_different_scope} labels and removed #{@initial_label}")
+ expect(issue_page.text_of_labels_block).to have_content(@new_label_same_scope)
+ expect(issue_page.text_of_labels_block).to have_content(@new_label_different_scope)
+ expect(issue_page.text_of_labels_block).not_to have_content(@initial_label)
+ end
+ end
+ end
+ end
+end
+```
+
+Notice that `select_labels_and_refresh` is now a method from the issue Page Object (which is not yet implemented), and that we verify the labels' text by using `text_of_labels_block`, instead of via the `labels_block` element. The `text_of_labels_block` method will also be implemented in the issue Page Object.
+
+Let's now update the Issue Page Object.
+
+#### Updates in the Issue Page Object
+
+> Page Objects are located in the `qa/qa/page/` directory, and its sub-directories.
+
+The file we will have to change is the [Issue Page Object](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/qa/qa/page/project/issue/show.rb).
+
+First, add the following code right below the definition of an already implemented view (keep in mind that view's definitions and their elements should be alphabetically ordered):
+
+```ruby
+view 'app/helpers/dropdowns_helper.rb' do
+ element :dropdown_input_field
+end
+
+view 'app/views/shared/issuable/_sidebar.html.haml' do
+ element :dropdown_menu_labels
+ element :edit_link_labels
+ element :labels_block
+end
+```
+
+Similarly to what we did before, let's first change the Page Object even without the elements being defined in the view (`_sidebar.html.haml`) and the `dropdowns_helper.rb` files, and later we will update them by adding the appropriate CSS selectors.
+
+Now, let's implement the methods `select_labels_and_refresh` and `text_of_labels_block`.
+
+Somewhere between the definition of the views and the private methods, add the following snippet of code (these should also be alphabetically ordered for organization reasons):
+
+```ruby
+def select_labels_and_refresh(labels)
+ click_element(:edit_link_labels)
+ labels.each do |label|
+ within_element(:dropdown_menu_labels, text: label) do
+ send_keys_to_element(:dropdown_input_field, [label, :enter])
+ end
+ end
+ click_body
+ labels.each do |label|
+ has_element?(:labels_block, text: label)
+ end
+ refresh
+end
+
+def text_of_labels_block
+ find_element(:labels_block)
+end
+```
+
+##### Details of `select_labels_and_refresh`
+
+Notice that we have not only moved the `select_labels_and_refresh` method, but we have also changed its implementation to:
+1. Click the `:edit_link_labels` element previously defined, instead of using `find('.block.labels .edit-link').click`
+2. Use `within_element(:dropdown_menu_labels, text: label)`, and inside of it, we call `send_keys_to_element(:dropdown_input_field, [label, :enter])`, which is a method that we will implement in the `QA::Page::Base` class to replace `find('.dropdown-menu-labels .dropdown-input-field').send_keys [label, :enter]`
+3. Use `click_body` after iterating on each label, instead of using `find('#content-body').click`
+4. Iterate on every label again, and then we use `has_element?(:labels_block, text: label)` after clicking the page body (which applies the labels), and before refreshing the page, to avoid test flakiness due to refreshing too fast.
+
+##### Details of `text_of_labels_block`
+
+The `text_of_labels_block` method is a simple method that returns the `:labels_block` element (`find_element(:labels_block)`).
+
+#### Updates in the view (*.html.haml) and `dropdowns_helper.rb` files
+
+Now let's change the view and the `dropdowns_helper` files to add the selectors that relate to the Page Object.
+
+In the [app/views/shared/issuable/_sidebar.html.haml](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/app/views/shared/issuable/_sidebar.html.haml) file, on [line 105 ](https://gitlab.com/gitlab-org/gitlab-ee/blob/84043fa72ca7f83ae9cde48ad670e6d5d16501a3/app/views/shared/issuable/_sidebar.html.haml#L105), add an extra class `qa-edit-link-labels`.
+
+The code should look like this: `= link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right qa-edit-link-labels'`.
+
+In the same file, on [line 121](https://gitlab.com/gitlab-org/gitlab-ee/blob/84043fa72ca7f83ae9cde48ad670e6d5d16501a3/app/views/shared/issuable/_sidebar.html.haml#L121), add an extra class `.qa-dropdown-menu-labels`.
+
+The code should look like this: `.dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable.qa-dropdown-menu-labels`.
+
+In the [`dropdowns_helper.rb`](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/app/helpers/dropdowns_helper.rb) file, on [line 94](https://gitlab.com/gitlab-org/gitlab-ee/blob/99e51a374f2c20bee0989cac802e4b5621f72714/app/helpers/dropdowns_helper.rb#L94), add an extra class `qa-dropdown-input-field`.
+
+The code should look like this: `filter_output = search_field_tag search_id, nil, class: "dropdown-input-field qa-dropdown-input-field", placeholder: placeholder, autocomplete: 'off'`.
+
+> Classes starting with `qa-` are used for testing purposes only, and by defining such classes in the elements we add **testability** in the application.
+
+> When defining a class like `qa-labels-block`, it is transformed into `:labels_block` for usage in the Page Objects. So, `qa-edit-link-labels` is transformed into `:edit_link_labels`, `qa-dropdown-menu-labels` is transformed into `:dropdown_menu_labels`, and `qa-dropdown-input-field` is transformed into `:dropdown_input_field`. Also, we use a [sanity test](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/qa/page#how-did-we-solve-fragile-tests-problem) to check that defined elements have their respective `qa-` selectors in the specified views.
+
+> We did not define the `qa-labels-block` class in the `app/views/shared/issuable/_sidebar.html.haml` file because it was already there to be used.
+
+#### Updates in the `QA::Page::Base` class
+
+The last thing that we have to do is to update `QA::Page::Base` class to add the `send_keys_to_element` method on it.
+
+Add the following snippet of code somewhere where class methods are defined (remember to organize methods alphabetically, and if you see a place where this standard is not being followed, it would be helpful if you could rearrange it):
+
+```ruby
+def send_keys_to_element(name, keys)
+ find_element(name).send_keys(keys)
+end
+```
+
+This method receives an element (`name`) and the `keys` that it will send to that element, and the keys are an array that can receive strings, or "special" keys, like `:enter`.
+
+As you might remember, in the Issue Page Object we call this method like this: `send_keys_to_element(:dropdown_input_field, [label, :enter])`.
+
+___
+
+With that, you should be able to start writing end-to-end tests yourself. *Congratulations!*
+
+[Page Objects]: page_objects.md
+[Resources]: resources.md
diff --git a/doc/development/testing_guide/end_to_end/resources.md b/doc/development/testing_guide/end_to_end/resources.md
new file mode 100644
index 00000000000..1e32db4f633
--- /dev/null
+++ b/doc/development/testing_guide/end_to_end/resources.md
@@ -0,0 +1,392 @@
+# Resource class in GitLab QA
+
+Resources are primarily created using Browser UI steps, but can also
+be created via the API or the CLI.
+
+## How to properly implement a resource class?
+
+All resource classes should inherit from `Resource::Base`.
+
+There is only one mandatory method to implement to define a resource class.
+This is the `#fabricate!` method, which is used to build the resource via the
+browser UI. Note that you should only use [Page objects](page_objects.md) to
+interact with a Web page in this method.
+
+Here is an imaginary example:
+
+```ruby
+module QA
+ module Resource
+ class Shirt < Base
+ attr_accessor :name
+
+ def fabricate!
+ Page::Dashboard::Index.perform do |dashboard_index|
+ dashboard_index.go_to_new_shirt
+ end
+
+ Page::Shirt::New.perform do |shirt_new|
+ shirt_new.set_name(name)
+ shirt_new.create_shirt!
+ end
+ end
+ end
+ end
+end
+```
+
+### Define API implementation
+
+A resource class may also implement the three following methods to be able to
+create the resource via the public GitLab API:
+
+- `#api_get_path`: The `GET` path to fetch an existing resource.
+- `#api_post_path`: The `POST` path to create a new resource.
+- `#api_post_body`: The `POST` body (as a Ruby hash) to create a new resource.
+
+Let's take the `Shirt` resource class, and add these three API methods:
+
+```ruby
+module QA
+ module Resource
+ class Shirt < Base
+ attr_accessor :name
+
+ def fabricate!
+ # ... same as before
+ end
+
+ def api_get_path
+ "/shirt/#{name}"
+ end
+
+ def api_post_path
+ "/shirts"
+ end
+
+ def api_post_body
+ {
+ name: name
+ }
+ end
+ end
+ end
+end
+```
+
+The `Project` resource is a good real example of Browser
+UI and API implementations.
+
+#### Resource attributes
+
+A resource may need another resource to exist first. For instance, a project
+needs a group to be created in.
+
+To define a resource attribute, you can use the `attribute` method with a
+block using the other resource class to fabricate the resource.
+
+That will allow access to the other resource from your resource object's
+methods. You would usually use it in `#fabricate!`, `#api_get_path`,
+`#api_post_path`, `#api_post_body`.
+
+Let's take the `Shirt` resource class, and add a `project` attribute to it:
+
+```ruby
+module QA
+ module Resource
+ class Shirt < Base
+ attr_accessor :name
+
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'project-to-create-a-shirt'
+ end
+ end
+
+ def fabricate!
+ project.visit!
+
+ Page::Project::Show.perform do |project_show|
+ project_show.go_to_new_shirt
+ end
+
+ Page::Shirt::New.perform do |shirt_new|
+ shirt_new.set_name(name)
+ shirt_new.create_shirt!
+ end
+ end
+
+ def api_get_path
+ "/project/#{project.path}/shirt/#{name}"
+ end
+
+ def api_post_path
+ "/project/#{project.path}/shirts"
+ end
+
+ def api_post_body
+ {
+ name: name
+ }
+ end
+ end
+ end
+end
+```
+
+**Note that all the attributes are lazily constructed. This means if you want
+a specific attribute to be fabricated first, you'll need to call the
+attribute method first even if you're not using it.**
+
+#### Product data attributes
+
+Once created, you may want to populate a resource with attributes that can be
+found in the Web page, or in the API response.
+For instance, once you create a project, you may want to store its repository
+SSH URL as an attribute.
+
+Again we could use the `attribute` method with a block, using a page object
+to retrieve the data on the page.
+
+Let's take the `Shirt` resource class, and define a `:brand` attribute:
+
+```ruby
+module QA
+ module Resource
+ class Shirt < Base
+ attr_accessor :name
+
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'project-to-create-a-shirt'
+ end
+ end
+
+ # Attribute populated from the Browser UI (using the block)
+ attribute :brand do
+ Page::Shirt::Show.perform do |shirt_show|
+ shirt_show.fetch_brand_from_page
+ end
+ end
+
+ # ... same as before
+ end
+ end
+end
+```
+
+**Note again that all the attributes are lazily constructed. This means if
+you call `shirt.brand` after moving to the other page, it'll not properly
+retrieve the data because we're no longer on the expected page.**
+
+Consider this:
+
+```ruby
+shirt =
+ QA::Resource::Shirt.fabricate! do |resource|
+ resource.name = "GitLab QA"
+ end
+
+shirt.project.visit!
+
+shirt.brand # => FAIL!
+```
+
+The above example will fail because now we're on the project page, trying to
+construct the brand data from the shirt page, however we moved to the project
+page already. There are two ways to solve this, one is that we could try to
+retrieve the brand before visiting the project again:
+
+```ruby
+shirt =
+ QA::Resource::Shirt.fabricate! do |resource|
+ resource.name = "GitLab QA"
+ end
+
+shirt.brand # => OK!
+
+shirt.project.visit!
+
+shirt.brand # => OK!
+```
+
+The attribute will be stored in the instance therefore all the following calls
+will be fine, using the data previously constructed. If we think that this
+might be too brittle, we could eagerly construct the data right before
+ending fabrication:
+
+```ruby
+module QA
+ module Resource
+ class Shirt < Base
+ # ... same as before
+
+ def fabricate!
+ project.visit!
+
+ Page::Project::Show.perform do |project_show|
+ project_show.go_to_new_shirt
+ end
+
+ Page::Shirt::New.perform do |shirt_new|
+ shirt_new.set_name(name)
+ shirt_new.create_shirt!
+ end
+
+ populate(:brand) # Eagerly construct the data
+ end
+ end
+ end
+end
+```
+
+The `populate` method will iterate through its arguments and call each
+attribute respectively. Here `populate(:brand)` has the same effect as
+just `brand`. Using the populate method makes the intention clearer.
+
+With this, it will make sure we construct the data right after we create the
+shirt. The drawback is that this will always construct the data when the
+resource is fabricated even if we don't need to use the data.
+
+Alternatively, we could just make sure we're on the right page before
+constructing the brand data:
+
+```ruby
+module QA
+ module Resource
+ class Shirt < Base
+ attr_accessor :name
+
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'project-to-create-a-shirt'
+ end
+ end
+
+ # Attribute populated from the Browser UI (using the block)
+ attribute :brand do
+ back_url = current_url
+ visit!
+
+ Page::Shirt::Show.perform do |shirt_show|
+ shirt_show.fetch_brand_from_page
+ end
+
+ visit(back_url)
+ end
+
+ # ... same as before
+ end
+ end
+end
+```
+
+This will make sure it's on the shirt page before constructing brand, and
+move back to the previous page to avoid breaking the state.
+
+#### Define an attribute based on an API response
+
+Sometimes, you want to define a resource attribute based on the API response
+from its `GET` or `POST` request. For instance, if the creation of a shirt via
+the API returns
+
+```ruby
+{
+ brand: 'a-brand-new-brand',
+ style: 't-shirt',
+ materials: [[:cotton, 80], [:polyamide, 20]]
+}
+```
+
+you may want to store `style` as-is in the resource, and fetch the first value
+of the first `materials` item in a `main_fabric` attribute.
+
+Let's take the `Shirt` resource class, and define a `:style` and a
+`:main_fabric` attributes:
+
+```ruby
+module QA
+ module Resource
+ class Shirt < Base
+ # ... same as before
+
+ # @style from the instance if present,
+ # or fetched from the API response if present,
+ # or a QA::Resource::Base::NoValueError is raised otherwise
+ attribute :style
+
+ # If @main_fabric is not present,
+ # and if the API does not contain this field, this block will be
+ # used to construct the value based on the API response, and
+ # store the result in @main_fabric
+ attribute :main_fabric do
+ api_response.&dig(:materials, 0, 0)
+ end
+
+ # ... same as before
+ end
+ end
+end
+```
+
+**Notes on attributes precedence:**
+
+- resource instance variables have the highest precedence
+- attributes from the API response take precedence over attributes from the
+ block (usually from Browser UI)
+- attributes without a value will raise a `QA::Resource::Base::NoValueError` error
+
+## Creating resources in your tests
+
+To create a resource in your tests, you can call the `.fabricate!` method on
+the resource class.
+Note that if the resource class supports API fabrication, this will use this
+fabrication by default.
+
+Here is an example that will use the API fabrication method under the hood
+since it's supported by the `Shirt` resource class:
+
+```ruby
+my_shirt = Resource::Shirt.fabricate! do |shirt|
+ shirt.name = 'my-shirt'
+end
+
+expect(page).to have_text(my_shirt.name) # => "my-shirt" from the resource's instance variable
+expect(page).to have_text(my_shirt.brand) # => "a-brand-new-brand" from the API response
+expect(page).to have_text(my_shirt.style) # => "t-shirt" from the API response
+expect(page).to have_text(my_shirt.main_fabric) # => "cotton" from the API response via the block
+```
+
+If you explicitly want to use the Browser UI fabrication method, you can call
+the `.fabricate_via_browser_ui!` method instead:
+
+```ruby
+my_shirt = Resource::Shirt.fabricate_via_browser_ui! do |shirt|
+ shirt.name = 'my-shirt'
+end
+
+expect(page).to have_text(my_shirt.name) # => "my-shirt" from the resource's instance variable
+expect(page).to have_text(my_shirt.brand) # => the brand name fetched from the `Page::Shirt::Show` page via the block
+expect(page).to have_text(my_shirt.style) # => QA::Resource::Base::NoValueError will be raised because no API response nor a block is provided
+expect(page).to have_text(my_shirt.main_fabric) # => QA::Resource::Base::NoValueError will be raised because no API response and the block didn't provide a value (because it's also based on the API response)
+```
+
+You can also explicitly use the API fabrication method, by calling the
+`.fabricate_via_api!` method:
+
+```ruby
+my_shirt = Resource::Shirt.fabricate_via_api! do |shirt|
+ shirt.name = 'my-shirt'
+end
+```
+
+In this case, the result will be similar to calling
+`Resource::Shirt.fabricate!`.
+
+## Where to ask for help?
+
+If you need more information, ask for help on `#quality` channel on Slack
+(internal, GitLab Team only).
+
+If you are not a Team Member, and you still need help to contribute, please
+open an issue in GitLab CE issue tracker with the `~QA` label.
diff --git a/doc/development/testing_guide/end_to_end/style_guide.md b/doc/development/testing_guide/end_to_end/style_guide.md
new file mode 100644
index 00000000000..0272e1810f2
--- /dev/null
+++ b/doc/development/testing_guide/end_to_end/style_guide.md
@@ -0,0 +1,99 @@
+# Style guide for writing end-to-end tests
+
+This document describes the conventions used at GitLab for writing End-to-end (E2E) tests using the GitLab QA project.
+
+## `click_` versus `go_to_`
+
+### When to use `click_`?
+
+When clicking in a single link to navigate, use `click_`.
+
+E.g.:
+
+```ruby
+def click_ci_cd_pipelines
+ within_sidebar do
+ click_element :link_pipelines
+ end
+end
+```
+
+From a testing perspective, if we want to check that clicking a link, or a button (a single interaction) is working as intended, we would want the test to read as:
+
+- Click a certain element
+- Verify the action took place
+
+### When to use `go_to_`?
+
+When interacting with multiple elements to go to a page, use `go_to_`.
+
+E.g.:
+
+```ruby
+def go_to_operations_environments
+ hover_operations do
+ within_submenu do
+ click_element(:operations_environments_link)
+ end
+ end
+end
+```
+
+`go_to_` fits the definition of interacting with multiple elements very well given it's more of a meta-navigation action that includes multiple interactions.
+
+Notice that in the above example, before clicking the `:operations_environments_link`, another element is hovered over.
+
+> We can create these methods as helpers to abstract multi-step navigation.
+
+### Element naming convention
+
+When adding new elements to a page, it's important that we have a uniform element naming convention.
+
+We follow a simple formula roughly based on hungarian notation.
+
+*Formula*: `element :<descriptor>_<type>`
+
+- `descriptor`: The natural-language description of what the element is. On the login page, this could be `username`, or `password`.
+- `type`: A physical control on the page that can be seen by a user.
+ - `_button`
+ - `_link`
+ - `_tab`
+ - `_dropdown`
+ - `_field`
+ - `_checkbox`
+ - `_radio`
+ - `_content`
+
+*Note: This list is a work in progress. This list will eventually be the end-all enumeration of all available types.
+ I.e., any element that does not end with something in this list is bad form.*
+
+#### Examples
+
+**Good**
+
+```ruby
+view '...' do
+ element :edit_button
+ element :notes_tab
+ element :squash_checkbox
+ element :username_field
+ element :issue_title_content
+end
+```
+
+**Bad**
+
+```ruby
+view '...' do
+ # `_confirmation` should be `_field`. what sort of confirmation? a checkbox confirmation? no real way to disambiguate.
+ # an appropriate replacement would be `element :password_confirmation_field`
+ element :password_confirmation
+
+ # `clone_options` is too vague. If it's a dropdown menu, it should be `clone_dropdown`.
+ # If it's a checkbox, it should be `clone_checkbox`
+ element :clone_options
+
+ # how is this url being displayed? is it a textbox? a simple span?
+ element :ssh_clone_url
+end
+```
diff --git a/doc/development/testing_guide/end_to_end_tests.md b/doc/development/testing_guide/end_to_end_tests.md
deleted file mode 100644
index 51fe19c3d9e..00000000000
--- a/doc/development/testing_guide/end_to_end_tests.md
+++ /dev/null
@@ -1,162 +0,0 @@
-# End-to-end Testing
-
-## What is end-to-end testing?
-
-End-to-end testing is a strategy used to check whether your application works
-as expected across the entire software stack and architecture, including
-integration of all micro-services and components that are supposed to work
-together.
-
-## Branch naming
-
-If your contribution contains **only** changes under the
-[`qa/` folder](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa), you can
-speed up the CI process by following some branch naming conventions. You have
-three choices:
-
-| Branch name | Valid example |
-|:----------------------|:-----------------------------|
-| Starting with `qa/` | `qa/new-oauth-login-test` |
-| Starting with `qa-` | `qa-new-oauth-login-test` |
-| Ending in `-qa` | `123-new-oauth-login-test-qa` |
-
-If your branch name matches any of the above, it will run only the QA-related
-jobs.
-If it does not, the whole application test suite will run (including QA-related
-jobs).
-
-## How do we test GitLab?
-
-We use [Omnibus GitLab][omnibus-gitlab] to build GitLab packages and then we
-test these packages using the [GitLab QA orchestrator][gitlab-qa] tool, which is
-a black-box testing framework for the API and the UI.
-
-### Testing nightly builds
-
-We run scheduled pipeline each night to test nightly builds created by Omnibus.
-You can find these nightly pipelines at [gitlab-org/quality/nightly/pipelines][quality-nightly-pipelines].
-Results are reported in the `#qa-nightly` Slack channel.
-
-### Testing staging
-
-We run scheduled pipeline each night to test staging.
-You can find these nightly pipelines at [gitlab-org/quality/staging/pipelines][quality-staging-pipelines].
-Results are reported in the `#qa-staging` Slack channel.
-
-### Testing code in merge requests
-
-#### Using the `package-and-qa` job
-
-It is possible to run end-to-end tests for a merge request, eventually being run in
-a pipeline in the [`gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/) project,
-by triggering the `package-and-qa` manual action in the `test` stage (not
-available for forks).
-
-**This runs end-to-end tests against a custom Omnibus package built from your
-merge request's changes.**
-
-Manual action that starts end-to-end tests is also available in merge requests
-in [Omnibus GitLab][omnibus-gitlab].
-
-Below you can read more about how to use it and how does it work.
-
-#### How does it work?
-
-Currently, we are using _multi-project pipeline_-like approach to run QA
-pipelines.
-
-![QA on merge requests CI/CD architecture](img/qa_on_merge_requests_cicd_architecture.png)
-
-<details>
-<summary>Show mermaid source</summary>
-<pre>
-graph LR
- A1 -.->|1. Triggers an omnibus-gitlab pipeline and wait for it to be done| A2
- B2[<b>`Trigger-qa` stage</b><br />`Trigger:qa-test` job] -.->|2. Triggers a gitlab-qa pipeline and wait for it to be done| A3
-
-subgraph gitlab-ce/ee pipeline
- A1[<b>`test` stage</b><br />`package-and-qa` job]
- end
-
-subgraph omnibus-gitlab pipeline
- A2[<b>`Trigger-docker` stage</b></b><br />`Trigger:gitlab-docker` job] -->|once done| B2
- end
-
-subgraph gitlab-qa pipeline
- A3>QA jobs run] -.->|3. Reports back the pipeline result to the `package-and-qa` job<br />and post the result on the original commit tested| A1
- end
-</pre>
-</details>
-
-1. Developer triggers a manual action, that can be found in CE / EE merge
- requests. This starts a chain of pipelines in multiple projects.
-
-1. The script being executed triggers a pipeline in [Omnibus GitLab][omnibus-gitlab]
- and waits for the resulting status. We call this a _status attribution_.
-
-1. GitLab packages are being built in the [Omnibus GitLab][omnibus-gitlab]
- pipeline. Packages are then pushed to its Container Registry.
-
-1. When packages are ready, and available in the registry, a final step in the
- [Omnibus GitLab][omnibus-gitlab] pipeline, triggers a new
- [GitLab QA pipeline][gitlab-qa-pipelines]. It also waits for a resulting status.
-
-1. GitLab QA pulls images from the registry, spins-up containers and runs tests
- against a test environment that has been just orchestrated by the `gitlab-qa`
- tool.
-
-1. The result of the [GitLab QA pipeline][gitlab-qa-pipelines] is being
- propagated upstream, through Omnibus, back to the CE / EE merge request.
-
-#### Using the `review-qa-all` jobs
-
-On every pipeline during the `test` stage, the `review-qa-smoke` job is
-automatically started: it runs the QA smoke suite against the
-[Review App][review-apps].
-
-You can also manually start the `review-qa-all`: it runs the full QA suite
-against the [Review App][review-apps].
-
-**This runs end-to-end tests against a Review App based on [the official GitLab
-Helm chart][helm-chart], itself deployed with custom
-[Cloud Native components][cng] built from your merge request's changes.**
-
-See [Review Apps][review-apps] for more details about Review Apps.
-
-[helm-chart]: https://gitlab.com/charts/gitlab/
-[cng]: https://gitlab.com/gitlab-org/build/CNG
-
-## How do I write tests?
-
-In order to write new tests, you first need to learn more about GitLab QA
-architecture. See the [documentation about it][gitlab-qa-architecture].
-
-Once you decided where to put [test environment orchestration scenarios] and
-[instance-level scenarios], take a look at the [GitLab QA README][instance-qa-readme],
-the [GitLab QA orchestrator README][gitlab-qa-readme], and [the already existing
-instance-level scenarios][instance-level scenarios].
-
-## Where can I ask for help?
-
-You can ask question in the `#quality` channel on Slack (GitLab internal) or
-you can find an issue you would like to work on in
-[the `gitlab-ce` issue tracker][gitlab-ce-issues],
-[the `gitlab-ee` issue tracker][gitlab-ce-issues], or
-[the `gitlab-qa` issue tracker][gitlab-qa-issues].
-
-[omnibus-gitlab]: https://gitlab.com/gitlab-org/omnibus-gitlab
-[gitlab-qa]: https://gitlab.com/gitlab-org/gitlab-qa
-[gitlab-qa-pipelines]: https://gitlab.com/gitlab-org/gitlab-qa/pipelines
-[gitlab-qa-readme]: https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md
-[quality-nightly-pipelines]: https://gitlab.com/gitlab-org/quality/nightly/pipelines
-[quality-staging-pipelines]: https://gitlab.com/gitlab-org/quality/staging/pipelines
-[review-apps]: ./review_apps.md
-[gitlab-qa-architecture]: https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/architecture.md
-[gitlab-qa-issues]: https://gitlab.com/gitlab-org/gitlab-qa/issues?label_name%5B%5D=new+scenario
-[gitlab-ce-issues]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name[]=QA&label_name[]=test
-[gitlab-ee-issues]: https://gitlab.com/gitlab-org/gitlab-ee/issues?label_name[]=QA&label_name[]=test
-[test environment orchestration scenarios]: https://gitlab.com/gitlab-org/gitlab-qa/tree/master/lib/gitlab/qa/scenario
-[instance-level scenarios]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/qa/specs/features
-[Page objects documentation]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/qa/page/README.md
-[instance-qa-readme]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/README.md
-[instance-qa-examples]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/qa
diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md
index f58a8dcbcdc..4c9d1684c00 100644
--- a/doc/development/testing_guide/frontend_testing.md
+++ b/doc/development/testing_guide/frontend_testing.md
@@ -15,10 +15,8 @@ information on general testing practices at GitLab.
## Jest
-GitLab has started to migrate tests to the [Jest](https://jestjs.io)
-testing framework. You can read a [detailed evaluation](https://gitlab.com/gitlab-org/gitlab-ce/issues/49171)
-of Jest compared to our use of Karma and Jasmine. In summary, it will allow us
-to improve the performance and consistency of our frontend tests.
+We have started to migrate frontend tests to the [Jest](https://jestjs.io) testing framework (see also the corresponding
+[epic](https://gitlab.com/groups/gitlab-org/-/epics/895)).
Jest tests can be found in `/spec/frontend` and `/ee/spec/frontend` in EE.
@@ -26,6 +24,17 @@ It is not yet a requirement to use Jest. You can view the
[epic](https://gitlab.com/groups/gitlab-org/-/epics/873) of issues
we need to solve before being able to use Jest for all our needs.
+### Differences to Karma
+
+- Jest runs in a Node.js environment, not in a browser. Support for running Jest tests in a browser [is planned](https://gitlab.com/gitlab-org/gitlab-ce/issues/58205).
+- Because Jest runs in a Node.js environment, it uses [jsdom](https://github.com/jsdom/jsdom) by default.
+- All calls to `setTimeout` and `setInterval` are mocked away. See also [Jest Timer Mocks](https://jestjs.io/docs/en/timer-mocks).
+- `rewire` is not required because Jest supports mocking modules. See also [Manual Mocks](https://jestjs.io/docs/en/manual-mocks).
+- The following will cause tests to fail in Jest:
+ - Unmocked requests.
+ - Unhandled Promise rejections.
+ - Calls to `console.warn`, including warnings from libraries like Vue.
+
### Debugging Jest tests
Running `yarn jest-debug` will run Jest in debug mode, allowing you to debug/inspect as described in the [Jest docs](https://jestjs.io/docs/en/troubleshooting#tests-are-failing-and-you-don-t-know-why).
@@ -58,9 +67,6 @@ Remember that the performance of each test depends on the environment.
GitLab uses the [Karma][karma] test runner with [Jasmine] as its test
framework for our JavaScript unit and integration tests.
-We generate HTML and JSON fixtures from backend views and controllers
-using RSpec (see `spec/javascripts/fixtures/*.rb` for examples).
-Fixtures are served during testing by the [jasmine-jquery][jasmine-jquery] plugin.
JavaScript tests live in `spec/javascripts/`, matching the folder structure
of `app/assets/javascripts/`: `app/assets/javascripts/behaviors/autosize.js`
@@ -187,6 +193,7 @@ export default function doSomething() {
visitUrl('/foo/bar');
}
```
+
```js
// my_module_spec.js
import doSomething from '~/my_module';
@@ -213,7 +220,187 @@ Further documentation on the babel rewire pluign API can be found on
#### Waiting in tests
-If you cannot avoid using [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) in tests, please use the [Jasmine mock clock](https://jasmine.github.io/api/2.9/Clock.html).
+Sometimes a test needs to wait for something to happen in the application before it continues.
+Avoid using [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout)
+because it makes the reason for waiting unclear and if passed a time larger than zero it will slow down our test suite.
+Instead use one of the following approaches.
+
+##### Promises and Ajax calls
+
+Register handler functions to wait for the `Promise` to be resolved.
+
+```javascript
+const askTheServer = () => {
+ return axios
+ .get('/endpoint')
+ .then(response => {
+ // do something
+ })
+ .catch(error => {
+ // do something else
+ });
+};
+```
+
+**in Jest:**
+
+```javascript
+it('waits for an Ajax call', () => {
+ return askTheServer().then(() => {
+ expect(something).toBe('done');
+ });
+});
+```
+
+**in Karma:**
+
+```javascript
+it('waits for an Ajax call', done => {
+ askTheServer()
+ .then(() => {
+ expect(something).toBe('done');
+ })
+ .then(done)
+ .catch(done.fail);
+});
+```
+
+If you are not able to register handlers to the `Promise`—for example because it is executed in a synchronous Vue life
+cycle hook—you can flush all pending `Promise`s:
+
+**in Jest:**
+
+```javascript
+it('waits for an Ajax call', () => {
+ synchronousFunction();
+ jest.runAllTicks();
+
+ expect(something).toBe('done');
+});
+```
+
+**in Karma:**
+
+You are out of luck. The following only works sometimes and may lead to flaky failures:
+
+```javascript
+it('waits for an Ajax call', done => {
+ synchronousFunction();
+
+ // create a new Promise and hope that it resolves after the rest
+ Promise.resolve()
+ .then(() => {
+ expect(something).toBe('done');
+ })
+ .then(done)
+ .catch(done.fail);
+});
+```
+
+##### Vue rendering
+
+To wait until a Vue component is re-rendered, use either of the equivalent
+[`Vue.nextTick()`](https://vuejs.org/v2/api/#Vue-nextTick) or `vm.$nextTick()`.
+
+**in Jest:**
+
+```javascript
+it('renders something', () => {
+ wrapper.setProps({ value: 'new value' });
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.text()).toBe('new value');
+ });
+});
+```
+
+**in Karma:**
+
+```javascript
+it('renders something', done => {
+ wrapper.setProps({ value: 'new value' });
+
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ expect(wrapper.text()).toBe('new value');
+ })
+ .then(done)
+ .catch(done.fail);
+});
+```
+
+##### `setTimeout()` / `setInterval()` in application
+
+If the application itself is waiting for some time, mock await the waiting. In Jest this is already
+[done by default](https://gitlab.com/gitlab-org/gitlab-ce/blob/a2128edfee799e49a8732bfa235e2c5e14949c68/jest.config.js#L47)
+(see also [Jest Timer Mocks](https://jestjs.io/docs/en/timer-mocks)). In Karma you can use the
+[Jasmine mock clock](https://jasmine.github.io/api/2.9/Clock.html).
+
+```javascript
+const doSomethingLater = () => {
+ setTimeout(() => {
+ // do something
+ }, 4000);
+};
+```
+
+**in Jest:**
+
+```javascript
+it('does something', () => {
+ doSomethingLater();
+ jest.runAllTimers();
+
+ expect(something).toBe('done');
+});
+```
+
+**in Karma:**
+
+```javascript
+it('does something', () => {
+ jasmine.clock().install();
+
+ doSomethingLater();
+ jasmine.clock().tick(4000);
+
+ expect(something).toBe('done');
+ jasmine.clock().uninstall();
+});
+```
+
+##### Events
+
+If the application triggers an event that you need to wait for in your test, register an event handler which contains
+the assertions:
+
+```javascript
+it('waits for an event', done => {
+ eventHub.$once('someEvent', eventHandler);
+
+ someFunction();
+
+ function eventHandler() {
+ expect(something).toBe('done');
+ done();
+ }
+});
+```
+
+In Jest you can also use a `Promise` for this:
+
+```javascript
+it('waits for an event', () => {
+ const eventTriggered = new Promise(resolve => eventHub.$once('someEvent', resolve));
+
+ someFunction();
+
+ return eventTriggered.then(() => {
+ expect(something).toBe('done');
+ });
+});
+```
#### Migrating flaky Karma tests to Jest
@@ -231,7 +418,7 @@ See this [section][vue-test].
For running the frontend tests, you need the following commands:
-- `rake karma:fixtures` (re-)generates fixtures.
+- `rake karma:fixtures` (re-)generates [fixtures](#frontend-test-fixtures).
- `yarn test` executes the tests.
As long as the fixtures don't change, `yarn test` is sufficient (and saves you some time).
@@ -279,6 +466,48 @@ yarn karma -f 'spec/javascripts/ide/**/file_spec.js'
Information on setting up and running RSpec integration tests with
[Capybara] can be found in the [Testing Best Practices](best_practices.md).
+## Frontend test fixtures
+
+Code that is added to HAML templates (in `app/views/`) or makes Ajax requests to the backend has tests that require HTML or JSON from the backend.
+Fixtures for these tests are located at:
+
+- `spec/javascripts/fixtures/`, for running tests in CE.
+- `ee/spec/javascripts/fixtures/`, for running tests in EE.
+
+Fixture files in:
+
+- The Karma test suite are served by [jasmine-jquery](https://github.com/velesin/jasmine-jquery).
+- Jest use `spec/frontend/helpers/fixtures.js`.
+
+The following are examples of tests that work for both Karma and Jest:
+
+```javascript
+it('makes a request', () => {
+ const responseBody = getJSONFixture('some/fixture.json'); // loads spec/javascripts/fixtures/some/fixture.json
+ axiosMock.onGet(endpoint).reply(200, responseBody);
+
+ myButton.click();
+
+ // ...
+});
+
+it('uses some HTML element', () => {
+ loadFixtures('some/page.html'); // loads spec/javascripts/fixtures/some/page.html and adds it to the DOM
+
+ const element = document.getElementById('#my-id');
+
+ // ...
+});
+```
+
+HTML and JSON fixtures are generated from backend views and controllers using RSpec (see `spec/javascripts/fixtures/*.rb`).
+
+For each fixture, the content of the `response` variable is stored in the output file.
+This variable gets automagically set if the test is marked as `type: :request` or `type: :controller`.
+Fixtures are regenerated using the `bin/rake karma:fixtures` command but you can also generate them individually,
+for example `bin/rspec spec/javascripts/fixtures/merge_requests.rb`.
+When creating a new fixture, it often makes sense to take a look at the corresponding tests for the endpoint in `(ee/)spec/controllers/` or `(ee/)spec/requests/`.
+
## Gotchas
### RSpec errors due to JavaScript
@@ -311,7 +540,6 @@ end
```
[jasmine-focus]: https://jasmine.github.io/2.5/focused_specs.html
-[jasmine-jquery]: https://github.com/velesin/jasmine-jquery
[karma]: http://karma-runner.github.io/
[vue-test]: https://docs.gitlab.com/ce/development/fe_guide/vue.html#testing-vue-components
[rspec]: https://github.com/rspec/rspec-rails#feature-specs
diff --git a/doc/development/testing_guide/img/review_apps_cicd_architecture.png b/doc/development/testing_guide/img/review_apps_cicd_architecture.png
index 87e472076f3..1ee28d3db91 100644
--- a/doc/development/testing_guide/img/review_apps_cicd_architecture.png
+++ b/doc/development/testing_guide/img/review_apps_cicd_architecture.png
Binary files differ
diff --git a/doc/development/testing_guide/index.md b/doc/development/testing_guide/index.md
index ecad9ba48a3..93ee2a6371a 100644
--- a/doc/development/testing_guide/index.md
+++ b/doc/development/testing_guide/index.md
@@ -71,7 +71,7 @@ Everything you should know about how to test Rake tasks.
---
-## [End-to-end tests](end_to_end_tests.md)
+## [End-to-end tests](end_to_end/index.md)
Everything you should know about how to run end-to-end tests using
[GitLab QA][gitlab-qa] testing framework.
diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md
index 55ca502f84a..63b7b97c32f 100644
--- a/doc/development/testing_guide/review_apps.md
+++ b/doc/development/testing_guide/review_apps.md
@@ -6,7 +6,7 @@ Review Apps are automatically deployed by each pipeline, both in
## How does it work?
-### CD/CD architecture diagram
+### CI/CD architecture diagram
![Review Apps CI/CD architecture](img/review_apps_cicd_architecture.png)
@@ -14,23 +14,29 @@ Review Apps are automatically deployed by each pipeline, both in
<summary>Show mermaid source</summary>
<pre>
graph TD
- B1 -.->|2. once gitlab:assets:compile is done,<br />triggers a CNG-mirror pipeline and wait for it to be done| A2
- C1 -.->|2. once review-build-cng is done,<br />Helm deploys the Review App using the Cloud<br/>Native images built by the CNG-mirror pipeline| A3
-
-subgraph gitlab-ce/ee `test` stage
- A1[gitlab:assets:compile]
- B1[review-build-cng] -->|1. wait for| A1
- C1[review-deploy] -->|1. wait for| B1
- D1[review-qa-smoke] -->|1. wait for| C1
- D1[review-qa-smoke] -.->|2. once review-deploy is done| E1>gitlab-qa runs the smoke<br/>suite against the Review App]
+ build-qa-image -.->|once the `prepare` stage is done| gitlab:assets:compile
+ review-build-cng -->|triggers a CNG-mirror pipeline and wait for it to be done| CNG-mirror
+ review-build-cng -.->|once the `test` stage is done| review-deploy
+ review-deploy -.->|once the `review` stage is done| review-qa-smoke
+
+subgraph 1. gitlab-ce/ee `prepare` stage
+ build-qa-image
end
-subgraph CNG-mirror pipeline
- A2>Cloud Native images are built];
+subgraph 2. gitlab-ce/ee `test` stage
+ gitlab:assets:compile -->|plays dependent job once done| review-build-cng
+ end
+
+subgraph 3. gitlab-ce/ee `review` stage
+ review-deploy["review-deploy<br /><br />Helm deploys the Review App using the Cloud<br/>Native images built by the CNG-mirror pipeline.<br /><br />Cloud Native images are deployed to the `review-apps-ce` or `review-apps-ee`<br />Kubernetes (GKE) cluster, in the GCP `gitlab-review-apps` project."]
end
-subgraph GCP `gitlab-review-apps` project
- A3>"Cloud Native images are deployed to the<br />`review-apps-ce` or `review-apps-ee` Kubernetes (GKE) cluster"];
+subgraph 4. gitlab-ce/ee `qa` stage
+ review-qa-smoke[review-qa-smoke<br /><br />gitlab-qa runs the smoke suite against the Review App.]
+ end
+
+subgraph CNG-mirror pipeline
+ CNG-mirror>Cloud Native images are built];
end
</pre>
</details>
@@ -38,117 +44,194 @@ subgraph GCP `gitlab-review-apps` project
### Detailed explanation
1. On every [pipeline][gitlab-pipeline] during the `test` stage, the
- [`review-build-cng`][review-build-cng] and
- [`review-deploy`][review-deploy] jobs are automatically started.
- - The [`review-deploy`][review-deploy] job waits for the
- [`review-build-cng`][review-build-cng] job to finish.
- - The [`review-build-cng`][review-build-cng] job waits for the
- [`gitlab:assets:compile`][gitlab:assets:compile] job to finish since the
- [`CNG-mirror`][cng-mirror] pipeline triggered in the following step depends on it.
-1. Once the [`gitlab:assets:compile`][gitlab:assets:compile] job is done,
- [`review-build-cng`][review-build-cng] [triggers a pipeline][cng-pipeline]
- in the [`CNG-mirror`][cng-mirror] project.
- - The [`CNG-mirror`][cng-pipeline] pipeline creates the Docker images of
- each component (e.g. `gitlab-rails-ee`, `gitlab-shell`, `gitaly` etc.)
- based on the commit from the [GitLab pipeline][gitlab-pipeline] and store
- them in its [registry][cng-mirror-registry].
- - We use the [`CNG-mirror`][cng-mirror] project so that the `CNG`, (**C**loud
- **N**ative **G**itLab), project's registry is not overloaded with a
- lot of transient Docker images.
-1. Once the [`review-build-cng`][review-build-cng] job is done, the
- [`review-deploy`][review-deploy] job deploys the Review App using
- [the official GitLab Helm chart][helm-chart] to the
- [`review-apps-ce`][review-apps-ce] / [`review-apps-ee`][review-apps-ee]
- Kubernetes cluster on GCP.
- - The actual scripts used to deploy the Review App can be found at
- [`scripts/review_apps/review-apps.sh`][review-apps.sh].
- - These scripts are basically
- [our official Auto DevOps scripts][Auto-DevOps.gitlab-ci.yml] where the
- default CNG images are overridden with the images built and stored in the
- [`CNG-mirror` project's registry][cng-mirror-registry].
- - Since we're using [the official GitLab Helm chart][helm-chart], this means
- you get a dedicated environment for your branch that's very close to what
- it would look in production.
+ [`gitlab:assets:compile`][gitlab:assets:compile] job is automatically started.
+ - Once it's done, it starts the [`review-build-cng`][review-build-cng]
+ manual job since the [`CNG-mirror`][cng-mirror] pipeline triggered in the
+ following step depends on it.
+1. The [`review-build-cng`][review-build-cng] job [triggers a pipeline][cng-mirror-pipeline]
+ in the [`CNG-mirror`][cng-mirror] project.
+ - The [`CNG-mirror`][cng-mirror-pipeline] pipeline creates the Docker images of
+ each component (e.g. `gitlab-rails-ee`, `gitlab-shell`, `gitaly` etc.)
+ based on the commit from the [GitLab pipeline][gitlab-pipeline] and stores
+ them in its [registry][cng-mirror-registry].
+ - We use the [`CNG-mirror`][cng-mirror] project so that the `CNG`, (**C**loud
+ **N**ative **G**itLab), project's registry is not overloaded with a
+ lot of transient Docker images.
+ - Note that the official CNG images are built by the `cloud-native-image`
+ job, which runs only for tags, and triggers itself a [`CNG`][cng] pipeline.
+1. Once the `test` stage is done, the [`review-deploy`][review-deploy] job
+ deploys the Review App using [the official GitLab Helm chart][helm-chart] to
+ the [`review-apps-ce`][review-apps-ce] / [`review-apps-ee`][review-apps-ee]
+ Kubernetes cluster on GCP.
+ - The actual scripts used to deploy the Review App can be found at
+ [`scripts/review_apps/review-apps.sh`][review-apps.sh].
+ - These scripts are basically
+ [our official Auto DevOps scripts][Auto-DevOps.gitlab-ci.yml] where the
+ default CNG images are overridden with the images built and stored in the
+ [`CNG-mirror` project's registry][cng-mirror-registry].
+ - Since we're using [the official GitLab Helm chart][helm-chart], this means
+ you get a dedicated environment for your branch that's very close to what
+ it would look in production.
1. Once the [`review-deploy`][review-deploy] job succeeds, you should be able to
- use your Review App thanks to the direct link to it from the MR widget. To log
- into the Review App, see "Log into my Review App?" below.
+ use your Review App thanks to the direct link to it from the MR widget. To log
+ into the Review App, see "Log into my Review App?" below.
**Additional notes:**
+- If the `review-deploy` job keep failing (note that we already retry it twice),
+ please post a message in the `#quality` channel and/or create a ~Quality ~bug
+ issue with a link to your merge request. Note that the deployment failure can
+ reveal an actual problem introduced in your merge request (i.e. this isn't
+ necessarily a transient failure)!
+- If the `review-qa-smoke` job keep failing (note that we already retry it twice),
+ please check the job's logs: you could discover an actual problem introduced in
+ your merge request. You can also download the artifacts to see screenshots of
+ the page at the time the failures occurred. If you don't find the cause of the
+ failure or if it seems unrelated to your change, please post a message in the
+ `#quality` channel and/or create a ~Quality ~bug issue with a link to your
+ merge request.
+- The manual [`review-stop`][gitlab-ci-yml] in the `test` stage can be used to
+ stop a Review App manually, and is also started by GitLab once a merge
+ request's branch is deleted after being merged.
+- Review Apps are cleaned up regularly via a pipeline schedule that runs
+ the [`schedule:review-cleanup`][gitlab-ci-yml] job.
- The Kubernetes cluster is connected to the `gitlab-{ce,ee}` projects using
[GitLab's Kubernetes integration][gitlab-k8s-integration]. This basically
allows to have a link to the Review App directly from the merge request
widget.
-- If the Review App deployment fails, you can simply retry it (there's no need
- to run the [`review-stop`][gitlab-ci-yml] job first).
-- The manual [`review-stop`][gitlab-ci-yml] in the `test` stage can be used to
- stop a Review App manually, and is also started by GitLab once a branch is
- deleted.
-- Review Apps are cleaned up regularly using a pipeline schedule that runs
- the [`schedule:review-cleanup`][gitlab-ci-yml] job.
## QA runs
-On every [pipeline][gitlab-pipeline] during the `test` stage, the
-`review-qa-smoke` job is automatically started: it runs the QA smoke suite.
-You can also manually start the `review-qa-all`: it runs the QA full suite.
+On every [pipeline][gitlab-pipeline] in the `qa` stage (which comes after the
+`review` stage), the `review-qa-smoke` job is automatically started and it runs
+the QA smoke suite.
-Note that both jobs first wait for the `review-deploy` job to be finished.
+You can also manually start the `review-qa-all`: it runs the full QA suite.
## Performance Metrics
-On every [pipeline][gitlab-pipeline] during the `test` stage, the
+On every [pipeline][gitlab-pipeline] in the `qa` stage, the
`review-performance` job is automatically started: this job does basic
-browser performance testing using [Sitespeed.io Container](https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html) .
-
-This job waits for the `review-deploy` job to be finished.
+browser performance testing using a
+[Sitespeed.io Container](../../user/project/merge_requests/browser_performance_testing.md).
-## How to?
+## How to:
-### Log into my Review App?
+### Log into my Review App
The default username is `root` and its password can be found in the 1Password
secure note named **gitlab-{ce,ee} Review App's root password**.
-### Enable a feature flag for my Review App?
+### Enable a feature flag for my Review App
1. Open your Review App and log in as documented above.
1. Create a personal access token.
1. Enable the feature flag using the [Feature flag API](../../api/features.md).
-### Find my Review App slug?
+### Find my Review App slug
1. Open the `review-deploy` job.
1. Look for `Checking for previous deployment of review-*`.
1. For instance for `Checking for previous deployment of review-qa-raise-e-12chm0`,
- your Review App slug would be `review-qa-raise-e-12chm0` in this case.
+ your Review App slug would be `review-qa-raise-e-12chm0` in this case.
-### Run a Rails console?
+### Run a Rails console
1. [Filter Workloads by your Review App slug](https://console.cloud.google.com/kubernetes/workload?project=gitlab-review-apps)
- , e.g. `review-29951-issu-id2qax`.
-1. Find and open the `task-runner` Deployment, e.g. `review-29951-issu-id2qax-task-runner`.
-1. Click on the Pod in the "Managed pods" section, e.g. `review-29951-issu-id2qax-task-runner-d5455cc8-2lsvz`.
+ , e.g. `review-qa-raise-e-12chm0`.
+1. Find and open the `task-runner` Deployment, e.g. `review-qa-raise-e-12chm0-task-runner`.
+1. Click on the Pod in the "Managed pods" section, e.g. `review-qa-raise-e-12chm0-task-runner-d5455cc8-2lsvz`.
1. Click on the `KUBECTL` dropdown, then `Exec` -> `task-runner`.
1. Replace `-c task-runner -- ls` with `-it -- gitlab-rails console` from the
- default command or
- - Run `kubectl exec --namespace review-apps-ce review-29951-issu-id2qax-task-runner-d5455cc8-2lsvz -it -- gitlab-rails console`
- and
- - Replace `review-apps-ce` with `review-apps-ee` if the Review App
- is running EE, and
- - Replace `review-29951-issu-id2qax-task-runner-d5455cc8-2lsvz`
- with your Pod's name.
+ default command or
+ - Run `kubectl exec --namespace review-apps-ce review-qa-raise-e-12chm0-task-runner-d5455cc8-2lsvz -it -- gitlab-rails console` and
+ - Replace `review-apps-ce` with `review-apps-ee` if the Review App
+ is running EE, and
+ - Replace `review-qa-raise-e-12chm0-task-runner-d5455cc8-2lsvz`
+ with your Pod's name.
-### Dig into a Pod's logs?
+### Dig into a Pod's logs
-1. [Filter Workloads by your Review App slug](https://console.cloud.google.com/kubernetes/workload?project=gitlab-review-apps)
- , e.g. `review-1979-1-mul-dnvlhv`.
+1. [Filter Workloads by your Review App slug](https://console.cloud.google.com/kubernetes/workload?project=gitlab-review-apps),
+ e.g. `review-qa-raise-e-12chm0`.
1. Find and open the `migrations` Deployment, e.g.
- `review-1979-1-mul-dnvlhv-migrations.1`.
+ `review-qa-raise-e-12chm0-migrations.1`.
1. Click on the Pod in the "Managed pods" section, e.g.
- `review-1979-1-mul-dnvlhv-migrations.1-nqwtx`.
+ `review-qa-raise-e-12chm0-migrations.1-nqwtx`.
1. Click on the `Container logs` link.
+### Troubleshoot a pending `dns-gitlab-review-app-external-dns` Deployment
+
+#### Finding the problem
+
+[In the past](https://gitlab.com/gitlab-org/gitlab-ce/issues/62834), it happened
+that the `dns-gitlab-review-app-external-dns` Deployment was in a pending state,
+effectively preventing all the Review Apps from getting a DNS record assigned,
+making them unreachable via domain name.
+
+This in turn prevented other components of the Review App to properly start
+(e.g. `gitlab-runner`).
+
+After some digging, we found that new mounts were failing, when being performed
+with transient scopes (e.g. pods) of `systemd-mount`:
+
+```
+MountVolume.SetUp failed for volume "dns-gitlab-review-app-external-dns-token-sj5jm" : mount failed: exit status 1
+Mounting command: systemd-run
+Mounting arguments: --description=Kubernetes transient mount for /var/lib/kubelet/pods/06add1c3-87b4-11e9-80a9-42010a800107/volumes/kubernetes.io~secret/dns-gitlab-review-app-external-dns-token-sj5jm --scope -- mount -t tmpfs tmpfs /var/lib/kubelet/pods/06add1c3-87b4-11e9-80a9-42010a800107/volumes/kubernetes.io~secret/dns-gitlab-review-app-external-dns-token-sj5jm
+Output: Failed to start transient scope unit: Connection timed out
+```
+
+This probably happened because the GitLab chart creates 67 resources, leading to
+a lot of mount points being created on the underlying GCP node.
+
+The [underlying issue seems to be a `systemd` bug](https://github.com/kubernetes/kubernetes/issues/57345#issuecomment-359068048)
+that was fixed in `systemd` `v237`. Unfortunately, our GCP nodes are currently
+using `v232`.
+
+For the record, the debugging steps to find out this issue were:
+
+1. Switch kubectl context to review-apps-ce (we recommend using [kubectx](https://kubectx.dev/))
+1. `kubectl get pods | grep dns`
+1. `kubectl describe pod <pod name>` & confirm exact error message
+1. Web search for exact error message, following rabbit hole to [a relevant kubernetes bug report](https://github.com/kubernetes/kubernetes/issues/57345)
+1. Access the node over SSH via the GCP console (**Computer Engine > VM
+ instances** then click the "SSH" button for the node where the `dns-gitlab-review-app-external-dns` pod runs)
+1. In the node: `systemctl --version` => systemd 232
+1. Gather some more information:
+ - `mount | grep kube | wc -l` => e.g. 290
+ - `systemctl list-units --all | grep -i var-lib-kube | wc -l` => e.g. 142
+1. Check how many pods are in a bad state:
+ - Get all pods running a given node: `kubectl get pods --field-selector=spec.nodeName=NODE_NAME`
+ - Get all the `Running` pods on a given node: `kubectl get pods --field-selector=spec.nodeName=NODE_NAME | grep Running`
+ - Get all the pods in a bad state on a given node: `kubectl get pods --field-selector=spec.nodeName=NODE_NAME | grep -v 'Running' | grep -v 'Completed'`
+
+#### Solving the problem
+
+To resolve the problem, we needed to (forcibly) drain some nodes:
+
+1. Try a normal drain on the node where the `dns-gitlab-review-app-external-dns`
+ pod runs so that Kubernetes automatically move it to another node: `kubectl drain NODE_NAME`
+1. If that doesn't work, you can also perform a forcible "drain" the node by removing all pods: `kubectl delete pods --field-selector=spec.nodeName=NODE_NAME`
+1. In the node:
+ - Perform `systemctl daemon-reload` to remove the dead/inactive units
+ - If that doesn't solve the problem, perform a hard reboot: `sudo systemctl reboot`
+1. Uncordon any cordoned nodes: `kubectl uncordon NODE_NAME`
+
+In parallel, since most Review Apps were in a broken state, we deleted them to
+clean up the list of non-`Running` pods.
+Following is a command to delete Review Apps based on their last deployment date
+(current date was June 6th at the time) with
+
+```
+helm ls -d | grep "Jun 4" | cut -f1 | xargs helm delete --purge
+```
+
+#### Mitigation steps taken to avoid this problem in the future
+
+We've created a new node pool with smaller machines so that it's less likely
+that a machine will hit the "too many mount points" problem in the future.
+
## Frequently Asked Questions
**Isn't it too much to trigger CNG image builds on every test run? This creates
@@ -161,11 +244,11 @@ thousands of unused Docker images.**
**How big are the Kubernetes clusters (`review-apps-ce` and `review-apps-ee`)?**
> The clusters are currently set up with a single pool of preemptible nodes,
- with a minimum of 1 node and a maximum of 50 nodes.
+ with a minimum of 1 node and a maximum of 500 nodes.
**What are the machine running on the cluster?**
- > We're currently using `n1-standard-16` (16 vCPUs, 60 GB memory) machines.
+ > We're currently using `n1-standard-1` (1 vCPU, 3.75 GB memory) machines.
**How do we secure this from abuse? Apps are open to the world so we need to
find a way to limit it to only us.**
@@ -182,7 +265,8 @@ find a way to limit it to only us.**
[review-build-cng]: https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/149511623
[review-deploy]: https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/149511624
[cng-mirror]: https://gitlab.com/gitlab-org/build/CNG-mirror
-[cng-pipeline]: https://gitlab.com/gitlab-org/build/CNG-mirror/pipelines/44364657
+[cng]: https://gitlab.com/gitlab-org/build/CNG
+[cng-mirror-pipeline]: https://gitlab.com/gitlab-org/build/CNG-mirror/pipelines/44364657
[cng-mirror-registry]: https://gitlab.com/gitlab-org/build/CNG-mirror/container_registry
[helm-chart]: https://gitlab.com/charts/gitlab/
[review-apps-ce]: https://console.cloud.google.com/kubernetes/clusters/details/us-central1-a/review-apps-ce?project=gitlab-review-apps
@@ -191,7 +275,7 @@ find a way to limit it to only us.**
[automated_cleanup.rb]: https://gitlab.com/gitlab-org/gitlab-ee/blob/master/scripts/review_apps/automated_cleanup.rb
[Auto-DevOps.gitlab-ci.yml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
[gitlab-ci-yml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab-ci.yml
-[gitlab-k8s-integration]: https://docs.gitlab.com/ee/user/project/clusters/index.html
+[gitlab-k8s-integration]: ../../user/project/clusters/index.md
[password-bug]: https://gitlab.com/gitlab-org/gitlab-ce/issues/53621
---
diff --git a/doc/development/testing_guide/smoke.md b/doc/development/testing_guide/smoke.md
index 30d861d7d68..c9d3238fbe9 100644
--- a/doc/development/testing_guide/smoke.md
+++ b/doc/development/testing_guide/smoke.md
@@ -17,7 +17,7 @@ Currently, our suite consists of this basic functionality coverage:
Smoke tests have the `:smoke` RSpec metadata.
-See [End-to-end Testing](./end_to_end_tests.md) for more details about
+See [End-to-end Testing](end_to_end/index.md) for more details about
end-to-end tests.
---
diff --git a/doc/development/testing_guide/testing_levels.md b/doc/development/testing_guide/testing_levels.md
index 352651fe91b..e1ce4d3b7d1 100644
--- a/doc/development/testing_guide/testing_levels.md
+++ b/doc/development/testing_guide/testing_levels.md
@@ -4,6 +4,15 @@
_This diagram demonstrates the relative priority of each test type we use. `e2e` stands for end-to-end._
+As of 2019-05-01, we have the following distribution of tests per level:
+
+| Test level | Community Edition | Enterprise Edition | Community + Enterprise Edition |
+| --------- | ---------- | -------------- | ----- |
+| Black-box tests at the system level (aka end-to-end or QA tests) | 68 (0.14%) | 31 (0.2%) | 99 (0.17%) |
+| White-box tests at the system level (aka system or feature tests) | 5,471 (11.9%) | 969 (7.4%) | 6440 (10.9%) |
+| Integration tests | 8,333 (18.2%) | 2,244 (17.2%) | 10,577 (17.9%) |
+| Unit tests | 32,031 (69.7%) | 9,778 (75.1%) | 41,809 (71%) |
+
## Unit tests
Formal definition: <https://en.wikipedia.org/wiki/Unit_testing>
@@ -16,19 +25,31 @@ records should use stubs/doubles as much as possible.
| Code path | Tests path | Testing engine | Notes |
| --------- | ---------- | -------------- | ----- |
+| `app/assets/javascripts/` | `spec/javascripts/`, `spec/frontend/` | Karma & Jest | More details in the [Frontend Testing guide](frontend_testing.md) section. |
| `app/finders/` | `spec/finders/` | RSpec | |
+| `app/graphql/` | `spec/graphql/` | RSpec | |
| `app/helpers/` | `spec/helpers/` | RSpec | |
-| `app/db/{post_,}migrate/` | `spec/migrations/` | RSpec | More details at [`spec/migrations/README.md`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/spec/migrations/README.md). |
+| `app/models/` | `spec/models/` | RSpec | |
| `app/policies/` | `spec/policies/` | RSpec | |
| `app/presenters/` | `spec/presenters/` | RSpec | |
-| `app/routing/` | `spec/routing/` | RSpec | |
| `app/serializers/` | `spec/serializers/` | RSpec | |
| `app/services/` | `spec/services/` | RSpec | |
-| `app/tasks/` | `spec/tasks/` | RSpec | |
| `app/uploaders/` | `spec/uploaders/` | RSpec | |
+| `app/validators/` | `spec/validators/` | RSpec | |
| `app/views/` | `spec/views/` | RSpec | |
| `app/workers/` | `spec/workers/` | RSpec | |
-| `app/assets/javascripts/` | `spec/javascripts/` | Karma | More details in the [Frontend Testing guide](frontend_testing.md) section. |
+| `bin/` | `spec/bin/` | RSpec | |
+| `config/` | `spec/config/` | RSpec | |
+| `config/initializers/` | `spec/initializers/` | RSpec | |
+| `config/routes.rb`, `config/routes/` | `spec/routing/` | RSpec | |
+| `config/puma.example.development.rb`, `config/unicorn.rb.example` | `spec/rack_servers/` | RSpec | |
+| `db/` | `spec/db/` | RSpec | |
+| `db/{post_,}migrate/` | `spec/migrations/` | RSpec | More details at [`spec/migrations/README.md`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/spec/migrations/README.md). |
+| `Gemfile` | `spec/dependencies/`, `spec/sidekiq/` | RSpec | |
+| `lib/` | `spec/lib/` | RSpec | |
+| `lib/tasks/` | `spec/tasks/` | RSpec | |
+| `rubocop/` | `spec/rubocop/` | RSpec | |
+| `spec/factories` | `spec/factories_spec.rb` | RSpec | |
## Integration tests
@@ -46,7 +67,7 @@ They're useful to test permissions, redirections, what view is rendered etc.
| `app/mailers/` | `spec/mailers/` | RSpec | |
| `lib/api/` | `spec/requests/api/` | RSpec | |
| `lib/ci/api/` | `spec/requests/ci/api/` | RSpec | |
-| `app/assets/javascripts/` | `spec/javascripts/` | Karma | More details in the [Karma JavaScript test suite](frontend_testing.md#karma-test-suite) section. |
+| `app/assets/javascripts/` | `spec/javascripts/`, `spec/frontend/` | Karma & Jest | More details in the [Frontend Testing guide](frontend_testing.md) section. |
### About controller tests
@@ -157,7 +178,7 @@ Every new feature should come with a [test plan].
| ---------- | -------------- | ----- |
| `qa/qa/specs/features/` | [Capybara] + [RSpec] + Custom QA framework | Tests should be placed under their corresponding [Product category] |
-> See [end-to-end tests](end_to_end_tests.md) for more information.
+> See [end-to-end tests](end_to_end/index.md) for more information.
Note that `qa/spec` contains unit tests of the QA framework itself, not to be
confused with the application's [unit tests](#unit-tests) or
diff --git a/doc/development/understanding_explain_plans.md b/doc/development/understanding_explain_plans.md
index 01a0044f096..bfbb7be70e3 100644
--- a/doc/development/understanding_explain_plans.md
+++ b/doc/development/understanding_explain_plans.md
@@ -80,8 +80,9 @@ Planning time: 2.861 ms
Execution time: 3428.596 ms
```
-For more information, refer to the official [EXPLAIN
-documentation](https://www.postgresql.org/docs/current/static/sql-explain.html).
+For more information, refer to the official
+[`EXPLAIN` documentation](https://www.postgresql.org/docs/current/sql-explain.html)
+and [using `EXPLAIN` guide](https://www.postgresql.org/docs/current/using-explain.html).
## Nodes
@@ -653,9 +654,39 @@ and related tools such as:
- <https://explain.depesz.com/>
- <http://tatiyants.com/postgres-query-plan-visualization/>
-GitLab employees can also use our chatops solution, available in Slack using the
-`/chatops` slash command. You can use chatops to get a query plan by running the
-following:
+
+## Producing query plans
+
+There are a few ways to get the output of a query plan. Of course you
+can directly run the `EXPLAIN` query in the `psql` console, or you can
+follow one of the other options below.
+
+### Rails console
+
+Using the [`activerecord-explain-analyze`](https://github.com/6/activerecord-explain-analyze)
+you can directly generate the query plan from the Rails console:
+
+```ruby
+pry(main)> require 'activerecord-explain-analyze'
+=> true
+pry(main)> Project.where('build_timeout > ?', 3600).explain(analyze: true)
+ Project Load (1.9ms) SELECT "projects".* FROM "projects" WHERE (build_timeout > 3600)
+ ↳ (pry):12
+=> EXPLAIN for: SELECT "projects".* FROM "projects" WHERE (build_timeout > 3600)
+Seq Scan on public.projects (cost=0.00..2.17 rows=1 width=742) (actual time=0.040..0.041 rows=0 loops=1)
+ Output: id, name, path, description, created_at, updated_at, creator_id, namespace_id, ...
+ Filter: (projects.build_timeout > 3600)
+ Rows Removed by Filter: 14
+ Buffers: shared hit=2
+Planning time: 0.411 ms
+Execution time: 0.113 ms
+```
+
+### Chatops
+
+[GitLab employees can also use our chatops solution, available in Slack using the
+`/chatops` slash command](chatops_on_gitlabcom.md).
+You can use chatops to get a query plan by running the following:
```
/chatops run explain SELECT COUNT(*) FROM projects WHERE visibility_level IN (0, 20)
@@ -674,3 +705,9 @@ For more information about the available options, run:
```
/chatops run explain --help
```
+
+## Further reading
+
+A more extensive guide on understanding query plans can be found in
+the [presentation](https://www.dalibo.org/_media/understanding_explain.pdf)
+from [Dalibo.org](https://www.dalibo.org/en/).
diff --git a/doc/development/ux_guide/img/animation-autoscroll.gif b/doc/development/ux_guide/img/animation-autoscroll.gif
deleted file mode 100644
index 155b0234c64..00000000000
--- a/doc/development/ux_guide/img/animation-autoscroll.gif
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/animation-dropdown.gif b/doc/development/ux_guide/img/animation-dropdown.gif
deleted file mode 100644
index c9b31d26165..00000000000
--- a/doc/development/ux_guide/img/animation-dropdown.gif
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/animation-hover.gif b/doc/development/ux_guide/img/animation-hover.gif
deleted file mode 100644
index 37ad9c76828..00000000000
--- a/doc/development/ux_guide/img/animation-hover.gif
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/animation-quickupdate.gif b/doc/development/ux_guide/img/animation-quickupdate.gif
deleted file mode 100644
index 8db70bc3d24..00000000000
--- a/doc/development/ux_guide/img/animation-quickupdate.gif
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/animation-reorder.gif b/doc/development/ux_guide/img/animation-reorder.gif
deleted file mode 100644
index ccdeb3d396f..00000000000
--- a/doc/development/ux_guide/img/animation-reorder.gif
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-close--active.png b/doc/development/ux_guide/img/button-close--active.png
deleted file mode 100644
index 97a5301fb91..00000000000
--- a/doc/development/ux_guide/img/button-close--active.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-close--hover.png b/doc/development/ux_guide/img/button-close--hover.png
deleted file mode 100644
index 6b8fdf5695b..00000000000
--- a/doc/development/ux_guide/img/button-close--hover.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-close--resting.png b/doc/development/ux_guide/img/button-close--resting.png
deleted file mode 100644
index 5679b51687c..00000000000
--- a/doc/development/ux_guide/img/button-close--resting.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-danger--active.png b/doc/development/ux_guide/img/button-danger--active.png
deleted file mode 100644
index 6a9aab0fcc2..00000000000
--- a/doc/development/ux_guide/img/button-danger--active.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-danger--hover.png b/doc/development/ux_guide/img/button-danger--hover.png
deleted file mode 100644
index 13e21c28779..00000000000
--- a/doc/development/ux_guide/img/button-danger--hover.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-danger--resting.png b/doc/development/ux_guide/img/button-danger--resting.png
deleted file mode 100644
index 0ff192bc463..00000000000
--- a/doc/development/ux_guide/img/button-danger--resting.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-info--active.png b/doc/development/ux_guide/img/button-info--active.png
deleted file mode 100644
index 12ecdc72a31..00000000000
--- a/doc/development/ux_guide/img/button-info--active.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-info--hover.png b/doc/development/ux_guide/img/button-info--hover.png
deleted file mode 100644
index 3bf93bf2b32..00000000000
--- a/doc/development/ux_guide/img/button-info--hover.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-info--resting.png b/doc/development/ux_guide/img/button-info--resting.png
deleted file mode 100644
index a37a37033bf..00000000000
--- a/doc/development/ux_guide/img/button-info--resting.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-primary.png b/doc/development/ux_guide/img/button-primary.png
deleted file mode 100644
index eda5ed84aec..00000000000
--- a/doc/development/ux_guide/img/button-primary.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-secondary.png b/doc/development/ux_guide/img/button-secondary.png
deleted file mode 100644
index 26d4e8cf43d..00000000000
--- a/doc/development/ux_guide/img/button-secondary.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-spam--active.png b/doc/development/ux_guide/img/button-spam--active.png
deleted file mode 100644
index a9e115f49c1..00000000000
--- a/doc/development/ux_guide/img/button-spam--active.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-spam--hover.png b/doc/development/ux_guide/img/button-spam--hover.png
deleted file mode 100644
index 3b2c16430a6..00000000000
--- a/doc/development/ux_guide/img/button-spam--hover.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-spam--resting.png b/doc/development/ux_guide/img/button-spam--resting.png
deleted file mode 100644
index 4f9f18ca68a..00000000000
--- a/doc/development/ux_guide/img/button-spam--resting.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-success--active.png b/doc/development/ux_guide/img/button-success--active.png
deleted file mode 100644
index b99f6f5e70e..00000000000
--- a/doc/development/ux_guide/img/button-success--active.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-success--hover.png b/doc/development/ux_guide/img/button-success--hover.png
deleted file mode 100644
index 0d0a61c679a..00000000000
--- a/doc/development/ux_guide/img/button-success--hover.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-success--resting.png b/doc/development/ux_guide/img/button-success--resting.png
deleted file mode 100644
index 53b955c650a..00000000000
--- a/doc/development/ux_guide/img/button-success--resting.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-success-secondary--active.png b/doc/development/ux_guide/img/button-success-secondary--active.png
deleted file mode 100644
index 333a91f2217..00000000000
--- a/doc/development/ux_guide/img/button-success-secondary--active.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-success-secondary--hover.png b/doc/development/ux_guide/img/button-success-secondary--hover.png
deleted file mode 100644
index 0cce59212e3..00000000000
--- a/doc/development/ux_guide/img/button-success-secondary--hover.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-success-secondary--resting.png b/doc/development/ux_guide/img/button-success-secondary--resting.png
deleted file mode 100644
index 2779a4949f8..00000000000
--- a/doc/development/ux_guide/img/button-success-secondary--resting.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-warning--active.png b/doc/development/ux_guide/img/button-warning--active.png
deleted file mode 100644
index f5760cd7c12..00000000000
--- a/doc/development/ux_guide/img/button-warning--active.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-warning--hover.png b/doc/development/ux_guide/img/button-warning--hover.png
deleted file mode 100644
index a1f4c5cbcc6..00000000000
--- a/doc/development/ux_guide/img/button-warning--hover.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/button-warning--resting.png b/doc/development/ux_guide/img/button-warning--resting.png
deleted file mode 100644
index 3d62fed5930..00000000000
--- a/doc/development/ux_guide/img/button-warning--resting.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/color-blue.png b/doc/development/ux_guide/img/color-blue.png
deleted file mode 100644
index 77c1a2cab31..00000000000
--- a/doc/development/ux_guide/img/color-blue.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/color-green.png b/doc/development/ux_guide/img/color-green.png
deleted file mode 100644
index 51600584c96..00000000000
--- a/doc/development/ux_guide/img/color-green.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/color-grey.png b/doc/development/ux_guide/img/color-grey.png
deleted file mode 100644
index f0f0b9d80bb..00000000000
--- a/doc/development/ux_guide/img/color-grey.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/color-orange.png b/doc/development/ux_guide/img/color-orange.png
deleted file mode 100644
index f16435c0a64..00000000000
--- a/doc/development/ux_guide/img/color-orange.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/color-red.png b/doc/development/ux_guide/img/color-red.png
deleted file mode 100644
index 5008e75da78..00000000000
--- a/doc/development/ux_guide/img/color-red.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/color-textprimary.png b/doc/development/ux_guide/img/color-textprimary.png
deleted file mode 100644
index 90f2821f0cf..00000000000
--- a/doc/development/ux_guide/img/color-textprimary.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/color-textsecondary.png b/doc/development/ux_guide/img/color-textsecondary.png
deleted file mode 100644
index 61cb8a13c45..00000000000
--- a/doc/development/ux_guide/img/color-textsecondary.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-alerts.png b/doc/development/ux_guide/img/components-alerts.png
deleted file mode 100644
index 66a43ac69e1..00000000000
--- a/doc/development/ux_guide/img/components-alerts.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-anchorlinks.png b/doc/development/ux_guide/img/components-anchorlinks.png
deleted file mode 100644
index bd8d30f5905..00000000000
--- a/doc/development/ux_guide/img/components-anchorlinks.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-contentblock.png b/doc/development/ux_guide/img/components-contentblock.png
deleted file mode 100644
index 58d87729701..00000000000
--- a/doc/development/ux_guide/img/components-contentblock.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-counts.png b/doc/development/ux_guide/img/components-counts.png
deleted file mode 100644
index 19280e988a0..00000000000
--- a/doc/development/ux_guide/img/components-counts.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-coverblock.png b/doc/development/ux_guide/img/components-coverblock.png
deleted file mode 100644
index 61160de5613..00000000000
--- a/doc/development/ux_guide/img/components-coverblock.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-dateexact.png b/doc/development/ux_guide/img/components-dateexact.png
deleted file mode 100644
index cc1fb8216bf..00000000000
--- a/doc/development/ux_guide/img/components-dateexact.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-daterelative.png b/doc/development/ux_guide/img/components-daterelative.png
deleted file mode 100644
index 4954dfb51b3..00000000000
--- a/doc/development/ux_guide/img/components-daterelative.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-dropdown.png b/doc/development/ux_guide/img/components-dropdown.png
deleted file mode 100644
index 7f9a701c089..00000000000
--- a/doc/development/ux_guide/img/components-dropdown.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-fileholder.png b/doc/development/ux_guide/img/components-fileholder.png
deleted file mode 100644
index 5bf8565346a..00000000000
--- a/doc/development/ux_guide/img/components-fileholder.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-horizontalform.png b/doc/development/ux_guide/img/components-horizontalform.png
deleted file mode 100644
index e6cbc69d20a..00000000000
--- a/doc/development/ux_guide/img/components-horizontalform.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-listinsidepanel.png b/doc/development/ux_guide/img/components-listinsidepanel.png
deleted file mode 100644
index 6b773a19954..00000000000
--- a/doc/development/ux_guide/img/components-listinsidepanel.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-listwithavatar.png b/doc/development/ux_guide/img/components-listwithavatar.png
deleted file mode 100644
index f6db575433c..00000000000
--- a/doc/development/ux_guide/img/components-listwithavatar.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-listwithhover.png b/doc/development/ux_guide/img/components-listwithhover.png
deleted file mode 100644
index 0826848ff34..00000000000
--- a/doc/development/ux_guide/img/components-listwithhover.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-panels.png b/doc/development/ux_guide/img/components-panels.png
deleted file mode 100644
index c1391ca07e5..00000000000
--- a/doc/development/ux_guide/img/components-panels.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-referencehover.png b/doc/development/ux_guide/img/components-referencehover.png
deleted file mode 100644
index af5405d3e0b..00000000000
--- a/doc/development/ux_guide/img/components-referencehover.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-referenceissues.png b/doc/development/ux_guide/img/components-referenceissues.png
deleted file mode 100644
index 4e175dc169d..00000000000
--- a/doc/development/ux_guide/img/components-referenceissues.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-referencelabels.png b/doc/development/ux_guide/img/components-referencelabels.png
deleted file mode 100644
index 29a985bbaa0..00000000000
--- a/doc/development/ux_guide/img/components-referencelabels.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-referencemilestone.png b/doc/development/ux_guide/img/components-referencemilestone.png
deleted file mode 100644
index 47c76a9d60f..00000000000
--- a/doc/development/ux_guide/img/components-referencemilestone.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-referencemrs.png b/doc/development/ux_guide/img/components-referencemrs.png
deleted file mode 100644
index 9a5032a1516..00000000000
--- a/doc/development/ux_guide/img/components-referencemrs.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-referencepeople.png b/doc/development/ux_guide/img/components-referencepeople.png
deleted file mode 100644
index f9ef11be853..00000000000
--- a/doc/development/ux_guide/img/components-referencepeople.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-rowcontentblock.png b/doc/development/ux_guide/img/components-rowcontentblock.png
deleted file mode 100644
index c66a50f9564..00000000000
--- a/doc/development/ux_guide/img/components-rowcontentblock.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-searchbox.png b/doc/development/ux_guide/img/components-searchbox.png
deleted file mode 100644
index 5c19024bfb0..00000000000
--- a/doc/development/ux_guide/img/components-searchbox.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-searchboxscoped.png b/doc/development/ux_guide/img/components-searchboxscoped.png
deleted file mode 100644
index d4a35977658..00000000000
--- a/doc/development/ux_guide/img/components-searchboxscoped.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-simplelist.png b/doc/development/ux_guide/img/components-simplelist.png
deleted file mode 100644
index 8d11c674e84..00000000000
--- a/doc/development/ux_guide/img/components-simplelist.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-table.png b/doc/development/ux_guide/img/components-table.png
deleted file mode 100644
index cedc55758a9..00000000000
--- a/doc/development/ux_guide/img/components-table.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/components-verticalform.png b/doc/development/ux_guide/img/components-verticalform.png
deleted file mode 100644
index 489ae6f862f..00000000000
--- a/doc/development/ux_guide/img/components-verticalform.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/cursors-default.png b/doc/development/ux_guide/img/cursors-default.png
deleted file mode 100644
index c188ec4e351..00000000000
--- a/doc/development/ux_guide/img/cursors-default.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/cursors-ibeam.png b/doc/development/ux_guide/img/cursors-ibeam.png
deleted file mode 100644
index 86f28639982..00000000000
--- a/doc/development/ux_guide/img/cursors-ibeam.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/cursors-move.png b/doc/development/ux_guide/img/cursors-move.png
deleted file mode 100644
index a9c610eaa88..00000000000
--- a/doc/development/ux_guide/img/cursors-move.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/cursors-panclosed.png b/doc/development/ux_guide/img/cursors-panclosed.png
deleted file mode 100644
index 6d247a765ac..00000000000
--- a/doc/development/ux_guide/img/cursors-panclosed.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/cursors-panopened.png b/doc/development/ux_guide/img/cursors-panopened.png
deleted file mode 100644
index 76f2eeda831..00000000000
--- a/doc/development/ux_guide/img/cursors-panopened.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/cursors-pointer.png b/doc/development/ux_guide/img/cursors-pointer.png
deleted file mode 100644
index d86dd955fa7..00000000000
--- a/doc/development/ux_guide/img/cursors-pointer.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/features-contextualnav.png b/doc/development/ux_guide/img/features-contextualnav.png
deleted file mode 100644
index aa816776fad..00000000000
--- a/doc/development/ux_guide/img/features-contextualnav.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/features-emptystates.png b/doc/development/ux_guide/img/features-emptystates.png
deleted file mode 100644
index 50f31f5e523..00000000000
--- a/doc/development/ux_guide/img/features-emptystates.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/features-filters.png b/doc/development/ux_guide/img/features-filters.png
deleted file mode 100644
index 41db76db938..00000000000
--- a/doc/development/ux_guide/img/features-filters.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/features-globalnav.png b/doc/development/ux_guide/img/features-globalnav.png
deleted file mode 100644
index 73294d1b524..00000000000
--- a/doc/development/ux_guide/img/features-globalnav.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/harry-robison.png b/doc/development/ux_guide/img/harry-robison.png
deleted file mode 100644
index 702a8b02262..00000000000
--- a/doc/development/ux_guide/img/harry-robison.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-add.png b/doc/development/ux_guide/img/icon-add.png
deleted file mode 100644
index f66525cc1b4..00000000000
--- a/doc/development/ux_guide/img/icon-add.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-close.png b/doc/development/ux_guide/img/icon-close.png
deleted file mode 100644
index af6c30ebe6a..00000000000
--- a/doc/development/ux_guide/img/icon-close.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-edit.png b/doc/development/ux_guide/img/icon-edit.png
deleted file mode 100644
index b9649f4aeec..00000000000
--- a/doc/development/ux_guide/img/icon-edit.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-notification.png b/doc/development/ux_guide/img/icon-notification.png
deleted file mode 100644
index 5cf8f8ab59a..00000000000
--- a/doc/development/ux_guide/img/icon-notification.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-rss.png b/doc/development/ux_guide/img/icon-rss.png
deleted file mode 100644
index 7e2987a2656..00000000000
--- a/doc/development/ux_guide/img/icon-rss.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-spec.png b/doc/development/ux_guide/img/icon-spec.png
deleted file mode 100644
index 5bb85c5be98..00000000000
--- a/doc/development/ux_guide/img/icon-spec.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-subscribe.png b/doc/development/ux_guide/img/icon-subscribe.png
deleted file mode 100644
index 7e2f5e6a1c6..00000000000
--- a/doc/development/ux_guide/img/icon-subscribe.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/icon-trash.png b/doc/development/ux_guide/img/icon-trash.png
deleted file mode 100644
index bc46638fb2e..00000000000
--- a/doc/development/ux_guide/img/icon-trash.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/illustration-size-large-horizontal.png b/doc/development/ux_guide/img/illustration-size-large-horizontal.png
deleted file mode 100644
index 8aa835adccc..00000000000
--- a/doc/development/ux_guide/img/illustration-size-large-horizontal.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/illustration-size-large-vertical.png b/doc/development/ux_guide/img/illustration-size-large-vertical.png
deleted file mode 100644
index 813b6a065e5..00000000000
--- a/doc/development/ux_guide/img/illustration-size-large-vertical.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/illustration-size-medium.png b/doc/development/ux_guide/img/illustration-size-medium.png
deleted file mode 100644
index 55cfe1dcb91..00000000000
--- a/doc/development/ux_guide/img/illustration-size-medium.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/illustration-size-small.png b/doc/development/ux_guide/img/illustration-size-small.png
deleted file mode 100644
index 0124f58f48e..00000000000
--- a/doc/development/ux_guide/img/illustration-size-small.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/illustrations-border-radius.png b/doc/development/ux_guide/img/illustrations-border-radius.png
deleted file mode 100644
index 4e2fef5c7f5..00000000000
--- a/doc/development/ux_guide/img/illustrations-border-radius.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/illustrations-caps-do.png b/doc/development/ux_guide/img/illustrations-caps-do.png
deleted file mode 100644
index f1030769b94..00000000000
--- a/doc/development/ux_guide/img/illustrations-caps-do.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/illustrations-caps-don't.png b/doc/development/ux_guide/img/illustrations-caps-don't.png
deleted file mode 100644
index ab7abcaaf6f..00000000000
--- a/doc/development/ux_guide/img/illustrations-caps-don't.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/illustrations-color-grey.png b/doc/development/ux_guide/img/illustrations-color-grey.png
deleted file mode 100644
index 63855026c2b..00000000000
--- a/doc/development/ux_guide/img/illustrations-color-grey.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/illustrations-color-orange.png b/doc/development/ux_guide/img/illustrations-color-orange.png
deleted file mode 100644
index 96765c8c28c..00000000000
--- a/doc/development/ux_guide/img/illustrations-color-orange.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/illustrations-color-purple.png b/doc/development/ux_guide/img/illustrations-color-purple.png
deleted file mode 100644
index 745d2c853ba..00000000000
--- a/doc/development/ux_guide/img/illustrations-color-purple.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/illustrations-geometric.png b/doc/development/ux_guide/img/illustrations-geometric.png
deleted file mode 100644
index 33f05547bac..00000000000
--- a/doc/development/ux_guide/img/illustrations-geometric.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/illustrations-palette-oragne.png b/doc/development/ux_guide/img/illustrations-palette-oragne.png
deleted file mode 100644
index 15f35912646..00000000000
--- a/doc/development/ux_guide/img/illustrations-palette-oragne.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/illustrations-palette-purple.png b/doc/development/ux_guide/img/illustrations-palette-purple.png
deleted file mode 100644
index e0f5839705e..00000000000
--- a/doc/development/ux_guide/img/illustrations-palette-purple.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/james-mackey.png b/doc/development/ux_guide/img/james-mackey.png
deleted file mode 100644
index f51a45c437b..00000000000
--- a/doc/development/ux_guide/img/james-mackey.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/karolina-plaskaty.png b/doc/development/ux_guide/img/karolina-plaskaty.png
deleted file mode 100644
index d1c9528dd5a..00000000000
--- a/doc/development/ux_guide/img/karolina-plaskaty.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/matthieu-poirier.png b/doc/development/ux_guide/img/matthieu-poirier.png
deleted file mode 100644
index 0ecc2d670d6..00000000000
--- a/doc/development/ux_guide/img/matthieu-poirier.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/modals-general-confimation-dialog.png b/doc/development/ux_guide/img/modals-general-confimation-dialog.png
deleted file mode 100644
index 4ea0ea10ca7..00000000000
--- a/doc/development/ux_guide/img/modals-general-confimation-dialog.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/modals-layout-for-modals.png b/doc/development/ux_guide/img/modals-layout-for-modals.png
deleted file mode 100644
index c481edd8250..00000000000
--- a/doc/development/ux_guide/img/modals-layout-for-modals.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/modals-special-confimation-dialog.png b/doc/development/ux_guide/img/modals-special-confimation-dialog.png
deleted file mode 100644
index d966010158b..00000000000
--- a/doc/development/ux_guide/img/modals-special-confimation-dialog.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/modals-three-buttons.png b/doc/development/ux_guide/img/modals-three-buttons.png
deleted file mode 100644
index 157d1b650bf..00000000000
--- a/doc/development/ux_guide/img/modals-three-buttons.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/monospacefont-sample.png b/doc/development/ux_guide/img/monospacefont-sample.png
deleted file mode 100644
index 1cd290b713c..00000000000
--- a/doc/development/ux_guide/img/monospacefont-sample.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/nazim-ramesh.png b/doc/development/ux_guide/img/nazim-ramesh.png
deleted file mode 100644
index dad2b37010b..00000000000
--- a/doc/development/ux_guide/img/nazim-ramesh.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/popover-placement-above.png b/doc/development/ux_guide/img/popover-placement-above.png
deleted file mode 100644
index 84c9c878ec2..00000000000
--- a/doc/development/ux_guide/img/popover-placement-above.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/popover-placement-below.png b/doc/development/ux_guide/img/popover-placement-below.png
deleted file mode 100644
index f6f18199ab6..00000000000
--- a/doc/development/ux_guide/img/popover-placement-below.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/skeleton-loading.gif b/doc/development/ux_guide/img/skeleton-loading.gif
deleted file mode 100644
index 5877139171d..00000000000
--- a/doc/development/ux_guide/img/skeleton-loading.gif
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/sourcesanspro-sample.png b/doc/development/ux_guide/img/sourcesanspro-sample.png
deleted file mode 100644
index f7ecf0c7c66..00000000000
--- a/doc/development/ux_guide/img/sourcesanspro-sample.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/steven-lyons.png b/doc/development/ux_guide/img/steven-lyons.png
deleted file mode 100644
index 2efe1d0b168..00000000000
--- a/doc/development/ux_guide/img/steven-lyons.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/surfaces-contentitemtitle.png b/doc/development/ux_guide/img/surfaces-contentitemtitle.png
deleted file mode 100644
index f6cd212ecfd..00000000000
--- a/doc/development/ux_guide/img/surfaces-contentitemtitle.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/surfaces-header.png b/doc/development/ux_guide/img/surfaces-header.png
deleted file mode 100644
index ba616388003..00000000000
--- a/doc/development/ux_guide/img/surfaces-header.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/surfaces-systeminformationblock.png b/doc/development/ux_guide/img/surfaces-systeminformationblock.png
deleted file mode 100644
index f3313add2b8..00000000000
--- a/doc/development/ux_guide/img/surfaces-systeminformationblock.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/surfaces-ux.png b/doc/development/ux_guide/img/surfaces-ux.png
deleted file mode 100644
index eaa7f70c0c7..00000000000
--- a/doc/development/ux_guide/img/surfaces-ux.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/tooltip-placement.png b/doc/development/ux_guide/img/tooltip-placement.png
deleted file mode 100644
index da49c192878..00000000000
--- a/doc/development/ux_guide/img/tooltip-placement.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/ux_guide/img/tooltip-usage.png b/doc/development/ux_guide/img/tooltip-usage.png
deleted file mode 100644
index 4f5884c4b48..00000000000
--- a/doc/development/ux_guide/img/tooltip-usage.png
+++ /dev/null
Binary files differ
diff --git a/doc/getting-started/subscription.md b/doc/getting-started/subscription.md
new file mode 100644
index 00000000000..65999183d4a
--- /dev/null
+++ b/doc/getting-started/subscription.md
@@ -0,0 +1,3 @@
+---
+redirect_to: '../subscriptions/index.md'
+--- \ No newline at end of file
diff --git a/doc/git_hooks/git_hooks.md b/doc/git_hooks/git_hooks.md
new file mode 100644
index 00000000000..b251e58410a
--- /dev/null
+++ b/doc/git_hooks/git_hooks.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../push_rules/push_rules.md'
+---
+
+This document was moved to [another location](../push_rules/push_rules.md)
diff --git a/doc/gitlab-basics/README.md b/doc/gitlab-basics/README.md
index 4e15f7cfd49..0c268eff9f1 100644
--- a/doc/gitlab-basics/README.md
+++ b/doc/gitlab-basics/README.md
@@ -2,18 +2,37 @@
comments: false
---
-# GitLab basics
-
-Step-by-step guides on the basics of working with Git and GitLab.
-
-- [Command line basics](command-line-commands.md)
-- [Start using Git on the command line](start-using-git.md)
-- [Create and add your SSH Keys](create-your-ssh-keys.md)
-- [Create a project](create-project.md)
-- [Create a group](../user/group/index.md#create-a-new-group)
-- [Create a branch](create-branch.md)
-- [Fork a project](fork-project.md)
-- [Add a file](add-file.md)
-- [Add an image](add-image.md)
-- [Create an issue](../user/project/issues/create_new_issue.md)
-- [Create a merge request](add-merge-request.md)
+# GitLab basics guides
+
+This section provides resources to help you start with GitLab by focusing on basic functionality.
+
+This documentation is split into the following groups:
+
+- [GitLab-specific functionality](#gitlab-basics), for basic GitLab features.
+- [General Git functionality](#git-basics), for working with Git in conjunction with GitLab.
+
+## GitLab basics
+
+The following are guides to basic GitLab functionality:
+
+- [Create and add your SSH public key](create-your-ssh-keys.md), for enabling Git over SSH.
+- [Create a project](create-project.md), to start using GitLab.
+- [Create a group](../user/group/index.md#create-a-new-group), to combine and administer projects together.
+- [Create a branch](create-branch.md), to make changes to files stored in a project's repository.
+- [Fork a project](fork-project.md), to duplicate projects so they can be worked on in parallel.
+- [Add a file](add-file.md), to add new files to a project's repository.
+- [Add an image](add-image.md), to add new images to a project's repository.
+- [Create an issue](../user/project/issues/create_new_issue.md), to start collaborating within a project.
+- [Create a merge request](add-merge-request.md), to request changes made in a branch be merged into a project's repository.
+- See how these features come together in the [GitLab Flow introduction video](https://youtu.be/InKNIvky2KE) and [GitLab Flow page](../workflow/gitlab_flow.md).
+
+## Git basics
+
+If you're familiar with Git on the command line, you can interact with your GitLab projects just as you would with any other Git repository.
+
+These resources will help get further acclimated to working on the command line.
+
+- [Start using Git on the command line](start-using-git.md), for some simple Git commands.
+- [Command line basics](command-line-commands.md), to create and edit files using the command line.
+
+More Git resources are available at GitLab's [Git documentation](../topics/git/index.md).
diff --git a/doc/gitlab-basics/command-line-commands.md b/doc/gitlab-basics/command-line-commands.md
index a0111be0767..1cf883679d7 100644
--- a/doc/gitlab-basics/command-line-commands.md
+++ b/doc/gitlab-basics/command-line-commands.md
@@ -13,10 +13,12 @@ button (you'll have to paste it on your shell in the next step).
![Copy the HTTPS or SSH](img/project_clone_url.png)
-## On the command line
+## Working with project files on the command line
This section has examples of some basic shell commands that you might find useful. For more information, search the web for _bash commands_.
+Alternatively, you can edit files using your choice of editor (IDE) or the GitLab user interface.
+
### Clone your project
Go to your computer's shell and type the following command with your SSH or HTTPS URL:
diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md
index 3e99496d531..a9ae4fb23f9 100644
--- a/doc/gitlab-basics/create-project.md
+++ b/doc/gitlab-basics/create-project.md
@@ -16,6 +16,7 @@ To create a project in GitLab:
- [Import a project](../user/project/import/index.md) from a different repository,
if enabled on your GitLab instance. Contact your GitLab admin if this
is unavailable.
+ - Run [CI/CD pipelines for external repositories](../ci/ci_cd_for_external_repos/index.md). **[PREMIUM]**
## Blank projects
@@ -57,7 +58,7 @@ Built-in templates are project templates that are:
To use a built-in template on the **New project** page:
-1. On the **Create from template** tab.
+1. On the **Create from template** tab, select the **Built-in** tab.
1. From the list of available built-in templates, click the:
- **Preview** button to look at the template source itself.
- **Use template** button to start creating the project.
diff --git a/doc/gitlab-basics/create-your-ssh-keys.md b/doc/gitlab-basics/create-your-ssh-keys.md
index 8fecdc6948e..aac73d4c9c5 100644
--- a/doc/gitlab-basics/create-your-ssh-keys.md
+++ b/doc/gitlab-basics/create-your-ssh-keys.md
@@ -1,22 +1,22 @@
-# How to create your SSH keys
+# Create and add your SSH public key
-This topic describes how to create SSH keys. You do this to use Git over SSH instead of Git over HTTP.
+This topic describes how to:
-## Creating your SSH keys
+- Create an SSH key pair to use with GitLab.
+- Add the SSH public key to your GitLab account.
-1. Go to your [command line](start-using-git.md) and follow the [instructions](../ssh/README.md) to generate your SSH key pair.
-1. Log in to GitLab.
-1. In the upper-right corner, click your avatar and select **Settings**.
-1. On the **User Settings** menu, select **SSH keys**.
-1. Paste the **public** key generated in the first step in the **Key**
- text field.
-1. Optionally, give it a descriptive title so that you can recognize it in the
- event you add multiple keys.
-1. Finally, click the **Add key** button to add it to GitLab. You will be able to see
- its fingerprint, title, and creation date.
+You do this to use [Git over SSH instead of Git over HTTP](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols).
- ![SSH key single page](img/profile_settings_ssh_keys_single_key.png)
+## Creating your SSH key pair
+
+1. Go to your [command line](start-using-git.md).
+1. Follow the [instructions](../ssh/README.md#generating-a-new-ssh-key-pair) to generate your SSH key pair.
+
+## Adding your SSH public key to GitLab
+
+To add the SSH public key to GitLab,
+see [Adding an SSH key to your GitLab account](../ssh/README.md#adding-an-ssh-key-to-your-gitlab-account).
NOTE: **Note:**
Once you add a key, you cannot edit it. If the paste
-didn't work, you need to remove the offending key and re-add it.
+[didn't work](../ssh/README.md#testing-that-everything-is-set-up-correctly), you need to remove the key and re-add it.
diff --git a/doc/gitlab-basics/img/new_issue_button.png b/doc/gitlab-basics/img/new_issue_button.png
deleted file mode 100644
index 3b113471f0c..00000000000
--- a/doc/gitlab-basics/img/new_issue_button.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/img/new_issue_page.png b/doc/gitlab-basics/img/new_issue_page.png
deleted file mode 100644
index ce3e60df276..00000000000
--- a/doc/gitlab-basics/img/new_issue_page.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/img/profile_settings_ssh_keys_single_key.png b/doc/gitlab-basics/img/profile_settings_ssh_keys_single_key.png
deleted file mode 100644
index 8014f1d5301..00000000000
--- a/doc/gitlab-basics/img/profile_settings_ssh_keys_single_key.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/img/public_file_link.png b/doc/gitlab-basics/img/public_file_link.png
deleted file mode 100644
index f60df6807f4..00000000000
--- a/doc/gitlab-basics/img/public_file_link.png
+++ /dev/null
Binary files differ
diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md
index e30afdf8a40..b3c5d32f2f5 100644
--- a/doc/gitlab-basics/start-using-git.md
+++ b/doc/gitlab-basics/start-using-git.md
@@ -71,6 +71,18 @@ git config --global --list
Start using Git via the command line with the most basic
commands as described below.
+## Initialize a local directory for Git version control
+
+If you have an existing local directory that you want to *initialize* for version control, use the `init` command to instruct Git to begin tracking the directory:
+
+```bash
+git init
+```
+
+This creates a `.git` directory that contains the Git configuration files.
+
+Once the directory has been initialized, you can [add a remote repository](#add-a-remote-repository) and [send changes to GitLab.com](#send-changes-to-gitlabcom). View the instructions on [Create a project](../gitlab-basics/create-project.html#push-to-create-a-new-project) to create a new project on GitLab with your changes.
+
### Clone a repository
To start working locally on an existing remote repository,
@@ -140,6 +152,16 @@ To view your remote repositories, type:
git remote -v
```
+### Add a remote repository
+
+To add a link to a remote repository:
+
+```bash
+git remote add SOURCE-NAME REPOSITORY-PATH
+```
+
+You'll use this source name every time you [push changes to GitLab.com](#send-changes-to-gitlabcom), so use something easy to remember and type.
+
### Create a branch
To create a branch, type the following (spaces won't be recognized in the branch name, so you will need to use a hyphen or underscore):
@@ -193,7 +215,7 @@ git commit -m "COMMENT TO DESCRIBE THE INTENTION OF THE COMMIT"
NOTE: **Note:**
The `.` character typically means _all_ in Git.
-### Send changes to gitlab.com
+### Send changes to GitLab.com
To push all local commits to the remote repository:
diff --git a/doc/gitlab-geo/README.md b/doc/gitlab-geo/README.md
new file mode 100644
index 00000000000..30d21db7de5
--- /dev/null
+++ b/doc/gitlab-geo/README.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/geo/replication/index.md'
+---
+
+This document was moved to [another location](../administration/geo/replication/index.md).
diff --git a/doc/gitlab-geo/after_setup.md b/doc/gitlab-geo/after_setup.md
new file mode 100644
index 00000000000..c8a7b9d1096
--- /dev/null
+++ b/doc/gitlab-geo/after_setup.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/geo/replication/using_a_geo_server.md'
+---
+
+This document was moved to [another location](../administration/geo/replication/using_a_geo_server.md).
diff --git a/doc/gitlab-geo/bring-primary-back.md b/doc/gitlab-geo/bring-primary-back.md
new file mode 100644
index 00000000000..8c43f4d805f
--- /dev/null
+++ b/doc/gitlab-geo/bring-primary-back.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/geo/disaster_recovery/bring_primary_back.md'
+---
+
+This document was moved to [another location](../administration/geo/disaster_recovery/bring_primary_back.md).
diff --git a/doc/gitlab-geo/configuration.md b/doc/gitlab-geo/configuration.md
new file mode 100644
index 00000000000..b46a2caea4a
--- /dev/null
+++ b/doc/gitlab-geo/configuration.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/geo/replication/configuration.md'
+---
+
+This document was moved to [another location](../administration/geo/replication/configuration.md).
diff --git a/doc/gitlab-geo/configuration_source.md b/doc/gitlab-geo/configuration_source.md
new file mode 100644
index 00000000000..b46a2caea4a
--- /dev/null
+++ b/doc/gitlab-geo/configuration_source.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/geo/replication/configuration.md'
+---
+
+This document was moved to [another location](../administration/geo/replication/configuration.md).
diff --git a/doc/gitlab-geo/database.md b/doc/gitlab-geo/database.md
new file mode 100644
index 00000000000..b4156dc4ec6
--- /dev/null
+++ b/doc/gitlab-geo/database.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/geo/replication/database.md'
+---
+
+This document was moved to [another location](../administration/geo/replication/database.md).
diff --git a/doc/gitlab-geo/database_source.md b/doc/gitlab-geo/database_source.md
new file mode 100644
index 00000000000..b4156dc4ec6
--- /dev/null
+++ b/doc/gitlab-geo/database_source.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/geo/replication/database.md'
+---
+
+This document was moved to [another location](../administration/geo/replication/database.md).
diff --git a/doc/gitlab-geo/disaster-recovery.md b/doc/gitlab-geo/disaster-recovery.md
new file mode 100644
index 00000000000..d42e815a879
--- /dev/null
+++ b/doc/gitlab-geo/disaster-recovery.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/geo/disaster_recovery/index.md'
+---
+
+This document was moved to [another location](../administration/geo/disaster_recovery/index.md).
diff --git a/doc/gitlab-geo/docker_registry.md b/doc/gitlab-geo/docker_registry.md
new file mode 100644
index 00000000000..26a708f6845
--- /dev/null
+++ b/doc/gitlab-geo/docker_registry.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/geo/replication/docker_registry.md'
+---
+
+This document was moved to [another location](../administration/geo/replication/docker_registry.md).
diff --git a/doc/gitlab-geo/faq.md b/doc/gitlab-geo/faq.md
new file mode 100644
index 00000000000..f1952bc7e4c
--- /dev/null
+++ b/doc/gitlab-geo/faq.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/geo/replication/faq.md'
+---
+
+This document was moved to [another location](../administration/geo/replication/faq.md).
diff --git a/doc/gitlab-geo/ha.md b/doc/gitlab-geo/ha.md
new file mode 100644
index 00000000000..23ed11eaf09
--- /dev/null
+++ b/doc/gitlab-geo/ha.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/geo/replication/high_availability.md'
+---
+
+This document was moved to [another location](../administration/geo/replication/high_availability.md).
diff --git a/doc/gitlab-geo/object_storage.md b/doc/gitlab-geo/object_storage.md
new file mode 100644
index 00000000000..1f29b7b7e8c
--- /dev/null
+++ b/doc/gitlab-geo/object_storage.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/geo/replication/object_storage.md'
+---
+
+This document was moved to [another location](../administration/geo/replication/object_storage.md).
diff --git a/doc/gitlab-geo/planned-failover.md b/doc/gitlab-geo/planned-failover.md
new file mode 100644
index 00000000000..720b6bc9424
--- /dev/null
+++ b/doc/gitlab-geo/planned-failover.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/geo/disaster_recovery/planned_failover.md'
+---
+
+This document was moved to [another location](../administration/geo/disaster_recovery/planned_failover.md).
diff --git a/doc/gitlab-geo/security-review.md b/doc/gitlab-geo/security-review.md
new file mode 100644
index 00000000000..a0a5b0e536c
--- /dev/null
+++ b/doc/gitlab-geo/security-review.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/geo/replication/security_review.md'
+---
+
+This document was moved to [another location](../administration/geo/replication/security_review.md).
diff --git a/doc/gitlab-geo/ssh.md b/doc/gitlab-geo/ssh.md
new file mode 100644
index 00000000000..4f8db687850
--- /dev/null
+++ b/doc/gitlab-geo/ssh.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/operations/fast_ssh_key_lookup.md'
+---
+
+This document was moved to [another location](../administration/operations/fast_ssh_key_lookup.md).
diff --git a/doc/gitlab-geo/troubleshooting.md b/doc/gitlab-geo/troubleshooting.md
new file mode 100644
index 00000000000..25fe1372c69
--- /dev/null
+++ b/doc/gitlab-geo/troubleshooting.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/geo/replication/troubleshooting.md'
+---
+
+This document was moved to [another location](../administration/geo/replication/troubleshooting.md).
diff --git a/doc/gitlab-geo/tuning.md b/doc/gitlab-geo/tuning.md
new file mode 100644
index 00000000000..84ac40f99db
--- /dev/null
+++ b/doc/gitlab-geo/tuning.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/geo/replication/tuning.md'
+---
+
+This document was moved to [another location](../administration/geo/replication/tuning.md).
diff --git a/doc/gitlab-geo/updating_the_geo_nodes.md b/doc/gitlab-geo/updating_the_geo_nodes.md
new file mode 100644
index 00000000000..28234ec02ed
--- /dev/null
+++ b/doc/gitlab-geo/updating_the_geo_nodes.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/geo/replication/updating_the_geo_nodes.md'
+---
+
+This document was moved to [another location](../administration/geo/replication/updating_the_geo_nodes.md).
diff --git a/doc/gitlab-geo/using_a_geo_server.md b/doc/gitlab-geo/using_a_geo_server.md
new file mode 100644
index 00000000000..c8a7b9d1096
--- /dev/null
+++ b/doc/gitlab-geo/using_a_geo_server.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/geo/replication/using_a_geo_server.md'
+---
+
+This document was moved to [another location](../administration/geo/replication/using_a_geo_server.md).
diff --git a/doc/install/README.md b/doc/install/README.md
index 53778f7f0d3..9cc21412898 100644
--- a/doc/install/README.md
+++ b/doc/install/README.md
@@ -1,6 +1,7 @@
---
comments: false
description: Read through the GitLab installation methods.
+type: index
---
# Installation **[CORE ONLY]**
@@ -81,7 +82,7 @@ the above methods, provided the cloud provider supports it.
- [Install on AWS](aws/index.md): Install Omnibus GitLab on AWS using the community AMIs that GitLab provides.
- [Install GitLab on Google Cloud Platform](google_cloud_platform/index.md): Install Omnibus GitLab on a VM in GCP.
- [Install GitLab on Azure](azure/index.md): Install Omnibus GitLab from Azure Marketplace.
-- [Install GitLab on OpenShift](openshift_and_gitlab/index.md): Install GitLab using the Docker image on OpenShift.
+- [Install GitLab on OpenShift](https://docs.gitlab.com/charts/installation/cloud/openshift.html): Install GitLab on OpenShift by using GitLab's Helm charts.
- [Install GitLab on DC/OS](https://mesosphere.com/blog/gitlab-dcos/): Install GitLab on Mesosphere DC/OS via the [GitLab-Mesosphere integration](https://about.gitlab.com/2016/09/16/announcing-gitlab-and-mesosphere/).
- [Install GitLab on DigitalOcean](https://about.gitlab.com/2016/04/27/getting-started-with-gitlab-and-digitalocean/): Install Omnibus GitLab on DigitalOcean.
- _Testing only!_ [DigitalOcean and Docker Machine](digitaloceandocker.md):
diff --git a/doc/install/aws/img/add_tags.png b/doc/install/aws/img/add_tags.png
deleted file mode 100644
index 3572cd5daa1..00000000000
--- a/doc/install/aws/img/add_tags.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/aws/img/create_route_table.png b/doc/install/aws/img/create_route_table.png
deleted file mode 100644
index ea72c57257e..00000000000
--- a/doc/install/aws/img/create_route_table.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/aws/index.md b/doc/install/aws/index.md
index 0000e03f1d7..73eaf758923 100644
--- a/doc/install/aws/index.md
+++ b/doc/install/aws/index.md
@@ -1,3 +1,7 @@
+---
+type: howto
+---
+
# Installing GitLab HA on Amazon Web Services (AWS)
This page offers a walkthrough of a common HA (Highly Available) configuration
@@ -383,7 +387,7 @@ after the instance is created.
CAUTION: **Caution:**
We **do not** recommend using the AWS Elastic File System (EFS), as it can result
-in [significantly degraded performance](../../administration/high_availability/nfs.html#avoid-using-awss-elastic-file-system-efs).
+in [significantly degraded performance](../../administration/high_availability/nfs.md#avoid-using-awss-elastic-file-system-efs).
### Configure security group
@@ -649,12 +653,24 @@ Have a read through these other resources and feel free to
[open an issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/new)
to request additional material:
-- [GitLab High Availability](https://docs.gitlab.com/ee/administration/high_availability/):
+- [GitLab High Availability](../../administration/high_availability/README.md):
GitLab supports several different types of clustering and high-availability.
-- [Geo replication](https://docs.gitlab.com/ee/administration/geo/replication/):
+- [Geo replication](../../administration/geo/replication/index.md):
Geo is the solution for widely distributed development teams.
- [Omnibus GitLab](https://docs.gitlab.com/omnibus/) - Everything you need to know
about administering your GitLab instance.
-- [Upload a license](https://docs.gitlab.com/ee/user/admin_area/license.html):
+- [Upload a license](../../user/admin_area/license.md):
Activate all GitLab Enterprise Edition functionality with a license.
- [Pricing](https://about.gitlab.com/pricing): Pricing for the different tiers.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/install/azure/img/azure-vm-management-settings-network-interfaces.png b/doc/install/azure/img/azure-vm-management-settings-network-interfaces.png
deleted file mode 100644
index 4ff10718059..00000000000
--- a/doc/install/azure/img/azure-vm-management-settings-network-interfaces.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-vm-management.png b/doc/install/azure/img/azure-vm-management.png
deleted file mode 100644
index a0e0067258c..00000000000
--- a/doc/install/azure/img/azure-vm-management.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/index.md b/doc/install/azure/index.md
index fa5be1d30f9..b1f79893baf 100644
--- a/doc/install/azure/index.md
+++ b/doc/install/azure/index.md
@@ -1,14 +1,10 @@
---
-description: 'Learn how to spin up a
-pre-configured GitLab VM on Microsoft Azure and have your very own private GitLab instance up and running in around 30 minutes.'
+description: 'Learn how to spin up a pre-configured GitLab VM on Microsoft Azure.'
+type: howto
---
# Install GitLab on Microsoft Azure
-> _This article was originally written by Dave Wentzel and [published on the GitLab Blog][Original-Blog-Post]._
->
-> _Ported to the GitLab documentation and updated on 2017-08-24 by [Ian Scorer](https://gitlab.com/iscorer)._
-
Azure is Microsoft's business cloud and GitLab is a pre-configured offering on the Azure Marketplace.
Hopefully, you aren't surprised to hear that Microsoft and Azure have embraced open source software
like Ubuntu, Red Hat Enterprise Linux, and of course - GitLab! This means that you can spin up a
@@ -444,3 +440,15 @@ Check out our other [Technical Articles][GitLab-Technical-Articles] or browse th
[SSH]: https://en.wikipedia.org/wiki/Secure_Shell
[PuTTY]: http://www.putty.org/
[Using-SSH-In-Putty]: https://mediatemple.net/community/products/dv/204404604/using-ssh-in-putty-
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/install/database_mysql.md b/doc/install/database_mysql.md
index e89846107b6..cbb3b766b4e 100644
--- a/doc/install/database_mysql.md
+++ b/doc/install/database_mysql.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# Database MySQL
NOTE: **Note:**
@@ -301,3 +305,15 @@ Details can be found in the [PostgreSQL][postgres-text-type] and
[postgres-text-type]: http://www.postgresql.org/docs/9.2/static/datatype-character.html
[ce-38152]: https://gitlab.com/gitlab-org/gitlab-ce/issues/38152
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/install/digitaloceandocker.md b/doc/install/digitaloceandocker.md
index d67695d75b4..63bb941ad47 100644
--- a/doc/install/digitaloceandocker.md
+++ b/doc/install/digitaloceandocker.md
@@ -1,8 +1,11 @@
+---
+type: howto
+---
+
# Digital Ocean and Docker Machine test environment
-CAUTION: **Caution:**
-This guide is for quickly testing different versions of GitLab and not recommended for ease of
-future upgrades or keeping the data you create.
+This guide is for quickly testing different versions of GitLab and not
+recommended for ease of future upgrades or keeping the data you create.
## Initial setup
@@ -28,7 +31,7 @@ locally on either macOS or Linux.
NOTE: **Note:**
The rest of the steps are identical for macOS and Linux.
-### Create new docker host
+## Create new docker host
1. Login to Digital Ocean.
1. Generate a new API token at <https://cloud.digitalocean.com/settings/api/tokens>.
@@ -60,9 +63,9 @@ The rest of the steps are identical for macOS and Linux.
Resource: <https://docs.docker.com/machine/drivers/digital-ocean/>.
-### Creating GitLab test instance
+## Creating GitLab test instance
-#### Connect your shell to the new machine
+### Connect your shell to the new machine
In this example we'll create a GitLab EE 8.10.8 instance.
@@ -74,7 +77,7 @@ eval "$(docker-machine env gitlab-test-env-do)"
You can add this to your `~/.bash_profile` file to ensure the `docker` client uses the `gitlab-test-env-do` docker host
-#### Create new GitLab container
+### Create new GitLab container
- HTTP port: `8888`
- SSH port: `2222`
@@ -83,7 +86,7 @@ You can add this to your `~/.bash_profile` file to ensure the `docker` client us
- Container name: `gitlab-test-8.10`
- GitLab version: **EE** `8.10.8-ee.0`
-##### Set up container settings
+#### Set up container settings
```sh
export SSH_PORT=2222
@@ -92,7 +95,7 @@ export VERSION=8.10.8-ee.0
export NAME=gitlab-test-8.10
```
-##### Create container
+#### Create container
```sh
docker run --detach \
@@ -103,9 +106,9 @@ docker run --detach \
gitlab/gitlab-ee:$VERSION
```
-#### Connect to the GitLab container
+### Connect to the GitLab container
-##### Retrieve the docker host IP
+#### Retrieve the docker host IP
```sh
docker-machine ip gitlab-test-env-do
@@ -114,7 +117,7 @@ docker-machine ip gitlab-test-env-do
Browse to: <http://192.168.151.134:8888/>.
-##### Execute interactive shell/edit configuration
+#### Execute interactive shell/edit configuration
```sh
docker exec -it $NAME /bin/bash
@@ -126,8 +129,20 @@ root@192:/# vi /etc/gitlab/gitlab.rb
root@192:/# gitlab-ctl reconfigure
```
-#### Resources
+### Resources
- <https://docs.gitlab.com/omnibus/docker/>.
- <https://docs.docker.com/machine/get-started/>.
- <https://docs.docker.com/machine/reference/ip/>.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/install/docker.md b/doc/install/docker.md
index 4568a949b0a..06da65189ba 100644
--- a/doc/install/docker.md
+++ b/doc/install/docker.md
@@ -1,3 +1,7 @@
+---
+type: index
+---
+
# Install GitLab with Docker
[Docker](https://www.docker.com) and container technology have been revolutionizing the software world for the past few years. They combine the performance and efficiency of native execution with the abstraction, security, and immutability of virtualization.
@@ -16,4 +20,4 @@ A [complete usage guide](https://docs.gitlab.com/omnibus/docker/) to these image
## Cloud native images
-GitLab is also working towards a [cloud native set of containers](https://gitlab.com/charts/helm.gitlab.io#docker-container-images), with a single image for each component service. We intend for these images to eventually replace the [Omnibus GitLab based images](#omnibus-gitlab-based-images).
+GitLab is also working towards a [cloud native set of containers](https://docs.gitlab.com/charts/), with a single image for each component service. We intend for these images to eventually replace the [Omnibus GitLab based images](#omnibus-gitlab-based-images).
diff --git a/doc/install/google-protobuf.md b/doc/install/google-protobuf.md
index a531b4519b3..434817c48cb 100644
--- a/doc/install/google-protobuf.md
+++ b/doc/install/google-protobuf.md
@@ -1,26 +1,5 @@
-# Installing a locally compiled google-protobuf gem
+---
+redirect_to: 'installation.md#google-protobuf-loaderror-libx86_64-linux-gnulibcso6-version-glibc_214-not-found'
+---
-First we must find the exact version of google-protobuf that your
-GitLab installation requires.
-
- cd /home/git/gitlab
-
- # Only one of the following two commands will print something. It
- # will look like: * google-protobuf (3.2.0)
- bundle list | grep google-protobuf
- bundle check | grep google-protobuf
-
-Below we use `3.2.0` as an example. Replace it with the version number
-you found above.
-
- cd /home/git/gitlab
- sudo -u git -H gem install google-protobuf --version 3.2.0 --platform ruby
-
-Finally, you can test whether google-protobuf loads correctly. The
-following should print 'OK'.
-
- sudo -u git -H bundle exec ruby -rgoogle/protobuf -e 'puts :OK'
-
-If the `gem install` command fails you may need to install developer
-tools. On Debian: `apt-get install build-essential libgmp-dev`, on
-Centos/RedHat `yum groupinstall 'Development Tools'`.
+This document was moved to [another location](installation.md#google-protobuf-loaderror-libx86_64-linux-gnulibcso6-version-glibc_214-not-found).
diff --git a/doc/install/google_cloud_platform/img/gcp_landing.png b/doc/install/google_cloud_platform/img/gcp_landing.png
deleted file mode 100644
index 92a9873728c..00000000000
--- a/doc/install/google_cloud_platform/img/gcp_landing.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/google_cloud_platform/index.md b/doc/install/google_cloud_platform/index.md
index 242ad70ae82..77c61acbfd4 100644
--- a/doc/install/google_cloud_platform/index.md
+++ b/doc/install/google_cloud_platform/index.md
@@ -1,14 +1,13 @@
---
description: 'Learn how to install a GitLab instance on Google Cloud Platform.'
+type: howto
---
# Installing GitLab on Google Cloud Platform
-![GCP landing page](img/gcp_landing.png)
+This guide will help you install GitLab on a [Google Cloud Platform (GCP)][gcp] instance.
-Getting started with GitLab on a [Google Cloud Platform (GCP)][gcp] instance is quick and easy.
-
-NOTE: **Note:**
+NOTE: **Alternative installation method:**
Google provides a whitepaper for [deploying production-ready GitLab on
Google Kubernetes Engine](https://cloud.google.com/solutions/deploying-production-ready-gitlab-on-gke),
including all steps and external resource configuration. These are an alternative to using a GCP VM, and use
@@ -26,10 +25,9 @@ Once you have performed those two steps, you can [create a VM](#creating-the-vm)
## Creating the VM
-To deploy GitLab on GCP you need to follow five simple steps:
-
-1. Go to <https://console.cloud.google.com/compute/instances> and login with your Google credentials.
+To deploy GitLab on GCP you first need to create a virtual machine:
+1. Go to <https://console.cloud.google.com/compute/instances> and log in with your Google credentials.
1. Click on **Create**
![Search for GitLab](img/launch_vm.png)
@@ -142,3 +140,15 @@ Kerberos, etc. Here are some documents you might be interested in reading:
[ssh]: https://cloud.google.com/compute/docs/instances/connecting-to-instance "Connecting to Linux Instances"
[omni-smtp]: https://docs.gitlab.com/omnibus/settings/smtp.html#smtp-settings "Omnibus GitLab SMTP settings"
[omni-ssl]: https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https "Omnibus GitLab enable HTTPS"
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 61f544deabe..eb484dde545 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -1,5 +1,28 @@
+---
+type: howto
+---
+
# Installation from source
+This is the official installation guide to set up a production GitLab server
+using the source files. To set up a **development installation** or for many
+other installation options, see the [main installation page](index.md).
+It was created for and tested on **Debian/Ubuntu** operating systems.
+Read [requirements.md](requirements.md) for hardware and operating system requirements.
+If you want to install on RHEL/CentOS, we recommend using the
+[Omnibus packages](https://about.gitlab.com/downloads/).
+
+This guide is long because it covers many cases and includes all commands you
+need, this is [one of the few installation scripts that actually works out of the box](https://twitter.com/robinvdvleuten/status/424163226532986880).
+The following steps have been known to work. **Use caution when you deviate**
+from this guide. Make sure you don't violate any assumptions GitLab makes about
+its environment. For example, many people run into permission problems because
+they changed the location of directories or run services as the wrong user.
+
+If you find a bug/error in this guide, **submit a merge request**
+following the
+[contributing guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md).
+
## Consider the Omnibus package installation
Since an installation from source is a lot of work and error prone we strongly recommend the fast and reliable [Omnibus package installation](https://about.gitlab.com/downloads/) (deb/rpm).
@@ -12,26 +35,42 @@ After this termination Runit will detect Sidekiq is not running and will start i
Since installations from source don't use Runit for process supervision, Sidekiq
can't be terminated and its memory usage will grow over time.
-## Select Version to Install
+## Select version to install
Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md) from the branch (version) of GitLab you would like to install (e.g., `11-7-stable`).
You can select the branch in the version dropdown in the top left corner of GitLab (below the menu bar).
If the highest number stable branch is unclear, check the [GitLab blog](https://about.gitlab.com/blog/) for installation guide links by version.
-## Important Notes
+## GitLab directory structure
-This guide is long because it covers many cases and includes all commands you need, this is [one of the few installation scripts that actually works out of the box](https://twitter.com/robinvdvleuten/status/424163226532986880).
+This is the main directory structure you will end up with following the instructions
+of this page:
-This installation guide was created for and tested on **Debian/Ubuntu** operating systems. Read [requirements.md](requirements.md) for hardware and operating system requirements. If you want to install on RHEL/CentOS, we recommend using the [Omnibus packages](https://about.gitlab.com/downloads/).
+```
+|-- home
+| |-- git
+| |-- .ssh
+| |-- gitlab
+| |-- gitlab-shell
+| |-- repositories
+```
-This is the official installation guide to set up a production server. To set up a **development installation** or for many other installation options, see [the installation section of the README](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/README.md#installation).
+- `/home/git/.ssh` - Contains OpenSSH settings. Specifically the `authorized_keys`
+ file managed by gitlab-shell.
+- `/home/git/gitlab` - GitLab core software.
+- `/home/git/gitlab-shell` - Core add-on component of GitLab. Maintains SSH
+ cloning and other functionality.
+- `/home/git/repositories` - Bare repositories for all projects organized by
+ namespace. This is where the git repositories which are pushed/pulled are
+ maintained for all projects. **This area contains critical data for projects.
+ [Keep a backup](../raketasks/backup_restore.md).**
-The following steps have been known to work. **Use caution when you deviate** from this guide. Make sure you don't violate any assumptions GitLab makes about its environment. For example, many people run into permission problems because they changed the location of directories or run services as the wrong user.
+NOTE: **Note:**
+The default locations for repositories can be configured in `config/gitlab.yml`
+of GitLab and `config.yml` of gitlab-shell.
-If you find a bug/error in this guide, **submit a merge request**
-following the
-[contributing guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md).
+For a more in-depth overview, see the [GitLab architecture doc](../development/architecture.md).
## Overview
@@ -95,11 +134,24 @@ Make sure you have the right version of Git installed:
# Install Git
sudo apt-get install -y git-core
-# Make sure Git is version 2.18.0 or higher
+# Make sure Git is version 2.21.0 or higher
git --version
```
-Is the system packaged Git too old? Remove it and compile from source.
+Starting with GitLab 12.0, Git is required to be compiled with `libpcre2`.
+Find out if that's the case:
+
+```sh
+ldd /usr/local/bin/git | grep pcre2
+```
+
+The output should be similar to:
+
+```
+libpcre2-8.so.0 => /usr/lib/libpcre2-8.so.0 (0x00007f08461c3000)
+```
+
+Is the system packaged Git too old, or not compiled with pcre2? Remove it and compile from source:
```sh
# Remove packaged Git
@@ -108,12 +160,21 @@ sudo apt-get remove git-core
# Install dependencies
sudo apt-get install -y libcurl4-openssl-dev libexpat1-dev gettext libz-dev libssl-dev build-essential
+# Download and compile pcre2 from source
+curl --silent --show-error --location https://ftp.pcre.org/pub/pcre/pcre2-10.33.tar.gz --output pcre2.tar.gz
+tar -xzf pcre2.tar.gz
+cd pcre2-10.33
+chmod +x configure
+./configure --prefix=/usr --enable-jit
+make
+make install
+
# Download and compile from source
cd /tmp
-curl --remote-name --location --progress https://www.kernel.org/pub/software/scm/git/git-2.18.0.tar.gz
-echo '94faf2c0b02a7920b0b46f4961d8e9cad08e81418614102898a55f980fa3e7e4 git-2.18.0.tar.gz' | shasum -a256 -c - && tar -xzf git-2.18.0.tar.gz
-cd git-2.18.0/
-./configure
+curl --remote-name --location --progress https://www.kernel.org/pub/software/scm/git/git-2.21.0.tar.gz
+echo '85eca51c7404da75e353eba587f87fea9481ba41e162206a6f70ad8118147bee git-2.21.0.tar.gz' | shasum -a256 -c - && tar -xzf git-2.21.0.tar.gz
+cd git-2.21.0/
+./configure --with-libpcre
make prefix=/usr/local all
# Install into /usr/local/bin
@@ -163,9 +224,9 @@ Download Ruby and compile it:
```sh
mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.3.tar.gz
-echo 'f919a9fbcdb7abecd887157b49833663c5c15fda ruby-2.5.3.tar.gz' | shasum -c - && tar xzf ruby-2.5.3.tar.gz
-cd ruby-2.5.3
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.3.tar.gz
+echo '2347ed6ca5490a104ebd5684d2b9b5eefa6cd33c ruby-2.6.3.tar.gz' | shasum -c - && tar xzf ruby-2.6.3.tar.gz
+cd ruby-2.6.3
./configure --disable-install-rdoc
make
@@ -189,11 +250,11 @@ page](https://golang.org/dl).
# Remove former Go installation folder
sudo rm -rf /usr/local/go
-curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
-echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz
+curl --remote-name --progress https://dl.google.com/go/go1.11.10.linux-amd64.tar.gz
+echo 'aefaa228b68641e266d1f23f1d95dba33f17552ba132878b65bb798ffa37e6d0 go1.11.10.linux-amd64.tar.gz' | shasum -a256 -c - && \
+ sudo tar -C /usr/local -xzf go1.11.10.linux-amd64.tar.gz
sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.10.3.linux-amd64.tar.gz
+rm go1.11.10.linux-amd64.tar.gz
```
## 4. Node
@@ -302,16 +363,14 @@ Redis 2.8 with:
sudo apt-get install redis-server
```
-If you are using Debian 7 or Ubuntu 12.04, follow the special documentation
-on [an alternate Redis installation](redis.md). Once done, follow the rest of
-the guide here.
+Once done, you can configure Redis:
```sh
# Configure redis to use sockets
sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.orig
# Disable Redis listening on TCP by setting 'port' to 0
-sed 's/^port .*/port 0/' /etc/redis/redis.conf.orig | sudo tee /etc/redis/redis.conf
+sudo sed 's/^port .*/port 0/' /etc/redis/redis.conf.orig | sudo tee /etc/redis/redis.conf
# Enable Redis socket for default Debian / Ubuntu path
echo 'unixsocket /var/run/redis/redis.sock' | sudo tee -a /etc/redis/redis.conf
@@ -320,9 +379,9 @@ echo 'unixsocket /var/run/redis/redis.sock' | sudo tee -a /etc/redis/redis.conf
echo 'unixsocketperm 770' | sudo tee -a /etc/redis/redis.conf
# Create the directory which contains the socket
-mkdir /var/run/redis
-chown redis:redis /var/run/redis
-chmod 755 /var/run/redis
+sudo mkdir -p /var/run/redis
+sudo chown redis:redis /var/run/redis
+sudo chmod 755 /var/run/redis
# Persist the directory which contains the socket, if applicable
if [ -d /etc/tmpfiles.d ]; then
@@ -384,7 +443,7 @@ sudo chmod -R u+rwX tmp/pids/
sudo chmod -R u+rwX tmp/sockets/
# Create the public/uploads/ directory
-sudo -u git -H mkdir public/uploads/
+sudo -u git -H mkdir -p public/uploads/
# Make sure only the GitLab user has access to the public/uploads/ directory
# now that files in public/uploads are served by gitlab-workhorse
@@ -434,7 +493,8 @@ sudo -u git -H editor config/resque.yml
```
CAUTION: **Caution:**
-Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup.
+Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup.
+If you want to use Puma web server, see [Using Puma](#using-puma) for the additional steps.
NOTE: **Note:**
If you want to use HTTPS, see [Using HTTPS](#using-https) for the additional steps.
@@ -448,6 +508,18 @@ sudo -u git cp config/database.yml.postgresql config/database.yml
# MySQL only:
sudo -u git cp config/database.yml.mysql config/database.yml
+# PostgreSQL only:
+# Remove host, username, and password lines from config/database.yml.
+# Once modified, the `production` settings will be as follows:
+#
+# production:
+# adapter: postgresql
+# encoding: unicode
+# database: gitlabhq_production
+# pool: 10
+#
+sudo -u git -H editor config/database.yml
+
# MySQL and remote PostgreSQL only:
# Update username/password in config/database.yml.
# You only need to adapt the production settings (first part).
@@ -540,6 +612,7 @@ sudo -u git -H make
```sh
# Fetch Gitaly source with Git and compile with Go
+cd /home/git/gitlab
sudo -u git -H bundle exec rake "gitlab:gitaly:install[/home/git/gitaly,/home/git/repositories]" RAILS_ENV=production
```
@@ -564,9 +637,22 @@ sudo -u git -H editor config.toml
For more information about configuring Gitaly see
[doc/administration/gitaly](../administration/gitaly).
+### Start Gitaly
+
+Gitaly must be running for the next section.
+
+```sh
+gitlab_path=/home/git/gitlab
+gitaly_path=/home/git/gitaly
+
+sudo -u git -H $gitlab_path/bin/daemon_with_pidfile $gitlab_path/tmp/pids/gitaly.pid \
+ $gitaly_path/gitaly $gitaly_path/config.toml >> $gitlab_path/log/gitaly.log 2>&1 &
+```
+
### Initialize Database and Activate Advanced Features
```sh
+cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production
# Type 'yes' to create the database tables.
@@ -577,10 +663,10 @@ sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production force=yes
```
NOTE: **Note:**
-You can set the Administrator/root password and e-mail by supplying them in environmental variables, `GITLAB_ROOT_PASSWORD` and `GITLAB_ROOT_EMAIL` respectively, as seen below. If you don't set the password (and it is set to the default one), wait to expose GitLab to the public internet until the installation is done and you've logged into the server the first time. During the first login, you'll be forced to change the default password.
+You can set the Administrator/root password and e-mail by supplying them in environmental variables, `GITLAB_ROOT_PASSWORD` and `GITLAB_ROOT_EMAIL` respectively, as seen below. If you don't set the password (and it is set to the default one), wait to expose GitLab to the public internet until the installation is done and you've logged into the server the first time. During the first login, you'll be forced to change the default password. An Enterprise Edition license may also be installed at this time by supplying a full path in the `GITLAB_LICENSE_FILE` environment variable.
```sh
-sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production GITLAB_ROOT_PASSWORD=yourpassword GITLAB_ROOT_EMAIL=youremail
+sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production GITLAB_ROOT_PASSWORD=yourpassword GITLAB_ROOT_EMAIL=youremail GITLAB_LICENSE_FILE="/path/to/license"
```
### Secure secrets.yml
@@ -638,6 +724,12 @@ sudo -u git -H yarn install --production --pure-lockfile
sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
```
+If `rake` fails with `JavaScript heap out of memory` error, try to run it with `NODE_OPTIONS` set as follows.
+
+```sh
+sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production NODE_ENV=production NODE_OPTIONS="--max_old_space_size=4096"
+```
+
### Start Your GitLab Instance
```sh
@@ -843,6 +935,25 @@ You also need to change the corresponding options (e.g. `ssh_user`, `ssh_host`,
Apart from the always supported markdown style, there are other rich text files that GitLab can display. But you might have to install a dependency to do so. See the [github-markup gem README](https://github.com/gitlabhq/markup#markups) for more information.
+### Using Puma
+
+Puma is a multi-threaded HTTP 1.1 server for Ruby applications.
+
+To use GitLab with Puma:
+
+1. Finish GitLab setup so you have it up and running.
+1. Copy the supplied example Puma config file into place:
+
+ ```sh
+ cd /home/git/gitlab
+
+ # Copy config file for the web server
+ sudo -u git -H config/puma.rb.example config/puma.rb
+ ```
+
+1. Edit the system `init.d` script to use `EXPERIMENTAL_PUMA=1` flag. If you have `/etc/default/gitlab`, then you should edit it instead.
+1. Restart GitLab.
+
## Troubleshooting
### "You appear to have cloned an empty repository."
@@ -856,8 +967,50 @@ and correctly [configured Nginx](#site-configuration).
### google-protobuf "LoadError: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.14' not found"
This can happen on some platforms for some versions of the
-google-protobuf gem. The workaround is to [install a source-only
-version of this gem](google-protobuf.md).
+`google-protobuf` gem. The workaround is to install a source-only
+version of this gem.
+
+First, you must find the exact version of `google-protobuf` that your
+GitLab installation requires:
+
+```sh
+cd /home/git/gitlab
+
+# Only one of the following two commands will print something. It
+# will look like: * google-protobuf (3.2.0)
+bundle list | grep google-protobuf
+bundle check | grep google-protobuf
+```
+
+Below, `3.2.0` is used as an example. Replace it with the version number
+you found above:
+
+```sh
+cd /home/git/gitlab
+sudo -u git -H gem install google-protobuf --version 3.2.0 --platform ruby
+```
+
+Finally, you can test whether `google-protobuf` loads correctly. The
+following should print 'OK'.
+
+```sh
+sudo -u git -H bundle exec ruby -rgoogle/protobuf -e 'puts :OK'
+```
+
+If the `gem install` command fails, you may need to install the developer
+tools of your OS.
+
+On Debian/Ubuntu:
+
+```sh
+sudo apt-get install build-essential libgmp-dev
+```
+
+On RedHat/CentOS:
+
+```sh
+sudo yum groupinstall 'Development Tools'
+```
[RVM]: https://rvm.io/ "RVM Homepage"
[rbenv]: https://github.com/sstephenson/rbenv "rbenv on GitHub"
diff --git a/doc/install/kubernetes/index.md b/doc/install/kubernetes/index.md
index 7312bf2d4f7..43655767002 100644
--- a/doc/install/kubernetes/index.md
+++ b/doc/install/kubernetes/index.md
@@ -1,41 +1,5 @@
---
-description: 'Read through the different methods to deploy GitLab on Kubernetes.'
+redirect_to: https://docs.gitlab.com/charts/
---
-# Installing GitLab on Kubernetes
-
-NOTE: **Kubernetes experience required:**
-Our Helm charts are recommended for those who are familiar with Kubernetes.
-If you're not sure if Kubernetes is for you, our
-[Omnibus GitLab packages](../README.md#installing-gitlab-using-the-omnibus-gitlab-package-recommended)
-are mature, scalable, support [high availability](../../administration/high_availability/README.md)
-and are used today on GitLab.com.
-It is not necessary to have GitLab installed on Kubernetes in order to use [GitLab Kubernetes integration](https://docs.gitlab.com/ee/user/project/clusters/index.html).
-
-The easiest method to deploy GitLab on [Kubernetes](https://kubernetes.io/) is
-to take advantage of GitLab's Helm charts. [Helm](https://github.com/kubernetes/helm/blob/master/README.md)
-is a package management tool for Kubernetes, allowing apps to be easily managed via their
-Charts. A [Chart](https://github.com/kubernetes/charts) is a detailed description
-of the application including how it should be deployed, upgraded, and configured.
-
-## GitLab Chart
-
-This chart contains all the required components to get started, and can scale to
-large deployments. It offers a number of benefits, among others:
-
-- Horizontal scaling of individual components.
-- No requirement for shared storage to scale.
-- Containers do not need `root` permissions.
-- Automatic SSL with Let's Encrypt.
-- An unprivileged GitLab Runner.
-
-Learn more about the [GitLab chart](https://docs.gitlab.com/charts/).
-
-## GitLab Runner Chart
-
-If you already have a GitLab instance running, inside or outside of Kubernetes,
-and you'd like to leverage the Runner's
-[Kubernetes capabilities](https://docs.gitlab.com/runner/executors/kubernetes.html),
-it can be deployed with the GitLab Runner chart.
-
-Learn more about the [GitLab Runner chart](https://docs.gitlab.com/runner/install/kubernetes.html).
+This document was moved to [another location](https://docs.gitlab.com/charts/).
diff --git a/doc/install/ldap.md b/doc/install/ldap.md
new file mode 100644
index 00000000000..d8d54864586
--- /dev/null
+++ b/doc/install/ldap.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../administration/auth/ldap.md'
+---
+
+This document was moved to [another location](../administration/auth/ldap.md).
diff --git a/doc/install/openshift_and_gitlab/img/pods-overview.png b/doc/install/openshift_and_gitlab/img/pods-overview.png
deleted file mode 100644
index 65927f65f4f..00000000000
--- a/doc/install/openshift_and_gitlab/img/pods-overview.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/openshift_and_gitlab/img/storage-volumes.png b/doc/install/openshift_and_gitlab/img/storage-volumes.png
deleted file mode 100644
index 3fd092919bb..00000000000
--- a/doc/install/openshift_and_gitlab/img/storage-volumes.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/openshift_and_gitlab/index.md b/doc/install/openshift_and_gitlab/index.md
index 77bd9e9f7a9..18981c43464 100644
--- a/doc/install/openshift_and_gitlab/index.md
+++ b/doc/install/openshift_and_gitlab/index.md
@@ -1,8 +1,5 @@
---
-author: Achilleas Pipinellis
-author_gitlab: axil
-level: intermediary
-article_type: tutorial
+type: howto
date: 2016-06-28
---
diff --git a/doc/install/pivotal/index.md b/doc/install/pivotal/index.md
new file mode 100644
index 00000000000..f068572f1e9
--- /dev/null
+++ b/doc/install/pivotal/index.md
@@ -0,0 +1,12 @@
+# GitLab Pivotal Tile **[PREMIUM ONLY]**
+
+CAUTION: **Discontinued:**
+As of September 13, 2017, the GitLab Enterprise Plus for Pivotal Cloud Foundry
+tile on Pivotal Network has reached its End of Availability (“EoAâ€) and is no
+longer available for download or sale through Pivotal. Current customers with
+active subscriptions will continue to receive support from GitLab through their
+subscription term. Pivotal and GitLab are collaborating on creating a new
+Kubernetes-based tile for the Pivotal Container Service. Please contact GitLab
+support with any questions regarding GitLab Enterprise Plus for Pivotal Cloud Foundry.
+
+Original article: <https://docs.pivotal.io/partners/gitlab/index.html>.
diff --git a/doc/install/redis.md b/doc/install/redis.md
index 4075e6283d0..cff5c2f2611 100644
--- a/doc/install/redis.md
+++ b/doc/install/redis.md
@@ -1,60 +1,5 @@
-# Install Redis on old distributions
+---
+redirect_to: installation.md#7-redis
+---
-GitLab requires at least Redis 2.8. The following guide is for Debian 7 and
-Ubuntu 12.04. If you are using Debian 8 or Ubuntu 14.04 and up, follow the
-[installation guide](installation.md).
-
-## Install Redis 2.8 in Debian 7
-
-Redis 2.8 is included in the Debian Wheezy [backports] repository.
-
-1. Edit `/etc/apt/sources.list` and add the following line:
-
- ```
- deb http://http.debian.net/debian wheezy-backports main
- ```
-
-1. Update the repositories:
-
- ```
- sudo apt-get update
- ```
-
-1. Install `redis-server`:
-
- ```
- sudo apt-get -t wheezy-backports install redis-server
- ```
-
-1. Follow the rest of the [installation guide](installation.md).
-
-## Install Redis 2.8 in Ubuntu 12.04
-
-We will [use a PPA](https://launchpad.net/~chris-lea/+archive/ubuntu/redis-server)
-to install a recent version of Redis.
-
-1. Install the PPA repository:
-
- ```
- sudo add-apt-repository ppa:chris-lea/redis-server
- ```
-
- Your system will now fetch the PPA's key. This enables your Ubuntu system to
- verify that the packages in the PPA have not been interfered with since they
- were built.
-
-1. Update the repositories:
-
- ```
- sudo apt-get update
- ```
-
-1. Install `redis-server`:
-
- ```
- sudo apt-get install redis-server
- ```
-
-1. Follow the rest of the [installation guide](installation.md).
-
-[backports]: http://backports.debian.org/Instructions/ "Debian backports website"
+This document was moved to [another location](installation.md#7-redis).
diff --git a/doc/install/relative_url.md b/doc/install/relative_url.md
index 5f129fd3bd1..96b7d0f3648 100644
--- a/doc/install/relative_url.md
+++ b/doc/install/relative_url.md
@@ -1,18 +1,19 @@
+---
+type: reference
+---
+
# Install GitLab under a relative URL
-NOTE: **Note:**
+While it is recommended to install GitLab on its own (sub)domain, sometimes
+this is not possible due to a variety of reasons. In that case, GitLab can also
+be installed under a relative URL, for example `https://example.com/gitlab`.
+
This document describes how to run GitLab under a relative URL for installations
from source. If you are using an Omnibus package,
[the steps are different][omnibus-rel]. Use this guide along with the
[installation guide](installation.md) if you are installing GitLab for the
first time.
----
-
-While it is recommended to install GitLab on its own (sub)domain, sometimes
-this is not possible due to a variety of reasons. In that case, GitLab can also
-be installed under a relative URL, for example `https://example.com/gitlab`.
-
There is no limit to how deeply nested the relative URL can be. For example you
could serve GitLab under `/foo/bar/gitlab/git` without any issues.
@@ -20,8 +21,6 @@ Note that by changing the URL on an existing GitLab installation, all remote
URLs will change, so you'll have to manually edit them in any local repository
that points to your GitLab instance.
----
-
The TL;DR list of configuration files that you need to change in order to
serve GitLab under a relative URL is:
@@ -126,3 +125,15 @@ To disable the relative URL:
[omnibus-rel]: http://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab "How to set up relative URL in Omnibus GitLab"
[restart gitlab]: ../administration/restart_gitlab.md#installations-from-source "How to restart GitLab"
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 9a6c2ce1976..ee3d17704a2 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -1,5 +1,12 @@
+---
+type: reference
+---
+
# Requirements
+This page includes useful information on the supported Operating Systems as well
+as the hardware requirements that are needed to install and use GitLab.
+
## Operating Systems
### Supported Unix distributions
@@ -12,7 +19,7 @@
- Scientific Linux (please use the CentOS packages and instructions)
- Oracle Linux (please use the CentOS packages and instructions)
-For the installations options please see [the installation page on the GitLab website](https://about.gitlab.com/installation/).
+For the installations options, see [the main installation page](README.md).
### Unsupported Unix distributions
@@ -87,7 +94,7 @@ if your available memory changes. We also recommend [configuring the kernel's sw
to a low value like `10` to make the most of your RAM while still having the swap
available when needed.
-Notice: The 25 workers of Sidekiq will show up as separate processes in your process overview (such as `top` or `htop`) but they share the same RAM allocation since Sidekiq is a multithreaded application. Please see the section below about Unicorn workers for information about how many you need of those.
+NOTE: **Note:** The 25 workers of Sidekiq will show up as separate processes in your process overview (such as `top` or `htop`) but they share the same RAM allocation since Sidekiq is a multithreaded application. Please see the section below about Unicorn workers for information about how many you need of those.
## Database
@@ -105,8 +112,10 @@ features of GitLab work with MySQL/MariaDB:
1. MySQL support for subgroups was [dropped with GitLab 9.3][post].
See [issue #30472][30472] for more information.
-1. Geo does [not support MySQL](https://docs.gitlab.com/ee/administration/geo/replication/database.html#mysql-replication). This means no supported Disaster Recovery solution if using MySQL. **[PREMIUM ONLY]**
+1. Geo does [not support MySQL](../administration/geo/replication/database.md). This means no supported Disaster Recovery solution if using MySQL. **[PREMIUM ONLY]**
1. [Zero downtime migrations](../update/README.md#upgrading-without-downtime) do not work with MySQL.
+1. [Database load balancing](../administration/database_load_balancing.md) is
+ supported only for PostgreSQL. **[PREMIUM ONLY]**
1. GitLab [optimizes the loading of dashboard events](https://gitlab.com/gitlab-org/gitlab-ce/issues/31806) using [PostgreSQL LATERAL JOINs](https://blog.heapanalytics.com/postgresqls-powerful-new-join-type-lateral/).
1. In general, SQL optimized for PostgreSQL may run much slower in MySQL due to
differences in query planners. For example, subqueries that work well in PostgreSQL
@@ -141,7 +150,17 @@ On some systems you may need to install an additional package (e.g.
#### Additional requirements for GitLab Geo
-If you are using [GitLab Geo](https://docs.gitlab.com/ee/development/geo.html), the [tracking database](https://docs.gitlab.com/ee/development/geo.html#geo-tracking-database) also requires the `postgres_fdw` extension.
+If you are using [GitLab Geo](../development/geo.md):
+
+- We strongly recommend running Omnibus-managed instances as they are actively
+ developed and tested. We aim to be compatible with most external (not managed
+ by Omnibus) databases (for example, AWS RDS) but we do not guarantee
+ compatibility.
+- The
+ [tracking database](../development/geo.md#using-the-tracking-database)
+ requires the
+ [postgres_fdw](https://www.postgresql.org/docs/9.6/static/postgres-fdw.html)
+ extension.
```
CREATE EXTENSION postgres_fdw;
@@ -149,15 +168,15 @@ CREATE EXTENSION postgres_fdw;
## Unicorn Workers
-It's possible to increase the amount of unicorn workers and this will usually help to reduce the response time of the applications and increase the ability to handle parallel requests.
-
For most instances we recommend using: CPU cores + 1 = unicorn workers.
So for a machine with 2 cores, 3 unicorn workers is ideal.
For all machines that have 2GB and up we recommend a minimum of three unicorn workers.
If you have a 1GB machine we recommend to configure only two Unicorn workers to prevent excessive swapping.
-To change the Unicorn workers when you have the Omnibus package (which defaults to the recommendation above) please see [the Unicorn settings in the Omnibus GitLab documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/unicorn.md#unicorn-settings).
+As long as you have enough available CPU and memory capacity, it's okay to increase the number of unicorn workers and this will usually help to reduce the response time of the applications and increase the ability to handle parallel requests.
+
+To change the Unicorn workers when you have the Omnibus package (which defaults to the recommendation above) please see [the Unicorn settings in the Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/unicorn.html).
## Redis and Sidekiq
@@ -189,13 +208,23 @@ you decide to run GitLab Runner and the GitLab Rails application on the same
machine.
It is also not safe to install everything on a single machine, because of the
-[security reasons] - especially when you plan to use shell executor with GitLab
+[security reasons](https://docs.gitlab.com/runner/security/), especially when you plan to use shell executor with GitLab
Runner.
We recommend using a separate machine for each GitLab Runner, if you plan to
use the CI features.
+The GitLab Runner server requirements depend on:
+
+- The type of [executor](https://docs.gitlab.com/runner/executors/) you configured on GitLab Runner.
+- Resources required to run build jobs.
+- Job concurrency settings.
-[security reasons]: https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/security/index.md
+Since the nature of the jobs varies for each use case, you will need to experiment by adjusting the job concurrency to get the optimum setting.
+
+For reference, GitLab.com's [auto-scaling shared runner](../user/gitlab_com/index.md#shared-runners) is configured so that a **single job** will run in a **single instance** with:
+
+- 1vCPU.
+- 3.75GB of RAM.
## Supported web browsers
@@ -212,5 +241,17 @@ Support is only provided for the current minor version of the major version you
Each time a new browser version is released, we begin supporting that version and stop supporting the third most recent version.
-Note: We do not support running GitLab with JavaScript disabled in the browser and have no plans of supporting that
+NOTE: **Note:** We do not support running GitLab with JavaScript disabled in the browser and have no plans of supporting that
in the future because we have features such as Issue Boards which require JavaScript extensively.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/install/structure.md b/doc/install/structure.md
index 8fc6ab4ab2f..87ef11c60fe 100644
--- a/doc/install/structure.md
+++ b/doc/install/structure.md
@@ -1,19 +1,5 @@
-# GitLab directory structure
+---
+redirect_to: installation.md#gitlab-directory-structure
+---
-This is the directory structure you will end up with following the instructions in the Installation Guide.
-
- |-- home
- | |-- git
- | |-- .ssh
- | |-- gitlab
- | |-- gitlab-shell
- | |-- repositories
-
-- `/home/git/.ssh` - contains openssh settings. Specifically the `authorized_keys` file managed by gitlab-shell.
-- `/home/git/gitlab` - GitLab core software.
-- `/home/git/gitlab-shell` - Core add-on component of GitLab. Maintains SSH cloning and other functionality.
-- `/home/git/repositories` - bare repositories for all projects organized by namespace. This is where the git repositories which are pushed/pulled are maintained for all projects. **This area is critical data for projects. [Keep a backup](../raketasks/backup_restore.md).**
-
-*Note: the default locations for repositories can be configured in `config/gitlab.yml` of GitLab and `config.yml` of gitlab-shell.*
-
-To see a more in-depth overview see the [GitLab architecture doc](../development/architecture.md).
+This page was moved to [another location](#installation.md#gitlab-directory-structure).
diff --git a/doc/integration/README.md b/doc/integration/README.md
index a539933f223..1fea6a32c28 100644
--- a/doc/integration/README.md
+++ b/doc/integration/README.md
@@ -15,7 +15,9 @@ See the documentation below for details on how to configure these services.
- [CAS](cas.md) Configure GitLab to sign in using CAS
- [External issue tracker](external-issue-tracker.md) Redmine, JIRA, etc.
- [Gmail actions buttons](gmail_action_buttons_for_gitlab.md) Adds GitLab actions to messages
+- [Jenkins](jenkins.md) Integrate with the Jenkins CI
- [JIRA](../user/project/integrations/jira.md) Integrate with the JIRA issue tracker
+- [Kerberos](kerberos.md) Integrate with Kerberos
- [LDAP](ldap.md) Set up sign in via LDAP
- [OAuth2 provider](oauth_provider.md) OAuth2 application creation
- [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, GitLab.com, Google, Bitbucket, Facebook, Shibboleth, SAML, Crowd, Azure and Authentiq ID
diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md
new file mode 100644
index 00000000000..6064c417900
--- /dev/null
+++ b/doc/integration/elasticsearch.md
@@ -0,0 +1,518 @@
+# Elasticsearch integration **[STARTER ONLY]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/109 "Elasticsearch Merge Request") in GitLab [Starter](https://about.gitlab.com/pricing/) 8.4. Support
+> for [Amazon Elasticsearch](http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-gsg.html) was [introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1305) in GitLab
+> [Starter](https://about.gitlab.com/pricing/) 9.0.
+
+This document describes how to set up Elasticsearch with GitLab. Once enabled,
+you'll have the benefit of fast search response times and the advantage of two
+special searches:
+
+- [Advanced Global Search](../user/search/advanced_global_search.md)
+- [Advanced Syntax Search](../user/search/advanced_search_syntax.md)
+
+## Version Requirements
+<!-- Please remember to update ee/lib/system_check/app/elasticsearch_check.rb if this changes -->
+
+| GitLab version | Elasticsearch version |
+| -------------- | --------------------- |
+| GitLab Enterprise Edition 8.4 - 8.17 | Elasticsearch 2.4 with [Delete By Query Plugin](https://www.elastic.co/guide/en/elasticsearch/plugins/2.4/plugins-delete-by-query.html) installed |
+| GitLab Enterprise Edition 9.0 - 11.4 | Elasticsearch 5.1 - 5.5 |
+| GitLab Enterprise Edition 11.5+ | Elasticsearch 5.6 - 6.x |
+
+## Installing Elasticsearch
+
+Elasticsearch is _not_ included in the Omnibus packages. You will have to
+install it yourself whether you are using the Omnibus package or installed
+GitLab from source. Providing detailed information on installing Elasticsearch
+is out of the scope of this document.
+
+Once the data is added to the database or repository and [Elasticsearch is
+enabled in the admin area](#enabling-elasticsearch) the search index will be
+updated automatically. Elasticsearch can be installed on the same machine as
+GitLab or on a separate server, or you can use the [Amazon Elasticsearch](http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-gsg.html)
+service.
+
+You can follow the steps as described in the [official web site](https://www.elastic.co/guide/en/elasticsearch/reference/current/install-elasticsearch.html "Elasticsearch installation documentation") or
+use the packages that are available for your OS.
+
+## Elasticsearch repository indexer (beta)
+
+In order to improve elasticsearch indexing performance, GitLab has made available a [new indexer written in Go](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer).
+This will replace the included Ruby indexer in the future but should be considered beta software for now, so there may be some bugs.
+
+If you would like to use it, please follow the instructions below.
+
+### Installation
+
+First, we need to install some dependencies, then we'll build and install
+the indexer itself.
+
+#### Dependencies
+
+This project relies on [ICU](http://site.icu-project.org/) for text encoding,
+therefore we need to ensure the development packages for your platform are
+installed before running `make`.
+
+##### Debian / Ubuntu
+
+To install on Debian or Ubuntu, run:
+
+```sh
+sudo apt install libicu-dev
+```
+
+##### CentOS / RHEL
+
+To install on CentOS or RHEL, run:
+
+```sh
+sudo yum install libicu-devel
+```
+
+##### Mac OSX
+
+To install on macOS, run:
+
+```sh
+brew install icu4c
+export PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:$PKG_CONFIG_PATH"
+```
+
+#### Building and installing
+
+To build and install the indexer, run:
+
+```sh
+git clone https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer.git
+cd gitlab-elasticsearch-indexer
+make
+sudo make install
+```
+
+The `gitlab-elasticsearch-indexer` will be installed to `/usr/local/bin`.
+
+You can change the installation path with the `PREFIX` env variable.
+Please remember to pass the `-E` flag to `sudo` if you do so.
+
+Example:
+
+```sh
+PREFIX=/usr sudo -E make install
+```
+
+Once installed, enable it under your instance's elasticsearch settings explained [below](#enabling-elasticsearch).
+
+## System Requirements
+
+Elasticsearch requires additional resources in excess of those documented in the
+[GitLab system requirements](../install/requirements.md). These will vary by
+installation size, but you should ensure **at least** an additional **8 GiB of RAM**
+for each Elasticsearch node, per the [official guidelines](https://www.elastic.co/guide/en/elasticsearch/guide/current/hardware.html).
+
+Keep in mind, this is the **minimum requirements** as per Elasticsearch. For
+production instances, they recommend considerably more resources.
+
+Storage requirements also vary based on the installation side, but as a rule of
+thumb, you should allocate the total size of your production database, **plus**
+two-thirds of the total size of your git repositories. Efforts to reduce this
+total are being tracked in this epic: [gitlab-org&153](https://gitlab.com/groups/gitlab-org/-/epics/153).
+
+## Enabling Elasticsearch
+
+In order to enable Elasticsearch, you need to have admin access. Go to
+**Admin > Settings > Integrations** and find the "Elasticsearch" section.
+
+The following Elasticsearch settings are available:
+
+| Parameter | Description |
+| --------- | ----------- |
+| `Elasticsearch indexing` | Enables/disables Elasticsearch indexing. You may want to enable indexing but disable search in order to give the index time to be fully completed, for example. Also, keep in mind that this option doesn't have any impact on existing data, this only enables/disables background indexer which tracks data changes. So by enabling this you will not get your existing data indexed, use special rake task for that as explained in [Adding GitLab's data to the Elasticsearch index](#adding-gitlabs-data-to-the-elasticsearch-index). |
+| `Use the new repository indexer (beta)` | Perform repository indexing using [GitLab Elasticsearch Indexer](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer). |
+| `Search with Elasticsearch enabled` | Enables/disables using Elasticsearch in search. |
+| `URL` | The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., "http://host1, https://host2:9200"). If your Elasticsearch instance is password protected, pass the `username:password` in the URL (e.g., `http://<username>:<password>@<elastic_host>:9200/`). |
+| `Number of Elasticsearch shards` | Elasticsearch indexes are split into multiple shards for performance reasons. In general, larger indexes need to have more shards. Changes to this value do not take effect until the index is recreated. You can read more about tradeoffs in the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html#create-index-settings) |
+| `Number of Elasticsearch replicas` | Each Elasticsearch shard can have a number of replicas. These are a complete copy of the shard, and can provide increased query performance or resilience against hardware failure. Increasing this value will greatly increase total disk space required by the index. |
+| `Limit namespaces and projects that can be indexed` | Enabling this will allow you to select namespaces and projects to index. All other namespaces and projects will use database search instead. Please note that if you enable this option but do not select any namespaces or projects, none will be indexed. [Read more below](#limiting-namespaces-and-projects).
+| `Using AWS hosted Elasticsearch with IAM credentials` | Sign your Elasticsearch requests using [AWS IAM authorization](http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html) or [AWS EC2 Instance Profile Credentials](http://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-create-iam-instance-profile.html#getting-started-create-iam-instance-profile-cli). The policies must be configured to allow `es:*` actions. |
+| `AWS Region` | The AWS region your Elasticsearch service is located in. |
+| `AWS Access Key` | The AWS access key. |
+| `AWS Secret Access Key` | The AWS secret access key. |
+
+### Limiting namespaces and projects
+
+If you select `Limit namespaces and projects that can be indexed`, more options will become available
+![limit namespaces and projects options](img/limit_namespaces_projects_options.png)
+
+You can select namespaces and projects to index exclusively. Please note that if the namespace is a group it will include
+any sub-groups and projects belonging to those sub-groups to be indexed as well.
+
+You can filter the selection dropdown by writing part of the namespace or project name you're interested in.
+![limit namespace filter](img/limit_namespace_filter.png)
+
+NOTE: **Note**:
+If no namespaces or projects are selected, no Elasticsearch indexing will take place.
+
+CAUTION: **Warning**:
+If you have already indexed your instance, you will have to regenerate the index in order to delete all existing data
+for filtering to work correctly. To do this run the rake tasks `gitlab:elastic:create_empty_index` and
+`gitlab:elastic:clear_index_status` Afterwards, removing a namespace or a projeect from the list will delete the data
+from the Elasticsearch index as expected.
+
+## Disabling Elasticsearch
+
+To disable the Elasticsearch integration:
+
+1. Navigate to the **Admin > Settings > Integrations**
+1. Find the 'Elasticsearch' section and uncheck 'Search with Elasticsearch enabled'
+ and 'Elasticsearch indexing'
+1. Click **Save** for the changes to take effect
+1. [Optional] Delete the existing index by running the command `sudo gitlab-rake gitlab:elastic:delete_index`
+
+## Adding GitLab's data to the Elasticsearch index
+
+### Indexing small instances (database size less than 500 MiB, size of repos less than 5 GiB)
+
+Configure Elasticsearch's host and port in **Admin > Settings**. Then index the data using one of the following commands:
+
+```sh
+# Omnibus installations
+sudo gitlab-rake gitlab:elastic:index
+
+# Installations from source
+bundle exec rake gitlab:elastic:index RAILS_ENV=production
+```
+
+After it completes the indexing process, [enable Elasticsearch searching](elasticsearch.md#enabling-elasticsearch).
+
+### Indexing large instances
+
+WARNING: **Warning**:
+Performing asynchronous indexing, as this will describe, will generate a lot of sidekiq jobs.
+Make sure to prepare for this task by either [Horizontally Scaling](../administration/high_availability/README.md#basic-scaling)
+or creating [extra sidekiq processes](../administration/operations/extra_sidekiq_processes.md)
+
+Configure Elasticsearch's host and port in **Admin > Settings > Integrations**. Then create empty indexes using one of the following commands:
+
+```sh
+# Omnibus installations
+sudo gitlab-rake gitlab:elastic:create_empty_index
+
+# Installations from source
+bundle exec rake gitlab:elastic:create_empty_index RAILS_ENV=production
+```
+
+Indexing large Git repositories can take a while. To speed up the process, you
+can temporarily disable auto-refreshing and replicating. In our experience, you can expect a 20%
+decrease in indexing time. We'll enable them when indexing is done. This step is optional!
+
+```bash
+curl --request PUT localhost:9200/gitlab-production/_settings --data '{
+ "index" : {
+ "refresh_interval" : "-1",
+ "number_of_replicas" : 0
+ } }'
+```
+
+Then enable Elasticsearch indexing and run project indexing tasks:
+
+```sh
+# Omnibus installations
+sudo gitlab-rake gitlab:elastic:index_projects
+
+# Installations from source
+bundle exec rake gitlab:elastic:index_projects RAILS_ENV=production
+```
+
+This enqueues a Sidekiq job for each project that needs to be indexed.
+You can view the jobs in the admin panel (they are placed in the `elastic_indexer`
+queue), or you can query indexing status using a rake task:
+
+```sh
+# Omnibus installations
+sudo gitlab-rake gitlab:elastic:index_projects_status
+
+# Installations from source
+bundle exec rake gitlab:elastic:index_projects_status RAILS_ENV=production
+
+Indexing is 65.55% complete (6555/10000 projects)
+```
+
+If you want to limit the index to a range of projects you can provide the
+`ID_FROM` and `ID_TO` parameters:
+
+```sh
+# Omnibus installations
+sudo gitlab-rake gitlab:elastic:index_projects ID_FROM=1001 ID_TO=2000
+
+# Installations from source
+bundle exec rake gitlab:elastic:index_projects ID_FROM=1001 ID_TO=2000 RAILS_ENV=production
+```
+
+Where `ID_FROM` and `ID_TO` are project IDs. Both parameters are optional.
+The above examples will index all projects starting with ID `1001` up to (and including) ID `2000`.
+
+TIP: **Troubleshooting:**
+Sometimes the project indexing jobs queued by `gitlab:elastic:index_projects`
+can get interrupted. This may happen for many reasons, but it's always safe
+to run the indexing task again - it will skip those repositories that have
+already been indexed.
+
+As the indexer stores the last commit SHA of every indexed repository in the
+database, you can run the indexer with the special parameter `UPDATE_INDEX` and
+it will check every project repository again to make sure that every commit in
+that repository is indexed, it can be useful in case if your index is outdated:
+
+```sh
+# Omnibus installations
+sudo gitlab-rake gitlab:elastic:index_projects UPDATE_INDEX=true ID_TO=1000
+
+# Installations from source
+bundle exec rake gitlab:elastic:index_projects UPDATE_INDEX=true ID_TO=1000 RAILS_ENV=production
+```
+
+You can also use the `gitlab:elastic:clear_index_status` Rake task to force the
+indexer to "forget" all progress, so retrying the indexing process from the
+start.
+
+To index all wikis:
+
+```sh
+# Omnibus installations
+sudo gitlab-rake gitlab:elastic:index_wikis
+
+# Installations from source
+bundle exec rake gitlab:elastic:index_wikis RAILS_ENV=production
+```
+
+The wiki indexer also supports the `ID_FROM` and `ID_TO` parameters if you want
+to limit a project set.
+
+Enable replication and refreshing again after indexing (only if you previously disabled it):
+
+```bash
+curl --request PUT localhost:9200/gitlab-production/_settings --data '{
+ "index" : {
+ "number_of_replicas" : 1,
+ "refresh_interval" : "1s"
+ } }'
+```
+
+A force merge should be called after enabling the refreshing above.
+
+For Elasticsearch 6.x, before proceeding with the force merge, the index should be in read-only mode:
+
+```bash
+curl --request PUT localhost:9200/gitlab-production/_settings --data '{
+ "settings": {
+ "index.blocks.write": true
+ } }'
+```
+
+Then, initiate the force merge:
+
+```bash
+curl --request POST 'http://localhost:9200/gitlab-production/_forcemerge?max_num_segments=5'
+```
+
+After this, if your index is in read-only, switch back to read-write:
+
+```bash
+curl --request PUT localhost:9200/gitlab-production/_settings --data '{
+ "settings": {
+ "index.blocks.write": false
+ } }'
+```
+
+Enable Elasticsearch search in **Admin > Settings > Integrations**. That's it. Enjoy it!
+
+## GitLab Elasticsearch Rake Tasks
+
+There are several rake tasks available to you via the command line:
+
+- [sudo gitlab-rake gitlab:elastic:index](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/tasks/gitlab/elastic.rake)
+ - This is a wrapper task. It does the following:
+ - `sudo gitlab-rake gitlab:elastic:create_empty_index`
+ - `sudo gitlab-rake gitlab:elastic:clear_index_status`
+ - `sudo gitlab-rake gitlab:elastic:index_projects`
+ - `sudo gitlab-rake gitlab:elastic:index_wikis`
+ - `sudo gitlab-rake gitlab:elastic:index_snippets`
+- [sudo gitlab-rake gitlab:elastic:index_projects](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/tasks/gitlab/elastic.rake)
+ - This iterates over all projects and queues sidekiq jobs to index them in the background.
+- [sudo gitlab-rake gitlab:elastic:index_projects_status](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/tasks/gitlab/elastic.rake)
+ - This determines the overall status of the indexing. It is done by counting the total number of indexed projects, dividing by a count of the total number of projects, then multiplying by 100.
+- [sudo gitlab-rake gitlab:elastic:index_wikis](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/tasks/gitlab/elastic.rake)
+ - Iterates over every project, determines if said project contains wiki data, and then indexes the blobs (content) of said wiki data.
+- [sudo gitlab-rake gitlab:elastic:create_empty_index](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/tasks/gitlab/elastic.rake)
+ - This generates an empty index on the Elasticsearch side.
+- [sudo gitlab-rake gitlab:elastic:clear_index_status](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/tasks/gitlab/elastic.rake)
+ - This deletes all instances of IndexStatus for all projects.
+- [sudo gitlab-rake gitlab:elastic:delete_index](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/tasks/gitlab/elastic.rake)
+ - This removes the GitLab index on the Elasticsearch instance.
+- [sudo gitlab-rake gitlab:elastic:recreate_index](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/tasks/gitlab/elastic.rake)
+ - Does the same thing as `sudo gitlab-rake gitlab:elastic:create_empty_index`
+- [sudo gitlab-rake gitlab:elastic:index_snippets](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/tasks/gitlab/elastic.rake)
+ - Performs an Elasticsearch import that indexes the snippets data.
+
+### Environment Variables
+
+In addition to the rake tasks, there are some environment variables that can be used to modify the process:
+
+| Environment Variable | Data Type | What it does |
+| -------------------- |:---------:| ---------------------------------------------------------------------------- |
+| `UPDATE_INDEX` | Boolean | Tells the indexer to overwrite any existing index data (true/false). |
+| `ID_TO` | Integer | Tells the indexer to only index projects less than or equal to the value. |
+| `ID_FROM` | Integer | Tells the indexer to only index projects greater than or equal to the value. |
+
+### Indexing a specific project
+
+Because the `ID_TO` and `ID_FROM` environment variables use the `or equal to` comparison, you can index only one project by using both these variables with the same project ID number:
+
+```sh
+root@git:~# sudo gitlab-rake gitlab:elastic:index_projects ID_TO=5 ID_FROM=5
+Indexing project repositories...I, [2019-03-04T21:27:03.083410 #3384] INFO -- : Indexing GitLab User / test (ID=33)...
+I, [2019-03-04T21:27:05.215266 #3384] INFO -- : Indexing GitLab User / test (ID=33) is done!
+```
+
+## Elasticsearch Index Scopes
+
+When performing a search, the GitLab index will use the following scopes:
+
+| Scope Name | What it searches |
+| ---------------- | ---------------------- |
+| `commits` | Commit data |
+| `projects` | Project data (default) |
+| `blobs` | Code |
+| `issues` | Issue data |
+| `merge_requests` | Merge Request data |
+| `milestones` | Milestone data |
+| `notes` | Note data |
+| `snippets` | Snippet data |
+| `wiki_blobs` | Wiki contents |
+
+## Tuning
+
+### Deleted documents
+
+Whenever a change or deletion is made to an indexed GitLab object (a merge request description is changed, a file is deleted from the master branch in a repository, a project is deleted, etc), a document in the index is deleted. However, since these are "soft" deletes, the overall number of "deleted documents", and therefore wasted space, increases. Elasticsearch does intelligent merging of segments in order to remove these deleted documents. However, depending on the amount and type of activity in your GitLab installation, it's possible to see as much as 50% wasted space in the index.
+
+In general, we recommend simply letting Elasticseach merge and reclaim space automatically, with the default settings. From [Lucene's Handling of Deleted Documents](https://www.elastic.co/blog/lucenes-handling-of-deleted-documents "Lucene's Handling of Deleted Documents"), _"Overall, besides perhaps decreasing the maximum segment size, it is best to leave Lucene's defaults as-is and not fret too much about when deletes are reclaimed."_
+
+However, some larger installations may wish to tune the merge policy settings:
+
+- Consider reducing the `index.merge.policy.max_merged_segment` size from the default 5 GB to maybe 2 GB or 3 GB. Merging only happens when a segment has at least 50% deletions. Smaller segment sizes will allow merging to happen more frequently.
+
+ ```bash
+ curl --request PUT http://localhost:9200/gitlab-production/_settings --data '{
+ "index" : {
+ "merge.policy.max_merged_segment": "2gb"
+ }
+ }'
+ ```
+
+- You can also adjust `index.merge.policy.reclaim_deletes_weight`, which controls how aggressively deletions are targeted. But this can lead to costly merge decisions, so we recommend not changing this unless you understand the tradeoffs.
+
+ ```bash
+ curl --request PUT http://localhost:9200/gitlab-production/_settings --data '{
+ "index" : {
+ "merge.policy.reclaim_deletes_weight": "3.0"
+ }
+ }'
+ ```
+
+- Do not do a [force merge](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html "Force Merge") to remove deleted documents. A warning in the [documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html "Force Merge") states that this can lead to very large segments that may never get reclaimed, and can also cause significant performance or availability issues.
+
+## Troubleshooting
+
+Here are some common pitfalls and how to overcome them:
+
+- **How can I verify my GitLab instance is using Elasticsearch?**
+
+ The easiest method is via the rails console (`sudo gitlab-rails console`) by running the following:
+
+ ```ruby
+ u = User.find_by_username('your-username')
+ s = SearchService.new(u, {:search => 'search_term'})
+ pp s.search_objects.class.name
+ ```
+
+ If you see `Elasticsearch::Model::Response::Records`, you are using Elasticsearch.
+
+- **I updated GitLab and now I can't find anything**
+
+ We continuously make updates to our indexing strategies and aim to support
+ newer versions of Elasticsearch. When indexing changes are made, it may
+ be necessary for you to [reindex](#adding-gitlabs-data-to-the-elasticsearch-index) after updating GitLab.
+
+- **I indexed all the repositories but I can't find anything**
+
+ Make sure you indexed all the database data [as stated above](#adding-gitlabs-data-to-the-elasticsearch-index).
+
+ Beyond that, check via the [Elasticsearch Search API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html) to see if the data shows up on the Elasticsearch side.
+
+ If it shows up via the [Elasticsearch Search API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html), check that it shows up via the rails console (`sudo gitlab-rails console`):
+
+ ```ruby
+ u = User.find_by_username('your-username')
+ s = SearchService.new(u, {:search => 'search_term', :scope => ‘blobs’})
+ pp s.search_objects.to_a
+ ```
+
+ See [Elasticsearch Index Scopes](elasticsearch.md#elasticsearch-index-scopes) for more information on searching for specific types of data.
+
+- **I indexed all the repositories but then switched elastic search servers and now I can't find anything**
+
+ You will need to re-run all the rake tasks to re-index the database, repositories, and wikis.
+
+- **The indexing process is taking a very long time**
+
+ The more data present in your GitLab instance, the longer the indexing process takes.
+
+- **No new data is added to the Elasticsearch index when I push code**
+
+ When performing the initial indexing of blobs, we lock all projects until the project finishes indexing. It could
+ happen that an error during the process causes one or multiple projects to remain locked. In order to unlock them,
+ run the `gitlab:elastic:clear_locked_projects` rake task.
+
+- **"Can't specify parent if no parent field has been configured"**
+
+ If you enabled Elasticsearch before GitLab 8.12 and have not rebuilt indexes you will get
+ exception in lots of different cases:
+
+ ```text
+ Elasticsearch::Transport::Transport::Errors::BadRequest([400] {
+ "error": {
+ "root_cause": [{
+ "type": "illegal_argument_exception",
+ "reason": "Can't specify parent if no parent field has been configured"
+ }],
+ "type": "illegal_argument_exception",
+ "reason": "Can't specify parent if no parent field has been configured"
+ },
+ "status": 400
+ }):
+ ```
+
+ This is because we changed the index mapping in GitLab 8.12 and the old indexes should be removed and built from scratch again,
+ see details in the [8-11-to-8-12 update guide](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/doc/update/8.11-to-8.12.md#11-elasticsearch-index-update-if-you-currently-use-elasticsearch).
+
+- Exception `Elasticsearch::Transport::Transport::Errors::BadRequest`
+
+ If you have this exception (just like in the case above but the actual message is different) please check if you have the correct Elasticsearch version and you met the other [requirements](#system-requirements).
+ There is also an easy way to check it automatically with `sudo gitlab-rake gitlab:check` command.
+
+- Exception `Elasticsearch::Transport::Transport::Errors::RequestEntityTooLarge`
+
+ ```text
+ [413] {"Message":"Request size exceeded 10485760 bytes"}
+ ```
+
+ This exception is seen when your Elasticsearch cluster is configured to reject
+ requests above a certain size (10MiB in this case). This corresponds to the
+ `http.max_content_length` setting in `elasticsearch.yml`. Increase it to a
+ larger size and restart your Elasticsearch cluster.
+
+ AWS has [fixed limits](http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/aes-limits.html)
+ for this setting ("Maximum Size of HTTP Request Payloads"), based on the size of
+ the underlying instance.
+
diff --git a/doc/integration/github.md b/doc/integration/github.md
index bee68688ace..5b01dd9feb7 100644
--- a/doc/integration/github.md
+++ b/doc/integration/github.md
@@ -19,12 +19,12 @@ To get the credentials (a pair of Client ID and Client Secret), you must registe
1. Provide the required details.
- Application name: This can be anything. Consider something like `<Organization>'s GitLab` or `<Your Name>'s GitLab` or something else descriptive.
- - Homepage URL: the URL to your GitLab installation. e.g., `https://gitlab.company.com`
+ - Homepage URL: The URL of your GitLab installation. For example, `https://gitlab.example.com`.
- Application description: Fill this in if you wish.
- - Authorization callback URL: `http(s)://${YOUR_DOMAIN}/users/auth/github/callback`. Please make sure the port is included if your GitLab instance is not configured on default port.
+ - Authorization callback URL: `http(s)://${YOUR_DOMAIN}/users/auth`. Please make sure the port is included if your GitLab instance is not configured on default port.
![Register OAuth App](img/github_register_app.png)
- NOTE: Be sure to append `/users/auth/github/callback` to the end of the callback URL
+ NOTE: Be sure to append `/users/auth` to the end of the callback URL
to prevent a [OAuth2 convert
redirect](http://tetraph.com/covert_redirect/) vulnerability.
diff --git a/doc/integration/img/google_app.png b/doc/integration/img/google_app.png
deleted file mode 100644
index 08f230452b4..00000000000
--- a/doc/integration/img/google_app.png
+++ /dev/null
Binary files differ
diff --git a/doc/integration/img/jenkins_gitlab_plugin_config.png b/doc/integration/img/jenkins_gitlab_plugin_config.png
new file mode 100644
index 00000000000..3e1f83e96dc
--- /dev/null
+++ b/doc/integration/img/jenkins_gitlab_plugin_config.png
Binary files differ
diff --git a/doc/integration/img/jenkins_gitlab_service.png b/doc/integration/img/jenkins_gitlab_service.png
new file mode 100644
index 00000000000..682a5ae8ee2
--- /dev/null
+++ b/doc/integration/img/jenkins_gitlab_service.png
Binary files differ
diff --git a/doc/integration/img/jenkins_gitlab_service_settings.png b/doc/integration/img/jenkins_gitlab_service_settings.png
new file mode 100644
index 00000000000..5a12e9cb39a
--- /dev/null
+++ b/doc/integration/img/jenkins_gitlab_service_settings.png
Binary files differ
diff --git a/doc/integration/img/jenkins_project.png b/doc/integration/img/jenkins_project.png
new file mode 100644
index 00000000000..126b05c8879
--- /dev/null
+++ b/doc/integration/img/jenkins_project.png
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_gl_setup_1.png b/doc/integration/img/jira_dev_panel_gl_setup_1.png
new file mode 100644
index 00000000000..75279877c93
--- /dev/null
+++ b/doc/integration/img/jira_dev_panel_gl_setup_1.png
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_jira_setup_1.png b/doc/integration/img/jira_dev_panel_jira_setup_1.png
new file mode 100644
index 00000000000..5c0f594cc1d
--- /dev/null
+++ b/doc/integration/img/jira_dev_panel_jira_setup_1.png
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_jira_setup_2.png b/doc/integration/img/jira_dev_panel_jira_setup_2.png
new file mode 100644
index 00000000000..a4778a00dd5
--- /dev/null
+++ b/doc/integration/img/jira_dev_panel_jira_setup_2.png
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_jira_setup_3.png b/doc/integration/img/jira_dev_panel_jira_setup_3.png
new file mode 100644
index 00000000000..4049a65f56b
--- /dev/null
+++ b/doc/integration/img/jira_dev_panel_jira_setup_3.png
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_jira_setup_4.png b/doc/integration/img/jira_dev_panel_jira_setup_4.png
new file mode 100644
index 00000000000..81d84cb173d
--- /dev/null
+++ b/doc/integration/img/jira_dev_panel_jira_setup_4.png
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_jira_setup_5.png b/doc/integration/img/jira_dev_panel_jira_setup_5.png
new file mode 100644
index 00000000000..73dc867d301
--- /dev/null
+++ b/doc/integration/img/jira_dev_panel_jira_setup_5.png
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_manual_refresh.png b/doc/integration/img/jira_dev_panel_manual_refresh.png
new file mode 100644
index 00000000000..dc92d533bde
--- /dev/null
+++ b/doc/integration/img/jira_dev_panel_manual_refresh.png
Binary files differ
diff --git a/doc/integration/img/limit_namespace_filter.png b/doc/integration/img/limit_namespace_filter.png
new file mode 100644
index 00000000000..88f5caa41db
--- /dev/null
+++ b/doc/integration/img/limit_namespace_filter.png
Binary files differ
diff --git a/doc/integration/img/limit_namespaces_projects_options.png b/doc/integration/img/limit_namespaces_projects_options.png
new file mode 100644
index 00000000000..488341f7e92
--- /dev/null
+++ b/doc/integration/img/limit_namespaces_projects_options.png
Binary files differ
diff --git a/doc/integration/img/salesforce_app_details.png b/doc/integration/img/salesforce_app_details.png
new file mode 100644
index 00000000000..00e66f07282
--- /dev/null
+++ b/doc/integration/img/salesforce_app_details.png
Binary files differ
diff --git a/doc/integration/img/salesforce_app_secret_details.png b/doc/integration/img/salesforce_app_secret_details.png
new file mode 100644
index 00000000000..fad2a4a1f97
--- /dev/null
+++ b/doc/integration/img/salesforce_app_secret_details.png
Binary files differ
diff --git a/doc/integration/img/salesforce_oauth_app_details.png b/doc/integration/img/salesforce_oauth_app_details.png
new file mode 100644
index 00000000000..a5fb680cca6
--- /dev/null
+++ b/doc/integration/img/salesforce_oauth_app_details.png
Binary files differ
diff --git a/doc/integration/img/ultra_auth_credentials.png b/doc/integration/img/ultra_auth_credentials.png
new file mode 100644
index 00000000000..cff98a4b056
--- /dev/null
+++ b/doc/integration/img/ultra_auth_credentials.png
Binary files differ
diff --git a/doc/integration/img/ultra_auth_edit_callback_url.png b/doc/integration/img/ultra_auth_edit_callback_url.png
new file mode 100644
index 00000000000..b7548122c5e
--- /dev/null
+++ b/doc/integration/img/ultra_auth_edit_callback_url.png
Binary files differ
diff --git a/doc/integration/img/ultra_auth_edit_callback_url_highlighted.png b/doc/integration/img/ultra_auth_edit_callback_url_highlighted.png
new file mode 100644
index 00000000000..4abf224756c
--- /dev/null
+++ b/doc/integration/img/ultra_auth_edit_callback_url_highlighted.png
Binary files differ
diff --git a/doc/integration/jenkins.md b/doc/integration/jenkins.md
new file mode 100644
index 00000000000..5950737b964
--- /dev/null
+++ b/doc/integration/jenkins.md
@@ -0,0 +1,134 @@
+# Jenkins CI service **[STARTER]**
+
+>**Note:**
+In GitLab 8.3, Jenkins integration using the
+[GitLab Hook Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+Hook+Plugin)
+was deprecated in favor of the
+[GitLab Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+Plugin).
+The deprecated integration has been renamed to [Jenkins CI (Deprecated)](jenkins_deprecated.md) in the
+project service settings. We may remove this in a future release and recommend
+using the new 'Jenkins CI' project service instead which is described in this
+document.
+
+## Overview
+
+[Jenkins](https://jenkins.io/) is a great Continuous Integration tool, similar to our built-in
+[GitLab CI](../ci/README.md).
+
+GitLab's Jenkins integration allows you to trigger a Jenkins build when you
+push code to a repository, or when a merge request is created. Additionally,
+it shows the pipeline status on merge requests widgets and on the project's home page.
+
+Videos are also available on [GitLab workflow with Jira issues and Jenkins pipelines](https://youtu.be/Jn-_fyra7xQ)
+and [Migrating from Jenkins to GitLab](https://www.youtube.com/watch?v=RlEVGOpYF5Y).
+
+## Use cases
+
+- Suppose you are new to GitLab, and want to keep using Jenkins until you prepare
+your projects to build with [GitLab CI/CD](../ci/README.md). You set up the
+integration between GitLab and Jenkins, then you migrate to GitLab CI later. While
+you organize yourself and your team to onboard GitLab, you keep your pipelines
+running with Jenkins, but view the results in your project's repository in GitLab.
+- Your team uses [Jenkins Plugins](https://plugins.jenkins.io/) for other proceedings,
+therefore, you opt for keep using Jenkins to build your apps. Show the results of your
+pipelines directly in GitLab.
+
+For a real use case, read the blog post [Continuous integration: From Jenkins to GitLab using Docker](https://about.gitlab.com/2017/07/27/docker-my-precious/).
+
+## Requirements
+
+* [Jenkins GitLab Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+Plugin)
+* [Jenkins Git Plugin](https://wiki.jenkins.io/display/JENKINS/Git+Plugin)
+* Git clone access for Jenkins from the GitLab repository
+* GitLab API access to report build status
+
+## Configure GitLab users
+
+Create a user or choose an existing user that Jenkins will use to interact
+through the GitLab API. This user will need to be a global Admin or added
+as a member to each Group/Project. Developer permission is required for reporting
+build status. This is because a successful build status can trigger a merge
+when 'Merge when pipeline succeeds' feature is used. Some features of the GitLab
+Plugin may require additional privileges. For example, there is an option to
+accept a merge request if the build is successful. Using this feature would
+require developer, maintainer or owner-level permission.
+
+Copy the private API token from **Profile Settings -> Account**. You will need this
+when configuring the Jenkins server later.
+
+## Configure the Jenkins server
+
+Install [Jenkins GitLab Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+Plugin)
+and [Jenkins Git Plugin](https://wiki.jenkins.io/display/JENKINS/Git+Plugin).
+
+Go to Manage Jenkins -> Configure System and scroll down to the 'GitLab' section.
+Enter the GitLab server URL in the 'GitLab host URL' field and paste the API token
+copied earlier in the 'API Token' field.
+
+For more information, see GitLab Plugin documentation about
+[Jenkins-to-GitLab authentication](https://github.com/jenkinsci/gitlab-plugin#jenkins-to-gitlab-authentication)
+
+![Jenkins GitLab plugin configuration](img/jenkins_gitlab_plugin_config.png)
+
+## Configure a Jenkins project
+
+Follow the GitLab Plugin documentation about [Jenkins Job Configuration](https://github.com/jenkinsci/gitlab-plugin#jenkins-job-configuration).
+
+NOTE: **Note:**
+Be sure to include the steps about [Build status configuration](https://github.com/jenkinsci/gitlab-plugin#build-status-configuration).
+The 'Publish build status to GitLab' post-build step is required to view
+Jenkins build status in GitLab Merge Requests.
+
+## Configure a GitLab project
+
+Create a new GitLab project or choose an existing one. Then, go to **Integrations ->
+Jenkins CI**.
+
+Check the 'Active' box. Select whether you want GitLab to trigger a build
+on push, Merge Request creation, tag push, or any combination of these. We
+recommend unchecking 'Merge Request events' unless you have a specific use-case
+that requires re-building a commit when a merge request is created. With 'Push
+events' selected, GitLab will build the latest commit on each push and the build
+status will be displayed in the merge request.
+
+Enter the Jenkins URL and Project name. The project name should be URL-friendly
+where spaces are replaced with underscores. To be safe, copy the project name
+from the URL bar of your browser while viewing the Jenkins project.
+
+Optionally, enter a username and password if your Jenkins server requires
+authentication.
+
+![GitLab service settings](img/jenkins_gitlab_service_settings.png)
+
+## Plugin functional overview
+
+GitLab does not contain a database table listing commits. Commits are always
+read from the repository directly. Therefore, it is not possible to retain the
+build status of a commit in GitLab. This is overcome by requesting build
+information from the integrated CI tool. The CI tool is responsible for creating
+and storing build status for Commits and Merge Requests.
+
+### Steps required to implement a similar integration
+
+>**Note:**
+All steps are implemented using AJAX requests on the merge request page.
+
+1. In order to display the build status in a merge request you must create a project service in GitLab.
+2. Your project service will do a (JSON) query to a URL of the CI tool with the SHA1 of the commit.
+3. The project service builds this URL and payload based on project service settings and knowledge of the CI tool.
+4. The response is parsed to give a response in GitLab (success/failed/pending).
+
+## Troubleshooting
+
+### Error in merge requests - "Could not connect to the CI server"
+
+This integration relies on Jenkins reporting the build status back to GitLab via
+the [Commit Status API](../api/commits.md#commit-status).
+
+The error 'Could not connect to the CI server' usually means that GitLab did not
+receive a build status update via the API. Either Jenkins was not properly
+configured or there was an error reporting the status via the API.
+
+1. [Configure the Jenkins server](#configure-the-jenkins-server) for GitLab API access
+2. [Configure a Jenkins project](#configure-a-jenkins-project), including the
+ 'Publish build status to GitLab' post-build action.
diff --git a/doc/integration/jenkins_deprecated.md b/doc/integration/jenkins_deprecated.md
new file mode 100644
index 00000000000..8001c5dbd83
--- /dev/null
+++ b/doc/integration/jenkins_deprecated.md
@@ -0,0 +1,53 @@
+# Jenkins CI (deprecated) service
+
+>**Note:** In GitLab 8.3, Jenkins integration using the
+[GitLab Hook Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+Hook+Plugin)
+was deprecated in favor of the
+[GitLab Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+Plugin).
+Please use documentation for the new [Jenkins CI service](jenkins.md).
+
+Integration includes:
+
+* Trigger Jenkins build after push to repo
+* Show build status on Merge Request page
+
+Requirements:
+
+* [Jenkins GitLab Hook plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+Hook+Plugin)
+* git clone access for Jenkins from GitLab repo (via ssh key)
+
+## Jenkins
+
+1. Install [GitLab Hook plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+Hook+Plugin)
+2. Set up jenkins project
+
+![screen](img/jenkins_project.png)
+
+## GitLab
+
+In GitLab, perform the following steps.
+
+### Read access to repository
+
+Jenkins needs read access to the GitLab repository. We already specified a
+private key to use in Jenkins, now we need to add a public one to the GitLab
+project. For that case we will need a Deploy key. Read the documentation on
+[how to set up a Deploy key](../ssh/README.md#deploy-keys).
+
+### Jenkins service
+
+Now navigate to GitLab services page and activate Jenkins
+
+![screen](img/jenkins_gitlab_service.png)
+
+Done! Now when you push to GitLab - it will create a build for Jenkins.
+And also you will be able to see merge request build status with a link to the Jenkins build.
+
+### Multi-project Configuration
+
+The GitLab Hook plugin in Jenkins supports the automatic creation of a project
+for each feature branch. After configuration GitLab will trigger feature branch
+builds and a corresponding project will be created in Jenkins.
+
+Configure the GitLab Hook plugin in Jenkins. Go to 'Manage Jenkins' and then
+'Configure System'. Find the 'GitLab Web Hook' section and configure as shown below.
diff --git a/doc/integration/jira_development_panel.md b/doc/integration/jira_development_panel.md
new file mode 100644
index 00000000000..703736eeb3c
--- /dev/null
+++ b/doc/integration/jira_development_panel.md
@@ -0,0 +1,141 @@
+# GitLab Jira development panel integration **[PREMIUM]**
+
+> [Introduced][ee-2381] in [GitLab Premium][eep] 10.0.
+
+Complementary to our [existing Jira][existing-jira] project integration, you're now able to integrate
+GitLab projects with [Jira Development Panel][jira-development-panel]. Both can be used
+simultaneously. This works with self-hosted GitLab or GitLab.com integrated with self-hosted Jira
+or cloud Jira.
+
+By doing this you can easily access related GitLab merge requests, branches, and commits directly from a Jira issue.
+
+This integration connects all GitLab projects within a top-level group or a personal namespace to projects in the Jira instance.
+A top-level GitLab group is one that does not have any parent group itself. All the projects of that top-level group,
+as well as projects of the top-level group's subgroups nesting down, are connected. Alternatively, you can specify
+a GitLab personal namespace in the Jira configuration, which will then connect the projects in that personal namespace to Jira.
+
+NOTE: **Note**:
+Note this is different from the [existing Jira][existing-jira] project integration, where the mapping
+is one GitLab project to the entire Jira instance.
+
+We recommend that a GitLab group admin
+or instance admin (in the case of self-hosted GitLab) set up the integration,
+in order to simplify administration.
+
+TIP: **Tip:**
+Create and use a single-purpose "jira" user in GitLab, so that removing
+regular users won't impact your integration.
+
+## Requirements
+
+### Self-hosted GitLab
+
+If you are using self-hosted GitLab, make sure your GitLab instance is accessible by Jira.
+
+- If you are connecting to Jira Cloud, make sure your instance is accessible via the internet.
+- If you are using Jira Server, make sure your instance is accessible however your network is set up.
+
+### GitLab.com
+
+There are no special requirements if you are using GitLab.com.
+
+## GitLab Configuration
+
+1. In GitLab, create a new application in order to allow Jira to connect with your GitLab account
+
+ While logged-in, go to `Settings -> Applications`. (Click your profile avatar at
+ the top right, choose `Settings`, and then navigate to `Applications` from the left
+ navigation menu.) Use the form to create a new application.
+
+ Enter a useful name for the `Name` field.
+
+ For the `Redirect URI` field, enter `https://<your-gitlab-instance-domain>/login/oauth/callback`,
+ replacing `<your-gitlab-instance-domain>` appropriately. So for example, if you are using GitLab.com,
+ this would be `https://gitlab.com/login/oauth/callback`.
+
+ NOTE: **Note**:
+ If using a GitLab version earlier than 11.3 the `Redirect URI` value should be `https://<your-gitlab-instance-domain>/-/jira/login/oauth/callback`.
+
+ ![GitLab Application setup](img/jira_dev_panel_gl_setup_1.png)
+ - Check `api` in the Scopes section.
+
+2. Click `Save application`. You will see the generated 'Application Id' and 'Secret' values.
+ Copy these values that you will use on the Jira configuration side.
+
+## Jira Configuration
+
+1. In Jira, from the gear menu at the top right, go to `Applications`. Navigate to `DVCS accounts`
+ from the left navigation menu. Click `Link GitHub account` to start creating a new integration.
+ (We are pretending to be GitHub in this integration until there is further platform support from Jira.)
+
+ ![Jira DVCS from Dashboard](img/jira_dev_panel_jira_setup_1.png)
+
+2. Complete the form
+
+ Select GitHub Enterprise for the `Host` field.
+
+ For the `Team or User Account` field, enter the relative path of a top-level GitLab group that you have access to,
+ or the relative path of your personal namespace.
+
+ ![Creation of Jira DVCS integration](img/jira_dev_panel_jira_setup_2.png)
+
+ For the `Host URL` field, enter `https://<your-gitlab-instance-domain>/`,
+ replacing `<your-gitlab-instance-domain>` appropriately. So for example, if you are using GitLab.com,
+ this would be `https://gitlab.com/`.
+
+ NOTE: **Note**:
+ If using a GitLab version earlier than 11.3 the `Host URL` value should be `https://<your-gitlab-instance-domain>/-/jira`
+
+ For the `Client ID` field, use the `Application ID` value from the previous section.
+
+ For the `Client Secret` field, use the `Secret` value from the previous section.
+
+ Ensure that the rest of the checkboxes are checked.
+
+3. Click `Add` to complete and create the integration.
+
+ Jira takes up to a few minutes to know about (import behind the scenes) all the commits and branches
+ for all the projects in the GitLab group you specified in the previous step. These are refreshed
+ every 60 minutes.
+
+ > **Note:**
+ > In the future, we plan on implementating real-time integration. If you need
+ > to refresh the data manually, you can do this from the `Applications -> DVCS
+ > accounts` screen where you initially set up the integration:
+ >
+ > ![Refresh GitLab information in Jira](img/jira_dev_panel_manual_refresh.png)
+
+To connect additional GitLab projects from other GitLab top-level groups (or personal namespaces), repeat the above
+steps with additional Jira DVCS accounts.
+
+You may now refer any Jira issue by its ID in branch names, commit messages and merge request names on GitLab's side,
+and you will be able to see the linked `branches`, `commits`, and `merge requests` when entering a Jira issue
+(inside the Jira issue, merge requests will be called "pull requests").
+
+![Branch, Commit and Pull Requests links on Jira issue](img/jira_dev_panel_jira_setup_3.png)
+
+Click the links to see your GitLab repository data.
+
+![GitLab commits details on a Jira issue](img/jira_dev_panel_jira_setup_4.png)
+
+![GitLab merge requests details on a Jira issue](img/jira_dev_panel_jira_setup_5.png)
+
+## Limitations
+
+- This integration is currently not supported on GitLab instances under a [relative url][relative-url] (e.g. `http://example.com/gitlab`).
+
+## Changelog
+
+### 11.10
+
+- [Instance admins can now setup integration for all namespaces](https://gitlab.com/gitlab-org/gitlab-ee/issues/8902)
+
+### 11.1
+
+- [Support GitLab subgroups in Jira development panel](https://gitlab.com/gitlab-org/gitlab-ee/issues/3561)
+
+[existing-jira]: ../user/project/integrations/jira.md
+[jira-development-panel]: https://confluence.atlassian.com/adminjiraserver070/integrating-with-development-tools-776637096.html#Integratingwithdevelopmenttools-Developmentpanelonissues
+[eep]: https://about.gitlab.com/pricing/
+[ee-2381]: https://gitlab.com/gitlab-org/gitlab-ee/issues/2381
+[relative-url]: https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab
diff --git a/doc/integration/kerberos.md b/doc/integration/kerberos.md
new file mode 100644
index 00000000000..44117755b83
--- /dev/null
+++ b/doc/integration/kerberos.md
@@ -0,0 +1,315 @@
+# Kerberos integration **[STARTER ONLY]**
+
+GitLab can integrate with [Kerberos][kerb] as an authentication mechanism.
+
+## Overview
+
+[Kerberos][kerb] is a secure method for authenticating a request for a service in a
+computer network. Kerberos was developed in the Athena Project at the
+[Massachusetts Institute of Technology (MIT)][mit]. The name is taken from Greek
+mythology; Kerberos was a three-headed dog who guarded the gates of Hades.
+
+## Use-cases
+
+- GitLab can be configured to allow your users to sign with their Kerberos credentials.
+- You can use Kerberos to [prevent][why-kerb] anyone from intercepting or eavesdropping on the transmitted password.
+
+## Configuration
+
+For GitLab to offer Kerberos token-based authentication, perform the
+following prerequisites. You still need to configure your system for
+Kerberos usage, such as specifying realms. GitLab will make use of the
+system's Kerberos settings.
+
+### GitLab keytab
+
+1. Create a Kerberos Service Principal for the HTTP service on your GitLab server.
+ If your GitLab server is `gitlab.example.com` and your Kerberos realm
+ `EXAMPLE.COM`, create a Service Principal `HTTP/gitlab.example.com@EXAMPLE.COM`
+ in your Kerberos database.
+1. Create a keytab on the GitLab server for the above Service Principal, e.g.
+ `/etc/http.keytab`.
+
+The keytab is a sensitive file and must be readable by the GitLab user. Set
+ownership and protect the file appropriately:
+
+```
+sudo chown git /etc/http.keytab
+sudo chmod 0600 /etc/http.keytab
+```
+
+### Configure GitLab
+
+**Installations from source**
+
+>**Note:**
+For source installations, make sure the `kerberos` gem group
+[has been installed](../install/installation.md#install-gems).
+
+1. Edit the kerberos section of [gitlab.yml] to enable Kerberos ticket-based
+ authentication. In most cases, you only need to enable Kerberos and specify
+ the location of the keytab:
+
+ ```yaml
+ omniauth:
+ enabled: true
+ allow_single_sign_on: ['kerberos']
+
+ kerberos:
+ # Allow the HTTP Negotiate authentication method for Git clients
+ enabled: true
+
+ # Kerberos 5 keytab file. The keytab file must be readable by the GitLab user,
+ # and should be different from other keytabs in the system.
+ # (default: use default keytab from Krb5 config)
+ keytab: /etc/http.keytab
+ ```
+
+1. [Restart GitLab] for the changes to take effect.
+
+---
+
+**Omnibus package installations**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['omniauth_enabled'] = true
+ gitlab_rails['omniauth_allow_single_sign_on'] = ['kerberos']
+
+ gitlab_rails['kerberos_enabled'] = true
+ gitlab_rails['kerberos_keytab'] = "/etc/http.keytab"
+ ```
+
+1. [Reconfigure GitLab] for the changes to take effect.
+
+---
+
+GitLab will now offer the `negotiate` authentication method for signing in and
+HTTP Git access, enabling Git clients that support this authentication protocol
+to authenticate with Kerberos tokens.
+
+## Creating and linking Kerberos accounts
+
+The Administrative user can navigate to **Admin > Users > Example User > Identities**
+and attach a Kerberos account. Existing GitLab users can go to **Profile > Account**
+and attach a Kerberos account. If you want to allow users without a GitLab
+account to login, you should enable the option `allow_single_sign_on` as
+described in the [Configure GitLab](#configure-gitlab) section. Then, the first
+time a user signs in with Kerberos credentials, GitLab will create a new GitLab
+user associated with the email, which is built from the Kerberos username and
+realm. User accounts will be created automatically when authentication was
+successful.
+
+## Linking Kerberos and LDAP accounts together
+
+If your users log in with Kerberos, but you also have [LDAP integration](../administration/auth/ldap.md)
+enabled, then your users will be automatically linked to their LDAP accounts on
+first login. For this to work, some prerequisites must be met:
+
+The Kerberos username must match the LDAP user's UID. You can choose which LDAP
+attribute is used as the UID in GitLab's [LDAP configuration](../administration/auth/ldap.md#configuration)
+but for Active Directory, this should be `sAMAccountName`.
+
+The Kerberos realm must match the domain part of the LDAP user's Distinguished
+Name. For instance, if the Kerberos realm is `AD.EXAMPLE.COM`, then the LDAP
+user's Distinguished Name should end in `dc=ad,dc=example,dc=com`.
+
+Taken together, these rules mean that linking will only work if your users'
+Kerberos usernames are of the form `foo@AD.EXAMPLE.COM` and their
+LDAP Distinguished Names look like `sAMAccountName=foo,dc=ad,dc=example,dc=com`.
+
+## HTTP Git access
+
+A linked Kerberos account enables you to `git pull` and `git push` using your
+Kerberos account, as well as your standard GitLab credentials.
+
+GitLab users with a linked Kerberos account can also `git pull` and `git push`
+using Kerberos tokens, i.e., without having to send their password with each
+operation.
+
+### HTTP Git access with Kerberos token (passwordless authentication)
+
+#### Support for Git before 2.4
+
+Until Git version 2.4, the `git` command uses only the `negotiate` authentication
+method if the HTTP server offers it, even if this method fails (such as when
+the client does not have a Kerberos token). It is thus not possible to fall back
+to username/password (also known as `basic`) authentication if Kerberos
+authentication fails.
+
+For GitLab users to be able to use either `basic` or `negotiate` authentication
+with older Git versions, it is possible to offer Kerberos ticket-based
+authentication on a different port (e.g. 8443) while the standard port will
+keep offering only `basic` authentication.
+
+**For source installations with HTTPS**
+
+1. Edit the NGINX configuration file for GitLab
+ (e.g., `/etc/nginx/sites-available/gitlab-ssl`) and configure NGINX to
+ listen to port `8443` in addition to the standard HTTPS port:
+
+ ```conf
+ server {
+ listen 0.0.0.0:443 ssl;
+ listen [::]:443 ipv6only=on ssl default_server;
+ listen 0.0.0.0:8443 ssl;
+ listen [::]:8443 ipv6only=on ssl;
+ ```
+
+1. Update the Kerberos section of [gitlab.yml]:
+
+ ```yaml
+ kerberos:
+ # Dedicated port: Git before 2.4 does not fall back to Basic authentication if Negotiate fails.
+ # To support both Basic and Negotiate methods with older versions of Git, configure
+ # nginx to proxy GitLab on an extra port (e.g. 8443) and uncomment the following lines
+ # to dedicate this port to Kerberos authentication. (default: false)
+ use_dedicated_port: true
+ port: 8443
+ https: true
+ ```
+
+1. [Restart GitLab] and NGINX for the changes to take effect.
+
+---
+
+**For Omnibus package installations**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['kerberos_use_dedicated_port'] = true
+ gitlab_rails['kerberos_port'] = 8443
+ gitlab_rails['kerberos_https'] = true
+ ```
+
+1. [Reconfigure GitLab] for the changes to take effect.
+
+---
+
+After this change, all Git remote URLs will have to be updated to
+`https://gitlab.example.com:8443/mygroup/myproject.git` in order to use
+Kerberos ticket-based authentication.
+
+## Upgrading from password-based to ticket-based Kerberos sign-ins
+
+Prior to GitLab 8.10 Enterprise Edition, users had to submit their
+Kerberos username and password to GitLab when signing in. We will
+remove support for password-based Kerberos sign-ins in a future
+release, so we recommend that you upgrade to ticket-based sign-ins.
+
+Depending on your existing GitLab configuration, the 'Sign in with:
+Kerberos Spnego' button may already be visible on your GitLab sign-in
+page. If not, then add the settings [described above](#configuration).
+
+Once you have verified that the 'Kerberos Spnego' button works
+without entering any passwords, you can proceed to disable
+password-based Kerberos sign-ins. To do this you need only need to
+remove the OmniAuth provider named `kerberos` from your `gitlab.yml` /
+`gitlab.rb` file.
+
+**For installations from source**
+
+1. Edit [gitlab.yml] and remove the `- { name: 'kerberos' }` line under omniauth
+ providers:
+
+ ```yaml
+ omniauth:
+ # ...
+ providers:
+ - { name: 'kerberos' } # <-- remove this line
+ ```
+
+1. [Restart GitLab] for the changes to take effect.
+
+---
+
+**For Omnibus installations**
+
+1. Edit `/etc/gitlab/gitlab.rb` and remove the `{ "name" => "kerberos" }` line
+ under `gitlab_rails['omniauth_providers']`:
+
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+ { "name" => "kerberos" } # <-- remove this entry
+ ]
+ ```
+
+1. [Reconfigure GitLab] for the changes to take effect.
+
+## Support for Active Directory Kerberos environments
+
+When using Kerberos ticket-based authentication in an Active Directory domain,
+it may be necessary to increase the maximum header size allowed by NGINX,
+as extensions to the Kerberos protocol may result in HTTP authentication headers
+larger than the default size of 8kB. Configure `large_client_header_buffers`
+to a larger value in [the NGINX configuration][nginx].
+
+## Troubleshooting
+
+### Unsupported GSSAPI mechanism
+
+With Kerberos SPNEGO authentication, the browser is expected to send a list of
+mechanisms it supports to GitLab. If it doesn't support any of the mechanisms
+GitLab supports, authentication will fail with a message like this in the log:
+
+```
+OmniauthKerberosSpnegoController: failed to process Negotiate/Kerberos authentication: gss_accept_sec_context did not return GSS_S_COMPLETE: An unsupported mechanism was requested Unknown error
+```
+
+This is usually seen when the browser is unable to contact the Kerberos server
+directly. It will fall back to an unsupported mechanism known as
+[`IAKERB`](https://k5wiki.kerberos.org/wiki/Projects/IAKERB), which tries to use
+the GitLab server as an intermediary to the Kerberos server.
+
+If you're experiencing this error, ensure there is connectivity between the
+client machine and the Kerberos server - this is a prerequisite! Traffic may be
+blocked by a firewall, or the DNS records may be incorrect.
+
+Another failure mode occurs when the forward and reverse DNS records for the
+GitLab server do not match. Often, Windows clients will work in this case, while
+Linux clients will fail. They use reverse DNS while detecting the Kerberos
+realm. If they get the wrong realm, then ordinary Kerberos mechanisms will fail,
+so the client will fall back to attempting to negotiate `IAKERB`, leading to the
+above error message.
+
+To fix this, ensure that the forward and reverse DNS for your GitLab server
+match. So for instance, if you acces GitLab as `gitlab.example.com`, resolving
+to IP address `1.2.3.4`, then `4.3.2.1.in-addr.arpa` must be a PTR record for
+`gitlab.example.com`.
+
+Finally, it's possible that the browser or client machine lack Kerberos support
+completely. Ensure that the Kerberos libraries are installed and that you can
+authenticate to other Kerberos services.
+
+### HTTP Basic: Access denied when cloning
+
+```sh
+remote: HTTP Basic: Access denied
+fatal: Authentication failed for '<KRB5 path>'
+```
+
+If you are using Git v2.11 or newer and see the above error when cloning, you can
+set the `http.emptyAuth` Git option to `true` to fix this:
+
+```
+git config --global http.emptyAuth true
+```
+
+See also: [Git v2.11 release notes](https://github.com/git/git/blob/master/Documentation/RelNotes/2.11.0.txt#L482-L486)
+
+## Helpful links
+
+- <https://help.ubuntu.com/community/Kerberos>
+- <http://blog.manula.org/2012/04/setting-up-kerberos-server-with-debian.html>
+- <http://www.roguelynn.com/words/explain-like-im-5-kerberos/>
+
+[gitlab.yml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/gitlab.yml.example
+[restart gitlab]: ../administration/restart_gitlab.md#installations-from-source
+[reconfigure gitlab]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
+[nginx]: http://nginx.org/en/docs/http/ngx_http_core_module.html#large_client_header_buffers
+[kerb]: https://web.mit.edu/kerberos/
+[mit]: http://web.mit.edu/
+[why-kerb]: http://web.mit.edu/sipb/doc/working/guide/guide/node20.html
+[ee]: https://about.gitlab.com/pricing/
diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
index 2932c884d04..a13e9f73f48 100644
--- a/doc/integration/omniauth.md
+++ b/doc/integration/omniauth.md
@@ -33,6 +33,9 @@ contains some settings that are common for all providers.
- [Authentiq](../administration/auth/authentiq.md)
- [OAuth2Generic](oauth2_generic.md)
- [JWT](../administration/auth/jwt.md)
+- [OpenID Connect](../administration/auth/oidc.md)
+- [UltraAuth](ultra_auth.md)
+- [SalesForce](salesforce.md)
## Initial OmniAuth Configuration
diff --git a/doc/integration/salesforce.md b/doc/integration/salesforce.md
new file mode 100644
index 00000000000..1ef43cfcece
--- /dev/null
+++ b/doc/integration/salesforce.md
@@ -0,0 +1,79 @@
+# Salesforce OmniAuth Provider
+
+You can integrate your GitLab instance with [Salesforce](https://www.salesforce.com/) to enable users to log in to your GitLab instance with their Salesforce account.
+
+## Create a Salesforce Connected App
+
+To enable Salesforce OmniAuth provider, you must use Salesforce's credentials for your GitLab instance.
+To get the credentials (a pair of Client ID and Client Secret), you must [create a Connected App](https://help.salesforce.com/articleView?id=connected_app_create.htm&type=5) on Salesforce.
+
+1. Sign in to [Salesforce](https://login.salesforce.com/).
+
+1. In Setup, enter `App Manager` in the Quick Find box, click **App Manager**, then click **New Connected App**.
+
+1. Fill in the application details into the following fields:
+ - **Connected App Name** and **API Name**: Set to any value but consider something like `<Organization>'s GitLab`, `<Your Name>'s GitLab`, or something else that is descriptive.
+ - **Contact Email**: Enter the contact email for Salesforce to use when contacting you or your support team.
+ - **Description**: Description for the application.
+
+ ![Salesforce App Details](img/salesforce_app_details.png)
+1. Select **API (Enable OAuth Settings)** and click on **Enable OAuth Settings**.
+1. Fill in the application details into the following fields:
+ - **Callback URL**: The callback URL of your GitLab installation. For example, `https://gitlab.example.com/users/auth/salesforce/callback`.
+ - **Selected OAuth Scopes**: Move **Access your basic information (id, profile, email, address, phone)** and **Allow access to your unique identifier (openid)** to the right column.
+
+ ![Salesforce Oauth App Details](img/salesforce_oauth_app_details.png)
+1. Click **Save**.
+
+1. On your GitLab server, open the configuration file.
+
+ For omnibus package:
+
+ ```sh
+ sudo editor /etc/gitlab/gitlab.rb
+ ```
+
+ For installations from source:
+
+ ```sh
+ cd /home/git/gitlab
+ sudo -u git -H editor config/gitlab.yml
+ ```
+
+1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
+
+1. Add the provider configuration:
+
+ For omnibus package:
+
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ "name" => "salesforce",
+ "app_id" => "SALESFORCE_CLIENT_ID",
+ "app_secret" => "SALESFORCE_CLIENT_SECRET"
+ }
+ ]
+ ```
+
+ For installation from source:
+
+ ```
+ - { name: 'salesforce',
+ app_id: 'SALESFORCE_CLIENT_ID',
+ app_secret: 'SALESFORCE_CLIENT_SECRET'
+ }
+ ```
+1. Change `SALESFORCE_CLIENT_ID` to the Consumer Key from the Salesforce connected application page.
+1. Change `SALESFORCE_CLIENT_SECRET` to the Consumer Secret from the Salesforce connected application page.
+ ![Salesforce App Secret Details](img/salesforce_app_secret_details.png)
+
+1. Save the configuration file.
+1. [Reconfigure GitLab]( ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure ) or [restart GitLab]( ../administration/restart_gitlab.md#installations-from-source ) for the changes to take effect if you installed GitLab via Omnibus or from source respectively.
+
+On the sign in page, there should now be a Salesforce icon below the regular sign in form.
+Click the icon to begin the authentication process. Salesforce will ask the user to sign in and authorize the GitLab application.
+If everything goes well, the user will be returned to GitLab and will be signed in.
+
+NOTE: **Note:**
+GitLab requires the email address of each new user. Once the user is logged in using Salesforce, GitLab will redirect the user to the profile page where they will have to provide the email and verify the email. \ No newline at end of file
diff --git a/doc/integration/saml.md b/doc/integration/saml.md
index 8ee07a7fcdc..22e07594d6f 100644
--- a/doc/integration/saml.md
+++ b/doc/integration/saml.md
@@ -1,5 +1,7 @@
# SAML OmniAuth Provider
+> This topic is for SAML on self-managed GitLab instances. For SAML on GitLab.com, see [SAML SSO for GitLab.com Groups](../user/group/saml_sso/index.md).
+
NOTE: **Note:**
You need to [enable OmniAuth](omniauth.md) in order to use this.
@@ -10,115 +12,115 @@ Microsoft ADFS to authenticate users.
First configure SAML 2.0 support in GitLab, then register the GitLab application
in your SAML IdP:
-1. Make sure GitLab is configured with HTTPS.
- See [Using HTTPS](../install/installation.md#using-https) for instructions.
-
-1. On your GitLab server, open the configuration file.
+1. Make sure GitLab is configured with HTTPS.
+ See [Using HTTPS](../install/installation.md#using-https) for instructions.
+
+1. On your GitLab server, open the configuration file.
- For omnibus package:
+ For omnibus package:
- ```sh
- sudo editor /etc/gitlab/gitlab.rb
- ```
+ ```sh
+ sudo editor /etc/gitlab/gitlab.rb
+ ```
- For installations from source:
+ For installations from source:
- ```sh
- cd /home/git/gitlab
+ ```sh
+ cd /home/git/gitlab
- sudo -u git -H editor config/gitlab.yml
- ```
+ sudo -u git -H editor config/gitlab.yml
+ ```
-1. To allow your users to use SAML to sign up without having to manually create
- an account first, don't forget to add the following values to your configuration:
+1. To allow your users to use SAML to sign up without having to manually create
+ an account first, don't forget to add the following values to your configuration:
- For omnibus package:
+ For omnibus package:
- ```ruby
- gitlab_rails['omniauth_enabled'] = true
- gitlab_rails['omniauth_allow_single_sign_on'] = ['saml']
- gitlab_rails['omniauth_block_auto_created_users'] = false
- ```
+ ```ruby
+ gitlab_rails['omniauth_enabled'] = true
+ gitlab_rails['omniauth_allow_single_sign_on'] = ['saml']
+ gitlab_rails['omniauth_block_auto_created_users'] = false
+ ```
- For installations from source:
+ For installations from source:
- ```yaml
- omniauth:
- enabled: true
- allow_single_sign_on: ["saml"]
- block_auto_created_users: false
- ```
+ ```yaml
+ omniauth:
+ enabled: true
+ allow_single_sign_on: ["saml"]
+ block_auto_created_users: false
+ ```
-1. You can also automatically link SAML users with existing GitLab users if their
- email addresses match by adding the following setting:
+1. You can also automatically link SAML users with existing GitLab users if their
+ email addresses match by adding the following setting:
- For omnibus package:
+ For omnibus package:
- ```ruby
- gitlab_rails['omniauth_auto_link_saml_user'] = true
- ```
+ ```ruby
+ gitlab_rails['omniauth_auto_link_saml_user'] = true
+ ```
- For installations from source:
+ For installations from source:
- ```yaml
- auto_link_saml_user: true
- ```
+ ```yaml
+ auto_link_saml_user: true
+ ```
-1. Add the provider configuration:
+1. Add the provider configuration:
- For omnibus package:
+ For omnibus package:
- ```ruby
- gitlab_rails['omniauth_providers'] = [
- {
- name: 'saml',
- args: {
- assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
- idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
- idp_sso_target_url: 'https://login.example.com/idp',
- issuer: 'https://gitlab.example.com',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'
- },
- label: 'Company Login' # optional label for SAML login button, defaults to "Saml"
- }
- ]
- ```
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ name: 'saml',
+ args: {
+ assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
+ idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
+ idp_sso_target_url: 'https://login.example.com/idp',
+ issuer: 'https://gitlab.example.com',
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'
+ },
+ label: 'Company Login' # optional label for SAML login button, defaults to "Saml"
+ }
+ ]
+ ```
- For installations from source:
-
- ```yaml
- omniauth:
- providers:
- - {
- name: 'saml',
- args: {
- assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
- idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
- idp_sso_target_url: 'https://login.example.com/idp',
- issuer: 'https://gitlab.example.com',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'
- },
- label: 'Company Login' # optional label for SAML login button, defaults to "Saml"
- }
- ```
+ For installations from source:
-1. Change the value for `assertion_consumer_service_url` to match the HTTPS endpoint
- of GitLab (append `users/auth/saml/callback` to the HTTPS URL of your GitLab
- installation to generate the correct value).
+ ```yaml
+ omniauth:
+ providers:
+ - {
+ name: 'saml',
+ args: {
+ assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
+ idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
+ idp_sso_target_url: 'https://login.example.com/idp',
+ issuer: 'https://gitlab.example.com',
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'
+ },
+ label: 'Company Login' # optional label for SAML login button, defaults to "Saml"
+ }
+ ```
-1. Change the values of `idp_cert_fingerprint`, `idp_sso_target_url`,
- `name_identifier_format` to match your IdP. If a fingerprint is used it must
- be a SHA1 fingerprint; check
- [the omniauth-saml documentation](https://github.com/omniauth/omniauth-saml)
- for more details on these options.
+1. Change the value for `assertion_consumer_service_url` to match the HTTPS endpoint
+ of GitLab (append `users/auth/saml/callback` to the HTTPS URL of your GitLab
+ installation to generate the correct value).
-1. Change the value of `issuer` to a unique name, which will identify the application
- to the IdP.
+1. Change the values of `idp_cert_fingerprint`, `idp_sso_target_url`,
+ `name_identifier_format` to match your IdP. If a fingerprint is used it must
+ be a SHA1 fingerprint; check
+ [the omniauth-saml documentation](https://github.com/omniauth/omniauth-saml)
+ for more details on these options.
-1. For the changes to take effect, you must [reconfigure][] GitLab if you installed via Omnibus or [restart GitLab][] if you installed from source.
+1. Change the value of `issuer` to a unique name, which will identify the application
+ to the IdP.
-1. Register the GitLab SP in your SAML 2.0 IdP, using the application name specified
- in `issuer`.
+1. For the changes to take effect, you must [reconfigure][] GitLab if you installed via Omnibus or [restart GitLab][] if you installed from source.
+
+1. Register the GitLab SP in your SAML 2.0 IdP, using the application name specified
+ in `issuer`.
To ease configuration, most IdP accept a metadata URL for the application to provide
configuration information to the IdP. To build the metadata URL for GitLab, append
@@ -185,6 +187,78 @@ tell GitLab which groups are external via the `external_groups:` element:
} }
```
+## Required groups
+
+>**Note:**
+This setting is only available on GitLab 10.2 EE and above.
+
+This setting works like `External Groups` setting. Just like there, your IdP has to
+pass Group Information to GitLab, you have to tell GitLab where to look or the
+groups SAML response, and which group membership should be requisite for logging in.
+When `required_groups` is not set or it is empty, anyone with proper authentication
+will be able to use the service.
+
+Example:
+
+```yaml
+{ name: 'saml',
+ label: 'Our SAML Provider',
+ groups_attribute: 'Groups',
+ required_groups: ['Developers', 'Managers', 'Admins'],
+ args: {
+ assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
+ idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
+ idp_sso_target_url: 'https://login.example.com/idp',
+ issuer: 'https://gitlab.example.com',
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
+ } }
+```
+
+## Admin Groups
+
+>**Note:**
+This setting is only available on GitLab 8.8 EE and above.
+
+This setting works very similarly to the `External Groups` setting. The requirements
+are the same, your IdP needs to pass Group information to GitLab, you need to tell
+GitLab where to look for the groups in the SAML response, and which group should be
+considered `admin groups`.
+
+```yaml
+{ name: 'saml',
+ label: 'Our SAML Provider',
+ groups_attribute: 'Groups',
+ admin_groups: ['Managers', 'Admins'],
+ args: {
+ assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
+ idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
+ idp_sso_target_url: 'https://login.example.com/idp',
+ issuer: 'https://gitlab.example.com',
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
+ } }
+```
+
+## Auditor Groups
+
+>**Note:**
+This setting is only available on GitLab 11.4 EE and above.
+
+This setting also follows the requirements documented for the `External Groups` setting. GitLab uses the Group information provided by your IdP to determine if a user should be assigned the `auditor` role.
+
+```yaml
+{ name: 'saml',
+ label: 'Our SAML Provider',
+ groups_attribute: 'Groups',
+ auditor_groups: ['Auditors', 'Security'],
+ args: {
+ assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
+ idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
+ idp_sso_target_url: 'https://login.example.com/idp',
+ issuer: 'https://gitlab.example.com',
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
+ } }
+```
+
## Bypass two factor authentication
If you want some SAML authentication methods to count as 2FA on a per session basis, you can register them in the
@@ -194,28 +268,28 @@ If you want some SAML authentication methods to count as 2FA on a per session ba
1. Edit `/etc/gitlab/gitlab.rb`:
- ```ruby
- gitlab_rails['omniauth_providers'] = [
- {
- name: 'saml',
- args: {
- assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
- idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
- idp_sso_target_url: 'https://login.example.com/idp',
- issuer: 'https://gitlab.example.com',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
- upstream_two_factor_authn_contexts:
- %w(
- urn:oasis:names:tc:SAML:2.0:ac:classes:CertificateProtectedTransport
- urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorOTPSMS
- urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorIGTOKEN
- )
-
- },
- label: 'Company Login' # optional label for SAML login button, defaults to "Saml"
- }
- ]
- ```
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ name: 'saml',
+ args: {
+ assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
+ idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
+ idp_sso_target_url: 'https://login.example.com/idp',
+ issuer: 'https://gitlab.example.com',
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
+ upstream_two_factor_authn_contexts:
+ %w(
+ urn:oasis:names:tc:SAML:2.0:ac:classes:CertificateProtectedTransport
+ urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorOTPSMS
+ urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorIGTOKEN
+ )
+
+ },
+ label: 'Company Login' # optional label for SAML login button, defaults to "Saml"
+ }
+ ]
+ ```
1. Save the file and [reconfigure][] GitLab for the changes to take effect.
@@ -225,27 +299,27 @@ If you want some SAML authentication methods to count as 2FA on a per session ba
1. Edit `config/gitlab.yml`:
- ```yaml
- omniauth:
- providers:
- - {
- name: 'saml',
- args: {
- assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
- idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
- idp_sso_target_url: 'https://login.example.com/idp',
- issuer: 'https://gitlab.example.com',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
- upstream_two_factor_authn_contexts:
- [
- 'urn:oasis:names:tc:SAML:2.0:ac:classes:CertificateProtectedTransport',
- 'urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorOTPSMS',
- 'urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorIGTOKEN'
- ]
- },
- label: 'Company Login' # optional label for SAML login button, defaults to "Saml"
- }
- ```
+ ```yaml
+ omniauth:
+ providers:
+ - {
+ name: 'saml',
+ args: {
+ assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
+ idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
+ idp_sso_target_url: 'https://login.example.com/idp',
+ issuer: 'https://gitlab.example.com',
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
+ upstream_two_factor_authn_contexts:
+ [
+ 'urn:oasis:names:tc:SAML:2.0:ac:classes:CertificateProtectedTransport',
+ 'urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorOTPSMS',
+ 'urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorIGTOKEN'
+ ]
+ },
+ label: 'Company Login' # optional label for SAML login button, defaults to "Saml"
+ }
+ ```
1. Save the file and [restart GitLab][] for the changes ot take effect
diff --git a/doc/integration/slash_commands.md b/doc/integration/slash_commands.md
index cd755089be8..71ea2e25533 100644
--- a/doc/integration/slash_commands.md
+++ b/doc/integration/slash_commands.md
@@ -20,8 +20,8 @@ Taking the trigger term as `project-name`, the commands are:
| `/project-name deploy <from> to <to>` | Deploy from the `<from>` environment to the `<to>` environment |
| `/project-name run <job name> <arguments>` | Execute [ChatOps](../ci/chatops/README.md) job `<job name>` on `master` |
-Note that if you are using the [GitLab Slack application](https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html) for
-your GitLab.com projects, you need to [add the `gitlab` keyword at the beginning of the command](https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html#usage).
+Note that if you are using the [GitLab Slack application](../user/project/integrations/gitlab_slack_application.md) for
+your GitLab.com projects, you need to [add the `gitlab` keyword at the beginning of the command](../user/project/integrations/gitlab_slack_application.md#usage).
## Issue commands
diff --git a/doc/integration/ultra_auth.md b/doc/integration/ultra_auth.md
new file mode 100644
index 00000000000..139cca456aa
--- /dev/null
+++ b/doc/integration/ultra_auth.md
@@ -0,0 +1,78 @@
+# UltraAuth OmniAuth Provider
+
+You can integrate your GitLab instance with [UltraAuth](https://ultraauth.com) to enable users to perform secure biometric authentication to your GitLab instance with your UltraAuth account. Users have to perform the biometric authentication using their mobile device with fingerprint sensor.
+
+## Create UltraAuth Application
+
+To enable UltraAuth OmniAuth provider, you must use UltraAuth's credentials for your GitLab instance.
+To get the credentials (a pair of Client ID and Client Secret), you must register an application on UltraAuth.
+
+1. Sign in to [UltraAuth](https://ultraauth.com).
+1. Navigate to [Create an App](https://ultraauth.com/select-strategy) and click on "Ruby on Rails".
+1. Scroll down the page that is displayed to locate the **Client ID** and **Client Secret**.
+ Keep this page open as you continue configuration.
+ ![UltraAuth Credentials: OPENID_CLIENT_ID and OPENID_CLIENT_SECRET](img/ultra_auth_credentials.png)
+1. Click on "Edit Callback URL" link.
+ ![Edit UltraAuth Callback URL](img/ultra_auth_edit_callback_url_highlighted.png)
+1. The callback URL will be `http(s)://<your_domain>/users/auth/ultraauth/callback`
+ ![UltraAuth Callback URL](img/ultra_auth_edit_callback_url.png)
+1. Select **Register application**.
+1. On your GitLab server, open the configuration file.
+
+ For omnibus package:
+
+ ```sh
+ sudo editor /etc/gitlab/gitlab.rb
+ ```
+
+ For installations from source:
+
+ ```sh
+ cd /home/git/gitlab
+ sudo -u git -H editor config/gitlab.yml
+ ```
+1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
+1. Add the provider configuration:
+
+ For omnibus package:
+
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ "name" => "ultraauth",
+ "app_id" => "OPENID_CLIENT_ID",
+ "app_secret" => "OPENID_CLIENT_SECRET",
+ "args" => {
+ "client_options" => {
+ "redirect_uri" => "https://example.com/users/auth/ultraauth/callback"
+ }
+ }
+ }
+ ]
+ ```
+
+ For installation from source:
+
+ ```
+ - { name: 'ultraauth',
+ app_id: 'OPENID_CLIENT_ID',
+ app_secret: 'OPENID_CLIENT_SECRET',
+ args: {
+ client_options: {
+ redirect_uri: 'https://example.com/users/auth/ultraauth/callback'
+ }
+ }
+ }
+ ```
+ __Replace `https://example.com/users/auth/ultraauth/callback` with your application's Callback URL.__
+1. Change `OPENID_CLIENT_ID` to the Client ID from the UltraAuth application page.
+1. Change `OPENID_CLIENT_SECRET` to the Client Secret from the UltraAuth application page.
+1. Save the configuration file.
+1. [Reconfigure GitLab]( ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure ) or [restart GitLab]( ../administration/restart_gitlab.md#installations-from-source ) for the changes to take effect if you
+ installed GitLab via Omnibus or from source respectively.
+
+On the sign in page, there should now be a UltraAuth icon below the regular sign in form.
+Click the icon to begin the authentication process. UltraAuth will ask the user to sign in and authorize the GitLab application.
+If everything goes well, the user will be returned to GitLab and will be signed in.
+
+**Note:** GitLab requires the email address of each new user. Once the user is logged in using UltraAuth, GitLab will redirect the user to the profile page where they will have to provide the email and verify the email.
diff --git a/doc/legal/corporate_contributor_license_agreement.md b/doc/legal/corporate_contributor_license_agreement.md
index e5fc7a3c85f..7f08188bd65 100644
--- a/doc/legal/corporate_contributor_license_agreement.md
+++ b/doc/legal/corporate_contributor_license_agreement.md
@@ -1,3 +1,29 @@
----
-redirect_to: 'README.md'
----
+# Corporate contributor license agreement
+
+You accept and agree to the following terms and conditions for Your present and future Contributions submitted to GitLab B.V.. Except for the license granted herein to GitLab B.V. and recipients of software distributed by GitLab B.V., You reserve all right, title, and interest in and to Your Contributions.
+
+1. Definitions.
+
+ "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with GitLab B.V.. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "Contribution" shall mean the code, documentation or other original works of authorship, including any modifications or additions to an existing work, that is submitted by You to GitLab B.V. for inclusion in, or documentation of, any of the products owned or managed by GitLab B.V. (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to GitLab B.V. or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, GitLab B.V. for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution."
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed.
+
+4. You represent that You are legally entitled to grant the above license. You represent further that each of Your employees is authorized to submit Contributions on Your behalf, but excluding employees that are designated in writing by You as "Not authorized to submit Contributions on behalf of [name of Your corporation here]." Such designations of exclusion for unauthorized employees are to be submitted via email to legal@gitlab.com.
+
+5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others).
+
+6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
+
+7. Should You wish to submit work that is not Your original creation, You may submit it to GitLab B.V. separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]".
+
+8. It is Your responsibility to notify GitLab.com when any change is required to the list of designated employees excluded from submitting Contributions on Your behalf per Section 4. Such notification should be sent via email to legal@gitlab.com.
+
+This text is licensed under the [Creative Commons Attribution 3.0 License](https://creativecommons.org/licenses/by/3.0/) and the original source is the Google Open Source Programs Office.
diff --git a/doc/legal/individual_contributor_license_agreement.md b/doc/legal/individual_contributor_license_agreement.md
index e5fc7a3c85f..59803aea080 100644
--- a/doc/legal/individual_contributor_license_agreement.md
+++ b/doc/legal/individual_contributor_license_agreement.md
@@ -1,3 +1,25 @@
----
-redirect_to: 'README.md'
----
+# Individual contributor license agreement
+
+You accept and agree to the following terms and conditions for Your present and future Contributions submitted to GitLab B.V.. Except for the license granted herein to GitLab B.V. and recipients of software distributed by GitLab B.V., You reserve all right, title, and interest in and to Your Contributions.
+
+1. Definitions.
+
+ "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with GitLab B.V.. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to GitLab B.V. for inclusion in, or documentation of, any of the products owned or managed by GitLab B.V. (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to GitLab B.V. or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, GitLab B.V. for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution."
+
+2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works.
+
+3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to GitLab B.V. and to recipients of software distributed by GitLab B.V. a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed.
+
+4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to GitLab B.V., or that your employer has executed a separate Corporate CLA with GitLab B.V..
+
+5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions.
+
+6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
+
+7. Should You wish to submit work that is not Your original creation, You may submit it to GitLab B.V. separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [insert_name_here]".
+
+8. You agree to notify GitLab B.V. of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect.
+
+This text is licensed under the [Creative Commons Attribution 3.0 License](https://creativecommons.org/licenses/by/3.0/) and the original source is the Google Open Source Programs Office.
diff --git a/doc/license/README.md b/doc/license/README.md
new file mode 100644
index 00000000000..fd110a39b61
--- /dev/null
+++ b/doc/license/README.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../user/admin_area/license.md'
+---
+
+This document was moved to [another location](../user/admin_area/license.md).
diff --git a/doc/migrate_ci_to_ce/README.md b/doc/migrate_ci_to_ce/README.md
index 4c4b423f40f..7659b743311 100644
--- a/doc/migrate_ci_to_ce/README.md
+++ b/doc/migrate_ci_to_ce/README.md
@@ -1,3 +1,7 @@
+---
+type: howto
+---
+
# Migrate GitLab CI to GitLab CE or EE
Beginning with version 8.0 of GitLab Community Edition (CE) and Enterprise
@@ -333,7 +337,9 @@ restoration](../raketasks/backup_restore.md) guide.
## Troubleshooting
### show:secrets problem (Omnibus-only)
+
If you see errors like this:
+
```
Missing `secret_key_base` or `db_key_base` for 'production' environment. The secrets will be generated and stored in `config/secrets.yml`
rake aborted!
@@ -344,6 +350,7 @@ This can happen if you are updating from versions prior to 7.13 straight to 8.0.
The fix for this is to update to Omnibus 7.14 first and then update it to 8.0.
### Permission denied when accessing /var/opt/gitlab/gitlab-ci/builds
+
To fix that issue you have to change builds/ folder permission before doing final backup:
```
sudo chown -R gitlab-ci:gitlab-ci /var/opt/gitlab/gitlab-ci/builds
@@ -355,8 +362,10 @@ sudo chown git:git /var/opt/gitlab/gitlab-ci/builds
```
### Problems when importing CI database to GitLab
+
If you were migrating CI database from MySQL to PostgreSQL manually you can see errors during import about missing sequences:
-```
+
+```sql
ALTER SEQUENCE
ERROR: relation "ci_builds_id_seq" does not exist
ERROR: relation "ci_commits_id_seq" does not exist
@@ -373,9 +382,9 @@ CREATE TABLE
To fix that you need to apply this SQL statement before doing final backup:
-```sql
-## Omnibus GitLab
+Omnibus GitLab installations:
+```sql
gitlab-ci-rails dbconsole <<EOF
-- ALTER TABLES - DROP DEFAULTS
ALTER TABLE ONLY ci_application_settings ALTER COLUMN id DROP DEFAULT;
@@ -428,9 +437,11 @@ ALTER TABLE ONLY ci_triggers ALTER COLUMN id SET DEFAULT nextval('ci_triggers_id
ALTER TABLE ONLY ci_variables ALTER COLUMN id SET DEFAULT nextval('ci_variables_id_seq'::regclass);
ALTER TABLE ONLY ci_web_hooks ALTER COLUMN id SET DEFAULT nextval('ci_web_hooks_id_seq'::regclass);
EOF
+```
-## Source installations
+Source installations:
+```
cd /home/gitlab_ci/gitlab-ci
sudo -u gitlab_ci -H bundle exec rails dbconsole production <<EOF
... COPY SQL STATEMENTS FROM ABOVE ...
diff --git a/doc/monitoring/performance/img/grafana_dashboard_dropdown.png b/doc/monitoring/performance/img/grafana_dashboard_dropdown.png
deleted file mode 100644
index 51eef90068d..00000000000
--- a/doc/monitoring/performance/img/grafana_dashboard_dropdown.png
+++ /dev/null
Binary files differ
diff --git a/doc/monitoring/performance/img/grafana_dashboard_import.png b/doc/monitoring/performance/img/grafana_dashboard_import.png
deleted file mode 100644
index fd639ee0eb8..00000000000
--- a/doc/monitoring/performance/img/grafana_dashboard_import.png
+++ /dev/null
Binary files differ
diff --git a/doc/monitoring/performance/img/grafana_data_source_configuration.png b/doc/monitoring/performance/img/grafana_data_source_configuration.png
deleted file mode 100644
index a98e0ed1e7d..00000000000
--- a/doc/monitoring/performance/img/grafana_data_source_configuration.png
+++ /dev/null
Binary files differ
diff --git a/doc/monitoring/performance/img/grafana_data_source_empty.png b/doc/monitoring/performance/img/grafana_data_source_empty.png
deleted file mode 100644
index 549ada8343e..00000000000
--- a/doc/monitoring/performance/img/grafana_data_source_empty.png
+++ /dev/null
Binary files differ
diff --git a/doc/monitoring/performance/img/grafana_save_icon.png b/doc/monitoring/performance/img/grafana_save_icon.png
deleted file mode 100644
index 68a071f5ae2..00000000000
--- a/doc/monitoring/performance/img/grafana_save_icon.png
+++ /dev/null
Binary files differ
diff --git a/doc/monitoring/performance/img/metrics_gitlab_configuration_settings.png b/doc/monitoring/performance/img/metrics_gitlab_configuration_settings.png
deleted file mode 100644
index b9563a00e97..00000000000
--- a/doc/monitoring/performance/img/metrics_gitlab_configuration_settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md
index 1d656574acd..72bace3d282 100644
--- a/doc/policy/maintenance.md
+++ b/doc/policy/maintenance.md
@@ -1,8 +1,15 @@
-# GitLab Maintenance Policy
+---
+type: concepts
+---
+
+# GitLab Release and Maintenance Policy
+
+GitLab has strict policies governing version naming, as well as release pace for major, minor,
+patch and security releases. New releases are usually announced on the [GitLab blog](https://about.gitlab.com/blog/categories/releases/).
## Versioning
-GitLab follows the [Semantic Versioning](http://semver.org/) for its releases:
+GitLab uses [Semantic Versioning](http://semver.org/) for its releases:
`(Major).(Minor).(Patch)` in a [pragmatic way](https://gist.github.com/jashkenas/cbd2b088e20279ae2c8e).
For example, for GitLab version 10.5.7:
@@ -15,9 +22,9 @@ Any part of the version number can increment into multiple digits, for example,
The following table describes the version types and their release cadence:
-| Version type | Description | Cadence |
-|:-------------|:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Major | For significant changes, or when any backward-incompatible changes are introduced to the public API. | Yearly. The next major release is GitLab 12.0 on June 22, 2019. Subsequent major releases will be scheduled for May 22 each year, by default. | |
+| Version type | Description | Cadence |
+|:-------------|:------------|:--------|
+| Major | For significant changes, or when any backward-incompatible changes are introduced to the public API. | Yearly. The next major release is GitLab 12.0 on June 22, 2019. Subsequent major releases will be scheduled for May 22 each year, by default. |
| Minor | For when new backward-compatible functionality is introduced to the public API, a minor feature is introduced, or when a set of smaller features is rolled out. | Monthly on the 22nd. |
| Patch | For backward-compatible bug fixes that fix incorrect behavior. See [Patch releases](#patch-releases). | As needed. |
@@ -75,10 +82,10 @@ that could change behavior in the next major release.
Please see the table below for some examples:
| Latest stable version | Your version | Recommended upgrade path | Note |
-| -------------- | ------------ | ------------------------ | ---------------- |
-| 9.4.5 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.4.5` | `8.17.7` is the last version in version `8` |
-| 10.1.4 | 8.13.4 | `8.13.4 -> 8.17.7 -> 9.5.10 -> 10.1.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9` |
-| 11.3.4 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9`, `10.8.7` is the last version in version `10` |
+| --------------------- | ------------ | ------------------------ | ---- |
+| 9.4.5 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.4.5` | `8.17.7` is the last version in version `8` |
+| 10.1.4 | 8.13.4 | `8.13.4 -> 8.17.7 -> 9.5.10 -> 10.1.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9` |
+| 11.3.4 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9`, `10.8.7` is the last version in version `10` |
More information about the release procedures can be found in our
[release documentation](https://gitlab.com/gitlab-org/release/docs). You may also want to read our
diff --git a/doc/public_access/public_access.md b/doc/public_access/public_access.md
index 8601551e3bd..b1637181855 100644
--- a/doc/public_access/public_access.md
+++ b/doc/public_access/public_access.md
@@ -1,13 +1,12 @@
-# Public access
-
-GitLab allows [Owners](../user/permissions.md) to change a projects' visibility in order to be accessed
-**publicly** or **internally**.
+---
+type: reference
+---
-Projects with either of these visibility levels will be listed in the
-public access directory (`/public` under your GitLab instance).
-Here is the [GitLab.com example](https://gitlab.com/public).
+# Public access
-Internal projects will only be available to authenticated users.
+GitLab allows [Owners](../user/permissions.md) to set a projects' visibility as **public**, **internal**
+or **private**. These visibility levels affect who can see the project in the
+public access directory (`/public` under your GitLab instance), like at [https://gitlab.com/public]().
## Visibility of projects
@@ -15,26 +14,26 @@ Internal projects will only be available to authenticated users.
Public projects can be cloned **without any** authentication.
-They will also be listed on the public access directory (`/public`).
+They will be listed in the public access directory (`/public`) for all users.
-**Any logged in user** will have [Guest](../user/permissions.md)
-permissions on the repository.
+**Any logged in user** will have [Guest permissions](../user/permissions.md)
+on the repository.
### Internal projects
Internal projects can be cloned by any logged in user.
-They will also be listed on the public access directory (`/public`) for logged
+They will also be listed in the public access directory (`/public`), but only for logged
in users.
-Any logged in user will have [Guest](../user/permissions.md) permissions
+Any logged in user will have [Guest permissions](../user/permissions.md)
on the repository.
### Private projects
-Private projects can only be cloned and viewed by project members, and
-they will only appear to project members on the public access directory
-(`https://gitlab.example.com/public`).
+Private projects can only be cloned and viewed by project members.
+
+They will appear in the public access directory (`/public`) for project members only.
### How to change project visibility
@@ -43,10 +42,10 @@ they will only appear to project members on the public access directory
## Visibility of groups
->**Note:**
-[Starting with][3323] GitLab 8.6, the group visibility has changed and can be
-configured the same way as projects. In previous versions, a group's page was
-always visible to all users.
+NOTE: **Note:**
+[Starting with](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3323) GitLab 8.6,
+the group visibility has changed and can be configured the same way as projects.
+In previous versions, a group's page was always visible to all users.
Like with projects, the visibility of a group can be set to dictate whether
anonymous users, all signed in users, or only explicit group members can view
@@ -54,8 +53,6 @@ it. The restriction for visibility levels on the application setting level also
applies to groups, so if that's set to internal, the explore page will be empty
for anonymous users. The group page now has a visibility level icon.
-[3323]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3323
-
## Visibility of users
The public page of a user, located at `/username`, is always visible whether
@@ -76,3 +73,15 @@ snippet:
This is useful to prevent people exposing their repositories to public
by accident. The restricted visibility settings do not apply to admin users.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/push_rules/push_rules.md b/doc/push_rules/push_rules.md
new file mode 100644
index 00000000000..b2d626a0a74
--- /dev/null
+++ b/doc/push_rules/push_rules.md
@@ -0,0 +1,173 @@
+---
+type: reference, howto
+---
+
+# Push Rules **[STARTER]**
+
+Gain additional control over what can and can't be pushed to your repository by using
+regular expressions to reject pushes based on commit contents, branch names or file details.
+
+## Overview
+
+GitLab already offers [protected branches][protected-branches], but there are
+cases when you need some specific rules like preventing git tag removal or
+enforcing a special format for commit messages.
+
+Push rules are essentially [pre-receive Git hooks][hooks] that are easy to
+enable in a user-friendly interface. They are defined globally if you are an
+admin or per project so you can have different rules applied to different
+projects depending on your needs.
+
+## Use cases
+
+Every push rule could have its own use case, but let's consider some examples.
+
+### Commit messages with a specific reference
+
+Let's assume you have the following requirements for your workflow:
+
+- every commit should reference a JIRA issue, for example: `Refactored css. Fixes JIRA-123.`
+- users should not be able to remove git tags with `git push`
+
+All you need to do is write a simple regular expression that requires the mention
+of a JIRA issue in the commit message, like `JIRA\-\d+`.
+
+Now when a user tries to push a commit with a message `Bugfix`, their push will
+be declined. Only pushing commits with messages like `Bugfix according to JIRA-123`
+will be accepted.
+
+### Restrict branch names
+
+Let's assume there's a strict policy for branch names in your company, and
+you want the branches to start with a certain name because you have different
+GitLab CI jobs (`feature`, `hotfix`, `docker`, `android`, etc.) that rely on the
+branch name.
+
+Your developers however, don't always remember that policy, so they push
+various branches and CI pipelines do not work as expected. By restricting the
+branch names globally in Push Rules, you can now sleep without the anxiety
+of your developers' mistakes. Every branch that doesn't match your push rule
+will get rejected.
+
+## Enabling push rules
+
+NOTE: **Note:**
+GitLab administrators can set push rules globally under
+**Admin area > Push Rules** that all new projects will inherit. You can later
+override them in a project's settings.
+
+1. Navigate to your project's **Settings > Repository** and expand **Push Rules**
+1. Set the rule you want
+1. Click **Save Push Rules** for the changes to take effect
+
+The following options are available.
+
+| Push rule | GitLab version | Description |
+| --------- | :------------: | ----------- |
+| Removal of tags with `git push` | **Starter** 7.10 | Forbid users to remove git tags with `git push`. Tags will still be able to be deleted through the web UI. |
+| Check whether author is a GitLab user | **Starter** 7.10 | Restrict commits by author (email) to existing GitLab users. |
+| Committer restriction | **Premium** 10.2 | GitLab will reject any commit that was not committed by the current authenticated user |
+| Check whether commit is signed through GPG | **Premium** 10.1 | Reject commit when it is not signed through GPG. Read [signing commits with GPG][signing-commits]. |
+| Prevent committing secrets to Git | **Starter** 8.12 | GitLab will reject any files that are likely to contain secrets. Read [what files are forbidden](#prevent-pushing-secrets-to-the-repository). |
+| Restrict by commit message | **Starter** 7.10 | Only commit messages that match this regular expression are allowed to be pushed. Leave empty to allow any commit message. Uses multiline mode, which can be disabled using `(?-m)`. |
+| Restrict by commit message (negative match)| **Starter** 11.1 | Only commit messages that do not match this regular expression are allowed to be pushed. Leave empty to allow any commit message. Uses multiline mode, which can be disabled using `(?-m)`. |
+| Restrict by branch name | **Starter** 9.3 | Only branch names that match this regular expression are allowed to be pushed. Leave empty to allow any branch name. |
+| Restrict by commit author's email | **Starter** 7.10 | Only commit author's email that match this regular expression are allowed to be pushed. Leave empty to allow any email. |
+| Prohibited file names | **Starter** 7.10 | Any committed filenames that match this regular expression are not allowed to be pushed. Leave empty to allow any filenames. |
+| Maximum file size | **Starter** 7.12 | Pushes that contain added or updated files that exceed this file size (in MB) are rejected. Set to 0 to allow files of any size. |
+
+TIP: **Tip:**
+GitLab uses [RE2 syntax](https://github.com/google/re2/wiki/Syntax) for regular expressions in push rules, and you can test them at the [GoLang regex tester](https://regex-golang.appspot.com).
+
+## Prevent pushing secrets to the repository
+
+> [Introduced][ee-385] in [GitLab Starter][ee] 8.12.
+
+You can turn on a predefined blacklist of files which won't be allowed to be
+pushed to a repository.
+
+By selecting the checkbox *Prevent committing secrets to Git*, GitLab prevents
+pushes to the repository when a file matches a regular expression as read from
+[`files_blacklist.yml`][list] (make sure you are at the right branch
+as your GitLab version when viewing this file).
+
+NOTE: **Note:**
+Files already committed won't get restricted by this push rule.
+
+Below is an example list of what will be rejected by these regular expressions:
+
+```shell
+#####################
+# AWS CLI credential blobs
+#####################
+.aws/credentials
+aws/credentials
+homefolder/aws/credentials
+
+#####################
+# Private RSA SSH keys
+#####################
+/ssh/id_rsa
+/.ssh/personal_rsa
+/config/server_rsa
+id_rsa
+.id_rsa
+
+#####################
+# Private DSA SSH keys
+#####################
+/ssh/id_dsa
+/.ssh/personal_dsa
+/config/server_dsa
+id_dsa
+.id_dsa
+
+#####################
+# Private ed25519 SSH keys
+#####################
+/ssh/id_ed25519
+/.ssh/personal_ed25519
+/config/server_ed25519
+id_ed25519
+.id_ed25519
+
+#####################
+# Private ECDSA SSH keys
+#####################
+/ssh/id_ecdsa
+/.ssh/personal_ecdsa
+/config/server_ecdsa
+id_ecdsa
+.id_ecdsa
+
+#####################
+# Any file with .pem or .key extensions
+#####################
+*.pem
+*.key
+
+#####################
+# Any file ending with _history or .history extension
+#####################
+pry.history
+bash_history
+```
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
+
+[protected-branches]: ../user/project/protected_branches.md
+[signing-commits]: ../user/project/repository/gpg_signed_commits/index.md
+[ee-385]: https://gitlab.com/gitlab-org/gitlab-ee/issues/385
+[list]: https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/gitlab/checks/files_blacklist.yml
+[hooks]: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
+[ee]: https://about.gitlab.com/pricing/
diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md
index 56db7b5eb3a..764916ca82d 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -917,9 +917,9 @@ backup beforehand.
1. Clear all the tokens for projects, groups, and the whole instance:
-CAUTION: **Caution:**
-The last UPDATE operation will stop the runners being able to pick up
-new jobs. You must register new runners.
+ CAUTION: **Caution:**
+ The last UPDATE operation will stop the runners being able to pick up
+ new jobs. You must register new runners.
```sql
-- Clear project tokens
diff --git a/doc/raketasks/cleanup.md b/doc/raketasks/cleanup.md
index e70a009323e..f5c788af578 100644
--- a/doc/raketasks/cleanup.md
+++ b/doc/raketasks/cleanup.md
@@ -23,6 +23,16 @@ sudo gitlab-rake gitlab:cleanup:repos
bundle exec rake gitlab:cleanup:repos RAILS_ENV=production
```
+Remove old repository copies from repositories moved to another storage.
+
+```
+# omnibus-gitlab
+sudo gitlab-rake gitlab:cleanup:moved
+
+# installation from source
+bundle exec rake gitlab:cleanup:moved RAILS_ENV=production
+```
+
Clean up local project upload files if they don't exist in GitLab database. The
task attempts to fix the file if it can find its project, otherwise it moves the
file to a lost and found directory.
diff --git a/doc/raketasks/import.md b/doc/raketasks/import.md
index bb316df5b9a..b59c06a24ea 100644
--- a/doc/raketasks/import.md
+++ b/doc/raketasks/import.md
@@ -16,7 +16,7 @@
The new folder needs to have git user ownership and read/write/execute access for git user and its group:
```
-sudo -u git mkdir /var/opt/gitlab/git-data/repository-import-<date>/new_group
+sudo -u git mkdir -p /var/opt/gitlab/git-data/repository-import-<date>/new_group
```
### Copy your bare repositories inside this newly created folder:
diff --git a/doc/security/README.md b/doc/security/README.md
index a90127e0356..c48d5bc2065 100644
--- a/doc/security/README.md
+++ b/doc/security/README.md
@@ -1,5 +1,6 @@
---
comments: false
+type: index
---
# Security
diff --git a/doc/security/crime_vulnerability.md b/doc/security/crime_vulnerability.md
index d61a205d954..9665cc0337f 100644
--- a/doc/security/crime_vulnerability.md
+++ b/doc/security/crime_vulnerability.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# How we manage the TLS protocol CRIME vulnerability
> CRIME ("Compression Ratio Info-leak Made Easy") is a security exploit against
@@ -7,15 +11,15 @@ authentication cookies, it allows an attacker to perform session hijacking on an
authenticated web session, allowing the launching of further attacks.
([CRIME](https://en.wikipedia.org/w/index.php?title=CRIME&oldid=692423806))
-### Description
+## Description
-The TLS Protocol CRIME Vulnerability affects compression over HTTPS, therefore
-it warns against using SSL Compression (for example gzip) or SPDY which
-optionally uses compression as well.
+The TLS Protocol CRIME Vulnerability affects systems that use data compression
+over HTTPS. Your system might be vulnerable to the CRIME vulnerability if you use
+SSL Compression (for example, gzip) or SPDY (which optionally uses compression).
GitLab supports both gzip and [SPDY][ngx-spdy] and mitigates the CRIME
-vulnerability by deactivating gzip when HTTPS is enabled. You can see the
-sources of the files in question:
+vulnerability by deactivating gzip when HTTPS is enabled. The sources of the
+files are here:
- [Source installation NGINX file][source-nginx]
- [Omnibus installation NGINX file][omnibus-nginx]
@@ -24,7 +28,7 @@ Although SPDY is enabled in Omnibus installations, CRIME relies on compression
(the 'C') and the default compression level in NGINX's SPDY module is 0
(no compression).
-### Nessus
+## Nessus
The Nessus scanner, [reports a possible CRIME vulnerability][nessus] in GitLab
similar to the following format:
@@ -45,12 +49,12 @@ SPDY support earlier than version 4 is advertised.
```
From the report above it is important to note that Nessus is only checking if
-TLS advertises the SPDY protocol earlier than version 4, it does not perform an
-attack nor does it check if compression is enabled. With just this approach, it
+TLS advertises the SPDY protocol earlier than version 4. It does not perform an
+attack nor does it check if compression is enabled. The Nessus scanner alone
cannot tell that SPDY's compression is disabled and not subject to the CRIME
vulnerability.
-### References
+## References
- Nginx ["Module ngx_http_spdy_module"][ngx-spdy]
- Tenable Network Security, Inc. ["Transport Layer Security (TLS) Protocol CRIME Vulnerability"][nessus]
@@ -61,3 +65,15 @@ vulnerability.
[ngx-spdy]: http://nginx.org/en/docs/http/ngx_http_spdy_module.html
[nessus]: https://www.tenable.com/plugins/index.php?view=single&id=62565
[wiki-crime]: https://en.wikipedia.org/wiki/CRIME
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/security/img/two_factor_authentication_group_settings.png b/doc/security/img/two_factor_authentication_group_settings.png
deleted file mode 100644
index 05d95554fd9..00000000000
--- a/doc/security/img/two_factor_authentication_group_settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/security/img/two_factor_authentication_settings.png b/doc/security/img/two_factor_authentication_settings.png
deleted file mode 100644
index 2a2208f98bd..00000000000
--- a/doc/security/img/two_factor_authentication_settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/security/information_exclusivity.md b/doc/security/information_exclusivity.md
index 22756232025..62a20d3f257 100644
--- a/doc/security/information_exclusivity.md
+++ b/doc/security/information_exclusivity.md
@@ -1,9 +1,36 @@
+---
+type: concepts
+---
# Information exclusivity
-Git is a distributed version control system (DVCS).
-This means that everyone that works with the source code has a local copy of the complete repository.
-In GitLab every project member that is not a guest (so reporters, developers and maintainers) can clone the repository to get a local copy.
-After obtaining this local copy the user can upload the full repository anywhere, including another project under their control or another server.
-The consequence is that you can't build access controls that prevent the intentional sharing of source code by users that have access to the source code.
-This is an inherent feature of a DVCS and all git management systems have this limitation.
-Obviously you can take steps to prevent unintentional sharing and information destruction, this is why only some people are allowed to invite others and nobody can force push a protected branch.
+Git is a distributed version control system (DVCS). This means that everyone
+who works with the source code has a local copy of the complete repository.
+
+In GitLab every project member that is not a guest (reporters, developers, and
+maintainers) can clone the repository to create a local copy. After obtaining
+a local copy, the user can upload the full repository anywhere, including to
+another project that is under their control, or onto another server.
+
+Therefore, it is impossible to build access controls that prevent the
+intentional sharing of source code by users that have access to the source code.
+
+This is an inherent feature of a DVCS. All git management systems have this
+limitation.
+
+You can take steps to prevent unintentional sharing and information
+destruction. This limitation is the reason why only certain people are allowed
+to [add users to a project](../user/project/members/index.md)
+and why only a GitLab admin can [force push a protected
+branch](../user/project/protected_branches.md).
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/security/password_length_limits.md b/doc/security/password_length_limits.md
index d21b26a43e8..d78293c75c6 100644
--- a/doc/security/password_length_limits.md
+++ b/doc/security/password_length_limits.md
@@ -1,11 +1,28 @@
+---
+type: reference, howto
+---
# Custom password length limits
-If you want to enforce longer user passwords you can create an extra Devise initializer with the steps below.
+If you want to enforce longer user passwords you can create an extra Devise
+initializer with the steps below.
-If you do not use the `devise_password_length.rb` initializer the password length is set to a minimum of 8 characters in `config/initializers/devise.rb`.
+If you do not use the `devise_password_length.rb` initializer the password
+length is set to a minimum of 8 characters in `config/initializers/devise.rb`.
```bash
cd /home/git/gitlab
sudo -u git -H cp config/initializers/devise_password_length.rb.example config/initializers/devise_password_length.rb
sudo -u git -H editor config/initializers/devise_password_length.rb # inspect and edit the new password length limits
```
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/security/rack_attack.md b/doc/security/rack_attack.md
index ad83dc05a93..fa4b0d1fb09 100644
--- a/doc/security/rack_attack.md
+++ b/doc/security/rack_attack.md
@@ -1,24 +1,28 @@
+---
+type: reference, howto
+---
# Rack Attack
-Rack Attack, also known as Rack::Attack, is [a rubygem](https://github.com/kickstarter/rack-attack)
+[Rack Attack](https://github.com/kickstarter/rack-attack), also known as Rack::Attack, is a Ruby gem
that is meant to protect GitLab with the ability to customize throttling and
-blocking user IPs.
+to block user IP addresses.
+
You can prevent brute-force passwords attacks, scrapers, or any other offenders
-by throttling requests from IP addresses making large volumes of requests.
-In case you find throttling is not enough to protect you against abusive clients,
-Rack Attack offers IP whitelisting, blacklisting, Fail2ban style filtering and
+by throttling requests from IP addresses that are making large volumes of requests.
+If you find throttling is not enough to protect you against abusive clients,
+Rack Attack offers IP whitelisting, blacklisting, Fail2ban style filtering, and
tracking.
**Note:** Starting with 11.2, Rack Attack is disabled by default. To continue
-using this feature, please enable it by [configuring `gitlab.rb` as described in Settings](#settings).
+using Rack Attack, please enable it by [configuring `gitlab.rb` as described in Settings](#settings).
By default, user sign-in, user sign-up (if enabled), and user password reset is
limited to 6 requests per minute. After trying for 6 times, the client will
have to wait for the next minute to be able to try again.
-If you installed or upgraded GitLab by following the [official guides](../install/README.md)
-this should be disabled by default. If your instance is not exposed to any incoming
-connections, it is recommended to leave Rack Attack disabled.
+If you installed or upgraded GitLab by following the [official guides](../install/README.md),
+Rack Attack should be disabled by default. If your instance is not exposed to any incoming
+connections, it is recommended that you leave Rack Attack disabled.
For more information on how to use these options check out
[rack-attack README](https://github.com/kickstarter/rack-attack/blob/master/README.md).
@@ -27,7 +31,7 @@ For more information on how to use these options check out
**Omnibus GitLab**
-1. Open `/etc/gitlab/gitlab.rb` with you editor
+1. Open `/etc/gitlab/gitlab.rb` with your editor
1. Add the following:
```ruby
@@ -53,7 +57,7 @@ The following settings can be configured:
For example, `["127.0.0.1", "127.0.0.2", "127.0.0.3"]`.
- `maxretry`: The maximum amount of times a request can be made in the
specified time.
-- `findtime`: The maximum amount of time failed requests can count against an IP
+- `findtime`: The maximum amount of time that failed requests can count against an IP
before it's blacklisted (in seconds).
- `bantime`: The total amount of time that a blacklisted IP will be blocked (in
seconds).
@@ -94,7 +98,7 @@ In case you want to remove a blocked IP, follow these steps:
1. Find the IPs that have been blocked in the production log:
```sh
- grep "Rack_Attack" /var/log/gitlab/gitlab-rails/production.log
+ grep "Rack_Attack" /var/log/gitlab/gitlab-rails/auth.log
```
1. Since the blacklist is stored in Redis, you need to open up `redis-cli`:
diff --git a/doc/security/reset_root_password.md b/doc/security/reset_root_password.md
index 6a882ed6fe5..a58d70f0ff2 100644
--- a/doc/security/reset_root_password.md
+++ b/doc/security/reset_root_password.md
@@ -1,8 +1,11 @@
+---
+type: howto
+---
# How to reset your root password
-Log into your server with root privileges. Then start a Ruby on Rails console.
+To reset your root password, first log into your server with root privileges.
-Start the console with this command:
+Start a Ruby on Rails console with this command:
```bash
gitlab-rails console production
@@ -38,3 +41,15 @@ user.save!
```
Exit the console and try to login with your new password.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/security/ssh_keys_restrictions.md b/doc/security/ssh_keys_restrictions.md
index 6b6a8a06cc9..ae4cc44519e 100644
--- a/doc/security/ssh_keys_restrictions.md
+++ b/doc/security/ssh_keys_restrictions.md
@@ -1,3 +1,6 @@
+---
+type: reference, howto
+---
# Restrict allowed SSH key technologies and minimum length
`ssh-keygen` allows users to create RSA keys with as few as 768 bits, which
@@ -25,3 +28,15 @@ An icon will be visible to the user of a restricted key in the SSH keys section
![Restricted SSH key icon](img/ssh_keys_restricted_key_icon.png)
Hovering over this icon will tell you why the key is restricted.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/security/two_factor_authentication.md b/doc/security/two_factor_authentication.md
index 4b65b901487..49dadd5abc2 100644
--- a/doc/security/two_factor_authentication.md
+++ b/doc/security/two_factor_authentication.md
@@ -1,3 +1,6 @@
+---
+type: howto
+---
# Enforce Two-factor Authentication (2FA)
Two-factor Authentication (2FA) provides an additional level of security to your
@@ -16,39 +19,53 @@ enforce everyone to set up 2FA, you can choose from two different ways:
- Enforce on next login.
- Suggest on next login, but allow a grace period before enforcing.
-In the Admin area under **Settings** (`/admin/application_settings`), look for
-the "Sign-in Restrictions" area, where you can configure both.
+After the configured grace period has elapsed, users will be able to log in but
+won't be able to leave the 2FA configuration area at `/profile/two_factor_auth`.
+
+To enable 2FA for all users:
+
+1. Navigate to **Admin area > Settings > General** (`/admin/application_settings`).
+1. Expand the **Sign-in restrictions** section, where you can configure both.
If you want 2FA enforcement to take effect on next login, change the grace
period to `0`.
----
+## Enforcing 2FA for all users in a group
-![Two factor authentication admin settings](img/two_factor_authentication_settings.png)
+If you want to enforce 2FA only for certain groups, you can:
----
+1. Enable it in the group's **Settings > General** page.
+1. Optionally specify a grace period as above.
-## Enforcing 2FA for all users in a group
+To change this setting, you need to be administrator or owner of the group.
+
+> [From](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24965) GitLab 12.0, 2FA settings for a group are also applied to subgroups.
If you want to enforce 2FA only for certain groups, you can enable it in the
group settings and specify a grace period as above. To change this setting you
need to be administrator or owner of the group.
-If there are multiple 2FA requirements (i.e. group + all users, or multiple
-groups) the shortest grace period will be used.
-
----
-
-![Two factor authentication group settings](img/two_factor_authentication_group_settings.png)
-
----
+The following are important notes about 2FA:
+
+- Projects belonging to a 2FA-enabled group that
+ [is shared](../user/project/members/share_project_with_groups.md)
+ with a 2FA-disabled group will *not* require members of the 2FA-disabled group to use
+ 2FA for the project. For example, if project *P* belongs to 2FA-enabled group *A* and
+ is shared with 2FA-disabled group *B*, members of group *B* can access project *P*
+ without 2FA. To ensure this scenario doesn't occur,
+ [prevent sharing of projects](../user/group/index.md#share-with-group-lock)
+ for the 2FA-enabled group.
+- If you add additional members to a project within a group or subgroup that has
+ 2FA enabled, 2FA is **not** required for those individually added members.
+- If there are multiple 2FA requirements (for example, group + all users, or multiple
+ groups) the shortest grace period will be used.
## Disabling 2FA for everyone
There may be some special situations where you want to disable 2FA for everyone
even when forced 2FA is disabled. There is a rake task for that:
-```
+```sh
# Omnibus installations
sudo gitlab-rake gitlab:two_factor:disable_for_all_users
@@ -56,5 +73,18 @@ sudo gitlab-rake gitlab:two_factor:disable_for_all_users
sudo -u git -H bundle exec rake gitlab:two_factor:disable_for_all_users RAILS_ENV=production
```
-**IMPORTANT: this is a permanent and irreversible action. Users will have to
- reactivate 2FA from scratch if they want to use it again.**
+CAUTION: **Caution:**
+This is a permanent and irreversible action. Users will have to
+reactivate 2FA from scratch if they want to use it again.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/security/unlock_user.md b/doc/security/unlock_user.md
index d5ecef7f605..75cf754e197 100644
--- a/doc/security/unlock_user.md
+++ b/doc/security/unlock_user.md
@@ -1,8 +1,12 @@
+---
+type: howto
+---
# How to unlock a locked user
-Log into your server with root privileges. Then start a Ruby on Rails console.
+To unlock a locked user, first log into your server with root privileges.
+
+Start a Ruby on Rails console with this command:
-Start the console with this command:
```bash
gitlab-rails console production
@@ -29,3 +33,15 @@ user.unlock_access!
```
Exit the console, the user should now be able to log in again.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/security/user_email_confirmation.md b/doc/security/user_email_confirmation.md
index 8c07e11dcb1..f0af0a7ac6a 100644
--- a/doc/security/user_email_confirmation.md
+++ b/doc/security/user_email_confirmation.md
@@ -1,7 +1,23 @@
+---
+type: howto
+---
# User email confirmation at sign-up
-GitLab admin can enable email confirmation on sign-up, if you want to confirm all
-user emails before they are able to sign-in.
+GitLab can be configured to require confirmation of a user's email address when
+the user signs up. When this setting is enabled, the user is unable to sign in until
+they confirm their email address.
In the Admin area under **Settings** (`/admin/application_settings`), go to section
-**Sign-up Restrictions** and look for **Send confirmation email on sign-up** option.
+**Sign-up Restrictions** and look for the **Send confirmation email on sign-up** option.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/security/user_file_uploads.md b/doc/security/user_file_uploads.md
index 98493d33b00..00a2607b607 100644
--- a/doc/security/user_file_uploads.md
+++ b/doc/security/user_file_uploads.md
@@ -1,11 +1,30 @@
+---
+type: reference
+---
# User File Uploads
-Images attached to issues, merge requests or comments do not require authentication
-to be viewed if someone knows the direct URL. This direct URL contains a random
-32-character ID that prevents unauthorized people from guessing the URL to an
-image containing sensitive information. We don't enable authentication because
-these images need to be visible in the body of notification emails, which are
-often read from email clients that are not authenticated with GitLab, like
-Outlook, Apple Mail, or the Mail app on your mobile device.
+Images that are attached to issues, merge requests, or comments
+do not require authentication to be viewed if they are accessed directly by URL.
+This direct URL contains a random 32-character ID that prevents unauthorized
+people from guessing the URL for an image, thus there is some protection if an
+image contains sensitive information.
-Note that non-image attachments do require authentication to be viewed.
+Authentication is not enabled because images must be visible in the body of
+notification emails, which are often read from email clients that are not
+authenticated with GitLab, such as Outlook, Apple Mail, or the Mail app on your
+mobile device.
+
+>**Note:**
+Non-image attachments do require authentication to be viewed.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/security/webhooks.md b/doc/security/webhooks.md
index 8c26bbac6a7..d4fa088cb15 100644
--- a/doc/security/webhooks.md
+++ b/doc/security/webhooks.md
@@ -1,20 +1,56 @@
+---
+type: concepts, reference, howto
+---
# Webhooks and insecure internal web services
-If you have non-GitLab web services running on your GitLab server or within its local network, these may be vulnerable to exploitation via Webhooks.
+If you have non-GitLab web services running on your GitLab server or within its
+local network, these may be vulnerable to exploitation via Webhooks.
-With [Webhooks](../user/project/integrations/webhooks.md), you and your project maintainers and owners can set up URLs to be triggered when specific things happen to projects. Normally, these requests are sent to external web services specifically set up for this purpose, that process the request and its attached data in some appropriate way.
+With [Webhooks](../user/project/integrations/webhooks.md), you and your project
+maintainers and owners can set up URLs to be triggered when specific changes
+occur in your projects. Normally, these requests are sent to external web services
+specifically set up for this purpose, that process the request and its attached
+data in some appropriate way.
-Things get hairy, however, when a Webhook is set up with a URL that doesn't point to an external, but to an internal service, that may do something completely unintended when the webhook is triggered and the POST request is sent.
+Things get hairy, however, when a Webhook is set up with a URL that doesn't
+point to an external, but to an internal service, that may do something
+completely unintended when the webhook is triggered and the POST request is
+sent.
-Because Webhook requests are made by the GitLab server itself, these have complete access to everything running on the server (`http://localhost:123`) or within the server's local network (`http://192.168.1.12:345`), even if these services are otherwise protected and inaccessible from the outside world.
+Because Webhook requests are made by the GitLab server itself, these have
+complete access to everything running on the server (`http://localhost:123`) or
+within the server's local network (`http://192.168.1.12:345`), even if these
+services are otherwise protected and inaccessible from the outside world.
-If a web service does not require authentication, Webhooks can be used to trigger destructive commands by getting the GitLab server to make POST requests to endpoints like `http://localhost:123/some-resource/delete`.
+If a web service does not require authentication, Webhooks can be used to
+trigger destructive commands by getting the GitLab server to make POST requests
+to endpoints like `http://localhost:123/some-resource/delete`.
-To prevent this type of exploitation from happening, starting with GitLab 10.6, all Webhook requests to the current GitLab instance server address and/or in a private network will be forbidden by default. That means that all requests made to 127.0.0.1, ::1 and 0.0.0.0, as well as IPv4 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 and IPv6 site-local (ffc0::/10) addresses won't be allowed.
+To prevent this type of exploitation from happening, starting with GitLab 10.6,
+all Webhook requests to the current GitLab instance server address and/or in a
+private network will be forbidden by default. That means that all requests made
+to 127.0.0.1, ::1 and 0.0.0.0, as well as IPv4 10.0.0.0/8, 172.16.0.0/12,
+192.168.0.0/16 and IPv6 site-local (ffc0::/10) addresses won't be allowed.
-This behavior can be overridden by enabling the option *"Allow requests to the local network from hooks and services"* in the *"Outbound requests"* section inside the Admin area under **Settings** (`/admin/application_settings/network`):
+This behavior can be overridden by enabling the option *"Allow requests to the
+local network from hooks and services"* in the *"Outbound requests"* section
+inside the Admin area under **Settings**
+(`/admin/application_settings/network`):
![Outbound requests admin settings](img/outbound_requests_section.png)
>**Note:**
-*System hooks* are exempt from this protection because they are set up by admins.
+*System hooks* are exempt from this protection because they are set up by
+admins.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/ssh/README.md b/doc/ssh/README.md
index 9c4a391e8da..dbd9bcee935 100644
--- a/doc/ssh/README.md
+++ b/doc/ssh/README.md
@@ -1,3 +1,7 @@
+---
+type: howto, reference
+---
+
# GitLab and SSH keys
Git is a distributed version control system, which means you can work locally
@@ -50,22 +54,26 @@ more information, you can read this
We'll focus on ED25519 and RSA and here.
NOTE: **Note:**
-As an admin, you can restrict
-[which keys should be permitted and their minimum length](../security/ssh_keys_restrictions.md).
+As an admin, you can [restrict which keys should be permitted and their minimum length](../security/ssh_keys_restrictions.md).
By default, all keys are permitted, which is also the case for
[GitLab.com](../user/gitlab_com/index.md#ssh-host-keys-fingerprints).
-## ED25519 SSH keys
+### ED25519 SSH keys
Following [best practices](https://linux-audit.com/using-ed25519-openssh-keys-instead-of-dsa-rsa-ecdsa/),
you should always favor [ED25519](https://ed25519.cr.yp.to/) SSH keys, since they
are more secure and have better performance over the other types.
-They were introduced in OpenSSH 6.5, so any modern OS should include the
-option to create them. If for any reason your OS or the GitLab instance you
-interact with doesn't support this, you can fallback to RSA.
+ED25519 SSH keys were introduced in OpenSSH 6.5,
+so any modern OS should include the option to create them.
+If for any reason your OS or the GitLab instance you interact with doesn't
+support ED25519, you can fallback to RSA.
+
+NOTE: **Note:**
+Omnibus does not ship with OpenSSH, so it uses the version on your GitLab server. If using
+Omnibus, ensure the version of OpenSSH installed is version 6.5 or newer if you want to use ED25519 SSH keys.
-## RSA SSH keys
+### RSA SSH keys
RSA keys are the most common ones and therefore the most compatible with
servers that may have an old OpenSSH version. Use them if the GitLab server
@@ -91,9 +99,8 @@ ssh-keygen -o -f ~/.ssh/id_rsa
## Generating a new SSH key pair
-Before creating an SSH key pair, make sure to read about the
-[different types of keys](#types-of-ssh-keys-and-which-to-choose) to understand
-their differences.
+Before creating an SSH key pair, make sure to understand the
+[different types of keys](#types-of-ssh-keys-and-which-to-choose).
To create a new SSH key pair:
@@ -166,12 +173,13 @@ Now, it's time to add the newly created public key to your GitLab account.
NOTE: **Note:**
If you opted to create an RSA key, the name might differ.
-1. Add your public SSH key to your GitLab account by clicking your avatar
- in the upper right corner and selecting **Settings**. From there on,
- navigate to **SSH Keys** and paste your public key in the "Key" section.
- If you created the key with a comment, this will appear under "Title".
- If not, give your key an identifiable title like _Work Laptop_ or
- _Home Workstation_, and click **Add key**.
+1. Add your **public** SSH key to your GitLab account by:
+ 1. Clicking your avatar in the upper right corner and selecting **Settings**.
+ 1. Navigating to **SSH Keys** and pasting your **public** key in the **Key** field. If you:
+
+ - Created the key with a comment, this will appear in the **Title** field.
+ - Created the key without a comment, give your key an identifiable title like _Work Laptop_ or _Home Workstation_.
+ 1. Click the **Add key** button.
NOTE: **Note:**
If you manually copied your public SSH key make sure you copied the entire
@@ -305,7 +313,7 @@ who needs to know and configure the private key.
GitLab administrators set up Global Deploy keys in the Admin area under the
section **Deploy Keys**. Ensure keys have a meaningful title as that will be
the primary way for project maintainers and owners to identify the correct Global
-Deploy key to add. For instance, if the key gives access to a SaaS CI instance,
+Deploy key to add. For instance, if the key gives access to a SaaS CI instance,
use the name of that service in the key name if that is all it is used for.
When creating Global Shared Deploy keys, give some thought to the granularity
of keys - they could be of very narrow usage such as just a specific service or
@@ -331,7 +339,7 @@ not implicitly give any access just by setting them up.
### Eclipse
-How to add your SSH key to Eclipse: <https://wiki.eclipse.org/EGit/User_Guide#Eclipse_SSH_Configuration>
+If you are using [EGit](https://www.eclipse.org/egit/), you can [add your SSH key to Eclipse](https://wiki.eclipse.org/EGit/User_Guide#Eclipse_SSH_Configuration).
## SSH on the GitLab server
diff --git a/doc/subscriptions/billing_table.png b/doc/subscriptions/billing_table.png
new file mode 100644
index 00000000000..acd1b6193ec
--- /dev/null
+++ b/doc/subscriptions/billing_table.png
Binary files differ
diff --git a/doc/subscriptions/index.md b/doc/subscriptions/index.md
new file mode 100644
index 00000000000..37051f6b10f
--- /dev/null
+++ b/doc/subscriptions/index.md
@@ -0,0 +1,128 @@
+---
+type: index, reference
+---
+
+# Subscription setup and management
+
+This page will help get you started with your new subscription or manage an existing one, whether you have subscribed to GitLab.com or self-managed GitLab.
+
+To subscribe, upgrade, or read more about the types of subscriptions, please see [Subscribe to GitLab](../README.md#subscribe-to-gitlab) on the GitLab Documentation landing page.
+
+## Set up GitLab
+
+Learn how GitLab helps you in the stages of the DevOps lifecycle by learning more [about the GitLab product](https://about.gitlab.com/product/), [GitLab features](https://about.gitlab.com/features/), and [GitLab Documentation](../README.md).
+
+### Self-managed: Install GitLab
+
+Take a look at [installing GitLab](https://about.gitlab.com/install/) and our [administrator documentation](../administration/index.md). Then, follow the instructions below under [Your subscription](#your-subscription) to apply your license file.
+
+### GitLab.com: Create a user and group
+
+Start with creating a user account for yourself using our [sign up page](https://gitlab.com/users/sign_in#register-pane).
+
+[GitLab groups](../user/group/index.md) help assemble related projects together allowing you to grant members access to several projects at once. A group is not required if you plan on having [projects](../user/project/) inside a personal namespace.
+
+## Your subscription
+
+You can view and manage subscriptions through our [Customers portal](https://customers.gitlab.com/). Information on applying your subscription is below.
+
+Please also see our [subscription FAQ](https://about.gitlab.com/pricing/licensing-faq/)
+
+### View subscription and seats
+
+To view and manage the subscriptions you have purchased and the number of seats associated with the subscription, please visit and log into the [Customers’ Portal](https://customers.gitlab.com/subscriptions). For more information, please see our [subscription FAQ](https://about.gitlab.com/pricing/licensing-faq/) and [pricing page](https://about.gitlab.com/pricing/), which includes information on our [true-up pricing policy](https://about.gitlab.com/handbook/product/pricing/#true-up-pricing) when adding more users than at the time of purchase.
+
+Please note that this account may have the same email, but is a _separate_ login from your GitLab.com account. If the two accounts are linked together, then you can use the "sign in with GitLab.com account" link underneath the `Sign In` button.
+
+### Change billing information
+
+In the customers portal, go to the `My Account` page, then revise the `Account Details` information and click on the `Update Account` button.
+
+Future purchases will use the information in this section. The email listed in this section is used for the Customers Portal login and for license related email communication.
+
+### Self-managed: Apply your license file
+
+After purchase, the license file is sent to the email address tied to the Customers portal account, which needs to be [uploaded to the GitLab instance](../user/admin_area/license.md#uploading-your-license).
+
+### Link your GitLab.com account with your Customers Portal account
+
+NOTE: **Note:**
+This is *required* for GitLab.com subscriptions.
+
+Once signed into the customers portal, if your account is not already linked, you should be prompted to link your account with a "Link my GitLab Account" button.
+
+You can also go to the [My Account](https://customers.gitlab.com/customers/edit) page to add or change the GitLab.com account link.
+
+### Change the linked GitLab.com account for your Customers Portal account
+
+To change which GitLab.com account is associated with a Customers Portal account, please follow these steps:
+
+1. Log into the [Customers Portal](https://customers.gitlab.com/customers/sign_in).
+1. In a separate browser tab, visit [GitLab.com](https://gitlab.com) to ensure you are not logged in, or if you are, log out.
+1. Back on the Customers Portal page, click [My Account](https://customers.gitlab.com/customers/edit) in the top menu.
+1. Under `Your GitLab.com account`, click the `Change linked account` button.
+1. Have the user you want associated log in to their [GitLab.com](https://gitlab.com) account.
+
+### GitLab.com: Associate your namespace with your subscription
+
+Once your GitLab.com account is linked, you can go to your [Subscriptions](https://customers.gitlab.com/subscriptions) page to choose or change the namespace your subscription applies to.
+
+Please note that you need to be a group owner to associate a group to your subscription.
+
+### Confirm or upgrade your GitLab.com subscription details within GitLab
+
+To see the status of your GitLab.com subscription, you can click on the Billings
+section of the relevant namespace:
+
+* For individuals, this is located at https://gitlab.com/profile/billings under
+in your Settings,
+* For groups, this is located under the group's Settings dropdown, under Billing.
+
+For groups, you can see details of your subscription - including your current
+plan - in the included table:
+
+![Billing table](billing_table.png)
+
+| Field | Description |
+| ------ | ------ |
+| Seats in subscription | If this is a paid plan, this represents the number of seats you've paid to support in your group. |
+| Seats currently in use | The number of active seats currently in use. |
+| Max seats used | The highest number of seats you've used. If this exceeds the seats in subscription, you may owe an additional fee for the additional users. |
+| Seats owed | If your max seats used exceeds the seats in your subscription, you'll owe an additional fee for the users you've added. |
+| Subscription start date | The date your subscription started. If this is for a Free plan, this is the date you transitioned off your group's paid plan. |
+| Subscription end date | The date your current subscription will end. This does not apply to Free plans. |
+
+### Subscription changes and your data
+
+When your subscription or trial expires, GitLab does not delete your data, however, depending on the tier and feature, it may become inaccessible. Please note that some features may not behave as expected if a graceful fallback is not currently implemented, such as [environment specific variables not being passed](https://gitlab.com/gitlab-org/gitlab-ce/issues/52825).
+
+If you renew or upgrade, your data will again be accessible.
+
+For self-managed customers, there is a two-week grace period when your features will continue to work as-is, after which the entire instance will become read only. However, if you remove the license, you will immediately revert to Core features.
+
+## Need help?
+
+[GitLab's Documentation](https://docs.gitlab.com/) offers a wide range of topics covering the use and administration of GitLab.
+
+We also encourage all users to search our project trackers for known issues and existing feature requests in:
+
+- [GitLab CE](https://gitlab.com/gitlab-org/gitlab-ce/issues/) for features included in all tiers, and
+- [GitLab EE](https://gitlab.com/gitlab-org/gitlab-ee/issues/) for paid-tier features.
+
+These issues are the best avenue for getting updates on specific product plans and for communicating directly with the relevant GitLab team members.
+
+### Contacting Support
+
+Learn more about the tiers of [GitLab Support](https://about.gitlab.com/support/) or [submit a request via the Support Portal](https://support.gitlab.com/hc/en-us/requests/new).
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md
index a3698d60f6d..a46f7d30892 100644
--- a/doc/system_hooks/system_hooks.md
+++ b/doc/system_hooks/system_hooks.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# System hooks
Your GitLab instance can perform HTTP POST requests on the following events:
@@ -27,11 +31,9 @@ The triggers for most of these are self-explanatory, but `project_update` and `p
System hooks can be used, e.g. for logging or changing information in a LDAP server.
-> **Note:**
->
-> We follow the same structure from Webhooks for Push and Tag events, but we never display commits.
->
-> Same deprecations from Webhooks are valid here.
+NOTE: **Note:**
+We follow the same structure and deprecations as [Webhooks](../user/project/integrations/webhooks.md)
+for Push and Tag events, but we never display commits.
## Hooks request example
@@ -640,3 +642,15 @@ X-Gitlab-Event: System Hook
"refs":["refs/heads/master"]
}
```
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/tools/email.md b/doc/tools/email.md
new file mode 100644
index 00000000000..a2d677484f0
--- /dev/null
+++ b/doc/tools/email.md
@@ -0,0 +1,48 @@
+---
+type: howto, reference
+---
+
+# Email from GitLab **[STARTER ONLY]**
+
+GitLab provides a simple tool to administrators for emailing all users, or users of
+a chosen group or project, right from the admin area. Users will receive the email
+at their primary email address.
+
+## Use-cases
+
+- Notify your users about a new project, a new feature, or a new product launch.
+- Notify your users about a new deployment, or that will be downtime expected
+ for a particular reason.
+
+## Sending emails to users from within GitLab
+
+1. Go to the admin area using the wrench icon in the top right corner and
+ navigate to **Overview > Users > Send email to users**.
+
+ ![admin users](email1.png)
+
+1. Compose an email and choose where it will be sent (all users or users of a
+ chosen group or project):
+
+ ![compose an email](email2.png)
+
+## Unsubscribing from emails
+
+Users can choose to unsubscribe from receiving emails from GitLab by following
+the unsubscribe link in the email. Unsubscribing is unauthenticated in order
+to keep this feature simple.
+
+On unsubscribe, users will receive an email notification that unsubscribe happened.
+The endpoint that provides the unsubscribe option is rate-limited.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/tools/email1.png b/doc/tools/email1.png
new file mode 100644
index 00000000000..e79ccc3e9a9
--- /dev/null
+++ b/doc/tools/email1.png
Binary files differ
diff --git a/doc/tools/email2.png b/doc/tools/email2.png
new file mode 100644
index 00000000000..d073c0e42da
--- /dev/null
+++ b/doc/tools/email2.png
Binary files differ
diff --git a/doc/topics/authentication/index.md b/doc/topics/authentication/index.md
index 0fc7f57feab..228da2d1f57 100644
--- a/doc/topics/authentication/index.md
+++ b/doc/topics/authentication/index.md
@@ -17,11 +17,11 @@ This page gathers all the resources for the topic **Authentication** within GitL
## GitLab administrators
- [LDAP (Community Edition)](../../administration/auth/ldap.md)
-- [LDAP (Enterprise Edition)](https://docs.gitlab.com/ee/administration/auth/ldap-ee.html)
+- [LDAP (Enterprise Edition)](../../administration/auth/ldap-ee.md) **[STARTER]**
- [Enforce Two-factor Authentication (2FA)](../../security/two_factor_authentication.md#enforce-two-factor-authentication-2fa)
- **Articles:**
- [How to Configure LDAP with GitLab CE](../../administration/auth/how_to_configure_ldap_gitlab_ce/index.md)
- - [How to Configure LDAP with GitLab EE](https://docs.gitlab.com/ee/administration/auth/how_to_configure_ldap_gitlab_ee/index.html)
+ - [How to Configure LDAP with GitLab EE](../../administration/auth/how_to_configure_ldap_gitlab_ee/index.md) **[STARTER]**
- [Feature Highlight: LDAP Integration](https://about.gitlab.com/2014/07/10/feature-highlight-ldap-sync/)
- [Debugging LDAP](https://about.gitlab.com/handbook/support/workflows/support-engineering/ldap/debugging_ldap.html)
- **Integrations:**
@@ -30,8 +30,10 @@ This page gathers all the resources for the topic **Authentication** within GitL
- [Atlassian Crowd OmniAuth Provider](../../administration/auth/crowd.md)
- [CAS OmniAuth Provider](../../integration/cas.md)
- [SAML OmniAuth Provider](../../integration/saml.md)
+ - [SAML for GitLab.com Groups](../../user/group/saml_sso/index.md) **[SILVER ONLY]**
+ - [SCIM user provisioning for GitLab.com Groups](../../user/group/saml_sso/scim_setup.md) **[SILVER ONLY]**
- [Okta SSO provider](../../administration/auth/okta.md)
- - [Kerberos integration (GitLab EE)](https://docs.gitlab.com/ee/integration/kerberos.html)
+ - [Kerberos integration (GitLab EE)](../../integration/kerberos.md) **[STARTER]**
## API
diff --git a/doc/topics/autodevops/img/autodevops_domain_variables.png b/doc/topics/autodevops/img/autodevops_domain_variables.png
deleted file mode 100644
index b6f8864796f..00000000000
--- a/doc/topics/autodevops/img/autodevops_domain_variables.png
+++ /dev/null
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_connect_cluster.png b/doc/topics/autodevops/img/guide_connect_cluster.png
deleted file mode 100644
index 703d536f37a..00000000000
--- a/doc/topics/autodevops/img/guide_connect_cluster.png
+++ /dev/null
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_create_cluster.png b/doc/topics/autodevops/img/guide_create_cluster.png
deleted file mode 100644
index cd1d0fdd8da..00000000000
--- a/doc/topics/autodevops/img/guide_create_cluster.png
+++ /dev/null
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_gke_apis_after.png b/doc/topics/autodevops/img/guide_gke_apis_after.png
deleted file mode 100644
index 380de958867..00000000000
--- a/doc/topics/autodevops/img/guide_gke_apis_after.png
+++ /dev/null
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_gke_apis_before.png b/doc/topics/autodevops/img/guide_gke_apis_before.png
deleted file mode 100644
index d06fc707887..00000000000
--- a/doc/topics/autodevops/img/guide_gke_apis_before.png
+++ /dev/null
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_merge_request_ide.png b/doc/topics/autodevops/img/guide_merge_request_ide.png
deleted file mode 100644
index c825b0849e1..00000000000
--- a/doc/topics/autodevops/img/guide_merge_request_ide.png
+++ /dev/null
Binary files differ
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index 1df492ba82c..34140a3260e 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -8,20 +8,23 @@ to simplify the setup and execution of a mature & modern software development li
## Overview
-NOTE: **Enabled by default:**
-Starting with GitLab 11.3, the Auto DevOps pipeline is enabled by default for all
-projects. If it has not been explicitly enabled for the project, Auto DevOps will be automatically
-disabled on the first pipeline failure. Your project will continue to use an alternative
-[CI/CD configuration file](../../ci/yaml/README.md) if one is found. A GitLab
-administrator can [change this setting](../../user/admin_area/settings/continuous_integration.html#auto-devops-core-only)
-in the admin area.
-
With Auto DevOps, the software development process becomes easier to set up
as every project can have a complete workflow from verification to monitoring
with minimal configuration. Just push your code and GitLab takes
care of everything else. This makes it easier to start new projects and brings
consistency to how applications are set up throughout a company.
+For an introduction to Auto DevOps, watch [AutoDevOps in GitLab 11.0](https://youtu.be/0Tc0YYBxqi4).
+
+## Enabled by default
+
+Starting with GitLab 11.3, the Auto DevOps pipeline is enabled by default for all
+projects. If it has not been explicitly enabled for the project, Auto DevOps will be automatically
+disabled on the first pipeline failure. Your project will continue to use an alternative
+[CI/CD configuration file](../../ci/yaml/README.md) if one is found. A GitLab
+administrator can [change this setting](../../user/admin_area/settings/continuous_integration.md#auto-devops-core-only)
+in the admin area.
+
## Quick start
If you are using GitLab.com, see the [quick start guide](quick_start_guide.md)
@@ -62,7 +65,7 @@ project in a simple and automatic way:
1. [Auto SAST (Static Application Security Testing)](#auto-sast-ultimate) **[ULTIMATE]**
1. [Auto Dependency Scanning](#auto-dependency-scanning-ultimate) **[ULTIMATE]**
1. [Auto License Management](#auto-license-management-ultimate) **[ULTIMATE]**
-1. [Auto Container Scanning](#auto-container-scanning)
+1. [Auto Container Scanning](#auto-container-scanning-ultimate) **[ULTIMATE]**
1. [Auto Review Apps](#auto-review-apps)
1. [Auto DAST (Dynamic Application Security Testing)](#auto-dast-ultimate) **[ULTIMATE]**
1. [Auto Deploy](#auto-deploy)
@@ -120,16 +123,11 @@ To make full use of Auto DevOps, you will need:
[default service template](../../user/project/integrations/services_templates.md)
for the entire GitLab installation.
-NOTE: **Note:**
If you do not have Kubernetes or Prometheus installed, then Auto Review Apps,
Auto Deploy, and Auto Monitoring will be silently skipped.
## Auto DevOps base domain
-NOTE: **Note**
-`AUTO_DEVOPS_DOMAIN` environment variable is deprecated and
-[is scheduled to be removed](https://gitlab.com/gitlab-org/gitlab-ce/issues/56959).
-
The Auto DevOps base domain is required if you want to make use of [Auto
Review Apps](#auto-review-apps) and [Auto Deploy](#auto-deploy). It can be defined
in any of the following places:
@@ -139,10 +137,13 @@ in any of the following places:
- or at the project level as a variable: `KUBE_INGRESS_BASE_DOMAIN`
- or at the group level as a variable: `KUBE_INGRESS_BASE_DOMAIN`.
-NOTE: **Note**
-The Auto DevOps base domain variable (`KUBE_INGRESS_BASE_DOMAIN`) follows the same order of precedence
+The base domain variable `KUBE_INGRESS_BASE_DOMAIN` follows the same order of precedence
as other environment [variables](../../ci/variables/README.md#priority-of-environment-variables).
+NOTE: **Note**
+`AUTO_DEVOPS_DOMAIN` environment variable is deprecated and
+[is scheduled to be removed](https://gitlab.com/gitlab-org/gitlab-ce/issues/56959).
+
A wildcard DNS A record matching the base domain(s) is required, for example,
given a base domain of `example.com`, you'd need a DNS entry like:
@@ -162,6 +163,12 @@ Auto DevOps base domain to `1.2.3.4.nip.io`.
Once set up, all requests will hit the load balancer, which in turn will route
them to the Kubernetes pods that run your application(s).
+NOTE: **Note:**
+From GitLab 11.8, `KUBE_INGRESS_BASE_DOMAIN` replaces `AUTO_DEVOPS_DOMAIN`.
+Support for `AUTO_DEVOPS_DOMAIN` was [removed in GitLab
+12.0](https://gitlab.com/gitlab-org/gitlab-ce/issues/56959).
+
+
## Using multiple Kubernetes clusters **[PREMIUM]**
When using Auto DevOps, you may want to deploy different environments to
@@ -179,7 +186,7 @@ Those environments are tied to jobs that use [Auto Deploy](#auto-deploy), so
except for the environment scope, they would also need to have a different
domain they would be deployed to. This is why you need to define a separate
`KUBE_INGRESS_BASE_DOMAIN` variable for all the above
-[based on the environment](https://docs.gitlab.com/ee/ci/variables/index.html#limiting-environment-scopes-of-variables-premium).
+[based on the environment](../../ci/variables/README.md#limiting-environment-scopes-of-environment-variables-premium).
The following table is an example of how the three different clusters would
be configured.
@@ -209,10 +216,6 @@ and verifying that your app is deployed as a review app in the Kubernetes
cluster with the `review/*` environment scope. Similarly, you can check the
other environments.
-NOTE: **Note:**
-From GitLab 11.8, `KUBE_INGRESS_BASE_DOMAIN` replaces `AUTO_DEVOPS_DOMAIN`.
-`AUTO_DEVOPS_DOMAIN` [is scheduled to be removed](https://gitlab.com/gitlab-org/gitlab-ce/issues/56959).
-
## Enabling/Disabling Auto DevOps
When first using Auto Devops, review the [requirements](#requirements) to ensure all necessary components to make
@@ -224,19 +227,20 @@ can enable/disable Auto DevOps at either the project-level or instance-level.
### Enabling/disabling Auto DevOps at the instance-level (Administrators only)
+Even when disabled at the instance level, group owners and project maintainers can still enable
+Auto DevOps at the group and project level, respectively.
+
1. Go to **Admin area > Settings > Continuous Integration and Deployment**.
1. Toggle the checkbox labeled **Default to Auto DevOps pipeline for all projects**.
1. If enabling, optionally set up the Auto DevOps [base domain](#auto-devops-base-domain) which will be used for Auto Deploy and Auto Review Apps.
1. Click **Save changes** for the changes to take effect.
-NOTE: **Note:**
-Even when disabled at the instance level, group owners and project maintainers are still able to enable
-Auto DevOps at group-level and project-level, respectively.
-
### Enabling/disabling Auto DevOps at the group-level
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/52447) in GitLab 11.10.
+Only administrators and group owners can enable or disable Auto DevOps at the group level.
+
To enable or disable Auto DevOps at the group-level:
1. Go to group's **Settings > CI/CD > Auto DevOps** page.
@@ -247,9 +251,6 @@ When enabling or disabling Auto DevOps at group-level, group configuration will
the subgroups and projects inside that group, unless Auto DevOps is specifically enabled or disabled on
the subgroup or project.
-NOTE: **Note**
-Only administrators and group owners are allowed to enable or disable Auto DevOps at group-level.
-
### Enabling/disabling Auto DevOps at the project-level
If enabling, check that your project doesn't have a `.gitlab-ci.yml`, or if one exists, remove it.
@@ -263,16 +264,13 @@ If enabling, check that your project doesn't have a `.gitlab-ci.yml`, or if one
When the feature has been enabled, an Auto DevOps pipeline is triggered on the default branch.
-NOTE: **Note:**
-For GitLab versions 10.0 - 10.2, when enabling Auto DevOps, a pipeline needs to be
-manually triggered either by pushing a new commit to the repository or by visiting
-`https://example.gitlab.com/<username>/<project>/pipelines/new` and creating
-a new pipeline for your default branch, generally `master`.
+### Feature flag to enable for a percentage of projects
-NOTE: **Note:**
-There is also a feature flag to enable Auto DevOps to a percentage of projects
-which can be enabled from the console with
-`Feature.get(:force_autodevops_on_by_default).enable_percentage_of_actors(10)`.
+There is also a feature flag to enable Auto DevOps by default to your chosen percentage of projects.
+
+This can be enabled from the console with the following, which uses the example of 10%:
+
+`Feature.get(:force_autodevops_on_by_default).enable_percentage_of_actors(10)`
### Deployment strategy
@@ -352,7 +350,6 @@ frameworks are detected automatically, but if your language is not detected,
you may succeed with a [custom buildpack](#custom-buildpacks). Check the
[currently supported languages](#currently-supported-languages).
-NOTE: **Note:**
Auto Test uses tests you already have in your application. If there are no
tests, it's up to you to add them.
@@ -365,7 +362,7 @@ created, and is uploaded as an artifact which you can later download and check
out.
Any differences between the source and target branches are also
-[shown in the merge request widget](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html).
+[shown in the merge request widget](../../user/project/merge_requests/code_quality.md).
### Auto SAST **[ULTIMATE]**
@@ -373,18 +370,14 @@ Any differences between the source and target branches are also
Static Application Security Testing (SAST) uses the
[SAST Docker image](https://gitlab.com/gitlab-org/security-products/sast) to run static
-analysis on the current code and checks for potential security issues. Once the
-report is created, it's uploaded as an artifact which you can later download and
-check out.
-
-Any security warnings are also
-[shown in the merge request widget](https://docs.gitlab.com/ee//user/project/merge_requests/sast.html).
+analysis on the current code and checks for potential security issues. The
+the Auto SAST stage will be skipped on licenses other than Ultimate and requires GitLab Runner 11.5 or above.
-NOTE: **Note:**
-The Auto SAST stage will be skipped on licenses other than Ultimate.
+Once the report is created, it's uploaded as an artifact which you can later download and
+check out.
-NOTE: **Note:**
-The Auto SAST job requires GitLab Runner 11.5 or above.
+Any security warnings are also shown in the merge request widget. Read more how
+[SAST works](../../user/application_security/sast/index.md).
### Auto Dependency Scanning **[ULTIMATE]**
@@ -392,18 +385,16 @@ The Auto SAST job requires GitLab Runner 11.5 or above.
Dependency Scanning uses the
[Dependency Scanning Docker image](https://gitlab.com/gitlab-org/security-products/dependency-scanning)
-to run analysis on the project dependencies and checks for potential security issues. Once the
+to run analysis on the project dependencies and checks for potential security issues.
+The Auto Dependency Scanning stage will be skipped on licenses other than Ultimate
+and requires GitLab Runner 11.5 or above.
+
+Once the
report is created, it's uploaded as an artifact which you can later download and
check out.
-Any security warnings are also
-[shown in the merge request widget](https://docs.gitlab.com/ee//user/project/merge_requests/dependency_scanning.html).
-
-NOTE: **Note:**
-The Auto Dependency Scanning stage will be skipped on licenses other than Ultimate.
-
-NOTE: **Note:**
-The Auto Dependency Scanning job requires GitLab Runner 11.5 or above.
+Any security warnings are also shown in the merge request widget. Read more about
+[Dependency Scanning](../../user/application_security/dependency_scanning/index.md).
### Auto License Management **[ULTIMATE]**
@@ -411,35 +402,34 @@ The Auto Dependency Scanning job requires GitLab Runner 11.5 or above.
License Management uses the
[License Management Docker image](https://gitlab.com/gitlab-org/security-products/license-management)
-to search the project dependencies for their license. Once the
+to search the project dependencies for their license. The Auto License Management stage
+will be skipped on licenses other than Ultimate.
+
+Once the
report is created, it's uploaded as an artifact which you can later download and
check out.
-Any licenses are also
-[shown in the merge request widget](https://docs.gitlab.com/ee//user/project/merge_requests/license_management.html).
-
-NOTE: **Note:**
-The Auto License Management stage will be skipped on licenses other than Ultimate.
+Any licenses are also shown in the merge request widget. Read more how
+[License Management works](../../user/application_security/license_management/index.md).
-### Auto Container Scanning
+### Auto Container Scanning **[ULTIMATE]**
> Introduced in GitLab 10.4.
Vulnerability Static Analysis for containers uses
[Clair](https://github.com/coreos/clair) to run static analysis on a
-Docker image and checks for potential security issues. Once the report is
+Docker image and checks for potential security issues. The Auto Container Scanning stage
+will be skipped on licenses other than Ultimate.
+
+Once the report is
created, it's uploaded as an artifact which you can later download and
check out.
-Any security warnings are also
-[shown in the merge request widget](https://docs.gitlab.com/ee//user/project/merge_requests/container_scanning.html).
-
-NOTE: **Note:**
-The Auto Container Scanning stage will be skipped on licenses other than Ultimate.
+Any security warnings are also shown in the merge request widget. Read more how
+[Container Scanning works](../../user/application_security/container_scanning/index.md).
### Auto Review Apps
-NOTE: **Note:**
This is an optional step, since many projects do not have a Kubernetes cluster
available. If the [requirements](#requirements) are not met, the job will
silently be skipped.
@@ -460,7 +450,7 @@ for example after the merge request is merged, the Review App will automatically
be deleted.
Review apps are deployed using the
-[auto-deploy-app](https://gitlab.com/charts/auto-deploy-app) chart with
+[auto-deploy-app](https://gitlab.com/gitlab-org/charts/auto-deploy-app) chart with
Helm. The app will be deployed into the [Kubernetes
namespace](../../user/project/clusters/index.md#deployment-variables)
for the environment.
@@ -484,14 +474,13 @@ in the first place, and thus not realize that it needs to re-apply the old confi
Dynamic Application Security Testing (DAST) uses the
popular open source tool [OWASP ZAProxy](https://github.com/zaproxy/zaproxy)
to perform an analysis on the current code and checks for potential security
-issues. Once the report is created, it's uploaded as an artifact which you can
-later download and check out.
+issues. The Auto DAST stage will be skipped on licenses other than Ultimate.
-Any security warnings are also
-[shown in the merge request widget](https://docs.gitlab.com/ee//user/project/merge_requests/dast.html).
+Once the report is created, it's uploaded as an artifact which you can
+later download and check out.
-NOTE: **Note:**
-The Auto DAST stage will be skipped on licenses other than Ultimate.
+Any security warnings are also shown in the merge request widget. Read how
+[DAST works](../../user/application_security/dast/index.md).
### Auto Browser Performance Testing **[PREMIUM]**
@@ -506,11 +495,10 @@ Auto Browser Performance Testing utilizes the [Sitespeed.io container](https://h
```
Any performance differences between the source and target branches are also
-[shown in the merge request widget](https://docs.gitlab.com/ee//user/project/merge_requests/browser_performance_testing.html).
+[shown in the merge request widget](../../user/project/merge_requests/browser_performance_testing.md).
### Auto Deploy
-NOTE: **Note:**
This is an optional step, since many projects do not have a Kubernetes cluster
available. If the [requirements](#requirements) are not met, the job will
silently be skipped.
@@ -528,7 +516,7 @@ You can make use of [environment variables](#environment-variables) to automatic
scale your pod replicas.
Apps are deployed using the
-[auto-deploy-app](https://gitlab.com/charts/auto-deploy-app) chart with
+[auto-deploy-app](https://gitlab.com/gitlab-org/charts/auto-deploy-app) chart with
Helm. The app will be deployed into the [Kubernetes
namespace](../../user/project/clusters/index.md#deployment-variables)
for the environment.
@@ -549,7 +537,7 @@ in the first place, and thus not realize that it needs to re-apply the old confi
For internal and private projects a [GitLab Deploy Token](../../user/project/deploy_tokens/index.md#gitlab-deploy-token)
will be automatically created, when Auto DevOps is enabled and the Auto DevOps settings are saved. This Deploy Token
-can be used for permanent access to the registry.
+can be used for permanent access to the registry. When the GitLab Deploy Token has been manually revoked, it won't be automatically created.
If the GitLab Deploy Token cannot be found, `CI_REGISTRY_PASSWORD` is
used. Note that `CI_REGISTRY_PASSWORD` is only valid during deployment.
@@ -559,9 +547,6 @@ be pulled again, e.g. after pod eviction, Kubernetes will fail to do so
as it will be attempting to fetch the image using
`CI_REGISTRY_PASSWORD`.
-NOTE: **Note:**
-When the GitLab Deploy Token has been manually revoked, it won't be automatically created.
-
#### Migrations
> [Introduced][ce-21955] in GitLab 11.4
@@ -584,22 +569,19 @@ Note that a post-install hook means that if any deploy succeeds,
If present, `DB_MIGRATE` will be run as a shell command within an application pod as
a helm pre-upgrade hook.
-For example, in a Rails application:
+For example, in a Rails application in an image built with
+[Herokuish](https://github.com/gliderlabs/herokuish):
-- `DB_INITIALIZE` can be set to `cd /app && RAILS_ENV=production
- bin/setup`
-- `DB_MIGRATE` can be set to `cd /app && RAILS_ENV=production bin/update`
+- `DB_INITIALIZE` can be set to `RAILS_ENV=production /bin/herokuish procfile exec bin/rails db:setup`
+- `DB_MIGRATE` can be set to `RAILS_ENV=production /bin/herokuish procfile exec bin/rails db:migrate`
-NOTE: **Note:**
-The `/app` path is the directory of your project inside the docker image
-as [configured by
-Herokuish](https://github.com/gliderlabs/herokuish#paths)
+Unless you have a `Dockerfile` in your repo, your image is built with
+Herokuish, and you must prefix commands run in these images with `/bin/herokuish
+procfile exec` to replicate the environment where your application will run.
### Auto Monitoring
-NOTE: **Note:**
-Check the [requirements](#requirements) for Auto Monitoring to make this stage
-work.
+See the [requirements](#requirements) for Auto Monitoring to enable this stage.
Once your application is deployed, Auto Monitoring makes it possible to monitor
your application's server and response metrics right out of the box. Auto
@@ -667,7 +649,7 @@ repo or by specifying a project variable:
- **Bundled chart** - If your project has a `./chart` directory with a `Chart.yaml`
file in it, Auto DevOps will detect the chart and use it instead of the [default
- one](https://gitlab.com/charts/auto-deploy-app).
+ one](https://gitlab.com/gitlab-org/charts/auto-deploy-app).
This can be a great way to control exactly how your application is deployed.
- **Project variable** - Create a [project variable](../../ci/variables/README.md#gitlab-cicd-environment-variables)
`AUTO_DEVOPS_CHART` with the URL of a custom chart to use or create two project variables `AUTO_DEVOPS_CHART_REPOSITORY` with the URL of a custom chart repository and `AUTO_DEVOPS_CHART` with the path to the chart.
@@ -675,7 +657,7 @@ repo or by specifying a project variable:
### Custom Helm chart per environment **[PREMIUM]**
You can specify the use of a custom Helm chart per environment by scoping the environment variable
-to the desired environment. See [Limiting environment scopes of variables](https://docs.gitlab.com/ee/ci/variables/#limiting-environment-scopes-of-variables-premium).
+to the desired environment. See [Limiting environment scopes of variables](../../ci/variables/README.md#limiting-environment-scopes-of-environment-variables-premium).
### Customizing `.gitlab-ci.yml`
@@ -734,13 +716,15 @@ also be customized, and you can easily use a [custom buildpack](#custom-buildpac
| **Variable** | **Description** |
| ------------ | --------------- |
-| `AUTO_DEVOPS_DOMAIN` | The [Auto DevOps domain](#auto-devops-base-domain). By default, set automatically by the [Auto DevOps setting](#enablingdisabling-auto-devops). This variable is deprecated and [is scheduled to be removed](https://gitlab.com/gitlab-org/gitlab-ce/issues/56959). Use `KUBE_INGRESS_BASE_DOMAIN` instead. |
-| `AUTO_DEVOPS_CHART` | The Helm Chart used to deploy your apps; defaults to the one [provided by GitLab](https://gitlab.com/charts/auto-deploy-app). |
+| `AUTO_DEVOPS_CHART` | The Helm Chart used to deploy your apps; defaults to the one [provided by GitLab](https://gitlab.com/gitlab-org/charts/auto-deploy-app). |
| `AUTO_DEVOPS_CHART_REPOSITORY` | The Helm Chart repository used to search for charts; defaults to `https://charts.gitlab.io`. |
+| `AUTO_DEVOPS_CHART_REPOSITORY_NAME` | From Gitlab 11.11, this variable can be used to set the name of the helm repository; defaults to "gitlab" |
+| `AUTO_DEVOPS_CHART_REPOSITORY_USERNAME` | From Gitlab 11.11, this variable can be used to set a username to connect to the helm repository. Defaults to no credentials. (Also set AUTO_DEVOPS_CHART_REPOSITORY_PASSWORD) |
+| `AUTO_DEVOPS_CHART_REPOSITORY_PASSWORD` | From Gitlab 11.11, this variable can be used to set a password to connect to the helm repository. Defaults to no credentials. (Also set AUTO_DEVOPS_CHART_REPOSITORY_USERNAME) |
| `REPLICAS` | The number of replicas to deploy; defaults to 1. |
| `PRODUCTION_REPLICAS` | The number of replicas to deploy in the production environment. This takes precedence over `REPLICAS`; defaults to 1. |
-| `CANARY_REPLICAS` | The number of canary replicas to deploy for [Canary Deployments](https://docs.gitlab.com/ee/user/project/canary_deployments.html); defaults to 1 |
-| `CANARY_PRODUCTION_REPLICAS` | The number of canary replicas to deploy for [Canary Deployments](https://docs.gitlab.com/ee/user/project/canary_deployments.html) in the production environment. This takes precedence over `CANARY_REPLICAS`; defaults to 1 |
+| `CANARY_REPLICAS` | The number of canary replicas to deploy for [Canary Deployments](../../user/project/canary_deployments.md); defaults to 1 |
+| `CANARY_PRODUCTION_REPLICAS` | The number of canary replicas to deploy for [Canary Deployments](../../user/project/canary_deployments.md) in the production environment. This takes precedence over `CANARY_REPLICAS`; defaults to 1 |
| `ADDITIONAL_HOSTS` | Fully qualified domain names specified as a comma-separated list that are added to the ingress hosts. |
| `<ENVIRONMENT>_ADDITIONAL_HOSTS` | For a specific environment, the fully qualified domain names specified as a comma-separated list that are added to the ingress hosts. This takes precedence over `ADDITIONAL_HOSTS`. |
| `POSTGRES_ENABLED` | Whether PostgreSQL is enabled; defaults to `"true"`. Set to `false` to disable the automatic deployment of PostgreSQL. |
@@ -767,6 +751,9 @@ also be customized, and you can easily use a [custom buildpack](#custom-buildpac
| `PERFORMANCE_DISABLED` | From GitLab 11.0, this variable can be used to disable the `performance` job. If the variable is present, the job will not be created. |
| `K8S_SECRET_*` | From GitLab 11.7, any variable prefixed with [`K8S_SECRET_`](#application-secret-variables) will be made available by Auto DevOps as environment variables to the deployed application. |
| `KUBE_INGRESS_BASE_DOMAIN` | From GitLab 11.8, this variable can be used to set a domain per cluster. See [cluster domains](../../user/project/clusters/index.md#base-domain) for more information. |
+| `ROLLOUT_RESOURCE_TYPE` | From GitLab 11.9, this variable allows specification of the resource type being deployed when using a custom helm chart. Default value is `deployment`. |
+| `ROLLOUT_STATUS_DISABLED` | From GitLab 12.0, this variable allows to disable rollout status check because it doesn't support all resource types, for example, `cronjob`. |
+| `HELM_UPGRADE_EXTRA_ARGS` | From GitLab 11.11, this variable allows extra arguments in `helm` commands when deploying the application. Note that using quotes will not prevent word splitting. |
TIP: **Tip:**
Set up the replica variables using a
@@ -822,11 +809,6 @@ metadata:
type: Opaque
```
-CAUTION: **Caution:**
-Variables with multiline values are not currently supported due to
-limitations with the current Auto DevOps scripting environment.
-
-NOTE: **Note:**
Environment variables are generally considered immutable in a Kubernetes
pod. Therefore, if you update an application secret without changing any
code then manually create a new pipeline, you will find that any running
@@ -835,6 +817,10 @@ can either push a code update to GitLab to force the Kubernetes
Deployment to recreate pods or manually delete running pods to
cause Kubernetes to create new pods with updated secrets.
+NOTE: **Note:**
+Variables with multiline values are not currently supported due to
+limitations with the current Auto DevOps scripting environment.
+
#### Advanced replica variables setup
Apart from the two replica-related variables for production mentioned above,
@@ -914,7 +900,7 @@ you when you're ready to manually deploy to production.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ci-yml/merge_requests/171)
in GitLab 11.0.
-A [canary environment](https://docs.gitlab.com/ee/user/project/canary_deployments.html) can be used
+A [canary environment](../../user/project/canary_deployments.md) can be used
before any changes are deployed to production.
If `CANARY_ENABLED` is defined in your project (e.g., set `CANARY_ENABLED` to
@@ -1003,8 +989,7 @@ Everything behaves the same way, except:
## Currently supported languages
-NOTE: **Note:**
-Not all buildpacks support Auto Test yet, as it's a relatively new
+Note that not all buildpacks support Auto Test yet, as it's a relatively new
enhancement. All of Heroku's [officially supported
languages](https://devcenter.heroku.com/articles/heroku-ci#currently-supported-languages)
support it, and some third-party buildpacks as well e.g., Go, Node, Java, PHP,
@@ -1094,3 +1079,7 @@ curl --data "value=true" --header "PRIVATE-TOKEN: personal_access_token" https:/
[ee]: https://about.gitlab.com/pricing/
[ce-21955]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21955
[ce-19507]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19507
+
+## Development guides
+
+Configuring [GDK for Auto DevOps](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/auto_devops.md).
diff --git a/doc/topics/autodevops/quick_start_guide.md b/doc/topics/autodevops/quick_start_guide.md
index 367e192b85a..6717e95266e 100644
--- a/doc/topics/autodevops/quick_start_guide.md
+++ b/doc/topics/autodevops/quick_start_guide.md
@@ -161,7 +161,7 @@ In the **test** stage, GitLab runs various checks on the application:
- The `code_quality` job checks the code quality and is allowed to fail
([Auto Code Quality](index.md#auto-code-quality-starter)) **[STARTER]**
- The `container_scanning` job checks the Docker container if it has any
- vulnerabilities and is allowed to fail ([Auto Container Scanning](index.md#auto-container-scanning))
+ vulnerabilities and is allowed to fail ([Auto Container Scanning](index.md#auto-container-scanning-ultimate))
- The `dependency_scanning` job checks if the application has any dependencies
susceptible to vulnerabilities and is allowed to fail ([Auto Dependency Scanning](index.md#auto-dependency-scanning-ultimate)) **[ULTIMATE]**
- The `sast` job runs static analysis on the current code to check for potential
@@ -208,7 +208,7 @@ applications. In the rightmost column for the production environment, you can ma
application is running.
Right below, there is the
-[Deploy Board](https://docs.gitlab.com/ee/user/project/deploy_boards.html).
+[Deploy Board](../../user/project/deploy_boards.md).
The squares represent pods in your Kubernetes cluster that are associated with
the given environment. Hovering above each square you can see the state of a
deployment and clicking a square will take you to the pod's logs page.
diff --git a/doc/topics/git/how_to_install_git/index.md b/doc/topics/git/how_to_install_git/index.md
index d7e1979217e..c7bede2d269 100644
--- a/doc/topics/git/how_to_install_git/index.md
+++ b/doc/topics/git/how_to_install_git/index.md
@@ -5,14 +5,20 @@ level: beginner
article_type: user guide
date: 2017-05-15
description: 'This article describes how to install Git on macOS, Ubuntu Linux and Windows.'
+type: howto
+last_updated: 2019-05-31
---
# Installing Git
-To begin contributing to GitLab projects
+To begin contributing to GitLab projects,
you will need to install the Git client on your computer.
+
This article will show you how to install Git on macOS, Ubuntu Linux and Windows.
+Information on [installing Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
+is also available at the official Git website.
+
## Install Git on macOS using the Homebrew package manager
Although it is easy to use the version of Git shipped with macOS
@@ -21,7 +27,7 @@ we recommend installing it via Homebrew to get access to
an extensive selection of dependency managed libraries and applications.
If you are sure you don't need access to any additional development libraries
-or don't have approximately 15gb of available disk space for Xcode and Homebrew
+or don't have approximately 15gb of available disk space for Xcode and Homebrew,
use one of the aforementioned methods.
### Installing Xcode
@@ -40,11 +46,12 @@ for the official Homebrew installation instructions.
With Homebrew installed you are now ready to install Git.
Open a Terminal and enter in the following command:
-```bash
+```sh
brew install git
```
Congratulations you should now have Git installed via Homebrew.
+
Next read our article on [adding an SSH key to GitLab](../../../ssh/README.md).
## Install Git on Ubuntu Linux
@@ -55,16 +62,30 @@ it is recommended to use the built in package manager to install Git.
Open a Terminal and enter in the following commands
to install the latest Git from the official Git maintained package archives:
-```bash
+```sh
sudo apt-add-repository ppa:git-core/ppa
sudo apt-get update
sudo apt-get install git
```
Congratulations you should now have Git installed via the Ubuntu package manager.
+
Next read our article on [adding an SSH key to GitLab](../../../ssh/README.md).
## Installing Git on Windows from the Git website
Browse to the [Git website](https://git-scm.com/) and download and install Git for Windows.
+
Next read our article on [adding an SSH key to GitLab](../../../ssh/README.md).
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/topics/git/index.md b/doc/topics/git/index.md
index 7707d56764e..cdcd8215b23 100644
--- a/doc/topics/git/index.md
+++ b/doc/topics/git/index.md
@@ -1,8 +1,12 @@
-# Git documentation
+---
+type: index
+---
+
+# Git
Git is a [free and open source](https://git-scm.com/about/free-and-open-source)
distributed version control system designed to handle everything from small to
-very large projects with speed and efficiency.
+large projects with speed and efficiency.
[GitLab](https://about.gitlab.com) is a Git-based fully integrated platform for
software development. Besides Git's functionalities, GitLab has a lot of
@@ -11,64 +15,73 @@ powerful [features](https://about.gitlab.com/features/) to enhance your
We've gathered some resources to help you to get the best from Git with GitLab.
+More information is also available on the [Git website](https://git-scm.com).
+
## Getting started
-- [Git concepts](../../university/training/user_training.md#git-concepts)
+The following resources will help you get started with Git:
+
+- [Git-ing started with Git](https://www.youtube.com/watch?v=Ce5nz5n41z4),
+ a video introduction to Git.
+- [Git Basics](https://git-scm.com/book/en/v2/Getting-Started-Git-Basics)
+- [Git on the Server - GitLab](https://git-scm.com/book/en/v2/Git-on-the-Server-GitLab)
- [How to install Git](how_to_install_git/index.md)
- [Start using Git on the command line](../../gitlab-basics/start-using-git.md)
- [Command Line basic commands](../../gitlab-basics/command-line-commands.md)
- [GitLab Git Cheat Sheet (download)](https://about.gitlab.com/images/press/git-cheat-sheet.pdf)
-- Commits
- - [Revert a commit](../../user/project/merge_requests/revert_changes.md#reverting-a-commit)
+- Commits:
+ - [Revert a commit](../../user/project/merge_requests/revert_changes.md#reverting-a-commit)
- [Cherry-picking a commit](../../user/project/merge_requests/cherry_pick_changes.md#cherry-picking-a-commit)
- [Squashing commits](../../workflow/gitlab_flow.md#squashing-commits-with-rebase)
-**Third-party references:**
+### Concepts
-- [Getting Started - Git website](https://git-scm.com)
-- [Getting Started - Version control](https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control)
-- [Getting Started - Git Basics](https://git-scm.com/book/en/v2/Getting-Started-Git-Basics)
-- [Getting Started - Installing Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
-- [Git on the Server - GitLab](https://git-scm.com/book/en/v2/Git-on-the-Server-GitLab)
+The following are resources about version control concepts:
-### Concepts
+- [Git concepts](../../university/training/user_training.md#git-concepts)
+- [Why Git is Worth the Learning Curve](https://about.gitlab.com/2017/05/17/learning-curve-is-the-biggest-challenge-developers-face-with-git/)
+- [The future of SaaS hosted Git repository pricing](https://about.gitlab.com/2016/05/11/git-repository-pricing/)
+- [Git website topic about version control](https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control)
+- [GitLab University presentation about Version Control](https://docs.google.com/presentation/d/16sX7hUrCZyOFbpvnrAFrg6tVO5_yT98IgdAqOmXwBho/edit?usp=sharing)
-- Article (2017-05-17): [Why Git is Worth the Learning Curve](https://about.gitlab.com/2017/05/17/learning-curve-is-the-biggest-challenge-developers-face-with-git/)
-- Article (2016-05-11): [The future of SaaS hosted Git repository pricing](https://about.gitlab.com/2016/05/11/git-repository-pricing/)
-- GLU Course (Presentation): [About Version Control](https://docs.google.com/presentation/d/16sX7hUrCZyOFbpvnrAFrg6tVO5_yT98IgdAqOmXwBho/edit?usp=sharing)
+## Git tips
-## Exploring Git
+The following resources may help you become more efficient at using Git:
- [Git Tips & Tricks](https://about.gitlab.com/2016/12/08/git-tips-and-tricks/)
- [Eight Tips to help you work better with Git](https://about.gitlab.com/2015/02/19/8-tips-to-help-you-work-better-with-git/)
## Troubleshooting Git
+If you have problems with Git, the following may help:
+
- [Numerous _undo_ possibilities in Git](numerous_undo_possibilities_in_git/index.md)
-- Learn a few [Git troubleshooting](troubleshooting_git.md) techniques to help you out.
+- Learn a few [Git troubleshooting](troubleshooting_git.md) techniques
## Branching strategies
-- [GitLab Flow](https://about.gitlab.com/2014/09/29/gitlab-flow/)
-
-**Third-party references:**
-
- [Git Branching - Branches in a Nutshell](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell)
- [Git Branching - Branching Workflows](https://git-scm.com/book/en/v2/Git-Branching-Branching-Workflows)
+- [GitLab Flow](https://about.gitlab.com/2014/09/29/gitlab-flow/)
## Advanced use
+The following are advanced topics for those who want to get the most out of Git:
+
- [Custom Git Hooks](../../administration/custom_hooks.md)
- [Git Attributes](../../user/project/git_attributes.md)
- Git Submodules: [Using Git submodules with GitLab CI](../../ci/git_submodules.md#using-git-submodules-with-gitlab-ci)
## API
-- [Gitignore templates](../../api/templates/gitignores.md)
+[Gitignore templates](../../api/templates/gitignores.md) API allow for
+Git-related queries from GitLab.
## Git LFS
+The following relate to Git Large File Storage:
+
- [Getting Started with Git LFS](https://about.gitlab.com/2017/01/30/getting-started-with-git-lfs-tutorial/)
- [GitLab Git LFS documentation](../../workflow/lfs/manage_large_binaries_with_git_lfs.md)
-- [Git-Annex to Git-LFS migration guide](https://docs.gitlab.com/ee/workflow/lfs/migrate_from_git_annex_to_git_lfs.html)
-- Article (2015-08-13): [Towards a production quality open source Git LFS server](https://about.gitlab.com/2015/08/13/towards-a-production-quality-open-source-git-lfs-server/)
+- [Git-Annex to Git-LFS migration guide](../../workflow/lfs/migrate_from_git_annex_to_git_lfs.md)
+- [Towards a production quality open source Git LFS server](https://about.gitlab.com/2015/08/13/towards-a-production-quality-open-source-git-lfs-server/)
diff --git a/doc/topics/git/numerous_undo_possibilities_in_git/index.md b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
index 8a8021dc36d..84201e11831 100644
--- a/doc/topics/git/numerous_undo_possibilities_in_git/index.md
+++ b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
@@ -4,25 +4,30 @@ author_gitlab: Letme
level: intermediary
article_type: tutorial
date: 2017-05-15
+type: howto
+last_updated: 2019-05-31
---
# Numerous undo possibilities in Git
-## Introduction
-
In this tutorial, we will show you different ways of undoing your work in Git, for which
we will assume you have a basic working knowledge of. Check GitLab's
-[Git documentation](../index.md#git-documentation) for reference.
+[Git documentation](../index.md) for reference.
+
Also, we will only provide some general info of the commands, which is enough
-to get you started for the easy cases/examples, but for anything more advanced please refer to the [Git book](https://git-scm.com/book/en/v2).
+to get you started for the easy cases/examples, but for anything more advanced
+please refer to the [Git book](https://git-scm.com/book/en/v2).
We will explain a few different techniques to undo your changes based on the stage
of the change in your current development. Also, keep in mind that [nothing in
-Git is really deleted.][git-autoclean-ref]
+Git is really deleted][git-autoclean-ref].
+
This means that until Git automatically cleans detached commits (which cannot be
accessed by branch or tag) it will be possible to view them with `git reflog` command
and access them with direct commit-id. Read more about _[redoing the undo](#redoing-the-undo)_ on the section below.
+## Introduction
+
This guide is organized depending on the [stage of development][git-basics]
where you want to undo your changes from and if they were shared with other developers
or not. Because Git is tracking changes a created or edited file is in the unstaged state
@@ -31,35 +36,41 @@ a file into the **staged** state, which is then committed (`git commit`) to your
local repository. After that, file can be shared with other developers (`git push`).
Here's what we'll cover in this tutorial:
- - [Undo local changes](#undo-local-changes) which were not pushed to remote repository
+- [Undo local changes](#undo-local-changes) which were not pushed to remote repository:
- - Before you commit, in both unstaged and staged state
- - After you committed
+ - Before you commit, in both unstaged and staged state.
+ - After you committed.
- - Undo changes after they are pushed to remote repository
+- Undo changes after they are pushed to remote repository:
- - [Without history modification](#undo-remote-changes-without-changing-history) (preferred way)
- - [With history modification](#undo-remote-changes-with-modifying-history) (requires
- coordination with team and force pushes).
- - [Usecases when modifying history is generally acceptable](#where-modifying-history-is-generally-acceptable)
- - [How to modify history](#how-modifying-history-is-done)
- - [How to remove sensitive information from repository](#deleting-sensitive-information-from-commits)
+ - [Without history modification](#undo-remote-changes-without-changing-history) (preferred way).
+ - [With history modification](#undo-remote-changes-with-modifying-history) (requires
+ coordination with team and force pushes).
+ - [Use cases when modifying history is generally acceptable](#where-modifying-history-is-generally-acceptable).
+ - [How to modify history](#how-modifying-history-is-done).
+ - [How to remove sensitive information from repository](#deleting-sensitive-information-from-commits).
### Branching strategy
[Git][git-official] is a de-centralized version control system, which means that beside regular
versioning of the whole repository, it has possibilities to exchange changes
-with other repositories. To avoid chaos with
+with other repositories.
+
+To avoid chaos with
[multiple sources of truth][git-distributed], various
development workflows have to be followed, and it depends on your internal
workflow how certain changes or commits can be undone or changed.
+
[GitLab Flow][gitlab-flow] provides a good
balance between developers clashing with each other while
developing the same feature and cooperating seamlessly, but it does not enable
joined development of the same feature by multiple developers by default.
+
When multiple developers develop the same feature on the same branch, clashing
with every synchronization is unavoidable, but a proper or chosen Git Workflow will
-prevent that anything is lost or out of sync when feature is complete. You can also
+prevent that anything is lost or out of sync when feature is complete.
+
+You can also
read through this blog post on [Git Tips & Tricks][gitlab-git-tips-n-tricks]
to learn how to easily **do** things in Git.
@@ -97,19 +108,19 @@ no changes added to commit (use "git add" and/or "git commit -a")
At this point there are 3 options to undo the local changes you have:
-- Discard all local changes, but save them for possible re-use [later](#quickly-save-local-changes)
+- Discard all local changes, but save them for possible re-use [later](#quickly-save-local-changes):
```shell
git stash
```
-- Discarding local changes (permanently) to a file
+- Discarding local changes (permanently) to a file:
```shell
git checkout -- <file>
```
-- Discard all local changes to all files permanently
+- Discard all local changes to all files permanently:
```shell
git reset --hard
@@ -150,7 +161,7 @@ of the staging tree. You also have an option to discard all changes with
Lets start the example by editing a file, with your favorite editor, to change the
content and add it to staging
-```
+```sh
vim <file>
git add <file>
```
@@ -164,30 +175,30 @@ Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
- new file: <file>
+ new file: <file>
```
Now you have 4 options to undo your changes:
-- Unstage the file to current commit (HEAD)
+- Unstage the file to current commit (HEAD):
```shell
git reset HEAD <file>
```
-- Unstage everything - retain changes
+- Unstage everything - retain changes:
```shell
git reset
```
-- Discard all local changes, but save them for [later](#quickly-save-local-changes)
+- Discard all local changes, but save them for [later](#quickly-save-local-changes):
```shell
git stash
```
-- Discard everything permanently
+- Discard everything permanently:
```shell
git reset --hard
@@ -206,7 +217,9 @@ your code, you'll have less options to troubleshoot your work.
Through the development process some of the previously committed changes do not
fit anymore in the end solution, or are source of the bugs. Once you find the
commit which triggered bug, or once you have a faulty commit, you can simply
-revert it with `git revert commit-id`. This command inverts (swaps) the additions and
+revert it with `git revert commit-id`.
+
+This command inverts (swaps) the additions and
deletions in that commit, so that it does not modify history. Retaining history
can be helpful in future to notice that some changes have been tried
unsuccessfully in the past.
@@ -225,19 +238,19 @@ through simple bisection process. You can read more about it [in official Git To
In our example we will end up with commit `B`, that introduced bug/error. We have
4 options on how to remove it (or part of it) from our repository.
-- Undo (swap additions and deletions) changes introduced by commit `B`.
+- Undo (swap additions and deletions) changes introduced by commit `B`:
```shell
git revert commit-B-id
```
-- Undo changes on a single file or directory from commit `B`, but retain them in the staged state
+- Undo changes on a single file or directory from commit `B`, but retain them in the staged state:
```shell
git checkout commit-B-id <file>
```
-- Undo changes on a single file or directory from commit `B`, but retain them in the unstaged state
+- Undo changes on a single file or directory from commit `B`, but retain them in the unstaged state:
```shell
git reset commit-B-id <file>
@@ -246,7 +259,9 @@ In our example we will end up with commit `B`, that introduced bug/error. We hav
- There is one command we also must not forget: **creating a new branch**
from the point where changes are not applicable or where the development has hit a
dead end. For example you have done commits `A-B-C-D` on your feature-branch
- and then you figure `C` and `D` are wrong. At this point you either reset to `B`
+ and then you figure `C` and `D` are wrong.
+
+ At this point you either reset to `B`
and do commit `F` (which will cause problems with pushing and if forced pushed also with other developers)
since branch now looks `A-B-F`, which clashes with what other developers have locally (you will
[change history](#with-history-modification)), or you simply checkout commit `B` create
@@ -269,13 +284,13 @@ In our example we will end up with commit `B`, that introduced bug/error. We hav
There is one command for history modification and that is `git rebase`. Command
provides interactive mode (`-i` flag) which enables you to:
- - **reword** commit messages (there is also `git commit --amend` for editing
- last commit message)
- - **edit** the commit content (changes introduced by commit) and message
- - **squash** multiple commits into a single one, and have a custom or aggregated
- commit message
- - **drop** commits - simply delete them
- - and few more options
+- **reword** commit messages (there is also `git commit --amend` for editing
+ last commit message).
+- **edit** the commit content (changes introduced by commit) and message.
+- **squash** multiple commits into a single one, and have a custom or aggregated
+ commit message.
+- **drop** commits - simply delete them.
+- and few more options.
Let us check few examples. Again there are commits `A-B-C-D` where you want to
delete commit `B`.
@@ -301,7 +316,7 @@ In case you want to modify something introduced in commit `B`.
- Command opens your favorite text editor where you write `edit` in front of commit
`B`, but leave default `pick` with all other commits. Save and exit the editor to
- perform a rebase
+ perform a rebase.
- Now do your edits and commit changes:
@@ -348,7 +363,9 @@ and then on end description of that action.
This topic is roughly same as modifying committed local changes without modifying
history. **It should be the preferred way of undoing changes on any remote repository
or public branch.** Keep in mind that branching is the best solution when you want
-to retain the history of faulty development, yet start anew from certain point. Branching
+to retain the history of faulty development, yet start anew from certain point.
+
+Branching
enables you to include the existing changes in new development (by merging) and
it also provides a clear timeline and development structure.
@@ -386,12 +403,14 @@ the cleanup of detached commits (happens automatically).
Modified history breaks the development chain of other developers, as changed
history does not have matching commits'ids. For that reason it should not
be used on any public branch or on branch that *might* be used by other
-developers. When contributing to big open source repositories (e.g. [GitLab CE][gitlab-ce]),
+developers. When contributing to big open source repositories (for example, [GitLab CE][gitlab-ce]),
it is acceptable to *squash* commits into a single one, to present
a nicer history of your contribution.
+
Keep in mind that this also removes the comments attached to certain commits
in merge requests, so if you need to retain traceability in GitLab, then
modifying history is not acceptable.
+
A feature-branch of a merge request is a public branch and might be used by
other developers, but project process and rules might allow or require
you to use `git rebase` (command that changes history) to reduce number of
@@ -400,8 +419,8 @@ GitLab). There is a `git merge --squash` command which does exactly that
(squashes commits on feature-branch to a single commit on target branch
at merge).
->**Note:**
-Never modify the commit history of `master` or shared branch
+NOTE: **Note:**
+Never modify the commit history of `master` or shared branch.
### How modifying history is done
@@ -436,7 +455,7 @@ pick <commit3-id> <commit3-commit-message>
# Note that empty commits are commented out
```
->**Note:**
+NOTE: **Note:**
It is important to notice that comment from the output clearly states that, if
you decide to abort, then do not just close your editor (as that will in-fact
modify history), but remove all uncommented lines and save.
@@ -470,7 +489,7 @@ tools that can use some of Git specifics to enable faster execution of common
tasks (which is exactly what removing sensitive information file is about).
An alternative is [BFG Repo-cleaner][bfg-repo-cleaner]. Keep in mind that these
tools are faster because they do not provide a same fully feature set as `git filter-branch`
-does, but focus on specific usecases.
+does, but focus on specific use cases.
## Conclusion
@@ -480,6 +499,18 @@ depending on the stage of your process. Git also enables rewriting history, but
should be avoided as it might cause problems when multiple developers are
contributing to the same codebase.
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
+
<!-- Identifiers, in alphabetical order -->
[bfg-repo-cleaner]: https://rtyley.github.io/bfg-repo-cleaner/
diff --git a/doc/topics/git/troubleshooting_git.md b/doc/topics/git/troubleshooting_git.md
index d1729d70158..417d91bf834 100644
--- a/doc/topics/git/troubleshooting_git.md
+++ b/doc/topics/git/troubleshooting_git.md
@@ -1,3 +1,7 @@
+---
+type: howto
+---
+
# Troubleshooting Git
Sometimes things don't work the way they should or as you might expect when
@@ -9,7 +13,7 @@ with Git.
'Broken pipe' errors can occur when attempting to push to a remote repository.
When pushing you will usually see:
-```
+```text
Write failed: Broken pipe
fatal: The remote end hung up unexpectedly
```
@@ -39,14 +43,15 @@ There's another option where you can prevent session timeouts by configuring
SSH 'keep alive' either on the client or on the server (if you are a GitLab
admin and have access to the server).
-NOTE: **Note:** configuring *both* the client and the server is unnecessary.
+NOTE: **Note:**
+Configuring *both* the client and the server is unnecessary.
**To configure SSH on the client side**:
-- On UNIX, edit `~/.ssh/config` (create the file if it doesn’t exist) and
- add or edit:
+- On UNIX, edit `~/.ssh/config` (create the file if it doesn’t exist) and
+ add or edit:
- ```
+ ```text
Host your-gitlab-instance-url.com
ServerAliveInterval 60
ServerAliveCountMax 5
@@ -58,7 +63,7 @@ NOTE: **Note:** configuring *both* the client and the server is unnecessary.
**To configure SSH on the server side**, edit `/etc/ssh/sshd_config` and add:
-```
+```text
ClientAliveInterval 60
ClientAliveCountMax 5
```
@@ -78,13 +83,40 @@ git push
In case you're running an older version of Git (< 2.9), consider upgrading
to >= 2.9 (see [Broken pipe when pushing to Git repository][Broken-Pipe]).
+## `ssh_exchange_identification` error
+
+Users may experience the following error when attempting to push or pull
+using Git over SSH:
+
+```text
+Please make sure you have the correct access rights
+and the repository exists.
+...
+ssh_exchange_identification: read: Connection reset by peer
+fatal: Could not read from remote repository.
+```
+
+This error usually indicates that SSH daemon's `MaxStartups` value is throttling
+SSH connections. This setting specifies the maximum number of unauthenticated
+connections to the SSH daemon. This affects users with proper authentication
+credentials (SSH keys) because every connection is 'unauthenticated' in the
+beginning. The default value is `10`.
+
+Increase `MaxStartups` by adding or modifying the value in `/etc/ssh/sshd_config`:
+
+```text
+MaxStartups 100
+```
+
+Restart SSHD for the change to take effect.
+
## Timeout during git push/pull
If pulling/pushing from/to your repository ends up taking more than 50 seconds,
-a timeout will be issued with a log of the number of operations performed
+a timeout will be issued with a log of the number of operations performed
and their respective timings, like the example below:
-```
+```text
remote: Running checks for branch: master
remote: Scanning for LFS objects... (153ms)
remote: Calculating new repository size... (cancelled after 729ms)
diff --git a/doc/university/README.md b/doc/university/README.md
index cf13246067f..c116e54ad48 100644
--- a/doc/university/README.md
+++ b/doc/university/README.md
@@ -1,5 +1,6 @@
---
comments: false
+type: index
---
# GitLab University
@@ -8,26 +9,22 @@ GitLab University is a great place to start when learning about version control
If you're looking for a GitLab subscription for _your university_, see our [Education](https://about.gitlab.com/solutions/education/) page.
-## GitLab University Curriculum
+The GitLab University curriculum is composed of GitLab videos, screencasts, presentations, projects and external GitLab content hosted on other services and has been organized into the following sections:
-The curriculum is composed of GitLab videos, screencasts, presentations, projects and external GitLab content hosted on other services and has been organized into the following sections.
+1. [GitLab Beginner](#1-gitlab-beginner).
+1. [GitLab Intermediate](#2-gitlab-intermediate).
+1. [GitLab Advanced](#3-gitlab-advanced).
+1. [External Articles](#4-external-articles).
+1. [Resources for GitLab Team Members](#5-resources-for-gitlab-team-members).
-1. [GitLab Beginner](#1-gitlab-beginner)
-1. [GitLab Intermediate](#2-gitlab-intermediate)
-1. [GitLab Advanced](#3-gitlab-advanced)
-1. [External Articles](#4-external-articles)
-1. [Resources for GitLab Team Members](#5-resources-for-gitlab-team-members)
+## 1. GitLab Beginner
----
-
-### 1. GitLab Beginner
-
-#### 1.1. Version Control and Git
+### 1.1. Version Control and Git
1. [Version Control Systems](https://docs.google.com/presentation/d/16sX7hUrCZyOFbpvnrAFrg6tVO5_yT98IgdAqOmXwBho/edit#slide=id.g72f2e4906_2_29)
1. [Code School: An Introduction to Git](https://www.codeschool.com/account/courses/try-git)
-#### 1.2. GitLab Basics
+### 1.2. GitLab Basics
1. [An Overview of GitLab.com - Video](https://www.youtube.com/watch?v=WaiL5DGEMR4)
1. [Why Use Git and GitLab - Slides](https://docs.google.com/a/gitlab.com/presentation/d/1RcZhFmn5VPvoFu6UMxhMOy7lAsToeBZRjLRn0LIdaNc/edit?usp=drive_web)
@@ -36,12 +33,12 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
1. [Git and GitLab Basics - Online Course](https://courses.platzi.com/classes/git-gitlab/concepto/part-1/part-23370/material/)
1. [Comparison of GitLab Versions](https://about.gitlab.com/features/#compare)
-#### 1.3. Your GitLab Account
+### 1.3. Your GitLab Account
1. [Create a GitLab Account - Online Course](https://courses.platzi.com/classes/git-gitlab/concepto/first-steps/create-an-account-on-gitlab/material/)
1. [Create and Add your SSH key to GitLab - Video](https://www.youtube.com/watch?v=54mxyLo3Mqk)
-#### 1.4. GitLab Projects
+### 1.4. GitLab Projects
1. [Repositories, Projects and Groups - Video](https://www.youtube.com/watch?v=4TWfh1aKHHw&index=1&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
1. [Creating a Project in GitLab - Video](https://www.youtube.com/watch?v=7p0hrpNaJ14)
@@ -49,14 +46,14 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
1. [GitLab Todos](https://about.gitlab.com/2016/03/02/gitlab-todos-feature-highlight/)
1. [GitLab's Work in Progress (WIP) Flag](https://about.gitlab.com/2016/01/08/feature-highlight-wip/)
-#### 1.5. Migrating from other Source Control
+### 1.5. Migrating from other Source Control
-1. [Migrating from BitBucket/Stash](https://docs.gitlab.com/ee/user/project/import/bitbucket.html)
-1. [Migrating from GitHub](https://docs.gitlab.com/ee/user/project/import/github.html)
-1. [Migrating from SVN](https://docs.gitlab.com/ee/user/project/import/svn.html)
-1. [Migrating from Fogbugz](https://docs.gitlab.com/ee/user/project/import/fogbugz.html)
+1. [Migrating from BitBucket/Stash](../user/project/import/bitbucket.md)
+1. [Migrating from GitHub](../user/project/import/github.md)
+1. [Migrating from SVN](../user/project/import/svn.md)
+1. [Migrating from Fogbugz](../user/project/import/fogbugz.md)
-#### 1.6. GitLab Inc.
+### 1.6. GitLab Inc.
1. [About GitLab](https://about.gitlab.com/about/)
1. [GitLab Direction](https://about.gitlab.com/direction/)
@@ -67,7 +64,7 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
1. [The GitLab Book Club](bookclub/index.md)
1. [GitLab Resources](https://about.gitlab.com/resources/)
-#### 1.7 Community and Support
+### 1.7 Community and Support
1. [Getting Help](https://about.gitlab.com/getting-help/)
- Proposing Features and Reporting and Tracking bugs for GitLab
@@ -79,22 +76,19 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
1. [GitLab Training Workshops](https://docs.gitlab.com/ce/university/training/end-user/)
1. [GitLab Professional Services](https://about.gitlab.com/services/)
-#### 1.8 GitLab Training Material
+### 1.8 GitLab Training Material
-1. [Git and GitLab Terminology](glossary/README.md)
1. [Git and GitLab Workshop - Slides](https://docs.google.com/presentation/d/1JzTYD8ij9slejV2-TO-NzjCvlvj6mVn9BORePXNJoMI/edit?usp=drive_web)
----
-
-### 2. GitLab Intermediate
+## 2. GitLab Intermediate
-#### 2.1 GitLab Pages
+### 2.1 GitLab Pages
1. [Using any Static Site Generator with GitLab Pages](https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/)
1. [Securing GitLab Pages with SSL](https://about.gitlab.com/2016/06/24/secure-gitlab-pages-with-startssl/)
-1. [GitLab Pages Documentation](https://docs.gitlab.com/ce/user/project/pages/)
+1. [GitLab Pages Documentation](../user/project/pages/index.md)
-#### 2.2. GitLab Issues
+### 2.2. GitLab Issues
1. [Markdown in GitLab](../user/markdown.md)
1. [Issues and Merge Requests - Video](https://www.youtube.com/watch?v=raXvuwet78M)
@@ -106,7 +100,7 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
1. [Designing GitLab Issue Board](https://about.gitlab.com/2016/08/31/designing-issue-boards/)
1. [From Idea to Production with GitLab - Video](https://www.youtube.com/watch?v=25pHyknRgEo&index=14&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
-#### 2.3. Continuous Integration
+### 2.3. Continuous Integration
1. [Operating Systems, Servers, VMs, Containers and Unix - Video](https://www.youtube.com/watch?v=V61kL6IC-zY&index=8&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
1. [GitLab CI - Product Page](https://about.gitlab.com/gitlab-ci/)
@@ -125,15 +119,15 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
1. [TechBeacon: Doing continuous delivery? Focus first on reducing release cycle times](https://techbeacon.com/doing-continuous-delivery-focus-first-reducing-release-cycle-times)
1. See **[Integrations](#39-integrations)** for integrations with other CI services.
-#### 2.4. Workflow
+### 2.4. Workflow
1. [GitLab Flow - Video](https://youtu.be/enMumwvLAug?list=PLFGfElNsQthZnwMUFi6rqkyUZkI00OxIV)
1. [GitLab Flow vs Forking in GitLab - Video](https://www.youtube.com/watch?v=UGotqAUACZA)
1. [GitLab Flow Overview](https://about.gitlab.com/2014/09/29/gitlab-flow/)
1. [Always Start with an Issue](https://about.gitlab.com/2016/03/03/start-with-an-issue/)
-1. [GitLab Flow Documentation](https://docs.gitlab.com/ee/workflow/gitlab_flow.html)
+1. [GitLab Flow Documentation](../workflow/gitlab_flow.md)
-#### 2.5. GitLab Comparisons
+### 2.5. GitLab Comparisons
1. [GitLab Compared to Other Tools](https://about.gitlab.com/comparison/)
1. [Comparing GitLab Terminology](https://about.gitlab.com/2016/01/27/comparing-terms-gitlab-github-bitbucket/)
@@ -141,17 +135,15 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
1. [GitLab Position FAQ](https://about.gitlab.com/handbook/positioning-faq)
1. [Customer review of GitLab with points on why they prefer GitLab](https://www.enovate.co.uk/web-design-blog/2015/11/25/gitlab-review/)
----
+## 3. GitLab Advanced
-### 3. GitLab Advanced
-
-#### 3.1. Dev Ops
+### 3.1. Dev Ops
1. [Xebia Labs: Dev Ops Terminology](https://xebialabs.com/glossary/)
1. [Xebia Labs: Periodic Table of DevOps Tools](https://xebialabs.com/periodic-table-of-devops-tools/)
1. [Puppet Labs: State of Dev Ops 2016 - Book](https://puppet.com/resources/white-paper/2016-state-of-devops-report)
-#### 3.2. Installing GitLab with Omnibus
+### 3.2. Installing GitLab with Omnibus
1. [What is Omnibus - Video](https://www.youtube.com/watch?v=XTmpKudd-Oo)
1. [How to Install GitLab with Omnibus - Video](https://www.youtube.com/watch?v=Q69YaOjqNhg)
@@ -161,62 +153,58 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
1. [Installing GitLab on Microsoft Azure](https://about.gitlab.com/2016/07/13/how-to-setup-a-gitlab-instance-on-microsoft-azure/)
1. [Installing GitLab on Digital Ocean](https://about.gitlab.com/2016/04/27/getting-started-with-gitlab-and-digitalocean/)
-#### 3.3. Permissions
+### 3.3. Permissions
1. [How to Manage Permissions in GitLab EE - Video](https://www.youtube.com/watch?v=DjUoIrkiNuM)
-#### 3.4. Large Files
+### 3.4. Large Files
1. [Big files in Git (Git LFS) - Video](https://www.youtube.com/watch?v=DawznUxYDe4)
-#### 3.5. LDAP and Active Directory
+### 3.5. LDAP and Active Directory
1. [How to Manage LDAP, Active Directory in GitLab - Video](https://www.youtube.com/watch?v=HPMjM-14qa8)
-#### 3.6 Custom Languages
+### 3.6 Custom Languages
1. [How to add Syntax Highlighting Support for Custom Languages to GitLab - Video](https://youtu.be/6WxTMqatrrA)
-#### 3.7. Scalability and High Availability
+### 3.7. Scalability and High Availability
1. [Scalability and High Availability - Video](https://www.youtube.com/watch?v=cXRMJJb6sp4&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e&index=2)
1. [High Availability - Video](https://www.youtube.com/watch?v=36KS808u6bE&index=15&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
1. [High Availability Documentation](https://about.gitlab.com/high-availability/)
-#### 3.8 Cycle Analytics
+### 3.8 Cycle Analytics
1. [GitLab Cycle Analytics Overview](https://about.gitlab.com/2016/09/21/cycle-analytics-feature-highlight/)
1. [GitLab Cycle Analytics - Product Page](https://about.gitlab.com/product/cycle-analytics/)
-#### 3.9. Integrations
+### 3.9. Integrations
1. [How to Integrate JIRA and Jenkins with GitLab - Video](https://gitlabmeetings.webex.com/gitlabmeetings/ldr.php?RCID=44b548147a67ab4d8a62274047146415)
-1. [How to Integrate Jira with GitLab](https://docs.gitlab.com/ce/user/project/integrations/jira.html)
-1. [How to Integrate Jenkins with GitLab](https://docs.gitlab.com/ee/integration/jenkins.html)
-1. [How to Integrate Bamboo with GitLab](https://docs.gitlab.com/ce/user/project/integrations/bamboo.html)
-1. [How to Integrate Slack with GitLab](https://docs.gitlab.com/ce/user/project/integrations/slack.html)
+1. [How to Integrate Jira with GitLab](../user/project/integrations/jira.md)
+1. [How to Integrate Jenkins with GitLab](../integration/jenkins.md)
+1. [How to Integrate Bamboo with GitLab](../user/project/integrations/bamboo.md)
+1. [How to Integrate Slack with GitLab](../user/project/integrations/slack.md)
1. [How to Integrate Convox with GitLab](https://about.gitlab.com/2016/06/09/continuous-delivery-with-gitlab-and-convox/)
1. [Getting Started with GitLab and Shippable CI](https://about.gitlab.com/2016/05/05/getting-started-gitlab-and-shippable/)
----
-
-### 4. External Articles
+## 4. External Articles
1. [2011 WSJ article by Marc Andreessen - Software is Eating the World](https://www.wsj.com/articles/SB10001424053111903480904576512250915629460)
1. [2014 Blog post by Chris Dixon - Software eats software development](http://cdixon.org/2014/04/13/software-eats-software-development/)
1. [2015 Venture Beat article - Actually, Open Source is Eating the World](http://venturebeat.com/2015/12/06/its-actually-open-source-software-thats-eating-the-world/)
----
-
-### 5. Resources for GitLab Team Members
+## 5. Resources for GitLab Team Members
NOTE: **Note:**
-Some content can only be accessed by GitLab team members
+Some content can only be accessed by GitLab team members.
1. [Support Path](support/README.md)
-1. [Sales Path (redirect to sales handbook)](https://about.gitlab.com/handbook/sales-onboarding/)
+1. [Sales Path](https://about.gitlab.com/handbook/sales-onboarding/)
1. [User Training](training/user_training.md)
1. [GitLab Flow Training](training/gitlab_flow.md)
-1. [Training Topics](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/university/training/topics/)
-1. [GitLab architecture for noobs](https://dev.gitlab.org/gitlab/gitlabhq/blob/master/doc/development/architecture.md)
+1. [Training Topics](training/index.md)
+1. [GitLab architecture](../development/architecture.md)
1. [Client Assessment of GitLab versus GitHub](https://docs.google.com/a/gitlab.com/spreadsheets/d/18cRF9Y5I6I7Z_ab6qhBEW55YpEMyU4PitZYjomVHM-M/edit?usp=sharing)
diff --git a/doc/university/bookclub/booklist.md b/doc/university/bookclub/booklist.md
index d5662be6fa6..33298e45393 100644
--- a/doc/university/bookclub/booklist.md
+++ b/doc/university/bookclub/booklist.md
@@ -1,117 +1,118 @@
---
comments: false
+type: index
---
# Books
-List of books and resources, that may be worth reading.
+List of books and resources that may be worth reading.
## Papers
-1. **The Humble Programmer**
+1. **The Humble Programmer**
- Edsger W. Dijkstra, 1972 ([paper](https://dl.acm.org/citation.cfm?id=361591))
+ Edsger W. Dijkstra, 1972 ([paper](https://dl.acm.org/citation.cfm?id=361591))
## Programming
-1. **Design Patterns: Elements of Reusable Object-Oriented Software**
+1. **Design Patterns: Elements of Reusable Object-Oriented Software**
- Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides, 1994 ([amazon](https://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612))
+ Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides, 1994 ([amazon](https://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612))
-1. **Clean Code: A Handbook of Agile Software Craftsmanship**
+1. **Clean Code: A Handbook of Agile Software Craftsmanship**
- Robert C. "Uncle Bob" Martin, 2008 ([amazon](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882))
+ Robert C. "Uncle Bob" Martin, 2008 ([amazon](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882))
-1. **Code Complete: A Practical Handbook of Software Construction**, 2nd Edition
+1. **Code Complete: A Practical Handbook of Software Construction**, 2nd Edition
- Steve McConnell, 2004 ([amazon](https://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670))
+ Steve McConnell, 2004 ([amazon](https://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670))
-1. **The Pragmatic Programmer: From Journeyman to Master**
+1. **The Pragmatic Programmer: From Journeyman to Master**
- Andrew Hunt, David Thomas, 1999 ([amazon](https://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X))
+ Andrew Hunt, David Thomas, 1999 ([amazon](https://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X))
-1. **Working Effectively with Legacy Code**
+1. **Working Effectively with Legacy Code**
- Michael Feathers, 2004 ([amazon](https://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052))
+ Michael Feathers, 2004 ([amazon](https://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052))
-1. **Eloquent Ruby**
+1. **Eloquent Ruby**
- Russ Olsen, 2011 ([amazon](https://www.amazon.com/Eloquent-Ruby-Addison-Wesley-Professional/dp/0321584104))
+ Russ Olsen, 2011 ([amazon](https://www.amazon.com/Eloquent-Ruby-Addison-Wesley-Professional/dp/0321584104))
-1. **Domain-Driven Design: Tackling Complexity in the Heart of Software**
+1. **Domain-Driven Design: Tackling Complexity in the Heart of Software**
- Eric Evans, 2003 ([amazon](https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215))
+ Eric Evans, 2003 ([amazon](https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215))
-1. **How to Solve It: A New Aspect of Mathematical Method**
+1. **How to Solve It: A New Aspect of Mathematical Method**
- Polya G. 1957 ([amazon](https://www.amazon.com/How-Solve-Mathematical-Princeton-Science/dp/069116407X))
+ Polya G. 1957 ([amazon](https://www.amazon.com/How-Solve-Mathematical-Princeton-Science/dp/069116407X))
-1. **Software Creativity 2.0**
+1. **Software Creativity 2.0**
- Robert L. Glass, 2006 ([amazon](https://www.amazon.com/Software-Creativity-2-0-Robert-Glass/dp/0977213315))
+ Robert L. Glass, 2006 ([amazon](https://www.amazon.com/Software-Creativity-2-0-Robert-Glass/dp/0977213315))
-1. **Object-Oriented Software Construction**
+1. **Object-Oriented Software Construction**
- Bertrand Meyer, 1997 ([amazon](https://www.amazon.com/Object-Oriented-Software-Construction-Book-CD-ROM/dp/0136291554))
+ Bertrand Meyer, 1997 ([amazon](https://www.amazon.com/Object-Oriented-Software-Construction-Book-CD-ROM/dp/0136291554))
-1. **Refactoring: Improving the Design of Existing Code**
+1. **Refactoring: Improving the Design of Existing Code**
- Martin Fowler, Kent Beck, 1999 ([amazon](https://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672))
+ Martin Fowler, Kent Beck, 1999 ([amazon](https://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672))
-1. **Test Driven Development: By Example**
+1. **Test Driven Development: By Example**
- Kent Beck, 2002 ([amazon](https://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530))
+ Kent Beck, 2002 ([amazon](https://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530))
-1. **Algorithms in C++: Fundamentals, Data Structure, Sorting, Searching**
+1. **Algorithms in C++: Fundamentals, Data Structure, Sorting, Searching**
- Robert Sedgewick, 1990 ([amazon](https://www.amazon.com/Algorithms-Parts-1-4-Fundamentals-Structure/dp/0201350882))
+ Robert Sedgewick, 1990 ([amazon](https://www.amazon.com/Algorithms-Parts-1-4-Fundamentals-Structure/dp/0201350882))
-1. **Effective C++**
+1. **Effective C++**
- Scott Mayers, 1996 ([amazon](https://www.amazon.com/Effective-Specific-Improve-Programs-Designs/dp/0321334876))
+ Scott Mayers, 1996 ([amazon](https://www.amazon.com/Effective-Specific-Improve-Programs-Designs/dp/0321334876))
-1. **Extreme Programming Explained: Embrace Change**
+1. **Extreme Programming Explained: Embrace Change**
- Kent Beck, 1999 ([amazon](https://www.amazon.com/Extreme-Programming-Explained-Embrace-Change/dp/0321278658))
+ Kent Beck, 1999 ([amazon](https://www.amazon.com/Extreme-Programming-Explained-Embrace-Change/dp/0321278658))
-1. **The Art of Computer Programming**
+1. **The Art of Computer Programming**
- Donald E. Knuth, 1997 ([amazon](https://www.amazon.com/Computer-Programming-Volumes-1-4A-Boxed/dp/0321751043))
+ Donald E. Knuth, 1997 ([amazon](https://www.amazon.com/Computer-Programming-Volumes-1-4A-Boxed/dp/0321751043))
-1. **Writing Efficient Programs**
+1. **Writing Efficient Programs**
- Jon Louis Bentley, 1982 ([amazon](https://www.amazon.com/Writing-Efficient-Programs-Prentice-Hall-Software/dp/013970244X))
+ Jon Louis Bentley, 1982 ([amazon](https://www.amazon.com/Writing-Efficient-Programs-Prentice-Hall-Software/dp/013970244X))
-1. **The Mythical Man-Month: Essays on Software Engineering**
+1. **The Mythical Man-Month: Essays on Software Engineering**
- Frederick Phillips Brooks, 1975 ([amazon](https://www.amazon.com/Mythical-Man-Month-Essays-Software-Engineering/dp/0201006502))
+ Frederick Phillips Brooks, 1975 ([amazon](https://www.amazon.com/Mythical-Man-Month-Essays-Software-Engineering/dp/0201006502))
-1. **Peopleware: Productive Projects and Teams** 3rd Edition
+1. **Peopleware: Productive Projects and Teams** 3rd Edition
- Tom DeMarco, Tim Lister, 2013 ([amazon](https://www.amazon.com/Peopleware-Productive-Projects-Teams-3rd/dp/0321934113))
+ Tom DeMarco, Tim Lister, 2013 ([amazon](https://www.amazon.com/Peopleware-Productive-Projects-Teams-3rd/dp/0321934113))
-1. **Principles Of Software Engineering Management**
+1. **Principles Of Software Engineering Management**
- Tom Gilb, 1988 ([amazon](https://www.amazon.com/Principles-Software-Engineering-Management-Gilb/dp/0201192462))
+ Tom Gilb, 1988 ([amazon](https://www.amazon.com/Principles-Software-Engineering-Management-Gilb/dp/0201192462))
## Other
-1. **Thinking, Fast and Slow**
+1. **Thinking, Fast and Slow**
- Daniel Kahneman, 2013 ([amazon](https://www.amazon.com/Thinking-Fast-Slow-Daniel-Kahneman/dp/0374533555))
+ Daniel Kahneman, 2013 ([amazon](https://www.amazon.com/Thinking-Fast-Slow-Daniel-Kahneman/dp/0374533555))
-1. **The Social Animal** 11th Edition
+1. **The Social Animal** 11th Edition
- Elliot Aronson, 2011 ([amazon](https://www.amazon.com/Social-Animal-Elliot-Aronson/dp/1429233419))
+ Elliot Aronson, 2011 ([amazon](https://www.amazon.com/Social-Animal-Elliot-Aronson/dp/1429233419))
-1. **Influence: Science and Practice** 5th Edition
+1. **Influence: Science and Practice** 5th Edition
- Robert B. Cialdini, 2008 ([amazon](https://www.amazon.com/Influence-Practice-Robert-B-Cialdini/dp/0205609996))
+ Robert B. Cialdini, 2008 ([amazon](https://www.amazon.com/Influence-Practice-Robert-B-Cialdini/dp/0205609996))
-1. **Getting to Yes: Negotiating Agreement Without Giving In**
+1. **Getting to Yes: Negotiating Agreement Without Giving In**
- Roger Fisher, William L. Ury, Bruce Patton, 2011 ([amazon](https://www.amazon.com/Getting-Yes-Negotiating-Agreement-Without/dp/0143118757))
+ Roger Fisher, William L. Ury, Bruce Patton, 2011 ([amazon](https://www.amazon.com/Getting-Yes-Negotiating-Agreement-Without/dp/0143118757))
-1. **How to Win Friends & Influence People**
+1. **How to Win Friends & Influence People**
- Dale Carnegie, 1981 ([amazon](https://www.amazon.com/How-Win-Friends-Influence-People/dp/0671027034))
+ Dale Carnegie, 1981 ([amazon](https://www.amazon.com/How-Win-Friends-Influence-People/dp/0671027034))
diff --git a/doc/university/bookclub/index.md b/doc/university/bookclub/index.md
index 63238685b2b..330078e979f 100644
--- a/doc/university/bookclub/index.md
+++ b/doc/university/bookclub/index.md
@@ -1,5 +1,6 @@
---
comments: false
+type: index
---
# The GitLab Book Club
@@ -11,13 +12,13 @@ See the [book list](booklist.md) for additional recommendations.
## Currently reading : Books about remote work
-1. **Remote: Office not required**
+1. **Remote: Office not required**
- David Heinemeier Hansson and Jason Fried, 2013
- ([amazon](http://www.amazon.co.uk/Remote-Required-David-Heinemeier-Hansson/dp/0091954673))
+ David Heinemeier Hansson and Jason Fried, 2013
+ ([amazon](http://www.amazon.co.uk/Remote-Required-David-Heinemeier-Hansson/dp/0091954673))
-1. **The Year Without Pants**
+1. **The Year Without Pants**
- Scott Berkun, 2013 ([ScottBerkun.com](http://scottberkun.com/yearwithoutpants/))
+ Scott Berkun, 2013 ([ScottBerkun.com](http://scottberkun.com/yearwithoutpants/))
Any other books you'd like to suggest? Edit this page and add them to the queue.
diff --git a/doc/university/glossary/README.md b/doc/university/glossary/README.md
index 0af2f8d2f54..21e2da3e47c 100644
--- a/doc/university/glossary/README.md
+++ b/doc/university/glossary/README.md
@@ -2,707 +2,10 @@
comments: false
---
-# What is the Glossary
+# Glossary
-This contains a simplified list and definitions of some of the terms that you will encounter in your day to day activities when working with GitLab.
-Please add any terms that you discover that you think would be useful for others.
+This page has been removed after an effort to ensure that all applicable GitLab-specific
+terms are available in context on the relevant [GitLab Documentation](https://docs.gitlab.com/)
+or [about.gitlab.com](https://about.gitlab.com/) pages.
-### 2FA
-
-User authentication by combination of 2 different steps during login. This allows for [more security](https://about.gitlab.com/handbook/security/).
-
-### Access Levels
-
-Process of selective restriction to create, view, modify or delete a resource based on a set of assigned permissions. See [GitLab's Permission Guidelines](../../user/permissions.md)
-
-### Active Directory (AD)
-
-A Microsoft-based [directory service](https://msdn.microsoft.com/en-us/library/bb742424.aspx) for windows domain networks. It uses LDAP technology under the hood.
-
-### Agile
-
-Building and [delivering software](http://agilemethodology.org/) in phases/parts rather than trying to build everything at once then delivering to the user/client. The latter is known as the WaterFall model.
-
-### Amazon RDS
-
-External reference: <http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html>
-
-### Application Lifecycle Management (ALM)
-
-The entire product lifecycle management process for an application, from requirements management, development, and testing until deployment. GitLab has [advantages](https://docs.google.com/presentation/d/1vCU-NbZWz8NTNK8Vu3y4zGMAHb5DpC8PE5mHtw1PWfI/edit#slide=id.g72f2e4906_2_288) over both legacy and modern ALM tools.
-
-### Artifactory
-
-A version control [system](https://www.jfrog.com/open-source/#os-arti) for non-text files.
-
-### Artifacts
-
-Objects (usually binary and large) created by a build process. These can include use cases, class diagrams, requirements and design documents.
-
-### Atlassian
-
-A [company](https://www.atlassian.com) that develops software products for developers and project managers including Bitbucket, Jira, Hipchat, Confluence, Bamboo.
-
-### Audit Log
-
-Also called an [audit trail](https://en.wikipedia.org/wiki/Audit_trail), an audit log is a document that records an event in an IT system.
-
-### Auto Defined User Group
-
-User groups are a way of centralizing control over important management tasks, particularly access control and password policies. A simple example of such groups are the users and the admins groups.
-In most of the cases these groups are auto defined in terms of access, rules of usage, conditions to be part of, etc.
-
-### Bamboo
-
-Atlassian's CI tool similar to GitLab CI and Jenkins.
-
-### Basic Subscription
-
-Entry level [subscription](https://about.gitlab.com/pricing/) for GitLab EE currently available in packs of 10.
-
-### Bitbucket
-
-Atlassian's web hosting service for Git and Mercurial Projects. Read about [migrating](https://docs.gitlab.com/ce/workflow/importing/import_projects_from_bitbucket.html) from BitBucket to a GitLab instance.
-
-### Branch
-
-A branch is a parallel version of a repository. This allows you to work on the repository without affecting the "master" branch, and without affecting the current "live" version. When you have made all your changes to your branch you can then merge to the master. When your merge request is accepted your changes will be "live."
-
-### Branded Login
-
-Having your own logo on [your GitLab instance login page](https://docs.gitlab.com/ee/customization/branded_login_page.html) instead of the GitLab logo.
-
-### Job triggers (Build Triggers)
-These protect your code base against breaks, for instance when a team is working on the same project. Learn about [setting up](https://docs.gitlab.com/ce/ci/triggers/README.html) job triggers.
-
-### CEPH
-
- A distributed object store and file [system](http://ceph.com/) designed to provide excellent performance, reliability and scalability.
-
-### ChatOps
-
-The ability to [initiate an action](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/1412) from chat. ChatBots run in your chat application and give you the ability to do "anything" from chat.
-
-### Clone
-
-A [copy](https://git-scm.com/docs/git-clone) of a repository stored on your machine that allows you to use your own editor without being online, but still tracks the changes made remotely.
-
-### Code Review
-
-Examination of a program's code. The main aim is to maintain high quality standards of code that is being shipped. Merge requests [serve as a code review tool](https://about.gitlab.com/2014/09/29/gitlab-flow/) in GitLab.
-
-### Code Snippet
-
-A small amount of code, usually selected for the purpose of showing other developers how to do something specific or reproduce a problem.
-
-### Collaborator
-
-Person with read and write access to a repository who has been invited by repository owner.
-
-### Commit
-
-A [change](https://git-scm.com/docs/git-commit) (revision) to a file that also creates an ID, allowing you to see revision history and the author of the changes.
-
-### Community
-
-[Everyone](https://about.gitlab.com/community/) who uses GitLab.
-
-### Confluence
-
-Atlassian's product for collaboration on documents and projects.
-
-### Continuous Delivery
-
-A [software engineering approach](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) in which continuous integration, automated testing, and automated deployment capabilities allow software to be developed and deployed rapidly, reliably and repeatedly with minimal human intervention. Still, the deployment to production is defined strategically and triggered manually. [Amazon moves toward continuous delivery](https://www.youtube.com/watch?v=esEFaY0FDKc)
-
-### Continuous Deployment
-
-A [software development practice](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) in which every code change goes through the entire pipeline and is put into production automatically, resulting in many production deployments every day. It does everything that Continuous Delivery does, but the process is fully automated, there's no human intervention at all. [The difference between Continuous Delivery and Continuous Integration.](https://www.youtube.com/watch?v=igwFj8PPSnw)
-
-### Continuous Integration
-
-A [software development practice](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) in which you build and test software every time a developer pushes code to the application, and it happens several times a day. [Thoughtworks discusses continuous integration.](https://www.thoughtworks.com/continuous-integration)
-
-### Contributor
-
-Term used for a person contributing to an open source project.
-
-### Conversational Development (ConvDev)
-
-A [natural evolution](https://about.gitlab.com/2016/09/14/gitlab-live-event-recap/) of software development that carries a conversation across functional groups throughout the development process, enabling developers to track the full path of development in a cohesive and intuitive way. ConvDev accelerates the development lifecycle by fostering collaboration and knowledge sharing from idea to production.
-
-### Cycle Analytics
-
-See <https://gitlab.com/gitlab-org/gitlab-ce/issues/22458>
-
-### Cycle Time
-
-The time it takes to move from [idea to production](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#from-idea-to-production-with-gitlab).
-
-### Data Centre
-
-Atlassian product for High Availability.
-
-### Dependencies
-
-As in "specify [dependencies](https://gitlab.com/gitlab-org/gitlab-ce/issues/14728) between stages."
-
-### Deploy Keys
-
-A [SSH key](https://docs.gitlab.com/ce/gitlab-basics/create-your-ssh-keys.html)stored on your server that grants access to a single GitLab repository. This is used by a GitLab runner to clone a project's code so that tests can be run against the checked out code.
-
-### Developer
-
-For us at GitLab, this means a software developer, or someone who makes software. It is also one of the levels of access in our multi-level approval system.
-
-### DevOps
-
-The intersection of software engineering, quality assurance, and technology operations. Explore more DevOps topics in the [glossary by XebiaLabs](https://xebialabs.com/glossary/)
-
-### Diff
-
-The difference between two commits, or saved changes. This will also be shown visually after the changes.
-
-### Directory
-
-A folder used for storing multiple files.
-
-### Docker Container Registry
-
-A [feature](https://docs.gitlab.com/ce/user/project/container_registry.html) of [GitLab projects](https://about.gitlab.com/2016/05/23/gitlab-container-registry/). Containers wrap up a piece of software in a complete filesystem that contains everything it needs to run: code, runtime, system tools, system libraries – anything you can install on a server. This guarantees that it will always run the same, regardless of the environment it is running in.
-
-### Dynamic Environment (review apps)
-
-### EC2 Instance
-
-### Elasticsearch
-
-Elasticsearch is a flexible, scalable and powerful search service. When [enabled](https://gitlab.com/help/integration/elasticsearch.md), it helps keep GitLab's search fast when dealing with a huge amount of data.
-
-### Emacs
-
-External reference: <https://www.masteringemacs.org/article/mastering-key-bindings-emacs>
-
-### First Byte
-
-External reference: <https://en.wikipedia.org/wiki/Time_To_First_Byte>
-
-First Byte (sometimes referred to as time to first byte or [TTFB](https://en.wikipedia.org/wiki/Time_To_First_Byte)) measures the time between making a request and receiving the first byte of information in return. As a result, First Byte encompasses everything that is the backend as well as network transit issues. It differs from [_Speed Index_](#speed-index) mostly by frontend related issues which are included in Speed Index such as javascript loading, page rendering, and so on.
-
-### Fork
-
-Your [own copy](https://docs.gitlab.com/ce/workflow/forking_workflow.html) of a repository that allows you to make changes to the repository without affecting the original.
-
-### Funnel, or: TOFU, MOFU, BOFU
-
-External reference: [Blog post](https://www.weidert.com/whole_brain_marketing_blog/bid/113688/ToFu-MoFu-BoFu-Serving-Up-The-Right-Content-for-Lead-Nurturing)
-
-TOFU: top of funnel
-MOFU: middle of funnel
-BOFU: bottom of funnel
-
-### Gerrit
-
-A code review [tool](https://www.gerritcodereview.com/) built on top of Git.
-
-### Git Attributes
-
-A [git attributes file](https://git-scm.com/docs/gitattributes) is a simple text file that gives attributes to pathnames.
-
-### Git Hooks
-
-[Scripts](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) you can use to trigger actions at certain points.
-
-Difference between a [webhook](#webhooks) and a git hook: a git hook is local to its repo (usually) while a webhook is not (it can make API or http calls). So for example if you want your linter to fire before you commit, you can set that up with a git hook. If the linter fails, the commit does not go through. A git hook _can_ be configured to go beyond its repo, e.g. by having it make an API call.
-
-### GitHost.io
-
-A single-tenant solution that provides GitLab CE or EE as a managed service. GitLab Inc. is responsible for installing, updating, hosting, and backing up customers' own private and secure GitLab instance.
-
-### GitHub
-
-A web-based Git repository hosting service with an enterprise offering. Its main features are: issue tracking, pull request with code review, abundancy of integrations and wiki. It offers free public repos, private repos and enterprise services are paid. Read about [importing a project](https://docs.gitlab.com/ce/workflow/importing/import_projects_from_github.html) from GitHub to GitLab.
-
-### GitLab CE
-
-Our free on Premise solution with >100,000 users
-
-### GitLab CI
-
-Our own Continuous Integration [feature](https://about.gitlab.com/gitlab-ci/) that is shipped with each instance
-
-### GitLab EE
-
-Our premium on premise [solution](https://about.gitlab.com/features/#enterprise) that currently has Basic, Standard and Plus subscription packages with additional features and support.
-
-### GitLab.com
-
-Our free SaaS for public and private repositories.
-
-### GitLab Geo
-
-Allows you to replicate your GitLab instance to other geographical locations as a read-only fully operational version. It [can be used](https://docs.gitlab.com/ee/administration/geo/replication/index.html) for cloning and fetching projects, in addition to reading any data. This will make working with large repositories over large distances much faster.
-
-### GitLab High Availability
-
-### GitLab Master Plan
-
-Related blog post: <https://about.gitlab.com/2016/09/13/gitlab-master-plan/>.
-
-### GitLab Pages
-
-These allow you to [create websites](https://gitlab.com/help/pages/README.md) for your GitLab projects, groups, or user account.
-
-### GitLab Runner
-
-Related project: <https://gitlab.com/gitlab-org/gitlab-runner>
-
-### Gitolite
-
-An [access layer](https://git-scm.com/book/en/v1/Git-on-the-Server-Gitolite) that sits on top of Git. Users are granted access to repos via a simple config file. As an admin, you only need the users' public SSH key and a username.
-
-### Gitorious
-
-A web-based hosting service for projects using Git. It was acquired by GitLab and we discontinued the service. Read the[Gitorious Acquisition Blog Post](https://about.gitlab.com/2015/03/03/gitlab-acquires-gitorious/).
-
-### Go
-
-An open source programming [language](https://golang.org/).
-
-### Gogs
-
-External reference: <https://gogs.io/>
-
-### GUI/ Git GUI
-
-A portable [graphical interface](https://git-scm.com/docs/git-gui) to Git that allows users to make changes to their repository by making new commits, amending existing ones, creating branches, performing local merges, and fetching/pushing to remote repositories.
-
-### High Availability for Disaster Recovery (HADR)
-
-Sometimes written HA/DR, this usually refers to a strategy for having a failover server in place in case the main server fails.
-
-### Hip Chat
-
-Atlassian's real time chat application for teams, Hip Chat is a competitor to Slack, RocketChat and MatterMost.
-
-### High Availability
-
-Refers to a [system or component](https://about.gitlab.com/high-availability/) that is continuously operational for a desirably long length of time. Availability can be measured relative to "100% operational" or "never failing."
-
-### Inner-sourcing
-
-The [use of](https://about.gitlab.com/2014/09/05/innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization/) open source development techniques within the corporation.
-
-### Internet Relay Chat (IRC)
-
-An [application layer protocol](http://www.irchelp.org/) that facilitates communication in the form of text.
-
-### Issue Tracker
-
-A [tool](https://docs.gitlab.com/ee/integration/external-issue-tracker.html) used to manage, organize, and maintain a list of issues, making it easier for an organization to manage.
-
-### Jenkins
-
-An Open Source CI tool written using the Java programming language. [Jenkins](https://jenkins.io/) does the same job as GitLab CI, Bamboo, and Travis CI. It is extremely popular. Related [documentation](https://docs.gitlab.com/ee/integration/jenkins.html).
-
-### Jira
-
-Atlassian's [project management software](https://www.atlassian.com/software/jira), i.e. a complex issue tracker. GitLab [can be configured](https://docs.gitlab.com/ee/project_services/jira.html) to interact with JIRA Core either using an on-premise instance or the SaaS solution that Atlassian offers.
-
-### JUnit
-
-A testing framework for the Java programming language, [JUnit](http://junit.org/junit4/) has been important in the evolution of test-driven development.
-
-### Kerberos
-
-A network authentication [protocol](http://web.mit.edu/kerberos/) that uses secret-key cryptography for security.
-
-### Kubernetes
-
-An open source container cluster manager originally designed by Google. It's basically a platform for automating deployment, scaling, and operations of application containers over clusters of hosts.
-
-### Labels
-
-An [identifier](https://docs.gitlab.com/ce/user/project/labels.html) to describe a group of one or more specific file revisions.
-
-### Lightweight Directory Access Protocol (LDAP)
-
- A directory (electronic address book) with user information (e.g. name, phone_number etc.)
-
-### LDAP User Authentication
-
-GitLab [integrates](https://docs.gitlab.com/ce/administration/auth/ldap.html) with LDAP to support user authentication. This enables GitLab to sign in people from an LDAP server (i.e., allowing people whose names are on the electronic user directory server to be able to use their LDAP accounts to login.)
-
-### LDAP Group Sync
-
-Allows you to synchronize the members of a GitLab group with one or more LDAP groups.
-
-### Lint
-
-Static code analysis for our various file types. For example, we use [scss-lint](https://github.com/brigade/scss-lint) to ensure that a consistent code styling is respected. Similar tools: rubocop / eslint.
-
-### Load Balancer
-
-A [device](https://en.wikipedia.org/wiki/Load_balancing_(computing)) that distributes network or application traffic across multiple servers.
-
-### Git Large File Storage (LFS)
-
-A way [to enable](https://about.gitlab.com/2015/11/23/announcing-git-lfs-support-in-gitlab/) git to handle large binary files by using reference pointers within small text files to point to the large files. Large files such as high resolution images and videos, audio files, and assets can be called from a remote server.
-
-### Linux
-
-An operating system like Windows or OS X. It is mostly used by software developers and on servers.
-
-### Markdown
-
-A lightweight markup language with plain text formatting syntax designed so that it can be converted to HTML and many other formats using a tool by the same name. Markdown is often used to format readme files, for writing messages in online discussion forums, and to create rich text using a plain text editor. Checkout GitLab's [Markdown guide](https://gitlab.com/help/user/markdown.md).
-
-### Maria DB
-
-A community developed fork/variation of MySQL. MySQL is owned by Oracle.
-
-### Master
-
-Name of the [default branch](https://git-scm.com/book/en/v1/Git-Branching-What-a-Branch-Is) in every git repository.
-
-### Mattermost
-
-An open source, self-hosted messaging alternative to Slack. View GitLab's Mattermost [feature](https://gitlab.com/gitlab-org/gitlab-mattermost).
-
-### Mercurial
-
-A free distributed version control system similar to and a competitor with Git.
-
-### Merge
-
-Takes changes from one branch, and [applies them](https://git-scm.com/docs/git-merge) into another branch.
-
-### Merge Conflict
-
-[Arises](https://about.gitlab.com/2016/09/06/resolving-merge-conflicts-from-the-gitlab-ui/) when a merge can't be performed cleanly between two versions of the same file.
-
-#### Merge Request
-
-[Takes changes](https://docs.gitlab.com/ce/gitlab-basics/add-merge-request.html) from one branch, and applies them into another branch.
-
-### Meteor
-
-A [platform](https://www.meteor.com) for building javascript apps.
-
-### Milestones
-
-Allow you to [organize issues](../../user/project/milestones/index.md) and merge requests in GitLab into a cohesive group, optionally setting a due date. A common use is keeping track of an upcoming software version. Milestones are created per-project.
-
-### Mirror Repositories
-
-A project that is set up to automatically have its branches, tags, and commits [updated from an upstream repository](https://docs.gitlab.com/ee/workflow/repository_mirroring.html). This is useful when a repository you're interested in is located on a different server, and you want to be able to browse its content and activity using the familiar GitLab interface.
-
-### MIT License
-
-A type of software license. It lets people do anything with your code with proper attribution and without warranty. It is the most common license for open source applications written in Ruby on Rails. GitLab CE is issued under this [license](https://docs.gitlab.com/ce/development/licensing.html). This means you can download the code, modify it as you want, and even build a new commercial product using the underlying code and it's not illegal. The only condition is that there is no form of warranty provided by GitLab so whatever happens when you use the code is your own problem.
-
-### Mondo Rescue
-
-A free disaster recovery [software](https://help.ubuntu.com/community/MondoMindi).
-
-#### Mount
-
-External reference:
-
-As stated on the [wikipedia page](https://en.wikipedia.org/wiki/Mount_(Unix)), "Mounting makes file systems, files, directories, devices and special files available for use and available to the user."
-
-For example, we have NFS servers where the _git files_ reside. In order for a worker node to "see" or "use" the git files, the NFS server needs to be _mounted_ on the worker; that is, the worker needs to know that the NFS server exists and how to connect to it. Think of it as getting a shared drive to show up in your Finder (on Mac) or Explorer (on Windows).
-
-### MySQL
-
-A relational [database](http://www.mysql.com/) owned by Oracle. Currently only supported if you are using EE.
-
-### Namespace
-
-A set of symbols that are used to organize objects of various kinds so that these objects may be referred to by name. Examples of namespaces in action include file systems that assign names to files; programming languages that organize their variables and subroutines in namespaces; and computer networks and distributed systems that assign names to resources, such as computers, printers, websites, (remote) files, etc.
-
-### Nginx
-
-A web [server](https://www.nginx.com/resources/wiki/) (pronounced "engine x"). [It can act](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/nginx.md) as a reverse proxy server for HTTP, HTTPS, SMTP, POP3, and IMAP protocols, as well as a load balancer and an HTTP cache.
-
-### OAuth
-
-An open standard for authorization, commonly used as a way for internet users to log into third party websites using their Microsoft, Google, Facebook or Twitter accounts without exposing their password. GitLab [is](https://docs.gitlab.com/ce/integration/oauth_provider.html) an OAuth2 authentication service provider.
-
-### Omnibus Packages
-
-A way to [package different services and tools](https://docs.gitlab.com/omnibus/) required to run GitLab, so that most developers can install it without laborious configuration.
-
-### On Premise
-
-On your own server. In GitLab, this [refers](https://about.gitlab.com/2015/02/12/why-ship-on-premises-in-the-saas-era/) to the ability to download GitLab EE/GitLab CE and host it on your own server rather than using GitLab.com, which is hosted by GitLab Inc's servers.
-
-### Open Core
-
-GitLab's [business model](https://about.gitlab.com/2016/07/20/gitlab-is-open-core-github-is-closed-source/). Coined by Andrew Lampitt in 2008, the [open core model](https://en.wikipedia.org/wiki/Open_core) primarily involves offering a "core" or feature-limited version of a software product as free and open-source software, while offering "commercial" versions or add-ons as proprietary software.
-
-### Open Source Software
-
-Software for which the original source code is freely [available](https://opensource.org/docs/osd) and may be redistributed and modified. GitLab prioritizes open source [stewardship](https://about.gitlab.com/2016/01/11/being-a-good-open-source-steward/). Including to providing access to the source code, open source software must comply with a number of criteria, among them free distribution and no discrimination against persons, groups, or fields of endeavor.
-
-#### Open Source Stewardship
-
-[Related blog post](https://about.gitlab.com/2016/01/11/being-a-good-open-source-steward/).
-
-### Owner
-
-The most powerful person on a GitLab project. They have the permissions of all the other users plus the additional permission of being able to destroy (i.e. delete) the project.
-
-### Platform as a Service (PaaS)
-
-Typically referred to in regards to application development, PaaS is a model in which a cloud provider delivers hardware and software tools to its users as a service.
-
-### Perforce
-
-The company that produces Helix. A commercial, proprietary, centralised VCS well known for its ability to version files of any size and type. They OEM a re-branded version of GitLab called "GitSwarm" that is tightly integrated with their "GitFusion" product, which in turn represents a portion of a Helix repository (called a depot) as a git repo.
-
-### Phabricator
-
-A suite of web-based software development collaboration tools, including the Differential code review tool, the Diffusion repository browser, the Herald change monitoring tool, the Maniphest bug tracker and the Phriction wiki. Phabricator integrates with Git, Mercurial, and Subversion.
-
-### Piwik Analytics
-
-An open source analytics software to help you analyze web traffic. It is similar to Google Analytics, except that the latter is not open source and information is stored by Google. In Piwik, the information is stored on your own server and hence is fully private.
-
-### Plus Subscription
-
-GitLab Premium EE [subscription](https://about.gitlab.com/pricing/) that includes training and dedicated Account Management and Service Engineer and complete support package.
-
-### PostgreSQL
-
-An [object-relational](https://en.wikipedia.org/wiki/PostgreSQL) database. Touted as the most advanced open source database, it is one of two database management systems [supported by](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/database.md) GitLab, the other being MySQL.
-
-### Protected Branches
-
-A [feature](https://docs.gitlab.com/ce/user/project/protected_branches.html) that protects branches from unauthorized pushes, force pushing or deletion.
-
-### Protected Tags
-
-A [feature](https://docs.gitlab.com/ce/user/project/protected_tags.html) that protects tags from unauthorized creation, update or deletion
-
-### Pull
-
-Git command to [synchronize](https://git-scm.com/docs/git-pull) the local repository with the remote repository, by fetching all remote changes and merging them into the local repository.
-
-### Puppet
-
-A popular DevOps [automation tool](https://puppet.com/product/how-puppet-works).
-
-### Push
-
-Git [command](https://git-scm.com/docs/git-push) to send commits from the local repository to the remote repository. Read about [advanced push rules](https://gitlab.com/help/pages/README.md) in GitLab.
-
-### Raketasks
-
-### RE Read Only
-
-Permissions to see a file and its contents, but not change it.
-
-### Rebase
-
-In addition to the merge, the [rebase](https://git-scm.com/book/en/v2/Git-Branching-Rebasing) is a main way to integrate changes from one branch into another.
-
-### Regression
-
-A regression is something that used to work one way in the last release and then we made a **breaking change** and it no longer works the same way.
-
-_or_
-
-A regression is defined as a change that results in a negative impact on the functionality of an existing feature due to recent changes, i.e. the latest release.
-
-### Remote mirroring
-
-### (Git) Repository
-
-A directory where Git [has been initiatlized](https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository) to start version controlling your files. The history of your work is stored here. A remote repository is not on your machine, but usually online (like on GitLab.com, for instance). The main remote repository is usually called "Origin."
-
-##### Remote repository
-
-A [repository](https://about.gitlab.com/2015/05/18/simple-words-for-a-gitlab-newbie/) that is not-on-your-machine, so it's anything that is not your computer. Usually, it is online, GitLab.com for instance. The main remote repository is usually called “Originâ€.
-
-### Requirements management
-
-Gives your distributed teams a single shared repository to collaborate and share requirements, understand their relationship to tests, and evaluate linked defects. It includes multiple, preconfigured requirement types.
-
-### Revision Control
-
-Also known as version control or source control, this is the management of changes to documents, computer programs, large web sites, and other collections of information. Changes are usually identified by a number or letter code, termed the "revision number," "revision level," or simply "revision."
-
-### RocketChat
-
-An open source chat application for teams, RocketChat is very similar to Slack but it is also open-source.
-
-### Route Table
-
-A route table contains rules (called routes) that determine where network traffic is directed. Each [subnet in a VPC](http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Route_Tables.html) must be associated with a route table.
-
-### Runners
-
-Actual build machines/containers that [run and execute tests](https://gitlab.com/gitlab-org/gitlab-runner) you have specified to be run on GitLab CI.
-
-### Sidekiq
-
-The background job processor GitLab [uses](https://docs.gitlab.com/ce/administration/troubleshooting/sidekiq.html) to asynchronously run tasks.
-
-### Software as a service (SaaS)
-
-Software that is hosted centrally and accessed on-demand (i.e. whenever you want to). This applies to GitLab.com.
-
-### Software Configuration Management (SCM)
-
-This term is often used by people when they mean "Version Control."
-
-### Scrum
-
-An Agile [framework](https://www.scrum.org/Resources/What-is-Scrum) designed to typically help complete complex software projects. It's made up of several parts: product requirements backlog, sprint planning, sprint (development), sprint review, and retrospec (analyzing the sprint). The goal is to end up with potentially shippable products.
-
-### Scrum Board
-
-The board used to track the status and progress of each of the sprint backlog items.
-
-### Shell
-
-Terminal on Mac OSX, GitBash on Windows, or Linux Terminal on Linux. You [use git](https://docs.gitlab.com/ce/gitlab-basics/start-using-git.html) and make changes to GitLab projects in your shell. You [use git](https://docs.gitlab.com/ce/gitlab-basics/start-using-git.html) and make changes to GitLab projects in your shell.
-
-### Shell command runner
-
-### Single-tenant
-
-The tenant purchases their own copy of the software and the software can be customized to meet the specific and needs of that customer. [GitHost.io](https://about.gitlab.com/handbook/positioning-faq/) is our provider of single-tenant 'managed cloud' GitLab instances.
-
-### Slack
-
-Real time messaging app for teams that is used internally by GitLab team members. GitLab users can enable [Slack integration](https://docs.gitlab.com/ce/project_services/slack.html) to trigger push, issue, and merge request events among others.
-
-### Slash commands
-
-### Slave Servers
-
-Also known as secondary servers, these help to spread the load over multiple machines. They also provide backups when the master/primary server crashes.
-
-### Source Code
-
-Program code as typed by a computer programmer (i.e. it has not yet been compiled/translated by the computer to machine language).
-
-### Speed Index
-
-[Speed Index](https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/metrics/speed-index) is "the average time at which visible parts of the page are displayed".
-
-### SSH Key
-
-A unique identifier of a computer. It is used to identify computers without the need for a password (e.g., On GitLab I have [added the ssh key](https://docs.gitlab.com/ce/gitlab-basics/create-your-ssh-keys.html) of all my work machines so that the GitLab instance knows that it can accept code pushes and pulls from this trusted machines whose keys are I have added.)
-
-### Single Sign On (SSO)
-
-An authentication process that allows you enter one username and password to access multiple applications.
-
-### Staging Area
-
-[Staging occurs](https://git-scm.com/book/en/v2/Getting-Started-Git-Basics) before the commit process in git. The staging area is a file, generally contained in your Git directory, that stores information about what will go into your next commit. It’s sometimes referred to as the “index.""
-
-### Standard Subscription
-
-Our mid range EE subscription that includes 24/7 support and support for High Availability [Standard Subscription](https://about.gitlab.com/pricing/).
-
-### Stash
-
-Atlassian's Git on-premise solution. Think of it as Atlassian's GitLab EE, now known as BitBucket Server.
-
-### Static Site Generators (SSGs)
-
-A [software](https://wiki.python.org/moin/StaticSiteGenerator) that takes some text and templates as input and produces html files on the output.
-
-### Subversion
-
-Non-proprietary, centralized version control system.
-
-### Sudo
-
-A program that allows you to perform superuser/administrator actions on Unix Operating Systems (e.g., Linux, OS X.) It actually stands for 'superuser do.'
-
-### Subversion (SVN)
-
-An open source version control system. Read about [migrating from SVN](https://docs.gitlab.com/ce/workflow/importing/migrating_from_svn.html) to GitLab using SubGit.
-
-### Tag
-
-[Represents](https://docs.gitlab.com/ce/api/tags.html) a version of a particular branch at a moment in time.
-
-### Tenancy
-
-#### Multi-tenant
-
-A [multi-tenant](http://whatis.techtarget.com/definition/multi-tenancy) GitLab instance can have any number of customers - such as companies or groups of users using it. GitLab.com is an example of a multi-tenant GitLab instance.
-
-#### Single-tenant
-
-A [single-tenant](http://searchcloudapplications.techtarget.com/definition/single-tenancy) GitLab instance has only one customer - such as a company - using it. On premise GitLab instances are almost exclusively single-tenant.
-
-### Tool Stack
-
-The set of tools used in a process to achieve a common outcome (e.g. set of tools used in Application Lifecycle Management).
-
-### Trac
-
-An open source project management and bug tracking web [application](https://trac.edgewall.org/).
-
-### True-Up licensing model
-
-### Ubuntu
-
-### Untracked files
-
-New files that Git has not [been told](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository) to track previously. Add them by using the command "git add [file path]"
-
-### Upstream repository vs. GitLab repository
-
-[External conversation](https://news.ycombinator.com/item?id=12487112)
-
-### User
-
-Anyone interacting with the software.
-
-### Version Control Software (VCS)
-
-Version control is a system that records changes to a file or set of files over time so that you can recall specific versions later. VCS [has evolved](https://docs.google.com/presentation/d/16sX7hUrCZyOFbpvnrAFrg6tVO5_yT98IgdAqOmXwBho/edit#slide=id.gd69537a19_0_32) from local version control systems, to centralized version control systems, to the present [distributed version control systems](https://en.wikipedia.org/wiki/Distributed_version_control) like Git, Mercurial, Bazaar, and Darcs. If any server dies, and these systems were collaborating via it, any of the client repositories can be copied back up to the server to restore it.
-
-### Virtual Private Cloud (VPC)
-
-A [VPC](https://docs.gitlab.com/ce/university/glossary/README.html#virtual-private-cloud-vpc) is an on demand configurable pool of shared computing resources allocated within a public cloud environment, providing some isolation between the different users using the resources. GitLab users need to create a new Amazon VPC in order to [set up High Availability](https://docs.gitlab.com/ce/university/high-availability/aws/).
-
-### Virtual private server (VPS)
-
-A [virtual machine](https://en.wikipedia.org/wiki/Virtual_private_server) sold as a service by an Internet hosting service. A VPS runs its own copy of an operating system, and customers have superuser-level access to that operating system instance, so they can install almost any software that runs on that OS.
-
-### VM Instance
-
-In object-oriented programming, an [instance](http://stackoverflow.com/questions/20461907/what-is-meaning-of-instance-in-programming) is a specific realization of any [object](https://cloud.google.com/compute/docs/instances/). An object may be varied in a number of ways. Each realized variation of that object is an instance. Therefore, a VM instance is an instance of a virtual machine, which is an emulation of a computer system.
-
-### Waterfall
-
-A [model](http://www.umsl.edu/~hugheyd/is6840/waterfall.html) of building software that involves collecting all requirements from the customer, then building and refining all the requirements and finally delivering the complete software to the customer that meets all the requirements they specified.
-
-### Webhooks
-
-A way for an app to [provide](https://docs.gitlab.com/ce/user/project/integrations/webhooks.html) other applications with real-time information (e.g., send a message to a slack channel when a commit is pushed.) Read about setting up [custom git hooks](https://gitlab.com/help/administration/custom_hooks.md) for when webhooks are insufficient.
-
-### Wiki
-
-A [website/system](http://www.wiki.com/) that allows for collaborative editing of its content by the users. In programming, wikis usually contain documentation of how to use the software.
-
-### Working area
-
-Files that have been modified but are not committed. Check them by using the command "git status".
-
-### Working Tree
-
-[Consists of files](http://stackoverflow.com/questions/3689838/difference-between-head-working-tree-index-in-git) that you are currently working on.
-
-### YAML
-
-A human-readable data serialization [language](http://www.yaml.org/about.html) that takes concepts from programming languages such as C, Perl, and Python, and ideas from XML and the data format of electronic mail.
+If you are looking for a definition of a specific term, please search these sites.
diff --git a/doc/university/high-availability/aws/README.md b/doc/university/high-availability/aws/README.md
index 01d5073ab7e..caaa0a3675b 100644
--- a/doc/university/high-availability/aws/README.md
+++ b/doc/university/high-availability/aws/README.md
@@ -1,394 +1,5 @@
---
-comments: false
+redirect_to: '../../../install/aws/index.md'
---
-> **Note**: We **do not** recommend using the AWS Elastic File System (EFS), as it can result
-in [significantly degraded performance](../../../administration/high_availability/nfs.md#avoid-using-awss-elastic-file-system-efs).
-
-# High Availability on AWS
-
-GitLab on AWS can leverage many of the services that are already
-configurable with High Availability. These services have a lot of
-flexibility and are able to adapt to most companies, best of all is the
-ability to automate both vertical and horizontal scaling.
-
-In this article we'll go through a basic HA setup where we'll start by
-configuring our Virtual Private Cloud and subnets to later integrate
-services such as RDS for our database server and ElastiCache as a Redis
-cluster to finally manage them within an auto scaling group with custom
-scaling policies.
-
-***
-
-## Where to Start
-
-Login to your AWS account through the `My Account` dropdown on
-`https://aws.amazon.com` or through the URI assigned to your team such as
-`https://myteam.signin.aws.amazon.com/console/`. You'll start on the
-Amazon Web Services console from where we can choose all of the services
-we'll be using to configure our cloud infrastructure.
-
-### Reference Architecture
-
-![Reference Architecture](img/reference-arch2.png)
-
-***
-
-## Network
-
-We'll start by creating a VPC for our GitLab cloud infrastructure, then
-we can create subnets to have public and private instances in at least
-two AZs. Public subnets will require a Route Table keep an associated
-Internet Gateway.
-
-### VPC
-
-Start by looking for the VPC option on the web console. Now create a new
-VPC. We can use `10.0.0.0/16` for the CIDR block and leave tenancy as
-default if we don't require dedicated hardware.
-
-![New VPC](img/new_vpc.png)
-
-If you're setting up the Elastic File System service then select the VPC
-and from the Actions dropdown choose Edit DNS Hostnames and select Yes.
-
-### Subnet
-
-Now let's create some subnets in different Availability Zones. Make sure
-that each subnet is associated to the VPC we just created, that it has
-a distinct VPC and lastly that CIDR blocks don't overlap. This will also
-allow us to enable multi-AZ for redundancy.
-
-We will create private and public subnets to match load balancers and
-RDS instances as well.
-
-![Subnet Creation](img/subnet.png)
-
-The subnets are listed with their name, AZ and CIDR block:
-
-- gitlab-public-10.0.0.0 - us-west-2a - 10.0.0.0
-- gitlab-private-10.0.1.0 - us-west-2a - 10.0.1.0
-- gitlab-public-10.0.2.0 - us-west-2b - 10.0.2.0
-- gitlab-private-10.0.3.0 - us-west-2b - 10.0.3.0
-
-### Route Table
-
-Up to now all our subnets are private. We need to create a Route Table
-to associate an Internet Gateway. On the same VPC dashboard choose
-Route Tables on the left column and give it a name and associate it to
-our newly created VPC.
-
-![Route Table](img/route_table.png)
-
-### Internet Gateway
-
-Now still on the same dashboard head over to Internet Gateways and
-create a new one. After its created press on the `Attach to VPC` button and
-select our VPC.
-
-![Internet Gateway](img/ig.png)
-
-### Configure Subnets
-
-Go back to the Router Tables screen and select the newly created one,
-press the Routes tab on the bottom section and edit it. We need to add a
-new target which will be our Internet Gateway and have it receive
-traffic from any destination.
-
-![Subnet Config](img/ig-rt.png)
-
-Before leaving this screen select the next tab to the right which is
-Subnet Associations and add our public subnets. If you followed our
-naming convention they should be easy to find.
-
-***
-
-## Database with RDS
-
-For our database server we will use Amazon RDS which offers Multi-AZ
-for redundancy. Let's start by creating a subnet group and then we'll
-create the actual RDS instance.
-
-### Subnet Group
-
-From the RDS dashboard select Subnet Groups. Lets select our VPC from
-the VPC ID dropdown and at the bottom we can add our private subnets.
-
-![Subnet Group](img/db-subnet-group.png)
-
-### RDS
-
-Select the RDS service from the Database section and create a new
-PostgreSQL instance. After choosing between a Production or
-Development instance we'll start with the actual configuration. On the
-image below we have the settings for this article but note the
-following two options which are of particular interest for HA:
-
-1. Multi-AZ-Deployment is recommended as redundancy. Read more at
- [High Availability (Multi-AZ)](http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.MultiAZ.html)
-1. While we chose a General Purpose (SSD) for this article a Provisioned
- IOPS (SSD) is best suited for HA. Read more about it at
- [Storage for Amazon RDS](http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html)
-
-![RDS Instance Specs](img/instance_specs.png)
-
-The rest of the setting on this page request a DB identifier, username,
-and a master password. We've chosen to use `gitlab-ha`, `gitlab` and a
-very secure password respectively. Keep these in hand for later.
-
-![Network and Security](img/rds-net-opt.png)
-
-Make sure to choose our gitlab VPC, our subnet group, not have it public,
-and to leave it to create a new security group. The only additional
-change which will be helpful is the database name for which we can use
-`gitlabhq_production`.
-
-***
-
-## ElastiCache
-
-EC is an in-memory hosted caching solution. Redis maintains its own
-persistence and is used for certain types of application.
-
-Let's choose the ElastiCache service in the Database section from our
-AWS console. Now let's create a cache subnet group which will be very
-similar to the RDS subnet group. Make sure to select our VPC and its
-private subnets.
-
-![ElastiCache](img/ec-subnet.png)
-
-Now press the Launch a Cache Cluster and choose Redis for our
-DB engine. You'll be able to configure details such as replication,
-Multi-AZ and node types. The second section will allow us to choose our
-subnet and security group and
-
-![Redis Cluster details](img/redis-cluster-det.png)
-
-![Redis Network](img/redis-net.png)
-
-***
-
-## Network File System
-
-GitLab requires a shared filesystem such as NFS. The file share(s) will be
-mounted on all application servers. There are a variety of ways to build an
-NFS server on AWS.
-
-One option is to use a third-party AMI that offers NFS as a service. A [search
-for 'NFS' in the AWS Marketplace](https://aws.amazon.com/marketplace/search/results?x=0&y=0&searchTerms=NFS&page=1&ref_=nav_search_box)
-shows options such as NetApp, SoftNAS and others.
-
-Another option is to build a simple NFS server using a vanilla Linux server backed
-by AWS Elastic Block Storage (EBS).
-
-> **Note:** GitLab does not recommend using AWS Elastic File System (EFS). See
- details in [High Availability NFS documentation](../../../administration/high_availability/nfs.md#avoid-using-awss-elastic-file-system-efs)
-
-***
-
-## Initiate AMI
-
-We are going to launch an EC2 instance and bake an image so that we can
-later use it for auto scaling. We'll also take this opportunity to add an
-extension to our RDS through this temporary EC2 instance.
-
-### EC2 Instance
-
-Look for the EC2 option and choose to create an instance. We'll need at
-least a t2.medium type and for this article we'll choose an Ubuntu 14.04
-HVM 64-bit. In the Configure Instance section choose our GitLab VPC and
-a public subnet. I'd choose at least 10GB of storage.
-
-In the security group we'll create a new one considering that we need to
-SSH into the instance and also try it out through http. So let's add the
-http traffic from anywhere and name it something such as
-`gitlab-ec2-security-group`.
-
-While we wait for it to launch we can allocate an Elastic IP and
-associate it with our new EC2 instance.
-
-### RDS and Redis Security Group
-
-After the instance is being created we will navigate to our EC2 security
-groups and add a small change for our EC2 instances to be able to
-connect to RDS. First copy the security group name we just defined,
-namely `gitlab-ec2-security-group`, and edit select the RDS security
-group and edit the inbound rules. Choose the rule type to be PostgreSQL
-and paste the name under source.
-
-![RDS security group](img/rds-sec-group.png)
-
-Similar to the above we'll jump to the `gitlab-ec2-security-group` group
-and add a custom TCP rule for port 6379 accessible within itself.
-
-### Install GitLab
-
-To connect through SSH you will need to have the `pem` file which you
-chose available and with the correct permissions such as `400`.
-
-After accessing your server don't forget to update and upgrade your
-packages.
-
- sudo apt-get update && sudo apt-get upgrade -y
-
-Then follow installation instructions from
-[GitLab](https://about.gitlab.com/downloads-ee/#ubuntu1404), but before
-running reconfigure we need to make sure all our services are tied down
-so just leave the reconfigure command until after we edit our gitlab.rb
-file.
-
-### Extension for PostgreSQL
-
-Connect to your new RDS instance to verify access and to install
-a required extension. We can find the host or endpoint by selecting the
-instance and we just created and after the details drop down we'll find
-it labeled as 'Endpoint'; do remember not to include the colon and port
-number.
-
- sudo /opt/gitlab/embedded/bin/psql -U gitlab -h <rds-endpoint> -d gitlabhq_production
- psql (9.4.7)
- Type "help" for help.
-
- gitlab=# CREATE EXTENSION pg_trgm;
- gitlab=# \q
-
-### Configure GitLab
-
-While connected to your server edit the `gitlab.rb` file at `/etc/gitlab/gitlab.rb`
-find the `external_url 'http://gitlab.example.com'` option and change it
-to the domain you will be using or the public IP address of the current
-instance to test the configuration.
-
-For a more detailed description about configuring GitLab read [Configuring GitLab for HA](http://docs.gitlab.com/ee/administration/high_availability/gitlab.html)
-
-Now look for the GitLab database settings and uncomment as necessary. In
-our current case we'll specify the adapter, encoding, host, db name,
-username, and password.
-
- gitlab_rails['db_adapter'] = "postgresql"
- gitlab_rails['db_encoding'] = "unicode"
- gitlab_rails['db_database'] = "gitlabhq_production"
- gitlab_rails['db_username'] = "gitlab"
- gitlab_rails['db_password'] = "mypassword"
- gitlab_rails['db_host'] = "<rds-endpoint>"
-
-Next, we only need to configure the Redis section by adding the host and
-uncommenting the port.
-
-The last configuration step is to [change the default file locations ](http://docs.gitlab.com/ee/administration/high_availability/nfs.html)
-to make the EFS integration easier to manage.
-
- gitlab_rails['redis_host'] = "<redis-endpoint>"
- gitlab_rails['redis_port'] = 6379
-
-Finally, run reconfigure. You might find it useful to run a check and
-a service status to make sure everything has been set up correctly.
-
- sudo gitlab-ctl reconfigure
- sudo gitlab-rake gitlab:check
- sudo gitlab-ctl status
-
-If everything looks good copy the Elastic IP over to your browser and
-test the instance manually.
-
-### AMI
-
-After you finish testing your EC2 instance go back to its dashboard and
-while the instance is selected press on the Actions dropdown to choose
-Image -> Create an Image. Give it a name and description and confirm.
-
-***
-
-## Load Balancer
-
-On the same dashboard look for Load Balancer on the left column and press
-the Create button. Choose a classic Load Balancer, our gitlab VPC, not
-internal and make sure its listening for HTTP and HTTPS on port 80.
-
-Here is a tricky part though, when adding subnets we need to associate
-public subnets instead of the private ones where our instances will
-actually live.
-
-On the security group section let's create a new one named
-`gitlab-loadbalancer-sec-group` and allow both HTTP ad HTTPS traffic
-from anywhere.
-
-The Load Balancer Health will allow us to indicate where to ping and what
-makes up a healthy or unhealthy instance.
-
-We won't add the instance on the next session because we'll destroy it
-momentarily as we'll be using the image we were creating. We will keep
-the Enable Cross-Zone and Enable Connection Draining active.
-
-After we finish creating the Load Balancer we can revisit our Security
-Groups to improve access only through the ELB and any other requirement
-you might have.
-
-***
-
-## Auto Scaling Group
-
-Our AMI should be done by now so we can start working on our Auto
-Scaling Group.
-
-This option is also available through the EC2 dashboard on the left
-sidebar. Press on the create button. Select the new image on My AMIs and
-give it a `t2.medium` size. To be able to use Elastic File System we need
-to add a script to mount EFS automatically at launch. We'll do this at
-the Advanced Details section where we have a [User Data](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html)
-text area that allows us to add a lot of custom configurations which
-allows you to add a custom script for when launching an instance. Let's
-add the following script to the User Data section:
-
- #cloud-config
- package_upgrade: true
- packages:
- - nfs-common
- runcmd:
- - mkdir -p /gitlab-data
- - chown ec2-user:ec2-user /gitlab-data
- - echo "$(curl --silent http://169.254.169.254/latest/meta-data/placement/availability-zone).file-system-id.aws-region.amazonaws.com:/ /gitlab-data nfs defaults,vers=4.1 0 0" >> /etc/fstab
- - mount -a -t nfs
- - sudo gitlab-ctl reconfigure
-
-On the security group section we can choose our existing
-`gitlab-ec2-security-group` group which has already been tested.
-
-After this is launched we are able to start creating our Auto Scaling
-Group. Start by giving it a name and assigning it our VPC and private
-subnets. We also want to always start with two instances and if you
-scroll down to Advanced Details we can choose to receive traffic from ELBs.
-Let's enable that option and select our ELB. We also want to use the ELB's
-health check.
-
-![Auto scaling](img/auto-scaling-det.png)
-
-### Policies
-
-This is the really great part of Auto Scaling, we get to choose when AWS
-launches new instances and when it removes them. For this group we'll
-scale between 2 and 4 instances where one instance will be added if CPU
-utilization is greater than 60% and one instance is removed if it falls
-to less than 45%. Here are the complete policies:
-
-![Policies](img/policies.png)
-
-You'll notice that after we save this AWS starts launching our two
-instances in different AZs and without a public IP which is exactly what
-we where aiming for.
-
-***
-
-## Final Thoughts
-
-After you're done with the policies section have some fun trying to break
-instances. You should be able to see how the Auto Scaling Group and the
-EC2 screen starts bringing them up again.
-
-High Availability is a vast area, we went mostly through scaling and
-some redundancy options but it might also imply Geographic replication.
-There is a lot of ground yet to cover so have a read through these other
-resources and feel free to open an issue to request additional material.
-
-- [GitLab High Availability](http://docs.gitlab.com/ce/administration/high_availability/README.html#sts=High%20Availability)
-- [GitLab Geo](https://docs.gitlab.com/ee/administration/geo/replication/index.html)
+This document was moved to [another location](../../../install/aws/index.md).
diff --git a/doc/university/high-availability/aws/img/auto-scaling-det.png b/doc/university/high-availability/aws/img/auto-scaling-det.png
deleted file mode 100644
index cf32c024bf8..00000000000
--- a/doc/university/high-availability/aws/img/auto-scaling-det.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/high-availability/aws/img/db-subnet-group.png b/doc/university/high-availability/aws/img/db-subnet-group.png
deleted file mode 100644
index 875184af310..00000000000
--- a/doc/university/high-availability/aws/img/db-subnet-group.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/high-availability/aws/img/ec-subnet.png b/doc/university/high-availability/aws/img/ec-subnet.png
deleted file mode 100644
index 43ef76b62d3..00000000000
--- a/doc/university/high-availability/aws/img/ec-subnet.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/high-availability/aws/img/elastic-file-system.png b/doc/university/high-availability/aws/img/elastic-file-system.png
deleted file mode 100644
index 5bcfb8d0588..00000000000
--- a/doc/university/high-availability/aws/img/elastic-file-system.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/high-availability/aws/img/ig-rt.png b/doc/university/high-availability/aws/img/ig-rt.png
deleted file mode 100644
index 62cca074a1e..00000000000
--- a/doc/university/high-availability/aws/img/ig-rt.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/high-availability/aws/img/ig.png b/doc/university/high-availability/aws/img/ig.png
deleted file mode 100644
index 2798d4beac3..00000000000
--- a/doc/university/high-availability/aws/img/ig.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/high-availability/aws/img/instance_specs.png b/doc/university/high-availability/aws/img/instance_specs.png
deleted file mode 100644
index 2a2b80103fb..00000000000
--- a/doc/university/high-availability/aws/img/instance_specs.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/high-availability/aws/img/new_vpc.png b/doc/university/high-availability/aws/img/new_vpc.png
deleted file mode 100644
index d872554fab7..00000000000
--- a/doc/university/high-availability/aws/img/new_vpc.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/high-availability/aws/img/policies.png b/doc/university/high-availability/aws/img/policies.png
deleted file mode 100644
index e99497a52a2..00000000000
--- a/doc/university/high-availability/aws/img/policies.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/high-availability/aws/img/rds-net-opt.png b/doc/university/high-availability/aws/img/rds-net-opt.png
deleted file mode 100644
index 13130ac96b8..00000000000
--- a/doc/university/high-availability/aws/img/rds-net-opt.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/high-availability/aws/img/rds-sec-group.png b/doc/university/high-availability/aws/img/rds-sec-group.png
deleted file mode 100644
index a88caba62c2..00000000000
--- a/doc/university/high-availability/aws/img/rds-sec-group.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/high-availability/aws/img/redis-cluster-det.png b/doc/university/high-availability/aws/img/redis-cluster-det.png
deleted file mode 100644
index 51d3a08eab6..00000000000
--- a/doc/university/high-availability/aws/img/redis-cluster-det.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/high-availability/aws/img/redis-net.png b/doc/university/high-availability/aws/img/redis-net.png
deleted file mode 100644
index 9022a9ada78..00000000000
--- a/doc/university/high-availability/aws/img/redis-net.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/high-availability/aws/img/reference-arch2.png b/doc/university/high-availability/aws/img/reference-arch2.png
deleted file mode 100644
index 0f8790d0f74..00000000000
--- a/doc/university/high-availability/aws/img/reference-arch2.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/high-availability/aws/img/route_table.png b/doc/university/high-availability/aws/img/route_table.png
deleted file mode 100644
index c8bef75f01a..00000000000
--- a/doc/university/high-availability/aws/img/route_table.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/high-availability/aws/img/subnet.png b/doc/university/high-availability/aws/img/subnet.png
deleted file mode 100644
index 681c29bf07a..00000000000
--- a/doc/university/high-availability/aws/img/subnet.png
+++ /dev/null
Binary files differ
diff --git a/doc/university/support/README.md b/doc/university/support/README.md
index feb90ae9bad..9563492c137 100644
--- a/doc/university/support/README.md
+++ b/doc/university/support/README.md
@@ -1,12 +1,13 @@
---
comments: false
+type: reference
---
# Support Boot Camp
**Goal:** Prepare new Service Engineers at GitLab
-For each stage there are learning goals and content to support the learning of the engineer.
+For each stage, there are learning goals and content to support the learning of the engineer.
The goal of this boot camp is to have every Service Engineer prepared to help our customers
with whatever needs they might have and to also assist our awesome community with their
questions.
@@ -15,7 +16,7 @@ Always start with the [University Overview](../README.md) and then work
your way here for more advanced and specific training. Once you feel comfortable
with the topics of the current stage, move to the next.
-### Stage 1
+## Stage 1
Follow the topics on the [University Overview](../README.md), concentrate on it
during your first Stage, but also:
@@ -23,22 +24,22 @@ during your first Stage, but also:
- Perform the [first steps](https://about.gitlab.com/handbook/support/onboarding/#first-steps) of
the on-boarding process for new Service Engineers
-#### Goals
+### Goals
Aim to have a good overview of the Product and main features, Git and the Company
-### Stage 2
+## Stage 2
Continue to look over remaining portions of the [University Overview](../README.md) and continue on to these topics:
-#### Set up your development machine
+### Set up your development machine
Get your development machine ready to familiarize yourself with the codebase, the components, and to be prepared to reproduce issues that our users encounter
- Install the [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit)
- [Set up OpenLDAP as part of this](https://gitlab.com/gitlab-org/gitlab-development-kit#openldap)
-#### Become comfortable with the Installation processes that we support
+### Become comfortable with the Installation processes that we support
It's important to understand how to install GitLab in the same way that our users do. Try installing different versions and upgrading and downgrading between them. Installation from source will give you a greater understanding of the components that we employ and how everything fits together.
@@ -54,58 +55,57 @@ Sometimes we need to upgrade customers from old versions of GitLab to latest, so
- Keep this up-to-date as patch and version releases become available, just like our customers would
- Try out the following installation path
- [Install GitLab 4.2 from source](https://gitlab.com/gitlab-org/gitlab-ce/blob/d67117b5a185cfb15a1d7e749588ff981ffbf779/doc/install/installation.md)
- - External MySQL database
- - External NGINX
+ - External MySQL database
+ - External NGINX
- Create some test data
- - Populated Repos
- - Users
- - Groups
- - Projects
- - [Backup using our Backup rake task](https://docs.gitlab.com/ce/raketasks/backup_restore.html#create-a-backup-of-the-gitlab-system)
+ - Populated Repos
+ - Users
+ - Groups
+ - Projects
+ - [Backup using our Backup rake task](../../raketasks/backup_restore.md#creating-a-backup-of-the-gitlab-system)
- [Upgrade to 5.0 source using our Upgrade documentation](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/doc/update/4.2-to-5.0.md)
- [Upgrade to 5.1 source](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/doc/update/5.0-to-5.1.md)
- [Upgrade to 6.0 source](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/doc/update/5.1-to-6.0.md)
- [Upgrade to 7.14 source](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/doc/update/6.x-or-7.x-to-7.14.md)
- - [Backup using our Backup rake task](https://docs.gitlab.com/ce/raketasks/backup_restore.html#create-a-backup-of-the-gitlab-system)
- - [Perform the MySQL to PostgreSQL migration to convert your backup](https://docs.gitlab.com/ce/update/mysql_to_postgresql.html#converting-a-gitlab-backup-file-from-mysql-to-postgres)
+ - [Perform the MySQL to PostgreSQL migration to convert your backup](../../update/mysql_to_postgresql.md)
- [Upgrade to Omnibus 7.14](https://docs.gitlab.com/omnibus/update/README.html#upgrading-from-a-non-omnibus-installation-to-an-omnibus-installation)
- - [Restore backup using our Restore rake task](https://docs.gitlab.com/ce/raketasks/backup_restore.html#restore-a-previously-created-backup)
+ - [Restore backup using our Restore rake task](../../raketasks/backup_restore.md#restore)
- [Upgrade to latest EE](https://about.gitlab.com/downloads-ee)
- - (GitLab inc. only) Acquire and apply a license for the Enterprise Edition product, ask in #support
-- Perform a downgrade from [EE to CE](https://docs.gitlab.com/ee/downgrade_ee_to_ce/README.html)
+ - (GitLab inc. only) Acquire and apply a license for the Enterprise Edition product, ask in #support
+- Perform a downgrade from [EE to CE](../../downgrade_ee_to_ce/README.md)
-#### Start to learn about some of the integrations that we support
+### Start to learn about some of the integrations that we support
Our integrations add great value to GitLab. User questions often relate to integrating GitLab with existing external services and the configuration involved
- Learn about our Integrations (specially, not only):
- - [LDAP](https://docs.gitlab.com/ee/integration/ldap.html)
- - [JIRA](https://docs.gitlab.com/ee/project_services/jira.html)
- - [Jenkins](https://docs.gitlab.com/ee/integration/jenkins.html)
- - [SAML](https://docs.gitlab.com/ce/integration/saml.html)
+ - [LDAP](../../integration/ldap.md)
+ - [JIRA](../../project_services/jira.md)
+ - [Jenkins](../../integration/jenkins.md)
+ - [SAML](../../integration/saml.md)
-#### Goals
+### Goals
- Aim to be comfortable with installation of the GitLab product and configuration of some of the major integrations
- Aim to have an installation available for reproducing customer reports
-### Stage 3
+## Stage 3
-#### Understand the gathering of diagnostics for GitLab instances
+### Understand the gathering of diagnostics for GitLab instances
-- Learn about the GitLab checks that are available
- - [Environment Information and maintenance checks](https://docs.gitlab.com/ce/raketasks/maintenance.html)
- - [GitLab check](https://docs.gitlab.com/ce/raketasks/check.html)
+- Learn about the GitLab checks that are available:
+ - [Environment Information and maintenance checks](../../raketasks/maintenance.md)
+ - [GitLab check](../../raketasks/check.md)
- Omnibus commands
- - [Status](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/maintenance/README.md#get-service-status)
- - [Starting and stopping services](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/maintenance/README.md#starting-and-stopping)
- - [Starting a rails console](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/maintenance/README.md#invoking-rake-tasks)
+ - [Status](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/maintenance/README.md#get-service-status)
+ - [Starting and stopping services](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/maintenance/README.md#starting-and-stopping)
+ - [Starting a rails console](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/maintenance/README.md#invoking-rake-tasks)
-#### Learn about the Support process
+### Learn about the Support process
Zendesk is our Support Centre and our main communication line with our Customers. We communicate with customers through several other channels too
-- Familiarize yourself with ZenDesk
+- Familiarize yourself with ZenDesk:
- [UI Overview](https://support.zendesk.com/hc/en-us/articles/203661806-Introduction-to-the-Zendesk-agent-interface)
- [Updating Tickets](https://support.zendesk.com/hc/en-us/articles/212530318-Updating-and-solving-tickets)
- [Working w/ Tickets](https://support.zendesk.com/hc/en-us/articles/203690856-Working-with-tickets) *Read: avoiding agent collision.*
@@ -117,16 +117,16 @@ Zendesk is our Support Centre and our main communication line with our Customers
- Here you will find a large variety of queries mainly from our Users who are self hosting GitLab CE
- Understand the questions that are asked and dig in to try to find a solution
- [Proceed on to the GitLab.com Support Forum](https://about.gitlab.com/handbook/support/#gitlabcom-support-trackera-namesupp-foruma)
- - Here you will find queries regarding our own GitLab.com
- - Helping Users here will give you an understanding of our Admin interface and other tools
+ - Here you will find queries regarding our own GitLab.com
+ - Helping Users here will give you an understanding of our Admin interface and other tools
- [Proceed on to the Twitter tickets in Zendesk](https://about.gitlab.com/handbook/support/#twitter)
- - Here you will gain a great insight into our userbase
- - Learn from any complaints and problems and feed them back to the team
- - Tweets can range from help needed with GitLab installations, the API and just general queries
+ - Here you will gain a great insight into our userbase
+ - Learn from any complaints and problems and feed them back to the team
+ - Tweets can range from help needed with GitLab installations, the API and just general queries
- [Proceed on to Regular email Support tickets](https://about.gitlab.com/handbook/support/#regular-zendesk-tickets-a-nameregulara)
- - Here you will find tickets from our GitLab EE Customers and GitLab CE Users
- - Tickets here are extremely varied and often very technical
- - You should be prepared for these tickets, given the knowledge gained from previous tiers and your training
+ - Here you will find tickets from our GitLab EE Customers and GitLab CE Users
+ - Tickets here are extremely varied and often very technical
+ - You should be prepared for these tickets, given the knowledge gained from previous tiers and your training
- Check out your colleagues' responses
- Hop on to the #support-live-feed channel in Slack and see the tickets as they come in and are updated
- Read through old tickets that your colleagues have worked on
@@ -134,14 +134,14 @@ Zendesk is our Support Centre and our main communication line with our Customers
- [Learn about Cisco WebEx](https://about.gitlab.com/handbook/support/onboarding/#webexa-namewebexa)
- Training calls
- Information gathering calls
- - It's good to find out how new and prospective customers are going to be using the product and how they will set up their infrastructure
+ - It's good to find out how new and prospective customers are going to be using the product and how they will set up their infrastructure
- Diagnosis calls
- - When email isn't enough we may need to hop on a call and do some debugging along side the customer
- - These paired calls are a great learning experience
+ - When email isn't enough we may need to hop on a call and do some debugging along side the customer
+ - These paired calls are a great learning experience
- Upgrade calls
- Emergency calls
-#### Learn about the Escalation process for tickets
+### Learn about the Escalation process for tickets
Some tickets need specific knowledge or a deep understanding of a particular component and will need to be escalated to a Senior Service Engineer or Developer
@@ -149,7 +149,7 @@ Some tickets need specific knowledge or a deep understanding of a particular com
- Find the macros in Zendesk for ticket escalations
- Take a look at the [GitLab.com Team page](https://about.gitlab.com/team/) to find the resident experts in their fields
-#### Learn about raising issues and fielding feature proposals
+### Learn about raising issues and fielding feature proposals
- Understand what's in the pipeline and proposed features at GitLab: [Direction Page](https://about.gitlab.com/direction/)
- Practice searching issues and filtering using [labels](https://gitlab.com/gitlab-org/gitlab-ce/labels) to find existing feature proposals and bugs
@@ -158,33 +158,45 @@ Some tickets need specific knowledge or a deep understanding of a particular com
- Take a look at the [existing issue templates](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#issue-tracker) to see what is expected
- Raise issues for bugs in a manner that would make the issue easily reproducible. A Developer or a contributor may work on your issue
-#### Goals
+### Goals
- Aim to have a good understanding of the problems that customers are facing
- Aim to have gained experience in scheduling and participating in calls with customers
- Aim to have a good understanding of ticket flow through Zendesk and how to interact with our various channels
-### Stage 4
+## Stage 4
-#### Advanced GitLab topics
+### Advanced GitLab topics
Move on to understanding some of GitLab's more advanced features. You can make use of GitLab.com to understand the features from an end-user perspective and then use your own instance to understand setup and configuration of the feature from an Administrative perspective
-- Set up and try [Git LFS](https://docs.gitlab.com/ee/workflow/lfs/manage_large_binaries_with_git_lfs.html)
-- Get to know the [GitLab API](https://docs.gitlab.com/ee/api/README.html), its capabilities and shortcomings
-- Learn how to [migrate from SVN to Git](https://docs.gitlab.com/ee/workflow/importing/migrating_from_svn.html)
-- Set up [GitLab CI](https://docs.gitlab.com/ee/ci/quick_start/README.html)
-- Create your first [GitLab Page](https://docs.gitlab.com/ce/administration/pages/)
+- Set up and try [Git LFS](../../workflow/lfs/manage_large_binaries_with_git_lfs.md)
+- Get to know the [GitLab API](../../api/README.md), its capabilities and shortcomings
+- Learn how to [migrate from SVN to Git](../../user/project/import/svn.md)
+- Set up [GitLab CI](../../ci/quick_start/README.md)
+- Create your first [GitLab Page](../../administration/pages/index.md)
- Get to know the GitLab Codebase by reading through the source code:
- Find the differences between the [EE codebase](https://gitlab.com/gitlab-org/gitlab-ce)
and the [CE codebase](https://gitlab.com/gitlab-org/gitlab-ce)
- Ask as many questions as you can think of on the `#support` chat channel
-#### Get initiated for on-call duty
+### Get initiated for on-call duty
- Read over the [public run-books to understand common tasks](https://gitlab.com/gitlab-com/runbooks)
- Create an issue on the internal Organization tracker to schedule time with the DevOps / Production team, so that you learn how to handle GitLab.com going down. Once you are trained for this, you are ready to be added to the on-call rotation.
-#### Goals
+### Goals
- Aim to become a fully-fledged Service Engineer!
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/university/training/gitlab_flow.md b/doc/university/training/gitlab_flow.md
index d7bc7bda43f..0ce92be4994 100644
--- a/doc/university/training/gitlab_flow.md
+++ b/doc/university/training/gitlab_flow.md
@@ -1,5 +1,6 @@
---
comments: false
+type: reference
---
# What is the GitLab Flow
@@ -41,5 +42,17 @@ comments: false
## More details
-For more information read through the [GitLab Flow](../../workflow/gitlab_flow.md)
+For more information, read through the [GitLab Flow](../../workflow/gitlab_flow.md)
documentation.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/university/training/index.md b/doc/university/training/index.md
index 14f096b130f..ddfc662123d 100644
--- a/doc/university/training/index.md
+++ b/doc/university/training/index.md
@@ -1,5 +1,6 @@
---
comments: false
+type: index
---
# GitLab Training Material
@@ -8,3 +9,34 @@ All GitLab training material is stored in markdown format. Slides are
generated using [Deskset](http://www.decksetapp.com/).
All training material is open to public contribution.
+
+This section contains the following topics:
+
+- [Agile and Git](topics/agile_git.md).
+- [Bisect](topics/bisect.md).
+- [Cherry pick](topics/cherry_picking.md).
+- [Code review and collaboration with Merge Requests](topics/merge_requests.md).
+- [Configure your environment](topics/env_setup.md).
+- [Explore GitLab](topics/explore_gitlab.md).
+- [Feature branching](topics/feature_branching.md).
+- [Getting started](topics/getting_started.md).
+- [GitLab flow](gitlab_flow.md).
+- [GitLab Git workshop](user_training.md).
+- [Git add](topics/git_add.md).
+- [Git introduction](topics/git_intro.md).
+- [Git log](topics/git_log.md).
+- [Git stash](topics/stash.md).
+- [Merge conflicts](topics/merge_conflicts.md).
+- [Rollback commits](topics/rollback_commits.md).
+- [Subtree](topics/subtree.md).
+- [Tags](topics/tags.md).
+- [Unstage](topics/unstage.md).
+
+## Additional Resources
+
+1. [GitLab Documentation](http://docs.gitlab.com)
+1. [GUI Clients](http://git-scm.com/downloads/guis)
+1. [Pro Git book](http://git-scm.com/book)
+1. [Platzi Course](https://courses.platzi.com/courses/git-gitlab/)
+1. [Code School tutorial](http://try.github.io/)
+1. Contact us at `subscribers@gitlab.com`
diff --git a/doc/university/training/topics/additional_resources.md b/doc/university/training/topics/additional_resources.md
deleted file mode 100644
index 4871372d105..00000000000
--- a/doc/university/training/topics/additional_resources.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-comments: false
----
-
-# Additional Resources
-
-1. GitLab Documentation: <http://docs.gitlab.com>.
-1. GUI Clients: <http://git-scm.com/downloads/guis>.
-1. Pro Git book: <http://git-scm.com/book>.
-1. Platzi Course: <https://courses.platzi.com/courses/git-gitlab/>.
-1. Code School tutorial: <http://try.github.io/>.
-1. Contact us at `subscribers@gitlab.com`.
diff --git a/doc/university/training/topics/agile_git.md b/doc/university/training/topics/agile_git.md
index 251af99bed7..42d91a50045 100644
--- a/doc/university/training/topics/agile_git.md
+++ b/doc/university/training/topics/agile_git.md
@@ -4,22 +4,16 @@ comments: false
# Agile and Git
-----------
-
## Agile
Lean software development methods focused on collaboration and interaction
with fast and smaller deployment cycles.
-----------
-
## Where Git comes in
Git is an excellent tool for an Agile team considering that it allows
decentralized and simultaneous development.
-----------
-
### Branching And Workflows
Branching in an Agile environment usually happens around user stories with one
@@ -30,8 +24,7 @@ with his/her initials, and US id.
After its tested merge into master and remove the branch.
-----------
-
## What about GitLab
+
Tools like GitLab enhance collaboration by adding dialog around code mainly
through issues and merge requests.
diff --git a/doc/university/training/topics/bisect.md b/doc/university/training/topics/bisect.md
index 4848d0412c1..4178afa2086 100644
--- a/doc/university/training/topics/bisect.md
+++ b/doc/university/training/topics/bisect.md
@@ -4,16 +4,12 @@ comments: false
# Bisect
-----------
-
## Bisect
- Find a commit that introduced a bug
- Works through a process of elimination
- Specify a known good and bad revision to begin
-----------
-
## Bisect
1. Start the bisect process
@@ -23,11 +19,9 @@ comments: false
1. Tell bisect the result
1. Repeat the previous 2 items until you find the offending commit
-----------
-
## Setup
-```
+```sh
mkdir bisect-ex
cd bisect-ex
touch index.html
@@ -44,9 +38,7 @@ comments: false
vi index.html
```
-----------
-
-```
+```sh
# Add all good 3
git add -A
git commit -m "fourth commit"
@@ -64,11 +56,9 @@ comments: false
git commit -m "seventh commit"
```
-----------
-
## Commands
-```
+```sh
git bisect start
# Test your code
git bisect bad
diff --git a/doc/university/training/topics/cherry_picking.md b/doc/university/training/topics/cherry_picking.md
index df23024b6ee..fa0cb5fe6a4 100644
--- a/doc/university/training/topics/cherry_picking.md
+++ b/doc/university/training/topics/cherry_picking.md
@@ -4,16 +4,12 @@ comments: false
# Cherry Pick
-----------
-
## Cherry Pick
- Given an existing commit on one branch, apply the change to another branch
- Useful for backporting bug fixes to previous release branches
- Make the commit on the master branch and pick in to stable
-----------
-
## Cherry Pick
1. Check out a new 'stable' branch from 'master'
@@ -23,8 +19,6 @@ comments: false
1. Check out the 'stable' branch
1. Cherry pick the commit using the SHA obtained earlier
-----------
-
## Commands
```bash
diff --git a/doc/university/training/topics/env_setup.md b/doc/university/training/topics/env_setup.md
index 78ca30e0f55..305f5ecb1fb 100644
--- a/doc/university/training/topics/env_setup.md
+++ b/doc/university/training/topics/env_setup.md
@@ -4,7 +4,6 @@ comments: false
# Configure your environment
-----------
## Install
- **Windows**
@@ -22,8 +21,6 @@ comments: false
sudo apt-get install git-all
```
-----------
-
## Configure Git
One-time configuration of the Git client
@@ -33,8 +30,6 @@ git config --global user.name "Your Name"
git config --global user.email you@example.com
```
-----------
-
## Configure SSH Key
```bash
diff --git a/doc/university/training/topics/explore_gitlab.md b/doc/university/training/topics/explore_gitlab.md
index 84a1879cd92..4ca931d0e26 100644
--- a/doc/university/training/topics/explore_gitlab.md
+++ b/doc/university/training/topics/explore_gitlab.md
@@ -4,8 +4,6 @@ comments: false
# Explore GitLab projects
-----------
-
- Dashboard
- User Preferences
- Issues
diff --git a/doc/university/training/topics/feature_branching.md b/doc/university/training/topics/feature_branching.md
index 0df5f26dbea..d2efe634533 100644
--- a/doc/university/training/topics/feature_branching.md
+++ b/doc/university/training/topics/feature_branching.md
@@ -4,8 +4,6 @@ comments: false
# Feature branching
-----------
-
- Efficient parallel workflow for teams
- Develop each feature in a branch
- Keeps changes isolated
@@ -13,8 +11,6 @@ comments: false
- Push branches to the server frequently
- Hint: This is a cheap backup for your work-in-progress code
-----------
-
## Feature branching
1. Create a new feature branch called 'squash_some_bugs'
@@ -22,11 +18,9 @@ comments: false
1. Commit
1. Push
-----------
-
## Commands
-```
+```sh
git checkout -b squash_some_bugs
# Edit `bugs.rb`
git status
diff --git a/doc/university/training/topics/getting_started.md b/doc/university/training/topics/getting_started.md
index d76ff57bfa3..08027c5d15b 100644
--- a/doc/university/training/topics/getting_started.md
+++ b/doc/university/training/topics/getting_started.md
@@ -4,8 +4,6 @@ comments: false
# Getting Started
-----------
-
## Instantiating Repositories
- Create a new repository by instantiating it through:
@@ -19,8 +17,6 @@ comments: false
git clone <url>
```
-----------
-
## Central Repos
- To instantiate a central repository a `--bare` flag is required.
@@ -31,27 +27,22 @@ comments: false
git init --bare project-name.git
```
-----------
-
## Instantiate workflow with clone
1. Create a project in your user namespace.
- - Choose to import from 'Any Repo by URL' and use <https://gitlab.com/gitlab-org/training-examples.git>.
+ - Choose to import from 'Any Repo by URL' and use <https://gitlab.com/gitlab-org/training-examples.git>.
1. Create a '`Workspace`' directory in your home directory.
1. Clone the '`training-examples`' project.
-----------
-
## Commands
-```
+```sh
mkdir ~/workspace
cd ~/workspace
git clone git@gitlab.example.com:<username>/training-examples.git
cd training-examples
```
-----------
## Git concepts
@@ -67,8 +58,6 @@ Files that have been modified but are not committed.
Modified files that have been marked to go in the next commit.
-----------
-
## Committing Workflow
1. Edit '`edit_this_file.rb`' in '`training-examples`'
@@ -79,11 +68,9 @@ Modified files that have been marked to go in the next commit.
1. Push the commit to the remote
1. View the git log
-----------
-
## Commands
-```
+```sh
# Edit `edit_this_file.rb`
git status
git diff
@@ -93,8 +80,6 @@ git push origin master
git log
```
-----------
-
## Note
- git fetch vs pull
diff --git a/doc/university/training/topics/git_add.md b/doc/university/training/topics/git_add.md
index e02a7deab91..4c61d5eb175 100644
--- a/doc/university/training/topics/git_add.md
+++ b/doc/university/training/topics/git_add.md
@@ -4,8 +4,6 @@ comments: false
# Git Add
-----------
-
## Git Add
Adds content to the index or staging area.
@@ -22,8 +20,6 @@ Adds content to the index or staging area.
git add -A
```
-----------
-
## Git add continued
- Add all text files in current dir:
diff --git a/doc/university/training/topics/git_intro.md b/doc/university/training/topics/git_intro.md
index 127323c292c..845bb7f0a81 100644
--- a/doc/university/training/topics/git_intro.md
+++ b/doc/university/training/topics/git_intro.md
@@ -4,8 +4,6 @@ comments: false
# Git introduction
-----------
-
## Intro
<https://git-scm.com/about>
@@ -17,8 +15,6 @@ comments: false
- Adapts to nearly any workflow
- Fast, reliable and stable file format
-----------
-
## Help!
Use the tools at your disposal when you get stuck.
diff --git a/doc/university/training/topics/git_log.md b/doc/university/training/topics/git_log.md
index 763ef802a04..11addcd3ee1 100644
--- a/doc/university/training/topics/git_log.md
+++ b/doc/university/training/topics/git_log.md
@@ -4,44 +4,38 @@ comments: false
# Git Log
-----------
-
Git log lists commit history. It allows searching and filtering.
- Initiate log:
- ```
+ ```sh
git log
```
- Retrieve set number of records:
- ```
+ ```sh
git log -n 2
```
- Search commits by author. Allows user name or a regular expression.
- ```
+ ```sh
git log --author="user_name"
```
-----------
-
- Search by comment message:
- ```
+ ```sh
git log --grep="<pattern>"
```
- Search by date:
- ```
+ ```sh
git log --since=1.month.ago --until=3.weeks.ago
```
-----------
-
## Git Log Workflow
1. Change to workspace directory
@@ -51,11 +45,9 @@ Git log lists commit history. It allows searching and filtering.
1. Search by date
1. Combine
-----------
-
## Commands
-```
+```sh
cd ~/workspace
git clone git@gitlab.com:gitlab-org/gitlab-runner.git
cd gitlab-runner
diff --git a/doc/university/training/topics/merge_conflicts.md b/doc/university/training/topics/merge_conflicts.md
index a7d42904229..dd235fe3a81 100644
--- a/doc/university/training/topics/merge_conflicts.md
+++ b/doc/university/training/topics/merge_conflicts.md
@@ -4,15 +4,11 @@ comments: false
# Merge conflicts
-----------
-
- Happen often
- Learning to fix conflicts is hard
- Practice makes perfect
- Force push after fixing conflicts. Be careful!
-----------
-
## Merge conflicts
1. Checkout a new branch and edit `conflicts.rb`. Add 'Line4' and 'Line5'.
@@ -26,11 +22,9 @@ comments: false
1. Force push the changes.
1. Finally continue with the Merge Request.
-----------
-
## Commands
-```
+```sh
git checkout -b conflicts_branch
# vi conflicts.rb
@@ -49,7 +43,7 @@ git push origin master
Create a merge request on the GitLab web UI. You'll see a conflict warning.
-```
+```sh
git checkout conflicts_branch
git fetch
git rebase master
@@ -65,7 +59,6 @@ git rebase --continue
# need to force push so that our remote branch is restructured
git push origin conflicts_branch -f
```
-----------
## Note
diff --git a/doc/university/training/topics/merge_requests.md b/doc/university/training/topics/merge_requests.md
index d7b771cd87b..b5bbe7b2e1e 100644
--- a/doc/university/training/topics/merge_requests.md
+++ b/doc/university/training/topics/merge_requests.md
@@ -4,8 +4,6 @@ comments: false
# Code review and collaboration with Merge Requests
-----------
-
- When you want feedback create a merge request
- Target is the default branch (usually master)
- Assign or mention the person you would like to review
@@ -14,8 +12,6 @@ comments: false
- Anyone can comment, not just the assignee
- Push corrections to the same branch
-----------
-
## Merge requests
**Create your first merge request**
@@ -25,8 +21,6 @@ comments: false
1. Push a new commit to the same branch
1. Review the changes again and notice the update
-----------
-
## Feedback and Collaboration
- Merge requests are a time for feedback and collaboration
@@ -36,8 +30,6 @@ comments: false
- Be as receptive as possible
- Feedback is about the best code, not the person. You are not your code
-----------
-
## Feedback and Collaboration
Review the Thoughtbot code-review guide for suggestions to follow when reviewing merge requests:
diff --git a/doc/university/training/topics/rollback_commits.md b/doc/university/training/topics/rollback_commits.md
index 96b89e3319a..1e6602deef2 100644
--- a/doc/university/training/topics/rollback_commits.md
+++ b/doc/university/training/topics/rollback_commits.md
@@ -4,40 +4,34 @@ comments: false
# Rollback Commits
-----------
-
## Undo Commits
- Undo last commit putting everything back into the staging area:
- ```
+ ```sh
git reset --soft HEAD^
```
- Add files and change message with:
- ```
+ ```sh
git commit --amend -m "New Message"
```
-----------
-
- Undo last and remove changes:
- ```
+ ```sh
git reset --hard HEAD^
```
- Same as last one but for two commits back:
- ```
+ ```sh
git reset --hard HEAD^^
```
** Don't reset after pushing **
-----------
-
## Reset Workflow
1. Edit file again 'edit_this_file.rb'
@@ -51,11 +45,9 @@ comments: false
1. Pull for updates
1. Push changes
-----------
-
## Commands
-```
+```sh
# Change file edit_this_file.rb
git status
git commit -am "kjkfjkg"
@@ -68,15 +60,13 @@ git pull origin master
git push origin master
```
-----------
-
## Note
- git revert vs git reset
- Reset removes the commit while revert removes the changes but leaves the commit
- Revert is safer considering we can revert a revert
-```
+```sh
# Changed file
git commit -am "bug introduced"
git revert HEAD
diff --git a/doc/university/training/topics/stash.md b/doc/university/training/topics/stash.md
index dfd28fbcbc9..02b2f610266 100644
--- a/doc/university/training/topics/stash.md
+++ b/doc/university/training/topics/stash.md
@@ -4,14 +4,12 @@ comments: false
# Git Stash
-----------
-
We use git stash to store our changes when they are not ready to be committed
and we need to change to a different branch.
- Stash:
- ```
+ ```sh
git stash save
# or
git stash
@@ -21,18 +19,16 @@ and we need to change to a different branch.
- Apply stash to keep working on it:
- ```
+ ```sh
git stash apply
# or apply a specific one from out stack
git stash apply stash@{3}
```
-----------
-
- Every time we save a stash it gets stacked so by using list we can see all our
stashes.
- ```
+ ```sh
git stash list
# or for more information (log methods)
git stash list --stat
@@ -40,7 +36,7 @@ and we need to change to a different branch.
- To clean our stack we need to manually remove them:
- ```
+ ```sh
# drop top stash
git stash drop
# or
@@ -49,19 +45,15 @@ and we need to change to a different branch.
git stash clear
```
-----------
-
- Apply and drop on one command:
- ```
+ ```sh
git stash pop
```
- If we meet conflicts we need to either reset or commit our changes.
- Conflicts through `pop` will not drop a stash afterwards.
-----------
-
## Git Stash
1. Modify a file
@@ -72,11 +64,9 @@ and we need to change to a different branch.
1. Apply with pop
1. View list to confirm changes
-----------
-
## Commands
-```
+```sh
# Modify edit_this_file.rb file
git add .
diff --git a/doc/university/training/topics/subtree.md b/doc/university/training/topics/subtree.md
index ba7c3394938..981918d4758 100644
--- a/doc/university/training/topics/subtree.md
+++ b/doc/university/training/topics/subtree.md
@@ -9,19 +9,15 @@ comments: false
- For these cases we need a dependency control system.
- Command are painfully long so aliases are necessary.
-----------
-
## Subtree Aliases
-- Add: git subtree add --prefix <target-folder> <url> <branch> --squash.
-- Pull: git subtree add --prefix <target-folder> <url> <branch> --squash.
-- Push: git subtree add --prefix <target-folder> <url> <branch>.
-- Ex: git config alias.sbp 'subtree pull --prefix st /
- git@gitlab.com:balameb/subtree-nested-example.git master --squash'.
-
-----------
+- Add: `git subtree add --prefix <target-folder> <url> <branch> --squash`.
+- Pull: `git subtree add --prefix <target-folder> <url> <branch> --squash`.
+- Push: `git subtree add --prefix <target-folder> <url> <branch>`.
+- Ex: `git config alias.sbp 'subtree pull --prefix st /
+ git@gitlab.com:balameb/subtree-nested-example.git master --squash'`.
-```
+```sh
# Add an alias
# Add
git config alias.sba 'subtree add --prefix st /
@@ -41,9 +37,7 @@ comments: false
```
-----------
-
-```
+```sh
# Adding, or committing won't change the sub repo at remote
# even if we push
git add -A
diff --git a/doc/university/training/topics/tags.md b/doc/university/training/topics/tags.md
index 14c39457838..cdbb8a2da7c 100644
--- a/doc/university/training/topics/tags.md
+++ b/doc/university/training/topics/tags.md
@@ -1,19 +1,16 @@
---
comments: false
+type: reference
---
# Tags
-----------
-
- Useful for marking deployments and releases
- Annotated tags are an unchangeable part of Git history
- Soft/lightweight tags can be set and removed at will
- Many projects combine an annotated release tag with a stable branch
- Consider setting deployment/release tags automatically
-----------
-
# Tags
- Create a lightweight tag
@@ -24,11 +21,9 @@ comments: false
<https://git-scm.com/book/en/Git-Basics-Tagging>
-----------
-
# Commands
-```
+```sh
git checkout master
# Lightweight tag
@@ -40,3 +35,15 @@ git tag
git push origin --tags
```
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/university/training/topics/unstage.md b/doc/university/training/topics/unstage.md
index da36a3218e5..af16afdc5d1 100644
--- a/doc/university/training/topics/unstage.md
+++ b/doc/university/training/topics/unstage.md
@@ -4,33 +4,29 @@ comments: false
# Unstage
-----------
-
## Unstage
-- To remove files from stage use reset HEAD. Where HEAD is the last commit of the current branch.
+- To remove files from stage use reset HEAD where HEAD is the last commit of the current branch. This will unstage the file but maintain the modifications.
```bash
git reset HEAD <file>
```
-- This will unstage the file but maintain the modifications. To revert the file back to the state it was in before the changes we can use:
+- To revert the file back to the state it was in before the changes we can use:
```bash
git checkout -- <file>
```
-----------
-
- To remove a file from disk and repo use 'git rm' and to rm a dir use the '-r' flag:
- ```
+ ```sh
git rm '*.txt'
git rm -r <dirname>
```
- If we want to remove a file from the repository but keep it on disk, say we forgot to add it to our `.gitignore` file then use `--cache`:
- ```
+ ```sh
git rm <filename> --cache
```
diff --git a/doc/university/training/user_training.md b/doc/university/training/user_training.md
index ca3f777f403..e440652edfc 100644
--- a/doc/university/training/user_training.md
+++ b/doc/university/training/user_training.md
@@ -1,11 +1,10 @@
---
comments: false
+type: reference
---
# GitLab Git Workshop
----
-
## Agenda
1. Brief history of Git.
@@ -13,8 +12,6 @@ comments: false
1. Configure your environment.
1. Workshop.
----
-
## Git introduction
<https://git-scm.com/about>
@@ -26,8 +23,6 @@ comments: false
- Adapts to nearly any workflow.
- Fast, reliable and stable file format.
----
-
## Help!
Use the tools at your disposal when you get stuck.
@@ -36,14 +31,10 @@ Use the tools at your disposal when you get stuck.
- Use Google.
- Read documentation at <https://git-scm.com>.
----
-
## GitLab Walkthrough
![fit](logo.png)
----
-
## Configure your environment
- Windows: Install 'Git for Windows'
@@ -56,8 +47,6 @@ Use the tools at your disposal when you get stuck.
- Debian: '`sudo apt-get install git-all`' or Red Hat '`sudo yum install git-all`'
----
-
## Git Workshop
### Overview
@@ -70,8 +59,6 @@ Use the tools at your disposal when you get stuck.
1. Merge requests.
1. Feedback and Collaboration.
----
-
## Configure Git
One-time configuration of the Git client:
@@ -81,8 +68,6 @@ git config --global user.name "Your Name"
git config --global user.email you@example.com
```
----
-
## Configure SSH Key
```sh
@@ -111,8 +96,6 @@ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQEL17Ufacg8cDhlQMS5NhV8z3GHZdhCrZbl4gz you@example.com
```
----
-
## Create a project
- Create a project in your user namespace.
@@ -120,8 +103,6 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQEL17Ufacg8cDhlQMS5NhV8z3GHZdhCrZbl4gz you@example.
- Create a '`development`' or '`workspace`' directory in your home directory.
- Clone the '`training-examples`' project.
----
-
## Commands (project)
```sh
@@ -137,8 +118,6 @@ git clone git@gitlab.example.com:<username>/training-examples.git
cd training-examples
```
----
-
## Git concepts
### Untracked files
@@ -153,8 +132,6 @@ Files that have been modified but are not committed.
Modified files that have been marked to go in the next commit.
----
-
## Committing
1. Edit '`edit_this_file.rb`' in '`training-examples`'.
@@ -165,8 +142,6 @@ Modified files that have been marked to go in the next commit.
1. Push the commit to the remote.
1. View the git log.
----
-
## Commands (committing)
```sh
@@ -179,8 +154,6 @@ git push origin master
git log
```
----
-
## Feature branching
- Efficient parallel workflow for teams.
@@ -190,8 +163,6 @@ git log
- Push branches to the server frequently.
- Hint: This is a cheap backup for your work-in-progress code.
----
-
## Feature branching steps
1. Create a new feature branch called 'squash_some_bugs'.
@@ -199,8 +170,6 @@ git log
1. Commit.
1. Push.
----
-
## Commands (feature branching)
```sh
@@ -212,8 +181,6 @@ git commit -m 'Fix some buggy code'
git push origin squash_some_bugs
```
----
-
## Merge requests
- When you want feedback create a merge request.
@@ -224,8 +191,6 @@ git push origin squash_some_bugs
- Anyone can comment, not just the assignee.
- Push corrections to the same branch.
----
-
## Merge requests steps
Create your first merge request:
@@ -235,8 +200,6 @@ Create your first merge request:
1. Push a new commit to the same branch.
1. Review the changes again and notice the update.
----
-
## Feedback and Collaboration
- Merge requests are a time for feedback and collaboration.
@@ -246,8 +209,6 @@ Create your first merge request:
- Be as receptive as possible.
- Feedback is about the best code, not the person. You are not your code.
----
-
## Feedback and Collaboration resources
Review the Thoughtbot code-review guide for suggestions to follow when reviewing merge requests:
@@ -255,8 +216,6 @@ Review the Thoughtbot code-review guide for suggestions to follow when reviewing
See GitLab merge requests for examples: <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests>.
----
-
## Explore GitLab projects
![fit](logo.png)
@@ -269,8 +228,6 @@ See GitLab merge requests for examples: <https://gitlab.com/gitlab-org/gitlab-ce
- Manage project members
- Project settings
----
-
## Tags
- Useful for marking deployments and releases.
@@ -279,8 +236,6 @@ See GitLab merge requests for examples: <https://gitlab.com/gitlab-org/gitlab-ce
- Many projects combine an annotated release tag with a stable branch.
- Consider setting deployment/release tags automatically.
----
-
## Tags steps
1. Create a lightweight tag.
@@ -289,8 +244,6 @@ See GitLab merge requests for examples: <https://gitlab.com/gitlab-org/gitlab-ce
Additional resources: <http://git-scm.com/book/en/Git-Basics-Tagging>.
----
-
## Commands (tags)
```sh
@@ -306,8 +259,6 @@ git tag
git push origin --tags
```
----
-
## Merge conflicts
- Happen often.
@@ -315,8 +266,6 @@ git push origin --tags
- Practice makes perfect.
- Force push after fixing conflicts. Be careful!
----
-
## Merge conflicts steps
1. Checkout a new branch and edit `conflicts.rb`. Add 'Line4' and 'Line5'.
@@ -325,8 +274,6 @@ git push origin --tags
1. Commit and push to master.
1. Create a merge request.
----
-
## Merge conflicts commands
After creating a merge request you should notice that conflicts exist. Resolve
@@ -343,8 +290,6 @@ git rebase --continue
git push origin <branch> -f
```
----
-
## Rebase with squash
You may end up with a commit log that looks like this:
@@ -361,8 +306,6 @@ Does this work?
Squash these in to meaningful commits using an interactive rebase.
----
-
## Rebase with squash commands
Squash the commits on the same branch we used for the merge conflicts step.
@@ -373,8 +316,6 @@ git rebase -i master
In the editor, leave the first commit as 'pick' and set others to 'fixup'.
----
-
## Questions?
![fit](logo.png)
@@ -383,9 +324,16 @@ Thank you for your hard work!
## Additional Resources
-- GitLab Documentation: <http://docs.gitlab.com/>.
-- GUI Clients: <http://git-scm.com/downloads/guis>.
-- Pro Git book: <http://git-scm.com/book>.
-- Platzi Course: <https://courses.platzi.com/courses/git-gitlab/>.
-- Code School tutorial: <http://try.github.io/>.
-- Contact us at `subscribers@gitlab.com`.
+See [additional resources](index.md#additional-resources).
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/update/10.0-ce-to-ee.md b/doc/update/10.0-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/10.0-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/10.1-ce-to-ee.md b/doc/update/10.1-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/10.1-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/10.2-ce-to-ee.md b/doc/update/10.2-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/10.2-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/10.3-ce-to-ee.md b/doc/update/10.3-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/10.3-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/10.4-ce-to-ee.md b/doc/update/10.4-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/10.4-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/10.5-ce-to-ee.md b/doc/update/10.5-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/10.5-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/10.6-ce-to-ee.md b/doc/update/10.6-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/10.6-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/10.7-ce-to-ee.md b/doc/update/10.7-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/10.7-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/10.8-ce-to-ee.md b/doc/update/10.8-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/10.8-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/11.0-ce-to-ee.md b/doc/update/11.0-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/11.0-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/11.1-ce-to-ee.md b/doc/update/11.1-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/11.1-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/11.2-ce-to-ee.md b/doc/update/11.2-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/11.2-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/11.3-ce-to-ee.md b/doc/update/11.3-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/11.3-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/11.4-ce-to-ee.md b/doc/update/11.4-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/11.4-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/11.5-ce-to-ee.md b/doc/update/11.5-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/11.5-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/11.6-ce-to-ee.md b/doc/update/11.6-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/11.6-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/11.7-ce-to-ee.md b/doc/update/11.7-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/11.7-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/11.8-ce-to-ee.md b/doc/update/11.8-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/11.8-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/6.0-ce-to-ee.md b/doc/update/6.0-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/6.0-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/6.1-ce-to-ee.md b/doc/update/6.1-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/6.1-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/6.2-ce-to-ee.md b/doc/update/6.2-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/6.2-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/6.3-ce-to-ee.md b/doc/update/6.3-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/6.3-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/6.4-ce-to-ee.md b/doc/update/6.4-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/6.4-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/6.5-ce-to-ee.md b/doc/update/6.5-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/6.5-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/6.6-ce-to-ee.md b/doc/update/6.6-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/6.6-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/6.7-ce-to-ee.md b/doc/update/6.7-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/6.7-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/6.8-ce-to-ee.md b/doc/update/6.8-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/6.8-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/6.9-ce-to-ee.md b/doc/update/6.9-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/6.9-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/7.0-ce-to-ee.md b/doc/update/7.0-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/7.0-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/7.1-ce-to-ee.md b/doc/update/7.1-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/7.1-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/7.10-ce-to-ee.md b/doc/update/7.10-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/7.10-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/7.11-ce-to-ee.md b/doc/update/7.11-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/7.11-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/7.12-ce-to-ee.md b/doc/update/7.12-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/7.12-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/7.13-ce-to-ee.md b/doc/update/7.13-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/7.13-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/7.14-ce-to-ee.md b/doc/update/7.14-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/7.14-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/7.3-ce-to-ee.md b/doc/update/7.3-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/7.3-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/7.4-ce-to-ee.md b/doc/update/7.4-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/7.4-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/7.5-ce-to-ee.md b/doc/update/7.5-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/7.5-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/7.6-ce-to-ee.md b/doc/update/7.6-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/7.6-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/7.7-ce-to-ee.md b/doc/update/7.7-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/7.7-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/7.8-ce-to-ee.md b/doc/update/7.8-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/7.8-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/7.9-ce-to-ee.md b/doc/update/7.9-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/7.9-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/8.0-ce-to-ee.md b/doc/update/8.0-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/8.0-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/8.1-ce-to-ee.md b/doc/update/8.1-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/8.1-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/8.10-ce-to-ee.md b/doc/update/8.10-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/8.10-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/8.11-ce-to-ee.md b/doc/update/8.11-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/8.11-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/8.12-ce-to-ee.md b/doc/update/8.12-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/8.12-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/8.13-ce-to-ee.md b/doc/update/8.13-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/8.13-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/8.14-ce-to-ee.md b/doc/update/8.14-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/8.14-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/8.15-ce-to-ee.md b/doc/update/8.15-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/8.15-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/8.16-ce-to-ee.md b/doc/update/8.16-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/8.16-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/8.17-ce-to-ee.md b/doc/update/8.17-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/8.17-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/8.2-ce-to-ee.md b/doc/update/8.2-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/8.2-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/8.3-ce-to-ee.md b/doc/update/8.3-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/8.3-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/8.4-ce-to-ee.md b/doc/update/8.4-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/8.4-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/8.5-ce-to-ee.md b/doc/update/8.5-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/8.5-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/8.6-ce-to-ee.md b/doc/update/8.6-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/8.6-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/8.7-ce-to-ee.md b/doc/update/8.7-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/8.7-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/8.8-ce-to-ee.md b/doc/update/8.8-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/8.8-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/8.9-ce-to-ee.md b/doc/update/8.9-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/8.9-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/9.0-ce-to-ee.md b/doc/update/9.0-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/9.0-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/9.1-ce-to-ee.md b/doc/update/9.1-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/9.1-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/9.2-ce-to-ee.md b/doc/update/9.2-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/9.2-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/9.3-ce-to-ee.md b/doc/update/9.3-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/9.3-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/9.4-ce-to-ee.md b/doc/update/9.4-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/9.4-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/9.5-ce-to-ee.md b/doc/update/9.5-ce-to-ee.md
new file mode 100644
index 00000000000..10c9e21fa81
--- /dev/null
+++ b/doc/update/9.5-ce-to-ee.md
@@ -0,0 +1,5 @@
+---
+redirect_to: upgrading_from_ce_to_ee.md
+---
+
+This document was moved to [another location](upgrading_from_ce_to_ee.md).
diff --git a/doc/update/mysql_to_postgresql.md b/doc/update/mysql_to_postgresql.md
index b7f7d71689d..b83abcd36f7 100644
--- a/doc/update/mysql_to_postgresql.md
+++ b/doc/update/mysql_to_postgresql.md
@@ -41,10 +41,26 @@ Debian/Ubuntu:
sudo apt-get install pgloader
```
-For other distributions, follow the instructions in PostrgreSQL's
+For other distributions, follow the instructions in PostgreSQL's
[download page](https://www.postgresql.org/download/) to add their repository
and then install `pgloader`.
+If you are migrating to a Docker based installation, you will need to install
+pgloader within the container as it is not included in the container image.
+
+1. Start a shell session in the context of the running container:
+
+ ``` bash
+ docker exec -it gitlab bash
+ ```
+
+1. Install pgloader:
+
+ ``` bash
+ apt-get update
+ apt-get -y install pgloader
+ ```
+
## Omnibus GitLab installations
For [Omnibus GitLab packages](https://about.gitlab.com/install/), you'll first
diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md
index 2e8380aa5d8..f2df4277ca8 100644
--- a/doc/update/patch_versions.md
+++ b/doc/update/patch_versions.md
@@ -67,7 +67,7 @@ sudo -u git -H bundle exec rake gettext:pack RAILS_ENV=production
sudo -u git -H bundle exec rake gettext:po_to_json RAILS_ENV=production
# Clean up assets and cache
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile cache:clear RAILS_ENV=production NODE_ENV=production
+sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile cache:clear RAILS_ENV=production NODE_ENV=production NODE_OPTIONS="--max_old_space_size=4096"
```
### 4. Update gitlab-workhorse to the corresponding version
@@ -106,14 +106,20 @@ sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
sudo -u git -H make
```
-### 8. Start application
+### 8. Install/Update `gitlab-elasticsearch-indexer` (optional) **[STARTER ONLY]**
+
+If you're interested in using GitLab's new [elasticsearch repository indexer](../integration/elasticsearch.md#elasticsearch-repository-indexer-beta) (currently in beta)
+please follow the instructions on the document linked above and enable the
+indexer usage in the GitLab admin settings.
+
+### 9. Start application
```bash
sudo service gitlab start
sudo service nginx restart
```
-### 9. Check application status
+### 10. Check application status
Check if GitLab and its environment are configured correctly:
diff --git a/doc/update/upgrading_from_ce_to_ee.md b/doc/update/upgrading_from_ce_to_ee.md
index 0d1ecab5f8e..428377adb19 100644
--- a/doc/update/upgrading_from_ce_to_ee.md
+++ b/doc/update/upgrading_from_ce_to_ee.md
@@ -9,6 +9,10 @@ Community Edition to Enterprise Edition. These documents can be found in the
[`doc/update` directory of Enterprise Edition's source
code][old-ee-upgrade-docs].
+If you want to upgrade the version only, for example 11.8 to 11.9, *without* changing the
+GitLab edition you are using (Community or Enterprise), see the
+[Upgrading from source](upgrading_from_source.md) documentation.
+
## General upgrading steps
This guide assumes you have a correctly configured and tested installation of
@@ -71,7 +75,7 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS
### 4. Install `gitlab-elasticsearch-indexer` (optional) **[STARTER ONLY]**
If you're interested in using GitLab's new [elasticsearch repository
-indexer][indexer-beta] (currently in beta) please follow the instructions on the
+indexer](../integration/elasticsearch.md) (currently in beta) please follow the instructions on the
document linked above and enable the indexer usage in the GitLab admin settings.
### 5. Start application
@@ -129,4 +133,3 @@ Additional instructions here.
[support@gitlab.com]: mailto:support@gitlab.com
[old-ee-upgrade-docs]: https://gitlab.com/gitlab-org/gitlab-ee/tree/11-8-stable-ee/doc/update
-[indexer-beta]: https://docs.gitlab.com/ee/integration/elasticsearch.html
diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md
index b0c9aaa1eed..bc8e5fed774 100644
--- a/doc/update/upgrading_from_source.md
+++ b/doc/update/upgrading_from_source.md
@@ -16,19 +16,16 @@ If the highest number stable branch is unclear please check the
[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
guide links by version.
+If you are changing from GitLab Community Edition to GitLab Enterprise Edition, see
+the [Upgrading from CE to EE](upgrading_from_ce_to_ee.md) documentation.
+
## Guidelines for all versions
This section contains all the steps necessary to upgrade Community Edition or
Enterprise Edition, regardless of the version you are upgrading to. Version
specific guidelines (should there be any) are covered separately.
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
+### 1. Backup
NOTE: If you installed GitLab from source, make sure `rsync` is installed.
@@ -38,6 +35,12 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
+### 2. Stop server
+
+```bash
+sudo service gitlab stop
+```
+
### 3. Update Ruby
NOTE: Beginning in GitLab 11.6, we only support Ruby 2.5 or higher, and dropped
@@ -49,9 +52,9 @@ Download Ruby and compile it:
```bash
mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.3.tar.gz
-echo 'f919a9fbcdb7abecd887157b49833663c5c15fda ruby-2.5.3.tar.gz' | shasum -c - && tar xzf ruby-2.5.3.tar.gz
-cd ruby-2.5.3
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.3.tar.gz
+echo '2347ed6ca5490a104ebd5684d2b9b5eefa6cd33c ruby-2.6.3.tar.gz' | shasum -c - && tar xzf ruby-2.6.3.tar.gz
+cd ruby-2.6.3
./configure --disable-install-rdoc
make
@@ -104,14 +107,54 @@ Download and install Go:
# Remove former Go installation folder
sudo rm -rf /usr/local/go
-curl --remote-name --progress https://dl.google.com/go/go1.10.5.linux-amd64.tar.gz
-echo 'a035d9beda8341b645d3f45a1b620cf2d8fb0c5eb409be36b389c0fd384ecc3a go1.10.5.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.10.5.linux-amd64.tar.gz
+curl --remote-name --progress https://dl.google.com/go/go1.11.10.linux-amd64.tar.gz
+echo 'aefaa228b68641e266d1f23f1d95dba33f17552ba132878b65bb798ffa37e6d0 go1.11.10.linux-amd64.tar.gz' | shasum -a256 -c - && \
+ sudo tar -C /usr/local -xzf go1.11.10.linux-amd64.tar.gz
sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.10.5.linux-amd64.tar.gz
+rm go1.11.10.linux-amd64.tar.gz
+```
+
+### 6. Update git
+
+NOTE: **Note:**
+GitLab 11.11 and higher only supports Git 2.21.x and newer, and
+[dropped support for older versions](https://gitlab.com/gitlab-org/gitlab-ce/issues/54255).
+Be sure to upgrade your installation if necessary.
+
+```bash
+# Make sure Git is version 2.21.0 or higher
+git --version
+
+# Remove packaged Git
+sudo apt-get remove git-core
+
+# Install dependencies
+sudo apt-get install -y libcurl4-openssl-dev libexpat1-dev gettext libz-dev libssl-dev build-essential
+
+# Download and compile pcre2 from source
+curl --silent --show-error --location https://ftp.pcre.org/pub/pcre/pcre2-10.33.tar.gz --output pcre2.tar.gz
+tar -xzf pcre2.tar.gz
+cd pcre2-10.33
+chmod +x configure
+./configure --prefix=/usr --enable-jit
+make
+make install
+
+# Download and compile from source
+cd /tmp
+curl --remote-name --location --progress https://www.kernel.org/pub/software/scm/git/git-2.21.0.tar.gz
+echo '85eca51c7404da75e353eba587f87fea9481ba41e162206a6f70ad8118147bee git-2.21.0.tar.gz' | shasum -a256 -c - && tar -xzf git-2.21.0.tar.gz
+cd git-2.21.0/
+./configure --with-libpcre
+make prefix=/usr/local all
+
+# Install into /usr/local/bin
+sudo make prefix=/usr/local install
+
+# You should edit config/gitlab.yml, change the git -> bin_path to /usr/local/bin/git
```
-### 6. Get latest code
+### 7. Get latest code
```bash
cd /home/git/gitlab
@@ -139,7 +182,7 @@ cd /home/git/gitlab
sudo -u git -H git checkout BRANCH-ee
```
-### 7. Update gitlab-shell
+### 8. Update gitlab-shell
```bash
cd /home/git/gitlab-shell
@@ -149,7 +192,7 @@ sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
sudo -u git -H bin/compile
```
-### 8. Update gitlab-workhorse
+### 9. Update gitlab-workhorse
Install and compile gitlab-workhorse. GitLab-Workhorse uses
[GNU Make](https://www.gnu.org/software/make/).
@@ -164,7 +207,7 @@ sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
sudo -u git -H make
```
-### 9. Update Gitaly
+### 10. Update Gitaly
#### Compile Gitaly
@@ -175,7 +218,7 @@ sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
sudo -u git -H make
```
-### 10. Update gitlab-pages
+### 11. Update gitlab-pages
#### Only needed if you use GitLab Pages
@@ -192,7 +235,7 @@ sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
sudo -u git -H make
```
-### 11. Update MySQL permissions
+### 12. Update MySQL permissions
If you are using MySQL you need to grant the GitLab user the necessary
permissions on the database:
@@ -214,7 +257,7 @@ You can make this setting permanent by adding it to your `my.cnf`:
log_bin_trust_function_creators=1
```
-### 12. Update configuration files
+### 13. Update configuration files
#### New configuration options for `gitlab.yml`
@@ -288,7 +331,7 @@ For Ubuntu 16.04.1 LTS:
sudo systemctl daemon-reload
```
-### 13. Install libs, migrations, etc.
+### 14. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
@@ -311,7 +354,7 @@ sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
+sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production NODE_OPTIONS="--max_old_space_size=4096"
# Clean up cache
sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
@@ -320,14 +363,14 @@ sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
**MySQL installations**: Run through the `MySQL strings limits` and `Tables and
data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-### 14. Start application
+### 15. Start application
```bash
sudo service gitlab start
sudo service nginx restart
```
-### 15. Check application status
+### 16. Check application status
Check if GitLab and its environment are configured correctly:
diff --git a/doc/user/admin_area/diff_limits.md b/doc/user/admin_area/diff_limits.md
index 9205860ef1f..4063c40a751 100644
--- a/doc/user/admin_area/diff_limits.md
+++ b/doc/user/admin_area/diff_limits.md
@@ -1,21 +1,40 @@
+---
+type: reference
+---
+
# Diff limits administration
+You can set a maximum size for display of diff files (patches).
+
+## Maximum diff patch size
+
+Diff files which exceed this value will be presented as 'too large' and won't
+be expandable. Instead of an expandable view, a link to the blob view will be
+shown.
+
+Patches greater than 10% of this size will be automatically collapsed, and a
+link to expand the diff will be presented.
+
NOTE: **Note:**
Merge requests and branch comparison views will be affected.
CAUTION: **Caution:**
-These settings are currently under experimental state. They'll
-increase the resource consumption of your instance and should
-be edited mindfully.
+This setting is experimental. An increased maximum will increase resource
+consumption of your instance. Keep this in mind when adjusting the maximum.
-1. Access **Admin area > Settings > General**
-1. Expand **Diff limits**
+1. Go to **Admin area > Settings > General**.
+1. Expand **Diff limits**.
+1. Enter a value for **Maximum diff patch size**, measured in bytes.
+1. Click on **Save changes**.
-### Maximum diff patch size
+<!-- ## Troubleshooting
-This is the content size each diff file (patch) is allowed to reach before
-it's collapsed, without the possibility of being expanded. A link redirecting
-to the blob view will be presented for the patches that surpass this limit.
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
-Patches surpassing 10% of this content size will be automatically collapsed,
-but expandable (a link to expand the diff will be presented).
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/admin_area/geo_nodes.md b/doc/user/admin_area/geo_nodes.md
new file mode 100644
index 00000000000..d99b87cbc5c
--- /dev/null
+++ b/doc/user/admin_area/geo_nodes.md
@@ -0,0 +1,86 @@
+---
+type: howto
+---
+
+# Geo nodes admin area **[PREMIUM ONLY]**
+
+You can configure various settings for GitLab Geo nodes. For more information, see
+[Geo documentation](../../administration/geo/replication/index.md).
+
+On the primary node, go to **Admin area > Geo**. On secondary nodes, go to **Admin area > Geo > Nodes**.
+
+## Common settings
+
+All Geo nodes have the following settings:
+
+| Setting | Description |
+| --------| ----------- |
+| Primary | This marks a Geo Node as **primary** node. There can be only one **primary** node; make sure that you first add the **primary** node and then all the others. |
+| Name | The unique identifier for the Geo node. Must match the setting `gitlab_rails[geo_node_name]` in `/etc/gitlab/gitlab.rb`. The setting defaults to `external_url` with a trailing slash. |
+| URL | The instance's user-facing URL. |
+
+The node you're reading from is indicated with a green `Current node` label, and
+the **primary** node is given a blue `Primary` label. Remember that you can only make
+changes on the **primary** node!
+
+## **Secondary** node settings
+
+**Secondary** nodes have a number of additional settings available:
+
+| Setting | Description |
+|---------------------------|-------------|
+| Selective synchronization | Enable Geo [selective sync](../../administration/geo/replication/configuration.md#selective-synchronization) for this **secondary** node. |
+| Repository sync capacity | Number of concurrent requests this **secondary** node will make to the **primary** node when backfilling repositories. |
+| File sync capacity | Number of concurrent requests this **secondary** node will make to the **primary** node when backfilling files. |
+
+## Geo backfill
+
+**Secondary** nodes are notified of changes to repositories and files by the **primary** node,
+and will always attempt to synchronize those changes as quickly as possible.
+
+Backfill is the act of populating the **secondary** node with repositories and files that
+existed *before* the **secondary** node was added to the database. Since there may be
+extremely large numbers of repositories and files, it's infeasible to attempt to
+download them all at once, so GitLab places an upper limit on the concurrency of
+these operations.
+
+How long the backfill takes is a function of the maximum concurrency, but higher
+values place more strain on the **primary** node. From [GitLab 10.2](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3107),
+the limits are configurable. If your **primary** node has lots of surplus capacity,
+you can increase the values to complete backfill in a shorter time. If it's
+under heavy load and backfill is reducing its availability for normal requests,
+you can decrease them.
+
+## Using a different URL for synchronization
+
+The **primary** node's Internal URL is used by **secondary** nodes to contact it
+(to sync repositories, for example). The name Internal URL distinguishes it from
+[External URL](https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-the-external-url-for-gitlab)
+which is used by users. Internal URL does not need to be a private address.
+
+Internal URL defaults to External URL, but you can customize it under
+**Admin area > Geo Nodes**.
+
+## Multiple secondary nodes behind a load balancer
+
+In GitLab 11.11, **secondary** nodes can use identical external URLs as long as
+a unique `name` is set for each Geo node. The `gitlab.rb` setting
+`gitlab_rails[geo_node_name]` must:
+
+- Be set for each GitLab instance that runs `unicorn`, `sidekiq`, or `geo_logcursor`.
+- Match a Geo node name.
+
+The load balancer must use sticky sessions in order to avoid authentication
+failures and cross site request errors.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. --> \ No newline at end of file
diff --git a/doc/user/admin_area/img/admin_wrench.png b/doc/user/admin_area/img/admin_wrench.png
new file mode 100644
index 00000000000..17eee143e87
--- /dev/null
+++ b/doc/user/admin_area/img/admin_wrench.png
Binary files differ
diff --git a/doc/user/admin_area/img/index_runners_search_or_filter.png b/doc/user/admin_area/img/index_runners_search_or_filter.png
new file mode 100644
index 00000000000..5176a1a39bf
--- /dev/null
+++ b/doc/user/admin_area/img/index_runners_search_or_filter.png
Binary files differ
diff --git a/doc/user/admin_area/img/license_admin_area.png b/doc/user/admin_area/img/license_admin_area.png
new file mode 100644
index 00000000000..b5662b81c5e
--- /dev/null
+++ b/doc/user/admin_area/img/license_admin_area.png
Binary files differ
diff --git a/doc/user/admin_area/img/license_details.png b/doc/user/admin_area/img/license_details.png
new file mode 100644
index 00000000000..2085bb437ad
--- /dev/null
+++ b/doc/user/admin_area/img/license_details.png
Binary files differ
diff --git a/doc/user/admin_area/img/license_upload.png b/doc/user/admin_area/img/license_upload.png
new file mode 100644
index 00000000000..29d55175a2d
--- /dev/null
+++ b/doc/user/admin_area/img/license_upload.png
Binary files differ
diff --git a/doc/user/admin_area/index.md b/doc/user/admin_area/index.md
index 00cea22e4e1..91c771764f8 100644
--- a/doc/user/admin_area/index.md
+++ b/doc/user/admin_area/index.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# GitLab Admin Area **[CORE ONLY]**
The Admin Area provides a web UI for administering some features of GitLab self-managed instances.
@@ -14,16 +18,210 @@ Only admin users can access the Admin Area.
The Admin Area is made up of the following sections:
-| Section | Description |
-|:------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Overview | View your GitLab Dashboard, and maintain projects, users, groups, jobs, runners, and Gitaly servers. |
-| Monitoring | View GitLab system information, and information on background jobs, logs, [health checks](monitoring/health_check.md), request profiles, and audit logs. |
-| Messages | Send and manage [broadcast messages](broadcast_messages.md) for your users. |
-| System Hooks | Configure [system hooks](../../system_hooks/system_hooks.md) for many events. |
-| Applications | Create system [OAuth applications](../../integration/oauth_provider.md) for integrations with other services. |
-| Abuse Reports | Manage [abuse reports](abuse_reports.md) submitted by your users. |
-| Deploy Keys | Create instance-wide [SSH deploy keys](../../ssh/README.md#deploy-keys). |
-| Service Templates | Create [service templates](../project/integrations/services_templates.md) for projects. |
-| Labels | Create and maintain [labels](labels.md) for your GitLab instance. |
-| Appearance | Customize [GitLab's appearance](../../customization/index.md). |
-| Settings | Modify the [settings](settings/index.md) for your GitLab instance. |
+| Section | Description |
+|:---------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------|
+| Overview | View your GitLab [Dashboard](#admin-dashboard), and administer [projects](#administer-projects), [users](#administer-users), [groups](#administer-groups), [jobs](#administer-jobs), [Runners](#administer-runners), and [Gitaly servers](#administer-gitaly-servers). |
+| Monitoring | View GitLab system information, and information on background jobs, logs, [health checks](monitoring/health_check.md), request profiles, and audit logs. |
+| Messages | Send and manage [broadcast messages](broadcast_messages.md) for your users. |
+| System Hooks | Configure [system hooks](../../system_hooks/system_hooks.md) for many events. |
+| Applications | Create system [OAuth applications](../../integration/oauth_provider.md) for integrations with other services. |
+| Abuse Reports | Manage [abuse reports](abuse_reports.md) submitted by your users. |
+| License **[STARTER ONLY]** | Upload, display, and remove [licenses](license.md). |
+| Push Rules **[STARTER]** | Configure pre-defined git [push rules](../../push_rules/push_rules.md) for projects. |
+| Geo **[PREMIUM ONLY]** | Configure and maintain [Geo nodes](geo_nodes.md). |
+| Deploy Keys | Create instance-wide [SSH deploy keys](../../ssh/README.md#deploy-keys). |
+| Service Templates | Create [service templates](../project/integrations/services_templates.md) for projects. |
+| Labels | Create and maintain [labels](labels.md) for your GitLab instance. |
+| Appearance | Customize [GitLab's appearance](../../customization/index.md). |
+| Settings | Modify the [settings](settings/index.md) for your GitLab instance. |
+
+## Admin Dashboard
+
+The Dashboard provides statistics and system information about the GitLab instance.
+
+To access the Dashboard, either:
+
+- Click the Admin Area icon (the wrench icon).
+- Visit `/admin` on your self-managed instance.
+
+The Dashboard is the default view of the Admin Area, and is made up of the following sections:
+
+| Section | Description |
+|------------|---------------|
+| Projects | The total number of projects, up to 10 of the latest projects, and the option of creating a new project. |
+| Users | The total number of users, up to 10 of the latest users, and the option of creating a new user. |
+| Groups | The total number of groups, up to 10 of the latest groups, and the option of creating a new group. |
+| Statistics | Totals of all elements of the GitLab instance. |
+| Features | All features available on the GitLab instance. Enabled features are marked with a green circle icon, and disabled features are marked with a power icon. |
+| Components | The major components of GitLab and the version number of each. A link to the Gitaly Servers is also included. |
+
+## Administer Projects
+
+You can administer all projects in the GitLab instance from the Admin Area's Projects page.
+
+To access the Projects page, go to **Admin Area > Overview > Projects**.
+
+Click the **All**, **Private**, **Internal**, or **Public** tab to list only projects of that
+criteria.
+
+By default, all projects are listed, in reverse order of when they were last updated. For each
+project, the following information is listed:
+
+- Name.
+- Namespace.
+- Description.
+- Size, updated every 15 minutes at most.
+
+Projects can be edited or deleted.
+
+The list of projects can be sorted by:
+
+- Name.
+- Last created.
+- Oldest created.
+- Last updated.
+- Oldest updated.
+- Owner.
+
+A user can choose to hide or show archived projects in the list.
+
+In the **Filter by name** field, type the project name you want to find, and GitLab will filter
+them as you type.
+
+Select from the **Namespace** dropdown to filter only projects in that namespace.
+
+You can combine the filter options. For example, to list only public projects with `score` in their name:
+
+1. Click the **Public** tab.
+1. Enter `score` in the **Filter by name...** input box.
+
+## Administer Users
+
+You can administer all users in the GitLab instance from the Admin Area's Users page.
+
+To access the Users page, go to **Admin Area > Overview > Users**.
+
+Click the **Active**, **Admins**, **2FA Enabled**, or **2FA Disabled**, **External**, or
+**Without projects** tab to list only users of that criteria.
+
+For each user, their username, email address, are listed, also the date their account was
+created and the date of last activity. To edit a user, click the **Edit** button in that user's
+row. To delete the user, or delete the user and their contributions, click the cog dropdown in
+that user's row, and select the desired option.
+
+To change the sort order:
+
+1. Click the sort dropdown.
+1. Select the desired order.
+
+By default the sort dropdown shows **Name**.
+
+To search for users, enter your criteria in the search field. The user search is case
+insensitive, and applies partial matching to name and username. To search for an email address,
+you must provide the complete email address.
+
+## Administer Groups
+
+You can administer all groups in the GitLab instance from the Admin Area's Groups page.
+
+To access the Groups page, go to **Admin Area > Overview > Groups**.
+
+For each group, the page displays their name, description, size, number of projects in the group,
+number of members, and whether the group is private, internal, or public. To edit a group, click
+the **Edit** button in that group's row. To delete the group, click the **Delete** button in
+that group's row.
+
+To change the sort order, click the sort dropdown and select the desired order. The default
+sort order is by **Last created**.
+
+To search for groups by name, enter your criteria in the search field. The group search is case
+insensitive, and applies partial matching.
+
+To [Create a new group](../group/index.md#create-a-new-group) click **New group**.
+
+## Administer Jobs
+
+You can administer all jobs in the GitLab instance from the Admin Area's Jobs page.
+
+To access the Jobs page, go to **Admin Area > Overview > Jobs**.
+
+All jobs are listed, in descending order of job ID.
+
+Click the **All** tab to list all jobs. Click the **Pending**, **Running**, or **Finished** tab to list only jobs of that status.
+
+For each job, the following details are listed:
+
+| Field | Description |
+|--------- | ----------- |
+| Status | Job status, either **passed**, **skipped**, or **failed**. |
+| Job | Includes links to the job, branch, and the commit that started the job. |
+| Pipeline | Includes a link to the specific pipeline. |
+| Project | Name of the project, and organization, to which the job belongs. |
+| Runner | Name of the CI runner assigned to execute the job. |
+| Stage | Stage that the job is declared in a `.gitlab-ci.yml` file. |
+| Name | Name of the job specified in a `.gitlab-ci.yml` file. |
+| Timing | Duration of the job, and how long ago the job completed. |
+| Coverage | Percentage of tests coverage. |
+
+## Administer Runners
+
+You can adminster all Runners in the GitLab instance from the Admin Area's **Runners** page. See
+[GitLab Runner](https://docs.gitlab.com/runner/) for more information on Runner itself.
+
+To access the **Runners** page, go to **Admin Area > Overview > Runners**.
+
+The **Runners** page features:
+
+- A description of Runners, and their possible states.
+- Instructions on installing a Runner.
+- A list of all registered Runners.
+
+Runners are listed in descending order by the date they were created, by default. You can change
+the sort order to *Last Contacted* from the dropdown beside the search field.
+
+To search Runners' descriptions:
+
+1. In the **Search or filter results...** field, type the description of the Runner you want to
+find.
+1. Press Enter.
+
+You can also filter Runners by status, type, and tag. To filter:
+
+1. Click in the **Search or filter results...** field.
+1. Select **status:**, **type:**, or **tag:**.
+1. Select or enter your search criteria.
+
+![Attributes of a Runner, with the **Search or filter results...** field active](img/index_runners_search_or_filter.png)
+
+For each Runner, the following attributes are listed:
+
+| Attribute | Description |
+| ------------ | ----------- |
+| Type | One or more of the following states: shared, group, specific, locked, or paused |
+| Runner token | Token used to identify the Runner, and which the Runner uses to communicate with the GitLab instance |
+| Description | Description given to the Runner when it was created |
+| Version | GitLab Runner version |
+| IP address | IP address of the host on which the Runner is registered |
+| Projects | Projects to which the Runner is assigned |
+| Jobs | Total of jobs run by the Runner |
+| Tags | Tags associated with the Runner |
+| Last contact | Timestamp indicating when the GitLab instance last contacted the Runner |
+
+You can also edit, pause, or remove each Runner.
+
+## Administer Gitaly servers
+
+You can list all Gitaly servers in the GitLab instance from the Admin Area's **Gitaly Servers**
+page. For more details, see [Gitaly](../../administration/gitaly/index.md).
+
+To access the **Gitaly Servers** page, go to **Admin Area > Overview > Gitaly Servers**.
+
+For each Gitaly server, the following details are listed:
+
+| Field | Description |
+| -------------- | ----------- |
+| Storage | Repository storage |
+| Address | Network address on which the Gitaly server is listening |
+| Server version | Gitaly version |
+| Git version | Version of Git installed on the Gitaly server |
+| Up to date | Indicates if the Gitaly server version is the latest version available. A green dot indicates the server is up to date. |
diff --git a/doc/user/admin_area/labels.md b/doc/user/admin_area/labels.md
index e383142c33e..eba27548f86 100644
--- a/doc/user/admin_area/labels.md
+++ b/doc/user/admin_area/labels.md
@@ -1,9 +1,25 @@
+---
+type: reference
+---
+
# Labels administration **[CORE ONLY]**
-## Default Labels
+In the Admin Area, you can manage labels for the GitLab instance. For more details, see [Labels](../project/labels.md).
-### Define your own default Label Set
+## Default Labels
-Labels that are created within the Labels view on the Admin Dashboard will be automatically added to each new project.
+Labels created in the Admin Area become available to each _new_ project.
![Default label set](img/admin_labels.png)
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/admin_area/license.md b/doc/user/admin_area/license.md
new file mode 100644
index 00000000000..8ddb9c3d707
--- /dev/null
+++ b/doc/user/admin_area/license.md
@@ -0,0 +1,120 @@
+---
+type: howto
+---
+
+# Activate all GitLab Enterprise Edition functionality with a license **[STARTER ONLY]**
+
+To activate all GitLab Enterprise Edition (EE) functionality, you need to upload
+a license. Once you've received your license from GitLab Inc., you can upload it
+by **signing into your GitLab instance as an admin** or add it at
+installation time.
+
+The license has the form of a base64 encoded ASCII text with a `.gitlab-license`
+extension and can be obtained when you [purchase one][pricing] or when you sign
+up for a [free trial].
+
+NOTE: **Note:**
+As of GitLab Enterprise Edition 9.4.0, a newly-installed instance without an
+uploaded license will only have the Core features active. A trial license will
+activate all Ultimate features, but after
+[the trial expires](#what-happens-when-your-license-expires), some functionality
+will be locked.
+
+## Uploading your license
+
+The very first time you visit your GitLab EE installation signed in as an admin,
+you should see a note urging you to upload a license with a link that takes you
+straight to the License admin area.
+
+Otherwise, you can:
+
+1. Navigate manually to the **Admin Area** by clicking the wrench icon in the menu bar.
+
+ ![Admin area icon](img/admin_wrench.png)
+
+1. And then going to the **License** tab and click on **Upload New License**.
+
+ ![License admin area](img/license_admin_area.png)
+
+1. If you've received a `.gitlab-license` file, you should have already downloaded
+ it in your local machine. You can then upload it directly by choosing the
+ license file and clicking the **Upload license** button. In the image below,
+ you can see that the selected license file is named `GitLab.gitlab-license`.
+
+ ![Upload license](img/license_upload.png)
+
+ If you've received your license as plain text, you need to select the
+ "Enter license key" option, copy the license, paste it into the "License key"
+ field and click **Upload license**.
+
+## Add your license at install time
+
+A license can be automatically imported at install time, by placing a file named
+`Gitlab.gitlab-license` in `/etc/gitlab/` for Omnibus, or `config/` for source installations.
+
+It is also possible to specify a custom location and filename for the license.
+
+Source installations should set the `GITLAB_LICENSE_FILE` environment
+variable with the path to a valid GitLab Enterprise Edition license.
+
+```sh
+export GITLAB_LICENSE_FILE="/path/to/license/file"
+```
+
+Omnibus installations should add this entry to `gitlab.rb`:
+
+```ruby
+gitlab_rails['license_file'] = "/path/to/license/file"
+```
+
+CAUTION:: **Caution:**
+These methods will only add a license at the time of installation. Use the
+admin area in the web ui to renew or upgrade licenses.
+
+---
+
+Once the license is uploaded, all GitLab Enterprise Edition functionality
+will be active until the end of the license period. When that period ends, the
+instance will [fall back](#what-happens-when-your-license-expires) to Core-only
+functionality.
+
+You can review the license details at any time in the License section of the
+Admin Area.
+
+![License details](img/license_details.png)
+
+## Notification before the license expires
+
+One month before the license expires, a message informing when the expiration
+is due to, will start appearing to GitLab admins. Make sure that you update your
+license, otherwise you will miss all the paid features if it expires.
+
+## What happens when your license expires
+
+In case your license expires, GitLab will lock down some features like Git pushes,
+issue creation, etc., and a message to inform of the expired license will be
+presented to all admins.
+
+In order to get back all the previous functionality, a new license must be uploaded.
+To fall back to having only the Core features active, you'll need to delete the
+expired license(s).
+
+## License history
+
+It's possible to upload and view more than one license,
+but only the latest license will be used as the active license.
+
+[free trial]: https://about.gitlab.com/free-trial/
+[pricing]: https://about.gitlab.com/pricing/
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. --> \ No newline at end of file
diff --git a/doc/user/admin_area/monitoring/health_check.md b/doc/user/admin_area/monitoring/health_check.md
index e183898dfb1..f80d4e9d2aa 100644
--- a/doc/user/admin_area/monitoring/health_check.md
+++ b/doc/user/admin_area/monitoring/health_check.md
@@ -1,12 +1,14 @@
-# Health Check
+---
+type: concepts, howto
+---
-> **Notes:**
+# Health Check
-> - Liveness and readiness probes were [introduced][ce-10416] in GitLab 9.1.
-> - The `health_check` endpoint was [introduced][ce-3888] in GitLab 8.8 and was
-> be deprecated in GitLab 9.1.
-> - [Access token](#access-token-deprecated) has been deprecated in GitLab 9.4
-> in favor of [IP whitelist](#ip-whitelist)
+> - Liveness and readiness probes were [introduced][ce-10416] in GitLab 9.1.
+> - The `health_check` endpoint was [introduced][ce-3888] in GitLab 8.8 and was
+> deprecated in GitLab 9.1.
+> - [Access token](#access-token-deprecated) has been deprecated in GitLab 9.4
+> in favor of [IP whitelist](#ip-whitelist).
GitLab provides liveness and readiness probes to indicate service health and
reachability to required services. These probes report on the status of the
@@ -17,8 +19,7 @@ traffic until the system is ready or restart the container as needed.
## IP whitelist
To access monitoring resources, the requesting client IP needs to be included in a whitelist.
-
-[Read how to add IPs to a whitelist for the monitoring endpoints][admin].
+For details, see [how to add IPs to a whitelist for the monitoring endpoints](../../../administration/monitoring/ip_whitelist.md).
## Using the endpoints
@@ -30,7 +31,7 @@ With default whitelist settings, the probes can be accessed from localhost using
The first endpoint, `health`, only checks whether the application server is running. It does not verify the database or other services are running. A successful response will return a 200 status code with the following message:
-```
+```text
GitLab OK
```
@@ -87,9 +88,8 @@ will return a valid successful HTTP status code, and a `success` message.
## Access token (Deprecated)
->**Note:**
-Access token has been deprecated in GitLab 9.4
-in favor of [IP whitelist](#ip-whitelist)
+> NOTE: **Note:**
+> Access token has been deprecated in GitLab 9.4 in favor of [IP whitelist](#ip-whitelist).
An access token needs to be provided while accessing the probe endpoints. The current
accepted token can be found under the **Admin area âž” Monitoring âž” Health check**
@@ -99,14 +99,25 @@ accepted token can be found under the **Admin area âž” Monitoring âž” Health che
The access token can be passed as a URL parameter:
-```
+```text
https://gitlab.example.com/-/readiness?token=ACCESS_TOKEN
```
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
+
[ce-10416]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10416
[ce-3888]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3888
[pingdom]: https://www.pingdom.com
[nagios-health]: https://nagios-plugins.org/doc/man/check_http.html
[newrelic-health]: https://docs.newrelic.com/docs/alerts/alert-policies/downtime-alerts/availability-monitoring
[kubernetes]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/
-[admin]: ../../../administration/monitoring/ip_whitelist.md
diff --git a/doc/user/admin_area/settings/account_and_limit_settings.md b/doc/user/admin_area/settings/account_and_limit_settings.md
new file mode 100644
index 00000000000..001e4b6bf48
--- /dev/null
+++ b/doc/user/admin_area/settings/account_and_limit_settings.md
@@ -0,0 +1,62 @@
+---
+type: reference
+---
+
+# Account and limit settings
+
+## Repository size limit **[STARTER]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/740) in [GitLab Enterprise Edition 8.12](https://about.gitlab.com/2016/09/22/gitlab-8-12-released/#limit-project-size-ee).
+> Available in [GitLab Starter](https://about.gitlab.com/pricing/).
+
+Repositories within your GitLab instance can grow quickly, especially if you are
+using LFS. Their size can grow exponentially, rapidly consuming available storage.
+
+To avoid this from happening, you can set a hard limit for your repositories' size.
+This limit can be set globally, per group, or per project, with per project limits
+taking the highest priority.
+
+There are numerous use cases where you might set up a limit for repository size.
+For instance, consider the following workflow:
+
+1. Your team develops apps which require large files to be stored in
+ the application repository.
+1. Although you have enabled [Git LFS](../../../workflow/lfs/manage_large_binaries_with_git_lfs.md#git-lfs)
+ to your project, your storage has grown significantly.
+1. Before you exceed available storage, you set up a limit of 10 GB
+ per repository.
+
+### How it works
+
+Only a GitLab administrator can set those limits. Setting the limit to `0` means
+there are no restrictions.
+
+These settings can be found within:
+
+- Each project's settings.
+- A group's settings.
+- The **Size limit per repository (MB)** field in the **Account and limit** section of a GitLab instance's
+ settings by navigating to either:
+ - **Admin Area > Settings > General**.
+ - The path `/admin/application_settings`.
+
+The first push of a new project, including LFS objects, will be checked for size
+and **will** be rejected if the sum of their sizes exceeds the maximum allowed
+repository size.
+
+For details on manually purging files, see [reducing the repository size using Git](../../project/repository/reducing_the_repo_size_using_git.md).
+
+NOTE: **Note:**
+For GitLab.com, the repository size limit is 10 GB.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md
index 22011cc6967..d2605cbfb5e 100644
--- a/doc/user/admin_area/settings/continuous_integration.md
+++ b/doc/user/admin_area/settings/continuous_integration.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# Continuous Integration and Deployment Admin settings **[CORE ONLY]**
In this area, you will find settings for Auto DevOps, Runners and job artifacts.
@@ -10,8 +14,8 @@ You can find it in the admin area, under **Settings > Continuous Integration and
To enable (or disable) [Auto DevOps](../../../topics/autodevops/index.md)
for all projects:
-1. Go to **Admin area > Settings > Continuous Integration and Deployment**.
-1. Check (or uncheck to disable) the box that says "Default to Auto DevOps pipeline for all projects".
+1. Go to **Admin area > Settings > Continuous Integration and Deployment**
+1. Check (or uncheck to disable) the box that says "Default to Auto DevOps pipeline for all projects"
1. Optionally, set up the [Auto DevOps base domain](../../../topics/autodevops/index.md#auto-devops-base-domain)
which is going to be used for Auto Deploy and Auto Review Apps.
1. Hit **Save changes** for the changes to take effect.
@@ -24,9 +28,9 @@ If you want to disable it for a specific project, you can do so in
## Maximum artifacts size **[CORE ONLY]**
-The maximum size of the [job artifacts][art-yml] can be set in the Admin area
-of your GitLab instance. The value is in *MB* and the default is 100MB per job;
-on GitLab.com it's [set to 1G](../../gitlab_com/index.md#gitlab-cicd).
+The maximum size of the [job artifacts](../../../administration/job_artifacts.md)
+can be set in the Admin area of your GitLab instance. The value is in *MB* and
+the default is 100MB per job; on GitLab.com it's [set to 1G](../../gitlab_com/index.md#gitlab-cicd).
To change it:
@@ -50,6 +54,94 @@ This setting is set per job and can be overridden in
[`.gitlab-ci.yml`](../../../ci/yaml/README.md#artifactsexpire_in).
To disable the expiration, set it to `0`. The default unit is in seconds.
+## Shared Runners pipeline minutes quota **[STARTER ONLY]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1078)
+in GitLab Starter 8.16.
+
+If you have enabled shared Runners for your GitLab instance, you can limit their
+usage by setting a maximum number of pipeline minutes that a group can use on
+shared Runners per month. Setting this to `0` (default value) will grant
+unlimited pipeline minutes. While build limits are stored as minutes, the
+counting is done in seconds. Usage resets on the first day of each month.
+On GitLab.com, the quota is calculated based on your
+[subscription plan](https://about.gitlab.com/pricing/#gitlab-com).
+
+To change the pipelines minutes quota:
+
+1. Go to **Admin area > Settings > Continuous Integration and Deployment**
+1. Set the pipeline minutes quota limit.
+1. Hit **Save changes** for the changes to take effect
+
+---
+
+While the setting in the Admin area has a global effect, as an admin you can
+also change each group's pipeline minutes quota to override the global value.
+
+1. Navigate to the **Groups** admin area and hit the **Edit** button for the
+ group you wish to change the pipeline minutes quota.
+1. Set the pipeline minutes quota to the desired value
+1. Hit **Save changes** for the changes to take effect.
+
+Once saved, you can see the build quota in the group admin view.
+The quota can also be viewed in the project admin view if shared Runners
+are enabled.
+
+![Project admin info](img/admin_project_quota_view.png)
+
+When the pipeline minutes quota for a group is set to a value different than 0,
+the **Pipelines quota** page is available to the group page settings list.
+You can see there an overview of the pipeline minutes quota of all projects of
+the group.
+
+![Group pipelines quota](img/group_pipelines_quota.png)
+
+
+## Extra Shared Runners pipeline minutes quota
+
+NOTE: **Note:**
+Only available on GitLab.com.
+
+You can purchase additional CI minutes so your pipelines will not be blocked after you have
+used all your CI minutes from your main quota.
+
+In order to purchase additional minutes, you should follow these steps:
+
+1. Go to **Group > Settings > Pipelines quota**. Once you are on that page, click on **Buy additional minutes**.
+
+ ![Buy additional minutes](img/buy_btn.png)
+
+1. Locate the subscription card that is linked to your group on GitLab.com,
+click on **Buy more CI minutes**, and complete the details about the transaction.
+
+ ![Buy additional minutes](img/buy_minutes_card.png)
+
+1. Once we have processed your payment, the extra CI minutes
+will be synced to your Group and you can visualize it from the
+**Group > Settings > Pipelines quota** page:
+
+ ![Additional minutes](img/additional_minutes.png)
+
+Be aware that:
+
+1. If you have purchased extra CI minutes before the purchase of a paid plan,
+we will calculate a pro-rated charge for your paid plan. That means you may
+be charged for less than one year since your subscription was previously
+created with the extra CI minutes.
+1. Once the extra CI minutes has been assigned to a Group they cannot be transferred
+to a different Group.
+1. If you have some minutes used over your default quota, these minutes will
+be deducted from your Additional Minutes quota immediately after your purchase of additional
+minutes.
+
+## What happens when my CI minutes quota run out
+
+When the CI minutes quota run out, an email is sent automatically to notifies the owner(s) of the group/namespace which
+includes a link to [purchase more minutes](https://customers.gitlab.com/plans).
+
+If you are not the owner of the group, you will need to contact them to let them know they need to
+[purchase more minutes](https://customers.gitlab.com/plans).
+
## Archive jobs **[CORE ONLY]**
Archiving jobs is useful for reducing the CI/CD footprint on the system by
@@ -65,3 +157,15 @@ To set the duration for which the jobs will be considered as old and expired:
Once that time passes, the jobs will be archived and no longer able to be
retried. Make it empty to never expire jobs. It has to be no less than 1 day,
for example: <code>15 days</code>, <code>1 month</code>, <code>2 years</code>.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/admin_area/settings/email.md b/doc/user/admin_area/settings/email.md
index 50c318a4969..9555a695b13 100644
--- a/doc/user/admin_area/settings/email.md
+++ b/doc/user/admin_area/settings/email.md
@@ -1,15 +1,37 @@
+---
+type: reference
+---
+
# Email
+You can customize some of the content in emails sent from your GitLab instance.
+
## Custom logo
The logo in the header of some emails can be customized, see the [logo customization section](../../../customization/branded_page_and_email_header.md).
+## Custom additional text **[PREMIUM ONLY]**
+
+> [Introduced][ee-5031] in [GitLab Premium][eep] 10.7.
+
+The additional text will appear at the bottom of any email and can be used for
+legal/auditing/compliance reasons.
+
+1. Go to **Admin area > Settings** (`/admin/application_settings`).
+1. Under the **Email** section, change the **Additional text** field.
+1. Hit **Save** for the changes to take effect.
+
+![Admin email settings](img/email_settings.png)
+
+[ee-5031]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/5031
+[eep]: https://about.gitlab.com/pricing/
+
## Custom hostname for private commit emails
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22560) in GitLab 11.5.
-This configuration option sets the email hostname for [private commit emails](../../profile/index.md#private-commit-email),
-and it's, by default, set to `users.noreply.YOUR_CONFIGURED_HOSTNAME`.
+This configuration option sets the email hostname for [private commit emails](../../profile/index.md#private-commit-email).
+ By default it is set to `users.noreply.YOUR_CONFIGURED_HOSTNAME`.
In order to change this option:
@@ -18,5 +40,17 @@ In order to change this option:
1. Hit **Save** for the changes to take effect.
NOTE: **Note**: Once the hostname gets configured, every private commit email using the previous hostname, will not get
-recognized by GitLab. This can directly conflict with certain [Push rules](https://docs.gitlab.com/ee/push_rules/push_rules.html) such as
+recognized by GitLab. This can directly conflict with certain [Push rules](../../../push_rules/push_rules.md) such as
`Check whether author is a GitLab user` and `Check whether committer is the current authenticated user`.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. --> \ No newline at end of file
diff --git a/doc/user/admin_area/settings/external_authorization.md b/doc/user/admin_area/settings/external_authorization.md
new file mode 100644
index 00000000000..11c0867da17
--- /dev/null
+++ b/doc/user/admin_area/settings/external_authorization.md
@@ -0,0 +1,128 @@
+---
+type: reference
+---
+
+# External authorization control **[CORE ONLY]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/4216) in
+> [GitLab Premium](https://about.gitlab.com/pricing) 10.6.
+> [Moved](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27056) to
+> [GitLab Core](https://about.gitlab.com/pricing/) in 11.10.
+
+In highly controlled environments, it may be necessary for access policy to be
+controlled by an external service that permits access based on project
+classification and user access. GitLab provides a way to check project
+authorization with your own defined service.
+
+## Overview
+
+Once the external service is configured and enabled, when a project is accessed,
+a request is made to the external service with the user information and project
+classification label assigned to the project. When the service replies with a
+known response, the result is cached for 6 hours.
+
+If the external authorization is enabled, GitLab will further block pages and
+functionality that render cross-project data. That includes:
+
+- most pages under Dashboard (Activity, Milestones, Snippets, Assigned merge
+ requests, Assigned issues, Todos)
+- under a specific group (Activity, Contribution analytics, Issues, Issue boards,
+ Labels, Milestones, Merge requests)
+- Global and Group search will be disabled
+
+This is to prevent performing to many requests at once to the external
+authorization service.
+
+Whenever access is granted or denied this is logged in a logfile called
+`external-policy-access-control.log`.
+Read more about logs GitLab keeps in the [omnibus documentation][omnibus-log-docs].
+
+## Configuration
+
+The external authorization service can be enabled by an admin on the GitLab's
+admin area under the settings page:
+
+![Enable external authorization service](img/external_authorization_service_settings.png)
+
+The available required properties are:
+
+- **Service URL**: The URL to make authorization requests to. When leaving the
+ URL blank, cross project features will remain available while still being able
+ to specify classification labels for projects.
+- **External authorization request timeout**: The timeout after which an
+ authorization request is aborted. When a request times out, access is denied
+ to the user.
+- **Client authentication certificate**: The certificate to use to authenticate
+ with the external authorization service.
+- **Client authentication key**: Private key for the certificate when
+ authentication is required for the external authorization service, this is
+ encrypted when stored.
+- **Client authentication key password**: Passphrase to use for the private key when authenticating with the external service this is encrypted when stored.
+- **Default classification label**: The classification label to use when
+ requesting authorization if no specific label is defined on the project
+
+When using TLS Authentication with a self signed certificate, the CA certificate
+needs to be trused by the openssl installation. When using GitLab installed using
+Omnibus, learn to install a custom CA in the
+[omnibus documentation][omnibus-ssl-docs]. Alternatively learn where to install
+custom certificates using `openssl version -d`.
+
+## How it works
+
+When GitLab requests access, it will send a JSON POST request to the external
+service with this body:
+
+```json
+{
+ "user_identifier": "jane@acme.org",
+ "project_classification_label": "project-label",
+ "user_ldap_dn": "CN=Jane Doe,CN=admin,DC=acme"
+}
+```
+
+The `user_ldap_dn` is optional and is only sent when the user is logged in
+through LDAP.
+
+When the external authorization service responds with a status code 200, the
+user is granted access. When the external service responds with a status code
+401 or 403, the user is denied access. In any case, the request is cached for 6 hours.
+
+When denying access, a `reason` can be optionally specified in the JSON body:
+
+```json
+{
+ "reason": "You are not allowed access to this project."
+}
+```
+
+Any other status code than 200, 401 or 403 will also deny access to the user, but the
+response will not be cached.
+
+If the service times out (after 500ms), a message "External Policy Server did
+not respond" will be displayed.
+
+## Classification labels
+
+You can use your own classification label in the project's
+**Settings > General > General project settings** page in the "Classification
+label" box. When no classification label is specified on a project, the default
+label defined in the [global settings](#configuration) will be used.
+
+The label will be shown on all project pages in the upper right corner.
+
+![classification label on project page](img/classification_label_on_project_page.png)
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
+
+[omnibus-ssl-docs]: https://docs.gitlab.com/omnibus/settings/ssl.html
+[omnibus-log-docs]: https://docs.gitlab.com/omnibus/settings/logs.html
diff --git a/doc/user/admin_area/settings/img/additional_minutes.png b/doc/user/admin_area/settings/img/additional_minutes.png
new file mode 100644
index 00000000000..d148ed79b92
--- /dev/null
+++ b/doc/user/admin_area/settings/img/additional_minutes.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/admin_area_default_artifacts_expiration.png b/doc/user/admin_area/settings/img/admin_area_default_artifacts_expiration.png
deleted file mode 100644
index 723be23e77b..00000000000
--- a/doc/user/admin_area/settings/img/admin_area_default_artifacts_expiration.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/settings/img/admin_area_maximum_artifacts_size.png b/doc/user/admin_area/settings/img/admin_area_maximum_artifacts_size.png
deleted file mode 100644
index 3f827f1f7a3..00000000000
--- a/doc/user/admin_area/settings/img/admin_area_maximum_artifacts_size.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/settings/img/admin_project_quota_view.png b/doc/user/admin_area/settings/img/admin_project_quota_view.png
new file mode 100644
index 00000000000..8320be860da
--- /dev/null
+++ b/doc/user/admin_area/settings/img/admin_project_quota_view.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/buy_btn.png b/doc/user/admin_area/settings/img/buy_btn.png
new file mode 100644
index 00000000000..0cc88b8a48f
--- /dev/null
+++ b/doc/user/admin_area/settings/img/buy_btn.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/buy_minutes_card.png b/doc/user/admin_area/settings/img/buy_minutes_card.png
new file mode 100644
index 00000000000..cf4ad34ead7
--- /dev/null
+++ b/doc/user/admin_area/settings/img/buy_minutes_card.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/classification_label_on_project_page.png b/doc/user/admin_area/settings/img/classification_label_on_project_page.png
new file mode 100644
index 00000000000..4aedb332cec
--- /dev/null
+++ b/doc/user/admin_area/settings/img/classification_label_on_project_page.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/email_settings.png b/doc/user/admin_area/settings/img/email_settings.png
new file mode 100644
index 00000000000..ed0a80d10ce
--- /dev/null
+++ b/doc/user/admin_area/settings/img/email_settings.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/external_authorization_service_settings.png b/doc/user/admin_area/settings/img/external_authorization_service_settings.png
new file mode 100644
index 00000000000..9b8658fd1a1
--- /dev/null
+++ b/doc/user/admin_area/settings/img/external_authorization_service_settings.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/file_template_admin_area.png b/doc/user/admin_area/settings/img/file_template_admin_area.png
new file mode 100644
index 00000000000..269d997e1d9
--- /dev/null
+++ b/doc/user/admin_area/settings/img/file_template_admin_area.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/file_template_user_dropdown.png b/doc/user/admin_area/settings/img/file_template_user_dropdown.png
new file mode 100644
index 00000000000..8c9eb49f6c9
--- /dev/null
+++ b/doc/user/admin_area/settings/img/file_template_user_dropdown.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/group_pipelines_quota.png b/doc/user/admin_area/settings/img/group_pipelines_quota.png
new file mode 100644
index 00000000000..d94b609ad6f
--- /dev/null
+++ b/doc/user/admin_area/settings/img/group_pipelines_quota.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/mirror_settings.png b/doc/user/admin_area/settings/img/mirror_settings.png
new file mode 100644
index 00000000000..090db6808a7
--- /dev/null
+++ b/doc/user/admin_area/settings/img/mirror_settings.png
Binary files differ
diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md
index 8358fe64f18..eed087ae52b 100644
--- a/doc/user/admin_area/settings/index.md
+++ b/doc/user/admin_area/settings/index.md
@@ -1,11 +1,16 @@
-# Admin area settings **[CORE ONLY]**
+---
+type: index
+---
-In the admin area settings, you can find various options for your GitLab
+# Admin Area settings **[CORE ONLY]**
+
+In the Admin Area **Settings** page, you can find various options for your GitLab
instance like sign-up restrictions, account limits and quota, metrics, etc.
-Navigate to it by going to **Admin area > Settings**. Some of the settings
+Navigate to it by going to **Admin Area > Settings**. Some of the settings
include:
+- [Account and limit settings](account_and_limit_settings.md) **[STARTER]**
- [Continuous Integration and Deployment](continuous_integration.md)
- [Email](email.md)
- [Sign up restrictions](sign_up_restrictions.md)
@@ -13,6 +18,7 @@ include:
- [Third party offers](third_party_offers.md)
- [Usage statistics](usage_statistics.md)
- [Visibility and access controls](visibility_and_access_controls.md)
+- [Custom templates repository](instance_template_repository.md) **[PREMIUM]**
NOTE: **Note:**
You can change the [first day of the week](../../profile/preferences.md) for the entire GitLab instance
@@ -20,7 +26,7 @@ in the **Localization** section of **Admin area > Settings > Preferences**.
## GitLab.com admin area settings
-Most of the settings under the admin area change the behavior of the whole
+Most of the settings under the Admin Area change the behavior of the whole
GitLab instance. For GitLab.com, the admin settings are available only for the
GitLab.com administrators, and the parameters can be found on the
[GitLab.com settings](../../gitlab_com/index.md) documentation.
diff --git a/doc/user/admin_area/settings/instance_template_repository.md b/doc/user/admin_area/settings/instance_template_repository.md
new file mode 100644
index 00000000000..91286a67c31
--- /dev/null
+++ b/doc/user/admin_area/settings/instance_template_repository.md
@@ -0,0 +1,79 @@
+---
+type: reference
+---
+
+# Instance template repository **[PREMIUM ONLY]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5986) in
+> [GitLab Premium](https://about.gitlab.com/pricing) 11.3.
+
+## Overview
+
+In hosted systems, enterprises often have a need to share their own templates
+across teams. This feature allows an administrator to pick a project to be the
+instance-wide collection of file templates. These templates are then exposed to
+all users [via the web editor](../../project/repository/web_editor.md#template-dropdowns)
+while the project remains secure.
+
+## Configuration
+
+As an administrator, navigate to **Admin area > Settings > Templates** and
+select the project to serve as the custom template repository.
+
+![File templates in the admin area](img/file_template_admin_area.png)
+
+Once a project has been selected, you can add custom templates to the repository,
+and they will appear in the appropriate places in the
+[frontend](../../project/repository/web_editor.md#template-dropdowns) and
+[API](../../../api/settings.md).
+
+Templates must be added to a specific subdirectory in the repository,
+corresponding to the kind of template. The following types of custom templates
+are supported:
+
+| Type | Directory | Extension |
+| :---------------: | :-----------: | :-----------: |
+| `Dockerfile` | `Dockerfile` | `.dockerfile` |
+| `.gitignore` | `gitignore` | `.gitignore` |
+| `.gitlab-ci.yml` | `gitlab-ci` | `.yml` |
+| `LICENSE` | `LICENSE` | `.txt` |
+
+Each template must go in its respective subdirectory, have the correct
+extension and not be empty. So, the hierarchy should look like this:
+
+```text
+|-- README.md
+|-- Dockerfile
+ |-- custom_dockerfile.dockerfile
+ |-- another_dockerfile.dockerfile
+|-- gitignore
+ |-- custom_gitignore.gitignore
+ |-- another_gitignore.gitignore
+|-- gitlab-ci
+ |-- custom_gitlab-ci.yml
+ |-- another_gitlab-ci.yml
+|-- LICENSE
+ |-- custom_license.txt
+ |-- another_license.txt
+```
+
+Once this is established, the list of custom templates will be included when
+creating a new file and the template type is selected. These will appear at the
+top of the list.
+
+![Custom template dropdown menu](img/file_template_user_dropdown.png)
+
+If this feature is disabled or no templates are present, there will be
+no "Custom" section in the selection dropdown.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/admin_area/settings/sign_up_restrictions.md b/doc/user/admin_area/settings/sign_up_restrictions.md
index d3ecfd42903..cebf36c7ec1 100644
--- a/doc/user/admin_area/settings/sign_up_restrictions.md
+++ b/doc/user/admin_area/settings/sign_up_restrictions.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# Sign-up restrictions
You can block email addresses of specific domains, or whitelist only some
@@ -37,5 +41,17 @@ semicolon, comma, or a new line.
![Domain Blacklist](img/domain_blacklist.png)
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
+
[ce-5259]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5259
[ce-598]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/598
diff --git a/doc/user/admin_area/settings/terms.md b/doc/user/admin_area/settings/terms.md
index e2290bf0598..a5f8d05f662 100644
--- a/doc/user/admin_area/settings/terms.md
+++ b/doc/user/admin_area/settings/terms.md
@@ -1,29 +1,35 @@
+---
+type: reference
+---
+
# Enforce accepting Terms of Service
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18570)
> in [GitLab Core](https://about.gitlab.com/pricing/) 10.8
+An admin can enforce acceptance of a terms of service and privacy policy. When this option is enabled, new and existing users must accept the terms.
+
## Configuration
-When it is required for all users of the GitLab instance to accept the
-Terms of Service, this can be configured by an admin on the settings
-page:
+To enforce acceptance of a Terms of Service and Privacy Policy:
-![Enable enforcing Terms of Service](img/enforce_terms.png).
+1. Log in to the GitLab instance as an admin user.
+1. Go to **Admin Area > Settings > General**.
+1. Expand the **Terms of Service and Privacy Policy** section.
+1. Check the **Require all users to accept Terms of Service and Privacy Policy when they access
+GitLab.** checkbox.
+1. Input the text of the **Terms of Service and Privacy Policy**. Markdown formatting can be used in this input box.
+1. Click **Save changes**.
+1. When you are presented with the **Terms of Service** statement, click **Accept terms**.
-The terms itself can be entered using Markdown. For each update to the
-terms, a new version is stored. When a user accepts or declines the
-terms, GitLab will keep track of which version they accepted or
-declined.
+![Enable enforcing Terms of Service](img/enforce_terms.png).
-When an admin enables this feature, they will automattically be
-directed to the page to accept the terms themselves. After they
-accept, they will be directed back to the settings page.
+For each update to the terms, a new version is stored. When a user accepts or declines the terms,
+GitLab will record which version they accepted or declined.
-## New registrations
+## New users
-When this feature is enabled, a checkbox will be available in the
-sign-up form.
+When this feature is enabled, a checkbox is added to the sign-up form.
![Sign up form](img/sign_up_terms.png)
@@ -49,3 +55,15 @@ If the user was already logged in when the feature was turned on,
they will be asked to accept the terms on their next interaction.
If a user declines the terms, they will be signed out.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/admin_area/settings/third_party_offers.md b/doc/user/admin_area/settings/third_party_offers.md
index 23311801790..d3c9cf7d8ff 100644
--- a/doc/user/admin_area/settings/third_party_offers.md
+++ b/doc/user/admin_area/settings/third_party_offers.md
@@ -1,9 +1,26 @@
+---
+type: reference
+---
+
# Third party offers
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20379)
> in [GitLab Core](https://about.gitlab.com/pricing/) 11.1
-Within GitLab, we inform users of available third-party offers they might find valuable in order to enhance the development of their projects.
-An example is the Google Cloud Platform free credit for using [Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine/).
+Within GitLab, we inform users of available third-party offers they might find valuable in order
+to enhance the development of their projects. An example is the Google Cloud Platform free credit
+for using [Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine/).
+
+The display of third-party offers can be toggled in the **Admin Area > Settings** page.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
-The display of third-party offers can be toggled in the Admin area on the Settings page.
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md
index e165a120162..652d6ad2cdd 100644
--- a/doc/user/admin_area/settings/usage_statistics.md
+++ b/doc/user/admin_area/settings/usage_statistics.md
@@ -1,10 +1,14 @@
+---
+type: reference
+---
+
# Usage statistics
GitLab Inc. will periodically collect information about your instance in order
to perform various actions.
All statistics are opt-out, you can enable/disable them from the admin panel
-under **Admin area > Settings > Usage statistics**.
+under **Admin area > Settings > Metrics and profiling > Usage statistics**.
## Version check **[CORE ONLY]**
@@ -48,6 +52,8 @@ You can view the exact JSON payload in the administration panel. To view the pay
1. Expand **Settings** in the left sidebar and click on **Metrics and profiling**.
1. Expand **Usage statistics** and click on the **Preview payload** button.
+You can see how [the usage ping data maps to different stages of the product](https://gitlab.com/gitlab-data/analytics/blob/master/transform/snowflake-dbt/data/ping_metrics_to_stage_mapping_data.csv).
+
### Deactivate the usage ping
The usage ping is opt-out. If you want to deactivate this feature, go to
@@ -81,6 +87,18 @@ of your instance to your users.
This can be restricted to admins by selecting "Only admins" in the Instance
Statistics visibility section under **Admin area > Settings > Usage statistics**.
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
+
[ee-557]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/557
[ee-735]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/735
[ce-23361]: https://gitlab.com/gitlab-org/gitlab-ce/issues/23361
diff --git a/doc/user/admin_area/settings/visibility_and_access_controls.md b/doc/user/admin_area/settings/visibility_and_access_controls.md
index 6a1e8004f87..a1229484388 100644
--- a/doc/user/admin_area/settings/visibility_and_access_controls.md
+++ b/doc/user/admin_area/settings/visibility_and_access_controls.md
@@ -1,8 +1,25 @@
+---
+type: reference
+---
+
# Visibility and access controls
+GitLab allows admins to:
+
+- Control access and visibility to GitLab resources including branches and projects.
+- Select from which hosting sites code can be imported into GitLab.
+- Select the protocols permitted to access GitLab.
+- Enable or disable repository mirroring.
+
+To access the visibility and access control options:
+
+1. Log in to GitLab as an admin.
+1. Go to **Admin Area > Settings > General**.
+1. Expand the **Visibility and access controls** section.
+
## Import sources
-Choose from which hosting sites the users can
+Choose from which hosting sites users can
[import their projects](../../project/import/index.md).
![import sources](img/import_sources.png)
@@ -11,12 +28,10 @@ Choose from which hosting sites the users can
> [Introduced][ce-4696] in GitLab 8.10.
-With GitLab's Access restrictions you can choose which Git access protocols you
-want your users to use to communicate with GitLab. This feature can be enabled
-via the `Application Settings` in the Admin interface.
+With GitLab's access restrictions, you can select with which protocols users can communicate with
+GitLab.
-The setting is called `Enabled Git access protocols`, and it gives you the option
-to choose between:
+From the **Enabled Git access protocols** dropdown, select one of the following:
- Both SSH and HTTP(S)
- Only SSH
@@ -24,10 +39,9 @@ to choose between:
![Settings Overview](img/access_restrictions.png)
-When both SSH and HTTP(S) are enabled, GitLab will behave as usual, it will give
-your users the option to choose which protocol they would like to use.
+When both SSH and HTTP(S) are enabled, your users can choose either protocol.
-When you choose to allow only one of the protocols, a couple of things will happen:
+When only one protocol is enabled:
- The project page will only show the allowed protocol's URL, with no option to
change it.
@@ -49,5 +63,27 @@ block access to the server itself. The ports used for the protocol, be it SSH or
HTTP, will still be accessible. What GitLab does is restrict access on the
application level.
+## Allow mirrors to be set up for projects
+
+> [Introduced][ee-3586] in GitLab 10.3.
+
+This option is enabled by default. By disabling it, both pull and push mirroring will no longer
+work in every repository and can only be re-enabled by an admin on a per-project basis.
+
+![Mirror settings](img/mirror_settings.png)
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
+
[ce-4696]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4696
[ce-18021]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18021
+[ee-3586]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3586
diff --git a/doc/user/application_security/container_scanning/img/container_scanning.png b/doc/user/application_security/container_scanning/img/container_scanning.png
new file mode 100644
index 00000000000..e47f62acd9d
--- /dev/null
+++ b/doc/user/application_security/container_scanning/img/container_scanning.png
Binary files differ
diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md
new file mode 100644
index 00000000000..a24374dff1d
--- /dev/null
+++ b/doc/user/application_security/container_scanning/index.md
@@ -0,0 +1,204 @@
+# Container Scanning **[ULTIMATE]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3672)
+in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4.
+
+## Overview
+
+If you are using [GitLab CI/CD](../../../ci/README.md), you can check your Docker
+images (or more precisely the containers) for known vulnerabilities by using
+[Clair](https://github.com/coreos/clair) and [clair-scanner](https://github.com/arminc/clair-scanner),
+two open source tools for Vulnerability Static Analysis for containers.
+
+You can take advantage of Container Scanning by either [including the CI job](#including-the-provided-template) in
+your existing `.gitlab-ci.yml` file or by implicitly using
+[Auto Container Scanning](../../../topics/autodevops/index.md#auto-container-scanning-ultimate)
+that is provided by [Auto DevOps](../../../topics/autodevops/index.md).
+
+GitLab checks the Container Scanning report, compares the found vulnerabilities
+between the source and target branches, and shows the information right on the
+merge request.
+
+![Container Scanning Widget](img/container_scanning.png)
+
+## Use cases
+
+If you distribute your application with Docker, then there's a great chance
+that your image is based on other Docker images that may in turn contain some
+known vulnerabilities that could be exploited.
+
+Having an extra job in your pipeline that checks for those vulnerabilities,
+and the fact that they are displayed inside a merge request, makes it very easy
+to perform audits for your Docker-based apps.
+
+## Requirements
+
+To enable Container Scanning in your pipeline, you need:
+
+- A GitLab Runner with the
+ [`docker`](https://docs.gitlab.com/runner/executors/docker.html#use-docker-in-docker-with-privileged-mode) or
+ [`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html#running-privileged-containers-for-the-runners)
+ executor running in privileged mode. If you're using the shared Runners on GitLab.com,
+ this is enabled by default.
+- To [build and push](../../../ci/docker/using_docker_build.md#container-registry-examples)
+ your Docker image to your project's [Container Registry](../../project/container_registry.md).
+ The name of the Docker image should match the following scheme:
+
+ ```
+ $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA
+ ```
+
+ The variables above can be found in the
+ [predefined environment variables](../../../ci/variables/predefined_variables.md)
+ document.
+
+## Configuring Container Scanning
+
+To enable Container Scanning in your project, define a job in your
+`.gitlab-ci.yml` file that generates the
+[Container Scanning report artifact](../../../ci/yaml/README.md#artifactsreportscontainer_scanning-ultimate).
+
+This can be done in two ways:
+
+- For GitLab 11.9 and later, including the provided
+ `Container-Scanning.gitlab-ci.yml` template (recommended).
+- Manually specifying the job definition. Not recommended unless using GitLab
+ 11.8 and earlier.
+
+### Including the provided template
+
+NOTE: **Note:**
+The CI/CD Container Scanning template is supported on GitLab 11.9 and later versions.
+For earlier versions, use the [manual job definition](#manual-job-definition-for-gitlab-115-and-later).
+
+A CI/CD [Container Scanning template](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml)
+with the default Container Scanning job definition is provided as a part of your GitLab
+installation that you can [include](../../../ci/yaml/README.md#includetemplate)
+in your `.gitlab-ci.yml` file.
+
+To enable Container Scanning using the provided template, add the following to
+your `.gitlab-ci.yml` file:
+
+```yaml
+include:
+ template: Container-Scanning.gitlab-ci.yml
+```
+
+The included template will:
+
+- Create a `container_scanning` job in your CI/CD pipeline.
+- Pull the already built Docker image from your project's
+ [Container Registry](../../project/container_registry.md) (see [requirements](#requirements))
+ and scan it for possible vulnerabilities.
+
+The report will be saved as a
+[Container Scanning report artifact](../../../ci/yaml/README.md#artifactsreportscontainer_scanning-ultimate)
+that you can later download and analyze.
+Due to implementation limitations, we always take the latest Container Scanning
+artifact available. Behind the scenes, the
+[GitLab Container Scanning analyzer](https://gitlab.com/gitlab-org/security-products/container-scanning)
+is used and runs the scans.
+
+If you want to whitelist some specific vulnerabilities, you can do so by defining
+them in a YAML file named `clair-whitelist.yml`. Read more in the
+[Clair documentation](https://github.com/arminc/clair-scanner/blob/master/README.md#example-whitelist-yaml-file).
+
+### Manual job definition for GitLab 11.5 and later
+
+CAUTION: **Caution:**
+The job definition shown below is supported on GitLab 11.5 and later versions.
+However, if you're using GitLab 11.9+, it's recommended to use
+[the provided Container Scanning template](#including-the-provided-template).
+
+For GitLab 11.5 and GitLab Runner 11.5 and later, the following `container_scanning`
+job can be added:
+
+```yaml
+container_scanning:
+ image: docker:stable
+ variables:
+ DOCKER_DRIVER: overlay2
+ ## Define two new variables based on GitLab's CI/CD predefined variables
+ ## https://docs.gitlab.com/ee/ci/variables/README.html#predefined-environment-variables
+ CI_APPLICATION_REPOSITORY: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
+ CI_APPLICATION_TAG: $CI_COMMIT_SHA
+ CLAIR_LOCAL_SCAN_VERSION: v2.0.8_fe9b059d930314b54c78f75afe265955faf4fdc1
+ allow_failure: true
+ services:
+ - docker:stable-dind
+ script:
+ - docker run -d --name db arminc/clair-db:latest
+ - docker run -p 6060:6060 --link db:postgres -d --name clair --restart on-failure arminc/clair-local-scan:${CLAIR_LOCAL_SCAN_VERSION}
+ - apk add -U wget ca-certificates
+ - docker pull ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG}
+ - wget https://github.com/arminc/clair-scanner/releases/download/v8/clair-scanner_linux_amd64
+ - mv clair-scanner_linux_amd64 clair-scanner
+ - chmod +x clair-scanner
+ - touch clair-whitelist.yml
+ - while( ! wget -q -O /dev/null http://docker:6060/v1/namespaces ) ; do sleep 1 ; done
+ - retries=0
+ - echo "Waiting for clair daemon to start"
+ - while( ! wget -T 10 -q -O /dev/null http://docker:6060/v1/namespaces ) ; do sleep 1 ; echo -n "." ; if [ $retries -eq 10 ] ; then echo " Timeout, aborting." ; exit 1 ; fi ; retries=$(($retries+1)) ; done
+ - ./clair-scanner -c http://docker:6060 --ip $(hostname -i) -r gl-container-scanning-report.json -l clair.log -w clair-whitelist.yml ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG} || true
+ artifacts:
+ reports:
+ container_scanning: gl-container-scanning-report.json
+```
+
+### Manual job definition for GitLab 11.4 and earlier (deprecated)
+
+CAUTION: **Deprecated:**
+Before GitLab 11.5, the Container Scanning job and artifact had to be named specifically
+to automatically extract report data and show it in the merge request widget.
+While these old job definitions are still maintained, they have been deprecated
+and may be removed in the next major release, GitLab 12.0. You are strongly
+advised to update your current `.gitlab-ci.yml` configuration to reflect that change.
+
+For GitLab 11.4 and earlier, the Container Scanning job should look like:
+
+```yaml
+container_scanning:
+ image: docker:stable
+ variables:
+ DOCKER_DRIVER: overlay2
+ ## Define two new variables based on GitLab's CI/CD predefined variables
+ ## https://docs.gitlab.com/ee/ci/variables/README.html#predefined-environment-variables
+ CI_APPLICATION_REPOSITORY: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
+ CI_APPLICATION_TAG: $CI_COMMIT_SHA
+ CLAIR_LOCAL_SCAN_VERSION: v2.0.8_fe9b059d930314b54c78f75afe265955faf4fdc1
+ allow_failure: true
+ services:
+ - docker:stable-dind
+ script:
+ - docker run -d --name db arminc/clair-db:latest
+ - docker run -p 6060:6060 --link db:postgres -d --name clair --restart on-failure arminc/clair-local-scan:${CLAIR_LOCAL_SCAN_VERSION}
+ - apk add -U wget ca-certificates
+ - docker pull ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG}
+ - wget https://github.com/arminc/clair-scanner/releases/download/v8/clair-scanner_linux_amd64
+ - mv clair-scanner_linux_amd64 clair-scanner
+ - chmod +x clair-scanner
+ - touch clair-whitelist.yml
+ - while( ! wget -q -O /dev/null http://docker:6060/v1/namespaces ) ; do sleep 1 ; done
+ - retries=0
+ - echo "Waiting for clair daemon to start"
+ - while( ! wget -T 10 -q -O /dev/null http://docker:6060/v1/namespaces ) ; do sleep 1 ; echo -n "." ; if [ $retries -eq 10 ] ; then echo " Timeout, aborting." ; exit 1 ; fi ; retries=$(($retries+1)) ; done
+ - ./clair-scanner -c http://docker:6060 --ip $(hostname -i) -r gl-container-scanning-report.json -l clair.log -w clair-whitelist.yml ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG} || true
+ artifacts:
+ paths: [gl-container-scanning-report.json]
+```
+
+Alternatively, the job name could be `sast:container`
+and the artifact name could be `gl-sast-container-report.json`.
+These names have been deprecated with GitLab 11.0
+and may be removed in the next major release, GitLab 12.0.
+
+## Security Dashboard
+
+The Security Dashboard is a good place to get an overview of all the security
+vulnerabilities in your groups and projects. Read more about the
+[Security Dashboard](../security_dashboard/index.md).
+
+## Interacting with the vulnerabilities
+
+Once a vulnerability is found, you can interact with it. Read more on how to
+[interact with the vulnerabilities](../index.md#interacting-with-the-vulnerabilities).
diff --git a/doc/user/application_security/dast/img/dast_all.png b/doc/user/application_security/dast/img/dast_all.png
new file mode 100644
index 00000000000..b6edc928dc3
--- /dev/null
+++ b/doc/user/application_security/dast/img/dast_all.png
Binary files differ
diff --git a/doc/user/application_security/dast/img/dast_single.png b/doc/user/application_security/dast/img/dast_single.png
new file mode 100644
index 00000000000..26ca4bde786
--- /dev/null
+++ b/doc/user/application_security/dast/img/dast_single.png
Binary files differ
diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md
new file mode 100644
index 00000000000..a722aa88f9d
--- /dev/null
+++ b/doc/user/application_security/dast/index.md
@@ -0,0 +1,261 @@
+# Dynamic Application Security Testing (DAST) **[ULTIMATE]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/4348)
+in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4.
+
+Running [static checks](../sast/index.md) on your code is the first step to detect
+vulnerabilities that can put the security of your code at risk. Yet, once
+deployed, your application is exposed to a new category of possible attacks,
+such as cross-site scripting or broken authentication flaws. This is where
+Dynamic Application Security Testing (DAST) comes into place.
+
+## Overview
+
+If you are using [GitLab CI/CD](../../../ci/README.md), you can analyze your running web application(s)
+for known vulnerabilities using Dynamic Application Security Testing (DAST).
+
+You can take advantage of DAST by either [including the CI job](#configuring-dast) in
+your existing `.gitlab-ci.yml` file or by implicitly using
+[Auto DAST](../../../topics/autodevops/index.md#auto-dast-ultimate)
+that is provided by [Auto DevOps](../../../topics/autodevops/index.md).
+
+GitLab checks the DAST report, compares the found vulnerabilities between the source and target
+branches, and shows the information right on the merge request.
+
+![DAST Widget](img/dast_all.png)
+
+By clicking on one of the detected linked vulnerabilities, you will be able to
+see the details and the URL(s) affected.
+
+![DAST Widget Clicked](img/dast_single.png)
+
+[Dynamic Application Security Testing (DAST)](https://en.wikipedia.org/wiki/Dynamic_Application_Security_Testing)
+is using the popular open source tool [OWASP ZAProxy](https://github.com/zaproxy/zaproxy)
+to perform an analysis on your running web application.
+
+By default, DAST executes [ZAP Baseline Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan) and will perform passive scanning only. It will not actively attack your application.
+
+However, DAST can be [configured](#full-scan)
+to also perform a so-called "active scan". That is, attack your application and produce a more extensive security report.
+It can be very useful combined with [Review Apps](../../../ci/review_apps/index.md).
+
+The [`dast`](https://gitlab.com/gitlab-org/security-products/dast/container_registry) Docker image in GitLab container registry is updated on a weekly basis to have all [`owasp2docker-weekly`](https://hub.docker.com/r/owasp/zap2docker-weekly/) updates in it.
+
+## Use cases
+
+It helps you automatically find security vulnerabilities in your running web
+applications while you are developing and testing your applications.
+
+## Requirements
+
+To run a DAST job, you need GitLab Runner with the
+[`docker` executor](https://docs.gitlab.com/runner/executors/docker.html).
+
+## Configuring DAST
+
+To enable DAST in your project, define a job in your `.gitlab-ci.yml` file that generates the
+[DAST report artifact](../../../ci/yaml/README.md#artifactsreportsdast-ultimate).
+
+This can be done in two ways:
+
+- For GitLab 11.9 and later, including the provided `DAST.gitlab-ci.yml` template (recommended).
+- Manually specifying the job definition. Not recommended unless using GitLab
+ 11.8 and earlier.
+
+### Including the provided template
+
+NOTE: **Note:**
+The CI/CD DAST template is supported on GitLab 11.9 and later versions.
+For earlier versions, use the [manual job definition](#manual-job-definition-for-gitlab-115-and-later).
+
+A CI/CD [DAST template](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml)
+with the default DAST job definition is provided as a part of your GitLab
+installation which you can [include](../../../ci/yaml/README.md#includetemplate)
+in your `.gitlab-ci.yml` file.
+
+To enable DAST using the provided template, add the following to your `.gitlab-ci.yml`
+file:
+
+```yaml
+include:
+ template: DAST.gitlab-ci.yml
+
+variables:
+ DAST_WEBSITE: https://example.com
+```
+
+The included template will create a `dast` job in your CI/CD pipeline and scan
+your project's source code for possible vulnerabilities.
+
+The report will be saved as a
+[DAST report artifact](../../../ci/yaml/README.md#artifactsreportsdast-ultimate)
+that you can later download and analyze. Due to implementation limitations we
+always take the latest DAST artifact available. Behind the scenes, the
+[GitLab DAST Docker image](https://gitlab.com/gitlab-org/security-products/dast)
+is used to run the tests on the specified URL and scan it for possible vulnerabilities.
+
+There are two ways to define the URL to be scanned by DAST:
+
+- Set the `DAST_WEBSITE` [variable](../../../ci/yaml/README.md#variables).
+- Add it in an `environment_url.txt` file at the root of your project.
+
+#### Authenticated scan
+
+It's also possible to authenticate the user before performing the DAST checks:
+
+```yaml
+include:
+ template: DAST.gitlab-ci.yml
+
+variables:
+ DAST_WEBSITE: https://example.com
+ DAST_AUTH_URL: https://example.com/sign-in
+ DAST_USERNAME: john.doe@example.com
+ DAST_PASSWORD: john-doe-password
+ DAST_USERNAME_FIELD: session[user] # the name of username field at the sign-in HTML form
+ DAST_PASSWORD_FIELD: session[password] # the name of password field at the sign-in HTML form
+ DAST_AUTH_EXCLUDE_URLS: http://example.com/sign-out,http://example.com/sign-out-2 # optional, URLs to skip during the authenticated scan; comma-separated, no spaces in between
+```
+
+The report will be saved as a
+[DAST report artifact](../../../ci/yaml/README.md#artifactsreportsdast-ultimate)
+that you can later download and analyze.
+Due to implementation limitations, we always take the latest DAST artifact available.
+
+#### Full scan
+
+DAST can be configured to perform [ZAP Full Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan), which
+includes both passive and active scanning against the same target website:
+
+```yaml
+include:
+ template: DAST.gitlab-ci.yml
+
+variables:
+ DAST_FULL_SCAN_ENABLED: "true"
+```
+
+#### Customizing the DAST settings
+
+The DAST settings can be changed through environment variables by using the
+[`variables`](../../../ci/yaml/README.md#variables) parameter in `.gitlab-ci.yml`.
+These variables are documented in the [DAST README](https://gitlab.com/gitlab-org/security-products/dast#settings).
+
+For example:
+
+```yaml
+include:
+ template: DAST.gitlab-ci.yml
+
+variables:
+ DAST_WEBSITE: https://example.com
+ DAST_TARGET_AVAILABILITY_TIMEOUT: 120
+```
+
+Because the template is [evaluated before](../../../ci/yaml/README.md#include) the pipeline
+configuration, the last mention of the variable will take precedence.
+
+#### Overriding the DAST template
+
+If you want to override the job definition (for example, change properties like
+`variables` or `dependencies`), you need to declare a `dast` job after the
+template inclusion and specify any additional keys under it. For example:
+
+```yaml
+include:
+ template: DAST.gitlab-ci.yml
+
+dast:
+ stage: dast # IMPORTANT: don't forget to add this
+ variables:
+ DAST_WEBSITE: https://example.com
+ CI_DEBUG_TRACE: "true"
+```
+
+As the DAST job belongs to a separate `dast` stage that runs after all
+[default stages](../../../ci/yaml/README.md#stages),
+don't forget to add `stage: dast` when you override the template job definition.
+
+### Manual job definition for GitLab 11.5 and later
+
+For GitLab 11.5 and GitLab Runner 11.5 and later, the following `dast`
+job can be added:
+
+```yaml
+dast:
+ image: registry.gitlab.com/gitlab-org/security-products/zaproxy
+ variables:
+ website: "https://example.com"
+ allow_failure: true
+ script:
+ - mkdir /zap/wrk/
+ - /zap/zap-baseline.py -J gl-dast-report.json -t $website || true
+ - cp /zap/wrk/gl-dast-report.json .
+ artifacts:
+ reports:
+ dast: gl-dast-report.json
+```
+
+Where the `website` variable holds the URL to run the tests against.
+
+For an authenticated scan, use the following definition:
+
+```yaml
+dast:
+ image: registry.gitlab.com/gitlab-org/security-products/zaproxy
+ variables:
+ website: "https://example.com"
+ login_url: "https://example.com/sign-in"
+ username: "john.doe@example.com"
+ password: "john-doe-password"
+ allow_failure: true
+ script:
+ - mkdir /zap/wrk/
+ - /zap/zap-baseline.py -J gl-dast-report.json -t $website
+ --auth-url $login_url
+ --auth-username $username
+ --auth-password $password || true
+ - cp /zap/wrk/gl-dast-report.json .
+ artifacts:
+ reports:
+ dast: gl-dast-report.json
+```
+
+See the [zaproxy documentation](https://gitlab.com/gitlab-org/security-products/zaproxy)
+to learn more about the authentication settings.
+
+### Manual job definition for GitLab 11.4 and earlier (deprecated)
+
+CAUTION: **Caution:**
+Before GitLab 11.5, DAST job and artifact had to be named specifically
+to automatically extract report data and show it in the merge request widget.
+While these old job definitions are still maintained they have been deprecated
+and may be removed in next major release, GitLab 12.0. You are strongly advised
+to update your current `.gitlab-ci.yml` configuration to reflect that change.
+
+For GitLab 11.4 and earlier, the job should look like:
+
+```yaml
+dast:
+ image: registry.gitlab.com/gitlab-org/security-products/zaproxy
+ variables:
+ website: "https://example.com"
+ allow_failure: true
+ script:
+ - mkdir /zap/wrk/
+ - /zap/zap-baseline.py -J gl-dast-report.json -t $website || true
+ - cp /zap/wrk/gl-dast-report.json .
+ artifacts:
+ paths: [gl-dast-report.json]
+```
+
+## Security Dashboard
+
+The Security Dashboard is a good place to get an overview of all the security
+vulnerabilities in your groups and projects. Read more about the
+[Security Dashboard](../security_dashboard/index.md).
+
+## Interacting with the vulnerabilities
+
+Once a vulnerability is found, you can interact with it. Read more on how to
+[interact with the vulnerabilities](../index.md#interacting-with-the-vulnerabilities).
diff --git a/doc/user/application_security/dependency_scanning/img/dependency_scanning.png b/doc/user/application_security/dependency_scanning/img/dependency_scanning.png
new file mode 100644
index 00000000000..18df356f846
--- /dev/null
+++ b/doc/user/application_security/dependency_scanning/img/dependency_scanning.png
Binary files differ
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
new file mode 100644
index 00000000000..f3bf743ad03
--- /dev/null
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -0,0 +1,395 @@
+# Dependency Scanning **[ULTIMATE]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5105)
+in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.7.
+
+## Overview
+
+If you are using [GitLab CI/CD](../../../ci/README.md), you can analyze your dependencies for known
+vulnerabilities using Dependency Scanning.
+
+You can take advantage of Dependency Scanning by either [including the CI job](#including-the-provided-template)
+in your existing `.gitlab-ci.yml` file or by implicitly using
+[Auto Dependency Scanning](../../../topics/autodevops/index.md#auto-dependency-scanning-ultimate)
+that is provided by [Auto DevOps](../../../topics/autodevops/index.md).
+
+GitLab checks the Dependency Scanning report, compares the found vulnerabilities
+between the source and target branches, and shows the information right on the
+merge request.
+
+![Dependency Scanning Widget](img/dependency_scanning.png)
+
+The results are sorted by the severity of the vulnerability:
+
+1. Critical
+1. High
+1. Medium
+1. Low
+1. Unknown
+1. Everything else
+
+## Use cases
+
+It helps to automatically find security vulnerabilities in your dependencies
+while you are developing and testing your applications. For example when your
+application is using an external (open source) library which is known to be vulnerable.
+
+## Requirements
+
+To run a Dependency Scanning job, you need GitLab Runner with the
+[`docker`](https://docs.gitlab.com/runner/executors/docker.html#use-docker-in-docker-with-privileged-mode) or
+[`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html#running-privileged-containers-for-the-runners)
+executor running in privileged mode. If you're using the shared Runners on GitLab.com,
+this is enabled by default.
+
+## Supported languages and package managers
+
+The following languages and dependency managers are supported.
+
+| Language (package managers) | Scan tool |
+|-----------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
+| JavaScript ([npm](https://www.npmjs.com/), [yarn](https://yarnpkg.com/en/)) | [gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium/general), [Retire.js](https://retirejs.github.io/retire.js) |
+| Python ([pip](https://pip.pypa.io/en/stable/)) (only `requirements.txt` supported) | [gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium/general) |
+| Ruby ([gem](https://rubygems.org/)) | [gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium/general), [bundler-audit](https://github.com/rubysec/bundler-audit) |
+| Java ([Maven](https://maven.apache.org/)) | [gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium/general) |
+| PHP ([Composer](https://getcomposer.org/)) | [gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium/general) |
+
+Some scanners require to send a list of project dependencies to GitLab's central
+servers to check for vulnerabilities. To learn more about this or to disable it,
+refer to the [GitLab Dependency Scanning tool documentation](https://gitlab.com/gitlab-org/security-products/dependency-scanning#remote-checks).
+
+## Configuring Dependency Scanning
+
+To enable Dependency Scanning in your project, define a job in your `.gitlab-ci.yml`
+file that generates the
+[Dependency Scanning report artifact](../../../ci/yaml/README.md#artifactsreportsdependency_scanning-ultimate).
+
+This can be done in two ways:
+
+- For GitLab 11.9 and later, including the provided `Dependency-Scanning.gitlab-ci.yml` template (recommended).
+- Manually specifying the job definition. Not recommended unless using GitLab
+ 11.8 and earlier.
+
+### Including the provided template
+
+NOTE: **Note:**
+The CI/CD Dependency Scanning template is supported on GitLab 11.9 and later versions.
+For earlier versions, use the [manual job definition](#manual-job-definition-for-gitlab-115-and-later).
+
+A CI/CD [Dependency Scanning template](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml)
+with the default Dependency Scanning job definition is provided as a part of your GitLab
+installation which you can [include](../../../ci/yaml/README.md#includetemplate)
+in your `.gitlab-ci.yml` file.
+
+To enable Dependency Scanning using the provided template, add the following to
+your `.gitlab-ci.yml` file:
+
+```yaml
+include:
+ template: Dependency-Scanning.gitlab-ci.yml
+```
+
+The included template will create a `dependency_scanning` job in your CI/CD
+pipeline and scan your project's source code for possible vulnerabilities.
+
+The report will be saved as a
+[Dependency Scanning report artifact](../../../ci/yaml/README.md#artifactsreportsdependency_scanning-ultimate)
+that you can later download and analyze. Due to implementation limitations, we
+always take the latest Dependency Scanning artifact available.
+
+Some security scanners require to send a list of project dependencies to GitLab
+central servers to check for vulnerabilities. To learn more about this or to
+disable it, check the
+[GitLab Dependency Scanning tool documentation](https://gitlab.com/gitlab-org/security-products/dependency-scanning#remote-checks).
+
+#### Customizing the Dependency Scanning settings
+
+The Dependency Scanning settings can be changed through environment variables by using the
+[`variables`](../../../ci/yaml/README.md#variables) parameter in `.gitlab-ci.yml`.
+These variables are documented in the
+[Dependency Scanning tool documentation](https://gitlab.com/gitlab-org/security-products/dependency-scanning#settings).
+
+For example:
+
+```yaml
+include:
+ template: Dependency-Scanning.gitlab-ci.yml
+
+variables:
+ DEP_SCAN_DISABLE_REMOTE_CHECKS: true
+```
+
+Because template is [evaluated before](../../../ci/yaml/README.md#include) the pipeline
+configuration, the last mention of the variable will take precedence.
+
+#### Overriding the Dependency Scanning template
+
+If you want to override the job definition (for example, change properties like
+`variables` or `dependencies`), you need to declare a `dependency_scanning` job
+after the template inclusion and specify any additional keys under it. For example:
+
+```yaml
+include:
+ template: Dependency-Scanning.gitlab-ci.yml
+
+dependency_scanning:
+ variables:
+ CI_DEBUG_TRACE: "true"
+```
+
+### Manual job definition for GitLab 11.5 and later
+
+For GitLab 11.5 and GitLab Runner 11.5 and later, the following `dependency_scanning`
+job can be added:
+
+```yaml
+dependency_scanning:
+ image: docker:stable
+ variables:
+ DOCKER_DRIVER: overlay2
+ allow_failure: true
+ services:
+ - docker:stable-dind
+ script:
+ - export DS_VERSION=${SP_VERSION:-$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')}
+ - |
+ docker run \
+ --env DS_ANALYZER_IMAGES \
+ --env DS_ANALYZER_IMAGE_PREFIX \
+ --env DS_ANALYZER_IMAGE_TAG \
+ --env DS_DEFAULT_ANALYZERS \
+ --env DEP_SCAN_DISABLE_REMOTE_CHECKS \
+ --env DS_DOCKER_CLIENT_NEGOTIATION_TIMEOUT \
+ --env DS_PULL_ANALYZER_IMAGE_TIMEOUT \
+ --env DS_RUN_ANALYZER_TIMEOUT \
+ --volume "$PWD:/code" \
+ --volume /var/run/docker.sock:/var/run/docker.sock \
+ "registry.gitlab.com/gitlab-org/security-products/dependency-scanning:$DS_VERSION" /code
+ dependencies: []
+ artifacts:
+ reports:
+ dependency_scanning: gl-dependency-scanning-report.json
+```
+
+You can supply many other [settings variables](https://gitlab.com/gitlab-org/security-products/dependency-scanning#settings)
+via `docker run --env` to customize your job execution.
+
+### Manual job definition for GitLab 11.4 and earlier (deprecated)
+
+CAUTION: **Caution:**
+Before GitLab 11.5, the Dependency Scanning job and artifact had to be named specifically
+to automatically extract the report data and show it in the merge request widget.
+While these old job definitions are still maintained, they have been deprecated
+and may be removed in the next major release, GitLab 12.0. You are strongly advised
+to update your current `.gitlab-ci.yml` configuration to reflect that change.
+
+For GitLab 11.4 and earlier, the job should look like:
+
+```yaml
+dependency_scanning:
+ image: docker:stable
+ variables:
+ DOCKER_DRIVER: overlay2
+ allow_failure: true
+ services:
+ - docker:stable-dind
+ script:
+ - export DS_VERSION=${SP_VERSION:-$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')}
+ - |
+ docker run \
+ --env DS_ANALYZER_IMAGES \
+ --env DS_ANALYZER_IMAGE_PREFIX \
+ --env DS_ANALYZER_IMAGE_TAG \
+ --env DS_DEFAULT_ANALYZERS \
+ --env DS_EXCLUDED_PATHS \
+ --env DEP_SCAN_DISABLE_REMOTE_CHECKS \
+ --env DS_DOCKER_CLIENT_NEGOTIATION_TIMEOUT \
+ --env DS_PULL_ANALYZER_IMAGE_TIMEOUT \
+ --env DS_RUN_ANALYZER_TIMEOUT \
+ --volume "$PWD:/code" \
+ --volume /var/run/docker.sock:/var/run/docker.sock \
+ "registry.gitlab.com/gitlab-org/security-products/dependency-scanning:$DS_VERSION" /code
+ artifacts:
+ paths: [gl-dependency-scanning-report.json]
+```
+
+## Reports JSON format
+
+CAUTION: **Caution:**
+The JSON report artifacts are not a public API of Dependency Scanning and their format may change in future.
+
+The Dependency Scanning tool emits a JSON report file. Here is an example of a structure for a report will all important parts of
+it highlighted:
+
+```json-doc
+{
+ "version": "2.0",
+ "vulnerabilities": [
+ {
+ "category": "dependency_scanning",
+ "name": "Regular Expression Denial of Service",
+ "message": "Regular Expression Denial of Service in debug",
+ "description": "The debug module is vulnerable to regular expression denial of service when untrusted user input is passed into the `o` formatter. It takes around 50k characters to block for 2 seconds making this a low severity issue.",
+ "cve": "yarn.lock:debug:gemnasium:37283ed4-0380-40d7-ada7-2d994afcc62a",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest versions.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "yarn.lock",
+ "dependency": {
+ "package": {
+ "name": "debug"
+ },
+ "version": "1.0.5"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-37283ed4-0380-40d7-ada7-2d994afcc62a",
+ "value": "37283ed4-0380-40d7-ada7-2d994afcc62a",
+ "url": "https://deps.sec.gitlab.com/packages/npm/debug/versions/1.0.5/advisories"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://nodesecurity.io/advisories/534"
+ },
+ {
+ "url": "https://github.com/visionmedia/debug/issues/501"
+ },
+ {
+ "url": "https://github.com/visionmedia/debug/pull/504"
+ }
+ ]
+ },
+ {
+ "category": "dependency_scanning",
+ "name": "Authentication bypass via incorrect DOM traversal and canonicalization",
+ "message": "Authentication bypass via incorrect DOM traversal and canonicalization in saml2-js",
+ "description": "Some XML DOM traversal and canonicalization APIs may be inconsistent in handling of comments within XML nodes. Incorrect use of these APIs by some SAML libraries results in incorrect parsing of the inner text of XML nodes such that any inner text after the comment is lost prior to cryptographically signing the SAML message. Text after the comment therefore has no impact on the signature on the SAML message.\r\n\r\nA remote attacker can modify SAML content for a SAML service provider without invalidating the cryptographic signature, which may allow attackers to bypass primary authentication for the affected SAML service provider.",
+ "cve": "yarn.lock:saml2-js:gemnasium:9952e574-7b5b-46fa-a270-aeb694198a98",
+ "severity": "Unknown",
+ "solution": "Upgrade to fixed version.\r\n",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "yarn.lock",
+ "dependency": {
+ "package": {
+ "name": "saml2-js"
+ },
+ "version": "1.5.0"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-9952e574-7b5b-46fa-a270-aeb694198a98",
+ "value": "9952e574-7b5b-46fa-a270-aeb694198a98",
+ "url": "https://deps.sec.gitlab.com/packages/npm/saml2-js/versions/1.5.0/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2017-11429",
+ "value": "CVE-2017-11429",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-11429"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://github.com/Clever/saml2/commit/3546cb61fd541f219abda364c5b919633609ef3d#diff-af730f9f738de1c9ad87596df3f6de84R279"
+ },
+ {
+ "url": "https://github.com/Clever/saml2/issues/127"
+ },
+ {
+ "url": "https://www.kb.cert.org/vuls/id/475445"
+ }
+ ]
+ }
+ ],
+ "remediations": [
+ {
+ "fixes": [
+ {
+ "cve": "yarn.lock:saml2-js:gemnasium:9952e574-7b5b-46fa-a270-aeb694198a98"
+ }
+ ],
+ "summary": "Upgrade saml2-js",
+ "diff": "ZGlmZiAtLWdpdCBhL...OR0d1ZUc2THh3UT09Cg==" // some content is omitted for brevity
+ }
+ ]
+}
+```
+
+Here is the description of the report file structure nodes and their meaning. All fields are mandatory to be present in
+the report JSON unless stated otherwise. Presence of optional fields depends on the underlying analyzers being used.
+
+| Report JSON node | Function |
+|------------------------------------------------------|----------|
+| `version` | Report syntax version used to generate this JSON. |
+| `vulnerabilities` | Array of vulnerability objects. |
+| `vulnerabilities[].category` | Where this vulnerability belongs (SAST, Dependency Scanning etc.). For Dependency Scanning, it will always be `dependency_scanning`. |
+| `vulnerabilities[].name` | Name of the vulnerability, this must not include the occurrence's specific information. Optional. |
+| `vulnerabilities[].message` | A short text that describes the vulnerability, it may include occurrence's specific information. Optional. |
+| `vulnerabilities[].description` | A long text that describes the vulnerability. Optional. |
+| `vulnerabilities[].cve` | A fingerprint string value that represents a concrete occurrence of the vulnerability. It's used to determine whether two vulnerability occurrences are same or different. May not be 100% accurate. **This is NOT a [CVE](https://cve.mitre.org/)**. |
+| `vulnerabilities[].severity` | How much the vulnerability impacts the software. Possible values: `Undefined` (an analyzer has not provided this info), `Info`, `Unknown`, `Low`, `Medium`, `High`, `Critical`. |
+| `vulnerabilities[].confidence` | How reliable the vulnerability's assessment is. Possible values: `Undefined` (an analyzer has not provided this info), `Ignore`, `Unknown`, `Experimental`, `Low`, `Medium`, `High`, `Confirmed`. |
+| `vulnerabilities[].solution` | Explanation of how to fix the vulnerability. Optional. |
+| `vulnerabilities[].scanner` | A node that describes the analyzer used find this vulnerability. |
+| `vulnerabilities[].scanner.id` | Id of the scanner as a snake_case string. |
+| `vulnerabilities[].scanner.name` | Name of the scanner, for display purposes. |
+| `vulnerabilities[].location` | A node that tells which class and/or method is affected by the vulnerability. |
+| `vulnerabilities[].location.file` | Path to the dependencies file (e.g., `yarn.lock`). Optional. |
+| `vulnerabilities[].location.dependency` | A node that describes the dependency of a project where the vulnerability is located. |
+| `vulnerabilities[].location.dependency.package` | A node that provides the information on the package where the vulnerability is located. |
+| `vulnerabilities[].location.dependency.package.name` | Name of the package where the vulnerability is located. Optional. |
+| `vulnerabilities[].location.dependency.version` | Version of the vulnerable package. Optional. |
+| `vulnerabilities[].identifiers` | An ordered array of references that identify a vulnerability on internal or external DBs. |
+| `vulnerabilities[].identifiers[].type` | Type of the identifier. Possible values: common identifier types (among `cve`, `cwe`, `osvdb`, and `usn`) or analyzer-dependent ones (e.g. `gemnasium` for [Gemnasium](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/)). |
+| `vulnerabilities[].identifiers[].name` | Name of the identifier for display purpose. |
+| `vulnerabilities[].identifiers[].value` | Value of the identifier for matching purpose. |
+| `vulnerabilities[].identifiers[].url` | URL to identifier's documentation. Optional. |
+| `vulnerabilities[].links` | An array of references to external documentation pieces or articles that describe the vulnerability further. Optional. |
+| `vulnerabilities[].links[].name` | Name of the vulnerability details link. Optional. |
+| `vulnerabilities[].links[].url` | URL of the vulnerability details document. Optional. |
+| `remediations` | An array of objects containing information on cured vulnerabilities along with patch diffs to apply. |
+| `remediations[].fixes` | An array of strings that represent references to vulnerabilities fixed by this particular remediation. |
+| `remediations[].fixes[].cve` | A string value that describes a fixed vulnerability occurrence in the same format as `vulnerabilities[].cve`. |
+| `remediations[].summary` | Overview of how the vulnerabilities have been fixed. |
+| `remediations[].diff` | base64-encoded remediation code diff, compatible with [`git apply`](https://git-scm.com/docs/git-format-patch#_discussion). |
+
+## Security Dashboard
+
+The Security Dashboard is a good place to get an overview of all the security
+vulnerabilities in your groups and projects. Read more about the
+[Security Dashboard](../security_dashboard/index.md).
+
+## Interacting with the vulnerabilities
+
+Once a vulnerability is found, you can interact with it. Read more on how to
+[interact with the vulnerabilities](../index.md#interacting-with-the-vulnerabilities).
+
+## Dependency List
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/10075)
+in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0.
+
+An additional benefit of Dependency Scanning is the ability to get a list of your project's dependencies with their versions.
+
+This list can be generated only for [supported languages and package managers](#supported-languages-and-package-managers).
+
+To see the generated dependency list, navigate to the Dependency List page under your project's left sidebar menu **Project > Dependency List**.
+
+## Contributing to the vulnerability database
+
+You can search the [gemnasium-db](https://gitlab.com/gitlab-org/security-products/gemnasium-db) project
+to find a vulnerability in the Gemnasium database.
+You can also [submit new vulnerabilities](https://gitlab.com/gitlab-org/security-products/gemnasium-db/blob/master/CONTRIBUTING.md). \ No newline at end of file
diff --git a/doc/user/application_security/img/create_issue_with_list_hover.png b/doc/user/application_security/img/create_issue_with_list_hover.png
new file mode 100644
index 00000000000..7d70e8299f5
--- /dev/null
+++ b/doc/user/application_security/img/create_issue_with_list_hover.png
Binary files differ
diff --git a/doc/user/application_security/img/dismissed_info.png b/doc/user/application_security/img/dismissed_info.png
new file mode 100644
index 00000000000..64d5cf26ed2
--- /dev/null
+++ b/doc/user/application_security/img/dismissed_info.png
Binary files differ
diff --git a/doc/user/application_security/img/interactive_reports.png b/doc/user/application_security/img/interactive_reports.png
new file mode 100644
index 00000000000..373b39104db
--- /dev/null
+++ b/doc/user/application_security/img/interactive_reports.png
Binary files differ
diff --git a/doc/user/application_security/img/issue.png b/doc/user/application_security/img/issue.png
new file mode 100644
index 00000000000..6467201df3f
--- /dev/null
+++ b/doc/user/application_security/img/issue.png
Binary files differ
diff --git a/doc/user/application_security/img/vulnerability_solution.png b/doc/user/application_security/img/vulnerability_solution.png
new file mode 100644
index 00000000000..7443b9b6eea
--- /dev/null
+++ b/doc/user/application_security/img/vulnerability_solution.png
Binary files differ
diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md
new file mode 100644
index 00000000000..679847b76d7
--- /dev/null
+++ b/doc/user/application_security/index.md
@@ -0,0 +1,114 @@
+# GitLab Secure **[ULTIMATE]**
+
+Check your application for security vulnerabilities that may lead to unauthorized access,
+data leaks, and denial of services. GitLab will perform static and dynamic tests on the
+code of your application, looking for known flaws and report them in the merge request
+so you can fix them before merging. Security teams can use dashboards to get a
+high-level view on projects and groups, and start remediation processes when needed.
+
+## Security scanning tools
+
+GitLab can scan and report any vulnerabilities found in your project.
+
+| Secure scanning tools | Description |
+|:-----------------------------------------------------------------------------|:-----------------------------------------------------------------------|
+| [Container Scanning](container_scanning/index.md) **[ULTIMATE]** | Scan Docker containers for known vulnerabilities. |
+| [Dependency Scanning](dependency_scanning/index.md) **[ULTIMATE]** | Analyze your dependencies for known vulnerabilities. |
+| [Dynamic Application Security Testing (DAST)](dast/index.md) **[ULTIMATE]** | Analyze running web applications for known vulnerabilities. |
+| [License Management](license_management/index.md) **[ULTIMATE]** | Search your project's dependencies for their licenses. |
+| [Security Dashboard](security_dashboard/index.md) **[ULTIMATE]** | View vulnerabilities in all your projects and groups. |
+| [Static Application Security Testing (SAST)](sast/index.md) **[ULTIMATE]** | Analyze source code for known vulnerabilities. |
+
+## Interacting with the vulnerabilities
+
+> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing) 10.8.
+
+CAUTION: **Warning:**
+This feature is currently [Alpha](https://about.gitlab.com/handbook/product/#alpha-beta-ga) and while you can start using it, it may receive important changes in the future.
+
+Each security vulnerability in the merge request report or the
+[Security Dashboard](security_dashboard/index.md) is actionable. Clicking on an
+entry, a detailed information will pop up with different possible options:
+
+- [Dismiss vulnerability](#dismissing-a-vulnerability): Dismissing a vulnerability
+ will place a <s>strikethrough</s> styling on it.
+- [Create issue](#creating-an-issue-for-a-vulnerability): The new issue will
+ have the title and description pre-populated with the information from the
+ vulnerability report and will be created as [confidential](../project/issues/confidential_issues.md) by default.
+- [Solution](#solutions-for-vulnerabilities): For some vulnerabilities
+ ([Dependency Scanning](dependency_scanning/index.md) and [Container Scanning](container_scanning/index.md))
+ a solution is provided for how to fix the vulnerability.
+
+![Interacting with security reports](img/interactive_reports.png)
+
+### Dismissing a vulnerability
+
+You can dismiss vulnerabilities by clicking the **Dismiss vulnerability** button.
+This will dismiss the vulnerability and re-render it to reflect its dismissed state.
+If you wish to undo this dismissal, you can click the **Undo dismiss** button.
+
+#### Adding a dismissal reason
+
+> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing) 12.0.
+
+When dismissing a vulnerability, it's often helpful to provide a reason for doing so.
+If you press the comment button next to **Dismiss vulnerability** in the modal, a text box will appear, allowing you to add a comment with your dismissal.
+This comment can not currently be edited or removed, but [future versions](https://gitlab.com/gitlab-org/gitlab-ee/issues/11721) will add this functionality.
+
+![Dismissed vulnerability comment](img/dismissed_info.png)
+
+### Creating an issue for a vulnerability
+
+You can create an issue for a vulnerability by selecting the **Create issue**
+button from within the vulnerability modal or using the action buttons to the right of
+a vulnerability row when in the group security dashboard.
+
+This will create a [confidential issue](../project/issues/confidential_issues.md)
+on the project this vulnerability came from and pre-fill it with some useful
+information taken from the vulnerability report. Once the issue is created, you
+will be redirected to it so you can edit, assign, or comment on it.
+
+Upon returning to the group security dashboard, you'll see that
+the vulnerability will now have an associated issue next to the name.
+
+![Linked issue in the group security dashboard](img/issue.png)
+
+### Solutions for vulnerabilities
+
+> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing) 11.7.
+
+CAUTION: **Warning:**
+Automatic Patch creation is only available for a subset of
+[Dependency Scanning](dependency_scanning/index.md). At the moment only Node.JS
+projects managed with yarn are supported.
+
+Some vulnerabilities can be fixed by applying the solution that GitLab
+automatically generates.
+
+#### Manually applying the suggested patch
+
+Some vulnerabilities can be fixed by applying a patch that is automatically
+generated by GitLab. To apply the fix:
+
+1. Click on the vulnerability.
+1. Download and review the patch file `remediation.patch`.
+2. Ensure your local project has the same commit checked out that was used to generate the patch.
+3. Run `git apply remediation.patch`.
+4. Verify and commit the changes to your branch.
+
+![Apply patch for dependency scanning](img/vulnerability_solution.png)
+
+#### Creating a merge request from a vulnerability
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9224) in
+ [GitLab Ultimate](https://about.gitlab.com/pricing) 11.9.
+
+In certain cases, GitLab will allow you to create a merge request that will
+automatically remediate the vulnerability. Any vulnerability that has a
+[solution](#solutions-for-vulnerabilities) can have a merge request created to
+automatically solve the issue.
+
+If this action is available there will be a **Create merge request** button in the vulnerability modal.
+Clicking on this button will create a merge request to apply the solution onto the source branch.
+
+![Create merge request from vulnerability](img/create_issue_with_list_hover.png)
diff --git a/doc/user/application_security/license_management/img/license_management.png b/doc/user/application_security/license_management/img/license_management.png
new file mode 100644
index 00000000000..cdce6b5fe38
--- /dev/null
+++ b/doc/user/application_security/license_management/img/license_management.png
Binary files differ
diff --git a/doc/user/application_security/license_management/img/license_management_decision.png b/doc/user/application_security/license_management/img/license_management_decision.png
new file mode 100644
index 00000000000..0763130c375
--- /dev/null
+++ b/doc/user/application_security/license_management/img/license_management_decision.png
Binary files differ
diff --git a/doc/user/application_security/license_management/img/license_management_pipeline_tab.png b/doc/user/application_security/license_management/img/license_management_pipeline_tab.png
new file mode 100644
index 00000000000..80ffca815b9
--- /dev/null
+++ b/doc/user/application_security/license_management/img/license_management_pipeline_tab.png
Binary files differ
diff --git a/doc/user/application_security/license_management/img/license_management_settings.png b/doc/user/application_security/license_management/img/license_management_settings.png
new file mode 100644
index 00000000000..b5490e59074
--- /dev/null
+++ b/doc/user/application_security/license_management/img/license_management_settings.png
Binary files differ
diff --git a/doc/user/application_security/license_management/index.md b/doc/user/application_security/license_management/index.md
new file mode 100644
index 00000000000..7878dc77084
--- /dev/null
+++ b/doc/user/application_security/license_management/index.md
@@ -0,0 +1,264 @@
+# License Management **[ULTIMATE]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5483)
+in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0.
+
+## Overview
+
+If you are using [GitLab CI/CD](../../../ci/README.md), you can search your project dependencies for their licenses
+using License Management.
+
+You can take advantage of License Management by either [including the job](#configuring-license-management)
+in your existing `.gitlab-ci.yml` file or by implicitly using
+[Auto License Management](../../../topics/autodevops/index.md#auto-license-management-ultimate)
+that is provided by [Auto DevOps](../../../topics/autodevops/index.md).
+
+GitLab checks the License Management report, compares the licenses between the
+source and target branches, and shows the information right on the merge request.
+Blacklisted licenses will be clearly visible with an `x` red icon next to them
+as well as new licenses which need a decision from you. In addition, you can
+[manually approve or blacklist](#project-policies-for-license-management)
+licenses in your project's settings.
+
+NOTE: **Note:**
+If the license management report doesn't have anything to compare to, no information
+will be displayed in the merge request area. That is the case when you add the
+`license_management` job in your `.gitlab-ci.yml` for the first time.
+Consecutive merge requests will have something to compare to and the license
+management report will be shown properly.
+
+![License Management Widget](img/license_management.png)
+
+If you are a project or group Maintainer, you can click on a license to be given
+the choice to approve it or blacklist it.
+
+![License approval decision](img/license_management_decision.png)
+
+## Use cases
+
+It helps you find what licenses your project uses in its dependencies, and decide for each of then
+whether to allow it or forbid it. For example, your application is using an external (open source)
+library whose license is incompatible with yours.
+
+## Supported languages and package managers
+
+The following languages and package managers are supported.
+
+| Language | Package managers |
+|------------|-------------------------------------------------------------------|
+| JavaScript | [Bower](https://bower.io/), [npm](https://www.npmjs.com/) |
+| Go | [Godep](https://github.com/tools/godep), go get |
+| Java | [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/) |
+| .NET | [Nuget](https://www.nuget.org/) |
+| Python | [pip](https://pip.pypa.io/en/stable/) |
+| Ruby | [gem](https://rubygems.org/) |
+
+## Requirements
+
+To run a License Management scanning job, you need GitLab Runner with the
+[`docker` executor](https://docs.gitlab.com/runner/executors/docker.html).
+
+## Configuring License Management
+
+To enable License Management in your project, define a job in your `.gitlab-ci.yml`
+file that generates the [License Management report artifact](../../../ci/yaml/README.md#artifactsreportslicense_management-ultimate).
+
+This can be done in two ways:
+
+- For GitLab 11.9 and later, including the provided `License-Management.gitlab-ci.yml` template (recommended).
+- Manually specifying the job definition. Not recommended unless using GitLab
+ 11.8 and earlier.
+
+### Including the provided template
+
+NOTE: **Note:**
+The CI/CD License Management template is supported on GitLab 11.9 and later versions.
+For earlier versions, use the [manual job definition](#manual-job-definition-for-gitlab-115-and-later).
+
+A CI/CD [License Management template](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/lib/gitlab/ci/templates/Security/License-Management.gitlab-ci.yml)
+with the default License Management job definition is provided as a part of your GitLab
+installation which you can [include](../../../ci/yaml/README.md#includetemplate)
+in your `.gitlab-ci.yml` file.
+
+To enable License Management using the provided template, add the following to
+your `.gitlab-ci.yml` file:
+
+```yaml
+include:
+ template: License-Management.gitlab-ci.yml
+```
+
+The included template will create a `license_management` job in your CI/CD pipeline
+and scan your dependencies to find their licenses.
+
+The report will be saved as a
+[License Management report artifact](../../../ci/yaml/README.md#artifactsreportslicense_management-ultimate)
+that you can later download and analyze. Due to implementation limitations, we
+always take the latest License Management artifact available. Behind the scenes, the
+[GitLab License Management Docker image](https://gitlab.com/gitlab-org/security-products/license-management)
+is used to detect the languages/frameworks and in turn analyzes the licenses.
+
+#### Installing custom dependencies
+
+> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.4.
+
+The `license_management` image already embeds many auto-detection scripts, languages,
+and packages. Nevertheless, it's almost impossible to cover all cases for all projects.
+That's why sometimes it's necessary to install extra packages, or to have extra steps
+in the project automated setup, like the download and installation of a certificate.
+For that, a `LICENSE_MANAGEMENT_SETUP_CMD` environment variable can be passed to the container,
+with the required commands to run before the license detection.
+
+If present, this variable will override the setup step necessary to install all the packages
+of your application (e.g.: for a project with a `Gemfile`, the setup step could be
+`bundle install`).
+
+For example:
+
+```yaml
+include:
+ template: License-Management.gitlab-ci.yml
+
+variables:
+ LICENSE_MANAGEMENT_SETUP_CMD: sh my-custom-install-script.sh
+```
+
+In this example, `my-custom-install-script.sh` is a shell script at the root
+directory of your project.
+
+#### Overriding the template
+
+If you want to override the job definition (for example, change properties like
+`variables` or `dependencies`), you need to declare a `license_management` job
+after the template inclusion and specify any additional keys under it. For example:
+
+```yaml
+include:
+ template: License-Management.gitlab-ci.yml
+
+license_management:
+ variables:
+ CI_DEBUG_TRACE: "true"
+```
+
+#### Configuring Maven projects
+
+The License Management tool provides a `MAVEN_CLI_OPTS` environment variable which can hold
+the command line arguments to pass to the `mvn install` command which is executed under the hood.
+Feel free to use it for the customization of Maven execution. For example:
+
+```yaml
+include:
+ template: License-Management.gitlab-ci.yml
+
+license_management:
+ variables:
+ MAVEN_CLI_OPTS: --debug
+```
+
+`mvn install` runs through all of the [build life cycle](http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html)
+stages prior to `install`, including `test`. Running unit tests is not directly
+necessary for the license scanning purposes and consumes time, so it's skipped
+by having the default value of `MAVEN_CLI_OPTS` as `-DskipTests`. If you want
+to supply custom `MAVEN_CLI_OPTS` and skip tests at the same time, don't forget
+to explicitly add `-DskipTests` to your options.
+If you still need to run tests during `mvn install`, add `-DskipTests=false` to
+`MAVEN_CLI_OPTS`.
+
+### Manual job definition for GitLab 11.5 and later
+
+For GitLab 11.5 and GitLab Runner 11.5 and later, the following `license_management`
+job can be added:
+
+```yaml
+license_management:
+ image:
+ name: "registry.gitlab.com/gitlab-org/security-products/license-management:$CI_SERVER_VERSION_MAJOR-$CI_SERVER_VERSION_MINOR-stable"
+ entrypoint: [""]
+ stage: test
+ allow_failure: true
+ script:
+ - /run.sh analyze .
+ artifacts:
+ reports:
+ license_management: gl-license-management-report.json
+```
+
+If you want to install custom project dependencies via the `SETUP_CMD` variable:
+
+```yaml
+license_management:
+ image:
+ name: "registry.gitlab.com/gitlab-org/security-products/license-management:$CI_SERVER_VERSION_MAJOR-$CI_SERVER_VERSION_MINOR-stable"
+ entrypoint: [""]
+ stage: test
+ variables:
+ SETUP_CMD: ./my-custom-install-script.sh
+ allow_failure: true
+ script:
+ - /run.sh analyze .
+ artifacts:
+ reports:
+ license_management: gl-license-management-report.json
+```
+
+### Manual job definition for GitLab 11.4 and earlier (deprecated)
+
+CAUTION: **Caution:**
+Before GitLab 11.5, the License Management job and artifact had to be named specifically
+to automatically extract the report data and show it in the merge request widget.
+While these old job definitions are still maintained, they have been deprecated
+and may be removed in the next major release, GitLab 12.0. You are strongly advised
+to update your current `.gitlab-ci.yml` configuration to reflect that change.
+
+For GitLab 11.4 and earlier, the job should look like:
+
+```yaml
+license_management:
+ image:
+ name: "registry.gitlab.com/gitlab-org/security-products/license-management:$CI_SERVER_VERSION_MAJOR-$CI_SERVER_VERSION_MINOR-stable"
+ entrypoint: [""]
+ stage: test
+ allow_failure: true
+ script:
+ - /run.sh analyze .
+ artifacts:
+ paths: [gl-license-management-report.json]
+```
+
+## Project policies for License Management
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5940)
+in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.4.
+
+From the project's settings:
+
+- The list of licenses and their status can be managed.
+- Licenses can be manually approved or blacklisted.
+
+To approve or blacklist a license:
+
+1. Either use the **Manage licenses** button in the merge request widget, or
+ navigate to the project's **Settings > CI/CD** and expand the
+ **License Management** section.
+1. Click the **Add a license** button.
+1. In the **License name** dropdown, either:
+ - Select one of the available licenses. You can search for licenses in the field
+ at the top of the list.
+ - Enter arbitrary text in the field at the top of the list. This will cause the text to be
+ added as a license name to the list.
+1. Select the **Approve** or **Blacklist** radio button to approve or blacklist respectively
+ the selected license.
+
+ ![License Management Settings](img/license_management_settings.png)
+
+## License Management report under pipelines
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5491)
+in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.2.
+
+From your project's left sidebar, navigate to **CI/CD > Pipelines** and click on the
+pipeline ID that has a `license_management` job to see the Licenses tab with the listed
+licenses (if any).
+
+![License Management Pipeline Tab](img/license_management_pipeline_tab.png)
diff --git a/doc/user/application_security/sast/img/sast.png b/doc/user/application_security/sast/img/sast.png
new file mode 100644
index 00000000000..2c75592c32a
--- /dev/null
+++ b/doc/user/application_security/sast/img/sast.png
Binary files differ
diff --git a/doc/user/application_security/sast/img/security_report.png b/doc/user/application_security/sast/img/security_report.png
new file mode 100644
index 00000000000..ba41b707238
--- /dev/null
+++ b/doc/user/application_security/sast/img/security_report.png
Binary files differ
diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md
new file mode 100644
index 00000000000..11361f8ad89
--- /dev/null
+++ b/doc/user/application_security/sast/index.md
@@ -0,0 +1,366 @@
+# Static Application Security Testing (SAST) **[ULTIMATE]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/3775)
+in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.3.
+
+NOTE: **4 of the top 6 attacks were application based.**
+Download our whitepaper,
+["A Seismic Shift in Application Security"](https://about.gitlab.com/resources/whitepaper-seismic-shift-application-security/)
+to learn how to protect your organization.
+
+## Overview
+
+If you are using [GitLab CI/CD](../../../ci/README.md), you can analyze your source code for known
+vulnerabilities using Static Application Security Testing (SAST).
+
+You can take advantage of SAST by either [including the CI job](#configuring-sast) in
+your existing `.gitlab-ci.yml` file or by implicitly using
+[Auto SAST](../../../topics/autodevops/index.md#auto-sast-ultimate)
+that is provided by [Auto DevOps](../../../topics/autodevops/index.md).
+
+GitLab checks the SAST report, compares the found vulnerabilities between the
+source and target branches, and shows the information right on the merge request.
+
+![SAST Widget](img/sast.png)
+
+The results are sorted by the priority of the vulnerability:
+
+1. Critical
+1. High
+1. Medium
+1. Low
+1. Unknown
+1. Everything else
+
+## Use cases
+
+- Your code has a potentially dangerous attribute in a class, or unsafe code
+ that can lead to unintended code execution.
+- Your application is vulnerable to cross-site scripting (XSS) attacks that can
+ be leveraged to unauthorized access to session data.
+
+## Requirements
+
+To run a SAST job, you need GitLab Runner with the
+[`docker`](https://docs.gitlab.com/runner/executors/docker.html#use-docker-in-docker-with-privileged-mode) or
+[`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html#running-privileged-containers-for-the-runners)
+executor running in privileged mode. If you're using the shared Runners on GitLab.com,
+this is enabled by default.
+
+## Supported languages and frameworks
+
+The following table shows which languages, package managers and frameworks are supported and which tools are used.
+
+| Language (package managers) / framework | Scan tool | Introduced in GitLab Version |
+|-----------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------|
+| .NET | [Security Code Scan](https://security-code-scan.github.io) | 11.0 |
+| Any | [Gitleaks](https://github.com/zricethezav/gitleaks) and [TruffleHog](https://github.com/dxa4481/truffleHog) | 11.9 |
+| C/C++ | [Flawfinder](https://www.dwheeler.com/flawfinder/) | 10.7 |
+| Elixir (Phoenix) | [Sobelow](https://github.com/nccgroup/sobelow) | 11.10 |
+| Go | [Gosec](https://github.com/securego/gosec) | 10.7 |
+| Groovy ([Ant](https://ant.apache.org/), [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/) and [SBT](https://www.scala-sbt.org/)) | [SpotBugs](https://spotbugs.github.io/) with the [find-sec-bugs](https://find-sec-bugs.github.io/) plugin | 11.3 (Gradle) & 11.9 (Ant, Maven, SBT) |
+| Java ([Ant](https://ant.apache.org/), [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/) and [SBT](https://www.scala-sbt.org/)) | [SpotBugs](https://spotbugs.github.io/) with the [find-sec-bugs](https://find-sec-bugs.github.io/) plugin | 10.6 (Maven), 10.8 (Gradle) & 11.9 (Ant, SBT) |
+| Javascript | [ESLint security plugin](https://github.com/nodesecurity/eslint-plugin-security) | 11.8 |
+| Node.js | [NodeJsScan](https://github.com/ajinabraham/NodeJsScan) | 11.1 |
+| PHP | [phpcs-security-audit](https://github.com/FloeDesignTechnologies/phpcs-security-audit) | 10.8 |
+| Python ([pip](https://pip.pypa.io/en/stable/)) | [bandit](https://github.com/PyCQA/bandit) | 10.3 |
+| Ruby on Rails | [brakeman](https://brakemanscanner.org) | 10.3 |
+| Scala ([Ant](https://ant.apache.org/), [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/) and [SBT](https://www.scala-sbt.org/)) | [SpotBugs](https://spotbugs.github.io/) with the [find-sec-bugs](https://find-sec-bugs.github.io/) plugin | 11.0 (SBT) & 11.9 (Ant, Gradle, Maven) |
+| Typescript | [TSLint config security](https://github.com/webschik/tslint-config-security/) | 11.9 |
+
+NOTE: **Note:**
+The Java analyzers can also be used for variants like the
+[Gradle wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html),
+[Grails](https://grails.org/) and the [Maven wrapper](https://github.com/takari/maven-wrapper).
+
+## Configuring SAST
+
+To enable SAST in your project, define a job in your `.gitlab-ci.yml` file that generates the
+[SAST report artifact](../../../ci/yaml/README.md#artifactsreportssast-ultimate).
+
+This can be done in two ways:
+
+- For GitLab 11.9 and later, including the provided `SAST.gitlab-ci.yml` template (recommended).
+- Manually specifying the job definition. Not recommended unless using GitLab
+ 11.8 and earlier.
+
+### Including the provided template
+
+NOTE: **Note:**
+The CI/CD SAST template is supported on GitLab 11.9 and later versions.
+For earlier versions, use the [manual job definition](#manual-job-definition-for-gitlab-115-and-later).
+
+A CI/CD [SAST template](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml)
+with the default SAST job definition is provided as a part of your GitLab
+installation which you can [include](../../../ci/yaml/README.md#includetemplate)
+in your `.gitlab-ci.yml` file.
+
+To enable SAST using the provided template, add the following to your `.gitlab-ci.yml`
+file:
+
+```yaml
+include:
+ template: SAST.gitlab-ci.yml
+```
+
+The included template will create a `sast` job in your CI/CD pipeline and scan
+your project's source code for possible vulnerabilities.
+
+The report will be saved as a
+[SAST report artifact](../../../ci/yaml/README.md#artifactsreportssast-ultimate)
+that you can later download and analyze. Due to implementation limitations, we
+always take the latest SAST artifact available. Behind the scenes, the
+[GitLab SAST Docker image](https://gitlab.com/gitlab-org/security-products/sast)
+is used to detect the languages/frameworks and in turn runs the matching scan tools.
+
+#### Customizing the SAST settings
+
+The SAST settings can be changed through environment variables by using the
+[`variables`](../../../ci/yaml/README.md#variables) parameter in `.gitlab-ci.yml`.
+These variables are documented in the
+[SAST tool documentation](https://gitlab.com/gitlab-org/security-products/sast#settings).
+
+In the following example, we include the SAST template and at the same time we
+set the `SAST_GOSEC_LEVEL` variable to `2`:
+
+```yaml
+include:
+ template: SAST.gitlab-ci.yml
+
+variables:
+ SAST_GOSEC_LEVEL: 2
+```
+
+Because the template is [evaluated before](../../../ci/yaml/README.md#include)
+the pipeline configuration, the last mention of the variable will take precedence.
+
+#### Overriding the SAST template
+
+If you want to override the job definition (for example, change properties like
+`variables` or `dependencies`), you need to declare a `sast` job after the
+template inclusion and specify any additional keys under it. For example:
+
+```yaml
+include:
+ template: SAST.gitlab-ci.yml
+
+sast:
+ variables:
+ CI_DEBUG_TRACE: "true"
+```
+
+### Manual job definition for GitLab 11.5 and later
+
+For GitLab 11.5 and GitLab Runner 11.5 and later, the following `sast`
+job can be added:
+
+```yaml
+sast:
+ stage: test
+ image: docker:stable
+ variables:
+ DOCKER_DRIVER: overlay2
+ allow_failure: true
+ services:
+ - docker:stable-dind
+ script:
+ - export SAST_VERSION=${SP_VERSION:-$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')}
+ - |
+ docker run \
+ --env SAST_ANALYZER_IMAGES \
+ --env SAST_ANALYZER_IMAGE_PREFIX \
+ --env SAST_ANALYZER_IMAGE_TAG \
+ --env SAST_DEFAULT_ANALYZERS \
+ --env SAST_EXCLUDED_PATHS \
+ --env SAST_BANDIT_EXCLUDED_PATHS \
+ --env SAST_BRAKEMAN_LEVEL \
+ --env SAST_GOSEC_LEVEL \
+ --env SAST_FLAWFINDER_LEVEL \
+ --env SAST_DOCKER_CLIENT_NEGOTIATION_TIMEOUT \
+ --env SAST_PULL_ANALYZER_IMAGE_TIMEOUT \
+ --env SAST_RUN_ANALYZER_TIMEOUT \
+ --volume "$PWD:/code" \
+ --volume /var/run/docker.sock:/var/run/docker.sock \
+ "registry.gitlab.com/gitlab-org/security-products/sast:$SAST_VERSION" /app/bin/run /code
+ dependencies: []
+ artifacts:
+ reports:
+ sast: gl-sast-report.json
+```
+
+You can supply many other [settings variables](https://gitlab.com/gitlab-org/security-products/sast#settings)
+via `docker run --env` to customize your job execution.
+
+### Manual job definition for GitLab 11.4 and earlier (deprecated)
+
+CAUTION: **Deprecated:**
+Before GitLab 11.5, the SAST job and artifact had to be named specifically
+to automatically extract report data and show it in the merge request widget.
+While these old job definitions are still maintained, they have been deprecated
+and may be removed in the next major release, GitLab 12.0. You are strongly
+advised to update your current `.gitlab-ci.yml` configuration to reflect that change.
+
+For GitLab 11.4 and earlier, the SAST job should look like:
+
+```yaml
+sast:
+ image: docker:stable
+ variables:
+ DOCKER_DRIVER: overlay2
+ allow_failure: true
+ services:
+ - docker:stable-dind
+ script:
+ - export SAST_VERSION=${SP_VERSION:-$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')}
+ - docker run
+ --env SAST_CONFIDENCE_LEVEL="${SAST_CONFIDENCE_LEVEL:-3}"
+ --volume "$PWD:/code"
+ --volume /var/run/docker.sock:/var/run/docker.sock
+ "registry.gitlab.com/gitlab-org/security-products/sast:$SAST_VERSION" /app/bin/run /code
+ artifacts:
+ paths: [gl-sast-report.json]
+```
+
+## Reports JSON format
+
+CAUTION: **Caution:**
+The JSON report artifacts are not a public API of SAST and their format may change in the future.
+
+The SAST tool emits a JSON report report file. Here is an example of a structure for a report will all important parts of
+it highlighted:
+
+```json-doc
+{
+ "version": "2.0",
+ "vulnerabilities": [
+ {
+ "category": "sast",
+ "name": "Predictable pseudorandom number generator",
+ "message": "Predictable pseudorandom number generator",
+ "description": "The use of java.util.Random is predictable",
+ "cve": "818bf5dacb291e15d9e6dc3c5ac32178:PREDICTABLE_RANDOM",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/groovy/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 47,
+ "end_line": 47,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "generateSecretToken2",
+ "dependency": {
+ "package": {}
+ }
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-PREDICTABLE_RANDOM",
+ "value": "PREDICTABLE_RANDOM",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-330",
+ "value": "330",
+ "url": "https://cwe.mitre.org/data/definitions/330.html"
+ }
+ ]
+ },
+ {
+ "category": "sast",
+ // "name" may be omitted because it could be not reported by a particular analyzer
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:4ad6d4c40a8c263fc265f3384724014e0a4f8dd6200af83e51ff120420038031:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 10,
+ "end_line": 10,
+ "dependency": {
+ "package": {}
+ }
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B108",
+ "value": "B108",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
+ }
+ ]
+ },
+ ],
+ "remediations": []
+}
+```
+
+Here is the description of the report file structure nodes and their meaning. All fields are mandatory to be present in
+the report JSON unless stated otherwise. Presence of optional fields depends on the underlying analyzers being used.
+
+| Report JSON node | Function |
+|-----------------------------------------|----------|
+| `version` | Report syntax version used to generate this JSON. |
+| `vulnerabilities` | Array of vulnerability objects. |
+| `vulnerabilities[].category` | Where this vulnerability belongs (SAST, Dependency Scanning etc.). For SAST, it will always be `sast`. |
+| `vulnerabilities[].name` | Name of the vulnerability, this must not include the occurrence's specific information. Optional. |
+| `vulnerabilities[].message` | A short text that describes the vulnerability, it may include the occurrence's specific information. Optional. |
+| `vulnerabilities[].description` | A long text that describes the vulnerability. Optional. |
+| `vulnerabilities[].cve` | A fingerprint string value that represents a concrete occurrence of the vulnerability. Is used to determine whether two vulnerability occurrences are same or different. May not be 100% accurate. **This is NOT a [CVE](https://cve.mitre.org/)**. |
+| `vulnerabilities[].severity` | How much the vulnerability impacts the software. Possible values: `Undefined` (an analyzer has not provided this info), `Info`, `Unknown`, `Low`, `Medium`, `High`, `Critical`. |
+| `vulnerabilities[].confidence` | How reliable the vulnerability's assessment is. Possible values: `Undefined` (an analyzer has not provided this info), `Ignore`, `Unknown`, `Experimental`, `Low`, `Medium`, `High`, `Confirmed`. |
+| `vulnerabilities[].solution` | Explanation of how to fix the vulnerability. Optional. |
+| `vulnerabilities[].scanner` | A node that describes the analyzer used find this vulnerability. |
+| `vulnerabilities[].scanner.id` | Id of the scanner as a snake_case string. |
+| `vulnerabilities[].scanner.name` | Name of the scanner, for display purposes. |
+| `vulnerabilities[].location` | A node that tells which class and/or method is affected by the vulnerability. |
+| `vulnerabilities[].location.file` | Path to the file where the vulnerability is located. Optional. |
+| `vulnerabilities[].location.start_line` | The first line of the code affected by the vulnerability. Optional. |
+| `vulnerabilities[].location.end_line` | The last line of the code affected by the vulnerability. Optional. |
+| `vulnerabilities[].location.class` | If specified, provides the name of the class where the vulnerability is located. Optional. |
+| `vulnerabilities[].location.method` | If specified, provides the name of the method where the vulnerability is located. Optional. |
+| `vulnerabilities[].identifiers` | An ordered array of references that identify a vulnerability on internal or external DBs. |
+| `vulnerabilities[].identifiers[].type` | Type of the identifier. Possible values: common identifier types (among `cve`, `cwe`, `osvdb`, and `usn`) or analyzer-dependent ones (e.g., `bandit_test_id` for [Bandit analyzer](https://wiki.openstack.org/wiki/Security/Projects/Bandit)). |
+| `vulnerabilities[].identifiers[].name` | Name of the identifier for display purposes. |
+| `vulnerabilities[].identifiers[].value` | Value of the identifier for matching purposes. |
+| `vulnerabilities[].identifiers[].url` | URL to identifier's documentation. Optional. |
+
+## Secret detection
+
+GitLab is also able to detect secrets and credentials that have been unintentionally pushed to the repository.
+For example, an API key that allows write access to third-party deployment environments.
+
+This check is performed by a specific analyzer during the `sast` job. It runs regardless of the programming
+language of your app, and you don't need to change anything to your
+CI/CD configuration file to turn it on. Results are available in the SAST report.
+
+GitLab currently includes [Gitleaks](https://github.com/zricethezav/gitleaks) and [TruffleHog](https://github.com/dxa4481/truffleHog) checks.
+
+## Security report under pipelines
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/3776)
+in [GitLab Ultimate](https://about.gitlab.com/pricing) 10.6.
+
+Visit any pipeline page which has a `sast` job and you will be able to see
+the security report tab with the listed vulnerabilities (if any).
+
+![Security Report](img/security_report.png)
+
+## Security Dashboard
+
+The Security Dashboard is a good place to get an overview of all the security
+vulnerabilities in your groups and projects. Read more about the
+[Security Dashboard](../security_dashboard/index.md).
+
+## Interacting with the vulnerabilities
+
+Once a vulnerability is found, you can interact with it. Read more on how to
+[interact with the vulnerabilities](../index.md#interacting-with-the-vulnerabilities).
diff --git a/doc/user/application_security/security_dashboard/img/dashboard.png b/doc/user/application_security/security_dashboard/img/dashboard.png
new file mode 100644
index 00000000000..a75168b1ce4
--- /dev/null
+++ b/doc/user/application_security/security_dashboard/img/dashboard.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/project_security_dashboard.png b/doc/user/application_security/security_dashboard/img/project_security_dashboard.png
new file mode 100644
index 00000000000..f0dad6c54d0
--- /dev/null
+++ b/doc/user/application_security/security_dashboard/img/project_security_dashboard.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/index.md b/doc/user/application_security/security_dashboard/index.md
new file mode 100644
index 00000000000..19eeb06a259
--- /dev/null
+++ b/doc/user/application_security/security_dashboard/index.md
@@ -0,0 +1,104 @@
+# GitLab Security Dashboard **[ULTIMATE]**
+
+The Security Dashboard is a good place to get an overview of all the security
+vulnerabilities in your groups and projects.
+
+You can also drill down into a vulnerability and get extra information, see which
+project it comes from, the file it's in, and various metadata to help you analyze
+the risk. You can also action these vulnerabilities by creating an issue for them,
+or by dismissing them.
+
+To benefit from the Security Dashboard you must first configure one of the
+[security reports](../index.md).
+
+## Supported reports
+
+The Security Dashboard supports the following reports:
+
+- [Container Scanning](../container_scanning/index.md)
+- [DAST](../dast/index.md)
+- [Dependency Scanning](../dependency_scanning/index.md)
+- [SAST](../sast/index.md)
+
+## Requirements
+
+To use the project or group security dashboard:
+
+1. At least one project inside a group must be configured with at least one of
+ the [supported reports](#supported-reports).
+2. The configured jobs must use the [new `reports` syntax](../../../ci/yaml/README.md#artifactsreports).
+3. [GitLab Runner](https://docs.gitlab.com/runner/) 11.5 or newer must be used.
+ If you're using the shared Runners on GitLab.com, this is already the case.
+
+## Project Security Dashboard
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/6165) in [GitLab Ultimate](https://about.gitlab.com/pricing) 11.1.
+
+At the project level, the Security Dashboard displays the latest security reports
+for your project. Use it to find and fix vulnerabilities affecting the
+[default branch](../../project/repository/branches/index.md#default-branch).
+
+![Project Security Dashboard](img/project_security_dashboard.png)
+
+## Group Security Dashboard
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/6709) in
+ [GitLab Ultimate](https://about.gitlab.com/pricing) 11.5.
+
+The group Security Dashboard gives an overview of the vulnerabilities of all the
+projects in a group and its subgroups.
+
+First, navigate to the Security Dashboard found under your group's
+**Overview > Security Dashboard**.
+
+Once you're on the dashboard, at the top you should see a series of filters for:
+
+- Severity
+- Confidence
+- Report type
+- Project
+
+![dashboard with action buttons and metrics](img/dashboard.png)
+
+Selecting one or more filters will filter the results in this page.
+The first section is an overview of all the vulnerabilities, grouped by severity.
+Underneath this overview is a timeline chart that shows how many open
+vulnerabilities your projects had at various points in time. You can filter among 30, 60, and
+90 days, with the default being 90. Hover over the chart to get more details about
+the open vulnerabilities at a specific time.
+
+Finally, there is a list of all the vulnerabilities in the group, sorted by severity.
+In that list, you can see the severity of the vulnerability, its name, its
+confidence (likelihood of the vulnerability to be a positive one), and the project
+it's from.
+
+If you hover over a row, there will appear some actions you can take:
+
+- "More info"
+- "Create issue"
+- "Dismiss vulnerability"
+
+Read more on how to [interact with the vulnerabilities](../index.md#interacting-with-the-vulnerabilities).
+
+## Keeping the dashboards up to date
+
+The Security Dashboard displays information from the results of the most recent
+security scan on the [default branch](../../project/repository/branches/index.md#default-branch),
+which means that security scans are performed every time the branch is updated.
+
+If the default branch is updated infrequently, scans are run infrequently and the
+information on the Security Dashboard can become outdated as new vulnerabilities
+are discovered.
+
+To ensure the information on the Security Dashboard is regularly updated,
+[configure a scheduled pipeline](../../project/pipelines/schedules.md) to run a
+daily security scan. This will update the information displayed on the Security
+Dashboard regardless of how often the default branch is updated.
+
+That way, reports are created even if no code change happens.
+
+## Security scans using Auto DevOps
+
+When using [Auto DevOps](../../../topics/autodevops/index.md), use
+[special environment variables](../../../topics/autodevops/index.md#environment-variables)
+to configure daily security scans.
diff --git a/doc/user/asciidoc.md b/doc/user/asciidoc.md
new file mode 100644
index 00000000000..a22b285b114
--- /dev/null
+++ b/doc/user/asciidoc.md
@@ -0,0 +1,372 @@
+# AsciiDoc
+
+GitLab uses the [Asciidoctor](https://asciidoctor.org) gem to convert AsciiDoc content to HTML5.
+Consult the [Asciidoctor User Manual](https://asciidoctor.org/docs/user-manual) for a complete Asciidoctor reference.
+
+## Syntax
+
+Here's a brief reference of the most commonly used AsciiDoc syntax.
+You can find the full documentation for the AsciiDoc syntax at https://asciidoctor.org/docs.
+
+### Paragraphs
+
+```asciidoc
+A normal paragraph.
+Line breaks are not preserved.
+```
+
+Line comments, which are lines that start with `//`, are skipped:
+
+```
+// this is a comment
+```
+
+A blank line separates paragraphs.
+
+A paragraph with the `[%hardbreaks]` option will preserve line breaks:
+
+```asciidoc
+[%hardbreaks]
+This paragraph carries the `hardbreaks` option.
+Notice how line breaks are now preserved.
+```
+
+An indented (literal) paragraph disables text formatting,
+preserves spaces and line breaks, and is displayed in a
+monospaced font:
+
+```asciidoc
+ This literal paragraph is indented with one space.
+ As a consequence, *text formatting*, spaces,
+ and lines breaks will be preserved.
+```
+
+An admonition paragraph grabs the reader's attention:
+
+```asciidoc
+NOTE: This is a brief reference, please read the full documentation at https://asciidoctor.org/docs.
+
+TIP: Lists can be indented. Leading whitespace is not significant.
+```
+
+### Text Formatting
+
+**Constrained (applied at word boundaries)**
+
+```asciidoc
+*strong importance* (aka bold)
+_stress emphasis_ (aka italic)
+`monospaced` (aka typewriter text)
+"`double`" and '`single`' typographic quotes
++passthrough text+ (substitutions disabled)
+`+literal text+` (monospaced with substitutions disabled)
+```
+
+**Unconstrained (applied anywhere)**
+
+```asciidoc
+**C**reate+**R**ead+**U**pdate+**D**elete
+fan__freakin__tastic
+``mono``culture
+```
+
+**Replacements**
+
+```asciidoc
+A long time ago in a galaxy far, far away...
+(C) 1976 Arty Artisan
+I believe I shall--no, actually I won't.
+```
+
+**Macros**
+
+```asciidoc
+// where c=specialchars, q=quotes, a=attributes, r=replacements, m=macros, p=post_replacements, etc.
+The European icon:flag[role=blue] is blue & contains pass:[************] arranged in a icon:circle-o[role=yellow].
+The pass:c[->] operator is often referred to as the stabby lambda.
+Since `pass:[++]` has strong priority in AsciiDoc, you can rewrite pass:c,a,r[C++ => C{pp}].
+// activate stem support by adding `:stem:` to the document header
+stem:[sqrt(4) = 2]
+```
+
+### Attributes
+
+```asciidoc
+// define attributes in the document header
+:name: value
+```
+
+```asciidoc
+:url-gem: https://rubygems.org/gems/asciidoctor
+
+You can download and install Asciidoctor {asciidoctor-version} from {url-gem}.
+C{pp} is not required, only Ruby.
+Use a leading backslash to output a word enclosed in curly braces, like \{name}.
+```
+
+### Links
+
+```asciidoc
+https://example.org/page[A webpage]
+link:../path/to/file.txt[A local file]
+xref:document.adoc[A sibling document]
+mailto:hello@example.org[Email to say hello!]
+```
+
+### Anchors
+
+```asciidoc
+[[idname,reference text]]
+// or written using normal block attributes as `[#idname,reftext=reference text]`
+A paragraph (or any block) with an anchor (aka ID) and reftext.
+
+See <<idname>> or <<idname,optional text of internal link>>.
+
+xref:document.adoc#idname[Jumps to anchor in another document].
+
+This paragraph has a footnote.footnote:[This is the text of the footnote.]
+```
+
+### Lists
+
+#### Unordered
+
+```asciidoc
+* level 1
+** level 2
+*** level 3
+**** level 4
+***** etc.
+* back at level 1
++
+Attach a block or paragraph to a list item using a list continuation (which you can enclose in an open block).
+
+.Some Authors
+[circle]
+- Edgar Allen Poe
+- Sheri S. Tepper
+- Bill Bryson
+```
+
+#### Ordered
+
+```asciidoc
+. Step 1
+. Step 2
+.. Step 2a
+.. Step 2b
+. Step 3
+
+.Remember your Roman numerals?
+[upperroman]
+. is one
+. is two
+. is three
+```
+
+#### Checklist
+
+```asciidoc
+* [x] checked
+* [ ] not checked
+```
+#### Callout
+
+```asciidoc
+// enable callout bubbles by adding `:icons: font` to the document header
+[,ruby]
+----
+puts 'Hello, World!' # <1>
+----
+<1> Prints `Hello, World!` to the console.
+```
+
+#### Description
+
+```asciidoc
+first term:: description of first term
+second term::
+description of second term
+```
+### Document Structure
+
+#### Header
+
+```asciidoc
+= Document Title
+Author Name <author@example.org>
+v1.0, 2019-01-01
+```
+#### Sections
+
+```asciidoc
+= Document Title (Level 0)
+== Level 1
+=== Level 2
+==== Level 3
+===== Level 4
+====== Level 5
+== Back at Level 1
+```
+
+#### Includes
+
+```asciidoc
+include::basics.adoc[]
+
+// define -a allow-uri-read to allow content to be read from URI
+include::https://example.org/installation.adoc[]
+```
+### Blocks
+
+```asciidoc
+--
+open - a general-purpose content wrapper; useful for enclosing content to attach to a list item
+--
+```
+
+```asciidoc
+// recognized types include CAUTION, IMPORTANT, NOTE, TIP, and WARNING
+// enable admonition icons by setting `:icons: font` in the document header
+[NOTE]
+====
+admonition - a notice for the reader, ranging in severity from a tip to an alert
+====
+```
+
+```asciidoc
+====
+example - a demonstration of the concept being documented
+====
+```
+
+```asciidoc
+.Toggle Me
+[%collapsible]
+====
+collapsible - these details are revealed by clicking the title
+====
+```
+
+```asciidoc
+****
+sidebar - auxiliary content that can be read independently of the main content
+****
+```
+
+```asciidoc
+....
+literal - an exhibit that features program output
+....
+```
+
+```asciidoc
+----
+listing - an exhibit that features program input, source code, or the contents of a file
+----
+```
+
+```asciidoc
+[,language]
+----
+source - a listing that is embellished with (colorized) syntax highlighting
+----
+```
+
+```asciidoc
+\```language
+fenced code - a shorthand syntax for the source block
+\```
+```
+
+```asciidoc
+[,attribution,citetitle]
+____
+quote - a quotation or excerpt; attribution with title of source are optional
+____
+```
+
+```asciidoc
+[verse,attribution,citetitle]
+____
+verse - a literary excerpt, often a poem; attribution with title of source are optional
+____
+```
+
+```asciidoc
+++++
+pass - content passed directly to the output document; often raw HTML
+++++
+```
+
+```asciidoc
+// activate stem support by adding `:stem:` to the document header
+[stem]
+++++
+x = y^2
+++++
+```
+
+```asciidoc
+////
+comment - content which is not included in the output document
+////
+```
+
+### Tables
+
+```asciidoc
+.Table Attributes
+[cols=>1h;2d,width=50%,frame=topbot]
+|===
+| Attribute Name | Values
+
+| options
+| header,footer,autowidth
+
+| cols
+| colspec[;colspec;...]
+
+| grid
+| all \| cols \| rows \| none
+
+| frame
+| all \| sides \| topbot \| none
+
+| stripes
+| all \| even \| odd \| none
+
+| width
+| (0%..100%)
+
+| format
+| psv {vbar} csv {vbar} dsv
+|===
+```
+
+### Multimedia
+
+```asciidoc
+image::screenshot.png[block image,800,450]
+
+Press image:reload.svg[reload,16,opts=interactive] to reload the page.
+
+video::movie.mp4[width=640,start=60,end=140,options=autoplay]
+
+video::aHjpOzsQ9YI[youtube]
+
+video::300817511[vimeo]
+```
+
+### Breaks
+
+```asciidoc
+// thematic break (aka horizontal rule)
+---
+```
+
+```asciidoc
+// page break
+<<<
+```
+
diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md
new file mode 100644
index 00000000000..b520c4fb579
--- /dev/null
+++ b/doc/user/clusters/applications.md
@@ -0,0 +1,290 @@
+# GitLab Managed Apps
+
+GitLab provides **GitLab Managed Apps**, a one-click install for various applications which can
+be added directly to your configured cluster. These applications are
+needed for [Review Apps](../../ci/review_apps/index.md) and
+[deployments](../../ci/environments.md) when using [Auto DevOps](../../topics/autodevops/index.md).
+You can install them after you
+[create a cluster](../project/clusters/index.md#adding-and-creating-a-new-gke-cluster-via-gitlab).
+
+## Installing applications
+
+Applications managed by GitLab will be installed onto the `gitlab-managed-apps` namespace.
+This namespace:
+
+- Is different from the namespace used for project deployments.
+- Is created once.
+- Has a non-configurable name.
+
+To see a list of available applications to install:
+
+1. For a:
+ - Project-level cluster, navigate to your project's **Operations > Kubernetes**.
+ - Group-level cluster, navigate to your group's **Kubernetes** page.
+
+Install Helm first as it's used to install other applications.
+
+NOTE: **Note:**
+As of GitLab 11.6, Helm will be upgraded to the latest version supported
+by GitLab before installing any of the applications.
+
+The following applications can be installed:
+
+- [Helm](#helm)
+- [Ingress](#ingress)
+- [Cert-Manager](#cert-manager)
+- [Prometheus](#prometheus)
+- [GitLab Runner](#gitlab-runner)
+- [JupyterHub](#jupyterhub)
+- [Knative](#knative)
+
+With the exception of Knative, the applications will be installed in a dedicated
+namespace called `gitlab-managed-apps`.
+
+NOTE: **Note:**
+Some applications are installable only for a project-level cluster.
+Support for installing these applications in a group-level cluster is
+planned for future releases.
+For updates, see [the issue tracking
+progress](https://gitlab.com/gitlab-org/gitlab-ce/issues/51989).
+
+CAUTION: **Caution:**
+If you have an existing Kubernetes cluster with Helm already installed,
+you should be careful as GitLab cannot detect it. In this case, installing
+Helm via the applications will result in the cluster having it twice, which
+can lead to confusion during deployments.
+
+### Helm
+
+> - Available for project-level clusters since GitLab 10.2.
+> - Available for group-level clusters since GitLab 11.6.
+
+[Helm](https://docs.helm.sh/) is a package manager for Kubernetes and is
+required to install all the other applications. It is installed in its
+own pod inside the cluster which can run the `helm` CLI in a safe
+environment.
+
+### Cert-Manager
+
+> - Available for project-level clusters since GitLab 11.6.
+> - Available for group-level clusters since GitLab 11.6.
+
+[Cert-Manager](https://docs.cert-manager.io/en/latest/) is a native
+Kubernetes certificate management controller that helps with issuing
+certificates. Installing Cert-Manager on your cluster will issue a
+certificate by [Let's Encrypt](https://letsencrypt.org/) and ensure that
+certificates are valid and up-to-date.
+
+NOTE: **Note:**
+The
+[stable/cert-manager](https://github.com/helm/charts/tree/master/stable/cert-manager)
+chart is used to install this application with a
+[`values.yaml`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/vendor/cert_manager/values.yaml)
+file.
+
+### GitLab Runner
+
+> - Available for project-level clusters since GitLab 10.6.
+> - Available for group-level clusters since GitLab 11.10.
+
+[GitLab Runner](https://docs.gitlab.com/runner/) is the open source
+project that is used to run your jobs and send the results back to
+GitLab. It is used in conjunction with [GitLab
+CI/CD](../../ci/README.md), the open-source continuous integration
+service included with GitLab that coordinates the jobs. When installing
+the GitLab Runner via the applications, it will run in **privileged
+mode** by default. Make sure you read the [security
+implications](../project/clusters/index.md/#security-implications) before doing so.
+
+NOTE: **Note:**
+The
+[runner/gitlab-runner](https://gitlab.com/charts/gitlab-runner)
+chart is used to install this application with a
+[`values.yaml`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/vendor/runner/values.yaml)
+file.
+
+### Ingress
+
+> - Available for project-level clusters since GitLab 10.2.
+> - Available for group-level clusters since GitLab 11.6.
+
+[Ingress](https://kubernetes.github.io/ingress-nginx/) can provide load
+balancing, SSL termination, and name-based virtual hosting. It acts as a
+web proxy for your applications and is useful if you want to use [Auto
+DevOps] or deploy your own web apps.
+
+NOTE: **Note:**
+The
+[stable/nginx-ingress](https://github.com/helm/charts/tree/master/stable/nginx-ingress)
+chart is used to install this application with a
+[`values.yaml`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/vendor/ingress/values.yaml)
+file.
+
+### JupyterHub
+
+> Available for project-level clusters since GitLab 11.0.
+
+[JupyterHub](https://jupyterhub.readthedocs.io/en/stable/) is a
+multi-user service for managing notebooks across a team. [Jupyter
+Notebooks](https://jupyter-notebook.readthedocs.io/en/latest/) provide a
+web-based interactive programming environment used for data analysis,
+visualization, and machine learning.
+
+Authentication will be enabled only for [project
+members](../project/members/index.md) with [Developer or
+higher](../permissions.md) access to the project.
+
+We use a [custom Jupyter
+image](https://gitlab.com/gitlab-org/jupyterhub-user-image/blob/master/Dockerfile)
+that installs additional useful packages on top of the base Jupyter. You
+will also see ready-to-use DevOps Runbooks built with Nurtch's [Rubix library](https://github.com/amit1rrr/rubix).
+
+More information on
+creating executable runbooks can be found in [our Runbooks
+documentation](../project/clusters/runbooks/index.md#executable-runbooks). Note that
+Ingress must be installed and have an IP address assigned before
+JupyterHub can be installed.
+
+NOTE: **Note:**
+The
+[jupyter/jupyterhub](https://jupyterhub.github.io/helm-chart/)
+chart is used to install this application with a
+[`values.yaml`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/vendor/jupyter/values.yaml)
+file.
+
+#### Jupyter Git Integration
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/28783) in GitLab 12 for project-level clusters.
+
+When installing JupyterHub onto your Kubernetes cluster, [JupyterLab's Git extension](https://github.com/jupyterlab/jupyterlab-git)
+is automatically provisioned and configured using the authenticated user's:
+
+- Name
+- Email
+- Newly created access token
+
+JupyterLab's Git extension enables full version control of your notebooks as well as issuance of Git commands within Jupyter.
+Git commands can be issued via the **Git** tab on the left panel or via Jupyter's command line prompt.
+
+NOTE: **Note:**
+JupyterLab's Git extension stores the user token in the JupyterHub DB in encrypted format
+and in the single user Jupyter instance as plain text. This is because [Git requires storing
+credentials as plain text](https://git-scm.com/docs/git-credential-store). Potentially, if
+a nefarious user finds a way to read from the file system in the single user Jupyter instance
+they could retrieve the token.
+
+![Jupyter's Git Extension](img/jupyter-git-extension.gif)
+
+You can clone repositories from the files tab in Jupyter:
+
+![Jupyter clone repository](img/jupyter-gitclone.png)
+
+### Knative
+
+> Available for project-level clusters since GitLab 11.5.
+
+[Knative](https://cloud.google.com/knative) provides a platform to
+create, deploy, and manage serverless workloads from a Kubernetes
+cluster. It is used in conjunction with, and includes
+[Istio](https://istio.io) to provide an external IP address for all
+programs hosted by Knative.
+
+You will be prompted to enter a wildcard
+domain where your applications will be exposed. Configure your DNS
+server to use the external IP address for that domain. For any
+application created and installed, they will be accessible as
+`<program_name>.<kubernetes_namespace>.<domain_name>`. This will require
+your kubernetes cluster to have [RBAC
+enabled](../project/clusters/index.md#rbac-cluster-resources).
+
+NOTE: **Note:**
+The
+[knative/knative](https://storage.googleapis.com/triggermesh-charts)
+chart is used to install this application.
+
+### Prometheus
+
+> - Available for project-level clusters since GitLab 10.4.
+> - Available for group-level clusters since GitLab 11.11.
+
+[Prometheus](https://prometheus.io/docs/introduction/overview/) is an
+open-source monitoring and alerting system useful to supervise your
+deployed applications.
+
+NOTE: **Note:**
+The
+[stable/prometheus](https://github.com/helm/charts/tree/master/stable/prometheus)
+chart is used to install this application with a
+[`values.yaml`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/vendor/prometheus/values.yaml)
+file.
+
+## Upgrading applications
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24789)
+in GitLab 11.8.
+
+The applications below can be upgraded.
+
+| Application | GitLab version |
+| ----------- | -------------- |
+| Runner | 11.8+ |
+
+To upgrade an application:
+
+1. For a:
+ - Project-level cluster, navigate to your project's **Operations > Kubernetes**.
+ - Group-level cluster, navigate to your group's **Kubernetes** page.
+1. Select your cluster.
+1. If an upgrade is available, the **Upgrade** button is displayed. Click the button to upgrade.
+
+NOTE: **Note:**
+Upgrades will reset values back to the values built into the `runner`
+chart plus the values set by
+[`values.yaml`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/vendor/runner/values.yaml)
+
+## Uninstalling applications
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/60665) in
+> GitLab 11.11.
+
+The applications below can be uninstalled.
+
+| Application | GitLab version | Notes |
+| ----------- | -------------- | ----- |
+| Prometheus | 11.11+ | All data will be deleted and cannot be restored. |
+
+To uninstall an application:
+
+1. For a:
+ - Project-level cluster, navigate to your project's **Operations > Kubernetes**.
+ - Group-level cluster, navigate to your group's **Kubernetes** page.
+1. Select your cluster.
+1. Click the **Uninstall** button for the application.
+
+Support for uninstalling all applications is planned for progressive rollout.
+To follow progress, see [the relevant
+epic](https://gitlab.com/groups/gitlab-org/-/epics/1201).
+
+## Troubleshooting applications
+
+Applications can fail with the following error:
+
+```text
+Error: remote error: tls: bad certificate
+```
+
+To avoid installation errors:
+
+- Before starting the installation of applications, make sure that time is synchronized
+ between your GitLab server and your Kubernetes cluster.
+- Ensure certificates are not out of sync. When installing applications, GitLab expects a new cluster with no previous installation of Helm.
+
+ You can confirm that the certificates match via `kubectl`:
+
+ ```sh
+ kubectl get configmaps/values-content-configuration-ingress -n gitlab-managed-apps -o \
+ "jsonpath={.data['cert\.pem']}" | base64 -d > a.pem
+ kubectl get secrets/tiller-secret -n gitlab-managed-apps -o "jsonpath={.data['ca\.crt']}" | base64 -d > b.pem
+ diff a.pem b.pem
+ ```
+
diff --git a/doc/user/clusters/img/jupyter-git-extension.gif b/doc/user/clusters/img/jupyter-git-extension.gif
new file mode 100644
index 00000000000..13a88d97425
--- /dev/null
+++ b/doc/user/clusters/img/jupyter-git-extension.gif
Binary files differ
diff --git a/doc/user/clusters/img/jupyter-gitclone.png b/doc/user/clusters/img/jupyter-gitclone.png
new file mode 100644
index 00000000000..41d467f806a
--- /dev/null
+++ b/doc/user/clusters/img/jupyter-gitclone.png
Binary files differ
diff --git a/doc/user/discussions/img/mr_review_resolve.png b/doc/user/discussions/img/mr_review_resolve.png
new file mode 100644
index 00000000000..34176f3fa8e
--- /dev/null
+++ b/doc/user/discussions/img/mr_review_resolve.png
Binary files differ
diff --git a/doc/user/discussions/img/mr_review_resolve2.png b/doc/user/discussions/img/mr_review_resolve2.png
new file mode 100644
index 00000000000..e4adb5f2c2d
--- /dev/null
+++ b/doc/user/discussions/img/mr_review_resolve2.png
Binary files differ
diff --git a/doc/user/discussions/img/mr_review_second_comment.png b/doc/user/discussions/img/mr_review_second_comment.png
new file mode 100644
index 00000000000..920ea05ad66
--- /dev/null
+++ b/doc/user/discussions/img/mr_review_second_comment.png
Binary files differ
diff --git a/doc/user/discussions/img/mr_review_second_comment_added.png b/doc/user/discussions/img/mr_review_second_comment_added.png
new file mode 100644
index 00000000000..1fb54348547
--- /dev/null
+++ b/doc/user/discussions/img/mr_review_second_comment_added.png
Binary files differ
diff --git a/doc/user/discussions/img/mr_review_start.png b/doc/user/discussions/img/mr_review_start.png
new file mode 100644
index 00000000000..38b44bda0d2
--- /dev/null
+++ b/doc/user/discussions/img/mr_review_start.png
Binary files differ
diff --git a/doc/user/discussions/img/mr_review_unresolve.png b/doc/user/discussions/img/mr_review_unresolve.png
new file mode 100644
index 00000000000..da895ceb89f
--- /dev/null
+++ b/doc/user/discussions/img/mr_review_unresolve.png
Binary files differ
diff --git a/doc/user/discussions/img/mr_review_unresolve2.png b/doc/user/discussions/img/mr_review_unresolve2.png
new file mode 100644
index 00000000000..a824b806e4a
--- /dev/null
+++ b/doc/user/discussions/img/mr_review_unresolve2.png
Binary files differ
diff --git a/doc/user/discussions/img/pending_review_comment.png b/doc/user/discussions/img/pending_review_comment.png
new file mode 100644
index 00000000000..916ef5b7452
--- /dev/null
+++ b/doc/user/discussions/img/pending_review_comment.png
Binary files differ
diff --git a/doc/user/discussions/img/review_comment_quickactions.png b/doc/user/discussions/img/review_comment_quickactions.png
new file mode 100644
index 00000000000..bd9880c329a
--- /dev/null
+++ b/doc/user/discussions/img/review_comment_quickactions.png
Binary files differ
diff --git a/doc/user/discussions/img/review_preview.png b/doc/user/discussions/img/review_preview.png
new file mode 100644
index 00000000000..4bf53a81b9c
--- /dev/null
+++ b/doc/user/discussions/img/review_preview.png
Binary files differ
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
index bf41fdecd10..20eabdada79 100644
--- a/doc/user/discussions/index.md
+++ b/doc/user/discussions/index.md
@@ -5,6 +5,7 @@ The ability to contribute conversationally is offered throughout GitLab.
You can leave a comment in the following places:
- issues
+- epics **[ULTIMATE]**
- merge requests
- snippets
- commits
@@ -52,6 +53,8 @@ persist through a commit ID change when:
- force-pushing after a rebase
- amending a commit
+This functionality is also demonstrated in the video [How to use Merge Request Commit Discussions](https://www.youtube.com/watch?v=TviJH6oRboo).
+
To create a commit diff discussion:
1. Navigate to the merge request **Commits** tab. A list of commits that
@@ -279,6 +282,75 @@ edit existing comments. Non-team members are restricted from adding or editing c
Additionally, locked issues and merge requests can not be reopened.
+## Merge Request Reviews **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/4213) in GitLab 11.4.
+
+When looking at a Merge Request diff, you are able to start a review.
+This allows you to create comments inside a Merge Request that are **only visible to you** until published,
+in order to allow you to submit them all as a single action.
+
+### Starting a review
+
+In order to start a review, simply write a comment on a diff as normal under the **Changes** tab
+in an MR and click on the **Start a review** button.
+
+![Starting a review](img/mr_review_start.png)
+
+Once a review is started, you will see any comments that are part of this review marked `Pending`.
+All comments that are part of a review show two buttons:
+
+- **Submit review**: Submits all comments that are part of the review, making them visible to other users.
+- **Add comment now**: Submits the specific comment as a regular comment instead of as part of the review.
+
+![A comment that is part of a review](img/pending_review_comment.png)
+
+You can use [quick actions] inside review comments. The comment will show the actions that will be performed once published.
+
+![A review comment with quick actions](img/review_comment_quickactions.png)
+
+To add more comments to a review, start writing a comment as normal and click the **Add to review** button.
+
+![Adding a second comment to a review](img/mr_review_second_comment.png)
+
+This will add the comment to the review.
+
+![Second review comment](img/mr_review_second_comment_added.png)
+
+### Resolving/Unresolving discussions
+
+Review comments can also resolve/unresolve [resolvable discussions](#resolvable-comments-and-discussions).
+When replying to a comment, you will see a checkbox that you can click in order to resolve or unresolve
+the discussion once published.
+
+![Resolve checkbox](img/mr_review_resolve.png)
+![Unresolve checkbox](img/mr_review_unresolve.png)
+
+If a particular pending comment will resolve or unresolve the discussion, this will be shown on the pending
+comment itself.
+
+![Resolve status](img/mr_review_resolve2.png)
+![Unresolve status](img/mr_review_unresolve2.png)
+
+### Submitting a review
+
+If you have any comments that have not been submitted, you will see a bar at the
+bottom of the screen with two buttons:
+
+- **Discard**: Discards all comments that have not been submitted.
+- **Finish review**: Opens a list of comments ready to be submitted for review.
+ Clicking **Submit review** will publish all comments. Any quick actions
+ submitted are performed at this time.
+
+Alternatively, every pending comment has a button to finish the entire review.
+
+![Review submission](img/review_preview.png)
+
+Submitting the review will send a single email to every notifiable user of the
+merge request with all the comments associated to it.
+
+Replying to this email will, consequentially, create a new comment on the associated merge request.
+
## Filtering notes
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/26723) in GitLab 11.5.
@@ -315,11 +387,6 @@ the Merge Request authored by the user that applied them.
![Add a new comment](img/insert_suggestion.png)
- > **Note:**
- The suggestion will only affect the commented line. Multi-line
- suggestions are currently not supported. Will be introduced by
- [#53310](https://gitlab.com/gitlab-org/gitlab-ce/issues/53310).
-
1. In the comment, add your suggestion to the pre-populated code block:
![Add a suggestion into a code block tagged properly](img/make_suggestion.png)
@@ -331,13 +398,10 @@ the Merge Request authored by the user that applied them.
![Apply suggestions](img/suggestion.png)
- > **Note:**
- Discussions are _not_ automatically resolved. Will be introduced by
- [#54405](https://gitlab.com/gitlab-org/gitlab-ce/issues/54405).
-
Once the author applies a suggestion, it will be marked with the **Applied** label,
-and GitLab will create a new commit with the message `Apply suggestion to <file-name>`
-and push the suggested change directly into the codebase in the merge request's branch.
+the discussion will be automatically resolved, and GitLab will create a new commit
+with the message `Apply suggestion to <file-name>` and push the suggested change
+directly into the codebase in the merge request's branch.
[Developer permission](../permissions.md) is required to do so.
> **Note:**
@@ -348,19 +412,23 @@ Custom commit messages will be introduced by
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/53310) in GitLab 11.10.
-Reviewers can also suggest changes to
-multiple lines with a single suggestion within Merge Request diff discussions.
+Reviewers can also suggest changes to multiple lines with a single suggestion
+within Merge Request diff discussions by adjusting the range offsets. The
+offsets are relative to the position of the diff discussion, and specify the
+range to be replaced by the suggestion when it is applied.
![Multi-line suggestion syntax](img/multi-line-suggestion-syntax.png)
-In the example above, the suggestion covers three lines above and four lines below the commented diff line.
-It'd change from 3 lines _above_ to 4 lines _below_ the commented Diff line.
+In the example above, the suggestion covers three lines above and four lines
+below the commented line. When applied, it would replace from 3 lines _above_
+to 4 lines _below_ the commented line, with the suggested change.
![Multi-line suggestion preview](img/multi-line-suggestion-preview.png)
NOTE: **Note:**
-Suggestions covering multiple lines are limited to 100 lines _above_ and 100 lines _below_
-the commented diff line, allowing up to 200 changed lines per suggestion.
+Suggestions covering multiple lines are limited to 100 lines _above_ and 100
+lines _below_ the commented diff line, allowing up to 200 changed lines per
+suggestion.
## Start a discussion by replying to a standard comment
diff --git a/doc/user/group/clusters/index.md b/doc/user/group/clusters/index.md
index 984881ef26c..3c5e820c1ca 100644
--- a/doc/user/group/clusters/index.md
+++ b/doc/user/group/clusters/index.md
@@ -1,3 +1,7 @@
+---
+type: reference
+---
+
# Group-level Kubernetes clusters
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/34758) in GitLab 11.6.
@@ -5,41 +9,17 @@
## Overview
-Similar to [project Kubernetes
-clusters](../../project/clusters/index.md), Group-level Kubernetes
-clusters allow you to connect a Kubernetes cluster to your group,
-enabling you to use the same cluster across multiple projects.
+Similar to [project-level](../../project/clusters/index.md) and
+[instance-level](../../instance/clusters/index.md) Kubernetes clusters,
+group-level Kubernetes clusters allow you to connect a Kubernetes cluster to
+your group, enabling you to use the same cluster across multiple projects.
## Installing applications
-GitLab provides a one-click install for various applications that can be
-added directly to your cluster.
-
-NOTE: **Note:**
-Applications will be installed in a dedicated namespace called
-`gitlab-managed-apps`. If you have added an existing Kubernetes cluster
-with Tiller already installed, you should be careful as GitLab cannot
-detect it. In this event, installing Tiller via the applications will
-result in the cluster having it twice. This can lead to confusion during
-deployments.
-
-| Application | GitLab version | Description | Helm Chart |
-| ----------- | -------------- | ----------- | ---------- |
-| [Helm Tiller](https://docs.helm.sh) | 11.6+ | Helm is a package manager for Kubernetes and is required to install all the other applications. It is installed in its own pod inside the cluster which can run the `helm` CLI in a safe environment. | n/a |
-| [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress) | 11.6+ | Ingress can provide load balancing, SSL termination, and name-based virtual hosting. It acts as a web proxy for your applications and is useful if you want to use [Auto DevOps](../../../topics/autodevops/index.md) or deploy your own web apps. | [stable/nginx-ingress](https://github.com/helm/charts/tree/master/stable/nginx-ingress) |
-| [Cert-Manager](https://docs.cert-manager.io/en/latest/) | 11.6+ | Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by [Let's Encrypt](https://letsencrypt.org/) and ensure that certificates are valid and up-to-date. | [stable/cert-manager](https://github.com/helm/charts/tree/master/stable/cert-manager) |
-| [GitLab Runner](https://docs.gitlab.com/runner/) | 11.10+ | GitLab Runner is the open source project that is used to run your jobs and send the results back to GitLab. It is used in conjunction with [GitLab CI/CD](../../../ci/README.md), the open-source continuous integration service included with GitLab that coordinates the jobs. When installing the GitLab Runner via the applications, it will run in **privileged mode** by default. Make sure you read the [security implications](../../project/clusters/index.md#security-implications) before doing so. | [runner/gitlab-runner](https://gitlab.com/charts/gitlab-runner) |
-
-NOTE: **Note:**
-Some [cluster
-applications](../../project/clusters/index.md#installing-applications)
-are installable only for a project-level cluster. Support for installing these
-applications in a group-level cluster is planned for future releases. For updates, see:
-
-- Support installing [JupyterHub in group-level
- clusters](https://gitlab.com/gitlab-org/gitlab-ce/issues/51989)
-- Support installing [Prometheus in group-level
- clusters](https://gitlab.com/gitlab-org/gitlab-ce/issues/51963)
+GitLab can install and manage some applications in your group-level
+cluster. For more information on installing, upgrading, uninstalling,
+and troubleshooting applications for your group cluster, see
+[Gitlab Managed Apps](../../clusters/applications.md).
## RBAC compatibility
@@ -72,6 +52,29 @@ Add another cluster similar to the first one and make sure to
[set an environment scope](#environment-scopes-premium) that will
differentiate the new cluster from the rest.
+## GitLab-managed clusters
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22011) in GitLab 11.5.
+> Became [optional](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/26565) in GitLab 11.11.
+
+NOTE: **Note:**
+Only available when creating clusters. Existing clusters not managed by GitLab
+cannot become GitLab-managed later.
+
+You can choose to allow GitLab to manage your cluster for you. If your cluster is
+managed by GitLab, resources for your projects will be automatically created. See the
+[Access controls](../../project/clusters/index.md#access-controls) section for details on which resources will
+be created.
+
+If you choose to manage your own cluster, project-specific resources will not be created
+automatically. If you are using [Auto DevOps](../../../topics/autodevops/index.md), you will
+need to explicitly provide the `KUBE_NAMESPACE` [deployment variable](../../project/clusters/index.md#deployment-variables)
+that will be used by your deployment jobs.
+
+NOTE: **Note:**
+If you [install applications](#installing-applications) on your cluster, GitLab will create
+the resources required to run these even if you have chosen to manage your own cluster.
+
## Base domain
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24580) in GitLab 11.8.
@@ -88,7 +91,7 @@ The domain should have a wildcard DNS configured to the Ingress IP address.
When adding more than one Kubernetes cluster to your project, you need to differentiate
them with an environment scope. The environment scope associates clusters with
[environments](../../../ci/environments.md) similar to how the
-[environment-specific variables](https://docs.gitlab.com/ee/ci/variables/README.html#limiting-environment-scopes-of-variables-premium)
+[environment-specific variables](../../../ci/variables/README.md#limiting-environment-scopes-of-environment-variables-premium)
work.
While evaluating which environment matches the environment scope of a
@@ -146,3 +149,15 @@ The following features are not currently available for group-level clusters:
1. Terminals (see [related issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/55487)).
1. Pod logs (see [related issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/55488)).
1. Deployment boards (see [related issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/55489)).
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/group/contribution_analytics/img/group_stats_cal.png b/doc/user/group/contribution_analytics/img/group_stats_cal.png
new file mode 100644
index 00000000000..0238c7bf088
--- /dev/null
+++ b/doc/user/group/contribution_analytics/img/group_stats_cal.png
Binary files differ
diff --git a/doc/user/group/contribution_analytics/img/group_stats_graph.png b/doc/user/group/contribution_analytics/img/group_stats_graph.png
new file mode 100644
index 00000000000..ccfd3782c6f
--- /dev/null
+++ b/doc/user/group/contribution_analytics/img/group_stats_graph.png
Binary files differ
diff --git a/doc/user/group/contribution_analytics/img/group_stats_table.png b/doc/user/group/contribution_analytics/img/group_stats_table.png
new file mode 100644
index 00000000000..f1d1031fa18
--- /dev/null
+++ b/doc/user/group/contribution_analytics/img/group_stats_table.png
Binary files differ
diff --git a/doc/user/group/contribution_analytics/index.md b/doc/user/group/contribution_analytics/index.md
new file mode 100644
index 00000000000..7e6cb24a51e
--- /dev/null
+++ b/doc/user/group/contribution_analytics/index.md
@@ -0,0 +1,77 @@
+---
+type: reference
+---
+
+# Contribution Analytics **[STARTER]**
+
+> Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 8.3.
+
+## Overview
+
+With Contribution Analytics you can get an overview of the following activity in your
+group:
+
+- Issues
+- Merge requests
+- Push events
+
+To view the Contribution Analytics, go to your group's **Overview > Contribution Analytics**
+page.
+
+## Use cases
+
+- Analyze your team's contributions over a period of time, and offer a bonus for the top
+contributors.
+- Identify opportunities for improvement with group members who may benefit from additional
+support.
+
+## Using Contribution Analytics
+
+There are three main bar graphs that illustrate the number of contributions per group
+member for the following:
+
+- Push events
+- Merge requests
+- Closed issues
+
+Hover over each bar to display the number of events for a specific group member.
+
+![Contribution analytics bar graphs](img/group_stats_graph.png)
+
+## Changing the period time
+
+You can choose from the following three periods:
+
+- Last week (default)
+- Last month
+- Last three months
+
+Select the desired period from the calendar dropdown.
+
+![Contribution analytics choose period](img/group_stats_cal.png)
+
+## Sorting by different factors
+
+Contributions per group member are also presented in tabular format. Click a column header to sort the table by that column:
+
+* Member name
+* Number of pushed events
+* Number of opened issues
+* Number of closed issues
+* Number of opened MRs
+* Number of accepted MRs
+* Number of total contributions
+
+![Contribution analytics contributions table](img/group_stats_table.png)
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/group/custom_project_templates.md b/doc/user/group/custom_project_templates.md
index 8e101407ac0..aa088d2fcdb 100644
--- a/doc/user/group/custom_project_templates.md
+++ b/doc/user/group/custom_project_templates.md
@@ -1,4 +1,8 @@
-# Custom group-level project templates **[PREMIUM ONLY]**
+---
+type: reference
+---
+
+# Custom group-level project templates **[PREMIUM]**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/6861) in [GitLab Premium](https://about.gitlab.com/pricing) 11.6.
@@ -24,3 +28,15 @@ Projects of nested subgroups of a selected template source cannot be used.
Repository and database information that are copied over to each new project are
identical to the data exported with [GitLab's Project Import/Export](../project/settings/import_export.md).
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/group/dependency_proxy/img/group_dependency_proxy.png b/doc/user/group/dependency_proxy/img/group_dependency_proxy.png
new file mode 100644
index 00000000000..035aff0b6c4
--- /dev/null
+++ b/doc/user/group/dependency_proxy/img/group_dependency_proxy.png
Binary files differ
diff --git a/doc/user/group/dependency_proxy/index.md b/doc/user/group/dependency_proxy/index.md
new file mode 100644
index 00000000000..4fc2d8e9509
--- /dev/null
+++ b/doc/user/group/dependency_proxy/index.md
@@ -0,0 +1,74 @@
+# Dependency Proxy **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/7934) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.11.
+
+NOTE: **Note:**
+This is the user guide. In order to use the dependency proxy, an administrator
+must first [configure it](../../../administration/dependency_proxy.md).
+
+For many organizations, it is desirable to have a local proxy for frequently used
+upstream images/packages. In the case of CI/CD, the proxy is responsible for
+receiving a request and returning the upstream image from a registry, acting
+as a pull-through cache.
+
+The dependency proxy is available in the group level. To access it, navigate to
+a group's **Overview > Dependency Proxy**.
+
+![Dependency Proxy group page](img/group_dependency_proxy.png)
+
+## Supported dependency proxies
+
+NOTE: **Note:**
+For a list of the upcoming additions to the proxies, visit the
+[direction page](https://about.gitlab.com/direction/package/dependency_proxy/#top-vision-items).
+
+The following dependency proxies are supported.
+
+| Dependency proxy | GitLab version |
+| ---------------- | -------------- |
+| Docker | 11.11+ |
+
+## Using the Docker dependency proxy
+
+With the Docker dependency proxy, you can use GitLab as a source for a Docker image.
+To get a Docker image into the dependency proxy:
+
+1. Find the proxy URL on your group's page under **Overview > Dependency Proxy**,
+ for example `gitlab.com/groupname/dependency_proxy/containers`.
+1. Trigger GitLab to pull the Docker image you want (e.g., `alpine:latest` or
+ `linuxserver/nextcloud:latest`) and store it in the proxy storage by using
+ one of the following ways:
+
+ - Manually pulling the Docker image:
+
+ ```bash
+ docker pull gitlab.com/groupname/dependency_proxy/containers/alpine:latest
+ ```
+
+ - From a `Dockerfile`:
+
+ ```bash
+ FROM gitlab.com/groupname/dependency_proxy/containers/alpine:latest
+ ```
+
+ - In [`.gitlab-ci.yml`](../../../ci/yaml/README.md#image):
+
+ ```bash
+ image: gitlab.com/groupname/dependency_proxy/containers/alpine:latest
+ ```
+
+GitLab will then pull the Docker image from Docker Hub and will cache the blobs
+on the GitLab server. The next time you pull the same image, it will get the latest
+information about the image from Docker Hub but will serve the existing blobs
+from GitLab.
+
+The blobs are kept forever, and there is no hard limit on how much data can be
+stored.
+
+## Limitations
+
+The following limitations apply:
+
+- Only public groups are supported (authentication is not supported yet).
+- Only Docker Hub is supported.
+- This feature requires Docker Hub being available.
diff --git a/doc/user/group/epics/img/button_close_epic.png b/doc/user/group/epics/img/button_close_epic.png
new file mode 100644
index 00000000000..aa1a889ea23
--- /dev/null
+++ b/doc/user/group/epics/img/button_close_epic.png
Binary files differ
diff --git a/doc/user/group/epics/img/button_reopen_epic.png b/doc/user/group/epics/img/button_reopen_epic.png
new file mode 100644
index 00000000000..7a953189270
--- /dev/null
+++ b/doc/user/group/epics/img/button_reopen_epic.png
Binary files differ
diff --git a/doc/user/group/epics/img/child_epics_roadmap.png b/doc/user/group/epics/img/child_epics_roadmap.png
new file mode 100644
index 00000000000..819fed58989
--- /dev/null
+++ b/doc/user/group/epics/img/child_epics_roadmap.png
Binary files differ
diff --git a/doc/user/group/epics/img/containing_epic.png b/doc/user/group/epics/img/containing_epic.png
new file mode 100644
index 00000000000..5ed693e6d6a
--- /dev/null
+++ b/doc/user/group/epics/img/containing_epic.png
Binary files differ
diff --git a/doc/user/group/epics/img/epic_view.png b/doc/user/group/epics/img/epic_view.png
new file mode 100644
index 00000000000..dbda98e4351
--- /dev/null
+++ b/doc/user/group/epics/img/epic_view.png
Binary files differ
diff --git a/doc/user/group/epics/img/epics_list_view.png b/doc/user/group/epics/img/epics_list_view.png
new file mode 100644
index 00000000000..b30608d9d31
--- /dev/null
+++ b/doc/user/group/epics/img/epics_list_view.png
Binary files differ
diff --git a/doc/user/group/epics/img/epics_search.png b/doc/user/group/epics/img/epics_search.png
new file mode 100644
index 00000000000..96335527468
--- /dev/null
+++ b/doc/user/group/epics/img/epics_search.png
Binary files differ
diff --git a/doc/user/group/epics/img/epics_sort.png b/doc/user/group/epics/img/epics_sort.png
new file mode 100644
index 00000000000..b23c65fd0ef
--- /dev/null
+++ b/doc/user/group/epics/img/epics_sort.png
Binary files differ
diff --git a/doc/user/group/epics/index.md b/doc/user/group/epics/index.md
new file mode 100644
index 00000000000..2e4106f55e5
--- /dev/null
+++ b/doc/user/group/epics/index.md
@@ -0,0 +1,233 @@
+---
+type: reference, howto
+---
+
+# Epics **[ULTIMATE]**
+
+> Introduced in [GitLab Ultimate][ee] 10.2.
+
+Epics let you manage your portfolio of projects more efficiently and with less
+effort by tracking groups of issues that share a theme, across projects and
+milestones.
+
+![epics list view](img/epics_list_view.png)
+
+## Use cases
+
+- Suppose your team is working on a large feature that involves multiple discussions throughout different issues created in distinct projects within a [Group](../index.md). With Epics, you can track all the related activities that together contribute to that single feature.
+- Track when the work for the group of issues is targeted to begin, and when it is targeted to end.
+- Discuss and collaborate on feature ideas and scope at a high-level.
+
+## Creating an epic
+
+A paginated list of epics is available in each group from where you can create
+a new epic. The list of epics includes also epics from all subgroups of the
+selected group. From your group page:
+
+1. Go to **Epics**
+1. Click the **New epic** button at the top right
+1. Enter a descriptive title and hit **Create epic**
+
+Once created, you will be taken to the view for that newly-created epic where
+you can change its title, description, start date, and due date.
+
+![epic view](img/epic_view.png)
+
+## Adding an issue to an epic
+
+An epic contains a list of issues and an issue can be associated with at most
+one epic. When on an epic, you can add its associated issues:
+
+1. Click the plus icon (<kbd>+</kbd>) under the epic description.
+1. Paste the link of the issue (you can hit <kbd>Spacebar</kbd> to add more than
+ one issues at a time).
+1. Click **Add**.
+
+Any issue belonging to a project in the epic's group or any of the epic's
+subgroups are eligible to be added. To remove an issue from an epic, click
+on the <kbd>x</kbd> button in the epic's issue list.
+
+NOTE: **Note:**
+When you add an issue or an epic to an epic that's already associated with another epic,
+the issue or the epic is automatically removed from the previous epic.
+
+## Multi-level child epics
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/8333) in GitLab Ultimate 11.7.
+
+Much like adding issues to an epic, an epic can have multiple child epics with
+the maximum depth being 5. To add a child epic:
+
+1. Click the plus icon (<kbd>+</kbd>) under the epic description.
+1. Paste the link of the epic.
+1. Click **Add**.
+
+Any epic that belongs to a group or subgroup of the parent epic's group is
+eligible to be added. To remove a child epic from a parent epic,
+click on the <kbd>x</kbd> button in the parent epic's epic list.
+
+## Start date and due date
+
+For each of the dates in the sidebar of an epic, you can choose to either:
+
+- Enter a fixed value.
+- Inherit a dynamic value called "From milestones".
+
+If you select "From milestones" for the start date, GitLab will automatically set the
+date to be earliest start date across all milestones that are currently assigned
+to the issues that are attached to the epic. Similarly, if you select "From milestones"
+for the due date, GitLab will set it to be the latest due date across all
+milestones that are currently assigned to those issues.
+
+These are dynamic dates in that if milestones are re-assigned to the issues, if the
+milestone dates change, or if issues are added or removed from the epic, then
+the re-calculation will happen immediately to set a new dynamic date.
+
+## Roadmap in epics
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/7327) in [GitLab Ultimate](https://about.gitlab.com/pricing) 11.10.
+
+If your epic contains one or more [child epics](#multi-level-child-epics) which
+have a [start or due date](#start-date-and-due-date), then you can see a
+[roadmap](../roadmap/index.md) view of the child epics under the parent epic itself.
+
+![Child epics roadmap](img/child_epics_roadmap.png)
+
+## Reordering issues and child epics
+
+Drag and drop to reorder issues and child epics. New issues and child epics added to an epic appear at the top of the list.
+
+## Deleting an epic
+
+NOTE: **Note:**
+To delete an epic, you need to be an [Owner][permissions] of a group/subgroup.
+
+When inside a single epic view, click the **Delete** button to delete the epic.
+A modal will pop-up to confirm your action.
+
+Deleting an epic releases all existing issues from their associated epic in the
+system.
+
+## Closing and reopening epics
+
+### Using buttons
+
+Whenever you decide that there is no longer need for that epic,
+close the epic using the close button:
+
+![close epic - button](img/button_close_epic.png)
+
+You can always reopen it using the reopen button.
+
+![reopen epic - button](img/button_reopen_epic.png)
+
+### Using quick actions
+
+You can close or reopen an epic using [Quick actions](../../project/quick_actions.md)
+
+## Navigating to an epic from an issue
+
+If an issue belongs to an epic, you can navigate to the containing epic with the
+link in the issue sidebar.
+
+![containing epic](img/containing_epic.png)
+
+## Promoting an issue to an epic
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/3777) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.6.
+
+If you have [permissions](../../permissions.md) to close an issue and create an
+epic in the parent group, you can promote an issue to an epic with the `/promote`
+[quick action](../../project/quick_actions.md#quick-actions-for-epics-ultimate).
+Only issues from projects that are in groups can be promoted.
+
+When the quick action is executed:
+
+- An epic is created in the same group as the project of the issue.
+- Subscribers of the issue are notified that the epic was created.
+
+The following issue metadata will be copied to the epic:
+
+- Title, description, activity/comment thread.
+- Upvotes/downvotes.
+- Participants.
+- Group labels that the issue already has.
+
+## Searching for an epic from epics list page
+
+> Introduced in [GitLab Ultimate][ee] 10.5.
+
+You can search for an epic from the list of epics using filtered search bar (similar to
+that of Issues and Merge requests) based on following parameters:
+
+- Title or description
+- Author name / username
+- Labels
+
+![epics search](img/epics_search.png)
+
+To search, go to the list of epics and click on the field **Search or filter results...**.
+It will display a dropdown menu, from which you can add an author. You can also enter plain
+text to search by epic title or description. When done, press <kbd>Enter</kbd> on your
+keyboard to filter the list.
+
+You can also sort epics list by:
+
+- **Created date**
+- **Last updated**
+- **Start date**
+- **Due date**
+
+Each option contains a button that can toggle the order between **ascending** and **descending**. The sort option and order will be persisted to be used wherever epics are browsed including the [roadmap](../roadmap/index.md).
+
+![epics sort](img/epics_sort.png)
+
+## Permissions
+
+If you have access to view an epic and have access to view an issue already
+added to that epic, then you can view the issue in the epic issue list.
+
+If you have access to edit an epic and have access to edit an issue, then you
+can add the issue to or remove it from the epic.
+
+Note that for a given group, the visibility of all projects must be the same as
+the group, or less restrictive. That means if you have access to a group's epic,
+then you already have access to its projects' issues.
+
+You may also consult the [group permissions table][permissions].
+
+[ee]: https://about.gitlab.com/pricing/
+[permissions]: ../../permissions.md#group-members-permissions
+
+## Thread
+
+- Comments: collaborate on that epic by posting comments in its thread.
+These text fields also fully support
+[GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm).
+
+## Comment, or start a discussion
+
+Once you wrote your comment, you can either:
+
+- Click "Comment" and your comment will be published.
+- Click "Start discussion": start a thread within that epic's thread to discuss specific points.
+
+## Award emoji
+
+- You can [award an emoji](../../award_emojis.md) to that epic or its comments.
+
+## Notifications
+
+- [Receive notifications](../../../workflow/notifications.md) for epic events.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/group/img/group_file_template_dropdown.png b/doc/user/group/img/group_file_template_dropdown.png
new file mode 100644
index 00000000000..d9caae1a223
--- /dev/null
+++ b/doc/user/group/img/group_file_template_dropdown.png
Binary files differ
diff --git a/doc/user/group/img/group_file_template_settings.png b/doc/user/group/img/group_file_template_settings.png
new file mode 100644
index 00000000000..ca42f7726db
--- /dev/null
+++ b/doc/user/group/img/group_file_template_settings.png
Binary files differ
diff --git a/doc/user/group/img/member_lock.png b/doc/user/group/img/member_lock.png
new file mode 100644
index 00000000000..3f1382e76c6
--- /dev/null
+++ b/doc/user/group/img/member_lock.png
Binary files differ
diff --git a/doc/user/group/img/membership_lock.png b/doc/user/group/img/membership_lock.png
deleted file mode 100644
index c9ad82c90f2..00000000000
--- a/doc/user/group/img/membership_lock.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/img/new_group_form.png b/doc/user/group/img/new_group_form.png
deleted file mode 100644
index 1c4d3ec6ceb..00000000000
--- a/doc/user/group/img/new_group_form.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index 74735886350..97d309caf7c 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -1,35 +1,51 @@
+---
+type: reference, howto
+---
+
# Groups
-With GitLab Groups you can assemble related projects together
-and grant members access to several projects at once.
+With GitLab Groups, you can:
+
+- Assemble related projects together.
+- Grant members access to several projects at once.
+
+For a video introduction to GitLab Groups, see [GitLab University: Repositories, Projects and Groups](https://www.youtube.com/watch?v=4TWfh1aKHHw).
Groups can also be nested in [subgroups](subgroups/index.md).
-Find your groups by expanding the left menu and clicking **Groups**:
+Find your groups by clicking **Groups > Your Groups** in the top navigation.
![GitLab Groups](img/groups.png)
-The Groups page displays all groups you are a member of, how many projects it holds,
-how many members it has, the group visibility, and, if you have enough permissions,
-a link to the group settings. By clicking the last button you can leave that group.
+> The **Groups** dropdown in the top navigation was [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/36234) in [GitLab 11.1](https://about.gitlab.com/2018/07/22/gitlab-11-1-released/#groups-dropdown-in-navigation).
+
+The **Groups** page displays:
+
+- All groups you are a member of, when **Your groups** is selected.
+- A list of public groups, when **Explore public groups** is selected.
+
+Each group on the **Groups** page is listed with:
+
+- How many subgroups it has.
+- How many projects it contains.
+- How many members the group has, not including members inherited from parent groups.
+- The group's visibility.
+- A link to the group's settings, if you have sufficient permissions.
+- A link to leave the group, if you are a member.
## Use cases
-You can create groups for numerous reasons. To name a few:
-
-- Organize related projects under the same [namespace](#namespaces), add members to that
- group and grant access to all their projects at once
-- Create a group, include members of your team, and make it easier to
- `@mention` all the team at once in issues and merge requests
- - Create a group for your company members, and create [subgroups](subgroups/index.md)
- for each individual team. Let's say you create a group called `company-team`, and among others,
- you created subgroups in this group for each individual team `backend-team`,
- `frontend-team`, and `production-team`:
- 1. When you start a new implementation from an issue, you add a comment:
+You can create groups for numerous reasons. To name a couple:
+
+- Grant access to multiple projects and multiple team members in fewer steps by organizing related projects under the same [namespace](#namespaces) and adding members to the top-level group.
+- Make it easier to `@mention` all of your team at once in issues and merge requests by creating a group and including the appropriate members.
+
+For example, you could create a group for your company members, and create a [subgroup](subgroups/index.md) for each individual team. Let's say you create a group called `company-team`, and you create subgroups in this group for the individual teams `backend-team`, `frontend-team`, and `production-team`.
+ - When you start a new implementation from an issue, you add a comment:
_"`@company-team`, let's do it! `@company-team/backend-team` you're good to go!"_
- 1. When your backend team needs help from frontend, they add a comment:
+ - When your backend team needs help from frontend, they add a comment:
_"`@company-team/frontend-team` could you help us here please?"_
- 1. When the frontend team completes their implementation, they comment:
+ - When the frontend team completes their implementation, they comment:
_"`@company-team/backend-team`, it's done! Let's ship it `@company-team/production-team`!"_
## Namespaces
@@ -44,7 +60,7 @@ For example, consider a user named Alex:
1. Alex creates an account on GitLab.com with the username `alex`;
their profile will be accessed under `https://gitlab.example.com/alex`
-1. Alex creates a group for their team with the groupname `alex-team`;
+1. Alex creates a group for their team with the group name `alex-team`;
the group and its projects will be accessed under `https://gitlab.example.com/alex-team`
1. Alex creates a subgroup of `alex-team` with the subgroup name `marketing`;
this subgroup and its projects will be accessed under `https://gitlab.example.com/alex-team/marketing`
@@ -57,8 +73,8 @@ By doing so:
## Issues and merge requests within a group
-Issues and merge requests are part of projects. For a given group, view all the
-[issues](../project/issues/index.md#issues-list) and [merge requests](../project/merge_requests/index.md#merge-requests-per-group) across all the projects in that group,
+Issues and merge requests are part of projects. For a given group, you can view all of the
+[issues](../project/issues/index.md#issues-list) and [merge requests](../project/merge_requests/index.md#merge-requests-per-group) across all projects in that group,
together in a single list view.
## Create a new group
@@ -66,13 +82,13 @@ together in a single list view.
> For a list of words that are not allowed to be used as group names see the
> [reserved names](../reserved_names.md).
-You can create a group in GitLab from:
+To create a new Group, either:
-1. The Groups page: expand the left menu, click **Groups**, and click the green button **New group**:
+- In the top menu, click **Groups** and then **Your Groups**, and click the green button **New group**.
![new group from groups page](img/new_group_from_groups.png)
-1. Elsewhere: expand the `plus` sign button on the top navbar and choose **New group**:
+- Or, in the top menu, expand the `plus` sign and choose **New group**.
![new group from elsewhere](img/new_group_from_other_pages.png)
@@ -80,57 +96,60 @@ Add the following information:
![new group info](img/create_new_group_info.png)
-1. Set the **Group path** which will be the **namespace** under which your projects
- will be hosted (path can contain only letters, digits, underscores, dashes
- and dots; it cannot start with dashes or end in dot).
-1. The **Group name** will populate with the path. Optionally, you can change
- it. This is the name that will display in the group views.
-1. Optionally, you can add a description so that others can briefly understand
+1. The **Group name** will automatically populate the URL. Optionally, you can change it.
+ This is the name that displays in group views.
+ The name can contain only:
+ - Alphanumeric characters
+ - Underscores
+ - Dashes and dots
+ - Spaces
+1. The **Group URL** is the namespace under which your projects will be hosted.
+ The URL can contain only:
+ - Alphanumeric characters
+ - Underscores
+ - Dashes and dots (it cannot start with dashes or end in a dot)
+1. Optionally, you can add a brief description to tell others
what this group is about.
-1. Optionally, choose an avatar for your project.
+1. Optionally, choose an avatar for your group.
1. Choose the [visibility level](../../public_access/public_access.md).
+For more details on creating groups, watch the video [GitLab Namespaces (users, groups and subgroups)](https://youtu.be/r0sJgjR2f5A).
+
## Add users to a group
-Add members to a group by navigating to the group's dashboard, and clicking **Members**:
+A benefit of putting multiple projects in one group is that you can
+give a user to access to all projects in the group with one action.
+
+Add members to a group by navigating to the group's dashboard and clicking **Members**.
![add members to group](img/add_new_members.png)
-Select the [permission level](../permissions.md#permissions) and add the new member. You can also set the expiring
-date for that user, from which they will no longer have access to your group.
-
-One of the benefits of putting multiple projects in one group is that you can
-give a user to access to all projects in the group with one action.
+Select the [permission level](../permissions.md#permissions), and add the new member. You can also set the expiring date for that user; this is the date on which they will no longer have access to your group.
-Consider we have a group with two projects:
+Consider a group with two projects:
-- On the **Group Members** page we can now add a new user to the group.
-- Now because this user is a **Developer** member of the group, he automatically
+- On the **Group Members** page, you can now add a new user to the group.
+- Now, because this user is a **Developer** member of the group, they automatically
gets **Developer** access to **all projects** within that group.
-If necessary, you can increase the access level of an individual user for a specific project,
-by adding them again as a new member to the project with the new permission levels.
+To increase the access level of an existing user for a specific project,
+add them again as a new member to the project with the desired permission level.
## Request access to a group
-As a group owner you can enable or disable non members to request access to
-your group. Go to the group settings and click on **Allow users to request access**.
+As a group owner, you can enable or disable the ability for non members to request access to
+your group. Go to the group settings, and click **Allow users to request access**.
-As a user, you can request to be a member of a group. Go to the group you'd
-like to be a member of, and click the **Request Access** button on the right
+As a user, you can request to be a member of a group, if that setting is enabled. Go to the group for which you'd like to be a member, and click the **Request Access** button on the right
side of your screen.
![Request access button](img/request_access_button.png)
----
-
Group owners and maintainers will be notified of your request and will be able to approve or
decline it on the members page.
![Manage access requests](img/access_requests_management.png)
----
-
If you change your mind before your request is approved, just click the
**Withdraw Access Request** button.
@@ -140,25 +159,27 @@ If you change your mind before your request is approved, just click the
There are two different ways to add a new project to a group:
-- Select a group and then click on the **New project** button.
+- Select a group, and then click **New project**. You can then continue [creating your project](../../gitlab-basics/create-project.md).
![New project](img/create_new_project_from_group.png)
- You can then continue on [creating a project](../../gitlab-basics/create-project.md).
-
- While you are creating a project, select a group namespace
you've already created from the dropdown menu.
![Select group](img/select_group_dropdown.png)
-### Default project creation level
+### Default project-creation level
+
+> [Introduced][ee-2534] in [GitLab Premium][ee] 10.5.
+> Brought to [GitLab Starter][ee] in 10.7.
+> [Moved](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/25975) to [GitLab Core](https://about.gitlab.com/pricing/) in 11.10.
-Group owners or administrators can allow users with the
+Group owners and administrators can allow users with the
Developer role to create projects under groups.
-By default, [Developers and Maintainers](../permissions.md#group-members-permissions) can create projects under agroup, but this can be changed either within the group settings for a group, or
-be set globally by a GitLab administrator in the Admin area
-at **Settings > General > Visibility and access controls**.
+By default, [Developers and Maintainers](../permissions.md#group-members-permissions) can create projects under a group. You can change this setting for a specific group within the group settings, or
+you can set this option globally in the Admin area
+at **Settings > General > Visibility and access controls** (you must be a GitLab administrator).
Available settings are `No one`, `Maintainers`, or `Developers + Maintainers`.
@@ -169,41 +190,69 @@ Learn how to [transfer a project into a group](../project/settings/index.md#tran
## Sharing a project with a group
You can [share your projects with a group](../project/members/share_project_with_groups.md)
-and give your group members access to the project all at once.
+and give all group members access to the project at once.
Alternatively, you can [lock the sharing with group feature](#share-with-group-lock).
## Manage group memberships via LDAP
-In GitLab Enterprise Edition it is possible to manage GitLab group memberships using LDAP groups.
+In GitLab Enterprise Edition, it is possible to manage GitLab group memberships using LDAP groups.
See [the GitLab Enterprise Edition documentation](../../integration/ldap.md) for more information.
+## Epics **[ULTIMATE]**
+
+> Introduced in [GitLab Ultimate][ee] 10.2.
+
+Epics let you manage your portfolio of projects more efficiently and with less
+effort by tracking groups of issues that share a theme, across projects and
+milestones.
+
+[Learn more about Epics.](epics/index.md)
+
+## Group Security Dashboard **[ULTIMATE]**
+
+Get an overview of the vulnerabilities of all the projects in a group and its subgroups.
+
+[Learn more about the Group Security Dashboard.](security_dashboard/index.md)
+
+## Insights **[ULTIMATE]**
+
+Configure the Insights that matter for your groups or projects, allowing users
+to explore data such as:
+
+- Triage hygiene
+- Issues created/closed per a given period
+- Average time for merge requests to be merged
+- Much more
+
+[Learn more about Insights](insights/index.md).
+
## Transferring groups
-From GitLab 10.5, groups can be transferred in the following ways:
+From GitLab 10.5, you can transfer groups in the following ways:
-- Top-level groups can be transferred to a group, converting them into subgroups.
-- Subgroups can be transferred to a new parent group.
-- Subgroups can be transferred out from a parent group, converting them into top-level groups.
+- Transfer a subgroup to a new parent group.
+- Convert a top-level group into a subgroup by transferring it to the desired group.
+- Convert a subgroup into a top-level group by transferring it out of its current group.
When transferring groups, note:
- Changing a group's parent can have unintended side effects. See [Redirects when changing repository paths](../project/index.md#redirects-when-changing-repository-paths).
- You can only transfer groups to groups you manage.
-- You will need to update your local repositories to point to the new location.
-- If the parent group's visibility is lower than the group's current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility.
-- Only explicit group membership is transferred, not inherited membership. If the group's owners have only inherited membership, this would leave the group without an owner. In this case, the user transferring the group becomes the group's owner.
+- You must update your local repositories to point to the new location.
+- If the parent group's visibility is lower than the group's current visibility, visibility levels for subgroups and projects will change to match the new parent group's visibility.
+- Only explicit group membership is transferred, not inherited membership. If the group's owners have only inherited membership, this leaves the group without an owner. In this case, the user transferring the group becomes the group's owner.
## Group settings
-Once you have created a group, you can manage its settings by navigating to
+After creating a group, you can manage its settings by navigating to
the group's dashboard, and clicking **Settings**.
![group settings](img/group_settings.png)
### General settings
-Besides giving you the option to edit any settings you've previously
+In addition to editing any settings you previously
set when [creating the group](#create-a-new-group), you can also
access further configurations for your group.
@@ -214,14 +263,14 @@ Changing a group's path can have unintended side effects. Read
before proceeding.
If you are vacating the path so it can be claimed by another group or user,
-you may need to rename the group name as well since both names and paths must
+you may need to rename the group, too, since both names and paths must
be unique.
To change your group path:
1. Navigate to your group's **Settings > General**.
-1. Enter a new name under "Group path".
-1. Hit **Save group**.
+1. Enter a new name under **Group path**.
+1. Click **Save group**.
CAUTION: **Caution:**
It is currently not possible to rename a namespace if it contains a
@@ -237,20 +286,17 @@ username, you can create a new group and transfer projects to it.
Add a security layer to your group by
[enforcing two-factor authentication (2FA)](../../security/two_factor_authentication.md#enforcing-2fa-for-all-users-in-a-group)
-to all group members.
+for all group members.
#### Share with group lock
Prevent projects in a group from [sharing
-a project with another group](../project/members/share_project_with_groups.md).
-This allows for tighter control over project access.
+a project with another group](../project/members/share_project_with_groups.md) to enable tighter control over project access.
-For example, consider you have two distinct teams (Group A and Group B)
-working together in a project.
-To inherit the group membership, you share the project between the
+For example, let's say you have two distinct teams (Group A and Group B) working together in a project, and to inherit the group membership, you share the project between the
two groups A and B. **Share with group lock** prevents any project within
-the group from being shared with another group. By doing so, you
-guarantee only the right group members have access to that projects.
+the group from being shared with another group,
+guaranteeing that only the right group members have access to those projects.
To enable this feature, navigate to the group settings page. Select
**Share with group lock** and **Save the group**.
@@ -259,29 +305,88 @@ To enable this feature, navigate to the group settings page. Select
#### Member Lock **[STARTER]**
-With **Member Lock** it is possible to lock membership in project to the
-level of members in group.
+Member lock lets a group owner prevent any new project membership to all of the
+projects within a group, allowing tighter control over project membership.
+
+For example, if you want to lock the group for an [Audit Event](../../administration/audit_events.md),
+enable Member lock to guarantee that project membership cannot be modified during that audit.
+
+To enable this feature:
+
+1. Navigate to the group's **Settings > General** page.
+1. Expand the **Permissions, LFS, 2FA** section, and select **Member lock**.
+1. Click **Save changes**.
+
+![Checkbox for membership lock](img/member_lock.png)
+
+This will disable the option for all users who previously had permissions to
+operate project memberships, so no new users can be added. Furthermore, any
+request to add a new user to a project through API will not be possible.
+
+#### Group file templates **[PREMIUM]**
-Learn more about [Member Lock](https://docs.gitlab.com/ee/user/group/index.html#member-lock).
+Group file templates allow you to share a set of templates for common file
+types with every project in a group. It is analogous to the
+[instance template repository](../admin_area/settings/instance_template_repository.md)
+feature, and the selected project should follow the same naming conventions as
+are documented on that page.
-#### Group-level file templates **[PREMIUM]**
+You can only choose projects in the group as the template source.
+This includes projects shared with the group, but it **excludes** projects in
+subgroups or parent groups of the group being configured.
-Group-level file templates allow you to share a set of templates for common file
-types with every project in a group.
+You can configure this feature for both subgroups and parent groups. A project
+in a subgroup will have access to the templates for that subgroup, as well as
+any parent groups.
-Learn more about [Group-level file templates](https://docs.gitlab.com/ee/user/group/index.html#group-level-file-templates-premium).
+![Group file template dropdown](img/group_file_template_dropdown.png)
+
+To enable this feature, navigate to the group settings page, expand the
+**Templates** section, choose a project to act as the template repository, and
+**Save group**.
+
+![Group file template settings](img/group_file_template_settings.png)
#### Group-level project templates **[PREMIUM]**
-Define project templates at a group-level by setting a group as a template source.
+Define project templates at a group level by setting a group as the template source.
[Learn more about group-level project templates](custom_project_templates.md).
### Advanced settings
-- **Projects**: view all projects within that group, add members to each project,
- access each project's settings, and remove any project from the same screen.
-- **Webhooks**: configure [webhooks](../project/integrations/webhooks.md) to your group.
-- **Kubernetes cluster integration**: connect your GitLab group with [Kubernetes clusters](clusters/index.md).
-- **Audit Events**: view [Audit Events](https://docs.gitlab.com/ee/administration/audit_events.html#audit-events)
+- **Projects**: View all projects within that group, add members to each project,
+ access each project's settings, and remove any project, all from the same screen.
+- **Webhooks**: Configure [webhooks](../project/integrations/webhooks.md) for your group.
+- **Kubernetes cluster integration**: Connect your GitLab group with [Kubernetes clusters](clusters/index.md).
+- **Audit Events**: View [Audit Events](../../administration/audit_events.md)
for the group. **[STARTER ONLY]**
-- **Pipelines quota**: keep track of the [pipeline quota](../admin_area/settings/continuous_integration.md) for the group.
+- **Pipelines quota**: Keep track of the [pipeline quota](../admin_area/settings/continuous_integration.md) for the group.
+
+## User contribution analysis **[STARTER]**
+
+With [GitLab Contribution Analytics](contribution_analytics/index.md),
+you have an overview of the contributions (pushes, merge requests,
+and issues) performed by your group members.
+
+## Issues analytics **[PREMIUM]**
+
+With [GitLab Issues Analytics](issues_analytics/index.md), you can see a bar chart of the number of issues created each month in your groups.
+
+## Dependency Proxy **[PREMIUM]**
+
+Use GitLab as a [dependency proxy](dependency_proxy/index.md) for upstream Docker images.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
+
+[ee]: https://about.gitlab.com/pricing/
+[ee-2534]: https://gitlab.com/gitlab-org/gitlab-ee/issues/2534
diff --git a/doc/user/group/insights/img/insights_example_stacked_bar_chart.png b/doc/user/group/insights/img/insights_example_stacked_bar_chart.png
new file mode 100644
index 00000000000..791d0e4bcdf
--- /dev/null
+++ b/doc/user/group/insights/img/insights_example_stacked_bar_chart.png
Binary files differ
diff --git a/doc/user/group/insights/img/insights_group_configuration.png b/doc/user/group/insights/img/insights_group_configuration.png
new file mode 100644
index 00000000000..0af0073e448
--- /dev/null
+++ b/doc/user/group/insights/img/insights_group_configuration.png
Binary files differ
diff --git a/doc/user/group/insights/img/insights_sidebar_link.png b/doc/user/group/insights/img/insights_sidebar_link.png
new file mode 100644
index 00000000000..64bbd1fc4d3
--- /dev/null
+++ b/doc/user/group/insights/img/insights_sidebar_link.png
Binary files differ
diff --git a/doc/user/group/insights/index.md b/doc/user/group/insights/index.md
new file mode 100644
index 00000000000..1aba5d0986b
--- /dev/null
+++ b/doc/user/group/insights/index.md
@@ -0,0 +1,58 @@
+---
+type: reference, howto
+---
+
+# Insights **[ULTIMATE]**
+
+> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.9 behind the `insights` feature flag.
+> **Generally Available** (GA) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0.
+
+Configure the Insights that matter for your groups to explore data such as
+triage hygiene, issues created/closed per a given period, average time for merge
+requests to be merged and much more.
+
+![Insights example stacked bar chart](img/insights_example_stacked_bar_chart.png)
+
+## View your group's Insights
+
+You can access your group's Insights by clicking the **Overview > Insights**
+link in the left sidebar:
+
+![Insights sidebar link](img/insights_sidebar_link.png)
+
+## Configure your Insights
+
+Navigate to your group's **Settings > General**, expand **Insights**, and choose
+the project that holds your `.gitlab/insights.yml` configuration file:
+
+![group insights configuration](img/insights_group_configuration.png)
+
+If no configuration was set, a [default configuration file](
+https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/fixtures/insights/default.yml)
+will be used.
+
+See the [Project's Insights documentation](../../project/insights/index.md) for
+more details about the `.gitlab/insights.yml` configuration file.
+
+## Permissions
+
+If you have access to view a group, then you have access to view their Insights.
+
+NOTE: **Note:**
+Issues or merge requests that you don't have access to (because you don't have
+access to the project they belong to, or because they are confidential) are
+filtered out of the Insights charts.
+
+You may also consult the [group permissions table](../../permissions.md#group-members-permissions).
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/group/issues_analytics/img/issues_created_per_month.png b/doc/user/group/issues_analytics/img/issues_created_per_month.png
new file mode 100644
index 00000000000..96f0d36c917
--- /dev/null
+++ b/doc/user/group/issues_analytics/img/issues_created_per_month.png
Binary files differ
diff --git a/doc/user/group/issues_analytics/index.md b/doc/user/group/issues_analytics/index.md
new file mode 100644
index 00000000000..46d5c1e2e09
--- /dev/null
+++ b/doc/user/group/issues_analytics/index.md
@@ -0,0 +1,43 @@
+---
+type: reference
+---
+
+# Issues Analytics **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/7478) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.5.
+
+Issues Analytics is a bar graph which illustrates the number of issues created each month.
+The default timespan is 13 months, which includes the current month, and the 12 months
+prior.
+
+To access the chart, navigate to a group's sidebar and select **Issues > Analytics**.
+
+Hover over each bar to see the total number of issues.
+
+To narrow the scope of issues included in the graph, enter your criteria in the
+**Search or filter results...** field. Criteria from the following list can be typed in or selected from a menu:
+
+- Author
+- Assignee
+- Milestone
+- Label
+- My reaction
+- Weight
+
+You can change the total number of months displayed by setting a URL parameter.
+For example, `https://gitlab.com/groups/gitlab-org/-/issues_analytics?months_back=15`
+shows a total of 15 months for the chart in the GitLab.org group.
+
+![Issues created per month](img/issues_created_per_month.png)
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/group/roadmap/img/epics_state_dropdown.png b/doc/user/group/roadmap/img/epics_state_dropdown.png
new file mode 100644
index 00000000000..cbcc3658a54
--- /dev/null
+++ b/doc/user/group/roadmap/img/epics_state_dropdown.png
Binary files differ
diff --git a/doc/user/group/roadmap/img/roadmap_timeline_months.png b/doc/user/group/roadmap/img/roadmap_timeline_months.png
new file mode 100644
index 00000000000..5a046b21507
--- /dev/null
+++ b/doc/user/group/roadmap/img/roadmap_timeline_months.png
Binary files differ
diff --git a/doc/user/group/roadmap/img/roadmap_timeline_quarters.png b/doc/user/group/roadmap/img/roadmap_timeline_quarters.png
new file mode 100644
index 00000000000..56f428cb471
--- /dev/null
+++ b/doc/user/group/roadmap/img/roadmap_timeline_quarters.png
Binary files differ
diff --git a/doc/user/group/roadmap/img/roadmap_timeline_weeks.png b/doc/user/group/roadmap/img/roadmap_timeline_weeks.png
new file mode 100644
index 00000000000..bf4c1dc0284
--- /dev/null
+++ b/doc/user/group/roadmap/img/roadmap_timeline_weeks.png
Binary files differ
diff --git a/doc/user/group/roadmap/img/roadmap_view.png b/doc/user/group/roadmap/img/roadmap_view.png
new file mode 100644
index 00000000000..ff41a2e0441
--- /dev/null
+++ b/doc/user/group/roadmap/img/roadmap_view.png
Binary files differ
diff --git a/doc/user/group/roadmap/index.md b/doc/user/group/roadmap/index.md
new file mode 100644
index 00000000000..683c715c8d5
--- /dev/null
+++ b/doc/user/group/roadmap/index.md
@@ -0,0 +1,87 @@
+---
+type: reference
+---
+
+# Roadmap **[ULTIMATE]**
+
+> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing) 10.5.
+
+An Epic within a group containing **Start date** and/or **Due date**
+can be visualized in a form of a timeline (e.g. a Gantt chart). The Epics Roadmap page
+shows such a visualization for all the epics which are under a group and/or its subgroups.
+
+![roadmap view](img/roadmap_view.png)
+
+A dropdown allows you to show only open or closed epics. By default, all epics are shown.
+
+![epics state dropdown](img/epics_state_dropdown.png)
+
+Epics in the view can be sorted by:
+
+- **Created date**
+- **Last updated**
+- **Start date**
+- **Due date**
+
+Each option contains a button that toggles the sort order between **ascending** and **descending**. The sort option and order will be persisted when browsing Epics,
+including the [epics list view](../epics/index.md).
+
+Roadmaps can also be [visualized inside an epic](../epics/index.md#roadmap-in-epics).
+
+## Timeline duration
+
+> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing) 11.0.
+
+Roadmap supports the following date ranges:
+
+- Quarters
+- Months (Default)
+- Weeks
+
+### Quarters
+
+![roadmap date range in quarters](img/roadmap_timeline_quarters.png)
+
+In _Quarters_ preset, roadmap shows epics which have start or due dates _falling within_ or
+_going through_ **past quarter**, **current quarter** and **next 4 quarters**, where _today_
+is shown by the vertical red line in the timeline. The sub-headers underneath the quarter name on
+the timeline header represent the month of the quarter.
+
+### Months
+
+![roadmap date range in months](img/roadmap_timeline_months.png)
+
+In _Months_ preset, roadmap shows epics which have start or due dates _falling within_ or
+_going through_ **past month**, **current month** and **next 5 months**, where _today_
+is shown by the vertical red line in the timeline. The sub-headers underneath the month name on
+the timeline header represent the date on starting day (Sunday) of the week. This preset is
+selected by default.
+
+### Weeks
+
+![roadmap date range in weeks](img/roadmap_timeline_weeks.png)
+
+In _Weeks_ preset, roadmap shows epics which have start or due dates _falling within_ or
+_going through_ **past week**, **current week** and **next 4 weeks**, where _today_
+is shown by the vertical red line in the timeline. The sub-headers underneath the week name on
+the timeline header represent the days of the week.
+
+## Timeline bar for an epic
+
+The timeline bar indicates the approximate position of an epic based on its start
+and due date. If an epic doesn't have a due date, the timeline bar fades
+away towards the future. Similarly, if an epic doesn't have a start date, the
+timeline bar becomes more visible as it approaches the epic's due date on the
+timeline.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/group/saml_sso/img/group_saml_configuration_information.png b/doc/user/group/saml_sso/img/group_saml_configuration_information.png
new file mode 100644
index 00000000000..98b83d0cb0f
--- /dev/null
+++ b/doc/user/group/saml_sso/img/group_saml_configuration_information.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/group_saml_settings.png b/doc/user/group/saml_sso/img/group_saml_settings.png
new file mode 100644
index 00000000000..d95acb5075f
--- /dev/null
+++ b/doc/user/group/saml_sso/img/group_saml_settings.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/scim_advanced.png b/doc/user/group/saml_sso/img/scim_advanced.png
new file mode 100644
index 00000000000..3b70e3fbe83
--- /dev/null
+++ b/doc/user/group/saml_sso/img/scim_advanced.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/scim_attribute_mapping.png b/doc/user/group/saml_sso/img/scim_attribute_mapping.png
new file mode 100644
index 00000000000..c9f6b71f5b0
--- /dev/null
+++ b/doc/user/group/saml_sso/img/scim_attribute_mapping.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/scim_token.png b/doc/user/group/saml_sso/img/scim_token.png
new file mode 100644
index 00000000000..7eb52bf6ea2
--- /dev/null
+++ b/doc/user/group/saml_sso/img/scim_token.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/unlink_group_saml.png b/doc/user/group/saml_sso/img/unlink_group_saml.png
new file mode 100644
index 00000000000..0561443b5f4
--- /dev/null
+++ b/doc/user/group/saml_sso/img/unlink_group_saml.png
Binary files differ
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
new file mode 100644
index 00000000000..fcfd638f185
--- /dev/null
+++ b/doc/user/group/saml_sso/index.md
@@ -0,0 +1,140 @@
+---
+type: reference, howto
+---
+
+# SAML SSO for GitLab.com Groups **[SILVER ONLY]**
+
+> Introduced in [GitLab.com Silver](https://about.gitlab.com/pricing/) 11.0.
+
+NOTE: **Note:**
+This topic is for SAML on GitLab.com Silver tier and above. For SAML on self-managed GitLab instances, see [SAML OmniAuth Provider](../../../integration/saml.md).
+
+SAML on GitLab.com allows users to be automatically added to a group, and then allows those users to sign into GitLab.com. Users should already have an account on the GitLab instance, or can create one when logging in for the first time.
+
+User synchronization for GitLab.com is partially supported using [SCIM](scim_setup.md).
+
+NOTE: **Note:**
+SAML SSO for GitLab.com groups does not sync users between providers without using SCIM. If a group is not using SCIM, group Owners will still need to manage user accounts (for example, removing users when necessary).
+
+## Configuring your Identity Provider
+
+1. Navigate to the group and click **Settings > SAML SSO**.
+1. Configure your SAML server using the **Assertion consumer service URL** and **Identifier**. Alternatively GitLab provides [metadata XML configuration](#metadata-configuration). See [your identity provider's documentation](#providers) for more details.
+1. Configure the SAML response to include a NameID that uniquely identifies each user.
+1. Configure required assertions using the [table below](#assertions).
+1. Once the identity provider is set up, move on to [configuring GitLab](#configuring-gitlab).
+
+![Issuer and callback for configuring SAML identity provider with GitLab.com](img/group_saml_configuration_information.png)
+
+### SSO enforcement
+
+SSO enforcement was:
+
+- [Introduced in GitLab 11.8](https://gitlab.com/gitlab-org/gitlab-ee/issues/5291).
+- [Improved upon in GitLab 11.11 with ongoing enforcement in the GitLab UI](https://gitlab.com/gitlab-org/gitlab-ee/issues/9255).
+
+With this option enabled, users must use your group's GitLab single sign on URL to be added to the group or be added via SCIM. Users cannot be added manually, and may only access project/group resources via the UI by signing in through the SSO URL.
+
+We intend to add a similar SSO requirement for [Git and API activity](https://gitlab.com/gitlab-org/gitlab-ee/issues/9152) in the future.
+
+### NameID
+
+GitLab.com uses the SAML NameID to identify users. The NameID element:
+
+- Is a required field in the SAML response.
+- Must be unique to each user.
+- Must be a persistent value that will never change, such as a unique ID or username. Email could also be used as the NameID, but only if it can be guaranteed to never change.
+
+### Assertions
+
+| Field | Supported keys |
+|-------|----------------|
+| Email (required)| `email`, `mail` |
+| Full Name | `name` |
+| First Name | `first_name`, `firstname`, `firstName` |
+| Last Name | `last_name`, `lastname`, `lastName` |
+
+## Metadata configuration
+
+GitLab provides metadata XML that can be used to configure your Identity Provider.
+
+1. Navigate to the group and click **Settings > SAML SSO**.
+1. Copy the provided **GitLab metadata URL**
+1. Follow your Identity Provider's documentation and paste the metadata URL when it is requested.
+
+## Configuring GitLab
+
+Once you've set up your identity provider to work with GitLab, you'll need to configure GitLab to use it for authentication:
+
+1. Navigate to the group's **Settings > SAML SSO**.
+1. Find the SSO URL from your Identity Provider and enter it the **Identity provider single sign on URL** field.
+1. Find and enter the fingerprint for the SAML token signing certificate in the **Certificate** field.
+1. Check the **Enable SAML authentication for this group** checkbox.
+1. Click the **Save changes** button.
+
+![Group SAML Settings for GitLab.com](img/group_saml_settings.png)
+
+## Providers
+
+| Provider | Documentation |
+|----------|---------------|
+| ADFS (Active Directory Federation Services) | [Create a Relying Party Trust](https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust) |
+| Azure | [Configuring single sign-on to applications](https://docs.microsoft.com/en-us/azure/active-directory/active-directory-saas-custom-apps) |
+| Auth0 | [Auth0 as Identity Provider](https://auth0.com/docs/protocols/saml/saml-idp-generic) |
+| G Suite | [Set up your own custom SAML application](https://support.google.com/a/answer/6087519?hl=en) |
+| JumpCloud | [Single Sign On (SSO) with GitLab](https://support.jumpcloud.com/customer/en/portal/articles/2810701-single-sign-on-sso-with-gitlab) |
+| Okta | [Setting up a SAML application in Okta](https://developer.okta.com/standards/SAML/setting_up_a_saml_application_in_okta) |
+| OneLogin | [Use the OneLogin SAML Test Connector](https://onelogin.service-now.com/support?id=kb_article&sys_id=93f95543db109700d5505eea4b96198f) |
+| Ping Identity | [Add and configure a new SAML application](https://docs.pingidentity.com/bundle/p1_enterpriseConfigSsoSaml_cas/page/enableAppWithoutURL.html) |
+
+## Linking SAML to your existing GitLab.com account
+
+To link SAML to your existing GitLab.com account:
+
+1. Sign in to your GitLab.com account.
+1. Locate the SSO URL for the group you are signing in to. A group Admin can find this on the group's **Settings > SAML SSO** page.
+1. Visit the SSO URL and click **Authorize**.
+1. Enter your credentials on the Identity Provider if prompted.
+1. You will be redirected back to GitLab.com and should now have access to the group. In the future, you can use SAML to sign in to GitLab.com.
+
+## Signing in to GitLab.com with SAML
+
+1. Locate the SSO URL for the group you are signing in to. A group Admin can find this on a group's **Settings > SAML SSO** page. If configured, it might also be possible to sign in to GitLab starting from your Identity Provider.
+1. Visit the SSO URL and click the **Sign in with Single Sign-On** button.
+1. Enter your credentials on the Identity Provider if prompted.
+1. You will be signed in to GitLab.com and redirected to the group.
+
+## Unlinking accounts
+
+Users can unlink SAML for a group from their profile page. This can be helpful if:
+
+- You no longer want a group to be able to sign you in to GitLab.com.
+- Your SAML NameID has changed and so GitLab can no longer find your user.
+
+For example, to unlink the `MyOrg` account, the following **Disconnect** button will be available under **Profile > Accounts**:
+
+![Unlink Group SAML](img/unlink_group_saml.png)
+
+## Glossary
+
+| Term | Description |
+|------|-------------|
+| Identity Provider | The service which manages your user identities such as ADFS, Okta, Onelogin or Ping Identity. |
+| Service Provider | SAML considers GitLab to be a service provider. |
+| Assertion | A piece of information about a user's identity, such as their name or role. Also know as claims or attributes. |
+| SSO | Single Sign On. |
+| Assertion consumer service URL | The callback on GitLab where users will be redirected after successfully authenticating with the identity provider. |
+| Issuer | How GitLab identifies itself to the identity provider. Also known as a "Relying party trust identifier". |
+| Certificate fingerprint | Used to confirm that communications over SAML are secure by checking that the server is signing communications with the correct certificate. Also known as a certificate thumbprint. |
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md
new file mode 100644
index 00000000000..96cc523f4ec
--- /dev/null
+++ b/doc/user/group/saml_sso/scim_setup.md
@@ -0,0 +1,122 @@
+---
+type: howto, reference
+---
+
+# SCIM provisioning using SAML SSO for Groups **[SILVER ONLY]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9388) in [GitLab.com Silver](https://about.gitlab.com/pricing/) 11.10.
+
+System for Cross-domain Identity Management (SCIM), is an open standard that enables the
+automation of user provisioning. When SCIM is provisioned for a GitLab group, membership of
+that group is synchronized between GitLab and the identity provider.
+
+GitLab's [SCIM API](../../../api/scim.md) implements part of [the RFC7644 protocol](https://tools.ietf.org/html/rfc7644).
+
+Currently, the following actions are available:
+
+- CREATE
+- UPDATE
+- DELETE (deprovisioning)
+
+The following identity providers are supported:
+
+- Azure
+
+## Requirements
+
+- [Group SSO](index.md) needs to be configured.
+- The `scim_group` feature flag must be enabled:
+
+ Run the following commands in a Rails console:
+
+ ```sh
+ # Omnibus GitLab
+ gitlab-rails console
+
+ # Installation from source
+ cd /home/git/gitlab
+ sudo -u git -H bin/rails console RAILS_ENV=production
+ ```
+
+ To enable SCIM for a group named `group_name`:
+
+ ```ruby
+ group = Group.find_by_full_path('group_name')
+ Feature.enable(:group_scim, group)
+ ```
+
+### GitLab configuration
+
+Once [Single sign-on](index.md) has been configured, we can:
+
+1. Navigate to the group and click **Settings > SAML SSO**.
+1. Click on the **Generate a SCIM token** button.
+1. Save the token and URL so they can be used in the next step.
+
+![SCIM token configuration](img/scim_token.png)
+
+## SCIM IdP configuration
+
+### Configuration on Azure
+
+In the [Single sign-on](index.md) configuration for the group, make sure
+that the **Name identifier value** (NameID) points to a unique identifier, such
+as the `user.objectid`. This will match the `extern_uid` used on GitLab.
+
+The GitLab app in Azure needs to be configured following
+[Azure's SCIM setup](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/use-scim-to-provision-users-and-groups#getting-started).
+
+Note the following:
+
+- The `Tenant URL` and `secret token` are the ones retrieved in the
+[previous step](#gitlab-configuration).
+- Should there be any problems with the availability of GitLab or similar
+errors, the notification email set will get those.
+- For mappings, we will only leave `Synchronize Azure Active Directory Users to AppName` enabled.
+
+You can then test the connection clicking on `Test Connection`.
+
+### Synchronize Azure Active Directory users
+
+1. Click on `Synchronize Azure Active Directory Users to AppName`, to configure
+the attribute mapping.
+1. Select the unique identifier (in the example `objectId`) as the `id` and `externalId`,
+and enable the `Create`, `Update`, and `Delete` actions.
+1. Map the `userPricipalName` to `emails[type eq "work"].value` and `mailNickname` to
+`userName`.
+
+ Example configuration:
+
+ ![Azure's attribute mapping configuration](img/scim_attribute_mapping.png)
+
+1. Click on **Show advanced options > Edit attribute list for AppName**.
+1. Leave the `id` as the primary and only required field.
+
+ NOTE: **Note:**
+ `username` should neither be primary nor required as we don't support
+ that field on GitLab SCIM yet.
+
+ ![Azure's attribute advanced configuration](img/scim_advanced.png)
+
+1. Save all the screens and, in the **Provisioning** step, set
+the `Provisioning Status` to `ON`.
+
+ NOTE: **Note:**
+ You can control what is actually synced by selecting the `Scope`. For example,
+ `Sync only assigned users and groups` will only sync the users assigned to
+ the application (`Users and groups`), otherwise it will sync the whole Active Directory.
+
+Once enabled, the synchronization details and any errors will appear on the
+bottom of the **Provisioning** screen, together with a link to the audit logs.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/group/security_dashboard/index.md b/doc/user/group/security_dashboard/index.md
new file mode 100644
index 00000000000..c59198df081
--- /dev/null
+++ b/doc/user/group/security_dashboard/index.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../../application_security/security_dashboard/index.md'
+---
+
+This document was moved to [another location](../../application_security/security_dashboard/index.md).
diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md
index 4e81e28a45a..79ae94dd9ef 100644
--- a/doc/user/group/subgroups/index.md
+++ b/doc/user/group/subgroups/index.md
@@ -1,11 +1,17 @@
+---
+type: reference, howto, concepts
+---
+
# Subgroups
NOTE: **Note:**
[Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/2772) in GitLab 9.0. Not available when using MySQL as external
database (support removed in GitLab 9.3 [due to performance reasons](https://gitlab.com/gitlab-org/gitlab-ce/issues/30472#note_27747600)).
-With subgroups (aka nested groups or hierarchical groups) you can have
-up to 20 levels of nested groups, which among other things can help you to:
+Subgroups, also known as nested groups or hierarchical groups, allow you to have up to 20
+levels of groups.
+
+By using subgroups you can do the following:
- **Separate internal / external organizations.** Since every group
can have its own visibility level, you are able to host groups for different
@@ -17,8 +23,9 @@ up to 20 levels of nested groups, which among other things can help you to:
## Database Requirements
-Nested groups are only supported when you use PostgreSQL. Supporting nested
-groups on MySQL in an efficient way is not possible due to MySQL's limitations.
+Subgroups are only supported when you use PostgreSQL. Supporting subgroups on MySQL in an
+efficient way is not possible due to MySQL's limitations.
+
See the following links for more information:
- <https://gitlab.com/gitlab-org/gitlab-ce/issues/30472>
@@ -37,7 +44,7 @@ only 1 parent group. It resembles a directory behavior or a nested items list:
- Group 1.2.2.1
In a real world example, imagine maintaining a GNU/Linux distribution with the
-first group being the name of the distro and subsequent groups split like:
+first group being the name of the distribution, and subsequent groups split as follows:
- Organization Group - GNU/Linux distro
- Category Subgroup - Packages
@@ -69,22 +76,22 @@ Another example of GitLab as a company would be the following:
---
-The maximum nested groups a group can have, including the first one in the
+The maximum subgroups a group can have, including the first one in the
hierarchy, is 21.
-Things like transferring or importing a project inside nested groups, work like
+Actions such as transferring or importing a project inside subgroups, work like
when performing these actions the traditional way with the `group/project`
structure.
## Creating a subgroup
NOTE: **Note:**
-You need to be an Owner of a group in order to be able to create a subgroup. For
+You must be an Owner of a group to create a subgroup. For
more information check the [permissions table](../../permissions.md#group-members-permissions).
For a list of words that are not allowed to be used as group names see the
[reserved names](../../reserved_names.md).
Users can always create subgroups if they are explicitly added as an Owner to
-a parent group even if group creation is disabled by an administrator in their
+a parent group, even if group creation is disabled by an administrator in their
settings.
To create a subgroup:
@@ -111,7 +118,7 @@ When you add a member to a subgroup, they inherit the membership and permission
level from the parent group. This model allows access to nested groups if you
have membership in one of its parents.
-The group permissions for a member can be changed only by Owners and only on
+The group permissions for a member can be changed only by Owners, and only on
the **Members** page of the group the member was added.
You can tell if a member has inherited the permissions from a parent group by
@@ -119,24 +126,24 @@ looking at the group's **Members** page.
![Group members page](img/group_members.png)
-From the image above, we can deduct the following things:
+From the image above, we can deduce the following things:
-- There are 5 members that have access to the group `four`
+- There are 5 members that have access to the group `four`.
- User0 is a Reporter and has inherited their permissions from group `one`
- which is above the hierarchy of group `four`
+ which is above the hierarchy of group `four`.
- User1 is a Developer and has inherited their permissions from group
- `one/two` which is above the hierarchy of group `four`
+ `one/two` which is above the hierarchy of group `four`.
- User2 is a Developer and has inherited their permissions from group
- `one/two/three` which is above the hierarchy of group `four`
+ `one/two/three` which is above the hierarchy of group `four`.
- For User3 there is no indication of a parent group, therefore they belong to
- group `four`, the one we're inspecting
+ group `four`, the one we're inspecting.
- Administrator is the Owner and member of **all** subgroups and for that reason,
- same as User3, there is no indication of an ancestor group
+ as with User3, there is no indication of an ancestor group.
### Overriding the ancestor group membership
NOTE: **Note:**
-You need to be an Owner of a group in order to be able to add members to it.
+You must be an Owner of a group to be able to add members to it.
NOTE: **Note:**
A user's permissions in a subgroup cannot be lower than in any of its ancestor groups.
@@ -154,7 +161,7 @@ the permissions will fallback to those of the ancestor group.
## Mentioning subgroups
Mentioning groups (`@group`) in issues, commits and merge requests, would
-notify all members of that group. Now with subgroups, there is a more granular
+notify all members of that group. Now with subgroups, there is more granular
support if you want to split your group's structure. Mentioning works as before
and you can choose the group of people to be notified.
@@ -179,3 +186,15 @@ Here's a list of what you can't do with subgroups:
[permissions]: ../../permissions.md#group-members-permissions
[reserved]: ../../reserved_names.md
[issue]: https://gitlab.com/gitlab-org/gitlab-ce/issues/30472#note_27747600
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/img/markdown_inline_diffs_tags_rendered.png b/doc/user/img/markdown_inline_diffs_tags_rendered.png
new file mode 100644
index 00000000000..4279a20b5a0
--- /dev/null
+++ b/doc/user/img/markdown_inline_diffs_tags_rendered.png
Binary files differ
diff --git a/doc/user/img/mermaid_diagram_render_gfm.png b/doc/user/img/mermaid_diagram_render_gfm.png
deleted file mode 100644
index 9d192a30a85..00000000000
--- a/doc/user/img/mermaid_diagram_render_gfm.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/index.md b/doc/user/index.md
index 8164b31c37e..1fc4e4c43cf 100644
--- a/doc/user/index.md
+++ b/doc/user/index.md
@@ -49,21 +49,22 @@ GitLab is a Git-based platform that integrates a great number of essential tools
With GitLab Enterprise Edition, you can also:
-- Provide support with [Service Desk](https://docs.gitlab.com/ee/user/project/service_desk.html).
+- Provide support with [Service Desk](project/service_desk.md).
- Improve collaboration with
- [Merge Request Approvals](https://docs.gitlab.com/ee/user/project/merge_requests/index.html#merge-request-approvals),
- [Multiple Assignees for Issues](https://docs.gitlab.com/ee/user/project/issues/multiple_assignees_for_issues.html),
+ [Merge Request Approvals](project/merge_requests/index.md#merge-request-approvals-starter),
+ [Multiple Assignees for Issues](project/issues/multiple_assignees_for_issues.md),
and [Multiple Issue Boards](project/issue_board.md#multiple-issue-boards-starter).
-- Create formal relationships between issues with [Related Issues](https://docs.gitlab.com/ee/user/project/issues/related_issues.html).
-- Use [Burndown Charts](https://docs.gitlab.com/ee/user/project/milestones/burndown_charts.html) to track progress during a sprint or while working on a new version of their software.
-- Leverage [Elasticsearch](https://docs.gitlab.com/ee/integration/elasticsearch.html) with [Advanced Global Search](https://docs.gitlab.com/ee/user/search/advanced_global_search.html) and [Advanced Syntax Search](https://docs.gitlab.com/ee/user/search/advanced_search_syntax.html) for faster, more advanced code search across your entire GitLab instance.
-- [Authenticate users with Kerberos](https://docs.gitlab.com/ee/integration/kerberos.html).
-- [Mirror a repository](https://docs.gitlab.com/ee/workflow/repository_mirroring.html) from elsewhere on your local server.
-- [Export issues as CSV](https://docs.gitlab.com/ee/user/project/issues/csv_export.html).
-- View your entire CI/CD pipeline involving more than one project with [Multiple-Project Pipelines](https://docs.gitlab.com/ee/ci/multi_project_pipeline_graphs.html).
-- [Lock files](https://docs.gitlab.com/ee/user/project/file_lock.html) to prevent conflicts.
-- View the current health and status of each CI environment running on Kubernetes with [Deploy Boards](https://docs.gitlab.com/ee/user/project/deploy_boards.html).
-- Leverage continuous delivery method with [Canary Deployments](https://docs.gitlab.com/ee/user/project/canary_deployments.html).
+- Create formal relationships between issues with [Related Issues](project/issues/related_issues.md).
+- Use [Burndown Charts](project/milestones/burndown_charts.md) to track progress during a sprint or while working on a new version of their software.
+- Leverage [Elasticsearch](../integration/elasticsearch.md) with [Advanced Global Search](search/advanced_global_search.md) and [Advanced Syntax Search](search/advanced_search_syntax.md) for faster, more advanced code search across your entire GitLab instance.
+- [Authenticate users with Kerberos](../integration/kerberos.md).
+- [Mirror a repository](../workflow/repository_mirroring.md) from elsewhere on your local server.
+- [Export issues as CSV](project/issues/csv_export.md).
+- View your entire CI/CD pipeline involving more than one project with [Multiple-Project Pipelines](../ci/multi_project_pipeline_graphs.md).
+- [Lock files](project/file_lock.md) to prevent conflicts.
+- View the current health and status of each CI environment running on Kubernetes with [Deploy Boards](project/deploy_boards.md).
+- Leverage continuous delivery method with [Canary Deployments](project/canary_deployments.md).
+- Scan your code for vulnerabilities and [display them in merge requests](application_security/sast/index.md).
You can also [integrate](project/integrations/project_services.md) GitLab with numerous third-party applications, such as Mattermost, Microsoft Teams, HipChat, Trello, Slack, Bamboo CI, JIRA, and a lot more.
@@ -106,8 +107,8 @@ to enjoy the best of GitLab.
- [Permissions](permissions.md): Learn the different set of permissions levels for each
user type (guest, reporter, developer, maintainer, owner).
- [Feature highlight](feature_highlight.md): Learn more about the little blue dots
- around the app that explain certain features
-- [Abuse reports](abuse_reports.md): Report abuse from users to GitLab administrators
+ around the app that explain certain features.
+- [Abuse reports](abuse_reports.md): Report abuse from users to GitLab administrators.
## Groups
@@ -171,3 +172,8 @@ Learn what is [Git](../topics/git/index.md) and its best practices.
## Instance statistics
See [various statistics](instance_statistics/index.md) of your GitLab instance.
+
+## Operations Dashboard **[PREMIUM]**
+
+See [Operations Dashboard](operations_dashboard/index.md) for a summary of each
+project's operational health.
diff --git a/doc/user/instance/clusters/index.md b/doc/user/instance/clusters/index.md
new file mode 100644
index 00000000000..894f83d3c75
--- /dev/null
+++ b/doc/user/instance/clusters/index.md
@@ -0,0 +1,23 @@
+# Instance-level Kubernetes clusters
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/39840) in GitLab 11.11.
+> Instance-level cluster integration is currently in [Beta](https://about.gitlab.com/handbook/product/#alpha-beta-ga).
+
+## Overview
+
+Similar to [project-level](../../project/clusters/index.md)
+and [group-level](../../group/clusters/index.md) Kubernetes clusters,
+instance-level Kubernetes clusters allow you to connect a Kubernetes cluster to
+the GitLab instance, which enables you to use the same cluster across multiple
+projects.
+
+## Cluster precedence
+
+GitLab will try match to clusters in the following order:
+
+- Project-level clusters
+- Group-level clusters
+- Instance level
+
+To be selected, the cluster must be enabled and
+match the [environment selector](../../../ci/environments.md#scoping-environments-with-specs-premium).
diff --git a/doc/user/instance_statistics/convdev.md b/doc/user/instance_statistics/convdev.md
index 2c9e0ecbf65..d486ecc39a4 100644
--- a/doc/user/instance_statistics/convdev.md
+++ b/doc/user/instance_statistics/convdev.md
@@ -5,7 +5,7 @@
NOTE: **Note:**
Your GitLab instance's [usage ping](../admin_area/settings/usage_statistics.md#usage-ping-core-only) must be activated in order to use this feature.
-The Conversational Development Index (ConvDev Index) gives you an overview of your entire
+The [Conversational Development](http://conversationaldevelopment.com/2017/04/16/what-is-conversational-development/) Index (ConvDev Index) gives you an overview of your entire
instance's adoption of [Concurrent DevOps](https://about.gitlab.com/concurrent-devops/)
from planning to monitoring.
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index 9891a43aa61..31c8093ced7 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -20,6 +20,7 @@ You can use GFM in the following areas:
- Snippets (the snippet must be named with a `.md` extension)
- Wiki pages
- Markdown documents inside repositories
+- Epics **[ULTIMATE]**
You can also use other rich text files in GitLab. You might have to install a
dependency to do so. Please see the [`github-markup` gem readme](https://github.com/gitlabhq/markup#markups) for more information.
@@ -245,7 +246,7 @@ https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#inline-
With inline diffs tags you can display {+ additions +} or [- deletions -].
-The wrapping tags can be either curly braces or square brackets: [+ additions +] or {- deletions -}.
+The wrapping tags can be either curly braces or square brackets.
Examples:
@@ -256,6 +257,10 @@ Examples:
- [- deletions -]
```
+becomes:
+
+![inline diffs tags rendered](img/markdown_inline_diffs_tags_rendered.png)
+
However the wrapping tags cannot be mixed as such:
```
@@ -285,15 +290,15 @@ On Linux, you can download [Noto Color Emoji](https://www.google.com/get/noto/he
Ubuntu 18.04 (like many modern Linux distros) has this font installed by default.
```
-Sometimes you want to <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/public/-/emojis/1/monkey.png" width="20px" height="20px" style="display:inline;margin:0"> around a bit and add some <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/public/-/emojis/1/star2.png" width="20px" height="20px" style="display:inline;margin:0"> to your <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/public/-/emojis/1/speech_balloon.png" width="20px" height="20px" style="display:inline;margin:0">. Well we have a gift for you:
+Sometimes you want to <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/monkey.png" width="20px" height="20px" style="display:inline;margin:0"> around a bit and add some <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/star2.png" width="20px" height="20px" style="display:inline;margin:0"> to your <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/speech_balloon.png" width="20px" height="20px" style="display:inline;margin:0">. Well we have a gift for you:
-<img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/public/-/emojis/1/zap.png" width="20px" height="20px" style="display:inline;margin:0">You can use emoji anywhere GFM is supported. <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/public/-/emojis/1/v.png" width="20px" height="20px" style="display:inline;margin:0">
+<img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/zap.png" width="20px" height="20px" style="display:inline;margin:0">You can use emoji anywhere GFM is supported. <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/v.png" width="20px" height="20px" style="display:inline;margin:0">
-You can use it to point out a <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/public/-/emojis/1/bug.png" width="20px" height="20px" style="display:inline;margin:0"> or warn about <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/public/-/emojis/1/speak_no_evil.png" width="20px" height="20px" style="display:inline;margin:0"> patches. And if someone improves your really <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/public/-/emojis/1/snail.png" width="20px" height="20px" style="display:inline;margin:0"> code, send them some <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/public/-/emojis/1/birthday.png" width="20px" height="20px" style="display:inline;margin:0">. People will <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/public/-/emojis/1/heart.png" width="20px" height="20px" style="display:inline;margin:0"> you for that.
+You can use it to point out a <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/bug.png" width="20px" height="20px" style="display:inline;margin:0"> or warn about <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/speak_no_evil.png" width="20px" height="20px" style="display:inline;margin:0"> patches. And if someone improves your really <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/snail.png" width="20px" height="20px" style="display:inline;margin:0"> code, send them some <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/birthday.png" width="20px" height="20px" style="display:inline;margin:0">. People will <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/heart.png" width="20px" height="20px" style="display:inline;margin:0"> you for that.
-If you are new to this, don't be <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/public/-/emojis/1/fearful.png" width="20px" height="20px" style="display:inline;margin:0">. You can easily join the emoji <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/public/-/emojis/1/family.png" width="20px" height="20px" style="display:inline;margin:0">. All you need to do is to look up one of the supported codes.
+If you are new to this, don't be <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/fearful.png" width="20px" height="20px" style="display:inline;margin:0">. You can easily join the emoji <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/family.png" width="20px" height="20px" style="display:inline;margin:0">. All you need to do is to look up one of the supported codes.
-Consult the [Emoji Cheat Sheet](https://www.webfx.com/tools/emoji-cheat-sheet/) for a list of all supported emoji codes. <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/public/-/emojis/1/thumbsup.png" width="20px" height="20px" style="display:inline;margin:0">
+Consult the [Emoji Cheat Sheet](https://www.webfx.com/tools/emoji-cheat-sheet/) for a list of all supported emoji codes. <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/thumbsup.png" width="20px" height="20px" style="display:inline;margin:0">
Most emoji are natively supported on macOS, Windows, iOS, Android and will fallback to image-based emoji where there is lack of support.
@@ -320,6 +325,7 @@ GFM will recognize the following:
| `#12345` | issue |
| `!123` | merge request |
| `$123` | snippet |
+| `&123` | epic **[ULTIMATE]** |
| `~123` | label by ID |
| `~bug` | one-word label by name |
| `~"feature request"` | multi-word label by name |
@@ -340,6 +346,7 @@ GFM also recognizes certain cross-project references:
| `namespace/project%123` | project milestone |
| `namespace/project$123` | snippet |
| `namespace/project@9ba12248` | specific commit |
+| `group1/subgroup&123` | epic **[ULTIMATE]** |
| `namespace/project@9ba12248...b19a04f5` | commit range comparison |
| `namespace/project~"Some label"` | issues with given label |
@@ -477,7 +484,7 @@ GitLab 10.3.
> If this is not rendered correctly, see
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#mermaid
-It is possible to generate diagrams and flowcharts from text using [Mermaid][mermaid].
+It is possible to generate diagrams and flowcharts from text using [Mermaid](https://mermaidjs.github.io/).
In order to generate a diagram or flowchart, you should write your text inside the `mermaid` block.
@@ -493,9 +500,15 @@ Example:
Becomes:
-<img src="./img/mermaid_diagram_render_gfm.png" width="200px" height="400px">
+```mermaid
+graph TD;
+ A-->B;
+ A-->C;
+ B-->D;
+ C-->D;
+```
-For details see the [Mermaid official page][mermaid].
+For details see the [Mermaid official page](https://mermaidjs.github.io/).
### Front matter
@@ -1018,7 +1031,7 @@ A link can be constructed relative to the current wiki page using `./<page>`,
it would link to `<your_wiki>/documentation/related`:
```markdown
- [Link to Related Page](./related)
+ [Link to Related Page](related)
```
- If this snippet was placed on a page at `<your_wiki>/documentation/related/content`,
@@ -1032,7 +1045,7 @@ A link can be constructed relative to the current wiki page using `./<page>`,
it would link to `<your_wiki>/documentation/related.md`:
```markdown
- [Link to Related Page](./related.md)
+ [Link to Related Page](related.md)
```
- If this snippet was placed on a page at `<your_wiki>/documentation/related/content`,
@@ -1069,7 +1082,6 @@ A link starting with a `/` is relative to the wiki root.
[^2]: This is my awesome footnote.
[markdown.md]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md
-[mermaid]: https://mermaidjs.github.io/ "Mermaid website"
[rouge]: http://rouge.jneen.net/ "Rouge website"
[redcarpet]: https://github.com/vmg/redcarpet "Redcarpet website"
[katex]: https://github.com/Khan/KaTeX "KaTeX website"
diff --git a/doc/user/operations_dashboard/img/index_operations_dashboard_top_bar_icon.png b/doc/user/operations_dashboard/img/index_operations_dashboard_top_bar_icon.png
new file mode 100644
index 00000000000..9d6a509ea72
--- /dev/null
+++ b/doc/user/operations_dashboard/img/index_operations_dashboard_top_bar_icon.png
Binary files differ
diff --git a/doc/user/operations_dashboard/img/index_operations_dashboard_with_projects.png b/doc/user/operations_dashboard/img/index_operations_dashboard_with_projects.png
new file mode 100644
index 00000000000..ee33eee8134
--- /dev/null
+++ b/doc/user/operations_dashboard/img/index_operations_dashboard_with_projects.png
Binary files differ
diff --git a/doc/user/operations_dashboard/index.md b/doc/user/operations_dashboard/index.md
new file mode 100644
index 00000000000..66362f27299
--- /dev/null
+++ b/doc/user/operations_dashboard/index.md
@@ -0,0 +1,37 @@
+# Operations Dashboard **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5781)
+in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.5.
+[Moved](https://gitlab.com/gitlab-org/gitlab-ee/issues/9218) to
+[GitLab Premium](https://about.gitlab.com/pricing/) in 11.10.
+
+The Operations Dashboard provides a summary of each project's operational health,
+including pipeline and alert status.
+
+The dashboard can be accessed via the top bar, by clicking on the new
+dashboard icon:
+
+![Operations Dashboard icon in top bar](img/index_operations_dashboard_top_bar_icon.png)
+
+## Adding a project to the dashboard
+
+NOTE: **Note:**
+For GitLab.com, the Operations Dashboard is available for free for public projects.
+If your project is private, the group it belongs to must have a
+[Gold](https://about.gitlab.com/pricing/) plan.
+
+To add a project to the dashboard:
+
+1. Click the **Add projects** button in the homescreen of the dashboard.
+1. Search and add one or more projects using the **Search your projects** field.
+1. Click the **Add projects** button.
+
+Once added, the dashboard will display the project's number of active alerts,
+last commit, pipeline status, and when it was last deployed.
+
+![Operations Dashboard with projects](img/index_operations_dashboard_with_projects.png)
+
+## Making it the default dashboard when you sign in
+
+The Operations Dashboard can also be made the default GitLab dashboard shown when
+you sign in. To make it the default, visit your [profile preferences](../profile/preferences.md).
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index a340dd063e4..5b348b1ac60 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -11,7 +11,7 @@ project itself, the highest permission level is used.
On public and internal projects the Guest role is not enforced. All users will
be able to create issues, leave comments, and clone or download the project code.
-When a member leaves the team all the assigned [Issues](project/issues/index.md) and [Merge Requests](project/merge_requests/index.md)
+When a member leaves a team's project, all the assigned [Issues](project/issues/index.md) and [Merge Requests](project/merge_requests/index.md)
will be unassigned automatically.
GitLab [administrators](../administration/index.md) receive all permissions.
@@ -36,90 +36,96 @@ In GitLab 11.0, the Master role was renamed to Maintainer.
The following table depicts the various user permission levels in a project.
-| Action | Guest | Reporter | Developer |Maintainer| Owner |
-|---------------------------------------|---------|------------|-------------|----------|--------|
-| Create new issue | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
-| Create confidential issue | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
-| View confidential issues | (✓) [^2] | ✓ | ✓ | ✓ | ✓ |
-| Leave comments | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
-| Lock issue discussions | | ✓ | ✓ | ✓ | ✓ |
-| Lock merge request discussions | | | ✓ | ✓ | ✓ |
-| See a list of jobs | ✓ [^3] | ✓ | ✓ | ✓ | ✓ |
-| See a job log | ✓ [^3] | ✓ | ✓ | ✓ | ✓ |
-| Download and browse job artifacts | ✓ [^3] | ✓ | ✓ | ✓ | ✓ |
-| View wiki pages | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
-| Create and edit wiki pages | | | ✓ | ✓ | ✓ |
-| Delete wiki pages | | | | ✓ | ✓ |
-| View license management reports **[ULTIMATE]** | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
-| View Security reports **[ULTIMATE]** | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
-| View project code | [^1] | ✓ | ✓ | ✓ | ✓ |
-| Pull project code | [^1] | ✓ | ✓ | ✓ | ✓ |
-| Download project | [^1] | ✓ | ✓ | ✓ | ✓ |
-| Assign issues | | ✓ | ✓ | ✓ | ✓ |
-| Assign merge requests | | | ✓ | ✓ | ✓ |
-| Label issues | | ✓ | ✓ | ✓ | ✓ |
-| Label merge requests | | | ✓ | ✓ | ✓ |
-| Create code snippets | | ✓ | ✓ | ✓ | ✓ |
-| Manage issue tracker | | ✓ | ✓ | ✓ | ✓ |
-| Manage labels | | ✓ | ✓ | ✓ | ✓ |
-| See a commit status | | ✓ | ✓ | ✓ | ✓ |
-| See a container registry | | ✓ | ✓ | ✓ | ✓ |
-| See environments | | ✓ | ✓ | ✓ | ✓ |
-| See a list of merge requests | | ✓ | ✓ | ✓ | ✓ |
-| Manage related issues **[STARTER]** | | ✓ | ✓ | ✓ | ✓ |
-| Lock issue discussions | | ✓ | ✓ | ✓ | ✓ |
-| Create issue from vulnerability **[ULTIMATE]** | | ✓ | ✓ | ✓ | ✓ |
-| View Error Tracking list | | ✓ | ✓ | ✓ | ✓ |
-| Pull from [Maven repository](https://docs.gitlab.com/ee/user/project/packages/maven_repository.html) or [NPM registry](https://docs.gitlab.com/ee/user/project/packages/npm_registry.html) **[PREMIUM]** | | ✓ | ✓ | ✓ | ✓ |
-| Publish to [Maven repository](https://docs.gitlab.com/ee/user/project/packages/maven_repository.html) or [NPM registry](https://docs.gitlab.com/ee/user/project/packages/npm_registry.html) **[PREMIUM]** | | | ✓ | ✓ | ✓ |
-| Lock merge request discussions | | | ✓ | ✓ | ✓ |
-| Create new environments | | | ✓ | ✓ | ✓ |
-| Stop environments | | | ✓ | ✓ | ✓ |
-| Manage/Accept merge requests | | | ✓ | ✓ | ✓ |
-| Create new merge request | | | ✓ | ✓ | ✓ |
-| Create new branches | | | ✓ | ✓ | ✓ |
-| Push to non-protected branches | | | ✓ | ✓ | ✓ |
-| Force push to non-protected branches | | | ✓ | ✓ | ✓ |
-| Remove non-protected branches | | | ✓ | ✓ | ✓ |
-| Add tags | | | ✓ | ✓ | ✓ |
-| Cancel and retry jobs | | | ✓ | ✓ | ✓ |
-| Create or update commit status | | | ✓ | ✓ | ✓ |
-| Update a container registry | | | ✓ | ✓ | ✓ |
-| Remove a container registry image | | | ✓ | ✓ | ✓ |
-| Create/edit/delete project milestones | | | ✓ | ✓ | ✓ |
-| View approved/blacklisted licenses **[ULTIMATE]** | | | ✓ | ✓ | ✓ |
-| Use security dashboard **[ULTIMATE]** | | | ✓ | ✓ | ✓ |
-| Dismiss vulnerability **[ULTIMATE]** | | | ✓ | ✓ | ✓ |
-| Apply code change suggestions | | | ✓ | ✓ | ✓ |
-| Use environment terminals | | | | ✓ | ✓ |
-| Add new team members | | | | ✓ | ✓ |
-| Push to protected branches | | | | ✓ | ✓ |
-| Enable/disable branch protection | | | | ✓ | ✓ |
-| Turn on/off protected branch push for devs| | | | ✓ | ✓ |
-| Enable/disable tag protections | | | | ✓ | ✓ |
-| Rewrite/remove Git tags | | | | ✓ | ✓ |
-| Edit project | | | | ✓ | ✓ |
-| Add deploy keys to project | | | | ✓ | ✓ |
-| Configure project hooks | | | | ✓ | ✓ |
-| Manage Runners | | | | ✓ | ✓ |
-| Manage job triggers | | | | ✓ | ✓ |
-| Manage variables | | | | ✓ | ✓ |
-| Manage GitLab Pages | | | | ✓ | ✓ |
-| Manage GitLab Pages domains and certificates | | | | ✓ | ✓ |
-| Remove GitLab Pages | | | | ✓ | ✓ |
+| Action | Guest | Reporter | Developer |Maintainer| Owner |
+|---------------------------------------------------|---------|------------|-------------|----------|--------|
+| Download project | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
+| Leave comments | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
+| View Insights charts **[ULTIMATE]** | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View approved/blacklisted licenses **[ULTIMATE]** | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View license management reports **[ULTIMATE]** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
+| View Security reports **[ULTIMATE]** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
+| View project code | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
+| Pull project code | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
| View GitLab Pages protected by [access control](project/pages/introduction.md#gitlab-pages-access-control-core-only) | ✓ | ✓ | ✓ | ✓ | ✓ |
-| Manage clusters | | | | ✓ | ✓ |
-| Manage license policy **[ULTIMATE]** | | | | ✓ | ✓ |
-| Edit comments (posted by any user) | | | | ✓ | ✓ |
-| Manage Error Tracking | | | | ✓ | ✓ |
-| Switch visibility level | | | | | ✓ |
-| Transfer project to another namespace | | | | | ✓ |
-| Remove project | | | | | ✓ |
-| Delete issues | | | | | ✓ |
-| Force push to protected branches [^4] | | | | | |
-| Remove protected branches [^4] | | | | | |
-| View project Audit Events | | | | ✓ | ✓ |
-| View project statistics | | ✓ | ✓ | ✓ | ✓ |
+| View wiki pages | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
+| See a list of jobs | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ |
+| See a job log | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ |
+| Download and browse job artifacts | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ |
+| Create new issue | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
+| See related issues | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Create confidential issue | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
+| View confidential issues | (*2*) | ✓ | ✓ | ✓ | ✓ |
+| Assign issues | | ✓ | ✓ | ✓ | ✓ |
+| Label issues | | ✓ | ✓ | ✓ | ✓ |
+| Lock issue discussions | | ✓ | ✓ | ✓ | ✓ |
+| Manage issue tracker | | ✓ | ✓ | ✓ | ✓ |
+| Manage related issues **[STARTER]** | | ✓ | ✓ | ✓ | ✓ |
+| Create issue from vulnerability **[ULTIMATE]** | | ✓ | ✓ | ✓ | ✓ |
+| Manage labels | | ✓ | ✓ | ✓ | ✓ |
+| Create code snippets | | ✓ | ✓ | ✓ | ✓ |
+| See a commit status | | ✓ | ✓ | ✓ | ✓ |
+| See a container registry | | ✓ | ✓ | ✓ | ✓ |
+| See environments | | ✓ | ✓ | ✓ | ✓ |
+| See a list of merge requests | | ✓ | ✓ | ✓ | ✓ |
+| View project statistics | | ✓ | ✓ | ✓ | ✓ |
+| View Error Tracking list | | ✓ | ✓ | ✓ | ✓ |
+| Pull from [Maven repository](project/packages/maven_repository.md) or [NPM registry](project/packages/npm_registry.md) **[PREMIUM]** | | ✓ | ✓ | ✓ | ✓ |
+| Publish to [Maven repository](project/packages/maven_repository.md) or [NPM registry](project/packages/npm_registry.md) **[PREMIUM]** | | | ✓ | ✓ | ✓ ||
+| Create new branches | | | ✓ | ✓ | ✓ |
+| Push to non-protected branches | | | ✓ | ✓ | ✓ |
+| Force push to non-protected branches | | | ✓ | ✓ | ✓ |
+| Remove non-protected branches | | | ✓ | ✓ | ✓ |
+| Create new merge request | | | ✓ | ✓ | ✓ |
+| Assign merge requests | | | ✓ | ✓ | ✓ |
+| Label merge requests | | | ✓ | ✓ | ✓ |
+| Lock merge request discussions | | | ✓ | ✓ | ✓ |
+| Manage/Accept merge requests | | | ✓ | ✓ | ✓ |
+| Create new environments | | | ✓ | ✓ | ✓ |
+| Stop environments | | | ✓ | ✓ | ✓ |
+| Add tags | | | ✓ | ✓ | ✓ |
+| Cancel and retry jobs | | | ✓ | ✓ | ✓ |
+| Create or update commit status | | | ✓ | ✓ | ✓ |
+| Update a container registry | | | ✓ | ✓ | ✓ |
+| Remove a container registry image | | | ✓ | ✓ | ✓ |
+| Create/edit/delete project milestones | | | ✓ | ✓ | ✓ |
+| Use security dashboard **[ULTIMATE]** | | | ✓ | ✓ | ✓ |
+| Dismiss vulnerability **[ULTIMATE]** | | | ✓ | ✓ | ✓ |
+| Apply code change suggestions | | | ✓ | ✓ | ✓ |
+| Create and edit wiki pages | | | ✓ | ✓ | ✓ |
+| Use environment terminals | | | | ✓ | ✓ |
+| Run Web IDE's Interactive Web Terminals **[ULTIMATE ONLY]** | | | | ✓ | ✓ |
+| Add new team members | | | | ✓ | ✓ |
+| Enable/disable branch protection | | | | ✓ | ✓ |
+| Push to protected branches | | | | ✓ | ✓ |
+| Turn on/off protected branch push for devs | | | | ✓ | ✓ |
+| Enable/disable tag protections | | | | ✓ | ✓ |
+| Rewrite/remove Git tags | | | | ✓ | ✓ |
+| Edit project | | | | ✓ | ✓ |
+| Add deploy keys to project | | | | ✓ | ✓ |
+| Configure project hooks | | | | ✓ | ✓ |
+| Manage Runners | | | | ✓ | ✓ |
+| Manage job triggers | | | | ✓ | ✓ |
+| Manage variables | | | | ✓ | ✓ |
+| Manage GitLab Pages | | | | ✓ | ✓ |
+| Manage GitLab Pages domains and certificates | | | | ✓ | ✓ |
+| Remove GitLab Pages | | | | ✓ | ✓ |
+| Manage clusters | | | | ✓ | ✓ |
+| Manage license policy **[ULTIMATE]** | | | | ✓ | ✓ |
+| Edit comments (posted by any user) | | | | ✓ | ✓ |
+| Manage Error Tracking | | | | ✓ | ✓ |
+| Delete wiki pages | | | | ✓ | ✓ |
+| View project Audit Events | | | | ✓ | ✓ |
+| Switch visibility level | | | | | ✓ |
+| Transfer project to another namespace | | | | | ✓ |
+| Remove project | | | | | ✓ |
+| Delete issues | | | | | ✓ |
+| Force push to protected branches [^4] | | | | | |
+| Remove protected branches [^4] | | | | | |
+
+- (*1*): All users are able to perform this action on public and internal projects, but not private projects.
+- (*2*): Guest users can only view the confidential issues they created themselves
+- (*3*): If **Public pipelines** is enabled in **Project Settings > CI/CD**
+- (*4*): Not allowed for Guest, Reporter, Developer, Maintainer, or Owner
## Project features permissions
@@ -162,7 +168,7 @@ to learn more.
The user that locks a file or directory is the only one that can edit and push their changes back to the repository where the locked objects are located.
-Read through the documentation on [permissions for File Locking](https://docs.gitlab.com/ee/user/project/file_lock.html#permissions-on-file-locking) to learn more.
+Read through the documentation on [permissions for File Locking](project/file_lock.md#permissions-on-file-locking) to learn more.
### Confidential Issues permissions
@@ -172,8 +178,12 @@ read through the documentation on [permissions and access to confidential issues
### Releases permissions
-[Project Releases](project/releases/index.md) can be read by all project
-members (Reporters, Developers, Maintainers, Owners) **except Guests**.
+[Project Releases](project/releases/index.md) can be read by project
+members with Reporter, Developer, Maintainer, and Owner permissions.
+Guest users can access Release pages for downloading assets but
+are not allowed to download the source code nor see repository
+information such as tags and commits.
+
Releases can be created, updated, or deleted via [Releases APIs](../api/releases/index.md)
by project Developers, Maintainers, and Owners.
@@ -186,20 +196,22 @@ Any user can remove themselves from a group, unless they are the last Owner of
the group. The following table depicts the various user permission levels in a
group.
-| Action | Guest | Reporter | Developer | Maintainer | Owner |
-|-------------------------|-------|----------|-----------|--------|-------|
-| Browse group | ✓ | ✓ | ✓ | ✓ | ✓ |
-| Edit group | | | | | ✓ |
-| Create subgroup | | | | | ✓ |
-| Create project in group | | | ✓ | ✓ | ✓ |
-| Manage group members | | | | | ✓ |
-| Remove group | | | | | ✓ |
-| Manage group labels | | ✓ | ✓ | ✓ | ✓ |
-| Create/edit/delete group milestones | | | ✓ | ✓ | ✓ |
-| View group epic **[ULTIMATE]** | ✓ | ✓ | ✓ | ✓ | ✓ |
-| Create/edit group epic **[ULTIMATE]** | | ✓ | ✓ | ✓ | ✓ |
-| Delete group epic **[ULTIMATE]** | | | | | ✓ |
-| View group Audit Events | | | | | ✓ |
+| Action | Guest | Reporter | Developer | Maintainer | Owner |
+|-------------------------------------------------|-------|----------|-----------|------------|-------|
+| Browse group | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View Insights charts **[ULTIMATE]** | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View group epic **[ULTIMATE]** | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Create/edit group epic **[ULTIMATE]** | | ✓ | ✓ | ✓ | ✓ |
+| Manage group labels | | ✓ | ✓ | ✓ | ✓ |
+| Create project in group | | | ✓ | ✓ | ✓ |
+| Create/edit/delete group milestones | | | ✓ | ✓ | ✓ |
+| Enable/disable a dependency proxy **[PREMIUM]** | | | ✓ | ✓ | ✓ |
+| Edit group | | | | | ✓ |
+| Create subgroup | | | | | ✓ |
+| Manage group members | | | | | ✓ |
+| Remove group | | | | | ✓ |
+| Delete group epic **[ULTIMATE]** | | | | | ✓ |
+| View group Audit Events | | | | | ✓ |
### Subgroup permissions
@@ -251,15 +263,15 @@ Please be aware that this regex could lead to a DOS attack, [see](https://en.wik
## Auditor users **[PREMIUM ONLY]**
->[Introduced][ee-998] in [GitLab Premium][eep] 8.17.
+>[Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/998) in [GitLab Premium](https://about.gitlab.com/pricing/) 8.17.
Auditor users are given read-only access to all projects, groups, and other
resources on the GitLab instance.
An Auditor user should be able to access all projects and groups of a GitLab instance
-with the permissions described on the documentation on [auditor users permissions](https://docs.gitlab.com/ee/administration/auditor_users.html#permissions-and-restrictions-of-an-auditor-user).
+with the permissions described on the documentation on [auditor users permissions](../administration/auditor_users.md#permissions-and-restrictions-of-an-auditor-user).
-[Read more about Auditor users.](https://docs.gitlab.com/ee/administration/auditor_users.html)
+[Read more about Auditor users.](../administration/auditor_users.md)
## Project features
@@ -292,7 +304,7 @@ instance and project. In addition, all admins can use the admin interface under
|---------------------------------------|-----------------|-------------|----------|--------|
| See commits and jobs | ✓ | ✓ | ✓ | ✓ |
| Retry or cancel job | | ✓ | ✓ | ✓ |
-| Erase job artifacts and trace | | ✓ [^5] | ✓ | ✓ |
+| Erase job artifacts and trace | | ✓ (*1*) | ✓ | ✓ |
| Remove project | | | ✓ | ✓ |
| Create project | | | ✓ | ✓ |
| Change project configuration | | | ✓ | ✓ |
@@ -301,6 +313,8 @@ instance and project. In addition, all admins can use the admin interface under
| See events in the system | | | | ✓ |
| Admin interface | | | | ✓ |
+- *1*: Only if the job was triggered by the user
+
### Job permissions
NOTE: **Note:**
@@ -308,25 +322,28 @@ In GitLab 11.0, the Master role was renamed to Maintainer.
>**Note:**
GitLab 8.12 has a completely redesigned job permissions system.
-Read all about the [new model and its implications][new-mod].
+Read all about the [new model and its implications](project/new_ci_build_permissions_model.md).
This table shows granted privileges for jobs triggered by specific types of
users:
-| Action | Guest, Reporter | Developer |Maintainer| Admin |
-|---------------------------------------------|-----------------|-------------|----------|--------|
-| Run CI job | | ✓ | ✓ | ✓ |
-| Clone source and LFS from current project | | ✓ | ✓ | ✓ |
-| Clone source and LFS from public projects | | ✓ | ✓ | ✓ |
-| Clone source and LFS from internal projects | | ✓ [^6] | ✓ [^6] | ✓ |
-| Clone source and LFS from private projects | | ✓ [^7] | ✓ [^7] | ✓ [^7] |
-| Push source and LFS | | | | |
-| Pull container images from current project | | ✓ | ✓ | ✓ |
-| Pull container images from public projects | | ✓ | ✓ | ✓ |
-| Pull container images from internal projects| | ✓ [^6] | ✓ [^6] | ✓ |
-| Pull container images from private projects | | ✓ [^7] | ✓ [^7] | ✓ [^7] |
-| Push container images to current project | | ✓ | ✓ | ✓ |
-| Push container images to other projects | | | | |
+| Action | Guest, Reporter | Developer |Maintainer| Admin |
+|---------------------------------------------|-----------------|-------------|----------|---------|
+| Run CI job | | ✓ | ✓ | ✓ |
+| Clone source and LFS from current project | | ✓ | ✓ | ✓ |
+| Clone source and LFS from public projects | | ✓ | ✓ | ✓ |
+| Clone source and LFS from internal projects | | ✓ (*1*) | ✓ (*1*) | ✓ |
+| Clone source and LFS from private projects | | ✓ (*2*) | ✓ (*2*) | ✓ (*2*) |
+| Pull container images from current project | | ✓ | ✓ | ✓ |
+| Pull container images from public projects | | ✓ | ✓ | ✓ |
+| Pull container images from internal projects| | ✓ (*1*) | ✓ (*1*) | ✓ |
+| Pull container images from private projects | | ✓ (*2*) | ✓ (*2*) | ✓ (*2*) |
+| Push container images to current project | | ✓ | ✓ | ✓ |
+| Push container images to other projects | | | | |
+| Push source and LFS | | | | |
+
+- *1*: Only if the user is not an external one
+- *2*: Only if the user is a member of the project
### New CI job permissions model
@@ -344,17 +361,4 @@ for details about the pipelines security model.
## LDAP users permissions
Since GitLab 8.15, LDAP user permissions can now be manually overridden by an admin user.
-Read through the documentation on [LDAP users permissions](https://docs.gitlab.com/ee/articles/how_to_configure_ldap_gitlab_ee/index.html#updating-user-permissions-new-feature) to learn more.
-
-[^1]: On public and internal projects, all users are able to perform this action
-[^2]: Guest users can only view the confidential issues they created themselves
-[^3]: If **Public pipelines** is enabled in **Project Settings > CI/CD**
-[^4]: Not allowed for Guest, Reporter, Developer, Maintainer, or Owner
-[^5]: Only if the job was triggered by the user
-[^6]: Only if user is not external one
-[^7]: Only if user is a member of the project
-
-[ce-18994]: https://gitlab.com/gitlab-org/gitlab-ce/issues/18994
-[new-mod]: project/new_ci_build_permissions_model.md
-[ee-998]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/998
-[eep]: https://about.gitlab.com/pricing/
+Read through the documentation on [LDAP users permissions](../administration/auth/how_to_configure_ldap_gitlab_ee/index.html) to learn more.
diff --git a/doc/user/profile/account/delete_account.md b/doc/user/profile/account/delete_account.md
index b497cc414af..304a7984191 100644
--- a/doc/user/profile/account/delete_account.md
+++ b/doc/user/profile/account/delete_account.md
@@ -14,7 +14,7 @@ Deleting a user will delete all projects in that user namespace.
[GitLab 9.1][ce-10273], and from the API in [GitLab 9.3][ce-11853].
When a user account is deleted, not all associated records are deleted with it.
-Here's a list of things that will not be deleted:
+Here's a list of things that will **not** be deleted:
- Issues that the user created
- Merge requests that the user created
@@ -23,7 +23,7 @@ Here's a list of things that will not be deleted:
- Award emoji that the user created
Instead of being deleted, these records will be moved to a system-wide
-"Ghost User", whose sole purpose is to act as a container for such records.
+user with the username "Ghost User", whose sole purpose is to act as a container for such records. Any commits made by a deleted user will still display the username of the original user.
When a user is deleted from an [abuse report](../../admin_area/abuse_reports.md) or spam log, these associated
records are not ghosted and will be removed, along with any groups the user
diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md
index 4085f3b678c..0b224fc7e01 100644
--- a/doc/user/profile/personal_access_tokens.md
+++ b/doc/user/profile/personal_access_tokens.md
@@ -37,19 +37,18 @@ Personal access tokens can be created with one or more scopes that allow various
actions that a given token can perform. The available scopes are depicted in
the following table.
-| Scope | Description |
-| ----- | ----------- |
-|`read_user` | Allows access to the read-only endpoints under `/users`. Essentially, any of the `GET` requests in the [Users API][users] are allowed ([introduced][ce-5951] in GitLab 8.15). |
-| `api` | Grants complete access to the API and Container Registry (read/write) ([introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5951) in GitLab 8.15). |
-| `read_registry` | Allows to read (pull) [container registry] images if a project is private and authorization is required ([introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11845) in GitLab 9.3). |
-| `sudo` | Allows performing API actions as any user in the system (if the authenticated user is an admin) ([introduced][ce-14838] in GitLab 10.2). |
-| `read_repository` | Allows read-only access (pull) to the repository through git clone. |
-| `write_repository` | Allows read-write access (pull, push) to the repository through git clone. Required for accessing Git repositories over HTTP when 2FA is enabled. |
+| Scope | Introduced in | Description |
+| ------------------ | ------------- | ----------- |
+| `read_user` | [GitLab 8.15](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5951) | Allows access to the read-only endpoints under `/users`. Essentially, any of the `GET` requests in the [Users API][users] are allowed. |
+| `api` | [GitLab 8.15](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5951) | Grants complete access to the API and Container Registry (read/write). |
+| `read_registry` | [GitLab 9.3](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11845) | Allows to read (pull) [container registry] images if a project is private and authorization is required. |
+| `sudo` | [GitLab 10.2](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14838) | Allows performing API actions as any user in the system (if the authenticated user is an admin). |
+| `read_repository` | [GitLab 10.7](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17894) | Allows read-only access (pull) to the repository through git clone. |
+| `write_repository` | [GitLab 11.11](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/26021) | Allows read-write access (pull, push) to the repository through git clone. Required for accessing Git repositories over HTTP when 2FA is enabled. |
[2fa]: ../account/two_factor_authentication.md
[api]: ../../api/README.md
[ce-3749]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3749
-[ce-14838]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14838
[container registry]: ../project/container_registry.md
[users]: ../../api/users.md
[usage]: ../../api/README.md#personal-access-tokens
diff --git a/doc/user/profile/preferences.md b/doc/user/profile/preferences.md
index f399dc40164..b61216b7b67 100644
--- a/doc/user/profile/preferences.md
+++ b/doc/user/profile/preferences.md
@@ -79,6 +79,7 @@ You have 8 options here that you can use for your default dashboard view:
- Your [Todos](../../workflow/todos.md)
- Assigned Issues
- Assigned Merge Requests
+- Operations Dashboard **[PREMIUM]**
### Project overview content
diff --git a/doc/user/project/canary_deployments.md b/doc/user/project/canary_deployments.md
new file mode 100644
index 00000000000..cce862b0911
--- /dev/null
+++ b/doc/user/project/canary_deployments.md
@@ -0,0 +1,71 @@
+# Canary Deployments **[PREMIUM]**
+
+> [Introduced][ee-1659] in [GitLab Premium][eep] 9.1.
+
+A popular [Continuous Integration](https://en.wikipedia.org/wiki/Continuous_integration)
+strategy, where a small portion of the fleet is updated to the new version of
+your application.
+
+## Overview
+
+When embracing [Continuous Delivery][cd-blog], a company needs to decide what
+type of deployment strategy to use. One of the most popular strategies is canary
+deployments, where a small portion of the fleet is updated to the new version
+first. This subset, the canaries, then serve as the proverbial
+[canary in the coal mine](https://en.wiktionary.org/wiki/canary_in_a_coal_mine).
+
+If there is a problem with the new version of the application, only a small
+percentage of users are affected and the change can either be fixed or quickly
+reverted.
+
+Leveraging [Kubernetes' Canary deployments][kube-canary], visualize your canary
+deployments right inside the [Deploy Board], without the need to leave GitLab.
+
+## Use cases
+
+Canary deployments can be used when you want to ship features to only a portion of
+your pods fleet and watch their behavior as a percentage of your user base
+visits the temporarily deployed feature. If all works well, you can deploy the
+feature to production knowing that it won't cause any problems.
+
+Canary deployments are also especially useful for backend refactors, performance
+improvements, or other changes where the user interface doesn't change, but you
+want to make sure the performance stays the same, or improves. Developers need
+to be careful when using canaries with user-facing changes, because by default,
+requests from the same user will be randomly distributed between canary and
+non-canary pods, which could result in confusion or even errors. If needed, you
+may want to consider [setting `service.spec.sessionAffinity` to `ClientIP` in
+your Kubernetes service definitions][kube-net], but that is beyond the scope of
+this document.
+
+## Enabling Canary Deployments
+
+Canary deployments require that you properly configure Deploy Boards:
+
+1. Follow the steps to [enable Deploy Boards](deploy_boards.md#enabling-deploy-boards).
+1. To track canary deployments you need to label your Kubernetes deployments and
+ pods with `track: canary`. To get started quickly, you can use the [Auto Deploy]
+ template for canary deployments that GitLab provides.
+
+Depending on the deploy, the label should be either `stable` or `canary`.
+Usually, `stable` and blank or missing label means the same thing, and `canary`
+or any other track means canary/temporary.
+This allows GitLab to discover whether deployment is stable or canary (temporary).
+
+Once all of the above are set up and the pipeline has run at least once,
+navigate to the environments page under **Pipelines > Environments**.
+As the pipeline executes Deploy Boards will clearly mark canary pods, enabling
+quick and easy insight into the status of each environment and deployment.
+
+Canary deployments are marked with a yellow dot in the Deploy Board so that you
+can easily notice them.
+
+![Canary deployments on Deploy Board](img/deploy_boards_canary_deployments.png)
+
+[autodeploy]: ../../ci/autodeploy/index.md "GitLab Autodeploy"
+[eep]: https://about.gitlab.com/pricing/
+[ee-1659]: https://gitlab.com/gitlab-org/gitlab-ee/issues/1659
+[kube-canary]: https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments
+[deploy board]: deploy_boards.md
+[cd-blog]: https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/
+[kube-net]: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies
diff --git a/doc/user/project/ci_cd_for_external_repo.md b/doc/user/project/ci_cd_for_external_repo.md
new file mode 100644
index 00000000000..a92d3a2c308
--- /dev/null
+++ b/doc/user/project/ci_cd_for_external_repo.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../../ci/ci_cd_for_external_repos/index.md'
+---
+
+This document was moved to [another location](../../ci/ci_cd_for_external_repos/index.md).
diff --git a/doc/user/project/clusters/img/k8s_cluster_monitoring.png b/doc/user/project/clusters/img/k8s_cluster_monitoring.png
new file mode 100644
index 00000000000..e449893a606
--- /dev/null
+++ b/doc/user/project/clusters/img/k8s_cluster_monitoring.png
Binary files differ
diff --git a/doc/user/project/clusters/img/kubernetes_pod_logs.png b/doc/user/project/clusters/img/kubernetes_pod_logs.png
new file mode 100644
index 00000000000..e664a47386a
--- /dev/null
+++ b/doc/user/project/clusters/img/kubernetes_pod_logs.png
Binary files differ
diff --git a/doc/user/project/clusters/img/pod_logs_deploy_board.png b/doc/user/project/clusters/img/pod_logs_deploy_board.png
new file mode 100644
index 00000000000..7f83382968b
--- /dev/null
+++ b/doc/user/project/clusters/img/pod_logs_deploy_board.png
Binary files differ
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index 1983513174c..dc21db603d6 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -19,8 +19,10 @@ or provide the credentials to an [existing Kubernetes cluster](#adding-an-existi
NOTE: **Note:**
From [GitLab 11.6](https://gitlab.com/gitlab-org/gitlab-ce/issues/34758) you
-can also associate a Kubernetes cluster to your groups. Learn more about
-[group Kubernetes clusters](../../group/clusters/index.md).
+can also associate a Kubernetes cluster to your groups and from
+[GitLab 11.11](https://gitlab.com/gitlab-org/gitlab-ce/issues/39840),
+to the GitLab instance. Learn more about [group-level](../../group/clusters/index.md)
+and [instance-level](../../instance/clusters/index.md) Kubernetes clusters.
## Adding and creating a new GKE cluster via GitLab
@@ -69,7 +71,8 @@ new Kubernetes cluster to your project:
- **Number of nodes** - Enter the number of nodes you wish the cluster to have.
- **Machine type** - The [machine type](https://cloud.google.com/compute/docs/machine-types)
of the Virtual Machine instance that the cluster will be based on.
- - **RBAC-enabled cluster** - Leave this checked if using default GKE creation options, see the [RBAC section](#role-based-access-control-rbac) for more information.
+ - **RBAC-enabled cluster** - Leave this checked if using default GKE creation options, see the [RBAC section](#rbac-cluster-resources) for more information.
+ - **GitLab-managed cluster** - Leave this checked if you want GitLab to manage namespaces and service accounts for this cluster. See the [Managed clusters section](#gitlab-managed-clusters) for more information.
1. Finally, click the **Create Kubernetes cluster** button.
After a couple of minutes, your cluster will be ready to go. You can now proceed
@@ -124,26 +127,26 @@ To add an existing Kubernetes cluster to your project:
1. Create a file called `gitlab-admin-service-account.yaml` with contents:
- ```yaml
- apiVersion: v1
- kind: ServiceAccount
- metadata:
- name: gitlab-admin
- namespace: kube-system
- ---
- apiVersion: rbac.authorization.k8s.io/v1beta1
- kind: ClusterRoleBinding
- metadata:
- name: gitlab-admin
- roleRef:
- apiGroup: rbac.authorization.k8s.io
- kind: ClusterRole
- name: cluster-admin
- subjects:
- - kind: ServiceAccount
- name: gitlab-admin
- namespace: kube-system
- ```
+ ```yaml
+ apiVersion: v1
+ kind: ServiceAccount
+ metadata:
+ name: gitlab-admin
+ namespace: kube-system
+ ---
+ apiVersion: rbac.authorization.k8s.io/v1beta1
+ kind: ClusterRoleBinding
+ metadata:
+ name: gitlab-admin
+ roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: cluster-admin
+ subjects:
+ - kind: ServiceAccount
+ name: gitlab-admin
+ namespace: kube-system
+ ```
1. Apply the service account and cluster role binding to your cluster:
@@ -188,6 +191,9 @@ To add an existing Kubernetes cluster to your project:
role binding. You can follow the [Google Cloud
documentation](https://cloud.google.com/iam/docs/granting-changing-revoking-access)
to grant access.
+
+ - **GitLab-managed cluster** - Leave this checked if you want GitLab to manage namespaces and service accounts for this cluster. See the [Managed clusters section](#gitlab-managed-clusters) for more information.
+
- **Project namespace** (optional) - You don't have to fill it in; by leaving
it blank, GitLab will create one for you. Also:
- Each project should have a unique namespace.
@@ -214,6 +220,29 @@ functionalities needed to successfully build and deploy a containerized
application. Bear in mind that the same credentials are used for all the
applications running on the cluster.
+## Gitlab-managed clusters
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22011) in GitLab 11.5.
+> Became [optional](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/26565) in GitLab 11.11.
+
+NOTE: **Note:**
+Only available when creating clusters. Existing clusters not managed by GitLab
+cannot become GitLab-managed later.
+
+You can choose to allow GitLab to manage your cluster for you. If your cluster is
+managed by GitLab, resources for your projects will be automatically created. See the
+[Access controls](#access-controls) section for details on which resources will
+be created.
+
+If you choose to manage your own cluster, project-specific resources will not be created
+automatically. If you are using [Auto DevOps](../../../topics/autodevops/index.md), you will
+need to explicitly provide the `KUBE_NAMESPACE` [deployment variable](#deployment-variables)
+that will be used by your deployment jobs, otherwise a namespace will be created for you.
+
+NOTE: **Note:**
+If you [install applications](#installing-applications) on your cluster, GitLab will create
+the resources required to run these even if you have chosen to manage your own cluster.
+
## Base domain
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24580) in GitLab 11.8.
@@ -234,65 +263,69 @@ you can either:
## Access controls
-When creating a cluster in GitLab, you will be asked if you would like to create an
-[Attribute-based access control (ABAC)](https://kubernetes.io/docs/admin/authorization/abac/) cluster, or
-a [Role-based access control (RBAC)](https://kubernetes.io/docs/admin/authorization/rbac/) one.
+When creating a cluster in GitLab, you will be asked if you would like to create either:
-NOTE: **Note:**
-[RBAC](#role-based-access-control-rbac) is recommended and the GitLab default.
+- An [Attribute-based access control (ABAC)](https://kubernetes.io/docs/admin/authorization/abac/) cluster.
+- A [Role-based access control (RBAC)](https://kubernetes.io/docs/admin/authorization/rbac/) cluster.
-Whether [ABAC](#attribute-based-access-control-abac) or [RBAC](#role-based-access-control-rbac) is enabled,
-GitLab will create the necessary service accounts and privileges in order to install and run
-[GitLab managed applications](#installing-applications):
+NOTE: **Note:**
+[RBAC](#rbac-cluster-resources) is recommended and the GitLab default.
-- If GitLab is creating the cluster, a `gitlab` service account with
- `cluster-admin` privileges will be created in the `default` namespace,
- which will be used by GitLab to manage the newly created cluster.
+GitLab creates the necessary service accounts and privileges to install and run
+[GitLab managed applications](#installing-applications). When GitLab creates the cluster:
+- A `gitlab` service account with `cluster-admin` privileges is created in the `default` namespace
+ to manage the newly created cluster.
- A project service account with [`edit`
privileges](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)
- will be created in the project namespace (also created by GitLab), which will
- be used in [deployment jobs](#deployment-variables).
+ is created in the GitLab-created project namespace for [deployment jobs](#deployment-variables).
NOTE: **Note:**
Restricted service account for deployment was [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/51716) in GitLab 11.5.
-- When you install Helm Tiller into your cluster, the `tiller` service account
- will be created with `cluster-admin` privileges in the `gitlab-managed-apps`
- namespace. This service account will be added to the installed Helm Tiller and will
- be used by Helm to install and run [GitLab managed applications](#installing-applications).
- Helm Tiller will also create additional service accounts and other resources for each
- installed application. Consult the documentation of the Helm charts for each application
- for details.
+When you install Helm into your cluster, the `tiller` service account
+is created with `cluster-admin` privileges in the `gitlab-managed-apps`
+namespace. This service account will be added to the installed Helm Tiller and will
+be used by Helm to install and run [GitLab managed applications](#installing-applications).
+Helm will also create additional service accounts and other resources for each
+installed application. Consult the documentation of the Helm charts for each application
+for details.
If you are [adding an existing Kubernetes cluster](#adding-an-existing-kubernetes-cluster),
ensure the token of the account has administrator privileges for the cluster.
-The following sections summarize which resources will be created on ABAC/RBAC clusters.
+The resources created by GitLab differ depending on the type of cluster.
+
+### ABAC cluster resources
-### Attribute-based access control (ABAC)
+GitLab creates the following resources for ABAC clusters.
-| Name | Kind | Details | Created when |
-| --- | --- | --- | --- |
-| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new GKE Cluster |
-| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new GKE Cluster |
-| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
-| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
-| Project namespace | `ServiceAccount` | Uses namespace of Project | Creating/Adding a new GKE Cluster |
-| Project namespace | `Secret` | Token for project ServiceAccount | Creating/Adding a new GKE Cluster |
+| Name | Type | Details | Created when |
+|:------------------|:---------------------|:----------------------------------|:---------------------------|
+| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new GKE Cluster |
+| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new GKE Cluster |
+| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
+| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
+| Project namespace | `ServiceAccount` | Uses namespace of Project | Deploying to a cluster |
+| Project namespace | `Secret` | Token for project ServiceAccount | Deploying to a cluster |
-### Role-based access control (RBAC)
+### RBAC cluster resources
-| Name | Kind | Details | Created when |
-| --- | --- | --- | --- |
-| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new GKE Cluster |
-| `gitlab-admin` | `ClusterRoleBinding` | [`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Creating a new GKE Cluster |
-| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new GKE Cluster |
-| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
-| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
-| Project namespace | `ServiceAccount` | Uses namespace of Project | Creating/Adding a new GKE Cluster |
-| Project namespace | `Secret` | Token for project ServiceAccount | Creating/Adding a new GKE Cluster |
-| Project namespace | `RoleBinding` | [`edit`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Creating/Adding a new GKE Cluster |
+GitLab creates the following resources for RBAC clusters.
+
+| Name | Type | Details | Created when |
+|:------------------|:---------------------|:-----------------------------------------------------------------------------------------------------------|:---------------------------|
+| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new GKE Cluster |
+| `gitlab-admin` | `ClusterRoleBinding` | [`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Creating a new GKE Cluster |
+| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new GKE Cluster |
+| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
+| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
+| Project namespace | `ServiceAccount` | Uses namespace of Project | Deploying to a cluster |
+| Project namespace | `Secret` | Token for project ServiceAccount | Deploying to a cluster |
+| Project namespace | `RoleBinding` | [`edit`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Deploying to a cluster |
+
+NOTE: **Note:**
+Project-specific resources are only created if your cluster is [managed by GitLab](#gitlab-managed-clusters).
### Security of GitLab Runners
@@ -314,86 +347,10 @@ install it manually.
## Installing applications
-GitLab provides **GitLab Managed Apps**, a one-click install for various applications which can
-be added directly to your configured cluster. Those applications are
-needed for [Review Apps](../../../ci/review_apps/index.md) and
-[deployments](../../../ci/environments.md). You can install them after you
-[create a cluster](#adding-and-creating-a-new-gke-cluster-via-gitlab).
-
-To see a list of available applications to install:
-
-1. Navigate to your project's **Operations > Kubernetes**.
-1. Select your cluster.
-
-Install Helm Tiller first because it's used to install other applications.
-
-NOTE: **Note:**
-As of GitLab 11.6, Helm Tiller will be upgraded to the latest version supported
-by GitLab before installing any of the applications.
-
-| Application | GitLab version | Description | Helm Chart |
-| ----------- | :------------: | ----------- | --------------- |
-| [Helm Tiller](https://docs.helm.sh/) | 10.2+ | Helm is a package manager for Kubernetes and is required to install all the other applications. It is installed in its own pod inside the cluster which can run the `helm` CLI in a safe environment. | n/a |
-| [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) | 10.2+ | Ingress can provide load balancing, SSL termination, and name-based virtual hosting. It acts as a web proxy for your applications and is useful if you want to use [Auto DevOps] or deploy your own web apps. | [stable/nginx-ingress](https://github.com/helm/charts/tree/master/stable/nginx-ingress) |
-| [Cert-Manager](https://docs.cert-manager.io/en/latest/) | 11.6+ | Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by [Let's Encrypt](https://letsencrypt.org/) and ensure that certificates are valid and up-to-date. | [stable/cert-manager](https://github.com/helm/charts/tree/master/stable/cert-manager) |
-| [Prometheus](https://prometheus.io/docs/introduction/overview/) | 10.4+ | Prometheus is an open-source monitoring and alerting system useful to supervise your deployed applications. | [stable/prometheus](https://github.com/helm/charts/tree/master/stable/prometheus) |
-| [GitLab Runner](https://docs.gitlab.com/runner/) | 10.6+ | GitLab Runner is the open source project that is used to run your jobs and send the results back to GitLab. It is used in conjunction with [GitLab CI/CD](../../../ci/README.md), the open-source continuous integration service included with GitLab that coordinates the jobs. When installing the GitLab Runner via the applications, it will run in **privileged mode** by default. Make sure you read the [security implications](#security-implications) before doing so. | [runner/gitlab-runner](https://gitlab.com/charts/gitlab-runner) |
-| [JupyterHub](http://jupyter.org/) | 11.0+ | [JupyterHub](https://jupyterhub.readthedocs.io/en/stable/) is a multi-user service for managing notebooks across a team. [Jupyter Notebooks](https://jupyter-notebook.readthedocs.io/en/latest/) provide a web-based interactive programming environment used for data analysis, visualization, and machine learning. We use a [custom Jupyter image](https://gitlab.com/gitlab-org/jupyterhub-user-image/blob/master/Dockerfile) that installs additional useful packages on top of the base Jupyter. Authentication will be enabled only for [project members](../members/index.md) with [Developer or higher](../../permissions.md) access to the project. You will also see ready-to-use DevOps Runbooks built with Nurtch's [Rubix library](https://github.com/amit1rrr/rubix). More information on creating executable runbooks can be found in [our Nurtch documentation](runbooks/index.md#nurtch-executable-runbooks). Note that Ingress must be installed and have an IP address assigned before JupyterHub can be installed. | [jupyter/jupyterhub](https://jupyterhub.github.io/helm-chart/) |
-| [Knative](https://cloud.google.com/knative) | 11.5+ | Knative provides a platform to create, deploy, and manage serverless workloads from a Kubernetes cluster. It is used in conjunction with, and includes [Istio](https://istio.io) to provide an external IP address for all programs hosted by Knative. You will be prompted to enter a wildcard domain where your applications will be exposed. Configure your DNS server to use the external IP address for that domain. For any application created and installed, they will be accessible as `<program_name>.<kubernetes_namespace>.<domain_name>`. This will require your kubernetes cluster to have [RBAC enabled](#role-based-access-control-rbac). | [knative/knative](https://storage.googleapis.com/triggermesh-charts)
-
-With the exception of Knative, the applications will be installed in a dedicated
-namespace called `gitlab-managed-apps`.
-
-CAUTION: **Caution:**
-If you have an existing Kubernetes cluster with Tiller already installed,
-you should be careful as GitLab cannot detect it. In this case, installing
-Tiller via the applications will result in the cluster having it twice, which
-can lead to confusion during deployments.
-
-### Upgrading applications
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24789)
-in GitLab 11.8.
-
-Users can perform a one-click upgrade for the GitLab Runner application,
-when there is an upgrade available.
-
-To upgrade the GitLab Runner application:
-
-1. Navigate to your project's **Operations > Kubernetes**.
-1. Select your cluster.
-1. Click the **Upgrade** button for the Runnner application.
-
-The **Upgrade** button will not be shown if there is no upgrade
-available.
-
-NOTE: **Note:**
-Upgrades will reset values back to the values built into the `runner`
-chart plus the values set by
-[`values.yaml`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/vendor/runner/values.yaml)
-
-### Troubleshooting applications
-
-Applications can fail with the following error:
-
-```text
-Error: remote error: tls: bad certificate
-```
-
-To avoid installation errors:
-
-- Before starting the installation of applications, make sure that time is synchronized
- between your GitLab server and your Kubernetes cluster.
-- Ensure certificates are not out of sync. When installing applications, GitLab expects a new cluster with no previous installation of Tiller.
-
- You can confirm that the certificates match via `kubectl`:
-
- ```sh
- kubectl get configmaps/values-content-configuration-ingress -n gitlab-managed-apps -o \
- "jsonpath={.data['cert\.pem']}" | base64 -d > a.pem
- kubectl get secrets/tiller-secret -n gitlab-managed-apps -o "jsonpath={.data['ca\.crt']}" | base64 -d > b.pem
- diff a.pem b.pem
- ```
+GitLab can install and manage some applications in your project-level
+cluster. For more information on installing, upgrading, uninstalling,
+and troubleshooting applications for your project cluster, see
+[Gitlab Managed Apps](../../clusters/applications.md).
## Getting the external endpoint
@@ -493,7 +450,7 @@ differentiate the new cluster with the rest.
When adding more than one Kubernetes cluster to your project, you need to differentiate
them with an environment scope. The environment scope associates clusters with [environments](../../../ci/environments.md) similar to how the
-[environment-specific variables](https://docs.gitlab.com/ee/ci/variables/README.html#limiting-environment-scopes-of-variables-premium) work.
+[environment-specific variables](../../../ci/variables/README.md#limiting-environment-scopes-of-environment-variables-premium) work.
The default environment scope is `*`, which means all jobs, regardless of their
environment, will use that cluster. Each scope can only be used by a single
@@ -565,7 +522,9 @@ service account of the cluster integration.
### Troubleshooting failed deployment jobs
GitLab will create a namespace and service account specifically for your
-deployment jobs, immediately before the jobs starts.
+deployment jobs. On project level clusters, this happens when the cluster
+is created. On group level clusters, resources are created immediately
+before the deployment job starts.
However, sometimes GitLab can not create them. In such instances, your job will fail with the message:
@@ -589,7 +548,7 @@ Common reasons for failure include:
When [Prometheus is deployed](#installing-applications), GitLab will automatically monitor the cluster's health. At the top of the cluster settings page, CPU and Memory utilization is displayed, along with the total amount available. Keeping an eye on cluster resources can be important, if the cluster runs out of memory pods may be shutdown or fail to start.
-![Cluster Monitoring](https://docs.gitlab.com/ee/user/project/clusters/img/k8s_cluster_monitoring.png)
+![Cluster Monitoring](img/k8s_cluster_monitoring.png)
## Enabling or disabling the Kubernetes cluster integration
@@ -617,11 +576,6 @@ To remove the Kubernetes cluster integration from your project, simply click the
**Remove integration** button. You will then be able to follow the procedure
and add a Kubernetes cluster again.
-## View Kubernetes pod logs from GitLab **[ULTIMATE]**
-
-Learn how to easily
-[view the logs of running pods in connected Kubernetes clusters](https://docs.gitlab.com/ee/user/project/clusters/kubernetes_pod_logs.html).
-
## What you can get with the Kubernetes integration
Here's what you can do with GitLab if you enable the Kubernetes integration.
@@ -634,7 +588,7 @@ displaying the status of the pods in the deployment. Developers and other
teammates can view the progress and status of a rollout, pod by pod, in the
workflow they already use without any need to access Kubernetes.
-[Read more about Deploy Boards](https://docs.gitlab.com/ee/user/project/deploy_boards.html)
+[Read more about Deploy Boards](../deploy_boards.md)
### Canary Deployments **[PREMIUM]**
@@ -642,7 +596,13 @@ Leverage [Kubernetes' Canary deployments](https://kubernetes.io/docs/concepts/cl
and visualize your canary deployments right inside the Deploy Board, without
the need to leave GitLab.
-[Read more about Canary Deployments](https://docs.gitlab.com/ee/user/project/canary_deployments.html)
+[Read more about Canary Deployments](../canary_deployments.md)
+
+### Pod logs **[ULTIMATE]**
+
+GitLab makes it easy to view the logs of running pods in connected Kubernetes clusters. By displaying the logs directly in GitLab, developers can avoid having to manage console tools or jump to a different interface.
+
+[Read more about Kubernetes pod logs](kubernetes_pod_logs.md)
### Kubernetes monitoring
diff --git a/doc/user/project/clusters/kubernetes_pod_logs.md b/doc/user/project/clusters/kubernetes_pod_logs.md
new file mode 100644
index 00000000000..368031070c1
--- /dev/null
+++ b/doc/user/project/clusters/kubernetes_pod_logs.md
@@ -0,0 +1,21 @@
+# Kubernetes Pod Logs **[ULTIMATE]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/4752) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0.
+
+GitLab makes it easy to view the logs of running pods in [connected Kubernetes clusters](index.md).
+By displaying the logs directly in GitLab, developers can avoid having to manage console tools or jump to a different interface.
+
+## Overview
+
+[Kubernetes](https://kubernetes.io) pod logs can be viewed directly within GitLab. Logs can be displayed by clicking on a specific pod from [Deploy Boards](../deploy_boards.md):
+
+1. Go to **Operations > Environments** and find the environment which contains the desired pod, like `production`.
+1. On the **Environments** page, you should see the status of the environment's pods with [Deploy Boards](../deploy_boards.md).
+1. When mousing over the list of pods, a tooltip will appear with the exact pod name and status.
+![Deploy Boards pod list](img/pod_logs_deploy_board.png)
+1. Click on the desired pod to bring up the logs view, which will contain the last 500 lines for that pod. Support for pods with multiple containers is coming [in a future release](https://gitlab.com/gitlab-org/gitlab-ee/issues/6502).
+![Deploy Boards pod list](img/kubernetes_pod_logs.png)
+
+## Requirements
+
+[Enabling Deploy Boards](../deploy_boards.md#enabling-deploy-boards) is required in order to be able to use Pod Logs.
diff --git a/doc/user/project/clusters/runbooks/index.md b/doc/user/project/clusters/runbooks/index.md
index 54c475a1762..c67b12fb91a 100644
--- a/doc/user/project/clusters/runbooks/index.md
+++ b/doc/user/project/clusters/runbooks/index.md
@@ -17,13 +17,15 @@ Modern implementations have introduced the concept of an "executable
runbooks", where, along with a well-defined process, operators can execute
pre-written code blocks or database queries against a given environment.
-## Nurtch Executable Runbooks
+## Executable Runbooks
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/45912) in GitLab 11.4.
The JupyterHub app offered via GitLab’s Kubernetes integration now ships
with Nurtch’s Rubix library, providing a simple way to create DevOps
-runbooks. A sample runbook is provided, showcasing common operations.
+runbooks. A sample runbook is provided, showcasing common operations. While Rubix makes it
+simple to create common Kubernetes and AWS workflows, you can also create them manually without
+Rubix.
**<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
Watch this [video](https://www.youtube.com/watch?v=Q_OqHIIUPjE)
@@ -34,7 +36,7 @@ for an overview of how this is accomplished in GitLab!**
To create an executable runbook, you will need:
1. **Kubernetes** - A Kubernetes cluster is required to deploy the rest of the applications.
- The simplest way to get started is to add a cluster using [GitLab's GKE integration](https://docs.gitlab.com/ee/user/project/clusters/#adding-and-creating-a-new-gke-cluster-via-gitlab).
+ The simplest way to get started is to add a cluster using [GitLab's GKE integration](../index.md#adding-and-creating-a-new-gke-cluster-via-gitlab).
1. **Helm Tiller** - Helm is a package manager for Kubernetes and is required to install
all the other applications. It is installed in its own pod inside the cluster which
can run the helm CLI in a safe environment.
@@ -59,7 +61,7 @@ the components outlined above and the preloaded demo runbook.
### 1. Add a Kubernetes cluster
-Follow the steps outlined in [Adding and creating a new GKE cluster via GitLab](https://docs.gitlab.com/ee/user/project/clusters/#adding-and-creating-a-new-gke-cluster-via-gitlab)
+Follow the steps outlined in [Adding and creating a new GKE cluster via GitLab](../index.md#adding-and-creating-a-new-gke-cluster-via-gitlab)
to add a Kubernetes cluster to your project.
### 2. Install Helm Tiller, Ingress, and JupyterHub
@@ -90,7 +92,7 @@ The server will take a couple of seconds to start.
### 4. Configure access
In order for the runbook to access your GitLab project, you will need to enter a
-[GitLab Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html)
+[GitLab Access Token](../../../profile/personal_access_tokens.md)
as well as your Project ID in the **Setup** section of the demo runbook.
Double-click the **DevOps-Runbook-Demo** folder located on the left panel.
diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md
index 5b7e9ef906f..2cda850f24e 100644
--- a/doc/user/project/clusters/serverless/index.md
+++ b/doc/user/project/clusters/serverless/index.md
@@ -158,21 +158,6 @@ Follow these steps to deploy a function using the Node.js runtime to your Knativ
description: "node.js runtime function"
environment:
MY_FUNCTION: echo-js
-
- echo-rb:
- handler: MyEcho.my_function
- source: ./echo-rb
- runtime: https://gitlab.com/gitlab-org/serverless/runtimes/ruby
- description: "Ruby runtime function"
- environment:
- MY_FUNCTION: echo-rb
-
- echo-docker:
- handler: echo-docker
- source: ./echo-docker
- description: "Dockerfile runtime function"
- environment:
- MY_FUNCTION: echo-docker
```
Explanation of the fields used above:
@@ -231,7 +216,7 @@ The sample function can now be triggered from any HTTP client using a simple `PO
--header "Content-Type: application/json" \
--request POST \
--data '{"GitLab":"FaaS"}' \
- http://functions-echo.functions-1.functions.example.com
+ http://functions-echo.functions-1.functions.example.com/
```
2. Using a web-based tool (ie. postman, restlet, etc)
diff --git a/doc/user/project/code_owners.md b/doc/user/project/code_owners.md
new file mode 100644
index 00000000000..ae04616943f
--- /dev/null
+++ b/doc/user/project/code_owners.md
@@ -0,0 +1,85 @@
+# Code Owners **[STARTER]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/6916)
+in [GitLab Starter](https://about.gitlab.com/pricing/) 11.3.
+
+You can use a `CODEOWNERS` file to specify users that are responsible
+for certain files in a repository.
+
+You can choose and add the `CODEOWNERS` file in three places:
+
+- to the root directory of the repository
+- inside the `.gitlab/` directory
+- inside the `docs/` directory
+
+The `CODEOWNERS` file is scoped to a branch, which means that with the
+introduction of new files, the person adding the new content can
+specify themselves as a code owner, all before the new changes
+get merged to the default branch.
+
+When a file matches multiple entries in the `CODEOWNERS` file,
+the users from all entries are displayed on the blob page of
+the given file.
+
+## The syntax of Code Owners files
+
+Files can be specified using the same kind of patterns you would use
+in the `.gitignore` file followed by the `@username` or email of one
+or more users that should be owners of the file.
+
+The order in which the paths are defined is significant: the last
+pattern that matches a given path will be used to find the code
+owners.
+
+Starting a line with a `#` indicates a comment. This needs to be
+escaped using `\#` to address files for which the name starts with a
+`#`.
+
+Example `CODEOWNERS` file:
+
+```
+# This is an example code owners file, lines starting with a `#` will
+# be ignored.
+
+# app/ @commented-rule
+
+# We can specify a default match using wildcards:
+* @default-codeowner
+
+# Rules defined later in the file take precedence over the rules
+# defined before.
+# This will match all files for which the file name ends in `.rb`
+*.rb @ruby-owner
+
+# Files with a `#` can still be accesssed by escaping the pound sign
+\#file_with_pound.rb @owner-file-with-pound
+
+# Multiple codeowners can be specified, separated by whitespace
+CODEOWNERS @multiple @owners @tab-separated
+
+# Both usernames or email addresses can be used to match
+# users. Everything else will be ignored. For example this will
+# specify `@legal` and a user with email `janedoe@gitlab.com` as the
+# owner for the LICENSE file
+LICENSE @legal this_does_not_match janedoe@gitlab.com
+
+# Ending a path in a `/` will specify the code owners for every file
+# nested in that directory, on any level
+/docs/ @all-docs
+
+# Ending a path in `/*` will specify code owners for every file in
+# that directory, but not nested deeper. This will match
+# `docs/index.md` but not `docs/projects/index.md`
+/docs/* @root-docs
+
+# This will make a `lib` directory nested anywhere in the repository
+# match
+lib/ @lib-owner
+
+# This will only match a `config` directory in the root of the
+# repository
+/config/ @config-owner
+
+# If the path contains spaces, these need to be escaped like this:
+path\ with\ spaces/ @space-owner
+```
diff --git a/doc/user/project/container_registry.md b/doc/user/project/container_registry.md
index 83b268db967..58b7fe33906 100644
--- a/doc/user/project/container_registry.md
+++ b/doc/user/project/container_registry.md
@@ -53,7 +53,7 @@ If you visit the **Registry** link under your project's menu, you can see the
explicit instructions to login to the Container Registry using your GitLab
credentials.
-For example if the Registry's URL is `registry.example.com`, the you should be
+For example if the Registry's URL is `registry.example.com`, then you should be
able to login with:
```
@@ -204,7 +204,7 @@ at the communication between the client and the Registry.
The REST API between the Docker client and Registry is [described
here](https://docs.docker.com/registry/spec/api/). Normally, one would just
use Wireshark or tcpdump to capture the traffic and see where things went
-wrong. However, since all communication between Docker clients and servers
+wrong. However, since all communications between Docker clients and servers
are done over HTTPS, it's a bit difficult to decrypt the traffic quickly even
if you know the private key. What can we do instead?
diff --git a/doc/user/project/cycle_analytics.md b/doc/user/project/cycle_analytics.md
index 19ab911e39f..dc97a44fd68 100644
--- a/doc/user/project/cycle_analytics.md
+++ b/doc/user/project/cycle_analytics.md
@@ -1,10 +1,7 @@
# Cycle Analytics
-> [Introduced][ce-5986] in GitLab 8.12. Further features were added in GitLab
- 8.14.
-
-Cycle Analytics measures the time spent to go from an [idea to production] for
-each of your projects. Cycle Analytics displays the median time for an idea to
+Cycle Analytics measures the time spent to go from an [idea to production] - also known
+as cycle time - for each of your projects. Cycle Analytics displays the median time for an idea to
reach production, along with the time typically spent in each DevOps stage along the way.
Cycle Analytics is useful in order to quickly determine the velocity of a given
@@ -54,9 +51,9 @@ Below you can see in more detail what the various stages of Cycle Analytics mean
| Issue | Measures the median time between creating an issue and taking action to solve it, by either labeling it or adding it to a milestone, whatever comes first. The label will be tracked only if it already has an [Issue Board list][board] created for it. |
| Plan | Measures the median time between the action you took for the previous stage, and pushing the first commit to the branch. The very first commit of the branch is the one that triggers the separation between **Plan** and **Code**, and at least one of the commits in the branch needs to contain the related issue number (e.g., `#42`). If none of the commits in the branch mention the related issue number, it is not considered to the measurement time of the stage. |
| Code | Measures the median time between pushing a first commit (previous stage) and creating a merge request (MR) related to that commit. The key to keep the process tracked is to include the [issue closing pattern] to the description of the merge request (for example, `Closes #xxx`, where `xxx` is the number of the issue related to this merge request). If the issue closing pattern is not present in the merge request description, the MR is not considered to the measurement time of the stage. |
-| Test | Measures the median time to run the entire pipeline for that project. It's related to the time GitLab CI takes to run every job for the commits pushed to that merge request defined in the previous stage. It is basically the start->finish time for all pipelines. `master` is not excluded. It does not attempt to track time for any particular stages. |
-| Review | Measures the median time taken to review the merge request, between its creation and until it's merged. |
-| Staging | Measures the median time between merging the merge request until the very first deployment to production. It's tracked by the [environment] set to `production` or matching `production/*` (case-sensitive, `Production` won't work) in your GitLab CI configuration. If there isn't a production environment, this is not tracked. |
+| Test | Measures the median time to run the entire pipeline for that project. It's related to the time GitLab CI takes to run every job for the commits pushed to that merge request defined in the previous stage. It is basically the start->finish time for all pipelines. |
+| Review | Measures the median time taken to review the merge request that has closing issue pattern, between its creation and until it's merged. |
+| Staging | Measures the median time between merging the merge request with closing issue pattern until the very first deployment to production. It's tracked by the [environment] set to `production` or matching `production/*` (case-sensitive, `Production` won't work) in your GitLab CI configuration. If there isn't a production environment, this is not tracked. |
| Production| The sum of all time (medians) taken to run the entire process, from issue creation to deploying the code to production. |
---
@@ -77,8 +74,7 @@ To sum up, anything that doesn't follow the [GitLab flow] won't be tracked at al
So, the Cycle Analytics dashboard won't present any data:
- For merge requests that do not close an issue.
-- For issues not labeled with a label present in the Issue Board.
-- For issues not assigned a milestone.
+- For issues not labeled with a label present in the Issue Board or for issues not assigned a milestone.
- For staging and production stages, if the project has no `production` or `production/*`
environment.
@@ -86,7 +82,7 @@ So, the Cycle Analytics dashboard won't present any data:
Below is a simple fictional workflow of a single cycle that happens in a
single day passing through all seven stages. Note that if a stage does not have
-a start/stop mark, it is not measured and hence not calculated in the median
+a start and a stop mark, it is not measured and hence not calculated in the median
time. It is assumed that milestones are created and CI for testing and setting
environments is configured.
diff --git a/doc/user/project/deploy_boards.md b/doc/user/project/deploy_boards.md
new file mode 100644
index 00000000000..0994c51abb2
--- /dev/null
+++ b/doc/user/project/deploy_boards.md
@@ -0,0 +1,126 @@
+# Deploy Boards **[PREMIUM]**
+
+> [Introduced][ee-1589] in [GitLab Premium][ee] 9.0.
+
+GitLab's Deploy Boards offer a consolidated view of the current health and
+status of each CI [environment] running on [Kubernetes], displaying the status
+of the pods in the deployment. Developers and other teammates can view the
+progress and status of a rollout, pod by pod, in the workflow they already use
+without any need to access Kubernetes.
+
+## Overview
+
+With Deploy Boards you can gain more insight into deploys with benefits such as:
+
+- Following a deploy from the start, not just when it's done
+- Watching the rollout of a build across multiple servers
+- Finer state detail (Waiting, Deploying, Finished, Unknown)
+- See [Canary Deployments](canary_deployments.md)
+
+Here's an example of a Deploy Board of the production environment.
+
+![Deploy Boards landing page](img/deploy_boards_landing_page.png)
+
+The squares represent pods in your Kubernetes cluster that are associated with
+the given environment. Hovering above each square you can see the state of a
+deploy rolling out. The percentage is the percent of the pods that are updated
+to the latest release.
+
+Since Deploy Boards are tightly coupled with Kubernetes, there is some required
+knowledge. In particular you should be familiar with:
+
+- [Kubernetes pods](https://kubernetes.io/docs/user-guide/pods)
+- [Kubernetes labels](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/)
+- [Kubernetes namespaces](https://kubernetes.io/docs/user-guide/namespaces/)
+- [Kubernetes canary deployments](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments)
+
+## Use cases
+
+Since the Deploy Board is a visual representation of the Kubernetes pods for a
+specific environment, there are lot of uses cases. To name a few:
+
+- You want to promote what's running in staging, to production. You go to the
+ environments list, verify that what's running in staging is what you think is
+ running, then click on the [manual action](../../ci/yaml/README.md#whenmanual) to deploy to production.
+- You trigger a deploy, and you've got lots of containers to upgrade so you know
+ it'll take a while (you've also throttled your deploy to only take down X
+ containers at a time). But you need to tell someone when it's deployed, so you
+ go to the environments list, look at the production environment to see what
+ the progress is in real-time as each pod is rolled.
+- You get a report that something is weird in production, so you look at the
+ production environment to see what is running, and if a deploy is ongoing or
+ stuck or failed.
+- You've got an MR that looks good, but you want to run it on staging because
+ staging is set up in some way closer to production. You go to the environment
+ list, find the [Review App][review apps] you're interested in, and click the
+ manual action to deploy it to staging.
+
+## Enabling Deploy Boards
+
+To display the Deploy Boards for a specific [environment] you should:
+
+1. Have a Kubernetes cluster up and running.
+
+ NOTE: **Running on OpenShift:**
+ If you are using OpenShift, ensure that you're using the `Deployment` resource
+ instead of `DeploymentConfiguration`, otherwise the Deploy Boards won't render
+ correctly. For more information, read the
+ [OpenShift docs](https://docs.openshift.com/container-platform/3.7/dev_guide/deployments/kubernetes_deployments.html#kubernetes-deployments-vs-deployment-configurations)
+ and [GitLab issue #4584](https://gitlab.com/gitlab-org/gitlab-ee/issues/4584).
+
+1. [Configure GitLab Runner][runners] with the [Docker][docker-exec] or
+ [Kubernetes][kube-exec] executor.
+1. Configure the [Kubernetes service][kube-service] in your project for the
+ cluster. The Kubernetes namespace is of particular note as you will need it
+ for your deployment scripts (exposed by the `KUBE_NAMESPACE` env variable).
+1. Ensure Kubernetes annotations of `app.gitlab.com/env: $CI_ENVIRONMENT_SLUG`
+ and `app.gitlab.com/app: $CI_PROJECT_PATH_SLUG` are applied to the
+ deployments, replica sets, and pods, where `$CI_ENVIRONMENT_SLUG` and
+ `$CI_PROJECT_PATH_SLUG` are the values of the CI variables. This is so we can
+ lookup the proper environment in a cluster/namespace which may have more
+ than one. These resources should be contained in the namespace defined in
+ the Kubernetes service setting. You can use an [Autodeploy] `.gitlab-ci.yml`
+ template which has predefined stages and commands to use, and automatically
+ applies the annotations. Each project will need to have a unique namespace in
+ Kubernetes as well. The image below demonstrates how this is shown inside
+ Kubernetes.
+
+ NOTE: **Note:**
+ The Kubernetes label of `app` is deprecated and may be removed in next major
+ release, GitLab 12.0.
+
+ ![Deploy Boards Kubernetes Label](img/deploy_boards_kubernetes_label.png)
+
+Once all of the above are set up and the pipeline has run at least once,
+navigate to the environments page under **Operations > Environments**.
+
+Deploy Boards are visible by default. You can explicitly click
+the triangle next to their respective environment name in order to hide them.
+
+## Canary Deployments
+
+A popular CI strategy, where a small portion of the fleet is updated to the new
+version of your application.
+
+[Read more about Canary Deployments.](canary_deployments.md)
+
+## Further reading
+
+- [GitLab Autodeploy][autodeploy]
+- [GitLab CI environment variables][variables]
+- [Environments and deployments][environment]
+- [Kubernetes deploy example][kube-deploy]
+
+[ee-1589]: https://gitlab.com/gitlab-org/gitlab-ee/issues/1589 "Deploy Boards initial issue"
+[ee]: https://about.gitlab.com/pricing/ "GitLab Enterprise Edition landing page"
+[kube-deploy]: https://gitlab.com/gitlab-examples/kubernetes-deploy "Kubernetes deploy example project"
+[kubernetes]: https://kubernetes.io "Kubernetes website"
+[environment]: ../../ci/environments.md "Environments and deployments documentation"
+[docker-exec]: https://docs.gitlab.com/runner/executors/docker.html "GitLab Runner Docker executor"
+[kube-exec]: https://docs.gitlab.com/runner/executors/kubernetes.html "GitLab Runner Kubernetes executor"
+[kube-service]: integrations/kubernetes.md "Kubernetes project service"
+[review apps]: ../../ci/review_apps/index.md "Review Apps documentation"
+[variables]: ../../ci/variables/README.md "GitLab CI variables"
+[autodeploy]: ../../ci/autodeploy/index.md "GitLab Autodeploy"
+[kube-image]: https://gitlab.com/gitlab-examples/kubernetes-deploy/container_registry "Kubernetes deploy Container Registry"
+[runners]: ../../ci/runners/README.md
diff --git a/doc/user/project/deploy_tokens/index.md b/doc/user/project/deploy_tokens/index.md
index 7688508c6ac..92a29b68a22 100644
--- a/doc/user/project/deploy_tokens/index.md
+++ b/doc/user/project/deploy_tokens/index.md
@@ -5,7 +5,7 @@
Deploy tokens allow to download (through `git clone`), or read the container registry images of a project without the need of having a user and a password.
Please note, that the expiration of deploy tokens happens on the date you define,
-at midnight UTC and that they can be only managed by [maintainers](https://docs.gitlab.com/ee/user/permissions.html).
+at midnight UTC and that they can be only managed by [maintainers](../../permissions.md).
## Creating a Deploy Token
diff --git a/doc/user/project/description_templates.md b/doc/user/project/description_templates.md
index 08647caaf07..05ad15476ab 100644
--- a/doc/user/project/description_templates.md
+++ b/doc/user/project/description_templates.md
@@ -2,8 +2,12 @@
>[Introduced][ce-4981] in GitLab 8.11.
+We all know that a properly submitted issue is more likely to be addressed in
+a timely manner by the developers of a project.
+
Description templates allow you to define context-specific templates for issue
-and merge request description fields for your project.
+and merge request description fields for your project, as well as help filter
+out a lot of unnecessary noise from issues.
## Overview
@@ -18,6 +22,18 @@ Description templates must be written in [Markdown](../markdown.md) and stored
in your project's repository under a directory named `.gitlab`. Only the
templates of the default branch will be taken into account.
+## Use-cases
+
+- Add a template to be used in every issue for a specific project,
+giving instructions and guidelines, requiring for information specific to that subject.
+For example, if you have a project for tracking new blog posts, you can require the
+title, outlines, author name, author social media information, etc.
+- Following the previous example, you can make a template for every MR submitted
+with a new blog post, requiring information about the post date, frontmatter data,
+images guidelines, link to the related issue, reviewer name, etc.
+- You can also create issues and merge request templates for different
+stages of your workflow, e.g., feature proposal, feature improvement, bug report, etc.
+
## Creating issue templates
Create a new Markdown (`.md`) file inside the `.gitlab/issue_templates/`
@@ -39,12 +55,38 @@ changes you made after picking the template and return it to its initial status.
![Description templates](img/description_templates.png)
+## Setting a default template for issues and merge requests **[STARTER]**
+
+> **Notes:**
+> - This feature was introduced before [description templates](#overview) and is
+> available in [GitLab Starter][products]. It can be enabled
+> in the project's settings.
+> - Templates for issues were [introduced][ee-28] in GitLab EE 8.1.
+> - Templates for merge requests were [introduced][ee-7478ece] in GitLab EE 6.9.
+
+The visibility of issues and/or merge requests should be set to either "Everyone
+with access" or "Only team members" in your project's **Settings** otherwise the
+template text areas won't show. This is the default behavior so in most cases
+you should be fine.
+
+Go to your project's **Settings** and fill in the "Default description template
+for issues" and "Default description template for merge requests" text areas
+for issues and merge requests respectively. Since GitLab issues and merge
+request support [Markdown](../markdown.md), you can use special markup like
+headings, lists, etc.
+
+![Default description templates](img/description_templates_default_settings.png)
+
+After you add the description, hit **Save changes** for the settings to take
+effect. Now, every time a new issue or merge request is created, it will be
+pre-filled with the text you entered in the template(s).
+
## Description template example
We make use of Description Templates for Issues and Merge Requests within the GitLab Community Edition project. Please refer to the [`.gitlab` folder][gitlab-ce-templates] for some examples.
> **Tip:**
-It is possible to use [quick actions](./quick_actions.md) within description templates to quickly add labels, assignees, and milestones. The quick actions will only be executed if the user submitting the Issue or Merge Request has the permissions perform the relevant actions.
+It is possible to use [quick actions](quick_actions.md) within description templates to quickly add labels, assignees, and milestones. The quick actions will only be executed if the user submitting the Issue or Merge Request has the permissions perform the relevant actions.
Here is an example for a Bug report template:
@@ -93,3 +135,6 @@ Possible fixes
[ce-4981]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4981
[gitlab-ce-templates]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/.gitlab
+[ee-28]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/28 "Merge Request for adding issues template"
+[ee-7478ece]: https://gitlab.com/gitlab-org/gitlab-ee/commit/7478ece8b48e80782b5465b96c79f85cc91d391b "Commit that introduced merge requests templates"
+[products]: https://about.gitlab.com/pricing/
diff --git a/doc/user/project/file_lock.md b/doc/user/project/file_lock.md
new file mode 100644
index 00000000000..3386eb9d0d4
--- /dev/null
+++ b/doc/user/project/file_lock.md
@@ -0,0 +1,101 @@
+# File Locking **[PREMIUM]**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/440) in [GitLab Premium](https://about.gitlab.com/pricing/) 8.9.
+> - This feature needs to have a license with the "File Lock" option enabled.
+> - If you are using Premium but you don't see the "Lock" button, ask your GitLab administrator.
+
+File Locking helps you avoid merge conflicts and better manage your binary files.
+Lock any file or directory, make your changes, and then unlock it so another
+member of the team can edit it.
+
+## Overview
+
+Working with multiple people on the same file can be a risk. Conflicts
+when merging a non-text file are hard to overcome and will require a lot
+of manual work to resolve. With GitLab Premium, File
+Locking helps you avoid merge conflicts and better manage your binary
+files by preventing everyone, except you, from modifying a specific file
+or entire directory.
+
+## Use-cases
+
+The file locking feature is useful in situations when:
+
+- Multiple people are working on the same file and you want to avoid merge
+ conflicts.
+- Your repository contains binary files in which situation there is no easy
+ way to tell the diff between yours and your colleagues' changes.
+- Prevent design assets from being overwritten.
+
+Locked directories are locked recursively, which means that everything that
+lies under them is also locked.
+
+## Permissions on file locking
+
+The user that locks a file or directory **is the only one** that can edit and
+push their changes back to the repository where the locked objects are located.
+
+Locks can be created by any person who has [push access](../../user/permissions.md) to the repository; i.e.,
+Developer and higher level, and can be removed solely by their author and any
+user with Maintainer permissions and above.
+
+If a file is locked and you are not the author of its locked state, a
+pre-receive hook will reject your changes when you try to push. In the
+following example, a user who has no permissions on the locked `.gitignore`
+file will see the message below:
+
+```bash
+Counting objects: 3, done.
+Delta compression using up to 4 threads.
+Compressing objects: 100% (3/3), done.
+Writing objects: 100% (3/3), 320 bytes | 0 bytes/s, done.
+Total 3 (delta 1), reused 0 (delta 0)
+remote: GitLab: The path '.gitignore' is locked by Administrator
+To https://example.com/gitlab-org/gitlab-ce.git
+ ! [remote rejected] master -> master (pre-receive hook declined)
+ error: failed to push some refs to 'https://example.com/gitlab-org/gitlab-ce.git'
+```
+
+Similarly, when a user that is not the author of the locked state of a file
+accepts a merge request, an error message will appear stating that the file
+is locked.
+
+![Merge request error message](img/file_lock_merge_request_error_message.png)
+
+## Locking a file or a directory
+
+>**Note:**
+Locking only works for the default branch you have set in the project's settings
+(usually `master`).
+
+To lock a file, navigate to the repository tree under the **Repository > Files** tab,
+pick the file you want to lock and hit the "Lock" button.
+
+![Locking file](img/file_lock.png)
+
+---
+
+To lock an entire directory, look for the "Lock" link next to "History".
+
+![Locking directory](img/file_lock_folders.png)
+
+---
+
+After you lock a file or directory, it will appear as locked in the repository
+view.
+
+![Repository view](img/file_lock_repository_view.png)
+
+## Unlocking a file or a directory
+
+To unlock a file or a directory, follow the same procedure as when you locked
+them. For a detailed view of every existing lock, see the next section on
+"Viewing and managing existing locks".
+
+## Viewing and managing existing locks
+
+To view or manage every existing lock, navigate to the
+**Project > Repository > Locked Files** area. There, you can view all existing
+locks and [remove the ones you have permission for](#permissions-on-file-locking).
+
+![Locked Files](img/file_lock_list.png)
diff --git a/doc/user/project/img/deploy_boards_canary_deployments.png b/doc/user/project/img/deploy_boards_canary_deployments.png
new file mode 100644
index 00000000000..037b4a908ab
--- /dev/null
+++ b/doc/user/project/img/deploy_boards_canary_deployments.png
Binary files differ
diff --git a/doc/user/project/img/deploy_boards_kubernetes_label.png b/doc/user/project/img/deploy_boards_kubernetes_label.png
new file mode 100644
index 00000000000..19785c74d07
--- /dev/null
+++ b/doc/user/project/img/deploy_boards_kubernetes_label.png
Binary files differ
diff --git a/doc/user/project/img/deploy_boards_landing_page.png b/doc/user/project/img/deploy_boards_landing_page.png
new file mode 100644
index 00000000000..c9621a06860
--- /dev/null
+++ b/doc/user/project/img/deploy_boards_landing_page.png
Binary files differ
diff --git a/doc/user/project/img/description_templates_default_settings.png b/doc/user/project/img/description_templates_default_settings.png
new file mode 100644
index 00000000000..ab314e83d06
--- /dev/null
+++ b/doc/user/project/img/description_templates_default_settings.png
Binary files differ
diff --git a/doc/user/project/img/file_lock.png b/doc/user/project/img/file_lock.png
new file mode 100644
index 00000000000..33f96f20e91
--- /dev/null
+++ b/doc/user/project/img/file_lock.png
Binary files differ
diff --git a/doc/user/project/img/file_lock_folders.png b/doc/user/project/img/file_lock_folders.png
new file mode 100644
index 00000000000..5ff3d4d9dbd
--- /dev/null
+++ b/doc/user/project/img/file_lock_folders.png
Binary files differ
diff --git a/doc/user/project/img/file_lock_list.png b/doc/user/project/img/file_lock_list.png
new file mode 100644
index 00000000000..2c276335c83
--- /dev/null
+++ b/doc/user/project/img/file_lock_list.png
Binary files differ
diff --git a/doc/user/project/img/file_lock_merge_request_error_message.png b/doc/user/project/img/file_lock_merge_request_error_message.png
new file mode 100644
index 00000000000..65bc3692da0
--- /dev/null
+++ b/doc/user/project/img/file_lock_merge_request_error_message.png
Binary files differ
diff --git a/doc/user/project/img/file_lock_repository_view.png b/doc/user/project/img/file_lock_repository_view.png
new file mode 100644
index 00000000000..8f4ef52aacd
--- /dev/null
+++ b/doc/user/project/img/file_lock_repository_view.png
Binary files differ
diff --git a/doc/user/project/img/issue_board.png b/doc/user/project/img/issue_board.png
deleted file mode 100644
index b753593d212..00000000000
--- a/doc/user/project/img/issue_board.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/key_value_labels.png b/doc/user/project/img/key_value_labels.png
new file mode 100644
index 00000000000..bec901f127f
--- /dev/null
+++ b/doc/user/project/img/key_value_labels.png
Binary files differ
diff --git a/doc/user/project/img/labels_epic_sidebar.png b/doc/user/project/img/labels_epic_sidebar.png
new file mode 100644
index 00000000000..f8162d89e9d
--- /dev/null
+++ b/doc/user/project/img/labels_epic_sidebar.png
Binary files differ
diff --git a/doc/user/project/img/labels_sidebar_inline.png b/doc/user/project/img/labels_sidebar_inline.png
deleted file mode 100644
index 2186f14ea92..00000000000
--- a/doc/user/project/img/labels_sidebar_inline.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/priority_sort_order.png b/doc/user/project/img/priority_sort_order.png
deleted file mode 100644
index cd1dd8237c0..00000000000
--- a/doc/user/project/img/priority_sort_order.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/protected_branches_choose_branch.png b/doc/user/project/img/protected_branches_choose_branch.png
deleted file mode 100644
index c2848db9c96..00000000000
--- a/doc/user/project/img/protected_branches_choose_branch.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/protected_branches_error_ui.png b/doc/user/project/img/protected_branches_error_ui.png
deleted file mode 100644
index 62839e49d89..00000000000
--- a/doc/user/project/img/protected_branches_error_ui.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/protected_branches_select_roles_and_users.png b/doc/user/project/img/protected_branches_select_roles_and_users.png
new file mode 100644
index 00000000000..4f62b057cc7
--- /dev/null
+++ b/doc/user/project/img/protected_branches_select_roles_and_users.png
Binary files differ
diff --git a/doc/user/project/img/protected_branches_select_roles_and_users_list.png b/doc/user/project/img/protected_branches_select_roles_and_users_list.png
new file mode 100644
index 00000000000..519f2267496
--- /dev/null
+++ b/doc/user/project/img/protected_branches_select_roles_and_users_list.png
Binary files differ
diff --git a/doc/user/project/img/service_desk_confirmation_email.png b/doc/user/project/img/service_desk_confirmation_email.png
new file mode 100644
index 00000000000..e08dced1e38
--- /dev/null
+++ b/doc/user/project/img/service_desk_confirmation_email.png
Binary files differ
diff --git a/doc/user/project/img/service_desk_disabled.png b/doc/user/project/img/service_desk_disabled.png
new file mode 100644
index 00000000000..3ae64dcbe96
--- /dev/null
+++ b/doc/user/project/img/service_desk_disabled.png
Binary files differ
diff --git a/doc/user/project/img/service_desk_enabled.png b/doc/user/project/img/service_desk_enabled.png
new file mode 100644
index 00000000000..329348e4b52
--- /dev/null
+++ b/doc/user/project/img/service_desk_enabled.png
Binary files differ
diff --git a/doc/user/project/img/service_desk_issue_tracker.png b/doc/user/project/img/service_desk_issue_tracker.png
new file mode 100644
index 00000000000..485751fab0a
--- /dev/null
+++ b/doc/user/project/img/service_desk_issue_tracker.png
Binary files differ
diff --git a/doc/user/project/img/service_desk_nav_item.png b/doc/user/project/img/service_desk_nav_item.png
new file mode 100644
index 00000000000..3420e355f67
--- /dev/null
+++ b/doc/user/project/img/service_desk_nav_item.png
Binary files differ
diff --git a/doc/user/project/img/service_desk_reply.png b/doc/user/project/img/service_desk_reply.png
new file mode 100644
index 00000000000..ae6ce31713b
--- /dev/null
+++ b/doc/user/project/img/service_desk_reply.png
Binary files differ
diff --git a/doc/user/project/img/service_desk_thread.png b/doc/user/project/img/service_desk_thread.png
new file mode 100644
index 00000000000..8d8ac39cc5b
--- /dev/null
+++ b/doc/user/project/img/service_desk_thread.png
Binary files differ
diff --git a/doc/user/project/import/gemnasium.md b/doc/user/project/import/gemnasium.md
new file mode 100644
index 00000000000..7f79ebf6353
--- /dev/null
+++ b/doc/user/project/import/gemnasium.md
@@ -0,0 +1,102 @@
+# Gemnasium **[ULTIMATE]**
+
+This guide describes how to migrate from Gemnasium.com to your own GitLab
+instance or GitLab.com.
+
+## Why is Gemnasium.com closed?
+
+Gemnasium has been [acquired by GitLab](https://about.gitlab.com/press/releases/2018-01-30-gemnasium-acquisition.html)
+in January 2018. Since May 15, 2018, the services provided by Gemnasium are no longer available.
+The team behind Gemnasium has joined GitLab as the new Security Products team
+and is working on a wider range of tools than just Dependency Scanning:
+[SAST](../../application_security/sast/index.md),
+[DAST](../../application_security/dast/index.md),
+[Container Scanning](../../application_security/container_scanning/index.md) and more.
+If you want to continue monitoring your dependencies, see the
+[Migrating to GitLab](#migrating-to-gitlab) section below.
+
+## What happened to my account?
+
+Your account has been automatically closed on May 15th, 2018. If you had a paid
+subscription at that time, your card will be refunded on a pro rata temporis basis.
+You may contact `gemnasium@gitlab.com` regarding your closed account.
+
+## Will my account/data be transferred to GitLab Inc.?
+
+All accounts and data have been deleted on May 15th, 2018. GitLab Inc.
+doesn't know anything about your private data, nor your projects, and therefore
+if they were vulnerable or not. GitLab Inc. takes personal information very seriously.
+
+## What happened to my badge?
+
+To avoid broken 404 images, all badges pointing to Gemnasium.com will be a
+placeholder, inviting you to migrate to GitLab (and pointing to this page).
+
+## Migrating to GitLab
+
+Gemnasium has been ported and integrated directly into GitLab CI/CD.
+You can still benefit from our dependency monitoring features, and it requires
+some steps to migrate your projects. There is no automatic import since GitLab
+doesn't know anything about any projects which existed on Gemnasium.com.
+Security features are free for public (open-source) projects hosted on GitLab.com.
+
+### If your project is hosted on GitLab (https://gitlab.com / self-hosted)
+
+You're almost set! If you're already using
+[Auto DevOps](../../../topics/autodevops/), you are already covered.
+Otherwise, you must configure your `.gitlab-ci.yml` according to the
+[dependency scanning page](../../application_security/dependency_scanning/index.md).
+
+### If your project is hosted on GitHub (https://github.com / GitHub Enterprise)
+
+Since [GitLab 10.6 comes with GitHub integration](https://about.gitlab.com/features/github/),
+GitLab users can now create a CI/CD project in GitLab connected to an external
+GitHub.com or GitHub Enterprise repository. This will automatically prompt
+GitLab CI/CD to run whenever code is pushed to GitHub and post CI/CD results
+back to both GitLab and GitHub when completed.
+
+1. Create a new project, and select the "CI/CD for external repo" tab:
+
+ ![Create new Project](img/gemnasium/create_project.png)
+
+1. Use the "GitHub" button to connect your repositories.
+
+ ![Connect from GitHub](img/gemnasium/connect_github.png)
+
+1. Select the project(s) to be set up with GitLab CI/CD and chose "Connect".
+
+ ![Select projects](img/gemnasium/select_project.png)
+
+ Once the configuration is done, you may click on your new
+ project on GitLab.
+
+ ![click on connected project](img/gemnasium/project_connected.png)
+
+ Your project is now mirrored on GitLab, where the Runners will be able to access
+ your source code and run your tests.
+
+ Optional step: If you set this up on GitLab.com, make sure the project is
+ public (in the project settings) if your GitHub project is public, since
+ the security feature is available only for [GitLab Ultimate](https://about.gitlab.com/pricing).
+
+1. To set up the dependency scanning job, corresponding to what Gemnasium was
+ doing, you must create a `.gitlab-ci.yml` file, or update it according to
+ the [dependency scanning docs](../../application_security/dependency_scanning/index.md).
+ The mirroring is pull-only by default, so you may create or update the file on
+ GitHub:
+
+ ![Edit gitlab-ci.yml file](img/gemnasium/edit_gitlab-ci.png)
+
+1. Once your file has been committed, a new pipeline will be automatically
+ triggered if your file is valid:
+
+ ![pipeline](img/gemnasium/pipeline.png)
+
+1. The result of the job will be visible directly from the pipeline view:
+
+ ![security report](img/gemnasium/report.png)
+
+NOTE: **Note:**
+If you don't commit very often to your project, you may want to use
+[scheduled pipelines](../pipelines/schedules.md) to run the job on a regular
+basis.
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index 63b90dd76fd..e194d57e2e0 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -60,6 +60,8 @@ For additional technical details, you can refer to the
[GitHub Importer](../../../development/github_importer.md "Working with the GitHub importer")
developer documentation.
+For an overview of the import process, see the video [Migrating from GitHub to GitLab](https://youtu.be/VYOXuOg9tQI).
+
## Import your GitHub repository into GitLab
### Using the GitHub integration
@@ -119,9 +121,9 @@ Depending your GitLab tier, [project mirroring](../../../workflow/repository_mir
your imported project in sync with its GitHub copy.
Additionally, you can configure GitLab to send pipeline status updates back GitHub with the
-[GitHub Project Integration](https://docs.gitlab.com/ee/user/project/integrations/github.html). **[PREMIUM]**
+[GitHub Project Integration](../integrations/github.md). **[PREMIUM]**
-If you import your project using [CI/CD for external repo](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/), then both
+If you import your project using [CI/CD for external repo](../../../ci/ci_cd_for_external_repos/index.md), then both
of the above are automatically configured. **[PREMIUM]**
## Improving the speed of imports on self-hosted instances
diff --git a/doc/user/project/import/gitlab_com.md b/doc/user/project/import/gitlab_com.md
index 3b37da67a5b..f48a158e2d3 100644
--- a/doc/user/project/import/gitlab_com.md
+++ b/doc/user/project/import/gitlab_com.md
@@ -1,8 +1,9 @@
# Project importing from GitLab.com to your private GitLab instance
You can import your existing GitLab.com projects to your GitLab instance. But keep in mind that it is possible only if
-GitLab support is enabled on your GitLab instance.
-You can read more about GitLab support [here](http://docs.gitlab.com/ce/integration/gitlab.html)
+GitLab.com integration is enabled on your GitLab instance.
+[Read more about GitLab.com integration for self-managed GitLab instances](../../../integration/gitlab.md).
+
To get to the importer page you need to go to "New project" page.
>**Note:**
diff --git a/doc/user/project/import/img/gemnasium/connect_github.png b/doc/user/project/import/img/gemnasium/connect_github.png
new file mode 100644
index 00000000000..5933f4d5d0a
--- /dev/null
+++ b/doc/user/project/import/img/gemnasium/connect_github.png
Binary files differ
diff --git a/doc/user/project/import/img/gemnasium/create_project.png b/doc/user/project/import/img/gemnasium/create_project.png
new file mode 100644
index 00000000000..6e00bf63405
--- /dev/null
+++ b/doc/user/project/import/img/gemnasium/create_project.png
Binary files differ
diff --git a/doc/user/project/import/img/gemnasium/edit_gitlab-ci.png b/doc/user/project/import/img/gemnasium/edit_gitlab-ci.png
new file mode 100644
index 00000000000..8336c803b83
--- /dev/null
+++ b/doc/user/project/import/img/gemnasium/edit_gitlab-ci.png
Binary files differ
diff --git a/doc/user/project/import/img/gemnasium/pipeline.png b/doc/user/project/import/img/gemnasium/pipeline.png
new file mode 100644
index 00000000000..ae4d5295ffa
--- /dev/null
+++ b/doc/user/project/import/img/gemnasium/pipeline.png
Binary files differ
diff --git a/doc/user/project/import/img/gemnasium/project_connected.png b/doc/user/project/import/img/gemnasium/project_connected.png
new file mode 100644
index 00000000000..8e7216c015b
--- /dev/null
+++ b/doc/user/project/import/img/gemnasium/project_connected.png
Binary files differ
diff --git a/doc/user/project/import/img/gemnasium/report.png b/doc/user/project/import/img/gemnasium/report.png
new file mode 100644
index 00000000000..5c4d58662c0
--- /dev/null
+++ b/doc/user/project/import/img/gemnasium/report.png
Binary files differ
diff --git a/doc/user/project/import/img/gemnasium/select_project.png b/doc/user/project/import/img/gemnasium/select_project.png
new file mode 100644
index 00000000000..588c5ca7ce1
--- /dev/null
+++ b/doc/user/project/import/img/gemnasium/select_project.png
Binary files differ
diff --git a/doc/user/project/import/img/import_projects_from_github_select_auth_method.png b/doc/user/project/import/img/import_projects_from_github_select_auth_method.png
deleted file mode 100644
index 90e6243aec0..00000000000
--- a/doc/user/project/import/img/import_projects_from_github_select_auth_method.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md
index cc73ea95f51..2b6927bd780 100644
--- a/doc/user/project/import/index.md
+++ b/doc/user/project/import/index.md
@@ -13,11 +13,15 @@
1. [From TFS](tfs.md)
1. [From repo by URL](repo_by_url.md)
1. [By uploading a manifest file (AOSP)](manifest.md)
+1. [From Gemnasium](gemnasium.md)
+1. [From Phabricator](phabricator.md)
In addition to the specific migration documentation above, you can import any
Git repository via HTTP from the New Project page. Be aware that if the
repository is too large the import can timeout.
+There is also the option of [connecting your external repository to get CI/CD benefits](../../../ci/ci_cd_for_external_repos/index.md). **[PREMIUM]**
+
## Migrating from self-hosted GitLab to GitLab.com
If you only need to migrate git repos, you can [import each project by URL](repo_by_url.md), but issues and merge requests can't be imported.
diff --git a/doc/user/project/import/phabricator.md b/doc/user/project/import/phabricator.md
new file mode 100644
index 00000000000..5c624e3aff6
--- /dev/null
+++ b/doc/user/project/import/phabricator.md
@@ -0,0 +1,29 @@
+# Import Phabricator tasks into a GitLab project
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/60562) in
+GitLab 12.0.
+
+GitLab allows you to import all tasks from a Phabricator instance into
+GitLab issues. The import creates a single project with the
+repository disabled.
+
+Currently, only the following basic fields are imported:
+
+- Title
+- Description
+- State (open or closed)
+- Created at
+- Closed at
+
+## Enabling this feature
+
+While this feature is incomplete, a feature flag is required to enable it so that
+we can gain early feedback before releasing it for everyone. To enable it:
+
+1. Run the following command in a Rails console:
+
+ ```ruby
+ Feature.enable(:phabricator_import)
+ ```
+
+1. Enable Phabricator as an [import source](../../admin_area/settings/visibility_and_access_controls.md#import-sources) in the Admin area.
diff --git a/doc/user/project/index.md b/doc/user/project/index.md
index 64139f9dbe9..587b4121e4e 100644
--- a/doc/user/project/index.md
+++ b/doc/user/project/index.md
@@ -13,7 +13,7 @@ the number of private projects you create.
When you create a project in GitLab, you'll have access to a large number of
[features](https://about.gitlab.com/features/):
-**Issues and merge requests:**
+**Repositories:**
- [Issue tracker](issues/index.md): Discuss implementations with your team within issues
- [Issue Boards](issue_board.md): Organize and prioritize your workflow
@@ -28,9 +28,16 @@ When you create a project in GitLab, you'll have access to a large number of
permission to create tags, and prevent accidental update or deletion
- [Signing commits](gpg_signed_commits/index.md): use GPG to sign your commits
- [Deploy tokens](deploy_tokens/index.md): Manage project-based deploy tokens that allow permanent access to the repository and Container Registry.
+- [Web IDE](web_ide/index.md)
+
+**Issues and merge requests:**
+
+- [Issue tracker](issues/index.md): Discuss implementations with your team within issues
+ - [Issue Boards](issue_board.md): Organize and prioritize your workflow
+ - [Multiple Issue Boards](issue_board.md#multiple-issue-boards-starter): Allow your teams to create their own workflows (Issue Boards) for the same project **[STARTER]**
- [Merge Requests](merge_requests/index.md): Apply your branching
strategy and get reviewed by your team
- - [Merge Request Approvals](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html): Ask for approval before
+ - [Merge Request Approvals](merge_requests/merge_request_approvals.md): Ask for approval before
implementing a change **[STARTER]**
- [Fix merge conflicts from the UI](merge_requests/resolve_conflicts.md):
Your Git diff tool right from GitLab's UI
@@ -67,6 +74,8 @@ When you create a project in GitLab, you'll have access to a large number of
timeout (defines the maximum amount of time in minutes that a job is able run), custom path for `.gitlab-ci.yml`, test coverage parsing, pipeline's visibility, and much more
- [Kubernetes cluster integration](clusters/index.md): Connecting your GitLab project
with a Kubernetes cluster
+ - [Feature Flags](operations/feature_flags.md): Feature flags allow you to ship a project in
+ different flavors by dynamically toggling certain functionality **[PREMIUM]**
- [GitLab Pages](pages/index.md): Build, test, and deploy your static
website with GitLab Pages
@@ -75,12 +84,18 @@ When you create a project in GitLab, you'll have access to a large number of
- [Wiki](wiki/index.md): document your GitLab project in an integrated Wiki.
- [Snippets](../snippets.md): store, share and collaborate on code snippets.
- [Cycle Analytics](cycle_analytics.md): review your development lifecycle.
+- [Insights](insights/index.md): configure the Insights that matter for your projects. **[ULTIMATE]**
+- [Security Dashboard](security_dashboard.md): Security Dashboard. **[ULTIMATE]**
- [Syntax highlighting](highlighting.md): an alternative to customize
your code blocks, overriding GitLab's default choice of language.
- [Badges](badges.md): badges for the project overview.
- [Releases](releases/index.md): a way to track deliverables in your project as snapshot in time of
the source, build output, and other metadata or artifacts
associated with a released version of your code.
+- [Maven packages](packages/maven_repository.md): your private Maven repository in GitLab. **[PREMIUM]**
+- [NPM packages](packages/npm_registry.md): your private NPM package registry in GitLab. **[PREMIUM]**
+- [Code owners](code_owners.md): specify code owners for certain files **[STARTER]**
+- [License Management](../application_security/license_management/index.md): approve and blacklist licenses for projects. **[ULTIMATE]**
### Project integrations
@@ -116,6 +131,13 @@ Read through the documentation on [project settings](settings/index.md).
- [Export a project from GitLab](settings/import_export.md#exporting-a-project-and-its-data)
- [Importing and exporting projects between GitLab instances](settings/import_export.md)
+## CI/CD for external repositories **[PREMIUM]**
+
+Instead of importing a repository directly to GitLab, you can connect your repository
+as a CI/CD project.
+
+Read through the documentation on [CI/CD for external repositories](../../ci/ci_cd_for_external_repos/index.md).
+
## Project members
Learn how to [add members to your projects](members/index.md).
diff --git a/doc/user/project/insights/img/insights_example_bar_chart.png b/doc/user/project/insights/img/insights_example_bar_chart.png
new file mode 100644
index 00000000000..eb96eb4a90f
--- /dev/null
+++ b/doc/user/project/insights/img/insights_example_bar_chart.png
Binary files differ
diff --git a/doc/user/project/insights/img/insights_example_bar_time_series_chart.png b/doc/user/project/insights/img/insights_example_bar_time_series_chart.png
new file mode 100644
index 00000000000..28aa81939d8
--- /dev/null
+++ b/doc/user/project/insights/img/insights_example_bar_time_series_chart.png
Binary files differ
diff --git a/doc/user/project/insights/img/insights_example_line_chart.png b/doc/user/project/insights/img/insights_example_line_chart.png
new file mode 100644
index 00000000000..131dbedd35e
--- /dev/null
+++ b/doc/user/project/insights/img/insights_example_line_chart.png
Binary files differ
diff --git a/doc/user/project/insights/img/insights_example_pie_chart.png b/doc/user/project/insights/img/insights_example_pie_chart.png
new file mode 100644
index 00000000000..518ed7338f9
--- /dev/null
+++ b/doc/user/project/insights/img/insights_example_pie_chart.png
Binary files differ
diff --git a/doc/user/project/insights/img/insights_example_stacked_bar_chart.png b/doc/user/project/insights/img/insights_example_stacked_bar_chart.png
new file mode 100644
index 00000000000..aafec4b394e
--- /dev/null
+++ b/doc/user/project/insights/img/insights_example_stacked_bar_chart.png
Binary files differ
diff --git a/doc/user/project/insights/img/insights_sidebar_link.png b/doc/user/project/insights/img/insights_sidebar_link.png
new file mode 100644
index 00000000000..aadb5745992
--- /dev/null
+++ b/doc/user/project/insights/img/insights_sidebar_link.png
Binary files differ
diff --git a/doc/user/project/insights/img/project_insights.png b/doc/user/project/insights/img/project_insights.png
new file mode 100644
index 00000000000..2d0292dda54
--- /dev/null
+++ b/doc/user/project/insights/img/project_insights.png
Binary files differ
diff --git a/doc/user/project/insights/index.md b/doc/user/project/insights/index.md
new file mode 100644
index 00000000000..2e2a27f112e
--- /dev/null
+++ b/doc/user/project/insights/index.md
@@ -0,0 +1,303 @@
+# Insights **[ULTIMATE]**
+
+> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.9 behind the `insights` feature flag.
+> **Generally Available** (GA) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0.
+
+Configure the Insights that matter for your projects to explore data such as
+triage hygiene, issues created/closed per a given period, average time for merge
+requests to be merged and much more.
+
+![Insights example bar chart](img/project_insights.png)
+
+NOTE: **Note:**
+This feature is [also available at the group level](../../group/insights/index.md).
+
+## View your project's Insights
+
+You can access your project's Insights by clicking the **Project > Insights**
+link in the left sidebar:
+
+![Insights sidebar link](img/insights_sidebar_link.png)
+
+## Configure your Insights
+
+Insights are configured using a YAML file called `.gitlab/insights.yml` within
+a project. That file will then be used in the project's Insights page.
+
+See [Writing your `.gitlab/insights.yml`](#writing-your-gitlabinsightsyml) below
+for details about the content of this file.
+
+NOTE: **Note:**
+Once the configuration file is created, you can also
+[use it for your project's group](../../group/insights/index.md#configure-your-insights).
+
+NOTE: **Note:**
+If the project doesn't have any configuration file, it'll try to use
+the group configuration if possible. If the group doesn't have any
+configuration, the default configuration will be used.
+
+## Permissions
+
+If you have access to view a project, then you have access to view their
+Insights.
+
+NOTE: **Note:**
+Issues or merge requests that you don't have access to (because you don't have
+access to the project they belong to, or because they are confidential) are
+filtered out of the Insights charts.
+
+You may also consult the [group permissions table](../../permissions.md#group-members-permissions).
+
+## Writing your `.gitlab/insights.yml`
+
+The `.gitlab/insights.yml` file defines the structure and order of the Insights
+charts that will be displayed in each Insights page of your project or group.
+
+Each page has a unique key and a collection of charts to fetch and display.
+
+For example, here's a single definition for Insights that will display one page with one chart:
+
+```yaml
+bugsCharts:
+ title: 'Charts for Bugs'
+ charts:
+ - title: Monthly Bugs Created (bar)
+ type: bar
+ query:
+ issuable_type: issue
+ issuable_state: opened
+ filter_labels:
+ - bug
+ group_by: month
+ period_limit: 24
+```
+
+Each chart definition is made up of a hash composed of key-value pairs.
+
+For example, here's single chart definition:
+
+```yaml
+- title: Monthly Bugs Created (bar)
+ type: bar
+ query:
+ issuable_type: issue
+ issuable_state: opened
+ filter_labels:
+ - bug
+ group_by: month
+ period_limit: 24
+```
+
+## Configuration parameters
+
+A chart is defined as a list of parameters that define the chart's behavior.
+
+The following table lists available parameters for charts:
+
+| Keyword | Description |
+|:---------------------------------------------------|:------------|
+| [`title`](#title) | The title of the chart. This will displayed on the Insights page. |
+| [`type`](#type) | The type of chart: `bar`, `line`, `stacked-bar`, `pie` etc. |
+| [`query`](#query) | A hash that defines the conditions for issues / merge requests to be part of the chart. |
+
+## Parameter details
+
+The following are detailed explanations for parameters used to configure
+Insights charts.
+
+### `title`
+
+`title` is the title of the chart as it will be displayed on the Insights page.
+For example:
+
+```yaml
+monthlyBugsCreated:
+ title: Monthly Bugs Created (bar)
+```
+
+### `type`
+
+`type` is the chart type.
+
+For example:
+
+```yaml
+monthlyBugsCreated:
+ title: Monthly Bugs Created (bar)
+ type: bar
+```
+
+Supported values are:
+
+| Name | Example |
+| ----- | ------- |
+| `bar` | ![Insights example bar chart](img/insights_example_bar_chart.png) |
+| `bar` (time series, i.e. when `group_by` is used) | ![Insights example bar time series chart](img/insights_example_bar_time_series_chart.png) |
+| `pie` | ![Insights example pie chart](img/insights_example_pie_chart.png) |
+| `line` | ![Insights example stacked bar chart](img/insights_example_line_chart.png) |
+| `stacked-bar` | ![Insights example stacked bar chart](img/insights_example_stacked_bar_chart.png) |
+
+### `query`
+
+`query` allows to define the conditions for issues / merge requests to be part
+of the chart.
+
+Example:
+
+```yaml
+monthlyBugsCreated:
+ title: Monthly Bugs Created (bar)
+ type: bar
+ query:
+ issuable_type: issue
+ issuable_state: opened
+ filter_labels:
+ - bug
+ collection_labels:
+ - S1
+ - S2
+ - S3
+ - S4
+ group_by: week
+ period_limit: 104
+```
+
+#### `query.issuable_type`
+
+Defines the type of "issuable" you want to create a chart for.
+
+Supported values are:
+
+- `issue`: The chart will display issues' data.
+- `merge_request`: The chart will display merge requests' data.
+
+#### `query.issuable_state`
+
+Filter by the state of the queried "issuable".
+
+If you omit it, the `opened` state filter will be applied.
+
+Supported values are:
+
+- `opened`: Open issues / merge requests.
+- `closed`: Closed Open issues / merge requests.
+- `locked`: Issues / merge requests that have their discussion locked.
+- `merged`: Merged merge requests.
+- `all`: Issues / merge requests in all states
+
+#### `query.filter_labels`
+
+Filter by labels applied to the queried "issuable".
+
+If you omit it, no labels filter will be applied. All the defined labels must be
+applied to the "issuable" in order for it to be selected.
+
+Example:
+
+```yaml
+monthlyBugsCreated:
+ title: Monthly regressions Created (bar)
+ type: bar
+ query:
+ issuable_type: issue
+ issuable_state: opened
+ filter_labels:
+ - bug
+ - regression
+```
+
+#### `query.collection_labels`
+
+Group "issuable" by the configured labels.
+
+If you omit it, no grouping will be done. When using this keyword, you need to
+set `type` to either `line` or `stacked-bar`.
+
+Example:
+
+```yaml
+weeklyBugsBySeverity:
+ title: Weekly Bugs By Severity (stacked bar)
+ type: stacked-bar
+ query:
+ issuable_type: issue
+ issuable_state: opened
+ filter_labels:
+ - bug
+ collection_labels:
+ - S1
+ - S2
+ - S3
+ - S4
+```
+
+#### `query.group_by`
+
+Define the X-axis of your chart.
+
+Supported values are:
+
+- `day`: Group data per day.
+- `week`: Group data per week.
+- `month`: Group data per month.
+
+#### `query.period_limit`
+
+Define how far "issuables" are queried in the past.
+
+The unit is related to the `query.group_by` you defined. For instance if you
+defined `query.group_by: 'day'` then `query.period_limit: 365` would mean
+"Gather and display data for the last 365 days".
+
+If you omit it, default values will be applied depending on the `query.group_by`
+you defined.
+
+| `query.group_by` | Default value |
+| ---------------- | ------------- |
+| `day` | 30 |
+| `week` | 4 |
+| `month` | 12 |
+
+## Complete example
+
+```yaml
+bugsCharts:
+ title: 'Charts for Bugs'
+ charts:
+ - title: Monthly Bugs Created (bar)
+ type: bar
+ query:
+ issuable_type: issue
+ issuable_state: opened
+ filter_labels:
+ - bug
+ group_by: month
+ period_limit: 24
+ - title: Weekly Bugs By Severity (stacked bar)
+ type: stacked-bar
+ query:
+ issuable_type: issue
+ issuable_state: opened
+ filter_labels:
+ - bug
+ collection_labels:
+ - S1
+ - S2
+ - S3
+ - S4
+ group_by: week
+ period_limit: 104
+ - title: Monthly Bugs By Team (line)
+ type: line
+ query:
+ issuable_type: merge_request
+ issuable_state: opened
+ filter_labels:
+ - bug
+ collection_labels:
+ - Manage
+ - Plan
+ - Create
+ group_by: month
+ period_limit: 24
+```
diff --git a/doc/user/project/integrations/custom_issue_tracker.md b/doc/user/project/integrations/custom_issue_tracker.md
index 6fc083170b6..23f1ce7a15a 100644
--- a/doc/user/project/integrations/custom_issue_tracker.md
+++ b/doc/user/project/integrations/custom_issue_tracker.md
@@ -7,9 +7,9 @@ in the table below.
| Field | Description |
| ----- | ----------- |
-| `title` | A title for the issue tracker (to differentiate between instances, for example) |
+| `title` | A title for the issue tracker (to differentiate between instances, for example). |
| `description` | A name for the issue tracker (to differentiate between instances, for example) |
-| `project_url` | Currently unused. Will be changed in a future release. |
+| `project_url` | The URL to the project in the custom issue tracker. |
| `issues_url` | The URL to the issue in the issue tracker project that is linked to this GitLab project. Note that the `issues_url` requires `:id` in the URL. This ID is used by GitLab as a placeholder to replace the issue number. For example, `https://customissuetracker.com/project-name/:id`. |
| `new_issue_url` | Currently unused. Will be changed in a future release. |
diff --git a/doc/user/project/integrations/github.md b/doc/user/project/integrations/github.md
new file mode 100644
index 00000000000..cdb0e34fdf6
--- /dev/null
+++ b/doc/user/project/integrations/github.md
@@ -0,0 +1,48 @@
+# GitHub project integration **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/3836) in GitLab Premium 10.6.
+
+GitLab provides an integration for updating the pipeline statuses on GitHub.
+This is especially useful if using GitLab for CI/CD only.
+
+This project integration is separate from the [instance wide GitHub integration](../import/github.md#mirroring-and-pipeline-status-sharing)
+and is automatically configured on [GitHub import](../../../integration/github.md).
+
+![Pipeline status update on GitHub](img/github_status_check_pipeline_update.png)
+
+## Configuration
+
+### Complete these steps on GitHub
+
+This integration requires a [GitHub API token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/)
+with `repo:status` access granted:
+
+1. Go to your "Personal access tokens" page at https://github.com/settings/tokens
+1. Click "Generate New Token"
+1. Ensure that `repo:status` is checked and click "Generate token"
+1. Copy the generated token to use on GitLab
+
+### Complete these steps on GitLab
+
+1. Navigate to the project you want to configure.
+1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services)
+1. Click "GitHub".
+1. Select the "Active" checkbox.
+1. Paste the token you've generated on GitHub
+1. Enter the path to your project on GitHub, such as `https://github.com/username/repository`
+1. Optionally check "Static status check names" checkbox to enable static status check names.
+1. Save or optionally click "Test Settings".
+
+#### Static / dynamic status check names
+
+Since GitLab 11.5 it is possible to opt-in to using static status check names.
+
+This makes it possible to mark these status checks as _Required_ on GitHub.
+If you check "Static status check names" checkbox on the integration page, your
+GitLab instance host name is going to be appended to a status check name,
+whereas in case of dynamic status check names, a branch name is going to be
+appended.
+
+Dynamic status check name is a default behavior.
+
+![Configure GitHub Project Integration](img/github_configuration.png)
diff --git a/doc/user/project/integrations/gitlab_slack_application.md b/doc/user/project/integrations/gitlab_slack_application.md
new file mode 100644
index 00000000000..8e062ca627b
--- /dev/null
+++ b/doc/user/project/integrations/gitlab_slack_application.md
@@ -0,0 +1,65 @@
+# GitLab Slack application **[FREE ONLY]**
+
+NOTE: **Note:**
+The GitLab Slack application is only configurable for GitLab.com. It will **not**
+work for on-premises installations where you can configure the
+[Slack slash commands](slack_slash_commands.md) service instead. We're working
+with Slack on making this configurable for all GitLab installations, but there's
+no ETA.
+It was first introduced in GitLab 9.4 and distributed to Slack App Directory in
+GitLab 10.2.
+
+Slack provides a native application which you can enable via your project's
+integrations on GitLab.com.
+
+## Slack App Directory
+
+The simplest way to enable the GitLab Slack application for your workspace is to
+install the [GitLab application](https://slack-platform.slack.com/apps/A676ADMV5-gitlab) from
+the [Slack App Directory](https://slack.com/apps).
+
+Clicking install will take you to the
+[GitLab Slack application landing page](https://gitlab.com/profile/slack/edit)
+where you can select a project to enable the GitLab Slack application for.
+
+![GitLab Slack application landing page](img/gitlab_slack_app_landing_page.png)
+
+## Configuration
+
+Alternatively, you can configure the Slack application with a project's
+integration settings.
+
+Keep in mind that you need to have the appropriate permissions for your Slack
+team in order to be able to install a new application, read more in Slack's
+docs on [Adding an app to your team][slack-docs].
+
+To enable GitLab's service for your Slack team:
+
+1. Go to your project's **Settings > Integration > Slack application** (only
+ visible on GitLab.com)
+1. Click the "Add to Slack" button
+
+That's all! You can now start using the Slack slash commands.
+
+## Usage
+
+After confirming the installation, you, and everyone else in your Slack team,
+can use all the [slash commands].
+
+When you perform your first slash command you will be asked to authorize your
+Slack user on GitLab.com.
+
+The only difference with the [manually configurable Slack slash commands][slack-manual]
+is that all the commands should be prefixed with the `/gitlab` keyword.
+We are working on making this configurable in the future.
+
+For example, to show the issue number `1001` under the `gitlab-org/gitlab-ce`
+project, you would do:
+
+```
+/gitlab gitlab-org/gitlab-ce issue show 1001
+```
+
+[slack-docs]: https://get.slack.help/hc/en-us/articles/202035138-Adding-apps-to-your-team
+[slash commands]: ../../../integration/slash_commands.md
+[slack-manual]: slack_slash_commands.md
diff --git a/doc/user/project/integrations/img/github_configuration.png b/doc/user/project/integrations/img/github_configuration.png
new file mode 100644
index 00000000000..9f2d47921c7
--- /dev/null
+++ b/doc/user/project/integrations/img/github_configuration.png
Binary files differ
diff --git a/doc/user/project/integrations/img/github_status_check_pipeline_update.png b/doc/user/project/integrations/img/github_status_check_pipeline_update.png
new file mode 100644
index 00000000000..9d02ca18497
--- /dev/null
+++ b/doc/user/project/integrations/img/github_status_check_pipeline_update.png
Binary files differ
diff --git a/doc/user/project/integrations/img/gitlab_slack_app_landing_page.png b/doc/user/project/integrations/img/gitlab_slack_app_landing_page.png
new file mode 100644
index 00000000000..57cd35c9f5d
--- /dev/null
+++ b/doc/user/project/integrations/img/gitlab_slack_app_landing_page.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_add_user_to_group.png b/doc/user/project/integrations/img/jira_add_user_to_group.png
index 27dac49260c..d8cf541a81e 100644
--- a/doc/user/project/integrations/img/jira_add_user_to_group.png
+++ b/doc/user/project/integrations/img/jira_add_user_to_group.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_added_user_to_group.png b/doc/user/project/integrations/img/jira_added_user_to_group.png
new file mode 100644
index 00000000000..b3e29a65d6e
--- /dev/null
+++ b/doc/user/project/integrations/img/jira_added_user_to_group.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_create_new_group.png b/doc/user/project/integrations/img/jira_create_new_group.png
index 06c4e84fc61..84be3a94a45 100644
--- a/doc/user/project/integrations/img/jira_create_new_group.png
+++ b/doc/user/project/integrations/img/jira_create_new_group.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_create_new_user.png b/doc/user/project/integrations/img/jira_create_new_user.png
index e9c03ed770d..8460dc98ef9 100644
--- a/doc/user/project/integrations/img/jira_create_new_user.png
+++ b/doc/user/project/integrations/img/jira_create_new_user.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_group_access.png b/doc/user/project/integrations/img/jira_group_access.png
index 448cc55504d..58cf114bd55 100644
--- a/doc/user/project/integrations/img/jira_group_access.png
+++ b/doc/user/project/integrations/img/jira_group_access.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_project_name.png b/doc/user/project/integrations/img/jira_project_name.png
deleted file mode 100644
index 981c7f7ca18..00000000000
--- a/doc/user/project/integrations/img/jira_project_name.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_service.png b/doc/user/project/integrations/img/jira_service.png
deleted file mode 100644
index 0ae2fa28756..00000000000
--- a/doc/user/project/integrations/img/jira_service.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_user_management_link.png b/doc/user/project/integrations/img/jira_user_management_link.png
index 5eb9d031c3e..43ef18da6c8 100644
--- a/doc/user/project/integrations/img/jira_user_management_link.png
+++ b/doc/user/project/integrations/img/jira_user_management_link.png
Binary files differ
diff --git a/doc/user/project/integrations/img/mattermost_configuration.png b/doc/user/project/integrations/img/mattermost_configuration.png
index e0b55b23520..75ef0310f2d 100644
--- a/doc/user/project/integrations/img/mattermost_configuration.png
+++ b/doc/user/project/integrations/img/mattermost_configuration.png
Binary files differ
diff --git a/doc/user/project/integrations/img/prometheus_add_metric.png b/doc/user/project/integrations/img/prometheus_add_metric.png
new file mode 100644
index 00000000000..e85670e1a13
--- /dev/null
+++ b/doc/user/project/integrations/img/prometheus_add_metric.png
Binary files differ
diff --git a/doc/user/project/integrations/img/prometheus_alert.png b/doc/user/project/integrations/img/prometheus_alert.png
new file mode 100644
index 00000000000..a37f0477fd9
--- /dev/null
+++ b/doc/user/project/integrations/img/prometheus_alert.png
Binary files differ
diff --git a/doc/user/project/integrations/img/prometheus_service_alerts.png b/doc/user/project/integrations/img/prometheus_service_alerts.png
new file mode 100644
index 00000000000..a81dfe7da14
--- /dev/null
+++ b/doc/user/project/integrations/img/prometheus_service_alerts.png
Binary files differ
diff --git a/doc/user/project/integrations/img/prometheus_yaml_deploy.png b/doc/user/project/integrations/img/prometheus_yaml_deploy.png
deleted file mode 100644
index 78dd178a077..00000000000
--- a/doc/user/project/integrations/img/prometheus_yaml_deploy.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/img/slack_configuration.png b/doc/user/project/integrations/img/slack_configuration.png
index 53b30e0e8cd..a14d2969488 100644
--- a/doc/user/project/integrations/img/slack_configuration.png
+++ b/doc/user/project/integrations/img/slack_configuration.png
Binary files differ
diff --git a/doc/user/project/integrations/jira.md b/doc/user/project/integrations/jira.md
index a90167b9767..234e3ad31cc 100644
--- a/doc/user/project/integrations/jira.md
+++ b/doc/user/project/integrations/jira.md
@@ -8,6 +8,8 @@ While you can always migrate content and process from Jira to GitLab Issues,
you can also opt to continue using Jira and use it together with GitLab through
our integration.
+For a video demonstration of integration with Jira, watch [GitLab workflow with Jira issues and Jenkins pipelines](https://youtu.be/Jn-_fyra7xQ).
+
Once you integrate your GitLab project with your Jira instance, you can automatically
detect and cross-reference activity between the GitLab project and any of your projects
in Jira. This includes the ability to close or transition Jira issues when the work
@@ -47,11 +49,11 @@ project in Jira and then enter the correct values in GitLab.
When connecting to **JIRA Server**, which supports basic authentication, a **username and password** are required. Check the link below and proceed to the next step:
-- [Setting up an user in JIRA server](jira_server_configuration.md)
+- [Setting up a user in JIRA server](jira_server_configuration.md)
When connecting to **JIRA Cloud**, which supports authentication via API token, an **email and API token**, are required. Check the link below and proceed to the next step:
-- [Setting up an user in JIRA cloud](jira_cloud_configuration.md)
+- [Setting up a user in JIRA cloud](jira_cloud_configuration.md)
### Configuring GitLab
diff --git a/doc/user/project/integrations/jira_server_configuration.md b/doc/user/project/integrations/jira_server_configuration.md
index 20036183187..13d65c4d8e4 100644
--- a/doc/user/project/integrations/jira_server_configuration.md
+++ b/doc/user/project/integrations/jira_server_configuration.md
@@ -1,18 +1,16 @@
# Creating a username and password for JIRA server
We need to create a user in Jira which will have access to all projects that
-need to integrate with GitLab. Login to your Jira instance as admin and under
-*Administration*, go to *User Management* and create a new user.
+need to integrate with GitLab.
As an example, we'll create a user named `gitlab` and add it to the `Jira-developers`
group.
NOTE: **Note**
-It is important that the user `gitlab` has 'write' access to projects in Jira.
+It is important that the Jira user created for the integration is given 'write'
+access to your Jira projects. This is covered in the process below.
-We have split this stage in steps so it is easier to follow.
-
-1. Log in to your Jira instance as an administrator and under **Administration**
+1. Log in to your Jira instance as an administrator and under **Jira Administration**
go to **User Management** to create a new user.
![Jira user management link](img/jira_user_management_link.png)
@@ -27,27 +25,34 @@ We have split this stage in steps so it is easier to follow.
![Jira create new user](img/jira_create_new_user.png)
-1. Create a `gitlab-developers` group which will have write access
- to projects in Jira. Go to the **Groups** tab and select **Create group**.
+1. Create a `gitlab-developers` group. (We will give this group write access to Jira
+ projects in a later step). Go to the **Groups** tab on the left, and select **Add group**.
![Jira create new user](img/jira_create_new_group.png)
- Give it an optional description and click **Create group**.
+ Give it a name and click **Add group**.
- ![Jira create new group](img/jira_create_new_group_name.png)
+1. Add the `gitlab` user to the `gitlab-developers` group by clicking **Edit members**.
+ The `gitlab-developers` group should be listed in the leftmost box as a selected group.
+ Under **Add members to selected group(s)**, enter `gitlab`.
-1. To give the newly-created group 'write' access, go to
- **Application access > View configuration** and add the `gitlab-developers`
- group to Jira Core.
+ ![Jira add user to group](img/jira_add_user_to_group.png)
+
+ Click **Add selected users** and `gitlab` should appear in the **Group member(s)** box.
+ This membership is saved automatically.
+
+ ![Jira added user to group](img/jira_added_user_to_group.png)
+
+1. To give the newly-created group 'write' access, you need to create a **Permission Scheme**.
+ To do this, click the gear icon and select **Issues**. Then click **Permission Schemes**.
+ Click **Add Permission Scheme** and enter a **Name** and, optionally, a **Description**.
+
+1. Once your permission scheme is created, you'll be taken back to the permissions scheme list.
+ Locate your new permissions scheme and click **Permissions**. Next to **Administer Projects**,
+ click **Edit**. In the resulting dialog box, select **Group** and select `gitlab-developers`
+ from the dropdown.
![Jira group access](img/jira_group_access.png)
-1. Add the `gitlab` user to the `gitlab-developers` group by going to
- **Users > GitLab user > Add group** and selecting the `gitlab-developers`
- group from the dropdown menu. Notice that the group says _Access_, which is
- intended as part of this process.
-
- ![Jira add user to group](img/jira_add_user_to_group.png)
-
The Jira configuration is complete. Write down the new Jira username and its
password as they will be needed when [configuring GitLab in the next section](jira.md#configuring-gitlab).
diff --git a/doc/user/project/integrations/mattermost.md b/doc/user/project/integrations/mattermost.md
index 8c5461de42f..d7fd75fd728 100644
--- a/doc/user/project/integrations/mattermost.md
+++ b/doc/user/project/integrations/mattermost.md
@@ -27,9 +27,11 @@ There, you will see a checkbox with the following events that can be triggered:
- Confidential issue
- Merge request
- Note
+- Confidential note
- Tag push
- Pipeline
- Wiki page
+- Deployment
Below each of these event checkboxes, you have an input field to enter
which Mattermost channel you want to send that event message. Enter your preferred channel handle (the hash sign `#` is optional).
diff --git a/doc/user/project/integrations/project_services.md b/doc/user/project/integrations/project_services.md
index 42c7824a125..0bfee3bac99 100644
--- a/doc/user/project/integrations/project_services.md
+++ b/doc/user/project/integrations/project_services.md
@@ -14,8 +14,7 @@ want to configure.
![Project services list](img/project_services.png)
-Below, you will find a list of the currently supported ones accompanied with
-comprehensive documentation.
+Below, you will find a list of the currently supported ones accompanied with comprehensive documentation.
## Services
@@ -35,10 +34,12 @@ Click on the service links to see further configuration instructions and details
| [Emails on push](emails_on_push.md) | Email the commits and diff of each push to a list of recipients |
| External Wiki | Replaces the link to the internal wiki with a link to an external wiki |
| Flowdock | Flowdock is a collaboration web app for technical teams |
+| [GitHub](github.md) **[PREMIUM]** | Sends pipeline notifications to GitHub |
| [Hangouts Chat](hangouts_chat.md) | Receive events notifications in Google Hangouts Chat |
| [HipChat](hipchat.md) | Private group chat and IM |
| [Irker (IRC gateway)](irker.md) | Send IRC messages, on update, to a list of recipients through an Irker gateway |
| [JIRA](jira.md) | JIRA issue tracker |
+| [Jenkins](../../../integration/jenkins.md) **[STARTER]** | An extendable open source continuous integration server |
| JetBrains TeamCity CI | A continuous integration and build server |
| [Mattermost slash commands](mattermost_slash_commands.md) | Mattermost chat and ChatOps slash commands |
| [Mattermost Notifications](mattermost.md) | Receive event notifications in Mattermost |
@@ -46,7 +47,8 @@ Click on the service links to see further configuration instructions and details
| Packagist | Update your project on Packagist, the main Composer repository |
| Pipelines emails | Email the pipeline status to a list of recipients |
| [Slack Notifications](slack.md) | Send GitLab events (e.g. issue created) to Slack as notifications |
-| [Slack slash commands](slack_slash_commands.md) | Use slash commands in Slack to control GitLab |
+| [Slack slash commands](slack_slash_commands.md) **[CORE ONLY]** | Use slash commands in Slack to control GitLab |
+| [GitLab Slack application](gitlab_slack_application.md) **[FREE ONLY]** | Use Slack's official application |
| PivotalTracker | Project Management Software (Source Commits Endpoint) |
| [Prometheus](prometheus.md) | Monitor the performance of your deployed apps |
| Pushover | Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop |
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
index 43a9e24526d..751e8e44e60 100644
--- a/doc/user/project/integrations/prometheus.md
+++ b/doc/user/project/integrations/prometheus.md
@@ -13,7 +13,7 @@ There are two ways to set up Prometheus integration, depending on where your app
- For deployments on Kubernetes, GitLab can automatically [deploy and manage Prometheus](#managed-prometheus-on-kubernetes).
- For other deployment targets, simply [specify the Prometheus server](#manual-configuration-of-prometheus).
-Once enabled, GitLab will automatically detect metrics from known services in the [metric library](#monitoring-cicd-environments).
+Once enabled, GitLab will automatically detect metrics from known services in the [metric library](#monitoring-cicd-environments). You are also able to [add your own metrics](#adding-additional-metrics-premium) as well.
## Enabling Prometheus Integration
@@ -93,6 +93,85 @@ GitLab will automatically scan the Prometheus server for metrics from known serv
You can view the performance dashboard for an environment by [clicking on the monitoring button](../../../ci/environments.md#monitoring-environments).
+### Adding additional metrics **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3799) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.6.
+
+Additional metrics can be monitored by adding them on the Prometheus integration page. Once saved, they will be displayed on the environment performance dashboard.
+
+![Add New Metric](img/prometheus_add_metric.png)
+
+A few fields are required:
+
+- **Name**: Chart title
+- **Type**: Type of metric. Metrics of the same type will be shown together.
+- **Query**: Valid [PromQL query](https://prometheus.io/docs/prometheus/latest/querying/basics/).
+- **Y-axis label**: Y axis title to display on the dashboard.
+- **Unit label**: Query units, for example `req / sec`. Shown next to the value.
+
+Multiple metrics can be displayed on the same chart if the fields **Name**, **Type**, and **Y-axis label** match between metrics. For example, a metric with **Name** `Requests Rate`, **Type** `Business`, and **Y-axis label** `rec / sec` would display on the same chart as a second metric with the same values. A **Legend label** is suggested if this feature used.
+
+#### Query Variables
+
+GitLab supports a limited set of [CI variables](../../../ci/variables/README.html) in the Prometheus query. This is particularly useful for identifying a specific environment, for example with `CI_ENVIRONMENT_SLUG`. The supported variables are:
+
+- CI_ENVIRONMENT_SLUG
+- KUBE_NAMESPACE
+
+To specify a variable in a query, enclose it in curly braces with a leading percent. For example: `%{ci_environment_slug}`.
+
+### Setting up alerts for Prometheus metrics **[ULTIMATE]**
+
+#### Managed Prometheus instances
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/6590) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.2 for [custom metrics](#adding-additional-metrics-premium), and 11.3 for [library metrics](prometheus_library/metrics.md).
+
+For managed Prometheus instances using auto configuration, alerts for metrics [can be configured](#adding-additional-metrics-premium) directly in the performance dashboard.
+
+To set an alert, click on the alarm icon in the top right corner of the metric you want to create the alert for. A dropdown
+will appear, with options to set the threshold and operator. Click **Add** to save and activate the alert.
+
+![Adding an alert](img/prometheus_alert.png)
+
+To remove the alert, click back on the alert icon for the desired metric, and click **Delete**.
+
+#### External Prometheus instances
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9258) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.8.
+
+For manually configured Prometheus servers, a notify endpoint is provided to use with Prometheus webhooks. If you have manual configuration enabled, an **Alerts** section is added to **Settings > Integrations > Prometheus**. This contains the *URL* and *Authorization Key*. The **Reset Key** button will invalidate the key and generate a new one.
+
+![Prometheus service configuration of Alerts](img/prometheus_service_alerts.png)
+
+To send GitLab alert notifications, copy the *URL* and *Authorization Key* into the [`webhook_configs`](https://prometheus.io/docs/alerting/configuration/#webhook_config) section of your Prometheus Alertmanager configuration:
+
+```yaml
+receivers:
+ name: gitlab
+ webhook_configs:
+ - http_config:
+ bearer_token: 9e1cbfcd546896a9ea8be557caf13a76
+ send_resolved: true
+ url: http://192.168.178.31:3001/root/manual_prometheus/prometheus/alerts/notify.json
+ ...
+```
+
+### Taking action on incidents **[ULTIMATE]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/4925) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.11.
+
+Alerts can be used to trigger actions, like open an issue automatically. To configure the actions:
+
+1. Navigate to your project's **Settings > Operations > Incidents**.
+1. Enable the option to create issues.
+1. Choose the [issue template](../description_templates.md) to create the issue from.
+1. Optionally, select whether to send an email notification to the developers of the project.
+1. Click **Save changes**.
+
+Once enabled, an issue will be opened automatically when an alert is triggered. The author of the issue will be the GitLab Alert Bot. To further customize the issue, you can add labels, mentions, or any other supported [quick action](../quick_actions.md) in the selected issue template.
+
+If the metric exceeds the threshold of the alert for over 5 minutes, an email will be sent to all [Maintainers and Owners](../../permissions.md#project-members-permissions) of the project.
+
## Determining the performance impact of a merge
> [Introduced][ce-10408] in GitLab 9.2.
diff --git a/doc/user/project/integrations/prometheus_library/kubernetes.md b/doc/user/project/integrations/prometheus_library/kubernetes.md
index 7a45c87ada0..8b1cf1a251a 100644
--- a/doc/user/project/integrations/prometheus_library/kubernetes.md
+++ b/doc/user/project/integrations/prometheus_library/kubernetes.md
@@ -1,6 +1,6 @@
# Monitoring Kubernetes
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8935) in GitLab 9.0
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8935) in GitLab 9.0.
GitLab has support for automatically detecting and monitoring Kubernetes metrics.
@@ -27,7 +27,7 @@ integration services must be enabled.
Prometheus needs to be deployed into the cluster and configured properly in order to gather Kubernetes metrics. GitLab supports two methods for doing so:
-- GitLab [integrates with Kubernetes](../../clusters/index.md), and can [deploy Prometheus into a connected cluster](../prometheus.html#managed-prometheus-on-kubernetes). It is automatically configured to collect Kubernetes metrics.
+- GitLab [integrates with Kubernetes](../../clusters/index.md), and can [deploy Prometheus into a connected cluster](../prometheus.md#managed-prometheus-on-kubernetes). It is automatically configured to collect Kubernetes metrics.
- To configure your own Prometheus server, you can follow the [Prometheus documentation](https://prometheus.io/docs/introduction/overview/).
## Specifying the Environment
@@ -35,3 +35,25 @@ Prometheus needs to be deployed into the cluster and configured properly in orde
In order to isolate and only display relevant CPU and Memory metrics for a given environment, GitLab needs a method to detect which containers it is running. Because these metrics are tracked at the container level, traditional Kubernetes labels are not available.
Instead, the [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) or [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) name should begin with [CI_ENVIRONMENT_SLUG](../../../../ci/variables/README.md#predefined-environment-variables). It can be followed by a `-` and additional content if desired. For example, a deployment name of `review-homepage-5620p5` would match the `review/homepage` environment.
+
+## Displaying Canary metrics **[PREMIUM]**
+
+> Introduced in [GitLab 10.2](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/15201).
+
+GitLab also gathers Kubernetes metrics for [canary deployments](../../canary_deployments.md), allowing easy comparison between the current deployed version and the canary.
+
+These metrics expect the [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) or [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) name to begin with `$CI_ENVIRONMENT_SLUG-canary`, to isolate the canary metrics.
+
+### Canary metrics supported
+
+- Average Memory Usage (MB)
+
+ ```
+ avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024
+ ```
+
+- Average CPU Utilization (%)
+
+ ```
+ avg(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}[15m])) by (job)) without (job) / count(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-canary-(.*)",namespace="%{kube_namespace}"}[15m])) by (pod_name))
+ ```
diff --git a/doc/user/project/integrations/slack_slash_commands.md b/doc/user/project/integrations/slack_slash_commands.md
index c267da69bb3..371e78ca3a4 100644
--- a/doc/user/project/integrations/slack_slash_commands.md
+++ b/doc/user/project/integrations/slack_slash_commands.md
@@ -1,10 +1,15 @@
-# Slack slash commands
+# Slack slash commands **[CORE ONLY]**
-> Introduced in GitLab 8.15
+> Introduced in GitLab 8.15.
-Slack slash commands allow you to control GitLab and view content right inside Slack, without having to leave it. This requires configurations in both Slack and GitLab.
+Slack slash commands allow you to control GitLab and view content right inside
+Slack, without having to leave it. This requires configurations in both Slack and GitLab.
-> Note: GitLab can also send events (e.g. issue created) to Slack as notifications. This is the separately configured [Slack Notifications Service](slack.md).
+GitLab can also send events (e.g., `issue created`) to Slack as notifications.
+This is the separately configured [Slack Notifications Service](slack.md).
+
+NOTE: **Note:**
+For GitLab.com, use the [Slack app](gitlab_slack_application.md) instead.
## Configuration
diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md
index 8e1603f9ec9..d5f28ddabc1 100644
--- a/doc/user/project/integrations/webhooks.md
+++ b/doc/user/project/integrations/webhooks.md
@@ -321,8 +321,14 @@ X-Gitlab-Event: Issue Hook
"group_id": 41
}],
"changes": {
- "updated_by_id": [null, 1],
- "updated_at": ["2017-09-15 16:50:55 UTC", "2017-09-15 16:52:00 UTC"],
+ "updated_by_id": {
+ "previous": null,
+ "current": 1
+ },
+ "updated_at": {
+ "previous": "2017-09-15 16:50:55 UTC",
+ "current": "2017-09-15 16:52:00 UTC"
+ },
"labels": {
"previous": [{
"id": 206,
@@ -647,7 +653,33 @@ X-Gitlab-Event: Note Hook
"description": "test",
"milestone_id": null,
"state": "closed",
- "iid": 17
+ "iid": 17,
+ "labels": [
+ {
+ "id": 25,
+ "title": "Afterpod",
+ "color": "#3e8068",
+ "project_id": null,
+ "created_at": "2019-06-05T14:32:20.211Z",
+ "updated_at": "2019-06-05T14:32:20.211Z",
+ "template": false,
+ "description": null,
+ "type": "GroupLabel",
+ "group_id": 4
+ },
+ {
+ "id": 86,
+ "title": "Element",
+ "color": "#231afe",
+ "project_id": 4,
+ "created_at": "2019-06-05T14:32:20.637Z",
+ "updated_at": "2019-06-05T14:32:20.637Z",
+ "template": false,
+ "description": null,
+ "type": "ProjectLabel",
+ "group_id": null
+ }
+ ],
}
}
```
@@ -851,8 +883,14 @@ X-Gitlab-Event: Merge Request Hook
"group_id": 41
}],
"changes": {
- "updated_by_id": [null, 1],
- "updated_at": ["2017-09-15 16:50:55 UTC", "2017-09-15 16:52:00 UTC"],
+ "updated_by_id": {
+ "previous": null,
+ "current": 1
+ },
+ "updated_at": {
+ "previous": "2017-09-15 16:50:55 UTC",
+ "current":"2017-09-15 16:52:00 UTC"
+ },
"labels": {
"previous": [{
"id": 206,
@@ -1004,7 +1042,7 @@ X-Gitlab-Event: Pipeline Hook
"email": "user@gitlab.com"
}
},
- "jobs":[
+ "builds":[
{
"id": 380,
"stage": "deploy",
diff --git a/doc/user/project/integrations/youtrack.md b/doc/user/project/integrations/youtrack.md
index a2a468b6fe4..81c148e41fd 100644
--- a/doc/user/project/integrations/youtrack.md
+++ b/doc/user/project/integrations/youtrack.md
@@ -31,8 +31,8 @@ To disable the internal issue tracker in a project:
## Referencing YouTrack issues in GitLab
Issues in YouTrack can be referenced as `<PROJECT>-<ID>`. `<PROJECT>`
-must start with a capital letter and can then be followed by capital or lower case
-letters, numbers or underscores. `<ID>` is a number. An example reference is `YT-101` or `Api_32-143`.
+must start with a letter and is followed by letters, numbers, or underscores.
+`<ID>` is a number. An example reference is `YT-101`, `Api_32-143` or `gl-030`.
References to `<PROJECT>-<ID>` in merge requests, commits, or comments are automatically linked to the YouTrack issue URL.
For more information, see the [External Issue Tracker](../../../integration/external-issue-tracker.md) documentation.
diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md
index ad47b848bea..31020de5208 100644
--- a/doc/user/project/issue_board.md
+++ b/doc/user/project/issue_board.md
@@ -151,7 +151,7 @@ Create lists for each of your team members and quickly drag-and-drop issues onto
## Permissions
-[Developers and up](../permissions.md) can use all the functionality of the
+[Reporters and up](../permissions.md) can use all the functionality of the
Issue Board, that is, create or delete lists and drag issues from one list to another.
## GitLab Enterprise features for Issue Boards
diff --git a/doc/user/project/issues/create_new_issue.md b/doc/user/project/issues/create_new_issue.md
index 9a147deecd4..c2916c79876 100644
--- a/doc/user/project/issues/create_new_issue.md
+++ b/doc/user/project/issues/create_new_issue.md
@@ -65,6 +65,26 @@ In GitLab 11.7, we updated the format of the generated email address.
However the older format is still supported, allowing existing aliases
or contacts to continue working._
+## New issue via Service Desk **[PREMIUM]**
+
+Enable [Service Desk](../service_desk.md) to your project and offer email support.
+By doing so, when your customer sends a new email, a new issue can be created in
+the appropriate project and followed up from there.
+
+## New issue from the group-level Issue Tracker
+
+Head to the Group dashboard and click "Issues" in the sidebar to visit the Issue Tracker
+for all projects in your Group. Select the project you'd like to add an issue for
+using the dropdown button at the top-right of the page.
+
+![Select project to create issue](img/select_project_from_group_level_issue_tracker.png)
+
+We'll keep track of the project you selected most recently, and use it as the default
+for your next visit. This should save you a lot of time and clicks, if you mostly
+create issues for the same project.
+
+![Create issue from group-level issue tracker](img/create_issue_from_group_level_issue_tracker.png)
+
## New issue via URL with prefilled fields
You can link directly to the new issue page for a given project, with prefilled
diff --git a/doc/user/project/issues/csv_export.md b/doc/user/project/issues/csv_export.md
new file mode 100644
index 00000000000..56b94585672
--- /dev/null
+++ b/doc/user/project/issues/csv_export.md
@@ -0,0 +1,77 @@
+# Export Issues to CSV **[STARTER]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1126) in [GitLab Starter 9.0](https://about.gitlab.com/2017/03/22/gitlab-9-0-released/#export-issues-ees-eep).
+
+Issues can be exported as CSV from GitLab and are sent to your default notification email as an attachment.
+
+## Overview
+
+**Export Issues to CSV** enables you and your team to export all the data collected from issues into
+a **[comma-separated values](https://en.wikipedia.org/wiki/Comma-separated_values)** (CSV) file,
+which stores tabular data in plain text.
+
+> _CSVs are a handy way of getting data from one program to another where one program cannot read the other ones normal output._ [Ref](https://www.quora.com/What-is-a-CSV-file-and-its-uses)
+
+CSV files can be used with any plotter or spreadsheet-based program, such as Microsoft Excel,
+Open Office Calc, or Google Spreadsheets.
+
+## Use cases
+
+Among numerous use cases for exporting issues for CSV, we can name a few:
+
+- Make a snapshot of issues for offline analysis or to communicate with other teams who may not be in GitLab
+- Create diagrams, graphs, and charts from the CSV data
+- Present the data in any other format for auditing or sharing reasons
+- Import the issues elsewhere to a system outside of GitLab
+- Long-term issues' data analysis with multiple snapshots created along the time
+- Use the long-term data to gather relevant feedback given in the issues, and improve your product based on real metrics
+
+## Choosing which issues to include
+
+From the issues page you can narrow down which issues to export using the search bar, along with the All/Open/Closed tabs. All issues returned will be exported, including those not shown on the first page.
+
+![CSV export button](img/csv_export_button.png)
+
+You will be asked to confirm the number of issues and email address for the export, after which the email will begin being prepared.
+
+![CSV export modal dialog](img/csv_export_modal.png)
+
+## Sorting
+
+Exported issues are always sorted by `Issue ID`.
+
+## Format
+
+> **Time Estimate** and **Time Spent** columns were [introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2627) in GitLab Starter 10.0.
+>
+> **Weight** and **Locked** columns were [introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/5300) in GitLab Starter 10.8.
+
+Data will be encoded with a comma as the column delimiter, with `"` used to quote fields if needed, and newlines to separate rows. The first row will be the headers, which are listed in the following table along with a description of the values:
+
+
+| Column | Description |
+|---------|-------------|
+| Issue ID | Issue `iid` |
+| URL | A link to the issue on GitLab |
+| Title | Issue `title` |
+| State | `Open` or `Closed` |
+| Description | Issue `description` |
+| Author | Full name of the issue author |
+| Author Username | Username of the author, with the `@` symbol omitted |
+| Assignee | Full name of the issue assignee |
+| Assignee Username | Username of the author, with the `@` symbol omitted |
+| Confidential | `Yes` or `No` |
+| Locked | `Yes` or `No` |
+| Due Date | Formated as `YYYY-MM-DD` |
+| Created At (UTC) | Formated as `YYYY-MM-DD HH:MM:SS` |
+| Updated At (UTC) | Formated as `YYYY-MM-DD HH:MM:SS` |
+| Milestone | Title of the issue milestone |
+| Weight | Issue weight |
+| Labels | Title of any labels joined with a `,` |
+| Time Estimate | [Time estimate](../../../workflow/time_tracking.md#estimates) in seconds |
+| Time Spent | [Time spent](../../../workflow/time_tracking.md#time-spent) in seconds |
+
+
+## Limitations
+
+As the issues will be sent as an email attachment, there is a limit on how much data can be exported. Currently this limit is 20MB to ensure successful delivery across a range of email providers. If this limit is reached we suggest narrowing the search before export, perhaps by exporting open and closed issues separately.
diff --git a/doc/user/project/issues/csv_import.md b/doc/user/project/issues/csv_import.md
index 032e3a73ad0..b0b1cfcfdf7 100644
--- a/doc/user/project/issues/csv_import.md
+++ b/doc/user/project/issues/csv_import.md
@@ -1,17 +1,23 @@
-# Importing Issues from CSV
+# Importing issues from CSV
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/23532) in GitLab 11.7.
-Issues can be imported to a project by uploading a CSV file. Supported fields are
-`title` and `description`.
+Issues can be imported to a project by uploading a CSV file with the columns
+`title` and `description`, in that order.
The user uploading the CSV file will be set as the author of the imported issues.
> **Note:** A permission level of `Developer` or higher is required to import issues.
+## Prepare for the import
+
+- Consider importing a test file containing only a few issues. There is no way to undo a large import without using the GitLab API.
+- Ensure your CSV file meets the [file format](#csv-file-format) requirements.
+
+## Import the file
+
To import issues:
-1. Ensure your CSV file meets the [file format](#csv-file-format) requirements.
1. Navigate to a project's Issues list page.
1. If existing issues are present, click the import icon at the top right, next to the **Edit issues** button.
1. For a project without any issues, click the button labeled **Import CSV** in the middle of the page.
@@ -20,11 +26,11 @@ To import issues:
The file is processed in the background and a notification email is sent
to you once the import is completed.
-## CSV File Format
+## CSV file format
### Header row
-CSV files must contain a header row beginning with at least two columns, `title` and `description`, in that order.
+CSV files must contain a header row where the first column header is `title` and the second is `description`.
If additional columns are present, they will be ignored.
### Column separator
@@ -53,7 +59,7 @@ The limit depends on the configuration value of Max Attachment Size for the GitL
For GitLab.com, it is set to 10 MB.
-## Sample Data
+## Sample data
```csv
title,description
diff --git a/doc/user/project/issues/img/comment-or-discussion.png b/doc/user/project/issues/img/comment-or-discussion.png
new file mode 100644
index 00000000000..ccecc9fa39f
--- /dev/null
+++ b/doc/user/project/issues/img/comment-or-discussion.png
Binary files differ
diff --git a/doc/user/project/issues/img/create_issue_from_group_level_issue_tracker.png b/doc/user/project/issues/img/create_issue_from_group_level_issue_tracker.png
new file mode 100644
index 00000000000..8996490ae63
--- /dev/null
+++ b/doc/user/project/issues/img/create_issue_from_group_level_issue_tracker.png
Binary files differ
diff --git a/doc/user/project/issues/img/create_mr_from_issue.png b/doc/user/project/issues/img/create_mr_from_issue.png
new file mode 100644
index 00000000000..680c42b5df0
--- /dev/null
+++ b/doc/user/project/issues/img/create_mr_from_issue.png
Binary files differ
diff --git a/doc/user/project/issues/img/csv_export_button.png b/doc/user/project/issues/img/csv_export_button.png
new file mode 100644
index 00000000000..f9fcfd71c2f
--- /dev/null
+++ b/doc/user/project/issues/img/csv_export_button.png
Binary files differ
diff --git a/doc/user/project/issues/img/csv_export_modal.png b/doc/user/project/issues/img/csv_export_modal.png
new file mode 100644
index 00000000000..f988deec966
--- /dev/null
+++ b/doc/user/project/issues/img/csv_export_modal.png
Binary files differ
diff --git a/doc/user/project/issues/img/group_issues_list_view.png b/doc/user/project/issues/img/group_issues_list_view.png
deleted file mode 100644
index c951a9e2dcd..00000000000
--- a/doc/user/project/issues/img/group_issues_list_view.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/issue_template.png b/doc/user/project/issues/img/issue_template.png
deleted file mode 100644
index 6cb2c07d27e..00000000000
--- a/doc/user/project/issues/img/issue_template.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/issues_main_view_numbered.jpg b/doc/user/project/issues/img/issues_main_view_numbered.jpg
deleted file mode 100644
index b4b68476d24..00000000000
--- a/doc/user/project/issues/img/issues_main_view_numbered.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/issues_main_view_numbered.png b/doc/user/project/issues/img/issues_main_view_numbered.png
new file mode 100644
index 00000000000..16cb6b497b0
--- /dev/null
+++ b/doc/user/project/issues/img/issues_main_view_numbered.png
Binary files differ
diff --git a/doc/user/project/issues/img/multiple_assignees.gif b/doc/user/project/issues/img/multiple_assignees.gif
new file mode 100644
index 00000000000..055a0efd9ae
--- /dev/null
+++ b/doc/user/project/issues/img/multiple_assignees.gif
Binary files differ
diff --git a/doc/user/project/issues/img/multiple_assignees_for_issues.png b/doc/user/project/issues/img/multiple_assignees_for_issues.png
new file mode 100644
index 00000000000..e8ae37d427d
--- /dev/null
+++ b/doc/user/project/issues/img/multiple_assignees_for_issues.png
Binary files differ
diff --git a/doc/user/project/issues/img/related_issues_add.png b/doc/user/project/issues/img/related_issues_add.png
new file mode 100644
index 00000000000..f59d2335386
--- /dev/null
+++ b/doc/user/project/issues/img/related_issues_add.png
Binary files differ
diff --git a/doc/user/project/issues/img/related_issues_remove.png b/doc/user/project/issues/img/related_issues_remove.png
new file mode 100644
index 00000000000..be2ec59e61b
--- /dev/null
+++ b/doc/user/project/issues/img/related_issues_remove.png
Binary files differ
diff --git a/doc/user/project/issues/img/reopen-issue.png b/doc/user/project/issues/img/reopen-issue.png
new file mode 100644
index 00000000000..1749be31239
--- /dev/null
+++ b/doc/user/project/issues/img/reopen-issue.png
Binary files differ
diff --git a/doc/user/project/issues/img/report-abuse.png b/doc/user/project/issues/img/report-abuse.png
new file mode 100644
index 00000000000..f189cbf1d36
--- /dev/null
+++ b/doc/user/project/issues/img/report-abuse.png
Binary files differ
diff --git a/doc/user/project/issues/img/select_project_from_group_level_issue_tracker.png b/doc/user/project/issues/img/select_project_from_group_level_issue_tracker.png
new file mode 100644
index 00000000000..97d93620b2a
--- /dev/null
+++ b/doc/user/project/issues/img/select_project_from_group_level_issue_tracker.png
Binary files differ
diff --git a/doc/user/project/issues/img/show-all-activity.png b/doc/user/project/issues/img/show-all-activity.png
new file mode 100644
index 00000000000..c43ba75ce25
--- /dev/null
+++ b/doc/user/project/issues/img/show-all-activity.png
Binary files differ
diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md
index c82b7f100d2..76dc6e49bce 100644
--- a/doc/user/project/issues/index.md
+++ b/doc/user/project/issues/index.md
@@ -86,7 +86,9 @@ For more information, see the [Issue Data and Actions](issue_data_and_actions.md
On the Issues List, you can view all issues in the current project, or from multiple projects when opening the Issues List from the higher-level group context. Filter the issue list by [any search query](../../search/index.md#issues-and-merge-requests-per-project) and/or specific metadata, such as label(s), assignees(s), status, and more. From this view, you can also make certain changes [in bulk](../bulk_editing.md) to the displayed issues.
-For more information, see the [Issue Data and Actions](issue_data_and_actions.md) page.
+For more information on interacting with Issues, see the [Issue Data and Actions](issue_data_and_actions.md) page.
+
+For sorting by issue priority, see [Label Priority](../labels.md#label-priority).
### Issue boards
@@ -102,13 +104,13 @@ For more information, see the [Issue Boards](../issue_board.md) page.
Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones.
-For more information, see the [Epics](https://docs.gitlab.com/ee/user/group/epics/) page.
+For more information, see the [Epics](../../group/epics/index.md) page.
### Related issues **[STARTER]**
You can mark two issues as related, so that when viewing each one, the other is always listed in its Related Issues section. This can help display important context, such as past work, dependencies, or duplicates.
-For more information, see [Related Issues](https://docs.gitlab.com/ee/user/project/issues/related_issues.html).
+For more information, see [Related Issues](related_issues.md).
### Crosslinking issues
@@ -123,13 +125,13 @@ For more information, see [Crosslinking issues](crosslinking_issues.md).
- [Close an issue](closing_issues.md)
- [Move an issue](moving_issues.md)
- [Delete an issue](deleting_issues.md)
-- [Create a merge request from an issue](issue_data_and_actions.md#18-new-merge-request)
+- [Create a merge request from an issue](issue_data_and_actions.md#22-create-merge-request)
## Advanced issue management
- [Bulk edit issues](../bulk_editing.md) - From the Issues List, select multiple issues in order to change their status, assignee, milestone, or labels in bulk.
- [Import issues](csv_import.md)
-- [Export issues](https://docs.gitlab.com/ee/user/project/issues/csv_export.html) **[STARTER]**
+- [Export issues](csv_export.md) **[STARTER]**
- [Issues API](../../../api/issues.md)
- Configure an [external issue tracker](../../../integration/external-issue-tracker.md) such as Jira, Redmine,
or Bugzilla.
diff --git a/doc/user/project/issues/issue_data_and_actions.md b/doc/user/project/issues/issue_data_and_actions.md
index 653bd94e513..da585022263 100644
--- a/doc/user/project/issues/issue_data_and_actions.md
+++ b/doc/user/project/issues/issue_data_and_actions.md
@@ -4,11 +4,13 @@ Please read through the [GitLab Issue Documentation](index.md) for an overview o
## Parts of an Issue
-The image below illustrates what an issue looks like:
+The image below illustrates what an issue may look like. Note that certain parts will
+look slightly different or will be absent, depending on the version of GitLab being used
+and the permissions of the user viewing the issue.
-![Issue view](img/issues_main_view_numbered.jpg)
+![Issue view](img/issues_main_view_numbered.png)
-You can find all the information on that issue on one screen.
+You can find all the information for that issue on one screen.
### Issue screen
@@ -16,157 +18,215 @@ An issue starts with its status (open or closed), followed by its author,
and includes many other functionalities, numbered in the image above to
explain what they mean, one by one.
-Many of the elements of the issue screen refresh automatically, such as the title and description, when they are changed by another user.
-Comments and system notes also appear automatically in response to various actions and content updates.
+Many of the elements of the issue screen refresh automatically, such as the title and
+description, when they are changed by another user. Comments and system notes also
+update automatically in response to various actions and content updates.
-#### 1. New Issue, close issue, edit
+#### 1. New Issue, close issue (reopen issue, report issue)
-- New issue: create a new issue in the same project
-- Close issue: close this issue
-- Edit: edit the same fields available when you create an issue.
+Clicking on **New issue** will open a new window to create a new issue in the same project.
+Clicking on **Close issue** will close this issue, but it will not be deleted. If the
+issue is already closed, you can still access it and the button will show **Reopen issue**, as shown below,
+which you can click to reopen the issue. A reopened issue is no different from any
+other issue.
+
+![Reopen Issue](img/reopen-issue.png)
+
+If you do not have rights to modify the issue, the **close issue** button will be
+replaced with **report issue**, which you can click to [submit an abuse report](../../abuse_reports.md)
+about the issue. It will also appear if you have rights to modify the issue, but only
+after it is closed.
+
+![Report Abuse](img/report-abuse.png)
#### 2. Todos
-- Add todo: add that issue to your [GitLab Todo](../../../workflow/todos.md) list
-- Mark todo as done: mark that issue as done (reflects on the Todo list)
+You can click **add todo** to add the issue to your [GitLab Todo](../../../workflow/todos.md)
+list. If it is already on your todo list, the buttom will show **mark todo as done**,
+which you can click to mark that issue as done (which will be reflected in the Todo list).
#### 3. Assignee
-Whenever someone starts to work on an issue, it can be assigned
-to that person. The assignee can be changed as much as needed.
-The idea is that the assignee is responsible for that issue until
-it's reassigned to someone else to take it from there.
+An issue can be assigned to yourself, another person, or [many people](#31-multiple-assignees-STARTER).
+The assignee(s) can be changed as much as needed. The idea is that the assignees are
+responsible for that issue until it's reassigned to someone else to take it from there.
+When assigned to someone, it will appear in their assigned issues list.
-> **Tip:**
-if a user is not member of that project, it can only be
+TIP: **Tip:**
+If a user is not member of that project, it can only be
assigned to them if they created the issue themselves.
##### 3.1. Multiple Assignees **[STARTER]**
-Often multiple people work on the same issue together,
-which can be especially difficult to track in large teams
-where there is shared ownership of an issue.
+Often multiple people work on the same issue together, which can be especially difficult
+to track in large teams where there is shared ownership of an issue.
In [GitLab Starter](https://about.gitlab.com/pricing/), you can
-assign multiple people to an issue.
+[assign multiple people](multiple_assignees_for_issues.md) to an issue.
+
+#### 4. Epic **[ULTIMATE]**
+
+You can assign issues to an [Epic](../../group/epics/index.md), which allows better
+management of groups of related issues.
-Learn more in the [Multiple Assignees documentation](https://docs.gitlab.com/ee/user/project/issues/multiple_assignees_for_issues.html).
+#### 5. Milestone
-#### 4. Milestone
+Select a [milestone](../milestones/index.md) to attribute that issue to.
-- Select a [milestone](../milestones/index.md) to attribute that issue to.
+#### 6. Time Tracking
-#### 5. Time Tracking
+Use [GitLab Quick Actions](../quick_actions.md) to [track estimates and time spent on issues](../../../workflow/time_tracking.md).
+You can add an [estimate of the time it will take](../../../workflow/time_tracking.md#estimates)
+to resolve the issue, and also add [the time spent](../../../workflow/time_tracking.md#time-spent)
+on the resolution of the issue.
-- Estimate time: add an estimate of the time it will take to resolve the issue.
-- Spend: add the time spent on the resolution of the issue
+#### 7. Due date
-> **Note:**
-Both estimate and spend times are set via [GitLab Quick Actions](../quick_actions.md).
+When you work on a tight schedule, it's important to have a way to set a deadline for
+implementations and for solving problems. This can be done in the [due date](due_dates.md)
+element. Due dates can be changed as many times as needed.
-Learn more in the [Time Tracking documentation](../../../workflow/time_tracking.md).
+#### 8. Labels
-#### 6. Due date
+Categorize issues by giving them [labels](../labels.md). They help to organize workflows,
+and they enable you to work with the [GitLab Issue Board](index.md#issue-boards).
-When you work on a tight schedule, it's important to
-have a way to set a deadline for implementations and for solving
-problems. This can be done in the [due date](due_dates.md) element. Due dates
-can be changed as many times as needed.
+Group Labels, which allow you to use the same labels for all projects within the same
+group, can be also given to issues. They work exactly the same, but they are immediately
+available to all projects in the group.
-#### 7. Labels
+TIP: **Tip:**
+If a label doesn't exist yet, you can click **Edit**, and it opens a dropdown menu
+from which you can select **Create new label**.
-Categorize issues by giving them [labels](../labels.md). They help to
-organize workflows, and they enable you to work with the
-[GitLab Issue Board](index.md#issue-boards).
+#### 9. Weight **[STARTER]**
-Group Labels, which allow you to use the same labels for a
-group of projects, can be also given to issues. They work exactly the same,
-but they are immediately available to all projects in the group.
+[Assign a weight](../../../workflow/issue_weight.md) to an issue.
+Larger values are used to indicate more effort is required to complete the issue. Only
+positive values or zero are allowed.
-> **Tip:**
-If a label doesn't exist yet, you can click **Edit**, and it opens a dropdown menu from which you can select **Create new label**.
+#### 10. Confidentiality
-#### 8. Weight **[STARTER]**
+You can [set an issue to be confidential](confidential_issues.md). When set, unauthorized
+users will not be able to access the issue, and will not see it listed in project
+issue boards or the issue list.
-- Assign a weight. Larger values are used to indicate more effort is required to complete the issue. Only positive values or zero are allowed.
+#### 11. Lock issue
-Learn more in the [Issue Weight documentation](https://docs.gitlab.com/ee/workflow/issue_weight.html).
+You can [lock the discussions](../../discussions/index.md#lock-discussions) in the issue,
+to prevent further comments from being added.
-#### 9. Participants
+#### 12. Participants
-- People involved in that issue (mentioned in the description or in the [discussion](../../discussions/index.md)).
+All the users involved in that issue. Either they participated in the [discussion](../../discussions/index.md),
+or were mentioned in the description or discussions.
-#### 10. Notifications
+#### 13. Notifications
-- Subscribe: if you are not a participant of the discussion on that issue, but
- want to receive notifications on each new input, subscribe to it.
-- Unsubscribe: if you are receiving notifications on that issue but no
+Click on the icon to enable/disable [notifications](../../../workflow/notifications.md#issue--epics--merge-request-events)
+for the issue. This will automatically enable if you participate in the issue in any way.
+
+- **Enable**: If you are not a participant in the discussion on that issue, but
+ want to receive notifications on each update, subscribe to it.
+- **Disable**: If you are receiving notifications for updates to that issue but no
longer want to receive them, unsubscribe from it.
-Read more in the [notifications documentation](../../../workflow/notifications.md#issue--merge-request-events).
+#### 14. Reference
+
+- A quick "copy to clipboard" button for that issue's reference, which looks like `foo/bar#xxx`,
+ where `foo` is the `username` or `groupname`, `bar` is the `project-name`, and
+ `xxx` is the issue number.
+
+#### 15. Edit
+
+Clicking this icon opens the issue for editing, and you will have access to all the
+same fields as when the issue was created. This icon will not display if the user
+does not have permission to edit the issue.
+
+#### 16. Description
+
+The plain text title and description of the issue fill the top center of the issue page.
+The description fully supports [GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm),
+allowing many formatting options.
+
+#### 17. Mentions
+
+You can mention a user or a group present in your GitLab instance with `@username` or
+`@groupname` and they will be notified via todos and email, unless they have disabled
+all notifications in their profile settings. This is controlled in the
+[notification settings](../../../workflow/notifications.md).
+
+Mentions for yourself (the current logged in user), will be highlighted in a different
+color, allowing you to easily see which comments involve you, helping you focus on
+them quickly.
+
+TIP: **Tip:**
+Avoid mentioning `@all` in issues and merge requests, as it sends an email notification
+to all the members of that project's group, which can be interpreted as spam.
+
+#### 18. Related Issues **[STARTER]**
+
+Issues that were mentioned as [related issues](related_issues.md) are listed here.
+You can also click the `+` to add more related issues.
+
+#### 19. Related Merge Requests
-#### 11. Reference
+Merge requests that were mentioned in that issue's description or in the issue discussion
+thread are listed as [related merge requests](crosslinking_issues.md#from-merge-requests) here.
+Also, if the current issue was mentioned as related in another merge request, that
+merge request will be listed here.
-- A quick "copy to clipboard" button for that issue's reference, `foo/bar#xxx`, where `foo` is the `username` or `groupname`, `bar`
- is the `project-name`, and `xxx` is the issue number.
+#### 20. Award emoji
-#### 12. Title and description
+You can award an emoji to that issue. There are shortcuts to "thumbs_up" and "thumbs_down",
+or you can click on the light gray "face" to choose a different reaction from the
+dropdown list of available [GitLab Flavored Markdown Emoji](../../markdown.md#emoji).
-- Title: a plain text title for describing the subject of the issue.
-- Description: a large text field which fully supports [GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm),
- to describe all the details of the issue.
+TIP: **Tip:**
+Posting "+1" as a comment in a thread spams all subscribed participants of that issue,
+clutters the discussion threads, and is not recommended. Awarding an emoji is a way
+to let them know your reaction without spamming them.
-#### 13. Mentions
+#### 21. Show all activity
-- You can mention a user or a group present in your GitLab instance with
- `@username` or `@groupname` and they will be notified via todos and email, unless
- they have disabled all notifications in their profile settings.
-- Mentions for yourself (the current logged in user), will be highlighted
- in a different color, allowing you to easily see which comments involve you,
- helping you focus on them quickly.
+You can filter what is displayed in the issue history by clicking on **Show all activity**
+and selecting either **Show comments only**, which only shows discussions and hides
+updates to the issue, or **Show history only**, which hides discussions and only shows updates.
-To change your [notification settings](../../../workflow/notifications.md), navigate to
-**Profile Settings** > **Notifications** > **Global notification level**
-and choose your preference from the dropdown menu.
+![Show all activity](img/show-all-activity.png)
-> **Tip:**
-Avoid mentioning `@all` in issues and merge requests,
-as it sends an email notification
-to all the members of that project's group, which can be
-interpreted as spam.
+#### 22. Create Merge Request
-#### 14. Related Merge Requests
+Create a new branch and [WIP merge request](../merge_requests/work_in_progress_merge_requests.md)
+in one action. The branch will be named `issuenumber-title` by default, but you can
+choose any name, and GitLab will verify that it is not already in use. The merge request
+will automatically inherit the milestone and labels of the issue, and will be set to
+close the issue when it is merged.
-- Any merge requests mentioned in that issue's description
- or in the issue discussion thread.
+![Create MR from issue](img/create_mr_from_issue.png)
-#### 15. Award emoji
+Optionally, you can choose to create a [new branch](../repository/web_editor.md#create-a-new-branch-from-an-issue)
+only, named after that issue.
-- Award an emoji to that issue.
+#### 23. Issue history
-> **Tip:**
-Posting "+1" as a comment in a thread spams all subscribed
-participants of that issue. Awarding an emoji is a way to let them
-know you like it without spamming them.
+All comments and updates to the issue are tracked and listed here, but this can be
+filtered, as shown above.
-#### 16. Thread
+#### 24. Comments
-- Comments: collaborate to that issue by posting comments in its thread.
- These text fields also fully support
- [GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm).
+Collaborate in the issue by posting comments in its thread. This text field also fully
+supports [GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm).
-#### 17. Comment, start a discussion, or comment and close
+#### 25. Submit Comment, start a discussion, or comment and close
-Once you write a comment, you can either:
+Once you write a comment, you can:
-- Click "Comment" and your comment will be published.
-- Click "Start discussion": start a thread within that issue's thread to discuss specific points.
-- Click "Comment and close issue": post your comment and close that issue in one click.
+- Click **Comment** and your comment will be published.
+- Choose **Start discussion** from the dropdown list and start a new [discussion thread](../../discussions/index.md#threaded-discussions)
+ within that issue's main thread to discuss specific points. This invites other participants
+ to reply directly to your discussion, keeping related comments grouped together.
-#### 18. New Merge Request
+![Comment or discussion](img/comment-or-discussion.png)
-- Create a new merge request (with a new source branch named after the issue) in one action.
- The merge request will automatically inherit the milestone and labels of the issue. The merge
- request will automatically close that issue when it is merged.
-- Optionally, you can just create a [new branch](../repository/web_editor.md#create-a-new-branch-from-an-issue)
- named after that issue.
+You can also close the issue from here, so you don't need to scroll to the top of the issue page.
diff --git a/doc/user/project/issues/moving_issues.md b/doc/user/project/issues/moving_issues.md
index 211a651b89e..8aac2c01444 100644
--- a/doc/user/project/issues/moving_issues.md
+++ b/doc/user/project/issues/moving_issues.md
@@ -8,3 +8,28 @@ There will also be a system note added to both issues indicating where it came f
You can move an issue with the "Move issue" button at the bottom of the right-sidebar when viewing the issue.
![move issue - button](img/sidebar_move_issue.png)
+
+## Troubleshooting
+
+### Moving Issues in Bulk
+
+If you have advanced technical skills you can also bulk move all the issues from one project to another in the rails console. The below script will move all the issues from one project to another that are not in status **closed**.
+
+To access rails console run `sudo gitlab-rails console` on the GitLab server and run the below script. Please be sure to change **project**, **admin_user** and **target_project** to your values. We do also recommend [creating a backup](https://docs.gitlab.com/ee/raketasks/backup_restore.html#creating-a-backup-of-the-gitlab-system) before attempting any changes in the console.
+
+```ruby
+project = Project.find_by_full_path('full path of the project where issues are moved from')
+issues = project.issues
+admin_user = User.find_by_username('username of admin user') # make sure user has permissions to move the issues
+target_project = Project.find_by_full_path('full path of target project where issues moved to')
+
+issues.each do |issue|
+ if issue.state != "closed" && issue.moved_to.nil?
+ Issues::MoveService.new(project, admin_user).execute(issue, target_project)
+ else
+ puts "issue with id: #{issue.id} and title: #{issue.title} was not moved"
+ end
+end; nil
+
+```
+
diff --git a/doc/user/project/issues/multiple_assignees_for_issues.md b/doc/user/project/issues/multiple_assignees_for_issues.md
new file mode 100644
index 00000000000..d1db0790d69
--- /dev/null
+++ b/doc/user/project/issues/multiple_assignees_for_issues.md
@@ -0,0 +1,41 @@
+# Multiple Assignees for Issues **[STARTER]**
+
+> **Note:**
+[Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/1904)
+in [GitLab Starter 9.2](https://about.gitlab.com/2017/05/22/gitlab-9-2-released/#multiple-assignees-for-issues).
+
+## Overview
+
+In large teams, where there is shared ownership of an issue, it can be difficult
+to track who is working on it, who already completed their contributions, who
+didn't even start yet.
+
+In [GitLab Enterprise Edition](https://about.gitlab.com/pricing/),
+you can also select multiple assignees to an issue, making it easier to
+track, and making clearer who is accountable for it.
+
+![multiple assignees for issues](img/multiple_assignees_for_issues.png)
+
+## Use cases
+
+Consider a team formed by frontend developers, backend developers,
+UX designers, QA testers, and a product manager working together to bring an idea to
+market.
+
+Multiple Assignees for Issues makes collaboration smoother,
+and allows shared responsibilities to be clearly displayed.
+All assignees are shown across your team's workflows and receive notifications (as they
+would as single assignees), simplifying communication and ownership.
+
+Once an assignee had their work completed, they would remove themselves as assignees, making
+it clear that their role is complete.
+
+## How it works
+
+From an opened issue, expand the right sidebar, locate the assignees entry,
+and click on **Edit**. From the dropdown menu, select as many users as you want
+to assign the issue to.
+
+![adding multiple assignees](img/multiple_assignees.gif)
+
+An assignee can be easily removed by deselecting them from the same dropdown menu.
diff --git a/doc/user/project/issues/related_issues.md b/doc/user/project/issues/related_issues.md
new file mode 100644
index 00000000000..e679ebf86e6
--- /dev/null
+++ b/doc/user/project/issues/related_issues.md
@@ -0,0 +1,40 @@
+# Related issues **[STARTER]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1797) in [GitLab Starter](https://about.gitlab.com/pricing/) 9.4.
+
+Related issues are a bi-directional relationship between any two issues
+and appear in a block below the issue description. Issues can be across groups
+and projects.
+
+The relationship only shows up in the UI if the user can see both issues.
+
+## Adding a related issue
+
+You can relate one issue to another by clicking the related issues "+" button
+in the header of the related issue block. Then, input the issue reference number
+or paste in the full URL of the issue.
+
+Issues of the same project can be specified just by the reference number.
+Issues from a different project require additional information like the
+group and the project name. For example:
+
+- same project: `#44`
+- same group: `project#44 `
+- different group: `group/project#44`
+
+Valid references will be added to a temporary list that you can review.
+When ready, click the green "Add related issues" button to submit.
+
+![Adding a related issue](img/related_issues_add.png)
+
+## Removing a related issue
+
+In the related issues block, click the "x" icon on the right-side of each issue
+token that you wish to remove. Due to the bi-directional relationship, it
+will no longer appear in either issue.
+
+![Removing a related issue](img/related_issues_remove.png)
+
+Please access our [permissions](../../permissions.md) page for more information.
+
+Additionally, you are also able to manage related issues through [our API](../../../api/issue_links.md).
diff --git a/doc/user/project/labels.md b/doc/user/project/labels.md
index 9c045dfcce4..3eca1313a18 100644
--- a/doc/user/project/labels.md
+++ b/doc/user/project/labels.md
@@ -8,13 +8,58 @@ Labels allow you to categorize issues or merge requests using descriptive titles
In GitLab, you can create project and group labels:
-- **Project labels** can be assigned to issues or merge requests in that project only.
+- **Project labels** can be assigned to issues or merge requests in that project only.
- **Group labels** can be assigned to any issue or merge request of any project in that group or any subgroups of the group.
+## Scoped labels **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9175) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.10.
+
+Scoped labels allow teams to use the simple and familiar feature of labels to
+annotate their issues, merge requests, and epics to achieve custom fields and
+custom workflow states by leveraging a special label title syntax.
+
+A scoped label is a kind of label defined only by a special double-colon syntax
+in the label’s title, using the format `key::value`. For example:
+
+![A sample scoped label](img/key_value_labels.png)
+
+An issue, epic, or merge request cannot have two scoped labels with the same key.
+For example, if an issue is already labeled `priority::3` and you apply the label `priority::2` to it,
+`priority::3` is automatically removed.
+
+This functionality is demonstrated in a video titled [Use scoped labels in GitLab 11.10 for custom fields and custom workflows](https://www.youtube.com/watch?v=4BCBby6du3c).
+
+### Labels with multiple colon pairs
+
+If labels have multiple instances of `::`, the longest path from left to right, until the last `::`, is considered the "key" or the "scope".
+
+For example, `nested::key1::value1` and `nested::key1::value2` cannot both exist on the same issue. Adding the latter label will automatically remove the former due to the shared scope of `nested::key1`.
+
+`nested::key1::value1` and `nested::key2::value1` can both exist on the same issue, as these are considered to use two different label scopes, `nested::key1` and `nested::key2`.
+
+### Workflows with scoped labels **[PREMIUM]**
+
+Suppose you wanted a custom field in issues to track the platform operating system
+that your features target, where each issue should only target one platform. You
+would then create labels `platform::iOS`, `platform::Android`, `platform::Linux`,
+etc., as necessary. Applying any one of these labels on a given issue would
+automatically remove any other existing label that starts with `platform::`.
+
+The same pattern could be applied to represent the workflow states of your teams.
+Suppose you have the labels `workflow::development`, `workflow::review`, and
+`workflow::deployed`. If an issue already has the label `workflow::development`
+applied, and a developer wanted to advance the issue to `workflow::review`, they
+would simply apply that label, and the `workflow::development` label would
+automatically be removed. This behavior already exists when you move issues
+across label lists in an [issue board](issue_board.md#creating-workflows), but
+now, team members who may not be working in an issue board directly would still
+be able to advance workflow states consistently in issues themselves.
+
## Creating labels
>**Note:**
-A permission level of `Developer` or higher is required to create labels.
+A permission level of Reporter or higher is required to create labels.
### New project label
@@ -35,6 +80,9 @@ GitLab will add the following default labels to the project:
To create a **group label**, follow similar steps from above to project labels. Navigate to **Issues > Labels** in the group and create it from there.
This page only shows group labels in this group.
+Alternatively, you can create group labels also from Epic sidebar. Please note that the created label will belong to the immediate group to which epic belongs.
+
+![Create Labels from Epic](img/labels_epic_sidebar.png)
Group labels appear in every label list page of the group's child projects.
@@ -42,14 +90,14 @@ Group labels appear in every label list page of the group's child projects.
### New project label from sidebar
-From the sidebar of an issue or a merge request, you can create a create a new **project label** inline immediately, instead of navigating to the project label list page.
+From the sidebar of an issue or a merge request, you can create a new **project label** inline immediately, instead of navigating to the project label list page.
![Labels inline](img/new_label_from_sidebar.gif)
## Editing labels
NOTE: **Note:**
-A permission level of `Developer` or higher is required to edit labels.
+A permission level of Reporter or higher is required to edit labels.
You can update a label by navigating to **Issues > Labels** in the project or group and clicking the pencil icon.
@@ -81,7 +129,7 @@ top-right:
GitLab will consider the label title and description for the search.
-## Filtering issues and merge requests by label
+## Filtering issues, merge requests and epics by label
### Filtering in list pages
@@ -89,11 +137,16 @@ From the project issue list page and the project merge request list page, you ca
From the group issue list page and the group merge request list page, you can [filter](../search/index.md#issues-and-merge-requests) by both group labels (including subgroup ancestors and subgroup descendants) and project labels.
+From the group epic list page, you can [filter](../search/index.md#issues-and-merge-requests) by both current group labels as well as descendant group labels.
+
![Labels group issues](img/labels_group_issues.png)
### Filtering in issue boards
- From [project boards](issue_board.md), you can filter by both group labels and project labels in the [search and filter bar](../search/index.md#issue-boards).
+- From [group issue boards](issue_board.md#group-issue-boards-premium), you can filter by only group labels in the [search and filter bar](../search/index.md#issue-boards). **[PREMIUM]**
+- From [project boards](issue_board.md), you can filter by both group labels and project labels in the [issue board configuration](issue_board.md#configurable-issue-boards-starter). **[STARTER]**
+- From [group issue boards](issue_board.md#group-issue-boards-premium), you can filter by only group labels in the [issue board configuration](issue_board.md#configurable-issue-boards-starter). **[STARTER]**
## Subscribing to labels
diff --git a/doc/user/project/maven_packages.md b/doc/user/project/maven_packages.md
new file mode 100644
index 00000000000..48835a2dac7
--- /dev/null
+++ b/doc/user/project/maven_packages.md
@@ -0,0 +1,5 @@
+---
+redirect_to: 'packages/maven_repository.md'
+---
+
+This document was moved to [another location](packages/maven_repository.md).
diff --git a/doc/user/project/members/img/add_new_user_to_project_settings.png b/doc/user/project/members/img/add_new_user_to_project_settings.png
deleted file mode 100644
index e49ea1a3e3d..00000000000
--- a/doc/user/project/members/img/add_new_user_to_project_settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/members/img/add_user_members_menu.png b/doc/user/project/members/img/add_user_members_menu.png
deleted file mode 100644
index 6f08088b52f..00000000000
--- a/doc/user/project/members/img/add_user_members_menu.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/members/img/max_access_level.png b/doc/user/project/members/img/max_access_level.png
deleted file mode 100644
index 42a0416ffbb..00000000000
--- a/doc/user/project/members/img/max_access_level.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/allow_collaboration.md b/doc/user/project/merge_requests/allow_collaboration.md
index da6e6b5fd3a..e94125e658d 100644
--- a/doc/user/project/merge_requests/allow_collaboration.md
+++ b/doc/user/project/merge_requests/allow_collaboration.md
@@ -1,3 +1,7 @@
+---
+type: reference, howto
+---
+
# Allow collaboration on merge requests across forks
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17395)
@@ -70,3 +74,15 @@ Here's how the process would look like:
Note the colon (`:`) between the two branches. The above command will push the
local branch `thedude-awesome-project-update-docs` to the
`update-docs` branch of the `git@gitlab.com:thedude/awesome-project.git` repository.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/project/merge_requests/authorization_for_merge_requests.md b/doc/user/project/merge_requests/authorization_for_merge_requests.md
index 79444ee5682..0579e3568da 100644
--- a/doc/user/project/merge_requests/authorization_for_merge_requests.md
+++ b/doc/user/project/merge_requests/authorization_for_merge_requests.md
@@ -1,8 +1,12 @@
+---
+type: concepts
+---
+
# Authorization for Merge requests
There are two main ways to have a merge request flow with GitLab:
-1. Working with [protected branches] in a single repository.
+1. Working with [protected branches](../protected_branches.md) in a single repository.
1. Working with forks of an authoritative project.
## Protected branch flow
@@ -53,4 +57,14 @@ forks.
- The project need to keep their forks up to date, which requires more advanced
Git skills (managing multiple remotes).
-[protected branches]: ../protected_branches.md
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/project/merge_requests/browser_performance_testing.md b/doc/user/project/merge_requests/browser_performance_testing.md
new file mode 100644
index 00000000000..f6c4f767e3c
--- /dev/null
+++ b/doc/user/project/merge_requests/browser_performance_testing.md
@@ -0,0 +1,70 @@
+---
+type: reference, howto
+---
+
+# Browser Performance Testing **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3507)
+in [GitLab Premium](https://about.gitlab.com/pricing/) 10.3.
+
+If your application offers a web interface and you are using
+[GitLab CI/CD](../../../ci/README.md), you can quickly determine the performance
+impact of pending code changes.
+
+## Overview
+
+GitLab uses [Sitespeed.io](https://www.sitespeed.io), a free and open source
+tool for measuring the performance of web sites, and has built a simple
+[Sitespeed plugin](https://gitlab.com/gitlab-org/gl-performance)
+which outputs the results in a file called `performance.json`. This plugin
+outputs the performance score for each page that is analyzed.
+
+The [Sitespeed.io performance score](http://examples.sitespeed.io/6.0/2017-11-23-23-43-35/help.html)
+is a composite value based on best practices, and we will be expanding support
+for [additional metrics](https://gitlab.com/gitlab-org/gitlab-ee/issues/4370)
+in a future release.
+
+Going a step further, GitLab can show the Performance report right
+in the merge request widget area:
+
+## Use cases
+
+For instance, consider the following workflow:
+
+1. A member of the marketing team is attempting to track engagement by adding a new tool
+1. With browser performance metrics, they see how their changes are impacting the usability of the page for end users
+1. The metrics show that after their changes the performance score of the page has gone down
+1. When looking at the detailed report, they see that the new Javascript library was included in `<head>` which affects loading page speed
+1. They ask a front end developer to help them, who sets the library to load asynchronously
+1. The frontend developer approves the merge request and authorizes its deployment to production
+
+## How it works
+
+First of all, you need to define a job in your `.gitlab-ci.yml` file that generates the
+[Performance report artifact](../../../ci/yaml/README.md#artifactsreportsperformance-premium).
+For more information on how the Performance job should look like, check the
+example on [Testing Browser Performance](../../../ci/examples/browser_performance.md).
+
+GitLab then checks this report, compares key performance metrics for each page
+between the source and target branches, and shows the information right on the merge request.
+
+>**Note:**
+If the Performance report doesn't have anything to compare to, no information
+will be displayed in the merge request area. That is the case when you add the
+Performance job in your `.gitlab-ci.yml` for the very first time.
+Consecutive merge requests will have something to compare to and the Performance
+report will be shown properly.
+
+![Performance Widget](img/browser_performance_testing.png)
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/project/merge_requests/cherry_pick_changes.md b/doc/user/project/merge_requests/cherry_pick_changes.md
index 06b3779668b..a5c191c150f 100644
--- a/doc/user/project/merge_requests/cherry_pick_changes.md
+++ b/doc/user/project/merge_requests/cherry_pick_changes.md
@@ -1,8 +1,11 @@
-# Cherry-pick changes
+---
+type: reference, concepts
+---
-> [Introduced][ce-3514] in GitLab 8.7.
+# Cherry-pick changes
-GitLab implements Git's powerful feature to [cherry-pick any commit][git-cherry-pick]
+GitLab implements Git's powerful feature to
+[cherry-pick any commit](https://git-scm.com/docs/git-cherry-pick "Git cherry-pick documentation")
with introducing a **Cherry-pick** button in merge requests and commit details.
## Cherry-picking a merge request
@@ -18,9 +21,9 @@ where you can choose to either:
- Cherry-pick the changes directly into the selected branch.
- Create a new merge request with the cherry-picked changes.
-## Cherry-picking a Commit
+## Cherry-picking a commit
-You can cherry-pick a Commit from the Commit details page:
+You can cherry-pick a commit from the commit details page:
![Cherry-pick commit](img/cherry_pick_changes_commit.png)
@@ -39,5 +42,14 @@ mainline:
git cherry-pick -m 2 7a39eb0
```
-[ce-3514]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3514 "Cherry-pick button Merge Request"
-[git-cherry-pick]: https://git-scm.com/docs/git-cherry-pick "Git cherry-pick documentation"
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/project/merge_requests/code_quality.md b/doc/user/project/merge_requests/code_quality.md
new file mode 100644
index 00000000000..c3c2bdd94b3
--- /dev/null
+++ b/doc/user/project/merge_requests/code_quality.md
@@ -0,0 +1,94 @@
+---
+type: reference, howto
+---
+
+# Code Quality **[STARTER]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1984)
+in [GitLab Starter](https://about.gitlab.com/pricing/) 9.3.
+
+With the help of [GitLab CI/CD](../../../ci/README.md), you can analyze your
+source code quality using GitLab Code Quality.
+Code Quality uses [Code Climate Engines](https://codeclimate.com), which are
+free and open source. Code Quality doesn't require a Code Climate subscription.
+
+Going a step further, GitLab can show the Code Quality report right
+in the merge request widget area:
+
+![Code Quality Widget](img/code_quality.gif)
+
+## Use cases
+
+For instance, consider the following workflow:
+
+1. Your backend team member starts a new implementation for making a certain feature in your app faster
+1. With Code Quality reports, they analyze how their implementation is impacting the code quality
+1. The metrics show that their code degrade the quality in 10 points
+1. You ask a co-worker to help them with this modification
+1. They both work on the changes until Code Quality report displays no degradations, only improvements
+1. You approve the merge request and authorize its deployment to staging
+1. Once verified, their changes are deployed to production
+
+## How it works
+
+First of all, you need to define a job in your `.gitlab-ci.yml` file that generates the
+[Code Quality report artifact](../../../ci/yaml/README.md#artifactsreportscodequality-starter).
+
+The Code Quality report artifact is a subset of the
+[Code Climate spec](https://github.com/codeclimate/spec/blob/master/SPEC.md#data-types).
+It must be a JSON file containing an array of objects with the following properties:
+
+| Name | Description |
+| ---------------------- | -------------------------------------------------------------------------------------- |
+| `description` | A description of the code quality violation. |
+| `fingerprint` | A unique fingerprint to identify the code quality violation. For example, an MD5 hash. |
+| `location.path` | The relative path to the file containing the code quality violation. |
+| `location.lines.begin` | The line on which the code quality violation occurred. |
+
+Example:
+
+```json
+[
+ {
+ "description": "'unused' is assigned a value but never used.",
+ "fingerprint": "7815696ecbf1c96e6894b779456d330e",
+ "location": {
+ "path": "lib/index.js",
+ "lines": {
+ "begin": 42
+ }
+ }
+ }
+]
+```
+
+NOTE: **Note:**
+Although the Code Climate spec supports more properties, those are ignored by GitLab.
+
+For more information on what the Code Quality job should look like, check the
+example on [analyzing a project's code quality](../../../ci/examples/code_quality.md).
+
+GitLab then checks this report, compares the metrics between the source and target
+branches, and shows the information right on the merge request.
+
+If multiple jobs in a pipeline generate a code quality artifact, only the artifact from
+the last created job (the job with the largest job ID) is used. To avoid confusion,
+configure only one job to generate a code quality artifact.
+
+If the Code Quality report doesn't have anything to compare to, no information
+will be displayed in the merge request area. That is the case when you add the
+Code Quality job in your `.gitlab-ci.yml` for the very first time.
+Consecutive merge requests will have something to compare to and the Code Quality
+report will be shown properly.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/project/merge_requests/code_quality_diff.md b/doc/user/project/merge_requests/code_quality_diff.md
new file mode 100644
index 00000000000..ccc694672a6
--- /dev/null
+++ b/doc/user/project/merge_requests/code_quality_diff.md
@@ -0,0 +1,6 @@
+---
+redirect_from: 'code_quality_diff.md'
+redirect_to: 'code_quality.md'
+---
+
+This document was moved to [another location](code_quality.md).
diff --git a/doc/user/project/merge_requests/container_scanning.md b/doc/user/project/merge_requests/container_scanning.md
new file mode 100644
index 00000000000..a062731ea35
--- /dev/null
+++ b/doc/user/project/merge_requests/container_scanning.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../../application_security/container_scanning/index.md'
+---
+
+This document was moved to [another location](../../application_security/container_scanning/index.md).
diff --git a/doc/user/project/merge_requests/dast.md b/doc/user/project/merge_requests/dast.md
new file mode 100644
index 00000000000..98a2906e560
--- /dev/null
+++ b/doc/user/project/merge_requests/dast.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../../application_security/dast/index.md'
+---
+
+This document was moved to [another location](../../application_security/dast/index.md).
diff --git a/doc/user/project/merge_requests/dependency_scanning.md b/doc/user/project/merge_requests/dependency_scanning.md
new file mode 100644
index 00000000000..bdc1c355016
--- /dev/null
+++ b/doc/user/project/merge_requests/dependency_scanning.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../../application_security/dependency_scanning/index.md'
+---
+
+This document was moved to [another location](../../application_security/dependency_scanning/index.md).
diff --git a/doc/user/project/merge_requests/fast_forward_merge.md b/doc/user/project/merge_requests/fast_forward_merge.md
index 3cd91a185e3..4f3c68090e4 100644
--- a/doc/user/project/merge_requests/fast_forward_merge.md
+++ b/doc/user/project/merge_requests/fast_forward_merge.md
@@ -1,21 +1,24 @@
+---
+type: reference, concepts
+---
+
# Fast-forward merge requests
-Retain a linear Git history and a way to accept merge requests without
-creating merge commits.
+Sometimes, a workflow policy might mandate a clean commit history without
+merge commits. In such cases, the fast-forward merge is the perfect candidate.
+
+With fast-forward merge requests, you can retain a linear Git history and a way
+to accept merge requests without creating merge commits.
## Overview
-When the fast-forward merge ([`--ff-only`][ffonly]) setting is enabled, no merge
-commits will be created and all merges are fast-forwarded, which means that
-merging is only allowed if the branch could be fast-forwarded.
+When the fast-forward merge
+([`--ff-only`](https://git-scm.com/docs/git-merge#git-merge---ff-only)) setting
+is enabled, no merge commits will be created and all merges are fast-forwarded,
+which means that merging is only allowed if the branch could be fast-forwarded.
When a fast-forward merge is not possible, the user is given the option to rebase.
-## Use cases
-
-Sometimes, a workflow policy might mandate a clean commit history without
-merge commits. In such cases, the fast-forward merge is the perfect candidate.
-
## Enabling fast-forward merges
1. Navigate to your project's **Settings** and search for the 'Merge method'
@@ -32,4 +35,14 @@ source branch locally before you will be able to do a fast-forward merge.
![Fast forward merge rebase locally](img/ff_merge_rebase_locally.png)
-[ffonly]: https://git-scm.com/docs/git-merge#git-merge---ff-only
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/project/merge_requests/img/approvals_can_override.png b/doc/user/project/merge_requests/img/approvals_can_override.png
new file mode 100644
index 00000000000..8d207d018e0
--- /dev/null
+++ b/doc/user/project/merge_requests/img/approvals_can_override.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/approvals_premium_mr_widget.png b/doc/user/project/merge_requests/img/approvals_premium_mr_widget.png
new file mode 100644
index 00000000000..b6dc86f312e
--- /dev/null
+++ b/doc/user/project/merge_requests/img/approvals_premium_mr_widget.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/approvals_premium_project_edit.png b/doc/user/project/merge_requests/img/approvals_premium_project_edit.png
new file mode 100644
index 00000000000..b6f6188b9cd
--- /dev/null
+++ b/doc/user/project/merge_requests/img/approvals_premium_project_edit.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/approvals_remove_on_push.png b/doc/user/project/merge_requests/img/approvals_remove_on_push.png
new file mode 100644
index 00000000000..73964827587
--- /dev/null
+++ b/doc/user/project/merge_requests/img/approvals_remove_on_push.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/approvals_starter_project_edit.png b/doc/user/project/merge_requests/img/approvals_starter_project_edit.png
new file mode 100644
index 00000000000..868b9d58740
--- /dev/null
+++ b/doc/user/project/merge_requests/img/approvals_starter_project_edit.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/approvals_starter_project_empty.png b/doc/user/project/merge_requests/img/approvals_starter_project_empty.png
new file mode 100644
index 00000000000..7375820224c
--- /dev/null
+++ b/doc/user/project/merge_requests/img/approvals_starter_project_empty.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/approve.png b/doc/user/project/merge_requests/img/approve.png
new file mode 100644
index 00000000000..e68259ac5c2
--- /dev/null
+++ b/doc/user/project/merge_requests/img/approve.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/approve_additionally.png b/doc/user/project/merge_requests/img/approve_additionally.png
new file mode 100644
index 00000000000..3db5a9159e5
--- /dev/null
+++ b/doc/user/project/merge_requests/img/approve_additionally.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/browser_performance_testing.png b/doc/user/project/merge_requests/img/browser_performance_testing.png
new file mode 100644
index 00000000000..eea77fb8b93
--- /dev/null
+++ b/doc/user/project/merge_requests/img/browser_performance_testing.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/code_quality.gif b/doc/user/project/merge_requests/img/code_quality.gif
new file mode 100644
index 00000000000..bab921cf38b
--- /dev/null
+++ b/doc/user/project/merge_requests/img/code_quality.gif
Binary files differ
diff --git a/doc/user/project/merge_requests/img/filter_approver_merge_requests.png b/doc/user/project/merge_requests/img/filter_approver_merge_requests.png
new file mode 100644
index 00000000000..9c386391a4f
--- /dev/null
+++ b/doc/user/project/merge_requests/img/filter_approver_merge_requests.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/multiple_assignees_for_merge_requests_sidebar.png b/doc/user/project/merge_requests/img/multiple_assignees_for_merge_requests_sidebar.png
new file mode 100644
index 00000000000..9ae6e350798
--- /dev/null
+++ b/doc/user/project/merge_requests/img/multiple_assignees_for_merge_requests_sidebar.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/remove_approval.png b/doc/user/project/merge_requests/img/remove_approval.png
new file mode 100644
index 00000000000..6083e1745ef
--- /dev/null
+++ b/doc/user/project/merge_requests/img/remove_approval.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/revert_changes_commit.png b/doc/user/project/merge_requests/img/revert_changes_commit.png
deleted file mode 100644
index c9dd0019024..00000000000
--- a/doc/user/project/merge_requests/img/revert_changes_commit.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/revert_changes_mr.png b/doc/user/project/merge_requests/img/revert_changes_mr.png
deleted file mode 100644
index 06b841b3002..00000000000
--- a/doc/user/project/merge_requests/img/revert_changes_mr.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md
index ba7d05a7ad7..447b338928c 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -1,7 +1,11 @@
+---
+type: index, reference, concepts
+---
+
# Merge requests
-Merge requests allow you to exchange changes you made to source code and
-collaborate with other people on the same project.
+Merge requests allow you to visualize and collaborate on the proposed changes
+to source code that exist as commits on a given Git branch.
![Merge request view](img/merge_request.png)
@@ -23,7 +27,7 @@ With GitLab merge requests, you can:
- Assign it to any registered user, and change the assignee how many times you need
- Assign a [milestone](../../project/milestones/index.md) and track the development of a broader implementation
- Organize your issues and merge requests consistently throughout the project with [labels](../../project/labels.md)
-- Add a time estimation and the time spent with that merge request with [Time Tracking](../../../workflow/time_tracking.html#time-tracking)
+- Add a time estimation and the time spent with that merge request with [Time Tracking](../../../workflow/time_tracking.md#time-tracking)
- [Resolve merge conflicts from the UI](#resolve-conflicts)
- Enable [fast-forward merge requests](#fast-forward-merge-requests)
- Enable [semi-linear history merge requests](#semi-linear-history-merge-requests) as another security layer to guarantee the pipeline is passing in the target branch
@@ -33,9 +37,16 @@ With GitLab merge requests, you can:
With **[GitLab Enterprise Edition][ee]**, you can also:
-- View the deployment process across projects with [Multi-Project Pipeline Graphs](https://docs.gitlab.com/ee/ci/multi_project_pipeline_graphs.html#multi-project-pipeline-graphs) **[PREMIUM]**
-- Request [approvals](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html) from your managers **[STARTER]**
-- Analyze the impact of your changes with [Code Quality reports](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html) **[STARTER]**
+- Prepare a full review and submit it once it's ready with [Merge Request Reviews](../../discussions/index.md#merge-request-reviews-premium) **[PREMIUM]**
+- View the deployment process across projects with [Multi-Project Pipelines](../../../ci/multi_project_pipelines.md) **[PREMIUM]**
+- Request [approvals](merge_request_approvals.md) from your managers **[STARTER]**
+- Analyze the impact of your changes with [Code Quality reports](code_quality.md) **[STARTER]**
+- Manage the licenses of your dependencies with [License Management](../../application_security/license_management/index.md) **[ULTIMATE]**
+- Analyze your source code for vulnerabilities with [Static Application Security Testing](../../application_security/sast/index.md) **[ULTIMATE]**
+- Analyze your running web applications for vulnerabilities with [Dynamic Application Security Testing](../../application_security/dast/index.md) **[ULTIMATE]**
+- Analyze your dependencies for vulnerabilities with [Dependency Scanning](../../application_security/dependency_scanning/index.md) **[ULTIMATE]**
+- Analyze your Docker images for vulnerabilities with [Container Scanning](../../application_security/container_scanning/index.md) **[ULTIMATE]**
+- Determine the performance impact of changes with [Browser Performance Testing](#browser-performance-testing-premium) **[PREMIUM]**
## Use cases
@@ -43,19 +54,21 @@ A. Consider you are a software developer working in a team:
1. You checkout a new branch, and submit your changes through a merge request
1. You gather feedback from your team
+1. You work on the implementation optimizing code with [Code Quality reports](code_quality.md) **[STARTER]**
1. You verify your changes with [JUnit test reports](../../../ci/junit_test_reports.md) in GitLab CI/CD
-1. You request the approval from your manager
-1. Your manager pushes a commit with his final review, [approves the merge request](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html), and set it to [merge when pipeline succeeds](#merge-when-pipeline-succeeds) (Merge Request Approvals are available in GitLab Starter)
+1. You avoid using dependencies whose license is not compatible with your project with [License Management reports](license_management.md) **[ULTIMATE]**
+1. You request the [approval](#merge-request-approvals-starter) from your manager
+1. Your manager pushes a commit with their final review, [approves the merge request](merge_request_approvals.md), and set it to [merge when pipeline succeeds](#merge-when-pipeline-succeeds) (Merge Request Approvals are available in GitLab Starter)
1. Your changes get deployed to production with [manual actions](../../../ci/yaml/README.md#whenmanual) for GitLab CI/CD
1. Your implementations were successfully shipped to your customer
-B. Consider you're a web developer writing a webpage for your company's:
+B. Consider you're a web developer writing a webpage for your company's website:
1. You checkout a new branch, and submit a new page through a merge request
1. You gather feedback from your reviewers
1. Your changes are previewed with [Review Apps](../../../ci/review_apps/index.md)
1. You request your web designers for their implementation
-1. You request the [approval](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html) from your manager **[STARTER]**
+1. You request the [approval](merge_request_approvals.md) from your manager **[STARTER]**
1. Once approved, your merge request is [squashed and merged](squash_and_merge.md), and [deployed to staging with GitLab Pages](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/)
1. Your production team [cherry picks](#cherry-pick-changes) the merge commit into production
@@ -159,6 +172,21 @@ in a Merge Request. To do so, click the **...** button in the gutter of the Merg
![Comment on any diff file line](img/comment-on-any-diff-line.png)
+## Perform a Review **[PREMIUM]**
+
+Start a review in order to create multiple comments on a diff and publish them once you're ready.
+Starting a review allows you to get all your thoughts in order and ensure you haven't missed anything
+before submitting all your comments.
+
+[Learn more about Merge Request Reviews](../../discussions/index.md#merge-request-reviews-premium)
+
+## Squash and merge
+
+GitLab allows you to squash all changes present in a merge request into a single
+commit when merging, to allow for a neater commit history.
+
+[Learn more about squash and merge.](squash_and_merge.md)
+
## Suggest changes
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/18008) in GitLab 11.6.
@@ -169,6 +197,28 @@ can easily apply them to the codebase directly from the UI. Read
through the documentation on [Suggest changes](../../discussions/index.md#suggest-changes)
to learn more.
+## Multiple assignees **[STARTER]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/2004)
+in [GitLab Starter 11.11](https://about.gitlab.com/pricing).
+
+Multiple people often review merge requests at the same time. GitLab allows you to have multiple assignees for merge requests to indicate everyone that is reviewing or accountable for it.
+
+![multiple assignees for merge requests sidebar](img/multiple_assignees_for_merge_requests_sidebar.png)
+
+To assign multiple assignees to a merge request:
+
+1. From a merge request, expand the right sidebar and locate the **Assignees** section.
+1. Click on **Edit** and from the dropdown menu, select as many users as you want
+ to assign the merge request to.
+
+Similarly, assignees are removed by deselecting them from the same dropdown menu.
+
+It's also possible to manage multiple assignees:
+
+- When creating a merge request.
+- Using [quick actions](../quick_actions.md#quick-actions-for-issues-and-merge-requests).
+
## Resolve conflicts
When a merge request has conflicts, GitLab may provide the option to resolve
@@ -314,6 +364,60 @@ have been marked as a **Work In Progress**.
[Learn more about setting a merge request as "Work In Progress".](work_in_progress_merge_requests.md)
+## Merge request approvals **[STARTER]**
+
+> Included in [GitLab Starter][products].
+
+If you want to make sure every merge request is approved by one or more people,
+you can enforce this workflow by using merge request approvals. Merge request
+approvals allow you to set the number of necessary approvals and predefine a
+list of approvers that will need to approve every merge request in a project.
+
+[Read more about merge request approvals.](merge_request_approvals.md)
+
+## Code Quality **[STARTER]**
+
+> Introduced in [GitLab Starter][products] 9.3.
+
+If you are using [GitLab CI][ci], you can analyze your source code quality using
+the [Code Climate][cc] analyzer [Docker image][cd]. Going a step further, GitLab
+can show the Code Climate report right in the merge request widget area.
+
+[Read more about Code Quality reports.](code_quality.md)
+
+## Browser Performance Testing **[PREMIUM]**
+
+> Introduced in [GitLab Premium][products] 10.3.
+
+If your application offers a web interface and you are using [GitLab CI/CD][ci], you can quickly determine the performance impact of pending code changes. GitLab uses [Sitespeed.io][sitespeed], a free and open source tool for measuring the performance of web sites, to analyze the performance of specific pages.
+
+GitLab runs the [Sitespeed.io container][sitespeed-container] and displays the difference in overall performance scores between the source and target branches.
+
+[Read more about Browser Performance Testing.](browser_performance_testing.md)
+
+## Security reports **[ULTIMATE]**
+
+GitLab can scan and report any vulnerabilities found in your project.
+
+[Read more about security reports.](../../application_security/index.md)
+
+## JUnit test reports
+
+Configure your CI jobs to use JUnit test reports, and let GitLab display a report
+on the merge request so that it’s easier and faster to identify the failure
+without having to check the entire job log.
+
+[Read more about JUnit test reports](../../../ci/junit_test_reports.md).
+
+## Live preview with Review Apps
+
+If you configured [Review Apps](https://about.gitlab.com/features/review-apps/) for your project,
+you can preview the changes submitted to a feature-branch through a merge request
+in a per-branch basis. No need to checkout the branch, install and preview locally;
+all your changes will be available to preview by anyone with the Review Apps link.
+
+[Read more about Review Apps.](../../../ci/review_apps/index.md)
+
## Merge request diff file navigation
When reviewing changes in the **Changes** tab the diff can be navigated using
@@ -411,7 +515,7 @@ seconds and the status will update automatically.
Merge Request pipeline statuses can't be retrieved when the following occurs:
-1. A Merge Requst is created
+1. A Merge Request is created
1. The Merge Request is closed
1. Changes are made in the project
1. The Merge Request is reopened
@@ -447,13 +551,13 @@ Add the following alias to your `~/.gitconfig`:
Now you can check out a particular merge request from any repository and any
remote. For example, to check out the merge request with ID 5 as shown in GitLab
-from the `upstream` remote, do:
+from the `origin` remote, do:
```
-git mr upstream 5
+git mr origin 5
```
-This will fetch the merge request into a local `mr-upstream-5` branch and check
+This will fetch the merge request into a local `mr-origin-5` branch and check
it out.
#### Checkout locally by modifying `.git/config` for a given repository
@@ -506,5 +610,14 @@ And to check out a particular merge request:
git checkout origin/merge-requests/1
```
+all the above can be done with [git-mr] script.
+
+[git-mr]: https://gitlab.com/glensc/git-mr
+[products]: https://about.gitlab.com/products/ "GitLab products page"
[protected branches]: ../protected_branches.md
+[ci]: ../../../ci/README.md
+[cc]: https://codeclimate.com/
+[cd]: https://hub.docker.com/r/codeclimate/codeclimate/
+[sitespeed]: https://www.sitespeed.io
+[sitespeed-container]: https://hub.docker.com/r/sitespeedio/sitespeed.io/
[ee]: https://about.gitlab.com/pricing/ "GitLab Enterprise Edition"
diff --git a/doc/user/project/merge_requests/license_management.md b/doc/user/project/merge_requests/license_management.md
new file mode 100644
index 00000000000..93116ebd7c6
--- /dev/null
+++ b/doc/user/project/merge_requests/license_management.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../../application_security/license_management/index.md'
+---
+
+This document was moved to [another location](../../application_security/license_management/index.md).
diff --git a/doc/user/project/merge_requests/merge_request_approvals.md b/doc/user/project/merge_requests/merge_request_approvals.md
new file mode 100644
index 00000000000..fd151a6df45
--- /dev/null
+++ b/doc/user/project/merge_requests/merge_request_approvals.md
@@ -0,0 +1,344 @@
+---
+type: reference, concepts
+---
+
+# Merge request approvals **[STARTER]**
+
+> Introduced in [GitLab Enterprise Edition 7.12](https://about.gitlab.com/2015/06/22/gitlab-7-12-released/#merge-request-approvers-ee-only).
+
+Merge request approvals enable enforced code review by requiring specified people
+to approve a merge request before it can be unblocked for merging.
+
+## Use cases
+
+1. Enforcing review of all code that gets merged into a repository.
+2. Specifying code maintainers for an entire repository.
+3. Specifying reviewers for a given proposed code change.
+4. Specifying categories of reviewers, such as BE, FE, QA, DB, etc., for all proposed code changes.
+
+## Enabling the new approvals interface
+
+NOTE: **Note:**
+Prior to 12.0, if you are running a self-managed instance, the new interface shown on
+this page will not be available unless the feature flag
+`approval_rules` is enabled, which can be done from the Rails console by
+instance administrators.
+
+Use these commands to start the Rails console:
+
+```sh
+# Omnibus GitLab
+gitlab-rails console
+
+# Installation from source
+cd /home/git/gitlab
+sudo -u git -H bin/rails console RAILS_ENV=production
+```
+
+Then run `Feature.enable(:approval_rules)` to enable the feature flag.
+
+## Editing approvals
+
+To edit the merge request approvals:
+
+1. Navigate to your project's **Settings > General** and expand
+ **Merge request approvals**.
+
+ ![Approvals starter project empty](img/approvals_starter_project_empty.png)
+
+1. Click **Edit**.
+1. Search for users or groups that will be [eligible to approve](#eligible-approvers)
+ merge requests and click the **Add** button to add them as approvers. Note: selecting
+ approvers is optional.
+1. Set the minimum number of required approvals under the **No. approvals required**
+ box. Note: the minimum can be 0.
+1. Click **Update approvers**.
+
+ ![Approvals starter project edit](img/approvals_starter_project_edit.png)
+
+The steps above are the minimum required to get approvals working in your
+merge requests, but there are a couple more options available that might be
+suitable to your workflow:
+
+- Choose whether the default settings can be
+ [overridden per merge request](#overriding-the-merge-request-approvals-default-settings)
+- Choose whether [approvals will be reset with new pushed commits](#resetting-approvals-on-push)
+
+## Editing approvals **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/1979) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.8.
+
+CAUTION: **Caution:**
+There was a [regression affecting this feature in 11.8](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9648). We recommend upgrading _at least_ to version 11.8.2. to avoid any issues.
+
+NOTE: **Note:**
+In 11.8 this feature does not work in [private groups](https://gitlab.com/gitlab-org/gitlab-ee/issues/10356).
+
+For GitLab Premium, [multiple approver rules](#multiple-approval-rules-premium) can be configured. To configure the merge
+request approval rules:
+
+1. Navigate to your project's **Settings > General** and expand **Merge request approvals**.
+1. Click **Add approvers** to create a new approval rule.
+1. Just like in [GitLab Starter](#editing-approvals), select the approval members and approvals required.
+1. Give the approval rule a name that describes the set of approvers selected.
+1. Click **Add approvers** to submit the new rule.
+
+ ![Approvals premium project edit](img/approvals_premium_project_edit.png)
+
+## Multiple approval rules **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/1979) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.8.
+
+For GitLab Premium, a merge request's overall approval status is determined by a set of rules. Each rule contains:
+
+- A set of [eligible approvers](#eligible-approvers).
+- A minimum number of approvals required.
+
+When an [eligible approver](#eligible-approvers) approves a merge request, it will reduce the number of approvals left for
+all rules that the approver belongs to.
+
+![Approvals premium merge request widget](img/approvals_premium_mr_widget.png)
+
+If no approval rules are set, then the overall minimum number of approvals required can be configured. With no approval rules,
+any [eligible approver](#eligible-approvers) may approve.
+
+## Eligible approvers
+
+The following can approve merge requests:
+
+- Users being added as approvers at project or merge request level.
+- [Code owners](../code_owners.md) related to the merge request ([introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/7933) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.5).
+
+An individual user can be added as an approver for a project if they are a member of:
+
+- The project.
+- The project's immediate parent group.
+- A group that has access to the project via a [share](../members/share_project_with_groups.md).
+
+A group can also be added as an approver. [In the future](https://gitlab.com/gitlab-org/gitlab-ee/issues/2048),
+group approvers will be restricted.
+
+If a user is added as an individual approver and is also part of a group approver,
+then that user is just counted once. The merge request author, as well as users who have committed
+to the merge request, do not count as eligible approvers,
+if [**Prevent author approval**](#allowing-merge-request-authors-to-approve-their-own-merge-requests) (enabled by default)
+and [**Prevent committers approval**](#prevent-approval-of-merge-requests-by-their-committers) (disabled by default)
+are enabled on the project settings.
+
+### Implicit approvers
+
+If the number of required approvals is greater than the number of approvers,
+other users will become implicit approvers to fill the gap.
+Those implicit approvers include members of the given project with Developer role or higher.
+
+## Adding or removing an approval
+
+If approvals are activated for the given project, when a user visits an open
+merge request, depending on their [eligibility](#eligible-approvers), one of
+the following is possible:
+
+- **They are not an eligible approver**: They cannot do anything with respect
+ to approving this merge request.
+
+- **They have not approved this merge request**:
+
+ - If the required number of approvals has _not_ been yet met, they can approve
+ it by clicking the displayed **Approve** button.
+ ![Approve](img/approve.png)
+ - If the required number of approvals has already been met, they can still
+ approve it by clicking the displayed **Approve additionally** button.
+ ![Add approval](img/approve_additionally.png)
+
+- **They have already approved this merge request**: They can remove their approval.
+
+ ![Remove approval](img/remove_approval.png)
+
+NOTE: **Note:**
+The merge request author is only allowed to approve their own merge request
+if [**Prevent author approval**](#allowing-merge-request-authors-to-approve-their-own-merge-requests) is disabled on the project settings.
+
+For a given merge request, if the approval restrictions have been satisfied,
+the merge request is unblocked and can be merged.
+Note, that meeting the required number of approvals is a necessary, but not
+sufficient condition for unblocking a merge request from being merged. There
+are other conditions that may block it, such as merge conflicts,
+[pending discussions](../../discussions/index.md#only-allow-merge-requests-to-be-merged-if-all-discussions-are-resolved)
+or a [failed CI/CD pipeline](merge_when_pipeline_succeeds.md).
+
+## Code Owners approvals **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/4418) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.9.
+
+It is possible to require at least one approval for each entry in the
+[`CODEOWNERS` file](../code_owners.md) that matches a file changed in
+the merge request. To enable this feature:
+
+1. Navigate to your project's **Settings > General** and expand
+ **Merge request approvals**.
+1. Tick the **Require approval from code owners** checkbox.
+1. Click **Save changes**.
+
+When this feature is enabled, all merge requests will need approval
+from one code owner per matched rule before it can be merged.
+
+## Overriding the merge request approvals default settings
+
+> Introduced in GitLab Enterprise Edition 9.4.
+
+NOTE: **Note:**
+If you are using GitLab Premium, things are a little different with [multiple approval rules](#multiple-approval-rules-premium).
+Read the differences [in GitLab Premium when overriding merge request approvals](#overriding-merge-request-approvals-default-settings-premium).
+
+If approvals are [set at the project level](#editing-approvals), the
+default configuration (number of required approvals and approvers) can be
+overridden for each merge request in that project.
+
+One possible scenario would be to to assign a group of approvers at the project
+level and change them later when creating or editing the merge request.
+
+First, you have to enable this option in the project's settings:
+
+1. Navigate to your project's **Settings > General** and expand
+ **Merge request approvals**
+1. Tick the "Can override approvers and approvals required per merge request"
+ checkbox
+
+ ![Approvals can override](img/approvals_can_override.png)
+
+1. Click **Save changes**
+
+NOTE: **Note:**
+If approver overriding is enabled
+and the project level approvers are changed after a merge request is created,
+the merge request retains the previous approvers.
+However, the approvers can be changed by [editing the merge request](#overriding-the-merge-request-approvals-default-settings).
+
+---
+
+The default approval settings can now be overridden when creating a
+[merge request](index.md) or by editing it after it's been created:
+
+1. Click **Edit** under the **Approvers** section.
+1. Search for users or groups that will be [eligible to approve](#eligible-approvers)
+ merge requests and click the **Add** button to add them as approvers or
+ remove existing approvers that were set in the project's settings.
+1. If you want to change the number of required approvals, set a new number
+ in the **No. approvals required** box.
+1. Click **Update approvers**.
+
+There are however some restrictions:
+
+- The amount of required approvals, if changed, must be greater than the default
+ set at the project level. This ensures that you're not forced to adjust settings
+ when someone is unavailable for approval, yet the process is still enforced.
+
+NOTE: **Note:**
+If you are contributing to a forked project, things are a little different.
+Read what happens when the
+[source and target branches are not the same](#merge-requests-with-different-source-branch-and-target-branch-projects).
+
+## Overriding merge request approvals default settings **[PREMIUM]**
+
+In GitLab Premium, when the approval rules are [set at the project level](#editing-approvals-premium), and
+**Can override approvers and approvals required per merge request** is checked, there are a few more
+restrictions (compared to [GitLab Starter](#overriding-the-merge-request-approvals-default-settings)):
+
+- Approval rules can be added to an MR with no restriction.
+- For project sourced approval rules, editing and removing approvers is not allowed.
+- The approvals required of all approval rules is configurable, but if a rule is backed by a project rule, then it is restricted
+to the minimum approvals required set in the project's corresponding rule.
+
+## Resetting approvals on push
+
+If approvals are [set at the project level](#editing-approvals),
+you can choose whether all approvals on a merge request are removed when
+new commits are pushed to the source branch of the merge request:
+
+1. Navigate to your project's **Settings > General** and expand
+ **Merge request approvals**
+1. Tick the "Remove all approvals in a merge request when new commits are pushed to its source branch"
+ checkbox
+
+ ![Approvals remove on push](img/approvals_remove_on_push.png)
+
+1. Click **Save changes**
+
+NOTE: **Note:**
+Approvals do not get reset when [rebasing a merge request](fast_forward_merge.md)
+from the UI.
+However, approvals will be reset if the target branch is changed.
+
+If you want approvals to persist, independent of changes to the merge request,
+turn this setting to off by unchecking the box and saving the changes.
+
+## Allowing merge request authors to approve their own merge requests
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/3349) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.3.
+
+You can allow merge request authors to self-approve merge requests by
+enabling it [at the project level](#editing-approvals). Authors
+also need to be included in the approvers list in order to be able to
+approve their merge request.
+
+1. Navigate to your project's **Settings > General** and expand **Merge request approvals**.
+1. Uncheck the **Prevent approval of merge requests by merge request author** checkbox, which is enabled by default.
+1. Click **Save changes**.
+
+## Prevent approval of merge requests by their committers
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/10441) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.10.
+
+You can prevent users that have committed to a merge request from approving it by
+enabling [**Prevent approval of merge requests by their committers**](#prevent-approval-of-merge-requests-by-their-committers).
+
+1. Navigate to your project's **Settings > General** and expand **Merge request approvals**.
+1. Tick the checkbox **Prevent approval of merge requests by their committers**.
+1. Click **Save changes**.
+
+## Require authentication when approving a merge request **[STARTER]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5981) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.0.
+
+You can force the approver to enter a password in order to authenticate who is approving the merge request by
+enabling **Require user password to approve**. This enables an Electronic Signature
+for approvals such as the one defined by [CFR Part 11](https://www.accessdata.fda.gov/scripts/cdrh/cfdocs/cfcfr/CFRSearch.cfm?CFRPart=11&showFR=1&subpartNode=21:1.0.1.1.8.3)):
+
+1. Navigate to your project's **Settings > General** and expand **Merge request approvals**.
+1. Tick the checkbox **Require user password to approve**.
+1. Click **Save changes**.
+
+## Merge requests with different source branch and target branch projects
+
+If the merge request source branch and target branch belong to different
+projects (which happens in merge requests in forked projects), everything is
+with respect to the target branch's project (typically the original project).
+In particular, since the merge request in this case is part of the target
+branch's project, the relevant settings are the target project's. The source
+branch's project settings are not applicable. Even if you start the merge
+request from the source branch's project UI, pay attention to the created merge
+request itself. It belongs to the target branch's project.
+
+## Approver suggestions
+
+Approvers are suggested for merge requests based on the previous authors of the files affected by the merge request.
+
+## Filtering merge requests by approvers
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9468) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.9.
+
+To filter merge requests by an individual approver, you can type (or select from
+the dropdown) `approver` and select the user.
+
+![Filter MRs by an approver](img/filter_approver_merge_requests.png)
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md b/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
index 1477e35dca8..c93c7a5fe08 100644
--- a/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
+++ b/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
@@ -1,3 +1,7 @@
+---
+type: reference, concepts
+---
+
# Merge when pipeline succeeds
When reviewing a merge request that looks ready to merge but still has one or
@@ -7,6 +11,8 @@ finish and remember to merge the request manually.
![Enable](img/merge_when_pipeline_succeeds_enable.png)
+## How it works
+
When you hit the "Merge When Pipeline Succeeds" button, the status of the merge
request will be updated to represent the impending merge. If you cannot wait
for the pipeline to succeed and want to merge immediately, this option is
@@ -29,9 +35,6 @@ changes to be reviewed.
## Only allow merge requests to be merged if the pipeline succeeds
-> **Note:**
-You need to have jobs configured to enable this feature.
-
You can prevent merge requests from being merged if their pipeline did not succeed
or if there are discussions to be resolved.
@@ -39,9 +42,21 @@ Navigate to your project's settings page and expand the **Merge requests** secti
In the **Merge checks** subsection, select the **Pipelines must succeed** check
box and hit **Save** for the changes to take effect.
-![Pipelines must succeed settings](img/merge_when_pipeline_succeeds_only_if_succeeds_settings.png)
+![Pipelines must succeed settings](img/merge_when_pipeline_succeeds_only_if_succeeds_settings.png)
From now on, every time the pipeline fails you will not be able to merge the
merge request from the UI, until you make all relevant jobs pass.
![Only allow merge if pipeline succeeds message](img/merge_when_pipeline_succeeds_only_if_succeeds_msg.png)
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/project/merge_requests/resolve_conflicts.md b/doc/user/project/merge_requests/resolve_conflicts.md
index ccef2853e3f..6a0f2d18629 100644
--- a/doc/user/project/merge_requests/resolve_conflicts.md
+++ b/doc/user/project/merge_requests/resolve_conflicts.md
@@ -1,3 +1,7 @@
+---
+type: reference, concepts
+---
+
# Merge request conflict resolution
Merge conflicts occur when two branches have different changes that cannot be
@@ -66,3 +70,15 @@ Additionally, GitLab does not detect conflicts in renames away from a path. For
example, this will not create a conflict: on branch `a`, doing `git mv file1
file2`; on branch `b`, doing `git mv file1 file3`. Instead, both files will be
present in the branch after the merge request is merged.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/project/merge_requests/revert_changes.md b/doc/user/project/merge_requests/revert_changes.md
index b9102798a49..1cbbcf45400 100644
--- a/doc/user/project/merge_requests/revert_changes.md
+++ b/doc/user/project/merge_requests/revert_changes.md
@@ -1,11 +1,13 @@
-# Reverting changes
+---
+type: reference, concepts
+---
-> [Introduced][ce-1990] in GitLab 8.5.
+# Reverting changes
-GitLab implements Git's powerful feature to [revert any commit][git-revert]
-with introducing a **Revert** button in merge requests and commit details.
+You can use Git's powerful feature to [revert any commit](https://git-scm.com/docs/git-revert "Git revert documentation")
+by clicking the **Revert** button in merge requests and commit details.
-## Reverting a Merge Request
+## Reverting a merge request
NOTE: **Note:**
The **Revert** button will only be available for merge requests
@@ -30,9 +32,9 @@ create a new merge request with the revert changes.
After the merge request has been reverted, the **Revert** button will not be
available anymore.
-## Reverting a Commit
+## Reverting a commit
-You can revert a Commit from the Commit details page:
+You can revert a commit from the commit details page:
![Revert commit](img/cherry_pick_changes_commit.png)
@@ -54,5 +56,14 @@ mainline:
git revert -m 2 7a39eb0
```
-[ce-1990]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/1990 "Revert button Merge Request"
-[git-revert]: https://git-scm.com/docs/git-revert "Git revert documentation"
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/project/merge_requests/sast.md b/doc/user/project/merge_requests/sast.md
new file mode 100644
index 00000000000..165290eb114
--- /dev/null
+++ b/doc/user/project/merge_requests/sast.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../../application_security/sast/index.md'
+---
+
+This document was moved to [another location](../../application_security/sast/index.md).
diff --git a/doc/user/project/merge_requests/sast_docker.md b/doc/user/project/merge_requests/sast_docker.md
new file mode 100644
index 00000000000..a062731ea35
--- /dev/null
+++ b/doc/user/project/merge_requests/sast_docker.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../../application_security/container_scanning/index.md'
+---
+
+This document was moved to [another location](../../application_security/container_scanning/index.md).
diff --git a/doc/user/project/merge_requests/squash_and_merge.md b/doc/user/project/merge_requests/squash_and_merge.md
index 4ff8ec3a7e6..39fd2588811 100644
--- a/doc/user/project/merge_requests/squash_and_merge.md
+++ b/doc/user/project/merge_requests/squash_and_merge.md
@@ -1,8 +1,14 @@
+---
+type: reference, concepts
+---
+
# Squash and merge
-> [Introduced][ee-1024] in [GitLab Starter][ee] 8.17, and in [GitLab Core][ce] [11.0][ce-18956].
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1024) in [GitLab Starter](https://about.gitlab.com/pricing/) 8.17.
+> - [Ported](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18956) to GitLab Core 11.0.
-Combine all commits of your merge request into one and retain a clean history.
+With squash and merge you can combine all your merge request's commits into one
+and retain a clean history.
## Overview
@@ -12,11 +18,11 @@ and then merges that commit using the merge method set for the project.
In other words, squashing a merge request turns a long list of commits:
-![List of commits from a merge request][mr-commits]
+![List of commits from a merge request](img/squash_mr_commits.png)
Into a single commit on merge:
-![A squashed commit followed by a merge commit][squashed-commit]
+![A squashed commit followed by a merge commit](img/squash_squashed_commit.png)
The squashed commit's commit message will be either:
@@ -44,20 +50,18 @@ all you have to do is enable squashing before you press merge to join
the commits in the merge request into a single commit.
This way, the history of your base branch remains clean with
-meaningful commit messages and is simpler to [revert] if necessary.
+meaningful commit messages and is simpler to [revert](revert_changes.md) if necessary.
## Enabling squash for a merge request
Anyone who can create or edit a merge request can choose for it to be squashed
on the merge request form:
-![Squash commits checkbox on edit form][squash-edit-form]
-
----
+![Squash commits checkbox on edit form](img/squash_edit_form.png)
This can then be overridden at the time of accepting the merge request:
-![Squash commits checkbox on accept merge request form][squash-mr-widget]
+![Squash commits checkbox on accept merge request form](img/squash_mr_widget.png)
## Commit metadata for squashed commits
@@ -69,19 +73,20 @@ The squashed commit has the following metadata:
## Squash and fast-forward merge
-When a project has the [fast-forward merge setting enabled][ff-merge], the merge
+When a project has the [fast-forward merge setting enabled](fast_forward_merge.md#enabling-fast-forward-merges), the merge
request must be able to be fast-forwarded without squashing in order to squash
it. This is because squashing is only available when accepting a merge request,
so a merge request may need to be rebased before squashing, even though
squashing can itself be considered equivalent to rebasing.
-[ee-1024]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1024
-[ce-18956]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18956
-[mr-commits]: img/squash_mr_commits.png
-[squashed-commit]: img/squash_squashed_commit.png
-[squash-edit-form]: img/squash_edit_form.png
-[squash-mr-widget]: img/squash_mr_widget.png
-[ff-merge]: fast_forward_merge.md#enabling-fast-forward-merges
-[ce]: https://about.gitlab.com/pricing/
-[ee]: https://about.gitlab.com/pricing/
-[revert]: revert_changes.md
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/project/merge_requests/versions.md b/doc/user/project/merge_requests/versions.md
index 70bd1e60594..fbe216c3aed 100644
--- a/doc/user/project/merge_requests/versions.md
+++ b/doc/user/project/merge_requests/versions.md
@@ -1,13 +1,8 @@
-# Merge requests versions
+---
+type: reference, concepts
+---
-> **Notes:**
->
-> - [Introduced][ce-5467] in GitLab 8.12.
-> - Comments are disabled while viewing outdated merge versions or comparing to
-> versions other than base.
-> - Merge request versions are based on push not on commit. So, if you pushed 5
-> commits in a single push, it will be a single option in the dropdown. If you
-> pushed 5 times, that will count for 5 options.
+# Merge requests versions
Every time you push to a branch that is tied to a merge request, a new version
of merge request diff is created. When you visit a merge request that contains
@@ -16,25 +11,38 @@ request diffs.
![Merge request versions](img/versions.png)
----
+## Selecting a version
By default, the latest version of changes is shown. However, you
can select an older one from version dropdown.
![Merge request versions dropdown](img/versions_dropdown.png)
----
+Merge request versions are based on push not on commit. So, if you pushed 5
+commits in a single push, it will be a single option in the dropdown. If you
+pushed 5 times, that will count for 5 options.
You can also compare the merge request version with an older one to see what has
changed since then.
![Merge request versions compare](img/versions_compare.png)
----
+Comments are disabled while viewing outdated merge versions or comparing to
+versions other than base.
Every time you push new changes to the branch, a link to compare the last
changes appears as a system note.
![Merge request versions system note](img/versions_system_note.png)
-[ce-5467]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5467
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/project/merge_requests/work_in_progress_merge_requests.md b/doc/user/project/merge_requests/work_in_progress_merge_requests.md
index 6f33eb9a482..9cd868067bc 100644
--- a/doc/user/project/merge_requests/work_in_progress_merge_requests.md
+++ b/doc/user/project/merge_requests/work_in_progress_merge_requests.md
@@ -1,4 +1,8 @@
-# "Work In Progress" Merge Requests
+---
+type: reference, concepts
+---
+
+# "Work In Progress" merge requests
If a merge request is not yet ready to be merged, perhaps due to continued development
or open discussions, you can prevent it from being accepted before it's ready by flagging
@@ -7,7 +11,7 @@ being merged, and it will stay disabled until the "WIP" flag has been removed.
![Blocked Accept Button](img/wip_blocked_accept_button.png)
-## Adding the "Work In Progress" flag to a Merge Request
+## Adding the "Work In Progress" flag to a merge request
There are several ways to flag a merge request as a Work In Progress:
@@ -21,7 +25,7 @@ There are several ways to flag a merge request as a Work In Progress:
source branch. This is not a toggle, and doing it again in another commit will have
no effect.
-## Removing the "Work In Progress" flag from a Merge Request
+## Removing the "Work In Progress" flag from a merge request
Similar to above, when a Merge Request is ready to be merged, you can remove the
"Work in Progress" flag in several ways:
@@ -37,10 +41,22 @@ Similar to above, when a Merge Request is ready to be merged, you can remove the
Must have at least Developer level permissions on the project for the button to
be visible.
-## Including/Excluding WIP Merge Requests when searching
+## Including/excluding WIP merge requests when searching
When viewing/searching the merge requests list, you can choose to include or exclude
WIP merge requests by adding a "WIP" filter in the search box, and choosing "Yes"
(to include) or "No" (to exclude).
![Filter WIP MRs](img/filter_wip_merge_requests.png)
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/project/milestones/burndown_charts.md b/doc/user/project/milestones/burndown_charts.md
new file mode 100644
index 00000000000..7ffeb032d7f
--- /dev/null
+++ b/doc/user/project/milestones/burndown_charts.md
@@ -0,0 +1,70 @@
+# Burndown Charts **[STARTER]**
+
+> **Notes:**
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1540) in [GitLab Starter](https://about.gitlab.com/pricing/) 9.1 for project milestones.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/5354) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.8 for group milestones.
+> - [Added](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/6495) to [GitLab Starter](https://about.gitlab.com/pricing/) 11.2 for group milestones.
+> - Closed or reopened issues prior to GitLab 9.1 won't have a `closed_at`
+> value, so the burndown chart considers them as closed on the milestone
+> `start_date`. In that case, a warning will be displayed.
+
+## Overview
+
+Burndown Charts are visual representations of the progress of completing a milestone.
+
+![burndown chart](img/burndown_chart.png)
+
+At a glance, you see the current state for the completion a given milestone.
+Without them, you would have to organize the data from the milestone and plot it
+yourself to have the same sense of progress.
+
+GitLab Starter plots it for you and presents it in a clear and beautiful chart.
+
+For an overview, check the video demonstration on [Mapping Work Versus Time, With Burndown Charts](https://about.gitlab.com/2017/04/25/mapping-work-to-do-versus-time-with-burndown-charts/).
+
+## Use cases
+
+Burndown Charts, in general, are used for tracking and analyzing the completion of
+a milestone. Therefore, their use cases are tied to the
+[use you are assigning your milestone to](index.md).
+
+To exemplify, suppose you lead a team of developers in a large company,
+and you follow this workflow:
+
+- Your company set the goal for the quarter to deliver 10 new features for your app
+ in the upcoming major release.
+- You create a milestone, and remind your team to assign that milestone to every new issue
+ and merge request that's part of the launch of your app.
+- Every week, you open the milestone, visualize the progress, identify the gaps,
+ and help your team to get their work done.
+- Every month, you check in with your supervisor, and show the progress of that milestone
+ from the Burndown Chart.
+- By the end of the quarter, your team successfully delivered 100% of that milestone, as
+ it was taken care of closely throughout the whole quarter.
+
+## How it works
+
+A Burndown Chart is available for every project or group milestone that has been attributed a **start
+date** and a **due date**.
+
+Find your project's **Burndown Chart** under **Project > Issues > Milestones**,
+and select a milestone from your current ones, while for group's, access the **Groups** dashboard,
+select a group, and go through **Issues > Milestones** on the sidebar.
+
+NOTE: **Note:**
+You're able to [promote project](index.md#promoting-project-milestones-to-group-milestones) to group milestones and still see the **Burndown Chart** for them, respecting license limitations.
+
+The chart indicates the project's progress throughout that milestone (for issues assigned to it).
+
+In particular, it shows how many issues were or are still open for a given day in the
+milestone's corresponding period.
+
+The Burndown Chart tracks when issues were created and when they were last closed—not their full history. For each day, it takes the number of issues still open and issues created that day and subtracts the number of issues closed that day.
+**Issues that were created and assigned a milestone before its start date—and remain open as of the start date—are considered as having been opened on the start date**. Therefore, when the milestone start date is changed the number of opened issues on each day may change.
+Reopened issues are
+considered as having been opened on the day after they were last closed.
+
+The Burndown Chart can also be toggled to display the cumulative open issue
+weight for a given day. When using this feature, make sure issue weights have
+been properly assigned, since an open issue with no weight adds zero to the
+cumulative value.
diff --git a/doc/user/project/milestones/img/burndown_chart.png b/doc/user/project/milestones/img/burndown_chart.png
new file mode 100644
index 00000000000..e06b24f9907
--- /dev/null
+++ b/doc/user/project/milestones/img/burndown_chart.png
Binary files differ
diff --git a/doc/user/project/milestones/index.md b/doc/user/project/milestones/index.md
index a7d6144e3ec..6cd866b5c0d 100644
--- a/doc/user/project/milestones/index.md
+++ b/doc/user/project/milestones/index.md
@@ -83,7 +83,10 @@ From the project issue/merge request list pages and the group issue/merge reques
### Filtering in issue boards
-From [project issue boards](../issue_board.md), you can filter by both group milestones and project milestones in the [search and filter bar](../../search/index.md#issue-boards).
+- From [project issue boards](../issue_board.md), you can filter by both group milestones and project milestones in the [search and filter bar](../../search/index.md#issue-boards).
+- From [group issue boards](../issue_board.md#group-issue-boards-premium), you can filter by only group milestones in the [search and filter bar](../../search/index.md#issue-boards). **[PREMIUM]**
+- From [project issue boards](../issue_board.md), you can filter by both group milestones and project milestones in the [issue board configuration](../issue_board.md#configurable-issue-boards-starter). **[STARTER]**
+- From [group issue boards](../issue_board.md#group-issue-boards-premium) you can filter by only group milestones in the [issue board configuration](../issue_board.md#configurable-issue-boards-starter). **[STARTER]**
### Special milestone filters
@@ -98,16 +101,17 @@ When filtering by milestone, in addition to choosing a specific project mileston
Not all features in the project milestone view are available in the group milestone view. This table summarizes the differences:
-| Feature | Project milestone view | Group milestone view |
-|---|:---:|:---:|
-| Title an description | ✓ | ✓ |
-| Issues assigned to milestone | ✓ | |
-| Merge requests assigned to milestone | ✓ | |
-| Participants and labels used | ✓ | |
-| Percentage complete | ✓ | ✓ |
-| Start date and due date | ✓ | ✓ |
-| Total issue time spent | ✓ | ✓ |
-| Total issue weight | ✓ | |
+| Feature | Project milestone view | Group milestone view |
+|--------------------------------------|:----------------------:|:--------------------:|
+| Title an description | ✓ | ✓ |
+| Issues assigned to milestone | ✓ | |
+| Merge requests assigned to milestone | ✓ | |
+| Participants and labels used | ✓ | |
+| Percentage complete | ✓ | ✓ |
+| Start date and due date | ✓ | ✓ |
+| Total issue time spent | ✓ | ✓ |
+| Total issue weight | ✓ | |
+| Burndown chart **[STARTER}** | ✓ | ✓ |
The milestone view shows the title and description.
@@ -118,12 +122,23 @@ These features are only available for project milestones and not group milestone
- Issues assigned to the milestone are displayed in three columns: Unstarted issues, ongoing issues, and completed issues.
- Merge requests assigned to the milestone are displayed in four columns: Work in progress merge requests, waiting for merge, rejected, and closed.
- Participants and labels that are used in issues and merge requests that have the milestone assigned are displayed.
+- [Burndown chart](#project-burndown-charts-starter).
+
+### Project Burndown Charts **[STARTER]**
+
+For project milestones in [GitLab Starter](https://about.gitlab.com/pricing), a [burndown chart](burndown_charts.md) is in the milestone view, showing the progress of completing a milestone.
+
+![burndown chart](img/burndown_chart.png)
+
+### Group Burndown Charts **[PREMIUM]**
+
+For group milestones in [GitLab Premium](https://about.gitlab.com/pricing), a [burndown chart](burndown_charts.md) is in the milestone view, showing the progress of completing a milestone.
### Milestone sidebar
The milestone sidebar on the milestone view shows the following:
-- Percentage complete, which is calculated as number of closed issues plus number of closed/merged merge requests divided by total number issues and merge requests.
+- Percentage complete, which is calculated as number of closed issues divided by total number of issues.
- The start date and due date.
- The total time spent on all issues that have the milestone assigned.
diff --git a/doc/user/project/new_ci_build_permissions_model.md b/doc/user/project/new_ci_build_permissions_model.md
index 6c3fa5eb463..c07c4099f22 100644
--- a/doc/user/project/new_ci_build_permissions_model.md
+++ b/doc/user/project/new_ci_build_permissions_model.md
@@ -28,10 +28,10 @@ The reasons to do it like that are:
and maximizing security.
With the new behavior, any job that is triggered by the user, is also marked
-with their permissions. When a user does a `git push` or changes files through
+with their read permissions. When a user does a `git push` or changes files through
the web UI, a new pipeline will be usually created. This pipeline will be marked
as created be the pusher (local push or via the UI) and any job created in this
-pipeline will have the permissions of the pusher.
+pipeline will have the read permissions of the pusher but not write permissions.
This allows us to make it really easy to evaluate the access for all projects
that have [Git submodules][gitsub] or are using container images that the pusher
@@ -44,14 +44,14 @@ It is important to note that we have a few types of users:
- **Administrators**: CI jobs created by Administrators will not have access
to all GitLab projects, but only to projects and container images of projects
- that the administrator is a member of.That means that if a project is either
+ that the administrator is a member of. That means that if a project is either
public or internal users have access anyway, but if a project is private, the
Administrator will have to be a member of it in order to have access to it
via another project's job.
- **External users**: CI jobs created by [external users](../permissions.md#external-users-permissions) will have
access only to projects to which user has at least reporter access. This
- rules out accessing all internal projects by default,
+ rules out accessing all internal projects by default.
This allows us to make the CI and permission system more trustworthy.
Let's consider the following scenario:
@@ -67,9 +67,10 @@ Let's consider the following scenario:
## Job token
-A unique job token is generated for each job and it allows the user to
+A unique job token is generated for each job and provides the user read
access all projects that would be normally accessible to the user creating that
-job.
+job. The unique job token does not have any write permissions, but there
+is a [proposal to add support](https://gitlab.com/gitlab-org/gitlab-ce/issues/18106).
We try to make sure that this token doesn't leak by:
diff --git a/doc/user/project/operations/feature_flags.md b/doc/user/project/operations/feature_flags.md
new file mode 100644
index 00000000000..a5db3d70bb9
--- /dev/null
+++ b/doc/user/project/operations/feature_flags.md
@@ -0,0 +1,177 @@
+# Feature Flags **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11845) in GitLab 11.4.
+
+CAUTION: **Warning:**
+This an _alpha_ feature and is subject to change at any time without
+prior notice.
+
+Feature flags allow you to ship a project in different flavors by
+dynamically toggling certain functionality.
+
+## Overview
+
+Feature Flags offer a feature toggle system for your application. They enable teams
+to achieve Continuous Delivery by deploying new features to production at smaller
+batches for controlled testing, separating feature delivery from customer launch.
+This helps reducing risk and allows you to easily manage which features to enable.
+
+GitLab offers a Feature Flags interface that allows you to create, toggle and
+remove feature flags.
+
+## How it works
+
+Underneath, GitLab uses [unleash](https://github.com/Unleash/unleash), a feature
+toggle service. GitLab provides an API where your application can talk to and get the
+list of feature flags you set in GitLab.
+
+The application must be configured to talk to GitLab, so that's up to the
+developers to use a compatible [client library](#client-libraries) and
+integrate it in their app.
+
+By setting a flag active or inactive via GitLab, your application will automatically
+know which features to enable or disable respectively.
+
+## Adding a new feature flag
+
+To add a new feature flag:
+
+1. Navigate to your project's **Operations > Feature Flags**.
+1. Click on the **New Feature Flag** button.
+1. Give it a name.
+
+ NOTE: **Note:**
+ A name can contain only lowercase letters, digits, underscores (`_`)
+ and dashes (`-`), must start with a letter, and cannot end with a dash (`-`)
+ or an underscore (`_`).
+
+1. Give it a description (optional, 255 characters max).
+1. Define environment [specs](#define-environment-specs). If you want the flag on by default, enable the catch-all [wildcard spec (`*`)](#define-environment-specs)
+1. Click **Create feature flag**.
+
+Once a feature flag is created, the list of existing feature flags will be presented
+with ability to edit or remove them.
+
+To make a feature flag active or inactive, click the pencil icon to edit it,
+and toggle the status for each [spec](#define-environment-specs).
+
+![Feature flags list](img/feature_flags_list.png)
+
+## Define environment specs
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/8621) in GitLab 11.8.
+
+In general, an application is deployed to multiple environments, such as
+production, staging and [review apps](../../../ci/review_apps/index.md).
+For example, you may not want to enable a feature flag on production until your QA team has
+first confirmed that the feature is working correctly on testing environments.
+
+To handle these situations, you can enable a feature flag on a particular environment
+with [Environment specs](../../../ci/environments.md#scoping-environments-with-specs-premium).
+You can define multiple specs per flag so that you can control your feature flag more granularly.
+
+To define specs for each environment:
+
+1. Navigate to your project's **Operations > Feature Flags**.
+1. Click on the **New Feature Flag** button or edit an existing flag.
+1. Set the status of the default [spec](../../../ci/environments.md#scoping-environments-with-specs-premium) (`*`). This status will be used for _all_ environments.
+1. If you want to enable/disable the feature on a specific environment, create a new [spec](../../../ci/environments.md#scoping-environments-with-specs-premium) and type the environment name.
+1. Set the status of the additional spec. This status takes precedence over the default spec's status since we always use the most specific match available.
+1. Click **Create feature flag** or **Update feature flag**.
+
+![Feature flag specs list](img/specs_list.png)
+
+NOTE: **NOTE**
+We'd highly recommend you to use the [Environment](../../../ci/environments.md)
+feature in order to quickly assess which flag is enabled per environment.
+
+## Integrating with your application
+
+In order to use Feature Flags, you need to first
+[get the access credentials](#configuring-feature-flags) from GitLab and then
+prepare your application and hook it with a [client library](#client-libraries).
+
+### Configuring Feature Flags
+
+To get the access credentials that your application will need to talk to GitLab:
+
+1. Navigate to your project's **Operations > Feature Flags**.
+1. Click on the **Configure** button to see the values:
+ - **API URL**: URL where the client (application) connects to get a list of feature flags.
+ - **Instance ID**: Unique token that authorizes the retrieval of the feature flags.
+ - **Application name**: The name of the running environment. For instance,
+ if the application runs for production server, application name would be
+ `production` or similar. This value is used for
+ [the environment spec evaluation](#define-environment-specs).
+
+NOTE: **Note:**
+The meaning of these fields might change over time. For example, we are not sure
+if **Instance ID** will be single token or multiple tokens, assigned to the
+**Environment**. Also, **Application name** could describe the version of
+application instead of the running environment.
+
+### Client libraries
+
+GitLab currently implements a single backend that is compatible with
+[Unleash](https://github.com/Unleash/unleash#client-implementations) clients.
+
+Unleash clients allow the developers to define in the app's code the default
+values for flags. Each feature flag evaluation can express the desired
+outcome in case the flag isn't present on the provided configuration file.
+
+Unleash currently offers a number of official SDKs for various frameworks and
+a number of community contributed libraries.
+
+Official clients:
+
+- [unleash/unleash-client-java](https://github.com/unleash/unleash-client-java)
+- [unleash/unleash-client-node](https://github.com/unleash/unleash-client-node)
+- [unleash/unleash-client-go](https://github.com/unleash/unleash-client-go)
+- [unleash/unleash-client-ruby](https://github.com/unleash/unleash-client-ruby)
+
+Community contributed clients:
+
+- [stiano/unleash-client-dotnet](https://github.com/stiano/unleash-client-dotnet) (.Net Core)
+- [onybo/unleash-client-core](https://github.com/onybo/unleash-client-core) (.Net Core)
+- [aes/unleash-client-python](https://github.com/aes/unleash-client-python) (Python 3)
+
+### Golang application example
+
+Here's an example of how to integrate the feature flags in a Golang application:
+
+```golang
+package main
+
+import (
+ "io"
+ "log"
+ "net/http"
+
+ "github.com/Unleash/unleash-client-go"
+)
+
+type metricsInterface struct {
+}
+
+func init() {
+ unleash.Initialize(
+ unleash.WithUrl("https://gitlab.com/api/v4/feature_flags/unleash/42"),
+ unleash.WithInstanceId("29QmjsW6KngPR5JNPMWx"),
+ unleash.WithAppName("production"),
+ unleash.WithListener(&metricsInterface{}),
+ )
+}
+
+func helloServer(w http.ResponseWriter, req *http.Request) {
+ if unleash.IsEnabled("my_feature_name") {
+ io.WriteString(w, "Feature enabled\n")
+ } else {
+ io.WriteString(w, "hello, world!\n")
+ }
+}
+
+func main() {
+ http.HandleFunc("/", helloServer)
+ log.Fatal(http.ListenAndServe(":8080", nil))
+}
+```
diff --git a/doc/user/project/operations/img/external_dashboard_link.png b/doc/user/project/operations/img/external_dashboard_link.png
new file mode 100644
index 00000000000..4fb8bce7cd0
--- /dev/null
+++ b/doc/user/project/operations/img/external_dashboard_link.png
Binary files differ
diff --git a/doc/user/project/operations/img/external_dashboard_settings.png b/doc/user/project/operations/img/external_dashboard_settings.png
new file mode 100644
index 00000000000..8dc380f01e2
--- /dev/null
+++ b/doc/user/project/operations/img/external_dashboard_settings.png
Binary files differ
diff --git a/doc/user/project/operations/img/feature_flags_list.png b/doc/user/project/operations/img/feature_flags_list.png
new file mode 100644
index 00000000000..5313a163fec
--- /dev/null
+++ b/doc/user/project/operations/img/feature_flags_list.png
Binary files differ
diff --git a/doc/user/project/operations/img/specs_list.png b/doc/user/project/operations/img/specs_list.png
new file mode 100644
index 00000000000..9630c907cfc
--- /dev/null
+++ b/doc/user/project/operations/img/specs_list.png
Binary files differ
diff --git a/doc/user/project/operations/index.md b/doc/user/project/operations/index.md
index b0f9936be5c..84711d1146f 100644
--- a/doc/user/project/operations/index.md
+++ b/doc/user/project/operations/index.md
@@ -7,5 +7,6 @@ your applications:
- Deploy to different [environments](../../../ci/environments.md).
- Connect your project to a [Kubernetes cluster](../clusters/index.md).
- Discover and view errors generated by your applications with [Error Tracking](error_tracking.md).
-- Create, toggle, and remove [Feature Flags](https://docs.gitlab.com/ee/user/project/operations/feature_flags.html). **[PREMIUM]**
-- [Trace](https://docs.gitlab.com/ee/user/project/operations/tracing.html) the performance and health of a deployed application. **[ULTIMATE]**
+- Create, toggle, and remove [Feature Flags](feature_flags.md). **[PREMIUM]**
+- [Trace](tracing.md) the performance and health of a deployed application. **[ULTIMATE]**
+- Add a [button to the Monitoring dashboard](linking_to_an_external_dashboard.md) linking directly to your existing external dashboards.
diff --git a/doc/user/project/operations/linking_to_an_external_dashboard.md b/doc/user/project/operations/linking_to_an_external_dashboard.md
new file mode 100644
index 00000000000..0371a40a217
--- /dev/null
+++ b/doc/user/project/operations/linking_to_an_external_dashboard.md
@@ -0,0 +1,19 @@
+# Linking to an external dashboard
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/57171) in GitLab 12.0.
+
+You can add a button to the Monitoring dashboard linking directly to your existing external dashboards.
+
+## Enabling the external dashboard link
+
+1. Go to **Settings > Operations** and scroll to the section titled **External dashboard**.
+
+1. Fill in the URL to your external dashboard and click **Save changes**.
+
+ ![External Dashboard Settings](img/external_dashboard_settings.png)
+
+1. There should now be a button on your
+ [Monitoring dashboard](../../../ci/environments.md#monitoring-environments) which
+ will open the URL you entered in the above step.
+
+ ![External Dashboard Link](img/external_dashboard_link.png)
diff --git a/doc/user/project/operations/tracing.md b/doc/user/project/operations/tracing.md
new file mode 100644
index 00000000000..0416e096cf2
--- /dev/null
+++ b/doc/user/project/operations/tracing.md
@@ -0,0 +1,34 @@
+# Tracing **[ULTIMATE]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/7903) in GitLab Ultimate 11.5.
+
+Tracing provides insight into the performance and health of a deployed application,
+tracking each function or microservice which handles a given request.
+
+This makes it easy to
+understand the end-to-end flow of a request, regardless of whether you are using a monolithic or distributed system.
+
+## Jaeger tracing
+
+[Jaeger](https://www.jaegertracing.io/) is an open source, end-to-end distributed
+tracing system used for monitoring and troubleshooting microservices-based distributed
+systems.
+
+### Deploying Jaeger
+
+To learn more about deploying Jaeger, read the official
+[Getting Started documentation](https://www.jaegertracing.io/docs/latest/getting-started/).
+There is an easy to use [all-in-one Docker image](https://www.jaegertracing.io/docs/latest/getting-started/#AllinoneDockerimage),
+as well as deployment options for [Kubernetes](https://github.com/jaegertracing/jaeger-kubernetes)
+and [OpenShift](https://github.com/jaegertracing/jaeger-openshift).
+
+### Enabling Jaeger
+
+GitLab provides an easy way to open the Jaeger UI from within your project:
+
+1. [Set up Jaeger](#deploying-jaeger) and configure your application using one of the
+ [client libraries](https://www.jaegertracing.io/docs/latest/client-libraries/).
+1. Navigate to your project's **Settings > Operations** and provide the Jaeger URL.
+1. Click **Save changes** for the changes to take effect.
+1. You can now visit **Operations > Tracing** in your project's sidebar and
+ GitLab will redirect you to the configured Jaeger URL. \ No newline at end of file
diff --git a/doc/user/project/packages/img/maven_package_view.png b/doc/user/project/packages/img/maven_package_view.png
new file mode 100644
index 00000000000..2eb4b6f76b4
--- /dev/null
+++ b/doc/user/project/packages/img/maven_package_view.png
Binary files differ
diff --git a/doc/user/project/packages/img/npm_package_view.png b/doc/user/project/packages/img/npm_package_view.png
new file mode 100644
index 00000000000..8baf7d0ef9f
--- /dev/null
+++ b/doc/user/project/packages/img/npm_package_view.png
Binary files differ
diff --git a/doc/user/project/packages/maven.md b/doc/user/project/packages/maven.md
new file mode 100644
index 00000000000..266225fdb8d
--- /dev/null
+++ b/doc/user/project/packages/maven.md
@@ -0,0 +1,5 @@
+---
+redirect_to: 'maven_repository.md'
+---
+
+This document was moved to [another location](maven_repository.md).
diff --git a/doc/user/project/packages/maven_packages.md b/doc/user/project/packages/maven_packages.md
new file mode 100644
index 00000000000..266225fdb8d
--- /dev/null
+++ b/doc/user/project/packages/maven_packages.md
@@ -0,0 +1,5 @@
+---
+redirect_to: 'maven_repository.md'
+---
+
+This document was moved to [another location](maven_repository.md).
diff --git a/doc/user/project/packages/maven_repository.md b/doc/user/project/packages/maven_repository.md
new file mode 100644
index 00000000000..9b7af738696
--- /dev/null
+++ b/doc/user/project/packages/maven_repository.md
@@ -0,0 +1,341 @@
+# GitLab Maven Repository **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5811) in
+ [GitLab Premium](https://about.gitlab.com/pricing/) 11.3.
+
+With the GitLab [Maven](https://maven.apache.org) Repository, every
+project can have its own space to store its Maven artifacts.
+
+![GitLab Maven Repository](img/maven_package_view.png)
+
+## Enabling the Maven Repository
+
+NOTE: **Note:**
+This option is available only if your GitLab administrator has
+[enabled support for the Maven repository](../../../administration/packages.md).**[PREMIUM ONLY]**
+
+After the Packages feature is enabled, the Maven Repository will be available for
+all new projects by default. To enable it for existing projects, or if you want
+to disable it:
+
+1. Navigate to your project's **Settings > General > Permissions**.
+1. Find the Packages feature and enable or disable it.
+1. Click on **Save changes** for the changes to take effect.
+
+You should then be able to see the **Packages** section on the left sidebar.
+Next, you must configure your project to authorize with the GitLab Maven
+repository.
+
+## Authenticating to the GitLab Maven Repository
+
+If a project is private or you want to upload Maven artifacts to GitLab,
+credentials will need to be provided for authorization. Support is available for
+[personal access tokens](#authenticating-with-a-personal-access-token) and
+[CI job tokens](#authenticating-with-a-ci-job-token) only.
+[Deploy tokens](../deploy_tokens/index.md) and regular username/password
+credentials do not work.
+
+### Authenticating with a personal access token
+
+To authenticate with a [personal access token](../../profile/personal_access_tokens.md),
+add a corresponding section to your
+[`settings.xml`](https://maven.apache.org/settings.html) file:
+
+```xml
+<settings>
+ <servers>
+ <server>
+ <id>gitlab-maven</id>
+ <configuration>
+ <httpHeaders>
+ <property>
+ <name>Private-Token</name>
+ <value>REPLACE_WITH_YOUR_PERSONAL_ACCESS_TOKEN</value>
+ </property>
+ </httpHeaders>
+ </configuration>
+ </server>
+ </servers>
+</settings>
+```
+
+You should now be able to upload Maven artifacts to your project.
+
+### Authenticating with a CI job token
+
+If you're using Maven with GitLab CI/CD, a CI job token can be used instead
+of a personal access token.
+
+To authenticate with a CI job token, add a corresponding section to your
+[`settings.xml`](https://maven.apache.org/settings.html) file:
+
+```xml
+<settings>
+ <servers>
+ <server>
+ <id>gitlab-maven</id>
+ <configuration>
+ <httpHeaders>
+ <property>
+ <name>Job-Token</name>
+ <value>${env.CI_JOB_TOKEN}</value>
+ </property>
+ </httpHeaders>
+ </configuration>
+ </server>
+ </servers>
+</settings>
+```
+
+You can read more on
+[how to create Maven packages using GitLab CI/CD](#creating-maven-packages-with-gitlab-cicd).
+
+## Configuring your project to use the GitLab Maven repository URL
+
+To download and upload packages from GitLab, you need a `repository` and
+`distributionManagement` section in your `pom.xml` file.
+
+Depending on your workflow and the amount of Maven packages you have, there are
+3 ways you can configure your project to use the GitLab endpoint for Maven packages:
+
+- **Project level**: Useful when you have few Maven packages which are not under
+ the same GitLab group.
+- **Group level**: Useful when you have many Maven packages under the same GitLab
+ group.
+- **Instance level**: Useful when you have many Maven packages under different
+ GitLab groups or on their own namespace.
+
+NOTE: **Note:**
+In all cases, you need a project specific URL for uploading a package in
+the `distributionManagement` section.
+
+### Project level Maven endpoint
+
+The example below shows how the relevant `repository` section of your `pom.xml`
+would look like:
+
+```xml
+<repositories>
+ <repository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ </repository>
+</repositories>
+<distributionManagement>
+ <repository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ </repository>
+ <snapshotRepository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ </snapshotRepository>
+</distributionManagement>
+```
+
+The `id` must be the same with what you
+[defined in `settings.xml`](#authenticating-to-the-gitlab-maven-repository).
+
+Replace `PROJECT_ID` with your project ID which can be found on the home page
+of your project.
+
+If you have a self-hosted GitLab installation, replace `gitlab.com` with your
+domain name.
+
+NOTE: **Note:**
+For retrieving artifacts, you can use either the
+[URL encoded](../../../api/README.md#namespaced-path-encoding) path of the project
+(e.g., `group%2Fproject`) or the project's ID (e.g., `42`). However, only the
+project's ID can be used for uploading.
+
+### Group level Maven endpoint
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8798) in GitLab Premium 11.7.
+
+If you rely on many packages, it might be inefficient to include the `repository` section
+with a unique URL for each package. Instead, you can use the group level endpoint for
+all your Maven packages stored within one GitLab group. Only packages you have access to
+will be available for download.
+
+The group level endpoint works with any package names, which means the you
+have the flexibility of naming compared to [instance level endpoint](#instance-level-maven-endpoint).
+However, GitLab will not guarantee the uniqueness of the package names within
+the group. You can have two projects with the same package name and package
+version. As a result, GitLab will serve whichever one is more recent.
+
+The example below shows how the relevant `repository` section of your `pom.xml`
+would look like. You still need a project specific URL for uploading a package in
+the `distributionManagement` section:
+
+```xml
+<repositories>
+ <repository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/groups/my-group/-/packages/maven</url>
+ </repository>
+</repositories>
+<distributionManagement>
+ <repository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ </repository>
+ <snapshotRepository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ </snapshotRepository>
+</distributionManagement>
+```
+
+The `id` must be the same with what you
+[defined in `settings.xml`](#authenticating-to-the-gitlab-maven-repository).
+
+Replace `my-group` with your group name and `PROJECT_ID` with your project ID
+which can be found on the home page of your project.
+
+If you have a self-hosted GitLab installation, replace `gitlab.com` with your
+domain name.
+
+NOTE: **Note:**
+For retrieving artifacts, you can use either the
+[URL encoded](../../../api/README.md#namespaced-path-encoding) path of the group
+(e.g., `group%2Fsubgroup`) or the group's ID (e.g., `12`).
+
+### Instance level Maven endpoint
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8274) in GitLab Premium 11.7.
+
+If you rely on many packages, it might be inefficient to include the `repository` section
+with a unique URL for each package. Instead, you can use the instance level endpoint for
+all maven packages stored in GitLab and the packages you have access to will be available
+for download.
+
+Note that **only packages that have the same path as the project** are exposed via
+the instance level endpoint.
+
+| Project | Package | Instance level endpoint available |
+| ------- | ------- | --------------------------------- |
+| `foo/bar` | `foo/bar/1.0-SNAPSHOT` | Yes |
+| `gitlab-org/gitlab-ce` | `foo/bar/1.0-SNAPSHOT` | No |
+| `gitlab-org/gitlab-ce` | `gitlab-org/gitlab-ce/1.0-SNAPSHOT` | Yes |
+
+The example below shows how the relevant `repository` section of your `pom.xml`
+would look like. You still need a project specific URL for uploading a package in
+the `distributionManagement` section:
+
+```xml
+<repositories>
+ <repository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/packages/maven</url>
+ </repository>
+</repositories>
+<distributionManagement>
+ <repository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ </repository>
+ <snapshotRepository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ </snapshotRepository>
+</distributionManagement>
+```
+
+The `id` must be the same with what you
+[defined in `settings.xml`](#authenticating-to-the-gitlab-maven-repository).
+
+Replace `PROJECT_ID` with your project ID which can be found on the home page
+of your project.
+
+If you have a self-hosted GitLab installation, replace `gitlab.com` with your
+domain name.
+
+NOTE: **Note:**
+For retrieving artifacts, you can use either the
+[URL encoded](../../../api/README.md#namespaced-path-encoding) path of the project
+(e.g., `group%2Fproject`) or the project's ID (e.g., `42`). However, only the
+project's ID can be used for uploading.
+
+## Uploading packages
+
+Once you have set up the [authentication](#authenticating-to-the-gitlab-maven-repository)
+and [configuration](#configuring-your-project-to-use-the-gitlab-maven-repository-url),
+test to upload a Maven artifact from a project of yours:
+
+```sh
+mvn deploy
+```
+
+You can then navigate to your project's **Packages** page and see the uploaded
+artifacts or even delete them.
+
+## Creating Maven packages with GitLab CI/CD
+
+Once you have your repository configured to use the GitLab Maven Repository,
+you can configure GitLab CI/CD to build new packages automatically. The example below
+shows how to create a new package each time the `master` branch is updated:
+
+1. Create a `ci_settings.xml` file that will serve as Maven's `settings.xml` file.
+ Add the server section with the same id you defined in your `pom.xml` file.
+ For example, in our case it's `gitlab-maven`:
+
+ ```xml
+ <settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
+ <servers>
+ <server>
+ <id>gitlab-maven</id>
+ <configuration>
+ <httpHeaders>
+ <property>
+ <name>Job-Token</name>
+ <value>${env.CI_JOB_TOKEN}</value>
+ </property>
+ </httpHeaders>
+ </configuration>
+ </server>
+ </servers>
+ </settings>
+ ```
+
+1. Make sure your `pom.xml` file includes the following:
+
+ ```xml
+ <repositories>
+ <repository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url>
+ </repository>
+ </repositories>
+ <distributionManagement>
+ <repository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url>
+ </repository>
+ <snapshotRepository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url>
+ </snapshotRepository>
+ </distributionManagement>
+ ```
+
+ TIP: **Tip:**
+ You can either let Maven utilize the CI environment variables or hardcode your project's ID.
+
+1. Add a `deploy` job to your `.gitlab-ci.yml` file:
+
+ ```yaml
+ deploy:
+ image: maven:3.3.9-jdk-8
+ script:
+ - 'mvn deploy -s ci_settings.xml'
+ only:
+ - master
+ ```
+
+1. Push those files to your repository.
+
+The next time the `deploy` job runs, it will copy `ci_settings.xml` to the
+user's home location (in this case the user is `root` since it runs in a
+Docker container), and Maven will utilize the configured CI
+[environment variables](../../../ci/variables/README.md#predefined-environment-variables).
diff --git a/doc/user/project/packages/npm_registry.md b/doc/user/project/packages/npm_registry.md
new file mode 100644
index 00000000000..2e274573434
--- /dev/null
+++ b/doc/user/project/packages/npm_registry.md
@@ -0,0 +1,120 @@
+# GitLab NPM Registry **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5934)
+ in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7.
+
+With the GitLab NPM Registry, every
+project can have its own space to store NPM packages.
+
+![GitLab NPM Registry](img/npm_package_view.png)
+
+NOTE: **Note:**
+Only [scoped](https://docs.npmjs.com/misc/scope) packages are supported.
+
+
+NOTE: **Note:**
+As `@group/subgroup/project` is not a valid NPM package name, publishing a package
+within a subgroup is not supported yet.
+
+## Enabling the NPM Registry
+
+NOTE: **Note:**
+This option is available only if your GitLab administrator has
+[enabled support for the NPM registry](../../../administration/packages.md).**[PREMIUM ONLY]**
+
+After the NPM registry is enabled, it will be available for all new projects
+by default. To enable it for existing projects, or if you want to disable it:
+
+1. Navigate to your project's **Settings > General > Permissions**.
+1. Find the Packages feature and enable or disable it.
+1. Click on **Save changes** for the changes to take effect.
+
+You should then be able to see the **Packages** section on the left sidebar.
+
+Before proceeding to authenticating with the GitLab NPM Registry, you should
+get familiar with the package naming convention.
+
+## Package naming convention
+
+**Only packages that have the same path as the project** are supported. For
+ example:
+
+| Project | Package | Supported |
+| ---------------------- | ----------------------- | --------- |
+| `foo/bar` | `@foo/bar` | Yes |
+| `gitlab-org/gitlab-ce` | `@gitlab-org/gitlab-ce` | Yes |
+| `gitlab-org/gitlab-ce` | `@foo/bar` | No |
+
+Now, you can configure your project to authenticate with the GitLab NPM
+Registry.
+
+## Authenticating to the GitLab NPM Registry
+
+If a project is private or you want to upload an NPM package to GitLab,
+credentials will need to be provided for authentication. Support is available
+only for [OAuth tokens](../../../api/oauth2.md#resource-owner-password-credentials-flow).
+
+CAUTION: **2FA not supported:**
+Authentication for personal access tokens is not yet supported
+([#9140](https://gitlab.com/gitlab-org/gitlab-ee/issues/9140)). If you have 2FA
+enabled, you won't be able to authenticate to the GitLab NPM Registry.
+
+### Authenticating with an OAuth token
+
+To authenticate with an [OAuth token](../../../api/oauth2.md#resource-owner-password-credentials-flow),
+add a corresponding section to your `.npmrc` file:
+
+```ini
+; Set URL for your scoped packages.
+; For example package with name `@foo/bar` will use this URL for download
+@foo:registry=https://gitlab.com/api/v4/packages/npm/
+
+; Add the OAuth token for the scoped packages URL. This will allow you to download
+; `@foo/` packages from private projects.
+//gitlab.com/api/v4/packages/npm/:_authToken=<your_oauth_token>
+
+; Add OAuth token for uploading to the registry. Replace <your_project_id>
+; with the project you want your package to be uploaded to.
+//gitlab.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken=<your_oauth_token>
+```
+
+Replace `<your_project_id>` with your project ID which can be found on the home page
+of your project and `<your_oauth_token>` with your OAuth token.
+
+If you have a self-hosted GitLab installation, replace `gitlab.com` with your
+domain name.
+
+You should now be able to download and upload NPM packages to your project.
+
+## Uploading packages
+
+Before you will be able to upload a package, you need to specify the registry
+for NPM. To do this, add the following section to the bottom of `package.json`:
+
+```json
+ "publishConfig": {
+ "@foo:registry":"https://gitlab.com/api/v4/projects/<your_project_id>/packages/npm/"
+ }
+```
+
+Replace `<your_project_id>` with your project ID, which can be found on the home
+page of your project, and replace `@foo` with your own scope.
+
+If you have a self-hosted GitLab installation, replace `gitlab.com` with your
+domain name.
+
+Once you have enabled it and set up [authentication](#authenticating-to-the-gitlab-npm-registry),
+you can upload an NPM package to your project:
+
+```sh
+npm publish
+```
+
+You can then navigate to your project's **Packages** page and see the uploaded
+packages or even delete them.
+
+## Uploading a package with the same version twice
+
+If you upload a package with a same name and version twice, GitLab will show
+both packages in the UI, but the GitLab NPM Registry will expose the most recent
+one as it supports only one package per version for `npm install`.
diff --git a/doc/user/project/pages/getting_started_part_four.md b/doc/user/project/pages/getting_started_part_four.md
index f552f60a07e..8baf41dba78 100644
--- a/doc/user/project/pages/getting_started_part_four.md
+++ b/doc/user/project/pages/getting_started_part_four.md
@@ -1,10 +1,6 @@
---
-last_updated: 2018-02-16
-author: Marcia Ramos
-author_gitlab: marcia
-level: intermediate
-article_type: user guide
-date: 2017-02-22
+last_updated: 2019-06-04
+type: reference, howto
---
# Creating and Tweaking GitLab CI/CD for GitLab Pages
@@ -54,7 +50,7 @@ Of course, before building it, you had to install Jekyll in your computer.
For that, you had to open your terminal and run `gem install jekyll`.
Right? GitLab CI + GitLab Runner do the same thing. But you need to
write in the `.gitlab-ci.yml` the script you want to run so
-GitLab Runner will do it for you. It looks more complicated then it
+GitLab Runner will do it for you. It looks more complicated than it
is. What you need to tell the Runner:
```
diff --git a/doc/user/project/pages/getting_started_part_one.md b/doc/user/project/pages/getting_started_part_one.md
index 7dbf58b5715..6d538ca2455 100644
--- a/doc/user/project/pages/getting_started_part_one.md
+++ b/doc/user/project/pages/getting_started_part_one.md
@@ -1,5 +1,6 @@
---
-last_updated: 2018-02-16
+last_updated: 2018-06-04
+type: concepts, reference
---
# Static sites and GitLab Pages domains
diff --git a/doc/user/project/pages/getting_started_part_three.md b/doc/user/project/pages/getting_started_part_three.md
index 9f2bc281f85..d585c19fc5c 100644
--- a/doc/user/project/pages/getting_started_part_three.md
+++ b/doc/user/project/pages/getting_started_part_three.md
@@ -1,10 +1,6 @@
---
-last_updated: 2018-11-19
-author: Marcia Ramos
-author_gitlab: marcia
-level: beginner
-article_type: user guide
-date: 2017-02-22
+last_updated: 2019-06-04
+type: concepts, reference, howto
---
# GitLab Pages custom domains and SSL/TLS Certificates
@@ -96,7 +92,7 @@ you need to log into your domain's admin control panel and add a DNS
`CNAME` record pointing your subdomain to your website URL
(`namespace.gitlab.io`) address.
-Notice that, despite it's a user or project website, the `CNAME`
+Note that, whether it's a user or a project website, the `CNAME`
should point to your Pages domain (`namespace.gitlab.io`),
without any `/project-name`.
diff --git a/doc/user/project/pages/getting_started_part_two.md b/doc/user/project/pages/getting_started_part_two.md
index 1034ba1733d..3e50cd4887c 100644
--- a/doc/user/project/pages/getting_started_part_two.md
+++ b/doc/user/project/pages/getting_started_part_two.md
@@ -1,10 +1,6 @@
---
-last_updated: 2019-03-05
-author: Marcia Ramos
-author_gitlab: marcia
-level: beginner
-article_type: user guide
-date: 2017-02-22
+last_updated: 2019-06-04
+type: reference, howto
---
# Projects for GitLab Pages and URL structure
@@ -13,11 +9,11 @@ date: 2017-02-22
To get started with GitLab Pages, you need:
-1. A project
-1. A configuration file (`.gitlab-ci.yml`) to deploy your site
+1. A project, thus a repository to hold your website's codebase.
+1. A configuration file (`.gitlab-ci.yml`) to deploy your site.
1. A specific `job` called `pages` in the configuration file
- that will make GitLab aware that you are deploying a GitLab Pages website
-1. A `public` directory with the content of the website
+ that will make GitLab aware that you are deploying a GitLab Pages website.
+1. A `public` directory with the static content of the website.
Optional Features:
@@ -88,14 +84,15 @@ website from your project's **Settings > Pages**.
You can also take some **optional** further steps:
-- _Remove the fork relationship._ The fork relashionship is necessary to contribute back to the project you originally forked from. If you don't have any intentions to do so, you can remove it. To do so, navigate to your project's **Settings**, expand **Advanced settings**, and scroll down to **Remove fork relationship**:
+- _Remove the fork relationship._ The fork relationship is necessary to contribute back to the project you originally forked from. If you don't have any intentions to do so, you can remove it. To do so, navigate to your project's **Settings**, expand **Advanced settings**, and scroll down to **Remove fork relationship**:
![remove fork relationship](img/remove_fork_relationship.png)
- _Make it a user or group website._ To turn a **project website** forked
from the Pages group into a **user/group** website, you'll need to:
- - Rename it to `namespace.gitlab.io`: navigate to project's **Settings** >
- expand **Advanced settings** > and scroll down to **Rename repository**.
+ - Rename it to `namespace.gitlab.io`: go to your project's
+ **Settings > General** and expand **Advanced**. Scroll down to
+ **Rename repository** and change the path to `namespace.gitlab.io`.
- Adjust your SSG's [base URL](#urls-and-baseurls) from `"project-name"` to
`""`. This setting will be at a different place for each SSG, as each of them
have their own structure and file tree. Most likely, it will be in the SSG's
@@ -139,7 +136,7 @@ where you'll find its default URL.
repository to you local computer and moving your site files into it,
you can run `git init` in your local website directory, add the
remote URL: `git remote add origin git@gitlab.com:namespace/project-name.git`,
- then add, commit, and push.
+ then add, commit, and push to GitLab.
## URLs and Baseurls
@@ -172,4 +169,4 @@ baseurl: ""
## Custom Domains
GitLab Pages supports custom domains and subdomains, served under HTTP or HTTPS.
-Please check the [next part](getting_started_part_three.md) of this series for an overview.
+See [GitLab Pages custom domains and SSL/TLS Certificates](getting_started_part_three.md) for more information.
diff --git a/doc/user/project/pages/img/pages_create_project.png b/doc/user/project/pages/img/pages_create_project.png
deleted file mode 100644
index 69e84b84984..00000000000
--- a/doc/user/project/pages/img/pages_create_project.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/pages/img/pages_create_user_page.png b/doc/user/project/pages/img/pages_create_user_page.png
deleted file mode 100644
index 2f1a19ae424..00000000000
--- a/doc/user/project/pages/img/pages_create_user_page.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/pages/img/pages_dns_details.png b/doc/user/project/pages/img/pages_dns_details.png
deleted file mode 100644
index 3e57f43f7ba..00000000000
--- a/doc/user/project/pages/img/pages_dns_details.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/pages/img/pages_multiple_domains.png b/doc/user/project/pages/img/pages_multiple_domains.png
deleted file mode 100644
index 76c39101439..00000000000
--- a/doc/user/project/pages/img/pages_multiple_domains.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/pages/img/pages_new_domain_button.png b/doc/user/project/pages/img/pages_new_domain_button.png
deleted file mode 100644
index cd59defa006..00000000000
--- a/doc/user/project/pages/img/pages_new_domain_button.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/pages/img/pages_upload_cert.png b/doc/user/project/pages/img/pages_upload_cert.png
deleted file mode 100644
index 64e5f8eced1..00000000000
--- a/doc/user/project/pages/img/pages_upload_cert.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md
index 91098d51160..04bda212128 100644
--- a/doc/user/project/pages/index.md
+++ b/doc/user/project/pages/index.md
@@ -1,6 +1,7 @@
---
description: 'Learn how to use GitLab Pages to deploy a static website at no additional cost.'
-last_updated: 2019-03-05
+last_updated: 2019-06-04
+type: index, reference
---
# GitLab Pages
@@ -140,7 +141,7 @@ To learn more about configuration options for GitLab Pages, read the following:
| [Static websites and Pages domains](getting_started_part_one.md) | Understand what is a static website, and how GitLab Pages default domains work. |
| [Projects and URL structure](getting_started_part_two.md) | Forking projects and creating new ones from scratch, understanding URLs structure and baseurls. |
| [GitLab CI/CD for GitLab Pages](getting_started_part_four.md) | Understand how to create your own `.gitlab-ci.yml` for your site. |
-| [Exploring GitLab Pages](introduction.md) | Technical aspects, specific configuration options, custom 404 pages, limitations. |
+| [Exploring GitLab Pages](introduction.md) | Requirements, technical aspects, specific GitLab CI's configuration options, custom 404 pages, limitations, FAQ. |
|---+---|
| [Custom domains and SSL/TLS Certificates](getting_started_part_three.md) | How to add custom domains and subdomains to your website, configure DNS records and SSL/TLS certificates. |
| [CloudFlare certificates](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/) | Secure your Pages site with CloudFlare certificates. |
diff --git a/doc/user/project/pages/introduction.md b/doc/user/project/pages/introduction.md
index a14a446aead..4fab7f79e0c 100644
--- a/doc/user/project/pages/introduction.md
+++ b/doc/user/project/pages/introduction.md
@@ -1,3 +1,8 @@
+---
+type: reference
+last_updated: 2018-06-04
+---
+
# Exploring GitLab Pages
This document is a user guide to explore the options and settings
@@ -10,7 +15,7 @@ To familiarize yourself with GitLab Pages first:
- Learn how to enable GitLab Pages
across your GitLab instance on the [administrator documentation](../../../administration/pages/index.md).
-## Pages requirements
+## GitLab Pages requirements
In brief, this is what you need to upload your website in GitLab Pages:
@@ -34,6 +39,99 @@ If you are using [GitLab Pages on GitLab.com](#gitlab-pages-on-gitlabcom) to hos
Visit the [GitLab Pages group](https://gitlab.com/groups/pages) for a complete list of example projects. Contributions are very welcome.
+## Custom error codes Pages
+
+You can provide your own 403 and 404 error pages by creating the `403.html` and
+`404.html` files respectively in the root directory of the `public/` directory
+that will be included in the artifacts. Usually this is the root directory of
+your project, but that may differ depending on your static generator
+configuration.
+
+If the case of `404.html`, there are different scenarios. For example:
+
+- If you use project Pages (served under `/projectname/`) and try to access
+ `/projectname/non/existing_file`, GitLab Pages will try to serve first
+ `/projectname/404.html`, and then `/404.html`.
+- If you use user/group Pages (served under `/`) and try to access
+ `/non/existing_file` GitLab Pages will try to serve `/404.html`.
+- If you use a custom domain and try to access `/non/existing_file`, GitLab
+ Pages will try to serve only `/404.html`.
+
+## Redirects in GitLab Pages
+
+Since you cannot use any custom server configuration files, like `.htaccess` or
+any `.conf` file, if you want to redirect a page to another
+location, you can use the [HTTP meta refresh tag][metarefresh].
+
+Some static site generators provide plugins for that functionality so that you
+don't have to create and edit HTML files manually. For example, Jekyll has the
+[redirect-from plugin](https://github.com/jekyll/jekyll-redirect-from).
+
+## GitLab Pages Access Control **[CORE ONLY]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/33422) in GitLab 11.5.
+
+NOTE: **Note:**
+GitLab Pages access control is not activated on GitLab.com. You can check its
+progress on the
+[infrastructure issue tracker](https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/5576).
+
+You can enable Pages access control on your project, so that only
+[members of your project](../../permissions.md#project-members-permissions)
+(at least Guest) can access your website:
+
+1. Navigate to your project's **Settings > General > Permissions**.
+1. Toggle the **Pages** button to enable the access control.
+
+ NOTE: **Note:**
+ If you don't see the toggle button, that means that it's not enabled.
+ Ask your administrator to [enable it](../../../administration/pages/index.md#access-control).
+
+1. The Pages access control dropdown allows you to set who can view pages hosted
+ with GitLab Pages, depending on your project's visibility:
+
+ - If your project is private:
+ - **Only project members**: Only project members will be able to browse the website.
+ - **Everyone**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership.
+ - If your project is internal:
+ - **Only project members**: Only project members will be able to browse the website.
+ - **Everyone with access**: Everyone logged into GitLab will be able to browse the website, no matter their project membership.
+ - **Everyone**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership.
+ - If your project is public:
+ - **Only project members**: Only project members will be able to browse the website.
+ - **Everyone with access**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership.
+
+1. Click **Save changes**.
+
+---
+
+The next time someone tries to access your website and the access control is
+enabled, they will be presented with a page to sign into GitLab and verify they
+can access the website.
+
+## Unpublishing your Pages
+
+If you ever feel the need to purge your Pages content, you can do so by going
+to your project's settings through the gear icon in the top right, and then
+navigating to **Pages**. Hit the **Remove pages** button and your Pages website
+will be deleted.
+
+![Remove pages](img/remove_pages.png)
+
+## Limitations
+
+When using Pages under the general domain of a GitLab instance (`*.example.io`),
+you _cannot_ use HTTPS with sub-subdomains. That means that if your
+username/groupname contains a dot, for example `foo.bar`, the domain
+`https://foo.bar.example.io` will _not_ work. This is a limitation of the
+[HTTP Over TLS protocol][rfc]. HTTP pages will continue to work provided you
+don't redirect HTTP to HTTPS.
+
+[rfc]: https://tools.ietf.org/html/rfc2818#section-3.1 "HTTP Over TLS RFC"
+
+GitLab Pages [does **not** support group websites for subgroups](../../group/subgroups/index.md#limitations).
+You can only create the highest-level group website.
+
## Specific configuration options for Pages
Learn how to set up GitLab CI/CD for specific use cases.
@@ -208,99 +306,6 @@ NOTE: **Note:**
When `public/data/index.html` exists, it takes priority over the `public/data.html`
file for both the `/data` and `/data/` URL paths.
-### Custom error codes pages
-
-You can provide your own 403 and 404 error pages by creating the `403.html` and
-`404.html` files respectively in the root directory of the `public/` directory
-that will be included in the artifacts. Usually this is the root directory of
-your project, but that may differ depending on your static generator
-configuration.
-
-If the case of `404.html`, there are different scenarios. For example:
-
-- If you use project Pages (served under `/projectname/`) and try to access
- `/projectname/non/existing_file`, GitLab Pages will try to serve first
- `/projectname/404.html`, and then `/404.html`.
-- If you use user/group Pages (served under `/`) and try to access
- `/non/existing_file` GitLab Pages will try to serve `/404.html`.
-- If you use a custom domain and try to access `/non/existing_file`, GitLab
- Pages will try to serve only `/404.html`.
-
-### Redirects in GitLab Pages
-
-Since you cannot use any custom server configuration files, like `.htaccess` or
-any `.conf` file, if you want to redirect a page to another
-location, you can use the [HTTP meta refresh tag][metarefresh].
-
-Some static site generators provide plugins for that functionality so that you
-don't have to create and edit HTML files manually. For example, Jekyll has the
-[redirect-from plugin](https://github.com/jekyll/jekyll-redirect-from).
-
-### GitLab Pages Access Control **[CORE ONLY]**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/33422) in GitLab 11.5.
-
-NOTE: **Note:**
-GitLab Pages access control is not activated on GitLab.com. You can check its
-progress on the
-[infrastructure issue tracker](https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/5576).
-
-You can enable Pages access control on your project, so that only
-[members of your project](../../permissions.md#project-members-permissions)
-(at least Guest) can access your website:
-
-1. Navigate to your project's **Settings > General > Permissions**.
-1. Toggle the **Pages** button to enable the access control.
-
- NOTE: **Note:**
- If you don't see the toggle button, that means that it's not enabled.
- Ask your administrator to [enable it](../../../administration/pages/index.md#access-control).
-
-1. The Pages access control dropdown allows you to set who can view pages hosted
- with GitLab Pages, depending on your project's visibility:
-
- - If your project is private:
- - **Only project members**: Only project members will be able to browse the website.
- - **Everyone**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership.
- - If your project is internal:
- - **Only project members**: Only project members will be able to browse the website.
- - **Everyone with access**: Everyone logged into GitLab will be able to browse the website, no matter their project membership.
- - **Everyone**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership.
- - If your project is public:
- - **Only project members**: Only project members will be able to browse the website.
- - **Everyone with access**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership.
-
-1. Click **Save changes**.
-
----
-
-The next time someone tries to access your website and the access control is
-enabled, they will be presented with a page to sign into GitLab and verify they
-can access the website.
-
-## Unpublishing your Pages
-
-If you ever feel the need to purge your Pages content, you can do so by going
-to your project's settings through the gear icon in the top right, and then
-navigating to **Pages**. Hit the **Remove pages** button and your Pages website
-will be deleted.
-
-![Remove pages](img/remove_pages.png)
-
-## Limitations
-
-When using Pages under the general domain of a GitLab instance (`*.example.io`),
-you _cannot_ use HTTPS with sub-subdomains. That means that if your
-username/groupname contains a dot, for example `foo.bar`, the domain
-`https://foo.bar.example.io` will _not_ work. This is a limitation of the
-[HTTP Over TLS protocol][rfc]. HTTP pages will continue to work provided you
-don't redirect HTTP to HTTPS.
-
-[rfc]: https://tools.ietf.org/html/rfc2818#section-3.1 "HTTP Over TLS RFC"
-
-GitLab Pages [does **not** support group websites for subgroups](../../group/subgroups/index.md#limitations).
-You can only create the highest-level group website.
-
## Frequently Asked Questions
### Can I download my generated pages?
diff --git a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
index ea22f3e905b..91a660c0f7a 100644
--- a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
+++ b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
@@ -1,5 +1,7 @@
---
description: "How to secure GitLab Pages websites with Let's Encrypt."
+type: howto
+last_updated: 2019-06-04
---
# Let's Encrypt for GitLab Pages
@@ -145,8 +147,8 @@ Now that your certificate has been issued, let's add it to your Pages site:
1. Visit your website at `https://example.com`.
To force `https` connections on your site, navigate to your
-project's **Settings > Pages** and check **Force domains with SSL
-certificates to use HTTPS**.
+project's **Settings > Pages** and check **Force HTTPS (requires
+valid certificates)**.
## Renewal
diff --git a/doc/user/project/pipelines/img/pipeline_schedule_variables.png b/doc/user/project/pipelines/img/pipeline_schedule_variables.png
index 74692add93a..29846206491 100644
--- a/doc/user/project/pipelines/img/pipeline_schedule_variables.png
+++ b/doc/user/project/pipelines/img/pipeline_schedule_variables.png
Binary files differ
diff --git a/doc/user/project/pipelines/img/pipeline_schedules_new_form.png b/doc/user/project/pipelines/img/pipeline_schedules_new_form.png
index 95203ec861b..e135dd51070 100644
--- a/doc/user/project/pipelines/img/pipeline_schedules_new_form.png
+++ b/doc/user/project/pipelines/img/pipeline_schedules_new_form.png
Binary files differ
diff --git a/doc/user/project/pipelines/job_artifacts.md b/doc/user/project/pipelines/job_artifacts.md
index a3f40c20192..002addfc043 100644
--- a/doc/user/project/pipelines/job_artifacts.md
+++ b/doc/user/project/pipelines/job_artifacts.md
@@ -16,7 +16,7 @@
> [administration/job_artifacts](../../../administration/job_artifacts.md).
Artifacts is a list of files and directories which are attached to a job
-after it completes successfully. This feature is enabled by default in all
+after it finishes. This feature is enabled by default in all
GitLab installations.
## Defining artifacts in `.gitlab-ci.yml`
@@ -36,12 +36,14 @@ pdf:
A job named `pdf` calls the `xelatex` command in order to build a pdf file from
the latex source file `mycv.tex`. We then define the `artifacts` paths which in
turn are defined with the `paths` keyword. All paths to files and directories
-are relative to the repository that was cloned during the build. These uploaded
-artifacts will be kept in GitLab for 1 week as defined by the `expire_in`
-definition. You have the option to keep the artifacts from expiring via the
-[web interface](#browsing-artifacts). If the expiry time is not defined,
-it defaults to the [instance wide
-setting](../../admin_area/settings/continuous_integration.md#default-artifacts-expiration-core-only).
+are relative to the repository that was cloned during the build.
+
+The artifacts will be uploaded when the job succeeds by default, but can be set to upload
+when the job fails, or always, if the [`artifacts:when`](../../../ci/yaml/README.md#artifactswhen)
+parameter is used. These uploaded artifacts will be kept in GitLab for 1 week as defined
+by the `expire_in` definition. You have the option to keep the artifacts from expiring
+via the [web interface](#browsing-artifacts). If the expiry time is not defined, it defaults
+to the [instance wide setting](../../admin_area/settings/continuous_integration.md#default-artifacts-expiration-core-only).
For more examples on artifacts, follow the [artifacts reference in
`.gitlab-ci.yml`](../../../ci/yaml/README.md#artifacts).
@@ -55,7 +57,8 @@ For more examples on artifacts, follow the [artifacts reference in
> **Note:**
> With [GitLab 10.1][ce-14399], HTML files in a public project can be previewed
> directly in a new tab without the need to download them when
-> [GitLab Pages](../../../administration/pages/index.md) is enabled
+> [GitLab Pages](../../../administration/pages/index.md) is enabled.
+> The same holds for textual formats (currently supported extensions: `.txt`, `.json`, and `.log`).
After a job finishes, if you visit the job's specific page, there are three
buttons. You can download the artifacts archive or browse its contents, whereas
diff --git a/doc/user/project/pipelines/schedules.md b/doc/user/project/pipelines/schedules.md
index 89f1beb6d1f..dd5427ab35a 100644
--- a/doc/user/project/pipelines/schedules.md
+++ b/doc/user/project/pipelines/schedules.md
@@ -79,7 +79,7 @@ For example, only two pipelines will be created per day if:
To change the Sidekiq worker's frequency:
-1. Edit the `pipeline_schedule_worker_cron` value in your instance's `gitlab.rb` file.
+1. Edit the `gitlab_rails['pipeline_schedule_worker_cron']` value in your instance's `gitlab.rb` file.
1. [Restart GitLab](../../../administration/restart_gitlab.md).
For GitLab.com, refer to the [dedicated settings page](../../gitlab_com/index.md#cron-jobs).
diff --git a/doc/user/project/pipelines/settings.md b/doc/user/project/pipelines/settings.md
index 8b762307ac4..16f48c462eb 100644
--- a/doc/user/project/pipelines/settings.md
+++ b/doc/user/project/pipelines/settings.md
@@ -20,6 +20,22 @@ There are two options. Using:
The default Git strategy can be overridden by the [GIT_STRATEGY variable](../../../ci/yaml/README.md#git-strategy)
in `.gitlab-ci.yml`.
+## Git shallow clone
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/28919) in GitLab 12.0.
+
+NOTE: **Note**: As of GitLab 12.0, newly created projects will automaticallyl have a default
+`git depth` value of `50`.
+
+It is possible to limit the number of changes that GitLab CI/CD will fetch when cloning
+a repository. Setting a limit to `git depth` can speed up Pipelines execution. Maximum
+allowed value is `1000`.
+
+To disable shallow clone and make GitLab CI/CD fetch all branches and tags each time,
+keep the value empty or set to `0`.
+
+This value can also be [overridden by `GIT_DEPTH`](../../../ci/large_repositories/index.md#shallow-cloning) variable in `.gitlab-ci.yml` file.
+
## Timeout
Timeout defines the maximum amount of time in minutes that a job is able run.
diff --git a/doc/user/project/protected_branches.md b/doc/user/project/protected_branches.md
index 2060b5dd4a2..56e8f1731ae 100644
--- a/doc/user/project/protected_branches.md
+++ b/doc/user/project/protected_branches.md
@@ -15,12 +15,10 @@ By default, a protected branch does four simple things:
- it prevents **anyone** from force pushing to the branch
- it prevents **anyone** from deleting the branch
-See the [Changelog](#changelog) section for changes over time.
+>**Note**:
+A GitLab admin is allowed to push to the protected branches.
->
->Additional functionality for GitLab Enterprise Edition:
->
->- Restrict push and merge access to [certain users][ee-restrict]
+See the [Changelog](#changelog) section for changes over time.
## Configuring protected branches
@@ -68,6 +66,21 @@ dropdown list in the "Already protected" area.
If you don't choose any of those options while creating a protected branch,
they are set to "Maintainers" by default.
+## Restricting push and merge access to certain users **[STARTER]**
+
+> This feature was [introduced][ce-5081] in [GitLab Starter][ee] 8.11.
+
+With GitLab Enterprise Edition you can restrict access to protected branches
+by choosing a role (Maintainers, Developers) as well as certain users. From the
+dropdown menu select the role and/or the users you want to have merge or push
+access.
+
+![Select roles and users](img/protected_branches_select_roles_and_users.png)
+
+Click **Protect** and the branch will appear in the "Protected branch" list.
+
+![Roles and users list](img/protected_branches_select_roles_and_users_list.png)
+
## Wildcard protected branches
> [Introduced][ce-4665] in GitLab 8.10.
@@ -169,3 +182,4 @@ for details about the pipelines security model.
[ce-21393]: https://gitlab.com/gitlab-org/gitlab-ce/issues/21393
[ee-restrict]: http://docs.gitlab.com/ee/user/project/protected_branches.html#restricting-push-and-merge-access-to-certain-users
[perm]: ../permissions.md
+[ee]: https://about.gitlab.com/pricing/
diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md
index 88f4de891a1..1d640966013 100644
--- a/doc/user/project/quick_actions.md
+++ b/doc/user/project/quick_actions.md
@@ -26,15 +26,16 @@ discussions, and descriptions:
| `/award :emoji:` | Toggle emoji award | ✓ | ✓ |
| `/assign me` | Assign yourself | ✓ | ✓ |
| `/assign @user` | Assign one user | ✓ | ✓ |
-| `/assign @user1 @user2` | Assign multiple users **[STARTER]** | ✓ | |
-| `/unassign` | Remove assignee(s) | ✓ | ✓ |
-| `/reassign @user1 @user2` | Change assignee | ✓ | ✓ |
+| `/assign @user1 @user2` | Assign multiple users **[STARTER]** | ✓ | ✓ |
+| `/unassign @user1 @user2` | Remove assignee(s) **[STARTER]** | ✓ | ✓ |
+| `/reassign @user1 @user2` | Change assignee **[STARTER]** | ✓ | ✓ |
+| `/unassign` | Remove current assignee | ✓ | ✓ |
| `/milestone %milestone` | Set milestone | ✓ | ✓ |
| `/remove_milestone` | Remove milestone | ✓ | ✓ |
| `/label ~label1 ~label2` | Add label(s). Label names can also start without ~ but mixed syntax is not supported. | ✓ | ✓ |
| `/unlabel ~label1 ~label2` | Remove all or specific label(s)| ✓ | ✓ |
| `/relabel ~label1 ~label2` | Replace label | ✓ | ✓ |
-| <code>/copy_metadata #issue &#124; !merge_request</code> | Copy labels and milestone from other issue or merge request | ✓ | ✓ |
+| <code>/copy_metadata #issue &#124; !merge_request</code> | Copy labels and milestone from other issue or merge request in the project | ✓ | ✓ |
| <code>/estimate &lt;1w 3d 2h 14m&gt;</code> | Set time estimate | ✓ | ✓ |
| `/remove_estimate` | Remove time estimate | ✓ | ✓ |
| <code>/spend &lt;time(1h 30m &#124; -1h 5m)&gt; &lt;date(YYYY-MM-DD)&gt;</code> | Add or subtract spent time; optionally, specify the date that time was spent on | ✓ | ✓ |
@@ -45,13 +46,15 @@ discussions, and descriptions:
| `/remove_due_date` | Remove due date | ✓ | |
| `/weight 0,1,2, ...` | Set weight **[STARTER]** | ✓ | |
| `/clear_weight` | Clears weight **[STARTER]** | ✓ | |
-| `/epic <group&epic &#124; Epic URL>` | Add to epic **[ULTIMATE]** | ✓ | |
+| `/epic <&epic &#124; group&epic &#124; Epic URL>` | Add to epic **[ULTIMATE]** | ✓ | |
| `/remove_epic` | Removes from epic **[ULTIMATE]** | ✓ | |
+| `/promote` | Promote issue to epic **[ULTIMATE]** | ✓ | |
| `/confidential` | Make confidential | ✓ | |
| `/duplicate #issue` | Mark this issue as a duplicate of another issue | ✓ |
| `/move path/to/project` | Move this issue to another project | ✓ | |
| `/target_branch <Local branch Name>` | Set target branch | | ✓ |
| `/wip` | Toggle the Work In Progress status | | ✓ |
+| `/approve` | Approve the merge request | | ✓ |
| `/merge` | Merge (when pipeline succeeds) | | ✓ |
| `/create_merge_request <branch name>` | Create a new merge request starting from the current issue | ✓ | |
diff --git a/doc/user/project/repository/gpg_signed_commits/index.md b/doc/user/project/repository/gpg_signed_commits/index.md
index 6495ede42e0..3260a355fdc 100644
--- a/doc/user/project/repository/gpg_signed_commits/index.md
+++ b/doc/user/project/repository/gpg_signed_commits/index.md
@@ -264,7 +264,7 @@ To remove a GPG key from your account:
## Rejecting commits that are not signed **[PREMIUM]**
You can configure your project to reject commits that aren't GPG-signed
-via [push rules](https://docs.gitlab.com/ee/push_rules/push_rules.html).
+via [push rules](../../../../push_rules/push_rules.md).
## GPG signing API
diff --git a/doc/user/project/repository/img/download_source_code.png b/doc/user/project/repository/img/download_source_code.png
new file mode 100644
index 00000000000..17f2cb4b3e8
--- /dev/null
+++ b/doc/user/project/repository/img/download_source_code.png
Binary files differ
diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md
index 22d912cd9d1..165f4c15165 100644
--- a/doc/user/project/repository/index.md
+++ b/doc/user/project/repository/index.md
@@ -68,7 +68,7 @@ according to the markup language.
| Plain text | `txt` |
| [Markdown](../../markdown.md) | `mdown`, `mkd`, `mkdn`, `md`, `markdown` |
| [reStructuredText](http://docutils.sourceforge.net/rst.html) | `rst` |
-| [Asciidoc](https://asciidoctor.org/docs/what-is-asciidoc/) | `adoc`, `ad`, `asciidoc` |
+| [AsciiDoc](../../asciidoc.md) | `adoc`, `ad`, `asciidoc` |
| [Textile](https://txstyle.org/) | `textile` |
| [rdoc](http://rdoc.sourceforge.net/doc/index.html) | `rdoc` |
| [Orgmode](https://orgmode.org/) | `org` |
@@ -97,7 +97,7 @@ Some things to note about precedence:
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/2508) in GitLab 9.1
-[Jupyter][jupyter] Notebook (previously IPython Notebook) files are used for
+[Jupyter](https://jupyter.org) Notebook (previously IPython Notebook) files are used for
interactive computing in many fields and contain a complete record of the
user's sessions and include code, narrative text, equations and rich output.
@@ -123,7 +123,7 @@ You can live preview changes submitted to a new branch with
[Review Apps](../../../ci/review_apps/index.md).
With [GitLab Starter](https://about.gitlab.com/pricing/), you can also request
-[approval](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html) from your managers.
+[approval](../merge_requests/merge_request_approvals.md) from your managers.
To create, delete, and view [branches](branches/index.md) via GitLab's UI:
@@ -154,7 +154,7 @@ Via command line, you can commit multiple times before pushing.
you will trigger a pipeline per push, not per commit.
- **Skip pipelines:**
You can add to you commit message the keyword
- [`[ci skip]`](../../../ci/yaml/README.html#skipping-jobs)
+ [`[ci skip]`](../../../ci/yaml/README.md#skipping-jobs)
and GitLab CI will skip that pipeline.
- **Cross-link issues and merge requests:**
[Cross-linking](../issues/crosslinking_issues.md#from-commit-messages)
@@ -173,11 +173,15 @@ Via command line, you can commit multiple times before pushing.
## Repository size
-On GitLab.com, your [repository size limit is 10GB](../../gitlab_com/index.md#repository-size-limit)
-(including LFS). For other instances, the repository size is limited by your
-system administrators.
+A project's repository size is reported on the project's **Details** page. The reported size is
+updated every 15 minutes at most, so may not reflect recent activity.
-You can also [reduce a repository size using Git](reducing_the_repo_size_using_git.md).
+The repository size for:
+
+- GitLab.com [is set by GitLab](../../gitlab_com/index.md#repository-size-limit).
+- Self-managed instances is set by your GitLab administrators.
+
+You can [reduce a repository's size using Git](reducing_the_repo_size_using_git.md).
## Contributors
@@ -220,14 +224,10 @@ Select branches to compare using the [branch filter search box](branches/index.m
Find it under your project's **Repository > Compare**.
-## Locked files
-
-> Available in [GitLab Premium](https://about.gitlab.com/pricing/).
-
-Lock your files to prevent any conflicting changes.
+## Locked files **[PREMIUM]**
-[File Locking](https://docs.gitlab.com/ee/user/project/file_lock.html) is available only in
-[GitLab Premium](https://about.gitlab.com/pricing/).
+Use [File Locking](../file_lock.md) to
+lock your files to prevent any conflicting changes.
## Repository's API
@@ -241,4 +241,21 @@ Projects that contain a `.xcodeproj` or `.xcworkspace` directory can now be clon
in Xcode using the new **Open in Xcode** button, located next to the Git URL
used for cloning your project. The button is only shown on macOS.
-[jupyter]: https://jupyter.org
+## Download Source Code
+
+> Support for directory download was [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/24704) in GitLab 11.11.
+
+The source code stored in a repository can be downloaded from the UI.
+By clicking the download icon, a dropdown will open with links to download the following:
+
+![Download source code](img/download_source_code.png)
+
+- **Source code:**
+ allows users to download the source code on branch they're currently
+ viewing. Available extensions: `zip`, `tar`, `tar.gz`, and `tar.bz2`.
+- **Directory:**
+ only shows up when viewing a sub-directory. This allows users to download
+ the specific directory they're currently viewing. Also available in `zip`,
+ `tar`, `tar.gz`, and `tar.bz2`.
+- **Artifacts:**
+ allows users to download the artifacts of the latest CI build.
diff --git a/doc/user/project/repository/reducing_the_repo_size_using_git.md b/doc/user/project/repository/reducing_the_repo_size_using_git.md
index 672567a8d7d..e3d771524ce 100644
--- a/doc/user/project/repository/reducing_the_repo_size_using_git.md
+++ b/doc/user/project/repository/reducing_the_repo_size_using_git.md
@@ -1,6 +1,6 @@
# Reducing the repository size using Git
-A GitLab Enterprise Edition administrator can set a [repository size limit][admin-repo-size]
+A GitLab Enterprise Edition administrator can set a [repository size limit](../../admin_area/settings/account_and_limit_settings.md)
which will prevent you from exceeding it.
When a project has reached its size limit, you will not be able to push to it,
@@ -14,7 +14,8 @@ move some blobs to LFS, or remove some old dependency updates from history.
Unfortunately, it's not so easy and that workflow won't work. Deleting files in
a commit doesn't actually reduce the size of the repo since the earlier commits
and blobs are still around. What you need to do is rewrite history with Git's
-[`filter-branch` option][gitscm], or a tool like the [BFG Repo-Cleaner][bfg].
+[`filter-branch` option](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History#The-Nuclear-Option:-filter-branch),
+or a tool like the [BFG Repo-Cleaner](https://rtyley.github.io/bfg-repo-cleaner/).
Note that even with that method, until `git gc` runs on the GitLab side, the
"removed" commits and blobs will still be around. You also need to be able to
@@ -98,6 +99,12 @@ up its own internal state, maximizing the space saved.
`git gc` against the repository. You will receive an email once it has
completed.
+This process will remove some copies of the rewritten commits from GitLab's
+cache and database, but there are still numerous gaps in coverage - at present,
+some of the copies may persist indefinitely. [Clearing the instance cache]
+(../../../administration/raketasks/maintenance.md#clear-redis-cache) may help to
+remove some of them, but it should not be depended on for security purposes!
+
## Using `git filter-branch`
1. Navigate to your repository:
@@ -131,7 +138,3 @@ up its own internal state, maximizing the space saved.
```
Your repository should now be below the size limit.
-
-[admin-repo-size]: https://docs.gitlab.com/ee/user/admin_area/settings/account_and_limit_settings.html#repository-size-limit
-[bfg]: https://rtyley.github.io/bfg-repo-cleaner/
-[gitscm]: https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History#The-Nuclear-Option:-filter-branch
diff --git a/doc/user/project/security_dashboard.md b/doc/user/project/security_dashboard.md
new file mode 100644
index 00000000000..a3da1ec97d3
--- /dev/null
+++ b/doc/user/project/security_dashboard.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../application_security/security_dashboard/index.md'
+---
+
+This document was moved to [another location](../application_security/security_dashboard/index.md).
diff --git a/doc/user/project/service_desk.md b/doc/user/project/service_desk.md
new file mode 100644
index 00000000000..1a582164d03
--- /dev/null
+++ b/doc/user/project/service_desk.md
@@ -0,0 +1,124 @@
+# Service Desk **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/149) in [GitLab Premium 9.1](https://about.gitlab.com/2017/04/22/gitlab-9-1-released/#service-desk-eep).
+
+## Overview
+
+Service Desk is a module that allows your team to connect directly
+with any external party through email right inside of GitLab; no external tools required.
+An ongoing conversation right where your software is built ensures that user feedback ends
+up directly where it's needed, helping you build the right features to solve your users'
+real problems.
+
+With Service Desk, you can provide efficient email support to your customers, who can now
+email you bug reports, feature requests, or general feedback that will all end up in your
+GitLab project as new issues. In turn, your team can respond straight from the project.
+
+As Service Desk is built right into GitLab itself, the complexity and inefficiencies
+of multiple tools and external integrations are eliminated, significantly shortening
+the cycle time from feedback to software update.
+
+For an overview, check the video demonstration on [GitLab Service Desk](https://about.gitlab.com/2017/05/09/demo-service-desk/).
+
+## Use cases
+
+For instance, let's assume you develop a game for iOS or Android.
+The codebase is hosted in your GitLab instance, built and deployed
+with GitLab CI.
+
+Here's how Service Desk will work for you:
+
+1. You'll provide a project-specific email address to your paying customers, who can email you directly from within the app
+1. Each email they send creates an issue in the appropriate project
+1. Your team members navigate to the Service Desk issue tracker, where they can see new support requests and respond inside associated issues
+1. Your team communicates back and forth with the customer to understand the request
+1. Your team starts working on implementing code to solve your customer's problem
+1. When your team finishes the implementation, whereupon the merge request is merged and the issue is closed automatically
+1. The customer will have been attended successfully via email, without having real access to your GitLab instance
+1. Your team saved time by not having to leave GitLab (or setup any integrations) to follow up with your customer
+
+## How it works
+
+GitLab Service Desk is a simple way to allow people to create issues in your
+GitLab instance without needing their own user account.
+
+It provides a unique email address for end users to create issues in a project,
+and replies can be sent either through the GitLab interface or by email. End
+users will only see the thread through email.
+
+## Configuring Service Desk
+
+> **Note:**
+Service Desk is enabled on GitLab.com. If you're a
+[Silver subscriber](https://about.gitlab.com/gitlab-com/),
+you can skip the step 1 below; you only need to enable it per project.
+
+1. [Set up incoming email](../../administration/incoming_email.md#set-it-up) for the GitLab instance. This must
+ support [email sub-addressing](../../administration/incoming_email.md#email-sub-addressing).
+2. Navigate to your project's **Settings** and scroll down to the **Service Desk**
+ section.
+3. If you have the correct access and an Premium license,
+ you will see an option to set up Service Desk:
+
+ ![Activate Service Desk option](img/service_desk_disabled.png)
+
+4. Checking that box will enable Service Desk for the project, and show a
+ unique email address to email issues to the project. These issues will be
+ [confidential](issues/confidential_issues.md), so they will only be visible to project members.
+
+ **Warning**: this email address can be used by anyone to create an issue on
+ this project, whether or not they have access to your GitLab instance.
+ We recommend **putting this behind an alias** so that it can be changed if
+ needed, and **[enabling Akismet](../../integration/akismet.md)** on your GitLab instance to add spam
+ checking to this service. Unblocked email spam would result in many spam
+ issues being created, and may disrupt your GitLab service.
+
+ ![Service Desk enabled](img/service_desk_enabled.png)
+
+ _In GitLab 11.7, we updated the format of the generated email address.
+ However the older format is still supported, allowing existing aliases
+ or contacts to continue working._
+
+
+5. Service Desk is now enabled for this project! You should be able to access it from your project's navigation **Issue submenu**:
+
+ ![Service Desk Navigation Item](img/service_desk_nav_item.png)
+
+## Using Service Desk
+
+### As an end user (issue creator)
+
+To create a Service Desk issue, an end user doesn't need to know anything about
+the GitLab instance. They just send an email to the address they are given, and
+receive an email back confirming receipt:
+
+![Service Desk enabled](img/service_desk_confirmation_email.png)
+
+This also gives the end user an option to unsubscribe.
+
+If they don't choose to unsubscribe, then any new comments added to the issue
+will be sent as emails:
+
+![Service Desk reply email](img/service_desk_reply.png)
+
+And any responses they send will be displayed in the issue itself.
+
+### As a responder to the issue
+
+For responders to the issue, everything works as usual. They'll see a familiar looking
+issue tracker, where they can see issues created via customer support requests and
+filter and interact with them just like other GitLab issues.
+
+![Service Desk Issue tracker](img/service_desk_issue_tracker.png)
+
+Messages from the end user will show as coming from the special Support Bot user, but apart from that,
+you can read and write comments as you normally do:
+
+![Service Desk issue thread](img/service_desk_thread.png)
+
+> Note that the project's visibility (private, internal, public) does not affect Service Desk.
+
+### Support Bot user
+
+Behind the scenes, Service Desk works by the special Support Bot user creating issues. This user
+does not count toward the license limit count.
diff --git a/doc/user/project/settings/img/import_export_download_export.png b/doc/user/project/settings/img/import_export_download_export.png
index 668254073e8..ab81c87bf5f 100644
--- a/doc/user/project/settings/img/import_export_download_export.png
+++ b/doc/user/project/settings/img/import_export_download_export.png
Binary files differ
diff --git a/doc/user/project/settings/img/import_export_export_button.png b/doc/user/project/settings/img/import_export_export_button.png
index 7f21bb2335b..9e368739695 100644
--- a/doc/user/project/settings/img/import_export_export_button.png
+++ b/doc/user/project/settings/img/import_export_export_button.png
Binary files differ
diff --git a/doc/user/project/settings/img/import_export_mail_link.png b/doc/user/project/settings/img/import_export_mail_link.png
index 48ef42855bc..985c37650d3 100644
--- a/doc/user/project/settings/img/import_export_mail_link.png
+++ b/doc/user/project/settings/img/import_export_mail_link.png
Binary files differ
diff --git a/doc/user/project/settings/img/import_export_new_project.png b/doc/user/project/settings/img/import_export_new_project.png
index b335700c5be..fc1f73c5d6e 100644
--- a/doc/user/project/settings/img/import_export_new_project.png
+++ b/doc/user/project/settings/img/import_export_new_project.png
Binary files differ
diff --git a/doc/user/project/settings/img/import_export_select_file.png b/doc/user/project/settings/img/import_export_select_file.png
index e1e5e031d81..e3e1a5ef980 100644
--- a/doc/user/project/settings/img/import_export_select_file.png
+++ b/doc/user/project/settings/img/import_export_select_file.png
Binary files differ
diff --git a/doc/user/project/settings/img/settings_edit_button.png b/doc/user/project/settings/img/settings_edit_button.png
deleted file mode 100644
index 32bcda03c7e..00000000000
--- a/doc/user/project/settings/img/settings_edit_button.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md
index 89008fd15b9..819515d7a4c 100644
--- a/doc/user/project/settings/import_export.md
+++ b/doc/user/project/settings/import_export.md
@@ -2,10 +2,11 @@
>**Notes:**
>
-> - [Introduced][ce-3050] in GitLab 8.9.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/3050) in GitLab 8.9.
> - Importing will not be possible if the import instance version differs from
> that of the exporter.
-> - For GitLab admins, please read through [Project import/export administration](../../../administration/raketasks/project_import_export.md).
+> - For GitLab admins, please read through
+> [Project import/export administration](../../../administration/raketasks/project_import_export.md).
> - For existing installations, the project import option has to be enabled in
> application settings (`/admin/application_settings`) under 'Import sources'.
> Ask your administrator if you don't see the **GitLab export** button when
@@ -14,15 +15,15 @@
> on the GitLab instance in application settings (`/admin/application_settings`)
> under 'Visibility and Access Controls'.
> - You can find some useful raketasks if you are an administrator in the
-> [import_export](../../../administration/raketasks/project_import_export.md)
-> raketask.
-> - The exports are stored in a temporary [shared directory][tmp] and are deleted
-> every 24 hours by a specific worker.
+> [import_export](../../../administration/raketasks/project_import_export.md) raketask.
+> - The exports are stored in a temporary [shared directory](../../../development/shared_files.md)
+> and are deleted every 24 hours by a specific worker.
> - Group members will get exported as project members, as long as the user has
> maintainer or admin access to the group where the exported project lives. An admin
> in the import side is required to map the users, based on email or username.
> Otherwise, a supplementary comment is left to mention the original author and
> the MRs, notes or issues will be owned by the importer.
+> - Project members with owner access will get imported as maintainers.
> - Control project Import/Export with the [API](../../../api/project_import_export.md).
> - If an imported project contains merge requests originated from forks,
> then new branches associated with such merge requests will be created
@@ -76,9 +77,9 @@ The following items will NOT be exported:
## Exporting a project and its data
-1. Go to the project settings page by clicking on **Edit Project**:
+1. Go to your project's homepage.
- ![Project settings button](img/settings_edit_button.png)
+1. Click **Settings** in the sidebar.
1. Scroll down to find the **Export project** button:
@@ -97,19 +98,14 @@ The following items will NOT be exported:
## Importing the project
-1. The new GitLab project import feature is at the far right of the import
- options when creating a New Project. Make sure you are in the right namespace
- and you have entered a project name. Click on **GitLab export**:
+1. The GitLab project import feature is the first import option when creating a
+ new project. Click on **GitLab export**:
![New project](img/import_export_new_project.png)
-1. You can see where the project will be imported to. You can now select file
- exported previously:
+1. Enter your project name and URL. Then select the file you exported previously:
![Select file](img/import_export_select_file.png)
1. Click on **Import project** to begin importing. Your newly imported project
page will appear soon.
-
-[ce-3050]: https://gitlab.com/gitlab-org/gitlab-ce/issues/3050
-[tmp]: ../../../development/shared_files.md
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index d5f4a7fd4ac..ba890c5ac01 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -26,6 +26,12 @@ Set up your project's access, [visibility](../../../public_access/public_access.
![projects sharing permissions](img/sharing_and_permissions_settings.png)
+If Issues are disabled, or you can't access Issues because you're not a project member, then Lables and Milestones
+links will be missing from the sidebar UI.
+
+You can still access them with direct links if you can access Merge Requests. This is deliberate, if you can see
+Issues or Merge Requests, both of which use Labels and Milestones, then you shouldn't be denied access to Labels and Milestones pages.
+
### Issue settings
Add an [issue description template](../description_templates.md#description-templates) to your project, so that every new issue will start with a custom template.
@@ -36,15 +42,15 @@ Set up your project's merge request settings:
- Set up the merge request method (merge commit, [fast-forward merge](../merge_requests/fast_forward_merge.html)).
- Merge request [description templates](../description_templates.md#description-templates).
-- Enable [merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html#merge-request-approvals). **[STARTER]**
+- Enable [merge request approvals](../merge_requests/merge_request_approvals.md). **[STARTER]**
- Enable [merge only of pipeline succeeds](../merge_requests/merge_when_pipeline_succeeds.md).
- Enable [merge only when all discussions are resolved](../../discussions/index.md#only-allow-merge-requests-to-be-merged-if-all-discussions-are-resolved).
![project's merge request settings](img/merge_requests_settings.png)
-### Service Desk
+### Service Desk **[PREMIUM]**
-Enable [Service Desk](https://docs.gitlab.com/ee/user/project/service_desk.html) for your project to offer customer support. Service Desk is available in [GitLab Premium](https://about.gitlab.com/pricing/).
+Enable [Service Desk](../service_desk.md) for your project to offer customer support.
### Export project
@@ -100,9 +106,9 @@ Only project Owners and Admin users have the [permissions] to transfer a project
You can transfer an existing project into a [group](../../group/index.md) if:
-1. you have at least **Maintainer** [permissions] to that group
-1. you are an **Owner** of the project.
-
+1. You have at least **Maintainer** [permissions] to that group.
+1. The project is in a subgroup you own.
+1. You are at least a **Maintainer** of the project under your personal namespace.
Similarly, if you are an owner of a group, you can transfer any of its projects
under your own user.
@@ -128,3 +134,7 @@ namespace if needed.
### Error Tracking
Configure Error Tracking to discover and view [Sentry errors within GitLab](../operations/error_tracking.md).
+
+### Jaeger tracing **[ULTIMATE]**
+
+Add the URL of a Jaeger server to allow your users to [easily access the Jaeger UI from within GitLab](../operations/tracing.md).
diff --git a/doc/user/project/web_ide/img/enable_web_ide.png b/doc/user/project/web_ide/img/enable_web_ide.png
deleted file mode 100644
index 196baa82ad2..00000000000
--- a/doc/user/project/web_ide/img/enable_web_ide.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/web_ide/index.md b/doc/user/project/web_ide/index.md
index 46a1b2bc3aa..a634a8b2f54 100644
--- a/doc/user/project/web_ide/index.md
+++ b/doc/user/project/web_ide/index.md
@@ -8,7 +8,7 @@ projects by providing an advanced editor with commit staging.
## Open the Web IDE
-The Web IDE can be opened when viewing a file, from the repository file list,
+You can open the Web IDE when viewing a file, from the repository file list,
and from merge requests.
![Open Web IDE](img/open_web_ide.png)
@@ -45,7 +45,7 @@ Single file editing is based on the [Ace Editor](https://ace.c9.io).
## Stage and commit changes
-After making your changes, click the Commit button in the bottom left to
+After making your changes, click the **Commit** button in the bottom left to
review the list of changed files. Click on each file to review the changes and
click the tick icon to stage the file.
@@ -67,10 +67,11 @@ shows you a preview of the merge request diff if you commit your changes.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19279) in [GitLab Core][ce] 11.0.
-The Web IDE can be used to quickly fix failing tests by opening the branch or
-merge request in the Web IDE and opening the logs of the failed job. The status
-of all jobs for the most recent pipeline and job traces for the current commit
-can be accessed by clicking the **Pipelines** button in the top right.
+You can use the Web IDE to quickly fix failing tests by opening
+the branch or merge request in the Web IDE and opening the logs of the failed
+job. You can access the status of all jobs for the most recent pipeline and job
+traces for the current commit by clicking the **Pipelines** button in the top
+right.
The pipeline status is also shown at all times in the status bar in the bottom
left.
@@ -79,31 +80,31 @@ left.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19318) in [GitLab Core][ce] 11.0.
-Switching between your authored and assigned merge requests can be done without
-leaving the Web IDE. Click the dropdown in the top of the sidebar to open a list
-of merge requests. You will need to commit or discard all your changes before
-switching to a different merge request.
+To switch between your authored and assigned merge requests, click the
+dropdown in the top of the sidebar to open a list of merge requests. You will
+need to commit or discard all your changes before switching to a different merge
+request.
## Switching branches
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20850) in [GitLab Core][ce] 11.2.
-Switching between branches of the current project repository can be done without
-leaving the Web IDE. Click the dropdown in the top of the sidebar to open a list
-of branches. You will need to commit or discard all your changes before
-switching to a different branch.
+To switch between branches of the current project repository, click the dropdown
+in the top of the sidebar to open a list of branches.
+You will need to commit or discard all your changes before switching to a
+different branch.
## Client Side Evaluation
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19764) in [GitLab Core][ce] 11.2.
-The Web IDE can be used to preview JavaScript projects right in the browser.
+You can use the Web IDE to preview JavaScript projects right in the browser.
This feature uses CodeSandbox to compile and bundle the JavaScript used to
preview the web application.
![Web IDE Client Side Evaluation](img/clientside_evaluation.png)
-Additionally, for public projects an `Open in CodeSandbox` button is available
+Additionally, for public projects an **Open in CodeSandbox** button is available
to transfer the contents of the project into a public CodeSandbox project to
quickly share your project with others.
@@ -115,9 +116,9 @@ GitLab.com
![Admin Client Side Evaluation setting](img/admin_clientside_evaluation.png)
-Once it has been enabled in application settings, projects with a
-`package.json` file and a `main` entry point can be previewed inside of the Web
-IDE. An example `package.json` is below.
+Once you have done that, you can preview projects with a `package.json` file and
+a `main` entry point inside the Web IDE. An example `package.json` is shown
+below.
```json
{
@@ -128,5 +129,123 @@ IDE. An example `package.json` is below.
}
```
+## Interactive Web Terminals for the Web IDE **[ULTIMATE ONLY]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5426) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.6.
+
+CAUTION: **Warning:**
+Interactive Web Terminals for the Web IDE is currently in **Beta**.
+
+[Interactive web terminals](../../../ci/interactive_web_terminal/index.md)
+give the user access to a terminal to interact with the Runner directly from
+GitLab, including through the Web IDE.
+
+Only project [**maintainers**](../../permissions.md#project-members-permissions)
+can run Interactive Web Terminals through the Web IDE.
+
+CAUTION: **Warning:**
+GitLab.com [does not support Interactive Web Terminals yet](https://gitlab.com/gitlab-org/gitlab-ce/issues/52611).
+Shared Runners in private instances are not supported either.
+
+### Runner configuration
+
+Some things need to be configured in the runner for the interactive web terminal
+to work:
+
+- The Runner needs to have
+ [`[session_server]` configured properly](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-session_server-section).
+- If you are using a reverse proxy with your GitLab instance, web terminals need to be
+ [enabled](../../../administration/integration/terminal.md#enabling-and-disabling-terminal-support). **[ULTIMATE ONLY]**
+
+If you have the terminal open and the job has finished with its tasks, the
+terminal will block the job from finishing for the duration configured in
+[`[session_server].terminal_max_retention_time`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-session_server-section)
+until you close the terminal window.
+
+NOTE: **Note:** Not all executors are
+[supported](https://docs.gitlab.com/runner/executors/#compatibility-chart)
+
+### Web IDE configuration file
+
+In order to enable the Web IDE terminals you need to create the file
+`.gitlab/.gitlab-webide.yml` inside the repository's root. This
+file is fairly similar to the [CI configuration file](../../../ci/yaml/README.md)
+syntax but with some restrictions:
+
+- No global blocks can be defined (ie: `before_script` or `after_script`)
+- Only one job named `terminal` can be added to this file.
+- Only the keywords `image`, `services`, `tags`, `before_script`, `script`, and
+`variables` are allowed to be used to configure the job.
+- To connect to the interactive terminal, the `terminal` job must be still alive
+and running, otherwise the terminal won't be able to connect to the job's session.
+By default the `script` keyword has the value `sleep 60` to prevent
+the job from ending and giving the Web IDE enough time to connect. This means
+that, if you override the default `script` value, you'll have to add a command
+which would keep the job running, like `sleep`.
+
+In the code below there is an example of this configuration file:
+
+```yaml
+terminal:
+ before_script:
+ - apt-get update
+ script: sleep 60
+ variables:
+ RAILS_ENV: "test"
+ NODE_ENV: "test"
+```
+
+Once the terminal has started, the console will be displayed and we could access
+the project repository files.
+
+**Important**. The terminal job is branch dependant. This means that the
+configuration file used to trigger and configure the terminal will be the one in
+the selected branch of the Web IDE.
+
+If there is no configuration file in a branch, an error message will be shown.
+
+### Running Interactive Terminals in the Web IDE
+
+If Interactive Terminals are available for the current user, the **Terminal** button
+will be visible in the right sidebar of the Web IDE. Click this button to open
+or close the terminal tab.
+
+Once open, the tab will show the **Start Web Terminal** button. This button may
+be disabled if the environment is not configured correctly. If so, a status
+message will describe the issue. Here are some reasons why **Start Web Terminal**
+may be disabled:
+
+- `.gitlab/.gitlab-webide.yml` does not exist or is set up incorrectly.
+- No active private runners are available for the project.
+
+If active, clicking the **Start Web Terminal** button will load the terminal view
+and start connecting to the runner's terminal. At any time, the **Terminal** tab
+can be closed and reopened and the state of the terminal will not be affected.
+
+When the terminal is started and is successfully connected to the runner, then the
+runner's shell prompt will appear in the terminal. From here, you can enter
+commands that will be executed within the runner's environment. This is similar
+to running commands in a local terminal or through SSH.
+
+While the terminal is running, it can be stopped by clicking **Stop Terminal**.
+This will disconnect the terminal and stop the runner's terminal job. From here,
+click **Restart Terminal** to start a new terminal session.
+
+### Limitations
+
+Interactive Terminals is in a beta phase and will continue to be improved upon in upcoming
+releases. In the meantime, please note that the user is limited to having only one
+active terminal at a time.
+
+### Troubleshooting
+
+- If the terminal's text is gray and unresponsive, then the terminal has stopped
+ and it can no longer be used. A stopped terminal can be restarted by clicking
+ **Restart Terminal**.
+- If the terminal displays **Connection Failure**, then the terminal could not
+ connect to the runner. Please try to stop and restart the terminal. If the
+ problem persists, double check your runner configuration.
+
+
[ce]: https://about.gitlab.com/pricing/
[ee]: https://about.gitlab.com/pricing/
diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md
index 95f606fd786..e3c6cd6d6ff 100644
--- a/doc/user/project/wiki/index.md
+++ b/doc/user/project/wiki/index.md
@@ -116,7 +116,9 @@ instructions.
## Customizing sidebar
-By default, the wiki would render a sidebar which lists all the pages for the
-wiki. You could as well provide a `_sidebar` page to replace this default
-sidebar. When this customized sidebar page is provided, the default sidebar
-would not be rendered, but the customized one.
+On the project's Wiki page, there is a right side navigation that renders the full Wiki pages list by default, with hierarchy.
+
+If the Wiki repository contains a `_sidebar` page, the file of this page replaces the default side navigation.
+This custom file serves to render it's custom content, fully replacing the standard sidebar.
+
+Support for displaying a generated TOC with a custom side navigation is planned.
diff --git a/doc/user/search/advanced_global_search.md b/doc/user/search/advanced_global_search.md
new file mode 100644
index 00000000000..f80f4183802
--- /dev/null
+++ b/doc/user/search/advanced_global_search.md
@@ -0,0 +1,75 @@
+# Advanced Global Search **[STARTER ONLY]**
+
+> - [Introduced][ee-109] in GitLab [Starter][ee] 8.4.
+> - This is the user documentation. To install and configure Elasticsearch,
+> visit the [administrator documentation](../../integration/elasticsearch.md).
+
+NOTE: **Note**
+Advanced Global Search (powered by Elasticsearch) is not yet available on GitLab.com. We are working on adding it. [Follow this epic for the latest updates](https://gitlab.com/groups/gitlab-org/-/epics/153).
+
+Leverage Elasticsearch for faster, more advanced code search across your entire
+GitLab instance.
+
+## Overview
+
+The Advanced Global Search in GitLab is a powerful search service that saves
+you time. Instead of creating duplicate code and wasting time, you can
+now search for code within other teams that can help your own project.
+
+GitLab leverages the search capabilities of [Elasticsearch] and enables it when
+searching in:
+
+- GitLab application
+- Projects
+- Repositories
+- Commits
+- Issues
+- Merge requests
+- Milestones
+- Notes (comments)
+- Snippets
+- Wiki
+
+## Use cases
+
+The Advanced Global Search can be useful in various scenarios.
+
+### Faster searches
+
+If you are dealing with huge amount of data and want to keep GitLab's search
+fast, the Advanced Global Search will help you achieve that.
+
+### Promote innersourcing
+
+Your company may consist of many different developer teams each of which has
+their own group where the various projects are hosted. Some of your applications
+may be connected to each other, so your developers need to instantly search
+throughout the GitLab instance and find the code they search for.
+
+## Searching globally
+
+Just use the search as before and GitLab will show you matching code from each
+project you have access to.
+
+![Advanced Global Search](img/advanced_global_search.png)
+
+You can also use the [Advanced Syntax Search](advanced_search_syntax.md) which
+provides some useful queries.
+
+>**Note:**
+Elasticsearch has only data for the default branch. That means that if you go
+to the repository tree and switch the branch from the default to something else,
+then the "Code" tab in the search result page will be served by the regular
+search even if Elasticsearch is enabled.
+
+[ee-1305]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1305
+[aws-elastic]: http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-gsg.html
+[aws-iam]: http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html
+[aws-instance-profile]: http://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-create-iam-instance-profile.html#getting-started-create-iam-instance-profile-cli
+[ee-109]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/109 "Elasticsearch Merge Request"
+[elasticsearch]: https://www.elastic.co/products/elasticsearch "Elasticsearch website"
+[install]: https://www.elastic.co/guide/en/elasticsearch/reference/current/_installation.html "Elasticsearch installation documentation"
+[pkg]: https://about.gitlab.com/downloads/ "Download Omnibus GitLab"
+[elastic-settings]: https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-configuration.html#settings "Elasticsearch configuration settings"
+[ee]: https://about.gitlab.com/pricing/
+[es]: https://www.elastic.co/products/elasticsearch
diff --git a/doc/user/search/advanced_search_syntax.md b/doc/user/search/advanced_search_syntax.md
new file mode 100644
index 00000000000..d302cb7a809
--- /dev/null
+++ b/doc/user/search/advanced_search_syntax.md
@@ -0,0 +1,69 @@
+# Advanced Syntax Search **[STARTER ONLY]**
+
+> **Notes:**
+> - Introduced in [GitLab Enterprise Starter][ee] 9.2
+> - This is the user documentation. To install and configure Elasticsearch,
+> visit the [administrator documentation](../../integration/elasticsearch.md).
+
+NOTE: **Note**
+Advanced Global Search (powered by Elasticsearch) is not yet available on GitLab.com. We are working on adding it. [Follow this epic for the latest updates](https://gitlab.com/groups/gitlab-org/-/epics/153).
+
+Use advanced queries for more targeted search results.
+
+## Overview
+
+The Advanced Syntax Search is a subset of the
+[Advanced Global Search](advanced_global_search.md), which you can use if you
+want to have more specific search results.
+
+## Use cases
+
+Let's say for example that the product you develop relies on the code of another
+product that's hosted under some other group.
+
+Since under your GitLab instance there are hosted hundreds of different projects,
+you need the search results to be as efficient as possible. You have a feeling
+of what you want to find (e.g., a function name), but at the same you're also
+not so sure.
+
+In that case, using the advanced search syntax in your query will yield much
+better results.
+
+## Using the Advanced Syntax Search
+
+The Advanced Syntax Search supports fuzzy or exact search queries with prefixes,
+boolean operators, and much more.
+
+Full details can be found in the [Elasticsearch documentation][elastic], but
+here's a quick guide:
+
+- Searches look for all the words in a query, in any order - e.g.: searching
+ issues for `display bug` will return all issues matching both those words, in any order.
+- To find the exact phrase (stemming still applies), use double quotes: `"display bug"`
+- To find bugs not mentioning display, use `-`: `bug -display`
+- To find a bug in display or sound, use `|`: `bug display | sound`
+- To group terms together, use parentheses: `bug | (display +sound)`
+- To match a partial word, use `*`: `bug find_by_*`
+- To find a term containing one of these symbols, use `\`: `argument \-last`
+
+### Syntax search filters
+
+The Advanced Syntax Search also supports the use of filters. The available filters are:
+
+ - filename: Filters by filename. You can use the glob (`*`) operator for fuzzy matching.
+ - path: Filters by path. You can use the glob (`*`) operator for fuzzy matching.
+ - extension: Filters by extension in the filename. Please write the extension without a leading dot. Exact match only.
+
+To use them, simply add them to your query in the format `<filter_name>:<value>` without
+ any spaces between the colon (`:`) and the value.
+
+Examples:
+
+- Finding a file with any content named `hello_world.rb`: `* filename:hello_world.rb`
+- Finding a file named `hello_world` with the text `whatever` inside of it: `whatever filename:hello_world`
+- Finding the text 'def create' inside files with the `.rb` extension: `def create extension:rb`
+- Finding the text `sha` inside files in a folder called `encryption`: `sha path:encryption`
+- Finding any file starting with `hello` containing `world` and with the `.js` extension: `world filename:hello* extension:js`
+
+[ee]: https://about.gitlab.com/pricing/
+[elastic]: https://www.elastic.co/guide/en/elasticsearch/reference/5.3/query-dsl-simple-query-string-query.html#_simple_query_string_syntax
diff --git a/doc/user/search/img/advanced_global_search.png b/doc/user/search/img/advanced_global_search.png
new file mode 100644
index 00000000000..4903bbb07e1
--- /dev/null
+++ b/doc/user/search/img/advanced_global_search.png
Binary files differ
diff --git a/doc/user/search/img/issues_any_assignee.png b/doc/user/search/img/issues_any_assignee.png
deleted file mode 100644
index 2f902bcc66c..00000000000
--- a/doc/user/search/img/issues_any_assignee.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/img/issues_author.png b/doc/user/search/img/issues_author.png
deleted file mode 100644
index 792f9746db6..00000000000
--- a/doc/user/search/img/issues_author.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/img/multiple_assignees.png b/doc/user/search/img/multiple_assignees.png
new file mode 100644
index 00000000000..5c46f3dda46
--- /dev/null
+++ b/doc/user/search/img/multiple_assignees.png
Binary files differ
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index 705983cce2a..bb6c48471c7 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -84,6 +84,12 @@ You can view recent searches by clicking on the little arrow-clock icon, which i
Individual filters can be removed by clicking on the filter's (x) button or backspacing. The entire search filter can be cleared by clicking on the search box's (x) button.
+## Filtering with multiple filters of the same type
+
+Some filters can be added multiple times. These include but are not limited to assignees and labels. When you filter with these multiple filters of the same type, the AND logic is applied. For example, if you were filtering `assignee:@sam assignee:@sarah`, your results will only include entries whereby the assignees are assigned to both Sam and Sarah are returned.
+
+![multiple assignees filtering](img/multiple_assignees.png)
+
### Shortcut
You'll also find a shortcut on the search field on the top-right of the project's dashboard to
@@ -136,3 +142,18 @@ you'll be able to, besides filtering them by **Name**, **Author**, **Assignee**,
and **Labels**, select multiple issues to add to a list of your choice:
![search and select issues to add to board](img/search_issues_board.png)
+
+## Advanced Global Search **[STARTER]**
+
+Leverage Elasticsearch for faster, more advanced code search across your entire
+GitLab instance.
+
+[Learn how to use the Advanced Global Search.](advanced_global_search.md)
+
+## Advanced Syntax Search **[STARTER]**
+
+Use advanced queries for more targeted search results.
+
+[Learn how to use the Advanced Syntax Search.](advanced_search_syntax.md)
+
+[ee]: https://about.gitlab.com/pricing/
diff --git a/doc/workflow/README.md b/doc/workflow/README.md
index 272f7807ac0..40e2486ace5 100644
--- a/doc/workflow/README.md
+++ b/doc/workflow/README.md
@@ -13,12 +13,15 @@ comments: false
- [Groups](../user/group/index.md)
- Issues - The GitLab Issue Tracker is an advanced and complete tool for
tracking the evolution of a new idea or the process of solving a problem.
+ - [Exporting Issues](../user/project/issues/csv_export.md) **[STARTER]** Export issues as a CSV, emailed as an attachment.
- [Confidential issues](../user/project/issues/confidential_issues.md)
- [Due date for issues](../user/project/issues/due_dates.md)
- [Issue Board](../user/project/issue_board.md)
- [Keyboard shortcuts](shortcuts.md)
- [File finder](file_finder.md)
+- [File lock](../user/project/file_lock.md) **[PREMIUM]**
- [Labels](../user/project/labels.md)
+- [Issue weight](issue_weight.md) **[STARTER]**
- [Notification emails](notifications.md)
- [Projects](../user/project/index.md)
- [Project forking workflow](forking_workflow.md)
@@ -41,6 +44,9 @@ comments: false
- [Merge requests versions](../user/project/merge_requests/versions.md)
- ["Work In Progress" merge requests](../user/project/merge_requests/work_in_progress_merge_requests.md)
- [Fast-forward merge requests](../user/project/merge_requests/fast_forward_merge.md)
+ - [Merge request approvals](../user/project/merge_requests/merge_request_approvals.md) **[STARTER]**
+- [Repository mirroring](repository_mirroring.md) **[STARTER]**
+- [Service Desk](../user/project/service_desk.md) **[PREMIUM]**
- [Manage large binaries with Git LFS](lfs/manage_large_binaries_with_git_lfs.md)
- [Importing from SVN, GitHub, Bitbucket, etc](importing/README.md)
- [Todos](todos.md)
diff --git a/doc/workflow/award_emoji.png b/doc/workflow/award_emoji.png
deleted file mode 100644
index 1ad634a343e..00000000000
--- a/doc/workflow/award_emoji.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/ff_merge.md b/doc/workflow/ff_merge.md
new file mode 100644
index 00000000000..11e9e1bbd6b
--- /dev/null
+++ b/doc/workflow/ff_merge.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../user/project/merge_requests/fast_forward_merge.md'
+---
+
+This document was moved to [user/project/merge_requests/fast_forward_merge](../user/project/merge_requests/fast_forward_merge.md).
diff --git a/doc/workflow/git_annex.md b/doc/workflow/git_annex.md
new file mode 100644
index 00000000000..84d25951908
--- /dev/null
+++ b/doc/workflow/git_annex.md
@@ -0,0 +1,238 @@
+# Git annex
+
+> **Warning:** GitLab has [completely
+removed][deprecate-annex-issue] in GitLab 9.0 (2017/03/22).
+Read through the [migration guide from git-annex to git-lfs][guide].
+
+The biggest limitation of Git, compared to some older centralized version
+control systems, has been the maximum size of the repositories.
+
+The general recommendation is to not have Git repositories larger than 1GB to
+preserve performance. Although GitLab has no limit (some repositories in GitLab
+are over 50GB!), we subscribe to the advice to keep repositories as small as
+you can.
+
+Not being able to version control large binaries is a big problem for many
+larger organizations.
+Videos, photos, audio, compiled binaries and many other types of files are too
+large. As a workaround, people keep artwork-in-progress in a Dropbox folder and
+only check in the final result. This results in using outdated files, not
+having a complete history and increases the risk of losing work.
+
+This problem is solved in GitLab Enterprise Edition by integrating the
+[git-annex] application.
+
+`git-annex` allows managing large binaries with Git without checking the
+contents into Git.
+You check-in only a symlink that contains the SHA-1 of the large binary. If you
+need the large binary, you can sync it from the GitLab server over `rsync`, a
+very fast file copying tool.
+
+## GitLab git-annex Configuration
+
+`git-annex` is disabled by default in GitLab. Below you will find the
+configuration options required to enable it.
+
+### Requirements
+
+`git-annex` needs to be installed both on the server and the client side.
+
+For Debian-like systems (e.g., Debian, Ubuntu) this can be achieved by running:
+
+```
+sudo apt-get update && sudo apt-get install git-annex
+```
+
+For RedHat-like systems (e.g., CentOS, RHEL) this can be achieved by running:
+
+```
+sudo yum install epel-release && sudo yum install git-annex
+```
+
+### Configuration for Omnibus packages
+
+For omnibus-gitlab packages, only one configuration setting is needed.
+The Omnibus package will internally set the correct options in all locations.
+
+1. In `/etc/gitlab/gitlab.rb` add the following line:
+
+ ```ruby
+ gitlab_shell['git_annex_enabled'] = true
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+### Configuration for installations from source
+
+There are 2 settings to enable git-annex on your GitLab server.
+
+One is located in `config/gitlab.yml` of the GitLab repository and the other
+one is located in `config.yml` of gitlab-shell.
+
+1. In `config/gitlab.yml` add or edit the following lines:
+
+ ```yaml
+ gitlab_shell:
+ git_annex_enabled: true
+ ```
+
+1. In `config.yml` of gitlab-shell add or edit the following lines:
+
+ ```yaml
+ git_annex_enabled: true
+ ```
+
+1. Save the files and [restart GitLab][] for the changes to take effect.
+
+## Using GitLab git-annex
+
+> **Note:**
+> Your Git remotes must be using the SSH protocol, not HTTP(S).
+
+Here is an example workflow of uploading a very large file and then checking it
+into your Git repository:
+
+```bash
+git clone git@example.com:group/project.git
+
+git annex init 'My Laptop' # initialize the annex project and give an optional description
+cp ~/tmp/debian.iso ./ # copy a large file into the current directory
+git annex add debian.iso # add the large file to git annex
+git commit -am "Add Debian iso" # commit the file metadata
+git annex sync --content # sync the Git repo and large file to the GitLab server
+```
+
+The output should look like this:
+
+```
+commit
+On branch master
+Your branch is ahead of 'origin/master' by 1 commit.
+ (use "git push" to publish your local commits)
+nothing to commit, working tree clean
+ok
+pull origin
+remote: Counting objects: 5, done.
+remote: Compressing objects: 100% (4/4), done.
+remote: Total 5 (delta 2), reused 0 (delta 0)
+Unpacking objects: 100% (5/5), done.
+From example.com:group/project
+ 497842b..5162f80 git-annex -> origin/git-annex
+ok
+(merging origin/git-annex into git-annex...)
+(recording state in git...)
+copy debian.iso (checking origin...) (to origin...)
+SHA256E-s26214400--8092b3d482fb1b7a5cf28c43bc1425c8f2d380e86869c0686c49aa7b0f086ab2.iso
+ 26,214,400 100% 638.88kB/s 0:00:40 (xfr#1, to-chk=0/1)
+ok
+pull origin
+ok
+(recording state in git...)
+push origin
+Counting objects: 15, done.
+Delta compression using up to 4 threads.
+Compressing objects: 100% (13/13), done.
+Writing objects: 100% (15/15), 1.64 KiB | 0 bytes/s, done.
+Total 15 (delta 1), reused 0 (delta 0)
+To example.com:group/project.git
+ * [new branch] git-annex -> synced/git-annex
+ * [new branch] master -> synced/master
+ok
+```
+
+Your files can be found in the `master` branch, but you'll notice that there
+are more branches created by the `annex sync` command.
+
+Git Annex will also create a new directory at `.git/annex/` and will record the
+tracked files in the `.git/config` file. The files you assign to be tracked
+with `git-annex` will not affect the existing `.git/config` records. The files
+are turned into symbolic links that point to data in `.git/annex/objects/`.
+
+The `debian.iso` file in the example will contain the symbolic link:
+
+```
+.git/annex/objects/ZW/1k/SHA256E-s82701--6384039733b5035b559efd5a2e25a493ab6e09aabfd5162cc03f6f0ec238429d.png/SHA256E-s82701--6384039733b5035b559efd5a2e25a493ab6e09aabfd5162cc03f6f0ec238429d.iso
+```
+
+Use `git annex info` to retrieve the information about the local copy of your
+repository.
+
+---
+
+Downloading a single large file is also very simple:
+
+```bash
+git clone git@gitlab.example.com:group/project.git
+
+git annex sync # sync Git branches but not the large file
+git annex get debian.iso # download the large file
+```
+
+To download all files:
+
+```bash
+git clone git@gitlab.example.com:group/project.git
+
+git annex sync --content # sync Git branches and download all the large files
+```
+
+By using `git-annex` without GitLab, anyone that can access the server can also
+access the files of all projects, but GitLab Annex ensures that you can only
+access files of projects you have access to (developer, maintainer, or owner role).
+
+## How it works
+
+Internally GitLab uses [GitLab Shell] to handle SSH access and this was a great
+integration point for `git-annex`.
+There is a setting in gitlab-shell so you can disable GitLab Annex support
+if you want to.
+
+## Troubleshooting tips
+
+Differences in version of `git-annex` on the GitLab server and on local machines
+can cause `git-annex` to raise unpredicted warnings and errors.
+
+Consult the [Annex upgrade page][annex-upgrade] for more information about
+the differences between versions. You can find out which version is installed
+on your server by navigating to <https://pkgs.org/download/git-annex> and
+searching for your distribution.
+
+Although there is no general guide for `git-annex` errors, there are a few tips
+on how to go around the warnings.
+
+### git-annex-shell: Not a git-annex or gcrypt repository.
+
+This warning can appear on the initial `git annex sync --content` and is caused
+by differences in `git-annex-shell`. You can read more about it
+[in this git-annex issue][issue].
+
+One important thing to note is that despite the warning, the `sync` succeeds
+and the files are pushed to the GitLab repository.
+
+If you get hit by this, you can run the following command inside the repository
+that the warning was raised:
+
+```
+git config remote.origin.annex-ignore false
+```
+
+Consecutive runs of `git annex sync --content` **should not** produce this
+warning and the output should look like this:
+
+```
+commit ok
+pull origin
+ok
+pull origin
+ok
+push origin
+```
+
+[annex-upgrade]: https://git-annex.branchable.com/upgrades/
+[deprecate-annex-issue]: https://gitlab.com/gitlab-org/gitlab-ee/issues/1648
+[git-annex]: https://git-annex.branchable.com/ "git-annex website"
+[gitlab shell]: https://gitlab.com/gitlab-org/gitlab-shell "GitLab Shell repository"
+[guide]: lfs/migrate_from_git_annex_to_git_lfs.html
+[issue]: https://git-annex.branchable.com/forum/Error_from_git-annex-shell_on_creation_of_gcrypt_special_remote/ "git-annex issue"
+[reconfigure GitLab]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
+[restart GitLab]: ../administration/restart_gitlab.md#installations-from-source
diff --git a/doc/workflow/git_lfs.md b/doc/workflow/git_lfs.md
new file mode 100644
index 00000000000..da217b0a5da
--- /dev/null
+++ b/doc/workflow/git_lfs.md
@@ -0,0 +1,5 @@
+---
+redirect_to: 'lfs/manage_large_binaries_with_git_lfs.md'
+---
+
+This document was moved to [another location](lfs/manage_large_binaries_with_git_lfs.md).
diff --git a/doc/workflow/gitlab_flow.md b/doc/workflow/gitlab_flow.md
index 1b9fb504b15..3e24557591c 100644
--- a/doc/workflow/gitlab_flow.md
+++ b/doc/workflow/gitlab_flow.md
@@ -27,6 +27,8 @@ People have a hard time figuring out which branch has the latest code, or which
Frequently, the reaction to this problem is to adopt a standardized pattern such as [Git flow](https://nvie.com/posts/a-successful-git-branching-model/) and [GitHub flow](http://scottchacon.com/2011/08/31/github-flow.html).
We think there is still room for improvement. In this document, we describe a set of practices we call GitLab flow.
+For a video introduction of how this works in GitLab, see [GitLab Flow](https://youtu.be/InKNIvky2KE).
+
## Git flow and its problems
![Git Flow timeline by Vincent Driessen, used with permission](gitdashflow.png)
@@ -166,7 +168,7 @@ This branch is the place for any work related to this change.
NOTE: **Note:**
The name of a branch might be dictated by organizational standards.
-For example, in GitLab, any branches in GitLab EE that are equivalent to branches in GitLab CE [must end in `-ee`](https://docs.gitlab.com/ee/development/automatic_ce_ee_merge.html#cherry-picking-from-ce-to-ee).
+For example, in GitLab, any branches in GitLab EE that are equivalent to branches in GitLab CE [must end in `-ee`](../development/automatic_ce_ee_merge.md#cherry-picking-from-ce-to-ee).
When you are done or want to discuss the code, open a merge request.
A merge request is an online place to discuss the change and review the code.
diff --git a/doc/workflow/img/copy_ssh_public_key_button.png b/doc/workflow/img/copy_ssh_public_key_button.png
new file mode 100644
index 00000000000..e20dae09a4d
--- /dev/null
+++ b/doc/workflow/img/copy_ssh_public_key_button.png
Binary files differ
diff --git a/doc/workflow/img/new_branch_from_issue.png b/doc/workflow/img/new_branch_from_issue.png
deleted file mode 100644
index 286d775bb9e..00000000000
--- a/doc/workflow/img/new_branch_from_issue.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/img/notification_global_settings.png b/doc/workflow/img/notification_global_settings.png
index 8a5494d16a8..72f7418f1f8 100644
--- a/doc/workflow/img/notification_global_settings.png
+++ b/doc/workflow/img/notification_global_settings.png
Binary files differ
diff --git a/doc/workflow/img/repository_mirroring_pull_settings_upper.png b/doc/workflow/img/repository_mirroring_pull_settings_upper.png
index c60354fdca7..8e15b5a0784 100644
--- a/doc/workflow/img/repository_mirroring_pull_settings_upper.png
+++ b/doc/workflow/img/repository_mirroring_pull_settings_upper.png
Binary files differ
diff --git a/doc/workflow/issue_weight.md b/doc/workflow/issue_weight.md
new file mode 100644
index 00000000000..267160dae2a
--- /dev/null
+++ b/doc/workflow/issue_weight.md
@@ -0,0 +1,22 @@
+# Issue Weight **[STARTER]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/76)
+> in [GitLab Starter](https://about.gitlab.com/pricing/) 8.3.
+
+When you have a lot of issues, it can be hard to get an overview.
+By adding a weight to each issue, you can get a better idea of how much time,
+value or complexity a given issue has or will cost.
+
+You can set the weight of an issue during its creation, by simply changing the
+value in the dropdown menu. You can set it to a non-negative integer
+value from 0, 1, 2, and so on. (The database stores a 4-byte value, so the
+upper bound is essentially limitless).
+You can remove weight from an issue
+as well.
+
+This value will appear on the right sidebar of an individual issue, as well as
+in the issues page next to a distinctive balance scale icon.
+
+As an added bonus, you can see the total sum of all issues on the milestone page.
+
+![issue page](issue_weight/issue.png)
diff --git a/doc/workflow/issue_weight/issue.png b/doc/workflow/issue_weight/issue.png
new file mode 100644
index 00000000000..3800b5940b8
--- /dev/null
+++ b/doc/workflow/issue_weight/issue.png
Binary files differ
diff --git a/doc/workflow/lfs/images/git-annex-branches.png b/doc/workflow/lfs/images/git-annex-branches.png
new file mode 100644
index 00000000000..3d614f68177
--- /dev/null
+++ b/doc/workflow/lfs/images/git-annex-branches.png
Binary files differ
diff --git a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
index da0243705aa..202f2e39975 100644
--- a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
+++ b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
@@ -250,6 +250,7 @@ If you are storing LFS files outside of GitLab you can disable LFS on the projec
It is possible to host LFS objects externally by setting a custom LFS url with `git config -f .lfsconfig lfs.url https://example.com/<project>.git/info/lfs`.
-Because GitLab verifies the existence of objects referenced by LFS pointers, push will fail when LFS is enabled for the project.
+You might choose to do this if you are using an appliance like a Sonatype Nexus to store LFS data. If you choose to use an external LFS store,
+GitLab will not be able to verify LFS objects which means that pushes will fail if you have GitLab LFS support enabled.
-LFS can be disabled from the [Project settings](../../user/project/settings/index.md).
+To stop push failure, LFS support can be disabled in the [Project settings](../../user/project/settings/index.md). This means you will lose GitLab LFS value-adds (Verifying LFS objects, UI integration for LFS).
diff --git a/doc/workflow/lfs/migrate_from_git_annex_to_git_lfs.md b/doc/workflow/lfs/migrate_from_git_annex_to_git_lfs.md
new file mode 100644
index 00000000000..71c73e3dffe
--- /dev/null
+++ b/doc/workflow/lfs/migrate_from_git_annex_to_git_lfs.md
@@ -0,0 +1,255 @@
+# Migration guide from Git Annex to Git LFS
+
+>**Note:**
+Git Annex support [has been removed][issue-remove-annex] in GitLab Enterprise
+Edition 9.0 (2017/03/22).
+
+Both [Git Annex][] and [Git LFS][] are tools to manage large files in Git.
+
+## History
+
+Git Annex [was introduced in GitLab Enterprise Edition 7.8][post-3], at a time
+where Git LFS didn't yet exist. A few months later, GitLab brought support for
+Git LFS in [GitLab 8.2][post-2] and is available for both Community and
+Enterprise editions.
+
+## Differences between Git Annex and Git LFS
+
+Some items below are general differences between the two protocols and some are
+ones that GitLab developed.
+
+- Git Annex works only through SSH, whereas Git LFS works both with SSH and HTTPS
+ (SSH support was added in GitLab 8.12).
+- Annex files are stored in a sub-directory of the normal repositories, whereas
+ LFS files are stored outside of the repositories in a place you can define.
+- Git Annex requires a more complex setup, but has much more options than Git
+ LFS. You can compare the commands each one offers by running `man git-annex`
+ and `man git-lfs`.
+- Annex files cannot be browsed directly in GitLab's interface, whereas LFS
+ files can.
+
+## Migration steps
+
+>**Note:**
+Since Git Annex files are stored in a sub-directory of the normal repositories
+(`.git/annex/objects`) and LFS files are stored outside of the repositories,
+they are not compatible as they are using a different scheme. Therefore, the
+migration has to be done manually per repository.
+
+There are basically two steps you need to take in order to migrate from Git
+Annex to Git LFS.
+
+### TL; DR
+
+If you know what you are doing and want to skip the reading, this is what you
+need to do (we assume you have [git-annex enabled](../git_annex.md#using-gitlab-git-annex) in your
+repository and that you have made backups in case something goes wrong).
+Fire up a terminal, navigate to your Git repository and:
+
+
+1. Disable `git-annex`:
+
+ ```bash
+ git annex sync --content
+ git annex direct
+ git annex uninit
+ git annex indirect
+ ```
+
+1. Enable `git-lfs`:
+
+ ```
+ git lfs install
+ git lfs track <files>
+ git add .
+ git commit -m "commit message"
+ git push
+ ```
+
+### Disabling Git Annex in your repo
+
+Before changing anything, make sure you have a backup of your repository first.
+There are a couple of ways to do that, but you can simply clone it to another
+local path and maybe push it to GitLab if you want a remote backup as well.
+Here you'll find a guide on
+[how to back up a **git-annex** repository to an external hard drive][bkp-ext-drive].
+
+Since Annex files are stored as objects with symlinks and cannot be directly
+modified, we need to first remove those symlinks.
+
+>**Note:**
+Make sure the you read about the [`direct` mode][annex-direct] as it contains
+useful information that may fit in your use case. Note that `annex direct` is
+deprecated in Git Annex version 6, so you may need to upgrade your repository
+if the server also has Git Annex 6 installed. Read more in the
+[Git Annex troubleshooting tips](../git_annex.md#troubleshooting-tips) section.
+
+1. Backup your repository
+
+ ```bash
+ cd repository
+ git annex sync --content
+ cd ..
+ git clone repository repository-backup
+ cd repository-backup
+ git annex get
+ cd ..
+ ```
+
+1. Use `annex direct`:
+
+ ```bash
+ cd repository
+ git annex direct
+ ```
+
+ The output should be similar to this:
+
+ ```bash
+ commit
+ On branch master
+ Your branch is up-to-date with 'origin/master'.
+ nothing to commit, working tree clean
+ ok
+ direct debian.iso ok
+ direct ok
+ ```
+
+1. Disable Git Annex with [`annex uninit`][uninit]:
+
+ ```bash
+ git annex uninit
+ ```
+
+ The output should be similar to this:
+
+ ```bash
+ unannex debian.iso ok
+ Deleted branch git-annex (was 2534d2c).
+ ```
+
+ This will `unannex` every file in the repository, leaving the original files.
+
+1. Switch back to `indirect` mode:
+
+ ```bash
+ git annex indirect
+ ```
+
+ The output should be similar to this:
+
+ ```bash
+ (merging origin/git-annex into git-annex...)
+ (recording state in git...)
+ commit (recording state in git...)
+
+ ok
+ (recording state in git...)
+ [master fac3194] commit before switching to indirect mode
+ 1 file changed, 1 deletion(-)
+ delete mode 120000 alpine-virt-3.4.4-x86_64.iso
+ ok
+ indirect ok
+ ok
+ ```
+
+---
+
+At this point, you have two options. Either add, commit and push the files
+directly back to GitLab or switch to Git LFS. We will tackle the LFS switch in
+the next section.
+
+### Enabling Git LFS in your repo
+
+Git LFS is enabled by default on all GitLab products (GitLab CE, GitLab EE,
+GitLab.com), therefore, you don't need to do anything server-side.
+
+1. First, make sure you have `git-lfs` installed locally:
+
+ ```bash
+ git lfs help
+ ```
+
+ If the terminal doesn't prompt you with a full response on `git-lfs` commands,
+ [install the Git LFS client][install-lfs] first.
+
+1. Inside the repo, run the following command to initiate LFS:
+
+ ```bash
+ git lfs install
+ ```
+
+1. Enable `git-lfs` for the group of files you want to track. You
+ can track specific files, all files containing the same extension, or an
+ entire directory:
+
+ ```bash
+ git lfs track images/01.png # per file
+ git lfs track **/*.png # per extension
+ git lfs track images/ # per directory
+ ```
+
+ Once you do that, run `git status` and you'll see `.gitattributes` added
+ to your repo. It collects all file patterns that you chose to track via
+ `git-lfs`.
+
+1. Add the files, commit and push them to GitLab:
+
+ ```bash
+ git add .
+ git commit -m "commit message"
+ git push
+ ```
+
+ If your remote is set up with HTTP, you will be asked to enter your login
+ credentials. If you have [2FA enabled](../../user/profile/account/two_factor_authentication.md), make sure to use a
+ [personal access token](../../user/profile/account/two_factor_authentication.md#personal-access-tokens)
+ instead of your password.
+
+## Removing the Git Annex branches
+
+After the migration finishes successfully, you can remove all `git-annex`
+related branches from your repository.
+
+On GitLab, navigate to your project's **Repository âž” Branches** and delete all
+branches created by Git Annex: `git-annex`, and all under `synced/`.
+
+![repository branches](images/git-annex-branches.png)
+
+You can also do this on the commandline with:
+
+ ```bash
+ git branch -d synced/master
+ git branch -d synced/git-annex
+ git push origin :synced/master
+ git push origin :synced/git-annex
+ git push origin :git-annex
+ git remote prune origin
+ ```
+
+If there are still some Annex objects inside your repository (`.git/annex/`)
+or references inside `.git/config`, run `annex uninit` again:
+
+```bash
+git annex uninit
+```
+
+## Further Reading
+
+- (Blog Post) [Getting Started with Git FLS][post-1]
+- (Blog Post) [Announcing LFS Support in GitLab][post-2]
+- (Blog Post) [GitLab Annex Solves the Problem of Versioning Large Binaries with Git][post-3]
+- (GitLab Docs) [Git Annex](../git_annex.md)
+- (GitLab Docs) [Git LFS](manage_large_binaries_with_git_lfs.md)
+
+[annex-direct]: https://git-annex.branchable.com/direct_mode/
+[bkp-ext-drive]: https://www.thomas-krenn.com/en/wiki/Git-annex_Repository_on_an_External_Hard_Drive
+[Git Annex]: http://git-annex.branchable.com/
+[Git LFS]: https://git-lfs.github.com/
+[install-lfs]: https://git-lfs.github.com/
+[issue-remove-annex]: https://gitlab.com/gitlab-org/gitlab-ee/issues/1648
+[lfs-track]: https://about.gitlab.com/2017/01/30/getting-started-with-git-lfs-tutorial/#tracking-files-with-lfs
+[post-1]: https://about.gitlab.com/2017/01/30/getting-started-with-git-lfs-tutorial/
+[post-2]: https://about.gitlab.com/2015/11/23/announcing-git-lfs-support-in-gitlab/
+[post-3]: https://about.gitlab.com/2015/02/17/gitlab-annex-solves-the-problem-of-versioning-large-binaries-with-git/
+[uninit]: https://git-annex.branchable.com/git-annex-uninit/
diff --git a/doc/workflow/merge_request_approvals.md b/doc/workflow/merge_request_approvals.md
new file mode 100644
index 00000000000..bfcd8faf236
--- /dev/null
+++ b/doc/workflow/merge_request_approvals.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../user/project/merge_requests/merge_request_approvals.md'
+---
+
+This document was moved to [another location](../user/project/merge_requests/merge_request_approvals.md).
diff --git a/doc/workflow/notifications.md b/doc/workflow/notifications.md
index 6ce789998a4..5d560f2e000 100644
--- a/doc/workflow/notifications.md
+++ b/doc/workflow/notifications.md
@@ -16,12 +16,16 @@ Notification settings are divided into three groups:
Each of these settings have levels of notification:
+- Global: For groups and projects, notifications as per global settings.
- Watch: Receive notifications for any activity.
-- On Mention: Receive notifications when `@mentioned` in comments.
- Participate: Receive notifications for threads you have participated in.
+- On Mention: Receive notifications when `@mentioned` in comments.
- Disabled: Turns off notifications.
- Custom: Receive notifications for custom selected events.
-- Global: For groups and projects, notifications as per global settings.
+
+> Introduced in GitLab 12.0
+
+You can also select an email address to receive notifications for each group you belong to.
### Global Settings
@@ -73,40 +77,43 @@ Below is the table of events users can be notified of:
| Group access level changed | User | Sent when user group access level is changed |
| Project moved | Project members [1] | [1] not disabled |
-### Issue / Merge request events
+### Issue / Epics / Merge request events
In most of the below cases, the notification will be sent to:
- Participants:
- the author and assignee of the issue/merge request
- authors of comments on the issue/merge request
- - anyone mentioned by `@username` in the issue/merge request title or description
- - anyone mentioned by `@username` in any of the comments on the issue/merge request
- ...with notification level "Participating" or higher
+ - anyone mentioned by `@username` in the title or description of the issue, merge request or epic **[ULTIMATE]**
+ - anyone with notification level "Participating" or higher that is mentioned by `@username`
+ in any of the comments on the issue, merge request, or epic **[ULTIMATE]**
- Watchers: users with notification level "Watch"
-- Subscribers: anyone who manually subscribed to the issue/merge request
+- Subscribers: anyone who manually subscribed to the issue, merge request, or epic **[ULTIMATE]**
- Custom: Users with notification level "custom" who turned on notifications for any of the events present in the table below
| Event | Sent to |
|------------------------|---------|
-| New issue | |
-| Close issue | |
+| New issue | |
+| Close issue | |
| Reassign issue | The above, plus the old assignee |
-| Reopen issue | |
+| Reopen issue | |
| Due issue | Participants and Custom notification level with this event selected |
| Change milestone issue | Subscribers, participants mentioned, and Custom notification level with this event selected |
| Remove milestone issue | Subscribers, participants mentioned, and Custom notification level with this event selected |
-| New merge request | |
+| New merge request | |
| Push to merge request | Participants and Custom notification level with this event selected |
| Reassign merge request | The above, plus the old assignee |
-| Close merge request | |
-| Reopen merge request | |
-| Merge merge request | |
+| Close merge request | |
+| Reopen merge request | |
+| Merge merge request | |
| Change milestone merge request | Subscribers, participants mentioned, and Custom notification level with this event selected |
| Remove milestone merge request | Subscribers, participants mentioned, and Custom notification level with this event selected |
| New comment | The above, plus anyone mentioned by `@username` in the comment, with notification level "Mention" or higher |
| Failed pipeline | The author of the pipeline |
| Successful pipeline | The author of the pipeline, if they have the custom notification setting for successful pipelines set |
+| New epic **[ULTIMATE]** | |
+| Close epic **[ULTIMATE]** | |
+| Reopen epic **[ULTIMATE]** | |
In addition, if the title or description of an Issue or Merge Request is
changed, notifications will be sent to any **new** mentions by `@username` as
diff --git a/doc/workflow/rebase_before_merge.md b/doc/workflow/rebase_before_merge.md
new file mode 100644
index 00000000000..10e768d3371
--- /dev/null
+++ b/doc/workflow/rebase_before_merge.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../user/project/merge_requests/fast_forward_merge.md'
+---
+
+This document was moved to [another location](../user/project/merge_requests/fast_forward_merge.md).
diff --git a/doc/workflow/repository_mirroring.md b/doc/workflow/repository_mirroring.md
index 9fcadbf3bee..5a24c254ed1 100644
--- a/doc/workflow/repository_mirroring.md
+++ b/doc/workflow/repository_mirroring.md
@@ -99,6 +99,10 @@ The repository will push soon. To force a push, click the appropriate button.
## Pulling from a remote repository **[STARTER]**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/51) in GitLab Enterprise Edition 8.2.
+> [Added Git LFS support](https://gitlab.com/gitlab-org/gitlab-ee/issues/10871) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.11.
+
+NOTE: **Note:** This feature [is available for free](https://gitlab.com/gitlab-org/gitlab-ee/issues/10361) to
+GitLab.com users until September 22nd, 2019.
You can set up a repository to automatically have its branches, tags, and commits updated from an
upstream repository.
@@ -222,8 +226,10 @@ being injected into your mirror, or your password being stolen.
### SSH public key authentication
To use SSH public key authentication, you'll also need to choose that option
-from the **Authentication method** dropdown. GitLab will generate a 4096-bit RSA
-key and display the public component of that key to you.
+from the **Authentication method** dropdown. When the mirror is created,
+GitLab generates a 4096-bit RSA key that can be copied by clicking the **Copy SSH public key** button.
+
+![Repository mirroring copy SSH public key to clipboard button](img/copy_ssh_public_key_button.png)
You then need to add the public SSH key to the other repository's configuration:
@@ -280,10 +286,10 @@ project mirroring again by [Forcing an update](#forcing-an-update-core).
[GitLab Starter](https://about.gitlab.com/pricing/) 10.3.
Pull mirroring uses polling to detect new branches and commits added upstream, often minutes
-afterwards. If you notify GitLab by [API](https://docs.gitlab.com/ee/api/projects.html#start-the-pull-mirroring-process-for-a-project),
+afterwards. If you notify GitLab by [API](https://docs.gitlab.com/ee/api/projects.html#start-the-pull-mirroring-process-for-a-project-starter),
updates will be pulled immediately.
-For more information, see [Start the pull mirroring process for a Project](https://docs.gitlab.com/ee/api/projects.html#start-the-pull-mirroring-process-for-a-project).
+For more information, see [Start the pull mirroring process for a Project](https://docs.gitlab.com/ee/api/projects.html#start-the-pull-mirroring-process-for-a-project-starter).
## Forcing an update **[CORE]**
diff --git a/doc/workflow/share_with_group.png b/doc/workflow/share_with_group.png
deleted file mode 100644
index 2c47625e29a..00000000000
--- a/doc/workflow/share_with_group.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/shortcuts.md b/doc/workflow/shortcuts.md
index 6ed6b0bda66..5068b5d4d20 100644
--- a/doc/workflow/shortcuts.md
+++ b/doc/workflow/shortcuts.md
@@ -1,6 +1,6 @@
# GitLab keyboard shortcuts
-You can see GitLab's keyboard shortcuts by using 'shift + ?'
+You can see GitLab's keyboard shortcuts by using <kbd>shift</kbd> + <kbd>?</kbd>
## Global Shortcuts
@@ -85,6 +85,14 @@ You can see GitLab's keyboard shortcuts by using 'shift + ?'
| <kbd>]</kbd> or <kbd>j</kbd> | Move to next file |
| <kbd>[</kbd> or <kbd>k</kbd> | Move to previous file |
+## Epics **[ULTIMATE]**
+
+| Keyboard Shortcut | Description |
+| ----------------- | ----------- |
+| <kbd>r</kbd> | Reply (quoting selected text) |
+| <kbd>e</kbd> | Edit description |
+| <kbd>l</kbd> | Change label |
+
## Wiki pages
| Keyboard Shortcut | Description |
diff --git a/doc/workflow/timezone.md b/doc/workflow/timezone.md
index 338b3a32265..da51c0f2c93 100644
--- a/doc/workflow/timezone.md
+++ b/doc/workflow/timezone.md
@@ -1,31 +1,39 @@
# Changing your time zone
The global time zone configuration parameter can be changed in `config/gitlab.yml`:
+
```
- # time_zone: 'UTC'
+# time_zone: 'UTC'
```
-Uncomment and customize if you want to change the default time zone of GitLab application.
+Uncomment and customize if you want to change the default time zone of the GitLab application.
+
+
+## Viewing available timezones
To see all available time zones, run `bundle exec rake time:zones:all`.
-With Omnibus installations, run `gitlab-rake time:zones:all`.
+For Omnibus installations, run `gitlab-rake time:zones:all`.
+
+NOTE: **Note:**
+Currently, this rake task does not list timezones in TZInfo format required by GitLab Omnibus during a reconfigure: [#58672](https://gitlab.com/gitlab-org/gitlab-ce/issues/58672).
## Changing time zone in omnibus installations
GitLab defaults its time zone to UTC. It has a global timezone configuration parameter in `/etc/gitlab/gitlab.rb`.
-To update, add the time zone that best applies to your location. Here are two examples:
+To obtain a list of timezones, log in to your GitLab application server and run a command that generates a list of timezones in TZInfo format for the server. For example, install `timedatectl` and run `timedatectl list-timezones`.
+
+To update, add the timezone that best applies to your location. For example:
+
```
gitlab_rails['time_zone'] = 'America/New_York'
```
-or
-```
-gitlab_rails['time_zone'] = 'Europe/Brussels'
-```
-After you added this field, reconfigure and restart:
+After adding the configuration parameter, reconfigure and restart your GitLab instance:
+
```
gitlab-ctl reconfigure
gitlab-ctl restart
```
+
diff --git a/doc/workflow/todos.md b/doc/workflow/todos.md
index 830f17aa7f2..32907db4f46 100644
--- a/doc/workflow/todos.md
+++ b/doc/workflow/todos.md
@@ -25,9 +25,8 @@ will still be shown in the body of the _To do_ tab.
A Todo appears in your Todos dashboard when:
-- an issue or merge request is assigned to you,
-- you are `@mentioned` in an issue or merge request, be it the description of
- the issue/merge request or in a comment,
+- an issue or merge request is assigned to you
+- you are `@mentioned` in the description or in a comment of an issue, merge request, or epic **[ULTIMATE]**
- you are `@mentioned` in a comment on a commit,
- a job in the CI pipeline running for your merge request failed, but this
job is not allowed to fail.
@@ -63,14 +62,14 @@ for filtering; otherwise, they appear as normal.
### Manually creating a Todo
-You can also add an issue or merge request to your Todos dashboard by clicking
-the "Add todo" button in the issue or merge request sidebar.
+You can also add an issue, merge request or epic to your Todos dashboard by clicking
+the "Add todo" button in the sidebar of the issue, merge request, or epic **[ULTIMATE]**.
![Adding a Todo from the issuable sidebar](img/todos_add_todo_sidebar.png)
## Marking a Todo as done
-Any action to the corresponding issue or merge request will mark your Todo as
+Any action to the corresponding issue, merge request or epic **[ULTIMATE]** will mark your Todo as
**Done**. Actions that dismiss Todos include:
- changing the assignee
@@ -84,10 +83,10 @@ Todos are personal, and they're only marked as done if the action is coming from
you. If you close the issue or merge request, your Todo will automatically
be marked as done.
-If someone else closes, merges, or takes action on the issue or merge
+If someone else closes, merges, or takes action on the issue, epic or merge
request, your Todo will remain pending. This prevents other users from closing issues without you being notified.
-There is just one Todo per issue or merge request, so mentioning a user a
+There is just one Todo per issue, epic or merge request, so mentioning a user a
hundred times in an issue will only trigger one Todo.
---
@@ -97,7 +96,7 @@ corresponding **Done** button, and it will disappear from your Todo list.
![A Todo in the Todos dashboard](img/todo_list_item.png)
-A Todo can also be marked as done from the issue or merge request sidebar using
+A Todo can also be marked as done from the issue, merge request or epic sidebar using
the "Mark todo as done" button.
![Mark todo as done from the issuable sidebar](img/todos_mark_done_sidebar.png)
@@ -114,7 +113,7 @@ There are four kinds of filters you can use on your Todos dashboard.
| Project | Filter by project |
| Group | Filter by group |
| Author | Filter by the author that triggered the Todo |
-| Type | Filter by issue or merge request |
+| Type | Filter by issue, merge request, or epic **[ULTIMATE]** |
| Action | Filter by the action that triggered the Todo |
You can also filter by more than one of these at the same time. The possible Actions are `Any Action`, `Assigned`, `Mentioned`, `Added`, `Pipelines`, and `Directly Addressed`, [as described above](#what-triggers-a-todo).
diff --git a/fixtures/emojis/index.json b/fixtures/emojis/index.json
index f55571d31fa..0406d404532 100644
--- a/fixtures/emojis/index.json
+++ b/fixtures/emojis/index.json
@@ -16344,7 +16344,7 @@
"aliases": [],
"aliases_ascii": [],
"keywords": [
- "accomodation",
+ "accommodation",
"building",
"checkin",
"whotel",
diff --git a/haml_lint/inline_javascript.rb b/haml_lint/inline_javascript.rb
new file mode 100644
index 00000000000..da6af92e82b
--- /dev/null
+++ b/haml_lint/inline_javascript.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+unless Rails.env.production?
+ require_dependency 'haml_lint/haml_visitor'
+ require_dependency 'haml_lint/linter'
+ require_dependency 'haml_lint/linter_registry'
+
+ module HamlLint
+ class Linter::InlineJavaScript < Linter
+ include ::HamlLint::LinterRegistry
+
+ def visit_filter(node)
+ return unless node.filter_type == 'javascript'
+
+ record_lint(node, 'Inline JavaScript is discouraged (https://docs.gitlab.com/ee/development/gotchas.html#do-not-use-inline-javascript-in-views)')
+ end
+
+ def visit_tag(node)
+ return unless node.tag_name == 'script'
+
+ record_lint(node, 'Inline JavaScript is discouraged (https://docs.gitlab.com/ee/development/gotchas.html#do-not-use-inline-javascript-in-views)')
+ end
+ end
+ end
+end
diff --git a/haml_lint/linter/no_plain_nodes.rb b/haml_lint/linter/no_plain_nodes.rb
new file mode 100644
index 00000000000..c39f61fa80d
--- /dev/null
+++ b/haml_lint/linter/no_plain_nodes.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+require 'active_support/core_ext/array/grouping'
+
+module HamlLint
+ class Linter
+ class NoPlainNodes < Linter
+ include ::HamlLint::LinterRegistry
+
+ def visit_tag(node)
+ if inline_plain_node?(node)
+ check_inline(node)
+ elsif !node.script.empty?
+ check_script(node)
+ else
+ check(node)
+ end
+ end
+
+ private
+
+ def check(node)
+ text_in_node(node).each { |string| record(node, string) }
+ end
+
+ def check_inline(node)
+ text = inline_text(node)
+ record(node, text) unless text.empty?
+ end
+
+ def check_script(node)
+ text = inline_text(node)
+ record(node, text) unless text.start_with?('=') || text.empty?
+ end
+
+ # Build an array of all strings in child text nodes.
+ # non text nodes are nil, where we'll split the sentences.
+ def text_in_node(node)
+ texts = node.children.map do |child|
+ child.text.strip if text_node?(child)
+ end
+
+ texts.split(nil).map { |sentence| sentence.join(' ') unless sentence.empty? }.compact
+ end
+
+ # Removes a node's attributes and tag from the source code,
+ # returning the inline text of a node.
+ def inline_text(node)
+ text = node.source_code.gsub("%#{node.tag_name}", '')
+
+ attributes = node.attributes_source.map(&:last)
+ attributes.each { |attribute| text = text.gsub(attribute, '') }
+
+ text.strip
+ end
+
+ def record(node, string)
+ record_lint(node, message(string))
+ end
+
+ def message(string)
+ "`#{string}` is a plain node. Please use an i18n method like `#{fixed(string)}`"
+ end
+
+ def fixed(string)
+ "= _('#{string}')"
+ end
+
+ def inline_plain_node?(node)
+ node.children.empty? && node.script.empty?
+ end
+
+ def plain_node?(node)
+ node.is_a?(::HamlLint::Tree::PlainNode)
+ end
+
+ def text_node?(node)
+ return false unless plain_node?(node)
+
+ !node.text.empty?
+ end
+ end
+ end
+end
diff --git a/jest.config.js b/jest.config.js
index fdbbe977f0b..84481642250 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -2,6 +2,10 @@ const IS_EE = require('./config/helpers/is_ee_env');
const reporters = ['default'];
+// To have consistent date time parsing both in local and CI environments we set
+// the timezone of the Node process. https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27738
+process.env.TZ = 'GMT';
+
if (process.env.CI) {
reporters.push([
'jest-junit',
@@ -24,6 +28,7 @@ module.exports = {
'^helpers(/.*)$': '<rootDir>/spec/frontend/helpers$1',
'^vendor(/.*)$': '<rootDir>/vendor/assets/javascripts$1',
'\\.(jpg|jpeg|png|svg)$': '<rootDir>/spec/frontend/__mocks__/file_mock.js',
+ 'emojis(/.*).json': '<rootDir>/fixtures/emojis$1.json',
},
collectCoverageFrom: ['<rootDir>/app/assets/javascripts/**/*.{js,vue}'],
coverageDirectory: '<rootDir>/coverage-frontend/',
diff --git a/lib/api/api.rb b/lib/api/api.rb
index bf8ddba6f0d..20f8c637274 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -6,7 +6,7 @@ module API
LOG_FILENAME = Rails.root.join("log", "api_json.log")
- NO_SLASH_URL_PART_REGEX = %r{[^/]+}
+ NO_SLASH_URL_PART_REGEX = %r{[^/]+}.freeze
NAMESPACE_OR_PROJECT_REQUIREMENTS = { id: NO_SLASH_URL_PART_REGEX }.freeze
COMMIT_ENDPOINT_REQUIREMENTS = NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(sha: NO_SLASH_URL_PART_REGEX).freeze
USER_REQUIREMENTS = { user_id: NO_SLASH_URL_PART_REGEX }.freeze
@@ -98,7 +98,6 @@ module API
mount ::API::Boards
mount ::API::Branches
mount ::API::BroadcastMessages
- mount ::API::CircuitBreakers
mount ::API::Commits
mount ::API::CommitStatuses
mount ::API::ContainerRegistry
@@ -134,6 +133,7 @@ module API
mount ::API::Pipelines
mount ::API::PipelineSchedules
mount ::API::ProjectClusters
+ mount ::API::ProjectEvents
mount ::API::ProjectExport
mount ::API::ProjectImport
mount ::API::ProjectHooks
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index 5c98b0ad56c..65d7f68bbf9 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -162,8 +162,8 @@ module API
result = DeleteBranchService.new(user_project, current_user)
.execute(params[:branch])
- if result[:status] != :success
- render_api_error!(result[:message], result[:return_code])
+ if result.error?
+ render_api_error!(result.message, result.http_status)
end
end
end
diff --git a/lib/api/circuit_breakers.rb b/lib/api/circuit_breakers.rb
deleted file mode 100644
index da756daadcc..00000000000
--- a/lib/api/circuit_breakers.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-module API
- class CircuitBreakers < Grape::API
- before { authenticated_as_admin! }
-
- resource :circuit_breakers do
- params do
- requires :type,
- type: String,
- desc: "The type of circuitbreaker",
- values: ['repository_storage']
- end
- resource ':type' do
- namespace '', requirements: { type: 'repository_storage' } do
- desc 'Get all git storages' do
- detail 'This feature was introduced in GitLab 9.5'
- end
- get do
- present []
- end
-
- desc 'Get all failing git storages' do
- detail 'This feature was introduced in GitLab 9.5'
- end
- get 'failing' do
- present []
- end
-
- desc 'Reset all storage failures and open circuitbreaker' do
- detail 'This feature was introduced in GitLab 9.5'
- end
- delete do
- end
- end
- end
- end
- end
-end
diff --git a/lib/api/commits.rb b/lib/api/commits.rb
index 65eb9bfb87e..80913f4ca07 100644
--- a/lib/api/commits.rb
+++ b/lib/api/commits.rb
@@ -96,17 +96,27 @@ module API
end
end
optional :start_branch, type: String, desc: 'Name of the branch to start the new commit from'
+ optional :start_project, types: [Integer, String], desc: 'The ID or path of the project to start the commit from'
optional :author_email, type: String, desc: 'Author email for commit'
optional :author_name, type: String, desc: 'Author name for commit'
optional :stats, type: Boolean, default: true, desc: 'Include commit stats'
optional :force, type: Boolean, default: false, desc: 'When `true` overwrites the target branch with a new commit based on the `start_branch`'
end
post ':id/repository/commits' do
+ if params[:start_project]
+ start_project = find_project!(params[:start_project])
+
+ unless user_project.forked_from?(start_project)
+ forbidden!("Project is not included in the fork network for #{start_project.full_name}")
+ end
+ end
+
authorize_push_to_branch!(params[:branch])
attrs = declared_params
attrs[:branch_name] = attrs.delete(:branch)
attrs[:start_branch] ||= attrs[:branch_name]
+ attrs[:start_project] = start_project if start_project
result = ::Files::MultiService.new(user_project, current_user, attrs).execute
diff --git a/lib/api/discussions.rb b/lib/api/discussions.rb
index 8afe6dda414..693172b7d08 100644
--- a/lib/api/discussions.rb
+++ b/lib/api/discussions.rb
@@ -134,9 +134,13 @@ module API
post ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes" do
noteable = find_noteable(parent_type, noteables_str, params[:noteable_id])
notes = readable_discussion_notes(noteable, params[:discussion_id])
+ first_note = notes.first
break not_found!("Discussion") if notes.empty?
- break bad_request!("Discussion is an individual note.") unless notes.first.part_of_discussion?
+
+ unless first_note.part_of_discussion? || first_note.to_discussion.can_convert_to_discussion?
+ break bad_request!("Discussion can not be replied to.")
+ end
opts = {
note: params[:body],
@@ -202,7 +206,7 @@ module API
delete_note(noteable, params[:note_id])
end
- if Noteable::RESOLVABLE_TYPES.include?(noteable_type.to_s)
+ if Noteable.resolvable_types.include?(noteable_type.to_s)
desc "Resolve/unresolve an existing #{noteable_type.to_s.downcase} discussion" do
success Entities::Discussion
end
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 4bdac278add..8840accf675 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -239,6 +239,7 @@ module API
end
end
+ expose :empty_repo?, as: :empty_repo
expose :archived?, as: :archived
expose :visibility
expose :owner, using: Entities::UserBasic, unless: ->(project, options) { project.group }
@@ -264,6 +265,7 @@ module API
expose :open_issues_count, if: lambda { |project, options| project.feature_available?(:issues, options[:current_user]) }
expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] }
+ expose :ci_default_git_depth
expose :public_builds, as: :public_jobs
expose :ci_config_path, if: -> (project, options) { Ability.allowed?(options[:current_user], :download_code, project) }
expose :shared_with_groups do |project, options|
@@ -286,6 +288,7 @@ module API
# N+1 is solved then by using `subject.tags.map(&:name)`
# MR describing the solution: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20555
super(projects_relation).preload(:group)
+ .preload(:ci_cd_settings)
.preload(project_group_links: { group: :route },
fork_network: :root_project,
fork_network_member: :forked_from_project,
@@ -302,6 +305,7 @@ module API
expose :commit_count
expose :storage_size
expose :repository_size
+ expose :wiki_size
expose :lfs_objects_size
expose :build_artifacts_size, as: :job_artifacts_size
end
@@ -354,6 +358,7 @@ module API
with_options format_with: -> (value) { value.to_i } do
expose :storage_size
expose :repository_size
+ expose :wiki_size
expose :lfs_objects_size
expose :build_artifacts_size, as: :job_artifacts_size
end
@@ -542,10 +547,15 @@ module API
class IssueBasic < ProjectEntity
expose :closed_at
expose :closed_by, using: Entities::UserBasic
- expose :labels do |issue|
- # Avoids an N+1 query since labels are preloaded
- issue.labels.map(&:title).sort
+
+ expose :labels do |issue, options|
+ if options[:with_labels_details]
+ ::API::Entities::LabelBasic.represent(issue.labels.sort_by(&:title))
+ else
+ issue.labels.map(&:title).sort
+ end
end
+
expose :milestone, using: Entities::Milestone
expose :assignees, :author, using: Entities::UserBasic
@@ -568,11 +578,21 @@ module API
expose :time_stats, using: 'API::Entities::IssuableTimeStats' do |issue|
issue
end
+
+ expose :task_completion_status
end
class Issue < IssueBasic
include ::API::Helpers::RelatedResourcesHelpers
+ expose(:has_tasks) do |issue, _|
+ !issue.task_list_items.empty?
+ end
+
+ expose :task_status, if: -> (issue, _) do
+ !issue.task_list_items.empty?
+ end
+
expose :_links do
expose :self do |issue|
expose_url(api_v4_project_issue_path(id: issue.project_id, issue_iid: issue.iid))
@@ -708,6 +728,8 @@ module API
end
expose :squash
+
+ expose :task_completion_status
end
class MergeRequest < MergeRequestBasic
@@ -878,7 +900,7 @@ module API
expose :push_event_payload,
as: :push_data,
using: PushEventPayload,
- if: -> (event, _) { event.push? }
+ if: -> (event, _) { event.push_action? }
expose :author_username do |event, options|
event.author&.username
@@ -922,7 +944,15 @@ module API
end
class NamespaceBasic < Grape::Entity
- expose :id, :name, :path, :kind, :full_path, :parent_id
+ expose :id, :name, :path, :kind, :full_path, :parent_id, :avatar_url
+
+ expose :web_url do |namespace|
+ if namespace.user?
+ Gitlab::Routing.url_helpers.user_url(namespace.owner)
+ else
+ namespace.web_url
+ end
+ end
end
class Namespace < NamespaceBasic
@@ -1148,22 +1178,33 @@ module API
end
end
- class Release < TagRelease
+ class Release < Grape::Entity
expose :name
+ expose :tag, as: :tag_name, if: lambda { |_, _| can_download_code? }
+ expose :description
expose :description_html do |entity|
MarkupHelper.markdown_field(entity, :description)
end
expose :created_at
expose :author, using: Entities::UserBasic, if: -> (release, _) { release.author.present? }
- expose :commit, using: Entities::Commit
+ expose :commit, using: Entities::Commit, if: lambda { |_, _| can_download_code? }
expose :assets do
- expose :assets_count, as: :count
- expose :sources, using: Entities::Releases::Source
+ expose :assets_count, as: :count do |release, _|
+ assets_to_exclude = can_download_code? ? [] : [:sources]
+ release.assets_count(except: assets_to_exclude)
+ end
+ expose :sources, using: Entities::Releases::Source, if: lambda { |_, _| can_download_code? }
expose :links, using: Entities::Releases::Link do |release, options|
release.links.sorted
end
end
+
+ private
+
+ def can_download_code?
+ Ability.allowed?(options[:current_user], :download_code, object.project)
+ end
end
class Tag < Grape::Entity
@@ -1234,7 +1275,7 @@ module API
end
class JobBasic < Grape::Entity
- expose :id, :status, :stage, :name, :ref, :tag, :coverage
+ expose :id, :status, :stage, :name, :ref, :tag, :coverage, :allow_failure
expose :created_at, :started_at, :finished_at
expose :duration
expose :user, with: User
@@ -1269,8 +1310,9 @@ module API
end
class Variable < Grape::Entity
- expose :key, :value
+ expose :variable_type, :key, :value
expose :protected?, as: :protected, if: -> (entity, _) { entity.respond_to?(:protected?) }
+ expose :masked?, as: :masked, if: -> (entity, _) { entity.respond_to?(:masked?) }
end
class Pipeline < PipelineBasic
diff --git a/lib/api/events.rb b/lib/api/events.rb
index b98aa9f31e1..e4c017fab42 100644
--- a/lib/api/events.rb
+++ b/lib/api/events.rb
@@ -4,34 +4,11 @@ module API
class Events < Grape::API
include PaginationParams
include APIGuard
+ helpers ::API::Helpers::EventsHelpers
- helpers do
- params :event_filter_params do
- optional :action, type: String, values: Event.actions, desc: 'Event action to filter on'
- optional :target_type, type: String, values: Event.target_types, desc: 'Event target type to filter on'
- optional :before, type: Date, desc: 'Include only events created before this date'
- optional :after, type: Date, desc: 'Include only events created after this date'
- end
-
- params :sort_params do
- optional :sort, type: String, values: %w[asc desc], default: 'desc',
- desc: 'Return events sorted in ascending and descending order'
- end
-
- def present_events(events)
- events = paginate(events)
-
- present events, with: Entities::Event
- end
-
- def find_events(source)
- EventsFinder.new(params.merge(source: source, current_user: current_user, with_associations: true)).execute
- end
- end
+ allow_access_with_scope :read_user, if: -> (request) { request.get? }
resource :events do
- allow_access_with_scope :read_user, if: -> (request) { request.get? }
-
desc "List currently authenticated user's events" do
detail 'This feature was introduced in GitLab 9.3.'
success Entities::Event
@@ -55,8 +32,6 @@ module API
requires :id, type: String, desc: 'The ID or Username of the user'
end
resource :users do
- allow_access_with_scope :read_user, if: -> (request) { request.get? }
-
desc 'Get the contribution events of a specified user' do
detail 'This feature was introduced in GitLab 8.13.'
success Entities::Event
@@ -76,25 +51,5 @@ module API
present_events(events)
end
end
-
- params do
- requires :id, type: String, desc: 'The ID of a project'
- end
- resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
- desc "List a Project's visible events" do
- success Entities::Event
- end
- params do
- use :pagination
- use :event_filter_params
- use :sort_params
- end
-
- get ":id/events" do
- events = find_events(user_project)
-
- present_events(events)
- end
- end
end
end
diff --git a/lib/api/group_variables.rb b/lib/api/group_variables.rb
index 3f048e0dc56..47fcbabb4d4 100644
--- a/lib/api/group_variables.rb
+++ b/lib/api/group_variables.rb
@@ -47,6 +47,7 @@ module API
requires :key, type: String, desc: 'The key of the variable'
requires :value, type: String, desc: 'The value of the variable'
optional :protected, type: String, desc: 'Whether the variable is protected'
+ optional :variable_type, type: String, values: Ci::GroupVariable.variable_types.keys, desc: 'The type of variable, must be one of env_var or file. Defaults to env_var'
end
post ':id/variables' do
variable_params = declared_params(include_missing: false)
@@ -67,6 +68,7 @@ module API
optional :key, type: String, desc: 'The key of the variable'
optional :value, type: String, desc: 'The value of the variable'
optional :protected, type: String, desc: 'Whether the variable is protected'
+ optional :variable_type, type: String, values: Ci::GroupVariable.variable_types.keys, desc: 'The type of variable, must be one of env_var or file'
end
# rubocop: disable CodeReuse/ActiveRecord
put ':id/variables/:key' do
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index ad16f26f5cc..ec1020c7c78 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -7,35 +7,9 @@ module API
before { authenticate_non_get! }
- helpers do
- params :optional_params_ce do
- optional :description, type: String, desc: 'The description of the group'
- optional :visibility, type: String,
- values: Gitlab::VisibilityLevel.string_values,
- default: Gitlab::VisibilityLevel.string_level(
- Gitlab::CurrentSettings.current_application_settings.default_group_visibility),
- desc: 'The visibility of the group'
- optional :lfs_enabled, type: Boolean, desc: 'Enable/disable LFS for the projects in this group'
- optional :request_access_enabled, type: Boolean, desc: 'Allow users to request member access'
- optional :share_with_group_lock, type: Boolean, desc: 'Prevent sharing a project with another group within this group'
- end
-
- if Gitlab.ee?
- params :optional_params_ee do
- optional :membership_lock, type: Boolean, desc: 'Prevent adding new members to project membership within this group'
- optional :ldap_cn, type: String, desc: 'LDAP Common Name'
- optional :ldap_access, type: Integer, desc: 'A valid access level'
- optional :shared_runners_minutes_limit, type: Integer, desc: '(admin-only) Pipeline minutes quota for this group'
- optional :extra_shared_runners_minutes_limit, type: Integer, desc: '(admin-only) Extra pipeline minutes quota for this group'
- all_or_none_of :ldap_cn, :ldap_access
- end
- end
-
- params :optional_params do
- use :optional_params_ce
- use :optional_params_ee if Gitlab.ee?
- end
+ helpers Helpers::GroupsHelpers
+ helpers do
params :statistics_params do
optional :statistics, type: Boolean, default: false, desc: 'Include project statistics'
end
@@ -176,10 +150,7 @@ module API
optional :name, type: String, desc: 'The name of the group'
optional :path, type: String, desc: 'The path of the group'
use :optional_params
-
- if Gitlab.ee?
- optional :file_template_project_id, type: Integer, desc: 'The ID of a project to use for custom templates in this group'
- end
+ use :optional_update_params_ee
end
put ':id' do
group = find_group!(params[:id])
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 8a21d44b4bf..00bcf6b055b 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -67,10 +67,6 @@ module API
initial_current_user != current_user
end
- def user_namespace
- @user_namespace ||= find_namespace!(params[:id])
- end
-
def user_group
@group ||= find_group!(params[:id])
end
@@ -449,7 +445,7 @@ module API
end
def present_carrierwave_file!(file, supports_direct_download: true)
- return not_found! unless file.exists?
+ return not_found! unless file&.exists?
if file.file_storage?
present_disk_file!(file.path, file.filename)
diff --git a/lib/api/helpers/events_helpers.rb b/lib/api/helpers/events_helpers.rb
new file mode 100644
index 00000000000..bf3b76bb92d
--- /dev/null
+++ b/lib/api/helpers/events_helpers.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module API
+ module Helpers
+ module EventsHelpers
+ extend Grape::API::Helpers
+
+ params :event_filter_params do
+ optional :action, type: String, values: Event.actions, desc: 'Event action to filter on'
+ optional :target_type, type: String, values: Event.target_types, desc: 'Event target type to filter on'
+ optional :before, type: Date, desc: 'Include only events created before this date'
+ optional :after, type: Date, desc: 'Include only events created after this date'
+ end
+
+ params :sort_params do
+ optional :sort, type: String, values: %w[asc desc], default: 'desc',
+ desc: 'Return events sorted in ascending and descending order'
+ end
+
+ def present_events(events)
+ events = paginate(events)
+
+ present events, with: Entities::Event
+ end
+
+ def find_events(source)
+ EventsFinder.new(params.merge(source: source, current_user: current_user, with_associations: true)).execute
+ end
+ end
+ end
+end
diff --git a/lib/api/helpers/groups_helpers.rb b/lib/api/helpers/groups_helpers.rb
new file mode 100644
index 00000000000..2c33d79f6c8
--- /dev/null
+++ b/lib/api/helpers/groups_helpers.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module API
+ module Helpers
+ module GroupsHelpers
+ extend ActiveSupport::Concern
+ extend Grape::API::Helpers
+
+ params :optional_params_ce do
+ optional :description, type: String, desc: 'The description of the group'
+ optional :visibility, type: String,
+ values: Gitlab::VisibilityLevel.string_values,
+ default: Gitlab::VisibilityLevel.string_level(
+ Gitlab::CurrentSettings.current_application_settings.default_group_visibility),
+ desc: 'The visibility of the group'
+ optional :lfs_enabled, type: Boolean, desc: 'Enable/disable LFS for the projects in this group'
+ optional :request_access_enabled, type: Boolean, desc: 'Allow users to request member access'
+ optional :share_with_group_lock, type: Boolean, desc: 'Prevent sharing a project with another group within this group'
+ end
+
+ params :optional_params_ee do
+ end
+
+ params :optional_update_params_ee do
+ end
+
+ params :optional_params do
+ use :optional_params_ce
+ use :optional_params_ee
+ end
+ end
+ end
+end
diff --git a/lib/api/helpers/internal_helpers.rb b/lib/api/helpers/internal_helpers.rb
index 71c30ec99a5..c318f5b9127 100644
--- a/lib/api/helpers/internal_helpers.rb
+++ b/lib/api/helpers/internal_helpers.rb
@@ -46,6 +46,8 @@ module API
def process_mr_push_options(push_options, project, user, changes)
output = {}
+ Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/61359')
+
service = ::MergeRequests::PushOptionsHandlerService.new(
project,
user,
diff --git a/lib/api/helpers/issues_helpers.rb b/lib/api/helpers/issues_helpers.rb
index f6762910b0c..5b7199fddb0 100644
--- a/lib/api/helpers/issues_helpers.rb
+++ b/lib/api/helpers/issues_helpers.rb
@@ -3,6 +3,14 @@
module API
module Helpers
module IssuesHelpers
+ extend Grape::API::Helpers
+
+ params :optional_issue_params_ee do
+ end
+
+ params :optional_issues_params_ee do
+ end
+
def self.update_params_at_least_one_of
[
:assignee_id,
@@ -18,6 +26,39 @@ module API
:title
]
end
+
+ def issue_finder(args = {})
+ args = declared_params.merge(args)
+
+ args.delete(:id)
+ args[:milestone_title] ||= args.delete(:milestone)
+ args[:label_name] ||= args.delete(:labels)
+ args[:scope] = args[:scope].underscore if args[:scope]
+
+ IssuesFinder.new(current_user, args)
+ end
+
+ def find_issues(args = {})
+ finder = issue_finder(args)
+ issues = finder.execute.with_api_entity_associations
+
+ issues.reorder(order_options_with_tie_breaker) # rubocop: disable CodeReuse/ActiveRecord
+ end
+
+ def issues_statistics(args = {})
+ finder = issue_finder(args)
+ counter = Gitlab::IssuablesCountForState.new(finder)
+
+ {
+ statistics: {
+ counts: {
+ all: counter[:all],
+ closed: counter[:closed],
+ opened: counter[:opened]
+ }
+ }
+ }
+ end
end
end
end
diff --git a/lib/api/helpers/members_helpers.rb b/lib/api/helpers/members_helpers.rb
index 73d58ee7f37..1395ffadab9 100644
--- a/lib/api/helpers/members_helpers.rb
+++ b/lib/api/helpers/members_helpers.rb
@@ -19,28 +19,13 @@ module API
.non_request
end
- # rubocop: disable CodeReuse/ActiveRecord
def find_all_members_for_project(project)
- shared_group_ids = project.project_group_links.pluck(:group_id)
- project_group_ids = project.group&.self_and_ancestors&.pluck(:id)
- source_ids = [project.id, project_group_ids, shared_group_ids]
- .flatten
- .compact
- Member.includes(:user)
- .joins(user: :project_authorizations)
- .where(project_authorizations: { project_id: project.id })
- .where(source_id: source_ids)
+ MembersFinder.new(project, current_user).execute(include_invited_groups_members: true)
end
- # rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def find_all_members_for_group(group)
- source_ids = group.self_and_ancestors.pluck(:id)
- Member.includes(:user)
- .where(source_id: source_ids)
- .where(source_type: 'Namespace')
+ GroupMembersFinder.new(group).execute
end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
end
diff --git a/lib/api/helpers/pagination.rb b/lib/api/helpers/pagination.rb
index 94b58a64d26..2a9b17ad22a 100644
--- a/lib/api/helpers/pagination.rb
+++ b/lib/api/helpers/pagination.rb
@@ -23,7 +23,7 @@ module API
def base_request_uri
@base_request_uri ||= URI.parse(request.url).tap do |uri|
uri.host = Gitlab.config.gitlab.host
- uri.port = nil
+ uri.port = Gitlab.config.gitlab.port
end
end
diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb
index aaf32dafca4..f242f1fea0e 100644
--- a/lib/api/helpers/projects_helpers.rb
+++ b/lib/api/helpers/projects_helpers.rb
@@ -4,48 +4,46 @@ module API
module Helpers
module ProjectsHelpers
extend ActiveSupport::Concern
+ extend Grape::API::Helpers
- included do
- helpers do
- params :optional_project_params_ce do
- optional :description, type: String, desc: 'The description of the project'
- optional :ci_config_path, type: String, desc: 'The path to CI config file. Defaults to `.gitlab-ci.yml`'
- optional :issues_enabled, type: Boolean, desc: 'Flag indication if the issue tracker is enabled'
- optional :merge_requests_enabled, type: Boolean, desc: 'Flag indication if merge requests are enabled'
- optional :wiki_enabled, type: Boolean, desc: 'Flag indication if the wiki is enabled'
- optional :jobs_enabled, type: Boolean, desc: 'Flag indication if jobs are enabled'
- optional :snippets_enabled, type: Boolean, desc: 'Flag indication if snippets are enabled'
- optional :shared_runners_enabled, type: Boolean, desc: 'Flag indication if shared runners are enabled for that project'
- optional :resolve_outdated_diff_discussions, type: Boolean, desc: 'Automatically resolve merge request diffs discussions on lines changed with a push'
- optional :container_registry_enabled, type: Boolean, desc: 'Flag indication if the container registry is enabled for that project'
- optional :lfs_enabled, type: Boolean, desc: 'Flag indication if Git LFS is enabled for that project'
- optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The visibility of the project.'
- optional :public_builds, type: Boolean, desc: 'Perform public builds'
- optional :request_access_enabled, type: Boolean, desc: 'Allow users to request member access'
- optional :only_allow_merge_if_pipeline_succeeds, type: Boolean, desc: 'Only allow to merge if builds succeed'
- optional :only_allow_merge_if_all_discussions_are_resolved, type: Boolean, desc: 'Only allow to merge if all discussions are resolved'
- optional :tag_list, type: Array[String], desc: 'The list of tags for a project'
- optional :avatar, type: File, desc: 'Avatar image for project'
- optional :printing_merge_request_link_enabled, type: Boolean, desc: 'Show link to create/view merge request when pushing from the command line'
- optional :merge_method, type: String, values: %w(ff rebase_merge merge), desc: 'The merge method used when merging merge requests'
- optional :initialize_with_readme, type: Boolean, desc: "Initialize a project with a README.md"
- optional :external_authorization_classification_label, type: String, desc: 'The classification label for the project'
- end
+ params :optional_project_params_ce do
+ optional :description, type: String, desc: 'The description of the project'
+ optional :ci_config_path, type: String, desc: 'The path to CI config file. Defaults to `.gitlab-ci.yml`'
+ optional :issues_enabled, type: Boolean, desc: 'Flag indication if the issue tracker is enabled'
+ optional :merge_requests_enabled, type: Boolean, desc: 'Flag indication if merge requests are enabled'
+ optional :wiki_enabled, type: Boolean, desc: 'Flag indication if the wiki is enabled'
+ optional :jobs_enabled, type: Boolean, desc: 'Flag indication if jobs are enabled'
+ optional :snippets_enabled, type: Boolean, desc: 'Flag indication if snippets are enabled'
+ optional :shared_runners_enabled, type: Boolean, desc: 'Flag indication if shared runners are enabled for that project'
+ optional :resolve_outdated_diff_discussions, type: Boolean, desc: 'Automatically resolve merge request diffs discussions on lines changed with a push'
+ optional :container_registry_enabled, type: Boolean, desc: 'Flag indication if the container registry is enabled for that project'
+ optional :lfs_enabled, type: Boolean, desc: 'Flag indication if Git LFS is enabled for that project'
+ optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The visibility of the project.'
+ optional :public_builds, type: Boolean, desc: 'Perform public builds'
+ optional :request_access_enabled, type: Boolean, desc: 'Allow users to request member access'
+ optional :only_allow_merge_if_pipeline_succeeds, type: Boolean, desc: 'Only allow to merge if builds succeed'
+ optional :only_allow_merge_if_all_discussions_are_resolved, type: Boolean, desc: 'Only allow to merge if all discussions are resolved'
+ optional :tag_list, type: Array[String], desc: 'The list of tags for a project'
+ optional :avatar, type: File, desc: 'Avatar image for project'
+ optional :printing_merge_request_link_enabled, type: Boolean, desc: 'Show link to create/view merge request when pushing from the command line'
+ optional :merge_method, type: String, values: %w(ff rebase_merge merge), desc: 'The merge method used when merging merge requests'
+ optional :initialize_with_readme, type: Boolean, desc: "Initialize a project with a README.md"
+ optional :external_authorization_classification_label, type: String, desc: 'The classification label for the project'
+ optional :ci_default_git_depth, type: Integer, desc: 'Default number of revisions for shallow cloning'
+ end
+
+ params :optional_project_params_ee do
+ end
- if Gitlab.ee?
- params :optional_project_params_ee do
- optional :repository_storage, type: String, desc: 'Which storage shard the repository is on. Available only to admins'
- optional :approvals_before_merge, type: Integer, desc: 'How many approvers should approve merge request by default'
- optional :mirror, type: Boolean, desc: 'Enables pull mirroring in a project'
- optional :mirror_trigger_builds, type: Boolean, desc: 'Pull mirroring triggers builds'
- end
- end
+ params :optional_project_params do
+ use :optional_project_params_ce
+ use :optional_project_params_ee
+ end
+
+ params :optional_filter_params_ee do
+ end
- params :optional_project_params do
- use :optional_project_params_ce
- use :optional_project_params_ee if Gitlab.ee?
- end
- end
+ params :optional_update_params_ee do
end
def self.update_params_at_least_one_of
diff --git a/lib/api/helpers/protected_branches_helpers.rb b/lib/api/helpers/protected_branches_helpers.rb
new file mode 100644
index 00000000000..0fc6841d79a
--- /dev/null
+++ b/lib/api/helpers/protected_branches_helpers.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module API
+ module Helpers
+ module ProtectedBranchesHelpers
+ extend ActiveSupport::Concern
+ extend Grape::API::Helpers
+
+ params :optional_params_ee do
+ end
+ end
+ end
+end
diff --git a/lib/api/helpers/related_resources_helpers.rb b/lib/api/helpers/related_resources_helpers.rb
index 793ae11b41d..9cdde25fe4e 100644
--- a/lib/api/helpers/related_resources_helpers.rb
+++ b/lib/api/helpers/related_resources_helpers.rb
@@ -13,6 +13,10 @@ module API
available?(:merge_requests, project, options[:current_user])
end
+ def expose_path(path)
+ Gitlab::Utils.append_path(Gitlab.config.gitlab.relative_url_root, path)
+ end
+
def expose_url(path)
url_options = Gitlab::Application.routes.default_url_options
protocol, host, port, script_name = url_options.values_at(:protocol, :host, :port, :script_name)
diff --git a/lib/api/helpers/services_helpers.rb b/lib/api/helpers/services_helpers.rb
index 953be7f3798..44c577204b8 100644
--- a/lib/api/helpers/services_helpers.rb
+++ b/lib/api/helpers/services_helpers.rb
@@ -563,6 +563,12 @@ module API
name: :notify_only_broken_pipelines,
type: Boolean,
desc: 'Notify only broken pipelines'
+ },
+ {
+ required: false,
+ name: :notify_only_default_branch,
+ type: Boolean,
+ desc: 'Send notifications only for the default branch'
}
],
'pivotaltracker' => [
diff --git a/lib/api/helpers/settings_helpers.rb b/lib/api/helpers/settings_helpers.rb
new file mode 100644
index 00000000000..6441bb579ff
--- /dev/null
+++ b/lib/api/helpers/settings_helpers.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module API
+ module Helpers
+ module SettingsHelpers
+ extend ActiveSupport::Concern
+ extend Grape::API::Helpers
+
+ params :optional_params_ee do
+ end
+
+ def self.optional_attributes
+ [*::ApplicationSettingsHelper.visible_attributes,
+ *::ApplicationSettingsHelper.external_authorization_service_attributes,
+ :performance_bar_allowed_group_id].freeze
+ end
+ end
+ end
+end
diff --git a/lib/api/helpers/users_helpers.rb b/lib/api/helpers/users_helpers.rb
new file mode 100644
index 00000000000..56fd3c6602d
--- /dev/null
+++ b/lib/api/helpers/users_helpers.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module API
+ module Helpers
+ module UsersHelpers
+ extend ActiveSupport::Concern
+ extend Grape::API::Helpers
+
+ params :optional_params_ee do
+ end
+
+ params :optional_index_params_ee do
+ end
+ end
+ end
+end
diff --git a/lib/api/helpers/variables_helpers.rb b/lib/api/helpers/variables_helpers.rb
new file mode 100644
index 00000000000..78a92d0f5a6
--- /dev/null
+++ b/lib/api/helpers/variables_helpers.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module API
+ module Helpers
+ module VariablesHelpers
+ extend ActiveSupport::Concern
+ extend Grape::API::Helpers
+
+ params :optional_params_ee do
+ end
+ end
+ end
+end
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index 00f0bbab231..224aaaaf006 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -264,10 +264,8 @@ module API
PostReceive.perform_async(params[:gl_repository], params[:identifier],
params[:changes], push_options.as_json)
- if Feature.enabled?(:mr_push_options, default_enabled: true)
- mr_options = push_options.get(:merge_request)
- output.merge!(process_mr_push_options(mr_options, project, user, params[:changes])) if mr_options.present?
- end
+ mr_options = push_options.get(:merge_request)
+ output.merge!(process_mr_push_options(mr_options, project, user, params[:changes])) if mr_options.present?
broadcast_message = BroadcastMessage.current&.last&.message
reference_counter_decreased = Gitlab::ReferenceCounter.new(params[:gl_repository]).decrease
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 000c00ea9f9..039ebf92187 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -3,44 +3,15 @@
module API
class Issues < Grape::API
include PaginationParams
+ helpers Helpers::IssuesHelpers
+ helpers ::Gitlab::IssuableMetadata
before { authenticate_non_get! }
- helpers ::Gitlab::IssuableMetadata
-
helpers do
- # rubocop: disable CodeReuse/ActiveRecord
- def find_issues(args = {})
- args = declared_params.merge(args)
-
- args.delete(:id)
- args[:milestone_title] = args.delete(:milestone)
- args[:label_name] = args.delete(:labels)
- args[:scope] = args[:scope].underscore if args[:scope]
-
- issues = IssuesFinder.new(current_user, args).execute
- .with_api_entity_associations
- issues.reorder(order_options_with_tie_breaker)
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- if Gitlab.ee?
- params :issues_params_ee do
- optional :weight, types: [Integer, String], integer_none_any: true, desc: 'The weight of the issue'
- end
-
- params :issue_params_ee do
- optional :weight, type: Integer, desc: 'The weight of the issue'
- end
- end
-
- params :issues_params do
+ params :issues_stats_params do
optional :labels, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names'
optional :milestone, type: String, desc: 'Milestone title'
- optional :order_by, type: String, values: %w[created_at updated_at], default: 'created_at',
- desc: 'Return issues ordered by `created_at` or `updated_at` fields.'
- optional :sort, type: String, values: %w[asc desc], default: 'desc',
- desc: 'Return issues sorted in `asc` or `desc` order.'
optional :milestone, type: String, desc: 'Return issues for a specific milestone'
optional :iids, type: Array[Integer], desc: 'The IID array of issues'
optional :search, type: String, desc: 'Search issues for text present in the title, description, or any combination of these'
@@ -49,16 +20,37 @@ module API
optional :created_before, type: DateTime, desc: 'Return issues created before the specified time'
optional :updated_after, type: DateTime, desc: 'Return issues updated after the specified time'
optional :updated_before, type: DateTime, desc: 'Return issues updated before the specified time'
+
optional :author_id, type: Integer, desc: 'Return issues which are authored by the user with the given ID'
+ optional :author_username, type: String, desc: 'Return issues which are authored by the user with the given username'
+ mutually_exclusive :author_id, :author_username
+
optional :assignee_id, types: [Integer, String], integer_none_any: true,
desc: 'Return issues which are assigned to the user with the given ID'
+ optional :assignee_username, type: Array[String], check_assignees_count: true,
+ coerce_with: Validations::CheckAssigneesCount.coerce,
+ desc: 'Return issues which are assigned to the user with the given username'
+ mutually_exclusive :assignee_id, :assignee_username
+
optional :scope, type: String, values: %w[created-by-me assigned-to-me created_by_me assigned_to_me all],
desc: 'Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`'
optional :my_reaction_emoji, type: String, desc: 'Return issues reacted by the authenticated user by the given emoji'
optional :confidential, type: Boolean, desc: 'Filter confidential or public issues'
- use :pagination
- use :issues_params_ee if Gitlab.ee?
+ use :optional_issues_params_ee
+ end
+
+ params :issues_params do
+ optional :with_labels_details, type: Boolean, desc: 'Return more label data than just lable title', default: false
+ optional :state, type: String, values: %w[opened closed all], default: 'all',
+ desc: 'Return opened, closed, or all issues'
+ optional :order_by, type: String, values: %w[created_at updated_at], default: 'created_at',
+ desc: 'Return issues ordered by `created_at` or `updated_at` fields.'
+ optional :sort, type: String, values: %w[asc desc], default: 'desc',
+ desc: 'Return issues sorted in `asc` or `desc` order.'
+
+ use :issues_stats_params
+ use :pagination
end
params :issue_params do
@@ -71,17 +63,27 @@ module API
optional :confidential, type: Boolean, desc: 'Boolean parameter if the issue should be confidential'
optional :discussion_locked, type: Boolean, desc: " Boolean parameter indicating if the issue's discussion is locked"
- use :issue_params_ee if Gitlab.ee?
+ use :optional_issue_params_ee
end
end
+ desc "Get currently authenticated user's issues statistics"
+ params do
+ use :issues_stats_params
+ optional :scope, type: String, values: %w[created_by_me assigned_to_me all], default: 'created_by_me',
+ desc: 'Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`'
+ end
+ get '/issues_statistics' do
+ authenticate! unless params[:scope] == 'all'
+
+ present issues_statistics, with: Grape::Presenters::Presenter
+ end
+
resource :issues do
desc "Get currently authenticated user's issues" do
- success Entities::IssueBasic
+ success Entities::Issue
end
params do
- optional :state, type: String, values: %w[opened closed all], default: 'all',
- desc: 'Return opened, closed, or all issues'
use :issues_params
optional :scope, type: String, values: %w[created-by-me assigned-to-me created_by_me assigned_to_me all], default: 'created_by_me',
desc: 'Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`'
@@ -91,7 +93,8 @@ module API
issues = paginate(find_issues)
options = {
- with: Entities::IssueBasic,
+ with: Entities::Issue,
+ with_labels_details: declared_params[:with_labels_details],
current_user: current_user,
issuable_metadata: issuable_meta_data(issues, 'Issue')
}
@@ -105,11 +108,9 @@ module API
end
resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get a list of group issues' do
- success Entities::IssueBasic
+ success Entities::Issue
end
params do
- optional :state, type: String, values: %w[opened closed all], default: 'all',
- desc: 'Return opened, closed, or all issues'
use :issues_params
end
get ":id/issues" do
@@ -118,13 +119,24 @@ module API
issues = paginate(find_issues(group_id: group.id, include_subgroups: true))
options = {
- with: Entities::IssueBasic,
+ with: Entities::Issue,
+ with_labels_details: declared_params[:with_labels_details],
current_user: current_user,
issuable_metadata: issuable_meta_data(issues, 'Issue')
}
present issues, options
end
+
+ desc 'Get statistics for the list of group issues'
+ params do
+ use :issues_stats_params
+ end
+ get ":id/issues_statistics" do
+ group = find_group!(params[:id])
+
+ present issues_statistics(group_id: group.id, include_subgroups: true), with: Grape::Presenters::Presenter
+ end
end
params do
@@ -134,11 +146,9 @@ module API
include TimeTrackingEndpoints
desc 'Get a list of project issues' do
- success Entities::IssueBasic
+ success Entities::Issue
end
params do
- optional :state, type: String, values: %w[opened closed all], default: 'all',
- desc: 'Return opened, closed, or all issues'
use :issues_params
end
get ":id/issues" do
@@ -147,7 +157,8 @@ module API
issues = paginate(find_issues(project_id: project.id))
options = {
- with: Entities::IssueBasic,
+ with: Entities::Issue,
+ with_labels_details: declared_params[:with_labels_details],
current_user: current_user,
project: user_project,
issuable_metadata: issuable_meta_data(issues, 'Issue')
@@ -156,6 +167,16 @@ module API
present issues, options
end
+ desc 'Get statistics for the list of project issues'
+ params do
+ use :issues_stats_params
+ end
+ get ":id/issues_statistics" do
+ project = find_project!(params[:id])
+
+ present issues_statistics(project_id: project.id), with: Grape::Presenters::Presenter
+ end
+
desc 'Get a single project issue' do
success Entities::Issue
end
@@ -192,6 +213,7 @@ module API
params.delete(:iid) unless current_user.can?(:set_issue_iid, user_project)
issue_params = declared_params(include_missing: false)
+ issue_params[:system_note_timestamp] = params[:created_at]
issue_params = convert_parameters_from_legacy_format(issue_params)
@@ -230,14 +252,9 @@ module API
issue = user_project.issues.find_by!(iid: params.delete(:issue_iid))
authorize! :update_issue, issue
- # Setting updated_at only allowed for admins and owners as well
- if params[:updated_at].present?
- if current_user.admin? || user_project.owner == current_user || current_user.owned_groups.include?(user_project.owner)
- issue.system_note_timestamp = params[:updated_at]
- else
- params.delete(:updated_at)
- end
- end
+ # Setting updated_at is allowed only for admins and owners
+ params.delete(:updated_at) unless current_user.can?(:set_issue_updated_at, user_project)
+ issue.system_note_timestamp = params[:updated_at]
update_params = declared_params(include_missing: false).merge(request: request, api: true)
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index ce85772e4ed..955624404f1 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -386,9 +386,8 @@ module API
)
if merge_when_pipeline_succeeds && merge_request.head_pipeline && merge_request.head_pipeline.active?
- ::MergeRequests::MergeWhenPipelineSucceedsService
- .new(merge_request.target_project, current_user, merge_params)
- .execute(merge_request)
+ AutoMergeService.new(merge_request.target_project, current_user, merge_params)
+ .execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
else
::MergeRequests::MergeService
.new(merge_request.target_project, current_user, merge_params)
@@ -429,11 +428,9 @@ module API
post ':id/merge_requests/:merge_request_iid/cancel_merge_when_pipeline_succeeds' do
merge_request = find_project_merge_request(params[:merge_request_iid])
- unauthorized! unless merge_request.can_cancel_merge_when_pipeline_succeeds?(current_user)
+ unauthorized! unless merge_request.can_cancel_auto_merge?(current_user)
- ::MergeRequests::MergeWhenPipelineSucceedsService
- .new(merge_request.target_project, current_user)
- .cancel(merge_request)
+ AutoMergeService.new(merge_request.target_project, current_user).cancel(merge_request)
end
desc 'Rebase the merge request against its target branch' do
diff --git a/lib/api/namespaces.rb b/lib/api/namespaces.rb
index 3cc09f6ac3f..77ecb3e7cde 100644
--- a/lib/api/namespaces.rb
+++ b/lib/api/namespaces.rb
@@ -44,6 +44,8 @@ module API
requires :id, type: String, desc: "Namespace's ID or path"
end
get ':id', requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ user_namespace = find_namespace!(params[:id])
+
present user_namespace, with: Entities::Namespace, current_user: current_user
end
end
diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb
index c86b50d3736..1d1ef1afc6b 100644
--- a/lib/api/pipeline_schedules.rb
+++ b/lib/api/pipeline_schedules.rb
@@ -118,6 +118,7 @@ module API
requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id'
requires :key, type: String, desc: 'The key of the variable'
requires :value, type: String, desc: 'The value of the variable'
+ optional :variable_type, type: String, values: Ci::PipelineScheduleVariable.variable_types.keys, desc: 'The type of variable, must be one of env_var or file. Defaults to env_var'
end
post ':id/pipeline_schedules/:pipeline_schedule_id/variables' do
authorize! :update_pipeline_schedule, pipeline_schedule
@@ -138,6 +139,7 @@ module API
requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id'
requires :key, type: String, desc: 'The key of the variable'
optional :value, type: String, desc: 'The value of the variable'
+ optional :variable_type, type: String, values: Ci::PipelineScheduleVariable.variable_types.keys, desc: 'The type of variable, must be one of env_var or file'
end
put ':id/pipeline_schedules/:pipeline_schedule_id/variables/:key' do
authorize! :update_pipeline_schedule, pipeline_schedule
diff --git a/lib/api/project_clusters.rb b/lib/api/project_clusters.rb
index b62ec887183..dcc8d94fb79 100644
--- a/lib/api/project_clusters.rb
+++ b/lib/api/project_clusters.rb
@@ -54,6 +54,7 @@ module API
requires :name, type: String, desc: 'Cluster name'
optional :enabled, type: Boolean, default: true, desc: 'Determines if cluster is active or not, defaults to true'
optional :domain, type: String, desc: 'Cluster base domain'
+ optional :managed, type: Boolean, default: true, desc: 'Determines if GitLab will manage namespaces and service accounts for this cluster, defaults to true'
requires :platform_kubernetes_attributes, type: Hash, desc: %q(Platform Kubernetes data) do
requires :api_url, type: String, allow_blank: false, desc: 'URL to access the Kubernetes API'
requires :token, type: String, desc: 'Token to authenticate against Kubernetes'
diff --git a/lib/api/project_events.rb b/lib/api/project_events.rb
new file mode 100644
index 00000000000..734311e1142
--- /dev/null
+++ b/lib/api/project_events.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module API
+ class ProjectEvents < Grape::API
+ include PaginationParams
+ include APIGuard
+ helpers ::API::Helpers::EventsHelpers
+
+ params do
+ requires :id, type: String, desc: 'The ID of a project'
+ end
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ desc "List a Project's visible events" do
+ success Entities::Event
+ end
+ params do
+ use :pagination
+ use :event_filter_params
+ use :sort_params
+ end
+
+ get ":id/events" do
+ events = find_events(user_project)
+
+ present_events(events)
+ end
+ end
+ end
+end
diff --git a/lib/api/project_import.rb b/lib/api/project_import.rb
index c64ec2fcc95..71891e43dcc 100644
--- a/lib/api/project_import.rb
+++ b/lib/api/project_import.rb
@@ -3,7 +3,8 @@
module API
class ProjectImport < Grape::API
include PaginationParams
- include Helpers::ProjectsHelpers
+
+ helpers Helpers::ProjectsHelpers
helpers do
def import_params
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index cb0106592f5..1e14c77b5be 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -6,27 +6,12 @@ module API
class Projects < Grape::API
include PaginationParams
include Helpers::CustomAttributes
- include Helpers::ProjectsHelpers
+
+ helpers Helpers::ProjectsHelpers
before { authenticate_non_get! }
helpers do
- if Gitlab.ee?
- params :optional_filter_params_ee do
- optional :wiki_checksum_failed, type: Grape::API::Boolean, default: false, desc: 'Limit by projects where wiki checksum is failed'
- optional :repository_checksum_failed, type: Grape::API::Boolean, default: false, desc: 'Limit by projects where repository checksum is failed'
- end
-
- params :optional_update_params_ee do
- optional :mirror_user_id, type: Integer, desc: 'User responsible for all the activity surrounding a pull mirror event'
- optional :only_mirror_protected_branches, type: Grape::API::Boolean, desc: 'Only mirror protected branches'
- optional :mirror_overwrites_diverged_branches, type: Grape::API::Boolean, desc: 'Pull mirror overwrites diverged branches'
- optional :import_url, type: String, desc: 'URL from which the project is imported'
- optional :packages_enabled, type: Grape::API::Boolean, desc: 'Enable project packages feature'
- optional :fallback_approvals_required, type: Integer, desc: 'Overall approvals required when no rule is present'
- end
- end
-
# EE::API::Projects would override this method
def apply_filters(projects)
projects = projects.with_issues_available_for_user(current_user) if params[:with_issues_enabled]
@@ -77,7 +62,7 @@ module API
optional :with_programming_language, type: String, desc: 'Limit to repositories which use the given programming language'
optional :min_access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'Limit by minimum access level of authenticated user'
- use :optional_filter_params_ee if Gitlab.ee?
+ use :optional_filter_params_ee
end
params :create_params do
@@ -296,7 +281,7 @@ module API
optional :path, type: String, desc: 'The path of the repository'
use :optional_project_params
- use :optional_update_params_ee if Gitlab.ee?
+ use :optional_update_params_ee
at_least_one_of(*Helpers::ProjectsHelpers.update_params_at_least_one_of)
end
diff --git a/lib/api/protected_branches.rb b/lib/api/protected_branches.rb
index f8cce1ed784..33dea25289a 100644
--- a/lib/api/protected_branches.rb
+++ b/lib/api/protected_branches.rb
@@ -8,6 +8,8 @@ module API
before { authorize_admin_project }
+ helpers Helpers::ProtectedBranchesHelpers
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
@@ -52,29 +54,7 @@ module API
values: ProtectedBranch::MergeAccessLevel.allowed_access_levels,
desc: 'Access levels allowed to merge (defaults: `40`, maintainer access level)'
- if Gitlab.ee?
- optional :unprotect_access_level, type: Integer,
- values: ProtectedBranch::UnprotectAccessLevel.allowed_access_levels,
- desc: 'Access levels allowed to unprotect (defaults: `40`, maintainer access level)'
-
- optional :allowed_to_push, type: Array, desc: 'An array of users/groups allowed to push' do
- optional :access_level, type: Integer, values: ProtectedBranch::PushAccessLevel.allowed_access_levels
- optional :user_id, type: Integer
- optional :group_id, type: Integer
- end
-
- optional :allowed_to_merge, type: Array, desc: 'An array of users/groups allowed to merge' do
- optional :access_level, type: Integer, values: ProtectedBranch::MergeAccessLevel.allowed_access_levels
- optional :user_id, type: Integer
- optional :group_id, type: Integer
- end
-
- optional :allowed_to_unprotect, type: Array, desc: 'An array of users/groups allowed to unprotect' do
- optional :access_level, type: Integer, values: ProtectedBranch::UnprotectAccessLevel.allowed_access_levels
- optional :user_id, type: Integer
- optional :group_id, type: Integer
- end
- end
+ use :optional_params_ee
end
# rubocop: disable CodeReuse/ActiveRecord
post ':id/protected_branches' do
diff --git a/lib/api/releases.rb b/lib/api/releases.rb
index cb85028f22c..6b17f4317db 100644
--- a/lib/api/releases.rb
+++ b/lib/api/releases.rb
@@ -23,7 +23,7 @@ module API
get ':id/releases' do
releases = ::ReleasesFinder.new(user_project, current_user).execute
- present paginate(releases), with: Entities::Release
+ present paginate(releases), with: Entities::Release, current_user: current_user
end
desc 'Get a single project release' do
@@ -34,9 +34,9 @@ module API
requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
end
get ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMETS do
- authorize_read_release!
+ authorize_download_code!
- present release, with: Entities::Release
+ present release, with: Entities::Release, current_user: current_user
end
desc 'Create a new release' do
@@ -63,7 +63,7 @@ module API
.execute
if result[:status] == :success
- present result[:release], with: Entities::Release
+ present result[:release], with: Entities::Release, current_user: current_user
else
render_api_error!(result[:message], result[:http_status])
end
@@ -86,7 +86,7 @@ module API
.execute
if result[:status] == :success
- present result[:release], with: Entities::Release
+ present result[:release], with: Entities::Release, current_user: current_user
else
render_api_error!(result[:message], result[:http_status])
end
@@ -107,7 +107,7 @@ module API
.execute
if result[:status] == :success
- present result[:release], with: Entities::Release
+ present result[:release], with: Entities::Release, current_user: current_user
else
render_api_error!(result[:message], result[:http_status])
end
@@ -135,6 +135,10 @@ module API
authorize! :destroy_release, release
end
+ def authorize_download_code!
+ authorize! :download_code, release
+ end
+
def release
@release ||= user_project.releases.find_by_tag(params[:tag])
end
diff --git a/lib/api/runner.rb b/lib/api/runner.rb
index c60d25b88cb..fdf4904e9f5 100644
--- a/lib/api/runner.rb
+++ b/lib/api/runner.rb
@@ -15,12 +15,14 @@ module API
optional :info, type: Hash, desc: %q(Runner's metadata)
optional :active, type: Boolean, desc: 'Should Runner be active'
optional :locked, type: Boolean, desc: 'Should Runner be locked for current project'
+ optional :access_level, type: String, values: Ci::Runner.access_levels.keys,
+ desc: 'The access_level of the runner'
optional :run_untagged, type: Boolean, desc: 'Should Runner handle untagged jobs'
optional :tag_list, type: Array[String], desc: %q(List of Runner's tags)
optional :maximum_timeout, type: Integer, desc: 'Maximum timeout set when this Runner will handle the job'
end
post '/' do
- attributes = attributes_for_keys([:description, :active, :locked, :run_untagged, :tag_list, :maximum_timeout])
+ attributes = attributes_for_keys([:description, :active, :locked, :run_untagged, :tag_list, :access_level, :maximum_timeout])
.merge(get_runner_details_from_request)
attributes =
@@ -96,6 +98,7 @@ module API
optional :certificate, type: String, desc: %q(Session's certificate)
optional :authorization, type: String, desc: %q(Session's authorization)
end
+ optional :job_age, type: Integer, desc: %q(Job should be older than passed age in seconds to be ran on runner)
end
post '/request' do
authenticate_runner!
diff --git a/lib/api/search.rb b/lib/api/search.rb
index 60095300ea1..1cab1a97186 100644
--- a/lib/api/search.rb
+++ b/lib/api/search.rb
@@ -112,12 +112,13 @@ module API
type: String,
desc: 'The scope of the search',
values: Helpers::SearchHelpers.project_search_scopes
+ optional :ref, type: String, desc: 'The name of a repository branch or tag. If not given, the default branch is used'
use :pagination
end
get ':id/(-/)search' do
check_users_search_allowed!
- present search(project_id: user_project.id), with: entity
+ present search({ project_id: user_project.id, repository_ref: params[:ref] }), with: entity
end
end
end
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index b064747e5fc..6767ef882cb 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -4,6 +4,8 @@ module API
class Settings < Grape::API
before { authenticated_as_admin! }
+ helpers Helpers::SettingsHelpers
+
helpers do
def current_settings
@current_setting ||=
@@ -136,48 +138,10 @@ module API
desc: "Restrictions on the complexity of uploaded #{type.upcase} keys. A value of #{ApplicationSetting::FORBIDDEN_KEY_VALUE} disables all #{type.upcase} keys."
end
- if Gitlab.ee?
- optional :elasticsearch_aws, type: Boolean, desc: 'Enable support for AWS hosted elasticsearch'
-
- given elasticsearch_aws: ->(val) { val } do
- optional :elasticsearch_aws_access_key, type: String, desc: 'AWS IAM access key'
- requires :elasticsearch_aws_region, type: String, desc: 'The AWS region the elasticsearch domain is configured'
- optional :elasticsearch_aws_secret_access_key, type: String, desc: 'AWS IAM secret access key'
- end
-
- optional :elasticsearch_indexing, type: Boolean, desc: 'Enable Elasticsearch indexing'
-
- given elasticsearch_indexing: ->(val) { val } do
- optional :elasticsearch_search, type: Boolean, desc: 'Enable Elasticsearch search'
- requires :elasticsearch_url, type: String, desc: 'The url to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., "http://localhost:9200, http://localhost:9201")'
- end
-
- optional :email_additional_text, type: String, desc: 'Additional text added to the bottom of every email for legal/auditing/compliance reasons'
- optional :help_text, type: String, desc: 'GitLab server administrator information'
- optional :repository_size_limit, type: Integer, desc: 'Size limit per repository (MB)'
- optional :file_template_project_id, type: Integer, desc: 'ID of project where instance-level file templates are stored.'
- optional :repository_storages, type: Array[String], desc: 'A list of names of enabled storage paths, taken from `gitlab.yml`. New projects will be created in one of these stores, chosen at random.'
- optional :snowplow_enabled, type: Boolean, desc: 'Enable Snowplow'
-
- given snowplow_enabled: ->(val) { val } do
- requires :snowplow_collector_uri, type: String, desc: 'Snowplow Collector URI'
- optional :snowplow_cookie_domain, type: String, desc: 'Snowplow cookie domain'
- optional :snowplow_site_id, type: String, desc: 'Snowplow Site/Application ID'
- end
-
- optional :usage_ping_enabled, type: Boolean, desc: 'Every week GitLab will report license usage back to GitLab, Inc.'
- end
-
- optional_attributes = [*::ApplicationSettingsHelper.visible_attributes,
- *::ApplicationSettingsHelper.external_authorization_service_attributes,
- :performance_bar_allowed_group_id]
-
- if Gitlab.ee?
- optional_attributes += EE::ApplicationSettingsHelper.possible_licensed_attributes
- end
+ use :optional_params_ee
- optional(*optional_attributes)
- at_least_one_of(*optional_attributes)
+ optional(*Helpers::SettingsHelpers.optional_attributes)
+ at_least_one_of(*Helpers::SettingsHelpers.optional_attributes)
end
put "application/settings" do
attrs = declared_params(include_missing: false)
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 2f23e33bd4a..6afeebb6890 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -15,6 +15,8 @@ module API
authenticate_non_get!
end
+ helpers Helpers::UsersHelpers
+
helpers do
# rubocop: disable CodeReuse/ActiveRecord
def find_user_by_id(params)
@@ -52,10 +54,7 @@ module API
optional :private_profile, type: Boolean, desc: 'Flag indicating the user has a private profile'
all_or_none_of :extern_uid, :provider
- if Gitlab.ee?
- optional :shared_runners_minutes_limit, type: Integer, desc: 'Pipeline minutes quota for this user'
- optional :extra_shared_runners_minutes_limit, type: Integer, desc: '(admin-only) Extra pipeline minutes quota for this user'
- end
+ use :optional_params_ee
end
params :sort_params do
@@ -85,10 +84,7 @@ module API
use :sort_params
use :pagination
use :with_custom_attributes
-
- if Gitlab.ee?
- optional :skip_ldap, type: Boolean, default: false, desc: 'Skip LDAP users'
- end
+ use :optional_index_params_ee
end
# rubocop: disable CodeReuse/ActiveRecord
get do
diff --git a/lib/api/validations/check_assignees_count.rb b/lib/api/validations/check_assignees_count.rb
new file mode 100644
index 00000000000..836ec936b31
--- /dev/null
+++ b/lib/api/validations/check_assignees_count.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module API
+ module Validations
+ class CheckAssigneesCount < Grape::Validations::Base
+ def self.coerce
+ lambda do |value|
+ case value
+ when String, Array
+ Array.wrap(value)
+ else
+ []
+ end
+ end
+ end
+
+ def validate_param!(attr_name, params)
+ return if param_allowed?(attr_name, params)
+
+ raise Grape::Exceptions::Validation,
+ params: [@scope.full_name(attr_name)],
+ message: "allows one value, but found #{params[attr_name].size}: #{params[attr_name].join(", ")}"
+ end
+
+ private
+
+ def param_allowed?(attr_name, params)
+ params[attr_name].size <= 1
+ end
+ end
+ end
+end
diff --git a/lib/api/variables.rb b/lib/api/variables.rb
index 3489ba827e4..af1d7936556 100644
--- a/lib/api/variables.rb
+++ b/lib/api/variables.rb
@@ -7,6 +7,8 @@ module API
before { authenticate! }
before { authorize! :admin_build, user_project }
+ helpers Helpers::VariablesHelpers
+
helpers do
def filter_variable_parameters(params)
# This method exists so that EE can more easily filter out certain
@@ -54,11 +56,11 @@ module API
params do
requires :key, type: String, desc: 'The key of the variable'
requires :value, type: String, desc: 'The value of the variable'
- optional :protected, type: String, desc: 'Whether the variable is protected'
+ optional :protected, type: Boolean, desc: 'Whether the variable is protected'
+ optional :masked, type: Boolean, desc: 'Whether the variable is masked'
+ optional :variable_type, type: String, values: Ci::Variable.variable_types.keys, desc: 'The type of variable, must be one of env_var or file. Defaults to env_var'
- if Gitlab.ee?
- optional :environment_scope, type: String, desc: 'The environment_scope of the variable'
- end
+ use :optional_params_ee
end
post ':id/variables' do
variable_params = declared_params(include_missing: false)
@@ -79,11 +81,11 @@ module API
params do
optional :key, type: String, desc: 'The key of the variable'
optional :value, type: String, desc: 'The value of the variable'
- optional :protected, type: String, desc: 'Whether the variable is protected'
+ optional :protected, type: Boolean, desc: 'Whether the variable is protected'
+ optional :masked, type: Boolean, desc: 'Whether the variable is masked'
+ optional :variable_type, type: String, values: Ci::Variable.variable_types.keys, desc: 'The type of variable, must be one of env_var or file'
- if Gitlab.ee?
- optional :environment_scope, type: String, desc: 'The environment_scope of the variable'
- end
+ use :optional_params_ee
end
# rubocop: disable CodeReuse/ActiveRecord
put ':id/variables/:key' do
diff --git a/lib/api/wikis.rb b/lib/api/wikis.rb
index 994074ddc67..5724adb2c40 100644
--- a/lib/api/wikis.rb
+++ b/lib/api/wikis.rb
@@ -33,7 +33,8 @@ module API
authorize! :read_wiki, user_project
entity = params[:with_content] ? Entities::WikiPage : Entities::WikiPageBasic
- present user_project.wiki.pages, with: entity
+
+ present user_project.wiki.list_pages(load_content: params[:with_content]), with: entity
end
desc 'Get a wiki page' do
diff --git a/lib/banzai/color_parser.rb b/lib/banzai/color_parser.rb
index 6d01d51955c..cce79e73d2d 100644
--- a/lib/banzai/color_parser.rb
+++ b/lib/banzai/color_parser.rb
@@ -2,13 +2,13 @@
module Banzai
module ColorParser
- ALPHA = /0(?:\.\d+)?|\.\d+|1(?:\.0+)?/ # 0.0..1.0
- PERCENTS = /(?:\d{1,2}|100)%/ # 00%..100%
- ALPHA_CHANNEL = /(?:,\s*(?:#{ALPHA}|#{PERCENTS}))?/
- BITS = /\d{1,2}|1\d\d|2(?:[0-4]\d|5[0-5])/ # 00..255
- DEGS = /-?\d+(?:deg)?/i # [-]digits[deg]
- RADS = /-?(?:\d+(?:\.\d+)?|\.\d+)rad/i # [-](digits[.digits] OR .digits)rad
- HEX_FORMAT = /\#(?:\h{3}|\h{4}|\h{6}|\h{8})/
+ ALPHA = /0(?:\.\d+)?|\.\d+|1(?:\.0+)?/.freeze # 0.0..1.0
+ PERCENTS = /(?:\d{1,2}|100)%/.freeze # 00%..100%
+ ALPHA_CHANNEL = /(?:,\s*(?:#{ALPHA}|#{PERCENTS}))?/.freeze
+ BITS = /\d{1,2}|1\d\d|2(?:[0-4]\d|5[0-5])/.freeze # 00..255
+ DEGS = /-?\d+(?:deg)?/i.freeze # [-]digits[deg]
+ RADS = /-?(?:\d+(?:\.\d+)?|\.\d+)rad/i.freeze # [-](digits[.digits] OR .digits)rad
+ HEX_FORMAT = /\#(?:\h{3}|\h{4}|\h{6}|\h{8})/.freeze
RGB_FORMAT = %r{
(?:rgba?
\(
@@ -20,7 +20,7 @@ module Banzai
#{ALPHA_CHANNEL}
\)
)
- }xi
+ }xi.freeze
HSL_FORMAT = %r{
(?:hsla?
\(
@@ -28,11 +28,11 @@ module Banzai
#{ALPHA_CHANNEL}
\)
)
- }xi
+ }xi.freeze
FORMATS = [HEX_FORMAT, RGB_FORMAT, HSL_FORMAT].freeze
- COLOR_FORMAT = /\A(#{Regexp.union(FORMATS)})\z/ix
+ COLOR_FORMAT = /\A(#{Regexp.union(FORMATS)})\z/ix.freeze
# Public: Analyzes whether the String is a color code.
#
diff --git a/lib/banzai/commit_renderer.rb b/lib/banzai/commit_renderer.rb
index f346151a3c1..2acc9d13f07 100644
--- a/lib/banzai/commit_renderer.rb
+++ b/lib/banzai/commit_renderer.rb
@@ -2,7 +2,7 @@
module Banzai
module CommitRenderer
- ATTRIBUTES = [:description, :title].freeze
+ ATTRIBUTES = [:description, :title, :full_title].freeze
def self.render(commits, project, user = nil)
obj_renderer = ObjectRenderer.new(user: user, default_project: project)
diff --git a/lib/banzai/filter/abstract_reference_filter.rb b/lib/banzai/filter/abstract_reference_filter.rb
index 44b151d01e7..0224dd8fcd1 100644
--- a/lib/banzai/filter/abstract_reference_filter.rb
+++ b/lib/banzai/filter/abstract_reference_filter.rb
@@ -363,6 +363,14 @@ module Banzai
group_ref
end
+
+ def unescape_html_entities(text)
+ CGI.unescapeHTML(text.to_s)
+ end
+
+ def escape_html_entities(text)
+ CGI.escapeHTML(text.to_s)
+ end
end
end
end
diff --git a/lib/banzai/filter/autolink_filter.rb b/lib/banzai/filter/autolink_filter.rb
index 086adf59d2b..56214043d87 100644
--- a/lib/banzai/filter/autolink_filter.rb
+++ b/lib/banzai/filter/autolink_filter.rb
@@ -33,7 +33,7 @@ module Banzai
# https://github.com/vmg/rinku/blob/v2.0.1/ext/rinku/autolink.c#L65
#
# Rubular: http://rubular.com/r/nrL3r9yUiq
- LINK_PATTERN = %r{([a-z][a-z0-9\+\.-]+://[^\s>]+)(?<!\?|!|\.|,|:)}
+ LINK_PATTERN = %r{([a-z][a-z0-9\+\.-]+://[^\s>]+)(?<!\?|!|\.|,|:)}.freeze
# Text matching LINK_PATTERN inside these elements will not be linked
IGNORE_PARENTS = %w(a code kbd pre script style).to_set
diff --git a/lib/banzai/filter/front_matter_filter.rb b/lib/banzai/filter/front_matter_filter.rb
index a27d18facd1..544231adea4 100644
--- a/lib/banzai/filter/front_matter_filter.rb
+++ b/lib/banzai/filter/front_matter_filter.rb
@@ -20,7 +20,7 @@ module Banzai
\s*
^\k<delim> # closing front matter marker
\s*
- }mx
+ }mx.freeze
def call
html.sub(PATTERN) do |_match|
diff --git a/lib/banzai/filter/label_reference_filter.rb b/lib/banzai/filter/label_reference_filter.rb
index 77e4c438bd0..4892668fc22 100644
--- a/lib/banzai/filter/label_reference_filter.rb
+++ b/lib/banzai/filter/label_reference_filter.rb
@@ -82,16 +82,18 @@ module Banzai
def object_link_text(object, matches)
label_suffix = ''
+ parent = project || group
if project || full_path_ref?(matches)
project_path = full_project_path(matches[:namespace], matches[:project])
parent_from_ref = from_ref_cached(project_path)
- reference = parent_from_ref.to_human_reference(project || group)
+ reference = parent_from_ref.to_human_reference(parent)
label_suffix = " <i>in #{reference}</i>" if reference.present?
end
- LabelsHelper.render_colored_label(object, label_suffix: label_suffix, title: tooltip_title(object))
+ presenter = object.present(issuable_subject: parent)
+ LabelsHelper.render_colored_label(presenter, label_suffix: label_suffix, title: tooltip_title(presenter))
end
def tooltip_title(label)
@@ -102,14 +104,6 @@ module Banzai
matches[:namespace] && matches[:project]
end
- def unescape_html_entities(text)
- CGI.unescapeHTML(text.to_s)
- end
-
- def escape_html_entities(text)
- CGI.escapeHTML(text.to_s)
- end
-
def object_link_title(object, matches)
# use title of wrapped element instead
nil
diff --git a/lib/banzai/filter/milestone_reference_filter.rb b/lib/banzai/filter/milestone_reference_filter.rb
index fce042e8946..08969753d75 100644
--- a/lib/banzai/filter/milestone_reference_filter.rb
+++ b/lib/banzai/filter/milestone_reference_filter.rb
@@ -51,13 +51,13 @@ module Banzai
# default implementation.
return super(text, pattern) if pattern != Milestone.reference_pattern
- text.gsub(pattern) do |match|
+ unescape_html_entities(text).gsub(pattern) do |match|
milestone = find_milestone($~[:project], $~[:namespace], $~[:milestone_iid], $~[:milestone_name])
if milestone
yield match, milestone.id, $~[:project], $~[:namespace], $~
else
- match
+ escape_html_entities(match)
end
end
end
diff --git a/lib/banzai/filter/spaced_link_filter.rb b/lib/banzai/filter/spaced_link_filter.rb
index 50bf823929c..ee7f10ebdf6 100644
--- a/lib/banzai/filter/spaced_link_filter.rb
+++ b/lib/banzai/filter/spaced_link_filter.rb
@@ -33,7 +33,7 @@ module Banzai
(?<new_link>.+?)
(?<title>\ ".+?")?
\)
- }x
+ }x.freeze
# Text matching LINK_OR_IMAGE_PATTERN inside these elements will not be linked
IGNORE_PARENTS = %w(a code kbd pre script style).to_set
diff --git a/lib/banzai/filter/table_of_contents_filter.rb b/lib/banzai/filter/table_of_contents_filter.rb
index f2ae17b44fa..ade4d260be1 100644
--- a/lib/banzai/filter/table_of_contents_filter.rb
+++ b/lib/banzai/filter/table_of_contents_filter.rb
@@ -17,7 +17,7 @@ module Banzai
# :toc - String containing Table of Contents data as a `ul` element with
# `li` child elements.
class TableOfContentsFilter < HTML::Pipeline::Filter
- PUNCTUATION_REGEXP = /[^\p{Word}\- ]/u
+ PUNCTUATION_REGEXP = /[^\p{Word}\- ]/u.freeze
def call
return doc if context[:no_header_anchors]
@@ -31,6 +31,7 @@ module Banzai
if header_content = node.children.first
id = node
.text
+ .strip
.downcase
.gsub(PUNCTUATION_REGEXP, '') # remove punctuation
.tr(' ', '-') # replace spaces with dash
diff --git a/lib/banzai/filter/wiki_link_filter/rewriter.rb b/lib/banzai/filter/wiki_link_filter/rewriter.rb
index f4cc8beeb52..77b5053f38c 100644
--- a/lib/banzai/filter/wiki_link_filter/rewriter.rb
+++ b/lib/banzai/filter/wiki_link_filter/rewriter.rb
@@ -4,6 +4,8 @@ module Banzai
module Filter
class WikiLinkFilter < HTML::Pipeline::Filter
class Rewriter
+ UNSAFE_SLUG_REGEXES = [/\Ajavascript:/i].freeze
+
def initialize(link_string, wiki:, slug:)
@uri = Addressable::URI.parse(link_string)
@wiki_base_path = wiki && wiki.wiki_base_path
@@ -35,6 +37,8 @@ module Banzai
# Of the form `./link`, `../link`, or similar
def apply_hierarchical_link_rules!
+ return if slug_considered_unsafe?
+
@uri = Addressable::URI.join(@slug, @uri) if @uri.to_s[0] == '.'
end
@@ -54,6 +58,10 @@ module Banzai
def repository_upload?
@uri.relative? && @uri.path.starts_with?(Wikis::CreateAttachmentService::ATTACHMENT_PATH)
end
+
+ def slug_considered_unsafe?
+ UNSAFE_SLUG_REGEXES.any? { |r| r.match?(@slug) }
+ end
end
end
end
diff --git a/lib/banzai/pipeline/gfm_pipeline.rb b/lib/banzai/pipeline/gfm_pipeline.rb
index 30cafd11834..d67f461be57 100644
--- a/lib/banzai/pipeline/gfm_pipeline.rb
+++ b/lib/banzai/pipeline/gfm_pipeline.rb
@@ -25,7 +25,6 @@ module Banzai
Filter::VideoLinkFilter,
Filter::ImageLazyLoadFilter,
Filter::ImageLinkFilter,
- Filter::EmojiFilter,
Filter::TableOfContentsFilter,
Filter::AutolinkFilter,
Filter::ExternalLinkFilter,
@@ -34,6 +33,7 @@ module Banzai
*reference_filters,
+ Filter::EmojiFilter,
Filter::TaskListFilter,
Filter::InlineDiffFilter,
diff --git a/lib/banzai/redactor.rb b/lib/banzai/redactor.rb
index 7db5f5e1f7d..c2da7fec7cc 100644
--- a/lib/banzai/redactor.rb
+++ b/lib/banzai/redactor.rb
@@ -70,8 +70,11 @@ module Banzai
# Build the raw <a> tag just with a link as href and content if
# it's originally a link pattern. We shouldn't return a plain text href.
original_link =
- if link_reference == 'true' && href = original_content
- %(<a href="#{href}">#{href}</a>)
+ if link_reference == 'true'
+ href = node.attr('href')
+ content = original_content
+
+ %(<a href="#{href}">#{content}</a>)
end
# The reference should be replaced by the original link's content,
diff --git a/lib/bitbucket_server/representation/repo.rb b/lib/bitbucket_server/representation/repo.rb
index 6c494b79166..dab7f8f22a1 100644
--- a/lib/bitbucket_server/representation/repo.rb
+++ b/lib/bitbucket_server/representation/repo.rb
@@ -20,7 +20,7 @@ module BitbucketServer
end
def browse_url
- # The JSON reponse contains an array of 1 element. Not sure if there
+ # The JSON response contains an array of 1 element. Not sure if there
# are cases where multiple links would be provided.
raw.dig('links', 'self').first.fetch('href')
end
diff --git a/lib/declarative_policy/preferred_scope.rb b/lib/declarative_policy/preferred_scope.rb
index 239780d8626..9b7d1548056 100644
--- a/lib/declarative_policy/preferred_scope.rb
+++ b/lib/declarative_policy/preferred_scope.rb
@@ -1,4 +1,3 @@
-# rubocop:disable Naming/FileName
# frozen_string_literal: true
module DeclarativePolicy
diff --git a/lib/gitlab.rb b/lib/gitlab.rb
index 1204e53ee2e..ccaf06c5d6a 100644
--- a/lib/gitlab.rb
+++ b/lib/gitlab.rb
@@ -36,10 +36,11 @@ module Gitlab
end
COM_URL = 'https://gitlab.com'.freeze
- APP_DIRS_PATTERN = %r{^/?(app|config|ee|lib|spec|\(\w*\))}
- SUBDOMAIN_REGEX = %r{\Ahttps://[a-z0-9]+\.gitlab\.com\z}
+ APP_DIRS_PATTERN = %r{^/?(app|config|ee|lib|spec|\(\w*\))}.freeze
+ SUBDOMAIN_REGEX = %r{\Ahttps://[a-z0-9]+\.gitlab\.com\z}.freeze
VERSION = File.read(root.join("VERSION")).strip.freeze
INSTALLATION_TYPE = File.read(root.join("INSTALLATION_TYPE")).strip.freeze
+ HTTP_PROXY_ENV_VARS = %w(http_proxy https_proxy HTTP_PROXY HTTPS_PROXY).freeze
def self.com?
# Check `gl_subdomain?` as well to keep parity with gitlab.com
@@ -59,7 +60,15 @@ module Gitlab
end
def self.ee?
- Object.const_defined?(:License)
+ if ENV['IS_GITLAB_EE'].present?
+ Gitlab::Utils.to_boolean(ENV['IS_GITLAB_EE'])
+ else
+ Object.const_defined?(:License)
+ end
+ end
+
+ def self.http_proxy_env?
+ HTTP_PROXY_ENV_VARS.any? { |name| ENV[name] }
end
def self.process_name
diff --git a/lib/gitlab/action_view_output/context.rb b/lib/gitlab/action_view_output/context.rb
new file mode 100644
index 00000000000..9fbc9811636
--- /dev/null
+++ b/lib/gitlab/action_view_output/context.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+# This file was simplified from https://raw.githubusercontent.com/rails/rails/195f39804a7a4a0034f25e8704220e03d95a752a/actionview/lib/action_view/context.rb.
+#
+# It is only needed by modules that need to call ActionView helper
+# methods (e.g. those in
+# https://github.com/rails/rails/tree/c4d3e202e10ae627b3b9c34498afb45450652421/actionview/lib/action_view/helpers)
+# to generate tags outside of a Rails controller (e.g. API, Sidekiq,
+# etc.).
+#
+# In Rails 5, ActionView::Context automatically includes CompiledTemplates.
+# This means that any module that includes ActionView::Context is now a descendant
+# of CompiledTemplates.
+#
+# When a partial is rendered for the first time, it runs
+# Module#module_eval, which will evaluate a string source that defines a
+# new method. For example:
+#
+# def _app_views_profiles_show_html_haml___1285955918103175884_70307801785400(local_assigns, output_buffer)
+# "hello world"
+# end
+#
+# When a new method is defined, the Ruby interpreter clears the method
+# cache for all descendants, and all methods for those modules will have
+# to be redefined. This can lead to a significant performance penalty.
+#
+# Rails 6 fixes this behavior by moving out the `include
+# CompiledTemplates` into ActionView::Base so that including `ActionView::Context`
+# doesn't quietly affect other modules in this way.
+
+if Rails::VERSION::STRING.start_with?('6')
+ raise 'This module is no longer needed in Rails 6. Use ActionView::Context instead.'
+end
+
+module Gitlab
+ module ActionViewOutput
+ module Context
+ attr_accessor :output_buffer, :view_flow
+ end
+ end
+end
diff --git a/lib/gitlab/asciidoc.rb b/lib/gitlab/asciidoc.rb
index df8f0470063..7f8300a0c2f 100644
--- a/lib/gitlab/asciidoc.rb
+++ b/lib/gitlab/asciidoc.rb
@@ -1,27 +1,41 @@
# frozen_string_literal: true
require 'asciidoctor'
-require 'asciidoctor/converter/html5'
-require "asciidoctor-plantuml"
+require 'asciidoctor-plantuml'
+require 'asciidoctor/extensions'
+require 'gitlab/asciidoc/html5_converter'
module Gitlab
# Parser/renderer for the AsciiDoc format that uses Asciidoctor and filters
# the resulting HTML through HTML pipeline filters.
module Asciidoc
- DEFAULT_ADOC_ATTRS = [
- 'showtitle', 'idprefix=user-content-', 'idseparator=-', 'env=gitlab',
- 'env-gitlab', 'source-highlighter=html-pipeline', 'icons=font',
- 'outfilesuffix=.adoc'
- ].freeze
+ MAX_INCLUDE_DEPTH = 5
+ DEFAULT_ADOC_ATTRS = {
+ 'showtitle' => true,
+ 'idprefix' => 'user-content-',
+ 'idseparator' => '-',
+ 'env' => 'gitlab',
+ 'env-gitlab' => '',
+ 'source-highlighter' => 'html-pipeline',
+ 'icons' => 'font',
+ 'outfilesuffix' => '.adoc',
+ 'max-include-depth' => MAX_INCLUDE_DEPTH
+ }.freeze
# Public: Converts the provided Asciidoc markup into HTML.
#
# input - the source text in Asciidoc format
+ # context - :commit, :project, :ref, :requested_path
#
def self.render(input, context)
+ extensions = proc do
+ include_processor ::Gitlab::Asciidoc::IncludeProcessor.new(context)
+ end
+
asciidoc_opts = { safe: :secure,
backend: :gitlab_html5,
- attributes: DEFAULT_ADOC_ATTRS }
+ attributes: DEFAULT_ADOC_ATTRS,
+ extensions: extensions }
context[:pipeline] = :ascii_doc
@@ -40,29 +54,5 @@ module Gitlab
conf.txt_enable = false
end
end
-
- class Html5Converter < Asciidoctor::Converter::Html5Converter
- extend Asciidoctor::Converter::Config
-
- register_for 'gitlab_html5'
-
- def stem(node)
- return super unless node.style.to_sym == :latexmath
-
- %(<pre#{id_attribute(node)} data-math-style="display"><code>#{node.content}</code></pre>)
- end
-
- def inline_quoted(node)
- return super unless node.type.to_sym == :latexmath
-
- %(<code#{id_attribute(node)} data-math-style="inline">#{node.text}</code>)
- end
-
- private
-
- def id_attribute(node)
- node.id ? %( id="#{node.id}") : nil
- end
- end
end
end
diff --git a/lib/gitlab/asciidoc/html5_converter.rb b/lib/gitlab/asciidoc/html5_converter.rb
new file mode 100644
index 00000000000..2c5c74e4789
--- /dev/null
+++ b/lib/gitlab/asciidoc/html5_converter.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'asciidoctor'
+require 'asciidoctor/converter/html5'
+
+module Gitlab
+ module Asciidoc
+ class Html5Converter < Asciidoctor::Converter::Html5Converter
+ extend Asciidoctor::Converter::Config
+
+ register_for 'gitlab_html5'
+
+ def stem(node)
+ return super unless node.style.to_sym == :latexmath
+
+ %(<pre#{id_attribute(node)} data-math-style="display"><code>#{node.content}</code></pre>)
+ end
+
+ def inline_quoted(node)
+ return super unless node.type.to_sym == :latexmath
+
+ %(<code#{id_attribute(node)} data-math-style="inline">#{node.text}</code>)
+ end
+
+ private
+
+ def id_attribute(node)
+ node.id ? %( id="#{node.id}") : nil
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/asciidoc/include_processor.rb b/lib/gitlab/asciidoc/include_processor.rb
new file mode 100644
index 00000000000..c6fbf540e9c
--- /dev/null
+++ b/lib/gitlab/asciidoc/include_processor.rb
@@ -0,0 +1,126 @@
+# frozen_string_literal: true
+
+require 'asciidoctor/include_ext/include_processor'
+
+module Gitlab
+ module Asciidoc
+ # Asciidoctor extension for processing includes (macro include::[]) within
+ # documents inside the same repository.
+ class IncludeProcessor < Asciidoctor::IncludeExt::IncludeProcessor
+ extend ::Gitlab::Utils::Override
+
+ def initialize(context)
+ super(logger: Gitlab::AppLogger)
+
+ @context = context
+ @repository = context[:project].try(:repository)
+
+ # Note: Asciidoctor calls #freeze on extensions, so we can't set new
+ # instance variables after initialization.
+ @cache = {
+ uri_types: {}
+ }
+ end
+
+ protected
+
+ override :include_allowed?
+ def include_allowed?(target, reader)
+ doc = reader.document
+
+ return false if doc.attributes.fetch('max-include-depth').to_i < 1
+ return false if target_uri?(target)
+
+ true
+ end
+
+ override :resolve_target_path
+ def resolve_target_path(target, reader)
+ return unless repository.try(:exists?)
+
+ base_path = reader.include_stack.empty? ? requested_path : reader.file
+ path = resolve_relative_path(target, base_path)
+
+ path if Gitlab::Git::Blob.find(repository, ref, path)
+ end
+
+ override :read_lines
+ def read_lines(filename, selector)
+ blob = read_blob(ref, filename)
+
+ if selector
+ blob.data.each_line.select.with_index(1, &selector)
+ else
+ blob.data
+ end
+ end
+
+ override :unresolved_include!
+ def unresolved_include!(target, reader)
+ reader.unshift_line("*[ERROR: include::#{target}[] - unresolved directive]*")
+ end
+
+ private
+
+ attr_accessor :context, :repository, :cache
+
+ # Gets a Blob at a path for a specific revision.
+ # This method will check that the Blob exists and contains readable text.
+ #
+ # revision - The String SHA1.
+ # path - The String file path.
+ #
+ # Returns a Blob
+ def read_blob(ref, filename)
+ blob = repository&.blob_at(ref, filename)
+
+ raise 'Blob not found' unless blob
+ raise 'File is not readable' unless blob.readable_text?
+
+ blob
+ end
+
+ # Resolves the given relative path of file in repository into canonical
+ # path based on the specified base_path.
+ #
+ # Examples:
+ #
+ # # File in the same directory as the current path
+ # resolve_relative_path("users.adoc", "doc/api/README.adoc")
+ # # => "doc/api/users.adoc"
+ #
+ # # File in the same directory, which is also the current path
+ # resolve_relative_path("users.adoc", "doc/api")
+ # # => "doc/api/users.adoc"
+ #
+ # # Going up one level to a different directory
+ # resolve_relative_path("../update/7.14-to-8.0.adoc", "doc/api/README.adoc")
+ # # => "doc/update/7.14-to-8.0.adoc"
+ #
+ # Returns a String
+ def resolve_relative_path(path, base_path)
+ p = Pathname(base_path)
+ p = p.dirname unless p.extname.empty?
+ p += path
+
+ p.cleanpath.to_s
+ end
+
+ def current_commit
+ cache[:current_commit] ||= context[:commit] || repository&.commit(ref)
+ end
+
+ def ref
+ context[:ref] || context[:project].default_branch
+ end
+
+ def requested_path
+ cache[:requested_path] ||= Addressable::URI.unescape(context[:requested_path])
+ end
+
+ def uri_type(path)
+ cache[:uri_types][path] ||= current_commit&.uri_type(path)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/auth/o_auth/auth_hash.rb b/lib/gitlab/auth/o_auth/auth_hash.rb
index 36fc8061d92..72a187377d0 100644
--- a/lib/gitlab/auth/o_auth/auth_hash.rb
+++ b/lib/gitlab/auth/o_auth/auth_hash.rb
@@ -55,7 +55,7 @@ module Gitlab
private
def info
- auth_hash.info
+ auth_hash['info']
end
def get_info(key)
diff --git a/lib/gitlab/auth/result.rb b/lib/gitlab/auth/result.rb
index 78fa25c5516..4ebf2afb9cb 100644
--- a/lib/gitlab/auth/result.rb
+++ b/lib/gitlab/auth/result.rb
@@ -1,4 +1,3 @@
-# rubocop:disable Naming/FileName
# frozen_string_literal: true
module Gitlab
diff --git a/lib/gitlab/auth_logger.rb b/lib/gitlab/auth_logger.rb
new file mode 100644
index 00000000000..6d3edba02b0
--- /dev/null
+++ b/lib/gitlab/auth_logger.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Gitlab
+ class AuthLogger < Gitlab::JsonLogger
+ def self.file_name_noext
+ 'auth'
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/calculate_wiki_sizes.rb b/lib/gitlab/background_migration/calculate_wiki_sizes.rb
new file mode 100644
index 00000000000..886c41a2b9d
--- /dev/null
+++ b/lib/gitlab/background_migration/calculate_wiki_sizes.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+# rubocop:disable Style/Documentation
+
+module Gitlab
+ module BackgroundMigration
+ class CalculateWikiSizes
+ def perform(start_id, stop_id)
+ ::ProjectStatistics.where(wiki_size: nil)
+ .where(id: start_id..stop_id)
+ .includes(project: [:route, :group, namespace: [:owner]]).find_each do |statistics|
+ statistics.refresh!(only: [:wiki_size])
+ rescue => e
+ Rails.logger.error "Failed to update wiki statistics. id: #{statistics.id} message: #{e.message}"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/fill_valid_time_for_pages_domain_certificate.rb b/lib/gitlab/background_migration/fill_valid_time_for_pages_domain_certificate.rb
new file mode 100644
index 00000000000..0e93b2cb2fa
--- /dev/null
+++ b/lib/gitlab/background_migration/fill_valid_time_for_pages_domain_certificate.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # save validity time pages domain
+ class FillValidTimeForPagesDomainCertificate
+ # define PagesDomain with only needed code
+ class PagesDomain < ActiveRecord::Base
+ self.table_name = 'pages_domains'
+
+ def x509
+ return unless certificate.present?
+
+ @x509 ||= OpenSSL::X509::Certificate.new(certificate)
+ rescue OpenSSL::X509::CertificateError
+ nil
+ end
+ end
+
+ def perform(start_id, stop_id)
+ PagesDomain.where(id: start_id..stop_id).find_each do |domain|
+ if Gitlab::Database.mysql?
+ domain.update_columns(
+ certificate_valid_not_before: domain.x509&.not_before,
+ certificate_valid_not_after: domain.x509&.not_after
+ )
+ else
+ # for some reason activerecord doesn't append timezone, iso8601 forces this
+ domain.update_columns(
+ certificate_valid_not_before: domain.x509&.not_before&.iso8601,
+ certificate_valid_not_after: domain.x509&.not_after&.iso8601
+ )
+ end
+ rescue => e
+ Rails.logger.error "Failed to update pages domain certificate valid time. id: #{domain.id}, message: #{e.message}"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/fix_cross_project_label_links.rb b/lib/gitlab/background_migration/fix_cross_project_label_links.rb
index 0a12401c35f..bf5d7f5f322 100644
--- a/lib/gitlab/background_migration/fix_cross_project_label_links.rb
+++ b/lib/gitlab/background_migration/fix_cross_project_label_links.rb
@@ -95,7 +95,7 @@ module Gitlab
local_labels = available_labels(project_id)
# get all label links for the given resource (issue/MR)
- # which reference a label not included in avaiable_labels
+ # which reference a label not included in available_labels
# (other than its project labels and labels of ancestor groups)
cross_labels = LabelLink
.select('label_id, labels.title as title, labels.color as color, label_links.id as label_link_id')
diff --git a/lib/gitlab/background_migration/populate_untracked_uploads_dependencies.rb b/lib/gitlab/background_migration/populate_untracked_uploads_dependencies.rb
index a84f794bfae..1924f2ffee2 100644
--- a/lib/gitlab/background_migration/populate_untracked_uploads_dependencies.rb
+++ b/lib/gitlab/background_migration/populate_untracked_uploads_dependencies.rb
@@ -8,8 +8,8 @@ module Gitlab
self.table_name = 'untracked_files_for_uploads'
# Ends with /:random_hex/:filename
- FILE_UPLOADER_PATH = %r{/\h+/[^/]+\z}
- FULL_PATH_CAPTURE = /\A(.+)#{FILE_UPLOADER_PATH}/
+ FILE_UPLOADER_PATH = %r{/\h+/[^/]+\z}.freeze
+ FULL_PATH_CAPTURE = /\A(.+)#{FILE_UPLOADER_PATH}/.freeze
# These regex patterns are tested against a relative path, relative to
# the upload directory.
diff --git a/lib/gitlab/background_migration/prepare_untracked_uploads.rb b/lib/gitlab/background_migration/prepare_untracked_uploads.rb
index 81ca2b0a9b7..1ee44a3a5a9 100644
--- a/lib/gitlab/background_migration/prepare_untracked_uploads.rb
+++ b/lib/gitlab/background_migration/prepare_untracked_uploads.rb
@@ -16,7 +16,7 @@ module Gitlab
RELATIVE_UPLOAD_DIR
)
FOLLOW_UP_MIGRATION = 'PopulateUntrackedUploads'.freeze
- START_WITH_ROOT_REGEX = %r{\A#{Gitlab.config.uploads.storage_path}/}
+ START_WITH_ROOT_REGEX = %r{\A#{Gitlab.config.uploads.storage_path}/}.freeze
EXCLUDED_HASHED_UPLOADS_PATH = "#{ABSOLUTE_UPLOAD_DIR}/@hashed/*".freeze
EXCLUDED_TMP_UPLOADS_PATH = "#{ABSOLUTE_UPLOAD_DIR}/tmp/*".freeze
diff --git a/lib/gitlab/background_migration/reset_merge_status.rb b/lib/gitlab/background_migration/reset_merge_status.rb
new file mode 100644
index 00000000000..447fec8903c
--- /dev/null
+++ b/lib/gitlab/background_migration/reset_merge_status.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Updates the range of given MRs to merge_status "unchecked", if they're opened
+ # and mergeable.
+ class ResetMergeStatus
+ def perform(from_id, to_id)
+ relation = MergeRequest.where(id: from_id..to_id,
+ state: 'opened',
+ merge_status: 'can_be_merged')
+
+ relation.update_all(merge_status: 'unchecked')
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/bitbucket_import/importer.rb b/lib/gitlab/bitbucket_import/importer.rb
index 769d3279f91..c9f0ed66a54 100644
--- a/lib/gitlab/bitbucket_import/importer.rb
+++ b/lib/gitlab/bitbucket_import/importer.rb
@@ -135,7 +135,7 @@ module Gitlab
def create_labels
LABELS.each do |label_params|
- label = ::Labels::CreateService.new(label_params).execute(project: project)
+ label = ::Labels::FindOrCreateService.new(nil, project, label_params).execute(skip_authorization: true)
if label.valid?
@labels[label_params[:title]] = label
else
diff --git a/lib/gitlab/bitbucket_server_import/importer.rb b/lib/gitlab/bitbucket_server_import/importer.rb
index 1d3ddeeb0f1..ff2694abd5e 100644
--- a/lib/gitlab/bitbucket_server_import/importer.rb
+++ b/lib/gitlab/bitbucket_server_import/importer.rb
@@ -201,6 +201,7 @@ module Gitlab
target_branch: Gitlab::Git.ref_name(pull_request.target_branch_name),
target_branch_sha: pull_request.target_branch_sha,
state: pull_request.state,
+ state_id: MergeRequest.available_states[pull_request.state],
author_id: author_id,
assignee_id: nil,
created_at: pull_request.created_at,
diff --git a/lib/gitlab/checks/branch_check.rb b/lib/gitlab/checks/branch_check.rb
index 1dbd564fb6f..4ddc1c718c7 100644
--- a/lib/gitlab/checks/branch_check.rb
+++ b/lib/gitlab/checks/branch_check.rb
@@ -48,7 +48,7 @@ module Gitlab
if project.empty_repo?
protected_branch_push_checks
- elsif creation? && protected_branch_creation_enabled?
+ elsif creation?
protected_branch_creation_checks
elsif deletion?
protected_branch_deletion_checks
@@ -124,10 +124,6 @@ module Gitlab
Gitlab::Routing.url_helpers.project_project_members_url(project)
end
- def protected_branch_creation_enabled?
- Feature.enabled?(:protected_branch_creation, project, default_enabled: true)
- end
-
def matching_merge_request?
Checks::MatchingMergeRequest.new(newrev, branch_name, project).match?
end
diff --git a/lib/gitlab/checks/lfs_check.rb b/lib/gitlab/checks/lfs_check.rb
index cc6a14d2d9a..67a65d61441 100644
--- a/lib/gitlab/checks/lfs_check.rb
+++ b/lib/gitlab/checks/lfs_check.rb
@@ -7,6 +7,7 @@ module Gitlab
ERROR_MESSAGE = 'LFS objects are missing. Ensure LFS is properly set up or try a manual "git lfs push --all".'.freeze
def validate!
+ return unless Feature.enabled?(:lfs_check, default_enabled: true)
return unless project.lfs_enabled?
return if skip_lfs_integrity_check
diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb
index 7011dd1aaf2..1c3ce08be76 100644
--- a/lib/gitlab/ci/build/artifacts/metadata.rb
+++ b/lib/gitlab/ci/build/artifacts/metadata.rb
@@ -11,8 +11,8 @@ module Gitlab
ParserError = Class.new(StandardError)
InvalidStreamError = Class.new(StandardError)
- VERSION_PATTERN = /^[\w\s]+(\d+\.\d+\.\d+)/
- INVALID_PATH_PATTERN = %r{(^\.?\.?/)|(/\.?\.?/)}
+ VERSION_PATTERN = /^[\w\s]+(\d+\.\d+\.\d+)/.freeze
+ INVALID_PATH_PATTERN = %r{(^\.?\.?/)|(/\.?\.?/)}.freeze
attr_reader :stream, :path, :full_version
diff --git a/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb b/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb
index 41135ae62bb..dbdc59505ac 100644
--- a/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb
+++ b/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb
@@ -6,7 +6,10 @@ module Gitlab
module Prerequisite
class KubernetesNamespace < Base
def unmet?
- deployment_cluster.present? && kubernetes_namespace.new_record?
+ deployment_cluster.present? &&
+ deployment_cluster.managed? &&
+ !deployment_cluster.project_type? &&
+ kubernetes_namespace.new_record?
end
def complete!
diff --git a/lib/gitlab/ci/config/entry/image.rb b/lib/gitlab/ci/config/entry/image.rb
index 0beeb44c272..21c42857895 100644
--- a/lib/gitlab/ci/config/entry/image.rb
+++ b/lib/gitlab/ci/config/entry/image.rb
@@ -24,7 +24,7 @@ module Gitlab
end
entry :ports, Entry::Ports,
- description: 'Ports used expose the image'
+ description: 'Ports used to expose the image'
attributes :ports
diff --git a/lib/gitlab/ci/config/entry/job.rb b/lib/gitlab/ci/config/entry/job.rb
index 290c9591b98..762532f7007 100644
--- a/lib/gitlab/ci/config/entry/job.rb
+++ b/lib/gitlab/ci/config/entry/job.rb
@@ -34,7 +34,7 @@ module Gitlab
message: 'should be on_success, on_failure, ' \
'always, manual or delayed' }
validates :dependencies, array_of_strings: true
- validates :extends, type: String
+ validates :extends, array_of_strings_or_string: true
end
validates :start_in, duration: { limit: '1 day' }, if: :delayed?
diff --git a/lib/gitlab/ci/config/entry/service.rb b/lib/gitlab/ci/config/entry/service.rb
index 084fa4047a4..8d16371e857 100644
--- a/lib/gitlab/ci/config/entry/service.rb
+++ b/lib/gitlab/ci/config/entry/service.rb
@@ -24,6 +24,9 @@ module Gitlab
validates :alias, type: String, presence: true, unless: ->(record) { record.ports.blank? }
end
+ entry :ports, Entry::Ports,
+ description: 'Ports used to expose the service'
+
def alias
value[:alias]
end
diff --git a/lib/gitlab/ci/config/extendable/entry.rb b/lib/gitlab/ci/config/extendable/entry.rb
index 7793db09d33..0001a259281 100644
--- a/lib/gitlab/ci/config/extendable/entry.rb
+++ b/lib/gitlab/ci/config/extendable/entry.rb
@@ -5,6 +5,8 @@ module Gitlab
class Config
class Extendable
class Entry
+ include Gitlab::Utils::StrongMemoize
+
InvalidExtensionError = Class.new(Extendable::ExtensionError)
CircularDependencyError = Class.new(Extendable::ExtensionError)
NestingTooDeepError = Class.new(Extendable::ExtensionError)
@@ -28,34 +30,46 @@ module Gitlab
end
def value
- @value ||= @context.fetch(@key)
+ strong_memoize(:value) do
+ @context.fetch(@key)
+ end
end
- def base_hash!
- @base ||= Extendable::Entry
- .new(extends_key, @context, self)
- .extend!
+ def base_hashes!
+ strong_memoize(:base_hashes) do
+ extends_keys.map do |key|
+ Extendable::Entry
+ .new(key, @context, self)
+ .extend!
+ end
+ end
end
- def extends_key
- value.fetch(:extends).to_s.to_sym if extensible?
+ def extends_keys
+ strong_memoize(:extends_keys) do
+ next unless extensible?
+
+ Array(value.fetch(:extends)).map(&:to_s).map(&:to_sym)
+ end
end
def ancestors
- @ancestors ||= Array(@parent&.ancestors) + Array(@parent&.key)
+ strong_memoize(:ancestors) do
+ Array(@parent&.ancestors) + Array(@parent&.key)
+ end
end
def extend!
return value unless extensible?
- if unknown_extension?
+ if unknown_extensions.any?
raise Entry::InvalidExtensionError,
- "#{key}: unknown key in `extends`"
+ "#{key}: unknown keys in `extends` (#{show_keys(unknown_extensions)})"
end
- if invalid_base?
+ if invalid_bases.any?
raise Entry::InvalidExtensionError,
- "#{key}: invalid base hash in `extends`"
+ "#{key}: invalid base hashes in `extends` (#{show_keys(invalid_bases)})"
end
if nesting_too_deep?
@@ -68,11 +82,18 @@ module Gitlab
"#{key}: circular dependency detected in `extends`"
end
- @context[key] = base_hash!.deep_merge(value)
+ merged = {}
+ base_hashes!.each { |h| merged.deep_merge!(h) }
+
+ @context[key] = merged.deep_merge!(value)
end
private
+ def show_keys(keys)
+ keys.join(', ')
+ end
+
def nesting_too_deep?
ancestors.count > MAX_NESTING_LEVELS
end
@@ -81,12 +102,16 @@ module Gitlab
ancestors.include?(key)
end
- def unknown_extension?
- !@context.key?(extends_key)
+ def unknown_extensions
+ strong_memoize(:unknown_extensions) do
+ extends_keys.reject { |key| @context.key?(key) }
+ end
end
- def invalid_base?
- !@context[extends_key].is_a?(Hash)
+ def invalid_bases
+ strong_memoize(:invalid_bases) do
+ extends_keys.reject { |key| @context[key].is_a?(Hash) }
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/command.rb b/lib/gitlab/ci/pipeline/chain/command.rb
index 03af99ba9a5..c911bfa7ff6 100644
--- a/lib/gitlab/ci/pipeline/chain/command.rb
+++ b/lib/gitlab/ci/pipeline/chain/command.rb
@@ -1,4 +1,3 @@
-# rubocop:disable Naming/FileName
# frozen_string_literal: true
module Gitlab
diff --git a/lib/gitlab/ci/pipeline/chain/limit/activity.rb b/lib/gitlab/ci/pipeline/chain/limit/activity.rb
index fe7c8738cc0..68482cf08a9 100644
--- a/lib/gitlab/ci/pipeline/chain/limit/activity.rb
+++ b/lib/gitlab/ci/pipeline/chain/limit/activity.rb
@@ -7,11 +7,11 @@ module Gitlab
module Limit
class Activity < Chain::Base
def perform!
- # to be overriden in EE
+ # to be overridden in EE
end
def break?
- false # to be overriden in EE
+ false # to be overridden in EE
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/limit/size.rb b/lib/gitlab/ci/pipeline/chain/limit/size.rb
index b4d51437cd6..cd330c58406 100644
--- a/lib/gitlab/ci/pipeline/chain/limit/size.rb
+++ b/lib/gitlab/ci/pipeline/chain/limit/size.rb
@@ -7,11 +7,11 @@ module Gitlab
module Limit
class Size < Chain::Base
def perform!
- # to be overriden in EE
+ # to be overridden in EE
end
def break?
- false # to be overriden in EE
+ false # to be overridden in EE
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/skip.rb b/lib/gitlab/ci/pipeline/chain/skip.rb
index 7d6e0704d4a..df92e229f12 100644
--- a/lib/gitlab/ci/pipeline/chain/skip.rb
+++ b/lib/gitlab/ci/pipeline/chain/skip.rb
@@ -7,7 +7,7 @@ module Gitlab
class Skip < Chain::Base
include ::Gitlab::Utils::StrongMemoize
- SKIP_PATTERN = /\[(ci[ _-]skip|skip[ _-]ci)\]/i
+ SKIP_PATTERN = /\[(ci[ _-]skip|skip[ _-]ci)\]/i.freeze
def perform!
if skipped?
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/and.rb b/lib/gitlab/ci/pipeline/expression/lexeme/and.rb
new file mode 100644
index 00000000000..54a0e2ad9dd
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/and.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Pipeline
+ module Expression
+ module Lexeme
+ class And < Lexeme::Operator
+ PATTERN = /&&/.freeze
+
+ def evaluate(variables = {})
+ @left.evaluate(variables) && @right.evaluate(variables)
+ end
+
+ def self.build(_value, behind, ahead)
+ new(behind, ahead)
+ end
+
+ def self.precedence
+ 11 # See: https://ruby-doc.org/core-2.5.0/doc/syntax/precedence_rdoc.html
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/base.rb b/lib/gitlab/ci/pipeline/expression/lexeme/base.rb
index 70c774416f6..7ebd2e25398 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/base.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/base.rb
@@ -15,10 +15,14 @@ module Gitlab
end
def self.scan(scanner)
- if scanner.scan(self::PATTERN)
+ if scanner.scan(pattern)
Expression::Token.new(scanner.matched, self)
end
end
+
+ def self.pattern
+ self::PATTERN
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/equals.rb b/lib/gitlab/ci/pipeline/expression/lexeme/equals.rb
index 668e85f5b9e..62f4c14f597 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/equals.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/equals.rb
@@ -8,11 +8,6 @@ module Gitlab
class Equals < Lexeme::Operator
PATTERN = /==/.freeze
- def initialize(left, right)
- @left = left
- @right = right
- end
-
def evaluate(variables = {})
@left.evaluate(variables) == @right.evaluate(variables)
end
@@ -20,6 +15,10 @@ module Gitlab
def self.build(_value, behind, ahead)
new(behind, ahead)
end
+
+ def self.precedence
+ 10 # See: https://ruby-doc.org/core-2.5.0/doc/syntax/precedence_rdoc.html
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/matches.rb b/lib/gitlab/ci/pipeline/expression/lexeme/matches.rb
index cd17bc4d78b..d7f47c0e7e6 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/matches.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/matches.rb
@@ -8,21 +8,36 @@ module Gitlab
class Matches < Lexeme::Operator
PATTERN = /=~/.freeze
- def initialize(left, right)
- @left = left
- @right = right
- end
-
def evaluate(variables = {})
text = @left.evaluate(variables)
regexp = @right.evaluate(variables)
regexp.scan(text.to_s).any?
+
+ if ci_variables_complex_expressions?
+ # return offset of first match, or nil if no matches
+ if match = regexp.scan(text.to_s).first
+ text.to_s.index(match)
+ end
+ else
+ # return true or false
+ regexp.scan(text.to_s).any?
+ end
end
def self.build(_value, behind, ahead)
new(behind, ahead)
end
+
+ def self.precedence
+ 10 # See: https://ruby-doc.org/core-2.5.0/doc/syntax/precedence_rdoc.html
+ end
+
+ private
+
+ def ci_variables_complex_expressions?
+ Feature.enabled?(:ci_variables_complex_expressions)
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/not_equals.rb b/lib/gitlab/ci/pipeline/expression/lexeme/not_equals.rb
new file mode 100644
index 00000000000..8166bcd5730
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/not_equals.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Pipeline
+ module Expression
+ module Lexeme
+ class NotEquals < Lexeme::Operator
+ PATTERN = /!=/.freeze
+
+ def evaluate(variables = {})
+ @left.evaluate(variables) != @right.evaluate(variables)
+ end
+
+ def self.build(_value, behind, ahead)
+ new(behind, ahead)
+ end
+
+ def self.precedence
+ 10 # See: https://ruby-doc.org/core-2.5.0/doc/syntax/precedence_rdoc.html
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/not_matches.rb b/lib/gitlab/ci/pipeline/expression/lexeme/not_matches.rb
new file mode 100644
index 00000000000..831c27fa0ea
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/not_matches.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Pipeline
+ module Expression
+ module Lexeme
+ class NotMatches < Lexeme::Operator
+ PATTERN = /\!~/.freeze
+
+ def evaluate(variables = {})
+ text = @left.evaluate(variables)
+ regexp = @right.evaluate(variables)
+
+ regexp.scan(text.to_s).none?
+ end
+
+ def self.build(_value, behind, ahead)
+ new(behind, ahead)
+ end
+
+ def self.precedence
+ 10 # See: https://ruby-doc.org/core-2.5.0/doc/syntax/precedence_rdoc.html
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/operator.rb b/lib/gitlab/ci/pipeline/expression/lexeme/operator.rb
index 3ebceb92eb7..3ddab7800c8 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/operator.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/operator.rb
@@ -6,9 +6,29 @@ module Gitlab
module Expression
module Lexeme
class Operator < Lexeme::Base
+ # This operator class is design to handle single operators that take two
+ # arguments. Expression::Parser was originally designed to read infix operators,
+ # and so the two operands are called "left" and "right" here. If we wish to
+ # implement an Operator that takes a greater or lesser number of arguments, a
+ # structural change or additional Operator superclass will likely be needed.
+
+ OperatorError = Class.new(Expression::ExpressionError)
+
+ def initialize(left, right)
+ raise OperatorError, 'Invalid left operand' unless left.respond_to? :evaluate
+ raise OperatorError, 'Invalid right operand' unless right.respond_to? :evaluate
+
+ @left = left
+ @right = right
+ end
+
def self.type
:operator
end
+
+ def self.precedence
+ raise NotImplementedError
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/or.rb b/lib/gitlab/ci/pipeline/expression/lexeme/or.rb
new file mode 100644
index 00000000000..807876f905a
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/or.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Pipeline
+ module Expression
+ module Lexeme
+ class Or < Lexeme::Operator
+ PATTERN = /\|\|/.freeze
+
+ def evaluate(variables = {})
+ @left.evaluate(variables) || @right.evaluate(variables)
+ end
+
+ def self.build(_value, behind, ahead)
+ new(behind, ahead)
+ end
+
+ def self.precedence
+ 12 # See: https://ruby-doc.org/core-2.5.0/doc/syntax/precedence_rdoc.html
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/pattern.rb b/lib/gitlab/ci/pipeline/expression/lexeme/pattern.rb
index 2b719c9c6fc..eb32dffc454 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/pattern.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/pattern.rb
@@ -8,10 +8,11 @@ module Gitlab
require_dependency 're2'
class Pattern < Lexeme::Value
- PATTERN = %r{^/.+/[ismU]*$}.freeze
+ PATTERN = %r{^/.+/[ismU]*$}.freeze
+ NEW_PATTERN = %r{^\/([^\/]|\\/)+[^\\]\/[ismU]*}.freeze
def initialize(regexp)
- @value = regexp
+ @value = self.class.eager_matching_with_escape_characters? ? regexp.gsub(/\\\//, '/') : regexp
unless Gitlab::UntrustedRegexp::RubySyntax.valid?(@value)
raise Lexer::SyntaxError, 'Invalid regular expression!'
@@ -24,9 +25,17 @@ module Gitlab
raise Expression::RuntimeError, 'Invalid regular expression!'
end
+ def self.pattern
+ eager_matching_with_escape_characters? ? NEW_PATTERN : PATTERN
+ end
+
def self.build(string)
new(string)
end
+
+ def self.eager_matching_with_escape_characters?
+ Feature.enabled?(:ci_variables_complex_expressions)
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/expression/lexer.rb b/lib/gitlab/ci/pipeline/expression/lexer.rb
index f26542361a2..23aa1ca4a36 100644
--- a/lib/gitlab/ci/pipeline/expression/lexer.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexer.rb
@@ -15,7 +15,22 @@ module Gitlab
Expression::Lexeme::Pattern,
Expression::Lexeme::Null,
Expression::Lexeme::Equals,
- Expression::Lexeme::Matches
+ Expression::Lexeme::Matches,
+ Expression::Lexeme::NotEquals,
+ Expression::Lexeme::NotMatches
+ ].freeze
+
+ NEW_LEXEMES = [
+ Expression::Lexeme::Variable,
+ Expression::Lexeme::String,
+ Expression::Lexeme::Pattern,
+ Expression::Lexeme::Null,
+ Expression::Lexeme::Equals,
+ Expression::Lexeme::Matches,
+ Expression::Lexeme::NotEquals,
+ Expression::Lexeme::NotMatches,
+ Expression::Lexeme::And,
+ Expression::Lexeme::Or
].freeze
MAX_TOKENS = 100
@@ -43,7 +58,7 @@ module Gitlab
return tokens if @scanner.eos?
- lexeme = LEXEMES.find do |type|
+ lexeme = available_lexemes.find do |type|
type.scan(@scanner).tap do |token|
tokens.push(token) if token.present?
end
@@ -56,6 +71,10 @@ module Gitlab
raise Lexer::SyntaxError, 'Too many tokens!'
end
+
+ def available_lexemes
+ Feature.enabled?(:ci_variables_complex_expressions) ? NEW_LEXEMES : LEXEMES
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/expression/parser.rb b/lib/gitlab/ci/pipeline/expression/parser.rb
index ed184309ab4..0679ed329e5 100644
--- a/lib/gitlab/ci/pipeline/expression/parser.rb
+++ b/lib/gitlab/ci/pipeline/expression/parser.rb
@@ -5,17 +5,30 @@ module Gitlab
module Pipeline
module Expression
class Parser
+ ParseError = Class.new(Expression::ExpressionError)
+
def initialize(tokens)
@tokens = tokens.to_enum
@nodes = []
end
- ##
- # This produces a reverse descent parse tree.
- #
- # It currently does not support precedence of operators.
- #
def tree
+ if Feature.enabled?(:ci_variables_complex_expressions)
+ rpn_parse_tree
+ else
+ reverse_descent_parse_tree
+ end
+ end
+
+ def self.seed(statement)
+ new(Expression::Lexer.new(statement).tokens)
+ end
+
+ private
+
+ # This produces a reverse descent parse tree.
+ # It does not support precedence of operators.
+ def reverse_descent_parse_tree
while token = @tokens.next
case token.type
when :operator
@@ -32,8 +45,51 @@ module Gitlab
@nodes.last || Lexeme::Null.new
end
- def self.seed(statement)
- new(Expression::Lexer.new(statement).tokens)
+ def rpn_parse_tree
+ results = []
+
+ tokens_rpn.each do |token|
+ case token.type
+ when :value
+ results.push(token.build)
+ when :operator
+ right_operand = results.pop
+ left_operand = results.pop
+
+ token.build(left_operand, right_operand).tap do |res|
+ results.push(res)
+ end
+ else
+ raise ParseError, 'Unprocessable token found in parse tree'
+ end
+ end
+
+ raise ParseError, 'Unreachable nodes in parse tree' if results.count > 1
+ raise ParseError, 'Empty parse tree' if results.count < 1
+
+ results.pop
+ end
+
+ # Parse the expression into Reverse Polish Notation
+ # (See: Shunting-yard algorithm)
+ def tokens_rpn
+ output = []
+ operators = []
+
+ @tokens.each do |token|
+ case token.type
+ when :value
+ output.push(token)
+ when :operator
+ if operators.any? && token.lexeme.precedence >= operators.last.lexeme.precedence
+ output.push(operators.pop)
+ end
+
+ operators.push(token)
+ end
+ end
+
+ output.concat(operators.reverse)
end
end
end
diff --git a/lib/gitlab/ci/pipeline/expression/statement.rb b/lib/gitlab/ci/pipeline/expression/statement.rb
index b03611f756e..0e81e1bd34c 100644
--- a/lib/gitlab/ci/pipeline/expression/statement.rb
+++ b/lib/gitlab/ci/pipeline/expression/statement.rb
@@ -7,16 +7,6 @@ module Gitlab
class Statement
StatementError = Class.new(Expression::ExpressionError)
- GRAMMAR = [
- %w[variable],
- %w[variable equals string],
- %w[variable equals variable],
- %w[variable equals null],
- %w[string equals variable],
- %w[null equals variable],
- %w[variable matches pattern]
- ].freeze
-
def initialize(statement, variables = {})
@lexer = Expression::Lexer.new(statement)
@variables = variables.with_indifferent_access
@@ -25,10 +15,6 @@ module Gitlab
def parse_tree
raise StatementError if @lexer.lexemes.empty?
- unless GRAMMAR.find { |syntax| syntax == @lexer.lexemes }
- raise StatementError, 'Unknown pipeline expression!'
- end
-
Expression::Parser.new(@lexer.tokens).tree
end
@@ -43,6 +29,7 @@ module Gitlab
end
def valid?
+ evaluate
parse_tree.is_a?(Lexeme::Base)
rescue Expression::ExpressionError
false
diff --git a/lib/gitlab/ci/status/stage/factory.rb b/lib/gitlab/ci/status/stage/factory.rb
index 58f4642510b..e50b0853725 100644
--- a/lib/gitlab/ci/status/stage/factory.rb
+++ b/lib/gitlab/ci/status/stage/factory.rb
@@ -6,7 +6,8 @@ module Gitlab
module Stage
class Factory < Status::Factory
def self.extended_statuses
- [Status::SuccessWarning]
+ [[Status::SuccessWarning],
+ [Status::Stage::PlayManual]]
end
def self.common_helpers
diff --git a/lib/gitlab/ci/status/stage/play_manual.rb b/lib/gitlab/ci/status/stage/play_manual.rb
new file mode 100644
index 00000000000..ac3fc0912fa
--- /dev/null
+++ b/lib/gitlab/ci/status/stage/play_manual.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Status
+ module Stage
+ class PlayManual < Status::Extended
+ include Gitlab::Routing
+
+ def action_icon
+ 'play'
+ end
+
+ def action_title
+ 'Play all manual'
+ end
+
+ def action_path
+ pipeline = subject.pipeline
+
+ project_stage_play_manual_path(pipeline.project, pipeline, subject.name)
+ end
+
+ def action_method
+ :post
+ end
+
+ def action_button_title
+ _('Play all manual')
+ end
+
+ def self.matches?(stage, user)
+ stage.manual_playable?
+ end
+
+ def has_action?
+ true
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/templates/.yamllint b/lib/gitlab/ci/templates/.yamllint
new file mode 100644
index 00000000000..669c8646ff2
--- /dev/null
+++ b/lib/gitlab/ci/templates/.yamllint
@@ -0,0 +1,5 @@
+extends: default
+
+rules:
+ line-length: disable
+ document-start: disable
diff --git a/lib/gitlab/ci/templates/Android-Fastlane.gitlab-ci.yml b/lib/gitlab/ci/templates/Android-Fastlane.gitlab-ci.yml
index 120272200c6..2ca6e73a803 100644
--- a/lib/gitlab/ci/templates/Android-Fastlane.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Android-Fastlane.gitlab-ci.yml
@@ -54,7 +54,7 @@ ensureContainer:
- rm -f android-signing-keystore.jks || true
artifacts:
paths:
- - app/build/outputs
+ - app/build/outputs
buildDebug:
extends: .build_job
@@ -116,6 +116,6 @@ promoteProduction:
# We only allow production promotion on `master` because
# it has its own production scoped secret variables
only:
- - master
+ - master
script:
- bundle exec fastlane promote_beta_to_production
diff --git a/lib/gitlab/ci/templates/Android.gitlab-ci.yml b/lib/gitlab/ci/templates/Android.gitlab-ci.yml
index 2be7f933462..b7194110002 100644
--- a/lib/gitlab/ci/templates/Android.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Android.gitlab-ci.yml
@@ -6,7 +6,7 @@ image: openjdk:8-jdk
variables:
ANDROID_COMPILE_SDK: "28"
ANDROID_BUILD_TOOLS: "28.0.2"
- ANDROID_SDK_TOOLS: "4333796"
+ ANDROID_SDK_TOOLS: "4333796"
before_script:
- apt-get --quiet update --yes
@@ -35,7 +35,7 @@ assembleDebug:
- ./gradlew assembleDebug
artifacts:
paths:
- - app/build/outputs/
+ - app/build/outputs/
debugTests:
stage: test
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
index 939112e6e41..65a6630365d 100644
--- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -50,8 +50,8 @@ variables:
POSTGRES_DB: $CI_ENVIRONMENT_SLUG
POSTGRES_VERSION: 9.6.2
- KUBERNETES_VERSION: 1.11.9
- HELM_VERSION: 2.13.1
+ KUBERNETES_VERSION: 1.11.10
+ HELM_VERSION: 2.14.0
DOCKER_DRIVER: overlay2
@@ -60,7 +60,7 @@ variables:
stages:
- build
- test
- - deploy # dummy stage to follow the template guidelines
+ - deploy # dummy stage to follow the template guidelines
- review
- dast
- staging
@@ -89,4 +89,4 @@ include:
dast:
except:
refs:
- - master \ No newline at end of file
+ - master
diff --git a/lib/gitlab/ci/templates/C++.gitlab-ci.yml b/lib/gitlab/ci/templates/C++.gitlab-ci.yml
index 9a8fa9d7091..33a2a534508 100644
--- a/lib/gitlab/ci/templates/C++.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/C++.gitlab-ci.yml
@@ -14,10 +14,10 @@ build:
artifacts:
paths:
- mybinary
- # depending on your build setup it's most likely a good idea to cache outputs to reduce the build time
- # cache:
- # paths:
- # - "*.o"
+ # depending on your build setup it's most likely a good idea to cache outputs to reduce the build time
+ # cache:
+ # paths:
+ # - "*.o"
# run tests using the binary built before
test:
diff --git a/lib/gitlab/ci/templates/Chef.gitlab-ci.yml b/lib/gitlab/ci/templates/Chef.gitlab-ci.yml
index 1e14aa8bea9..5f17c93b853 100644
--- a/lib/gitlab/ci/templates/Chef.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Chef.gitlab-ci.yml
@@ -23,31 +23,31 @@ stages:
foodcritic:
stage: lint
script:
- - chef exec foodcritic .
+ - chef exec foodcritic .
cookstyle:
stage: lint
script:
- - chef exec cookstyle .
+ - chef exec cookstyle .
chefspec:
stage: test
script:
- - chef exec rspec spec
+ - chef exec rspec spec
# Set up your test matrix here. Example:
-#verify-centos-6:
-# stage: functional
-# before_script:
-# - apt-get update
-# - apt-get -y install rsync
-# script:
-# - kitchen verify default-centos-6 --destroy=always
+# verify-centos-6:
+# stage: functional
+# before_script:
+# - apt-get update
+# - apt-get -y install rsync
+# script:
+# - kitchen verify default-centos-6 --destroy=always
#
-#verify-centos-7:
-# stage: functional
-# before_script:
-# - apt-get update
-# - apt-get -y install rsync
-# script:
-# - kitchen verify default-centos-7 --destroy=always
+# verify-centos-7:
+# stage: functional
+# before_script:
+# - apt-get update
+# - apt-get -y install rsync
+# script:
+# - kitchen verify default-centos-7 --destroy=always
diff --git a/lib/gitlab/ci/templates/Clojure.gitlab-ci.yml b/lib/gitlab/ci/templates/Clojure.gitlab-ci.yml
index 0610cb9ccc0..c3568c0d2c8 100644
--- a/lib/gitlab/ci/templates/Clojure.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Clojure.gitlab-ci.yml
@@ -8,7 +8,7 @@ before_script:
# If you need to install any external applications, like a
# postgres client, you may want to uncomment the line below:
#
- #- apt-get update -y
+ # - apt-get update -y
#
# Retrieve project dependencies
# Do this on before_script since it'll be shared between both test and
@@ -17,6 +17,6 @@ before_script:
test:
script:
- # If you need to run any migrations or configure the database, this
- # would be the point to do it.
- - lein test
+ # If you need to run any migrations or configure the database, this
+ # would be the point to do it.
+ - lein test
diff --git a/lib/gitlab/ci/templates/Crystal.gitlab-ci.yml b/lib/gitlab/ci/templates/Crystal.gitlab-ci.yml
index 36386a19fdc..e9301a2638d 100644
--- a/lib/gitlab/ci/templates/Crystal.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Crystal.gitlab-ci.yml
@@ -22,15 +22,15 @@ cache:
# services such as redis or postgres
before_script:
- apt-get update -qq && apt-get install -y -qq libxml2-dev
- - crystal -v # Print out Crystal version for debugging
+ - crystal -v # Print out Crystal version for debugging
- shards
# If you are using built-in Crystal Spec.
spec:
script:
- - crystal spec
+ - crystal spec
# If you are using minitest.cr
minitest:
script:
- - crystal test/spec_test.cr # change to the file(s) you execute for tests
+ - crystal test/spec_test.cr # change to the file(s) you execute for tests
diff --git a/lib/gitlab/ci/templates/Django.gitlab-ci.yml b/lib/gitlab/ci/templates/Django.gitlab-ci.yml
index 1d8be6f017e..d35fcb0f807 100644
--- a/lib/gitlab/ci/templates/Django.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Django.gitlab-ci.yml
@@ -16,19 +16,19 @@ variables:
# http://docs.gitlab.com/ce/ci/yaml/README.html#cache
cache:
paths:
- - ~/.cache/pip/
+ - ~/.cache/pip/
# This is a basic example for a gem or script which doesn't use
# services such as redis or postgres
before_script:
- - python -V # Print out python version for debugging
+ - python -V # Print out python version for debugging
# Uncomment next line if your Django app needs a JS runtime:
# - apt-get update -q && apt-get install nodejs -yqq
- pip install -r requirements.txt
# To get Django tests to work you may need to create a settings file using
# the following DATABASES:
-#
+#
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.postgresql_psycopg2',
@@ -46,4 +46,4 @@ test:
variables:
DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB"
script:
- - python manage.py test
+ - python manage.py test
diff --git a/lib/gitlab/ci/templates/Docker.gitlab-ci.yml b/lib/gitlab/ci/templates/Docker.gitlab-ci.yml
index eeefadaa019..f6d240b7b6d 100644
--- a/lib/gitlab/ci/templates/Docker.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Docker.gitlab-ci.yml
@@ -1,14 +1,11 @@
-# Official docker image.
-image: docker:latest
-
-services:
- - docker:dind
-
-before_script:
- - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
-
build-master:
+ # Official docker image.
+ image: docker:latest
stage: build
+ services:
+ - docker:dind
+ before_script:
+ - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- docker build --pull -t "$CI_REGISTRY_IMAGE" .
- docker push "$CI_REGISTRY_IMAGE"
@@ -16,7 +13,13 @@ build-master:
- master
build:
+ # Official docker image.
+ image: docker:latest
stage: build
+ services:
+ - docker:dind
+ before_script:
+ - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- docker build --pull -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" .
- docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG"
diff --git a/lib/gitlab/ci/templates/Elixir.gitlab-ci.yml b/lib/gitlab/ci/templates/Elixir.gitlab-ci.yml
index cf9c731637c..4d4c6a64cd5 100644
--- a/lib/gitlab/ci/templates/Elixir.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Elixir.gitlab-ci.yml
@@ -15,4 +15,4 @@ before_script:
mix:
script:
- - mix test
+ - mix test
diff --git a/lib/gitlab/ci/templates/Go.gitlab-ci.yml b/lib/gitlab/ci/templates/Go.gitlab-ci.yml
index 55fda1a4799..1b686bc6cc0 100644
--- a/lib/gitlab/ci/templates/Go.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Go.gitlab-ci.yml
@@ -16,21 +16,21 @@ before_script:
- cd $GOPATH/src/$REPO_NAME
stages:
- - test
- - build
- - deploy
+ - test
+ - build
+ - deploy
format:
- stage: test
- script:
- - go fmt $(go list ./... | grep -v /vendor/)
- - go vet $(go list ./... | grep -v /vendor/)
- - go test -race $(go list ./... | grep -v /vendor/)
+ stage: test
+ script:
+ - go fmt $(go list ./... | grep -v /vendor/)
+ - go vet $(go list ./... | grep -v /vendor/)
+ - go test -race $(go list ./... | grep -v /vendor/)
compile:
- stage: build
- script:
- - go build -race -ldflags "-extldflags '-static'" -o $CI_PROJECT_DIR/mybinary
- artifacts:
- paths:
- - mybinary
+ stage: build
+ script:
+ - go build -race -ldflags "-extldflags '-static'" -o $CI_PROJECT_DIR/mybinary
+ artifacts:
+ paths:
+ - mybinary
diff --git a/lib/gitlab/ci/templates/Grails.gitlab-ci.yml b/lib/gitlab/ci/templates/Grails.gitlab-ci.yml
index dbc868238f8..efcd1d3ddc0 100644
--- a/lib/gitlab/ci/templates/Grails.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Grails.gitlab-ci.yml
@@ -16,25 +16,25 @@ variables:
# We use SDKMan as tool for managing versions
before_script:
- - apt-get update -qq && apt-get install -y -qq unzip
- - curl -sSL https://get.sdkman.io | bash
- - echo sdkman_auto_answer=true > /root/.sdkman/etc/config
- - source /root/.sdkman/bin/sdkman-init.sh
- - sdk install gradle $GRADLE_VERSION < /dev/null
- - sdk use gradle $GRADLE_VERSION
-# As it's not a good idea to version gradle.properties feel free to add your
-# environments variable here
- - echo grailsVersion=$GRAILS_VERSION > gradle.properties
- - echo gradleWrapperVersion=2.14 >> gradle.properties
-# refresh dependencies from your project
- - ./gradlew --refresh-dependencies
-# Be aware that if you are using Angular profile,
-# Bower cannot be run as root if you don't allow it before.
-# Feel free to remove next line if you are not using Bower
- - echo {\"allow_root\":true} > /root/.bowerrc
+ - apt-get update -qq && apt-get install -y -qq unzip
+ - curl -sSL https://get.sdkman.io | bash
+ - echo sdkman_auto_answer=true > /root/.sdkman/etc/config
+ - source /root/.sdkman/bin/sdkman-init.sh
+ - sdk install gradle $GRADLE_VERSION < /dev/null
+ - sdk use gradle $GRADLE_VERSION
+ # As it's not a good idea to version gradle.properties feel free to add your
+ # environments variable here
+ - echo grailsVersion=$GRAILS_VERSION > gradle.properties
+ - echo gradleWrapperVersion=2.14 >> gradle.properties
+ # refresh dependencies from your project
+ - ./gradlew --refresh-dependencies
+ # Be aware that if you are using Angular profile,
+ # Bower cannot be run as root if you don't allow it before.
+ # Feel free to remove next line if you are not using Bower
+ - echo {\"allow_root\":true} > /root/.bowerrc
# This build job does the full grails pipeline
# (compile, test, integrationTest, war, assemble).
build:
- script:
- - ./gradlew build
+ script:
+ - ./gradlew build
diff --git a/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml
index 546c4affb4e..a09217e8cf0 100644
--- a/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml
@@ -26,8 +26,8 @@ performance:
- mv sitespeed-results/data/performance.json performance.json
artifacts:
paths:
- - performance.json
- - sitespeed-results/
+ - performance.json
+ - sitespeed-results/
only:
refs:
- branches
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
index 1e9591e113b..dcf8254ef94 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
@@ -338,7 +338,6 @@ rollout 100%:
image_tag=${CI_APPLICATION_TAG:-$CI_COMMIT_TAG}
fi
- replicas="1"
service_enabled="true"
postgres_enabled="$POSTGRES_ENABLED"
@@ -383,7 +382,7 @@ rollout 100%:
--set application.database_url="$DATABASE_URL" \
--set application.secretName="$APPLICATION_SECRET_NAME" \
--set application.secretChecksum="$APPLICATION_SECRET_CHECKSUM" \
- --set service.commonName="le.$KUBE_INGRESS_BASE_DOMAIN" \
+ --set service.commonName="le-$CI_PROJECT_ID.$KUBE_INGRESS_BASE_DOMAIN" \
--set service.url="$CI_ENVIRONMENT_URL" \
--set service.additionalHosts="$additional_hosts" \
--set replicaCount="$replicas" \
@@ -394,6 +393,7 @@ rollout 100%:
--set postgresql.postgresDatabase="$POSTGRES_DB" \
--set postgresql.imageTag="$POSTGRES_VERSION" \
--set application.initializeCommand="$DB_INITIALIZE" \
+ $HELM_UPGRADE_EXTRA_ARGS \
--namespace="$KUBE_NAMESPACE" \
"$name" \
chart/
@@ -403,6 +403,7 @@ rollout 100%:
--wait \
--set application.initializeCommand="" \
--set application.migrateCommand="$DB_MIGRATE" \
+ $HELM_UPGRADE_EXTRA_ARGS \
--namespace="$KUBE_NAMESPACE" \
"$name" \
chart/
@@ -422,7 +423,7 @@ rollout 100%:
--set application.database_url="$DATABASE_URL" \
--set application.secretName="$APPLICATION_SECRET_NAME" \
--set application.secretChecksum="$APPLICATION_SECRET_CHECKSUM" \
- --set service.commonName="le.$KUBE_INGRESS_BASE_DOMAIN" \
+ --set service.commonName="le-$CI_PROJECT_ID.$KUBE_INGRESS_BASE_DOMAIN" \
--set service.url="$CI_ENVIRONMENT_URL" \
--set service.additionalHosts="$additional_hosts" \
--set replicaCount="$replicas" \
@@ -431,13 +432,17 @@ rollout 100%:
--set postgresql.postgresUser="$POSTGRES_USER" \
--set postgresql.postgresPassword="$POSTGRES_PASSWORD" \
--set postgresql.postgresDatabase="$POSTGRES_DB" \
+ --set postgresql.imageTag="$POSTGRES_VERSION" \
--set application.migrateCommand="$DB_MIGRATE" \
+ $HELM_UPGRADE_EXTRA_ARGS \
--namespace="$KUBE_NAMESPACE" \
"$name" \
chart/
fi
- kubectl rollout status -n "$KUBE_NAMESPACE" -w "$ROLLOUT_RESOURCE_TYPE/$name"
+ if [[ -z "$ROLLOUT_STATUS_DISABLED" ]]; then
+ kubectl rollout status -n "$KUBE_NAMESPACE" -w "$ROLLOUT_RESOURCE_TYPE/$name"
+ fi
}
function scale() {
@@ -487,7 +492,7 @@ rollout 100%:
fi
helm init --client-only
- helm repo add gitlab ${AUTO_DEVOPS_CHART_REPOSITORY:-https://charts.gitlab.io}
+ helm repo add ${AUTO_DEVOPS_CHART_REPOSITORY_NAME:-gitlab} ${AUTO_DEVOPS_CHART_REPOSITORY:-https://charts.gitlab.io} ${AUTO_DEVOPS_CHART_REPOSITORY_USERNAME:+"--username" "$AUTO_DEVOPS_CHART_REPOSITORY_USERNAME"} ${AUTO_DEVOPS_CHART_REPOSITORY_PASSWORD:+"--password" "$AUTO_DEVOPS_CHART_REPOSITORY_PASSWORD"}
if [[ ! -d "$auto_chart" ]]; then
helm fetch ${auto_chart} --untar
fi
@@ -500,26 +505,16 @@ rollout 100%:
}
function ensure_namespace() {
- kubectl describe namespace "$KUBE_NAMESPACE" || kubectl create namespace "$KUBE_NAMESPACE"
- }
-
- # Function to ensure backwards compatibility with AUTO_DEVOPS_DOMAIN
- function ensure_kube_ingress_base_domain() {
- if [ -z ${KUBE_INGRESS_BASE_DOMAIN+x} ] && [ -n "$AUTO_DEVOPS_DOMAIN" ] ; then
- export KUBE_INGRESS_BASE_DOMAIN=$AUTO_DEVOPS_DOMAIN
- fi
+ kubectl get namespace "$KUBE_NAMESPACE" || kubectl create namespace "$KUBE_NAMESPACE"
}
function check_kube_domain() {
- ensure_kube_ingress_base_domain
-
if [[ -z "$KUBE_INGRESS_BASE_DOMAIN" ]]; then
echo "In order to deploy or use Review Apps,"
- echo "AUTO_DEVOPS_DOMAIN or KUBE_INGRESS_BASE_DOMAIN variables must be set"
+ echo "KUBE_INGRESS_BASE_DOMAIN variables must be set"
echo "From 11.8, you can set KUBE_INGRESS_BASE_DOMAIN in cluster settings"
echo "or by defining a variable at group or project level."
echo "You can also manually add it in .gitlab-ci.yml"
- echo "AUTO_DEVOPS_DOMAIN support will be dropped on 12.0"
false
else
true
diff --git a/lib/gitlab/ci/templates/Julia.gitlab-ci.yml b/lib/gitlab/ci/templates/Julia.gitlab-ci.yml
index 2c4683fbfbb..32d4e07d398 100644
--- a/lib/gitlab/ci/templates/Julia.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Julia.gitlab-ci.yml
@@ -20,7 +20,7 @@
# want coverage results.
- julia -e 'using Pkg; Pkg.clone(pwd()); Pkg.build("MyPackage"); Pkg.test("MyPackage"; coverage = true)'
# Comment out below if you do not want coverage results.
- - julia -e 'using Pkg; Pkg.add("Coverage");
+ - julia -e 'using Pkg; Pkg.add("Coverage");
import MyPackage; cd(joinpath(dirname(pathof(MyPackage)), ".."));
using Coverage; cl, tl = get_summary(process_folder());
println("(", cl/tl*100, "%) covered")'
@@ -55,17 +55,16 @@ pages:
image: julia:0.7
stage: deploy
script:
- - apt-get update -qq && apt-get install -y git # needed by Documenter
- - julia -e 'using Pkg; Pkg.clone(pwd()); Pkg.build("MyPackage");' # rebuild Julia (can be put somewhere else I'm sure
- - julia -e 'using Pkg; import MyPackage; Pkg.add("Documenter")' # install Documenter
- - julia --color=yes docs/make.jl # make documentation
- - mv docs/build public # move to the directory picked up by Gitlab pages
+ - apt-get update -qq && apt-get install -y git # needed by Documenter
+ - julia -e 'using Pkg; Pkg.clone(pwd()); Pkg.build("MyPackage");' # rebuild Julia (can be put somewhere else I'm sure
+ - julia -e 'using Pkg; import MyPackage; Pkg.add("Documenter")' # install Documenter
+ - julia --color=yes docs/make.jl # make documentation
+ - mv docs/build public # move to the directory picked up by Gitlab pages
artifacts:
paths:
- public
only:
- - master
-
+ - master
# WARNING: This template is using the `julia` images from [Docker
# Hub][3]. One can use custom Julia images and/or the official ones found
diff --git a/lib/gitlab/ci/templates/Laravel.gitlab-ci.yml b/lib/gitlab/ci/templates/Laravel.gitlab-ci.yml
index e1cd29ecc94..9bde04dff19 100644
--- a/lib/gitlab/ci/templates/Laravel.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Laravel.gitlab-ci.yml
@@ -16,8 +16,8 @@ variables:
# http://docs.gitlab.com/ce/ci/yaml/README.html#cache
cache:
paths:
- - vendor/
- - node_modules/
+ - vendor/
+ - node_modules/
# This is a basic example for a gem or script which doesn't use
# services such as redis or postgres
@@ -37,7 +37,7 @@ before_script:
- docker-php-ext-enable xdebug
# Install Composer and project dependencies.
- curl -sS https://getcomposer.org/installer | php
- - php composer.phar install
+ - php composer.phar install
# Install Node dependencies.
# comment this out if you don't have a node dependency
- npm install
@@ -63,10 +63,10 @@ before_script:
test:
script:
- # run laravel tests
- - php vendor/bin/phpunit --coverage-text --colors=never
- # run frontend tests
- # if you have any task for testing frontend
- # set it in your package.json script
- # comment this out if you don't have a frontend test
- - npm test
+ # run laravel tests
+ - php vendor/bin/phpunit --coverage-text --colors=never
+ # run frontend tests
+ # if you have any task for testing frontend
+ # set it in your package.json script
+ # comment this out if you don't have a frontend test
+ - npm test
diff --git a/lib/gitlab/ci/templates/Maven.gitlab-ci.yml b/lib/gitlab/ci/templates/Maven.gitlab-ci.yml
index c9838c7a7ff..13ab98d3a16 100644
--- a/lib/gitlab/ci/templates/Maven.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Maven.gitlab-ci.yml
@@ -1,18 +1,14 @@
----
+# This file is a template, and might need editing before it works on your project.
+
# Build JAVA applications using Apache Maven (http://maven.apache.org)
# For docker image tags see https://hub.docker.com/_/maven/
#
# For general lifecycle information see https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
-#
-# This template will build and test your projects as well as create the documentation.
-#
+
+# This template will build and test your projects
# * Caches downloaded dependencies and plugins between invocation.
# * Verify but don't deploy merge requests.
# * Deploy built artifacts from master branch only.
-# * Shows how to use multiple jobs in test stage for verifying functionality
-# with multiple JDKs.
-# * Uses site:stage to collect the documentation for multi-module projects.
-# * Publishes the documentation for `master` branch.
variables:
# This will suppress any download for dependencies and plugins or upload messages which would clutter the console log.
@@ -23,78 +19,38 @@ variables:
# `installAtEnd` and `deployAtEnd` are only effective with recent version of the corresponding plugins.
MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true"
+# This template uses jdk8 for verifying and deploying images
+image: maven:3.3.9-jdk-8
+
# Cache downloaded dependencies and plugins between builds.
# To keep cache across branches add 'key: "$CI_JOB_NAME"'
cache:
paths:
- .m2/repository
-# This will only validate and compile stuff and run e.g. maven-enforcer-plugin.
-# Because some enforcer rules might check dependency convergence and class duplications
-# we use `test-compile` here instead of `validate`, so the correct classpath is picked up.
-.validate: &validate
- stage: build
- script:
- - 'mvn $MAVEN_CLI_OPTS test-compile'
-
# For merge requests do not `deploy` but only run `verify`.
# See https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
.verify: &verify
stage: test
script:
- - 'mvn $MAVEN_CLI_OPTS verify site site:stage'
+ - 'mvn $MAVEN_CLI_OPTS verify'
except:
- master
-# Validate merge requests using JDK7
-validate:jdk7:
- <<: *validate
- image: maven:3.3.9-jdk-7
-
-# Validate merge requests using JDK8
-validate:jdk8:
- <<: *validate
- image: maven:3.3.9-jdk-8
-
-# Verify merge requests using JDK7
-verify:jdk7:
- <<: *verify
- image: maven:3.3.9-jdk-7
-
# Verify merge requests using JDK8
verify:jdk8:
<<: *verify
- image: maven:3.3.9-jdk-8
+# To deploy packages from CI, create a ci_settings.xml file
+# For deploying packages to GitLab's Maven Repository: See https://docs.gitlab.com/ee/user/project/packages/maven_repository.html#creating-maven-packages-with-gitlab-cicd for more details.
+# Please note: The GitLab Maven Repository is currently only available in GitLab Premium / Ultimate.
# For `master` branch run `mvn deploy` automatically.
-# Here you need to decide whether you want to use JDK7 or 8.
-# To get this working you need to define a volume while configuring your gitlab-ci-multi-runner.
-# Mount your `settings.xml` as `/root/.m2/settings.xml` which holds your secrets.
-# See https://maven.apache.org/settings.html
deploy:jdk8:
- # Use stage test here, so the pages job may later pickup the created site.
- stage: test
- script:
- - 'mvn $MAVEN_CLI_OPTS deploy site site:stage'
- only:
- - master
- # Archive up the built documentation site.
- artifacts:
- paths:
- - target/staging
- image: maven:3.3.9-jdk-8
-
-pages:
- image: busybox:latest
stage: deploy
script:
- # Because Maven appends the artifactId automatically to the staging path if you did define a parent pom,
- # you might need to use `mv target/staging/YOUR_ARTIFACT_ID public` instead.
- - mv target/staging public
- dependencies:
- - deploy:jdk8
- artifacts:
- paths:
- - public
+ - if [ ! -f ci_settings.xml ];
+ then echo "CI settings missing\! If deploying to GitLab Maven Repository, please see https://docs.gitlab.com/ee/user/project/packages/maven_repository.html#creating-maven-packages-with-gitlab-cicd for instructions.";
+ fi
+ - 'mvn $MAVEN_CLI_OPTS deploy -s ci_settings.xml'
only:
- master
diff --git a/lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml b/lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml
index 41de1458582..b87178141a1 100644
--- a/lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml
@@ -14,14 +14,14 @@ services:
# http://docs.gitlab.com/ce/ci/yaml/README.html#cache
cache:
paths:
- - node_modules/
+ - node_modules/
test_async:
script:
- - npm install
- - node ./specs/start.js ./specs/async.spec.js
+ - npm install
+ - node ./specs/start.js ./specs/async.spec.js
test_db:
script:
- - npm install
- - node ./specs/start.js ./specs/db-postgres.spec.js
+ - npm install
+ - node ./specs/start.js ./specs/db-postgres.spec.js
diff --git a/lib/gitlab/ci/templates/OpenShift.gitlab-ci.yml b/lib/gitlab/ci/templates/OpenShift.gitlab-ci.yml
index 61a925e0d2d..65abee1f5eb 100644
--- a/lib/gitlab/ci/templates/OpenShift.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/OpenShift.gitlab-ci.yml
@@ -1,9 +1,9 @@
image: ayufan/openshift-cli
stages:
- - build # dummy stage to follow the template guidelines
+ - build # dummy stage to follow the template guidelines
- test
- - deploy # dummy stage to follow the template guidelines
+ - deploy # dummy stage to follow the template guidelines
- review
- staging
- production
diff --git a/lib/gitlab/ci/templates/PHP.gitlab-ci.yml b/lib/gitlab/ci/templates/PHP.gitlab-ci.yml
index 33f44ee9222..b9fee2d5731 100644
--- a/lib/gitlab/ci/templates/PHP.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/PHP.gitlab-ci.yml
@@ -4,19 +4,19 @@ image: php:7.1.1
# Select what we should cache between builds
cache:
paths:
- - vendor/
+ - vendor/
before_script:
-- apt-get update -yqq
-- apt-get install -yqq git libmcrypt-dev libpq-dev libcurl4-gnutls-dev libicu-dev libvpx-dev libjpeg-dev libpng-dev libxpm-dev zlib1g-dev libfreetype6-dev libxml2-dev libexpat1-dev libbz2-dev libgmp3-dev libldap2-dev unixodbc-dev libsqlite3-dev libaspell-dev libsnmp-dev libpcre3-dev libtidy-dev
-# Install PHP extensions
-- docker-php-ext-install mbstring mcrypt pdo_pgsql curl json intl gd xml zip bz2 opcache
-# Install & enable Xdebug for code coverage reports
-- pecl install xdebug
-- docker-php-ext-enable xdebug
-# Install and run Composer
-- curl -sS https://getcomposer.org/installer | php
-- php composer.phar install
+ - apt-get update -yqq
+ - apt-get install -yqq git libmcrypt-dev libpq-dev libcurl4-gnutls-dev libicu-dev libvpx-dev libjpeg-dev libpng-dev libxpm-dev zlib1g-dev libfreetype6-dev libxml2-dev libexpat1-dev libbz2-dev libgmp3-dev libldap2-dev unixodbc-dev libsqlite3-dev libaspell-dev libsnmp-dev libpcre3-dev libtidy-dev
+ # Install PHP extensions
+ - docker-php-ext-install mbstring mcrypt pdo_pgsql curl json intl gd xml zip bz2 opcache
+ # Install & enable Xdebug for code coverage reports
+ - pecl install xdebug
+ - docker-php-ext-enable xdebug
+ # Install and run Composer
+ - curl -sS https://getcomposer.org/installer | php
+ - php composer.phar install
# Bring in any services we need http://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-a-service
# See http://docs.gitlab.com/ce/ci/services/README.html for examples.
@@ -33,4 +33,4 @@ variables:
# If Xdebug was installed you can generate a coverage report and see code coverage metrics.
test:
script:
- - vendor/bin/phpunit --configuration phpunit.xml --coverage-text --colors=never \ No newline at end of file
+ - vendor/bin/phpunit --configuration phpunit.xml --coverage-text --colors=never
diff --git a/lib/gitlab/ci/templates/Pages/Brunch.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Brunch.gitlab-ci.yml
index d6de8cab5d1..d2dd3fbfb75 100644
--- a/lib/gitlab/ci/templates/Pages/Brunch.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Brunch.gitlab-ci.yml
@@ -4,12 +4,12 @@ image: node:4.2.2
pages:
cache:
paths:
- - node_modules/
+ - node_modules/
script:
- - npm install -g brunch
- - brunch build --production
+ - npm install -g brunch
+ - brunch build --production
artifacts:
paths:
- - public
+ - public
only:
- - master
+ - master
diff --git a/lib/gitlab/ci/templates/Pages/Doxygen.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Doxygen.gitlab-ci.yml
index 791afdd23f1..ba422c08614 100644
--- a/lib/gitlab/ci/templates/Pages/Doxygen.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Doxygen.gitlab-ci.yml
@@ -3,11 +3,11 @@ image: alpine
pages:
script:
- - apk update && apk add doxygen
- - doxygen doxygen/Doxyfile
- - mv doxygen/documentation/html/ public/
+ - apk update && apk add doxygen
+ - doxygen doxygen/Doxyfile
+ - mv doxygen/documentation/html/ public/
artifacts:
paths:
- - public
+ - public
only:
- - master
+ - master
diff --git a/lib/gitlab/ci/templates/Pages/Gatsby.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Gatsby.gitlab-ci.yml
index 9df2a4797b2..a683561a455 100644
--- a/lib/gitlab/ci/templates/Pages/Gatsby.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Gatsby.gitlab-ci.yml
@@ -4,14 +4,14 @@ image: node:latest
# http://docs.gitlab.com/ce/ci/yaml/README.html#cache
cache:
paths:
- - node_modules/
+ - node_modules/
pages:
script:
- - yarn install
- - ./node_modules/.bin/gatsby build --prefix-paths
+ - yarn install
+ - ./node_modules/.bin/gatsby build --prefix-paths
artifacts:
paths:
- - public
+ - public
only:
- - master
+ - master
diff --git a/lib/gitlab/ci/templates/Pages/HTML.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/HTML.gitlab-ci.yml
index 249a168aa33..92f25280c6e 100644
--- a/lib/gitlab/ci/templates/Pages/HTML.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/HTML.gitlab-ci.yml
@@ -2,11 +2,11 @@
pages:
stage: deploy
script:
- - mkdir .public
- - cp -r * .public
- - mv .public public
+ - mkdir .public
+ - cp -r * .public
+ - mv .public public
artifacts:
paths:
- - public
+ - public
only:
- - master
+ - master
diff --git a/lib/gitlab/ci/templates/Pages/Harp.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Harp.gitlab-ci.yml
index 4b58003ee10..0e206423fa5 100644
--- a/lib/gitlab/ci/templates/Pages/Harp.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Harp.gitlab-ci.yml
@@ -4,12 +4,12 @@ image: node:4.2.2
pages:
cache:
paths:
- - node_modules
+ - node_modules
script:
- - npm install -g harp
- - harp compile ./ public
+ - npm install -g harp
+ - harp compile ./ public
artifacts:
paths:
- - public
+ - public
only:
- - master
+ - master
diff --git a/lib/gitlab/ci/templates/Pages/Hexo.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Hexo.gitlab-ci.yml
index a9e195370f7..d91a8d7421f 100644
--- a/lib/gitlab/ci/templates/Pages/Hexo.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Hexo.gitlab-ci.yml
@@ -3,15 +3,15 @@ image: node:10.15.3
pages:
script:
- - npm install hexo-cli -g
- - test -e package.json && npm install
- - hexo generate
+ - npm install hexo-cli -g
+ - test -e package.json && npm install
+ - hexo generate
artifacts:
paths:
- - public
+ - public
cache:
paths:
- node_modules
key: project
only:
- - master
+ - master
diff --git a/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml
index f9ddcc6fb0a..9a3ecd1c34f 100644
--- a/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml
@@ -3,15 +3,15 @@ image: dettmering/hugo-build
pages:
script:
- - hugo
+ - hugo
artifacts:
paths:
- - public
+ - public
only:
- - master
+ - master
test:
script:
- - hugo
+ - hugo
except:
- - master
+ - master
diff --git a/lib/gitlab/ci/templates/Pages/Hyde.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Hyde.gitlab-ci.yml
index f5b40f2b9f1..7a441a2f70f 100644
--- a/lib/gitlab/ci/templates/Pages/Hyde.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Hyde.gitlab-ci.yml
@@ -3,7 +3,7 @@ image: python:2.7
cache:
paths:
- - vendor/
+ - vendor/
test:
stage: test
@@ -20,6 +20,6 @@ pages:
- hyde gen -d public
artifacts:
paths:
- - public
+ - public
only:
- master
diff --git a/lib/gitlab/ci/templates/Pages/JBake.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/JBake.gitlab-ci.yml
index 7a485f8d135..886b6c36249 100644
--- a/lib/gitlab/ci/templates/Pages/JBake.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/JBake.gitlab-ci.yml
@@ -4,28 +4,28 @@
# JBake https://jbake.org/ is a Java based, open source, static site/blog generator for developers & designers
#
# This yml works with jBake 2.5.1
-# Feel free to change JBAKE_VERSION version
+# Feel free to change JBAKE_VERSION version
#
# HowTo at: https://jorge.aguilera.gitlab.io/howtojbake/
image: java:8
variables:
- JBAKE_VERSION: 2.5.1
+ JBAKE_VERSION: 2.5.1
# We use SDKMan as tool for managing versions
before_script:
- - apt-get update -qq && apt-get install -y -qq unzip zip
- - curl -sSL https://get.sdkman.io | bash
- - echo sdkman_auto_answer=true > /root/.sdkman/etc/config
- - source /root/.sdkman/bin/sdkman-init.sh
- - sdk install jbake $JBAKE_VERSION < /dev/null
- - sdk use jbake $JBAKE_VERSION
+ - apt-get update -qq && apt-get install -y -qq unzip zip
+ - curl -sSL https://get.sdkman.io | bash
+ - echo sdkman_auto_answer=true > /root/.sdkman/etc/config
+ - source /root/.sdkman/bin/sdkman-init.sh
+ - sdk install jbake $JBAKE_VERSION < /dev/null
+ - sdk use jbake $JBAKE_VERSION
# This build job produced the output directory of your site
pages:
- script:
- - jbake . public
- artifacts:
- paths:
- - public
+ script:
+ - jbake . public
+ artifacts:
+ paths:
+ - public
diff --git a/lib/gitlab/ci/templates/Pages/Jekyll.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Jekyll.gitlab-ci.yml
index 37f50554036..0d742aa282d 100644
--- a/lib/gitlab/ci/templates/Pages/Jekyll.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Jekyll.gitlab-ci.yml
@@ -6,25 +6,24 @@ variables:
JEKYLL_ENV: production
before_script:
-- bundle install
+ - bundle install
test:
stage: test
script:
- - bundle exec jekyll build -d test
+ - bundle exec jekyll build -d test
artifacts:
paths:
- - test
+ - test
except:
- - master
+ - master
pages:
stage: deploy
script:
- - bundle exec jekyll build -d public
+ - bundle exec jekyll build -d public
artifacts:
paths:
- - public
+ - public
only:
- - master
-
+ - master
diff --git a/lib/gitlab/ci/templates/Pages/Jigsaw.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Jigsaw.gitlab-ci.yml
index 5ca4619e200..2d26b86a328 100644
--- a/lib/gitlab/ci/templates/Pages/Jigsaw.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Jigsaw.gitlab-ci.yml
@@ -7,8 +7,8 @@ image: php:7.2
# These folders are cached between builds
cache:
paths:
- - vendor/
- - node_modules/
+ - vendor/
+ - node_modules/
before_script:
# Update packages
@@ -28,10 +28,10 @@ before_script:
pages:
script:
- - npm run production
- - mv build_production public
+ - npm run production
+ - mv build_production public
artifacts:
paths:
- - public
+ - public
only:
- - master
+ - master
diff --git a/lib/gitlab/ci/templates/Pages/Lektor.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Lektor.gitlab-ci.yml
index c5c44a5d86c..93ab8e0be0d 100644
--- a/lib/gitlab/ci/templates/Pages/Lektor.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Lektor.gitlab-ci.yml
@@ -3,10 +3,10 @@ image: python:2.7
pages:
script:
- - pip install lektor
- - lektor build --output-path public
+ - pip install lektor
+ - lektor build --output-path public
artifacts:
paths:
- - public
+ - public
only:
- - master
+ - master
diff --git a/lib/gitlab/ci/templates/Pages/Metalsmith.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Metalsmith.gitlab-ci.yml
index c6ded272150..6524405133a 100644
--- a/lib/gitlab/ci/templates/Pages/Metalsmith.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Metalsmith.gitlab-ci.yml
@@ -4,13 +4,13 @@ image: node:4.2.2
pages:
cache:
paths:
- - node_modules/
+ - node_modules/
script:
- - npm install -g metalsmith
- - npm install
- - make build
+ - npm install -g metalsmith
+ - npm install
+ - make build
artifacts:
paths:
- - public
+ - public
only:
- - master
+ - master
diff --git a/lib/gitlab/ci/templates/Pages/Middleman.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Middleman.gitlab-ci.yml
index 9f4cc0574d6..57ac323dfdf 100644
--- a/lib/gitlab/ci/templates/Pages/Middleman.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Middleman.gitlab-ci.yml
@@ -3,25 +3,25 @@ image: ruby:2.3
cache:
paths:
- - vendor
+ - vendor
test:
script:
- - apt-get update -yqqq
- - apt-get install -y nodejs
- - bundle install --path vendor
- - bundle exec middleman build
+ - apt-get update -yqqq
+ - apt-get install -y nodejs
+ - bundle install --path vendor
+ - bundle exec middleman build
except:
- master
pages:
script:
- - apt-get update -yqqq
- - apt-get install -y nodejs
- - bundle install --path vendor
- - bundle exec middleman build
+ - apt-get update -yqqq
+ - apt-get install -y nodejs
+ - bundle install --path vendor
+ - bundle exec middleman build
artifacts:
paths:
- - public
+ - public
only:
- - master
+ - master
diff --git a/lib/gitlab/ci/templates/Pages/Nanoc.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Nanoc.gitlab-ci.yml
index b469b316ba5..7f037b5f5cf 100644
--- a/lib/gitlab/ci/templates/Pages/Nanoc.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Nanoc.gitlab-ci.yml
@@ -3,10 +3,10 @@ image: ruby:2.3
pages:
script:
- - bundle install -j4
- - nanoc
+ - bundle install -j4
+ - nanoc
artifacts:
paths:
- - public
+ - public
only:
- - master
+ - master
diff --git a/lib/gitlab/ci/templates/Pages/Octopress.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Octopress.gitlab-ci.yml
index 4762ec9acfd..6d912a89bc1 100644
--- a/lib/gitlab/ci/templates/Pages/Octopress.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Octopress.gitlab-ci.yml
@@ -3,13 +3,13 @@ image: ruby:2.3
pages:
script:
- - apt-get update -qq && apt-get install -qq nodejs
- - bundle install -j4
- - bundle exec rake generate
- - mv public .public
- - mv .public/octopress public
+ - apt-get update -qq && apt-get install -qq nodejs
+ - bundle install -j4
+ - bundle exec rake generate
+ - mv public .public
+ - mv .public/octopress public
artifacts:
paths:
- - public
+ - public
only:
- - master
+ - master
diff --git a/lib/gitlab/ci/templates/Pages/Pelican.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Pelican.gitlab-ci.yml
index c5f3154f587..09c6649fc13 100644
--- a/lib/gitlab/ci/templates/Pages/Pelican.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Pelican.gitlab-ci.yml
@@ -3,8 +3,8 @@ image: python:2.7-alpine
pages:
script:
- - pip install -r requirements.txt
- - pelican -s publishconf.py
+ - pip install -r requirements.txt
+ - pelican -s publishconf.py
artifacts:
paths:
- - public/
+ - public/
diff --git a/lib/gitlab/ci/templates/Python.gitlab-ci.yml b/lib/gitlab/ci/templates/Python.gitlab-ci.yml
index 3eaed4e91cd..00b8b94b574 100644
--- a/lib/gitlab/ci/templates/Python.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Python.gitlab-ci.yml
@@ -18,34 +18,34 @@ cache:
- venv/
before_script:
- - python -V # Print out python version for debugging
+ - python -V # Print out python version for debugging
- pip install virtualenv
- virtualenv venv
- source venv/bin/activate
test:
script:
- - python setup.py test
- - pip install tox flake8 # you can also use tox
- - tox -e py36,flake8
+ - python setup.py test
+ - pip install tox flake8 # you can also use tox
+ - tox -e py36,flake8
run:
script:
- - python setup.py bdist_wheel
- # an alternative approach is to install and run:
- - pip install dist/*
- # run the command here
+ - python setup.py bdist_wheel
+ # an alternative approach is to install and run:
+ - pip install dist/*
+ # run the command here
artifacts:
paths:
- - dist/*.whl
+ - dist/*.whl
pages:
script:
- - pip install sphinx sphinx-rtd-theme
- - cd doc ; make html
- - mv build/html/ ../public/
+ - pip install sphinx sphinx-rtd-theme
+ - cd doc ; make html
+ - mv build/html/ ../public/
artifacts:
paths:
- - public
+ - public
only:
- - master
+ - master
diff --git a/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml b/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
index 93196dbd475..b3cad8b858a 100644
--- a/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
@@ -21,7 +21,7 @@ cache:
# This is a basic example for a gem or script which doesn't use
# services such as redis or postgres
before_script:
- - ruby -v # Print out ruby version for debugging
+ - ruby -v # Print out ruby version for debugging
# Uncomment next line if your rails app needs a JS runtime:
# - apt-get update -q && apt-get install nodejs -yqq
- bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby
@@ -29,19 +29,19 @@ before_script:
# Optional - Delete if not using `rubocop`
rubocop:
script:
- - rubocop
+ - rubocop
rspec:
script:
- - rspec spec
+ - rspec spec
rails:
variables:
DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB"
script:
- - rails db:migrate
- - rails db:seed
- - rails test
+ - rails db:migrate
+ - rails db:seed
+ - rails test
# This deploy job uses a simple deploy flow to Heroku, other providers, e.g. AWS Elastic Beanstalk
# are supported too: https://github.com/travis-ci/dpl
@@ -49,5 +49,5 @@ deploy:
type: deploy
environment: production
script:
- - gem install dpl
- - dpl --provider=heroku --app=$HEROKU_APP_NAME --api-key=$HEROKU_PRODUCTION_KEY
+ - gem install dpl
+ - dpl --provider=heroku --app=$HEROKU_APP_NAME --api-key=$HEROKU_PRODUCTION_KEY
diff --git a/lib/gitlab/ci/templates/Rust.gitlab-ci.yml b/lib/gitlab/ci/templates/Rust.gitlab-ci.yml
index cab087c48c7..a25dc38e4e7 100644
--- a/lib/gitlab/ci/templates/Rust.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Rust.gitlab-ci.yml
@@ -5,19 +5,19 @@ image: "rust:latest"
# Optional: Pick zero or more services to be used on all builds.
# Only needed when using a docker container to run your tests in.
# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service
-#services:
-# - mysql:latest
-# - redis:latest
-# - postgres:latest
+# services:
+# - mysql:latest
+# - redis:latest
+# - postgres:latest
# Optional: Install a C compiler, cmake and git into the container.
# You will often need this when you (or any of your dependencies) depends on C code.
-#before_script:
-#- apt-get update -yqq
-#- apt-get install -yqq --no-install-recommends build-essential
+# before_script:
+# - apt-get update -yqq
+# - apt-get install -yqq --no-install-recommends build-essential
# Use cargo to test the project
test:cargo:
script:
- - rustc --version && cargo --version # Print version info for debugging
- - cargo test --all --verbose
+ - rustc --version && cargo --version # Print version info for debugging
+ - cargo test --all --verbose
diff --git a/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
index eef361c19e9..5372ec6cceb 100644
--- a/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
@@ -22,7 +22,10 @@ container_scanning:
DOCKER_SERVICE: docker
DOCKER_HOST: tcp://${DOCKER_SERVICE}:2375/
# https://hub.docker.com/r/arminc/clair-local-scan/tags
- CLAIR_LOCAL_SCAN_VERSION: v2.0.6
+ CLAIR_LOCAL_SCAN_VERSION: v2.0.8_fe9b059d930314b54c78f75afe265955faf4fdc1
+ ## Disable the proxy for clair-local-scan, otherwise Container Scanning will
+ ## fail when a proxy is used.
+ NO_PROXY: ${DOCKER_SERVICE},localhost
allow_failure: true
services:
- docker:stable-dind
diff --git a/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
index 2a90cc9a06c..4b55ffd3771 100644
--- a/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
@@ -1,4 +1,4 @@
-# Read more about this feature here: https://docs.gitlab.com/ee/user/project/merge_requests/dast.html
+# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/dast/
# Configure the scanning tool through the environment variables.
# List of the variables: https://gitlab.com/gitlab-org/security-products/dast#settings
@@ -12,44 +12,29 @@ stages:
dast:
stage: dast
- image: docker:stable
+ image:
+ name: "registry.gitlab.com/gitlab-org/security-products/dast:$CI_SERVER_VERSION_MAJOR-$CI_SERVER_VERSION_MINOR-stable"
variables:
- DOCKER_DRIVER: overlay2
+ # URL to scan:
+ # DAST_WEBSITE: https://example.com/
+ #
+ # Time limit for target availability (scan is attempted even when timeout):
+ # DAST_TARGET_AVAILABILITY_TIMEOUT: 60
+ #
+ # Set these variables to scan with an authenticated user:
+ # DAST_AUTH_URL: https://example.com/sign-in
+ # DAST_USERNAME: john.doe@example.com
+ # DAST_PASSWORD: john-doe-password
+ # DAST_USERNAME_FIELD: session[user] # the name of username field at the sign-in HTML form
+ # DAST_PASSWORD_FIELD: session[password] # the name of password field at the sign-in HTML form
+ # DAST_AUTH_EXCLUDE_URLS: http://example.com/sign-out,http://example.com/sign-out-2 # optional: URLs to skip during the authenticated scan; comma-separated, no spaces in between
+ #
+ # Perform ZAP Full Scan, which includes both passive and active scanning:
+ # DAST_FULL_SCAN_ENABLED: "true"
allow_failure: true
- services:
- - docker:stable-dind
script:
- export DAST_WEBSITE=${DAST_WEBSITE:-$(cat environment_url.txt)}
- - export DAST_VERSION=${SP_VERSION:-$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')}
- - |
- if ! docker info &>/dev/null; then
- if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then
- export DOCKER_HOST='tcp://localhost:2375'
- fi
- fi
- - |
- function dast_run() {
- docker run \
- --env DAST_TARGET_AVAILABILITY_TIMEOUT \
- --volume "$PWD:/output" \
- --volume /var/run/docker.sock:/var/run/docker.sock \
- -w /output \
- "registry.gitlab.com/gitlab-org/security-products/dast:$DAST_VERSION" \
- /analyze -t $DAST_WEBSITE \
- "$@"
- }
- - |
- if [ -n "$DAST_AUTH_URL" ]
- then
- dast_run \
- --auth-url $DAST_AUTH_URL \
- --auth-username $DAST_USERNAME \
- --auth-password $DAST_PASSWORD \
- --auth-username-field $DAST_USERNAME_FIELD \
- --auth-password-field $DAST_PASSWORD_FIELD
- else
- dast_run
- fi
+ - /analyze -t $DAST_WEBSITE
artifacts:
reports:
dast: gl-dast-report.json
diff --git a/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
index 7f80a6e9285..8dd9775c583 100644
--- a/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
@@ -20,16 +20,27 @@ dependency_scanning:
export DOCKER_HOST='tcp://localhost:2375'
fi
fi
+ - | # this is required to avoid undesirable reset of Docker image ENV variables being set on build stage
+ function propagate_env_vars() {
+ CURRENT_ENV=$(printenv)
+
+ for VAR_NAME; do
+ echo $CURRENT_ENV | grep "${VAR_NAME}=" > /dev/null && echo "--env $VAR_NAME "
+ done
+ }
- |
docker run \
- --env DS_ANALYZER_IMAGES \
- --env DS_ANALYZER_IMAGE_PREFIX \
- --env DS_ANALYZER_IMAGE_TAG \
- --env DS_DEFAULT_ANALYZERS \
- --env DEP_SCAN_DISABLE_REMOTE_CHECKS \
- --env DS_DOCKER_CLIENT_NEGOTIATION_TIMEOUT \
- --env DS_PULL_ANALYZER_IMAGE_TIMEOUT \
- --env DS_RUN_ANALYZER_TIMEOUT \
+ $(propagate_env_vars \
+ DS_ANALYZER_IMAGES \
+ DS_ANALYZER_IMAGE_PREFIX \
+ DS_ANALYZER_IMAGE_TAG \
+ DS_DEFAULT_ANALYZERS \
+ DS_EXCLUDED_PATHS \
+ DEP_SCAN_DISABLE_REMOTE_CHECKS \
+ DS_DOCKER_CLIENT_NEGOTIATION_TIMEOUT \
+ DS_PULL_ANALYZER_IMAGE_TIMEOUT \
+ DS_RUN_ANALYZER_TIMEOUT \
+ ) \
--volume "$PWD:/code" \
--volume /var/run/docker.sock:/var/run/docker.sock \
"registry.gitlab.com/gitlab-org/security-products/dependency-scanning:$DS_VERSION" /code
diff --git a/lib/gitlab/ci/templates/Security/License-Management.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/License-Management.gitlab-ci.yml
index 0208beb35b8..b6555e627a1 100644
--- a/lib/gitlab/ci/templates/Security/License-Management.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/License-Management.gitlab-ci.yml
@@ -1,7 +1,7 @@
# Read more about this feature here: https://docs.gitlab.com/ee/user/project/merge_requests/license_management.html
variables:
- LICENSE_MANAGEMENT_SETUP_CMD: '' # If needed, specify a command to setup your environment with a custom package manager.
+ LICENSE_MANAGEMENT_SETUP_CMD: '' # If needed, specify a command to setup your environment with a custom package manager.
license_management:
stage: test
diff --git a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
index b941e89991e..8713b833011 100644
--- a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
@@ -20,18 +20,41 @@ sast:
export DOCKER_HOST='tcp://localhost:2375'
fi
fi
+ - | # this is required to avoid undesirable reset of Docker image ENV variables being set on build stage
+ function propagate_env_vars() {
+ CURRENT_ENV=$(printenv)
+
+ for VAR_NAME; do
+ echo $CURRENT_ENV | grep "${VAR_NAME}=" > /dev/null && echo "--env $VAR_NAME "
+ done
+ }
- |
docker run \
- --env SAST_ANALYZER_IMAGES \
- --env SAST_ANALYZER_IMAGE_PREFIX \
- --env SAST_ANALYZER_IMAGE_TAG \
- --env SAST_DEFAULT_ANALYZERS \
- --env SAST_BRAKEMAN_LEVEL \
- --env SAST_GOSEC_LEVEL \
- --env SAST_FLAWFINDER_LEVEL \
- --env SAST_DOCKER_CLIENT_NEGOTIATION_TIMEOUT \
- --env SAST_PULL_ANALYZER_IMAGE_TIMEOUT \
- --env SAST_RUN_ANALYZER_TIMEOUT \
+ $(propagate_env_vars \
+ SAST_BANDIT_EXCLUDED_PATHS \
+ SAST_ANALYZER_IMAGES \
+ SAST_ANALYZER_IMAGE_PREFIX \
+ SAST_ANALYZER_IMAGE_TAG \
+ SAST_DEFAULT_ANALYZERS \
+ SAST_PULL_ANALYZER_IMAGES \
+ SAST_BRAKEMAN_LEVEL \
+ SAST_FLAWFINDER_LEVEL \
+ SAST_GITLEAKS_ENTROPY_LEVEL \
+ SAST_GOSEC_LEVEL \
+ SAST_EXCLUDED_PATHS \
+ SAST_DOCKER_CLIENT_NEGOTIATION_TIMEOUT \
+ SAST_PULL_ANALYZER_IMAGE_TIMEOUT \
+ SAST_RUN_ANALYZER_TIMEOUT \
+ ANT_HOME \
+ ANT_PATH \
+ GRADLE_PATH \
+ JAVA_OPTS \
+ JAVA_PATH \
+ MAVEN_CLI_OPTS \
+ MAVEN_PATH \
+ MAVEN_REPO_PATH \
+ SBT_PATH \
+ ) \
--volume "$PWD:/code" \
--volume /var/run/docker.sock:/var/run/docker.sock \
"registry.gitlab.com/gitlab-org/security-products/sast:$SAST_VERSION" /app/bin/run /code
diff --git a/lib/gitlab/ci/templates/Serverless.gitlab-ci.yml b/lib/gitlab/ci/templates/Serverless.gitlab-ci.yml
index 0fb7c57ab72..a3db2705bf6 100644
--- a/lib/gitlab/ci/templates/Serverless.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Serverless.gitlab-ci.yml
@@ -8,25 +8,13 @@ stages:
- deploy
.serverless:build:image:
- variables:
- DOCKERFILE: "Dockerfile"
stage: build
- image:
- name: gcr.io/kaniko-project/executor:debug
- entrypoint: [""]
- only:
- refs:
- - master
- script:
- - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
- - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/$DOCKERFILE --destination $CI_REGISTRY_IMAGE
+ image: registry.gitlab.com/gitlab-org/gitlabktl:latest
+ script: /usr/bin/gitlabktl app build
.serverless:deploy:image:
stage: deploy
- image: gcr.io/triggermesh/tm@sha256:e3ee74db94d215bd297738d93577481f3e4db38013326c90d57f873df7ab41d5
- only:
- refs:
- - master
+ image: gcr.io/triggermesh/tm@sha256:3cfdd470a66b741004fb02354319d79f1598c70117ce79978d2e07e192bfb336 # v0.0.11
environment: development
script:
- echo "$CI_REGISTRY_IMAGE"
diff --git a/lib/gitlab/ci/templates/Swift.gitlab-ci.yml b/lib/gitlab/ci/templates/Swift.gitlab-ci.yml
index 9aa4abd4791..ffed7a0fec2 100644
--- a/lib/gitlab/ci/templates/Swift.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Swift.gitlab-ci.yml
@@ -25,7 +25,7 @@ archive_project:
- master
artifacts:
paths:
- - build/ProjectName.ipa
+ - build/ProjectName.ipa
tags:
- ios_11-3
- xcode_9-3
diff --git a/lib/gitlab/ci/templates/dotNET-Core.yml b/lib/gitlab/ci/templates/dotNET-Core.yml
new file mode 100644
index 00000000000..40ca296d7bd
--- /dev/null
+++ b/lib/gitlab/ci/templates/dotNET-Core.yml
@@ -0,0 +1,117 @@
+---
+# This is a simple example illustrating how to build and test .NET Core project
+# with GitLab Continuous Integration / Continuous Delivery.
+
+# ### Specify the Docker image
+#
+# Instead of installing .NET Core SDK manually, a docker image is used
+# with already pre-installed .NET Core SDK.
+#
+# The 'latest' tag targets the latest available version of .NET Core SDK image.
+# If preferred, you can explicitly specify version of .NET Core (e.g. using '2.2-sdk' tag).
+#
+# See other available tags for .NET Core: https://hub.docker.com/r/microsoft/dotnet
+# Learn more about Docker tags: https://docs.docker.com/glossary/?term=tag
+# and the Docker itself: https://opensource.com/resources/what-docker
+image: microsoft/dotnet:latest
+
+# ### Define variables
+#
+variables:
+ # 1) Name of directory where restore and build objects are stored.
+ OBJECTS_DIRECTORY: 'obj'
+ # 2) Name of directory used for keeping restored dependencies.
+ NUGET_PACKAGES_DIRECTORY: '.nuget'
+ # 3) A relative path to the source code from project repository root.
+ # NOTE: Please edit this path so it matches the structure of your project!
+ SOURCE_CODE_PATH: '*/*/'
+
+# ### Define stage list
+#
+# In this example there are only two stages.
+# Initially, the project will be built and then tested.
+stages:
+ - build
+ - test
+
+# ### Define global cache rule
+#
+# Before building the project, all dependencies (e.g. third-party NuGet packages)
+# must be restored. Jobs on GitLab.com's Shared Runners are executed on autoscaled machines.
+#
+# Each machine is used only once (for security reasons) and after that is removed.
+# This means that, before every job, a dependency restore must be performed
+# because restored dependencies are removed along with machines. Fortunately,
+# GitLab provides cache mechanism with the aim of keeping restored dependencies
+# for other jobs.
+#
+# This example shows how to configure cache to pass over restored
+# dependencies for re-use.
+#
+# With global cache rule, cached dependencies will be downloaded before every job
+# and then unpacked to the paths as specified below.
+cache:
+ # Per-stage and per-branch caching.
+ key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG"
+ paths:
+ # Specify three paths that should be cached:
+ #
+ # 1) Main JSON file holding information about package dependency tree, packages versions,
+ # frameworks etc. It also holds information where to the dependencies were restored.
+ - '$SOURCE_CODE_PATH$OBJECTS_DIRECTORY/project.assets.json'
+ # 2) Other NuGet and MSBuild related files. Also needed.
+ - '$SOURCE_CODE_PATH$OBJECTS_DIRECTORY/*.csproj.nuget.*'
+ # 3) Path to the directory where restored dependencies are kept.
+ - '$NUGET_PACKAGES_DIRECTORY'
+ #
+ # 'pull-push' policy means that latest cache will be downloaded (if it exists)
+ # before executing the job, and a newer version will be uploaded afterwards.
+ # Such a setting saves time when there are no changes in referenced third-party
+ # packages.
+ #
+ # For example, if you run a pipeline with changes in your code,
+ # but with no changes within third-party packages which your project is using,
+ # then project restore will happen quickly as all required dependencies
+ # will already be there — unzipped from cache.
+
+ # 'pull-push' policy is the default cache policy, you do not have to specify it explicitly.
+ policy: pull-push
+
+# ### Restore project dependencies
+#
+# NuGet packages by default are restored to '.nuget/packages' directory
+# in the user's home directory. That directory is out of scope of GitLab caching.
+#
+# To get around this, a custom path can be specified using the '--packages <PATH>' option
+# for 'dotnet restore' command. In this example, a temporary directory is created
+# in the root of project repository, so its content can be cached.
+#
+# Learn more about GitLab cache: https://docs.gitlab.com/ee/ci/caching/index.html
+before_script:
+ - 'dotnet restore --packages $NUGET_PACKAGES_DIRECTORY'
+
+build:
+ stage: build
+ # ### Build all projects discovered from solution file.
+ #
+ # Note: this will fail if you have any projects in your solution that are not
+ # .NET Core-based projects (e.g. WCF service), which is based on .NET Framework,
+ # not .NET Core. In this scenario, you will need to build every .NET Core-based
+ # project by explicitly specifying a relative path to the directory
+ # where it is located (e.g. 'dotnet build ./src/ConsoleApp').
+ # Only one project path can be passed as a parameter to 'dotnet build' command.
+ script:
+ - 'dotnet build --no-restore'
+
+tests:
+ stage: test
+ # ### Run the tests
+ #
+ # You can either run tests for all test projects that are defined in your solution
+ # with 'dotnet test' or run tests only for specific project by specifying
+ # a relative path to the directory where it is located (e.g. 'dotnet test ./test/UnitTests').
+ #
+ # You may want to define separate testing jobs for different types of testing
+ # (e.g. integration tests, unit tests etc).
+ script:
+ - 'dotnet test --no-restore'
diff --git a/lib/gitlab/ci/templates/dotNET.gitlab-ci.yml b/lib/gitlab/ci/templates/dotNET.gitlab-ci.yml
index 5e128b793d0..b29f45323f5 100644
--- a/lib/gitlab/ci/templates/dotNET.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/dotNET.gitlab-ci.yml
@@ -3,12 +3,12 @@
# (located in gitlab-runner.exe directory):
# shell = "powershell"
#
-# The script is composed of 3 stages: build, test and deploy.
+# The script is composed of 3 stages: build, test and deploy.
#
# The build stage restores NuGet packages and uses msbuild to build the exe and msi
# One major issue you'll find is that you can't build msi projects from command line
# if you use vdproj. There are workarounds building msi via devenv, but they rarely work
-# The best solution is migrating your vdproj projects to WiX, as it can be build directly
+# The best solution is migrating your vdproj projects to WiX, as it can be build directly
# by msbuild.
#
# The test stage runs nunit from command line against Test project inside your solution
@@ -38,28 +38,28 @@ stages:
build_job:
stage: build
only:
- - tags # the build process will only be started by git tag commits
+ - tags # the build process will only be started by git tag commits
script:
- - '& "$env:NUGET_PATH" restore' # restore Nuget dependencies
- - '& "$env:MSBUILD_PATH" /p:Configuration=Release' # build the project
+ - '& "$env:NUGET_PATH" restore' # restore Nuget dependencies
+ - '& "$env:MSBUILD_PATH" /p:Configuration=Release' # build the project
artifacts:
- expire_in: 1 week # save gitlab server space, we copy the files we need to deploy folder later on
+ expire_in: 1 week # save gitlab server space, we copy the files we need to deploy folder later on
paths:
- - '$env:EXE_RELEASE_FOLDER\YourApp.exe' # saving exe to copy to deploy folder
- - '$env:MSI_RELEASE_FOLDER\YourApp Setup.msi' # saving msi to copy to deploy folder
- - '$env:TEST_FOLDER\' # saving entire Test project so NUnit can run tests
+ - '$env:EXE_RELEASE_FOLDER\YourApp.exe' # saving exe to copy to deploy folder
+ - '$env:MSI_RELEASE_FOLDER\YourApp Setup.msi' # saving msi to copy to deploy folder
+ - '$env:TEST_FOLDER\' # saving entire Test project so NUnit can run tests
test_job:
stage: test
only:
- tags
script:
- - '& "$env:NUNIT_PATH" ".\$env:TEST_FOLDER\Tests.dll"' # running NUnit tests
+ - '& "$env:NUNIT_PATH" ".\$env:TEST_FOLDER\Tests.dll"' # running NUnit tests
artifacts:
- when: always # save test results even when the task fails
- expire_in: 1 week # save gitlab server space, we copy the files we need to deploy folder later on
+ when: always # save test results even when the task fails
+ expire_in: 1 week # save gitlab server space, we copy the files we need to deploy folder later on
paths:
- - '.\TestResult.xml' # saving NUnit results to copy to deploy folder
+ - '.\TestResult.xml' # saving NUnit results to copy to deploy folder
dependencies:
- build_job
@@ -79,7 +79,6 @@ deploy_job:
- 'xcopy /y ".\$env:EXE_RELEASE_FOLDER\YourApp.exe" "$deployFolder"'
- 'xcopy /y ".\$env:MSI_RELEASE_FOLDER\YourApp Setup.msi" "$deployFolder"'
- 'xcopy /y ".\TestResult.xml" "$deployFolder"'
-
dependencies:
- build_job
- test_job
diff --git a/lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml b/lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml
index a4a9e96c1d2..87aea8527d1 100644
--- a/lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml
@@ -1,13 +1,13 @@
# This is a very simple template that mainly relies on FastLane to build and distribute your app.
# Read more about how to use this template on the blog post https://about.gitlab.com/2019/03/06/ios-publishing-with-gitlab-and-fastlane/
-# You will also need fastlane and signing configuration for this to work, along with a MacOS runner.
+# You will also need fastlane and signing configuration for this to work, along with a MacOS runner.
# These details are provided in the blog post.
# Note that when you're using the shell executor for MacOS builds, the
# build and tests run as the identity of the runner logged in user, directly on
# the build host. This is less secure than using container executors, so please
-# take a look at our security implications documentation at
-# https://docs.gitlab.com/runner/security/#usage-of-shell-executor for additional
+# take a look at our security implications documentation at
+# https://docs.gitlab.com/runner/security/#usage-of-shell-executor for additional
# detail on what to keep in mind in this scenario.
stages:
@@ -27,4 +27,4 @@ build:
- bundle exec fastlane build
artifacts:
paths:
- - ./*.ipa
+ - ./*.ipa
diff --git a/lib/gitlab/ci/trace.rb b/lib/gitlab/ci/trace.rb
index bf5f2a31f0e..dfae260239e 100644
--- a/lib/gitlab/ci/trace.rb
+++ b/lib/gitlab/ci/trace.rb
@@ -209,10 +209,7 @@ module Gitlab
end
def paths
- [
- default_path,
- deprecated_path
- ].compact
+ [default_path]
end
def default_directory
@@ -227,15 +224,6 @@ module Gitlab
File.join(default_directory, "#{job.id}.log")
end
- def deprecated_path
- File.join(
- Settings.gitlab_ci.builds_path,
- job.created_at.utc.strftime("%Y_%m"),
- job.project.ci_id.to_s,
- "#{job.id}.log"
- ) if job.project&.ci_id
- end
-
def trace_artifact
job.job_artifacts_trace
end
diff --git a/lib/gitlab/ci/variables/collection/item.rb b/lib/gitlab/ci/variables/collection/item.rb
index 833aa75adb5..aab10aef398 100644
--- a/lib/gitlab/ci/variables/collection/item.rb
+++ b/lib/gitlab/ci/variables/collection/item.rb
@@ -27,13 +27,9 @@ module Gitlab
# don't expose `file` attribute at all (stems from what the runner
# expects).
#
- # If the `variable_masking` feature is enabled we expose the `masked`
- # attribute, otherwise it's not exposed.
- #
def to_runner_variable
@variable.reject do |hash_key, hash_value|
- (hash_key == :file && hash_value == false) ||
- (hash_key == :masked && !Feature.enabled?(:variable_masking))
+ hash_key == :file && hash_value == false
end
end
diff --git a/lib/gitlab/cluster/lifecycle_events.rb b/lib/gitlab/cluster/lifecycle_events.rb
index b05dca409d1..e0f9eb59924 100644
--- a/lib/gitlab/cluster/lifecycle_events.rb
+++ b/lib/gitlab/cluster/lifecycle_events.rb
@@ -44,6 +44,14 @@ module Gitlab
(@master_restart_hooks ||= []) << block
end
+ def on_master_start(&block)
+ if in_clustered_environment?
+ on_before_fork(&block)
+ else
+ on_worker_start(&block)
+ end
+ end
+
#
# Lifecycle integration methods (called from unicorn.rb, puma.rb, etc.)
#
diff --git a/lib/gitlab/cluster/puma_worker_killer_initializer.rb b/lib/gitlab/cluster/puma_worker_killer_initializer.rb
index 4ed9a9a02ab..4affc52b7b0 100644
--- a/lib/gitlab/cluster/puma_worker_killer_initializer.rb
+++ b/lib/gitlab/cluster/puma_worker_killer_initializer.rb
@@ -27,6 +27,9 @@ module Gitlab
# is restarted already, thus periodically restarting workers shouldn't be
# needed.
config.rolling_restart_frequency = false
+
+ observer = Gitlab::Cluster::PumaWorkerKillerObserver.new
+ config.pre_term = observer.callback
end
PumaWorkerKiller.start
diff --git a/lib/gitlab/cluster/puma_worker_killer_observer.rb b/lib/gitlab/cluster/puma_worker_killer_observer.rb
new file mode 100644
index 00000000000..3b4ebc3fbae
--- /dev/null
+++ b/lib/gitlab/cluster/puma_worker_killer_observer.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Cluster
+ class PumaWorkerKillerObserver
+ def initialize
+ @counter = Gitlab::Metrics.counter(:puma_killer_terminations_total, 'Number of workers terminated by PumaWorkerKiller')
+ end
+
+ # returns the Proc to be used as the observer callback block
+ def callback
+ method(:log_termination)
+ end
+
+ private
+
+ def log_termination(worker)
+ labels = { worker: "worker_#{worker.index}" }
+
+ @counter.increment(labels)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/cluster/rack_timeout_observer.rb b/lib/gitlab/cluster/rack_timeout_observer.rb
new file mode 100644
index 00000000000..5182b2be148
--- /dev/null
+++ b/lib/gitlab/cluster/rack_timeout_observer.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Cluster
+ class RackTimeoutObserver
+ TRANSITION_STATES = %i(ready active).freeze
+
+ def initialize
+ @counter = Gitlab::Metrics.counter(:rack_requests_total, 'Number of requests in a given rack state')
+ end
+
+ # returns the Proc to be used as the observer callback block
+ def callback
+ method(:log_timeout_exception)
+ end
+
+ private
+
+ def log_timeout_exception(env)
+ info = env[::Rack::Timeout::ENV_INFO_KEY]
+ return unless info
+ return if TRANSITION_STATES.include?(info.state)
+
+ @counter.increment(labels(info, env))
+ end
+
+ def labels(info, env)
+ params = controller_params(env) || grape_params(env) || {}
+
+ {
+ controller: params['controller'],
+ action: params['action'],
+ route: params['route'],
+ state: info.state
+ }
+ end
+
+ def controller_params(env)
+ env['action_dispatch.request.parameters']
+ end
+
+ def grape_params(env)
+ endpoint = env[Grape::Env::API_ENDPOINT]
+ route = endpoint&.route&.pattern&.origin
+ return unless route
+
+ { 'route' => route }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/config/entry/validators.rb b/lib/gitlab/config/entry/validators.rb
index df34d254c65..6796fcce75f 100644
--- a/lib/gitlab/config/entry/validators.rb
+++ b/lib/gitlab/config/entry/validators.rb
@@ -36,10 +36,10 @@ module Gitlab
class AllowedArrayValuesValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
- unkown_values = value - options[:in]
- unless unkown_values.empty?
+ unknown_values = value - options[:in]
+ unless unknown_values.empty?
record.errors.add(attribute, "contains unknown values: " +
- unkown_values.join(', '))
+ unknown_values.join(', '))
end
end
end
diff --git a/lib/gitlab/content_disposition.rb b/lib/gitlab/content_disposition.rb
index 32207514ce5..ff6154a5b26 100644
--- a/lib/gitlab/content_disposition.rb
+++ b/lib/gitlab/content_disposition.rb
@@ -22,13 +22,13 @@ module Gitlab
end
# rubocop:disable Style/VariableInterpolation
- TRADITIONAL_ESCAPED_CHAR = /[^ A-Za-z0-9!#$+.^_`|~-]/
+ TRADITIONAL_ESCAPED_CHAR = /[^ A-Za-z0-9!#$+.^_`|~-]/.freeze
def ascii_filename
'filename="' + percent_escape(::I18n.transliterate(filename), TRADITIONAL_ESCAPED_CHAR) + '"'
end
- RFC_5987_ESCAPED_CHAR = /[^A-Za-z0-9!#$&+.^_`|~-]/
+ RFC_5987_ESCAPED_CHAR = /[^A-Za-z0-9!#$&+.^_`|~-]/.freeze
# rubocop:enable Style/VariableInterpolation
def utf8_filename
diff --git a/lib/gitlab/danger/helper.rb b/lib/gitlab/danger/helper.rb
index e6cadc83a54..4440033f903 100644
--- a/lib/gitlab/danger/helper.rb
+++ b/lib/gitlab/danger/helper.rb
@@ -1,6 +1,4 @@
# frozen_string_literal: true
-require 'net/http'
-require 'json'
require_relative 'teammate'
@@ -8,7 +6,6 @@ module Gitlab
module Danger
module Helper
RELEASE_TOOLS_BOT = 'gitlab-release-tools-bot'
- ROULETTE_DATA_URL = URI.parse('https://about.gitlab.com/roulette.json').freeze
# Returns a list of all files that have been added, modified or renamed.
# `git.modified_files` might contain paths that already have been renamed,
@@ -60,32 +57,6 @@ module Gitlab
ee? ? 'gitlab-ee' : 'gitlab-ce'
end
- # Looks up the current list of GitLab team members and parses it into a
- # useful form
- #
- # @return [Array<Teammate>]
- def team
- @team ||=
- begin
- rsp = Net::HTTP.get_response(ROULETTE_DATA_URL)
- raise "Failed to read #{ROULETTE_DATA_URL}: #{rsp.code} #{rsp.message}" unless
- rsp.is_a?(Net::HTTPSuccess)
-
- data = JSON.parse(rsp.body)
- data.map { |hash| ::Gitlab::Danger::Teammate.new(hash) }
- rescue JSON::ParserError
- raise "Failed to parse JSON response from #{ROULETTE_DATA_URL}"
- end
- end
-
- # Like +team+, but only returns teammates in the current project, based on
- # project_name.
- #
- # @return [Array<Teammate>]
- def project_team
- team.select { |member| member.in_project?(project_name) }
- end
-
# @return [Hash<String,Array<String>>]
def changes_by_category
all_changed_files.each_with_object(Hash.new { |h, k| h[k] = [] }) do |file, hash|
@@ -116,15 +87,14 @@ module Gitlab
end
CATEGORY_LABELS = {
- docs: "~Documentation",
+ docs: "~Documentation", # Docs are reviewed along DevOps stages, so don't need roulette for now.
none: "",
- qa: "~QA"
+ qa: "~QA",
+ test: "~test for `spec/features/*`"
}.freeze
-
- # rubocop:disable Style/RegexpLiteral
CATEGORIES = {
- %r{\Adoc/} => :docs,
- %r{\A(CONTRIBUTING|LICENSE|MAINTENANCE|PHILOSOPHY|PROCESS|README)(\.md)?\z} => :docs,
+ %r{\Adoc/} => :none, # To reinstate roulette for documentation, set to `:docs`.
+ %r{\A(CONTRIBUTING|LICENSE|MAINTENANCE|PHILOSOPHY|PROCESS|README)(\.md)?\z} => :none, # To reinstate roulette for documentation, set to `:docs`.
%r{\A(ee/)?app/(assets|views)/} => :frontend,
%r{\A(ee/)?app/assets/stylesheets/pages} => :css,
@@ -142,6 +112,8 @@ module Gitlab
\.prettierrc |
\.scss-lint.yml |
\.stylelintrc |
+ \.haml-lint.yml |
+ \.haml-lint_todo.yml |
babel\.config\.js |
jest\.config\.js |
karma\.config\.js |
@@ -152,6 +124,7 @@ module Gitlab
%r{\A(ee/)?app/(?!assets|views)[^/]+} => :backend,
%r{\A(ee/)?(bin|config|danger|generator_templates|lib|rubocop|scripts)/} => :backend,
+ %r{\A(ee/)?spec/features/} => :test,
%r{\A(ee/)?spec/(?!javascripts|frontend)[^/]+} => :backend,
%r{\A(ee/)?vendor/(?!assets)[^/]+} => :backend,
%r{\A(ee/)?vendor/(languages\.yml|licenses\.csv)\z} => :backend,
@@ -167,10 +140,13 @@ module Gitlab
# Fallbacks in case the above patterns miss anything
%r{\.rb\z} => :backend,
- %r{\.(md|txt)\z} => :docs,
+ %r{\.(md|txt)\z} => :none, # To reinstate roulette for documentation, set to `:docs`.
%r{\.js\z} => :frontend
}.freeze
- # rubocop:enable Style/RegexpLiteral
+
+ def new_teammates(usernames)
+ usernames.map { |u| Gitlab::Danger::Teammate.new('username' => u) }
+ end
end
end
end
diff --git a/lib/gitlab/danger/roulette.rb b/lib/gitlab/danger/roulette.rb
new file mode 100644
index 00000000000..25de0a87c9d
--- /dev/null
+++ b/lib/gitlab/danger/roulette.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'net/http'
+require 'json'
+require 'cgi'
+
+require_relative 'teammate'
+
+module Gitlab
+ module Danger
+ module Roulette
+ ROULETTE_DATA_URL = 'https://about.gitlab.com/roulette.json'
+ HTTPError = Class.new(RuntimeError)
+
+ # Looks up the current list of GitLab team members and parses it into a
+ # useful form
+ #
+ # @return [Array<Teammate>]
+ def team
+ @team ||=
+ begin
+ data = http_get_json(ROULETTE_DATA_URL)
+ data.map { |hash| ::Gitlab::Danger::Teammate.new(hash) }
+ rescue JSON::ParserError
+ raise "Failed to parse JSON response from #{ROULETTE_DATA_URL}"
+ end
+ end
+
+ # Like +team+, but only returns teammates in the current project, based on
+ # project_name.
+ #
+ # @return [Array<Teammate>]
+ def project_team(project_name)
+ team.select { |member| member.in_project?(project_name) }
+ end
+
+ def canonical_branch_name(branch_name)
+ branch_name.gsub(/^[ce]e-|-[ce]e$/, '')
+ end
+
+ def new_random(seed)
+ Random.new(Digest::MD5.hexdigest(seed).to_i(16))
+ end
+
+ # Known issue: If someone is rejected due to OOO, and then becomes not OOO, the
+ # selection will change on next spin
+ def spin_for_person(people, random:)
+ people.shuffle(random: random)
+ .find(&method(:valid_person?))
+ end
+
+ private
+
+ def valid_person?(person)
+ !mr_author?(person) && !out_of_office?(person)
+ end
+
+ def mr_author?(person)
+ person.username == gitlab.mr_author
+ end
+
+ def out_of_office?(person)
+ username = CGI.escape(person.username)
+ api_endpoint = "https://gitlab.com/api/v4/users/#{username}/status"
+ response = http_get_json(api_endpoint)
+ response["message"]&.match?(/OOO/i)
+ rescue HTTPError, JSON::ParserError
+ false # this is no worse than not checking for OOO
+ end
+
+ def http_get_json(url)
+ rsp = Net::HTTP.get_response(URI.parse(url))
+
+ unless rsp.is_a?(Net::HTTPSuccess)
+ raise HTTPError, "Failed to read #{url}: #{rsp.code} #{rsp.message}"
+ end
+
+ JSON.parse(rsp.body)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/danger/teammate.rb b/lib/gitlab/danger/teammate.rb
index bfada512727..b44f134f2c1 100644
--- a/lib/gitlab/danger/teammate.rb
+++ b/lib/gitlab/danger/teammate.rb
@@ -3,11 +3,12 @@
module Gitlab
module Danger
class Teammate
- attr_reader :name, :username, :projects
+ attr_reader :name, :username, :role, :projects
def initialize(options = {})
- @name = options['name']
@username = options['username']
+ @name = options['name'] || @username
+ @role = options['role']
@projects = options['projects']
end
@@ -20,20 +21,32 @@ module Gitlab
end
# Traintainers also count as reviewers
- def reviewer?(project, category)
- capabilities(project).include?("reviewer #{category}") || traintainer?(project, category)
+ def reviewer?(project, category, labels)
+ has_capability?(project, category, :reviewer, labels) ||
+ traintainer?(project, category, labels)
end
- def traintainer?(project, category)
- capabilities(project).include?("trainee_maintainer #{category}")
+ def traintainer?(project, category, labels)
+ has_capability?(project, category, :trainee_maintainer, labels)
end
- def maintainer?(project, category)
- capabilities(project).include?("maintainer #{category}")
+ def maintainer?(project, category, labels)
+ has_capability?(project, category, :maintainer, labels)
end
private
+ def has_capability?(project, category, kind, labels)
+ case category
+ when :test
+ area = role[/Test Automation Engineer, (\w+)/, 1]
+
+ area && labels.any?(area) if kind == :reviewer
+ else
+ capabilities(project).include?("#{kind} #{category}")
+ end
+ end
+
def capabilities(project)
Array(projects.fetch(project, []))
end
diff --git a/lib/gitlab/data_builder/deployment.rb b/lib/gitlab/data_builder/deployment.rb
new file mode 100644
index 00000000000..f11e032ab84
--- /dev/null
+++ b/lib/gitlab/data_builder/deployment.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module DataBuilder
+ module Deployment
+ extend self
+
+ def build(deployment)
+ {
+ object_kind: 'deployment',
+ status: deployment.status,
+ deployable_id: deployment.deployable_id,
+ deployable_url: Gitlab::UrlBuilder.build(deployment.deployable),
+ environment: deployment.environment.name,
+ project: deployment.project.hook_attrs,
+ short_sha: deployment.short_sha,
+ user: deployment.user.hook_attrs,
+ user_url: Gitlab::UrlBuilder.build(deployment.user),
+ commit_url: Gitlab::UrlBuilder.build(deployment.commit),
+ commit_title: deployment.commit.title
+ }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/data_builder/note.rb b/lib/gitlab/data_builder/note.rb
index 65601dcdf31..16e62622ed4 100644
--- a/lib/gitlab/data_builder/note.rb
+++ b/lib/gitlab/data_builder/note.rb
@@ -44,6 +44,7 @@ module Gitlab
data[:commit] = build_data_for_commit(project, user, note)
elsif note.for_issue?
data[:issue] = note.noteable.hook_attrs
+ data[:issue][:labels] = note.noteable.labels(&:hook_attrs)
elsif note.for_merge_request?
data[:merge_request] = note.noteable.hook_attrs
elsif note.for_snippet?
diff --git a/lib/gitlab/data_builder/pipeline.rb b/lib/gitlab/data_builder/pipeline.rb
index fa06fb935f7..e1e813849bf 100644
--- a/lib/gitlab/data_builder/pipeline.rb
+++ b/lib/gitlab/data_builder/pipeline.rb
@@ -19,7 +19,7 @@ module Gitlab
def hook_attrs(pipeline)
{
id: pipeline.id,
- ref: pipeline.ref,
+ ref: pipeline.source_ref,
tag: pipeline.tag,
sha: pipeline.sha,
before_sha: pipeline.before_sha,
diff --git a/lib/gitlab/data_builder/push.rb b/lib/gitlab/data_builder/push.rb
index af385d7d4ca..40bda3410e1 100644
--- a/lib/gitlab/data_builder/push.rb
+++ b/lib/gitlab/data_builder/push.rb
@@ -58,7 +58,10 @@ module Gitlab
# }
#
# rubocop:disable Metrics/ParameterLists
- def build(project, user, oldrev, newrev, ref, commits = [], message = nil, commits_count: nil, push_options: {})
+ def build(
+ project:, user:, ref:, oldrev: nil, newrev: nil,
+ commits: [], commits_count: nil, message: nil, push_options: {})
+
commits = Array(commits)
# Total commits count
@@ -113,7 +116,12 @@ module Gitlab
ref = "#{Gitlab::Git::BRANCH_REF_PREFIX}#{project.default_branch}"
commits = project.repository.commits(project.default_branch.to_s, limit: 3)
- build(project, user, commits.last&.id, commits.first&.id, ref, commits)
+ build(project: project,
+ user: user,
+ oldrev: commits.last&.id,
+ newrev: commits.first&.id,
+ ref: ref,
+ commits: commits)
end
def sample_data
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index 7f5eb1188fc..cc61bb7fa02 100644
--- a/lib/gitlab/database/migration_helpers.rb
+++ b/lib/gitlab/database/migration_helpers.rb
@@ -905,6 +905,12 @@ module Gitlab
end
end
+ def remove_foreign_key_if_exists(*args)
+ if foreign_key_exists?(*args)
+ remove_foreign_key(*args)
+ end
+ end
+
def remove_foreign_key_without_error(*args)
remove_foreign_key(*args)
rescue ArgumentError
diff --git a/lib/gitlab/diff/suggestion.rb b/lib/gitlab/diff/suggestion.rb
index 027c7a31bcf..4a3ac2106e2 100644
--- a/lib/gitlab/diff/suggestion.rb
+++ b/lib/gitlab/diff/suggestion.rb
@@ -33,6 +33,8 @@ module Gitlab
end
def to_content
+ return "" if @text.blank?
+
# The parsed suggestion doesn't have information about the correct
# ending characters (we may have a line break, or not), so we take
# this information from the last line being changed (last
diff --git a/lib/gitlab/diff/suggestions_parser.rb b/lib/gitlab/diff/suggestions_parser.rb
index c8c03d5d001..6e17ffaf6ff 100644
--- a/lib/gitlab/diff/suggestions_parser.rb
+++ b/lib/gitlab/diff/suggestions_parser.rb
@@ -10,10 +10,12 @@ module Gitlab
# Returns an array of Gitlab::Diff::Suggestion which represents each
# suggestion in the given text.
#
- def parse(text, position:, project:)
+ def parse(text, position:, project:, supports_suggestion: true)
return [] unless position.complete?
- html = Banzai.render(text, project: nil, no_original_data: true)
+ html = Banzai.render(text, project: nil,
+ no_original_data: true,
+ suggestions_filter_enabled: supports_suggestion)
doc = Nokogiri::HTML(html)
suggestion_nodes = doc.search('pre.suggestion')
diff --git a/lib/gitlab/discussions_diff/highlight_cache.rb b/lib/gitlab/discussions_diff/highlight_cache.rb
index 270cfb89488..369c6b87fb4 100644
--- a/lib/gitlab/discussions_diff/highlight_cache.rb
+++ b/lib/gitlab/discussions_diff/highlight_cache.rb
@@ -52,6 +52,19 @@ module Gitlab
end
end
+ # Clears multiple cache keys at once.
+ #
+ # raw_keys - An Array of unique cache keys, without namespaces.
+ #
+ # It returns the number of cache keys cleared. Ex.: 42
+ def clear_multiple(raw_keys)
+ return [] if raw_keys.empty?
+
+ keys = raw_keys.map { |id| cache_key_for(id) }
+
+ Redis::Cache.with { |redis| redis.del(keys) }
+ end
+
def cache_key_for(raw_key)
"#{cache_key_prefix}:#{raw_key}"
end
diff --git a/lib/gitlab/file_detector.rb b/lib/gitlab/file_detector.rb
index 2770469ca9f..9fc2217ad43 100644
--- a/lib/gitlab/file_detector.rb
+++ b/lib/gitlab/file_detector.rb
@@ -16,6 +16,7 @@ module Gitlab
avatar: /\Alogo\.(png|jpg|gif)\z/,
issue_template: %r{\A\.gitlab/issue_templates/[^/]+\.md\z},
merge_request_template: %r{\A\.gitlab/merge_request_templates/[^/]+\.md\z},
+ metrics_dashboard: %r{\A\.gitlab/dashboards/[^/]+\.yml\z},
xcode_config: %r{\A[^/]*\.(xcodeproj|xcworkspace)(/.+)?\z},
# Configuration files
diff --git a/lib/gitlab/git/object_pool.rb b/lib/gitlab/git/object_pool.rb
index 8eb3c28ab70..d0577d7a4ff 100644
--- a/lib/gitlab/git/object_pool.rb
+++ b/lib/gitlab/git/object_pool.rb
@@ -40,6 +40,10 @@ module Gitlab
@repository ||= Gitlab::Git::Repository.new(storage, relative_path, GL_REPOSITORY, gl_project_path)
end
+ def fetch
+ object_pool_service.fetch(source_repository)
+ end
+
private
def object_pool_service
diff --git a/lib/gitlab/git/pre_receive_error.rb b/lib/gitlab/git/pre_receive_error.rb
index b46d4ba0b02..ef9b1bf5224 100644
--- a/lib/gitlab/git/pre_receive_error.rb
+++ b/lib/gitlab/git/pre_receive_error.rb
@@ -14,7 +14,7 @@ module Gitlab
'GL-HOOK-ERR:' # Messages marked as safe by user
].freeze
- SAFE_MESSAGE_REGEX = /^(#{SAFE_MESSAGE_PREFIXES.join('|')})\s*(?<safe_message>.+)/
+ SAFE_MESSAGE_REGEX = /^(#{SAFE_MESSAGE_PREFIXES.join('|')})\s*(?<safe_message>.+)/.freeze
def initialize(message = '')
super(sanitize(message))
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index be9e926728c..8a2e711ec4e 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -34,34 +34,6 @@ module Gitlab
TagExistsError = Class.new(StandardError)
ChecksumError = Class.new(StandardError)
- class << self
- def create_hooks(repo_path, global_hooks_path)
- local_hooks_path = File.join(repo_path, 'hooks')
- real_local_hooks_path = :not_found
-
- begin
- real_local_hooks_path = File.realpath(local_hooks_path)
- rescue Errno::ENOENT
- # real_local_hooks_path == :not_found
- end
-
- # Do nothing if hooks already exist
- unless real_local_hooks_path == File.realpath(global_hooks_path)
- if File.exist?(local_hooks_path)
- # Move the existing hooks somewhere safe
- FileUtils.mv(
- local_hooks_path,
- "#{local_hooks_path}.old.#{Time.now.to_i}")
- end
-
- # Create the hooks symlink
- FileUtils.ln_sf(global_hooks_path, local_hooks_path)
- end
-
- true
- end
- end
-
# Directory name of repo
attr_reader :name
@@ -118,6 +90,12 @@ module Gitlab
gitaly_repository_client.exists?
end
+ def create_repository
+ wrapped_gitaly_errors do
+ gitaly_repository_client.create_repository
+ end
+ end
+
# Returns an Array of branch names
# sorted by name ASC
def branch_names
@@ -231,12 +209,12 @@ module Gitlab
end
end
- def archive_metadata(ref, storage_path, project_path, format = "tar.gz", append_sha:)
+ def archive_metadata(ref, storage_path, project_path, format = "tar.gz", append_sha:, path: nil)
ref ||= root_ref
commit = Gitlab::Git::Commit.find(self, ref)
return {} if commit.nil?
- prefix = archive_prefix(ref, commit.id, project_path, append_sha: append_sha)
+ prefix = archive_prefix(ref, commit.id, project_path, append_sha: append_sha, path: path)
{
'ArchivePrefix' => prefix,
@@ -248,13 +226,14 @@ module Gitlab
# This is both the filename of the archive (missing the extension) and the
# name of the top-level member of the archive under which all files go
- def archive_prefix(ref, sha, project_path, append_sha:)
+ def archive_prefix(ref, sha, project_path, append_sha:, path:)
append_sha = (ref != sha) if append_sha.nil?
formatted_ref = ref.tr('/', '-')
prefix_segments = [project_path, formatted_ref]
prefix_segments << sha if append_sha
+ prefix_segments << path.tr('/', '-').gsub(%r{^/|/$}, '') if path
prefix_segments.join('-')
end
@@ -303,6 +282,11 @@ module Gitlab
(size.to_f / 1024).round(2)
end
+ # Return git object directory size in bytes
+ def object_directory_size
+ gitaly_repository_client.get_object_directory_size.to_f * 1024
+ end
+
# Build an array of commits.
#
# Usage.
@@ -493,7 +477,7 @@ module Gitlab
end
# Return total diverging commits count
- def diverging_commit_count(from, to, max_count:)
+ def diverging_commit_count(from, to, max_count: 0)
wrapped_gitaly_errors do
gitaly_commit_client.diverging_commit_count(from, to, max_count: max_count)
end
@@ -731,18 +715,29 @@ module Gitlab
end
def compare_source_branch(target_branch_name, source_repository, source_branch_name, straight:)
+ reachable_ref =
+ if source_repository == self
+ source_branch_name
+ else
+ # If a tmp ref was created before for a separate repo comparison (forks),
+ # we're able to short-circuit the tmp ref re-creation:
+ # 1. Take the SHA from the source repo
+ # 2. Read that in the current "target" repo
+ # 3. If that SHA is still known (readable), it means GC hasn't
+ # cleaned it up yet, so we can use it instead re-writing the tmp ref.
+ source_commit_id = source_repository.commit(source_branch_name)&.sha
+ commit(source_commit_id)&.sha if source_commit_id
+ end
+
+ return compare(target_branch_name, reachable_ref, straight: straight) if reachable_ref
+
tmp_ref = "refs/tmp/#{SecureRandom.hex}"
return unless fetch_source_branch!(source_repository, source_branch_name, tmp_ref)
- Gitlab::Git::Compare.new(
- self,
- target_branch_name,
- tmp_ref,
- straight: straight
- )
+ compare(target_branch_name, tmp_ref, straight: straight)
ensure
- delete_refs(tmp_ref)
+ delete_refs(tmp_ref) if tmp_ref
end
def write_ref(ref_path, ref, old_ref: nil)
@@ -816,7 +811,8 @@ module Gitlab
gitaly_repository_client.create_from_snapshot(url, auth)
end
- def rebase(user, rebase_id, branch:, branch_sha:, remote_repository:, remote_branch:)
+ # DEPRECATED: https://gitlab.com/gitlab-org/gitaly/issues/1628
+ def rebase_deprecated(user, rebase_id, branch:, branch_sha:, remote_repository:, remote_branch:)
wrapped_gitaly_errors do
gitaly_operation_client.user_rebase(user, rebase_id,
branch: branch,
@@ -826,6 +822,20 @@ module Gitlab
end
end
+ def rebase(user, rebase_id, branch:, branch_sha:, remote_repository:, remote_branch:, &block)
+ wrapped_gitaly_errors do
+ gitaly_operation_client.rebase(
+ user,
+ rebase_id,
+ branch: branch,
+ branch_sha: branch_sha,
+ remote_repository: remote_repository,
+ remote_branch: remote_branch,
+ &block
+ )
+ end
+ end
+
def rebase_in_progress?(rebase_id)
wrapped_gitaly_errors do
gitaly_repository_client.rebase_in_progress?(rebase_id)
@@ -889,6 +899,12 @@ module Gitlab
end
end
+ def disconnect_alternates
+ wrapped_gitaly_errors do
+ gitaly_repository_client.disconnect_alternates
+ end
+ end
+
def gitaly_repository
Gitlab::GitalyClient::Util.repository(@storage, @relative_path, @gl_repository, @gl_project_path)
end
@@ -998,6 +1014,13 @@ module Gitlab
private
+ def compare(base_ref, head_ref, straight:)
+ Gitlab::Git::Compare.new(self,
+ base_ref,
+ head_ref,
+ straight: straight)
+ end
+
def empty_diff_stats
Gitlab::Git::DiffStatsCollection.new([])
end
diff --git a/lib/gitlab/git/repository_cleaner.rb b/lib/gitlab/git/repository_cleaner.rb
index 2d1d8435cf3..9dd0ddfb44b 100644
--- a/lib/gitlab/git/repository_cleaner.rb
+++ b/lib/gitlab/git/repository_cleaner.rb
@@ -12,9 +12,9 @@ module Gitlab
@repository = repository
end
- def apply_bfg_object_map(io)
+ def apply_bfg_object_map_stream(io, &blk)
wrapped_gitaly_errors do
- gitaly_cleanup_client.apply_bfg_object_map(io)
+ gitaly_cleanup_client.apply_bfg_object_map_stream(io, &blk)
end
end
diff --git a/lib/gitlab/git/rugged_impl/commit.rb b/lib/gitlab/git/rugged_impl/commit.rb
index f6777dfa0c3..bce4fa14fb4 100644
--- a/lib/gitlab/git/rugged_impl/commit.rb
+++ b/lib/gitlab/git/rugged_impl/commit.rb
@@ -21,6 +21,17 @@ module Gitlab
nil
end
+ # This needs to return an array of Gitlab::Git:Commit objects
+ # instead of Rugged::Commit objects to ensure upstream models
+ # operate on a consistent interface. Unlike
+ # Gitlab::Git::Commit.find, Gitlab::Git::Commit.batch_by_oid
+ # doesn't attempt to decorate the result.
+ def rugged_batch_by_oid(repo, oids)
+ oids.map { |oid| rugged_find(repo, oid) }
+ .compact
+ .map { |commit| decorate(repo, commit) }
+ end
+
override :find_commit
def find_commit(repo, commit_id)
if Feature.enabled?(:rugged_find_commit)
@@ -29,6 +40,15 @@ module Gitlab
super
end
end
+
+ override :batch_by_oid
+ def batch_by_oid(repo, oids)
+ if Feature.enabled?(:rugged_list_commits_by_oid)
+ rugged_batch_by_oid(repo, oids)
+ else
+ super
+ end
+ end
end
extend ::Gitlab::Utils::Override
diff --git a/lib/gitlab/git/rugged_impl/repository.rb b/lib/gitlab/git/rugged_impl/repository.rb
index c0a91f59ab9..e91b0ddcd31 100644
--- a/lib/gitlab/git/rugged_impl/repository.rb
+++ b/lib/gitlab/git/rugged_impl/repository.rb
@@ -12,7 +12,7 @@ module Gitlab
module Repository
extend ::Gitlab::Utils::Override
- FEATURE_FLAGS = %i(rugged_find_commit rugged_tree_entries rugged_tree_entry rugged_commit_is_ancestor rugged_commit_tree_entry).freeze
+ FEATURE_FLAGS = %i(rugged_find_commit rugged_tree_entries rugged_tree_entry rugged_commit_is_ancestor rugged_commit_tree_entry rugged_list_commits_by_oid).freeze
def alternate_object_directories
relative_object_directories.map { |d| File.join(path, d) }
diff --git a/lib/gitlab/git/rugged_impl/tree.rb b/lib/gitlab/git/rugged_impl/tree.rb
index bb13d114d46..9c37bb01961 100644
--- a/lib/gitlab/git/rugged_impl/tree.rb
+++ b/lib/gitlab/git/rugged_impl/tree.rb
@@ -43,6 +43,8 @@ module Gitlab
ordered_entries.concat(tree_entries_from_rugged(repository, sha, entry.path, true))
end
end
+
+ ordered_entries
end
def rugged_populate_flat_path(repository, sha, path, entries)
diff --git a/lib/gitlab/git/wiki.rb b/lib/gitlab/git/wiki.rb
index a0dd4a24363..c1bcd8e934a 100644
--- a/lib/gitlab/git/wiki.rb
+++ b/lib/gitlab/git/wiki.rb
@@ -86,9 +86,14 @@ module Gitlab
end
end
- def pages(limit: 0, sort: nil, direction_desc: false)
+ def list_pages(limit: 0, sort: nil, direction_desc: false, load_content: false)
wrapped_gitaly_errors do
- gitaly_get_all_pages(limit: limit, sort: sort, direction_desc: direction_desc)
+ gitaly_list_pages(
+ limit: limit,
+ sort: sort,
+ direction_desc: direction_desc,
+ load_content: load_content
+ )
end
end
@@ -168,10 +173,17 @@ module Gitlab
Gitlab::Git::WikiFile.new(wiki_file)
end
- def gitaly_get_all_pages(limit: 0, sort: nil, direction_desc: false)
- gitaly_wiki_client.get_all_pages(
- limit: limit, sort: sort, direction_desc: direction_desc
- ).map do |wiki_page, version|
+ def gitaly_list_pages(limit: 0, sort: nil, direction_desc: false, load_content: false)
+ params = { limit: limit, sort: sort, direction_desc: direction_desc }
+
+ gitaly_pages =
+ if load_content
+ gitaly_wiki_client.load_all_pages(params)
+ else
+ gitaly_wiki_client.list_all_pages(params)
+ end
+
+ gitaly_pages.map do |wiki_page, version|
Gitlab::Git::WikiPage.new(wiki_page, version)
end
end
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index cb80ed64eff..4b626509008 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -85,7 +85,7 @@ module Gitlab
check_push_access!
end
- ::Gitlab::GitAccessResult::Success.new(console_messages: check_for_console_messages(cmd))
+ success_result(cmd)
end
def guest_can_download_code?
@@ -365,6 +365,10 @@ module Gitlab
protected
+ def success_result(cmd)
+ ::Gitlab::GitAccessResult::Success.new(console_messages: check_for_console_messages(cmd))
+ end
+
def changes_list
@changes_list ||= Gitlab::ChangesList.new(changes == ANY ? [] : changes)
end
diff --git a/lib/gitlab/git_ref_validator.rb b/lib/gitlab/git_ref_validator.rb
index 3f13ebeb9d0..dfff6823689 100644
--- a/lib/gitlab/git_ref_validator.rb
+++ b/lib/gitlab/git_ref_validator.rb
@@ -5,12 +5,15 @@
module Gitlab
module GitRefValidator
extend self
+
+ EXPANDED_PREFIXES = %w[refs/heads/ refs/remotes/].freeze
+ DISALLOWED_PREFIXES = %w[-].freeze
+
# Validates a given name against the git reference specification
#
# Returns true for a valid reference name, false otherwise
def validate(ref_name)
- not_allowed_prefixes = %w(refs/heads/ refs/remotes/ -)
- return false if ref_name.start_with?(*not_allowed_prefixes)
+ return false if ref_name.start_with?(*(EXPANDED_PREFIXES + DISALLOWED_PREFIXES))
return false if ref_name == 'HEAD'
begin
@@ -19,5 +22,21 @@ module Gitlab
return false
end
end
+
+ def validate_merge_request_branch(ref_name)
+ return false if ref_name.start_with?(*DISALLOWED_PREFIXES)
+
+ expanded_name = if ref_name.start_with?(*EXPANDED_PREFIXES)
+ ref_name
+ else
+ "refs/heads/#{ref_name}"
+ end
+
+ begin
+ Rugged::Reference.valid_name?(expanded_name)
+ rescue ArgumentError
+ return false
+ end
+ end
end
end
diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb
index 35565b68388..e683d4e5bbe 100644
--- a/lib/gitlab/gitaly_client.rb
+++ b/lib/gitlab/gitaly_client.rb
@@ -26,11 +26,15 @@ module Gitlab
end
end
- PEM_REGEX = /\-+BEGIN CERTIFICATE\-+.+?\-+END CERTIFICATE\-+/m
+ PEM_REGEX = /\-+BEGIN CERTIFICATE\-+.+?\-+END CERTIFICATE\-+/m.freeze
SERVER_VERSION_FILE = 'GITALY_SERVER_VERSION'
MAXIMUM_GITALY_CALLS = 30
CLIENT_NAME = (Sidekiq.server? ? 'gitlab-sidekiq' : 'gitlab-web').freeze
+ SERVER_FEATURE_CATFILE_CACHE = 'catfile-cache'.freeze
+ # Server feature flags should use '_' to separate words.
+ SERVER_FEATURE_FLAGS = [SERVER_FEATURE_CATFILE_CACHE].freeze
+
MUTEX = Mutex.new
define_histogram :gitaly_controller_action_duration_seconds do
@@ -52,9 +56,9 @@ module Gitlab
end
def self.interceptors
- return [] unless Gitlab::Tracing.enabled?
+ return [] unless Labkit::Tracing.enabled?
- [Gitlab::Tracing::GRPCInterceptor.instance]
+ [Labkit::Tracing::GRPCInterceptor.instance]
end
private_class_method :interceptors
@@ -165,7 +169,10 @@ module Gitlab
current_transaction_labels.merge(gitaly_service: service.to_s, rpc: rpc.to_s),
duration)
- add_call_details(feature: "#{service}##{rpc}", duration: duration, request: request_hash, rpc: rpc)
+ if peek_enabled?
+ add_call_details(feature: "#{service}##{rpc}", duration: duration, request: request_hash, rpc: rpc,
+ backtrace: Gitlab::Profiler.clean_backtrace(caller))
+ end
end
def self.query_time
@@ -215,7 +222,8 @@ module Gitlab
feature = feature_stack && feature_stack[0]
metadata['call_site'] = feature.to_s if feature
metadata['gitaly-servers'] = address_metadata(remote_storage) if remote_storage
- metadata['x-gitlab-correlation-id'] = Gitlab::CorrelationId.current_id if Gitlab::CorrelationId.current_id
+ metadata['x-gitlab-correlation-id'] = Labkit::Correlation::CorrelationId.current_id if Labkit::Correlation::CorrelationId.current_id
+ metadata['gitaly-session-id'] = session_id if feature_enabled?(SERVER_FEATURE_CATFILE_CACHE)
metadata.merge!(server_feature_flags)
@@ -232,7 +240,9 @@ module Gitlab
result
end
- SERVER_FEATURE_FLAGS = %w[].freeze
+ def self.session_id
+ Gitlab::SafeRequestStore[:gitaly_session_id] ||= SecureRandom.uuid
+ end
def self.server_feature_flags
SERVER_FEATURE_FLAGS.map do |f|
@@ -350,15 +360,17 @@ module Gitlab
Gitlab::SafeRequestStore["gitaly_call_permitted"] = 0
end
- def self.add_call_details(details)
- return unless Gitlab::SafeRequestStore[:peek_enabled]
+ def self.peek_enabled?
+ Gitlab::SafeRequestStore[:peek_enabled]
+ end
+ def self.add_call_details(details)
Gitlab::SafeRequestStore['gitaly_call_details'] ||= []
Gitlab::SafeRequestStore['gitaly_call_details'] << details
end
def self.list_call_details
- return [] unless Gitlab::SafeRequestStore[:peek_enabled]
+ return [] unless peek_enabled?
Gitlab::SafeRequestStore['gitaly_call_details'] || []
end
diff --git a/lib/gitlab/gitaly_client/blob_service.rb b/lib/gitlab/gitaly_client/blob_service.rb
index 6b8e58e6199..8ccefb00d20 100644
--- a/lib/gitlab/gitaly_client/blob_service.rb
+++ b/lib/gitlab/gitaly_client/blob_service.rb
@@ -55,13 +55,13 @@ module Gitlab
def get_blobs(revision_paths, limit = -1)
return [] if revision_paths.empty?
- revision_paths.map! do |rev, path|
+ request_revision_paths = revision_paths.map do |rev, path|
Gitaly::GetBlobsRequest::RevisionPath.new(revision: rev, path: encode_binary(path))
end
request = Gitaly::GetBlobsRequest.new(
repository: @gitaly_repo,
- revision_paths: revision_paths,
+ revision_paths: request_revision_paths,
limit: limit
)
diff --git a/lib/gitlab/gitaly_client/cleanup_service.rb b/lib/gitlab/gitaly_client/cleanup_service.rb
index 3e8d6a773ca..a56bc35f6d7 100644
--- a/lib/gitlab/gitaly_client/cleanup_service.rb
+++ b/lib/gitlab/gitaly_client/cleanup_service.rb
@@ -12,25 +12,32 @@ module Gitlab
@storage = repository.storage
end
- def apply_bfg_object_map(io)
- first_request = Gitaly::ApplyBfgObjectMapRequest.new(repository: gitaly_repo)
+ def apply_bfg_object_map_stream(io, &blk)
+ responses = GitalyClient.call(
+ storage,
+ :cleanup_service,
+ :apply_bfg_object_map_stream,
+ build_object_map_enum(io),
+ timeout: GitalyClient.no_timeout
+ )
+
+ responses.each(&blk)
+ end
+
+ private
- enum = Enumerator.new do |y|
- y.yield first_request
+ def build_object_map_enum(io)
+ Enumerator.new do |y|
+ # First request. For simplicity, doesn't include any object map data
+ y << Gitaly::ApplyBfgObjectMapStreamRequest.new(repository: gitaly_repo)
+ # Now stream the BFG object map file to gitaly in chunks
while data = io.read(RepositoryService::MAX_MSG_SIZE)
- y.yield Gitaly::ApplyBfgObjectMapRequest.new(object_map: data)
+ y << Gitaly::ApplyBfgObjectMapStreamRequest.new(object_map: data)
+
break if io&.eof?
end
end
-
- GitalyClient.call(
- storage,
- :cleanup_service,
- :apply_bfg_object_map,
- enum,
- timeout: GitalyClient.no_timeout
- )
end
end
end
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index 0d5debfcd01..d21b98d36ea 100644
--- a/lib/gitlab/gitaly_client/commit_service.rb
+++ b/lib/gitlab/gitaly_client/commit_service.rb
@@ -79,7 +79,7 @@ module Gitlab
def tree_entry(ref, path, limit = nil)
if Pathname.new(path).cleanpath.to_s.start_with?('../')
- # The TreeEntry RPC should return an empty reponse in this case but in
+ # The TreeEntry RPC should return an empty response in this case but in
# Gitaly 0.107.0 and earlier we get an exception instead. This early return
# saves us a Gitaly roundtrip while also avoiding the exception.
return
@@ -174,7 +174,7 @@ module Gitlab
response.each_with_object({}) do |gitaly_response, hsh|
gitaly_response.commits.each do |commit_for_tree|
- hsh[commit_for_tree.path] = Gitlab::Git::Commit.new(@repository, commit_for_tree.commit)
+ hsh[commit_for_tree.path_bytes] = Gitlab::Git::Commit.new(@repository, commit_for_tree.commit)
end
end
end
diff --git a/lib/gitlab/gitaly_client/conflicts_service.rb b/lib/gitlab/gitaly_client/conflicts_service.rb
index 077b63205a8..d16e45c964d 100644
--- a/lib/gitlab/gitaly_client/conflicts_service.rb
+++ b/lib/gitlab/gitaly_client/conflicts_service.rb
@@ -65,9 +65,9 @@ module Gitlab
our_commit_oid: @our_commit_oid,
target_repository: target_repository.gitaly_repository,
their_commit_oid: @their_commit_oid,
- source_branch: source_branch,
- target_branch: target_branch,
- commit_message: resolution.commit_message,
+ source_branch: encode_binary(source_branch),
+ target_branch: encode_binary(target_branch),
+ commit_message: encode_binary(resolution.commit_message),
user: Gitlab::Git::User.from_gitlab(resolution.user).to_gitaly
)
end
diff --git a/lib/gitlab/gitaly_client/object_pool_service.rb b/lib/gitlab/gitaly_client/object_pool_service.rb
index ce1fb4d68ae..d7fac26bc13 100644
--- a/lib/gitlab/gitaly_client/object_pool_service.rb
+++ b/lib/gitlab/gitaly_client/object_pool_service.rb
@@ -33,6 +33,15 @@ module Gitlab
GitalyClient.call(storage, :object_pool_service, :link_repository_to_object_pool,
request, timeout: GitalyClient.fast_timeout)
end
+
+ def fetch(repository)
+ request = Gitaly::FetchIntoObjectPoolRequest.new(
+ object_pool: object_pool,
+ origin: repository.gitaly_repository
+ )
+
+ GitalyClient.call(storage, :object_pool_service, :fetch_into_object_pool, request)
+ end
end
end
end
diff --git a/lib/gitlab/gitaly_client/operation_service.rb b/lib/gitlab/gitaly_client/operation_service.rb
index b0f328ce3d4..b42e6cbad8d 100644
--- a/lib/gitlab/gitaly_client/operation_service.rb
+++ b/lib/gitlab/gitaly_client/operation_service.rb
@@ -107,7 +107,7 @@ module Gitlab
branch: encode_binary(branch),
target_ref: encode_binary(target_ref),
user: Gitlab::Git::User.from_gitlab(user).to_gitaly,
- message: message
+ message: encode_binary(message)
)
response = GitalyClient.call(@repository.storage, :operation_service, :user_merge_to_ref, request)
@@ -197,6 +197,7 @@ module Gitlab
start_repository: start_repository)
end
+ # DEPRECATED: https://gitlab.com/gitlab-org/gitaly/issues/1628
def user_rebase(user, rebase_id, branch:, branch_sha:, remote_repository:, remote_branch:)
request = Gitaly::UserRebaseRequest.new(
repository: @gitaly_repo,
@@ -225,6 +226,49 @@ module Gitlab
end
end
+ def rebase(user, rebase_id, branch:, branch_sha:, remote_repository:, remote_branch:)
+ request_enum = QueueEnumerator.new
+ rebase_sha = nil
+
+ response_enum = GitalyClient.call(
+ @repository.storage,
+ :operation_service,
+ :user_rebase_confirmable,
+ request_enum.each,
+ remote_storage: remote_repository.storage
+ )
+
+ # First request
+ request_enum.push(
+ Gitaly::UserRebaseConfirmableRequest.new(
+ header: Gitaly::UserRebaseConfirmableRequest::Header.new(
+ repository: @gitaly_repo,
+ user: Gitlab::Git::User.from_gitlab(user).to_gitaly,
+ rebase_id: rebase_id.to_s,
+ branch: encode_binary(branch),
+ branch_sha: branch_sha,
+ remote_repository: remote_repository.gitaly_repository,
+ remote_branch: encode_binary(remote_branch)
+ )
+ )
+ )
+
+ perform_next_gitaly_rebase_request(response_enum) do |response|
+ rebase_sha = response.rebase_sha
+ end
+
+ yield rebase_sha
+
+ # Second request confirms with gitaly to finalize the rebase
+ request_enum.push(Gitaly::UserRebaseConfirmableRequest.new(apply: true))
+
+ perform_next_gitaly_rebase_request(response_enum)
+
+ rebase_sha
+ ensure
+ request_enum.close
+ end
+
def user_squash(user, squash_id, branch, start_sha, end_sha, author, message)
request = Gitaly::UserSquashRequest.new(
repository: @gitaly_repo,
@@ -346,6 +390,20 @@ module Gitlab
private
+ def perform_next_gitaly_rebase_request(response_enum)
+ response = response_enum.next
+
+ if response.pre_receive_error.present?
+ raise Gitlab::Git::PreReceiveError, response.pre_receive_error
+ elsif response.git_error.present?
+ raise Gitlab::Git::Repository::GitError, response.git_error
+ end
+
+ yield response if block_given?
+
+ response
+ end
+
def call_cherry_pick_or_revert(rpc, user:, commit:, branch_name:, message:, start_branch_name:, start_repository:)
request_class = "Gitaly::User#{rpc.to_s.camelcase}Request".constantize
diff --git a/lib/gitlab/gitaly_client/ref_service.rb b/lib/gitlab/gitaly_client/ref_service.rb
index 6f6698607d9..b7d509dfa48 100644
--- a/lib/gitlab/gitaly_client/ref_service.rb
+++ b/lib/gitlab/gitaly_client/ref_service.rb
@@ -239,6 +239,12 @@ module Gitlab
messages
end
+ def pack_refs
+ request = Gitaly::PackRefsRequest.new(repository: @gitaly_repo)
+
+ GitalyClient.call(@storage, :ref_service, :pack_refs, request)
+ end
+
private
def consume_refs_response(response)
diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb
index 74aae4a8e97..d8e9dccb644 100644
--- a/lib/gitlab/gitaly_client/repository_service.rb
+++ b/lib/gitlab/gitaly_client/repository_service.rb
@@ -47,6 +47,13 @@ module Gitlab
response.size
end
+ def get_object_directory_size
+ request = Gitaly::GetObjectDirectorySizeRequest.new(repository: @gitaly_repo)
+ response = GitalyClient.call(@storage, :repository_service, :get_object_directory_size, request, timeout: GitalyClient.medium_timeout)
+
+ response.size
+ end
+
def apply_gitattributes(revision)
request = Gitaly::ApplyGitattributesRequest.new(repository: @gitaly_repo, revision: encode_binary(revision))
GitalyClient.call(@storage, :repository_service, :apply_gitattributes, request, timeout: GitalyClient.fast_timeout)
@@ -331,6 +338,14 @@ module Gitlab
search_results_from_response(response)
end
+ def disconnect_alternates
+ request = Gitaly::DisconnectGitAlternatesRequest.new(
+ repository: @gitaly_repo
+ )
+
+ GitalyClient.call(@storage, :object_pool_service, :disconnect_git_alternates, request)
+ end
+
private
def search_results_from_response(gitaly_response)
diff --git a/lib/gitlab/gitaly_client/wiki_service.rb b/lib/gitlab/gitaly_client/wiki_service.rb
index e036cdcd800..ce9faad825c 100644
--- a/lib/gitlab/gitaly_client/wiki_service.rb
+++ b/lib/gitlab/gitaly_client/wiki_service.rb
@@ -87,7 +87,27 @@ module Gitlab
wiki_page_from_iterator(response)
end
- def get_all_pages(limit: 0, sort: nil, direction_desc: false)
+ def list_all_pages(limit: 0, sort: nil, direction_desc: false)
+ sort_value = Gitaly::WikiListPagesRequest::SortBy.resolve(sort.to_s.upcase.to_sym)
+
+ params = { repository: @gitaly_repo, limit: limit, direction_desc: direction_desc }
+ params[:sort] = sort_value if sort_value
+
+ request = Gitaly::WikiListPagesRequest.new(params)
+ stream = GitalyClient.call(@repository.storage, :wiki_service, :wiki_list_pages, request, timeout: GitalyClient.medium_timeout)
+ stream.each_with_object([]) do |message, pages|
+ page = message.page
+
+ next unless page
+
+ wiki_page = GitalyClient::WikiPage.new(page.to_h)
+ version = new_wiki_page_version(page.version)
+
+ pages << [wiki_page, version]
+ end
+ end
+
+ def load_all_pages(limit: 0, sort: nil, direction_desc: false)
sort_value = Gitaly::WikiGetAllPagesRequest::SortBy.resolve(sort.to_s.upcase.to_sym)
params = { repository: @gitaly_repo, limit: limit, direction_desc: direction_desc }
@@ -95,6 +115,7 @@ module Gitlab
request = Gitaly::WikiGetAllPagesRequest.new(params)
response = GitalyClient.call(@repository.storage, :wiki_service, :wiki_get_all_pages, request, timeout: GitalyClient.medium_timeout)
+
pages = []
loop do
diff --git a/lib/gitlab/github_import/importer/issue_importer.rb b/lib/gitlab/github_import/importer/issue_importer.rb
index 656d46b6a7d..a468f6d8821 100644
--- a/lib/gitlab/github_import/importer/issue_importer.rb
+++ b/lib/gitlab/github_import/importer/issue_importer.rb
@@ -53,6 +53,7 @@ module Gitlab
description: description,
milestone_id: milestone_finder.id_for(issue),
state: issue.state,
+ state_id: ::Issue.available_states[issue.state],
created_at: issue.created_at,
updated_at: issue.updated_at
}
diff --git a/lib/gitlab/github_import/importer/pull_request_importer.rb b/lib/gitlab/github_import/importer/pull_request_importer.rb
index 1b293ddc7c7..377e873d24d 100644
--- a/lib/gitlab/github_import/importer/pull_request_importer.rb
+++ b/lib/gitlab/github_import/importer/pull_request_importer.rb
@@ -55,6 +55,7 @@ module Gitlab
source_branch: pull_request.formatted_source_branch,
target_branch: pull_request.target_branch,
state: pull_request.state,
+ state_id: ::MergeRequest.available_states[pull_request.state],
milestone_id: milestone_finder.id_for(pull_request),
author_id: author_id,
assignee_id: user_finder.assignee_id_for(pull_request),
diff --git a/lib/gitlab/github_import/parallel_importer.rb b/lib/gitlab/github_import/parallel_importer.rb
index 9d81441d96e..1d3541b80c7 100644
--- a/lib/gitlab/github_import/parallel_importer.rb
+++ b/lib/gitlab/github_import/parallel_importer.rb
@@ -29,29 +29,13 @@ module Gitlab
end
def execute
- jid = generate_jid
-
- # The original import JID is the JID of the RepositoryImportWorker job,
- # which will be removed once that job completes. Reusing that JID could
- # result in StuckImportJobsWorker marking the job as stuck before we get
- # to running Stage::ImportRepositoryWorker.
- #
- # We work around this by setting the JID to a custom generated one, then
- # refreshing it in the various stages whenever necessary.
- Gitlab::SidekiqStatus
- .set(jid, StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION)
-
- project.import_state.update_column(:jid, jid)
+ Gitlab::Import::SetAsyncJid.set_jid(project)
Stage::ImportRepositoryWorker
.perform_async(project.id)
true
end
-
- def generate_jid
- "github-importer/#{project.id}"
- end
end
end
end
diff --git a/lib/gitlab/github_import/representation/diff_note.rb b/lib/gitlab/github_import/representation/diff_note.rb
index be1334ca98a..d336b1ba797 100644
--- a/lib/gitlab/github_import/representation/diff_note.rb
+++ b/lib/gitlab/github_import/representation/diff_note.rb
@@ -13,7 +13,7 @@ module Gitlab
:diff_hunk, :author, :note, :created_at, :updated_at,
:github_id
- NOTEABLE_ID_REGEX = %r{/pull/(?<iid>\d+)}i
+ NOTEABLE_ID_REGEX = %r{/pull/(?<iid>\d+)}i.freeze
# Builds a diff note from a GitHub API response.
#
diff --git a/lib/gitlab/github_import/representation/note.rb b/lib/gitlab/github_import/representation/note.rb
index 070e3b2db8d..5b98ce7d5ed 100644
--- a/lib/gitlab/github_import/representation/note.rb
+++ b/lib/gitlab/github_import/representation/note.rb
@@ -12,7 +12,7 @@ module Gitlab
expose_attribute :noteable_id, :noteable_type, :author, :note,
:created_at, :updated_at, :github_id
- NOTEABLE_TYPE_REGEX = %r{/(?<type>(pull|issues))/(?<iid>\d+)}i
+ NOTEABLE_TYPE_REGEX = %r{/(?<type>(pull|issues))/(?<iid>\d+)}i.freeze
# Builds a note from a GitHub API response.
#
diff --git a/lib/gitlab/gl_repository.rb b/lib/gitlab/gl_repository.rb
index a56ca1e39e7..04dabe423e8 100644
--- a/lib/gitlab/gl_repository.rb
+++ b/lib/gitlab/gl_repository.rb
@@ -1,7 +1,9 @@
# frozen_string_literal: true
module Gitlab
- module GlRepository
+ class GlRepository
+ include Singleton
+
PROJECT = RepoType.new(
name: :project,
access_checker_class: Gitlab::GitAccess,
@@ -19,7 +21,7 @@ module Gitlab
}.freeze
def self.types
- TYPES
+ instance.types
end
def self.parse(gl_repository)
@@ -39,5 +41,11 @@ module Gitlab
def self.default_type
PROJECT
end
+
+ def types
+ TYPES
+ end
+
+ private_class_method :instance
end
end
diff --git a/lib/gitlab/gl_repository/repo_type.rb b/lib/gitlab/gl_repository/repo_type.rb
index 7abe6c29a25..19915980d7f 100644
--- a/lib/gitlab/gl_repository/repo_type.rb
+++ b/lib/gitlab/gl_repository/repo_type.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Gitlab
- module GlRepository
+ class GlRepository
class RepoType
attr_reader :name,
:access_checker_class,
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index e00309e7946..582c3065189 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -15,7 +15,12 @@ module Gitlab
gon.relative_url_root = Gitlab.config.gitlab.relative_url_root
gon.shortcuts_path = Gitlab::Routing.url_helpers.help_page_path('shortcuts')
gon.user_color_scheme = Gitlab::ColorSchemes.for_user(current_user).css_class
- gon.sentry_dsn = Gitlab::CurrentSettings.clientside_sentry_dsn if Gitlab::CurrentSettings.clientside_sentry_enabled
+
+ if Gitlab::CurrentSettings.clientside_sentry_enabled
+ gon.sentry_dsn = Gitlab::CurrentSettings.clientside_sentry_dsn
+ gon.sentry_environment = Gitlab.config.sentry.environment
+ end
+
gon.gitlab_url = Gitlab.config.gitlab.url
gon.revision = Gitlab.revision
gon.gitlab_logo = ActionController::Base.helpers.asset_path('gitlab_logo.png')
diff --git a/lib/gitlab/grape_logging/loggers/correlation_id_logger.rb b/lib/gitlab/grape_logging/loggers/correlation_id_logger.rb
index fa4c5d86d44..bbe4b24c7d4 100644
--- a/lib/gitlab/grape_logging/loggers/correlation_id_logger.rb
+++ b/lib/gitlab/grape_logging/loggers/correlation_id_logger.rb
@@ -6,7 +6,7 @@ module Gitlab
module Loggers
class CorrelationIdLogger < ::GrapeLogging::Loggers::Base
def parameters(_, _)
- { Gitlab::CorrelationId::LOG_KEY => Gitlab::CorrelationId.current_id }
+ { Labkit::Correlation::CorrelationId::LOG_KEY => Labkit::Correlation::CorrelationId.current_id }
end
end
end
diff --git a/lib/gitlab/graphql/authorize.rb b/lib/gitlab/graphql/authorize.rb
index f62813db82c..f8d0208e275 100644
--- a/lib/gitlab/graphql/authorize.rb
+++ b/lib/gitlab/graphql/authorize.rb
@@ -8,7 +8,7 @@ module Gitlab
extend ActiveSupport::Concern
def self.use(schema_definition)
- schema_definition.instrument(:field, Instrumentation.new)
+ schema_definition.instrument(:field, Instrumentation.new, after_built_ins: true)
end
end
end
diff --git a/lib/gitlab/graphql/authorize/authorize_field_service.rb b/lib/gitlab/graphql/authorize/authorize_field_service.rb
index 8deff79fc84..619ce100421 100644
--- a/lib/gitlab/graphql/authorize/authorize_field_service.rb
+++ b/lib/gitlab/graphql/authorize/authorize_field_service.rb
@@ -15,15 +15,10 @@ module Gitlab
def authorized_resolve
proc do |parent_typed_object, args, ctx|
- resolved_obj = @old_resolve_proc.call(parent_typed_object, args, ctx)
- authorizing_obj = authorize_against(parent_typed_object)
- checker = build_checker(ctx[:current_user], authorizing_obj)
-
- if resolved_obj.respond_to?(:then)
- resolved_obj.then(&checker)
- else
- checker.call(resolved_obj)
- end
+ resolved_type = @old_resolve_proc.call(parent_typed_object, args, ctx)
+ authorizing_object = authorize_against(parent_typed_object, resolved_type)
+
+ filter_allowed(ctx[:current_user], resolved_type, authorizing_object)
end
end
@@ -38,7 +33,7 @@ module Gitlab
type = @field.type
# When the return type of @field is a collection, find the singular type
- if type.get_field('edges')
+ if @field.connection?
type = node_type_for_relay_connection(type)
elsif type.list?
type = node_type_for_basic_connection(type)
@@ -52,43 +47,60 @@ module Gitlab
Array.wrap(@field.metadata[:authorize])
end
- # If it's a built-in/scalar type, authorize using its parent object.
- # nil means authorize using the resolved object
- def authorize_against(parent_typed_object)
- parent_typed_object.object if built_in_type? && parent_typed_object.respond_to?(:object)
+ def authorize_against(parent_typed_object, resolved_type)
+ if scalar_type?
+ # The field is a built-in/scalar type, or a list of scalars
+ # authorize using the parent's object
+ parent_typed_object.object
+ elsif resolved_type.respond_to?(:object)
+ # The field is a type representing a single object, we'll authorize
+ # against the object directly
+ resolved_type.object
+ elsif @field.connection? || resolved_type.is_a?(Array)
+ # The field is a connection or a list of non-built-in types, we'll
+ # authorize each element when rendering
+ nil
+ else
+ # Resolved type is a single object that might not be loaded yet by
+ # the batchloader, we'll authorize that
+ resolved_type
+ end
end
- def build_checker(current_user, authorizing_obj)
- lambda do |resolved_obj|
- # Load the elements if they were not loaded by BatchLoader yet
- resolved_obj = resolved_obj.sync if resolved_obj.respond_to?(:sync)
-
- check = lambda do |object|
- authorizations.all? do |ability|
- Ability.allowed?(current_user, ability, authorizing_obj || object)
- end
+ def filter_allowed(current_user, resolved_type, authorizing_object)
+ if authorizing_object
+ # Authorizing fields representing scalars, or a simple field with an object
+ resolved_type if allowed_access?(current_user, authorizing_object)
+ elsif @field.connection?
+ # A connection with pagination, modify the visible nodes in on the
+ # connection type in place
+ resolved_type.edge_nodes.to_a.keep_if { |node| allowed_access?(current_user, node) }
+ resolved_type
+ elsif resolved_type.is_a? Array
+ # A simple list of rendered types each object being an object to authorize
+ resolved_type.select do |single_object_type|
+ allowed_access?(current_user, single_object_type.object)
end
+ elsif resolved_type.nil?
+ # We're not rendering anything, for example when a record was not found
+ # no need to do anything
+ else
+ raise "Can't authorize #{@field}"
+ end
+ end
- case resolved_obj
- when Array, ActiveRecord::Relation
- resolved_obj.select(&check)
- else
- resolved_obj if check.call(resolved_obj)
- end
+ def allowed_access?(current_user, object)
+ object = object.sync if object.respond_to?(:sync)
+
+ authorizations.all? do |ability|
+ Ability.allowed?(current_user, ability, object)
end
end
# Returns the singular type for relay connections.
# This will be the type class of edges.node
def node_type_for_relay_connection(type)
- type = type.get_field('edges').type.unwrap.get_field('node')&.type
-
- if type.nil?
- raise Gitlab::Graphql::Errors::ConnectionDefinitionError,
- 'Connection Type must conform to the Relay Cursor Connections Specification'
- end
-
- type
+ type.unwrap.get_field('edges').type.unwrap.get_field('node').type
end
# Returns the singular type for basic connections, for example `[Types::ProjectType]`
@@ -96,8 +108,8 @@ module Gitlab
type.unwrap
end
- def built_in_type?
- GraphQL::Schema::BUILT_IN_TYPES.has_value?(node_type_for_basic_connection(@field.type))
+ def scalar_type?
+ node_type_for_basic_connection(@field.type).kind.scalar?
end
end
end
diff --git a/lib/gitlab/graphql/connections/keyset_connection.rb b/lib/gitlab/graphql/connections/keyset_connection.rb
index 851054c0393..715963a44c1 100644
--- a/lib/gitlab/graphql/connections/keyset_connection.rb
+++ b/lib/gitlab/graphql/connections/keyset_connection.rb
@@ -22,8 +22,17 @@ module Gitlab
end
# rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def paged_nodes
+ # These are the nodes that will be loaded into memory for rendering
+ # So we're ok loading them into memory here as that's bound to happen
+ # anyway. Having them ready means we can modify the result while
+ # rendering the fields.
+ @paged_nodes ||= load_paged_nodes.to_a
+ end
+
+ private
+
+ def load_paged_nodes
if first && last
raise Gitlab::Graphql::Errors::ArgumentError.new("Can only provide either `first` or `last`, not both")
end
@@ -31,12 +40,9 @@ module Gitlab
if last
sliced_nodes.last(limit_value)
else
- sliced_nodes.limit(limit_value)
+ sliced_nodes.limit(limit_value) # rubocop: disable CodeReuse/ActiveRecord
end
end
- # rubocop: enable CodeReuse/ActiveRecord
-
- private
def before_slice
if sort_direction == :asc
diff --git a/lib/gitlab/graphql/errors.rb b/lib/gitlab/graphql/errors.rb
index bcbba72e017..fe74549e322 100644
--- a/lib/gitlab/graphql/errors.rb
+++ b/lib/gitlab/graphql/errors.rb
@@ -6,7 +6,6 @@ module Gitlab
BaseError = Class.new(GraphQL::ExecutionError)
ArgumentError = Class.new(BaseError)
ResourceNotAvailable = Class.new(BaseError)
- ConnectionDefinitionError = Class.new(BaseError)
end
end
end
diff --git a/lib/gitlab/graphql/generic_tracing.rb b/lib/gitlab/graphql/generic_tracing.rb
new file mode 100644
index 00000000000..936b22d5afa
--- /dev/null
+++ b/lib/gitlab/graphql/generic_tracing.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+# This class is used as a hook to observe graphql runtime events. From this
+# hook both gitlab metrics and opentracking measurements are generated
+
+module Gitlab
+ module Graphql
+ class GenericTracing < GraphQL::Tracing::PlatformTracing
+ self.platform_keys = {
+ 'lex' => 'graphql.lex',
+ 'parse' => 'graphql.parse',
+ 'validate' => 'graphql.validate',
+ 'analyze_query' => 'graphql.analyze',
+ 'analyze_multiplex' => 'graphql.analyze',
+ 'execute_multiplex' => 'graphql.execute',
+ 'execute_query' => 'graphql.execute',
+ 'execute_query_lazy' => 'graphql.execute',
+ 'execute_field' => 'graphql.execute',
+ 'execute_field_lazy' => 'graphql.execute'
+ }
+
+ def platform_field_key(type, field)
+ "#{type.name}.#{field.name}"
+ end
+
+ def platform_trace(platform_key, key, data, &block)
+ tags = { platform_key: platform_key, key: key }
+ start = Gitlab::Metrics::System.monotonic_time
+
+ with_labkit_tracing(tags, &block)
+ ensure
+ duration = Gitlab::Metrics::System.monotonic_time - start
+
+ graphql_duration_seconds.observe(tags, duration)
+ end
+
+ private
+
+ def with_labkit_tracing(tags, &block)
+ return yield unless Labkit::Tracing.enabled?
+
+ name = "#{tags[:platform_key]}.#{tags[:key]}"
+ span_tags = {
+ 'component' => 'web',
+ 'span.kind' => 'server'
+ }.merge(tags.stringify_keys)
+
+ Labkit::Tracing.with_tracing(operation_name: name, tags: span_tags, &block)
+ end
+
+ def graphql_duration_seconds
+ @graphql_duration_seconds ||= Gitlab::Metrics.histogram(
+ :graphql_duration_seconds,
+ 'GraphQL execution time'
+ )
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/loaders/batch_lfs_oid_loader.rb b/lib/gitlab/graphql/loaders/batch_lfs_oid_loader.rb
new file mode 100644
index 00000000000..8f34e58a771
--- /dev/null
+++ b/lib/gitlab/graphql/loaders/batch_lfs_oid_loader.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ module Loaders
+ class BatchLfsOidLoader
+ def initialize(repository, blob_id)
+ @repository, @blob_id = repository, blob_id
+ end
+
+ def find
+ BatchLoader.for(blob_id).batch(key: repository) do |blob_ids, loader, batch_args|
+ Gitlab::Git::Blob.batch_lfs_pointers(batch_args[:key], blob_ids).each do |loaded_blob|
+ loader.call(loaded_blob.id, loaded_blob.lfs_oid)
+ end
+ end
+ end
+
+ private
+
+ attr_reader :repository, :blob_id
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/loaders/batch_model_loader.rb b/lib/gitlab/graphql/loaders/batch_model_loader.rb
index 5a0099dc6b1..50d3293fcbb 100644
--- a/lib/gitlab/graphql/loaders/batch_model_loader.rb
+++ b/lib/gitlab/graphql/loaders/batch_model_loader.rb
@@ -12,7 +12,7 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def find
- BatchLoader.for({ model: model_class, id: model_id }).batch do |loader_info, loader|
+ BatchLoader.for({ model: model_class, id: model_id.to_i }).batch do |loader_info, loader|
per_model = loader_info.group_by { |info| info[:model] }
per_model.each do |model, info|
ids = info.map { |i| i[:id] }
diff --git a/lib/gitlab/graphql/loaders/batch_project_statistics_loader.rb b/lib/gitlab/graphql/loaders/batch_project_statistics_loader.rb
new file mode 100644
index 00000000000..5e151f4dbd7
--- /dev/null
+++ b/lib/gitlab/graphql/loaders/batch_project_statistics_loader.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ module Loaders
+ class BatchProjectStatisticsLoader
+ attr_reader :project_id
+
+ def initialize(project_id)
+ @project_id = project_id
+ end
+
+ def find
+ BatchLoader.for(project_id).batch do |project_ids, loader|
+ ProjectStatistics.for_project_ids(project_ids).each do |statistics|
+ loader.call(statistics.project_id, statistics)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/query_analyzers/log_query_complexity.rb b/lib/gitlab/graphql/query_analyzers/log_query_complexity.rb
deleted file mode 100644
index 95db130dbfc..00000000000
--- a/lib/gitlab/graphql/query_analyzers/log_query_complexity.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Graphql
- module QueryAnalyzers
- class LogQueryComplexity
- class << self
- def analyzer
- GraphQL::Analysis::QueryComplexity.new do |query, complexity|
- # temporary until https://gitlab.com/gitlab-org/gitlab-ce/issues/59587
- Rails.logger.info("[GraphQL Query Complexity] #{complexity} | admin? #{query.context[:current_user]&.admin?}")
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/graphql/query_analyzers/logger_analyzer.rb b/lib/gitlab/graphql/query_analyzers/logger_analyzer.rb
new file mode 100644
index 00000000000..01b55a1667f
--- /dev/null
+++ b/lib/gitlab/graphql/query_analyzers/logger_analyzer.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ module QueryAnalyzers
+ class LoggerAnalyzer
+ COMPLEXITY_ANALYZER = GraphQL::Analysis::QueryComplexity.new { |query, complexity_value| complexity_value }
+ DEPTH_ANALYZER = GraphQL::Analysis::QueryDepth.new { |query, depth_value| depth_value }
+
+ def analyze?(query)
+ Feature.enabled?(:graphql_logging, default_enabled: true)
+ end
+
+ def initial_value(query)
+ variables = process_variables(query.provided_variables)
+ default_initial_values(query).merge({
+ query_string: query.query_string,
+ variables: variables
+ })
+ rescue => e
+ Gitlab::Sentry.track_exception(e)
+ default_initial_values(query)
+ end
+
+ def call(memo, visit_type, irep_node)
+ memo
+ end
+
+ def final_value(memo)
+ return if memo.nil?
+
+ analyzers = [COMPLEXITY_ANALYZER, DEPTH_ANALYZER]
+ complexity, depth = GraphQL::Analysis.analyze_query(memo[:query], analyzers)
+
+ memo[:depth] = depth
+ memo[:complexity] = complexity
+ memo[:duration] = duration(memo[:time_started]).round(1)
+
+ GraphqlLogger.info(memo.except!(:time_started, :query))
+ rescue => e
+ Gitlab::Sentry.track_exception(e)
+ end
+
+ private
+
+ def process_variables(variables)
+ if variables.respond_to?(:to_s)
+ variables.to_s
+ else
+ variables
+ end
+ end
+
+ def duration(time_started)
+ nanoseconds = Gitlab::Metrics::System.monotonic_time - time_started
+ nanoseconds * 1000000
+ end
+
+ def default_initial_values(query)
+ {
+ time_started: Gitlab::Metrics::System.monotonic_time,
+ query_string: nil,
+ query: query,
+ variables: nil,
+ duration: nil
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/representation/tree_entry.rb b/lib/gitlab/graphql/representation/tree_entry.rb
new file mode 100644
index 00000000000..7ea83db5876
--- /dev/null
+++ b/lib/gitlab/graphql/representation/tree_entry.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ module Representation
+ class TreeEntry < SimpleDelegator
+ class << self
+ def decorate(entries, repository)
+ return if entries.nil?
+
+ entries.map do |entry|
+ if entry.is_a?(TreeEntry)
+ entry
+ else
+ self.new(entry, repository)
+ end
+ end
+ end
+ end
+
+ attr_accessor :repository
+
+ def initialize(raw_entry, repository)
+ @repository = repository
+
+ super(raw_entry)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/tracing.rb b/lib/gitlab/graphql/tracing.rb
deleted file mode 100644
index 6b505e4262b..00000000000
--- a/lib/gitlab/graphql/tracing.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Graphql
- class Tracing < GraphQL::Tracing::PlatformTracing
- self.platform_keys = {
- 'lex' => 'graphql.lex',
- 'parse' => 'graphql.parse',
- 'validate' => 'graphql.validate',
- 'analyze_query' => 'graphql.analyze',
- 'analyze_multiplex' => 'graphql.analyze',
- 'execute_multiplex' => 'graphql.execute',
- 'execute_query' => 'graphql.execute',
- 'execute_query_lazy' => 'graphql.execute',
- 'execute_field' => 'graphql.execute',
- 'execute_field_lazy' => 'graphql.execute'
- }
-
- def platform_field_key(type, field)
- "#{type.name}.#{field.name}"
- end
-
- def platform_trace(platform_key, key, data, &block)
- start = Gitlab::Metrics::System.monotonic_time
-
- yield
- ensure
- duration = Gitlab::Metrics::System.monotonic_time - start
-
- graphql_duration_seconds.observe({ platform_key: platform_key, key: key }, duration)
- end
-
- private
-
- def graphql_duration_seconds
- @graphql_duration_seconds ||= Gitlab::Metrics.histogram(
- :graphql_duration_seconds,
- 'GraphQL execution time'
- )
- end
- end
- end
-end
diff --git a/lib/gitlab/graphql_logger.rb b/lib/gitlab/graphql_logger.rb
new file mode 100644
index 00000000000..43d917908b6
--- /dev/null
+++ b/lib/gitlab/graphql_logger.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Gitlab
+ class GraphqlLogger < Gitlab::JsonLogger
+ def self.file_name_noext
+ 'graphql_json'
+ end
+ end
+end
diff --git a/lib/gitlab/group_search_results.rb b/lib/gitlab/group_search_results.rb
index 7255293b194..334642f252e 100644
--- a/lib/gitlab/group_search_results.rb
+++ b/lib/gitlab/group_search_results.rb
@@ -2,6 +2,8 @@
module Gitlab
class GroupSearchResults < SearchResults
+ attr_reader :group
+
def initialize(current_user, limit_projects, group, query, default_project_filter: false, per_page: 20)
super(current_user, limit_projects, query, default_project_filter: default_project_filter, per_page: per_page)
@@ -26,5 +28,9 @@ module Gitlab
.where(id: groups.select('members.user_id'))
end
# rubocop:enable CodeReuse/ActiveRecord
+
+ def issuable_params
+ super.merge(group_id: group.id)
+ end
end
end
diff --git a/lib/gitlab/health_checks/metric.rb b/lib/gitlab/health_checks/metric.rb
index 62a5216d159..184083de2bc 100644
--- a/lib/gitlab/health_checks/metric.rb
+++ b/lib/gitlab/health_checks/metric.rb
@@ -1,4 +1,3 @@
-# rubocop:disable Naming/FileName
# frozen_string_literal: true
module Gitlab::HealthChecks
diff --git a/lib/gitlab/health_checks/result.rb b/lib/gitlab/health_checks/result.rb
index d32a6980eb8..4586b1d94a7 100644
--- a/lib/gitlab/health_checks/result.rb
+++ b/lib/gitlab/health_checks/result.rb
@@ -1,4 +1,3 @@
-# rubocop:disable Naming/FileName
# frozen_string_literal: true
module Gitlab::HealthChecks
diff --git a/lib/gitlab/hook_data/issue_builder.rb b/lib/gitlab/hook_data/issue_builder.rb
index d39ff8c21cc..cfc9ebe4f92 100644
--- a/lib/gitlab/hook_data/issue_builder.rb
+++ b/lib/gitlab/hook_data/issue_builder.rb
@@ -44,7 +44,8 @@ module Gitlab
human_total_time_spent: issue.human_total_time_spent,
human_time_estimate: issue.human_time_estimate,
assignee_ids: issue.assignee_ids,
- assignee_id: issue.assignee_ids.first # This key is deprecated
+ assignee_id: issue.assignee_ids.first, # This key is deprecated
+ labels: issue.labels
}
issue.attributes.with_indifferent_access.slice(*self.class.safe_hook_attributes)
diff --git a/lib/gitlab/http.rb b/lib/gitlab/http.rb
index bcd9e2be35f..db2b4dde244 100644
--- a/lib/gitlab/http.rb
+++ b/lib/gitlab/http.rb
@@ -9,9 +9,16 @@ module Gitlab
BlockedUrlError = Class.new(StandardError)
RedirectionTooDeep = Class.new(StandardError)
+ HTTP_ERRORS = [
+ SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET,
+ Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Net::OpenTimeout,
+ Net::ReadTimeout, Gitlab::HTTP::BlockedUrlError,
+ Gitlab::HTTP::RedirectionTooDeep
+ ].freeze
+
include HTTParty # rubocop:disable Gitlab/HTTParty
- connection_adapter ProxyHTTPConnectionAdapter
+ connection_adapter HTTPConnectionAdapter
def self.perform_request(http_method, path, options, &block)
super
diff --git a/lib/gitlab/http_connection_adapter.rb b/lib/gitlab/http_connection_adapter.rb
new file mode 100644
index 00000000000..41eab3658bc
--- /dev/null
+++ b/lib/gitlab/http_connection_adapter.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+# This class is part of the Gitlab::HTTP wrapper. Depending on the value
+# of the global setting allow_local_requests_from_hooks_and_services this adapter
+# will allow/block connection to internal IPs and/or urls.
+#
+# This functionality can be overridden by providing the setting the option
+# allow_local_requests = true in the request. For example:
+# Gitlab::HTTP.get('http://www.gitlab.com', allow_local_requests: true)
+#
+# This option will take precedence over the global setting.
+module Gitlab
+ class HTTPConnectionAdapter < HTTParty::ConnectionAdapter
+ def connection
+ begin
+ @uri, hostname = Gitlab::UrlBlocker.validate!(uri, allow_local_network: allow_local_requests?,
+ allow_localhost: allow_local_requests?,
+ dns_rebind_protection: dns_rebind_protection?)
+ rescue Gitlab::UrlBlocker::BlockedUrlError => e
+ raise Gitlab::HTTP::BlockedUrlError, "URL '#{uri}' is blocked: #{e.message}"
+ end
+
+ super.tap do |http|
+ http.hostname_override = hostname if hostname
+ end
+ end
+
+ private
+
+ def allow_local_requests?
+ options.fetch(:allow_local_requests, allow_settings_local_requests?)
+ end
+
+ def dns_rebind_protection?
+ return false if Gitlab.http_proxy_env?
+
+ Gitlab::CurrentSettings.dns_rebinding_protection_enabled?
+ end
+
+ def allow_settings_local_requests?
+ Gitlab::CurrentSettings.allow_local_requests_from_hooks_and_services?
+ end
+ end
+end
diff --git a/lib/gitlab/import/set_async_jid.rb b/lib/gitlab/import/set_async_jid.rb
new file mode 100644
index 00000000000..584d24045ee
--- /dev/null
+++ b/lib/gitlab/import/set_async_jid.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+# The original import JID is the JID of the RepositoryImportWorker job,
+# which will be removed once that job completes. Reusing that JID could
+# result in StuckImportJobsWorker marking the job as stuck before we get
+# to running Stage::ImportRepositoryWorker.
+#
+# We work around this by setting the JID to a custom generated one, then
+# refreshing it in the various stages whenever necessary.
+module Gitlab
+ module Import
+ module SetAsyncJid
+ def self.set_jid(project)
+ jid = generate_jid(project)
+
+ Gitlab::SidekiqStatus
+ .set(jid, StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION)
+
+ project.import_state.update_column(:jid, jid)
+ end
+
+ def self.generate_jid(project)
+ "async-import/#{project.id}"
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb b/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb
index fcf6a25ab00..acb7f225b17 100644
--- a/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb
+++ b/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb
@@ -30,10 +30,7 @@ module Gitlab
def handle_response_error(response)
unless response.success?
- error_code = response.dig('Error', 'Code') || response.code
- error_message = response.dig('Error', 'Message') || response.message
-
- raise StrategyError.new("Error uploading the project. Code #{error_code}: #{error_message}")
+ raise StrategyError.new("Error uploading the project. Code #{response.code}: #{response.message}")
end
end
diff --git a/lib/gitlab/import_export/attribute_cleaner.rb b/lib/gitlab/import_export/attribute_cleaner.rb
index 93b37b7bc5f..c28a1674018 100644
--- a/lib/gitlab/import_export/attribute_cleaner.rb
+++ b/lib/gitlab/import_export/attribute_cleaner.rb
@@ -4,6 +4,7 @@ module Gitlab
module ImportExport
class AttributeCleaner
ALLOWED_REFERENCES = RelationFactory::PROJECT_REFERENCES + RelationFactory::USER_REFERENCES + ['group_id']
+ PROHIBITED_REFERENCES = Regexp.union(/\Acached_markdown_version\Z/, /_id\Z/, /_html\Z/).freeze
def self.clean(*args)
new(*args).clean
@@ -24,7 +25,11 @@ module Gitlab
private
def prohibited_key?(key)
- key.end_with?('_id') && !ALLOWED_REFERENCES.include?(key)
+ key =~ PROHIBITED_REFERENCES && !permitted_key?(key)
+ end
+
+ def permitted_key?(key)
+ ALLOWED_REFERENCES.include?(key)
end
def excluded_key?(key)
diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml
index ce268793128..71c44af9254 100644
--- a/lib/gitlab/import_export/import_export.yml
+++ b/lib/gitlab/import_export/import_export.yml
@@ -75,6 +75,7 @@ project_tree:
- :project_badges
- :ci_cd_settings
- :error_tracking_setting
+ - :metrics_setting
# Only include the following attributes for the models specified.
included_attributes:
@@ -155,6 +156,9 @@ excluded_attributes:
- :when
- :artifacts_file
- :artifacts_metadata
+ - :artifacts_file_store
+ - :artifacts_metadata_store
+ - :artifacts_size
- :commands
push_event_payload:
- :event_id
@@ -175,6 +179,8 @@ excluded_attributes:
- :enabled
methods:
+ notes:
+ - :type
labels:
- :type
label:
diff --git a/lib/gitlab/import_export/members_mapper.rb b/lib/gitlab/import_export/members_mapper.rb
index 6be95a16513..a154de5419e 100644
--- a/lib/gitlab/import_export/members_mapper.rb
+++ b/lib/gitlab/import_export/members_mapper.rb
@@ -59,7 +59,11 @@ module Gitlab
end
def member_hash(member)
- parsed_hash(member).merge('source_id' => @project.id, 'importing' => true)
+ parsed_hash(member).merge(
+ 'source_id' => @project.id,
+ 'importing' => true,
+ 'access_level' => [member['access_level'], ProjectMember::MAINTAINER].min
+ ).except('user_id')
end
def parsed_hash(member)
diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb
index 51001750a6c..20caadb89c0 100644
--- a/lib/gitlab/import_export/project_tree_restorer.rb
+++ b/lib/gitlab/import_export/project_tree_restorer.rb
@@ -129,7 +129,7 @@ module Gitlab
def visibility_level
level = override_params['visibility_level'] || json_params['visibility_level'] || @project.visibility_level
- level = @project.group.visibility_level if @project.group && level > @project.group.visibility_level
+ level = @project.group.visibility_level if @project.group && level.to_i > @project.group.visibility_level
{ 'visibility_level' => level }
end
diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb
index 61a1aa6da5a..efd3f550a22 100644
--- a/lib/gitlab/import_export/relation_factory.rb
+++ b/lib/gitlab/import_export/relation_factory.rb
@@ -25,7 +25,8 @@ module Gitlab
metrics: 'MergeRequest::Metrics',
ci_cd_settings: 'ProjectCiCdSetting',
error_tracking_setting: 'ErrorTracking::ProjectErrorTrackingSetting',
- links: 'Releases::Link' }.freeze
+ links: 'Releases::Link',
+ metrics_setting: 'ProjectMetricsSetting' }.freeze
USER_REFERENCES = %w[author_id assignee_id updated_by_id merged_by_id latest_closed_by_id user_id created_by_id last_edited_by_id merge_user_id resolved_by_id closed_by_id].freeze
@@ -152,6 +153,9 @@ module Gitlab
@relation_hash.delete('trace') # old export files have trace
@relation_hash.delete('token')
@relation_hash.delete('commands')
+ @relation_hash.delete('artifacts_file_store')
+ @relation_hash.delete('artifacts_metadata_store')
+ @relation_hash.delete('artifacts_size')
imported_object
elsif @relation_name == :merge_requests
diff --git a/lib/gitlab/import_sources.rb b/lib/gitlab/import_sources.rb
index 67952ca0f2d..e4d625b5738 100644
--- a/lib/gitlab/import_sources.rb
+++ b/lib/gitlab/import_sources.rb
@@ -20,7 +20,8 @@ module Gitlab
ImportSource.new('git', 'Repo by URL', nil),
ImportSource.new('gitlab_project', 'GitLab export', Gitlab::ImportExport::Importer),
ImportSource.new('gitea', 'Gitea', Gitlab::LegacyGithubImport::Importer),
- ImportSource.new('manifest', 'Manifest file', nil)
+ ImportSource.new('manifest', 'Manifest file', nil),
+ ImportSource.new('phabricator', 'Phabricator', Gitlab::PhabricatorImport::Importer)
].freeze
class << self
diff --git a/lib/gitlab/json_logger.rb b/lib/gitlab/json_logger.rb
index a5a5759cc89..ab34fb03158 100644
--- a/lib/gitlab/json_logger.rb
+++ b/lib/gitlab/json_logger.rb
@@ -10,7 +10,7 @@ module Gitlab
data = {}
data[:severity] = severity
data[:time] = timestamp.utc.iso8601(3)
- data[Gitlab::CorrelationId::LOG_KEY] = Gitlab::CorrelationId.current_id
+ data[Labkit::Correlation::CorrelationId::LOG_KEY] = Labkit::Correlation::CorrelationId.current_id
case message
when String
diff --git a/lib/gitlab/kubernetes/errors.rb b/lib/gitlab/kubernetes/errors.rb
new file mode 100644
index 00000000000..81bf636eef7
--- /dev/null
+++ b/lib/gitlab/kubernetes/errors.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ module Errors
+ CONNECTION = [
+ SocketError,
+ OpenSSL::SSL::SSLError,
+ Errno::ECONNRESET,
+ Errno::ENETUNREACH,
+ Errno::ECONNREFUSED,
+ Errno::EHOSTUNREACH,
+ Net::OpenTimeout,
+ Net::ReadTimeout,
+ IPAddr::InvalidAddressError
+ ].freeze
+
+ AUTHENTICATION = [
+ OpenSSL::X509::CertificateError
+ ].freeze
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/helm/api.rb b/lib/gitlab/kubernetes/helm/api.rb
index 7dfd9ed4f35..978cafae9ac 100644
--- a/lib/gitlab/kubernetes/helm/api.rb
+++ b/lib/gitlab/kubernetes/helm/api.rb
@@ -22,6 +22,14 @@ module Gitlab
alias_method :update, :install
+ def uninstall(command)
+ namespace.ensure_exists!
+ create_config_map(command)
+
+ delete_pod!(command.pod_name)
+ kubeclient.create_pod(command.pod_resource)
+ end
+
##
# Returns Pod phase
#
diff --git a/lib/gitlab/legacy_github_import/importer.rb b/lib/gitlab/legacy_github_import/importer.rb
index 70b18221a66..751726d4810 100644
--- a/lib/gitlab/legacy_github_import/importer.rb
+++ b/lib/gitlab/legacy_github_import/importer.rb
@@ -55,7 +55,12 @@ module Gitlab
import_pull_requests
import_issues
import_comments(:issues)
- import_comments(:pull_requests)
+
+ # Gitea doesn't have an API endpoint for pull requests comments
+ unless project.gitea_import?
+ import_comments(:pull_requests)
+ end
+
import_wiki
# Gitea doesn't have a Release API yet
diff --git a/lib/gitlab/lets_encrypt/challenge.rb b/lib/gitlab/lets_encrypt/challenge.rb
new file mode 100644
index 00000000000..136268c974b
--- /dev/null
+++ b/lib/gitlab/lets_encrypt/challenge.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module LetsEncrypt
+ class Challenge
+ def initialize(acme_challenge)
+ @acme_challenge = acme_challenge
+ end
+
+ delegate :token, :file_content, :status, :request_validation, to: :acme_challenge
+
+ private
+
+ attr_reader :acme_challenge
+ end
+ end
+end
diff --git a/lib/gitlab/lets_encrypt/client.rb b/lib/gitlab/lets_encrypt/client.rb
new file mode 100644
index 00000000000..66aea137012
--- /dev/null
+++ b/lib/gitlab/lets_encrypt/client.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module LetsEncrypt
+ class Client
+ include Gitlab::Utils::StrongMemoize
+
+ PRODUCTION_DIRECTORY_URL = 'https://acme-v02.api.letsencrypt.org/directory'
+ STAGING_DIRECTORY_URL = 'https://acme-staging-v02.api.letsencrypt.org/directory'
+
+ def new_order(domain_name)
+ ensure_account
+
+ acme_order = acme_client.new_order(identifiers: [domain_name])
+
+ ::Gitlab::LetsEncrypt::Order.new(acme_order)
+ end
+
+ def load_order(url)
+ ensure_account
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ ::Gitlab::LetsEncrypt::Order.new(acme_client.order(url: url))
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+
+ def load_challenge(url)
+ ensure_account
+
+ ::Gitlab::LetsEncrypt::Challenge.new(acme_client.challenge(url: url))
+ end
+
+ def terms_of_service_url
+ acme_client.terms_of_service
+ end
+
+ def enabled?
+ return false unless Feature.enabled?(:pages_auto_ssl)
+
+ return false unless private_key
+
+ Gitlab::CurrentSettings.lets_encrypt_terms_of_service_accepted
+ end
+
+ private
+
+ def acme_client
+ @acme_client ||= ::Acme::Client.new(private_key: private_key, directory: acme_api_directory_url)
+ end
+
+ def private_key
+ strong_memoize(:private_key) do
+ private_key_string = Gitlab::CurrentSettings.lets_encrypt_private_key
+ private_key_string ||= generate_private_key
+ OpenSSL::PKey.read(private_key_string) if private_key_string
+ end
+ end
+
+ def admin_email
+ Gitlab::CurrentSettings.lets_encrypt_notification_email
+ end
+
+ def contact
+ "mailto:#{admin_email}"
+ end
+
+ def ensure_account
+ raise 'Acme integration is disabled' unless enabled?
+
+ @acme_account ||= acme_client.new_account(contact: contact, terms_of_service_agreed: true)
+ end
+
+ def acme_api_directory_url
+ if Rails.env.production?
+ PRODUCTION_DIRECTORY_URL
+ else
+ STAGING_DIRECTORY_URL
+ end
+ end
+
+ def generate_private_key
+ return if Gitlab::Database.read_only?
+
+ application_settings = Gitlab::CurrentSettings.current_application_settings
+ application_settings.with_lock do
+ unless application_settings.lets_encrypt_private_key
+ application_settings.update(lets_encrypt_private_key: OpenSSL::PKey::RSA.new(4096).to_pem)
+ end
+
+ application_settings.lets_encrypt_private_key
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/lets_encrypt/order.rb b/lib/gitlab/lets_encrypt/order.rb
new file mode 100644
index 00000000000..9c2365f98a8
--- /dev/null
+++ b/lib/gitlab/lets_encrypt/order.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module LetsEncrypt
+ class Order
+ def initialize(acme_order)
+ @acme_order = acme_order
+ end
+
+ def new_challenge
+ authorization = @acme_order.authorizations.first
+ challenge = authorization.http
+ ::Gitlab::LetsEncrypt::Challenge.new(challenge)
+ end
+
+ def request_certificate(domain:, private_key:)
+ csr = ::Acme::Client::CertificateRequest.new(
+ private_key: OpenSSL::PKey.read(private_key),
+ subject: { common_name: domain }
+ )
+
+ acme_order.finalize(csr: csr)
+ end
+
+ delegate :url, :status, :expires, :certificate, to: :acme_order
+
+ private
+
+ attr_reader :acme_order
+ end
+ end
+end
diff --git a/lib/gitlab/lfs_token.rb b/lib/gitlab/lfs_token.rb
index 31e6fc9d8c7..124e34562c1 100644
--- a/lib/gitlab/lfs_token.rb
+++ b/lib/gitlab/lfs_token.rb
@@ -35,8 +35,7 @@ module Gitlab
end
def token_valid?(token_to_check)
- HMACToken.new(actor).token_valid?(token_to_check) ||
- LegacyRedisDeviseToken.new(actor).token_valid?(token_to_check)
+ HMACToken.new(actor).token_valid?(token_to_check)
end
def deploy_key_pushable?(project)
@@ -103,44 +102,5 @@ module Gitlab
Settings.attr_encrypted_db_key_base.first(16)
end
end
-
- # TODO: LegacyRedisDeviseToken and references need to be removed after
- # next released milestone
- #
- class LegacyRedisDeviseToken
- TOKEN_LENGTH = 50
- DEFAULT_EXPIRY_TIME = 1800 * 1000 # 30 mins
-
- def initialize(actor)
- @actor = actor
- end
-
- def token_valid?(token_to_check)
- Devise.secure_compare(stored_token, token_to_check)
- end
-
- def stored_token
- Gitlab::Redis::SharedState.with { |redis| redis.get(state_key) }
- end
-
- # This method exists purely to facilitate legacy testing to ensure the
- # same redis key is used.
- #
- def store_new_token(expiry_time_in_ms = DEFAULT_EXPIRY_TIME)
- Gitlab::Redis::SharedState.with do |redis|
- new_token = Devise.friendly_token(TOKEN_LENGTH)
- redis.set(state_key, new_token, px: expiry_time_in_ms)
- new_token
- end
- end
-
- private
-
- attr_reader :actor
-
- def state_key
- "gitlab:lfs_token:#{actor.class.name.underscore}_#{actor.id}"
- end
- end
end
end
diff --git a/lib/gitlab/markdown_cache.rb b/lib/gitlab/markdown_cache.rb
new file mode 100644
index 00000000000..0354c710a3f
--- /dev/null
+++ b/lib/gitlab/markdown_cache.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module MarkdownCache
+ # Increment this number every time the renderer changes its output
+ CACHE_COMMONMARK_VERSION_START = 10
+ CACHE_COMMONMARK_VERSION = 16
+
+ BaseError = Class.new(StandardError)
+ UnsupportedClassError = Class.new(BaseError)
+ end
+end
diff --git a/lib/gitlab/markdown_cache/active_record/extension.rb b/lib/gitlab/markdown_cache/active_record/extension.rb
new file mode 100644
index 00000000000..f3abe631779
--- /dev/null
+++ b/lib/gitlab/markdown_cache/active_record/extension.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module MarkdownCache
+ module ActiveRecord
+ module Extension
+ extend ActiveSupport::Concern
+
+ included do
+ # Using before_update here conflicts with elasticsearch-model somehow
+ before_create :refresh_markdown_cache, if: :invalidated_markdown_cache?
+ before_update :refresh_markdown_cache, if: :invalidated_markdown_cache?
+ end
+
+ # Always exclude _html fields from attributes (including serialization).
+ # They contain unredacted HTML, which would be a security issue
+ def attributes
+ attrs = super
+ html_fields = cached_markdown_fields.html_fields
+ whitelisted = cached_markdown_fields.html_fields_whitelisted
+ exclude_fields = html_fields - whitelisted
+
+ attrs.except!(*exclude_fields)
+ attrs.delete('cached_markdown_version') if whitelisted.empty?
+
+ attrs
+ end
+
+ def changed_markdown_fields
+ changed_attributes.keys.map(&:to_s) & cached_markdown_fields.markdown_fields.map(&:to_s)
+ end
+
+ def write_markdown_field(field_name, value)
+ write_attribute(field_name, value)
+ end
+
+ def markdown_field_changed?(field_name)
+ attribute_changed?(field_name)
+ end
+
+ def save_markdown(updates)
+ return unless persisted? && Gitlab::Database.read_write?
+
+ update_columns(updates)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/markdown_cache/field_data.rb b/lib/gitlab/markdown_cache/field_data.rb
new file mode 100644
index 00000000000..14622c0f186
--- /dev/null
+++ b/lib/gitlab/markdown_cache/field_data.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module MarkdownCache
+ # Knows about the relationship between markdown and html field names, and
+ # stores the rendering contexts for the latter
+ class FieldData
+ def initialize
+ @data = {}
+ end
+
+ delegate :[], :[]=, to: :@data
+
+ def markdown_fields
+ @data.keys
+ end
+
+ def html_field(markdown_field)
+ "#{markdown_field}_html"
+ end
+
+ def html_fields
+ @html_fields ||= markdown_fields.map { |field| html_field(field) }
+ end
+
+ def html_fields_whitelisted
+ markdown_fields.each_with_object([]) do |field, fields|
+ if @data[field].fetch(:whitelisted, false)
+ fields << html_field(field)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/markdown_cache/redis/extension.rb b/lib/gitlab/markdown_cache/redis/extension.rb
new file mode 100644
index 00000000000..97fc23343b4
--- /dev/null
+++ b/lib/gitlab/markdown_cache/redis/extension.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module MarkdownCache
+ module Redis
+ module Extension
+ extend ActiveSupport::Concern
+
+ attr_reader :cached_markdown_version
+
+ class_methods do
+ def cache_markdown_field(markdown_field, context = {})
+ super
+
+ # define the `[field]_html` accessor
+ html_field = cached_markdown_fields.html_field(markdown_field)
+ define_method(html_field) do
+ load_cached_markdown unless markdown_data_loaded?
+
+ instance_variable_get("@#{html_field}")
+ end
+ end
+ end
+
+ private
+
+ def save_markdown(updates)
+ markdown_store.save(updates)
+ end
+
+ def write_markdown_field(field_name, value)
+ instance_variable_set("@#{field_name}", value)
+ end
+
+ def markdown_field_changed?(field_name)
+ false
+ end
+
+ def changed_markdown_fields
+ []
+ end
+
+ def cached_markdown
+ @cached_data ||= markdown_store.read
+ end
+
+ def load_cached_markdown
+ cached_markdown.each do |field_name, value|
+ write_markdown_field(field_name, value)
+ end
+ end
+
+ def markdown_data_loaded?
+ cached_markdown_version.present? || markdown_store.loaded?
+ end
+
+ def markdown_store
+ @store ||= Gitlab::MarkdownCache::Redis::Store.new(self)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/markdown_cache/redis/store.rb b/lib/gitlab/markdown_cache/redis/store.rb
new file mode 100644
index 00000000000..0f954404808
--- /dev/null
+++ b/lib/gitlab/markdown_cache/redis/store.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module MarkdownCache
+ module Redis
+ class Store
+ EXPIRES_IN = 1.day
+
+ def initialize(subject)
+ @subject = subject
+ @loaded = false
+ end
+
+ def save(updates)
+ @loaded = false
+
+ Gitlab::Redis::Cache.with do |r|
+ r.mapped_hmset(markdown_cache_key, updates)
+ r.expire(markdown_cache_key, EXPIRES_IN)
+ end
+ end
+
+ def read
+ @loaded = true
+
+ results = Gitlab::Redis::Cache.with do |r|
+ r.mapped_hmget(markdown_cache_key, *fields)
+ end
+ # The value read from redis is a string, so we're converting it back
+ # to an int.
+ results[:cached_markdown_version] = results[:cached_markdown_version].to_i
+ results
+ end
+
+ def loaded?
+ @loaded
+ end
+
+ private
+
+ def fields
+ @fields ||= @subject.cached_markdown_fields.html_fields + [:cached_markdown_version]
+ end
+
+ def markdown_cache_key
+ unless @subject.respond_to?(:cache_key)
+ raise Gitlab::MarkdownCache::UnsupportedClassError,
+ "This class has no cache_key to use for caching"
+ end
+
+ "markdown_cache:#{@subject.cache_key}"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/dashboard/base_service.rb b/lib/gitlab/metrics/dashboard/base_service.rb
new file mode 100644
index 00000000000..090014aa597
--- /dev/null
+++ b/lib/gitlab/metrics/dashboard/base_service.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+# Searches a projects repository for a metrics dashboard and formats the output.
+# Expects any custom dashboards will be located in `.gitlab/dashboards`
+module Gitlab
+ module Metrics
+ module Dashboard
+ class BaseService < ::BaseService
+ PROCESSING_ERROR = Gitlab::Metrics::Dashboard::Stages::BaseStage::DashboardProcessingError
+ NOT_FOUND_ERROR = Gitlab::Template::Finders::RepoTemplateFinder::FileNotFoundError
+
+ def get_dashboard
+ success(dashboard: process_dashboard)
+ rescue NOT_FOUND_ERROR
+ error("#{dashboard_path} could not be found.", :not_found)
+ rescue PROCESSING_ERROR => e
+ error(e.message, :unprocessable_entity)
+ end
+
+ # Summary of all known dashboards for the service.
+ # @return [Array<Hash>] ex) [{ path: String, default: Boolean }]
+ def self.all_dashboard_paths(_project)
+ raise NotImplementedError
+ end
+
+ private
+
+ # Returns a new dashboard Hash, supplemented with DB info
+ def process_dashboard
+ Gitlab::Metrics::Dashboard::Processor
+ .new(project, params[:environment], raw_dashboard)
+ .process(insert_project_metrics: insert_project_metrics?)
+ end
+
+ # @return [String] Relative filepath of the dashboard yml
+ def dashboard_path
+ params[:dashboard_path]
+ end
+
+ # Returns an un-processed dashboard from the cache.
+ def raw_dashboard
+ Gitlab::Metrics::Dashboard::Cache.fetch(cache_key) { get_raw_dashboard }
+ end
+
+ # @return [Hash] an unmodified dashboard
+ def get_raw_dashboard
+ raise NotImplementedError
+ end
+
+ # @return [String]
+ def cache_key
+ raise NotImplementedError
+ end
+
+ # Determines whether custom metrics should be included
+ # in the processed output.
+ def insert_project_metrics?
+ false
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/dashboard/cache.rb b/lib/gitlab/metrics/dashboard/cache.rb
new file mode 100644
index 00000000000..a9ccf0fea9b
--- /dev/null
+++ b/lib/gitlab/metrics/dashboard/cache.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'set'
+
+module Gitlab
+ module Metrics
+ module Dashboard
+ class Cache
+ CACHE_KEYS = 'all_cached_metric_dashboards'
+
+ class << self
+ # Stores a dashboard in the cache, documenting the key
+ # so the cached can be cleared in bulk at another time.
+ def fetch(key)
+ register_key(key)
+
+ Rails.cache.fetch(key) { yield }
+ end
+
+ # Resets all dashboard caches, such that all
+ # dashboard content will be loaded from source on
+ # subsequent dashboard calls.
+ def delete_all!
+ all_keys.each { |key| Rails.cache.delete(key) }
+
+ Rails.cache.delete(CACHE_KEYS)
+ end
+
+ private
+
+ def register_key(key)
+ new_keys = all_keys.add(key).to_a.join('|')
+
+ Rails.cache.write(CACHE_KEYS, new_keys)
+ end
+
+ def all_keys
+ Set.new(Rails.cache.read(CACHE_KEYS)&.split('|'))
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/dashboard/finder.rb b/lib/gitlab/metrics/dashboard/finder.rb
new file mode 100644
index 00000000000..49ea5c7d4f2
--- /dev/null
+++ b/lib/gitlab/metrics/dashboard/finder.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+# Returns DB-supplmented dashboard info for determining
+# the layout of UI. Intended entry-point for the Metrics::Dashboard
+# module.
+module Gitlab
+ module Metrics
+ module Dashboard
+ class Finder
+ class << self
+ # Returns a formatted dashboard packed with DB info.
+ # @return [Hash]
+ def find(project, user, environment, dashboard_path = nil)
+ service = system_dashboard?(dashboard_path) ? system_service : project_service
+
+ service
+ .new(project, user, environment: environment, dashboard_path: dashboard_path)
+ .get_dashboard
+ end
+
+ # Summary of all known dashboards.
+ # @return [Array<Hash>] ex) [{ path: String, default: Boolean }]
+ def find_all_paths(project)
+ project.repository.metrics_dashboard_paths
+ end
+
+ # Summary of all known dashboards. Used to populate repo cache.
+ # Prefer #find_all_paths.
+ def find_all_paths_from_source(project)
+ Gitlab::Metrics::Dashboard::Cache.delete_all!
+
+ system_service.all_dashboard_paths(project)
+ .+ project_service.all_dashboard_paths(project)
+ end
+
+ private
+
+ def system_service
+ Gitlab::Metrics::Dashboard::SystemDashboardService
+ end
+
+ def project_service
+ Gitlab::Metrics::Dashboard::ProjectDashboardService
+ end
+
+ def system_dashboard?(filepath)
+ !filepath || system_service.system_dashboard?(filepath)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/dashboard/processor.rb b/lib/gitlab/metrics/dashboard/processor.rb
new file mode 100644
index 00000000000..a33a010ad97
--- /dev/null
+++ b/lib/gitlab/metrics/dashboard/processor.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Metrics
+ module Dashboard
+ # Responsible for processesing a dashboard hash, inserting
+ # relevant DB records & sorting for proper rendering in
+ # the UI. These includes shared metric info, custom metrics
+ # info, and alerts (only in EE).
+ class Processor
+ SYSTEM_SEQUENCE = [
+ Stages::CommonMetricsInserter,
+ Stages::ProjectMetricsInserter,
+ Stages::EndpointInserter,
+ Stages::Sorter
+ ].freeze
+
+ PROJECT_SEQUENCE = [
+ Stages::CommonMetricsInserter,
+ Stages::EndpointInserter,
+ Stages::Sorter
+ ].freeze
+
+ def initialize(project, environment, dashboard)
+ @project = project
+ @environment = environment
+ @dashboard = dashboard
+ end
+
+ # Returns a new dashboard hash with the results of
+ # running transforms on the dashboard.
+ def process(insert_project_metrics:)
+ @dashboard.deep_symbolize_keys.tap do |dashboard|
+ sequence(insert_project_metrics).each do |stage|
+ stage.new(@project, @environment, dashboard).transform!
+ end
+ end
+ end
+
+ private
+
+ def sequence(insert_project_metrics)
+ insert_project_metrics ? SYSTEM_SEQUENCE : PROJECT_SEQUENCE
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/dashboard/project_dashboard_service.rb b/lib/gitlab/metrics/dashboard/project_dashboard_service.rb
new file mode 100644
index 00000000000..e88658e4f9f
--- /dev/null
+++ b/lib/gitlab/metrics/dashboard/project_dashboard_service.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+# Searches a projects repository for a metrics dashboard and formats the output.
+# Expects any custom dashboards will be located in `.gitlab/dashboards`
+# Use Gitlab::Metrics::Dashboard::Finder to retrive dashboards.
+module Gitlab
+ module Metrics
+ module Dashboard
+ class ProjectDashboardService < Gitlab::Metrics::Dashboard::BaseService
+ DASHBOARD_ROOT = ".gitlab/dashboards"
+
+ class << self
+ def all_dashboard_paths(project)
+ file_finder(project)
+ .list_files_for(DASHBOARD_ROOT)
+ .map { |filepath| { path: filepath, default: false } }
+ end
+
+ def file_finder(project)
+ Gitlab::Template::Finders::RepoTemplateFinder.new(project, DASHBOARD_ROOT, '.yml')
+ end
+ end
+
+ private
+
+ # Searches the project repo for a custom-defined dashboard.
+ def get_raw_dashboard
+ yml = self.class.file_finder(project).read(dashboard_path)
+
+ YAML.safe_load(yml)
+ end
+
+ def cache_key
+ "project_#{project.id}_metrics_dashboard_#{dashboard_path}"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/dashboard/stages/base_stage.rb b/lib/gitlab/metrics/dashboard/stages/base_stage.rb
new file mode 100644
index 00000000000..0db7b176e8d
--- /dev/null
+++ b/lib/gitlab/metrics/dashboard/stages/base_stage.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Metrics
+ module Dashboard
+ module Stages
+ class BaseStage
+ DashboardProcessingError = Class.new(StandardError)
+ LayoutError = Class.new(DashboardProcessingError)
+
+ DEFAULT_PANEL_TYPE = 'area-chart'
+
+ attr_reader :project, :environment, :dashboard
+
+ def initialize(project, environment, dashboard)
+ @project = project
+ @environment = environment
+ @dashboard = dashboard
+ end
+
+ # Entry-point to the stage
+ def transform!
+ raise NotImplementedError
+ end
+
+ protected
+
+ def missing_panel_groups!
+ raise LayoutError.new('Top-level key :panel_groups must be an array')
+ end
+
+ def missing_panels!
+ raise LayoutError.new('Each "panel_group" must define an array :panels')
+ end
+
+ def missing_metrics!
+ raise LayoutError.new('Each "panel" must define an array :metrics')
+ end
+
+ def for_metrics
+ missing_panel_groups! unless dashboard[:panel_groups].is_a?(Array)
+
+ dashboard[:panel_groups].each do |panel_group|
+ missing_panels! unless panel_group[:panels].is_a?(Array)
+
+ panel_group[:panels].each do |panel|
+ missing_metrics! unless panel[:metrics].is_a?(Array)
+
+ panel[:metrics].each do |metric|
+ yield metric
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/dashboard/stages/common_metrics_inserter.rb b/lib/gitlab/metrics/dashboard/stages/common_metrics_inserter.rb
new file mode 100644
index 00000000000..188912bedb4
--- /dev/null
+++ b/lib/gitlab/metrics/dashboard/stages/common_metrics_inserter.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Metrics
+ module Dashboard
+ module Stages
+ class CommonMetricsInserter < BaseStage
+ # For each metric in the dashboard config, attempts to
+ # find a corresponding database record. If found,
+ # includes the record's id in the dashboard config.
+ def transform!
+ common_metrics = ::PrometheusMetric.common
+
+ for_metrics do |metric|
+ metric_record = common_metrics.find { |m| m.identifier == metric[:id] }
+ metric[:metric_id] = metric_record.id if metric_record
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/dashboard/stages/endpoint_inserter.rb b/lib/gitlab/metrics/dashboard/stages/endpoint_inserter.rb
new file mode 100644
index 00000000000..2a959854be0
--- /dev/null
+++ b/lib/gitlab/metrics/dashboard/stages/endpoint_inserter.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Metrics
+ module Dashboard
+ module Stages
+ class EndpointInserter < BaseStage
+ MissingQueryError = Class.new(DashboardProcessingError)
+
+ def transform!
+ for_metrics do |metric|
+ metric[:prometheus_endpoint_path] = endpoint_for_metric(metric)
+ end
+ end
+
+ private
+
+ def endpoint_for_metric(metric)
+ Gitlab::Routing.url_helpers.prometheus_api_project_environment_path(
+ project,
+ environment,
+ proxy_path: query_type(metric),
+ query: query_for_metric(metric)
+ )
+ end
+
+ def query_type(metric)
+ metric[:query] ? :query : :query_range
+ end
+
+ def query_for_metric(metric)
+ query = metric[query_type(metric)]
+
+ raise MissingQueryError.new('Each "metric" must define one of :query or :query_range') unless query
+
+ query
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/dashboard/stages/project_metrics_inserter.rb b/lib/gitlab/metrics/dashboard/stages/project_metrics_inserter.rb
new file mode 100644
index 00000000000..221610a14d1
--- /dev/null
+++ b/lib/gitlab/metrics/dashboard/stages/project_metrics_inserter.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Metrics
+ module Dashboard
+ module Stages
+ class ProjectMetricsInserter < BaseStage
+ # Inserts project-specific metrics into the dashboard
+ # config. If there are no project-specific metrics,
+ # this will have no effect.
+ def transform!
+ project.prometheus_metrics.each do |project_metric|
+ group = find_or_create_panel_group(dashboard[:panel_groups], project_metric)
+ panel = find_or_create_panel(group[:panels], project_metric)
+ find_or_create_metric(panel[:metrics], project_metric)
+ end
+ end
+
+ private
+
+ # Looks for a panel_group corresponding to the
+ # provided metric object. If unavailable, inserts one.
+ # @param panel_groups [Array<Hash>]
+ # @param metric [PrometheusMetric]
+ def find_or_create_panel_group(panel_groups, metric)
+ panel_group = find_panel_group(panel_groups, metric)
+ return panel_group if panel_group
+
+ panel_group = new_panel_group(metric)
+ panel_groups << panel_group
+
+ panel_group
+ end
+
+ # Looks for a panel corresponding to the provided
+ # metric object. If unavailable, inserts one.
+ # @param panels [Array<Hash>]
+ # @param metric [PrometheusMetric]
+ def find_or_create_panel(panels, metric)
+ panel = find_panel(panels, metric)
+ return panel if panel
+
+ panel = new_panel(metric)
+ panels << panel
+
+ panel
+ end
+
+ # Looks for a metric corresponding to the provided
+ # metric object. If unavailable, inserts one.
+ # @param metrics [Array<Hash>]
+ # @param metric [PrometheusMetric]
+ def find_or_create_metric(metrics, metric)
+ target_metric = find_metric(metrics, metric)
+ return target_metric if target_metric
+
+ target_metric = new_metric(metric)
+ metrics << target_metric
+
+ target_metric
+ end
+
+ def find_panel_group(panel_groups, metric)
+ return unless panel_groups
+
+ panel_groups.find { |group| group[:group] == metric.group_title }
+ end
+
+ def find_panel(panels, metric)
+ return unless panels
+
+ panel_identifiers = [DEFAULT_PANEL_TYPE, metric.title, metric.y_label]
+ panels.find { |panel| panel.values_at(:type, :title, :y_label) == panel_identifiers }
+ end
+
+ def find_metric(metrics, metric)
+ return unless metrics
+
+ metrics.find { |m| m[:id] == metric.identifier }
+ end
+
+ def new_panel_group(metric)
+ {
+ group: metric.group_title,
+ priority: metric.priority,
+ panels: []
+ }
+ end
+
+ def new_panel(metric)
+ {
+ type: DEFAULT_PANEL_TYPE,
+ title: metric.title,
+ y_label: metric.y_label,
+ metrics: []
+ }
+ end
+
+ def new_metric(metric)
+ metric.queries.first.merge(metric_id: metric.id)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/dashboard/stages/sorter.rb b/lib/gitlab/metrics/dashboard/stages/sorter.rb
new file mode 100644
index 00000000000..ba5aa78059c
--- /dev/null
+++ b/lib/gitlab/metrics/dashboard/stages/sorter.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Metrics
+ module Dashboard
+ module Stages
+ class Sorter < BaseStage
+ def transform!
+ missing_panel_groups! unless dashboard[:panel_groups].is_a? Array
+
+ sort_groups!
+ sort_panels!
+ end
+
+ private
+
+ # Sorts the groups in the dashboard by the :priority key
+ def sort_groups!
+ dashboard[:panel_groups] = dashboard[:panel_groups].sort_by { |group| -group[:priority].to_i }
+ end
+
+ # Sorts the panels in the dashboard by the :weight key
+ def sort_panels!
+ dashboard[:panel_groups].each do |group|
+ missing_panels! unless group[:panels].is_a? Array
+
+ group[:panels] = group[:panels].sort_by { |panel| -panel[:weight].to_i }
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/dashboard/system_dashboard_service.rb b/lib/gitlab/metrics/dashboard/system_dashboard_service.rb
new file mode 100644
index 00000000000..67509ed4230
--- /dev/null
+++ b/lib/gitlab/metrics/dashboard/system_dashboard_service.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+# Fetches the system metrics dashboard and formats the output.
+# Use Gitlab::Metrics::Dashboard::Finder to retrive dashboards.
+module Gitlab
+ module Metrics
+ module Dashboard
+ class SystemDashboardService < Gitlab::Metrics::Dashboard::BaseService
+ SYSTEM_DASHBOARD_PATH = 'config/prometheus/common_metrics.yml'
+
+ class << self
+ def all_dashboard_paths(_project)
+ [{
+ path: SYSTEM_DASHBOARD_PATH,
+ default: true
+ }]
+ end
+
+ def system_dashboard?(filepath)
+ filepath == SYSTEM_DASHBOARD_PATH
+ end
+ end
+
+ private
+
+ def dashboard_path
+ SYSTEM_DASHBOARD_PATH
+ end
+
+ # Returns the base metrics shipped with every GitLab service.
+ def get_raw_dashboard
+ yml = File.read(Rails.root.join(dashboard_path))
+
+ YAML.safe_load(yml)
+ end
+
+ def cache_key
+ "metrics_dashboard_#{dashboard_path}"
+ end
+
+ def insert_project_metrics?
+ true
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/metric.rb b/lib/gitlab/metrics/metric.rb
index 9e4d70a71ff..30f181542be 100644
--- a/lib/gitlab/metrics/metric.rb
+++ b/lib/gitlab/metrics/metric.rb
@@ -4,7 +4,7 @@ module Gitlab
module Metrics
# Class for storing details of a single metric (label, value, etc).
class Metric
- JITTER_RANGE = 0.000001..0.001
+ JITTER_RANGE = (0.000001..0.001).freeze
attr_reader :series, :values, :tags, :type
diff --git a/lib/gitlab/metrics/samplers/puma_sampler.rb b/lib/gitlab/metrics/samplers/puma_sampler.rb
new file mode 100644
index 00000000000..25e40c70230
--- /dev/null
+++ b/lib/gitlab/metrics/samplers/puma_sampler.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'puma/state_file'
+
+module Gitlab
+ module Metrics
+ module Samplers
+ class PumaSampler < BaseSampler
+ def metrics
+ @metrics ||= init_metrics
+ end
+
+ def init_metrics
+ {
+ puma_workers: ::Gitlab::Metrics.gauge(:puma_workers, 'Total number of workers'),
+ puma_running_workers: ::Gitlab::Metrics.gauge(:puma_running_workers, 'Number of active workers'),
+ puma_stale_workers: ::Gitlab::Metrics.gauge(:puma_stale_workers, 'Number of stale workers'),
+ puma_phase: ::Gitlab::Metrics.gauge(:puma_phase, 'Phase number (increased during phased restarts)'),
+ puma_running: ::Gitlab::Metrics.gauge(:puma_running, 'Number of running threads'),
+ puma_queued_connections: ::Gitlab::Metrics.gauge(:puma_queued_connections, 'Number of connections in that worker\'s "todo" set waiting for a worker thread'),
+ puma_active_connections: ::Gitlab::Metrics.gauge(:puma_active_connections, 'Number of threads processing a request'),
+ puma_pool_capacity: ::Gitlab::Metrics.gauge(:puma_pool_capacity, 'Number of requests the worker is capable of taking right now'),
+ puma_max_threads: ::Gitlab::Metrics.gauge(:puma_max_threads, 'Maximum number of worker threads'),
+ puma_idle_threads: ::Gitlab::Metrics.gauge(:puma_idle_threads, 'Number of spawned threads which are not processing a request')
+ }
+ end
+
+ def sample
+ json_stats = puma_stats
+ return unless json_stats
+
+ stats = JSON.parse(json_stats)
+
+ if cluster?(stats)
+ sample_cluster(stats)
+ else
+ sample_single_worker(stats)
+ end
+ end
+
+ private
+
+ def puma_stats
+ Puma.stats
+ rescue NoMethodError
+ Rails.logger.info "PumaSampler: stats are not available yet, waiting for Puma to boot"
+ nil
+ end
+
+ def sample_cluster(stats)
+ set_master_metrics(stats)
+
+ stats['worker_status'].each do |worker|
+ last_status = worker['last_status']
+ labels = { worker: "worker_#{worker['index']}" }
+
+ metrics[:puma_phase].set(labels, worker['phase'])
+ set_worker_metrics(last_status, labels) if last_status.present?
+ end
+ end
+
+ def sample_single_worker(stats)
+ metrics[:puma_workers].set({}, 1)
+ metrics[:puma_running_workers].set({}, 1)
+
+ set_worker_metrics(stats)
+ end
+
+ def cluster?(stats)
+ stats['worker_status'].present?
+ end
+
+ def set_master_metrics(stats)
+ labels = { worker: "master" }
+
+ metrics[:puma_workers].set(labels, stats['workers'])
+ metrics[:puma_running_workers].set(labels, stats['booted_workers'])
+ metrics[:puma_stale_workers].set(labels, stats['old_workers'])
+ metrics[:puma_phase].set(labels, stats['phase'])
+ end
+
+ def set_worker_metrics(stats, labels = {})
+ metrics[:puma_running].set(labels, stats['running'])
+ metrics[:puma_queued_connections].set(labels, stats['backlog'])
+ metrics[:puma_active_connections].set(labels, stats['max_threads'] - stats['pool_capacity'])
+ metrics[:puma_pool_capacity].set(labels, stats['pool_capacity'])
+ metrics[:puma_max_threads].set(labels, stats['max_threads'])
+ metrics[:puma_idle_threads].set(labels, stats['running'] + stats['pool_capacity'] - stats['max_threads'])
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/samplers/ruby_sampler.rb b/lib/gitlab/metrics/samplers/ruby_sampler.rb
index 18a69321905..17eacbd21d8 100644
--- a/lib/gitlab/metrics/samplers/ruby_sampler.rb
+++ b/lib/gitlab/metrics/samplers/ruby_sampler.rb
@@ -23,25 +23,32 @@ module Gitlab
end
def init_metrics
- metrics = {}
- metrics[:sampler_duration] = ::Gitlab::Metrics.counter(with_prefix(:sampler, :duration_seconds_total), 'Sampler time', labels)
- metrics[:total_time] = ::Gitlab::Metrics.counter(with_prefix(:gc, :duration_seconds_total), 'Total GC time', labels)
+ metrics = {
+ file_descriptors: ::Gitlab::Metrics.gauge(with_prefix(:file, :descriptors), 'File descriptors used', labels, :livesum),
+ memory_bytes: ::Gitlab::Metrics.gauge(with_prefix(:memory, :bytes), 'Memory used', labels, :livesum),
+ process_cpu_seconds_total: ::Gitlab::Metrics.gauge(with_prefix(:process, :cpu_seconds_total), 'Process CPU seconds total'),
+ process_max_fds: ::Gitlab::Metrics.gauge(with_prefix(:process, :max_fds), 'Process max fds'),
+ process_resident_memory_bytes: ::Gitlab::Metrics.gauge(with_prefix(:process, :resident_memory_bytes), 'Memory used', labels, :livesum),
+ process_start_time_seconds: ::Gitlab::Metrics.gauge(with_prefix(:process, :start_time_seconds), 'Process start time seconds'),
+ sampler_duration: ::Gitlab::Metrics.counter(with_prefix(:sampler, :duration_seconds_total), 'Sampler time', labels),
+ total_time: ::Gitlab::Metrics.counter(with_prefix(:gc, :duration_seconds_total), 'Total GC time', labels)
+ }
+
GC.stat.keys.each do |key|
metrics[key] = ::Gitlab::Metrics.gauge(with_prefix(:gc_stat, key), to_doc_string(key), labels, :livesum)
end
- metrics[:memory_usage] = ::Gitlab::Metrics.gauge(with_prefix(:memory, :bytes), 'Memory used', labels, :livesum)
- metrics[:file_descriptors] = ::Gitlab::Metrics.gauge(with_prefix(:file, :descriptors), 'File descriptors used', labels, :livesum)
-
metrics
end
def sample
start_time = System.monotonic_time
- metrics[:memory_usage].set(labels.merge(worker_label), System.memory_usage)
metrics[:file_descriptors].set(labels.merge(worker_label), System.file_descriptor_count)
-
+ metrics[:process_cpu_seconds_total].set(labels.merge(worker_label), ::Gitlab::Metrics::System.cpu_time)
+ metrics[:process_max_fds].set(labels.merge(worker_label), ::Gitlab::Metrics::System.max_open_file_descriptors)
+ metrics[:process_start_time_seconds].set(labels.merge(worker_label), ::Gitlab::Metrics::System.process_start_time)
+ set_memory_usage_metrics
sample_gc
metrics[:sampler_duration].increment(labels, System.monotonic_time - start_time)
@@ -61,11 +68,19 @@ module Gitlab
metrics[:total_time].increment(labels, GC::Profiler.total_time)
end
+ def set_memory_usage_metrics
+ memory_usage = System.memory_usage
+ memory_labels = labels.merge(worker_label)
+
+ metrics[:memory_bytes].set(memory_labels, memory_usage)
+ metrics[:process_resident_memory_bytes].set(memory_labels, memory_usage)
+ end
+
def worker_label
+ return { worker: 'sidekiq' } if Sidekiq.server?
return {} unless defined?(Unicorn::Worker)
worker_no = ::Prometheus::Client::Support::Unicorn.worker_id
-
if worker_no
{ worker: worker_no }
else
diff --git a/lib/gitlab/metrics/samplers/unicorn_sampler.rb b/lib/gitlab/metrics/samplers/unicorn_sampler.rb
index bec64e864b3..9af7e0afed4 100644
--- a/lib/gitlab/metrics/samplers/unicorn_sampler.rb
+++ b/lib/gitlab/metrics/samplers/unicorn_sampler.rb
@@ -4,16 +4,16 @@ module Gitlab
module Metrics
module Samplers
class UnicornSampler < BaseSampler
- def initialize(interval)
- super(interval)
+ def metrics
+ @metrics ||= init_metrics
end
- def unicorn_active_connections
- @unicorn_active_connections ||= ::Gitlab::Metrics.gauge(:unicorn_active_connections, 'Unicorn active connections', {}, :max)
- end
-
- def unicorn_queued_connections
- @unicorn_queued_connections ||= ::Gitlab::Metrics.gauge(:unicorn_queued_connections, 'Unicorn queued connections', {}, :max)
+ def init_metrics
+ {
+ unicorn_active_connections: ::Gitlab::Metrics.gauge(:unicorn_active_connections, 'Unicorn active connections', {}, :max),
+ unicorn_queued_connections: ::Gitlab::Metrics.gauge(:unicorn_queued_connections, 'Unicorn queued connections', {}, :max),
+ unicorn_workers: ::Gitlab::Metrics.gauge(:unicorn_workers, 'Unicorn workers')
+ }
end
def enabled?
@@ -23,14 +23,13 @@ module Gitlab
def sample
Raindrops::Linux.tcp_listener_stats(tcp_listeners).each do |addr, stats|
- unicorn_active_connections.set({ socket_type: 'tcp', socket_address: addr }, stats.active)
- unicorn_queued_connections.set({ socket_type: 'tcp', socket_address: addr }, stats.queued)
+ set_unicorn_connection_metrics('tcp', addr, stats)
end
-
Raindrops::Linux.unix_listener_stats(unix_listeners).each do |addr, stats|
- unicorn_active_connections.set({ socket_type: 'unix', socket_address: addr }, stats.active)
- unicorn_queued_connections.set({ socket_type: 'unix', socket_address: addr }, stats.queued)
+ set_unicorn_connection_metrics('unix', addr, stats)
end
+
+ metrics[:unicorn_workers].set({}, unicorn_workers_count)
end
private
@@ -39,6 +38,13 @@ module Gitlab
@tcp_listeners ||= Unicorn.listener_names.grep(%r{\A[^/]+:\d+\z})
end
+ def set_unicorn_connection_metrics(type, addr, stats)
+ labels = { socket_type: type, socket_address: addr }
+
+ metrics[:unicorn_active_connections].set(labels, stats.active)
+ metrics[:unicorn_queued_connections].set(labels, stats.queued)
+ end
+
def unix_listeners
@unix_listeners ||= Unicorn.listener_names - tcp_listeners
end
@@ -46,6 +52,10 @@ module Gitlab
def unicorn_with_listeners?
defined?(Unicorn) && Unicorn.listener_names.any?
end
+
+ def unicorn_workers_count
+ `pgrep -f '[u]nicorn_rails worker.+ #{Rails.root.to_s}'`.split.count
+ end
end
end
end
diff --git a/lib/gitlab/metrics/system.rb b/lib/gitlab/metrics/system.rb
index 426496855e3..33c0de91c11 100644
--- a/lib/gitlab/metrics/system.rb
+++ b/lib/gitlab/metrics/system.rb
@@ -23,6 +23,22 @@ module Gitlab
def self.file_descriptor_count
Dir.glob('/proc/self/fd/*').length
end
+
+ def self.max_open_file_descriptors
+ match = File.read('/proc/self/limits').match(/Max open files\s*(\d+)/)
+
+ return unless match && match[1]
+
+ match[1].to_i
+ end
+
+ def self.process_start_time
+ fields = File.read('/proc/self/stat').split
+
+ # fields[21] is linux proc stat field "(22) starttime".
+ # The value is expressed in clock ticks, divide by clock ticks for seconds.
+ ( fields[21].to_i || 0 ) / clk_tck
+ end
else
def self.memory_usage
0.0
@@ -31,6 +47,14 @@ module Gitlab
def self.file_descriptor_count
0
end
+
+ def self.max_open_file_descriptors
+ 0
+ end
+
+ def self.process_start_time
+ 0
+ end
end
# THREAD_CPUTIME is not supported on OS X
@@ -59,6 +83,10 @@ module Gitlab
def self.monotonic_time
Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second)
end
+
+ def self.clk_tck
+ @clk_tck ||= `getconf CLK_TCK`.to_i
+ end
end
end
end
diff --git a/lib/gitlab/middleware/correlation_id.rb b/lib/gitlab/middleware/correlation_id.rb
index 80dddc41c12..fffd5da827f 100644
--- a/lib/gitlab/middleware/correlation_id.rb
+++ b/lib/gitlab/middleware/correlation_id.rb
@@ -12,7 +12,7 @@ module Gitlab
end
def call(env)
- ::Gitlab::CorrelationId.use_id(correlation_id(env)) do
+ ::Labkit::Correlation::CorrelationId.use_id(correlation_id(env)) do
@app.call(env)
end
end
diff --git a/lib/gitlab/middleware/read_only.rb b/lib/gitlab/middleware/read_only.rb
index 83c52a6c6e0..8e17073abab 100644
--- a/lib/gitlab/middleware/read_only.rb
+++ b/lib/gitlab/middleware/read_only.rb
@@ -3,7 +3,7 @@
module Gitlab
module Middleware
class ReadOnly
- API_VERSIONS = (3..4)
+ API_VERSIONS = (3..4).freeze
def self.internal_routes
@internal_routes ||=
diff --git a/lib/gitlab/middleware/release_env.rb b/lib/gitlab/middleware/release_env.rb
index 849cf8f759b..0719fb2e8c6 100644
--- a/lib/gitlab/middleware/release_env.rb
+++ b/lib/gitlab/middleware/release_env.rb
@@ -1,4 +1,3 @@
-# rubocop:disable Naming/FileName
# frozen_string_literal: true
module Gitlab
diff --git a/lib/gitlab/namespaced_session_store.rb b/lib/gitlab/namespaced_session_store.rb
new file mode 100644
index 00000000000..34520078bfb
--- /dev/null
+++ b/lib/gitlab/namespaced_session_store.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Gitlab
+ class NamespacedSessionStore
+ delegate :[], :[]=, to: :store
+
+ def initialize(key)
+ @key = key
+ end
+
+ def initiated?
+ !Session.current.nil?
+ end
+
+ def store
+ return unless Session.current
+
+ Session.current[@key] ||= {}
+ Session.current[@key]
+ end
+ end
+end
diff --git a/lib/gitlab/omniauth_initializer.rb b/lib/gitlab/omniauth_initializer.rb
index e0ac9eec1f2..2a2083ebae0 100644
--- a/lib/gitlab/omniauth_initializer.rb
+++ b/lib/gitlab/omniauth_initializer.rb
@@ -36,12 +36,25 @@ module Gitlab
hash_arguments = provider['args'].merge(provider_defaults(provider))
# A Hash from the configuration will be passed as is.
- provider_arguments << hash_arguments.symbolize_keys
+ provider_arguments << normalize_hash_arguments(hash_arguments)
end
provider_arguments
end
+ def normalize_hash_arguments(args)
+ args.symbolize_keys!
+
+ # Rails 5.1 deprecated the use of string names in the middleware
+ # (https://github.com/rails/rails/commit/83b767ce), so we need to
+ # pass in the actual class to Devise.
+ if args[:strategy_class].is_a?(String)
+ args[:strategy_class] = args[:strategy_class].constantize
+ end
+
+ args
+ end
+
def provider_defaults(provider)
case provider['name']
when 'cas3'
diff --git a/lib/gitlab/performance_bar/peek_query_tracker.rb b/lib/gitlab/performance_bar/peek_query_tracker.rb
index ac392432427..3a27e26eaba 100644
--- a/lib/gitlab/performance_bar/peek_query_tracker.rb
+++ b/lib/gitlab/performance_bar/peek_query_tracker.rb
@@ -26,20 +26,17 @@ module Gitlab
subscribe('sql.active_record') do |_, start, finish, _, data|
if Gitlab::SafeRequestStore.store[:peek_enabled]
- # data[:cached] is only available starting from Rails 5.1.0
- # https://github.com/rails/rails/blob/v5.1.0/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb#L113
- # Before that, data[:name] was set to 'CACHE'
- # https://github.com/rails/rails/blob/v4.2.9/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb#L80
- unless data.fetch(:cached, data[:name] == 'CACHE')
- track_query(data[:sql].strip, data[:binds], start, finish)
+ unless data[:cached]
+ backtrace = Gitlab::Profiler.clean_backtrace(caller)
+ track_query(data[:sql].strip, data[:binds], backtrace, start, finish)
end
end
end
end
- def track_query(raw_query, bindings, start, finish)
+ def track_query(raw_query, bindings, backtrace, start, finish)
duration = (finish - start) * 1000.0
- query_info = { duration: duration.round(3), sql: raw_query }
+ query_info = { duration: duration.round(3), sql: raw_query, backtrace: backtrace }
PEEK_DB_CLIENT.query_details << query_info
end
diff --git a/lib/gitlab/phabricator_import.rb b/lib/gitlab/phabricator_import.rb
new file mode 100644
index 00000000000..3885a9934d5
--- /dev/null
+++ b/lib/gitlab/phabricator_import.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module PhabricatorImport
+ BaseError = Class.new(StandardError)
+
+ def self.available?
+ Feature.enabled?(:phabricator_import) &&
+ Gitlab::CurrentSettings.import_sources.include?('phabricator')
+ end
+ end
+end
diff --git a/lib/gitlab/phabricator_import/base_worker.rb b/lib/gitlab/phabricator_import/base_worker.rb
new file mode 100644
index 00000000000..b69c65e78f8
--- /dev/null
+++ b/lib/gitlab/phabricator_import/base_worker.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+# All workers within a Phabricator import should inherit from this worker and
+# implement the `#import` method. The jobs should then be scheduled using the
+# `.schedule` class method instead of `.perform_async`
+#
+# Doing this makes sure that only one job of that type is running at the same time
+# for a certain project. This will avoid deadlocks. When a job is already running
+# we'll wait for it for 10 times 5 seconds to restart. If the running job hasn't
+# finished, by then, we'll retry in 30 seconds.
+#
+# It also makes sure that we keep the import state of the project up to date:
+# - It keeps track of the jobs so we know how many jobs are running for the
+# project
+# - It refreshes the import jid, so it doesn't get cleaned up by the
+# `StuckImportJobsWorker`
+# - It marks the import as failed if a job failed to many times
+# - It marks the import as finished when all remaining jobs are done
+module Gitlab
+ module PhabricatorImport
+ class BaseWorker
+ include ApplicationWorker
+ include ProjectImportOptions # This marks the project as failed after too many tries
+ include Gitlab::ExclusiveLeaseHelpers
+
+ class << self
+ def schedule(project_id, *args)
+ perform_async(project_id, *args)
+ add_job(project_id)
+ end
+
+ def add_job(project_id)
+ worker_state(project_id).add_job
+ end
+
+ def remove_job(project_id)
+ worker_state(project_id).remove_job
+ end
+
+ def worker_state(project_id)
+ Gitlab::PhabricatorImport::WorkerState.new(project_id)
+ end
+ end
+
+ def perform(project_id, *args)
+ in_lock("#{self.class.name.underscore}/#{project_id}/#{args}", ttl: 2.hours, sleep_sec: 5.seconds) do
+ project = Project.find_by_id(project_id)
+ next unless project
+
+ # Bail if the import job already failed
+ next unless project.import_state&.in_progress?
+
+ project.import_state.refresh_jid_expiration
+
+ import(project, *args)
+
+ # If this is the last running job, finish the import
+ project.after_import if self.class.worker_state(project_id).running_count < 2
+
+ self.class.remove_job(project_id)
+ end
+ rescue Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError
+ # Reschedule a job if there was already a running one
+ # Running them at the same time could cause a deadlock updating the same
+ # resource
+ self.class.perform_in(30.seconds, project_id, *args)
+ end
+
+ private
+
+ def import(project, *args)
+ importer_class.new(project, *args).execute
+ end
+
+ def importer_class
+ raise NotImplementedError, "Implement `#{__method__}` on #{self.class}"
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/phabricator_import/cache/map.rb b/lib/gitlab/phabricator_import/cache/map.rb
new file mode 100644
index 00000000000..fa8b37b20ca
--- /dev/null
+++ b/lib/gitlab/phabricator_import/cache/map.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+module Gitlab
+ module PhabricatorImport
+ module Cache
+ class Map
+ def initialize(project)
+ @project = project
+ end
+
+ def get_gitlab_model(phabricator_id)
+ cached_info = get(phabricator_id)
+ return unless cached_info[:classname] && cached_info[:database_id]
+
+ cached_info[:classname].constantize.find_by_id(cached_info[:database_id])
+ end
+
+ def set_gitlab_model(object, phabricator_id)
+ set(object.class, object.id, phabricator_id)
+ end
+
+ private
+
+ attr_reader :project
+
+ def set(klass_name, object_id, phabricator_id)
+ key = cache_key_for_phabricator_id(phabricator_id)
+
+ redis.with do |r|
+ r.multi do |multi|
+ multi.mapped_hmset(key,
+ { classname: klass_name, database_id: object_id })
+ multi.expire(key, timeout)
+ end
+ end
+ end
+
+ def get(phabricator_id)
+ key = cache_key_for_phabricator_id(phabricator_id)
+
+ redis.with do |r|
+ r.pipelined do |pipe|
+ # Extend the TTL when a key was
+ pipe.expire(key, timeout)
+ pipe.mapped_hmget(key, :classname, :database_id)
+ end.last
+ end
+ end
+
+ def cache_key_for_phabricator_id(phabricator_id)
+ "#{Redis::Cache::CACHE_NAMESPACE}/phabricator-import/#{project.id}/#{phabricator_id}"
+ end
+
+ def redis
+ Gitlab::Redis::Cache
+ end
+
+ def timeout
+ # Setting the timeout to the same one as we do for clearing stuck jobs
+ # this makes sure all cache is available while the import is running.
+ StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/phabricator_import/conduit.rb b/lib/gitlab/phabricator_import/conduit.rb
new file mode 100644
index 00000000000..4c64d737389
--- /dev/null
+++ b/lib/gitlab/phabricator_import/conduit.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+module Gitlab
+ module PhabricatorImport
+ module Conduit
+ ApiError = Class.new(Gitlab::PhabricatorImport::BaseError)
+ ResponseError = Class.new(ApiError)
+ end
+ end
+end
diff --git a/lib/gitlab/phabricator_import/conduit/client.rb b/lib/gitlab/phabricator_import/conduit/client.rb
new file mode 100644
index 00000000000..4469a3f5849
--- /dev/null
+++ b/lib/gitlab/phabricator_import/conduit/client.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+module Gitlab
+ module PhabricatorImport
+ module Conduit
+ class Client
+ def initialize(phabricator_url, api_token)
+ @phabricator_url = phabricator_url
+ @api_token = api_token
+ end
+
+ def get(path, params: {})
+ response = Gitlab::HTTP.get(build_url(path), body: build_params(params), headers: headers)
+ Response.parse!(response)
+ rescue *Gitlab::HTTP::HTTP_ERRORS => e
+ # Wrap all errors from the API into an API-error.
+ raise ApiError.new(e)
+ end
+
+ private
+
+ attr_reader :phabricator_url, :api_token
+
+ def headers
+ { "Accept" => 'application/json' }
+ end
+
+ def build_url(path)
+ URI.join(phabricator_url, '/api/', path).to_s
+ end
+
+ def build_params(params)
+ params = params.dup
+ params.compact!
+ params.reverse_merge!("api.token" => api_token)
+
+ CGI.unescape(params.to_query)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/phabricator_import/conduit/maniphest.rb b/lib/gitlab/phabricator_import/conduit/maniphest.rb
new file mode 100644
index 00000000000..848b71e49e7
--- /dev/null
+++ b/lib/gitlab/phabricator_import/conduit/maniphest.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+module Gitlab
+ module PhabricatorImport
+ module Conduit
+ class Maniphest
+ def initialize(phabricator_url:, api_token:)
+ @client = Client.new(phabricator_url, api_token)
+ end
+
+ def tasks(after: nil)
+ TasksResponse.new(get_tasks(after))
+ end
+
+ private
+
+ def get_tasks(after)
+ client.get('maniphest.search',
+ params: {
+ after: after,
+ attachments: { projects: 1, subscribers: 1, columns: 1 }
+ })
+ end
+
+ attr_reader :client
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/phabricator_import/conduit/pagination.rb b/lib/gitlab/phabricator_import/conduit/pagination.rb
new file mode 100644
index 00000000000..5f54cccdbc8
--- /dev/null
+++ b/lib/gitlab/phabricator_import/conduit/pagination.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+module Gitlab
+ module PhabricatorImport
+ module Conduit
+ class Pagination
+ def initialize(cursor_json)
+ @cursor_json = cursor_json
+ end
+
+ def has_next_page?
+ next_page.present?
+ end
+
+ def next_page
+ cursor_json["after"]
+ end
+
+ private
+
+ attr_reader :cursor_json
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/phabricator_import/conduit/response.rb b/lib/gitlab/phabricator_import/conduit/response.rb
new file mode 100644
index 00000000000..6053ecfbd5e
--- /dev/null
+++ b/lib/gitlab/phabricator_import/conduit/response.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+module Gitlab
+ module PhabricatorImport
+ module Conduit
+ class Response
+ def self.parse!(http_response)
+ unless http_response.success?
+ raise Gitlab::PhabricatorImport::Conduit::ResponseError,
+ "Phabricator responded with #{http_response.status}"
+ end
+
+ response = new(JSON.parse(http_response.body))
+
+ unless response.success?
+ raise ResponseError,
+ "Phabricator Error: #{response.error_code}: #{response.error_info}"
+ end
+
+ response
+ rescue JSON::JSONError => e
+ raise ResponseError.new(e)
+ end
+
+ def initialize(json)
+ @json = json
+ end
+
+ def success?
+ error_code.nil?
+ end
+
+ def error_code
+ json['error_code']
+ end
+
+ def error_info
+ json['error_info']
+ end
+
+ def data
+ json_result&.fetch('data')
+ end
+
+ def pagination
+ return unless cursor_info = json_result&.fetch('cursor')
+
+ @pagination ||= Pagination.new(cursor_info)
+ end
+
+ private
+
+ attr_reader :json
+
+ def json_result
+ json['result']
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/phabricator_import/conduit/tasks_response.rb b/lib/gitlab/phabricator_import/conduit/tasks_response.rb
new file mode 100644
index 00000000000..cbcf7259fb2
--- /dev/null
+++ b/lib/gitlab/phabricator_import/conduit/tasks_response.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+module Gitlab
+ module PhabricatorImport
+ module Conduit
+ class TasksResponse
+ def initialize(conduit_response)
+ @conduit_response = conduit_response
+ end
+
+ delegate :pagination, to: :conduit_response
+
+ def tasks
+ @tasks ||= conduit_response.data.map do |task_json|
+ Gitlab::PhabricatorImport::Representation::Task.new(task_json)
+ end
+ end
+
+ private
+
+ attr_reader :conduit_response
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/phabricator_import/import_tasks_worker.rb b/lib/gitlab/phabricator_import/import_tasks_worker.rb
new file mode 100644
index 00000000000..c36954a8d41
--- /dev/null
+++ b/lib/gitlab/phabricator_import/import_tasks_worker.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+module Gitlab
+ module PhabricatorImport
+ class ImportTasksWorker < BaseWorker
+ def importer_class
+ Gitlab::PhabricatorImport::Issues::Importer
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/phabricator_import/importer.rb b/lib/gitlab/phabricator_import/importer.rb
new file mode 100644
index 00000000000..c1797f4027e
--- /dev/null
+++ b/lib/gitlab/phabricator_import/importer.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module PhabricatorImport
+ class Importer
+ def self.async?
+ true
+ end
+
+ def self.imports_repository?
+ # This does not really import a repository, but we want to skip all
+ # repository related tasks in the `Projects::ImportService`
+ true
+ end
+
+ def initialize(project)
+ @project = project
+ end
+
+ def execute
+ Gitlab::Import::SetAsyncJid.set_jid(project)
+ schedule_first_tasks_page
+
+ true
+ rescue => e
+ fail_import(e.message)
+
+ false
+ end
+
+ private
+
+ attr_reader :project
+
+ def schedule_first_tasks_page
+ ImportTasksWorker.schedule(project.id)
+ end
+
+ def fail_import(message)
+ project.import_state.mark_as_failed(message)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/phabricator_import/issues/importer.rb b/lib/gitlab/phabricator_import/issues/importer.rb
new file mode 100644
index 00000000000..a58438452ff
--- /dev/null
+++ b/lib/gitlab/phabricator_import/issues/importer.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+module Gitlab
+ module PhabricatorImport
+ module Issues
+ class Importer
+ def initialize(project, after = nil)
+ @project, @after = project, after
+ end
+
+ def execute
+ schedule_next_batch
+
+ tasks_response.tasks.each do |task|
+ TaskImporter.new(project, task).execute
+ end
+ end
+
+ private
+
+ attr_reader :project, :after
+
+ def schedule_next_batch
+ return unless tasks_response.pagination.has_next_page?
+
+ Gitlab::PhabricatorImport::ImportTasksWorker
+ .schedule(project.id, tasks_response.pagination.next_page)
+ end
+
+ def tasks_response
+ @tasks_response ||= client.tasks(after: after)
+ end
+
+ def client
+ @client ||=
+ Gitlab::PhabricatorImport::Conduit::Maniphest
+ .new(phabricator_url: project.import_data.data['phabricator_url'],
+ api_token: project.import_data.credentials[:api_token])
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/phabricator_import/issues/task_importer.rb b/lib/gitlab/phabricator_import/issues/task_importer.rb
new file mode 100644
index 00000000000..40d4392cbc1
--- /dev/null
+++ b/lib/gitlab/phabricator_import/issues/task_importer.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+module Gitlab
+ module PhabricatorImport
+ module Issues
+ class TaskImporter
+ def initialize(project, task)
+ @project, @task = project, task
+ end
+
+ def execute
+ # TODO: get the user from the project namespace from the username loaded by Phab-id
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/60565
+ issue.author = User.ghost
+
+ # TODO: Reformat the description with attachments, escaping accidental
+ # links and add attachments
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/60603
+ issue.assign_attributes(task.issue_attributes)
+
+ save!
+
+ issue
+ end
+
+ private
+
+ attr_reader :project, :task
+
+ def save!
+ # Just avoiding an extra redis call, we've already updated the expiry
+ # when reading the id from the map
+ was_persisted = issue.persisted?
+
+ issue.save! if issue.changed?
+
+ object_map.set_gitlab_model(issue, task.phabricator_id) unless was_persisted
+ end
+
+ def issue
+ @issue ||= find_issue_by_phabricator_id(task.phabricator_id) ||
+ project.issues.new
+ end
+
+ def find_issue_by_phabricator_id(phabricator_id)
+ object_map.get_gitlab_model(phabricator_id)
+ end
+
+ def object_map
+ Gitlab::PhabricatorImport::Cache::Map.new(project)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/phabricator_import/project_creator.rb b/lib/gitlab/phabricator_import/project_creator.rb
new file mode 100644
index 00000000000..b37a5b44980
--- /dev/null
+++ b/lib/gitlab/phabricator_import/project_creator.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module PhabricatorImport
+ class ProjectCreator
+ def initialize(current_user, params)
+ @current_user = current_user
+ @params = params.dup
+ end
+
+ def execute
+ return unless import_url.present? && api_token.present?
+
+ project = Projects::CreateService.new(current_user, create_params).execute
+ return project unless project.persisted?
+
+ project.project_feature.update!(project_feature_attributes)
+
+ project
+ end
+
+ private
+
+ attr_reader :current_user, :params
+
+ def create_params
+ {
+ name: project_name,
+ path: project_path,
+ namespace_id: namespace_id,
+ import_type: 'phabricator',
+ import_url: Project::UNKNOWN_IMPORT_URL,
+ import_data: import_data
+ }
+ end
+
+ def project_name
+ params[:name]
+ end
+
+ def project_path
+ params[:path]
+ end
+
+ def namespace_id
+ params[:namespace_id] || current_user.namespace_id
+ end
+
+ def import_url
+ params[:phabricator_server_url]
+ end
+
+ def api_token
+ params[:api_token]
+ end
+
+ def project_feature_attributes
+ @project_features_attributes ||= begin
+ # everything disabled except for issues
+ ProjectFeature::FEATURES.map do |feature|
+ [ProjectFeature.access_level_attribute(feature), ProjectFeature::DISABLED]
+ end.to_h.merge(ProjectFeature.access_level_attribute(:issues) => ProjectFeature::ENABLED)
+ end
+ end
+
+ def import_data
+ {
+ data: {
+ phabricator_url: import_url
+ },
+ credentials: {
+ api_token: params.fetch(:api_token)
+ }
+ }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/phabricator_import/representation/task.rb b/lib/gitlab/phabricator_import/representation/task.rb
new file mode 100644
index 00000000000..6aedc71b626
--- /dev/null
+++ b/lib/gitlab/phabricator_import/representation/task.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+module Gitlab
+ module PhabricatorImport
+ module Representation
+ class Task
+ def initialize(json)
+ @json = json
+ end
+
+ def phabricator_id
+ json['phid']
+ end
+
+ def issue_attributes
+ @issue_attributes ||= {
+ title: issue_title,
+ description: issue_description,
+ state: issue_state,
+ created_at: issue_created_at,
+ closed_at: issue_closed_at
+ }
+ end
+
+ private
+
+ attr_reader :json
+
+ def issue_title
+ # The 255 limit is the validation we impose on the Issue title in
+ # Issuable
+ @issue_title ||= json['fields']['name'].truncate(255)
+ end
+
+ def issue_description
+ json['fields']['description']['raw']
+ end
+
+ def issue_state
+ issue_closed_at.present? ? :closed : :opened
+ end
+
+ def issue_created_at
+ return unless json['fields']['dateCreated']
+
+ @issue_created_at ||= cast_datetime(json['fields']['dateCreated'])
+ end
+
+ def issue_closed_at
+ return unless json['fields']['dateClosed']
+
+ @issue_closed_at ||= cast_datetime(json['fields']['dateClosed'])
+ end
+
+ def cast_datetime(value)
+ Time.at(value.to_i)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/phabricator_import/worker_state.rb b/lib/gitlab/phabricator_import/worker_state.rb
new file mode 100644
index 00000000000..38829e34509
--- /dev/null
+++ b/lib/gitlab/phabricator_import/worker_state.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+module Gitlab
+ module PhabricatorImport
+ class WorkerState
+ def initialize(project_id)
+ @project_id = project_id
+ end
+
+ def add_job
+ redis.with do |r|
+ r.pipelined do |pipe|
+ pipe.incr(all_jobs_key)
+ pipe.expire(all_jobs_key, timeout)
+ end
+ end
+ end
+
+ def remove_job
+ redis.with do |r|
+ r.decr(all_jobs_key)
+ end
+ end
+
+ def running_count
+ redis.with { |r| r.get(all_jobs_key) }.to_i
+ end
+
+ private
+
+ attr_reader :project_id
+
+ def redis
+ Gitlab::Redis::SharedState
+ end
+
+ def all_jobs_key
+ @all_jobs_key ||= "phabricator-import/jobs/project-#{project_id}/job-count"
+ end
+
+ def timeout
+ # Make sure we get rid of all the information after a job is marked
+ # as failed/succeeded
+ StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/profiler.rb b/lib/gitlab/profiler.rb
index 93a9fcf1591..890228e5e78 100644
--- a/lib/gitlab/profiler.rb
+++ b/lib/gitlab/profiler.rb
@@ -16,7 +16,11 @@ module Gitlab
ee/lib/gitlab/middleware/
lib/gitlab/performance_bar/
lib/gitlab/request_profiler/
+ lib/gitlab/query_limiting/
+ lib/gitlab/tracing/
lib/gitlab/profiler.rb
+ lib/gitlab/correlation_id.rb
+ lib/gitlab/webpack/dev_server_middleware.rb
].freeze
# Takes a URL to profile (can be a fully-qualified URL, or an absolute path)
@@ -69,7 +73,7 @@ module Gitlab
result = with_custom_logger(logger) do
with_user(user) do
- RubyProf.profile { app.public_send(verb, url, post_data, headers) } # rubocop:disable GitlabSecurity/PublicSend
+ RubyProf.profile { app.public_send(verb, url, params: post_data, headers: headers) } # rubocop:disable GitlabSecurity/PublicSend
end
end
diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb
index 58f06b6708c..0f3b97e2317 100644
--- a/lib/gitlab/project_search_results.rb
+++ b/lib/gitlab/project_search_results.rb
@@ -138,6 +138,12 @@ module Gitlab
project
end
+ def filter_milestones_by_project(milestones)
+ return Milestone.none unless Ability.allowed?(@current_user, :read_milestone, @project)
+
+ milestones.where(project_id: project.id) # rubocop: disable CodeReuse/ActiveRecord
+ end
+
def repository_project_ref
@repository_project_ref ||= repository_ref || project.default_branch
end
@@ -145,5 +151,9 @@ module Gitlab
def repository_wiki_ref
@repository_wiki_ref ||= repository_ref || project.wiki.default_branch
end
+
+ def issuable_params
+ super.merge(project_id: project.id)
+ end
end
end
diff --git a/lib/gitlab/prometheus/query_variables.rb b/lib/gitlab/prometheus/query_variables.rb
index 1cc85d4b4a6..9cc21129547 100644
--- a/lib/gitlab/prometheus/query_variables.rb
+++ b/lib/gitlab/prometheus/query_variables.rb
@@ -4,9 +4,12 @@ module Gitlab
module Prometheus
module QueryVariables
def self.call(environment)
+ deployment_platform = environment.deployment_platform
+ namespace = deployment_platform&.kubernetes_namespace_for(environment.project) || ''
+
{
ci_environment_slug: environment.slug,
- kube_namespace: environment.deployment_platform&.actual_namespace || '',
+ kube_namespace: namespace,
environment_filter: %{container_name!="POD",environment="#{environment.slug}"}
}
end
diff --git a/lib/gitlab/proxy_http_connection_adapter.rb b/lib/gitlab/proxy_http_connection_adapter.rb
deleted file mode 100644
index a64cb47e77e..00000000000
--- a/lib/gitlab/proxy_http_connection_adapter.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-# This class is part of the Gitlab::HTTP wrapper. Depending on the value
-# of the global setting allow_local_requests_from_hooks_and_services this adapter
-# will allow/block connection to internal IPs and/or urls.
-#
-# This functionality can be overridden by providing the setting the option
-# allow_local_requests = true in the request. For example:
-# Gitlab::HTTP.get('http://www.gitlab.com', allow_local_requests: true)
-#
-# This option will take precedence over the global setting.
-module Gitlab
- class ProxyHTTPConnectionAdapter < HTTParty::ConnectionAdapter
- def connection
- unless allow_local_requests?
- begin
- Gitlab::UrlBlocker.validate!(uri, allow_local_network: false)
- rescue Gitlab::UrlBlocker::BlockedUrlError => e
- raise Gitlab::HTTP::BlockedUrlError, "URL '#{uri}' is blocked: #{e.message}"
- end
- end
-
- super
- end
-
- private
-
- def allow_local_requests?
- options.fetch(:allow_local_requests, allow_settings_local_requests?)
- end
-
- def allow_settings_local_requests?
- Gitlab::CurrentSettings.allow_local_requests_from_hooks_and_services?
- end
- end
-end
diff --git a/lib/gitlab/push_options.rb b/lib/gitlab/push_options.rb
index 810aba436cc..3137676ba4b 100644
--- a/lib/gitlab/push_options.rb
+++ b/lib/gitlab/push_options.rb
@@ -15,7 +15,7 @@ module Gitlab
mr: :merge_request
}).freeze
- OPTION_MATCHER = /(?<namespace>[^\.]+)\.(?<key>[^=]+)=?(?<value>.*)/
+ OPTION_MATCHER = /(?<namespace>[^\.]+)\.(?<key>[^=]+)=?(?<value>.*)/.freeze
attr_reader :options
diff --git a/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb b/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb
index 1cd158db2b0..e1579cfddc0 100644
--- a/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb
+++ b/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb
@@ -102,7 +102,7 @@ module Gitlab
@updates[:milestone_id] = nil
end
- desc _('Copy labels and milestone from other issue or merge request')
+ desc _('Copy labels and milestone from other issue or merge request in this project')
explanation do |source_issuable|
_("Copy labels and milestone from %{source_issuable_reference}.") % { source_issuable_reference: source_issuable.to_reference }
end
diff --git a/lib/gitlab/quick_actions/spend_time_and_date_separator.rb b/lib/gitlab/quick_actions/spend_time_and_date_separator.rb
index f5176376a60..4a62e83e8e9 100644
--- a/lib/gitlab/quick_actions/spend_time_and_date_separator.rb
+++ b/lib/gitlab/quick_actions/spend_time_and_date_separator.rb
@@ -11,7 +11,7 @@ module Gitlab
# if date doesn't present return time with current date
# in other cases return nil
class SpendTimeAndDateSeparator
- DATE_REGEX = %r{(\d{2,4}[/\-.]\d{1,2}[/\-.]\d{1,2})}
+ DATE_REGEX = %r{(\d{2,4}[/\-.]\d{1,2}[/\-.]\d{1,2})}.freeze
def initialize(spend_command_arg)
@spend_arg = spend_command_arg
diff --git a/lib/gitlab/routing.rb b/lib/gitlab/routing.rb
index 3b05f181ed2..84885be9bda 100644
--- a/lib/gitlab/routing.rb
+++ b/lib/gitlab/routing.rb
@@ -45,7 +45,7 @@ module Gitlab
def self.redirect_legacy_paths(router, *paths)
build_redirect_path = lambda do |request, _params, path|
- # Only replace the last occurence of `path`.
+ # Only replace the last occurrence of `path`.
#
# `request.fullpath` includes the querystring
new_path = request.path.sub(%r{/#{path}(/*)(?!.*#{path})}, "/-/#{path}\\1")
diff --git a/lib/gitlab/sanitizers/svg.rb b/lib/gitlab/sanitizers/svg.rb
index 0d4e6be2129..98f78c5e74b 100644
--- a/lib/gitlab/sanitizers/svg.rb
+++ b/lib/gitlab/sanitizers/svg.rb
@@ -9,7 +9,7 @@ module Gitlab
class Scrubber < Loofah::Scrubber
# http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#embedding-custom-non-visible-data-with-the-data-*-attributes
- DATA_ATTR_PATTERN = /\Adata-(?!xml)[a-z_][\w.\u00E0-\u00F6\u00F8-\u017F\u01DD-\u02AF-]*\z/u
+ DATA_ATTR_PATTERN = /\Adata-(?!xml)[a-z_][\w.\u00E0-\u00F6\u00F8-\u017F\u01DD-\u02AF-]*\z/u.freeze
def scrub(node)
unless Whitelist::ALLOWED_ELEMENTS.include?(node.name)
diff --git a/lib/gitlab/search_results.rb b/lib/gitlab/search_results.rb
index 8988b9ad7be..7c1e6b1baff 100644
--- a/lib/gitlab/search_results.rb
+++ b/lib/gitlab/search_results.rb
@@ -2,6 +2,8 @@
module Gitlab
class SearchResults
+ COUNT_LIMIT = 1001
+
attr_reader :current_user, :query, :per_page
# Limit search results by passed projects
@@ -25,29 +27,26 @@ module Gitlab
def objects(scope, page = nil, without_count = true)
collection = case scope
when 'projects'
- projects.page(page).per(per_page)
+ projects
when 'issues'
- issues.page(page).per(per_page)
+ issues
when 'merge_requests'
- merge_requests.page(page).per(per_page)
+ merge_requests
when 'milestones'
- milestones.page(page).per(per_page)
+ milestones
when 'users'
- users.page(page).per(per_page)
+ users
else
- Kaminari.paginate_array([]).page(page).per(per_page)
- end
+ Kaminari.paginate_array([])
+ end.page(page).per(per_page)
without_count ? collection.without_count : collection
end
- # rubocop: disable CodeReuse/ActiveRecord
def limited_projects_count
- @limited_projects_count ||= projects.limit(count_limit).count
+ @limited_projects_count ||= limited_count(projects)
end
- # rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def limited_issues_count
return @limited_issues_count if @limited_issues_count
@@ -56,35 +55,28 @@ module Gitlab
# and confidential issues user has access to, is too complex.
# It's faster to try to fetch all public issues first, then only
# if necessary try to fetch all issues.
- sum = issues(public_only: true).limit(count_limit).count
- @limited_issues_count = sum < count_limit ? issues.limit(count_limit).count : sum
+ sum = limited_count(issues(public_only: true))
+ @limited_issues_count = sum < count_limit ? limited_count(issues) : sum
end
- # rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def limited_merge_requests_count
- @limited_merge_requests_count ||= merge_requests.limit(count_limit).count
+ @limited_merge_requests_count ||= limited_count(merge_requests)
end
- # rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def limited_milestones_count
- @limited_milestones_count ||= milestones.limit(count_limit).count
+ @limited_milestones_count ||= limited_count(milestones)
end
- # rubocop: enable CodeReuse/ActiveRecord
- # rubocop:disable CodeReuse/ActiveRecord
def limited_users_count
- @limited_users_count ||= users.limit(count_limit).count
+ @limited_users_count ||= limited_count(users)
end
- # rubocop:enable CodeReuse/ActiveRecord
def single_commit_result?
false
end
def count_limit
- 1001
+ COUNT_LIMIT
end
def users
@@ -99,58 +91,82 @@ module Gitlab
limit_projects.search(query)
end
- # rubocop: disable CodeReuse/ActiveRecord
def issues(finder_params = {})
- issues = IssuesFinder.new(current_user, finder_params).execute
+ issues = IssuesFinder.new(current_user, issuable_params.merge(finder_params)).execute
+
unless default_project_filter
- issues = issues.where(project_id: project_ids_relation)
+ issues = issues.where(project_id: project_ids_relation) # rubocop: disable CodeReuse/ActiveRecord
end
- issues =
- if query =~ /#(\d+)\z/
- issues.where(iid: $1)
- else
- issues.full_search(query)
- end
-
- issues.reorder('updated_at DESC')
+ issues
end
- # rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def milestones
- milestones = Milestone.where(project_id: project_ids_relation)
- milestones = milestones.search(query)
+ milestones = Milestone.search(query)
+
+ milestones = filter_milestones_by_project(milestones)
+
milestones.reorder('updated_at DESC')
end
# rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def merge_requests
- merge_requests = MergeRequestsFinder.new(current_user).execute
+ merge_requests = MergeRequestsFinder.new(current_user, issuable_params).execute
+
unless default_project_filter
merge_requests = merge_requests.in_projects(project_ids_relation)
end
- merge_requests =
- if query =~ /[#!](\d+)\z/
- merge_requests.where(iid: $1)
- else
- merge_requests.full_search(query)
- end
-
- merge_requests.reorder('updated_at DESC')
+ merge_requests
end
- # rubocop: enable CodeReuse/ActiveRecord
def default_scope
'projects'
end
+ # Filter milestones by authorized projects.
+ # For performance reasons project_id is being plucked
+ # to be used on a smaller query.
+ #
+ # rubocop: disable CodeReuse/ActiveRecord
+ def filter_milestones_by_project(milestones)
+ project_ids =
+ milestones.where(project_id: project_ids_relation)
+ .select(:project_id).distinct
+ .pluck(:project_id)
+
+ return Milestone.none if project_ids.nil?
+
+ authorized_project_ids_relation =
+ Project.where(id: project_ids).ids_with_milestone_available_for(current_user)
+
+ milestones.where(project_id: authorized_project_ids_relation)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
# rubocop: disable CodeReuse/ActiveRecord
def project_ids_relation
limit_projects.select(:id).reorder(nil)
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ def issuable_params
+ {}.tap do |params|
+ params[:sort] = 'updated_desc'
+
+ if query =~ /#(\d+)\z/
+ params[:iids] = $1
+ else
+ params[:search] = query
+ end
+ end
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def limited_count(relation)
+ relation.reorder(nil).limit(count_limit).size
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
end
end
diff --git a/lib/gitlab/sentry.rb b/lib/gitlab/sentry.rb
index 956c16117f5..72c44114001 100644
--- a/lib/gitlab/sentry.rb
+++ b/lib/gitlab/sentry.rb
@@ -10,7 +10,7 @@ module Gitlab
def self.context(current_user = nil)
return unless enabled?
- Raven.tags_context(locale: I18n.locale)
+ Raven.tags_context(default_tags)
if current_user
Raven.user_context(
@@ -44,16 +44,19 @@ module Gitlab
extra[:issue_url] = issue_url if issue_url
context # Make sure we've set everything we know in the context
- tags = {
- Gitlab::CorrelationId::LOG_KEY.to_sym => Gitlab::CorrelationId.current_id
- }
-
- Raven.capture_exception(exception, tags: tags, extra: extra)
+ Raven.capture_exception(exception, tags: default_tags, extra: extra)
end
end
def self.should_raise_for_dev?
Rails.env.development? || Rails.env.test?
end
+
+ def self.default_tags
+ {
+ Labkit::Correlation::CorrelationId::LOG_KEY.to_sym => Labkit::Correlation::CorrelationId.current_id,
+ locale: I18n.locale
+ }
+ end
end
end
diff --git a/lib/gitlab/session.rb b/lib/gitlab/session.rb
new file mode 100644
index 00000000000..7487ba04a6d
--- /dev/null
+++ b/lib/gitlab/session.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Gitlab
+ class Session
+ STORE_KEY = :session_storage
+
+ class << self
+ def with_session(session)
+ old = self.current
+ self.current = session
+ yield
+ ensure
+ self.current = old
+ end
+
+ def current
+ Thread.current[STORE_KEY]
+ end
+
+ protected
+
+ def current=(value)
+ Thread.current[STORE_KEY] = value
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/setup_helper.rb b/lib/gitlab/setup_helper.rb
index 2b7e12639be..0d3e78c0a66 100644
--- a/lib/gitlab/setup_helper.rb
+++ b/lib/gitlab/setup_helper.rb
@@ -44,6 +44,13 @@ module Gitlab
config[:'gitlab-shell'] = { dir: Gitlab.config.gitlab_shell.path }
config[:bin_dir] = Gitlab.config.gitaly.client_path
+ if Rails.env.test?
+ # Compared to production, tests run in constrained environments. This
+ # number is meant to grow with the number of concurrent rails requests /
+ # sidekiq jobs, and concurrency will be low anyway in test.
+ config[:git] = { catfile_cache_size: 5 }
+ end
+
TomlRB.dump(config)
end
diff --git a/lib/gitlab/sherlock/middleware.rb b/lib/gitlab/sherlock/middleware.rb
index 747cb0f9142..f7b08d58e49 100644
--- a/lib/gitlab/sherlock/middleware.rb
+++ b/lib/gitlab/sherlock/middleware.rb
@@ -4,9 +4,9 @@ module Gitlab
module Sherlock
# Rack middleware used for tracking request metrics.
class Middleware
- CONTENT_TYPES = %r{text/html|application/json}i
+ CONTENT_TYPES = %r{text/html|application/json}i.freeze
- IGNORE_PATHS = %r{^/sherlock}
+ IGNORE_PATHS = %r{^/sherlock}.freeze
def initialize(app)
@app = app
diff --git a/lib/gitlab/sherlock/query.rb b/lib/gitlab/sherlock/query.rb
index 11561eec32a..159ce27e702 100644
--- a/lib/gitlab/sherlock/query.rb
+++ b/lib/gitlab/sherlock/query.rb
@@ -15,7 +15,7 @@ module Gitlab
|GROUP\s+BY
|ORDER\s+BY
|LIMIT
- |OFFSET)\s+}ix # Vim indent breaks when this is on a newline :<
+ |OFFSET)\s+}ix.freeze # Vim indent breaks when this is on a newline :<
# Creates a new Query using a String and a separate Array of bindings.
#
diff --git a/lib/gitlab/sidekiq_config.rb b/lib/gitlab/sidekiq_config.rb
index fb303e3fb0c..c102fa14cfc 100644
--- a/lib/gitlab/sidekiq_config.rb
+++ b/lib/gitlab/sidekiq_config.rb
@@ -7,7 +7,7 @@ module Gitlab
module SidekiqConfig
QUEUE_CONFIG_PATHS = %w[app/workers/all_queues.yml ee/app/workers/all_queues.yml].freeze
- # This method is called by `bin/sidekiq-cluster` in EE, which runs outside
+ # This method is called by `ee/bin/sidekiq-cluster` in EE, which runs outside
# of bundler/Rails context, so we cannot use any gem or Rails methods.
def self.worker_queues(rails_path = Rails.root.to_s)
@worker_queues ||= {}
@@ -19,7 +19,7 @@ module Gitlab
end
end
- # This method is called by `bin/sidekiq-cluster` in EE, which runs outside
+ # This method is called by `ee/bin/sidekiq-cluster` in EE, which runs outside
# of bundler/Rails context, so we cannot use any gem or Rails methods.
def self.expand_queues(queues, all_queues = self.worker_queues)
return [] if queues.empty?
diff --git a/lib/gitlab/sidekiq_middleware/correlation_injector.rb b/lib/gitlab/sidekiq_middleware/correlation_injector.rb
index b807b3a03ed..1539fd706ab 100644
--- a/lib/gitlab/sidekiq_middleware/correlation_injector.rb
+++ b/lib/gitlab/sidekiq_middleware/correlation_injector.rb
@@ -4,8 +4,8 @@ module Gitlab
module SidekiqMiddleware
class CorrelationInjector
def call(worker_class, job, queue, redis_pool)
- job[Gitlab::CorrelationId::LOG_KEY] ||=
- Gitlab::CorrelationId.current_or_new_id
+ job[Labkit::Correlation::CorrelationId::LOG_KEY] ||=
+ Labkit::Correlation::CorrelationId.current_or_new_id
yield
end
diff --git a/lib/gitlab/sidekiq_middleware/correlation_logger.rb b/lib/gitlab/sidekiq_middleware/correlation_logger.rb
index cb8ff4a6284..cffc4483573 100644
--- a/lib/gitlab/sidekiq_middleware/correlation_logger.rb
+++ b/lib/gitlab/sidekiq_middleware/correlation_logger.rb
@@ -4,9 +4,9 @@ module Gitlab
module SidekiqMiddleware
class CorrelationLogger
def call(worker, job, queue)
- correlation_id = job[Gitlab::CorrelationId::LOG_KEY]
+ correlation_id = job[Labkit::Correlation::CorrelationId::LOG_KEY]
- Gitlab::CorrelationId.use_id(correlation_id) do
+ Labkit::Correlation::CorrelationId.use_id(correlation_id) do
yield
end
end
diff --git a/lib/gitlab/slash_commands/result.rb b/lib/gitlab/slash_commands/result.rb
index 607c9c8dec1..a66a2e0726b 100644
--- a/lib/gitlab/slash_commands/result.rb
+++ b/lib/gitlab/slash_commands/result.rb
@@ -1,4 +1,3 @@
-# rubocop:disable Naming/FileName
# frozen_string_literal: true
module Gitlab
diff --git a/lib/gitlab/sql/pattern.rb b/lib/gitlab/sql/pattern.rb
index b698391c8bd..fd108b4c124 100644
--- a/lib/gitlab/sql/pattern.rb
+++ b/lib/gitlab/sql/pattern.rb
@@ -6,7 +6,7 @@ module Gitlab
extend ActiveSupport::Concern
MIN_CHARS_FOR_PARTIAL_MATCHING = 3
- REGEX_QUOTED_WORD = /(?<=\A| )"[^"]+"(?= |\z)/
+ REGEX_QUOTED_WORD = /(?<=\A| )"[^"]+"(?= |\z)/.freeze
class_methods do
def fuzzy_search(query, columns)
diff --git a/lib/gitlab/tracing/common.rb b/lib/gitlab/tracing/common.rb
deleted file mode 100644
index 3a08ede8138..00000000000
--- a/lib/gitlab/tracing/common.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-# frozen_string_literal: true
-
-require 'opentracing'
-
-module Gitlab
- module Tracing
- module Common
- def tracer
- OpenTracing.global_tracer
- end
-
- # Convience method for running a block with a span
- def in_tracing_span(operation_name:, tags:, child_of: nil)
- scope = tracer.start_active_span(
- operation_name,
- child_of: child_of,
- tags: tags
- )
- span = scope.span
-
- # Add correlation details to the span if we have them
- correlation_id = Gitlab::CorrelationId.current_id
- if correlation_id
- span.set_tag('correlation_id', correlation_id)
- end
-
- begin
- yield span
- rescue => e
- log_exception_on_span(span, e)
- raise e
- ensure
- scope.close
- end
- end
-
- def postnotify_span(operation_name, start_time, end_time, tags: nil, child_of: nil, exception: nil)
- span = OpenTracing.start_span(operation_name, start_time: start_time, tags: tags, child_of: child_of)
-
- log_exception_on_span(span, exception) if exception
-
- span.finish(end_time: end_time)
- end
-
- def log_exception_on_span(span, exception)
- span.set_tag('error', true)
- span.log_kv(kv_tags_for_exception(exception))
- end
-
- def kv_tags_for_exception(exception)
- case exception
- when Exception
- {
- 'event': 'error',
- 'error.kind': exception.class.to_s,
- 'message': Gitlab::UrlSanitizer.sanitize(exception.message),
- 'stack': exception.backtrace&.join("\n")
- }
- else
- {
- 'event': 'error',
- 'error.kind': exception.class.to_s,
- 'error.object': Gitlab::UrlSanitizer.sanitize(exception.to_s)
- }
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/tracing/factory.rb b/lib/gitlab/tracing/factory.rb
deleted file mode 100644
index fc714164353..00000000000
--- a/lib/gitlab/tracing/factory.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-require "cgi"
-
-module Gitlab
- module Tracing
- class Factory
- OPENTRACING_SCHEME = "opentracing"
-
- def self.create_tracer(service_name, connection_string)
- return unless connection_string.present?
-
- begin
- opentracing_details = parse_connection_string(connection_string)
- driver_name = opentracing_details[:driver_name]
-
- case driver_name
- when "jaeger"
- JaegerFactory.create_tracer(service_name, opentracing_details[:options])
- else
- raise "Unknown driver: #{driver_name}"
- end
- rescue => e
- # Can't create the tracer? Warn and continue sans tracer
- warn "Unable to instantiate tracer: #{e}"
- nil
- end
- end
-
- def self.parse_connection_string(connection_string)
- parsed = URI.parse(connection_string)
-
- unless valid_uri?(parsed)
- raise "Invalid tracing connection string"
- end
-
- {
- driver_name: parsed.host,
- options: parse_query(parsed.query)
- }
- end
- private_class_method :parse_connection_string
-
- def self.parse_query(query)
- return {} unless query
-
- CGI.parse(query).symbolize_keys.transform_values(&:first)
- end
- private_class_method :parse_query
-
- def self.valid_uri?(uri)
- return false unless uri
-
- uri.scheme == OPENTRACING_SCHEME &&
- uri.host.to_s =~ /^[a-z0-9_]+$/ &&
- uri.path.empty?
- end
- private_class_method :valid_uri?
- end
- end
-end
diff --git a/lib/gitlab/tracing/grpc_interceptor.rb b/lib/gitlab/tracing/grpc_interceptor.rb
deleted file mode 100644
index 6c2aab73125..00000000000
--- a/lib/gitlab/tracing/grpc_interceptor.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: true
-
-require 'opentracing'
-require 'grpc'
-
-module Gitlab
- module Tracing
- class GRPCInterceptor < GRPC::ClientInterceptor
- include Common
- include Singleton
-
- def request_response(request:, call:, method:, metadata:)
- wrap_with_tracing(method, 'unary', metadata) do
- yield
- end
- end
-
- def client_streamer(requests:, call:, method:, metadata:)
- wrap_with_tracing(method, 'client_stream', metadata) do
- yield
- end
- end
-
- def server_streamer(request:, call:, method:, metadata:)
- wrap_with_tracing(method, 'server_stream', metadata) do
- yield
- end
- end
-
- def bidi_streamer(requests:, call:, method:, metadata:)
- wrap_with_tracing(method, 'bidi_stream', metadata) do
- yield
- end
- end
-
- private
-
- def wrap_with_tracing(method, grpc_type, metadata)
- tags = {
- 'component' => 'grpc',
- 'span.kind' => 'client',
- 'grpc.method' => method,
- 'grpc.type' => grpc_type
- }
-
- in_tracing_span(operation_name: "grpc:#{method}", tags: tags) do |span|
- OpenTracing.inject(span.context, OpenTracing::FORMAT_TEXT_MAP, metadata)
-
- yield
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/tracing/jaeger_factory.rb b/lib/gitlab/tracing/jaeger_factory.rb
deleted file mode 100644
index 93520d5667b..00000000000
--- a/lib/gitlab/tracing/jaeger_factory.rb
+++ /dev/null
@@ -1,97 +0,0 @@
-# frozen_string_literal: true
-
-require 'jaeger/client'
-
-module Gitlab
- module Tracing
- class JaegerFactory
- # When the probabilistic sampler is used, by default 0.1% of requests will be traced
- DEFAULT_PROBABILISTIC_RATE = 0.001
-
- # The default port for the Jaeger agent UDP listener
- DEFAULT_UDP_PORT = 6831
-
- # Reduce this from default of 10 seconds as the Ruby jaeger
- # client doesn't have overflow control, leading to very large
- # messages which fail to send over UDP (max packet = 64k)
- # Flush more often, with smaller packets
- FLUSH_INTERVAL = 5
-
- def self.create_tracer(service_name, options)
- kwargs = {
- service_name: service_name,
- sampler: get_sampler(options[:sampler], options[:sampler_param]),
- reporter: get_reporter(service_name, options[:http_endpoint], options[:udp_endpoint])
- }.compact
-
- extra_params = options.except(:sampler, :sampler_param, :http_endpoint, :udp_endpoint, :strict_parsing, :debug) # rubocop: disable CodeReuse/ActiveRecord
- if extra_params.present?
- message = "jaeger tracer: invalid option: #{extra_params.keys.join(", ")}"
-
- if options[:strict_parsing]
- raise message
- else
- warn message
- end
- end
-
- Jaeger::Client.build(kwargs)
- end
-
- def self.get_sampler(sampler_type, sampler_param)
- case sampler_type
- when "probabilistic"
- sampler_rate = sampler_param ? sampler_param.to_f : DEFAULT_PROBABILISTIC_RATE
- Jaeger::Samplers::Probabilistic.new(rate: sampler_rate)
- when "const"
- const_value = sampler_param == "1"
- Jaeger::Samplers::Const.new(const_value)
- else
- nil
- end
- end
- private_class_method :get_sampler
-
- def self.get_reporter(service_name, http_endpoint, udp_endpoint)
- encoder = Jaeger::Encoders::ThriftEncoder.new(service_name: service_name)
-
- if http_endpoint.present?
- sender = get_http_sender(encoder, http_endpoint)
- elsif udp_endpoint.present?
- sender = get_udp_sender(encoder, udp_endpoint)
- else
- return
- end
-
- Jaeger::Reporters::RemoteReporter.new(
- sender: sender,
- flush_interval: FLUSH_INTERVAL
- )
- end
- private_class_method :get_reporter
-
- def self.get_http_sender(encoder, address)
- Jaeger::HttpSender.new(
- url: address,
- encoder: encoder,
- logger: Logger.new(STDOUT)
- )
- end
- private_class_method :get_http_sender
-
- def self.get_udp_sender(encoder, address)
- pair = address.split(":", 2)
- host = pair[0]
- port = pair[1] ? pair[1].to_i : DEFAULT_UDP_PORT
-
- Jaeger::UdpSender.new(
- host: host,
- port: port,
- encoder: encoder,
- logger: Logger.new(STDOUT)
- )
- end
- private_class_method :get_udp_sender
- end
- end
-end
diff --git a/lib/gitlab/tracing/rack_middleware.rb b/lib/gitlab/tracing/rack_middleware.rb
deleted file mode 100644
index e6a31293f7b..00000000000
--- a/lib/gitlab/tracing/rack_middleware.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require 'opentracing'
-
-module Gitlab
- module Tracing
- class RackMiddleware
- include Common
-
- REQUEST_METHOD = 'REQUEST_METHOD'
-
- def initialize(app)
- @app = app
- end
-
- def call(env)
- method = env[REQUEST_METHOD]
-
- context = tracer.extract(OpenTracing::FORMAT_RACK, env)
- tags = {
- 'component' => 'rack',
- 'span.kind' => 'server',
- 'http.method' => method,
- 'http.url' => self.class.build_sanitized_url_from_env(env)
- }
-
- in_tracing_span(operation_name: "http:#{method}", child_of: context, tags: tags) do |span|
- @app.call(env).tap do |status_code, _headers, _body|
- span.set_tag('http.status_code', status_code)
- end
- end
- end
-
- # Generate a sanitized (safe) request URL from the rack environment
- def self.build_sanitized_url_from_env(env)
- request = ActionDispatch::Request.new(env)
-
- original_url = request.original_url
- uri = URI.parse(original_url)
- uri.query = request.filtered_parameters.to_query if uri.query.present?
-
- uri.to_s
- end
- end
- end
-end
diff --git a/lib/gitlab/tracing/rails/action_view_subscriber.rb b/lib/gitlab/tracing/rails/action_view_subscriber.rb
deleted file mode 100644
index 88816e1fb32..00000000000
--- a/lib/gitlab/tracing/rails/action_view_subscriber.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Tracing
- module Rails
- class ActionViewSubscriber
- include RailsCommon
-
- COMPONENT_TAG = 'ActionView'
- RENDER_TEMPLATE_NOTIFICATION_TOPIC = 'render_template.action_view'
- RENDER_COLLECTION_NOTIFICATION_TOPIC = 'render_collection.action_view'
- RENDER_PARTIAL_NOTIFICATION_TOPIC = 'render_partial.action_view'
-
- # Instruments Rails ActionView events for opentracing.
- # Returns a lambda, which, when called will unsubscribe from the notifications
- def self.instrument
- subscriber = new
-
- subscriptions = [
- ActiveSupport::Notifications.subscribe(RENDER_TEMPLATE_NOTIFICATION_TOPIC) do |_, start, finish, _, payload|
- subscriber.notify_render_template(start, finish, payload)
- end,
- ActiveSupport::Notifications.subscribe(RENDER_COLLECTION_NOTIFICATION_TOPIC) do |_, start, finish, _, payload|
- subscriber.notify_render_collection(start, finish, payload)
- end,
- ActiveSupport::Notifications.subscribe(RENDER_PARTIAL_NOTIFICATION_TOPIC) do |_, start, finish, _, payload|
- subscriber.notify_render_partial(start, finish, payload)
- end
- ]
-
- create_unsubscriber subscriptions
- end
-
- # For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html
- def notify_render_template(start, finish, payload)
- generate_span_for_notification("render_template", start, finish, payload, tags_for_render_template(payload))
- end
-
- def notify_render_collection(start, finish, payload)
- generate_span_for_notification("render_collection", start, finish, payload, tags_for_render_collection(payload))
- end
-
- def notify_render_partial(start, finish, payload)
- generate_span_for_notification("render_partial", start, finish, payload, tags_for_render_partial(payload))
- end
-
- private
-
- def tags_for_render_template(payload)
- {
- 'component' => COMPONENT_TAG,
- 'template.id' => payload[:identifier],
- 'template.layout' => payload[:layout]
- }
- end
-
- def tags_for_render_collection(payload)
- {
- 'component' => COMPONENT_TAG,
- 'template.id' => payload[:identifier],
- 'template.count' => payload[:count] || 0,
- 'template.cache.hits' => payload[:cache_hits] || 0
- }
- end
-
- def tags_for_render_partial(payload)
- {
- 'component' => COMPONENT_TAG,
- 'template.id' => payload[:identifier]
- }
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/tracing/rails/active_record_subscriber.rb b/lib/gitlab/tracing/rails/active_record_subscriber.rb
deleted file mode 100644
index 32f5658e57e..00000000000
--- a/lib/gitlab/tracing/rails/active_record_subscriber.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Tracing
- module Rails
- class ActiveRecordSubscriber
- include RailsCommon
-
- ACTIVE_RECORD_NOTIFICATION_TOPIC = 'sql.active_record'
- OPERATION_NAME_PREFIX = 'active_record:'
- DEFAULT_OPERATION_NAME = 'sqlquery'
-
- # Instruments Rails ActiveRecord events for opentracing.
- # Returns a lambda, which, when called will unsubscribe from the notifications
- def self.instrument
- subscriber = new
-
- subscription = ActiveSupport::Notifications.subscribe(ACTIVE_RECORD_NOTIFICATION_TOPIC) do |_, start, finish, _, payload|
- subscriber.notify(start, finish, payload)
- end
-
- create_unsubscriber [subscription]
- end
-
- # For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html
- def notify(start, finish, payload)
- generate_span_for_notification(notification_name(payload), start, finish, payload, tags_for_notification(payload))
- end
-
- private
-
- def notification_name(payload)
- OPERATION_NAME_PREFIX + (payload[:name].presence || DEFAULT_OPERATION_NAME)
- end
-
- def tags_for_notification(payload)
- {
- 'component' => 'ActiveRecord',
- 'span.kind' => 'client',
- 'db.type' => 'sql',
- 'db.connection_id' => payload[:connection_id],
- 'db.cached' => payload[:cached] || false,
- 'db.statement' => payload[:sql]
- }
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/tracing/rails/rails_common.rb b/lib/gitlab/tracing/rails/rails_common.rb
deleted file mode 100644
index 88e914f62f8..00000000000
--- a/lib/gitlab/tracing/rails/rails_common.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Tracing
- module Rails
- module RailsCommon
- extend ActiveSupport::Concern
- include Gitlab::Tracing::Common
-
- class_methods do
- def create_unsubscriber(subscriptions)
- -> { subscriptions.each { |subscriber| ActiveSupport::Notifications.unsubscribe(subscriber) } }
- end
- end
-
- def generate_span_for_notification(operation_name, start, finish, payload, tags)
- exception = payload[:exception]
-
- postnotify_span(operation_name, start, finish, tags: tags, exception: exception)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/tracing/sidekiq/client_middleware.rb b/lib/gitlab/tracing/sidekiq/client_middleware.rb
deleted file mode 100644
index 2b71c1ea21e..00000000000
--- a/lib/gitlab/tracing/sidekiq/client_middleware.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-require 'opentracing'
-
-module Gitlab
- module Tracing
- module Sidekiq
- class ClientMiddleware
- include SidekiqCommon
-
- SPAN_KIND = 'client'
-
- def call(worker_class, job, queue, redis_pool)
- in_tracing_span(
- operation_name: "sidekiq:#{job['class']}",
- tags: tags_from_job(job, SPAN_KIND)) do |span|
- # Inject the details directly into the job
- tracer.inject(span.context, OpenTracing::FORMAT_TEXT_MAP, job)
-
- yield
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/tracing/sidekiq/server_middleware.rb b/lib/gitlab/tracing/sidekiq/server_middleware.rb
deleted file mode 100644
index 5b43c4310e6..00000000000
--- a/lib/gitlab/tracing/sidekiq/server_middleware.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-require 'opentracing'
-
-module Gitlab
- module Tracing
- module Sidekiq
- class ServerMiddleware
- include SidekiqCommon
-
- SPAN_KIND = 'server'
-
- def call(worker, job, queue)
- context = tracer.extract(OpenTracing::FORMAT_TEXT_MAP, job)
-
- in_tracing_span(
- operation_name: "sidekiq:#{job['class']}",
- child_of: context,
- tags: tags_from_job(job, SPAN_KIND)) do |span|
- yield
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/tracing/sidekiq/sidekiq_common.rb b/lib/gitlab/tracing/sidekiq/sidekiq_common.rb
deleted file mode 100644
index a911a29d773..00000000000
--- a/lib/gitlab/tracing/sidekiq/sidekiq_common.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Tracing
- module Sidekiq
- module SidekiqCommon
- include Gitlab::Tracing::Common
-
- def tags_from_job(job, kind)
- {
- 'component' => 'sidekiq',
- 'span.kind' => kind,
- 'sidekiq.queue' => job['queue'],
- 'sidekiq.jid' => job['jid'],
- 'sidekiq.retry' => job['retry'].to_s,
- 'sidekiq.args' => job['args']&.join(", ")
- }
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/url_blocker.rb b/lib/gitlab/url_blocker.rb
index 641ba70ef83..9a8df719827 100644
--- a/lib/gitlab/url_blocker.rb
+++ b/lib/gitlab/url_blocker.rb
@@ -8,38 +8,68 @@ module Gitlab
BlockedUrlError = Class.new(StandardError)
class << self
- def validate!(url, ports: [], schemes: [], allow_localhost: false, allow_local_network: true, ascii_only: false, enforce_user: false, enforce_sanitization: false)
- return true if url.nil?
+ # Validates the given url according to the constraints specified by arguments.
+ #
+ # ports - Raises error if the given URL port does is not between given ports.
+ # allow_localhost - Raises error if URL resolves to a localhost IP address and argument is true.
+ # allow_local_network - Raises error if URL resolves to a link-local address and argument is true.
+ # ascii_only - Raises error if URL has unicode characters and argument is true.
+ # enforce_user - Raises error if URL user doesn't start with alphanumeric characters and argument is true.
+ # enforce_sanitization - Raises error if URL includes any HTML/CSS/JS tags and argument is true.
+ #
+ # Returns an array with [<uri>, <original-hostname>].
+ # rubocop:disable Metrics/CyclomaticComplexity
+ # rubocop:disable Metrics/ParameterLists
+ def validate!(
+ url,
+ ports: [],
+ schemes: [],
+ allow_localhost: false,
+ allow_local_network: true,
+ ascii_only: false,
+ enforce_user: false,
+ enforce_sanitization: false,
+ dns_rebind_protection: true)
+ # rubocop:enable Metrics/CyclomaticComplexity
+ # rubocop:enable Metrics/ParameterLists
+
+ return [nil, nil] if url.nil?
# Param url can be a string, URI or Addressable::URI
uri = parse_url(url)
validate_html_tags!(uri) if enforce_sanitization
- # Allow imports from the GitLab instance itself but only from the configured ports
- return true if internal?(uri)
-
+ hostname = uri.hostname
port = get_port(uri)
- validate_scheme!(uri.scheme, schemes)
- validate_port!(port, ports) if ports.any?
- validate_user!(uri.user) if enforce_user
- validate_hostname!(uri.hostname)
- validate_unicode_restriction!(uri) if ascii_only
+
+ unless internal?(uri)
+ validate_scheme!(uri.scheme, schemes)
+ validate_port!(port, ports) if ports.any?
+ validate_user!(uri.user) if enforce_user
+ validate_hostname!(hostname)
+ validate_unicode_restriction!(uri) if ascii_only
+ end
begin
- addrs_info = Addrinfo.getaddrinfo(uri.hostname, port, nil, :STREAM).map do |addr|
+ addrs_info = Addrinfo.getaddrinfo(hostname, port, nil, :STREAM).map do |addr|
addr.ipv6_v4mapped? ? addr.ipv6_to_ipv4 : addr
end
rescue SocketError
- return true
+ return [uri, nil]
end
+ protected_uri_with_hostname = enforce_uri_hostname(addrs_info, uri, hostname, dns_rebind_protection)
+
+ # Allow url from the GitLab instance itself but only for the configured hostname and ports
+ return protected_uri_with_hostname if internal?(uri)
+
validate_localhost!(addrs_info) unless allow_localhost
validate_loopback!(addrs_info) unless allow_localhost
validate_local_network!(addrs_info) unless allow_local_network
validate_link_local!(addrs_info) unless allow_local_network
- true
+ protected_uri_with_hostname
end
def blocked_url?(*args)
@@ -52,6 +82,25 @@ module Gitlab
private
+ # Returns the given URI with IP address as hostname and the original hostname respectively
+ # in an Array.
+ #
+ # It checks whether the resolved IP address matches with the hostname. If not, it changes
+ # the hostname to the resolved IP address.
+ #
+ # The original hostname is used to validate the SSL, given in that scenario
+ # we'll be making the request to the IP address, instead of using the hostname.
+ def enforce_uri_hostname(addrs_info, uri, hostname, dns_rebind_protection)
+ address = addrs_info.first
+ ip_address = address&.ip_address
+
+ return [uri, nil] unless dns_rebind_protection && ip_address && ip_address != hostname
+
+ uri = uri.dup
+ uri.hostname = ip_address
+ [uri, hostname]
+ end
+
def get_port(uri)
uri.port || uri.default_port
end
diff --git a/lib/gitlab/url_builder.rb b/lib/gitlab/url_builder.rb
index f86d599e4cb..42cf1ec1f0e 100644
--- a/lib/gitlab/url_builder.rb
+++ b/lib/gitlab/url_builder.rb
@@ -30,6 +30,10 @@ module Gitlab
snippet_url(object)
when Milestone
milestone_url(object)
+ when ::Ci::Build
+ project_job_url(object.project, object)
+ when User
+ user_url(object)
else
raise NotImplementedError.new("No URL builder defined for #{object.class}")
end
diff --git a/lib/gitlab/url_sanitizer.rb b/lib/gitlab/url_sanitizer.rb
index 880712de5fe..215454fe63c 100644
--- a/lib/gitlab/url_sanitizer.rb
+++ b/lib/gitlab/url_sanitizer.rb
@@ -47,6 +47,10 @@ module Gitlab
@credentials ||= { user: @url.user.presence, password: @url.password.presence }
end
+ def user
+ credentials[:user]
+ end
+
def full_url
@full_url ||= generate_full_url.to_s
end
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index 08156d7ffa6..9aa2e972adf 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -26,7 +26,7 @@ module Gitlab
uuid: Gitlab::CurrentSettings.uuid,
hostname: Gitlab.config.gitlab.host,
version: Gitlab::VERSION,
- installation_type: Gitlab::INSTALLATION_TYPE,
+ installation_type: installation_type,
active_user_count: count(User.active),
recorded_at: Time.now,
edition: 'CE'
@@ -81,6 +81,7 @@ module Gitlab
milestone_lists: count(List.milestone),
milestones: count(Milestone),
pages_domains: count(PagesDomain),
+ pool_repositories: count(PoolRepository),
projects: count(Project),
projects_imported_from_github: count(Project.where(import_type: 'github')),
projects_with_repositories_enabled: count(ProjectFeature.where('repository_access_level > ?', ProjectFeature::DISABLED)),
@@ -190,6 +191,14 @@ module Gitlab
result[key] = approx_counts[model] || -1
end
end
+
+ def installation_type
+ if Rails.env.production?
+ Gitlab::INSTALLATION_TYPE
+ else
+ "gitlab-development-kit"
+ end
+ end
end
end
end
diff --git a/lib/gitlab/user_extractor.rb b/lib/gitlab/user_extractor.rb
index f0557f6ad68..ede60c9ab1d 100644
--- a/lib/gitlab/user_extractor.rb
+++ b/lib/gitlab/user_extractor.rb
@@ -7,7 +7,7 @@ module Gitlab
class UserExtractor
# Not using `Devise.email_regexp` to filter out any chars that an email
# does not end with and not pinning the email to a start of end of a string.
- EMAIL_REGEXP = /(?<email>([^@\s]+@[^@\s]+(?<!\W)))/
+ EMAIL_REGEXP = /(?<email>([^@\s]+@[^@\s]+(?<!\W)))/.freeze
USERNAME_REGEXP = User.reference_pattern
def initialize(text)
diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb
index 0c2acac3d1e..46a7b5b982a 100644
--- a/lib/gitlab/workhorse.rb
+++ b/lib/gitlab/workhorse.rb
@@ -63,16 +63,34 @@ module Gitlab
]
end
- def send_git_archive(repository, ref:, format:, append_sha:)
+ def send_git_archive(repository, ref:, format:, append_sha:, path: nil)
+ path_enabled = Feature.enabled?(:git_archive_path, default_enabled: true)
+ path = nil unless path_enabled
+
format ||= 'tar.gz'
format = format.downcase
- params = repository.archive_metadata(ref, Gitlab.config.gitlab.repository_downloads_path, format, append_sha: append_sha)
- raise "Repository or ref not found" if params.empty?
- params['GitalyServer'] = gitaly_server_hash(repository)
+ metadata = repository.archive_metadata(
+ ref,
+ Gitlab.config.gitlab.repository_downloads_path,
+ format,
+ append_sha: append_sha,
+ path: path
+ )
- # If present DisableCache must be a Boolean. Otherwise workhorse ignores it.
+ raise "Repository or ref not found" if metadata.empty?
+
+ params =
+ if path_enabled
+ send_git_archive_params(repository, metadata, path, archive_format(format))
+ else
+ metadata
+ end
+
+ # If present, DisableCache must be a Boolean. Otherwise
+ # workhorse ignores it.
params['DisableCache'] = true if git_archive_cache_disabled?
+ params['GitalyServer'] = gitaly_server_hash(repository)
[
SEND_DATA_HEADER,
@@ -216,10 +234,19 @@ module Gitlab
protected
+ # This is the outermost encoding of a senddata: header. It is safe for
+ # inclusion in HTTP response headers
def encode(hash)
Base64.urlsafe_encode64(JSON.dump(hash))
end
+ # This is for encoding individual fields inside the senddata JSON that
+ # contain binary data. In workhorse, the corresponding struct field should
+ # be type []byte
+ def encode_binary(binary)
+ Base64.encode64(binary)
+ end
+
def gitaly_server_hash(repository)
{
address: Gitlab::GitalyClient.address(repository.project.repository_storage),
@@ -238,6 +265,34 @@ module Gitlab
def git_archive_cache_disabled?
ENV['WORKHORSE_ARCHIVE_CACHE_DISABLED'].present? || Feature.enabled?(:workhorse_archive_cache_disabled)
end
+
+ def archive_format(format)
+ case format
+ when "tar.bz2", "tbz", "tbz2", "tb2", "bz2"
+ Gitaly::GetArchiveRequest::Format::TAR_BZ2
+ when "tar"
+ Gitaly::GetArchiveRequest::Format::TAR
+ when "zip"
+ Gitaly::GetArchiveRequest::Format::ZIP
+ else
+ Gitaly::GetArchiveRequest::Format::TAR_GZ
+ end
+ end
+
+ def send_git_archive_params(repository, metadata, path, format)
+ {
+ 'ArchivePath' => metadata['ArchivePath'],
+ 'GetArchiveRequest' => encode_binary(
+ Gitaly::GetArchiveRequest.new(
+ repository: repository.gitaly_repository,
+ commit_id: metadata['CommitId'],
+ prefix: metadata['ArchivePrefix'],
+ format: format,
+ path: path.presence || ""
+ ).to_proto
+ )
+ }
+ end
end
end
end
diff --git a/lib/haml_lint/inline_javascript.rb b/lib/haml_lint/inline_javascript.rb
deleted file mode 100644
index 2e98227a05e..00000000000
--- a/lib/haml_lint/inline_javascript.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# rubocop:disable Naming/FileName
-# frozen_string_literal: true
-
-unless Rails.env.production?
- require_dependency 'haml_lint/haml_visitor'
- require_dependency 'haml_lint/linter'
- require_dependency 'haml_lint/linter_registry'
-
- module HamlLint
- class Linter::InlineJavaScript < Linter
- include LinterRegistry
-
- def visit_filter(node)
- return unless node.filter_type == 'javascript'
-
- record_lint(node, 'Inline JavaScript is discouraged (https://docs.gitlab.com/ee/development/gotchas.html#do-not-use-inline-javascript-in-views)')
- end
-
- def visit_tag(node)
- return unless node.tag_name == 'script'
-
- record_lint(node, 'Inline JavaScript is discouraged (https://docs.gitlab.com/ee/development/gotchas.html#do-not-use-inline-javascript-in-views)')
- end
- end
- end
-end
diff --git a/lib/mattermost/session.rb b/lib/mattermost/session.rb
index e2083848a8d..722e3e04d1c 100644
--- a/lib/mattermost/session.rb
+++ b/lib/mattermost/session.rb
@@ -122,7 +122,7 @@ module Mattermost
@oauth_uri = nil
- response = get('/oauth/gitlab/login', follow_redirects: false, format: 'text/html')
+ response = get('/oauth/gitlab/login', follow_redirects: false)
return unless (300...400) === response.code
redirect_uri = response.headers['location']
diff --git a/lib/peek/views/tracing.rb b/lib/peek/views/tracing.rb
index 0de32a8fdda..94726a498ea 100644
--- a/lib/peek/views/tracing.rb
+++ b/lib/peek/views/tracing.rb
@@ -4,9 +4,9 @@ module Peek
module Views
class Tracing < View
def results
- {
- tracing_url: Gitlab::Tracing.tracing_url
- }
+ tracing_url = Labkit::Tracing.tracing_url(Gitlab.process_name)
+
+ { tracing_url: tracing_url }
end
end
end
diff --git a/lib/quality/kubernetes_client.rb b/lib/quality/kubernetes_client.rb
index 2ff9e811425..190b48ba7cb 100644
--- a/lib/quality/kubernetes_client.rb
+++ b/lib/quality/kubernetes_client.rb
@@ -18,6 +18,8 @@ module Quality
'delete',
'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa',
'--now',
+ '--ignore-not-found',
+ '--include-uninitialized',
%(-l release="#{release_name}")
]
diff --git a/lib/quality/seeders/issues.rb b/lib/quality/seeders/issues.rb
new file mode 100644
index 00000000000..4c8cb6e97cc
--- /dev/null
+++ b/lib/quality/seeders/issues.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+# rubocop:disable CodeReuse/ActiveRecord
+module Quality
+ module Seeders
+ class Issues
+ DEFAULT_BACKFILL_WEEKS = 52
+ DEFAULT_AVERAGE_ISSUES_PER_WEEK = 10
+
+ attr_reader :project, :user
+
+ def initialize(project:)
+ @project = project
+ end
+
+ def seed(backfill_weeks: DEFAULT_BACKFILL_WEEKS, average_issues_per_week: DEFAULT_AVERAGE_ISSUES_PER_WEEK)
+ created_at = backfill_weeks.to_i.weeks.ago
+ team = project.team.users
+ created_issues_count = 0
+
+ loop do
+ rand(average_issues_per_week * 2).times do
+ params = {
+ title: FFaker::Lorem.sentence(6),
+ description: FFaker::Lorem.sentence,
+ created_at: created_at + rand(6).days,
+ state: %w[opened closed].sample,
+ milestone: project.milestones.sample,
+ assignee_ids: Array(team.pluck(:id).sample(3)),
+ labels: labels.join(',')
+ }
+ issue = ::Issues::CreateService.new(project, team.sample, params).execute
+
+ if issue.persisted?
+ created_issues_count += 1
+ print '.' # rubocop:disable Rails/Output
+ end
+ end
+
+ created_at += 1.week
+
+ break if created_at > Time.now
+ end
+
+ created_issues_count
+ end
+
+ private
+
+ def labels
+ @labels_pool ||= project.labels.limit(rand(3)).pluck(:title).tap do |labels_array|
+ labels_array.concat(project.group.labels.limit(rand(3)).pluck(:title)) if project.group
+ end
+ end
+ end
+ end
+end
+# rubocop:enable CodeReuse/ActiveRecord
diff --git a/lib/quality/test_level.rb b/lib/quality/test_level.rb
new file mode 100644
index 00000000000..24d8eac200c
--- /dev/null
+++ b/lib/quality/test_level.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module Quality
+ class TestLevel
+ UnknownTestLevelError = Class.new(StandardError)
+
+ TEST_LEVEL_FOLDERS = {
+ unit: %w[
+ bin
+ config
+ db
+ dependencies
+ factories
+ finders
+ frontend
+ graphql
+ helpers
+ initializers
+ javascripts
+ lib
+ migrations
+ models
+ policies
+ presenters
+ rack_servers
+ routing
+ rubocop
+ serializers
+ services
+ sidekiq
+ tasks
+ uploaders
+ validators
+ views
+ workers
+ elastic_integration
+ ],
+ integration: %w[
+ controllers
+ mailers
+ requests
+ ],
+ system: ['features']
+ }.freeze
+
+ attr_reader :prefix
+
+ def initialize(prefix = nil)
+ @prefix = prefix
+ @patterns = {}
+ @regexps = {}
+ end
+
+ def pattern(level)
+ @patterns[level] ||= "#{prefix}spec/{#{TEST_LEVEL_FOLDERS.fetch(level).join(',')}}{,/**/}*_spec.rb".freeze
+ end
+
+ def regexp(level)
+ @regexps[level] ||= Regexp.new("#{prefix}spec/(#{TEST_LEVEL_FOLDERS.fetch(level).join('|')})").freeze
+ end
+
+ def level_for(file_path)
+ case file_path
+ when regexp(:unit)
+ :unit
+ when regexp(:integration)
+ :integration
+ when regexp(:system)
+ :system
+ else
+ raise UnknownTestLevelError, "Test level for #{file_path} couldn't be set. Please rename the file properly or change the test level detection regexes in #{__FILE__}."
+ end
+ end
+ end
+end
diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab
index 2f2de083dc0..32df74f104a 100755
--- a/lib/support/init.d/gitlab
+++ b/lib/support/init.d/gitlab
@@ -1,8 +1,8 @@
#! /bin/sh
# GITLAB
-# Maintainer: @randx
-# Authors: rovanion.luckey@gmail.com, @randx
+# Maintainer: @dzaporozhets
+# Authors: rovanion.luckey@gmail.com, @dzaporozhets
### BEGIN INIT INFO
# Provides: gitlab
@@ -26,6 +26,7 @@
### Environment variables
RAILS_ENV="production"
+EXPERIMENTAL_PUMA=""
# Script variable names should be lower-case not to conflict with
# internal /bin/sh variables such as PATH, EDITOR or SHELL.
@@ -75,7 +76,7 @@ check_pids(){
echo "Could not create the path $pid_path needed to store the pids."
exit 1
fi
- # If there exists a file which should hold the value of the Unicorn pid: read it.
+ # If there exists a file which should hold the value of the web server pid: read it.
if [ -f "$web_server_pid_path" ]; then
wpid=$(cat "$web_server_pid_path")
else
@@ -198,7 +199,7 @@ check_stale_pids(){
# If there is a pid it is something else than 0, the service is running if
# *_status is == 0.
if [ "$wpid" != "0" ] && [ "$web_status" != "0" ]; then
- echo "Removing stale Unicorn web server pid. This is most likely caused by the web server crashing the last time it ran."
+ echo "Removing stale web server pid. This is most likely caused by the web server crashing the last time it ran."
if ! rm "$web_server_pid_path"; then
echo "Unable to remove stale pid, exiting."
exit 1
@@ -250,12 +251,12 @@ exit_if_not_running(){
fi
}
-## Starts Unicorn and Sidekiq if they're not running.
+## Starts web server and Sidekiq if they're not running.
start_gitlab() {
check_stale_pids
if [ "$web_status" != "0" ]; then
- echo "Starting GitLab Unicorn"
+ echo "Starting GitLab web server"
fi
if [ "$sidekiq_status" != "0" ]; then
echo "Starting GitLab Sidekiq"
@@ -275,12 +276,12 @@ start_gitlab() {
# Then check if the service is running. If it is: don't start again.
if [ "$web_status" = "0" ]; then
- echo "The Unicorn web server already running with pid $wpid, not restarting."
+ echo "The web server already running with pid $wpid, not restarting."
else
# Remove old socket if it exists
rm -f "$rails_socket" 2>/dev/null
# Start the web server
- RAILS_ENV=$RAILS_ENV bin/web start
+ RAILS_ENV=$RAILS_ENV EXPERIMENTAL_PUMA=$EXPERIMENTAL_PUMA bin/web start
fi
# If sidekiq is already running, don't start it again.
@@ -336,13 +337,13 @@ start_gitlab() {
print_status
}
-## Asks Unicorn, Sidekiq and MailRoom if they would be so kind as to stop, if not kills them.
+## Asks web server, Sidekiq and MailRoom if they would be so kind as to stop, if not kills them.
stop_gitlab() {
exit_if_not_running
if [ "$web_status" = "0" ]; then
- echo "Shutting down GitLab Unicorn"
- RAILS_ENV=$RAILS_ENV bin/web stop
+ echo "Shutting down GitLab web server"
+ RAILS_ENV=$RAILS_ENV EXPERIMENTAL_PUMA=$EXPERIMENTAL_PUMA bin/web stop
fi
if [ "$sidekiq_status" = "0" ]; then
echo "Shutting down GitLab Sidekiq"
@@ -398,9 +399,9 @@ print_status() {
return
fi
if [ "$web_status" = "0" ]; then
- echo "The GitLab Unicorn web server with pid $wpid is running."
+ echo "The GitLab web server with pid $wpid is running."
else
- printf "The GitLab Unicorn web server is \033[31mnot running\033[0m.\n"
+ printf "The GitLab web server is \033[31mnot running\033[0m.\n"
fi
if [ "$sidekiq_status" = "0" ]; then
echo "The GitLab Sidekiq job dispatcher with pid $spid is running."
@@ -438,15 +439,15 @@ print_status() {
fi
}
-## Tells unicorn to reload its config and Sidekiq to restart
+## Tells web server to reload its config and Sidekiq to restart
reload_gitlab(){
exit_if_not_running
if [ "$wpid" = "0" ];then
- echo "The GitLab Unicorn Web server is not running thus its configuration can't be reloaded."
+ echo "The GitLab web server Web server is not running thus its configuration can't be reloaded."
exit 1
fi
- printf "Reloading GitLab Unicorn configuration... "
- RAILS_ENV=$RAILS_ENV bin/web reload
+ printf "Reloading GitLab web server configuration... "
+ RAILS_ENV=$RAILS_ENV EXPERIMENTAL_PUMA=$EXPERIMENTAL_PUMA bin/web reload
echo "Done."
echo "Restarting GitLab Sidekiq since it isn't capable of reloading its config..."
@@ -461,7 +462,7 @@ reload_gitlab(){
print_status
}
-## Restarts Sidekiq and Unicorn.
+## Restarts Sidekiq and web server.
restart_gitlab(){
check_status
if [ "$web_status" = "0" ] || [ "$sidekiq_status" = "0" ] || [ "$gitlab_workhorse" = "0" ] || { [ "$mail_room_enabled" = true ] && [ "$mail_room_status" = "0" ]; } || { [ "$gitlab_pages_enabled" = true ] && [ "$gitlab_pages_status" = "0" ]; } || { [ "$gitaly_enabled" = true ] && [ "$gitaly_status" = "0" ]; }; then
diff --git a/lib/support/init.d/gitlab.default.example b/lib/support/init.d/gitlab.default.example
index 295c79fccfc..ab41dba3017 100644
--- a/lib/support/init.d/gitlab.default.example
+++ b/lib/support/init.d/gitlab.default.example
@@ -5,6 +5,9 @@
# Normal values are "production", "test" and "development".
RAILS_ENV="production"
+# Uncomment the line below to enable Puma web server instead of Unicorn.
+# EXPERIMENTAL_PUMA=1
+
# app_user defines the user that GitLab is run as.
# The default is "git".
app_user="git"
diff --git a/lib/system_check/app/git_version_check.rb b/lib/system_check/app/git_version_check.rb
index 7c3e7759dd0..467711fb74e 100644
--- a/lib/system_check/app/git_version_check.rb
+++ b/lib/system_check/app/git_version_check.rb
@@ -7,7 +7,7 @@ module SystemCheck
set_check_pass -> { "yes (#{self.current_version})" }
def self.required_version
- @required_version ||= Gitlab::VersionInfo.parse('2.18.0')
+ @required_version ||= Gitlab::VersionInfo.parse('2.21.0')
end
def self.current_version
diff --git a/lib/system_check/app/ruby_version_check.rb b/lib/system_check/app/ruby_version_check.rb
index 60e07718338..53da62df176 100644
--- a/lib/system_check/app/ruby_version_check.rb
+++ b/lib/system_check/app/ruby_version_check.rb
@@ -7,7 +7,7 @@ module SystemCheck
set_check_pass -> { "yes (#{self.current_version})" }
def self.required_version
- @required_version ||= Gitlab::VersionInfo.new(2, 3, 5)
+ @required_version ||= Gitlab::VersionInfo.new(2, 5, 3)
end
def self.current_version
diff --git a/lib/system_check/base_check.rb b/lib/system_check/base_check.rb
index 46aad8aa885..c36cacbaf4f 100644
--- a/lib/system_check/base_check.rb
+++ b/lib/system_check/base_check.rb
@@ -121,7 +121,7 @@ module SystemCheck
#
# @see #try_fixing_it
# @see #fix_and_rerun
- # @see #for_more_infromation
+ # @see #for_more_information
def show_error
raise NotImplementedError
end
diff --git a/lib/tasks/gemojione.rake b/lib/tasks/gemojione.rake
index 560a52053d8..8cf7c9e89f0 100644
--- a/lib/tasks/gemojione.rake
+++ b/lib/tasks/gemojione.rake
@@ -209,7 +209,7 @@ namespace :gemojione do
image.destroy!
end
- EMOJI_IMAGE_PATH_RE = /(.*?)(([0-9a-f]-?)+)\.png$/i
+ EMOJI_IMAGE_PATH_RE = /(.*?)(([0-9a-f]-?)+)\.png$/i.freeze
def rename_to_named_emoji_image!(emoji_unicode_string_to_name_map, image_path)
# Rename file from unicode to emoji name
matches = EMOJI_IMAGE_PATH_RE.match(image_path)
diff --git a/lib/tasks/gettext.rake b/lib/tasks/gettext.rake
index 2235a6ba194..91a52144dd2 100644
--- a/lib/tasks/gettext.rake
+++ b/lib/tasks/gettext.rake
@@ -19,6 +19,7 @@ namespace :gettext do
Rake::Task['gettext:po_to_json'].invoke
end
+ desc 'Regenerate gitlab.pot file'
task :regenerate do
pot_file = 'locale/gitlab.pot'
# Remove all translated files, this speeds up finding
diff --git a/lib/tasks/gitlab/assets.rake b/lib/tasks/gitlab/assets.rake
index 7a42e4e92a0..a07ae3a418a 100644
--- a/lib/tasks/gitlab/assets.rake
+++ b/lib/tasks/gitlab/assets.rake
@@ -10,9 +10,15 @@ namespace :gitlab do
rake:assets:precompile
webpack:compile
gitlab:assets:fix_urls
+ gitlab:assets:compile_vrt
].each(&Gitlab::TaskHelpers.method(:invoke_and_time_task))
end
+ desc 'GitLab | Assets | Compile visual review toolbar'
+ task :compile_vrt do
+ system 'yarn', 'webpack-vrt'
+ end
+
desc 'GitLab | Assets | Clean up old compiled frontend assets'
task clean: ['rake:assets:clean']
diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake
index 3977fc7ad8c..c531eb1d216 100644
--- a/lib/tasks/gitlab/backup.rake
+++ b/lib/tasks/gitlab/backup.rake
@@ -20,6 +20,11 @@ namespace :gitlab do
backup.pack
backup.cleanup
backup.remove_old
+
+ puts "Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data \n" \
+ "and are not included in this backup. You will need these files to restore a backup.\n" \
+ "Please back them up manually.".color(:red)
+ puts "Backup task is done."
end
# Restore backup of GitLab system
@@ -68,6 +73,9 @@ namespace :gitlab do
Rake::Task['cache:clear'].invoke
backup.cleanup
+ puts "Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data \n" \
+ "and are not included in this backup. You will need to restore these files manually.".color(:red)
+ puts "Restore task is done."
end
namespace :repo do
diff --git a/lib/tasks/gitlab/features.rake b/lib/tasks/gitlab/features.rake
index d115961108e..d88bcca0819 100644
--- a/lib/tasks/gitlab/features.rake
+++ b/lib/tasks/gitlab/features.rake
@@ -17,7 +17,7 @@ namespace :gitlab do
if status
Feature.enable(flag)
else
- Feature.disable(flag)
+ Feature.get(flag).remove
end
end
end
diff --git a/lib/tasks/gitlab/seed.rake b/lib/tasks/gitlab/seed.rake
new file mode 100644
index 00000000000..155ba979b36
--- /dev/null
+++ b/lib/tasks/gitlab/seed.rake
@@ -0,0 +1,34 @@
+namespace :gitlab do
+ namespace :seed do
+ desc "GitLab | Seed | Seeds issues"
+ task :issues, [:project_full_path] => :environment do |t, args|
+ projects =
+ if args.project_full_path
+ project = Project.find_by_full_path(args.project_full_path)
+
+ unless project
+ error_message = "Project '#{args.project_full_path}' does not exist!"
+ potential_projects = Project.search(args.project_full_path)
+
+ if potential_projects.present?
+ error_message += " Did you mean '#{potential_projects.first.full_path}'?"
+ end
+
+ puts error_message.color(:red)
+ exit 1
+ end
+
+ [project]
+ else
+ Project.find_each
+ end
+
+ projects.each do |project|
+ puts "\nSeeding issues for the '#{project.full_path}' project"
+ seeder = Quality::Seeders::Issues.new(project: project)
+ issues_created = seeder.seed(backfill_weeks: 5, average_issues_per_week: 2)
+ puts "\n#{issues_created} issues created!"
+ end
+ end
+ end
+end
diff --git a/lib/tasks/gitlab/shell.rake b/lib/tasks/gitlab/shell.rake
index ee3ef9dad6e..487808a7baa 100644
--- a/lib/tasks/gitlab/shell.rake
+++ b/lib/tasks/gitlab/shell.rake
@@ -51,9 +51,6 @@ namespace :gitlab do
end
end
- # (Re)create hooks
- Rake::Task['gitlab:shell:create_hooks'].invoke
-
Gitlab::Shell.ensure_secret_token!
end
@@ -78,15 +75,6 @@ namespace :gitlab do
end
end
end
-
- desc 'Create or repair repository hooks symlink'
- task create_hooks: :gitlab_environment do
- warn_user_is_not_gitlab
-
- puts 'Creating/Repairing hooks symlinks for all repositories'
- system(*%W(#{Gitlab.config.gitlab_shell.path}/bin/create-hooks) + repository_storage_paths_args)
- puts 'done'.color(:green)
- end
end
def setup
diff --git a/lib/tasks/haml-lint.rake b/lib/tasks/haml-lint.rake
index 786efd14b1a..305e15d69d5 100644
--- a/lib/tasks/haml-lint.rake
+++ b/lib/tasks/haml-lint.rake
@@ -1,6 +1,6 @@
unless Rails.env.production?
require 'haml_lint/rake_task'
- require 'haml_lint/inline_javascript'
+ require Rails.root.join('haml_lint/inline_javascript')
# Workaround for warnings from parser/current
# Keep it even if it no longer emits any warnings,
diff --git a/lib/tasks/lint.rake b/lib/tasks/lint.rake
index c5d0f2c292f..2353b2dc659 100644
--- a/lib/tasks/lint.rake
+++ b/lib/tasks/lint.rake
@@ -37,32 +37,15 @@ unless Rails.env.production?
lint:static_verification
].each do |task|
pid = Process.fork do
- rd_out, wr_out = IO.pipe
- rd_err, wr_err = IO.pipe
- stdout = $stdout.dup
- stderr = $stderr.dup
- $stdout.reopen(wr_out)
- $stderr.reopen(wr_err)
-
- begin
- Rake::Task[task].invoke
- rescue SystemExit => ex
- msg = "*** Rake task #{task} exited:"
- raise ex
- rescue => ex
- msg = "*** Rake task #{task} raised #{ex.class}:"
- raise ex
- ensure
- $stdout.reopen(stdout)
- $stderr.reopen(stderr)
- wr_out.close
- wr_err.close
-
- warn "\n#{msg}\n\n" if msg
-
- IO.copy_stream(rd_out, $stdout)
- IO.copy_stream(rd_err, $stderr)
- end
+ puts "*** Running rake task: #{task} ***"
+
+ Rake::Task[task].invoke
+ rescue SystemExit => ex
+ warn "!!! Rake task #{task} exited:"
+ raise ex
+ rescue StandardError, ScriptError => ex
+ warn "!!! Rake task #{task} raised #{ex.class}:"
+ raise ex
end
Process.waitpid(pid)
diff --git a/lib/tasks/spec.rake b/lib/tasks/spec.rake
index 2eddcb3c777..c881ad4cf12 100644
--- a/lib/tasks/spec.rake
+++ b/lib/tasks/spec.rake
@@ -1,7 +1,32 @@
+# frozen_string_literal: true
+
+return if Rails.env.production?
+
Rake::Task["spec"].clear if Rake::Task.task_defined?('spec')
namespace :spec do
- desc 'GitLab | Rspec | Run request specs'
+ desc 'GitLab | RSpec | Run unit tests'
+ RSpec::Core::RakeTask.new(:unit, :rspec_opts) do |t, args|
+ require_dependency 'quality/test_level'
+ t.pattern = Quality::TestLevel.new.pattern(:unit)
+ t.rspec_opts = args[:rspec_opts]
+ end
+
+ desc 'GitLab | RSpec | Run integration tests'
+ RSpec::Core::RakeTask.new(:integration, :rspec_opts) do |t, args|
+ require_dependency 'quality/test_level'
+ t.pattern = Quality::TestLevel.new.pattern(:integration)
+ t.rspec_opts = args[:rspec_opts]
+ end
+
+ desc 'GitLab | RSpec | Run system tests'
+ RSpec::Core::RakeTask.new(:system, :rspec_opts) do |t, args|
+ require_dependency 'quality/test_level'
+ t.pattern = Quality::TestLevel.new.pattern(:system)
+ t.rspec_opts = args[:rspec_opts]
+ end
+
+ desc '[Deprecated] Use the "bin/rspec --tag api" instead'
task :api do
cmds = [
%w(rake gitlab:setup),
@@ -10,7 +35,7 @@ namespace :spec do
run_commands(cmds)
end
- desc 'GitLab | Rspec | Run feature specs'
+ desc '[Deprecated] Use the "spec:system" task instead'
task :feature do
cmds = [
%w(rake gitlab:setup),
@@ -19,7 +44,7 @@ namespace :spec do
run_commands(cmds)
end
- desc 'GitLab | Rspec | Run model specs'
+ desc '[Deprecated] Use "bin/rspec spec/models" instead'
task :models do
cmds = [
%w(rake gitlab:setup),
@@ -28,7 +53,7 @@ namespace :spec do
run_commands(cmds)
end
- desc 'GitLab | Rspec | Run service specs'
+ desc '[Deprecated] Use "bin/rspec spec/services" instead'
task :services do
cmds = [
%w(rake gitlab:setup),
@@ -37,7 +62,7 @@ namespace :spec do
run_commands(cmds)
end
- desc 'GitLab | Rspec | Run lib specs'
+ desc '[Deprecated] Use "bin/rspec spec/lib" instead'
task :lib do
cmds = [
%w(rake gitlab:setup),
@@ -45,15 +70,6 @@ namespace :spec do
]
run_commands(cmds)
end
-
- desc 'GitLab | Rspec | Run other specs'
- task :other do
- cmds = [
- %w(rake gitlab:setup),
- %w(rspec spec --tag ~@api --tag ~@feature --tag ~@models --tag ~@lib --tag ~@services)
- ]
- run_commands(cmds)
- end
end
desc "GitLab | Run specs"
diff --git a/locale/ar_SA/gitlab.po b/locale/ar_SA/gitlab.po
index 9d3218cbd36..bd69bc85978 100644
--- a/locale/ar_SA/gitlab.po
+++ b/locale/ar_SA/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Arabic\n"
"Language: ar_SA\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ar\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:34\n"
+"PO-Revision-Date: 2019-06-14 10:21\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -87,6 +84,15 @@ msgstr[5] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -150,6 +156,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -159,6 +174,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -195,10 +219,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -243,6 +264,12 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -255,12 +282,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -276,6 +315,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -294,6 +339,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -342,6 +399,9 @@ msgstr[5] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -354,9 +414,33 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -381,6 +465,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -409,7 +496,7 @@ msgstr[4] ""
msgstr[5] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -418,7 +505,7 @@ msgstr[4] ""
msgstr[5] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -439,7 +526,7 @@ msgstr[4] ""
msgstr[5] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -448,7 +535,7 @@ msgstr[4] ""
msgstr[5] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -457,7 +544,7 @@ msgstr[4] ""
msgstr[5] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -495,15 +582,27 @@ msgstr[5] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -513,6 +612,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -543,6 +645,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -579,19 +684,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -621,6 +726,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -666,12 +774,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -708,6 +828,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -729,10 +852,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -741,9 +870,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -753,6 +888,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -765,9 +903,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -780,10 +927,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -792,10 +942,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -807,6 +966,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -828,6 +990,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -942,6 +1107,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -963,15 +1131,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -1044,9 +1221,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -1080,10 +1254,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -1107,21 +1284,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -1137,6 +1329,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1170,7 +1365,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1224,6 +1422,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1281,9 +1482,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1293,6 +1500,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1302,6 +1515,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1320,6 +1536,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1377,12 +1605,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1413,37 +1635,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1461,6 +1683,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1473,12 +1698,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1491,6 +1740,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1506,6 +1758,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1536,6 +1794,18 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1623,15 +1893,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1743,6 +2022,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1845,12 +2148,39 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1866,6 +2196,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -2016,6 +2349,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -2034,6 +2382,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -2124,9 +2475,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -2148,9 +2505,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2166,6 +2529,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2178,6 +2547,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2202,6 +2580,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2229,6 +2613,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2250,6 +2637,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2280,7 +2670,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2352,16 +2742,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2415,9 +2823,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2472,6 +2889,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2490,7 +2910,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2508,12 +2934,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2529,6 +2967,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2637,6 +3078,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2673,19 +3117,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2718,6 +3153,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2754,6 +3192,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2763,9 +3204,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2829,7 +3267,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2883,40 +3321,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2928,6 +3378,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2937,6 +3390,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2988,9 +3444,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -3009,6 +3471,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -3132,6 +3597,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -3159,9 +3627,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3174,9 +3648,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3240,6 +3720,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3285,6 +3768,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3294,6 +3780,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3312,9 +3801,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3330,6 +3816,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3339,6 +3831,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3348,9 +3843,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3384,9 +3885,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3459,6 +3969,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3474,12 +3990,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3498,6 +4029,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3576,15 +4110,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3621,6 +4179,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3672,6 +4233,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3693,6 +4269,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3873,6 +4497,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3927,9 +4554,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3951,6 +4584,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3981,18 +4620,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -4005,25 +4668,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -4065,6 +4722,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -4101,6 +4761,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -4119,6 +4785,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -4143,9 +4812,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4170,6 +4869,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4206,9 +4908,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4239,12 +4938,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4257,7 +4962,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4269,9 +4977,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4407,18 +5139,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4455,9 +5220,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4467,6 +5238,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4476,6 +5253,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4485,6 +5265,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4518,9 +5304,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4617,6 +5409,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4704,6 +5499,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4713,27 +5529,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4752,6 +5601,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4764,16 +5619,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4788,6 +5655,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4851,7 +5724,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4863,9 +5736,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4950,6 +5820,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4998,6 +5874,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -5007,6 +5886,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -5031,6 +5913,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -5076,6 +5964,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -5085,6 +5982,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -5103,6 +6003,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -5133,12 +6036,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5496,6 +6405,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5553,6 +6468,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5562,6 +6480,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5634,6 +6555,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5652,9 +6576,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5730,6 +6663,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5739,6 +6675,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5766,13 +6705,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5784,9 +6726,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5817,9 +6756,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5883,6 +6831,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5952,6 +6903,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5979,6 +6933,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5988,12 +6945,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -6003,6 +6963,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -6021,6 +6984,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -6036,6 +7005,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -6045,6 +7020,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -6114,10 +7095,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6198,6 +7188,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6207,6 +7203,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6216,9 +7218,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6270,12 +7281,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6297,12 +7317,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6354,18 +7386,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6375,6 +7431,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6387,6 +7446,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6405,6 +7467,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6480,6 +7548,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6576,6 +7686,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6585,6 +7701,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6609,12 +7728,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6627,6 +7752,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6675,6 +7803,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6693,6 +7824,9 @@ msgstr[5] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6720,6 +7854,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6735,6 +7875,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6753,6 +7899,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6765,6 +7914,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6786,6 +7938,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6861,6 +8019,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6879,6 +8040,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6909,6 +8073,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6930,6 +8097,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6948,6 +8118,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6972,12 +8145,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -7038,6 +8220,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -7050,6 +8241,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -7074,6 +8274,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -7104,6 +8307,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -7116,15 +8322,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -7134,12 +8334,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -7158,6 +8352,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -7176,6 +8394,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7188,6 +8409,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7221,7 +8445,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7236,6 +8460,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7251,6 +8481,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7290,9 +8523,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7338,9 +8568,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7365,9 +8607,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7386,7 +8625,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7395,6 +8634,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7416,6 +8664,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7476,6 +8736,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7488,6 +8766,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7587,6 +8868,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7611,6 +8895,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7641,6 +8928,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7650,12 +8943,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7671,6 +8973,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7695,6 +9000,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7716,9 +9024,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7734,6 +9039,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7761,6 +9069,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7809,6 +9123,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7824,6 +9141,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7833,6 +9156,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7887,6 +9213,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7902,6 +9231,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7917,7 +9252,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7944,13 +9285,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7968,6 +9309,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -8013,6 +9357,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -8037,9 +9387,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -8061,6 +9408,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -8070,6 +9420,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -8097,6 +9453,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -8118,9 +9477,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -8133,7 +9504,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -8160,6 +9531,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -8181,12 +9555,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8265,6 +9654,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8274,10 +9666,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8298,6 +9693,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8358,6 +9756,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8388,6 +9789,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8397,12 +9807,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8433,6 +9861,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8445,6 +9876,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8466,7 +9906,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8484,12 +9924,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8505,12 +9999,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8538,15 +10038,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8577,6 +10086,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8598,6 +10110,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8610,6 +10125,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8637,6 +10155,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8646,9 +10176,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8658,18 +10194,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8688,9 +10239,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8706,13 +10254,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8727,6 +10278,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8748,6 +10302,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8841,6 +10398,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8886,6 +10446,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8937,6 +10500,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8946,18 +10527,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8967,12 +10590,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -9129,6 +10812,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -9147,16 +10839,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -9165,18 +10863,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9225,9 +10929,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9252,12 +10962,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9282,15 +11034,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9309,24 +11070,45 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9351,6 +11133,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9363,6 +11148,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9372,7 +11160,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9381,25 +11172,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9414,6 +11217,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9444,6 +11265,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9453,7 +11277,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9468,6 +11292,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9507,12 +11334,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9567,6 +11388,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9585,6 +11412,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9624,6 +11454,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9666,6 +11505,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9708,6 +11550,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9792,6 +11640,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9801,6 +11652,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9816,6 +11670,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9828,6 +11685,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9888,9 +11748,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9912,6 +11784,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9987,9 +11862,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -10020,12 +11892,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -10038,6 +11922,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -10065,6 +11955,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -10101,6 +11994,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -10182,6 +12078,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10212,19 +12111,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10242,6 +12144,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10263,6 +12168,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10290,6 +12198,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10305,6 +12225,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10317,9 +12240,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10335,9 +12267,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10395,12 +12324,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10410,6 +12357,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10419,6 +12369,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10488,6 +12441,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10506,6 +12462,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10530,7 +12489,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10542,6 +12501,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10602,6 +12564,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10656,6 +12621,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10728,6 +12699,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10752,6 +12726,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10782,6 +12759,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10842,12 +12825,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10878,6 +12867,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10950,6 +12942,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10974,6 +12969,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10986,6 +13044,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -11016,18 +13080,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -11109,6 +13185,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -11121,6 +13200,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -11136,6 +13218,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -11178,6 +13287,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -11193,6 +13305,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11250,6 +13365,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11268,6 +13392,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11292,9 +13422,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11304,6 +13446,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11313,6 +13458,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11352,6 +13500,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11373,15 +13524,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11415,9 +13581,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11433,6 +13614,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11451,6 +13638,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11463,6 +13653,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11475,18 +13668,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11511,6 +13716,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11523,6 +13734,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11532,22 +13746,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11619,12 +13842,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11697,6 +13914,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11889,6 +14112,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11904,6 +14130,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11970,6 +14199,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -12006,6 +14238,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -12018,9 +14253,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -12030,6 +14271,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -12072,6 +14316,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -12123,15 +14403,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -12141,24 +14436,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -12177,18 +14490,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12258,6 +14586,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12309,6 +14649,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12318,6 +14661,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12336,6 +14682,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12345,6 +14739,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12402,6 +14802,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12417,6 +14820,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12492,6 +15030,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12507,9 +15054,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12555,12 +15120,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12570,6 +15141,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12579,6 +15153,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12606,6 +15183,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12633,6 +15213,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12675,6 +15282,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12693,6 +15303,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12702,6 +15315,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12723,6 +15339,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12732,13 +15351,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12756,6 +15378,9 @@ msgstr[5] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12936,6 +15561,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12951,7 +15579,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12963,6 +15597,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12978,6 +15615,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12996,6 +15639,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -13020,9 +15672,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -13053,12 +15711,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -13068,6 +15735,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -13098,6 +15771,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -13110,6 +15792,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -13122,6 +15807,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -13155,6 +15843,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -13176,27 +15867,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -13230,7 +15945,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13248,6 +15966,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13281,10 +16002,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13299,6 +16023,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13416,6 +16155,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13449,9 +16191,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13467,12 +16206,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13599,9 +16332,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13623,10 +16353,10 @@ msgstr[5] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13668,6 +16398,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13710,9 +16443,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13725,6 +16464,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13749,6 +16494,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13782,6 +16530,12 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13791,6 +16545,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13809,6 +16566,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13839,6 +16599,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13866,7 +16629,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13881,6 +16644,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13935,6 +16701,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13953,18 +16722,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13995,30 +16761,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -14103,15 +16851,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -14241,7 +17004,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -14250,18 +17013,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -14295,12 +17070,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index f62cc8295f4..d94315d5c76 100644
--- a/locale/bg/gitlab.po
+++ b/locale/bg/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Bulgarian\n"
"Language: bg_BG\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: bg\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:35\n"
+"PO-Revision-Date: 2019-06-14 10:22\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr "ДобавÑне на нова папка"
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,6 +1459,18 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
+msgid "Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr ""
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to delete this list?"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "ÐаиÑтина ли иÑкате да изтриете този план за Ñхема?"
@@ -1274,18 +1492,6 @@ msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove approver %{name}?"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}?"
-msgstr ""
-
msgid "Are you sure you want to remove the attachment?"
msgstr ""
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Прикачете файл чрез влачене и пуÑкане или %{upload_link}"
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "ТърÑете в клоните"
@@ -1856,6 +2161,21 @@ msgstr "Разглеждане на файловете"
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "от"
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "Избиране в клона"
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr "Графики"
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr "Подбиране на това подаване"
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr "пропуÑнато"
msgid "CiStatus|running"
msgstr "протича в момента"
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr "Копиране на адреÑа в буфера за обмен"
@@ -3166,6 +3624,12 @@ msgstr "Копиране на идентификатора на подаване
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr "Етикет"
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "ВнедрÑване"
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr "Да не Ñе показва повече"
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "Редактиране на плана %{id} за Ñхема"
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr "СобÑтвеникът не може да бъде променен"
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr "Файлове"
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Разклонение на"
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr "ОÑвежаването започна уÑпешно"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr "ВнаÑÑне на хранилище"
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr "ПредÑтавÑме Ви анализа на циклите"
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr "Изключено"
msgid "LFSStatus|Enabled"
msgstr "Включено"
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] "ПоÑледните %d дни"
msgid "Last Pipeline"
msgstr "ПоÑледна Ñхема"
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr "Ðаучете повече в"
@@ -6602,6 +7726,12 @@ msgstr "ÐапуÑкане на проекта"
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "добавите SSH ключ"
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr "Ðов файл"
@@ -7419,6 +8675,9 @@ msgstr "Ðова заÑвка за Ñливане"
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr "Ð¡ÑŠÐ±Ð¸Ñ‚Ð¸Ñ Ð·Ð° извеÑÑ‚Ñване"
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "ЗатварÑне на проблем"
@@ -7695,6 +8993,9 @@ msgstr "УчаÑтие"
msgid "NotificationLevel|Watch"
msgstr "Ðаблюдение"
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr "Филтър"
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr "Отворен"
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr "СобÑтвеник"
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr "Схема"
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr "План за Ñхема"
@@ -8069,6 +9430,9 @@ msgstr "Схеми"
msgid "Pipelines charts"
msgstr "Графики за Ñхемите"
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr "Ñ ÐµÑ‚Ð°Ð¿"
msgid "Pipeline|with stages"
msgstr "Ñ ÐµÑ‚Ð°Ð¿Ð¸"
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr "Свързани заÑвки за Ñливане"
msgid "Related Merged Requests"
msgstr "Свързани приложени заÑвки за Ñливане"
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr "ÐапомнÑне по-къÑно"
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr "Премахване на проекта"
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Запазване на плана за Ñхема"
@@ -9676,9 +11508,21 @@ msgstr "ТърÑете в клоните и етикетите"
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr "Изберете формата на архива"
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr "зададете парола"
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr "Звезда"
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr "Преминаване към клон/етикет"
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr "Етикети"
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "Етапът на проблемите показва колко е времето от Ñъздаването на проблем до определÑнето на целеви етап на проекта за него, или до добавÑнето му в ÑпиÑък на дъÑката за проблеми. Започнете да добавÑте проблеми, за да видите данните за този етап."
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr "Етапът на издаване показва общото времÐ
msgid "The project can be accessed by any logged in user."
msgstr "Ð’Ñеки впиÑан потребител има доÑтъп до проекта."
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr "Ð’Ñеки може да има доÑтъп до проекта, без нужда от удоÑтоверÑване."
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr "Хранилището за този проект не ÑъщеÑтвуÐ
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr "Етапът на теÑтване показва времето, кое
msgid "The time taken by each data entry gathered by that stage."
msgstr "Времето, което отнема вÑеки Ð·Ð°Ð¿Ð¸Ñ Ð¾Ñ‚ данни за ÑÑŠÐ¾Ñ‚Ð²ÐµÑ‚Ð½Ð¸Ñ ÐµÑ‚Ð°Ð¿."
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "СтойноÑтта, коÑто Ñе намира в Ñредата на поÑледователноÑтта от наблюдавани данни. Ðапример: медианата на 3, 5 и 9 е 5, а медианата на 3, 5, 7 и 8 е (5+7)/2 = 6."
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr "Това означава, че нÑма да можете да изпр
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr "Време преди един проблем да бъде планиран за работа"
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr "Качване на файл"
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr "щракнете за качване"
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr "Публичен"
msgid "VisibilityLevel|Unknown"
msgstr "ÐеизвеÑтно"
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "ИÑкате ли да видите данните? Помолете админиÑтратор за доÑтъп."
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr "ÐÑма доÑтатъчно данни за този етап."
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,8 +15319,14 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "Ðа път Ñте да премахнете „%{group_name}“. Ðко Ñ Ð¿Ñ€ÐµÐ¼Ð°Ñ…Ð½ÐµÑ‚Ðµ, групата ÐЕ може да бъде възÑтановена! ÐÐИСТИÐРли иÑкате това?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
@@ -12731,6 +15337,9 @@ msgstr "Ðа път Ñте да премахнете връзката на раÐ
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr "Ðуждаете Ñе от разрешение."
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr "ÐÑма да можете да изтеглÑте или изпраща
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr "Вашето име"
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] "ден"
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr "нова заÑвка за Ñливане"
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/bn_BD/gitlab.po b/locale/bn_BD/gitlab.po
index dd593020e0f..8290a84180a 100644
--- a/locale/bn_BD/gitlab.po
+++ b/locale/bn_BD/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Bengali\n"
"Language: bn_BD\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: bn\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:35\n"
+"PO-Revision-Date: 2019-06-14 10:21\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,37 +1459,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1856,6 +2161,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/bn_IN/gitlab.po b/locale/bn_IN/gitlab.po
index 75fdf861c0d..f4c87c8fc3b 100644
--- a/locale/bn_IN/gitlab.po
+++ b/locale/bn_IN/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Bengali, India\n"
"Language: bn_IN\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: bn-IN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:35\n"
+"PO-Revision-Date: 2019-06-14 10:22\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,37 +1459,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1856,6 +2161,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/ca_ES/gitlab.po b/locale/ca_ES/gitlab.po
index 1facbc90b47..fcf7a6bc34e 100644
--- a/locale/ca_ES/gitlab.po
+++ b/locale/ca_ES/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Catalan\n"
"Language: ca_ES\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ca\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:36\n"
+"PO-Revision-Date: 2019-06-14 10:22\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr " Estat"
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] "%d petició de fusió"
msgstr[1] "%d peticions de fusió"
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d mètrica"
msgstr[1] "%d mètriques"
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] "%{text} %{files} fitxers"
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] "1 grup"
msgstr[1] "%d grups"
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] "%d usuaris"
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr "2FA activat"
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr "Quant al GitLab"
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr "Compte"
msgid "Account and limit"
msgstr "Compte i límit"
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr "Afegeix una taula"
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr "Afegeix el comentari"
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr "Afegeix un comentari a la imatge"
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr "Afegeix una llicència"
@@ -625,9 +747,18 @@ msgstr "Afegeix una aplicació nova"
msgid "Add new directory"
msgstr "Afegeix un directori nou"
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr "Afegeix una reacció"
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,22 +771,34 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr "Afegeix usuaris al grup:"
-msgid "Add users or groups who are allowed to approve every merge request"
-msgstr ""
-
msgid "Add users to group"
msgstr "Afegeix usuaris al grup"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
+msgstr ""
+
msgid "Added at"
msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr "Text addicional"
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr "Informació general d'administració"
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr "Configuració avançada"
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr "Qualsevol"
msgid "Any Label"
msgstr "Qualsevol etiqueta"
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr "Aparença"
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr "Aplicació"
@@ -1158,6 +1355,9 @@ msgstr "ID de l'aplicació"
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr "abr"
@@ -1253,37 +1459,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr "N'esteu segur?"
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr "Artefactes"
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr "Taulers"
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr "Nom de la branca"
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1856,6 +2161,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr "Canvia la plantilla"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr "Diagrames"
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr "Trieu una plantilla..."
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr "Tancades"
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr "Comentaris"
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr "Connecta"
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr "S'està connectant..."
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr "Copia l'URL al porta-retalls"
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr "Crea una etiqueta de projecte"
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr "Etiqueta"
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr "Creat per mi"
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr "Node actual"
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr "Perfil"
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr "Selector de data"
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr "Depura"
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr "Domini"
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr "No ho mostris més"
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr "Fet"
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr "Elasticsearch"
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr "Introduïu el títol de la petició de fusió"
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr "Entorns"
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr "Com ho puc resoldre-ho?"
msgid "Epics|More information"
msgstr "Més informació"
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr "S'ha produït un error en carregar les peticions de fusió."
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr "Facebook"
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr "Nom"
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr "Fitxers"
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr "Claus GPG"
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr "Git"
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr "Enrere"
@@ -5480,9 +6376,18 @@ msgstr "Vés a"
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr "Grups"
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr "Ajuda"
@@ -5816,12 +6745,15 @@ msgstr "Pàgina d'ajuda"
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Amaga el valor"
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr "Historial"
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr "ID"
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] "Instància"
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr "Petició de fusió"
@@ -6928,15 +8106,9 @@ msgstr "Peticions de fusió"
msgid "Merge Requests created"
msgstr "S'han creat les peticions de fusió"
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr "Esdeveniments de fusió"
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr "Petició de fusió"
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr "Missatges"
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr "Mètriques"
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr "Mètrica nova"
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr "Mou"
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr "Nom"
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/cs_CZ/gitlab.po b/locale/cs_CZ/gitlab.po
index f41277b2c79..60d3a1c3f48 100644
--- a/locale/cs_CZ/gitlab.po
+++ b/locale/cs_CZ/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Czech\n"
"Language: cs_CZ\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: cs\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:35\n"
+"PO-Revision-Date: 2019-06-14 10:24\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -77,6 +74,13 @@ msgstr[3] "%d commitů pozadu"
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -126,6 +130,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -133,6 +144,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -163,10 +181,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -205,6 +220,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -217,12 +238,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -238,6 +271,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr "Profilový obrázek %{name}"
@@ -256,6 +295,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -296,6 +347,9 @@ msgstr[3] ""
msgid "%{text} is available"
msgstr "%{text} je k dispozici"
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -308,9 +362,31 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -335,6 +411,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -357,14 +436,14 @@ msgstr[2] ""
msgstr[3] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -381,21 +460,21 @@ msgstr[2] ""
msgstr[3] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -425,15 +504,27 @@ msgstr[3] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr "1. příspěvek!"
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr "Dvoufaktorové ověření povoleno"
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -443,6 +534,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -473,6 +567,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -509,19 +606,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -551,6 +648,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -596,12 +696,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -638,6 +750,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -659,10 +774,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -671,9 +792,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -683,6 +810,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -695,9 +825,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr "Přidat reakci"
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -710,10 +849,13 @@ msgstr "Přidat úkol"
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
+msgstr ""
+
+msgid "AddMember|No users specified."
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -722,10 +864,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr "DodateÄný text"
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -737,6 +888,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -758,6 +912,9 @@ msgstr "Zastavení úloh selhalo"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "Chystáte se zastavit všechny úlohy. To způsobí přerušení všech aktuálně spuštěných úloh."
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -872,6 +1029,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -891,15 +1051,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -972,9 +1141,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -1008,10 +1174,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -1035,21 +1204,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -1065,6 +1249,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1098,7 +1285,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1152,6 +1342,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1209,9 +1402,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr "Vzhled"
@@ -1221,6 +1420,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1230,6 +1435,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1248,6 +1456,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1297,12 +1517,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr "Dub"
@@ -1333,37 +1547,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1381,6 +1595,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1393,12 +1610,36 @@ msgstr ""
msgid "Are you sure?"
msgstr "Jste si jisti?"
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr "Artefakty"
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1411,6 +1652,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr "PÅ™iÅ™aÄte vlastní barvu jako například #FF0000"
@@ -1426,6 +1670,12 @@ msgstr ""
msgid "Assign to"
msgstr "Přiřadit k"
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1456,6 +1706,16 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1543,15 +1803,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr "K dispozici"
@@ -1663,6 +1932,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1765,12 +2058,35 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1786,6 +2102,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1936,6 +2255,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1954,6 +2288,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -2044,9 +2381,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -2068,9 +2411,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2086,6 +2435,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2098,6 +2453,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2122,6 +2486,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2149,6 +2519,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2170,6 +2543,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2200,7 +2576,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2272,16 +2648,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2335,9 +2729,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2392,6 +2795,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2410,7 +2816,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2428,12 +2840,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2449,6 +2873,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2557,6 +2984,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2593,19 +3023,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2638,6 +3059,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2674,6 +3098,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2683,9 +3110,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2749,7 +3173,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2803,40 +3227,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2848,6 +3284,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2857,6 +3296,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2908,9 +3350,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2929,6 +3377,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -3050,6 +3501,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -3077,9 +3531,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3092,9 +3552,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3158,6 +3624,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3203,6 +3672,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3212,6 +3684,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3230,9 +3705,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3248,6 +3720,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3257,6 +3735,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3266,9 +3747,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3302,9 +3789,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3377,6 +3873,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3392,12 +3894,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3416,6 +3933,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3494,15 +4014,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3539,6 +4083,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3590,6 +4137,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3611,6 +4173,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3789,6 +4399,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3843,9 +4456,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3867,6 +4486,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3897,18 +4522,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3921,25 +4570,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3981,6 +4624,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -4017,6 +4663,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -4035,6 +4687,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -4059,9 +4714,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4086,6 +4771,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4122,9 +4810,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4155,12 +4840,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4173,7 +4864,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4185,9 +4879,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4323,18 +5041,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4371,9 +5122,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4383,6 +5140,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4392,6 +5155,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4401,6 +5167,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4434,9 +5206,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4533,6 +5311,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4620,6 +5401,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4629,27 +5431,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4668,6 +5503,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4680,16 +5521,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4704,6 +5557,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4767,7 +5626,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4779,9 +5638,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4864,6 +5720,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4912,6 +5774,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4921,6 +5786,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4945,6 +5813,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4990,6 +5864,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4999,6 +5882,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -5017,6 +5903,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -5047,12 +5936,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5410,6 +6305,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5467,6 +6368,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5476,6 +6380,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5548,6 +6455,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5566,9 +6476,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5644,6 +6563,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5653,6 +6575,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5680,13 +6605,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5698,9 +6626,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5731,9 +6656,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5797,6 +6731,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5866,6 +6803,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5893,6 +6833,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5902,12 +6845,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5917,6 +6863,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5933,6 +6882,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5948,6 +6903,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5957,6 +6918,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -6026,10 +6993,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6110,6 +7086,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6119,6 +7101,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6128,9 +7116,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6182,12 +7179,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6209,12 +7215,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6264,18 +7282,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6285,6 +7327,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6297,6 +7342,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6315,6 +7363,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6390,6 +7444,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6486,6 +7582,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6495,6 +7597,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6519,12 +7624,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6537,6 +7648,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6585,6 +7699,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6601,6 +7718,9 @@ msgstr[3] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6628,6 +7748,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6643,6 +7769,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6661,6 +7793,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6673,6 +7808,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6694,6 +7832,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6769,6 +7913,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6785,6 +7932,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6815,6 +7965,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6836,6 +7989,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6854,6 +8010,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6878,12 +8037,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6944,6 +8112,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6956,6 +8133,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6980,6 +8166,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -7010,6 +8199,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -7022,15 +8214,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -7040,12 +8226,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -7064,6 +8244,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -7082,6 +8286,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7094,6 +8301,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7127,7 +8337,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7142,6 +8352,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7157,6 +8373,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7196,9 +8415,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7244,9 +8460,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7271,9 +8499,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7292,7 +8517,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7301,6 +8526,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7322,6 +8556,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7382,6 +8628,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7394,6 +8658,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7491,6 +8758,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7515,6 +8785,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7545,6 +8818,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7554,12 +8833,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7575,6 +8863,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7599,6 +8890,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7620,9 +8914,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7638,6 +8929,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7665,6 +8959,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7713,6 +9013,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7728,6 +9031,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7737,6 +9046,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7791,6 +9103,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7806,6 +9121,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7821,7 +9142,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7846,13 +9173,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7870,6 +9197,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7915,6 +9245,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7939,9 +9275,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7963,6 +9296,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7972,6 +9308,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7999,6 +9341,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -8020,9 +9365,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -8035,7 +9392,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -8062,6 +9419,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -8083,12 +9443,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8167,6 +9542,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8176,10 +9554,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8200,6 +9581,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8260,6 +9644,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8290,6 +9677,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8299,12 +9695,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8335,6 +9749,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8347,6 +9764,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8368,7 +9794,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8386,12 +9812,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8407,12 +9887,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8440,15 +9926,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8479,6 +9974,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8500,6 +9998,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8512,6 +10013,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8539,6 +10043,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8548,9 +10064,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8560,18 +10082,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8590,9 +10127,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8608,13 +10142,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8629,6 +10166,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8650,6 +10190,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8743,6 +10286,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8788,6 +10334,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8839,6 +10388,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8848,18 +10415,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8869,12 +10478,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -9031,6 +10700,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -9049,16 +10727,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -9067,18 +10751,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9127,9 +10817,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9154,12 +10850,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9184,15 +10922,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9209,24 +10956,45 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9251,6 +11019,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9263,6 +11034,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9272,7 +11046,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9281,25 +11058,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9314,6 +11103,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9344,6 +11151,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9353,7 +11163,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9368,6 +11178,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9407,12 +11220,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9467,6 +11274,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9481,6 +11294,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9520,6 +11336,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9562,6 +11387,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9602,6 +11430,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9686,6 +11520,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9695,6 +11532,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9710,6 +11550,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9722,6 +11565,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9782,9 +11628,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9806,6 +11664,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9881,9 +11742,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9914,12 +11772,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9932,6 +11802,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9959,6 +11835,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9995,6 +11874,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -10076,6 +11958,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10106,19 +11991,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10136,6 +12024,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10157,6 +12048,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10184,6 +12078,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10199,6 +12105,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10211,9 +12120,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10229,9 +12147,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10287,12 +12202,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10302,6 +12235,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10311,6 +12247,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10380,6 +12319,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10398,6 +12340,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10422,7 +12367,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10434,6 +12379,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10494,6 +12442,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10548,6 +12499,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10620,6 +12577,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10644,6 +12604,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10674,6 +12637,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10734,12 +12703,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10770,6 +12745,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10842,6 +12820,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10866,6 +12847,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10878,6 +12922,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10908,18 +12958,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -11001,6 +13063,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -11013,6 +13078,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -11028,6 +13096,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -11068,6 +13163,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -11083,6 +13181,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11140,6 +13241,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11158,6 +13268,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11182,9 +13298,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11194,6 +13322,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11203,6 +13334,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11242,6 +13376,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11263,15 +13400,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11305,9 +13457,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11323,6 +13490,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11341,6 +13514,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11353,6 +13529,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11365,18 +13544,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11401,6 +13592,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11413,6 +13610,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11422,22 +13622,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11509,12 +13718,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11587,6 +13790,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11775,6 +13984,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11790,6 +14002,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11856,6 +14071,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11892,6 +14110,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11904,9 +14125,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11916,6 +14143,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11958,6 +14188,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -12009,15 +14275,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -12027,24 +14308,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -12063,18 +14362,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12144,6 +14458,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12195,6 +14521,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12204,6 +14533,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12222,6 +14554,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12231,6 +14611,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12288,6 +14674,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12303,6 +14692,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12378,6 +14902,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12393,9 +14926,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12441,12 +14992,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12456,6 +15013,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12465,6 +15025,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12492,6 +15055,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12519,6 +15085,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12561,6 +15154,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12579,6 +15175,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12588,6 +15187,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12609,6 +15211,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12618,13 +15223,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12640,6 +15248,9 @@ msgstr[3] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12820,6 +15431,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12835,7 +15449,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12847,6 +15467,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12862,6 +15485,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12880,6 +15509,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12904,9 +15542,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12937,12 +15581,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12952,6 +15605,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12982,6 +15641,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12994,6 +15662,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -13006,6 +15677,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -13039,6 +15713,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -13060,27 +15737,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -13114,7 +15815,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13132,6 +15836,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13165,10 +15872,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
msgstr ""
-msgid "at"
+msgid "already shared with this group"
+msgstr ""
+
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13183,6 +15893,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13288,6 +16013,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13321,9 +16049,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13339,12 +16064,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13467,9 +16186,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13489,10 +16205,10 @@ msgstr[3] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13534,6 +16250,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13570,9 +16289,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13585,6 +16310,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13609,6 +16340,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13640,6 +16374,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13649,6 +16389,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13667,6 +16410,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13695,6 +16441,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13722,7 +16471,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13737,6 +16486,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13791,6 +16543,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13809,18 +16564,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13851,26 +16603,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13955,15 +16693,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -14083,7 +16836,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -14092,18 +16845,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -14137,12 +16902,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/cy_GB/gitlab.po b/locale/cy_GB/gitlab.po
index 5d41baffb24..dd4e6d82647 100644
--- a/locale/cy_GB/gitlab.po
+++ b/locale/cy_GB/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Welsh\n"
"Language: cy_GB\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: cy\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:40\n"
+"PO-Revision-Date: 2019-06-14 10:27\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -87,6 +84,15 @@ msgstr[5] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -150,6 +156,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -159,6 +174,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -195,10 +219,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -243,6 +264,12 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -255,12 +282,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -276,6 +315,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -294,6 +339,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -342,6 +399,9 @@ msgstr[5] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -354,9 +414,33 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -381,6 +465,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -409,7 +496,7 @@ msgstr[4] ""
msgstr[5] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -418,7 +505,7 @@ msgstr[4] ""
msgstr[5] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -439,7 +526,7 @@ msgstr[4] ""
msgstr[5] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -448,7 +535,7 @@ msgstr[4] ""
msgstr[5] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -457,7 +544,7 @@ msgstr[4] ""
msgstr[5] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -495,15 +582,27 @@ msgstr[5] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -513,6 +612,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -543,6 +645,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -579,19 +684,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -621,6 +726,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -666,12 +774,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -708,6 +828,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -729,10 +852,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -741,9 +870,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -753,6 +888,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -765,9 +903,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -780,10 +927,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -792,10 +942,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -807,6 +966,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -828,6 +990,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -942,6 +1107,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -963,15 +1131,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -1044,9 +1221,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -1080,10 +1254,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -1107,21 +1284,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -1137,6 +1329,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1170,7 +1365,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1224,6 +1422,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1281,9 +1482,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1293,6 +1500,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1302,6 +1515,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1320,6 +1536,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1377,12 +1605,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1413,37 +1635,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1461,6 +1683,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1473,12 +1698,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1491,6 +1740,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1506,6 +1758,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1536,6 +1794,18 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1623,15 +1893,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1743,6 +2022,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1845,12 +2148,39 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1866,6 +2196,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -2016,6 +2349,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -2034,6 +2382,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -2124,9 +2475,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -2148,9 +2505,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2166,6 +2529,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2178,6 +2547,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2202,6 +2580,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2229,6 +2613,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2250,6 +2637,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2280,7 +2670,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2352,16 +2742,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2415,9 +2823,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2472,6 +2889,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2490,7 +2910,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2508,12 +2934,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2529,6 +2967,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2637,6 +3078,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2673,19 +3117,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2718,6 +3153,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2754,6 +3192,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2763,9 +3204,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2829,7 +3267,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2883,40 +3321,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2928,6 +3378,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2937,6 +3390,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2988,9 +3444,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -3009,6 +3471,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -3132,6 +3597,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -3159,9 +3627,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3174,9 +3648,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3240,6 +3720,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3285,6 +3768,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3294,6 +3780,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3312,9 +3801,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3330,6 +3816,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3339,6 +3831,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3348,9 +3843,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3384,9 +3885,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3459,6 +3969,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3474,12 +3990,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3498,6 +4029,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3576,15 +4110,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3621,6 +4179,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3672,6 +4233,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3693,6 +4269,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3873,6 +4497,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3927,9 +4554,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3951,6 +4584,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3981,18 +4620,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -4005,25 +4668,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -4065,6 +4722,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -4101,6 +4761,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -4119,6 +4785,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -4143,9 +4812,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4170,6 +4869,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4206,9 +4908,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4239,12 +4938,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4257,7 +4962,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4269,9 +4977,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4407,18 +5139,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4455,9 +5220,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4467,6 +5238,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4476,6 +5253,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4485,6 +5265,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4518,9 +5304,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4617,6 +5409,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4704,6 +5499,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4713,27 +5529,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4752,6 +5601,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4764,16 +5619,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4788,6 +5655,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4851,7 +5724,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4863,9 +5736,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4950,6 +5820,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4998,6 +5874,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -5007,6 +5886,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -5031,6 +5913,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -5076,6 +5964,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -5085,6 +5982,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -5103,6 +6003,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -5133,12 +6036,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5496,6 +6405,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5553,6 +6468,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5562,6 +6480,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5634,6 +6555,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5652,9 +6576,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5730,6 +6663,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5739,6 +6675,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5766,13 +6705,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5784,9 +6726,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5817,9 +6756,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5883,6 +6831,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5952,6 +6903,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5979,6 +6933,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5988,12 +6945,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -6003,6 +6963,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -6021,6 +6984,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -6036,6 +7005,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -6045,6 +7020,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -6114,10 +7095,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6198,6 +7188,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6207,6 +7203,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6216,9 +7218,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6270,12 +7281,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6297,12 +7317,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6354,18 +7386,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6375,6 +7431,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6387,6 +7446,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6405,6 +7467,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6480,6 +7548,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6576,6 +7686,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6585,6 +7701,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6609,12 +7728,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6627,6 +7752,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6675,6 +7803,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6693,6 +7824,9 @@ msgstr[5] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6720,6 +7854,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6735,6 +7875,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6753,6 +7899,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6765,6 +7914,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6786,6 +7938,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6861,6 +8019,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6879,6 +8040,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6909,6 +8073,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6930,6 +8097,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6948,6 +8118,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6972,12 +8145,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -7038,6 +8220,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -7050,6 +8241,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -7074,6 +8274,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -7104,6 +8307,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -7116,15 +8322,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -7134,12 +8334,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -7158,6 +8352,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -7176,6 +8394,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7188,6 +8409,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7221,7 +8445,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7236,6 +8460,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7251,6 +8481,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7290,9 +8523,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7338,9 +8568,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7365,9 +8607,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7386,7 +8625,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7395,6 +8634,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7416,6 +8664,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7476,6 +8736,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7488,6 +8766,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7587,6 +8868,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7611,6 +8895,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7641,6 +8928,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7650,12 +8943,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7671,6 +8973,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7695,6 +9000,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7716,9 +9024,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7734,6 +9039,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7761,6 +9069,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7809,6 +9123,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7824,6 +9141,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7833,6 +9156,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7887,6 +9213,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7902,6 +9231,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7917,7 +9252,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7944,13 +9285,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7968,6 +9309,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -8013,6 +9357,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -8037,9 +9387,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -8061,6 +9408,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -8070,6 +9420,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -8097,6 +9453,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -8118,9 +9477,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -8133,7 +9504,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -8160,6 +9531,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -8181,12 +9555,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8265,6 +9654,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8274,10 +9666,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8298,6 +9693,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8358,6 +9756,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8388,6 +9789,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8397,12 +9807,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8433,6 +9861,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8445,6 +9876,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8466,7 +9906,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8484,12 +9924,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8505,12 +9999,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8538,15 +10038,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8577,6 +10086,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8598,6 +10110,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8610,6 +10125,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8637,6 +10155,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8646,9 +10176,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8658,18 +10194,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8688,9 +10239,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8706,13 +10254,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8727,6 +10278,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8748,6 +10302,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8841,6 +10398,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8886,6 +10446,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8937,6 +10500,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8946,18 +10527,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8967,12 +10590,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -9129,6 +10812,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -9147,16 +10839,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -9165,18 +10863,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9225,9 +10929,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9252,12 +10962,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9282,15 +11034,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9309,24 +11070,45 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9351,6 +11133,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9363,6 +11148,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9372,7 +11160,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9381,25 +11172,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9414,6 +11217,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9444,6 +11265,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9453,7 +11277,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9468,6 +11292,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9507,12 +11334,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9567,6 +11388,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9585,6 +11412,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9624,6 +11454,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9666,6 +11505,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9708,6 +11550,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9792,6 +11640,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9801,6 +11652,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9816,6 +11670,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9828,6 +11685,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9888,9 +11748,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9912,6 +11784,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9987,9 +11862,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -10020,12 +11892,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -10038,6 +11922,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -10065,6 +11955,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -10101,6 +11994,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -10182,6 +12078,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10212,19 +12111,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10242,6 +12144,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10263,6 +12168,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10290,6 +12198,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10305,6 +12225,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10317,9 +12240,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10335,9 +12267,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10395,12 +12324,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10410,6 +12357,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10419,6 +12369,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10488,6 +12441,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10506,6 +12462,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10530,7 +12489,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10542,6 +12501,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10602,6 +12564,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10656,6 +12621,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10728,6 +12699,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10752,6 +12726,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10782,6 +12759,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10842,12 +12825,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10878,6 +12867,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10950,6 +12942,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10974,6 +12969,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10986,6 +13044,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -11016,18 +13080,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -11109,6 +13185,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -11121,6 +13200,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -11136,6 +13218,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -11178,6 +13287,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -11193,6 +13305,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11250,6 +13365,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11268,6 +13392,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11292,9 +13422,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11304,6 +13446,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11313,6 +13458,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11352,6 +13500,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11373,15 +13524,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11415,9 +13581,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11433,6 +13614,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11451,6 +13638,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11463,6 +13653,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11475,18 +13668,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11511,6 +13716,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11523,6 +13734,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11532,22 +13746,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11619,12 +13842,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11697,6 +13914,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11889,6 +14112,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11904,6 +14130,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11970,6 +14199,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -12006,6 +14238,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -12018,9 +14253,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -12030,6 +14271,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -12072,6 +14316,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -12123,15 +14403,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -12141,24 +14436,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -12177,18 +14490,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12258,6 +14586,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12309,6 +14649,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12318,6 +14661,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12336,6 +14682,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12345,6 +14739,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12402,6 +14802,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12417,6 +14820,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12492,6 +15030,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12507,9 +15054,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12555,12 +15120,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12570,6 +15141,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12579,6 +15153,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12606,6 +15183,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12633,6 +15213,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12675,6 +15282,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12693,6 +15303,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12702,6 +15315,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12723,6 +15339,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12732,13 +15351,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12756,6 +15378,9 @@ msgstr[5] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12936,6 +15561,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12951,7 +15579,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12963,6 +15597,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12978,6 +15615,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12996,6 +15639,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -13020,9 +15672,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -13053,12 +15711,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -13068,6 +15735,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -13098,6 +15771,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -13110,6 +15792,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -13122,6 +15807,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -13155,6 +15843,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -13176,27 +15867,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -13230,7 +15945,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13248,6 +15966,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13281,10 +16002,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13299,6 +16023,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13416,6 +16155,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13449,9 +16191,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13467,12 +16206,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13599,9 +16332,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13623,10 +16353,10 @@ msgstr[5] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13668,6 +16398,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13710,9 +16443,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13725,6 +16464,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13749,6 +16494,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13782,6 +16530,12 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13791,6 +16545,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13809,6 +16566,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13839,6 +16599,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13866,7 +16629,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13881,6 +16644,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13935,6 +16701,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13953,18 +16722,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13995,30 +16761,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -14103,15 +16851,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -14241,7 +17004,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -14250,18 +17013,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -14295,12 +17070,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/da_DK/gitlab.po b/locale/da_DK/gitlab.po
index 0741f7e7e87..87b8715e114 100644
--- a/locale/da_DK/gitlab.po
+++ b/locale/da_DK/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Danish\n"
"Language: da_DK\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: da\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:37\n"
+"PO-Revision-Date: 2019-06-14 10:11\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,37 +1459,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1856,6 +2161,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po
index 7bf03d54f8a..5a611c60e8f 100644
--- a/locale/de/gitlab.po
+++ b/locale/de/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: German\n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
@@ -13,19 +13,16 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: de\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:39\n"
+"PO-Revision-Date: 2019-06-14 10:23\n"
msgid " Please sign in."
-msgstr ""
-
-msgid " Status"
-msgstr " Status"
+msgstr " Bitte melde dich an."
msgid " Try to %{action} this file again."
-msgstr ""
+msgstr " Versuche die Datei erneut zu %{action}."
msgid " You need to do this before %{grace_period_deadline}."
-msgstr ""
+msgstr " Das musst du vor %{grace_period_deadline} tun."
msgid " and"
msgstr " und"
@@ -41,18 +38,18 @@ msgstr[0] " um %d Punkt verbessert"
msgstr[1] " um %d Punkte verbessert"
msgid " or "
-msgstr ""
+msgstr " oder "
msgid " or <#epic id>"
-msgstr ""
+msgstr " oder <#epic id>"
msgid " or <#issue id>"
-msgstr ""
+msgstr " oder <#issue id>"
msgid "%d comment"
msgid_plural "%d comments"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Kommentar"
+msgstr[1] "%d Kommentare"
msgid "%d commit"
msgid_plural "%d commits"
@@ -65,7 +62,12 @@ msgstr[0] "%d Commit hinterher"
msgstr[1] "%d Commits hinterher"
msgid "%d commits"
-msgstr ""
+msgstr "%d Commits"
+
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] "%d Beitrag"
+msgstr[1] "%d Beiträge"
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -89,8 +91,8 @@ msgstr[1] "%d Tickets"
msgid "%d issue selected"
msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Ticket ausgewählt"
+msgstr[1] "%d Tickets ausgewählt"
msgid "%d layer"
msgid_plural "%d layers"
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] "%d Merge-Request"
msgstr[1] "%d Merge-Requests"
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d Metrik"
msgstr[1] "%d Metriken"
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] "%d weiterer Kommentar"
+msgstr[1] "%d weiterere Kommentare"
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] "%d vorgemerkte Änderung"
@@ -131,42 +143,45 @@ msgstr "%{authorsName}'s Diskussion"
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} verfasste %{commit_timeago}"
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr "%{counter_storage} (%{counter_repositories} Repositories, %{counter_build_artifacts} Buildartefakte, %{counter_lfs_objects} LFS)"
-
-msgid "%{count} %{alerts}"
-msgstr "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
+msgstr "%{counter_repositories} Repositories, %{counter_wikis} Wikis, %{counter_build_artifacts} Build-Artefakte, %{counter_lfs_objects} LFS"
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} Zustimmung erforderlich von %{name}"
+msgstr[1] "%{count} Zustimmungen erforderlich von %{name}"
msgid "%{count} approvals from %{name}"
-msgstr ""
+msgstr "%{count} Zustimmungen von %{name}"
msgid "%{count} more"
-msgstr ""
+msgstr "%{count} weitere"
msgid "%{count} more assignees"
msgstr "%{count} weitere Zugewiesene"
msgid "%{count} of %{required} approvals from %{name}"
-msgstr ""
+msgstr "%{count} der erforderlichen %{required} Zustimmungen durch %{name}"
msgid "%{count} of %{total}"
-msgstr ""
+msgstr "%{count} von %{total}"
msgid "%{count} participant"
msgid_plural "%{count} participants"
-msgstr[0] "%{count} Teilnehmer"
-msgstr[1] "%{count} Teilnehmer"
+msgstr[0] "%{count} Teilnehmer(in)"
+msgstr[1] "%{count} Teilnehmer(innen)"
msgid "%{count} pending comment"
msgid_plural "%{count} pending comments"
msgstr[0] "%{count} ausstehender Kommentar"
msgstr[1] "%{count} ausstehende Kommentare"
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr "%{edit_in_new_fork_notice} Versuche erneut, diesen Commit zu cherry-picken."
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr "%{edit_in_new_fork_notice} Versuche erneut, diesen Commit rückgängig zu machen."
+
msgid "%{filePath} deleted"
msgstr "%{filePath} gelöscht"
@@ -174,22 +189,34 @@ msgid "%{firstLabel} +%{labelCount} more"
msgstr "%{firstLabel} +%{labelCount} mehr"
msgid "%{gitlab_ci_yml} not found in this commit"
-msgstr ""
+msgstr "%{gitlab_ci_yml} in diesem Commit nicht gefunden"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}Gruppen%{group_docs_link_end} ermöglichen dir die Verwaltung und die Zusammenarbeit über mehrere Projekte hinweg. Mitglieder einer Gruppe haben Zugriff auf alle Projekte darin."
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr "%{group_name} nutzt Accounts, die von einer Gruppe verwaltet werden. Du musst dir einen neuen GitLab-Account erstellen, welcher von %{group_name} verwaltet wird."
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} wird entfernt! Bist du sicher?"
msgid "%{label_for_message} unavailable"
-msgstr ""
+msgstr "%{label_for_message} nicht verfügbar"
+
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} ist eine freie, automatisierte und offene Zertifizierungsstelle (CA), die digitale Zertifikate vergibt, um HTTPS (SSL/TSL) für Webseiten zu ermöglichen."
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr "%{level_name} ist in einer %{group_level_name} -Gruppe nicht erlaubt."
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr "%{level_name} ist nicht zulässig, da das Fork-Quellprojekt eine geringere Sichtbarkeit hat."
msgid "%{level_name} visibility has been restricted by the administrator."
-msgstr ""
+msgstr "%{level_name} Sichtbarkeit wurde vom/von der Administrator(in) eingeschränkt."
msgid "%{link_start}Read more%{link_end} about role permissions"
-msgstr ""
+msgstr "%{link_start}Erfahre mehr%{link_end} über Rollenberechtigungen"
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Gestartet"
@@ -198,7 +225,13 @@ msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} ist durch Gitlab-Benutzer(in) %{lock_user_id} gesperrt"
msgid "%{mrText}, this issue will be closed automatically."
-msgstr ""
+msgstr "%{mrText}, dieses Ticket wird automatisch geschlossen werden."
+
+msgid "%{name} contained %{resultsString}"
+msgstr "%{name} enthielt %{resultsString}"
+
+msgid "%{name} found %{resultsString}"
+msgstr "%{name} gefunden %{resultsString}"
msgid "%{name}'s avatar"
msgstr "Avatar von %{name}"
@@ -213,34 +246,46 @@ msgid "%{percent}%% complete"
msgstr "%{percent}%% abgeschlossen"
msgid "%{service_title} activated."
-msgstr ""
+msgstr "%{service_title} aktiviert."
msgid "%{service_title} settings saved, but not activated."
-msgstr ""
+msgstr "%{service_title} Einstellungen gespeichert, aber nicht aktiviert."
+
+msgid "%{size} GiB"
+msgstr "%{size} GiB"
+
+msgid "%{size} KiB"
+msgstr "%{size} KiB"
+
+msgid "%{size} MiB"
+msgstr "%{size} MiB"
+
+msgid "%{size} bytes"
+msgstr "%{size} Bytes"
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
-msgstr ""
+msgstr "%{spammable_titlecase} wurde erfolgreich an Akismet übermittelt."
msgid "%{state} epics"
-msgstr ""
+msgstr "%{state} Epics"
msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgstr[1] "%{strong_start}%{branch_count}%{strong_end} Branches"
msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgstr[1] "%{strong_start}%{commit_count}%{strong_end} Commits"
msgid "%{strong_start}%{human_size}%{strong_end} Files"
-msgstr ""
+msgstr "%{strong_start}%{human_size}%{strong_end} Dateien"
msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgstr[1] "%{strong_start}%{tag_count}%{strong_end} Tags"
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
@@ -250,6 +295,9 @@ msgstr[1] "%{text} %{files} Dateien"
msgid "%{text} is available"
msgstr "%{text} ist verfügbar"
+msgid "%{title} %{operator} %{threshold}"
+msgstr "%{title} %{operator} %{threshold}"
+
msgid "%{title} changes"
msgstr "%{title} Änderungen"
@@ -260,13 +308,33 @@ msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what infor
msgstr "%{usage_ping_link_start}Erfahre mehr%{usage_ping_link_end} darüber, welche Informationen mit GitLab Inc. geteilt werden."
msgid "%{user_name} profile page"
+msgstr "Profileseite von %{user_name}"
+
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr "%{verb} %{time_spent_value} verbrachte Zeit."
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr "'%{level}' ist kein gültiger Sichtbarkeitslevel"
+
+msgid "'%{source}' is not a import source"
+msgstr "'%{source}' ist keine Import-Quelle"
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
msgstr ""
msgid "(No changes)"
-msgstr ""
+msgstr "(Keine Änderungen)"
+
+msgid "(check progress)"
+msgstr "(Fortschritt überprüfen)"
msgid "(external source)"
-msgstr ""
+msgstr "(externe Quelle)"
msgid "+ %{count} more"
msgstr "+ %{count} weitere"
@@ -275,10 +343,10 @@ msgid "+ %{moreCount} more"
msgstr "+ %{moreCount} weitere"
msgid "+%{extraOptionCount} more"
-msgstr ""
+msgstr "+%{extraOptionCount} weitere"
msgid ", or "
-msgstr ""
+msgstr ", oder "
msgid "- Runner is active and can process any new jobs"
msgstr "- Prozessor ist aktiv und kann neue Jobs verarbeiten"
@@ -289,6 +357,9 @@ msgstr "- Runner ist angehalten und wird keine neuen Aufgaben entgegennehmen"
msgid "- show less"
msgstr "- weniger anzeigen"
+msgid "0 for unlimited"
+msgstr "0 für unbegrenzt"
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] "1 %{type} Zusatz"
@@ -301,21 +372,21 @@ msgstr[1] "%{count} %{type} Änderungen"
msgid "1 Day"
msgid_plural "%d Days"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 Tag"
+msgstr[1] "%d Tage"
msgid "1 closed issue"
-msgid_plural "%d closed issues"
-msgstr[0] "1 geschlossenes Ticket"
-msgstr[1] "%d geschlossene Tickets"
+msgid_plural "%{issues} closed issues"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
-msgstr[0] "1 geschlossener Merge-Request"
-msgstr[1] "%d geschlossene Merge-Requests"
+msgid_plural "%{merge_requests} closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 day"
-msgstr ""
+msgstr "1 Tag"
msgid "1 group"
msgid_plural "%d groups"
@@ -323,19 +394,19 @@ msgstr[0] "Eine Gruppe"
msgstr[1] "%d Gruppen"
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
-msgstr[0] "1 zusammengeführter Merge-Request"
-msgstr[1] "%d zusammengeführte Merge-Requests"
+msgid_plural "%{merge_requests} merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
-msgstr[0] "1 offenes Ticket"
-msgstr[1] "%d offene Tickets"
+msgid_plural "%{issues} open issues"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
-msgstr[0] "1 offener Merge-Request"
-msgstr[1] "%d offene Merge-Requests"
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 pipeline"
msgid_plural "%d pipelines"
@@ -353,28 +424,43 @@ msgstr[0] "1 Benutzer(in)"
msgstr[1] "%d Benutzer(innen)"
msgid "1 week"
-msgstr ""
+msgstr "1 Woche"
+
+msgid "1-9 contributions"
+msgstr "1-9 Beiträge"
+
+msgid "10-19 contributions"
+msgstr "10-19 Beiträge"
msgid "1st contribution!"
msgstr "Erster Beitrag!"
+msgid "20-29 contributions"
+msgstr "20-29 Beiträge"
+
msgid "2FA"
-msgstr ""
+msgstr "2FA"
msgid "2FA enabled"
msgstr "Zwei-Faktor-Authentifizierung aktiviert"
-msgid "3 days"
+msgid "2FADevice|Registered On"
msgstr ""
+msgid "3 days"
+msgstr "3 Tage"
+
msgid "3 hours"
-msgstr ""
+msgstr "3 Stunden"
msgid "30 minutes"
-msgstr ""
+msgstr "30 Minuten"
+
+msgid "30+ contributions"
+msgstr "30+ Beiträge"
msgid "403|Please contact your GitLab administrator to get permission."
-msgstr ""
+msgstr "Bitte kontaktiere deine(n) GitLab-Administrator(in) um die Erlaubnis zu erhalten."
msgid "403|You don't have the permission to access this page."
msgstr "Du hast nicht die Berechtigung auf diese Seite zuzugreifen."
@@ -389,7 +475,7 @@ msgid "404|Please contact your GitLab administrator if you think this is a mista
msgstr "Bitte kontaktiere deine(n) GitLab-Administrator(in), wenn du denkst, dass dies ein Fehler ist."
msgid "8 hours"
-msgstr ""
+msgstr "8 Stunden"
msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
msgstr "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> fügt allen von johnsmith@example.com erstellten Tickets und Kommentaren \"Von <a href=\"#\">@johnsmith</a>\" hinzu und setzt <a href=\"#\">@johnsmith</a> als Zuständigen für alle Tickets die ursprünglich johnsmith@example.com zugewiesen waren."
@@ -403,6 +489,9 @@ msgstr "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> fügt
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> fügt \"Von <a href=\"#\">johnsmith@example.com</a>\" zu allen Tickets und Kommentaren hinzu, die ursprünglich von johnsmith@example.com erstellt wurden. Standardmäßig wird die E-Mail-Adresse maskiert, um den Datenschutz des Nutzers zu gewährleisten. Nutze diese Option, wenn du die volle E-Mail-Adresse anzeigen willst."
+msgid "<no name set>"
+msgstr "<no name set>"
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr "<strong>%{changedFilesLength} nicht vorgemerkte</strong> und <strong>%{stagedFilesLength} vorgemerkte</strong> Änderungen"
@@ -419,25 +508,28 @@ msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong>
msgstr "<strong>%{pushes}</strong> Pushes, mehr als <strong>%{commits}</strong> Commits von <strong>%{people}</strong> Mitwirkenden."
msgid "<strong>Deletes</strong> source branch"
-msgstr ""
+msgstr "<strong>Löscht</strong> den Quellbranch"
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr "Ein 'Runner' ist ein Prozess, welcher ein Job ausführt. Du kannst so viele Runner erstellen wie du benötigst."
msgid "A .NET Core console application template, customizable for any .NET Core project"
-msgstr ""
+msgstr "Eine .NET Core-Konsolenanwendungsvorlage, anpassbar für jedes .NET Core-Projekt"
msgid "A GitBook site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr ""
+msgstr "Eine GitBook-Seite, welche statt GitLab Netlify für CI/CD nutzt, aber trotzdem von all den anderen nützlichen GitLab-Funktionen profitiert."
msgid "A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr ""
+msgstr "Eine Hexo-Seite, die statt GitLab Netlify für CI/CD nutzt, aber trotzdem von all den anderen nützlichen GitLab-Funktionen profitiert."
msgid "A Hugo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr ""
+msgstr "Eine Hugo-Seite, die statt GitLab Netlify für CI/CD nutzt, aber trotzdem von all den anderen nützlichen GitLab-Funktionen profitiert."
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr ""
+msgstr "Eine Jekyll-Seite, die statt GitLab Netlify für CI/CD nutzt, aber trotzdem von all den anderen nützlichen GitLab-Funktionen profitiert."
+
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
+msgstr "Ein Let's Encrypt-Konto wird für diese GitLab-Installation mit deiner E-Mail-Adresse konfiguriert. Du erhältst E-Mails, um vor dem Ablaufen der Zertifikate zu warnen."
msgid "A default branch cannot be chosen for an empty project."
msgstr "Ein Default-Branch kann nicht für ein leeres Projekt ausgewählt werden."
@@ -445,32 +537,29 @@ msgstr "Ein Default-Branch kann nicht für ein leeres Projekt ausgewählt werden
msgid "A deleted user"
msgstr "Ein(e) gelöschte(r) Benutzer(in)"
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr "Ein Mitglied des GitLab-Missbrauchsteams wird deinen Bericht so schnell wie möglich überprüfen."
-
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
-msgstr ""
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
+msgstr "Ein Fork ist eine Kopie eines Projekts.<br />Wenn du ein Repository forkst, kannst du, ohne Auswirkungen auf das ursprüngliche Projekt, Änderungen vornehmen."
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr "Ein neuer Branch wird in deinem Fork erzeugt und ein neuer Merge-Request wird gestartet."
msgid "A new impersonation token has been created."
-msgstr ""
+msgstr "Eine neuer Identitätswechsel-Token wurde erstellt."
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr ""
+msgstr "Eine einfache HTML-Seite, welche statt GitLab Netlify für CI/CD nutzt, aber trotzdem von all den anderen nützlichen GitLab-Funktionen profitiert."
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr "In einem Projekt speicherst du deine Dateien (Repository), planst deine Arbeit (Tickets) und veröffentlichst deine Dokumentation (Wiki), %{among_other_things_link}."
msgid "A ready-to-go template for use with Android apps."
-msgstr ""
+msgstr "Eine gebrauchsfertige Vorlage zur Nutzung mit Android-Apps."
msgid "A ready-to-go template for use with iOS Swift apps."
-msgstr ""
+msgstr "Eine gebrauchsfertige Vorlage zur Nutzung mit iOS Swift-Apps."
msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
msgstr "Ein regulärer Ausdruck, um die Ausgabe der Testabdeckung in der Fehlerprotokollierung des Jobs zu finden. Zum Deaktivieren leer lassen"
@@ -479,7 +568,10 @@ msgid "A user with write access to the source branch selected this option"
msgstr "Ein(e) Benutzer(in) mit Schreibzugriff auf den Quellbranch hat diese Option ausgewählt"
msgid "API Help"
-msgstr ""
+msgstr "API-Hilfe"
+
+msgid "API Token"
+msgstr "API Token"
msgid "About GitLab"
msgstr "Ãœber GitLab"
@@ -500,7 +592,7 @@ msgid "Abuse reports"
msgstr "Missbrauchsmeldungen"
msgid "Accept invitation"
-msgstr ""
+msgstr "Einladung annehmen"
msgid "Accept terms"
msgstr "Bedingungen akzeptieren"
@@ -512,7 +604,7 @@ msgid "Access Tokens"
msgstr "Zugangs-Token"
msgid "Access denied for your LDAP account."
-msgstr ""
+msgstr "Zugriff für dein LDAP-Konto verweigert."
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "Zugriff abgelehnt! Stelle sicher, dass du diesem Repository Bereitstellungsschlüssel hinzufügen kannst."
@@ -521,22 +613,34 @@ msgid "Access expiration date"
msgstr "Zugriff auf das Ablaufdatum"
msgid "Access forbidden. Check your access level."
-msgstr ""
+msgstr "Zugriff verboten. Überprüfe deine Zugriffsebene."
msgid "Access to '%{classification_label}' not allowed"
msgstr "Zugriff auf '%{classification_label}' nicht erlaubt"
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr "Konto"
msgid "Account and limit"
msgstr "Konto und Limit"
+msgid "Account: %{account}"
+msgstr "Konto: %{account}"
+
msgid "Action to take when receiving an alert."
-msgstr ""
+msgstr "Aktion beim Empfang eines Alarms."
msgid "Activate Service Desk"
-msgstr ""
+msgstr "Service-Desk aktivieren"
msgid "Active"
msgstr "Aktiv"
@@ -551,10 +655,10 @@ msgid "Add"
msgstr "Hinzufügen"
msgid "Add CHANGELOG"
-msgstr ""
+msgstr "CHANGELOG hinzufügen"
msgid "Add CONTRIBUTING"
-msgstr ""
+msgstr "CONTRIBUTING hinzufügen"
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr "Gruppen-Webhooks und GitLab Enterprise Edition hinzufügen."
@@ -566,58 +670,76 @@ msgid "Add Kubernetes cluster"
msgstr "Kubernetes-Cluster hinzufügen"
msgid "Add README"
-msgstr ""
+msgstr "README hinzufügen"
+
+msgid "Add a GPG key"
+msgstr "GPG-Schlüssel hinzufügen"
msgid "Add a bullet list"
-msgstr ""
+msgstr "Aufzählungsliste hinzufügen"
msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
+msgstr "Trage einen allgemeinen Kommentar zu diesem %{noteable_name} bei."
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr "Füge zu deinem Wiki eine Startseite mit Informationen zu deinem GitLab-Project hinzu und GitLab wird sie hier anstatt dieser Meldung anzeigen."
msgid "Add a link"
-msgstr ""
+msgstr "Einen Link hinzufügen"
msgid "Add a numbered list"
-msgstr ""
+msgstr "Eine nummerierte Liste hinzufügen"
msgid "Add a table"
msgstr "Tabelle hinzufügen"
msgid "Add a task list"
-msgstr ""
+msgstr "Eine Aufgabenliste hinzufügen"
+
+msgid "Add a todo"
+msgstr "To-do hinzufügen"
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Füge zusätzlichen Text hinzu, der in jeglicher E-Mail-Kommunikation angezeigt wird. Maximal %{character_limit} Zeichen"
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr "SSH-Schlüssel hinzufügen"
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
-msgstr ""
+msgstr "Genehmigungsberechtigte hinzufügen"
msgid "Add bold text"
-msgstr ""
+msgstr "Fetten Text hinzufügen"
+
+msgid "Add child epic to an epic"
+msgstr "Sub-Epic hinzufügen"
msgid "Add comment now"
msgstr "Jetzt kommentieren"
-msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
+msgid "Add email address"
msgstr ""
+msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
+msgstr "Kopf- und Fußzeile zu E-Mails hinzufügen. Bitte beachte, dass Farbeinstellungen nur innerhalb des Anwendungs-Interfaces angewendet werden"
+
msgid "Add image comment"
msgstr "Bildkommentar hinzufügen"
msgid "Add italic text"
-msgstr ""
+msgstr "Kursiven Text hinzufügen"
+
+msgid "Add label(s)"
+msgstr "Label(s) hinzufügen"
msgid "Add license"
msgstr "Lizenz hinzufügen"
msgid "Add list"
-msgstr ""
+msgstr "Liste hinzufügen"
msgid "Add new application"
msgstr "Neue Anwendung hinzufügen"
@@ -625,12 +747,21 @@ msgstr "Neue Anwendung hinzufügen"
msgid "Add new directory"
msgstr "Erstelle eine neues Verzeichnis"
+msgid "Add or subtract spent time"
+msgstr "Addiere oder subtrahiere verbrachte Zeit"
+
msgid "Add reaction"
msgstr "Reaktion hinzufügen"
-msgid "Add to project"
+msgid "Add to merge train"
msgstr ""
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
+msgid "Add to project"
+msgstr "Zum Projekt hinzufügen"
+
msgid "Add to review"
msgstr "Zum Review hinzufügen"
@@ -640,23 +771,35 @@ msgstr "To-do hinzufügen"
msgid "Add user(s) to the group:"
msgstr "Benutzer(innen) zur Gruppe hinzufügen:"
-msgid "Add users or groups who are allowed to approve every merge request"
-msgstr ""
-
msgid "Add users to group"
msgstr "Füge Benutzer(innen) zur Gruppe hinzu"
+msgid "AddMember|No users specified."
+msgstr "Keine Benutzer(innen) angegeben."
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
+msgstr "Zu viele Benutzer(innen) angegeben (Limit ist %{user_limit})"
+
msgid "Added at"
-msgstr ""
+msgstr "Hinzugefügt um"
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr "Das Hinzufügen neuer Anwendungen ist in deiner GitLab-Instanz deaktiviert. Bitte kontaktiere deine(n) GitLab-Administrator(in), um die Berechtigung zu erhalten"
+msgid "Additional minutes"
+msgstr "Zusätzliche Minuten"
+
msgid "Additional text"
msgstr "Zusätzlicher Text"
-msgid "Aditional minutes"
-msgstr ""
+msgid "Adds"
+msgstr "Fügt hinzu"
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr "Fügt %{epic_ref} als Sub-Epic hinzu."
+
+msgid "Adds a todo."
+msgstr "Fügt ein To-do hinzu."
msgid "Admin Area"
msgstr "Adminbereich"
@@ -665,7 +808,10 @@ msgid "Admin Overview"
msgstr "Admin-Ãœbersicht"
msgid "Admin Section"
-msgstr ""
+msgstr "Admin-Bereich"
+
+msgid "Admin notes"
+msgstr "Admin-Notizen"
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr "Du bist gerade dabei den/die Benutzer(in) %{username} dauerhaft zu löschen. Tickets, Merge-Requests und Gruppen, die mit ihm/ihr verknüpft sind, werden einem systemweiten \"Ghost-user\" zugewiesen. Um Datenverlust zu vermeiden, ziehe in Erwägung stattdessen die Funktion %{strong_start}Benutzer(in) blockieren%{strong_end} zu verwenden. Nachdem du %{strong_start}Benutzer(in) entfernen%{strong_end} ausgeführt hast, kann es nicht rückgängig gemacht oder der/die Benutzer(in) wiederhergestellt werden."
@@ -688,6 +834,9 @@ msgstr "Stoppen von Jobs ist fehlgeschlagen"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "Du bist dabei, alle Jobs zu stoppen. Dies hält alle aktuellen Jobs, die ausgeführt werden, an."
+msgid "AdminNote|Note"
+msgstr "Notiz"
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr "Du bist gerade dabei das Projekt %{projectName}, sein Repository und alle verknüpften Ressourcen einschließlich Tickets, Merge-Requests, etc. zu löschen. Nachdem du %{strong_start}Projekt entfernen%{strong_end} ausgeführt hast, kann es nicht rückgängig gemacht oder wiederhergestellt werden."
@@ -701,43 +850,43 @@ msgid "AdminProjects|Delete project"
msgstr "Projekt löschen"
msgid "AdminSettings|Auto DevOps domain"
-msgstr ""
+msgstr "Auto-DevOps-Domain"
msgid "AdminSettings|Enable shared runners for new projects"
-msgstr ""
+msgstr "'Shared Runners' für neue Projekte aktivieren"
msgid "AdminSettings|Environment variables are protected by default"
-msgstr ""
+msgstr "Umgebungsvariablen sind standardmäßig geschützt"
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
-msgstr "Gib eine Domäne an, die standardmäßig für die Auto-Review-Anwendungen- und Auto-Bereitstsellungs-Phasen jedes Projekts verwendet werden soll."
+msgstr "Gib eine Domain an, die standardmäßig für die Auto-Review-Anwendungen- und Auto-Bereitstsellungs-Phasen jedes Projekts verwendet werden soll."
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
-msgstr ""
+msgstr "Eine neu erstellte Umgebungsvariable ist standardmäßig geschützt."
msgid "AdminUsers|2FA Disabled"
-msgstr ""
+msgstr "2FA deaktiviert"
msgid "AdminUsers|2FA Enabled"
-msgstr ""
+msgstr "2FA aktiviert"
msgid "AdminUsers|Active"
-msgstr ""
+msgstr "Aktiv"
msgid "AdminUsers|Admin"
-msgstr ""
+msgstr "Admin"
msgid "AdminUsers|Admins"
-msgstr ""
+msgstr "Admins"
msgid "AdminUsers|Block user"
msgstr "Benutzer(in) blockieren"
msgid "AdminUsers|Blocked"
-msgstr ""
+msgstr "Blockiert"
msgid "AdminUsers|Cannot unblock LDAP blocked users"
-msgstr ""
+msgstr "Kann gesperrte LDAP-Benutzer(innen) nicht entsperren"
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr "Benutzer(in) %{username} und seine/ihre Beiträge löschen?"
@@ -752,28 +901,28 @@ msgid "AdminUsers|Delete user and contributions"
msgstr "Benutzer(in) und Beiträge löschen"
msgid "AdminUsers|External"
-msgstr ""
+msgstr "Extern"
msgid "AdminUsers|It's you!"
-msgstr ""
+msgstr "Das bist du!"
msgid "AdminUsers|New user"
-msgstr ""
+msgstr "Neue(r) Benutzer(in)"
msgid "AdminUsers|No users found"
-msgstr ""
+msgstr "Keine Benutzer(innen) gefunden"
msgid "AdminUsers|Search by name, email or username"
-msgstr ""
+msgstr "Suche nach Name, E-Mail oder Benutzername"
msgid "AdminUsers|Search users"
-msgstr ""
+msgstr "Benutzer(innen) suchen"
msgid "AdminUsers|Send email to users"
-msgstr ""
+msgstr "E-Mail an Benutzer(innen) senden"
msgid "AdminUsers|Sort by"
-msgstr ""
+msgstr "Sortiert nach"
msgid "AdminUsers|To confirm, type %{projectName}"
msgstr "Zur Bestätigung %{projectName} eingeben"
@@ -782,24 +931,27 @@ msgid "AdminUsers|To confirm, type %{username}"
msgstr "Zur Bestätigung %{username} eingeben"
msgid "AdminUsers|User will be blocked"
-msgstr ""
+msgstr "Benutzer(in) wird gesperrt"
msgid "AdminUsers|Without projects"
-msgstr ""
+msgstr "Ohne Projekte"
msgid "Advanced"
-msgstr ""
+msgstr "Erweitert"
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr "Erweiterte Berechtigungen, Large File Storage und Einstellungen zur Zwei-Faktor-Authentifizierung."
msgid "Advanced search functionality"
-msgstr ""
+msgstr "Erweiterte Suchfunktion"
msgid "Advanced settings"
msgstr "Erweiterte Einstellungen"
msgid "After a successful password update you will be redirected to login screen."
+msgstr "Nach dem erfolgreichen Ändern des Passwortes wirst du zum Anmeldebildschirm weitergeleitet."
+
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
msgid "Alert"
@@ -808,49 +960,58 @@ msgstr[0] "Alarm"
msgstr[1] "Alarme"
msgid "Alerts"
-msgstr ""
+msgstr "Alarme"
msgid "All"
msgstr "Alle"
msgid "All Members"
-msgstr ""
+msgstr "Alle Mitglieder"
msgid "All changes are committed"
msgstr "Alle Änderungen sind committed"
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Alle Features sind für leere Projekte, Vorlagen, oder beim Import aktiviert. Du kannst sie aber danach in den Projekteinstellungen deaktivieren."
-msgid "All issues for this milestone are closed. You may close this milestone now."
+msgid "All groups and projects"
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr "Alle Tickets für diesen Meilenstein sind geschlossen. Du kannst diesen Meilenstein jetzt schließen."
+
msgid "All merge conflicts were resolved. The merge request can now be merged."
-msgstr ""
+msgstr "Alle Merge-Konflikte wurden gelöst. Der Merge-Request kann nun gemerged werden."
+
+msgid "All projects"
+msgstr "Alle Projekte"
msgid "All todos were marked as done."
-msgstr ""
+msgstr "Alle To-dos wurden als erledigt markiert."
msgid "All users"
msgstr "Alle Benutzer(innen)"
msgid "All users must have a name."
-msgstr ""
+msgstr "Alle Benutzer(innen) benötigen einen Namen."
msgid "Allow \"%{group_name}\" to sign you in"
-msgstr ""
+msgstr "Erlaube \"%{group_name}\" dich anzumelden"
msgid "Allow commits from members who can merge to the target branch."
msgstr "Erlaube Commits von Mitgliedern die zum Zielbranch mergen können."
msgid "Allow group owners to manage LDAP-related settings"
-msgstr ""
+msgstr "Gruppenbesitzer erlauben, LDAP-bezogene Einstellungen zu verwalten"
msgid "Allow mirrors to be set up for projects"
-msgstr ""
+msgstr "Lass zu, dass Mirrors für Projekte eingerichtet werden"
msgid "Allow only the selected protocols to be used for Git access."
-msgstr ""
+msgstr "Nur die ausgewählten Protokolle für den Git-Zugriff zulassen."
msgid "Allow projects within this group to use Git LFS"
msgstr "Erlaube es Projekten in dieser Gruppe Git LFS zu verwenden"
@@ -865,10 +1026,10 @@ msgid "Allow requests to the local network from hooks and services."
msgstr "Erlaube Anfragen an das lokale Netzwerk von Hooks und Diensten."
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
-msgstr ""
+msgstr "Diesem Schlüssel auch erlauben, in das Repository zu pushen? (Normalerweise ist nur Pull-Zugriff erlaubt)"
msgid "Allow users to register any application to use GitLab as an OAuth provider"
-msgstr ""
+msgstr "Erlaube Benutzer(innen), jede Anwendung zur Nutzung von GitLab als OAuth-Anbieter zu registrieren"
msgid "Allow users to request access"
msgstr "Erlaube es Benutzer(innen) Zugriff zu beantragen"
@@ -877,7 +1038,7 @@ msgid "Allow users to request access if visibility is public or internal."
msgstr "Erlaube es Benutzer(innen) Zugriff zu beantragen, wenn die Sichtbarkeit Öffentlich oder Intern ist."
msgid "Allowed to fail"
-msgstr ""
+msgstr "Scheitern erlaubt"
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Ermöglicht dir das Hinzufügen und Verwalten von Kubernetes-Clustern."
@@ -889,7 +1050,7 @@ msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr "Wird auch \"Relying-Party-Service-URL\" oder \"Antwort-URL\" genannt"
msgid "Alternate support URL for help page"
-msgstr ""
+msgstr "Alternative Support-URL für die Hilfe-Seite"
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr "Alternativ kannst du einen %{personal_access_token_link} verwenden. Wenn du deinen persönlichen Access-Token erzeugst, musst du den Gültigkeitsbereich <code>repo</code> auswählen, damit wir eine Liste deiner öffentlichen und privaten Repositories anzeigen können, die für die Verbindung verfügbar sind."
@@ -900,9 +1061,6 @@ msgstr "Alternativ kannst du einen %{personal_access_token_link} verwenden. Wenn
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr "Dauer (in Stunden), für die der/die Benutzer(in) die erzwungene Konfiguration der Zwei-Faktor-Authentifizierung überspringen darf"
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr "Beim Absenden des Formulars wird automatisch ein SSH-Schlüssel generiert. Weitere Informationen findest du in der Dokumentation."
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr "Eine Anwendung namens %{link_to_client} fordert Zugriff auf dein GitLab-Konto an."
@@ -919,16 +1077,16 @@ msgid "An error occurred adding a new draft."
msgstr "Beim Hinzufügen eines neuen Entwurfs ist ein Fehler aufgetreten."
msgid "An error occurred creating the new branch."
-msgstr ""
+msgstr "Beim Anlegen des neuen Branches ist ein Fehler aufgetreten."
msgid "An error occurred fetching the approval rules."
-msgstr ""
+msgstr "Beim Abrufen der Genehmigungsregeln ist ein Fehler aufgetreten."
msgid "An error occurred fetching the approvers for the new rule."
-msgstr ""
+msgstr "Beim Abrufen der Genehmigungsberechtigten für die neue Regel ist ein Fehler aufgetreten."
msgid "An error occurred fetching the dropdown data."
-msgstr ""
+msgstr "Beim Abrufen der Dropdown-Daten ist ein Fehler aufgetreten."
msgid "An error occurred previewing the blob"
msgstr "Bei der Vorschau des Blobs ist ein Fehler aufgetreten"
@@ -936,14 +1094,17 @@ msgstr "Bei der Vorschau des Blobs ist ein Fehler aufgetreten"
msgid "An error occurred when toggling the notification subscription"
msgstr "Beim Umschalten des Benachrichtigungs-Abonnements trat ein Fehler auf"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr "Beim Versuch, einen Kommentar zu lösen, ist ein Fehler aufgetreten. Bitte versuche es erneut."
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr "Beim Versuch, eine Diskussion zu lösen, ist ein Fehler aufgetreten. Bitte versuche es erneut."
+
msgid "An error occurred when updating the issue weight"
msgstr "Beim Aktualisieren der Ticket-Gewichtung ist ein Fehler aufgetreten"
-msgid "An error occurred while adding approver"
-msgstr "Beim Hinzufügen eines Genehmigungsberechtigten ist ein Fehler aufgetreten"
-
msgid "An error occurred while deleting the approvers group"
-msgstr ""
+msgstr "Beim Löschen der Genehmigungsberechtigten-Gruppe trat ein Fehler auf"
msgid "An error occurred while deleting the comment"
msgstr "Beim Löschen des Kommentars ist ein Fehler aufgetreten"
@@ -952,7 +1113,7 @@ msgid "An error occurred while detecting host keys"
msgstr "Bei der Erkennung von Hostschlüsseln ist ein Fehler aufgetreten"
msgid "An error occurred while disabling Service Desk."
-msgstr ""
+msgstr "Beim Deaktivieren des Service-Desks ist ein Fehler aufgetreten."
msgid "An error occurred while dismissing the alert. Refresh the page and try again."
msgstr "Beim Ausblenden des Alarms ist ein Fehler aufgetreten. Aktualisiere die Seite und versuche es erneut."
@@ -961,22 +1122,37 @@ msgid "An error occurred while dismissing the feature highlight. Refresh the pag
msgstr "Beim Ausblenden des Feature-Highlights ist ein Fehler aufgetreten. Aktualisiere die Seite und versuche es erneut auszublenden."
msgid "An error occurred while enabling Service Desk."
+msgstr "Beim Aktivieren des Service-Desks ist ein Fehler aufgetreten."
+
+msgid "An error occurred while fetching environments."
msgstr ""
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr "Beim Abrufen der Label-Farben ist ein Fehler aufgetreten."
+
msgid "An error occurred while fetching markdown preview"
msgstr "Beim Abrufen der Markdown-Vorschau ist ein Fehler aufgetreten"
msgid "An error occurred while fetching pending comments"
msgstr "Beim Abrufen der ausstehenden Kommentare ist ein Fehler aufgetreten"
+msgid "An error occurred while fetching projects autocomplete."
+msgstr "Beim Abrufen der Projekt-Autovervollständigung ist ein Fehler aufgetreten."
+
msgid "An error occurred while fetching sidebar data"
msgstr "Während des Abrufens der Daten für die Seitenleiste ist ein Fehler aufgetreten"
-msgid "An error occurred while fetching stages."
-msgstr "Beim Abrufen der Phasen ist ein Fehler aufgetreten."
-
msgid "An error occurred while fetching the Service Desk address."
-msgstr ""
+msgstr "Beim Abrufen der Service-Desk-Adresse ist ein Fehler aufgetreten."
+
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr "Beim Abrufen der Board-Listen ist ein Fehler aufgetreten. Bitte versuche es erneut."
+
+msgid "An error occurred while fetching the builds."
+msgstr "Beim Abrufen der Builds ist ein Fehler aufgetreten."
msgid "An error occurred while fetching the job log."
msgstr "Beim Abrufen des Jobprotokolls ist ein Fehler aufgetreten."
@@ -991,7 +1167,10 @@ msgid "An error occurred while fetching the pipeline."
msgstr "Beim Abrufen der Pipeline ist ein Fehler aufgetreten."
msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
+msgstr "Beim Abrufen der Releases ist ein Fehler aufgetreten. Bitte versuche es erneut."
+
+msgid "An error occurred while fetching this tab."
+msgstr "Beim Abrufen des Tabs ist ein Fehler aufgetreten."
msgid "An error occurred while getting projects"
msgstr "Beim Abrufen der Projekte ist ein Fehler aufgetreten"
@@ -1009,7 +1188,7 @@ msgid "An error occurred while loading commit signatures"
msgstr "Beim Laden der Commit-Signaturen ist ein Fehler aufgetreten"
msgid "An error occurred while loading designs. Please try again."
-msgstr ""
+msgstr "Beim Laden der Designs ist ein Fehler aufgetreten. Bitte versuche es erneut."
msgid "An error occurred while loading diff"
msgstr "Beim Laden des Diffs ist ein Fehler aufgetreten"
@@ -1021,19 +1200,22 @@ msgid "An error occurred while loading the file"
msgstr "Beim Laden der Datei ist ein Fehler aufgetreten"
msgid "An error occurred while loading the subscription details."
-msgstr ""
+msgstr "Beim Laden der Abonnementdetails ist ein Fehler aufgetreten."
msgid "An error occurred while making the request."
msgstr "Beim Bearbeiten der Anfrage ist ein Fehler aufgetreten."
-msgid "An error occurred while removing approver"
-msgstr "Beim Löschen eines Genehmigungsberechtigten ist ein Fehler aufgetreten"
+msgid "An error occurred while moving the issue."
+msgstr "Beim Verschieben des Tickets ist ein Fehler aufgetreten."
+
+msgid "An error occurred while parsing recent searches"
+msgstr "Beim Parsen der letzten Suchen ist ein Fehler aufgetreten"
msgid "An error occurred while removing epics."
-msgstr ""
+msgstr "Beim Entfernen des Epics ist ein Fehler aufgetreten."
msgid "An error occurred while removing issues."
-msgstr ""
+msgstr "Beim Entfernen der Tickets ist ein Fehler aufgetreten."
msgid "An error occurred while rendering KaTeX"
msgstr "Beim Erstellen der Vorschau für KaTeX trat ein Fehler auf"
@@ -1054,7 +1236,7 @@ msgid "An error occurred while saving assignees"
msgstr "Beim Speichern der Zuweisungen ist ein Fehler aufgetreten"
msgid "An error occurred while saving the approval settings"
-msgstr ""
+msgstr "Beim Speichern der Genehmigungseinstellungen ist ein Fehler aufgetreten"
msgid "An error occurred while subscribing to notifications."
msgstr "Beim Abonnieren von Benachrichtigungen ist ein Fehler aufgetreten."
@@ -1063,7 +1245,7 @@ msgid "An error occurred while unsubscribing to notifications."
msgstr "Beim Abbestellen der Benachrichtigungen ist ein Fehler aufgetreten."
msgid "An error occurred while updating approvers"
-msgstr ""
+msgstr "Beim Ändern der Genehmigungsberechtigten ist ein Fehler aufgetreten"
msgid "An error occurred while updating the comment"
msgstr "Beim Aktualisieren des Kommentars ist ein Fehler aufgetreten"
@@ -1072,58 +1254,61 @@ msgid "An error occurred while validating username"
msgstr "Beim Validieren des Benutzernamens ist ein Fehler aufgetreten"
msgid "An error occurred whilst committing your changes."
-msgstr ""
+msgstr "Beim Committen deiner Änderungen ist ein Fehler aufgetreten."
msgid "An error occurred whilst fetching the job trace."
msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
-msgstr ""
+msgstr "Beim Abrufen der neuesten Pipeline ist ein Fehler aufgetreten."
+
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr "Beim Abrufen der Dateien für - %{branchId} ist ein Fehler aufgetreten"
msgid "An error occurred whilst loading all the files."
-msgstr ""
+msgstr "Beim Laden aller Dateien ist ein Fehler aufgetreten."
msgid "An error occurred whilst loading the file content."
-msgstr ""
+msgstr "Beim Laden des Dateiinhalts ist ein Fehler aufgetreten."
msgid "An error occurred whilst loading the file."
-msgstr ""
+msgstr "Beim Laden der Datei ist ein Fehler aufgetreten."
msgid "An error occurred whilst loading the merge request changes."
-msgstr ""
+msgstr "Beim Laden der Merge-Request-Änderungen ist ein Fehler aufgetreten."
msgid "An error occurred whilst loading the merge request version data."
-msgstr ""
+msgstr "Beim Laden der Versionsdaten des Merge-Requests ist ein Fehler aufgetreten."
msgid "An error occurred whilst loading the merge request."
-msgstr ""
+msgstr "Beim Laden des Merge-Requests ist ein Fehler aufgetreten."
msgid "An error occurred whilst loading the pipelines jobs."
-msgstr ""
+msgstr "Beim Laden der Pipeline-Jobs ist ein Fehler aufgetreten."
msgid "An error occurred. Please try again."
msgstr "Ein Fehler ist aufgetreten. Bitte versuche es erneut."
msgid "An unexpected error occurred while checking the project environment."
-msgstr ""
+msgstr "Beim Überprüfen der Projektumgebung ist ein unerwarteter Fehler aufgetreten."
msgid "An unexpected error occurred while checking the project runners."
-msgstr ""
+msgstr "Beim Überprüfen der Projekt-Runner ist ein unerwarteter Fehler aufgetreten."
msgid "An unexpected error occurred while communicating with the Web Terminal."
-msgstr ""
+msgstr "Bei der Kommunikation mit dem Web-Terminal ist ein unerwarteter Fehler aufgetreten."
msgid "An unexpected error occurred while starting the Web Terminal."
-msgstr ""
+msgstr "Beim Starten des Web-Terminals ist ein unerwarteter Fehler aufgetreten."
msgid "An unexpected error occurred while stopping the Web Terminal."
-msgstr ""
+msgstr "Beim Beenden des Web-Terminals ist ein unerwarteter Fehler aufgetreten."
msgid "Analytics"
msgstr "Analysen"
msgid "Ancestors"
-msgstr ""
+msgstr "Vorfahren"
msgid "Anonymous"
msgstr "Anonym"
@@ -1137,16 +1322,28 @@ msgstr "Irgendein"
msgid "Any Label"
msgstr "Beliebiges Label"
+msgid "Any Milestone"
+msgstr "Jeder Meilenstein"
+
msgid "Any encrypted tokens"
-msgstr ""
+msgstr "Alle verschlüsselten Tokens"
+
+msgid "Any namespace"
+msgstr "Jeder Namensraum"
msgid "Appearance"
msgstr "Aussehen"
msgid "Appearance was successfully created."
-msgstr ""
+msgstr "Das Erscheinungsbild wurde erfolgreich erstellt."
msgid "Appearance was successfully updated."
+msgstr "Das Erscheinungsbild wurde erfolgreich aktualisiert."
+
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
msgstr ""
msgid "Application"
@@ -1158,11 +1355,14 @@ msgstr "Anwendungs-ID"
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr "Die Anwendung wurde deinstalliert, konnte jedoch nicht gelöscht werden: %{error_message}"
+
msgid "Application was successfully destroyed."
-msgstr ""
+msgstr "Anwendung wurde erfolgreich gelöscht."
msgid "Application was successfully updated."
-msgstr ""
+msgstr "Anwendung wurde erfolgreich aktualisiert."
msgid "Application: %{name}"
msgstr "Anwendung: %{name}"
@@ -1171,28 +1371,40 @@ msgid "Applications"
msgstr "Anwendungen"
msgid "Applied"
-msgstr ""
+msgstr "Angewendet"
msgid "Apply suggestion"
-msgstr ""
+msgstr "Vorschlag anwenden"
+
+msgid "Applying command"
+msgstr "Befehl anwenden"
+
+msgid "Applying command to %{commandDescription}"
+msgstr "Befehl anwenden, um: %{commandDescription}"
+
+msgid "Applying multiple commands"
+msgstr "Mehrere Befehle anwenden"
+
+msgid "Applying suggestion"
+msgstr "Vorschlag anwenden"
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Mitglied"
+msgstr[1] "%d Mitglieder"
msgid "ApprovalRuleRemove|Approvals from this member are not revoked."
msgid_plural "ApprovalRuleRemove|Approvals from these members are not revoked."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Zustimmungen dieses Mitglieds werden nicht widerrufen."
+msgstr[1] "Zustimmungen dieser Mitglieder werden nicht widerrufen."
msgid "ApprovalRuleRemove|You are about to remove the %{name} approver group which has %{nMembers}."
-msgstr ""
+msgstr "Du bist dabei die Genehmigungsberechtigten-Gruppe %{name} mit %{nMembers} zu löschen."
msgid "ApprovalRuleSummary|%d member"
msgid_plural "ApprovalRuleSummary|%d members"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Mitglied"
+msgstr[1] "%d Mitglieder"
msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
@@ -1203,26 +1415,20 @@ msgid "ApprovalRule|All members with Developer role or higher and code owners (i
msgstr ""
msgid "ApprovalRule|Members"
-msgstr ""
+msgstr "Mitglieder"
msgid "ApprovalRule|Name"
-msgstr ""
+msgstr "Name"
msgid "ApprovalRule|No. approvals required"
msgstr ""
msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
+msgstr "z.B. QS, Sicherheit, etc."
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr "Apr"
@@ -1230,10 +1436,10 @@ msgid "April"
msgstr "April"
msgid "Archive jobs"
-msgstr ""
+msgstr "Jobs archivieren"
msgid "Archive project"
-msgstr ""
+msgstr "Projekt archivieren"
msgid "Archived project! Repository and other project resources are read-only"
msgstr "Archiviertes Projekt! Repository und andere Projektressourcen sind schreibgeschützt"
@@ -1245,14 +1451,26 @@ msgid "Archiving the project will make it entirely read-only. It is hidden from
msgstr ""
msgid "Are you sure"
-msgstr ""
+msgstr "Bist du sicher"
msgid "Are you sure that you want to archive this project?"
-msgstr ""
+msgstr "Möchtest du wirklich dieses Projekt archivieren?"
msgid "Are you sure that you want to unarchive this project?"
+msgstr "Möchtest du wirklich dieses Projekt aus dem Archiv zurückholen?"
+
+msgid "Are you sure you want to cancel creating this comment?"
+msgstr "Möchtest du wirklich die Erstellung dieses Kommentars abbrechen?"
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr "Möchtest du wirklich die Bearbeitung dieses Kommentars abbrechen?"
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
+msgid "Are you sure you want to delete this list?"
+msgstr "Möchtest du wirklich diese Liste löschen?"
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Bist Du sicher, dass Du diesen Pipeline-Zeitplan löschen möchtest?"
@@ -1263,10 +1481,10 @@ msgid "Are you sure you want to lose unsaved changes?"
msgstr "Bist du sicher, dass du alle nicht gespeicherten Änderungen verwerfen möchtest?"
msgid "Are you sure you want to lose your issue information?"
-msgstr ""
+msgstr "Möchtest du wirklich die Ticketinformationen verlieren?"
msgid "Are you sure you want to permanently delete this license?"
-msgstr ""
+msgstr "Möchtest du wirklich diese Lizenz dauerhaft löschen?"
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr "Möchtest du den öffentlichen Schlüssel wirklich neu generieren? Du musst dann den öffentlichen Schlüssel auf dem Remote-Server aktualisieren, bevor die Spiegelung wieder funktioniert."
@@ -1274,18 +1492,6 @@ msgstr "Möchtest du den öffentlichen Schlüssel wirklich neu generieren? Du mu
msgid "Are you sure you want to remove %{group_name}?"
msgstr "Bist du sicher, dass du %{group_name} wirklich entfernen willst?"
-msgid "Are you sure you want to remove approver %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove approver %{name}?"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}?"
-msgstr ""
-
msgid "Are you sure you want to remove the attachment?"
msgstr ""
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr "Bist du sicher, dass du den Health-Check-Token zurücksetzen willst?"
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr "Bist du sicher, dass du diese Umgebung stoppen möchtest?"
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr "Bist Du sicher?"
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr "Artefakt-ID"
msgid "Artifacts"
msgstr "Artefakte"
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr "Aufsteigend"
@@ -1329,6 +1562,9 @@ msgid "Assertion consumer service URL"
msgstr "Assertion-Consumer-Service-URL"
msgid "Assets"
+msgstr "Assets"
+
+msgid "Assign"
msgstr ""
msgid "Assign custom color like #FF0000"
@@ -1341,11 +1577,17 @@ msgid "Assign milestone"
msgstr "Meilenstein zuweisen"
msgid "Assign some issues to this milestone."
-msgstr ""
+msgstr "Einige Tickets diesem Meilenstein zuordnen."
msgid "Assign to"
msgstr "Zuweisen an"
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr "Zugewiesene Tickets"
@@ -1371,11 +1613,19 @@ msgid "At least one approval from a code owner is required to change files match
msgstr ""
msgid "Attach a file"
-msgstr ""
+msgstr "Datei anhängen"
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Datei mittels Drag &amp; Drop oder %{upload_link} hinzufügen"
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] "Datei anhängen"
+msgstr[1] "%d Dateien anhängen"
+
+msgid "Attaching the file failed."
+msgstr "Die Datei konnte nicht angehängt werden."
+
msgid "Audit Events"
msgstr "Audit-Ereignisse"
@@ -1389,7 +1639,7 @@ msgid "Authentication Log"
msgstr "Authentifizierungsprotokoll"
msgid "Authentication failed: %{error_message}"
-msgstr ""
+msgstr "Authentifizierung fehlgeschlagen: %{error_message}"
msgid "Authentication log"
msgstr "Authentifizierungsprotokoll"
@@ -1398,7 +1648,7 @@ msgid "Authentication method"
msgstr "Authentifizierungsmethode"
msgid "Authentication method updated"
-msgstr ""
+msgstr "Authentifizierungsmethode aktualisiert"
msgid "Authentication via U2F device failed."
msgstr ""
@@ -1463,20 +1713,29 @@ msgstr "Erfahre mehr in der %{link_to_documentation}"
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr "Die Auto-DevOps-Pipeline wurde aktiviert und wir verwendet, falls keine alternative CI-Konfigurationsdatei gefunden wurde. %{more_information_link}"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
msgid "Automatically marked as default internal user"
msgstr "Automatisch als interne(r) Standardbenutzer(in) gekennzeichnet"
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatically resolved"
msgstr ""
-msgid "Automatically resolved"
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
msgstr ""
+msgid "Autosave|Note"
+msgstr "Notiz"
+
msgid "Available"
msgstr "Verfügbar"
msgid "Available group Runners: %{runners}"
-msgstr ""
+msgstr "Verfügbare Gruppen-Runner: %{runners}"
msgid "Available shared Runners:"
msgstr ""
@@ -1488,7 +1747,7 @@ msgid "Avatar for %{assigneeName}"
msgstr ""
msgid "Avatar for %{name}"
-msgstr ""
+msgstr "Avatar von %{name}"
msgid "Avatar will be removed. Are you sure?"
msgstr "Avatar wird entfernt. Bist du sicher?"
@@ -1583,6 +1842,30 @@ msgstr "Deine Badges"
msgid "Badges|e.g. %{exampleUrl}"
msgstr "z. B. %{exampleUrl}"
+msgid "Badge|New"
+msgstr "Neu"
+
+msgid "Balsamiq file could not be loaded."
+msgstr "Balsamiq-Datei konnte nicht geladen werden."
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr "Alle ausstehenden Kommentare löschen"
@@ -1593,10 +1876,10 @@ msgid "BatchComments|You're about to discard your review which will delete all o
msgstr "Du bist dabei deinen Review zu verwerfen und damit alle ausstehenden Kommentare zu löschen. Die gelöschten Kommentare können %{strong_start}nicht%{strong_end} wiederhergestellt werden."
msgid "Be careful. Changing the project's namespace can have unintended side effects."
-msgstr ""
+msgstr "Vorsicht. Änderungen am Projektnamensraum können unbeabsichtigte Nebenwirkungen haben."
msgid "Be careful. Renaming a project's repository can have unintended side effects."
-msgstr ""
+msgstr "Vorsicht. Das Umbenennen des Projekt-Repositorys kann unbeabsichtigte Nebenwirkungen haben."
msgid "Begin with the selected commit"
msgstr "Mit dem ausgewählten Commit beginnen"
@@ -1644,7 +1927,7 @@ msgid "BillingPlans|This group uses the plan associated with its parent group."
msgstr "Diese Gruppe verwendet den Tarif der übergeordneten Gruppe."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
-msgstr "Im Abschnitt Abrechnung von %{parent_billing_page_link} können Sie den Tarif für diese Gruppe verwalten."
+msgstr "Im Abschnitt Abrechnung von %{parent_billing_page_link} kannst du den Tarif für diese Gruppe verwalten."
msgid "BillingPlans|Upgrade"
msgstr "Upgrade"
@@ -1680,17 +1963,36 @@ msgid "Bitbucket import"
msgstr "Bitbucket-Import"
msgid "Block"
-msgstr ""
+msgstr "Sperren"
msgid "Blocked"
-msgstr ""
+msgstr "Gesperrt"
+
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
msgid "Blog"
msgstr "Blog"
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr "Boards"
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "Branch %{branchName} wurde im Repository dieses Projekts nicht gefunden."
@@ -1706,6 +2008,9 @@ msgstr "Branch existiert bereits"
msgid "Branch name"
msgstr "Branch-Name"
+msgid "Branch not loaded - %{branchId}"
+msgstr "Branch nicht geladen - %{branchId}"
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Branches durchsuchen"
@@ -1731,7 +2036,7 @@ msgid "Branches|Compare"
msgstr "Vergleichen"
msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
-msgstr "Löschen Sie alle Branches, die in \"%{default_branch}\" zusammengeführt werden"
+msgstr "Lösche alle Branches, die in \"%{default_branch}\" zusammengeführt werden"
msgid "Branches|Delete branch"
msgstr "Branch löschen"
@@ -1836,10 +2141,10 @@ msgid "Branches|protected"
msgstr "geschützt"
msgid "Broadcast Message was successfully created."
-msgstr ""
+msgstr "Broadcast-Nachricht wurde erfolgreich erstellt."
msgid "Broadcast Message was successfully updated."
-msgstr ""
+msgstr "Broadcast-Nachricht wurde erfolgreich aktualisiert."
msgid "Browse Directory"
msgstr "Verzeichnis durchsuchen"
@@ -1854,46 +2159,64 @@ msgid "Browse files"
msgstr "Dateien durchsuchen"
msgid "Built-in"
+msgstr "Integriert"
+
+msgid "BurndownChartLabel|Guideline"
msgstr ""
-msgid "Business"
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
msgstr ""
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
+msgid "Business"
+msgstr "Business"
+
msgid "Business metrics (Custom)"
msgstr "Business-Metriken (benutzerdefiniert)"
msgid "Buy EE"
-msgstr ""
+msgstr "EE kaufen"
msgid "Buy GitLab Enterprise Edition"
-msgstr ""
+msgstr "Kaufe die GitLab Enterprise Edition"
msgid "By %{user_name}"
-msgstr ""
+msgstr "Von %{user_name}"
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
-msgstr ""
+msgstr "Standardmäßig versendet GitLab E-Mails in HTML- und Nur-Text-Formaten, sodass Mail-Clients das zu verwendende Format auswählen können. Deaktiviere diese Option, wenn E-Mails ausschließlich im Nur-Text-Format versendet werden sollen."
+
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr "Standardmäßig verwenden alle Projekte und Gruppen die globalen Einstellungen für Benachrichtigungen."
msgid "ByAuthor|by"
msgstr "von"
msgid "CHANGELOG"
-msgstr ""
+msgstr "CHANGELOG"
msgid "CI / CD"
msgstr "CI / CD"
msgid "CI / CD Charts"
-msgstr ""
+msgstr "CI/CD-Diagramme"
msgid "CI / CD Settings"
msgstr "CI/CD-Einstellungen"
msgid "CI Lint"
-msgstr ""
+msgstr "CI Lint"
msgid "CI variables"
-msgstr ""
+msgstr "CI-Variablen"
msgid "CI will run using the credentials assigned above."
msgstr "CI wird mit den oben angegebenen Anmeldeinformationen ausgeführt."
@@ -1923,7 +2246,7 @@ msgid "CICD|Continuous deployment to production"
msgstr "Kontinuierliche Bereitstellung für Produktion"
msgid "CICD|Continuous deployment to production using timed incremental rollout"
-msgstr ""
+msgstr "Kontinuierliche Bereitstellung für die Produktion mit zeitgesteuertem, schrittweisem Rollout"
msgid "CICD|Default to Auto DevOps pipeline"
msgstr "Standard für Auto-DevOps-Pipeline"
@@ -1944,29 +2267,35 @@ msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration
msgstr "Die Auto-DevOps-Pipeline wird ausgeführt, wenn keine alternative CI-Konfigurationsdatei gefunden wird."
msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
-msgstr ""
+msgstr "Du musst eine %{kubernetes_cluster_start}Kubernetes-Cluster-integration%{kubernetes_cluster_end} mit einer Domain zu diesem Projekt hinzufügen, damit deine Bereitstellungsstrategie korrekt funktioniert."
msgid "CICD|group enabled"
-msgstr ""
+msgstr "Gruppe aktiviert"
msgid "CICD|instance enabled"
msgstr "Instanz aktiviert"
msgid "CONTRIBUTING"
-msgstr ""
+msgstr "CONTRIBUTING"
msgid "Callback URL"
msgstr "Callback-URL"
msgid "Can override approvers and approvals required per merge request"
-msgstr ""
+msgstr "Kann erforderliche Genehmigungsberechtigte und Genehmigungen pro Merge-Request überschreiben"
msgid "Can't find HEAD commit for this branch"
msgstr "HEAD-Commit kann für diesen Branch nicht gefunden werden"
+msgid "Can't find variable: ZiteReader"
+msgstr "Kann Variable nicht finden: ZiteReader"
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,29 +2317,41 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr "Kann verwalteten Kubernetes-Cluster nicht ändern"
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
msgid "Capacity threshold"
-msgstr ""
+msgstr "Kapazitätsschwelle"
msgid "Certificate"
-msgstr ""
+msgstr "Zertifikat"
msgid "Certificate (PEM)"
-msgstr ""
+msgstr "Zertifikat (PEM)"
msgid "Change Weight"
msgstr "Gewichtung ändern"
+msgid "Change assignee(s)"
+msgstr "Zuweisung(en) ändern"
+
+msgid "Change assignee(s)."
+msgstr "Zuweisung(en) ändern."
+
msgid "Change path"
-msgstr ""
+msgstr "Pfad ändern"
msgid "Change permissions"
-msgstr ""
+msgstr "Berechtigungen ändern"
msgid "Change template"
msgstr "Vorlage ändern"
@@ -2018,6 +2359,15 @@ msgstr "Vorlage ändern"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "Ändere diesen Wert, um zu beeinflussen, wie oft die GitLab UI nach Updates fragt."
+msgid "Change title"
+msgstr "Titel ändern"
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "In dem Branch wählen"
@@ -2034,13 +2384,19 @@ msgid "ChangeTypeAction|This will create a new commit in order to revert the exi
msgstr "Dies wird einen neuen Commit erzeugen, um die vorhandenen Änderungen rückgängig zu machen."
msgid "Changes"
-msgstr ""
+msgstr "Änderungen"
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr "Änderungen werden angezeigt, als ob die <b>Quell</b>-Revision in die <b>Ziel</b>-Revision gemerged wurde."
msgid "Changes suppressed. Click to show."
-msgstr ""
+msgstr "Änderungen unterdrückt. Zum Anzeigen klicken."
+
+msgid "Changes the title to \"%{title_param}\"."
+msgstr "Ändert den Titel in \"%{title_param}\"."
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr "Die Änderungen werden nicht ausgeführt bis %{link_start}neu indexiert%{link_end} wurde."
msgid "Charts"
msgstr "Diagramme"
@@ -2058,17 +2414,20 @@ msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "Lies die %{docs_link_start}Dokumentation%{docs_link_end}."
msgid "Check your .gitlab-ci.yml"
-msgstr ""
+msgstr "Prüfe deine .gitlab-ci.yml"
msgid "Checking %{text} availability…"
msgstr "Prüfe %{text} Verfügbarkeit…"
msgid "Checking approval status"
-msgstr ""
+msgstr "Prüfe Genehmigungsstatus"
msgid "Checking branch availability..."
msgstr "Überprüfe Verfügbarkeit des Branches..."
+msgid "Checking username availability..."
+msgstr "Überprüfe Verfügbarkeit des Benutzernamens..."
+
msgid "Cherry-pick this commit"
msgstr "Diesen Commit cherry picken"
@@ -2085,13 +2444,16 @@ msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to s
msgstr "Wähle einen Branch/Tag (z. B. %{master}) oder gib einen Commit ein (z. B. %{sha}), um zu sehen, was geändert wurde oder um einen Merge-Request zu erstellen."
msgid "Choose a file"
-msgstr ""
+msgstr "Wähle eine Datei"
msgid "Choose a role permission"
-msgstr ""
+msgstr "Wähle eine Rollenberechtigung aus"
+
+msgid "Choose a template"
+msgstr "Vorlage auswählen"
msgid "Choose a template..."
-msgstr "Wählen Sie eine Vorlage..."
+msgstr "Vorlage auswählen ..."
msgid "Choose a type..."
msgstr "Typ auswählen..."
@@ -2120,7 +2482,7 @@ msgstr "Wähle welche Repositories du verbinden und die CI/CD-Pipelines ausführ
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr "Wähle die Fragmente aus, die du mit diesem sekundären Knoten synchronisieren möchtest."
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr "übersprungen"
msgid "CiStatus|running"
msgstr "laufend"
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr "Variablenschlüssel eingeben"
msgid "CiVariables|Input variable value"
msgstr "Variablenwert eingeben"
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr "Variable jetzt löschen"
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr "Suche löschen"
msgid "Clear search input"
msgstr "Suchfelder löschen"
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr "Klicke auf einen beliebigen <strong>-Projektnamen</strong> in der folgenden Projektliste, um zum Projektmeilenstein zu navigieren."
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr "Klicke auf den <strong>Download</strong>-Button und warte bis das Herunterladen abgeschlossen ist."
@@ -2310,7 +2699,10 @@ msgid "Close epic"
msgstr "Epic schließen"
msgid "Close milestone"
-msgstr ""
+msgstr "Meilenstein abschließen"
+
+msgid "Close sidebar"
+msgstr "Seitenleiste schließen"
msgid "Closed"
msgstr "Geschlossen"
@@ -2319,7 +2711,7 @@ msgid "Closed issues"
msgstr "Geschlossene Tickets"
msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
-msgstr ""
+msgstr "%{custom_domain_start}Mehr Informationen%{custom_domain_end}."
msgid "ClusterIntegration| can be used instead of a custom domain."
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} wurde erfolgreich auf deinem Kubernetes-Cluster installiert"
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr "ClusterIntegration|Eine Kubernetes-Cluster-Integration hinzufügen"
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr "Wenn du deiner Gruppe ein Kubernetes-Cluster hinzufügst, wird das Cluster automatisch von allen deinen Projekten geteilt. Benutze Review-Anwendungen, stelle deine Anwendungen bereit und führe einfach alle deine Pipelines für alle Projekte auf dem selben Cluster aus."
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr "Wenn du deiner Gruppe eine Integration hinzufügst, wird das Cluster von allen deinen Projekten geteilt."
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Erweiterte Optionen für die Integration dieses Kubernetes-Clusters"
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr "Anwendungen"
@@ -2477,6 +2890,9 @@ msgstr "GitLab Runner"
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Google Cloud Platform-Projekt"
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr "Ingress bietet die Möglichkeit, Dienste-Anfragen je nach Anfragehost oder -pfad weiterzuleiten. So werden viele Dienste an einer Stelle zentral zusammengefasst."
-msgid "ClusterIntegration|Install"
-msgstr "Installieren"
-
-msgid "ClusterIntegration|Installed"
-msgstr "Installiert"
-
-msgid "ClusterIntegration|Installing"
-msgstr "Installiere"
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,9 +2965,12 @@ msgstr "Knative Domainname:"
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
-msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgid "ClusterIntegration|Knative domain name was updated successfully."
msgstr ""
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr "Knative erweitert Kubernetes und bietet eine Reihe von Middleware-Komponenten. Diese sind essentiell für moderne, Quellcode-basiert, containerisierte, überall lauffähige Anwendungen: ein eigenen RZ, in der Cloud oder im Rechenzentrum eines Drittanbieters."
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr "Kubernetes-Cluster"
@@ -2594,6 +3004,9 @@ msgstr "Lerne mehr über Kubernetes"
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr "Lerne mehr über die Kubernetes Gruppen-Cluster"
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr "Maschinentyp"
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr "Stelle sicher, dass dein Konto %{link_to_requirements}, um Kubernetes-Cluster zu erstellen"
-msgid "ClusterIntegration|Manage"
-msgstr "Manage"
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr "Verwalte dein Kubernetes-Cluster hier: %{link_gke}"
@@ -2669,7 +3079,7 @@ msgstr "Ersetze dies mit deinem eigenen Hostnamen wenn du möchtest. Wenn du die
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "Anfrage zur Installation fehlgeschlagen"
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,12 +3133,36 @@ msgstr "Beim Erstellen deines Kubernetes-Clusters auf der Google Kubernetes Engi
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "Beim Installieren von %{title} ist ein Fehler aufgetreten"
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
+msgstr ""
+
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
+msgstr ""
+
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
+msgstr ""
+
msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
+msgstr ""
+
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr "Dieses Konto benötigt die Berechtigungen um ein Kubernetes-Cluster in dem untenstehenden %{link_to_container_project} zu erstellen"
@@ -2741,22 +3175,10 @@ msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "Kubernetes-Cluster umschalten"
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
-msgstr ""
-
-msgid "ClusterIntegration|Updating"
-msgstr ""
-
-msgid "ClusterIntegration|Upgrade"
-msgstr ""
-
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
-msgstr ""
-
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr "Wir konnten nicht verifizieren, ob für eines deiner Projekte auf GCP di
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "Mit einem Kubernetes-Cluster innerhalb dieses Projekts kannst du auf einfache Weise Review-Anwendungen verwenden, deine Anwendungen bereitstellen, Pipelines ausführen und vieles mehr."
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr "Du musst zuerst Helm Tiller installieren, bevor du die Anwendung unten installierst"
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "Dein Account benötigt eine %{link_to_kubernetes_engine}"
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr "Zone"
@@ -2823,14 +3251,20 @@ msgid "Collapse"
msgstr "Reduzieren"
msgid "Collapse approvers"
-msgstr ""
+msgstr "Genehmigungsberechtigte ausblenden"
msgid "Collapse sidebar"
msgstr "Seitenleiste einklappen"
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr "Kommentieren"
@@ -2849,6 +3283,9 @@ msgstr "Kommentieren & Diskussion wieder eröffnen"
msgid "Comment form position"
msgstr "Position des Kommentarformulars"
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr "Kommentare"
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr "Zeitüberschreitung für Gitaly konfigurieren."
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr "Tracing konfigurieren"
@@ -2995,9 +3435,15 @@ msgstr "Konfiguriere, wie ein(e) Benutzer(in) ein neues Konto erstellt."
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr "Verbinden"
@@ -3010,9 +3456,15 @@ msgstr "GitHub-Repositorys verbinden"
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr "Verbinde deine externen Repositories, und CI/CD-Pipelines werden für neue Commits ausgeführt. Ein GitLab-Projekt wird nur mit aktivierten CI/CD-Funktionen erstellt."
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr "Verbinden..."
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr "Mit der in GitLab integrierten Docker-Container-Registry kann jedes Proj
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr "Du kannst auch %{deploy_token} für den schreibgeschützten Zugriff auf die Registry-Images verwenden."
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,8 +3576,11 @@ msgstr "Commits für %{branch_name}, ausgenommen Merge-Commits. Limitiert auf 6.
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr "Bitte warte einen Moment, diese Seite wird automatisch aktualisiert, wenn bereit."
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
-msgstr "Steuern Sie die Anzeige von Angeboten Dritter."
+msgstr "Steuere die Anzeige von Angeboten Dritter."
msgid "Control the maximum concurrency of repository backfill for this secondary node"
msgstr "Steuere die maximale Parallelität des Repository-Backfills für diesen sekundären Knoten"
@@ -3130,6 +3588,9 @@ msgstr "Steuere die maximale Parallelität des Repository-Backfills für diesen
msgid "ConvDev Index"
msgstr "ConvDev-Index"
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr "Kopiere SSH clone-URL"
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr "Kopiere öffentlichen SSH-Schlüssel in die Zwischenablage"
-
msgid "Copy URL to clipboard"
msgstr "Kopiere URL in die Zwischenablage"
@@ -3166,6 +3624,12 @@ msgstr "Kopiere Commit SHA in die Zwischenablage"
msgid "Copy file path to clipboard"
msgstr "Dateipfad in Zwischenablage kopieren"
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr "Link kopieren"
@@ -3175,6 +3639,9 @@ msgstr "Referenz in Zwischenablage kopieren"
msgid "Copy secret to clipboard"
msgstr "Secret in Zwischenablage kopieren"
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr "In Zwischenablage kopieren"
@@ -3184,9 +3651,15 @@ msgstr "Token in Zwischenablage kopieren"
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr "Erstelle einen neuen Branch"
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr "Neues Ticket erstellen"
@@ -3295,6 +3777,12 @@ msgstr "Projektlabel erstellen"
msgid "Create your first page"
msgstr "Erstelle deine erste Seite"
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr "Tag "
@@ -3310,12 +3798,27 @@ msgstr "Erstellt am"
msgid "Created by me"
msgstr "Von mir erstellt"
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr "Erstellt am"
msgid "Created on:"
msgstr "Erstellt am:"
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr "Epic wird angelegt"
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr "Aktueller Knoten"
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr "Profil"
@@ -3412,15 +3918,39 @@ msgstr "Alle"
msgid "DashboardProjects|Personal"
msgstr "Persönliche"
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr "Datumsauswahl"
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr "Debug"
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr "Standard: Importiere direkt die Google Code-E-Mail-Adresse oder den Nutzernamen"
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr "Gelöscht"
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr "Verweigern"
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "Bereitstellung"
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr "Gruppen-Runner deaktivieren"
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr "Verwerfen"
@@ -3783,6 +4388,12 @@ msgstr "Entwurf verwerfen"
msgid "Discard review"
msgstr "Review verwerfen"
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr "Hervorheben des Merge-Requests beenden"
msgid "Dismiss trial promotion"
msgstr "Testversions-Hinweis ausblenden"
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr "Möchtest du festlegen, wie die E-Mail-Adressen und Nutzernamen von Google Code in GitLab importiert werden?"
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr "Dokumentation für gängige Identitätsanbieter"
msgid "Domain"
msgstr "Domäne"
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr "Nicht erneut anzeigen"
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr "Erledigt"
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
+msgid "Download codes"
msgstr ""
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
-msgstr ""
-
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr "Label bearbeiten"
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "Pipeline-Zeitplan bearbeiten %{id}"
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr "Elasticsearch"
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr "Elasticsearch-Integration. Elasticsearch AWS IAM."
@@ -3940,7 +4578,7 @@ msgid "Elastic|None. Select namespaces to index."
msgstr ""
msgid "Elastic|None. Select projects to index."
-msgstr ""
+msgstr "Keine. Wähle Projekte zum Indexieren aus."
msgid "Email"
msgstr "E-Mail"
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr "E-Mail-Patch"
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr "E-Mails"
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr "Einbetten"
@@ -4002,6 +4673,9 @@ msgstr "SAML-Authentifizierung für diese Gruppe aktivieren"
msgid "Enable Sentry for error reporting and logging."
msgstr "Aktiviere Sentry für die Fehlerberichterstattung und -protokollierung."
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr "Aktiviere und konfiguriere InfluxDB-Messwerte."
@@ -4038,9 +4712,6 @@ msgstr "Aktiviere reCAPTCHA oder Akismet und lege die IP-Grenzwerte fest."
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr "Aktiviere die Performance-Leiste für eine bestimmte Gruppe."
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr "Endet am (UTC)"
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr "Gib unten deine Bitbucket-Server-URL und deinen persönlichen Zugriffstoken ein"
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr "Gib die Beschreibung des Tickets ein"
@@ -4089,7 +4766,10 @@ msgstr "Gib die Beschreibung des Merge-Requests ein"
msgid "Enter the merge request title"
msgstr "Gib den Titel des Merge-Requests ein"
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr "Umgebungen"
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "Beim Abrufen der Umgebungen ist ein Fehler aufgetreten."
@@ -4237,20 +4941,53 @@ msgid "Epics Roadmap"
msgstr "Epics Roadmap"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
-msgstr "Mit Epics können Sie Ihre Projekte effizienter und mit weniger Aufwand verwalten"
+msgstr "Mit Epics kannst du deine Projekte effizienter und mit weniger Aufwand verwalten"
+
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr "Wie kann ich dieses Problem lösen?"
msgid "Epics|More information"
msgstr "Weitere Informationen"
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr "Diese Daten beeinflussen, wie deine Epics in der Roadmap erscheinen. Die Daten der Meilensteine ​​stammen aus den Meilensteinen, die den Tickets im Epic zugewiesen wurden. Du kannst auch feste Termine festlegen oder sie vollständig entfernen."
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr "Um dein Epics %{epicDateType} basierend auf den Meilensteinen zu planen, weise einen Meilenstein mit einem %{epicDateType} einem beliebigen Ticket im Epic zu."
@@ -4287,9 +5024,15 @@ msgstr "Fehler beim Abrufen der Label."
msgid "Error fetching network graph."
msgstr "Fehler beim Abrufen des Netzwerkgraphen."
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr "Fehler beim Abrufen der Referenzen"
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr "Fehler beim Abrufen der Daten des Nutzungsberichts."
@@ -4299,6 +5042,12 @@ msgstr "Fehler beim Laden der Branch-Daten. Bitte versuche es erneut."
msgid "Error loading branches."
msgstr "Fehler beim Laden der Branches."
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr "Fehler beim Laden des letzten Commits."
@@ -4308,6 +5057,9 @@ msgstr "Fehler beim Laden der Markdown-Vorschau"
msgid "Error loading merge requests."
msgstr "Fehler beim Laden der Merge-Requests."
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr "Fehler beim Laden der Projektdaten. Bitte versuche es erneut."
@@ -4317,6 +5069,12 @@ msgstr "Fehler beim Laden der Vorlagentypen."
msgid "Error loading template."
msgstr "Fehler beim Laden der Vorlage."
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr "Beim Umschalten des Benachrichtigungs-Abonnements trat ein Fehler auf"
@@ -4350,9 +5108,15 @@ msgstr "Fehler beim Aktualisieren des To-do-Status."
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr "Fehler beim Laden des Merge-Requests. Bitte versuche es erneut."
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4462,7 +5229,7 @@ msgid "Expand all"
msgstr "Alle erweitern"
msgid "Expand approvers"
-msgstr ""
+msgstr "Genehmigungsberechtigte anzeigen"
msgid "Expand sidebar"
msgstr "Menüleiste ausklappen"
@@ -4495,7 +5262,7 @@ msgid "Explore groups"
msgstr "Erkunde Gruppen"
msgid "Explore projects"
-msgstr "Projekte erkunden"
+msgstr "Projekte entdecken"
msgid "Explore public groups"
msgstr "Erkunde öffentliche Gruppen"
@@ -4536,6 +5303,27 @@ msgstr "Klassifizierungslabel"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "Wenn kein Klassifizierungslabel gesetzt ist, wird das Standardlabel `%{default_label}` benutzt."
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr "Facebook"
@@ -4545,27 +5333,60 @@ msgstr "Fehlgeschlagen"
msgid "Failed Jobs"
msgstr "Fehlgeschlagene Jobs"
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr "Wechsel des/der Besitzers/-in fehlgeschlagen"
msgid "Failed to check related branches."
msgstr "Verwandte Branches konnten nicht überprüft werden."
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr "Bereitstellung fehlgeschlagen für"
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr "Fehler beim Laden der Emoji-Liste."
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr "Fehler beim Entfernen des Tickets vom Bord, bitte versuche es erneut."
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,18 +5423,30 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr "Signieren mit Smartcard-Authentifizierung fehlgeschlagen"
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr "Tickets konnten nicht aktualisiert werden, bitte versuche es erneut."
+msgid "Failed to update tag!"
+msgstr ""
+
+msgid "Failed to update."
+msgstr ""
+
+msgid "Failed to upgrade."
+msgstr ""
+
msgid "Failed to upload object map file"
msgstr ""
msgid "Failure"
msgstr "Fehlschlag"
-msgid "Fast-forward merge"
-msgstr ""
-
msgid "Fast-forward merge without a merge commit"
msgstr ""
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr "Feature Flags"
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,8 +5528,8 @@ msgstr "Inaktiv"
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
-msgstr "Installiere eine %{docs_link_start}kompatible Client-Bibliothek%{docs_link_end} und gib während der Konfiguration die API-URL, den Namen der Anwendung und die Instanz-ID an."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
+msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr "Instanz-ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr "Weitere Informationen"
-
msgid "FeatureFlags|Name"
msgstr "Name"
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr "Dateien"
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr "Fülle die Felder unten aus, schalte <strong>%{enable_label}</strong> an, und drücke <strong>%{save_changes}</strong>"
@@ -4826,6 +5674,9 @@ msgstr "Suche die neu extrahierte Datei <code>Takeout/Google Code Project Hostin
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr "Fingerabdrücke"
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr "Review beenden"
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr "Fertiggestellt"
@@ -4859,6 +5713,12 @@ msgstr "Fixer Starttermin"
msgid "Fixed:"
msgstr "Behoben:"
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr "FogBugz-E-Mail"
@@ -4904,6 +5764,15 @@ msgstr "Bei privaten Projekten kann jedes Mitglied (Gast oder höher) Pipelines
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr "Bei öffentlichen Projekten, kann jeder sich die Pipelines ansehen und auf Job-Details (Ausgabeprotokolle und Artefakte) zugreifen"
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Fork von"
@@ -4913,6 +5782,9 @@ msgstr "Geforkt von %{project_name} (gelöscht)"
msgid "Forking in progress"
msgstr "Fork wird erstellt"
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr "Fehler in deiner .gitlab-ci.yml gefunden:"
msgid "Free Trial of GitLab.com Gold"
msgstr "Kostenlose Testversion von GitLab.com Gold"
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr "Von Meilensteinen:"
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr "Installiere den Runner aus der Anwendungsliste in der Kubernetes-Cluster Detailansicht"
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr "GPG-Schlüssel"
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5049,7 +5930,7 @@ msgid "GeoNodes|Learn more about Wiki checksum progress"
msgstr "Erfahre mehr über den Wiki-Prüfsummenfortschritt"
msgid "GeoNodes|Learn more about Wiki verification"
-msgstr "Erfahren Sie mehr über die Wiki-Verifikation"
+msgstr "Erfahre mehr über die Wiki-Verifikation"
msgid "GeoNodes|Loading nodes"
msgstr "Knoten werden geladen"
@@ -5324,6 +6205,12 @@ msgstr "Synchronisierung fehlgeschlagen - %{error}"
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr "Git"
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr "Git-Repository-URL"
msgid "Git revision"
msgstr "Git-Revision"
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr "Git-Strategie für Pipelines"
@@ -5462,6 +6355,9 @@ msgstr "Gitea-Import"
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr "Zurück"
@@ -5480,9 +6376,18 @@ msgstr "Gehe zu"
msgid "Go to %{link_to_google_takeout}."
msgstr "Gehe zu %{link_to_google_takeout}."
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr "Google Code-Import"
@@ -5558,6 +6463,9 @@ msgstr "Gruppenname"
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr "Gruppe: %{group_name}"
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr "Vom %{dateWord}"
@@ -5594,13 +6505,16 @@ msgstr "Bis %{dateWord}"
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr "entferne die Freigabe mit Gruppensperre von %{ancestor_group_name}"
msgid "Groups"
msgstr "Gruppen"
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr "Gruppen können durch %{subgroup_docs_link_start}Untergruppen%{subgroup_docs_link_end} verschachtelt werden."
@@ -5721,7 +6644,7 @@ msgid "GroupsDropdown|Frequently visited"
msgstr "Häufig besucht"
msgid "GroupsDropdown|Groups you visit often will appear here"
-msgstr "Gruppen, die Sie häufig besuchen, werden hier angezeigt"
+msgstr "Gruppen, die du häufig besuchst, werden hier angezeigt"
msgid "GroupsDropdown|Loading groups"
msgstr "Gruppen werden geladen"
@@ -5780,6 +6703,9 @@ msgstr "Keine Gruppen oder Projekte entsprachen deiner Suche"
msgid "GroupsTree|Search by name"
msgstr "Nach Namen suchen"
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr "Lasse deine Nutzer an diese Adresse mailen"
@@ -5807,6 +6733,9 @@ msgstr "Keine Probleme erkannt"
msgid "HealthCheck|Unhealthy"
msgstr "Problematisch"
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr "Hilfe"
@@ -5816,12 +6745,15 @@ msgstr "Hilfe-Seite"
msgid "Help page text and support page url."
msgstr "Text der Hilfeseite und die Supportseiten-URL."
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
-msgstr "Hier ist der öffentliche SSH-Schlüssel, der auf dem Remote-Server hinzugefügt werden muss. Weitere Informationen findest du in der Dokumentation."
+msgid "Hide archived projects"
+msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr "Manuelle Eingabe der Host-Tasten ausblenden"
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr "Nutzdaten ausblenden"
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Wert ausblenden"
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr "Verlauf"
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr "Bereinigung erfolgreich gestartet"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr "Ich akzeptiere die %{terms_link}"
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr "Nutzungs- und Datenschutzbestimmungen"
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr "ID"
@@ -5938,11 +6891,20 @@ msgstr "When aktiv"
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr "Wenn diese Option aktiviert ist, wird der Zugriff auf Projekte mit einem externen Service anhand ihrer Klassifizierungslabels überprüft."
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr "Wenn du GitHub verwendest, siehst du den Pipeline-Status für deine Commits und Pull-Anfragen, auf GitHub. %{more_info_link}"
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
-msgstr "Wenn dein HTTP-Repository nicht öffentlich zugänglich ist, füge der URL Authentifizierungsinformationen hinzu: <code>https://benutzername:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
+msgstr ""
msgid "ImageDiffViewer|2-up"
msgstr "2-up"
@@ -6022,6 +6984,12 @@ msgstr "Importiere Repositories von GitHub"
msgid "Import repository"
msgstr "Repository importieren"
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr "Verbinde Repositories von"
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr "Verbessere Ticketboards mit der GitLab Enterprise Edition."
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr "Inkompatibles Projekt"
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr "Gibt an, ob dieser Runner Jobs ohne Tags auswählen kann"
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr "Inline"
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr "Installiere einen GitLab Runner"
msgid "Install Runner on Kubernetes"
msgstr "Installiere einen Runner auf Kubernetes"
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] "Instanz"
@@ -6174,18 +7178,42 @@ msgstr "Arbeitsablaufsanalysen vorgestellt"
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr "Einladen"
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr "Ticketereignisse"
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr "Board"
@@ -6300,6 +7340,48 @@ msgstr "Jan"
msgid "January"
msgstr "Januar"
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr "Job"
@@ -6396,6 +7478,12 @@ msgstr "Juli"
msgid "July"
msgstr "Juli"
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr "Juni"
@@ -6405,6 +7493,9 @@ msgstr "Juni"
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -6429,12 +7520,18 @@ msgstr "Kubernetes-Cluster wurde erfolgreich aktualisiert."
msgid "Kubernetes configured"
msgstr "Kubernetes konfiguriert"
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr "Die Kubernetes-Service-Integration wurde eingestellt. %{deprecated_message_content} deine Kubernetes-Cluster mit der neuen Seite <a href=\"%{url}\"/>Kubernetes-Cluster</a>"
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr "LFS"
@@ -6447,6 +7544,9 @@ msgstr "Deaktiviert"
msgid "LFSStatus|Enabled"
msgstr "Aktiviert"
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr "Label"
@@ -6481,7 +7581,7 @@ msgid "Labels can be applied to %{features}. Group labels are available for any
msgstr "Labels können auf %{features} angewendet werden. Gruppenlabels stehen für jedes Projekt innerhalb der Gruppe zur Verfügung."
msgid "Labels can be applied to issues and merge requests to categorize them."
-msgstr "Labels können Tickets und Merge-Requests hinzugefügt werden um diese zu kategorisieren."
+msgstr "Labels können Tickets und Merge-Requests hinzugefügt werden, um diese zu kategorisieren."
msgid "Labels can be applied to issues and merge requests."
msgstr "Labels können auf Tickets und Merge-Requests angewendet werden."
@@ -6495,6 +7595,9 @@ msgstr "Label hochstufen"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr "%{labelTitle} hochzustufen macht es für alle Projekte in %{groupName} verfügbar. Existierende Projektlabels mit dem selben Titel werden zusammengeführt. Diese Aktion kann nicht rückgängig gemacht werden."
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] "Letzten %d Tage"
msgid "Last Pipeline"
msgstr "Letzte Pipeline"
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr "Letzte Aktualisierung"
msgid "Last updated"
msgstr "Letzte Aktualisierung"
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr "Du hast gepusht zu"
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr "Erfahre mehr über Kubernetes"
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr "Erfahre mehr in den"
@@ -6602,6 +7726,12 @@ msgstr "Verlasse das Projekt"
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr "Belasse die Optionen \"Dateityp\" und \"Ãœbergabemethode\" auf ihren Standardwerten."
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr "Lizenz"
@@ -6677,6 +7807,9 @@ msgstr "URL"
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr "Du bist im Begriff, die Lizenz %{name} aus diesem Projekt zu entfernen."
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] "Anzeige beschränkt auf maximal %d Ereignis"
msgstr[1] "Anzeige beschränkt auf maximal %d Ereignisse"
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -6721,6 +7857,9 @@ msgstr "Live-Vorschau"
msgid "Loading contribution stats for group members"
msgstr "Beitragsstatistiken für Gruppenmitglieder laden"
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr "Laden der GitLab IDE..."
@@ -6742,6 +7881,9 @@ msgstr "Sperre %{issuableDisplayName}"
msgid "Lock not found"
msgstr "Sperrung nicht gefunden"
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr "%{issuableDisplayName} sperren? Es werden nur noch <strong>Projektmitglieder</strong> kommentieren können."
@@ -6760,6 +7902,9 @@ msgstr "Auf aktuelle Projekte beschränkt"
msgid "Locks give the ability to lock specific file or folder."
msgstr "Sperrungen bieten die Möglichkeit, bestimmte Dateien oder Ordner zu sperren."
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr "Mit Smartcard einloggen"
@@ -6770,10 +7915,10 @@ msgid "Logs"
msgstr "Protokolle"
msgid "MRApprovals|Approved by"
-msgstr ""
+msgstr "Genehmigt von"
msgid "MRApprovals|Approvers"
-msgstr ""
+msgstr "Genehmigungsberechtigte"
msgid "MRApprovals|Pending approvals"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr "Mache alle in deinem Team unabhängig von ihrem Standort produktiver. GitLab Geo erstellt schreibgeschützte Mirror deiner GitLab-Instanz, sodass du die Zeit zum Klonen und Abrufen großer Repos reduzieren kannst."
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr "Stelle sicher, dass du mit dem Konto angemeldet bist, welches Besitzer der zu importierenden Projekte ist."
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6833,13 +7987,13 @@ msgid "Manual job"
msgstr ""
msgid "Map a FogBugz account ID to a GitLab user"
-msgstr "Ordne eine FogBugz-Konto-ID einem/einer GitLab-Benutzer(in) zu"
+msgstr "Ordne eine FogBugz-Konto-ID einem/einer GitLab-Benutzer(in) zu"
msgid "Map a Google Code user to a GitLab user"
msgstr "Ordne eine(n) Google Code-Benutzer(in) einem/einer GitLab-Benutzer(in) zu"
msgid "Map a Google Code user to a full email address"
-msgstr "Ordne eine(n) Google Code-Benutzer(in) einer vollständige E-Mail-Adresse zu"
+msgstr "Ordne eine(n) Google Code-Benutzer(in) einer vollständigen E-Mail-Adresse zu"
msgid "Map a Google Code user to a full name"
msgstr "Ordne eine(n) Google Code-Benutzer(in) einem vollständigen Namen zu"
@@ -6850,6 +8004,15 @@ msgstr "März"
msgid "March"
msgstr "März"
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr "To-do als erledigt markieren"
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr "Markdown aktiviert"
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr "Maven-Metadaten"
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr "Maximale Job-Zeitüberschreitung"
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr "Merge-Request"
@@ -6928,15 +8106,9 @@ msgstr "Merge-Requests"
msgid "Merge Requests created"
msgstr "Merge_Request erstellt"
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr "Merge-Ereignisse"
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr "Merge-Request"
@@ -6959,7 +8125,7 @@ msgid "Merge request approvals"
msgstr "Merge-Request-Genehmigungen"
msgid "Merge request approvals allow you to set the number of necessary approvals and predefine a list of approvers that will need to approve every merge request in a project."
-msgstr ""
+msgstr "Merge-Request-Genehmigungen ermöglichen dir, die Zahl der notwendigen Genehmigungen festzulegen und eine Liste von Genehmigungsberechtigten anzulegen, die jeden Merge-Request in einem Projekt genehmigen müssen."
msgid "Merge requests"
msgstr "Merge-Requests"
@@ -6970,6 +8136,30 @@ msgstr "Merge-Requests dienen dazu, deine Änderungsvorschläge für ein Projekt
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr "Löse diese Diskussion in einem neuen Ticket"
msgid "MergeRequests|Saving the comment failed"
msgstr "Speichern des Kommentars fehlgeschlagen"
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr "Kommentare für diese Datei umschalten"
@@ -7033,8 +8229,8 @@ msgstr "%{paragraphStart}hat die Beschreibung %{descriptionChangedTimes} Mal %{t
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
-msgstr "Dateien filtern"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
+msgstr ""
msgid "MergeRequest|No files found"
msgstr "Keine Dateien gefunden"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr "Nachrichten"
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr "Metriken"
@@ -7063,6 +8265,9 @@ msgstr "Metriken und Profiling"
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "Sieh dir die CI/CD-Dokumentation zur Bereitstellung in einer Umgebung an"
@@ -7102,9 +8307,6 @@ msgstr "Neue Metrik"
msgid "Metrics|No deployed environments"
msgstr "Keine bereitgestellten Umgebungen"
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr "Y-Achsen-Bezeichnung"
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr "z. B. Durchsatz"
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr "Du bist dabei, den Meilenstein %{milestoneTitle} endgültig zu löschen
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr "Du bist dabei, den Meilenstein %{milestoneTitle} endgültig zu löschen. Dieser Meilenstein wird zur Zeit von keinem Ticket und keinem Merge-Request verwendet."
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr "<p>%{milestonePromotion}</p> %{finalWarning}"
-
msgid "Milestones|Delete milestone"
msgstr "Meilenstein löschen"
@@ -7198,8 +8409,8 @@ msgstr "%{milestoneTitle} zum Gruppenmeilenstein hochstufen?"
msgid "Milestones|Promote Milestone"
msgstr "Meilenstein hochstufen"
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
-msgstr "Die Hochstufung von %{milestone} wird ihn für alle Projekte innerhalb von %{groupName} verfügbar machen. Bereits existierende Projekt-Meilensteine mit dem selben Namen werden zusammengeführt. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
+msgstr ""
msgid "Milestones|This action cannot be reversed."
msgstr "Diese Aktion kann nicht rückgängig gemacht werden."
@@ -7207,6 +8418,15 @@ msgstr "Diese Aktion kann nicht rückgängig gemacht werden."
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr "Repository spiegeln"
@@ -7228,6 +8448,18 @@ msgstr "Spiegelnde Repositories"
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "einen SSH-Schlüssel hinzufügen"
@@ -7277,7 +8509,7 @@ msgid "More than %{number_commits_distance} commits different with %{default_bra
msgstr ""
msgid "Most stars"
-msgstr "Die meisten Sterne"
+msgstr "Favoriten"
msgid "Mount point %{mounted_as} not found in %{model_class}."
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr "Verschieben"
msgid "Move issue"
msgstr "Ticket verschieben"
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr "Mehrere Ticket-Boards"
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr "Name"
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr "Neues Label benennen"
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr "Neuer Epic"
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr "Neue Datei"
@@ -7419,6 +8675,9 @@ msgstr "Neuer Merge-Request"
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr "Neue Pipelines brechen ältere, ausstehende Pipelines in dem selben Branch ab"
@@ -7449,6 +8708,12 @@ msgstr "Neu..."
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr "Nein"
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr "Kein Label"
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr "Keine Branches gefunden"
@@ -7479,6 +8753,9 @@ msgstr "Es konnte keine Verbindung zu einem Gitaly-Server hergestellt werden. Bi
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr "Für dieses Projekt wurden keine Container-Images gespeichert. Füge eines hinzu, indem du den Anweisungen oben folgst."
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr "Keine Beiträge gefunden"
@@ -7503,6 +8780,9 @@ msgstr "Keine Datei ausgewählt"
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr "Keine Dateien gefunden."
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr "Keine Merge-Requests für den gewählten Zeitraum."
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr "Keine anderen Tags mit einem solchen Namen oder einer solchen Beschreibung"
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr "Nein, importiere die vorhandenen E-Mail-Adressen und Benutzernamen direkt."
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr "Knoten"
@@ -7617,6 +8903,9 @@ msgstr "Hinweis: Ãœberlege dir, deine(n) GitLab-Administrator(in) zu bitten, ein
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr "Hinweis: Überlege dir, deine(n) GitLab Administrator(in) zu bitten, einen %{github_integration_link} zu konfigurieren. Mit diesem kannst du dich über GitHub anmelden und Repositories importieren, ohne einen persönlichen Access-Token generieren zu müssen."
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "Bist du sicher, dass du die Erstellung dieses Kommentars abbrechen möchtest?"
@@ -7632,6 +8921,12 @@ msgstr "Nur Kommentare anzeigen"
msgid "Notes|Show history only"
msgstr "Nur Verlauf anzeigen"
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr "Benachrichtigungsereignisse"
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "Ticket schließen"
@@ -7695,6 +8993,9 @@ msgstr "Teilnehmen"
msgid "NotificationLevel|Watch"
msgstr "Beobachten"
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr "Benachrichtigungen"
@@ -7710,6 +9011,12 @@ msgstr "Nov"
msgid "November"
msgstr "November"
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr "OK"
@@ -7725,8 +9032,14 @@ msgstr "Oktober"
msgid "OfSearchInADropdown|Filter"
msgstr "Filter"
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
-msgstr "Nach dem Import können Repositories über SSH gespiegelt werden. Lies mehr %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
+msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
msgstr ""
@@ -7748,13 +9061,13 @@ msgstr "Ein oder mehrere deiner Bitbucket-Projekte kann/können nicht direkt in
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "Ein oder mehrere Ihrer Google Code-Projekte kann/können nicht direkt in GitLab importiert werden, da sie Subversion oder Mercurial für die Versionskontrolle anstelle von Git verwenden."
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
+msgstr ""
+
msgid "Only admins"
msgstr "Nur Administrator(inn)en"
-msgid "Only allow merge requests to be merged if all discussions are resolved"
-msgstr ""
-
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr "Nur Projektmitglieder können kommentieren."
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr "Ups, bist du sicher?"
@@ -7797,7 +9113,7 @@ msgid "Open raw"
msgstr ""
msgid "Open sidebar"
-msgstr "Menüleiste öffnen"
+msgstr "Seitenleiste öffnen"
msgid "Open source software to collaborate on code"
msgstr "Open-Source-Software für die Zusammenarbeit an Code"
@@ -7817,6 +9133,12 @@ msgstr "Erstellt"
msgid "Opens in a new window"
msgstr "Wird in einem neuen Fenster geöffnet"
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr "Vorgänge"
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr "Andere Labels"
msgid "Other information"
msgstr "Andere Informationen"
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr "Ausgehende Anfragen"
@@ -7874,6 +9196,12 @@ msgstr "Ãœbersicht"
msgid "Overwrite diverged branches"
msgstr "Ãœberschreibe abweichende Branches"
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr "Besitzer(in)"
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "Letzte »"
@@ -7922,9 +9253,21 @@ msgstr "Teil der Merge-Request-Änderungen"
msgid "Password"
msgstr "Passwort"
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,8 +9280,8 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
-msgstr "Füge deinen öffentlichen SSH-Schlüssel ein, der normalerweise in der Datei '~/.ssh/id_rsa.pub' enthalten ist und mit 'ssh-rsa' beginnt. Verwende nicht deinen privaten SSH-Schlüssel."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
msgid "Path"
msgstr ""
@@ -7964,6 +9307,9 @@ msgstr "In Arbeit"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr "Personen ohne Berechtigung werden nie eine Benachrichtigung bekommen und können auch nicht kommentieren."
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr "Führe erweiterte Optionen aus, wie z. B. das Ändern des Pfades, Übertragen oder Entfernen einer Gruppe."
@@ -7985,12 +9331,27 @@ msgstr "Persönlicher Zugangs-Token"
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr "Pipeline"
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr "Zeitplan der Pipeline"
@@ -8069,6 +9430,9 @@ msgstr "Pipelines"
msgid "Pipelines charts"
msgstr "Pipelinediagramme"
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr "Pipelines des letzten Monats"
@@ -8078,10 +9442,13 @@ msgstr "Pipelines der letzten Woche"
msgid "Pipelines for last year"
msgstr "Pipelines des letzten Jahres"
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr "Erste Schritte mit Pipelines"
msgid "Pipelines|Loading Pipelines"
msgstr "Pipelines laden"
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "Der Projekt-Cache wurde erfolgreich zurückgesetzt."
@@ -8162,6 +9532,9 @@ msgstr "Pipeline stoppen"
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr "Pipeline #%{pipelineId} stoppen?"
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr "Variabeln"
@@ -8192,6 +9565,15 @@ msgstr "mit Phase"
msgid "Pipeline|with stages"
msgstr "mit Phasen"
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr "Unformatierter Diff"
@@ -8201,12 +9583,30 @@ msgstr "PlantUML"
msgid "Play"
msgstr "Ausführen"
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr "Bitte akzeptiere die Nutzungsbedingungen, um fortzufahren."
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr "Bitte wähle eine Gruppen-URL ohne Sonderzeichen."
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr "Bitte gib einen beschreibenden Namen für deine Gruppe ein."
@@ -8249,6 +9652,15 @@ msgstr "Bitte beachte, dass diese Anwendung nicht von GitLab bereitgestellt wird
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,8 +9682,8 @@ msgstr "Bitte erneut versuchen"
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
-msgstr "Bitte verwende dieses Formular um Benutzer(innen) zu melden, die Spam-Tickets, -Kommentare erstellen oder sich unangemessen verhalten."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
+msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -8288,12 +9700,66 @@ msgstr "Einstellungen"
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr "Navigationsthema"
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr "Drücke Eingabe oder klicke um zu suchen"
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr "Vorschau"
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr "Vorschau der Nutzdaten"
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr "Primär"
@@ -8342,15 +9814,24 @@ msgstr "Privat - Die Gruppe und dessen Projekte können nur von Mitgliedern eing
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr "Private Projekte können in deinem persönlichen Namensraum erstellt werden:"
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr "Profil"
msgid "Profile Settings"
msgstr "Profileinstellungen"
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr "Du bist dabei, %{yourAccount} permanent zu löschen, inklusive aller Tickets, Merge-Requests und Gruppen die mit deinem Account verknüpft sind. Sobald du %{deleteAccount} bestätigst, kann diese Aktion nicht rückgängig gemacht werden."
@@ -8381,6 +9862,9 @@ msgstr "Avatar zuschneiden"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "Avatar wird entfernt. Bist du sicher?"
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr "Benutzernamen ändern"
@@ -8402,6 +9886,9 @@ msgstr "Status löschen"
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr "Aktueller Pfad: %{path}"
msgid "Profiles|Current status"
msgstr "Aktueller Status"
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr "Konto löschen"
@@ -8441,6 +9931,18 @@ msgstr "Profil bearbeiten"
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr "Ungültiges Kennwort"
msgid "Profiles|Invalid username"
msgstr "Ungültiger Benutzername"
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr "Erfahre mehr"
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr "Hat einen privaten Beitrag geleistet"
@@ -8462,18 +9970,33 @@ msgstr "Haupteinstellungen"
msgid "Profiles|No file chosen"
msgstr "Keine Datei ausgewählt"
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr "Pfad"
msgid "Profiles|Position and size your new avatar"
msgstr "Lege Position und Größe deines neuen Avatars fest"
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr "Private Beiträge"
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr "Öffentlicher Avatar"
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr "Avatar entfernen"
@@ -8492,11 +10015,8 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "Die maximal zulässige Dateigröße beträgt 200KB."
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
-msgstr "Das sieht nicht aus wie ein öffentlicher SSH-Schlüssel aus. Bist du sicher, dass du ihn hinzufügen willst?"
+msgstr "Das sieht nicht wie ein öffentlicher SSH-Schlüssel aus. Bist du sicher, dass du ihn hinzufügen willst?"
msgid "Profiles|This email will be displayed on your public profile"
msgstr ""
@@ -8510,20 +10030,23 @@ msgstr "Dieses Emoji und diese Nachricht werden in deinem Profil und auf der ges
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Gib deinen %{confirmationValue} zur Bestätigung ein:"
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
-msgstr "Beginnt normalerweise mit \"ssh-rsa ...\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
+msgstr ""
msgid "Profiles|Update profile settings"
msgstr "Profileinstellungen aktualisieren"
msgid "Profiles|Update username"
-msgstr "Benutzername aktualisieren"
+msgstr "Benutzernamen aktualisieren"
msgid "Profiles|Upload new avatar"
msgstr "Neuen Avatar hochladen"
@@ -8531,6 +10054,9 @@ msgstr "Neuen Avatar hochladen"
msgid "Profiles|Use a private email - %{email}"
msgstr "Private E-Mail verwenden - %{email}"
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr "Änderung des Benutzernamens fehlgeschlagen - %{message}"
@@ -8552,6 +10078,9 @@ msgstr "Du kannst deinen Avatar hier ändern"
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr "Du kannst deinen Avatar hier ändern oder den aktuellen Avatar entfernen, um zu %{gravatar_link} zurückzukehren"
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr "Du kannst deinen Avatar hier hochladen"
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr "Projektavatar"
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "Abonnieren"
@@ -8741,6 +10276,24 @@ msgstr "Du musst dich anmelden, um ein Projekt zu markieren"
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "Projekt ID: %{project_id}"
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr "Badges"
@@ -8750,18 +10303,60 @@ msgstr "Kontaktiere eine(n) Administrator(in), um diese Einstellung zu ändern."
msgid "ProjectSettings|Customize your project badges."
msgstr "Deine Projekt-Badges anpassen."
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr "Fehler beim Schützen des Tags"
msgid "ProjectSettings|Failed to update tag!"
msgstr "Fehler beim Aktualisieren des Tags!"
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr "Erfahre mehr über Badges."
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Nur signierte Commits können zu diesem Repository gepusht werden."
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr "Diese Einstellung wird auf Serverebene angewendet und kann von einem Admin überschrieben werden."
@@ -8771,12 +10366,72 @@ msgstr "Diese Einstellung wird auf Serverebene angewendet, wurde aber für diese
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "Diese Einstellung wird auf alle Projekte angewendet, sofern sie nicht von einem Admin überschrieben wird."
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr "Benutzer(innen) können nur Commits in dieses Repository pushen die mit einer ihrer eigenen verifizierten E-Mail-Adressen committet wurden."
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr "Projekte"
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8916,7 +10571,7 @@ msgid "PrometheusService|To enable manual configuration, uninstall Prometheus fr
msgstr "Deinstalliere Prometheus aus deinen Clustern, um die manuelle Konfiguration zu aktivieren"
msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
-msgstr "Deaktivier die manuelle Konfiguration unten, um die Installation von Prometheus auf deinen Clustern zu ermöglichen"
+msgstr "Deaktiviere unten die manuelle Konfiguration, um die Installation von Prometheus auf deinen Clustern zu ermöglichen"
msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
msgstr "Warte auf deine erste Bereitstellung in eine Umgebung, um allgemeine Metriken zu finden"
@@ -8933,6 +10588,15 @@ msgstr "Zum Gruppenmeilenstein hochstufen"
msgid "Promote to group label"
msgstr "Hochstufen zum Gruppenlabel"
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr "Nicht wieder anzeigen"
@@ -8951,36 +10615,48 @@ msgstr ""
msgid "Protected"
msgstr "Geschützt"
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr "Geschützte Umgebungen"
+msgid "Protected Tag"
+msgstr ""
+
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} wird für Entwickler änderbar sein. Bist du sicher?"
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "Für Bereitstellung zugelassen"
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
-msgstr "Wähle aus, wer die Bereitstellung durchführen darf"
-
msgid "ProtectedEnvironment|Environment"
msgstr "Umgebung"
msgid "ProtectedEnvironment|Protect"
msgstr "Schützen"
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr "Schütze Umgebungen um einzuschränken, wer Bereitstellungen ausführen darf."
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr "Schütze eine Umgebung"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr "Geschützte Umgebung (%{protected_environments_count})"
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr "Wähle eine Umgebung"
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr "Es gibt derzeit keine geschützten Umgebungen, schütze eine Umgebung mit dem Formular oben."
@@ -9029,9 +10705,15 @@ msgstr "Pull"
msgid "Push"
msgstr "Push"
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr "Push-Regeln"
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr "Pushed"
msgid "Pushes"
msgstr "Pushes"
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr "Quartale"
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr "Kurzbefehle können in Ticket-Beschreibungen und Kommentarfeldern verwendet werden."
@@ -9086,15 +10810,24 @@ msgstr "Echtzeit-Features"
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr "Zuletzt gesucht"
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr "Zu SAML-Provider umleiten um Konfiguration zu testen"
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] "In einer Sekunde aktualisieren, um den aktualisierten Status anzuzeigen..."
msgstr[1] "In %d Sekunden aktualisieren, um den aktualisierten Status anzuzeigen..."
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr "Schlüssel neu generieren"
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr "Regex-Muster"
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr "Anmelden"
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr "Registriere dich und sieh deine Runner für diese Gruppe."
msgid "Register and see your runners for this project."
msgstr "Registriere die Runner für dieses Projekt und zeige sie an."
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr "Zugehörige Merge-Requests"
msgid "Related Merged Requests"
msgstr "Zugehörige umgesetzte Merge-Requests"
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr "Zugehörige Merge-Requests"
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr "Später erinnern"
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr "Entfernen"
@@ -9172,34 +10932,49 @@ msgstr "Runner entfernen"
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
msgstr ""
-msgid "Remove approvers"
+msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approvers"
+msgstr "Genehmigungsberechtigte entfernen"
+
msgid "Remove approvers?"
+msgstr "Genehmigungsberechtigte entfernen?"
+
+msgid "Remove assignee"
msgstr ""
msgid "Remove avatar"
msgstr "Avatar entfernen"
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr "Gruppe entfernen"
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr "Priorität entfernen"
msgid "Remove project"
msgstr "Projekt entfernen"
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr "Entfernte Gruppe kann nicht wiederhergestellt werden!"
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr "Durch das Entfernen der Gruppe werden alle untergeordneten Projekte und Ressourcen entfernt."
@@ -9244,6 +11037,9 @@ msgstr "Authentifizierung reparieren"
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,8 +11049,8 @@ msgstr "Antworte direkt auf diese E-Mail oder %{view_it_on_gitlab}."
msgid "Repo by URL"
msgstr "Repo via URL"
-msgid "Report abuse to GitLab"
-msgstr "Missbrauch an GitLab melden"
+msgid "Report abuse to admin"
+msgstr ""
msgid "Reporting"
msgstr "Statusbericht"
@@ -9268,6 +11064,9 @@ msgstr "Aktionen"
msgid "Reports|Class"
msgstr "Klasse"
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr "Vertrauen"
@@ -9307,12 +11106,6 @@ msgstr "Ergebnisse der Testzusammenfassung werden analysiert"
msgid "Reports|Vulnerability"
msgstr "Sicherheitslücke"
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr "Keine geänderten Testergebnisse"
@@ -9367,16 +11160,25 @@ msgstr "Fordere alle Benutzer(innen) auf, die Nutzungsbedingungen und Datenschut
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Benötigt die Zustimmung von %{names}."
+msgstr[1] "Benötigt noch %{count} Zustimmungen von %{names}."
msgid "Requires approval."
msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr "Wiederhole diese Aufgabe"
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr "Wiederhole die Überprüfung"
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr "Roadmap"
@@ -9580,6 +11400,9 @@ msgstr "SAML SSO für %{group_name}"
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr "SSH-Schlüssel"
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr "SSH-Hostschlüssel"
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr "Öffentlicher SSH-Schlüssel"
@@ -9604,6 +11430,9 @@ msgstr "Speichern"
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr "Anwendung speichern"
@@ -9616,6 +11445,9 @@ msgstr "Änderungen vor dem Testen speichern"
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Zeitplan der Pipeline speichern"
@@ -9676,9 +11508,21 @@ msgstr "Suche nach Branches und Tags"
msgid "Search files"
msgstr "Dateien durchsuchen"
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr "Suche nach Projekten, Tickets usw."
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr "Projekt suchen"
msgid "Search projects"
msgstr "Projekte suchen"
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr "Suche Benutzer(innen)"
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr "Mehr Informationen"
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr "Das Sicherheits-Dashboard zeigt den neuesten Sicherheitsbericht an. Verwende es, um Schwachstellen zu finden und zu beheben."
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr "Überwache Sicherheitslücken in deinem Code"
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr "Pipeline %{pipelineLink} ausgelöst"
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr "Auswählen"
msgid "Select Archive Format"
msgstr "Archivierungsformat auswählen"
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr "Wähle eine Gruppe aus, die du einladen möchtest"
@@ -9853,6 +11715,9 @@ msgstr "Wähle eine existierendes Kubernetes-Cluster aus oder erstelle ein neues
msgid "Select branch/tag"
msgstr "Branch/Tag auswählen"
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr "Wenn du eine(n) GitLab-Benutzer(in) azswählst, wird in der Beschreibung
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr "E-Mail senden"
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr "Service-Desk"
@@ -9989,7 +11860,7 @@ msgid "Set a default template for issue descriptions."
msgstr ""
msgid "Set a number of approvals required, the approvers and other approval settings."
-msgstr ""
+msgstr "Lege eine Anzahl der erforderlichen Genehmigungen, die Genehmigungsberechtigten und andere Genehmigungseinstellungen fest."
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Lege ein Passwort für dein Konto fest, um mittels %{protocol} zu übertragen (push) oder abzurufen (pull)."
@@ -10000,21 +11871,24 @@ msgstr "Lege ein Vorlagen-Repository für Projekte in dieser Gruppe fest"
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr "Lege die Standardeinstellungen fest und beschränke die Sichtbarkeitsstufen. Konfiguriere die Importquellen und das Git-Zugriffsprotokoll."
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr "Lege ein Instanz-weites Vorlagen-Repository"
msgid "Set max session time for web terminal."
msgstr "Lege die maximale Sitzungszeit für das Web-Terminal fest."
+msgid "Set milestone"
+msgstr ""
+
msgid "Set new password"
msgstr ""
msgid "Set notification email for abuse reports."
msgstr "Benachrichtigungs-E-Mail für Missbrauchsberichte festlegen."
-msgid "Set number of approvers required before open merge requests can be merged"
-msgstr ""
-
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr "Lege Anforderungen für eine(n) Benutzer(in) fest, um sich anzumelden. Aktiviere die erforderliche Zwei-Faktor-Authentifizierung."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr "CI/CD einrichten"
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr "Richte dein Projekt so ein, dass Änderungen automatisch an ein anderes Repository gesendet bzw. von diesem abgerufen werden. Branches, Tags und Commits werden automatisch synchronisiert."
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr "ein Passwort festlegst"
@@ -10078,6 +11958,18 @@ msgstr "Leider konnten wir deinen Status nicht festlegen. Bitte versuche es spä
msgid "SetStatusModal|What's your status?"
msgstr "Wie ist dein Status?"
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr "Einstellungen"
@@ -10093,6 +11985,9 @@ msgstr "Geteilte Runner"
msgid "Shared projects"
msgstr "Geteilte Projekte"
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr "Durch Zurücksetzen der Pipeline-Minuten für diesen Namensraum werden die aktuell verwendeten Minuten auf Null gesetzt."
@@ -10105,9 +12000,18 @@ msgstr "Verwendete Pipeline-Minuten zurücksetzen"
msgid "Sherlock Transactions"
msgstr "Sherlock-Transaktionen"
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr "Befehl anzeigen"
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr "Neuste Version zeigen"
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr "Ãœbergeordnete Seiten anzeigen"
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr "Abmelden"
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr "Anmeldebeschränkungen"
msgid "Sign-up restrictions"
msgstr "Registrierungsbeschränkungen"
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr "Größe"
@@ -10203,6 +12125,9 @@ msgstr "Größe und Domain-Einstellungen für statische Webseiten"
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr "Slack-Anwendung"
@@ -10272,6 +12197,9 @@ msgstr "Etwas ist beim Ändern des Sperrzustandes von %{issuableDisplayName} sch
msgid "Something went wrong when toggling the button"
msgstr "Beim Umschalten des Buttons ist etwas schief gelaufen"
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr "Beim Abrufen der Kommentare ist etwas schiefgelaufen. Bitte versuche es
msgid "Something went wrong while fetching group member contributions"
msgstr "Beim Abrufen von Gruppenmitgliedsbeiträgen ist ein Fehler aufgetreten"
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr "Etwas ist beim Auflösen der Diskussion fehlgeschlagen. Versuche es spä
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr "Etwas lief schief, %{project} konnte nicht zum Dashboard hinzugefügt werden"
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr "Etwas ist schief gelaufen. Bitte versuche es erneut."
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr "Entschuldigung, keine Epics stimmten mit deiner Suche überein"
@@ -10386,6 +12320,9 @@ msgstr "Am unbeliebtesten"
msgid "SortOptions|Less weight"
msgstr "Niedrigere Gewichtung"
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr "Zuletzt angemeldet"
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr "Startdatum"
@@ -10492,7 +12435,7 @@ msgid "Squash commits"
msgstr "Squash Commits"
msgid "Stage"
-msgstr "Phase"
+msgstr "Vormerken"
msgid "Stage & Commit"
msgstr "Vormerken & Committen"
@@ -10512,6 +12455,9 @@ msgstr "Vorgemerkt %{type}"
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr "Markiere ein Label, um es zu einem priorisierten Label zu machen. Ordne die priorisierten Labels durch Ziehen an, um ihre relative Priorität zu ändern."
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr "Favorisieren"
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "Starte den Runner!"
@@ -10626,12 +12581,18 @@ msgstr "Speicherplatz"
msgid "Storage:"
msgstr "Speicher:"
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr "Untergruppen"
msgid "Subgroups and projects"
msgstr "Untergruppen und Projekte"
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr "Als Spam einreichen"
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr "Abonniert"
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr "Zu Branch/Tag wechseln"
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr "Informationen synchronisieren"
@@ -10800,18 +12836,30 @@ msgstr "Systemmetriken (benutzerdefiniert)"
msgid "System metrics (Kubernetes)"
msgstr "Systemmetriken (Kubernetes)"
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr "Tags"
msgid "Tags feed"
msgstr "Tags-Feed"
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr "Tags:"
@@ -10876,7 +12924,7 @@ msgid "TagsPage|This tag has no release notes."
msgstr "Dieses Tag enthält keine Versionshinweise."
msgid "TagsPage|Use git tag command to add a new one:"
-msgstr "Verwenden Sie den Befehl git tag, um einen neuen Tag hinzuzufügen:"
+msgstr "Verwende den Befehl git tag, um einen neuen Tag hinzuzufügen:"
msgid "TagsPage|Write your release notes or drag files here…"
msgstr "Schreibe deine Versionshinweise oder ziehen Dateien hier hinein…"
@@ -10893,6 +12941,9 @@ msgstr "Zielbranch"
msgid "Team"
msgstr "Team"
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr "Vorlage"
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "Nutzungsbedingungen und Datenschutzerklärung"
@@ -10920,6 +12974,33 @@ msgstr "Testabdeckung analysieren"
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr "Das Character-Highlighter hilft dir, die Betreffzeile auf %{titleLength} Zeichen zu beschränken und den Textkörper auf %{bodyLength} zu kürzen, damit sie in Git lesbar sind."
@@ -10973,6 +13057,9 @@ msgstr "Die Verbindung wird nach %{timeout} beendet. Verwende eine Clone/Push-Ko
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr "Die Bereitstellung dieses Jobs auf %{environmentLink} war nicht erfolgreich."
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "Die Ticketphase stellt die Zeit vom Anlegen eines Tickets bis zum Zuweisen zu einem Meilenstein oder dem Hinzufügen zu deinem Ticket-Board dar. Erstelle einen Ticket, damit dessen Daten hier erscheinen."
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "Das Kennwort, das zum Entschlüsseln des privaten Schlüssels erforderlich ist. Dies ist optional und der Wert wird im Ruhezustand verschlüsselt."
@@ -11072,9 +13174,21 @@ msgstr "Die Produktionsphase stellt die Gesamtzeit vom Anlegen eines Tickets bis
msgid "The project can be accessed by any logged in user."
msgstr "Auf das Projekt kann jede(r) angemeldete Nutzer(in) zugreifen."
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr "Auf das Projekt kann ohne Authentifizierung zugegriffen werden."
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr "Die Pseudonymizer-Datensammlung ist deaktiviert. Wenn sie aktiv ist, führt GitLab einen Hintergrundjob aus, der pseudonymisierte CSVs der GitLab-Datenbank erzeugt, die in dein konfiguriertes Objektspeicherverzeichnis hochgeladen werden."
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr "Das Repository für dieses Projekt existiert nicht."
msgid "The repository for this project is empty"
msgstr "Das Repository für dieses Projekt ist leer"
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr "Das Repository muss über <code>http://</code>, <code>https://</code> oder <code>git://</code> erreichbar sein."
@@ -11132,6 +13252,9 @@ msgstr "Die Testphase stellt die Zeit dar, die GitLab CI benötigt um die Pipeli
msgid "The time taken by each data entry gathered by that stage."
msgstr "Die Zeit, die jede Dateneingabe in dieser Phase benötigt."
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr "Die Aktualisierungsaktion wird nach %{number_of_minutes} Minuten abgebrochen. Verwende für große Repositories eine Clone / Push-Kombination."
@@ -11153,15 +13276,30 @@ msgstr "Die Benutzerzuordnung ist ein JSON-Dokument das festlegt, wie die E-Mail
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr "Die Benutzerzuordnung legt fest, wie die E-Mail-Adressen und Benutzernamen der FogBuz-Benutzer(innen), die an deinem Projekt teilnehmen, in GitLab importiert werden. Du kannst dies ändern, indem du die Tabelle unten ausfüllst."
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "Der mittlere aller erfassten Werte. Zum Beispiel ist für 3, 5, 9 der Median 5. Bei 3, 5, 7, 8 ist der Median (5+7)/2 = 6."
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr "Es gibt noch keine archivierten Projekte"
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr "Es gibt keine vorgemerkten Änderungen"
msgid "There are no unstaged changes"
msgstr "Es gibt keine nicht vorgemerkten Änderungen"
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr "Beim Hinzufügen eines To-dos ist ein Fehler aufgetreten."
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr "Beim Löschen des To-dos ist ein Fehler aufgetreten."
@@ -11213,6 +13366,12 @@ msgstr "Beim Laden des Benutzeraktivitäts-Kalenders ist ein Fehler aufgetreten.
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr "Beim Abonnieren dieses Labels ist ein Fehler aufgetreten."
msgid "There was an error when unsubscribing from this label."
msgstr "Beim Abmelden von der Abonnierung dieses Labels ist ein Fehler aufgetreten."
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr "Können unter %{link} verwaltet werden."
msgid "Third party offers"
msgstr "Angebote von Drittanbietern"
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr "Diese GitLab-Instanz stellt noch keine geteilten Runner bereit. Instanz-
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr "Diese Anwendung wurde erstellt von %{link_to_owner}."
msgid "This application will be able to:"
msgstr "Diese Anwendung wird in der Lage sein:"
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr "Der Umfang dieses Boards ist reduziert"
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr "Dieser Branch wurde verändert, seit du begonnen hast ihn zu bearbeiten. Möchtest du einen neuen Branch anlegen?"
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr "Dieses Datum ist nach dem Fälligkeitsdatum, daher erscheint dieses Epic
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr "Dieses Datum ist vor dem Startdatum, daher erscheint dieses Epic nicht in der Roadmap."
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr "Dieser Diff ist reduziert."
@@ -11303,6 +13486,9 @@ msgstr "Dieses Verzeichnis"
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,24 +13498,33 @@ msgstr "Diese Gruppe"
msgid "This group does not provide any group Runners yet."
msgstr "Diese Gruppe stellt noch keine Gruppenrunner zur Verfügung."
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr "Dies ist ein vertrauliches Ticket."
msgid "This is a delayed job to run in %{remainingTime}"
msgstr "Dies ist ein in %{remainingTime} auszuführender verzögerter Job"
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr "Dies ist der erste Merge-Request des Autors für dieses Projekt."
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
+msgid "This is your current session"
+msgstr ""
+
msgid "This issue is confidential"
msgstr "Dieses Ticket ist vertraulich"
-msgid "This issue is confidential and locked."
-msgstr "Dieses Ticket ist vertraulich und gesperrt."
-
msgid "This issue is locked."
msgstr "Dieses Ticket ist gesperrt."
@@ -11399,12 +13594,6 @@ msgstr "Dies bedeutet, dass du keinen Code pushen kannst, bevor du kein leeres R
msgid "This merge request is locked."
msgstr "Dieser Merge-Request ist gesperrt."
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr "Diese E-Mails werden automatisch zu hier gelisteten Tickets (wobei die Kommentare zur E-Mail-Konversation werden)."
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr "Zeit bis ein Ticket geplant wird"
@@ -11661,6 +13856,9 @@ msgstr "Tipp:"
msgid "Title"
msgstr "Titel"
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr "Um einen SSH-Schlüssel hinzuzufügen, musst du %{generate_link_start}einen generieren%{link_end} oder einen %{existing_link_start}vorhandenen Schlüssel%{link_end} verwenden."
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr "Um GitHub-Repositories zu verbinden kannst du einen %{personal_access_token_link} verwenden. Wenn du deinen persönlichen Access-Token erzeugst, musst du den Gültigkeitsbereich <code>repo</code> auswählen, damit wir eine Liste deiner öffentlichen und privaten Repositories anzeigen können, die für die Verbindung verfügbar sind."
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr "So richtest du die SAML-Authentifizierung für deine Gruppe über einen Identitätsanbieter wie Azure, Okta, Onelogin, Ping Identity oder deinen benutzerdefinierten SAML 2.0-Anbieter ein:"
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr "Um deine Jobs zur Verfügung zu stellen, kannst du Runner zu deiner Gruppe hinzufügen"
@@ -11778,6 +13982,9 @@ msgstr "To-dos"
msgid "Toggle Sidebar"
msgstr "Seitenleiste ein-/ausblenden"
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr "Diskussion ein-/ausblenden"
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Navigation umschalten"
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Seitenleiste ein-/ausblenden"
@@ -11802,6 +14015,9 @@ msgstr "Toggle Status: OFF"
msgid "ToggleButton|Toggle Status: ON"
msgstr "Toggle Status: ON"
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr "Token"
@@ -11844,6 +14060,42 @@ msgstr "Verfolge die Zeit mit Kurzbefehlen"
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr "Baumstrukturansicht"
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr "Teste für 30 Tage alles was GitLab zu bieten hat."
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "Aktiviere den Service-Desk"
msgid "Twitter"
msgstr "Twitter"
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr "Zwei-Faktor-Authentifizierung"
msgid "Type"
msgstr "Typ"
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr "Der Diff konnten nicht geladen werden. %{button_try_again}"
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "Aufgrund von \"%{reason}\" konntest du dich nicht mit SAML anmelden"
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr "Dieses Epic kann gerade nicht aktualisiert werden."
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr "Unbekannt"
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr "Entsperren"
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr "Dieses %{issuableDisplayName} entsperren? <strong>Jeder</strong> wird in der Lage sein zu kommentieren."
msgid "Unlocked"
msgstr "Entsperrt"
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr "Diskussion wieder starten"
@@ -12013,7 +14313,7 @@ msgid "Update"
msgstr "Aktualisieren"
msgid "Update approvers"
-msgstr ""
+msgstr "Genehmigungsberechtigte aktualisieren"
msgid "Update failed"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr "Deine Gruppenbezeichnung, Beschreibung, Avatar und Sichtbarkeit anpassen
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr "Datei hochladen"
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr "Zum Upload klicken"
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr "Der Nutzungsbericht ist nicht aktiviert"
msgid "Usage statistics"
msgstr "Nutzungsstatistiken"
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr "Verwende <code>%{native_redirect_uri}</code> für lokale Tests"
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "Nutze den Service-Desk, um dich direkt in GitLab via E-Mail mit deinen Benutzer(inne)n zu verbinden (z. B. um Kunden-Support anzubieten)"
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr "Verwende Gruppenmeilensteine, um Tickets aus mehreren Projekten im selben Meilenstein zu verwalten."
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr "Benutzerzuordnung"
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr "Aktivität"
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr "Benutzer(innen)"
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,21 +14864,30 @@ msgstr "Version"
msgid "View app"
msgstr "App anzeigen"
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
-msgid "View eligible approvers"
+msgid "View documentation"
msgstr ""
+msgid "View eligible approvers"
+msgstr "Geeignete Genehmigungsberechtigte anzeigen"
+
msgid "View epics list"
msgstr "Epic-Liste anzeigen"
msgid "View file @ "
msgstr "Zeige Datei @ "
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr "Gruppenlabels ansehen"
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr "Sieh es auf GitLab an"
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr "Die Dokumentation anzeigen"
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr "Sichtbarkeit und Zugriffskontrollen"
@@ -12405,6 +14957,33 @@ msgstr "Öffentlich"
msgid "VisibilityLevel|Unknown"
msgstr "Unbekannt"
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr "Schweregrad"
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Du möchtest die Daten sehen? Bitte frage eine(n) Administrator(in) nach dem Zugang."
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "Wir haben potenziellen Spam in %{humanized_resource_name} gefunden. Bitte löse den reCAPTCHA um fortzufahren."
@@ -12474,6 +15059,9 @@ msgstr "Es liegen nicht genügend Daten vor, um diese Phase anzuzeigen."
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "Wir wollen sicher gehen, dass du es bist. Bitte bestätige, dass du kein Roboter bist."
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr "Webhooks ermöglichen es dir eine URL aufzurufen, wenn z. B. neuer Code gepusht oder ein neues Ticket erstellt wird. Du kannst Webhooks so konfigurieren, dass sie auf bestimmte Ereignisse wie Pushes, Tickets oder Merge-Requests reagieren. Gruppen-Webhooks werden auf alle Projekte in einer Gruppe angewendet, so dass du die Webhook-Funktionalität in der gesamten Gruppe standardisieren kannst."
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr "Wochen"
@@ -12504,17 +15095,20 @@ msgstr "Gewichtung"
msgid "Weight %{weight}"
msgstr "Gewichtung %{weight}"
+msgid "Welcome to the Guided GitLab Tour"
+msgstr ""
+
+msgid "Welcome to your Issue Board!"
+msgstr ""
+
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Wenn ein Runner gesperrt ist, kann er keinem anderen Projekt zugewiesen werden"
msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr "Wenn diese Option aktiviert ist, können Benutzer(innen) GitLab nicht verwenden, bis die Bedingungen akzeptiert wurden."
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
-msgstr "Wenn die URL leer gelassen wird, können Klassifizierungslabels weiterhin angegeben werden ohne projektübergreifende Eigenschaften auszuschalten oder einen externen Autorisierungscheck durchzuführen."
+msgstr "Wenn die URL leer gelassen wird, können Klassifizierungslabels weiterhin angegeben werden, ohne projektübergreifende Eigenschaften auszuschalten oder einen externen Autorisierungscheck durchzuführen."
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr "Wer kann diese Gruppe sehen?"
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr "Ja"
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr "Ja, füg' es hinzu"
@@ -12719,8 +15319,14 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr "Du bist Administrator(in). Wenn du <strong>%{client_name}</strong> Zugriff gewährst, wird es auch als Administrator mit GitLab interagieren können. Mit Vorsicht fortfahren."
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "Du bist dabei %{group_name} zu entfernen. Entfernte Gruppen können NICHT wiederhergestellt werden! Bist du dir WIRKLICH sicher?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "Du bist dabei %{project_full_name} zu entfernen. Entfernte Projekte können NICHT wiederhergestellt werden! Bist Du dir WIRKLICH sicher?"
@@ -12731,6 +15337,9 @@ msgstr "Du bist dabei, die Beziehung des Forks zum Ursprungsprojekt %{forked_fro
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr "Du bist dabei %{project_full_name} einem/einer andere(n) Besitzer(in) zu übergeben. Bist du dir WIRKLICH sicher?"
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr "Du kannst stattdessen %{linkStart}den Blob anzeigen%{linkEnd}."
msgid "You can also create a project from the command line."
msgstr "Du kannst ein Projekt auch über die Kommandozeile erstellen."
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr "Du kannst auch ein Label markieren, um es zu einem Prioritätslabel zu machen."
@@ -12759,11 +15374,20 @@ msgid "You can create files directly in GitLab using one of the following option
msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
-msgstr "Du kannst einfach dazu beitragen, indem du um Beitritt zu dieser Gruppen bittest."
+msgstr "Du kannst einfach dazu beitragen, indem du um Aufnahme in diesen Gruppen bittest."
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr "Du kannst ganz einfach einen Runner auf einem Kubernetes-Cluster installieren. %{link_to_help_page}"
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr "Du kannst das Diagramm mit den Pfeiltasten bewegen."
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "Du kannst den Merge-Konflikt lösen, indem du entweder den interaktiven Modus verwendest, indem du die Schaltflächen %{use_ours} oder %{use_theirs} wählst, oder indem du die Dateien direkt bearbeitest. Übernimm diese Änderungen mittels Commit in %{branch_name}"
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr "Du kannst Jobs so einrichten, dass nur Runner mit bestimmten Tags verwendet werden. Trenne die Tags durch Kommas."
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr "Du kannst deine .gitlab-ci.yml mit %{linkStart}CI Lint%{linkEnd} testen."
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr "Du hast noch keine Abonnements"
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr "Du verfügst nicht über die erforderlichen Berechtigungen um die Einstellungen der LDAP-Gruppensynchronisierung zu überschreiben."
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr "Du hast keine Anwendungen"
@@ -12836,6 +15475,12 @@ msgstr "Du hast keine autorisierten Anwendungen"
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12849,7 +15494,7 @@ msgid "You have no permissions"
msgstr "Du hast keine Berechtigungen"
msgid "You have not added any approvers. Start by adding users or groups."
-msgstr ""
+msgstr "Du hast keine Genehmigungsberechtigten hinzugefügt. Beginne, indem du Benutzer(innen) oder Gruppen hinzufügst."
msgid "You have reached your project limit"
msgstr "Du hast die Projektbegrenzung erreicht"
@@ -12866,6 +15511,15 @@ msgstr "Du musst unsere Nutzungsbedingungen und Datenschutzerklärung akzeptiere
msgid "You must have maintainer access to force delete a lock"
msgstr "Du musst Betreuerzugriff besitzen, um das Entfernen einer Sperre zu erzwingen"
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr "Du benötigst eine andere Lizenz, um die FileLocks-Funktion zu aktivieren"
@@ -12878,6 +15532,9 @@ msgstr "Du benötigst git-lfs in Version %{min_git_lfs_version} (oder höher) um
msgid "You need permission."
msgstr "Du brauchst eine Genehmigung."
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr "Du kannst erst mittels SSH übertragen (push) oder abrufen (pull), nachd
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "Du musst einen deinem Profil einen SSH-Schlüssel hinzufügen, bevor du deinen Projekt-Code mittels Pull oder Push über SSH übertragen kannst"
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr "Du musst unterschiedliche Branchnamen verwenden, um einen gültigen Vergleich zu erhalten."
@@ -12944,27 +15607,51 @@ msgstr "Du erhältst diese E-Mail aufgrund deines Accounts auf %{host}."
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr "Du erhältst diese E-Mail aufgrund deines Kontos auf %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr "YouTube"
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr "Deine Gruppen"
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr "Die Informationen zu deinem Kubernetes-Cluster auf dieser Seite können weiterhin bearbeitet werden. Es wird jedoch empfohlen, die Konfiguration zu deaktivieren und neu zu konfigurieren"
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr "Deine Projekte (Standard)"
msgid "Your Projects' Activity"
msgstr "Aktivitäten deiner Projekte"
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr "Deine To-dos"
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,8 +15685,11 @@ msgstr "Deine Änderungen wurden gespeichert"
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
-msgstr "Dein Kommentar wird nicht öffentlich sichtbar sein."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
+msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
msgstr ""
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr "Dein Name"
@@ -13049,12 +15742,15 @@ msgstr "vor"
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
-msgstr "unter anderem"
+msgid "already being used for another group or project milestone."
+msgstr ""
-msgid "at"
+msgid "already shared with this group"
msgstr ""
+msgid "among other things"
+msgstr "unter anderem"
+
msgid "attach a new file"
msgstr ""
@@ -13067,6 +15763,21 @@ msgstr "Branch-Name"
msgid "by"
msgstr "von"
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr "%{linkStartTag}Lerne mehr über Containerüberprüfung%{linkEndTag}"
@@ -13160,6 +15871,9 @@ msgstr "(wird geladen)"
msgid "ciReport|(is loading, errors when loading results)"
msgstr "(Lädt, Fehler beim Laden der Ergebnisse)"
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr "DAST"
@@ -13211,12 +15922,6 @@ msgstr "Abhängigkeitsüberprüfung"
msgid "ciReport|Description"
msgstr "Beschreibung"
-msgid "ciReport|Dismiss vulnerability"
-msgstr "Sicherheitslücke ausblenden"
-
-msgid "ciReport|Dismissed by"
-msgstr "Abgelehnt von"
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr "Fehler beim Laden des Abhängigkeitsprüfungs-Berichtes"
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr "Fehler beim Wiedereinblenden. Bitte versuche es erneut."
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr "Upgrade %{name} von %{version} zu %{fixed}."
@@ -13355,12 +16057,12 @@ msgstr[1] "Verwendet von %{packagesString} und %{lastPackage}"
msgid "ciReport|View full report"
msgstr "Gesamten Bericht anzeigen"
-msgid "ciReport|on pipeline"
-msgstr "in der Pipeline"
-
msgid "commented on %{link_to_project}"
msgstr ""
+msgid "commit %{commit_id}"
+msgstr ""
+
msgid "confidence|Confirmed"
msgstr ""
@@ -13386,7 +16088,7 @@ msgid "confidence|Unknown"
msgstr ""
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr "Du willst die Vertraulichkeit deaktivieren. Das bedeutet, dass <strong>jeder</strong> das Ticket betrachten und kommentieren kann."
+msgstr "Du willst die Vertraulichkeit deaktivieren. Das bedeutet, dass <strong>alle</strong> das Ticket betrachten und kommentieren können."
msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
msgstr "Du willst die Vertraulichkeit aktivieren. Das bedeutet, dass nur Teammitglieder mit <strong>mindestens Reporter-Zugriff</strong> das Ticket betrachten und kommentieren können."
@@ -13400,6 +16102,9 @@ msgstr "konnte den privaten Schlüssel nicht lesen, ist die Passphrase korrekt?"
msgid "customize"
msgstr "anpassen"
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] "Tag"
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] "Entwurf"
msgstr[1] "Entwürfe"
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr "aktiviert"
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr "%{slash_command} aktualisiert die geschätzte Zeit mit dem aktuellsten Befehl."
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr "von"
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr "hier"
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] "Instanz abgeschlossen"
msgstr[1] "Instanzen abgeschlossen"
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr "ist ungültig, weil es eine Downstream-Sperre gibt"
@@ -13507,6 +16233,9 @@ msgstr "ist aufgrund einer Upstream-Sperre ungültig"
msgid "is not a valid X509 certificate."
msgstr "ist kein gültiges X509-Zertifikat."
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] "Merge-Request"
msgstr[1] "Merge-Requests"
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,8 +16313,8 @@ msgstr "%{metricsLinkStart} Speicherauslastung %{metricsLinkEnd} %{emphasisStart
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "%{metricsLinkStart} Speicherauslastung %{metricsLinkEnd} ist %{emphasisStart} unverändert %{emphasisEnd} bei %{memoryFrom} MB"
-msgid "mrWidget|Add approval"
-msgstr "Genehmigung hinzufügen"
+msgid "mrWidget|Added to the merge train by"
+msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "Erlaube Commits von Mitgliedern die zum Zielbranch mergen können"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "Während des Sendens deiner Genehmigung trat ein Fehler auf."
+msgid "mrWidget|Approval password is invalid."
+msgstr "Falsches Zustimmungspasswort."
+
msgid "mrWidget|Approve"
msgstr "Genehmigen"
@@ -13647,6 +16385,9 @@ msgstr "Fehler beim Laden der Bereitstellungsstatistiken"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr "Schnelles Mergen ist nicht möglich. Um diesen Merge_request zu mergen, rebase zuerst lokal."
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr "Wenn der %{branch} Branch in deinem lokalen Repository existiert kannst du den Merge-Request manuell mergen mit Hilfe des"
@@ -13665,17 +16406,14 @@ msgstr "Merge"
msgid "mrWidget|Merge failed."
msgstr "Merge fehlgeschlagen."
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
+msgstr ""
+
msgid "mrWidget|Merge locally"
msgstr "Lokal mergen"
-msgid "mrWidget|Merge request approved"
-msgstr "Merge-Request genehmigt"
-
msgid "mrWidget|Merge request approved."
-msgstr ""
-
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr "Merge-Request genehmigt; du kannst zusätzlich genehmigen"
+msgstr "Merge-Request genehmigt."
msgid "mrWidget|Merged by"
msgstr "Merged von"
@@ -13707,22 +16445,12 @@ msgstr "Jetzt aktualisieren"
msgid "mrWidget|Refreshing now"
msgstr "Aktualisiere gerade"
-msgid "mrWidget|Remove your approval"
-msgstr "Entferne deine Genehmigung"
+msgid "mrWidget|Remove from merge train"
+msgstr ""
msgid "mrWidget|Request to merge"
msgstr "Anfrage zum Mergen"
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] "Erfordert 1 weitere Genehmigung"
-msgstr[1] "Erfordert %d weitere Genehmigungen"
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] "Erfordert 1 weitere Genehmigung durch"
-msgstr[1] "Erfordert %d weitere Genehmigungen durch"
-
msgid "mrWidget|Resolve conflicts"
msgstr "Konflikte auflösen"
@@ -13796,7 +16524,7 @@ msgid "mrWidget|You can delete the source branch now"
msgstr ""
msgid "mrWidget|You can merge this merge request manually using the"
-msgstr "Du kannst diesen Merge-Request manuell mergen mit dem"
+msgstr "Du kannst diesen Merge-Request manuell mergen mit der"
msgid "mrWidget|branch does not exist."
msgstr "Branch existiert nicht."
@@ -13807,15 +16535,30 @@ msgstr "Befehlszeile"
msgid "mrWidget|into"
msgstr "hinein"
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr "wird automatisch zusammengeführt, wenn die Pipeline erfolgreich ist"
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr "nicht verfügbar"
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr "Neuer Merge-Request"
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr "Quelle"
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} aktualisiert die Summe der aufgewendeten Zeit."
msgid "started"
msgstr "gestartet"
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr "verwendet Kubernetes-Cluster, um deinen Code bereitzustellen!"
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr "sieh es auf GitLab an"
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "mit %{additions} Ergänzungen, %{deletions} Löschungen."
diff --git a/locale/el_GR/gitlab.po b/locale/el_GR/gitlab.po
index 142d421aed0..71834d27dde 100644
--- a/locale/el_GR/gitlab.po
+++ b/locale/el_GR/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Greek\n"
"Language: el_GR\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: el\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:39\n"
+"PO-Revision-Date: 2019-06-14 10:19\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,37 +1459,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1856,6 +2161,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
index ef131535e9d..6cccd00890c 100644
--- a/locale/eo/gitlab.po
+++ b/locale/eo/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Esperanto\n"
"Language: eo_UY\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: eo\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:38\n"
+"PO-Revision-Date: 2019-06-14 10:25\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr "Aldoni novan dosierujon"
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,6 +1459,18 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
+msgid "Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr ""
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to delete this list?"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Ĉu vi certe volas forigi ĉi tiun ĉenstablan planon?"
@@ -1274,18 +1492,6 @@ msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove approver %{name}?"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}?"
-msgstr ""
-
msgid "Are you sure you want to remove the attachment?"
msgstr ""
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Alkroĉu dosieron per Åovmetado aÅ­ %{upload_link}"
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Serĉu branĉon"
@@ -1856,6 +2161,21 @@ msgstr "Elekti dosierojn"
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "de"
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "Elekti en branĉon"
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr "Diagramoj"
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr "Precize elekti ĉi tiun kunmetadon"
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr "transsaltita"
msgid "CiStatus|running"
msgstr "plenumiÄanta"
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr "Kopii la adreson en la kopibufron"
@@ -3166,6 +3624,12 @@ msgstr "Kopii la identigilon de la enmetado"
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr "Etikedo"
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "Disponigado"
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr "Ne montru denove"
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "Redakti ĉenstablan planon %{id}"
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr "Ne eblas ÅanÄi la posedanton"
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr "Dosieroj"
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Disbranĉigita el"
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr "La refreÅigo komenciÄis sukcese"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr "Enporti deponejon"
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr "Ni prezentas al vi la ciklan analizon"
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr "MalÅaltita"
msgid "LFSStatus|Enabled"
msgstr "Åœaltita"
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] "La lastaj %d tagoj"
msgid "Last Pipeline"
msgstr "Lasta ĉenstablo"
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr "Lernu pli en la"
@@ -6602,6 +7726,12 @@ msgstr "Forlasi la projekton"
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "aldonos SSH-Ålosilon"
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr "Nova dosiero"
@@ -7419,6 +8675,9 @@ msgstr "Nova peto pri kunfando"
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr "Sciigaj eventoj"
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "Fermi problemon"
@@ -7695,6 +8993,9 @@ msgstr "Partoprenado"
msgid "NotificationLevel|Watch"
msgstr "Rigardado"
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr "Filtrilo"
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr "Malfermita"
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr "Posedanto"
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr "Ĉenstablo"
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr "Ĉenstabla plano"
@@ -8069,6 +9430,9 @@ msgstr "Ĉenstabloj"
msgid "Pipelines charts"
msgstr "Ĉenstablaj diagramoj"
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr "kun etapo"
msgid "Pipeline|with stages"
msgstr "kun etapoj"
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr "Rilataj petoj pri kunfando"
msgid "Related Merged Requests"
msgstr "Rilataj aplikitaj petoj pri kunfando"
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr "Rememorigu denove"
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr "Forigi la projekton"
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Konservi ĉenstablan planon"
@@ -9676,9 +11508,21 @@ msgstr "Serĉu branĉon aŭ etikedon"
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr "Elektu formaton de arkivo"
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr "kreos pasvorton"
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr "Steligi"
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr "Iri al branĉo/etikedo"
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr "Etikedoj"
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "La etapo de la problemo montras kiom la tempo pasas de la kreado de problemo Äis la atribuado de la problemo al cela etapo de la projekto, aÅ­ al listo sur la problemtabulo. Komencu krei problemojn por vidi la datenojn por ĉi tiu etapo."
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr "La etapo de eldonado montras la tutan tempon de la kreado de problemo Ä
msgid "The project can be accessed by any logged in user."
msgstr "Ĉiu ensalutita uzanto havas atingon al la projekto"
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr "Ĉiu povas havi atingon al la projekto, sen ensaluti"
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr "La deponejo por ĉi tiu projekto ne ekzistas."
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr "La etapo de testado montras kiom da tempo necesas al „GitLab CI“ por
msgid "The time taken by each data entry gathered by that stage."
msgstr "La tempo, kiu estas necesa por ĉiu dateno kolektita de la etapo."
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "La valoro, kiu troviÄas en la mezo de aro da rigardataj valoroj. Ekzemple: inter 3, 5 kaj 9, la mediano estas 5. Inter 3, 5, 7 kaj 8, la mediano estas (5+7)/2 = 6."
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr "Ĉi tiu signifas, ke vi ne povos alpuÅi kodon, antaÅ­ ol vi kreos malpl
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr "Tempo antaÅ­ problemo estas planita por ellabori"
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr "AlÅuti dosieron"
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr "alklaku por alÅuti"
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr "Publika"
msgid "VisibilityLevel|Unknown"
msgstr "Nekonata"
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Ĉu vi volas vidi la datenojn? Bonvolu peti atingeblon de administranto."
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr "Ne estas sufiĉe da datenoj por montri ĉi tiun etapon."
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,8 +15319,14 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "Vi forigos „%{group_name}“. Oni NE POVAS malfari la forigon de grupo! Ĉu vi estas ABSOLUTE certa?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
@@ -12731,6 +15337,9 @@ msgstr "Vi forigos la rilaton de la disbranĉigo al la originala projekto, „%{
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr "VI bezonas permeson."
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr "Vi ne povos eltiri aÅ­ alpuÅi kodon per SSH antaÅ­ ol vi %{add_ssh_key_
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr "Via nomo"
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] "tago"
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr "novan peton pri kunfando"
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po
index 0775ef83503..2d61063f6a1 100644
--- a/locale/es/gitlab.po
+++ b/locale/es/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Spanish\n"
"Language: es_ES\n"
"MIME-Version: 1.0\n"
@@ -13,19 +13,16 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: es-ES\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:32\n"
+"PO-Revision-Date: 2019-06-14 10:17\n"
msgid " Please sign in."
msgstr " Por favor, inicie sesión."
-msgid " Status"
-msgstr " Estado"
-
msgid " Try to %{action} this file again."
-msgstr ""
+msgstr " Intente %{action} este archivo de nuevo."
msgid " You need to do this before %{grace_period_deadline}."
-msgstr ""
+msgstr "Necesita hacer esto antes de %{grace_period_deadline}."
msgid " and"
msgstr " y"
@@ -67,20 +64,25 @@ msgstr[1] "%d commits detrás"
msgid "%d commits"
msgstr "%d commits"
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] "%d contribución"
+msgstr[1] "%d contribuciones"
+
msgid "%d exporter"
msgid_plural "%d exporters"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d exportador"
+msgstr[1] "%d exportadores"
msgid "%d failed test result"
msgid_plural "%d failed test results"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d resultado de prueba fallido"
+msgstr[1] "%d resultados de prueba fallidos"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d solucionado el resultado de la prueba"
+msgstr[1] "%d solucionados los resultados de la prueba"
msgid "%d issue"
msgid_plural "%d issues"
@@ -89,8 +91,8 @@ msgstr[1] "%d incidencias"
msgid "%d issue selected"
msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d incidencia seleccionada"
+msgstr[1] "%d incidencias seleccionadas"
msgid "%d layer"
msgid_plural "%d layers"
@@ -99,6 +101,11 @@ msgstr[1] "%d capas"
msgid "%d merge request"
msgid_plural "%d merge requests"
+msgstr[0] "%d merge request"
+msgstr[1] "%d merge requests"
+
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
@@ -107,6 +114,11 @@ msgid_plural "%d metrics"
msgstr[0] "%d métrica"
msgstr[1] "%d métricas"
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] "%d comentarios más"
+msgstr[1] "%d comentarios más"
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -123,27 +135,24 @@ msgstr[0] "%s cambio adicional ha sido omitido para evitar problemas de rendimie
msgstr[1] "%s cambios adicionales han sido omitidos para evitar problemas de rendimiento."
msgid "%{actionText} & %{openOrClose} %{noteable}"
-msgstr ""
+msgstr "%{actionText} & %{openOrClose} %{noteable}"
msgid "%{authorsName}'s discussion"
msgstr "Discusión de %{authorsName}"
msgid "%{commit_author_link} authored %{commit_timeago}"
-msgstr ""
-
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
+msgstr "%{commit_author_link} escribió %{commit_timeago}"
-msgid "%{count} %{alerts}"
-msgstr "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
+msgstr "%{counter_repositories} repositorios, %{counter_wikis} wikis, %{counter_build_artifacts} artefactos, %{counter_lfs_objects} LFS"
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} se requiere la aprobación de %{name}"
+msgstr[1] "%{count} se requieren las aprobaciones de %{name}"
msgid "%{count} approvals from %{name}"
-msgstr ""
+msgstr "%{count} aprobaciones de %{name}"
msgid "%{count} more"
msgstr "%{count} más"
@@ -152,7 +161,7 @@ msgid "%{count} more assignees"
msgstr "%{count} asignados más"
msgid "%{count} of %{required} approvals from %{name}"
-msgstr ""
+msgstr "%{count} de %{required} aprobaciones de %{name}"
msgid "%{count} of %{total}"
msgstr "%{count} de %{total}"
@@ -164,8 +173,14 @@ msgstr[1] "%{count} participantes"
msgid "%{count} pending comment"
msgid_plural "%{count} pending comments"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} comentario pendiente"
+msgstr[1] "%{count} comentarios pendientes"
+
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr "%{edit_in_new_fork_notice} Intente hacer cherry-pick de nuevo de este commit."
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr "%{edit_in_new_fork_notice} Intentar revertir este commit otra vez."
msgid "%{filePath} deleted"
msgstr "%{filePath} eliminado"
@@ -177,7 +192,10 @@ msgid "%{gitlab_ci_yml} not found in this commit"
msgstr "No es posible encontrar %{gitlab_ci_yml} en este commit"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
+msgstr "Los %{group_docs_link_start}Grupos%{group_docs_link_end} le permiten administrar y colaborar en múltiples proyectos. Los miembros de un grupo tienen acceso a todos sus proyectos."
+
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr "%{group_name} utiliza cuentas administradas de grupo. Debe crear una nueva cuenta de GitLab que será administrada por %{group_name}."
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "¡Va a eliminar %{issuableType}! ¿Está seguro de que desea realizar esta acción?"
@@ -185,11 +203,20 @@ msgstr "¡Va a eliminar %{issuableType}! ¿Está seguro de que desea realizar es
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} no disponible"
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} es una autoridad certificadora (CA) gratis y open source, que ofrece certificados digitales con el objetivo de habilitar HTTPS (SSL/TLS) para los sitios web."
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr "%{level_name} no está permitido en un grupo de %{group_level_name}."
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr "%{level_name} no está permitido debido a que el fork del proyecto origen tiene menor visibilidad."
+
msgid "%{level_name} visibility has been restricted by the administrator."
-msgstr ""
+msgstr "La visibilidad de %{level_name} ha sido restringida por el administrador."
msgid "%{link_start}Read more%{link_end} about role permissions"
-msgstr ""
+msgstr "%{link_start}Lea más%{link_end} acerca de los permisos de rol"
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Iniciado"
@@ -198,7 +225,13 @@ msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} está bloqueado por el usuario de GitLab %{lock_user_id}"
msgid "%{mrText}, this issue will be closed automatically."
-msgstr ""
+msgstr "%{mrText}, esta incidencia se cerrará automáticamente."
+
+msgid "%{name} contained %{resultsString}"
+msgstr "%{name} contenido en %{resultsString}"
+
+msgid "%{name} found %{resultsString}"
+msgstr "%{name} encontrado %{resultsString}"
msgid "%{name}'s avatar"
msgstr "Avatar de %{name}"
@@ -213,34 +246,46 @@ msgid "%{percent}%% complete"
msgstr "%{percent}%% completado"
msgid "%{service_title} activated."
-msgstr ""
+msgstr "%{service_title} activado."
msgid "%{service_title} settings saved, but not activated."
-msgstr ""
+msgstr "Se guardaron las configuraciones del %{service_title}, pero no se han activado."
+
+msgid "%{size} GiB"
+msgstr "%{size} Gb"
+
+msgid "%{size} KiB"
+msgstr "%{size} Kb"
+
+msgid "%{size} MiB"
+msgstr "%{size} Mb"
+
+msgid "%{size} bytes"
+msgstr "%{size} bytes"
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
-msgstr ""
+msgstr "%{spammable_titlecase} se envió con éxito a Akismet."
msgid "%{state} epics"
msgstr "%{state} épicas"
msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgstr[1] "%{strong_start}%{branch_count}%{strong_end} Branches"
msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgstr[1] "%{strong_start}%{commit_count}%{strong_end} Commits"
msgid "%{strong_start}%{human_size}%{strong_end} Files"
-msgstr ""
+msgstr "%{strong_start}%{human_size}%{strong_end} Archivos"
msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{strong_start}%{tag_count}%{strong_end} Etiqueta"
+msgstr[1] "%{strong_start}%{tag_count}%{strong_end} Etiquetas"
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
@@ -250,6 +295,9 @@ msgstr[1] "%{text}%{files} archivos"
msgid "%{text} is available"
msgstr "%{text} esta disponible"
+msgid "%{title} %{operator} %{threshold}"
+msgstr "%{title} %{operator} %{threshold}"
+
msgid "%{title} changes"
msgstr "%{title} cambios"
@@ -257,13 +305,33 @@ msgid "%{unstaged} unstaged and %{staged} staged changes"
msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
-msgstr ""
+msgstr "%{usage_ping_link_start}Más información%{usage_ping_link_end} acerca de lo que se comparte en GitLab Inc."
msgid "%{user_name} profile page"
+msgstr "%{user_name} página de perfil"
+
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr "%{verb} %{time_spent_value} tiempo gastado."
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr "'%{level}' no es un nivel de visibilidad válido"
+
+msgid "'%{source}' is not a import source"
+msgstr "'%{source}' no es una fuente valida para importar"
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
msgstr ""
msgid "(No changes)"
-msgstr ""
+msgstr "(Sin cambios)"
+
+msgid "(check progress)"
+msgstr "(comprobar el progreso)"
msgid "(external source)"
msgstr "(fuente externa)"
@@ -289,6 +357,9 @@ msgstr "- El ejecutor está en pausa y no recibirá ningún trabajo nuevo"
msgid "- show less"
msgstr "- mostrar menos"
+msgid "0 for unlimited"
+msgstr "0 para ilimitado"
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] "1 adición de %{type}"
@@ -305,15 +376,15 @@ msgstr[0] "1 Día"
msgstr[1] "%d Días"
msgid "1 closed issue"
-msgid_plural "%d closed issues"
-msgstr[0] "1 incidencia cerrada"
-msgstr[1] "%d incidencias cerradas"
-
-msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
+msgid "1 closed merge request"
+msgid_plural "%{merge_requests} closed merge requests"
+msgstr[0] "1 solicitud de fusión cerrada"
+msgstr[1] "%{merge_requests} merge requests cerrados"
+
msgid "1 day"
msgstr "1 día"
@@ -323,20 +394,20 @@ msgstr[0] "1 grupo"
msgstr[1] "%d grupos"
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
-msgstr[0] "1 incidencia abierta"
-msgstr[1] "%d incidencias abiertas"
-
-msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
+msgid "1 open merge request"
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] "1 merge request abierto"
+msgstr[1] "%{merge_requests} merge request abiertos"
+
msgid "1 pipeline"
msgid_plural "%d pipelines"
msgstr[0] "1 pipeline"
@@ -355,15 +426,27 @@ msgstr[1] "%d usuarios"
msgid "1 week"
msgstr "1 semana"
+msgid "1-9 contributions"
+msgstr "1-9 contribuciones"
+
+msgid "10-19 contributions"
+msgstr "10-19 contribuciones"
+
msgid "1st contribution!"
msgstr "¡1ra contribución!"
+msgid "20-29 contributions"
+msgstr "20-29 contribuciones"
+
msgid "2FA"
msgstr "2FA"
msgid "2FA enabled"
msgstr "Verificación en 2 pasos habilitada"
+msgid "2FADevice|Registered On"
+msgstr "Registrado En"
+
msgid "3 days"
msgstr "3 días"
@@ -373,6 +456,9 @@ msgstr "3 horas"
msgid "30 minutes"
msgstr "30 minutos"
+msgid "30+ contributions"
+msgstr "Más de 30 contribuciones"
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr "Por favor póngase en contacto con su administrador de GitLab para obtener los permisos necesarios."
@@ -392,94 +478,100 @@ msgid "8 hours"
msgstr "8 horas"
msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> añadirá \"Por <a href=\"#\">@johnsmith</a>\" a todas las incidencias y comentarios creados por johnsmith@example.com, y colocará a <a href=\"#\">@johnsmith</a> como la persona asiganda a todas las incidencias inicialmente asignadas a johnsmith@example.com."
msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"John Smith\"</code>añadirá \"por John Smith\" a todas las incidencias y comentarios creados originalmente por johnsmith@example.com."
msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> añadirá \"Por johnsm...@example.com\" a todas las incidencias y comentarios originalmente creados por johnsmith@example.com. El correo electrónico o nombre de usuario está oculto para asegurar la privacidad del usuario."
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> añadirá \"Por <a href=\"#\">johnsmith@example.com</a>\" a todas las incidencias y comentarios originalmente creados por johnsmith@example.com. Por defecto, el correo electrónico o el nombre de usuario está oculto para asegurar la privacidad del usuario. Utilice esta opción si desea mostrar la dirección de correo electrónico completa."
+
+msgid "<no name set>"
+msgstr "<no tiene el nombre establecido>"
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
-msgstr ""
+msgstr "<strong>%{created_count}</strong> creadas, <strong>%{accepted_count}</strong> aceptadas."
msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
-msgstr ""
+msgstr "<strong>%{created_count}</strong> creada, <strong>%{closed_count}</strong> cerrada."
msgid "<strong>%{group_name}</strong> group members"
-msgstr ""
+msgstr "miembros del grupo <strong>%{group_name}</strong>"
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
msgid "<strong>Deletes</strong> source branch"
-msgstr ""
+msgstr "<strong>elimina</strong> la rama origen"
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr ""
+msgstr "Un ejecutor es un proceso que ejecuta un trabajo. Puede configurar tantos ejecutores como usted necesite."
msgid "A .NET Core console application template, customizable for any .NET Core project"
msgstr "Una plantilla de aplicación de consola .NET Core, personalizable para cualquier proyecto .NET Core"
msgid "A GitBook site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr "Un sitio basado en GitBook que utiliza Netlify como herramienta de CI/CD en lugar de GitLab, pero con todas las otras excelentes características de GitLab."
+msgstr "Un sitio basado en GitBook que utiliza Netlify como herramienta de CI/CD en lugar de GitLab, pero con las demás excelentes características de GitLab."
msgid "A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr "Un sitio basado en Hexo que usa Netlify como herramienta de CI/CD en lugar de GitLab, pero con todas las otras excelentes características de GitLab."
+msgstr "Un sitio basado en Hexo que usa Netlify como herramienta de CI/CD en lugar de GitLab, pero con las demás excelentes características de GitLab."
msgid "A Hugo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr "Un sitio basado en Hugo que usa Netlify como herramienta de CI/CD en lugar de GitLab, pero con todas las otras excelentes características de GitLab."
+msgstr "Un sitio basado en Hugo que usa Netlify como herramienta de CI/CD en lugar de GitLab, pero con las demás excelentes características de GitLab."
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr "Un sitio basado en Jekyll que usa Netlify como herramienta de CI/CD en lugar de GitLab, pero con todas las otras excelentes características de GitLab."
+msgstr "Un sitio basado en Jekyll que usa Netlify como herramienta de CI/CD en lugar de GitLab, pero con las de más excelentes características de GitLab."
+
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
+msgstr "Se configurará una cuenta de Let's Encrypt para esta instalación de GitLab utilizando su correo electrónico. Recibirá correos electrónicos con avisos sobre la caducidad de los certificados."
msgid "A default branch cannot be chosen for an empty project."
-msgstr ""
+msgstr "No se puede elegir una rama por defecto para un proyecto vacío."
msgid "A deleted user"
msgstr "Un usuario eliminado"
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr "Un miembro del equipo de GitLab revisará tus comentarios tan pronto como sea posible."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
+msgstr "Un fork es una copia de un proyecto.<br />Realizar un fork de un repositorio le permite realizar cambios sin afectar al proyecto original."
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
-msgstr ""
-
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
-msgstr ""
+msgstr "Se creará una nueva rama en su proceso de fork y se iniciará una nueva solicitud de merge."
msgid "A new impersonation token has been created."
-msgstr ""
+msgstr "Se ha creado un nuevo token de impersonación."
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr ""
+msgstr "Un sitio hecho con HTML plano que utiliza Netlify para CI/CD en lugar de GitLab, pero con las demás excelentes características de GitLab."
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
+msgstr "Un proyecto es donde sus archivos (repositorio), planifica su trabajo (incidencias), y publica su documentación (wiki), %{among_other_things_link}."
msgid "A ready-to-go template for use with Android apps."
-msgstr ""
+msgstr "Una plantilla lista para utilizar con aplicaciones de Android."
msgid "A ready-to-go template for use with iOS Swift apps."
-msgstr ""
+msgstr "Una plantilla lista para utilizar con las aplicaciones iOS basadas en Swift."
msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
-msgstr ""
+msgstr "Una expresión regular que se utilizará para rastrear la cantidad de cobertura de código en la salida del trabajo. Déjela en blanco para deshabilitarla"
msgid "A user with write access to the source branch selected this option"
-msgstr ""
+msgstr "Un usuario con acceso de escritura a la rama origen seleccionó esta opción"
msgid "API Help"
-msgstr ""
+msgstr "Ayuda de la API"
+
+msgid "API Token"
+msgstr "Token del API"
msgid "About GitLab"
msgstr "Acerca de Gitlab"
@@ -497,7 +589,7 @@ msgid "Abuse Reports"
msgstr "Reportes de abuso"
msgid "Abuse reports"
-msgstr ""
+msgstr "Informar de un abuso"
msgid "Accept invitation"
msgstr "Aceptar invitación"
@@ -512,19 +604,28 @@ msgid "Access Tokens"
msgstr "Tokens de acceso"
msgid "Access denied for your LDAP account."
-msgstr ""
+msgstr "Acceso denegado para su cuenta LDAP."
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "¡Acceso denegado! Por favor, verifique que puede agregar las claves de despliegue a este repositorio."
msgid "Access expiration date"
-msgstr ""
+msgstr "Fecha de expiración del acceso"
msgid "Access forbidden. Check your access level."
-msgstr ""
+msgstr "Acceso denegado. Por favor, compruebe su nivel de acceso."
msgid "Access to '%{classification_label}' not allowed"
-msgstr ""
+msgstr "El acceso a '%{classification_label}' no está permitido"
+
+msgid "AccessDropdown|Groups"
+msgstr "Grupos"
+
+msgid "AccessDropdown|Roles"
+msgstr "Roles"
+
+msgid "AccessDropdown|Users"
+msgstr "Usuarios"
msgid "Account"
msgstr "Cuenta"
@@ -532,11 +633,14 @@ msgstr "Cuenta"
msgid "Account and limit"
msgstr "Cuenta y límite"
+msgid "Account: %{account}"
+msgstr "Cuenta: %{account}"
+
msgid "Action to take when receiving an alert."
-msgstr ""
+msgstr "Acción a realizar cuando se reciba una alerta."
msgid "Activate Service Desk"
-msgstr ""
+msgstr "Activar Service Desk"
msgid "Active"
msgstr "Activo"
@@ -554,10 +658,10 @@ msgid "Add CHANGELOG"
msgstr "Añadir CHANGELOG"
msgid "Add CONTRIBUTING"
-msgstr ""
+msgstr "Añadir CONTRIBUTING"
msgid "Add Group Webhooks and GitLab Enterprise Edition."
-msgstr ""
+msgstr "Añadir Webhooks de grupo y GitLab Enterprise Edition."
msgid "Add Jaeger URL"
msgstr "Añadir URL de Jaeger"
@@ -568,14 +672,17 @@ msgstr "Añadir clúster de Kubernetes"
msgid "Add README"
msgstr "Añadir README"
+msgid "Add a GPG key"
+msgstr "Añadir una clave GPG"
+
msgid "Add a bullet list"
msgstr "Añadir una lista de viñetas"
msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
+msgstr "Añadir un comentario general a este %{noteable_name}."
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
-msgstr ""
+msgstr "Añada una página de inicio a su wiki que contenga información sobre su proyecto y GitLab la mostrará aquí en lugar de este mensaje."
msgid "Add a link"
msgstr "Añadir un enlace"
@@ -589,35 +696,50 @@ msgstr "Añadir tabla"
msgid "Add a task list"
msgstr "Añadir una lista de tareas"
+msgid "Add a todo"
+msgstr "Añadir tarea pendiente"
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
-msgstr ""
+msgstr "Añada un texto adicional que aparecerá en todas las comunicaciones vía correo electrónico. El límite es de %{character_limit} caracteres"
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr "Añadir una clave SSH"
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
-msgstr ""
+msgstr "Añadir aprobadores"
msgid "Add bold text"
msgstr "Añadir texto en negrita"
+msgid "Add child epic to an epic"
+msgstr "Añadir una tarea épica hija a otra tarea épica"
+
msgid "Add comment now"
msgstr "Añadir comentario ahora"
-msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
+msgid "Add email address"
msgstr ""
+msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
+msgstr "Añadir encabezado y pie de página a los correos electrónicos. Tenga en cuenta que la configuración de los colores solo se aplicará dentro de la interfaz de la aplicación"
+
msgid "Add image comment"
msgstr "Añadir comentario a la imagen"
msgid "Add italic text"
msgstr "Añadir texto en cursiva"
+msgid "Add label(s)"
+msgstr "Añadir etiqueta(s)"
+
msgid "Add license"
msgstr "Añadir licencia"
msgid "Add list"
-msgstr ""
+msgstr "Añadir lista"
msgid "Add new application"
msgstr "Añadir una nueva aplicación"
@@ -625,9 +747,18 @@ msgstr "Añadir una nueva aplicación"
msgid "Add new directory"
msgstr "Agregar nuevo directorio"
+msgid "Add or subtract spent time"
+msgstr "Agregar o restar tiempo consumido"
+
msgid "Add reaction"
msgstr "Añadir reacción"
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr "Añadir al proyecto"
@@ -640,23 +771,35 @@ msgstr "Añadir tarea pendiente"
msgid "Add user(s) to the group:"
msgstr "Añadir usuario(s) al grupo:"
-msgid "Add users or groups who are allowed to approve every merge request"
-msgstr ""
-
msgid "Add users to group"
msgstr "Agregar usuarios al grupo"
+msgid "AddMember|No users specified."
+msgstr "No se han especificado usuarios."
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
+msgstr "Demasiados usuarios especificados (el límite es %{user_limit})"
+
msgid "Added at"
msgstr "Añadido el"
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
-msgstr ""
+msgstr "Se ha deshabilitado la opción de añadir nuevas aplicaciones en su instancia de GitLab. Póngase en contacto con su administrador de GitLab para obtener el permiso"
+
+msgid "Additional minutes"
+msgstr "Minutos adicionales"
msgid "Additional text"
msgstr "Texto adicional"
-msgid "Aditional minutes"
-msgstr ""
+msgid "Adds"
+msgstr "Añadir"
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr "Añade %{epic_ref} como tarea épica hija."
+
+msgid "Adds a todo."
+msgstr "Añadir una tarea pendiente."
msgid "Admin Area"
msgstr "Ãrea de administración"
@@ -665,13 +808,16 @@ msgid "Admin Overview"
msgstr "Vista de administrador"
msgid "Admin Section"
-msgstr ""
+msgstr "Sección de administración"
+
+msgid "Admin notes"
+msgstr "Notas del administrador"
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Está a punto de eliminar permanentemente el usuario %{username}. Las incidencias, merge requests, y los grupos vinculados a ellos serán trasladados a un usuario \"fantasma\". Para evitar la pérdida de datos, considere la posibilidad de la opción %{strong_start}bloquear usuario%{strong_end}. Una vez %{strong_start}elimine el usuario%{strong_end}, no se puede deshacer esta acción ni recuperar los datos del usuario eliminado."
msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Está a punto de eliminar permanentemente el usuario %{username}. Las incidencias, merge requests, y los grupos vinculados a ellos serán trasladados a un usuario \"fantasma\". Para evitar la pérdida de datos, considere la posibilidad de la opción %{strong_start}bloquear usuario%{strong_end}. Una vez %{strong_start}elimine el usuario%{strong_end}, no se puede deshacer esta acción ni recuperar los datos del usuario eliminado."
msgid "AdminArea|Stop all jobs"
msgstr "Detener todos los trabajos"
@@ -686,10 +832,13 @@ msgid "AdminArea|Stopping jobs failed"
msgstr "Error al detener trabajos"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
-msgstr ""
+msgstr "Está a punto de detener todos los trabajos. Esto detendrá todos los trabajos que se están ejecutando actualmente."
+
+msgid "AdminNote|Note"
+msgstr "Nota"
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Está a punto de eliminar permanentemente el proyecto %{projectName}, su repositorio y todos los recursos relacionados, esto inclueye las incidencias, los merge requests, así como también los grupos, etc. Una vez confirme y presione sobre %{strong_start}Eliminar proyecto%{strong_end},no se puede deshacer esta acción ni recuperar los datos del proyecto eliminado."
msgid "AdminProjects|Delete"
msgstr "Eliminar"
@@ -704,16 +853,16 @@ msgid "AdminSettings|Auto DevOps domain"
msgstr "Dominio Auto DevOps"
msgid "AdminSettings|Enable shared runners for new projects"
-msgstr ""
+msgstr "Habilitar ejecutores compartidos para los nuevos proyectos"
msgid "AdminSettings|Environment variables are protected by default"
msgstr "Las variables de entorno están protegidas por defecto"
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
-msgstr ""
+msgstr "Especifique un dominio para utilizar por defecto durante las etapas despliegue automático de cada proyecto y las de los mismos."
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
-msgstr ""
+msgstr "Cuando crea una nueva variable de entorno, se protegerá por defecto."
msgid "AdminUsers|2FA Disabled"
msgstr "2FA desactivado"
@@ -737,7 +886,7 @@ msgid "AdminUsers|Blocked"
msgstr "Bloqueado"
msgid "AdminUsers|Cannot unblock LDAP blocked users"
-msgstr ""
+msgstr "No se pueden desbloquear los usuarios bloqueados de LDAP"
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr "¿Eliminar el usuario %{username} y sus contribuciones?"
@@ -749,7 +898,7 @@ msgid "AdminUsers|Delete user"
msgstr "Eliminar usuario"
msgid "AdminUsers|Delete user and contributions"
-msgstr ""
+msgstr "Eliminar el usuario y sus contribuciones"
msgid "AdminUsers|External"
msgstr "Externos"
@@ -794,13 +943,16 @@ msgid "Advanced permissions, Large File Storage and Two-Factor authentication se
msgstr "Permisos avanzados, almacenamiento de grandes archivos y configuraciones de autenticación de dos factores."
msgid "Advanced search functionality"
-msgstr ""
+msgstr "Funcionalidad de búsqueda avanzada"
msgid "Advanced settings"
msgstr "Configuración avanzada"
msgid "After a successful password update you will be redirected to login screen."
-msgstr ""
+msgstr "Después de una actualización correcta de la contraseña, será redirigido a la pantalla de inicio de sesión."
+
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr "Después de una actualización correcta de la contraseña, se le redirigirá a la página de inicio de sesión donde podrá iniciar sesión con su nueva contraseña."
msgid "Alert"
msgid_plural "Alerts"
@@ -817,58 +969,67 @@ msgid "All Members"
msgstr "Todos los miembros"
msgid "All changes are committed"
+msgstr "Se ha realizado commit de todos los cambios"
+
+msgid "All email addresses will be used to identify your commits."
msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Todas las funcionalidades están habilitadas para proyectos en blanco, plantillas, o al importar, pero puedes deshabilitarlas posteriormente en la configuración del proyecto."
+msgid "All groups and projects"
+msgstr "Todos los grupos y proyectos"
+
msgid "All issues for this milestone are closed. You may close this milestone now."
-msgstr ""
+msgstr "Todas las incidencias para este hito están cerradas. Puede cerrar este hito ahora."
msgid "All merge conflicts were resolved. The merge request can now be merged."
-msgstr ""
+msgstr "Se han solucionado todos los conflictos del merge. Puede realizar el merge request."
+
+msgid "All projects"
+msgstr "Todos los proyectos"
msgid "All todos were marked as done."
-msgstr ""
+msgstr "Se marcaron todas las tareas pendientes como realizadas."
msgid "All users"
msgstr "Todos los usuarios"
msgid "All users must have a name."
-msgstr ""
+msgstr "Todos los usuarios deben tener un nombre."
msgid "Allow \"%{group_name}\" to sign you in"
-msgstr ""
+msgstr "Permitir al grupo %{group_name} iniciar sesión"
msgid "Allow commits from members who can merge to the target branch."
-msgstr ""
+msgstr "Permitir commits de los miembros que pueden hacer merge con la rama de destino."
msgid "Allow group owners to manage LDAP-related settings"
-msgstr ""
+msgstr "Permitir a los propietarios de los grupos administrar configuraciones relacionadas con LDAP"
msgid "Allow mirrors to be set up for projects"
-msgstr ""
+msgstr "Permitir que se establezcan replicas para los proyectos"
msgid "Allow only the selected protocols to be used for Git access."
-msgstr ""
+msgstr "Permitir que sólo los protocolos seleccionados tengan acceso a Git."
msgid "Allow projects within this group to use Git LFS"
-msgstr ""
+msgstr "Permitir que los proyectos dentro de este grupo usen Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
-msgstr ""
+msgstr "Permitir acceso público a los pipelines y a los detalles del trabajo, incluidos los logs de salida y los artefactos"
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
-msgstr ""
+msgstr "Permitir el renderizado de diagramas PlantUML en documentos Asciidoc."
msgid "Allow requests to the local network from hooks and services."
-msgstr ""
+msgstr "Permitir peticiones a la red local desde los hooks y los servicios."
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
msgid "Allow users to register any application to use GitLab as an OAuth provider"
-msgstr ""
+msgstr "Permitir a los usuarios registrar cualquier aplicación para usar GitLab como proveedor de OAuth"
msgid "Allow users to request access"
msgstr "Permitir a los usuarios solicitar acceso"
@@ -877,10 +1038,10 @@ msgid "Allow users to request access if visibility is public or internal."
msgstr "Permitir a los usuarios solicitar acceso si la visibilidad es pública o interna."
msgid "Allowed to fail"
-msgstr ""
+msgstr "Permitido fallar"
msgid "Allows you to add and manage Kubernetes clusters."
-msgstr ""
+msgstr "Le permite agregar y administrar clusters de Kubernetes."
msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
msgstr ""
@@ -889,25 +1050,22 @@ msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
msgid "Alternate support URL for help page"
-msgstr ""
+msgstr "URL de soporte alternativa para la página de ayuda"
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
-msgstr ""
+msgstr "Alternativamente, puede utilizar un %{personal_access_token_link}. Cuando cree su token de acceso personal, debe seleccionar el alcance del <code>repositorio</code>, para que podamos mostrar una lista de sus repositorios públicos y privados que estén disponibles para conectarse."
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
-msgstr ""
+msgstr "Alternativamente, puedes utilizar un %{personal_access_token_link}. Cuando crea su token de acceso personal, deberá seleccionar el ámbito del <code>repo</code>, entonces podremos mostrar una lista de sus repositorios públicos y privados disponibles para importar."
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
-msgstr ""
-
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
+msgstr "Cantidad de tiempo (en horas) que los usuarios pueden omitir la configuración forzada de la autenticación de dos factores"
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
-msgstr ""
+msgstr "Una aplicación llamada %{link_to_client} está solicitando el acceso a su cuenta de Gitlab."
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
-msgstr ""
+msgstr "Se agregará a un campo de usuario de Gitlab el nombre completo del usuario de FogBugz (por ejemplo, \"John Smith\") en la descripción de todos los errores y los comentarios. También se asociarán o asignarán estos errores y comentarios al creador del proyecto."
msgid "An error has occurred"
msgstr "Se ha producido un error"
@@ -936,14 +1094,17 @@ msgstr "Ha ocurrido un error visualizando el blob"
msgid "An error occurred when toggling the notification subscription"
msgstr "Se produjo un error al activar/desactivar la suscripción de notificación"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr "Se ha producido un error al intentar resolver un comentario. Por favor, inténtelo de nuevo."
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr "Se ha producido un error al intentar resolver una discusión. Por favor, inténtelo de nuevo."
+
msgid "An error occurred when updating the issue weight"
msgstr "Se ha producido un error al actualizar el tamaño de la incidencia"
-msgid "An error occurred while adding approver"
-msgstr "Se ha producido un error al añadir el aprobador."
-
msgid "An error occurred while deleting the approvers group"
-msgstr ""
+msgstr "Se ha producido un error al eliminar el grupo de aprobadores"
msgid "An error occurred while deleting the comment"
msgstr "Se ha producido un error al eliminar el comentario"
@@ -952,7 +1113,7 @@ msgid "An error occurred while detecting host keys"
msgstr "Se ha producido un error al detectar las claves del host."
msgid "An error occurred while disabling Service Desk."
-msgstr ""
+msgstr "Se ha producido un error al deshabilitar Service Desk."
msgid "An error occurred while dismissing the alert. Refresh the page and try again."
msgstr "Se ha producido un error al desactivar la alerta. Actualice la página y vuelva a intentarlo."
@@ -961,7 +1122,16 @@ msgid "An error occurred while dismissing the feature highlight. Refresh the pag
msgstr "Se ha producido un error al desactivar la función resaltar. Actualice la página y vuelva a intentarlo."
msgid "An error occurred while enabling Service Desk."
-msgstr ""
+msgstr "Se ha producido un error al habilitar Service Desk."
+
+msgid "An error occurred while fetching environments."
+msgstr "Se ha producido un error al obtener los entornos."
+
+msgid "An error occurred while fetching folder content."
+msgstr "Se ha producido un error al obtener el contenido de la carpeta."
+
+msgid "An error occurred while fetching label colors."
+msgstr "Se ha producido un error al obtener los colores de las etiquetas."
msgid "An error occurred while fetching markdown preview"
msgstr "Se ha producido un error al obtener la previsualización del markdown."
@@ -969,14 +1139,20 @@ msgstr "Se ha producido un error al obtener la previsualización del markdown."
msgid "An error occurred while fetching pending comments"
msgstr "Se ha producido un error al recuperar los comentarios pendientes"
+msgid "An error occurred while fetching projects autocomplete."
+msgstr "Se ha producido un error al obtener la información de autocompletado de los proyectos."
+
msgid "An error occurred while fetching sidebar data"
msgstr "Se ha producido un error al obtener los datos de la barra lateral."
-msgid "An error occurred while fetching stages."
-msgstr "Se ha producido un error al obtener las etapas del pipeline."
-
msgid "An error occurred while fetching the Service Desk address."
-msgstr ""
+msgstr "Se ha producido un error al obtener la dirección de Service Desk."
+
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr "Se ha producido un error al obtener la lista de tableros. Por favor vuelva a intentarlo."
+
+msgid "An error occurred while fetching the builds."
+msgstr "Se ha producido un error al obtener el resultado de los trabajo de las construcción."
msgid "An error occurred while fetching the job log."
msgstr "Se ha producido un error al obtener el log del trabajo."
@@ -991,7 +1167,10 @@ msgid "An error occurred while fetching the pipeline."
msgstr "Se ha producido un error mientras se obtenía el pipeline."
msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
+msgstr "Se ha producido un error al obtener las versiones. Por favor, inténtelo de nuevo."
+
+msgid "An error occurred while fetching this tab."
+msgstr "Se ha producido un error al obtener esta pestaña."
msgid "An error occurred while getting projects"
msgstr "Se ha producido un error al obtener los proyectos"
@@ -1009,7 +1188,7 @@ msgid "An error occurred while loading commit signatures"
msgstr "Se ha producido un error al cargar las firmas de los commits"
msgid "An error occurred while loading designs. Please try again."
-msgstr ""
+msgstr "Se ha producido un error al cargar diseños. Por favor, inténtelo de nuevo."
msgid "An error occurred while loading diff"
msgstr "Se ha producido un error al cargar el diff"
@@ -1026,14 +1205,17 @@ msgstr "Se ha producido un error al cargar los detalles de la suscripción."
msgid "An error occurred while making the request."
msgstr "Se ha producido un error al crear la petición."
-msgid "An error occurred while removing approver"
-msgstr "Se ha producido un error al eliminar el aprobador."
+msgid "An error occurred while moving the issue."
+msgstr "Se ha producido un error al mover la incidencia."
+
+msgid "An error occurred while parsing recent searches"
+msgstr "Se ha producido un error al analizar búsquedas recientes"
msgid "An error occurred while removing epics."
msgstr "Se ha producido un error al eliminar las tareas épicas."
msgid "An error occurred while removing issues."
-msgstr ""
+msgstr "Se ha producido un error al eliminar las incidencias."
msgid "An error occurred while rendering KaTeX"
msgstr "Se ha producido un error durante el renderizado con KaTeX"
@@ -1054,7 +1236,7 @@ msgid "An error occurred while saving assignees"
msgstr "Se ha producido un error al guardar las asignaciones"
msgid "An error occurred while saving the approval settings"
-msgstr ""
+msgstr "Se ha producido un error al guardar la configuración de aprobaciones"
msgid "An error occurred while subscribing to notifications."
msgstr "Se ha producido un error al suscribirse a las notificaciones."
@@ -1063,7 +1245,7 @@ msgid "An error occurred while unsubscribing to notifications."
msgstr "Se ha producido un error al cancelar la suscripción a las notificaciones."
msgid "An error occurred while updating approvers"
-msgstr ""
+msgstr "Se ha producido un error al actualizar los aprobadores"
msgid "An error occurred while updating the comment"
msgstr "Se ha producido un error al actualizar el comentario"
@@ -1072,52 +1254,55 @@ msgid "An error occurred while validating username"
msgstr "Se ha producido un error al validar el nombre de usuario"
msgid "An error occurred whilst committing your changes."
-msgstr ""
+msgstr "Se ha producido un error al hacer commit de sus cambios."
msgid "An error occurred whilst fetching the job trace."
-msgstr ""
+msgstr "Se ha producido un error al obtener el log del trabajo."
msgid "An error occurred whilst fetching the latest pipeline."
-msgstr ""
+msgstr "Se ha producido un error al obtener el último pipeline."
+
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr "Se ha producido un error al obtener los archivos de - %{branchId}"
msgid "An error occurred whilst loading all the files."
-msgstr ""
+msgstr "Se ha producido un error al cargar todos los archivos."
msgid "An error occurred whilst loading the file content."
-msgstr ""
+msgstr "Se ha producido un error al cargar el contenido del fichero."
msgid "An error occurred whilst loading the file."
-msgstr ""
+msgstr "Se ha producido un error al cargar el archivo."
msgid "An error occurred whilst loading the merge request changes."
-msgstr ""
+msgstr "Se ha producido un error al cargar los cambios del merge request."
msgid "An error occurred whilst loading the merge request version data."
-msgstr ""
+msgstr "Se ha producido un error al cargar los datos de versión del merge request."
msgid "An error occurred whilst loading the merge request."
-msgstr ""
+msgstr "Se ha producido un error al cargar el merge request."
msgid "An error occurred whilst loading the pipelines jobs."
-msgstr ""
+msgstr "Se ha producido un error al cargar los trabajos de lo pipelines."
msgid "An error occurred. Please try again."
msgstr "Se ha producido un error. Por favor inténtelo de nuevo."
msgid "An unexpected error occurred while checking the project environment."
-msgstr ""
+msgstr "Se ha producido un error inesperado al comprobar el entorno del proyecto."
msgid "An unexpected error occurred while checking the project runners."
-msgstr ""
+msgstr "Se ha producido un error inesperado al comprobar los ejecutores del proyecto."
msgid "An unexpected error occurred while communicating with the Web Terminal."
-msgstr ""
+msgstr "Se ha producido un error inesperado al comunicarse con la Terminal Web."
msgid "An unexpected error occurred while starting the Web Terminal."
-msgstr ""
+msgstr "Se ha producido un error inesperado al iniciar el Terminal Web."
msgid "An unexpected error occurred while stopping the Web Terminal."
-msgstr ""
+msgstr "Se ha producido un error inesperado al detener el Terminal Web."
msgid "Analytics"
msgstr "Analíticas"
@@ -1137,17 +1322,29 @@ msgstr "Cualquiera"
msgid "Any Label"
msgstr "Cualquier etiqueta"
+msgid "Any Milestone"
+msgstr "Cualquier hito"
+
msgid "Any encrypted tokens"
-msgstr ""
+msgstr "Cualquier token encriptado"
+
+msgid "Any namespace"
+msgstr "Cualquier espacio de nombres"
msgid "Appearance"
msgstr "Apariencia"
msgid "Appearance was successfully created."
-msgstr ""
+msgstr "La apariencia se creó correctamente."
msgid "Appearance was successfully updated."
-msgstr ""
+msgstr "La apariencia se actualizó correctamente."
+
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr "Añadir el comentario con %{TABLEFLIP}"
+
+msgid "Append the comment with %{shrug}"
+msgstr "Añadir el comentario con %{shrug}"
msgid "Application"
msgstr "Aplicación"
@@ -1156,13 +1353,16 @@ msgid "Application ID"
msgstr "ID de la aplicación"
msgid "Application settings saved successfully"
-msgstr ""
+msgstr "Se ha guardado correctamente la configuración de la aplicación"
+
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr "La aplicación se ha desinstalado correctamente pero no se ha podido destruir: %{error_message}"
msgid "Application was successfully destroyed."
-msgstr ""
+msgstr "Se ha destruido correctamente la aplicación."
msgid "Application was successfully updated."
-msgstr ""
+msgstr "Se ha actualizado correctamente la aplicación."
msgid "Application: %{name}"
msgstr "Aplicación: %{name}"
@@ -1176,6 +1376,18 @@ msgstr "Aplicado"
msgid "Apply suggestion"
msgstr "Aplicar sugerencia"
+msgid "Applying command"
+msgstr "Aplicando el comando"
+
+msgid "Applying command to %{commandDescription}"
+msgstr "Aplicando el comando a %{commandDescription}"
+
+msgid "Applying multiple commands"
+msgstr "Aplicando múltiples comandos"
+
+msgid "Applying suggestion"
+msgstr "Aplicando sugerencia"
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] "%d miembro"
@@ -1183,11 +1395,11 @@ msgstr[1] "%d miembros"
msgid "ApprovalRuleRemove|Approvals from this member are not revoked."
msgid_plural "ApprovalRuleRemove|Approvals from these members are not revoked."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Las aprobaciones de este miembro no están revocadas."
+msgstr[1] "Las aprobaciones de estos miembros no están revocadas."
msgid "ApprovalRuleRemove|You are about to remove the %{name} approver group which has %{nMembers}."
-msgstr ""
+msgstr "Está apunto de eliminar el grupo de aprobadores %{name} que tiene %{nMembers}."
msgid "ApprovalRuleSummary|%d member"
msgid_plural "ApprovalRuleSummary|%d members"
@@ -1196,33 +1408,27 @@ msgstr[1] "%d miembros"
msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} aprobación requerida para %{membersCount}"
+msgstr[1] "%{count} aprobaciones requeridas para %{membersCount}"
msgid "ApprovalRule|All members with Developer role or higher and code owners (if any)"
-msgstr ""
+msgstr "Todos los miembros con un rol de desarrollador o superior y que son propietarios del código (si los hay)"
msgid "ApprovalRule|Members"
msgstr "Miembros"
msgid "ApprovalRule|Name"
-msgstr ""
+msgstr "Nombre"
msgid "ApprovalRule|No. approvals required"
-msgstr ""
+msgstr "No se requiere aprobaciones"
msgid "ApprovalRule|e.g. QA, Security, etc."
-msgstr ""
+msgstr "por ejemplo, QA, Seguridad, etc."
msgid "Approvals"
msgstr "Aprobaciones"
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr "Abril"
@@ -1233,7 +1439,7 @@ msgid "Archive jobs"
msgstr "Archivar trabajos"
msgid "Archive project"
-msgstr ""
+msgstr "Archivar proyecto"
msgid "Archived project! Repository and other project resources are read-only"
msgstr "¡Proyecto archivado!. El repositorio y el resto de recursos del proyecto son de sólo lectura"
@@ -1242,16 +1448,28 @@ msgid "Archived projects"
msgstr "Proyectos archivados"
msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. <strong>The repository cannot be committed to, and no issues, comments or other entities can be created.</strong>"
-msgstr ""
+msgstr "Archivar el proyecto lo hará de sólo lectura. Está oculto desde el panel de control y no aparece en las búsquedas. <strong>En el repositorio no se puede hacer commits, y no se pueden crear incidencias, comentarios u otras entidades.</strong>"
msgid "Are you sure"
msgstr "¿Está seguro?"
msgid "Are you sure that you want to archive this project?"
-msgstr ""
+msgstr "¿Está seguro de que desea archivar el proyecto?"
msgid "Are you sure that you want to unarchive this project?"
-msgstr ""
+msgstr "¿Está seguro de que desea desarchivar este proyecto?"
+
+msgid "Are you sure you want to cancel creating this comment?"
+msgstr "¿Está seguro que deseas cancelar la creación de este comentario?"
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr "¿Está seguro de que desea cancelar la edición de este comentario?"
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
+msgstr "¿Está seguro de que desea borrar este dispositivo? Esta acción no se puede deshacer."
+
+msgid "Are you sure you want to delete this list?"
+msgstr "¿Está seguro que desea eliminar esta lista?"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "¿Estás seguro que deseas eliminar esta programación del pipeline?"
@@ -1263,10 +1481,10 @@ msgid "Are you sure you want to lose unsaved changes?"
msgstr "¿Estás seguro de que deseas descartar los cambios no guardados?"
msgid "Are you sure you want to lose your issue information?"
-msgstr ""
+msgstr "¿Estás seguro que quiere perder la información de su incidencia?"
msgid "Are you sure you want to permanently delete this license?"
-msgstr ""
+msgstr "¿Está seguro de que desea eliminar de forma permanente esta licencia?"
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr "¿Seguro que quiere regenerar la clave pública? Deberá actualizar la clave pública en el servidor remoto antes de que la duplicación funcione nuevamente."
@@ -1274,18 +1492,6 @@ msgstr "¿Seguro que quiere regenerar la clave pública? Deberá actualizar la c
msgid "Are you sure you want to remove %{group_name}?"
msgstr "¿Está seguro que desea eliminar %{group_name}?"
-msgid "Are you sure you want to remove approver %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove approver %{name}?"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}?"
-msgstr ""
-
msgid "Are you sure you want to remove the attachment?"
msgstr "¿Está seguro que desea eliminar el archivo adjunto?"
@@ -1296,10 +1502,13 @@ msgid "Are you sure you want to reset registration token?"
msgstr "¿Está seguro que desea reinicializar el token de registro?"
msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
+msgstr "¿Está seguro de que desea restablecer el token SCIM? La provisión de SCIM dejará de funcionar hasta que se actualice el nuevo token."
msgid "Are you sure you want to reset the health check token?"
-msgstr "¿Está seguro que desea reinicializar el token de Verificación de Estado?"
+msgstr "¿Está seguro que desea restablecer el token de verificación de estado?"
+
+msgid "Are you sure you want to revoke this nickname?"
+msgstr "¿Está seguro que desea revocar este nick?"
msgid "Are you sure you want to stop this environment?"
msgstr "¿Está seguro de que desea detener este entorno?"
@@ -1313,12 +1522,36 @@ msgstr "¿Está seguro de que desea darse de baja de la %{type}: %{link_to_notea
msgid "Are you sure?"
msgstr "¿Estás seguro?"
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr "¿Está seguro? Todos los commits que se firmaron con esta clave GPG serán marcados como no verificados."
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr "¿Está seguro? Eliminar esta clave GPG no afecta a los commits ya firmados."
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr "¿Está seguro?. Al hacer esto invalidará sus aplicaciones registradas y sus dispositivos U2F."
+
msgid "Artifact ID"
msgstr "ID del artefacto"
msgid "Artifacts"
msgstr "Artefactos"
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr "Dado que los dispositivos U2F solo son compatibles con algunos navegadores, requerimos que configure una aplicación de autenticación de dos factores antes que un dispositivo U2F. De esta forma, siempre podrá iniciar sesión, incluso cuando utilice un navegador no compatible."
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr "el %{user} hizo push a la rama %{branch} de %{project_name} ( %{commit_url} ):"
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr "Asana - Teamwork sin correo electrónico"
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr "Lista de ramas separadas por comas que se inspeccionarán automáticamente. Dejela en blanco para incluir todas las ramas."
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr "El token de acceso personal del usuario. El usuario debe tener acceso a la tarea, todos los comentarios se atribuirán a este usuario."
+
msgid "Ascending"
msgstr "Ascendente"
@@ -1329,7 +1562,10 @@ msgid "Assertion consumer service URL"
msgstr "URL del servicio de aserción del consumidor"
msgid "Assets"
-msgstr ""
+msgstr "Recursos"
+
+msgid "Assign"
+msgstr "Asignar"
msgid "Assign custom color like #FF0000"
msgstr "Asigne colores personalizados como #FF0000"
@@ -1341,11 +1577,17 @@ msgid "Assign milestone"
msgstr "Asignar milestone"
msgid "Assign some issues to this milestone."
-msgstr ""
+msgstr "Asignar algunas incidencias a este hito."
msgid "Assign to"
msgstr "Asignar a"
+msgid "Assign yourself to these issues"
+msgstr "Asignarse estas incidencias"
+
+msgid "Assign yourself to this issue"
+msgstr "Asignarse esta incidencia"
+
msgid "Assigned Issues"
msgstr "Incidencias asignadas"
@@ -1362,13 +1604,13 @@ msgid "Assignee lists not available with your current license"
msgstr "Las listas de asignaciones no se encuentran disponibles con su licencia actual"
msgid "Assignee lists show all issues assigned to the selected user."
-msgstr ""
+msgstr "Las listas de asignados muestran todos las incidencias asignadas al usuario seleccionado."
msgid "Assignee(s)"
msgstr "Asignado(s)"
msgid "At least one approval from a code owner is required to change files matching the respective CODEOWNER rules."
-msgstr ""
+msgstr "Se requiere al menos la aprobación de un propietario del código para cambiar los archivos que coincidan con las reglas de CODEOWNER."
msgid "Attach a file"
msgstr "Adjuntar un archivo"
@@ -1376,6 +1618,14 @@ msgstr "Adjuntar un archivo"
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Adjunte un archivo arrastrando &amp; soltando o %{upload_link}"
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] "Adjuntar un archivo"
+msgstr[1] "Adjuntar %d archivos"
+
+msgid "Attaching the file failed."
+msgstr "Se ha producido un error al adjuntar el archivo."
+
msgid "Audit Events"
msgstr "Eventos de auditoría"
@@ -1389,7 +1639,7 @@ msgid "Authentication Log"
msgstr "Registro de Autenticación"
msgid "Authentication failed: %{error_message}"
-msgstr ""
+msgstr "Error de autenticación: %{error_message}"
msgid "Authentication log"
msgstr "Log de autenticación"
@@ -1398,10 +1648,10 @@ msgid "Authentication method"
msgstr "Método de autenticación"
msgid "Authentication method updated"
-msgstr ""
+msgstr "Método de autenticación actualizado"
msgid "Authentication via U2F device failed."
-msgstr ""
+msgstr "Se ha producido un error en la autenticación a través del dispositivo U2F."
msgid "Author"
msgstr "Autor"
@@ -1413,7 +1663,7 @@ msgid "Authorization key"
msgstr "Clave de autorización"
msgid "Authorization was granted by entering your username and password in the application."
-msgstr ""
+msgstr "Se concedió la autorización al introducir su nombre de usuario y contraseña en la aplicación."
msgid "Authorize"
msgstr "Autorizar"
@@ -1422,7 +1672,7 @@ msgid "Authorize %{link_to_client} to use your account?"
msgstr "¿Autorizar %{link_to_client} para utilizar su cuenta?"
msgid "Authorized %{new_chat_name}"
-msgstr ""
+msgstr "Autorizado %{new_chat_name}"
msgid "Authorized At"
msgstr "Autorizado en"
@@ -1443,7 +1693,7 @@ msgid "Auto DevOps, runners and job artifacts"
msgstr "Auto DevOps, ejecutores y artefactos"
msgid "Auto-cancel redundant, pending pipelines"
-msgstr ""
+msgstr "Cancelación redundante automática, pipelines pendientes"
msgid "AutoDevOps|Auto DevOps"
msgstr "Auto DevOps"
@@ -1461,28 +1711,37 @@ msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "Más información en %{link_to_documentation}"
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr "El pipeline de Auto DevOps ha sido habilitado y será utilizado si no se encuentra un archivo de configuración CI alternativo. %{more_information_link}"
+
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
msgid "Automatically marked as default internal user"
msgstr "Marcado automáticamente como usuario interno por defecto"
-msgid "Automatically resolve merge request diff discussions when they become outdated"
-msgstr ""
-
msgid "Automatically resolved"
msgstr "Resuelto automáticamente"
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr "Nota"
+
msgid "Available"
msgstr "Disponible"
msgid "Available group Runners: %{runners}"
-msgstr ""
+msgstr "Grupo de ejecutores disponible: %{runners}"
msgid "Available shared Runners:"
-msgstr ""
+msgstr "Ejecutores compartidos disponibles:"
msgid "Available specific runners"
-msgstr ""
+msgstr "Ejecutores dedicados disponibles"
msgid "Avatar for %{assigneeName}"
msgstr "Avatar para %{assigneeName}"
@@ -1575,7 +1834,7 @@ msgid "Badges|This project has no badges"
msgstr "Este proyecto no tiene insignias"
msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr ""
+msgstr "Va a eliminar esta insignia. Las insignias eliminadas <strong>no se pueden</strong> restaurar."
msgid "Badges|Your badges"
msgstr "Sus insignias"
@@ -1583,6 +1842,30 @@ msgstr "Sus insignias"
msgid "Badges|e.g. %{exampleUrl}"
msgstr "por ejemplo, %{exampleUrl}"
+msgid "Badge|New"
+msgstr "Nueva"
+
+msgid "Balsamiq file could not be loaded."
+msgstr "El archivo Balsamiq no se pudo cargar."
+
+msgid "BambooService|A continuous integration and build server"
+msgstr "Un servidor de integración y construcción continua"
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr "Un usuario con acceso a la API, si es aplicable"
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr "Atlassian Bamboo CI"
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr "La URL raíz de Bamboo, por ejemplo, https://bamboo.example.com"
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr "Borrar todos los comentarios pendientes"
@@ -1590,13 +1873,13 @@ msgid "BatchComments|Discard review?"
msgstr "¿Descartar revisión?"
msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
-msgstr ""
+msgstr "Está a punto de descartar su revisión, lo que eliminará todos sus comentarios pendientes. Los comentarios eliminados %{strong_start} no pueden %{strong_end} volver a restaurarse."
msgid "Be careful. Changing the project's namespace can have unintended side effects."
-msgstr ""
+msgstr "Tenga cuidado. Cambiar el espacio de nombres del proyecto puede tener efectos secundarios no deseados."
msgid "Be careful. Renaming a project's repository can have unintended side effects."
-msgstr ""
+msgstr "Tenga cuidado. Cambiar el nombre del repositorio de un proyecto puede tener efectos secundarios no deseados."
msgid "Begin with the selected commit"
msgstr "Iniciar con el commit seleccionado"
@@ -1626,16 +1909,16 @@ msgid "BillingPlans|Downgrade"
msgstr "Planes de Facturación | Volver a un plan anterior"
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
-msgstr ""
+msgstr "Obtenga más información sobre cada plan leyendo nuestro %{faq_link}, o pruebe una versión gratuita de 30 días de Gitlab.com Gold."
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
-msgstr ""
+msgstr "Aprenda más sobre cada plan, leyendo nuestro %{faq_link}."
msgid "BillingPlans|Manage plan"
msgstr "Gestionar plan"
msgid "BillingPlans|Please contact %{customer_support_link} in that case."
-msgstr ""
+msgstr "Por favor contacte con %{customer_support_link} para ese caso."
msgid "BillingPlans|See all %{plan_name} features"
msgstr "Ver todas las novedades del %{plan_name}"
@@ -1674,7 +1957,7 @@ msgid "BillingPlans|per user"
msgstr "por usuario"
msgid "Bitbucket Server Import"
-msgstr ""
+msgstr "Importar desde un servidor de Bitbucket"
msgid "Bitbucket import"
msgstr "Importar desde Bitbucket"
@@ -1685,15 +1968,34 @@ msgstr ""
msgid "Blocked"
msgstr "Bloqueado"
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr "Blog"
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr "Tableros"
-msgid "Branch %{branchName} was not found in this project's repository."
+msgid "Boards|Edit board"
msgstr ""
+msgid "Boards|View scope"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr "No se encontró la rama %{branchName} en el repositorio de este proyecto."
+
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr "La rama <strong>%{branch_name}</strong> fue creada. Para configurar el auto despliegue, escoge una plantilla Yaml para GitLab CI y envía tus cambios. %{link_to_autodeploy_doc}"
@@ -1706,6 +2008,9 @@ msgstr "La rama ya existe"
msgid "Branch name"
msgstr "Nombre de la rama"
+msgid "Branch not loaded - %{branchId}"
+msgstr "Branch no cargada - %{branchId}"
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Buscar ramas"
@@ -1806,13 +2111,13 @@ msgid "Branches|The branch could not be updated automatically because it has div
msgstr ""
msgid "Branches|The default branch cannot be deleted"
-msgstr ""
+msgstr "No se puede eliminar la rama por defecto"
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
+msgstr "Para evitar pérdida de datos, considere hacer un merge request de esta rama antes de borrarla."
msgid "Branches|To confirm, type %{branch_name_confirmation}:"
msgstr ""
@@ -1821,7 +2126,7 @@ msgid "Branches|To discard the local changes and overwrite the branch with the u
msgstr ""
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
-msgstr ""
+msgstr "Va a eliminar de forma permanente la rama protegida %{branch_name}."
msgid "Branches|diverged from upstream"
msgstr ""
@@ -1836,10 +2141,10 @@ msgid "Branches|protected"
msgstr "protegido"
msgid "Broadcast Message was successfully created."
-msgstr ""
+msgstr "El mensaje de difusión se creó correctamente."
msgid "Broadcast Message was successfully updated."
-msgstr ""
+msgstr "El mensaje de difusión se actualizó correctamente."
msgid "Browse Directory"
msgstr "Examinar directorio"
@@ -1856,6 +2161,21 @@ msgstr "Examinar archivos"
msgid "Built-in"
msgstr "Integrado"
+msgid "BurndownChartLabel|Guideline"
+msgstr "Guía"
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr "Incidencias abiertas"
+
+msgid "BurndownChartLabel|Progress"
+msgstr "Progreso"
+
+msgid "BurndownChartLabel|Remaining"
+msgstr "Restante"
+
msgid "Business"
msgstr "Negocio"
@@ -1863,16 +2183,19 @@ msgid "Business metrics (Custom)"
msgstr "Métricas de negocio (personalizadas)"
msgid "Buy EE"
-msgstr ""
+msgstr "Comprar EE"
msgid "Buy GitLab Enterprise Edition"
-msgstr ""
+msgstr "Comprar GitLab Enterprise Edition"
msgid "By %{user_name}"
msgstr "Por %{user_name}"
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
-msgstr ""
+msgstr "De forma predeterminada, GitLab envía correos electrónicos en formatos HTML y de texto sin formato para que los clientes de correo puedan elegir qué formato utilizar. Desactive esta opción sí solo desea enviar correos electrónicos sin formato."
+
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr "Por defecto, todos los proyectos y grupos utilizarán la configuración de notificaciones global."
msgid "ByAuthor|by"
msgstr "por"
@@ -1893,10 +2216,10 @@ msgid "CI Lint"
msgstr "Cl Lint"
msgid "CI variables"
-msgstr ""
+msgstr "Variables de CI/CD"
msgid "CI will run using the credentials assigned above."
-msgstr ""
+msgstr "CI/CD se ejecutará utilizando las credenciales asignadas anteriormente."
msgid "CI/CD"
msgstr "CI/CD"
@@ -1923,13 +2246,13 @@ msgid "CICD|Continuous deployment to production"
msgstr "Despliegue continuo a producción"
msgid "CICD|Continuous deployment to production using timed incremental rollout"
-msgstr ""
+msgstr "Implementación continua a producción utilizando despliegue incremental cronometrado"
msgid "CICD|Default to Auto DevOps pipeline"
-msgstr ""
+msgstr "Por defecto al pipeline de Auto DevOps"
msgid "CICD|Default to Auto DevOps pipeline for all projects"
-msgstr ""
+msgstr "Por defecto al pipeline de Auto DevOps para todos los proyectos"
msgid "CICD|Deployment strategy"
msgstr "Estrategia de despliegue"
@@ -1941,34 +2264,40 @@ msgid "CICD|Learn more about Auto DevOps"
msgstr "Aprenda más de Auto DevOps"
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
-msgstr ""
+msgstr "El pipeline de Auto DevOps se ejecutará si no se encuentra ningún archivo de configuración alternativo de CI."
msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
-msgstr ""
+msgstr "Debe añadir un %{kubernetes_cluster_start} cluster de integración Kubernetes%{kubernetes_cluster_end} a este proyecto con un dominio para que su estrategia de despliegue funcione correctamente."
msgid "CICD|group enabled"
-msgstr ""
+msgstr "grupo habilitado"
msgid "CICD|instance enabled"
msgstr "Instancia habilitada"
msgid "CONTRIBUTING"
-msgstr ""
+msgstr "CONTRIBUTING"
msgid "Callback URL"
msgstr "URL de callback"
msgid "Can override approvers and approvals required per merge request"
-msgstr ""
+msgstr "Los aprobadores y las aprobaciones requeridas se pueden sobreescribir por cada merge request"
msgid "Can't find HEAD commit for this branch"
msgstr "No se puede encontrar el commit HEAD para este 'branch'"
+msgid "Can't find variable: ZiteReader"
+msgstr "No se puede encontrar la variable: ZiteReader"
+
msgid "Can't remove group members without group managed account"
-msgstr ""
+msgstr "No se pueden eliminar miembros del grupo sin una cuenta administrada por grupo"
+
+msgid "Can't scan the code?"
+msgstr "¿No puede escanear el código?"
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
+msgstr "Canary Deployment es una estrategia de CI, donde solo una pequeña porción se actualiza a la nueva versión de tu aplicación."
msgid "Cancel"
msgstr "Cancelar"
@@ -1977,25 +2306,31 @@ msgid "Cancel this job"
msgstr "Cancelar este trabajo"
msgid "Cannot be merged automatically"
-msgstr ""
+msgstr "No se puede hacer merge automáticamente"
msgid "Cannot create the abuse report. The user has been deleted."
-msgstr ""
+msgstr "No se puede crear el informe de abuso. El usuario ha sido eliminado."
msgid "Cannot create the abuse report. This user has been blocked."
-msgstr ""
+msgstr "No se puede crear el informe de abuso. Este usuario ha sido bloqueado."
msgid "Cannot modify managed Kubernetes cluster"
msgstr "No se puede modificar el clúster de Kubernetes gestionado"
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr "¡No se puede referir a un hito de grupo por un id interno!"
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
+msgstr "No se puede procesar la imagen. Se ha superado el número máximo de caracteres (%{charLimit})."
+
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
msgstr ""
msgid "Cannot skip two factor authentication setup"
-msgstr ""
+msgstr "No se puede omitir la configuración de autenticación de dos factores"
msgid "Capacity threshold"
-msgstr ""
+msgstr "Límite de capacidad"
msgid "Certificate"
msgstr "Certificado"
@@ -2006,8 +2341,14 @@ msgstr "Certificado (PEM)"
msgid "Change Weight"
msgstr "Cambiar peso"
+msgid "Change assignee(s)"
+msgstr "Cambiar asignado(s)"
+
+msgid "Change assignee(s)."
+msgstr "Cambiar asignado(s)."
+
msgid "Change path"
-msgstr ""
+msgstr "Cambiar la ruta"
msgid "Change permissions"
msgstr "Modificar los permisos"
@@ -2016,7 +2357,16 @@ msgid "Change template"
msgstr "Cambiar plantilla"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
-msgstr ""
+msgstr "Cambie este valor para modificar la frecuencia con la que la interfaz de usuario de GitLab obtiene las actualizaciones."
+
+msgid "Change title"
+msgstr "Cambiar el título"
+
+msgid "Change your password"
+msgstr "Cambia su contraseña"
+
+msgid "Change your password or recover your current one"
+msgstr "Cambia o recuperar su contraseña"
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "Escoger en la rama"
@@ -2031,17 +2381,23 @@ msgid "ChangeTypeAction|Revert"
msgstr "Revertir"
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
-msgstr ""
+msgstr "Esta acción creará un nuevo commit para deshacer los cambios existentes."
msgid "Changes"
msgstr "Cambios"
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
-msgstr ""
+msgstr "Los cambios se muestran como si la revisión del <b>origen</b> se ha fusionado con la revisión del <b>objetivo</b>."
msgid "Changes suppressed. Click to show."
msgstr "Cambios eliminados. Haga clic para mostrar."
+msgid "Changes the title to \"%{title_param}\"."
+msgstr "Cambia el título a \"%{title_param}\"."
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr "No se realizarán los cambios hasta que el índice sea %{link_start}recreado%{link_end}."
+
msgid "Charts"
msgstr "Gráficos"
@@ -2052,10 +2408,10 @@ msgid "Check again"
msgstr "Verficar de nuevo"
msgid "Check feature availability on namespace plan"
-msgstr ""
+msgstr "Compruebe la disponibilidad de la función en el plan de espacio de nombres"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
-msgstr ""
+msgstr "Compruebe la documentación %{docs_link_start}%{docs_link_end}."
msgid "Check your .gitlab-ci.yml"
msgstr "Compruebe su fichero .gitlab-ci.yml"
@@ -2064,11 +2420,14 @@ msgid "Checking %{text} availability…"
msgstr "Comprobando disponibilidad de %{text}..."
msgid "Checking approval status"
-msgstr ""
+msgstr "Comprobar el estado de aprobación"
msgid "Checking branch availability..."
msgstr "Verificando disponibilidad de la rama..."
+msgid "Checking username availability..."
+msgstr "Verificando la disponibilidad del nombres de usuario..."
+
msgid "Cherry-pick this commit"
msgstr "Escoger este cambio"
@@ -2076,10 +2435,10 @@ msgid "Cherry-pick this merge request"
msgstr "Escoger esta solicitud de fusión"
msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
-msgstr ""
+msgstr "Elija <strong>Crear archivo</strong> y espere a que se complete el archivo."
msgid "Choose <strong>Next</strong> at the bottom of the page."
-msgstr ""
+msgstr "Elija <strong>Siguiente</strong> en la parte inferior de la página."
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr "Elija un branch/tag (por ejemplo, %{master}) o introduzca un commit (por ejemplo, %{sha}) para ver lo qué ha cambiado o para crear un merge request."
@@ -2090,6 +2449,9 @@ msgstr "Seleccione un archivo"
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr "Elija una plantilla"
+
msgid "Choose a template..."
msgstr "Elegir una plantilla..."
@@ -2100,7 +2462,7 @@ msgid "Choose any color."
msgstr "Elegir cualquier color."
msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
-msgstr ""
+msgstr "Elija entre <code>clone</code> o <code>fetch</code> para obtener el código de la aplicación más reciente"
msgid "Choose file…"
msgstr "Seleccione un archivo…"
@@ -2109,18 +2471,18 @@ msgid "Choose the top-level group for your repository imports."
msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
-msgstr ""
+msgstr "Escoja el nivel de visibilidad, habilite/deshabilite las características del proyecto (incidencias, repositorio, wiki, fragmentos de código) y configure los permisos necesarios según sus necesidades."
msgid "Choose what content you want to see on a group’s overview page"
-msgstr ""
+msgstr "Elija que contenido desea ver en la página de información general de un grupo"
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
-msgstr ""
+msgstr "Elija que repositorios quiere conectar y ejecutar los CI/CD pipelines."
msgid "Choose which shards you wish to synchronize to this secondary node."
-msgstr ""
+msgstr "Elija cuál de los shards desea sincronizar para este nodo secundario."
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2148,7 +2510,7 @@ msgid "CiStatusLabel|pending"
msgstr "pendiente"
msgid "CiStatusLabel|preparing"
-msgstr ""
+msgstr "preparando"
msgid "CiStatusLabel|skipped"
msgstr "omitido"
@@ -2184,7 +2546,7 @@ msgid "CiStatusText|pending"
msgstr "pendiente"
msgid "CiStatusText|preparing"
-msgstr ""
+msgstr "preparando"
msgid "CiStatusText|skipped"
msgstr "omitido"
@@ -2192,17 +2554,35 @@ msgstr "omitido"
msgid "CiStatus|running"
msgstr "en ejecución"
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr "No se puede utilizar una variable enmascarada con el valor actual"
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr "Clave"
+
+msgid "CiVariables|Masked"
+msgstr "Máscara"
+
msgid "CiVariables|Remove variable row"
-msgstr ""
+msgstr "Eliminar fila de variables"
-msgid "CiVariables|This variable will not be masked"
-msgstr ""
+msgid "CiVariables|Scope"
+msgstr "Alcance"
+
+msgid "CiVariables|State"
+msgstr "Estado"
+
+msgid "CiVariables|Type"
+msgstr "Tipo"
+
+msgid "CiVariables|Value"
+msgstr "Valor"
msgid "CiVariable|* (All environments)"
msgstr "* (Todos los entornos)"
@@ -2211,16 +2591,16 @@ msgid "CiVariable|All environments"
msgstr "Todos los entornos"
msgid "CiVariable|Create wildcard"
-msgstr ""
+msgstr "Crear comodín"
msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
+msgstr "Se ha producido un error al guardar las variables"
msgid "CiVariable|Masked"
-msgstr ""
+msgstr "Enmascarado"
msgid "CiVariable|New environment"
-msgstr ""
+msgstr "Nuevo entorno"
msgid "CiVariable|Protected"
msgstr "Protegido"
@@ -2229,16 +2609,16 @@ msgid "CiVariable|Search environments"
msgstr "Buscar entornos"
msgid "CiVariable|Toggle masked"
-msgstr ""
+msgstr "Alternar enmascaramiento"
msgid "CiVariable|Toggle protected"
-msgstr ""
+msgstr "Alternar protegido"
msgid "CiVariable|Validation failed"
msgstr "Error de validación"
msgid "Classification Label (optional)"
-msgstr ""
+msgstr "Etiqueta de clasificación (opcional)"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "no está disponible: %{reason}"
@@ -2247,7 +2627,7 @@ msgid "Clear"
msgstr "Limpiar"
msgid "Clear input"
-msgstr ""
+msgstr "Limpiar entrada"
msgid "Clear search"
msgstr "Limpiar búsqueda"
@@ -2255,20 +2635,29 @@ msgstr "Limpiar búsqueda"
msgid "Clear search input"
msgstr "Limpiar el historial de búsqueda"
+msgid "Clear weight"
+msgstr "Limpiar peso"
+
+msgid "Clears weight."
+msgstr "Limpiar peso."
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
+msgstr "Haga clic en cualquier <strong>nombre de proyecto</strong> en la lista de proyectos que se muestra a continuación para navegar hasta el hito de proyecto correspondiente."
+
+msgid "Click here"
msgstr ""
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
-msgstr ""
+msgstr "Haga click en el botón <strong>Descargar</strong> y espere a que se complete la descarga."
msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
-msgstr ""
+msgstr "Haga clic sobre el botón <strong>Promocionar</strong> , situado en la esquina superior derecha para promocionarlo a un hito de grupo."
msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
-msgstr ""
+msgstr "Haga click en el botón <strong>Seleccionar uno</strong> en la parte derecha, ya que sólo necesitamos \"Google Code Project Hosting\"."
msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
-msgstr ""
+msgstr "Haga clic en el botón que se muestra a continuación para comenzar con el proceso de instalación navegando hasta la página de Kubernetes"
msgid "Click to expand it."
msgstr "Haga clic para expandir."
@@ -2312,6 +2701,9 @@ msgstr "Cerrar épica"
msgid "Close milestone"
msgstr "Cerrar hito"
+msgid "Close sidebar"
+msgstr "Cerrar la barra lateral"
+
msgid "Closed"
msgstr "Cerrado"
@@ -2319,25 +2711,31 @@ msgid "Closed issues"
msgstr "Incidencias cerradas"
msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
-msgstr ""
+msgstr "ClusterIntegration | %{custom_domain_start}Más información%{custom_domain_end}."
msgid "ClusterIntegration| can be used instead of a custom domain."
-msgstr ""
+msgstr "Se puede utilizar en lugar de un dominio personalizado."
msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
+msgstr "Es el ámbito del entorno por defecto para este cluster. Esto significa que todos los trabajos, independientemente de su entorno, utilizarán este cluster. %{environment_scope_start}Más información%{environment_scope_end}"
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} se instaló correctamente en su clúster de Kubernetes"
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr "%{title} desinstalado correctamente."
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
msgstr "API URL"
msgid "ClusterIntegration|API URL should be a valid http/https url."
-msgstr ""
+msgstr "La URL de la API debe ser una url http/https válida."
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr "Añadir cluster de Kubernetes"
@@ -2346,34 +2744,49 @@ msgid "ClusterIntegration|Add a Kubernetes cluster integration"
msgstr "Añadir integración con cluster de Kubernetes "
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
-msgstr ""
+msgstr "Agregar un cluster Kubernetes a su grupo compartirá automáticamente el cluster en todos sus proyectos. Utilice las aplicaciones de revisión, implemente sus aplicaciones y ejecute fácilmente los pipelines para todos los proyectos que utilizan el mismo clúster."
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr "Agregar un clúster Kubernetes compartirá automáticamente el clúster a todos los proyectos. Utilice las aplicaciones de revisión, implemente sus aplicaciones y ejecute fácilmente sus pipelines en todos los proyectos que utilizan el mismo clúster."
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
-msgstr ""
+msgstr "Agregar una integración a su grupo compartirá el cluster en todos sus proyectos."
+
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr "Agregar una integración compartirá el cluster en todos sus proyectos."
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
-msgstr ""
+msgstr "Opciones avanzadas para la integración de este clúster de Kubernetes"
+
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr "Todos los datos serán eliminados y no se podrán restaurar."
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr "Permitir que GitLab administre el espacio de nombres y las cuentas de servicio para este cluster."
msgid "ClusterIntegration|Alternatively"
msgstr "Alternativamente"
msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
-msgstr ""
+msgstr "Se ha producido un error al intentar contactar con la API de Google Cloud. Por favor, inténtelo de nuevo más tarde."
msgid "ClusterIntegration|An error occurred while trying to fetch project zones: %{error}"
-msgstr ""
+msgstr "Se ha producido un error al intentar obtener las zonas del proyecto: %{error}"
msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
-msgstr ""
+msgstr "Se ha producido un error al intentar recuperar los proyectos: %{error}"
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
-msgstr ""
+msgstr "Se ha producido un error al intentar obtener los tipos de máquina de las zonas: %{error}"
+
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr "Se cancelará cualquier pipeline que se encuentre en ejecución."
msgid "ClusterIntegration|Applications"
msgstr "Aplicaciones"
msgid "ClusterIntegration|Apply for credit"
-msgstr ""
+msgstr "Solicitar crédito"
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr "¿Está seguro de que desea eliminar la integración con este clúster de Kubernetes? Esta acción no eliminará su clúster de Kubernetes."
@@ -2385,25 +2798,25 @@ msgid "ClusterIntegration|CA Certificate"
msgstr "Certificado CA"
msgid "ClusterIntegration|Cert-Manager"
-msgstr ""
+msgstr "Administrador de certificados"
msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
-msgstr ""
+msgstr "Cert-Manager es un controlador de administración de certificados de Kubernetes nativo, que ayuda a emitir certificados. La instalación de Cert-Manager en su cluster emitirá un certificado por %{letsEncrypt} y garantizará que los certificados sean válidos y estén actualizados."
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "paquete de certificado de autoridad (formato PEM)"
msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
-msgstr ""
+msgstr "Seleccione que aplicaciones instalar en su clúster Kubernetes. Es necesario Helm Tiller para instalar cualquiera de las siguientes aplicaciones."
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
-msgstr ""
+msgstr "Seleccione cuál de los entornos de su proyecto utilizará este clúster de Kubernetes."
msgid "ClusterIntegration|Cluster health"
msgstr "Estado de salud del cluster"
msgid "ClusterIntegration|Cluster name is required."
-msgstr ""
+msgstr "Se requiere el nombre del clúster."
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
msgstr ""
@@ -2415,19 +2828,19 @@ msgid "ClusterIntegration|Copy CA Certificate"
msgstr "Copiar Certificado CA"
msgid "ClusterIntegration|Copy Ingress Endpoint to clipboard"
-msgstr ""
+msgstr "Copiar el endpoint de entrada al portapapeles"
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr "Copiar el nombre del host de Jupyter en el portapapeles"
msgid "ClusterIntegration|Copy Knative Endpoint to clipboard"
-msgstr ""
+msgstr "Copiar el endpoint de Knative al portapapeles"
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr "Copiar el nombre del clúster Kubernetes"
msgid "ClusterIntegration|Copy Service Token"
-msgstr ""
+msgstr "Copiar token de servicio"
msgid "ClusterIntegration|Create Kubernetes cluster"
msgstr "Crear cluster de Kubernetes"
@@ -2448,19 +2861,19 @@ msgid "ClusterIntegration|Environment scope"
msgstr "Alcance del entorno"
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
-msgstr ""
+msgstr "Por cada nueva cuenta de Google Cloud Platform (GCP) recibe $300 de crédito %{sign_up_link}. En colaboración con Google, Gitlab le ofrece $200 adicionales para cuentas nuevas o cuentas ya existentes de Google Compute Platform para empezar con la integración de GitLab con Google Kubernetes Engine."
msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
-msgstr ""
+msgstr "Se ha producido un error al configurar el cluster de Google Kubernetes Engine: %{message}"
msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
-msgstr ""
+msgstr "Se ha producido un error al hacer una petición a Google Cloud Platform: %{message}"
msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
-msgstr ""
+msgstr "Se ha producido un error al ejecutar Kubeclient: %{message}"
msgid "ClusterIntegration|Fetching machine types"
-msgstr ""
+msgstr "Obtener los tipos de máquinas"
msgid "ClusterIntegration|Fetching projects"
msgstr "Obtener proyectos"
@@ -2475,7 +2888,10 @@ msgid "ClusterIntegration|GitLab Runner"
msgstr "GitLab Runner"
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
-msgstr ""
+msgstr "Los ejecutores de GitLab se conectan al repositorio de código de este proyecto y ejecutan los trabajos de CI/CD, devolviendo los resultados e desplegando las aplicaciones a producción."
+
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr "Cluster de GitLab administrado"
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Proyecto de Google Cloud Platform"
@@ -2493,49 +2909,40 @@ msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
+msgstr "Helm optimiza la instalación y la administración de aplicaciones de Kubernetes. Tiller se ejecuta dentro de su cluster de Kubernetes y gestiona las versiones de sus charts."
msgid "ClusterIntegration|Hide"
msgstr "Ocultar"
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
-msgstr ""
+msgstr "Si está configurando varios clústeres y utiliza Auto DevOps, por favor lea primero, %{help_link_start} y %{help_link_end}."
msgid "ClusterIntegration|In order to view the health of your cluster, you must first install Prometheus below."
-msgstr ""
+msgstr "Para ver el estado de salud de su cluster, primero debe instalar Prometheus:"
msgid "ClusterIntegration|Ingress"
msgstr "Entrada"
msgid "ClusterIntegration|Ingress Endpoint"
-msgstr ""
+msgstr "Endpoint de Ingress"
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
-msgstr ""
-
-msgid "ClusterIntegration|Install"
-msgstr "Instalar"
-
-msgid "ClusterIntegration|Installed"
-msgstr "Instalado"
-
-msgid "ClusterIntegration|Installing"
-msgstr "Instalando"
+msgstr "Ingress le ofrece una forma de encaminar las solicitudes a los servicios en función del host o la ruta de la solicitud, centralizando una serie de servicios en un solo punto de entrada."
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
-msgstr ""
+msgstr "La instalación de Ingress puede incurrir en costes adicionales. Obtenga más información sobre Ingress en el siguiente enlace %{pricingLink}."
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
-msgstr ""
+msgid "ClusterIntegration|Instance cluster"
+msgstr "Instancia del clúster"
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
-msgstr ""
+msgstr "Integrar la automatización del clúster de Kubernetes"
msgid "ClusterIntegration|Integration status"
msgstr "Estado de integración"
msgid "ClusterIntegration|Issuer Email"
-msgstr ""
+msgstr "Correo electrónico del emisor"
msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
msgstr ""
@@ -2547,19 +2954,22 @@ msgid "ClusterIntegration|JupyterHub"
msgstr "JupyterHub"
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
-msgstr ""
+msgstr "JupyterHub es un concentrador multiusuario que genera, gestiona y representa varias instancias del servidor para un sólo usuario, Jupyter notebook. JupyterHub puede utilizarse para servir notebooks a una clase de estudiantes, a un grupo corporativo de ciencias de datos o a un grupo de investigación científica."
msgid "ClusterIntegration|Knative"
msgstr "Knative"
msgid "ClusterIntegration|Knative Domain Name:"
-msgstr ""
+msgstr "Nombre de dominio de Knative:"
msgid "ClusterIntegration|Knative Endpoint:"
-msgstr ""
+msgstr "Endpoint de Knative:"
+
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr "Se actualizó correctamente el nombre de dominio de Knative."
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
-msgstr ""
+msgstr "Knative extiende Kubernetes para proporcionar un conjunto de componentes de middleware que son esenciales para construir aplicaciones modernas y basadas en contenedores que pueden ejecutarse en cualquier lugar: en su propio centro de datos, en la nube o incluso en un centro de datos de terceros."
msgid "ClusterIntegration|Kubernetes cluster"
msgstr "cluster de Kubernetes"
@@ -2568,19 +2978,19 @@ msgid "ClusterIntegration|Kubernetes cluster details"
msgstr "Detalles del cluster de Kubernetes"
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
-msgstr ""
+msgstr "Se está creando el clúster de Kubernetes en Google Kubernetes Engine..."
msgid "ClusterIntegration|Kubernetes cluster name"
msgstr "Nombre de cluster de Kubernetes"
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
-msgstr ""
+msgstr "El clúster de Kubernetes se creó correctamente en Google Kubernetes Engine. Actualice la página para ver los detalles del clúster Kubernetes"
msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "ClusterIntegration | Los clústeres de Kubernetes le permiten utilizar aplicaciones de revisión, desplegar sus aplicaciones, ejecutar sus pipelines y mucho más de una manera sencilla."
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
-msgstr ""
+msgstr "Los clústeres de Kubernetes se pueden utilizar para desplegar aplicaciones y proporcionar aplicaciones de revisión para este proyecto"
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr "Aprenda más sobre los tipos de %{help_link_start_machine_type}instancias %{help_link_end} y sus %{help_link_start_pricing}precios%{help_link_end}."
@@ -2594,6 +3004,9 @@ msgstr "Más información sobre Kubernetes"
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr "Más información sobre los grupos de clústeres de Kubernetes"
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr "Más información sobre los grupos de clústeres de Kubernetes"
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr "Let's Encrypt"
@@ -2603,9 +3016,6 @@ msgstr "Tipo de máquina"
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr "Asegúrese de que su cuenta %{link_to_requirements} cumple con los requisitos para crear clusters de Kubernetes"
-msgid "ClusterIntegration|Manage"
-msgstr "Administrar"
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr "Administre su cluster de Kubernetes visitando %{link_gke}"
@@ -2625,7 +3035,7 @@ msgid "ClusterIntegration|Number of nodes"
msgstr "Número de nodos"
msgid "ClusterIntegration|Number of nodes must be a numerical value."
-msgstr ""
+msgstr "El número de nodos debe ser un valor numérico."
msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
msgstr "Por favor, introduzca la información de acceso a su clúster de Kubernetes. Si necesita ayuda, puede leer nuestra %{link_to_help_page} en Kubernetes"
@@ -2634,7 +3044,7 @@ msgid "ClusterIntegration|Please make sure that your Google account meets the fo
msgstr "Asegúrese de que su cuenta de Google cumpla con los siguientes requisitos:"
msgid "ClusterIntegration|Point a wildcard DNS to this generated endpoint in order to access your application after it has been deployed."
-msgstr ""
+msgstr "ClusterIntegration | Apunte un DNS comodín a este punto final generado para acceder a su aplicación después de que se haya desplegar."
msgid "ClusterIntegration|Project cluster"
msgstr "Clúster del proyecto"
@@ -2652,25 +3062,25 @@ msgid "ClusterIntegration|RBAC-enabled cluster"
msgstr "Cluster RBAC habilitado"
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
-msgstr ""
+msgstr "Lea nuestra %{link_to_help_page} sobre la integración de clústeres Kubernetes."
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
-msgstr ""
+msgstr "Eliminar la integración de clústeres de Kubernetes"
msgid "ClusterIntegration|Remove integration"
msgstr "Eliminar integración"
msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
-msgstr ""
+msgstr "Eliminar la configuración del clúster de Kubernetes de este proyecto. Esto no eliminará su clúster de Kubernetes real."
msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
-msgstr ""
+msgstr "Reemplácelo con su propio nombre de host si lo desea. Si lo hace, apunte el nombre de host a la Dirección IP de Ingress que se muestra en la parte superior."
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "Falló la solicitud para iniciar la instalación"
-msgid "ClusterIntegration|Retry update"
-msgstr ""
+msgid "ClusterIntegration|Request to begin uninstalling failed"
+msgstr "La solicitud para comenzar la desinstalación ha fallado"
msgid "ClusterIntegration|Save changes"
msgstr "Guardar cambios"
@@ -2685,7 +3095,7 @@ msgid "ClusterIntegration|Search zones"
msgstr "Buscar zonas"
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
-msgstr ""
+msgstr "Consulte y edite los detalles de su clúster de Kubernetes"
msgid "ClusterIntegration|Select machine type"
msgstr "Seleccione el tipo de máquina"
@@ -2706,10 +3116,10 @@ msgid "ClusterIntegration|Select zone to choose machine type"
msgstr "Seleccione la zona para elegir el tipo de máquina"
msgid "ClusterIntegration|Service Token"
-msgstr ""
+msgstr "Token de servicio"
msgid "ClusterIntegration|Service token is required."
-msgstr ""
+msgstr "El token de servicio es necesario."
msgid "ClusterIntegration|Show"
msgstr "Mostrar"
@@ -2718,65 +3128,83 @@ msgid "ClusterIntegration|Something went wrong on our end."
msgstr "Algo salió mal de nuestro lado."
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
-msgstr ""
+msgstr "Se ha producido un error durante la creación de su clúster de Kubernetes en Google Kubernetes Engine"
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "Algo salió mal durante la instalación de %{title}"
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr "Se ha producido un error al desinstalar %{title}"
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr "Se ha producido un error al intentar actualizar el nombre de dominio de Knative."
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
+msgstr "El certificado Kubernetes utilizado para autenticarse en el clúster."
+
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
+msgstr "La URL utilizada para acceder a la API de Kubernetes."
+
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
+msgstr "Se eliminará la dirección IP asociada y no se podrá restaurar."
+
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
+msgstr "El certificado asociado se eliminará y no se podrá restaurar."
+
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
+msgstr "Se eliminarán el balanceador de carga asociado y la dirección IP y no podrán ser restaurados."
+
msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
-msgstr ""
+msgstr "El endpoint está en proceso de ser asignado. Por favor verifique su cluster o las cuotas de Google Kubernetes Engine si es proceso tarda mucho tiempo en finalizar."
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
+msgstr "Se ha producido un error durante la autenticación con su cluster. Por favor, asegúrese de que su la CA de su certificado y su token son válidos."
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr "Esta cuenta debe tener permisos para crear un clúster de Kubernetes en el %{link_to_container_project} especificado a continuación"
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
-msgstr ""
+msgstr "Esta opción le permitirá instalar aplicaciones en clústeres RBAC."
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
-msgstr ""
+msgstr "Para acceder a su aplicación después del despliegue, apunte un registroDNS comodín al endpoint de Knative."
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "Activar/Desactivar el clúster de Kubernetes"
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
-msgstr ""
-
-msgid "ClusterIntegration|Updating"
-msgstr ""
-
-msgid "ClusterIntegration|Upgrade"
-msgstr "Actualización"
-
-msgid "ClusterIntegration|Upgrade failed"
-msgstr "Actualización fallida"
-
-msgid "ClusterIntegration|Upgraded"
-msgstr "Actualizado"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr "ClusterIntegration | Desinstalar %{appTitle}"
-msgid "ClusterIntegration|Upgrading"
-msgstr "Actualizando"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgstr "Se ha podroducido un erro al actualizar. Por favor revise los registros y vuelva a intentarlo."
msgid "ClusterIntegration|Validating project billing status"
msgstr "Validación del estado de facturación del proyecto"
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
-msgstr ""
+msgstr "No hemos podido verificar que uno de sus proyectos en GCP tenga habilitada la facturación. Por favor, inténtalo de nuevo."
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr ""
+msgstr "Con un clúster de Kubernetes asociado a este proyecto, puede utilizar las aplicaciones de revisión, implementar sus aplicaciones, ejecutar sus pipelines y mucho más, de una manera sencilla."
+
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr "Está a punto de desinstalar %{appTitle} de su cluster."
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr "Primero debe instalar Helm Tiller antes de instalar las aplicaciones que se muestran a continuación"
msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
-msgstr ""
+msgstr "Debe tener un cluster RBAC habilitado para instalar Knative."
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "Su cuenta debe tener %{link_to_kubernetes_engine}"
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr "La API de su cluster está inaccesible. Por favor, asegúrese de que la URL del API es correcta."
+
msgid "ClusterIntegration|Zone"
msgstr "Zona"
@@ -2793,7 +3221,7 @@ msgid "ClusterIntegration|meets the requirements"
msgstr "cumple con los requisitos"
msgid "ClusterIntegration|pricing"
-msgstr ""
+msgstr "Precios"
msgid "ClusterIntegration|properly configured"
msgstr "configurado correctamente"
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr "Contraer la barra lateral"
+msgid "ComboSearch is not defined"
+msgstr "ComboSearch no está definido"
+
msgid "Command line instructions"
msgstr "Instrucciones de la línea de comando"
+msgid "Commands applied"
+msgstr "Comandos aplicados"
+
msgid "Comment"
msgstr "Comentar"
@@ -2849,6 +3283,9 @@ msgstr "Comentar y dejar la discusión sin resolver"
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr "El comentario está siendo actualizado"
+
msgid "Comments"
msgstr "Comentarios"
@@ -2876,7 +3313,7 @@ msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
msgstr "Estadísticas de los commits para %{ref} %{start_time} - %{end_time}"
msgid "Commit to %{branchName} branch"
-msgstr ""
+msgstr "Commit en la rama %{branchName}"
msgid "CommitBoxTitle|Commit"
msgstr "Cambio"
@@ -2885,7 +3322,7 @@ msgid "CommitMessage|Add %{file_name}"
msgstr "Agregar %{file_name}"
msgid "CommitWidget|authored"
-msgstr ""
+msgstr "autorizado"
msgid "Commits"
msgstr "Cambios"
@@ -2894,10 +3331,10 @@ msgid "Commits feed"
msgstr "Feed de cambios"
msgid "Commits per day hour (UTC)"
-msgstr ""
+msgstr "Commits por hora (UTC)"
msgid "Commits per day of month"
-msgstr ""
+msgstr "Commits por día del mes"
msgid "Commits per weekday"
msgstr "Commits por dia de la semana"
@@ -2912,7 +3349,7 @@ msgid "Commits|History"
msgstr "Historial"
msgid "Commits|No related merge requests found"
-msgstr ""
+msgstr "No se encontraron merge requests relacionados"
msgid "Committed by"
msgstr "Enviado por"
@@ -2921,7 +3358,7 @@ msgid "Commit…"
msgstr "Commit..."
msgid "Company"
-msgstr ""
+msgstr "Empresa"
msgid "Compare"
msgstr "Comparar"
@@ -2963,28 +3400,31 @@ msgid "Confidentiality"
msgstr "Confidencialidad"
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
-msgstr ""
+msgstr "Configure los ejecutores de GitLab para comenzar a usar el terminal web. %{helpStart}Aprenda más.%{helpEnd}"
msgid "Configure Gitaly timeouts."
msgstr "Configurar los tiempos de espera de Gitaly."
+msgid "Configure Let's Encrypt"
+msgstr "Configurar Let's Encrypt"
+
msgid "Configure Tracing"
-msgstr ""
+msgstr "Configurar seguimiento"
msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
-msgstr ""
+msgstr "Configure un archivo <code>.gitlab-webide.yml</code> en el directorio <code>.gitlab</code> para comenzar a utilizar el Terminal Web. %{helpStart}Aprende más.%{helpEnd}"
msgid "Configure automatic git checks and housekeeping on repositories."
-msgstr ""
+msgstr "Configurar las comprobaciones automáticas de Git y el mantenimiento en los repositorios."
msgid "Configure limits for web and API requests."
-msgstr ""
+msgstr "Configurar los límites para las peticiones web y las peticiones API."
msgid "Configure push mirrors."
-msgstr ""
+msgstr "Configurar las replicas para push."
msgid "Configure storage path settings."
-msgstr ""
+msgstr "Configure los ajustes de la ruta de almacenamiento."
msgid "Configure the %{link} integration."
msgstr "Configurar la %{link} integración."
@@ -2993,10 +3433,16 @@ msgid "Configure the way a user creates a new account."
msgstr "Configure la forma en la que un usuario crea una cuenta nueva."
msgid "Confirm"
+msgstr "Confirmar"
+
+msgid "Confirmation email sent to %{email}"
msgstr ""
msgid "Confirmation required"
-msgstr ""
+msgstr "Se requiere confirmación"
+
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr "¡Enhorabuena ha habilitado la autenticación de dos factores!"
msgid "Connect"
msgstr "Conectar"
@@ -3010,38 +3456,44 @@ msgstr "Conectar los repositorios desde GitHub"
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr "Conecte sus repositorios externos, y los pipelines de CI/CD se ejecutarán para los nuevos commits. Se creará un proyecto de Gitlab sólo con las caracteristicas de CI/CD habilitadas."
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr "Conectando..."
+msgid "Connection failure"
+msgstr "Error de conexión"
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
-msgstr ""
+msgstr "Póngase en contacto con el propietario del grupo %{namespace_name} para actualizar el plan."
msgid "Contact owner %{link_start}%{owner_name}%{link_end} to upgrade the plan."
-msgstr ""
+msgstr "Póngase en contacto con el propietario %{link_start}%{owner_name}%{link_end} para actualizar el plan."
msgid "Contact sales to upgrade"
-msgstr ""
+msgstr "Póngase en contacto con ventas para actualizar"
msgid "Contact your Administrator to upgrade your license."
-msgstr ""
+msgstr "Póngase en contacto con el administrador para actualizar su licencia."
msgid "Container Registry"
msgstr "Registro de contenedores"
msgid "Container registry images"
-msgstr ""
+msgstr "Imágenes del registro de contenedores"
msgid "ContainerRegistry|Created"
msgstr "Creado"
msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
-msgstr ""
+msgstr "Inicie sesión por primera vez en el Container Registry de GitLab&rsquo; utilizando su usuario y su contraseña. Si tiene %{link_2fa} necesita utilizar un %{link_token}:"
msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
msgstr "Gitlab soporta hasta 3 niveles para nombres de imágenes. Los siguientes ejemplos de imágenes son válidos para tu proyecto:"
msgid "ContainerRegistry|How to use the Container Registry"
-msgstr ""
+msgstr "Cómo utilizar el registro de contenedores"
msgid "ContainerRegistry|Learn more about"
msgstr "Conozca más sobre"
@@ -3068,13 +3520,16 @@ msgid "ContainerRegistry|Tag ID"
msgstr "Etiqueta ID"
msgid "ContainerRegistry|Use different image names"
-msgstr "Usar nombres de imagen diferentes"
+msgstr "Utilizar nombres de imagen diferentes"
msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
-msgstr ""
+msgstr "Con el registro de contenedores de Docker integrado en GitLab, cada proyecto puede tener su propio espacio para almacenar sus imágenes de Docker."
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
-msgstr ""
+msgstr "También puede utilizar un %{deploy_token} para acceder en modo de solo lectura al registro de imágenes."
+
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr "Contiene %{count} archivos de imágenes de tipo blob con un tamaño de (%{size})"
msgid "Contents of .gitlab-ci.yml"
msgstr "Contenido de .gitlab-ci.yml"
@@ -3098,7 +3553,7 @@ msgid "Contribution Analytics"
msgstr "Análisis de contribución"
msgid "Contribution Charts"
-msgstr ""
+msgstr "Gráficos de contribución"
msgid "Contributions for <strong>%{calendar_date}</strong>"
msgstr "Contribuciones para <strong>%{calendar_date}</strong>"
@@ -3121,36 +3576,39 @@ msgstr "Commits a %{branch_name}, excluyendo merge commits. Limitado a 6,000 com
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr "Espere un momento; esta página se actualizará automáticamente cuando esté lista."
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr "Controlar la visualización de las ofertas de terceros."
msgid "Control the maximum concurrency of repository backfill for this secondary node"
-msgstr ""
+msgstr "Controla la concurrencia máxima para el backfill del repositorio para este nodo secundario"
msgid "ConvDev Index"
msgstr "Ãndice ConvDev"
+msgid "Copied"
+msgstr "Copiado"
+
msgid "Copy %{http_label} clone URL"
-msgstr ""
+msgstr "Copiar la URL %{http_label} de clonado"
msgid "Copy %{protocol} clone URL"
-msgstr ""
+msgstr "Copiar la URL de clonado del protocolo %{protocol}"
msgid "Copy ID to clipboard"
msgstr "Copiar el ID a portapapeles"
msgid "Copy KRB5 clone URL"
-msgstr ""
+msgstr "Copiar la URL de clonado KRB5"
msgid "Copy SSH clone URL"
-msgstr ""
+msgstr "Copiar la URL de clonado SSH"
msgid "Copy SSH public key"
msgstr "Copiar la clave pública SSH"
-msgid "Copy SSH public key to clipboard"
-msgstr "Copiar la clave pública SSH al portapapeles"
-
msgid "Copy URL to clipboard"
msgstr "Copiar URL al portapapeles"
@@ -3166,6 +3624,12 @@ msgstr "Copiar SHA del cambio al portapapeles"
msgid "Copy file path to clipboard"
msgstr "Copie la ruta del archivo al portapapeles"
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr "Copiar las etiquetas y el hito desde %{source_issuable_reference}."
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr "Copiar las etiquetas y los hitos desde otras incidencias ó merge request en este proyecto"
+
msgid "Copy link"
msgstr "Copiar enlace"
@@ -3175,6 +3639,9 @@ msgstr "Copiar la referencia al portapapeles"
msgid "Copy secret to clipboard"
msgstr "Copia secreto al portapapeles"
+msgid "Copy source to clipboard"
+msgstr "Copia la fuente al portapapeles"
+
msgid "Copy to clipboard"
msgstr "Copiar al portapapeles"
@@ -3182,31 +3649,37 @@ msgid "Copy token to clipboard"
msgstr "Copiar token al portapapeles"
msgid "Could not authorize chat nickname. Try again!"
-msgstr ""
+msgstr "No se puede autorizar el nick del chat. Por favor, inténtelo de nuevo"
+
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr "No se pudo cambiar HEAD: el branch '%{branch}' no existe"
msgid "Could not connect to FogBugz, check your URL"
+msgstr "No se puede conectar a FogBugz, por favor, compruebe su URL"
+
+msgid "Could not connect to Web IDE file mirror service."
msgstr ""
msgid "Could not create Wiki Repository at this time. Please try again later."
-msgstr ""
+msgstr "No es posible crear la Wiki del repositorio en este momento. Por favor, inténtelo de nuevo más tarde."
msgid "Could not delete chat nickname %{chat_name}."
-msgstr ""
+msgstr "No es posible eliminar el apodo del chate %{chat_name}."
msgid "Could not remove the trigger."
-msgstr ""
+msgstr "No es posible eliminar el disparador."
msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
-msgstr ""
+msgstr "No es posible recuperar el estado del pipeline. Para obtener información, sobre los pasos a seguir para la solución de problemas, lea la documentación %{linkStart}.%{linkEnd}"
msgid "Could not revoke impersonation token %{token_name}."
-msgstr ""
+msgstr "No se puede revocar el token de suplantación %{token_name}."
msgid "Could not revoke personal access token %{personal_access_token_name}."
-msgstr ""
+msgstr "No se pudo revocar el token de acceso personal %{personal_access_token_name}."
msgid "Coverage"
-msgstr ""
+msgstr "Cobertura"
msgid "Create"
msgstr "Crear"
@@ -3218,11 +3691,20 @@ msgid "Create New Domain"
msgstr "Crear un nuevo dominio"
msgid "Create a GitLab account first, and then connect it to your %{label} account."
-msgstr ""
+msgstr "Cree primero una cuenta de GitLab y luego conéctela a su cuenta %{label}."
+
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr "Cree un proxy local para almacenar las imágenes usadas frecuentemente con anterioridad. %{link_start}Obtenga más%{link_end} información sobre los proxies de dependencias."
+
+msgid "Create a merge request."
+msgstr "Crear un merge request."
msgid "Create a new branch"
msgstr "Crear un nuevo 'branch'"
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr "Cree un nuevo archivo ya todavía no hay archivos. Posteriormente, podrá confirmar los cambios con sus commits."
+
msgid "Create a new issue"
msgstr "Crear una nueva incidencia"
@@ -3233,7 +3715,7 @@ msgid "Create a personal access token on your account to pull or push via %{prot
msgstr "Crear un token de acceso personal en tu cuenta para actualizar o enviar a través de %{protocol}."
msgid "Create an issue. Issues are created for each alert triggered."
-msgstr ""
+msgstr "Crear una incidencia. Se crearán incidencias para cada alerta activada."
msgid "Create branch"
msgstr "Crear rama"
@@ -3260,13 +3742,13 @@ msgid "Create group label"
msgstr "Crear etiqueta de grupo"
msgid "Create lists from labels. Issues with that label appear in that list."
-msgstr ""
+msgstr "Crear listas desde las etiquetas. Las incidencias que contengan esa etiqueta aparecerán en esa lista."
msgid "Create merge request"
msgstr "Crear solicitud de fusión"
msgid "Create merge request and branch"
-msgstr ""
+msgstr "Crear un merge request y un branch"
msgid "Create milestone"
msgstr "Crear hito"
@@ -3281,7 +3763,7 @@ msgid "Create new file"
msgstr "Crear nuevo archivo"
msgid "Create new file or directory"
-msgstr ""
+msgstr "Crear un nuevo archivo o directorio"
msgid "Create new label"
msgstr "Crear nueva etiqueta"
@@ -3295,6 +3777,12 @@ msgstr "Crear etiqueta de proyecto"
msgid "Create your first page"
msgstr "Crea tu primera página"
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr "No tiene permiso para crear un subgrupo en este grupo."
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr "No tiene permisos para crear grupos."
+
msgid "CreateTag|Tag"
msgstr "Etiqueta"
@@ -3310,12 +3798,27 @@ msgstr "Creado en"
msgid "Created by me"
msgstr "Creado por mí"
+msgid "Created issue %{issueLink}"
+msgstr "Incidencia creada %{issueLink}"
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr "Incidencia creada %{issueLink} en %{projectLink}"
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr "Creado el merge request %{mergeRequestLink}"
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr "Creado el merge request %{mergeRequestLink} en %{projectLink}"
+
msgid "Created on"
msgstr "Creado en"
msgid "Created on:"
msgstr "Creado sobre:"
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr "Crea una rama %{branch_name} y un merge request para resolver esta incidencia"
+
msgid "Creating epic"
msgstr "Creando épica"
@@ -3326,14 +3829,17 @@ msgid "Cron syntax"
msgstr "Sintaxis de Cron"
msgid "Current Branch"
-msgstr ""
+msgstr "Rama actual"
msgid "Current Project"
-msgstr ""
+msgstr "Proyecto actual"
msgid "Current node"
msgstr "Nodo actual"
+msgid "Current password"
+msgstr "Contraseña actual"
+
msgid "CurrentUser|Profile"
msgstr "Perfil"
@@ -3341,10 +3847,10 @@ msgid "CurrentUser|Settings"
msgstr "Configuración"
msgid "Custom CI config path"
-msgstr ""
+msgstr "Ruta de configuración de CI personalizada"
msgid "Custom hostname (for private commit emails)"
-msgstr ""
+msgstr "Nombre de host personalizado (para los correos electrónicos privados de los commit)"
msgid "Custom notification events"
msgstr "Eventos de notificaciones personalizadas"
@@ -3353,31 +3859,31 @@ msgid "Custom notification levels are the same as participating levels. With cus
msgstr "Los niveles de notificación personalizados son los mismos que los niveles participantes. Con los niveles de notificación personalizados, también recibirá notificaciones para eventos seleccionados. Para obtener más información, consulte %{notification_link}."
msgid "Custom project templates"
-msgstr ""
+msgstr "Plantillas de proyectos personalizadas"
msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
-msgstr ""
+msgstr "No se han configurado plantillas de proyecto personalizadas para grupos de los que es miembro. Las plantillas se habilitan desde la página de configuración de un grupo. Póngase en contacto con el propietario o el encargado de su grupo para configurar las plantillas de proyecto personalizadas."
msgid "Customize colors"
msgstr "Personalizar colores"
msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
-msgstr ""
+msgstr "Personalice cómo las direcciones de correo electrónico y los nombres de usuario de FogBugz se importan en GitLab. En el siguiente paso, podrá seleccionar los proyectos que desea importar."
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
-msgstr ""
+msgstr "Personalice cómo las direcciones de correo electrónico y los nombres de usuario de FogBugz se importan en GitLab. En el siguiente paso, podrá seleccionar los proyectos que desea importar."
msgid "Customize language and region related settings."
-msgstr ""
+msgstr "Personalice los ajustes relacionados con el idioma y la región."
msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
-msgstr ""
+msgstr "Personalice la configuración de su pipeline, vea el estado de su pipeline y el informe de cobertura."
msgid "Cycle Analytics"
-msgstr ""
+msgstr "Cycle Analytics"
msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
-msgstr ""
+msgstr "Cycle Analytics proporciona una visión general del tiempo que se tarda en pasar una idea a producción, en su proyecto."
msgid "CycleAnalyticsStage|Code"
msgstr "Código"
@@ -3412,8 +3918,20 @@ msgstr "Todos"
msgid "DashboardProjects|Personal"
msgstr "Personales"
+msgid "DashboardProjects|Trending"
+msgstr "Tendencias"
+
msgid "Dashboards"
-msgstr ""
+msgstr "Paneles de control"
+
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr "%{firstProject} y %{secondProject}"
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr "%{firstProject}, %{rest}, y %{secondProject}"
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr "No se puede agregar %{invalidProjects}. Este panel de control está disponible para proyectos públicos y proyectos privados en grupos con un plan Gold."
msgid "Data is still calculating..."
msgstr "Los datos aún se están calculando..."
@@ -3421,6 +3939,18 @@ msgstr "Los datos aún se están calculando..."
msgid "Date picker"
msgstr "Selector de fecha"
+msgid "DayTitle|F"
+msgstr "V"
+
+msgid "DayTitle|M"
+msgstr "L"
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr "Mi"
+
msgid "Debug"
msgstr "Depurar"
@@ -3440,46 +3970,49 @@ msgid "Default Branch"
msgstr "Branch por defecto"
msgid "Default artifacts expiration"
-msgstr ""
+msgstr "Vencimiento predeterminado para los artefactos"
msgid "Default classification label"
msgstr "Etiqueta de clasificación por defecto"
msgid "Default description template for issues"
-msgstr ""
+msgstr "Plantilla de descripción predeterminada para las incidencias"
msgid "Default first day of the week"
-msgstr ""
+msgstr "Primer día de la semana por defecto"
msgid "Default first day of the week in calendars and date pickers."
-msgstr ""
+msgstr "Primer día de la semana por defecto en calendarios y selectores de fechas."
msgid "Default issue template"
+msgstr "Plantilla de incidencia por defecto"
+
+msgid "Default project deletion protection"
msgstr ""
msgid "Default: Directly import the Google Code email address or username"
msgstr "Por defecto: Importar directamente el nombre de usuario o la dirección de correo electrónico de Google Code"
msgid "Default: Map a FogBugz account ID to a full name"
-msgstr ""
+msgstr "Por defecto: Asignar un ID de cuenta de FogBugz a un nombre completo"
msgid "Define a custom pattern with cron syntax"
msgstr "Definir un patrón personalizado con la sintaxis de cron"
msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
-msgstr ""
+msgstr "Defina entornos en las distintas etapas de despliegue en el fichero <code>.gitlab-ci.yml</code> para llevar un registro de las implementaciones desde aquí."
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
-msgstr ""
+msgstr "¿Está seguro de que quiere ejecutar %{jobName} inmediatamente? De lo contrario, este trabajo se ejecutará automáticamente una vez que finalice el temporizador."
msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
-msgstr ""
+msgstr "¿Está seguro de que quiere ejecutar %{job_name} inmediatamente? De lo contrario, este trabajo se ejecutará automáticamente una vez que finalice el temporizador."
msgid "DelayedJobs|Start now"
msgstr "Comenzar ahora"
msgid "DelayedJobs|Unschedule"
-msgstr ""
+msgstr "Desprogramar"
msgid "DelayedJobs|delayed"
msgstr "retrasado"
@@ -3497,7 +4030,7 @@ msgid "Delete comment"
msgstr "Eliminar comentario"
msgid "Delete license"
-msgstr ""
+msgstr "Eliminar la licencia"
msgid "Delete list"
msgstr "Eliminar lista"
@@ -3508,27 +4041,90 @@ msgstr "Eliminar rama origen"
msgid "Delete this attachment"
msgstr "Eliminar este adjunto"
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr "Se ha producido un error al eliminar el repositorio del proyecto. Por favor, inténtelo de nuevo o póngase en contacto con el administrador."
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr "Se ha producido un error al eliminar algunas etiquetas en el registro de contenedores del proyecto. Por favor, inténtelo de nuevo o póngase en contacto con el administrador."
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr "Se ha producido un error al eliminar el repositorio de wiki. Por favor, inténtelo de nuevo o póngase en contacto con el administrador."
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr "Se ha producido un error al restaurar el repositorio del proyecto. Por favor, póngase en contacto con el administrador."
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr "Se ha producido un error al restaurar el repositorio de la wiki. Por favor, póngase en contacto con el administrador."
+
msgid "Deleted"
msgstr "Eliminado"
msgid "Deleted chat nickname: %{chat_name}!"
-msgstr ""
+msgstr "¡Eliminado el nick del chat %{chat_name}!"
msgid "Deleting the license failed."
-msgstr ""
+msgstr "Se ha producido un error al eliminar la licencia."
msgid "Deleting the license failed. The license was not found."
-msgstr ""
+msgstr "Se ha producido un error al eliminar la licencia. No se encontró ninguna licencia."
msgid "Deleting the license failed. You are not permitted to perform this action."
-msgstr ""
+msgstr "Se ha producido un error al eliminar la licencia. No tiene permiso para realizar esta acción."
msgid "Denied authorization of chat nickname %{user_name}."
-msgstr ""
+msgstr "Autorización denegada del nick del chat %{user_name}."
msgid "Deny"
msgstr "Denegar"
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr "Proxy de dependencias"
+
+msgid "Dependency proxy"
+msgstr "Proxy de dependencias"
+
+msgid "Dependency proxy URL"
+msgstr "URL del proxy de dependencias"
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr "La funcionalidad del proxy de dependencias está limitada, por ahora, únicamente a grupos públicos."
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr "Cambiar el proxy de dependencias"
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "Despliegue"
@@ -3538,7 +4134,7 @@ msgid "Deploy Keys"
msgstr "Claves de despliegue"
msgid "Deploy key was successfully updated."
-msgstr ""
+msgstr "La clave de despliegue se actualizó correctamente."
msgid "DeployKeys|+%{count} others"
msgstr "+%{count} otros"
@@ -3589,16 +4185,16 @@ msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
msgstr "Está a punto de eliminar esta clave de despliegue. ¿Está seguro?"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
-msgstr ""
+msgstr "Claves de despliegue activas (%{active_tokens})"
msgid "DeployTokens|Add a deploy token"
-msgstr ""
+msgstr "Añadir un token de despliegue"
msgid "DeployTokens|Allows read-only access to the registry images"
-msgstr ""
+msgstr "Permite el acceso en modo de sólo lectura al registro de imágenes"
msgid "DeployTokens|Allows read-only access to the repository"
-msgstr ""
+msgstr "Permite el acceso en modo de sólo lectura al repositorio"
msgid "DeployTokens|Copy deploy token to clipboard"
msgstr "Copiar el token de despliegue al portapapeles"
@@ -3634,7 +4230,7 @@ msgid "DeployTokens|Revoke %{name}"
msgstr "Revocar %{name}"
msgid "DeployTokens|Scopes"
-msgstr ""
+msgstr "Ãmbitos"
msgid "DeployTokens|This action cannot be undone."
msgstr "Esta acción no se puede deshacer."
@@ -3652,13 +4248,13 @@ msgid "DeployTokens|Username"
msgstr "Nombre de usuario"
msgid "DeployTokens|You are about to revoke"
-msgstr ""
+msgstr "Está a punto de revocar"
msgid "DeployTokens|Your New Deploy Token"
-msgstr ""
+msgstr "Su nuevo token de despliegue"
msgid "DeployTokens|Your new project deploy token has been created."
-msgstr ""
+msgstr "Se ha creado su nuevo token de despliegue de proyecto."
msgid "Deployed"
msgstr "Desplegado"
@@ -3670,7 +4266,7 @@ msgid "Deploying to"
msgstr "Desplegando en"
msgid "Deprioritize label"
-msgstr ""
+msgstr "Bajar la prioridad de la etiqueta"
msgid "Descending"
msgstr "Descendente"
@@ -3679,40 +4275,43 @@ msgid "Description"
msgstr "Descripción"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
-msgstr ""
+msgstr "Descripción analizada con %{link_start}GitLab Flavored Markdown%{link_end}"
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
-msgstr ""
+msgstr "Las plantillas de descripción le permiten definir plantillas relativas al contexto para incidencias y campos de descripción de las peticiones de fusión para tu proyecto."
msgid "Description:"
msgstr "Descripción:"
msgid "DesignManagement|%{current_design} of %{designs_count}"
-msgstr ""
+msgstr "%{current_design} de %{designs_count}"
msgid "DesignManagement|Could not find design, please try again."
-msgstr ""
+msgstr "Se ha producido un error al buscar el diseño, por favor, inténtelo de nuevo."
msgid "DesignManagement|Error uploading a new design. Please try again"
-msgstr ""
+msgstr "Se ha producido un error al cargar un nuevo diseño. Por favor, inténtelo de nuevo"
msgid "DesignManagement|Go back to designs"
-msgstr ""
+msgstr "Volver a los diseños"
msgid "DesignManagement|Go to next design"
-msgstr ""
+msgstr "Ir al siguiente diseño"
msgid "DesignManagement|Go to previous design"
-msgstr ""
+msgstr "Ir al diseño anterior"
+
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr "El número máximo de diseños permitidos que se pueden cargar es %{upload_limit}. Por favor, inténtalo de nuevo."
msgid "DesignManagement|The one place for your designs"
-msgstr ""
+msgstr "Un lugar para tus diseños"
msgid "DesignManagement|Upload and view the latest designs for this issue. Consistent and easy to find, so everyone is up to date."
-msgstr ""
+msgstr "Cargue y vea los últimos diseños para esta incidencia. Consistente y fácil de encontrar, para que todos estén al día."
msgid "DesignManagement|Upload designs"
-msgstr ""
+msgstr "Cargar diseños"
msgid "Designs"
msgstr "Diseños"
@@ -3727,19 +4326,19 @@ msgid "Details (default)"
msgstr "Detalles (por defecto)"
msgid "Detect host keys"
-msgstr ""
+msgstr "Detectar las claves del host"
msgid "Diff content limits"
-msgstr ""
+msgstr "Límites de contenido del diff"
msgid "Diff limits"
-msgstr ""
+msgstr "Límites del diff"
msgid "Diffs|No file name available"
-msgstr ""
+msgstr "Sin nombre de archivo disponible"
msgid "Diffs|Something went wrong while fetching diff lines."
-msgstr ""
+msgstr "Se ha producido un error mientras se obtienen las líneas del diff."
msgid "Direction"
msgstr "Dirección"
@@ -3754,14 +4353,20 @@ msgid "Disable for this project"
msgstr "Deshabilitar para este proyecto"
msgid "Disable group Runners"
-msgstr ""
+msgstr "Desactivar el grupo de ejecutores"
msgid "Disable shared Runners"
-msgstr ""
+msgstr "Deshabilitar los ejecutores compartidos"
+
+msgid "Disable two-factor authentication"
+msgstr "Desactivar la autenticación de dos factores"
msgid "Disabled"
msgstr "Deshabilitado"
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr "Las réplicas deshabilitadas solo pueden ser habilitadas por los propietarios de las instancias. Se recomienda eliminarlas."
+
msgid "Discard"
msgstr "Descartar"
@@ -3783,6 +4388,12 @@ msgstr "Descartar borrador"
msgid "Discard review"
msgstr "Descartar la revisión"
+msgid "DiscordService|Discord Notifications"
+msgstr "Notificaciones de Discord"
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr "Recibir las notificaciones de eventos en Discord"
+
msgid "Discover GitLab Geo"
msgstr "Descubra GitLab Geo"
@@ -3790,10 +4401,10 @@ msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr "Descubra proyectos, grupos y fragmentos. Comparta sus proyectos con otros"
msgid "Discuss a specific suggestion or question"
-msgstr ""
+msgstr "Discuta una sugerencia específica o una pregunta"
msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
+msgstr "Discuta una propuesta específica o una pregunta que necesita ser resuelta"
msgid "Discussion"
msgstr "Discusión"
@@ -3802,29 +4413,53 @@ msgid "Dismiss"
msgstr "Descartar"
msgid "Dismiss ConvDev introduction"
-msgstr ""
+msgstr "Ocultar el cuadro de introducción de ConvDev"
msgid "Dismiss Cycle Analytics introduction box"
-msgstr ""
+msgstr "Ocultar el cuadro de introducción de Cycle Analytics"
msgid "Dismiss Merge Request promotion"
-msgstr ""
+msgstr "Ocultar la promoción del merge request"
msgid "Dismiss trial promotion"
-msgstr ""
+msgstr "Ocultar el cuadro de introducción del periodo de prueba"
+
+msgid "Dismissed"
+msgstr "Descartado"
+
+msgid "Dismissed at %{projectLink}"
+msgstr "Ocultado en %{projectLink}"
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr "Descartado en el pipeline %{pipelineLink}"
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr "Descartado en el pipeline %{pipelineLink} en %{projectLink}"
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
-msgstr ""
+msgstr "¿Desea personalizar cómo se importan en GitLab las direcciones de correo electrónico y los nombres de usuario de Google Code?"
+
+msgid "Dockerfile"
+msgstr "Dockerfile"
msgid "Documentation for popular identity providers"
-msgstr ""
+msgstr "Documentación para los proveedores de identidad más populares"
msgid "Domain"
msgstr "Dominio"
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr "La verificación del dominio es una medida de seguridad esencial para los sitios públicos de GitLab. Los usuarios deben demostrar que administran o que son los propietarios de un dominio antes de poder habilitarlo"
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr "No mostrar de nuevo"
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr "No se preocupe, puede acceder a este visita haciendo clic sobre el ícono de ayuda situado en la esquina superior derecha y seleccionando <strong>aprender GitLab</strong>."
+
msgid "Done"
msgstr "Hecho"
@@ -3835,28 +4470,22 @@ msgid "Download artifacts"
msgstr "Descargar artefactos"
msgid "Download asset"
-msgstr ""
+msgstr "Descargar activo"
+
+msgid "Download codes"
+msgstr "Descargar codigos"
msgid "Download export"
-msgstr ""
+msgstr "Descargar exportación"
msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
-msgstr "Descargar tar"
-
-msgid "Download tar.bz2"
-msgstr "Descargar tar.bz2"
-
-msgid "Download tar.gz"
-msgstr "Descargar tar.gz"
+msgstr "Descargar licencia"
-msgid "Download zip"
-msgstr "Descargar zip"
+msgid "Download source code"
+msgstr "Descargar el código fuente"
-msgid "DownloadArtifacts|Download"
-msgstr "Descargar"
+msgid "Download this directory"
+msgstr "Descargar este directorio"
msgid "DownloadCommit|Email Patches"
msgstr "Parches por correo electrónico"
@@ -3877,7 +4506,7 @@ msgid "Due date"
msgstr "Fecha de vencimiento"
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
-msgstr ""
+msgstr "Durante este proceso, le solicitaremos las URLs de parte de Gitlab.Por favor, utilice las URLs que se muestran a continuación."
msgid "Each Runner can be in one of the following states:"
msgstr "Cada ejecutor puede estar en uno de los siguientes estados:"
@@ -3889,7 +4518,7 @@ msgid "Edit %{name}"
msgstr "Editar %{name}"
msgid "Edit Deploy Key"
-msgstr ""
+msgstr "Editar la clave de despliegue"
msgid "Edit Label"
msgstr "Editar etiqueta"
@@ -3897,6 +4526,9 @@ msgstr "Editar etiqueta"
msgid "Edit Milestone"
msgstr "Editar hito"
+msgid "Edit Password"
+msgstr "Editar la contraseña"
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "Editar Programación del Pipeline %{id}"
@@ -3933,14 +4565,20 @@ msgstr "Editar clave pública de despliegue"
msgid "Elasticsearch"
msgstr "Elasticsearch"
+msgid "Elasticsearch indexing restrictions"
+msgstr "Restricciones en la indexación de Elasticsearch"
+
+msgid "Elasticsearch indexing started"
+msgstr "Comenzó la indexación de Elasticsearch"
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr "Integración de Elastisearch. Elasticsearch AWS IAM."
msgid "Elastic|None. Select namespaces to index."
-msgstr ""
+msgstr "Ninguno. Seleccione los espacios de nombres a indexar."
msgid "Elastic|None. Select projects to index."
-msgstr ""
+msgstr "Ninguno. Seleccione los proyectos a indexar."
msgid "Email"
msgstr "Correo electrónico"
@@ -3951,33 +4589,66 @@ msgstr "Correo electrónico"
msgid "Email patch"
msgstr "Enviar parche por correo electrónico"
+msgid "Email the pipelines status to a list of recipients."
+msgstr "Envía el estado de los pipelines a una lista de destinatarios."
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
-msgstr ""
+msgstr "Parece que el correo electrónico está en blanco. Asegúrese de que su respuesta esté en la parte superior del correo electrónico, no podemos procesar las respuestas en línea."
msgid "EmailError|The thread you are replying to no longer exists, perhaps it was deleted? If you believe this is in error, contact a staff member."
-msgstr ""
+msgstr "El hilo al que intenta responder ya no existe, ¿Quizás se eliminó? Si cree que esto se debe a un error, póngase en contacto con un miembro del equipo técnico."
msgid "EmailError|We couldn't figure out what the email is for. Please create your issue or comment through the web interface."
-msgstr ""
+msgstr "No ha sido posible averiguar para qué es el correo electrónico. Por favor cree su incidencia o comentario a través de la interfaz web."
msgid "EmailError|We couldn't figure out what the email is in reply to. Please create your comment through the web interface."
-msgstr ""
+msgstr "No es posible averiguar a qué dirección responder en el correo electrónico. Por favor, cree su comentario a través de la interfaz web."
msgid "EmailError|We couldn't figure out what user corresponds to the email. Please create your comment through the web interface."
-msgstr ""
+msgstr "No es posible averiguar a qué usuario corresponde al correo electrónico. Por favor, cree su comentario a través de la interfaz web."
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
-msgstr ""
+msgstr "No es posible encontrar el proyecto. Por favor, compruebe si hay algún error tipográfico."
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
-msgstr ""
+msgstr "No se le permite realizar esta acción. Si cree que esto se debe a un error, por favor, póngase en contacto con un miembro del personal."
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
-msgstr ""
+msgstr "Su cuenta ha sido bloqueada. Si cree que esto se debe a un error, por favor, póngase en contacto con un miembro del personal."
+
+msgid "EmailToken|reset it"
+msgstr "reiniciarlo"
+
+msgid "EmailToken|resetting..."
+msgstr "reiniciando..."
msgid "Emails"
msgstr "Correos electrónicos"
+msgid "Emails separated by comma"
+msgstr "Correos electrónicos separados por comas"
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr "EmailsOnPushService | Desactivar diferencias de código"
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr "No incluya información sensible en los diferencias de código que se envían en el cuerpo de la notificación."
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr "Enviar por correo electrónico los commits y los diff de cada push a una lista de destinatarios."
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr "Emails al realizar un push"
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr "Correos electrónicos separados por espacios en blanco"
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr "Enviar desde el committer"
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr "Enviar notificaciones desde la dirección de correo electrónico del commiter si el dominio es parte del dominio en el que se está ejecutando GitLab (por ejemplo, %{domains})."
+
msgid "Embed"
msgstr "Incrustado"
@@ -4002,6 +4673,9 @@ msgstr "Habilitar autenticación SAML para este grupo"
msgid "Enable Sentry for error reporting and logging."
msgstr "Habilite Sentry para el obtener el informe de errores y el registro."
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr "Habilitar y configurar las métricas de InfluxDB."
@@ -4027,31 +4701,28 @@ msgid "Enable mirror configuration"
msgstr "Habilitar configuración de espejo"
msgid "Enable or disable the Pseudonymizer data collection."
-msgstr ""
+msgstr "Habilitar o deshabilitar la recolección de datos con Pseudonymizer."
msgid "Enable or disable version check and usage ping."
-msgstr ""
+msgstr "Habilite o deshabilite la comprobación de versión y el ping de uso."
msgid "Enable reCAPTCHA or Akismet and set IP limits."
-msgstr ""
+msgstr "Habilite reCAPTCHA o Akismet y establezca límites IP."
msgid "Enable shared Runners"
-msgstr ""
-
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
+msgstr "Habilitar ejecutores compartidos"
msgid "Enable two-factor authentication"
-msgstr ""
+msgstr "Habilitar la autenticación de dos factores"
msgid "Enable usage ping"
-msgstr ""
+msgstr "Habilitar ping de uso"
msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
msgstr ""
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
+msgstr "Habilitar/Deshabilitar su Service Desk. %{link_start} Obtenga más información sobre Service Desk en el siguiente enlace %{link_end}."
msgid "Enabled"
msgstr "Habilitado"
@@ -4063,37 +4734,46 @@ msgid "Enabled sources for code import during project creation. OmniAuth must be
msgstr ""
msgid "Enabling this will only make licensed EE features available to projects if the project namespace's plan includes the feature or if the project is public."
-msgstr ""
+msgstr "Habilitar esta opción solo hará que las funciones con licencia EE estén disponibles para los proyectos si el plan del espacio de nombres del proyecto incluye esta opción o si el proyecto es público."
msgid "End date"
-msgstr ""
+msgstr "Fecha de finalización"
msgid "Ends at (UTC)"
msgstr "Finaliza a las (UTC)"
+msgid "Enforce DNS rebinding attack protection"
+msgstr "Reforzar la protección de ataques a DNS"
+
msgid "Enter at least three characters to search"
-msgstr ""
+msgstr "Introduzca al menos tres caracteres para buscar"
msgid "Enter in your Bitbucket Server URL and personal access token below"
-msgstr ""
+msgstr "Introduzca a continuación, la URL de su servidor de Bitbucket y su token de acceso personal"
+
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr "Introduzca la URL de su servidor Phabricator y su token de acceso"
msgid "Enter the issue description"
-msgstr ""
+msgstr "Introduzca la descripción de la incidencia"
msgid "Enter the issue title"
-msgstr ""
+msgstr "Introduzca el título de la incidencia"
msgid "Enter the merge request description"
-msgstr ""
+msgstr "Introduzca la descripción del merge request"
msgid "Enter the merge request title"
-msgstr ""
+msgstr "Introduzca el título del merge request"
+
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr "Está viendo el último entorno actualizado"
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
-msgstr ""
+msgstr "Las variables de entorno están configuradas por el administrador para estar %{link_start}protegidas%{link_end} por defecto"
msgid "Environment:"
msgstr "Entorno:"
@@ -4101,8 +4781,32 @@ msgstr "Entorno:"
msgid "Environments"
msgstr "Entornos"
+msgid "Environments Dashboard"
+msgstr "Panel de control de entornos"
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
-msgstr ""
+msgstr "Los Entornos le permiten hacer un seguimiento de los despliegues de su aplicación %{link_to_read_more}."
+
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr "Añadir un proyecto al panel"
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr "Añadir proyectos"
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr "Panel de control de entornos"
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr "Trabajo: %{job}"
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr "Más acciones"
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr "Eliminar"
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr "El panel de control de entornos proporciona un resumen detallado del estado de los entornos de cada proyecto, incluidos los estados de alerta y de los pipelines."
msgid "Environments|An error occurred while fetching the environments."
msgstr "Se ha producido un error al recuperar los entornos."
@@ -4111,10 +4815,10 @@ msgid "Environments|An error occurred while making the request."
msgstr "Se ha producido un error al realizar la solicitud."
msgid "Environments|An error occurred while re-deploying the environment, please try again"
-msgstr ""
+msgstr "Se ha producido un error mientras se volvía desplegar el entorno, por favor, inténtelo de nuevo"
msgid "Environments|An error occurred while rolling back the environment, please try again"
-msgstr ""
+msgstr "Se ha producido un error mientras se volvía a desplegar el entorno, por favor, inténtelo de nuevo"
msgid "Environments|An error occurred while stopping the environment, please try again"
msgstr "Ocurrió un error al detener el entorno, por favor inténtelo de nuevo"
@@ -4138,13 +4842,13 @@ msgid "Environments|Environments"
msgstr "Entornos"
msgid "Environments|Environments are places where code gets deployed, such as staging or production."
-msgstr ""
+msgstr "Los entornos son lugares en los que se despliega el código, como por ejemplo, los entornos de test o los entornos de producción."
msgid "Environments|Job"
msgstr "Trabajo"
msgid "Environments|Learn more about stopping environments"
-msgstr ""
+msgstr "Obtenga más información sobre cómo detener los entornos"
msgid "Environments|New environment"
msgstr "Nuevo entorno"
@@ -4153,13 +4857,13 @@ msgid "Environments|No deployments yet"
msgstr "Todavía no hay despliegues"
msgid "Environments|No pod name has been specified"
-msgstr ""
+msgstr "No se ha especificado ningún nombre de pod"
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
-msgstr ""
+msgstr "Note que esta acción detendrá el entorno, pero %{emphasisStart}no%{emphasisEnd} tendrá ningún efecto sobre cualquier instancia debido a que no hay una \"acción para detener el entorno\" definida en el archivo %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd}."
msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
-msgstr ""
+msgstr "Tenga en cuenta que esta acción detendrá el entorno, pero %{emphasis_start}no%{emphasis_end} trendrá efecto en ningún despliegue existente debido a que no hay \"acción de detener entorno\" definida en el archivo %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end}."
msgid "Environments|Open live environment"
msgstr ""
@@ -4168,13 +4872,13 @@ msgid "Environments|Pod logs from"
msgstr ""
msgid "Environments|Re-deploy"
-msgstr ""
+msgstr "Re-desplegar"
msgid "Environments|Re-deploy environment %{environment_name}?"
-msgstr ""
+msgstr "¿Desea redesplegar el entorno %{environment_name}?"
msgid "Environments|Re-deploy environment %{name}?"
-msgstr ""
+msgstr "¿Desea redesplegar el entorno %{name}?"
msgid "Environments|Re-deploy to environment"
msgstr "Re-desplegar al entorno"
@@ -4183,16 +4887,16 @@ msgid "Environments|Read more about environments"
msgstr "Obtenga más información sobre los entornos"
msgid "Environments|Rollback"
-msgstr ""
+msgstr "Restaurar"
msgid "Environments|Rollback environment"
msgstr "Deshacer entorno"
msgid "Environments|Rollback environment %{environment_name}?"
-msgstr ""
+msgstr "¿Desea restaurar el entorno %{environment_name}?"
msgid "Environments|Rollback environment %{name}?"
-msgstr ""
+msgstr "¿Desea restaurar el entorno %{name}?"
msgid "Environments|Show all"
msgstr "Mostrar todo"
@@ -4204,16 +4908,16 @@ msgid "Environments|Stop environment"
msgstr "Detener entorno"
msgid "Environments|Stopping"
-msgstr ""
+msgstr "Deteniendo"
msgid "Environments|This action will relaunch the job for commit %{commit_id}, putting the environment in a previous version. Are you sure you want to continue?"
-msgstr ""
+msgstr "Esta acción volverá a ejecutar el trabajo para el commit %{commit_id}, cambiando el entorno a una versión anterior. ¿Está seguro de que desea continuar?"
msgid "Environments|This action will relaunch the job for commit %{linkStart}%{commitId}%{linkEnd}, putting the environment in a previous version. Are you sure you want to continue?"
-msgstr ""
+msgstr "Esta acción volverá a ejecutar el trabajo para el commit %{linkStart}%{commitId}%{linkEnd}, cambiando el entorno a una versión anterior. ¿Está seguro de que desea continuar?"
msgid "Environments|This action will run the job defined by %{name} for commit %{linkStart}%{commitId}%{linkEnd} putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?"
-msgstr ""
+msgstr "Esta acción ejecutará el trabajo definido por %{name} para el commit %{linkStart}%{commitId}%{linkEnd}, estableciendo el entorno a una versión anterior. Puede dejar el entorno en la última versión de su aplicación volviendo a desplegarlo. ¿Está seguro de que desea continuar?"
msgid "Environments|This action will run the job defined by staging for commit %{commit_id}, putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?"
msgstr ""
@@ -4222,7 +4926,7 @@ msgid "Environments|Updated"
msgstr "Actualizado"
msgid "Environments|You don't have any environments right now"
-msgstr ""
+msgstr "No tiene ningún entorno ahora mismo"
msgid "Environments|protected"
msgstr "protegido"
@@ -4239,7 +4943,25 @@ msgstr "Hoja de ruta de tareas épicas"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr "Las tareas épicas le permiten administrar sus proyectos de manera más eficiente y con menos esfuerzo"
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
+msgstr "Se ha producido un error mientras se guardaba la fecha tipo %{epicDateType}"
+
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
msgstr ""
msgid "Epics|How can I solve this?"
@@ -4248,14 +4970,29 @@ msgstr "¿Cómo puedo resolver esto?"
msgid "Epics|More information"
msgstr "Más información"
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
+msgstr "Estas fechas afectan en como aparecen sus épicas en la hoja de ruta. Las fechas de los hitos provienen de los hitos asignados a las incidencias en su épica. También puede establecer fechas fijas o eliminarlas por completo."
+
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
-msgstr ""
+msgstr "Para programar la fecha %{epicDateType} de su épica basada en hitos, asigne un hito con una fecha %{epicDateType} a cualquier incidencia de la épica."
msgid "Epics|due"
-msgstr ""
+msgstr "vencimiento"
msgid "Epics|start"
msgstr "Inicio"
@@ -4267,7 +5004,7 @@ msgid "Error Reporting and Logging"
msgstr "Informe y registro de errores"
msgid "Error Tracking"
-msgstr ""
+msgstr "Control de errores"
msgid "Error creating a new path"
msgstr "Se ha producido un error al crear una nueva ruta"
@@ -4287,9 +5024,15 @@ msgstr "Se ha producido un error en la recuperación de las etiquetas."
msgid "Error fetching network graph."
msgstr "Se ha producido un error al obtener el gráfico de la red."
+msgid "Error fetching projects"
+msgstr "Se ha producido un error al obtener los proyectos"
+
msgid "Error fetching refs"
msgstr "Se ha producido un error al obtener los refs"
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr "Se ha producido un error al obtener los datos de uso de ping."
@@ -4299,6 +5042,12 @@ msgstr "Se ha producido un error al cargar los datos de la rama. Por favor, vuel
msgid "Error loading branches."
msgstr "Error al cargar ramas."
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr "Se ha producido un error al cargar el visor de archivos."
+
msgid "Error loading last commit."
msgstr "Error al cargar el último commit."
@@ -4308,6 +5057,9 @@ msgstr "Se ha producido un error al cargar la vista previa de Markdown"
msgid "Error loading merge requests."
msgstr "Se ha producido un error al cargar los merge requests."
+msgid "Error loading milestone tab"
+msgstr "Se ha producido un error al cargar la pestaña Hitos"
+
msgid "Error loading project data. Please try again."
msgstr "Se ha producido un error al cargar los datos del proyecto. Por favor, vuelva a intentarlo."
@@ -4317,20 +5069,26 @@ msgstr "Se ha producido un error al cargar tipos de plantilla."
msgid "Error loading template."
msgstr "Se ha producido un error al cargar la plantilla."
+msgid "Error loading viewer"
+msgstr "Se ha producido un error al cargar el visor"
+
+msgid "Error occurred when fetching sidebar data"
+msgstr "Se ha producido un error al obtener los datos de la barra lateral"
+
msgid "Error occurred when toggling the notification subscription"
msgstr "Se ha producido un error al activar/desactivar la suscripción de las notificaciones"
msgid "Error occurred. User was not blocked"
-msgstr ""
+msgstr "Se ha producido un error. No se ha bloqueado el usuario"
msgid "Error occurred. User was not confirmed"
-msgstr ""
+msgstr "Se ha producido un error. No se ha confirmado el usuario"
msgid "Error occurred. User was not unblocked"
-msgstr ""
+msgstr "Se ha producido un error. El usuario no estaba desbloqueado"
msgid "Error occurred. User was not unlocked"
-msgstr ""
+msgstr "Se ha producido un error. El usuario no estaba desbloqueado"
msgid "Error rendering markdown preview"
msgstr "Se ha producido un error al renderizar la vista previa de markdown"
@@ -4348,16 +5106,22 @@ msgid "Error updating todo status."
msgstr "Se ha producido un error al actualizar el estado de las tareas pendientes."
msgid "Error uploading file"
-msgstr ""
+msgstr "Se ha producido un error al enviar el fichero"
+
+msgid "Error uploading file: %{stripped}"
+msgstr "Se ha producido un error al subir el archivo: %{stripped}"
msgid "Error while loading the merge request. Please try again."
msgstr "Se ha producido un error al procesar su merge request. Por favor, inténtelo de nuevo."
+msgid "Error while loading the project data. Please try again."
+msgstr "Error al cargar los datos del proyecto. Por favor, vuelva a intentarlo."
+
msgid "Error while migrating %{upload_id}: %{error_message}"
-msgstr ""
+msgstr "Se ha producido un error al migrar %{upload_id}: %{error_message}"
msgid "Error with Akismet. Please check the logs for more info."
-msgstr ""
+msgstr "Error con Akismet. Por favor, compruebe los registros de error para obtener más información."
msgid "Error:"
msgstr "Error:"
@@ -4366,19 +5130,19 @@ msgid "ErrorTracking|Active"
msgstr "Activo"
msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
-msgstr ""
+msgstr "Después de añadir su token de autenticación, utilice el botón 'Conectar' para cargar los proyectos"
msgid "ErrorTracking|Auth Token"
msgstr "Token de autenticación"
msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
-msgstr ""
+msgstr "Haga clic en 'Conectar' para restablecer la conexión a Sentry y activar el menú desplegable."
msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
-msgstr ""
+msgstr "La conexión ha fallado. Por favor, compruebe el token de autenticación y vuelva a intentarlo."
msgid "ErrorTracking|Find your hostname in your Sentry account settings page"
-msgstr ""
+msgstr "Encuentre su nombre del host en la página de configuración de su cuenta de Sentry"
msgid "ErrorTracking|No projects available"
msgstr "No hay proyectos disponibles"
@@ -4387,7 +5151,7 @@ msgid "ErrorTracking|Select project"
msgstr "Seleccionar proyecto"
msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
-msgstr ""
+msgstr "Para habilitar la selección del proyecto, ingrese un token de autenticación válido"
msgid "Errors"
msgstr "Errores"
@@ -4417,7 +5181,7 @@ msgid "Events"
msgstr "Eventos"
msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
-msgstr ""
+msgstr "Cada intento de %{action} ha fallado: %{job_error_message}. Por favor, inténtalo de nuevo."
msgid "Every day (at 4:00am)"
msgstr "Todos los días (a las 4:00 am)"
@@ -4435,22 +5199,25 @@ msgid "Everyone can contribute"
msgstr "Todo el mundo puede colaborar"
msgid "Everything you need to create a GitLab Pages site using GitBook."
-msgstr ""
+msgstr "Todo lo que necesita para crear un sitio de GitLab Pages con GitBook."
msgid "Everything you need to create a GitLab Pages site using Hexo."
-msgstr ""
+msgstr "Todo lo que necesita para crear un sitio de GitLab Pages utilizando Hexo."
msgid "Everything you need to create a GitLab Pages site using Hugo."
-msgstr ""
+msgstr "Todo lo que necesitas para crear un sitio de GitLab Pages con Hugo."
msgid "Everything you need to create a GitLab Pages site using Jekyll."
-msgstr ""
+msgstr "Todo lo que necesita para crear un sitio de GitLab Pages con Jekyll."
msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr "Todo lo que necesita para crear un sitio de GitLab Pages utilizando HTML plano."
+
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
msgid "Except policy:"
-msgstr ""
+msgstr "Extracto de la política:"
msgid "Existing members and groups"
msgstr "Miembros y grupos existentes"
@@ -4462,7 +5229,7 @@ msgid "Expand all"
msgstr "Expandir todo"
msgid "Expand approvers"
-msgstr ""
+msgstr "Expandir aprobadores"
msgid "Expand sidebar"
msgstr "Expandir barra lateral"
@@ -4507,13 +5274,13 @@ msgid "Export issues"
msgstr "Exportar incidencias"
msgid "Export project"
-msgstr ""
+msgstr "Exportar proyecto"
msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
-msgstr ""
+msgstr "Exporte este proyecto con todos los datos relacionados para mover su proyecto a una nueva instancia de GitLab. Una vez que finalice la exportación, puede importar el archivo desde la página \"Nuevo proyecto\"."
msgid "External Classification Policy Authorization"
-msgstr ""
+msgstr "Política de autorización de clasificación externa"
msgid "External URL"
msgstr "URL externa"
@@ -4525,10 +5292,10 @@ msgid "External authentication"
msgstr "Autenticación externa"
msgid "External authorization denied access to this project"
-msgstr ""
+msgstr "Se ha denegado la autorización externa para el acceso a este proyecto"
msgid "External authorization request timeout"
-msgstr ""
+msgstr "Tiempo de espera agotado para la solicitud de acceso"
msgid "ExternalAuthorizationService|Classification label"
msgstr "Etiqueta de clasificación"
@@ -4536,6 +5303,27 @@ msgstr "Etiqueta de clasificación"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "Cuando no existe ninguna etiqueta de clasificación se utilizará la etiqueta predeterminada `%{default_label}'."
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr "Agregue un botón al panel de control de métricas que se enlaza directamente con sus paneles de control externos existentes."
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr "Introduzca la URL del panel de control que desea enlazar"
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr "Panel de control externo"
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr "URL completa del panel del control"
+
+msgid "ExternalWikiService|External Wiki"
+msgstr "Wiki externo"
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr "Reemplaza el enlace a la Wiki interna con un enlace a una Wiki externa."
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr "URL del Wiki externo"
+
msgid "Facebook"
msgstr "Facebook"
@@ -4545,26 +5333,59 @@ msgstr "Fallido"
msgid "Failed Jobs"
msgstr "Trabajos fallidos"
+msgid "Failed create wiki"
+msgstr "Se ha producido un error al crear el wiki"
+
msgid "Failed to change the owner"
msgstr "Error al cambiar el propietario"
msgid "Failed to check related branches."
msgstr "Se ha producido un error al verificar las branchs relacionadas."
+msgid "Failed to connect to the prometheus server"
+msgstr "Se ha producido un error al conectar con el servidor"
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr "No es posible realizar el merge request. Por favor, inténtelo de nuevo."
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr "Se ha producido un erro al crear una rama para esta incidencia. Por favor, inténtalo de nuevo."
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr "Se ha producido un error al crear el repositorio a través de gitlab-shell"
+
msgid "Failed to create resources"
msgstr "Se ha producido un error al crear los recursos"
msgid "Failed to deploy to"
msgstr "Se ha producido un error al desplegar a"
+msgid "Failed to get ref."
+msgstr "Se ha producido un error al obtener ref."
+
+msgid "Failed to install."
+msgstr "Se ha producido un error al instalar."
+
msgid "Failed to load emoji list."
msgstr "Se ha producido un error al cargar la lista de emojis."
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr "Se ha producido un error al cargar los errores desde Sentry. El mensaje de error es: %{errorMessage}"
+msgid "Failed to load groups & users."
+msgstr "Se ha producido un error al cargar grupos y usuarios."
+
+msgid "Failed to load related branches"
+msgstr "Se ha producido un error al cargar ramas relacionadas"
+
msgid "Failed to promote label due to internal error. Please contact administrators."
-msgstr ""
+msgstr "Se ha producido un erro al promocionar la etiqueta debido a un error interno. Por favor, póngase en contacto con los administradores."
+
+msgid "Failed to protect the branch"
+msgstr "Se ha producido un error al proteger la rama"
+
+msgid "Failed to protect the environment"
+msgstr "Se ha producido un error al proteger el entorno"
msgid "Failed to remove issue from board, please try again."
msgstr "Se ha producido un error al eliminar la incidencia del tablero, por favor, inténtelo de nuevo."
@@ -4576,38 +5397,56 @@ msgid "Failed to remove the pipeline schedule"
msgstr "Error al eliminar la programación del pipeline"
msgid "Failed to remove user identity."
-msgstr ""
+msgstr "Se ha producido un error al eliminar la identidad del usuario."
msgid "Failed to remove user key."
-msgstr ""
+msgstr "Se ha producido un error al eliminar la clave del usuario."
msgid "Failed to reset key. Please try again."
-msgstr ""
+msgstr "Se ha producido un error al restablecer la clave. Por favor, inténtalo de nuevo."
+
+msgid "Failed to save comment!"
+msgstr "¡Se ha producido un error al guardar el comentario!"
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr "Se ha producido un error al guardar las resoluciones de los conflictos producidos durante el merge. ¡Por favor, inténtelo de nuevo!"
msgid "Failed to save new settings"
-msgstr ""
+msgstr "Se ha producido un error al guardar los nuevos ajustes"
msgid "Failed to save preferences (%{error_message})."
-msgstr ""
+msgstr "Se ha producido un error al guardar las preferencias (%{error_message})."
msgid "Failed to save preferences."
-msgstr ""
+msgstr "Se ha producido un error al guardar las preferencias."
msgid "Failed to signing using smartcard authentication"
msgstr "Se ha producido un error al inciar sesión utilizando la autenticación mediante una tarjeta inteligente"
+msgid "Failed to update branch!"
+msgstr "¡Se ha producido un error al actualizar la rama!"
+
+msgid "Failed to update environment!"
+msgstr "Se ha producido un error al actualizar el entorno!"
+
msgid "Failed to update issues, please try again."
msgstr "Se ha producido un error al actualizar las incidencias. Por favor, inténtalo de nuevo."
+msgid "Failed to update tag!"
+msgstr "¡Se ha producido un error al actualizar la etiqueta!"
+
+msgid "Failed to update."
+msgstr "Se ha producido un error al actualizar."
+
+msgid "Failed to upgrade."
+msgstr "Se ha producido un error al actualizar."
+
msgid "Failed to upload object map file"
-msgstr ""
+msgstr "Se ha producido un error al cargar el archivo de mapa de objetos"
msgid "Failure"
msgstr "Error"
-msgid "Fast-forward merge"
-msgstr ""
-
msgid "Fast-forward merge without a merge commit"
msgstr ""
@@ -4615,10 +5454,16 @@ msgid "Faster as it re-uses the project workspace (falling back to clone if it d
msgstr ""
msgid "Favicon was successfully removed."
-msgstr ""
+msgstr "Se ha eliminado correctamente el Favicon."
msgid "Feature Flags"
-msgstr ""
+msgstr "Feature Flags"
+
+msgid "Feature flag was not removed."
+msgstr "No se ha eliminado la Feature Flag."
+
+msgid "Feature flag was successfully removed."
+msgstr "Feature flag eliminada correctamente."
msgid "FeatureFlags|* (All Environments)"
msgstr "* (Todos los entornos)"
@@ -4636,67 +5481,64 @@ msgid "FeatureFlags|Configure"
msgstr "Configurar"
msgid "FeatureFlags|Configure feature flags"
-msgstr ""
+msgstr "Configurar Feature Flags"
msgid "FeatureFlags|Create feature flag"
-msgstr ""
+msgstr "Crear Feature Flag"
msgid "FeatureFlags|Delete %{name}?"
msgstr "¿Eliminar %{name}?"
msgid "FeatureFlags|Delete feature flag"
-msgstr ""
+msgstr "Eliminar Feature Flag"
msgid "FeatureFlags|Description"
msgstr "Descripción"
msgid "FeatureFlags|Edit Feature Flag"
-msgstr ""
+msgstr "Editar Feature Flag"
msgid "FeatureFlags|Environment Spec"
-msgstr ""
+msgstr "Especificación del entorno"
msgid "FeatureFlags|Environment Specs"
-msgstr ""
+msgstr "Especificaciones del entorno"
msgid "FeatureFlags|Feature Flag"
-msgstr ""
+msgstr "Feature Flag"
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcare rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
-msgstr ""
+msgstr "Feature Flag se construye creando un conjunto de reglas para definir el estado de los entornos de destino. Se establece una regla por defecto comodín %{codeStart}*%{codeEnd} para %{boldStart}Todos los entornos%{boldEnd}, y a continuación, puede agregar tantas reglas como sea necesario seleccionando las especificaciones. Puede alternar el comportamiento de cada una de sus reglas estableciéndolas cómo %{boldStart}Activas%{boldEnd} o %{boldStart}Inactivas%{boldEnd}."
msgid "FeatureFlags|Feature Flags"
-msgstr ""
+msgstr "Feature Flags"
msgid "FeatureFlags|Feature Flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
-msgstr ""
+msgstr "Las Feature Flags le permiten configurar su código en diferentes sabores y alternar dinámicamente ciertas funciones."
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
-msgstr ""
+msgstr "Se a a eliminar la Feature Flag%{name}. ¿Está seguro de que desea continuar?"
msgid "FeatureFlags|Get started with Feature Flags"
-msgstr ""
+msgstr "Acerca de las Feature Flags"
msgid "FeatureFlags|Inactive"
msgstr "Inactivo"
msgid "FeatureFlags|Inactive flag for %{scope}"
-msgstr ""
+msgstr "Desactivar Flag para %{scope}"
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr "ID de instancia"
msgid "FeatureFlags|Loading Feature Flags"
-msgstr ""
+msgstr "Cargar Feature Flags"
msgid "FeatureFlags|More Information"
-msgstr ""
-
-msgid "FeatureFlags|More information"
-msgstr ""
+msgstr "Más información"
msgid "FeatureFlags|Name"
msgstr "Nombre"
@@ -4705,28 +5547,28 @@ msgid "FeatureFlags|New"
msgstr "Nuevo"
msgid "FeatureFlags|New Feature Flag"
-msgstr ""
+msgstr "Nueva Feature Flag"
msgid "FeatureFlags|Protected"
-msgstr ""
+msgstr "Protegido"
msgid "FeatureFlags|Status"
msgstr "Estado"
msgid "FeatureFlags|Target environments"
-msgstr ""
+msgstr "Entornos de destino"
msgid "FeatureFlags|There are no active Feature Flags"
-msgstr ""
+msgstr "No hay Feature Flags activas"
msgid "FeatureFlags|There are no inactive Feature Flags"
-msgstr ""
+msgstr "No hay Feature Flags inactivas"
msgid "FeatureFlags|There was an error fetching the feature flags."
-msgstr ""
+msgstr "Se ha producido un error al obtener las Feature Flag."
msgid "FeatureFlags|Try again in a few moments or contact your support team."
-msgstr ""
+msgstr "Inténtelo de nuevo en un momento o contacte con su equipo de soporte."
msgid "Feb"
msgstr "Feb"
@@ -4735,16 +5577,16 @@ msgid "February"
msgstr "Febrero"
msgid "Fetching incoming email"
-msgstr ""
+msgstr "Obteniendo el correo entrante"
msgid "Fetching licenses failed."
-msgstr ""
+msgstr "Se ha producido un error al obtener las licencias."
msgid "Fetching licenses failed. The request endpoint was not found."
-msgstr ""
+msgstr "Se ha producido un error al obtener las licencias. No es posible encontrar el endpoint de la solicitud."
msgid "Fetching licenses failed. You are not permitted to perform this action."
-msgstr ""
+msgstr "Se ha producido un error al obtener las licencias. No está autorizado a realizar esta acción."
msgid "Fields on this page are now uneditable, you can configure"
msgstr "Ahora puede editar los campos en esta página, puede configurar"
@@ -4755,7 +5597,7 @@ msgstr[0] "Archivo"
msgstr[1] "Archivos"
msgid "File added"
-msgstr ""
+msgstr "Archivo añadido"
msgid "File browser"
msgstr "Explorador de archivos"
@@ -4764,7 +5606,7 @@ msgid "File deleted"
msgstr "Archivo eliminado"
msgid "File mode changed from %{a_mode} to %{b_mode}"
-msgstr ""
+msgstr "El modo del archivo ha cambiado de %{a_mode} a %{b_mode}"
msgid "File moved"
msgstr "Archivo movido"
@@ -4778,9 +5620,15 @@ msgstr "Error al subir el archivo."
msgid "Files"
msgstr "Archivos"
-msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
+msgid "Files breadcrumb"
msgstr ""
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr "Archivos, directorios y submódulos en la ruta %{path} para la referencia del commit %{ref}"
+
+msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
+msgstr "Rellene los siguientes campos, active <strong>%{enable_label}</strong>y presione <strong>%{save_changes}</strong>"
+
msgid "Filter"
msgstr "Filtro"
@@ -4794,7 +5642,7 @@ msgid "Filter by commit message"
msgstr "Filtrar por mensaje del cambio"
msgid "Filter by milestone name"
-msgstr ""
+msgstr "Filtrar por nombre del hito"
msgid "Filter by two-factor authentication"
msgstr "Filtrar por autenticación de dos factores"
@@ -4824,17 +5672,23 @@ msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/Google
msgstr "Busque el archivo extraído <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code>."
msgid "Fingerprint"
-msgstr ""
+msgstr "Huella digital"
+
+msgid "Fingerprint:"
+msgstr "Huella:"
msgid "Fingerprints"
msgstr "Huellas digitales"
msgid "Finish editing this message first!"
-msgstr ""
+msgstr "¡Termine la edición de este mensaje primero!"
msgid "Finish review"
msgstr "Finalizar revisión"
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr "Finalizar la configuración de su cuenta dedicada para <strong>%{group_name}</strong>."
+
msgid "Finished"
msgstr "Finalizado"
@@ -4859,6 +5713,12 @@ msgstr "Fecha de inicio fija"
msgid "Fixed:"
msgstr "Arreglado:"
+msgid "FlowdockService|Flowdock Git source token"
+msgstr "Token de origen de Flowdock Git"
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr "Flowdock es una aplicación de colaboración web para equipos técnicos."
+
msgid "FogBugz Email"
msgstr "Correo electrónico de FogBugz"
@@ -4884,52 +5744,67 @@ msgid "Footer message"
msgstr "Mensaje a pie de página"
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
+msgstr "Para los proyectos internos, cualquier usuario que haya iniciado sesión puede visualizar los pipelines y acceder a un trabajo de forma detallada (registros de salida y artefactos)"
msgid "For more info, read the documentation."
msgstr "Para más información, por favor lea la documentación."
msgid "For more information, go to the "
-msgstr ""
+msgstr "Para obtener más información, vaya a "
msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
-msgstr ""
+msgstr "Para obtener más información, por favor revise el documento de configuración de %{link_start_tag}Jaeger%{link_end_tag}"
msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
-msgstr ""
+msgstr "Para obtener más información, consulte la documentación en %{deactivating_usage_ping_link_start} desactivar el uso ping %{deactivating_usage_ping_link_end}."
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
+msgstr "Para los proyectos privados, cualquier miembro (visitante o administrador) puede visualizar los pipelines y acceder los detalles de los trabajos (registros de salida and artefactos)"
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
+msgstr "Para los proyectos públicos, cualquiera puede visualizar los pipelines y acceder los detalles de los trabajos (registros de salida and artefactos)"
+
+msgid "Fork"
+msgstr "Fork"
+
+msgid "Fork Error!"
+msgstr "Se ha producido un error al realizar el fork, por favor, inténtelo de nuevo"
+
+msgid "Fork project"
+msgstr "Realizar un fork del proyecto"
msgid "ForkedFromProjectPath|Forked from"
msgstr "Bifurcado de"
msgid "ForkedFromProjectPath|Forked from %{project_name} (deleted)"
-msgstr ""
+msgstr "Fork desde %{project_name} (eliminado)"
msgid "Forking in progress"
-msgstr ""
+msgstr "Fork en progreso"
+
+msgid "Forking repository"
+msgstr "Realizando un fork del repositorio"
msgid "Forks"
-msgstr ""
+msgstr "Forks"
msgid "Format"
msgstr "Formato"
msgid "Forward external support email address to"
-msgstr ""
+msgstr "Reenviar la dirección de correo electrónico de soporte externo a"
msgid "Found errors in your %{gitlab_ci_yml}:"
-msgstr ""
+msgstr "Se han encontrado errores en su archivo %{gitlab_ci_yml}:"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr "Se han encontrado errores en su fichero .gitlab-ci.yml:"
msgid "Free Trial of GitLab.com Gold"
-msgstr ""
+msgstr "Prueba gratuita de GitLab.com Gold"
+
+msgid "Friday"
+msgstr "Viernes"
msgid "From %{providerTitle}"
msgstr "De %{providerTitle}"
@@ -4961,11 +5836,17 @@ msgstr "De los hitos:"
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr "Desde la vista de detalles del clúster de Kubernetes, seleccione instalar 'runner' desde la lista de aplicaciones"
+msgid "Full name"
+msgstr "Nombre completo"
+
msgid "GPG Key ID:"
msgstr "ID de la clave GPG:"
msgid "GPG Keys"
-msgstr "Llaves GPG"
+msgstr "Claves GPG"
+
+msgid "GPG keys allow you to verify signed commits."
+msgstr "Las claves GPG le permiten verificar los commits firmados."
msgid "GPG signature (loading...)"
msgstr "Firma GPG (cargando...)"
@@ -4977,7 +5858,7 @@ msgid "General Settings"
msgstr "Configuración general"
msgid "General pipelines"
-msgstr ""
+msgstr "Pipelines"
msgid "Generate a default set of labels"
msgstr "Generar un conjunto predeterminado de etiquetas"
@@ -4986,34 +5867,34 @@ msgid "Generate key"
msgstr "Generar clave"
msgid "Generate new export"
-msgstr ""
+msgstr "Generar nueva exportación"
msgid "Geo"
msgstr "Geo"
msgid "Geo Nodes"
-msgstr ""
+msgstr "Geo Nodos"
msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
-msgstr ""
+msgstr "Geo le permite replicar su instancia de Gitlab a otras ubicaciones geográficas."
msgid "GeoNodeSyncStatus|Node is failing or broken."
-msgstr ""
+msgstr "El nodo está caído o fallando."
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
-msgstr ""
+msgstr "El nodo es lento, está sobrecargado o se ha recuperado después de una interrupción."
msgid "GeoNodes|Checksummed"
-msgstr ""
+msgstr "Comprobado"
msgid "GeoNodes|Data is out of date from %{timeago}"
-msgstr ""
+msgstr "No se han actualizado los datos desde %{timeago}"
msgid "GeoNodes|Data replication lag"
-msgstr ""
+msgstr "Retraso en replicación de datos"
msgid "GeoNodes|Does not match the primary storage configuration"
-msgstr ""
+msgstr "No coincide con la configuración principal de almacenamiento"
msgid "GeoNodes|Failed"
msgstr "Fallido"
@@ -5031,7 +5912,7 @@ msgid "GeoNodes|Health status"
msgstr "Estado de salud"
msgid "GeoNodes|Internal URL"
-msgstr ""
+msgstr "URL interna"
msgid "GeoNodes|Last event ID processed by cursor"
msgstr "ID del último evento procesado por el cursor"
@@ -5079,13 +5960,13 @@ msgid "GeoNodes|Out of sync"
msgstr "Sin sincronización"
msgid "GeoNodes|Pausing replication stops the sync process."
-msgstr ""
+msgstr "Pausar la replica detiene el proceso de sincronización."
msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
-msgstr ""
+msgstr "La eliminación de un nodo primario detiene el proceso de sincronización para todos los nodos. No se puede reanudar la sincronización sin perder algunos datos en todos los nodos secundarios. En este caso, recomendamos volver a configurar todos los nodos desde cero. ¿Está seguro de que desea continuar?"
msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
-msgstr ""
+msgstr "La eliminación de un nodo secundario detiene el proceso de sincronización. No es posible volver a agregar el mismo nodo sin perder algunos datos. Solo recomendamos configurar un nuevo nodo secundario en este caso. ¿Está seguro de que desea continuar?"
msgid "GeoNodes|Replication slot WAL"
msgstr "Slots de replicación WAL"
@@ -5160,7 +6041,7 @@ msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr "Wikis verificados con sus contrapartes en el nodo principal"
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
-msgstr ""
+msgstr "Con %{geo} puede instalar una instancia especial de solo lectura y replicarla en cualquier lugar. Antes de agregar los nodos, siga las %{instructions} en el orden exacto en que se muestran."
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr "Ha configurado los nodos Geo utilizando una conexión HTTP insegura. Le recomendamos la utilización de una conexión HTTPS."
@@ -5190,22 +6071,22 @@ msgid "Geo|Batch operations"
msgstr "Operaciones por lotes"
msgid "Geo|Choose which groups you wish to synchronize to this secondary node."
-msgstr ""
+msgstr "Escoja que grupos desea sincronizar con este nodo secundario."
msgid "Geo|Control the maximum concurrency of LFS/attachment backfill for this secondary node"
-msgstr ""
+msgstr "Controla la concurrencia máxima de LFS/attachment para este nodo secundario"
msgid "Geo|Control the maximum concurrency of verification operations for this Geo node"
-msgstr ""
+msgstr "Controla el número máximo de operaciones de verificación concurrentes para este nodo Geo"
msgid "Geo|Control the minimum interval in days that a repository should be reverified for this primary node"
-msgstr ""
+msgstr "Controla el intervalo mínimo de días que un repositorio debe volver a ser verificado para este nodo principal"
msgid "Geo|Could not remove tracking entry for an existing project."
msgstr "No se puede eliminar la entrada de seguimiento para un proyecto existente."
msgid "Geo|Could not remove tracking entry for an existing upload."
-msgstr ""
+msgstr "No se puede eliminar la entrada de seguimiento para un proyecto existente."
msgid "Geo|Failed"
msgstr "Fallido"
@@ -5214,7 +6095,7 @@ msgid "Geo|File sync capacity"
msgstr "Capacidad de sincronización de archivos"
msgid "Geo|Geo Status"
-msgstr ""
+msgstr "Estado de Geo"
msgid "Geo|Groups to synchronize"
msgstr "Grupos a sincronizar"
@@ -5223,10 +6104,10 @@ msgid "Geo|In sync"
msgstr "Sincronizado"
msgid "Geo|Internal URL"
-msgstr ""
+msgstr "URL interna"
msgid "Geo|Last repository check run"
-msgstr ""
+msgstr "Comprobar último repositorio ejecutado"
msgid "Geo|Last successful sync"
msgstr "Última sincronización correcta"
@@ -5244,7 +6125,7 @@ msgid "Geo|Next sync scheduled at"
msgstr "Próxima sincronización programada en"
msgid "Geo|Not synced yet"
-msgstr ""
+msgstr "Sin sincronizar aún"
msgid "Geo|Pending"
msgstr "Pendiente"
@@ -5256,31 +6137,31 @@ msgid "Geo|Pending verification"
msgstr "Pendiente de verificación"
msgid "Geo|Please refer to Geo Troubleshooting."
-msgstr ""
+msgstr "Por favor, consulte la sección de solución de problemas de Geo."
msgid "Geo|Project"
-msgstr ""
+msgstr "Proyecto"
msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
-msgstr ""
+msgstr "El proyecto Geo|(ID: %{project_id}) ya no existe en el nodo primario. Es seguro eliminar esta entrada, esta acción no eliminará ningún dato del disco."
msgid "Geo|Projects in certain groups"
msgstr "Proyectos en determinados grupos"
msgid "Geo|Projects in certain storage shards"
-msgstr ""
+msgstr "Proyectos en determinados grupos de almacenamiento"
msgid "Geo|Re-verification interval"
-msgstr ""
+msgstr "Intervalo de verificación"
msgid "Geo|Recheck"
-msgstr ""
+msgstr "Volver a comprobar"
msgid "Geo|Recheck all projects"
-msgstr ""
+msgstr "Volver a comprobar todos los proyectos"
msgid "Geo|Redownload"
-msgstr ""
+msgstr "Volver a descargar"
msgid "Geo|Remove"
msgstr "Eliminar"
@@ -5310,19 +6191,25 @@ msgid "Geo|Status"
msgstr "Estado"
msgid "Geo|Sync"
-msgstr ""
+msgstr "Sincronizar"
msgid "Geo|Synced"
msgstr "Sincronizado"
msgid "Geo|Synced at"
-msgstr ""
+msgstr "Sincronizado en"
msgid "Geo|Synchronization failed - %{error}"
msgstr "Se ha producido un error durante la sincronización - %{error}"
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
-msgstr ""
+msgstr "La URL definida en el nodo primario que los nodos secundarios deben usar para contactarlo. Devuelve `url` si no está establecida"
+
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr "La base de datos está %{db_lag} detrás del nodo primario."
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr "El nodo está %{minutes_behind} detrás del nodo primario."
msgid "Geo|This is a primary node"
msgstr "Este es un nodo primario"
@@ -5331,10 +6218,10 @@ msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
msgstr "La entrada de seguimiento del proyecto (%{project_id}) se eliminó correctamente."
msgid "Geo|Tracking entry for upload (%{type}/%{id}) was successfully removed."
-msgstr ""
+msgstr "La entrada de seguimiento de carga (%{type}/%{id}) se ha eliminado correctamente."
msgid "Geo|Tracking entry will be removed. Are you sure?"
-msgstr ""
+msgstr "Se eliminará la entrada de seguimiento. ¿Está seguro de que desea continuar?"
msgid "Geo|URL"
msgstr "URL"
@@ -5343,19 +6230,19 @@ msgid "Geo|Unknown state"
msgstr "Estado desconocido"
msgid "Geo|Verification capacity"
-msgstr ""
+msgstr "Capacidad de verificación"
msgid "Geo|Verification failed - %{error}"
-msgstr ""
+msgstr "Se ha producido un error durante la verificación - %{error}"
msgid "Geo|Waiting for scheduler"
-msgstr ""
+msgstr "Esperando por el programador"
msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
+msgstr "Está en un nodo Geo secundario de <b>sólo lectura</b>. Si quiere realizar cambios, debe visitar esta página en %{primary_node}."
msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
-msgstr ""
+msgstr "Está en un nodo secundario, <b>de solo lectura</b> Geo. Es posible que pueda realizar una cantidad limitada de cambios o realizar una cantidad limitada de acciones en esta página."
msgid "Geo|misconfigured"
msgstr "desconfigurado"
@@ -5370,16 +6257,19 @@ msgid "Get a free instance review"
msgstr "Obtenga una revisión de instancia gratuita"
msgid "Get started with error tracking"
-msgstr ""
+msgstr "Comenzar con el control de errores"
msgid "Getting started with releases"
-msgstr ""
+msgstr "Primeros pasos con las versiones"
msgid "Git"
msgstr "Git"
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
-msgstr ""
+msgstr "Git LFS no está habilitado en este servidor de GitLab, póngase en contacto con su administrador."
+
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr "Los objetos Git LFS se sincronizarán en los servidores de replica si LFS está %{docs_link_start}habilitado para el proyecto%{docs_link_end}. <strong>no</strong> se sincronizarán en servidores espejos de push."
msgid "Git global setup"
msgstr "Configuración global de Git"
@@ -5390,6 +6280,9 @@ msgstr "URL del repositorio Git"
msgid "Git revision"
msgstr "Revisión de Git"
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr "Estrategia de Git para los 'pipelines'"
@@ -5403,7 +6296,7 @@ msgid "GitLab CI Linter has been moved"
msgstr "Se ha movido GitLab CI Linter"
msgid "GitLab Enterprise Edition %{plan}"
-msgstr ""
+msgstr "GitLab Enterprise Edition %{plan}"
msgid "GitLab Geo"
msgstr "GitLab Geo"
@@ -5415,34 +6308,34 @@ msgid "GitLab Import"
msgstr "Importar desde GitLab"
msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
-msgstr ""
+msgstr "Los ejecutores compartidos de GitLab ejecutan el código de diferentes proyectos en el mismo ejecutor a menos que configure el auto escalado de os ejecutores de GitLab con MaxBuilds 1 (que se encuentra en GitLab.com)."
msgid "GitLab User"
msgstr "Usuario de GitLab"
msgid "GitLab allows you to continue using your license even if you exceed the number of seats you purchased. You will be required to pay for these seats when you renew your license."
-msgstr ""
+msgstr "GitLab le permite continuar usando su licencia incluso si excede la cantidad puestos que compró. Deberá por pagar estos puestos cuando renueve su licencia."
msgid "GitLab metadata URL"
-msgstr ""
+msgstr "URL de metadatos de GitLab"
msgid "GitLab project export"
msgstr "Exportar proyecto desde GitLab"
msgid "GitLab restart is required to apply changes"
-msgstr ""
+msgstr "Se requiere reiniciar GitLab para aplicar cambios"
msgid "GitLab single sign on URL"
msgstr "URL de inicio de sesión único de GitLab"
msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
+msgstr "Gitlab ejecutará un trabajo como tarea de fondo que producirá un archivo CSV seudonimizado de la base de datos de Gitlab y que se cargará a su directorio de almacenamiento de objetos que tenga configurado."
msgid "GitLab.com import"
msgstr "Importar desde GitLab.com"
msgid "GitLab’s issue tracker"
-msgstr ""
+msgstr "El gestor de incidencias de GitLab"
msgid "Gitaly"
msgstr "Gitaly"
@@ -5460,13 +6353,16 @@ msgid "Gitea Import"
msgstr "Importar desde Gitea"
msgid "Given access %{time_ago}"
-msgstr ""
+msgstr "Acceso concedido %{time_ago}"
+
+msgid "Global notification settings"
+msgstr "Configuración global de las notificaciones"
msgid "Go Back"
msgstr "Volver"
msgid "Go Micro is a framework for micro service development."
-msgstr ""
+msgstr "Go Micro es un framework para el desarrollo de microservicios."
msgid "Go back"
msgstr "Volver"
@@ -5480,9 +6376,18 @@ msgstr "Ir a"
msgid "Go to %{link_to_google_takeout}."
msgstr "Ir a %{link_to_google_takeout}."
+msgid "Go to parent"
+msgstr "Ir al principal"
+
msgid "Go to project"
msgstr "Ir al proyecto"
+msgid "Go to your fork"
+msgstr "Ir a su fork"
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr "Importar desde Google Code"
@@ -5490,7 +6395,7 @@ msgid "Google Takeout"
msgstr "Google Takeout"
msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
-msgstr "La autenticación de Google no se encuentra %{link_to_documentation}. Pregúntale a tu administrador de GitLab si quieres usar este servicio."
+msgstr "La autenticación de Google no se encuentra %{link_to_documentation}. Pregúntale a tu administrador de GitLab si quieres utilizar este servicio."
msgid "Got it!"
msgstr "¡Lo tengo!"
@@ -5508,10 +6413,10 @@ msgid "Group"
msgstr "Grupo"
msgid "Group %{group_name} was scheduled for deletion."
-msgstr ""
+msgstr "Se ha programado el grupo %{group_name} para su eliminación."
msgid "Group %{group_name} was successfully created."
-msgstr ""
+msgstr "El grupo %{group_name} se actualizó correctamente."
msgid "Group CI/CD settings"
msgstr "Configuración de grupo CI/CD"
@@ -5529,7 +6434,7 @@ msgid "Group Runners"
msgstr "Grupo de ejecutores"
msgid "Group SAML must be enabled to test"
-msgstr ""
+msgstr "El grupo SAML debe estar habilitado para poder probar"
msgid "Group URL"
msgstr "URL del grupo"
@@ -5550,16 +6455,19 @@ msgid "Group info:"
msgstr "Información del grupo:"
msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
+msgstr "Los mantenedores de grupo pueden registrar grupos de ejecutores en el %{link}"
msgid "Group name"
msgstr "Nombre del grupo"
msgid "Group overview content"
-msgstr ""
+msgstr "Resumen del contenido del grupo"
+
+msgid "Group pipeline minutes were successfully reset."
+msgstr "La cuota de minutos del pipeline fue restablecida con éxito."
msgid "Group was successfully updated."
-msgstr ""
+msgstr "Grupo actualizado correctamente."
msgid "Group:"
msgstr "Grupo:"
@@ -5567,6 +6475,9 @@ msgstr "Grupo:"
msgid "Group: %{group_name}"
msgstr "Grupo: %{group_name}"
+msgid "Group: %{name}"
+msgstr "Grupo: %{name}"
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr "Desde %{dateWord}"
@@ -5577,145 +6488,157 @@ msgid "GroupRoadmap|Sorry, no epics matched your search"
msgstr "Lo sentimos, no hay tareas épicas que coincidan con su búsqueda"
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
-msgstr ""
+msgstr "La hoja de ruta muestra el progreso de sus tareas épicas a lo largo de una línea de tiempo"
msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of the %{linkStart}child epics%{linkEnd}."
-msgstr ""
+msgstr "Para ver la hoja de ruta, agregue una fecha de inicio o de vencimiento a una de las %{linkStart}tareas épicas secundarias%{linkEnd}."
msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
-msgstr ""
+msgstr "Para ver la hoja de ruta, agregue la fecha de inicio o la de vencimiento a una de sus tareas épicas de este grupo o sus subgrupos; de %{startDate} hasta %{endDate}."
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
-msgstr ""
+msgstr "Para ampliar su búsqueda, cambie o elimine los filtros; desde %{startDate} a %{endDate}."
msgid "GroupRoadmap|Until %{dateWord}"
msgstr "Hasta %{dateWord}"
msgid "GroupSAML|Certificate fingerprint"
-msgstr ""
+msgstr "Huella digital del certificado"
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
-msgstr ""
+msgid "GroupSAML|Enable SAML authentication for this group."
+msgstr "Habilitar la autenticación SAML para este grupo."
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
-msgstr ""
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgstr "Forzar autenticación SSO para este grupo."
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
+msgstr "Obligar a los usuarios tener cuentas administradas de grupo dedicadas para este grupo."
msgid "GroupSAML|Enforced SSO"
-msgstr ""
+msgstr "SSO Forzado"
msgid "GroupSAML|Generate a SCIM token"
-msgstr ""
+msgstr "Generar un token SCIM"
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
-msgstr ""
-
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
+msgstr "Genere un token SCIM para configurar su sistema para la administración de identidades entre dominios."
msgid "GroupSAML|Identity provider single sign on URL"
-msgstr ""
+msgstr "URL de inicio de sesión único del proveedor de identidades"
msgid "GroupSAML|Make sure you save this token — you won't be able to access it again."
-msgstr ""
+msgstr "Asegúrese de guardar este token - no podrá acceder a él de nuevo."
msgid "GroupSAML|Manage your group’s membership while adding another level of security with SAML."
-msgstr ""
+msgstr "Administre los miembros del grupo al agregar otro nivel de seguridad con SAML."
msgid "GroupSAML|Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
-msgstr ""
+msgstr "Cuando un usuario inicie la sesión en su grupo se reenviará aquí. Esta información, que también se puede denominar, \"SSO Service Location\", \"SAML Token Issuance Endpoint\", o \"SAML 2.0/W-Federation URL\" la puede obtener de su proveedor de identidad."
msgid "GroupSAML|SAML Single Sign On"
-msgstr ""
+msgstr "SAML Single Sign On"
msgid "GroupSAML|SAML Single Sign On Settings"
-msgstr ""
+msgstr "Opciones de configuración de SAML Single Sign On"
msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
+msgstr "URL del endpoint de SCIM API"
msgid "GroupSAML|SCIM Token"
-msgstr ""
+msgstr "Token SCIM"
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
-msgstr ""
+msgstr "La huella digital SHA1 del certificado de firma de tokens SAML. Puede obtener esta información de su proveedor de identidad, donde también se puede llamar \"Huella digital\"."
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
+msgstr "El token SCIM está oculto. Para ver el valor del token de nuevo, necesita "
+
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr "Para poder habilitar el SSO, primero debe habilitar la autenticación SAML."
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr "Para poder habilitar cuentas de grupo administradas, primero debe habilitar el SSO."
msgid "GroupSAML|Toggle SAML authentication"
-msgstr ""
+msgstr "Activar la autenticación SAML"
+
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr "Con las cuentas administradas de grupo habilitadas, todos los usuarios sin una cuenta administrada de grupo serán excluidos del mismo."
msgid "GroupSAML|Your SCIM token"
-msgstr ""
+msgstr "Tu token SCIM"
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
-msgstr ""
+msgstr "El pipeline Auto DevOps se actualizó para el grupo"
msgid "GroupSettings|Auto DevOps will automatically build, test and deploy your application based on a predefined Continuous Integration and Delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end}"
-msgstr ""
+msgstr "Auto DevOps compilará, probará e implementará automáticamente su aplicación en base a una configuración predefinida de integración y entrega continua. %{auto_devops_start}Obtenga más información sobre Auto DevOps%{auto_devops_end}"
msgid "GroupSettings|Badges"
msgstr "GroupSettings|Insignias"
msgid "GroupSettings|Custom project templates"
-msgstr ""
+msgstr "Plantillas de proyecto personalizadas"
msgid "GroupSettings|Customize your group badges."
-msgstr ""
+msgstr "Personalice sus insignias de grupo."
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
-msgstr ""
+msgstr "Por defecto, al pipeline de Auto DevOps para todos los proyectos englobados dentro de este grupo"
msgid "GroupSettings|Learn more about badges."
-msgstr ""
+msgstr "Aprenda más sobre insignias."
msgid "GroupSettings|Learn more about group-level project templates."
-msgstr ""
+msgstr "Más información sobre las plantillas de proyecto a nivel de grupo."
msgid "GroupSettings|New runners registration token has been generated!"
-msgstr ""
+msgstr "¡Se ha generado el token de registro para los nuevos ejecutores!"
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Prevenir que se comparta un proyecto de %{group} con otros grupos"
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
-msgstr ""
+msgstr "Seleccione un subgrupo como fuente de plantilla de proyecto personalizada para este grupo."
msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
-msgstr ""
+msgstr "El pipeline Auto DevOps se ejecutará si no se encuentra ningún archivo de configuración de CI/CD alternativo."
msgid "GroupSettings|There was a problem updating Auto DevOps pipeline: %{error_messages}."
-msgstr ""
+msgstr "Se ha producido un error al actualizar el pipeline de Auto DevOps: %{error_messages}."
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
-msgstr ""
+msgstr "Esta configuración aplica a %{ancestor_group} y se ha sobreescrito para este subgrupo."
msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
-msgstr ""
+msgstr "Esta configuración se aplica en %{ancestor_group}. Para compartir los proyectos de este grupo con otro grupo, solicite al propietario que sobrescriba la configuración o %{remove_ancestor_share_with_group_lock}."
msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
-msgstr ""
+msgstr "Esta configuración se aplica en %{ancestor_group}. Puede sobrescribir la configuración o %{remove_ancestor_share_with_group_lock}."
msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
-msgstr ""
+msgstr "Esta configuración se aplicará a todos los subgrupos a menos que se sobrescriba por el propietario de un grupo. Los grupos que ya tienen acceso al proyecto seguirán teniendo acceso, a menos que estos permisos se eliminen manualmente."
msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
-msgstr ""
+msgstr "No se puede deshabilitar cuando el grupo principal \"Compartir con bloqueo de grupo\" está habilitado, excepto por el propietario del grupo principal"
msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
-msgstr ""
+msgstr "eliminar el recurso compartido con bloqueo de grupo desde %{ancestor_group_name}"
msgid "Groups"
msgstr "Grupos"
+msgid "Groups (%{count})"
+msgstr "Grupos: (%{count})"
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
+msgstr "Los grupos también se pueden anidar creando %{subgroup_docs_link_start}subgrupos%{subgroup_docs_link_end}."
msgid "Groups with access to <strong>%{project_name}</strong>"
-msgstr ""
+msgstr "Los grupos con acceso a <strong>%{project_name}</strong>"
msgid "GroupsDropdown|Frequently visited"
msgstr "Más visitado"
@@ -5730,28 +6653,28 @@ msgid "GroupsDropdown|Search your groups"
msgstr "Buscar en sus grupos"
msgid "GroupsDropdown|Something went wrong on our end."
-msgstr ""
+msgstr "Ha ocurrido un error de nuestro lado."
msgid "GroupsDropdown|Sorry, no groups matched your search"
-msgstr ""
+msgstr "Lo sentimos, no hay grupos que coincidan con su búsqueda"
msgid "GroupsDropdown|This feature requires browser localStorage support"
-msgstr ""
+msgstr "Esta característica requiere localStorage en su navegador web"
msgid "GroupsEmptyState|A group is a collection of several projects."
-msgstr ""
+msgstr "Un grupo es una colección de varios proyectos."
msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
-msgstr ""
+msgstr "Al organizar sus proyectos como un grupo, estos funcionan de la misma forma que una carpeta."
msgid "GroupsEmptyState|No groups found"
msgstr "No se encuentran grupos"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
-msgstr ""
+msgstr "Puede administrar los permisos y el acceso de cada miembro del grupo a cada proyecto del grupo."
msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
-msgstr ""
+msgstr "¿Está seguro que desea dejar el grupo \"%{fullName}\"?"
msgid "GroupsTree|Create a project in this group."
msgstr "Crear un proyecto en este grupo."
@@ -5772,40 +6695,46 @@ msgid "GroupsTree|Loading groups"
msgstr "Cargando grupos"
msgid "GroupsTree|No groups matched your search"
-msgstr ""
+msgstr "Lo sentimos, no existen grupos que coincidan con su búsqueda"
msgid "GroupsTree|No groups or projects matched your search"
-msgstr ""
+msgstr "Lo sentimos, no existen grupos ni proyectos que coincidan con su búsqueda"
msgid "GroupsTree|Search by name"
msgstr "Buscar por nombre"
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr "HTTP básico: Acceso denegado\\nDebe utilizar un token de acceso personal con alcance 'api' para Git a través de HTTP.\\nPuedes generar uno a %{profile_personal_access_tokens_url}"
+
msgid "Have your users email"
msgstr ""
msgid "Header logo was successfully removed."
-msgstr ""
+msgstr "Se ha eliminado el logo del encabezado correctamente."
msgid "Header message"
msgstr "Encabezado del mensaje"
msgid "Health Check"
-msgstr "Verificación del estado"
+msgstr "Verificación de estado"
msgid "Health information can be retrieved from the following endpoints. More information is available"
-msgstr ""
+msgstr "La información de la verificación del estado del sistema se puede obtener de los siguientes endpoints. Hay disponible más información adicional"
msgid "HealthCheck|Access token is"
-msgstr "Token de Acceso es"
+msgstr "El token de acceso es"
msgid "HealthCheck|Healthy"
msgstr "Saludable"
msgid "HealthCheck|No Health Problems Detected"
-msgstr ""
+msgstr "No se han detectado problemas"
msgid "HealthCheck|Unhealthy"
-msgstr "Poco Saludable"
+msgstr "Poco saludable"
+
+msgid "Hello there"
+msgstr "¡Hola!"
msgid "Help"
msgstr "Ayuda"
@@ -5816,21 +6745,27 @@ msgstr "Página de ayuda"
msgid "Help page text and support page url."
msgstr "Texto de la página de ayuda y url de la página de soporte."
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
-msgstr "Aquí está la clave pública SSH que se debe añadir al servidor remoto. Para obtener más información, consulte la documentación."
+msgid "Hide archived projects"
+msgstr "Ocultar proyectos archivados"
msgid "Hide file browser"
-msgstr ""
+msgstr "Ocultar el explorador de archivos"
+
+msgid "Hide group projects"
+msgstr "Ocultar grupos de proyectos"
msgid "Hide host keys manual input"
msgstr ""
msgid "Hide marketing-related entries from help"
-msgstr ""
+msgstr "Ocultar en la ayuda las entradas relacionadas con marketing"
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr "Ocultar proyectos compartidos"
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Ocultar valor"
@@ -5840,28 +6775,40 @@ msgid "Hide values"
msgstr "Ocultar valores"
msgid "Highest role:"
-msgstr ""
+msgstr "Rol más alto:"
msgid "History"
msgstr "Historial"
+msgid "History of authentications"
+msgstr "Historial de autentificación"
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr "Falló la ejecución del hook. Asegúrese de que el grupo tiene, al menos, un proyecto con commits."
+
msgid "Hook was successfully created."
-msgstr ""
+msgstr "El hook se ha creado correctamente."
msgid "Hook was successfully updated."
-msgstr ""
+msgstr "El hook se actualizó correctamente."
msgid "Housekeeping"
-msgstr ""
+msgstr "Mantenimiento"
msgid "Housekeeping successfully started"
msgstr "Servicio de limpieza iniciado con éxito"
msgid "Housekeeping, export, path, transfer, remove, archive."
-msgstr ""
+msgstr "Tareas de mantenimiento, exportación, ruta, transferencia, eliminación, archivo."
+
+msgid "How many replicas each Elasticsearch shard has."
+msgstr "Cuántas réplicas tiene cada shard de Elasticsearch."
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr "¿En cuántos shards se puede dividir el índice de Elasticsearch?."
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
-msgstr ""
+msgstr "Sin embargo, ya es miembro de este %{member_source}. Inicie sesión con una cuenta diferente para aceptar la invitación."
msgid "I accept the %{terms_link}"
msgstr "Aceptar los %{terms_link}"
@@ -5869,6 +6816,12 @@ msgstr "Aceptar los %{terms_link}"
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr "Aceptar los términos de servicio y la política de privacidad"
+msgid "I forgot my password"
+msgstr "He olvidado mi contraseña"
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr "He leído y acepto los términos de servicio de Let's Encrypt %{link_start}%{link_end}"
+
msgid "ID"
msgstr "ID"
@@ -5888,19 +6841,19 @@ msgid "IDE|Edit"
msgstr "Editar"
msgid "IDE|Get started with Live Preview"
-msgstr ""
+msgstr "Comenzar con la vista previa"
msgid "IDE|Go to project"
msgstr "Ir al proyecto"
msgid "IDE|Live Preview"
-msgstr ""
+msgstr "Vista previa"
msgid "IDE|Open in file view"
-msgstr ""
+msgstr "Abrir en la vista de archivo"
msgid "IDE|Preview your web application using Web IDE client-side evaluation."
-msgstr ""
+msgstr "Previsualice su aplicación web utilizando la evaluación del lado del cliente del Web IDE."
msgid "IDE|Refresh preview"
msgstr "Actualizar vista previa"
@@ -5918,19 +6871,19 @@ msgid "Identities"
msgstr "Identidades"
msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-msgstr ""
+msgstr "Si algún trabajo supera este umbral de tiempo de espera, se marcará como fallido. Se permite la utilización del lenguaje de entrada de tiempo para humanos, como por ejemplo, \"1 hora\". Los valores que no contengan ninguna especificación de formato se representan como tiempo en segundos."
msgid "If checked, group owners can manage LDAP group links and LDAP member overrides"
-msgstr ""
+msgstr "Si está marcado, los propietarios de grupos pueden administrar enlaces de grupo LDAP y anular los miembros LDAP"
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
msgstr ""
msgid "If disabled, only admins will be able to set up mirrors in projects."
-msgstr ""
+msgstr "Si está deshabilitado, solo los administradores podrán configurar mirrors en los proyectos."
msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
+msgstr "Si está deshabilitado, el nivel de acceso dependerá de los permisos del usuario en el proyecto."
msgid "If enabled"
msgstr "Si está habilitado"
@@ -5938,11 +6891,20 @@ msgstr "Si está habilitado"
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr "Si está habilitado, el acceso a los proyectos se validará en un servicio externo utilizando su etiqueta de clasificación."
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr "Si esto fue un error puede %{leave_link_start}dejar el %{source_type}%{link_end}."
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr "Si esto fue un error puede dejar el %{source_type}."
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr "Si utiliza GitHub, verá los estados del pipeline en GitHub para sus commit y sus pull request. %{more_info_link}"
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
-msgstr ""
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr "Si pierde los códigos de recuperación, puede generar otros nuevos, invalidando todos los códigos anteriores."
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
+msgstr "Si su repositorio HTTP no es accesible públicamente, añada sus credenciales."
msgid "ImageDiffViewer|2-up"
msgstr "2-up"
@@ -5954,7 +6916,7 @@ msgid "ImageDiffViewer|Swipe"
msgstr "Swipe"
msgid "Impersonation has been disabled"
-msgstr ""
+msgstr "La suplantación ha sido deshabilitada"
msgid "Import"
msgstr "Importar"
@@ -6022,53 +6984,74 @@ msgstr "Importar repositorios desde GitHub"
msgid "Import repository"
msgstr "Importar repositorio"
+msgid "Import tasks"
+msgstr "Importar tareas"
+
+msgid "Import tasks from Phabricator into issues"
+msgstr "Importar tareas desde Phabricator como incidencias"
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
-msgstr ""
+msgstr "Se agotó el tiempo de espera para el proceso de importación. Este proceso ha tardado más de %{import_jobs_expiration} segundos"
msgid "Import/Export illustration"
-msgstr ""
+msgstr "Importar/Exportar ilustración"
msgid "ImportButtons|Connect repositories from"
msgstr "Conectar repositorios desde"
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr "URL de importación bloqueada: %{message}"
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr "Error al importar el repositorio %{project_safe_import_url} en %{project_full_path} - %{message}"
+
msgid "ImportProjects|Importing the project failed"
-msgstr ""
+msgstr "Se ha producido un error al importar el proyecto"
msgid "ImportProjects|Requesting your %{provider} repositories failed"
-msgstr ""
+msgstr "Solicitando a su %{provider} los repositorios fallados"
msgid "ImportProjects|Select the projects you want to import"
-msgstr ""
+msgstr "Seleccione los proyectos que desea importar"
+
+msgid "ImportProjects|The remote data could not be imported."
+msgstr "No se pudieron importar los datos remotos."
+
+msgid "ImportProjects|The repository could not be created."
+msgstr "No se pudo crear el repositorio."
msgid "ImportProjects|Updating the imported projects failed"
+msgstr "Se ha producido un error al actualizar los proyectos importados"
+
+msgid "Improve Issue boards"
msgstr ""
msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgstr "Mejore los tableros de incidencias con GitLab Enterprise Edition."
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
-msgstr ""
+msgstr "Mejore los merge request y la atención al cliente con GitLab Enterprise Edition."
msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
-msgstr ""
+msgstr "Mejore la gestión de incidencias con Issue weight y GitLab Enterprise Edition."
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
-msgstr ""
+msgstr "Mejore la búsqueda con Advanced Global Search y GitLab Enterprise Edition."
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
-msgstr ""
+msgstr "Con el fin de permitir el análisis a nivel de instancia, por favor solicite a un administrador que habilite %{usage_ping_link_start}el uso de ping%{usage_ping_link_end}."
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
-msgstr ""
+msgstr "Con el fin de recopilar datos precisos sobre los datos de uso, es posible que tarde de 1 a 2 semanas en poder ver su índice."
msgid "In the next step, you'll be able to select the projects you want to import."
-msgstr ""
+msgstr "En el siguiente paso, podrá seleccionar los proyectos que desea importar."
msgid "Incidents"
msgstr "Incidentes"
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
-msgstr ""
+msgstr "Incluya un acuerdo de términos de servicio y una política de privacidad que todos los usuarios deben aceptar."
msgid "Include author name in notification email body"
msgstr "Incluir el nombre del autor en el cuerpo del correo electrónico de notificación"
@@ -6077,28 +7060,37 @@ msgid "Include merge request description"
msgstr "Introduzca la descripción del merge request"
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
-msgstr ""
+msgstr "Incluya el nombre de usuario en la URL en caso de que sea necesario: <code>https://nombredeusuario@gitlab.empresa.com/grupo/proyecto.git</code>."
msgid "Includes LFS objects. It can be overridden per group, or per project. 0 for unlimited."
-msgstr ""
+msgstr "Incluye objetos LFS. Se puede sobreescribir a nivel de grupo o de proyecto. Puede establecerse a 0 para hacer que este valor sea ilimitado."
msgid "Includes an MVC structure to help you get started."
-msgstr ""
+msgstr "Incluye una estructura MVC para ayudarle a comenzar."
msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
-msgstr ""
+msgstr "Incluye una estructura MVC, Gemfile, Rakefile, junto con muchos otros, para ayudarlo a comenzar."
msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
-msgstr ""
+msgstr "Incluye una estructura MVC, mvnw y pom.xml para ayudarle a comenzar."
msgid "Incompatible Project"
msgstr "Proyecto incompatible"
+msgid "Incompatible options set!"
+msgstr "¡Conjunto de opciones incompatibles configuradas!"
+
+msgid "Indexing"
+msgstr "Indexando"
+
msgid "Indicates whether this runner can pick jobs without tags"
-msgstr ""
+msgstr "Indica si este ejecutor puede seleccionar trabajos sin etiquetas"
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
-msgstr ""
+msgstr "Informa a los usuarios que no hayan cargado las claves SSH que no pueden hacer push sobre SSH hasta que se agregue una"
+
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr "Puede encontrar información sobre plantillas de Pages adicionales y cómo instalarlas en nuestro %{pages_getting_started_guide}."
msgid "Inline"
msgstr "En línea"
@@ -6107,10 +7099,10 @@ msgid "Input host keys manually"
msgstr ""
msgid "Input your repository URL"
-msgstr ""
+msgstr "Introduzca la URL de su repositorio"
msgid "Insert a quote"
-msgstr ""
+msgstr "Insertar una cita"
msgid "Insert code"
msgstr "Insertar código"
@@ -6119,6 +7111,9 @@ msgid "Insert suggestion"
msgstr "Insertar sugerencia"
msgid "Insights"
+msgstr "Insights"
+
+msgid "Install"
msgstr ""
msgid "Install GitLab Runner"
@@ -6127,6 +7122,15 @@ msgstr "Instalar GitLab Runner"
msgid "Install Runner on Kubernetes"
msgstr "Instalar Gitlab Runner en Kubernetes"
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] "Instancia"
@@ -6142,7 +7146,7 @@ msgid "Instance does not support multiple Kubernetes clusters"
msgstr "La instancia no soporta múltiples clústeres de Kubernetes"
msgid "Instance license"
-msgstr ""
+msgstr "Licencia de la instancia"
msgid "Integrations"
msgstr "Integraciones"
@@ -6172,29 +7176,56 @@ msgid "Introducing Cycle Analytics"
msgstr "Introducción a Cycle Analytics"
msgid "Introducing Your Conversational Development Index"
-msgstr ""
+msgstr "Presentando su índice de desarrollo conversacional"
+
+msgid "Invalid Insights config file detected"
+msgstr "Archivo de configuración de Insights no válido detectado"
msgid "Invalid Login or password"
+msgstr "Inicio de sesión o contraseña no válida"
+
+msgid "Invalid date"
msgstr ""
+msgid "Invalid feature"
+msgstr "Característica no válida"
+
+msgid "Invalid field"
+msgstr "Campo no válido"
+
msgid "Invalid file."
-msgstr ""
+msgstr "Archivo no válido."
+
+msgid "Invalid import params"
+msgstr "Parámetros de importación no válidos"
msgid "Invalid input, please avoid emojis"
-msgstr ""
+msgstr "Entrada no válida, por favor, evite los emojis"
msgid "Invalid pin code"
+msgstr "Código PIN inválido."
+
+msgid "Invalid query"
msgstr ""
-msgid "Invalid two-factor code."
+msgid "Invalid repository path"
+msgstr "Ruta del repositorio no válida"
+
+msgid "Invalid server response"
msgstr ""
+msgid "Invalid two-factor code."
+msgstr "Código de dos factores no válido."
+
msgid "Invitation"
msgstr "Invitación"
msgid "Invite"
msgstr "Invitar"
+msgid "Invite \"%{trimmed}\" by email"
+msgstr "Invitar a \"%{trimmed}\" por correo electrónico"
+
msgid "Invite group"
msgstr "Invitar al grupo"
@@ -6205,10 +7236,13 @@ msgid "Invoke Count"
msgstr ""
msgid "Invoke Time"
-msgstr ""
+msgstr "Tiempo de invocación"
+
+msgid "Is using license seat:"
+msgstr "Está usando el asiento de licencia:"
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
-msgstr ""
+msgstr "Cerrado (%{moved_link_start}movido%{moved_link_end})"
msgid "Issue"
msgstr "Incidencia"
@@ -6223,6 +7257,12 @@ msgid "Issue events"
msgstr "Eventos de incidencia"
msgid "Issue template (optional)"
+msgstr "Plantilla de la incidencia (opcional)"
+
+msgid "Issue update failed"
+msgstr "Se ha producido un error al actualizar incidencia"
+
+msgid "Issue was closed by %{name} %{reason}"
msgstr ""
msgid "IssueBoards|Board"
@@ -6232,55 +7272,55 @@ msgid "IssueBoards|Boards"
msgstr "Tableros"
msgid "IssueBoards|Create new board"
-msgstr ""
+msgstr "Crear nuevo tablero"
msgid "IssueBoards|Delete board"
-msgstr ""
+msgstr "Eliminar tablero"
msgid "IssueBoards|No matching boards found"
-msgstr ""
+msgstr "No se encontraron tableros coincidentes"
msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
-msgstr ""
+msgstr "Algunos de sus tableros están ocultos, active una licencia para verlos de nuevo."
msgid "IssueBoards|Switch board"
-msgstr ""
+msgstr "Cambiar tablero"
msgid "Issues"
msgstr "Incidencias"
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
-msgstr ""
+msgstr "Las incidencias pueden ser errores, tareas o ideas para ser discutidas. Además, las mismas, pueden ser buscadas y filtradas."
msgid "Issues closed"
msgstr "Incidencias cerradas"
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
-msgstr ""
+msgstr "Incidencias con comentarios, merge requests con diffs y comentarios, etiquetas, hitos, fragmentos de código y otras entidades de proyecto"
msgid "Issues, merge requests, pushes, and comments."
-msgstr ""
+msgstr "Incidencias, merge requests, pushes y comentarios."
msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
-msgstr ""
+msgstr "Una vez haya comenzado a crear incidencias, podremos iniciar el seguimiento y mostrar distintas métricas para sus proyectos"
msgid "IssuesAnalytics|Issues Created"
-msgstr ""
+msgstr "Incidencias creadas"
msgid "IssuesAnalytics|Issues created per month"
-msgstr ""
+msgstr "Incidencias creadas por mes"
msgid "IssuesAnalytics|Last 12 months"
-msgstr ""
+msgstr "Últimos 12 meses"
msgid "IssuesAnalytics|Sorry, your filter produced no results"
msgstr "Lo sentimos, su filtro no ha producido ningún resultado."
msgid "IssuesAnalytics|There are no issues for the projects in your group"
-msgstr ""
+msgstr "No hay incidencias para los proyectos contenidos en su grupo"
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
-msgstr ""
+msgstr "Para ampliar su búsqueda, cambie o elimine los filtros en la barra de filtros que se muestra en la parte superior"
msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
msgstr ""
@@ -6292,7 +7332,7 @@ msgid "Jaeger URL"
msgstr "URL de Jaeger"
msgid "Jaeger tracing"
-msgstr ""
+msgstr "Trazabilidad de Jaeger"
msgid "Jan"
msgstr "Ene"
@@ -6300,41 +7340,83 @@ msgstr "Ene"
msgid "January"
msgstr "Enero"
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr "Los eventos para %{noteable_model_name} están deshabilitados."
+
+msgid "JiraService|If different from Web URL"
+msgstr "Si es diferente de la URL Web"
+
+msgid "JiraService|JIRA API URL"
+msgstr "URL del API de JIRA"
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr "Los comentarios de JIRA se crearán cuando se haga referencia a una incidencia en un commit."
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr "Los comentarios de JIRA se crearán cuando se haga referencia a una incidencia en un commit."
+
+msgid "JiraService|Jira issue tracker"
+msgstr "Gestos de incidencias Jira"
+
+msgid "JiraService|Password or API token"
+msgstr "Contraseña o token del API"
+
+msgid "JiraService|Transition ID(s)"
+msgstr "ID(s) de transición"
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr "Utilice , o ; para separar múltiples IDs de transición"
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr "Utilice una contraseña para la versión servidor y un token API para la versión en la nube"
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr "Utilice una contraseña para la versión servidor y un correo electrónico para la versión en la nube"
+
+msgid "JiraService|Username or Email"
+msgstr "Nombre de usuario o correo electrónico"
+
+msgid "JiraService|Web URL"
+msgstr "URL web"
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr "los ids de transición sólo pueden contener números que se puedan separar mediante , o ;"
+
msgid "Job"
msgstr "Trabajo"
msgid "Job Failed #%{build_id}"
-msgstr ""
+msgstr "Trabajo fallido #%{build_id}"
msgid "Job ID"
-msgstr ""
+msgstr "Id del trabajo"
msgid "Job has been erased"
msgstr "El trabajo ha sido eliminado"
msgid "Job has been successfully erased!"
-msgstr ""
+msgstr "¡El trabajo se ha borrado correctamente!"
msgid "Job has wrong arguments format."
-msgstr ""
+msgstr "El trabajo tiene el formato de argumentos erróneo."
msgid "Job is missing the `model_type` argument."
-msgstr ""
+msgstr "El trabajo no tiene definido el argumento `model_type`."
msgid "Job is stuck. Check runners."
-msgstr ""
+msgstr "El trabajo está bloqueado. Por favor, compruebe los ejecutores."
msgid "Job traces and artifacts"
-msgstr ""
+msgstr "Registros de los trabajos y artefactos"
msgid "Job was retried"
-msgstr ""
+msgstr "Se reintentó el trabajo"
msgid "Jobs"
msgstr "Trabajos"
msgid "Job|Browse"
-msgstr ""
+msgstr "Explorar"
msgid "Job|Complete Raw"
msgstr ""
@@ -6343,52 +7425,52 @@ msgid "Job|Download"
msgstr "Descargar"
msgid "Job|Erase job log"
-msgstr ""
+msgstr "Borrar el registro del trabajo"
msgid "Job|Job artifacts"
-msgstr ""
+msgstr "Artefactos del trabajo"
msgid "Job|Job has been erased"
-msgstr ""
+msgstr "Se ha eliminado el trabajo"
msgid "Job|Job has been erased by"
-msgstr ""
+msgstr "El trabajo ha sido borrado por"
msgid "Job|Keep"
msgstr "Mantener"
msgid "Job|Pipeline"
-msgstr ""
+msgstr "Pipeline"
msgid "Job|Scroll to bottom"
-msgstr ""
+msgstr "Desplazar hacia abajo"
msgid "Job|Scroll to top"
-msgstr ""
+msgstr "Desplazar hacia arriba"
msgid "Job|Show complete raw"
-msgstr ""
+msgstr "Mostrar trabajo completo en crudo"
msgid "Job|The artifacts were removed"
-msgstr ""
+msgstr "Se han eliminado los artefactos"
msgid "Job|The artifacts will be removed"
-msgstr ""
+msgstr "Los artefactos serán eliminados"
msgid "Job|This job failed because the necessary resources were not successfully created."
-msgstr ""
+msgstr "Este trabajo falló porque los recursos necesarios no se crearon correctamente."
msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
-msgstr ""
+msgstr "Este trabajo está bloqueado porque el proyecto no tiene ningún ejecutor en línea asignado a él."
msgid "Job|for"
-msgstr ""
+msgstr "Trabajo para"
msgid "Job|into"
-msgstr ""
+msgstr "en"
msgid "Job|with"
-msgstr ""
+msgstr "con"
msgid "Jul"
msgstr "Jul"
@@ -6396,6 +7478,12 @@ msgstr "Jul"
msgid "July"
msgstr "Julio"
+msgid "Jump to first unresolved discussion"
+msgstr "Ir a la primera discusión sin resolver"
+
+msgid "Jump to next unresolved discussion"
+msgstr "Ir a la siguiente discusión sin resolver"
+
msgid "Jun"
msgstr "Jun"
@@ -6405,6 +7493,9 @@ msgstr "Junio"
msgid "Key (PEM)"
msgstr "Clave (PEM)"
+msgid "Key: %{key}"
+msgstr "Clave: %{key}"
+
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -6421,25 +7512,31 @@ msgid "Kubernetes cluster integration was not removed."
msgstr "No se ha eliminado la integración del clúster de Kubernetes."
msgid "Kubernetes cluster integration was successfully removed."
-msgstr ""
+msgstr "La integración del clúster de Kubernetes se eliminó correctamente."
msgid "Kubernetes cluster was successfully updated."
-msgstr ""
+msgstr "El clúster de Kubernetes se actualizó correctamente."
msgid "Kubernetes configured"
msgstr "Kubernetes configurado"
+msgid "Kubernetes error: %{error_code}"
+msgstr "Error de Kubernetes: %{error_code}"
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
-msgstr ""
+msgstr "La integración del servicio de Kubernetes ha quedado obsoleta. %{deprecated_message_content} sus clústeres de Kubernetes con la nueva página de <a href=\"%{url}\"/>Clústers de Kubernetes</a>"
msgid "LDAP settings"
msgstr "Configuración LDAP"
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr "Sincronización LDAP en curso. Esto podría tardar unos minutos. Por favor, actualice la página para ver los cambios."
+
msgid "LFS"
msgstr "LFS"
msgid "LFS objects"
-msgstr ""
+msgstr "Objetos LFS"
msgid "LFSStatus|Disabled"
msgstr "Deshabilitado"
@@ -6447,6 +7544,9 @@ msgstr "Deshabilitado"
msgid "LFSStatus|Enabled"
msgstr "Habilitado"
+msgid "LICENSE"
+msgstr "LICENCIA"
+
msgid "Label"
msgstr "Etiqueta"
@@ -6454,22 +7554,22 @@ msgid "Label actions dropdown"
msgstr ""
msgid "Label lists show all issues with the selected label."
-msgstr ""
+msgstr "Las listas de etiquetas muestran todas las incidencias con las etiquetas seleccionadas."
msgid "Label was created"
-msgstr ""
+msgstr "Etiqueta creada"
msgid "Label was removed"
-msgstr ""
+msgstr "Etiqueta eliminada"
msgid "Label was successfully updated."
-msgstr ""
+msgstr "La etiqueta se ha actualizada con éxito."
msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
-msgstr ""
+msgstr "%{firstLabelName} +%{remainingLabelCount} más"
msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
-msgstr ""
+msgstr "%{labelsString}} +%{remainingLabelCount} más"
msgid "LabelSelect|Labels"
msgstr "Etiquetas"
@@ -6478,23 +7578,26 @@ msgid "Labels"
msgstr "Etiquetas"
msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
-msgstr ""
+msgstr "Las etiquetas se pueden aplicar a %{features}. Las etiquetas de los grupos se encuentran disponibles para cualquier proyecto dentro del grupo."
msgid "Labels can be applied to issues and merge requests to categorize them."
-msgstr ""
+msgstr "Las etiquetas se pueden aplicar a incidencias y merge requests para categorizarlos."
msgid "Labels can be applied to issues and merge requests."
-msgstr ""
+msgstr "Las etiquetas se pueden aplicar a las incidencias y a los merge requests."
msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
-msgstr ""
+msgstr "<span>¿Promocionar la etiqueta</span> %{labelTitle} <span>a etiqueta de grupo?</span>"
msgid "Labels|Promote Label"
-msgstr ""
+msgstr "Promocionar etiqueta"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr "Y %{count} más"
+
msgid "Language"
msgstr "Idioma"
@@ -6509,6 +7612,9 @@ msgstr[1] "Últimos %d días"
msgid "Last Pipeline"
msgstr "Último Pipeline"
+msgid "Last accessed on"
+msgstr "Último acceso"
+
msgid "Last activity"
msgstr "Última actividad"
@@ -6519,7 +7625,7 @@ msgid "Last contact"
msgstr "Último contacto"
msgid "Last edited %{date}"
-msgstr ""
+msgstr "Última edición el %{date}"
msgid "Last edited by %{name}"
msgstr "Última edición por %{name}"
@@ -6536,6 +7642,12 @@ msgstr "Última actualización"
msgid "Last updated"
msgstr "Última actualización"
+msgid "Last used"
+msgstr "Utilizado por última vez"
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr "Ha hecho push a"
@@ -6546,19 +7658,25 @@ msgid "Latest changes"
msgstr "Últimos cambios"
msgid "Latest pipeline for this branch"
-msgstr ""
+msgstr "Último pipeline para este branch"
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr "Aprenda GitLab"
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr "Aprenda como contribuir %{link_start}a las plantillas integradas%{link_end}"
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
-msgstr ""
+msgstr "Aprenda como %{no_packages_link_start}publicar y compartir sus paquetes%{no_packages_link_end} con GitLab."
msgid "Learn more"
msgstr "Conozca más"
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
-msgstr ""
+msgstr "Obtenga más información sobre %{issue_boards_url}, para realizar un seguimiento de las incidencias en varias listas, mediante el uso de etiquetas, asignaciones e hitos. Si echa en falta alguna incidencia, en los tableros de incidencias, por favor cree un incidencia en %{gitlab_issues_url}."
msgid "Learn more about Auto DevOps"
msgstr "Aprenda más sobre Auto DevOps"
@@ -6569,16 +7687,22 @@ msgstr "Aprenda más acerca de Kubernetes"
msgid "Learn more about Web Terminal"
msgstr "Aprenda más sobre la Terminal Web"
-msgid "Learn more about approvals."
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Learn more about approvals."
+msgstr "Obtenga más información sobre las aprobaciones."
+
msgid "Learn more about custom project templates"
-msgstr ""
+msgstr "Más información sobre las plantillas de proyecto personalizadas"
msgid "Learn more about group-level project templates"
-msgstr ""
+msgstr "Obtenga más información sobre las plantillas de proyectos a nivel de grupo"
msgid "Learn more about signing commits"
+msgstr "Más información sobre los commits firmados"
+
+msgid "Learn more about the dependency list"
msgstr ""
msgid "Learn more in the"
@@ -6591,7 +7715,7 @@ msgid "Leave"
msgstr "Abandonar"
msgid "Leave edit mode? All unsaved changes will be lost."
-msgstr ""
+msgstr "¿Desea salir del modo de edición? Se perderán todos los cambios no guardados."
msgid "Leave group"
msgstr "Abandonar grupo"
@@ -6600,6 +7724,12 @@ msgid "Leave project"
msgstr "Abandonar proyecto"
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
+msgstr "Deja las opciones \"Tipo de archivo\" y \"Método de entrega\" con sus valores por defecto."
+
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr "Let's Encrypt no acepta correos electrónicos de example.com"
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
msgid "License"
@@ -6609,31 +7739,31 @@ msgid "LicenseManagement|Add a license"
msgstr "Añadir licencia"
msgid "LicenseManagement|Add licenses manually to approve or blacklist"
-msgstr ""
+msgstr "Añadir licencias manualmente para aprobar o agregar la licencia a la lista negra"
msgid "LicenseManagement|Approve"
-msgstr ""
+msgstr "Aprobar"
msgid "LicenseManagement|Approve license"
-msgstr ""
+msgstr "Aprobar licencia"
msgid "LicenseManagement|Approve license?"
-msgstr ""
+msgstr "¿Aprobar licencia?"
msgid "LicenseManagement|Approved"
msgstr "Aprobado"
msgid "LicenseManagement|Blacklist"
-msgstr ""
+msgstr "Lista negra"
msgid "LicenseManagement|Blacklist license"
-msgstr ""
+msgstr "Lista Negra"
msgid "LicenseManagement|Blacklist license?"
-msgstr ""
+msgstr "¿Bloquear licencia?"
msgid "LicenseManagement|Blacklisted"
-msgstr ""
+msgstr "Bloqueada"
msgid "LicenseManagement|Cancel"
msgstr "Cancelar"
@@ -6677,20 +7807,26 @@ msgstr "URL"
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr "Está a punto de eliminar la licencia, %{name}, de este proyecto."
+msgid "Licensed Features"
+msgstr "Características licenciadas"
+
msgid "Licensed to"
-msgstr ""
+msgstr "Licenciado a"
msgid "Licenses"
msgstr "Licencias"
msgid "Limit namespaces and projects that can be indexed"
-msgstr ""
+msgstr "Limitar los espacios de nombres y los proyectos que se pueden indexar"
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
msgstr[0] "Limitado a mostrar %d evento como máximo"
msgstr[1] "Limitado a mostrar %d eventos como máximo"
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -6704,7 +7840,7 @@ msgid "List available repositories"
msgstr "Lista de repositorios disponibles"
msgid "List of IPs and CIDRs of allowed secondary nodes. Comma-separated, e.g. \"1.1.1.1, 2.2.2.0/24\""
-msgstr ""
+msgstr "Lista de IPs y CIDRs permitidos de los nodos secundarios. Separados por comas, por ejemplo, \"1.1.1.1, 2.2.2.0/24\""
msgid "List view"
msgstr "Vista de lista"
@@ -6721,6 +7857,9 @@ msgstr "Vista previa"
msgid "Loading contribution stats for group members"
msgstr "Cargando las estadísticas de las colaboraciones de los miembros del grupo"
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr "Cargando el IDE de GitLab..."
@@ -6742,6 +7881,9 @@ msgstr "Bloquear %{issuableDisplayName}"
msgid "Lock not found"
msgstr "Bloqueo no encontrado"
+msgid "Lock the discussion"
+msgstr "Bloquear la discusión"
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr "¿Bloquear este %{issuableDisplayName}? Sólo los <strong>miembros del proyecto</strong> podrán comentar."
@@ -6760,11 +7902,14 @@ msgstr "Bloqueado a los proyectos actuales"
msgid "Locks give the ability to lock specific file or folder."
msgstr "Los bloqueos brindan la capacidad de bloquear archivos o carpetas específicos."
+msgid "Locks the discussion"
+msgstr "Bloquear la discusión"
+
msgid "Login with smartcard"
msgstr "Iniciar sesión con una tarjeta inteligente"
msgid "Logo was successfully removed."
-msgstr ""
+msgstr "El logotipo se ha eliminado correctamente."
msgid "Logs"
msgstr "Logs"
@@ -6773,25 +7918,34 @@ msgid "MRApprovals|Approved by"
msgstr "Aprobado por"
msgid "MRApprovals|Approvers"
-msgstr ""
+msgstr "Aprobadores"
msgid "MRApprovals|Pending approvals"
-msgstr ""
+msgstr "Aprobaciones pendientes"
msgid "MRDiff|Show changes only"
-msgstr ""
+msgstr "Mostrar sólo los cambios"
msgid "MRDiff|Show full file"
-msgstr ""
+msgstr "Mostrar el archivo completo"
+
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr "Realice y revise los cambios en el navegador con el Web IDE"
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr "Haga que todos en su equipo sean más productivos, independientemente de su ubicación. GitLab Geo crea réplicas de solo lectura de su instancia de GitLab para que pueda reducir el tiempo que lleva clonar y obtener grandes repositorios."
+msgid "Make issue confidential."
+msgstr "Hacer esta incidencia confidencial."
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr "Asegúrese de haber iniciado sesión en la cuenta que posee los proyectos que desea importar."
+msgid "Makes this issue confidential"
+msgstr "Hace este incidencia confidencial"
+
msgid "Manage"
-msgstr ""
+msgstr "Administrar"
msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
msgstr "Administre los repositorios de Git con controles de acceso detallados que mantienen su código seguro. Realice revisiones de código y mejore la colaboración con merge request. Cada proyecto también puede tener una herramienta de gestión de incidencias y un wiki."
@@ -6806,10 +7960,10 @@ msgid "Manage all notifications"
msgstr "Administrar todas las notificaciones"
msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
-msgstr ""
+msgstr "Administre aplicaciones que puedan utilizar GitLab como proveedor OAuth, y aplicaciones que haya autorizado para utilizar su cuenta."
msgid "Manage applications that you've authorized to use your account."
-msgstr ""
+msgstr "Administre las aplicaciones que haya autorizado a utilizar su cuenta."
msgid "Manage group labels"
msgstr "Administrar etiquetas de grupo"
@@ -6850,6 +8004,15 @@ msgstr "Marzo"
msgid "March"
msgstr "Marzo"
+msgid "Mark as resolved"
+msgstr "Marcar como resuelto"
+
+msgid "Mark comment as resolved"
+msgstr "Marcar comentario como resuelto"
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr "Marque esta incidencia como duplicada de otra incidencia"
+
msgid "Mark todo as done"
msgstr "Marcar tarea pendiente como completada"
@@ -6857,11 +8020,20 @@ msgid "Markdown"
msgstr "Markdown"
msgid "Markdown Help"
-msgstr ""
+msgstr "Ayuda de Markdown"
msgid "Markdown enabled"
msgstr "Markdown habilitado"
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr "Marca esta incidencia como un duplicada de %{duplicate_reference}."
+
+msgid "Marks todo as done."
+msgstr "Marcar tarea pendiente como completada."
+
+msgid "Match not found; try refining your search query."
+msgstr "No se encontró la coincidencia; por favor refine la consulta de su búsqueda."
+
msgid "Maven Metadata"
msgstr "Metadatos de Maven"
@@ -6869,7 +8041,7 @@ msgid "Max access level"
msgstr "Nivel de acceso máximo"
msgid "Max seats used"
-msgstr ""
+msgstr "Máximo de puestos utilizados"
msgid "Maximum artifacts size (MB)"
msgstr "Tamaño máximo de los artefactos (MB)"
@@ -6884,16 +8056,19 @@ msgid "Maximum delay (Minutes)"
msgstr "Retraso máximo (minutos)"
msgid "Maximum job timeout"
-msgstr ""
+msgstr "Tiempo de espera máximo para el trabajo"
+
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr "El tiempo de espera máximo para los trabajos tiene un valor que no puede ser aceptado"
msgid "Maximum number of mirrors that can be synchronizing at the same time."
-msgstr ""
+msgstr "Número máximo de réplicas que se pueden sincronizar al mismo tiempo."
msgid "Maximum push size (MB)"
-msgstr ""
+msgstr "Tamaño máximo para los archivos a subir al ejecutar un comando push (MB)"
msgid "Maximum time between updates that a mirror can have when scheduled to synchronize."
-msgstr ""
+msgstr "El tiempo máximo entre las actualizaciones que puede esperar una réplica cuando está programada para sincronizarse."
msgid "May"
msgstr "Mayo"
@@ -6902,7 +8077,7 @@ msgid "Median"
msgstr "Mediana"
msgid "Member lock"
-msgstr ""
+msgstr "Bloqueo de miembros"
msgid "Member since %{date}"
msgstr "Miembro desde %{date}"
@@ -6911,9 +8086,12 @@ msgid "Members"
msgstr "Miembros"
msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
-msgstr ""
+msgstr "Los miembros se pueden añadir por proyecto <i>Mantenedores</i> o <i>Propietarios</i>"
msgid "Members of <strong>%{project_name}</strong>"
+msgstr "Miembros de <strong>%{project_name}</strong>"
+
+msgid "Merge"
msgstr ""
msgid "Merge Request"
@@ -6928,35 +8106,23 @@ msgstr "Merge requests"
msgid "Merge Requests created"
msgstr "Solicitudes de merge creadas"
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
-msgstr ""
-
-msgid "Merge commit with semi-linear history"
-msgstr ""
+msgstr "Mensaje del merge commit"
msgid "Merge events"
msgstr "Eventos de merge"
msgid "Merge immediately"
-msgstr ""
+msgstr "Realizar merge inmediatamente"
msgid "Merge in progress"
-msgstr ""
-
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
+msgstr "Merge en progreso"
msgid "Merge request"
msgstr "Merge request"
msgid "Merge request approvals"
-msgstr ""
+msgstr "Aprobar los merge request"
msgid "Merge request approvals allow you to set the number of necessary approvals and predefine a list of approvers that will need to approve every merge request in a project."
msgstr ""
@@ -6968,38 +8134,68 @@ msgid "Merge requests are a place to propose changes you've made to a project an
msgstr "Los merge request son un lugar para proponer los cambios que ha realizado en un proyecto y discutir esos cambios con otros miembros"
msgid "Merge when pipeline succeeds"
+msgstr "Ejecutar merge cuando el pipeline se ejecute con éxito"
+
+msgid "MergeConflict|Commit to source branch"
+msgstr "Commit a la rama origen"
+
+msgid "MergeConflict|Committing..."
+msgstr "Realizando commit..."
+
+msgid "MergeConflict|HEAD//our changes"
msgstr ""
-msgid "MergeRequests|Add a reply"
+msgid "MergeConflict|Use ours"
+msgstr "Utilizar el nuestro"
+
+msgid "MergeConflict|Use theirs"
+msgstr "Utilizar el suyo"
+
+msgid "MergeConflict|conflict"
+msgstr "conflicto"
+
+msgid "MergeConflict|conflicts"
+msgstr "conflictos"
+
+msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequests|Add a reply"
+msgstr "Añadir una respuesta"
+
msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr "Se ha producido un error al guardar el borrador del comentario."
msgid "MergeRequests|Discussion stays resolved"
-msgstr ""
+msgstr "La discusión permanece resuelta"
msgid "MergeRequests|Discussion stays unresolved"
-msgstr ""
+msgstr "La discusión permanece sin resolver"
msgid "MergeRequests|Discussion will be resolved"
-msgstr ""
+msgstr "Se resolverá la discusión"
msgid "MergeRequests|Discussion will be unresolved"
+msgstr "La discusión no se resolverá"
+
+msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
msgid "MergeRequests|Jump to next unresolved discussion"
-msgstr ""
+msgstr "Saltar a la siguiente discusión sin resolver"
msgid "MergeRequests|Reply..."
msgstr "Responder..."
msgid "MergeRequests|Resolve this discussion in a new issue"
-msgstr ""
+msgstr "Resolver esta discusión en una nueva incidencia"
msgid "MergeRequests|Saving the comment failed"
msgstr "Se ha producido un error al guardar el comentario"
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr "Alternar los comentarios para este archivo"
@@ -7010,31 +8206,31 @@ msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr "Ver el archivo reemplazado @ %{commitId}"
msgid "MergeRequests|commented on commit %{commitLink}"
-msgstr ""
+msgstr "comentado en el commit %{commitLink}"
msgid "MergeRequests|started a discussion"
-msgstr ""
+msgstr "comenzó una discusión"
msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
-msgstr ""
+msgstr "Comenzó una discusión en %{linkStart}una versión antigua del diff%{linkEnd}"
msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
-msgstr ""
+msgstr "Inició una discusión en %{linkStart}el dif%{linkEnd}"
msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
-msgstr ""
+msgstr "comenzó una discusión sobre un cambio desactualizado en el commit %{linkStart}%{commitId}%{linkEnd}"
msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
-msgstr ""
+msgstr "comenzó una discusión en el commit %{linkStart}%{commitId}%{linkEnd}"
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
-msgstr ""
+msgstr "%{paragraphStart}cambió la descripción %{descriptionChangedTimes} veces %{timeDifferenceMinutes}%{paragraphEnd}"
msgid "MergeRequest|Error loading full diff. Please try again."
-msgstr ""
+msgstr "Se ha producido un error al cargar el diff completo. Por favor, inténtalo de nuevo."
-msgid "MergeRequest|Filter files"
-msgstr ""
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
+msgstr "Filtrar archivos o buscar con %{modifier_key}+ p"
msgid "MergeRequest|No files found"
msgstr "No se encontraron archivos"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr "Mensajes"
+msgid "Metric was successfully added."
+msgstr "La métrica se añadió correctamente."
+
+msgid "Metric was successfully updated."
+msgstr "La métrica se actualizó correctamente."
+
msgid "Metrics"
msgstr "Métricas"
@@ -7058,11 +8260,14 @@ msgid "Metrics - Prometheus"
msgstr "Métricas - Prometheus"
msgid "Metrics and profiling"
-msgstr ""
+msgstr "Métricas e informes"
msgid "Metrics for environment"
msgstr "Métricas para el entorno"
+msgid "Metrics|Add metric"
+msgstr "Añadir métrica"
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "Consulte la documentación de CI/CD sobre la implementación en un entorno"
@@ -7085,7 +8290,7 @@ msgid "Metrics|For grouping similar metrics"
msgstr "Para agrupar métricas similares"
msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
-msgstr ""
+msgstr "Etiqueta del eje Y (normalmente la unidad). El eje X siempre representa el tiempo."
msgid "Metrics|Learn about environments"
msgstr "Aprenda sobre los entornos"
@@ -7102,9 +8307,6 @@ msgstr "Nueva métrica"
msgid "Metrics|No deployed environments"
msgstr "No hay entornos desplegados"
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr "La consulta PromQL es válida"
@@ -7112,28 +8314,28 @@ msgid "Metrics|Prometheus Query Documentation"
msgstr "Documentción sobre las consultas de Prometheus"
msgid "Metrics|Show last"
-msgstr ""
+msgstr "Mostrar último"
msgid "Metrics|There was an error fetching the environments data, please try again"
msgstr "Se ha producido un error al recuperar los datos de los distintos entornos, por favor inténtelo de nuevo"
msgid "Metrics|There was an error getting deployment information."
-msgstr ""
+msgstr "Se ha producido un error al obtener información sobre los despliegues."
msgid "Metrics|There was an error getting environments information."
-msgstr ""
+msgstr "Se ha producido un error al obtener información sobre los entornos."
msgid "Metrics|There was an error trying to validate your query"
-msgstr ""
+msgstr "Se ha producido un error al intentar validar su consulta"
msgid "Metrics|There was an error while retrieving metrics"
-msgstr ""
+msgstr "Se ha producido un error al obtener las métricas"
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
-msgstr ""
+msgstr "Se ha producido una respuesta inesperada de los datos de las métricas desde el endpoint de Prometheus"
msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
-msgstr ""
+msgstr "Se ha producido una respuesta inesperada de los datos de las métricas desde el endpoint de Prometheus"
msgid "Metrics|Unit label"
msgstr "Etiqueta de las unidades"
@@ -7142,90 +8344,120 @@ msgid "Metrics|Used as a title for the chart"
msgstr "Utilizado como título para el gráfico"
msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
-msgstr ""
+msgstr "Se utiliza si la consulta devuelve una sola serie. Si devuelve varias series, la leyenda de sus etiquetas sera seleccionada de la respuesta."
msgid "Metrics|Y-axis label"
msgstr "Etiqueta del eje Y"
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
-msgstr ""
+msgstr "Está a punto de eliminar permanentemente esta métrica. Esta acción no se puede deshacer."
+
+msgid "Metrics|e.g. HTTP requests"
+msgstr "Por ejemplo, solicitudes HTTP"
+
+msgid "Metrics|e.g. Requests/second"
+msgstr "Peticiones/segundo"
msgid "Metrics|e.g. Throughput"
msgstr "por ejemplo, rendimiento"
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr "por ejemplo, tasa (http_requests_total[5m])"
+
+msgid "Metrics|e.g. req/sec"
+msgstr "por ejemplo, req/seg."
+
msgid "Migrated %{success_count}/%{total_count} files."
-msgstr ""
+msgstr "Migrados %{success_count}/%{total_count} archivos."
msgid "Migration successful."
-msgstr ""
+msgstr "Migración correcta."
msgid "Milestone"
msgstr "Hito"
msgid "Milestone lists not available with your current license"
-msgstr ""
+msgstr "Las listas de hitos no están disponibles con tu licencia actual"
msgid "Milestone lists show all issues from the selected milestone."
-msgstr ""
+msgstr "Las listas de hitos muestran todas las incidencias desde el hito seleccionado."
msgid "Milestones"
msgstr "Hitos"
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
-msgstr ""
+msgstr "Está a punto de eliminar permanentemente el hito %{milestoneTitle} y eliminarlo de %{issuesWithCount} y %{mergeRequestsWithCount}. Una vez eliminado, no se podrá deshacer la operación ni recuperar el hito eliminado."
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
-msgstr ""
-
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
+msgstr "Está a punto de eliminar permanentemente el hito %{milestoneTitle}. Este hito no está siendo utilizado actualmente en ninguna incidencia ni en ningún merge request."
msgid "Milestones|Delete milestone"
msgstr "Eliminar hito"
msgid "Milestones|Delete milestone %{milestoneTitle}?"
-msgstr ""
+msgstr "¿Desea eliminar el hito %{milestoneTitle}?"
msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
-msgstr ""
+msgstr "Se ha producido un error al eliminar el hito %{milestoneTitle}"
msgid "Milestones|Milestone %{milestoneTitle} was not found"
-msgstr ""
+msgstr "No se puede encontrar el hito %{milestoneTitle}"
msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
-msgstr ""
+msgstr "¿Promocionar %{milestoneTitle} para agrupar el hito?"
msgid "Milestones|Promote Milestone"
-msgstr ""
+msgstr "Hitos|Promover hito"
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
-msgstr ""
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
+msgstr "Promover a %{milestoneTitle} lo hará disponible para todos los proyectos dentro de %{groupName}. Los hitos de proyecto existentes con el mismo nombre serán fusionados."
msgid "Milestones|This action cannot be reversed."
-msgstr ""
+msgstr "Esta acción no se puede deshacer"
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
-msgstr ""
+msgstr "Capacidad mínima que debe estar disponible antes de que programemos más mirrors de forma preventiva."
+
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr "La longitud mínima es de %{minimum_password_length} caracteres"
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr "La longitud mínima es de %{minimum_password_length} caracteres."
+
+msgid "Minutes"
+msgstr "Minutos"
msgid "Mirror a repository"
-msgstr ""
+msgstr "Replicar un repositorio"
msgid "Mirror direction"
-msgstr ""
+msgstr "Dirección de la réplica"
msgid "Mirror repository"
-msgstr ""
+msgstr "Replicar repositorio"
msgid "Mirror user"
-msgstr ""
+msgstr "Replicar usuario"
msgid "Mirrored repositories"
-msgstr ""
+msgstr "Repositorios replicados"
msgid "Mirroring repositories"
-msgstr ""
+msgstr "Replicando repositorios"
msgid "Mirroring settings were successfully updated."
+msgstr "La configuración de las réplicas se actualizó correctamente."
+
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr "La configuración de las réplicas se actualizó correctamente. El proyecto se está actualizando."
+
+msgid "Mirroring was successfully disabled."
+msgstr "Se ha desactivado la replica."
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
msgstr ""
msgid "MissingSSHKeyWarningLink|add an SSH key"
@@ -7238,19 +8470,19 @@ msgid "Modal|Close"
msgstr "Cerrar"
msgid "Modify commit message"
-msgstr ""
+msgstr "Modificar el mensaje de commit"
msgid "Modify commit messages"
-msgstr ""
+msgstr "Modificar los mensajes de commit"
msgid "Modify merge commit"
-msgstr ""
+msgstr "Modificar el merge commit"
msgid "Monday"
msgstr "Lunes"
msgid "Monitor your errors by integrating with Sentry"
-msgstr ""
+msgstr "Monitorice sus errores integrando Sentry"
msgid "Monitoring"
msgstr "Monitorizar"
@@ -7274,13 +8506,13 @@ msgid "More information is available|here"
msgstr "Hay más información disponible | aquí"
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
-msgstr ""
+msgstr "Más de %{number_commits_distance} commits diferente con %{default_branch}"
msgid "Most stars"
msgstr "Más estrellas"
msgid "Mount point %{mounted_as} not found in %{model_class}."
-msgstr ""
+msgstr "No es posible encontrar el punto de montaje %{mounted_as} en %{model_class}."
msgid "Move"
msgstr "Mover"
@@ -7288,18 +8520,39 @@ msgstr "Mover"
msgid "Move issue"
msgstr "Mover incidencia"
+msgid "Move issue from one column of the board to another"
+msgstr "Mover la incidencia de una columna del tablero a otra"
+
+msgid "Move this issue to another project."
+msgstr "Mueve esta incodencia a otro proyecto."
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr "¡No se puede mover la incidencia debido a permisos insuficientes!"
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr "¡No se puede mover la incidencia al proyecto en el que se crea!"
+
+msgid "Moves issue to %{label} column in the board."
+msgstr "Mover la incidencia a la columna %{label} en el tablero."
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr "Mueve esta incidencia a %{path_to_project}."
+
msgid "Multiple issue boards"
msgstr "Múltiples tableros de incidencias"
msgid "Multiple model types found: %{model_types}"
-msgstr ""
+msgstr "Se encontraron varios tipos de modelo: %{model_types}"
msgid "Multiple uploaders found: %{uploader_types}"
-msgstr ""
+msgstr "Se encontraron varios tipos de cargadores: %{uploader_types}"
msgid "Name"
msgstr "Nombre"
+msgid "Name has already been taken"
+msgstr "El nombre ya está en uso"
+
msgid "Name new label"
msgstr "Nombre de la nueva etiqueta"
@@ -7310,13 +8563,13 @@ msgid "Name:"
msgstr "Nombre:"
msgid "Namespaces to index"
-msgstr ""
+msgstr "Espacios de nombres a indexar"
msgid "Naming, topics, avatar"
-msgstr ""
+msgstr "Nombres, temas, avatar"
msgid "Naming, visibility"
-msgstr ""
+msgstr "Nomenclatura, visibilidad"
msgid "Nav|Help"
msgstr "Ayuda"
@@ -7366,7 +8619,7 @@ msgid "New Milestone"
msgstr "Nuevo hito"
msgid "New Pages Domain"
-msgstr ""
+msgstr "Nuevo dominio de Pages"
msgid "New Password"
msgstr "Nueva contraseña"
@@ -7384,7 +8637,7 @@ msgid "New branch unavailable"
msgstr "Nueva rama no disponible"
msgid "New deploy key"
-msgstr ""
+msgstr "Nueva clave de despliegue"
msgid "New directory"
msgstr "Nuevo directorio"
@@ -7395,6 +8648,9 @@ msgstr "Nuevo entorno"
msgid "New epic"
msgstr "Nueva tarea épica"
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr "Nuevo archivo"
@@ -7402,7 +8658,7 @@ msgid "New group"
msgstr "Nuevo grupo"
msgid "New health check access token has been generated!"
-msgstr ""
+msgstr "¡Se ha generado un nuevo token de acceso para la verificación de estado!"
msgid "New identity"
msgstr "Nueva identidad"
@@ -7419,6 +8675,9 @@ msgstr "Nueva solicitud de fusión"
msgid "New milestone"
msgstr "Nuevo hito"
+msgid "New password"
+msgstr "Nueva contraseña"
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr "Los nuevos 'pipelines' cancelarán los 'pipelines' más antiguos y pendientes en el mismo 'branch'"
@@ -7426,7 +8685,7 @@ msgid "New project"
msgstr "Nuevo proyecto"
msgid "New runners registration token has been generated!"
-msgstr ""
+msgstr "¡Se ha generado el token de registro para los nuevos ejecutores!"
msgid "New schedule"
msgstr "Nueva programación"
@@ -7441,29 +8700,44 @@ msgid "New tag"
msgstr "Nueva etiqueta"
msgid "New users set to external"
-msgstr ""
+msgstr "Nuevos usuarios configurados como externos"
msgid "New..."
msgstr "Nuevo..."
msgid "Newly registered users will by default be external"
-msgstr ""
+msgstr "Los usuarios recién registrados serán creados, por defecto, como externos"
+
+msgid "Next"
+msgstr "Siguiente"
+
+msgid "Nickname"
+msgstr "Seudónimo"
msgid "No"
msgstr "No"
msgid "No %{providerTitle} repositories available to import"
-msgstr ""
+msgstr "No hay %{providerTitle} repositorios disponibles para importar"
msgid "No Label"
msgstr "Sin etiqueta"
+msgid "No Milestone"
+msgstr "Sin hito"
+
msgid "No Tag"
-msgstr ""
+msgstr "Sin etiquetas"
msgid "No activities found"
msgstr "No se han encontrado actividades"
+msgid "No available namespaces to fork the project."
+msgstr "No hay espacios de nombres disponibles para hacer un fork el proyecto."
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr "No se han encontrado ramas"
@@ -7471,16 +8745,19 @@ msgid "No changes"
msgstr "Sin cambios"
msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
-msgstr ""
+msgstr "No hay cambios entre %{ref_start}%{source_branch}%{ref_end} y %{ref_start}%{target_branch}%{ref_end}"
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "¡No ha sido posible realizar la conexión con un servidor de Gitaly, por favor compruebe sus logs!"
msgid "No container images stored for this project. Add one by following the instructions above."
-msgstr ""
+msgstr "No hay imágenes de contenedores guardadas para este proyecto. puede agregar una imagen siguiendo las instrucciones que se muestran más arriba."
+
+msgid "No contributions"
+msgstr "Sin contribuciones"
msgid "No contributions were found"
-msgstr ""
+msgstr "No se encontraron contribuciones"
msgid "No credit card required."
msgstr "No se necesita tarjeta de crédito."
@@ -7492,7 +8769,7 @@ msgid "No due date"
msgstr "Sin fecha límite"
msgid "No errors to display."
-msgstr ""
+msgstr "No hay errores para mostrar."
msgid "No estimate or time spent"
msgstr "Sin estimación o tiempo gastado"
@@ -7503,6 +8780,9 @@ msgstr "No se ha seleccionado nignun archivo"
msgid "No file selected"
msgstr "No ha seleccionado ningún archivo"
+msgid "No files"
+msgstr "No hay archivos"
+
msgid "No files found."
msgstr "No se han encontrado archivos."
@@ -7510,28 +8790,25 @@ msgid "No issues for the selected time period."
msgstr "No hay incidencias para el período de tiempo seleccionado."
msgid "No job trace"
-msgstr ""
+msgstr "No hay registro de trabajo"
msgid "No labels with such name or description"
-msgstr ""
+msgstr "No hay etiquetas con ese nombre o descripción"
msgid "No license. All rights reserved"
msgstr "Sin licencia. Todos los derechos reservados"
msgid "No licenses found."
-msgstr ""
+msgstr "No se encontraron licencias."
msgid "No matching results"
msgstr "No se han encontrado resultados"
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
-msgstr ""
+msgstr "No hay solicitudes de merge request para el período de tiempo seleccionado."
msgid "No merge requests found"
-msgstr ""
+msgstr "No se han encontrado merge requests"
msgid "No messages were logged"
msgstr "No se registraron mensajes"
@@ -7540,13 +8817,16 @@ msgid "No milestones to show"
msgstr "No hay hitos para mostrar"
msgid "No other labels with such name or description"
-msgstr ""
+msgstr "No hay otras etiquetas con ese nombre o descripción"
+
+msgid "No parent group"
+msgstr "Ningún grupo padre"
msgid "No preview for this file type"
msgstr "No hay vista previa para este tipo de archivo"
msgid "No prioritised labels with such name or description"
-msgstr ""
+msgstr "No hay etiquetas priorizadas con ese nombre o descripción"
msgid "No public groups"
msgstr "No hay grupos públicos"
@@ -7567,7 +8847,13 @@ msgid "No start date"
msgstr "Sin fecha de inicio"
msgid "No, directly import the existing email addresses and usernames."
-msgstr ""
+msgstr "No, importe directamente las direcciones de correo electrónico y los nombres de usuario existentes."
+
+msgid "Node was successfully created."
+msgstr "El nodo se ha creado correctamente."
+
+msgid "Node was successfully updated."
+msgstr "El nodo se actualizó correctamente."
msgid "Nodes"
msgstr "Nodos"
@@ -7579,10 +8865,10 @@ msgid "Not available"
msgstr "No disponible"
msgid "Not available for private projects"
-msgstr ""
+msgstr "No está disponible para proyectos privados"
msgid "Not available for protected branches"
-msgstr ""
+msgstr "No está disponible para ramas protegidas"
msgid "Not confidential"
msgstr "No es confidencial"
@@ -7591,19 +8877,19 @@ msgid "Not enough data"
msgstr "No hay suficientes datos"
msgid "Not found."
-msgstr ""
+msgstr "No encontrado."
msgid "Not now"
msgstr "Ahora no"
msgid "Not ready yet. Try again later."
-msgstr ""
+msgstr "No está listo todavía. Por favor, inténtalo de nuevo más tarde."
msgid "Not started"
-msgstr ""
+msgstr "No iniciado"
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
-msgstr ""
+msgstr "Tenga en cuenta que esta invitación se envió a %{mail_to_invite_email}, pero ha iniciado sesión como %{link_to_current_user} con el correo electrónico %{mail_to_current_user}."
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr "Nota: Como administrador, puede configurar %{github_integration_link}, que le permitirá realizar el inicio de sesión a través de GitHub y le permitirá la conexión de repositorios sin la necesidad de generar un token de acceso personal."
@@ -7617,6 +8903,9 @@ msgstr "Nota: Considere preguntarle a su administrador de GitLab que configure %
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr "Nota: Considere pedirle a su administrador de GitLab que configure %{github_integration_link}, que le permitirá el inicio de sesión a través de GitHub y le permitirá la conexión de repositorios sin la necesidad de generar un token de acceso personal."
+msgid "NoteForm|Note"
+msgstr "Nota"
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "¿Está seguro de que desea cancelar la creación de este comentario?"
@@ -7632,14 +8921,23 @@ msgstr "Mostrar sólo los comentarios"
msgid "Notes|Show history only"
msgstr "Mostrar sólo el historial"
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr "Este comentario ha cambiado desde que se comenzó a editar, por favor revise el %{open_link}comentario actualizado%{close_link} para asegurar que no se pierde ningún tipo de información"
+
+msgid "Nothing to preview."
+msgstr "Nada para previsualizar."
+
msgid "Notification events"
msgstr "Eventos de notificación"
msgid "Notification setting"
-msgstr ""
+msgstr "Configuración de las notificaciones"
msgid "Notification setting - %{notification_title}"
-msgstr ""
+msgstr "Configuración de las notificaciones - %{notification_title}"
+
+msgid "Notification settings saved"
+msgstr "Configuración de las notificaciones guardada"
msgid "NotificationEvent|Close issue"
msgstr "Cerrar incidencia"
@@ -7695,6 +8993,9 @@ msgstr "Participación"
msgid "NotificationLevel|Watch"
msgstr "Vigilancia"
+msgid "NotificationSetting|Custom"
+msgstr "Personalizado"
+
msgid "Notifications"
msgstr "Notificaciones"
@@ -7710,11 +9011,17 @@ msgstr "Nov"
msgid "November"
msgstr "Noviembre"
+msgid "Number of Elasticsearch replicas"
+msgstr "Número de réplicas de Elasticsearch"
+
+msgid "Number of Elasticsearch shards"
+msgstr "Número de shards de Elasticsearch"
+
msgid "OK"
msgstr "OK"
msgid "Object does not exist on the server or you don't have permissions to access it"
-msgstr ""
+msgstr "El objeto no existe en el servidor o no tiene permisos para acceder a él"
msgid "Oct"
msgstr "Oct"
@@ -7725,14 +9032,20 @@ msgstr "Octubre"
msgid "OfSearchInADropdown|Filter"
msgstr "Filtrar"
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
-msgstr "Una vez importados, los repositorios se pueden duplicar a través de SSH. Lea más en %{ssh_link}"
+msgid "Ok let's go"
+msgstr "Adelante"
+
+msgid "Onboarding"
+msgstr "Primeros pasos"
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
+msgstr "Una vez importados, los repositorios se pueden replicar vía de SSH. Para obtener más información, haga clic %{link_start}aquí%{link_end}."
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
msgstr ""
msgid "Once the exported file is ready, you will receive a notification email with a download link, or you can download it from this page."
-msgstr ""
+msgstr "Una vez que el archivo exportado esté preparado, recibirá una notificación por correo electrónico con un enlace para su descarga, también puede descargarlo desde esta página."
msgid "One more item"
msgid_plural "%d more items"
@@ -7740,37 +9053,40 @@ msgstr[0] "Un elemento más"
msgstr[1] "%d elementos más"
msgid "One or more groups that you don't have access to."
-msgstr ""
+msgstr "Uno o más grupos a los que no tiene acceso."
msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
-msgstr ""
+msgstr "No ha sido posible importar uno o más de sus proyectos de Bitbucket a GitLab porque utilizan Subversion o Mercurial como sistema de control de versiones, en lugar de Git."
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr "No se ha sido posible importar uno o más de sus proyectos de Google Code a GitLab porque utilizan Subversion o Mercurial como sistema de control de versiones, en lugar de Git."
+
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
msgid "Only admins"
msgstr "Sólo administradores"
-msgid "Only allow merge requests to be merged if all discussions are resolved"
-msgstr ""
-
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
-msgstr ""
+msgstr "Sólo replicar ramas protegidas"
msgid "Only policy:"
-msgstr ""
+msgstr "Sólo la política:"
msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
-msgstr ""
+msgstr "Por favor, proceda únicamente si confía en %{idp_url} para controlar su cuenta de GitLab."
msgid "Only project members can comment."
msgstr "Sólo los miembros de proyecto pueden comentar."
msgid "Only project members will be imported. Group members will be skipped."
-msgstr ""
+msgstr "Solo se importarán los miembros del proyecto. Los miembros del grupo se omitirán."
+
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr "Sólo se soportan estas extensiones: %{extension_list}"
msgid "Oops, are you sure?"
msgstr "Oops, ¿está seguro?"
@@ -7817,6 +9133,12 @@ msgstr "Abierto"
msgid "Opens in a new window"
msgstr "Abre en una nueva ventana"
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr "La operación ha fallado. Por favor, compruebe los registros del pod para %{pod_name} para más obtener más información."
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr "Se ha agotado el tiempo de la operación. Por favor, compruebe los registros del pod para %{pod_name} para obtener más información."
+
msgid "Operations"
msgstr "Operaciones"
@@ -7830,34 +9152,31 @@ msgid "OperationsDashboard|Add a project to the dashboard"
msgstr "Agregar un proyecto al panel"
msgid "OperationsDashboard|Add projects"
-msgstr ""
+msgstr "Añadir proyectos"
msgid "OperationsDashboard|More information"
-msgstr ""
+msgstr "Más información"
msgid "OperationsDashboard|Operations Dashboard"
-msgstr ""
+msgstr "Panel de control de operaciones"
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
-msgstr ""
-
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
+msgstr "El panel de control de operaciones proporciona un resumen del estado operativo de cada proyecto, incluidos los estados de canalización y alerta."
msgid "Optional"
msgstr "Opcional"
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
-msgstr ""
+msgstr "Opcionalmente, puede %{link_to_customize} cómo se importan en Gitlab las direcciones de correo y los nombres de usuario de FogBugz."
msgid "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
-msgstr ""
+msgstr "Opcionalmente, puede %{link_to_customize} cómo se importan en Gitlab las direcciones de correo y los nombres de usuario de Google Code."
msgid "Options"
msgstr "Opciones"
msgid "Or you can choose one of the suggested colors below"
-msgstr ""
+msgstr "O puede seleccionar alguno de los colores sugeridos a continuación"
msgid "Other Labels"
msgstr "Otras etiquetas"
@@ -7865,6 +9184,9 @@ msgstr "Otras etiquetas"
msgid "Other information"
msgstr "Otra información"
+msgid "Other merge requests block this MR"
+msgstr "Otras merge request bloquean este MR"
+
msgid "Outbound requests"
msgstr "Peticiones salientes"
@@ -7874,6 +9196,12 @@ msgstr "Resumen"
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr "Propiedad de cualquier persona"
+
+msgid "Owned by me"
+msgstr "De mi propiedad"
+
msgid "Owner"
msgstr "Propietario"
@@ -7887,19 +9215,22 @@ msgid "Packages"
msgstr "Paquetes"
msgid "Page not found"
-msgstr ""
+msgstr "Página no encontrada"
msgid "Page was successfully deleted"
-msgstr ""
+msgstr "Página eliminada correctamente"
msgid "Pages"
msgstr "Páginas"
msgid "Pages Domain"
-msgstr ""
+msgstr "Dominio de Pages"
msgid "Pages Domains"
-msgstr ""
+msgstr "Dominios de Pages"
+
+msgid "Pages getting started guide"
+msgstr "Guía de inicio de Pages"
msgid "Pagination|Last »"
msgstr "Último »"
@@ -7922,29 +9253,41 @@ msgstr "Parte de los cambios de los merge requests"
msgid "Password"
msgstr "Contraseña"
+msgid "Password (optional)"
+msgstr "Contraseña (opcional)"
+
msgid "Password authentication is unavailable."
-msgstr ""
+msgstr "La autenticación con contraseña no está disponible."
+
+msgid "Password confirmation"
+msgstr "Confirmar contraseña"
+
+msgid "Password successfully changed"
+msgstr "La contraseña se ha cambiado correctamente"
+
+msgid "Password was successfully updated. Please login with it"
+msgstr "La contraseña se actualizó correctamente. Por favor, inicie la sesión de nuevo"
msgid "Past due"
-msgstr ""
+msgstr "Vencido"
msgid "Paste a machine public key here. Read more about how to generate it %{link_start}here%{link_end}"
-msgstr ""
+msgstr "Pegue aquí la clave pública de la máquina. Obtenga más información acerca de cómo generarla %{link_start}aquí%{link_end}"
msgid "Paste epic link"
-msgstr ""
+msgstr "Pegar el enlace de la tarea épica"
msgid "Paste issue link"
-msgstr ""
+msgstr "Pegar el enlace de la incidencia"
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
-msgstr "Pegue su clave pública SSH, que generalmente está contenida en el archivo '~ /.ssh/id_rsa.pub' y comienza con 'ssh-rsa'. No utilice su clave SSH privada."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
msgid "Path"
-msgstr ""
+msgstr "Ruta"
msgid "Path, transfer, remove"
-msgstr ""
+msgstr "Ruta, transferir, eliminar"
msgid "Path:"
msgstr "Ruta:"
@@ -7953,7 +9296,7 @@ msgid "Pause"
msgstr "Pausar"
msgid "Pause replication"
-msgstr ""
+msgstr "Pausar replicación"
msgid "Paused Runners don't accept new jobs"
msgstr "Los runers pausados no aceptan nuevos trabajos"
@@ -7964,6 +9307,9 @@ msgstr "Pendiente"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr "Las personas no autorizadas nunca recibirán una notificación y no podrán comentar."
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr "Realice opciones avanzadas como cambiar la ruta, transferir o eliminar el grupo."
@@ -7974,7 +9320,7 @@ msgid "Permissions"
msgstr "Permisos"
msgid "Permissions Help"
-msgstr ""
+msgstr "Ayuda de los permisos"
msgid "Permissions, LFS, 2FA"
msgstr "Permisos, LFS, 2FA"
@@ -7983,14 +9329,29 @@ msgid "Personal Access Token"
msgstr "Token de acceso personal"
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr "No se permite la creación de proyectos personales. Por favor, póngase en contacto con su administrador con preguntas"
+
+msgid "Phabricator Server Import"
msgstr ""
+msgid "Phabricator Server URL"
+msgstr "URL del servidor de Phabricator"
+
+msgid "Phabricator Tasks"
+msgstr "Tareas de Phabricator"
+
msgid "Pick a name"
msgstr "Escoja un nombre"
+msgid "Pin code"
+msgstr "Código pin"
+
msgid "Pipeline"
msgstr "Pipeline"
+msgid "Pipeline ID (IID)"
+msgstr "ID del pipeline (IID)"
+
msgid "Pipeline Schedule"
msgstr "Programación del Pipeline"
@@ -7998,7 +9359,7 @@ msgid "Pipeline Schedules"
msgstr "Programaciones de los Pipelines"
msgid "Pipeline minutes quota"
-msgstr ""
+msgstr "Cuota de minutos del pipeline"
msgid "Pipeline quota"
msgstr "Cuota de pipelines"
@@ -8007,7 +9368,7 @@ msgid "Pipeline triggers"
msgstr "Disparadores de los triggers"
msgid "Pipeline: %{status}"
-msgstr ""
+msgstr "Pipeline: %{status}"
msgid "PipelineCharts|Failed:"
msgstr "Fallidos:"
@@ -8058,10 +9419,10 @@ msgid "PipelineSheduleIntervalPattern|Custom"
msgstr "Personalizado"
msgid "PipelineStatusTooltip|Commit: %{ci_status}"
-msgstr ""
+msgstr "Commit: %{ci_status}"
msgid "PipelineStatusTooltip|Pipeline: %{ci_status}"
-msgstr ""
+msgstr "Pipeline: %{ci_status}"
msgid "Pipelines"
msgstr "Pipelines"
@@ -8069,6 +9430,9 @@ msgstr "Pipelines"
msgid "Pipelines charts"
msgstr "Gráficos de los pipelines"
+msgid "Pipelines emails"
+msgstr "Correos electrónicos de pipelines"
+
msgid "Pipelines for last month"
msgstr "Pipelines del mes pasado"
@@ -8078,14 +9442,17 @@ msgstr "Pipelines de la semana pasada"
msgid "Pipelines for last year"
msgstr "Pipelines del año pasado"
-msgid "Pipelines need to be configured to enable this feature."
-msgstr ""
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgstr "La configuración de los pipelines para '%{project_name}' se actualizó correctamente."
+
+msgid "Pipelines| to purchase more minutes."
msgstr ""
+msgid "Pipelines|API"
+msgstr "API"
+
msgid "Pipelines|Build with confidence"
-msgstr ""
+msgstr "Construir con confianza"
msgid "Pipelines|CI Lint"
msgstr "CI Lint"
@@ -8094,7 +9461,7 @@ msgid "Pipelines|Clear Runner Caches"
msgstr "Limpiar la caché de los runners"
msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
-msgstr ""
+msgstr "La integración continua le puede ayudar a capturar errores en su producto mediante la ejecución de pruebas automáticas, mientras que el despliegue continuo le puede ayudar a llevar el código al entorno de su producto."
msgid "Pipelines|Get started with Pipelines"
msgstr "Comenzar a utilizar los pipelines"
@@ -8102,6 +9469,9 @@ msgstr "Comenzar a utilizar los pipelines"
msgid "Pipelines|Loading Pipelines"
msgstr "Cargar pipelines"
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "Caché del proyecto restablecida correctamente."
@@ -8109,10 +9479,10 @@ msgid "Pipelines|Run Pipeline"
msgstr "Ejecutar Pipeline"
msgid "Pipelines|Something went wrong while cleaning runners cache."
-msgstr ""
+msgstr "Se ha producido un error durante el proceso de limpieza de la memoria caché de los runners."
msgid "Pipelines|There are currently no %{scope} pipelines."
-msgstr ""
+msgstr "Actualmente no hay %{scope} pipelines."
msgid "Pipelines|There are currently no pipelines."
msgstr "Actualmente no hay pipelines."
@@ -8121,19 +9491,19 @@ msgid "Pipelines|There was an error fetching the pipelines. Try again in a few m
msgstr "Se ha producido un error al obtener los pipelines. Por favor, inténtelo de nuevo en unos momentos o contacte con su equipo de soporte."
msgid "Pipelines|This project is not currently set up to run pipelines."
-msgstr ""
+msgstr "Este proyecto no está configurado para ejecutar pipelines."
msgid "Pipeline|Commit"
msgstr "Commit"
msgid "Pipeline|Coverage"
-msgstr ""
+msgstr "Cobertura"
msgid "Pipeline|Duration"
msgstr "Duración"
msgid "Pipeline|Existing branch name or tag"
-msgstr ""
+msgstr "Nombre de la rama o etiqueta existente"
msgid "Pipeline|Pipeline"
msgstr "Pipeline"
@@ -8142,13 +9512,13 @@ msgid "Pipeline|Run Pipeline"
msgstr "Ejecutar Pipeline"
msgid "Pipeline|Run for"
-msgstr ""
+msgstr "Ejecutar para"
msgid "Pipeline|Search branches"
msgstr "Buscar ramas"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
-msgstr ""
+msgstr "Especifique los valores de las variables que se utilizarán en esta ejecución. Se usarán los valores especificados por defecto en %{settings_link}."
msgid "Pipeline|Stages"
msgstr "Etapas"
@@ -8162,6 +9532,9 @@ msgstr "Detener pipeline"
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr "¿Desea detener la ejecución del pipeline #%{pipelineId}?"
+msgid "Pipeline|Triggerer"
+msgstr "Disparador"
+
msgid "Pipeline|Variables"
msgstr "Variables"
@@ -8172,19 +9545,19 @@ msgid "Pipeline|all"
msgstr "todos"
msgid "Pipeline|for"
-msgstr ""
+msgstr "para"
msgid "Pipeline|into"
-msgstr ""
+msgstr "en"
msgid "Pipeline|on"
-msgstr ""
+msgstr "en"
msgid "Pipeline|success"
msgstr "exitósos"
msgid "Pipeline|with"
-msgstr ""
+msgstr "con"
msgid "Pipeline|with stage"
msgstr "con etapa"
@@ -8192,6 +9565,15 @@ msgstr "con etapa"
msgid "Pipeline|with stages"
msgstr "con etapas"
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr "Lista de branches separadas por comas que serán inspeccionadas automáticamente. Deje este campo en blanco para incluir todas las ramas."
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr "API token de Pivotal Tracker."
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr "Software de gestión de proyectos (Source Commits Endpoint)"
+
msgid "Plain diff"
msgstr "Dif simple"
@@ -8201,56 +9583,86 @@ msgstr "PlantUML"
msgid "Play"
msgstr "Ejecutar"
+msgid "Play all manual"
+msgstr "Ejecutar todo manualmente"
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
-msgstr ""
+msgstr "Por favor %{link_to_register} o %{link_to_sign_in} para comentar"
msgid "Please accept the Terms of Service before continuing."
msgstr "Por favor, acepte los términos del servicio antes de continuar."
+msgid "Please add a comment in the text area above"
+msgstr "Por favor agregue un comentario en el cuadre de texto situado en la parte superior"
+
+msgid "Please add a list to your board first"
+msgstr "Por favor, agregue una lista primero a su tablero"
+
+msgid "Please check the configuration file for this chart"
+msgstr "Por favor, compruebe el archivo de configuración de este gráfico"
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr "Por favor, compruebe el archivo de configuración para asegurarse de que se ha declarado una colección de gráficos."
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr "Por favor, compruebe el archivo de configuración para asegurarse de que está disponible y que el fichero YAML es válido"
+
msgid "Please choose a group URL with no special characters."
msgstr "Por favor, elija una URL de grupo sin caracteres especiales."
msgid "Please complete your profile with email address"
-msgstr ""
+msgstr "Por favor, complete su perfil con una dirección de correo electrónico"
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
-msgstr ""
+msgstr "Por favor, conviértalo a %{link_to_git}, y vaya de nuevo a través de %{link_to_import_flow}."
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
-msgstr ""
+msgstr "Por favor, conviértalo a Git en Google Code, y diríjase de nuevo a %{link_to_import_flow}."
msgid "Please create a password for your new account."
-msgstr ""
+msgstr "Por favor, cree una nueva contraseña para su cuenta."
msgid "Please create a username with only alphanumeric characters."
-msgstr ""
+msgstr "Por favor, cree un nombre de usuario con sólo caracteres alfanuméricos."
msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
-msgstr ""
+msgstr "Por favor, habilite y migre todos los proyectos existentes al almacenamiento de tipo hash para evitar problemas de seguridad y asegurar la integridad de los datos. %{migrate_link}"
msgid "Please enter a non-negative number"
-msgstr ""
+msgstr "Por favor, introduzca un número no negativo"
msgid "Please enter a number greater than %{number} (from the project settings)"
-msgstr ""
+msgstr "Por favor, introduzca un número mayor que %{number} (desde la configuración del proyecto)"
msgid "Please enter a valid number"
msgstr "Por favor, introduzca un número válido"
+msgid "Please enter or upload a license."
+msgstr "Por favor, introduzca o cargue una licencia."
+
msgid "Please fill in a descriptive name for your group."
-msgstr ""
+msgstr "Por favor ingrese un nombre descriptivo para su grupo."
msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
-msgstr ""
+msgstr "Por favor, migre todos los proyectos existentes al almacenamiento hasheado para evitar problemas de seguridad y asegurar la integridad de los datos. %{migrate_link}"
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
-msgstr ""
+msgstr "Por favor, tenga en cuenta que esta aplicación no la proporciona GitLab y deberá verificar su autenticidad antes de permitir su acceso."
msgid "Please provide a name"
msgstr "Por favor, proporcione un nombre"
+msgid "Please provide a valid email address."
+msgstr "Por favor proporcione una dirección de correo electrónico válida."
+
+msgid "Please retype the email address."
+msgstr "Por favor, vuelva a introducir la dirección de correo electrónico."
+
+msgid "Please select a file"
+msgstr "Por favor, seleccione un archivo"
+
msgid "Please select a group."
-msgstr ""
+msgstr "Por favor, seleccione un grupo."
msgid "Please select and add a member"
msgstr "Por favor seleccione y añada un miembro"
@@ -8270,11 +9682,11 @@ msgstr "Por favor inténtelo de nuevo"
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr "Por favor, actualice PostgreSQL a la versión 9.6 o superior. No es posible determinar el estado de la replicación de manera fiable con la versión instalada actualmente."
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
-msgstr ""
+msgstr "Espere un momento; esta página se actualizará automáticamente cuando esté lista."
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr "Por favor espere mientras nos conectamos a su repositorio."
@@ -8286,35 +9698,95 @@ msgid "Preferences"
msgstr "Preferencias"
msgid "Preferences saved."
+msgstr "Preferencias guardadas."
+
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr "Mostrar tiempo en formato 24 horas"
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr "Por ejemplo: hace 30 minutos."
+
+msgid "Preferences|Layout width"
msgstr ""
msgid "Preferences|Navigation theme"
msgstr "Tema de navegación"
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr "Estas opciones de configuración actualizarán la forma en la que se muestran la fecha y las hora."
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
+msgstr "Esta función es experimental y las traducciones todavía no están completas"
+
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
msgstr ""
+msgid "Preferences|Time display"
+msgstr "Formato de hora"
+
+msgid "Preferences|Time format"
+msgstr "Formato de hora"
+
+msgid "Preferences|Time preferences"
+msgstr "Preferencias de hora"
+
+msgid "Preferences|Use relative times"
+msgstr "Utilizar tiempos relativos"
+
+msgid "Press %{key}-C to copy"
+msgstr "Presione %{key}-C para copiar"
+
msgid "Press Enter or click to search"
msgstr "Presione Enter o haga clic para buscar"
msgid "Prevent adding new members to project membership within this group"
-msgstr ""
+msgstr "Impedir que se añadan nuevos miembros al proyecto dentro de este grupo"
msgid "Prevent approval of merge requests by merge request author"
-msgstr ""
+msgstr "Impedir la aprobación de merge request por el autor del merge request"
msgid "Prevent approval of merge requests by merge request committers"
-msgstr ""
+msgstr "Impedir la aprobación de merge request por colaboradores del merge request"
msgid "Preview"
msgstr "Vista previa"
+msgid "Preview Markdown"
+msgstr "Vista previa de Markdown"
+
msgid "Preview changes"
-msgstr ""
+msgstr "Vista previa de los cambios"
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr "Artefactos anteriores"
+
msgid "Primary"
msgstr "Principal"
@@ -8340,22 +9812,31 @@ msgid "Private - The group and its projects can only be viewed by members."
msgstr "Privado - El grupo y sus proyectos sólo pueden ser vistos por sus miembros."
msgid "Private group(s)"
-msgstr ""
+msgstr "Grupo(s) privado(s)"
+
+msgid "Private profile"
+msgstr "Perfil privado"
msgid "Private projects can be created in your personal namespace with:"
msgstr "Los proyectos privados se pueden crear en su espacio de nombres personal con:"
+msgid "Proceed"
+msgstr "Continuar"
+
msgid "Profile"
msgstr "Perfil"
msgid "Profile Settings"
msgstr "Configuración del perfil"
+msgid "ProfileSession|on"
+msgstr "Encendido"
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Está a punto de eliminar permanentemente %{yourAccount}, y todas las incidencias, solicitudes de fusión y grupos vinculados a su cuenta. Una vez que confirme %{deleteAccount}, no se podrá deshacerse esta acción ni recuperar los datos borrados."
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
-msgstr ""
+msgstr "Está a punto de renombrar el usuario %{currentUsernameBold} a %{newUsernameBold}. El perfil del usuario y los proyectos serán redirigidos al espacio de nombres %{newUsername} pero este redireccionamiento caducará una vez que otro usuario o grupo registre el %{currentUsername}. Por favor, actualice los remotos de su repositorio Git tan pronto como sea posible."
msgid "Profiles|@username"
msgstr "@nombredeusuario"
@@ -8364,7 +9845,7 @@ msgid "Profiles|Account scheduled for removal."
msgstr "Cuenta programada para su eliminación."
msgid "Profiles|Activate signin with one of the following services"
-msgstr ""
+msgstr "Active el inicio de sesión con uno de los siguientes servicios"
msgid "Profiles|Active"
msgstr "Activo"
@@ -8373,25 +9854,28 @@ msgid "Profiles|Add key"
msgstr "Añadir clave"
msgid "Profiles|Add status emoji"
-msgstr ""
+msgstr "Agregar emoji de estado"
msgid "Profiles|Avatar cropper"
-msgstr ""
+msgstr "Redimensionador de avatar"
msgid "Profiles|Avatar will be removed. Are you sure?"
-msgstr ""
+msgstr "El avatar será eliminado, ¿está seguro?"
+
+msgid "Profiles|Bio"
+msgstr "Bio"
msgid "Profiles|Change username"
msgstr "Cambiar el nombre de usuario"
msgid "Profiles|Changing your username can have unintended side effects."
-msgstr ""
+msgstr "Cambiar su nombre de usuario puede tener efectos secundarios no deseados."
msgid "Profiles|Choose file..."
msgstr "Seleccionar un archivo..."
msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
-msgstr ""
+msgstr "Seleccione mostrar las contribuciones de los proyectos privados en su perfil público sin ningún tipo de información de proyecto, repositorio u organización"
msgid "Profiles|City, country"
msgstr "Ciudad, país"
@@ -8400,6 +9884,9 @@ msgid "Profiles|Clear status"
msgstr "Borrar estado"
msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr "Haga clic en el icono para activar el inicio de sesión con uno de los siguientes servicios"
+
+msgid "Profiles|Commit email"
msgstr ""
msgid "Profiles|Connect"
@@ -8414,6 +9901,9 @@ msgstr "Ruta actual: %{path}"
msgid "Profiles|Current status"
msgstr "Estado actual"
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr "Eliminar la cuenta"
@@ -8424,7 +9914,7 @@ msgid "Profiles|Delete your account?"
msgstr "¿Eliminar su cuenta?"
msgid "Profiles|Deleting an account has the following effects:"
-msgstr ""
+msgstr "La eliminación de su cuenta tiene los siguientes efectos:"
msgid "Profiles|Disconnect"
msgstr "Desconectar"
@@ -8433,47 +9923,80 @@ msgid "Profiles|Do not show on profile"
msgstr "No mostrar en el perfil"
msgid "Profiles|Don't display activity-related personal information on your profiles"
-msgstr ""
+msgstr "No mostrar información personal relacionada con su actividad en sus perfiles"
msgid "Profiles|Edit Profile"
msgstr "Editar perfil"
msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr "Introduzca su nombre para que las personas que le conozca puedan reconocer su perfil"
+
+msgid "Profiles|Feed token was successfully reset"
msgstr ""
+msgid "Profiles|Full name"
+msgstr "Nombre completo"
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr "Incluir las contribuciones privadas en mi perfil"
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr "El token de correo electrónico entrante se ha restablecido correctamente"
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
-msgstr ""
+msgstr "Aumente la seguridad de su cuenta al habilitar la autenticación de dos factores (2FA)"
msgid "Profiles|Invalid password"
-msgstr "Contraseña inválida"
+msgstr "Contraseña no válida"
msgid "Profiles|Invalid username"
msgstr "Nombre de usuario inválido"
+msgid "Profiles|Key"
+msgstr "Clave"
+
msgid "Profiles|Learn more"
msgstr "Más información"
+msgid "Profiles|Location"
+msgstr "Ubicación"
+
msgid "Profiles|Made a private contribution"
-msgstr ""
+msgstr "A hecho una contribución privada"
msgid "Profiles|Main settings"
msgstr "Configuración principal"
msgid "Profiles|No file chosen"
+msgstr "No hay ningún archivo seleccionado"
+
+msgid "Profiles|Notification email"
msgstr ""
+msgid "Profiles|Organization"
+msgstr "Organización"
+
msgid "Profiles|Path"
msgstr "Ruta"
msgid "Profiles|Position and size your new avatar"
+msgstr "Posición y tamaño de su nuevo avatar"
+
+msgid "Profiles|Primary email"
msgstr ""
msgid "Profiles|Private contributions"
-msgstr ""
+msgstr "Contribuciones privadas"
+
+msgid "Profiles|Profile was successfully updated"
+msgstr "El perfil se actualizó correctamente"
msgid "Profiles|Public Avatar"
msgstr "Avatar público"
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr "Eliminar avatar"
@@ -8481,46 +10004,46 @@ msgid "Profiles|Set new profile picture"
msgstr "Establecer una nueva imagen de perfil"
msgid "Profiles|Social sign-in"
-msgstr ""
+msgstr "Inicio de sesión social"
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr "Algunas opciones no están disponibles para cuentas LDAP"
msgid "Profiles|Tell us about yourself in fewer than 250 characters"
-msgstr ""
+msgstr "Cuéntenos más sobre usted en menos de 250 caracteres"
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "El tamaño máximo de archivo permitido es 200KB."
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "No se parece a una clave SSH pública, ¿está seguro de que desea agregarla?"
msgid "Profiles|This email will be displayed on your public profile"
-msgstr ""
+msgstr "Esta dirección de correo electrónico se mostrará en su perfil público"
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{commit_email_link_start}Learn more%{commit_email_link_end}"
-msgstr ""
+msgstr "Perfiles | Este correo electrónico se usará para operaciones basadas en web, como ediciones y fusiones. %{commit_email_link_start}Aprende más%{commit_email_link_end}"
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
-msgstr ""
+msgstr "Este emoji y el mensaje se mostrarán en su perfil y en toda la interfaz."
msgid "Profiles|This information will appear on your profile"
-msgstr ""
+msgstr "Esta información aparecerá en tu perfil"
+
+msgid "Profiles|Time settings"
+msgstr "Ajustes de tiempo"
msgid "Profiles|Two-Factor Authentication"
-msgstr ""
+msgstr "Autenticación de dos factores"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Escribe tu %{confirmationValue} para confirmar:"
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
-msgstr "Normalmente comienza con \"ssh-rsa ...\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
+msgstr ""
msgid "Profiles|Update profile settings"
-msgstr ""
+msgstr "Actualizar la configuración del perfil"
msgid "Profiles|Update username"
msgstr "Actualizar el nombre de usuario"
@@ -8529,34 +10052,40 @@ msgid "Profiles|Upload new avatar"
msgstr "Cargar un avatar nuevo"
msgid "Profiles|Use a private email - %{email}"
-msgstr ""
+msgstr "Utilice un correo electrónico privado - %{email}"
+
+msgid "Profiles|User ID"
+msgstr "ID de usuario"
msgid "Profiles|Username change failed - %{message}"
-msgstr ""
+msgstr "Se ha producido un error al cambiar el nombre de usuario - %{message}"
msgid "Profiles|Username successfully changed"
-msgstr ""
+msgstr "El nombre de usuario se cambió con éxito"
msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
-msgstr ""
+msgstr "El uso de emojis en los nombres parece divertido, pero por favor, intente establecer un mensaje de estado en su lugar"
msgid "Profiles|What's your status?"
msgstr "¿Cuál es su estado?"
msgid "Profiles|Who you represent or work for"
-msgstr ""
+msgstr "A quién representa o para quién trabaja"
msgid "Profiles|You can change your avatar here"
-msgstr ""
+msgstr "Puedes cambiar su avatar aquí"
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
-msgstr ""
+msgstr "Puede cambiar aquí su avatar o eliminar el avatar actual para volver a %{gravatar_link}"
+
+msgid "Profiles|You can set your current timezone here"
+msgstr "Puede configurar su zona horaria actual aquí"
msgid "Profiles|You can upload your avatar here"
-msgstr ""
+msgstr "Puede subir su avatar aquí"
msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
-msgstr ""
+msgstr "Puede subir directamente su avatar aquí o modificarlo en %{gravatar_link}"
msgid "Profiles|You don't have access to delete this user."
msgstr "No tienes acceso para eliminar este usuario."
@@ -8565,19 +10094,19 @@ msgid "Profiles|You must transfer ownership or delete these groups before you ca
msgstr "Debes transferir o eliminar estos grupos antes de que puedas eliminar tu cuenta."
msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
-msgstr ""
+msgstr "Su perfil de LinkedIn desde linkedin.com/in/profilename"
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "Actualmente su cuenta es propietaria de estos grupos:"
msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
-msgstr ""
+msgstr "Su dirección de correo electrónico se ha establecido automáticamente en base a su cuenta %{provider_label}"
msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
-msgstr ""
+msgstr "Su ubicación se ha establecido automáticamente basándose en su cuenta %{provider_label}"
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
-msgstr ""
+msgstr "Su nombre se configuró automáticamente en función de su cuenta %{provider_label}, de modo que las personas que conozca lo reconozcan"
msgid "Profiles|Your status"
msgstr "Su estado"
@@ -8607,13 +10136,13 @@ msgid "Project"
msgstr "Proyecto"
msgid "Project \"%{name}\" is no longer available. Select another project to continue."
-msgstr ""
+msgstr "El proyecto \"%{name}\" ya no está disponible. Por favor, seleccione otro proyecto para continuar."
msgid "Project %{project_repo} could not be found"
-msgstr ""
+msgstr "No es posible encontrar el proyecto %{project_repo}"
msgid "Project '%{project_name}' is being imported."
-msgstr ""
+msgstr "Se está importando el proyecto '%{project_name}'."
msgid "Project '%{project_name}' is in the process of being deleted."
msgstr "El proyecto '%{project_name}' está en proceso de ser eliminado."
@@ -8631,7 +10160,7 @@ msgid "Project Badges"
msgstr "Insignias de proyecto"
msgid "Project ID"
-msgstr ""
+msgstr "ID de proyecto"
msgid "Project URL"
msgstr "URL del proyecto"
@@ -8640,16 +10169,19 @@ msgid "Project access must be granted explicitly to each user."
msgstr "El acceso al proyecto debe concederse explícitamente a cada usuario."
msgid "Project and wiki repositories"
-msgstr ""
+msgstr "Repositorios de proyecto y wiki"
msgid "Project avatar"
msgstr "Avatar del proyecto"
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr "No se puede compartir el proyecto con el grupo en el que está o con uno de sus grupos padre."
+
msgid "Project configuration, including services"
-msgstr ""
+msgstr "Configuración del proyecto, incluyendo sus servicios"
msgid "Project description (optional)"
-msgstr ""
+msgstr "Descripción del proyecto (opcional)"
msgid "Project details"
msgstr "Detalles del Proyecto"
@@ -8670,7 +10202,7 @@ msgid "Project export started. A download link will be sent by email."
msgstr "Se inició la exportación del proyecto. Se enviará un enlace de descarga por correo electrónico."
msgid "Project has too many %{label_for_message} to search"
-msgstr ""
+msgstr "El proyecto tiene demasiadas %{label_for_message} para buscar"
msgid "Project members"
msgstr "Miembros del proyecto"
@@ -8682,14 +10214,17 @@ msgid "Project slug"
msgstr "Slug del proyecto"
msgid "Project uploads"
-msgstr ""
+msgstr "Proyectos subidos"
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
-msgstr ""
+msgstr "Se modificará el nivel de visibilidad del proyecto para hacerlo coincidir con las reglas del espacio de nombres al transferirlo a un grupo."
msgid "Project:"
msgstr "Proyecto:"
+msgid "Project: %{name}"
+msgstr "Proyecto: %{name}"
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "Suscribirse"
@@ -8733,22 +10268,43 @@ msgid "ProjectOverview|Unstar"
msgstr "Desmarcar como favorito"
msgid "ProjectOverview|You have reached your project limit"
-msgstr "Ha alcanzado el límite de tu proyecto"
+msgstr "Ha alcanzado el límite de su proyecto"
msgid "ProjectOverview|You must sign in to star a project"
-msgstr ""
+msgstr "Debe iniciar sesión para marcar como favorito un proyecto"
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "ID de proyecto: %{project_id}"
+msgid "ProjectSelect| or group"
+msgstr "o grupo"
+
+msgid "ProjectSelect|Search for project"
+msgstr "Buscar proyecto"
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr "Opciones adicionales de los merge request que influyen cómo y cuándo se realizarán los merges"
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr "Todas las discusiones deben ser resueltas"
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr "Insignias"
msgid "ProjectSettings|Contact an admin to change this setting."
-msgstr ""
+msgstr "Póngase en contacto con el administrador para cambiar esta configuración."
msgid "ProjectSettings|Customize your project badges."
-msgstr ""
+msgstr "Personalice las insignias de su proyecto."
+
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr "Todo merge crea un merge commit"
msgid "ProjectSettings|Failed to protect the tag"
msgstr "¡Se ha producido un error al proteger la etiqueta!"
@@ -8756,27 +10312,126 @@ msgstr "¡Se ha producido un error al proteger la etiqueta!"
msgid "ProjectSettings|Failed to update tag!"
msgstr "¡Se ha producido un error al actualizar la etiqueta!"
+msgid "ProjectSettings|Fast-forward merge"
+msgstr "Fast-forward merge"
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr "Solo fast-forward merges"
+
msgid "ProjectSettings|Learn more about badges."
+msgstr "Más información sobre insignias."
+
+msgid "ProjectSettings|Merge checks"
+msgstr "Comprobaciones de Merge"
+
+msgid "ProjectSettings|Merge commit"
+msgstr "Merge commit"
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr "Merge commit con historial semi-lineal"
+
+msgid "ProjectSettings|Merge method"
+msgstr "Método de Merge"
+
+msgid "ProjectSettings|Merge options"
+msgstr "Opciones de Merge"
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
msgstr ""
+msgid "ProjectSettings|No merge commits are created"
+msgstr "No se han creado merge commits"
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
-msgstr ""
+msgstr "Solo se pueden enviar commits firmados a este repositorio."
+
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr "La ejecución debe finalizar correctamente"
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr "Se deben configurar los pipelines para habilitar esta característica."
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr "Mostrar el enlace para crear/ver los merge requests cuando se haga push desde la línea de comandos"
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr "Estas comprobaciones deben pasar antes de que se pueda ejecutar el merge request"
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
-msgstr ""
+msgstr "Esta configuración se aplica a nivel del servidor y se puede sobreescribir por un administrador."
msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
-msgstr ""
+msgstr "Esta configuración se aplica a nivel del servidor pero se ha sobreescrito para este proyecto."
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
-msgstr ""
+msgstr "Esta configuración se aplicará a todos los proyectos a menos que sea sobreescrita por un administrador."
+
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr "Esto determinará el historial de commits cuando se haga un merge request"
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
-msgstr ""
+msgstr "Solamente pueden hacer push commit a este repositorio los usuarios cuyos commits se crearon mediante la utilización de correos electrónicos verificados."
+
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr "Cuando surgen conflictos, al usuario se le da la opción de realizar un rebase"
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ".NET Core"
+
+msgid "ProjectTemplates|Android"
+msgstr "Android"
+
+msgid "ProjectTemplates|Go Micro"
+msgstr "Go Micro"
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr "Netlify/GitBook"
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr "Netlify/Hexo"
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr "Netlify/Hugo"
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr "Netlify/Jekyll"
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr "Netlify/HTML plano"
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr "NodeJS Express"
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr "Pages/GitBook"
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr "Pages/Hexo"
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr "Pages/Hugo"
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr "Pages/Jekyll"
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr "Pages/HTML plano"
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr "Ruby on Rails"
+
+msgid "ProjectTemplates|Spring"
+msgstr "Spring"
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr "IOS (Swift)"
msgid "Projects"
msgstr "Proyectos"
+msgid "Projects (%{count})"
+msgstr "Proyectos (%{count})"
+
msgid "Projects Successfully Retrieved"
msgstr "Proyectos recuperados con éxito"
@@ -8784,10 +10439,10 @@ msgid "Projects shared with %{group_name}"
msgstr "Proyectos compartidos con %{group_name}"
msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
-msgstr ""
+msgstr "Los proyectos que pertenecen a un grupo tienen como prefijo el espacio de nombres del grupo. Los proyectos existentes se pueden mover a un grupo."
msgid "Projects to index"
-msgstr ""
+msgstr "Proyectos a indexar"
msgid "Projects with write access"
msgstr "Proyectos con acceso de escritura"
@@ -8811,7 +10466,7 @@ msgid "ProjectsDropdown|Sorry, no projects matched your search"
msgstr "Lo sentimos, no hay proyectos que coincidan con su búsqueda"
msgid "ProjectsDropdown|This feature requires browser localStorage support"
-msgstr ""
+msgstr "Esta función requiere que el navegador permita la utilización de almacenamiento local (localStorage)"
msgid "PrometheusAlerts|Add alert"
msgstr "Añadir alerta"
@@ -8829,28 +10484,28 @@ msgid "PrometheusAlerts|Error deleting alert"
msgstr "Se ha producido un error al eliminar la alerta"
msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
+msgstr "Se ha producido un error al recuperar la alerta"
msgid "PrometheusAlerts|Error saving alert"
msgstr "Se ha producido un error al guardar la alerta"
msgid "PrometheusAlerts|No alert set"
-msgstr ""
+msgstr "No hay ninguna alerta establecida"
msgid "PrometheusAlerts|Operator"
msgstr "Operador"
msgid "PrometheusAlerts|Select query"
-msgstr ""
+msgstr "Seleccionar consulta"
msgid "PrometheusAlerts|Threshold"
msgstr "Umbral"
msgid "PrometheusService|%{exporters} with %{metrics} were found"
-msgstr ""
+msgstr "se han encontrado %{exporters} con %{metrics}"
msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
-msgstr ""
+msgstr "<p class=\"text-tertiary\">No se han encontrado<a href=\"%{docsUrl}\">métricas comunes</a> </p>"
msgid "PrometheusService|Active"
msgstr "Activo"
@@ -8859,19 +10514,19 @@ msgid "PrometheusService|Auto configuration"
msgstr "Configuración automática"
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
-msgstr ""
+msgstr "Implemente y configure Prometheus automáticamente en sus clústeres para supervisar los entornos de su proyecto"
msgid "PrometheusService|Common metrics"
msgstr "Métricas comunes"
msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
-msgstr ""
+msgstr "Las métricas comunes más son monitorizadas automáticamente en base a una librería de métricas de los exportadores más populares."
msgid "PrometheusService|Custom metrics"
msgstr "Métricas personalizadas"
msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
-msgstr ""
+msgstr "Habilite Prometheus para definir métricas personalizadas, utilizando cualquiera de las opciones anteriores"
msgid "PrometheusService|Finding and configuring metrics..."
msgstr "Encontrar y configurar métricas..."
@@ -8904,22 +10559,22 @@ msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example
msgstr "URL Base de Prometheus, como http://prometheus.example.com/"
msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
-msgstr ""
+msgstr "Prometheus se administra automáticamente en sus clusters"
msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
-msgstr ""
+msgstr "Estas métricas serán monitorizadas una vez se realice el primer despliegue a un entorno"
msgid "PrometheusService|Time-series monitoring service"
-msgstr ""
+msgstr "Servicio de monitorización de series de tiempo"
msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
-msgstr ""
+msgstr "Para habilitar la configuración manual, por favor, desinstale Prometheus de sus clústeres"
msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
-msgstr ""
+msgstr "Para permitir la instalación de Prometheus en sus clústeres, por favor, desactive la configuración manual"
msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
-msgstr ""
+msgstr "Esperando su primera despliegue en un entorno para buscar métricas comunes"
msgid "Promote"
msgstr "Promocionar"
@@ -8933,6 +10588,15 @@ msgstr "Promocionar a hito de grupo"
msgid "Promote to group label"
msgstr "Promocionar a etiqueta de grupo"
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr "Solo se pueden promover los hitos del proyecto."
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr "El proyecto no pertenecen a un grupo."
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr "Ha fallado la promoción - %{message}"
+
msgid "Promotions|Don't show me this again"
msgstr "No mostrar este mensaje de nuevo"
@@ -8946,22 +10610,28 @@ msgid "Promotions|Upgrade plan"
msgstr "Plan de actualización"
msgid "Prompt users to upload SSH keys"
-msgstr ""
+msgstr "Solicitar a los usuarios que carguen claves SSH"
msgid "Protected"
msgstr "Protegido"
+msgid "Protected Branch"
+msgstr "Rama protegida"
+
+msgid "Protected Environment"
+msgstr "Entorno protegido"
+
msgid "Protected Environments"
msgstr "Entornos protegidos"
+msgid "Protected Tag"
+msgstr "Etiqueta protegida"
+
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
-msgstr ""
+msgstr "%{environment_name} podrá modificarse por los desarrolladores. ¿Estás seguro de que desea continuar?"
msgid "ProtectedEnvironment|Allowed to deploy"
-msgstr ""
-
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
-msgstr ""
+msgstr "Permitido desplegar"
msgid "ProtectedEnvironment|Environment"
msgstr "Entorno"
@@ -8969,32 +10639,38 @@ msgstr "Entorno"
msgid "ProtectedEnvironment|Protect"
msgstr "Proteger"
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
-msgstr ""
+msgstr "Proteger un entorno"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
-msgstr ""
+msgstr "Entorno Protegido (%{protected_environments_count})"
+
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr "Proteger un entorno restringe los usuarios que pueden realizar despliegues."
msgid "ProtectedEnvironment|Select an environment"
-msgstr ""
+msgstr "Seleccione un entorno"
+
+msgid "ProtectedEnvironment|Select users"
+msgstr "Seleccionar usuarios"
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr "Seleccione los usuarios para implementar y administrar las opciones de configuración de Feature Flags"
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
-msgstr ""
+msgstr "Actualmente no hay entornos protegidos, proteja un entorno con el formulario mostrado anteriormente."
msgid "ProtectedEnvironment|Unprotect"
msgstr "Desproteger"
msgid "ProtectedEnvironment|Your environment can't be unprotected"
-msgstr ""
+msgstr "No se puede desproteger su entorno"
msgid "ProtectedEnvironment|Your environment has been protected."
-msgstr ""
+msgstr "Se ha protegido su entorno."
msgid "ProtectedEnvironment|Your environment has been unprotected"
-msgstr ""
+msgstr "Se ha desprotegido su entorno"
msgid "Protip:"
msgstr "Sugerencia:"
@@ -9003,7 +10679,7 @@ msgid "Provider"
msgstr "Proveedor"
msgid "Pseudonymizer data collection"
-msgstr ""
+msgstr "Pseudonymizer data collection"
msgid "Public"
msgstr "Público"
@@ -9015,10 +10691,10 @@ msgid "Public - The project can be accessed without any authentication."
msgstr "Público - El proyecto puede ser accedido sin ninguna autenticación."
msgid "Public Access Help"
-msgstr ""
+msgstr "Ayuda de acceso público"
msgid "Public deploy keys (%{deploy_keys_count})"
-msgstr ""
+msgstr "Claves de despliegue público (%{deploy_keys_count})"
msgid "Public pipelines"
msgstr "Pipelines públicos"
@@ -9029,9 +10705,15 @@ msgstr "Pull"
msgid "Push"
msgstr "Push"
+msgid "Push Rule updated successfully."
+msgstr "Regla de push actualizadas con éxito."
+
msgid "Push Rules"
msgstr "Reglas de Push"
+msgid "Push Rules updated successfully."
+msgstr "Reglas de push actualizadas con éxito."
+
msgid "Push an existing Git repository"
msgstr "Push a un repositorio de Git existente"
@@ -9042,7 +10724,7 @@ msgid "Push events"
msgstr "Eventos Push"
msgid "Push project from command line"
-msgstr ""
+msgstr "Hacer push al proyecto desde línea de comando"
msgid "Push to create a project"
msgstr "Push para crear un proyecto"
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr "Pushes"
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr "El %{user_name} ha eliminado el branch\"%{ref}\"."
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr "El usuario %{user_name} ha realizado un push a la rama \"%{ref}\"."
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr "El usuario %{user_name} ha realizado un push a una nueva rama \"%{ref}\"."
+
+msgid "PushoverService|High Priority"
+msgstr "Prioridad alta"
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr "Dejar en blanco para todos los dispositivos activos"
+
+msgid "PushoverService|Low Priority"
+msgstr "Prioridad baja"
+
+msgid "PushoverService|Lowest Priority"
+msgstr "Prioridad más baja"
+
+msgid "PushoverService|Normal Priority"
+msgstr "Prioridad normal"
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr "Vea el proyecto %{project_full_name}"
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr "Número total de commits: %{total_commits_count}"
+
+msgid "PushoverService|Your application key"
+msgstr "Su clave de aplicación"
+
+msgid "PushoverService|Your user key"
+msgstr "Su clave de usuario"
+
msgid "Quarters"
msgstr "Trimestres"
msgid "Query"
msgstr "Consulta"
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr "Se pueden utilizar acciones rápidas en la descripción de las incidencias y en los cuadros de texto de los comentarios."
@@ -9069,7 +10793,7 @@ msgid "README"
msgstr "README"
msgid "Rake Tasks Help"
-msgstr ""
+msgstr "Ayuda sobre las tareas de Rake"
msgid "Read more"
msgstr "Leer más"
@@ -9078,13 +10802,16 @@ msgid "Read more about environments"
msgstr "Lea más acerca de los entornos"
msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
-msgstr ""
+msgstr "Lea más sobre los permisos de este proyecto <strong>%{link_to_help}</strong>"
msgid "Real-time features"
msgstr "Características en tiempo real"
msgid "Receive alerts from manually configured Prometheus servers."
-msgstr ""
+msgstr "Recibe alertas desde los servidores de Prometheus configurados manualmente."
+
+msgid "Receive notifications about your own activity"
+msgstr "Recibir notificaciones acerca de su propia actividad"
msgid "Recent"
msgstr "Reciente"
@@ -9092,11 +10819,17 @@ msgstr "Reciente"
msgid "Recent Project Activity"
msgstr "Actividad reciente del proyecto"
+msgid "Recent Searches Service is unavailable"
+msgstr "El servicio de búsquedas recientes no está disponible"
+
msgid "Recent searches"
msgstr "Búsquedas recientes"
+msgid "Recovery Codes"
+msgstr "Codigos de recuperacion"
+
msgid "Redirect to SAML provider to test configuration"
-msgstr ""
+msgstr "Redirigir al proveedor de SAML para probar la configuración"
msgid "Reference:"
msgstr "Referencia:"
@@ -9109,26 +10842,47 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] "Actualizar en un segundo para mostrar el estado actualizado..."
msgstr[1] "Actualizar en %d segundos para mostrar el estado actualizado..."
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr "Regenerar clave"
+msgid "Regenerate recovery codes"
+msgstr "Regenerar los códigos de recuperación"
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr "Patrón regex"
+msgid "Register"
+msgstr "Registro"
+
msgid "Register / Sign In"
msgstr "Registrarse / Iniciar sesión"
+msgid "Register Two-Factor Authenticator"
+msgstr "Registrar un dispositivo de autenticación de dos factores"
+
msgid "Register U2F device"
msgstr "Registrar dispositivo U2F"
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr "Registrar un dispositivo universal de autenticación de dos factores (U2F)"
+
msgid "Register and see your runners for this group."
msgstr "Registrar y ver sus ejecutores en este grupo."
msgid "Register and see your runners for this project."
msgstr "Registrar y ver sus ejecutores en este proyecto."
+msgid "Register with two-factor app"
+msgstr "Registrarse con la aplicación de dos factores"
+
msgid "Registration"
-msgstr ""
+msgstr "Registro"
msgid "Registry"
msgstr "Registro"
@@ -9151,8 +10905,11 @@ msgstr "Solicitudes de fusión Relacionadas"
msgid "Related Merged Requests"
msgstr "Solicitudes de fusión Relacionadas"
+msgid "Related issues"
+msgstr "Incidencias relacionadas"
+
msgid "Related merge requests"
-msgstr ""
+msgstr "Solicitudes de fusión relacionadas"
msgid "Releases"
msgstr "Versiones"
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr "Recordar después"
+msgid "Remote object has no absolute path."
+msgstr "El objeto remoto no tiene una ruta absoluta."
+
msgid "Remove"
msgstr "Eliminar"
@@ -9170,58 +10930,91 @@ msgid "Remove Runner"
msgstr "Eliminar ejecutor"
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
-msgstr ""
+msgstr "Elimine todas las aprobaciones en un merge request cuando se realicen nuevos commits a la rama de origen"
-msgid "Remove approver"
-msgstr ""
+msgid "Remove all or specific assignee(s)"
+msgstr "Eliminar todos los asignados o los asignados específicos"
+
+msgid "Remove all or specific label(s)"
+msgstr "Eliminar todas las etiquetas o las etiquetas específicas"
msgid "Remove approvers"
-msgstr ""
+msgstr "Eliminar los aprobadores"
msgid "Remove approvers?"
-msgstr ""
+msgstr "¿Eliminar los aprobadores?"
+
+msgid "Remove assignee"
+msgstr "Eliminar el usuario asignado"
msgid "Remove avatar"
msgstr "Eliminar avatar"
+msgid "Remove child epic from an epic"
+msgstr "Eliminar la tarea épica hija de una tarea épica"
+
+msgid "Remove due date"
+msgstr "Eliminar la fecha de vencimiento"
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr "Eliminar grupo"
+msgid "Remove milestone"
+msgstr "Eliminar el hito"
+
msgid "Remove priority"
msgstr "Eliminar prioridad"
msgid "Remove project"
msgstr "Eliminar proyecto"
-msgid "Remove this label? Are you sure?"
-msgstr ""
+msgid "Remove spent time"
+msgstr "Eliminar el tiempo gastado"
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
-msgstr ""
+msgid "Remove time estimate"
+msgstr "Eliminar el tiempo estimado"
msgid "Removed"
-msgstr ""
+msgstr "Eliminado"
msgid "Removed %{type} with id %{id}"
-msgstr ""
+msgstr "Eliminado %{type} con id %{id}"
msgid "Removed group can not be restored!"
msgstr "¡No se puede restaurar un grupo eliminado!"
msgid "Removed projects cannot be restored!"
-msgstr ""
+msgstr "¡No se pueden restaurar los proyectos eliminados!"
+
+msgid "Removes %{epic_ref} from child epics."
+msgstr "Eliminar %{epic_ref} de las tareas épicas hijas."
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr "Elimina el %{milestone_reference} hito."
+
+msgid "Removes all labels."
+msgstr "Elimina todas las etiquetas."
+
+msgid "Removes spent time."
+msgstr "Elimina el tiempo gastado."
+
+msgid "Removes the due date."
+msgstr "Elimina la fecha de vencimiento."
+
+msgid "Removes time estimate."
+msgstr "Elimina el tiempo estimado."
msgid "Removing group will cause all child projects and resources to be removed."
msgstr "Eliminar un grupo hará que todos los proyectos y recursos sean eliminados."
msgid "Removing license…"
-msgstr ""
+msgstr "Eliminando la licencia…"
msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
+msgstr "Al eliminar el proyecto se eliminarán su repositorio y todos los recursos relacionados incluyendo las incidencias, merge requests, etc."
msgid "Rename"
msgstr "Renombrar"
@@ -9233,7 +11026,7 @@ msgid "Rename folder"
msgstr "Renombrar carpeta"
msgid "Reopen epic"
-msgstr ""
+msgstr "Reabrir la tarea épica"
msgid "Reopen milestone"
msgstr "Reabrir hito"
@@ -9242,7 +11035,10 @@ msgid "Repair authentication"
msgstr "Reparar la autenticación"
msgid "Replace"
-msgstr ""
+msgstr "Reemplazar"
+
+msgid "Replace all label(s)"
+msgstr "Reemplazar todas las etiquetas"
msgid "Reply to comment"
msgstr "Responder a este comentario"
@@ -9253,14 +11049,14 @@ msgstr "Responda a este correo directamente o %{view_it_on_gitlab}."
msgid "Repo by URL"
msgstr "Repo por URL"
-msgid "Report abuse to GitLab"
-msgstr "Reportar abuso a GitLab"
+msgid "Report abuse to admin"
+msgstr ""
msgid "Reporting"
-msgstr ""
+msgstr "Informes"
msgid "Reports|%{failedString} and %{resolvedString}"
-msgstr ""
+msgstr "%{failedString} y %{resolvedString}"
msgid "Reports|Actions"
msgstr "Acciones"
@@ -9268,6 +11064,9 @@ msgstr "Acciones"
msgid "Reports|Class"
msgstr "Clase"
+msgid "Reports|Classname"
+msgstr "Nombre de la clase"
+
msgid "Reports|Confidence"
msgstr "Confianza"
@@ -9278,16 +11077,16 @@ msgid "Reports|Failure"
msgstr "Fallo"
msgid "Reports|Metrics reports are loading"
-msgstr ""
+msgstr "Los informes de las métricas se están cargando"
msgid "Reports|Metrics reports changed on %{numberOfChanges} %{pointsString}"
-msgstr ""
+msgstr "Los informes de las métricas se han modificado en %{numberOfChanges} %{pointsString}"
msgid "Reports|Metrics reports did not change"
-msgstr ""
+msgstr "Los informes de las métricas no han cambiado"
msgid "Reports|Metrics reports failed loading results"
-msgstr ""
+msgstr "Se ha producido un erro al cargar os resultados de los informes de métricas"
msgid "Reports|Severity"
msgstr "Severidad"
@@ -9296,25 +11095,19 @@ msgid "Reports|System output"
msgstr "Salida del sistema"
msgid "Reports|Test summary"
-msgstr ""
+msgstr "Resumen de la prueba"
msgid "Reports|Test summary failed loading results"
-msgstr ""
+msgstr "Se ha producido un error al cargar los resultados de la prueba"
msgid "Reports|Test summary results are being parsed"
-msgstr ""
+msgstr "Se están analizando los resultados de la prueba"
msgid "Reports|Vulnerability"
-msgstr ""
-
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
+msgstr "Vulnerabilidad"
msgid "Reports|no changed test results"
-msgstr ""
+msgstr "no hay cambios en los resultados de las pruebas"
msgid "Repository"
msgstr "Repositorio"
@@ -9326,13 +11119,13 @@ msgid "Repository URL"
msgstr "URL del repositorio"
msgid "Repository check was triggered."
-msgstr ""
+msgstr "Se activó la verificación del repositorio."
msgid "Repository cleanup"
msgstr "Limpieza del repositorio"
msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
-msgstr ""
+msgstr "Ha comenzado la limpieza del repositorio. Recibirá un correo electrónico una vez que la operación de limpieza haya finalizado."
msgid "Repository has no locks."
msgstr "El repositorio no tiene bloqueos."
@@ -9341,41 +11134,50 @@ msgid "Repository maintenance"
msgstr "Mantenimiento del repositorio"
msgid "Repository mirror"
-msgstr ""
+msgstr "Replica del repositorio"
msgid "Repository storage"
-msgstr ""
+msgstr "Almacenamiento del repositorio"
msgid "RepositorySettingsAccessLevel|Select"
-msgstr ""
+msgstr "Seleccionar"
msgid "Request Access"
msgstr "Solicitar acceso"
msgid "Requested %{time_ago}"
-msgstr ""
+msgstr "Solicitado %{time_ago}"
msgid "Requests Profiles"
msgstr ""
msgid "Require all users in this group to setup Two-factor authentication"
-msgstr ""
+msgstr "Requerir que todos los usuarios en este grupo configuren la autenticación de dos factores"
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
-msgstr ""
+msgstr "Requerir a todos los usuarios que acepten los términos del servicio y la política de privacidad cuando accedan a GitLab."
msgid "Require approval from code owners"
-msgstr ""
+msgstr "Requiere aprobación de los propietarios del código"
+
+msgid "Require user password to approve"
+msgstr "Requiere una contraseña de usuario para aprobar"
+
+msgid "Require users to prove ownership of custom domains"
+msgstr "Requerir a los usuarios desmostrar la propiedad de los dominios personalizados"
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Requiere aprobación de %{names}."
+msgstr[1] "Requiere %{count} aprobaciones más de %{names}."
msgid "Requires approval."
msgid_plural "Requires %d more approvals."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Requiere aprobación."
+msgstr[1] "Requiere %d aprobaciones más."
+
+msgid "Resend confirmation email"
+msgstr ""
msgid "Resend invite"
msgstr "Reenviar invitación"
@@ -9387,7 +11189,7 @@ msgid "Reset authorization key?"
msgstr "¿Reiniciar la clave de autorización?"
msgid "Reset health check access token"
-msgstr ""
+msgstr "Restablecer el token de acceso de verificación de estado"
msgid "Reset key"
msgstr "Reiniciar la clave"
@@ -9396,7 +11198,7 @@ msgid "Reset runners registration token"
msgstr "Reinicializar el token de registro del runner"
msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
-msgstr ""
+msgstr "Al restablecer la clave de autorización se invalidará la clave anterior. Las configuraciones de alerta existentes deberán actualizarse con la nueva clave."
msgid "Resolve all discussions in new issue"
msgstr "Resolver todas las discusiones en una nueva incidencia"
@@ -9411,16 +11213,25 @@ msgid "Resolved"
msgstr "Resuelto"
msgid "Resolved 1 discussion."
-msgstr ""
+msgstr "Resolver una discusión."
msgid "Resolved all discussions."
-msgstr ""
+msgstr "Resolver todas las discusiones."
+
+msgid "Resolved by %{name}"
+msgstr "Resuelto por %{name}"
+
+msgid "Resolved by %{resolvedByName}"
+msgstr "Resuelto por %{resolvedByName}"
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr "Resuelve las direcciones IP una vez y las utiliza para enviar peticiones"
msgid "Response"
msgstr "Respuesta"
msgid "Response didn't include `service_desk_address`"
-msgstr ""
+msgstr "La respuesta no contiene `service_desk_address`"
msgid "Response metrics (AWS ELB)"
msgstr "Métricas de respuesta (AWS ELB)"
@@ -9429,13 +11240,13 @@ msgid "Response metrics (Custom)"
msgstr "Métricas de respuesta (personalizadas)"
msgid "Response metrics (HA Proxy)"
-msgstr ""
+msgstr "Métricas de respuesta (HA Proxy)"
msgid "Response metrics (NGINX Ingress VTS)"
-msgstr ""
+msgstr "Métricas de respuesta (NGINX Ingress VTS)"
msgid "Response metrics (NGINX Ingress)"
-msgstr ""
+msgstr "Métricas de respuesta (NGINX)"
msgid "Response metrics (NGINX)"
msgstr "Respuesta métricas (NGINX)"
@@ -9447,7 +11258,7 @@ msgid "Resume"
msgstr "Reanudar"
msgid "Resume replication"
-msgstr ""
+msgstr "Reanudar la replicación"
msgid "Retry"
msgstr "Reintentar"
@@ -9456,6 +11267,9 @@ msgid "Retry this job"
msgstr "Reintentar este trabajo"
msgid "Retry this job in order to create the necessary resources."
+msgstr "Vuelva a intentar este trabajo para crear los recursos necesarios."
+
+msgid "Retry update"
msgstr ""
msgid "Retry verification"
@@ -9479,22 +11293,28 @@ msgid "Review"
msgstr "Revisión"
msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
-msgstr ""
+msgstr "Revise el proceso de configuración de los proveedores de servicios de su proveedor de identidad; en este caso, GitLab es el \"proveedor de servicios\" o la \"parte confiante\"."
msgid "Reviewing"
-msgstr ""
+msgstr "Revisando"
msgid "Reviewing (merge request !%{mergeRequestId})"
-msgstr ""
+msgstr "Revisando (merge request !%{mergeRequestId})"
msgid "Revoke"
msgstr "Revocar"
msgid "Revoked impersonation token %{token_name}!"
-msgstr ""
+msgstr "¡Token de suplantación revocado %{token_name}!"
msgid "Revoked personal access token %{personal_access_token_name}!"
-msgstr ""
+msgstr "Se ha revocado el token de acceso personal %{personal_access_token_name}!"
+
+msgid "RightSidebar|adding a"
+msgstr "Agregar a"
+
+msgid "RightSidebar|deleting the"
+msgstr "Eliminar el"
msgid "Roadmap"
msgstr "Hoja de ruta"
@@ -9503,34 +11323,34 @@ msgid "Run CI/CD pipelines for external repositories"
msgstr "Ejecutar los pipelines de CI/CD para los repositorios externos"
msgid "Run housekeeping"
-msgstr ""
+msgstr "Ejecutar tareas de mantenimiento"
msgid "Run tests against your code live using the Web Terminal"
-msgstr ""
+msgstr "Ejecutar las pruebas contra su código a través del terminal web"
msgid "Run untagged jobs"
msgstr "Ejecutar trabajos no etiquetados"
msgid "Runner cannot be assigned to other projects"
-msgstr ""
+msgstr "No se puede asignar el ejecutor a otros proyectos"
msgid "Runner runs jobs from all unassigned projects"
-msgstr ""
+msgstr "El ejecutor ejecuta los trabajos de todos los proyectos desasignados"
msgid "Runner runs jobs from all unassigned projects in its group"
-msgstr ""
+msgstr "El ejecutor ejecuta los trabajos de todos los proyectos desasignados"
msgid "Runner runs jobs from assigned projects"
-msgstr ""
+msgstr "El ejecutor ejecuta los trabajos de todos los proyectos asignados"
msgid "Runner token"
msgstr "Token del ejecutor"
msgid "Runner was not updated."
-msgstr ""
+msgstr "No se actualizó el ejecutor."
msgid "Runner was successfully updated."
-msgstr ""
+msgstr "El ejecutor se ha actualizado correctamente."
msgid "Runner will not receive any new jobs"
msgstr "El ejecutor no recibirá ningún trabajo nuevo"
@@ -9545,10 +11365,10 @@ msgid "Runners activated for this project"
msgstr "Ejecutores activos para este proyecto"
msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
+msgstr "Los ejecutores se pueden instalar en usuarios separados, en servidores o incluso en su máquina local."
msgid "Runners can be placed on separate users, servers, even on your local machine."
-msgstr ""
+msgstr "Los ejecutores se pueden colocar como usuarios separados, en servidores o incluso en su máquina local."
msgid "Runners currently online: %{active_runners_count}"
msgstr "Ejecutores actualmente en línea: %{active_runners_count}"
@@ -9560,7 +11380,7 @@ msgid "Runners page."
msgstr "Página de ejecutores."
msgid "Runners|You have used all your shared Runners pipeline minutes."
-msgstr ""
+msgstr "Ha utilizado todos los minutos de sus ejecutores compartidos en el pipeline."
msgid "Running"
msgstr "En ejecución"
@@ -9569,7 +11389,7 @@ msgid "Running…"
msgstr "Ejecutando…"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
-msgstr ""
+msgstr "Ejecuta una serie de tareas de mantenimiento dentro del repositorio actual, como comprimir las revisiones de los archivos y eliminar objetos no disponibles."
msgid "SAML SSO"
msgstr "SAML SSO"
@@ -9580,15 +11400,21 @@ msgstr "SAML SSO para %{group_name}"
msgid "SAML for %{group_name}"
msgstr "SAML para %{group_name}"
+msgid "SSH Key"
+msgstr "Clave SSH"
+
msgid "SSH Keys"
-msgstr "Llaves SSH"
+msgstr "Claves SSH"
msgid "SSH Keys Help"
-msgstr ""
+msgstr "Ayuda sobre las claves SSH"
msgid "SSH host keys"
msgstr "Claves de host SSH"
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr "Las claves SSH le permiten establecer una conexión segura entre su ordenador y GitLab."
+
msgid "SSH public key"
msgstr "Clave pública SSH"
@@ -9604,6 +11430,9 @@ msgstr "Guardar"
msgid "Save Changes"
msgstr "Guardar cambios"
+msgid "Save anyway"
+msgstr "Guardar de todos modos"
+
msgid "Save application"
msgstr "Guardar aplicación"
@@ -9611,11 +11440,14 @@ msgid "Save changes"
msgstr "Guardar los cambios"
msgid "Save changes before testing"
-msgstr ""
+msgstr "Guardar los cambios antes de realizar la prueba"
msgid "Save comment"
msgstr "Guardar comentario"
+msgid "Save password"
+msgstr "Guardar la contraseña"
+
msgid "Save pipeline schedule"
msgstr "Guardar programación del pipeline"
@@ -9623,7 +11455,7 @@ msgid "Save variables"
msgstr "Guardar variables"
msgid "Saving project."
-msgstr ""
+msgstr "Guardar proyecto."
msgid "Schedule a new pipeline"
msgstr "Programar un nuevo pipeline"
@@ -9644,10 +11476,10 @@ msgid "Scope"
msgstr "Alcance"
msgid "Scope not supported with disabled 'users_search' feature!"
-msgstr ""
+msgstr "¡El alcance no es compatible con la función 'users_search' deshabilitada!"
msgid "Scoped issue boards"
-msgstr ""
+msgstr "Tableros de incidencias con alcance limitado"
msgid "Scoped label"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr "Buscar ramas y etiquetas"
msgid "Search files"
msgstr "Buscar archivos"
+msgid "Search for a LDAP group"
+msgstr "Buscar un grupo de LDAP"
+
+msgid "Search for a group"
+msgstr "Buscar un grupo"
+
+msgid "Search for a user"
+msgstr "Buscar un usuario"
+
msgid "Search for projects, issues, etc."
msgstr "Buscar proyectos, incidencias, etc."
+msgid "Search forks"
+msgstr "Buscar forks"
+
msgid "Search groups"
msgstr "Buscar grupos"
@@ -9700,6 +11544,9 @@ msgstr "Buscar proyecto"
msgid "Search projects"
msgstr "Buscar proyectos"
+msgid "Search projects..."
+msgstr "Buscar proyectos..."
+
msgid "Search users"
msgstr "Buscar usuarios"
@@ -9734,13 +11581,13 @@ msgid "SearchAutocomplete|in this project"
msgstr "en este proyecto"
msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for \"%{term}\""
-msgstr ""
+msgstr "Mostrando %{from} - %{to} de %{count} %{scope} para \"%{term}\""
msgid "Seats currently in use"
-msgstr ""
+msgstr "Puestos actualmente en uso"
msgid "Seats in license"
-msgstr ""
+msgstr "Puestos en la licencia"
msgid "Secret"
msgstr "Secreto"
@@ -9749,40 +11596,37 @@ msgid "Security"
msgstr "Seguridad"
msgid "Security Dashboard"
-msgstr "Tablero de seguridad"
+msgstr "Panel de control de seguridad"
msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
-msgstr ""
+msgstr "Se ha producido un error al obtener los datos del panel de control. Por favor, compruebe su conexión de red y vuelva a intentarlo."
msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
-msgstr ""
+msgstr "Se ha producido un error al obtener los datos del panel de control. Por favor, compruebe su conexión de red y vuelva a intentarlo."
msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
-msgstr ""
+msgstr "Se ha producido un error al obtener los datos del panel de control. Por favor, compruebe su conexión de red y vuelva a intentarlo."
msgid "Security Dashboard|Issue Created"
msgstr "Incidencia creada"
msgid "Security Reports|Create issue"
-msgstr ""
+msgstr "Crear incidencia"
msgid "Security Reports|Dismiss vulnerability"
-msgstr ""
+msgstr "Informes de seguridad | Descartar vulnerabilidad"
msgid "Security Reports|Learn more about setting up your dashboard"
-msgstr ""
+msgstr "Obtenga más información sobre cómo configurar su panel de control"
msgid "Security Reports|More info"
msgstr "Más información"
-msgid "Security Reports|No Vulnerabilities"
-msgstr "Sin vulnerabilidades"
-
msgid "Security Reports|There was an error creating the issue."
-msgstr ""
+msgstr "Se ha producido un error al crear la incidencia."
msgid "Security Reports|There was an error creating the merge request."
-msgstr ""
+msgstr "Se ha producido un error al crear el merge request."
msgid "Security Reports|There was an error dismissing the vulnerability."
msgstr ""
@@ -9797,35 +11641,53 @@ msgid "Security Reports|Undo dismiss"
msgstr ""
msgid "Security Reports|We've found no vulnerabilities for your group"
-msgstr ""
+msgstr "No se han encontrado vulnerabilidades para su grupo"
msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
-msgstr ""
+msgstr "Aunque es raro que no haya vulnerabilidades para su grupo, puede suceder. En cualquier caso, le pedimos que verifique dos veces su configuración para asegurarse de que ha configurado su panel de control correctamente."
msgid "Security dashboard"
-msgstr ""
+msgstr "Panel de control de seguridad"
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr "Panel de control de seguridad muestra el último informe de seguridad. Úselo para encontrar y corregir vulnerabilidades."
-msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgid "SecurityDashboard|Confidence"
msgstr ""
+msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgstr "Monitorizar las vulnerabilidades en su código"
+
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
+msgstr "Activado el pipeline %{pipelineLink}"
+
+msgid "SecurityDashboard|Project"
msgstr ""
-msgid "See metrics"
+msgid "SecurityDashboard|Report type"
msgstr ""
-msgid "See the affected projects in the GitLab admin panel"
+msgid "SecurityDashboard|Severity"
msgstr ""
+msgid "See metrics"
+msgstr "Ver métricas"
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr "Ver los proyectos afectados en el panel de administración de GitLab"
+
msgid "Select"
msgstr "Seleccionar"
msgid "Select Archive Format"
msgstr "Seleccionar formato de archivo"
+msgid "Select Page"
+msgstr "Seleccionar página"
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr "Seleccione un archivo en la barra lateral izquierda para comenzar la edición. Posteriormente, podrá hacer commit de sus cambios."
+
msgid "Select a group to invite"
msgstr "Seleccione un grupo a invitar"
@@ -9833,10 +11695,10 @@ msgid "Select a namespace to fork the project"
msgstr "Seleccione un espacio de nombres para hacer un fork del proyecto"
msgid "Select a new namespace"
-msgstr ""
+msgstr "Seleccione un nuevo espacio de nombres"
msgid "Select a project to read Insights configuration file"
-msgstr ""
+msgstr "Seleccione un proyecto para leer el archivo de configuración de Insights"
msgid "Select a repository"
msgstr "Seleccione un repositorio"
@@ -9851,6 +11713,9 @@ msgid "Select an existing Kubernetes cluster or create a new one"
msgstr "Seleccione un clúster existente de Kubernetes o cree un cluster nuevo"
msgid "Select branch/tag"
+msgstr "Selecciona rama/etiqueta"
+
+msgid "Select group or project"
msgstr ""
msgid "Select members to invite"
@@ -9875,18 +11740,21 @@ msgid "Select target branch"
msgstr "Selecciona una rama de destino"
msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
+msgstr "Seleccione la rama que desea establecer como predeterminada para este proyecto. Todas los merge request y los commit se realizarán automáticamente contra ese branch a menos que especifique uno diferente."
msgid "Select the custom project template source group."
msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
-msgstr ""
+msgstr "Los niveles seleccionados no pueden ser utilizados por usuarios que no tengan permisos de admnistración para grupos, proyectos o fragmentos de código. Si el nivel público está restringido, los perfiles de usuario solo son visibles para los usuarios registrados."
msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
-msgstr ""
+msgstr "Al seleccionar un usuario de GitLab añadirá un link al usuario en la descripción de las incidencias, así como también, en los comentarios (por ejemplo, \"Por <a href=\"#\">@johnsmith</a>\"). Al hacer esto, también asociará y asignará dichas incidencias y comentarios con el usuario seleccionado."
msgid "Send an email notification to Developers."
+msgstr "Enviar una notificación por correo electrónico a los desarrolladores."
+
+msgid "Send confirmation email"
msgstr ""
msgid "Send email"
@@ -9905,13 +11773,13 @@ msgid "Sep"
msgstr "Sep"
msgid "Separate topics with commas."
-msgstr ""
+msgstr "Separar temas con comas."
msgid "September"
msgstr "Septiembre"
msgid "Server supports batch API only, please update your Git LFS client to version 1.0.1 and up."
-msgstr ""
+msgstr "El servidor solo admite API por lotes, actualice su cliente Git LFS a la versión 1.0.1 o superior."
msgid "Server version"
msgstr "Versión del servidor"
@@ -9920,43 +11788,43 @@ msgid "Serverless"
msgstr "Serverless"
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
-msgstr ""
+msgstr "Las métricas de llamadas a funciones serverless requiere que se instale primero Prometheus."
msgid "ServerlessDetails|Install Prometheus"
-msgstr ""
+msgstr "Instalar Prometheus"
msgid "ServerlessDetails|Invocation metrics loading or not available at this time."
-msgstr ""
+msgstr "Se están cargando las métricas de invocación o no están disponibles en este momento."
msgid "ServerlessDetails|Invocations"
-msgstr ""
+msgstr "Invocaciones"
msgid "ServerlessDetails|Kubernetes Pods"
-msgstr ""
+msgstr "Pods de Kubernetes"
msgid "ServerlessDetails|More information"
-msgstr ""
+msgstr "Más información"
msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
-msgstr ""
+msgstr "Número de pods de Kubernetes en uso a lo largo del tiempo según la necesidad."
msgid "ServerlessDetails|pod in use"
-msgstr ""
+msgstr "pod en uso"
msgid "ServerlessDetails|pods in use"
-msgstr ""
+msgstr "pods en uso"
msgid "ServerlessURL|Copy URL to clipboard"
-msgstr ""
+msgstr "Copiar la URL al portapapeles"
msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
-msgstr ""
+msgstr "Para comenzar a utilizar las funciones como servicio, debe instalar Knative en su clúster Kubernetes."
msgid "Serverless|Getting started with serverless"
-msgstr ""
+msgstr "Comenzando con serverless"
msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
-msgstr ""
+msgstr "Sí cree que ninguno de estos casos aplican, por favor, vuelva a intentarlo más tarde. Es posible que los datos de la función todavía no esté disponible."
msgid "Serverless|Install Knative"
msgstr "Instalar Knative"
@@ -9968,7 +11836,10 @@ msgid "Serverless|No functions available"
msgstr "No hay funciones disponibles"
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
-msgstr ""
+msgstr "Actualmente no hay datos de función disponibles desde Knative. Esto puede deberse por a múltiples razones, incluyendo:"
+
+msgid "Service"
+msgstr "Servicio"
msgid "Service Desk"
msgstr "Service Desk"
@@ -9986,49 +11857,55 @@ msgid "Session expiration, projects limit and attachment size."
msgstr "Caducidad de la sesión, límite de proyectos y tamaño de los archivos adjuntos."
msgid "Set a default template for issue descriptions."
-msgstr ""
+msgstr "Establecer una plantilla predeterminada para las descripciones de las incidencias."
msgid "Set a number of approvals required, the approvers and other approval settings."
-msgstr ""
+msgstr "Establezca el número de aprobaciones requeridas, los aprobadores y otras opciones de configuración de las aprobaciones."
msgid "Set a password on your account to pull or push via %{protocol}."
-msgstr "Establezca una contraseña en su cuenta para actualizar o enviar a través de %{protocol}."
+msgstr "Establezca una contraseña en su cuenta para hacer pull o push vía %{protocol}."
msgid "Set a template repository for projects in this group"
-msgstr ""
+msgstr "Establecer un repositorio de plantillas para los proyectos de este grupo"
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
-msgstr ""
+msgstr "Establecer y restringir los niveles de visibilidad por defecto. Configure origenes para la importación y el protocolo de acceso de Git."
+
+msgid "Set due date"
+msgstr "Establecer fecha de finalización"
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
-msgstr ""
+msgstr "Establecer el tiempo máximo de sesión para el terminal de web."
+
+msgid "Set milestone"
+msgstr "Establecer hito"
msgid "Set new password"
msgstr "Establecer una nueva contraseña"
msgid "Set notification email for abuse reports."
-msgstr ""
-
-msgid "Set number of approvers required before open merge requests can be merged"
-msgstr ""
+msgstr "Establecer una dirección de correo electrónico de notificación para los informes de abuso de uso."
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
-msgstr ""
+msgstr "Establezca los requisitos para que un usuario pueda iniciar sesión. Habilite la autenticación basada en dos factores."
msgid "Set the default expiration time for each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: <code>4 mins 2 sec</code>, <code>2h42min</code>."
-msgstr ""
+msgstr "Establezca el tiempo de caducidad predeterminado para los artefactos generados en cada trabajo. 0 para una caducidad ilimitada. La unidad predeterminada son segundos, pero puede definir una alternativa. Por ejemplo: <code>4 minutos 2 segundos</code>, <code>2h42min</code>."
msgid "Set the duration for which the jobs will be considered as old and expired. Once that time passes, the jobs will be archived and no longer able to be retried. Make it empty to never expire jobs. It has to be no less than 1 day, for example: <code>15 days</code>, <code>1 month</code>, <code>2 years</code>."
-msgstr ""
+msgstr "Establezca la duración durante la cual los trabajos se considerarán antiguos y vencidos. Una vez pasado ese tiempo, los trabajos se archivarán y ya no se podrá volver a reintentar su ejecución. Establezca este campo como nulo para que los trabajos no caduquen. Este valor, no debe ser inferior a 1 día, por ejemplo: <code>15 días</code>, <code>1 mes</code>, <code>2 años</code>."
msgid "Set the maximum file size for each job's artifacts"
-msgstr ""
+msgstr "Establecer el tamaño máximo de archivo para los artefactos de cada trabajo"
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
-msgstr ""
+msgstr "Establece el número máximo de minutos de pipeline que un grupo puede utilize en los ejecutores compartidos mensualmente. Establezca esta valor a 0 para obtener un número ilimitado."
+
+msgid "Set time estimate"
+msgstr "Establecer el tiempo estimado"
msgid "Set up CI/CD"
msgstr "Configurar CI/CD"
@@ -10046,25 +11923,28 @@ msgid "Set up new U2F device"
msgstr "Configurar nuevo dispositivo U2F"
msgid "Set up new password"
-msgstr "Configurar nueva contraseña"
+msgstr "Establecer una nueva contraseña"
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr "Establecer el peso"
+
msgid "SetPasswordToCloneLink|set a password"
msgstr "establecer una contraseña"
msgid "SetStatusModal|Add status emoji"
-msgstr ""
+msgstr "Añadir emoji de estado"
msgid "SetStatusModal|Clear status"
-msgstr ""
+msgstr "Borrar estado"
msgid "SetStatusModal|Edit status"
-msgstr ""
+msgstr "Editar estado"
msgid "SetStatusModal|Remove status"
-msgstr ""
+msgstr "Eliminar estado"
msgid "SetStatusModal|Set a status"
msgstr "Establecer un estado"
@@ -10073,11 +11953,23 @@ msgid "SetStatusModal|Set status"
msgstr "Establecer estado"
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
-msgstr ""
+msgstr "Lo sentimos, no hemos podido establecer su estado. Por favor, inténtelo de nuevo más tarde."
msgid "SetStatusModal|What's your status?"
msgstr "¿Cuál es su estado?"
+msgid "Sets the due date to %{due_date}."
+msgstr "Establecer la fecha de vencimiento a %{due_date}."
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr "Establece el hito en %{milestone_reference}."
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr "Establece el tiempo estimado a %{time_estimate}."
+
+msgid "Sets weight to %{weight}."
+msgstr "Establecer el peso a %{weight}."
+
msgid "Settings"
msgstr "Configuración"
@@ -10085,7 +11977,7 @@ msgid "Share"
msgstr "Compartir"
msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
-msgstr ""
+msgstr "Comparta <strong>%{sso_label}</strong> con los diferentes miembros para que puedan iniciar sesión en su grupo a través de su proveedor de identidad"
msgid "Shared Runners"
msgstr "Ejecturores compartidos"
@@ -10093,21 +11985,33 @@ msgstr "Ejecturores compartidos"
msgid "Shared projects"
msgstr "Proyectos compartidos"
+msgid "Shared runners help link"
+msgstr "Enlace de ayuda de los ejecutores compartidos"
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
-msgstr ""
+msgstr "Al reiniciar los minutos del pipeline para este espacio de nombres, los minutos utilizados actualmente se establecerán a cero."
msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
-msgstr ""
+msgstr "Restablecer minutos de los 'pipelines'"
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
-msgstr ""
+msgstr "Restablecer los minutos utilizados de los 'pipelines'"
msgid "Sherlock Transactions"
msgstr "Transacciones de Sherlock"
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr "Mostrar toda la actividad"
+msgid "Show archived projects"
+msgstr "Mostrar proyectos archivados"
+
+msgid "Show archived projects only"
+msgstr "Mostrar solo proyectos archivados"
+
msgid "Show command"
msgstr "Mostrar comando"
@@ -10118,19 +12022,16 @@ msgid "Show complete raw log"
msgstr "Mostrar el registro completo sin procesar"
msgid "Show file browser"
-msgstr ""
+msgstr "Mostrar el explorador de archivos"
msgid "Show latest version"
msgstr "Mostrar la última versión"
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr "Mostrar páginas padre"
msgid "Show parent subgroups"
-msgstr ""
+msgstr "Mostrar subgrupos padre"
msgid "Show whitespace changes"
msgstr "Mostrar los espacios en blanco de los cambios"
@@ -10150,7 +12051,7 @@ msgid "Sidebar|None"
msgstr "Ninguno"
msgid "Sidebar|Only numeral characters allowed"
-msgstr ""
+msgstr "Solo se permiten caracteres numéricos"
msgid "Sidebar|Weight"
msgstr "Peso"
@@ -10162,7 +12063,7 @@ msgid "Sign in / Register"
msgstr "Iniciar sesión / Registro"
msgid "Sign in to \"%{group_name}\""
-msgstr ""
+msgstr "Iniciar sesión en %{group_name}\""
msgid "Sign in using smart card"
msgstr "Inicie sesión mediante una tarjeta inteligente"
@@ -10179,21 +12080,42 @@ msgstr "Inicie sesión con una tarjeta inteligente"
msgid "Sign out"
msgstr "Cerrar sesión"
+msgid "Sign out & Register"
+msgstr "Cerrar la sesión y regístrarse"
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr "¡Registro creado correctamente! Por favor, confirme su dirección de correo electrónico para iniciar sesión."
+
msgid "Sign-in restrictions"
msgstr "Restricciones de inicio de sesión"
msgid "Sign-up restrictions"
msgstr "Restricciones de registro"
-msgid "Signing in using %{label} has been disabled"
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
msgstr ""
-msgid "Signing in using your %{label} account without a pre-existing GitLab account is not allowed."
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
msgstr ""
+msgid "Signed in"
+msgstr "Sesión iniciada"
+
+msgid "Signed in with %{authentication} authentication"
+msgstr "Iniciado con autenticación de %{authentication}"
+
+msgid "Signing in using %{label} has been disabled"
+msgstr "Se ha deshabilitado el inicio de sesión utilizando %{label}"
+
+msgid "Signing in using your %{label} account without a pre-existing GitLab account is not allowed."
+msgstr "No está permitido iniciar sesión usando su cuenta de %{label} sin una cuenta de GitLab preexistente."
+
msgid "Similar issues"
msgstr "Incidencias similares"
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr "Tamaño"
@@ -10203,6 +12125,9 @@ msgstr "Configuración del tamaño y del dominio para los sitios web estáticos"
msgid "Size limit per repository (MB)"
msgstr "Límite de tamaño por repositorio (MB)"
+msgid "Skip this for now"
+msgstr "Omitir esto por ahora"
+
msgid "Slack application"
msgstr "Aplicación Slack"
@@ -10219,37 +12144,37 @@ msgid "Smartcard authentication failed: client certificate header is missing."
msgstr "Falló la autenticación de la tarjeta inteligente: falta la cabecera del certificado del cliente."
msgid "Snippet Contents"
-msgstr ""
+msgstr "Contenido del fragmento de código"
msgid "Snippets"
msgstr "Fragmentos de código"
msgid "SnippetsEmptyState|Explore public snippets"
-msgstr ""
+msgstr "Explorar fragmentos de código públicos"
msgid "SnippetsEmptyState|New snippet"
-msgstr ""
+msgstr "Nuevo fragmento de código"
msgid "SnippetsEmptyState|No snippets found"
-msgstr ""
+msgstr "No se encontraron fragmentos de código"
msgid "SnippetsEmptyState|Snippets are small pieces of code or notes that you want to keep."
-msgstr ""
+msgstr "Los fragmentos de código son pequeños piezas de código o notas que desea conservar."
msgid "SnippetsEmptyState|There are no snippets to show."
-msgstr ""
+msgstr "No hay fragmentos de código que mostrar."
msgid "SnippetsEmptyState|They can be either public or private."
-msgstr ""
+msgstr "Pueden ser públicos o privados."
msgid "Some email servers do not support overriding the email sender name. Enable this option to include the name of the author of the issue, merge request or comment in the email body instead."
-msgstr ""
+msgstr "Algunos servidores de correo electrónico no permiten sobreescribir el nombre del remitente del correo electrónico. Habilite esta opción para incluir el nombre del autor de la incidencia, del merge request o del comentario en el cuerpo del correo electrónico."
msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
-msgstr ""
+msgstr "Alguien editó este %{issueType} al mismo tiempo que usted. La descripción se ha actualizado y deberá volver a realizar los cambios."
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
-msgstr ""
+msgstr "Alguien editó este merge request al mismo tiempo que lo hizo usted. Por favor, actualice la página para ver los cambios."
msgid "Something went wrong on our end"
msgstr "Algo salió mal por nuestra parte"
@@ -10261,7 +12186,7 @@ msgid "Something went wrong on our end. Please try again!"
msgstr "Algo salió mal en nuestro lado. ¡Por favor, inténtelo de nuevo!"
msgid "Something went wrong on our end. Please try again."
-msgstr ""
+msgstr "Algo salió mal en por nuestra parte. ¡Por favor, inténtelo de nuevo!."
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr "Algo salió mal al intentar cambiar la confidencialidad de esta incidencia. ¡Por favor, inténtelo de nuevo!"
@@ -10272,14 +12197,17 @@ msgstr "Algo salió mal al intentar cambiar el estado de bloqueo de este %{issua
msgid "Something went wrong when toggling the button"
msgstr "Algo salió mal al cambiar el estado del botón. ¡Por favor, inténtelo de nuevo!"
+msgid "Something went wrong while adding your award. Please try again."
+msgstr "Se ha producido un error al agregar su premio. Por favor, inténtalo de nuevo."
+
msgid "Something went wrong while applying the suggestion. Please try again."
-msgstr ""
+msgstr "Se ha producido un error al aplicar la sugerencia. Por favor, inténtelo de nuevo."
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr "Algo salió mal al cerrar la incidencia %{issuable}. ¡Por favor, inténtelo de nuevo!"
msgid "Something went wrong while deleting the source branch. Please try again."
-msgstr ""
+msgstr "Se ha producido un error al eliminar la rama origen. Por favor, inténtelo de nuevo."
msgid "Something went wrong while fetching %{listType} list"
msgstr "Algo salió mal al obtener la lista de %{listType}. ¡Por favor, inténtelo de nuevo!"
@@ -10290,8 +12218,11 @@ msgstr "Algo salió mal al buscar comentarios. Inténtalo de nuevo. ¡Por favor,
msgid "Something went wrong while fetching group member contributions"
msgstr "Algo salió mal al obtener las contribuciones de los miembros del grupo. ¡Por favor, inténtelo de nuevo!"
+msgid "Something went wrong while fetching latest comments."
+msgstr "Se ha producido un error al obtener los últimos comentarios."
+
msgid "Something went wrong while fetching related merge requests."
-msgstr ""
+msgstr "Se ha producido un error al obtener los merge request relacionados."
msgid "Something went wrong while fetching the environments for this merge request. Please try again."
msgstr "Algo salió mal al buscar los entornos para este merge request. ¡Por favor, inténtelo de nuevo!"
@@ -10303,7 +12234,7 @@ msgid "Something went wrong while fetching the registry list."
msgstr "Se ha producido un error mientras se obtenía la lista de registros."
msgid "Something went wrong while merging this merge request. Please try again."
-msgstr ""
+msgstr "Se ha producido un error, mientras se realizaba el merge request. Por favor, inténtelo de nuevo."
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
msgstr "Algo salió mal al volver a abrir la incidencia %{issuable}. ¡Por favor, inténtelo de nuevo!"
@@ -10314,18 +12245,21 @@ msgstr "Algo salió mal al resolver esta discusión. ¡Por favor, inténtelo de
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr "Algo salió mal, no se puede agregar %{project} al panel de control"
-msgid "Something went wrong, unable to get operations projects"
-msgstr "Algo salió mal, no es posible obtener los proyectos operativos"
+msgid "Something went wrong, unable to get projects"
+msgstr "Se ha producido un error al obtener los proyectos"
msgid "Something went wrong, unable to remove project"
-msgstr ""
+msgstr "Se ha producido un error al eliminar el proyecto"
msgid "Something went wrong, unable to search projects"
-msgstr ""
+msgstr "Se ha producido un error al buscar los proyectos"
msgid "Something went wrong. Please try again."
msgstr "Algo salió mal. ¡Por favor, inténtelo de nuevo!"
+msgid "Something went wrong. Try again later."
+msgstr "Se ha producido un error. Por favor, inténtelo más tarde."
+
msgid "Sorry, no epics matched your search"
msgstr "Lo sentimos, no hay tareas épicas que coincidan con su búsqueda"
@@ -10333,13 +12267,13 @@ msgid "Sorry, no projects matched your search"
msgstr "Lo sentimos, no hay proyectos que coincidan con su búsqueda"
msgid "Sorry, your filter produced no results"
-msgstr ""
+msgstr "Lo sentimos, su filtro no ha producido ningún resultado"
msgid "Sort by"
msgstr "Ordenar por"
msgid "Sort direction"
-msgstr ""
+msgstr "Dirección de clasificación"
msgid "SortOptions|Access level, ascending"
msgstr "Nivel de acceso, ascendente"
@@ -10386,23 +12320,26 @@ msgstr "Menos popular"
msgid "SortOptions|Less weight"
msgstr "Menos peso"
+msgid "SortOptions|Manual"
+msgstr "Manual"
+
msgid "SortOptions|Milestone due date"
-msgstr ""
+msgstr "Fecha de finalización del hito"
msgid "SortOptions|Milestone due later"
-msgstr ""
+msgstr "Hitos que finalizan más tarde"
msgid "SortOptions|Milestone due soon"
-msgstr ""
+msgstr "Hitos que finalizan pronto"
msgid "SortOptions|More weight"
-msgstr ""
+msgstr "Más peso"
msgid "SortOptions|Most popular"
msgstr "Más populares"
msgid "SortOptions|Most stars"
-msgstr ""
+msgstr "Más populares"
msgid "SortOptions|Name"
msgstr "Nombre"
@@ -10414,19 +12351,19 @@ msgid "SortOptions|Name, descending"
msgstr "Nombre, descendente"
msgid "SortOptions|Oldest created"
-msgstr ""
+msgstr "Creado más antiguo"
msgid "SortOptions|Oldest joined"
-msgstr ""
+msgstr "Incorporación más antigua"
msgid "SortOptions|Oldest last activity"
-msgstr ""
+msgstr "Última actividad más antigua"
msgid "SortOptions|Oldest sign in"
-msgstr ""
+msgstr "Registro más antiguo"
msgid "SortOptions|Oldest updated"
-msgstr ""
+msgstr "Actualizado más antiguo"
msgid "SortOptions|Popularity"
msgstr "Popularidad"
@@ -10435,16 +12372,22 @@ msgid "SortOptions|Priority"
msgstr "Prioridad"
msgid "SortOptions|Recent last activity"
-msgstr ""
+msgstr "Últimas actividades recientes"
msgid "SortOptions|Recent sign in"
-msgstr ""
+msgstr "Registro más reciente"
+
+msgid "SortOptions|Sort direction"
+msgstr "Dirección de clasificación"
+
+msgid "SortOptions|Stars"
+msgstr "Estrellas"
msgid "SortOptions|Start date"
msgstr "Fecha de inicio"
msgid "SortOptions|Start later"
-msgstr ""
+msgstr "Comienza más tarde"
msgid "SortOptions|Start soon"
msgstr "Comienza pronto"
@@ -10462,10 +12405,10 @@ msgid "Source code"
msgstr "Código fuente"
msgid "Source is not available"
-msgstr ""
+msgstr "El origen no esta disponible"
msgid "Source project cannot be found."
-msgstr ""
+msgstr "No se puede encontrar el proyecto."
msgid "Spam Logs"
msgstr "Registros de correo no deseado"
@@ -10480,22 +12423,22 @@ msgid "Specific Runners"
msgstr "Ejecutores específicos"
msgid "Specify an e-mail address regex pattern to identify default internal users."
-msgstr ""
+msgstr "Especifique un patrón para la expresión regular de direcciones de correo electrónico para identificar usuarios internos predeterminados."
msgid "Specify the following URL during the Runner setup:"
-msgstr ""
+msgstr "Especifique la siguiente dirección URL durante la configuración del ejecutor:"
msgid "Squash commit message"
-msgstr ""
+msgstr "Modificar el mensaje de commit"
msgid "Squash commits"
-msgstr ""
+msgstr "Squash commits"
msgid "Stage"
msgstr ""
msgid "Stage & Commit"
-msgstr ""
+msgstr "Stage & Commit"
msgid "Stage all changes"
msgstr ""
@@ -10510,6 +12453,9 @@ msgid "Staged %{type}"
msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
+msgstr "Resalte una etiqueta para convertirla en una etiqueta con prioridad. Ordene las etiquetas priorizadas para cambiar su prioridad relativa, arrastrando."
+
+msgid "Star toggle failed. Try again later."
msgstr ""
msgid "StarProject|Star"
@@ -10525,25 +12471,28 @@ msgid "Starred projects"
msgstr "Proyectos favoritos"
msgid "StarredProjectsEmptyState|Visit a project page and press on a star icon. Then, you can find the project on this page."
-msgstr ""
+msgstr "Visite una página de proyecto y haga click sobre el ícono de una estrella. Posteriormente, podrá encontrar el proyecto en esta página."
msgid "StarredProjectsEmptyState|You don't have starred projects yet."
-msgstr ""
+msgstr "Aún no tiene proyectos destacados."
msgid "Stars"
msgstr "Estrellas"
msgid "Start GitLab Ultimate trial"
-msgstr ""
+msgstr "Iniciar el periodo de prueba de GitLab Ultimate"
+
+msgid "Start Indexing"
+msgstr "Iniciar indexado"
msgid "Start Web Terminal"
-msgstr ""
+msgstr "Iniciar Terminal web"
msgid "Start a %{new_merge_request} with these changes"
msgstr "Iniciar una %{new_merge_request} con estos cambios"
msgid "Start a new merge request"
-msgstr ""
+msgstr "Iniciar un nuevo merge request"
msgid "Start a review"
msgstr "Comenzar una revisión"
@@ -10552,18 +12501,24 @@ msgid "Start and due date"
msgstr "Fechas de inicio y de fin"
msgid "Start cleanup"
-msgstr ""
+msgstr "Iniciar la limpieza"
msgid "Start date"
msgstr "Fecha de inicio"
msgid "Start discussion"
-msgstr ""
+msgstr "Iniciar una discusión"
msgid "Start discussion & close %{noteable_name}"
-msgstr ""
+msgstr "Iniciar la discusión y cerrar %{noteable_name}"
msgid "Start discussion & reopen %{noteable_name}"
+msgstr "Iniciar la discusión y volver a abrir %{noteable_name}"
+
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
msgstr ""
msgid "Start the Runner!"
@@ -10579,13 +12534,13 @@ msgid "Started %{startsIn}"
msgstr "Iniciado %{startsIn}"
msgid "Started asynchronous removal of all repository check states."
-msgstr ""
+msgstr "Se inició la eliminación asíncrona de todos los estados de verificación del repositorio."
msgid "Starting..."
msgstr "Iniciando..."
msgid "Starts %{startsIn}"
-msgstr ""
+msgstr "Comienza %{startsIn}"
msgid "Starts at (UTC)"
msgstr "Comienza a las (UTC)"
@@ -10626,12 +12581,18 @@ msgstr "Almacenamiento"
msgid "Storage:"
msgstr "Almacenamiento:"
+msgid "StorageSize|Unknown"
+msgstr "Desconocido"
+
msgid "Subgroups"
msgstr "Sub-grupos"
msgid "Subgroups and projects"
msgstr "Subgrupos y proyectos"
+msgid "Subkeys"
+msgstr "Subclaves"
+
msgid "Submit as spam"
msgstr "Enviar como correo no deseado"
@@ -10662,107 +12623,176 @@ msgstr "Suscríbase al calendario"
msgid "Subscribed"
msgstr "Suscrito"
+msgid "Subscription"
+msgstr "Suscripción"
+
msgid "SubscriptionTable|Billing"
-msgstr ""
+msgstr "Facturación"
msgid "SubscriptionTable|Free"
-msgstr ""
+msgstr "Gratis"
msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
-msgstr ""
+msgstr "GitLab le permite continuar utilizando su suscripción incluso si excede la cantidad de puestos que compró. Deberá pagar estos puestos en el momento de la renovación."
msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
-msgstr ""
+msgstr "GitLab.com %{planName} %{suffix}"
msgid "SubscriptionTable|Last invoice"
-msgstr ""
+msgstr "Última factura"
msgid "SubscriptionTable|Loading subscriptions"
-msgstr ""
+msgstr "Cargando suscripciones"
msgid "SubscriptionTable|Manage"
-msgstr ""
+msgstr "Administrar"
msgid "SubscriptionTable|Max seats used"
-msgstr ""
+msgstr "Número máximo de puestos utilizados"
msgid "SubscriptionTable|Next invoice"
-msgstr ""
+msgstr "Próxima factura"
msgid "SubscriptionTable|Seats currently in use"
-msgstr ""
+msgstr "Puestos actualmente en uso"
msgid "SubscriptionTable|Seats in subscription"
-msgstr ""
+msgstr "Puestos en la suscripción"
msgid "SubscriptionTable|Seats owed"
-msgstr ""
+msgstr "Número máximo de puestos adeudados"
msgid "SubscriptionTable|Subscription end date"
-msgstr ""
+msgstr "Fecha de finalización de la suscripción"
msgid "SubscriptionTable|Subscription start date"
-msgstr ""
+msgstr "Fecha de inicio de la suscripción"
msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
-msgstr ""
+msgstr "Esta es la última vez que el equipo de GitLab.com se puso en contacto con usted para liquidar los saldos pendientes."
msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
-msgstr ""
+msgstr "Este es el número máximo de usuarios que han existido al mismo tiempo desde que se inició esta suscripción."
msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
-msgstr ""
+msgstr "Esta es la próxima fecha en la que el equipo de GitLab.com se pondrá en contacto con usted para resolver cualquier deuda pendiente."
msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
-msgstr ""
+msgstr "Este es el número de puestos que necesita comprar si actualiza a un plan de pago."
msgid "SubscriptionTable|Trial"
msgstr "Prueba"
msgid "SubscriptionTable|Trial end date"
-msgstr ""
+msgstr "Tabla de suscripción | Fecha de finalización de prueba"
msgid "SubscriptionTable|Trial start date"
-msgstr ""
+msgstr "Fecha de inicio de la versión de prueba"
msgid "SubscriptionTable|Upgrade"
-msgstr ""
+msgstr "Actualizar"
msgid "SubscriptionTable|Usage"
-msgstr ""
+msgstr "Uso"
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
-msgstr ""
+msgstr "El recuento de uso se realiza una vez al día a 12:00 PM."
+
+msgid "Subtracts"
+msgstr "Sustraer"
msgid "Successfully blocked"
-msgstr ""
+msgstr "Bloqueado con éxito"
msgid "Successfully confirmed"
-msgstr ""
+msgstr "Confirmado con éxito"
msgid "Successfully deleted U2F device."
-msgstr ""
+msgstr "Dispositivo U2F eliminado con éxito."
msgid "Successfully removed email."
-msgstr ""
+msgstr "Correo electrónico eliminado con éxito."
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
-msgstr ""
+msgstr "Se ha programado un pipeline a ejecutar. Vaya a la página %{pipelines_link_start}Pipelines%{pipelines_link_end} para obtener más detalles."
msgid "Successfully unblocked"
-msgstr ""
+msgstr "Desbloqueado con éxito"
msgid "Successfully unlocked"
-msgstr ""
+msgstr "Desbloqueado con éxito"
msgid "Suggested change"
msgstr "Cambio sugerido"
+msgid "SuggestedColors|Bright green"
+msgstr "Verde brillante"
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr "Cian grisáceo oscuro"
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr "Azul oscuro (moderado)"
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr "Naranja oscuro (moderado)"
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr "Rosa oscuro (moderado)"
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr "Violeta oscuro (moderado)"
+
+msgid "SuggestedColors|Feijoa"
+msgstr "Verde feijoa"
+
+msgid "SuggestedColors|Lime green"
+msgstr "Verde lima"
+
+msgid "SuggestedColors|Moderate blue"
+msgstr "Azul (moderado)"
+
+msgid "SuggestedColors|Pure red"
+msgstr "Rojo puro"
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr "Azul ligeramente desaturado"
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr "Verde ligeramente desaturado"
+
+msgid "SuggestedColors|Soft orange"
+msgstr "Naranja suave"
+
+msgid "SuggestedColors|Soft red"
+msgstr "Rojo suave"
+
+msgid "SuggestedColors|Strong pink"
+msgstr "Rosa fuerte"
+
+msgid "SuggestedColors|Strong red"
+msgstr "Rojo fuerte"
+
+msgid "SuggestedColors|Strong yellow"
+msgstr "Amarillo fuerte"
+
+msgid "SuggestedColors|UA blue"
+msgstr "Azul UA"
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr "Azul muy oscuro desaturado"
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr "Verde lima muy oscuro"
+
+msgid "SuggestedColors|Very pale orange"
+msgstr "Naranja muy pálido"
+
msgid "Sunday"
msgstr "Domingo"
msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
-msgstr ""
+msgstr "El soporte para certificados personalizados está deshabilitado. Pida al administrador de su sistema que lo active."
msgid "Support page URL"
msgstr "URL de la página de soporte"
@@ -10770,6 +12800,12 @@ msgstr "URL de la página de soporte"
msgid "Switch branch/tag"
msgstr "Cambiar rama/etiqueta"
+msgid "Switch to GitLab Next"
+msgstr "Cambiar a GitLab Next"
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr "Sincronizar información"
@@ -10780,7 +12816,7 @@ msgid "System Hooks"
msgstr "Hooks de sistema"
msgid "System Hooks Help"
-msgstr ""
+msgstr "Ayuda de los hooks del sistema"
msgid "System Info"
msgstr "Información del sistema"
@@ -10789,10 +12825,10 @@ msgid "System default (%{default})"
msgstr "Sistema predeterminado (%{default})"
msgid "System header and footer"
-msgstr ""
+msgstr "Encabezado y pie de página del sistema"
msgid "System hook was successfully updated."
-msgstr ""
+msgstr "El hook del sistema se actualizó correctamente."
msgid "System metrics (Custom)"
msgstr "Métricas del sistema (personalizadas)"
@@ -10800,18 +12836,30 @@ msgstr "Métricas del sistema (personalizadas)"
msgid "System metrics (Kubernetes)"
msgstr "Métricas del sistema (Kubernetes)"
+msgid "Table of Contents"
+msgstr "Tabla de contenidos"
+
msgid "Tag"
msgstr "Etiqueta"
msgid "Tag list:"
msgstr "Listas de etiquetas:"
+msgid "Tag this commit."
+msgstr "Etiquetar este commit."
+
msgid "Tags"
msgstr "Etiquetas"
msgid "Tags feed"
msgstr "Feed de tags"
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr "Etiqueta este commit a %{tag_name} con \"%{message}\"."
+
+msgid "Tags this commit to %{tag_name}."
+msgstr "Etiqueta este commit a %{tag_name}."
+
msgid "Tags:"
msgstr "Etiquetas:"
@@ -10834,7 +12882,7 @@ msgid "TagsPage|Delete tag"
msgstr "Eliminar etiqueta"
msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
-msgstr ""
+msgstr "¿Está seguro que desea eliminar la etiqueta %{tag_name}?. Esta acción no se podrá deshacer"
msgid "TagsPage|Edit release notes"
msgstr "Editar las notas de la versión"
@@ -10870,7 +12918,7 @@ msgid "TagsPage|Tags"
msgstr "Etiquetas"
msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
-msgstr ""
+msgstr "Los tags de git le permiten marcar puntos importantes y específicos en la historia del proyecto"
msgid "TagsPage|This tag has no release notes."
msgstr "Esta etiqueta no tiene notas de la versión."
@@ -10888,11 +12936,14 @@ msgid "Target Branch"
msgstr "Rama de destino"
msgid "Target branch"
-msgstr ""
+msgstr "Rama de destino"
msgid "Team"
msgstr "Equipo"
+msgid "Team domain"
+msgstr "Dominio del equipo"
+
msgid "Template"
msgstr "Plantilla"
@@ -10905,6 +12956,9 @@ msgstr "Terminal"
msgid "Terminal for environment"
msgstr "Terminal para el entorno"
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "Términos del acuerdo de servicio y de la política de privacidad"
@@ -10915,51 +12969,81 @@ msgid "Test SAML SSO"
msgstr "Prueba SAML SSO"
msgid "Test coverage parsing"
-msgstr ""
+msgstr "Análisis de cobertura de las pruebas"
msgid "Test failed."
-msgstr ""
+msgstr "Prueba fallida."
+
+msgid "Test settings and save changes"
+msgstr "Probar los ajustes y los guardar cambios"
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr "Asegúrese de que uno de sus proyectos tenga merge requests."
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr "Asegúrese de que el proyecto tenga trabajos de CI."
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr "Asegúrese de que el proyecto tenga pipelines de CI."
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr "Asegúrese de que el proyecto tiene por lo menos un commit."
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr "Asegúrese de que el proyecto tenga incidencias."
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr "Asegúrese de que el proyecto tenga merge requests."
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr "Asegúrese de que el proyecto tenga notas."
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr "Asegúrese de que el wiki está habilitado y tiene páginas."
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
-msgstr ""
+msgstr "Gracias por su informe. Un administrador de GitLab lo examinará en breve."
msgid "Thanks! Don't show me this again"
msgstr "¡Gracias! No mostrar esto de nuevo"
msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
-msgstr ""
+msgstr "El grupo \"%{group_path}\" le permite iniciar sesión utilizando su cuenta de inicio de sesión único"
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "El %{type} contiene el siguiente error:"
+msgstr[1] "El %{type} contiene los siguientes errores:"
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
-msgstr ""
+msgstr "La búsqueda avanzada global de GitLab es un potente servicio de búsqueda que le permite ahorrar tiempo. En vez de crear código duplicado y perder el tiempo, puede buscar código de otros equipos que le pueda ayudar a su propio proyecto."
msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
-msgstr ""
+msgstr "La exportación CSV se creará en segundo plano. Una vez finalizada, será enviada a <strong>%{email}</strong> como un fichero adjunto al correo electrónico."
msgid "The Git LFS objects will <strong>not</strong> be synced."
-msgstr ""
+msgstr "Los objetos Git LFS <strong>no</strong> serán sincronizados."
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
-msgstr ""
+msgstr "El gestor de incidencias es el lugar para agregar cosas que necesitan ser mejoradas o resueltas en un proyecto"
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
-msgstr ""
+msgstr "El gestor de incidencias es el lugar para agregar cosas que necesitan ser mejoradas o resueltas en un proyecto. Puede registrarse o iniciar sesión para crear incidencias para este proyecto."
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
+msgstr "Un certificado X.509 se utiliza cuando se require una comunicación TLS con un servicio de autorización externo. Si se deja en blanco, el certificado utilizado desde el servidor es validado cuando se accedes a través del protocolo HTTPS."
msgid "The amount of seconds after which a request to get a secondary node status will time out."
-msgstr ""
+msgstr "Cantidad de segundos a partir de los cuales expirará una petición para obtener el estado de un nodo secundario."
msgid "The branch for this project has no active pipeline configuration."
+msgstr "La rama para este proyecto no tiene una configuración de un pipeline activa."
+
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
msgstr ""
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
-msgstr ""
+msgstr "El resaltado de caracteres le ayuda a mantener la línea de asunto en %{titleLength} caracteres y a limitar el mensaje a %{bodyLength} para que sea legible en git."
msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
msgstr "La etapa de desarrollo muestra el tiempo desde el primer cambio hasta la creación de la solicitud de fusión. Los datos serán automáticamente incorporados aquí una vez creada tu primera solicitud de fusión."
@@ -10968,73 +13052,85 @@ msgid "The collection of events added to the data gathered for that stage."
msgstr "La colección de eventos agregados a los datos recopilados para esa etapa."
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
-msgstr ""
+msgstr "La conexión terminará después de %{timeout}. Para los repositorios que tarden más tiempo, utilice una combinación de git clone y git push."
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
+msgstr "El contenido de esta página no está codificado en UTF-8. Las ediciones sobre este contenido, solo se pueden realizar a través del repositorio Git."
+
+msgid "The dependency list details information about the components used within your project."
msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
-msgstr ""
+msgstr "El despliegue de este trabajo en %{environmentLink} no tuvo éxito."
msgid "The directory has been successfully created."
-msgstr ""
+msgstr "El directorio se ha creado correctamente."
msgid "The entered user map is not a valid JSON user map."
-msgstr ""
+msgstr "El mapa de usuario introducido no es un mapa de usuario JSON válido."
msgid "The file has been successfully created."
-msgstr ""
+msgstr "El archivo se ha creado correctamente."
msgid "The file has been successfully deleted."
-msgstr ""
+msgstr "El archivo se ha eliminado correctamente."
msgid "The following items will NOT be exported:"
-msgstr ""
+msgstr "No se exportarán los siguientes elementos:"
msgid "The following items will be exported:"
-msgstr ""
+msgstr "Se exportarán los siguientes elementos:"
msgid "The fork relationship has been removed."
msgstr "La relación con la bifurcación se ha eliminado."
msgid "The global settings require you to enable Two-Factor Authentication for your account."
-msgstr ""
+msgstr "La configuración global requiere que habilite la autenticación de dos factores para su cuenta."
msgid "The group and any internal projects can be viewed by any logged in user."
-msgstr ""
+msgstr "El grupo y cualquier proyecto interno pueden ser vistos por cualquier usuario conectado."
msgid "The group and any public projects can be viewed without any authentication."
-msgstr ""
+msgstr "El grupo y cualquier proyecto público se pueden ver sin necesidad de autenticación."
msgid "The group and its projects can only be viewed by members."
-msgstr ""
+msgstr "El grupo y sus proyectos sólo se pueden ver por sus miembros."
msgid "The group settings for %{group_links} require you to enable Two-Factor Authentication for your account. You can %{leave_group_links}."
-msgstr ""
+msgstr "La configuración de grupos para %{group_links} requiere que habilite la autenticación en dos pasos para sú cuenta. Puede %{leave_group_links}."
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
-msgstr ""
+msgstr "La importación finalizará después de %{timeout}. Para los repositorios que necesiten más tiempo, utilice una combinación de comandos 'clone'/'push'."
msgid "The invitation could not be accepted."
-msgstr ""
+msgstr "No se ha podido aceptar la invitación."
msgid "The invitation could not be declined."
-msgstr ""
+msgstr "No se ha podido rechazar la invitación."
msgid "The invitation has already been accepted."
-msgstr ""
+msgstr "La invitación ya ha sido aceptada."
msgid "The invitation was successfully resent."
-msgstr ""
+msgstr "La invitación se reenvió correctamente."
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "La etapa de incidencia muestra el tiempo que toma desde la creación de un tema hasta asignar el tema a un hito, o añadir el tema a una lista en el panel de temas. Empieza a crear temas para ver los datos de esta etapa."
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr "La licencia se ha eliminado. GitLab vuelto al modelo de licencia anterior."
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr "La licencia se ha eliminado. GitLab ya no tiene una licencia válida."
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr "La licencia se ha subido correctamente y está activada. Puede ver los detalles de a continuación."
+
msgid "The maximum file size allowed is %{size}."
msgstr "El tamaño máximo de archivo permitido es de %{size}."
msgid "The maximum file size allowed is 200KB."
-msgstr ""
+msgstr "El tamaño máximo de archivo permitido es de 200KB."
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
msgstr ""
@@ -11046,13 +13142,19 @@ msgid "The merge conflicts for this merge request have already been resolved. Pl
msgstr ""
msgid "The name %{entryName} is already taken in this directory."
+msgstr "El nombre %{entryName} ya se está utilizando en este directorio."
+
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgid "The number of times an upload record could not find its file"
msgstr ""
+msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgstr "La contraseña requerida para descifrar la clave privada. Esto es opcional y su valor está encriptado."
+
msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
-msgstr ""
+msgstr "Ruta al archivo de configuración de CI/CD. Por defecto apunta a <code>.gitlab-ci.yml</code>"
msgid "The phase of the development lifecycle."
msgstr "La etapa del ciclo de vida de desarrollo."
@@ -11064,7 +13166,7 @@ msgid "The planning stage shows the time from the previous step to pushing your
msgstr "La etapa de planificación muestra el tiempo desde el paso anterior hasta el envío de tu primera confirmación. Este tiempo se añadirá automáticamente una vez que usted envíe el primer cambio."
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
+msgstr "La clave privada que se utiliza cuando se proporciona un certificado cliente. Este valor está encriptado."
msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
msgstr "La etapa de producción muestra el tiempo total que tarda entre la creación de una incidencia y el despliegue del código a producción. Los datos se añadirán automáticamente una vez haya finalizado por completo el ciclo de idea a producción."
@@ -11072,20 +13174,35 @@ msgstr "La etapa de producción muestra el tiempo total que tarda entre la creac
msgid "The project can be accessed by any logged in user."
msgstr "El proyecto puede ser accedido por cualquier usuario conectado."
+msgid "The project can be accessed by any user who is logged in."
+msgstr "El proyecto puede ser consultado por cualquier usuario que ha iniciado sesión."
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr "El proyecto puede ser consultado por cualquier persona, independientemente de autenticación."
+
msgid "The project can be accessed without any authentication."
msgstr "El proyecto puede accederse sin ninguna autenticación."
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr "El proyecto es accesible solo por los miembros del proyecto. Se debe otorgar el acceso explícitamente a cada usuario."
+
+msgid "The project is still being deleted. Please try again later."
+msgstr "Todavía se está eliminando el proyecto. Por favor, inténtelo de nuevo más tarde."
+
msgid "The project was successfully forked."
msgstr ""
msgid "The project was successfully imported."
-msgstr ""
+msgstr "El proyecto se ha importado correctamente."
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr "La replica ha tardado demasiado tiempo en completarse."
+
msgid "The remote repository is being updated..."
-msgstr ""
+msgstr "Se está actualizando el repositorio remoto..."
msgid "The repository for this project does not exist."
msgstr "El repositorio para este proyecto no existe."
@@ -11093,6 +13210,9 @@ msgstr "El repositorio para este proyecto no existe."
msgid "The repository for this project is empty"
msgstr "El repositorio de este proyecto está vacío"
+msgid "The repository is being updated..."
+msgstr "Se está actualizando el repositorio remoto..."
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr "El repositorio debe ser accesible a través de <code>http://</code>, <code>https://</code> o <code>git://</code>."
@@ -11106,25 +13226,25 @@ msgid "The roadmap shows the progress of your epics along a timeline"
msgstr "La hoja de ruta muestra el progreso de sus tareas épicas a lo largo de una línea de tiempo"
msgid "The schedule time must be in the future!"
-msgstr ""
+msgstr "¡El horario programado debe ser en el futuro!"
msgid "The snippet can be accessed without any authentication."
-msgstr ""
+msgstr "Se puede acceder al fragmento de código sin necesidad ningún tipo de autenticación."
msgid "The snippet is visible only to me."
-msgstr ""
+msgstr "El fragmento de código sólo es visible por mí."
msgid "The snippet is visible only to project members."
-msgstr ""
+msgstr "El fragmento de código es visible sólo por los miembros del proyecto."
msgid "The snippet is visible to any logged in user."
-msgstr ""
+msgstr "El fragmento de código es visible por cualquier usuario que haya iniciado sesión."
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "La etapa de puesta en escena muestra el tiempo entre la fusión y el despliegue de código en el entorno de producción. Los datos se añadirán automáticamente una vez que se despliega a producción por primera vez."
msgid "The tabs below will be removed in a future version"
-msgstr ""
+msgstr "Las pestañas que se muestran a continuación serán eliminadas en una versión futura"
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr "La etapa de pruebas muestra el tiempo que GitLab CI toma para ejecutar cada pipeline para la solicitud de fusión relacionada. Los datos se añadirán automáticamente luego de que el primer pipeline termine de ejecutarse."
@@ -11132,20 +13252,23 @@ msgstr "La etapa de pruebas muestra el tiempo que GitLab CI toma para ejecutar c
msgid "The time taken by each data entry gathered by that stage."
msgstr "El tiempo utilizado por cada entrada de datos obtenido por esa etapa."
-msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
msgstr ""
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr "El proceso de actualización finalizará después de %{number_of_minutes} minutos. Para repositorios grandes, utilice una combinación de clone y push."
+
msgid "The uploaded file is not a valid Google Takeout archive."
-msgstr ""
+msgstr "El archivo subido no es un archivo de Google Takeout válido."
msgid "The usage ping is disabled, and cannot be configured through this form."
msgstr ""
msgid "The user is being deleted."
-msgstr ""
+msgstr "Se está eliminando el usuario."
msgid "The user map has been saved. Continue by selecting the projects you want to import."
-msgstr ""
+msgstr "Se ha guardado el mapa de usuario. Por favor, continue seleccionando los proyectos que desea importar."
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -11153,23 +13276,38 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr "La URL orientada al usuario del nodo Geo."
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "El valor en el punto medio de una serie de valores observados. Por ejemplo, entre 3, 5, 9, la mediana es 5. Entre 3, 5, 7, 8, la mediana es (5 + 7) / 2 = 6."
-msgid "There are no approvers"
-msgstr ""
+msgid "There are no GPG keys associated with this account."
+msgstr "No hay claves GPG asociadas con esta cuenta."
+
+msgid "There are no GPG keys with access to your account."
+msgstr "No hay claves GPG con acceso a su cuenta."
+
+msgid "There are no SSH keys associated with this account."
+msgstr "No hay claves SSH asociadas con esta cuenta."
+
+msgid "There are no SSH keys with access to your account."
+msgstr "No hay claves SSH con acceso a su cuenta."
msgid "There are no archived projects yet"
msgstr "Aún no hay proyectos archivados"
+msgid "There are no charts configured for this page"
+msgstr "No hay gráficas configuradas para esta página"
+
msgid "There are no closed issues"
-msgstr ""
+msgstr "No hay ninguna incidencia cerrada"
msgid "There are no closed merge requests"
-msgstr ""
+msgstr "No hay merge request cerrados"
msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
-msgstr ""
+msgstr "No hay plantillas de proyecto personalizadas para esta instancia de GitLab. Estas plantillas se habilitan desde el área de administración de GitLab. Por favor, póngase en contacto con el administrador de la instancia de GitLab para configurar plantillas de proyecto personalizadas."
msgid "There are no issues to show"
msgstr "Aún no hay incidencias que mostrar"
@@ -11181,61 +13319,85 @@ msgid "There are no open issues"
msgstr "No hay ninguna incidencia abierta"
msgid "There are no open merge requests"
-msgstr ""
+msgstr "No hay merge requests abiertos"
msgid "There are no packages yet"
-msgstr ""
+msgstr "Todavía no hay paquetes"
msgid "There are no projects shared with this group yet"
msgstr "Aún no hay proyectos compartidos con este grupo"
msgid "There are no staged changes"
-msgstr ""
+msgstr "No hay staged changes"
msgid "There are no unstaged changes"
+msgstr "No hay unstaged changes"
+
+msgid "There is already a repository with that name on disk"
+msgstr "Ya hay un repositorio con ese nombre en el disco"
+
+msgid "There was a problem communicating with your device."
+msgstr "Se ha producido un problema al conectarse con su dispositivo."
+
+msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was an error %{message} todo."
+msgstr "Se ha producido un un error %{message} en la lista de tareas pendientes."
+
msgid "There was an error adding a todo."
+msgstr "Se ha producido un error al añadir la tarea pendiente."
+
+msgid "There was an error creating the issue"
msgstr ""
msgid "There was an error deleting the todo."
-msgstr ""
+msgstr "Se ha producido un error al eliminar la tarea pendiente."
msgid "There was an error fetching configuration for charts"
-msgstr ""
+msgstr "Se ha producido un error al recuperar la configuración de las gráficas"
msgid "There was an error gathering the chart data"
-msgstr ""
+msgstr "Se ha producido un error al recopilar los datos del gráfico"
msgid "There was an error loading users activity calendar."
msgstr "Se ha producido un error al cargar el calendario de actividades de los usuarios."
msgid "There was an error removing the e-mail."
-msgstr ""
+msgstr "Se ha producido un error al eliminar el correo electrónico."
+
+msgid "There was an error resetting group pipeline minutes."
+msgstr "Se ha producido un error al restablecer los minutos de ejecución de los pipelines del grupo."
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr "Se ha producido un error al restablecer los minutos de ejecución de los pipelines del usuario."
msgid "There was an error saving your changes."
-msgstr ""
+msgstr "Se ha producido un error al guardar sus cambios."
msgid "There was an error saving your notification settings."
-msgstr ""
+msgstr "Se ha producido un error al actualizar la configuración de las notificaciones."
msgid "There was an error subscribing to this label."
-msgstr ""
+msgstr "Se ha producido un error al subscribirse a esta etiqueta."
msgid "There was an error when reseting email token."
msgstr "Se ha producido un error al restablecer el token de correo electrónico."
msgid "There was an error when subscribing to this label."
-msgstr ""
+msgstr "Se ha producido un error al suscribirse a esta etiqueta."
msgid "There was an error when unsubscribing from this label."
-msgstr ""
+msgstr "Se ha producido un error al cancelar la suscripción de esta etiqueta."
+
+msgid "There was an error while fetching cycle analytics data."
+msgstr "Se ha producido un error mientras se obtenían los datos de Cycle Analytics."
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
+msgstr "Se ha producido un error con reCAPTCHA. Por favor, resuelva el reCAPTCHA de nuevo."
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
-msgstr ""
+msgstr "Estas incidencias tienen un título similar al de la incidencia que está creando. Sería mejor hacer un comentario en alguna de estas en vez de crear otra incidencia similar."
msgid "They can be managed using the %{link}."
msgstr "Se pueden administrar usando el %{link}."
@@ -11243,17 +13405,23 @@ msgstr "Se pueden administrar usando el %{link}."
msgid "Third party offers"
msgstr "Ofertas de terceros"
-msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
+msgstr "Este %{issuable} está bloqueado. Solo los <strong>miembros del proyecto</strong> pueden comentar."
+
msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
-msgstr ""
+msgstr "Este %{viewer} no se puede mostrar porque %{reason}. En su lugar, puedes %{options}."
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr "Esta instancia de GitLab aún no proporciona ningún 'runner' compartido. Los administradores de instancias pueden registrar 'runner' compartidos en el área de administración."
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
-msgstr ""
+msgstr "Esta acción puede provocar la pérdida de datos. Para prevenir acciones accidentales, le pedimos que confirme su intención."
+
+msgid "This also resolves the discussion"
+msgstr "Esto también resuelve la discusión"
msgid "This application was created by %{link_to_owner}."
msgstr "Esta aplicación fue creada por %{link_to_owner}."
@@ -11261,47 +13429,65 @@ msgstr "Esta aplicación fue creada por %{link_to_owner}."
msgid "This application will be able to:"
msgstr "Está aplicación podrá:"
+msgid "This block is self-referential"
+msgstr "Este bloque es auto-referencial"
+
msgid "This board's scope is reduced"
msgstr "El alcance de este tablero es limitado"
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr "Esta rama ha cambiado desde que se comenzó a editar. ¿Le gustaría crear una nueva rama?"
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr "No se puede mostrar este gráfico"
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
msgid "This commit was signed with a <strong>verified</strong> signature and the committer email is verified to belong to the same user."
-msgstr ""
+msgstr "Este commit fue firmado con una firma verificada, y <strong>se ha verificado</strong> que la dirección de correo electrónico del committer y la firma pertenecen al mismo usuario."
msgid "This commit was signed with a different user's verified signature."
-msgstr ""
+msgstr "Este commit fue firmado con la firma verificada de un usuario diferente."
msgid "This commit was signed with a verified signature, but the committer email is <strong>not verified</strong> to belong to the same user."
-msgstr ""
+msgstr "Este commit fue firmado con una firma verificada, pero <strong>no se ha verificado</strong> si la dirección de correo electrónico del commiter y la firma pertenecen al mismo usuario."
msgid "This commit was signed with an <strong>unverified</strong> signature."
-msgstr ""
+msgstr "Esta commit fue firmado con una firma <strong>no verificada</strong>."
msgid "This container registry has been scheduled for deletion."
-msgstr ""
+msgstr "Se ha programado este registro de contenedores para su eliminación."
msgid "This date is after the due date, so this epic won't appear in the roadmap."
-msgstr ""
+msgstr "Esta fecha es posterior a la fecha de vencimiento, por lo que esta tarea épica no aparecerá en la hoja de ruta."
msgid "This date is before the start date, so this epic won't appear in the roadmap."
-msgstr ""
+msgstr "Esta fecha es anterior a la fecha de inicio planificada, por lo que esta tarea épica no aparecerá en la hoja de ruta."
+
+msgid "This device has already been registered with us."
+msgstr "Este dispositivo ya ha sido registrado con nosotros."
+
+msgid "This device has not been registered with us."
+msgstr "Este dispositivo no se ha registrado con nosotros."
msgid "This diff is collapsed."
msgstr "El diff está contraído."
msgid "This diff was suppressed by a .gitattributes entry."
-msgstr ""
+msgstr "Se ha eliminado el diff por una entrada en el fichero .gitattributes."
msgid "This directory"
msgstr "Este directorio"
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
-msgstr ""
+msgstr "Este dominio no está verificado. Es necesario verificar la propiedad del mismo antes de activar el acceso."
+
+msgid "This environment has no deployments yet."
+msgstr "Este entorno todavía no tiene despliegues."
msgid "This field is required."
msgstr "Este campo es obligatorio."
@@ -11312,24 +13498,33 @@ msgstr "Este grupo"
msgid "This group does not provide any group Runners yet."
msgstr "Este grupo aún no proporciona ningún grupo de 'runners'."
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr "Este es un usuario \"fantasma\", creado para mantener todas las incidencias creadass por usuarios de Gitlab que ya han sido eliminados. Este usuario no se puede eliminar."
+
msgid "This is a confidential issue."
msgstr "Esta incidencia es confidencial."
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr "Esta es una lista de dispositivos desde los que ha iniciado sesión. Cierre todas las sesiones que no reconozca."
+
+msgid "This is a security log of important events involving your account."
+msgstr "Este es un registro de seguridad de eventos importantes relacionados con su cuenta."
+
msgid "This is the author's first Merge Request to this project."
-msgstr ""
+msgstr "Este es el primer Merge Request del autor a este proyecto."
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
-msgstr ""
+msgstr "Este es el número máximo de usuarios que han existido al mismo tiempo desde que se habilitó la licencia. Este es el número mínimo de puestos que deberá comprar cuando renueve su licencia."
+
+msgid "This is your current session"
+msgstr "Esta es su sesión actual"
msgid "This issue is confidential"
msgstr "Esta incidencia es confidencial"
-msgid "This issue is confidential and locked."
-msgstr "Esta incidencia es confidencial y está bloqueada."
-
msgid "This issue is locked."
msgstr "Esta incidencia está bloqueada."
@@ -11337,7 +13532,7 @@ msgid "This job depends on a user to trigger its process. Often they are used to
msgstr "Este trabajo depende de que un usuario active su proceso. A menudo se utilizan para implementar código en entornos de producción"
msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
-msgstr ""
+msgstr "Este trabajo depende de trabajos anteriores que se deben ejecutar correctamente, antes de que este trabajo se active"
msgid "This job does not have a trace."
msgstr "Esta tarea no tiene seguimiento."
@@ -11355,37 +13550,37 @@ msgid "This job has not started yet"
msgstr "Todavia no ha comenzado la tarea"
msgid "This job is an out-of-date deployment to %{environmentLink}."
-msgstr ""
+msgstr "Este trabajo corresponde con un despliegue obsoleto en %{environmentLink}."
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
-msgstr ""
+msgstr "Este trabajo corresponde con un despliegue obsoleto en %{environmentLink}. Vea el despliegue más reciente %{deploymentLink}."
msgid "This job is archived. Only the complete pipeline can be retried."
-msgstr ""
+msgstr "Este trabajo está archivado. Solo puede reintentar la ejecución del pipeline completo."
msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
-msgstr ""
+msgstr "Este trabajo está creando un despliegue en %{environmentLink} y sobrescribirá el último %{deploymentLink}."
msgid "This job is creating a deployment to %{environmentLink}."
-msgstr ""
+msgstr "Este trabajo está creando un despliegue en %{environmentLink}."
msgid "This job is in pending state and is waiting to be picked by a runner"
-msgstr ""
+msgstr "Este trabajo se encuentra en estado pendiente y está a la espera de ser ejecutado por un ejecutor"
msgid "This job is performing tasks that must complete before it can start"
-msgstr ""
+msgstr "Este trabajo está realizando tareas que deben completarse antes de que pueda comenzar"
msgid "This job is preparing to start"
-msgstr ""
+msgstr "Este trabajo se está preparando para empezar"
msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
-msgstr ""
+msgstr "Este trabajo está bloqueado porque no tienes ningún ejecutor activo en línea con ninguna de estas etiquetas asignadas:"
msgid "This job is stuck because you don't have any active runners that can run this job."
-msgstr ""
+msgstr "Este trabajo está bloqueado porque no tiene ningún ejecutor activo que pueda ejecutar este trabajo."
msgid "This job is the most recent deployment to %{link}."
-msgstr ""
+msgstr "Este trabajo es el despliegue más reciente en %{link}."
msgid "This job requires a manual action"
msgstr "Este trabajo requiere una acción manual"
@@ -11399,65 +13594,59 @@ msgstr "Esto significa que no puede enviar código hasta que cree un repositorio
msgid "This merge request is locked."
msgstr "Este merge request está bloqueado."
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
-msgstr ""
+msgstr "Este espacio de nombres ya esta en uso. Por favor, elija otro diferente."
msgid "This option is disabled as you don't have write permissions for the current branch"
-msgstr ""
+msgstr "Esta opción está desactivada ya que no tiene permisos de escritura para la rama actual"
msgid "This page is unavailable because you are not allowed to read information across multiple projects."
-msgstr ""
+msgstr "Esta página no está disponible porque no se le permite leer la información a través de múltiples proyectos."
msgid "This page will be removed in a future release."
msgstr "Esta página se eliminará en una versión futura."
msgid "This pipeline is run on the source branch"
-msgstr ""
+msgstr "Este pipeline se ejecuta en la rama de origen"
msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
-msgstr ""
+msgstr "Este pipeline utiliza una configuración de CI/CD predefinida habilitada por %{strongStart}Auto DevOps.%{strongEnd}"
msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b>Auto DevOps.</b>"
-msgstr ""
+msgstr "Este pipeline utiliza una configuración de CI/CD predefinida habilitada por <b>Auto DevOps.</b>"
msgid "This project"
msgstr "Este proyecto"
msgid "This project does not belong to a group and can therefore not make use of group Runners."
-msgstr ""
+msgstr "Este proyecto no pertenece a ningún grupo y, por lo tanto, no puede hacer uso de un grupo de ejecutores."
msgid "This project does not have a wiki homepage yet"
-msgstr ""
+msgstr "Este proyecto todavía no tiene una pagina de inicio del wiki"
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
+msgstr "Este proyecto no tiene la facturación habilitada. Para crear un clúster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">habilite la facturación <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> e inténtelo de nuevo."
msgid "This repository"
msgstr "Este repositorio"
msgid "This repository is currently empty. A new Auto DevOps pipeline will be created after a new file has been pushed to a branch."
-msgstr ""
+msgstr "Actualmente, este repositorio está vacío. Se creará un nuevo pipeline de Auto DevOps tan pronto como haya añadido un archivo a una rama."
msgid "This runner will only run on pipelines triggered on protected branches"
-msgstr ""
+msgstr "Este ejecutor solo se ejecutará en pipelines disparados sobre ramas protegidas"
msgid "This setting can be overridden in each project."
-msgstr ""
+msgstr "Esta configuración se puede reemplazar en cada proyecto."
msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
-msgstr ""
+msgstr "Esta configuración actualizará el nombre del host que se utiliza para generar los correos electrónicos de commit privados. %{learn_more}"
msgid "This timeout will take precedence when lower than project-defined timeout and accepts a human readable time input language like \"1 hour\". Values without specification represent seconds."
-msgstr ""
+msgstr "Este tiempo de espera tendrá prioridad cuando sea más bajo que el tiempo de espera definido por el proyecto y acepte un lenguaje de entrada de tiempo legible como por ejemplo, \"1 hora\". Los valores sin especificación de tipo representan segundos."
msgid "This user cannot be unlocked manually from GitLab"
-msgstr ""
+msgstr "Este usuario no puede ser desbloqueado manualmente desde GitLab"
msgid "This user has no identities"
msgstr "El usuario no tiene ninguna identidad"
@@ -11469,12 +13658,18 @@ msgid "This user will be the author of all events in the activity feed that are
msgstr ""
msgid "This will redirect you to an external sign in page."
-msgstr ""
+msgstr "Esto le redirigirá a una página de inicio de sesión externa."
msgid "This will remove the fork relationship to source project"
msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
+msgstr "Automáticamente, esos correos electrónicos se convierten en incidencias (la conversación por correo electrónico, se convierte en comentarios) enumerados aquí."
+
+msgid "Thursday"
+msgstr "Jueves"
+
+msgid "Time based: Yes"
msgstr ""
msgid "Time before an issue gets scheduled"
@@ -11493,7 +13688,7 @@ msgid "Time estimate"
msgstr "Tiempo estimado"
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
-msgstr ""
+msgstr "Tiempo en segundos que GitLab esperará hasta obtener una respuesta de un servicio externo. Cuando el servicio no responda a tiempo, se denegará el acceso."
msgid "Time remaining"
msgstr "Tiempo restante"
@@ -11508,7 +13703,7 @@ msgid "Time until first merge request"
msgstr "Tiempo hasta la primera solicitud de fusión"
msgid "TimeTrackingEstimated|Est"
-msgstr ""
+msgstr "Est"
msgid "TimeTracking|Estimated:"
msgstr "Estimado:"
@@ -11661,104 +13856,113 @@ msgstr "Sugerencia:"
msgid "Title"
msgstr "Título"
+msgid "Title:"
+msgstr "Título:"
+
msgid "Titles and Filenames"
msgstr "Títulos y nombres de archivos"
msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
-msgstr ""
+msgstr "Para %{link_to_help} de su dominio, añada la clave anterior a un registro TXT dentro de su configuración DNS."
msgid "To GitLab"
msgstr "A GitLab"
msgid "To access this domain create a new DNS record"
-msgstr ""
+msgstr "Para acceder a este dominio, cree un nuevo registro DNS"
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
+msgstr "Para agregar una clave SSH necesita %{generate_link_start}generar una%{link_end} o utilizar una clave existente %{existing_link_start}%{link_end}."
+
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr "Para agregar la entrada manualmente, proporcione los siguientes detalles a la aplicación en su teléfono."
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
-msgstr ""
+msgstr "Para conectar a los repositorios de GitHub, puede utilizar un %{personal_access_token_link}. Cuando cree su token de acceso personal, deberá seleccionar el alcance del <code>repo</code>, para que podamos mostrarle una lista de sus repositorios públicos y privados que están disponibles para conectarse."
msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
-msgstr ""
+msgstr "Para conectar a los repositorios de GitHub, primero debe autorizar a GitLab a acceder a la lista de repositorios de GitHub:"
msgid "To connect an SVN repository, check out %{svn_link}."
-msgstr ""
+msgstr "Para conectar un repositorio SVN, eche un vistazo a %{svn_link}."
msgid "To define internal users, first enable new users set to external"
-msgstr ""
+msgstr "Para definir los usuarios internos, primero habilite nuevos usuarios externos"
msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
msgstr ""
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
-msgstr ""
+msgstr "Para comenzar, introduzca su URL de FogBugz, y a continuación, introduzca la información de inicio de sesión. En los siguientes pasos, podrá asignar usuarios y seleccionar los proyectos que desea importar."
msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
-msgstr ""
+msgstr "Para comenzar, vincule esta página a su servidor Jaeger, o descubra cómo instalar %{link_start_tag}Jaeger%{link_end_tag}"
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
-msgstr ""
+msgstr "Para comenzar, introduzca la URL de su servidor de Gitea y un %{link_to_personal_token}."
msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
-msgstr ""
+msgstr "Para ayudar a mejorar GitLab y su experiencia de usuario, GitLab recopilará periódicamente información de uso."
msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
-msgstr ""
+msgstr "Para ayudar a mejorar GitLab, nos gustaría recopilar periódicamente información de uso. Esto se puede cambiar en cualquier momento en %{settings_link_start}Configuraciones%{link_end}. %{info_link_start}Más información%{link_end}"
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
-msgstr ""
+msgstr "Para importar los repositorios de GitHub, puede utilizar un %{personal_access_token_link}. Cuando cree su token de acceso personal, deberá seleccionar el alcance de <code>repo</code>, para que podamos mostrarle una lista de sus repositorios públicos y privados que están disponibles para importar."
msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
-msgstr ""
+msgstr "Para importar los repositorios de GitHub, primero debe autorizar a GitLab a acceder a la lista de repositorios de GitHub:"
msgid "To import an SVN repository, check out %{svn_link}."
-msgstr ""
+msgstr "Para importar un repositorio SVN, puede ver %{svn_link}."
msgid "To keep this project going, create a new issue"
-msgstr ""
+msgstr "Para mantener este proyecto en marcha, crea una nueva incidencia"
msgid "To keep this project going, create a new merge request"
-msgstr ""
+msgstr "Para mantener este proyecto en marcha, cree un nuevo merge request"
msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
-msgstr ""
+msgstr "Para enlazar Sentry con GitLab, por favor, introduzca la URL de Sentry y el token de autenticación."
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
-msgstr ""
+msgstr "Para mover o copiar todo un proyecto de GitLab de una instalación de GitLab a esta, navegue hasta la página de configuración del proyecto original, genere un archivo de exportación y súbalo aquí."
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
-msgstr ""
+msgstr "Para utilizar únicamente las funciones de CI/CD en un repositorio externo, seleccione <strong>CI/CD para un repositorio externo</strong>."
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
-msgstr ""
+msgstr "Para abrir Jaeger y ver fácilmente la trazabilidad desde GitLab, enlace la página %{link} a su servidor"
msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
-msgstr ""
+msgstr "Para mantener el rendimiento, solo se muestran <strong>%{display_size} de %{real_size}</strong> archivos."
msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
-msgstr ""
+msgstr "Para recibir alertas de los servicios de Prometheus configurados manualmente, agregue la siguiente URL y la clave de autorización a su archivo de configuración del webhook de Prometheus. Puede obtener más información sobre la %{linkStart}configuración de Prometheus%{linkEnd} para enviar alertas a GitLab."
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
-msgstr ""
+msgstr "Para configurar la autenticación SAML para su grupo a través de un proveedor de identidad como Azure, Okta, Onelogin, Ping Identity o su proveedor SAML 2.0 personalizado:"
+
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr "Para especificar el nivel de notificación por proyecto de un grupo al que pertenece, debe visitar la página del proyecto y cambiar el nivel de las notificaciones."
msgid "To start serving your jobs you can add Runners to your group"
-msgstr ""
+msgstr "Para empezar a servir sus trabajos, puede agregar ejecutores a su grupo"
msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
+msgstr "Para comenzar a ejecutar sus trabajos, puede agregar ejecutores específicos a su proyecto o utilizar ejecutores compartidos"
msgid "To this GitLab instance"
msgstr "A esta instancia de GitLab"
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
-msgstr ""
+msgstr "Para validar sus configuraciones de GitLab CI, vaya a 'CI/CD → Pipelines' dentro de su proyecto y haga clic en el botón 'CI Lint'."
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
+msgstr "Para ver la hoja de ruta, agregue una fecha de inicio o final para cada uno de las tareas épicas en este grupo o en uno de sus subgrupos. En la vista mensual, sólo se mostrarán las tareas las épicas del último mes, del mes en curso, y de los próximos 5 meses."
msgid "To widen your search, change or remove filters above"
-msgstr ""
+msgstr "Para ampliar la búsqueda, cambie o elimine filtros"
msgid "To widen your search, change or remove filters."
msgstr "Para ampliar la búsqueda, cambie o elimine filtros."
@@ -11770,7 +13974,7 @@ msgid "Todo"
msgstr "Tareas pendientes"
msgid "Todo was successfully marked as done."
-msgstr ""
+msgstr "La tarea pendiente se ha marcado como realizada correctamente."
msgid "Todos"
msgstr "Tareas pendientes"
@@ -11778,9 +13982,12 @@ msgstr "Tareas pendientes"
msgid "Toggle Sidebar"
msgstr "Ocultar barra lateral"
-msgid "Toggle comments for this file"
+msgid "Toggle backtrace"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr "Mostrar/ocultar los comentarios para este archivo"
+
msgid "Toggle commit description"
msgstr "Cambiar la descripción del commit"
@@ -11788,18 +13995,27 @@ msgid "Toggle commit list"
msgstr ""
msgid "Toggle discussion"
+msgstr "Alternar la discusión"
+
+msgid "Toggle emoji award"
msgstr ""
msgid "Toggle navigation"
+msgstr "Alternar navegación"
+
+msgid "Toggle project"
msgstr ""
msgid "Toggle sidebar"
-msgstr ""
+msgstr "Ocultar/mostrar barra lateral"
msgid "ToggleButton|Toggle Status: OFF"
-msgstr ""
+msgstr "Cambiar estado: OFF"
msgid "ToggleButton|Toggle Status: ON"
+msgstr "Cambiar estado: ON"
+
+msgid "Toggles :%{name}: emoji award."
msgstr ""
msgid "Token"
@@ -11812,10 +14028,10 @@ msgid "Too many changes to show."
msgstr "Hay demasiados cambios para mostrar."
msgid "Topics"
-msgstr ""
+msgstr "Temas"
msgid "Total"
-msgstr ""
+msgstr "Total"
msgid "Total Contributions"
msgstr "Contribuciones totales"
@@ -11836,12 +14052,48 @@ msgid "Track activity with Contribution Analytics."
msgstr "Monitorizar la actividad con Contribution Analytics."
msgid "Track groups of issues that share a theme, across projects and milestones"
-msgstr ""
+msgstr "Haga un seguimiento de grupos de incidencias que comparten un tema, a través de proyectos e hitos"
msgid "Track time with quick actions"
-msgstr ""
+msgstr "Seguimiento del tiempo con acciones rápidas"
msgid "Transfer project"
+msgstr "Transferir proyecto"
+
+msgid "TransferGroup|Database is not supported."
+msgstr "La base de datos no es compatible."
+
+msgid "TransferGroup|Group is already a root group."
+msgstr "El grupo ya es un grupo raíz."
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr "El grupo ya está asociado al grupo principal."
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr "El grupo principal ya tiene un subgrupo definido con la misma ruta."
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr "Transferencia fallida: %{error_message}"
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr "No tiene permisos suficientes."
+
+msgid "TransferProject|Cannot move project"
+msgstr "No se puede mover el proyecto"
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr "Por favor, seleccione un nuevo espacio de nombre para su proyecto."
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr "No se puede transferir el proyecto, porque hay etiquetas definidas en el registro de contenedores"
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr "Ya existe un proyecto con el mismo nombre o ruta en el espacio de nombres de destino"
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr "Se ha producido un error durante el proceso de transferencia, por favor, contacte con un administrador."
+
+msgid "Tree"
msgstr ""
msgid "Tree view"
@@ -11851,13 +14103,13 @@ msgid "Trending"
msgstr "Tendencia"
msgid "Trigger pipelines for mirror updates"
-msgstr ""
+msgstr "Ejecutar pipelines para la actualización de las replicas"
msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
msgstr ""
msgid "Trigger removed."
-msgstr ""
+msgstr "Disparador eliminado."
msgid "Trigger this manual action"
msgstr "Disparar esta acción manual"
@@ -11866,22 +14118,22 @@ msgid "Trigger token:"
msgstr ""
msgid "Trigger variables:"
-msgstr ""
+msgstr "Variables de disparador:"
msgid "Trigger was created successfully."
-msgstr ""
+msgstr "El disparador fue creado con éxito."
msgid "Trigger was re-assigned."
-msgstr ""
+msgstr "Disparador fue reasignado."
msgid "Trigger was successfully updated."
-msgstr ""
+msgstr "El disparador se actualizó correctamente."
msgid "Triggerer"
msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
-msgstr ""
+msgstr "Los disparados pueden obligar a un branch o un tag específico a ser reconstruido con una llamada API. Estos tokens suplantarán a su usuario asociado, incluido su acceso a los proyectos y sus permisos de proyecto."
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
@@ -11890,22 +14142,37 @@ msgid "Try again"
msgstr "Inténtelo de nuevo"
msgid "Try again?"
-msgstr ""
+msgstr "¿Desea intentarlo de nuevo?"
msgid "Try all GitLab has to offer for 30 days."
msgstr "Pruebe todo lo que GitLab tiene para ofrecer durante 30 días."
+msgid "Try to fork again"
+msgstr "Intentar realizar el fork de nuevo"
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
-msgstr ""
+msgstr "Intentando comunicarse con su dispositivo. Conéctelo (si aún no lo ha hecho) y presione el botón en el dispositivo ahora."
+
+msgid "Tuesday"
+msgstr "Martes"
msgid "Turn on Service Desk"
-msgstr ""
+msgstr "Activar el Service Desk"
msgid "Twitter"
msgstr "Twitter"
+msgid "Two-Factor Authentication"
+msgstr "Autenticación de doble factor"
+
+msgid "Two-factor Authentication"
+msgstr "Autenticación de doble factor"
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr "Códigos de recuperación de la autenticación de doble factor"
+
msgid "Two-factor Authentication has been disabled for this user"
-msgstr ""
+msgstr "Se ha deshabilitado la autenticación de dos factores para este usuario"
msgid "Two-factor authentication"
msgstr "Autenticación de doble factor"
@@ -11913,29 +14180,47 @@ msgstr "Autenticación de doble factor"
msgid "Type"
msgstr "Tipo"
+msgid "U2F Devices (%{length})"
+msgstr "Dispositivos U2F (%{length})"
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr "U2F sólo funciona con sitios web habilitados con HTTPS. Contacte con su administrador para más detalles."
+
msgid "URL"
msgstr "URL"
msgid "Unable to connect to server: %{error}"
+msgstr "Imposible conectar con el servidor: %{error}"
+
+msgid "Unable to generate new instance ID"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
-msgstr ""
+msgstr "No se puede cargar el fichero diff. %{button_try_again}"
+
+msgid "Unable to resolve"
+msgstr "No se puede resolver"
msgid "Unable to schedule a pipeline to run immediately"
-msgstr ""
+msgstr "No se puede programar un pipeline para que se ejecute inmediatamente"
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
-msgstr ""
+msgstr "Se ha producido un error al iniciar la sesión en el grupo mediante SAML debido a \"%{reason}\""
+
+msgid "Unable to update label prioritization at this time"
+msgstr "No se puede actualizar la prioridad de la etiqueta en este momento"
msgid "Unable to update this epic at this time."
-msgstr ""
+msgstr "No se puede actualizar la tarea epíca en este momento."
+
+msgid "Unable to update this issue at this time."
+msgstr "No se puede actualizar esta incidencia en este momento."
msgid "Unarchive project"
-msgstr ""
+msgstr "Desarchivar proyecto"
msgid "Unarchiving the project will restore people's ability to make changes to it. The repository can be committed to, and issues, comments and other entities can be created. <strong>Once active this project shows up in the search and on the dashboard.</strong>"
-msgstr ""
+msgstr "Desarchivar el proyecto restaurará la capacidad de las personas para realizar cambios en él. En el repositorio se podrán hacer commits, y se pueden crear incidencias, comentarios y otras entidades. <strong>Una vez activo, este proyecto aparece en la búsqueda y en el panel.</strong>"
msgid "Unblock"
msgstr "Desbloquear"
@@ -11944,28 +14229,43 @@ msgid "Undo"
msgstr "Deshacer"
msgid "Unfortunately, your email message to GitLab could not be processed."
-msgstr ""
+msgstr "Desafortunadamente, su mensaje de correo electrónico a GitLab no pudo ser procesado."
msgid "Unknown"
msgstr "Desconocido"
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr "¡Estrategia de cifrado desconocida: %{encrypted_strategy}!"
+
+msgid "Unknown format"
+msgstr "Formato desconocido"
+
+msgid "Unknown response text"
+msgstr "Texto de respuesta desconocido"
+
msgid "Unlimited"
-msgstr ""
+msgstr "Ilimitado"
msgid "Unlock"
msgstr "Desbloquear"
+msgid "Unlock the discussion"
+msgstr "Desbloquear la discusión"
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr "Desbloquear este %{issuableDisplayName}? <strong>Todos</strong> podrán comentar."
msgid "Unlocked"
msgstr "Desbloqueado"
+msgid "Unlocks the discussion"
+msgstr "Desbloquear la discusión"
+
msgid "Unresolve discussion"
-msgstr ""
+msgstr "Discusión no resuelta"
msgid "Unschedule job"
-msgstr ""
+msgstr "No programado"
msgid "Unstage"
msgstr ""
@@ -11998,7 +14298,7 @@ msgid "Unsubscribe at project level"
msgstr "Eliminar suscripción a nivel de proyecto"
msgid "Unsubscribe from %{type}"
-msgstr ""
+msgstr "Cancelar la suscripción a %{type}"
msgid "Unverified"
msgstr "Sin verificar"
@@ -12007,16 +14307,16 @@ msgid "Up to date"
msgstr "Actualizado"
msgid "Upcoming"
-msgstr ""
+msgstr "Próximo"
msgid "Update"
msgstr "Actualizar"
msgid "Update approvers"
-msgstr ""
+msgstr "Actualizar aprobadores"
msgid "Update failed"
-msgstr ""
+msgstr "Se ha producido un error en la actualización"
msgid "Update now"
msgstr "Actualizar ahora"
@@ -12028,13 +14328,25 @@ msgid "Update your group name, description, avatar, and visibility."
msgstr "Actualice el nombre de su grupo, su descripción, su avatar y su visibilidad."
msgid "Update your project name, topics, description and avatar."
-msgstr ""
+msgstr "Actualice el nombre de su proyecto, los temas, la descripción y el avatar."
+
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr "¡No se puede cambiar el nombre del proyecto porque el registro de contenedores contiene etiquetas!"
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr "No se puede establecer la rama por defecto"
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr "¡Nuevo nivel de visibilidad no permitido!"
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr "¡No ha sido posible actualizar el proyecto!"
msgid "Updated"
msgstr "Actualizado"
msgid "Updated %{updated_at} by %{updated_by}"
-msgstr ""
+msgstr "Actualizado %{updated_at} por %{updated_by}"
msgid "Updating"
msgstr "Actualizando"
@@ -12043,28 +14355,28 @@ msgid "Upgrade plan to unlock Canary Deployments feature"
msgstr ""
msgid "Upgrade your plan"
-msgstr ""
+msgstr "Actualice su plan"
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr "Actualice su plan para activar la búsqueda global avanzada."
msgid "Upgrade your plan to activate Contribution Analytics."
-msgstr ""
+msgstr "Actualice su plan para activar la herramienta Contribution Analytics."
msgid "Upgrade your plan to activate Group Webhooks."
msgstr "Actualice su plan para activar la herramienta Group Webhooks."
msgid "Upgrade your plan to activate Issue weight."
-msgstr ""
+msgstr "Actualice su plan para activar la herramienta Issue Weight."
msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
+msgstr "Actualice su plan para mejorar los tableros de incidencias."
msgid "Upgrade your plan to improve Merge Requests."
-msgstr ""
+msgstr "Actualice su plan para mejorar los merge requests."
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
-msgstr ""
+msgstr "Subir el fichero <code>GoogleCodeProjectHosting.json</code> aquí:"
msgid "Upload CSV file"
msgstr "Subir fichero CSV"
@@ -12073,85 +14385,145 @@ msgid "Upload New File"
msgstr "Subir nuevo archivo"
msgid "Upload a certificate for your domain with all intermediates"
-msgstr ""
+msgstr "Suba un certificado para su dominio con todos los certificados intermedios"
msgid "Upload a private key for your certificate"
-msgstr ""
+msgstr "Suba una clave privada para su certificado"
msgid "Upload file"
msgstr "Subir archivo"
+msgid "Upload file does not exist"
+msgstr "El archivo de subida no existe"
+
msgid "Upload object map"
-msgstr ""
+msgstr "Subir un mapa de objetos"
msgid "UploadLink|click to upload"
msgstr "Hacer clic para subir"
msgid "Uploaded on"
+msgstr "Subido en"
+
+msgid "Uploading changes to terminal"
msgstr ""
msgid "Uploads"
-msgstr ""
+msgstr "Subidas"
msgid "Upstream"
-msgstr ""
+msgstr "Upstream"
msgid "Upvotes"
-msgstr ""
+msgstr "Votos positivos"
msgid "Usage"
-msgstr ""
+msgstr "Uso"
msgid "Usage ping is not enabled"
msgstr ""
msgid "Usage statistics"
+msgstr "Estadísticas de uso"
+
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr "Comprar minutos adicionales"
+
+msgid "UsageQuota|Current period usage"
+msgstr "Periodo actual de uso"
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr "Pipelines"
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr "|Ilimitado"
+
+msgid "UsageQuota|Usage"
+msgstr "Uso"
+
+msgid "UsageQuota|Usage Quotas"
+msgstr "Cuotas de uso"
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr "Uso de los recursos del grupo a través de los proyectos en el grupo %{strong_start}%{group_name}%{strong_end}"
+
+msgid "UsageQuota|Usage since"
+msgstr "Uso desde"
+
+msgid "UsageQuota|Wiki"
msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
msgid "Use <code>%{native_redirect_uri}</code> for local tests"
-msgstr ""
+msgstr "Use <code>%{native_redirect_uri}</code> para los tests locales"
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
+msgstr "Utilice la herramienta Service Desk para conectarse con sus usuarios (por ejemplo, para ofrecer soporte al cliente) a través del correo electrónico directamente desde dentro de GitLab"
+
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr "Utilice un dispositivo de hardware para agregar un segundo factor de autenticación."
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr "Utilice un autenticador de contraseña de un único uso en su dispositivo móvil u ordenador para habilitar la autenticación de dos factores (2FA)."
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
-msgstr ""
+msgstr "Use los hitos de grupo para administrar incidencias de múltiples proyectos en el mismo hito."
msgid "Use one line per URI"
-msgstr ""
+msgstr "Utilice una línea por URI"
msgid "Use template"
-msgstr "Usar plantilla"
+msgstr "Utilizar plantilla"
msgid "Use the following registration token during setup:"
-msgstr ""
+msgstr "Utilice el siguiente token de registro durante la configuración:"
msgid "Use your global notification setting"
msgstr "Utiliza tu configuración de notificación global"
msgid "Use your smart card to authenticate with the LDAP server."
-msgstr ""
+msgstr "Utilice su tarjeta inteligente para autenticarse contra el servidor LDAP."
msgid "Used by members to sign in to your group in GitLab"
-msgstr ""
+msgstr "Utilizado por los miembros para iniciar sesión en su grupo en GitLab"
msgid "Used to help configure your identity provider"
-msgstr ""
+msgstr "Se utiliza para ayudar a configurar su proveedor de identidad"
msgid "User %{current_user_username} has started impersonating %{username}"
-msgstr ""
+msgstr "El usuario %{current_user_username} ha comenzado a suplantar %{username}"
msgid "User %{username} was successfully removed."
-msgstr ""
+msgstr "El usuario %{username} se ha eliminado correctamente."
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
msgid "User OAuth applications"
-msgstr ""
+msgstr "Aplicaciones OAuth del usuario"
msgid "User Settings"
msgstr "Ajustes de usuario"
@@ -12160,40 +14532,178 @@ msgid "User and IP Rate Limits"
msgstr "Usuarios y ratio de límites de IP"
msgid "User identity was successfully created."
-msgstr ""
+msgstr "La identidad de usuario se ha creado correctamente."
msgid "User identity was successfully removed."
-msgstr ""
+msgstr "La identidad de usuario se ha eliminado correctamente."
msgid "User identity was successfully updated."
-msgstr ""
+msgstr "La identidad de usuario se ha actualizado correctamente."
msgid "User key was successfully removed."
-msgstr ""
+msgstr "La clave de usuario se ha eliminado correctamente."
msgid "User map"
-msgstr ""
+msgstr "Mapa de usuario"
+
+msgid "User pipeline minutes were successfully reset."
+msgstr "La cuota de minutos del pipeline fue restablecida con éxito."
msgid "User settings"
-msgstr ""
+msgstr "Configuración del usuario"
msgid "User was successfully created."
-msgstr ""
+msgstr "Usuario creado correctamente."
msgid "User was successfully removed from group and any subresources."
-msgstr ""
+msgstr "Se ha eliminado el usuario correctamente del grupo y de los recursos."
msgid "User was successfully removed from project."
-msgstr ""
+msgstr "Se ha eliminado el usuario correctamente del proyecto."
msgid "User was successfully updated."
+msgstr "Usuario actualizado correctamente."
+
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
msgstr ""
msgid "UserProfile|Activity"
msgstr "Actividad"
msgid "UserProfile|Already reported for abuse"
-msgstr ""
+msgstr "Ya se informó del abuso"
msgid "UserProfile|Contributed projects"
msgstr "Proyectos contribuidos"
@@ -12202,86 +14712,113 @@ msgid "UserProfile|Edit profile"
msgstr "Editar perfil"
msgid "UserProfile|Explore public groups to find projects to contribute to."
-msgstr ""
+msgstr "Explore los grupos públicos para encontrar proyectos en los que contribuir."
msgid "UserProfile|Groups"
msgstr "Grupos"
msgid "UserProfile|Groups are the best way to manage projects and members."
-msgstr ""
+msgstr "Los grupos son la mejor forma de administrar los proyectos y sus miembros."
msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
-msgstr ""
+msgstr "¡Únase o cree un grupo para comenzar a contribuir comentando en incidencias o enviando merge requests!"
msgid "UserProfile|Most Recent Activity"
-msgstr ""
+msgstr "Actividad más reciente"
msgid "UserProfile|No snippets found."
-msgstr ""
+msgstr "No se han encontrado fragmentos de código."
msgid "UserProfile|Overview"
-msgstr ""
+msgstr "Resumen"
msgid "UserProfile|Personal projects"
-msgstr ""
+msgstr "Proyectos personales"
msgid "UserProfile|Report abuse"
-msgstr ""
+msgstr "Informar de abuso"
msgid "UserProfile|Snippets"
-msgstr ""
+msgstr "Fragmentos de código"
msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
-msgstr ""
+msgstr "Los fragmentos de código en GitLab pueden ser privados, internos o públicos."
msgid "UserProfile|Subscribe"
-msgstr ""
+msgstr "Suscribirse"
msgid "UserProfile|This user doesn't have any personal projects"
-msgstr ""
+msgstr "Este usuario no tiene ningún proyecto personal"
msgid "UserProfile|This user has a private profile"
-msgstr ""
+msgstr "Este usuario tiene un perfil privado"
msgid "UserProfile|This user hasn't contributed to any projects"
-msgstr ""
+msgstr "Este usuario no ha contribuido a ningún proyecto"
msgid "UserProfile|View all"
-msgstr ""
+msgstr "Ver todo"
msgid "UserProfile|View user in admin area"
-msgstr ""
+msgstr "Ver usuario en el área de administración"
msgid "UserProfile|You can create a group for several dependent projects."
-msgstr ""
+msgstr "Puede crear un grupo que agrupe varios proyectos dependientes."
msgid "UserProfile|You haven't created any personal projects."
-msgstr ""
+msgstr "No ha creado ningún proyecto personal."
msgid "UserProfile|You haven't created any snippets."
-msgstr ""
+msgstr "No has creado ningún fragmento de código."
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
-msgstr ""
+msgstr "A su elección, sus proyectos pueden estar disponible públicamente, internamente o ser privados."
+
+msgid "Username (optional)"
+msgstr "Nombre de usuario (opcional)"
+
+msgid "Username is already taken."
+msgstr "El nombre de usuario no está disponible."
+
+msgid "Username is available."
+msgstr "El nombre de usuario está disponible."
msgid "Users"
msgstr "Usuarios"
msgid "Users outside of license"
-msgstr ""
+msgstr "Usuarios fuera de la licencia"
msgid "Users requesting access to"
-msgstr ""
+msgstr "Usuarios que solicitan acceso a"
msgid "Users were successfully added."
-msgstr ""
+msgstr "Usuarios añadidos con éxito."
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
-msgstr ""
+msgstr "Los usuarios con un rol de Invitado o de aquellos que no pertenecen a cualquiera de los proyectos o grupos no cuentan a efectos de puestos en uso."
+
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr "%{name} + %{length} más"
+
+msgid "UsersSelect|Any User"
+msgstr "Cualquier usuario"
+
+msgid "UsersSelect|Assignee"
+msgstr "Asignado"
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr "Ningún asignado - %{openingTag} asignarse a usted mismo %{closingTag}"
+
+msgid "UsersSelect|Unassigned"
+msgstr "Sin asignar"
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr "Validar"
@@ -12289,34 +14826,34 @@ msgid "Validate your GitLab CI configuration file"
msgstr "Valide su archivo de configuración de GitLab CI"
msgid "Validations failed."
-msgstr ""
+msgstr "La validación ha fallado."
msgid "Validity"
-msgstr ""
+msgstr "Validez"
msgid "Value"
msgstr "Valor"
msgid "Variables"
-msgstr ""
+msgstr "Variables"
msgid "Various container registry settings."
-msgstr ""
+msgstr "Varias opciones de configuración del registro de contenedores."
msgid "Various email settings."
-msgstr ""
+msgstr "Varias opciones de configuración de correo electrónico."
msgid "Various localization settings."
-msgstr ""
+msgstr "Varias opciones de localización."
msgid "Various settings that affect GitLab performance."
-msgstr ""
+msgstr "Varias opciones de configuración que afectan el rendimiento de GitLab."
msgid "Verification information"
msgstr "Información de verificación"
msgid "Verification status"
-msgstr ""
+msgstr "Estado de la verificación"
msgid "Verified"
msgstr "Verificado"
@@ -12327,14 +14864,20 @@ msgstr "Versión"
msgid "View app"
msgstr "Ver aplicación"
-msgid "View deployment"
+msgid "View dependency details for your project"
msgstr ""
+msgid "View deployment"
+msgstr "Ver despliegue"
+
msgid "View details: %{details_url}"
-msgstr ""
+msgstr "Ver detalles: %{details_url}"
+
+msgid "View documentation"
+msgstr "Ver documentación"
msgid "View eligible approvers"
-msgstr ""
+msgstr "Ver aprobadores elegibles"
msgid "View epics list"
msgstr "Ver lista de tareas épicas"
@@ -12342,18 +14885,24 @@ msgstr "Ver lista de tareas épicas"
msgid "View file @ "
msgstr "Ver archivo @ "
+msgid "View full dashboard"
+msgstr "Ver el panel de control completo"
+
msgid "View group labels"
-msgstr ""
+msgstr "Ver etiquetas de grupo"
msgid "View in Sentry"
-msgstr ""
+msgstr "Ver en Sentry"
msgid "View it on GitLab"
msgstr "Ver en GitLab"
-msgid "View job trace"
+msgid "View job"
msgstr ""
+msgid "View job trace"
+msgstr "Ver el registro del trabajo"
+
msgid "View jobs"
msgstr "Ver trabajos"
@@ -12376,7 +14925,10 @@ msgid "View the documentation"
msgstr "Ver documentación"
msgid "Viewing commit"
-msgstr ""
+msgstr "Ver commit"
+
+msgid "Visibility"
+msgstr "Visibilidad"
msgid "Visibility and access controls"
msgstr "Visibilidad y control de acceso"
@@ -12388,7 +14940,7 @@ msgid "Visibility level:"
msgstr "Nivel de visibilidad:"
msgid "Visibility, project features, permissions"
-msgstr ""
+msgstr "Visibilidad, características del proyecto, permisos"
msgid "Visibility:"
msgstr "Visibilidad:"
@@ -12405,11 +14957,38 @@ msgstr "Público"
msgid "VisibilityLevel|Unknown"
msgstr "Desconocido"
-msgid "Vulnerability Chart"
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr "%{stepStart}Paso 1%{stepEnd}. Copie el siguiente script:"
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr "%{stepStart}Paso 2%{stepEnd}. Agregue %{headTags} a cada pagina de su aplicación. "
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr "%{stepStart}Paso 3%{stepEnd}. Abra la app de revisión y proporcione un token de acceso personal siguiendo %{linkStart}token de acceso personal%{linkEnd}."
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr "%{stepStart}Paso 4%{stepEnd}. Ahora puede dejar comentarios desde la app de revisión."
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr "Agregar el siguiente script a su código hace posible dejar feedback directamente desde dentro de la aplicación de revisión. El feedback facilitado sera enviado automáticamente a la discusión del merge request, incluyendo los metadatos."
+
+msgid "VisualReviewApp|Open review app"
+msgstr "Abrir la aplicación de revisión"
+
+msgid "VisualReviewApp|Review"
+msgstr "Revisión"
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr "Revise y haga comentarios directamente desde la aplicación de revisión"
+
+msgid "Vulnerabilities"
msgstr ""
+msgid "Vulnerability Chart"
+msgstr "Gráfico de vulnerabilidades"
+
msgid "Vulnerability List"
-msgstr ""
+msgstr "Lista de vulnerabilidades"
msgid "Vulnerability|Class"
msgstr "Clase"
@@ -12427,7 +15006,7 @@ msgid "Vulnerability|Identifiers"
msgstr "Identificadores"
msgid "Vulnerability|Image"
-msgstr ""
+msgstr "Imagen"
msgid "Vulnerability|Instances"
msgstr "Instancias"
@@ -12436,34 +15015,40 @@ msgid "Vulnerability|Links"
msgstr "Enlaces"
msgid "Vulnerability|Namespace"
-msgstr ""
+msgstr "Espacio de nombres"
msgid "Vulnerability|Project"
msgstr "Proyecto"
msgid "Vulnerability|Report Type"
-msgstr ""
+msgstr "Tipo de informe"
msgid "Vulnerability|Severity"
msgstr "Severidad"
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr "Espera a que se cargue la fuente para copiarla al portapapeles"
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "¿Quieres ver los datos? Por favor pide acceso al administrador."
msgid "We can't find an epic that matches what you are looking for."
-msgstr ""
+msgstr "No podemos encontrar una tarea épica que coincida con lo que está buscando."
msgid "We can't find an issue that matches what you are looking for."
-msgstr ""
+msgstr "No podemos encontrar una incidencia que coincida con lo que está buscando."
msgid "We could not determine the path to remove the epic"
-msgstr ""
+msgstr "No es posible determinar la ruta para eliminar esta tarea épica"
msgid "We could not determine the path to remove the issue"
-msgstr ""
+msgstr "No es posible determinar la ruta para eliminar esta incidencia"
msgid "We couldn't find any results matching"
-msgstr ""
+msgstr "No hemos encontrado ningún resultado coincidente"
+
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr "Hemos creado una breve visita guiada que le ayudará a aprender los conceptos básicos de GitLab y cómo le ayudará a mejorar en su trabajo. Sólo debería llevarle un par de minutos. Será guiado por dos tipos de ayudantes, que puede reconocer por su color."
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "Hemos detectado spam potencial en %{humanized_resource_name}. Por favor resuelva el reCAPTCHA para poder continuar."
@@ -12472,6 +15057,9 @@ msgid "We don't have enough data to show this stage."
msgstr "No hay suficientes datos para mostrar en esta etapa."
msgid "We heard back from your U2F device. You have been authenticated."
+msgstr "Hemos obtenido respuesta desde su dispositivo U2F. Ha sido autenticado correctamente."
+
+msgid "We sent you an email with reset password instructions"
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -12487,14 +15075,17 @@ msgid "Web terminal"
msgstr "Terminal web"
msgid "Webhooks"
-msgstr ""
+msgstr "Webhooks"
msgid "Webhooks Help"
-msgstr ""
+msgstr "Ayuda de Webhooks"
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr "Los Webhooks le permiten invocar una URL si, por ejemplo, se realiza un push a o se crea una nueva incidencia. Puede configurar los webhooks para escuchar eventos específicos como pushes, incidencias, o merge request. Los webhooks de grupo se aplicarán a todos los proyectos de un grupo, permitiéndote estandarizar la funcionalidad del webhook a través de todo el grupo."
+msgid "Wednesday"
+msgstr "Miércoles"
+
msgid "Weeks"
msgstr "Semanas"
@@ -12504,26 +15095,32 @@ msgstr "Peso"
msgid "Weight %{weight}"
msgstr "Peso %{weight}"
+msgid "Welcome to the Guided GitLab Tour"
+msgstr "Bienvenido al tour guiado de GitLab"
+
+msgid "Welcome to your Issue Board!"
+msgstr "¡Bienvenido a su tablón de incidendias!"
+
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Cuando un ejecutor está bloqueado, no se puede asignar a otros proyectos"
msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr "Cuando está habilitado, los usuarios no pueden utilizar GitLab hasta que se hayan aceptado los términos de uso."
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr "Al dejar la URL en blanco, aún se pueden especificar las etiquetas de clasificación sin deshabilitar las funciones de proyectos cruzados ni realizar comprobaciones de autorización externas."
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Cuando el merge request sea aceptado"
+msgstr[1] "Cuando los merge request sean aceptados"
msgid "When:"
msgstr "Cuando:"
+msgid "White helpers give contextual information."
+msgstr "Los ayudantes blancos proporcionan información contextual."
+
msgid "Who can see this group?"
msgstr "¿Quién puede ver este grupo?"
@@ -12534,7 +15131,7 @@ msgid "Wiki"
msgstr "Wiki"
msgid "Wiki was successfully updated."
-msgstr ""
+msgstr "El wiki se actualizó correctamente."
msgid "WikiClone|Clone your wiki"
msgstr "Clonar su wiki"
@@ -12606,10 +15203,10 @@ msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
msgstr "Para vincular a una página (nueva), simplemente escriba %{link_example}"
msgid "WikiNewPagePlaceholder|how-to-setup"
-msgstr ""
+msgstr "Cómo hacer la configuración"
msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
-msgstr ""
+msgstr "Sugerencia: Puede especificar la ruta completa para el nuevo archivo. Crearemos automáticamente cualquier directorio que sea necesario."
msgid "WikiNewPageTitle|New Wiki Page"
msgstr "Nueva página de Wiki"
@@ -12636,7 +15233,7 @@ msgid "WikiPageEdit|Update %{page_title}"
msgstr "Actualizar %{page_title}"
msgid "WikiPage|Page slug"
-msgstr ""
+msgstr "Indice de la página"
msgid "WikiPage|Write your content or drag files here…"
msgstr "Escriba su contenido o arrastre archivos aquí…"
@@ -12648,7 +15245,7 @@ msgid "Wiki|Create page"
msgstr "Crear página"
msgid "Wiki|Created date"
-msgstr ""
+msgstr "Fecha de creación"
msgid "Wiki|Edit Page"
msgstr "Editar página"
@@ -12669,7 +15266,7 @@ msgid "Wiki|Pages"
msgstr "Páginas"
msgid "Wiki|Title"
-msgstr ""
+msgstr "Título"
msgid "Wiki|Wiki Pages"
msgstr "Páginas del Wiki"
@@ -12684,10 +15281,10 @@ msgid "Withdraw Access Request"
msgstr "Retirar Solicitud de Acceso"
msgid "Workflow Help"
-msgstr ""
+msgstr "Ayuda sobre el flujo de trabajo"
msgid "Write"
-msgstr ""
+msgstr "Escritura"
msgid "Write a comment or drag your files here…"
msgstr "Escriba un comentario o arrastre sus archivos aquí…"
@@ -12699,16 +15296,19 @@ msgid "Write milestone description..."
msgstr "Escriba la descripción del hito..."
msgid "Wrong extern UID provided. Make sure Auth0 is configured correctly."
-msgstr ""
+msgstr "UID externo incorrecto. Por favor, asegúrese de que Auth0 está configurado correctamente."
msgid "Yes"
msgstr "Si"
+msgid "Yes or No"
+msgstr "Sí o no"
+
msgid "Yes, add it"
msgstr "Si, hazlo"
msgid "Yes, let me map Google Code users to full names or GitLab users."
-msgstr ""
+msgstr "Sí, déjenme asignar usuarios de Google Code a nombres completos o usuarios de GitLab."
msgid "Yesterday"
msgstr "Ayer"
@@ -12717,28 +15317,37 @@ msgid "You"
msgstr "Usted"
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
-msgstr ""
+msgstr "Es administrador, lo que significa que otorgar acceso a <strong>%{client_name}</strong> le permitirá interactuar con GitLab como también administrador. Por favor, proceda con precaución."
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "Va a eliminar %{group_name}. ¡El grupo eliminado NO puede ser restaurado! ¿Estás TOTALMENTE seguro?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr "Está intentando eliminar un archivo que ha sido actualizado previamente."
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr "Está intentando actualizar un archivo que ha sido modificado desde que comenzó a editarlo."
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr "Va a eliminar %{project_full_name}. ¡No es posible restaurar un proyecto eliminado! ¿Está TOTALMENTE seguro?"
+
msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
msgstr "Vas a eliminar el enlace de la bifurcación con el proyecto original %{forked_from_project}. ¿Estás TOTALMENTE seguro?"
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
+msgstr "Va a transferir %{project_full_name} a otro propietario. ¿Está TOTALMENTE seguro?"
+
+msgid "You are not allowed to unlink your primary login account"
msgstr ""
msgid "You are now impersonating %{username}"
-msgstr ""
+msgstr "Está suplantando la identidad de %{username}"
msgid "You are on a read-only GitLab instance."
msgstr "Está en una instancia de sólo lectura GitLab."
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
-msgstr ""
+msgstr "Está recibiendo este mensaje porque es un administrador de GitLab para %{url}."
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr "Puede %{linkStart}ver el blob%{linkEnd} en su lugar."
@@ -12746,11 +15355,17 @@ msgstr "Puede %{linkStart}ver el blob%{linkEnd} en su lugar."
msgid "You can also create a project from the command line."
msgstr "También puede crear un proyecto desde la línea de comandos."
+msgid "You can also press &#8984;-Enter"
+msgstr "También puede pulsar &#8984;- Enter"
+
+msgid "You can also press Ctrl-Enter"
+msgstr "También puede presionar Ctrl-Enter"
+
msgid "You can also star a label to make it a priority label."
-msgstr ""
+msgstr "También puede destacar una etiqueta para convertirla en una etiqueta prioritaria."
msgid "You can also test your %{gitlab_ci_yml} in %{lint_link_start}CI Lint%{lint_link_end}"
-msgstr ""
+msgstr "También puede validar su fichero %{gitlab_ci_yml} en %{lint_link_start}CI Lint%{lint_link_end}"
msgid "You can also upload existing files from your computer using the instructions below."
msgstr "También puede subir archivos existentes desde su ordenador utilizando las instrucciones que se muestran a continuación."
@@ -12759,11 +15374,20 @@ msgid "You can create files directly in GitLab using one of the following option
msgstr "Puede crear archivos directamente en GitLab utiliznado una de las siguientes opciones."
msgid "You can easily contribute to them by requesting to join these groups."
-msgstr ""
+msgstr "Puede contribuir fácilmente pidiendo unirse a estos grupos."
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr "Puede instalar fácilmente un ejecutor en un clúster de Kubernetes. %{link_to_help_page}"
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr "Puede invitar a un nuevo miembro a <strong>%{project_name}</strong> o invitar a otro grupo."
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr "Puedes invitar a un nuevo miembro a <strong>%{project_name}</strong>."
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr "Puedes invitar a otro grupo a <strong>%{project_name}</strong>."
+
msgid "You can move around the graph by using the arrow keys."
msgstr "Puede moverse por el gráfico usando las teclas de flecha."
@@ -12780,31 +15404,37 @@ msgid "You can only edit files when you are on a branch"
msgstr "Solo puede agregar archivos cuando está en una rama"
msgid "You can only merge once the items above are resolved"
-msgstr ""
+msgstr "Solo puede hacer el merge una vez que haya resuelto los elementos anteriores"
msgid "You can only transfer the project to namespaces you manage."
-msgstr ""
+msgstr "Solo puede transferir el proyecto a los espacios de nombres que administre."
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
-msgstr ""
+msgstr "Puede resolver el conflicto del merge request utilizando el modo Interactivo, utilizando los botones %{use_ours} o %{use_theirs}, o editando los archivos directamente. Confirme estos cambios en %{branch_name}"
+
+msgid "You can see your chat accounts."
+msgstr "Puede ver sus cuentas de chat."
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
-msgstr ""
+msgstr "Puede configurar trabajos para usar solo ejecutores con etiquetas específicas. Por favor, separe las etiquetas con comas."
+
+msgid "You can specify notification level per group or per project."
+msgstr "Puede especificar el nivel de la notificación por grupo o por proyecto."
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr "Puede probar su archivo .gitlab-ci.yml en %{linkStart}CI Lint%{linkEnd}."
msgid "You cannot impersonate a blocked user"
-msgstr ""
+msgstr "No puede suplantar a un usuario bloqueado"
msgid "You cannot impersonate a user who cannot log in"
-msgstr ""
+msgstr "No puede suplantar a un usuario que no puede iniciar sesión"
msgid "You cannot impersonate an internal user"
-msgstr ""
+msgstr "No puede suplantar a un usuario interno"
msgid "You cannot play this scheduled pipeline at the moment. Please wait a minute."
-msgstr ""
+msgstr "No puede ejecutar este pipeline programado en este momento. Por favor, espere un minuto."
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr "No puedes escribir en una instancia secundaria de sólo lectura de GitLab Geo. Utilice %{link_to_primary_node} en lugar de otro."
@@ -12813,20 +15443,29 @@ msgid "You cannot write to this read-only GitLab instance."
msgstr "No puede escribir en esta instancia de sólo lectura de GitLab."
msgid "You could not create a new trigger."
-msgstr ""
+msgstr "No es posible crear un nuevo disparador."
msgid "You could not take ownership of trigger."
-msgstr ""
+msgstr "No es posible obtener la propiedad del disparador."
msgid "You do not have any subscriptions yet"
msgstr "Aún no tiene ninguna suscripción"
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr "No tiene permiso para dejar este %{namespaceType}."
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
-msgstr ""
+msgstr "No tiene permiso para ejecutar el terminal web. Por favor, póngase en contacto con un administrador del proyecto."
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr "No tiene los permisos necesarios para sobreescribir la configuración de la sincronización de grupos de LDAP."
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr "No tiene ningún nick de chat activo."
+
msgid "You don't have any applications"
msgstr "No tiene ninguna aplicación"
@@ -12834,31 +15473,37 @@ msgid "You don't have any authorized applications"
msgstr "No tiene ninguna aplicación autorizada"
msgid "You don't have any deployments right now."
-msgstr ""
+msgstr "No tienes ningún despliegue en este momento."
+
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr "Se le ha concedido %{access_level} acceso al %{source_link} %{source_type}."
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr "Se le ha concedido el acceso a %{access_level} a %{source_name} %{source_type}."
msgid "You have been granted %{member_human_access} access to %{label}."
-msgstr ""
+msgstr "Se le ha concedido acceso de %{member_human_access} a %{label}."
msgid "You have been unsubscribed from this thread."
-msgstr ""
+msgstr "Se ha cancelado la suscripción a este hilo."
msgid "You have declined the invitation to join %{label}."
-msgstr ""
+msgstr "Has rechazado la invitación para unirse a %{label}."
msgid "You have no permissions"
msgstr "No tiene permisos"
msgid "You have not added any approvers. Start by adding users or groups."
-msgstr ""
+msgstr "No ha añadido aprobadores. Empiece por añadir usuarios o grupos."
msgid "You have reached your project limit"
msgstr "Has alcanzado el límite de tu proyecto"
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
-msgstr ""
+msgstr "Dejó el \"%{membershipable_human_name}\" %{source_type}."
msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
-msgstr ""
+msgstr "También puede añadir variables que están disponibles para la aplicación en ejecución, anteponiendo la clave de variable con <code>K8S_SECRET_</code>."
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr "Debe aceptar nuestros Términos de servicio y la política de privacidad para poder registrar una cuenta"
@@ -12866,11 +15511,20 @@ msgstr "Debe aceptar nuestros Términos de servicio y la política de privacidad
msgid "You must have maintainer access to force delete a lock"
msgstr "Debe tener permiso como mantenedor para forzar la eliminación de un bloqueo"
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr "Debe tener permiso para crear un proyecto en un espacio de nombres antes de realizar fork."
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr "Necesita una licencia diferente para habilitar la función FileLocks"
msgid "You need a different license to use Geo replication."
-msgstr ""
+msgstr "Necesita una licencia diferente para usar las repicas con Geo."
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr "Necesita la versión %{min_git_lfs_version} de git-lfs para continuar. Por favor, visite la URL https://git-lfs.github.com"
@@ -12878,26 +15532,32 @@ msgstr "Necesita la versión %{min_git_lfs_version} de git-lfs para continuar. P
msgid "You need permission."
msgstr "Necesitas permisos."
+msgid "You need to be logged in."
+msgstr "Es necesario haber iniciado una sesión."
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
-msgstr ""
+msgstr "Necesita registrar una aplicación de autenticación de dos factores antes de poder configurar un dispositivo U2F."
msgid "You need to specify both an Access Token and a Host URL."
-msgstr ""
+msgstr "Necesita especificar un token de acceso como una URL de host."
msgid "You need to upload a GitLab project export archive (ending in .gz)."
-msgstr ""
+msgstr "Es necesario subir un archivo de exportación de proyecto de GitLab (en formato .gz)."
msgid "You need to upload a Google Takeout archive."
-msgstr ""
+msgstr "Necesita subir un archivo de Google Takeout."
+
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr "Trató de hacer un fork de %{link_to_the_project} pero falló por la siguiente razón:"
msgid "You will lose all changes you've made to this file. This action cannot be undone."
-msgstr ""
+msgstr "Perderá todos los cambios que haya realizado en este archivo. Esta acción no se puede deshacer."
msgid "You will lose all the unstaged changes you've made in this project. This action cannot be undone."
-msgstr ""
+msgstr "Perderá todos los cambios no guardados en este proyecto. Esta acción no se puede deshacer."
msgid "You will need to update your local repositories to point to the new location."
-msgstr ""
+msgstr "Debe actualizar sus repositorios locales para que apunten a la nueva ubicación."
msgid "You will not get any notifications via email"
msgstr "No recibirás ninguna notificación por correo electrónico"
@@ -12921,61 +15581,88 @@ msgid "You won't be able to pull or push project code via SSH until you %{add_ss
msgstr "No podrás actualizar o enviar código al proyecto a través de SSH hasta que %{add_ssh_key_link} en su perfil"
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
-msgstr ""
+msgstr "No podrá actualizar o enviar código al proyecto a través de SSH hasta que no agregue una clave SSH a su perfil"
+
+msgid "You'll be signed out from your current account automatically."
+msgstr "Se cerrará la sesión de su cuenta actual de forma automática."
msgid "You'll need to use different branch names to get a valid comparison."
-msgstr ""
+msgstr "Tendrá que utilizar nombres de ramas diferentes para obtener resultados de comparación correctos."
msgid "You're not allowed to make changes to this project directly. A fork of this project has been created that you can make changes in, so you can submit a merge request."
-msgstr ""
+msgstr "No tiene permiso para realizar cambios directamente en este proyecto. Se ha creado un fork de este proyecto que puede utilizar para realizar los cambios que desee, por lo que puede enviar un merge request."
msgid "You're not allowed to make changes to this project directly. A fork of this project is being created that you can make changes in, so you can submit a merge request."
-msgstr ""
+msgstr "No tiene permiso para realizar cambios directamente en este proyecto. Se ha creado un fork de este proyecto que puede utilizar para realizar los cambios que desee, por lo que puede enviar un merge request."
msgid "You're only seeing %{startTag}other activity%{endTag} in the feed. To add a comment, switch to one of the following options."
-msgstr ""
+msgstr "Solo está viendo %{startTag}otra actividad%{endTag} en el feed. Para agregar un comentario, cambie a una de las siguientes opciones."
msgid "You're receiving this email because %{reason}."
msgstr "Está recibiendo este correo porque %{reason}."
msgid "You're receiving this email because of your account on %{host}."
-msgstr ""
+msgstr "Está recibiendo este correo electrónico por su cuenta en %{host}."
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr "Está recibiendo este correo electrónico porque tiene su cuenta en %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr "Ya ha habilitado la autenticación de dos pasos utilizando una contraseña de un solo uso. Para registrar un dispositivo diferente, primero debe desactivar la autenticación de dos factores."
+
msgid "YouTube"
msgstr "YouTube"
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr "Sus claves GPG (%{count})"
+
msgid "Your Groups"
msgstr "Sus grupos"
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr "La información del cluster de Kubernetes en esta página aún se puede editar, pero se recomienda desactivarla y modificar"
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr "Sus proyectos (por defecto)"
msgid "Your Projects' Activity"
msgstr "Actividad de sus proyectos"
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr "Sus Claves SSH (%{count})"
+
msgid "Your Todos"
msgstr "Sus tareas pendientes"
+msgid "Your U2F device did not send a valid JSON response."
+msgstr "Su dispositivo U2F no envió una respuesta JSON válida."
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
-msgstr ""
+msgstr "Es necesario configurar su dispositivo U2F. Conéctelo (si no lo ha hecho ya) y haha clic en el botón situado a la izquierda."
msgid "Your U2F device was registered!"
-msgstr ""
+msgstr "¡Se ha registrado su dispositivo U2F!"
msgid "Your access request to the %{source_type} has been withdrawn."
-msgstr ""
+msgstr "Su solicitud de acceso a %{source_type} ha sido retirada."
msgid "Your account uses dedicated credentials for the \"%{group_name}\" group and can only be updated through SSO."
-msgstr ""
+msgstr "Su cuenta utiliza credenciales dedicadas para el grupo \"%{group_name}\" y sólo puede actualizarse a través de SSO."
msgid "Your applications (%{size})"
msgstr "Sus aplicaciones (%{size})"
@@ -12984,7 +15671,7 @@ msgid "Your authorized applications"
msgstr "Sus aplicaciones autorizadas"
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
-msgstr ""
+msgstr "Su navegador no soporta U2F. Por favor, utilice la versión de escritorio de Google Chrome (versión 41 o posterior)."
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr "Puede hacer commit de sus cambios a %{branch_name} porque hay un merge request abierto."
@@ -12996,70 +15683,79 @@ msgid "Your changes have been saved"
msgstr "Se han guardado sus cambios"
msgid "Your changes have been successfully committed."
-msgstr ""
+msgstr "Los cambios se han guardado correctamente."
+
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr "Se ha producido un error al enviar su comentario. Por favor, compruebe su conexión de red y vuelva a intentarlo."
-msgid "Your comment will not be visible to the public."
-msgstr "Tus comentarios no serán visibles al público."
+msgid "Your comment could not be updated! Please check your network connection and try again."
+msgstr "Se ha producido un error al editar su comentario. Por favor, compruebe su conexión de red y vuelva a intentarlo."
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
-msgstr ""
+msgstr "Se interrumpirán sus servicios de despliegue, tendrá que arreglarlos manualmente después del cambio de nombre."
msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
-msgstr ""
+msgstr "¡El dispositivo se ha configurado correctamente!. Por favor, asígnele un nombre y regístrelo con el servidor de GitLab."
msgid "Your groups"
msgstr "Tus grupos"
msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
-msgstr ""
+msgstr "Se están importando sus incidencias. Al finalizar el proceso, recibirá un correo electrónico de confirmación."
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
-msgstr ""
+msgstr "Sus incidencias serán importados como tarea de fondo. Al finalizar el proceso, recibirá un correo electrónico de confirmación."
+
+msgid "Your message here"
+msgstr "Su mensaje aquí"
msgid "Your name"
msgstr "Tu nombre"
msgid "Your new SCIM token"
-msgstr ""
+msgstr "Su nuevo token SCIM"
msgid "Your new personal access token has been created."
-msgstr ""
+msgstr "Se ha creado su nuevo token de acceso personal."
msgid "Your password reset token has expired."
-msgstr ""
+msgstr "Su token para restablecer la contraseña ha caducado."
msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
-msgstr ""
+msgstr "¡Su límite de proyecto es %{limit} proyectos! Por favor, contacte con su administrador para aumentarlo"
msgid "Your projects"
msgstr "Tus proyectos"
msgid "Your request for access has been queued for review."
-msgstr ""
+msgstr "Su solicitud de acceso ha sido puesta en cola para su revisión."
msgid "a deleted user"
msgstr "un usuario eliminado"
msgid "added %{created_at_timeago}"
-msgstr ""
+msgstr "añadido %{created_at_timeago}"
msgid "ago"
msgstr "hace"
msgid "allowed to fail"
-msgstr ""
+msgstr "permitido fallar"
+
+msgid "already being used for another group or project milestone."
+msgstr "ya se está utilizando para otro grupo o hito del proyecto."
+
+msgid "already shared with this group"
+msgstr "compartido previamente con este grupo"
msgid "among other things"
msgstr "entre otras cosas"
-msgid "at"
-msgstr ""
-
msgid "attach a new file"
-msgstr ""
+msgstr "adjuntar un nuevo archivo"
msgid "authored"
-msgstr ""
+msgstr "autor"
msgid "branch name"
msgstr "nombre de la rama"
@@ -13067,6 +15763,21 @@ msgstr "nombre de la rama"
msgid "by"
msgstr "por"
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr "no se puede modificar si un proyecto personal ya contiene etiquetas de registro de contenedor."
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr "no se puede habilitar a menos que todos los dominios tengan certificados TLS"
+
+msgid "cannot block others"
+msgstr "no puede bloquear a otros"
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr "no se puede bloquer"
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr "%{linkStartTag}Aprenda más sobre el analísis de contenedores %{linkEndTag}"
@@ -13101,43 +15812,43 @@ msgstr[0] "%{reportType} %{status} detectada %{fixedCount} vulnerabilidad correg
msgstr[1] "%{reportType} %{status} detectado %{fixedCount} vulnerabilidad corregida"
msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed, and %{dismissedCount} dismissed vulnerabilities"
-msgstr ""
+msgstr "%{reportType} %{status} detectadas %{fixedCount} arregladas, y %{dismissedCount} vulnerabilidades descartadas"
msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{reportType} %{status} detectada %{newCount} nueva vulnerabilidad"
+msgstr[1] "%{reportType} %{status} detectadas %{newCount} nuevas vulnerabilidades"
msgid "ciReport|%{reportType} %{status} detected %{newCount} new, %{fixedCount} fixed, and %{dismissedCount} dismissed vulnerabilities"
-msgstr ""
+msgstr "%{reportType} %{status} detectó %{newCount} vulnerabilidades nuevas, %{fixedCount} corregidas y %{dismissedCount} descartadas"
msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{dismissedCount} dismissed vulnerabilities"
-msgstr ""
+msgstr "%{reportType} %{status} detectó %{newCount} nuevos, y descartó %{dismissedCount} vulnerabilidades"
msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{dismissedCount} dismissed vulnerabilities for the source branch only"
-msgstr ""
+msgstr "%{reportType} %{status} detectó %{newCount} vulnerabilidades nuevas y corrigió %{dismissedCount} vulnerabilidades para la rama origen"
msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
-msgstr ""
+msgstr "%{reportType} %{status} detectó %{newCount} vulnerabilidades nuevas y corrigió %{fixedCount}"
msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{reportType} %{status} detectó %{newCount} vulnerabilidad para la rama fuente"
+msgstr[1] "%{reportType} %{status} detectó %{newCount} vulnerabilidades para la rama fuente"
msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
-msgstr ""
+msgstr "%{reportType} %{status} no detecto nuevas vulnerabilidades"
msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
-msgstr ""
+msgstr "%{reportType} %{status} no detecto vulnerabilidades"
msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
-msgstr ""
+msgstr "%{reportType} %{status} no detectó vulnerabilidades para la rama origen"
msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{reportType} detectada %{vulnerabilityCount} vulnerabilidad"
+msgstr[1] "%{reportType} detectada %{vulnerabilityCount} vulnerabilidades"
msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr "%{reportType} no detectó vulnerabilidades"
@@ -13146,10 +15857,10 @@ msgid "ciReport|%{reportType} is loading"
msgstr "%{reportType} está cargando"
msgid "ciReport|%{reportType}: Loading resulted in an error"
-msgstr ""
+msgstr "%{reportType}: La carga finalizó con errores"
msgid "ciReport|%{vulnerability} in %{featurename}"
-msgstr ""
+msgstr "%{vulnerability} en %{featurename}"
msgid "ciReport|(errors when loading results)"
msgstr "(se han producido errores al cargar resultados)"
@@ -13160,14 +15871,17 @@ msgstr "(está cargando)"
msgid "ciReport|(is loading, errors when loading results)"
msgstr "(está cargando, se han producido errores al cargar resultados)"
+msgid "ciReport|All confidence levels"
+msgstr "Todos los niveles de confianza"
+
msgid "ciReport|All projects"
-msgstr ""
+msgstr "Todos los proyectos"
msgid "ciReport|All report types"
-msgstr ""
+msgstr "Todos los tipos de informes"
msgid "ciReport|All severities"
-msgstr ""
+msgstr "Todos los niveles de gravedad"
msgid "ciReport|Class"
msgstr "Clase"
@@ -13179,7 +15893,7 @@ msgid "ciReport|Confidence"
msgstr "Confianza"
msgid "ciReport|Container Scanning"
-msgstr ""
+msgstr "Análisis de contenedores"
msgid "ciReport|Container scanning"
msgstr "Análisis de contenedores"
@@ -13188,19 +15902,16 @@ msgid "ciReport|Container scanning detects known vulnerabilities in your docker
msgstr "El análisis de contenedores detecta vulnerabilidades conocidas en sus imágenes de Docker."
msgid "ciReport|Create issue"
-msgstr ""
+msgstr "Crear incidencia"
msgid "ciReport|Create merge request"
-msgstr ""
-
-msgid "ciReport|Created %{eventType}"
-msgstr ""
+msgstr "Crear merge request"
msgid "ciReport|DAST"
msgstr "DAST"
msgid "ciReport|Dependency Scanning"
-msgstr ""
+msgstr "Escaneo de dependencias"
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr "El análisis de dependencias detecta vulnerabilidades conocidas en las dependencias de su código fuente."
@@ -13211,17 +15922,11 @@ msgstr "Escaneo de seguridad"
msgid "ciReport|Description"
msgstr "Descripción"
-msgid "ciReport|Dismiss vulnerability"
-msgstr "Descartar vulnerabilidad"
-
-msgid "ciReport|Dismissed by"
-msgstr "Descartado por"
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
-msgstr ""
+msgstr "Descargue y aplique el parche para corregir esta vulnerabilidad."
msgid "ciReport|Download patch"
-msgstr ""
+msgstr "Descargar parche"
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
msgstr "Dynamic Application Security Testing (DAST) detecta vulnerabilidades conocidas en su código fuente."
@@ -13239,35 +15944,35 @@ msgid "ciReport|Identifiers"
msgstr "Identificadores"
msgid "ciReport|Image"
-msgstr ""
+msgstr "Imagen"
msgid "ciReport|Implement this solution by creating a merge request"
-msgstr ""
+msgstr "Implemente esta solución creando un merge request"
msgid "ciReport|Instances"
msgstr "Instancias"
msgid "ciReport|Investigate this vulnerability by creating an issue"
-msgstr ""
+msgstr "Investigue esta vulnerabilidad creando una incidencia"
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr "Obtenga más información sobre cómo interactuar con los informes de seguridad (Alpha)."
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "El administrador de licencias detectó %d licencia para la rama de origen"
+msgstr[1] "El administrador de licencias detectó %d licencias para la rama de origen"
msgid "ciReport|License management detected %d new license"
msgid_plural "ciReport|License management detected %d new licenses"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "El administrador de licencias detectó %d nueva licencia"
+msgstr[1] "El administrador de licencias detectó %d nueva licencia"
msgid "ciReport|License management detected no licenses for the source branch only"
-msgstr ""
+msgstr "El administrador de licencias no detectó ninguna licencia para la rama de origen"
msgid "ciReport|License management detected no new licenses"
-msgstr ""
+msgstr "El administrador de licencias no detectó nuevas licencias"
msgid "ciReport|Links"
msgstr "Enlaces"
@@ -13312,13 +16017,13 @@ msgid "ciReport|Static Application Security Testing (SAST) detects known vulnera
msgstr "Static Application Security Testing (SAST) detecta vulnerabilidades conocidas en su código fuente."
msgid "ciReport|There was an error creating the issue. Please try again."
-msgstr ""
+msgstr "Se ha producido un error al crear la incidencia. Por favor, inténtelo de nuevo."
msgid "ciReport|There was an error creating the merge request. Please try again."
-msgstr ""
+msgstr "Se ha producido un error al crear el merge request. Por favor, inténtelo de nuevo."
msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
-msgstr ""
+msgstr "Se ha producido un error al descartar la vulnerabilidad. Por favor, inténtelo de nuevo."
msgid "ciReport|There was an error loading DAST report"
msgstr "Se ha producido un error al cargar el informe SAST."
@@ -13330,66 +16035,63 @@ msgid "ciReport|There was an error loading container scanning report"
msgstr "Se ha producido un error al cargar el informe de escaneo de contenedores."
msgid "ciReport|There was an error loading dependency scanning report"
-msgstr ""
+msgstr "Se ha producido un error al cargar el informe de análisis de dependencias"
msgid "ciReport|There was an error reverting the dismissal. Please try again."
-msgstr ""
-
-msgid "ciReport|Undo dismiss"
-msgstr ""
+msgstr "Se ha producido un error al descartar la vulnerabilidad. Por favor, inténtalo de nuevo."
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
-msgstr ""
+msgstr "Actualice desde la versión %{name} de %{version} a %{fixed}."
msgid "ciReport|Upgrade %{name} to %{fixed}."
-msgstr ""
+msgstr "Actualizar %{name} a %{fixed}."
msgid "ciReport|Upgrade to %{fixed}."
-msgstr ""
+msgstr "Actualizar a %{fixed}."
msgid "ciReport|Used by %{packagesString}"
msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Utilizado por %{packagesString}"
+msgstr[1] "Utilizado por %{packagesString} y %{lastPackage}"
msgid "ciReport|View full report"
msgstr "Ver informe completo"
-msgid "ciReport|on pipeline"
-msgstr "en el pipeline"
-
msgid "commented on %{link_to_project}"
+msgstr "comentado en %{link_to_project}"
+
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
-msgstr ""
+msgstr "Confirmada"
msgid "confidence|Experimental"
-msgstr ""
+msgstr "Experimental"
msgid "confidence|High"
-msgstr ""
+msgstr "Alta"
msgid "confidence|Ignore"
-msgstr ""
+msgstr "Ignorar"
msgid "confidence|Low"
-msgstr ""
+msgstr "Baja"
msgid "confidence|Medium"
-msgstr ""
+msgstr "Media"
msgid "confidence|Undefined"
-msgstr ""
+msgstr "Sin definir"
msgid "confidence|Unknown"
-msgstr ""
+msgstr "Desconocida"
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
+msgstr "Va a desactivar la confidencialidad. Esto significa que <strong>todos</strong> podrán ver y dejar un comentario sobre este tema."
msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
+msgstr "Va a activar la confidencialidad. Esto significa que solo los miembros del equipo con como mínimo,<strong>acceso como Reporter</strong> podrán ver y dejar comentarios sobre la incidencia."
msgid "connecting"
msgstr "conectando"
@@ -13400,27 +16102,30 @@ msgstr "no se ha podido leer la clave privada, ¿La contraseña es correcta?"
msgid "customize"
msgstr "personalizar"
+msgid "date must not be after 9999-12-31"
+msgstr "la fecha no puede ser superior a 9999-12-31"
+
msgid "day"
msgid_plural "days"
msgstr[0] "día"
msgstr[1] "días"
msgid "deleted"
-msgstr ""
+msgstr "eliminado"
msgid "deploy token"
msgstr "desplegar token"
msgid "detached"
-msgstr ""
+msgstr "Desvinculado"
msgid "disabled"
msgstr "deshabilitado"
msgid "discussion resolved"
msgid_plural "discussions resolved"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "discusión resuelta"
+msgstr[1] "discusiones resueltas"
msgid "done"
msgstr "hecho"
@@ -13430,11 +16135,17 @@ msgid_plural "drafts"
msgstr[0] "borrador"
msgstr[1] "borradores"
+msgid "element is not a hierarchy"
+msgstr "el elemento no es una jerarquía"
+
msgid "enabled"
msgstr "habilitado"
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr "encriptado: debe ser :requerido, :opcional o :migrando"
+
msgid "epic"
-msgstr ""
+msgstr "épica"
msgid "error"
msgstr "error"
@@ -13445,20 +16156,26 @@ msgstr "código de error:"
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr "%{slash_command} actualizará la hora estimada con el último comando."
+msgid "expired on %{milestone_due_date}"
+msgstr "expiró el %{milestone_due_date}"
+
+msgid "expires on %{milestone_due_date}"
+msgstr "expira el %{milestone_due_date}"
+
msgid "failed"
-msgstr ""
+msgstr "fallido"
msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch}"
-msgstr ""
+msgstr "para %{link_to_merge_request} con %{link_to_merge_request_source_branch}"
msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch} into %{link_to_merge_request_target_branch}"
-msgstr ""
+msgstr "para %{link_to_merge_request} con %{link_to_merge_request_source_branch} en %{link_to_merge_request_target_branch}"
msgid "for %{link_to_pipeline_ref}"
-msgstr ""
+msgstr "para %{link_to_pipeline_ref}"
msgid "for %{ref}"
-msgstr ""
+msgstr "para %{ref}"
msgid "for this project"
msgstr "para este proyecto"
@@ -13469,6 +16186,9 @@ msgstr "de"
msgid "group"
msgstr "grupo"
+msgid "has already been taken"
+msgstr "ya está en uso"
+
msgid "here"
msgstr "aquí"
@@ -13476,7 +16196,7 @@ msgid "https://your-bitbucket-server"
msgstr "https://tu-servidor-bitbucket"
msgid "image diff"
-msgstr ""
+msgstr "imagen dif"
msgid "import flow"
msgstr "flujo de importación"
@@ -13485,10 +16205,10 @@ msgid "importing"
msgstr "importando"
msgid "in group %{link_to_group}"
-msgstr ""
+msgstr "en el grupo %{link_to_group}"
msgid "in project %{link_to_project}"
-msgstr ""
+msgstr "en el proyecto %{link_to_project}"
msgid "index"
msgstr "índice"
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] "instancia completada"
msgstr[1] "instancias completadas"
+msgid "invalid milestone state `%{state}`"
+msgstr "estado del hito invalido '%{state}'"
+
+msgid "is enabled."
+msgstr "está habilitado."
+
msgid "is invalid because there is downstream lock"
msgstr "no es válido porque hay un bloqueo en sentido descendente"
@@ -13507,26 +16233,32 @@ msgstr "no es válido porque hay un bloqueo en sentido ascendente"
msgid "is not a valid X509 certificate."
msgstr "no es un certificado X509 válido."
+msgid "is not an email you own"
+msgstr "no es un correo electrónico de su propiedad"
+
msgid "is out of the hierarchy of the Group owning the template"
-msgstr ""
+msgstr "Está fuera de la jerarquía del grupo que posee la plantilla"
msgid "issue"
-msgstr ""
+msgstr "incidencia"
msgid "issue boards"
msgstr "tablero de incidencias"
msgid "it is stored externally"
-msgstr ""
+msgstr "es almacenado externamente"
msgid "it is stored in LFS"
-msgstr ""
+msgstr "se almacena en el LFS"
msgid "it is too large"
-msgstr ""
+msgstr "es demasiado grande"
+
+msgid "jigsaw is not defined"
+msgstr "jigsaw no está definido"
msgid "latest"
-msgstr ""
+msgstr "último"
msgid "latest deployment"
msgstr "último despliegue"
@@ -13535,7 +16267,7 @@ msgid "latest version"
msgstr "última versión"
msgid "leave %{group_name}"
-msgstr ""
+msgstr "abandonar %{group_name}"
msgid "license management"
msgstr "gestión de licencias"
@@ -13544,78 +16276,84 @@ msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "bloqueado por %{path_lock_user_name} %{created_at}"
msgid "manual"
-msgstr ""
+msgstr "manual"
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] "merge request"
msgstr[1] "merge requests"
+msgid "milestone should belong either to a project or a group."
+msgstr "el hito debe pertenecer a un proyecto o un grupo."
+
msgid "missing"
-msgstr ""
+msgstr "falta"
msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
-msgstr ""
+msgstr "%{commitCount} y %{mergeCommitCount} se añadirán a %{targetBranch}."
msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
-msgstr ""
+msgstr "%{commitCount} se añadirá a %{targetBranch}."
msgid "mrWidgetCommitsAdded|1 merge commit"
-msgstr ""
+msgstr "1 merge commit"
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "Restaure o use una rama diferente %{missingBranchName}"
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
-msgstr ""
+msgstr "%{link_start}Obtenga más información sobre como resolver conflictos%{link_end}"
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
-msgstr ""
+msgstr "Uso de %{metricsLinkStart} memoria %{metricsLinkEnd} %{emphasisStart} disminuido %{emphasisEnd} de %{memoryFrom}MB a %{memoryTo}MB"
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
-msgstr ""
+msgstr "Uso de %{metricsLinkStart} memoria %{metricsLinkEnd} %{emphasisStart} incrementado %{emphasisEnd} de %{memoryFrom}MB a %{memoryTo}MB"
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
-msgstr ""
+msgstr "%{metricsLinkStart} El uso de la memoria %{metricsLinkEnd} es %{emphasisStart} sin cambios %{emphasisEnd} en %{memoryFrom}MB"
-msgid "mrWidget|Add approval"
-msgstr "Añadir aprobación"
+msgid "mrWidget|Added to the merge train by"
+msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
+msgstr "Permitir que los commits de los miembros se pueden mergear con la rama de destino"
msgid "mrWidget|An error occurred while removing your approval."
-msgstr ""
+msgstr "se ha producido un error al eliminar su aprobación."
msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
-msgstr ""
+msgstr "Se ha producido un error al recuperar los datos de aprobación para este merge request."
msgid "mrWidget|An error occurred while submitting your approval."
-msgstr ""
+msgstr "Se ha producido un error al enviar su aprobación."
+
+msgid "mrWidget|Approval password is invalid."
+msgstr "La contraseña de aprobación no es correcta."
msgid "mrWidget|Approve"
msgstr "Aprobar"
msgid "mrWidget|Approve additionally"
-msgstr ""
+msgstr "Aprobar adicionalmente"
msgid "mrWidget|Approved by"
msgstr "Aprobado por"
msgid "mrWidget|Cancel automatic merge"
-msgstr ""
+msgstr "Cancelar merge automático"
msgid "mrWidget|Check out branch"
msgstr "Check-out"
msgid "mrWidget|Checking ability to merge automatically"
-msgstr ""
+msgstr "Comprobando la capacidad para realizar los merge automáticamente"
msgid "mrWidget|Cherry-pick"
msgstr "Cherry-pick"
msgid "mrWidget|Cherry-pick this merge request in a new merge request"
-msgstr ""
+msgstr "Hacer un cherry-pick de este merge request en un nuevo merge request"
msgid "mrWidget|Closed"
msgstr "Cerrado"
@@ -13630,7 +16368,7 @@ msgid "mrWidget|Create an issue to resolve them later"
msgstr "Crear una incidencia para resolverla posteriormente"
msgid "mrWidget|Delete source branch"
-msgstr ""
+msgstr "Eliminar la rama de origen"
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "Las estadísticas de los despliegues no están disponibles actualmente"
@@ -13647,6 +16385,9 @@ msgstr "Error al cargar las estadísticas de despliegue"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr "No es posible realizar un merge fast-forward. Para poder hacer un merge de esta solicitud, es necesario hacer rebase localmente."
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr "Si el branch %{branch} existe en su repositorio local, puede hacer un merge de la solicitud de merge request manualmente utilizando la línea de comandos"
@@ -13665,26 +16406,23 @@ msgstr "Merge"
msgid "mrWidget|Merge failed."
msgstr "Merge fallido."
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
+msgstr ""
+
msgid "mrWidget|Merge locally"
msgstr "Merge local"
-msgid "mrWidget|Merge request approved"
-msgstr "Solicitud de merge request aprobada"
-
msgid "mrWidget|Merge request approved."
-msgstr ""
-
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
+msgstr "merge request aprobado."
msgid "mrWidget|Merged by"
msgstr "Merge realizado por"
msgid "mrWidget|No approval required"
-msgstr ""
+msgstr "No se requiere ninguna aprobación"
msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
+msgstr "No se requiere ninguna aprobación; todavía puede aprobar"
msgid "mrWidget|Open in Web IDE"
msgstr "Abrir en Web IDE"
@@ -13707,22 +16445,12 @@ msgstr "Actualizar ahora"
msgid "mrWidget|Refreshing now"
msgstr "Actualizar ahora"
-msgid "mrWidget|Remove your approval"
-msgstr "Eliminar su aprobación"
+msgid "mrWidget|Remove from merge train"
+msgstr ""
msgid "mrWidget|Request to merge"
msgstr "Solicitud de merge"
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] "Requiere una aprobación más"
-msgstr[1] "Requiere %d aprobaciones más"
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] "requiere 1 aprobación más de"
-msgstr[1] "requiere %d aprobaciones más de"
-
msgid "mrWidget|Resolve conflicts"
msgstr "Resolver conflictos"
@@ -13733,10 +16461,10 @@ msgid "mrWidget|Revert"
msgstr "Revertir"
msgid "mrWidget|Revert this merge request in a new merge request"
-msgstr ""
+msgstr "Revertir esta solicitud de merge en un nuevo merge request"
msgid "mrWidget|Revoke approval"
-msgstr ""
+msgstr "Revocar la aprobación"
msgid "mrWidget|Set by"
msgstr "Establecido por"
@@ -13757,22 +16485,22 @@ msgid "mrWidget|The source branch HEAD has recently changed. Please reload the p
msgstr ""
msgid "mrWidget|The source branch has been deleted"
-msgstr ""
+msgstr "Se ha eliminado el branch de origen"
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
-msgstr ""
+msgstr "la rama de origen está %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} en relación a la rama de destino"
msgid "mrWidget|The source branch is being deleted"
-msgstr ""
+msgstr "El branch de origen está siendo eliminado"
msgid "mrWidget|The source branch will be deleted"
-msgstr ""
+msgstr "El branch de origen será eliminado"
msgid "mrWidget|The source branch will not be deleted"
-msgstr ""
+msgstr "El branch de origen no será eliminado"
msgid "mrWidget|There are merge conflicts"
-msgstr ""
+msgstr "Hay conflictos de merge"
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr "Hay discusiones sin resolver. Por favor resuelve estas discusiones"
@@ -13790,13 +16518,13 @@ msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "Este proyecto está archivado, se ha deshabilitado el acceso de escritura"
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
-msgstr ""
+msgstr "No tiene permiso para editar este proyecto directamente. Por favor, haga un fork para hacer cambios."
msgid "mrWidget|You can delete the source branch now"
-msgstr ""
+msgstr "Puede eliminar el branch de origen ahora"
msgid "mrWidget|You can merge this merge request manually using the"
-msgstr ""
+msgstr "Puede hacer merge de este merge request manualmente usando el"
msgid "mrWidget|branch does not exist."
msgstr "la rama no existe."
@@ -13807,37 +16535,52 @@ msgstr "línea de comandos"
msgid "mrWidget|into"
msgstr "en"
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
+msgstr "se ejecutará el merge cuando la ejecución del pipeline se finalice con éxito"
+
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be greater than start date"
+msgstr "debe ser mayor que la fecha de inicio"
+
msgid "n/a"
msgstr "n/a"
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr "el intervalo debe estar comprendido entre 10 minutos y 1 mes"
+
msgid "new merge request"
msgstr "nueva solicitud de fusión"
+msgid "no contributions"
+msgstr "sin contribuciones"
+
msgid "none"
-msgstr ""
+msgstr "ninguno"
msgid "notification emails"
msgstr "correos electrónicos de notificación"
msgid "nounSeries|%{firstItem} and %{lastItem}"
-msgstr ""
+msgstr "%{firstItem}, y %{lastItem}"
msgid "nounSeries|%{item}, %{nextItem}"
-msgstr ""
+msgstr "%{item}, %{nextItem}"
msgid "nounSeries|%{item}, and %{lastItem}"
-msgstr ""
+msgstr "%{item}, y %{lastItem}"
msgid "or"
msgstr "o"
msgid "out of %d total test"
msgid_plural "out of %d total tests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "total de %d prueba"
+msgstr[1] "totales de %d pruebas"
msgid "parent"
msgid_plural "parents"
@@ -13852,8 +16595,8 @@ msgstr "token de acceso personal"
msgid "point"
msgid_plural "points"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "punto"
+msgstr[1] "puntos"
msgid "private"
msgstr "privado"
@@ -13862,7 +16605,7 @@ msgid "private key does not match certificate."
msgstr "la clave privada no coincide con el certificado."
msgid "processing"
-msgstr ""
+msgstr "procesando"
msgid "project"
msgid_plural "projects"
@@ -13888,7 +16631,7 @@ msgid "remove weight"
msgstr "eliminar el peso"
msgid "rendered diff"
-msgstr ""
+msgstr "diff renderizado"
msgid "reply"
msgid_plural "replies"
@@ -13896,43 +16639,46 @@ msgstr[0] "respuesta"
msgstr[1] "respuestas"
msgid "reset it."
-msgstr ""
+msgstr "restablecer."
msgid "score"
-msgstr ""
+msgstr "puntuación"
msgid "security Reports|There was an error creating the merge request"
-msgstr ""
+msgstr "Se ha producido un error al crear el merge request"
msgid "severity|Critical"
-msgstr ""
+msgstr "Crítica"
msgid "severity|High"
-msgstr ""
+msgstr "Alta"
msgid "severity|Info"
-msgstr ""
+msgstr "Info"
msgid "severity|Low"
-msgstr ""
+msgstr "Baja"
msgid "severity|Medium"
-msgstr ""
+msgstr "Media"
msgid "severity|Undefined"
-msgstr ""
+msgstr "Sin definir"
msgid "severity|Unknown"
-msgstr ""
+msgstr "Desconocida"
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
-msgstr ""
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
+msgstr "debe ser mayor o igual que %{access} el nivel de acceso heredado del grupo %{group_name}"
msgid "show less"
-msgstr ""
+msgstr "mostrar menos"
msgid "sign in"
-msgstr ""
+msgstr "iniciar sesión"
+
+msgid "sort:"
+msgstr "ordenar:"
msgid "source"
msgstr "origen"
@@ -13940,23 +16686,32 @@ msgstr "origen"
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr "La parte superior especificada no es parte del árbol"
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} actualizará la suma del tiempo empleado."
msgid "started"
msgstr "iniciado"
+msgid "started on %{milestone_start_date}"
+msgstr "comenzó en %{milestone_start_date}"
+
+msgid "starts on %{milestone_start_date}"
+msgstr "comienza en %{milestone_start_date}"
+
msgid "stuck"
-msgstr ""
+msgstr "bloqueado"
msgid "success"
-msgstr ""
+msgstr "éxito"
msgid "syntax is correct"
-msgstr ""
+msgstr "la sintaxis es correcta"
msgid "syntax is incorrect"
-msgstr ""
+msgstr "la sintaxis es incorrecta"
msgid "this document"
msgstr "este documento"
@@ -13965,7 +16720,7 @@ msgid "to help your contributors communicate effectively!"
msgstr "¡Para ayudar a sus colaboradores a comunicarse de manera efectiva!"
msgid "triggered"
-msgstr ""
+msgstr "disparado"
msgid "updated"
msgstr "actualizado"
@@ -13977,13 +16732,34 @@ msgid "uses Kubernetes clusters to deploy your code!"
msgstr "¡Utilizar los clústeres de Kubernetes para implementar tu código!"
msgid "verify ownership"
+msgstr "verificar el propietario"
+
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
msgstr ""
msgid "view it on GitLab"
msgstr "ver en GitLab"
msgid "view the blob"
-msgstr ""
+msgstr "ver el blob"
+
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr "Añadir un comentario o motivo para el descarte"
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr "Añadir comentario y descartar"
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr "Descartar vulnerabilidad"
+
+msgid "vulnerability|Undo dismiss"
+msgstr "Deshacer descartar"
+
+msgid "vulnerability|dismissed"
+msgstr "Descartado"
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "con %{additions} adiciones, %{deletions} eliminaciones."
diff --git a/locale/et_EE/gitlab.po b/locale/et_EE/gitlab.po
index 36f5074b8ff..0a15fa7ba8a 100644
--- a/locale/et_EE/gitlab.po
+++ b/locale/et_EE/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Estonian\n"
"Language: et_EE\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: et\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:38\n"
+"PO-Revision-Date: 2019-06-14 10:25\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,37 +1459,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1856,6 +2161,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/fil_PH/gitlab.po b/locale/fil_PH/gitlab.po
index c2139dcc495..40d0545c177 100644
--- a/locale/fil_PH/gitlab.po
+++ b/locale/fil_PH/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Filipino\n"
"Language: fil_PH\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: fil\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:38\n"
+"PO-Revision-Date: 2019-06-14 10:19\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,37 +1459,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1856,6 +2161,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/fr/gitlab.po b/locale/fr/gitlab.po
index 0843adc6d56..2c558704303 100644
--- a/locale/fr/gitlab.po
+++ b/locale/fr/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: French\n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: fr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:38\n"
+"PO-Revision-Date: 2019-06-14 10:26\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr " Statut"
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -32,8 +29,8 @@ msgstr " et"
msgid " degraded on %d point"
msgid_plural " degraded on %d points"
-msgstr[0] "dégradé sur %d point"
-msgstr[1] "dégradé sur %d points"
+msgstr[0] " dégradé sur %d point"
+msgstr[1] " dégradé sur %d points"
msgid " improved on %d point"
msgid_plural " improved on %d points"
@@ -67,6 +64,11 @@ msgstr[1] "%d commits de retard"
msgid "%d commits"
msgstr "%d commits"
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d exportateur"
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] "%d demande de fusion"
msgstr[1] "%d demandes de fusion"
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d métrique"
msgstr[1] "%d métriques"
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] "%d changement à valider"
@@ -131,11 +143,8 @@ msgstr "Discussion de %{authorsName}"
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} a créé %{commit_timeago}"
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr "%{counter_storage} (%{counter_repositories} dépôts, %{counter_build_artifacts} artefacts construits, %{counter_lfs_objects} LFS)"
-
-msgid "%{count} %{alerts}"
-msgstr "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
+msgstr ""
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] "%{count} commentaire en attente"
msgstr[1] "%{count} commentaires en attente"
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr "%{filePath} supprimé"
@@ -179,12 +194,24 @@ msgstr "%{gitlab_ci_yml} non trouvé dans ce commit"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "Les %{group_docs_link_start}groupes%{group_docs_link_end} vous permettent de gérer plusieurs projets et d’y collaborer. Les membres d’un groupe ont accès à tous ses projets."
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} sera supprimé ! Êtesâ€vous sûr ?"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} indisponible"
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr "%{lock_path} est verrouillé par l’utilisateur GitLab %{lock_user_id}"
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr "Avatar de %{name}"
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr "%{text} est disponible"
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr "Changements %{title}"
@@ -262,9 +310,29 @@ msgstr "%{usage_ping_link_start}En savoir plus%{usage_ping_link_end} sur les i
msgid "%{user_name} profile page"
msgstr "Profil de %{user_name}"
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr "(source externe)"
@@ -289,6 +357,9 @@ msgstr "- l’exécuteur est en pause et ne recevra pas de nouvelles tâches"
msgid "- show less"
msgstr "- en montrer moins"
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] "un ajout de %{type}"
@@ -305,14 +376,14 @@ msgstr[0] "un jour"
msgstr[1] "%d jours"
msgid "1 closed issue"
-msgid_plural "%d closed issues"
-msgstr[0] "un ticket fermé"
-msgstr[1] "%d tickets fermés"
+msgid_plural "%{issues} closed issues"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
-msgstr[0] "une demande de fusion fermée"
-msgstr[1] "%d demandes de fusion fermées"
+msgid_plural "%{merge_requests} closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 day"
msgstr ""
@@ -323,19 +394,19 @@ msgstr[0] "Un groupe"
msgstr[1] "%d groupes"
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
-msgstr[0] "une demande de fusion fusionnée"
-msgstr[1] "%d demandes de fusion fusionnées"
+msgid_plural "%{merge_requests} merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] "un ticket ouvert"
-msgstr[1] "%d tickets ouverts"
+msgstr[1] "%{issues} tickets ouverts"
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
-msgstr[0] "une demande de fusion ouverte"
-msgstr[1] "%d demandes de fusion ouvertes"
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 pipeline"
msgid_plural "%d pipelines"
@@ -355,15 +426,27 @@ msgstr[1] "%d utilisateurs"
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr "1ʳᵉ contribution !"
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr "Authentification à deux facteurs"
msgid "2FA enabled"
msgstr "2FA activé"
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr "Veuillez contacter votre administrateur·rice GitLab afin d’obtenir l’autorisation."
@@ -403,6 +489,9 @@ msgstr "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> ajoute
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> ajoutera « Par <a href=\"#\">johnsmith@example.com</a> » à tous les tickets et commentaires créés à l’origine par johnsmith@example.com. Par défaut, l’adresse de courriel ou le nom d’utilisateur est masqué pour garantir la confidentialité de l’utilisateur. Utilisez cette option si vous souhaitez afficher l’adresse de courriel complète."
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr "<strong>%{changedFilesLength} modifications non indexées</strong> et <strong>%{stagedFilesLength} modifications d’étape</strong>"
@@ -439,19 +528,19 @@ msgstr "Un site Hugo qui utilise Netlify comme intégration et livraison continu
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr "Un site Jekyll qui utilise Netlify comme intégration et livraison continues (CI/CD) au lieu de GitLab, mais en gardant toutes les autres fonctionnalités géniales de GitLab."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
+msgstr ""
+
msgid "A default branch cannot be chosen for an empty project."
msgstr "Une branche par défaut ne peut pas être choisie pour un projet vide."
msgid "A deleted user"
msgstr "Un utilisateur supprimé"
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr "Un membre de l’équipe de vérification des abus de GitLab examinera votre rapport dès que possible."
-
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr "Une personne avec un accès en écriture à la branche source a sélecti
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr "À propos de GitLab"
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr "Accès à « %{classification_label} » non autorisé"
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr "Compte"
msgid "Account and limit"
msgstr "Limitations du compte"
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr "Action à réaliser lors de la réception d’une alerte."
@@ -568,6 +672,9 @@ msgstr "Ajouter une grappe de serveurs Kubernetes"
msgid "Add README"
msgstr "Ajouter un README"
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr "Ajouter une liste à puces"
@@ -589,11 +696,17 @@ msgstr "Ajouter un tableau"
msgid "Add a task list"
msgstr "Ajouter une liste de tâches"
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Ajouter un texte apparaissant dans toutes communications par courriel (%{character_limit} caractères maximum)"
-msgid "Add approver(s)"
-msgstr "Ajouter un ou des approbateurs"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
+msgstr ""
msgid "Add approvers"
msgstr "Ajouter des approbateurs"
@@ -601,9 +714,15 @@ msgstr "Ajouter des approbateurs"
msgid "Add bold text"
msgstr "Ajouter du texte en gras"
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr "Ajouter un commentaire"
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "Ajouter un enâ€tête et un pied de page aux courriels. Veuillez noter que les paramètres de couleur seront appliqués uniquement à l’intérieur de l’interface de l’application"
@@ -613,6 +732,9 @@ msgstr "Ajouter un commentaire à l’image"
msgid "Add italic text"
msgstr "Ajouter du texte en italique"
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr "Ajouter une licence"
@@ -625,9 +747,18 @@ msgstr "Ajouter une nouvelle application"
msgid "Add new directory"
msgstr "Ajouter un nouveau dossier"
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr "Ajouter une réaction"
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr "Ajouter au projet"
@@ -640,22 +771,34 @@ msgstr "Ajouter à la liste « à faire »"
msgid "Add user(s) to the group:"
msgstr "Ajouter un ou des utilisateurs au groupe :"
-msgid "Add users or groups who are allowed to approve every merge request"
-msgstr "Ajouter des utilisateurs ou des groupes autorisés à approuver chaque demande de fusion"
-
msgid "Add users to group"
msgstr "Ajouter des utilisateurs au groupe"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
+msgstr ""
+
msgid "Added at"
msgstr "Ajouté à"
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr "L’ajout de nouvelles applications est désactivé dans votre instance GitLab. Veuillez contacter votre administrateur GitLab pour en obtenir la permission."
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr "Texte supplémentaire"
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr "Vue administrateur"
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr "Vous êtes sur le point de supprimer définitivement l’utilisateur %{username}. Les tickets, demandes de fusion et les groupes qui leur sont liés seront transférés à un « utilisateur fantôme » du système. Pour éviter toute perte de données, envisagez plutôt d’utiliser la fonctionnalité « %{strong_start}bloquer l’utilisateur%{strong_end} ». L’action « %{strong_start}supprimer l’utilisateur%{strong_end} » ne peut être annulée ni faire l’objet d’une restauration."
@@ -688,6 +834,9 @@ msgstr "L’arrêt des tâches a échoué"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "Vous êtes sur le point d’arrêter toutes les tâches. Toutes les tâches en cours seront interrompues."
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr "Vous êtes sur le point de supprimer définitivement le projet %{projectName}, son dépôt et toutes les ressources qui lui sont liées, y compris les tickets, les demandes de fusion, etc. Après sa confirmation par un clic sur « %{strong_start}supprimer le projet%{strong_end} », l’action ne peut être annulée ni faire l’objet d’une restauration."
@@ -802,6 +951,9 @@ msgstr "Paramètres avancés"
msgid "After a successful password update you will be redirected to login screen."
msgstr "Après modification de votre mot de passe, vous serez redirigé vers l’écran de connexion."
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "Alerte"
@@ -819,15 +971,24 @@ msgstr "Tous les membres"
msgid "All changes are committed"
msgstr "Toutes les modifications sont validées"
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Toutes les fonctionnalités sont activées pour les projets vierges, à partir de modèles ou lors de l’importation, mais vous pouvez les désactiver ultérieurement dans les paramètres du projet."
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr "Vous pouvez également utiliser un %{personal_access_token_link}. Lorsqu
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr "Durée (en heures) durant laquelle les utilisateurs sont autorisés à outrepasser la configuration de l’authentification à double facteur obligatoire"
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr "Une paire de clefs SSH sera automatiquement générée après soumission du formulaire. Pour plus d’informations, veuillez vous référer à la documentation."
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr "Une application appelée %{link_to_client} demande l’accès à votre compte GitLab."
@@ -936,12 +1094,15 @@ msgstr "Une erreur s’est produite lors de la prévisualisation du blob"
msgid "An error occurred when toggling the notification subscription"
msgstr "Une erreur s’est produite lors de l’activation ou la désactivation de l’abonnement aux notifications"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "Une erreur est survenue lors de la mise à jour du poids du ticket"
-msgid "An error occurred while adding approver"
-msgstr "Une erreur s’est produite lors de l’ajout de l’approba·teur·trice"
-
msgid "An error occurred while deleting the approvers group"
msgstr ""
@@ -963,21 +1124,36 @@ msgstr "Une erreur s’est produite lors du rejet de la mise en avant de la fonc
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr "Une erreur s’est produite lors de la prévisualisation markdown"
msgid "An error occurred while fetching pending comments"
msgstr "Une erreur est survenue lors de la récupération des commentaires en attente"
+msgid "An error occurred while fetching projects autocomplete."
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "Une erreur s’est produite lors de la récupération des données de la barre latérale"
-msgid "An error occurred while fetching stages."
-msgstr "Une erreur est survenue lors de la récupération des étapes."
-
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr "Une erreur est survenue pendant la récupération du journal de la tâche."
@@ -993,6 +1169,9 @@ msgstr "Une erreur est survenue pendant la récupération du pipeline."
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr "Une erreur s’est produite lors de la récupération des projets"
@@ -1026,8 +1205,11 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr "Une erreur s’est produite lors de la requête."
-msgid "An error occurred while removing approver"
-msgstr "Une erreur est survenue lors de la suppression de l’approba·teur·trice"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
+msgstr ""
msgid "An error occurred while removing epics."
msgstr ""
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr "Tout"
msgid "Any Label"
msgstr "Toute étiquette"
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr "Apparence"
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr "Application"
@@ -1158,6 +1355,9 @@ msgstr "Identifiant de l’application"
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr "avr."
@@ -1253,6 +1459,18 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
+msgid "Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr ""
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to delete this list?"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Êtesâ€vous sûr·e de vouloir supprimer ce pipeline programmé ?"
@@ -1274,18 +1492,6 @@ msgstr "Êtesâ€vous sûr de vouloir générer une nouvelle paire de clefs ? V
msgid "Are you sure you want to remove %{group_name}?"
msgstr "Voulezâ€vous vraiment supprimer %{group_name} ?"
-msgid "Are you sure you want to remove approver %{name}"
-msgstr "Êtesâ€vous sûr(e) de vouloir supprimer %{name} des approbateurs"
-
-msgid "Are you sure you want to remove approver %{name}?"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}"
-msgstr "Êtesâ€vous sûr(e) de vouloir supprimer le groupe « %{name} »"
-
-msgid "Are you sure you want to remove group %{name}?"
-msgstr ""
-
msgid "Are you sure you want to remove the attachment?"
msgstr ""
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr "Êtesâ€vous sûr·e de vouloir réinitialiser le jeton de bilan de santé ?"
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr "Êtesâ€vous sûr(e) de vouloir arrêter cet environnement ?"
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr "Êtesâ€vous certain(e) ?"
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr "Identifiant de l’artefact"
msgid "Artifacts"
msgstr "Artéfacts"
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr "Croissant"
@@ -1331,6 +1564,9 @@ msgstr "URL du service consommateur d’assertion"
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr "Attribuer une couleur personnalisée comme #FF0000"
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr "Assigner à"
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr "Tickets assignés"
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Attachez un fichier par glisserâ€déposer ou %{upload_link}"
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr "Événements d’audit"
@@ -1463,13 +1713,22 @@ msgstr "Apprenezâ€en davantage en consultant la %{link_to_documentation}"
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr "Le pipeline Auto DevOps a été activé et sera utilisé si aucun autre fichier de configuration d’intégration continue n’est trouvé. %{more_information_link}"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
msgid "Automatically marked as default internal user"
msgstr "Marqué automatiquement comme utilisateur interne par défaut"
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatically resolved"
msgstr ""
-msgid "Automatically resolved"
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
msgstr ""
msgid "Available"
@@ -1583,6 +1842,30 @@ msgstr "Vos badges numériques"
msgid "Badges|e.g. %{exampleUrl}"
msgstr "p. ex. %{exampleUrl}"
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr "Supprimer tous les commentaires en attente"
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr "Blog"
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr "Tableaux"
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "La branche %{branchName} n’a pas été trouvée dans le dépôt de ce projet."
@@ -1706,6 +2008,9 @@ msgstr "Ce nom de branche existe déjà"
msgid "Branch name"
msgstr "Nom de la branche"
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Rechercher les branches"
@@ -1856,6 +2161,21 @@ msgstr "Parcourir les fichiers"
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "par"
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr "Impossible de trouver le dernier commit (HEAD) pour cette branche"
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr "Impossible de modifier la grappe de serveurs gérée par Kubernetes"
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr "Modifier le poids"
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr "Changer de modèle"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "Modifiez cette valeur pour influencer la fréquence d’interrogation de l’interface utilisateur GitLab pour les mises à jour."
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "Picorer dans la branche"
@@ -2042,6 +2392,12 @@ msgstr "Les modifications sont affichées comme si la révision <b>source</b> é
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr "Statistiques"
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr "Vérification de la disponibilité du nom de branche…"
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr "Picorer ce commit"
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr "Choisir un modèle…"
@@ -2120,7 +2482,7 @@ msgstr "Choisissez quels dépôts vous voulez connecter pour exécuter des pipel
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr "Choisissez les fragments que vous souhaitez synchroniser avec ce nœud secondaire."
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr "ignoré"
msgid "CiStatus|running"
msgstr "en cours"
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr "Nom de la variable"
msgid "CiVariables|Input variable value"
msgstr "Valeur de la variable"
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr "Supprimer cette variable"
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr "Effacer la recherche"
msgid "Clear search input"
msgstr "Vider le champ de recherche"
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr "Cliquez sur n’importe quel <strong>nom de projet</strong> dans la liste des projets ciâ€dessous pour naviguer jusqu’au jalon du projet."
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr "Cliquez sur le bouton <strong>Télécharger</strong> et attendez que le téléchargement soit terminé."
@@ -2312,6 +2701,9 @@ msgstr "Clore l’épopée"
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr "Fermé(e)"
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} a été installé avec succès sur votre grappe de serveurs Kubernetes"
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr "Ajouter une intégration d’une grappe de serveurs Kubernetes"
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr "Une grappe de serveurs Kubernetes ajoutée à votre groupe la rendra automatiquement disponible pour tous vos projets. Vous pourrez utiliser les applications de revue de code, déployer vos applications et exécuter facilement vos pipelines avec tous les projets utilisant la même grappe de serveurs."
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr "Ajouter une intégration à votre groupe rendra la grappe de serveurs disponible pour l’ensemble de vos projets."
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Options avancées concernant l’intégration de cette grappe de serveurs Kubernetes"
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr "Applications"
@@ -2477,6 +2890,9 @@ msgstr "Exécuteur GitLab"
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Projet Google Cloud Platform"
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr "Ingress vous permet de router les requêtes vers des services en fonction de l’hôte ou du chemin de la requête, en centralisant un certain nombre de services vers un seul point d’entrée."
-msgid "ClusterIntegration|Install"
-msgstr "Installer"
-
-msgid "ClusterIntegration|Installed"
-msgstr "Installé"
-
-msgid "ClusterIntegration|Installing"
-msgstr "En cours d’installation"
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr "Nom de domaine Knative :"
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr "En savoir plus sur Kubernetes"
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr "En savoir plus sur les grappes de serveurs Kubernetes de groupe"
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr "Type de machine"
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr "Assurezâ€vous que votre compte %{link_to_requirements} pour créer des grappes de serveurs Kubernetes"
-msgid "ClusterIntegration|Manage"
-msgstr "Gérer"
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr "Gérez votre grappe de serveurs Kubernetes en visitant %{link_gke}"
@@ -2669,7 +3079,7 @@ msgstr "Vous pouvez remplacer ceci par un nom d’hôte personnalisé. Auquel ca
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "La demande de lancement de l’installation a échoué"
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,12 +3133,36 @@ msgstr "Une erreur s’est produite lors de la création de votre grappe de serv
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "Une erreur s’est produite lors de l’installation de %{title}"
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
+msgstr ""
+
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
+msgstr ""
+
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
+msgstr ""
+
msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
+msgstr ""
+
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr "Ce compte doit disposer des autorisations pour créer une grappe de serveurs Kubernetes dans le %{link_to_container_project} spécifié ciâ€dessous"
@@ -2741,22 +3175,10 @@ msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "Activer/désactiver la grappe de serveurs Kubernetes"
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
-msgstr ""
-
-msgid "ClusterIntegration|Updating"
-msgstr ""
-
-msgid "ClusterIntegration|Upgrade"
-msgstr ""
-
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
-msgstr ""
-
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr "Nous n’avons pu vérifier que la facturation de l’un de vos projets
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "Avec une grappe de serveurs Kubernetes associée à ce projet, vous pouvez utiliser des applications de revue, déployer vos applications, exécuter vos pipelines, et bien plus encore."
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr "Vous devez d’abord installer Helm Tiller avant d’installer les applications ciâ€dessous"
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "Votre compte doit disposer de %{link_to_kubernetes_engine}"
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr "Zone"
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr "Masquer la barre latérale"
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr "Commenter"
@@ -2849,6 +3283,9 @@ msgstr "Commenter et marquer la discussion comme non résolue"
msgid "Comment form position"
msgstr "Position du formulaire de commentaire"
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr "Commentaires"
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr "Configurer les délais d’expiration de Gitaly."
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr "Configurer le traçage"
@@ -2995,9 +3435,15 @@ msgstr "Configurez la manière dont une personne crée un nouveau compte."
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr "Connecter"
@@ -3010,9 +3456,15 @@ msgstr "Se connecter à des dépôts à partir de GitHub"
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr "Connectez vos dépôts externes afin que les pipelines d’intégration et de livraison continues (CI/CD) s’exécutent lors de nouveaux commits. Un projet GitLab sera créé avec uniquement les fonctionnalités CI/CD activées."
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr "Connexion en cours…"
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr "Avec le registre de conteneur Docker intégré à GitLab, chaque projet
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr "Vous pouvez également utiliser un %{deploy_token} pour un accès en lecture seule aux images du registre."
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr "Commits sur %{branch_name}, à l’exclusion des commits de fusion (limi
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr "Veuillez patienter, cette page va être automatiquement actualisée."
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr "Contrôle l’affichage des offres tierces."
@@ -3130,6 +3588,9 @@ msgstr "Contrôle la concurrence maximale des remplacements de dépôt pour ce n
msgid "ConvDev Index"
msgstr "Index ConvDev"
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr "Copier l’URL SSH de clonage"
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr "Copier la clef SSH publique dans le presseâ€papiers"
-
msgid "Copy URL to clipboard"
msgstr "Copier l’URL dans le presseâ€papiers"
@@ -3166,6 +3624,12 @@ msgstr "Copier le condensat SHA du commit"
msgid "Copy file path to clipboard"
msgstr "Copier le chemin d’accès du fichier dans le presseâ€papiers"
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr "Copier le lien"
@@ -3175,6 +3639,9 @@ msgstr "Copier la référence dans le presseâ€papiers"
msgid "Copy secret to clipboard"
msgstr "Copier le secret dans le presseâ€papiers"
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr "Copier dans le presseâ€papiers"
@@ -3184,9 +3651,15 @@ msgstr "Copier le jeton dans le presseâ€papiers"
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr "Créer une nouvelle branche"
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr "Créer un nouveau ticket"
@@ -3295,6 +3777,12 @@ msgstr "Créer une étiquette de projet"
msgid "Create your first page"
msgstr "Créer votre première page"
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr "Étiquette"
@@ -3310,12 +3798,27 @@ msgstr "Créé à"
msgid "Created by me"
msgstr "Créé par moi"
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr "Créé le"
msgid "Created on:"
msgstr "Créé le :"
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr "Création de l’épopée en cours"
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr "NÅ“ud actuel"
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr "Profil"
@@ -3412,15 +3918,39 @@ msgstr "Tous"
msgid "DashboardProjects|Personal"
msgstr "Personnels"
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr "Sélecteur de date"
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr "Déboguer"
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr "Par défaut : importer directement l’adresse de courriel ou le nom d’utilisateur provenant de Google Code"
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr "Supprimé"
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr "Refuser"
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "Déploiement"
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr "Désactiver les exécuteurs de groupe"
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr "Rejeter"
@@ -3783,6 +4388,12 @@ msgstr "Abandonner le brouillon"
msgid "Discard review"
msgstr "Rejeter la revue de code"
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr "Rejeter la promotion de la demande de fusion"
msgid "Dismiss trial promotion"
msgstr "Rejeter l’offre promotionnelle"
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr "Voulezâ€vous personnaliser la manière dont les adresses de courriel et les noms d’utilisateurs issus de Google Code sont importés dans GitLab ?"
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr "Documentation des principaux fournisseurs d’identité"
msgid "Domain"
msgstr "Domaine"
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr "Ne plus afficher"
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr "Effectué"
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr "Modifier l’étiquette"
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "Éditer le pipeline programmé %{id}"
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr "Elasticsearch"
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr "Intégration d’Elasticsearch. Elasticsearch AWS IAM."
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr "Correctif par courriel"
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr "Courriels"
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr "Embarquer"
@@ -4002,6 +4673,9 @@ msgstr "Activer l’authentification SAML pour ce groupe"
msgid "Enable Sentry for error reporting and logging."
msgstr "Activer Sentry pour les rapports d’erreurs et la journalisation."
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr "Activer et configurer les métriques InfluxDB."
@@ -4038,9 +4712,6 @@ msgstr "Activer reCAPTCHA ou Akismet et définir des limites d’adresse IP."
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr "Activer la barre de performance pour un groupe donné."
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr "Se termine à (UTC)"
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr "Entrez l’URL de votre serveur Bitbucket et votre jeton d’accès personnel ciâ€dessous"
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr "Entrez la description du problème"
@@ -4089,7 +4766,10 @@ msgstr "Entrez la description de la demande de fusion"
msgid "Enter the merge request title"
msgstr "Entrez l’intitulé de la demande de fusion"
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr "Environnements"
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "Une erreur s’est produite lors de la récupération des environnements."
@@ -4239,18 +4943,51 @@ msgstr "Feuille de route des épopées"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr "Les épopées vous permettent de gérer votre portefeuille de projets plus efficacement et avec moins d’efforts"
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr "Comment puisâ€je résoudre ceci ?"
msgid "Epics|More information"
msgstr "En savoir plus"
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr "Ces dates affectent la manière dont vos épopées apparaissent sur la feuille de route. Les dates des jalons proviennent des jalons attribués aux tickets de l’épopée. Vous pouvez également définir des dates fixes ou les supprimer complètement."
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr "Afin de planifier la date de %{epicDateType} de votre épopée en fonction des jalons, attribuez un jalon avec une date de %{epicDateType} à tous les tickets concernant l’épopée."
@@ -4287,9 +5024,15 @@ msgstr "Erreur lors de la récupération des étiquettes."
msgid "Error fetching network graph."
msgstr "Erreur lors de la récupération du graphique du réseau."
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr "Erreur lors de la récupération des refs"
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr "Erreur lors de la récupération des données d’utilisation."
@@ -4299,6 +5042,12 @@ msgstr "Erreur lors du chargement des données de branche. Veuillez réessayer."
msgid "Error loading branches."
msgstr "Erreur lors du chargement des branches."
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr "Erreur lors du chargement du dernier commit."
@@ -4308,6 +5057,9 @@ msgstr "Erreur lors du chargement de l’aperçu du Markdown"
msgid "Error loading merge requests."
msgstr "Erreur lors du chargement des demandes de fusion."
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr "Erreur lors du chargement des données du projet. Veuillez réessayer."
@@ -4317,6 +5069,12 @@ msgstr "Erreur lors du chargement des types de modèles."
msgid "Error loading template."
msgstr "Erreur lors du chargement du modèle."
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr "Une erreur s’est produite lors de l’activation ou de la désactivation de l’abonnement aux notifications"
@@ -4350,9 +5108,15 @@ msgstr "Erreur lors de la mise à jour du statut de tâche à faire."
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr "Erreur lors du chargement de la demande de fusion. Veuillez réessayer."
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr "Étiquette de classification"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "Lorsqu’aucune étiquette de classification n’est définie, l’étiquette par défaut « %{default_label} » sera utilisée."
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr "Facebook"
@@ -4545,27 +5333,60 @@ msgstr "Échec"
msgid "Failed Jobs"
msgstr "Tâches ayant échoué"
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr "Échec du changement de propriétaire"
msgid "Failed to check related branches."
msgstr "Échec de la vérification des branches liées."
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr "Échec du déploiement sur"
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr "Impossible de charger la liste des émojis."
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr "Impossible de supprimer le ticket du tableau, veuillez réessayer."
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,18 +5423,30 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr "Échec de la signature via authentification par carte à puce"
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr "Échec de la mise à jour du ticket. Veuillez réessayer."
+msgid "Failed to update tag!"
+msgstr ""
+
+msgid "Failed to update."
+msgstr ""
+
+msgid "Failed to upgrade."
+msgstr ""
+
msgid "Failed to upload object map file"
msgstr ""
msgid "Failure"
msgstr "Échec"
-msgid "Fast-forward merge"
-msgstr ""
-
msgid "Fast-forward merge without a merge commit"
msgstr ""
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr "Indicateurs de fonctionnalités"
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,8 +5528,8 @@ msgstr "Inactif"
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
-msgstr "Installez une %{docs_link_start}bibliothèque cliente compatible%{docs_link_end} et spécifiez l’URL de l’API, le nom de l’application et l’identifiant d’instance lors de la configuration."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
+msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr "Identifiant d’instance"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr "Plus d’informations"
-
msgid "FeatureFlags|Name"
msgstr "Nom"
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr "Fichiers"
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr "Renseignez les champs ciâ€dessous, activez <strong>%{enable_label}</strong> et appuyez sur <strong>%{save_changes}</strong>"
@@ -4826,6 +5674,9 @@ msgstr "Cherchez le fichier <code>Takeout/Google Code Project Hosting/GoogleC
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr "Empreintes"
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr "Terminer la revue de code"
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr "Terminé"
@@ -4859,6 +5713,12 @@ msgstr "Date de début fixe"
msgid "Fixed:"
msgstr "Fixée :"
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr "Courriel de FogBugz"
@@ -4904,6 +5764,15 @@ msgstr "Pour les projets privés, tout membre (invité ou supérieur) peut affic
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr "Pour les projets publics, tout le monde peut afficher des pipelines et accéder aux détails des tâches (journaux de sortie et artefacts)"
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Divergence issue de"
@@ -4913,6 +5782,9 @@ msgstr "Divergence issue de %{project_name} (supprimé)"
msgid "Forking in progress"
msgstr "Divergence en cours"
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr "Erreurs trouvées dans votre fichier .gitlab-ci.yml :"
msgid "Free Trial of GitLab.com Gold"
msgstr "Essai gratuit de GitLab.com Gold"
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr "À partir des jalons :"
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr "À partir de l’affichage des détails de la grappe de serveurs Kubernetes, installez un exécuteur à partir de la liste des applications"
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr "Clefs GPG"
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr "Synchro en échec — %{error}"
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr "Git"
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr "URL du dépôt Git"
msgid "Git revision"
msgstr "Révision de Git"
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr "Stratégie Git pour les pipelines"
@@ -5462,6 +6355,9 @@ msgstr "Importation depuis Gitea"
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr "Retour"
@@ -5480,9 +6376,18 @@ msgstr "Aller vers"
msgid "Go to %{link_to_google_takeout}."
msgstr "Consultez le site de %{link_to_google_takeout}."
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr "Importation depuis Google Code"
@@ -5558,6 +6463,9 @@ msgstr "Nom du groupe"
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr "Groupe : %{group_name}"
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr "Depuis %{dateWord}"
@@ -5594,13 +6505,16 @@ msgstr "Jusqu’au %{dateWord}"
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr "supprimer le partage avec verrou de groupe pour %{ancestor_group_name}"
msgid "Groups"
msgstr "Groupes"
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr "Les groupes peuvent également être imbriqués en créant des %{subgroup_docs_link_start}sousâ€groupes%{subgroup_docs_link_end}."
@@ -5780,6 +6703,9 @@ msgstr "Aucun groupe ni projet ne correspond à votre recherche"
msgid "GroupsTree|Search by name"
msgstr "Rechercher par nom"
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr "Récupérer les adresses de courriel des utilisateurs"
@@ -5807,6 +6733,9 @@ msgstr "Aucun problème détecté"
msgid "HealthCheck|Unhealthy"
msgstr "En mauvaise santé"
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr "Aide"
@@ -5816,12 +6745,15 @@ msgstr "Page d’aide"
msgid "Help page text and support page url."
msgstr "Texte de la page d’aide et URL de la page de support."
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
-msgstr "Voici la clef SSH publique qui doit être ajoutée sur le serveur distant. Pour plus d’informations, veuillez vous référer à la documentation."
+msgid "Hide archived projects"
+msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr "Masquer la saisie manuelle des clefs d’hôtes"
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr "Masquer la charge utile"
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Masquer la valeur"
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr "Historique"
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr "Maintenance démarrée avec succès"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr "J’accepte les %{terms_link}"
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr "Conditions générales d’utilisation et politique de confidentialité"
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr "Identifiant"
@@ -5938,11 +6891,20 @@ msgstr "Si activé"
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr "Si activé, l’accès aux projets sera validé sur un service externe en se basant sur leurs étiquettes de classification respectives."
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr "Si vous utilisez GitHub, vous verrez les statuts des pipelines sur GitHub pour vos commits et demandes d’intégration (pull requests). %{more_info_link}"
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
-msgstr "Si votre dépôt HTTP n’est pas accessible publiquement, ajoutez des informations d’authentification à l’URL : <code>https://utilisateur:mot_de_passe@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
+msgstr ""
msgid "ImageDiffViewer|2-up"
msgstr "côte à côte"
@@ -6022,6 +6984,12 @@ msgstr "Importer des dépôts à partir de GitHub"
msgid "Import repository"
msgstr "Importer un dépôt"
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr "Connecter des dépôts provenant de"
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr "Améliorez le tableau des tickets avec Gitlab Entreprise Edition."
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr "Projet incompatible"
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr "Indique si l’exécuteur peut choisir des tâches sans étiquettes (tags)"
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr "En ligne"
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr "Installer GitLab Runner"
msgid "Install Runner on Kubernetes"
msgstr "Installez un exécuteur sur Kubernetes"
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] "Instance"
@@ -6174,18 +7178,42 @@ msgstr "Introduction à l’analyseur de cycle"
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr "Inviter"
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr "Événements du ticket"
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr "Tableau"
@@ -6300,6 +7340,48 @@ msgstr "janv."
msgid "January"
msgstr "janvier"
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr "Tâche"
@@ -6396,6 +7478,12 @@ msgstr "juill."
msgid "July"
msgstr "juillet"
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr "juin"
@@ -6405,6 +7493,9 @@ msgstr "juin"
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -6429,12 +7520,18 @@ msgstr "La grappe de serveurs Kubernetes a été mise à jour avec succès."
msgid "Kubernetes configured"
msgstr "Kubernetes configuré"
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr "L’intégration du service Kubernetes est obsolète. %{deprecated_message_content} vos grappes de serveurs Kubernetes en utilisant la nouvelle page <a href=\"%{url}\"/>Clusters Kubernetes</a>"
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr "LFS"
@@ -6447,6 +7544,9 @@ msgstr "Désactivé"
msgid "LFSStatus|Enabled"
msgstr "Activé"
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr "Étiquette"
@@ -6495,6 +7595,9 @@ msgstr "Promouvoir l’étiquette"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr "La promotion de l’étiquette « %{labelTitle} » va la rendre disponible pour tous les projets du groupe %{groupName}. Les étiquettes de projet ayant le même intitulé seront fusionnées. Cette action est irréversible."
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] "Les %d derniers jours"
msgid "Last Pipeline"
msgstr "Dernier pipeline"
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr "Dernière mise à jour"
msgid "Last updated"
msgstr "Dernière mise à jour"
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr "Vous avez poussé sur"
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr "En savoir plus sur Kubernetes"
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr "Apprenezâ€en plus dans la"
@@ -6602,6 +7726,12 @@ msgstr "Quitter le projet"
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr "Laisser les options « type de fichier » et « mode de livraison » à leurs valeurs par défaut."
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr "Licence"
@@ -6677,6 +7807,9 @@ msgstr "URL"
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr "Vous êtes sur le point de supprimer la licence, %{name}, de ce projet."
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] "Affichage limité à %d événement maximum"
msgstr[1] "Affichage limité à %d événements maximum"
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -6721,6 +7857,9 @@ msgstr "Prévisualisation"
msgid "Loading contribution stats for group members"
msgstr "Chargement des statistiques de contribution des membres du groupe"
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr "Chargement de l’EDI de GitLab…"
@@ -6742,6 +7881,9 @@ msgstr "Verrouiller %{issuableDisplayName}"
msgid "Lock not found"
msgstr "Verrou non trouvé"
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr "Verrouiller ce·t·te %{issuableDisplayName} ? Seuls les <strong>membres du projet</strong> seront en mesure de commenter."
@@ -6760,6 +7902,9 @@ msgstr "Verrouillé aux projets en cours"
msgid "Locks give the ability to lock specific file or folder."
msgstr "Les verrous permettent de verrouiller un fichier ou un dossier spécifique."
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr "Se connecter avec une carte à puce"
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr "Rendez chaque membre de votre équipe plus productif, quel que soit l’endroit où il se situe. GitLab Geo crée des miroirs en lecture seule de votre instance GitLab afin que vous puissiez réduire le temps nécessaire pour cloner et récupérer de gros dépôts."
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr "Assurezâ€vous d’être connecté avec le compte propriétaire des projets que vous souhaitez importer."
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr "mars"
msgid "March"
msgstr "mars"
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr "Marquer comme fait"
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr "Markdown activé"
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr "Métadonnées Maven"
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr "Durée maximale d’exécution de la tâche"
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr "Demande de fusion"
@@ -6928,15 +8106,9 @@ msgstr "Demandes de fusion"
msgid "Merge Requests created"
msgstr "Demandes de fusion créées"
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr "Événements de fusion"
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr "Demande de fusion"
@@ -6970,6 +8136,30 @@ msgstr "Les demandes de fusion permettent de proposer les modifications que vous
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr "Résoudre cette discussion avec un nouveau ticket"
msgid "MergeRequests|Saving the comment failed"
msgstr "L’enregistrement du commentaire a échoué"
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr "Activer/désactiver les commentaires pour ce fichier"
@@ -7033,8 +8229,8 @@ msgstr "%{paragraphStart}a changé la description %{descriptionChangedTimes} f
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
-msgstr "Filtrer les fichiers"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
+msgstr ""
msgid "MergeRequest|No files found"
msgstr "Aucun fichier trouvé"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr "Messages"
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr "Métriques"
@@ -7063,6 +8265,9 @@ msgstr "Statistiques et rapports"
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "Consultez la documentation sur l’intégration et la livraison continues (CI/CD) concernant le déploiement dans un environnement"
@@ -7102,9 +8307,6 @@ msgstr "Nouvelle métrique"
msgid "Metrics|No deployed environments"
msgstr "Aucun environnement déployé"
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr "Libellé de l’axe Y"
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr "p. ex., débit"
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr "Vous êtes sur le point de supprimer définitivement le jalon %{mileston
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr "Vous êtes sur le point de supprimer définitivement le jalon %{milestoneTitle}. Ce jalon n’est actuellement référencé par aucun ticket ni aucune demande de fusion."
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr "<p>%{milestonePromotion}</p> %{finalWarning}"
-
msgid "Milestones|Delete milestone"
msgstr "Supprimer le jalon"
@@ -7198,8 +8409,8 @@ msgstr "Promouvoir %{milestoneTitle} en tant que jalon de groupe ?"
msgid "Milestones|Promote Milestone"
msgstr "Promouvoir le jalon"
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
-msgstr "Promouvoir %{milestone} le rendra disponible pour tous les projets du groupe %{groupName}. Les jalons des projets portant le même nom seront fusionnés."
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
+msgstr ""
msgid "Milestones|This action cannot be reversed."
msgstr "Cette action ne peut pas être annulée."
@@ -7207,6 +8418,15 @@ msgstr "Cette action ne peut pas être annulée."
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr "Créer un miroir de dépôt"
@@ -7228,6 +8448,18 @@ msgstr "Dépôts miroir"
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "ajouter une clef SSH"
@@ -7288,6 +8520,24 @@ msgstr "Déplacer"
msgid "Move issue"
msgstr "Déplacer le ticket"
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr "Tableaux de tickets multiples"
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr "Nom"
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr "Nommez la nouvelle étiquette"
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr "Nouvelle épopée"
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr "Nouveau fichier"
@@ -7419,6 +8675,9 @@ msgstr "Nouvelle demande de fusion"
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr "De nouveaux pipelines annuleront les anciens pipelines en attente sur la même branche"
@@ -7449,6 +8708,12 @@ msgstr "Nouveau…"
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr "Non"
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr "Aucune étiquette"
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr "Aucune branche trouvée"
@@ -7479,6 +8753,9 @@ msgstr "Aucune connexion n’a pu être établie avec un serveur Gitaly, veuille
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr "Aucune image de conteneur stockée pour ce projet. Ajoutezâ€en une en suivant les instructions ciâ€dessous."
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr "Aucune contribution n’a été trouvée"
@@ -7503,6 +8780,9 @@ msgstr "Aucun fichier sélectionné"
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr "Aucun fichier trouvé."
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr "Aucune demande de fusion pour la période sélectionnée."
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr "Aucune autre étiquette avec un tel nom ou une telle description"
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr "Non, importer directement les adresses de courriel et les noms d’utilisateur existants."
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr "NÅ“uds"
@@ -7617,6 +8903,9 @@ msgstr "Remarque : Envisagez de demander à votre administrateur ou administrat
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr "Remarque : Envisagez de demander à votre administra·teur·trice GitLab de configurer %{github_integration_link}, ce qui vous permettra de vous connecter via GitHub et d’importer des dépôts sans générer de jeton d’accès personnel."
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "Souhaitezâ€vous réellement annuler la création de ce commentaire ?"
@@ -7632,6 +8921,12 @@ msgstr "Afficher uniquement les commentaires"
msgid "Notes|Show history only"
msgstr "Afficher uniquement l’historique"
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr "Événement de notifications"
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "Clore le ticket"
@@ -7695,6 +8993,9 @@ msgstr "Participer"
msgid "NotificationLevel|Watch"
msgstr "Surveiller"
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr "Notifications"
@@ -7710,6 +9011,12 @@ msgstr "nov."
msgid "November"
msgstr "novembre"
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr "OK"
@@ -7725,8 +9032,14 @@ msgstr "octobre"
msgid "OfSearchInADropdown|Filter"
msgstr "Filtre"
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
-msgstr "Une fois importés, les dépôts peuvent être mis en miroir via SSH. Voir %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
+msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
msgstr ""
@@ -7748,13 +9061,13 @@ msgstr "Un ou plusieurs de vos projets Bitbucket ne peuvent être importés dire
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "Un ou plusieurs de vos projets Google Code ne peuvent être importés directement dans GitLab parce qu’ils utilisent Subversion ou Mercurial comme gestionnaire de versions au lieu de Git."
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
+msgstr ""
+
msgid "Only admins"
msgstr "Seulement les administrateurs"
-msgid "Only allow merge requests to be merged if all discussions are resolved"
-msgstr ""
-
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr "Seuls les membres du projet peuvent commenter."
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr "Ouh là, êtesâ€vous sûr(e) ?"
@@ -7817,6 +9133,12 @@ msgstr "Ouvert"
msgid "Opens in a new window"
msgstr "Ouvrir dans une nouvelle fenêtre"
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr "Opérations"
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr "Le tableau de bord des opérations fournit un résumé de l’état de santé opérationnel de chaque projet, comprenant les états des pipelines et des alertes."
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr "Autres étiquettes"
msgid "Other information"
msgstr "Autres informations"
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr "Requêtes sortantes"
@@ -7874,6 +9196,12 @@ msgstr "Vue d’ensemble"
msgid "Overwrite diverged branches"
msgstr "Écraser les branches divergentes"
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr "Propriétaire"
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "Dernière ⇥"
@@ -7922,9 +9253,21 @@ msgstr "Partie des modifications de la demande de fusion"
msgid "Password"
msgstr "Mot de Passe"
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,8 +9280,8 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
-msgstr "Collez votre clef SSH publique, qui est habituellement située dans le fichier « ~/.ssh/id_rsa.pub » et commence par « ssh-rsa ». N’utilisez pas votre clef SSH privée !"
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
msgid "Path"
msgstr ""
@@ -7964,6 +9307,9 @@ msgstr "En attente"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr "Les personnes sans autorisation ne recevront jamais de notifications et ne pourront pas commenter."
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr "Effectuer des actions avancées telles que la modification du chemin d’accès, le transfert ou la suppression du groupe."
@@ -7985,12 +9331,27 @@ msgstr "Jeton d’accès personnel"
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr "Pipeline"
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr "Planification de pipeline"
@@ -8069,6 +9430,9 @@ msgstr "Pipelines"
msgid "Pipelines charts"
msgstr "Graphiques des pipelines"
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr "Pipelines du mois dernier"
@@ -8078,10 +9442,13 @@ msgstr "Pipelines de la semaine dernière"
msgid "Pipelines for last year"
msgstr "Pipelines de l’année dernière"
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr "Premiers pas avec les pipelines"
msgid "Pipelines|Loading Pipelines"
msgstr "Chargement des pipelines"
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "Réinitialisation du cache de projet réussie."
@@ -8162,6 +9532,9 @@ msgstr "Arrêter le pipeline"
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr "Arrêter le pipeline numéro %{pipelineId} ?"
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr "Variables"
@@ -8192,6 +9565,15 @@ msgstr "avec l’étape"
msgid "Pipeline|with stages"
msgstr "avec les étapes"
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr "Diff brut"
@@ -8201,12 +9583,30 @@ msgstr "PlantUML"
msgid "Play"
msgstr "Lancer"
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr "Veuillez accepter les conditions générales d’utilisation avant de continuer."
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr "Veuillez choisir une URL de groupe sans caractères spéciaux."
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr "Veuillez saisir un nom descriptif pour votre groupe."
@@ -8249,6 +9652,15 @@ msgstr "Veuillez noter que cette application n’est pas fournie par GitLab, vou
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,8 +9682,8 @@ msgstr "Veuillez réessayer"
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
-msgstr "Veuillez utiliser ce formulaire pour signaler à GitLab les utilisateurs qui créent des tickets ou des commentaires indésirables, ou qui se comportent de manière inappropriée."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
+msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -8288,12 +9700,66 @@ msgstr "Préférences"
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr "Thème de navigation"
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr "Appuyez sur Entrée ou cliquez pour rechercher"
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr "Aperçu"
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr "Aperçu de la charge utile"
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr "Principal"
@@ -8342,15 +9814,24 @@ msgstr "Privé — le groupe ainsi que ses projets ne sont accessibles qu’à s
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr "Des projets privés peuvent être créés dans votre espace de noms personnel avec :"
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr "Profil"
msgid "Profile Settings"
msgstr "Paramètres du profil"
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr "Vous êtes sur le point de supprimer définitivement %{yourAccount}, ainsi que tous les tickets, les demandes de fusion et les groupes liés à votre compte. Après confirmation, %{deleteAccount} ne peut être ni annulé ni restauré."
@@ -8381,6 +9862,9 @@ msgstr "Rogneur d’avatar"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "L’avatar sera supprimé. Êtesâ€vous sûr·e ?"
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr "Changer le nom d’utilisateur·rice"
@@ -8402,6 +9886,9 @@ msgstr "Effacer le statut"
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr "Chemin d’accès actuel : %{path}"
msgid "Profiles|Current status"
msgstr "État actuel"
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr "Supprimer un compte"
@@ -8441,6 +9931,18 @@ msgstr "Modifier le profil"
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr "Mot de passe incorrect"
msgid "Profiles|Invalid username"
msgstr "Nom d’utilisateur incorrect"
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr "En savoir plus"
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr "a fait une contribution privée"
@@ -8462,18 +9970,33 @@ msgstr "Paramètres principaux"
msgid "Profiles|No file chosen"
msgstr "Aucun fichier choisi"
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr "Chemin d’accès"
msgid "Profiles|Position and size your new avatar"
msgstr "Position et taille de votre nouvel avatar"
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr "Contributions privées"
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr "Avatar public"
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr "Supprimer l’avatar"
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "La taille de fichier maximale autorisée est de 200 Kio."
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "Ceci ne ressemble pas à une clef SSH publique, êtesâ€vous sûr(e) de vouloir l’ajouter ?"
@@ -8510,14 +10030,17 @@ msgstr "Cet émoji et ce message apparaîtront sur votre profil et partout dans
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Saisissez votre %{confirmationValue} pour confirmer :"
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
-msgstr "Commence généralement par « ssh-rsa […] »"
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
+msgstr ""
msgid "Profiles|Update profile settings"
msgstr "Mettre à jour les paramètres du profil"
@@ -8531,6 +10054,9 @@ msgstr "Téléverser un nouvel avatar"
msgid "Profiles|Use a private email - %{email}"
msgstr "Utiliser une adresse de courriel privée — %{email}"
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr "Le changement de nom d’utilisateur a échoué : %{message}"
@@ -8552,6 +10078,9 @@ msgstr "Vous pouvez changer votre avatar ici"
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr "Vous pouvez changer votre avatar ici ou supprimer l’avatar actuel et revenir à %{gravatar_link}"
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr "Vous pouvez téléverser votre avatar ici"
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr "Avatar du projet"
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "S’abonner"
@@ -8741,6 +10276,24 @@ msgstr "Vous devez vous authentifier afin de pouvoir ajouter une étoile à un p
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "Identifiant de projet : %{project_id}"
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr "Badges numériques"
@@ -8750,18 +10303,60 @@ msgstr "Contactez un administrateur pour modifier ce paramètre."
msgid "ProjectSettings|Customize your project badges."
msgstr "Personnalisez les badges numériques de votre projet."
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr "Impossible de protéger l’étiquette"
msgid "ProjectSettings|Failed to update tag!"
msgstr "Impossible de mettre à jour l’étiquette !"
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr "En savoir plus sur les badges numériques."
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Seuls les commits signés peuvent être poussés sur ce dépôt Git."
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr "Ce paramètre s’applique au niveau du serveur mais il peut être outrepassé par un administrateur."
@@ -8771,12 +10366,72 @@ msgstr "Ce paramètre s’applique au niveau du serveur, mais il a été outrepa
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "Ce paramètre s’appliquera à tous les projets à moins qu’un administrateur ou une administratrice ne l’outrepasse sur certains projets."
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr "Les utilisateurs et utilisatrices ne peuvent uniquement pousser sur ce dépôt que des commits qui ont été effectués avec une de leurs adresses de courriel vérifiées."
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr "Projets"
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr "Promouvoir en jalon de groupe"
msgid "Promote to group label"
msgstr "Promouvoir en tant qu’étiquette de groupe"
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr "Ne plus réafficher ce message"
@@ -8951,36 +10615,48 @@ msgstr ""
msgid "Protected"
msgstr "Protégé"
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr "Environnements protégés"
+msgid "Protected Tag"
+msgstr ""
+
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} sera accessible en écriture aux développeurs. Êtesâ€vous sûr de vouloir cela ?"
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "Autorisé à déployer"
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
-msgstr "ProtectedEnvironment|Choisissez qui est autorisé à déployer"
-
msgid "ProtectedEnvironment|Environment"
msgstr "Environnement"
msgid "ProtectedEnvironment|Protect"
msgstr "Protéger"
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr "Protéger les environnements afin de restreindre les déploiements aux personnes autorisées."
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr "Protéger un environnement"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr "Environnements protégés (%{protected_environments_count})"
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr "Sélectionner un environnement"
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr "Il n’y a actuellement aucun environnement protégé, protégezâ€en un avec le formulaire ciâ€dessus."
@@ -9029,9 +10705,15 @@ msgstr "Récupérer"
msgid "Push"
msgstr "Push"
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr "Règles de poussage Git"
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr "Poussé"
msgid "Pushes"
msgstr "Poussées Git"
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr "Trimestres"
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr "Les actions rapides peuvent être utilisées dans la description des tickets et dans les zones de commentaire."
@@ -9086,15 +10810,24 @@ msgstr "Fonctionnalités en temps réel"
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr "Recherches récentes"
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr "Rediriger vers le fournisseur SAML pour tester la configuration"
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] "L’affichage sera réactualisé dans une seconde avec le statut mis à jour..."
msgstr[1] "L’affichage sera réactualisé dans %d secondes avec le statut mis à jour…"
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr "Régénérer la clef"
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr "Expression rationnelle"
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr "Inscription / Connexion"
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr "Identifiezâ€vous et accédez à vos exécuteurs pour ce groupe."
msgid "Register and see your runners for this project."
msgstr "Enregistrer et afficher vos exécuteurs pour ce projet."
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr "Demandes de fusion liées"
msgid "Related Merged Requests"
msgstr "Demandes fusionnées liées"
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr "Demandes de fusion liées"
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr "Me le rappeler ultérieurement"
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr "Supprimer"
@@ -9172,7 +10932,10 @@ msgstr "Supprimer l’exécuteur"
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr "Supprimer l’avatar"
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr "Supprimer le groupe"
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr "Supprimer la priorité"
msgid "Remove project"
msgstr "Supprimer le projet"
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr "Un groupe supprimé ne peut être restauré !"
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr "Supprimer le groupe entraînera la suppression de tous les projets et ressources affiliés."
@@ -9244,6 +11037,9 @@ msgstr "Réparer l’authentification"
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,8 +11049,8 @@ msgstr "Répondez directement à ce courriel ou %{view_it_on_gitlab}."
msgid "Repo by URL"
msgstr "Dépôt par URL"
-msgid "Report abuse to GitLab"
-msgstr "Signaler un abus à GitLab"
+msgid "Report abuse to admin"
+msgstr ""
msgid "Reporting"
msgstr "Rapports"
@@ -9268,6 +11064,9 @@ msgstr "Actions"
msgid "Reports|Class"
msgstr "Classe"
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr "Confiance"
@@ -9307,12 +11106,6 @@ msgstr "Les résultats de la synthèse des tests sont en cours d’analyse"
msgid "Reports|Vulnerability"
msgstr "Vulnérabilité"
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr "aucun résultat de test modifié"
@@ -9367,6 +11160,12 @@ msgstr "Exiger que tous les utilisateurs acceptent les conditions générales dâ
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr "Relancer cette tâche"
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr "Relancer la vérification"
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr "Feuille de route"
@@ -9580,6 +11400,9 @@ msgstr "Authentification unique SAML pour %{group_name}"
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr "Clefs SSH"
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr "Clefs SSH de l’hôte"
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr "Clef SSH publique"
@@ -9604,6 +11430,9 @@ msgstr "Enregistrer"
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr "Enregistrer l’application"
@@ -9616,6 +11445,9 @@ msgstr "Enregistrer les modifications avant de tester"
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Sauvegarder la planification du pipeline"
@@ -9676,9 +11508,21 @@ msgstr "Rechercher dans les branches et les étiquettes"
msgid "Search files"
msgstr "Rechercher des fichiers"
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr "Rechercher des projets, des tickets, etc."
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr "Rechercher des projets"
msgid "Search projects"
msgstr "Rechercher des projets"
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr "Rechercher des utilisateurs et utilisatrices"
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr "Plus d’informations"
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr "Une erreur est survenue lors de la création du ticket."
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr "Le tableau de bord de sécurité affiche le dernier rapport de sécurité. Utilisezâ€le pour rechercher et corriger les vulnérabilités."
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr "Surveiller les vulnérabilités dans votre code"
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr "Pipeline %{pipelineLink} déclenché"
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr "Sélectionner"
msgid "Select Archive Format"
msgstr "Sélectionnez le format de l’archive"
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr "Sélectionnez un groupe à inviter"
@@ -9853,6 +11715,9 @@ msgstr "Sélectionnez une grappe de serveurs Kubernetes existante ou créezâ€en
msgid "Select branch/tag"
msgstr "Sélectionner une branche ou une étiquette"
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr "La sélection d’un utilisateur de GitLab va ajouter un lien vers cet u
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr "Envoyer un courriel"
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr "Service d’assistance"
@@ -10000,21 +11871,24 @@ msgstr "Définir un modèle de dépôt pour les projets de ce groupe"
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr "Définissez les valeurs par défaut et restreignez les niveaux de visibilité. Configurez les sources d’importation et le protocole d’accès pour Git."
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr "Définir un dépôt de modèles au niveau de l’instance"
msgid "Set max session time for web terminal."
msgstr "Définissez le temps maximal de la session pour le terminal Web."
+msgid "Set milestone"
+msgstr ""
+
msgid "Set new password"
msgstr ""
msgid "Set notification email for abuse reports."
msgstr "Définissez un courriel de notification pour les rapports d’abus."
-msgid "Set number of approvers required before open merge requests can be merged"
-msgstr ""
-
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr "Définissez les exigences pour la connexion d’un utilisateur. Activez l’authentification obligatoire à deux facteurs."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr "Configuration CI/CD"
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr "Configurez votre projet afin de pouvoir pousser et/ou récupérer automatiquement les modifications vers ou depuis un autre dépôt. Les branches, les étiquetets et les commits seront automatiquement synchronisés."
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr "définir un mot de passe"
@@ -10078,6 +11958,18 @@ msgstr "Désolé, l’état n’a pas pu être défini. Veuillez réessayer ultÃ
msgid "SetStatusModal|What's your status?"
msgstr "Quel est votre état ?"
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr "Paramètres"
@@ -10093,6 +11985,9 @@ msgstr "Exécuteurs partagés"
msgid "Shared projects"
msgstr "Projets partagés"
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr "En réinitialisant le compteur de minutes du pipeline pour cet espace de noms, les minutes actuellement utilisées seront mises à zéro."
@@ -10105,9 +12000,18 @@ msgstr "Réinitialiser les minutes du pipeline utilisées"
msgid "Sherlock Transactions"
msgstr "Transactions Sherlock"
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr "Afficher la commande"
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr "Afficher la dernière version"
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr "Afficher les pages parentes"
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr "Se déconnecter"
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr "Restrictions de connexion"
msgid "Sign-up restrictions"
msgstr "Restrictions d’inscription"
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr "Taille"
@@ -10203,6 +12125,9 @@ msgstr "Paramètres de taille et de domaine pour les sites Web statiques"
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr "Application Slack"
@@ -10272,6 +12197,9 @@ msgstr "Une erreur est survenue lors de la tentative de modification de l’éta
msgid "Something went wrong when toggling the button"
msgstr "Une erreur s’est produite lors du basculement du bouton"
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr "Une erreur est survenue lors de la récupération des commentaires. Veui
msgid "Something went wrong while fetching group member contributions"
msgstr "Une erreur s’est produite lors de la récupération des contributions des membres du groupe"
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,8 +12245,8 @@ msgstr "Une erreur s’est produite lors de la « résolution » de la discuss
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr "Une erreur est survenue, impossible d’ajouter %{project} au tableau de bord"
-msgid "Something went wrong, unable to get operations projects"
-msgstr "Une erreur est survenue, impossible d’obtenir des projets d’opérations"
+msgid "Something went wrong, unable to get projects"
+msgstr ""
msgid "Something went wrong, unable to remove project"
msgstr "Une erreur est survenue, impossible de supprimer le projet"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr "Quelque chose s’est mal passé. Veuillez réessayer."
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr "Désolé, aucune épopée ne correspond à votre recherche"
@@ -10386,6 +12320,9 @@ msgstr "Popularité croissante"
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr "Date d’inscription décroissante"
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr "Date de début"
@@ -10512,6 +12455,9 @@ msgstr "%{type} en étape"
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr "Mettez une étoile sur une étiquette pour en faire une étiquette prioritaire. Ordonnez les étiquettes prioritaires pour changer leurs priorités relatives en les faisant glisser."
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr "Mettre en favori"
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "Démarrer l’exécuteur !"
@@ -10626,12 +12581,18 @@ msgstr "Stockage"
msgid "Storage:"
msgstr "Stockage :"
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr "Sousâ€groupes"
msgid "Subgroups and projects"
msgstr "Sousâ€groupes et projets"
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr "Soumettre comme indésirable"
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr "Abonné"
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr "Changer de branche ou d’étiquette"
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr "Synchroniser les informations"
@@ -10800,18 +12836,30 @@ msgstr "Métriques du système (personnalisées)"
msgid "System metrics (Kubernetes)"
msgstr "Métriques du système (Kubernetes)"
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr "Étiquettes"
msgid "Tags feed"
msgstr "Flux d’étiquettes"
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr "Étiquettes :"
@@ -10893,6 +12941,9 @@ msgstr "Branche cible"
msgid "Team"
msgstr "Équipe"
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr "Modèle"
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "Conditions générales d’utilisation et politique de confidentialité"
@@ -10920,6 +12974,33 @@ msgstr "Analyse de la couverture des tests"
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr "Le surligneur de caractères vous aide à garder la longueur de l’objet à %{titleLength} caractères maximum et à faire des renvois à la ligne pour limiter les lignes du corps du message à %{bodyLength} caractères, afin de les rendre lisibles sous Git."
@@ -10973,6 +13057,9 @@ msgstr "La connexion expirera après %{timeout}. Pour les dépôts qui nécessit
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr "Le déploiement de cette tâche sur %{environmentLink} a échoué."
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "Le présentoir des tickets affiche le temps nécessaire entre la création d’un ticket et son assignation à un jalon ou son ajout à une liste dans votre tableau de tickets. Commencez par créer des tickets pour voir des données sur ce présentoir."
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "La phrase de passe permettant de déchiffrer la clef privée. Ceci est facultatif et la valeur est chiffrée au repos."
@@ -11072,9 +13174,21 @@ msgstr "L’étape de mise en production montre le temps nécessaire entre la cr
msgid "The project can be accessed by any logged in user."
msgstr "Votre projet est accessible à tous les utilisateur et utilisatrices authentifiés."
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr "Votre projet est accessible sans aucune authentification."
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr "La collecte de données du pseudonymiseur est désactivée. Lorsque cette option est activée, GitLab exécute un travail en tâche de fond produisant des fichiers CSV pseudonymisés à partir de la base de données GitLab qui seront téléchargés dans le répertoire de stockage d’objets que vous avez configuré."
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr "Le dépôt de ce projet n’existe pas."
msgid "The repository for this project is empty"
msgstr "Le dépôt de ce projet est vide"
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr "Le dépôt doit être accessible via <code>http://</code>, <code>https://</code> ou <code>git://</code>."
@@ -11132,6 +13252,9 @@ msgstr "L’étape de test montre le temps que que met l’intégration continue
msgid "The time taken by each data entry gathered by that stage."
msgstr "Le temps pris par chaque entrée récoltée durant cette étape."
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr "L’action de mise à jour expirera au bout de %{number_of_minutes} minutes. Pour les gros dépôts, utilisez une combinaison de clone et push."
@@ -11153,15 +13276,30 @@ msgstr "La carte des utilisateurs (<code>user map</code>) est un document JSON q
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr "La carte des utilisateurs met en correspondance les utilisateurs de FogBugz qui ont participé à vos projets en précisant la manière dont leurs adresses de courriel et leurs noms d’utilisateur sont importés dans GitLab. Vous pouvez y apporter des modifications en remplissant le tableau ciâ€dessous."
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "La valeur située au point médian d’une série de valeur observée. Par exemple., entre 3, 5 et 9, le médian est 5. Entre 3, 5, 7 et 8, le médian est (5+7)/2 = 6."
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr "Il n’y a pas encore de projets archivés"
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr "Il n’y a aucune modification indexée"
msgid "There are no unstaged changes"
msgstr "Il n’y a aucune modification non indexée"
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr "Une erreur est survenue lors de l’ajout d’une tâche à accomplir (todo)."
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr "Une erreur est survenue lors de la suppression de la tâche à accomplir (todo)."
@@ -11213,6 +13366,12 @@ msgstr "Une erreur s’est produite lors du chargement du calendrier d’activit
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr "Une erreur s’est produite lors de l’abonnement à cette étiquette."
msgid "There was an error when unsubscribing from this label."
msgstr "Une erreur s’est produite lors de la désinscription à cette étiquette."
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr "Ils peuvent être gérés en utilisant %{link}."
msgid "Third party offers"
msgstr "Offres tierces"
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr "Cette instance de GitLab ne fournit aucun exécuteur partagé pour le mo
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr "Cette application a été créée par %{link_to_owner}."
msgid "This application will be able to:"
msgstr "Cette application sera en mesure de :"
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr "La portée de ce tableau est réduite"
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr "Cette branche a changé depuis que vous y avez apporté des modifications. Souhaitezâ€vous créer une nouvelle branche ?"
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr "Cette date est postérieure à la date d’échéance, cette épopée nâ
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr "Cette date est antérieure à la date de début, cette épopée n’apparaîtra donc pas dans la feuille de route."
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr "Ce diff est replié."
@@ -11303,6 +13486,9 @@ msgstr "Ce répertoire"
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,24 +13498,33 @@ msgstr "Ce groupe"
msgid "This group does not provide any group Runners yet."
msgstr "Ce groupe ne fournit pas encore d’exécuteurs de groupe."
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr "Ce ticket est confidentiel."
msgid "This is a delayed job to run in %{remainingTime}"
msgstr "Il s’agit d’une tâche différée devant être exécutée dans %{remainingTime}"
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr "C’est la première demande de fusion de cet auteur pour ce projet."
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
+msgid "This is your current session"
+msgstr ""
+
msgid "This issue is confidential"
msgstr "Ce ticket est confidentiel"
-msgid "This issue is confidential and locked."
-msgstr "Ce ticket est confidentiel et verrouillé."
-
msgid "This issue is locked."
msgstr "Ce ticket est verrouillé."
@@ -11399,12 +13594,6 @@ msgstr "Cela signifie que vous ne pouvez pas pousser du code tant que vous n’a
msgid "This merge request is locked."
msgstr "Cette demande de fusion est verrouillée."
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr "Ces courriels deviennent automatiquement des tickets (dont les commentaires résultent de la conversation par courriel) répertoriés ici."
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr "Temps avant qu’un ticket ne soit planifié"
@@ -11661,6 +13856,9 @@ msgstr "Astuce :"
msgid "Title"
msgstr "Titre"
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr "Afin d’ajouter une clef SSH, vous devez soit %{generate_link_start}en génèrer une%{link_end}, soit utiliser une %{existing_link_start}clef existante%{link_end}."
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr "Pour connecter des dépôts GitHub, vous pouvez utiliser un %{personal_access_token_link}. Lorsque vous créerez votre jeton d’accès, vous devrez sélectionner la portée <code>dépôt</code>, afin de permettre l’affichage d’une liste de vos dépôts publics et privés disponibles à la connexion."
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr "Pour configurer l’authentification SAML pour votre groupe via un fournisseur d’identité tel qu’Azure, Okta, Onelogin, Ping Identity ou votre fournisseur SAML 2.0 personnalisé :"
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr "Pour commencer à exécuter vos tâches, vous pouvez ajouter des exécuteurs à votre groupe"
@@ -11778,6 +13982,9 @@ msgstr "À faire"
msgid "Toggle Sidebar"
msgstr "Afficher/masquer la barre latérale"
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr "Basculer la discussion"
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Activer/désactiver la navigation"
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Afficher/masquer la barre latérale"
@@ -11802,6 +14015,9 @@ msgstr "État du commutateur : Inactif"
msgid "ToggleButton|Toggle Status: ON"
msgstr "État du commutateur : Actif"
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr "Jeton"
@@ -11844,6 +14060,42 @@ msgstr "Suivre le temps estimé/passé avec les actions rapides"
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr "Vue arborescente"
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr "Essayez tout ce que GitLab peut vous offrir pendant 30 jours."
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "Activer le service d’assistance"
msgid "Twitter"
msgstr "Twitter"
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr "Authentification à double facteur"
msgid "Type"
msgstr "Type"
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr "Impossible de charger le diff. %{button_try_again}"
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "Impossible de vous connecter au groupe via SAML en raison de « %{reason} »"
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr "Impossible de mettre à jour cette épopée pour le moment."
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr "Inconnu"
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr "Déverrouiller"
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr "Déverrouiller %{issuableDisplayName} ? <strong>Tout le monde</strong> sera en mesure de commenter."
msgid "Unlocked"
msgstr "Déverrouillé"
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr "Marquer la discussion comme non résolue"
@@ -12030,6 +14330,18 @@ msgstr "Modifiez le nom du groupe, sa description, son avatar et sa visibilité.
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr "Téléverser un fichier"
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr "Cliquez pour envoyer"
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr "L’envoi des données d’utilisation est désactivé"
msgid "Usage statistics"
msgstr "Statistiques d’utilisation"
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr "Utiliser <code>%{native_redirect_uri}</code> pour les tests locaux"
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "Le service d’assistance (Service Desk) permet d’interagir avec vos utilisateurs (p. ex., pour offrir un support client) par courriel depuis GitLab"
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr "Utilisez les jalons de groupe pour gérer les tickets de plusieurs projets dans le même jalon."
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr "Correspondance entre utilisateurs"
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr "Activité"
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr "Utilisateurs et utilisatrices"
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr "Version"
msgid "View app"
msgstr "Voir l’application"
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr "Afficher la liste des épopées"
msgid "View file @ "
msgstr "Voir le fichier @ "
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr "Afficher les labels de groupe"
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr "Voir sur GitLab"
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr "Afficher la documentation"
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr "Contrôles de visibilité et d’accès"
@@ -12405,6 +14957,33 @@ msgstr "Public"
msgid "VisibilityLevel|Unknown"
msgstr "Inconnu"
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr "Gravité"
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Vous voulez voir les données ? Merci de contacter un administrateur pour en obtenir l’accès."
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "Nous avons détecté un potentiel courriel indésirable dans %{humanized_resource_name}. Veuillez résoudre le reCAPTCHA pour continuer."
@@ -12474,6 +15059,9 @@ msgstr "Nous n’avons pas suffisamment de données pour afficher cette étape."
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "Nous voulons nous assurer qu’il s’agit bien de vous, merci de confirmer que vous n’êtes pas un robot."
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr "Les webhooks vous permettent de déclencher une URL si, par exemple, du nouveau code est poussé ou un nouveau ticket est créé. Vous pouvez configurer les webhooks pour écouter les événements spécifiques comme des poussées de code, des tickets ou des demandes de fusion. Les webhooks de groupes s’appliqueront à tous les projets dans un groupe, ce qui vous permet de normaliser la fonctionnalité du webhook dans votre groupe entier."
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr "Semaines"
@@ -12504,15 +15095,18 @@ msgstr "Poids"
msgid "Weight %{weight}"
msgstr "Poids %{weight}"
+msgid "Welcome to the Guided GitLab Tour"
+msgstr ""
+
+msgid "Welcome to your Issue Board!"
+msgstr ""
+
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Lorsqu’un exécuteur est verrouillé, il ne peut pas être affecté à d’autres projets"
msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr "Lorsque cette option est activée, les utilisateurs et utilisarices ne pourront pas utiliser GitLab tant que les conditions générales d’utilisation ne seront pas acceptées."
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr "Lorsque vous laissez l’URL vide, des étiquettes de classification peuvent toujours être spécifiées sans désactiver les fonctionnalités interâ€projets ni effectuer de vérifications d’autorisation externes."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr "Qui peut voir ce groupe ?"
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr "Oui"
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr "Oui, l’ajouter"
@@ -12719,8 +15319,14 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr "Vous êtes un administrateur ou une administratrice, ce qui signifie qu’accorder un accès à <strong>%{client_name}</strong> lui permettra d’interagir avec GitLab en tant qu’administrateur également. Faitesâ€le avec prudence."
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "Vous êtes sur le point de supprimer %{group_name}. Les groupes supprimés NE PEUVENT PAS être restaurés ! Êtes vous ABSOLUMENT sûr·e ?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "Vous êtes sur le point de supprimer %{project_full_name}. Les projets supprimés NE PEUVENT PAS être restaurés ! Êtesâ€vous ABSOLUMENT sûr·e ?"
@@ -12731,6 +15337,9 @@ msgstr "Vous êtes sur le point de supprimer la relation de divergence avec le p
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr "Vous allez transférer %{project_full_name} à un nouveau ou une nouvelle propriétaire. Êtesâ€vous VRAIMENT sûr(e) ?"
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr "Vous pouvez %{linkStart}afficher les données brutes%{linkEnd} à la pla
msgid "You can also create a project from the command line."
msgstr "Vous pouvez également créer un projet en ligne de commande."
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr "Vous pouvez marquer un label comme important pour en faire un label prioritaire."
@@ -12764,6 +15379,15 @@ msgstr "Vous pouvez facilement y contribuer en demandant à rejoindre ces groupe
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr "Vous pouvez facilement installer un Exécuteur sur un cluster Kubernetes. %{link_to_help_page}"
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr "Vous pouvez vous déplacer dans le graphique en utilisant les touches fléchées."
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "Vous pouvez résoudre le conflit de fusion Git soit en mode interactif, en cliquant sur les boutons « %{use_ours} » ou « %{use_theirs} », soit en modifiant directement les fichiers. Valider ces modifications dans la branche « %{branch_name} »"
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr "Vous pouvez configurer des tâches pour n’utiliser des exécuteurs qu’avec des étiquettes spécifiques. Séparez les étiquettes par des virgules."
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr "Vous pouvez tester votre fichier « .gitlab-ci.yml » avec %{linkStart}CI Lint%{linkEnd}."
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr "Vous n’avez souscrit à aucun abonnement pour le moment"
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr "Vous ne disposez pas des autorisations appropriées pour outrepasser les paramètres de synchronisation du groupe LDAP."
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr "Vous ne disposez d’aucune application"
@@ -12836,6 +15475,12 @@ msgstr "Vous ne disposez d’aucune application autorisée"
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr "Vous devez accepter les conditions générales d’utilisation et la pol
msgid "You must have maintainer access to force delete a lock"
msgstr "Seul un responsable peut forcer la suppression d’un verrou"
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr "Vous avez besoin d’une licence différente pour activer la fonctionnalité de verrouillage de fichiers FileLocks"
@@ -12878,6 +15532,9 @@ msgstr "Pour aller plus loin, vous devez disposer de git-lfs en version %{min_g
msgid "You need permission."
msgstr "Vous avez besoin d’une autorisation."
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr "Vous devez %{add_ssh_key_link} dans votre profil afin de pouvoir récupÃ
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "Vous ne pourrez pas récupérer ou pousser de code via SSH tant que vous n’aurez pas ajouté de clef SSH à votre profil"
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr "Vous devrez utiliser différents noms de branches pour obtenir une comparaison valide."
@@ -12944,27 +15607,51 @@ msgstr "Vous recevez ce courriel parce que vous possédez un compte sur %{host}.
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr "Vous recevez ce courriel en raison de votre compte sur %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr "YouTube"
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr "Vos groupes"
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr "Vos informations de cluster Kubernetes sur cette page sont toujours modifiables, mais il est conseillé de désactiver et reconfigurer"
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr "Vos projets (défaut)"
msgid "Your Projects' Activity"
msgstr "Activité de vos projets favoris"
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr "Vos tâches à faire"
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,8 +15685,11 @@ msgstr "Vos modifications ont été enregistrées"
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
-msgstr "Votre commentaire ne sera pas visible publiquement."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
+msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
msgstr ""
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr "Votre nom"
@@ -13049,12 +15742,15 @@ msgstr "auparavant "
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
-msgstr "entre autres choses"
+msgid "already being used for another group or project milestone."
+msgstr ""
-msgid "at"
+msgid "already shared with this group"
msgstr ""
+msgid "among other things"
+msgstr "entre autres choses"
+
msgid "attach a new file"
msgstr ""
@@ -13067,6 +15763,21 @@ msgstr "nom de la branche"
msgid "by"
msgstr "par"
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr "%{linkStartTag}En savoir plus à propos de l’analyse des conteneurs %{linkEndTag}"
@@ -13160,6 +15871,9 @@ msgstr "(en cours de chargement)"
msgid "ciReport|(is loading, errors when loading results)"
msgstr "(en cours de chargement, erreurs lors du chargement des résultats)"
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr "DAST"
@@ -13211,12 +15922,6 @@ msgstr "Analyse des dépendances"
msgid "ciReport|Description"
msgstr "Description"
-msgid "ciReport|Dismiss vulnerability"
-msgstr "Rejeter la vulnérabilité"
-
-msgid "ciReport|Dismissed by"
-msgstr "Rejeté par"
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr "Une erreur s’est produite lors du chargement du rapport d’analyse de
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr "Une erreur s’est produite lors de l’annulation du rejet. Veuillez réessayer."
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr "Mise à niveau de %{name} de %{version} à %{fixed}."
@@ -13355,12 +16057,12 @@ msgstr[1] "Utilisé par %{packagesString} et %{lastPackage}"
msgid "ciReport|View full report"
msgstr "Voir le rapport complet"
-msgid "ciReport|on pipeline"
-msgstr "dans le pipeline"
-
msgid "commented on %{link_to_project}"
msgstr ""
+msgid "commit %{commit_id}"
+msgstr ""
+
msgid "confidence|Confirmed"
msgstr ""
@@ -13400,6 +16102,9 @@ msgstr "impossible de lire la clef privée, la phrase secrète estâ€elle correc
msgid "customize"
msgstr "personnaliser"
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] "jour"
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] "brouillon"
msgstr[1] "brouillons"
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr "activé"
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr "%{slash_command} mettra à jour la durée estimée avec la dernière commande."
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr "de"
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr "ici"
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] "instance terminée"
msgstr[1] "instances terminées"
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr "n’est pas valide, car il y a un verrou en aval"
@@ -13507,6 +16233,9 @@ msgstr "n’est pas valide, car il y a un verrou en amont"
msgid "is not a valid X509 certificate."
msgstr "n’est pas un certificat X.509 valide."
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] "demande de fusion"
msgstr[1] "demandes de fusion"
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,8 +16313,8 @@ msgstr "%{metricsLinkStart}L’usage mémoire%{metricsLinkEnd} %{emphasisStart}a
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "%{metricsLinkStart}L’usage mémoire%{metricsLinkEnd} %{emphasisStart}est resté stable%{emphasisEnd} à %{memoryFrom}MO"
-msgid "mrWidget|Add approval"
-msgstr "Ajouter une approbation"
+msgid "mrWidget|Added to the merge train by"
+msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "Autoriser les commits des membres qui peuvent fusionner dans la branche cible"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "Une erreur est survenue lors de l’envoi de votre approbation."
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr "Approuver"
@@ -13647,6 +16385,9 @@ msgstr "Impossible de charger les statistiques de déploiement"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr "La fusion rapide fastâ€forward n’est pas possible. Pour réaliser cette fusion, vous devez d’abord effectuer un « git rebase » en local."
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr "Si la branche %{branch} existe dans votre dépôt local, vous pouvez fusionner cette demande de fusion manuellement à l’aide de"
@@ -13665,18 +16406,15 @@ msgstr "Fusionner"
msgid "mrWidget|Merge failed."
msgstr "La fusion a échoué."
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
+msgstr ""
+
msgid "mrWidget|Merge locally"
msgstr "Fusionner localement"
-msgid "mrWidget|Merge request approved"
-msgstr "Demande de fusion approuvée"
-
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr "Demande de fusion approuvée ; vous pouvez ajouter votre approbation"
-
msgid "mrWidget|Merged by"
msgstr "Fusionnée par"
@@ -13707,22 +16445,12 @@ msgstr "Actualiser maintenant"
msgid "mrWidget|Refreshing now"
msgstr "Actualisation en cours"
-msgid "mrWidget|Remove your approval"
-msgstr "Supprimer votre approbation"
+msgid "mrWidget|Remove from merge train"
+msgstr ""
msgid "mrWidget|Request to merge"
msgstr "Demande de fusion de"
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] "Nécessite encore une approbation"
-msgstr[1] "Nécessite encore %d approbations"
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] "Nécessite encore l’approbation de"
-msgstr[1] "Nécessite encore %d approbations de"
-
msgid "mrWidget|Resolve conflicts"
msgstr "Résoudre les conflits"
@@ -13807,15 +16535,30 @@ msgstr "ligne de commande"
msgid "mrWidget|into"
msgstr "dans"
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr "pour être fusionnée automatiquement lorsque le pipeline réussit"
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr "non disponible"
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr "nouvelle demande de fusion"
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr "source"
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} mettra à jour la somme du temps passé."
msgid "started"
msgstr "démarré"
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr "utilise les grappes de serveurs Kubernetes pour déployer votre code !
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr "voir sur GitLab"
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "avec %{additions} ajouts, %{deletions} suppressions."
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index e6e161a2b27..9aed0471e3d 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -19,9 +19,6 @@ msgstr ""
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -44,6 +41,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -79,6 +81,11 @@ msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -100,7 +107,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} more"
@@ -138,6 +145,9 @@ msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
msgid "%{level_name} is not allowed in a %{group_level_name} group."
msgstr ""
@@ -159,6 +169,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
@@ -174,6 +190,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -245,6 +273,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -291,15 +322,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -309,6 +352,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -339,6 +385,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -366,19 +415,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -408,6 +457,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -453,6 +505,9 @@ msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -474,6 +529,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -498,9 +556,18 @@ msgstr ""
msgid "Add a todo"
msgstr ""
+msgid "Add an SSH key"
+msgstr ""
+
msgid "Add bold text"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -534,6 +601,9 @@ msgstr ""
msgid "Add to project"
msgstr ""
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr ""
@@ -699,12 +769,18 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "All"
msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -714,6 +790,9 @@ msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -771,9 +850,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -795,6 +871,12 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -804,13 +886,25 @@ msgstr ""
msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
msgstr ""
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching projects autocomplete."
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
msgstr ""
msgid "An error occurred while fetching the job log."
@@ -828,6 +922,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -849,6 +946,12 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
+msgstr ""
+
msgid "An error occurred while rendering KaTeX"
msgstr ""
@@ -876,6 +979,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -909,9 +1015,18 @@ msgstr ""
msgid "Any"
msgstr ""
+msgid "Any Label"
+msgstr ""
+
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -936,6 +1051,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -954,6 +1072,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "Apr"
msgstr ""
@@ -984,6 +1114,18 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
+msgid "Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr ""
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to delete this list?"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -1014,6 +1156,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1023,9 +1168,21 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -1089,6 +1246,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -1170,15 +1335,21 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1290,6 +1461,9 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
msgid "BambooService|A continuous integration and build server"
msgstr ""
@@ -1356,6 +1530,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1503,6 +1680,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1584,6 +1764,12 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Cancel"
msgstr ""
@@ -1608,6 +1794,9 @@ msgstr ""
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -1632,6 +1821,12 @@ msgstr ""
msgid "Change title"
msgstr ""
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -1680,6 +1875,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -1701,6 +1899,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -1722,7 +1923,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -1794,16 +1995,31 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -1896,6 +2112,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1911,7 +2130,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1929,12 +2154,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -1950,6 +2187,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2055,6 +2295,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2085,19 +2328,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2130,6 +2364,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2166,6 +2403,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2175,9 +2415,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2241,7 +2478,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2295,40 +2532,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2340,6 +2589,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2349,6 +2601,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2385,9 +2640,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2406,6 +2667,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2519,6 +2783,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2537,15 +2804,24 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
msgid "Connect repositories from GitHub"
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Container Registry"
msgstr ""
@@ -2639,12 +2915,18 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -2660,9 +2942,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -2681,7 +2960,7 @@ msgstr ""
msgid "Copy labels and milestone from %{source_issuable_reference}."
msgstr ""
-msgid "Copy labels and milestone from other issue or merge request"
+msgid "Copy labels and milestone from other issue or merge request in this project"
msgstr ""
msgid "Copy link"
@@ -2693,6 +2972,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -2747,6 +3029,9 @@ msgstr ""
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -2852,6 +3137,9 @@ msgstr ""
msgid "Current Branch"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -2924,12 +3212,27 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3220,9 +3523,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3256,6 +3565,9 @@ msgstr ""
msgid "Discuss a specific suggestion or question that needs to be resolved"
msgstr ""
+msgid "Discussion"
+msgstr ""
+
msgid "Dismiss"
msgstr ""
@@ -3268,9 +3580,18 @@ msgstr ""
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -3286,22 +3607,16 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
-msgstr ""
-
-msgid "Download tar.gz"
+msgid "Download export"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3334,6 +3649,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3400,6 +3718,12 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
@@ -3445,6 +3769,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -3478,9 +3805,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -3502,12 +3826,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -3520,7 +3850,7 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -3679,6 +4009,9 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
@@ -3691,6 +4024,9 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -3700,6 +4036,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -3709,6 +4048,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -3742,9 +4087,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -3916,6 +4267,18 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
msgid "ExternalWikiService|External Wiki"
msgstr ""
@@ -3943,6 +4306,15 @@ msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
msgid "Failed to create repository via gitlab-shell"
msgstr ""
@@ -3952,6 +4324,9 @@ msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
msgid "Failed to install."
msgstr ""
@@ -3961,6 +4336,9 @@ msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -3979,6 +4357,12 @@ msgstr ""
msgid "Failed to remove user key."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -3988,9 +4372,15 @@ msgstr ""
msgid "Failed to save preferences."
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
+msgid "Failed to update tag!"
+msgstr ""
+
msgid "Failed to update."
msgstr ""
@@ -4003,9 +4393,6 @@ msgstr ""
msgid "Failure"
msgstr ""
-msgid "Fast-forward merge"
-msgstr ""
-
msgid "Fast-forward merge without a merge commit"
msgstr ""
@@ -4053,6 +4440,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Filter"
msgstr ""
@@ -4092,6 +4485,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4152,6 +4548,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4161,6 +4566,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4173,6 +4581,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4200,12 +4611,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -4248,6 +4665,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -4302,6 +4722,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -4320,9 +4743,15 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -4452,6 +4881,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -4557,12 +4989,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -4572,6 +5007,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -4586,6 +5024,9 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -4610,6 +5051,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -4673,7 +5120,16 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -4754,6 +5210,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -4847,12 +5309,24 @@ msgstr ""
msgid "Insert suggestion"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance Statistics"
msgstr ""
@@ -4895,12 +5369,21 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
msgid "Invalid feature"
msgstr ""
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
@@ -4919,6 +5402,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -4943,6 +5429,12 @@ msgstr ""
msgid "Issue events"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -5108,6 +5600,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -5117,6 +5615,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -5159,6 +5660,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -5180,6 +5684,9 @@ msgstr ""
msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
msgstr ""
+msgid "LabelSelect|Labels"
+msgstr ""
+
msgid "Labels"
msgstr ""
@@ -5201,6 +5708,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -5215,6 +5725,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -5242,6 +5755,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -5257,6 +5776,9 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn more"
msgstr ""
@@ -5269,6 +5791,9 @@ msgstr ""
msgid "Learn more about Kubernetes"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about signing commits"
msgstr ""
@@ -5293,11 +5818,20 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -5322,6 +5856,9 @@ msgstr ""
msgid "Live preview"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -5373,6 +5910,9 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make issue confidential."
msgstr ""
@@ -5382,6 +5922,9 @@ msgstr ""
msgid "Makes this issue confidential"
msgstr ""
+msgid "Manage"
+msgstr ""
+
msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
msgstr ""
@@ -5439,6 +5982,12 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
msgid "Mark this issue as a duplicate of another issue"
msgstr ""
@@ -5496,21 +6045,18 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
-msgid "Merge Request"
+msgid "Merge"
msgstr ""
-msgid "Merge Requests"
+msgid "Merge Request"
msgstr ""
-msgid "Merge commit"
+msgid "Merge Requests"
msgstr ""
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -5520,9 +6066,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -5535,6 +6078,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -5589,7 +6156,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -5619,6 +6186,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -5631,9 +6201,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|Show last"
msgstr ""
@@ -5691,7 +6258,16 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged. This action cannot be reversed."
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
msgstr ""
msgid "Mirror a repository"
@@ -5712,6 +6288,9 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -5790,6 +6369,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -5900,6 +6482,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -5930,18 +6515,33 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
msgid "No %{providerTitle} repositories available to import"
msgstr ""
+msgid "No Label"
+msgstr ""
+
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -5957,13 +6557,13 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
-msgid "No contributions were found"
+msgid "No contributions"
msgstr ""
-msgid "No details available"
+msgid "No contributions were found"
msgstr ""
-msgid "No due date"
+msgid "No details available"
msgstr ""
msgid "No errors to display."
@@ -5978,6 +6578,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -5990,9 +6593,6 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests found"
msgstr ""
@@ -6005,6 +6605,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -6065,6 +6668,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -6080,6 +6686,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -6089,6 +6701,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -6140,6 +6755,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -6187,12 +6805,6 @@ msgstr ""
msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
-msgstr ""
-
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
-msgstr ""
-
msgid "Only mirror protected branches"
msgstr ""
@@ -6241,6 +6853,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -6271,6 +6889,12 @@ msgstr ""
msgid "Overview"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -6292,6 +6916,18 @@ msgstr ""
msgid "Pages getting started guide"
msgstr ""
+msgid "Pagination|Go to first page"
+msgstr ""
+
+msgid "Pagination|Go to last page"
+msgstr ""
+
+msgid "Pagination|Go to next page"
+msgstr ""
+
+msgid "Pagination|Go to previous page"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -6313,16 +6949,28 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
msgid "Paste a machine public key here. Read more about how to generate it %{link_start}here%{link_end}"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -6346,6 +6994,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -6367,12 +7018,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -6457,10 +7123,10 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -6541,6 +7207,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -6589,12 +7258,18 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a list to your board first"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -6619,6 +7294,15 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -6634,7 +7318,7 @@ msgstr ""
msgid "Please try again"
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -6649,24 +7333,84 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Prioritize"
msgstr ""
@@ -6688,15 +7432,24 @@ msgstr ""
msgid "Private - The group and its projects can only be viewed by members."
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -6727,6 +7480,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -6748,6 +7504,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -6760,6 +7519,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -6787,6 +7549,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -6796,9 +7570,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -6808,18 +7588,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -6838,9 +7633,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -6856,13 +7648,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -6877,6 +7672,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -6898,6 +7696,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -7090,18 +7891,132 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -7222,6 +8137,12 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Tag"
+msgstr ""
+
msgid "Protip:"
msgstr ""
@@ -7324,12 +8245,21 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -7341,21 +8271,36 @@ msgstr[1] ""
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registry"
msgstr ""
@@ -7431,12 +8376,6 @@ msgstr ""
msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? Are you sure?"
-msgstr ""
-
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
-msgstr ""
-
msgid "Remove time estimate"
msgstr ""
@@ -7491,7 +8430,7 @@ msgstr ""
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -7503,6 +8442,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
@@ -7566,6 +8508,12 @@ msgstr ""
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -7593,6 +8541,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -7623,6 +8580,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -7658,6 +8618,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Run housekeeping"
msgstr ""
@@ -7718,6 +8684,9 @@ msgstr ""
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -7727,6 +8696,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -7742,6 +8714,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -7751,6 +8726,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -7805,9 +8783,18 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -7829,6 +8816,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -7877,6 +8867,9 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -7925,6 +8918,9 @@ msgstr ""
msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -8006,6 +9002,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -8123,9 +9122,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -8141,9 +9149,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -8179,6 +9184,18 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -8245,6 +9262,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -8257,6 +9277,9 @@ msgstr ""
msgid "Something went wrong while fetching comments. Please try again."
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -8284,6 +9307,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no projects matched your search"
msgstr ""
@@ -8338,6 +9364,9 @@ msgstr ""
msgid "SortOptions|Least popular"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -8389,6 +9418,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -8455,6 +9490,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -8482,6 +9520,9 @@ msgstr ""
msgid "Start a new merge request"
msgstr ""
+msgid "Start a review"
+msgstr ""
+
msgid "Start and due date"
msgstr ""
@@ -8548,12 +9589,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -8581,6 +9628,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "Subtracts"
msgstr ""
@@ -8608,6 +9658,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -8620,6 +9733,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "System Hooks"
msgstr ""
@@ -8644,6 +9763,9 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
@@ -8746,6 +9868,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -8767,6 +9892,9 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
msgid "TestHooks|Ensure one of your projects has merge requests."
msgstr ""
@@ -8811,6 +9939,9 @@ msgstr ""
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -8898,6 +10029,9 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
msgid "The number of times an upload record could not find its file"
msgstr ""
@@ -8925,9 +10059,18 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
msgid "The project is still being deleted. Please try again later."
msgstr ""
@@ -9009,6 +10152,18 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
+msgstr ""
+
msgid "There are no archived projects yet"
msgstr ""
@@ -9042,6 +10197,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error loading users activity calendar."
msgstr ""
@@ -9066,6 +10230,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -9078,6 +10245,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -9090,6 +10260,9 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
@@ -9099,6 +10272,9 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -9117,6 +10293,12 @@ msgstr ""
msgid "This container registry has been scheduled for deletion."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -9147,13 +10329,19 @@ msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -9288,6 +10476,12 @@ msgstr ""
msgid "This will remove the fork relationship to source project"
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -9472,6 +10666,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -9487,6 +10684,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To define internal users, first enable new users set to external"
msgstr ""
@@ -9529,6 +10729,9 @@ msgstr ""
msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -9559,6 +10762,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -9682,12 +10888,27 @@ msgstr ""
msgid "Try again?"
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -9697,15 +10918,30 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "Unable to connect to server: %{error}"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -9727,6 +10963,9 @@ msgstr ""
msgid "Unknown format"
msgstr ""
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlock"
msgstr ""
@@ -9820,6 +11059,9 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
+msgid "Updated"
+msgstr ""
+
msgid "Updating"
msgstr ""
@@ -9862,6 +11104,12 @@ msgstr ""
msgid "Use <code>%{native_redirect_uri}</code> for local tests"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -10000,6 +11248,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -10009,6 +11266,21 @@ msgstr ""
msgid "Users were successfully added."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using required encryption strategy when encrypted field is missing!"
msgstr ""
@@ -10060,6 +11332,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -10096,6 +11371,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -10123,6 +11401,9 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -10138,6 +11419,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -10153,13 +11437,16 @@ msgstr ""
msgid "Webhooks Help"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Wednesday"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -10350,6 +11637,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -10371,7 +11661,7 @@ msgstr ""
msgid "You are attempting to update a file that has changed since you started editing it."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -10383,6 +11673,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -10398,6 +11691,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -10419,6 +11718,12 @@ msgstr ""
msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -10443,9 +11748,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -10473,6 +11784,15 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -10482,6 +11802,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -10509,9 +11835,21 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -10524,6 +11862,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -10578,24 +11919,45 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
@@ -10635,7 +11997,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -10653,6 +12018,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -10713,6 +12081,9 @@ msgstr ""
msgid "commented on %{link_to_project}"
msgstr ""
+msgid "commit %{commit_id}"
+msgstr ""
+
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -10728,6 +12099,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -10849,6 +12223,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -10968,6 +12345,9 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
+msgstr ""
+
msgid "mrWidget|Merge locally"
msgstr ""
@@ -11043,9 +12423,6 @@ msgstr ""
msgid "mrWidget|The source branch will not be deleted"
msgstr ""
-msgid "mrWidget|The target branch has advanced, which invalidates the merge request pipeline. Please update the source branch and retry merging"
-msgstr ""
-
msgid "mrWidget|There are merge conflicts"
msgstr ""
@@ -11097,6 +12474,9 @@ msgstr ""
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -11166,7 +12546,7 @@ msgstr[1] ""
msgid "score"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -11175,6 +12555,9 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
@@ -11226,6 +12609,12 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
diff --git a/locale/gl_ES/gitlab.po b/locale/gl_ES/gitlab.po
index a773d0af51f..8dac79b6133 100644
--- a/locale/gl_ES/gitlab.po
+++ b/locale/gl_ES/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Galician\n"
"Language: gl_ES\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: gl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:39\n"
+"PO-Revision-Date: 2019-06-14 10:26\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr "Estado"
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d exportador"
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] "%d merge request"
msgstr[1] "%d merge requests"
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,37 +1459,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1856,6 +2161,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/he_IL/gitlab.po b/locale/he_IL/gitlab.po
index 6210346cb46..71f4068a5d9 100644
--- a/locale/he_IL/gitlab.po
+++ b/locale/he_IL/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Hebrew\n"
"Language: he_IL\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: he\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:37\n"
+"PO-Revision-Date: 2019-06-14 10:15\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -77,6 +74,13 @@ msgstr[3] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -126,6 +130,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -133,6 +144,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -163,10 +181,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -205,6 +220,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -217,12 +238,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -238,6 +271,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -256,6 +295,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -296,6 +347,9 @@ msgstr[3] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -308,9 +362,31 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -335,6 +411,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -357,14 +436,14 @@ msgstr[2] ""
msgstr[3] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -381,21 +460,21 @@ msgstr[2] ""
msgstr[3] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -425,15 +504,27 @@ msgstr[3] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -443,6 +534,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -473,6 +567,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -509,19 +606,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -551,6 +648,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -596,12 +696,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -638,6 +750,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -659,10 +774,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -671,9 +792,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -683,6 +810,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -695,9 +825,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -710,10 +849,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
+msgstr ""
+
+msgid "AddMember|No users specified."
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -722,10 +864,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -737,6 +888,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -758,6 +912,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -872,6 +1029,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -891,15 +1051,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -972,9 +1141,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -1008,10 +1174,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -1035,21 +1204,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -1065,6 +1249,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1098,7 +1285,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1152,6 +1342,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1209,9 +1402,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1221,6 +1420,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1230,6 +1435,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1248,6 +1456,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1297,12 +1517,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1333,37 +1547,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1381,6 +1595,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1393,12 +1610,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1411,6 +1652,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1426,6 +1670,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1456,6 +1706,16 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1543,15 +1803,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1663,6 +1932,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1765,12 +2058,35 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1786,6 +2102,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1936,6 +2255,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1954,6 +2288,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -2044,9 +2381,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -2068,9 +2411,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2086,6 +2435,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2098,6 +2453,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2122,6 +2486,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2149,6 +2519,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2170,6 +2543,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2200,7 +2576,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2272,16 +2648,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2335,9 +2729,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2392,6 +2795,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2410,7 +2816,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2428,12 +2840,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2449,6 +2873,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2557,6 +2984,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2593,19 +3023,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2638,6 +3059,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2674,6 +3098,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2683,9 +3110,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2749,7 +3173,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2803,40 +3227,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2848,6 +3284,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2857,6 +3296,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2908,9 +3350,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2929,6 +3377,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -3050,6 +3501,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -3077,9 +3531,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3092,9 +3552,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3158,6 +3624,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3203,6 +3672,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3212,6 +3684,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3230,9 +3705,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3248,6 +3720,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3257,6 +3735,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3266,9 +3747,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3302,9 +3789,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3377,6 +3873,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3392,12 +3894,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3416,6 +3933,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3494,15 +4014,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3539,6 +4083,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3590,6 +4137,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3611,6 +4173,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3789,6 +4399,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3843,9 +4456,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3867,6 +4486,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3897,18 +4522,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3921,25 +4570,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3981,6 +4624,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -4017,6 +4663,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -4035,6 +4687,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -4059,9 +4714,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4086,6 +4771,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4122,9 +4810,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4155,12 +4840,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4173,7 +4864,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4185,9 +4879,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4323,18 +5041,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4371,9 +5122,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4383,6 +5140,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4392,6 +5155,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4401,6 +5167,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4434,9 +5206,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4533,6 +5311,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4620,6 +5401,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4629,27 +5431,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4668,6 +5503,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4680,16 +5521,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4704,6 +5557,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4767,7 +5626,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4779,9 +5638,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4864,6 +5720,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4912,6 +5774,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4921,6 +5786,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4945,6 +5813,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4990,6 +5864,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4999,6 +5882,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -5017,6 +5903,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -5047,12 +5936,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5410,6 +6305,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5467,6 +6368,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5476,6 +6380,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5548,6 +6455,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5566,9 +6476,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5644,6 +6563,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5653,6 +6575,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5680,13 +6605,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5698,9 +6626,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5731,9 +6656,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5797,6 +6731,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5866,6 +6803,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5893,6 +6833,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5902,12 +6845,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5917,6 +6863,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5933,6 +6882,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5948,6 +6903,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5957,6 +6918,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -6026,10 +6993,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6110,6 +7086,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6119,6 +7101,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6128,9 +7116,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6182,12 +7179,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6209,12 +7215,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6264,18 +7282,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6285,6 +7327,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6297,6 +7342,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6315,6 +7363,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6390,6 +7444,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6486,6 +7582,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6495,6 +7597,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6519,12 +7624,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6537,6 +7648,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6585,6 +7699,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6601,6 +7718,9 @@ msgstr[3] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6628,6 +7748,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6643,6 +7769,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6661,6 +7793,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6673,6 +7808,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6694,6 +7832,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6769,6 +7913,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6785,6 +7932,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6815,6 +7965,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6836,6 +7989,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6854,6 +8010,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6878,12 +8037,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6944,6 +8112,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6956,6 +8133,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6980,6 +8166,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -7010,6 +8199,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -7022,15 +8214,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -7040,12 +8226,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -7064,6 +8244,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -7082,6 +8286,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7094,6 +8301,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7127,7 +8337,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7142,6 +8352,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7157,6 +8373,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7196,9 +8415,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7244,9 +8460,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7271,9 +8499,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7292,7 +8517,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7301,6 +8526,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7322,6 +8556,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7382,6 +8628,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7394,6 +8658,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7491,6 +8758,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7515,6 +8785,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7545,6 +8818,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7554,12 +8833,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7575,6 +8863,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7599,6 +8890,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7620,9 +8914,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7638,6 +8929,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7665,6 +8959,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7713,6 +9013,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7728,6 +9031,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7737,6 +9046,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7791,6 +9103,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7806,6 +9121,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7821,7 +9142,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7846,13 +9173,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7870,6 +9197,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7915,6 +9245,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7939,9 +9275,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7963,6 +9296,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7972,6 +9308,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7999,6 +9341,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -8020,9 +9365,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -8035,7 +9392,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -8062,6 +9419,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -8083,12 +9443,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8167,6 +9542,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8176,10 +9554,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8200,6 +9581,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8260,6 +9644,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8290,6 +9677,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8299,12 +9695,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8335,6 +9749,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8347,6 +9764,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8368,7 +9794,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8386,12 +9812,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8407,12 +9887,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8440,15 +9926,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8479,6 +9974,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8500,6 +9998,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8512,6 +10013,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8539,6 +10043,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8548,9 +10064,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8560,18 +10082,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8590,9 +10127,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8608,13 +10142,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8629,6 +10166,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8650,6 +10190,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8743,6 +10286,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8788,6 +10334,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8839,6 +10388,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8848,18 +10415,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8869,12 +10478,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -9031,6 +10700,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -9049,16 +10727,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -9067,18 +10751,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9127,9 +10817,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9154,12 +10850,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9184,15 +10922,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9209,24 +10956,45 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9251,6 +11019,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9263,6 +11034,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9272,7 +11046,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9281,25 +11058,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9314,6 +11103,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9344,6 +11151,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9353,7 +11163,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9368,6 +11178,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9407,12 +11220,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9467,6 +11274,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9481,6 +11294,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9520,6 +11336,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9562,6 +11387,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9602,6 +11430,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9686,6 +11520,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9695,6 +11532,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9710,6 +11550,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9722,6 +11565,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9782,9 +11628,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9806,6 +11664,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9881,9 +11742,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9914,12 +11772,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9932,6 +11802,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9959,6 +11835,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9995,6 +11874,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -10076,6 +11958,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10106,19 +11991,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10136,6 +12024,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10157,6 +12048,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10184,6 +12078,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10199,6 +12105,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10211,9 +12120,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10229,9 +12147,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10287,12 +12202,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10302,6 +12235,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10311,6 +12247,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10380,6 +12319,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10398,6 +12340,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10422,7 +12367,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10434,6 +12379,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10494,6 +12442,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10548,6 +12499,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10620,6 +12577,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10644,6 +12604,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10674,6 +12637,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10734,12 +12703,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10770,6 +12745,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10842,6 +12820,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10866,6 +12847,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10878,6 +12922,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10908,18 +12958,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -11001,6 +13063,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -11013,6 +13078,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -11028,6 +13096,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -11068,6 +13163,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -11083,6 +13181,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11140,6 +13241,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11158,6 +13268,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11182,9 +13298,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11194,6 +13322,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11203,6 +13334,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11242,6 +13376,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11263,15 +13400,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11305,9 +13457,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11323,6 +13490,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11341,6 +13514,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11353,6 +13529,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11365,18 +13544,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11401,6 +13592,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11413,6 +13610,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11422,22 +13622,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11509,12 +13718,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11587,6 +13790,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11775,6 +13984,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11790,6 +14002,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11856,6 +14071,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11892,6 +14110,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11904,9 +14125,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11916,6 +14143,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11958,6 +14188,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -12009,15 +14275,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -12027,24 +14308,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -12063,18 +14362,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12144,6 +14458,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12195,6 +14521,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12204,6 +14533,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12222,6 +14554,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12231,6 +14611,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12288,6 +14674,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12303,6 +14692,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12378,6 +14902,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12393,9 +14926,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12441,12 +14992,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12456,6 +15013,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12465,6 +15025,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12492,6 +15055,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12519,6 +15085,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12561,6 +15154,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12579,6 +15175,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12588,6 +15187,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12609,6 +15211,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12618,13 +15223,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12640,6 +15248,9 @@ msgstr[3] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12820,6 +15431,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12835,7 +15449,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12847,6 +15467,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12862,6 +15485,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12880,6 +15509,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12904,9 +15542,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12937,12 +15581,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12952,6 +15605,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12982,6 +15641,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12994,6 +15662,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -13006,6 +15677,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -13039,6 +15713,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -13060,27 +15737,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -13114,7 +15815,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13132,6 +15836,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13165,10 +15872,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
msgstr ""
-msgid "at"
+msgid "already shared with this group"
+msgstr ""
+
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13183,6 +15893,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13288,6 +16013,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13321,9 +16049,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13339,12 +16064,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13467,9 +16186,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13489,10 +16205,10 @@ msgstr[3] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13534,6 +16250,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13570,9 +16289,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13585,6 +16310,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13609,6 +16340,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13640,6 +16374,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13649,6 +16389,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13667,6 +16410,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13695,6 +16441,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13722,7 +16471,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13737,6 +16486,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13791,6 +16543,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13809,18 +16564,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13851,26 +16603,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13955,15 +16693,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -14083,7 +16836,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -14092,18 +16845,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -14137,12 +16902,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/hi_IN/gitlab.po b/locale/hi_IN/gitlab.po
index b7ea475b90a..3a647e7b861 100644
--- a/locale/hi_IN/gitlab.po
+++ b/locale/hi_IN/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Hindi\n"
"Language: hi_IN\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: hi\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:34\n"
+"PO-Revision-Date: 2019-06-14 10:18\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,37 +1459,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1856,6 +2161,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/hr_HR/gitlab.po b/locale/hr_HR/gitlab.po
index 5fe10132d71..316cab67e8b 100644
--- a/locale/hr_HR/gitlab.po
+++ b/locale/hr_HR/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Croatian\n"
"Language: hr_HR\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: hr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:37\n"
+"PO-Revision-Date: 2019-06-14 10:24\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -72,6 +69,12 @@ msgstr[2] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -114,12 +117,24 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -147,10 +162,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -186,6 +198,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -198,12 +216,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -219,6 +249,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -237,6 +273,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -273,6 +321,9 @@ msgstr[2] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -285,9 +336,30 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -312,6 +384,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -331,13 +406,13 @@ msgstr[1] ""
msgstr[2] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -352,19 +427,19 @@ msgstr[1] ""
msgstr[2] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -390,15 +465,27 @@ msgstr[2] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -408,6 +495,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -438,6 +528,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -474,19 +567,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -516,6 +609,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -561,12 +657,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -603,6 +711,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -624,10 +735,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -636,9 +753,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -648,6 +771,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -660,9 +786,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -675,10 +810,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
+msgstr ""
+
+msgid "AddMember|No users specified."
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -687,10 +825,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -702,6 +849,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -723,6 +873,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -837,6 +990,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -855,15 +1011,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -936,9 +1101,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -972,10 +1134,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -999,21 +1164,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -1029,6 +1209,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1062,7 +1245,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1116,6 +1302,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1173,9 +1362,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1185,6 +1380,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1194,6 +1395,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1212,6 +1416,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1257,12 +1473,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1293,37 +1503,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1341,6 +1551,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1353,12 +1566,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1371,6 +1608,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1386,6 +1626,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1416,6 +1662,15 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1503,15 +1758,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1623,6 +1887,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1725,12 +2013,33 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1746,6 +2055,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1896,6 +2208,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1914,6 +2241,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -2004,9 +2334,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -2028,9 +2364,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2046,6 +2388,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2058,6 +2406,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2082,6 +2439,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2109,6 +2472,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2130,6 +2496,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2160,7 +2529,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2232,16 +2601,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2295,9 +2682,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2352,6 +2748,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2370,7 +2769,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2388,12 +2793,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2409,6 +2826,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2517,6 +2937,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2553,19 +2976,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2598,6 +3012,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2634,6 +3051,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2643,9 +3063,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2709,7 +3126,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2763,40 +3180,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2808,6 +3237,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2817,6 +3249,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2868,9 +3303,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2889,6 +3330,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -3009,6 +3453,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -3036,9 +3483,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3051,9 +3504,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3117,6 +3576,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3162,6 +3624,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3171,6 +3636,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3189,9 +3657,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3207,6 +3672,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3216,6 +3687,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3225,9 +3699,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3261,9 +3741,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3336,6 +3825,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3351,12 +3846,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3375,6 +3885,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3453,15 +3966,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3498,6 +4035,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3549,6 +4089,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3570,6 +4125,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3747,6 +4350,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3801,9 +4407,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3825,6 +4437,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3855,18 +4473,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3879,25 +4521,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3939,6 +4575,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3975,6 +4614,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3993,6 +4638,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -4017,9 +4665,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4044,6 +4722,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4080,9 +4761,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4113,12 +4791,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4131,7 +4815,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4143,9 +4830,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4281,18 +4992,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4329,9 +5073,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4341,6 +5091,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4350,6 +5106,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4359,6 +5118,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4392,9 +5157,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4491,6 +5262,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4578,6 +5352,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4587,27 +5382,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4626,6 +5454,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4638,16 +5472,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4662,6 +5508,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4725,7 +5577,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4737,9 +5589,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4821,6 +5670,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4869,6 +5724,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4878,6 +5736,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4902,6 +5763,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4947,6 +5814,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4956,6 +5832,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4974,6 +5853,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -5004,12 +5886,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5367,6 +6255,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5424,6 +6318,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5433,6 +6330,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5505,6 +6405,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5523,9 +6426,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5601,6 +6513,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5610,6 +6525,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5637,13 +6555,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5655,9 +6576,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5688,9 +6606,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5754,6 +6681,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5823,6 +6753,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5850,6 +6783,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5859,12 +6795,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5874,6 +6813,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5889,6 +6831,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5904,6 +6852,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5913,6 +6867,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5982,10 +6942,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6066,6 +7035,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6075,6 +7050,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6084,9 +7065,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6138,12 +7128,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6165,12 +7164,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6219,18 +7230,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6240,6 +7275,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6252,6 +7290,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6270,6 +7311,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6345,6 +7392,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6441,6 +7530,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6450,6 +7545,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6474,12 +7572,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6492,6 +7596,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6540,6 +7647,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6555,6 +7665,9 @@ msgstr[2] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6582,6 +7695,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6597,6 +7716,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6615,6 +7740,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6627,6 +7755,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6648,6 +7779,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6723,6 +7860,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6738,6 +7878,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6768,6 +7911,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6789,6 +7935,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6807,6 +7956,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6831,12 +7983,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6897,6 +8058,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6909,6 +8079,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6933,6 +8112,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6963,6 +8145,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6975,15 +8160,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6993,12 +8172,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -7017,6 +8190,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -7035,6 +8232,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7047,6 +8247,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7080,7 +8283,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7095,6 +8298,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7110,6 +8319,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7149,9 +8361,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7197,9 +8406,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7224,9 +8445,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7245,7 +8463,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7254,6 +8472,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7275,6 +8502,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7335,6 +8574,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7347,6 +8604,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7443,6 +8703,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7467,6 +8730,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7497,6 +8763,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7506,12 +8778,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7527,6 +8808,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7551,6 +8835,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7572,9 +8859,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7590,6 +8874,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7617,6 +8904,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7665,6 +8958,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7680,6 +8976,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7689,6 +8991,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7743,6 +9048,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7758,6 +9066,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7773,7 +9087,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7797,13 +9117,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7821,6 +9141,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7866,6 +9189,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7890,9 +9219,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7914,6 +9240,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7923,6 +9252,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7950,6 +9285,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7971,9 +9309,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7986,7 +9336,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -8013,6 +9363,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -8034,12 +9387,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8118,6 +9486,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8127,10 +9498,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgstr ""
+
+msgid "Pipelines| to purchase more minutes."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8151,6 +9525,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8211,6 +9588,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8241,6 +9621,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8250,12 +9639,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8286,6 +9693,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8298,6 +9708,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8319,7 +9738,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8337,12 +9756,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8358,12 +9831,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8391,15 +9870,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8430,6 +9918,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8451,6 +9942,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8463,6 +9957,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8490,6 +9987,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8499,9 +10008,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8511,18 +10026,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8541,9 +10071,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8559,13 +10086,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8580,6 +10110,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8601,6 +10134,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8694,6 +10230,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8739,6 +10278,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8790,6 +10332,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8799,18 +10359,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8820,12 +10422,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8982,6 +10644,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -9000,16 +10671,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -9018,18 +10695,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9078,9 +10761,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9105,12 +10794,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9135,15 +10866,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9159,24 +10899,45 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9201,6 +10962,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9213,6 +10977,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9222,7 +10989,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9231,25 +11001,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9264,6 +11046,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9294,6 +11094,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9303,7 +11106,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9318,6 +11121,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9357,12 +11163,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9417,6 +11217,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9429,6 +11235,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9468,6 +11277,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9510,6 +11328,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9549,6 +11370,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9633,6 +11460,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9642,6 +11472,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9657,6 +11490,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9669,6 +11505,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9729,9 +11568,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9753,6 +11604,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9828,9 +11682,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9861,12 +11712,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9879,6 +11742,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9906,6 +11775,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9942,6 +11814,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -10023,6 +11898,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10053,19 +11931,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10083,6 +11964,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10104,6 +11988,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10131,6 +12018,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10146,6 +12045,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10158,9 +12060,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10176,9 +12087,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10233,12 +12141,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10248,6 +12174,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10257,6 +12186,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10326,6 +12258,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10344,6 +12279,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10368,7 +12306,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10380,6 +12318,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10440,6 +12381,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10494,6 +12438,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10566,6 +12516,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10590,6 +12543,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10620,6 +12576,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10680,12 +12642,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10716,6 +12684,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10788,6 +12759,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10812,6 +12786,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10824,6 +12861,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10854,18 +12897,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10947,6 +13002,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10959,6 +13017,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10974,6 +13035,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -11013,6 +13101,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -11028,6 +13119,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11085,6 +13179,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11103,6 +13206,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11127,9 +13236,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11139,6 +13260,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11148,6 +13272,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11187,6 +13314,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11208,15 +13338,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11250,9 +13395,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11268,6 +13428,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11286,6 +13452,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11298,6 +13467,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11310,18 +13482,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11346,6 +13530,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11358,6 +13548,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11367,22 +13560,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11454,12 +13656,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11532,6 +13728,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11718,6 +13920,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11733,6 +13938,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11799,6 +14007,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11835,6 +14046,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11847,9 +14061,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11859,6 +14079,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11901,6 +14124,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11952,15 +14211,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11970,24 +14244,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -12006,18 +14298,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12087,6 +14394,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12138,6 +14457,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12147,6 +14469,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12165,6 +14490,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12174,6 +14547,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12231,6 +14610,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12246,6 +14628,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12321,6 +14838,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12336,9 +14862,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12384,12 +14928,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12399,6 +14949,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12408,6 +14961,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12435,6 +14991,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12462,6 +15021,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12504,6 +15090,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12522,6 +15111,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12531,6 +15123,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12552,6 +15147,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12561,13 +15159,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12582,6 +15183,9 @@ msgstr[2] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12762,6 +15366,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12777,7 +15384,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12789,6 +15402,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12804,6 +15420,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12822,6 +15444,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12846,9 +15477,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12879,12 +15516,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12894,6 +15540,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12924,6 +15576,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12936,6 +15597,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12948,6 +15612,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12981,6 +15648,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -13002,27 +15672,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -13056,7 +15750,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13074,6 +15771,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13107,10 +15807,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13125,6 +15828,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13224,6 +15942,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13257,9 +15978,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13275,12 +15993,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13401,9 +16113,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13422,10 +16131,10 @@ msgstr[2] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13467,6 +16176,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13500,9 +16212,15 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13515,6 +16233,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13539,6 +16263,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13569,6 +16296,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13578,6 +16311,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13596,6 +16332,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13623,6 +16362,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13650,7 +16392,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13665,6 +16407,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13719,6 +16464,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13737,18 +16485,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13779,24 +16524,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13881,15 +16614,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -14004,7 +16752,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -14013,18 +16761,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -14058,12 +16818,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/hu_HU/gitlab.po b/locale/hu_HU/gitlab.po
index b702cb701c6..d6f224c306e 100644
--- a/locale/hu_HU/gitlab.po
+++ b/locale/hu_HU/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Hungarian\n"
"Language: hu_HU\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: hu\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:31\n"
+"PO-Revision-Date: 2019-06-14 10:12\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,37 +1459,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1856,6 +2161,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/id_ID/gitlab.po b/locale/id_ID/gitlab.po
index e3f45e5a4f1..2775a4148b7 100644
--- a/locale/id_ID/gitlab.po
+++ b/locale/id_ID/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Indonesian\n"
"Language: id_ID\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: id\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:34\n"
+"PO-Revision-Date: 2019-06-14 10:12\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -62,6 +59,10 @@ msgstr[0] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -90,10 +91,18 @@ msgid "%d merge request"
msgid_plural "%d merge requests"
msgstr[0] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -115,10 +124,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -148,6 +154,12 @@ msgid "%{count} pending comment"
msgid_plural "%{count} pending comments"
msgstr[0] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -160,12 +172,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -181,6 +205,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -199,6 +229,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -227,6 +269,9 @@ msgstr[0] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -239,9 +284,28 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -266,6 +330,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -279,11 +346,11 @@ msgid_plural "%d Days"
msgstr[0] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgid "1 day"
@@ -294,15 +361,15 @@ msgid_plural "%d groups"
msgstr[0] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgid "1 pipeline"
@@ -320,15 +387,27 @@ msgstr[0] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -338,6 +417,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -368,6 +450,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -404,19 +489,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -446,6 +531,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -491,12 +579,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -533,6 +633,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -554,10 +657,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -566,9 +675,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -578,6 +693,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -590,9 +708,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -605,10 +732,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -617,10 +747,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -632,6 +771,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -653,6 +795,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -767,6 +912,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -783,15 +931,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -864,9 +1021,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -900,10 +1054,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -927,21 +1084,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -957,6 +1129,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -990,7 +1165,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1044,6 +1222,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1101,9 +1282,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1113,6 +1300,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1122,6 +1315,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1140,6 +1336,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1177,12 +1385,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1213,37 +1415,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1261,6 +1463,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1273,12 +1478,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1291,6 +1520,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1306,6 +1538,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1336,6 +1574,13 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1423,15 +1668,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1543,6 +1797,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1645,12 +1923,29 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1666,6 +1961,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1816,6 +2114,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1834,6 +2147,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1924,9 +2240,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1948,9 +2270,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -1966,6 +2294,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -1978,6 +2312,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2002,6 +2345,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2029,6 +2378,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2050,6 +2402,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2080,7 +2435,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2152,16 +2507,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2215,9 +2588,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2272,6 +2654,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2290,7 +2675,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2308,12 +2699,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2329,6 +2732,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2437,6 +2843,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2473,19 +2882,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2518,6 +2918,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2554,6 +2957,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2563,9 +2969,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2629,7 +3032,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2683,40 +3086,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2728,6 +3143,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2737,6 +3155,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2788,9 +3209,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2809,6 +3236,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2927,6 +3357,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2954,9 +3387,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -2969,9 +3408,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3035,6 +3480,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3080,6 +3528,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3089,6 +3540,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3107,9 +3561,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3125,6 +3576,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3134,6 +3591,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3143,9 +3603,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3179,9 +3645,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3254,6 +3729,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3269,12 +3750,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3293,6 +3789,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3371,15 +3870,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3416,6 +3939,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3467,6 +3993,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3488,6 +4029,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3663,6 +4252,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3717,9 +4309,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3741,6 +4339,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3771,18 +4375,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3795,25 +4423,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3855,6 +4477,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3891,6 +4516,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3909,6 +4540,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3933,9 +4567,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -3960,6 +4624,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -3996,9 +4663,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4029,12 +4693,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4047,7 +4717,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4059,9 +4732,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4197,18 +4894,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4245,9 +4975,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4257,6 +4993,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4266,6 +5008,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4275,6 +5020,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4308,9 +5059,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4407,6 +5164,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4494,6 +5254,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4503,27 +5284,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4542,6 +5356,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4554,16 +5374,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
+msgstr ""
+
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4578,6 +5410,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4641,7 +5479,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4653,9 +5491,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4735,6 +5570,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4783,6 +5624,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4792,6 +5636,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4816,6 +5663,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4861,6 +5714,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4870,6 +5732,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4888,6 +5753,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4918,12 +5786,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5281,6 +6155,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5338,6 +6218,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5347,6 +6230,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5419,6 +6305,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5437,9 +6326,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5515,6 +6413,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5524,6 +6425,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5551,13 +6455,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5569,9 +6476,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5602,9 +6506,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5668,6 +6581,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5737,6 +6653,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5764,6 +6683,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5773,12 +6695,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5788,6 +6713,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5801,6 +6729,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5816,6 +6750,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5825,6 +6765,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5894,10 +6840,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -5978,6 +6933,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -5987,6 +6948,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -5996,9 +6963,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6050,12 +7026,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6077,12 +7062,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6129,18 +7126,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6150,6 +7171,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6162,6 +7186,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6180,6 +7207,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6255,6 +7288,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6351,6 +7426,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6360,6 +7441,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6384,12 +7468,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6402,6 +7492,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6450,6 +7543,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6463,6 +7559,9 @@ msgstr[0] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6490,6 +7589,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6505,6 +7610,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6523,6 +7634,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6535,6 +7649,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6556,6 +7673,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6631,6 +7754,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6644,6 +7770,9 @@ msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6674,6 +7803,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6695,6 +7827,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6713,6 +7848,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6737,12 +7875,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6803,6 +7950,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6815,6 +7971,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6839,6 +8004,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6869,6 +8037,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6881,15 +8052,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6899,12 +8064,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6923,6 +8082,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6941,6 +8124,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -6953,6 +8139,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -6986,7 +8175,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7001,6 +8190,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7016,6 +8211,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7055,9 +8253,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7103,9 +8298,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7130,9 +8337,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7151,7 +8355,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7160,6 +8364,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7181,6 +8394,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7241,6 +8466,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7253,6 +8496,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7347,6 +8593,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7371,6 +8620,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7401,6 +8653,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7410,12 +8668,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7431,6 +8698,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7455,6 +8725,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7476,9 +8749,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7494,6 +8764,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7521,6 +8794,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7569,6 +8848,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7584,6 +8866,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7593,6 +8881,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7647,6 +8938,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7662,6 +8956,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7677,7 +8977,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7699,13 +9005,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7723,6 +9029,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7768,6 +9077,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7792,9 +9107,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7816,6 +9128,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7825,6 +9140,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7852,6 +9173,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7873,9 +9197,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7888,7 +9224,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7915,6 +9251,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7936,12 +9275,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8020,6 +9374,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8029,10 +9386,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8053,6 +9413,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8113,6 +9476,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8143,6 +9509,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8152,12 +9527,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8188,6 +9581,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8200,6 +9596,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8221,7 +9626,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8239,12 +9644,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8260,12 +9719,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8293,15 +9758,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8332,6 +9806,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8353,6 +9830,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8365,6 +9845,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8392,6 +9875,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8401,9 +9896,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8413,18 +9914,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8443,9 +9959,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8461,13 +9974,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8482,6 +9998,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8503,6 +10022,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8596,6 +10118,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8641,6 +10166,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8692,6 +10220,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8701,18 +10247,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8722,12 +10310,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8884,6 +10532,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8902,16 +10559,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8920,18 +10583,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -8980,9 +10649,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9007,12 +10682,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9037,15 +10754,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9059,24 +10785,45 @@ msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9101,6 +10848,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9113,6 +10863,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9122,7 +10875,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9131,25 +10887,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9164,6 +10932,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9194,6 +10980,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9203,7 +10992,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9218,6 +11007,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9257,12 +11049,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9317,6 +11103,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9325,6 +11117,9 @@ msgid "Requires approval."
msgid_plural "Requires %d more approvals."
msgstr[0] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9364,6 +11159,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9406,6 +11210,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9443,6 +11250,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9527,6 +11340,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9536,6 +11352,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9551,6 +11370,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9563,6 +11385,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9623,9 +11448,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9647,6 +11484,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9722,9 +11562,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9755,12 +11592,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9773,6 +11622,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9800,6 +11655,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9836,6 +11694,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9917,6 +11778,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -9947,19 +11811,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -9977,6 +11844,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -9998,6 +11868,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10025,6 +11898,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10040,6 +11925,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10052,9 +11940,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10070,9 +11967,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10125,12 +12019,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10140,6 +12052,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10149,6 +12064,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10218,6 +12136,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10236,6 +12157,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10260,7 +12184,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10272,6 +12196,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10332,6 +12259,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10386,6 +12316,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10458,6 +12394,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10482,6 +12421,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10512,6 +12454,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10572,12 +12520,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10608,6 +12562,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10680,6 +12637,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10704,6 +12664,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10716,6 +12739,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10746,18 +12775,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10839,6 +12880,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10851,6 +12895,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10866,6 +12913,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10903,6 +12977,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10918,6 +12995,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -10975,6 +13055,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -10993,6 +13082,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11017,9 +13112,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11029,6 +13136,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11038,6 +13148,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11077,6 +13190,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11098,15 +13214,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11140,9 +13271,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11158,6 +13304,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11176,6 +13328,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11188,6 +13343,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11200,18 +13358,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11236,6 +13406,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11248,6 +13424,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11257,22 +13436,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11344,12 +13532,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11422,6 +13604,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11604,6 +13792,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11619,6 +13810,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11685,6 +13879,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11721,6 +13918,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11733,9 +13933,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11745,6 +13951,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11787,6 +13996,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11838,15 +14083,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11856,24 +14116,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11892,18 +14170,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -11973,6 +14266,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12024,6 +14329,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12033,6 +14341,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12051,6 +14362,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12060,6 +14419,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12117,6 +14482,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12132,6 +14500,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12207,6 +14710,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12222,9 +14734,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12270,12 +14800,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12285,6 +14821,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12294,6 +14833,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12321,6 +14863,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12348,6 +14893,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12390,6 +14962,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12408,6 +14983,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12417,6 +14995,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12438,6 +15019,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12447,13 +15031,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12466,6 +15053,9 @@ msgstr[0] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12646,6 +15236,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12661,7 +15254,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12673,6 +15272,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12688,6 +15290,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12706,6 +15314,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12730,9 +15347,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12763,12 +15386,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12778,6 +15410,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12808,6 +15446,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12820,6 +15467,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12832,6 +15482,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12865,6 +15518,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12886,27 +15542,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12940,7 +15620,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -12958,6 +15641,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -12991,10 +15677,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13009,6 +15698,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13096,6 +15800,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13129,9 +15836,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13147,12 +15851,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13269,9 +15967,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13288,10 +15983,10 @@ msgstr[0] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13333,6 +16028,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13360,9 +16058,15 @@ msgid "draft"
msgid_plural "drafts"
msgstr[0] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13375,6 +16079,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13399,6 +16109,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13427,6 +16140,12 @@ msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13436,6 +16155,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13454,6 +16176,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13479,6 +16204,9 @@ msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13506,7 +16234,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13521,6 +16249,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13575,6 +16306,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13593,18 +16327,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13635,20 +16366,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13733,15 +16456,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13846,7 +16584,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13855,18 +16593,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13900,12 +16650,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po
index 3a8b10706bc..dc749104ecb 100644
--- a/locale/it/gitlab.po
+++ b/locale/it/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Italian\n"
"Language: it_IT\n"
"MIME-Version: 1.0\n"
@@ -13,19 +13,16 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: it\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:28\n"
+"PO-Revision-Date: 2019-06-14 10:12\n"
msgid " Please sign in."
-msgstr ""
-
-msgid " Status"
-msgstr " Stato"
+msgstr " Per favore effettua il login."
msgid " Try to %{action} this file again."
-msgstr ""
+msgstr " Provare a %{action} di nuovo questo file."
msgid " You need to do this before %{grace_period_deadline}."
-msgstr ""
+msgstr " Devi farlo prima di %{grace_period_deadline}."
msgid " and"
msgstr " e"
@@ -41,18 +38,18 @@ msgstr[0] " migliorato di %d punto"
msgstr[1] " migliorato di %d punti"
msgid " or "
-msgstr ""
+msgstr " o "
msgid " or <#epic id>"
-msgstr ""
+msgstr " o <#epic id>"
msgid " or <#issue id>"
-msgstr ""
+msgstr " o <#issue id>"
msgid "%d comment"
msgid_plural "%d comments"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d commento"
+msgstr[1] "%d commenti"
msgid "%d commit"
msgid_plural "%d commits"
@@ -65,7 +62,12 @@ msgstr[0] "%d commit indietro"
msgstr[1] "%d commit indietro"
msgid "%d commits"
-msgstr ""
+msgstr "%d commit"
+
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -89,8 +91,8 @@ msgstr[1] "%d issue"
msgid "%d issue selected"
msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d problema selezionato"
+msgstr[1] "%d problemi selezionati"
msgid "%d layer"
msgid_plural "%d layers"
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] "%d richiesta di merge"
msgstr[1] "%d richieste di merge"
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d metrica"
msgstr[1] "%d metriche"
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] "%d modifica in stage"
@@ -131,31 +143,28 @@ msgstr "Discussione di %{authorsName}"
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} fatto %{commit_timeago}"
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
-msgid "%{count} %{alerts}"
-msgstr "%{count}%{alerts}"
-
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
msgstr[0] ""
msgstr[1] ""
msgid "%{count} approvals from %{name}"
-msgstr ""
+msgstr "%{count} approvazioni da %{name}"
msgid "%{count} more"
-msgstr ""
+msgstr "%{count} altro"
msgid "%{count} more assignees"
msgstr "%{count} altri assegnatari"
msgid "%{count} of %{required} approvals from %{name}"
-msgstr ""
+msgstr "%{count} su %{required} approvazioni da %{name}"
msgid "%{count} of %{total}"
-msgstr ""
+msgstr "%{count} aperti su %{total}"
msgid "%{count} participant"
msgid_plural "%{count} participants"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] "%{count} commento in attesa"
msgstr[1] "%{count} commenti in attesa"
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr "%{filePath} eliminato"
@@ -174,23 +189,35 @@ msgid "%{firstLabel} +%{labelCount} more"
msgstr "%{firstLabel} + %{labelCount} più"
msgid "%{gitlab_ci_yml} not found in this commit"
-msgstr ""
+msgstr "%{gitlab_ci_yml} non trovato in questo commit"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "I %{group_docs_link_start}Gruppi%{group_docs_link_end} consentono di gestire e collaborare in vari progetti. I membri di un gruppo hanno accesso a tutti i suoi progetti."
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} sarà rimosso! Sei sicuro?"
msgid "%{label_for_message} unavailable"
+msgstr "%{label_for_message} non disponibile"
+
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
msgstr ""
-msgid "%{level_name} visibility has been restricted by the administrator."
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
msgstr ""
-msgid "%{link_start}Read more%{link_end} about role permissions"
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
+msgid "%{level_name} visibility has been restricted by the administrator."
+msgstr "la visibilità %{level_name} è stata limitata dall'amministratore."
+
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr "%{link_start}Leggi di più%{link_end} sulle autorizzazioni di ruolo"
+
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Partito"
@@ -198,6 +225,12 @@ msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} è bloccato dall'utente GitLab %{lock_user_id}"
msgid "%{mrText}, this issue will be closed automatically."
+msgstr "%{mrText}, questo issue verrà chiuso automaticamente."
+
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
msgstr ""
msgid "%{name}'s avatar"
@@ -213,86 +246,124 @@ msgid "%{percent}%% complete"
msgstr "%{percent}%% completato"
msgid "%{service_title} activated."
-msgstr ""
+msgstr "%{service_title} attivato."
msgid "%{service_title} settings saved, but not activated."
+msgstr "le impostazioni di %{service_title} sono state salvate, ma non attivate."
+
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
msgstr ""
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
msgid "%{state} epics"
-msgstr ""
+msgstr "%{state} epici"
msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{strong_start}%{branch_count}%{strong_end} branch"
+msgstr[1] "%{strong_start}%{branch_count}%{strong_end} branch"
msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgstr[1] "%{strong_start}%{commit_count}%{strong_end} Commit"
msgid "%{strong_start}%{human_size}%{strong_end} Files"
-msgstr ""
+msgstr "%{strong_start}%{human_size}%{strong_end} File"
msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgstr[1] "%{strong_start}%{tag_count}%{strong_end} Tag"
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{text}%{files}"
+msgstr[1] "%{text}%{files} file"
msgid "%{text} is available"
msgstr "%{text} è disponibile"
-msgid "%{title} changes"
+msgid "%{title} %{operator} %{threshold}"
msgstr ""
+msgid "%{title} changes"
+msgstr "%{title} cambiamenti"
+
msgid "%{unstaged} unstaged and %{staged} staged changes"
-msgstr ""
+msgstr "%{unstaged} cambiamenti unstaged e %{staged} staged"
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
-msgstr ""
+msgstr "%{usage_ping_link_start}scopri di più%{usage_ping_link_end} riguardo a quale informazione è condivisa con GitLab Inc."
msgid "%{user_name} profile page"
+msgstr "Pagina profilo di %{user_name}"
+
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
msgstr ""
msgid "(No changes)"
msgstr ""
-msgid "(external source)"
+msgid "(check progress)"
msgstr ""
+msgid "(external source)"
+msgstr "(fonte esterna)"
+
msgid "+ %{count} more"
-msgstr ""
+msgstr "+ %{count} ulteriori"
msgid "+ %{moreCount} more"
msgstr "+ %{moreCount} più"
msgid "+%{extraOptionCount} more"
-msgstr ""
+msgstr "+%{extraOptionCount} ulteriori"
msgid ", or "
-msgstr ""
+msgstr ", o "
msgid "- Runner is active and can process any new jobs"
-msgstr ""
+msgstr "- Il runner è attivo e può processare nuovi lavori"
msgid "- Runner is paused and will not receive any new jobs"
-msgstr ""
+msgstr "- Il runner è in pausa e non riceverà nuovi lavori"
msgid "- show less"
msgstr "- riduci"
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 %{type} inserimento"
+msgstr[1] "%{count} %{type} inserimenti"
msgid "1 %{type} modification"
msgid_plural "%{count} %{type} modifications"
@@ -305,37 +376,37 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 day"
-msgstr ""
+msgstr "1 giorno"
msgid "1 group"
msgid_plural "%d groups"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 gruppo"
+msgstr[1] "%d gruppi"
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
-msgstr[0] ""
-msgstr[1] ""
+msgid_plural "%{issues} open issues"
+msgstr[0] "1 issue aperto"
+msgstr[1] "%{issues} issue aperti"
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] "1 richiesta di merge aperta"
+msgstr[1] "%{merge_requests} richieste di merge aperte"
msgid "1 pipeline"
msgid_plural "%d pipelines"
@@ -344,65 +415,83 @@ msgstr[1] "%d pipeline"
msgid "1 role"
msgid_plural "%d roles"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 ruolo"
+msgstr[1] "%d ruoli"
msgid "1 user"
msgid_plural "%d users"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 utente"
+msgstr[1] "%d utenti"
msgid "1 week"
+msgstr "1 settimana"
+
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
msgstr ""
msgid "1st contribution!"
msgstr "Primo contributo!"
-msgid "2FA"
+msgid "20-29 contributions"
msgstr ""
+msgid "2FA"
+msgstr "2FA"
+
msgid "2FA enabled"
msgstr "2FA abilitata"
-msgid "3 days"
+msgid "2FADevice|Registered On"
msgstr ""
+msgid "3 days"
+msgstr "3 giorni"
+
msgid "3 hours"
-msgstr ""
+msgstr "3 ore"
msgid "30 minutes"
+msgstr "30 minuti"
+
+msgid "30+ contributions"
msgstr ""
msgid "403|Please contact your GitLab administrator to get permission."
-msgstr ""
+msgstr "403|Contatta l'amministratore di GitLab per ottenere l'autorizzazione."
msgid "403|You don't have the permission to access this page."
-msgstr ""
+msgstr "403|Non hai i permessi per accedere a questa pagina."
msgid "404|Make sure the address is correct and the page hasn't moved."
-msgstr ""
+msgstr "404|Assicurarsi che l'indirizzo sia corretto e che la pagina non sia stata spostata."
msgid "404|Page Not Found"
-msgstr ""
+msgstr "404|Pagina non trovata"
msgid "404|Please contact your GitLab administrator if you think this is a mistake."
-msgstr ""
+msgstr "404 | Si prega di contattare il proprio amministratore GitLab se credi sia un errore."
msgid "8 hours"
-msgstr ""
+msgstr "8 ore"
msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> aggiungerà \"Da <a href=\"#\">@johnsmith</a>\"per tutti gli issue e i commenti creati originariamente da johnsmith@example.com, e imposterà <a href=\"#\">@johnsmith</a> come assegnatario su tutti gli issue originariamente assegnati a johnsmith@example.com."
msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"John Smith\"</code> aggiungerà \"Da John Smith\" per tutti i problemi e i commenti creati originariamente da johnsmith@example.com."
msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> Aggiungerà \"Da johnsm...@example.com\"per tutti i problemi e i commenti creati originariamente da johnsmith@example.com. L'indirizzo email o il nome utente sono mascherati per garantire la privacy dell'utente."
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
-msgstr ""
+msgid "A default branch cannot be chosen for an empty project."
+msgstr "Un ramo predefinito non può essere scelto per un progetto vuoto."
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr "Account"
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,18 +714,27 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
-msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
+msgid "Add email address"
msgstr ""
+msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
+msgstr "Aggiungi intestazione e footer alle e-mail. Le impostazioni dei colori verranno applicate solo nell'interfaccia dell'applicazione"
+
msgid "Add image comment"
msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr "Aggiungi una directory (cartella)"
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,9 +810,12 @@ msgstr ""
msgid "Admin Section"
msgstr ""
-msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgid "Admin notes"
msgstr ""
+msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr "Stai per eliminare definitivamente l'utente %{username}. I problemi, le richieste di merge e i gruppi ad essi collegati verranno trasferiti a un \"Utente fantasma\" a livello di sistema. Per evitare la perdita di dati, prendi invece in considerazione di utilizzare la funzione %{strong_start}blocco utente%{strong_end}. Una volta che hai %{strong_start}Eliminato l'utente%{strong_end}, non può essere annullato o ripristinato."
+
msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr "Impostazioni Avanzate"
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr "Errore durante l'attivazione/disattivazione della sottoscrizione per l'iscrizione"
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,19 +1124,34 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
+msgid "An error occurred while fetching projects autocomplete."
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "Errore durante il recupero dei dati della barra laterale"
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching the Service Desk address."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
-msgid "An error occurred while fetching the Service Desk address."
+msgid "An error occurred while fetching the builds."
msgstr ""
msgid "An error occurred while fetching the job log."
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr "Aspetto"
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr "Apr"
@@ -1253,6 +1459,18 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
+msgid "Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr ""
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to delete this list?"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Sei sicuro di voler cancellare questa pipeline programmata?"
@@ -1274,18 +1492,6 @@ msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove approver %{name}?"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}?"
-msgstr ""
-
msgid "Are you sure you want to remove the attachment?"
msgstr ""
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr "Confermi di voler resettare il token di controllo di stato?"
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr "Sei sicuro?"
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr "Artefatti"
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Aggiungi un file tramite trascina &amp; rilascia ( drag &amp; drop) o %{upload_link}"
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr "Approfondisci: %{link_to_documentation}"
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr "Disponibile"
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr "La Branch esiste già"
msgid "Branch name"
msgstr "Nome Branch"
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Cerca branches"
@@ -1856,6 +2161,21 @@ msgstr "Guarda i files"
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "per"
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "Preleva nella branch"
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr "Grafici"
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr "Controllo disponibilità branch..."
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr "Cherry-pick di questo commit"
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr "saltata"
msgid "CiStatus|running"
msgstr "in corso"
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr "Applicazioni"
@@ -2477,6 +2890,9 @@ msgstr "Gitlab Runner"
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr "Installa"
-
-msgid "ClusterIntegration|Installed"
-msgstr "Installato"
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr "Tipo di macchina"
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr "Commenti"
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr "Con il Docker Container Registry integrato in Gitlab, ogni progetto può
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr "Esegui i commit su %{branch_name}, escludendo i commit di merge. Limitat
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr "Attendere prego, questa pagina si ricaricherà automaticamente appena pronta."
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr "Copia URL negli appunti"
@@ -3166,6 +3624,12 @@ msgstr "Copia l'SHA del commit negli appunti"
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr "Tag"
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr "Tutti"
msgid "DashboardProjects|Personal"
msgstr "Personale"
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "Rilascio"
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr "Non mostrare più"
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
+msgid "Download codes"
msgstr ""
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
-msgstr ""
-
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "Cambia programmazione della pipeline %{id}"
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr "E-mail"
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "Errore durante il fetch degli ambienti."
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr "Errore durante l'attivazione/disattivazione della sottoscrizione per l'iscrizione"
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr "Impossibile cambiare owner"
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
+msgstr ""
+
+msgid "Failed to upgrade."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr "Files"
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Fork da"
@@ -4913,6 +5782,9 @@ msgstr "Fork da %{project_name} (eliminato)"
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr "Chiavi GPG"
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr "Cronologia"
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr "Housekeeping iniziato con successo"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5924,7 +6877,7 @@ msgid "If checked, group owners can manage LDAP group links and LDAP member over
msgstr ""
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
-msgstr ""
+msgstr "Se disabilitato, un ramo locale divergente non verrà automaticamente aggiornato con i commit dalla sua controparte remota, per prevenire la perdita locale dei dati. Se il ramo predefinito (%{default_branch}) è divergente e non può essere aggiornato, il mirroring fallirà. Altri rami divergenti vengono silenziosamente ignorati."
msgid "If disabled, only admins will be able to set up mirrors in projects."
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr "Importa repository"
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr "Introduzione delle Analisi Cicliche"
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr "Gen"
msgid "January"
msgstr "Gennaio"
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr "Lug"
msgid "July"
msgstr "Luglio"
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr "Giu"
@@ -6405,6 +7493,9 @@ msgstr "Giugno"
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr "Disabilitato"
msgid "LFSStatus|Enabled"
msgstr "Abilitato"
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] "Gli ultimi %d giorni"
msgid "Last Pipeline"
msgstr "Ultima Pipeline"
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr "Ultimo aggiornamento"
msgid "Last updated"
msgstr "Ultimo aggiornamento"
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr "Leggi di più su"
@@ -6602,6 +7726,12 @@ msgstr "Abbandona il progetto"
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr "Mar"
msgid "March"
msgstr "Marzo"
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr "Richieste di merge"
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr "Richiesta di merge"
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr "Messaggi"
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "aggiungi una chiave SSH"
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr "Nuovo file"
@@ -7419,6 +8675,9 @@ msgstr "Nuova richiesta di merge"
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr "Notifica eventi"
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "Chiudi issue"
@@ -7695,6 +8993,9 @@ msgstr "Partecipa"
msgid "NotificationLevel|Watch"
msgstr "Osserva"
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr "Notifiche"
@@ -7710,6 +9011,12 @@ msgstr "Nov"
msgid "November"
msgstr "Novembre"
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr "Ottobre"
msgid "OfSearchInADropdown|Filter"
msgstr "Filtra"
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr "Solo i membri del progetto possono commentare."
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr "Aperto"
msgid "Opens in a new window"
msgstr "Si apre in una nuova finestra"
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr "Panoramica"
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr "Proprietario"
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "Ultima »"
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr "Password"
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr "Pipeline"
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr "Pianificazione Pipeline"
@@ -8069,6 +9430,9 @@ msgstr "Pipeline"
msgid "Pipelines charts"
msgstr "Grafici pipeline"
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr "Pipeline per il mese scorso"
@@ -8078,10 +9442,13 @@ msgstr "Pipeline per la settimana scorsa"
msgid "Pipelines for last year"
msgstr "Pipeline per l'ultimo anno"
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8148,7 +9518,7 @@ msgid "Pipeline|Search branches"
msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
-msgstr ""
+msgstr "Pipeline|Specifica i valori delle variabili da utilizzare in questa esecuzione. I valori specificati nel %{settings_link} verranno utilizzati come predefiniti."
msgid "Pipeline|Stages"
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr "con stadio"
msgid "Pipeline|with stages"
msgstr "con più stadi"
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr "Preferenze"
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,20 +9814,29 @@ msgstr "Privato - Il gruppo e i suoi progetti possono essere visualizzati solo d
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr "Profilo"
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
-msgstr ""
+msgstr "Profiles| Stai per cambiare il nome utente %{currentUsernameBold} in %{newUsernameBold}. Profilo e progetti verranno reindirizzati allo spazio dei nomi %{newUsername} ma questo reindirizzamento scadrà quando lo spazio dei nomi %{currentUsername} viene registrato da un altro utente o gruppo. Per favore aggiorna i remote repository di Git il prima possibile."
msgid "Profiles|@username"
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr "Elimina account"
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr "Password non valida"
msgid "Profiles|Invalid username"
msgstr "Username non valido"
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8505,18 +10025,21 @@ msgid "Profiles|This email will be used for web based operations, such as edits
msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
-msgstr ""
+msgstr "Questa emoticon e questo messaggio appariranno sul tuo profilo e su tutta l'interfaccia."
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Inserisci il tuo %{confirmationValue} per confermare:"
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "Iscriviti"
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr "Progetti"
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr "Richieste di Merge Correlate"
msgid "Related Merged Requests"
msgstr "Richieste di Merge Completate Correlate"
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr "Ricordamelo più tardi"
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr "Rimuovi progetto"
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr "Chiavi SSH"
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Salva pianificazione pipeline"
@@ -9676,9 +11508,21 @@ msgstr "Ricerca branches e tags"
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr "Seleziona formato d'archivio"
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9875,7 +11740,7 @@ msgid "Select target branch"
msgstr "Seleziona una branch di destinazione"
msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
+msgstr "Seleziona il ramo che vuoi impostare come predefinito per questo progetto. Tutte le richieste di merge e i commit verranno automaticamente eseguiti su questo ramo, a meno che non ne sia specificato uno diverso."
msgid "Select the custom project template source group."
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr "imposta una password"
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr "Impostazioni"
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10504,7 +12447,7 @@ msgid "Stage changes"
msgstr ""
msgid "Staged"
-msgstr ""
+msgstr "Staged"
msgid "Staged %{type}"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr "Star"
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr "Cambia branch/tag"
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10855,7 +12903,7 @@ msgid "TagsPage|Optionally, add a message to the tag."
msgstr ""
msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
-msgstr ""
+msgstr "Facoltativamente, aggiungi le note di rilascio al tag. Verranno archiviate nel database GitLab e visualizzate nella pagina dei tag."
msgid "TagsPage|Release notes"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "Lo stadio di Issue mostra il tempo che impiega un issue ad esser correlato ad una Milestone, o ad esser aggiunto ad una tua Lavagna. Inizia la creazione di problemi per visualizzare i dati in questo stadio."
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr "Lo stadio di produzione mostra il tempo totale che trascorre tra la crea
msgid "The project can be accessed by any logged in user."
msgstr "Qualunque utente autenticato può accedere a questo progetto."
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr "Chiunque può accedere a questo progetto (senza alcuna autenticazione)."
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr "La repository di questo progetto non esiste."
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr "Lo stadio di test mostra il tempo che ogni Pipeline impiega per essere e
msgid "The time taken by each data entry gathered by that stage."
msgstr "Il tempo aggregato relativo eventi/data entry raccolto in quello stadio."
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "Il valore falsato nel mezzo di una serie di dati osservati. ES: tra 3,5,9 il mediano è 5. Tra 3,5,7,8 il mediano è (5+7)/2 quindi 6."
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr "Questo significa che non è possibile effettuare push di codice fino a c
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr "Il tempo che impiega un issue per esser pianificato"
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -11977,7 +14277,7 @@ msgid "Unstage changes"
msgstr ""
msgid "Unstaged"
-msgstr ""
+msgstr "Unstaged"
msgid "Unstaged %{type}"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr "Carica file"
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr "clicca per caricare"
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr "Pubblico"
msgid "VisibilityLevel|Unknown"
msgstr "Sconosciuto"
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Vuoi visualizzare i dati? Richiedi l'accesso ad un amministratore, grazie."
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr "Non ci sono sufficienti dati da mostrare su questo stadio"
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,8 +15319,14 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "Stai per rimuovere il gruppo %{group_name}. I gruppi rimossi NON POSSONO esser ripristinati! Sei ASSOLUTAMENTE sicuro?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
@@ -12731,6 +15337,9 @@ msgstr "Stai per rimuovere la relazione con il progetto sorgente %{forked_from_p
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12807,7 +15437,7 @@ msgid "You cannot play this scheduled pipeline at the moment. Please wait a minu
msgstr ""
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
-msgstr ""
+msgstr "Non puoi scrivere su un'istanza di GitLab Geo secondaria di sola lettura. Per favore utilizza invece %{link_to_primary_node}."
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr "Necessiti del permesso."
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr "Non sarai in grado di effettuare push o pull tramite SSH fino a che %{ad
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr "Il tuo nome"
@@ -13049,10 +15742,13 @@ msgstr "fa"
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] "giorno"
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr "Nuova richiesta di merge"
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/ja/gitlab.po b/locale/ja/gitlab.po
index ed9037c9503..814f4ea85d2 100644
--- a/locale/ja/gitlab.po
+++ b/locale/ja/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Japanese\n"
"Language: ja_JP\n"
"MIME-Version: 1.0\n"
@@ -13,19 +13,16 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ja\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:29\n"
+"PO-Revision-Date: 2019-06-14 10:20\n"
msgid " Please sign in."
-msgstr ""
-
-msgid " Status"
-msgstr " ステータス"
+msgstr " サインインã—ã¦ãã ã•ã„。"
msgid " Try to %{action} this file again."
-msgstr ""
+msgstr " ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ã‚‚ã†ä¸€åº¦ %{action} ã—ã¦ã¿ã¦ãã ã•ã„。"
msgid " You need to do this before %{grace_period_deadline}."
-msgstr ""
+msgstr " %{grace_period_deadline} ã®å‰ã«ã“れを行ã†å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
msgid " and"
msgstr " ã¨"
@@ -45,7 +42,7 @@ msgid " or <#epic id>"
msgstr " ã¾ãŸã¯ <#エピックID>"
msgid " or <#issue id>"
-msgstr ""
+msgstr " ã¾ãŸã¯ <#課題 ID>"
msgid "%d comment"
msgid_plural "%d comments"
@@ -62,6 +59,10 @@ msgstr[0] "%d個ã®ã‚³ãƒŸãƒƒãƒˆå¾…ã¡"
msgid "%d commits"
msgstr "%d個ã®ã‚³ãƒŸãƒƒãƒˆ"
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] "貢献 %d件"
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d exporter"
@@ -90,10 +91,18 @@ msgid "%d merge request"
msgid_plural "%d merge requests"
msgstr[0] "%d 個ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d メトリクス"
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] "%d 件以上ã®ã‚³ãƒ¡ãƒ³ãƒˆ"
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] "%d件ã®ã‚¹ãƒ†ãƒ¼ã‚¸æ¸ˆã¿å¤‰æ›´"
@@ -115,11 +124,8 @@ msgstr "%{authorsName} ã®ãƒ‡ã‚£ã‚¹ã‚«ãƒƒã‚·ãƒ§ãƒ³"
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} ㌠%{commit_timeago} ã«ã‚³ãƒŸãƒƒãƒˆã—ã¾ã—ãŸ"
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr "%{counter_storage} (%{counter_repositories} リãƒã‚¸ãƒˆãƒªã€%{counter_build_artifacts} ビルドアーティファクトã€%{counter_lfs_objects} LFS)"
-
-msgid "%{count} %{alerts}"
-msgstr "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
+msgstr ""
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
@@ -148,6 +154,12 @@ msgid "%{count} pending comment"
msgid_plural "%{count} pending comments"
msgstr[0] "ä¿ç•™ä¸­ã®ã‚³ãƒ¡ãƒ³ãƒˆ%{count} 件"
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr "%{edit_in_new_fork_notice} ã“ã®ã‚³ãƒŸãƒƒãƒˆã‚’ã‚‚ã†ä¸€åº¦ãƒã‚§ãƒªãƒ¼ãƒ”ックã—ã¦ãã ã•ã„。"
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr "%{edit_in_new_fork_notice} ã“ã®ã‚³ãƒŸãƒƒãƒˆã‚’ã‚‚ã†ä¸€åº¦revertã—ã¦ãã ã•ã„。"
+
msgid "%{filePath} deleted"
msgstr "%{filePath} ãŒå‰Šé™¤ã•ã‚Œã¾ã—ãŸ"
@@ -160,14 +172,26 @@ msgstr "%{gitlab_ci_yml} ã¯ã“ã®ã‚³ãƒŸãƒƒãƒˆã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}グループ%{group_docs_link_end}を使用ã™ã‚‹ã¨ã€è¤‡æ•°ã®ãƒ—ロジェクトを管ç†ã—ã¦å…±åŒä½œæ¥­ã‚’è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚グループã®ãƒ¡ãƒ³ãƒãƒ¼ã¯ã€æ‰€å±žã™ã‚‹ãƒ—ロジェクトã®ã™ã¹ã¦ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚"
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType}を削除ã—ã¾ã™ï¼ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} ã¯åˆ©ç”¨ä¸å¯"
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} ã¯ã€ç„¡æ–™ã®è‡ªå‹•åŒ–ã•ã‚ŒãŸã‚ªãƒ¼ãƒ—ンãªèªè¨¼å±€(CA)ã§ã€Webサイトã§HTTPS(SSL/TLS)を有効ã«ã™ã‚‹ãŸã‚ã«ãƒ‡ã‚¸ã‚¿ãƒ«è¨¼æ˜Žæ›¸ã‚’発行ã§ãã¾ã™ã€‚"
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr "%{level_name} 㯠%{group_level_name} グループã«å«ã‚られã¾ã›ã‚“。"
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr "%{level_name} ã¯è¨±å¯ã•ã‚Œã¾ã›ã‚“。フォークã—ãŸã‚½ãƒ¼ã‚¹ãƒ—ロジェクトã¯ã‚ˆã‚Šå¯è¦–性ãŒä½Žã„ã‹ã‚‰ã§ã™ã€‚"
+
msgid "%{level_name} visibility has been restricted by the administrator."
-msgstr ""
+msgstr "%{level_name} ã®å¯è¦–性ã¯ç®¡ç†è€…ã«ã‚ˆã‚Šåˆ¶é™ã•ã‚Œã¦ã„ã¾ã™ã€‚"
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "ロールã®æ¨©é™ã«ã¤ã„ã¦%{link_start}ã‚‚ã£ã¨èª­ã‚€%{link_end}"
@@ -179,7 +203,13 @@ msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} ã¯GitLab ユーザー %{lock_user_id} ã«ã‚ˆã£ã¦ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™"
msgid "%{mrText}, this issue will be closed automatically."
-msgstr ""
+msgstr "%{mrText} ã€ã“ã®èª²é¡Œã¯è‡ªå‹•çš„ã«ã‚¯ãƒ­ãƒ¼ã‚ºã—ã¾ã™ã€‚"
+
+msgid "%{name} contained %{resultsString}"
+msgstr "%{name} ã«ã¯ %{resultsString} ãŒå«ã¾ã‚Œã¦ã„ã¾ã™"
+
+msgid "%{name} found %{resultsString}"
+msgstr "%{name} ã« %{resultsString} ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ"
msgid "%{name}'s avatar"
msgstr "%{name}ã®ã‚¢ãƒã‚¿ãƒ¼"
@@ -194,13 +224,25 @@ msgid "%{percent}%% complete"
msgstr "%{percent}%% 完了"
msgid "%{service_title} activated."
-msgstr ""
+msgstr "%{service_title} ãŒèµ·å‹•ã•ã‚Œã¾ã—ãŸ"
msgid "%{service_title} settings saved, but not activated."
-msgstr ""
+msgstr "%{service_title} 設定ã¯ä¿å­˜ã•ã‚Œã¾ã—ãŸãŒã€æœ‰åŠ¹åŒ–ã•ã‚Œã¦ã„ã¾ã›ã‚“。"
+
+msgid "%{size} GiB"
+msgstr "%{size} GiB"
+
+msgid "%{size} KiB"
+msgstr "%{size} KiB"
+
+msgid "%{size} MiB"
+msgstr "%{size} MiB"
+
+msgid "%{size} bytes"
+msgstr "%{size} ãƒã‚¤ãƒˆ"
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
-msgstr ""
+msgstr "%{spammable_titlecase} ã¯Akismetã«æ­£å¸¸ã«é€ä¿¡ã•ã‚Œã¾ã—ãŸã€‚"
msgid "%{state} epics"
msgstr "%{state}エピック"
@@ -227,6 +269,9 @@ msgstr[0] "%{text} %{files} ファイル"
msgid "%{text} is available"
msgstr "%{text} ãŒåˆ©ç”¨ã§ãã¾ã™ã€‚"
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr "%{title} ã®å¤‰æ›´"
@@ -239,9 +284,28 @@ msgstr "GitLab Inc. ã¨ã©ã®ã‚ˆã†ãªæƒ…報を共有ã™ã‚‹ã‹ã«ã¤ã„ã¦ã¯ %{
msgid "%{user_name} profile page"
msgstr "%{user_name} プロフィールページ"
-msgid "(No changes)"
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr "'%{level}' ã¯æœ‰åŠ¹ãªå¯è¦–レベルã§ã¯ã‚ã‚Šã¾ã›ã‚“"
+
+msgid "'%{source}' is not a import source"
+msgstr "'%{source}' ã¯ã‚¤ãƒ³ãƒãƒ¼ãƒˆã‚½ãƒ¼ã‚¹ã§ã¯ã‚ã‚Šã¾ã›ã‚“。"
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+
+msgid "(%{mrCount} merged)"
msgstr ""
+msgid "(No changes)"
+msgstr "(変更ãªã—)"
+
+msgid "(check progress)"
+msgstr "(進行状æ³ã‚’確èªã™ã‚‹)"
+
msgid "(external source)"
msgstr "(外部ソース)"
@@ -266,6 +330,9 @@ msgstr "- RunnerãŒåœæ­¢ä¸­ã®ãŸã‚æ–°ã—ã„ジョブã¯å‡¦ç†ã•ã‚Œã¾ã›ã‚“"
msgid "- show less"
msgstr "- 折りãŸãŸã‚€"
+msgid "0 for unlimited"
+msgstr "0ã¯ç„¡åˆ¶é™ã®æ„味"
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] "%{count} %{type} 件ã®è¿½åŠ æƒ…å ±"
@@ -279,31 +346,31 @@ msgid_plural "%d Days"
msgstr[0] "%d æ—¥"
msgid "1 closed issue"
-msgid_plural "%d closed issues"
-msgstr[0] "%d件ã®ã‚¯ãƒ­ãƒ¼ã‚ºã•ã‚ŒãŸèª²é¡Œ"
+msgid_plural "%{issues} closed issues"
+msgstr[0] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
-msgstr[0] "%d件ã®ã‚¯ãƒ­ãƒ¼ã‚ºã•ã‚ŒãŸãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
+msgid_plural "%{merge_requests} closed merge requests"
+msgstr[0] ""
msgid "1 day"
-msgstr ""
+msgstr "1 æ—¥"
msgid "1 group"
msgid_plural "%d groups"
msgstr[0] "%dグループ"
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
-msgstr[0] "%d件ã®ãƒžãƒ¼ã‚¸ã•ã‚ŒãŸãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
+msgid_plural "%{merge_requests} merged merge requests"
+msgstr[0] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
-msgstr[0] "%d件ã®èª²é¡Œ"
+msgid_plural "%{issues} open issues"
+msgstr[0] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
-msgstr[0] "%d件ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] ""
msgid "1 pipeline"
msgid_plural "%d pipelines"
@@ -318,25 +385,40 @@ msgid_plural "%d users"
msgstr[0] "%dユーザー"
msgid "1 week"
-msgstr ""
+msgstr "1 週間"
+
+msgid "1-9 contributions"
+msgstr "貢献 1-9 件"
+
+msgid "10-19 contributions"
+msgstr "貢献 10-19 件"
msgid "1st contribution!"
msgstr "最åˆã®è²¢çŒ®!"
+msgid "20-29 contributions"
+msgstr "貢献 20-29 件"
+
msgid "2FA"
msgstr "2FA"
msgid "2FA enabled"
msgstr "2段階èªè¨¼ãŒæœ‰åŠ¹"
-msgid "3 days"
+msgid "2FADevice|Registered On"
msgstr ""
+msgid "3 days"
+msgstr "3 æ—¥"
+
msgid "3 hours"
-msgstr ""
+msgstr "3 時間"
msgid "30 minutes"
-msgstr ""
+msgstr "30 分"
+
+msgid "30+ contributions"
+msgstr "貢献 30 件以上"
msgid "403|Please contact your GitLab administrator to get permission."
msgstr "ã“ã®ãƒšãƒ¼ã‚¸ã®é–²è¦§ã«ã¯æ¨©é™ãŒå¿…è¦ã§ã™ã€‚GitLab 管ç†è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。"
@@ -354,7 +436,7 @@ msgid "404|Please contact your GitLab administrator if you think this is a mista
msgstr "ã“ã®ãƒšãƒ¼ã‚¸ãŒæ­£ã—ããªã„å ´åˆã€GitLab 管ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
msgid "8 hours"
-msgstr ""
+msgstr "8 時間"
msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
msgstr "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> 㯠johnsmith@example.com ã«ã‚ˆã‚‹å…¨ã¦ã®èª²é¡Œã¨ã‚³ãƒ¡ãƒ³ãƒˆã« \"By <a href=\"#\">@johnsmith</a>\" を追加ã—ã¾ã™ã€‚ã¾ãŸã€ <a href=\"#\">@johnsmith</a> を元々 johnsmith@example.com ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚Œã¦ã„ãŸå…¨ã¦ã®èª²é¡Œã®æ‹…当者ã¨ã—ã¦è¨­å®šã—ã¾ã™ã€‚"
@@ -368,6 +450,9 @@ msgstr "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> ã¯ã€
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> ã¯ã€johnsmith@example.com ãŒä½œæˆã—ãŸå…¨ã¦ã®èª²é¡Œã¨ã‚³ãƒ¡ãƒ³ãƒˆã« \"By <a href=\"#\">johnsmith@example.com</a>\" を追加ã—ã¾ã™ã€‚デフォルトã§ã€ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚„ユーザーåã‚’éš ã—ã¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ—ライãƒã‚·ãƒ¼ã‚’ä¿è­·ã•ã‚Œã¾ã™ã€‚メールアドレスを全ã¦è¡¨ç¤ºã—ãŸã„å ´åˆã€ã“ã®æ–¹æ³•ã‚’指定ã—ã¦ãã ã•ã„。"
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr "<strong>ステージã•ã‚Œã¦ã„ãªã„変更 %{changedFilesLength} </strong> ã¨<strong>ステージã•ã‚ŒãŸå¤‰æ›´ %{stagedFilesLength} </strong>"
@@ -390,7 +475,7 @@ msgid "A 'Runner' is a process which runs a job. You can set up as many Runners
msgstr "「Runnerã€ã¯ã‚¸ãƒ§ãƒ–を実行ã™ã‚‹ãƒ—ロセスã§ã™ã€‚å¿…è¦ãªæ•°ã® Runner ã‚’ä»»æ„ã«ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ã§ãã¾ã™ã€‚"
msgid "A .NET Core console application template, customizable for any .NET Core project"
-msgstr ""
+msgstr "ä»»æ„ã®.NET Coreプロジェクト用ã«ã‚«ã‚¹ã‚¿ãƒžã‚¤ã‚ºå¯èƒ½ãªã€.NET Coreコンソールアプリケーションテンプレート"
msgid "A GitBook site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr "GitLab ã®ä»£ã‚ã‚Šã« Netlify for CI/CD を使用ã—ã¦ã„ã‚‹ GitBook サイトã§ã™ãŒã€GitLab ã«ã¯ãªã„優れãŸæ©Ÿèƒ½ã‚‚å‚™ãˆã¦ã„ã¾ã™ã€‚"
@@ -404,26 +489,26 @@ msgstr "GitLab ã®ä»£ã‚ã‚Šã« Netlify for CI/CD を使用ã—ã¦ã„ã‚‹ Hugo サã
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr "GitLab ã®ä»£ã‚ã‚Šã« Netlify for CI/CD を使用ã—ã¦ã„ã‚‹ Jekyll サイトã§ã™ãŒã€GitLab ã«ã¯ãªã„優れãŸæ©Ÿèƒ½ã‚‚å‚™ãˆã¦ã„ã¾ã™ã€‚"
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
+msgstr "Let's Encryptアカウントをã“ã®GitLabインストール用ã«æ§‹æˆã™ã‚‹ãŸã‚ã«ã‚ãªãŸã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’使用ã—ã¾ã™ã€‚証明書ã®æœŸé™ãŒåˆ‡ã‚ŒãŸéš›ã€è­¦å‘Šãƒ¡ãƒ¼ãƒ«ãŒå±Šãã¾ã™ã€‚"
+
msgid "A default branch cannot be chosen for an empty project."
msgstr "プロジェクトãŒç©ºã®å ´åˆã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ãƒ–ランãƒã‚’é¸æŠžã§ãã¾ã›ã‚“。"
msgid "A deleted user"
msgstr "削除ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼"
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr "ãŸã ã¡ã«é–‹ç™ºãƒ¡ãƒ³ãƒãƒ¼ã§ã„ãŸã ã„ãŸãƒ¬ãƒãƒ¼ãƒˆã‚’æ‹èª­ã—å‚考ã«ã•ã›ã¦ã„ãŸã ãã¾ã™ã€‚"
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
+msgstr "フォークã¯ãƒ—ロジェクトã®ã‚³ãƒ”ーã§ã™ã€‚<br />リãƒã‚¸ãƒˆãƒªã‚’フォークã™ã‚‹ã¨ã€å…ƒã®ãƒ—ロジェクトã«å½±éŸ¿ã‚’与ãˆãšã«å¤‰æ›´ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
-msgstr ""
-
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr "フォークã«æ–°ã—ã„ブランãƒãŒä½œæˆã•ã‚Œã€æ–°ã—ã„マージリクエストãŒé–‹å§‹ã—ã¾ã™ã€‚"
msgid "A new impersonation token has been created."
-msgstr ""
+msgstr "æ–°ã—ã„å½è£…トークンãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr "GitLab ã®ä»£ã‚ã‚Šã« Netlify for CI/CD を使用ã—ã¦ã„るプレーン HTML サイトã§ã™ãŒã€GitLab ã«ã¯ãªã„優れãŸæ©Ÿèƒ½ã‚‚å‚™ãˆã¦ã„ã¾ã™ã€‚"
@@ -444,7 +529,10 @@ msgid "A user with write access to the source branch selected this option"
msgstr "ã“ã®ã‚ªãƒ—ションをé¸æŠžã—ãŸã‚½ãƒ¼ã‚¹ãƒ–ランãƒã¸ã®æ›¸ãè¾¼ã¿ã‚’許å¯ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼"
msgid "API Help"
-msgstr ""
+msgstr "API ヘルプ"
+
+msgid "API Token"
+msgstr "API トークン"
msgid "About GitLab"
msgstr "GitLab ã«ã¤ã„ã¦"
@@ -477,7 +565,7 @@ msgid "Access Tokens"
msgstr "アクセス トークン"
msgid "Access denied for your LDAP account."
-msgstr ""
+msgstr "ã‚ãªãŸã® LDAP アカウントã®ã‚¢ã‚¯ã‚»ã‚¹ãŒæ‹’å¦ã•ã‚Œã¾ã—ãŸã€‚"
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "アクセスãŒæ‹’å¦ã•ã‚Œã¾ã—ãŸï¼ã“ã®ãƒªãƒã‚¸ãƒˆãƒªã«ãƒ‡ãƒ—ロイキーを追加ã§ãã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。"
@@ -486,22 +574,34 @@ msgid "Access expiration date"
msgstr "アクセス有効期é™"
msgid "Access forbidden. Check your access level."
-msgstr ""
+msgstr "アクセスã¯ç¦æ­¢ã•ã‚Œã¦ã„ã¾ã™ã€‚アクセスレベルを確èªã—ã¦ãã ã•ã„。"
msgid "Access to '%{classification_label}' not allowed"
msgstr "'%{classification_label}'ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“"
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr "アカウント"
msgid "Account and limit"
msgstr "アカウントã¨åˆ¶é™"
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr "アラートをå—ä¿¡ã—ãŸéš›ã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³"
msgid "Activate Service Desk"
-msgstr ""
+msgstr "サービスデスクを有効ã«ã™ã‚‹"
msgid "Active"
msgstr "有効"
@@ -516,7 +616,7 @@ msgid "Add"
msgstr "追加"
msgid "Add CHANGELOG"
-msgstr ""
+msgstr "変更履歴を追加"
msgid "Add CONTRIBUTING"
msgstr "CONTRIBUTINGを追加"
@@ -533,6 +633,9 @@ msgstr "Kubernetes クラスターを追加"
msgid "Add README"
msgstr "README を追加"
+msgid "Add a GPG key"
+msgstr "GPGキーを追加"
+
msgid "Add a bullet list"
msgstr "箇æ¡æ›¸ãリストを追加"
@@ -543,7 +646,7 @@ msgid "Add a homepage to your wiki that contains information about your project
msgstr "ã‚ãªãŸã® Wiki ã«ãƒ—ロジェクトã«é–¢ã™ã‚‹æƒ…報をå«ã‚€ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ã‚’追加ã™ã‚‹ã¨ã€GitLab ã¯ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã®ä»£ã‚ã‚Šã«ãれをã“ã“ã«è¡¨ç¤ºã—ã¾ã™ã€‚"
msgid "Add a link"
-msgstr ""
+msgstr "リンクを追加"
msgid "Add a numbered list"
msgstr "番å·ä»˜ãリストを追加"
@@ -554,11 +657,17 @@ msgstr "テーブルを追加ã™ã‚‹"
msgid "Add a task list"
msgstr "タスクリストを追加"
+msgid "Add a todo"
+msgstr "Todo を追加"
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "ã™ã¹ã¦ã®ãƒ¡ãƒ¼ãƒ«ã«è¡¨ç¤ºã™ã‚‹ãƒ†ã‚­ã‚¹ãƒˆã‚’追加ã—ã¾ã™ã€‚ ãŸã ã—ã€%{character_limit} 文字ã®åˆ¶é™ãŒã‚ã‚Šã¾ã™ã€‚"
-msgid "Add approver(s)"
-msgstr "承èªè€…を追加"
+msgid "Add an SSH key"
+msgstr "SSH éµã‚’追加"
+
+msgid "Add an issue"
+msgstr ""
msgid "Add approvers"
msgstr "承èªè€…を追加"
@@ -566,9 +675,15 @@ msgstr "承èªè€…を追加"
msgid "Add bold text"
msgstr "太字ã®ãƒ†ã‚­ã‚¹ãƒˆã‚’追加"
+msgid "Add child epic to an epic"
+msgstr "エピックã«å­ã‚¨ãƒ”ックを追加"
+
msgid "Add comment now"
msgstr "コメントã™ã‚‹"
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "メールã«ãƒ˜ãƒƒãƒ€ãƒ¼ã¨ãƒ•ãƒƒã‚¿ãƒ¼ã‚’追加ã—ã¾ã™ã€‚色設定ã¯ã‚¢ãƒ—リケーションインターフェース内ã§ã®ã¿é©ç”¨ã•ã‚Œã¾ã™ã€‚"
@@ -578,11 +693,14 @@ msgstr "ç”»åƒã‚³ãƒ¡ãƒ³ãƒˆã‚’追加"
msgid "Add italic text"
msgstr "斜体ã®ãƒ†ã‚­ã‚¹ãƒˆã‚’追加"
+msgid "Add label(s)"
+msgstr "ラベルを追加"
+
msgid "Add license"
msgstr "ライセンスを追加"
msgid "Add list"
-msgstr ""
+msgstr "リストを追加"
msgid "Add new application"
msgstr "æ–°ã—ã„アプリケーションを追加"
@@ -590,9 +708,18 @@ msgstr "æ–°ã—ã„アプリケーションを追加"
msgid "Add new directory"
msgstr "æ–°è¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’追加"
+msgid "Add or subtract spent time"
+msgstr "作業時間を追加ã¾ãŸã¯æ¸›ã‚‰ã™"
+
msgid "Add reaction"
msgstr "リアクションã®è¿½åŠ "
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr "プロジェクトã«è¿½åŠ "
@@ -605,24 +732,36 @@ msgstr "Todoを追加"
msgid "Add user(s) to the group:"
msgstr "グループã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’追加:"
-msgid "Add users or groups who are allowed to approve every merge request"
-msgstr "ã™ã¹ã¦ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®æ‰¿èªã‚’許å¯ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã®è¿½åŠ "
-
msgid "Add users to group"
msgstr "ユーザーをグループã¸è¿½åŠ "
+msgid "AddMember|No users specified."
+msgstr "ユーザーãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。"
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
+msgstr "ユーザーãŒå¤šã指定ã—ã™ãŽã¦ã„ã¾ã™ã€‚(上é™ã¯ %{user_limit})"
+
msgid "Added at"
msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr "ã‚ãªãŸã® GitLab インスタンスã§æ–°ã—ã„アプリケーションを追加ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。権é™ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€GitLab 管ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr "追加テキスト"
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr "追加"
+
+msgid "Adds %{epic_ref} as child epic."
msgstr ""
+msgid "Adds a todo."
+msgstr "Todoを追加ã—ã¾ã™ã€‚"
+
msgid "Admin Area"
msgstr "管ç†è€…エリア"
@@ -630,13 +769,16 @@ msgid "Admin Overview"
msgstr "管ç†è€…用概è¦"
msgid "Admin Section"
+msgstr "管ç†ã‚»ã‚¯ã‚·ãƒ§ãƒ³"
+
+msgid "Admin notes"
msgstr ""
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "%{username}を完全ã«å‰Šé™¤ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ç´ä»˜ã„ã¦ã„ã‚‹ã€èª²é¡Œã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ãŠã‚ˆã³ã‚°ãƒ«ãƒ¼ãƒ—ã¯ã€ã‚·ã‚¹ãƒ†ãƒ å…¨ä½“ã®ã€ŒGhost-userã€ã«è»¢é€ã•ã‚Œã¾ã™ã€‚データã®æ¶ˆå¤±ã‚’é¿ã‘ã‚‹ã«ã¯ã€å‰Šé™¤ã§ã¯ãªã%{strong_start} ユーザーã®ãƒ–ロック機能%{strong_end}を使用ã—ã¦ãã ã•ã„。一度%{strong_start}ユーザーã®å‰Šé™¤ %{strong_end}を実行ã™ã‚‹ã¨å…ƒã«æˆ»ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“。"
msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "ユーザー %{username} を完全ã«å‰Šé™¤ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ユーザーã«ç´ä»˜ã„ã¦ã„る課題ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ãŠã‚ˆã³ã‚°ãƒ«ãƒ¼ãƒ—ã¯ã™ã¹ã¦å‰Šé™¤ã•ã‚Œã¾ã™ã€‚データã®æ失をé¿ã‘ã‚‹ãŸã‚ã«ã¯ã€å‰Šé™¤ã§ã¯ãªã%{strong_start}ユーザーã®ãƒ–ロック機能%{strong_end}を使用ã—ã¦ãã ã•ã„。一度%{strong_start}ユーザーã®å‰Šé™¤%{strong_end}を実行ã™ã‚‹ã¨ã€å…ƒã«æˆ»ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“。"
msgid "AdminArea|Stop all jobs"
msgstr "å…¨ã¦ã®ã‚¸ãƒ§ãƒ–ã‚’åœæ­¢"
@@ -653,6 +795,9 @@ msgstr "ジョブã®åœæ­¢ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "å…¨ã¦ã®ã‚¸ãƒ§ãƒ–ã‚’åœæ­¢ã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šç¾åœ¨å®Ÿè¡Œä¸­ã®ã‚¸ãƒ§ãƒ–ã¯åœæ­¢ã•ã‚Œã¾ã™ã€‚"
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr "プロジェクト %{projectName} ã¨ãã®ãƒªãƒã‚¸ãƒˆãƒªã€èª²é¡Œã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãªã©ã®ã™ã¹ã¦ã®é–¢é€£ãƒªã‚½ãƒ¼ã‚¹ã‚’完全ã«å‰Šé™¤ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã„ã¾ä¸€åº¦ç¢ºèªã—〠%{strong_start}プロジェクトã®å‰Šé™¤%{strong_end}を押ã—ã¦ãã ã•ã„。削除ã—ãŸã‚ã¨ã€å…ƒã«æˆ»ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“。"
@@ -756,10 +901,10 @@ msgid "Advanced"
msgstr "高度ãªè¨­å®š"
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
-msgstr ""
+msgstr "高度ãªæ¨©é™ã€ãƒ©ãƒ¼ã‚¸ãƒ•ã‚¡ã‚¤ãƒ«ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ã€2è¦ç´ èªè¨¼ã®è¨­å®š"
msgid "Advanced search functionality"
-msgstr ""
+msgstr "高度ãªæ¤œç´¢æ©Ÿèƒ½"
msgid "Advanced settings"
msgstr "高度ãªè¨­å®š"
@@ -767,6 +912,9 @@ msgstr "高度ãªè¨­å®š"
msgid "After a successful password update you will be redirected to login screen."
msgstr "パスワードã®æ›´æ–°ã«æˆåŠŸã™ã‚‹ã¨ã€ãƒ­ã‚°ã‚¤ãƒ³ç”»é¢ã«ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã•ã‚Œã¾ã™ã€‚"
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "アラート"
@@ -783,23 +931,32 @@ msgstr "ã™ã¹ã¦ã®ãƒ¡ãƒ³ãƒãƒ¼"
msgid "All changes are committed"
msgstr "ã™ã¹ã¦ã®å¤‰æ›´ãŒã‚³ãƒŸãƒƒãƒˆã•ã‚Œã¦ã„ã¾ã™"
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "空ã®ãƒ—ロジェクトã€ãƒ†ãƒ³ãƒ—レートã‹ã‚‰ã€ã¾ãŸã¯ã‚¤ãƒ³ãƒãƒ¼ãƒˆæ™‚ã«ã™ã¹ã¦ã®æ©Ÿèƒ½ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã™ãŒã€å¾Œã§ãƒ—ロジェクト設定ã§ç„¡åŠ¹ã«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr "ã“ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã«é–¢ã™ã‚‹èª²é¡Œã¯ã™ã¹ã¦è§£æ±ºã•ã‚Œã¾ã—ãŸã€‚ã“ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã‚’クローズã§ãã¾ã™ã€‚"
msgid "All merge conflicts were resolved. The merge request can now be merged."
-msgstr ""
+msgstr "ã™ã¹ã¦ã®ç«¶åˆãŒè§£æ±ºã•ã‚Œã¾ã—ãŸã€‚マージリクエストをマージã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
+
+msgid "All projects"
+msgstr "ã™ã¹ã¦ã®ãƒ—ロジェクト"
msgid "All todos were marked as done."
-msgstr ""
+msgstr "ã™ã¹ã¦ã®TodoãŒå®Œäº†ã¨ã—ã¦ãƒžãƒ¼ã‚¯ã•ã‚Œã¾ã—ãŸã€‚"
msgid "All users"
msgstr "ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼"
msgid "All users must have a name."
-msgstr ""
+msgstr "ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«åå‰ãŒå¿…è¦ã§ã™ã€‚"
msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
@@ -832,7 +989,7 @@ msgid "Allow this key to push to repository as well? (Default only allows pull a
msgstr "ã“ã®ã‚­ãƒ¼ã‚‚リãƒã‚¸ãƒˆãƒªã«ãƒ—ッシュã§ãるよã†ã«ã—ã¾ã™ã‹ï¼Ÿ (デフォルトã¯ãƒ—ルアクセスã®ã¿ã‚’許å¯ã—ã¾ã™)"
msgid "Allow users to register any application to use GitLab as an OAuth provider"
-msgstr ""
+msgstr "ユーザーãŒGitLabã‚’OAuthプロãƒã‚¤ãƒ€ãƒ¼ã¨ã—ã¦ä½¿ç”¨ã™ã‚‹ã‚らゆるアプリケーションを登録ã™ã‚‹ã“ã¨ã‚’許å¯"
msgid "Allow users to request access"
msgstr "ユーザーãŒã‚¢ã‚¯ã‚»ã‚¹ã‚’è¦æ±‚ã§ãるよã†ã«ã™ã‚‹"
@@ -841,7 +998,7 @@ msgid "Allow users to request access if visibility is public or internal."
msgstr "å¯è¦–性ãŒå…¬é–‹ã¾ãŸã¯å†…部ã®å ´åˆã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã‚¢ã‚¯ã‚»ã‚¹ã‚’è¦æ±‚ã§ãるよã†ã«ã—ã¾ã™ã€‚"
msgid "Allowed to fail"
-msgstr ""
+msgstr "失敗を許容"
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Kubernetes クラスターを追加ãŠã‚ˆã³ç®¡ç†ã§ãã¾ã™ã€‚"
@@ -864,9 +1021,6 @@ msgstr "ã‚ã‚‹ã„ã¯ã€ %{personal_access_token_link} を使用ã™ã‚‹ã“ã¨ã‚‚ã
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr "ユーザーãŒå¼·åˆ¶çš„ãª2è¦ç´ èªè¨¼ã‚’無視ã§ãる時間(時間å˜ä½)"
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr "ã“ã®ãƒ•ã‚©ãƒ¼ãƒ ã‚’é€ä¿¡ã™ã‚‹ã¨è‡ªå‹•çš„ã« SSH éµã‚’生æˆã—ã¾ã™ã€‚詳細ã«ã¤ã„ã¦ã¯æ–‡æ›¸ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr "アプリケーション㮠%{link_to_client} ãŒã‚ãªãŸã® GitLab アカウントã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’è¦æ±‚ã—ã¦ã„ã¾ã™ã€‚"
@@ -900,12 +1054,15 @@ msgstr "Blobã®ãƒ—レビュー中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred when toggling the notification subscription"
msgstr "通知購読ã®åˆ‡ã‚Šæ›¿ãˆæ™‚ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr "コメントã®è§£æ±ºä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr "検討ã®è§£æ±ºä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+
msgid "An error occurred when updating the issue weight"
msgstr "課題ã®ã‚¦ã‚¨ã‚¤ãƒˆæ›´æ–°æ™‚ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
-msgid "An error occurred while adding approver"
-msgstr "承èªè€…ã®è¿½åŠ ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
-
msgid "An error occurred while deleting the approvers group"
msgstr "承èªè€…グループã®å‰Šé™¤ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -916,7 +1073,7 @@ msgid "An error occurred while detecting host keys"
msgstr "ホストキーã®æ¤œå‡ºä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred while disabling Service Desk."
-msgstr ""
+msgstr "サービスデスクã®ç„¡åŠ¹åŒ–中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while dismissing the alert. Refresh the page and try again."
msgstr "アラートã®æ¶ˆåŽ»ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ページを更新ã—ã¦ã‚„ã‚Šç›´ã—ã¦ä¸‹ã•ã„。"
@@ -925,28 +1082,43 @@ msgid "An error occurred while dismissing the feature highlight. Refresh the pag
msgstr "ãƒã‚¤ãƒ©ã‚¤ãƒˆã‚’消去ã—ã¦ã„ã‚‹ã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ページを更新ã—ã¦ã‚‚ã†ä¸€åº¦æ¶ˆåŽ»ã—ã¦ãã ã•ã„。"
msgid "An error occurred while enabling Service Desk."
+msgstr "サービスデスクã®æœ‰åŠ¹åŒ–中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
msgstr ""
+msgid "An error occurred while fetching label colors."
+msgstr "ラベルã®è‰²ã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+
msgid "An error occurred while fetching markdown preview"
msgstr "Markdown プレビューã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred while fetching pending comments"
-msgstr ""
+msgstr "ä¿ç•™ä¸­ã®ã‚³ãƒ¡ãƒ³ãƒˆã‚’å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+
+msgid "An error occurred while fetching projects autocomplete."
+msgstr "プロジェクトã®ã‚ªãƒ¼ãƒˆã‚³ãƒ³ãƒ—リートå–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while fetching sidebar data"
msgstr "サイドãƒãƒ¼ã®ãƒ‡ãƒ¼ã‚¿å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-msgid "An error occurred while fetching stages."
-msgstr ""
-
msgid "An error occurred while fetching the Service Desk address."
-msgstr ""
+msgstr "サービスデスクアドレスã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr "ボードリストã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+
+msgid "An error occurred while fetching the builds."
+msgstr "ビルドã®ãƒ•ã‚§ãƒƒãƒä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while fetching the job log."
-msgstr ""
+msgstr "ã“ã®ã‚¸ãƒ§ãƒ–ã®ãƒ­ã‚°ã‚’フェッãƒã™ã‚‹é–“ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while fetching the job."
-msgstr ""
+msgstr "ã“ã®ã‚¸ãƒ§ãƒ–ã®å–å¾—ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while fetching the jobs."
msgstr "ジョブã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -957,6 +1129,9 @@ msgstr "パイプラインã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while fetching the releases. Please try again."
msgstr "リリースã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+msgid "An error occurred while fetching this tab."
+msgstr "ã“ã®ã‚¿ãƒ–ã®ãƒ•ã‚§ãƒƒãƒä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+
msgid "An error occurred while getting projects"
msgstr "プロジェクトã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -967,7 +1142,7 @@ msgid "An error occurred while initializing path locks"
msgstr "パスロックã®åˆæœŸåŒ–中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred while loading chart data"
-msgstr ""
+msgstr "グラフデータã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while loading commit signatures"
msgstr "コミットシグãƒãƒãƒ£ã®èª­è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -990,8 +1165,11 @@ msgstr "サブスクリプションã®è©³ç´°ã‚’ロード中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿ
msgid "An error occurred while making the request."
msgstr "リクエスト作æˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-msgid "An error occurred while removing approver"
-msgstr "承èªè€…ã®å‰Šé™¤ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "An error occurred while moving the issue."
+msgstr "課題ã®ç§»å‹•ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+
+msgid "An error occurred while parsing recent searches"
+msgstr "検索履歴ã®è§£æžä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred while removing epics."
msgstr "エピックã®å‰Šé™¤ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -1044,6 +1222,9 @@ msgstr "ジョブトレースã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred whilst fetching the latest pipeline."
msgstr "最新ã®ãƒ‘イプラインã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr "ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ«ã®èª­è¾¼ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -1051,7 +1232,7 @@ msgid "An error occurred whilst loading the file content."
msgstr "ファイルã®å†…容を読込中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred whilst loading the file."
-msgstr ""
+msgstr "ファイルã®ãƒ­ãƒ¼ãƒ‰ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred whilst loading the merge request changes."
msgstr "マージリクエストã®å¤‰æ›´ã‚’読込中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -1060,10 +1241,10 @@ msgid "An error occurred whilst loading the merge request version data."
msgstr "マージリクエストã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…報を読込中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred whilst loading the merge request."
-msgstr ""
+msgstr "マージリクエストã®ãƒ­ãƒ¼ãƒ‰ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred whilst loading the pipelines jobs."
-msgstr ""
+msgstr "パイプラインジョブã®ãƒ­ãƒ¼ãƒ‰ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred. Please try again."
msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚å†åº¦ãŠè©¦ã—ãã ã•ã„。"
@@ -1087,7 +1268,7 @@ msgid "Analytics"
msgstr "アクセス解æž"
msgid "Ancestors"
-msgstr ""
+msgstr "祖先"
msgid "Anonymous"
msgstr "匿å"
@@ -1101,17 +1282,29 @@ msgstr "ä»»æ„ã®"
msgid "Any Label"
msgstr "ä»»æ„ã®ãƒ©ãƒ™ãƒ«"
-msgid "Any encrypted tokens"
+msgid "Any Milestone"
msgstr ""
+msgid "Any encrypted tokens"
+msgstr "æš—å·åŒ–済ã¿ãƒˆãƒ¼ã‚¯ãƒ³"
+
+msgid "Any namespace"
+msgstr "ä»»æ„ã®ãƒãƒ¼ãƒ ã‚¹ãƒšãƒ¼ã‚¹"
+
msgid "Appearance"
msgstr "外観"
msgid "Appearance was successfully created."
-msgstr ""
+msgstr "外観ã¯æ­£å¸¸ã«ä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
msgid "Appearance was successfully updated."
-msgstr ""
+msgstr "外観ã¯æ­£å¸¸ã«æ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚"
+
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr "コメントを%{TABLEFLIP} ã«è¿½åŠ "
+
+msgid "Append the comment with %{shrug}"
+msgstr "コメントを %{shrug} ã«è¿½åŠ "
msgid "Application"
msgstr "アプリケーション"
@@ -1120,13 +1313,16 @@ msgid "Application ID"
msgstr "アプリケーション ID"
msgid "Application settings saved successfully"
-msgstr ""
+msgstr "アプリケーション設定ã¯æ­£å¸¸ã«ä¿å­˜ã•ã‚Œã¾ã—ãŸ"
+
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr "アプリケーションã¯ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¾ã—ãŸãŒã€ç ´æ£„ã«å¤±æ•—ã—ã¾ã—ãŸ: %{error_message}"
msgid "Application was successfully destroyed."
-msgstr ""
+msgstr "アプリケーションã¯æ­£å¸¸ã«ç ´æ£„ã•ã‚Œã¾ã—ãŸã€‚"
msgid "Application was successfully updated."
-msgstr ""
+msgstr "アプリケーションã¯æ­£å¸¸ã«æ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚"
msgid "Application: %{name}"
msgstr "アプリケーション:%{name}"
@@ -1140,13 +1336,25 @@ msgstr "é©ç”¨æ¸ˆã¿"
msgid "Apply suggestion"
msgstr "æ案をé©ç”¨"
+msgid "Applying command"
+msgstr "コマンドをé©ç”¨"
+
+msgid "Applying command to %{commandDescription}"
+msgstr "コマンドを %{commandDescription} ã«é©ç”¨ã™ã‚‹"
+
+msgid "Applying multiple commands"
+msgstr "複数ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’é©ç”¨"
+
+msgid "Applying suggestion"
+msgstr "æ案をé©ç”¨"
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] "%d 人ã®ãƒ¡ãƒ³ãƒãƒ¼"
msgid "ApprovalRuleRemove|Approvals from this member are not revoked."
msgid_plural "ApprovalRuleRemove|Approvals from these members are not revoked."
-msgstr[0] ""
+msgstr[0] "ã“ã®ãƒ¡ãƒ³ãƒãƒ¼ã‹ã‚‰ã®æ‰¿èªã¯å–り消ã•ã‚Œã¾ã›ã‚“。"
msgid "ApprovalRuleRemove|You are about to remove the %{name} approver group which has %{nMembers}."
msgstr "%{nMembers} 人ã®ãƒ¡ãƒ³ãƒãƒ¼ãŒã„ã‚‹ %{name} 承èªè€…グループを削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚"
@@ -1157,10 +1365,10 @@ msgstr[0] "%d 人ã®ãƒ¡ãƒ³ãƒãƒ¼"
msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
-msgstr[0] ""
+msgstr[0] "%{membersCount} åã®ã†ã¡ %{count} åã‹ã‚‰ã®æ‰¿èªãŒå¿…è¦"
msgid "ApprovalRule|All members with Developer role or higher and code owners (if any)"
-msgstr ""
+msgstr "開発者ã¾ãŸã¯ãれ以上ã®å½¹å‰²ã‚’ã‚‚ã¤å…¨ã¦ã®ãƒ¡ãƒ³ãƒãƒ¼ãŠã‚ˆã³ã‚³ãƒ¼ãƒ‰æ‰€æœ‰è€…ã®ãƒ¡ãƒ³ãƒãƒ¼"
msgid "ApprovalRule|Members"
msgstr "メンãƒãƒ¼"
@@ -1177,12 +1385,6 @@ msgstr ""
msgid "Approvals"
msgstr "承èª"
-msgid "Approvals required"
-msgstr "承èªãŒå¿…è¦"
-
-msgid "Approvers"
-msgstr "承èªè€…"
-
msgid "Apr"
msgstr "4月"
@@ -1193,7 +1395,7 @@ msgid "Archive jobs"
msgstr "アーカイブジョブ"
msgid "Archive project"
-msgstr ""
+msgstr "プロジェクトをアーカイブ"
msgid "Archived project! Repository and other project resources are read-only"
msgstr "ã“ã®ãƒ—ロジェクトã¯ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã•ã‚Œã¦ã„ã¾ã™ã€‚リãƒã‚¸ãƒˆãƒªãŠã‚ˆã³ãã®ä»–ã®ãƒ—ロジェクトリソースã¯èª­ã¿å–り専用ã§ã™"
@@ -1208,11 +1410,23 @@ msgid "Are you sure"
msgstr "よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "Are you sure that you want to archive this project?"
-msgstr ""
+msgstr "本当ã«ã“ã®ãƒ—ロジェクトをアーカイブã—ã¾ã™ã‹ï¼Ÿ"
msgid "Are you sure that you want to unarchive this project?"
+msgstr "ã“ã®ãƒ—ロジェクトã®ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–を解除ã—ã¦ã‚ˆã‚ã—ã„ã§ã™ã‹?"
+
+msgid "Are you sure you want to cancel creating this comment?"
+msgstr "ã“ã®ã‚³ãƒ¡ãƒ³ãƒˆã®ä½œæˆã‚’キャンセルã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr "ã“ã®ã‚³ãƒ¡ãƒ³ãƒˆã®ç·¨é›†ã‚’キャンセルã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
+msgid "Are you sure you want to delete this list?"
+msgstr "本当ã«ã“ã®ãƒªã‚¹ãƒˆã‚’消去ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹?"
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "ã“ã®ãƒ‘イプラインスケジュールを削除ã—ã¾ã™ã‹ï¼Ÿ"
@@ -1226,7 +1440,7 @@ msgid "Are you sure you want to lose your issue information?"
msgstr "本当ã«èª²é¡Œæƒ…報を削除ã—ã¾ã™ã‹?"
msgid "Are you sure you want to permanently delete this license?"
-msgstr ""
+msgstr "ã“ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’完全ã«å‰Šé™¤ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr "公開éµã‚’å†ç”Ÿæˆã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹? ミラーリングを行ã†å‰ã«ãƒªãƒ¢ãƒ¼ãƒˆã‚µãƒ¼ãƒãƒ¼ã®å…¬é–‹éµã‚’æ›´æ–°ã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。"
@@ -1234,18 +1448,6 @@ msgstr "公開éµã‚’å†ç”Ÿæˆã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹? ミラーリングã
msgid "Are you sure you want to remove %{group_name}?"
msgstr "ã“ã® %{group_name} を削除ã—ã¦ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
-msgid "Are you sure you want to remove approver %{name}"
-msgstr "承èªè€… %{name} を削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
-
-msgid "Are you sure you want to remove approver %{name}?"
-msgstr "承èªè€… %{name} を削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
-
-msgid "Are you sure you want to remove group %{name}"
-msgstr "グループ %{name} を削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
-
-msgid "Are you sure you want to remove group %{name}?"
-msgstr "グループ %{name} を削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
-
msgid "Are you sure you want to remove the attachment?"
msgstr "添付ファイルを削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
@@ -1256,11 +1458,14 @@ msgid "Are you sure you want to reset registration token?"
msgstr "本当ã«ç™»éŒ²ãƒˆãƒ¼ã‚¯ãƒ³ã‚’リセットã—ã¾ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
+msgstr "本当ã«SCIMトークンをリセットã—ã¦ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿæ–°ã—ã„トークンを更新ã™ã‚‹ã¾ã§SCIMプロビジョニングã¯æ©Ÿèƒ½ã—ãªããªã‚Šã¾ã™ã€‚"
msgid "Are you sure you want to reset the health check token?"
msgstr "本当ã«ãƒ˜ãƒ«ã‚¹ãƒã‚§ãƒƒã‚¯ãƒˆãƒ¼ã‚¯ãƒ³ã‚’リセットã—ã¾ã™ã‹ï¼Ÿ"
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr "ã“ã®ç’°å¢ƒã‚’åœæ­¢ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
@@ -1273,12 +1478,36 @@ msgstr ""
msgid "Are you sure?"
msgstr "本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr "アーティファクト ID"
msgid "Artifacts"
msgstr "アーティファクト"
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr "Asana - Eメールã®ãªã„ãƒãƒ¼ãƒ ãƒ¯ãƒ¼ã‚¯"
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr "自動的ã«æ¤œæŸ»ã™ã‚‹ãƒ–ランãƒã®ã‚«ãƒ³ãƒžåŒºåˆ‡ã‚Šãƒªã‚¹ãƒˆã€‚ã™ã¹ã¦ã®ãƒ–ランãƒã‚’対象ã«å«ã‚ã‚‹ã«ã¯ç©ºç™½ã®ã¾ã¾ã«ã—ã¾ã™ã€‚"
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr "ユーザーã®ãƒ‘ーソナルアクセストークン。ユーザーã¯ã‚¿ã‚¹ã‚¯ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã™ã¹ã¦ã®ã‚³ãƒ¡ãƒ³ãƒˆã¯ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«å±žã—ã¾ã™ã€‚"
+
msgid "Ascending"
msgstr "昇順"
@@ -1291,6 +1520,9 @@ msgstr "アサーション コンシューマー サービス URL"
msgid "Assets"
msgstr "アセット"
+msgid "Assign"
+msgstr "割り当ã¦"
+
msgid "Assign custom color like #FF0000"
msgstr "#FF0000ã®ã‚ˆã†ãªã‚«ã‚¹ã‚¿ãƒ ã‚«ãƒ©ãƒ¼ã‚’割り当ã¦ã‚‹"
@@ -1306,6 +1538,12 @@ msgstr "ã“ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã«ã„ãã¤ã‹ã®èª²é¡Œã‚’割り当ã¦ã¾ã™
msgid "Assign to"
msgstr "割り当ã¦å…ˆ"
+msgid "Assign yourself to these issues"
+msgstr "ã“れらã®èª²é¡Œã‚’自分ã«å‰²ã‚Šå½“ã¦ã¾ã™"
+
+msgid "Assign yourself to this issue"
+msgstr "ã“ã®èª²é¡Œã‚’自分ã«å‰²ã‚Šå½“ã¦ã¾ã™"
+
msgid "Assigned Issues"
msgstr "割り当ã¦ã‚‰ã‚ŒãŸèª²é¡Œ"
@@ -1328,7 +1566,7 @@ msgid "Assignee(s)"
msgstr "担当者"
msgid "At least one approval from a code owner is required to change files matching the respective CODEOWNER rules."
-msgstr ""
+msgstr "ãã‚Œãžã‚Œã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’変更ã™ã‚‹ã«ã¯ã€CODEOWNERã®ãƒ«ãƒ¼ãƒ«ã«ä¸€è‡´ã™ã‚‹ã€å°‘ãªãã¨ã‚‚1åã®ã‚³ãƒ¼ãƒ‰æ‰€æœ‰è€…ã‹ã‚‰ã®æ‰¿èªãŒå¿…è¦ã§ã™ã€‚"
msgid "Attach a file"
msgstr "ファイルを添付"
@@ -1336,6 +1574,13 @@ msgstr "ファイルを添付"
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "ドラッグ&ドロップã¾ãŸã¯ %{upload_link} ã§ãƒ•ã‚¡ã‚¤ãƒ«ã‚’添付"
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+
+msgid "Attaching the file failed."
+msgstr "ファイルã®æ·»ä»˜ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
+
msgid "Audit Events"
msgstr "監査イベント"
@@ -1349,7 +1594,7 @@ msgid "Authentication Log"
msgstr "èªè¨¼ãƒ­ã‚°"
msgid "Authentication failed: %{error_message}"
-msgstr ""
+msgstr "èªè¨¼å¤±æ•—: %{error_message}"
msgid "Authentication log"
msgstr "èªè¨¼ãƒ­ã‚°"
@@ -1358,10 +1603,10 @@ msgid "Authentication method"
msgstr "èªè¨¼æ–¹æ³•"
msgid "Authentication method updated"
-msgstr ""
+msgstr "èªè¨¼æ–¹æ³•ã‚’æ›´æ–°ã—ã¾ã—ãŸ"
msgid "Authentication via U2F device failed."
-msgstr ""
+msgstr "U2Fデãƒã‚¤ã‚¹ã«ã‚ˆã‚‹èªè¨¼ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
msgid "Author"
msgstr "作æˆè€…"
@@ -1382,7 +1627,7 @@ msgid "Authorize %{link_to_client} to use your account?"
msgstr "ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã« %{link_to_client} を承èªã—ã¾ã™ã‹ï¼Ÿ"
msgid "Authorized %{new_chat_name}"
-msgstr ""
+msgstr "%{new_chat_name} ãŒæ‰¿èªã•ã‚Œã¾ã—ãŸ"
msgid "Authorized At"
msgstr ""
@@ -1403,7 +1648,7 @@ msgid "Auto DevOps, runners and job artifacts"
msgstr "Auto DevOps, Runner,ãŠã‚ˆã³æˆæžœç‰©"
msgid "Auto-cancel redundant, pending pipelines"
-msgstr ""
+msgstr "冗長・ä¿ç•™ä¸­ã®ãƒ‘イプラインを自動キャンセル"
msgid "AutoDevOps|Auto DevOps"
msgstr "Auto DevOps"
@@ -1421,17 +1666,26 @@ msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "詳ã—ãã¯ã€ %{link_to_documentation} を見ã¦ãã ã•ã„。"
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
-msgstr ""
+msgstr "Auto DevOpsã®ãƒ‘イプラインãŒæœ‰åŠ¹ã«ãªã£ã¦ãŠã‚Šã€ä»£æ›¿ã®CIã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ãŒè¦‹ã¤ã‹ã‚‰ãªã„å ´åˆã«ä½¿ç”¨ã—ã¾ã™ã€‚ %{more_information_link}"
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically marked as default internal user"
+msgstr "自動的ã«ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®å†…部ユーザーã¨ã—ã¦ãƒžãƒ¼ã‚¯ã—ã¾ã—ãŸã€‚"
+
msgid "Automatically resolved"
msgstr "自動解決"
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr "注æ„"
+
msgid "Available"
msgstr "利用å¯èƒ½"
@@ -1543,6 +1797,30 @@ msgstr "ãƒãƒƒã‚¸"
msgid "Badges|e.g. %{exampleUrl}"
msgstr "例 %{exampleUrl}"
+msgid "Badge|New"
+msgstr "æ–°"
+
+msgid "Balsamiq file could not be loaded."
+msgstr "Balsamiq ファイルを読ã¿è¾¼ã¿ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
+
+msgid "BambooService|A continuous integration and build server"
+msgstr "継続的インテグレーションã¨ãƒ“ルドサーãƒãƒ¼"
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr "APIアクセス権をæŒã¤ãƒ¦ãƒ¼ã‚¶ãƒ¼(該当ã™ã‚‹å ´åˆ)"
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr "アトラシアンBamboo CI"
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr "KEYã®ã‚ˆã†ãªBambooã®ãƒ“ルドプランキー"
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr "Bamboo ã®ãƒ«ãƒ¼ãƒˆURL 例: https://bamboo.example.com"
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr "ä¿ç•™ä¸­ã®ã‚³ãƒ¡ãƒ³ãƒˆã‚’ã™ã¹ã¦å‰Šé™¤"
@@ -1550,13 +1828,13 @@ msgid "BatchComments|Discard review?"
msgstr "レビューを破棄ã—ã¾ã™ã‹ï¼Ÿ"
msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
-msgstr ""
+msgstr "ã‚ãªãŸã¯ãƒ¬ãƒ“ューを破棄ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ペンディング中ã®ã‚³ãƒ¡ãƒ³ãƒˆã¯ã™ã¹ã¦ç ´æ£„ã•ã‚Œã¾ã™ã€‚破棄ã•ã‚ŒãŸã‚³ãƒ¡ãƒ³ãƒˆã¯%{strong_start}復元ã§ãã¾ã›ã‚“%{strong_end}。"
msgid "Be careful. Changing the project's namespace can have unintended side effects."
-msgstr ""
+msgstr "ã”注æ„ãã ã•ã„。プロジェクトã®åå‰ç©ºé–“を変更ã™ã‚‹ã¨ã€æ„図ã—ãªã„副作用ãŒç™ºç”Ÿã™ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚"
msgid "Be careful. Renaming a project's repository can have unintended side effects."
-msgstr ""
+msgstr "ã”注æ„ãã ã•ã„。プロジェクトã®ãƒªãƒã‚¸ãƒˆãƒªã®åå‰ã‚’変更ã™ã‚‹ã¨ã€æ„図ã—ãªã„副作用ãŒç™ºç”Ÿã™ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚"
msgid "Begin with the selected commit"
msgstr "é¸æŠžã—ãŸã‚³ãƒŸãƒƒãƒˆã§ã¯ã˜ã‚ã‚‹"
@@ -1616,7 +1894,7 @@ msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn
msgstr "ã‚ãªãŸã® GitLab.com 試用版㯠%{expiration_date} ã«æœŸé™åˆ‡ã‚Œã«ãªã‚Šã¾ã—ãŸã€‚%{learn_more_text}"
msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
-msgstr ""
+msgstr "ã‚ãªãŸã® ゴールド試用版ã¯ã€<strong>%{expiration_date} ã®å¾Œã«æœŸé™ãŒåˆ‡ã‚Œã¾ã™</strong>。 GitLab.com Goldã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€ %{features_link} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
msgid "BillingPlans|features"
msgstr "機能"
@@ -1645,12 +1923,29 @@ msgstr "ブロック"
msgid "Blocked"
msgstr "ブロック中"
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+
msgid "Blog"
msgstr "ブログ"
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr "ボード"
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "%{branchName} ブランãƒã¯ã“ã®ãƒ—ロジェクトã®ãƒªãƒã‚¸ãƒˆãƒªã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚"
@@ -1666,6 +1961,9 @@ msgstr "ブランãƒã¯æ—¢ã«ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™"
msgid "Branch name"
msgstr "ブランãƒå"
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "ブランãƒã‚’検索"
@@ -1796,10 +2094,10 @@ msgid "Branches|protected"
msgstr "ä¿è­·"
msgid "Broadcast Message was successfully created."
-msgstr ""
+msgstr "ブロードキャストメッセージã¯æ­£å¸¸ã«ä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
msgid "Broadcast Message was successfully updated."
-msgstr ""
+msgstr "ブロードキャストメッセージã¯æ­£å¸¸ã«æ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚"
msgid "Browse Directory"
msgstr "ディレクトリを表示"
@@ -1816,6 +2114,21 @@ msgstr "ファイルを表示"
msgid "Built-in"
msgstr "ビルトイン"
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr "ビジãƒã‚¹"
@@ -1823,10 +2136,10 @@ msgid "Business metrics (Custom)"
msgstr "ビジãƒã‚¹ãƒ¡ãƒˆãƒªã‚¯ã‚¹ï¼ˆã‚«ã‚¹ã‚¿ãƒ ï¼‰"
msgid "Buy EE"
-msgstr ""
+msgstr "EE版を購入"
msgid "Buy GitLab Enterprise Edition"
-msgstr ""
+msgstr "GitLabエンタープライズエディションを購入"
msgid "By %{user_name}"
msgstr ""
@@ -1834,6 +2147,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "作者"
@@ -1853,7 +2169,7 @@ msgid "CI Lint"
msgstr "CI Lint"
msgid "CI variables"
-msgstr ""
+msgstr "CI 変数"
msgid "CI will run using the credentials assigned above."
msgstr "CI ã¯ä¸Šè¨˜ã§å‰²ã‚Šå½“ã¦ã‚‰ã‚ŒãŸè³‡æ ¼æƒ…報を元ã«å®Ÿè¡Œã—ã¾ã™ã€‚"
@@ -1889,7 +2205,7 @@ msgid "CICD|Default to Auto DevOps pipeline"
msgstr "デフォルト㮠Auto DevOps パイプライン"
msgid "CICD|Default to Auto DevOps pipeline for all projects"
-msgstr ""
+msgstr "ã™ã¹ã¦ã®ãƒ—ロジェクトã§ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã® Auto DevOps パイプライン"
msgid "CICD|Deployment strategy"
msgstr "デプロイ戦略"
@@ -1913,7 +2229,7 @@ msgid "CICD|instance enabled"
msgstr "インスタンスãŒæœ‰åŠ¹"
msgid "CONTRIBUTING"
-msgstr ""
+msgstr "CONTRIBUTING"
msgid "Callback URL"
msgstr "コールãƒãƒƒã‚¯ URL"
@@ -1924,12 +2240,18 @@ msgstr "マージリクエストã”ã¨ã«å¿…è¦ãªæ‰¿èªè€…ã¨æ‰¿èªã‚’上書ã
msgid "Can't find HEAD commit for this branch"
msgstr "ã“ã®ãƒ–ランãƒã«ã¯ HEAD コミットãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr "グループ管ç†ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒãªã„ã¨ã‚°ãƒ«ãƒ¼ãƒ—メンãƒãƒ¼ã¯å‰Šé™¤ã§ãã¾ã›ã‚“"
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgid "Can't scan the code?"
msgstr ""
+msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
+msgstr "カナリアデプロイã¯ã€ä¸€éƒ¨ã®ã‚¢ãƒ—リケーションãŒã‚ãªãŸã®ã‚¢ãƒ—リケーションã®æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«æ›´æ–°ã•ã‚Œã‚‹ã€ã¨ã„ã†ä¸€èˆ¬çš„ãªCI戦略ã§ã™ã€‚"
+
msgid "Cancel"
msgstr "キャンセル"
@@ -1948,9 +2270,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr "管ç†ä¸‹ã® Kubernetes クラスターを変更ã§ãã¾ã›ã‚“"
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr "内部IDã§ã‚°ãƒ«ãƒ¼ãƒ—マイルストーンをå‚ç…§ã§ãã¾ã›ã‚“。"
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -1966,6 +2294,12 @@ msgstr "証明書 (PEM)"
msgid "Change Weight"
msgstr "ウェイトを変更ã™ã‚‹"
+msgid "Change assignee(s)"
+msgstr "担当者を変更"
+
+msgid "Change assignee(s)."
+msgstr "担当者を変更ã—ã¾ã™ã€‚"
+
msgid "Change path"
msgstr ""
@@ -1978,6 +2312,15 @@ msgstr "テンプレートを変更"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "GitLab UI ã®æ›´æ–°é »åº¦ã‚’変更ã™ã‚‹ã«ã¯ã“ã®å€¤ã‚’変更ã—ã¦ãã ã•ã„。"
+msgid "Change title"
+msgstr "タイトル変更"
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "ピック先ブランãƒ:"
@@ -2002,6 +2345,12 @@ msgstr "<b>source</b>リビジョンãŒ<b>target</b>リビジョン内ã«å–ã‚Šè
msgid "Changes suppressed. Click to show."
msgstr "変更ã¯æŠ‘制ã•ã‚Œã¾ã—ãŸã€‚クリックã—ã¦è¡¨ç¤º"
+msgid "Changes the title to \"%{title_param}\"."
+msgstr "タイトルを \"%{title_param}\" ã«å¤‰æ›´ã—ã¾ã™ã€‚"
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr "ãƒãƒ£ãƒ¼ãƒˆ"
@@ -2029,6 +2378,9 @@ msgstr "承èªã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚’確èªã™ã‚‹"
msgid "Checking branch availability..."
msgstr "ブランãƒãŒåˆ©ç”¨å¯èƒ½ã‹ç¢ºèªã—ã¦ã„ã¾ã™â€¦"
+msgid "Checking username availability..."
+msgstr "ユーザーåãŒåˆ©ç”¨å¯èƒ½ã‹ç¢ºèªã—ã¦ã„ã¾ã™..."
+
msgid "Cherry-pick this commit"
msgstr "ã“ã®ã‚³ãƒŸãƒƒãƒˆã‚’ãƒã‚§ãƒªãƒ¼ãƒ”ック"
@@ -2050,6 +2402,9 @@ msgstr "ファイルをé¸æŠžã—ã¦ãã ã•ã„"
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr "テンプレートをé¸æŠžã—ã¦ãã ã•ã„"
+
msgid "Choose a template..."
msgstr "テンプレートをé¸æŠžã—ã¦ãã ã•ã„..."
@@ -2063,7 +2418,7 @@ msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent
msgstr "<code>clone</code> ã¾ãŸã¯ <code>fetch</code> ã‚’é¸æŠžã—ã¦æœ€æ–°ã®ã‚¢ãƒ—リケーションコードをå–å¾—ã—ã¦ãã ã•ã„"
msgid "Choose file…"
-msgstr ""
+msgstr "ファイルをé¸æŠž..."
msgid "Choose the top-level group for your repository imports."
msgstr "インãƒãƒ¼ãƒˆãƒªãƒã‚¸ãƒˆãƒªã®ãƒˆãƒƒãƒ—レベルã®ã‚°ãƒ«ãƒ¼ãƒ—ã‚’é¸æŠžã—ã¦ãã ã•ã„。"
@@ -2080,7 +2435,7 @@ msgstr "CI/CD パイプラインを実行ã—ãŸã„リãƒã‚¸ãƒˆãƒªã‚’é¸æŠžã—ã¦
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr "セカンダリノードã¨åŒæœŸã•ã›ãŸã„シャードをé¸æŠžã—ã¦ãã ã•ã„。"
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2114,7 +2469,7 @@ msgid "CiStatusLabel|skipped"
msgstr "スキップ済ã¿"
msgid "CiStatusLabel|waiting for delayed job"
-msgstr ""
+msgstr "予約済ã¿ã‚¸ãƒ§ãƒ–実行待ã¡"
msgid "CiStatusLabel|waiting for manual action"
msgstr "手動実行待ã¡"
@@ -2129,7 +2484,7 @@ msgid "CiStatusText|created"
msgstr "作æˆæ¸ˆã¿"
msgid "CiStatusText|delayed"
-msgstr ""
+msgstr "é…延"
msgid "CiStatusText|failed"
msgstr "失敗"
@@ -2152,16 +2507,34 @@ msgstr "スキップ済ã¿"
msgid "CiStatus|running"
msgstr "実行中"
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr "キーを入力"
msgid "CiVariables|Input variable value"
msgstr "値を入力"
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr "マスク"
+
msgid "CiVariables|Remove variable row"
msgstr "環境変数を削除"
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr "状態"
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2215,9 +2588,18 @@ msgstr "検索をクリア"
msgid "Clear search input"
msgstr "検索欄ã®æ¶ˆåŽ»"
+msgid "Clear weight"
+msgstr "ウェイトをクリア"
+
+msgid "Clears weight."
+msgstr "ウェイトをクリアã—ã¾ã™ã€‚"
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr "プロジェクトリストã§<strong>プロジェクトå</strong>をクリックã™ã‚‹ã¨ã€ãƒ—ロジェクトã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã«ç§»å‹•ã—ã¾ã™ã€‚"
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr "<strong>ダウンロード</strong> ボタンをクリックã—ã€ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã®å®Œäº†ã‚’ãŠå¾…ã¡ãã ã•ã„。"
@@ -2272,6 +2654,9 @@ msgstr "エピックを閉ã˜ã‚‹"
msgid "Close milestone"
msgstr "マイルストーンを閉ã˜ã‚‹"
+msgid "Close sidebar"
+msgstr "サイドãƒãƒ¼ã‚’é–‰ã˜ã‚‹"
+
msgid "Closed"
msgstr "クローズ"
@@ -2279,7 +2664,7 @@ msgid "Closed issues"
msgstr "クローズã—ãŸèª²é¡Œ"
msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
-msgstr ""
+msgstr "%{custom_domain_start} 詳細情報 %{custom_domain_end}"
msgid "ClusterIntegration| can be used instead of a custom domain."
msgstr "カスタムドメインã®ä»£ã‚ã‚Šã«ä½¿ç”¨ã§ãã¾ã™ã€‚"
@@ -2290,8 +2675,14 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} ã¯æ­£å¸¸ã« Kubernetes クラスターã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¾ã—ãŸ"
-msgid "ClusterIntegration|%{title} upgraded successfully."
-msgstr "%{title} ã¯æ­£å¸¸ã«ã‚¢ãƒƒãƒ—グレードã•ã‚Œã¾ã—ãŸã€‚"
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr "%{title} ã¯æ­£å¸¸ã«ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã§ãã¾ã—ãŸã€‚"
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
+msgstr "サービス・トークンã¯ã€ %{code}cluster-admin%{end_code} 特権をæŒã¤ %{code}kube-system%{end_code} スコープã§ã™ã€‚"
msgid "ClusterIntegration|API URL"
msgstr "API URL"
@@ -2308,12 +2699,24 @@ msgstr "Kubernetes クラスターã®çµ±åˆã‚’追加"
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr "グループ㫠Kubernetes クラスターを追加ã™ã‚‹ã¨ã€ã™ã¹ã¦ã®ãƒ—ロジェクトã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¼ãŒè‡ªå‹•çš„ã«å…±æœ‰ã•ã‚Œã¾ã™ã€‚Review Apps を使用ã—ã€ã‚¢ãƒ—リケーションを導入ã—ã€åŒã˜ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¼ã‚’使用ã™ã‚‹ã™ã¹ã¦ã®ãƒ—ロジェクトã®ãƒ‘イプラインを簡å˜ã«å®Ÿè¡Œã—ã¾ã™ã€‚"
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr "グループã«çµ±åˆã‚’追加ã™ã‚‹ã¨ã€ã™ã¹ã¦ã®ãƒ—ロジェクトã§ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¼ãŒå…±æœ‰ã•ã‚Œã¾ã™ã€‚"
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "ã“ã® Kubernetes クラスター統åˆã«é–¢ã™ã‚‹è©³ç´°ã‚ªãƒ—ション"
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2329,6 +2732,9 @@ msgstr "プロジェクトã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ:%{error}
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr "ゾーンã®ãƒžã‚·ãƒ³ã‚¿ã‚¤ãƒ—ã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ:%{error}"
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr "アプリケーション"
@@ -2345,7 +2751,7 @@ msgid "ClusterIntegration|CA Certificate"
msgstr "CA 証明書"
msgid "ClusterIntegration|Cert-Manager"
-msgstr ""
+msgstr "Cert-Manager"
msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
msgstr ""
@@ -2387,7 +2793,7 @@ msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr "Kubernetes クラスターåをコピー"
msgid "ClusterIntegration|Copy Service Token"
-msgstr ""
+msgstr "サービストークンをコピー"
msgid "ClusterIntegration|Create Kubernetes cluster"
msgstr "Kubernetes クラスターを作æˆ"
@@ -2437,6 +2843,9 @@ msgstr "GitLab Runner"
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Google Cloud Platform プロジェクト"
@@ -2473,20 +2882,11 @@ msgstr "Ingress エンドãƒã‚¤ãƒ³ãƒˆ"
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr "インストール"
-
-msgid "ClusterIntegration|Installed"
-msgstr "インストール済ã¿"
-
-msgid "ClusterIntegration|Installing"
-msgstr "インストール中"
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr "Ingress をインストールã™ã‚‹ã¨è¿½åŠ ã®ã‚³ã‚¹ãƒˆãŒã‹ã‹ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ 詳細ã«ã¤ã„ã¦ã¯ %{pricingLink} ã‚’å‚ç…§"
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
-msgstr "Knative をインストールã™ã‚‹ã¨è¿½åŠ ã®ã‚³ã‚¹ãƒˆãŒã‹ã‹ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ 詳細ã«ã¤ã„ã¦ã¯ %{pricingLink} ã‚’å‚ç…§"
+msgid "ClusterIntegration|Instance cluster"
+msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
msgstr "Kubernetes クラスターを自動統åˆ"
@@ -2518,6 +2918,9 @@ msgstr "Knativeドメインå:"
msgid "ClusterIntegration|Knative Endpoint:"
msgstr "Knative エンドãƒã‚¤ãƒ³ãƒˆ:"
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2554,6 +2957,9 @@ msgstr "Kubernetes ã®è©³ç´°"
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr "グループ Kubernetes クラスターã®è©³ç´°"
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr "Let's Encrypt"
@@ -2563,9 +2969,6 @@ msgstr "マシンタイプ"
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr "Kubernetes クラスター を作æˆã™ã‚‹ã«ã¯ã€ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã® %{link_to_requirements} を確èªã—ã¦ãã ã•ã„"
-msgid "ClusterIntegration|Manage"
-msgstr "管ç†"
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr "%{link_gke} ã«ã‚¢ã‚¯ã‚»ã‚¹ã—㦠Kubernetes クラスターを管ç†"
@@ -2629,8 +3032,8 @@ msgstr "å¿…è¦ã«å¿œã˜ã¦ã“れをã‚ãªãŸã®ãƒ›ã‚¹ãƒˆåã«ç½®ãæ›ãˆã¾ã™
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "インストール開始ã«å¤±æ•—ã—ã¾ã—ãŸ"
-msgid "ClusterIntegration|Retry update"
-msgstr "アップデートをå†è©¦è¡Œ"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
+msgstr ""
msgid "ClusterIntegration|Save changes"
msgstr "変更をä¿å­˜"
@@ -2666,10 +3069,10 @@ msgid "ClusterIntegration|Select zone to choose machine type"
msgstr "ゾーンをé¸æŠžã—ã¦ãƒžã‚·ãƒ³ã‚¿ã‚¤ãƒ—ã‚’é¸æŠž"
msgid "ClusterIntegration|Service Token"
-msgstr ""
+msgstr "サービストークン"
msgid "ClusterIntegration|Service token is required."
-msgstr ""
+msgstr "サービストークンãŒå¿…è¦ã§ã™ã€‚"
msgid "ClusterIntegration|Show"
msgstr "表示"
@@ -2683,12 +3086,36 @@ msgstr "Google Kubernetes Engine 上㮠Kubernetes クラスターを作æˆä¸­ã
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "%{title} ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
+msgstr ""
+
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
+msgstr ""
+
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
+msgstr ""
+
msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
+msgstr ""
+
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr "ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ %{link_to_container_project} 㧠Kubernetes クラスターを作æˆã™ã‚‹ã®ã«ä»¥ä¸‹ã®æ¨©é™ãŒå¿…è¦ã§ã™"
@@ -2701,23 +3128,11 @@ msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "Kubernetes クラスターを切り替ãˆ"
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Updating"
-msgstr "アップデート中"
-
-msgid "ClusterIntegration|Upgrade"
-msgstr "アップグレード"
-
-msgid "ClusterIntegration|Upgrade failed"
-msgstr "アップグレードã«å¤±æ•—ã—ã¾ã—ãŸ"
-
-msgid "ClusterIntegration|Upgraded"
-msgstr "アップグレード済ã¿"
-
-msgid "ClusterIntegration|Upgrading"
-msgstr "アップグレード中"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgstr ""
msgid "ClusterIntegration|Validating project billing status"
msgstr "プロジェクトã®è«‹æ±‚ステータスを検証ã—ã¦ã„ã¾ã™"
@@ -2728,6 +3143,9 @@ msgstr "GCP 上ã®ãƒ—ロジェクトã®è¦æ±‚ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã‚‹ã“ã¨ã‚
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "ã“ã®ãƒ—ロジェクト㫠Kubernetes クラスターを関連付ã‘ã‚‹ã“ã¨ã§ã€Review Apps ã®ä½¿ç”¨ã€ã‚¢ãƒ—リケーションã®ãƒ‡ãƒ—ロイã€ãƒ‘イプラインã®å®Ÿè¡Œãªã©ã‚’ç°¡å˜ã«è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚"
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr "次ã®ã‚¢ãƒ—リケーションをインストールã™ã‚‹å‰ã«ã€Helm Tiller をインストールã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“"
@@ -2737,6 +3155,9 @@ msgstr "Knative をインストールã™ã‚‹ã«ã¯ã€RBAC 対応ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "アカウント㫠%{link_to_kubernetes_engine} ãŒå¿…è¦ã§ã™ã€‚"
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr "ゾーン"
@@ -2765,10 +3186,10 @@ msgid "Code"
msgstr "コード"
msgid "Code Owners"
-msgstr ""
+msgstr "コードオーナー"
msgid "Code owner approval is required"
-msgstr ""
+msgstr "コードオーナーã®æ‰¿èªãŒå¿…è¦ã§ã™"
msgid "Code owners"
msgstr "コードオーナー"
@@ -2777,7 +3198,7 @@ msgid "CodeOwner|Pattern"
msgstr "パターン"
msgid "Cohorts"
-msgstr ""
+msgstr "コホート"
msgid "Collapse"
msgstr "折りãŸãŸã‚€"
@@ -2788,9 +3209,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr "サイドãƒãƒ¼ã‚’éš ã™"
+msgid "ComboSearch is not defined"
+msgstr "ComboSearch ãŒå®šç¾©ã•ã‚Œã¦ã„ã¾ã›ã‚“"
+
msgid "Command line instructions"
msgstr "コマンドライン命令"
+msgid "Commands applied"
+msgstr "é©ç”¨æ¸ˆã¿ã‚³ãƒžãƒ³ãƒ‰"
+
msgid "Comment"
msgstr "コメント"
@@ -2809,6 +3236,9 @@ msgstr "ã“ã®æ¤œè¨Žã«ã‚³ãƒ¡ãƒ³ãƒˆã—未解決ã«ã™ã‚‹"
msgid "Comment form position"
msgstr "コメントフォームã®ä½ç½®"
+msgid "Comment is being updated"
+msgstr "コメントãŒæ›´æ–°ã•ã‚Œã¦ã„ã¾ã™"
+
msgid "Comments"
msgstr "コメント"
@@ -2880,7 +3310,7 @@ msgid "Commit…"
msgstr "コミット"
msgid "Company"
-msgstr ""
+msgstr "会社"
msgid "Compare"
msgstr "比較"
@@ -2927,6 +3357,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr "Gitaly ã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã‚’設定ã—ã¾ã™ã€‚"
+msgid "Configure Let's Encrypt"
+msgstr "Let's Encryptを設定"
+
msgid "Configure Tracing"
msgstr "トレースã®æ§‹æˆ"
@@ -2952,9 +3385,15 @@ msgid "Configure the way a user creates a new account."
msgstr "ユーザーãŒæ–°ã—ã„アカウントを作æˆã™ã‚‹æ–¹æ³•ã‚’設定ã—ã¾ã™ã€‚"
msgid "Confirm"
+msgstr "確èª"
+
+msgid "Confirmation email sent to %{email}"
msgstr ""
msgid "Confirmation required"
+msgstr "確èªãŒå¿…è¦ã§ã™"
+
+msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
msgid "Connect"
@@ -2969,9 +3408,15 @@ msgstr "GitHubã‹ã‚‰ãƒªãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶š"
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr "外部リãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶šã—ã¦ã€æ–°ã—ã„コミットãŒã‚ã‚‹ã¨CI/CDパイプラインを実行ã—ã¾ã™ã€‚CI/CDã®æ©Ÿèƒ½ãŒæœ‰åŠ¹ã§ã‚ã‚‹ã¨ãã®ã¿ã€GitLabプロジェクトã¯ä½œæˆã•ã‚Œã¾ã™ã€‚"
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr "接続ã—ã¦ã„ã¾ã™..."
+msgid "Connection failure"
+msgstr "接続ã«å¤±æ•—ã—ã¾ã—ãŸ"
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -2982,13 +3427,13 @@ msgid "Contact sales to upgrade"
msgstr "アップグレードã®å•ã„åˆã‚ã›"
msgid "Contact your Administrator to upgrade your license."
-msgstr ""
+msgstr "システム管ç†è€…ã«é€£çµ¡ã—ã¦ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’アップグレードã—ã¦ãã ã•ã„。"
msgid "Container Registry"
msgstr "コンテナレジストリ"
msgid "Container registry images"
-msgstr ""
+msgstr "コンテナレジストリã®ã‚¤ãƒ¡ãƒ¼ã‚¸"
msgid "ContainerRegistry|Created"
msgstr "作æˆæ¸ˆã¿"
@@ -3035,6 +3480,9 @@ msgstr "GitLabã¨çµ±åˆã•ã‚ŒãŸã‚³ãƒ³ãƒ†ãƒŠãƒ¬ã‚¸ã‚¹ãƒˆãƒªã§ã€å…¨ã¦ã®ãƒ—ロ
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr "レジストリイメージã¸ã®èª­ã¿å–り専用アクセスã®ãŸã‚ã« %{deploy_token} を使用ã§ãã¾ã™ã€‚"
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ".gitlab-ci.yml ã®å†…容"
@@ -3080,6 +3528,9 @@ msgstr "%{branch_name} ã¸ã®ã‚³ãƒŸãƒƒãƒˆï¼ˆãƒžãƒ¼ã‚¸ã‚³ãƒŸãƒƒãƒˆã‚’除ãã€6,0
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr "ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„ã€ã“ã®ãƒšãƒ¼ã‚¸ã¯æº–å‚™ãŒæ•´ã†ã¨è‡ªå‹•çš„ã«æ›´æ–°ã•ã‚Œã¾ã™ã€‚"
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr "サードパーティã®ã‚ªãƒ•ã‚¡ãƒ¼ã®è¡¨ç¤ºã‚’管ç†ã—ã¾ã™ã€‚"
@@ -3089,6 +3540,9 @@ msgstr "ã“ã®ã‚»ã‚«ãƒ³ãƒ€ãƒªãƒŽãƒ¼ãƒ‰ã®ãƒªãƒã‚¸ãƒˆãƒªãƒãƒƒã‚¯ãƒ•ã‚£ãƒ«ã®æœ€
msgid "ConvDev Index"
msgstr "ConvDev インデックス"
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr "%{http_label} クローン URL をコピー"
@@ -3107,9 +3561,6 @@ msgstr "SSH 用クローン URL をコピー"
msgid "Copy SSH public key"
msgstr "SSH 公開éµã‚’コピー"
-msgid "Copy SSH public key to clipboard"
-msgstr "SSH 公開éµã‚’クリップボードã«ã‚³ãƒ”ー"
-
msgid "Copy URL to clipboard"
msgstr "クリップボードã«URLをコピー"
@@ -3125,6 +3576,12 @@ msgstr "コミットã®SHAをクリップボードã«ã‚³ãƒ”ー"
msgid "Copy file path to clipboard"
msgstr "ファイルパスをクリップボードã«ã‚³ãƒ”ーã™ã‚‹"
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr "リンクをコピー"
@@ -3132,7 +3589,10 @@ msgid "Copy reference to clipboard"
msgstr "クリップボードã¸ã‚³ãƒ”ー"
msgid "Copy secret to clipboard"
-msgstr ""
+msgstr "クリップボードã«ã‚·ãƒ¼ã‚¯ãƒ¬ãƒƒãƒˆã‚’コピー"
+
+msgid "Copy source to clipboard"
+msgstr "ソースをクリップボードã«ã‚³ãƒ”ー"
msgid "Copy to clipboard"
msgstr "クリップボードã«ã‚³ãƒ”ー"
@@ -3141,19 +3601,25 @@ msgid "Copy token to clipboard"
msgstr "トークンをクリップボードã«ã‚³ãƒ”ーã—ã¾ã™"
msgid "Could not authorize chat nickname. Try again!"
-msgstr ""
+msgstr "ãƒãƒ£ãƒƒãƒˆã®ãƒ‹ãƒƒã‚¯ãƒãƒ¼ãƒ ã‚’承èªã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr "HEADを変更ã§ãã¾ã›ã‚“ã§ã—ãŸï¼š'%{branch}'ブランムãŒå­˜åœ¨ã—ã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
-msgstr ""
+msgstr "ãƒãƒ£ãƒƒãƒˆã®ãƒ‹ãƒƒã‚¯ãƒãƒ¼ãƒ  %{chat_name} を削除ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "Could not remove the trigger."
-msgstr ""
+msgstr "トリガーを除去ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
msgstr "パイプラインステータスをå–å¾—ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚トラブルシューティングã®æ‰‹é †ã«ã¤ã„ã¦ã¯ã€ %{linkStart} マニュアルをå‚ç…§ã—ã¦ãã ã•ã„。%{linkEnd}"
@@ -3177,11 +3643,20 @@ msgid "Create New Domain"
msgstr "æ–°ã—ã„ドメインを作æˆ"
msgid "Create a GitLab account first, and then connect it to your %{label} account."
+msgstr "ã¯ã˜ã‚ã«GitLabアカウントを作æˆã—ã€ãã®å¾Œ %{label} ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«æŽ¥ç¶šã—ã¾ã™ã€‚"
+
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
msgstr ""
+msgid "Create a merge request."
+msgstr "マージリクエストを作æˆ."
+
msgid "Create a new branch"
msgstr "æ–°ã—ã„ブランãƒã‚’作æˆ"
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr "課題ã®æ–°è¦ä½œæˆ"
@@ -3254,6 +3729,12 @@ msgstr "プロジェクトラベルを作æˆ"
msgid "Create your first page"
msgstr "最åˆã®ãƒšãƒ¼ã‚¸ã‚’作æˆã™ã‚‹"
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr "ã‚ãªãŸã¯ã€ã‚°ãƒ«ãƒ¼ãƒ—を作æˆã™ã‚‹æ¨©é™ã‚’ã‚‚ã£ã¦ã„ã¾ã›ã‚“。"
+
msgid "CreateTag|Tag"
msgstr "ã‚¿ã‚°"
@@ -3269,12 +3750,27 @@ msgstr "作æˆæ—¥"
msgid "Created by me"
msgstr "自分ãŒä½œæˆ"
+msgid "Created issue %{issueLink}"
+msgstr "作æˆã—ãŸèª²é¡Œ %{issueLink}"
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr "%{projectLink} ã«èª²é¡Œ %{issueLink} を作æˆã—ã¾ã—ãŸ"
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr "%{projectLink} ã«ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ %{mergeRequestLink} を作æˆã—ã¾ã—ãŸ"
+
msgid "Created on"
msgstr "作æˆæ—¥æ™‚"
msgid "Created on:"
msgstr "作æˆæ—¥æ™‚:"
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr "ã“ã®èª²é¡Œã‚’解決ã™ã‚‹ãŸã‚ã«'%{branch_name}'ブランãƒã¨ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’作æˆã—ã¾ã™ã€‚"
+
msgid "Creating epic"
msgstr "エピックを作æˆã—ã¦ã„ã¾ã™"
@@ -3293,6 +3789,9 @@ msgstr "ç¾åœ¨ã®ãƒ—ロジェクト"
msgid "Current node"
msgstr "ç¾åœ¨ã®ãƒŽãƒ¼ãƒ‰"
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr "プロフィール"
@@ -3371,7 +3870,19 @@ msgstr "ã™ã¹ã¦"
msgid "DashboardProjects|Personal"
msgstr "個人"
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
+msgstr "ダッシュボード"
+
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Data is still calculating..."
@@ -3380,6 +3891,18 @@ msgstr "データã¯ã¾ã è¨ˆç®—中ã§ã™..."
msgid "Date picker"
msgstr "日付é¸æŠž"
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr "デãƒãƒƒã‚°"
@@ -3399,13 +3922,13 @@ msgid "Default Branch"
msgstr "デフォルトブランãƒ"
msgid "Default artifacts expiration"
-msgstr ""
+msgstr "デフォルトã®ã‚¢ãƒ¼ãƒ†ã‚£ãƒ•ã‚¡ã‚¯ãƒˆã®æœ‰åŠ¹æœŸé™"
msgid "Default classification label"
msgstr "デフォルト分類ラベル"
msgid "Default description template for issues"
-msgstr ""
+msgstr "課題ã®ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®èª¬æ˜Žãƒ†ãƒ³ãƒ—レート"
msgid "Default first day of the week"
msgstr ""
@@ -3414,22 +3937,25 @@ msgid "Default first day of the week in calendars and date pickers."
msgstr "カレンダーã¨æ—¥ä»˜ã®è¨­å®šã§ä½¿ç”¨ã™ã‚‹ã€é€±ã®æœ€åˆã®æ—¥(デフォルト)"
msgid "Default issue template"
+msgstr "デフォルトã®èª²é¡Œãƒ†ãƒ³ãƒ—レート"
+
+msgid "Default project deletion protection"
msgstr ""
msgid "Default: Directly import the Google Code email address or username"
msgstr "デフォルト:Google コードã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¾ãŸã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼åを直接インãƒãƒ¼ãƒˆã™ã‚‹"
msgid "Default: Map a FogBugz account ID to a full name"
-msgstr ""
+msgstr "デフォルト:FogBugz ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆIDをフルãƒãƒ¼ãƒ ã«ãƒžãƒƒãƒ—ã™ã‚‹"
msgid "Define a custom pattern with cron syntax"
msgstr "Cron 構文ã§ã‚«ã‚¹ã‚¿ãƒ ãªãƒ‘ターンを指定ã™ã‚‹"
msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
-msgstr ""
+msgstr "デプロイステージã®ç’°å¢ƒã‚’ <code>.gitlab-ci.yml</code> ã§å®šç¾©ã—ã¦ã€ãƒ‡ãƒ—ロイを追跡ã—ã¾ã™ã€‚"
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
-msgstr ""
+msgstr "%{jobName} ã‚’ã™ãã«å®Ÿè¡Œã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿä»Šã™ã実行ã—ãªã„å ´åˆã§ã‚‚ã€ã“ã®ã‚¸ãƒ§ãƒ–ã¯äºˆç´„ã•ã‚ŒãŸã‚¿ã‚¤ãƒŸãƒ³ã‚°ã§è‡ªå‹•çš„ã«å®Ÿè¡Œã•ã‚Œã¾ã™ã€‚"
msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
msgstr "%{job_name} ã‚’ã™ãã«å®Ÿè¡Œã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿã“ã®ã‚¸ãƒ§ãƒ–ã¯ã‚¿ã‚¤ãƒžãƒ¼çµ‚了後自動的ã«å®Ÿè¡Œã•ã‚Œã¾ã™ã€‚"
@@ -3438,10 +3964,10 @@ msgid "DelayedJobs|Start now"
msgstr "今ã™ã始ã‚ã‚‹"
msgid "DelayedJobs|Unschedule"
-msgstr ""
+msgstr "スケジュールを解除"
msgid "DelayedJobs|delayed"
-msgstr ""
+msgstr "予約済ã¿"
msgid "Delete"
msgstr "削除"
@@ -3456,7 +3982,7 @@ msgid "Delete comment"
msgstr "コメントを削除"
msgid "Delete license"
-msgstr ""
+msgstr "ライセンスを削除"
msgid "Delete list"
msgstr "リストを削除ã™ã‚‹"
@@ -3467,6 +3993,21 @@ msgstr "ソースブランãƒã‚’削除"
msgid "Delete this attachment"
msgstr "ã“ã®æ·»ä»˜ãƒ•ã‚¡ã‚¤ãƒ«ã‚’削除"
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr "プロジェクトã®ãƒªãƒã‚¸ãƒˆãƒªã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã™ã‹ã€ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr "プロジェクトã®ã‚³ãƒ³ãƒ†ãƒŠãƒªãƒã‚¸ãƒˆãƒªã®ã‚¿ã‚°ã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã™ã‹ã€ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr "プロジェクトã®wikiリãƒã‚¸ãƒˆãƒªã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã™ã‹ã€ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr "プロジェクトã®ãƒªãƒã‚¸ãƒˆãƒªã®ãƒ¬ã‚¹ãƒˆã‚¢ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã™ã‹ã€ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr "wikiリãƒã‚¸ãƒˆãƒªã®ãƒ¬ã‚¹ãƒˆã‚¢ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã™ã‹ã€ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
+
msgid "Deleted"
msgstr "削除完了"
@@ -3474,13 +4015,13 @@ msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
msgid "Deleting the license failed."
-msgstr ""
+msgstr "ライセンスã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
msgid "Deleting the license failed. The license was not found."
msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
-msgstr ""
+msgstr "ライセンスã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚ãªãŸã¯ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®å‰Šé™¤ã‚’許å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。"
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
@@ -3488,6 +4029,54 @@ msgstr ""
msgid "Deny"
msgstr "æ‹’å¦"
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "デプロイ"
@@ -3496,7 +4085,7 @@ msgid "Deploy Keys"
msgstr "デプロイキー"
msgid "Deploy key was successfully updated."
-msgstr ""
+msgstr "デプロイキーã¯æ­£å¸¸ã«æ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚"
msgid "DeployKeys|+%{count} others"
msgstr "+ %{count} プロジェクト"
@@ -3658,9 +4247,12 @@ msgid "DesignManagement|Go back to designs"
msgstr ""
msgid "DesignManagement|Go to next design"
-msgstr ""
+msgstr "次ã®ãƒ‡ã‚¶ã‚¤ãƒ³ã¸"
msgid "DesignManagement|Go to previous design"
+msgstr "å‰ã®ãƒ‡ã‚¶ã‚¤ãƒ³ã¸"
+
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
msgid "DesignManagement|The one place for your designs"
@@ -3670,7 +4262,7 @@ msgid "DesignManagement|Upload and view the latest designs for this issue. Consi
msgstr ""
msgid "DesignManagement|Upload designs"
-msgstr ""
+msgstr "デザインをアップロード"
msgid "Designs"
msgstr "デザイン"
@@ -3717,9 +4309,15 @@ msgstr "グループ Runner を無効ã«ã™ã‚‹"
msgid "Disable shared Runners"
msgstr "共有 Runner を無効化"
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr "無効"
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr "破棄"
@@ -3741,17 +4339,23 @@ msgstr "下書ãを破棄"
msgid "Discard review"
msgstr "レビューを破棄"
-msgid "Discover GitLab Geo"
+msgid "DiscordService|Discord Notifications"
+msgstr "Discord 通知"
+
+msgid "DiscordService|Receive event notifications in Discord"
msgstr ""
+msgid "Discover GitLab Geo"
+msgstr "GitLab Geo ã«ã¤ã„ã¦"
+
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr "プロジェクトã€ã‚°ãƒ«ãƒ¼ãƒ—ã€ã‚¹ãƒ‹ãƒšãƒƒãƒˆã‚’発見ã™ã‚‹ã€‚ã‚ãªãŸã®ãƒ—ロジェクトを他ã®äººã¨å…±æœ‰ã™ã‚‹"
msgid "Discuss a specific suggestion or question"
-msgstr ""
+msgstr "具体的ãªæ案や質å•ã«ã¤ã„ã¦è­°è«–ã—ã¾ã™ã€‚"
msgid "Discuss a specific suggestion or question that needs to be resolved"
-msgstr ""
+msgstr "解決ãŒå¿…è¦ãªã€å…·ä½“çš„ãªæ案や質å•ã«ã¤ã„ã¦è­°è«–ã™ã‚‹ã€‚"
msgid "Discussion"
msgstr "検討"
@@ -3771,18 +4375,42 @@ msgstr "マージリクエストã®æ˜‡æ ¼ã‚’å´ä¸‹ã—ã¾ã™"
msgid "Dismiss trial promotion"
msgstr "トライアルプロモーションを閉ã˜ã‚‹"
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr "Google コードã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¨ãƒ¦ãƒ¼ã‚¶ãƒ¼åã‚’ GitLab ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹æ–¹æ³•ã‚’カスタマイズã—ã¾ã™ã‹ï¼Ÿ"
+msgid "Dockerfile"
+msgstr "Dockerfile"
+
msgid "Documentation for popular identity providers"
msgstr "一般的㪠ID プロãƒã‚¤ãƒ€ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆ"
msgid "Domain"
msgstr "ドメイン"
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr "次回ã‹ã‚‰è¡¨ç¤ºã—ãªã„"
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr "完了"
@@ -3795,26 +4423,20 @@ msgstr "æˆæžœç‰©ã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰"
msgid "Download asset"
msgstr "アセットをダウンロード"
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
-msgstr ""
+msgid "Download export"
+msgstr "エクスãƒãƒ¼ãƒˆã‚’ダウンロード"
-msgid "Download tar.gz"
-msgstr ""
+msgid "Download license"
+msgstr "ライセンスをダウンロード"
-msgid "Download zip"
-msgstr ""
+msgid "Download source code"
+msgstr "ソースコードをダウンロード"
-msgid "DownloadArtifacts|Download"
-msgstr ""
+msgid "Download this directory"
+msgstr "ã“ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’ダウンロード"
msgid "DownloadCommit|Email Patches"
msgstr "パッãƒã‚’メールã§é€ä¿¡"
@@ -3855,6 +4477,9 @@ msgstr "ラベルã®ç·¨é›†"
msgid "Edit Milestone"
msgstr "マイルストーンを編集"
+msgid "Edit Password"
+msgstr "パスワードを編集"
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "パイプラインスケジュール %{id} を編集"
@@ -3891,11 +4516,17 @@ msgstr "公開デプロイキーã®ç·¨é›†"
msgid "Elasticsearch"
msgstr "Elasticsearch"
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr "Elasticsearch ã®çµ±åˆã€‚Elasticsearch AWS IAM。"
msgid "Elastic|None. Select namespaces to index."
-msgstr ""
+msgstr "ãªã—。インデックスã«åå‰ç©ºé–“ã‚’é¸æŠžã—ã¦ãã ã•ã„"
msgid "Elastic|None. Select projects to index."
msgstr ""
@@ -3904,38 +4535,71 @@ msgid "Email"
msgstr "メール"
msgid "Email address"
-msgstr ""
+msgstr "メールアドレス"
msgid "Email patch"
msgstr "パッãƒã‚’メールã™ã‚‹"
+msgid "Email the pipelines status to a list of recipients."
+msgstr "パイプラインã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚’å—信者ã®ãƒªã‚¹ãƒˆã«Eメールã§é€šçŸ¥ã—ã¾ã™ã€‚"
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
-msgstr ""
+msgstr "メールãŒç©ºã®ã‚ˆã†ã§ã™ã€‚返信文ãŒãƒ¡ãƒ¼ãƒ«ã®ä¸€ç•ªä¸Šã«ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。インラインã®è¿”ä¿¡ã¯å‡¦ç†ã§ãã¾ã›ã‚“。"
msgid "EmailError|The thread you are replying to no longer exists, perhaps it was deleted? If you believe this is in error, contact a staff member."
-msgstr ""
+msgstr "返信ã•ã‚ŒãŸã‚¹ãƒ¬ãƒƒãƒ‰ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã›ã‚“。ãŠãらããã‚Œã¯å‰Šé™¤ã•ã‚ŒãŸã‚‚ã®ã¨æ€ã‚ã‚Œã¾ã™ã€‚ã“ã‚ŒãŒèª¤ã£ã¦ã„ã‚‹ã¨æ€ã‚れる場åˆã¯ã€ã‚¹ã‚¿ãƒƒãƒ•ãƒ¡ãƒ³ãƒãƒ¼ã«å•ã„åˆã‚ã›ã¦ãã ã•ã„。"
msgid "EmailError|We couldn't figure out what the email is for. Please create your issue or comment through the web interface."
msgstr ""
msgid "EmailError|We couldn't figure out what the email is in reply to. Please create your comment through the web interface."
-msgstr ""
+msgstr "メールãŒã©ã“ã¸ã®è¿”ä¿¡ã‹åˆ¤ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚ Webインターフェイス上ã‹ã‚‰ã‚³ãƒ¡ãƒ³ãƒˆã‚’作æˆã—ã¦ãã ã•ã„。"
msgid "EmailError|We couldn't figure out what user corresponds to the email. Please create your comment through the web interface."
msgstr ""
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
-msgstr ""
+msgstr "プロジェクトãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚入力ミスãŒãªã„ã‹ç¢ºèªã—ã¦ãã ã•ã„。"
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
-msgstr ""
+msgstr "ã“ã®æ“作ã®å®Ÿè¡Œã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。ã“ã‚ŒãŒèª¤ã£ã¦ã„ã‚‹ã¨æ€ã‚れる場åˆã¯ã€ã‚¹ã‚¿ãƒƒãƒ•ãƒ¡ãƒ³ãƒãƒ¼ã«å•ã„åˆã‚ã›ã¦ãã ã•ã„。"
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
-msgstr ""
+msgstr "ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ãƒ–ロックã•ã‚Œã¾ã—ãŸã€‚ã“ã‚ŒãŒèª¤ã£ã¦ã„ã‚‹ã¨æ€ã‚れる場åˆã¯ã€ã‚¹ã‚¿ãƒƒãƒ•ãƒ¡ãƒ³ãƒãƒ¼ã«å•ã„åˆã‚ã›ã¦ãã ã•ã„。"
+
+msgid "EmailToken|reset it"
+msgstr "リセットã™ã‚‹"
+
+msgid "EmailToken|resetting..."
+msgstr "リセット中..."
msgid "Emails"
msgstr "メール"
+msgid "Emails separated by comma"
+msgstr "Eメール (コンマ区切り)"
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr "埋ã‚è¾¼ã¿"
@@ -3960,6 +4624,9 @@ msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã® SAML èªè¨¼ã‚’有効ã«ã™ã‚‹"
msgid "Enable Sentry for error reporting and logging."
msgstr "エラー報告ã¨ãƒ­ã‚°è¨˜éŒ²ã®ãŸã‚ã« Sentry を有効ã«ã™ã‚‹ã€‚"
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr "InfluxDB ã®ãƒ¡ãƒˆãƒªã‚¯ã‚¹ã‚’有効ã«ã—ã¦è¨­å®šã™ã‚‹ã€‚"
@@ -3996,9 +4663,6 @@ msgstr "reCAPTCHA ã¾ãŸã¯ Akismet ã®æœ‰åŠ¹ã€ãŠã‚ˆã³ IP 制é™ã‚’設定ã™ã
msgid "Enable shared Runners"
msgstr "共有 Runner を有効化"
-msgid "Enable the Performance Bar for a given group."
-msgstr "指定グループã®ãƒ‘フォーマンスãƒãƒ¼ã‚’有効ã«ã™ã‚‹ã€‚"
-
msgid "Enable two-factor authentication"
msgstr "2è¦ç´ èªè¨¼ã‚’有効ã«ã™ã‚‹"
@@ -4029,12 +4693,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr "終了時刻 (UTC)"
-msgid "Enter at least three characters to search"
+msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enter at least three characters to search"
+msgstr "å°‘ãªãã¨ã‚‚3文字以上ã§æ¤œç´¢ã—ã¦ãã ã•ã„"
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr "ã‚ãªãŸã® Bitbucket Server ã® URL ã¨ä»¥ä¸‹ã®å€‹äººã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ã‚’入力ã—ã¦ãã ã•ã„"
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr "課題ã®èª¬æ˜Žã‚’入力ã—ã¦ãã ã•ã„"
@@ -4047,7 +4717,10 @@ msgstr "マージリクエストã®èª¬æ˜Žã‚’入力ã—ã¦ãã ã•ã„"
msgid "Enter the merge request title"
msgstr "マージリクエストã®ã‚¿ã‚¤ãƒˆãƒ«ã‚’入力ã—ã¦ãã ã•ã„"
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4059,9 +4732,33 @@ msgstr "環境:"
msgid "Environments"
msgstr "環境"
+msgid "Environments Dashboard"
+msgstr "環境ダッシュボード"
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr "環境ã¯ã‚¢ãƒ—リケーションã®ãƒ‡ãƒ—ロイを追加ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ %{link_to_read_more}"
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr "ダッシュボードã«ãƒ—ロジェクトを追加"
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr "プロジェクトを追加"
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr "環境ダッシュボード"
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr "ジョブ: %{job}"
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "環境をå–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -4069,7 +4766,7 @@ msgid "Environments|An error occurred while making the request."
msgstr "リクエスト作æˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Environments|An error occurred while re-deploying the environment, please try again"
-msgstr ""
+msgstr "環境ã®å†ãƒ‡ãƒ—ロイ中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„"
msgid "Environments|An error occurred while rolling back the environment, please try again"
msgstr "環境ã®ãƒ­ãƒ¼ãƒ«ãƒãƒƒã‚¯ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„"
@@ -4096,7 +4793,7 @@ msgid "Environments|Environments"
msgstr "環境一覧"
msgid "Environments|Environments are places where code gets deployed, such as staging or production."
-msgstr ""
+msgstr "環境ã¨ã¯ã€staging ã‚„ production ã¨ã„ã£ãŸã‚³ãƒ¼ãƒ‰ã‚’デプロイã™ã‚‹å…ˆã§ã™ã€‚"
msgid "Environments|Job"
msgstr "ジョブ"
@@ -4114,10 +4811,10 @@ msgid "Environments|No pod name has been specified"
msgstr "pod åãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã›ã‚“"
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
-msgstr ""
+msgstr "ã“ã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯ç’°å¢ƒã‚’åœæ­¢ã™ã‚‹ã“ã¨ã«æ³¨æ„ã—ã¦ãã ã•ã„。ã—ã‹ã—ã€%{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} ファイルã§å®šç¾©ã•ã‚Œã¦ã„ã‚‹ã€ç’°å¢ƒåœæ­¢ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ä»¥å¤–ã«ã‚ˆã‚‹ã€ã‚らゆる既存ã®ãƒ‡ãƒ—ロイメントã«å½±éŸ¿ã‚’ %{emphasisStart}与ãˆã¾ã›ã‚“%{emphasisEnd}。"
msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
-msgstr ""
+msgstr "ã“ã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯ã€ç’°å¢ƒã‚’åœæ­¢ã™ã‚‹ã“ã¨ã«æ³¨æ„ã—ã¦ãã ã•ã„。ã—ã‹ã—ã€%{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} ファイルã§å®šç¾©ã•ã‚Œã¦ã„ã‚‹ã€ç’°å¢ƒåœæ­¢ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ä»¥å¤–ã«ã‚ˆã‚‹ã€ã‚らゆる既存ã®ãƒ‡ãƒ—ロイメントã«å½±éŸ¿ã‚’ %{emphasis_start} 与ãˆã¾ã›ã‚“%{emphasis_end} 。"
msgid "Environments|Open live environment"
msgstr "ライブ環境を開ã"
@@ -4197,18 +4894,51 @@ msgstr "エピック ロードマップ"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr "エピックを使用ã™ã‚‹ã¨ã€ãƒ—ロジェクトã®ãƒãƒ¼ãƒˆãƒ•ã‚©ãƒªã‚ªã‚’より効率的ã‹ã¤å°‘ãªã„労力ã§ç®¡ç†ã§ãã¾ã™"
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr "%{epicDateType} ã®ä¿å­˜ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr "ã©ã†ã™ã‚Œã°è§£æ±ºã§ãã¾ã™ã‹ï¼Ÿ"
msgid "Epics|More information"
msgstr "詳ã—ã„情報"
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr "マイルストーンã«åŸºã¥ã„ãŸã‚¨ãƒ”ック㮠%{epicDateType} をスケジューリングã™ã‚‹ã«ã¯ã€ã‚¨ãƒ”ックã®èª²é¡Œã« %{epicDateType} ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã‚’割り当ã¦ã¾ã™ã€‚"
@@ -4228,7 +4958,7 @@ msgid "Error Tracking"
msgstr "エラートラッキング"
msgid "Error creating a new path"
-msgstr ""
+msgstr "æ–°ã—ã„パスã®ä½œæˆã‚¨ãƒ©ãƒ¼"
msgid "Error creating epic"
msgstr "エピックã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼"
@@ -4245,9 +4975,15 @@ msgstr "ラベルã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Error fetching network graph."
msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚°ãƒ©ãƒ•ã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr "å‚ç…§ã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿ"
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr "Ping データå–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -4255,8 +4991,14 @@ msgid "Error loading branch data. Please try again."
msgstr "ブランムデータã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "Error loading branches."
+msgstr "ブランãƒã®ãƒ­ãƒ¼ãƒ‰ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
+
+msgid "Error loading burndown chart data"
msgstr ""
+msgid "Error loading file viewer."
+msgstr "ファイルビューワーã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
+
msgid "Error loading last commit."
msgstr "ç›´è¿‘ã®ã‚³ãƒŸãƒƒãƒˆã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -4266,14 +5008,23 @@ msgstr ""
msgid "Error loading merge requests."
msgstr "マージリクエストをロード中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr "プロジェクトデータã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "Error loading template types."
-msgstr ""
+msgstr "テンプレートタイプã®èª­ã¿è¾¼ã¿ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Error loading template."
-msgstr ""
+msgstr "テンプレートã®èª­ã¿è¾¼ã¿ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+
+msgid "Error loading viewer"
+msgstr "ビューワーã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸ"
+
+msgid "Error occurred when fetching sidebar data"
+msgstr "サイドãƒãƒ¼ãƒ‡ãƒ¼ã‚¿ã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Error occurred when toggling the notification subscription"
msgstr "通知購読ã®åˆ‡ã‚Šæ›¿ãˆã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -4291,7 +5042,7 @@ msgid "Error occurred. User was not unlocked"
msgstr ""
msgid "Error rendering markdown preview"
-msgstr ""
+msgstr "Markdownプレビューã®ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ã‚¨ãƒ©ãƒ¼"
msgid "Error saving label update."
msgstr "ラベルã®æ›´æ–°ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -4308,9 +5059,15 @@ msgstr "TODO ã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚’更新中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr "マージリクエストã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4327,25 +5084,25 @@ msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to l
msgstr ""
msgid "ErrorTracking|Auth Token"
-msgstr ""
+msgstr "èªè¨¼ãƒˆãƒ¼ã‚¯ãƒ³"
msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
msgstr ""
msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
-msgstr ""
+msgstr "接続ã«å¤±æ•—ã—ã¾ã—ãŸã€‚èªè¨¼ãƒˆãƒ¼ã‚¯ãƒ³ã‚’å†ç¢ºèªã—ã¦ã€ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "ErrorTracking|Find your hostname in your Sentry account settings page"
msgstr ""
msgid "ErrorTracking|No projects available"
-msgstr ""
+msgstr "利用ã§ãるプロジェクトã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "ErrorTracking|Select project"
-msgstr ""
+msgstr "プロジェクトã®é¸æŠž"
msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
-msgstr ""
+msgstr "プロジェクトã®é¸æŠžã‚’有効ã«ã™ã‚‹ã«ã¯ã€æœ‰åŠ¹ãªèªè¨¼ãƒˆãƒ¼ã‚¯ãƒ³ã‚’入力ã—ã¦ãã ã•ã„"
msgid "Errors"
msgstr "エラー"
@@ -4390,21 +5147,24 @@ msgid "Everyone"
msgstr "全員"
msgid "Everyone can contribute"
-msgstr ""
+msgstr "全員ãŒè²¢çŒ®ã§ãã¾ã™"
msgid "Everything you need to create a GitLab Pages site using GitBook."
-msgstr ""
+msgstr "GitBook を使ã£ã¦ GitLab Pages サイトを作æˆã™ã‚‹ãŸã‚ã«å¿…è¦ãªã“ã¨ã™ã¹ã¦ã€‚"
msgid "Everything you need to create a GitLab Pages site using Hexo."
-msgstr ""
+msgstr "Hexo を使ã£ã¦GitLab Pagesサイトを作æˆã™ã‚‹ãŸã‚ã«å¿…è¦ãªã‚‚ã®ã™ã¹ã¦ã€‚"
msgid "Everything you need to create a GitLab Pages site using Hugo."
-msgstr ""
+msgstr "Hugo を使ã£ã¦ GitLab Pages サイトを作æˆã™ã‚‹ãŸã‚ã«å¿…è¦ãªã‚‚ã®ã™ã¹ã¦ã€‚"
msgid "Everything you need to create a GitLab Pages site using Jekyll."
-msgstr ""
+msgstr "Jekyll を使ã£ã¦ GitLab Pages サイトを作æˆã™ã‚‹ãŸã‚ã«å¿…è¦ãªã‚‚ã®ã™ã¹ã¦ã€‚"
msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr "プレーンHTML を使ã£ã¦ GitLab Pages サイトを作æˆã™ã‚‹ãŸã‚ã«å¿…è¦ãªã‚‚ã®ã™ã¹ã¦ã€‚"
+
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
msgid "Except policy:"
@@ -4465,7 +5225,7 @@ msgid "Export issues"
msgstr "課題をエクスãƒãƒ¼ãƒˆ"
msgid "Export project"
-msgstr ""
+msgstr "プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ"
msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
msgstr ""
@@ -4494,6 +5254,27 @@ msgstr "分類ラベル"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "ラベルãŒåˆ†é¡žã•ã‚Œã¦ã„ãªã„ã¨ãã¯ã€`%{default_label}` ãŒæ—¢å®šã®ãƒ©ãƒ™ãƒ«ã¨ã—ã¦ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚"
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr "Facebook"
@@ -4503,25 +5284,58 @@ msgstr "失敗"
msgid "Failed Jobs"
msgstr "失敗ã—ãŸã‚¸ãƒ§ãƒ–"
+msgid "Failed create wiki"
+msgstr "wiki を作æˆã§ãã¾ã›ã‚“ã§ã—ãŸ"
+
msgid "Failed to change the owner"
msgstr "オーナーを変更ã§ãã¾ã›ã‚“ã§ã—ãŸ"
msgid "Failed to check related branches."
msgstr "関連ã™ã‚‹ãƒ–ランãƒã®ç¢ºèªã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
-msgid "Failed to create resources"
+msgid "Failed to connect to the prometheus server"
msgstr ""
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr "gitlab-shell 経由ã§ã®ãƒªãƒã‚¸ãƒˆãƒªä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸ"
+
+msgid "Failed to create resources"
+msgstr "リソースã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸ"
+
msgid "Failed to deploy to"
msgstr ""
-msgid "Failed to load emoji list."
+msgid "Failed to get ref."
msgstr ""
+msgid "Failed to install."
+msgstr "インストールã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
+
+msgid "Failed to load emoji list."
+msgstr "絵文字リストã®ãƒ­ãƒ¼ãƒ‰ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
+
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
+msgstr "内部エラーã®ãŸã‚ã€ãƒ©ãƒ™ãƒ«ã‚’昇格ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚管ç†è€…ã«å•ã„åˆã‚ã›ã¦ãã ã•ã„。"
+
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
msgstr ""
msgid "Failed to remove issue from board, please try again."
@@ -4534,38 +5348,56 @@ msgid "Failed to remove the pipeline schedule"
msgstr "パイプラインスケジュールを削除ã§ãã¾ã›ã‚“ã§ã—ãŸ"
msgid "Failed to remove user identity."
-msgstr ""
+msgstr "ユーザー識別å­ã‚’削除ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "Failed to remove user key."
-msgstr ""
+msgstr "ユーザーキーを削除ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "Failed to reset key. Please try again."
+msgstr "キーをリセットã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ãŠè©¦ã—下ã•ã„。"
+
+msgid "Failed to save comment!"
msgstr ""
-msgid "Failed to save new settings"
+msgid "Failed to save merge conflicts resolutions. Please try again!"
msgstr ""
+msgid "Failed to save new settings"
+msgstr "æ–°ã—ã„設定をä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ"
+
msgid "Failed to save preferences (%{error_message})."
-msgstr ""
+msgstr "設定をä¿å­˜ã§ãã¾ã›ã‚“ã§ã—㟠(%{error_message})。"
msgid "Failed to save preferences."
-msgstr ""
+msgstr "設定をä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "Failed to signing using smartcard authentication"
msgstr "スマートカードèªè¨¼ã‚’使用ã—ã¦ã®ç½²åã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
+msgid "Failed to update branch!"
+msgstr "ブランãƒã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸ"
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr "課題ã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+msgid "Failed to update tag!"
+msgstr "ã‚¿ã‚°ã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸ"
+
+msgid "Failed to update."
+msgstr ""
+
+msgid "Failed to upgrade."
+msgstr ""
+
msgid "Failed to upload object map file"
msgstr "オブジェクトマップファイルをアップロードã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "Failure"
msgstr "失敗"
-msgid "Fast-forward merge"
-msgstr ""
-
msgid "Fast-forward merge without a merge commit"
msgstr ""
@@ -4573,17 +5405,23 @@ msgid "Faster as it re-uses the project workspace (falling back to clone if it d
msgstr ""
msgid "Favicon was successfully removed."
-msgstr ""
+msgstr "Faviconã¯æ­£å¸¸ã«å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚"
msgid "Feature Flags"
msgstr "機能フラグ"
-msgid "FeatureFlags|* (All Environments)"
+msgid "Feature flag was not removed."
msgstr ""
-msgid "FeatureFlags|* (All environments)"
+msgid "Feature flag was successfully removed."
msgstr ""
+msgid "FeatureFlags|* (All Environments)"
+msgstr "* (ã™ã¹ã¦ã®ç’°å¢ƒ)"
+
+msgid "FeatureFlags|* (All environments)"
+msgstr "* (ã™ã¹ã¦ã®ç’°å¢ƒ)"
+
msgid "FeatureFlags|API URL"
msgstr "API URL"
@@ -4594,7 +5432,7 @@ msgid "FeatureFlags|Configure"
msgstr ""
msgid "FeatureFlags|Configure feature flags"
-msgstr ""
+msgstr "機能フラグを設定"
msgid "FeatureFlags|Create feature flag"
msgstr "機能フラグを作æˆ"
@@ -4603,7 +5441,7 @@ msgid "FeatureFlags|Delete %{name}?"
msgstr "%{name} を削除ã—ã¾ã™ã‹ï¼Ÿ"
msgid "FeatureFlags|Delete feature flag"
-msgstr ""
+msgstr "機能フラグを削除"
msgid "FeatureFlags|Description"
msgstr "説明"
@@ -4641,7 +5479,7 @@ msgstr "無効"
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4653,9 +5491,6 @@ msgstr "機能フラグを読ã¿è¾¼ã‚“ã§ã„ã¾ã™"
msgid "FeatureFlags|More Information"
msgstr "詳細情報"
-msgid "FeatureFlags|More information"
-msgstr "詳細情報"
-
msgid "FeatureFlags|Name"
msgstr "åå‰"
@@ -4672,7 +5507,7 @@ msgid "FeatureFlags|Status"
msgstr "ステータス"
msgid "FeatureFlags|Target environments"
-msgstr ""
+msgstr "ターゲット環境"
msgid "FeatureFlags|There are no active Feature Flags"
msgstr "有効ãªæ©Ÿèƒ½ãƒ•ãƒ©ã‚°ã¯ã‚ã‚Šã¾ã›ã‚“"
@@ -4735,6 +5570,12 @@ msgstr "ファイルアップロードエラー"
msgid "Files"
msgstr "ファイル"
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr "下記項目ã«å¿…è¦äº‹é …を入力ã—〠<strong>%{enable_label}</strong>をオンã«ã—ã¦ã€ <strong>%{save_changes}</strong>を押ã—ã¦ãã ã•ã„。"
@@ -4742,28 +5583,28 @@ msgid "Filter"
msgstr "フィルター"
msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
+msgstr "ã‚ãªãŸãŒæœ€è¿‘é–‰ã˜ãŸ %{issuable_type} ã§ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼"
msgid "Filter by %{issuable_type} that are currently opened."
-msgstr ""
+msgstr "ã‚ãªãŸãŒæœ€è¿‘é–‹ã„㟠%{issuable_type} ã§ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼"
msgid "Filter by commit message"
msgstr "コミットメッセージã§çµžã‚Šè¾¼ã¿"
msgid "Filter by milestone name"
-msgstr ""
+msgstr "マイルストーンåã§çµžã‚Šè¾¼ã‚€"
msgid "Filter by two-factor authentication"
-msgstr ""
+msgstr "2è¦ç´ èªè¨¼ã§çµžã‚Šè¾¼ã¿"
msgid "Filter results by group"
-msgstr ""
+msgstr "グループã§çµžã‚Šè¾¼ã¿"
msgid "Filter results by project"
-msgstr ""
+msgstr "プロジェクトã§çµžã‚Šè¾¼ã¿"
msgid "Filter..."
-msgstr ""
+msgstr "フィルター..."
msgid "Find by path"
msgstr "パスã§æ¤œç´¢"
@@ -4783,6 +5624,9 @@ msgstr ""
msgid "Fingerprint"
msgstr "フィンガープリント"
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr "フィンガープリント"
@@ -4792,6 +5636,9 @@ msgstr ""
msgid "Finish review"
msgstr "レビューを完了ã™ã‚‹"
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr "完了"
@@ -4816,6 +5663,12 @@ msgstr ""
msgid "Fixed:"
msgstr "修正:"
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr "FogBugz メール"
@@ -4853,7 +5706,7 @@ msgid "For more information, please review %{link_start_tag}Jaeger's configurati
msgstr ""
msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
-msgstr ""
+msgstr "詳細ã«ã¤ã„ã¦ã¯ %{deactivating_usage_ping_link_start}ping ã®ä½¿ç”¨ã®ç„¡åŠ¹åŒ–%{deactivating_usage_ping_link_end} ã«ã¤ã„ã¦ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’å‚ç…§ã—ã¦ãã ã•ã„"
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -4861,6 +5714,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr "フォーク"
+
+msgid "Fork Error!"
+msgstr "フォークエラー"
+
+msgid "Fork project"
+msgstr "プロジェクトをフォーク"
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "フォーク元"
@@ -4870,6 +5732,9 @@ msgstr "%{project_name} ã‹ã‚‰ãƒ•ã‚©ãƒ¼ã‚¯ (削除済)"
msgid "Forking in progress"
msgstr "フォーク中ã§ã™"
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr "フォーク"
@@ -4888,6 +5753,9 @@ msgstr ".gitlab-ci.yml ã«ã‚¨ãƒ©ãƒ¼ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ:"
msgid "Free Trial of GitLab.com Gold"
msgstr "GitLab.com Gold プランã®ç„¡å„Ÿè©¦ç”¨"
+msgid "Friday"
+msgstr "金曜日"
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4918,15 +5786,21 @@ msgstr "マイルストーンã‹ã‚‰:"
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr "Kubernetes クラスターã®è©³ç´°ç”»é¢ã‚’介ã—ã¦ã€ã‚¢ãƒ—リケーションリストã‹ã‚‰ Runner をインストールã—ã¾ã™ã€‚"
-msgid "GPG Key ID:"
+msgid "Full name"
msgstr ""
+msgid "GPG Key ID:"
+msgstr "GPG キー ID:"
+
msgid "GPG Keys"
msgstr "GPG キー"
-msgid "GPG signature (loading...)"
+msgid "GPG keys allow you to verify signed commits."
msgstr ""
+msgid "GPG signature (loading...)"
+msgstr "GPG ã‚·ã‚°ãƒãƒãƒ£ (読ã¿è¾¼ã¿ä¸­...)"
+
msgid "General"
msgstr "一般"
@@ -4955,7 +5829,7 @@ msgid "Geo allows you to replicate your GitLab instance to other geographical lo
msgstr "Geo ã¯ã€GitLab インスタンスを他ã®åœ°ç†çš„ãªå ´æ‰€ã«è¤‡è£½ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
msgid "GeoNodeSyncStatus|Node is failing or broken."
-msgstr ""
+msgstr "ノードãŒæ•…éšœã—ã¦ã„ã‚‹ã‹å£Šã‚Œã¦ã„ã¾ã™ã€‚"
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr "ノードãŒé…延ã€éŽè² è·ãŒã‹ã‹ã£ã¦ã„ã‚‹ã€ã¾ãŸã¯åœæ­¢ã‹ã‚‰ã®å›žå¾©ç›´å¾Œã§ã™ã€‚"
@@ -4985,10 +5859,10 @@ msgid "GeoNodes|GitLab version does not match the primary node version"
msgstr "GitLab ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒå„ªå…ˆãƒŽãƒ¼ãƒ‰ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¨ä¸€è‡´ã—ã¾ã›ã‚“"
msgid "GeoNodes|Health status"
-msgstr ""
+msgstr "稼動状æ³"
msgid "GeoNodes|Internal URL"
-msgstr ""
+msgstr "内部 URL"
msgid "GeoNodes|Last event ID processed by cursor"
msgstr "カーソルã§å‡¦ç†ã•ã‚ŒãŸæœ€çµ‚イベント ID"
@@ -5036,7 +5910,7 @@ msgid "GeoNodes|Out of sync"
msgstr "åŒæœŸå¯¾è±¡å¤–"
msgid "GeoNodes|Pausing replication stops the sync process."
-msgstr ""
+msgstr "レプリケーションを一時åœæ­¢ã™ã‚‹ã¨ã€åŒæœŸãƒ—ロセスãŒåœæ­¢ã—ã¾ã™ã€‚"
msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
msgstr ""
@@ -5180,7 +6054,7 @@ msgid "Geo|In sync"
msgstr "åŒæœŸ"
msgid "Geo|Internal URL"
-msgstr ""
+msgstr "内部 URL"
msgid "Geo|Last repository check run"
msgstr ""
@@ -5216,7 +6090,7 @@ msgid "Geo|Please refer to Geo Troubleshooting."
msgstr ""
msgid "Geo|Project"
-msgstr ""
+msgstr "プロジェクト"
msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
msgstr ""
@@ -5267,7 +6141,7 @@ msgid "Geo|Status"
msgstr "状態"
msgid "Geo|Sync"
-msgstr ""
+msgstr "åŒæœŸ"
msgid "Geo|Synced"
msgstr "åŒæœŸæ¸ˆã¿"
@@ -5281,6 +6155,12 @@ msgstr "åŒæœŸã«å¤±æ•—ã—ã¾ã—㟠- %{error}"
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr "ã“ã‚Œã¯ãƒ—ライマリノードã§ã™"
@@ -5330,12 +6210,15 @@ msgid "Get started with error tracking"
msgstr "エラー追跡を開始"
msgid "Getting started with releases"
-msgstr ""
+msgstr "リリースã®é–‹å§‹"
msgid "Git"
msgstr "Git"
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
+msgstr "ã“ã®GitLabサーãƒãƒ¼ã¯Git LFSãŒç„¡åŠ¹ã«ãªã£ã¦ã„ã¾ã™ã€‚管ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
+
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
msgstr ""
msgid "Git global setup"
@@ -5347,6 +6230,9 @@ msgstr "Git リãƒã‚¸ãƒˆãƒª URL"
msgid "Git revision"
msgstr "Git リビジョン"
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5419,6 +6305,9 @@ msgstr "Gitea インãƒãƒ¼ãƒˆ"
msgid "Given access %{time_ago}"
msgstr "%{time_ago} ã«ã‚¢ã‚¯ã‚»ã‚¹è¨±å¯"
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr "戻る"
@@ -5437,9 +6326,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr "プロジェクトã«ç§»å‹•"
+msgid "Go to your fork"
+msgstr "自分ã®ãƒ•ã‚©ãƒ¼ã‚¯ã¸ç§»å‹•"
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr "Google コードã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
@@ -5515,6 +6413,9 @@ msgstr "グループå"
msgid "Group overview content"
msgstr "グループ概è¦ã‚³ãƒ³ãƒ†ãƒ³ãƒ„"
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5524,6 +6425,9 @@ msgstr "グループ:"
msgid "Group: %{group_name}"
msgstr "グループ:%{group_name}"
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr "%{dateWord} ã‹ã‚‰"
@@ -5551,13 +6455,16 @@ msgstr "%{dateWord} ã¾ã§"
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5569,11 +6476,8 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
-msgstr ""
+msgstr "アイデンティティプロãƒã‚¤ãƒ€ã®ã‚·ãƒ³ã‚°ãƒ«ã‚µã‚¤ãƒ³ã‚ªãƒ³ URL"
msgid "GroupSAML|Make sure you save this token — you won't be able to access it again."
msgstr ""
@@ -5585,28 +6489,37 @@ msgid "GroupSAML|Members will be forwarded here when signing in to your group. G
msgstr ""
msgid "GroupSAML|SAML Single Sign On"
-msgstr ""
+msgstr "SAML シングルサインオン"
msgid "GroupSAML|SAML Single Sign On Settings"
-msgstr ""
+msgstr "SAML シングル サインオンã®è¨­å®š"
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
msgid "GroupSAML|SCIM Token"
-msgstr ""
+msgstr "SCIMトークン"
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
-msgstr ""
+msgstr "SAML トークン㮠SHA1 フィンガープリントã§è¨¼æ˜Žæ›¸ã«ç½²åã—ã¾ã™ã€‚ã“ã‚Œã¯ã‚µãƒ ãƒ—リントã¨å‘¼ã°ã‚Œã‚¢ã‚¤ãƒ‡ãƒ³ãƒ†ã‚£ãƒ†ã‚£ãƒ—ロãƒã‚¤ãƒ€ãƒ¼ã‹ã‚‰å–å¾—ã§ãã¾ã™ã€‚"
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr "グループ管ç†ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’有効ã«ã™ã‚‹ã¨ã€ã‚°ãƒ«ãƒ¼ãƒ—管ç†ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’æŒãŸãªã„ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‹ã‚‰é™¤å¤–ã•ã‚Œã¾ã™ã€‚"
+
msgid "GroupSAML|Your SCIM token"
-msgstr ""
+msgstr "SCIMトークン"
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
@@ -5668,6 +6581,9 @@ msgstr "グループã®ãƒ­ãƒƒã‚¯ã‚’ %{ancestor_group_name} ã®å…±æœ‰ã‹ã‚‰å‰Šé™¤
msgid "Groups"
msgstr "グループ"
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr "グループã¯ã€%{subgroup_docs_link_start}サブグループ%{subgroup_docs_link_end}を作æˆã™ã‚‹ã“ã¨ã§ãƒã‚¹ãƒˆã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
@@ -5693,7 +6609,7 @@ msgid "GroupsDropdown|Sorry, no groups matched your search"
msgstr ""
msgid "GroupsDropdown|This feature requires browser localStorage support"
-msgstr ""
+msgstr "ã“ã®æ©Ÿèƒ½ã«ã¯ãƒ–ラウザー㫠localStorage サãƒãƒ¼ãƒˆãŒå¿…è¦ã§ã™"
msgid "GroupsEmptyState|A group is a collection of several projects."
msgstr "グループã¯è¤‡æ•°ã®ãƒ—ロジェクトã®é›†åˆä½“ã§ã™ã€‚"
@@ -5737,6 +6653,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr "åå‰ã§æ¤œç´¢"
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr "ユーザーã«ãƒ¡ãƒ¼ãƒ«ã‚’é€ä¿¡"
@@ -5764,6 +6683,9 @@ msgstr "正常性ã«å•é¡Œã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "HealthCheck|Unhealthy"
msgstr "異常"
+msgid "Hello there"
+msgstr "ã“ã‚“ã«ã¡ã¯"
+
msgid "Help"
msgstr "ヘルプ"
@@ -5773,12 +6695,15 @@ msgstr "ヘルプページ"
msgid "Help page text and support page url."
msgstr "ヘルプページテキストã¨ã‚µãƒãƒ¼ãƒˆãƒšãƒ¼ã‚¸URL。"
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
-msgstr "ã“ã“ã«ã¯ã€ãƒªãƒ¢ãƒ¼ãƒˆã‚µãƒ¼ãƒãƒ¼ã«è¿½åŠ ã™ã‚‹å¿…è¦ã®ã‚る公開 SSH éµãŒã‚ã‚Šã¾ã™ã€‚詳細ã¯ã€æ–‡æ›¸ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
+msgid "Hide archived projects"
+msgstr "アーカイブã—ãŸãƒ—ロジェクトをéžè¡¨ç¤ºã«"
msgid "Hide file browser"
msgstr "ファイルブラウザをéžè¡¨ç¤º"
+msgid "Hide group projects"
+msgstr "グループプロジェクトをéžè¡¨ç¤º"
+
msgid "Hide host keys manual input"
msgstr "ホストキーã®ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«å…¥åŠ›ã‚’éš ã™"
@@ -5788,6 +6713,9 @@ msgstr ""
msgid "Hide payload"
msgstr "ペイロードを隠ã™"
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "éžè¡¨ç¤º"
@@ -5801,14 +6729,20 @@ msgstr ""
msgid "History"
msgstr "履歴"
-msgid "Hook was successfully created."
+msgid "History of authentications"
msgstr ""
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
+msgid "Hook was successfully created."
+msgstr "フックã¯æ­£å¸¸ã«ä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
+
msgid "Hook was successfully updated."
msgstr ""
msgid "Housekeeping"
-msgstr ""
+msgstr "ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ング"
msgid "Housekeeping successfully started"
msgstr "ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ングã¯æ­£å¸¸ã«èµ·å‹•ã—ã¾ã—ãŸã€‚"
@@ -5816,6 +6750,12 @@ msgstr "ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ングã¯æ­£å¸¸ã«èµ·å‹•ã—ã¾ã—ãŸã€‚"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr "ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ングã€ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã€ãƒ‘スã€è»¢é€ã€å‰Šé™¤ã€ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–。"
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr "ã—ã‹ã—ã€ã‚ãªãŸã¯ã™ã§ã«ã“ã® %{member_source} ã®ãƒ¡ãƒ³ãƒãƒ¼ã§ã™ã€‚招待をå—ã‘入れるã«ã¯ã€åˆ¥ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’使用ã—ã¦ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã—ã¦ãã ã•ã„。"
@@ -5825,6 +6765,12 @@ msgstr "%{terms_link} ã«åŒæ„ã™ã‚‹"
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr "利用è¦ç´„ã¨ãƒ—ライãƒã‚·ãƒ¼ãƒãƒªã‚·ãƒ¼"
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr "ID"
@@ -5894,11 +6840,20 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr "有効ã«è¨­å®šã—ãŸå ´åˆã€å¤–部サービスã‹ã‚‰ãƒ—ロジェクトã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ãŒåˆ†é¡žãƒ©ãƒ™ãƒ«ã‚’使用ã—ã¦åˆ¶å¾¡ã•ã‚Œã¾ã™ã€‚"
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr "GitHub を使用ã—ã¦ã„ã‚‹å ´åˆã€GitHub 上ã®ã‚³ãƒŸãƒƒãƒˆã‚„プルリクエストã‹ã‚‰ãƒ‘イプラインã®çŠ¶æ…‹ã‚’確èªã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚%{more_info_link}"
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
-msgstr "HTTP リãƒã‚¸ãƒˆãƒªãŒå…¬é–‹è¨­å®šã•ã‚Œã¦ã„ãªã„ã¨ãã¯ã€èªè¨¼æƒ…報を URL ã«è¿½åŠ ã—ã¦ãã ã•ã„(URL: <code>https://username:password@gitlab.company.com/group/project.git</code>)。"
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
+msgstr ""
msgid "ImageDiffViewer|2-up"
msgstr "2-up"
@@ -5978,6 +6933,12 @@ msgstr "リãƒã‚¸ãƒˆãƒªã‚’ GitHub ã‹ã‚‰ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹"
msgid "Import repository"
msgstr "リãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆ"
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr "インãƒãƒ¼ãƒˆãŒã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã—ãŸã€‚インãƒãƒ¼ãƒˆã« %{import_jobs_expiration} 秒以上ã‹ã‹ã‚Šã¾ã—ãŸ"
@@ -5987,16 +6948,31 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr "リãƒã‚¸ãƒˆãƒªã¸æŽ¥ç¶š"
-msgid "ImportProjects|Importing the project failed"
+msgid "ImportProjects|Blocked import URL: %{message}"
msgstr ""
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
+msgid "ImportProjects|Importing the project failed"
+msgstr "プロジェクトã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆã«å¤±æ•—ã—ã¾ã—ãŸ"
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr "リモートデータをインãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
+
+msgid "ImportProjects|The repository could not be created."
+msgstr "リãƒã‚¸ãƒˆãƒªã‚’作æˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
+
msgid "ImportProjects|Updating the imported projects failed"
+msgstr "インãƒãƒ¼ãƒˆã—ãŸãƒ—ロジェクトã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸ"
+
+msgid "Improve Issue boards"
msgstr ""
msgid "Improve Issue boards with GitLab Enterprise Edition."
@@ -6050,12 +7026,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr "互æ›æ€§ã®ãªã„プロジェクト"
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr "SSH éµã‚’アップロードã—ã¦ã„ãªã„ユーザーã«ã€è¿½åŠ ã•ã‚Œã‚‹ã¾ã§ SSH 経由ã§ãƒ—ッシュã§ããªã„ã“ã¨ã‚’通知"
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr "インライン"
@@ -6069,7 +7054,7 @@ msgid "Insert a quote"
msgstr ""
msgid "Insert code"
-msgstr ""
+msgstr "コードを挿入"
msgid "Insert suggestion"
msgstr "候補を挿入ã™ã‚‹"
@@ -6077,12 +7062,24 @@ msgstr "候補を挿入ã™ã‚‹"
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr "GitLab Runner ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«"
msgid "Install Runner on Kubernetes"
msgstr "Kubernetes 㫠Runner をインストール"
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] "インスタンス"
@@ -6129,18 +7126,42 @@ msgstr "サイクル分æžã®ã”紹介"
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
+msgstr "無効ãªãƒ•ã‚¡ã‚¤ãƒ«ã§ã™ã€‚"
+
+msgid "Invalid import params"
msgstr ""
msgid "Invalid input, please avoid emojis"
-msgstr ""
+msgstr "入力ãŒç„¡åŠ¹ã§ã™ã€‚絵文字をå«ã‚ãªã„ã§ãã ã•ã„"
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6150,6 +7171,9 @@ msgstr "招待状"
msgid "Invite"
msgstr "招待"
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr "グループã«æ‹›å¾…ã™ã‚‹"
@@ -6162,11 +7186,14 @@ msgstr "呼ã³å‡ºã—回数"
msgid "Invoke Time"
msgstr "呼ã³å‡ºã—時間"
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
msgid "Issue"
-msgstr ""
+msgstr "課題"
msgid "Issue Boards"
msgstr ""
@@ -6180,6 +7207,12 @@ msgstr "課題イベント"
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr "ボード"
@@ -6217,7 +7250,7 @@ msgid "Issues, merge requests, pushes, and comments."
msgstr "課題ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã€ãƒ—ッシュã€ã‚³ãƒ¡ãƒ³ãƒˆ"
msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
-msgstr ""
+msgstr "プロジェクトã®èª²é¡Œã®ä½œæˆã‚’開始ã—ãŸã‚‰ã€ãƒ—ロジェクトã®ãƒ¡ãƒˆãƒªã‚¯ã‚¹ã‚’追跡ã—ã¦è¡¨ç¤ºã§ãã¾ã™ã€‚"
msgid "IssuesAnalytics|Issues Created"
msgstr "課題ãŒä½œæˆã•ã‚Œã¾ã—ãŸ"
@@ -6241,7 +7274,7 @@ msgid "It must have a header row and at least two columns: the first column is t
msgstr "ヘッダー行ã¨å°‘ãªãã¨ã‚‚2ã¤ã®åˆ—ãŒå¿…è¦ã§ã™ã€‚最åˆã®åˆ—ã¯èª²é¡Œã®ã‚¿ã‚¤ãƒˆãƒ«ã€2番目ã®åˆ—ã¯èª²é¡Œã®èª¬æ˜Žã§ã™ã€‚区切り文字ã¯è‡ªå‹•çš„ã«æ¤œå‡ºã•ã‚Œã¾ã™ã€‚"
msgid "It's you"
-msgstr ""
+msgstr "ã‚ãªãŸã§ã™"
msgid "Jaeger URL"
msgstr "Jaeger URL"
@@ -6255,6 +7288,48 @@ msgstr "1月"
msgid "January"
msgstr "1月"
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr "JIRA APIã®URL"
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr "課題ãŒã‚³ãƒŸãƒƒãƒˆã§å‚ç…§ã•ã‚Œã‚‹ã¨ JiraコメントãŒä½œæˆã•ã‚Œã¾ã™ã€‚"
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr "パスワードã¾ãŸã¯APIトークン"
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr "Web URL"
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr "ジョブ"
@@ -6313,7 +7388,7 @@ msgid "Job|Keep"
msgstr "維æŒ"
msgid "Job|Pipeline"
-msgstr ""
+msgstr "パイプライン"
msgid "Job|Scroll to bottom"
msgstr "最下部ã«ã‚¹ã‚¯ãƒ­ãƒ¼ãƒ«"
@@ -6351,6 +7426,12 @@ msgstr "7月"
msgid "July"
msgstr "7月"
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr "6月"
@@ -6360,6 +7441,9 @@ msgstr "6月"
msgid "Key (PEM)"
msgstr "キー (PEM)"
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -6384,17 +7468,23 @@ msgstr "Kubernetes クラスターã¯æ­£å¸¸ã«æ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚"
msgid "Kubernetes configured"
msgstr "Kubernetes 構æˆæ¸ˆã¿"
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr "Kubernetes サービスã®çµ±åˆã¯å»ƒæ­¢ã•ã‚Œã¾ã—ãŸã€‚%{deprecated_message_content} æ–°ã—ã„<a href=\"%{url}\"/>Kubernetes クラスター</a> ã®ãƒšãƒ¼ã‚¸ã‚’使用ã—ã¦ãã ã•ã„"
msgid "LDAP settings"
msgstr "LDAP 設定"
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr "LFS"
msgid "LFS objects"
-msgstr ""
+msgstr "LFS オブジェクト"
msgid "LFSStatus|Disabled"
msgstr "無効"
@@ -6402,6 +7492,9 @@ msgstr "無効"
msgid "LFSStatus|Enabled"
msgstr "有効"
+msgid "LICENSE"
+msgstr "ライセンス"
+
msgid "Label"
msgstr "ラベル"
@@ -6412,7 +7505,7 @@ msgid "Label lists show all issues with the selected label."
msgstr "ラベル一覧ã«ã¯ã€é¸æŠžã—ãŸãƒ©ãƒ™ãƒ«ãŒä»˜ã„ãŸã™ã¹ã¦ã®èª²é¡ŒãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
msgid "Label was created"
-msgstr ""
+msgstr "ラベルãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
msgid "Label was removed"
msgstr ""
@@ -6450,6 +7543,9 @@ msgstr "ラベルã®æ˜‡æ ¼"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr "%{labelTitle} を宣言ã™ã‚‹ã¨ %{groupName} 内ã®ã™ã¹ã¦ã®ãƒ—ロジェクト内ã§åˆ©ç”¨å¯èƒ½ã«ãªã‚Šã¾ã™ã€‚åŒã˜ã‚¿ã‚¤ãƒˆãƒ«ã®æ—¢å­˜ã®ãƒ—ロジェクトラベルã¯ãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã™ã€‚ã“ã®æ“作ã¯å…ƒã«æˆ»ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“。"
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr "言語"
@@ -6463,6 +7559,9 @@ msgstr[0] "éŽåŽ»%d日間"
msgid "Last Pipeline"
msgstr "最新パイプライン"
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr "最後ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティ"
@@ -6490,6 +7589,12 @@ msgstr "最終更新"
msgid "Last updated"
msgstr "最終更新"
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr "ã“ã“ã¸ãƒ—ッシュã—ã¾ã—ãŸ"
@@ -6505,6 +7610,12 @@ msgstr "ã“ã®ãƒ–ランãƒã®æœ€æ–°ã®ãƒ‘イプライン"
msgid "Lead"
msgstr "リード"
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6523,6 +7634,9 @@ msgstr "Kubernetes ã®è©³ç´°"
msgid "Learn more about Web Terminal"
msgstr "Web Terminalã®è©³ç´°"
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr "承èªã®è©³ç´°"
@@ -6535,6 +7649,9 @@ msgstr "グループレベルプロジェクトテンプレートã®è©³ç´°"
msgid "Learn more about signing commits"
msgstr "コミットã¸ã®ç½²åã®è©³ç´°"
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr "詳ã—ã見る:"
@@ -6545,7 +7662,7 @@ msgid "Leave"
msgstr "離れる"
msgid "Leave edit mode? All unsaved changes will be lost."
-msgstr ""
+msgstr "編集モードを終了ã—ã¾ã™ã‹ï¼Ÿãã®å ´åˆã€ä¿å­˜ã—ã¦ã„ãªã„変更ã¯ã™ã¹ã¦å¤±ã‚ã‚Œã¾ã™ã€‚"
msgid "Leave group"
msgstr "グループを離脱"
@@ -6556,6 +7673,12 @@ msgstr "プロジェクトを離脱"
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr "Let's Encryptã¯example.comã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’å—ã‘付ã‘ã¾ã›ã‚“"
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr "ライセンス"
@@ -6605,7 +7728,7 @@ msgid "LicenseManagement|License name"
msgstr "ライセンスå"
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
-msgstr ""
+msgstr "ã“ã®ãƒ—ロジェクトã®æ‰¿èªæ¸ˆã¿ãŠã‚ˆã³ãƒ–ラックリストã«ç™»éŒ²ã•ã‚ŒãŸãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’管ç†ã—ã¾ã™ã€‚"
msgid "LicenseManagement|Packages"
msgstr "パッケージ"
@@ -6631,6 +7754,9 @@ msgstr "URL"
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr "ã“ã®ãƒ—ロジェクトã‹ã‚‰ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ %{name} を削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚"
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6644,6 +7770,9 @@ msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -6674,6 +7803,9 @@ msgstr "ライブプレビュー"
msgid "Loading contribution stats for group members"
msgstr "グループメンãƒãƒ¼ã®è²¢çŒ®åº¦æƒ…報を読ã¿è¾¼ã¿ä¸­"
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr "GitLab IDE ã®èª­ã¿è¾¼ã¿ä¸­..."
@@ -6684,7 +7816,7 @@ msgid "Loading…"
msgstr "読ã¿è¾¼ã¿ä¸­â€¦"
msgid "Localization"
-msgstr ""
+msgstr "ローカライズ"
msgid "Lock"
msgstr "ロック"
@@ -6695,6 +7827,9 @@ msgstr "ロック %{issuableDisplayName}"
msgid "Lock not found"
msgstr "ロックãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr "%{issuableDisplayName} をロックã—ã¾ã™ã‹ï¼Ÿ<strong>プロジェクトメンãƒãƒ¼</strong> ã®ã¿ã‚³ãƒ¡ãƒ³ãƒˆã§ãã¾ã™ã€‚"
@@ -6713,6 +7848,9 @@ msgstr "ç¾åœ¨ã®ãƒ—ロジェクトã¯ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™"
msgid "Locks give the ability to lock specific file or folder."
msgstr "ロックã¯ã€ç‰¹å®šã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚„フォルダをロックã™ã‚‹æ©Ÿèƒ½ã‚’æä¾›ã—ã¾ã™ã€‚"
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr "スマートカードã§ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹"
@@ -6737,10 +7875,19 @@ msgstr "変更ã®ã¿è¡¨ç¤º"
msgid "MRDiff|Show full file"
msgstr "ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’表示"
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr "ãƒãƒ¼ãƒ å…¨å“¡ãŒå ´æ‰€ã«é–¢ä¿‚ãªãより生産的ã«æ´»å‹•ã§ãã¾ã™ã€‚GitLab Geo ã¯ã€å¤§ããªã‚µã‚¤ã‚ºã®ãƒªãƒã‚¸ãƒˆãƒªã®å–得やクローンã«ã‹ã‹ã‚‹æ™‚間を削減ã™ã‚‹ãŸã‚ã«ã€èª­ã¿è¾¼ã¿å°‚用ã®ãƒŸãƒ©ãƒ¼ã‚’ GitLab インスタンス上ã«ä½œæˆã—ã¾ã™ã€‚"
+msgid "Make issue confidential."
+msgstr "課題をéžå…¬é–‹è¨­å®šã«ã™ã‚‹"
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
+msgstr "インãƒãƒ¼ãƒˆã™ã‚‹ãƒ—ロジェクトを所有ã™ã‚‹ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã§ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。"
+
+msgid "Makes this issue confidential"
msgstr ""
msgid "Manage"
@@ -6803,6 +7950,15 @@ msgstr "3月"
msgid "March"
msgstr "3月"
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr "ã“ã®èª²é¡Œã‚’別ã®èª²é¡Œã¨é‡è¤‡ã—ã¦ã„ã‚‹ã¨ãƒžãƒ¼ã‚¯ã™ã‚‹"
+
msgid "Mark todo as done"
msgstr "Todo を完了ã«ã™ã‚‹"
@@ -6810,11 +7966,20 @@ msgid "Markdown"
msgstr "Markdown"
msgid "Markdown Help"
-msgstr ""
+msgstr "Markdown ヘルプ"
msgid "Markdown enabled"
msgstr "マークダウンを使用ã§ãã¾ã™"
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr "Maven メタデータ"
@@ -6822,7 +7987,7 @@ msgid "Max access level"
msgstr "最大アクセスレベル"
msgid "Max seats used"
-msgstr ""
+msgstr "最大使用シート数"
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -6839,6 +8004,9 @@ msgstr "最大é…延時間(分)"
msgid "Maximum job timeout"
msgstr "ジョブタイムアウトã®æœ€å¤§å€¤"
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr "åŒæ™‚ã«åŒæœŸã§ãるミラーã®æœ€å¤§æ•°ã€‚"
@@ -6869,27 +8037,24 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr "<strong>%{project_name}</strong>ã®ãƒ¡ãƒ³ãƒãƒ¼"
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr "マージリクエスト"
msgid "Merge Request Approvals"
-msgstr ""
+msgstr "マージリクエスト承èª"
msgid "Merge Requests"
msgstr "マージリクエスト"
msgid "Merge Requests created"
-msgstr ""
-
-msgid "Merge commit"
-msgstr ""
+msgstr "作æˆã•ã‚ŒãŸãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
msgid "Merge commit message"
msgstr "マージコミットメッセージ"
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr "マージイベント"
@@ -6899,12 +8064,6 @@ msgstr "今ã™ãマージã™ã‚‹"
msgid "Merge in progress"
msgstr "進行中ã®ãƒžãƒ¼ã‚¸"
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr "マージパイプラインã¯ãƒžãƒ¼ã‚¸å®Ÿè¡Œå‰ã«ã€äº‹å‰ãƒžãƒ¼ã‚¸ã®çµæžœã®æ¤œè¨¼ã‚’試ã¿ã¾ã™"
-
msgid "Merge request"
msgstr "マージリクエスト"
@@ -6923,6 +8082,30 @@ msgstr "マージリクエストã¨ã¯ã€ãƒ—ロジェクトã«åŠ ãˆãŸå¤‰æ›´ã‚’
msgid "Merge when pipeline succeeds"
msgstr "パイプラインãŒæˆåŠŸã—ãŸã¨ãã«ãƒžãƒ¼ã‚¸"
+msgid "MergeConflict|Commit to source branch"
+msgstr "ソースブランãƒã¸ã®ã‚³ãƒŸãƒƒãƒˆ"
+
+msgid "MergeConflict|Committing..."
+msgstr "コミット中..."
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr "競åˆ"
+
+msgid "MergeConflict|conflicts"
+msgstr "競åˆ"
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr "返信を追加"
@@ -6941,9 +8124,12 @@ msgstr "ディスカッションã¯è§£æ±ºã•ã‚Œã¾ã™ã€‚"
msgid "MergeRequests|Discussion will be unresolved"
msgstr "ディスカッションã¯è§£æ±ºã•ã‚Œã¾ã›ã‚“。"
-msgid "MergeRequests|Jump to next unresolved discussion"
+msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
+msgid "MergeRequests|Jump to next unresolved discussion"
+msgstr "次ã®æœªè§£æ±ºã®è­°è«–ã«ã‚¸ãƒ£ãƒ³ãƒ—ã™ã‚‹"
+
msgid "MergeRequests|Reply..."
msgstr "返信..."
@@ -6953,6 +8139,9 @@ msgstr "æ–°ã—ã„課題ã§ã“ã®æ¤œè¨Žã‚’解決ã™ã‚‹"
msgid "MergeRequests|Saving the comment failed"
msgstr "コメントã®ä¿å­˜ã«å¤±æ•—ã—ã¾ã—ãŸ"
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr "ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã®ã‚³ãƒ¡ãƒ³ãƒˆã‚’切り替ãˆã¾ã™"
@@ -6986,8 +8175,8 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
-msgstr "ファイルã®ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
+msgstr ""
msgid "MergeRequest|No files found"
msgstr "ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
@@ -7001,6 +8190,12 @@ msgstr ""
msgid "Messages"
msgstr "メッセージ"
+msgid "Metric was successfully added."
+msgstr "メトリクスã¯æ­£å¸¸ã«è¿½åŠ ã•ã‚Œã¾ã—ãŸã€‚"
+
+msgid "Metric was successfully updated."
+msgstr "メトリクスã¯æ­£å¸¸ã«æ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚"
+
msgid "Metrics"
msgstr "メトリクス"
@@ -7016,6 +8211,9 @@ msgstr "メトリクスã¨ãƒ—ロファイリング"
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr "メトリクスを追加"
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "環境ã¸ã®ãƒ‡ãƒ—ロイã«ã¤ã„ã¦ã¯ã€CI / CD ã®æ–‡æ›¸ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
@@ -7023,10 +8221,10 @@ msgid "Metrics|Create metric"
msgstr "メトリクスを作æˆ"
msgid "Metrics|Delete metric"
-msgstr ""
+msgstr "メトリクスを削除"
msgid "Metrics|Delete metric?"
-msgstr ""
+msgstr "メトリクスを削除?"
msgid "Metrics|Edit metric"
msgstr "メトリクスを編集"
@@ -7055,9 +8253,6 @@ msgstr "æ–°è¦ãƒ¡ãƒˆãƒªã‚¯ã‚¹"
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7103,9 +8298,21 @@ msgstr "Y軸ラベル"
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr "例:スループット"
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7130,9 +8337,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr "<p>%{milestonePromotion}</p> %{finalWarning}"
-
msgid "Milestones|Delete milestone"
msgstr "マイルストーンã®å‰Šé™¤"
@@ -7151,8 +8355,8 @@ msgstr "%{milestoneTitle} をグループマイルストーンã«æ˜‡æ ¼ã—ã¾ã™
msgid "Milestones|Promote Milestone"
msgstr "マイルストーンã®æ˜‡æ ¼"
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
-msgstr "%{milestone} を宣言ã™ã‚‹ã¨ã€ %{groupName} 内ã®ã™ã¹ã¦ã®ãƒ—ロジェクトã§åˆ©ç”¨ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚åŒã˜åå‰ã®æ—¢å­˜ã®ãƒ—ロジェクトマイルストーンãŒãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã™ã€‚ "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
+msgstr ""
msgid "Milestones|This action cannot be reversed."
msgstr "ã“ã®æ“作ã¯å…ƒã«æˆ»ã›ã¾ã›ã‚“。"
@@ -7160,6 +8364,15 @@ msgstr "ã“ã®æ“作ã¯å…ƒã«æˆ»ã›ã¾ã›ã‚“。"
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr "分"
+
msgid "Mirror a repository"
msgstr ""
@@ -7179,6 +8392,18 @@ msgid "Mirroring repositories"
msgstr ""
msgid "Mirroring settings were successfully updated."
+msgstr "ミラーリングã®è¨­å®šã‚’æ­£ã—ãä¿å­˜ã—ã¾ã—ãŸã€‚"
+
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr "ミラーリング設定を正ã—ãæ›´æ–°ã—ã¾ã—ãŸã€‚プロジェクトã¯æ›´æ–°ä¸­ã§ã™ã€‚"
+
+msgid "Mirroring was successfully disabled."
+msgstr "ミラーリングを正ã—ã無効化ã—ã¾ã—ãŸ"
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
msgstr ""
msgid "MissingSSHKeyWarningLink|add an SSH key"
@@ -7191,7 +8416,7 @@ msgid "Modal|Close"
msgstr "é–‰ã˜ã‚‹"
msgid "Modify commit message"
-msgstr ""
+msgstr "コミットメッセージã®ä¿®æ•´"
msgid "Modify commit messages"
msgstr "コミットメッセージを修正"
@@ -7233,7 +8458,7 @@ msgid "Most stars"
msgstr "スター数ã®å¤šã„é †"
msgid "Mount point %{mounted_as} not found in %{model_class}."
-msgstr ""
+msgstr "%{mounted_as} ã®ãƒžã‚¦ãƒ³ãƒˆãƒã‚¤ãƒ³ãƒˆãŒ%{model_class} 内ã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
msgid "Move"
msgstr "移動"
@@ -7241,6 +8466,24 @@ msgstr "移動"
msgid "Move issue"
msgstr "課題を移動"
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr "課題を %{path_to_project} ã«ç§»å‹•ã™ã‚‹ã€‚"
+
msgid "Multiple issue boards"
msgstr "マルãƒèª²é¡Œãƒœãƒ¼ãƒ‰"
@@ -7248,11 +8491,14 @@ msgid "Multiple model types found: %{model_types}"
msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
-msgstr ""
+msgstr "複数ã®ã‚¢ãƒƒãƒ—ローダーãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ: %{uploader_types}"
msgid "Name"
msgstr "åå‰"
+msgid "Name has already been taken"
+msgstr "ãã®åå‰ã¯æ—¢ã«ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™ã€‚"
+
msgid "Name new label"
msgstr "æ–°ã—ã„ラベルã«åå‰ã‚’ã¤ã‘ã‚‹"
@@ -7266,7 +8512,7 @@ msgid "Namespaces to index"
msgstr ""
msgid "Naming, topics, avatar"
-msgstr ""
+msgstr "命åã€ãƒˆãƒ”ックã€ã‚¢ãƒã‚¿ãƒ¼"
msgid "Naming, visibility"
msgstr ""
@@ -7347,6 +8593,9 @@ msgstr "æ–°ã—ã„環境"
msgid "New epic"
msgstr "æ–°ã—ã„エピック"
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr "æ–°è¦ãƒ•ã‚¡ã‚¤ãƒ«"
@@ -7371,6 +8620,9 @@ msgstr "æ–°è¦ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
msgid "New milestone"
msgstr "æ–°ã—ã„マイルストーン"
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7401,6 +8653,12 @@ msgstr "æ–°è¦...\t"
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr "ã„ã„ãˆ"
@@ -7410,12 +8668,21 @@ msgstr ""
msgid "No Label"
msgstr "ラベルãŒã‚ã‚Šã¾ã›ã‚“"
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr "アクティビティã¯ã‚ã‚Šã¾ã›ã‚“"
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7431,8 +8698,11 @@ msgstr "Gitaly サーãƒãƒ¼ã«æŽ¥ç¶šã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ログを確èªã
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr "貢献ãªã—"
+
msgid "No contributions were found"
-msgstr ""
+msgstr "貢献ãŒã¿ã¤ã‹ã‚Šã¾ã›ã‚“。"
msgid "No credit card required."
msgstr "クレジット カードã¯å¿…è¦ã‚ã‚Šã¾ã›ã‚“"
@@ -7455,6 +8725,9 @@ msgstr "ファイルãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“"
msgid "No file selected"
msgstr "ファイルãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“"
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr "ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。"
@@ -7471,16 +8744,13 @@ msgid "No license. All rights reserved"
msgstr ""
msgid "No licenses found."
-msgstr ""
+msgstr "ライセンスãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。"
msgid "No matching results"
msgstr "一致ã™ã‚‹çµæžœãŒã‚ã‚Šã¾ã›ã‚“"
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
-msgstr ""
+msgstr "é¸æŠžã—ãŸæœŸé–“ã«ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯ã‚ã‚Šã¾ã›ã‚“。"
msgid "No merge requests found"
msgstr "マージリクエストã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ"
@@ -7494,6 +8764,9 @@ msgstr "表示ã™ã‚‹ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ãŒã‚ã‚Šã¾ã›ã‚“"
msgid "No other labels with such name or description"
msgstr "ãã®ä»–ã«ã€ãã®åå‰ã¾ãŸã¯èª¬æ˜Žã®ãƒ©ãƒ™ãƒ«ãŒã‚ã‚Šã¾ã›ã‚“"
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7504,7 +8777,7 @@ msgid "No public groups"
msgstr ""
msgid "No pushes for the selected time period."
-msgstr ""
+msgstr "é¸æŠžã—ãŸæœŸé–“ã«ãƒ—ッシュã¯ã‚ã‚Šã¾ã›ã‚“。"
msgid "No repository"
msgstr "リãƒã‚¸ãƒˆãƒªãŒã‚ã‚Šã¾ã›ã‚“"
@@ -7521,6 +8794,12 @@ msgstr "開始日ãªã—"
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr "ノード"
@@ -7569,6 +8848,9 @@ msgstr "注: GitLab ã®ç®¡ç†è€…ã«%{github_integration_link} を設定ã—ã¦ã€
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr "注: GitLab ã®ç®¡ç†è€…ã«%{github_integration_link} を設定ã—ã¦ã€GitHub 経由ã®ãƒ­ã‚°ã‚¤ãƒ³ãŒè¨±å¯ã—ã€å€‹äººç”¨ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ã‚’生æˆã›ãšã«ãƒªãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆã§ããªã„ã‹å•ã„åˆã‚ã›ãã ã•ã„。"
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "本当ã«ã“ã®ã‚³ãƒ¡ãƒ³ãƒˆã®ä½œæˆã‚’キャンセルã—ã¾ã™ã‹ï¼Ÿ"
@@ -7584,6 +8866,12 @@ msgstr "コメントã®ã¿è¡¨ç¤º"
msgid "Notes|Show history only"
msgstr "履歴ã®ã¿è¡¨ç¤º"
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr "プレビューã§ãã‚‹ã‚‚ã®ã¯ä½•ã‚‚ã‚ã‚Šã¾ã›ã‚“。"
+
msgid "Notification events"
msgstr "イベント通知"
@@ -7593,6 +8881,9 @@ msgstr "通知設定"
msgid "Notification setting - %{notification_title}"
msgstr "通知設定 - %{notification_title}"
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "課題をクローズ"
@@ -7606,7 +8897,7 @@ msgid "NotificationEvent|Merge merge request"
msgstr "マージリクエストをマージ"
msgid "NotificationEvent|New epic"
-msgstr ""
+msgstr "æ–°è¦ã‚¨ãƒ“ック"
msgid "NotificationEvent|New issue"
msgstr "æ–°è¦èª²é¡Œ"
@@ -7647,6 +8938,9 @@ msgstr "å‚加"
msgid "NotificationLevel|Watch"
msgstr "ã™ã¹ã¦é€šçŸ¥"
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr "通知"
@@ -7662,6 +8956,12 @@ msgstr "11月"
msgid "November"
msgstr "11月"
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr "OK"
@@ -7677,8 +8977,14 @@ msgstr "10月"
msgid "OfSearchInADropdown|Filter"
msgstr "フィルター"
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
-msgstr "インãƒãƒ¼ãƒˆã™ã‚‹ã¨ãƒªãƒã‚¸ãƒˆãƒªã¯ SSH ã§ãƒŸãƒ©ãƒ¼ãƒªãƒ³ã‚°ã§ãã¾ã™ã€‚詳細㯠%{ssh_link} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
+msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
msgstr ""
@@ -7699,20 +9005,20 @@ msgstr "1ã¤ä»¥ä¸Šã® Bitbucket プロジェクトを GitLab ã«ç›´æŽ¥ã‚¤ãƒ³ãƒã
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "1ã¤ä»¥ä¸Šã® Google コードプロジェクトを GitLab ã«ç›´æŽ¥ã‚¤ãƒ³ãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“。ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç®¡ç†ã«ã€Git ã§ã¯ãªãã€Subversion ã‚„ Mercurial を使用ã—ã¦ã„ã‚‹ã‹ã‚‰ã§ã™ã€‚"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
+msgstr ""
+
msgid "Only admins"
msgstr "管ç†è€…ã®ã¿"
-msgid "Only allow merge requests to be merged if all discussions are resolved"
-msgstr ""
-
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
msgstr ""
msgid "Only policy:"
-msgstr ""
+msgstr "ãƒãƒªã‚·ãƒ¼ã®ã¿:"
msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
msgstr ""
@@ -7723,6 +9029,9 @@ msgstr "プロジェクトメンãƒãƒ¼ã®ã¿ã‚³ãƒ¡ãƒ³ãƒˆã§ãã¾ã™"
msgid "Only project members will be imported. Group members will be skipped."
msgstr "プロジェクトメンãƒãƒ¼ã®ã¿ãŒã‚¤ãƒ³ãƒãƒ¼ãƒˆã•ã‚Œã¾ã™ã€‚グループメンãƒãƒ¼ã¯ã‚¹ã‚­ãƒƒãƒ—ã•ã‚Œã¾ã™ã€‚"
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7733,7 +9042,7 @@ msgid "Open Documentation"
msgstr "ドキュメントを開ã"
msgid "Open comment type dropdown"
-msgstr ""
+msgstr "コメントタイプドロップダウンを開ã"
msgid "Open errors"
msgstr ""
@@ -7768,6 +9077,12 @@ msgstr "オープンã•ã‚ŒãŸã®ã¯"
msgid "Opens in a new window"
msgstr "æ–°è¦ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã§é–‹ã"
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr "é‹ç”¨"
@@ -7778,7 +9093,7 @@ msgid "Operations Settings"
msgstr ""
msgid "OperationsDashboard|Add a project to the dashboard"
-msgstr ""
+msgstr "ダッシュボードã«ãƒ—ロジェクトを追加"
msgid "OperationsDashboard|Add projects"
msgstr ""
@@ -7792,9 +9107,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr "オプション"
@@ -7816,6 +9128,9 @@ msgstr "ãã®ä»–ã®ãƒ©ãƒ™ãƒ«"
msgid "Other information"
msgstr "ãã®ä»–ã®æƒ…å ±"
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7825,6 +9140,12 @@ msgstr "概è¦"
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr "オーナー"
@@ -7852,6 +9173,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "最後 »"
@@ -7873,9 +9197,21 @@ msgstr "マージリクエストã§ã®å¤‰æ›´ç®‡æ‰€"
msgid "Password"
msgstr "パスワード"
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr "期é™åˆ‡ã‚Œ"
@@ -7888,11 +9224,11 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
-msgstr "ã‚ãªãŸã® SSH 公開éµã‚’貼り付ã‘ã¾ã™ã€‚ã“ã®éµã¯é€šå¸¸ã€ãƒ•ã‚¡ã‚¤ãƒ« '~/.ssh/id_rsa.pub' 内ã«ã‚ã‚Šã€'ssh-rsa' ã¨ã„ã†æ–‡å­—列ã‹ã‚‰å§‹ã¾ã‚Šã¾ã™ã€‚SSH ã®ç§˜å¯†éµã‚’使用ã—ãªã„よã†ã«ã—ã¦ãã ã•ã„。"
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
msgid "Path"
-msgstr ""
+msgstr "パス"
msgid "Path, transfer, remove"
msgstr ""
@@ -7915,6 +9251,9 @@ msgstr "ä¿ç•™ä¸­"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr "権é™ã®ãªã„ユーザーã¯ä¸€åˆ‡é€šçŸ¥ã‚’å—ã‘ã‚‹ã“ã¨ãŒãªãã€ã¾ãŸã‚³ãƒ¡ãƒ³ãƒˆã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã›ã‚“。"
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr "パスã®å¤‰æ›´ã€è»¢é€ã€ã‚°ãƒ«ãƒ¼ãƒ—ã®å‰Šé™¤ãªã©ã®é«˜åº¦ãªã‚ªãƒ—ションを実行ã—ã¾ã™ã€‚"
@@ -7936,12 +9275,27 @@ msgstr "個人ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³"
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr "åå‰ã‚’é¸æŠž"
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr "パイプライン"
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr "パイプラインスケジュール"
@@ -8020,6 +9374,9 @@ msgstr "パイプライン"
msgid "Pipelines charts"
msgstr "パイプラインãƒãƒ£ãƒ¼ãƒˆ"
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr "先月ã®ãƒ‘イプライン"
@@ -8029,12 +9386,15 @@ msgstr "先週ã®ãƒ‘イプライン"
msgid "Pipelines for last year"
msgstr "昨年ã®ãƒ‘イプライン"
-msgid "Pipelines need to be configured to enable this feature."
-msgstr "ã“ã®æ©Ÿèƒ½ã‚’有効ã«ã™ã‚‹ã«ã¯ã€ãƒ‘イプラインを設定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
+msgstr "API"
+
msgid "Pipelines|Build with confidence"
msgstr ""
@@ -8053,6 +9413,9 @@ msgstr "パイプラインã®åˆ©ç”¨ã‚’開始ã™ã‚‹"
msgid "Pipelines|Loading Pipelines"
msgstr "パイプラインを読ã¿è¾¼ã¿ä¸­"
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "プロジェクトã®ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’正常ã«ãƒªã‚»ãƒƒãƒˆã—ã¾ã—ãŸã€‚"
@@ -8060,7 +9423,7 @@ msgid "Pipelines|Run Pipeline"
msgstr "パイプライン実行"
msgid "Pipelines|Something went wrong while cleaning runners cache."
-msgstr ""
+msgstr "Runner キャッシュã®ã‚¯ãƒªãƒ¼ãƒ‹ãƒ³ã‚°ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Pipelines|There are currently no %{scope} pipelines."
msgstr "%{scope} パイプラインã¯ç¾åœ¨ã‚ã‚Šã¾ã›ã‚“。"
@@ -8078,7 +9441,7 @@ msgid "Pipeline|Commit"
msgstr "コミット"
msgid "Pipeline|Coverage"
-msgstr ""
+msgstr "ã‚«ãƒãƒ¬ãƒƒã‚¸"
msgid "Pipeline|Duration"
msgstr "期間"
@@ -8113,6 +9476,9 @@ msgstr "パイプラインã®åœæ­¢"
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr "#%{pipelineId} パイプラインをåœæ­¢ã—ã¾ã™ã‹ï¼Ÿ"
+msgid "Pipeline|Triggerer"
+msgstr "トリガー"
+
msgid "Pipeline|Variables"
msgstr "変数"
@@ -8143,6 +9509,15 @@ msgstr "ステージã‚ã‚Š"
msgid "Pipeline|with stages"
msgstr "ステージã‚ã‚Š"
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8152,12 +9527,30 @@ msgstr "PlantUML"
msgid "Play"
msgstr "実行"
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr "コメントã™ã‚‹ã«ã¯ %{link_to_register} ã¾ãŸã¯ %{link_to_sign_in} ã‚’ã—ã¦ãã ã•ã„"
msgid "Please accept the Terms of Service before continuing."
msgstr "続ã‘ã‚‹å‰ã«ã€åˆ©ç”¨è¦ç´„ã«åŒæ„ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
+msgid "Please add a comment in the text area above"
+msgstr "上ã®ãƒ†ã‚­ã‚¹ãƒˆã‚¨ãƒªã‚¢ã«ã‚³ãƒ¡ãƒ³ãƒˆã‚’加ãˆã¦ãã ã•ã„。"
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr "ãƒãƒ£ãƒ¼ãƒˆã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’確èªã—ã¦ãã ã•ã„"
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8171,7 +9564,7 @@ msgid "Please convert them to Git on Google Code, and go through the %{link_to_i
msgstr "ãれらを Google コード上㧠Git ã«å¤‰æ›ã—ã¦ã€å†ã³ %{link_to_import_flow} ã‚’è¡Œã£ã¦ãã ã•ã„。"
msgid "Please create a password for your new account."
-msgstr ""
+msgstr "æ–°ã—ã„アカウントã®ãƒ‘スワードを作æˆã—ã¦ãã ã•ã„。"
msgid "Please create a username with only alphanumeric characters."
msgstr ""
@@ -8180,7 +9573,7 @@ msgid "Please enable and migrate to hashed storage to avoid security issues and
msgstr ""
msgid "Please enter a non-negative number"
-msgstr ""
+msgstr "有効ãªã‚¼ãƒ­ä»¥ä¸Šã®æ•°å­—を入力ã—ã¦ãã ã•ã„"
msgid "Please enter a number greater than %{number} (from the project settings)"
msgstr ""
@@ -8188,8 +9581,11 @@ msgstr ""
msgid "Please enter a valid number"
msgstr "有効ãªæ•°å€¤ã‚’入力ã—ã¦ãã ã•ã„"
+msgid "Please enter or upload a license."
+msgstr "ライセンスを入力ã—ã¦ãã ã•ã„ã€ã¾ãŸã¯ã‚¢ãƒƒãƒ—ロードã—ã¦ãã ã•ã„。"
+
msgid "Please fill in a descriptive name for your group."
-msgstr ""
+msgstr "ã‚ãªãŸã®ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚ã‹ã‚Šã‚„ã™ã„åå‰ã‚’記入ã—ã¦ãã ã•ã„。"
msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
msgstr ""
@@ -8200,17 +9596,26 @@ msgstr "ã“ã®ã‚¢ãƒ—リケーション㯠GitLab ãŒæä¾›ã—ã¦ã„ã¾ã›ã‚“。ã
msgid "Please provide a name"
msgstr "åå‰ã‚’入力ã—ã¦ãã ã•ã„"
-msgid "Please select a group."
+msgid "Please provide a valid email address."
msgstr ""
-msgid "Please select and add a member"
+msgid "Please retype the email address."
msgstr ""
+msgid "Please select a file"
+msgstr "ファイルをé¸æŠžã—ã¦ãã ã•ã„"
+
+msgid "Please select a group."
+msgstr "グループをé¸æŠžã—ã¦ä¸‹ã•ã„。"
+
+msgid "Please select and add a member"
+msgstr "メンãƒãƒ¼ã‚’é¸æŠžã—ã¦è¿½åŠ ã—ã¦ãã ã•ã„"
+
msgid "Please select at least one filter to see results"
msgstr "çµæžœã‚’表示ã™ã‚‹ã«ã¯ã€å°‘ãªãã¨ã‚‚1ã¤ã®ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã‚’é¸æŠžã—ã¦ãã ã•ã„"
msgid "Please set a new password before proceeding."
-msgstr ""
+msgstr "続ã‘ã‚‹å‰ã«æ–°ã—ã„パスワードを設定ã—ã¦ãã ã•ã„。"
msgid "Please solve the reCAPTCHA"
msgstr "reCAPTCHA を解決ã—ã¦ãã ã•ã„"
@@ -8219,9 +9624,9 @@ msgid "Please try again"
msgstr "ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„"
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
-msgstr ""
+msgstr "PostgreSQLã‚’ãƒãƒ¼ã‚¸ãƒ§ãƒ³9.6以é™ã«ã‚¢ãƒƒãƒ—グレードã—ã¦ãã ã•ã„。ç¾åœ¨ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã¯ã€ãƒ¬ãƒ—リケーションã®çŠ¶æ…‹ã‚’確実ã«åˆ¤æ–­ã§ãã¾ã›ã‚“。"
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8239,12 +9644,66 @@ msgstr "基本設定"
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr "ナビゲーションテーマ"
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr "ã“ã®æ©Ÿèƒ½ã¯å®Ÿé¨“çš„ãªã‚‚ã®ã§ã™ã€‚ã¾ãŸç¿»è¨³ã¯ã¾ã å®Œäº†ã—ã¦ã„ã¾ã›ã‚“"
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr "時間フォーマット"
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8260,12 +9719,18 @@ msgstr ""
msgid "Preview"
msgstr "プレビュー"
+msgid "Preview Markdown"
+msgstr "マークダウンをプレビュー"
+
msgid "Preview changes"
-msgstr ""
+msgstr "変更をプレビュー"
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr "プライマリ"
@@ -8293,15 +9758,24 @@ msgstr "プライベート - グループã¨ãƒ—ロジェクトã¯ãƒ¡ãƒ³ãƒãƒ¼ã®
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr "ã‚ãªãŸå€‹äººã®åå‰ç©ºé–“ã«ãƒ—ライベートプロジェクトを作æˆã§ãã¾ã™:"
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr "プロフィール"
msgid "Profile Settings"
msgstr "プロファイルã®è¨­å®š"
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8332,6 +9806,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "ã‚¢ãƒã‚¿ãƒ¼ã‚’削除ã—ã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr "ユーザーåã®å¤‰æ›´"
@@ -8353,6 +9830,9 @@ msgstr "ステータスをクリア"
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8365,6 +9845,9 @@ msgstr "ç¾åœ¨ã®ãƒ‘ス: %{path}"
msgid "Profiles|Current status"
msgstr "ç¾åœ¨ã®çŠ¶æ…‹"
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr "アカウント削除"
@@ -8392,6 +9875,18 @@ msgstr "プロフィールを編集"
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr "フルãƒãƒ¼ãƒ "
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8401,9 +9896,15 @@ msgstr "パスワードãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“"
msgid "Profiles|Invalid username"
msgstr "ユーザーåãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“"
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8413,44 +9914,56 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr "パス"
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
+msgstr "公開アãƒã‚¿ãƒ¼"
+
+msgid "Profiles|Public email"
msgstr ""
msgid "Profiles|Remove avatar"
-msgstr ""
+msgstr "ã‚¢ãƒã‚¿ãƒ¼ã‚’削除"
msgid "Profiles|Set new profile picture"
msgstr "æ–°ã—ã„プロフィール画åƒã‚’設定ã™ã‚‹"
msgid "Profiles|Social sign-in"
-msgstr ""
+msgstr "ソーシャルサインイン"
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
msgid "Profiles|Tell us about yourself in fewer than 250 characters"
-msgstr ""
+msgstr "250文字未満ã§è‡ªå·±ç´¹ä»‹ã—ã¦ãã ã•ã„"
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
-msgstr ""
+msgstr "ã“れ㯠SSH ã®å…¬é–‹éµã«ã¯è¦‹ãˆã¾ã›ã‚“。本当ã«è¿½åŠ ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "Profiles|This email will be displayed on your public profile"
-msgstr ""
+msgstr "ã“ã®ãƒ¡ãƒ¼ãƒ«ã‚’ã‚ãªãŸã®å…¬é–‹ãƒ—ロフィールã«è¡¨ç¤ºã—ã¾ã™"
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{commit_email_link_start}Learn more%{commit_email_link_end}"
msgstr ""
@@ -8459,15 +9972,18 @@ msgid "Profiles|This emoji and message will appear on your profile and throughou
msgstr ""
msgid "Profiles|This information will appear on your profile"
+msgstr "ã“ã®æƒ…報をプロフィールã«è¡¨ç¤ºã—ã¾ã™"
+
+msgid "Profiles|Time settings"
msgstr ""
msgid "Profiles|Two-Factor Authentication"
-msgstr ""
+msgstr "2è¦ç´ èªè¨¼"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "確èªã®ãŸã‚ %{confirmationValue} を入力ã—ã¦ãã ã•ã„:"
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8482,6 +9998,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr "ユーザーåã®å¤‰æ›´ã«å¤±æ•—ã—ã¾ã—㟠- %{message}"
@@ -8498,16 +10017,19 @@ msgid "Profiles|Who you represent or work for"
msgstr ""
msgid "Profiles|You can change your avatar here"
-msgstr ""
+msgstr "ã‚ãªãŸã®ã‚¢ãƒã‚¿ãƒ¼ã‚’変更ã§ãã¾ã™"
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr "ã‚ãªãŸã®ã‚¢ãƒã‚¿ãƒ¼ã‚’変更ã™ã‚‹ã‹ã€ç¾åœ¨ã®ã‚¢ãƒã‚¿ãƒ¼ã‚’削除ã—㦠%{gravatar_link} ã«æˆ»ã›ã¾ã™ã€‚"
+
+msgid "Profiles|You can set your current timezone here"
msgstr ""
msgid "Profiles|You can upload your avatar here"
-msgstr ""
+msgstr "ã‚ãªãŸã®ã‚¢ãƒã‚¿ãƒ¼ã‚’アップロードã§ãã¾ã™"
msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
-msgstr ""
+msgstr "ã“ã“ã«ã‚ãªãŸã®ã‚¢ãƒã‚¿ãƒ¼ã‚’アップロードã™ã‚‹ã‹ã€ %{gravatar_link} ã«å¤‰æ›´ã§ãã¾ã™ã€‚"
msgid "Profiles|You don't have access to delete this user."
msgstr "ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’削除ã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“"
@@ -8522,13 +10044,13 @@ msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ç¾åœ¨ã“れらã®ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚ªãƒ¼ãƒŠãƒ¼ã§ã™:"
msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
-msgstr ""
+msgstr "ã‚ãªãŸã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¯ã‚ãªãŸã® %{provider_label} アカウントã«åŸºã¥ã„ã¦è‡ªå‹•çš„ã«è¨­å®šã•ã‚Œã¾ã—ãŸ"
msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
-msgstr ""
+msgstr "ã‚ãªãŸã®å ´æ‰€ã¯ã‚ãªãŸã® %{provider_label} アカウントã«åŸºã¥ã„ã¦è‡ªå‹•çš„ã«è¨­å®šã•ã‚Œã¾ã—ãŸ"
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
-msgstr ""
+msgstr "ã‚ãªãŸã®åå‰ã¯ã‚ãªãŸã® %{provider_label} アカウントã«åŸºã¥ã„ã¦è‡ªå‹•çš„ã«è¨­å®šã•ã‚Œã¾ã—ãŸã€‚ãã‚Œã§ã‚ãªãŸãŒçŸ¥ã£ã¦ã„る人ãŒã‚ãªãŸã‚’èªè­˜ã§ãã¾ã™"
msgid "Profiles|Your status"
msgstr ""
@@ -8540,7 +10062,7 @@ msgid "Profiles|username"
msgstr "ユーザーå"
msgid "Profiles|website.com"
-msgstr ""
+msgstr "website.com"
msgid "Profiles|your account"
msgstr "ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆ"
@@ -8585,7 +10107,7 @@ msgid "Project ID"
msgstr ""
msgid "Project URL"
-msgstr ""
+msgstr "プロジェクト㮠URL"
msgid "Project access must be granted explicitly to each user."
msgstr "ユーザーã”ã¨ã«ãƒ—ロジェクトアクセスã®æ¨©é™ã‚’指定ã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。"
@@ -8596,6 +10118,9 @@ msgstr ""
msgid "Project avatar"
msgstr "プロジェクトアãƒã‚¿ãƒ¼"
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8641,6 +10166,9 @@ msgstr ""
msgid "Project:"
msgstr "プロジェクト:"
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "講読"
@@ -8669,13 +10197,13 @@ msgid "ProjectLifecycle|Stage"
msgstr "ステージ"
msgid "ProjectOverview|Fork"
-msgstr ""
+msgstr "フォーク"
msgid "ProjectOverview|Forks"
-msgstr ""
+msgstr "フォーク"
msgid "ProjectOverview|Go to your fork"
-msgstr ""
+msgstr "ã‚ãªãŸã®ãƒ•ã‚©ãƒ¼ã‚¯ã¸ç§»å‹•"
msgid "ProjectOverview|Star"
msgstr ""
@@ -8692,6 +10220,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr "ãƒãƒƒã‚¸"
@@ -8701,18 +10247,60 @@ msgstr "ã“ã®è¨­å®šã‚’変更ã™ã‚‹ã«ã¯ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "ã“ã®ãƒªãƒã‚¸ãƒˆãƒªã«ã¯ç½²åã•ã‚ŒãŸã‚³ãƒŸãƒƒãƒˆã®ã¿ãƒ—ッシュã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8722,12 +10310,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ".Net Core"
+
+msgid "ProjectTemplates|Android"
+msgstr "Android"
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr "Ruby on Rails"
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr "iOS (Swift)"
+
msgid "Projects"
msgstr "プロジェクト"
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8762,7 +10410,7 @@ msgid "ProjectsDropdown|Sorry, no projects matched your search"
msgstr "検索æ¡ä»¶ã«ä¸€è‡´ã—ãŸãƒ—ロジェクトã¯ã‚ã‚Šã¾ã›ã‚“ã§ã—ãŸ"
msgid "ProjectsDropdown|This feature requires browser localStorage support"
-msgstr ""
+msgstr "ã“ã®æ©Ÿèƒ½ã«ã¯ãƒ–ラウザー㫠localStorage サãƒãƒ¼ãƒˆãŒå¿…è¦ã§ã™"
msgid "PrometheusAlerts|Add alert"
msgstr ""
@@ -8864,7 +10512,7 @@ msgid "PrometheusService|Time-series monitoring service"
msgstr "時系列監視サービス"
msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
-msgstr ""
+msgstr "手動設定を有効ã«ã™ã‚‹ãŸã‚ã«ã¯ã€ã‚ãªãŸã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¼ã‹ã‚‰ Prometheus をアンインストールã—ã¾ã™"
msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
msgstr "クラスター㫠Prometheus をインストールã™ã‚‹ã«ã¯ã€ä»¥ä¸‹ã®æ‰‹å‹•è¨­å®šã‚’無効ã«ã—ã¦ãã ã•ã„"
@@ -8884,6 +10532,15 @@ msgstr "グループマイルストーンã«æ˜‡æ ¼"
msgid "Promote to group label"
msgstr "グループラベルã¸æ˜‡æ ¼"
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr "次回ã‹ã‚‰ã¯ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã—ãªã„"
@@ -8900,38 +10557,50 @@ msgid "Prompt users to upload SSH keys"
msgstr ""
msgid "Protected"
+msgstr "ä¿è­·ã•ã‚Œã¦ã„ã¾ã™"
+
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
msgstr ""
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
-msgstr ""
+msgstr "環境"
msgid "ProtectedEnvironment|Protect"
msgstr "ä¿è­·"
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr "環境をä¿è­·"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr "ä¿è­·ã•ã‚ŒãŸç’°å¢ƒ (%{protected_environments_count})"
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr "環境をé¸æŠž"
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr "ç¾åœ¨ä¿è­·ã•ã‚ŒãŸç’°å¢ƒã¯ã‚ã‚Šã¾ã›ã‚“。上ã®ãƒ•ã‚©ãƒ¼ãƒ ã§ç’°å¢ƒã‚’ä¿è­·ã—ã¦ãã ã•ã„。"
@@ -8980,9 +10649,15 @@ msgstr "プル"
msgid "Push"
msgstr "プッシュ"
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr "プッシュルール"
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9007,12 +10682,54 @@ msgstr "プッシュ済ã¿"
msgid "Pushes"
msgstr "プッシュ"
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr "クォーター"
msgid "Query"
msgstr "クエリ"
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr "クイックアクションã¯èª²é¡Œã®èª¬æ˜Žã¨ã‚³ãƒ¡ãƒ³ãƒˆæ¬„ã§ä½¿ç”¨ã§ãã¾ã™ã€‚"
@@ -9037,15 +10754,24 @@ msgstr "リアルタイム機能"
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr "最近ã®æ¤œç´¢"
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9059,22 +10785,43 @@ msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
+msgstr "æ­£è¦è¡¨ç¾ãƒ‘ターン"
+
+msgid "Register"
msgstr ""
msgid "Register / Sign In"
msgstr "登録 / サインイン"
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
+msgstr "U2F デãƒã‚¤ã‚¹ã‚’登録ã™ã‚‹"
+
+msgid "Register Universal Two-Factor (U2F) Device"
msgstr ""
msgid "Register and see your runners for this group."
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã® Runner ã®ç™»éŒ²ã¨ç¢ºèª"
msgid "Register and see your runners for this project."
+msgstr "ã“ã®ãƒ—ロジェクトã«ã‚ãªãŸã® Runner を登録ã—確èªã—ã¾ã™ã€‚"
+
+msgid "Register with two-factor app"
msgstr ""
msgid "Registration"
@@ -9101,6 +10848,9 @@ msgstr "関連ã™ã‚‹ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
msgid "Related Merged Requests"
msgstr "関連ã™ã‚‹ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr "関連ã™ã‚‹ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
@@ -9113,6 +10863,9 @@ msgstr ""
msgid "Remind later"
msgstr "後ã§é€šçŸ¥"
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr "削除"
@@ -9122,8 +10875,11 @@ msgstr "Runner を削除"
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr "æ–°ã—ã„コミットãŒã‚½ãƒ¼ã‚¹ãƒ–ランãƒã«ãƒ—ッシュã•ã‚ŒãŸã¨ãã«ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®ã™ã¹ã¦ã®æ‰¿èªã‚’削除ã™ã‚‹"
-msgid "Remove approver"
-msgstr "承èªè€…を削除"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
+msgstr ""
msgid "Remove approvers"
msgstr ""
@@ -9131,25 +10887,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr "ã‚¢ãƒã‚¿ãƒ¼ã‚’削除"
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr "優先度を削除"
msgid "Remove project"
msgstr "プロジェクトを削除"
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9164,6 +10932,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9174,13 +10960,13 @@ msgid "Removing the project will delete its repository and all related resources
msgstr ""
msgid "Rename"
-msgstr ""
+msgstr "åå‰ã‚’変更"
msgid "Rename file"
-msgstr ""
+msgstr "ファイルåを変更"
msgid "Rename folder"
-msgstr ""
+msgstr "フォルダåを変更"
msgid "Reopen epic"
msgstr ""
@@ -9194,6 +10980,9 @@ msgstr "èªè¨¼ã®ä¿®å¾©"
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr "コメントã«è¿”ä¿¡"
@@ -9203,29 +10992,32 @@ msgstr ""
msgid "Repo by URL"
msgstr "リãƒã‚¸ãƒˆãƒª URL"
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
msgstr "レãƒãƒ¼ãƒˆ"
msgid "Reports|%{failedString} and %{resolvedString}"
-msgstr ""
+msgstr "%{failedString} 㨠%{resolvedString}"
msgid "Reports|Actions"
-msgstr ""
+msgstr "アクション"
msgid "Reports|Class"
+msgstr "クラス"
+
+msgid "Reports|Classname"
msgstr ""
msgid "Reports|Confidence"
msgstr ""
msgid "Reports|Execution time"
-msgstr ""
+msgstr "実行時間"
msgid "Reports|Failure"
-msgstr ""
+msgstr "失敗"
msgid "Reports|Metrics reports are loading"
msgstr ""
@@ -9243,7 +11035,7 @@ msgid "Reports|Severity"
msgstr ""
msgid "Reports|System output"
-msgstr ""
+msgstr "システム出力"
msgid "Reports|Test summary"
msgstr ""
@@ -9255,13 +11047,7 @@ msgid "Reports|Test summary results are being parsed"
msgstr ""
msgid "Reports|Vulnerability"
-msgstr ""
-
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
+msgstr "脆弱性"
msgid "Reports|no changed test results"
msgstr ""
@@ -9273,7 +11059,7 @@ msgid "Repository Settings"
msgstr ""
msgid "Repository URL"
-msgstr ""
+msgstr "リãƒã‚¸ãƒˆãƒª URL"
msgid "Repository check was triggered."
msgstr ""
@@ -9317,13 +11103,22 @@ msgstr "GitLab ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹éš›ã«ã€ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒåˆ©ç”¨è¦
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
msgid "Requires approval."
msgid_plural "Requires %d more approvals."
-msgstr[0] ""
+msgstr[0] "もㆠ%d 件ã®æ‰¿èªãŒå¿…è¦ã§ã™ã€‚"
+
+msgid "Resend confirmation email"
+msgstr ""
msgid "Resend invite"
msgstr "招待をå†é€ä¿¡"
@@ -9356,7 +11151,7 @@ msgid "Resolve discussion"
msgstr "検討を解決"
msgid "Resolved"
-msgstr ""
+msgstr "解決済ã¿"
msgid "Resolved 1 discussion."
msgstr ""
@@ -9364,9 +11159,18 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
-msgid "Response"
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
msgstr ""
+msgid "Response"
+msgstr "レスãƒãƒ³ã‚¹"
+
msgid "Response didn't include `service_desk_address`"
msgstr ""
@@ -9374,19 +11178,19 @@ msgid "Response metrics (AWS ELB)"
msgstr ""
msgid "Response metrics (Custom)"
-msgstr ""
+msgstr "レスãƒãƒ³ã‚¹ メトリクス(カスタム)"
msgid "Response metrics (HA Proxy)"
-msgstr ""
+msgstr "レスãƒãƒ³ã‚¹ãƒ¡ãƒˆãƒªã‚¯ã‚¹ (HA Proxy)"
msgid "Response metrics (NGINX Ingress VTS)"
-msgstr ""
+msgstr "レスãƒãƒ³ã‚¹ãƒ¡ãƒˆãƒªã‚¯ã‚¹ (NGINX Ingress VTS)"
msgid "Response metrics (NGINX Ingress)"
msgstr ""
msgid "Response metrics (NGINX)"
-msgstr ""
+msgstr "レスãƒãƒ³ã‚¹ãƒ¡ãƒˆãƒªã‚¯ã‚¹ (NGINX)"
msgid "Restart Terminal"
msgstr "ターミナルをå†èµ·å‹•"
@@ -9406,6 +11210,9 @@ msgstr "ジョブをå†è©¦è¡Œã—ã¦ãã ã•ã„"
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr "検証をå†è©¦è¡Œã—ã¦ãã ã•ã„"
@@ -9426,7 +11233,7 @@ msgid "Review"
msgstr "レビュー"
msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
-msgstr ""
+msgstr "ã‚ãªãŸã® ID プロãƒã‚¤ãƒ€ãƒ¼ã®ã‚µãƒ¼ãƒ“スプロãƒã‚¤ãƒ€ãƒ¼ã‚’構æˆã™ã‚‹ãŸã‚ã®ãƒ—ロセスを確èªã—ã¾ã™ã€‚ ã“ã®ä¾‹ã§ã¯ã€GitLab ã¯ã€Œã‚µãƒ¼ãƒ“スプロãƒã‚¤ãƒ€ãƒ¼ã€ã¾ãŸã¯ã€Œè¨¼æ˜Žæ›¸åˆ©ç”¨è€…ã€ã€‚"
msgid "Reviewing"
msgstr "レビュー中"
@@ -9443,6 +11250,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr "ロードマップ"
@@ -9501,10 +11314,10 @@ msgid "Runners currently online: %{active_runners_count}"
msgstr "ç¾åœ¨ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ã®Runner: %{active_runners_count}"
msgid "Runners page"
-msgstr ""
+msgstr "Runner ã®ãƒšãƒ¼ã‚¸"
msgid "Runners page."
-msgstr ""
+msgstr "Runner ã®ãƒšãƒ¼ã‚¸ã€‚"
msgid "Runners|You have used all your shared Runners pipeline minutes."
msgstr ""
@@ -9513,7 +11326,7 @@ msgid "Running"
msgstr "稼åƒä¸­"
msgid "Running…"
-msgstr ""
+msgstr "実行中…"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
@@ -9527,6 +11340,9 @@ msgstr "%{group_name} 用㮠SAML SSO"
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr "SSH éµ"
@@ -9536,6 +11352,9 @@ msgstr ""
msgid "SSH host keys"
msgstr "SSH ホストキー"
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr "SSH 公開éµ"
@@ -9543,7 +11362,7 @@ msgid "SSL Verification"
msgstr "SSL ã®æ¤œè¨¼"
msgid "Saturday"
-msgstr ""
+msgstr "土曜日"
msgid "Save"
msgstr "ä¿å­˜"
@@ -9551,6 +11370,9 @@ msgstr "ä¿å­˜"
msgid "Save Changes"
msgstr "変更をä¿å­˜"
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr "アプリケーションã®ä¿å­˜"
@@ -9563,6 +11385,9 @@ msgstr ""
msgid "Save comment"
msgstr "コメントをä¿å­˜"
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "パイプラインスケジュールをä¿å­˜"
@@ -9612,7 +11437,7 @@ msgid "Search"
msgstr "検索"
msgid "Search an environment spec"
-msgstr ""
+msgstr "環境スペックを検索"
msgid "Search branches"
msgstr "ブランãƒã‚’検索"
@@ -9623,9 +11448,21 @@ msgstr "ブランãƒã¾ãŸã¯ã‚¿ã‚°ã‚’検索"
msgid "Search files"
msgstr "ファイルã®æ¤œç´¢"
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr "ユーザーを検索"
+
msgid "Search for projects, issues, etc."
msgstr "プロジェクトや課題ãªã©ã‚’検索ã™ã‚‹ã€‚"
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr "グループを検索"
@@ -9647,11 +11484,14 @@ msgstr "プロジェクトを検索"
msgid "Search projects"
msgstr "プロジェクトを検索"
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr "ユーザーを検索"
msgid "Search users or groups"
-msgstr ""
+msgstr "ユーザーã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—を検索"
msgid "Search your projects"
msgstr "プロジェクトを検索"
@@ -9672,7 +11512,7 @@ msgid "SearchAutocomplete|Merge requests assigned to me"
msgstr ""
msgid "SearchAutocomplete|in all GitLab"
-msgstr ""
+msgstr "å…¨ã¦ã® GitLab 中ã§"
msgid "SearchAutocomplete|in this group"
msgstr ""
@@ -9714,7 +11554,7 @@ msgid "Security Reports|Create issue"
msgstr ""
msgid "Security Reports|Dismiss vulnerability"
-msgstr ""
+msgstr "脆弱性を無視ã™ã‚‹"
msgid "Security Reports|Learn more about setting up your dashboard"
msgstr ""
@@ -9722,48 +11562,57 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
msgid "Security Reports|There was an error creating the merge request."
-msgstr ""
+msgstr "マージリクエストã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Security Reports|There was an error dismissing the vulnerability."
msgstr ""
msgid "Security Reports|There was an error reverting the dismissal."
-msgstr ""
+msgstr "無視ã®å–り消ã—中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "Security Reports|Undo dismiss"
-msgstr ""
+msgstr "å…ƒã«æˆ»ã™"
msgid "Security Reports|We've found no vulnerabilities for your group"
-msgstr ""
+msgstr "ã‚ãªãŸã®ã‚°ãƒ«ãƒ¼ãƒ—ã«è„†å¼±æ€§ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ"
msgid "Security Reports|While it's rare to have no vulnerabilities for your group, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "Security dashboard"
-msgstr ""
+msgstr "セキュリティダッシュボード"
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
-msgid "See metrics"
+msgid "SecurityDashboard|Project"
msgstr ""
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
+msgid "See metrics"
+msgstr "メトリクスをå‚ç…§"
+
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
@@ -9773,6 +11622,12 @@ msgstr "é¸æŠž"
msgid "Select Archive Format"
msgstr "アーカイブã®ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã‚’é¸æŠž"
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9786,10 +11641,10 @@ msgid "Select a project to read Insights configuration file"
msgstr ""
msgid "Select a repository"
-msgstr ""
+msgstr "リãƒã‚¸ãƒˆãƒªã‚’é¸æŠž"
msgid "Select a template repository"
-msgstr ""
+msgstr "テンプレートリãƒã‚¸ãƒˆãƒªã‚’é¸æŠž"
msgid "Select a timezone"
msgstr "タイムゾーンをé¸æŠž"
@@ -9800,9 +11655,12 @@ msgstr "既存㮠Kubernetes クラスターをé¸æŠžã™ã‚‹ã‹ã€æ–°ã—ã„ã‚‚ã®
msgid "Select branch/tag"
msgstr "ブランãƒãƒ»ã‚¿ã‚°é¸æŠž"
-msgid "Select members to invite"
+msgid "Select group or project"
msgstr ""
+msgid "Select members to invite"
+msgstr "招待ã™ã‚‹ãƒ¡ãƒ³ãƒãƒ¼ã‚’é¸æŠž"
+
msgid "Select project"
msgstr "プロジェクトã®é¸æŠž"
@@ -9834,19 +11692,22 @@ msgid "Selecting a GitLab user will add a link to the GitLab user in the descrip
msgstr "GitLab ユーザーをé¸æŠžã™ã‚‹ã¨ã€GitLab ユーザーã¸ã®ãƒªãƒ³ã‚¯ãŒèª²é¡Œã‚„コメントã®èª¬æ˜Žã«è¿½åŠ ã•ã‚Œã¾ã™ (例:\"By <a href=\"#\">@johnsmith</a>\")。ã¾ãŸã€ã“れらã®èª²é¡Œã‚„コメントをé¸æŠžã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã«é–¢é€£ä»˜ã‘や割り当ã¦ãŒã§ãã¾ã™ã€‚"
msgid "Send an email notification to Developers."
+msgstr "開発者ã«ãƒ¡ãƒ¼ãƒ«é€šçŸ¥ã‚’é€ä¿¡ã™ã‚‹"
+
+msgid "Send confirmation email"
msgstr ""
msgid "Send email"
msgstr "メールをé€ä¿¡"
msgid "Send report"
-msgstr ""
+msgstr "レãƒãƒ¼ãƒˆã‚’é€ä¿¡"
msgid "Send usage data"
msgstr ""
msgid "Sentry API URL"
-msgstr ""
+msgstr "Sentry API URL"
msgid "Sep"
msgstr "9月"
@@ -9912,9 +11773,12 @@ msgid "Serverless|Learn more about Serverless"
msgstr ""
msgid "Serverless|No functions available"
-msgstr ""
+msgstr "利用å¯èƒ½ãªæ©Ÿèƒ½ã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr "ç¾åœ¨ Knative ã‹ã‚‰å…¥æ‰‹å¯èƒ½ãªæ©Ÿèƒ½ãƒ‡ãƒ¼ã‚¿ã¯ã‚ã‚Šã¾ã›ã‚“。ã“ã‚Œã¯ã„ãã¤ã‹ç†ç”±ãŒè€ƒãˆã‚‰ã‚Œã¾ã™:"
+
+msgid "Service"
msgstr ""
msgid "Service Desk"
@@ -9947,21 +11811,24 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr "デフォルトを設定ã—ã€å¯è¦–性レベルを制é™ã—ã¾ã™ã€‚インãƒãƒ¼ãƒˆã‚½ãƒ¼ã‚¹ã¨ git アクセスプロトコルを設定ã—ã¾ã™ã€‚"
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr "インスタンス全体レベルã®ãƒ†ãƒ³ãƒ—レートリãƒã‚¸ãƒˆãƒªã‚’設定ã—ã¾ã™ã€‚"
msgid "Set max session time for web terminal."
msgstr "ウェブターミナルã®æœ€å¤§ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚¿ã‚¤ãƒ ã‚’設定ã™ã‚‹ã€‚"
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
+msgid "Set new password"
+msgstr "æ–°ã—ã„パスワードを設定"
+
msgid "Set notification email for abuse reports."
msgstr "迷惑行為レãƒãƒ¼ãƒˆã®é€šçŸ¥ãƒ¡ãƒ¼ãƒ«ã‚’設定ã™ã‚‹ã€‚"
-msgid "Set number of approvers required before open merge requests can be merged"
-msgstr ""
-
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr "ユーザーãŒã‚µã‚¤ãƒ³ã‚¤ãƒ³ã™ã‚‹ãŸã‚ã®è¦ä»¶ã‚’設定ã—ã¾ã™ã€‚å¿…é ˆã®äºŒè¦ç´ èªè¨¼ã‚’有効ã«ã—ã¾ã™ã€‚"
@@ -9977,6 +11844,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr "CI/CD を設定"
@@ -9993,11 +11863,14 @@ msgid "Set up new U2F device"
msgstr ""
msgid "Set up new password"
-msgstr ""
+msgstr "æ–°ã—ã„パスワードを設定"
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr "ウェイトを設定"
+
msgid "SetPasswordToCloneLink|set a password"
msgstr "パスワードを設定"
@@ -10005,19 +11878,19 @@ msgid "SetStatusModal|Add status emoji"
msgstr ""
msgid "SetStatusModal|Clear status"
-msgstr ""
+msgstr "ステータスをåˆæœŸåŒ–"
msgid "SetStatusModal|Edit status"
-msgstr ""
+msgstr "ステータスを編集"
msgid "SetStatusModal|Remove status"
-msgstr ""
+msgstr "ステータスを削除"
msgid "SetStatusModal|Set a status"
-msgstr ""
+msgstr "ステータスを設定"
msgid "SetStatusModal|Set status"
-msgstr ""
+msgstr "ステータスを設定"
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
@@ -10025,6 +11898,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr "設定"
@@ -10038,7 +11923,10 @@ msgid "Shared Runners"
msgstr "共有 Runner"
msgid "Shared projects"
-msgstr ""
+msgstr "共有プロジェクト"
+
+msgid "Shared runners help link"
+msgstr "共有Runnerã®ãƒ˜ãƒ«ãƒ—リンク"
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10052,26 +11940,32 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr "シャーロックトランザクション"
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr "ã™ã¹ã¦ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティを表示"
+msgid "Show archived projects"
+msgstr "アーカイブã—ãŸãƒ—ロジェクトを表示"
+
+msgid "Show archived projects only"
+msgstr "アーカイブã—ãŸãƒ—ロジェクトã®ã¿ã‚’表示"
+
msgid "Show command"
msgstr "コマンドを表示"
msgid "Show comments only"
-msgstr ""
+msgstr "コメントã®ã¿è¡¨ç¤º"
msgid "Show complete raw log"
msgstr "完全ãªç”Ÿãƒ­ã‚°ã‚’表示ã™ã‚‹"
msgid "Show file browser"
-msgstr ""
+msgstr "ファイルブラウザを表示"
msgid "Show latest version"
-msgstr ""
-
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
+msgstr "最新ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’表示"
msgid "Show parent pages"
msgstr "親ページを表示"
@@ -10080,7 +11974,7 @@ msgid "Show parent subgroups"
msgstr "親ã®ã‚µãƒ–グループを表示"
msgid "Show whitespace changes"
-msgstr ""
+msgstr "空白 (éžè¡¨ç¤ºæ–‡å­—) ã®å¤‰æ›´ã‚’表示ã™ã‚‹"
msgid "Showing %d event"
msgid_plural "Showing %d events"
@@ -10111,7 +12005,7 @@ msgid "Sign in to \"%{group_name}\""
msgstr ""
msgid "Sign in using smart card"
-msgstr ""
+msgstr "スマートカードを使ã£ã¦ã‚µã‚¤ãƒ³ã‚¤ãƒ³"
msgid "Sign in via 2FA code"
msgstr ""
@@ -10120,17 +12014,35 @@ msgid "Sign in with Single Sign-On"
msgstr "シングルサインオンã§ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã™ã‚‹"
msgid "Sign in with smart card"
-msgstr ""
+msgstr "スマートカードã§ã‚µã‚¤ãƒ³ã‚¤ãƒ³"
msgid "Sign out"
msgstr "サインアウト"
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr "サインインã®åˆ¶é™"
msgid "Sign-up restrictions"
msgstr "サインアップã®åˆ¶é™"
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10138,6 +12050,9 @@ msgid "Signing in using your %{label} account without a pre-existing GitLab acco
msgstr ""
msgid "Similar issues"
+msgstr "é¡žä¼¼ã®èª²é¡Œ"
+
+msgid "Single or combined queries"
msgstr ""
msgid "Size"
@@ -10147,6 +12062,9 @@ msgid "Size and domain settings for static websites"
msgstr "é™çš„ãªã‚¦ã‚§ãƒ–サイトã®ã‚µã‚¤ã‚ºã¨ãƒ‰ãƒ¡ã‚¤ãƒ³ã®è¨­å®š"
msgid "Size limit per repository (MB)"
+msgstr "リãƒã‚¸ãƒˆãƒªæ¯Žã®ã‚µã‚¤ã‚ºåˆ¶é™ (MB)"
+
+msgid "Skip this for now"
msgstr ""
msgid "Slack application"
@@ -10162,7 +12080,7 @@ msgid "Smartcard"
msgstr "スマートカード"
msgid "Smartcard authentication failed: client certificate header is missing."
-msgstr ""
+msgstr "スマートカードèªè¨¼ã«å¤±æ•—:クライアント証明書ヘッダーãŒã‚ã‚Šã¾ã›ã‚“。"
msgid "Snippet Contents"
msgstr "スニペットã®å†…容"
@@ -10174,16 +12092,16 @@ msgid "SnippetsEmptyState|Explore public snippets"
msgstr ""
msgid "SnippetsEmptyState|New snippet"
-msgstr ""
+msgstr "æ–°ã—ã„スニペット"
msgid "SnippetsEmptyState|No snippets found"
-msgstr ""
+msgstr "スニペットãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
msgid "SnippetsEmptyState|Snippets are small pieces of code or notes that you want to keep."
msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
-msgstr ""
+msgstr "表示ã™ã‚‹ã‚¹ãƒ‹ãƒšãƒƒãƒˆã¯ã‚ã‚Šã¾ã›ã‚“。"
msgid "SnippetsEmptyState|They can be either public or private."
msgstr ""
@@ -10204,10 +12122,10 @@ msgid "Something went wrong on our end."
msgstr "å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Something went wrong on our end. Please try again!"
-msgstr ""
+msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã—ã°ã‚‰ã経ã£ã¦ã‹ã‚‰ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ã¿ã¦ãã ã•ã„。"
msgid "Something went wrong on our end. Please try again."
-msgstr ""
+msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã—ã°ã‚‰ã経ã£ã¦ã‹ã‚‰ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ã¿ã¦ãã ã•ã„。"
msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr "課題ã®å…¬é–‹ç¯„囲ã®å¤‰æ›´ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -10218,6 +12136,9 @@ msgstr "%{issuableDisplayName} をロック状態ã«ã™ã‚‹ã®ã«å¤±æ•—ã—ã¾ã—ã
msgid "Something went wrong when toggling the button"
msgstr "ボタンã®åˆ‡ã‚Šæ›¿ãˆä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10231,11 +12152,14 @@ msgid "Something went wrong while fetching %{listType} list"
msgstr "%{listType} ã®ãƒªã‚¹ãƒˆå–得中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "Something went wrong while fetching comments. Please try again."
-msgstr ""
+msgstr "コメントã®å–得中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。"
msgid "Something went wrong while fetching group member contributions"
msgstr "グループメンãƒãƒ¼ã®è²¢çŒ®åº¦ã‚’å–得中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10260,7 +12184,7 @@ msgstr "ã“ã®æ¤œè¨Žã‚’解決ã—ã¦ã„ã‚‹ã¨ãã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10272,6 +12196,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr "å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚å†è©¦è¡Œã—ã¦ãã ã•ã„。"
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr "申ã—訳ã‚ã‚Šã¾ã›ã‚“ã€æ¤œç´¢ã«ä¸€è‡´ã™ã‚‹ã‚¨ãƒ”ックã¯ã‚ã‚Šã¾ã›ã‚“"
@@ -10279,7 +12206,7 @@ msgid "Sorry, no projects matched your search"
msgstr ""
msgid "Sorry, your filter produced no results"
-msgstr ""
+msgstr "申ã—訳ã‚ã‚Šã¾ã›ã‚“。ã‚ãªãŸãŒæŒ‡å®šã—ãŸãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã§ã¯è©²å½“ã™ã‚‹çµæžœãŒã‚ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "Sort by"
msgstr "並ã¹æ›¿ãˆ"
@@ -10332,6 +12259,9 @@ msgstr "人気順"
msgid "SortOptions|Less weight"
msgstr "ウェイトãŒå°ã•ã„é †"
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10386,6 +12316,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr "最近ã®ã‚µã‚¤ãƒ³ã‚¤ãƒ³é †"
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10411,7 +12347,7 @@ msgid "Source is not available"
msgstr "ソースã¯åˆ©ç”¨ã§ãã¾ã›ã‚“"
msgid "Source project cannot be found."
-msgstr ""
+msgstr "ソースプロジェクトãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。"
msgid "Spam Logs"
msgstr "スパム ログ"
@@ -10458,6 +12394,9 @@ msgstr "ステージ済㿠%{type}"
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr "優先ラベルã«ã™ã‚‹ã«ã¯ã€ãƒ©ãƒ™ãƒ«ã«ã‚¹ã‚¿ãƒ¼ã‚’付ã‘ã¾ã™ã€‚ドラッグã—ã¦ã€å„ªå…ˆé †ä½ã‚’並ã¹æ›¿ãˆã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr "スターを付ã‘ã‚‹"
@@ -10477,11 +12416,14 @@ msgid "StarredProjectsEmptyState|You don't have starred projects yet."
msgstr ""
msgid "Stars"
-msgstr ""
+msgstr "スター"
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10501,7 +12443,7 @@ msgid "Start cleanup"
msgstr ""
msgid "Start date"
-msgstr ""
+msgstr "開始日"
msgid "Start discussion"
msgstr ""
@@ -10512,6 +12454,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "Runner ã‚’èµ·å‹•!"
@@ -10528,7 +12476,7 @@ msgid "Started asynchronous removal of all repository check states."
msgstr ""
msgid "Starting..."
-msgstr ""
+msgstr "開始中..."
msgid "Starts %{startsIn}"
msgstr ""
@@ -10543,7 +12491,7 @@ msgid "Status"
msgstr "状態"
msgid "Status:"
-msgstr ""
+msgstr "ステータス:"
msgid "Stop Terminal"
msgstr "ターミナルをåœæ­¢"
@@ -10572,12 +12520,18 @@ msgstr "ストレージ"
msgid "Storage:"
msgstr "ストレージ:"
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr "サブグループ"
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr "スパムã¨ã—ã¦å ±å‘Š"
@@ -10608,6 +12562,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10672,7 +12629,7 @@ msgid "SubscriptionTable|Trial start date"
msgstr ""
msgid "SubscriptionTable|Upgrade"
-msgstr ""
+msgstr "アップグレード"
msgid "SubscriptionTable|Usage"
msgstr ""
@@ -10680,6 +12637,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10704,6 +12664,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr "日曜日"
@@ -10716,6 +12739,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr "ブランãƒãƒ»ã‚¿ã‚°åˆ‡ã‚Šæ›¿ãˆ"
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr "åŒæœŸæƒ…å ±"
@@ -10735,7 +12764,7 @@ msgid "System default (%{default})"
msgstr ""
msgid "System header and footer"
-msgstr ""
+msgstr "システムヘッダーã¨ãƒ•ãƒƒã‚¿ãƒ¼"
msgid "System hook was successfully updated."
msgstr ""
@@ -10746,18 +12775,30 @@ msgstr "システムメトリクス(カスタム)"
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr "ã‚¿ã‚°"
msgid "Tag list:"
msgstr "タグ一覧:"
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr "ã‚¿ã‚°"
msgid "Tags feed"
msgstr "タグフィード"
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr "ã‚¿ã‚°:"
@@ -10839,6 +12880,9 @@ msgstr "ターゲットブランãƒ"
msgid "Team"
msgstr "ãƒãƒ¼ãƒ "
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr "テンプレート"
@@ -10851,6 +12895,9 @@ msgstr "ターミナル"
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "利用è¦ç´„ã¨ãƒ—ライãƒã‚·ãƒ¼ãƒãƒªã‚·ãƒ¼"
@@ -10866,6 +12913,33 @@ msgstr "テストカãƒãƒ¬ãƒƒã‚¸è§£æž"
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10903,6 +12977,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10918,6 +12995,9 @@ msgstr "コãƒã‚¯ã‚·ãƒ§ãƒ³ã¯ %{timeout} ã§ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã™ã€‚タイ
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -10975,9 +13055,18 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "課題ステージã§ã¯ã€èª²é¡ŒãŒç™»éŒ²ã•ã‚Œã¦ã‹ã‚‰ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚Œã‚‹ã‹ã€èª²é¡Œãƒœãƒ¼ãƒ‰ã®ãƒªã‚¹ãƒˆã«è¿½åŠ ã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã“ã®ãƒªã‚¹ãƒˆã«è¡¨ç¤ºã™ã‚‹ã«ã¯èª²é¡Œã‚’最åˆã«ä½œæˆã—ã¦ãã ã•ã„。"
-msgid "The maximum file size allowed is %{size}."
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr "ライセンスãŒå‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚ GitLab ã¯ä»¥å‰ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã«æˆ»ã‚Šã¾ã—ãŸã€‚"
+
+msgid "The license was removed. GitLab now no longer has a valid license."
msgstr ""
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
+msgid "The maximum file size allowed is %{size}."
+msgstr "許å¯ã•ã‚Œã‚‹æœ€å¤§ãƒ•ã‚¡ã‚¤ãƒ«ã‚µã‚¤ã‚ºã¯ %{size} ã§ã™ã€‚"
+
msgid "The maximum file size allowed is 200KB."
msgstr "許å¯ã•ã‚Œã‚‹æœ€å¤§ãƒ•ã‚¡ã‚¤ãƒ«ã‚µã‚¤ã‚ºã¯ 200KB ã§ã™ã€‚"
@@ -10993,6 +13082,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "秘密éµã®å¾©å·ã«å¿…è¦ã¨ãªã‚‹ãƒ‘スフレーズ。ã“ã‚Œã¯ã‚ªãƒ—ションã§ã€å€¤ã¯æš—å·åŒ–ã—ã¦ä¿å­˜ã•ã‚Œã¾ã™ã€‚"
@@ -11017,9 +13112,21 @@ msgstr "プロダクションステージã§ã¯ã€èª²é¡ŒãŒä½œæˆã•ã‚Œã¦ã‹ã‚‰
msgid "The project can be accessed by any logged in user."
msgstr "プロジェクトã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ãƒ¦ãƒ¼ã‚¶ãƒ¼ã§ã‚ã‚Œã°èª°ã§ã‚‚アクセスã§ãã¾ã™ã€‚"
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr "プロジェクトã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ãªã—ã«èª°ã§ã‚‚アクセスã§ãã¾ã™ã€‚"
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11029,6 +13136,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr "匿å化データコレクションã¯ç„¡åŠ¹ã§ã™ã€‚有効ã«ã—ãŸã¨ãã€GitLab ã¯ã€ã‚ãªãŸãŒè¨­å®šã—ãŸã‚ªãƒ–ジェクトストレージディレクトリã«ã‚¢ãƒƒãƒ—ロードã™ã‚‹ GitLab データベースã®åŒ¿å化ã—㟠CSV を生æˆã™ã‚‹ã‚¸ãƒ§ãƒ–ã‚’ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã§å®Ÿè¡Œã—ã¾ã™ã€‚"
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11038,6 +13148,9 @@ msgstr "ã“ã®ãƒ—ロジェクトã«ãƒªãƒã‚¸ãƒˆãƒªã¯ã‚ã‚Šã¾ã›ã‚“。"
msgid "The repository for this project is empty"
msgstr "ã“ã®ãƒ—ロジェクトã«ãƒªãƒã‚¸ãƒˆãƒªã¯ã‚ã‚Šã¾ã›ã‚“"
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr "リãƒã‚¸ãƒˆãƒªã«ã¯ã€<code>http://</code>〠<code>https://</code> ã¾ãŸã¯ <code>git://</code>ã§æŽ¥ç¶šã§ããªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。"
@@ -11077,6 +13190,9 @@ msgstr "テスティングステージã§ã¯ã€GitLab CI ãŒé–¢é€£ã™ã‚‹ãƒžãƒ¼ã‚
msgid "The time taken by each data entry gathered by that stage."
msgstr "ã“ã®ã‚¹ãƒ†ãƒ¼ã‚¸ã«åŽé›†ã•ã‚ŒãŸãƒ‡ãƒ¼ã‚¿æ¯Žã®æ™‚é–“"
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11098,13 +13214,28 @@ msgstr "ユーザーマップã¯ã€ã‚ãªãŸã®ãƒ—ロジェクトã«å‚加ã—ãŸ
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr "ユーザーマップã¯ã€ã‚ãªãŸã®ãƒ—ロジェクトã«å‚加ã—㟠FogBugz ユーザーã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¨ãƒ¦ãƒ¼ã‚¶ãƒ¼åã‚’ GitLab ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹æ™‚ã«ãƒžãƒƒãƒ”ングã—ã¾ã™ã€‚ã“れを変更ã™ã‚‹ã«ã¯ã€ä»¥ä¸‹ã®è¡¨ã«å…¥åŠ›ã—ã¾ã™ã€‚"
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "得られãŸä¸€é€£ã®ãƒ‡ãƒ¼ã‚¿ã‚’å°ã•ã„é †ã«ä¸¦ã¹ãŸã¨ãã«ä¸­å¤®ã«ä½ç½®ã™ã‚‹å€¤ã€‚例ãˆã°ã€3, 5, 9 ã®ä¸­å¤®å€¤ã¯ 5。3, 5, 7, 8 ã®ä¸­å¤®å€¤ã¯ (5+7)/2 = 6。"
-msgid "There are no approvers"
-msgstr "承èªè€…ã¯ã„ã¾ã›ã‚“"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
+msgstr ""
msgid "There are no archived projects yet"
+msgstr "アーカイブã•ã‚ŒãŸãƒ—ロジェクトã¯ã‚ã‚Šã¾ã›ã‚“"
+
+msgid "There are no charts configured for this page"
msgstr ""
msgid "There are no closed issues"
@@ -11140,9 +13271,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11158,6 +13304,12 @@ msgstr "ユーザーã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティカレンダーã®èª­ã¿è¾¼ã¿ä¸­ã«
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11176,6 +13328,9 @@ msgstr "ラベルã®è³¼èª­ã™ã‚‹ã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "There was an error when unsubscribing from this label."
msgstr "ラベルã®è³¼èª­è§£é™¤ã™ã‚‹ã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11188,6 +13343,9 @@ msgstr "%{link}を使用ã—ã¦ãれらを管ç†ã§ãã¾ã™ã€‚"
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11200,18 +13358,30 @@ msgstr "ã“ã® GitLab インスタンスã¯ã¾ã å…±æœ‰ Runner ã‚’æä¾›ã—ã¦ã
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr "ã“ã®ã‚¢ãƒ—リケーション㯠%{link_to_owner} ã«ã‚ˆã£ã¦ä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr "編集を開始ã—ã¦ã‹ã‚‰ãƒ–ランãƒãŒæ›´æ–°ã•ã‚Œã¦ã„ã¾ã™ã€‚æ–°ã—ã„ブランãƒã‚’作æˆã—ã¾ã™ã‹ï¼Ÿ"
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11236,6 +13406,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr "ã“ã®å·®åˆ†ã¯æŠ˜ã‚ŠãŸãŸã¾ã‚Œã¦ã„ã¾ã™ã€‚"
@@ -11248,6 +13424,9 @@ msgstr "ディレクトリ"
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11257,10 +13436,19 @@ msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—"
msgid "This group does not provide any group Runners yet."
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã¯ã¾ã ã‚°ãƒ«ãƒ¼ãƒ— Runner ã‚’æä¾›ã—ã¦ã„ã¾ã›ã‚“。"
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr "ã“ã‚Œã¯éžå…¬é–‹ã®èª²é¡Œã§ã™ã€‚"
msgid "This is a delayed job to run in %{remainingTime}"
+msgstr "ã“れ㯠%{remainingTime} ã«å®Ÿè¡Œã•ã‚Œã‚‹é…延ジョブã§ã™"
+
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
msgstr ""
msgid "This is the author's first Merge Request to this project."
@@ -11269,12 +13457,12 @@ msgstr "ã“ã®ãƒ—ロジェクトã«å¯¾ã™ã‚‹ã€ä½œæˆè€…ã®æœ€åˆã®ãƒžãƒ¼ã‚¸ãƒª
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
+msgid "This is your current session"
+msgstr ""
+
msgid "This issue is confidential"
msgstr "ã“ã®èª²é¡Œã¯éžå…¬é–‹è¨­å®šã§ã™"
-msgid "This issue is confidential and locked."
-msgstr "ã“ã®èª²é¡Œã¯éžå…¬é–‹ã§ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™"
-
msgid "This issue is locked."
msgstr "ã“ã®èª²é¡Œã¯ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™ã€‚"
@@ -11327,7 +13515,7 @@ msgid "This job is stuck because you don't have any active runners online with a
msgstr ""
msgid "This job is stuck because you don't have any active runners that can run this job."
-msgstr ""
+msgstr "ã“ã®ã‚¸ãƒ§ãƒ–を実行ã§ãるアクティブ㪠Runner ãŒãªã„ãŸã‚ã€ã“ã®ã‚¸ãƒ§ãƒ–ã¯åœæ­¢ã—ã¦ã„ã¾ã™ã€‚"
msgid "This job is the most recent deployment to %{link}."
msgstr ""
@@ -11336,7 +13524,7 @@ msgid "This job requires a manual action"
msgstr "ã“ã®ã‚¸ãƒ§ãƒ–ã¯æ‰‹å‹•ã«ã‚ˆã‚‹å®Ÿè¡Œã‚’求ã‚ã¦ã„ã¾ã™"
msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
-msgstr ""
+msgstr "ã“ã®ã‚¸ãƒ§ãƒ–ã¯ã‚¿ã‚¤ãƒžãƒ¼çµ‚了後ã«è‡ªå‹•çš„ã«å®Ÿè¡Œã•ã‚Œã¾ã™ã€‚多ãã®å ´åˆæœ¬ç•ªç’°å¢ƒã¸ã®æ®µéšŽçš„ãªãƒ­ãƒ¼ãƒ«ã‚¢ã‚¦ãƒˆãƒ‡ãƒ—ロイã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚スケジュールã•ã‚Œã¦ã„ãªã„ã¨ãã¯æ‰‹å‹•ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã«å¤‰æ›ã•ã‚Œã¾ã™ã€‚"
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "空リãƒã‚¸ãƒˆãƒªã‚’作æˆã¾ãŸã¯æ—¢å­˜ãƒªãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆã‚’ã—ãªã‘ã‚Œã°ã€ã‚³ãƒ¼ãƒ‰ã®ãƒ—ッシュã¯ã§ãã¾ã›ã‚“。"
@@ -11344,12 +13532,6 @@ msgstr "空リãƒã‚¸ãƒˆãƒªã‚’作æˆã¾ãŸã¯æ—¢å­˜ãƒªãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼
msgid "This merge request is locked."
msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™ã€‚"
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11393,7 +13575,7 @@ msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
msgid "This setting can be overridden in each project."
-msgstr ""
+msgstr "ã“ã®è¨­å®šã¯ã€å„プロジェクトã§ä¸Šæ›¸ãã§ãã¾ã™ã€‚"
msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
msgstr ""
@@ -11414,7 +13596,7 @@ msgid "This user will be the author of all events in the activity feed that are
msgstr ""
msgid "This will redirect you to an external sign in page."
-msgstr ""
+msgstr "外部ã®ã‚µã‚¤ãƒ³ã‚¤ãƒ³ãƒšãƒ¼ã‚¸ã«ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã—ã¾ã™ã€‚"
msgid "This will remove the fork relationship to source project"
msgstr ""
@@ -11422,6 +13604,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr "ã“ã“ã«ãƒªã‚¹ãƒˆã‚¢ãƒƒãƒ—ã•ã‚Œã¦ã„ã‚‹ã“れらã®ãƒ¡ãƒ¼ãƒ«ã¯è‡ªå‹•çš„ã«èª²é¡Œã«ãªã‚Šã¾ã™ã€‚(メールã®ã‚„ã‚Šå–ã‚Šã¯èª²é¡Œã®ã‚³ãƒ¡ãƒ³ãƒˆã«ãªã‚Šã¾ã™ï¼‰"
+msgid "Thursday"
+msgstr "木曜日"
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr "課題ãŒè¨ˆç”»ã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“"
@@ -11604,9 +13792,12 @@ msgstr "ヒント:"
msgid "Title"
msgstr "タイトル"
-msgid "Titles and Filenames"
+msgid "Title:"
msgstr ""
+msgid "Titles and Filenames"
+msgstr "タイトルã¨ãƒ•ã‚¡ã‚¤ãƒ«å"
+
msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
msgstr ""
@@ -11619,6 +13810,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr "SSH キーを追加ã™ã‚‹ã«ã¯ã€%{generate_link_start}キーを生æˆã™ã‚‹%{link_end} ã¾ãŸã¯%{existing_link_start}既存ã®ã‚­ãƒ¼ã‚’使用ã™ã‚‹%{link_end}ã®ã©ã¡ã‚‰ã‹ãŒå¿…è¦ã§ã™ã€‚"
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr "GitHub リãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶šã™ã‚‹ãŸã‚ã« %{personal_access_token_link} を使用ã§ãã¾ã™ã€‚個人用アクセストークンを作æˆã™ã‚‹ã«ã¯<code>リãƒã‚¸ãƒˆãƒª</code> スコープをé¸æŠžã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚ŠæŽ¥ç¶šã§ãる公開・éžå…¬é–‹ãƒªãƒã‚¸ãƒˆãƒªã®ä¸€è¦§ã‚’表示ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -11659,10 +13853,10 @@ msgid "To import an SVN repository, check out %{svn_link}."
msgstr "SVN リãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ã€%{svn_link} ã‚’ã”確èªãã ã•ã„。"
msgid "To keep this project going, create a new issue"
-msgstr ""
+msgstr "ã“ã®ãƒ—ロジェクトを継続ã™ã‚‹ãŸã‚ã«ã€æ–°ã—ã„課題を作æˆã—ã¦ãã ã•ã„"
msgid "To keep this project going, create a new merge request"
-msgstr ""
+msgstr "ã“ã®ãƒ—ロジェクトを継続ã™ã‚‹ã«ã¯ã€æ–°ã—ã„マージリクエストを作æˆã—ã¦ãã ã•ã„"
msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
msgstr ""
@@ -11685,6 +13879,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr "Azureã€Oktaã€Oneloginã€Ping Identyã€ã¾ãŸã¯ã‚«ã‚¹ã‚¿ãƒ  SAML 2.0 プロãƒã‚¤ãƒ€ãƒ¼ãªã©ã® ID プロãƒã‚¤ãƒ€ãƒ¼ã‚’利用ã—ã¦ã€ã‚ãªãŸã®ã‚°ãƒ«ãƒ¼ãƒ—ã® SAML èªè¨¼ã‚’設定ã™ã‚‹ã«ã¯:"
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr "ジョブを開始ã™ã‚‹ãŸã‚ã€ã‚°ãƒ«ãƒ¼ãƒ—ã« Runner を追加ã§ãã¾ã™"
@@ -11721,6 +13918,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr "サイドãƒãƒ¼ã‚’切り替ãˆ"
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11733,9 +13933,15 @@ msgstr "コミットリストを切り替ãˆ"
msgid "Toggle discussion"
msgstr "検討ã®è¡¨ç¤ºãƒ»éžè¡¨ç¤ºã‚’切り替ãˆã‚‹"
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "サイドãƒãƒ¼ã‚’切り替ãˆ"
@@ -11745,6 +13951,9 @@ msgstr "切り替ãˆçŠ¶æ…‹:オフ"
msgid "ToggleButton|Toggle Status: ON"
msgstr "切り替ãˆçŠ¶æ…‹:オン"
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr "トークン"
@@ -11787,6 +13996,42 @@ msgstr "クイックアクションã§ä½œæ¥­æ™‚間を記録"
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr "データベースã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“。"
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr "プロジェクトを移動ã§ãã¾ã›ã‚“"
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr "プロジェクトã®æ–°ã—ã„åå‰ç©ºé–“ã‚’é¸æŠžã—ã¦ãã ã•ã„。"
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr "移動先ã®åå‰ç©ºé–“ã«ã€åŒã˜åå‰ã¾ãŸã¯åŒã˜ãƒ‘スをæŒã¤ãƒ—ロジェクトãŒæ—¢ã«å­˜åœ¨ã—ã¾ã™"
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11794,7 +14039,7 @@ msgid "Trending"
msgstr "トレンド分æž"
msgid "Trigger pipelines for mirror updates"
-msgstr ""
+msgstr "ミラー更新ã®ãŸã‚ã®ã€ãƒ‘イプライントリガー"
msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
msgstr ""
@@ -11806,10 +14051,10 @@ msgid "Trigger this manual action"
msgstr "ã“ã®æ‰‹å‹•ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã‚’トリガーã™ã‚‹"
msgid "Trigger token:"
-msgstr ""
+msgstr "トリガートークン:"
msgid "Trigger variables:"
-msgstr ""
+msgstr "トリガー変数:"
msgid "Trigger was created successfully."
msgstr ""
@@ -11821,7 +14066,7 @@ msgid "Trigger was successfully updated."
msgstr ""
msgid "Triggerer"
-msgstr ""
+msgstr "トリガー"
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr "トリガーã¯ã€ç‰¹å®šã®ãƒ–ランãƒã¾ãŸã¯ã‚¿ã‚°ã‚’ API 呼ã³å‡ºã—ã§å¼·åˆ¶çš„ã«å†æ§‹ç¯‰ã•ã›ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã“れらã®ãƒˆãƒ¼ã‚¯ãƒ³ã¯ã€ãƒ—ロジェクトã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚„プロジェクトã®ã‚¢ã‚¯ã‚»ã‚¹æ¨©ãªã©ã€é–¢é€£ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’å½è£…ã—ã¾ã™ã€‚"
@@ -11836,44 +14081,77 @@ msgid "Try again?"
msgstr "å†è©¦è¡Œã—ã¾ã™ã‹ï¼Ÿ"
msgid "Try all GitLab has to offer for 30 days."
+msgstr "30日間ã§GitLabãŒæä¾›ã™ã‚‹ã™ã¹ã¦ã®æ©Ÿèƒ½ã‚’試ã—ã¦ã¿ã¦ãã ã•ã„。"
+
+msgid "Try to fork again"
msgstr ""
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr "ç«æ›œæ—¥"
+
msgid "Turn on Service Desk"
msgstr "サービスデスクを有効ã«ã™ã‚‹"
msgid "Twitter"
msgstr "Twitter"
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
msgid "Two-factor authentication"
-msgstr ""
+msgstr "2è¦ç´ èªè¨¼"
msgid "Type"
msgstr "タイプ"
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr "URL"
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr "差分を読ã¿è¾¼ã‚€ã“ã¨ãŒã§ãã¾ã›ã‚“。%{button_try_again}"
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "\"%{reason}\"ã®ãŸã‚ SAML ã§ã‚°ãƒ«ãƒ¼ãƒ—ã«ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã§ãã¾ã›ã‚“"
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11892,23 +14170,38 @@ msgstr ""
msgid "Unknown"
msgstr "ä¸æ˜Ž"
-msgid "Unlimited"
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
msgstr ""
+msgid "Unlimited"
+msgstr "無制é™"
+
msgid "Unlock"
msgstr "アンロック"
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr "%{issuableDisplayName} ã®ãƒ­ãƒƒã‚¯ã‚’解除ã—ã¾ã™ã‹ï¼Ÿ <strong>全員</strong>ãŒã‚³ãƒ¡ãƒ³ãƒˆã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚"
msgid "Unlocked"
msgstr "アンロック済ã¿"
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr "検討を未解決ã«ã™ã‚‹"
msgid "Unschedule job"
-msgstr ""
+msgstr "ジョブã®ã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«ã‚’解除"
msgid "Unstage"
msgstr ""
@@ -11959,7 +14252,7 @@ msgid "Update approvers"
msgstr ""
msgid "Update failed"
-msgstr ""
+msgstr "更新失敗"
msgid "Update now"
msgstr "今ã™ãæ›´æ–°"
@@ -11973,6 +14266,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -11989,10 +14294,10 @@ msgid "Upgrade your plan"
msgstr ""
msgid "Upgrade your plan to activate Advanced Global Search."
-msgstr ""
+msgstr "高度ãªã‚°ãƒ­ãƒ¼ãƒãƒ«æ¤œç´¢ã‚’有効ã«ã™ã‚‹ãŸã‚ã«ãƒ—ランをアップグレードã—ã¾ã™ã€‚"
msgid "Upgrade your plan to activate Contribution Analytics."
-msgstr ""
+msgstr "貢献分æžã‚’有効ã«ã™ã‚‹ãŸã‚ã«ã€ãƒ—ランをアップグレードã—ã¾ã™ã€‚"
msgid "Upgrade your plan to activate Group Webhooks."
msgstr "グループ ウェブフックを有効ã«ã™ã‚‹ãŸã‚ã«ã€ãƒ—ランをアップグレード"
@@ -12024,20 +14329,26 @@ msgstr ""
msgid "Upload file"
msgstr "ファイルをアップロード"
-msgid "Upload object map"
+msgid "Upload file does not exist"
msgstr ""
+msgid "Upload object map"
+msgstr "オブジェクトマップをアップロード"
+
msgid "UploadLink|click to upload"
msgstr "クリックã—ã¦ã‚¢ãƒƒãƒ—ロード"
msgid "Uploaded on"
msgstr ""
-msgid "Uploads"
+msgid "Uploading changes to terminal"
msgstr ""
+msgid "Uploads"
+msgstr "アップロード"
+
msgid "Upstream"
-msgstr ""
+msgstr "Upstream"
msgid "Upvotes"
msgstr "ã„ã„ã­"
@@ -12051,6 +14362,54 @@ msgstr ""
msgid "Usage statistics"
msgstr "使用状æ³ã®çµ±è¨ˆ"
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr "パイプライン"
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr "無制é™"
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12060,6 +14419,12 @@ msgstr "ローカルテスト㫠<code>%{native_redirect_uri}</code> を使用"
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "サービスデスクを使用ã—ã¦ã€GitLab 内ã®ãƒ¡ãƒ¼ãƒ«ã§ãƒ¦ãƒ¼ã‚¶ã¨æŽ¥ç¶šï¼ˆä¾‹ï¼šé¡§å®¢ã‚µãƒãƒ¼ãƒˆï¼‰"
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr "グループマイルストーンを使用ã—ã¦ã€åŒã˜ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³å†…ã®è¤‡æ•°ã®ãƒ—ロジェクトã®èª²é¡Œã‚’管ç†ã—ã¾ã™ã€‚"
@@ -12117,9 +14482,12 @@ msgstr ""
msgid "User map"
msgstr "ユーザーマップ"
-msgid "User settings"
+msgid "User pipeline minutes were successfully reset."
msgstr ""
+msgid "User settings"
+msgstr "ユーザー設定"
+
msgid "User was successfully created."
msgstr ""
@@ -12132,9 +14500,144 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
-msgid "UserProfile|Activity"
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
msgstr ""
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr "アクティビティ"
+
msgid "UserProfile|Already reported for abuse"
msgstr ""
@@ -12142,7 +14645,7 @@ msgid "UserProfile|Contributed projects"
msgstr ""
msgid "UserProfile|Edit profile"
-msgstr ""
+msgstr "プロフィールを編集"
msgid "UserProfile|Explore public groups to find projects to contribute to."
msgstr ""
@@ -12157,7 +14660,7 @@ msgid "UserProfile|Join or create a group to start contributing by commenting on
msgstr ""
msgid "UserProfile|Most Recent Activity"
-msgstr ""
+msgstr "最新ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティ"
msgid "UserProfile|No snippets found."
msgstr "スニペットãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。"
@@ -12207,6 +14710,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr "ユーザー"
@@ -12222,9 +14734,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12270,12 +14800,18 @@ msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³"
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr "ドキュメントã®è¡¨ç¤º"
+
msgid "View eligible approvers"
msgstr ""
@@ -12285,6 +14821,9 @@ msgstr ""
msgid "View file @ "
msgstr "ファイルを表示 @ "
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr "グループラベルを表示"
@@ -12294,6 +14833,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr "GitLab ã§è¡¨ç¤º"
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12321,6 +14863,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr "å¯è¦–性ã¨ã‚¢ã‚¯ã‚»ã‚¹åˆ¶å¾¡"
@@ -12348,9 +14893,36 @@ msgstr "パブリック"
msgid "VisibilityLevel|Unknown"
msgstr "ä¸æ˜Ž"
-msgid "Vulnerability Chart"
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
msgstr ""
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
+msgid "Vulnerability Chart"
+msgstr "脆弱性ãƒãƒ£ãƒ¼ãƒˆ"
+
msgid "Vulnerability List"
msgstr ""
@@ -12379,7 +14951,7 @@ msgid "Vulnerability|Links"
msgstr "リンク"
msgid "Vulnerability|Namespace"
-msgstr ""
+msgstr "åå‰ç©ºé–“"
msgid "Vulnerability|Project"
msgstr "プロジェクト"
@@ -12390,6 +14962,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "ã“ã®ãƒ‡ãƒ¼ã‚¿ã‚’å‚ç…§ã—ãŸã„ã§ã™ã‹ï¼Ÿã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã«ã¯ç®¡ç†è€…ã«å•ã„åˆã‚ã›ã¦ãã ã•ã„。"
@@ -12397,7 +14972,7 @@ msgid "We can't find an epic that matches what you are looking for."
msgstr ""
msgid "We can't find an issue that matches what you are looking for."
-msgstr ""
+msgstr "ã‚ãªãŸãŒæŽ¢ã—ã¦ã„ã‚‹æ¡ä»¶ã«åˆã†èª²é¡Œã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "We could not determine the path to remove the epic"
msgstr ""
@@ -12408,6 +14983,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "%{humanized_resource_name} ã«ã‚¹ãƒ‘ムãŒã‚ã‚‹å¯èƒ½æ€§ã‚’検出ã—ã¾ã—ãŸã€‚続行ã™ã‚‹ã«ã¯ reCAPTCHA を実行ã—ã¦ãã ã•ã„。"
@@ -12417,6 +14995,9 @@ msgstr "データä¸è¶³ã®ãŸã‚ã€ã“ã®ã‚¹ãƒ†ãƒ¼ã‚¸ã®è¡¨ç¤ºã¯ã§ãã¾ã›ã‚“
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "本人確èªã®ãŸã‚ã€ã‚ãªãŸãŒãƒ­ãƒœãƒƒãƒˆã§ãªã„ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。"
@@ -12438,6 +15019,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr "水曜日"
+
msgid "Weeks"
msgstr "週"
@@ -12447,15 +15031,18 @@ msgstr "ウェイト"
msgid "Weight %{weight}"
msgstr "ウェイト %{weight}"
+msgid "Welcome to the Guided GitLab Tour"
+msgstr ""
+
+msgid "Welcome to your Issue Board!"
+msgstr ""
+
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Runner ãŒãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã‚‹å ´åˆã€ä»–ã®ãƒ—ロジェクトã«å‰²ã‚Šå½“ã¦ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“"
msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr "有効ã«ã—ãŸå ´åˆã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒè¦ç´„ã«åŒæ„ã•ã‚Œã‚‹ã¾ã§ GitLab を使用ã§ãã¾ã›ã‚“。"
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr "URL を空白ã®ã¾ã¾ã«ã™ã‚‹ã¨ã€ãƒ—ロジェクト間ã®æ©Ÿèƒ½ã‚’無効ã«ã—ãŸã‚Šã€å¤–部èªè¨¼ãƒã‚§ãƒƒã‚¯ã‚’実行ã—ãŸã‚Šã›ãšã«åˆ†é¡žãƒ©ãƒ™ãƒ«ã‚’指定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -12466,9 +15053,12 @@ msgstr[0] ""
msgid "When:"
msgstr ""
-msgid "Who can see this group?"
+msgid "White helpers give contextual information."
msgstr ""
+msgid "Who can see this group?"
+msgstr "誰ãŒã“ã®ã‚°ãƒ«ãƒ¼ãƒ—を見れã¾ã™ã‹ï¼Ÿ"
+
msgid "Who will be able to see this group?"
msgstr ""
@@ -12646,6 +15236,9 @@ msgstr ""
msgid "Yes"
msgstr "ã¯ã„"
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr "ã¯ã„ã€è¿½åŠ ã—ã¾ã™"
@@ -12661,8 +15254,14 @@ msgstr "ã‚ãªãŸ"
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "%{group_name} グループを削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ 削除ã•ã‚ŒãŸã‚°ãƒ«ãƒ¼ãƒ—ã¯çµ¶å¯¾ã«å…ƒã«æˆ»ã›ã¾ã›ã‚“ï¼æœ¬å½“ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "%{project_full_name} プロジェクトを削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚削除ã•ã‚ŒãŸãƒ—ロジェクトã¯çµ¶å¯¾ã«å…ƒã«ã¯æˆ»ã›ã¾ã›ã‚“ï¼æœ¬å½“ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
@@ -12673,6 +15272,9 @@ msgstr "å…ƒã®ãƒ—ロジェクト (%{forked_from_project}) ã¨ã®ãƒªãƒ¬ãƒ¼ã‚·ãƒ§ã
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr "%{project_full_name} を別ã®ã‚ªãƒ¼ãƒŠãƒ¼ã«å§”è­²ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12688,6 +15290,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr "コマンドラインã‹ã‚‰ãƒ—ロジェクトを作æˆã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr "ラベルã«ã‚¹ã‚¿ãƒ¼ã‚’付ã‘ã¦å„ªå…ˆãƒ©ãƒ™ãƒ«ã«ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
@@ -12706,6 +15314,15 @@ msgstr "ã“れらã®ã‚°ãƒ«ãƒ¼ãƒ—ã¸ã®å‚加をリクエストã™ã‚‹ã“ã¨ã§ã€
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr "Kubernetes クラスター㫠Runner ã‚’ç°¡å˜ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã§ãã¾ã™ã€‚%{link_to_help_page}"
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr "矢å°ã‚­ãƒ¼ã‚’使用ã—ã¦ã‚°ãƒ©ãƒ•ã‚’移動ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -12725,17 +15342,23 @@ msgid "You can only merge once the items above are resolved"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
-msgstr ""
+msgstr "プロジェクトã¯è‡ªåˆ†ãŒç®¡ç†ã™ã‚‹åå‰ç©ºé–“ã«ã®ã¿è»¢é€ã§ãã¾ã™ã€‚"
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
-msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgid "You can specify notification level per group or per project."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr "%{linkStart} CI Lint %{linkEnd} ã§.gitlab-ci.ymlをテストã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -12761,6 +15384,9 @@ msgid "You could not take ownership of trigger."
msgstr ""
msgid "You do not have any subscriptions yet"
+msgstr "ã‚ãªãŸã«ã¯ã‚µãƒ–スクリプションãŒã‚ã‚Šã¾ã›ã‚“"
+
+msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
@@ -12769,6 +15395,12 @@ msgstr "Web ターミナルを実行ã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。プロジã‚
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr "LDAP グループã®åŒæœŸã®è¨­å®šã‚’上書ãã™ã‚‹ãŸã‚ã®é©åˆ‡ãªæ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。"
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr "アプリケーションãŒã‚ã‚Šã¾ã›ã‚“"
@@ -12778,6 +15410,12 @@ msgstr "承èªã•ã‚ŒãŸã‚¢ãƒ—リケーションãŒã‚ã‚Šã¾ã›ã‚“"
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12808,6 +15446,15 @@ msgstr "アカウントを登録ã™ã‚‹ã«ã¯ã€åˆ©ç”¨è¦ç´„ã¨ãƒ—ライãƒã‚·ãƒ¼
msgid "You must have maintainer access to force delete a lock"
msgstr "ロックを強制的ã«å‰Šé™¤ã™ã‚‹ã«ã¯ã€Maintainer ã®ã‚¢ã‚¯ã‚»ã‚¹æ¨©ãŒå¿…è¦ã§ã™"
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr "フォークã™ã‚‹å‰ã«ã€åå‰ç©ºé–“ã«ãƒ—ロジェクトを作æˆã™ã‚‹æ¨©é™ãŒå¿…è¦ã§ã™ã€‚"
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr "ファイルロック機能を有効ã«ã™ã‚‹ã«ã¯åˆ¥ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãŒå¿…è¦ã§ã™"
@@ -12820,6 +15467,9 @@ msgstr ""
msgid "You need permission."
msgstr "権é™ãŒå¿…è¦ã§ã™"
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12832,6 +15482,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12865,6 +15518,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "SSH éµã‚’プロフィールã«è¿½åŠ ã—ãªã„é™ã‚Šã€SSH 経由ã§ãƒ—ロジェクトã®ã‚³ãƒ¼ãƒ‰ã‚’プルã—ãŸã‚Šãƒ—ッシュã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。"
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr "有効ãªæ¯”較を行ã†ãŸã‚ã«ã¯ã€ç•°ãªã‚‹ãƒ–ランãƒåを使用ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -12886,27 +15542,51 @@ msgstr "ã“ã®ãƒ¡ãƒ¼ãƒ«ã¯ %{host} ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆå®›ã«é€ä¿¡ã•ã‚Œã¾ã—ãŸ
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr "ã“ã®ãƒ¡ãƒ¼ãƒ«ã¯ %{host} ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆå®›ã«é€ä¿¡ã•ã‚Œã¾ã—ãŸã€‚ %{manage_notifications_link}&middot;%{help_link}"
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr "YouTube"
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr "所属グループ"
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr "ã“ã®ãƒšãƒ¼ã‚¸ã® Kubernetes クラスター情報ã¯ç·¨é›†å¯èƒ½ã§ã™ãŒã€ç„¡åŠ¹ã«ã—ã¦å†è¨­å®šã™ã‚‹ã“ã¨ã‚’推奨ã—ã¾ã™"
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr "プロジェクト(デフォルト)"
msgid "Your Projects' Activity"
msgstr "プロジェクトã®æ´»å‹•"
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr "ã‚ãªãŸã®Todo"
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12920,7 +15600,7 @@ msgid "Your account uses dedicated credentials for the \"%{group_name}\" group a
msgstr ""
msgid "Your applications (%{size})"
-msgstr ""
+msgstr "アプリケーション(%{size})"
msgid "Your authorized applications"
msgstr "承èªã•ã‚ŒãŸã‚¢ãƒ—リケーション"
@@ -12940,8 +15620,11 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
-msgstr "ã“ã®ã‚³ãƒ¡ãƒ³ãƒˆã¯ä¸€èˆ¬ã«ã¯è¡¨ç¤ºã•ã‚Œã¾ã›ã‚“。"
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
+msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
msgstr ""
@@ -12958,6 +15641,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr "åå‰"
@@ -12991,14 +15677,17 @@ msgstr "å‰"
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
-msgstr "ãã®ä»–ã®ã‚‚ã®"
+msgid "already being used for another group or project milestone."
+msgstr ""
-msgid "at"
+msgid "already shared with this group"
msgstr ""
+msgid "among other things"
+msgstr "ãã®ä»–ã®ã‚‚ã®"
+
msgid "attach a new file"
-msgstr ""
+msgstr "æ–°ã—ã„ファイルを添付"
msgid "authored"
msgstr ""
@@ -13009,6 +15698,21 @@ msgstr "ブランãƒå"
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr "%{linkStartTag}コンテナスキャンã®è©³ç´°%{linkEndTag}"
@@ -13096,6 +15800,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13127,10 +15834,7 @@ msgid "ciReport|Create issue"
msgstr ""
msgid "ciReport|Create merge request"
-msgstr ""
-
-msgid "ciReport|Created %{eventType}"
-msgstr ""
+msgstr "マージリクエストを作æˆ"
msgid "ciReport|DAST"
msgstr "DAST"
@@ -13147,12 +15851,6 @@ msgstr "ä¾å­˜é–¢ä¿‚スキャン"
msgid "ciReport|Description"
msgstr "説明"
-msgid "ciReport|Dismiss vulnerability"
-msgstr "脆弱性を無視ã™ã‚‹"
-
-msgid "ciReport|Dismissed by"
-msgstr "次ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ç„¡è¦–ã•ã‚Œã¾ã—ãŸ"
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13269,9 +15967,6 @@ msgstr "ä¾å­˜é–¢ä¿‚スキャンレãƒãƒ¼ãƒˆã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™º
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr "無視ã®å–り消ã—中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr "%{name} ã‚’ %{version} ã‹ã‚‰ %{fixed} ã¸ã‚¢ãƒƒãƒ—グレードã—ã¦ãã ã•ã„。"
@@ -13288,12 +15983,12 @@ msgstr[0] ""
msgid "ciReport|View full report"
msgstr "レãƒãƒ¼ãƒˆå…¨ä½“を見る"
-msgid "ciReport|on pipeline"
-msgstr "パイプライン"
-
msgid "commented on %{link_to_project}"
msgstr ""
+msgid "commit %{commit_id}"
+msgstr ""
+
msgid "confidence|Confirmed"
msgstr ""
@@ -13301,22 +15996,22 @@ msgid "confidence|Experimental"
msgstr ""
msgid "confidence|High"
-msgstr ""
+msgstr "高"
msgid "confidence|Ignore"
-msgstr ""
+msgstr "無視"
msgid "confidence|Low"
-msgstr ""
+msgstr "低"
msgid "confidence|Medium"
-msgstr ""
+msgstr "中"
msgid "confidence|Undefined"
-msgstr ""
+msgstr "未定義"
msgid "confidence|Unknown"
-msgstr ""
+msgstr "ä¸æ˜Ž"
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr "ã‚ãªãŸã¯å…¬é–‹è¨­å®šã«å¤‰æ›´ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã“ã‚Œã¯<strong>ã™ã¹ã¦ã®äºº</strong> ãŒé–²è¦§å¯èƒ½ã«ãªã‚Šã€èª²é¡Œã«å¯¾ã—ã¦ã‚³ãƒ¡ãƒ³ãƒˆã‚’残ã™ã“ã¨ãŒã§ãるよã†ã«ãªã‚‹ã“ã¨ã‚’æ„味ã—ã¾ã™ã€‚"
@@ -13333,6 +16028,9 @@ msgstr "秘密éµã‚’読ã¿å–ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚パスフレ
msgid "customize"
msgstr "カスタマイズ"
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] "æ—¥"
@@ -13360,12 +16058,18 @@ msgid "draft"
msgid_plural "drafts"
msgstr[0] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr "有効"
-msgid "epic"
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
msgstr ""
+msgid "epic"
+msgstr "エピック"
+
msgid "error"
msgstr "エラー"
@@ -13375,6 +16079,12 @@ msgstr "エラー コード:"
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr "%{slash_command} コマンドã§è¦‹ç©æ™‚é–“ã‚’æ›´æ–°ã§ãã¾ã™ã€‚"
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13399,6 +16109,9 @@ msgstr ""
msgid "group"
msgstr "グループ"
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr "ã“ã“"
@@ -13421,12 +16134,18 @@ msgid "in project %{link_to_project}"
msgstr ""
msgid "index"
-msgstr ""
+msgstr "インデックス"
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] "インスタンスãŒå®Œäº†ã—ã¾ã—ãŸ"
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13434,6 +16153,9 @@ msgid "is invalid because there is upstream lock"
msgstr ""
msgid "is not a valid X509 certificate."
+msgstr "ã¯æœ‰åŠ¹ãª X509 証明書ã§ã¯ã‚ã‚Šã¾ã›ã‚“。"
+
+msgid "is not an email you own"
msgstr ""
msgid "is out of the hierarchy of the Group owning the template"
@@ -13454,9 +16176,12 @@ msgstr ""
msgid "it is too large"
msgstr ""
-msgid "latest"
+msgid "jigsaw is not defined"
msgstr ""
+msgid "latest"
+msgstr "最新"
+
msgid "latest deployment"
msgstr "最新ã®ãƒ‡ãƒ—ロイ"
@@ -13473,12 +16198,15 @@ msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "%{path_lock_user_name} ã«ã‚ˆã£ã¦ %{created_at} ã«ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™ã€‚"
msgid "manual"
-msgstr ""
+msgstr "マニュアル"
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] "マージリクエスト"
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13506,8 +16234,8 @@ msgstr "%{metricsLinkStart} メモリ %{metricsLinkEnd} 使用率㌠%{memoryFro
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "%{metricsLinkStart} メモリ %{metricsLinkEnd} 使用率㯠%{memoryFrom} MB㧠%{emphasisStart} 変化ãªã— %{emphasisEnd}"
-msgid "mrWidget|Add approval"
-msgstr "承èªã‚’追加"
+msgid "mrWidget|Added to the merge train by"
+msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "ターゲットブランãƒã«ãƒžãƒ¼ã‚¸ã§ãるメンãƒãƒ¼ã‹ã‚‰ã®ã‚³ãƒŸãƒƒãƒˆã‚’許å¯ã™ã‚‹"
@@ -13521,6 +16249,9 @@ msgstr "マージリクエストã®æ‰¿èªæƒ…報をå–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿ
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "承èªã‚’é€ä¿¡ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr "承èª"
@@ -13558,7 +16289,7 @@ msgid "mrWidget|Create an issue to resolve them later"
msgstr "ã‚ã¨ã§è§£æ±ºã™ã‚‹ãŸã‚ã«èª²é¡Œã‚’作æˆã™ã‚‹"
msgid "mrWidget|Delete source branch"
-msgstr ""
+msgstr "ソースブランãƒã‚’削除"
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "デプロイ統計ã¯ç¾åœ¨åˆ©ç”¨ã§ãã¾ã›ã‚“"
@@ -13573,6 +16304,9 @@ msgid "mrWidget|Failed to load deployment statistics"
msgstr "デプロイ統計ã®ãƒ­ãƒ¼ãƒ‰ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr "æ—©é€ã‚Šãƒžãƒ¼ã‚¸ã¯ã§ãã¾ã›ã‚“。ã“ã®è¦æ±‚をマージã™ã‚‹ã«ã¯ã€ã¾ãšãƒ­ãƒ¼ã‚«ãƒ«ã‚’ rebase ã—ã¾ã™ã€‚"
+
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
msgstr ""
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
@@ -13593,18 +16327,15 @@ msgstr "マージ"
msgid "mrWidget|Merge failed."
msgstr "マージã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
+msgstr ""
+
msgid "mrWidget|Merge locally"
msgstr "ローカルã§ãƒžãƒ¼ã‚¸"
-msgid "mrWidget|Merge request approved"
-msgstr "マージリクエストãŒæ‰¿èªã•ã‚Œã¾ã—ãŸ"
-
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr "マージ作業者"
@@ -13618,13 +16349,13 @@ msgid "mrWidget|Open in Web IDE"
msgstr "Web IDE ã§é–‹ã"
msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
-msgstr ""
+msgstr "パイプラインãŒãƒ–ロックã•ã‚Œã¾ã—ãŸã€‚ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®ãƒ‘イプラインã«ã¯ã€æ‰‹å‹•æ“作ãŒå¿…è¦ã§ã™"
msgid "mrWidget|Plain diff"
msgstr "プレーン差分"
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
-msgstr ""
+msgstr "自動マージã®æº–å‚™ãŒã§ãã¾ã—ãŸã€‚ã“ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’マージã™ã‚‹ã«ã¯ã€ã“ã®ãƒªãƒã‚¸ãƒˆãƒªã¸ã®æ›¸ãè¾¼ã¿æ¨©é™ã‚’æŒã¤äººã«ä¾é ¼ã—ã¾ã™"
msgid "mrWidget|Refresh"
msgstr "æ›´æ–°"
@@ -13635,25 +16366,17 @@ msgstr "ã™ãã«æ›´æ–°"
msgid "mrWidget|Refreshing now"
msgstr "更新中"
-msgid "mrWidget|Remove your approval"
-msgstr "承èªã‚’削除ã™ã‚‹"
+msgid "mrWidget|Remove from merge train"
+msgstr ""
msgid "mrWidget|Request to merge"
msgstr "マージをリクエスト"
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] "もㆠ%d 件ã®æ‰¿èªãŒå¿…è¦ã§ã™"
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] "もㆠ%d 件ã®æ‰¿èªãŒå¿…è¦ã§ã™"
-
msgid "mrWidget|Resolve conflicts"
msgstr "競åˆã‚’解決ã™ã‚‹"
msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
-msgstr ""
+msgstr "ã“れらã®ç«¶åˆã‚’解消ã™ã‚‹ã‹ã€ã¾ãŸã¯ã“ã®ãƒªãƒã‚¸ãƒˆãƒªã¸ã®æ›¸ãè¾¼ã¿ã‚¢ã‚¯ã‚»ã‚¹æ¨©ã‚’æŒã¤äººã«ãƒ­ãƒ¼ã‚«ãƒ«ã§ãƒžãƒ¼ã‚¸ã™ã‚‹ã‚ˆã†ä¾é ¼ã™ã‚‹"
msgid "mrWidget|Revert"
msgstr "リãƒãƒ¼ãƒˆ"
@@ -13716,7 +16439,7 @@ msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "ã“ã®ãƒ—ロジェクトã¯ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã•ã‚Œã¦ã„ã‚‹ãŸã‚ã€æ›¸ãè¾¼ã¿ã¯ç„¡åŠ¹ã§ã™ã€‚"
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
-msgstr ""
+msgstr "ã“ã®ãƒ—ロジェクトを直接編集ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。変更ã™ã‚‹ã«ã¯ãƒ•ã‚©ãƒ¼ã‚¯ã—ã¦ãã ã•ã„。"
msgid "mrWidget|You can delete the source branch now"
msgstr "ソースブランãƒã‚’削除ã§ãるよã†ã«ãªã‚Šã¾ã—ãŸ"
@@ -13733,17 +16456,32 @@ msgstr "コマンド ライン"
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr "パイプラインãŒæˆåŠŸã—ãŸã¨ãã¯è‡ªå‹•çš„ã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã™"
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr "æ–°è¦ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
+msgid "no contributions"
+msgstr "貢献ãªã—"
+
msgid "none"
-msgstr ""
+msgstr "ãªã—"
msgid "notification emails"
msgstr "メール通知"
@@ -13779,7 +16517,7 @@ msgid_plural "points"
msgstr[0] ""
msgid "private"
-msgstr ""
+msgstr "プライベート"
msgid "private key does not match certificate."
msgstr "秘密éµãŒè¨¼æ˜Žæ›¸ã¨ä¸€è‡´ã—ã¾ã›ã‚“。"
@@ -13792,10 +16530,10 @@ msgid_plural "projects"
msgstr[0] "プロジェクト"
msgid "quick actions"
-msgstr ""
+msgstr "クイックアクション"
msgid "register"
-msgstr ""
+msgstr "登録"
msgid "remaining"
msgstr "残り"
@@ -13810,7 +16548,7 @@ msgid "remove weight"
msgstr "ウェイトを削除"
msgid "rendered diff"
-msgstr ""
+msgstr "差分を表示"
msgid "reply"
msgid_plural "replies"
@@ -13823,7 +16561,7 @@ msgid "score"
msgstr "スコア"
msgid "security Reports|There was an error creating the merge request"
-msgstr ""
+msgstr "マージリクエストã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "severity|Critical"
msgstr ""
@@ -13846,7 +16584,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13855,21 +16593,33 @@ msgstr ""
msgid "sign in"
msgstr "サインイン"
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr "ソース"
msgid "source diff"
msgstr "ソース差分"
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} ã¯ç´¯è¨ˆçµŒéŽæ™‚é–“ã‚’æ›´æ–°ã—ã¾ã™"
msgid "started"
msgstr "開始"
-msgid "stuck"
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
msgstr ""
+msgid "stuck"
+msgstr "スタック"
+
msgid "success"
msgstr ""
@@ -13883,7 +16633,7 @@ msgid "this document"
msgstr "ã“ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆ"
msgid "to help your contributors communicate effectively!"
-msgstr ""
+msgstr "コントリビュータã®ã‚³ãƒŸãƒ¥ãƒ‹ã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã‚’効率化ã™ã‚‹ï¼"
msgid "triggered"
msgstr ""
@@ -13900,12 +16650,33 @@ msgstr "コードをデプロイã™ã‚‹ãŸã‚ã« Kubernetes クラスターを使
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr "GitLab ã§è¦‹ã‚‹"
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "%{additions} 件ã®è¿½åŠ ã¨ %{deletions} 件ã®å‰Šé™¤ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -13914,5 +16685,5 @@ msgid_plural "within %d minutes "
msgstr[0] "%d 分以内"
msgid "yaml invalid"
-msgstr ""
+msgstr "yaml ãŒç„¡åŠ¹ã§ã™"
diff --git a/locale/ka_GE/gitlab.po b/locale/ka_GE/gitlab.po
index 392e35c5b88..25d60cdf6d3 100644
--- a/locale/ka_GE/gitlab.po
+++ b/locale/ka_GE/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Georgian\n"
"Language: ka_GE\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ka\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:39\n"
+"PO-Revision-Date: 2019-06-14 10:26\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,37 +1459,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1856,6 +2161,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/ko/gitlab.po b/locale/ko/gitlab.po
index 75e53196f93..b36de3639cf 100644
--- a/locale/ko/gitlab.po
+++ b/locale/ko/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Korean\n"
"Language: ko_KR\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ko\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:29\n"
+"PO-Revision-Date: 2019-06-14 10:13\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr " ìƒíƒœ"
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -62,6 +59,10 @@ msgstr[0] "%d 커밋 behind"
msgid "%d commits"
msgstr "%dê°œì˜ ì»¤ë°‹"
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d 내보내기"
@@ -90,10 +91,18 @@ msgid "%d merge request"
msgid_plural "%d merge requests"
msgstr[0] "머지 리퀘스트(MR) %d개"
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d 측정치"
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] "%dê°œì˜ ìŠ¤í…Œì´ì§•ëœ 변경사항"
@@ -115,11 +124,8 @@ msgstr "%{authorsName}ì˜ í† ë¡ "
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_timeago} ì— %{commit_author_link} ë‹˜ì´ ì»¤ë°‹í•˜ì˜€ìŠµë‹ˆë‹¤."
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr "%{counter_storage} (%{counter_repositories} 저장소, %{counter_build_artifacts} 빌드 아티팩트, %{counter_lfs_objects} LFS)"
-
-msgid "%{count} %{alerts}"
-msgstr "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
+msgstr ""
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
@@ -148,6 +154,12 @@ msgid "%{count} pending comment"
msgid_plural "%{count} pending comments"
msgstr[0] "%{count}ê°œì˜ ëŒ€ê¸°ì¤‘ì¸ ëŒ“ê¸€ "
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr "%{filePath} ì‚­ì œë¨"
@@ -160,12 +172,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}그룹%{group_docs_link_end}ì„ ì‚¬ìš©í•˜ë©´ 여러 프로ì íŠ¸ë¥¼ 관리하고 ê³µë™ ìž‘ì—…ì„ ìˆ˜í–‰ í•  수 있습니다. 그룹 회ì›ì€ 모든 프로ì íŠ¸ì— 액세스 í•  수 있습니다."
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType}ì´ ì‚­ì œë©ë‹ˆë‹¤! 확실합니까?"
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -181,6 +205,12 @@ msgstr "%{lock_path} 경로는 GitLab User %{lock_user_id} ì— ì˜í•´ 잠겼습ë
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr "%{name} ì˜ ì•„ë°”íƒ€"
@@ -199,6 +229,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -227,6 +269,9 @@ msgstr[0] "%{text} %{files} 파ì¼"
msgid "%{text} is available"
msgstr "%{text} 사용 가능"
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr "%{title} 변경"
@@ -239,9 +284,28 @@ msgstr "GitLab Inc와 공유ë˜ëŠ” ì •ë³´ì— ëŒ€í•´ %{usage_ping_link_start}ë”
msgid "%{user_name} profile page"
msgstr "%{user_name} 프로필 페ì´ì§€"
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr "(외부 소스)"
@@ -266,6 +330,9 @@ msgstr "- Runner ê°€ ì¼ì‹œì •ì§€ ë˜ì–´ 새로운 ìž‘ì—…ì„ ë°›ì„ ìˆ˜ 없습ë‹
msgid "- show less"
msgstr "-ëœ ë³´ê¸°"
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] "%{count} %{type} ê°œì˜ ì¶”ê°€ ì •ë³´"
@@ -279,12 +346,12 @@ msgid_plural "%d Days"
msgstr[0] "%dì¼"
msgid "1 closed issue"
-msgid_plural "%d closed issues"
-msgstr[0] "%d ê°œì˜ ì´ìŠˆ closed"
+msgid_plural "%{issues} closed issues"
+msgstr[0] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
-msgstr[0] "%dê±´ì˜ ë¨¸ì§€ë¦¬í€˜ìŠ¤íŠ¸ 닫힘"
+msgid_plural "%{merge_requests} closed merge requests"
+msgstr[0] ""
msgid "1 day"
msgstr ""
@@ -294,16 +361,16 @@ msgid_plural "%d groups"
msgstr[0] "%d 그룹"
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
-msgstr[0] "%dê±´ì˜ ë¨¸ì§€ë¦¬í€˜ìŠ¤íŠ¸ 머지ë¨"
+msgid_plural "%{merge_requests} merged merge requests"
+msgstr[0] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
-msgstr[0] "%dê°œì˜ ì˜¤í”ˆëœ ì´ìŠˆ"
+msgid_plural "%{issues} open issues"
+msgstr[0] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
-msgstr[0] "%dê°œì˜ ì˜¤í”ˆëœ ë¨¸ì§€ 리퀘스트(MR)"
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] ""
msgid "1 pipeline"
msgid_plural "%d pipelines"
@@ -320,15 +387,27 @@ msgstr[0] "%dëª…ì˜ ì‚¬ìš©ìž"
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr "첫번째 기여!"
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr "2단계 ì¸ì¦(2FA)"
msgid "2FA enabled"
msgstr "2FA 사용"
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -338,6 +417,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr "403|ê¶Œí•œì„ ì–»ìœ¼ë ¤ë©´ GitLab 관리ìžì—게 문ì˜í•˜ì‹­ì‹œì˜¤."
@@ -368,6 +450,9 @@ msgstr "<code>\"johnsmith@example.com\": \"johnsm... @ example.com\"</code> ì€
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> ì€ ì›ëž˜ johnsmith@example.comì´ ìƒì„±í•œ 모든 ì´ìŠˆì™€ 주ì„ì— \"By <a href=\"#\">johnsmith@example.com</a>\"ì„ ì¶”ê°€í•©ë‹ˆë‹¤. 기본ì ìœ¼ë¡œ ì´ë©”ì¼ ì£¼ì†Œ ë˜ëŠ” ì‚¬ìš©ìž ì´ë¦„ì€ ê°€ë ¤ì ¸ 있어서 사용ìžì˜ ê°œì¸ì •ë³´ë¥¼ 보호합니다. ì „ì²´ ì „ìž ë©”ì¼ ì£¼ì†Œë¥¼ 표시하려면 ì´ ì˜µì…˜ì„ ì‚¬ìš©í•˜ì‹­ì‹œì˜¤."
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr "<strong>%{changedFilesLength}개가 스테ì´ì§•ë˜ì§€ 않았고, %{stagedFilesLength}개가 스테ì´ì§•</strong>ëœ ë³€ê²½ì‚¬í•­"
@@ -404,19 +489,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
+msgstr ""
+
msgid "A default branch cannot be chosen for an empty project."
msgstr "빈 프로ì íŠ¸ì—서는 기본 브랜치를 ì„ íƒí•  수 없습니다."
msgid "A deleted user"
msgstr "ì‚­ì œëœ ì‚¬ìš©ìž"
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr "GitLabì˜ ì‚¬ì´ë²„ í­ë ¥ ë°©ì§€íŒ€ì´ ìµœëŒ€í•œ 빨리 ê·€í•˜ì˜ ë¦¬í¬íŠ¸ë¥¼ 검토 í•  것 입니다."
-
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -446,6 +531,9 @@ msgstr "소스 ë¸Œëžœì¹˜ì— ëŒ€í•œ 쓰기 ê¶Œí•œì´ ìžˆëŠ” 사용ìžê°€ ì´ ì˜µì
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr "GitLabì— ëŒ€í•˜ì—¬"
@@ -491,12 +579,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr "%{classification_label} ì— ëŒ€í•œ 액세스가 허용ë˜ì§€ 않습니다."
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr "계정"
msgid "Account and limit"
msgstr "계정과 제한"
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -533,6 +633,9 @@ msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° 추가"
msgid "Add README"
msgstr "README 추가"
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -554,10 +657,16 @@ msgstr "í…Œì´ë¸” 추가"
msgid "Add a task list"
msgstr "ìž‘ì—… ëª©ë¡ ì¶”ê°€"
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "모든 ì´ë©”ì¼ì— í‘œì‹œë  í…스트를 추가합니다. %{character_limit} ìž ì œí•œì´ ìžˆìŠµë‹ˆë‹¤."
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -566,9 +675,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr "댓글 추가"
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -578,6 +693,9 @@ msgstr "ì´ë¯¸ì§€ 댓글 추가"
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr "ë¼ì´ì„ ìŠ¤ 추가"
@@ -590,9 +708,18 @@ msgstr "새 애플리케ì´ì…˜ 추가"
msgid "Add new directory"
msgstr "새 디렉토리 추가"
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr "ë°˜ì‘ ì¶”ê°€"
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr "프로ì íŠ¸ì— 추가"
@@ -605,22 +732,34 @@ msgstr "í•  ì¼ ì¶”ê°€"
msgid "Add user(s) to the group:"
msgstr "ê·¸ë£¹ì— ì‚¬ìš©ìž ì¶”ê°€:"
-msgid "Add users or groups who are allowed to approve every merge request"
-msgstr "모든 머지요청(MR) ì„ ìŠ¹ì¸í•  수 있는 ì‚¬ìš©ìž ë˜ëŠ” 그룹 추가"
-
msgid "Add users to group"
msgstr "ê·¸ë£¹ì— ì‚¬ìš©ìž ì¶”ê°€"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
+msgstr ""
+
msgid "Added at"
msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr "GitLab ì¸ìŠ¤í„´ìŠ¤ì— 새 애플리케ì´ì…˜ì„ 추가 í•  수 없습니다. ê¶Œí•œì„ ì–»ìœ¼ë ¤ë©´ GitLab 관리ìžì—게 문ì˜í•˜ì‹­ì‹œì˜¤."
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr "추가 í…스트"
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -632,6 +771,9 @@ msgstr "ê´€ë¦¬ìž ê°œìš”"
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr "%{username}ì„ ì˜êµ¬ì ìœ¼ë¡œ 삭제하려고 합니다. ì´ìŠˆ, 머지 리퀘스트(MR) ë° ì—°ê²°ëœ ê·¸ë£¹ì´ \"Ghost-user\"으로 변경ë©ë‹ˆë‹¤. ë°ì´í„° ì†ì‹¤ì„ 방지하기 위해 %{strong_start}차단 사용ìž%{strong_end} ê¸°ëŠ¥ì„ ì‚¬ìš©í•´ë³´ì„¸ìš”. %{strong_start}ì‚¬ìš©ìž ì‚­ì œ%{strong_end}ì‹œ ë˜ëŒë¦¬ê±°ë‚˜, 복구할 수 없습니다."
@@ -653,6 +795,9 @@ msgstr "ìž‘ì—… ì¤‘ì§€ì— ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤."
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "모든 ìž‘ì—…ì„ ì¤‘ì§€í•©ë‹ˆë‹¤. 현재 ì‹¤í–‰ì¤‘ì¸ ëª¨ë“  ìž‘ì—…ì´ ì¤‘ì§€ë©ë‹ˆë‹¤."
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr "%{projectName}프로ì íŠ¸, 저장소 ë° ë¬¸ì œ, 머지 리퀘스트(MR) ë“±ì„ í¬í•¨í•œ 모든 관련 리소스를 ì˜êµ¬ížˆ 삭제하려고합니다. 확ì¸í•˜ê³  %{strong_start}프로ì íŠ¸ ì‚­ì œ%{strong_end}를 누르면 실행 취소 ë˜ëŠ” 복구를 í•  수 없습니다."
@@ -767,6 +912,9 @@ msgstr "고급 설정"
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "알림"
@@ -783,15 +931,24 @@ msgstr ""
msgid "All changes are committed"
msgstr "모든 ë³€ê²½ì‚¬í•­ì´ ì»¤ë°‹ë˜ì—ˆìŠµë‹ˆë‹¤."
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "모든 ê¸°ëŠ¥ì€ ë¹„ì–´ìžˆëŠ” 프로ì íŠ¸, 템플릿, 가져올 ë•Œ 사용할 수 있지만 ë‚˜ì¤‘ì— í”„ë¡œì íŠ¸ 설정ì—ì„œ 비활성화 í•  수 있습니다."
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr "현재 마ì¼ìŠ¤í†¤ì— ê´€ë ¨ëœ ëª¨ë“  ì´ìŠˆë“¤ì´ 마ê°ë˜ì—ˆìŠµë‹ˆë‹¤. 현재 마ì¼ìŠ¤í†¤ì„ 마ê°í•  수 있습니다."
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -864,9 +1021,6 @@ msgstr "대신, %{personal_access_token_link} (ì„) 를 사용할 수 있습니ë
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr "사용ìžê°€ 다중 ì¸ì¦ì„ 강제로 구성해야 í•  ì‹œê°„ì„ ê±´ë„ˆ 뛸 수있는 기간 (시간)"
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr "ì–‘ì‹ì„ 제출하면 SSH 키가 ìžë™ìœ¼ë¡œ ìƒì„±ë©ë‹ˆë‹¤. ìžì„¸í•œ ë‚´ìš©ì€ ë¬¸ì„œë¥¼ 참조하십시오."
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr "%{link_to_client} ì´ë¼ëŠ” ì‘ìš© í”„ë¡œê·¸ëž¨ì´ GitLab ê³„ì •ì— ëŒ€í•œ 액세스를 요청하고 있습니다."
@@ -900,12 +1054,15 @@ msgstr "BLOB 미리보기 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred when toggling the notification subscription"
msgstr "알림 êµ¬ë… ì—¬ë¶€ 변경 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "ì´ìŠˆ ì¤‘ìš”ë„ ì—…ë°ì´íŠ¸ 중 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-msgid "An error occurred while adding approver"
-msgstr "승ì¸ìžë¥¼ ì¶”ê°€í•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
-
msgid "An error occurred while deleting the approvers group"
msgstr ""
@@ -927,21 +1084,36 @@ msgstr "기능 ê°•ì¡° 표시를 해제하는 ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr "마í¬ë‹¤ìš´ 미리보기를 가져 오는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while fetching pending comments"
msgstr "ëŒ“ê¸€ì„ ì—…ë°ì´íŠ¸í•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgid "An error occurred while fetching projects autocomplete."
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "사ì´ë“œë°” ë°ì´í„°ë¥¼ 가져오는 중 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-msgid "An error occurred while fetching stages."
-msgstr "스테ì´ì§€ë¥¼ 가져 오는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr "ìž‘ì—… 로그를 가져 오는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -957,6 +1129,9 @@ msgstr "파ì´í”„ë¼ì¸ì„ ë°˜ì˜í•˜ë˜ 중 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr "프로ì íŠ¸ë¥¼ 가져오는 ë™ì•ˆ 오류가 ë°œìƒ í–ˆìŠµë‹ˆë‹¤."
@@ -990,8 +1165,11 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr "ìš”ì²­ì„ ìƒì„±í•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-msgid "An error occurred while removing approver"
-msgstr "승ì¸ìžë¥¼ 삭제하는 중 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
+msgstr ""
msgid "An error occurred while removing epics."
msgstr ""
@@ -1044,6 +1222,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1101,9 +1282,15 @@ msgstr "Any"
msgid "Any Label"
msgstr "모든 ë¼ë²¨"
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr "외관"
@@ -1113,6 +1300,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr "어플리케ì´ì…˜"
@@ -1122,6 +1315,9 @@ msgstr "애플리케ì´ì…˜ ID"
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1140,6 +1336,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1177,12 +1385,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr "4ì›”"
@@ -1213,6 +1415,18 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
+msgid "Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr ""
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to delete this list?"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "ì´ íŒŒì´í”„ë¼ì¸ ìŠ¤ì¼€ì¥´ì„ ì‚­ì œ 하시겠습니까?"
@@ -1234,18 +1448,6 @@ msgstr "공개키를 재ìƒì„±í•˜ì‹œê² ìŠµë‹ˆê¹Œ? 미러ë§ì´ 다시 ë™ìž‘하ê
msgid "Are you sure you want to remove %{group_name}?"
msgstr "ì •ë§ë¡œ %{group_name}(ì„)를 ì‚­ì œ 하시겠습니까?"
-msgid "Are you sure you want to remove approver %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove approver %{name}?"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}?"
-msgstr ""
-
msgid "Are you sure you want to remove the attachment?"
msgstr ""
@@ -1261,6 +1463,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr "헬스 ì²´í¬ í† í°ì„ 초기화 하시겠습니까?"
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr "ì´ í™˜ê²½ì„ ì¤‘ë‹¨í•˜ê¸¸ ì›í•˜ë‚˜ìš”?"
@@ -1273,12 +1478,36 @@ msgstr ""
msgid "Are you sure?"
msgstr "확실합니까?"
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr "결과물 ID"
msgid "Artifacts"
msgstr "결과물"
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr "오름차순"
@@ -1291,6 +1520,9 @@ msgstr "문제 알림 ì†Œë¹„ìž ì„œë¹„ìŠ¤ URL"
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr "#FF0000ê³¼ ê°™ì´ ë§žì¶¤ ìƒ‰ìƒ ì§€ì •"
@@ -1306,6 +1538,12 @@ msgstr ""
msgid "Assign to"
msgstr "담당ìž"
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr "í• ë‹¹ëœ ì´ìŠˆ"
@@ -1336,6 +1574,13 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "드래그 &amp; 드롭 ë˜ëŠ” %{upload_link}"
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr "ê°ì‚¬ ì´ë²¤íŠ¸"
@@ -1423,13 +1668,22 @@ msgstr "ë” ì•Œì•„ë³´ê¸° %{link_to_documentation}"
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr "Auto DevOps 파ì´í”„ ë¼ì¸ì´ 활성화ë˜ì—ˆìœ¼ë©° 대체 CI 구성 파ì¼ì´ 없는 ê²½ìš°ì— ì‚¬ìš©ë©ë‹ˆë‹¤. %{more_information_link}"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
msgid "Automatically marked as default internal user"
msgstr "기본 내부 사용ìžë¡œ ìžë™ 표시"
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatically resolved"
+msgstr ""
+
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
msgstr ""
-msgid "Automatically resolved"
+msgid "Autosave|Note"
msgstr ""
msgid "Available"
@@ -1543,6 +1797,30 @@ msgstr "내 배지"
msgid "Badges|e.g. %{exampleUrl}"
msgstr "e.g. %{exampleUrl}"
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr "모든 보류 ì¤‘ì— ìžˆëŠ” 커맨트 ì‚­ì œ"
@@ -1645,12 +1923,29 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+
msgid "Blog"
msgstr "블로그"
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr "보드"
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "%{branchName} 브랜치는 ì´ í”„ë¡œì íŠ¸ ì €ìž¥ì†Œì— ì—†ìŠµë‹ˆë‹¤."
@@ -1666,6 +1961,9 @@ msgstr "해당 브랜치는 ì´ë¯¸ 사용중입니다"
msgid "Branch name"
msgstr "브랜치 ì´ë¦„"
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "브랜치 검색"
@@ -1816,6 +2114,21 @@ msgstr "íŒŒì¼ ì°¾ì•„ë³´ê¸°"
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1834,6 +2147,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "작성ìž"
@@ -1924,9 +2240,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr "ì´ ë¸Œëžœì¹˜ì—ì„œ HEAD ì»¤ë°‹ì„ ì°¾ì„ ìˆ˜ 없습니다."
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1948,9 +2270,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr "ì´ë¯¸ êµ¬ì„±ëœ Kubernetes í´ëŸ¬ìŠ¤í„°ëŠ” 수정할 수 없습니다"
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -1966,6 +2294,12 @@ msgstr ""
msgid "Change Weight"
msgstr "ì¤‘ìš”ë„ ë³€ê²½"
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -1978,6 +2312,15 @@ msgstr "템플릿 변경"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "ì´ ê°’ì— ë”°ë¼ GitLab UIì—ì„œ ì—…ë°ì´íŠ¸ë¥¼ 확ì¸í•˜ëŠ” 빈ë„ê°€ 달ë¼ì§‘니다."
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "브랜치ì—ì„œ Pick"
@@ -2002,6 +2345,12 @@ msgstr "변경 ì‚¬í•­ì€ <b>source</b> ë¦¬ë¹„ì „ì´ <b>target</b> ë¦¬ë¹„ì „ì— ë
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr "차트"
@@ -2029,6 +2378,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr "브랜치가 사용 가능한지 í™•ì¸ ì¤‘..."
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr "ì´ ì»¤ë°‹ì„ Cherry-pick"
@@ -2050,6 +2402,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr "템플릿 ì„ íƒ..."
@@ -2080,7 +2435,7 @@ msgstr "Ci/CD 파ì´í”„ë¼ì¸ì´ ì—°ê²°ë˜ê³  실행할 저장소를 ì„ íƒí•´ ì
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr "ì´ ì„¸ì»¨ë”리 ë…¸ë“œì— ì–´ë–¤ 샤드 (shards)를 ë™ê¸°í™” 할지 ì„ íƒí•˜ì„¸ìš”."
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2152,16 +2507,34 @@ msgstr "건너 뜀"
msgid "CiStatus|running"
msgstr "실행 중"
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr "입력 변수 키"
msgid "CiVariables|Input variable value"
msgstr "입력 변수 값"
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr "변수 행 제거"
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2215,9 +2588,18 @@ msgstr "검색 지우기"
msgid "Clear search input"
msgstr "검색 입력 지우기"
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr "아래 프로ì íŠ¸ 목ë¡ì—ì„œ <strong>프로ì íŠ¸ ì´ë¦„</strong>ì„ ëˆŒëŸ¬ 프로ì íŠ¸ 마ì¼ìŠ¤í†¤ì„ 봅니다."
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr "<strong>다운로드</strong> ë²„íŠ¼ì„ í´ë¦­í•˜ê³  다운로드가 완료 ë  ë•Œê¹Œì§€ 기다려 주세요."
@@ -2272,6 +2654,9 @@ msgstr "ì—픽 닫기"
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr "닫힘"
@@ -2290,7 +2675,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList}ê°€ Kubernetes í´ëŸ¬ìŠ¤í„°ì— 설치ë˜ì—ˆìŠµë‹ˆë‹¤"
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2308,12 +2699,24 @@ msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° ì—°ë™ ì¶”ê°€"
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr "ê·¸ë£¹ì— Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 추가하면 모든 프로ì íŠ¸ì—ì„œ í´ëŸ¬ìŠ¤í„°ê°€ ìžë™ìœ¼ë¡œ 공유ë©ë‹ˆë‹¤. ì‘ìš© í”„ë¡œê·¸ëž¨ì„ ê²€í† í•˜ê³  ì‘ìš© í”„ë¡œê·¸ëž¨ì„ ë°°í¬í•˜ê³  ë™ì¼í•œ í´ëŸ¬ìŠ¤í„°ë¥¼ 사용하는 모든 프로ì íŠ¸ì— 대한 파ì´í”„ ë¼ì¸ì„ 쉽게 실행할 수 있습니다."
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr "ê·¸ë£¹ì— ì—°ë™ì„ 하시면 모든 프로ì íŠ¸ì—ì„œ í´ëŸ¬ìŠ¤í„°ê°€ 공유ë©ë‹ˆë‹¤."
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° í†µí•©ì— ëŒ€í•œ 고급 옵션"
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2329,6 +2732,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr "애플리케ì´ì…˜"
@@ -2437,6 +2843,9 @@ msgstr "ClusterIntegration|GitLab Runner"
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Google Cloud Platform 프로ì íŠ¸"
@@ -2473,19 +2882,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr "설치"
-
-msgid "ClusterIntegration|Installed"
-msgstr "설치ë¨"
-
-msgid "ClusterIntegration|Installing"
-msgstr "설치중"
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2518,6 +2918,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2554,6 +2957,9 @@ msgstr "Kubernetesì— ëŒ€í•´ ìžì„¸ížˆ 알아보기."
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr "그룹 Kubernetes í´ëŸ¬ìŠ¤í„°ì— 대해 ìžì„¸ížˆ 알아보기."
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr "Let's Encrypt"
@@ -2563,9 +2969,6 @@ msgstr "머신 타입"
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 만들려면 %{link_to_requirements} ë§í¬ì—ì„œ ê³„ì •ì˜ í•„ìˆ˜ì‚¬í•­ì„ í™•ì¸í•˜ì„¸ìš”."
-msgid "ClusterIntegration|Manage"
-msgstr "관리"
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr "%{link_gke}ì— ë°©ë¬¸í•˜ì—¬ Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 관리하세요."
@@ -2629,7 +3032,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "설치 시작 요청 실패"
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2683,40 +3086,52 @@ msgstr "구글 Kubernetes ì—”ì§„ì— Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 만드는 ë™ì•ˆ
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "설치하는 ë™ì•ˆ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. %{title}"
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
-msgstr "%{link_to_container_project} 프로ì íŠ¸ì— Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 만들기 위해서는 ì´ ê³„ì •ì— ì•„ëž˜ì— ëª…ì‹œëœ ê¶Œí•œì´ í•„ìš”í•©ë‹ˆë‹¤"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
+msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
-msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° 토글"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
+msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr "%{link_to_container_project} 프로ì íŠ¸ì— Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 만들기 위해서는 ì´ ê³„ì •ì— ì•„ëž˜ì— ëª…ì‹œëœ ê¶Œí•œì´ í•„ìš”í•©ë‹ˆë‹¤"
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° 토글"
+
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2728,6 +3143,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "ì´ í”„ë¡œì íŠ¸ì— ì—°ê²°ëœ Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 통해 어플리케ì´ì…˜ì„ 리뷰, ë°°í¬í•  수 있고, 파ì´í”„ë¼ì¸ì„ 실행할 수 있습니다. ê·¸ 외ì—ë„ ë§Žì€ ì¼ì„ 훨씬 쉬운 방법으로 수행할 수 있습니다."
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2737,6 +3155,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "ë‹¹ì‹ ì˜ ê³„ì •ì€ %{link_to_kubernetes_engine} ì´ ìžˆì–´ì•¼ 합니다."
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr "Zone"
@@ -2788,9 +3209,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr "사ì´ë“œ ë°” 축소"
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr "코멘트"
@@ -2809,6 +3236,9 @@ msgstr "댓글 작성 ë° í† ë¡ ì„ í•´ê²°í•˜ì§€ ì•ŠìŒ"
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr "코멘트"
@@ -2927,6 +3357,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr "Gitaly 시간 제한 설정."
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr "ì¶”ì  êµ¬ì„±"
@@ -2954,9 +3387,15 @@ msgstr "사용ìžê°€ 새로운 ê³„ì •ì„ ë§Œë“œëŠ” ë°©ë²•ì„ ì„¤ì •í•©ë‹ˆë‹¤."
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr "ì—°ê²°"
@@ -2969,9 +3408,15 @@ msgstr "GitHub으로부터 저장소 연결"
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr "ë‹¹ì‹ ì˜ ì™¸ë¶€ 저장소를 연결하면 CI/CD 파ì´í”„ë¼ì¸ì´ 새로운 ì»¤ë°‹ì— ëŒ€í•´ 실행ë©ë‹ˆë‹¤. GitLab 프로ì íŠ¸ëŠ” CI/CD기능만 사용하여 ìƒì„±ë©ë‹ˆë‹¤."
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr "연결중..."
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3035,6 +3480,9 @@ msgstr "GitLabì— í†µí•© Docker 컨테ì´ë„ˆ 레지스트리를 ì´ìš©í•˜ë©´, ëª
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3080,6 +3528,9 @@ msgstr "머지 ì»¤ë°‹ì„ ì œì™¸í•œ %{branch_name}ì„ ì»¤ë°‹í•˜ì‹­ì‹œì˜¤. 6,000ê°
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr "잠시만 기다려주십시오, ì´ íŽ˜ì´ì§€ëŠ” 준비가 완료ë˜ë©´ ìžë™ìœ¼ë¡œ 새로고침ë©ë‹ˆë‹¤."
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3089,6 +3540,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr "ConvDev ì¸ë±ìŠ¤"
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3107,9 +3561,6 @@ msgstr "SSH í´ë¡  URL 복사"
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr "SSH 공개키를 í´ë¦½ë³´ë“œì— 복사하기"
-
msgid "Copy URL to clipboard"
msgstr "URLì„ í´ë¦½ë³´ë“œì— 복사"
@@ -3125,6 +3576,12 @@ msgstr "ì»¤ë°‹ì˜ SHA를 í´ë¦½ë³´ë“œë¡œ 복사합니다"
msgid "Copy file path to clipboard"
msgstr "íŒŒì¼ ê²½ë¡œë¥¼ í´ë¦½ë³´ë“œì— 복사"
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr "ë§í¬ 복사"
@@ -3134,6 +3591,9 @@ msgstr "ë ˆí¼ëŸ°ìŠ¤ë¥¼ í´ë¦½ë³´ë“œë¡œ 복사"
msgid "Copy secret to clipboard"
msgstr "í´ë¦½ë³´ë“œì— 비밀값 복사"
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr "í´ë¦½ë³´ë“œì— 복사"
@@ -3143,9 +3603,15 @@ msgstr "í´ë¦½ë³´ë“œì— í† í° ë³µì‚¬"
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3179,9 +3645,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr "새 브랜치 ìƒì„±"
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr "새 ì´ìŠˆ 만들기"
@@ -3254,6 +3729,12 @@ msgstr "새로운 프로ì íŠ¸ ë¼ë²¨"
msgid "Create your first page"
msgstr "첫 페ì´ì§€ 만들기"
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr "태그"
@@ -3269,12 +3750,27 @@ msgstr "ìƒì„± 위치"
msgid "Created by me"
msgstr "ë‚˜ì— ì˜í•´ ìƒì„±ë¨"
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr "ìƒì„±ì¼"
msgid "Created on:"
msgstr "ìƒì„±ì¼:"
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr "ì—픽 ìƒì„± 중"
@@ -3293,6 +3789,9 @@ msgstr ""
msgid "Current node"
msgstr "현재 노드"
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr "프로파ì¼"
@@ -3371,15 +3870,39 @@ msgstr "모든"
msgid "DashboardProjects|Personal"
msgstr "ê°œì¸"
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr "날짜 ì„ íƒ"
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr "디버그"
@@ -3416,6 +3939,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr "기본값: Google 코드 ì´ë©”ì¼ ì£¼ì†Œ ë˜ëŠ” ì‚¬ìš©ìž ì´ë¦„ì„ ì§ì ‘ 가져옵니다."
@@ -3467,6 +3993,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr "ì‚­ì œë¨"
@@ -3488,6 +4029,54 @@ msgstr ""
msgid "Deny"
msgstr "거부"
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "ë°°í¬"
@@ -3663,6 +4252,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3717,9 +4309,15 @@ msgstr "그룹 Runner 사용 중지"
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr "취소"
@@ -3741,6 +4339,12 @@ msgstr "초안 삭제"
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3771,18 +4375,42 @@ msgstr "머지 리퀘스트 프로모션 제거"
msgid "Dismiss trial promotion"
msgstr "í‰ê°€íŒ 프로모션 제거"
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr "Google Code ì´ë©”ì¼ ì£¼ì†Œì™€ 사용ìžëª…ì„ GitLab으로 가져오는 ë°©ë²•ì„ ì‚¬ìš©ìž ì •ì˜í•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr "ì¸ê¸°ìžˆëŠ” ID 제공 ì—…ì²´ì— ëŒ€í•œ 문서"
msgid "Domain"
msgstr "ë„ë©”ì¸"
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr "다시 표시하지 ì•ŠìŒ"
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr "완료"
@@ -3795,25 +4423,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3855,6 +4477,9 @@ msgstr "ë¼ë²¨ 편집"
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "파ì´í”„ë¼ì¸ 스케줄 편집 %{id}"
@@ -3891,6 +4516,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr "Elasticsearch"
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr "Elasticsearch ì—°ë™, Elasticsearch AWS IAM"
@@ -3909,6 +4540,9 @@ msgstr ""
msgid "Email patch"
msgstr "패치를 ì´ë©”ì¼ë¡œ 보냄"
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3933,9 +4567,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr "ì´ë©”ì¼"
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr "임베드"
@@ -3960,6 +4624,9 @@ msgstr "ì´ ê·¸ë£¹ì— SAML ì¸ì¦ 사용"
msgid "Enable Sentry for error reporting and logging."
msgstr "Sentry를 사용해 오류 보고와 ë¡œê¹…ì„ í™œì„±í™”í•©ë‹ˆë””."
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr "InfluxDB 매트릭스를 활성화하고 구성합니다."
@@ -3996,9 +4663,6 @@ msgstr "reCAPTCHA ë˜ëŠ” Akismetì„ í™œì„±í™”í•˜ê³  IP ì œí•œì„ ì„¤ì •í•©ë‹ˆë‹¤
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr "주어진 ê·¸ë£¹ì— ëŒ€í•´ 성능 표시 바를 활성화 합니다."
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4029,12 +4693,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr "(UTC)ì— ì¢…ë£Œë©ë‹ˆë‹¤"
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr "아래 Bitbucket Server URL ë° ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°ì„ 입력하십시오."
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr "ì´ìŠˆ 설명 ìž…ë ¥"
@@ -4047,7 +4717,10 @@ msgstr "머지 리퀘스트(MR) ì„¤ëª…ì„ ìž…ë ¥ 해주세요"
msgid "Enter the merge request title"
msgstr "머지 리퀘스트(MR) ì œëª©ì„ ìž…ë ¥ 해주세요"
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4059,9 +4732,33 @@ msgstr ""
msgid "Environments"
msgstr "환경"
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "í™˜ê²½ê°’ë“¤ì„ ë°˜ì˜í•˜ëŠ” ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -4197,18 +4894,51 @@ msgstr "ì—픽 로드맵"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr "ì´ê²ƒì„ 어떻게 í•´ê²°í•  수 있습니까?"
msgid "Epics|More information"
msgstr "ìžì„¸í•œ ë‚´ìš©"
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4245,9 +4975,15 @@ msgstr "ë¼ë²¨ì„ 가져 오는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Error fetching network graph."
msgstr "ë„¤íŠ¸ì›Œí¬ ê·¸ëž˜í”„ ë°˜ì˜ ì¤‘ 오류"
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr "refs ë°˜ì˜ ì¤‘ 오류"
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr "사용 í•‘ ë°ì´í„° ë°˜ì˜ ì¤‘ 오류"
@@ -4257,6 +4993,12 @@ msgstr "브랜치 ë°ì´í„°ë¥¼ 로드하는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. ë‹
msgid "Error loading branches."
msgstr "브랜치 로드 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr "마지막 ì»¤ë°‹ì„ ë¡œë“œí•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -4266,6 +5008,9 @@ msgstr "ë§ˆí¬ ë‹¤ìš´ 미리보기 오류"
msgid "Error loading merge requests."
msgstr "머지 리퀘스트(MR)를 로드하는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr "프로ì íŠ¸ ë°ì´í„°ë¥¼ 로드하는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„하십시오."
@@ -4275,6 +5020,12 @@ msgstr "템플릿 유형 로드 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Error loading template."
msgstr "템플릿 로딩 오류."
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr "êµ¬ë… ì•Œë¦¼ì„ ì „í™˜í•  ë•Œ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
@@ -4308,9 +5059,15 @@ msgstr "해야할 ì¼ ìƒíƒœ 갱신 중 오류 ë°œìƒ"
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr "머지 리퀘스트(MR) 요청 중 오류 ë°œìƒ. 다시 ì‹œë„하십시오."
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4407,6 +5164,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4494,6 +5254,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr "Facebook"
@@ -4503,27 +5284,60 @@ msgstr "실패"
msgid "Failed Jobs"
msgstr "작업 실패"
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr "소유ìžë¥¼ 변경하지 못했습니다"
msgid "Failed to check related branches."
msgstr "관련 브랜치를 확ì¸í•˜ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤."
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr "ì´ëª¨ì§€ 목ë¡ì„ 불러올 수 없습니다"
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr "게시íŒì—ì„œ ì´ìŠˆë¥¼ ì œê±°í•˜ëŠ”ë° ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤, 다시 ì‹œë„í•´ 주십시오."
@@ -4542,6 +5356,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4554,18 +5374,30 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr "ì´ìŠˆë¥¼ ê°±ì‹ í•˜ëŠ”ë° ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤, 다시 ì‹œë„í•´ 주십시오."
+msgid "Failed to update tag!"
+msgstr ""
+
+msgid "Failed to update."
+msgstr ""
+
+msgid "Failed to upgrade."
+msgstr ""
+
msgid "Failed to upload object map file"
msgstr ""
msgid "Failure"
msgstr "실패"
-msgid "Fast-forward merge"
-msgstr ""
-
msgid "Fast-forward merge without a merge commit"
msgstr ""
@@ -4578,6 +5410,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4641,8 +5479,8 @@ msgstr "비활성화"
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
-msgstr "%{docs_link_start}호환 í´ë¼ì´ì–¸íŠ¸ ë¼ì´ë¸ŒëŸ¬ë¦¬%{docs_link_end}를 설치하고 API URL, 어플리케ì´ì…˜ ì´ë¦„, ì¸ìŠ¤í„´ìŠ¤ ID를 설정 과정ì—ì„œ 지정하세요."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
+msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr "ì¸ìŠ¤í„´ìŠ¤ ID"
@@ -4653,9 +5491,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr "ë” ë§Žì€ ì •ë³´"
-
msgid "FeatureFlags|Name"
msgstr "ì´ë¦„"
@@ -4735,6 +5570,12 @@ msgstr ""
msgid "Files"
msgstr "파ì¼"
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4783,6 +5624,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr "지문"
@@ -4792,6 +5636,9 @@ msgstr ""
msgid "Finish review"
msgstr "리뷰 완료"
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr "완료"
@@ -4816,6 +5663,12 @@ msgstr ""
msgid "Fixed:"
msgstr "수정ë¨:"
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr "FogBugz ì´ë©”ì¼"
@@ -4861,6 +5714,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "다른 프로ì íŠ¸ì—ì„œ í¬í¬ë¨: "
@@ -4870,6 +5732,9 @@ msgstr "%{project_name} (ì‚­ì œ) ì—ì„œ í¬í¬ë¨"
msgid "Forking in progress"
msgstr "í¬í¬ 진행중"
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4888,6 +5753,9 @@ msgstr ".gitlab-ci.ymlì—ì„œ 오류를 발견했습니다:"
msgid "Free Trial of GitLab.com Gold"
msgstr "GitLab.com Gold 무료 ì²´í—˜íŒ"
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4918,12 +5786,18 @@ msgstr "마ì¼ìŠ¤í†¤ì—ì„œ:"
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° 세부사항 ë³´ê¸°ì˜ ì• í”Œë¦¬ì¼€ì´ì…˜ 목ë¡ì—ì„œ Runner를 설치하십시오."
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr "GPG 키"
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5281,6 +6155,12 @@ msgstr "Geo|ë™ê¸°í™” 실패 - %{error}"
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5338,6 +6218,9 @@ msgstr "Git"
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5347,6 +6230,9 @@ msgstr "Git 저장소 URL"
msgid "Git revision"
msgstr "Git 리비전"
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr "파ì´í”„ ë¼ì¸ì— 대한 Git ì „ëžµ"
@@ -5419,6 +6305,9 @@ msgstr "Gitea 가져오기"
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr "ì´ì „으로"
@@ -5437,9 +6326,18 @@ msgstr "ì´ë™"
msgid "Go to %{link_to_google_takeout}."
msgstr "%{link_to_google_takeout}ë¡œ ì´ë™í•˜ì‹­ì‹œì˜¤."
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr "Google Code 가져오기"
@@ -5515,6 +6413,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5524,6 +6425,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr "그룹: %{group_name}"
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5551,13 +6455,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5569,9 +6476,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5602,9 +6506,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5668,6 +6581,9 @@ msgstr "%{ancestor_group_name} ì—ì„œ 그룹 lock 공유 제거"
msgid "Groups"
msgstr "그룹들"
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5737,6 +6653,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr "ì´ë¦„으로 검색"
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr "사용ìžì—게 ì´ë©”ì¼ ë°œì‹ "
@@ -5764,6 +6683,9 @@ msgstr " 헬스 문제가 발견ë˜ì§€ 않았습니다."
msgid "HealthCheck|Unhealthy"
msgstr "비정ìƒ"
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr "ë„움ë§"
@@ -5773,12 +6695,15 @@ msgstr "ë„ì›€ë§ íŽ˜ì´ì§€"
msgid "Help page text and support page url."
msgstr "ë„ì›€ë§ íŽ˜ì´ì§€ í…스트 ë° ì§€ì› íŽ˜ì´ì§€ url."
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr "호스트 키 ìˆ˜ë™ ìž…ë ¥ 숨기기"
@@ -5788,6 +6713,9 @@ msgstr ""
msgid "Hide payload"
msgstr "페ì´ë¡œë“œ 숨기기"
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "값 숨기기"
@@ -5801,6 +6729,12 @@ msgstr ""
msgid "History"
msgstr "ì´ë ¥"
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5816,6 +6750,12 @@ msgstr "Housekeepingì´ ì„±ê³µì ìœ¼ë¡œ 시작ë˜ì—ˆìŠµë‹ˆë‹¤"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5825,6 +6765,12 @@ msgstr "%{terms_link}ì— ë™ì˜í•©ë‹ˆë‹¤."
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr "서비스 약관 ë° ê°œì¸ì •ë³´ 보호 ì •ì±…"
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr "ID"
@@ -5894,11 +6840,20 @@ msgstr "만약 활성화 ëœ ê²½ìš°"
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
-msgstr "HTTP 저장소를 공개ì ìœ¼ë¡œ 액세스할 수 없는 경우, URLì— ì¸ì¦ 정보를 추가하십시오:<code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
+msgstr ""
msgid "ImageDiffViewer|2-up"
msgstr ""
@@ -5978,6 +6933,12 @@ msgstr "GitHub으로 부터 저장소 가져오기"
msgid "Import repository"
msgstr "저장소 가져 오기"
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -5987,6 +6948,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -5996,9 +6963,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr "GitLab Enterprise Editionì„ í†µí•´ ì´ìŠˆ 보드를 í–¥ìƒ ì‹œí‚µë‹ˆë‹¤."
@@ -6050,12 +7026,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr "호환ë˜ì§€ 않는 프로ì íŠ¸"
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr "ì¸ë¼ì¸"
@@ -6077,12 +7062,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr "GitLab Runner 설치"
msgid "Install Runner on Kubernetes"
msgstr "Kubernetesì— Runner 설치"
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] "ì¸ìŠ¤í„´ìŠ¤"
@@ -6129,18 +7126,42 @@ msgstr "Cycle Analytics 소개"
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6150,6 +7171,9 @@ msgstr ""
msgid "Invite"
msgstr "초대"
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6162,6 +7186,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6180,6 +7207,12 @@ msgstr "ì´ìŠˆ ì´ë²¤íŠ¸"
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr "보드"
@@ -6255,6 +7288,48 @@ msgstr "1ì›”"
msgid "January"
msgstr "1ì›”"
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr "Job"
@@ -6351,6 +7426,12 @@ msgstr "7ì›”"
msgid "July"
msgstr "7ì›”"
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr "6ì›”"
@@ -6360,6 +7441,9 @@ msgstr "6ì›”"
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -6384,12 +7468,18 @@ msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ê°€ 성공ì ìœ¼ë¡œ ì—…ë°ì´íŠ¸ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Kubernetes configured"
msgstr "Kubernetes 설정ë¨"
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr "Kubernetes 서비스 í†µí•©ì€ ë” ì´ìƒ 사용ë˜ì§€ 않습니다. %{deprecated_message_content} 새로운 <a href=\"%{url}\"/>Kubernetes í´ëŸ¬ìŠ¤í„°</a> 페ì´ì§€"
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr "LFS"
@@ -6402,6 +7492,9 @@ msgstr "Disabled"
msgid "LFSStatus|Enabled"
msgstr "Enabled"
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr "ë¼ë²¨"
@@ -6450,6 +7543,9 @@ msgstr "ë ˆì´ë¸” 승격"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6463,6 +7559,9 @@ msgstr[0] "최근 %d ì¼"
msgid "Last Pipeline"
msgstr "최근 파ì´í”„ë¼ì¸"
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6490,6 +7589,12 @@ msgstr "최근 ì—…ë°ì´íŠ¸"
msgid "Last updated"
msgstr "최근 ì—…ë°ì´íŠ¸ë¨"
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr "푸쉬: "
@@ -6505,6 +7610,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6523,6 +7634,9 @@ msgstr "Kubernetesì— ëŒ€í•´ ë” ì•Œì•„ë³´ê¸°"
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6535,6 +7649,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr "ë” ìžì„¸ížˆ 알아보기"
@@ -6556,6 +7673,12 @@ msgstr "프로ì íŠ¸ì—ì„œ 나가기"
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr "ë¼ì´ì„¼ìŠ¤"
@@ -6631,6 +7754,9 @@ msgstr "URL"
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr "ì´ í”„ë¡œì íŠ¸ì—ì„œ ë¼ì´ì„¼ìŠ¤ %{name}(ì„)를 제거하려고합니다."
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6644,6 +7770,9 @@ msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
msgstr[0] "최대 %d ì´ë²¤íŠ¸ 만 표시하는 것으로 제한ë©ë‹ˆë‹¤."
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -6674,6 +7803,9 @@ msgstr "실시간 미리보기"
msgid "Loading contribution stats for group members"
msgstr "그룹 구성ì›ë“¤ì˜ ê¸°ì—¬ë„ í†µê³„ì¹˜ 로드 중"
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr "GitLab IDE 로드 중..."
@@ -6695,6 +7827,9 @@ msgstr "%{issuableDisplayName} 잠금"
msgid "Lock not found"
msgstr "ìž ê¸ˆì„ ì°¾ì„ ìˆ˜ 없습니다."
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6713,6 +7848,9 @@ msgstr "현재 프로ì íŠ¸ì— ìž ê¹€"
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr "스마트 카드로 로그ì¸"
@@ -6737,12 +7875,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6803,6 +7950,15 @@ msgstr "3ì›”"
msgid "March"
msgstr "3ì›”"
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr "í•  ì¼ì„ 완료로 표시"
@@ -6815,6 +7971,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr "마í¬ë‹¤ìš´ 활성화ë¨"
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr "Maven 메타 ë°ì´í„°"
@@ -6839,6 +8004,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr "최대 작업 시간 초과"
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6869,6 +8037,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr "머지 리퀘스트(MR)"
@@ -6881,15 +8052,9 @@ msgstr "머지 리퀘스트(MR)"
msgid "Merge Requests created"
msgstr "머지 리퀘스트(MR) ìƒì„±ë¨"
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr "머지 ì´ë²¤íŠ¸"
@@ -6899,12 +8064,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr "머지 리퀘스트(MR)"
@@ -6923,6 +8082,30 @@ msgstr "머지 리퀘스트(MR)는 프로ì íŠ¸ì˜ 변경 ì‚¬í•­ì„ ì œì•ˆí•˜ê³ 
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6941,6 +8124,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -6953,6 +8139,9 @@ msgstr "새로운 ì´ìŠˆì—ì„œ ì´ í† ë¡ ì„ í•´ê²°í•˜ì„¸ìš”."
msgid "MergeRequests|Saving the comment failed"
msgstr "코멘트 저장 실패"
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr "ì´ íŒŒì¼ì— 대한 설명 전환"
@@ -6986,7 +8175,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7001,6 +8190,12 @@ msgstr ""
msgid "Messages"
msgstr "메시지"
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7016,6 +8211,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7055,9 +8253,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7103,9 +8298,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7130,9 +8337,6 @@ msgstr "마ì¼ìŠ¤í†¤ %{milestoneTitle}(ì„)를 ì˜êµ¬ížˆ 삭제하고 %{issuesWi
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr "마ì¼ìŠ¤í†¤ %{milestoneTitle}ì„ ì˜êµ¬ì ìœ¼ë¡œ 삭제하려고 합니다. ì´ ë§ˆì¼ìŠ¤í†¤ì€ ì–´ë– í•œ ì´ìŠˆ ë˜ëŠ” 머지 리퀘스트(MR)ì—ì„œë„ ì‚¬ìš©ë˜ì§€ 않습니다."
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr "<p>%{milestonePromotion}</p> %{finalWarning}"
-
msgid "Milestones|Delete milestone"
msgstr "마ì¼ìŠ¤í†¤ ì‚­ì œ"
@@ -7151,7 +8355,7 @@ msgstr "%{milestoneTitle} ì„(를) 그룹 마ì¼ìŠ¤í†¤ìœ¼ë¡œ 승격하시겠습ë
msgid "Milestones|Promote Milestone"
msgstr "마ì¼ìŠ¤í†¤ 승격"
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7160,6 +8364,15 @@ msgstr "ì´ ë™ìž‘ì€ ë˜ëŒë¦´ 수 없습니다."
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr "저장소 미러하기"
@@ -7181,6 +8394,18 @@ msgstr "ë¯¸ëŸ¬ë§ ì €ìž¥ì†Œ"
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "SSH 키 추가"
@@ -7241,6 +8466,24 @@ msgstr "ì´ë™"
msgid "Move issue"
msgstr "ì´ìŠˆ ì´ë™"
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr "여러 ì´ìŠˆ ë³´ë“œ"
@@ -7253,6 +8496,9 @@ msgstr ""
msgid "Name"
msgstr "ì´ë¦„"
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr "새 ë¼ë²¨ ì´ë¦„ 지정"
@@ -7347,6 +8593,9 @@ msgstr ""
msgid "New epic"
msgstr "ì‹ ê·œ ì—픽"
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr "새 파ì¼"
@@ -7371,6 +8620,9 @@ msgstr "새 머지 리퀘스트(MR)"
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr "새로운 파ì´í”„ ë¼ì¸ì€ ë™ì¼í•œ ë¸Œëžœì¹˜ì— ìžˆëŠ” ì´ì „ì˜ ëŒ€ê¸° ì¤‘ì¸ íŒŒì´í”„ ë¼ì¸ì„ 취소 합니다."
@@ -7401,6 +8653,12 @@ msgstr "새로 만들기..."
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr "아니오"
@@ -7410,12 +8668,21 @@ msgstr ""
msgid "No Label"
msgstr "ë¼ë²¨ ì—†ìŒ"
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr "브랜치가 존재하지 않습니다."
@@ -7431,6 +8698,9 @@ msgstr "Gitaly Serverì— ì—°ê²°í•  수 없습니다. 로그를 확ì¸í•˜ì‹­ì‹œì˜
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr "기여를 ì°¾ì„ ìˆ˜ 없습니다."
@@ -7455,6 +8725,9 @@ msgstr "파ì¼ì„ ì„ íƒí•˜ì§€ 않았습니다."
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr "파ì¼ì„ ì°¾ì„ ìˆ˜ 없습니다."
@@ -7476,9 +8749,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr "ì„ íƒí•œ 기간 ë™ì•ˆ 머지 리퀘스트(MR)ê°€ 없습니다."
@@ -7494,6 +8764,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr "그런 ì´ë¦„ ë˜ëŠ” 설명ì´ìžˆëŠ” 다른 ë ˆì´ë¸”ì´ ì—†ìŠµë‹ˆë‹¤."
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7521,6 +8794,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr "노드"
@@ -7569,6 +8848,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr "참고: 관리ìžì—게 %{github_integration_link} (ì„) 를 설정하여, GitHub를 통한 로그ì¸ì„ 허용하고 ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°ì„ ìƒì„±í•˜ì§€ ì•Šê³  저장소를 가져올 수 있ë„ë¡ í—ˆìš©í•  수 있는지 문ì˜í•˜ì‹­ì‹œì˜¤."
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7584,6 +8866,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr "알림 ì´ë²¤íŠ¸"
@@ -7593,6 +8881,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "ì´ìŠˆ 닫기"
@@ -7647,6 +8938,9 @@ msgstr "참여"
msgid "NotificationLevel|Watch"
msgstr "Watch"
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr "알림"
@@ -7662,6 +8956,12 @@ msgstr "11ì›”"
msgid "November"
msgstr "11ì›”"
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr "확ì¸"
@@ -7677,8 +8977,14 @@ msgstr "10ì›”"
msgid "OfSearchInADropdown|Filter"
msgstr "í•„í„°"
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
-msgstr "가져오기가 완료ë˜ë©´ 저장소를 SSH를 통해 ë¯¸ëŸ¬ë§ í•  수 있습니다. ë” ì•Œì•„ë³´ê¸° %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
+msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
msgstr ""
@@ -7699,13 +9005,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
+msgstr ""
+
msgid "Only admins"
msgstr "관리ìžë§Œ 가능"
-msgid "Only allow merge requests to be merged if all discussions are resolved"
-msgstr ""
-
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7723,6 +9029,9 @@ msgstr "프로ì íŠ¸ 구성ì›ë§Œ ëŒ“ê¸€ì„ ë‹¬ 수 있습니다."
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr "ì´ëŸ°, 확실합니까?"
@@ -7768,6 +9077,12 @@ msgstr "열린"
msgid "Opens in a new window"
msgstr "새 창으로 열기"
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr "ìš´ì˜ìž"
@@ -7792,9 +9107,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7816,6 +9128,9 @@ msgstr "기타 ë¼ë²¨"
msgid "Other information"
msgstr "다른 정보"
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr "외부로 가는 요청"
@@ -7825,6 +9140,12 @@ msgstr "개요"
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr "소유ìž"
@@ -7852,6 +9173,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "마지막 »"
@@ -7873,9 +9197,21 @@ msgstr "머지 리퀘스트(MR) 변경 사항 중 ì¼ë¶€"
msgid "Password"
msgstr "패스워드"
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7888,7 +9224,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7915,6 +9251,9 @@ msgstr "대기중"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr "경로 변경, 그룹 전송 ë˜ëŠ” 제거와 ê°™ì€ ê³ ê¸‰ ì˜µì…˜ì„ ìˆ˜í–‰í•©ë‹ˆë‹¤."
@@ -7936,12 +9275,27 @@ msgstr "ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°"
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr "파ì´í”„ë¼ì¸"
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr "파ì´í”„ë¼ì¸ 스케쥴"
@@ -8020,6 +9374,9 @@ msgstr "파ì´í”„ë¼ì¸"
msgid "Pipelines charts"
msgstr "파ì´í”„ë¼ì¸ 차트"
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr "ì§€ë‚œë‹¬ì˜ íŒŒì´í”„ë¼ì¸"
@@ -8029,10 +9386,13 @@ msgstr "ì§€ë‚œì£¼ì˜ íŒŒì´í”„ë¼ì¸"
msgid "Pipelines for last year"
msgstr "ì§€ë‚œí•´ì˜ íŒŒì´í”„ë¼ì¸"
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8053,6 +9413,9 @@ msgstr "파ì´í”„ ë¼ì¸ìœ¼ë¡œ 시작하기"
msgid "Pipelines|Loading Pipelines"
msgstr "파ì´í”„ë¼ì¸ 로딩중"
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "프로ì íŠ¸ ìºì‹œê°€ 성공ì ìœ¼ë¡œ 재설정ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -8113,6 +9476,9 @@ msgstr "파ì´í”„ë¼ì¸ 중지"
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr "#%{pipelineId} 파ì´í”„ë¼ì¸ì„ 중지하시겠습니까?"
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr "변수"
@@ -8143,6 +9509,15 @@ msgstr "스테ì´ì§•"
msgid "Pipeline|with stages"
msgstr "스테ì´ì§•"
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8152,12 +9527,30 @@ msgstr "PlantUML"
msgid "Play"
msgstr "Play"
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr "계ì†í•˜ê¸° ì „ì— ì„œë¹„ìŠ¤ ì•½ê´€ì— ë™ì˜í•˜ì‹­ì‹œì˜¤."
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8188,6 +9581,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8200,6 +9596,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8221,7 +9626,7 @@ msgstr "다시 ì‹œë„í•´ 주세요."
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8239,12 +9644,66 @@ msgstr "환경 설정"
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr "테마 íƒìƒ‰"
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8260,12 +9719,18 @@ msgstr ""
msgid "Preview"
msgstr "미리보기"
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr "주"
@@ -8293,15 +9758,24 @@ msgstr "Private - 그룹과 ê·¸ë£¹ì˜ í”„ë¡œì íŠ¸ë“¤ì€ ë©¤ë²„ë“¤ì´ ì—´ëžŒí• 
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr "비공개 프로ì íŠ¸ëŠ” ê°œì¸ ë„¤ìž„ìŠ¤íŽ˜ì´ìŠ¤ì—ì„œ 만들어집니다:"
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr "프로필"
msgid "Profile Settings"
msgstr "프로필 설정"
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr "%{yourAccount}를 ì˜êµ¬ì ìœ¼ë¡œ 삭제하려고 합니다. ì´ìŠˆ, 머지 리퀘스트(MR), 그리고 ë‚´ ê³„ì •ì— ì—°ê²°ëœ ê·¸ë£¹ê°€ ì‚­ì œë ê²ƒìž…니다. %{deleteAccount}ì„ í™•ì¸í•˜ë©´ ë˜ëŒë¦¬ê±°ë‚˜, 취소할 수 없습니다."
@@ -8332,6 +9806,9 @@ msgstr "아바타 ìžë¥´ê¸°"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "아바타가 ì‚­ì œë©ë‹ˆë‹¤. 확실합니까?"
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr "사용ìžëª… 변경"
@@ -8353,6 +9830,9 @@ msgstr "ìƒíƒœ 지우기"
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8365,6 +9845,9 @@ msgstr "현재 경로: %{path}"
msgid "Profiles|Current status"
msgstr "현재 ìƒíƒœ"
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr "계정 삭제"
@@ -8392,6 +9875,18 @@ msgstr "프로필 편집"
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8401,9 +9896,15 @@ msgstr "ìž˜ëª»ëœ íŒ¨ìŠ¤ì›Œë“œ"
msgid "Profiles|Invalid username"
msgstr "ìž˜ëª»ëœ ì‚¬ìš©ìžì´ë¦„"
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr "ë” ì•Œì•„ë³´ê¸°"
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8413,18 +9914,33 @@ msgstr "주요 설정"
msgid "Profiles|No file chosen"
msgstr "파ì¼ì´ ì„ íƒë˜ì§€ 않았습니다."
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr "경로"
msgid "Profiles|Position and size your new avatar"
msgstr "새 아바타 위치 ë° í¬ê¸° ì¡°ì ˆ"
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr "비밀 기여"
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr "공개 아바타"
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr "아바타 제거"
@@ -8443,9 +9959,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "최대 허용ë˜ëŠ” 파ì¼ì˜ í¬ê¸°ëŠ” 200KB입니다."
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "ì´ê²ƒì€ 공개 SSH 키가 아닌것 같습니다. ì •ë§ë¡œ 추가 하시겠어요?"
@@ -8461,14 +9974,17 @@ msgstr "ì´ ê·¸ë¦¼ê³¼ 메시지는 프로필과 ì¸í„°íŽ˜ì´ìŠ¤ ì „ì²´ì— ë‚˜íƒ€
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "확ì¸ì„ 위해 %{confirmationValue} 를 입력하세요."
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
-msgstr "ì¼ë°˜ì ìœ¼ë¡œ \"ssh-rsa ...\"으로 시작합니다."
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
+msgstr ""
msgid "Profiles|Update profile settings"
msgstr "프로필 설정 ì—…ë°ì´íŠ¸"
@@ -8482,6 +9998,9 @@ msgstr "새 아바타 업로드"
msgid "Profiles|Use a private email - %{email}"
msgstr "ê°œì¸ ì´ë©”ì¼ ì‚¬ìš© - %{email}"
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr "ì‚¬ìš©ìž ì´ë¦„ 바꾸기 실패 - %{message}"
@@ -8503,6 +10022,9 @@ msgstr "여기ì—ì„œ 아바타를 변경할 수 있습니다."
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr "여기ì—ì„œ 아바타를 변경하거나 현재 아바타를 제거하여 %{gravatar_link}ë¡œ ë˜ëŒë¦´ 수 있습니다"
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr "여기ì—ì„œ 아바타를 업로드 í•  수 있습니다."
@@ -8596,6 +10118,9 @@ msgstr ""
msgid "Project avatar"
msgstr "프로ì íŠ¸ 아바타"
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8641,6 +10166,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "구ë…"
@@ -8692,6 +10220,24 @@ msgstr "프로ì íŠ¸ì— ë³„ì„ í‘œì‹œí•˜ë ¤ë©´ 로그ì¸í•´ì•¼í•©ë‹ˆë‹¤."
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "프로ì íŠ¸ ID: %{project_id}"
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr "뱃지"
@@ -8701,18 +10247,60 @@ msgstr "ì´ ì„¤ì •ì„ ë³€ê²½í•˜ë ¤ë©´ 관리ìžì—게 문ì˜í•˜ì„¸ìš”."
msgid "ProjectSettings|Customize your project badges."
msgstr "프로ì íŠ¸ 뱃지 커스텀마ì´ì§•"
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr "태그 ë³´í˜¸ì— ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤."
msgid "ProjectSettings|Failed to update tag!"
msgstr "태그 ì—…ë°ì´íŠ¸ì— 실패했습니다!"
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr "ë±ƒì§€ì— ëŒ€í•´ ìžì„¸ížˆ 알아보세요."
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "ì´ ì €ìž¥ì†Œì—는 ì„œëª…ëœ ì»¤ë°‹ë§Œ 푸쉬할 수 있습니다."
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr "ì´ ì„¤ì •ì€ ì„œë²„ 레벨ì—ì„œ ì ìš©ë˜ì—ˆìœ¼ë©°, 관리ìžì— ì˜í•´ ë³€ê²½ë  ìˆ˜ 있습니다."
@@ -8722,12 +10310,72 @@ msgstr "ì´ ì„¤ì •ì€ ì„œë²„ 레벨ì—ì„œ ì ìš©ë˜ì—ˆìœ¼ë©°, 프로ì íŠ¸ì— ì
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "관리ìžì— 변경ë˜ì§€ 않는 í•œ, ì´ ì„¤ì •ì€ ëª¨ë“  프로ì íŠ¸ì— ì ìš©ë©ë‹ˆë‹¤."
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr "사용ìžëŠ” ì´ ì €ìž¥ì†Œì— ì¸ì¦ëœ ì´ë©”ì¼ë¡œ ì»¤ë°‹ëœ ì»¤ë°‹ë§Œì„ push í•  수 있습니다."
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr "프로ì íŠ¸"
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8884,6 +10532,15 @@ msgstr "그룹 마ì¼ìŠ¤í†¤ìœ¼ë¡œ 승격"
msgid "Promote to group label"
msgstr "그룹 ë¼ë²¨ë¡œ 승격"
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr "다시 표시하지 않습니다."
@@ -8902,16 +10559,22 @@ msgstr ""
msgid "Protected"
msgstr "보호ë¨"
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr "ë³´í˜¸ëœ í™˜ê²½"
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8920,18 +10583,24 @@ msgstr "환경"
msgid "ProtectedEnvironment|Protect"
msgstr "보호"
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -8980,9 +10649,15 @@ msgstr "Pull"
msgid "Push"
msgstr "Push"
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr "Push 규칙"
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9007,12 +10682,54 @@ msgstr "푸시ë¨"
msgid "Pushes"
msgstr "푸시"
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr "분기별"
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr "Quick actionì€ ì´ìŠˆ 설명ì´ë‚˜ 댓글 박스ì—ì„œ 사용 가능합니다."
@@ -9037,15 +10754,24 @@ msgstr "실시간 기능"
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr "최근 검색"
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9059,24 +10785,45 @@ msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr "키 재ìƒì„±"
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr "ì •ê·œ í‘œí˜„ì‹ íŒ¨í„´"
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr "ë“±ë¡ / 로그ì¸"
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9101,6 +10848,9 @@ msgstr "관련 머지 리퀘스트(MR)"
msgid "Related Merged Requests"
msgstr "관련 머지 리퀘스트(MR)"
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr "ê´€ë ¨ëœ ë¨¸ì§€ 리퀘스트(MR)"
@@ -9113,6 +10863,9 @@ msgstr ""
msgid "Remind later"
msgstr "ë‚˜ì¤‘ì— ë‹¤ì‹œ 알림"
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr "삭제"
@@ -9122,7 +10875,10 @@ msgstr "Runner 제거"
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9131,25 +10887,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr "아바타 제거"
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr "우선 순위 삭제"
msgid "Remove project"
msgstr "프로ì íŠ¸ ì‚­ì œ"
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9164,6 +10932,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9194,6 +10980,9 @@ msgstr "ì¸ì¦ 복구"
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9203,8 +10992,8 @@ msgstr ""
msgid "Repo by URL"
msgstr "저장소 URL"
-msgid "Report abuse to GitLab"
-msgstr "GitLabì— ì•…ìš© 사례 ì‹ ê³ "
+msgid "Report abuse to admin"
+msgstr ""
msgid "Reporting"
msgstr "ë³´ê³ "
@@ -9218,6 +11007,9 @@ msgstr "ìž‘ì—…"
msgid "Reports|Class"
msgstr "í´ëž˜ìŠ¤"
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9257,12 +11049,6 @@ msgstr "테스트 요약 ê²°ê³¼ 분ì„중"
msgid "Reports|Vulnerability"
msgstr "취약ì "
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr "ë³€ê²½ëœ í…ŒìŠ¤íŠ¸ ê²°ê³¼ ì—†ìŒ"
@@ -9317,6 +11103,12 @@ msgstr "GitLabì— ì•¡ì„¸ìŠ¤ í•  ë•Œ 모든 사용ìžê°€ 서비스 약관 ë° ê°œ
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9325,6 +11117,9 @@ msgid "Requires approval."
msgid_plural "Requires %d more approvals."
msgstr[0] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9364,6 +11159,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9406,6 +11210,9 @@ msgstr "ì´ ìž‘ì—… 재시ë„"
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr "ê²€ì¦ ìž¬ì‹œë„"
@@ -9443,6 +11250,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr "로드맵"
@@ -9527,6 +11340,9 @@ msgstr "%{group_name}ì˜ SAML SSO"
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr "SSH 키"
@@ -9536,6 +11352,9 @@ msgstr ""
msgid "SSH host keys"
msgstr "SSH 호스트 키"
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr "SSH 공개키"
@@ -9551,6 +11370,9 @@ msgstr "저장"
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr "애플리케ì´ì…˜ 저장"
@@ -9563,6 +11385,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "파ì´í”„ë¼ì¸ 스케줄 저장"
@@ -9623,9 +11448,21 @@ msgstr "브랜치 ë° íƒœê·¸ 검색"
msgid "Search files"
msgstr "íŒŒì¼ ê²€ìƒ‰"
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr "프로ì íŠ¸, 문제 등 검색"
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9647,6 +11484,9 @@ msgstr "프로ì íŠ¸ 검색"
msgid "Search projects"
msgstr "프로ì íŠ¸ 검색"
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr "ì‚¬ìš©ìž ê²€ìƒ‰"
@@ -9722,9 +11562,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr "ë” ë§Žì€ ì •ë³´"
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr "ì´ìŠˆë¥¼ ìƒì„± í•˜ë˜ ì¤‘ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -9755,12 +11592,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr "보안 대시보드ì—는 최신 보안 보고서가 표시ë©ë‹ˆë‹¤. 취약ì ì„ 찾고, ìˆ˜ì •í•˜ëŠ”ë° ì‚¬ìš©í•˜ì„¸ìš”."
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr "코드 ì·¨ì•½ì  ëª¨ë‹ˆí„°ë§"
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr "파ì´í”„ë¼ì¸ %{pipelineLink} 실행ë¨"
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9773,6 +11622,12 @@ msgstr "ì„ íƒ"
msgid "Select Archive Format"
msgstr "ì•„ì¹´ì´ë¸Œ í¬ë§· ì„ íƒ"
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr "초대 í•  그룹 ì„ íƒ"
@@ -9800,6 +11655,9 @@ msgstr "기존 Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ ì„ íƒí•˜ê±°ë‚˜ 새로 만듭니다."
msgid "Select branch/tag"
msgstr "브랜치/태그 ì„ íƒ"
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9836,6 +11694,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr "ì´ë©”ì¼ ì „ì†¡"
@@ -9917,6 +11778,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr "서비스 ë°ìŠ¤í¬"
@@ -9947,21 +11811,24 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr "ê¸°ë³¸ê°’ì„ ì„¤ì •í•˜ê³  공개 ìˆ˜ì¤€ì„ ì œí•œí•˜ì‹­ì‹œì˜¤. 소스 가져오기와 git ì ‘ê·¼ í”„ë¡œí† ì½œì„ ì„¤ì •í•˜ì‹­ì‹œì˜¤."
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr "웹 터미ë„ì˜ ìµœëŒ€ 세션 ì‹œê°„ì„ ì„¤ì •í•©ë‹ˆë‹¤."
+msgid "Set milestone"
+msgstr ""
+
msgid "Set new password"
msgstr ""
msgid "Set notification email for abuse reports."
msgstr "남용 ë³´ê³ ì„œì— ëŒ€í•œ 알림 ì´ë©”ì¼ì„ 설정합니다."
-msgid "Set number of approvers required before open merge requests can be merged"
-msgstr ""
-
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr "사용ìžì˜ ë¡œê·¸ì¸ ìš”êµ¬ ì‚¬í•­ì„ ì„¤ì •í•©ë‹ˆë‹¤. 반드시 ì´ì¤‘ ì¸ì¦ 하ë„ë¡ ì„¤ì •í•©ë‹ˆë‹¤."
@@ -9977,6 +11844,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr "CI/CD 설정"
@@ -9998,6 +11868,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr "패스워드 설정"
@@ -10025,6 +11898,18 @@ msgstr "죄송합니다, ë‹¹ì‹ ì˜ ìƒíƒœë¥¼ 설정할 수 없습니다. ìž ì‹œí
msgid "SetStatusModal|What's your status?"
msgstr "ìƒíƒœê°€ 어떤가요?"
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr "설정"
@@ -10040,6 +11925,9 @@ msgstr "공용 Runners"
msgid "Shared projects"
msgstr "ê³µìœ ëœ í”„ë¡œì íŠ¸"
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10052,9 +11940,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr "ì…œë¡ íŠ¸ëžœì ì…˜"
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr "명령 보기"
@@ -10070,9 +11967,6 @@ msgstr ""
msgid "Show latest version"
msgstr "최신 버전 보기"
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr "부모 페ì´ì§€ 보기"
@@ -10125,12 +12019,30 @@ msgstr ""
msgid "Sign out"
msgstr "로그아웃"
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr "ë¡œê·¸ì¸ ì œí•œ"
msgid "Sign-up restrictions"
msgstr "가입 제한"
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10140,6 +12052,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr "í¬ê¸°"
@@ -10149,6 +12064,9 @@ msgstr "ì •ì  ì›¹ 사ì´íŠ¸ì˜ í¬ê¸° ë° ë„ë©”ì¸ ì„¤ì •"
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr "Slack 어플리케ì´ì…˜"
@@ -10218,6 +12136,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr "ë²„íŠ¼ì„ í† ê¸€í•˜ë˜ ì¤‘ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10236,6 +12157,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10260,7 +12184,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10272,6 +12196,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr "문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„해주세요."
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr "죄송합니다. 검색과 ì¼ì¹˜í•˜ëŠ” ì—í”½ì´ ì—†ìŠµë‹ˆë‹¤."
@@ -10332,6 +12259,9 @@ msgstr "ëœ ì¸ê¸°ìžˆëŠ”"
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10386,6 +12316,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr "최근 로그ì¸"
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10458,6 +12394,9 @@ msgstr "%{type} 스테ì´ì§€ë¨"
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr "별표"
@@ -10482,6 +12421,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10512,6 +12454,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "Runner 시작!"
@@ -10572,12 +12520,18 @@ msgstr "스토리지"
msgid "Storage:"
msgstr "저장소:"
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr "하위 그룹"
msgid "Subgroups and projects"
msgstr "서브 그룹과 프로ì íŠ¸"
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr "스팸으로 제출"
@@ -10608,6 +12562,9 @@ msgstr ""
msgid "Subscribed"
msgstr "구ë…ë¨"
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10680,6 +12637,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10704,6 +12664,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10716,6 +12739,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr "스위치 브랜치/태그"
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr "ì •ë³´ ë™ê¸°í™”"
@@ -10746,18 +12775,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr "태그 "
msgid "Tags feed"
msgstr "태그 피드"
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr "태그:"
@@ -10839,6 +12880,9 @@ msgstr "ëŒ€ìƒ ë¸Œëžœì¹˜"
msgid "Team"
msgstr "팀"
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr "템플릿"
@@ -10851,6 +12895,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "서비스 약관 계약 ë° ê°œì¸ ì •ë³´ 보호 ì •ì±…"
@@ -10866,6 +12913,33 @@ msgstr "테스트 커버리지 파싱"
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10903,6 +12977,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10918,6 +12995,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -10975,6 +13055,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "ì´ìŠˆ 단계ì—는 ì´ìŠˆë¥¼ 작성하여 마ì¼ìŠ¤í†¤ìœ¼ë¡œ 지정하는 ë° ê±¸ë¦¬ëŠ” 시간 ë˜ëŠ” ì´ìŠˆ ë³´ë“œì˜ ëª©ë¡ì— ì´ìŠˆë¥¼ 추가하는 ì‹œê°„ì´ í‘œì‹œë©ë‹ˆë‹¤. ì´ ë‹¨ê³„ì˜ ë°ì´í„°ë¥¼ 보기 위해서는 ì´ìŠˆë¥¼ 먼저 작성해야 합니다."
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -10993,6 +13082,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11017,9 +13112,21 @@ msgstr "프로ë•ì…˜ 단계ì—서는 문제를 만들고 코드를 프로ë•ì…˜
msgid "The project can be accessed by any logged in user."
msgstr "ì´ í”„ë¡œì íŠ¸ëŠ” ë¡œê·¸ì¸ í•œ 사용ìžê°€ë§Œ 액세스 í•  수 있습니다."
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr "ì´ í”„ë¡œì íŠ¸ëŠ” ì¸ì¦ì—†ì´ 액세스 í•  수 있습니다."
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11029,6 +13136,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11038,6 +13148,9 @@ msgstr "ì´ í”„ë¡œì íŠ¸ì˜ 저장소가 존재하지 않습니다."
msgid "The repository for this project is empty"
msgstr "ì´ í”„ë¡œì íŠ¸ì˜ 저장소가 비어있습니다."
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr "저장소를 <code>http://</code>, <code>https://</code> ë˜ëŠ” <code>git://</code> 통해 액세스할 수 있어야 합니다."
@@ -11077,6 +13190,9 @@ msgstr "테스트 단계ì—서는 GitLab CIê°€ 관련 머지 리퀘스트(MR)ì„
msgid "The time taken by each data entry gathered by that stage."
msgstr "해당 단계ì—ì„œ 수집 í•œ ê° ë°ì´í„° ìž…ë ¥ì— ì†Œìš” ëœ ì‹œê°„"
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11098,15 +13214,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "ê°’ì€ ì¼ë ¨ì˜ 관측 ê°’ 중ì ì— 있습니다. 예를 들어, 3, 5, 9 사ì´ì˜ 중간 ê°’ì€ 5입니다. 3, 5, 7, 8 사ì´ì˜ 중간 ê°’ì€ (5 + 7) / 2 = 6입니다."
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11140,9 +13271,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr "í•  ì¼ì„ 추가하는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr "í•  ì¼ì„ 삭제하는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -11158,6 +13304,12 @@ msgstr "ì‚¬ìš©ìž í™œë™ ìº˜ë¦°ë”를 로딩하는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí•˜ì˜€
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11176,6 +13328,9 @@ msgstr "ì´ ë¼ë²¨ì„ 구ë…í•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "There was an error when unsubscribing from this label."
msgstr "ì´ ë¼ë²¨ì„ 구ë…ì·¨ì†Œí•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11188,6 +13343,9 @@ msgstr "%{link}를 사용하여 관리 할 수 ​​있습니다."
msgid "Third party offers"
msgstr "타사 제공"
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11200,18 +13358,30 @@ msgstr "ì´ GitLab ì¸ìŠ¤í„´ìŠ¤ëŠ” 공유 Runnersê°€ 제공ë˜ì§€ 않습니다.
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr "ì´ ì‘ìš© í”„ë¡œê·¸ëž¨ì€ ë‹¤ìŒì„ 수행 í•  수 있습니다."
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr "ì´ ë³´ë“œì˜ ë²”ìœ„ê°€ 축소ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11236,6 +13406,12 @@ msgstr "ì´ ë‚ ì§œëŠ” 마ê°ì¼ ì´í›„ì´ë¯€ë¡œ ì´ ì—í”½ì€ ë¡œë“œë§µì— ë‚˜íƒ
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr "ì´ ë¹„êµëŠ” 접혀있습니다."
@@ -11248,6 +13424,9 @@ msgstr "ì´ ë””ë ‰í† ë¦¬"
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11257,24 +13436,33 @@ msgstr "ì´ ê·¸ë£¹"
msgid "This group does not provide any group Runners yet."
msgstr "ì´ ê·¸ë£¹ì€ ì•„ì§ ê·¸ë£¹ Runners를 제공하지 않습니다."
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr "비밀 ì´ìŠˆìž…니다."
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr "ì´ ì €ìžì˜ ì´ í”„ë¡œì íŠ¸ì— 대한 첫번째 머지 리퀘스트(MR) 입니다."
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
+msgid "This is your current session"
+msgstr ""
+
msgid "This issue is confidential"
msgstr "ì´ ì´ìŠˆëŠ” 비밀입니다."
-msgid "This issue is confidential and locked."
-msgstr "ì´ ì´ìŠˆëŠ” confidential ì´ê³  잠금 ìƒíƒœìž…니다."
-
msgid "This issue is locked."
msgstr "ì´ ì´ìŠˆëŠ” lock ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -11344,12 +13532,6 @@ msgstr "즉, 빈 저장소를 만들거나 기존 저장소를 가져올 때까ì
msgid "This merge request is locked."
msgstr "ì´ ë¨¸ì§€ 리퀘스트(MR)는 잠겨있습니다."
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11422,6 +13604,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr "ì´ìŠˆê°€ 스케줄ë˜ê¸° ì „ì˜ ì‹œê°„"
@@ -11604,6 +13792,9 @@ msgstr "íŒ:"
msgid "Title"
msgstr "제목"
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11619,6 +13810,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr "GitHub 저장소 ì—°ê²°í• ë•Œ, %{personal_access_token_link}ì„ ì‚¬ìš©í•  수 있습니다. ê°œì¸ ì—‘ì„¸ìŠ¤ 토í°ì„ ìƒì„±í• ë•Œ <code>repo</code> scope를 ì„ íƒí•´ì•¼ ì—°ê²°ì— ì‚¬ìš©í•  수 있는 공개, 비공개 저장소가 표시ë˜ì–´ ì—°ê²°í•  수 있게 ë©ë‹ˆë‹¤."
@@ -11685,6 +13879,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11721,6 +13918,9 @@ msgstr "í• ì¼ë“¤"
msgid "Toggle Sidebar"
msgstr "사ì´ë“œë°” 전환"
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11733,9 +13933,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr "토글 토론"
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "토글 네비게ì´ì…˜"
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "사ì´ë“œë°” 토글"
@@ -11745,6 +13951,9 @@ msgstr "토글 ìƒíƒœ: OFF"
msgid "ToggleButton|Toggle Status: ON"
msgstr "토글 ìƒíƒœ: ON"
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr "토í°"
@@ -11787,6 +13996,42 @@ msgstr "퀵 ì•¡ì…˜ 시간 추ì "
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11838,15 +14083,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr "GitLabì´ ì œê³µí•˜ëŠ” 모든 ê¸°ëŠ¥ì„ 30ë™ì•ˆ 사용해 보세요."
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "서비스 ë°ìŠ¤í¬ 켜기"
msgid "Twitter"
msgstr "Twitter"
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11856,24 +14116,42 @@ msgstr "2단계 ì¸ì¦"
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr "ì°¨ì´ì ì„ ì½ì–´ë“¤ì¼ 수 없습니다. %{button_try_again}"
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11892,18 +14170,33 @@ msgstr ""
msgid "Unknown"
msgstr "ì•Œ 수 ì—†ìŒ"
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr "잠금 해제"
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr "%{issuableDisplayName}(ì„)를 잠금해제 하시겠습니까? <strong>모ë‘ê°€</strong> 코멘트 í•  수 있게 ë©ë‹ˆë‹¤."
msgid "Unlocked"
msgstr "잠금 í•´ì œë¨"
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr "í•´ê²°ë˜ì§€ ì•Šì€ í† ë¡ "
@@ -11973,6 +14266,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12024,6 +14329,9 @@ msgstr ""
msgid "Upload file"
msgstr "íŒŒì¼ ì—…ë¡œë“œ"
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12033,6 +14341,9 @@ msgstr "업로드하려면 í´ë¦­í•˜ì‹­ì‹œì˜¤."
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12051,6 +14362,54 @@ msgstr "ping ì‚¬ìš©ì´ í™œì„±í™” ë˜ì§€ 않았습니다."
msgid "Usage statistics"
msgstr "사용 통계"
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12060,6 +14419,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr "그룹 마ì¼ìŠ¤í†¤ì„ 사용하시면 여러 프로ì íŠ¸ì˜ ì´ìŠˆë“¤ì„ í•˜ë‚˜ì˜ ë§ˆì¼ìŠ¤í†¤ìœ¼ë¡œ 관리할 수 있습니다."
@@ -12117,6 +14482,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12132,6 +14500,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr "활ë™"
@@ -12207,6 +14710,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr "사용ìžë“¤"
@@ -12222,9 +14734,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12270,12 +14800,18 @@ msgstr "버전"
msgid "View app"
msgstr "앱 보기"
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12285,6 +14821,9 @@ msgstr "ì—픽 ëª©ë¡ ë³´ê¸°"
msgid "View file @ "
msgstr "파ì¼ë³´ê¸° @ "
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr "그룹 ë¼ë²¨ 보기"
@@ -12294,6 +14833,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr "GitLabì—ì„œ 보기"
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12321,6 +14863,9 @@ msgstr "문서 보기"
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr "공개 범위 ë° ì•¡ì„¸ìŠ¤ 설정"
@@ -12348,6 +14893,33 @@ msgstr "Public"
msgid "VisibilityLevel|Unknown"
msgstr "ì•Œ 수 ì—†ìŒ"
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12390,6 +14962,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "ì´ ë°ì´í„°ë¥¼ ë³´ê³  싶ì€ê°€ìš”? 관리ìžì—게 액세스 ê¶Œí•œì„ ìš”ì²­í•˜ì„¸ìš”."
@@ -12408,6 +14983,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "%{humanized_resource_name}ì—ì„œ 잠재ì ì¸ ìŠ¤íŒ¸ì„ íƒì§€í–ˆìŠµë‹ˆë‹¤. 계ì†í•˜ë ¤ë©´ reCAPTCHA를 진행하세요."
@@ -12417,6 +14995,9 @@ msgstr "ì´ ë‹¨ê³„ë¥¼ ë³´ì—¬ì£¼ê¸°ì— ì¶©ë¶„í•œ ë°ì´í„°ê°€ 없습니다."
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "ì •ë§ ë‹¹ì‹ ì´ ë§žëŠ”ì§€ 확ì¸í•˜ê³  싶습니다, ë‹¹ì‹ ì´ ë¡œë´‡ì´ ì•„ë‹ˆë¼ëŠ” ê²ƒì„ í™•ì¸í•´ì£¼ì‹­ì‹œì˜¤."
@@ -12438,6 +15019,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr "주"
@@ -12447,15 +15031,18 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
+msgid "Welcome to the Guided GitLab Tour"
+msgstr ""
+
+msgid "Welcome to your Issue Board!"
+msgstr ""
+
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Runnerê°€ 잠겨 있으면 다른 프로ì íŠ¸ì— 할당 í•  수 없습니다"
msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr "사용 설정ë˜ë©´ 사용ìžëŠ” GitLab ì•½ê´€ì´ ìˆ˜ë½ ë  ë•Œê¹Œì§€ GitLabì„ ì‚¬ìš©í•  수 없습니다."
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
@@ -12466,6 +15053,9 @@ msgstr[0] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr "누가 ì´ ê·¸ë£¹ì„ ë³¼ 수 있나요?"
@@ -12646,6 +15236,9 @@ msgstr ""
msgid "Yes"
msgstr "예"
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr "네, 추가합니다."
@@ -12661,8 +15254,14 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "%{group_name} ê·¸ë£¹ì„ ì œê±°í•˜ë ¤ê³ í•©ë‹ˆë‹¤. \\\"ì •ë§ë¡œ\\\" 확실합니까?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "%{project_full_name} 프로ì íŠ¸ë¥¼ 삭제하려고 합니다. ì‚­ì œëœ í”„ë¡œì íŠ¸ëŠ” \"절대로\" 복구할 수 없습니다! \"ì •ë§ë¡œ\" 확실합니까?"
@@ -12673,6 +15272,9 @@ msgstr "í¬í¬ 관계를 소스 프로ì íŠ¸ %{forked_from_project}ì— ëŒ€í•´ ì 
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr "%{project_full_name} (ì„) 를 다른 소유ìžì—게 ì´ì „하려고합니다. \"ì •ë§ë¡œ\" 확실합니까?"
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12688,6 +15290,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr "ëª…ë ¹ì¤„ì„ í†µí•´ 프로ì íŠ¸ë¥¼ ìƒì„±í•  수 있습니다."
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr "ë¼ë²¨ì— 별표를 붙여 우선순위 ë¼ë²¨ì„ 만들 ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤."
@@ -12706,6 +15314,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ì— Runner를 쉽게 설치할 수 있습니다. %{link_to_help_page}"
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr "화살표 키를 사용하여 그래프를 움ì§ì¼ 수 있습니다."
@@ -12730,9 +15347,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12763,12 +15386,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr "ë‹¹ì‹ ì€ ì• í”Œë¦¬ì¼€ì´ì…˜ì„ 가지고 있지 않습니다."
@@ -12778,6 +15410,12 @@ msgstr "ìŠ¹ì¸ ëœ ì• í”Œë¦¬ì¼€ì´ì…˜ì´ 없습니다."
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12808,6 +15446,15 @@ msgstr "ê³„ì •ì„ ë“±ë¡í•˜ë ¤ë©´ 서비스 약관 ë° ê°œì¸ ì •ë³´ 취급 ë°©ì
msgid "You must have maintainer access to force delete a lock"
msgstr "강제로 ìž ê¸ˆì„ ì œê±°í•˜ë ¤ë©´ ê´€ë¦¬ìž ê¶Œí•œì´ ìžˆì–´ì•¼í•©ë‹ˆë‹¤."
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12820,6 +15467,9 @@ msgstr ""
msgid "You need permission."
msgstr "ê¶Œí•œì´ í•„ìš”í•©ë‹ˆë‹¤."
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12832,6 +15482,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12865,6 +15518,9 @@ msgstr "ë‹¹ì‹ ì˜ í”„ë¡œí•„ì— %{add_ssh_key_link} 를 하기 ì „ì—는 SSH를 í
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "ë‹¹ì‹ ì˜ í”„ë¡œí•„ì— SSH 키를 등ë¡í•˜ê¸° 전까지 SSH를 통해 프로ì íŠ¸ë¥¼ 가져오거나 푸시할 수 없습니다."
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr "올바른 ë³€ê²½ì‚¬í•­ì„ ê°€ì ¸ì˜¤ë ¤ë©´ 다른 ì´ë¦„ì˜ ë¸Œëžœì¹˜ë¥¼ 사용해야합니다."
@@ -12886,27 +15542,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr "ì´ ì´ë©”ì¼ì„ 받는 ì´ìœ ëŠ” 사용ìžì˜ ê³„ì •ì´ %{host}ì— ìžˆê¸° 때문입니다. %{manage_notifications_link}&middot;%{help_link}"
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr "YouTube"
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr "ë‚˜ì˜ ê·¸ë£¹ë“¤"
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr "ì´ íŽ˜ì´ì§€ì—ì„œ Kubernetes í´ëŸ¬ìŠ¤í„° 정보를 계ì†í•´ì„œ 편집할 수 있지만, 비활성화 하거나 재설정하는 ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤."
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr "ë‹¹ì‹ ì˜ í”„ë¡œì íŠ¸ (기본값)"
msgid "Your Projects' Activity"
msgstr "ë‹¹ì‹ ì˜ í”„ë¡œì íŠ¸ 활ë™"
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr "ë‹¹ì‹ ì˜ í• ì¼"
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12940,8 +15620,11 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
-msgstr "ëŒ“ê¸€ì´ ê³µê°œì— í‘œì‹œë˜ì§€ 않습니다."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
+msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
msgstr ""
@@ -12958,6 +15641,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr "ê·€í•˜ì˜ ì´ë¦„"
@@ -12991,12 +15677,15 @@ msgstr "ì „"
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
-msgstr "다른 것들 중"
+msgid "already being used for another group or project milestone."
+msgstr ""
-msgid "at"
+msgid "already shared with this group"
msgstr ""
+msgid "among other things"
+msgstr "다른 것들 중"
+
msgid "attach a new file"
msgstr ""
@@ -13009,6 +15698,21 @@ msgstr "브랜치 ì´ë¦„"
msgid "by"
msgstr "by"
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13096,6 +15800,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13129,9 +15836,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13147,12 +15851,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr "설명"
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13269,9 +15967,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13288,10 +15983,10 @@ msgstr[0] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13333,6 +16028,9 @@ msgstr "ê°œì¸ í‚¤ë¥¼ ì½ì„ 수 없습니다. 암호가 맞습니까?"
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] "ì¼"
@@ -13360,9 +16058,15 @@ msgid "draft"
msgid_plural "drafts"
msgstr[0] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr "사용"
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13375,6 +16079,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr "%{slash_command} ëª…ë ¹ì€ ì˜ˆìƒì‹œê°„ì„ ê°€ìž¥ 마지막 명령으로 ì—…ë°ì´íŠ¸ 합니다."
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13399,6 +16109,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr "여기"
@@ -13427,6 +16140,12 @@ msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13436,6 +16155,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr "올바른 X509 ì¸ì¦ì„œê°€ 아닙니다."
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13454,6 +16176,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13479,6 +16204,9 @@ msgid "merge request"
msgid_plural "merge requests"
msgstr[0] "머지 리퀘스트(MR)"
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13506,7 +16234,7 @@ msgstr "%{metricsLinkStart} 메모리 사용률 %{metricsLinkEnd} ì´ %{memoryFr
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "%{metricsLinkStart} 메모리 사용률 %{metricsLinkEnd} ì´ %{memoryFrom}MB ì—ì„œ %{emphasisStart} 변하지 않았습니다. %{emphasisEnd}"
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13521,6 +16249,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13575,6 +16306,9 @@ msgstr "ë°°í¬ í†µê³„ë¥¼ ë¡œë“œí•˜ëŠ”ë° ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr "%{branch} 브랜치가 로컬 ì €ìž¥ì†Œì— ìžˆìœ¼ë©´ ì´ ë¨¸ì§€ 리퀘스트(MR)를 다ìŒê³¼ ê°™ì´ ìˆ˜ë™ìœ¼ë¡œ 머지할 수 있습니다."
@@ -13593,18 +16327,15 @@ msgstr "머지"
msgid "mrWidget|Merge failed."
msgstr "머지 실패."
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
+msgstr ""
+
msgid "mrWidget|Merge locally"
msgstr "로컬ì—ì„œ 머지"
-msgid "mrWidget|Merge request approved"
-msgstr "머지 리퀘스트(MR) 승ì¸ë¨"
-
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr "머지 리퀘스트(MR)승ì¸ë¨; 추가ì ìœ¼ë¡œ 승ì¸í•  수 있습니다."
-
msgid "mrWidget|Merged by"
msgstr "머지:"
@@ -13635,20 +16366,12 @@ msgstr "지금 새로고침"
msgid "mrWidget|Refreshing now"
msgstr "지금 새로고침 중"
-msgid "mrWidget|Remove your approval"
-msgstr "ë‚˜ì˜ ìŠ¹ì¸ ì œê±°"
+msgid "mrWidget|Remove from merge train"
+msgstr ""
msgid "mrWidget|Request to merge"
msgstr "머지 리퀘스트(MR)"
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] "%dê°œì˜ ì¶”ê°€ ìŠ¹ì¸ í•„ìš”"
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr "ì¶©ëŒ í•´ê²°"
@@ -13733,15 +16456,30 @@ msgstr "명령줄"
msgid "mrWidget|into"
msgstr "로"
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr "파ì´í”„ë¼ì¸ì´ 성공하면 ìžë™ìœ¼ë¡œ 머지ë©ë‹ˆë‹¤."
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr "해당 ì—†ìŒ"
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr "새 머지 리퀘스트(MR)"
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13846,7 +16584,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13855,18 +16593,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr "소스"
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} 소요 ëœ ì‹œê°„ì˜ í•©ê³„ë¥¼ ì—…ë°ì´íŠ¸í•©ë‹ˆë‹¤."
msgid "started"
msgstr "시작ë¨"
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13900,12 +16650,33 @@ msgstr "kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 사용하여 코드를 ë°°í¬í•©ë‹ˆë‹¤!"
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr "GitLabì—ì„œ 보기"
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "%{additions} ê°œì˜ ì¶”ê°€, %{deletions} ê°œì˜ ì‚­ì œê°€ 있습니다."
diff --git a/locale/mn_MN/gitlab.po b/locale/mn_MN/gitlab.po
index 9018bdd7cb2..07fea230372 100644
--- a/locale/mn_MN/gitlab.po
+++ b/locale/mn_MN/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Mongolian\n"
"Language: mn_MN\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: mn\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:29\n"
+"PO-Revision-Date: 2019-06-14 10:13\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,37 +1459,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1856,6 +2161,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/nb_NO/gitlab.po b/locale/nb_NO/gitlab.po
index e6e7657d028..3ee90cd308f 100644
--- a/locale/nb_NO/gitlab.po
+++ b/locale/nb_NO/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Norwegian Bokmal\n"
"Language: nb_NO\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: nb\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:29\n"
+"PO-Revision-Date: 2019-06-14 10:13\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,37 +1459,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1856,6 +2161,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/nl_NL/gitlab.po b/locale/nl_NL/gitlab.po
index b1cb8543b19..cb608bb36e6 100644
--- a/locale/nl_NL/gitlab.po
+++ b/locale/nl_NL/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Dutch\n"
"Language: nl_NL\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: nl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:37\n"
+"PO-Revision-Date: 2019-06-14 10:24\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr " Status"
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] "%d commits achterlopend"
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d exporter"
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] "%d merge request"
msgstr[1] "%d merge requests"
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d metriek"
msgstr[1] "%d statistieken"
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] "%d bepaalde wijziging"
@@ -131,11 +143,8 @@ msgstr "%{authorsName}'s discussie"
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} schreef %{commit_timeago}"
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artefacten, %{counter_lfs_objects} LFS)"
-
-msgid "%{count} %{alerts}"
-msgstr "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
+msgstr ""
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] "%{count} openstaande reactie"
msgstr[1] "%{count} openstaande reacties"
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr "%{filePath} verwijderd"
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}Groepen%{group_docs_link_end} stellen u in staat over meerdere projecten samen te werken en te beheren. Leden van een groep hebben toegang tot alle projecten."
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} wordt verwijderd! Weet je het zeker?"
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr "%{lock_path} is vergrendeld door GitLab Gebruiker %{lock_user_id}"
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr "%{name};'s avatar"
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] "%{text}%{files} bestanden"
msgid "%{text} is available"
msgstr "%{text} is beschikbaar"
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr "%{title} wijzigingen"
@@ -262,9 +310,29 @@ msgstr "%{usage_ping_link_start}Lees meer%{usage_ping_link_end} over welke infor
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr "- Runner is onderbroken en zal geen nieuwe taken ontvangen"
msgid "- show less"
msgstr "- toon minder"
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] "1 %{type} toevoeging"
@@ -305,14 +376,14 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
-msgstr[0] "1 gesloten issue"
-msgstr[1] "%d gesloten issues"
+msgid_plural "%{issues} closed issues"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
-msgstr[0] "1 gesloten merge request"
-msgstr[1] "%d gesloten merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 day"
msgstr ""
@@ -323,19 +394,19 @@ msgstr[0] "1 groep"
msgstr[1] "%d groepen"
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
-msgstr[0] "1 samengevoegde merge request"
-msgstr[1] "%d samengevoegde merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
-msgstr[0] "1 open issue"
-msgstr[1] "%d open issues"
+msgid_plural "%{issues} open issues"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
-msgstr[0] "1 open merge request"
-msgstr[1] "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 pipeline"
msgid_plural "%d pipelines"
@@ -355,15 +426,27 @@ msgstr[1] "%d gebruikers"
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr "1e bijdrage!"
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr "2FA ingeschakeld"
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr "Over GitLab"
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr "Account"
msgid "Account and limit"
msgstr "Account en limiet"
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr "Nieuwe map toevoegen"
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr "Uiterlijk"
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr "Applicatie"
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,37 +1459,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "BranchSwitcherPlaceholder|Zoek branches"
@@ -1856,6 +2161,21 @@ msgstr "Door bestanden bladeren"
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "door"
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr "Grafieken"
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr "Cherry-pick deze commit"
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr "overgeslagen"
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr "Opmerkingen"
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
+msgstr ""
+
+msgid "Failed to upgrade."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr "Geopend"
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
msgstr ""
-msgid "at"
+msgid "already shared with this group"
+msgstr ""
+
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/pa_IN/gitlab.po b/locale/pa_IN/gitlab.po
index 3fe2383be2c..271a784632a 100644
--- a/locale/pa_IN/gitlab.po
+++ b/locale/pa_IN/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Punjabi\n"
"Language: pa_IN\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: pa-IN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:28\n"
+"PO-Revision-Date: 2019-06-14 10:14\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,37 +1459,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1856,6 +2161,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/pl_PL/gitlab.po b/locale/pl_PL/gitlab.po
index cb99176aef0..ac3a92314ea 100644
--- a/locale/pl_PL/gitlab.po
+++ b/locale/pl_PL/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Polish\n"
"Language: pl_PL\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: pl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:30\n"
+"PO-Revision-Date: 2019-06-14 10:14\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -77,6 +74,13 @@ msgstr[3] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -126,6 +130,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -133,6 +144,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -163,10 +181,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -205,6 +220,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -217,12 +238,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -238,6 +271,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -256,6 +295,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -296,6 +347,9 @@ msgstr[3] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -308,9 +362,31 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -335,6 +411,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -357,14 +436,14 @@ msgstr[2] ""
msgstr[3] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -381,21 +460,21 @@ msgstr[2] ""
msgstr[3] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -425,15 +504,27 @@ msgstr[3] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -443,6 +534,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -473,6 +567,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr "<strong>%{changedFilesLength} niezarejestrowane</strong> i <strong>%{stagedFilesLength} zarejestrowane</strong> zmiany"
@@ -509,19 +606,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -551,6 +648,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -596,12 +696,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -638,6 +750,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -659,10 +774,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -671,9 +792,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -683,6 +810,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -695,9 +825,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -710,10 +849,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
+msgstr ""
+
+msgid "AddMember|No users specified."
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -722,10 +864,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -737,6 +888,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -758,6 +912,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -872,6 +1029,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -891,15 +1051,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -972,9 +1141,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -1008,10 +1174,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -1035,21 +1204,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr "Wystąpił błąd podczas pobierania oczekującego komentarza"
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -1065,6 +1249,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1098,7 +1285,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1152,6 +1342,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1209,9 +1402,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1221,6 +1420,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1230,6 +1435,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1248,6 +1456,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1297,12 +1517,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1333,6 +1547,18 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
+msgid "Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr ""
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to delete this list?"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
@@ -1354,18 +1580,6 @@ msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove approver %{name}?"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}?"
-msgstr ""
-
msgid "Are you sure you want to remove the attachment?"
msgstr ""
@@ -1381,6 +1595,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr "Czy na pewno chcesz zatrzymać to środowisko?"
@@ -1393,12 +1610,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1411,6 +1652,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1426,6 +1670,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1456,6 +1706,16 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1543,15 +1803,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr "Proces Automatyczny DevOps został włączony i będzie używany, jeśli nie zostanie znaleziony alternatywny plik konfiguracyjny CI. %{more_information_link}"
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1663,6 +1932,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1765,12 +2058,35 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1786,6 +2102,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1936,6 +2255,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1954,6 +2288,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -2044,9 +2381,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -2068,9 +2411,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2086,6 +2435,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2098,6 +2453,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2122,6 +2486,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2149,6 +2519,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2170,6 +2543,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2200,7 +2576,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2272,16 +2648,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2335,9 +2729,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2392,6 +2795,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2410,7 +2816,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2428,12 +2840,24 @@ msgstr "Dodaj integracjÄ™ klastra Kubernetes"
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr "Dodanie klastra Kubernetes do Twojej grupy spowoduje automatyczne udostępnienie klastra we wszystkich Twoich projektach. Korzystaj z aplikacji oceniających, wdrażaj aplikacje i łatwo uruchamiaj procesy dla wszystkich projektów korzystając z tego samego klastra."
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr "Dodanie integracji do Twojej grupy spowoduje udostępnienie klastra we wszystkich Twoich projektach."
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2449,6 +2873,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2557,6 +2984,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Projekt Platformy Google Cloud"
@@ -2593,19 +3023,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr "Wprowadzanie umożliwia kierowanie żądań do usług na podstawie hosta lub ścieżki żądania, centralizując szereg usług w jeden punkt początkowy."
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2638,6 +3059,9 @@ msgstr "Nazwa Domeny Knative:"
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2674,6 +3098,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2683,9 +3110,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2749,7 +3173,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2803,40 +3227,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2848,6 +3284,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2857,6 +3296,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2908,9 +3350,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2929,6 +3377,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -3050,6 +3501,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -3077,9 +3531,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3092,9 +3552,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3158,6 +3624,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3203,6 +3672,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3212,6 +3684,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3230,9 +3705,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3248,6 +3720,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3257,6 +3735,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3266,9 +3747,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3302,9 +3789,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3377,6 +3873,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3392,12 +3894,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3416,6 +3933,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3494,15 +4014,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3539,6 +4083,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3590,6 +4137,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3611,6 +4173,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3789,6 +4399,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3843,9 +4456,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3867,6 +4486,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3897,18 +4522,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3921,25 +4570,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3981,6 +4624,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -4017,6 +4663,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -4035,6 +4687,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -4059,9 +4714,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4086,6 +4771,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4122,9 +4810,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4155,12 +4840,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4173,7 +4864,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4185,9 +4879,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4323,18 +5041,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4371,9 +5122,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4383,6 +5140,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4392,6 +5155,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4401,6 +5167,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4434,9 +5206,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4533,6 +5311,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4620,6 +5401,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4629,27 +5431,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4668,6 +5503,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4680,16 +5521,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
+msgstr ""
+
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4704,6 +5557,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4767,7 +5626,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4779,9 +5638,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4864,6 +5720,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4912,6 +5774,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4921,6 +5786,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4945,6 +5813,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4990,6 +5864,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4999,6 +5882,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -5017,6 +5903,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -5047,12 +5936,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5410,6 +6305,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5467,6 +6368,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5476,6 +6380,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5548,6 +6455,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5566,9 +6476,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5644,6 +6563,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5653,6 +6575,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5680,13 +6605,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5698,9 +6626,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5731,9 +6656,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5797,6 +6731,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5866,6 +6803,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5893,6 +6833,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5902,12 +6845,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5917,6 +6863,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5933,6 +6882,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5948,6 +6903,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5957,6 +6918,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -6026,10 +6993,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6110,6 +7086,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6119,6 +7101,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6128,9 +7116,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6182,12 +7179,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6209,12 +7215,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6264,18 +7282,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6285,6 +7327,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6297,6 +7342,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6315,6 +7363,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6390,6 +7444,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6486,6 +7582,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6495,6 +7597,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6519,12 +7624,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6537,6 +7648,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6585,6 +7699,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6601,6 +7718,9 @@ msgstr[3] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6628,6 +7748,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6643,6 +7769,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6661,6 +7793,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6673,6 +7808,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6694,6 +7832,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6769,6 +7913,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6785,6 +7932,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6815,6 +7965,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6836,6 +7989,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6854,6 +8010,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6878,12 +8037,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6944,6 +8112,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6956,6 +8133,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6980,6 +8166,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -7010,6 +8199,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -7022,15 +8214,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -7040,12 +8226,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -7064,6 +8244,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -7082,6 +8286,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7094,6 +8301,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7127,7 +8337,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7142,6 +8352,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7157,6 +8373,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7196,9 +8415,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7244,9 +8460,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7271,9 +8499,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7292,7 +8517,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7301,6 +8526,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7322,6 +8556,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7382,6 +8628,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7394,6 +8658,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7491,6 +8758,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7515,6 +8785,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7545,6 +8818,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7554,12 +8833,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7575,6 +8863,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7599,6 +8890,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7620,9 +8914,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7638,6 +8929,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7665,6 +8959,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7713,6 +9013,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7728,6 +9031,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7737,6 +9046,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7791,6 +9103,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7806,6 +9121,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7821,7 +9142,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7846,13 +9173,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7870,6 +9197,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7915,6 +9245,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7939,9 +9275,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7963,6 +9296,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7972,6 +9308,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7999,6 +9341,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -8020,9 +9365,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -8035,7 +9392,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -8062,6 +9419,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -8083,12 +9443,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8167,6 +9542,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8176,10 +9554,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8200,6 +9581,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8260,6 +9644,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8290,6 +9677,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8299,12 +9695,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8335,6 +9749,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8347,6 +9764,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8368,7 +9794,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8386,12 +9812,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8407,12 +9887,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8440,15 +9926,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8479,6 +9974,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8500,6 +9998,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8512,6 +10013,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8539,6 +10043,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8548,9 +10064,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8560,18 +10082,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8590,9 +10127,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8608,13 +10142,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8629,6 +10166,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8650,6 +10190,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8743,6 +10286,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8788,6 +10334,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8839,6 +10388,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8848,18 +10415,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8869,12 +10478,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -9031,6 +10700,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -9049,16 +10727,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -9067,18 +10751,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9127,9 +10817,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9154,12 +10850,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9184,15 +10922,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9209,24 +10956,45 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9251,6 +11019,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9263,6 +11034,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9272,7 +11046,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9281,25 +11058,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9314,6 +11103,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9344,6 +11151,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9353,7 +11163,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9368,6 +11178,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9407,12 +11220,6 @@ msgstr "Wyniki podsumowania testu sÄ… analizowane"
msgid "Reports|Vulnerability"
msgstr "Wrażliwość"
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr "brak zmienionych wyników testów"
@@ -9467,6 +11274,12 @@ msgstr "Wymagaj od wszystkich użytkowników akceptacji Warunków Usługi i Poli
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9481,6 +11294,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9520,6 +11336,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9562,6 +11387,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9602,6 +11430,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr "Harmonogram"
@@ -9686,6 +11520,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9695,6 +11532,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9710,6 +11550,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9722,6 +11565,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9782,9 +11628,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9806,6 +11664,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9881,9 +11742,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9914,12 +11772,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9932,6 +11802,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9959,6 +11835,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9995,6 +11874,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -10076,6 +11958,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10106,19 +11991,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10136,6 +12024,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10157,6 +12048,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10184,6 +12078,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10199,6 +12105,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10211,9 +12120,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10229,9 +12147,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10287,12 +12202,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10302,6 +12235,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10311,6 +12247,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10380,6 +12319,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10398,6 +12340,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr "Coś poszło nie tak podczas pobierania kontrybucji członków grupy"
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10422,8 +12367,8 @@ msgstr "Coś poszło nie tak podczas rozwiązywania tej dyskusji. Spróbuj ponow
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr "Coś poszło nie tak, nie można dodać %{project} do pulpitu nawigacyjnego"
-msgid "Something went wrong, unable to get operations projects"
-msgstr "Coś poszło nie tak, nie można uzyskać projektów operacyjnych"
+msgid "Something went wrong, unable to get projects"
+msgstr ""
msgid "Something went wrong, unable to remove project"
msgstr "Coś poszło nie tak, nie można usunąć projektu"
@@ -10434,6 +12379,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr "Przepraszamy, żadne epiki nie pasują do Twoich wyszukiwań"
@@ -10494,6 +12442,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr "Mniej obciążenia"
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10548,6 +12499,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10620,6 +12577,9 @@ msgstr "Zaplanowane %{type}"
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr "Oznacz etykietę gwiazdką, by nadać jej status priorytetowy. Zorganizuj etykiety priorytetowe celem zmiany ich względnej ważności, poprzez przeciągnięcie."
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10644,6 +12604,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10674,6 +12637,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10734,12 +12703,18 @@ msgstr ""
msgid "Storage:"
msgstr "Przechowywanie:"
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr "Podgrupy i projekty"
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10770,6 +12745,9 @@ msgstr ""
msgid "Subscribed"
msgstr "Subskrybowany"
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10842,6 +12820,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10866,6 +12847,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10878,6 +12922,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr "Synchronizuj informacje"
@@ -10908,18 +12958,30 @@ msgstr "Metryki systemowe (Niestandardowe)"
msgid "System metrics (Kubernetes)"
msgstr "Metryki systemowe (Kubernetes)"
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -11001,6 +13063,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -11013,6 +13078,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -11028,6 +13096,33 @@ msgstr "Przetwarzanie pokrycia testowego"
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -11068,6 +13163,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr "Zakreślacz znaków pomaga ci utrzymać linię tematyczną do %{titleLength} znaków i zawinąć body do %{bodyLength}, aby można je było odczytać w git."
@@ -11083,6 +13181,9 @@ msgstr "Połączenie upłynie po %{timeout}. W przypadku repozytoriów, którym
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr "Wdrożenie tego zadania do %{environmentLink} nie powiodło się."
@@ -11140,6 +13241,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11158,6 +13268,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11182,9 +13298,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11194,6 +13322,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr "Zbiór danych pseudonimizera jest wyłączony. Po włączeniu GitLab uruchomi zadanie w tle, które będzie wytwarzać pseudonimiczne pliki CSV bazy danych GitLab, które zostaną przesłane do skonfigurowanego katalogu przechowywania obiektów."
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11203,6 +13334,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11242,6 +13376,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr "Akcja aktualizacji zakończy się po upływie %{number_of_minutes} minut. W przypadku dużych repozytoriów użyj kombinacji klonuj/pchnij."
@@ -11263,15 +13400,30 @@ msgstr "Mapa użytkownika to dokument JSON mapujący użytkowników Google Code,
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr "Mapa użytkownika to mapowanie użytkowników FogBugz, którzy uczestniczyli w Twoich projektach, w celu zaimportowania ich adresów e-mail i nazw użytkowników do GitLab. Możesz to zmienić, wypełniając poniższą tabelę."
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr "Nie ma jeszcze projektów zarchiwizowanych"
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11305,9 +13457,24 @@ msgstr "Brak zaplanowanych zmian"
msgid "There are no unstaged changes"
msgstr "Brak niezaplanowanych zmian"
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr "Wystąpił błąd podczas ładowania zadań do wykonania."
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11323,6 +13490,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11341,6 +13514,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11353,6 +13529,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11365,18 +13544,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11401,6 +13592,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11413,6 +13610,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11422,22 +13622,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11509,12 +13718,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11587,6 +13790,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11775,6 +13984,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11790,6 +14002,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11856,6 +14071,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11892,6 +14110,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11904,9 +14125,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11916,6 +14143,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11958,6 +14188,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -12009,15 +14275,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -12027,24 +14308,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -12063,18 +14362,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12144,6 +14458,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12195,6 +14521,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12204,6 +14533,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12222,6 +14554,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12231,6 +14611,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12288,6 +14674,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12303,6 +14692,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12378,6 +14902,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12393,9 +14926,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12441,12 +14992,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12456,6 +15013,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12465,6 +15025,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12492,6 +15055,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12519,6 +15085,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12561,6 +15154,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12579,6 +15175,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12588,6 +15187,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12609,6 +15211,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12618,13 +15223,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12640,6 +15248,9 @@ msgstr[3] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12820,6 +15431,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12835,7 +15449,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12847,6 +15467,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12862,6 +15485,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12880,6 +15509,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12904,9 +15542,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12937,12 +15581,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12952,6 +15605,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12982,6 +15641,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12994,6 +15662,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -13006,6 +15677,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -13039,6 +15713,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -13060,27 +15737,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -13114,7 +15815,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13132,6 +15836,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13165,10 +15872,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
msgstr ""
-msgid "at"
+msgid "already shared with this group"
+msgstr ""
+
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13183,6 +15893,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13288,6 +16013,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13321,9 +16049,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13339,12 +16064,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13467,9 +16186,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13489,10 +16205,10 @@ msgstr[3] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13534,6 +16250,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13570,9 +16289,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13585,6 +16310,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13609,6 +16340,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13640,6 +16374,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13649,6 +16389,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13667,6 +16410,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13695,6 +16441,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13722,7 +16471,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13737,6 +16486,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13791,6 +16543,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13809,18 +16564,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13851,26 +16603,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13955,15 +16693,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -14083,7 +16836,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -14092,18 +16845,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -14137,12 +16902,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
index 41d12896559..f73affc2cbc 100644
--- a/locale/pt_BR/gitlab.po
+++ b/locale/pt_BR/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Portuguese, Brazilian\n"
"Language: pt_BR\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: pt-BR\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-13 15:37\n"
+"PO-Revision-Date: 2019-06-14 10:11\n"
msgid " Please sign in."
msgstr " Por favor, entre usando sua conta."
-msgid " Status"
-msgstr " Status"
-
msgid " Try to %{action} this file again."
msgstr " Tentar %{action} este arquivo novamente."
@@ -67,6 +64,11 @@ msgstr[1] "%d commits atrás"
msgid "%d commits"
msgstr "%d commits"
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d exporter"
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] "%d merge request"
msgstr[1] "%d merge requests"
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d métrica"
msgstr[1] "%d métricas"
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] "mais %d comentário"
+msgstr[1] "mais %d comentários"
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] "%d mudança na lista de commit"
@@ -131,11 +143,8 @@ msgstr "Discussão de %{authorsName}"
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} fez commit %{commit_timeago}"
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr "%{counter_storage} (%{counter_repositories} repositórios, %{counter_build_artifacts} artefatos de build, %{counter_lfs_objects} LFS)"
-
-msgid "%{count} %{alerts}"
-msgstr "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
+msgstr ""
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] "%{count} comentário pendente"
msgstr[1] "%{count} comentários pendentes"
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr "%{edit_in_new_fork_notice} Tente fazer cherry-pick desse commit novamente."
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr "%{edit_in_new_fork_notice} Tente reverter este commit novamente."
+
msgid "%{filePath} deleted"
msgstr "%{filePath} excluído"
@@ -179,12 +194,24 @@ msgstr "%{gitlab_ci_yml} não encontrado neste commit"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}Grupos%{group_docs_link_end} permitem que você gerencie e colabore em vários projetos. Os membros de um grupo têm acesso a todos os seus projetos."
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr "%{group_name} usa contas gerenciadas por grupo. Você precisa criar uma nova conta do GitLab que será gerenciada por %{group_name}."
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} será removido! Você tem certeza?"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} indisponível"
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} é uma autoridade certificadora (CA) gratuita, automatizada e aberta, que fornece certificados digitais, afim de habilitar o HTTPS (SSL/TLS) para sites."
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr "%{level_name} não é permitido em um grupo %{group_level_name}."
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr "%{level_name} não é permitido, pois o projeto de origem do fork possui menor visibilidade."
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr "A visibilidade de %{level_name} foi restringida pelo administrador."
@@ -200,6 +227,12 @@ msgstr "%{lock_path} está bloqueado pelo usuário do GitLab %{lock_user_id}"
msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText}, essa issue foi fechada automaticamente."
+msgid "%{name} contained %{resultsString}"
+msgstr "%{name} continha %{resultsString}"
+
+msgid "%{name} found %{resultsString}"
+msgstr "%{name} encontrou %{resultsString}"
+
msgid "%{name}'s avatar"
msgstr "Avatar de %{name}"
@@ -218,6 +251,18 @@ msgstr "%{service_title} ativado."
msgid "%{service_title} settings saved, but not activated."
msgstr "Configurações de %{service_title} salvadas, mas não ativadas."
+msgid "%{size} GiB"
+msgstr "%{size} GiB"
+
+msgid "%{size} KiB"
+msgstr "%{size} KiB"
+
+msgid "%{size} MiB"
+msgstr "%{size} MiB"
+
+msgid "%{size} bytes"
+msgstr "%{size} bytes"
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr "%{spammable_titlecase} foi enviado para Akismet com sucesso."
@@ -250,6 +295,9 @@ msgstr[1] "%{text} %{files} arquivos"
msgid "%{text} is available"
msgstr "%{text} está disponível"
+msgid "%{title} %{operator} %{threshold}"
+msgstr "%{title} %{operator} %{threshold}"
+
msgid "%{title} changes"
msgstr "Alterações de %{title}"
@@ -262,9 +310,29 @@ msgstr "%{usage_ping_link_start}Saiba mais%{usage_ping_link_end} sobre quais inf
msgid "%{user_name} profile page"
msgstr "Página de perfil de %{user_name}"
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr "%{verb} %{time_spent_value} spent time."
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr "'%{level}' não é um nível de visibilidade válido"
+
+msgid "'%{source}' is not a import source"
+msgstr "'%{source}' não é uma fonte de importação"
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr "(Nenhuma mudança)"
+msgid "(check progress)"
+msgstr "(verificar progresso)"
+
msgid "(external source)"
msgstr "(fonte externa)"
@@ -289,6 +357,9 @@ msgstr "- O runner está pausado e não receberá nenhuma tarefa nova"
msgid "- show less"
msgstr "- exibir menos"
+msgid "0 for unlimited"
+msgstr "0 para ilimitado"
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] "1 adição de %{type}"
@@ -305,14 +376,14 @@ msgstr[0] "1 dia"
msgstr[1] "%d dias"
msgid "1 closed issue"
-msgid_plural "%d closed issues"
-msgstr[0] "1 issue fechada"
-msgstr[1] "%d issues fechadas"
+msgid_plural "%{issues} closed issues"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
-msgstr[0] "1 merge request fechado"
-msgstr[1] "%d merge requests fechados"
+msgid_plural "%{merge_requests} closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 day"
msgstr "1 dia"
@@ -323,19 +394,19 @@ msgstr[0] "1 grupo"
msgstr[1] "%d grupos"
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
-msgstr[0] "1 merge request com merge"
-msgstr[1] "%d merge requests com merge"
+msgid_plural "%{merge_requests} merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
-msgstr[0] "1 issue aberta"
-msgstr[1] "%d issues abertas"
+msgid_plural "%{issues} open issues"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
-msgstr[0] "1 merge request aberto"
-msgstr[1] "%d merge request aberto"
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 pipeline"
msgid_plural "%d pipelines"
@@ -355,15 +426,27 @@ msgstr[1] "%d usuários"
msgid "1 week"
msgstr "1 semana"
+msgid "1-9 contributions"
+msgstr "1-9 contribuições"
+
+msgid "10-19 contributions"
+msgstr "10-19 contribuições"
+
msgid "1st contribution!"
msgstr "1ª contribuição!"
+msgid "20-29 contributions"
+msgstr "20-29 contribuições"
+
msgid "2FA"
msgstr "A2F"
msgid "2FA enabled"
msgstr "Autenticação de 2 passos ativada"
+msgid "2FADevice|Registered On"
+msgstr "Registrado em"
+
msgid "3 days"
msgstr "3 dias"
@@ -373,6 +456,9 @@ msgstr "3 horas"
msgid "30 minutes"
msgstr "30 minutos"
+msgid "30+ contributions"
+msgstr "30+ contribuições"
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr "Por favor entre em contato com o seu administrador do GitLab para obter permissão."
@@ -403,6 +489,9 @@ msgstr "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> adicio
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> adicionará \"Por <a href=\"#\">johnsmith@example.com</a>\" a todas as issues e comentários originalmente criados por johnsmith@example.com. Por padrão, o endereço de e-mail ou nome de usuário é mascarado para garantir a privacidade do usuário. Use esta opção se você quiser mostrar o endereço de e-mail completo."
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr "<strong>%{changedFilesLength} fora da lista de commit</strong> e <strong>%{stagedFilesLength} na lista de commit</strong>"
@@ -439,20 +528,20 @@ msgstr "Um site Hugo que usa Netlify para CI/CD em vez do Gitlab, mas ainda com
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr "Um site Jekyll que usa Netlify para CI/CD em vez do Gitlab, mas ainda com todas as outras ótimas funcionalidades do Gitlab."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
+msgstr "Uma conta Let's Encrypt será configurada para esta instalação do GitLab usando seu endereço de e-mail. Você receberá e-mails para avisar sobre certificados expirados."
+
msgid "A default branch cannot be chosen for an empty project."
msgstr "Um branch padrão não pode ser escolhido para um projeto vazio."
msgid "A deleted user"
msgstr "Um usuário excluído"
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr "Um membro da equipe de abusos GitLab irá rever a sua avaliação assim que possível."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
+msgstr "Um fork é uma cópia de um projeto.<br />Fork de um repositório permite que você faça alterações sem afetar o projeto original."
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
-msgstr "Um commit de merge é criado para cada merge, e só é permitido o merge desde que não haja conflito."
-
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
-msgstr "Um commit de merge é criado para cada merge, mas só é permitido o merge se merge de fast-forward for possível. Dessa forma, você pode se certificar de que, se essa merge request compilaria com sucesso, após o merge para o branch destino ela também compilaria."
+msgid "A member of the abuse team will review your report as soon as possible."
+msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr "Um novo \"branch\" será criado no seu \"fork\" e um novo merge request será iniciado."
@@ -481,6 +570,9 @@ msgstr "Um usuário com permissão de escrita no branch de origem selecionou est
msgid "API Help"
msgstr "Ajuda da API"
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr "Sobre o GitLab"
@@ -526,12 +618,24 @@ msgstr "Acesso proibido. Verifique seu nível de acesso."
msgid "Access to '%{classification_label}' not allowed"
msgstr "Acesso a '%{classification_label}' não permitido"
+msgid "AccessDropdown|Groups"
+msgstr "Grupos"
+
+msgid "AccessDropdown|Roles"
+msgstr "Cargos"
+
+msgid "AccessDropdown|Users"
+msgstr "Usuários"
+
msgid "Account"
msgstr "Conta"
msgid "Account and limit"
msgstr "Conta e limites"
+msgid "Account: %{account}"
+msgstr "Conta: %{account}"
+
msgid "Action to take when receiving an alert."
msgstr "Ação a ser tomada ao receber um alerta."
@@ -568,6 +672,9 @@ msgstr "Adicionar cluster Kubernetes"
msgid "Add README"
msgstr "Adicionar README"
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr "Adicionar uma lista de marcadores"
@@ -589,11 +696,17 @@ msgstr "Adicionar uma tabela"
msgid "Add a task list"
msgstr "Adicionar uma lista de tarefas"
+msgid "Add a todo"
+msgstr "Adicionar tarefa"
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Coloque um texto adicional para aparecer em todas as comunicações por email. Limite de %{character_limit} caracteres"
-msgid "Add approver(s)"
-msgstr "Adicionar aprovador(es)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
+msgstr "Adicionar uma issue"
msgid "Add approvers"
msgstr "Adicionar aprovadores"
@@ -601,9 +714,15 @@ msgstr "Adicionar aprovadores"
msgid "Add bold text"
msgstr "Adicionar texto em negrito"
+msgid "Add child epic to an epic"
+msgstr "Adicionar épico filho a um épico"
+
msgid "Add comment now"
msgstr "Adicionar comentário"
+msgid "Add email address"
+msgstr "Adicionar endereço de e-mail"
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "Adicione cabeçalho e rodapé aos emails. Por favor, note que as configurações de cor só serão aplicadas dentro da interface do aplicativo"
@@ -613,6 +732,9 @@ msgstr "Adicionar comentário de imagem"
msgid "Add italic text"
msgstr "Adicionar texto em itálico"
+msgid "Add label(s)"
+msgstr "Adicionar etiqueta(s)"
+
msgid "Add license"
msgstr "Adicionar licença"
@@ -625,9 +747,18 @@ msgstr "Adicionar novo aplicativo"
msgid "Add new directory"
msgstr "Adicionar novo diretório"
+msgid "Add or subtract spent time"
+msgstr "Adicionar ou subtrair tempo gasto"
+
msgid "Add reaction"
msgstr "Adicionar reação"
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr "Adicionar ao projeto"
@@ -640,23 +771,35 @@ msgstr "Adicionar tarefa"
msgid "Add user(s) to the group:"
msgstr "Adicionar usuário(s) ao grupo:"
-msgid "Add users or groups who are allowed to approve every merge request"
-msgstr "Adicionar usuários ou grupos com permissão para aprovar todos os merge request"
-
msgid "Add users to group"
msgstr "Adicionar usuários ao grupo"
+msgid "AddMember|No users specified."
+msgstr "Não há usuários especificados."
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
+msgstr "Muitos usuários especificados (o limite é %{user_limit})"
+
msgid "Added at"
msgstr "Adicionado em"
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr "A adição de novos aplicativos está desativada na sua instância do GitLab. Entre em contato com seu administrador do GitLab para obter a permissão"
+msgid "Additional minutes"
+msgstr "Minutos adicionais"
+
msgid "Additional text"
msgstr "Texto adicional"
-msgid "Aditional minutes"
-msgstr "Minutos adicionais"
+msgid "Adds"
+msgstr "Adiciona"
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr "Adiciona %{epic_ref} como épico filho."
+
+msgid "Adds a todo."
+msgstr "Adiciona uma tarefa."
msgid "Admin Area"
msgstr "Ãrea do Administrador"
@@ -667,6 +810,9 @@ msgstr "Visão Geral do Administrador"
msgid "Admin Section"
msgstr "Seção de Admin"
+msgid "Admin notes"
+msgstr "Notas de administração"
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr "Você está prestes a excluir permanentemente o usuário %{username}. Issues, merge requests, e grupos vinculados a ele serão transferidos para um \"usuário fantasma\" em todo o sistema. Para evitar a perda de dados, considere o uso do recurso %{strong_start}bloquear usuário%{strong_end}. Depois de %{strong_start}Deletar o usuário%{strong_end}, não será possível desfazer ou recuperá-lo."
@@ -688,6 +834,9 @@ msgstr "Erro ao parar tarefas"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "Você parará todas as tarefas. Os processos em execução serão abruptamente interrompidos."
+msgid "AdminNote|Note"
+msgstr "Nota"
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr "Você está prestes a excluir permanentemente o projeto %{projectName}, seu repositório e todos os recursos relacionados, incluindo issues, merge requests, etc. Uma vez que você confirmar e pressionar %{strong_start}Excluir projeto%{strong_end}, este não poderá ser desfeito ou recuperado."
@@ -802,6 +951,9 @@ msgstr "Configurações avançadas"
msgid "After a successful password update you will be redirected to login screen."
msgstr "Após uma atualização de senha bem-sucedida, você será redirecionado para a tela de login."
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "Alerta"
@@ -819,15 +971,24 @@ msgstr "Todos os membros"
msgid "All changes are committed"
msgstr "Houve commit com todas as mudanças"
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Todos os recursos estão habilitados para projetos em branco, a partir de modelos ou ao importar, mas você pode desativá-los posteriormente nas configurações do projeto."
+msgid "All groups and projects"
+msgstr "Todos os grupos e projetos"
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr "Todas as issues para este marco estão fechadas. Você pode fechar este marco agora."
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr "Todos os conflitos de merge foram resolvidos. A merge request pode agora ter o merge realizado."
+msgid "All projects"
+msgstr "Todos os projetos"
+
msgid "All todos were marked as done."
msgstr "Todos os afazeres foram marcados como concluídos."
@@ -900,9 +1061,6 @@ msgstr "Alternativamente, você pode usar um %{personal_access_token_link}. Quan
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr "Quantidade de tempo (em horas) que os usuários podem ignorar a configuração forçada da autenticação de dois fatores"
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr "Uma chave SSH será gerada automaticamente quando o formulário for enviado. Para mais informações, consulte a documentação."
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr "Um aplicativo chamado %{link_to_client} está solicitando acesso à sua conta do GitLab."
@@ -936,12 +1094,15 @@ msgstr "Erro ao pré-visualizar o blob"
msgid "An error occurred when toggling the notification subscription"
msgstr "Erro ao modificar notificação de assinatura"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr "Ocorreu um erro ao tentar resolver um comentário. Por favor, tente novamente."
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr "Ocorreu um erro ao tentar resolver uma discussão. Por favor, tente novamente."
+
msgid "An error occurred when updating the issue weight"
msgstr "Ocorreu um erro ao atualizar o peso do issue"
-msgid "An error occurred while adding approver"
-msgstr "Ocorreu um erro ao adicionar o aprovador"
-
msgid "An error occurred while deleting the approvers group"
msgstr "Ocorreu um erro ao excluir o grupo de aprovadores"
@@ -963,21 +1124,36 @@ msgstr "Erro ao remover alerta. Atualize a página e tente novamente."
msgid "An error occurred while enabling Service Desk."
msgstr "Um erro ocorreu ao habilitar a Central de Serviços."
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr "Ocorreu um erro ao buscar cores de rótulo."
+
msgid "An error occurred while fetching markdown preview"
msgstr "Erro ao gerar pré-visualização do markdown"
msgid "An error occurred while fetching pending comments"
msgstr "Ocorreu um erro ao recuperar os comentários pendentes"
+msgid "An error occurred while fetching projects autocomplete."
+msgstr "Ocorreu um erro ao buscar o autocomplemento de projetos."
+
msgid "An error occurred while fetching sidebar data"
msgstr "Erro ao recuperar informações da barra lateral"
-msgid "An error occurred while fetching stages."
-msgstr "Ocorreu um erro o enquanto busca estágios."
-
msgid "An error occurred while fetching the Service Desk address."
msgstr "Um erro ocorreu ao consultar o endereço da Central de Serviços."
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr "Ocorreu um erro ao buscar lista de painéis. Por favor, tente novamente."
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr "Ocorreu um erro na recuperação de logs da tarefa."
@@ -993,6 +1169,9 @@ msgstr "Erro ao recuperar informações da pipeline."
msgid "An error occurred while fetching the releases. Please try again."
msgstr "Ocorreu um erro ao buscar as releases. Por favor, tente novamente."
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr "Erro ao recuperar projetos"
@@ -1026,8 +1205,11 @@ msgstr "Um erro ocorreu ao carregar os detalhes da inscrição."
msgid "An error occurred while making the request."
msgstr "Erro ao fazer a requisição."
-msgid "An error occurred while removing approver"
-msgstr "Ocorreu um erro ao remover o aprovador"
+msgid "An error occurred while moving the issue."
+msgstr "Ocorreu um erro ao mover issue."
+
+msgid "An error occurred while parsing recent searches"
+msgstr "Ocorreu um erro ao analisar as pesquisas recentes"
msgid "An error occurred while removing epics."
msgstr "Ocorreu um erro ao remover épicos."
@@ -1080,6 +1262,9 @@ msgstr "Ocorreu um erro ao buscar o rastreamento do trabalho."
msgid "An error occurred whilst fetching the latest pipeline."
msgstr "Ocorreu um erro ao recuperar o último pipeline."
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr "Erro ao carregar todos os arquivos."
@@ -1137,9 +1322,15 @@ msgstr "Qualquer um"
msgid "Any Label"
msgstr "Qualquer etiqueta"
+msgid "Any Milestone"
+msgstr "Qualquer marco"
+
msgid "Any encrypted tokens"
msgstr "Qualquer tokens criptografados"
+msgid "Any namespace"
+msgstr "Qualquer namespace"
+
msgid "Appearance"
msgstr "Aparência"
@@ -1149,6 +1340,12 @@ msgstr "Aparência criada com sucesso."
msgid "Appearance was successfully updated."
msgstr "A aparência foi atualizada com sucesso."
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr "Anexar o comentário com %{TABLEFLIP}"
+
+msgid "Append the comment with %{shrug}"
+msgstr "Anexar o comentário com %{shrug}"
+
msgid "Application"
msgstr "Aplicativo"
@@ -1158,6 +1355,9 @@ msgstr "ID da aplicação"
msgid "Application settings saved successfully"
msgstr "As configurações do aplicativo foram salvas com sucesso"
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr "Aplicativo desinstalado, mas falhou em destruir: %{error_message}"
+
msgid "Application was successfully destroyed."
msgstr "Aplicação foi destruída com sucesso."
@@ -1176,10 +1376,22 @@ msgstr "Aplicado"
msgid "Apply suggestion"
msgstr "Aplicar sugestão"
+msgid "Applying command"
+msgstr "Aplicando comando"
+
+msgid "Applying command to %{commandDescription}"
+msgstr "Aplicando comando a %{commandDescription}"
+
+msgid "Applying multiple commands"
+msgstr "Aplicando vários comandos"
+
+msgid "Applying suggestion"
+msgstr "Aplicando sugestão"
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d membro"
+msgstr[1] "%d membros"
msgid "ApprovalRuleRemove|Approvals from this member are not revoked."
msgid_plural "ApprovalRuleRemove|Approvals from these members are not revoked."
@@ -1217,12 +1429,6 @@ msgstr "por exemplo, QA, segurança, etc."
msgid "Approvals"
msgstr "Aprovações"
-msgid "Approvals required"
-msgstr "Aprovações necessárias"
-
-msgid "Approvers"
-msgstr "Aprovadores"
-
msgid "Apr"
msgstr "Abr"
@@ -1253,6 +1459,18 @@ msgstr "Tem certeza que deseja arquivar este projeto?"
msgid "Are you sure that you want to unarchive this project?"
msgstr "Tem certeza que deseja desarquivar este projeto?"
+msgid "Are you sure you want to cancel creating this comment?"
+msgstr "Tem certeza de que deseja cancelar a criação deste comentário?"
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr "Tem certeza de que deseja cancelar a edição deste comentário?"
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to delete this list?"
+msgstr "Você tem certeza que deseja excluir esta lista?"
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Tem certeza que deseja excluir este agendamento de pipeline?"
@@ -1266,7 +1484,7 @@ msgid "Are you sure you want to lose your issue information?"
msgstr "Você deseja mesmo perder as informações da sua issue?"
msgid "Are you sure you want to permanently delete this license?"
-msgstr ""
+msgstr "Tem certeza que deseja excluir permanentemente esta licença?"
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr "Tem certeza de que deseja regenerar a chave pública? Você precisará atualizar a chave pública no servidor remote antes que o espelhamento funcione novamente."
@@ -1274,18 +1492,6 @@ msgstr "Tem certeza de que deseja regenerar a chave pública? Você precisará a
msgid "Are you sure you want to remove %{group_name}?"
msgstr "Você tem certeza que quer remover %{group_name}?"
-msgid "Are you sure you want to remove approver %{name}"
-msgstr "Você deseja mesmo remover o aprovador %{name}"
-
-msgid "Are you sure you want to remove approver %{name}?"
-msgstr "Você deseja mesmo remover o aprovador %{name}?"
-
-msgid "Are you sure you want to remove group %{name}"
-msgstr "Você deseja mesmo remover o grupo %{name}"
-
-msgid "Are you sure you want to remove group %{name}?"
-msgstr "Você deseja mesmo remover o grupo %{name}?"
-
msgid "Are you sure you want to remove the attachment?"
msgstr "Você deseja mesmo remover o anexo?"
@@ -1296,11 +1502,14 @@ msgid "Are you sure you want to reset registration token?"
msgstr "Você tem certeza que quer recriar o token de registro?"
msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
+msgstr "Tem certeza de que deseja redefinir o token SCIM? O provisionamento SCIM irá parar de funcionar até que o novo token seja atualizado."
msgid "Are you sure you want to reset the health check token?"
msgstr "Você tem certeza que quer reiniciar o token de status de saúde?"
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr "Você tem certeza de que deseja parar este ambiente?"
@@ -1313,12 +1522,36 @@ msgstr "Tem certeza de que deseja cancelar o recebimento do %{type}: %{link_to_n
msgid "Are you sure?"
msgstr "Você tem certeza?"
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr "ID do artefato"
msgid "Artifacts"
msgstr "Artefatos"
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr "%{user} enviou para o branch %{branch} do projeto %{project_name} ( %{commit_url} ):"
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr "Asana - Trabalho em equipe sem e-mail"
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr "Lista de branches separados por vírgulas que serão automaticamente inspecionados. Deixe em branco para incluir todos os branches."
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr "Token de acesso pessoal do usuário. O usuário deve ter acesso à tarefa, todos os comentários serão atribuídos a este usuário."
+
msgid "Ascending"
msgstr "Ascendente"
@@ -1331,6 +1564,9 @@ msgstr "URL de serviço do consumidor de asserção"
msgid "Assets"
msgstr "Recursos"
+msgid "Assign"
+msgstr "Atribuir"
+
msgid "Assign custom color like #FF0000"
msgstr "Coloque uma cor personalizada, como #FF0000"
@@ -1346,6 +1582,12 @@ msgstr "Atribua alguns issues a este marco."
msgid "Assign to"
msgstr "Atribuir à"
+msgid "Assign yourself to these issues"
+msgstr "Atribuir-se a essas issues"
+
+msgid "Assign yourself to this issue"
+msgstr "Atribuir-se a essa issue"
+
msgid "Assigned Issues"
msgstr "Problemas Atribuídos"
@@ -1376,6 +1618,14 @@ msgstr "Anexar um arquivo"
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Para anexar arquivo, arraste e solte ou %{upload_link}"
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr "Falha ao anexar o arquivo."
+
msgid "Audit Events"
msgstr "Eventos de Auditoria"
@@ -1463,15 +1713,24 @@ msgstr "Saiba mais em %{link_to_documentation}"
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr "A pipeline de Auto DevOps foi ativada e será usada se não for encontrada configuração CI alternativa nos arquivos. %{more_information_link}"
-msgid "Automatically marked as default internal user"
-msgstr "Marcado automaticamente como interno de usuário padrão"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically marked as default internal user"
+msgstr "Marcado automaticamente como interno de usuário padrão"
+
msgid "Automatically resolved"
msgstr "Resolvido automaticamente"
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr "Atualiza automaticamente os branches e tags deste projeto do repositório upstream a cada hora."
+
+msgid "Autosave|Note"
+msgstr "Nota"
+
msgid "Available"
msgstr "Disponível"
@@ -1583,6 +1842,30 @@ msgstr "Seus selos"
msgid "Badges|e.g. %{exampleUrl}"
msgstr "por exemplo, %{exampleUrl}"
+msgid "Badge|New"
+msgstr "Novo"
+
+msgid "Balsamiq file could not be loaded."
+msgstr "O arquivo Balsamiq não pôde ser carregado."
+
+msgid "BambooService|A continuous integration and build server"
+msgstr "Um servidor de integração e build contínua"
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr "Um usuário com acesso à API, se aplicável"
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr "Atlassian Bamboo CI"
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr "Chave de plano de build Bambu como KEY"
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr "URL raiz de bambu como https://bamboo.exemplo.com"
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr "Você precisa configurar etiquetas de revisão automáticas e um gatilho de repositório no Bamboo."
+
msgid "BatchComments|Delete all pending comments"
msgstr "Excluir todos os comentários pendentes"
@@ -1685,12 +1968,31 @@ msgstr "Bloquear"
msgid "Blocked"
msgstr "Bloqueado"
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr "Blog"
+msgid "Blue helpers indicate an action to be taken."
+msgstr "Auxiliares azuis indicam uma ação a ser tomada."
+
msgid "Boards"
msgstr "Painéis"
+msgid "Boards|Edit board"
+msgstr "Editar painel"
+
+msgid "Boards|View scope"
+msgstr "Ver escopo"
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "O branch %{branchName} não foi encontrado no repositório deste projeto."
@@ -1706,6 +2008,9 @@ msgstr "Branch já utilizada"
msgid "Branch name"
msgstr "Nome da branch"
+msgid "Branch not loaded - %{branchId}"
+msgstr "Branch não carregado - %{branchId}"
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Procurar por branches"
@@ -1836,10 +2141,10 @@ msgid "Branches|protected"
msgstr "protegido"
msgid "Broadcast Message was successfully created."
-msgstr ""
+msgstr "Transmissão de messagem foi criada com sucesso."
msgid "Broadcast Message was successfully updated."
-msgstr ""
+msgstr "Transmissão de messagem foi atualizada com sucesso."
msgid "Browse Directory"
msgstr "Navegar no Diretório"
@@ -1856,6 +2161,21 @@ msgstr "Navegar pelos arquivos"
msgid "Built-in"
msgstr "Embutido"
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr "Negócios"
@@ -1874,6 +2194,9 @@ msgstr "Por %{user_name}"
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr "Por padrão, o GitLab envia e-mails em formatos HTML e texto plano para que os clientes possam escolher o formato a ser utilizado. Desative esta opção se você quiser apenas enviar e-mails em formato de texto plano."
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr "Por padrão, todos os projetos e grupos usarão as configurações de notificações globais."
+
msgid "ByAuthor|by"
msgstr "por"
@@ -1929,7 +2252,7 @@ msgid "CICD|Default to Auto DevOps pipeline"
msgstr "Padrão para o pipeline Auto DevOps"
msgid "CICD|Default to Auto DevOps pipeline for all projects"
-msgstr ""
+msgstr "Padrão para pipeline de Auto DevOps para todos os projetos"
msgid "CICD|Deployment strategy"
msgstr "Estratégia de deploy"
@@ -1944,7 +2267,7 @@ msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration
msgstr "O pipeline de Auto DevOps será executado se nenhum arquivo de configuração de IC alternativo for encontrado."
msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
-msgstr ""
+msgstr "Você precisa adicionar uma %{kubernetes_cluster_start}integração de cluster Kubernetes%{kubernetes_cluster_end} a este projeto com um domínio para que sua estratégia de deploy funcione corretamente."
msgid "CICD|group enabled"
msgstr "grupo habilitado"
@@ -1964,9 +2287,15 @@ msgstr "Pode substituir aprovadores e aprovações necessárias por merge reques
msgid "Can't find HEAD commit for this branch"
msgstr "Não é possível encontrar o commit HEAD para este branch"
+msgid "Can't find variable: ZiteReader"
+msgstr "Não foi possível encontrar a variável: ZiteReader"
+
msgid "Can't remove group members without group managed account"
msgstr "Não é possível remover membros do grupo sem uma conta gerenciada do grupo"
+msgid "Can't scan the code?"
+msgstr "Não consegue escanear o código?"
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr "Canary Deployments é uma estratégia popular em CI onde uma pequena porção da frota é atualizada para a nova versão do seu aplicativo."
@@ -1980,19 +2309,25 @@ msgid "Cannot be merged automatically"
msgstr "Não pode ser feito o merge automaticamente"
msgid "Cannot create the abuse report. The user has been deleted."
-msgstr ""
+msgstr "Não é possível criar o relatório de abuso. O usuário foi excluído."
msgid "Cannot create the abuse report. This user has been blocked."
-msgstr ""
+msgstr "Não é possível criar o relatório de abuso. Este usuário foi bloqueado."
msgid "Cannot modify managed Kubernetes cluster"
msgstr "Não se pode modificar um cluster Kubernetes gerenciado"
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr "Não é possível se referir a um marco de grupo por um Id interno!"
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr "Não é possível renderizar a imagem. A contagem máxima de caracteres (%{charLimit}) foi excedida."
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr "Não foi possível mostrar a pré-visualização. Para pré-visualizações em arquivos de sketch, eles devem ter o formato de arquivo introduzido pela versão 43 ou superior do Sketch."
+
msgid "Cannot skip two factor authentication setup"
-msgstr ""
+msgstr "Não é possível ignorar a configuração de autenticação de dois fatores"
msgid "Capacity threshold"
msgstr "Limite de capacidade"
@@ -2006,6 +2341,12 @@ msgstr "Certificado (PEM)"
msgid "Change Weight"
msgstr "Alterar Peso"
+msgid "Change assignee(s)"
+msgstr "Alterar responsável(eis)"
+
+msgid "Change assignee(s)."
+msgstr "Alterar responsável(eis)."
+
msgid "Change path"
msgstr "Alterar caminho"
@@ -2018,6 +2359,15 @@ msgstr "Mudar modelo"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "Altere esse valor para influenciar com que frequência a interface do usuário do GitLab pesquisa atualizações."
+msgid "Change title"
+msgstr "Alterar Título"
+
+msgid "Change your password"
+msgstr "Altere sua senha"
+
+msgid "Change your password or recover your current one"
+msgstr "Altere sua senha ou recupere sua senha atual"
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "Pick para um branch"
@@ -2042,6 +2392,12 @@ msgstr "Mudanças serão mostradas se revisão de <b>origem</b> tiver sofrido me
msgid "Changes suppressed. Click to show."
msgstr "Alterações suprimidas. Clique para mostrar."
+msgid "Changes the title to \"%{title_param}\"."
+msgstr "Altera o título para \"%{title_param}\"."
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr "As alterações não ocorrerão até que o índice seja %{link_start}recriado%{link_end}."
+
msgid "Charts"
msgstr "Gráficos"
@@ -2069,6 +2425,9 @@ msgstr "Verificando status de aprovação"
msgid "Checking branch availability..."
msgstr "Verificando disponibilidade de branch..."
+msgid "Checking username availability..."
+msgstr "Verificando disponibilidade do nome de usuário..."
+
msgid "Cherry-pick this commit"
msgstr "Cherry-pick esse commit"
@@ -2090,6 +2449,9 @@ msgstr "Escolha um arquivo"
msgid "Choose a role permission"
msgstr "Escolha uma permissão de cargo"
+msgid "Choose a template"
+msgstr "Escolha um modelo"
+
msgid "Choose a template..."
msgstr "Escolha um modelo..."
@@ -2120,8 +2482,8 @@ msgstr "Escolha quais repositórios você deseja se conectar e executar pipeline
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr "Escolha quais shards você deseja sincronizar nesse nó secundário."
-msgid "Choose your merge method, set up a default merge request description template."
-msgstr "Escolha o seu método de merge, configure um modelo de descrição do merge request padrão."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
+msgstr ""
msgid "CiStatusLabel|canceled"
msgstr "cancelado"
@@ -2192,17 +2554,35 @@ msgstr "ignorado"
msgid "CiStatus|running"
msgstr "executando"
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr "Não é possível usar a variável mascarada com o valor atual"
+
msgid "CiVariables|Input variable key"
msgstr "Digite o nome da variável"
msgid "CiVariables|Input variable value"
msgstr "Digite o valor da variável"
+msgid "CiVariables|Key"
+msgstr "Chave"
+
+msgid "CiVariables|Masked"
+msgstr "Mascarada"
+
msgid "CiVariables|Remove variable row"
msgstr "Remover a variável"
-msgid "CiVariables|This variable will not be masked"
-msgstr ""
+msgid "CiVariables|Scope"
+msgstr "Escopo"
+
+msgid "CiVariables|State"
+msgstr "Estado"
+
+msgid "CiVariables|Type"
+msgstr "Tipo"
+
+msgid "CiVariables|Value"
+msgstr "Valor"
msgid "CiVariable|* (All environments)"
msgstr "* (Todos os ambientes)"
@@ -2214,10 +2594,10 @@ msgid "CiVariable|Create wildcard"
msgstr "Criar curinga"
msgid "CiVariable|Error occurred while saving variables"
-msgstr ""
+msgstr "CiVariable|Ocorreu um erro ao salvar variáveis"
msgid "CiVariable|Masked"
-msgstr ""
+msgstr "Mascarada"
msgid "CiVariable|New environment"
msgstr "Novo ambiente"
@@ -2238,7 +2618,7 @@ msgid "CiVariable|Validation failed"
msgstr "Falha na validação"
msgid "Classification Label (optional)"
-msgstr ""
+msgstr "Etiqueta de Classificação (opcional)"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "está indisponível: %{reason}"
@@ -2255,9 +2635,18 @@ msgstr "Limpar Pesquisa"
msgid "Clear search input"
msgstr "Limpar campo de pesquisa"
+msgid "Clear weight"
+msgstr "Limpar peso"
+
+msgid "Clears weight."
+msgstr "Limpa o peso."
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr "Clique em qualquer <strong>nome de projeto</strong> na lista a seguir para navegar para o marco do projeto."
+msgid "Click here"
+msgstr "Clique aqui"
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr "Clique no botão <strong>Baixar</strong> e aguarde a conclusão do download."
@@ -2312,6 +2701,9 @@ msgstr "Fechar épico"
msgid "Close milestone"
msgstr "Fechar marco"
+msgid "Close sidebar"
+msgstr "Fechar barra lateral"
+
msgid "Closed"
msgstr "Fechado"
@@ -2325,19 +2717,25 @@ msgid "ClusterIntegration| can be used instead of a custom domain."
msgstr " pode ser usado em vez de um domínio personalizado."
msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
+msgstr " é o escopo do ambiente padrão para este cluster. Isso significa que todos os trabalhos, independentemente do ambiente, usarão esse cluster. %{environment_scope_start}Mais informação%{environment_scope_end}"
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} foi instalado com sucesso no seu cluster Kubernetes"
-msgid "ClusterIntegration|%{title} upgraded successfully."
-msgstr ""
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr "%{title} desinstalado com sucesso."
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr "%{title} atualizado com sucesso."
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
+msgstr "Um token de serviço com escopo definido como %{code}kube-system%{end_code} com privilégios de %{code}cluster-admin%{end_code}."
msgid "ClusterIntegration|API URL"
msgstr "API URL"
msgid "ClusterIntegration|API URL should be a valid http/https url."
-msgstr ""
+msgstr "A URL da API deve ser uma url http/https válida."
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr "Adicionar cluster Kubernetes"
@@ -2348,12 +2746,24 @@ msgstr "Adicionar uma integração com cluster Kubernetes"
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr "Adicionando um cluster kubernetes no seu grupo, irá compartilhar automaticamente o cluster entre todos os seus projetos. Utilize apps de revisão, faça deploy de suas aplicações e rode facilmente suas pipelines para todos os seus projetos usando o mesmo cluster."
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr "A adição de um cluster kubernetes irá compartilhar automaticamente o cluster entre todos os projetos. Utilize apps de revisão, faça deploy de suas aplicações e rode facilmente suas pipelines para todos os seus projetos usando o mesmo cluster."
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr "Adicionando uma integração ao seu grupo irá compartilhar o cluster entre todos os seus projetos."
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr "A adição de uma integração irá compartilhar o cluster entre todos os projetos."
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Opções avançadas na integração deste cluster Kubernetes"
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr "Todos os dados serão excluídos e não poderão ser restaurados."
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr "Permite que o GitLab gerencie contas serviços e namespaces para esse cluster."
+
msgid "ClusterIntegration|Alternatively"
msgstr "Alternativamente"
@@ -2361,22 +2771,25 @@ msgid "ClusterIntegration|An error occurred when trying to contact the Google Cl
msgstr "Ocorreu um erro ao entrar em contato com a Google Cloud API. Por favor, tente novamente mais tarde."
msgid "ClusterIntegration|An error occurred while trying to fetch project zones: %{error}"
-msgstr ""
+msgstr "Ocorreu um erro ao tentar realizar o fetch de zonas do projeto: %{error}"
msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
-msgstr ""
+msgstr "Ocorreu um erro ao tentar realizar o fetch de seus projetos: %{error}"
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
-msgstr ""
+msgstr "Ocorreu um erro ao tentar realizar o fetch dos tipos de máquinas da zona: %{error}"
+
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr "Quaisquer pipelines em execução serão cancelados."
msgid "ClusterIntegration|Applications"
-msgstr "Aplicações"
+msgstr "Aplicativos"
msgid "ClusterIntegration|Apply for credit"
msgstr "Inscreva-se para receber créditos"
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
-msgstr "Tem certeza de que deseja remover a integração deste cluster do Kubernetes? Isso não excluirá o seu cluster atual do Kubernetes."
+msgstr "Tem certeza de que deseja remover a integração deste cluster Kubernetes? Isso não excluirá o seu cluster Kubernetes atual."
msgid "ClusterIntegration|Base domain"
msgstr "Domínio base"
@@ -2385,16 +2798,16 @@ msgid "ClusterIntegration|CA Certificate"
msgstr "Certificado CA"
msgid "ClusterIntegration|Cert-Manager"
-msgstr ""
+msgstr "Cert-Manager"
msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
-msgstr ""
+msgstr "Cert-Manager é um controlador de gerenciamento de certificados nativo do Kubernetes que ajuda na emissão de certificados. A instalação do Cert-Manager em seu cluster emitirá um certificado por %{letsEncrypt} e garantirá que os certificados sejam válidos e atualizados."
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "Pacote de autoridade certificadora (Formato PEM)"
msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
-msgstr "Escolha quais aplicativos instalar em seu cluster do Kubernetes. O Helm Tiller é necessário para instalar qualquer um dos seguintes aplicativos."
+msgstr "Escolha quais aplicativos instalar em seu cluster Kubernetes. O Helm Tiller é necessário para instalar qualquer um dos seguintes aplicativos."
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "Escolha quais dos seus ambientes usarão esse cluster."
@@ -2403,10 +2816,10 @@ msgid "ClusterIntegration|Cluster health"
msgstr "Saúde do cluster"
msgid "ClusterIntegration|Cluster name is required."
-msgstr ""
+msgstr "O nome do cluster é obrigatório."
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
-msgstr ""
+msgstr "Clusters são utilizados selecionando o ancestral mais próximo de um ambiente de escopo correspondente. Por exemplo, projeto de clusters vai substituir grupo de clusters."
msgid "ClusterIntegration|Copy API URL"
msgstr "Copiar URL da API"
@@ -2415,19 +2828,19 @@ msgid "ClusterIntegration|Copy CA Certificate"
msgstr "Copiar certificado CA"
msgid "ClusterIntegration|Copy Ingress Endpoint to clipboard"
-msgstr ""
+msgstr "Copiar o Endereço IP de Ingress para a área de transferência"
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr "Copiar nome do host Jupyter para a área de transferência"
msgid "ClusterIntegration|Copy Knative Endpoint to clipboard"
-msgstr ""
+msgstr "ClusterIntegration|Copiar Knative Endpoint para área de transferência"
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr "Copiar nome do cluster Kubernetes"
msgid "ClusterIntegration|Copy Service Token"
-msgstr ""
+msgstr "Copiar Token de Serviço"
msgid "ClusterIntegration|Create Kubernetes cluster"
msgstr "Integração de Clusters | Criar cluster Kubernetes"
@@ -2436,7 +2849,7 @@ msgid "ClusterIntegration|Did you know?"
msgstr "Você sabia?"
msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
-msgstr "Ative ou desative connexão do GitLab com seu cluster Kubernetes."
+msgstr "Ative ou desative conexão do GitLab com seu cluster Kubernetes."
msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
msgstr "Habilite esta configuração se estiver usando o controle de acesso baseado em função (RBAC)."
@@ -2454,7 +2867,7 @@ msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster:
msgstr ""
msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
-msgstr ""
+msgstr "Falha ao requisitar ao Google Cloud Platform: %{message}"
msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr "Gitlab Runner"
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr "Cluster gerenciado pelo GitLab"
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Google Cloud Platform projeto"
@@ -2502,31 +2918,22 @@ msgid "ClusterIntegration|If you are setting up multiple clusters and are using
msgstr "Se você está configurando múltiplos clusters e você está usando auto DevOps, %{help_link_start}leia isso primeiro%{help_link_end}."
msgid "ClusterIntegration|In order to view the health of your cluster, you must first install Prometheus below."
-msgstr ""
+msgstr "Para visualizar a saúde do seu cluster, você deve primeiro instalar o Prometheus abaixo."
msgid "ClusterIntegration|Ingress"
msgstr "Ingressar"
msgid "ClusterIntegration|Ingress Endpoint"
-msgstr ""
+msgstr "Ingress Endpoint"
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr "Ingress oferece uma maneira de rotear solicitações para serviços com base no host ou caminho da solicitação, centralizando diversos serviços em um único ponto de entrada."
-msgid "ClusterIntegration|Install"
-msgstr "Instalar"
-
-msgid "ClusterIntegration|Installed"
-msgstr "Instalado"
-
-msgid "ClusterIntegration|Installing"
-msgstr "Instalando"
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
-msgstr ""
+msgstr "Instalação do Ingress poderá incorrer em custos adicionais. Saiba mais %{pricingLink}."
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
-msgstr ""
+msgid "ClusterIntegration|Instance cluster"
+msgstr "Cluster de instância"
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
msgstr "Integrar automação de cluster Kubernetes"
@@ -2538,7 +2945,7 @@ msgid "ClusterIntegration|Issuer Email"
msgstr ""
msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
-msgstr ""
+msgstr "Emissores representam uma autoridade certificadora. Você deve fornecer um endereço de e-mail do seu Emissor."
msgid "ClusterIntegration|Jupyter Hostname"
msgstr "Nome do host Jupyter"
@@ -2556,10 +2963,13 @@ msgid "ClusterIntegration|Knative Domain Name:"
msgstr "Nome de domínio Knative:"
msgid "ClusterIntegration|Knative Endpoint:"
+msgstr "Knative Endpoint:"
+
+msgid "ClusterIntegration|Knative domain name was updated successfully."
msgstr ""
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
-msgstr ""
+msgstr "Knative estende Kubernetes para fornecer um conjunto de componentes de middleware que são essenciais para construir aplicativos modernos, centrados em fontes e baseados em contêineres que podem ser executados em qualquer lugar: no local, na nuvem ou até mesmo em um datacenter de terceiros."
msgid "ClusterIntegration|Kubernetes cluster"
msgstr "Cluter Kubernetes"
@@ -2594,6 +3004,9 @@ msgstr "Saiba mais sobre os Kubernetes"
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr "Saiba mais sobre grupo de cluster Kubernetes"
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr "Saiba mais sobre instância de cluster Kubernetes"
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr "Let's Encrypt"
@@ -2603,9 +3016,6 @@ msgstr "Tipo de máquina"
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr "Tenha certeza de que sua conta %{link_to_requirements} para criar clusters Kubernetes"
-msgid "ClusterIntegration|Manage"
-msgstr "Gerenciar"
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr "Gerenciar seu cluster Kubernetes visitando %{link_gke}"
@@ -2625,7 +3035,7 @@ msgid "ClusterIntegration|Number of nodes"
msgstr "Número de nós"
msgid "ClusterIntegration|Number of nodes must be a numerical value."
-msgstr ""
+msgstr "O número de nós deve ser um valor numérico."
msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
msgstr "Por favor, entre com as informações de acesso para seu cluter Kubernetes. Se precisar de ajuda, você pode ler nosso %{link_to_help_page} em Kubernetes"
@@ -2634,7 +3044,7 @@ msgid "ClusterIntegration|Please make sure that your Google account meets the fo
msgstr "Por favor, tenha certeza que sua conta no Google cumpre com os requisitos:"
msgid "ClusterIntegration|Point a wildcard DNS to this generated endpoint in order to access your application after it has been deployed."
-msgstr ""
+msgstr "Aponte um DNS curinga para este endpoint gerado para acessar seu aplicativo após ele ter sido implantado."
msgid "ClusterIntegration|Project cluster"
msgstr "Cluster do Projeto"
@@ -2669,8 +3079,8 @@ msgstr "Substitua isso por seu próprio nome de host, se desejar. Se você fizer
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "Solicitação para início de instalação falhou"
-msgid "ClusterIntegration|Retry update"
-msgstr ""
+msgid "ClusterIntegration|Request to begin uninstalling failed"
+msgstr "Solicitação para início de desinstalação falhou"
msgid "ClusterIntegration|Save changes"
msgstr "Salvar alterações"
@@ -2685,7 +3095,7 @@ msgid "ClusterIntegration|Search zones"
msgstr "Pesquisar zonas"
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
-msgstr "Veja e edite os detalhes de seus cluster Kubernates"
+msgstr "Veja e edite os detalhes de seus cluster Kubernetes"
msgid "ClusterIntegration|Select machine type"
msgstr "Selecionar tipo de máquina"
@@ -2706,10 +3116,10 @@ msgid "ClusterIntegration|Select zone to choose machine type"
msgstr "Selecione a zone para escolher o tipo de máquina"
msgid "ClusterIntegration|Service Token"
-msgstr ""
+msgstr "Token de serviço"
msgid "ClusterIntegration|Service token is required."
-msgstr ""
+msgstr "Token de serviço é necessário."
msgid "ClusterIntegration|Show"
msgstr "Mostrar"
@@ -2723,10 +3133,34 @@ msgstr "Erro ao criar cluster Kubernetes no Google Kubernetes Engine"
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "Algo deu errado ao instalar %{title}"
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr "Algo deu errado ao desinstalar %{title}"
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgstr "A especificação de um domínio permitirá que você use os estágios do Auto Review Apps e do Auto Deploy para %{auto_devops_start}Auto DevOps%{auto_devops_end}. O domínio deve ter um DNS curinga configurado correspondente ao domínio."
+
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
+msgstr "O certificado do Kubernetes usado para autenticar no cluster."
+
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
+msgstr "A URL usada para acessar a API do Kubernetes."
+
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
+msgstr "O IP associado será excluído e não poderá ser restaurado."
+
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
+msgstr "O certificado associado será excluído e não poderá ser restaurado."
+
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
+msgstr "O balanceador de carga e o IP associados serão excluídos e não poderão ser restaurados."
+
msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr "O endpoint está em processo de atribuição. Verifique o seu cluster Kubernetes ou Quotas no Google Kubernetes Engine se demorar muito."
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
@@ -2741,24 +3175,12 @@ msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "Alternar cluster Kubernetes"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr "Desinstalar %{appTitle}"
+
msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
-msgid "ClusterIntegration|Updating"
-msgstr "Atualizando"
-
-msgid "ClusterIntegration|Upgrade"
-msgstr "Atualizar"
-
-msgid "ClusterIntegration|Upgrade failed"
-msgstr "Falha na atualização"
-
-msgid "ClusterIntegration|Upgraded"
-msgstr "Atualizado"
-
-msgid "ClusterIntegration|Upgrading"
-msgstr "Atualizando"
-
msgid "ClusterIntegration|Validating project billing status"
msgstr "Validando status de faturamento do projeto"
@@ -2768,6 +3190,9 @@ msgstr "Não foi possível verificar se um dos seus projetos no GCP possui o fat
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "Com um cluster Kubernetes associado a esse projeto, você pode utilizar apps de revisão, publicar suas aplicações, executar suas pipelines e muito mais de um jeito simples."
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr "Você deve primeiro instalar o Helm Tiller antes de instalar os aplicativos abaixo"
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "Sua conta precisa de %{link_to_kubernetes_engine}"
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr "Zona"
@@ -2828,9 +3256,15 @@ msgstr "Recolher aprovadores"
msgid "Collapse sidebar"
msgstr "Minimizar barra lateral"
+msgid "ComboSearch is not defined"
+msgstr "ComboSearch não está definido"
+
msgid "Command line instructions"
msgstr "Instruções de linha de comando"
+msgid "Commands applied"
+msgstr "Comandos aplicados"
+
msgid "Comment"
msgstr "Comentário"
@@ -2849,6 +3283,9 @@ msgstr "Comentar e marcar a discussão como não resolvida"
msgid "Comment form position"
msgstr "Posição do formulário de comentários"
+msgid "Comment is being updated"
+msgstr "O comentário está sendo atualizado"
+
msgid "Comments"
msgstr "Comentários"
@@ -2963,11 +3400,14 @@ msgid "Confidentiality"
msgstr "Confidencialidade"
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
-msgstr ""
+msgstr "Configure os runners do GitLab para começar a usar o Terminal da Web. %{helpStart}Saiba mais.%{helpEnd}"
msgid "Configure Gitaly timeouts."
msgstr "Configurar timeouts do Gitaly."
+msgid "Configure Let's Encrypt"
+msgstr "Configurar Let's Encrypt"
+
msgid "Configure Tracing"
msgstr "Configurar rastreamento"
@@ -2995,9 +3435,15 @@ msgstr "Configurar a forma como o usuário cria uma nova conta."
msgid "Confirm"
msgstr "Confirmar"
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr "Confirmação necessária"
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr "Parabéns! Você ativou a autenticação de dois fatores!"
+
msgid "Connect"
msgstr "Conectar"
@@ -3010,9 +3456,15 @@ msgstr "Conectar repositórios do GitHub"
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr "Conecte seus repositórios externos e pipelines CI/CD vão ser executados para novos commits. Um projeto GitLab será criado com apenas recursos de CI/CD ativados."
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr "Conectando..."
+msgid "Connection failure"
+msgstr "Falha na conexão"
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr "Com o Container Registry do Docker integrado ao Gitlab, todo projeto pod
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr "Você pode usar também um %{deploy_token} para acesso somente-leitura às imagens do registry."
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr "Conteúdo de .gitlab-ci.yml"
@@ -3121,6 +3576,9 @@ msgstr "Commits à %{branch_name}, excluindo commits de merge. Limitado à 6000
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr "Por favor, espere um momento, essa página será atualizada automaticamente."
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr "Controle a exibição de ofertas de terceiros."
@@ -3130,6 +3588,9 @@ msgstr "Controlar a concorrência máxima do enchimento do repositório para ess
msgid "ConvDev Index"
msgstr "Ãndice ConvDev"
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr "Copiar URL de clone do %{http_label}"
@@ -3148,9 +3609,6 @@ msgstr "Copiar URL de Clone do SSH"
msgid "Copy SSH public key"
msgstr "Copiar chave pública SSH"
-msgid "Copy SSH public key to clipboard"
-msgstr "Copiar chave pública SSH para área de transferência"
-
msgid "Copy URL to clipboard"
msgstr "Copiar URL para área de transferência"
@@ -3166,6 +3624,12 @@ msgstr "Copiar SHA do commit para a área de transferência"
msgid "Copy file path to clipboard"
msgstr "Copiar o local do arquivo para a área de transferência"
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr "Copiar link"
@@ -3175,6 +3639,9 @@ msgstr "Copiar referência para área de transferência"
msgid "Copy secret to clipboard"
msgstr "Copiar segredo para a área de transferência"
+msgid "Copy source to clipboard"
+msgstr "Copiar fonte para área de transferência"
+
msgid "Copy to clipboard"
msgstr "Copiar para área de transferência"
@@ -3184,14 +3651,20 @@ msgstr "Copiar token para a área de transferência"
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr "Não foi possível mudar o HEAD: o branch \"%{branch}\" não existe"
+
msgid "Could not connect to FogBugz, check your URL"
+msgstr "Não foi possível se conectar a FogBugz, verifique sua URL"
+
+msgid "Could not connect to Web IDE file mirror service."
msgstr ""
msgid "Could not create Wiki Repository at this time. Please try again later."
-msgstr ""
+msgstr "Não foi possível criar o repositório Wiki no momento. Por favor, tente novamente mais tarde."
msgid "Could not delete chat nickname %{chat_name}."
-msgstr ""
+msgstr "Não foi possível excluir o apelido de bate-papo %{chat_name}."
msgid "Could not remove the trigger."
msgstr "Não foi possível remover o gatilho."
@@ -3220,9 +3693,18 @@ msgstr "Criar novo domínio"
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr "Criar uma nova branch"
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr "Criar uma nova issue"
@@ -3295,6 +3777,12 @@ msgstr "Criar etiqueta de projeto"
msgid "Create your first page"
msgstr "Crie sua primeira página"
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr "Tag"
@@ -3310,12 +3798,27 @@ msgstr "Criado em"
msgid "Created by me"
msgstr "Criado por mim"
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr "Criado em"
msgid "Created on:"
msgstr "Criado em:"
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr "Criando epic"
@@ -3334,6 +3837,9 @@ msgstr "Projeto atual"
msgid "Current node"
msgstr "Nó atual"
+msgid "Current password"
+msgstr "Senha atual"
+
msgid "CurrentUser|Profile"
msgstr "Perfil"
@@ -3344,7 +3850,7 @@ msgid "Custom CI config path"
msgstr "Caminho de configuração do IC personalizado"
msgid "Custom hostname (for private commit emails)"
-msgstr "Hostname personalizado (para e-mails de commit privado)"
+msgstr "Nome de host personalizado (para e-mails de commit privado)"
msgid "Custom notification events"
msgstr "Eventos de notificação personalizados"
@@ -3412,15 +3918,39 @@ msgstr "Todos"
msgid "DashboardProjects|Personal"
msgstr "Pessoal"
+msgid "DashboardProjects|Trending"
+msgstr "Tendências"
+
msgid "Dashboards"
msgstr "Dashboards"
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr "%{firstProject} e %{secondProject}"
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr "%{firstProject}, %{rest} e %{secondProject}"
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr "Não foi possível adicionar %{invalidProjects}. Esse dashboard está disponível para projetos públicos, e projetos privados em grupos com um plano Gold."
+
msgid "Data is still calculating..."
msgstr "Os dados ainda estão a ser calculados..."
msgid "Date picker"
msgstr "Seletor de data"
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr "Depurar"
@@ -3446,7 +3976,7 @@ msgid "Default classification label"
msgstr "Etiqueta de classificação padrão"
msgid "Default description template for issues"
-msgstr ""
+msgstr "Modelo de descrição padrão para issues"
msgid "Default first day of the week"
msgstr "Primeiro dia da semana padrão"
@@ -3455,6 +3985,9 @@ msgid "Default first day of the week in calendars and date pickers."
msgstr "Primeiro dia da semana padrão em calendários e selecionadores de data."
msgid "Default issue template"
+msgstr "Modelo de issue padrão"
+
+msgid "Default project deletion protection"
msgstr ""
msgid "Default: Directly import the Google Code email address or username"
@@ -3497,7 +4030,7 @@ msgid "Delete comment"
msgstr "Excluir comentário"
msgid "Delete license"
-msgstr ""
+msgstr "Excluir licença"
msgid "Delete list"
msgstr "Excluir lista"
@@ -3508,27 +4041,90 @@ msgstr "Excluir branch de origem"
msgid "Delete this attachment"
msgstr "Excluir este anexo"
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr "Excluído"
msgid "Deleted chat nickname: %{chat_name}!"
-msgstr ""
+msgstr "Apelido de bate-papo excluído: %{chat_name}!"
msgid "Deleting the license failed."
-msgstr ""
+msgstr "A exclusão da licença falhou."
msgid "Deleting the license failed. The license was not found."
-msgstr ""
+msgstr "A exclusão da licença falhou. A licença não foi encontrada."
msgid "Deleting the license failed. You are not permitted to perform this action."
-msgstr ""
+msgstr "A exclusão de licença falhou. Você não tem permissão para executar essa ação."
msgid "Denied authorization of chat nickname %{user_name}."
-msgstr ""
+msgstr "Negada autorização do apelido de bate-papo %{user_name}."
msgid "Deny"
msgstr "Recusar"
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr "Proxy de Dependências"
+
+msgid "Dependency proxy"
+msgstr "Proxy de dependências"
+
+msgid "Dependency proxy URL"
+msgstr "URL de proxy de dependências"
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "Implantação"
@@ -3538,7 +4134,7 @@ msgid "Deploy Keys"
msgstr "Chaves para deploy"
msgid "Deploy key was successfully updated."
-msgstr ""
+msgstr "A chave de deploy foi atualizada com sucesso."
msgid "DeployKeys|+%{count} others"
msgstr "+%{count} outros"
@@ -3679,7 +4275,7 @@ msgid "Description"
msgstr "Descrição"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
-msgstr ""
+msgstr "Descrição analisada com %{link_start}GitLab Flavored Markdown%{link_end}"
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr "Os modelos de descrição permitem que você defina modelos específicos de contexto para os campos de descrição de merge request e emissão para seu projeto."
@@ -3688,31 +4284,34 @@ msgid "Description:"
msgstr "Descrição:"
msgid "DesignManagement|%{current_design} of %{designs_count}"
-msgstr ""
+msgstr "%{current_design} de %{designs_count}"
msgid "DesignManagement|Could not find design, please try again."
-msgstr ""
+msgstr "Não foi possível encontrar o design. Por favor, tente novamente."
msgid "DesignManagement|Error uploading a new design. Please try again"
-msgstr ""
+msgstr "Erro ao enviar um novo design. Por favor, tente novamente."
msgid "DesignManagement|Go back to designs"
-msgstr ""
+msgstr "Voltar para designs"
msgid "DesignManagement|Go to next design"
-msgstr ""
+msgstr "Ir para o próximo design"
msgid "DesignManagement|Go to previous design"
+msgstr "Ir para o design anterior"
+
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
msgid "DesignManagement|The one place for your designs"
msgstr ""
msgid "DesignManagement|Upload and view the latest designs for this issue. Consistent and easy to find, so everyone is up to date."
-msgstr ""
+msgstr "Envie e veja os designs mais recentes para este issue. Consistente e fácil de encontrar, de forma que todos estejam atualizados."
msgid "DesignManagement|Upload designs"
-msgstr ""
+msgstr "Enviar designs"
msgid "Designs"
msgstr "Designs"
@@ -3759,9 +4358,15 @@ msgstr "Desabilitar runners de grupo"
msgid "Disable shared Runners"
msgstr "Desativar Runners compartilhados"
+msgid "Disable two-factor authentication"
+msgstr "Desativar autenticação de dois fatores"
+
msgid "Disabled"
msgstr "Desativado"
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr "Os espelhos desativados só podem ser ativados por donos de instâncias. É recomendável que você os exclua."
+
msgid "Discard"
msgstr "Descartar"
@@ -3783,6 +4388,12 @@ msgstr "Descartar rascunho"
msgid "Discard review"
msgstr "Descartar revisão"
+msgid "DiscordService|Discord Notifications"
+msgstr "Notificações do Discord"
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr "Receber notificações de eventos no Discord"
+
msgid "Discover GitLab Geo"
msgstr "Descubra o GitLab Geo"
@@ -3813,18 +4424,42 @@ msgstr "Descartar promoção de Merge Request"
msgid "Dismiss trial promotion"
msgstr "Ignorar promoção de avaliação"
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr "Deseja personalizar como os endereços de e-mail e nomes de usuário do Google Code são importados para o GitLab?"
+msgid "Dockerfile"
+msgstr "Dockerfile"
+
msgid "Documentation for popular identity providers"
msgstr "Documentação para provedores de identidade populares"
msgid "Domain"
msgstr "Domínio"
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr "Não exibir novamente"
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr "Pronto"
@@ -3837,26 +4472,20 @@ msgstr "Baixar artefatos"
msgid "Download asset"
msgstr "Baixar recurso"
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
-msgstr ""
+msgid "Download export"
+msgstr "Baixar exportação"
-msgid "Download tar.gz"
-msgstr ""
+msgid "Download license"
+msgstr "Baixar licença"
-msgid "Download zip"
-msgstr ""
+msgid "Download source code"
+msgstr "Baixar código-fonte"
-msgid "DownloadArtifacts|Download"
-msgstr ""
+msgid "Download this directory"
+msgstr "Baixar este diretório"
msgid "DownloadCommit|Email Patches"
msgstr "Email com as mudanças"
@@ -3897,6 +4526,9 @@ msgstr "Editar etiqueta"
msgid "Edit Milestone"
msgstr "Editar marco"
+msgid "Edit Password"
+msgstr "Editar senha"
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "Alterar Agendamento do Pipeline %{id}"
@@ -3933,6 +4565,12 @@ msgstr "Editar chave de deploy pública"
msgid "Elasticsearch"
msgstr "Elasticsearch"
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr "Integração com Elasticsearch. Elasticsearch AWS IAM."
@@ -3951,6 +4589,9 @@ msgstr "Endereço de e-mail"
msgid "Email patch"
msgstr "Patch de email"
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr "E-mails"
+msgid "Emails separated by comma"
+msgstr "E-mails separados por vírgula"
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr "Embutido"
@@ -4002,6 +4673,9 @@ msgstr "Ativar autenticação SAML para esse grupo"
msgid "Enable Sentry for error reporting and logging."
msgstr "Ativar Sentry para report de erro e log."
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr "Habilitar e configurar métricas InfluxDB."
@@ -4038,9 +4712,6 @@ msgstr "Ativar reCAPTCHA ou Akismet e definir seus limites de IP."
msgid "Enable shared Runners"
msgstr "Ativar Runners partilhados"
-msgid "Enable the Performance Bar for a given group."
-msgstr "Ative a barra de desempenho para um determinado grupo."
-
msgid "Enable two-factor authentication"
msgstr "Ativar autenticação de dois fatores"
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr "Termina em (UTC)"
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr "Digite o seu URL do servidor do Bitbucket e o token de acesso pessoal abaixo"
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr "Digite a descrição da issue"
@@ -4089,7 +4766,10 @@ msgstr "Digite a descrição do merge request"
msgid "Enter the merge request title"
msgstr "Digite o título do merge request"
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr "Ambiente:"
msgid "Environments"
msgstr "Ambientes"
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr "Os ambientes permitem que você acompanhe as implantações do seu aplicativo %{link_to_read_more}."
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr "Adicionar um projeto ao dashboard"
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr "Adicionar projetos"
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr "Dashboard de Ambientes"
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr "Tarefa: %{job}"
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr "Mais ações"
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr "Remover"
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr "O dashboard de ambientes fornece um resumo do status dos ambientes de cada projeto, incluindo status de pipelines e alertas."
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "Um erro ocorreu ao recuperar ambientes."
@@ -4239,18 +4943,51 @@ msgstr "Roadmap de epics"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr "Epics permitem gerenciar seu portfólio de projetos de forma mais eficiente e com menos esforço"
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr "Como posso resolver isso?"
msgid "Epics|More information"
msgstr "Mais informações"
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr "Essas datas afetam a maneira como seus épicos aparecem no planejamento. As datas dos marcos vêm dos marcos atribuídos aos problemas do épico. Você também pode definir datas fixas ou removê-las completamente."
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr "Para agendar o seu épico %{epicDateType} baseado em marcos temporais, atribua um marco com uma data %{epicDateType} a qualquer issue no épico."
@@ -4287,9 +5024,15 @@ msgstr "Erro ao carregar etiquetas."
msgid "Error fetching network graph."
msgstr "Erro ao recuperar gráfico de rede."
+msgid "Error fetching projects"
+msgstr "Erro ao obter projetos"
+
msgid "Error fetching refs"
msgstr "Erro ao recuperar refs"
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr "Erro ao recupera dados de ping."
@@ -4299,6 +5042,12 @@ msgstr "Erro ao carregar dados de branch. Por favor, tente novamente."
msgid "Error loading branches."
msgstr "Erro ao carregar os branches."
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr "Erro ao carregar o visualizador de arquivos."
+
msgid "Error loading last commit."
msgstr "Erro ao carregar último commit."
@@ -4308,6 +5057,9 @@ msgstr "Erro ao carregar a pré-visualização do markdown"
msgid "Error loading merge requests."
msgstr "Erro ao carregar merge requests."
+msgid "Error loading milestone tab"
+msgstr "Erro ao carregar a aba de marco"
+
msgid "Error loading project data. Please try again."
msgstr "Erro ao carregar dados do projeto. Por favor, tente novamente."
@@ -4317,6 +5069,12 @@ msgstr "Erro ao carregar os tipos de modelo."
msgid "Error loading template."
msgstr "Erro ao carregar o modelo."
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr "Erro ao alterar configuração de notificação de assinatura"
@@ -4350,9 +5108,15 @@ msgstr "Erro ao atualizar status das tarefas."
msgid "Error uploading file"
msgstr "Erro ao enviar o arquivo"
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr "Erro ao carregar o merge request. Por favor, tente novamente."
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,9 +5213,12 @@ msgstr "Tudo o que você precisa para criar um site do GitLab Pages usando o Jek
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr "Tudo o que você precisa para criar um site do GitLab Pages usando HTML simples."
-msgid "Except policy:"
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
+msgid "Except policy:"
+msgstr "Exceto da política:"
+
msgid "Existing members and groups"
msgstr "Membros e grupos existentes"
@@ -4471,7 +5238,7 @@ msgid "Expiration date"
msgstr "Data de validade"
msgid "Expired"
-msgstr ""
+msgstr "Expirado"
msgid "Expired %{expiredOn}"
msgstr "Expirou %{expiredOn}"
@@ -4510,7 +5277,7 @@ msgid "Export project"
msgstr "Exportar projeto"
msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
-msgstr ""
+msgstr "Exporte este projeto com todos os dados relacionados para mover seu projeto para uma nova instância do GitLab. Quando a exportação estiver concluída, você poderá importar o arquivo da página \"Novo projeto\"."
msgid "External Classification Policy Authorization"
msgstr "Autorização de Política de Classificação Externa"
@@ -4536,6 +5303,27 @@ msgstr "Etiqueta de classificação"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "Quando nenhum etiqueta de classificação está definida, a etiqueta padrão `%{default_label}` será usada."
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr "Adicione um botão ao dashboard de métricas vinculado diretamente aos seus dashboards externos existentes."
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr "Digite a URL do dashboard ao qual você deseja vincular"
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr "Dashboard externo"
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr "URL completa de dashboard"
+
+msgid "ExternalWikiService|External Wiki"
+msgstr "Wiki externo"
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr "Substitui o link para o wiki interno por um link para um wiki externo."
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr "Facebook"
@@ -4545,25 +5333,58 @@ msgstr "Falha"
msgid "Failed Jobs"
msgstr "Tarefas com falha"
+msgid "Failed create wiki"
+msgstr "Falha ao criar wiki"
+
msgid "Failed to change the owner"
msgstr "Erro ao alterar o proprietário"
msgid "Failed to check related branches."
msgstr "Falha ao procurar por branches relacionadas."
-msgid "Failed to create resources"
+msgid "Failed to connect to the prometheus server"
msgstr ""
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr "Falha ao criar repositório via gitlab-shell"
+
+msgid "Failed to create resources"
+msgstr "Falha ao criar recursos"
+
msgid "Failed to deploy to"
msgstr "Falha ao fazer deploy para"
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr "Falha ao instalar."
+
msgid "Failed to load emoji list."
msgstr "Falha ao carregar a lista de emojis."
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
+msgstr "Falha ao carregar erros do Sentry. Mensagem de erro: %{errorMessage}"
+
+msgid "Failed to load groups & users."
msgstr ""
+msgid "Failed to load related branches"
+msgstr "Falha ao carregar branches relacionados"
+
msgid "Failed to promote label due to internal error. Please contact administrators."
+msgstr "Falha ao promover etiqueta devido a erro interno. Por favor, contate os administradores."
+
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
msgstr ""
msgid "Failed to remove issue from board, please try again."
@@ -4576,38 +5397,56 @@ msgid "Failed to remove the pipeline schedule"
msgstr "Erro ao excluir o agendamento do pipeline"
msgid "Failed to remove user identity."
-msgstr ""
+msgstr "Falha ao remover a identidade do usuário."
msgid "Failed to remove user key."
-msgstr ""
+msgstr "Falha ao remover a chave do usuário."
msgid "Failed to reset key. Please try again."
msgstr "Falha ao redefinir a chave. Por favor, tente novamente."
+msgid "Failed to save comment!"
+msgstr "Falha ao salvar o comentário!"
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr "Falha ao salvar resoluções de conflitos de merge. Por favor, tente novamente!"
+
msgid "Failed to save new settings"
-msgstr ""
+msgstr "Falha ao salvar novas configurações"
msgid "Failed to save preferences (%{error_message})."
-msgstr ""
+msgstr "Falha ao salvar preferências (%{error_message})."
msgid "Failed to save preferences."
-msgstr ""
+msgstr "Falha ao salvar preferências."
msgid "Failed to signing using smartcard authentication"
msgstr "Falha ao entrar usando a autenticação de cartão inteligente"
+msgid "Failed to update branch!"
+msgstr "Falha ao atualizar o branch!"
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr "Falha ao atualizar Issues. Por favor, tente novamente."
+msgid "Failed to update tag!"
+msgstr "Falha ao atualizar a tag!"
+
+msgid "Failed to update."
+msgstr "Falha ao atualizar."
+
+msgid "Failed to upgrade."
+msgstr ""
+
msgid "Failed to upload object map file"
msgstr ""
msgid "Failure"
msgstr "Falha"
-msgid "Fast-forward merge"
-msgstr ""
-
msgid "Fast-forward merge without a merge commit"
msgstr ""
@@ -4615,11 +5454,17 @@ msgid "Faster as it re-uses the project workspace (falling back to clone if it d
msgstr "Mais rápido, uma vez que reutiliza o espaço de trabalho do projeto (voltando a clonar, se não existir)"
msgid "Favicon was successfully removed."
-msgstr ""
+msgstr "O favicon foi removido com sucesso."
msgid "Feature Flags"
msgstr "Feature flag"
+msgid "Feature flag was not removed."
+msgstr "O Feature flag não foi removido."
+
+msgid "Feature flag was successfully removed."
+msgstr "A feature flag foi removida com sucesso."
+
msgid "FeatureFlags|* (All Environments)"
msgstr "* (Todos os Ambientes)"
@@ -4683,8 +5528,8 @@ msgstr "Inativo"
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr "Sinalizador inativo para %{scope}"
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
-msgstr "Instale uma %{docs_link_start}biblioteca de cliente compatível%{docs_link_end} e especifique o URL da API, o nome do aplicativo e o ID da instância durante a configuração."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
+msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr "ID da instância"
@@ -4695,9 +5540,6 @@ msgstr "Carregando feature flag"
msgid "FeatureFlags|More Information"
msgstr "Mais informações"
-msgid "FeatureFlags|More information"
-msgstr "Mais informações"
-
msgid "FeatureFlags|Name"
msgstr "Nome"
@@ -4708,7 +5550,7 @@ msgid "FeatureFlags|New Feature Flag"
msgstr "Nova feature flag"
msgid "FeatureFlags|Protected"
-msgstr ""
+msgstr "Protegido"
msgid "FeatureFlags|Status"
msgstr "Status"
@@ -4735,10 +5577,10 @@ msgid "February"
msgstr "Fevereiro"
msgid "Fetching incoming email"
-msgstr ""
+msgstr "Obtendo e-mails recebidos"
msgid "Fetching licenses failed."
-msgstr ""
+msgstr "A obtenção das licenças falhou."
msgid "Fetching licenses failed. The request endpoint was not found."
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr "Erro ao enviar arquivo."
msgid "Files"
msgstr "Arquivos"
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr "Preencha nos campos abaixo, ative o <strong>%{enable_label}</strong> e pressione <strong>%{save_changes}</strong>"
@@ -4826,6 +5674,9 @@ msgstr "Encontre o arquivo recém-extraído <code>Takeout/Google Code Project Ho
msgid "Fingerprint"
msgstr "Impressão digital"
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr "Impressões digitais"
@@ -4835,6 +5686,9 @@ msgstr "Conclua a edição desta mensagem primeiro!"
msgid "Finish review"
msgstr "Concluir a revisão"
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr "Finalizado"
@@ -4859,6 +5713,12 @@ msgstr "Data de início fixa"
msgid "Fixed:"
msgstr "Fixo:"
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr "E-mail do FogBugz"
@@ -4904,6 +5764,15 @@ msgstr "Para projetos privados, qualquer membro (guest ou superior) pode visuali
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr "Para projetos públicos, qualquer pessoa pode visualizar pipelines e acessar detalhes das tarefas (logs de saída e artefatos)"
+msgid "Fork"
+msgstr "Fork"
+
+msgid "Fork Error!"
+msgstr "Erro de fork!"
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Fork criado a partir de"
@@ -4913,6 +5782,9 @@ msgstr "Fork a partir de %{project_name} (apagado)"
msgid "Forking in progress"
msgstr "Fork em andamento"
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr "Forks"
@@ -4931,6 +5803,9 @@ msgstr "Erros encontrados em seu .gitlab-ci.yml:"
msgid "Free Trial of GitLab.com Gold"
msgstr "Avaliação gratuita do GitLab.com Gold"
+msgid "Friday"
+msgstr "Sexta-feira"
+
msgid "From %{providerTitle}"
msgstr "Do %{providerTitle}"
@@ -4961,12 +5836,18 @@ msgstr "A partir de marcos:"
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr "Na visualização de detalhes do cluster do Kubernetes, instale o Runner pela lista de aplicativos"
+msgid "Full name"
+msgstr "Nome completo"
+
msgid "GPG Key ID:"
msgstr "ID da chave GPG:"
msgid "GPG Keys"
msgstr "Chaves GPG"
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr "Assinatura GPG (carregando...)"
@@ -5031,7 +5912,7 @@ msgid "GeoNodes|Health status"
msgstr "Status de saúde"
msgid "GeoNodes|Internal URL"
-msgstr ""
+msgstr "URL interna"
msgid "GeoNodes|Last event ID processed by cursor"
msgstr "O ID do último evento processado por cursor"
@@ -5082,10 +5963,10 @@ msgid "GeoNodes|Pausing replication stops the sync process."
msgstr ""
msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
-msgstr ""
+msgstr "A remoção de um nó primário interrompe o processo de sincronização para todos os nós. A sincronização não pode ser retomada sem perder alguns dados em todos os secundários. Neste caso, recomendamos a configuração de todos os nós do zero. Você tem certeza?"
msgid "GeoNodes|Removing a secondary node stops the sync process. It is not currently possible to add back the same node without losing some data. We only recommend setting up a new secondary node in this case. Are you sure?"
-msgstr ""
+msgstr "A remoção de um nó secundário interrompe o processo de sincronização. Atualmente não é possível adicionar de volta o mesmo nó sem perder alguns dados. Recomendamos apenas configurar um novo nó secundário nesse caso. Você tem certeza?"
msgid "GeoNodes|Replication slot WAL"
msgstr "WAL de slots de replicação"
@@ -5190,10 +6071,10 @@ msgid "Geo|Batch operations"
msgstr "Operações em lote"
msgid "Geo|Choose which groups you wish to synchronize to this secondary node."
-msgstr ""
+msgstr "Escolha quais grupos você deseja sincronizar nesse nó secundário."
msgid "Geo|Control the maximum concurrency of LFS/attachment backfill for this secondary node"
-msgstr ""
+msgstr "Controle a concorrência máxima de preenchimento de anexo/LFS para esse nó secundário"
msgid "Geo|Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
@@ -5223,7 +6104,7 @@ msgid "Geo|In sync"
msgstr "Em sincronia"
msgid "Geo|Internal URL"
-msgstr ""
+msgstr "URL interna"
msgid "Geo|Last repository check run"
msgstr ""
@@ -5259,7 +6140,7 @@ msgid "Geo|Please refer to Geo Troubleshooting."
msgstr ""
msgid "Geo|Project"
-msgstr ""
+msgstr "Projeto"
msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
msgstr "Projeto (ID: %{project_id}) não existe mais no primário. É seguro remover esse registro, pois isso não removerá nenhum dado no disco."
@@ -5310,13 +6191,13 @@ msgid "Geo|Status"
msgstr "Status"
msgid "Geo|Sync"
-msgstr ""
+msgstr "Sincronizar"
msgid "Geo|Synced"
msgstr "Sincronizado"
msgid "Geo|Synced at"
-msgstr ""
+msgstr "Sincronizado em"
msgid "Geo|Synchronization failed - %{error}"
msgstr "Falha na sincronização - %{error}"
@@ -5324,6 +6205,12 @@ msgstr "Falha na sincronização - %{error}"
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5379,6 +6266,9 @@ msgid "Git"
msgstr "Git"
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
+msgstr "Git LFS não está habilitado neste servidor GitLab, contate seu administrador."
+
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
msgstr ""
msgid "Git global setup"
@@ -5390,6 +6280,9 @@ msgstr "URL do repositório Git"
msgid "Git revision"
msgstr "Revisão do Git"
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr "Estratégia Git para pipelines"
@@ -5462,6 +6355,9 @@ msgstr "Importação do Gitea"
msgid "Given access %{time_ago}"
msgstr "Acesso concedido %{time_ago}"
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr "Voltar"
@@ -5480,9 +6376,18 @@ msgstr "Ir para"
msgid "Go to %{link_to_google_takeout}."
msgstr "Ir para %{link_to_google_takeout}."
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr "Ir para o projeto"
+msgid "Go to your fork"
+msgstr "Ir para seu fork"
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr "Importação do Google Code"
@@ -5511,7 +6416,7 @@ msgid "Group %{group_name} was scheduled for deletion."
msgstr ""
msgid "Group %{group_name} was successfully created."
-msgstr ""
+msgstr "O grupo %{group_name} foi criado com sucesso."
msgid "Group CI/CD settings"
msgstr "Configurações de CI/CD do grupo"
@@ -5558,8 +6463,11 @@ msgstr "Nome do grupo"
msgid "Group overview content"
msgstr "Conteúdo da visão geral do grupo"
+msgid "Group pipeline minutes were successfully reset."
+msgstr "Os minutos do pipeline do grupo foram redefinidos com sucesso."
+
msgid "Group was successfully updated."
-msgstr ""
+msgstr "O grupo foi atualizado com sucesso."
msgid "Group:"
msgstr "Grupo:"
@@ -5567,6 +6475,9 @@ msgstr "Grupo:"
msgid "Group: %{group_name}"
msgstr "Grupo: %{group_name}"
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr "A partir de %{dateWord}"
@@ -5583,43 +6494,43 @@ msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of the %
msgstr ""
msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
-msgstr ""
+msgstr "Para visualizar o planejamento, adicione uma data de início ou de vencimento a um dos seus épicos neste grupo ou em seus subgrupos; de %{startDate} a %{endDate}."
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
-msgstr ""
+msgstr "Para expandir a sua pesquisa, altere ou remova filtros; de %{startDate} para %{endDate}."
msgid "GroupRoadmap|Until %{dateWord}"
msgstr "Até %{dateWord}"
msgid "GroupSAML|Certificate fingerprint"
+msgstr "Impressão digital do certificado"
+
+msgid "GroupSAML|Configuration"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
-msgstr ""
+msgstr "SSO forçado"
msgid "GroupSAML|Generate a SCIM token"
-msgstr ""
+msgstr "Gerar um token SCIM"
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
-msgstr ""
-
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
+msgstr "Gera um token SCIM para configurar seu Sistema para Gerenciamento de Identidade entre Domínios."
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
msgid "GroupSAML|Make sure you save this token — you won't be able to access it again."
-msgstr ""
+msgstr "Certifique-se de salvar este token — você não poderá acessá-lo novamente."
msgid "GroupSAML|Manage your group’s membership while adding another level of security with SAML."
msgstr ""
@@ -5645,14 +6556,23 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
-msgstr ""
+msgstr "Pipeline de Auto DevOps foi atualizado para o grupo"
msgid "GroupSettings|Auto DevOps will automatically build, test and deploy your application based on a predefined Continuous Integration and Delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end}"
msgstr ""
@@ -5661,7 +6581,7 @@ msgid "GroupSettings|Badges"
msgstr "Selos"
msgid "GroupSettings|Custom project templates"
-msgstr ""
+msgstr "Modelos de projetos personalizados"
msgid "GroupSettings|Customize your group badges."
msgstr "Personalize os selos do seu grupo."
@@ -5711,6 +6631,9 @@ msgstr "retirar a trava de compartilhamento de grupo de %{ancestor_group_name}"
msgid "Groups"
msgstr "Grupos"
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr "Grupos também podem ser aninhados criando %{subgroup_docs_link_start}subgrupos%{subgroup_docs_link_end}."
@@ -5780,11 +6703,14 @@ msgstr "Desculpe, nenhum grupo ou projeto correspondem à sua pesquisa"
msgid "GroupsTree|Search by name"
msgstr "Procura por nome"
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr "Tem o e-mail de seus usuários"
msgid "Header logo was successfully removed."
-msgstr ""
+msgstr "O logo do cabeçalho foi removido com sucesso."
msgid "Header message"
msgstr "Mensagem de cabeçalho"
@@ -5807,6 +6733,9 @@ msgstr "Nenhum problema de saúde detectado"
msgid "HealthCheck|Unhealthy"
msgstr "Não saudável"
+msgid "Hello there"
+msgstr "Olá"
+
msgid "Help"
msgstr "Ajuda"
@@ -5816,12 +6745,15 @@ msgstr "Página de ajuda"
msgid "Help page text and support page url."
msgstr "Texto da página de ajuda e Url da página de suporte."
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
-msgstr "Aqui está a chave SSH pública que precisa ser adicionada ao servidor remoto. Para mais informações, consulte a documentação."
+msgid "Hide archived projects"
+msgstr "Ocultar projetos arquivados"
msgid "Hide file browser"
msgstr "Ocultar navegador de arquivos"
+msgid "Hide group projects"
+msgstr "Ocultar projetos de grupo"
+
msgid "Hide host keys manual input"
msgstr "Ocultar entrada manual das teclas do host"
@@ -5831,6 +6763,9 @@ msgstr "Ocultar as entradas relacionadas ao marketing da ajuda"
msgid "Hide payload"
msgstr "Ocultar carga"
+msgid "Hide shared projects"
+msgstr "Ocultar projetos compartilhados"
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Ocultar valor"
@@ -5845,11 +6780,17 @@ msgstr ""
msgid "History"
msgstr "Histórico"
+msgid "History of authentications"
+msgstr "Histórico de autenticações"
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr "A execução do hook falhou. Certifique-se de que o grupo tenha um projeto com commits."
+
msgid "Hook was successfully created."
-msgstr ""
+msgstr "O Hook foi criado com sucesso."
msgid "Hook was successfully updated."
-msgstr ""
+msgstr "O Hook foi atualizado com sucesso."
msgid "Housekeeping"
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr "Manutenção iniciada com sucesso"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr "No entanto, você já é um membro deste %{member_source}. Faça login usando uma conta diferente para aceitar o convite."
@@ -5869,6 +6816,12 @@ msgstr "Eu aceito o %{terms_link}"
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr "Termos de Serviço e Política de Privacidade"
+msgid "I forgot my password"
+msgstr "Esqueci minha senha"
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr "Eu li e concordo com os %{link_start}Termos de Serviço%{link_end} do Let's Encrypt"
+
msgid "ID"
msgstr "ID"
@@ -5938,11 +6891,20 @@ msgstr "Se ativado"
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr "Se ativado, o acesso aos projetos será validado em um serviço externo usando sua etiqueta de classificação."
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr "Se estiver usando o GitHub, você verá os status do pipeline no GitHub para seus commits e pull requests. %{more_info_link}"
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
-msgstr "Se o seu repositório HTTP não estiver acessível publicamente, adicione informações de autenticação à URL:<code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
+msgstr ""
msgid "ImageDiffViewer|2-up"
msgstr "2-up"
@@ -6022,6 +6984,12 @@ msgstr "Importar repositórios do GitHub"
msgid "Import repository"
msgstr "Importar repositório"
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr "Importação expirou. A importação demorou mais de %{import_jobs_expiration} segundos"
@@ -6031,6 +6999,12 @@ msgstr "Importar/exportar ilustração"
msgid "ImportButtons|Connect repositories from"
msgstr "Conectar repositórios de"
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr "Falha ao importar o projeto"
@@ -6040,9 +7014,18 @@ msgstr "Falha ao solicitar seus repositórios do %{provider}"
msgid "ImportProjects|Select the projects you want to import"
msgstr "Selecione os projetos que você deseja importar"
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr "Falha ao atualizar os projetos importados"
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr "Melhore os painéis com GitLab Enterprise Edition."
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr "Projeto Incompatível"
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr "Indexando"
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr "Indica se este runner pode escolher tarefas sem tags"
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr "Em linha"
@@ -6121,12 +7113,24 @@ msgstr "Inserir sugestão"
msgid "Insights"
msgstr "Insights"
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr "Instalar o GitLab Runner"
msgid "Install Runner on Kubernetes"
msgstr "Instalar Runner no Kubernates"
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] "Instância"
@@ -6172,29 +7176,56 @@ msgid "Introducing Cycle Analytics"
msgstr "Apresentando a Análise de Ciclo"
msgid "Introducing Your Conversational Development Index"
-msgstr ""
+msgstr "Introduzindo sua Conversa com o Ãndice de Desenvolvimento"
+
+msgid "Invalid Insights config file detected"
+msgstr "Arquivo de configuração de Insights inválido detectado"
msgid "Invalid Login or password"
+msgstr "Login ou senha inválidos"
+
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
msgstr ""
+msgid "Invalid field"
+msgstr "Campo inválido"
+
msgid "Invalid file."
+msgstr "Arquivo inválido."
+
+msgid "Invalid import params"
msgstr ""
msgid "Invalid input, please avoid emojis"
msgstr "Entrada inválida, por favor, evite emojis"
msgid "Invalid pin code"
+msgstr "Código PIN inválido"
+
+msgid "Invalid query"
msgstr ""
-msgid "Invalid two-factor code."
+msgid "Invalid repository path"
+msgstr "Caminho de repositório inválido"
+
+msgid "Invalid server response"
msgstr ""
+msgid "Invalid two-factor code."
+msgstr "Código de dois fatores inválido."
+
msgid "Invitation"
msgstr "Convite"
msgid "Invite"
msgstr "Convidar"
+msgid "Invite \"%{trimmed}\" by email"
+msgstr "Convidar \"%{trimmed}\" por e-mail"
+
msgid "Invite group"
msgstr "Convidar grupo"
@@ -6207,9 +7238,12 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
-msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
+msgid "Is using license seat:"
msgstr ""
+msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
+msgstr "Fechado (%{moved_link_start}movido%{moved_link_end})"
+
msgid "Issue"
msgstr "Issue"
@@ -6223,6 +7257,12 @@ msgid "Issue events"
msgstr "Eventos de issue"
msgid "Issue template (optional)"
+msgstr "Modelo de issue (opcional)"
+
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
msgstr ""
msgid "IssueBoards|Board"
@@ -6241,7 +7281,7 @@ msgid "IssueBoards|No matching boards found"
msgstr ""
msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
-msgstr ""
+msgstr "Alguns de seus painéis estão ocultos, ative uma licença para vê-los novamente."
msgid "IssueBoards|Switch board"
msgstr "Alternar painel"
@@ -6256,7 +7296,7 @@ msgid "Issues closed"
msgstr "Issues fechadas"
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
-msgstr ""
+msgstr "Issues com comentários, merge requests com diffs e comentários, etiquetas, marcos, snippets e outras entidades do projeto"
msgid "Issues, merge requests, pushes, and comments."
msgstr "Issues, merge requests, pushes e comentários."
@@ -6300,6 +7340,48 @@ msgstr "Jan"
msgid "January"
msgstr "Janeiro"
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr "Eventos para %{noteable_model_name} estão desabilitados."
+
+msgid "JiraService|If different from Web URL"
+msgstr "Se diferente do URL da Web"
+
+msgid "JiraService|JIRA API URL"
+msgstr "URL da API do JIRA"
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr "Trabalho"
@@ -6396,6 +7478,12 @@ msgstr "Jul"
msgid "July"
msgstr "Julho"
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr "Jun"
@@ -6405,6 +7493,9 @@ msgstr "Junho"
msgid "Key (PEM)"
msgstr "Chave (PEM)"
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -6429,12 +7520,18 @@ msgstr "O cluster do Kubernetes foi atualizado com sucesso."
msgid "Kubernetes configured"
msgstr "Kubernetes configurado"
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr "Integração de serviço Kubernetes foi depreciada. %{deprecated_message_content} seus clusters Kubernetes usando a nova página <a href=\"%{url}\"/>Clusters Kubernetes</a>"
msgid "LDAP settings"
msgstr "Configurações LDAP"
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr "LFS"
@@ -6447,6 +7544,9 @@ msgstr "Desabilitado"
msgid "LFSStatus|Enabled"
msgstr "Habilitado"
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr "Etiqueta"
@@ -6457,13 +7557,13 @@ msgid "Label lists show all issues with the selected label."
msgstr "Listas de etiqueta mostram todas as issues com a etiqueta selecionada."
msgid "Label was created"
-msgstr ""
+msgstr "A etiqueta foi criada"
msgid "Label was removed"
-msgstr ""
+msgstr "A etiqueta foi removida"
msgid "Label was successfully updated."
-msgstr ""
+msgstr "A etiqueta foi atualizada com sucesso."
msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
msgstr "%{firstLabelName} +%{remainingLabelCount} mais"
@@ -6495,6 +7595,9 @@ msgstr "Promover etiqueta"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr "Promover %{labelTitle} irá disponibilizá-la para todos os projetos dentro de %{groupName}. Etiquetas de projetos existentes com o mesmo título serão mescladas. Esta ação não pode ser revertida."
+msgid "Labels|and %{count} more"
+msgstr "e mais %{count}"
+
msgid "Language"
msgstr "Idioma"
@@ -6509,6 +7612,9 @@ msgstr[1] "Últimos %d dias"
msgid "Last Pipeline"
msgstr "Último Pipeline"
+msgid "Last accessed on"
+msgstr "Acessado pela última vez em"
+
msgid "Last activity"
msgstr "Última atividade"
@@ -6536,6 +7642,12 @@ msgstr "Última atualização"
msgid "Last updated"
msgstr "Último atualizado"
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr "Você fez o push para"
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr "Aprenda GitLab"
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr "Aprenda como %{link_start}contribuir para os modelos embutidos%{link_end}"
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr "Saiba como %{no_packages_link_start}publicar e compartilhar seus pacotes%{no_packages_link_end} com o GitLab."
@@ -6569,6 +7687,9 @@ msgstr "Saiba mais sobre o Kubernetes"
msgid "Learn more about Web Terminal"
msgstr "Saiba mais sobre o Terminal Web"
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr "Saiba mas sobre aprovações."
@@ -6581,6 +7702,9 @@ msgstr "Saiba mais sobre os modelos de projeto de nível de grupo"
msgid "Learn more about signing commits"
msgstr "Saiba mais sobre assinar commits"
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr "Saiba mais em"
@@ -6602,6 +7726,12 @@ msgstr "Sair do projeto"
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr "Deixe as opções \"Tipo de arquivo\" e \"Método de entrega\" em seus valores padrão."
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr "O Let's Encrypt não aceita e-mails de example.com"
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr "Licença"
@@ -6677,6 +7807,9 @@ msgstr "URL"
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr "Você está prestes a remover a licença %{name} deste projeto."
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr "Licenciado para"
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] "Limitado a mostrar %d evento, no máximo"
msgstr[1] "Limitado a mostrar %d eventos, no máximo"
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -6721,6 +7857,9 @@ msgstr "Pré-visualização ao vivo"
msgid "Loading contribution stats for group members"
msgstr "Carregando estados de contribuição para membros de grupo"
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr "Carregando IDE do GitLab..."
@@ -6742,6 +7881,9 @@ msgstr "Bloquear %{issuableDisplayName}"
msgid "Lock not found"
msgstr "Bloqueio não encontrado"
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr "Travar este %{issuableDisplayName}? Apenas <strong>membros do projeto</strong> poderão comentar."
@@ -6760,6 +7902,9 @@ msgstr "Travado para projetos existentes"
msgid "Locks give the ability to lock specific file or folder."
msgstr "Travas possibilitam travar um arquivo ou uma pasta específica."
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr "Entrar com cartão inteligente"
@@ -6784,15 +7929,24 @@ msgstr "Mostrar apenas alterações"
msgid "MRDiff|Show full file"
msgstr "Mostrar arquivo completo"
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr "Faça com que todos em sua equipe sejam mais produtivos, independentemente da localização deles. O GitLab Geo cria espelhos somente leitura de sua instância do GitLab para que você possa reduzir o tempo necessário para clonar e buscar grandes repositórios."
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr "Certifique-se de que você está conectado à conta que possui os projetos que você deseja importar."
-msgid "Manage"
+msgid "Makes this issue confidential"
msgstr ""
+msgid "Manage"
+msgstr "Gerenciar"
+
msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
msgstr "Gerencie repositórios Git com controles de acesso refinados que mantêm seu código seguro. Realize revisões de código e aprimore a colaboração com merge requests. Cada projeto também pode ter um rastreador de issue e um wiki."
@@ -6850,6 +8004,15 @@ msgstr "Mar"
msgid "March"
msgstr "Março"
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr "Marcar comentário como resolvido"
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr "Marcar esta issue como uma duplicata de outra issue"
+
msgid "Mark todo as done"
msgstr "Marcar como concluído"
@@ -6857,11 +8020,20 @@ msgid "Markdown"
msgstr "Markdown"
msgid "Markdown Help"
-msgstr ""
+msgstr "Ajuda do Markdown"
msgid "Markdown enabled"
msgstr "Markdown habilitado"
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr "Metadado do Maven"
@@ -6886,6 +8058,9 @@ msgstr "Atraso máximo (minutos)"
msgid "Maximum job timeout"
msgstr "Tempo limite máximo da tarefa"
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr "Os membros podem ser adicionados pelos <i>mantenedores</i> ou <i>proprie
msgid "Members of <strong>%{project_name}</strong>"
msgstr "Membros de <strong>%{project_name}</strong>"
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr "Merge Request"
@@ -6928,15 +8106,9 @@ msgstr "Merge Requests"
msgid "Merge Requests created"
msgstr "Merge Requests criadas"
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr "Mensagem do commit de merge"
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr "Eventos de merge"
@@ -6946,12 +8118,6 @@ msgstr "Fazer merge imediatamente"
msgid "Merge in progress"
msgstr "Merge em andamento"
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr "Merge requests"
@@ -6970,6 +8136,30 @@ msgstr "A tela de Merge request é um lugar para propor mudanças em um projeto
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr "Commit para o branch de origem"
+
+msgid "MergeConflict|Committing..."
+msgstr "Fazendo commit..."
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr "HEAD//nossas alterações"
+
+msgid "MergeConflict|Use ours"
+msgstr "Usar nossas"
+
+msgid "MergeConflict|Use theirs"
+msgstr "Usar deles"
+
+msgid "MergeConflict|conflict"
+msgstr "conflito"
+
+msgid "MergeConflict|conflicts"
+msgstr "conflitos"
+
+msgid "MergeConflict|origin//their changes"
+msgstr "origin//alterações deles"
+
msgid "MergeRequests|Add a reply"
msgstr "Adicionar uma resposta"
@@ -6988,6 +8178,9 @@ msgstr "Discussão será resolvida"
msgid "MergeRequests|Discussion will be unresolved"
msgstr "Discussão não será resolvida"
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr "Ir para a próxima discussão não resolvida"
@@ -7000,6 +8193,9 @@ msgstr "Resolver essa discussão em um novo issue"
msgid "MergeRequests|Saving the comment failed"
msgstr "Falha ao salvar comentário"
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr "Ativar/desativar comentários para este arquivo"
@@ -7033,8 +8229,8 @@ msgstr "%{paragraphStart}alterou a descrição %{descriptionChangedTimes} vezes
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr "Erro ao carregar o diff completo. Por favor, tente novamente."
-msgid "MergeRequest|Filter files"
-msgstr "Filtrar arquivos"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
+msgstr ""
msgid "MergeRequest|No files found"
msgstr "Nenhum arquivo encontrado"
@@ -7043,11 +8239,17 @@ msgid "Merged"
msgstr "Merge realizado"
msgid "Merged branches are being deleted. This can take some time depending on the number of branches. Please refresh the page to see changes."
-msgstr ""
+msgstr "Branches com merge realizado estão sendo excluídas. Isso pode levar algum tempo dependendo do número de branches. Por favor, atualize a página para ver as alterações."
msgid "Messages"
msgstr "Mensagens"
+msgid "Metric was successfully added."
+msgstr "A métrica foi adicionada com sucesso."
+
+msgid "Metric was successfully updated."
+msgstr "A métrica foi atualizada com sucesso."
+
msgid "Metrics"
msgstr "Métricas"
@@ -7063,6 +8265,9 @@ msgstr "Métricas e perfis"
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr "Adicionar métrica"
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "Confira a documentação de CI/CD sobre como implantar em um ambiente"
@@ -7073,7 +8278,7 @@ msgid "Metrics|Delete metric"
msgstr ""
msgid "Metrics|Delete metric?"
-msgstr ""
+msgstr "Excluir métrica?"
msgid "Metrics|Edit metric"
msgstr "Editar métricas"
@@ -7102,9 +8307,6 @@ msgstr "Nova métrica"
msgid "Metrics|No deployed environments"
msgstr "Nenhum ambiente implantado"
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,14 +8352,26 @@ msgstr "Rótulo do eixo Y"
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr "ex., Taxa de transferência"
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
msgid "Migration successful."
-msgstr ""
+msgstr "Migração bem sucedida."
msgid "Milestone"
msgstr "Marco"
@@ -7177,9 +8391,6 @@ msgstr "Você está prestes a excluir permanentemente o marco %{milestoneTitle}
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr "Você está prestes a excluir permanentemente o marco %{milestoneTitle}. Este marco não é usado atualmente em nenhuma issue ou merge requests."
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr "<p>%{milestonePromotion}</p> %{finalWarning}"
-
msgid "Milestones|Delete milestone"
msgstr "Excluir marco"
@@ -7198,15 +8409,24 @@ msgstr "Promover %{milestoneTitle} para marco de grupo?"
msgid "Milestones|Promote Milestone"
msgstr "Promover Marco"
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
-msgstr "Promover %{milestone} irá disponibilizá-lo para todos os projetos dentro de %{groupName}. Os marcos de projeto existentes com o mesmo nome serão mesclados. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
+msgstr "Promover %{milestoneTitle} irá disponibilizá-lo para todos os projetos dentro de %{groupName}. Os milestones de projeto existentes com o mesmo título serão mesclados."
msgid "Milestones|This action cannot be reversed."
msgstr "Essa ação não pode ser revertida."
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
+msgstr "Capacidade mínima para estar disponível antes de agendar mais espelhos preventivamente."
+
+msgid "Minimum length is %{minimum_password_length} characters"
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr "Minutos"
+
msgid "Mirror a repository"
msgstr "Espelhar um repositório"
@@ -7228,6 +8448,18 @@ msgstr "Espelhando repositórios"
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr "Faltando endpoint de assinaturas do commit!"
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "adicione uma chave SSH"
@@ -7288,6 +8520,24 @@ msgstr "Mover"
msgid "Move issue"
msgstr "Mover issue"
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr "Múltiplos painéis"
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr "Nome"
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr "Nome da nova etiqueta"
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr "Novo épico"
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr "Novo arquivo"
@@ -7419,6 +8675,9 @@ msgstr "Novo merge request"
msgid "New milestone"
msgstr "Novo marco"
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr "Novos pipelines cancelarão pipelines pendentes mais antigos no mesmo branch"
@@ -7449,21 +8708,36 @@ msgstr "Novo..."
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr "Próximo"
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr "Não"
msgid "No %{providerTitle} repositories available to import"
-msgstr ""
+msgstr "Não há repositórios do %{providerTitle} disponíveis para importação"
msgid "No Label"
msgstr "Sem etiqueta"
+msgid "No Milestone"
+msgstr "Nenhum marco"
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr "Nenhuma atividade encontrada"
+msgid "No available namespaces to fork the project."
+msgstr "Nenhum namespace disponível para fazer fork do projeto."
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr "Nenhuma branch encontrada"
@@ -7479,6 +8753,9 @@ msgstr "Nenhuma conexão pode ser feita para um servidor Gitaly, por favor check
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr "Não há nenhuma imagem gravada neste projeto. Adicione uma seguindo as instruções acima."
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr "Nenhuma contribuição foi encontrada"
@@ -7503,6 +8780,9 @@ msgstr "Nenhum arquivo escolhido"
msgid "No file selected"
msgstr "Nenhum arquivo selecionado"
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr "Nenhum arquivo encontrado."
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr "Nenhum resultado correspondente"
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr "Sem merge requests para o período de tempo selecionado."
@@ -7542,6 +8819,9 @@ msgstr "Sem marcos para mostrar"
msgid "No other labels with such name or description"
msgstr "Sem outras etiquetas com esse nome ou descrição"
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr "Não, importe diretamente os endereços de e-mail e nomes de usuários existentes."
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr "Nós"
@@ -7591,13 +8877,13 @@ msgid "Not enough data"
msgstr "Dados insuficientes"
msgid "Not found."
-msgstr ""
+msgstr "Não encontrado."
msgid "Not now"
msgstr "Agora não"
msgid "Not ready yet. Try again later."
-msgstr ""
+msgstr "Ainda não está pronto. Tente mais tarde."
msgid "Not started"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr "Nota: Considere pedir ao seu administrador do GitLab para configurar %{g
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr "Nota: Considere pedir ao seu administrador do GitLab para configurar %{github_integration_link}, o que permitirá o login via GitHub e permitir a importação de repositórios sem gerar um Token de Acesso Pessoal."
+msgid "NoteForm|Note"
+msgstr "Nota"
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "Você tem certeza que quer cancelar a criação deste comentário?"
@@ -7632,6 +8921,12 @@ msgstr "Mostrar apenas comentários"
msgid "Notes|Show history only"
msgstr "Mostrar apenas histórico"
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr "Esse comentário foi alterado desde que você começou a editá-lo. Por favor, reveja o %{open_link}comentário atualizado%{close_link} para garantir que nenhuma informação seja perdida"
+
+msgid "Nothing to preview."
+msgstr "Nada para pré-visualizar."
+
msgid "Notification events"
msgstr "Eventos de notificação"
@@ -7641,6 +8936,9 @@ msgstr "Configuração de notificação"
msgid "Notification setting - %{notification_title}"
msgstr "Configuração de notificação - %{notification_title}"
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "Fechar issue"
@@ -7695,6 +8993,9 @@ msgstr "Participar"
msgid "NotificationLevel|Watch"
msgstr "Observar"
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr "Notificações"
@@ -7710,6 +9011,12 @@ msgstr "Nov"
msgid "November"
msgstr "Novembro"
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr "OK"
@@ -7725,8 +9032,14 @@ msgstr "Outubro"
msgid "OfSearchInADropdown|Filter"
msgstr "Filtrar"
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
-msgstr "Uma vez importados, repositórios podem ser espelhados por SSH. Leia mais em %{ssh_link}"
+msgid "Ok let's go"
+msgstr "Ok, vamos lá"
+
+msgid "Onboarding"
+msgstr "Começando"
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
+msgstr "Uma vez importados, os repositórios podem ser espelhados por SSH. Leia mais %{link_start}aqui%{link_end}."
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
msgstr ""
@@ -7748,13 +9061,13 @@ msgstr "Um ou mais dos seus projetos do Bitbucket não podem ser importados dire
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "Um ou mais dos seus projetos do Google Code não podem ser importados diretamente no GitLab porque eles usam Subversion ou Mercurial para o controle de versão, ao invés de Git."
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
+msgstr ""
+
msgid "Only admins"
msgstr "Apenas administradores"
-msgid "Only allow merge requests to be merged if all discussions are resolved"
-msgstr ""
-
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr "Somente membros do projeto podem comentar."
msgid "Only project members will be imported. Group members will be skipped."
msgstr "Apenas membros do projeto serão importados. Membros do grupo serão ignorados."
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr "Oops, você tem certeza?"
@@ -7817,6 +9133,12 @@ msgstr "Aberto"
msgid "Opens in a new window"
msgstr "Abrir em nova janela"
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr "Operações"
@@ -7830,20 +9152,17 @@ msgid "OperationsDashboard|Add a project to the dashboard"
msgstr "Adicione um projeto ao painel"
msgid "OperationsDashboard|Add projects"
-msgstr ""
+msgstr "Adicionar projetos"
msgid "OperationsDashboard|More information"
-msgstr ""
+msgstr "Mais informações"
msgid "OperationsDashboard|Operations Dashboard"
-msgstr ""
+msgstr "Painel de Operações"
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr "O painel de operações fornece um resumo da integridade operacional de cada projeto, incluindo status de pipeline e alerta."
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr "Opcional"
@@ -7865,6 +9184,9 @@ msgstr "Outras etiquetas"
msgid "Other information"
msgstr "Outra informação"
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr "Pedidos de saída"
@@ -7874,6 +9196,12 @@ msgstr "Visão geral"
msgid "Overwrite diverged branches"
msgstr "Substituir branches divergentes"
+msgid "Owned by anyone"
+msgstr "Possuído por qualquer pessoa"
+
+msgid "Owned by me"
+msgstr "Possuído por mim"
+
msgid "Owner"
msgstr "Proprietário"
@@ -7887,10 +9215,10 @@ msgid "Packages"
msgstr "Pacotes"
msgid "Page not found"
-msgstr ""
+msgstr "Página não encontrada"
msgid "Page was successfully deleted"
-msgstr ""
+msgstr "Página excluída com sucesso"
msgid "Pages"
msgstr "Páginas"
@@ -7901,6 +9229,9 @@ msgstr "Domínio de páginas"
msgid "Pages Domains"
msgstr "Domínios de páginas"
+msgid "Pages getting started guide"
+msgstr "Guia de primeiros passos a Páginas"
+
msgid "Pagination|Last »"
msgstr "Último >>"
@@ -7922,9 +9253,21 @@ msgstr "Parte das mudanças do merge request"
msgid "Password"
msgstr "Senha"
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr "Atrasado"
@@ -7932,13 +9275,13 @@ msgid "Paste a machine public key here. Read more about how to generate it %{lin
msgstr ""
msgid "Paste epic link"
-msgstr ""
+msgstr "Colar link de épico"
msgid "Paste issue link"
-msgstr ""
+msgstr "Colar link de issue"
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
-msgstr "Cole a sua chave SSH pública, que geralmente é encontrada no arquivo '~/.ssh/id_rsa.pub' e começa com 'ssh-rsa'. Não use a sua chave SSH privada."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
msgid "Path"
msgstr ""
@@ -7964,6 +9307,9 @@ msgstr "Pendente"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr "Pessoas sem permissão nunca receberão uma notificação e não serão capazes de comentar."
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr "Execute opções avançadas, como alterar o caminho, transferir ou remover o grupo."
@@ -7985,12 +9331,27 @@ msgstr "Token de Acesso Pessoal"
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr "Escolha um nome"
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr "Pipeline"
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr "Agendamento da Pipeline"
@@ -8007,7 +9368,7 @@ msgid "Pipeline triggers"
msgstr "Gatilho de pipeline"
msgid "Pipeline: %{status}"
-msgstr ""
+msgstr "Pipeline: %{status}"
msgid "PipelineCharts|Failed:"
msgstr "Falhou:"
@@ -8069,6 +9430,9 @@ msgstr "Pipelines"
msgid "Pipelines charts"
msgstr "Gráficos de pipelines"
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr "Pipelines para o último mês"
@@ -8078,12 +9442,15 @@ msgstr "Pipelines para a última semana"
msgid "Pipelines for last year"
msgstr "Pipelines para o último ano"
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
msgstr ""
+msgid "Pipelines|API"
+msgstr "API"
+
msgid "Pipelines|Build with confidence"
msgstr "Construa com confiança"
@@ -8102,6 +9469,9 @@ msgstr "Saiba como funcionam as pipelines"
msgid "Pipelines|Loading Pipelines"
msgstr "Carregando Pipelines"
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "Cache do projeto redefinido com sucesso."
@@ -8142,7 +9512,7 @@ msgid "Pipeline|Run Pipeline"
msgstr "Executar Pipeline"
msgid "Pipeline|Run for"
-msgstr ""
+msgstr "Executar para"
msgid "Pipeline|Search branches"
msgstr "Pesquisar branches"
@@ -8162,6 +9532,9 @@ msgstr "Parar pipeline"
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr "Parar pipeline #%{pipelineId}?"
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr "Variáveis"
@@ -8192,6 +9565,15 @@ msgstr "com etapa"
msgid "Pipeline|with stages"
msgstr "com etapas"
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr "Diff simples"
@@ -8201,17 +9583,35 @@ msgstr "PlantUML"
msgid "Play"
msgstr "Iniciar"
+msgid "Play all manual"
+msgstr "Iniciar todas manualmente"
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr "Por favor, %{link_to_register} ou %{link_to_sign_in} para comentar"
msgid "Please accept the Terms of Service before continuing."
msgstr "Por favor, aceite os Termos de Serviço antes de continuar."
+msgid "Please add a comment in the text area above"
+msgstr "Por favor, adicione um comentário na área de texto acima"
+
+msgid "Please add a list to your board first"
+msgstr "Por favor adicione uma lista ao seu primeiro painel"
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr "Por favor, escolha um URL de grupo sem caracteres especiais."
msgid "Please complete your profile with email address"
-msgstr ""
+msgstr "Por favor, complete seu perfil com endereço de e-mail"
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr "Por favor, converta-os para %{link_to_git} e passe pelo %{link_to_import_flow} novamente."
@@ -8220,7 +9620,7 @@ msgid "Please convert them to Git on Google Code, and go through the %{link_to_i
msgstr "Por favor, converta-os em Git no Google Code e passe pelo %{link_to_import_flow} novamente."
msgid "Please create a password for your new account."
-msgstr ""
+msgstr "Por favor, crie uma senha para sua nova conta."
msgid "Please create a username with only alphanumeric characters."
msgstr "Crie um nome de usuário com apenas caracteres alfanuméricos."
@@ -8232,11 +9632,14 @@ msgid "Please enter a non-negative number"
msgstr "Digite um número não-negativo"
msgid "Please enter a number greater than %{number} (from the project settings)"
-msgstr ""
+msgstr "Por favor, insira um número maior que %{number} (das configurações do projeto)"
msgid "Please enter a valid number"
msgstr "Digite um número válido"
+msgid "Please enter or upload a license."
+msgstr "Por favor, insira ou envie uma licença."
+
msgid "Please fill in a descriptive name for your group."
msgstr "Por favor, preencha um nome descritivo para o seu grupo."
@@ -8249,9 +9652,18 @@ msgstr "Por favor, note que esse aplicativo não é fornecido pelo GitLab e vocÃ
msgid "Please provide a name"
msgstr "Por favor, forneça um nome"
-msgid "Please select a group."
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
msgstr ""
+msgid "Please select a file"
+msgstr "Por favor, selecione um arquivo"
+
+msgid "Please select a group."
+msgstr "Por favor, selecione um grupo."
+
msgid "Please select and add a member"
msgstr "Por favor, selecione e adicione um membro"
@@ -8270,11 +9682,11 @@ msgstr "Por favor, tente novamente"
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr "Por favor, atualize o PostgreSQL para a versão 9.6 ou superior. O status da replicação não pode ser determinado de maneira confiável com a versão atual."
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
-msgstr "Use este formulário para denunciar usuários ao GitLab que criam spam de issues, comentários ou se comportam de maneira inapropriada."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
+msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
-msgstr ""
+msgstr "Por favor, espere um momento, essa página será atualizada automaticamente."
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr "Por favor, aguarde enquanto conectamos ao seu repositório. Atualize à vontade."
@@ -8286,14 +9698,68 @@ msgid "Preferences"
msgstr "Preferências"
msgid "Preferences saved."
+msgstr "Preferências salvas."
+
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr "Exibir a hora no formato de 24 horas"
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr "Por exemplo: 30 mins atrás."
+
+msgid "Preferences|Layout width"
msgstr ""
msgid "Preferences|Navigation theme"
msgstr "Tema de navegação"
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr "Essas configurações vão atualizar como datas e horas são exibidas para você."
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr "Este recurso é experimental e as traduções ainda não estão completas"
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr "Exibição de hora"
+
+msgid "Preferences|Time format"
+msgstr "Formato de hora"
+
+msgid "Preferences|Time preferences"
+msgstr "Preferências de hora"
+
+msgid "Preferences|Use relative times"
+msgstr "Usar tempos relativos"
+
+msgid "Press %{key}-C to copy"
+msgstr "Pressione %{key}-C para copiar"
+
msgid "Press Enter or click to search"
msgstr "Pressione Enter ou clique para pesquisar"
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr "Pré-visualizar"
-msgid "Preview changes"
+msgid "Preview Markdown"
msgstr ""
+msgid "Preview changes"
+msgstr "Visualizar alterações"
+
msgid "Preview payload"
msgstr "Pré-visualização de carga"
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr "Primário"
@@ -8340,17 +9812,26 @@ msgid "Private - The group and its projects can only be viewed by members."
msgstr "Privado - O grupo e seus projetos só podem ser vistos por seus membros."
msgid "Private group(s)"
-msgstr ""
+msgstr "Grupo(s) privado(s)"
+
+msgid "Private profile"
+msgstr "Perfil privado"
msgid "Private projects can be created in your personal namespace with:"
msgstr "Projetos privados podem ser criados em seu namespace pessoal com:"
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr "Perfil"
msgid "Profile Settings"
msgstr "Configurações do perfil"
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr "Você está prestes a excluir permanentemente a %{yourAccount}, e todas as issues, merge requests e grupos vinculados a sua conta. Depois de confirmar clicando em %{deleteAccount}, isso não poderá ser desfeito ou recuperado."
@@ -8381,6 +9862,9 @@ msgstr "Recortar Avatar"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "O avatar será removido. Você tem certeza?"
+msgid "Profiles|Bio"
+msgstr "Bio"
+
msgid "Profiles|Change username"
msgstr "Alterar nome de usuário"
@@ -8402,6 +9886,9 @@ msgstr "Limpar status"
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr "Clique no ícone para ativar o login com um dos seguintes serviços"
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr "Conectar"
@@ -8414,6 +9901,9 @@ msgstr "Caminho atual: %{path}"
msgid "Profiles|Current status"
msgstr "Status atual"
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr "Excluir conta"
@@ -8441,6 +9931,18 @@ msgstr "Editar perfil"
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr "Digite seu nome, então as pessoas que você conhece podem reconhecê-lo"
+msgid "Profiles|Feed token was successfully reset"
+msgstr "O token de feed foi redefinido com sucesso"
+
+msgid "Profiles|Full name"
+msgstr "Nome completo"
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr "Incluir contribuições privadas no meu perfil"
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr "O token de e-mail recebido foi redefinido com sucesso"
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr "Aumente a segurança da sua conta ativando a autenticação de dois fatores (A2F)"
@@ -8450,9 +9952,15 @@ msgstr "Senha inválida"
msgid "Profiles|Invalid username"
msgstr "Nome de usuário inválido"
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr "Saiba mais"
+msgid "Profiles|Location"
+msgstr "Local"
+
msgid "Profiles|Made a private contribution"
msgstr "Fez uma contribuição privada"
@@ -8462,18 +9970,33 @@ msgstr "Configurações principais"
msgid "Profiles|No file chosen"
msgstr "Nenhum arquivo escolhido"
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr "Organização"
+
msgid "Profiles|Path"
msgstr "Caminho"
msgid "Profiles|Position and size your new avatar"
msgstr "Posicione e dimensione seu novo avatar"
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr "Contribuições privadas"
+msgid "Profiles|Profile was successfully updated"
+msgstr "O perfil foi atualizado com sucesso"
+
msgid "Profiles|Public Avatar"
msgstr "Avatar público"
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr "Remover avatar"
@@ -8492,9 +10015,6 @@ msgstr "Conte-nos sobre você em menos de 250 caracteres"
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "O tamanho máximo de arquivo permitido é de 200KB."
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "Isso não se parece com uma chave pública SSH, você tem certeza que gostaria de adicioná-la?"
@@ -8510,14 +10030,17 @@ msgstr "Este emoji e mensagem aparecerão no seu perfil e em toda a interface."
msgid "Profiles|This information will appear on your profile"
msgstr "Esta informação aparecerá no seu perfil"
+msgid "Profiles|Time settings"
+msgstr "Configurações de hora"
+
msgid "Profiles|Two-Factor Authentication"
msgstr "Autenticação de dois fatores"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Escreva sua %{confirmationValue} para confirmar:"
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
-msgstr "Geralmente se inicia com \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
+msgstr ""
msgid "Profiles|Update profile settings"
msgstr "Atualizar configurações do perfil"
@@ -8531,6 +10054,9 @@ msgstr "Enviar novo avatar"
msgid "Profiles|Use a private email - %{email}"
msgstr "Utilize um email privado - %{email}"
+msgid "Profiles|User ID"
+msgstr "ID do usuário"
+
msgid "Profiles|Username change failed - %{message}"
msgstr "Falha na alteração de nome de usuário - %{message}"
@@ -8552,6 +10078,9 @@ msgstr "Você pode alterar o seu avatar aqui"
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr "Você pode alterar o seu avatar aqui ou remover o avatar atual e reverter para %{gravatar_link}"
+msgid "Profiles|You can set your current timezone here"
+msgstr "Você pode definir seu fuso horário atual aqui"
+
msgid "Profiles|You can upload your avatar here"
msgstr "Você pode enviar o seu avatar aqui"
@@ -8571,7 +10100,7 @@ msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "Sua conta é atualmente proprietária dos seguintes grupos:"
msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
-msgstr ""
+msgstr "Seu endereço de e-mail foi definido automaticamente com base na sua conta do %{provider_label}"
msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
msgstr "A sua localização foi definida automaticamente com base na sua conta do %{provider_label}"
@@ -8610,10 +10139,10 @@ msgid "Project \"%{name}\" is no longer available. Select another project to con
msgstr "O projeto \"%{name}\" não está mais disponível. Selecione um outro projeto para continuar."
msgid "Project %{project_repo} could not be found"
-msgstr ""
+msgstr "O projeto %{project_repo} não pôde ser encontrado"
msgid "Project '%{project_name}' is being imported."
-msgstr ""
+msgstr "O projeto '%{project_name}' está sendo importado."
msgid "Project '%{project_name}' is in the process of being deleted."
msgstr "O projeto '%{project_name}' está sendo excluído."
@@ -8640,14 +10169,17 @@ msgid "Project access must be granted explicitly to each user."
msgstr "Acesso ao projeto deve ser concedido explicitamente para cada usuário."
msgid "Project and wiki repositories"
-msgstr ""
+msgstr "Repositórios do projeto e wiki"
msgid "Project avatar"
msgstr "Imagem do projeto"
-msgid "Project configuration, including services"
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
msgstr ""
+msgid "Project configuration, including services"
+msgstr "Configuração do projeto, incluindo serviços"
+
msgid "Project description (optional)"
msgstr "Descrição do projeto (opcional)"
@@ -8658,7 +10190,7 @@ msgid "Project export could not be deleted."
msgstr "A exportação do projeto não pôde ser excluída."
msgid "Project export enabled"
-msgstr ""
+msgstr "Exportação de projetos ativada"
msgid "Project export has been deleted."
msgstr "Exportação do projeto excluída."
@@ -8685,11 +10217,14 @@ msgid "Project uploads"
msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
-msgstr ""
+msgstr "O nível de visibilidade do projeto será alterado para coincidir com as regras do namespace ao transferir para um grupo."
msgid "Project:"
msgstr "Projeto:"
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "Inscreva-se"
@@ -8741,6 +10276,24 @@ msgstr "Você precisa entrar para marcar um projeto como favorito"
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "ID do Projeto: %{project_id}"
+msgid "ProjectSelect| or group"
+msgstr " ou grupo"
+
+msgid "ProjectSelect|Search for project"
+msgstr "Pesquisar por projeto"
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr "Selos"
@@ -8750,18 +10303,60 @@ msgstr "Contate um administrador para alterar essa configuração."
msgid "ProjectSettings|Customize your project badges."
msgstr "Personalize os selos do seu projeto."
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr "Falha ao proteger a tag"
msgid "ProjectSettings|Failed to update tag!"
msgstr "Falha ao atualizar a tag!"
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr "Saiba mais sobre os selos."
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Apenas para commits assinados pode-se fazer push para este repositório."
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr "Essa configuração está aplicada no nível do servidor e pode ser sobrescrita por um administrador."
@@ -8771,12 +10366,72 @@ msgstr "Essa configuração está aplicada no nível do servidor, mas foi sobres
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "Essa configuração será aplicada a todos os projetos a menos que seja sobrescrita por um administrador."
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr "Usuários só podem fazer push para este repositório com commits que contenham um de seus e-mails verificados."
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ".NET Core"
+
+msgid "ProjectTemplates|Android"
+msgstr "Android"
+
+msgid "ProjectTemplates|Go Micro"
+msgstr "Go Micro"
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr "Netlify/GitBook"
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr "Netlify/Hexo"
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr "Netlify/Hugo"
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr "Netlify/Jekyll"
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr "Netlify/HTML simples"
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr "NodeJS Express"
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr "Páginas/GitBook"
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr "Páginas/Hexo"
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr "Páginas/Hugo"
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr "Páginas/Jekyll"
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr "Páginas/HTML simples"
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr "Ruby on Rails"
+
+msgid "ProjectTemplates|Spring"
+msgstr "Spring"
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr "Projetos"
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr "Promover para Marco de Grupo"
msgid "Promote to group label"
msgstr "Promover para etiqueta de grupo"
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr "Não me mostre isso novamente"
@@ -8951,36 +10615,48 @@ msgstr ""
msgid "Protected"
msgstr "Protegido"
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr "Ambientes Protegidos"
+msgid "Protected Tag"
+msgstr ""
+
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} poderá ser editado por desenvolvedores. Tem certeza disso?"
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "Permitido fazer deploy"
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
-msgstr "Escolher quem tem permissão para fazer deploy"
-
msgid "ProtectedEnvironment|Environment"
msgstr "Ambiente"
msgid "ProtectedEnvironment|Protect"
msgstr "Proteger"
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr "Proteger Ambientes, a fim de restringir quem pode executar deploy."
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr "Proteger um ambiente"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr "Ambiente Protegido (%{protected_environments_count})"
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr "Selecione um ambiente"
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr "Atualmente não existem ambientes protegidos, proteja um ambiente com o formulário acima."
@@ -9029,9 +10705,15 @@ msgstr "Pull"
msgid "Push"
msgstr "Push"
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr "Regras de push"
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr "Push realizado"
msgid "Pushes"
msgstr "Pushes"
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr "Ver projeto %{project_full_name}"
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr "Trimestres"
msgid "Query"
msgstr "Consulta"
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr "Ações rápidas podem ser usadas nas descrições das issues e nas caixas de comentário."
@@ -9086,15 +10810,24 @@ msgstr "Recursos em tempo real"
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr "Recente"
msgid "Recent Project Activity"
msgstr "Atividade recente do projeto"
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr "Pesquisas recentes"
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr "Redirecionar para provedor SAML para testar configuração"
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] "Atualizando em um segundo para mostrar o status atualizado..."
msgstr[1] "Atualizando em %d segundos para mostrar o status atualizado..."
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr "Gerar uma nova chave"
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr "Padrão Regex"
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr "Registrar/Login"
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr "Registrar dispositivo U2F"
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr "Registre-se e veja seus runners para este grupo."
msgid "Register and see your runners for this project."
msgstr "Registre-se e veja seus runners para este projeto."
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr "Merge Requests Relacionados"
msgid "Related Merged Requests"
msgstr "Merge Requests Relacionados"
+msgid "Related issues"
+msgstr "Issues relacionadas"
+
msgid "Related merge requests"
msgstr "Merge requests relacionados"
@@ -9163,6 +10920,9 @@ msgstr "As versões marcam pontos específicos no histórico de desenvolvimento
msgid "Remind later"
msgstr "Lembrar mais tarde"
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr "Remover"
@@ -9172,8 +10932,11 @@ msgstr "Remover Runner"
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
-msgstr "Remover aprovador"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
+msgstr ""
msgid "Remove approvers"
msgstr "Remover aprovadores"
@@ -9181,32 +10944,44 @@ msgstr "Remover aprovadores"
msgid "Remove approvers?"
msgstr "Remover aprovadores?"
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr "Remover imagem"
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr "Remover grupo"
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr "Remover prioridade"
msgid "Remove project"
msgstr "Remover projeto"
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
-msgstr ""
+msgstr "Removido"
msgid "Removed %{type} with id %{id}"
-msgstr ""
+msgstr "Removido %{type} com id %{id}"
msgid "Removed group can not be restored!"
msgstr "O grupo removido não pode ser restaurado!"
@@ -9214,14 +10989,32 @@ msgstr "O grupo removido não pode ser restaurado!"
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr "Remove %{epic_ref} de épicos filhos."
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr "A remoção do grupo fará com que todos os projetos e recursos filhos sejam removidos."
msgid "Removing license…"
-msgstr ""
+msgstr "Removendo a licença…"
msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
+msgstr "Remover o projeto irá apagar seu repositório e todos os recursos relacionados, incluindo issues, merge request etc."
msgid "Rename"
msgstr "Renomear"
@@ -9242,6 +11035,9 @@ msgid "Repair authentication"
msgstr "Corrigir autenticação"
msgid "Replace"
+msgstr "Substituir"
+
+msgid "Replace all label(s)"
msgstr ""
msgid "Reply to comment"
@@ -9253,8 +11049,8 @@ msgstr "Responda a este e-mail diretamente ou %{view_it_on_gitlab}."
msgid "Repo by URL"
msgstr "Repositório por URL"
-msgid "Report abuse to GitLab"
-msgstr "Denunciar abuso ao GitLab"
+msgid "Report abuse to admin"
+msgstr ""
msgid "Reporting"
msgstr "Reportando"
@@ -9268,6 +11064,9 @@ msgstr "Ações"
msgid "Reports|Class"
msgstr "Classe"
+msgid "Reports|Classname"
+msgstr "Noma da classe"
+
msgid "Reports|Confidence"
msgstr "Confiança"
@@ -9307,12 +11106,6 @@ msgstr "Os resultados do resumo de teste estão sendo analisados"
msgid "Reports|Vulnerability"
msgstr "Vulnerabilidade"
-msgid "Reports|issue"
-msgstr "issue"
-
-msgid "Reports|merge request"
-msgstr "merge request"
-
msgid "Reports|no changed test results"
msgstr "sem resultados de teste alterados"
@@ -9329,10 +11122,10 @@ msgid "Repository check was triggered."
msgstr ""
msgid "Repository cleanup"
-msgstr ""
+msgstr "Limpeza do repositório"
msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
-msgstr ""
+msgstr "A limpeza do repositório já começou. Você receberá um e-mail assim que a operação de limpeza for concluída."
msgid "Repository has no locks."
msgstr "O repositório não possui bloqueios."
@@ -9367,6 +11160,12 @@ msgstr "Exija que todos os usuários aceitem Termos de Serviço e Política de P
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr "Exigir senha do usuário para aprovar"
+
+msgid "Require users to prove ownership of custom domains"
+msgstr "Exigir que os usuários comprovem a propriedade de domínios personalizados"
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr "Reenviar convite"
@@ -9416,11 +11218,20 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr "Resolvido por %{name}"
+
+msgid "Resolved by %{resolvedByName}"
+msgstr "Resolvido por %{resolvedByName}"
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr "Resposta"
msgid "Response didn't include `service_desk_address`"
-msgstr ""
+msgstr "A resposta não incluiu `service_desk_address`"
msgid "Response metrics (AWS ELB)"
msgstr "Métricas de resposta (AWS ELB)"
@@ -9458,6 +11269,9 @@ msgstr "Refazer tarefa"
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr "Tentar novamente a verificação"
@@ -9467,7 +11281,7 @@ msgstr[0] "Mostrar valor"
msgstr[1] "Mostrar valores"
msgid "Reveal values"
-msgstr ""
+msgstr "Mostrar valores"
msgid "Revert this commit"
msgstr "Reverter este commit"
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr "Roadmap"
@@ -9580,6 +11400,9 @@ msgstr "SAML SSO para %{group_name}"
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr "Chaves SSH"
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr "Chaves SSH do host"
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr "Chave SSH pública"
@@ -9604,6 +11430,9 @@ msgstr "Salvar"
msgid "Save Changes"
msgstr "Salvar alterações"
+msgid "Save anyway"
+msgstr "Salvar mesmo assim"
+
msgid "Save application"
msgstr "Salvar aplicativo"
@@ -9616,6 +11445,9 @@ msgstr "Salvar alterações antes de testar"
msgid "Save comment"
msgstr "Salvar comentário"
+msgid "Save password"
+msgstr "Salvar senha"
+
msgid "Save pipeline schedule"
msgstr "Salvar agendamento da pipeline"
@@ -9676,9 +11508,21 @@ msgstr "Procurar branch e tags"
msgid "Search files"
msgstr "Procurar arquivos"
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr "Pesquisar por um grupo"
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr "Pesquise por projetos, issues, etc."
+msgid "Search forks"
+msgstr "Pesquisar forks"
+
msgid "Search groups"
msgstr "Procurar grupos"
@@ -9700,6 +11544,9 @@ msgstr "Procurar projeto"
msgid "Search projects"
msgstr "Pesquisar projetos"
+msgid "Search projects..."
+msgstr "Pesquisar projetos..."
+
msgid "Search users"
msgstr "Procurar usuários"
@@ -9734,7 +11581,7 @@ msgid "SearchAutocomplete|in this project"
msgstr "neste projeto"
msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for \"%{term}\""
-msgstr ""
+msgstr "Mostrando %{from} - %{to} de %{count} %{scope} para \"%{term}\""
msgid "Seats currently in use"
msgstr ""
@@ -9749,7 +11596,7 @@ msgid "Security"
msgstr "Segurança"
msgid "Security Dashboard"
-msgstr "Painel de controle de segurança"
+msgstr "Painel de segurança"
msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr "Erro ao recuperar dados do dashboard. Por favor, verifique sua conexão de rede e tente novamente."
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr "Mais informações"
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr "Ocorreu um erro ao criar a issue."
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr "O painel de segurança exibe o último relatório de segurança. Use-o para encontrar e corrigir vulnerabilidades."
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr "Monitorar vulnerabilidades no seu código"
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr "Pipeline %{pipelineLink} acionado"
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr "Ver métricas"
@@ -9826,6 +11682,12 @@ msgstr "Selecionar"
msgid "Select Archive Format"
msgstr "Selecionar Formato do Arquivo"
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr "Selecione um grupo para convidar"
@@ -9833,7 +11695,7 @@ msgid "Select a namespace to fork the project"
msgstr "Selecione um namespace para realizar o fork do projeto"
msgid "Select a new namespace"
-msgstr ""
+msgstr "Selecione um novo namespace"
msgid "Select a project to read Insights configuration file"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr "Selecione um cluster existente do Kubernetes ou crie um novo"
msgid "Select branch/tag"
msgstr "Selecionar o branch/tag"
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr "Selecione membros para convidar"
@@ -9889,6 +11754,9 @@ msgstr "A seleção de um usuário do GitLab adicionará um link para o usuário
msgid "Send an email notification to Developers."
msgstr "Enviar um e-mail de notificação para os desenvolvedores."
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr "Enviar e-mail"
@@ -9905,7 +11773,7 @@ msgid "Sep"
msgstr "Set"
msgid "Separate topics with commas."
-msgstr ""
+msgstr "Separe os tópicos com vírgulas."
msgid "September"
msgstr "Setembro"
@@ -9947,7 +11815,7 @@ msgid "ServerlessDetails|pods in use"
msgstr ""
msgid "ServerlessURL|Copy URL to clipboard"
-msgstr ""
+msgstr "Copiar URL para a área de transferência"
msgid "Serverless| In order to start using functions as a service, you must first install Knative on your Kubernetes cluster."
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr "Balcão de Atendimento"
@@ -9986,7 +11857,7 @@ msgid "Session expiration, projects limit and attachment size."
msgstr "Expiração de sessão, limite de projetos e tamanho de anexo."
msgid "Set a default template for issue descriptions."
-msgstr ""
+msgstr "Defina um modelo padrão para descrições de issues."
msgid "Set a number of approvals required, the approvers and other approval settings."
msgstr ""
@@ -10000,21 +11871,24 @@ msgstr "Definir um repositório de modelos para projetos neste grupo"
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr "Definir padrão e restringir os níveis de visibilidade. Configurar fontes de importação e protocolo de acesso git."
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr "Definir repositório de modelos para toda a instância"
msgid "Set max session time for web terminal."
msgstr "Defina o tempo máximo da sessão para o terminal da web."
+msgid "Set milestone"
+msgstr "Definir marco"
+
msgid "Set new password"
-msgstr ""
+msgstr "Definir nova senha"
msgid "Set notification email for abuse reports."
msgstr "Definir notificação por e-mail para relatórios de abuso."
-msgid "Set number of approvers required before open merge requests can be merged"
-msgstr ""
-
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr "Definir requisitos para um usuário entrar. Ative a autenticação obrigatória de dois fatores."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr "Configurar CI/CD"
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr "Configure seu projeto para fazer push e/ou pull de um repositório para outro automaticamente. Branches, tags e commits serão sincronizados automaticamente."
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr "defina uma senha"
@@ -10078,6 +11958,18 @@ msgstr "Desculpe, nós não fomos capazes de definir o seu status. Por favor, te
msgid "SetStatusModal|What's your status?"
msgstr "Qual é o seu status?"
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr "Configurações"
@@ -10093,6 +11985,9 @@ msgstr "Runners Compartilhados"
msgid "Shared projects"
msgstr "Projetos compartilhados"
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr "Ao redefinir os minutos de pipeline para esse espaço de nomes, os minutos atualmente usados serão definido para zero."
@@ -10105,9 +12000,18 @@ msgstr "Redefinir minutos usados de pipeline"
msgid "Sherlock Transactions"
msgstr "Transações de Sherlock"
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr "Mostrar todas as atividades"
+msgid "Show archived projects"
+msgstr "Mostrar projetos arquivados"
+
+msgid "Show archived projects only"
+msgstr "Mostrar somente projetos arquivados"
+
msgid "Show command"
msgstr "Exibir comando"
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr "Mostrar a versão mais recente"
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr "Mostrar páginas acima"
@@ -10179,21 +12080,42 @@ msgstr "Entrar com cartão inteligente"
msgid "Sign out"
msgstr "Sair"
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr "Restrições de login"
msgid "Sign-up restrictions"
msgstr "Restrições de cadastro"
-msgid "Signing in using %{label} has been disabled"
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
msgstr ""
-msgid "Signing in using your %{label} account without a pre-existing GitLab account is not allowed."
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
msgstr ""
+msgid "Signing in using %{label} has been disabled"
+msgstr "Fazer login usando %{label} foi desativado"
+
+msgid "Signing in using your %{label} account without a pre-existing GitLab account is not allowed."
+msgstr "Fazer login usando sua conta %{label} sem uma conta GitLab pré-existente não é permitida."
+
msgid "Similar issues"
msgstr "Issues semelhantes"
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr "Tamanho"
@@ -10203,6 +12125,9 @@ msgstr "Configurações de tamanho e domínio para sites estáticos"
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr "Ignorar isso por hora"
+
msgid "Slack application"
msgstr "Aplicativo Slack"
@@ -10225,7 +12150,7 @@ msgid "Snippets"
msgstr "Snippets"
msgid "SnippetsEmptyState|Explore public snippets"
-msgstr ""
+msgstr "Explorar snippets públicos"
msgid "SnippetsEmptyState|New snippet"
msgstr ""
@@ -10249,7 +12174,7 @@ msgid "Someone edited this %{issueType} at the same time you did. The descriptio
msgstr ""
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
-msgstr ""
+msgstr "Alguém editou este merge request ao mesmo tempo que você. Por favor, atualize a página para ver as alterações."
msgid "Something went wrong on our end"
msgstr "Algo deu errado do nosso lado"
@@ -10272,6 +12197,9 @@ msgstr "Algo deu errado ao tentar mudar o estado de bloqueio desse %{issuableDis
msgid "Something went wrong when toggling the button"
msgstr "Algo deu errado ao alternar o botão"
+msgid "Something went wrong while adding your award. Please try again."
+msgstr "Algo deu errado ao adicionar seu prêmio. Por favor, tente novamente."
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr "Algo deu errado ao buscar os comentários. Por favor, tente novamente."
msgid "Something went wrong while fetching group member contributions"
msgstr "Algo deu errado ao obter as contribuições de membro do grupo"
+msgid "Something went wrong while fetching latest comments."
+msgstr "Algo deu errado ao obter os comentários mais recentes."
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,8 +12245,8 @@ msgstr "Algo deu errado ao resolver essa discussão. Por favor, tente novamente.
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr "Algo deu errado, incapaz de adicionar %{project} ao dashboard"
-msgid "Something went wrong, unable to get operations projects"
-msgstr "Algo deu errado, não é possível obter os projetos de operações"
+msgid "Something went wrong, unable to get projects"
+msgstr "Algo deu errado, não foi possível obter os projetos"
msgid "Something went wrong, unable to remove project"
msgstr "Algo deu errado, não é possível remover o projeto"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr "Algo deu errado. Por favor, tente novamente."
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr "Desculpe, nenhum épico corresponde à sua pesquisa"
@@ -10333,7 +12267,7 @@ msgid "Sorry, no projects matched your search"
msgstr "Desculpe, nenhum projeto corresponde à sua pesquisa"
msgid "Sorry, your filter produced no results"
-msgstr ""
+msgstr "Desculpe, seu filtro não produziu resultados"
msgid "Sort by"
msgstr "Ordenar por"
@@ -10386,6 +12320,9 @@ msgstr "Menos populares"
msgid "SortOptions|Less weight"
msgstr "Menos peso"
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr "Assinados mais novos"
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr "Data de início"
@@ -10512,6 +12455,9 @@ msgstr "%{type} na lista para commit"
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr "Coloque uma estrela em uma etiqueta para dar prioridade. Altere a ordem das etiquetas priorizadas arrastando-as para alterar sua prioridade."
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr "Marcar como favorito"
@@ -10528,7 +12474,7 @@ msgid "StarredProjectsEmptyState|Visit a project page and press on a star icon.
msgstr ""
msgid "StarredProjectsEmptyState|You don't have starred projects yet."
-msgstr ""
+msgstr "Você ainda não tem projetos favoritos."
msgid "Stars"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr "Iniciar indexação"
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr "Iniciar discussão e fechar %{noteable_name}"
msgid "Start discussion & reopen %{noteable_name}"
msgstr "Iniciar discussão e reabrir %{noteable_name}"
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "Inicie o Runner!"
@@ -10626,12 +12581,18 @@ msgstr "Armazenamento"
msgid "Storage:"
msgstr "Armazenamento:"
+msgid "StorageSize|Unknown"
+msgstr "Desconhecido"
+
msgid "Subgroups"
msgstr "Subgrupos"
msgid "Subgroups and projects"
msgstr "Subgrupos e projetos"
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr "Enviar como spam"
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr "Inscrito"
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr "Cobrança"
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr "Domingo"
@@ -10770,6 +12800,12 @@ msgstr "URL da página de suporte"
msgid "Switch branch/tag"
msgstr "Trocar branch/tag"
+msgid "Switch to GitLab Next"
+msgstr "Mudar para GitLab Next"
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr "Informação de sincronização"
@@ -10800,18 +12836,30 @@ msgstr "Métricas de sistema (Personalizado)"
msgid "System metrics (Kubernetes)"
msgstr "Métricas do sistema (Kubernetes)"
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr "Tag"
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr "Tags"
msgid "Tags feed"
msgstr "Feed de tags"
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr "Tags:"
@@ -10893,6 +12941,9 @@ msgstr "Branch de destino"
msgid "Team"
msgstr "Equipe"
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr "Modelo"
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "Contrato de Termos de Serviço e Política de Privacidade"
@@ -10920,6 +12974,33 @@ msgstr "Análise de cobertura de teste"
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr "O realçador de caracteres ajuda a manter a linha de assunto com %{titleLength} caracteres e quebra a linha do corpo em %{bodyLength} para que sejam legíveis no git."
@@ -10973,6 +13057,9 @@ msgstr "A conexão expirará após %{timeout}. Para repositórios que demoram ma
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr "O deploy desta tarefa para o ambiente %{environmentLink} foi mal sucedida."
@@ -11016,20 +13103,29 @@ msgid "The import will time out after %{timeout}. For repositories that take lon
msgstr "A importação expirará após %{timeout}. Para repositórios que demoram mais tempo, use a combinação clone/push."
msgid "The invitation could not be accepted."
-msgstr ""
+msgstr "O convite não pôde ser aceito."
msgid "The invitation could not be declined."
-msgstr ""
+msgstr "O convite não pôde ser recusado."
msgid "The invitation has already been accepted."
-msgstr ""
+msgstr "O convite já foi aceito."
msgid "The invitation was successfully resent."
-msgstr ""
+msgstr "O convite foi reenviado com sucesso."
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "A etapa de planejamento mostra o tempo que se leva desde a criação de uma issue até sua atribuição à um marco, ou sua adição a uma lista no seu painel. Comece a criar issues para ver dados para esta etapa."
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "A senha necessária para descriptografar a chave privada. Isso é opcional e o seu valor é criptografado."
@@ -11072,9 +13174,21 @@ msgstr "A etapa de produção mostra o tempo total que leva entre criar uma issu
msgid "The project can be accessed by any logged in user."
msgstr "O projeto pode ser acessado por qualquer usuário autenticado."
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr "O projeto pode ser acessado sem a necessidade de autenticação."
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr "A coleção de dados pseudonymizer está desativada. Quando ativada, o GitLab executará uma tarefa em segundo plano que produzirá CSVs com pseudônimos do banco de dados do GitLab que serão carregados no diretório de armazenamento de objetos configurado."
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr "Não existe repositório para este projeto."
msgid "The repository for this project is empty"
msgstr "O repositório para este projeto está vazio"
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr "O repositório deve ser acessível por <code>http://</code>, <code>https://</code> ou <code>git://</code>."
@@ -11132,6 +13252,9 @@ msgstr "A etapa de testes mostra o tempo que o GitLab CI leva para executar cada
msgid "The time taken by each data entry gathered by that stage."
msgstr "O tempo necessário por cada entrada de dados reunida por essa etapa."
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr "A ação de atualização irá expirar depois de %{number_of_minutes} minutos. Para grandes repositórios, use uma combinação de clone/push."
@@ -11153,20 +13276,35 @@ msgstr "O mapa do usuário é um documento JSON que mapeia os usuários do Googl
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr "O mapa do usuário é um mapeamento dos usuários do FogBugz que participaram de seus projetos para a maneira como seus endereços de e-mail e nomes de usuários serão importados para o GitLab. Você pode alterar isso preenchendo a tabela abaixo."
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "O valor situado no ponto médio de uma série de valores observados. Ex., entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5+7)/2 = 6."
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr "Ainda não há projetos arquivados"
-msgid "There are no closed issues"
+msgid "There are no charts configured for this page"
msgstr ""
+msgid "There are no closed issues"
+msgstr "Não há issues fechadas"
+
msgid "There are no closed merge requests"
-msgstr ""
+msgstr "Não há merge requests fechados"
msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr "Não há mudanças na lista para commit"
msgid "There are no unstaged changes"
msgstr "Não há mudanças fora da lista para commit"
+msgid "There is already a repository with that name on disk"
+msgstr "Já existe um repositório com esse nome no disco"
+
+msgid "There was a problem communicating with your device."
+msgstr "Houve um problema de comunicação com o seu dispositivo."
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr "Houve um erro ao adicionar uma tarefa."
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr "Houve um erro ao excluir a tarefa."
@@ -11213,9 +13366,15 @@ msgstr "Erro ao carregar calendário de atividades."
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error saving your changes."
+msgid "There was an error resetting group pipeline minutes."
msgstr ""
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
+msgid "There was an error saving your changes."
+msgstr "Ocorreu um erro ao salvar suas alterações."
+
msgid "There was an error saving your notification settings."
msgstr "Erro ao salvar suas configurações de notificação."
@@ -11231,6 +13390,9 @@ msgstr "Erro ao se inscrever nessa etiqueta."
msgid "There was an error when unsubscribing from this label."
msgstr "Erro ao se anular a inscrição dessa etiqueta."
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr "Eles podem ser gerenciados usando o %{link}."
msgid "Third party offers"
msgstr "Ofertas de terceiros"
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr "Esta instância do GitLab ainda não fornece nenhum Runner compartilhado
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr "Isso também resolve a discussão"
+
msgid "This application was created by %{link_to_owner}."
msgstr "Esse aplicativo foi criado por %{link_to_owner}."
msgid "This application will be able to:"
msgstr "Esse aplicativo será capaz de:"
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr "O escopo deste painel está reduzido"
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr "Esse branch mudou desde quando você começou sua edição. Você quer criar um novo branch?"
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr "Essa data é posterior à data de vencimento, portanto, esse épico não
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr "Esta data é anterior a data de início, portanto este epic não aparecerá no planejamento."
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr "Esse diff está recolhido."
@@ -11303,33 +13486,45 @@ msgstr "Esse diretório"
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
-msgid "This field is required."
+msgid "This environment has no deployments yet."
msgstr ""
+msgid "This field is required."
+msgstr "Este campo é obrigatório."
+
msgid "This group"
msgstr "Esse grupo"
msgid "This group does not provide any group Runners yet."
msgstr "Este grupo não fornece nenhum grupo de Runners ainda."
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr "Essa issue é confidencial."
msgid "This is a delayed job to run in %{remainingTime}"
msgstr "Esta tarefa foi atrasada para executar em %{remainingTime}"
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr "Esta é uma lista de dispositivos com os quais você logou em sua conta. Revogue qualquer sessão que você não reconheça."
+
+msgid "This is a security log of important events involving your account."
+msgstr "Este é um registro de segurança de eventos importantes envolvendo a sua conta."
+
msgid "This is the author's first Merge Request to this project."
msgstr "Esse é o autor do primeiro merge request desse projeto."
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
+msgid "This is your current session"
+msgstr "Esta é a sua sessão atual"
+
msgid "This issue is confidential"
msgstr "Essa issue é confidencial"
-msgid "This issue is confidential and locked."
-msgstr "Essa issue é confidencial e está bloqueada."
-
msgid "This issue is locked."
msgstr "Essa issue está bloqueada."
@@ -11399,12 +13594,6 @@ msgstr "Isto significa que você não pode entregar código até que crie um rep
msgid "This merge request is locked."
msgstr "Esse merge request está bloqueado."
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr "Esses e-mails se tornam automaticamente issues (com os comentários se tornando a conversa por e-mail) listados aqui."
+msgid "Thursday"
+msgstr "Quinta-feira"
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr "Tempo até que uma issue seja agendada"
@@ -11661,6 +13856,9 @@ msgstr "Dica:"
msgid "Title"
msgstr "Título"
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr "Para adicionar uma chave SSH, você precisa %{generate_link_start}gerar uma%{link_end} ou usar uma %{existing_link_start}chave existente%{link_end}."
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr "Para conectar repositórios do GitHub, você pode usar um %{personal_access_token_link}. Ao criar seu Token de Acesso Pessoal, você precisará selecionar o escopo do <code>repositório</code>, então podemos exibir uma lista de seus repositórios públicos e privados que estão disponíveis para conexão."
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr "Para configurar a autenticação SAML para o seu grupo por meio de um provedor de identidade, como Azure, Okta, Onelogin, Ping Identity ou seu provedor SAML 2.0 personalizado:"
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr "Para começar a servir suas tarefas, você pode adicionar Runners ao seu grupo"
@@ -11778,6 +13982,9 @@ msgstr "Afazeres"
msgid "Toggle Sidebar"
msgstr "Alternar barra lateral"
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr "Alternar discussão"
+msgid "Toggle emoji award"
+msgstr "Alternar prêmio de emoji"
+
msgid "Toggle navigation"
msgstr "Alternar navegação"
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Ativar/Desativar barra lateral"
@@ -11802,6 +14015,9 @@ msgstr "Mudar Status: Desligado"
msgid "ToggleButton|Toggle Status: ON"
msgstr "Mudar Status: Ligado"
+msgid "Toggles :%{name}: emoji award."
+msgstr "Alternar :%{name}: prêmio de emoji."
+
msgid "Token"
msgstr "Token"
@@ -11815,7 +14031,7 @@ msgid "Topics"
msgstr "Tópicos"
msgid "Total"
-msgstr ""
+msgstr "Total"
msgid "Total Contributions"
msgstr "Contribuições totais"
@@ -11842,6 +14058,42 @@ msgid "Track time with quick actions"
msgstr "Acompanhe o tempo com ações rápidas"
msgid "Transfer project"
+msgstr "Transferir projeto"
+
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
msgstr ""
msgid "Tree view"
@@ -11895,15 +14147,30 @@ msgstr "Tentar novamente?"
msgid "Try all GitLab has to offer for 30 days."
msgstr "Use tudo que o GitLab tem para oferecer por 30 dias."
+msgid "Try to fork again"
+msgstr "Tente realizar o fork novamente"
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr "Terça-feira"
+
msgid "Turn on Service Desk"
msgstr "Ativar o Balcão de Atendimento"
msgid "Twitter"
msgstr "Twitter"
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr "Autenticação de dois fatores"
msgid "Type"
msgstr "Tipo"
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr "URL"
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr "Não é possível carregar o diff. %{button_try_again}"
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "Não é possível inscrever você no grupo com SAML devido a \"%{reason}\""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr "Não é possível atualizar este épico neste momento."
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr "Desarquivar projeto"
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr "Desconhecido"
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr "Formato desconhecido"
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr "Ilimitado"
msgid "Unlock"
msgstr "Desbloquear"
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr "Desbloquear este %{issuableDisplayName}? <strong>Todos</strong> poderão comentar."
msgid "Unlocked"
msgstr "Desbloqueado"
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr "Reabrir discussão"
@@ -12030,11 +14330,23 @@ msgstr "Atualize o nome do seu grupo, descrição, avatar e visibilidade."
msgid "Update your project name, topics, description and avatar."
msgstr "Atualize o nome do seu projeto, tópicos, a descrição e o avatar."
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr "Atualizado"
msgid "Updated %{updated_at} by %{updated_by}"
-msgstr ""
+msgstr "Atualizado em %{updated_at} por %{updated_by}"
msgid "Updating"
msgstr "Atualizando"
@@ -12043,7 +14355,7 @@ msgid "Upgrade plan to unlock Canary Deployments feature"
msgstr ""
msgid "Upgrade your plan"
-msgstr ""
+msgstr "Aprimore seu plano"
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr "Aprimore seu plano para ativar a Pesquisa Global Avançada."
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr "Enviar arquivo"
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,17 +14405,20 @@ msgstr "clique para fazer upload"
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
msgid "Upstream"
-msgstr ""
+msgstr "Upstream"
msgid "Upvotes"
msgstr "Votos positivos"
msgid "Usage"
-msgstr ""
+msgstr "Uso"
msgid "Usage ping is not enabled"
msgstr "Dados de uso não está habilitado"
@@ -12108,6 +14426,54 @@ msgstr "Dados de uso não está habilitado"
msgid "Usage statistics"
msgstr "Estatísticas de uso"
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr "Comprar minutos adicionais"
+
+msgid "UsageQuota|Current period usage"
+msgstr "Uso do período atual"
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr "Pipelines"
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr "Ilimitado"
+
+msgid "UsageQuota|Usage"
+msgstr "Uso"
+
+msgid "UsageQuota|Usage Quotas"
+msgstr "Cotas de uso"
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr "Uso de recursos de grupo entre os projetos no grupo %{strong_start}%{group_name}%{strong_end}"
+
+msgid "UsageQuota|Usage since"
+msgstr "Uso desde"
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr "Use <code>%{native_redirect_uri}</code> para testes locais"
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "Use o Balcão de Atendimento para se conectar com seus usuários (por exemplo, para oferecer suporte ao cliente) por email dentro do GitLab"
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr "Use marcos de grupo para gerenciar issues de vários projetos no mesmo marco."
@@ -12151,7 +14523,7 @@ msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{
msgstr "GrupoCoortes de usuário são mostradas somente quando os %{usage_ping_link_start}dados de uso%{usage_ping_link_end} são habilitados."
msgid "User OAuth applications"
-msgstr ""
+msgstr "Aplicativos OAuth do usuário"
msgid "User Settings"
msgstr "Configurações do Usuário"
@@ -12160,25 +14532,28 @@ msgid "User and IP Rate Limits"
msgstr "Limites de Taxa de Usuário e IP"
msgid "User identity was successfully created."
-msgstr ""
+msgstr "A identidade do usuário foi criada com sucesso."
msgid "User identity was successfully removed."
-msgstr ""
+msgstr "A identidade do usuário foi removida com sucesso."
msgid "User identity was successfully updated."
-msgstr ""
+msgstr "A identidade do usuário foi atualizada com sucesso."
msgid "User key was successfully removed."
-msgstr ""
+msgstr "A chave do usuário removida com sucesso."
msgid "User map"
msgstr "Mapa do usuário"
-msgid "User settings"
+msgid "User pipeline minutes were successfully reset."
msgstr ""
+msgid "User settings"
+msgstr "Configurações do usuário"
+
msgid "User was successfully created."
-msgstr ""
+msgstr "Usuário criado com sucesso."
msgid "User was successfully removed from group and any subresources."
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr "Atividade"
@@ -12202,16 +14712,16 @@ msgid "UserProfile|Edit profile"
msgstr "Editar perfil"
msgid "UserProfile|Explore public groups to find projects to contribute to."
-msgstr ""
+msgstr "Explore grupos públicos para encontrar projetos para contribuir."
msgid "UserProfile|Groups"
msgstr "Grupos"
msgid "UserProfile|Groups are the best way to manage projects and members."
-msgstr ""
+msgstr "Os grupos são a melhor maneira de gerenciar projetos e membros."
msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
-msgstr ""
+msgstr "Entre ou crie um grupo para começar a contribuir comentando em issues ou enviando merge requests!"
msgid "UserProfile|Most Recent Activity"
msgstr "Atividade mais recente"
@@ -12253,10 +14763,10 @@ msgid "UserProfile|View user in admin area"
msgstr "Exibir usuário na área administrativa"
msgid "UserProfile|You can create a group for several dependent projects."
-msgstr ""
+msgstr "Você pode criar um grupo para vários projetos dependentes."
msgid "UserProfile|You haven't created any personal projects."
-msgstr ""
+msgstr "Você não criou nenhum projeto pessoal."
msgid "UserProfile|You haven't created any snippets."
msgstr "Você não criou nenhum snippet."
@@ -12264,6 +14774,15 @@ msgstr "Você não criou nenhum snippet."
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr "Seus projetos podem estar disponíveis publicamente, internamente ou privadamente, à sua escolha."
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr "Usuários"
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr "%{name} + %{length} mais"
+
+msgid "UsersSelect|Any User"
+msgstr "Qualquer usuário"
+
+msgid "UsersSelect|Assignee"
+msgstr "Responsável"
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr "Nenhum responsável - %{openingTag} atribua a você mesmo %{closingTag}"
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,11 +14864,17 @@ msgstr "Versão"
msgid "View app"
msgstr "Exibir aplicativo"
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
-msgstr ""
+msgstr "Ver detalhes: %{details_url}"
+
+msgid "View documentation"
+msgstr "Ver documentação"
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr "Ve lista de épicos"
msgid "View file @ "
msgstr "Ver arquivo @ "
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr "Visualizar etiquetas de grupo"
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr "Ver no GitLab"
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr "Ver a documentação"
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr "Visibilidade e controles de acesso"
@@ -12405,6 +14957,33 @@ msgstr "Público"
msgid "VisibilityLevel|Unknown"
msgstr "Desconhecido"
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr "%{stepStart}Etapa 1%{stepEnd}. Copie o seguinte script:"
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr "Abrir app de revisão"
+
+msgid "VisualReviewApp|Review"
+msgstr "Revisar"
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr "Revise e comente diretamente no app de revisão"
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,11 +15026,14 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr "Gravidade"
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Precisa visualizar os dados? Solicite acesso ao administrador."
msgid "We can't find an epic that matches what you are looking for."
-msgstr ""
+msgstr "Não conseguimos encontrar um épico que corresponde ao que você está procurando."
msgid "We can't find an issue that matches what you are looking for."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr "Criamos uma pequena visita guiada que o ajudará a aprender os fundamentos do GitLab e como ele o ajudará a ser melhor no seu trabalho. Deve demorar apenas alguns minutos. Você será guiado por dois tipos de auxiliares, melhor reconhecidos pela sua cor."
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "Detectamos spam potencial no %{humanized_resource_name}. Por favor, resolva o reCAPTCHA para continuar."
@@ -12474,6 +15059,9 @@ msgstr "Esta etapa não possui dados suficientes para exibição."
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "Queremos ter certeza de que é você, confirme que você não é um robô."
@@ -12481,7 +15069,7 @@ msgid "Web IDE"
msgstr "IDE Web"
msgid "Web Terminal"
-msgstr ""
+msgstr "Terminal Web"
msgid "Web terminal"
msgstr "Terminal Web"
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr "Webhooks permitem que você acione um URL se, por exemplo, um novo código for feito push ou se uma nova issue for criada. Você pode configurar os webhooks para interagir com eventos específicos como pushes, issues ou merge requests. Webhooks de grupos serão aplicados para todos os projetos em um grupo, permitindo que você padronize o funcionamento em todo o grupo."
+msgid "Wednesday"
+msgstr "Quarta-feira"
+
msgid "Weeks"
msgstr "Semanas"
@@ -12504,15 +15095,18 @@ msgstr "Peso"
msgid "Weight %{weight}"
msgstr "Peso %{weight}"
+msgid "Welcome to the Guided GitLab Tour"
+msgstr "Bem-vindo ao Visita Guiada ao GitLab"
+
+msgid "Welcome to your Issue Board!"
+msgstr ""
+
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Quando um runner está bloqueado, não pode ser atribuído a outros projetos"
msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr "Quando ativado, os usuários não podem usar o GitLab até que os termos tenham sido aceitos."
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr "Ao deixar o URL em branco, a classificação das etiquetas ainda podem ser especificadas sem desativar os recursos do projeto ou executar verificações de autorização externas."
@@ -12522,7 +15116,10 @@ msgstr[0] ""
msgstr[1] ""
msgid "When:"
-msgstr ""
+msgstr "Quando:"
+
+msgid "White helpers give contextual information."
+msgstr "Auxiliares brancos fornecem informações contextuais."
msgid "Who can see this group?"
msgstr "Quem pode ver esse grupo?"
@@ -12534,7 +15131,7 @@ msgid "Wiki"
msgstr "Wiki"
msgid "Wiki was successfully updated."
-msgstr ""
+msgstr "Wiki foi atualizado com sucesso."
msgid "WikiClone|Clone your wiki"
msgstr "Clonar sua wiki"
@@ -12696,7 +15293,7 @@ msgid "Write access allowed"
msgstr ""
msgid "Write milestone description..."
-msgstr ""
+msgstr "Escreva a descrição do marco..."
msgid "Wrong extern UID provided. Make sure Auth0 is configured correctly."
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr "Sim"
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr "Sim, adicionar"
@@ -12719,8 +15319,14 @@ msgstr "Você"
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr "Você é um administrador, o que significa que conceder acesso a <strong>%{client_name}</strong> permitirá que eles também interajam com o GitLab como administrador. Prossiga com cuidado."
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "Você vai remover %{group_name}. Grupos removidos NÃO PODEM ser restaurados! Você está ABSOLUTAMENTE certo?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "Você irá remover %{project_full_name}. O projeto removido NÃO PODE ser restaurado! Tem certeza ABSOLUTA?"
@@ -12731,14 +15337,17 @@ msgstr "Você está prestes a remover a relação de fork do projeto original %{
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr "Você irá transferir %{project_full_name} para outro proprietário. Tem certeza ABSOLUTA?"
-msgid "You are now impersonating %{username}"
+msgid "You are not allowed to unlink your primary login account"
msgstr ""
+msgid "You are now impersonating %{username}"
+msgstr "Você está agora se passando por %{username}"
+
msgid "You are on a read-only GitLab instance."
msgstr "Você está em uma instância somente-leitura do GitLab."
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
-msgstr ""
+msgstr "Você está recebendo esta mensagem porque você é um administrador do GitLab para %{url}."
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr "Você pode %{linkStart}visualizar o blob%{linkEnd} em vez disso."
@@ -12746,6 +15355,12 @@ msgstr "Você pode %{linkStart}visualizar o blob%{linkEnd} em vez disso."
msgid "You can also create a project from the command line."
msgstr "Você também pode criar um projeto a partir da linha de comando."
+msgid "You can also press &#8984;-Enter"
+msgstr "Você também pode pressionar &#8984;-Enter"
+
+msgid "You can also press Ctrl-Enter"
+msgstr "Você também pode pressionar Ctrl-Enter"
+
msgid "You can also star a label to make it a priority label."
msgstr "Você também pode marcar uma etiqueta para torná-la uma etiqueta de prioridade."
@@ -12764,6 +15379,15 @@ msgstr "Você pode facilmente contribuir para eles pedindo para se juntar nesses
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr "Você pode instalar facilmente um Runner em um cluster Kubernetes. %{link_to_help_page}"
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr "Você pode mover o gráfico usando as setas do teclado."
@@ -12771,7 +15395,7 @@ msgid "You can now submit a merge request to get this change into the original b
msgstr ""
msgid "You can now submit a merge request to get this change into the original project."
-msgstr ""
+msgstr "Agora você pode enviar um merge request para fazer esta mudança no projeto original."
msgid "You can only add files when you are on a branch"
msgstr "Você somente pode adicionar arquivos quando estiver em um branch"
@@ -12780,28 +15404,34 @@ msgid "You can only edit files when you are on a branch"
msgstr "Você só pode editar arquivos quando estiver em um branch"
msgid "You can only merge once the items above are resolved"
-msgstr ""
+msgstr "Você só pode fazer o merge quando os itens acima forem resolvidos"
msgid "You can only transfer the project to namespaces you manage."
-msgstr ""
+msgstr "Você só pode transferir o projeto para namespaces que você gerencia."
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "Você pode resolver o conflito de merge usando o modo Interativo, escolhendo os botões %{use_ours} ou %{use_theirs} ou editando os arquivos diretamente. Confirme essas alterações em %{branch_name}"
+msgid "You can see your chat accounts."
+msgstr "Você pode ver suas contas de bate-papo."
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr "Você pode configurar tarefas para só usar os runners com tags específicas. Separe tags com vírgulas."
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr "Você pode testar o seu .gitlab-ci.yml no %{linkStart}CI Lint%{linkEnd}."
msgid "You cannot impersonate a blocked user"
-msgstr ""
+msgstr "Você não pode se passar por um usuário bloqueado"
msgid "You cannot impersonate a user who cannot log in"
-msgstr ""
+msgstr "Você não pode se passar por um usuário que não pode fazer login"
msgid "You cannot impersonate an internal user"
-msgstr ""
+msgstr "Você não pode se passar por um usuário interno"
msgid "You cannot play this scheduled pipeline at the moment. Please wait a minute."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr "Você ainda não tem nenhuma inscrição"
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr "Você não tem permissão para deixar este %{namespaceType}."
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr "Você não tem as permissões corretas para substituir as configurações de sincronização do grupo LDAP."
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr "Você não tem nenhum nome de bate-papo ativo."
+
msgid "You don't have any applications"
msgstr "Você não tem nenhum aplicativo"
@@ -12836,6 +15475,12 @@ msgstr "Você não tem nenhum aplicativo autorizado"
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr "Você recebeu acesso %{access_level} ao %{source_link} %{source_type}."
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr "Você recebeu acesso %{access_level} ao %{source_name} %{source_type}."
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr "Você deve aceitar nossos Termos de Serviço e política de privacidade
msgid "You must have maintainer access to force delete a lock"
msgstr "Você deve ter o acesso de mantenedor para apagar um bloqueio"
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr "Você deve ter permissão para criar um projeto em um namespace antes de criar o fork."
+
+msgid "You must provide a valid current password"
+msgstr "Você deve fornecer uma senha atual válida"
+
+msgid "You must provide your current password in order to change it."
+msgstr "Você deve fornecer sua senha atual para alterá-la."
+
msgid "You need a different license to enable FileLocks feature"
msgstr "Você precisa de uma licença diferente para ativar o recurso FileLocks"
@@ -12878,6 +15532,9 @@ msgstr "Você precisa do git-lfs na versão %{min_git_lfs_version} (ou maior) pa
msgid "You need permission."
msgstr "Você precisa de permissão."
+msgid "You need to be logged in."
+msgstr "Você precisa estar conectado."
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr "Você tentou criar o fork %{link_to_the_project}, mas ocorreu uma falha pelo seguinte motivo:"
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr "Você não conseguirá fazer pull ou push no projeto via SSH até que a
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "Você não poderá fazer push ou pull do código via SSH enquanto não adicionar sua chave SSH no seu perfil"
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr "Você precisará usar nomes de branch diferentes para obter uma comparação válida."
@@ -12944,27 +15607,51 @@ msgstr "Você está recebendo este e-mail devido à sua conta no %{host}."
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr "Você está recebendo este e-mail devido à sua conta no %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr "YouTube"
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr "Seus Grupos"
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr "As informações do cluster do Kubernetes nesta página ainda são editáveis, mas é recomendado que você desative e reconfigure"
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr "Seus projetos (padrão)"
msgid "Your Projects' Activity"
msgstr "Atividade dos seus projetos"
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr "Seus lembretes"
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,8 +15685,11 @@ msgstr "Suas alterações foram salvas"
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
-msgstr "Seu comentário não estará visível ao público."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr "Seu comentário não pôde ser enviado! Por favor, verifique sua conexão de rede e tente novamente."
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
+msgstr "Seu comentário não pôde ser atualizado! Por favor, verifique sua conexão de rede e tente novamente."
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
msgstr ""
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr "Sua mensagem aqui"
+
msgid "Your name"
msgstr "Seu nome"
@@ -13026,7 +15719,7 @@ msgid "Your new personal access token has been created."
msgstr ""
msgid "Your password reset token has expired."
-msgstr ""
+msgstr "Seu token de redefinição de senha expirou."
msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
msgstr ""
@@ -13049,12 +15742,15 @@ msgstr "atrás"
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
-msgstr "entre outras coisas"
+msgid "already being used for another group or project milestone."
+msgstr ""
-msgid "at"
+msgid "already shared with this group"
msgstr ""
+msgid "among other things"
+msgstr "entre outras coisas"
+
msgid "attach a new file"
msgstr ""
@@ -13067,6 +15763,21 @@ msgstr "nome da branch"
msgid "by"
msgstr "por"
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr "não foi possível bloquear outros"
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr "não é possível bloquear a si próprio"
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr "%{linkStartTag}Saiba mais sobre Verificação de Container %{linkEndTag}"
@@ -13160,6 +15871,9 @@ msgstr "(está carregando)"
msgid "ciReport|(is loading, errors when loading results)"
msgstr "(está carregando, erros ao carregar resultados)"
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr "Todos os projetos"
@@ -13193,9 +15907,6 @@ msgstr "Criar issue"
msgid "ciReport|Create merge request"
msgstr "Criar merge request"
-msgid "ciReport|Created %{eventType}"
-msgstr "Criado %{eventType}"
-
msgid "ciReport|DAST"
msgstr "DAST"
@@ -13211,12 +15922,6 @@ msgstr "Verificação de dependência"
msgid "ciReport|Description"
msgstr "Descrição"
-msgid "ciReport|Dismiss vulnerability"
-msgstr "Ignorar vulnerabilidade"
-
-msgid "ciReport|Dismissed by"
-msgstr "Ignorado por"
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr "Ocorreu um erro ao carregar o relatório de verificação de dependênci
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr "Houve um erro ao reverter o descarte. Por favor, tente novamente."
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr "Atualizar %{name} de %{version} para %{fixed}."
@@ -13355,12 +16057,12 @@ msgstr[1] "Usado por %{packagesString} e %{lastPackage}"
msgid "ciReport|View full report"
msgstr "Visualizar relatório completo"
-msgid "ciReport|on pipeline"
-msgstr "na pipeline"
-
msgid "commented on %{link_to_project}"
msgstr ""
+msgid "commit %{commit_id}"
+msgstr ""
+
msgid "confidence|Confirmed"
msgstr ""
@@ -13400,6 +16102,9 @@ msgstr "não foi possível ler a chave privada, a senha está correta?"
msgid "customize"
msgstr "personalizar"
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] "dia"
@@ -13430,21 +16135,33 @@ msgid_plural "drafts"
msgstr[0] "rascunho"
msgstr[1] "rascunhos"
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr "habilitado"
-msgid "epic"
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
msgstr ""
+msgid "epic"
+msgstr "épico"
+
msgid "error"
msgstr ""
msgid "error code:"
-msgstr ""
+msgstr "código de erro:"
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr "%{slash_command} irá atualizar o tempo estimado com o último comando."
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr "de"
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr "aqui"
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] "instâncias completas"
msgstr[1] "instâncias completas"
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr "é inválido porque há bloqueio no recebimento de dados"
@@ -13507,11 +16233,14 @@ msgstr "é inválido porque há bloqueio no envio de dados"
msgid "is not a valid X509 certificate."
msgstr "não é um certificado X509 válido."
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
msgid "issue"
-msgstr ""
+msgstr "issue"
msgid "issue boards"
msgstr "painéis"
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] "merge request"
msgstr[1] "merge requests"
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,8 +16313,8 @@ msgstr "%{metricsLinkStart} Memória %{metricsLinkEnd} uso %{emphasisStart} aume
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "%{metricsLinkStart} Memória %{metricsLinkEnd} uso é %{emphasisStart} inalterado %{emphasisEnd} em %{memoryFrom}MB"
-msgid "mrWidget|Add approval"
-msgstr "Adicionar aprovação"
+msgid "mrWidget|Added to the merge train by"
+msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "Permite commits de membros que podem fazer merge ao branch de destino"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "Ocorreu um erro ao enviar sua aprovação."
+msgid "mrWidget|Approval password is invalid."
+msgstr "A senha de aprovação é inválida."
+
msgid "mrWidget|Approve"
msgstr "Aprovar"
@@ -13647,6 +16385,9 @@ msgstr "Falha ao carregar estatísticas de deploy"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr "Merge fast-forward não é possível. Para fazer merge, primeiramente faça rebase local."
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr "Se o branch %{branch} existir em seu repositório local, você poderá fazer o merge request manualmente usando o"
@@ -13665,18 +16406,15 @@ msgstr "Fazer merge"
msgid "mrWidget|Merge failed."
msgstr "Falha ao fazer merge."
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
+msgstr ""
+
msgid "mrWidget|Merge locally"
msgstr "Fazer merge localmente"
-msgid "mrWidget|Merge request approved"
-msgstr "Merge request aprovado"
-
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr "Merge request aprovado; você pode adicionalmente"
-
msgid "mrWidget|Merged by"
msgstr "Merge realizado por"
@@ -13707,22 +16445,12 @@ msgstr "Atualizar agora"
msgid "mrWidget|Refreshing now"
msgstr "Atualizando agora"
-msgid "mrWidget|Remove your approval"
-msgstr "Remover sua aprovação"
+msgid "mrWidget|Remove from merge train"
+msgstr ""
msgid "mrWidget|Request to merge"
msgstr "Merge de"
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] "Requer mais 1 aprovação"
-msgstr[1] "Requer mais %d aprovações"
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] "Requer mais 1 aprovação por"
-msgstr[1] "Requer mais %d aprovações por"
-
msgid "mrWidget|Resolve conflicts"
msgstr "Resolver conflitos"
@@ -13807,15 +16535,30 @@ msgstr "linha de comando"
msgid "mrWidget|into"
msgstr "para"
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr "para ser realizado merge automaticamente quando o pipeline for bem sucedido"
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr "n/a"
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr "novo merge request"
+msgid "no contributions"
+msgstr "nenhuma contribuição"
+
msgid "none"
msgstr "nenhum"
@@ -13925,27 +16668,39 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
-msgstr ""
+msgstr "mostrar menos"
msgid "sign in"
msgstr "entrar"
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr "origem"
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} irá atualizar a soma do tempo gasto."
msgid "started"
msgstr "iniciado"
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr "use clusters Kubernetes para deploy do seu código!"
msgid "verify ownership"
msgstr "verificar propriedade"
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr "ver no GitLab"
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "com %{additions} adições, %{deletions} remoções."
diff --git a/locale/pt_PT/gitlab.po b/locale/pt_PT/gitlab.po
index 3a2d4ebb37f..bc1732cd69a 100644
--- a/locale/pt_PT/gitlab.po
+++ b/locale/pt_PT/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Portuguese\n"
"Language: pt_PT\n"
"MIME-Version: 1.0\n"
@@ -13,22 +13,19 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: pt-PT\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:30\n"
+"PO-Revision-Date: 2019-06-14 10:14\n"
msgid " Please sign in."
-msgstr ""
-
-msgid " Status"
-msgstr ""
+msgstr " Por favor, inicia a sessão."
msgid " Try to %{action} this file again."
-msgstr ""
+msgstr " Tenta %{action} este ficheiro novamente."
msgid " You need to do this before %{grace_period_deadline}."
-msgstr ""
+msgstr " Tens de fazer isto antes de %{grace_period_deadline}."
msgid " and"
-msgstr ""
+msgstr " e"
msgid " degraded on %d point"
msgid_plural " degraded on %d points"
@@ -37,22 +34,22 @@ msgstr[1] ""
msgid " improved on %d point"
msgid_plural " improved on %d points"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] " melhorado em %d ponto"
+msgstr[1] " melhorado em %d pontos"
msgid " or "
-msgstr ""
+msgstr " ou "
msgid " or <#epic id>"
-msgstr ""
+msgstr " ou <#epic id>"
msgid " or <#issue id>"
-msgstr ""
+msgstr " ou <#issue id>"
msgid "%d comment"
msgid_plural "%d comments"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d comentário"
+msgstr[1] "%d comentários"
msgid "%d commit"
msgid_plural "%d commits"
@@ -61,169 +58,217 @@ msgstr[1] ""
msgid "%d commit behind"
msgid_plural "%d commits behind"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d envio atrás"
+msgstr[1] "%d envios atrás"
msgid "%d commits"
-msgstr ""
+msgstr "%d envios"
+
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] "%d contribuição"
+msgstr[1] "%d contribuições"
msgid "%d exporter"
msgid_plural "%d exporters"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d exportador"
+msgstr[1] "%d exportadores"
msgid "%d failed test result"
msgid_plural "%d failed test results"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d resultado do teste falhou"
+msgstr[1] "%d resultados do teste falharam"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d resultado do teste fixo"
+msgstr[1] "%d resultados do teste fixos"
msgid "%d issue"
msgid_plural "%d issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d problema"
+msgstr[1] "%d problemas"
msgid "%d issue selected"
msgid_plural "%d issues selected"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d problema selecionado"
+msgstr[1] "%d problemas selecionados"
msgid "%d layer"
msgid_plural "%d layers"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d camada"
+msgstr[1] "%d camadas"
msgid "%d merge request"
msgid_plural "%d merge requests"
+msgstr[0] "%d pedido de mesclagem"
+msgstr[1] "%d pedidos de mesclagem"
+
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
msgid "%d metric"
msgid_plural "%d metrics"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d métrica"
+msgstr[1] "%d métricas"
+
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] "mais %d comentário"
+msgstr[1] "mais %d comentários"
msgid "%d staged change"
msgid_plural "%d staged changes"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d fase alterada"
+msgstr[1] "%d fases alteradas"
msgid "%d unstaged change"
msgid_plural "%d unstaged changes"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d fase não alterada"
+msgstr[1] "%d fases não alteradas"
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%s envio adicional foi omitido para prevenir problemas de desempenho."
+msgstr[1] "%s envios adicionais foram omitidos para prevenir problemas de desempenho."
msgid "%{actionText} & %{openOrClose} %{noteable}"
-msgstr ""
+msgstr "%{actionText} & %{openOrClose} %{noteable}"
msgid "%{authorsName}'s discussion"
-msgstr ""
+msgstr "Tópico de %{authorsName}"
msgid "%{commit_author_link} authored %{commit_timeago}"
-msgstr ""
-
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
+msgstr "%{commit_author_link} autorizou %{commit_timeago}"
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} aprovação obrigatória de %{name}"
+msgstr[1] "%{count} aprovações obrigatórias de %{name}"
msgid "%{count} approvals from %{name}"
-msgstr ""
+msgstr "%{count} aprovações de %{name}"
msgid "%{count} more"
-msgstr ""
+msgstr "mais %{count}"
msgid "%{count} more assignees"
-msgstr ""
+msgstr "mais %{count} responsáveis"
msgid "%{count} of %{required} approvals from %{name}"
-msgstr ""
+msgstr "%{count} de %{required} aprovações de %{name}"
msgid "%{count} of %{total}"
-msgstr ""
+msgstr "%{count} de %{total}"
msgid "%{count} participant"
msgid_plural "%{count} participants"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} participante"
+msgstr[1] "%{count} participantes"
msgid "%{count} pending comment"
msgid_plural "%{count} pending comments"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} comentário pendente"
+msgstr[1] "%{count} comentários pendentes"
+
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr "%{edit_in_new_fork_notice} Tenta fazer cherry-pick neste envio novamente."
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr "%{edit_in_new_fork_notice} Tenta reverter este envio novamente."
msgid "%{filePath} deleted"
-msgstr ""
+msgstr "%{filePath} apagado"
msgid "%{firstLabel} +%{labelCount} more"
-msgstr ""
+msgstr "mais %{firstLabel} +%{labelCount}"
msgid "%{gitlab_ci_yml} not found in this commit"
-msgstr ""
+msgstr "%{gitlab_ci_yml} não foi encontrado neste envio"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr "%{group_docs_link_start}Grupos%{group_docs_link_end} permitem-te gerenciares e colaborares em vários projetos. Os membros de um grupo têm acesso a todos os teus projetos."
+
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
-msgstr ""
+msgstr "%{issuableType} será removido! Tens a certeza?"
msgid "%{label_for_message} unavailable"
+msgstr "%{label_for_message} indisponível"
+
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr "%{lets_encrypt_link_start}Vamos Criptografar%{lets_encrypt_link_end} é uma autoridade de certificação (CA) grátis, automatizada e aberta, que fornece certificados digitais para habilitar HTTPS (SSL/TLS) a sites."
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr "%{level_name} não é permitido num grupo %{group_level_name}."
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
msgid "%{level_name} visibility has been restricted by the administrator."
-msgstr ""
+msgstr "a visibilidade de %{level_name} foi restringida pelo administrador."
msgid "%{link_start}Read more%{link_end} about role permissions"
-msgstr ""
+msgstr "%{link_start}Lê mais%{link_end} sobre as permissões de função"
msgid "%{loadingIcon} Started"
-msgstr ""
+msgstr "%{loadingIcon} Iniciado"
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
-msgstr ""
+msgstr "%{lock_path} está bloqueado pelo Utilizador do GitLab %{lock_user_id}"
msgid "%{mrText}, this issue will be closed automatically."
-msgstr ""
+msgstr "%{mrText}, este problema será encerrado automaticamente."
+
+msgid "%{name} contained %{resultsString}"
+msgstr "%{name} continha %{resultsString}"
+
+msgid "%{name} found %{resultsString}"
+msgstr "%{name} encontrou %{resultsString}"
msgid "%{name}'s avatar"
-msgstr ""
+msgstr "Avatar de %{name}"
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
msgid "%{openOrClose} %{noteable}"
-msgstr ""
+msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
-msgstr ""
+msgstr "%{percent}%% completado"
msgid "%{service_title} activated."
-msgstr ""
+msgstr "%{service_title} ativado."
msgid "%{service_title} settings saved, but not activated."
+msgstr "%{service_title} definições guardadas, mas não ativadas."
+
+msgid "%{size} GiB"
msgstr ""
-msgid "%{spammable_titlecase} was submitted to Akismet successfully."
+msgid "%{size} KiB"
msgstr ""
-msgid "%{state} epics"
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
msgstr ""
+msgid "%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr "%{spammable_titlecase} foi enviado ao Akismet com sucesso."
+
+msgid "%{state} epics"
+msgstr "%{state} épicos"
+
msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
msgstr[0] ""
@@ -231,11 +276,11 @@ msgstr[1] ""
msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{strong_start}%{commit_count}%{strong_end} Envio"
+msgstr[1] "%{strong_start}%{commit_count}%{strong_end} Envios"
msgid "%{strong_start}%{human_size}%{strong_end} Files"
-msgstr ""
+msgstr "%{strong_start}%{human_size}%{strong_end} Ficheiros"
msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
@@ -244,98 +289,124 @@ msgstr[1] ""
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{text} %{files}"
+msgstr[1] "%{text} %{files} ficheiros"
msgid "%{text} is available"
-msgstr ""
+msgstr "%{text} está disponível"
+
+msgid "%{title} %{operator} %{threshold}"
+msgstr "%{title} %{operator} %{threshold}"
msgid "%{title} changes"
-msgstr ""
+msgstr "Alterações de %{title}"
msgid "%{unstaged} unstaged and %{staged} staged changes"
-msgstr ""
+msgstr "%{unstaged} fases não alterada e %{staged} fases alteradas"
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
-msgstr ""
+msgstr "%{usage_ping_link_start}Aprende mais%{usage_ping_link_end} sobre quais informações são compartilhadas com o GitLab Inc."
msgid "%{user_name} profile page"
+msgstr "página de perfil de %{user_name}"
+
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr "%{verb} %{time_spent_value} tempo passado."
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr "'%{level}' não é um nível de visibilidade válido"
+
+msgid "'%{source}' is not a import source"
+msgstr "'%{source}' não é uma fonte de importação"
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
msgstr ""
msgid "(No changes)"
-msgstr ""
+msgstr "(Sem alterações)"
+
+msgid "(check progress)"
+msgstr "(verificar progresso)"
msgid "(external source)"
-msgstr ""
+msgstr "(fonte externa)"
msgid "+ %{count} more"
-msgstr ""
+msgstr "+ mais %{count}"
msgid "+ %{moreCount} more"
-msgstr ""
+msgstr "+ mais %{moreCount}"
msgid "+%{extraOptionCount} more"
-msgstr ""
+msgstr "+ mais %{extraOptionCount}"
msgid ", or "
-msgstr ""
+msgstr ", ou "
msgid "- Runner is active and can process any new jobs"
-msgstr ""
+msgstr "- O runner está ativo e pode processar novos trabalhos"
msgid "- Runner is paused and will not receive any new jobs"
-msgstr ""
+msgstr "- O runner está em pausa e não receberá nenhum trabalho novo"
msgid "- show less"
-msgstr ""
+msgstr "- mostrar menos"
+
+msgid "0 for unlimited"
+msgstr "0 para ilimitado"
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 adição de %{type}"
+msgstr[1] "%{count} adições %{type}"
msgid "1 %{type} modification"
msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 alteração de %{type}"
+msgstr[1] "%{count} alterações de %{type}"
msgid "1 Day"
msgid_plural "%d Days"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 Dia"
+msgstr[1] "%d dias"
msgid "1 closed issue"
-msgid_plural "%d closed issues"
-msgstr[0] ""
-msgstr[1] ""
+msgid_plural "%{issues} closed issues"
+msgstr[0] "1 problema encerrado"
+msgstr[1] "%{issues} problemas encerrados"
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgid_plural "%{merge_requests} closed merge requests"
+msgstr[0] "1 pedido de mesclagem encerrado"
+msgstr[1] "%{merge_requests} pedidos de mesclagem encerrados"
msgid "1 day"
-msgstr ""
+msgstr "1 dia"
msgid "1 group"
msgid_plural "%d groups"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 grupo"
+msgstr[1] "%d grupos"
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgid_plural "%{merge_requests} merged merge requests"
+msgstr[0] "1 pedido de mesclagem mesclado"
+msgstr[1] "%{merge_requests} pedidos de mesclagem mesclados"
msgid "1 open issue"
-msgid_plural "%d open issues"
-msgstr[0] ""
-msgstr[1] ""
+msgid_plural "%{issues} open issues"
+msgstr[0] "1 problema aberto"
+msgstr[1] "%{issues} problemas abertos"
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] "1 pedido de mesclagem aberto"
+msgstr[1] "%{merge_requests} pedidos de mesclagem abertos"
msgid "1 pipeline"
msgid_plural "%d pipelines"
@@ -344,771 +415,885 @@ msgstr[1] ""
msgid "1 role"
msgid_plural "%d roles"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 função"
+msgstr[1] "%d funções"
msgid "1 user"
msgid_plural "%d users"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 utilizador"
+msgstr[1] "%d utilizadores"
msgid "1 week"
-msgstr ""
+msgstr "1 semana"
+
+msgid "1-9 contributions"
+msgstr "1-9 contribuições"
+
+msgid "10-19 contributions"
+msgstr "10-19 contribuições"
msgid "1st contribution!"
-msgstr ""
+msgstr "1ª contribuição!"
+
+msgid "20-29 contributions"
+msgstr "20-29 contribuições"
msgid "2FA"
-msgstr ""
+msgstr "A2F"
msgid "2FA enabled"
+msgstr "A2F ativado"
+
+msgid "2FADevice|Registered On"
msgstr ""
msgid "3 days"
-msgstr ""
+msgstr "3 dias"
msgid "3 hours"
-msgstr ""
+msgstr "3 horas"
msgid "30 minutes"
-msgstr ""
+msgstr "30 minutos"
+
+msgid "30+ contributions"
+msgstr "30+ contribuições"
msgid "403|Please contact your GitLab administrator to get permission."
-msgstr ""
+msgstr "Entra em contacto com o teu administrador do GitLab para obter permissão."
msgid "403|You don't have the permission to access this page."
-msgstr ""
+msgstr "Não tens permissão para acessar esta página."
msgid "404|Make sure the address is correct and the page hasn't moved."
-msgstr ""
+msgstr "Certifica-te de que o endereço está correto e a página não foi movida."
msgid "404|Page Not Found"
-msgstr ""
+msgstr "Página Não Encontrada"
msgid "404|Please contact your GitLab administrator if you think this is a mistake."
-msgstr ""
+msgstr "Por favor, contacta o teu administrador do GitLab se achas que isto é um erro."
msgid "8 hours"
-msgstr ""
+msgstr "8 horas"
msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> adicionará \"Por <a href=\"#\">@johnsmith</a>\" a todos os problemas e comentários, originalmente, criados por johnsmith@example.com e definirá <a href=\"#\">@johnsmith</a> como o responsável de todos os problemas, originalmente, atribuídos a johnsmith@example.com."
msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"John Smith\"</code> adicionará \"Por John Smith\" a todos os problemas e comentários, originalmente, criados por johnsmith@example.com."
msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> adicionará \"Por johnsm...@example.com\" a todos os problemas e comentários, originalmente, criados por johnsmith@example.com. O endereço de email ou nome de utilizador é ocultado para garantir a privacidade do utilizador."
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
+msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> adicionará \"Por <a href=\"#\">johnsmith@example.com</a>\" a todos os problemas e comentários, originalmente, criados por johnsmith@example.com. Por padrão, o endereço de email ou nome de utilizador é ocultado para garantir a privacidade do utilizador. Use esta opção se quiser mostrar o endereço de email completo."
+
+msgid "<no name set>"
msgstr ""
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
-msgstr ""
+msgstr "<strong>%{changedFilesLength} alterações não organizadas</strong> e <strong>%{stagedFilesLength} alterações organizadas</strong>"
msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
-msgstr ""
+msgstr "<strong>%{created_count}</strong> criado(s), <strong>%{accepted_count}</strong> aceitado(s)."
msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
-msgstr ""
+msgstr "<strong>%{created_count}</strong> criado(s), <strong>%{closed_count}</strong> encerrado(s)."
msgid "<strong>%{group_name}</strong> group members"
-msgstr ""
+msgstr "Membros do grupo <strong>%{group_name}</strong>"
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
msgid "<strong>Deletes</strong> source branch"
-msgstr ""
+msgstr "<strong>Apagar</strong> o ramo de origem"
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr ""
+msgstr "Um 'Runner' é um processo que executa um trabalho. Podes configurar tantos 'Runners' quantos precisares."
msgid "A .NET Core console application template, customizable for any .NET Core project"
-msgstr ""
+msgstr "Um .NET Core de um modelo da aplicação de consola, personalizável para qualquer projeto .NET Core"
msgid "A GitBook site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr ""
+msgstr "Um site GitBook que usa o Netlify para CI/CD, em vez do GitLab, mas ainda com todos os outros ótimos recursos do GitLab."
msgid "A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr ""
+msgstr "Um site Hexo que usa o Netlify para CI/CD, em vez do GitLab, mas ainda com todos os outros ótimos recursos do GitLab."
msgid "A Hugo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr ""
+msgstr "Um site Hugo que usa o Netlify para CI/CD, em vez do GitLab, mas ainda com todos os outros ótimos recursos do GitLab."
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr ""
+msgstr "Um site Jekyll que usa o Netlify para CI/CD, em vez do GitLab, mas ainda com todos os outros ótimos recursos do GitLab."
+
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
+msgstr "Uma conta Vamos Criptografar será configurada para esta instalação no GitLab ao usar o teu endereço de email. Irás receber emails de aviso de expiração de certificados."
msgid "A default branch cannot be chosen for an empty project."
-msgstr ""
+msgstr "Um ramo padrão não pode ser escolhido para um projeto vazio."
msgid "A deleted user"
-msgstr ""
+msgstr "Um utilizador apagado"
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr ""
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
+msgstr "Um fork é uma cópia de um projeto.<br />Bifurcação de um repositório permite que faças alterações sem afetar o projeto original."
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
-msgstr ""
-
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
-msgstr ""
+msgstr "Um novo ramo será criado no teu fork e um novo pedido de mesclagem será iniciado."
msgid "A new impersonation token has been created."
-msgstr ""
+msgstr "Um novo token de representação foi criado."
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
-msgstr ""
+msgstr "Um site HTML simples que usa o Netlify para CI/CD, em vez do GitLab, mas ainda com todos os outros ótimos recursos do GitLab."
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
+msgstr "Um projeto é onde armazenas os teus ficheiros (repositório), planeias o teu trabalho (problemas), e publicas a tua documentação (wiki), %{among_other_things_link}."
msgid "A ready-to-go template for use with Android apps."
-msgstr ""
+msgstr "Um modelo pronto para uso para usar em aplicações Android."
msgid "A ready-to-go template for use with iOS Swift apps."
-msgstr ""
+msgstr "Um modelo pronto para uso para usar em aplicações iOS Swift."
msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
-msgstr ""
+msgstr "Uma expressão regular que será usada para encontrar a saída de cobertura de teste na localização de trabalho. Deixa em branco para desativar"
msgid "A user with write access to the source branch selected this option"
-msgstr ""
+msgstr "Um utilizador com permissão de escrita ao ramo de origem selecionado para esta opção"
msgid "API Help"
+msgstr "Ajuda da API"
+
+msgid "API Token"
msgstr ""
msgid "About GitLab"
-msgstr ""
+msgstr "Sobre o GitLab"
msgid "About GitLab CE"
-msgstr ""
+msgstr "Sobre o GitLab CE"
msgid "About auto deploy"
-msgstr ""
+msgstr "Sobre a implantação automática"
msgid "About this feature"
-msgstr ""
+msgstr "Sobre este recurso"
msgid "Abuse Reports"
-msgstr ""
+msgstr "Relatórios de Abuso"
msgid "Abuse reports"
-msgstr ""
+msgstr "Relatórios de abuso"
msgid "Accept invitation"
-msgstr ""
+msgstr "Aceitar convite"
msgid "Accept terms"
-msgstr ""
+msgstr "Aceitar os termos"
msgid "Accepted MR"
-msgstr ""
+msgstr "PM aceitado"
msgid "Access Tokens"
-msgstr ""
+msgstr "Tokens de Acesso"
msgid "Access denied for your LDAP account."
-msgstr ""
+msgstr "Acesso negado à tua conta LDAP."
msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr ""
+msgstr "Acesso negado! Por favor, verifica se podes adicionar chaves de implantação para este repositório."
msgid "Access expiration date"
-msgstr ""
+msgstr "Data de expiração do acesso"
msgid "Access forbidden. Check your access level."
-msgstr ""
+msgstr "Acesso proibido. Verifica o teu nível de acesso."
msgid "Access to '%{classification_label}' not allowed"
+msgstr "Acesso a(ao) '%{classification_label}' não permitido"
+
+msgid "AccessDropdown|Groups"
msgstr ""
-msgid "Account"
+msgid "AccessDropdown|Roles"
msgstr ""
+msgid "AccessDropdown|Users"
+msgstr ""
+
+msgid "Account"
+msgstr "Conta"
+
msgid "Account and limit"
+msgstr "Conta e limite"
+
+msgid "Account: %{account}"
msgstr ""
msgid "Action to take when receiving an alert."
-msgstr ""
+msgstr "Ação a tomar ao receber um alerta."
msgid "Activate Service Desk"
-msgstr ""
+msgstr "Ativar Central de Serviços"
msgid "Active"
-msgstr ""
+msgstr "Ativo"
msgid "Active Sessions"
-msgstr ""
+msgstr "Sessões Ativas"
msgid "Activity"
-msgstr ""
+msgstr "Atividade"
msgid "Add"
-msgstr ""
+msgstr "Adicionar"
msgid "Add CHANGELOG"
-msgstr ""
+msgstr "Adicionar Registo de alterações"
msgid "Add CONTRIBUTING"
msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
-msgstr ""
+msgstr "Adicionar Webhooks de Grupo e Edição Empresarial do GitLab."
msgid "Add Jaeger URL"
-msgstr ""
+msgstr "Adicionar URL Jaeger"
msgid "Add Kubernetes cluster"
-msgstr ""
+msgstr "Adicionar cluster Kubernetes"
msgid "Add README"
+msgstr "Adicionar README"
+
+msgid "Add a GPG key"
msgstr ""
msgid "Add a bullet list"
-msgstr ""
+msgstr "Adicionar uma lista de marcadores"
msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
+msgstr "Adicionar um comentário geral para este %{noteable_name}."
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
-msgstr ""
+msgstr "Adiciona uma página inicial à tua wiki que contenha informações sobre o teu projeto e o GitLab irá exibi-lo aqui, ao invés desta mensagem."
msgid "Add a link"
-msgstr ""
+msgstr "Adicionar um link"
msgid "Add a numbered list"
-msgstr ""
+msgstr "Adicionar uma lista numerada"
msgid "Add a table"
-msgstr ""
+msgstr "Adicionar uma tabela"
msgid "Add a task list"
-msgstr ""
+msgstr "Adicionar uma lista de tarefas"
+
+msgid "Add a todo"
+msgstr "Adicionar um \"a fazer\""
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr "Adiciona um texto adicional para aparecer em todas as comunicações por email. Limite de %{character_limit} caracteres"
+
+msgid "Add an SSH key"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
-msgstr ""
+msgstr "Adicionar aprovadores"
msgid "Add bold text"
+msgstr "Adicionar texto em negrito"
+
+msgid "Add child epic to an epic"
msgstr ""
msgid "Add comment now"
+msgstr "Adicionar comentário agora"
+
+msgid "Add email address"
msgstr ""
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
-msgstr ""
+msgstr "Adicionar cabeçalho e rodapé aos emails. Por favor, nota que as definições de cor só serão aplicadas dentro da interface da aplicação"
msgid "Add image comment"
-msgstr ""
+msgstr "Adicionar comentário de imagem"
msgid "Add italic text"
-msgstr ""
+msgstr "Adicionar texto em itálico"
+
+msgid "Add label(s)"
+msgstr "Adicionar rótulo(s)"
msgid "Add license"
-msgstr ""
+msgstr "Adicionar licença"
msgid "Add list"
-msgstr ""
+msgstr "Adicionar lista"
msgid "Add new application"
-msgstr ""
+msgstr "Adicionar nova aplicação"
msgid "Add new directory"
-msgstr ""
+msgstr "Adicionar novo diretório"
+
+msgid "Add or subtract spent time"
+msgstr "Adicionar ou subtrair o tempo gasto"
msgid "Add reaction"
+msgstr "Adicionar reação"
+
+msgid "Add to merge train"
msgstr ""
-msgid "Add to project"
+msgid "Add to merge train when pipeline succeeds"
msgstr ""
+msgid "Add to project"
+msgstr "Adicionar ao projeto"
+
msgid "Add to review"
-msgstr ""
+msgstr "Adicionar à revisão"
msgid "Add todo"
-msgstr ""
+msgstr "Adicionar \"a fazer\""
msgid "Add user(s) to the group:"
-msgstr ""
-
-msgid "Add users or groups who are allowed to approve every merge request"
-msgstr ""
+msgstr "Adicionar utilizador(es) ao grupo:"
msgid "Add users to group"
-msgstr ""
+msgstr "Adicionar utilizadores ao grupo"
+
+msgid "AddMember|No users specified."
+msgstr "Nenhum utilizador especificado."
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
+msgstr "Muitos utilizadores especificados (o limite é %{user_limit})"
msgid "Added at"
-msgstr ""
+msgstr "Adicionado em"
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
-msgstr ""
+msgstr "A adição de novas aplicações está desativada na tua instância do GitLab. Entra em contacto com o teu administrador do GitLab para obter a permissão"
+
+msgid "Additional minutes"
+msgstr "Minutos adicionais"
msgid "Additional text"
-msgstr ""
+msgstr "Texto adicional"
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr "Adiciona"
+
+msgid "Adds %{epic_ref} as child epic."
msgstr ""
+msgid "Adds a todo."
+msgstr "Adicionar um \"a fazer\"."
+
msgid "Admin Area"
-msgstr ""
+msgstr "Ãrea de Administração"
msgid "Admin Overview"
-msgstr ""
+msgstr "Visão Geral do Administrador"
msgid "Admin Section"
+msgstr "Secção de Administração"
+
+msgid "Admin notes"
msgstr ""
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Estás prestes a apagar, permanentemente, o utilizador %{username}. Problemas, pedidos de mesclagem, e grupos vinculados a ele, serão transferidos a um \"utilizador fantasma\" em todo o sistema. Para evitar a perda de dados, considera usar o recurso %{strong_start}bloquear utilizador%{strong_end}. Assim, que %{strong_start}apagares o utilizador%{strong_end}, não será possível desfazer ou recuperá-lo."
msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Estás prestes a apagar, permanentemente, o utilizador %{username}. Isto apagará todos os problemas, pedidos de mesclagem e grupos vinculados a ele. Para evitar a perda de dados, considera usar o recurso %{strong_start}bloquear utilizador%{strong_end}. Assim, que%{strong_start}apagares o utilizador%{strong_end}, não será possível desfazer ou recuperá-lo."
msgid "AdminArea|Stop all jobs"
-msgstr ""
+msgstr "Parar todos os trabalhos"
msgid "AdminArea|Stop all jobs?"
-msgstr ""
+msgstr "Parar todos os trabalhos?"
msgid "AdminArea|Stop jobs"
-msgstr ""
+msgstr "Parar trabalhos"
msgid "AdminArea|Stopping jobs failed"
-msgstr ""
+msgstr "Erro ao parar trabalhos"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
-msgstr ""
+msgstr "Estás prestes a parar todos os trabalhos. Isto irá interromper todos os trabalhos em execução."
+
+msgid "AdminNote|Note"
+msgstr "Nota"
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Estás prestes a apagar, permanentemente, o projeto %{projectName}, o teu repositório e todos os recursos relacionados, incluindo problemas, pedidos de mesclagem, etc. Assim, que confirmares e pressionares %{strong_start}Apagar projeto%{strong_end}, não será possível desfazer ou recuperá-lo."
msgid "AdminProjects|Delete"
-msgstr ""
+msgstr "Apagar"
msgid "AdminProjects|Delete Project %{projectName}?"
-msgstr ""
+msgstr "Apagar o Projeto %{projectName}?"
msgid "AdminProjects|Delete project"
-msgstr ""
+msgstr "Apagar projeto"
msgid "AdminSettings|Auto DevOps domain"
-msgstr ""
+msgstr "Domínio Auto DevOps"
msgid "AdminSettings|Enable shared runners for new projects"
-msgstr ""
+msgstr "Ativar runners compartilhados aos novos projetos"
msgid "AdminSettings|Environment variables are protected by default"
-msgstr ""
+msgstr "Variáveis de ambiente são protegidas por padrão"
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
-msgstr ""
+msgstr "Especifica um domínio para utilizar por padrão para cada projeto, Revisão Automática de Aplicações e Implementação Automática de fases."
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
-msgstr ""
+msgstr "Ao criar uma nova variável de ambiente, ela será protegida por padrão."
msgid "AdminUsers|2FA Disabled"
-msgstr ""
+msgstr "A2F Desativada"
msgid "AdminUsers|2FA Enabled"
-msgstr ""
+msgstr "A2F Ativada"
msgid "AdminUsers|Active"
-msgstr ""
+msgstr "Ativo"
msgid "AdminUsers|Admin"
-msgstr ""
+msgstr "Administrador"
msgid "AdminUsers|Admins"
-msgstr ""
+msgstr "Administradores"
msgid "AdminUsers|Block user"
-msgstr ""
+msgstr "Bloquear utilizador"
msgid "AdminUsers|Blocked"
-msgstr ""
+msgstr "Bloqueado"
msgid "AdminUsers|Cannot unblock LDAP blocked users"
-msgstr ""
+msgstr "Não é possível desbloquear utilizadores bloqueados em LDAP"
msgid "AdminUsers|Delete User %{username} and contributions?"
-msgstr ""
+msgstr "Apagar Utilizador %{username} e as suas contribuições?"
msgid "AdminUsers|Delete User %{username}?"
-msgstr ""
+msgstr "Apagar Utilizador %{username}?"
msgid "AdminUsers|Delete user"
-msgstr ""
+msgstr "Apagar utilizador"
msgid "AdminUsers|Delete user and contributions"
-msgstr ""
+msgstr "Apagar utilizador e as suas contribuições"
msgid "AdminUsers|External"
-msgstr ""
+msgstr "Externo"
msgid "AdminUsers|It's you!"
-msgstr ""
+msgstr "És tu!"
msgid "AdminUsers|New user"
-msgstr ""
+msgstr "Novo utilizador"
msgid "AdminUsers|No users found"
-msgstr ""
+msgstr "Nenhum utilizador encontrado"
msgid "AdminUsers|Search by name, email or username"
-msgstr ""
+msgstr "Pesquisar por nome, email ou nome de utilizador"
msgid "AdminUsers|Search users"
-msgstr ""
+msgstr "Pesquisar utilizadores"
msgid "AdminUsers|Send email to users"
-msgstr ""
+msgstr "Enviar email aos utilizadores"
msgid "AdminUsers|Sort by"
-msgstr ""
+msgstr "Ordenar por"
msgid "AdminUsers|To confirm, type %{projectName}"
-msgstr ""
+msgstr "Para confirmar, digita %{projectName}"
msgid "AdminUsers|To confirm, type %{username}"
-msgstr ""
+msgstr "Para confirmar, digita %{username}"
msgid "AdminUsers|User will be blocked"
-msgstr ""
+msgstr "O utilizador será bloqueado"
msgid "AdminUsers|Without projects"
-msgstr ""
+msgstr "Sem projetos"
msgid "Advanced"
-msgstr ""
+msgstr "Avançado"
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
-msgstr ""
+msgstr "Permissões avançadas, Armazenamento de Ficheiro Grandes e definições de autenticação de Dois Fatores."
msgid "Advanced search functionality"
-msgstr ""
+msgstr "Funcionalidade de pesquisa avançada"
msgid "Advanced settings"
-msgstr ""
+msgstr "Definições avançadas"
msgid "After a successful password update you will be redirected to login screen."
+msgstr "Após uma atualização de palavra-passe bem-sucedida, serás redirecionado à tela de início de sessão."
+
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
msgid "Alert"
msgid_plural "Alerts"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Alerta"
+msgstr[1] "Alertas"
msgid "Alerts"
-msgstr ""
+msgstr "Alertas"
msgid "All"
-msgstr ""
+msgstr "Todos"
msgid "All Members"
-msgstr ""
+msgstr "Todos os Membros"
msgid "All changes are committed"
+msgstr "Todas as alterações foram enviadas"
+
+msgid "All email addresses will be used to identify your commits."
msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr "Todos os recursos estão ativos para os projetos vazios, a partir de modelos ou ao importar, mas poderás desativá-las, posteriormente, nas definições do projeto."
+
+msgid "All groups and projects"
msgstr ""
msgid "All issues for this milestone are closed. You may close this milestone now."
-msgstr ""
+msgstr "Todos os problemas para estes objetivos estão encerrados. Podes agora, fechar este objetivo."
msgid "All merge conflicts were resolved. The merge request can now be merged."
-msgstr ""
+msgstr "Todos os conflitos de mesclagem foram resolvidos. O pedido de mesclagem pode agora ser mesclado."
+
+msgid "All projects"
+msgstr "Todos os projetos"
msgid "All todos were marked as done."
-msgstr ""
+msgstr "Todos os \"a fazer\" foram marcados como concluídos."
msgid "All users"
-msgstr ""
+msgstr "Todos os utilizadores"
msgid "All users must have a name."
-msgstr ""
+msgstr "Todos os utilizadores devem ter um nome."
msgid "Allow \"%{group_name}\" to sign you in"
-msgstr ""
+msgstr "Permitir que \"%{group_name}\" adicione-te"
msgid "Allow commits from members who can merge to the target branch."
-msgstr ""
+msgstr "Permitir envios de membros que podem mesclar ao ramo de destino."
msgid "Allow group owners to manage LDAP-related settings"
-msgstr ""
+msgstr "Permitir que proprietários de grupos gerenciem as definições relacionadas ao LDAP"
msgid "Allow mirrors to be set up for projects"
-msgstr ""
+msgstr "Permitir espelhos para que sejam configurados aos projetos"
msgid "Allow only the selected protocols to be used for Git access."
-msgstr ""
+msgstr "Permitir apenas, que os protocolos selecionados sejam usados para acessar o Git."
msgid "Allow projects within this group to use Git LFS"
-msgstr ""
+msgstr "Permitir que projetos dentro deste grupo usem o Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
-msgstr ""
+msgstr "Permitir acesso público às pipelines e detalhes do trabalho, incluindo registos de saída e artefatos"
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
-msgstr ""
+msgstr "Permitir renderização de diagramas PlantUML em documentos Asciidoc."
msgid "Allow requests to the local network from hooks and services."
-msgstr ""
+msgstr "Permitir pedidos à rede local dos hooks e serviços."
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
-msgstr ""
+msgstr "Permitir que esta chave seja também, enviada ao repositório? (O padrão só permite o acesso pull)"
msgid "Allow users to register any application to use GitLab as an OAuth provider"
-msgstr ""
+msgstr "Permitir que os utilizadores se registem a qualquer aplicação para usar o GitLab como um fornecedor OAuth"
msgid "Allow users to request access"
-msgstr ""
+msgstr "Permitir que os utilizadores solicitem acesso"
msgid "Allow users to request access if visibility is public or internal."
-msgstr ""
+msgstr "Permitir que os utilizadores peçam acesso, caso a visibilidade for pública ou interna."
msgid "Allowed to fail"
-msgstr ""
+msgstr "Permissão para falhar"
msgid "Allows you to add and manage Kubernetes clusters."
-msgstr ""
+msgstr "Permite -te adicionar e gerenciar clusters do Kubernetes."
msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
-msgstr ""
+msgstr "Também chamado de \"Emissor\" ou \"identificador de confiança de terceiros\""
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
-msgstr ""
+msgstr "Também chamado de \"URL do serviço de terceiros\" ou \"URL de resposta\""
msgid "Alternate support URL for help page"
-msgstr ""
+msgstr "Suporte alternativo URL para a página de ajuda"
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
-msgstr ""
+msgstr "Alternativamente, podes usar um %{personal_access_token_link}. Quando crias o teu Token de Acesso Pessoal, vais precisar de selecionar o escopo do <code>repositório</code>, para que possamos exibir uma lista dos teus repositórios públicos e privados que estão disponíveis para serem conectados."
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
-msgstr ""
+msgstr "Alternativamente, podes usar um %{personal_access_token_link}. Quando crias o teu Token de Acesso Pessoal, vais precisar de selecionar o escopo do <code>repositório</code>, para que possamos mostrar a lista dos teus repositórios públicos e privados que estão disponíveis para importar."
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
-msgstr ""
-
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
+msgstr "Quantidade de tempo (em horas) que os utilizadores podem ignorar a configuração forçada da autenticação de dois fatores"
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
-msgstr ""
+msgstr "Uma aplicação chamada %{link_to_client} está a pedir acesso à tua conta do GitLab."
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
-msgstr ""
+msgstr "Um campo vazio do Utilizador do GitLab adicionará o nome completo do utilizador do FogBugz (por exemplo, \"Por John Smith\") na descrição de todos os problemas e comentários. Ele também irá associar e/ou atribuir estes problemas e comentários ao criador do projeto."
msgid "An error has occurred"
-msgstr ""
+msgstr "Ocorreu um erro"
msgid "An error occurred adding a draft to the discussion."
-msgstr ""
+msgstr "Ocorreu um erro ao adicionar um rascunho ao tópico."
msgid "An error occurred adding a new draft."
-msgstr ""
+msgstr "Ocorreu um erro ao adicionar um novo rascunho."
msgid "An error occurred creating the new branch."
-msgstr ""
+msgstr "Ocorreu um erro ao criar o novo ramo."
msgid "An error occurred fetching the approval rules."
-msgstr ""
+msgstr "Ocorreu um erro ao buscar as regras de aprovação."
msgid "An error occurred fetching the approvers for the new rule."
-msgstr ""
+msgstr "Ocorreu um erro ao buscar os aprovadores para as novas regras."
msgid "An error occurred fetching the dropdown data."
-msgstr ""
+msgstr "Ocorreu um erro ao buscar os dados suspensos."
msgid "An error occurred previewing the blob"
-msgstr ""
+msgstr "Ocorreu um erro ao pré-visualizar o blob"
msgid "An error occurred when toggling the notification subscription"
-msgstr ""
+msgstr "Ocorreu um erro ao alternar a notificação de assinatura"
-msgid "An error occurred when updating the issue weight"
-msgstr ""
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr "Ocorreu um erro ao tentar resolver um comentário. Por favor, tenta novamente."
-msgid "An error occurred while adding approver"
-msgstr ""
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr "Ocorreu um erro ao tentar resolver um tópico. Por favor, tenta novamente."
+
+msgid "An error occurred when updating the issue weight"
+msgstr "Ocorreu um erro ao atualizar o peso do problema"
msgid "An error occurred while deleting the approvers group"
-msgstr ""
+msgstr "Ocorreu um erro ao apagar os aprovadores do grupo"
msgid "An error occurred while deleting the comment"
-msgstr ""
+msgstr "Ocorreu um erro ao apagar o comentário"
msgid "An error occurred while detecting host keys"
-msgstr ""
+msgstr "Ocorreu um erro ao detectar as chaves do host"
msgid "An error occurred while disabling Service Desk."
-msgstr ""
+msgstr "Ocorreu um erro ao desativar a Central de Serviços."
msgid "An error occurred while dismissing the alert. Refresh the page and try again."
-msgstr ""
+msgstr "Ocorreu um erro ao dispensar o alerta. Atualiza a página e tenta novamente."
msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
-msgstr ""
+msgstr "Ocorreu um erro ao dispensar o recurso de destaque. Atualiza a página e tenta dispensar novamente."
msgid "An error occurred while enabling Service Desk."
+msgstr "Ocorreu um erro ao ativar a Central de Serviços."
+
+msgid "An error occurred while fetching environments."
msgstr ""
-msgid "An error occurred while fetching markdown preview"
+msgid "An error occurred while fetching folder content."
msgstr ""
+msgid "An error occurred while fetching label colors."
+msgstr "Ocorreu um erro ao buscar as cores dos rótulos."
+
+msgid "An error occurred while fetching markdown preview"
+msgstr "Ocorreu um erro ao buscar a pré-visualização do markdown"
+
msgid "An error occurred while fetching pending comments"
-msgstr ""
+msgstr "Ocorreu um erro ao buscar os comentários pendentes"
-msgid "An error occurred while fetching sidebar data"
-msgstr ""
+msgid "An error occurred while fetching projects autocomplete."
+msgstr "Ocorreu um erro ao buscar projetos de conclusão automática."
-msgid "An error occurred while fetching stages."
-msgstr ""
+msgid "An error occurred while fetching sidebar data"
+msgstr "Ocorreu um erro ao buscar os dados da barra lateral"
msgid "An error occurred while fetching the Service Desk address."
-msgstr ""
+msgstr "Ocorreu um erro ao buscar o endereço da Central de Serviços."
+
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr "Ocorreu um erro ao buscar as listas do painel. Por favor, tenta novamente."
+
+msgid "An error occurred while fetching the builds."
+msgstr "Ocorreu um erro ao buscar as compilações."
msgid "An error occurred while fetching the job log."
-msgstr ""
+msgstr "Ocorreu um erro ao buscar o registo do trabalho."
msgid "An error occurred while fetching the job."
-msgstr ""
+msgstr "Ocorreu um erro ao buscar o trabalho."
msgid "An error occurred while fetching the jobs."
-msgstr ""
+msgstr "Ocorreu um erro ao buscar os trabalhos."
msgid "An error occurred while fetching the pipeline."
-msgstr ""
+msgstr "Ocorreu um erro ao buscar a pipeline."
msgid "An error occurred while fetching the releases. Please try again."
-msgstr ""
+msgstr "Ocorreu um erro ao buscar os lançamentos. Por favor, tenta novamente."
+
+msgid "An error occurred while fetching this tab."
+msgstr "Ocorreu um erro ao buscar esta aba."
msgid "An error occurred while getting projects"
-msgstr ""
+msgstr "Ocorreu um erro ao receber os projetos"
msgid "An error occurred while importing project: %{details}"
-msgstr ""
+msgstr "Ocorreu um erro durante a importação do projeto: %{details}"
msgid "An error occurred while initializing path locks"
-msgstr ""
+msgstr "Ocorreu um erro ao iniciar bloqueios de caminho"
msgid "An error occurred while loading chart data"
-msgstr ""
+msgstr "Ocorreu um erro ao carregar os dados do gráfico"
msgid "An error occurred while loading commit signatures"
-msgstr ""
+msgstr "Ocorreu um erro ao carregar as assinaturas de envio"
msgid "An error occurred while loading designs. Please try again."
-msgstr ""
+msgstr "Ocorreu um erro ao carregar os designs. Por favor, tenta novamente."
msgid "An error occurred while loading diff"
-msgstr ""
+msgstr "Ocorreu um erro ao carregar o diff"
msgid "An error occurred while loading filenames"
-msgstr ""
+msgstr "Ocorreu um erro ao carregar os nomes dos ficheiros"
msgid "An error occurred while loading the file"
-msgstr ""
+msgstr "Ocorreu um erro ao carregar o ficheiro"
msgid "An error occurred while loading the subscription details."
-msgstr ""
+msgstr "Ocorreu um erro ao carregar os detalhes da assinatura."
msgid "An error occurred while making the request."
-msgstr ""
+msgstr "Ocorreu um erro ao fazer o pedido."
-msgid "An error occurred while removing approver"
-msgstr ""
+msgid "An error occurred while moving the issue."
+msgstr "Ocorreu um erro ao mover o problema."
+
+msgid "An error occurred while parsing recent searches"
+msgstr "Ocorreu um erro ao analisar pesquisas recentes"
msgid "An error occurred while removing epics."
-msgstr ""
+msgstr "Ocorreu um erro ao remover épicos."
msgid "An error occurred while removing issues."
-msgstr ""
+msgstr "Ocorreu um erro ao remover problemas."
msgid "An error occurred while rendering KaTeX"
-msgstr ""
+msgstr "Ocorreu um erro ao renderizar o KaTeX"
msgid "An error occurred while rendering preview broadcast message"
-msgstr ""
+msgstr "Ocorreu um erro ao renderizar a mensagem de pré-visualização da transmissão"
msgid "An error occurred while retrieving calendar activity"
-msgstr ""
+msgstr "Ocorreu um erro ao recuperar as atividades do calendário"
msgid "An error occurred while retrieving diff"
-msgstr ""
+msgstr "Ocorreu um erro ao recuperar o diff"
msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
+msgstr "Ocorreu um erro ao guardar o estado de sobreposição do LDAP. Por favor, tenta novamente."
msgid "An error occurred while saving assignees"
-msgstr ""
+msgstr "Ocorreu um erro ao guardar destinatários"
msgid "An error occurred while saving the approval settings"
-msgstr ""
+msgstr "Ocorreu um erro ao guardar as definições de aprovação"
msgid "An error occurred while subscribing to notifications."
-msgstr ""
+msgstr "Ocorreu um erro ao assinar as notificações."
msgid "An error occurred while unsubscribing to notifications."
-msgstr ""
+msgstr "Ocorreu um erro ao cancelar a assinatura das notificações."
msgid "An error occurred while updating approvers"
-msgstr ""
+msgstr "Ocorreu um erro ao atualizar aprovadores"
msgid "An error occurred while updating the comment"
-msgstr ""
+msgstr "Ocorreu um erro ao atualizar o comentário"
msgid "An error occurred while validating username"
-msgstr ""
+msgstr "Ocorreu um erro ao validar o nome de utilizador"
msgid "An error occurred whilst committing your changes."
-msgstr ""
+msgstr "Ocorreu um erro ao enviar as tuas alterações."
msgid "An error occurred whilst fetching the job trace."
msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
+msgstr "Ocorreu um erro ao buscar o pipeline mais recente."
+
+msgid "An error occurred whilst getting files for - %{branchId}"
msgstr ""
msgid "An error occurred whilst loading all the files."
-msgstr ""
+msgstr "Ocorreu um erro durante o carregamento de todos os ficheiros."
msgid "An error occurred whilst loading the file content."
-msgstr ""
+msgstr "Ocorreu um erro ao carregar o conteúdo do ficheiro."
msgid "An error occurred whilst loading the file."
-msgstr ""
+msgstr "Ocorreu um erro ao carregar o ficheiro."
msgid "An error occurred whilst loading the merge request changes."
-msgstr ""
+msgstr "Ocorreu um erro ao carregar as alterações do pedido de mesclagem."
msgid "An error occurred whilst loading the merge request version data."
-msgstr ""
+msgstr "Ocorreu um erro ao carregar os dados da versão do pedido de mesclagem."
msgid "An error occurred whilst loading the merge request."
-msgstr ""
+msgstr "Ocorreu um erro ao carregar o pedido de mesclagem."
msgid "An error occurred whilst loading the pipelines jobs."
msgstr ""
msgid "An error occurred. Please try again."
-msgstr ""
+msgstr "Ocorreu um erro. Por favor, tenta novamente."
msgid "An unexpected error occurred while checking the project environment."
-msgstr ""
+msgstr "Ocorreu um erro inesperado ao verificar o ambiente do projeto."
msgid "An unexpected error occurred while checking the project runners."
-msgstr ""
+msgstr "Ocorreu um erro inesperado ao verificar os runners do projeto."
msgid "An unexpected error occurred while communicating with the Web Terminal."
msgstr ""
@@ -1126,204 +1311,252 @@ msgid "Ancestors"
msgstr ""
msgid "Anonymous"
-msgstr ""
+msgstr "Anónimo"
msgid "Anti-spam verification"
-msgstr ""
+msgstr "Verificação anti-spam"
msgid "Any"
-msgstr ""
+msgstr "Qualquer"
msgid "Any Label"
-msgstr ""
+msgstr "Qualquer Rótulo"
+
+msgid "Any Milestone"
+msgstr "Qualquer Objetivo"
msgid "Any encrypted tokens"
-msgstr ""
+msgstr "Quaisquer tokens encriptados"
+
+msgid "Any namespace"
+msgstr "Qualquer namespace"
msgid "Appearance"
-msgstr ""
+msgstr "Aparência"
msgid "Appearance was successfully created."
-msgstr ""
+msgstr "A aparência foi criada com sucesso."
msgid "Appearance was successfully updated."
-msgstr ""
+msgstr "A aparência foi atualizada com sucesso."
+
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr "Anexar o comentário com %{TABLEFLIP}"
+
+msgid "Append the comment with %{shrug}"
+msgstr "Anexar o comentário com %{shrug}"
msgid "Application"
-msgstr ""
+msgstr "Aplicação"
msgid "Application ID"
-msgstr ""
+msgstr "ID da Aplicação"
msgid "Application settings saved successfully"
-msgstr ""
+msgstr "Definições da aplicação salvas com sucesso"
+
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr "Aplicação desinstalada mas falhou ao destruir: %{error_message}"
msgid "Application was successfully destroyed."
-msgstr ""
+msgstr "A aplicação foi destruída com sucesso."
msgid "Application was successfully updated."
-msgstr ""
+msgstr "A aplicação foi atualizada com sucesso."
msgid "Application: %{name}"
-msgstr ""
+msgstr "Aplicação: %{name}"
msgid "Applications"
-msgstr ""
+msgstr "Aplicações"
msgid "Applied"
-msgstr ""
+msgstr "Aplicado"
msgid "Apply suggestion"
-msgstr ""
+msgstr "Aplicar sugestão"
+
+msgid "Applying command"
+msgstr "A aplicar comando"
+
+msgid "Applying command to %{commandDescription}"
+msgstr "A aplicar comando a %{commandDescription}"
+
+msgid "Applying multiple commands"
+msgstr "A aplicar vários comandos"
+
+msgid "Applying suggestion"
+msgstr "A aplicar a sugestão"
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d membro"
+msgstr[1] "%d membros"
msgid "ApprovalRuleRemove|Approvals from this member are not revoked."
msgid_plural "ApprovalRuleRemove|Approvals from these members are not revoked."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Aprovações deste membro não são revogadas."
+msgstr[1] "Aprovações destes membros não são revogadas."
msgid "ApprovalRuleRemove|You are about to remove the %{name} approver group which has %{nMembers}."
-msgstr ""
+msgstr "Estás prestes a remover o grupo de aprovação %{name} que tem %{nMembers}."
msgid "ApprovalRuleSummary|%d member"
msgid_plural "ApprovalRuleSummary|%d members"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d membro"
+msgstr[1] "%d membros"
msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} aprovação obrigatória de %{membersCount}"
+msgstr[1] "%{count} aprovações obrigatórias de %{membersCount}"
msgid "ApprovalRule|All members with Developer role or higher and code owners (if any)"
-msgstr ""
+msgstr "Todos os membros com a função de Desenvolvedor ou superior e proprietários de código (se houver)"
msgid "ApprovalRule|Members"
-msgstr ""
+msgstr "Membros"
msgid "ApprovalRule|Name"
-msgstr ""
+msgstr "Nome"
msgid "ApprovalRule|No. approvals required"
-msgstr ""
+msgstr "Nº de aprovações obrigatórias"
msgid "ApprovalRule|e.g. QA, Security, etc."
msgstr ""
msgid "Approvals"
-msgstr ""
-
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
+msgstr "Aprovações"
msgid "Apr"
-msgstr ""
+msgstr "abr"
msgid "April"
-msgstr ""
+msgstr "abril"
msgid "Archive jobs"
msgstr ""
msgid "Archive project"
-msgstr ""
+msgstr "Arquivar projeto"
msgid "Archived project! Repository and other project resources are read-only"
-msgstr ""
+msgstr "Projeto arquivado! Repositório e outros recursos de projeto são somente de leitura"
msgid "Archived projects"
-msgstr ""
+msgstr "Projetos arquivados"
msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. <strong>The repository cannot be committed to, and no issues, comments or other entities can be created.</strong>"
-msgstr ""
+msgstr "Arquivar o projeto fará com que ele seja, completamente, somente de leitura. Ele está escondido do painel de controlo e não aparece em pesquisas. <strong>O repositório não pode ser comprometido, e nenhum problema, comentários ou outras entidades podem ser criadas.</strong>"
msgid "Are you sure"
-msgstr ""
+msgstr "Tens a certeza"
msgid "Are you sure that you want to archive this project?"
-msgstr ""
+msgstr "Tens a certeza de que desejas arquivar este projeto?"
msgid "Are you sure that you want to unarchive this project?"
+msgstr "Tens a certeza de que desejas desarquivar este projeto?"
+
+msgid "Are you sure you want to cancel creating this comment?"
+msgstr "Tens a certeza de que desejas cancelar a criação deste comentário?"
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr "Tens a certeza de que desejas cancelar a edição deste comentário?"
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
+msgid "Are you sure you want to delete this list?"
+msgstr "Tens a certeza de que desejas apagar esta lista?"
+
msgid "Are you sure you want to delete this pipeline schedule?"
-msgstr ""
+msgstr "Tens a certeza de que desejas apagar este agendamento de pipeline?"
msgid "Are you sure you want to erase this build?"
-msgstr ""
+msgstr "Tens a certeza de que desejas apagar esta compilação?"
msgid "Are you sure you want to lose unsaved changes?"
-msgstr ""
+msgstr "Tens a certeza de que queres perder as alterações não guardadas?"
msgid "Are you sure you want to lose your issue information?"
-msgstr ""
+msgstr "Tens a certeza de que desejas alterar as informações do teu perfil?"
msgid "Are you sure you want to permanently delete this license?"
-msgstr ""
+msgstr "Tens a certeza de que desejas apagar permanentemente esta licença?"
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
-msgstr ""
+msgstr "Tens a certeza de que pretendes gerar novamente a chave pública? Terás que atualizar a chave pública no servidor remoto para que a sincronização fique novamente a funcionar."
msgid "Are you sure you want to remove %{group_name}?"
-msgstr ""
-
-msgid "Are you sure you want to remove approver %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove approver %{name}?"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}?"
-msgstr ""
+msgstr "Tens a certeza de que queres remover %{group_name}?"
msgid "Are you sure you want to remove the attachment?"
-msgstr ""
+msgstr "Tens a certeza de que desejas remover o anexo?"
msgid "Are you sure you want to remove this identity?"
-msgstr ""
+msgstr "Tens a certeza de que queres remover esta identidade?"
msgid "Are you sure you want to reset registration token?"
-msgstr ""
+msgstr "Tens a certeza de que queres recriar o token de registo?"
msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
+msgstr "Tens a certeza de que desejas repor o token SCIM? O provisionamento de SCIM irá parar de funcionar até que o novo token seja atualizado."
msgid "Are you sure you want to reset the health check token?"
+msgstr "Tens a certeza de que queres reiniciar o token de estado de saúde?"
+
+msgid "Are you sure you want to revoke this nickname?"
msgstr ""
msgid "Are you sure you want to stop this environment?"
-msgstr ""
+msgstr "Tens a certeza de que desejas parar este ambiente?"
msgid "Are you sure you want to unlock %{path_lock_path}?"
-msgstr ""
+msgstr "Tens a certeza de que queres desbloquear %{path_lock_path}?"
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
-msgstr ""
+msgstr "Tens a certeza de que desejas cancelar o recebimento do %{type}: %{link_to_noteable_text}?"
msgid "Are you sure?"
+msgstr "Tens a certeza?"
+
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
msgstr ""
-msgid "Artifact ID"
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
+msgid "Artifact ID"
+msgstr "ID do Artefato"
+
msgid "Artifacts"
+msgstr "Artefatos"
+
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
-msgid "Ascending"
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr "Asana - Trabalho em equipa sem email"
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr "Lista separada por vírgulas de ramos, que será, automaticamente, inspecionados. Deixa em branco para incluir todos os ramos."
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr "Token de Acesso Pessoal do Utilizador. O utilizador deve ter acesso à tarefa, todos os comentários serão atribuídos a este utilizador."
+
+msgid "Ascending"
+msgstr "Ascendente"
+
msgid "Ask your group maintainer to set up a group Runner."
-msgstr ""
+msgstr "Pede ao responsável do grupo para configurar um grupo Runner."
msgid "Assertion consumer service URL"
msgstr ""
@@ -1331,8 +1564,11 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr "Atribuir"
+
msgid "Assign custom color like #FF0000"
-msgstr ""
+msgstr "Atribui uma cor personalizada, como #FF0000"
msgid "Assign labels"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1461,17 +1711,26 @@ msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr "A pipeline Auto DevOps foi ativada e será usada se nenhum ficheiro de configuração de IC alternativo for encontrado. %{more_information_link}"
+
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr "Nota"
+
msgid "Available"
msgstr ""
@@ -1509,88 +1768,112 @@ msgid "Badges"
msgstr ""
msgid "Badges|A new badge was added."
-msgstr ""
+msgstr "Foi adicionado um novo emblema."
msgid "Badges|Add badge"
-msgstr ""
+msgstr "Adicionar emblema"
msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
-msgstr ""
+msgstr "Falha ao adicionar emblema, por favor, verifica os URLs inseridos e tenta novamente."
msgid "Badges|Badge image URL"
-msgstr ""
+msgstr "URL da imagem do emblema"
msgid "Badges|Badge image preview"
-msgstr ""
+msgstr "Pré-visualização da imagem do emblema"
msgid "Badges|Delete badge"
-msgstr ""
+msgstr "Apagar emblema"
msgid "Badges|Delete badge?"
-msgstr ""
+msgstr "Apagar emblema?"
msgid "Badges|Deleting the badge failed, please try again."
-msgstr ""
+msgstr "Erro ao apagar emblema, por favor, tenta novamente."
msgid "Badges|Group Badge"
-msgstr ""
+msgstr "Emblema do grupo"
msgid "Badges|Link"
-msgstr ""
+msgstr "Link"
msgid "Badges|No badge image"
-msgstr ""
+msgstr "Sem imagem de emblema"
msgid "Badges|No image to preview"
-msgstr ""
+msgstr "Sem imagem para pré-visualizar"
msgid "Badges|Please fill in a valid URL"
-msgstr ""
+msgstr "Por favor, preenche uma URL válida"
msgid "Badges|Project Badge"
-msgstr ""
+msgstr "Emblema do Projeto"
msgid "Badges|Reload badge image"
-msgstr ""
+msgstr "Recarregar imagem do emblema"
msgid "Badges|Save changes"
-msgstr ""
+msgstr "Guardar alterações"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
-msgstr ""
+msgstr "Erro ao guardar o emblema, por favor, verifica os URLs introduzidos e tenta novamente."
msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr ""
+msgstr "As %{docsLinkStart}variáveis%{docsLinkEnd} suportadas pelo GitLab: %{placeholders}"
msgid "Badges|The badge was deleted."
-msgstr ""
+msgstr "O emblema foi apagado."
msgid "Badges|The badge was saved."
-msgstr ""
+msgstr "O emblema foi guardado."
msgid "Badges|This group has no badges"
-msgstr ""
+msgstr "Este grupo não tem emblemas"
msgid "Badges|This project has no badges"
-msgstr ""
+msgstr "Este projeto não tem emblemas"
msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr ""
+msgstr "Estás prestes a apagar este emblema. Emblemas apagados <strong>não podem</strong> ser restaurados."
msgid "Badges|Your badges"
-msgstr ""
+msgstr "Os teus emblemas"
msgid "Badges|e.g. %{exampleUrl}"
+msgstr "por exemplo, %{exampleUrl}"
+
+msgid "Badge|New"
+msgstr "Novo"
+
+msgid "Balsamiq file could not be loaded."
msgstr ""
+msgid "BambooService|A continuous integration and build server"
+msgstr "Uma integração contínua e servidor de construção"
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr "Um utilizador com acesso à API, se aplicável"
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr "Atlassian Bamboo CI"
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr "Chave de plano de compilação do Bamboo como KEY"
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr "URL raiz do Bamboo como https://bamboo.example.com"
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr "Deves configurar um rótulo de revisão automático e um disparador de repositório no Bamboo."
+
msgid "BatchComments|Delete all pending comments"
-msgstr ""
+msgstr "Apagar todos os comentários pendentes"
msgid "BatchComments|Discard review?"
-msgstr ""
+msgstr "Rejeitar revisão?"
msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
-msgstr ""
+msgstr "Estás prestes a rejeitar a tua revisão, o que apagará todos os teus comentários pendentes. Os comentários apagados %{strong_start}não podem%{strong_end} ser restaurados."
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -1611,67 +1894,67 @@ msgid "Billing"
msgstr ""
msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
-msgstr ""
+msgstr "%{group_name} está atualmente no plano %{plan_link}."
msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
-msgstr ""
+msgstr "Downgrade e atualização automática para alguns planos, está, atualmente, não disponível."
msgid "BillingPlans|Current plan"
-msgstr ""
+msgstr "Plano atual"
msgid "BillingPlans|Customer Support"
-msgstr ""
+msgstr "Suporte ao Cliente"
msgid "BillingPlans|Downgrade"
-msgstr ""
+msgstr "Downgrade"
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
-msgstr ""
+msgstr "Aprende mais sobre cada plano ao ler o nosso %{faq_link} ou inicia uma avaliação gratuita de 30 dias do GitLab.com Gold."
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
-msgstr ""
+msgstr "Aprende mais sobre cada plano ao ler as nossas %{faq_link}."
msgid "BillingPlans|Manage plan"
-msgstr ""
+msgstr "Gerenciar plano"
msgid "BillingPlans|Please contact %{customer_support_link} in that case."
-msgstr ""
+msgstr "Por favor, entra em contacto com %{customer_support_link} para resolver o teu caso."
msgid "BillingPlans|See all %{plan_name} features"
-msgstr ""
+msgstr "Vê todos os recursos do %{plan_name}"
msgid "BillingPlans|This group uses the plan associated with its parent group."
-msgstr ""
+msgstr "Este grupo utiliza o plano de associados com o teu grupo pai."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
-msgstr ""
+msgstr "Para gerenciar o plano para este grupo, visita a secção de facturação de %{parent_billing_page_link}."
msgid "BillingPlans|Upgrade"
-msgstr ""
+msgstr "Atualizar"
msgid "BillingPlans|You are currently on the %{plan_link} plan."
-msgstr ""
+msgstr "Estás atualmente no plano %{plan_link}."
msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
-msgstr ""
+msgstr "O teu GitLab.com avaliação expirou em %{expiration_date}. %{learn_more_text}"
msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
-msgstr ""
+msgstr "A tua demonstração de Ouro irá <strong>expirar após %{expiration_date}</strong>. Podes aprender mais sobre o GitLab.com Gold ao ler sobre os nossos %{features_link}."
msgid "BillingPlans|features"
-msgstr ""
+msgstr "recursos"
msgid "BillingPlans|frequently asked questions"
-msgstr ""
+msgstr "perguntas frequentes"
msgid "BillingPlans|monthly"
-msgstr ""
+msgstr "mensalmente"
msgid "BillingPlans|paid annually at %{price_per_year}"
-msgstr ""
+msgstr "pago anualmente em %{price_per_year}"
msgid "BillingPlans|per user"
-msgstr ""
+msgstr "por utilizador"
msgid "Bitbucket Server Import"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1701,11 +2003,14 @@ msgid "Branch has changed"
msgstr ""
msgid "Branch is already taken"
-msgstr ""
+msgstr "Ramo já está a ser usado"
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1713,61 +2018,61 @@ msgid "BranchSwitcherTitle|Switch branch"
msgstr ""
msgid "Branches"
-msgstr ""
+msgstr "Ramos"
msgid "Branches|Active"
-msgstr ""
+msgstr "Ativo"
msgid "Branches|Active branches"
-msgstr ""
+msgstr "Ramos ativos"
msgid "Branches|All"
-msgstr ""
+msgstr "Todos"
msgid "Branches|Cant find HEAD commit for this branch"
-msgstr ""
+msgstr "Não foi possível encontrar o envio do HEAD para este ramo"
msgid "Branches|Compare"
-msgstr ""
+msgstr "Comparar"
msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
-msgstr ""
+msgstr "Apagar todos os ramos que foram mesclados em '%{default_branch}'"
msgid "Branches|Delete branch"
-msgstr ""
+msgstr "Apagar ramo"
msgid "Branches|Delete merged branches"
-msgstr ""
+msgstr "Apagar ramos que foram mesclados"
msgid "Branches|Delete protected branch"
-msgstr ""
+msgstr "Apagar ramo protegido"
msgid "Branches|Delete protected branch '%{branch_name}'?"
-msgstr ""
+msgstr "Apagar ramo protegido '%{branch_name}'?"
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
-msgstr ""
+msgstr "Apagar o ramo '%{branch_name}' não pode ser desfeito. Tens a certeza?"
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
-msgstr ""
+msgstr "Ao apagar os ramos mesclados não pode ser desfeito. Tens a certeza?"
msgid "Branches|Filter by branch name"
-msgstr ""
+msgstr "Filtrar por nome de ramo"
msgid "Branches|Merged into %{default_branch}"
msgstr ""
msgid "Branches|New branch"
-msgstr ""
+msgstr "Novo ramo"
msgid "Branches|No branches to show"
-msgstr ""
+msgstr "Nenhum ramo para mostrar"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Uma vez que confirmares e pressionares %{delete_protected_branch}, não pode ser desfeito ou recuperado."
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
-msgstr ""
+msgstr "Somente um responsável ou dono do projeto poderá apagar ramos protegidas"
msgid "Branches|Overview"
msgstr ""
@@ -1785,28 +2090,28 @@ msgid "Branches|Show more active branches"
msgstr ""
msgid "Branches|Show more stale branches"
-msgstr ""
+msgstr "Mostrar mais ramos obsoletos"
msgid "Branches|Show overview of the branches"
msgstr ""
msgid "Branches|Show stale branches"
-msgstr ""
+msgstr "Mostrar os ramos obsoletos"
msgid "Branches|Sort by"
msgstr ""
msgid "Branches|Stale"
-msgstr ""
+msgstr "Obsoleto"
msgid "Branches|Stale branches"
-msgstr ""
+msgstr "Ramos obsoletos"
msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
-msgstr ""
+msgstr "O ramo não pode ser atualizado, automaticamente,, porque ele divergiu do teu upstream de contrapartida."
msgid "Branches|The default branch cannot be deleted"
-msgstr ""
+msgstr "O ramo padrão não pode ser apagado"
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr ""
@@ -1824,10 +2129,10 @@ msgid "Branches|You’re about to permanently delete the protected branch %{bran
msgstr ""
msgid "Branches|diverged from upstream"
-msgstr ""
+msgstr "divergiu da upstream"
msgid "Branches|merged"
-msgstr ""
+msgstr "mesclado"
msgid "Branches|project settings"
msgstr ""
@@ -1856,6 +2161,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr "Por padrão, todos os projetos e grupos usarão as definições globais de notificações."
+
msgid "ByAuthor|by"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2664,12 +3074,12 @@ msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from th
msgstr ""
msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
-msgstr ""
+msgstr "Substituiristo com o teu próprio nome de host, se o quiseres. Se o fizeres, aponta o nome de host ao Endereço IP de Entrada a partir de cima."
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2876,7 +3313,7 @@ msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
msgstr ""
msgid "Commit to %{branchName} branch"
-msgstr ""
+msgstr "Enviar para o ramo %{branchName}"
msgid "CommitBoxTitle|Commit"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3257,7 +3739,7 @@ msgid "Create group"
msgstr ""
msgid "Create group label"
-msgstr ""
+msgstr "Criar rótulo do grupo"
msgid "Create lists from labels. Issues with that label appear in that list."
msgstr ""
@@ -3290,11 +3772,17 @@ msgid "Create new..."
msgstr ""
msgid "Create project label"
-msgstr ""
+msgstr "Criar rótulo do projeto"
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3356,7 +3862,7 @@ msgid "Custom project templates"
msgstr ""
msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
-msgstr ""
+msgstr "Modelos de projeto personalizados não foram configurados para grupos dos quais é membro. Eles são ativados na página de definições de um grupo. Entra em contacto com o proprietário ou responsável do teu grupo para configurar modelos de projetos personalizados."
msgid "Customize colors"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3515,13 +4063,13 @@ msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
msgid "Deleting the license failed."
-msgstr ""
+msgstr "Ocorreu um erro ao apagar a licença."
msgid "Deleting the license failed. The license was not found."
msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
-msgstr ""
+msgstr "Ocorreu um erro ao apagar a licença. Não tens permissões para realizar esta operação."
msgid "Denied authorization of chat nickname %{user_name}."
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3946,11 +4584,14 @@ msgid "Email"
msgstr ""
msgid "Email address"
-msgstr ""
+msgstr "Endereço de email"
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr "Ficheiros, diretórios e submódulos no caminho %{path} para referência de envio %{ref}"
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4923,7 +5795,7 @@ msgid "Forward external support email address to"
msgstr ""
msgid "Found errors in your %{gitlab_ci_yml}:"
-msgstr ""
+msgstr "Erros encontrados no teu %{gitlab_ci_yml}:"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -4974,7 +5855,7 @@ msgid "General"
msgstr ""
msgid "General Settings"
-msgstr ""
+msgstr "Definições Gerais"
msgid "General pipelines"
msgstr ""
@@ -5214,7 +6095,7 @@ msgid "Geo|File sync capacity"
msgstr ""
msgid "Geo|Geo Status"
-msgstr ""
+msgstr "Estado Geo"
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr "Definições globais de notificação"
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5550,7 +6455,7 @@ msgid "Group info:"
msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
+msgstr "Os responsáveis do grupo podem registar runners de grupo no %{link}"
msgid "Group name"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr "Grupos (%{count})"
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr "Histórico de autenticações"
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6454,7 +7554,7 @@ msgid "Label actions dropdown"
msgstr ""
msgid "Label lists show all issues with the selected label."
-msgstr ""
+msgstr "Listas de rótulos que mostram todos os problemas com o rótulo selecionado."
msgid "Label was created"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6770,7 +7915,7 @@ msgid "Logs"
msgstr ""
msgid "MRApprovals|Approved by"
-msgstr ""
+msgstr "Aprovado por"
msgid "MRApprovals|Approvers"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr "Correspondência não encontrada;; tenta refinar a tua consulta de pesquisa."
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6911,11 +8086,14 @@ msgid "Members"
msgstr ""
msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
-msgstr ""
+msgstr "Os membros podem ser adicionados ao projeto <i>Responsáveis</i> ou <i>Proprietários</i>"
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7124,7 +8326,7 @@ msgid "Metrics|There was an error getting environments information."
msgstr ""
msgid "Metrics|There was an error trying to validate your query"
-msgstr ""
+msgstr "Houve um erro ao tentar validar a tua consulta"
msgid "Metrics|There was an error while retrieving metrics"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7540,6 +8817,9 @@ msgid "No milestones to show"
msgstr ""
msgid "No other labels with such name or description"
+msgstr "Nenhuns outros rótulos com tal nome ou descrição"
+
+msgid "No parent group"
msgstr ""
msgid "No preview for this file type"
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr "Definições de notificação salvas"
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr "Personalizado"
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7860,11 +9179,14 @@ msgid "Or you can choose one of the suggested colors below"
msgstr ""
msgid "Other Labels"
-msgstr ""
+msgstr "Outros Rótulos"
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr "Por favor, adiciona um comentário na área de texto acima"
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8700,10 +10235,10 @@ msgid "ProjectCreationLevel|Default project creation protection"
msgstr ""
msgid "ProjectCreationLevel|Developers + Maintainers"
-msgstr ""
+msgstr "Desenvolvedores + Responsáveis"
msgid "ProjectCreationLevel|Maintainers"
-msgstr ""
+msgstr "Responsáveis"
msgid "ProjectCreationLevel|No one"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,17 +10366,77 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr "Projetos (%{count})"
+
msgid "Projects Successfully Retrieved"
msgstr ""
msgid "Projects shared with %{group_name}"
-msgstr ""
+msgstr "Projetos compartilhados com %{group_name}"
msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr "Receber notificações sobre a tua própria atividade"
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9644,7 +11476,7 @@ msgid "Scope"
msgstr ""
msgid "Scope not supported with disabled 'users_search' feature!"
-msgstr ""
+msgstr "Escopo não compatível com o recurso desabilitado 'users_search'!"
msgid "Scoped issue boards"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr "Pesquisar por um grupo LDAP"
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10088,26 +11980,38 @@ msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in
msgstr ""
msgid "Shared Runners"
-msgstr ""
+msgstr "Runners Compartilhados"
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
-msgstr ""
+msgstr "Repor os minutos do pipeline"
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
-msgstr ""
+msgstr "Repor os minutos de pipeline que foram usados"
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr "Conectado com a autenticação de %{authentication}"
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10369,16 +12303,16 @@ msgid "SortOptions|Largest repository"
msgstr ""
msgid "SortOptions|Last Contact"
-msgstr ""
+msgstr "Último Contacto"
msgid "SortOptions|Last created"
-msgstr ""
+msgstr "Último criado"
msgid "SortOptions|Last joined"
-msgstr ""
+msgstr "Última conexão"
msgid "SortOptions|Last updated"
-msgstr ""
+msgstr "Última atualização"
msgid "SortOptions|Least popular"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10564,6 +12513,12 @@ msgid "Start discussion & close %{noteable_name}"
msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
+msgstr "Iniciar a discussão e reabrir %{noteable_name}"
+
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
msgstr ""
msgid "Start the Runner!"
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr "Assinatura"
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10705,7 +12669,7 @@ msgid "SubscriptionTable|Subscription start date"
msgstr ""
msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
-msgstr ""
+msgstr "Esta é a última vez que a equipa do GitLab.com estava em contacto contigo para resolver quaisquer saldos pendentes."
msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10765,11 +12795,17 @@ msgid "Support for custom certificates is disabled. Ask your system's administra
msgstr ""
msgid "Support page URL"
-msgstr ""
+msgstr "Página URL de suporte"
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,11 +13039,14 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
-msgstr ""
+msgstr "O estágio de codificação mostra a hora do primeiro envio para criar o pedido de mesclagem. Os dados serão adicionados, automaticamente,, assim que criares o teu primeiro pedido de mesclagem."
msgid "The collection of events added to the data gathered for that stage."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11100,7 +13220,7 @@ msgid "The repository must be accessible over <code>http://</code>, <code>https:
msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
-msgstr ""
+msgstr "A fase de revisão mostra a hora do primeiro envio para criar o envio de mesclagem. Os dados serão adicionados, automaticamente,, assim que criares o teu primeiro pedido de mesclagem."
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,20 +13276,35 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
msgid "There are no closed merge requests"
-msgstr ""
+msgstr "Não há pedidos de mesclagem encerrados"
msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
msgstr ""
@@ -11175,13 +13313,13 @@ msgid "There are no issues to show"
msgstr ""
msgid "There are no labels yet"
-msgstr ""
+msgstr "Não há ainda rótulos"
msgid "There are no open issues"
msgstr ""
msgid "There are no open merge requests"
-msgstr ""
+msgstr "Não há pedidos de mesclagem abertos"
msgid "There are no packages yet"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,21 +13420,33 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
msgstr ""
+msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
+msgstr "Esta confirmação faz parte do pedido de mesclagem %{link_to_merge_request}. Os comentários criados aqui, serão criados no contexto desse pedido de mesclagem."
+
msgid "This commit was signed with a <strong>verified</strong> signature and the committer email is verified to belong to the same user."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr "Este é um registo de segurança de eventos importantes que envolvem a tua conta."
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,16 +13997,25 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
msgid "ToggleButton|Toggle Status: OFF"
-msgstr ""
+msgstr "Alternar Estado: DESLIGADO"
msgid "ToggleButton|Toggle Status: ON"
+msgstr "Alternar Estado: LIGADO"
+
+msgid "Toggles :%{name}: emoji award."
msgstr ""
msgid "Token"
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12259,11 +14769,20 @@ msgid "UserProfile|You haven't created any personal projects."
msgstr ""
msgid "UserProfile|You haven't created any snippets."
-msgstr ""
+msgstr "UserProfile|Não criaste nenhuns fragmentos."
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,11 +15355,17 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
msgid "You can also test your %{gitlab_ci_yml} in %{lint_link_start}CI Lint%{lint_link_end}"
-msgstr ""
+msgstr "Também podes testar o teu %{gitlab_ci_yml} em %{lint_link_start}CI Lint%{lint_link_end}"
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr "Podes convidar um novo para <strong>%{project_name}</strong> ou convidar outro grupo."
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr "Podes convidar um novo membro para <strong>%{project_name}</strong>."
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr "Podes convidar outro grupo para <strong>%{project_name}</strong>."
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12834,6 +15473,12 @@ msgid "You don't have any authorized applications"
msgstr ""
msgid "You don't have any deployments right now."
+msgstr "Não tens nenhumas implantações por enquanto."
+
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
msgstr ""
msgid "You have been granted %{member_human_access} access to %{label}."
@@ -12864,6 +15509,15 @@ msgid "You must accept our Terms of Service and privacy policy in order to regis
msgstr ""
msgid "You must have maintainer access to force delete a lock"
+msgstr "Deves ter acesso de responsável para forçar o apagamento de um bloqueio"
+
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
msgstr ""
msgid "You need a different license to enable FileLocks feature"
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12903,10 +15563,10 @@ msgid "You will not get any notifications via email"
msgstr ""
msgid "You will only receive notifications for the events you choose"
-msgstr ""
+msgstr "Irás apenas receber notificações para eventos que escolheres"
msgid "You will only receive notifications for threads you have participated in"
-msgstr ""
+msgstr "Irás apenas receber notificações para tópicos que participaste"
msgid "You will receive notifications for any activity"
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13038,22 +15731,25 @@ msgid "Your request for access has been queued for review."
msgstr ""
msgid "a deleted user"
-msgstr ""
+msgstr "um utilizador apagado"
msgid "added %{created_at_timeago}"
-msgstr ""
+msgstr "adicionado %{created_at_timeago}"
msgid "ago"
-msgstr ""
+msgstr "atrás"
msgid "allowed to fail"
-msgstr ""
+msgstr "permissão para falhar"
-msgid "among other things"
-msgstr ""
+msgid "already being used for another group or project milestone."
+msgstr "já está a ser usado por outro grupo ou objetivos do projeto."
-msgid "at"
-msgstr ""
+msgid "already shared with this group"
+msgstr "já foi compartilhado com este grupo"
+
+msgid "among other things"
+msgstr "entre outras coisas"
msgid "attach a new file"
msgstr ""
@@ -13062,11 +15758,26 @@ msgid "authored"
msgstr ""
msgid "branch name"
-msgstr ""
+msgstr "nome do ramo"
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr "Adiciona um comentário ou razão para dispensar"
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr "Adicionar comentário e dispensa"
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr "Dispensar vulnerabilidade"
+
+msgid "vulnerability|Undo dismiss"
+msgstr "Desfazer dispensa"
+
+msgid "vulnerability|dismissed"
+msgstr "dispensado"
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/ro_RO/gitlab.po b/locale/ro_RO/gitlab.po
index c508597c9cc..bd79e38ba94 100644
--- a/locale/ro_RO/gitlab.po
+++ b/locale/ro_RO/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Romanian\n"
"Language: ro_RO\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ro\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:30\n"
+"PO-Revision-Date: 2019-06-14 10:15\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -72,6 +69,12 @@ msgstr[2] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -114,12 +117,24 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -147,10 +162,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -186,6 +198,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -198,12 +216,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -219,6 +249,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -237,6 +273,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -273,6 +321,9 @@ msgstr[2] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -285,9 +336,30 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -312,6 +384,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -331,13 +406,13 @@ msgstr[1] ""
msgstr[2] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -352,19 +427,19 @@ msgstr[1] ""
msgstr[2] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -390,15 +465,27 @@ msgstr[2] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -408,6 +495,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -438,6 +528,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -474,19 +567,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -516,6 +609,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -561,12 +657,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -603,6 +711,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -624,10 +735,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -636,9 +753,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -648,6 +771,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -660,9 +786,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -675,10 +810,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
+msgstr ""
+
+msgid "AddMember|No users specified."
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -687,10 +825,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -702,6 +849,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -723,6 +873,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -837,6 +990,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -855,15 +1011,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -936,9 +1101,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -972,10 +1134,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -999,21 +1164,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -1029,6 +1209,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1062,7 +1245,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1116,6 +1302,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1173,9 +1362,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1185,6 +1380,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1194,6 +1395,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1212,6 +1416,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1257,12 +1473,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1293,37 +1503,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1341,6 +1551,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1353,12 +1566,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1371,6 +1608,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1386,6 +1626,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1416,6 +1662,15 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1503,15 +1758,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1623,6 +1887,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1725,12 +2013,33 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1746,6 +2055,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1896,6 +2208,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1914,6 +2241,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -2004,9 +2334,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -2028,9 +2364,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2046,6 +2388,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2058,6 +2406,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2082,6 +2439,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2109,6 +2472,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2130,6 +2496,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2160,7 +2529,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2232,16 +2601,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2295,9 +2682,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2352,6 +2748,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2370,7 +2769,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2388,12 +2793,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2409,6 +2826,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2517,6 +2937,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2553,19 +2976,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2598,6 +3012,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2634,6 +3051,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2643,9 +3063,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2709,7 +3126,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2763,40 +3180,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2808,6 +3237,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2817,6 +3249,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2868,9 +3303,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2889,6 +3330,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -3009,6 +3453,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -3036,9 +3483,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3051,9 +3504,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3117,6 +3576,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3162,6 +3624,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3171,6 +3636,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3189,9 +3657,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3207,6 +3672,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3216,6 +3687,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3225,9 +3699,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3261,9 +3741,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3336,6 +3825,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3351,12 +3846,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3375,6 +3885,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3453,15 +3966,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3498,6 +4035,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3549,6 +4089,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3570,6 +4125,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3747,6 +4350,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3801,9 +4407,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3825,6 +4437,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3855,18 +4473,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3879,25 +4521,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3939,6 +4575,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3975,6 +4614,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3993,6 +4638,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -4017,9 +4665,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4044,6 +4722,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4080,9 +4761,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4113,12 +4791,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4131,7 +4815,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4143,9 +4830,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4281,18 +4992,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4329,9 +5073,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4341,6 +5091,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4350,6 +5106,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4359,6 +5118,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4392,9 +5157,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4491,6 +5262,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4578,6 +5352,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4587,27 +5382,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4626,6 +5454,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4638,16 +5472,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4662,6 +5508,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4725,7 +5577,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4737,9 +5589,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4821,6 +5670,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4869,6 +5724,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4878,6 +5736,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4902,6 +5763,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4947,6 +5814,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4956,6 +5832,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4974,6 +5853,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -5004,12 +5886,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5367,6 +6255,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5424,6 +6318,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5433,6 +6330,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5505,6 +6405,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5523,9 +6426,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5601,6 +6513,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5610,6 +6525,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5637,13 +6555,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5655,9 +6576,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5688,9 +6606,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5754,6 +6681,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5823,6 +6753,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5850,6 +6783,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5859,12 +6795,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5874,6 +6813,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5889,6 +6831,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5904,6 +6852,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5913,6 +6867,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5982,10 +6942,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6066,6 +7035,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6075,6 +7050,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6084,9 +7065,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6138,12 +7128,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6165,12 +7164,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6219,18 +7230,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6240,6 +7275,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6252,6 +7290,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6270,6 +7311,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6345,6 +7392,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6441,6 +7530,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6450,6 +7545,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6474,12 +7572,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6492,6 +7596,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6540,6 +7647,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6555,6 +7665,9 @@ msgstr[2] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6582,6 +7695,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6597,6 +7716,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6615,6 +7740,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6627,6 +7755,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6648,6 +7779,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6723,6 +7860,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6738,6 +7878,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6768,6 +7911,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6789,6 +7935,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6807,6 +7956,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6831,12 +7983,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6897,6 +8058,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6909,6 +8079,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6933,6 +8112,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6963,6 +8145,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6975,15 +8160,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6993,12 +8172,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -7017,6 +8190,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -7035,6 +8232,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7047,6 +8247,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7080,7 +8283,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7095,6 +8298,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7110,6 +8319,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7149,9 +8361,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7197,9 +8406,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7224,9 +8445,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7245,7 +8463,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7254,6 +8472,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7275,6 +8502,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7335,6 +8574,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7347,6 +8604,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7443,6 +8703,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7467,6 +8730,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7497,6 +8763,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7506,12 +8778,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7527,6 +8808,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7551,6 +8835,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7572,9 +8859,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7590,6 +8874,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7617,6 +8904,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7665,6 +8958,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7680,6 +8976,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7689,6 +8991,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7743,6 +9048,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7758,6 +9066,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7773,7 +9087,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7797,13 +9117,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7821,6 +9141,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7866,6 +9189,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7890,9 +9219,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7914,6 +9240,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7923,6 +9252,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7950,6 +9285,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7971,9 +9309,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7986,7 +9336,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -8013,6 +9363,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -8034,12 +9387,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8118,6 +9486,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8127,10 +9498,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgstr ""
+
+msgid "Pipelines| to purchase more minutes."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8151,6 +9525,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8211,6 +9588,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8241,6 +9621,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8250,12 +9639,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8286,6 +9693,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8298,6 +9708,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8319,7 +9738,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8337,12 +9756,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8358,12 +9831,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8391,15 +9870,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8430,6 +9918,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8451,6 +9942,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8463,6 +9957,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8490,6 +9987,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8499,9 +10008,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8511,18 +10026,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8541,9 +10071,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8559,13 +10086,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8580,6 +10110,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8601,6 +10134,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8694,6 +10230,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8739,6 +10278,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8790,6 +10332,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8799,18 +10359,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8820,12 +10422,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8982,6 +10644,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -9000,16 +10671,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -9018,18 +10695,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9078,9 +10761,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9105,12 +10794,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9135,15 +10866,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9159,24 +10899,45 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9201,6 +10962,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9213,6 +10977,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9222,7 +10989,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9231,25 +11001,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9264,6 +11046,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9294,6 +11094,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9303,7 +11106,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9318,6 +11121,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9357,12 +11163,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9417,6 +11217,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9429,6 +11235,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9468,6 +11277,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9510,6 +11328,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9549,6 +11370,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9633,6 +11460,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9642,6 +11472,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9657,6 +11490,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9669,6 +11505,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9729,9 +11568,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9753,6 +11604,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9828,9 +11682,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9861,12 +11712,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9879,6 +11742,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9906,6 +11775,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9942,6 +11814,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -10023,6 +11898,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10053,19 +11931,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10083,6 +11964,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10104,6 +11988,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10131,6 +12018,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10146,6 +12045,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10158,9 +12060,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10176,9 +12087,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10233,12 +12141,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10248,6 +12174,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10257,6 +12186,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10326,6 +12258,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10344,6 +12279,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10368,7 +12306,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10380,6 +12318,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10440,6 +12381,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10494,6 +12438,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10566,6 +12516,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10590,6 +12543,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10620,6 +12576,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10680,12 +12642,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10716,6 +12684,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10788,6 +12759,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10812,6 +12786,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10824,6 +12861,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10854,18 +12897,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10947,6 +13002,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10959,6 +13017,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10974,6 +13035,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -11013,6 +13101,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -11028,6 +13119,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11085,6 +13179,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11103,6 +13206,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11127,9 +13236,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11139,6 +13260,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11148,6 +13272,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11187,6 +13314,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11208,15 +13338,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11250,9 +13395,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11268,6 +13428,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11286,6 +13452,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11298,6 +13467,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11310,18 +13482,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11346,6 +13530,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11358,6 +13548,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11367,22 +13560,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11454,12 +13656,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11532,6 +13728,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11718,6 +13920,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11733,6 +13938,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11799,6 +14007,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11835,6 +14046,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11847,9 +14061,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11859,6 +14079,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11901,6 +14124,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11952,15 +14211,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11970,24 +14244,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -12006,18 +14298,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12087,6 +14394,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12138,6 +14457,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12147,6 +14469,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12165,6 +14490,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12174,6 +14547,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12231,6 +14610,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12246,6 +14628,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12321,6 +14838,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12336,9 +14862,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12384,12 +14928,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12399,6 +14949,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12408,6 +14961,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12435,6 +14991,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12462,6 +15021,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12504,6 +15090,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12522,6 +15111,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12531,6 +15123,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12552,6 +15147,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12561,13 +15159,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12582,6 +15183,9 @@ msgstr[2] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12762,6 +15366,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12777,7 +15384,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12789,6 +15402,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12804,6 +15420,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12822,6 +15444,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12846,9 +15477,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12879,12 +15516,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12894,6 +15540,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12924,6 +15576,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12936,6 +15597,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12948,6 +15612,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12981,6 +15648,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -13002,27 +15672,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -13056,7 +15750,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13074,6 +15771,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13107,10 +15807,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13125,6 +15828,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13224,6 +15942,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13257,9 +15978,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13275,12 +15993,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13401,9 +16113,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13422,10 +16131,10 @@ msgstr[2] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13467,6 +16176,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13500,9 +16212,15 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13515,6 +16233,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13539,6 +16263,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13569,6 +16296,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13578,6 +16311,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13596,6 +16332,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13623,6 +16362,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13650,7 +16392,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13665,6 +16407,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13719,6 +16464,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13737,18 +16485,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13779,24 +16524,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13881,15 +16614,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -14004,7 +16752,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -14013,18 +16761,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -14058,12 +16818,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/ru/gitlab.po b/locale/ru/gitlab.po
index 8298adf4526..08836089f1d 100644
--- a/locale/ru/gitlab.po
+++ b/locale/ru/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Russian\n"
"Language: ru_RU\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ru\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-13 17:27\n"
+"PO-Revision-Date: 2019-06-14 10:15\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr " СтатуÑ"
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -77,6 +74,13 @@ msgstr[3] "на %d коммитов позади"
msgid "%d commits"
msgstr "%d коммитов"
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d ÑкÑпортер"
@@ -126,6 +130,13 @@ msgstr[1] "%d запроÑа на ÑлиÑние"
msgstr[2] "%d запроÑов на ÑлиÑние"
msgstr[3] "%d запроÑов на ÑлиÑние"
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d метрика"
@@ -133,6 +144,13 @@ msgstr[1] "%d метрики"
msgstr[2] "%d метрик"
msgstr[3] "%d метрик"
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] "%d запиÑанное изменение"
@@ -163,11 +181,8 @@ msgstr "ОбÑуждение %{authorsName}"
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} Ñоздан %{commit_timeago}"
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr "%{counter_storage} (%{counter_repositories} репозиториев, %{counter_build_artifacts} Ñборок артефактов, %{counter_lfs_objects} LFS)"
-
-msgid "%{count} %{alerts}"
-msgstr "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
+msgstr ""
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
@@ -205,6 +220,12 @@ msgstr[1] "%{count} комментариев в ожидании"
msgstr[2] "%{count} комментариев в ожидании"
msgstr[3] "%{count} комментарии в ожидании"
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr "%{filePath} удален"
@@ -217,12 +238,24 @@ msgstr "%{gitlab_ci_yml} не найден в Ñтом коммите"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}Группы%{group_docs_link_end} позволÑÑŽÑ‚ управлÑÑ‚ÑŒ неÑколькими проектами и Ñотрудничать Ñ Ð½Ð¸Ð¼Ð¸. Члены группы имеют доÑтуп ко вÑем ее проектам."
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} будет удален! Вы уверены?"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} недоÑтупно"
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -238,6 +271,12 @@ msgstr "%{lock_path} заблокирован пользователем GitLab
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr "Ðватар Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{name}"
@@ -256,6 +295,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -281,10 +332,10 @@ msgstr ""
msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%{strong_start}%{tag_count}%{strong_end} Тег"
+msgstr[1] "%{strong_start}%{tag_count}%{strong_end} Тега"
+msgstr[2] "%{strong_start}%{tag_count}%{strong_end} Тегов"
+msgstr[3] "%{strong_start}%{tag_count}%{strong_end} Тегов"
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
@@ -296,6 +347,9 @@ msgstr[3] "%{text} %{files} файлах"
msgid "%{text} is available"
msgstr "%{text} доÑтупен"
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² %{title}"
@@ -308,9 +362,31 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr "Ñтраница Ð¿Ñ€Ð¾Ñ„Ð¸Ð»Ñ %{user_name}"
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr "(внешний иÑточник)"
@@ -335,6 +411,9 @@ msgstr "- Runner приоÑтановлен и не получит новые з
msgid "- show less"
msgstr "- Ñвернуть"
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] "1 дополнение типа %{type}"
@@ -357,18 +436,18 @@ msgstr[2] ""
msgstr[3] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
-msgstr[0] "1 закрытое обÑуждение"
-msgstr[1] "%d закрытых обÑуждений"
-msgstr[2] "%d закрытых обÑуждений"
-msgstr[3] "%d закрытых обÑуждений"
+msgid_plural "%{issues} closed issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
-msgstr[0] "1 закрытый Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
-msgstr[1] "%d закрытых запроÑов на ÑлиÑние"
-msgstr[2] "%d закрытых запроÑов на ÑлиÑние"
-msgstr[3] "%d закрытых запроÑов на ÑлиÑние"
+msgid_plural "%{merge_requests} closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "1 day"
msgstr ""
@@ -381,25 +460,25 @@ msgstr[2] "%d групп"
msgstr[3] "%d групп"
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
-msgstr[0] "1 объединенный Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
-msgstr[1] "%d объединенных запроÑов на ÑлиÑние"
-msgstr[2] "%d объединенных запроÑов на ÑлиÑние"
-msgstr[3] "%d объединенные запроÑов на ÑлиÑние"
+msgid_plural "%{merge_requests} merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
-msgstr[0] "1 открытое обÑуждение"
-msgstr[1] "%d открытых обÑуждений"
-msgstr[2] "%d открытых обÑуждений"
-msgstr[3] "%d открытых обÑуждений"
+msgid_plural "%{issues} open issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
-msgstr[0] "1 открытый Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
-msgstr[1] "%d открытых запроÑов на ÑлиÑние"
-msgstr[2] "%d открытых запроÑов на ÑлиÑние"
-msgstr[3] "%d открытых запроÑов на ÑлиÑние"
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "1 pipeline"
msgid_plural "%d pipelines"
@@ -425,15 +504,27 @@ msgstr[3] "%d пользователей"
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr "Первый вклад!"
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr "Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ"
msgid "2FA enabled"
msgstr "Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð°"
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -443,6 +534,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr "ПожалуйÑта обратитеÑÑŒ к вашему админиÑтратору GitLab Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ."
@@ -473,6 +567,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -509,19 +606,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
+msgstr ""
+
msgid "A default branch cannot be chosen for an empty project."
msgstr "Ð”Ð»Ñ Ð¿ÑƒÑтого проекта Ð½ÐµÐ»ÑŒÐ·Ñ Ð²Ñ‹Ð±Ñ€Ð°Ñ‚ÑŒ ветку по умолчанию."
msgid "A deleted user"
msgstr "Удаленный пользователь"
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr "Сотрудник группы по борьбе Ñ Ð½Ð°Ñ€ÑƒÑˆÐµÐ½Ð¸Ñми GitLab раÑÑмотрит ваш отчет так быÑтро, наÑколько Ñто возможно."
-
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -551,6 +648,9 @@ msgstr "Пользователь Ñ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸ÐµÐ¼ на запиÑÑŒ в
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr "О GitLab"
@@ -596,12 +696,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr "ДоÑтуп к '%{classification_label}' не разрешён"
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr "Ð£Ñ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ"
msgid "Account and limit"
msgstr "Ðккаунт и ограничениÑ"
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr "ДейÑтвиÑ, предпринимаемые при получении предупреждениÑ."
@@ -638,6 +750,9 @@ msgstr "Добавить Kubernetes клаÑтер"
msgid "Add README"
msgstr "Добавить README"
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr "Добавить маркированный ÑпиÑок"
@@ -659,11 +774,17 @@ msgstr "Добавить таблицу"
msgid "Add a task list"
msgstr "Добавить ÑпиÑок задач"
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Добавить дополнительный текÑÑ‚, который будет отображатьÑÑ Ð²Ð¾ вÑех ÑообщениÑÑ… Ñлектронной почты. МакÑимум %{character_limit} Ñимволов"
-msgid "Add approver(s)"
-msgstr "Добавить утверждающего(их)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
+msgstr ""
msgid "Add approvers"
msgstr "Добавить утверждающих"
@@ -671,9 +792,15 @@ msgstr "Добавить утверждающих"
msgid "Add bold text"
msgstr "Добавить жирный текÑÑ‚"
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr "Добавить комментарий"
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -683,6 +810,9 @@ msgstr "Добавить комментарий к изображению"
msgid "Add italic text"
msgstr "Добавить курÑив"
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr "Добавить лицензию"
@@ -695,9 +825,18 @@ msgstr "Добавить новое приложение"
msgid "Add new directory"
msgstr "Добавить новый каталог"
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr "Добавить реакцию"
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr "Добавить в проект"
@@ -710,22 +849,34 @@ msgstr "Добавить в дела"
msgid "Add user(s) to the group:"
msgstr "Добавить пользовател(Ñ/ей) в группу:"
-msgid "Add users or groups who are allowed to approve every merge request"
-msgstr "Добавить пользователей или группы, которые имеют право утверждать каждый Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
-
msgid "Add users to group"
msgstr "Добавить пользователей в группу"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
+msgstr ""
+
msgid "Added at"
msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr "Добавление новых приложений отключено в вашем ÑкземплÑре GitLab. ОбратитеÑÑŒ к админиÑтратору GitLab, чтобы получить разрешение"
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr "Дополнительный текÑÑ‚"
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -737,6 +888,9 @@ msgstr "Обзор ÐдминиÑтратора"
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ окончательно удалить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{username}. ОбÑуждениÑ, запроÑÑ‹ ÑлиÑÐ½Ð¸Ñ Ð¸ ÑвÑзанные Ñ Ð½Ð¸Ð¼Ð¸ группы будут переданы общеÑиÑтемному «Призрачному пользователю». Чтобы избежать потери данных, раÑÑмотрите возможноÑÑ‚ÑŒ иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¸ %{strong_start}блокировки пользователÑ%{strong_end}. ПоÑле %{strong_start}ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ%{strong_end} его будет невозможно воÑÑтановить или отменить удаление."
@@ -758,6 +912,9 @@ msgstr "ОÑтановка заданий не удалаÑÑŒ"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ оÑтановить вÑе заданиÑ. Это дейÑтвие оÑтановит вÑе текущие заданиÑ, находÑщиеÑÑ Ð² процеÑÑе выполнениÑ."
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ окончательно удалить проект %{projectName}, его репозиторий и вÑе ÑвÑзанные реÑурÑÑ‹, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð¾Ð±ÑуждениÑ, запроÑÑ‹ ÑлиÑÐ½Ð¸Ñ Ð¸ Ñ‚.д. ПоÑле Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ %{strong_start}ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð°%{strong_end} его будет невозможно воÑÑтановить или отменить удаление."
@@ -872,6 +1029,9 @@ msgstr "РаÑширенные наÑтройки"
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "Предупреждение"
@@ -891,15 +1051,24 @@ msgstr "Ð’Ñе УчаÑтники"
msgid "All changes are committed"
msgstr "Ð’Ñе Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð·Ð°Ñ„Ð¸ÐºÑированы"
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Ð’Ñе функции ÑиÑтемы включаютÑÑ Ð´Ð»Ñ Ð¿ÑƒÑÑ‚Ñ‹Ñ… проектов, Ñозданных из шаблонов или импортированных, но вы можете отключить их впоÑледÑтвии в наÑтройках проекта."
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -972,9 +1141,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr "Ð’Ñ€ÐµÐ¼Ñ (в чаÑах), на которое пользователÑм позволено пропуÑкать принудительную наÑтройку двухфакторной аутентификации"
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr "SSH ключ автоматичеÑки ÑгенерируетÑÑ Ð¿Ð¾Ñле отправки формы. ОбратитеÑÑŒ к документации Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ информации."
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr "Приложение под названием %{link_to_client} запрашивает доÑтуп к вашей учетной запиÑи GitLab."
@@ -1008,12 +1174,15 @@ msgstr "Произошла ошибка при предварительном п
msgid "An error occurred when toggling the notification subscription"
msgstr "Произошла ошибка при переключении подпиÑки на оповещениÑ"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "Произошла ошибка при обновлении веÑа обÑуждениÑ"
-msgid "An error occurred while adding approver"
-msgstr "Произошла ошибка при удалении утверждающего"
-
msgid "An error occurred while deleting the approvers group"
msgstr ""
@@ -1035,21 +1204,36 @@ msgstr "Произошла ошибка при отключении уведом
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr "Произошла ошибка при предварительном проÑмотре markdown"
msgid "An error occurred while fetching pending comments"
msgstr ""
+msgid "An error occurred while fetching projects autocomplete."
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "Произошла ошибка при получении денег данных Ð´Ð»Ñ Ð±Ð¾ÐºÐ¾Ð²Ð¾Ð¹ панели"
-msgid "An error occurred while fetching stages."
-msgstr "Произошла ошибка при извлечении Ñтадий."
-
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -1065,6 +1249,9 @@ msgstr "Произошла ошибка при получении Ñборочн
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr "Произошла ошибка при получении ÑпиÑка проектов"
@@ -1098,8 +1285,11 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr "Произошла ошибка при выполнении запроÑа."
-msgid "An error occurred while removing approver"
-msgstr "Произошла ошибка при удалении утверждающего"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
+msgstr ""
msgid "An error occurred while removing epics."
msgstr ""
@@ -1152,6 +1342,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1209,9 +1402,15 @@ msgstr "Любой"
msgid "Any Label"
msgstr "Ð›ÑŽÐ±Ð°Ñ ÐœÐµÑ‚ÐºÐ°"
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr "Оформление"
@@ -1221,6 +1420,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr "Приложение"
@@ -1230,6 +1435,9 @@ msgstr "Идентификатор приложениÑ"
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1248,6 +1456,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr "Применить предложение"
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1297,12 +1517,6 @@ msgstr ""
msgid "Approvals"
msgstr "УтверждениÑ"
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr "Утверждающие"
-
msgid "Apr"
msgstr "Ðпр."
@@ -1333,6 +1547,18 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
+msgid "Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr ""
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to delete this list?"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Ð’Ñ‹ уверены, что вы хотите удалить Ñто раÑпиÑание Ñборочной линии?"
@@ -1354,18 +1580,6 @@ msgstr "Ð’Ñ‹ уверены, что вы хотите заново ÑгенерÐ
msgid "Are you sure you want to remove %{group_name}?"
msgstr "Вы уверены, что вы хотите удалить %{group_name}?"
-msgid "Are you sure you want to remove approver %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove approver %{name}?"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}?"
-msgstr ""
-
msgid "Are you sure you want to remove the attachment?"
msgstr ""
@@ -1381,6 +1595,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr "Ð’Ñ‹ уверены, что хотите ÑброÑить Ñтот токен проверки работоÑпоÑобноÑти?"
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr "Ð’Ñ‹ уверены, что вы хотите оÑтановить Ñто окружение?"
@@ -1393,12 +1610,36 @@ msgstr ""
msgid "Are you sure?"
msgstr "Вы уверены?"
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr "ID артефакта"
msgid "Artifacts"
msgstr "Ðртефакты"
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr "По возраÑтанию"
@@ -1411,6 +1652,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr "Ðазначьте пользовательÑкий цвет, например #FF0000"
@@ -1426,6 +1670,12 @@ msgstr ""
msgid "Assign to"
msgstr "Ðазначить"
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr "Ðазначенные обÑуждениÑ"
@@ -1456,6 +1706,16 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Приложить файл через drag &amp; drop или %{upload_link}"
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1543,15 +1803,24 @@ msgstr "Подробнее по ÑÑылке %{link_to_documentation}"
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr "Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ Auto DevOps была включена и будет иÑпользоватьÑÑ, еÑли не найден альтернативный файл конфигурации CI. %{more_information_link}"
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr "ДоÑтупен"
@@ -1663,6 +1932,30 @@ msgstr "Ваши значки"
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1760,17 +2053,40 @@ msgid "Bitbucket import"
msgstr ""
msgid "Block"
-msgstr ""
+msgstr "Заблокировать"
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Blog"
msgstr "Блог"
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr "ДоÑки"
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "Ветка %{branchName} не найдена в репозитории проекта."
@@ -1786,6 +2102,9 @@ msgstr "Ветвь уже ÑущеÑтвует"
msgid "Branch name"
msgstr "Ð˜Ð¼Ñ Ð²ÐµÑ‚Ð²Ð¸"
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "ПоиÑк веток"
@@ -1936,6 +2255,21 @@ msgstr "ПроÑмотр файлов"
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1954,6 +2288,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "по автору"
@@ -2044,9 +2381,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr "Ðевозможно найти HEAD-коммит Ñтой ветки"
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -2068,9 +2411,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr "Ðевозможно изменить управлÑемый клаÑтер Kubernetes"
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2086,11 +2435,17 @@ msgstr "Сертификат (PEM)"
msgid "Change Weight"
msgstr "Изменить ВеÑ"
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
msgid "Change permissions"
-msgstr ""
+msgstr "Изменить разрешениÑ"
msgid "Change template"
msgstr "Изменить шаблон"
@@ -2098,6 +2453,15 @@ msgstr "Изменить шаблон"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "Измените Ñто значение, чтобы уÑтановить как чаÑто GitLab UI запрашивает обновлениÑ."
+msgid "Change title"
+msgstr "Изменить заголовок"
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "Выбрать в ветке"
@@ -2122,6 +2486,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr "Диаграммы"
@@ -2149,6 +2519,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr "Проверка доÑтупноÑти ветви..."
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr "Подобрать в Ñтом коммите"
@@ -2168,6 +2541,9 @@ msgid "Choose a file"
msgstr ""
msgid "Choose a role permission"
+msgstr "Выберите разрешение роли"
+
+msgid "Choose a template"
msgstr ""
msgid "Choose a template..."
@@ -2189,7 +2565,7 @@ msgid "Choose the top-level group for your repository imports."
msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
-msgstr ""
+msgstr "Выберите уровень доÑтупа, включите / отключите функции проекта (обÑуждениÑ, репозиторий, вики, примеры кода) и наÑтройте Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð½Ð° проекте."
msgid "Choose what content you want to see on a group’s overview page"
msgstr ""
@@ -2200,7 +2576,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2272,16 +2648,34 @@ msgstr "пропущено"
msgid "CiStatus|running"
msgstr "выполнÑетÑÑ"
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr "Ключ входной переменной"
msgid "CiVariables|Input variable value"
msgstr "Значение входной переменной"
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr "Удалить Ñтроку переменных"
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2335,9 +2729,18 @@ msgstr "ОчиÑтить поиÑк"
msgid "Clear search input"
msgstr "ОчиÑтить Ñтроку поиÑка"
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr "Выберите из ÑпиÑка любой <strong>проект</strong>, чтобы перейти к Ñтапу проекта."
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2392,6 +2795,9 @@ msgstr "Завершить цель"
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr "Закрыто"
@@ -2410,7 +2816,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} уÑпешно уÑтановлены на вашем клаÑтере Kubernetes"
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2428,12 +2840,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Дополнительные опции Ð´Ð»Ñ Ñтой интеграции Ñ ÐºÐ»Ð°Ñтером Kubernetes"
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2449,6 +2873,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr "ПриложениÑ"
@@ -2557,6 +2984,9 @@ msgstr "GitLab Runner"
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2593,19 +3023,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr "УÑтановить"
-
-msgid "ClusterIntegration|Installed"
-msgstr "УÑтановлен"
-
-msgid "ClusterIntegration|Installing"
-msgstr "УÑтановка"
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2638,6 +3059,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2674,18 +3098,18 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Let's Encrypt"
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Let's Encrypt"
+msgstr "Let's Encrypt"
+
msgid "ClusterIntegration|Machine type"
msgstr "Тип машины"
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr "УбедитеÑÑŒ, что ваша ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ %{link_to_requirements} Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÐºÐ»Ð°Ñтеров"
-msgid "ClusterIntegration|Manage"
-msgstr "Управление"
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr "УправлÑйте вашему клаÑтером Kubernetes, Ð¿ÐµÑ€ÐµÐ¹Ð´Ñ Ð¿Ð¾ ÑÑылке %{link_gke}"
@@ -2749,7 +3173,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "Ðе удалоÑÑŒ выполнить Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° запуÑк процеÑÑа уÑтановки"
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2803,40 +3227,52 @@ msgstr "Что-то пошло не так при Ñоздании клаÑтеÑ
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "Произошли ошибки во Ð²Ñ€ÐµÐ¼Ñ ÑƒÑтановки %{title}"
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
-msgstr " У Ñтой учетной запиÑи должны быть Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð½Ð° Ñоздание клаÑтера Kubernetes в %{link_to_container_project} указанных ниже"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
+msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
-msgstr "Переключить клаÑтер Kubernetes"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
+msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr " У Ñтой учетной запиÑи должны быть Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð½Ð° Ñоздание клаÑтера Kubernetes в %{link_to_container_project} указанных ниже"
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr "Переключить клаÑтер Kubernetes"
+
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2848,6 +3284,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "ЕÑли привÑзать клаÑтер Kubernetes к Ñтому проекту, вы Ñ Ð»Ñ‘Ð³ÐºÐ¾Ñтью Ñможете иÑпользовать Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñ€ÐµÐ²ÑŒÑŽ, развертывать ваши приложениÑ, запуÑкать Ñборочные линии и многое другое."
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2857,6 +3296,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "Ваша ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ должна иметь %{link_to_kubernetes_engine}"
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr "Зона"
@@ -2908,9 +3350,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr "Свернуть боковую панель"
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr "Комментарий"
@@ -2929,6 +3377,9 @@ msgstr "Прокомментировать и переоткрыть диÑкуÑ
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr "Комментарии"
@@ -3050,6 +3501,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr "ÐаÑтройка таймаутов Gitaly."
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -3075,9 +3529,15 @@ msgid "Configure the way a user creates a new account."
msgstr ""
msgid "Confirm"
+msgstr "Подтвердить"
+
+msgid "Confirmation email sent to %{email}"
msgstr ""
msgid "Confirmation required"
+msgstr "ТребуетÑÑ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ðµ"
+
+msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
msgid "Connect"
@@ -3092,9 +3552,15 @@ msgstr "Подключить репозитории Ñ GitHub"
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr "Подключение..."
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3102,7 +3568,7 @@ msgid "Contact owner %{link_start}%{owner_name}%{link_end} to upgrade the plan."
msgstr ""
msgid "Contact sales to upgrade"
-msgstr ""
+msgstr "СвÑзатьÑÑ Ñ Ð¾Ñ‚Ð´ÐµÐ»Ð¾Ð¼ продаж Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ"
msgid "Contact your Administrator to upgrade your license."
msgstr ""
@@ -3158,6 +3624,9 @@ msgstr "Когда рееÑÑ‚Ñ€ контейнеров Docker интегриро
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr "Ð’Ñ‹ также можете иÑпользовать %{deploy_token} Ð´Ð»Ñ Ð´Ð¾Ñтупа в режиме только чтение к рееÑтру образов."
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3203,6 +3672,9 @@ msgstr "Коммиты в %{branch_name}, за иÑключением комми
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr "ПожалуйÑта подождите, Ñта Ñтраница автоматичеÑки обновитÑÑ Ð¿Ð¾ готовноÑти."
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3212,6 +3684,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3230,9 +3705,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr "Копировать URL в буфер обмена"
@@ -3248,6 +3720,12 @@ msgstr "Копировать SHA коммита в буфер обмена"
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr "Копировать ÑÑылку"
@@ -3257,6 +3735,9 @@ msgstr "Скопировать ÑÑылку в буфер обмена"
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr "Скопировать в буфер обмена"
@@ -3266,9 +3747,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3302,9 +3789,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr "Создать новую ветку"
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr "Создать новое обÑуждение"
@@ -3377,6 +3873,12 @@ msgstr "Создать метку проекта"
msgid "Create your first page"
msgstr "Создайте вашу первую Ñтраницу"
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr "Тег"
@@ -3392,12 +3894,27 @@ msgstr ""
msgid "Created by me"
msgstr "Создано мной"
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3416,6 +3933,9 @@ msgstr ""
msgid "Current node"
msgstr "Текущий узел"
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr "Профиль"
@@ -3494,15 +4014,39 @@ msgstr "Ð’Ñе"
msgid "DashboardProjects|Personal"
msgstr "Личные"
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr "Отладка"
@@ -3539,6 +4083,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3579,15 +4126,30 @@ msgid "Delete comment"
msgstr "Удалить комментарий"
msgid "Delete license"
-msgstr ""
+msgstr "Удалить лицензию"
msgid "Delete list"
msgstr "Удалить ÑпиÑок"
msgid "Delete source branch"
-msgstr ""
+msgstr "Удалить иÑходную ветку"
msgid "Delete this attachment"
+msgstr "Удалить вложение"
+
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
msgstr ""
msgid "Deleted"
@@ -3611,6 +4173,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "Развертывание"
@@ -3789,6 +4399,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3843,9 +4456,15 @@ msgstr "Выключить групповые обработчиков задаÐ
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3867,6 +4486,12 @@ msgstr "Удалить черновик"
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3897,18 +4522,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr "Домен"
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr "Ðе показывать Ñнова"
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr "Выполнено"
@@ -3921,25 +4570,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
-msgstr ""
+msgid "Download license"
+msgstr "Скачать лицензию"
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3981,6 +4624,9 @@ msgstr "Редактировать метку"
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "Изменить раÑпиÑание Ñборочной линии %{id}"
@@ -3997,7 +4643,7 @@ msgid "Edit environment"
msgstr ""
msgid "Edit file"
-msgstr ""
+msgstr "Изменить файл"
msgid "Edit files in the editor and commit changes here"
msgstr "Редактируйте файлы в редакторе и зафикÑируйте Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð·Ð´ÐµÑÑŒ"
@@ -4017,6 +4663,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr "Elasticsearch"
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr "Ð˜Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ñ Elasticsearch. Elasticsearch AWS IAM."
@@ -4035,6 +4687,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -4059,9 +4714,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr "Email-адреÑа"
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr "Ð’Ñтроить"
@@ -4086,6 +4771,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr "Включить Sentry Ð´Ð»Ñ Ð¾Ñ‚Ñ‡ÐµÑ‚Ð¾Ð² об ошибках и журналированиÑ."
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr "Включить и наÑтроить метрики InfluxDB."
@@ -4122,11 +4810,8 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr "Включите панель производительноÑти Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ группы."
-
msgid "Enable two-factor authentication"
-msgstr ""
+msgstr "Включить двухфакторную аутентификацию"
msgid "Enable usage ping"
msgstr "Включить Ñбор ÑтатиÑтики иÑпользованиÑ"
@@ -4155,12 +4840,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr "ЗаканчиваетÑÑ Ð² (UTC)"
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr "Введите опиÑание обÑуждениÑ"
@@ -4173,7 +4864,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr "Введите заголовок запроÑа на ÑлиÑние"
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4185,9 +4879,33 @@ msgstr ""
msgid "Environments"
msgstr "Среды"
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "Произошла ошибка при получении окружений."
@@ -4323,18 +5041,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr "Цели позволÑÑ‚ вам управлÑÑ‚ÑŒ портфелем проектов более Ñффективно и Ñ Ð¼ÐµÐ½ÑŒÑˆÐ¸Ð¼Ð¸ уÑилиÑми"
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4371,9 +5122,15 @@ msgstr "Ошибка Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¼ÐµÑ‚Ð¾Ðº."
msgid "Error fetching network graph."
msgstr "Ошибка Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ñетевого графа."
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr "Ошибка Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ ÑÑылок"
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr "Ошибка при получении данных об иÑпользовании ping."
@@ -4383,6 +5140,12 @@ msgstr "Ошибка загрузки данных ветки. ПожалуйÑÑ
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr "Ошибка загрузки поÑледнего коммита."
@@ -4392,6 +5155,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr "Ошибка загрузки запроÑов на ÑлиÑние."
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr "Ошибка загрузки данных проекта. ПожалуйÑта, попробуйте еще раз."
@@ -4401,6 +5167,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr "Произошла ошибка при переключении подпиÑки на оповещение"
@@ -4434,9 +5206,15 @@ msgstr "Ошибка при обновлении ÑтатуÑа дела."
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4533,6 +5311,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4620,6 +5401,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr "Facebook"
@@ -4629,27 +5431,60 @@ msgstr "Ðеудачно"
msgid "Failed Jobs"
msgstr "Ðевыполненные ЗаданиÑ"
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr "Ðе удалоÑÑŒ изменить владельца"
msgid "Failed to check related branches."
msgstr "Ðе удалоÑÑŒ проверить ÑвÑзанные ветки."
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr "Ошибка при удалении обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ñ Ð´Ð¾Ñки, повторите попытку."
@@ -4668,6 +5503,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4680,16 +5521,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr "Ошибка Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±Ñуждений, пожалуйÑта, попробуйте Ñнова."
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
+msgstr ""
+
+msgid "Failed to upgrade."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4704,6 +5557,12 @@ msgstr ""
msgid "Feature Flags"
msgstr "Функциональные опции"
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4767,7 +5626,7 @@ msgstr "Ðеактивен"
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4779,9 +5638,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4853,7 +5709,7 @@ msgid "File mode changed from %{a_mode} to %{b_mode}"
msgstr ""
msgid "File moved"
-msgstr ""
+msgstr "Файл перемещен"
msgid "File templates"
msgstr ""
@@ -4864,6 +5720,12 @@ msgstr ""
msgid "Files"
msgstr "Файлы"
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4886,10 +5748,10 @@ msgid "Filter by two-factor authentication"
msgstr ""
msgid "Filter results by group"
-msgstr ""
+msgstr "Фильтровать результаты по группе"
msgid "Filter results by project"
-msgstr ""
+msgstr "Фильтровать результаты по проекту"
msgid "Filter..."
msgstr "Фильтр..."
@@ -4898,7 +5760,7 @@ msgid "Find by path"
msgstr "ПоиÑк по пути"
msgid "Find existing members by name"
-msgstr ""
+msgstr "Ðайти ÑущеÑтвующих учаÑтников по имени"
msgid "Find file"
msgstr "Ðайти файл"
@@ -4910,6 +5772,9 @@ msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/Google
msgstr ""
msgid "Fingerprint"
+msgstr "Отпечаток"
+
+msgid "Fingerprint:"
msgstr ""
msgid "Fingerprints"
@@ -4921,11 +5786,14 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr "Завершено"
msgid "First day of the week"
-msgstr ""
+msgstr "Первый день недели"
msgid "FirstPushedBy|First"
msgstr "Первый"
@@ -4945,6 +5813,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4973,7 +5847,7 @@ msgid "For internal projects, any logged in user can view pipelines and access j
msgstr ""
msgid "For more info, read the documentation."
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ информации читайте документацию."
msgid "For more information, go to the "
msgstr ""
@@ -4990,6 +5864,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Ответвлено от"
@@ -4999,6 +5882,9 @@ msgstr "Ответвление от %{project_name} (удалено)"
msgid "Forking in progress"
msgstr "ВыполнÑетÑÑ Ð¾Ñ‚Ð²ÐµÑ‚Ð²Ð»ÐµÐ½Ð¸Ðµ"
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -5017,6 +5903,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -5047,20 +5936,26 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr "GPG Ключи"
-msgid "GPG signature (loading...)"
+msgid "GPG keys allow you to verify signed commits."
msgstr ""
+msgid "GPG signature (loading...)"
+msgstr "GPG подпиÑÑŒ (загрузка...)"
+
msgid "General"
msgstr "ОÑновныe"
msgid "General Settings"
-msgstr ""
+msgstr "ОÑновные ÐаÑтройки"
msgid "General pipelines"
msgstr ""
@@ -5410,6 +6305,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5467,15 +6368,21 @@ msgstr "Git"
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
-msgid "Git global setup"
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
msgstr ""
+msgid "Git global setup"
+msgstr "Глобальные наÑтройки Git"
+
msgid "Git repository URL"
msgstr "URL-Ð°Ð´Ñ€ÐµÑ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ Git"
msgid "Git revision"
msgstr "Ð ÐµÐ²Ð¸Ð·Ð¸Ñ git"
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5548,6 +6455,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr "ВернутьÑÑ Ð½Ð°Ð·Ð°Ð´"
@@ -5558,7 +6468,7 @@ msgid "Go back"
msgstr "ВернутьÑÑ"
msgid "Go full screen"
-msgstr ""
+msgstr "Ðа веÑÑŒ Ñкран"
msgid "Go to"
msgstr ""
@@ -5566,9 +6476,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5644,6 +6563,9 @@ msgstr "Ðазвание группы"
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5653,6 +6575,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5680,13 +6605,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5698,9 +6626,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5731,9 +6656,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5797,6 +6731,9 @@ msgstr "удалить возможноÑÑ‚ÑŒ поделитьÑÑ Ñ Ð³Ñ€ÑƒÐ¿Ð¿
msgid "Groups"
msgstr "Группы"
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5866,6 +6803,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5893,6 +6833,9 @@ msgstr "Проблем работоÑпоÑобноÑти не обнаружеÐ
msgid "HealthCheck|Unhealthy"
msgstr "ÐеÑтабильный"
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr "Помощь"
@@ -5902,12 +6845,15 @@ msgstr "Страница Ñправки"
msgid "Help page text and support page url."
msgstr "ТекÑÑ‚ Ñтраницы Ñправки и Url-Ð°Ð´Ñ€ÐµÑ Ñтраницы поддержки."
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5917,6 +6863,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Скрыть значение"
@@ -5933,6 +6882,12 @@ msgstr ""
msgid "History"
msgstr "ИÑториÑ"
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5948,6 +6903,12 @@ msgstr "ОчиÑтка уÑпешно запущена"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5957,6 +6918,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr "ID"
@@ -6026,10 +6993,19 @@ msgstr "ЕÑли включено"
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6110,6 +7086,12 @@ msgstr "Импорт репозиториев из GitHub"
msgid "Import repository"
msgstr "Импорт репозиториÑ"
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6119,6 +7101,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6128,9 +7116,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6182,12 +7179,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6209,12 +7215,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr "УÑтановить Runner на Kubernetes"
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] "ЭкземплÑÑ€"
@@ -6264,18 +7282,42 @@ msgstr "Внедрение Цикла Ðналитик"
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6285,6 +7327,9 @@ msgstr ""
msgid "Invite"
msgstr "Приглашение"
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6297,6 +7342,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6315,6 +7363,12 @@ msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð¾Ð±Ñуждений"
msgid "Issue template (optional)"
msgstr "Шаблон обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ (необÑзательно)"
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr "ДоÑка"
@@ -6390,6 +7444,48 @@ msgstr "Янв."
msgid "January"
msgstr "Январь"
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr "Задание"
@@ -6486,6 +7582,12 @@ msgstr "Июл."
msgid "July"
msgstr "Июль"
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr "Июн."
@@ -6495,6 +7597,9 @@ msgstr "Июнь"
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -6519,12 +7624,18 @@ msgstr "КлаÑтер Kubernetes был уÑпешно обновлён."
msgid "Kubernetes configured"
msgstr "Kubernetes наÑтроен"
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr "LFS"
@@ -6537,6 +7648,9 @@ msgstr "Отключено"
msgid "LFSStatus|Enabled"
msgstr "Включено"
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr "Метка"
@@ -6585,6 +7699,9 @@ msgstr "ПеренеÑти Метку"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6601,6 +7718,9 @@ msgstr[3] "ПоÑледние %d дни"
msgid "Last Pipeline"
msgstr "ПоÑледнÑÑ Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð›Ð¸Ð½Ð¸Ñ"
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6628,6 +7748,12 @@ msgstr "ПоÑледнее обновление"
msgid "Last updated"
msgstr "ПоÑледний раз обновлено"
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr "Вы отправили в"
@@ -6643,6 +7769,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6661,6 +7793,9 @@ msgstr "Подробнее о Kubernates"
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6673,6 +7808,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr "Узнайте больше в"
@@ -6694,6 +7832,12 @@ msgstr "Покинуть проект"
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr "ЛицензиÑ"
@@ -6769,6 +7913,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6785,6 +7932,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -6815,6 +7965,9 @@ msgstr "Предварительный проÑмотр в реальном вр
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr "Загрузка GitLab IDE..."
@@ -6836,6 +7989,9 @@ msgstr "Заблокировать %{issuableDisplayName}"
msgid "Lock not found"
msgstr "Блокировка не найдена"
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6854,6 +8010,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6878,12 +8037,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6944,6 +8112,15 @@ msgstr "Мар."
msgid "March"
msgstr "Март"
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr "Отметить как Ñделанное"
@@ -6956,6 +8133,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr "Включен режим Markdown"
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6980,6 +8166,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -7010,6 +8199,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
@@ -7022,15 +8214,9 @@ msgstr "ЗапроÑÑ‹ на СлиÑние"
msgid "Merge Requests created"
msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние Ñоздан"
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ ÑлиÑний"
@@ -7040,12 +8226,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
@@ -7064,6 +8244,30 @@ msgstr "ЗапроÑÑ‹ на ÑлиÑние- Ñто меÑто, где можно
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -7082,6 +8286,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7094,6 +8301,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7127,7 +8337,7 @@ msgstr "%{paragraphStart}изменил опиÑание %{descriptionChangedTim
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7142,6 +8352,12 @@ msgstr ""
msgid "Messages"
msgstr "СообщениÑ"
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr "Метрики"
@@ -7157,6 +8373,9 @@ msgstr "Метрики и профилирование"
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7196,9 +8415,6 @@ msgstr "ÐÐ¾Ð²Ð°Ñ Ð¼ÐµÑ‚Ñ€Ð¸ÐºÐ°"
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7244,9 +8460,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7271,9 +8499,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr "Удалить Ñтап"
@@ -7292,7 +8517,7 @@ msgstr "ПовыÑить %{milestoneTitle} до группового Ñтапа?
msgid "Milestones|Promote Milestone"
msgstr "ПовыÑить Ñтап"
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7301,6 +8526,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7322,6 +8556,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "добавить ключ SSH"
@@ -7382,6 +8628,24 @@ msgstr "ПеремеÑтить"
msgid "Move issue"
msgstr "ПеремеÑтить обÑуждение"
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7394,6 +8658,9 @@ msgstr ""
msgid "Name"
msgstr "ИмÑ"
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr "Ðазвать новую метку"
@@ -7491,6 +8758,9 @@ msgstr ""
msgid "New epic"
msgstr "ÐÐ¾Ð²Ð°Ñ Ñ†ÐµÐ»ÑŒ"
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr "Ðовый файл"
@@ -7515,6 +8785,9 @@ msgstr "Ðовый Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7545,6 +8818,12 @@ msgstr "Ðовый..."
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr "Ðет"
@@ -7554,12 +8833,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7575,6 +8863,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7599,6 +8890,9 @@ msgstr "Файл не выбран"
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr "Файлы не найдены."
@@ -7620,9 +8914,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7638,6 +8929,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr "Ðет других меток Ñ Ñ‚Ð°ÐºÐ¸Ð¼ наименованием или опиÑанием"
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7665,6 +8959,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7713,6 +9013,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "Ð’Ñ‹ уверены, что вы хотите отменить Ñоздание Ñтого комментариÑ?"
@@ -7728,6 +9031,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr "Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾ ÑобытиÑÑ…"
@@ -7737,6 +9046,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "ОбÑуждение закрыто"
@@ -7791,6 +9103,9 @@ msgstr "УчаÑтие"
msgid "NotificationLevel|Watch"
msgstr "ОтÑлеживать"
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr "УведомлениÑ"
@@ -7806,6 +9121,12 @@ msgstr "ÐоÑб."
msgid "November"
msgstr "ÐоÑбрь"
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr "ОК"
@@ -7821,7 +9142,13 @@ msgstr "ОктÑбрь"
msgid "OfSearchInADropdown|Filter"
msgstr "Фильтр"
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7846,13 +9173,13 @@ msgstr "Один или неÑколько проектов Bitbucket не моÐ
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "Один или неÑколько проектов Google Code не могут быть импортированы в GitLab, поÑкольку они иÑпользуют Subversion или Mercurial Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²ÐµÑ€ÑиÑми, а не Git."
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
+msgstr ""
+
msgid "Only admins"
msgstr "Только админиÑтраторы"
-msgid "Only allow merge requests to be merged if all discussions are resolved"
-msgstr ""
-
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7870,6 +9197,9 @@ msgstr "Только учаÑтники проекта могут оÑтавлÑ
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7915,6 +9245,12 @@ msgstr "Открыто"
msgid "Opens in a new window"
msgstr "ОткроетÑÑ Ð² новом окне"
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr "Операции"
@@ -7939,9 +9275,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7963,6 +9296,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr "ИÑходÑщие запроÑÑ‹"
@@ -7972,6 +9308,12 @@ msgstr "Обзор"
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr "Владелец"
@@ -7999,6 +9341,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "ПоÑледнÑÑ Â»"
@@ -8020,9 +9365,21 @@ msgstr "ЧаÑÑ‚ÑŒ изменений запроÑа на ÑлиÑние"
msgid "Password"
msgstr "Пароль"
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -8035,7 +9392,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -8062,6 +9419,9 @@ msgstr "В ожидании"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -8083,12 +9443,27 @@ msgstr "ПерÑональный Токен ДоÑтупа"
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr "Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ"
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr "РаÑпиÑание Сборочной Линии"
@@ -8167,6 +9542,9 @@ msgstr "Сборочные линии"
msgid "Pipelines charts"
msgstr "Диаграммы Ñборочных линий"
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr "Сборочные линии за поÑледний меÑÑц"
@@ -8176,10 +9554,13 @@ msgstr "Сборочные линии за поÑледнюю неделю"
msgid "Pipelines for last year"
msgstr "Сборочные линии за поÑледний год"
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8200,6 +9581,9 @@ msgstr "Ðачало работы Ñо Ñборочными линиÑми"
msgid "Pipelines|Loading Pipelines"
msgstr "ЗагружаютÑÑ Ñборочные линии"
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "КÑш проекта уÑпешно очищен."
@@ -8260,6 +9644,9 @@ msgstr "ОÑтановить Ñборочную линию"
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr "ОÑтановить Ñборочную линию #%{pipelineId}?"
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8290,6 +9677,15 @@ msgstr "Ñо Ñтадией"
msgid "Pipeline|with stages"
msgstr "Ñо ÑтадиÑми"
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8299,12 +9695,30 @@ msgstr "PlantUML"
msgid "Play"
msgstr "ЗапуÑк"
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8335,6 +9749,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8347,6 +9764,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8368,7 +9794,7 @@ msgstr "ПожалуйÑта, попробуйте ещё раз"
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8386,12 +9812,66 @@ msgstr "ПредпочтениÑ"
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8407,12 +9887,18 @@ msgstr ""
msgid "Preview"
msgstr "Предварительный проÑмотр"
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8440,15 +9926,24 @@ msgstr "ÐŸÑ€Ð¸Ð²Ð°Ñ‚Ð½Ð°Ñ - Группу и включённые в неё пр
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr "Личные проекты могут быть Ñозданы в вашем перÑональном проÑтранÑтве Ñ:"
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr "Профиль"
msgid "Profile Settings"
msgstr "ÐаÑтройки профилÑ"
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8479,6 +9974,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr "Изменить Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"
@@ -8500,6 +9998,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8512,6 +10013,9 @@ msgstr "Текущий путь: %{path}"
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr "Удалить Учетную запиÑÑŒ"
@@ -8539,6 +10043,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8548,9 +10064,15 @@ msgstr "Ðеверный пароль"
msgid "Profiles|Invalid username"
msgstr "Ðеверное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8560,18 +10082,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr "Путь"
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8590,9 +10127,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "Это не выглÑдит как публичный SSH-ключ, вы уверены, что вы хотите добавить его?"
@@ -8608,13 +10142,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Введите значение %{confirmationValue} Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ:"
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8629,6 +10166,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr "Ошибка Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¸Ð¼ÐµÐ½Ð¸ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ - %{message}"
@@ -8650,6 +10190,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8743,6 +10286,9 @@ msgstr ""
msgid "Project avatar"
msgstr "Ðватар проекта"
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8788,6 +10334,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "ПодпиÑатьÑÑ"
@@ -8839,6 +10388,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8848,18 +10415,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8869,12 +10478,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr "Проекты"
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -9031,6 +10700,15 @@ msgstr "ПовыÑить до Группового Этапа"
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -9049,16 +10727,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -9067,18 +10751,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9127,9 +10817,15 @@ msgstr "Получить"
msgid "Push"
msgstr "Отправить"
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr "Отправить ÑущеÑтвующий репозиторий Git"
@@ -9154,12 +10850,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr "БыÑтрые дейÑÑ‚Ð²Ð¸Ñ Ð¼Ð¾Ð³ÑƒÑ‚ иÑпользоватьÑÑ Ð² опиÑании обÑуждений и комментариÑÑ…."
@@ -9184,15 +10922,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9209,24 +10956,45 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr "РегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ / Вход"
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr "ЗарегиÑтрируйте и проÑмотрите ваши обработчики заданий Ð´Ð»Ñ Ñтой группы."
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9251,6 +11019,9 @@ msgstr "СвÑзанные ЗапроÑÑ‹ на СлиÑние"
msgid "Related Merged Requests"
msgstr "СвÑзанные Влитые ЗапроÑÑ‹"
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9263,6 +11034,9 @@ msgstr ""
msgid "Remind later"
msgstr "Ðапомнить позже"
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr "Удалить"
@@ -9272,7 +11046,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9281,25 +11058,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr "Удалить аватар"
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr "Удалить проект"
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9314,6 +11103,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9344,6 +11151,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9353,7 +11163,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9368,6 +11178,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9407,12 +11220,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9467,6 +11274,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9481,6 +11294,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9520,6 +11336,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9562,6 +11387,9 @@ msgstr "Повторить Ñто фоновое задание"
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9602,6 +11430,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9686,6 +11520,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr "SSH-ключи"
@@ -9695,6 +11532,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9710,6 +11550,9 @@ msgstr "Сохранить"
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9722,6 +11565,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Сохранить раÑпиÑание Ñборочной лини"
@@ -9782,9 +11628,21 @@ msgstr "Ðайти ветки и теги"
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr "ПоиÑк проектов, обÑуждений и Ñ‚.д."
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9806,6 +11664,9 @@ msgstr "ПоиÑк проекта"
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr "ПоиÑк пользователей"
@@ -9881,9 +11742,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9914,12 +11772,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9932,6 +11802,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr "Выбрать формат архива"
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9959,6 +11835,9 @@ msgstr "Выбрать ÑущеÑтвующий клаÑтер Kubernetes или
msgid "Select branch/tag"
msgstr "Выбрать ветку/тег"
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9995,6 +11874,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr "Отправить email уведомление Разработчикам."
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr "Отправить Ñлектронное пиÑьмо"
@@ -10076,6 +11958,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10106,21 +11991,24 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr "УÑтановить макÑимальное Ð²Ñ€ÐµÐ¼Ñ ÑеанÑа Ð´Ð»Ñ Ð²ÐµÐ±-терминала."
+msgid "Set milestone"
+msgstr ""
+
msgid "Set new password"
msgstr ""
msgid "Set notification email for abuse reports."
msgstr "ÐаÑтроить ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾ Ñлектронной почте Ð´Ð»Ñ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾ злоупотреблениÑÑ…."
-msgid "Set number of approvers required before open merge requests can be merged"
-msgstr ""
-
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -10136,6 +12024,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr "ÐаÑтройка CI/CD"
@@ -10157,6 +12048,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr "уÑтановите пароль"
@@ -10184,6 +12078,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr "ÐаÑтройки"
@@ -10199,6 +12105,9 @@ msgstr "Общие обработчики заданий"
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10211,9 +12120,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr "Показать команду"
@@ -10229,9 +12147,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr "Показать родительÑкие Ñтраницы"
@@ -10287,12 +12202,30 @@ msgstr ""
msgid "Sign out"
msgstr "Выйти"
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr "ÐžÐ³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð²Ñ…Ð¾Ð´Ð°"
msgid "Sign-up restrictions"
msgstr "ÐžÐ³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ñ€ÐµÐ³Ð¸Ñтрации"
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10302,6 +12235,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10311,6 +12247,9 @@ msgstr "ÐаÑтройки размера и доменных имён Ð´Ð»Ñ Ñ
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10380,6 +12319,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr "Что-то пошло не так при переключении кнопки"
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10398,6 +12340,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10422,7 +12367,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10434,6 +12379,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr "Произошла ошибка. Попробуйте позже."
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10494,6 +12442,9 @@ msgstr "Ðаименее популÑрный"
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10548,6 +12499,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr "Ðедавно заходившие"
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10620,6 +12577,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr "В избранное"
@@ -10644,6 +12604,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10674,6 +12637,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "ЗапуÑтить GitLab Runner!"
@@ -10734,12 +12703,18 @@ msgstr "Хранилище"
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr "Подгруппы"
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10770,6 +12745,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10842,6 +12820,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10866,6 +12847,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10878,6 +12922,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr "Переключить ветка/тег"
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10908,18 +12958,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr "Теги"
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr "Теги:"
@@ -11001,6 +13063,9 @@ msgstr "Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð²ÐµÑ‚ÐºÐ°"
msgid "Team"
msgstr "Команда"
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr "Шаблон"
@@ -11013,6 +13078,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -11028,6 +13096,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -11068,6 +13163,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -11083,6 +13181,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11140,6 +13241,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "Ð¡Ñ‚Ð°Ð´Ð¸Ñ Ð¾Ð±ÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¿Ð¾ÐºÐ°Ð·Ñ‹Ð²Ð°ÐµÑ‚ времÑ, которое потребуетÑÑ Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñ‚Ð° ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±ÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð´Ð¾ Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¾Ð±Ñуждению вехи, или Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±ÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð½Ð° вашу доÑку задач. Ðачните Ñоздавать обÑуждениÑ, чтобы увидеть ÑÐ²ÐµÐ´ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñтой Ñтадии."
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11158,6 +13268,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11182,9 +13298,21 @@ msgstr "ПроизводÑтвенный Ñтап показывает общеÐ
msgid "The project can be accessed by any logged in user."
msgstr "ДоÑтуп к проекту возможен любым зарегиÑтрированным пользователем."
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr "ДоÑтуп к проекту возможен без какой-либо проверки подлинноÑти."
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11194,6 +13322,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11203,6 +13334,9 @@ msgstr "Репозиторий Ð´Ð»Ñ Ñтого проекта не ÑущеÑÑ
msgid "The repository for this project is empty"
msgstr "Репозиторий Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ проекта пуÑтой"
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr "Репозиторий должен быть доÑтупен через протоколы <code>http: //</code>, <code>https: //</code> или <code>git: //</code>."
@@ -11242,6 +13376,9 @@ msgstr "Этап теÑÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ÐºÐ°Ð·Ñ‹Ð²Ð°ÐµÑ‚ времÑ, коÑ
msgid "The time taken by each data entry gathered by that stage."
msgstr "ВремÑ, затраченное каждым Ñлементом, Ñобранным на Ñтом Ñтапе."
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11263,15 +13400,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "Среднее значение в Ñ€Ñду. Пример: между 3, 5, 9, Ñреднее 5, между 3, 5, 7, 8, Ñреднее (5+7)/2 = 6."
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11305,9 +13457,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11323,6 +13490,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11341,6 +13514,9 @@ msgstr "При подпиÑке на Ñту метку произошла оши
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11353,6 +13529,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11365,18 +13544,30 @@ msgstr "Этот ÑкземплÑÑ€ GitLab пока не предоÑтавлÑÐ
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11401,6 +13592,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11413,6 +13610,9 @@ msgstr "Этот каталог"
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11422,24 +13622,33 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr "Эта группа пока не Ñодержит групповых обработчики заданий."
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr "Это конфиденциальное обÑуждение."
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr "Это первый Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние от автора в Ñтот проект."
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
+msgid "This is your current session"
+msgstr ""
+
msgid "This issue is confidential"
msgstr "Это обÑуждение ÑвлÑетÑÑ ÐºÐ¾Ð½Ñ„Ð¸Ð´ÐµÐ½Ñ†Ð¸Ð°Ð»ÑŒÐ½Ñ‹Ð¼"
-msgid "This issue is confidential and locked."
-msgstr "Это обÑуждение конфиденциально и заблокировано."
-
msgid "This issue is locked."
msgstr "ОбÑуждение заблокировано."
@@ -11509,12 +13718,6 @@ msgstr "Это означает, что вы не можете отправитÑ
msgid "This merge request is locked."
msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние заблокирован."
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11587,6 +13790,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð´Ð¾ начала Ð¿Ð¾Ð¿Ð°Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±ÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð² планировщик"
@@ -11775,6 +13984,9 @@ msgstr "Совет:"
msgid "Title"
msgstr "Заголовок"
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11790,6 +14002,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr "Чтобы добавить SSH-ключ вам нужно %{generate_link_start}Ñгенерировать его%{link_end} или иÑпользовать %{existing_link_start}ÑущеÑтвующий ключ%{link_end}."
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11856,6 +14071,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr "Чтобы начать выполнÑÑ‚ÑŒ Ñвои заданиÑ, вы можете добавить обработчик заданий в вашу группу"
@@ -11892,6 +14110,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11904,9 +14125,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Переключить боковую панель"
@@ -11916,6 +14143,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11958,6 +14188,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -12009,15 +14275,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -12027,24 +14308,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr "Ðе удаетÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·Ð¸Ñ‚ÑŒ отличиÑ. %{button_try_again}"
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -12063,18 +14362,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr "Разблокировать"
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr "Разблокировано"
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr "Переоткрыть диÑкуÑÑию"
@@ -12144,6 +14458,18 @@ msgstr "Обновить наименование вашей группы, её
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12195,6 +14521,9 @@ msgstr ""
msgid "Upload file"
msgstr "Загрузить файл"
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12204,6 +14533,9 @@ msgstr "кликните Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸"
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12222,6 +14554,54 @@ msgstr ""
msgid "Usage statistics"
msgstr "СтатиÑтика иÑпользованиÑ"
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12231,6 +14611,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12288,6 +14674,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12303,6 +14692,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr "ÐктивноÑÑ‚ÑŒ"
@@ -12378,6 +14902,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr "Пользователи"
@@ -12393,9 +14926,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12441,12 +14992,18 @@ msgstr "ВерÑиÑ"
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12456,6 +15013,9 @@ msgstr "Показать ÑпиÑок целей"
msgid "View file @ "
msgstr "ПроÑмотр файла @ "
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr "ПроÑмотр меток группы"
@@ -12465,6 +15025,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12492,6 +15055,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12519,6 +15085,33 @@ msgstr "Публичный"
msgid "VisibilityLevel|Unknown"
msgstr "Ðе определен"
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12561,6 +15154,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Хотите увидеть данные? ОбратитеÑÑŒ к админиÑтратору за доÑтупом."
@@ -12579,6 +15175,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12588,6 +15187,9 @@ msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¿Ð¾ Ñтапу отÑутÑтвует."
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "Мы хотим быть уверены, что Ñто вы, пожалуйÑта, подтвердите, что вы не робот."
@@ -12609,6 +15211,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr "Веб-обработчики позволÑÑŽÑ‚ вам вызывать Ð°Ð´Ñ€ÐµÑ URL еÑли, например, отправлен новый код или Ñоздано новое обÑуждение. Ð’Ñ‹ можете наÑтроить веб-обработчики так, чтобы они реагировали на определённые ÑобытиÑ, такие как отправки кода, обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ запроÑÑ‹ на ÑлиÑние. Групповые веб-обработчики применÑÑŽÑ‚ÑÑ ÐºÐ¾ вÑем проектам в группе и позволÑÑŽÑ‚ вам Ñтандартизовать функциональноÑÑ‚ÑŒ веб-обработчиков Ð´Ð»Ñ Ð²Ñей вашей группы."
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12618,15 +15223,18 @@ msgstr "ВеÑ"
msgid "Weight %{weight}"
msgstr "Ð’ÐµÑ %{weight}"
+msgid "Welcome to the Guided GitLab Tour"
+msgstr ""
+
+msgid "Welcome to your Issue Board!"
+msgstr ""
+
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Когда процеÑÑ Runner заблокирован, он не может быть назначен другим проектам"
msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
@@ -12640,6 +15248,9 @@ msgstr[3] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12820,6 +15431,9 @@ msgstr ""
msgid "Yes"
msgstr "Да"
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12835,8 +15449,14 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ удалить %{group_name}. Удаленные группы ÐЕ МОГУТ быть воÑÑтановлены! Ð’Ñ‹ ÐБСОЛЮТÐО уверены?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "Ð’Ñ‹ хотите удалить %{project_full_name}. Удаленный проект ÐЕ МОЖЕТ быть воÑÑтановлен! Ð’Ñ‹ ÐБСОЛЮТÐО уверены?"
@@ -12847,6 +15467,9 @@ msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ удалить ÑвÑзь ответвлен
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ передать проект %{project_full_name} другому владельцу. Ð’Ñ‹ ÐБСОЛЮТÐО уверены?"
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12862,6 +15485,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr "Ð’Ñ‹ также можете Ñоздать проект из командной Ñтроки."
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12880,6 +15509,15 @@ msgstr "Ð’Ñ‹ можете легко внеÑти Ñвой вклад в них,
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr "Ð’Ñ‹ можете перемещатьÑÑ Ð¿Ð¾ диаграмме Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ клавиш Ñо Ñтрелками."
@@ -12904,9 +15542,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12937,12 +15581,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12952,6 +15605,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12982,6 +15641,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12994,6 +15662,9 @@ msgstr ""
msgid "You need permission."
msgstr "Вам нужно разрешение."
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -13006,6 +15677,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -13039,6 +15713,9 @@ msgstr "Ð’Ñ‹ не Ñможете получать и отправлÑÑ‚ÑŒ код
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "Ð’Ñ‹ не Ñможете работать Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð¾Ð¼ через SSH, пока не добавите в Ñвой профиль SSH ключ"
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ð¾Ð³Ð¾ ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ Ð²Ð°Ð¼ нужно иÑпользовать разные имена веток."
@@ -13060,27 +15737,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr "Ð’Ñ‹ получили Ñто Ñлектронное пиÑьмо из Ñвоей учетной запиÑи %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr "YouTube"
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr "Ваши Группы"
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ Вашем Kubernetes клаÑтере на Ñтой Ñтранице по-прежнему доÑтупна Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ, но мы рекомендуем вам отключить его перед переконфигурированием"
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr "Ваши проекты (по умолчанию)"
msgid "Your Projects' Activity"
msgstr "ÐктивноÑÑ‚ÑŒ ваших проектов"
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr "Ваши дела"
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -13114,8 +15815,11 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
-msgstr "Ваш комментарий не будет виден вÑем."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
+msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
msgstr ""
@@ -13132,6 +15836,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr "Ваше имÑ"
@@ -13165,10 +15872,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13183,6 +15893,21 @@ msgstr "Ð¸Ð¼Ñ Ð²ÐµÑ‚Ð²Ð¸"
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13288,6 +16013,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13321,9 +16049,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13339,12 +16064,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr "ОпиÑание"
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13467,9 +16186,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13489,10 +16205,10 @@ msgstr[3] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13534,6 +16250,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] "день"
@@ -13570,9 +16289,15 @@ msgstr[1] "черновиков"
msgstr[2] "черновиков"
msgstr[3] "черновики"
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr "включено"
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13585,6 +16310,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13609,6 +16340,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13640,6 +16374,12 @@ msgstr[1] "завершенных ÑкземплÑров"
msgstr[2] "завершенных ÑкземплÑров"
msgstr[3] "завершенные ÑкземплÑры"
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13649,6 +16389,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13667,6 +16410,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13695,6 +16441,9 @@ msgstr[1] "запроÑов на ÑлиÑние"
msgstr[2] "запроÑов на ÑлиÑние"
msgstr[3] "запроÑов на ÑлиÑние"
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13722,7 +16471,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13737,6 +16486,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr "Одобрить"
@@ -13791,6 +16543,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13809,18 +16564,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
-msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние одобрен"
+msgid "mrWidget|Merge locally"
+msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние одобрен; вы можете дополнительно одобрить"
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13851,26 +16603,12 @@ msgstr "Обновить ÑейчаÑ"
msgid "mrWidget|Refreshing now"
msgstr "ОбновлÑетÑÑ ÑейчаÑ"
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] "ТребуетÑÑ ÐµÑ‰Ðµ 1 разрешение"
-msgstr[1] "ТребуетÑÑ ÐµÑ‰Ðµ %d разрешений"
-msgstr[2] "ТребуетÑÑ ÐµÑ‰Ðµ %d разрешений"
-msgstr[3] "ТребуетÑÑ ÐµÑ‰Ðµ %d разрешений"
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] "ТребуетÑÑ ÐµÑ‰Ðµ 1 разрешение пользователÑ"
-msgstr[1] "ТребуетÑÑ ÐµÑ‰Ðµ %d разрешений пользователÑ"
-msgstr[2] "ТребуетÑÑ ÐµÑ‰Ðµ %d разрешений пользователÑ"
-msgstr[3] "ТребуетÑÑ ÐµÑ‰Ðµ %d разрешений пользователÑ"
-
msgid "mrWidget|Resolve conflicts"
msgstr "Разрешить конфликты"
@@ -13955,15 +16693,30 @@ msgstr "ÐºÐ¾Ð¼Ð°Ð½Ð´Ð½Ð°Ñ Ñтрока"
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr "н/д"
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr "новый Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -14083,7 +16836,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -14092,18 +16845,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr "иÑходный текÑÑ‚"
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr "запущено"
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -14137,12 +16902,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/sk_SK/gitlab.po b/locale/sk_SK/gitlab.po
index 9a02c0d0f60..3e1d08ed59e 100644
--- a/locale/sk_SK/gitlab.po
+++ b/locale/sk_SK/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Slovak\n"
"Language: sk_SK\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: sk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:32\n"
+"PO-Revision-Date: 2019-06-14 10:17\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -77,6 +74,13 @@ msgstr[3] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -126,6 +130,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -133,6 +144,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -163,10 +181,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -205,6 +220,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -217,12 +238,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -238,6 +271,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -256,6 +295,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -296,6 +347,9 @@ msgstr[3] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -308,9 +362,31 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -335,6 +411,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -357,14 +436,14 @@ msgstr[2] ""
msgstr[3] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -381,21 +460,21 @@ msgstr[2] ""
msgstr[3] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -425,15 +504,27 @@ msgstr[3] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -443,6 +534,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -473,6 +567,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -509,19 +606,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -551,6 +648,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -596,12 +696,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -638,6 +750,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -659,10 +774,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -671,9 +792,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -683,6 +810,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -695,9 +825,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -710,10 +849,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
+msgstr ""
+
+msgid "AddMember|No users specified."
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -722,10 +864,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -737,6 +888,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -758,6 +912,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -872,6 +1029,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -891,15 +1051,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -972,9 +1141,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -1008,10 +1174,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -1035,21 +1204,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -1065,6 +1249,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1098,7 +1285,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1152,6 +1342,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1209,9 +1402,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1221,6 +1420,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1230,6 +1435,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1248,6 +1456,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1297,12 +1517,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1333,37 +1547,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1381,6 +1595,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1393,12 +1610,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1411,6 +1652,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1426,6 +1670,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1456,6 +1706,16 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1543,15 +1803,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1663,6 +1932,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1765,12 +2058,35 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1786,6 +2102,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1936,6 +2255,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1954,6 +2288,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -2044,9 +2381,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -2068,9 +2411,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2086,6 +2435,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2098,6 +2453,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2122,6 +2486,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2149,6 +2519,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2170,6 +2543,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2200,7 +2576,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2272,16 +2648,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2335,9 +2729,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2392,6 +2795,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2410,7 +2816,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2428,12 +2840,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2449,6 +2873,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2557,6 +2984,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2593,19 +3023,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2638,6 +3059,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2674,6 +3098,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2683,9 +3110,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2749,7 +3173,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2803,40 +3227,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2848,6 +3284,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2857,6 +3296,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2908,9 +3350,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2929,6 +3377,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -3050,6 +3501,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -3077,9 +3531,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3092,9 +3552,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3158,6 +3624,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3203,6 +3672,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3212,6 +3684,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3230,9 +3705,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3248,6 +3720,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3257,6 +3735,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3266,9 +3747,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3302,9 +3789,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3377,6 +3873,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3392,12 +3894,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3416,6 +3933,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3494,15 +4014,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3539,6 +4083,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3590,6 +4137,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3611,6 +4173,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3789,6 +4399,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3843,9 +4456,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3867,6 +4486,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3897,18 +4522,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3921,25 +4570,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3981,6 +4624,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -4017,6 +4663,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -4035,6 +4687,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -4059,9 +4714,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4086,6 +4771,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4122,9 +4810,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4155,12 +4840,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4173,7 +4864,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4185,9 +4879,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4323,18 +5041,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4371,9 +5122,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4383,6 +5140,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4392,6 +5155,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4401,6 +5167,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4434,9 +5206,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4533,6 +5311,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4620,6 +5401,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4629,27 +5431,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4668,6 +5503,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4680,16 +5521,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4704,6 +5557,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4767,7 +5626,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4779,9 +5638,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4864,6 +5720,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4912,6 +5774,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4921,6 +5786,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4945,6 +5813,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4990,6 +5864,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4999,6 +5882,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -5017,6 +5903,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -5047,12 +5936,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5410,6 +6305,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5467,6 +6368,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5476,6 +6380,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5548,6 +6455,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5566,9 +6476,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5644,6 +6563,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5653,6 +6575,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5680,13 +6605,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5698,9 +6626,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5731,9 +6656,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5797,6 +6731,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5866,6 +6803,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5893,6 +6833,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5902,12 +6845,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5917,6 +6863,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5933,6 +6882,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5948,6 +6903,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5957,6 +6918,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -6026,10 +6993,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6110,6 +7086,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6119,6 +7101,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6128,9 +7116,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6182,12 +7179,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6209,12 +7215,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6264,18 +7282,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6285,6 +7327,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6297,6 +7342,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6315,6 +7363,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6390,6 +7444,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6486,6 +7582,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6495,6 +7597,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6519,12 +7624,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6537,6 +7648,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6585,6 +7699,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6601,6 +7718,9 @@ msgstr[3] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6628,6 +7748,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6643,6 +7769,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6661,6 +7793,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6673,6 +7808,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6694,6 +7832,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6769,6 +7913,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6785,6 +7932,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6815,6 +7965,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6836,6 +7989,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6854,6 +8010,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6878,12 +8037,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6944,6 +8112,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6956,6 +8133,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6980,6 +8166,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -7010,6 +8199,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -7022,15 +8214,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -7040,12 +8226,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -7064,6 +8244,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -7082,6 +8286,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7094,6 +8301,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7127,7 +8337,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7142,6 +8352,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7157,6 +8373,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7196,9 +8415,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7244,9 +8460,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7271,9 +8499,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7292,7 +8517,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7301,6 +8526,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7322,6 +8556,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7382,6 +8628,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7394,6 +8658,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7491,6 +8758,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7515,6 +8785,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7545,6 +8818,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7554,12 +8833,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7575,6 +8863,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7599,6 +8890,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7620,9 +8914,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7638,6 +8929,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7665,6 +8959,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7713,6 +9013,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7728,6 +9031,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7737,6 +9046,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7791,6 +9103,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7806,6 +9121,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7821,7 +9142,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7846,13 +9173,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7870,6 +9197,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7915,6 +9245,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7939,9 +9275,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7963,6 +9296,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7972,6 +9308,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7999,6 +9341,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -8020,9 +9365,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -8035,7 +9392,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -8062,6 +9419,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -8083,12 +9443,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8167,6 +9542,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8176,10 +9554,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8200,6 +9581,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8260,6 +9644,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8290,6 +9677,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8299,12 +9695,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8335,6 +9749,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8347,6 +9764,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8368,7 +9794,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8386,12 +9812,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8407,12 +9887,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8440,15 +9926,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8479,6 +9974,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8500,6 +9998,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8512,6 +10013,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8539,6 +10043,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8548,9 +10064,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8560,18 +10082,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8590,9 +10127,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8608,13 +10142,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8629,6 +10166,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8650,6 +10190,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8743,6 +10286,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8788,6 +10334,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8839,6 +10388,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8848,18 +10415,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8869,12 +10478,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -9031,6 +10700,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -9049,16 +10727,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -9067,18 +10751,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9127,9 +10817,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9154,12 +10850,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9184,15 +10922,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9209,24 +10956,45 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9251,6 +11019,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9263,6 +11034,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9272,7 +11046,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9281,25 +11058,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9314,6 +11103,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9344,6 +11151,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9353,7 +11163,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9368,6 +11178,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9407,12 +11220,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9467,6 +11274,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9481,6 +11294,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9520,6 +11336,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9562,6 +11387,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9602,6 +11430,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9686,6 +11520,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9695,6 +11532,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9710,6 +11550,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9722,6 +11565,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9782,9 +11628,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9806,6 +11664,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9881,9 +11742,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9914,12 +11772,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9932,6 +11802,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9959,6 +11835,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9995,6 +11874,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -10076,6 +11958,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10106,19 +11991,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10136,6 +12024,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10157,6 +12048,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10184,6 +12078,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10199,6 +12105,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10211,9 +12120,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10229,9 +12147,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10287,12 +12202,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10302,6 +12235,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10311,6 +12247,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10380,6 +12319,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10398,6 +12340,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10422,7 +12367,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10434,6 +12379,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10494,6 +12442,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10548,6 +12499,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10620,6 +12577,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10644,6 +12604,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10674,6 +12637,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10734,12 +12703,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10770,6 +12745,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10842,6 +12820,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10866,6 +12847,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10878,6 +12922,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10908,18 +12958,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -11001,6 +13063,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -11013,6 +13078,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -11028,6 +13096,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -11068,6 +13163,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -11083,6 +13181,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11140,6 +13241,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11158,6 +13268,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11182,9 +13298,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11194,6 +13322,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11203,6 +13334,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11242,6 +13376,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11263,15 +13400,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11305,9 +13457,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11323,6 +13490,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11341,6 +13514,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11353,6 +13529,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11365,18 +13544,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11401,6 +13592,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11413,6 +13610,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11422,22 +13622,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11509,12 +13718,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11587,6 +13790,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11775,6 +13984,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11790,6 +14002,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11856,6 +14071,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11892,6 +14110,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11904,9 +14125,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11916,6 +14143,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11958,6 +14188,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -12009,15 +14275,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -12027,24 +14308,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -12063,18 +14362,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12144,6 +14458,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12195,6 +14521,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12204,6 +14533,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12222,6 +14554,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12231,6 +14611,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12288,6 +14674,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12303,6 +14692,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12378,6 +14902,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12393,9 +14926,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12441,12 +14992,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12456,6 +15013,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12465,6 +15025,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12492,6 +15055,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12519,6 +15085,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12561,6 +15154,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12579,6 +15175,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12588,6 +15187,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12609,6 +15211,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12618,13 +15223,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12640,6 +15248,9 @@ msgstr[3] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12820,6 +15431,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12835,7 +15449,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12847,6 +15467,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12862,6 +15485,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12880,6 +15509,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12904,9 +15542,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12937,12 +15581,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12952,6 +15605,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12982,6 +15641,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12994,6 +15662,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -13006,6 +15677,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -13039,6 +15713,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -13060,27 +15737,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -13114,7 +15815,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13132,6 +15836,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13165,10 +15872,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
msgstr ""
-msgid "at"
+msgid "already shared with this group"
+msgstr ""
+
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13183,6 +15893,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13288,6 +16013,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13321,9 +16049,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13339,12 +16064,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13467,9 +16186,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13489,10 +16205,10 @@ msgstr[3] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13534,6 +16250,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13570,9 +16289,15 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13585,6 +16310,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13609,6 +16340,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13640,6 +16374,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13649,6 +16389,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13667,6 +16410,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13695,6 +16441,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13722,7 +16471,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13737,6 +16486,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13791,6 +16543,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13809,18 +16564,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13851,26 +16603,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13955,15 +16693,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -14083,7 +16836,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -14092,18 +16845,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -14137,12 +16902,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/sq_AL/gitlab.po b/locale/sq_AL/gitlab.po
index 4ef535ebf6f..c3560018979 100644
--- a/locale/sq_AL/gitlab.po
+++ b/locale/sq_AL/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Albanian\n"
"Language: sq_AL\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: sq\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:28\n"
+"PO-Revision-Date: 2019-06-14 10:21\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,37 +1459,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1856,6 +2161,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/sr_CS/gitlab.po b/locale/sr_CS/gitlab.po
index 6a7a71426ef..1118681c99d 100644
--- a/locale/sr_CS/gitlab.po
+++ b/locale/sr_CS/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Serbian (Latin)\n"
"Language: sr_CS\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: sr-CS\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:31\n"
+"PO-Revision-Date: 2019-06-14 10:16\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -72,6 +69,12 @@ msgstr[2] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -114,12 +117,24 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -147,10 +162,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -186,6 +198,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -198,12 +216,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -219,6 +249,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -237,6 +273,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -273,6 +321,9 @@ msgstr[2] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -285,9 +336,30 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -312,6 +384,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -331,13 +406,13 @@ msgstr[1] ""
msgstr[2] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -352,19 +427,19 @@ msgstr[1] ""
msgstr[2] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -390,15 +465,27 @@ msgstr[2] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -408,6 +495,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -438,6 +528,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -474,19 +567,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -516,6 +609,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -561,12 +657,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -603,6 +711,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -624,10 +735,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -636,9 +753,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -648,6 +771,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -660,9 +786,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -675,10 +810,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
+msgstr ""
+
+msgid "AddMember|No users specified."
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -687,10 +825,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -702,6 +849,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -723,6 +873,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -837,6 +990,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -855,15 +1011,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -936,9 +1101,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -972,10 +1134,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -999,21 +1164,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -1029,6 +1209,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1062,7 +1245,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1116,6 +1302,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1173,9 +1362,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1185,6 +1380,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1194,6 +1395,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1212,6 +1416,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1257,12 +1473,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1293,37 +1503,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1341,6 +1551,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1353,12 +1566,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1371,6 +1608,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1386,6 +1626,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1416,6 +1662,15 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1503,15 +1758,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1623,6 +1887,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1725,12 +2013,33 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1746,6 +2055,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1896,6 +2208,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1914,6 +2241,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -2004,9 +2334,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -2028,9 +2364,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2046,6 +2388,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2058,6 +2406,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2082,6 +2439,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2109,6 +2472,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2130,6 +2496,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2160,7 +2529,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2232,16 +2601,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2295,9 +2682,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2352,6 +2748,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2370,7 +2769,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2388,12 +2793,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2409,6 +2826,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2517,6 +2937,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2553,19 +2976,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2598,6 +3012,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2634,6 +3051,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2643,9 +3063,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2709,7 +3126,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2763,40 +3180,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2808,6 +3237,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2817,6 +3249,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2868,9 +3303,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2889,6 +3330,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -3009,6 +3453,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -3036,9 +3483,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3051,9 +3504,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3117,6 +3576,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3162,6 +3624,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3171,6 +3636,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3189,9 +3657,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3207,6 +3672,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3216,6 +3687,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3225,9 +3699,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3261,9 +3741,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3336,6 +3825,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3351,12 +3846,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3375,6 +3885,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3453,15 +3966,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3498,6 +4035,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3549,6 +4089,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3570,6 +4125,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3747,6 +4350,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3801,9 +4407,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3825,6 +4437,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3855,18 +4473,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3879,25 +4521,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3939,6 +4575,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3975,6 +4614,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3993,6 +4638,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -4017,9 +4665,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4044,6 +4722,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4080,9 +4761,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4113,12 +4791,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4131,7 +4815,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4143,9 +4830,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4281,18 +4992,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4329,9 +5073,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4341,6 +5091,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4350,6 +5106,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4359,6 +5118,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4392,9 +5157,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4491,6 +5262,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4578,6 +5352,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4587,27 +5382,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4626,6 +5454,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4638,16 +5472,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4662,6 +5508,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4725,7 +5577,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4737,9 +5589,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4821,6 +5670,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4869,6 +5724,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4878,6 +5736,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4902,6 +5763,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4947,6 +5814,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4956,6 +5832,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4974,6 +5853,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -5004,12 +5886,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5367,6 +6255,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5424,6 +6318,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5433,6 +6330,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5505,6 +6405,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5523,9 +6426,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5601,6 +6513,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5610,6 +6525,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5637,13 +6555,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5655,9 +6576,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5688,9 +6606,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5754,6 +6681,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5823,6 +6753,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5850,6 +6783,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5859,12 +6795,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5874,6 +6813,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5889,6 +6831,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5904,6 +6852,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5913,6 +6867,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5982,10 +6942,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6066,6 +7035,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6075,6 +7050,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6084,9 +7065,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6138,12 +7128,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6165,12 +7164,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6219,18 +7230,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6240,6 +7275,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6252,6 +7290,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6270,6 +7311,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6345,6 +7392,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6441,6 +7530,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6450,6 +7545,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6474,12 +7572,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6492,6 +7596,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6540,6 +7647,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6555,6 +7665,9 @@ msgstr[2] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6582,6 +7695,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6597,6 +7716,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6615,6 +7740,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6627,6 +7755,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6648,6 +7779,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6723,6 +7860,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6738,6 +7878,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6768,6 +7911,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6789,6 +7935,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6807,6 +7956,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6831,12 +7983,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6897,6 +8058,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6909,6 +8079,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6933,6 +8112,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6963,6 +8145,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6975,15 +8160,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6993,12 +8172,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -7017,6 +8190,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -7035,6 +8232,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7047,6 +8247,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7080,7 +8283,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7095,6 +8298,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7110,6 +8319,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7149,9 +8361,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7197,9 +8406,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7224,9 +8445,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7245,7 +8463,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7254,6 +8472,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7275,6 +8502,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7335,6 +8574,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7347,6 +8604,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7443,6 +8703,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7467,6 +8730,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7497,6 +8763,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7506,12 +8778,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7527,6 +8808,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7551,6 +8835,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7572,9 +8859,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7590,6 +8874,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7617,6 +8904,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7665,6 +8958,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7680,6 +8976,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7689,6 +8991,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7743,6 +9048,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7758,6 +9066,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7773,7 +9087,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7797,13 +9117,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7821,6 +9141,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7866,6 +9189,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7890,9 +9219,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7914,6 +9240,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7923,6 +9252,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7950,6 +9285,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7971,9 +9309,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7986,7 +9336,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -8013,6 +9363,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -8034,12 +9387,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8118,6 +9486,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8127,10 +9498,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgstr ""
+
+msgid "Pipelines| to purchase more minutes."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8151,6 +9525,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8211,6 +9588,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8241,6 +9621,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8250,12 +9639,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8286,6 +9693,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8298,6 +9708,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8319,7 +9738,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8337,12 +9756,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8358,12 +9831,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8391,15 +9870,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8430,6 +9918,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8451,6 +9942,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8463,6 +9957,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8490,6 +9987,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8499,9 +10008,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8511,18 +10026,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8541,9 +10071,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8559,13 +10086,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8580,6 +10110,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8601,6 +10134,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8694,6 +10230,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8739,6 +10278,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8790,6 +10332,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8799,18 +10359,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8820,12 +10422,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8982,6 +10644,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -9000,16 +10671,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -9018,18 +10695,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9078,9 +10761,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9105,12 +10794,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9135,15 +10866,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9159,24 +10899,45 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9201,6 +10962,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9213,6 +10977,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9222,7 +10989,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9231,25 +11001,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9264,6 +11046,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9294,6 +11094,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9303,7 +11106,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9318,6 +11121,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9357,12 +11163,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9417,6 +11217,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9429,6 +11235,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9468,6 +11277,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9510,6 +11328,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9549,6 +11370,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9633,6 +11460,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9642,6 +11472,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9657,6 +11490,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9669,6 +11505,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9729,9 +11568,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9753,6 +11604,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9828,9 +11682,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9861,12 +11712,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9879,6 +11742,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9906,6 +11775,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9942,6 +11814,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -10023,6 +11898,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10053,19 +11931,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10083,6 +11964,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10104,6 +11988,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10131,6 +12018,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10146,6 +12045,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10158,9 +12060,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10176,9 +12087,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10233,12 +12141,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10248,6 +12174,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10257,6 +12186,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10326,6 +12258,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10344,6 +12279,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10368,7 +12306,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10380,6 +12318,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10440,6 +12381,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10494,6 +12438,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10566,6 +12516,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10590,6 +12543,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10620,6 +12576,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10680,12 +12642,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10716,6 +12684,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10788,6 +12759,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10812,6 +12786,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10824,6 +12861,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10854,18 +12897,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10947,6 +13002,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10959,6 +13017,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10974,6 +13035,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -11013,6 +13101,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -11028,6 +13119,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11085,6 +13179,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11103,6 +13206,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11127,9 +13236,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11139,6 +13260,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11148,6 +13272,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11187,6 +13314,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11208,15 +13338,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11250,9 +13395,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11268,6 +13428,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11286,6 +13452,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11298,6 +13467,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11310,18 +13482,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11346,6 +13530,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11358,6 +13548,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11367,22 +13560,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11454,12 +13656,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11532,6 +13728,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11718,6 +13920,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11733,6 +13938,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11799,6 +14007,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11835,6 +14046,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11847,9 +14061,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11859,6 +14079,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11901,6 +14124,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11952,15 +14211,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11970,24 +14244,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -12006,18 +14298,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12087,6 +14394,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12138,6 +14457,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12147,6 +14469,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12165,6 +14490,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12174,6 +14547,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12231,6 +14610,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12246,6 +14628,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12321,6 +14838,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12336,9 +14862,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12384,12 +14928,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12399,6 +14949,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12408,6 +14961,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12435,6 +14991,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12462,6 +15021,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12504,6 +15090,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12522,6 +15111,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12531,6 +15123,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12552,6 +15147,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12561,13 +15159,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12582,6 +15183,9 @@ msgstr[2] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12762,6 +15366,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12777,7 +15384,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12789,6 +15402,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12804,6 +15420,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12822,6 +15444,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12846,9 +15477,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12879,12 +15516,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12894,6 +15540,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12924,6 +15576,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12936,6 +15597,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12948,6 +15612,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12981,6 +15648,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -13002,27 +15672,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -13056,7 +15750,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13074,6 +15771,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13107,10 +15807,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13125,6 +15828,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13224,6 +15942,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13257,9 +15978,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13275,12 +15993,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13401,9 +16113,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13422,10 +16131,10 @@ msgstr[2] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13467,6 +16176,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13500,9 +16212,15 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13515,6 +16233,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13539,6 +16263,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13569,6 +16296,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13578,6 +16311,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13596,6 +16332,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13623,6 +16362,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13650,7 +16392,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13665,6 +16407,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13719,6 +16464,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13737,18 +16485,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13779,24 +16524,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13881,15 +16614,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -14004,7 +16752,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -14013,18 +16761,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -14058,12 +16818,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/sr_SP/gitlab.po b/locale/sr_SP/gitlab.po
index b8596ea8a38..f3ce29f397f 100644
--- a/locale/sr_SP/gitlab.po
+++ b/locale/sr_SP/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Serbian (Cyrillic)\n"
"Language: sr_SP\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: sr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:31\n"
+"PO-Revision-Date: 2019-06-14 10:16\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -72,6 +69,12 @@ msgstr[2] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -114,12 +117,24 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -147,10 +162,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -186,6 +198,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -198,12 +216,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -219,6 +249,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -237,6 +273,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -273,6 +321,9 @@ msgstr[2] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -285,9 +336,30 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -312,6 +384,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -331,13 +406,13 @@ msgstr[1] ""
msgstr[2] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -352,19 +427,19 @@ msgstr[1] ""
msgstr[2] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -390,15 +465,27 @@ msgstr[2] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -408,6 +495,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -438,6 +528,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -474,19 +567,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -516,6 +609,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -561,12 +657,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -603,6 +711,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -624,10 +735,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -636,9 +753,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -648,6 +771,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -660,9 +786,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -675,10 +810,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
+msgstr ""
+
+msgid "AddMember|No users specified."
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -687,10 +825,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -702,6 +849,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -723,6 +873,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -837,6 +990,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -855,15 +1011,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -936,9 +1101,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -972,10 +1134,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -999,21 +1164,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -1029,6 +1209,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1062,7 +1245,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1116,6 +1302,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1173,9 +1362,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1185,6 +1380,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1194,6 +1395,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1212,6 +1416,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1257,12 +1473,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1293,37 +1503,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1341,6 +1551,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1353,12 +1566,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1371,6 +1608,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1386,6 +1626,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1416,6 +1662,15 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1503,15 +1758,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1623,6 +1887,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1725,12 +2013,33 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1746,6 +2055,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1896,6 +2208,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1914,6 +2241,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -2004,9 +2334,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -2028,9 +2364,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2046,6 +2388,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2058,6 +2406,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2082,6 +2439,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2109,6 +2472,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2130,6 +2496,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2160,7 +2529,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2232,16 +2601,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2295,9 +2682,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2352,6 +2748,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2370,7 +2769,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2388,12 +2793,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2409,6 +2826,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2517,6 +2937,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2553,19 +2976,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2598,6 +3012,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2634,6 +3051,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2643,9 +3063,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2709,7 +3126,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2763,40 +3180,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2808,6 +3237,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2817,6 +3249,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2868,9 +3303,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2889,6 +3330,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -3009,6 +3453,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -3036,9 +3483,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3051,9 +3504,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3117,6 +3576,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3162,6 +3624,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3171,6 +3636,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3189,9 +3657,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3207,6 +3672,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3216,6 +3687,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3225,9 +3699,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3261,9 +3741,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3336,6 +3825,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3351,12 +3846,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3375,6 +3885,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3453,15 +3966,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3498,6 +4035,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3549,6 +4089,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3570,6 +4125,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3747,6 +4350,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3801,9 +4407,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3825,6 +4437,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3855,18 +4473,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3879,25 +4521,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3939,6 +4575,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3975,6 +4614,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3993,6 +4638,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -4017,9 +4665,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4044,6 +4722,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4080,9 +4761,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4113,12 +4791,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4131,7 +4815,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4143,9 +4830,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4281,18 +4992,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4329,9 +5073,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4341,6 +5091,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4350,6 +5106,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4359,6 +5118,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4392,9 +5157,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4491,6 +5262,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4578,6 +5352,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4587,27 +5382,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4626,6 +5454,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4638,16 +5472,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4662,6 +5508,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4725,7 +5577,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4737,9 +5589,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4821,6 +5670,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4869,6 +5724,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4878,6 +5736,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4902,6 +5763,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4947,6 +5814,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4956,6 +5832,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4974,6 +5853,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -5004,12 +5886,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5367,6 +6255,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5424,6 +6318,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5433,6 +6330,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5505,6 +6405,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5523,9 +6426,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5601,6 +6513,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5610,6 +6525,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5637,13 +6555,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5655,9 +6576,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5688,9 +6606,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5754,6 +6681,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5823,6 +6753,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5850,6 +6783,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5859,12 +6795,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5874,6 +6813,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5889,6 +6831,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5904,6 +6852,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5913,6 +6867,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5982,10 +6942,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6066,6 +7035,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6075,6 +7050,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6084,9 +7065,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6138,12 +7128,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6165,12 +7164,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6219,18 +7230,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6240,6 +7275,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6252,6 +7290,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6270,6 +7311,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6345,6 +7392,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6441,6 +7530,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6450,6 +7545,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6474,12 +7572,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6492,6 +7596,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6540,6 +7647,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6555,6 +7665,9 @@ msgstr[2] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6582,6 +7695,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6597,6 +7716,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6615,6 +7740,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6627,6 +7755,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6648,6 +7779,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6723,6 +7860,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6738,6 +7878,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6768,6 +7911,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6789,6 +7935,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6807,6 +7956,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6831,12 +7983,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6897,6 +8058,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6909,6 +8079,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6933,6 +8112,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6963,6 +8145,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6975,15 +8160,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6993,12 +8172,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -7017,6 +8190,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -7035,6 +8232,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7047,6 +8247,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7080,7 +8283,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7095,6 +8298,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7110,6 +8319,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7149,9 +8361,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7197,9 +8406,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7224,9 +8445,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7245,7 +8463,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7254,6 +8472,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7275,6 +8502,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7335,6 +8574,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7347,6 +8604,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7443,6 +8703,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7467,6 +8730,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7497,6 +8763,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7506,12 +8778,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7527,6 +8808,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7551,6 +8835,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7572,9 +8859,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7590,6 +8874,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7617,6 +8904,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7665,6 +8958,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7680,6 +8976,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7689,6 +8991,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7743,6 +9048,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7758,6 +9066,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7773,7 +9087,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7797,13 +9117,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7821,6 +9141,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7866,6 +9189,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7890,9 +9219,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7914,6 +9240,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7923,6 +9252,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7950,6 +9285,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7971,9 +9309,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7986,7 +9336,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -8013,6 +9363,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -8034,12 +9387,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8118,6 +9486,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8127,10 +9498,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgstr ""
+
+msgid "Pipelines| to purchase more minutes."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8151,6 +9525,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8211,6 +9588,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8241,6 +9621,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8250,12 +9639,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8286,6 +9693,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8298,6 +9708,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8319,7 +9738,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8337,12 +9756,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8358,12 +9831,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8391,15 +9870,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8430,6 +9918,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8451,6 +9942,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8463,6 +9957,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8490,6 +9987,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8499,9 +10008,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8511,18 +10026,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8541,9 +10071,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8559,13 +10086,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8580,6 +10110,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8601,6 +10134,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8694,6 +10230,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8739,6 +10278,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8790,6 +10332,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8799,18 +10359,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8820,12 +10422,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8982,6 +10644,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -9000,16 +10671,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -9018,18 +10695,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9078,9 +10761,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9105,12 +10794,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9135,15 +10866,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9159,24 +10899,45 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9201,6 +10962,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9213,6 +10977,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9222,7 +10989,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9231,25 +11001,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9264,6 +11046,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9294,6 +11094,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9303,7 +11106,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9318,6 +11121,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9357,12 +11163,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9417,6 +11217,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9429,6 +11235,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9468,6 +11277,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9510,6 +11328,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9549,6 +11370,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9633,6 +11460,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9642,6 +11472,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9657,6 +11490,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9669,6 +11505,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9729,9 +11568,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9753,6 +11604,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9828,9 +11682,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9861,12 +11712,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9879,6 +11742,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9906,6 +11775,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9942,6 +11814,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -10023,6 +11898,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10053,19 +11931,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10083,6 +11964,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10104,6 +11988,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10131,6 +12018,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10146,6 +12045,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10158,9 +12060,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10176,9 +12087,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10233,12 +12141,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10248,6 +12174,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10257,6 +12186,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10326,6 +12258,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10344,6 +12279,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10368,7 +12306,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10380,6 +12318,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10440,6 +12381,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10494,6 +12438,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10566,6 +12516,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10590,6 +12543,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10620,6 +12576,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10680,12 +12642,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10716,6 +12684,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10788,6 +12759,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10812,6 +12786,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10824,6 +12861,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10854,18 +12897,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10947,6 +13002,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10959,6 +13017,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10974,6 +13035,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -11013,6 +13101,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -11028,6 +13119,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11085,6 +13179,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11103,6 +13206,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11127,9 +13236,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11139,6 +13260,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11148,6 +13272,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11187,6 +13314,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11208,15 +13338,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11250,9 +13395,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11268,6 +13428,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11286,6 +13452,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11298,6 +13467,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11310,18 +13482,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11346,6 +13530,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11358,6 +13548,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11367,22 +13560,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11454,12 +13656,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11532,6 +13728,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11718,6 +13920,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11733,6 +13938,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11799,6 +14007,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11835,6 +14046,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11847,9 +14061,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11859,6 +14079,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11901,6 +14124,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11952,15 +14211,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11970,24 +14244,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -12006,18 +14298,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12087,6 +14394,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12138,6 +14457,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12147,6 +14469,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12165,6 +14490,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12174,6 +14547,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12231,6 +14610,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12246,6 +14628,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12321,6 +14838,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12336,9 +14862,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12384,12 +14928,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12399,6 +14949,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12408,6 +14961,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12435,6 +14991,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12462,6 +15021,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12504,6 +15090,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12522,6 +15111,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12531,6 +15123,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12552,6 +15147,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12561,13 +15159,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12582,6 +15183,9 @@ msgstr[2] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12762,6 +15366,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12777,7 +15384,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12789,6 +15402,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12804,6 +15420,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12822,6 +15444,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12846,9 +15477,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12879,12 +15516,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12894,6 +15540,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12924,6 +15576,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12936,6 +15597,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12948,6 +15612,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12981,6 +15648,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -13002,27 +15672,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -13056,7 +15750,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13074,6 +15771,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13107,10 +15807,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13125,6 +15828,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13224,6 +15942,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13257,9 +15978,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13275,12 +15993,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13401,9 +16113,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13422,10 +16131,10 @@ msgstr[2] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13467,6 +16176,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13500,9 +16212,15 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13515,6 +16233,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13539,6 +16263,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13569,6 +16296,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13578,6 +16311,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13596,6 +16332,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13623,6 +16362,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13650,7 +16392,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13665,6 +16407,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13719,6 +16464,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13737,18 +16485,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13779,24 +16524,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13881,15 +16614,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -14004,7 +16752,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -14013,18 +16761,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -14058,12 +16818,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/sv_SE/gitlab.po b/locale/sv_SE/gitlab.po
index 5504a0d8cf4..0bed58e7c61 100644
--- a/locale/sv_SE/gitlab.po
+++ b/locale/sv_SE/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Swedish\n"
"Language: sv_SE\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: sv-SE\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:32\n"
+"PO-Revision-Date: 2019-06-14 10:18\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,37 +1459,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1856,6 +2161,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/sw_KE/gitlab.po b/locale/sw_KE/gitlab.po
index c56880bae2a..8c4ae06837d 100644
--- a/locale/sw_KE/gitlab.po
+++ b/locale/sw_KE/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Swahili\n"
"Language: sw_KE\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: sw\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:32\n"
+"PO-Revision-Date: 2019-06-14 10:17\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr ""
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -67,6 +64,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
msgstr[1] ""
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] ""
@@ -131,10 +143,7 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -179,12 +194,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr ""
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr ""
@@ -218,6 +251,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -250,6 +295,9 @@ msgstr[1] ""
msgid "%{text} is available"
msgstr ""
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr ""
@@ -262,9 +310,29 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -289,6 +357,9 @@ msgstr ""
msgid "- show less"
msgstr ""
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] ""
@@ -305,12 +376,12 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -323,17 +394,17 @@ msgstr[0] ""
msgstr[1] ""
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -355,15 +426,27 @@ msgstr[1] ""
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr ""
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr ""
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr ""
@@ -373,6 +456,9 @@ msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,19 +528,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -481,6 +570,9 @@ msgstr ""
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -526,12 +618,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr ""
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -568,6 +672,9 @@ msgstr ""
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -589,10 +696,16 @@ msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -601,9 +714,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr ""
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -613,6 +732,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -625,9 +747,18 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -640,10 +771,13 @@ msgstr ""
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -652,10 +786,19 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr ""
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
msgstr ""
msgid "Admin Area"
@@ -667,6 +810,9 @@ msgstr ""
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -688,6 +834,9 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -802,6 +951,9 @@ msgstr ""
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] ""
@@ -819,15 +971,24 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr ""
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -936,10 +1094,13 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when updating the issue weight"
msgstr ""
msgid "An error occurred while deleting the approvers group"
@@ -963,21 +1124,36 @@ msgstr ""
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr ""
msgid "An error occurred while fetching pending comments"
msgstr ""
-msgid "An error occurred while fetching sidebar data"
+msgid "An error occurred while fetching projects autocomplete."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching sidebar data"
msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr ""
@@ -993,6 +1169,9 @@ msgstr ""
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr ""
@@ -1026,7 +1205,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1080,6 +1262,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1137,9 +1322,15 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr ""
@@ -1149,6 +1340,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1158,6 +1355,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1176,6 +1376,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1217,12 +1429,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr ""
@@ -1253,37 +1459,37 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
-msgid "Are you sure you want to delete this pipeline schedule?"
+msgid "Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "Are you sure you want to erase this build?"
+msgid "Are you sure you want to cancel editing this comment?"
msgstr ""
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
-msgid "Are you sure you want to lose your issue information?"
+msgid "Are you sure you want to delete this list?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
+msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
-msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgid "Are you sure you want to erase this build?"
msgstr ""
-msgid "Are you sure you want to remove %{group_name}?"
+msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
+msgid "Are you sure you want to lose your issue information?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}?"
+msgid "Are you sure you want to permanently delete this license?"
msgstr ""
-msgid "Are you sure you want to remove group %{name}"
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
-msgid "Are you sure you want to remove group %{name}?"
+msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove the attachment?"
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr ""
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -1346,6 +1582,12 @@ msgstr ""
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1376,6 +1618,14 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -1463,15 +1713,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1583,6 +1842,30 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1685,12 +1968,31 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr ""
msgid "Branch name"
msgstr ""
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr ""
@@ -1856,6 +2161,21 @@ msgstr ""
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,6 +2341,12 @@ msgstr ""
msgid "Change Weight"
msgstr ""
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
msgid "Change path"
msgstr ""
@@ -2018,6 +2359,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr ""
@@ -2069,6 +2425,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,7 +2482,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2192,16 +2554,34 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2255,9 +2635,18 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2330,7 +2722,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2348,12 +2746,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2369,6 +2779,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2477,6 +2890,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2513,19 +2929,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2558,6 +2965,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,9 +3016,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2669,7 +3079,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2828,9 +3256,15 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr ""
@@ -2849,6 +3283,9 @@ msgstr ""
msgid "Comment form position"
msgstr ""
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3076,6 +3528,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3121,6 +3576,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr ""
@@ -3166,6 +3624,12 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr ""
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr ""
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr ""
@@ -3295,6 +3777,12 @@ msgstr ""
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -3310,12 +3798,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3412,15 +3918,39 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
msgstr ""
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,9 +4358,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3783,6 +4388,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr ""
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3837,25 +4472,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3897,6 +4526,9 @@ msgstr ""
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,6 +4565,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3951,6 +4589,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4089,7 +4766,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4287,9 +5024,15 @@ msgstr ""
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4350,9 +5108,15 @@ msgstr ""
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4536,6 +5303,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5462,6 +6355,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5558,6 +6463,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5567,6 +6475,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5645,9 +6556,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr ""
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5780,6 +6703,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -5816,12 +6745,15 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,6 +6780,12 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,18 +7178,42 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6195,6 +7223,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,6 +7238,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6225,6 +7259,12 @@ msgstr ""
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr ""
msgid "January"
msgstr ""
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr ""
msgid "July"
msgstr ""
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr ""
@@ -6405,6 +7493,9 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6429,12 +7520,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6447,6 +7544,9 @@ msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr ""
@@ -6495,6 +7595,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6536,6 +7642,12 @@ msgstr ""
msgid "Last updated"
msgstr ""
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6569,6 +7687,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6602,6 +7726,12 @@ msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6721,6 +7857,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6760,6 +7902,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr ""
msgid "March"
msgstr ""
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr ""
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6886,6 +8058,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6916,6 +8091,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr ""
@@ -6928,15 +8106,9 @@ msgstr ""
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr ""
@@ -6946,12 +8118,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr ""
@@ -6970,6 +8136,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6988,6 +8178,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -7000,6 +8193,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -7033,7 +8229,7 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7150,9 +8352,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr ""
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7228,6 +8448,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
@@ -7288,6 +8520,24 @@ msgstr ""
msgid "Move issue"
msgstr ""
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr ""
@@ -7300,6 +8550,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7395,6 +8648,9 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -7419,6 +8675,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -7449,6 +8708,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7458,12 +8723,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,6 +8753,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7542,6 +8819,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
@@ -7617,6 +8903,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,6 +8936,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr ""
@@ -7710,6 +9011,12 @@ msgstr ""
msgid "November"
msgstr ""
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7725,7 +9032,13 @@ msgstr ""
msgid "OfSearchInADropdown|Filter"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7772,6 +9085,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7865,6 +9184,9 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr ""
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,6 +9229,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7964,6 +9307,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr ""
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8342,15 +9814,24 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr ""
msgid "Profile Settings"
msgstr ""
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8381,6 +9862,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8402,6 +9886,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8414,6 +9901,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8441,6 +9931,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8450,9 +9952,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8462,18 +9970,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8492,9 +10015,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8510,13 +10030,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,6 +10054,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8552,6 +10078,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8645,6 +10174,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8750,18 +10303,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr ""
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8933,6 +10588,15 @@ msgstr ""
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8951,16 +10615,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8969,18 +10639,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9109,24 +10842,45 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr ""
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,7 +10932,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9181,25 +10944,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9244,6 +11037,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace all label(s)"
+msgstr ""
+
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9496,6 +11310,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr ""
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9700,6 +11544,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9775,9 +11622,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9889,6 +11754,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -10000,19 +11871,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,6 +11928,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
@@ -10078,6 +11958,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10093,6 +11985,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10105,9 +12000,18 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr ""
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,7 +12245,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10326,6 +12257,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10386,6 +12320,9 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -10440,6 +12377,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10512,6 +12455,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
@@ -10536,6 +12482,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
@@ -10662,6 +12623,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr ""
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr ""
msgid "Team"
msgstr ""
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10905,6 +12956,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10958,6 +13039,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,6 +13198,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11093,6 +13210,9 @@ msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,22 +13498,31 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
+msgid "This issue is confidential"
msgstr ""
msgid "This issue is locked."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11661,6 +13856,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11778,6 +13982,9 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,9 +13997,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11802,6 +14015,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11895,15 +14147,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -12030,6 +14330,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr ""
msgid "Upload file"
msgstr ""
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr ""
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12174,6 +14546,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12189,6 +14564,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr ""
@@ -12264,6 +14774,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12327,12 +14864,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr ""
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12405,6 +14957,33 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr ""
@@ -12504,13 +15095,16 @@ msgstr ""
msgid "Weight %{weight}"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12764,6 +15379,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12836,6 +15475,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr ""
@@ -13049,10 +15742,13 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13160,6 +15871,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,10 +16057,10 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13400,6 +16102,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] ""
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,7 +16313,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13707,22 +16445,12 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
msgstr ""
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr ""
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr ""
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr ""
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/tr_TR/gitlab.po b/locale/tr_TR/gitlab.po
index 37fefca2afd..b976a7d9ed0 100644
--- a/locale/tr_TR/gitlab.po
+++ b/locale/tr_TR/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Turkish\n"
"Language: tr_TR\n"
"MIME-Version: 1.0\n"
@@ -13,19 +13,16 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: tr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-13 08:55\n"
+"PO-Revision-Date: 2019-06-14 10:18\n"
msgid " Please sign in."
msgstr " Lütfen oturum açın."
-msgid " Status"
-msgstr " Durum"
-
msgid " Try to %{action} this file again."
msgstr " Bu dosyaya yine %{action} deneyin."
msgid " You need to do this before %{grace_period_deadline}."
-msgstr ""
+msgstr " Bunu %{grace_period_deadline} önce yapmanız gerekiyor."
msgid " and"
msgstr " ve"
@@ -67,6 +64,11 @@ msgstr[1] "%d 'e bağlı işlem"
msgid "%d commits"
msgstr "%d iÅŸlem"
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d dışa aktaran"
@@ -102,11 +104,21 @@ msgid_plural "%d merge requests"
msgstr[0] "%d birleÅŸtirme isteÄŸi"
msgstr[1] "%d birleÅŸtirme isteÄŸi"
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d metrik"
msgstr[1] "%d metrik"
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] "%d aşamalı değişiklik"
@@ -131,11 +143,8 @@ msgstr "%{authorsName} kişisinin tartışması"
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} %{commit_timeago} yazdı"
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr "%{counter_storage} (%{counter_repositories} depo, %{counter_build_artifacts} yapı eseri, %{counter_lfs_objects} LFS)"
-
-msgid "%{count} %{alerts}"
-msgstr "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
+msgstr ""
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
@@ -167,6 +176,12 @@ msgid_plural "%{count} pending comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr "%{edit_in_new_fork_notice} Bu işlemi tekrar özenle seçmeyi deneyin."
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr "%{edit_in_new_fork_notice} Bu işlemi tekrar geri almaya çalışın."
+
msgid "%{filePath} deleted"
msgstr "%{filePath} silindi"
@@ -179,12 +194,24 @@ msgstr "%{gitlab_ci_yml} bu işlemde bulunamadı"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} kaldırılacak! Emin misiniz?"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} kullanılamaz"
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr "Bir %{group_level_name} grubunda %{level_name} izin verilmez."
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -200,6 +227,12 @@ msgstr "%{lock_path} dizini %{lock_user_id} GitLab kullanıcısı tarafından ki
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr "%{name} kullanıcısının avatarı"
@@ -218,9 +251,21 @@ msgstr "%{service_title} etkinleÅŸtirildi."
msgid "%{service_title} settings saved, but not activated."
msgstr ""
-msgid "%{spammable_titlecase} was submitted to Akismet successfully."
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
msgstr ""
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
+msgid "%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr "%{spammable_titlecase} başarıyla Akismet'e gönderildi."
+
msgid "%{state} epics"
msgstr "%{state} epik"
@@ -250,6 +295,9 @@ msgstr[1] "%{text} %{files} dosyaları"
msgid "%{text} is available"
msgstr "%{text} kullanılabilir"
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr "%{title} deÄŸiÅŸiklik"
@@ -257,14 +305,34 @@ msgid "%{unstaged} unstaged and %{staged} staged changes"
msgstr "%{unstaged} aşamasız ve %{staged} aşamalı değişiklik"
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
-msgstr ""
+msgstr "Hangi bilgilerin GitLab Inc. ile paylaşıldığı hakkında %{usage_ping_link_start}daha fazla bilgi edinin%{usage_ping_link_end}."
msgid "%{user_name} profile page"
msgstr "%{user_name} profil sayfası"
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr "'%{level}' geçerli bir görünürlük seviyesi değil"
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr "(DeÄŸiÅŸiklik yok)"
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr "(dış kaynak)"
@@ -289,6 +357,9 @@ msgstr "- Çalıştırıcı duraklatıldı ve yeni işler almayacak"
msgid "- show less"
msgstr "- daha az göster"
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] "1 %{type} ek"
@@ -305,14 +376,14 @@ msgstr[0] "1 gün"
msgstr[1] "%d gün"
msgid "1 closed issue"
-msgid_plural "%d closed issues"
-msgstr[0] "1 kapatılmış sorun"
-msgstr[1] "%d kapatılmış sorun"
+msgid_plural "%{issues} closed issues"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
-msgstr[0] "1 kapatılmış birleştirme talebi"
-msgstr[1] "%d kapatılmış birleştirme talebi"
+msgid_plural "%{merge_requests} closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 day"
msgstr "1 gün"
@@ -323,19 +394,19 @@ msgstr[0] "1 grup"
msgstr[1] "%d grup"
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
-msgstr[0] "1 birleÅŸtirilmiÅŸ birleÅŸtirme talebi"
-msgstr[1] "%d birleÅŸtirilmiÅŸ birleÅŸtirme talebi"
+msgid_plural "%{merge_requests} merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
-msgstr[0] "1 açık sorun"
-msgstr[1] "%d açık sorun"
+msgid_plural "%{issues} open issues"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
-msgstr[0] "1 açık birleştirme talebi"
-msgstr[1] "%d açık birleştirme talebi"
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] ""
+msgstr[1] ""
msgid "1 pipeline"
msgid_plural "%d pipelines"
@@ -355,15 +426,27 @@ msgstr[1] "%d kullanıcı"
msgid "1 week"
msgstr "1 hafta"
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr "İlk katkı!"
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr "2FA"
msgid "2FA enabled"
msgstr "2FA etkin"
+msgid "2FADevice|Registered On"
+msgstr ""
+
msgid "3 days"
msgstr "3 gün"
@@ -373,20 +456,23 @@ msgstr "3 saat"
msgid "30 minutes"
msgstr "30 dakika"
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
-msgstr "403|İzin almak için lütfen GitLab yöneticinize başvurun."
+msgstr "İzin almak için lütfen GitLab yöneticinize başvurun."
msgid "403|You don't have the permission to access this page."
-msgstr "403 | Bu sayfaya eriÅŸim izniniz yok."
+msgstr "Bu sayfaya eriÅŸim izniniz yok."
msgid "404|Make sure the address is correct and the page hasn't moved."
-msgstr "404|Adresin doğru olduğundan ve sayfanın taşınmadığından emin olun."
+msgstr "Adresin doğru olduğundan ve sayfanın taşınmadığından emin olun."
msgid "404|Page Not Found"
-msgstr "404|Sayfa Bulunamadı"
+msgstr "Sayfa Bulunamadı"
msgid "404|Please contact your GitLab administrator if you think this is a mistake."
-msgstr "404|Lütfen bunun bir hata olduğunu düşünüyorsanız, GitLab yöneticinizle görüşün."
+msgstr "Lütfen bunun bir hata olduğunu düşünüyorsanız, GitLab yöneticinizle görüşün."
msgid "8 hours"
msgstr "8 saat"
@@ -403,6 +489,9 @@ msgstr ""
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -439,26 +528,26 @@ msgstr "GitLab yerine CI/CD için Netlify kullanan, ancak diğer tüm GitLab öz
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr "GitLab yerine CI/CD için Netlify kullanan, ancak diğer tüm GitLab özelliklerine sahip bir Jekyll sitesi."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
+msgstr ""
+
msgid "A default branch cannot be chosen for an empty project."
msgstr "Boş bir proje için bir varsayılan dal seçilemez."
msgid "A deleted user"
msgstr "Silinmiş kullanıcı"
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr "GitLab'ın suistimal ekibinin bir üyesi raporunuzu en kısa sürede gözden geçirecek."
-
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr "Çatalınızdan yeni bir dal oluşturulacak ve yeni bir birleştirme talebi başlatılacak."
msgid "A new impersonation token has been created."
-msgstr ""
+msgstr "Yeni bir kimliğe bürünme belirteci oluşturuldu."
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr "GitLab yerine CI/CD için Netlify kullanan, ancak diğer tüm GitLab özelliklerine sahip bir düz bir HTML sitesi."
@@ -481,6 +570,9 @@ msgstr "Bu dala yazma yetkisi olan kullanıcı bu seçeneği seçti"
msgid "API Help"
msgstr "API Yardımı"
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr "GitLab Hakkında"
@@ -512,7 +604,7 @@ msgid "Access Tokens"
msgstr "Erişim Anahtarları"
msgid "Access denied for your LDAP account."
-msgstr ""
+msgstr "LDAP hesabınız için erişim reddedildi."
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "Erişim reddedildi! Lütfen bu depoya dağıtım anahtarlarını ekleyebileceğinizi doğrulayın."
@@ -521,17 +613,29 @@ msgid "Access expiration date"
msgstr "EriÅŸim bitiÅŸ tarihi"
msgid "Access forbidden. Check your access level."
-msgstr ""
+msgstr "Erişim yasaklandı. Erişim seviyenizi kontrol edin."
msgid "Access to '%{classification_label}' not allowed"
msgstr "'%{classification_label}' eriÅŸimine izin verilmedi"
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr "Hesap"
msgid "Account and limit"
msgstr "Hesap ve sınırı"
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr "Bir uyarı alırken yapılması gerekenler."
@@ -568,6 +672,9 @@ msgstr "Kubernetes kümesi ekle"
msgid "Add README"
msgstr "BENÄ°OKU ekle"
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr "Madde iÅŸareti listesi ekle"
@@ -589,11 +696,17 @@ msgstr "Tablo ekle"
msgid "Add a task list"
msgstr "Görev listesi ekle"
+msgid "Add a todo"
+msgstr "Bir yapılacak ekleyin"
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Tüm e-posta iletişiminde görünecek ek metin ekleyin. %{character_limit} karakter sınırı"
-msgid "Add approver(s)"
-msgstr "Onaylayan(ları) ekle"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
+msgstr ""
msgid "Add approvers"
msgstr "Onaylayanları ekle"
@@ -601,9 +714,15 @@ msgstr "Onaylayanları ekle"
msgid "Add bold text"
msgstr "Kalın metin ekle"
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr "Åžimdi yorum ekle"
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "E-postalar için üstbilgi ve altbilgi ekleyin. Renk ayarları sadece uygulama arabirimi içinde uygulanacak unutmayın"
@@ -613,6 +732,9 @@ msgstr "Resim yorumu ekle"
msgid "Add italic text"
msgstr "EÄŸik metin ekle"
+msgid "Add label(s)"
+msgstr "Etiket(ler) ekleyin"
+
msgid "Add license"
msgstr "Lisans ekle"
@@ -625,9 +747,18 @@ msgstr "Yeni uygulama ekle"
msgid "Add new directory"
msgstr "Yeni dizin ekle"
+msgid "Add or subtract spent time"
+msgstr "Harcanan zamanı ekleyin veya çıkarın"
+
msgid "Add reaction"
msgstr "Tepki ekle"
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr "Projeye ekle"
@@ -640,23 +771,35 @@ msgstr "Yapılacaklara Ekle"
msgid "Add user(s) to the group:"
msgstr "Gruba kullanıcı(lar) ekleyin:"
-msgid "Add users or groups who are allowed to approve every merge request"
-msgstr "Her bir birleştirme isteğini onaylamasına izin verilen kullanıcıları veya grupları ekle"
-
msgid "Add users to group"
msgstr "Kullanıcıları gruba ekle"
+msgid "AddMember|No users specified."
+msgstr "Kullanıcı belirtilmedi."
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
+msgstr "Çok fazla kullanıcı belirtildi (sınır %{user_limit})"
+
msgid "Added at"
msgstr "Tarihinde eklendi"
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr "GitLab örneğinizde yeni uygulamalar eklemek devre dışı bırakıldı. İzin almak için lütfen GitLab yöneticinize başvurun"
+msgid "Additional minutes"
+msgstr "Ek dakika"
+
msgid "Additional text"
msgstr "Ek metin"
-msgid "Aditional minutes"
-msgstr "Ekstra dakika"
+msgid "Adds"
+msgstr "Ekler"
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
+msgstr "Bir yapılacak ekler."
msgid "Admin Area"
msgstr "Yönetici alanı"
@@ -667,6 +810,9 @@ msgstr "Yönetim Genel Bakış"
msgid "Admin Section"
msgstr "Yönetici Bölümü"
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -677,28 +823,31 @@ msgid "AdminArea|Stop all jobs"
msgstr "Tüm işleri durdur"
msgid "AdminArea|Stop all jobs?"
-msgstr "Tüm işleri durdur?"
+msgstr "Tüm işler durdurulsun mu?"
msgid "AdminArea|Stop jobs"
msgstr "Ä°ÅŸleri durdur"
msgid "AdminArea|Stopping jobs failed"
-msgstr "AdminArea|Durdurma işleri başarısız oldu"
+msgstr "İşleri durdurma başarısız oldu"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
-msgstr "AdminArea|Bütün işleri durdurmak üzeresiniz. Bu işlem çalışan tüm mevcut işleri durduracaktır."
+msgstr "Bütün işleri durdurmak üzeresiniz. Bu işlem, çalışan tüm mevcut işleri durduracaktır."
+
+msgid "AdminNote|Note"
+msgstr ""
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
-msgstr "AdminProjects|Sil"
+msgstr "Sil"
msgid "AdminProjects|Delete Project %{projectName}?"
-msgstr "AdminProjects|%{projectName} projesi silinsin mi?"
+msgstr "%{projectName} projesi silinsin mi?"
msgid "AdminProjects|Delete project"
-msgstr "AdminProjects|Projeyi sil"
+msgstr "Projeyi sil"
msgid "AdminSettings|Auto DevOps domain"
msgstr "Otomatik DevOps etki alanı"
@@ -802,6 +951,9 @@ msgstr "GeliÅŸmiÅŸ ayarlar"
msgid "After a successful password update you will be redirected to login screen."
msgstr "Başarılı bir şifre güncellemesinden sonra giriş ekranına yönlendirileceksiniz."
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "Uyarı"
@@ -819,15 +971,24 @@ msgstr "Tüm Kullanıcılar"
msgid "All changes are committed"
msgstr "Tüm değişiklikler işlendi"
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Tüm özellikler şablonlardan veya içe aktarırken boş projeler için etkindir, ancak daha sonra proje ayarlarında bunları devre dışı bırakabilirsiniz."
+msgid "All groups and projects"
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr "Bu dönüm noktası için tüm konular kapalı. Şimdi bu dönüm noktasını kapatabilirsiniz."
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
+msgid "All projects"
+msgstr ""
+
msgid "All todos were marked as done."
msgstr "Tüm yapılacaklar yapıldı olarak işaretlendi."
@@ -900,9 +1061,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr "Form gönderildiğinde otomatik SSH anahtarı oluşturur. Daha fazla bilgi için belgeleri inceleyin."
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr "%{link_to_client} adlı uygulama, GitLab hesabınıza erişim talep ediyor."
@@ -936,12 +1094,15 @@ msgstr "Blob datanın öngösteriminde, bir hata meydana geldi"
msgid "An error occurred when toggling the notification subscription"
msgstr "Bildirim aboneliÄŸini deÄŸiÅŸtirirken bir sorun meydana geldi"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "Sorun ağırlığı güncellenirken bir hata oluştu"
-msgid "An error occurred while adding approver"
-msgstr "Onaylayıcı eklenirken bir hata oluştu"
-
msgid "An error occurred while deleting the approvers group"
msgstr "Onaylayanlar grubu silinirken bir hata oluÅŸtu"
@@ -963,21 +1124,36 @@ msgstr "Özellik vurgusunu gönderirken bir hata oluştu. Sayfayı yenileyin ve
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr "Markdown ön izlemesi yüklenirken hata oluştu"
msgid "An error occurred while fetching pending comments"
msgstr "Bekleyen yorumlar alınırken bir hata oluştu"
+msgid "An error occurred while fetching projects autocomplete."
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "Kenar çubuğu verileri getirilirken bir hata oluştu"
-msgid "An error occurred while fetching stages."
-msgstr "Aşamalar alınırken bir hata oluştu."
-
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr "İş kayıtları alınırken bir hata oluştu."
@@ -993,6 +1169,9 @@ msgstr "İş hattı alınırken bir hata oluştu."
msgid "An error occurred while fetching the releases. Please try again."
msgstr "Sürümler alınırken bir hata oluştu. Lütfen tekrar deneyin."
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr "Projeler yüklenirken bir hata oluştu"
@@ -1026,8 +1205,11 @@ msgstr "Abonelik ayrıntıları yüklenirken bir hata oluştu."
msgid "An error occurred while making the request."
msgstr "Talep edilirken bir hata oluÅŸtu."
-msgid "An error occurred while removing approver"
-msgstr "Onaylayan kaldırılırken bir hata oluştu"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
+msgstr ""
msgid "An error occurred while removing epics."
msgstr "Epikler kaldırılırken bir hata oluştu."
@@ -1080,6 +1262,9 @@ msgstr "İş izi alınırken bir hata oluştu."
msgid "An error occurred whilst fetching the latest pipeline."
msgstr "En son iş hattı alınırken bir hata oluştu."
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr "Tüm dosyalar yüklenirken bir hata oluştu."
@@ -1137,9 +1322,15 @@ msgstr "Herhangi"
msgid "Any Label"
msgstr "Herhangi bir etiket"
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr "Görünüm"
@@ -1147,6 +1338,12 @@ msgid "Appearance was successfully created."
msgstr ""
msgid "Appearance was successfully updated."
+msgstr "Görünüm başarıyla güncellendi."
+
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
msgstr ""
msgid "Application"
@@ -1158,11 +1355,14 @@ msgstr "Uygulama KimliÄŸi"
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
msgid "Application was successfully updated."
-msgstr ""
+msgstr "Uygulama başarıyla güncellendi."
msgid "Application: %{name}"
msgstr "Uygulama: %{name}"
@@ -1176,6 +1376,18 @@ msgstr "Uygulandı"
msgid "Apply suggestion"
msgstr "Öneriyi uygula"
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] "%d üye"
@@ -1187,7 +1399,7 @@ msgstr[0] "Bu üyenin onayları iptal edilmez."
msgstr[1] "Bu üyenin onayları iptal edilmez."
msgid "ApprovalRuleRemove|You are about to remove the %{name} approver group which has %{nMembers}."
-msgstr ""
+msgstr "%{nMembers} bulunan %{name} onaylayan grubunu kaldırmak üzeresiniz."
msgid "ApprovalRuleSummary|%d member"
msgid_plural "ApprovalRuleSummary|%d members"
@@ -1196,11 +1408,11 @@ msgstr[1] "%d üye"
msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{membersCount} tarafından %{count} onay gerekli"
+msgstr[1] "%{membersCount} tarafından %{count} onay gerekli"
msgid "ApprovalRule|All members with Developer role or higher and code owners (if any)"
-msgstr ""
+msgstr "Geliştirici rolüne sahip veya daha yüksek olan tüm üyeler ve kod sahipleri (eğer varsa)"
msgid "ApprovalRule|Members"
msgstr "Kullanıcılar"
@@ -1217,12 +1429,6 @@ msgstr "örneğin. QA, Güvenlik vb."
msgid "Approvals"
msgstr "Onaylar"
-msgid "Approvals required"
-msgstr "Onaylar gerekli"
-
-msgid "Approvers"
-msgstr "Onaylayanlar"
-
msgid "Apr"
msgstr "Nis"
@@ -1253,6 +1459,18 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
+msgid "Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr ""
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to delete this list?"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Bu iş hattı planını silmek istediğinizden emin misiniz?"
@@ -1274,18 +1492,6 @@ msgstr "Genel anahtarı yeniden oluşturmak istediğinizden emin misiniz? Yansı
msgid "Are you sure you want to remove %{group_name}?"
msgstr "%{group_name} grubunu silmek istediÄŸinizden emin misiniz?"
-msgid "Are you sure you want to remove approver %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove approver %{name}?"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}?"
-msgstr ""
-
msgid "Are you sure you want to remove the attachment?"
msgstr ""
@@ -1301,6 +1507,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr "Sağlık kontrolü erişim anahtarını sıfırlamak istediğinizden emin misiniz?"
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1313,12 +1522,36 @@ msgstr ""
msgid "Are you sure?"
msgstr "Emin misiniz?"
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr "Yapı Kimliği"
msgid "Artifacts"
msgstr "Yapılar"
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr "%{user}, %{project_name} projesinin %{branch} dalına yolladı ( %{commit_url} ):"
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr "Artan"
@@ -1331,6 +1564,9 @@ msgstr ""
msgid "Assets"
msgstr "Varlıklar"
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr "#FF0000 gibi özel renk ata"
@@ -1346,6 +1582,12 @@ msgstr "Bu dönüm noktasına bazı sorunları atayın."
msgid "Assign to"
msgstr "Ata"
+msgid "Assign yourself to these issues"
+msgstr "Kendinizi bu soruna atayın"
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr "Atanan sorunlar"
@@ -1376,6 +1618,14 @@ msgstr "Bir dosya ekle"
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Sürükleyip bırakarak bir dosya ekle veya %{upload_link}"
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr "Denetim Etkinlikleri"
@@ -1398,7 +1648,7 @@ msgid "Authentication method"
msgstr "Kimlik doğrulama yöntemi"
msgid "Authentication method updated"
-msgstr ""
+msgstr "Kimlik doğrulama yöntemi güncellendi"
msgid "Authentication via U2F device failed."
msgstr ""
@@ -1449,29 +1699,38 @@ msgid "AutoDevOps|Auto DevOps"
msgstr "Otomatik DevOps"
msgid "AutoDevOps|Auto DevOps documentation"
-msgstr "Otomatik DevOps belgeleleri"
+msgstr "Otomatik DevOps belgeleri"
msgid "AutoDevOps|Enable in settings"
-msgstr "AutoDevOps|Ayarlardan etkinleÅŸtirin"
+msgstr "Ayarlardan etkinleÅŸtirin"
msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
-msgstr ""
+msgstr "Önceden tanımlanmış bir CI / CD yapılandırmasına göre uygulamanızı otomatik olarak oluşturur, test eder ve dağıtır."
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
-msgstr ""
+msgstr "%{link_to_documentation} adresinden daha fazla bilgi edinin"
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr "Otomatik DevOps iş hattı etkinleştirildi ve alternatif bir CI yapılandırma dosyası bulunmazsa kullanılacak. %{more_information_link}"
+
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
msgid "Automatically marked as default internal user"
msgstr "Otomatik olarak varsayılan kullanıcı olarak işaretlendi"
-msgid "Automatically resolve merge request diff discussions when they become outdated"
-msgstr ""
-
msgid "Automatically resolved"
msgstr "Otomatik olarak çözüldü"
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr "Kullanılabilir"
@@ -1509,16 +1768,16 @@ msgid "Badges"
msgstr "Rozetler"
msgid "Badges|A new badge was added."
-msgstr "Badges|Yeni bir rozet eklendi."
+msgstr "Yeni bir rozet eklendi."
msgid "Badges|Add badge"
-msgstr "Badges|Rozet ekle"
+msgstr "Rozet ekle"
msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
-msgstr "Badges|Rozetin eklenmesi başarısız oldu, lütfen girilen bağlantıları kontrol edin ve tekrar deneyin."
+msgstr "Rozetin eklenmesi başarısız oldu, lütfen girilen bağlantıları kontrol edin ve tekrar deneyin."
msgid "Badges|Badge image URL"
-msgstr "Badges|Rozet resim bağlantısı"
+msgstr "Rozet resim bağlantısı"
msgid "Badges|Badge image preview"
msgstr "Rozet resmi önizlemesi"
@@ -1583,6 +1842,30 @@ msgstr "Rozetleriniz"
msgid "Badges|e.g. %{exampleUrl}"
msgstr "örn. %{exampleUrl}"
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr "Bekleyen tüm yorumları sil"
@@ -1590,7 +1873,7 @@ msgid "BatchComments|Discard review?"
msgstr "İnceleme atılsın mı?"
msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
-msgstr ""
+msgstr "Bekleyen tüm yorumlarınızı silecek olan incelemenizi silmek üzeresiniz. Silinen yorumlar %{strong_start}geri%{strong_end} yüklenemez."
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr ""
@@ -1620,16 +1903,16 @@ msgid "BillingPlans|Current plan"
msgstr "Mevcut plan"
msgid "BillingPlans|Customer Support"
-msgstr "Müşteri Desteği"
+msgstr "Müşteri desteği"
msgid "BillingPlans|Downgrade"
-msgstr "Mevcut Planı Düşür"
+msgstr "Mevcut planı düşür"
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
-msgstr "%{faq_link}'i okuyarak her plan hakkında daha fazla bilgi edinin veya GitLab.com Altın paketinin ücretsiz 30 günlük deneme sürümünü başlatın."
+msgstr "%{faq_link} bölümünü okuyarak her plan hakkında daha fazla bilgi edinin veya GitLab.com Altın paketinin ücretsiz 30 günlük deneme sürümünü başlatın."
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
-msgstr "%{faq_link}'i okuyarak her bir ödeme planı hakkında daha fazla bilgi edinin."
+msgstr "%{faq_link} bölümünü okuyarak her bir ödeme planı hakkında daha fazla bilgi edinin."
msgid "BillingPlans|Manage plan"
msgstr "Planı yönet"
@@ -1641,7 +1924,7 @@ msgid "BillingPlans|See all %{plan_name} features"
msgstr "%{plan_name} planı için bütün özellikleri görüntüle"
msgid "BillingPlans|This group uses the plan associated with its parent group."
-msgstr "Bu grup üst grupla ilişkili planı kullanır."
+msgstr "Bu grup, üst grup ile ilişkili planı kullanır."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Bu grubun planını yönetmek için, %{parent_billing_page_link} faturalandırma bölümünü ziyaret edin."
@@ -1650,7 +1933,7 @@ msgid "BillingPlans|Upgrade"
msgstr "Yükselt"
msgid "BillingPlans|You are currently on the %{plan_link} plan."
-msgstr "Şu an %{plan_link} plan kullanıyorsunuz."
+msgstr "Şu an %{plan_link} planını kullanıyorsunuz."
msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
msgstr "GitLab.com deneme sürümünüzün süresi %{expiration_date} tarihinde doldu. %{learn_more_text}"
@@ -1685,12 +1968,31 @@ msgstr "Engelle"
msgid "Blocked"
msgstr "EngellenmiÅŸ"
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Blog"
msgstr "Blog"
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr "Panolar"
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1706,6 +2008,9 @@ msgstr "Dal zaten alınmış"
msgid "Branch name"
msgstr "Dal adı"
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Dallarda ara"
@@ -1803,7 +2108,7 @@ msgid "Branches|Stale branches"
msgstr "EskimiÅŸ dallar"
msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
-msgstr "Dal otomatik olarak güncellenemedi çünkü akışta uyuşmazlıklar var."
+msgstr "Dal, giriş yönü karşılığından ayrıldığı için otomatik olarak güncellenemedi."
msgid "Branches|The default branch cannot be deleted"
msgstr "Öntanımlı dal silinemez"
@@ -1824,7 +2129,7 @@ msgid "Branches|You’re about to permanently delete the protected branch %{bran
msgstr "Korumalı olan %{branch_name} dalını kalıcı olarak silmek üzeresiniz."
msgid "Branches|diverged from upstream"
-msgstr "akıştan sapmış"
+msgstr "akıştan ayrılmış"
msgid "Branches|merged"
msgstr "birleÅŸtirildi"
@@ -1839,7 +2144,7 @@ msgid "Broadcast Message was successfully created."
msgstr ""
msgid "Broadcast Message was successfully updated."
-msgstr ""
+msgstr "Yayın Mesajı başarıyla güncellendi."
msgid "Browse Directory"
msgstr "Dizine Gözat"
@@ -1856,6 +2161,21 @@ msgstr "Dosyalara gözat"
msgid "Built-in"
msgstr "Dahili"
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr "Ä°ÅŸ"
@@ -1874,6 +2194,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr "Öntanımlı olarak GitLab, e-postaları HTML ve düz metin biçimlerinde gönderir, böylece posta istemcileri hangi biçimi kullanacaklarını seçebilir. Yalnızca düz metin biçiminde e-postalar göndermek istiyorsanız bu seçeneği devre dışı bırakın."
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "tarafından"
@@ -1923,13 +2246,13 @@ msgid "CICD|Continuous deployment to production"
msgstr "Üretimde sürekli dağıtım"
msgid "CICD|Continuous deployment to production using timed incremental rollout"
-msgstr ""
+msgstr "Zamanlı artan dağıtım kullanarak üretime sürekli dağıtım"
msgid "CICD|Default to Auto DevOps pipeline"
-msgstr ""
+msgstr "Varsayılan Otomatik DevOps iş hattı"
msgid "CICD|Default to Auto DevOps pipeline for all projects"
-msgstr ""
+msgstr "Tüm projeler için varsayılan Otomatik DevOps iş hattı"
msgid "CICD|Deployment strategy"
msgstr "Dağıtım stratejisi"
@@ -1941,16 +2264,16 @@ msgid "CICD|Learn more about Auto DevOps"
msgstr "Otomatik DevOps hakkında daha fazla bilgi edinin"
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
-msgstr ""
+msgstr "Alternatif CI yapılandırma dosyası bulunmazsa, Otomatik DevOps iş hattı çalışır."
msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
-msgstr ""
+msgstr "Dağıtım stratejinizin doğru çalışabilmesi için bu projeye bir %{kubernetes_cluster_start}Kubernetes küme entegrasyonunu%{kubernetes_cluster_end} bir etki alanıyla birlikte eklemeniz gerekir."
msgid "CICD|group enabled"
-msgstr ""
+msgstr "grup etkinleÅŸtirildi"
msgid "CICD|instance enabled"
-msgstr ""
+msgstr "örnek etkinleştirildi"
msgid "CONTRIBUTING"
msgstr ""
@@ -1964,9 +2287,15 @@ msgstr "Birleştirme isteği için gereken onaylayıcıları ve onayları geçer
msgid "Can't find HEAD commit for this branch"
msgstr "Bu dal için HEAD işlemi bulunamadı"
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1988,9 +2317,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr "Görüntü oluşturulamıyor. En yüksek karakter sayısı (%{charLimit}) aşıldı."
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -2006,9 +2341,15 @@ msgstr "Sertifika (PEM)"
msgid "Change Weight"
msgstr "Ağırlığı değiştir"
-msgid "Change path"
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
msgstr ""
+msgid "Change path"
+msgstr "Yolu deÄŸiÅŸtir"
+
msgid "Change permissions"
msgstr "Ä°zinleri deÄŸiÅŸtir"
@@ -2018,6 +2359,15 @@ msgstr "Åžablonu deÄŸiÅŸtir"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "GitLab UI'nin güncellemeler için ne sıklıkla sorguladığını etkilemek için bu değeri değiştirin."
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "Dalı seç"
@@ -2025,10 +2375,10 @@ msgid "ChangeTypeActionLabel|Revert in branch"
msgstr "Dalı geri al"
msgid "ChangeTypeAction|Cherry-pick"
-msgstr ""
+msgstr "Dikkatli seç"
msgid "ChangeTypeAction|Revert"
-msgstr "Geri döndür"
+msgstr "Geri al"
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -2042,6 +2392,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr "Değişiklikler bastırıldı. Göstermek için tıkla."
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr "Grafikler"
@@ -2069,6 +2425,9 @@ msgstr "Onay durumunu kontrol et"
msgid "Checking branch availability..."
msgstr "Dal uygunluÄŸu kontrol ediliyor..."
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr ""
@@ -2090,6 +2449,9 @@ msgstr "Bir dosya seç"
msgid "Choose a role permission"
msgstr "İzin için bir rol seç"
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2120,8 +2482,8 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
-msgstr ""
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
+msgstr "Birleştirme yönteminizi, seçeneklerinizi, kontrollerinizi seçin ve bir varsayılan birleştirme isteği açıklama şablonu ayarlayın."
msgid "CiStatusLabel|canceled"
msgstr "iptal edildi"
@@ -2130,37 +2492,37 @@ msgid "CiStatusLabel|created"
msgstr "oluÅŸturuldu"
msgid "CiStatusLabel|delayed"
-msgstr ""
+msgstr "gecikmiÅŸ"
msgid "CiStatusLabel|failed"
msgstr "başarısız"
msgid "CiStatusLabel|manual action"
-msgstr ""
+msgstr "el ile eylem"
msgid "CiStatusLabel|passed"
-msgstr ""
+msgstr "geçti"
msgid "CiStatusLabel|passed with warnings"
-msgstr ""
+msgstr "uyarılarla geçti"
msgid "CiStatusLabel|pending"
msgstr "bekliyor"
msgid "CiStatusLabel|preparing"
-msgstr ""
+msgstr "CiStatusLabel|hazırlanıyor"
msgid "CiStatusLabel|skipped"
msgstr "atlandı"
msgid "CiStatusLabel|waiting for delayed job"
-msgstr ""
+msgstr "gecikmeli iÅŸ bekliyor"
msgid "CiStatusLabel|waiting for manual action"
-msgstr ""
+msgstr "elle işlem için bekliyor"
msgid "CiStatusText|blocked"
-msgstr ""
+msgstr "engellendi"
msgid "CiStatusText|canceled"
msgstr "iptal edildi"
@@ -2169,7 +2531,7 @@ msgid "CiStatusText|created"
msgstr "oluÅŸturuldu"
msgid "CiStatusText|delayed"
-msgstr ""
+msgstr "gecikti"
msgid "CiStatusText|failed"
msgstr "başarısız"
@@ -2184,7 +2546,7 @@ msgid "CiStatusText|pending"
msgstr "bekliyor"
msgid "CiStatusText|preparing"
-msgstr ""
+msgstr "CiStatusText|hazırlanıyor"
msgid "CiStatusText|skipped"
msgstr "atlandı"
@@ -2192,16 +2554,34 @@ msgstr "atlandı"
msgid "CiStatus|running"
msgstr "çalışıyor"
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr "Değişken anahtarını girin"
msgid "CiVariables|Input variable value"
msgstr "DeÄŸiÅŸken deÄŸerini girin"
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr "Değişken satırı kaldırın"
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2217,7 +2597,7 @@ msgid "CiVariable|Error occurred while saving variables"
msgstr "DeÄŸiÅŸkenler kaydedilirken hata oluÅŸtu"
msgid "CiVariable|Masked"
-msgstr ""
+msgstr "Maskeli"
msgid "CiVariable|New environment"
msgstr "Yeni ortam"
@@ -2238,7 +2618,7 @@ msgid "CiVariable|Validation failed"
msgstr "Doğrulama başarısız"
msgid "Classification Label (optional)"
-msgstr ""
+msgstr "Sınıflandırma Etiketi (isteğe bağlı)"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "kullanılamıyor: %{reason}"
@@ -2255,9 +2635,18 @@ msgstr "Aramayı temizle"
msgid "Clear search input"
msgstr "Arama giriÅŸini temizle"
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -2312,6 +2701,9 @@ msgstr ""
msgid "Close milestone"
msgstr ""
+msgid "Close sidebar"
+msgstr "Kenar çubuğunu kapat"
+
msgid "Closed"
msgstr "Kapalı"
@@ -2319,64 +2711,85 @@ msgid "Closed issues"
msgstr "Kapalı sorunlar"
msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
-msgstr ""
+msgstr "%{custom_domain_start}Daha fazla bilgi%{custom_domain_end}."
msgid "ClusterIntegration| can be used instead of a custom domain."
-msgstr ""
+msgstr "özel bir etki alanı yerine kullanılabilir."
msgid "ClusterIntegration| is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
+msgstr ", bu küme için varsayılan ortam kapsamıdır. Bu tüm işlerin, ortamları ne olursa olsun, bu kümeyi kullanacakları anlamına gelir. %{environment_scope_start}Daha fazla bilgi%{environment_scope_end}"
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr "%{appList} Kubernetes kümenize başarıyla yüklendi"
+
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
msgstr "API adresi"
msgid "ClusterIntegration|API URL should be a valid http/https url."
-msgstr ""
+msgstr "API URL'leri geçerli bir http/https url'si olmalıdır."
msgid "ClusterIntegration|Add Kubernetes cluster"
-msgstr ""
+msgstr "Kubernetes kümesi ekle"
msgid "ClusterIntegration|Add a Kubernetes cluster integration"
-msgstr ""
+msgstr "Bir Kubernetes küme entegrasyonu ekleyin"
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr "Grubunuza bir Kubernetes kümesi eklemek, tüm projeleriniz arasında kümeyi otomatik olarak paylaşır. Uygulamaları gözden geçirmeyi kullanın, uygulamalarınızı yayınlayın ve aynı kümeyi kullanan tüm projeler için iş hattınızı kolayca çalıştırın."
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr "Grubunuza bir entegrasyon eklemek, kümeyi tüm projeleriniz arasında paylaşacaktır."
+
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
msgstr ""
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgstr "Bu Kubernetes kümesinin entegrasyonu hakkında gelişmiş seçenekler"
+
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Alternatively"
msgstr "Alternatifler"
msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
-msgstr ""
+msgstr "Google Cloud API ile iletişim kurulurken bir hata oluştu. Lütfen daha sonra tekrar deneyin."
msgid "ClusterIntegration|An error occurred while trying to fetch project zones: %{error}"
msgstr "Proje alanlarını almaya çalışırken hata oluştu: %{error}"
msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
-msgstr ""
+msgstr "Projelerinizi almaya çalışırken bir hata oluştu: %{error}"
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
+msgstr "Bölge makine türlerini getirmeye çalışırken bir hata oluştu: %{error}"
+
+msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
msgid "ClusterIntegration|Applications"
msgstr "Uygulamalar"
msgid "ClusterIntegration|Apply for credit"
-msgstr ""
+msgstr "Krediye baÅŸvur"
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
-msgstr ""
+msgstr "Kubernetes küme entegrasyonunu kaldırmak istediğinizden emin misiniz? Bu sizin güncel Kubernetes kümenizi silmez."
msgid "ClusterIntegration|Base domain"
msgstr "Temel etki alanı"
@@ -2385,7 +2798,7 @@ msgid "ClusterIntegration|CA Certificate"
msgstr "CA Sertifikası"
msgid "ClusterIntegration|Cert-Manager"
-msgstr "Sertifika-Yöneticisi"
+msgstr "Sertifika Yöneticisi"
msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
msgstr ""
@@ -2397,13 +2810,13 @@ msgid "ClusterIntegration|Choose which applications to install on your Kubernete
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
-msgstr ""
+msgstr "Ortamlarınızdan hangisinin bu kümeyi kullanacağını seçin."
msgid "ClusterIntegration|Cluster health"
-msgstr ""
+msgstr "Küme sağlığı"
msgid "ClusterIntegration|Cluster name is required."
-msgstr ""
+msgstr "Küme ismi gerekli."
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
msgstr ""
@@ -2415,19 +2828,19 @@ msgid "ClusterIntegration|Copy CA Certificate"
msgstr "CA Sertifikasını Kopyala"
msgid "ClusterIntegration|Copy Ingress Endpoint to clipboard"
-msgstr ""
+msgstr "Giriş - bitiş noktasını panoya kopyala"
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
-msgstr "Jupyter Ana Bilgisayar Adını panoya kopyala"
+msgstr "Jupyter ana bilgisayar adını panoya kopyala"
msgid "ClusterIntegration|Copy Knative Endpoint to clipboard"
-msgstr ""
+msgstr "Knative bitiş noktasını panoya kopyala"
msgid "ClusterIntegration|Copy Kubernetes cluster name"
-msgstr ""
+msgstr "Kubernetes küme adını kopyala"
msgid "ClusterIntegration|Copy Service Token"
-msgstr ""
+msgstr "Hizmet erişim anahtarını kopyala"
msgid "ClusterIntegration|Create Kubernetes cluster"
msgstr "Kubernetes kümesi oluştur"
@@ -2436,13 +2849,13 @@ msgid "ClusterIntegration|Did you know?"
msgstr "Biliyor muydunuz?"
msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
-msgstr ""
+msgstr "GitLab'ın Kubernetes kümeniz ile olan bağlantısını etkinleştirin veya devre dışı bırakın."
msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
-msgstr ""
+msgstr "Rol tabanlı erişim kontrolü (RBAC) kullanıyorsanız bu ayarı etkinleştirin."
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
-msgstr ""
+msgstr "Kubernetes kümeniz için ayrıntıları girin"
msgid "ClusterIntegration|Environment scope"
msgstr "Ortam kapsamı"
@@ -2451,13 +2864,13 @@ msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives
msgstr ""
msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
-msgstr ""
+msgstr "Google Kubernetes Motor Kümesi yapılandırılamadı: %{message}"
msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
-msgstr ""
+msgstr "Google Bulut Platform isteği başarısız oldu: %{message}"
msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
-msgstr ""
+msgstr "Kubeclient çalıştırılamadı: %{message}"
msgid "ClusterIntegration|Fetching machine types"
msgstr "Makine türleri getiriliyor"
@@ -2475,6 +2888,9 @@ msgid "ClusterIntegration|GitLab Runner"
msgstr "GitLab Çalıştırıcı"
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
+msgstr "GitLab Çalıştırıcı; depoya bağlanır ve CI/CD işlerini yürütür, sonuçları geri iter ve uygulamaları üretime dağıtır."
+
+msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
msgid "ClusterIntegration|Google Cloud Platform project"
@@ -2493,7 +2909,7 @@ msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
+msgstr "Helm, Kubernetes uygulamalarını kurmayı ve yönetmeyi kolaylaştırır. Tiller, Kubernetes kümelerinizin içinde çalışır ve grafiklerinizin sürümlerini yönetir."
msgid "ClusterIntegration|Hide"
msgstr "Gizle"
@@ -2505,27 +2921,18 @@ msgid "ClusterIntegration|In order to view the health of your cluster, you must
msgstr "Kümenizin sağlığını görmek için önce aşağıdan Prometheus'u yüklemelisiniz."
msgid "ClusterIntegration|Ingress"
-msgstr ""
+msgstr "Ingress"
msgid "ClusterIntegration|Ingress Endpoint"
-msgstr ""
+msgstr "Ingress bitiş noktası"
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
-msgstr ""
-
-msgid "ClusterIntegration|Install"
-msgstr "Yükle"
-
-msgid "ClusterIntegration|Installed"
-msgstr "Yüklendi"
-
-msgid "ClusterIntegration|Installing"
-msgstr "Yükleniyor"
+msgstr "Ingress; istekleri, istek ana bilgisayarına veya yoluna dayanarak hizmetlere yönlendirerek bir dizi hizmeti tek bir giriş noktasına merkezileştirme yolu sunar."
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
-msgstr ""
+msgstr "Ingress'ın yüklenmesi ek ücrete neden olabilir. %{pricingLink} hakkında daha fazla bilgi edinin."
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2535,13 +2942,13 @@ msgid "ClusterIntegration|Integration status"
msgstr "Bütünleşme durumu"
msgid "ClusterIntegration|Issuer Email"
-msgstr ""
+msgstr "Yayınlayıcı e-postası"
msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
-msgstr ""
+msgstr "Yayınlayıcı, bir sertifika yetkilisini temsil eder. Yayınlayıcınız için bir e-posta adresi sağlamalısınız. "
msgid "ClusterIntegration|Jupyter Hostname"
-msgstr "Jupyter Ana Bilgisayar Adı"
+msgstr "Jupyter ana bilgisayar adı"
msgid "ClusterIntegration|JupyterHub"
msgstr "JupyterHub"
@@ -2550,12 +2957,15 @@ msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and pro
msgstr ""
msgid "ClusterIntegration|Knative"
-msgstr ""
+msgstr "Knative"
msgid "ClusterIntegration|Knative Domain Name:"
-msgstr ""
+msgstr "Knative etki alanı adı:"
msgid "ClusterIntegration|Knative Endpoint:"
+msgstr "Knative bitiş noktası:"
+
+msgid "ClusterIntegration|Knative domain name was updated successfully."
msgstr ""
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
@@ -2565,22 +2975,22 @@ msgid "ClusterIntegration|Kubernetes cluster"
msgstr "Kubernetes kümesi"
msgid "ClusterIntegration|Kubernetes cluster details"
-msgstr "Kubernetes kümesi detayları"
+msgstr "Kubernetes kümesi ayrıntıları"
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
-msgstr "Kubernetes kümesi, Google Kubernetes Motoru'nda oluşturuluyor..."
+msgstr "Kubernetes kümesi, Google Kubernetes Motoru içinde oluşturuluyor..."
msgid "ClusterIntegration|Kubernetes cluster name"
msgstr "Kubernetes kümesi adı"
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
-msgstr ""
+msgstr "Kubernetes kümesi, Google Kubernetes Motoru içinde başarıyla oluşturuldu. Kubernetes kümesinin ayrıntılarını görmek için sayfayı yenileyin"
msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr ""
+msgstr "Kubernetes kümeleri; uygulamaları gözden geçirme özelliğini kullanmanıza, uygulamalarınızı yayınlamanıza, iş hattınızı çalıştırmanıza ve çok daha fazlasına kolay bir şekilde izin verir."
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
-msgstr ""
+msgstr "Kubernet kümeleri, uygulamaları dağıtmak ve bu proje için Gözden Geçirme Uygulamaları sağlamak için kullanılabilir"
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
@@ -2594,6 +3004,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2603,23 +3016,20 @@ msgstr "Makine türü"
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr "Yönet"
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
msgid "ClusterIntegration|No machine types matched your search"
-msgstr ""
+msgstr "Aramanız hiçbir makine türü ile eşleşmiyor"
msgid "ClusterIntegration|No projects found"
msgstr "Proje bulunamadı"
msgid "ClusterIntegration|No projects matched your search"
-msgstr ""
+msgstr "Aramanız ile eşleşen bir proje yok"
msgid "ClusterIntegration|No zones matched your search"
-msgstr ""
+msgstr "Aramanızla hiçbir alan eşleşmedi"
msgid "ClusterIntegration|Number of nodes"
msgstr ""
@@ -2669,14 +3079,14 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
msgstr ""
msgid "ClusterIntegration|Search machine types"
-msgstr ""
+msgstr "Makine türlerini ara"
msgid "ClusterIntegration|Search projects"
msgstr "Projeleri ara"
@@ -2723,40 +3133,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "%{title} yüklenirken bir sorun oluştu"
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2768,6 +3190,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2777,6 +3202,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr "Alan"
@@ -2828,9 +3256,15 @@ msgstr "Onaylananları daralt"
msgid "Collapse sidebar"
msgstr "Kenar çubuğunu daralt"
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr "Komut satırı talimatları"
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr "Yorum"
@@ -2849,6 +3283,9 @@ msgstr "Yorumla ve tartışmayı devam ettir"
msgid "Comment form position"
msgstr "Yorum formu konumu"
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr "Yorumlar"
@@ -2867,7 +3304,7 @@ msgid "Commit deleted"
msgstr ""
msgid "Commit duration in minutes for last 30 commits"
-msgstr ""
+msgstr "Son 30 işlem için dakika cinsinden işlem süresi"
msgid "Commit message"
msgstr "İşlem mesajı"
@@ -2903,7 +3340,7 @@ msgid "Commits per weekday"
msgstr ""
msgid "Commits|An error occurred while fetching merge requests data."
-msgstr ""
+msgstr "BirleÅŸtirme istek verileri getirilirken bir hata oluÅŸtu."
msgid "Commits|Commit: %{commitText}"
msgstr ""
@@ -2968,6 +3405,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2995,9 +3435,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr "BaÄŸlan"
@@ -3010,9 +3456,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr "Bağlanıyor…"
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3026,22 +3478,22 @@ msgid "Contact your Administrator to upgrade your license."
msgstr ""
msgid "Container Registry"
-msgstr ""
+msgstr "Kapsayıcı Kaydı"
msgid "Container registry images"
-msgstr ""
+msgstr "Kapsayıcı kaydı resimleri"
msgid "ContainerRegistry|Created"
-msgstr "OluÅŸturuldu"
+msgstr "OluÅŸturuldu:"
msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
msgstr ""
msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
-msgstr ""
+msgstr "GitLab, 3 seviyeye kadar görüntü isimlerini destekler. Aşağıdaki görsel örnekleri projeniz için geçerlidir:"
msgid "ContainerRegistry|How to use the Container Registry"
-msgstr ""
+msgstr "Kapsayıcı Kaydı nasıl kullanılır?"
msgid "ContainerRegistry|Learn more about"
msgstr "Hakkında daha fazlasını öğren"
@@ -3050,7 +3502,7 @@ msgid "ContainerRegistry|No tags in Container Registry for this container image.
msgstr ""
msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
-msgstr ""
+msgstr "Giriş yaptıktan sonra, genel %{build} ve %{push} komutlarını kullanarak bir kapsayıcı resim oluşturmakta ve yüklemekte özgürsünüz"
msgid "ContainerRegistry|Remove repository"
msgstr "Depoyu kaldır"
@@ -3071,9 +3523,12 @@ msgid "ContainerRegistry|Use different image names"
msgstr "Farklı resim adları kullan"
msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
-msgstr ""
+msgstr "GitLab'a entegre Docker Kapsayıcı Kaydı ile, her projenin Docker resimlerini depolamak için kendi alanı olabilir."
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
+msgstr "Kayıt defteri resimlerine salt okunur erişim için bir %{deploy_token} de kullanabilirsiniz."
+
+msgid "Contains %{count} blobs of images (%{size})"
msgstr ""
msgid "Contents of .gitlab-ci.yml"
@@ -3092,7 +3547,7 @@ msgid "Contribute to GitLab"
msgstr "GitLab'a katkıda bulunun"
msgid "Contribution"
-msgstr ""
+msgstr "Katkı"
msgid "Contribution Analytics"
msgstr "Katkı Analizi"
@@ -3101,16 +3556,16 @@ msgid "Contribution Charts"
msgstr "Katkı Grafikleri"
msgid "Contributions for <strong>%{calendar_date}</strong>"
-msgstr ""
+msgstr "<strong>%{calendar_date}</strong> için katkılar"
msgid "Contributions per group member"
-msgstr ""
+msgstr "Grup üyesi başına katkılar"
msgid "Contributors"
msgstr "Katkıda Bulunanlar"
msgid "ContributorsPage|%{startDate} – %{endDate}"
-msgstr "ContributorsPage|%{startDate} – %{endDate}"
+msgstr "%{startDate} – %{endDate}"
msgid "ContributorsPage|Building repository graph."
msgstr ""
@@ -3119,7 +3574,10 @@ msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limi
msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
-msgstr "ContributorsPage|Lütfen bekleyin, hazır olduğunda bu sayfa otomatik olarak yenilenir."
+msgstr "Lütfen bekleyin, hazır olduğunda bu sayfa otomatik olarak yenilenir."
+
+msgid "Control emails linked to your account"
+msgstr ""
msgid "Control the display of third party offers."
msgstr ""
@@ -3130,6 +3588,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3148,9 +3609,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr "SSH ortak anahtarını kopyala"
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr "URL'yi panoya kopyala"
@@ -3166,6 +3624,12 @@ msgstr "İşlem SHA'yı panoya kopyala"
msgid "Copy file path to clipboard"
msgstr "Dosya yolunu panoya kopyala"
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr "Bağlantıyı kopyala"
@@ -3175,6 +3639,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
@@ -3184,9 +3651,15 @@ msgstr "Erişim anahtarını panoya kopyala"
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3220,9 +3693,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr "Yeni bir dal oluÅŸtur"
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr "Yeni bir sorun oluÅŸtur"
@@ -3295,6 +3777,12 @@ msgstr "Proje etiketi oluÅŸtur"
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr "Etiket"
@@ -3310,12 +3798,27 @@ msgstr "OluÅŸturma tarihi"
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr "OluÅŸturulma tarihi"
msgid "Created on:"
msgstr "OluÅŸturulma tarihi:"
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3334,6 +3837,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr "Profil"
@@ -3350,7 +3856,7 @@ msgid "Custom notification events"
msgstr "Özel bildirim etkinlikleri"
msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
-msgstr ""
+msgstr "Özel bildirim seviyeleri, katılımcı seviyeleriyle aynıdır. Özel bildirim seviyeleri ile belirli etkinlikler için de bildirim alacaksınız. Daha fazla bilgi için %{notification_link} adresini inceleyin."
msgid "Custom project templates"
msgstr ""
@@ -3392,13 +3898,13 @@ msgid "CycleAnalyticsStage|Production"
msgstr "Yapım"
msgid "CycleAnalyticsStage|Review"
-msgstr "CycleAnalyticsStage|Ä°nceleme"
+msgstr "Ä°ncele"
msgid "CycleAnalyticsStage|Staging"
msgstr "Hazırlama"
msgid "CycleAnalyticsStage|Test"
-msgstr "CycleAnalyticsStage|Test"
+msgstr "Test"
msgid "DNS"
msgstr "DNS"
@@ -3410,9 +3916,21 @@ msgid "DashboardProjects|All"
msgstr "Tümü"
msgid "DashboardProjects|Personal"
-msgstr "DashboardProjects|KiÅŸisel"
+msgstr "KiÅŸisel"
+
+msgid "DashboardProjects|Trending"
+msgstr ""
msgid "Dashboards"
+msgstr "Gösterge Panoları"
+
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Data is still calculating..."
@@ -3421,6 +3939,18 @@ msgstr "Veri hala hesaplanıyor..."
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -3457,6 +3987,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3508,6 +4041,21 @@ msgstr "Kaynak dalı sil"
msgid "Delete this attachment"
msgstr "Bu eki sil"
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr "Proje kapsayıcı kaydından bazı etiketler kaldırılamadı. Lütfen tekrar deneyin veya yöneticiniz ile temasa geçin."
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3529,6 +4077,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
@@ -3538,7 +4134,7 @@ msgid "Deploy Keys"
msgstr ""
msgid "Deploy key was successfully updated."
-msgstr ""
+msgstr "Dağıtım anahtarı başarıyla güncellendi."
msgid "DeployKeys|+%{count} others"
msgstr "+%{count} diÄŸer"
@@ -3592,31 +4188,31 @@ msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr ""
msgid "DeployTokens|Add a deploy token"
-msgstr ""
+msgstr "Dağıtıcı belirteci ekleyin"
msgid "DeployTokens|Allows read-only access to the registry images"
-msgstr ""
+msgstr "Kayıt defteri resimlerine salt okunur erişim sağlar"
msgid "DeployTokens|Allows read-only access to the repository"
-msgstr ""
+msgstr "Kayıt defteri görüntülerine salt okunur erişimi sağlar"
msgid "DeployTokens|Copy deploy token to clipboard"
msgstr ""
msgid "DeployTokens|Copy username to clipboard"
-msgstr ""
+msgstr "Kullanıcı adını panoya kopyala"
msgid "DeployTokens|Create deploy token"
-msgstr ""
+msgstr "Dağıtıcı belirteci oluştur"
msgid "DeployTokens|Created"
msgstr "OluÅŸturuldu"
msgid "DeployTokens|Deploy Tokens"
-msgstr ""
+msgstr "Dağıtıcı Belirteci"
msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
-msgstr ""
+msgstr "Dağıtıcı belirteçleri, depo ve kayıt defteri resimlerinize salt okunur erişime izin verir."
msgid "DeployTokens|Expires"
msgstr ""
@@ -3637,7 +4233,7 @@ msgid "DeployTokens|Scopes"
msgstr ""
msgid "DeployTokens|This action cannot be undone."
-msgstr "DeployTokens|Bu işlem geri alınamaz."
+msgstr "Bu işlem geri alınamaz."
msgid "DeployTokens|This project has no active Deploy Tokens."
msgstr ""
@@ -3649,7 +4245,7 @@ msgid "DeployTokens|Use this username as a login."
msgstr ""
msgid "DeployTokens|Username"
-msgstr ""
+msgstr "Kullanıcı adı"
msgid "DeployTokens|You are about to revoke"
msgstr ""
@@ -3670,7 +4266,7 @@ msgid "Deploying to"
msgstr ""
msgid "Deprioritize label"
-msgstr ""
+msgstr "Etiket önceliğini azalt"
msgid "Descending"
msgstr ""
@@ -3705,6 +4301,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3759,7 +4358,13 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
+msgstr "Devre dışı"
+
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
msgstr ""
msgid "Discard"
@@ -3783,11 +4388,17 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr "Discord Bildirimleri"
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr "Discord'da olay bildirimlerini alın"
+
msgid "Discover GitLab Geo"
msgstr ""
msgid "Discover projects, groups and snippets. Share your projects with others"
-msgstr ""
+msgstr "Projeleri, grupları ve parçacıkları keşfedin. Projelerinizi başkalarıyla paylaşın"
msgid "Discuss a specific suggestion or question"
msgstr ""
@@ -3813,18 +4424,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr "Deneme promosyonunu reddet"
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr "Bir daha gösterme"
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr "Tamamlandı"
@@ -3837,29 +4472,23 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
+msgid "Download codes"
msgstr ""
-msgid "Download tar"
-msgstr ""
-
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
-msgstr "E-posta Yamaları"
+msgstr "E-posta yamaları"
msgid "DownloadCommit|Plain Diff"
msgstr ""
@@ -3897,6 +4526,9 @@ msgstr "Etiketi Düzenle"
msgid "Edit Milestone"
msgstr ""
+msgid "Edit Password"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -3933,9 +4565,15 @@ msgstr "Genel dağıtım anahtarını düzenle"
msgid "Elasticsearch"
msgstr "Esnek arama"
-msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr "Esnek arama bütünleşmesi. Esnek arama AWS IAM."
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -3946,11 +4584,14 @@ msgid "Email"
msgstr "E-posta"
msgid "Email address"
-msgstr ""
+msgstr "E-posta adresi"
msgid "Email patch"
msgstr "E-posta yaması"
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3975,9 +4616,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr "E-postalar"
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -4002,6 +4673,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -4038,9 +4712,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr "İki aşamalı doğrulamayı etkinleştir"
@@ -4071,12 +4742,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
-msgid "Enter at least three characters to search"
+msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enter at least three characters to search"
+msgstr "Aramak için en az üç karakter girin"
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr ""
@@ -4084,12 +4761,15 @@ msgid "Enter the issue title"
msgstr "Sorun başlığını girin"
msgid "Enter the merge request description"
-msgstr ""
+msgstr "Birleştirme isteği açıklamasını girin"
msgid "Enter the merge request title"
msgstr "Birleştirme isteğinin başlığını girin"
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4101,9 +4781,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "Ortamlar getirilirken bir hata oluÅŸtu."
@@ -4219,7 +4923,7 @@ msgid "Environments|This action will run the job defined by staging for commit %
msgstr ""
msgid "Environments|Updated"
-msgstr "Environments|Güncellendi:"
+msgstr "Güncellendi"
msgid "Environments|You don't have any environments right now"
msgstr ""
@@ -4239,18 +4943,51 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
@@ -4282,14 +5019,20 @@ msgid "Error fetching contributors data."
msgstr "Katkıda bulunanlar verileri alınırken hata oluştu."
msgid "Error fetching labels."
-msgstr ""
+msgstr "Etiketler getirilirken hata oluÅŸtu."
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4299,6 +5042,12 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr ""
@@ -4308,6 +5057,9 @@ msgstr "Markdown önizlemesi yüklenirken hata oluştu"
msgid "Error loading merge requests."
msgstr "Birleştirme isteği yüklenirken hata oluştu."
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4317,6 +5069,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr "Bildirim aboneliÄŸini deÄŸiÅŸtirirken bir sorun meydana geldi"
@@ -4336,7 +5094,7 @@ msgid "Error rendering markdown preview"
msgstr "Marka oluşturma önizlemesi yapılırken hata oluştu"
msgid "Error saving label update."
-msgstr ""
+msgstr "Etiket güncellenirken sorun oluştu."
msgid "Error updating %{issuableType}"
msgstr ""
@@ -4345,14 +5103,20 @@ msgid "Error updating status for all todos."
msgstr "Bütün yapılacaklar için durum güncellenirken hata oluştu."
msgid "Error updating todo status."
-msgstr ""
+msgstr "Yapılacak durumu güncellenirken hata oluştu."
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr "Birleştirme isteğini yüklerken hata oluştu. Lütfen tekrar deneyin."
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4396,22 +5160,22 @@ msgid "Estimated"
msgstr ""
msgid "EventFilterBy|Filter by all"
-msgstr ""
+msgstr "Tümünü süz"
msgid "EventFilterBy|Filter by comments"
-msgstr ""
+msgstr "Yorumlara göre süz"
msgid "EventFilterBy|Filter by issue events"
-msgstr ""
+msgstr "Sorun olaylarına göre süz"
msgid "EventFilterBy|Filter by merge events"
-msgstr ""
+msgstr "Birleştirme olaylarına göre süz"
msgid "EventFilterBy|Filter by push events"
-msgstr ""
+msgstr "Yollama olayına göre süz"
msgid "EventFilterBy|Filter by team"
-msgstr ""
+msgstr "Ekibe göre süz"
msgid "Events"
msgstr "Etkinlikler"
@@ -4449,6 +5213,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4492,19 +5259,19 @@ msgid "Explore Groups"
msgstr "Grupları Keşfet"
msgid "Explore groups"
-msgstr "Grupları keşfet"
+msgstr "Grupları keşfedin"
msgid "Explore projects"
-msgstr "Projeleri keÅŸfet"
+msgstr "Projeleri keÅŸfedin"
msgid "Explore public groups"
-msgstr "Genel grupları keşfet"
+msgstr "Genel grupları keşfedin"
msgid "Export as CSV"
msgstr "CSV olarak dışa aktar"
msgid "Export issues"
-msgstr ""
+msgstr "Dışa aktarma sorunları"
msgid "Export project"
msgstr ""
@@ -4531,11 +5298,32 @@ msgid "External authorization request timeout"
msgstr ""
msgid "ExternalAuthorizationService|Classification label"
-msgstr ""
+msgstr "Sınıflandırma etiketi"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4545,27 +5333,60 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr "Sahibi değiştirme başarısız"
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -4584,6 +5405,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4596,16 +5423,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failure"
+msgid "Failed to update."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4620,6 +5459,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4683,7 +5528,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4695,9 +5540,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4711,7 +5553,7 @@ msgid "FeatureFlags|Protected"
msgstr ""
msgid "FeatureFlags|Status"
-msgstr ""
+msgstr "Durum"
msgid "FeatureFlags|Target environments"
msgstr ""
@@ -4778,6 +5620,12 @@ msgstr ""
msgid "Files"
msgstr "Dosyalar"
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4785,25 +5633,25 @@ msgid "Filter"
msgstr "Süzgeç"
msgid "Filter by %{issuable_type} that are currently closed."
-msgstr ""
+msgstr "Kapalı olan %{issuable_type} türüne göre süz."
msgid "Filter by %{issuable_type} that are currently opened."
-msgstr ""
+msgstr "Açık olan %{issuable_type} türüne göre süz."
msgid "Filter by commit message"
-msgstr "İşlem mesajına göre süzgeçle"
+msgstr "İşlem mesajına göre süz"
msgid "Filter by milestone name"
-msgstr ""
+msgstr "Dönüm noktası adına göre süz"
msgid "Filter by two-factor authentication"
-msgstr ""
+msgstr "İki adımlı kimlik doğrulamasına göre süz"
msgid "Filter results by group"
-msgstr ""
+msgstr "Gruba göre sonuçları süz"
msgid "Filter results by project"
-msgstr ""
+msgstr "Projeye göre sonuçları süz"
msgid "Filter..."
msgstr "Süzgeç..."
@@ -4826,6 +5674,9 @@ msgstr ""
msgid "Fingerprint"
msgstr "Parmak izi"
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4835,6 +5686,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4842,10 +5696,10 @@ msgid "First day of the week"
msgstr ""
msgid "FirstPushedBy|First"
-msgstr ""
+msgstr "Ä°lk"
msgid "FirstPushedBy|pushed by"
-msgstr ""
+msgstr "Tarafından yollandı:"
msgid "Fixed date"
msgstr "Düzeltilme zamanı"
@@ -4859,6 +5713,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4904,6 +5764,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -4913,6 +5782,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr "Çatallar"
@@ -4931,6 +5803,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr "GitLab.com Gold Ãœcretsiz Deneme"
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4961,12 +5836,18 @@ msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr "GPG Anahtarları"
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -4980,7 +5861,7 @@ msgid "General pipelines"
msgstr ""
msgid "Generate a default set of labels"
-msgstr ""
+msgstr "Varsayılan etiket kümesi oluştur"
msgid "Generate key"
msgstr ""
@@ -5007,7 +5888,7 @@ msgid "GeoNodes|Checksummed"
msgstr "Sağlama yapıldı"
msgid "GeoNodes|Data is out of date from %{timeago}"
-msgstr "%{timeago} tarih verileri güncel değil"
+msgstr "Veriler, %{timeago} itibaren güncel değil"
msgid "GeoNodes|Data replication lag"
msgstr "Veri çoğaltma gecikmesi"
@@ -5214,7 +6095,7 @@ msgid "Geo|File sync capacity"
msgstr ""
msgid "Geo|Geo Status"
-msgstr ""
+msgstr "CoÄŸrafi Durum"
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -5307,7 +6188,7 @@ msgid "Geo|Shards to synchronize"
msgstr ""
msgid "Geo|Status"
-msgstr "Geo|Durum"
+msgstr "Durum"
msgid "Geo|Sync"
msgstr ""
@@ -5324,6 +6205,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr "Düğüm şu anda %{minutes_behind} birincil düğümün gerisinde."
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5367,7 +6254,7 @@ msgid "Geo|secondary"
msgstr ""
msgid "Get a free instance review"
-msgstr ""
+msgstr "Ücretsiz bir örnek incelemesi alın"
msgid "Get started with error tracking"
msgstr ""
@@ -5381,6 +6268,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5390,6 +6280,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5460,6 +6353,9 @@ msgid "Gitea Import"
msgstr ""
msgid "Given access %{time_ago}"
+msgstr "%{time_ago} eriÅŸim verildi"
+
+msgid "Global notification settings"
msgstr ""
msgid "Go Back"
@@ -5480,9 +6376,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5517,7 +6422,7 @@ msgid "Group CI/CD settings"
msgstr ""
msgid "Group Git LFS status:"
-msgstr ""
+msgstr "Grup Git LFS durumu:"
msgid "Group ID"
msgstr ""
@@ -5558,8 +6463,11 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr "Grup iş hattı kayıtları başarıyla sıfırlandı."
+
msgid "Group was successfully updated."
-msgstr ""
+msgstr "Grup başarıyla güncellendi."
msgid "Group:"
msgstr "Grup:"
@@ -5567,6 +6475,9 @@ msgstr "Grup:"
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5574,7 +6485,7 @@ msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
msgid "GroupRoadmap|Sorry, no epics matched your search"
-msgstr ""
+msgstr "Üzgünüz, aramanızla eşleşen bir epik yok"
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
@@ -5586,7 +6497,7 @@ msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
-msgstr ""
+msgstr "Aramanızı genişletmek için süzgeçleri değiştirin veya kaldırın; %{startDate} - %{endDate}."
msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
@@ -5594,13 +6505,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5612,9 +6526,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5622,7 +6533,7 @@ msgid "GroupSAML|Make sure you save this token — you won't be able to access i
msgstr ""
msgid "GroupSAML|Manage your group’s membership while adding another level of security with SAML."
-msgstr ""
+msgstr "SAML ile başka güvenlik seviyesi eklerken grubunuzun üyeliğini yönetin."
msgid "GroupSAML|Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
msgstr ""
@@ -5645,14 +6556,23 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
-msgstr ""
+msgstr "Grup için Otomatik DevOps iş hattı güncellendi"
msgid "GroupSettings|Auto DevOps will automatically build, test and deploy your application based on a predefined Continuous Integration and Delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end}"
msgstr ""
@@ -5670,7 +6590,7 @@ msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within thi
msgstr ""
msgid "GroupSettings|Learn more about badges."
-msgstr ""
+msgstr "Rozetler hakkında daha fazla bilgi edin."
msgid "GroupSettings|Learn more about group-level project templates."
msgstr ""
@@ -5711,6 +6631,9 @@ msgstr ""
msgid "Groups"
msgstr "Gruplar"
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -5727,13 +6650,13 @@ msgid "GroupsDropdown|Loading groups"
msgstr ""
msgid "GroupsDropdown|Search your groups"
-msgstr ""
+msgstr "Gruplarınızı arayın"
msgid "GroupsDropdown|Something went wrong on our end."
msgstr ""
msgid "GroupsDropdown|Sorry, no groups matched your search"
-msgstr ""
+msgstr "Üzgünüz, aramanızla eşleşen hiçbir grup bulunamadı"
msgid "GroupsDropdown|This feature requires browser localStorage support"
msgstr ""
@@ -5742,10 +6665,10 @@ msgid "GroupsEmptyState|A group is a collection of several projects."
msgstr ""
msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
-msgstr ""
+msgstr "Eğer projelerinizi bir grup altında düzenlerseniz, bir klasör gibi çalışır."
msgid "GroupsEmptyState|No groups found"
-msgstr "GroupsEmptyState|Grup bulunamadı"
+msgstr "Grup bulunamadı"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
@@ -5772,12 +6695,15 @@ msgid "GroupsTree|Loading groups"
msgstr ""
msgid "GroupsTree|No groups matched your search"
-msgstr ""
+msgstr "Aramanızla eşleşen grup yok"
msgid "GroupsTree|No groups or projects matched your search"
-msgstr ""
+msgstr "Aramanız ile eşleşen grup veya proje yok"
msgid "GroupsTree|Search by name"
+msgstr "İsme göre arayın"
+
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
msgstr ""
msgid "Have your users email"
@@ -5807,6 +6733,9 @@ msgstr ""
msgid "HealthCheck|Unhealthy"
msgstr ""
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr "Yardım"
@@ -5816,12 +6745,15 @@ msgstr "Yardım sayfası"
msgid "Help page text and support page url."
msgstr "Yardım sayfası metni ve destek sayfası bağlantısı."
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr "Dosya tarayıcısını gizle"
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5831,6 +6763,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5845,11 +6780,17 @@ msgstr ""
msgid "History"
msgstr ""
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
msgid "Hook was successfully updated."
-msgstr ""
+msgstr "Kanca başarıyla güncellendi."
msgid "Housekeeping"
msgstr ""
@@ -5860,6 +6801,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5869,6 +6816,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5888,7 +6841,7 @@ msgid "IDE|Edit"
msgstr ""
msgid "IDE|Get started with Live Preview"
-msgstr "Canlı Önizlemeye başlarken"
+msgstr ""
msgid "IDE|Go to project"
msgstr ""
@@ -5906,7 +6859,7 @@ msgid "IDE|Refresh preview"
msgstr "Önizlemeyi yenile"
msgid "IDE|Review"
-msgstr "Ä°nceleme"
+msgstr "Ä°ncele"
msgid "IP Address"
msgstr ""
@@ -5938,10 +6891,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -5981,13 +6943,13 @@ msgid "Import in progress"
msgstr ""
msgid "Import issues"
-msgstr ""
+msgstr "İçe aktarma sorunları"
msgid "Import members"
msgstr ""
msgid "Import members from another project"
-msgstr ""
+msgstr "Üyeleri başka bir projeden içe aktar"
msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
@@ -5996,7 +6958,7 @@ msgid "Import project"
msgstr ""
msgid "Import project members"
-msgstr ""
+msgstr "Proje üyelerini içe aktar"
msgid "Import projects from Bitbucket"
msgstr "Bitbucket'ten projeleri içe aktar"
@@ -6022,6 +6984,12 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -6031,6 +6999,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -6040,9 +7014,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr "Almak istediğiniz projeleri seçin"
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr "GitLab Kurumsal Sürüm ile sorun panolarını iyileştirin."
@@ -6094,12 +7077,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6121,12 +7113,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6174,27 +7178,54 @@ msgstr ""
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
+msgstr "Geçersiz pin kodu"
+
+msgid "Invalid query"
msgstr ""
-msgid "Invalid two-factor code."
+msgid "Invalid repository path"
+msgstr "Geçersiz depo yolu"
+
+msgid "Invalid server response"
msgstr ""
+msgid "Invalid two-factor code."
+msgstr "Geçersiz iki adımlı doğrulama kodu."
+
msgid "Invitation"
msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6207,14 +7238,17 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
-msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
+msgid "Is using license seat:"
msgstr ""
+msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
+msgstr "Kapatıldı (%{moved_link_start}taşındı%{moved_link_end})"
+
msgid "Issue"
msgstr ""
msgid "Issue Boards"
-msgstr ""
+msgstr "Sorun Panoları"
msgid "Issue board focus mode"
msgstr ""
@@ -6225,26 +7259,32 @@ msgstr "Sorun etkinlikleri"
msgid "Issue template (optional)"
msgstr ""
-msgid "IssueBoards|Board"
+msgid "Issue update failed"
msgstr ""
-msgid "IssueBoards|Boards"
+msgid "Issue was closed by %{name} %{reason}"
msgstr ""
+msgid "IssueBoards|Board"
+msgstr "Pano"
+
+msgid "IssueBoards|Boards"
+msgstr "Panolar"
+
msgid "IssueBoards|Create new board"
msgstr "Yeni pano oluÅŸtur"
msgid "IssueBoards|Delete board"
-msgstr ""
+msgstr "Panoyu sil"
msgid "IssueBoards|No matching boards found"
-msgstr ""
+msgstr "Eşleşen pano bulunamadı"
msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
-msgstr ""
+msgstr "Bazı panolarınız gizlendi, tekrar görmek için bir lisans etkinleştirin."
msgid "IssueBoards|Switch board"
-msgstr ""
+msgstr "Panoyu deÄŸiÅŸtir"
msgid "Issues"
msgstr "Sorunlar"
@@ -6259,28 +7299,28 @@ msgid "Issues with comments, merge requests with diffs and comments, labels, mil
msgstr ""
msgid "Issues, merge requests, pushes, and comments."
-msgstr ""
+msgstr "Sorunlar, birleÅŸtirme istekleri, itmeler ve yorumlar."
msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
msgstr ""
msgid "IssuesAnalytics|Issues Created"
-msgstr ""
+msgstr "Sorunlar OluÅŸturuldu"
msgid "IssuesAnalytics|Issues created per month"
-msgstr ""
+msgstr "Aylık oluşturulan sorunlar"
msgid "IssuesAnalytics|Last 12 months"
-msgstr ""
+msgstr "Son 12 ay"
msgid "IssuesAnalytics|Sorry, your filter produced no results"
-msgstr ""
+msgstr "Üzgünüz, süzgeciniz sonuç üretmedi"
msgid "IssuesAnalytics|There are no issues for the projects in your group"
-msgstr ""
+msgstr "Grubunuzdaki projeler için hiç sorun yok"
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
-msgstr ""
+msgstr "Aramanızı genişletmek için yukarıdaki süzgeç çubuğundaki süzgeçleri değiştirin veya kaldırın"
msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
msgstr ""
@@ -6300,6 +7340,48 @@ msgstr "Oca"
msgid "January"
msgstr "Ocak"
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr ""
@@ -6396,6 +7478,12 @@ msgstr "Tem"
msgid "July"
msgstr "Temmuz"
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr "Haz"
@@ -6405,6 +7493,9 @@ msgstr "Haziran"
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6424,17 +7515,23 @@ msgid "Kubernetes cluster integration was successfully removed."
msgstr ""
msgid "Kubernetes cluster was successfully updated."
-msgstr ""
+msgstr "Kubernetes kümesi başarıyla güncellendi."
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr "LDAP eşitlemesi devam ediyor. Bu birkaç dakika sürebilir. Değişiklikleri görmek için sayfayı yenileyin."
+
msgid "LFS"
msgstr ""
@@ -6442,28 +7539,31 @@ msgid "LFS objects"
msgstr ""
msgid "LFSStatus|Disabled"
-msgstr "LFSStatus|Kapalı"
+msgstr "Kapalı"
msgid "LFSStatus|Enabled"
-msgstr "LFSStatus|Etkin"
+msgstr "Etkin"
-msgid "Label"
+msgid "LICENSE"
msgstr ""
+msgid "Label"
+msgstr "Etiket"
+
msgid "Label actions dropdown"
msgstr ""
msgid "Label lists show all issues with the selected label."
-msgstr ""
+msgstr "Etiket listeleri, seçilen etiket ile ilgili tüm sorunları gösterir."
msgid "Label was created"
-msgstr ""
+msgstr "Etiket oluÅŸturuldu"
msgid "Label was removed"
-msgstr ""
+msgstr "Etiket kaldırıldı"
msgid "Label was successfully updated."
-msgstr ""
+msgstr "Etiket başarıyla güncellendi."
msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
msgstr ""
@@ -6472,7 +7572,7 @@ msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
msgstr ""
msgid "LabelSelect|Labels"
-msgstr ""
+msgstr "Etiketler"
msgid "Labels"
msgstr "Etiketler"
@@ -6481,20 +7581,23 @@ msgid "Labels can be applied to %{features}. Group labels are available for any
msgstr ""
msgid "Labels can be applied to issues and merge requests to categorize them."
-msgstr ""
+msgstr "Etiketler sorunları ve birleştirme taleplerini kategorize etmek için kullanılabilir."
msgid "Labels can be applied to issues and merge requests."
-msgstr ""
+msgstr "Etiketler sorunlara ve birleÅŸtirme taleplerine uygulanabilir."
msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
msgstr ""
msgid "Labels|Promote Label"
-msgstr ""
+msgstr "Etiket Tanıtımı"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr "Dil"
@@ -6509,6 +7612,9 @@ msgstr[1] ""
msgid "Last Pipeline"
msgstr ""
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr "Son etkinlik"
@@ -6536,12 +7642,18 @@ msgstr ""
msgid "Last updated"
msgstr "Son güncelleme"
-msgid "LastPushEvent|You pushed to"
+msgid "Last used"
msgstr ""
-msgid "LastPushEvent|at"
+msgid "Last used on:"
msgstr ""
+msgid "LastPushEvent|You pushed to"
+msgstr "Şuna yolladınız:"
+
+msgid "LastPushEvent|at"
+msgstr " "
+
msgid "Latest changes"
msgstr ""
@@ -6551,6 +7663,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6561,14 +7679,17 @@ msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple
msgstr ""
msgid "Learn more about Auto DevOps"
-msgstr ""
+msgstr "Otomatik DevOps hakkında daha fazla bilgi edinin"
msgid "Learn more about Kubernetes"
-msgstr ""
+msgstr "Kubernetes hakkında daha fazla bilgi edinin"
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6581,6 +7702,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -6600,6 +7724,12 @@ msgid "Leave project"
msgstr ""
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
+msgstr "\"Dosya türü\" ve \"Teslim yöntemi\" seçeneklerini varsayılan değerlerinde bırakın."
+
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
msgid "License"
@@ -6677,6 +7807,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6691,6 +7824,9 @@ msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgstr[1] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6719,6 +7855,9 @@ msgid "Live preview"
msgstr "Canlı önizleme"
msgid "Loading contribution stats for group members"
+msgstr "Grup üyeleri için katkı istatistikleri yükleniyor"
+
+msgid "Loading functions timed out. Please reload the page to try again."
msgstr ""
msgid "Loading the GitLab IDE..."
@@ -6742,6 +7881,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6758,6 +7900,9 @@ msgid "Locked to current projects"
msgstr ""
msgid "Locks give the ability to lock specific file or folder."
+msgstr "Kilitler, belirli bir dosyayı veya klasörü kilitleme yeteneği sağlar."
+
+msgid "Locks the discussion"
msgstr ""
msgid "Login with smartcard"
@@ -6784,12 +7929,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6812,13 +7966,13 @@ msgid "Manage applications that you've authorized to use your account."
msgstr ""
msgid "Manage group labels"
-msgstr ""
+msgstr "Grup etiketlerini yönet"
msgid "Manage labels"
-msgstr ""
+msgstr "Etiketleri yönet"
msgid "Manage project labels"
-msgstr ""
+msgstr "Proje etiketlerini yönet"
msgid "Manage two-factor authentication"
msgstr ""
@@ -6850,6 +8004,15 @@ msgstr "Mar"
msgid "March"
msgstr "Mart"
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr "Yapılacağı tamamlandı olarak işaretle"
@@ -6862,6 +8025,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6881,11 +8053,14 @@ msgid "Maximum capacity"
msgstr ""
msgid "Maximum delay (Minutes)"
-msgstr ""
+msgstr "Maksimum gecikme (dakika)"
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6911,46 +8086,37 @@ msgid "Members"
msgstr "Ãœyeler"
msgid "Members can be added by project <i>Maintainers</i> or <i>Owners</i>"
-msgstr ""
+msgstr "Üyeler, <i>Sorumlu</i> veya <i>Sahipleri</i> tarafından eklenebilir"
msgid "Members of <strong>%{project_name}</strong>"
+msgstr "<strong>%{project_name}</strong> projesinin üyeleri"
+
+msgid "Merge"
msgstr ""
msgid "Merge Request"
msgstr "BirleÅŸtirme Ä°steÄŸi"
msgid "Merge Request Approvals"
-msgstr ""
+msgstr "Birleştirme İsteği Onayları"
msgid "Merge Requests"
msgstr "BirleÅŸtirme Ä°stekleri"
msgid "Merge Requests created"
-msgstr ""
-
-msgid "Merge commit"
-msgstr ""
+msgstr "BirleÅŸtirme istekleri oluÅŸturuldu"
msgid "Merge commit message"
-msgstr ""
-
-msgid "Merge commit with semi-linear history"
-msgstr ""
+msgstr "Birleştirme işlemi mesajı"
msgid "Merge events"
-msgstr ""
+msgstr "BirleÅŸtirme etkinlikleri"
msgid "Merge immediately"
-msgstr ""
+msgstr "Hemen birleÅŸtir"
msgid "Merge in progress"
-msgstr ""
-
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
+msgstr "BirleÅŸtirme devam ediyor"
msgid "Merge request"
msgstr "BirleÅŸtirme isteÄŸi"
@@ -6968,31 +8134,58 @@ msgid "Merge requests are a place to propose changes you've made to a project an
msgstr ""
msgid "Merge when pipeline succeeds"
+msgstr "İş hattı başarılı olduğunda birleştir"
+
+msgid "MergeConflict|Commit to source branch"
msgstr ""
-msgid "MergeRequests|Add a reply"
+msgid "MergeConflict|Committing..."
msgstr ""
-msgid "MergeRequests|An error occurred while saving the draft comment."
+msgid "MergeConflict|HEAD//our changes"
msgstr ""
-msgid "MergeRequests|Discussion stays resolved"
+msgid "MergeConflict|Use ours"
msgstr ""
-msgid "MergeRequests|Discussion stays unresolved"
+msgid "MergeConflict|Use theirs"
msgstr ""
-msgid "MergeRequests|Discussion will be resolved"
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequests|Add a reply"
+msgstr "Bir yanıt ekle"
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr "Taslak yorum kaydedilirken bir hata oluÅŸtu."
+
+msgid "MergeRequests|Discussion stays resolved"
+msgstr "Tartışma çözüldü"
+
+msgid "MergeRequests|Discussion stays unresolved"
+msgstr "Tartışma çözülmedi"
+
+msgid "MergeRequests|Discussion will be resolved"
+msgstr "Tartışma çözülecek"
+
msgid "MergeRequests|Discussion will be unresolved"
+msgstr "Tartışma çözülmedi"
+
+msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
msgid "MergeRequests|Reply..."
-msgstr ""
+msgstr "Yanıt..."
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr "Bu tartışmayı yeni bir konuyla çöz"
@@ -7000,44 +8193,47 @@ msgstr "Bu tartışmayı yeni bir konuyla çöz"
msgid "MergeRequests|Saving the comment failed"
msgstr "Yorum kaydedilemedi"
-msgid "MergeRequests|Toggle comments for this file"
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
msgstr ""
+msgid "MergeRequests|Toggle comments for this file"
+msgstr "Bu dosya için yorumları değiştir"
+
msgid "MergeRequests|View file @ %{commitId}"
-msgstr ""
+msgstr "Dosyayı göster @ %{commitId}"
msgid "MergeRequests|View replaced file @ %{commitId}"
-msgstr ""
+msgstr "Değiştirilen @ %{commitId} dosyasını görüntüle"
msgid "MergeRequests|commented on commit %{commitLink}"
-msgstr ""
+msgstr "%{commitLink} işlemine yorum yapıldı"
msgid "MergeRequests|started a discussion"
-msgstr ""
+msgstr "bir tartışma başlattı"
msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
-msgstr ""
+msgstr "%{linkStart}bir eski sürüm değişikliği%{linkEnd} ile ilgili bir tartışma başlattı"
msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
-msgstr ""
+msgstr "%{linkStart}değişiklik%{linkEnd} ile ilgili bir tartışma başlattı"
msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
msgstr ""
msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
-msgstr ""
+msgstr "%{linkStart}%{commitId}%{linkEnd} işlemi ile ilgili bir tartışma başlattı"
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
-msgstr ""
+msgstr "%{paragraphStart}açıklama %{descriptionChangedTimes}sürelerini%{timeDifferenceMinutes} değiştirdi%{paragraphEnd}"
msgid "MergeRequest|Error loading full diff. Please try again."
-msgstr ""
+msgstr "Tam değişiklik yüklenirken hata oluştu. Lütfen tekrar deneyin."
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
-msgstr ""
+msgstr "Dosya bulunamadı"
msgid "Merged"
msgstr "BirleÅŸtirildi"
@@ -7048,6 +8244,12 @@ msgstr ""
msgid "Messages"
msgstr "Mesajlar"
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr "Ölçüt başarıyla güncellendi."
+
msgid "Metrics"
msgstr ""
@@ -7063,6 +8265,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7102,9 +8307,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7136,7 +8338,7 @@ msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
msgstr ""
msgid "Metrics|Unit label"
-msgstr ""
+msgstr "Birim etiketi"
msgid "Metrics|Used as a title for the chart"
msgstr "Grafik için başlık olarak kullanılır"
@@ -7145,14 +8347,26 @@ msgid "Metrics|Used if the query returns a single series. If it returns multiple
msgstr ""
msgid "Metrics|Y-axis label"
-msgstr ""
+msgstr "Y ekseni etiketi"
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7177,9 +8391,6 @@ msgstr ""
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
-
msgid "Milestones|Delete milestone"
msgstr "Dönüm noktasını sil"
@@ -7198,7 +8409,7 @@ msgstr ""
msgid "Milestones|Promote Milestone"
msgstr ""
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
@@ -7207,6 +8418,15 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7226,13 +8446,25 @@ msgid "Mirroring repositories"
msgstr ""
msgid "Mirroring settings were successfully updated."
+msgstr "Yansıtma ayarları başarıyla güncellendi."
+
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr "Yansıtma ayarları başarıyla güncellendi. Proje güncelleniyor."
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
msgstr ""
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
msgid "Modal|Cancel"
-msgstr "Modal|Ä°ptal"
+msgstr "Ä°ptal"
msgid "Modal|Close"
msgstr "Kapat"
@@ -7288,9 +8520,27 @@ msgstr ""
msgid "Move issue"
msgstr "Konuyu taşı"
-msgid "Multiple issue boards"
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
msgstr ""
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
+msgid "Multiple issue boards"
+msgstr "Çoklu sorun panoları"
+
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -7300,9 +8550,12 @@ msgstr ""
msgid "Name"
msgstr ""
-msgid "Name new label"
+msgid "Name has already been taken"
msgstr ""
+msgid "Name new label"
+msgstr "Yeni etiketi adlandır"
+
msgid "Name your individual key via a title"
msgstr "Bireysel anahtarınızı bir başlık ile adlandırın"
@@ -7322,7 +8575,7 @@ msgid "Nav|Help"
msgstr "Yardım"
msgid "Nav|Home"
-msgstr "GiriÅŸ"
+msgstr "Ana sayfa"
msgid "Nav|Sign In / Register"
msgstr "Oturum Aç / Kaydol"
@@ -7395,6 +8648,9 @@ msgstr "Yeni ortam"
msgid "New epic"
msgstr "Yeni epik"
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr "Yeni dosya"
@@ -7419,6 +8675,9 @@ msgstr "Yeni birleÅŸtirme isteÄŸi"
msgid "New milestone"
msgstr "Yeni dönüm noktası"
+msgid "New password"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr "Yeni iş hatları, aynı daldaki daha eski iş hatlarını iptal edecek"
@@ -7449,6 +8708,12 @@ msgstr "Yeni..."
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7456,6 +8721,9 @@ msgid "No %{providerTitle} repositories available to import"
msgstr ""
msgid "No Label"
+msgstr "Etiket yok"
+
+msgid "No Milestone"
msgstr ""
msgid "No Tag"
@@ -7464,6 +8732,12 @@ msgstr "Etiket Yok"
msgid "No activities found"
msgstr "Etkinlik bulunamadı"
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7479,9 +8753,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
-msgid "No contributions were found"
+msgid "No contributions"
msgstr ""
+msgid "No contributions were found"
+msgstr "Hiçbir katkı bulunamadı"
+
msgid "No credit card required."
msgstr ""
@@ -7503,6 +8780,9 @@ msgstr ""
msgid "No file selected"
msgstr "Dosya seçili değil"
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr "Dosya bulunamadı."
@@ -7524,9 +8804,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7537,11 +8814,14 @@ msgid "No messages were logged"
msgstr ""
msgid "No milestones to show"
-msgstr ""
+msgstr "Gösterilecek dönüm noktası yok"
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr "Bu dosya türü için önizleme yok"
@@ -7569,6 +8849,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr "Düğüm başarıyla güncellendi."
+
msgid "Nodes"
msgstr ""
@@ -7617,14 +8903,17 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
-msgstr "Notlar|Bu yorumu oluşturmayı iptal etmek istediğinizden emin misiniz?"
+msgstr "Bu yorumu oluşturmayı iptal etmek istediğinizden emin misiniz?"
msgid "Notes|Collapse replies"
msgstr ""
msgid "Notes|Show all activity"
-msgstr "Tüm etkinliği göster"
+msgstr "Tüm etkinlikleri göster"
msgid "Notes|Show comments only"
msgstr ""
@@ -7632,6 +8921,12 @@ msgstr ""
msgid "Notes|Show history only"
msgstr ""
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -7641,17 +8936,20 @@ msgstr "Bildirim ayarı"
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr ""
msgid "NotificationEvent|Close merge request"
-msgstr ""
+msgstr "BirleÅŸtirme isteÄŸini kapat"
msgid "NotificationEvent|Failed pipeline"
msgstr ""
msgid "NotificationEvent|Merge merge request"
-msgstr ""
+msgstr "BirleÅŸtirme isteÄŸi birleÅŸtir"
msgid "NotificationEvent|New epic"
msgstr ""
@@ -7660,7 +8958,7 @@ msgid "NotificationEvent|New issue"
msgstr ""
msgid "NotificationEvent|New merge request"
-msgstr ""
+msgstr "Yeni birleÅŸtirme isteÄŸi"
msgid "NotificationEvent|New note"
msgstr "Yeni not"
@@ -7669,7 +8967,7 @@ msgid "NotificationEvent|Reassign issue"
msgstr ""
msgid "NotificationEvent|Reassign merge request"
-msgstr ""
+msgstr "BirleÅŸtirme isteÄŸini yeniden ata"
msgid "NotificationEvent|Reopen issue"
msgstr ""
@@ -7681,7 +8979,7 @@ msgid "NotificationLevel|Custom"
msgstr "Özel"
msgid "NotificationLevel|Disabled"
-msgstr ""
+msgstr "Devre dışı"
msgid "NotificationLevel|Global"
msgstr ""
@@ -7695,6 +8993,9 @@ msgstr ""
msgid "NotificationLevel|Watch"
msgstr ""
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr "Bildirimler"
@@ -7710,6 +9011,12 @@ msgstr "Kas"
msgid "November"
msgstr "Kasım"
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr ""
@@ -7723,9 +9030,15 @@ msgid "October"
msgstr "Ekim"
msgid "OfSearchInADropdown|Filter"
+msgstr "Süzgeç"
+
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
msgstr ""
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7748,13 +9061,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7767,11 +9080,14 @@ msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign
msgstr ""
msgid "Only project members can comment."
-msgstr ""
+msgstr "Sadece proje üyeleri yorum yapabilir."
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7817,6 +9133,12 @@ msgstr ""
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7841,9 +9163,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7854,17 +9173,20 @@ msgid "Optionally, you can %{link_to_customize} how Google Code email addresses
msgstr ""
msgid "Options"
-msgstr ""
+msgstr "Seçenekler"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
msgid "Other Labels"
-msgstr ""
+msgstr "DiÄŸer Etiketler"
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
@@ -7874,6 +9196,12 @@ msgstr "Genel bakış"
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr ""
@@ -7901,17 +9229,20 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
-msgid "Pagination|Last »"
+msgid "Pages getting started guide"
msgstr ""
+msgid "Pagination|Last »"
+msgstr "Son »"
+
msgid "Pagination|Next"
-msgstr ""
+msgstr "Sonraki"
msgid "Pagination|Prev"
-msgstr ""
+msgstr "Önceki"
msgid "Pagination|« First"
-msgstr ""
+msgstr "« İlk"
msgid "Parameter"
msgstr ""
@@ -7922,9 +9253,21 @@ msgstr ""
msgid "Password"
msgstr "Åžifre"
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7937,7 +9280,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7947,7 +9290,7 @@ msgid "Path, transfer, remove"
msgstr ""
msgid "Path:"
-msgstr ""
+msgstr "Yol:"
msgid "Pause"
msgstr ""
@@ -7964,9 +9307,12 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
-msgid "Perform advanced options such as changing path, transferring, or removing the group."
+msgid "People without permission will never get a notification."
msgstr ""
+msgid "Perform advanced options such as changing path, transferring, or removing the group."
+msgstr "Yolu değiştirme, grubu aktarma veya kaldırma gibi gelişmiş seçenekleri uygulayın."
+
msgid "Performance optimization"
msgstr ""
@@ -7985,12 +9331,27 @@ msgstr "Kişisel Erişim Anahtarı"
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr ""
@@ -7998,7 +9359,7 @@ msgid "Pipeline Schedules"
msgstr ""
msgid "Pipeline minutes quota"
-msgstr ""
+msgstr "İş hattı dakika kotası"
msgid "Pipeline quota"
msgstr "İş Hattı Kotası"
@@ -8007,7 +9368,7 @@ msgid "Pipeline triggers"
msgstr ""
msgid "Pipeline: %{status}"
-msgstr ""
+msgstr "İş hattı: %{status}"
msgid "PipelineCharts|Failed:"
msgstr ""
@@ -8037,7 +9398,7 @@ msgid "PipelineSchedules|Inactive"
msgstr ""
msgid "PipelineSchedules|Next Run"
-msgstr ""
+msgstr "Sonraki çalışma"
msgid "PipelineSchedules|None"
msgstr ""
@@ -8058,10 +9419,10 @@ msgid "PipelineSheduleIntervalPattern|Custom"
msgstr ""
msgid "PipelineStatusTooltip|Commit: %{ci_status}"
-msgstr ""
+msgstr "Ä°ÅŸlem: %{ci_status}"
msgid "PipelineStatusTooltip|Pipeline: %{ci_status}"
-msgstr ""
+msgstr "İş hattı: %{ci_status}"
msgid "Pipelines"
msgstr ""
@@ -8069,6 +9430,9 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines emails"
+msgstr "İş hattı e-postaları"
+
msgid "Pipelines for last month"
msgstr ""
@@ -8078,10 +9442,13 @@ msgstr ""
msgid "Pipelines for last year"
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgstr "'%{project_name}' için iş hattı ayarları başarıyla güncellendi."
+
+msgid "Pipelines| to purchase more minutes."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8102,6 +9469,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8145,7 +9515,7 @@ msgid "Pipeline|Run for"
msgstr ""
msgid "Pipeline|Search branches"
-msgstr ""
+msgstr "Dalları ara"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
@@ -8154,7 +9524,7 @@ msgid "Pipeline|Stages"
msgstr ""
msgid "Pipeline|Status"
-msgstr ""
+msgstr "Durum"
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -8162,6 +9532,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8192,6 +9565,15 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8201,12 +9583,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8237,6 +9637,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8249,6 +9652,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8270,7 +9682,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8288,12 +9700,66 @@ msgstr "Tercihler"
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
-msgstr "Preferences|Gezinme teması"
+msgstr "Gezinme teması"
+
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr "Aramak için Enter tuşuna basın veya tıklayın"
@@ -8309,12 +9775,18 @@ msgstr ""
msgid "Preview"
msgstr "Önizleme"
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr "Önizleme yükü"
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8322,13 +9794,13 @@ msgid "Prioritize"
msgstr ""
msgid "Prioritize label"
-msgstr ""
+msgstr "Etikete öncelik ver"
msgid "Prioritized Labels"
-msgstr ""
+msgstr "Öncelikli Etiketler"
msgid "Prioritized label"
-msgstr ""
+msgstr "Öncelikli etiket"
msgid "Private"
msgstr "Özel"
@@ -8342,15 +9814,24 @@ msgstr "Özel - Grup ve grubun projeleri sadece üyeler tarafından görülebili
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr "Profil"
msgid "Profile Settings"
msgstr "Profil Ayarları"
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr ""
@@ -8364,7 +9845,7 @@ msgid "Profiles|Account scheduled for removal."
msgstr "Hesabın kaldırılması planlandı."
msgid "Profiles|Activate signin with one of the following services"
-msgstr ""
+msgstr "Aşağıdaki hizmetlerden biriyle oturum açmayı etkinleştirin"
msgid "Profiles|Active"
msgstr "Etkin"
@@ -8381,6 +9862,9 @@ msgstr "Profil resmi kırpıcı"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "Profil resmi kaldırılacak. Emin misiniz?"
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr "Kullanıcı adını değiştir"
@@ -8391,7 +9875,7 @@ msgid "Profiles|Choose file..."
msgstr "Dosya seç..."
msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
-msgstr ""
+msgstr "Herhangi bir proje, havuz veya kuruluş bilgisi olmadan özel projelerinizin genel profilindeki katkılarını göstermeyi seçin"
msgid "Profiles|City, country"
msgstr "Şehir, ülke"
@@ -8400,6 +9884,9 @@ msgid "Profiles|Clear status"
msgstr "Durumu temizle"
msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr "Aşağıdaki hizmetlerden biriyle giriş yapmak için simgeye tıklayın"
+
+msgid "Profiles|Commit email"
msgstr ""
msgid "Profiles|Connect"
@@ -8409,11 +9896,14 @@ msgid "Profiles|Connected Accounts"
msgstr "Bağlı Hesaplar"
msgid "Profiles|Current path: %{path}"
-msgstr "Geçerli dizin: %{path}"
+msgstr "Geçerli yol: %{path}"
msgid "Profiles|Current status"
msgstr "Mevcut durum"
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr "Hesabı Sil"
@@ -8441,18 +9931,36 @@ msgstr "Profili Düzenle"
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr "Adınızı girin, böylece tanıdığınız kişiler sizi tanıyabilir"
-msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
msgstr ""
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr "İki Adımlı Kimlik Doğrulamayı (2FA) etkinleştirerek hesabınızın güvenliğini artırın"
+
msgid "Profiles|Invalid password"
msgstr "Geçersiz şifre"
msgid "Profiles|Invalid username"
msgstr "Geçersiz kullanıcı adı"
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr "Daha fazla bilgi edin"
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr "Özel bir katkı yaptı"
@@ -8462,18 +9970,33 @@ msgstr "Ana ayarlar"
msgid "Profiles|No file chosen"
msgstr "Dosya seçili değil"
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr "Yol"
msgid "Profiles|Position and size your new avatar"
msgstr "Yeni profil resminizi konumlandırın ve boyutlandırın"
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr "Özel katkılar"
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr "Genel Profil Resmi"
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr "Profil resmini kaldır"
@@ -8484,25 +10007,22 @@ msgid "Profiles|Social sign-in"
msgstr "Sosyal oturum açma"
msgid "Profiles|Some options are unavailable for LDAP accounts"
-msgstr ""
+msgstr "LDAP hesapları için bazı seçenekler kullanılamıyor"
msgid "Profiles|Tell us about yourself in fewer than 250 characters"
-msgstr ""
+msgstr "Bize 250 karakterden daha azı ile kendinizden bahsedin"
msgid "Profiles|The maximum file size allowed is 200KB."
-msgstr ""
-
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
+msgstr "200 KB izin verilen en yüksek dosya boyutudur."
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
-msgstr ""
+msgstr "Bu, genel bir SSH anahtarına benzemiyor. Eklemek istediğinizden emin misiniz?"
msgid "Profiles|This email will be displayed on your public profile"
-msgstr ""
+msgstr "Bu e-posta, herkese açık profilinizde gösterilecek"
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{commit_email_link_start}Learn more%{commit_email_link_end}"
-msgstr ""
+msgstr "Bu e-posta, düzenlemeler ve birleştirmeler gibi web tabanlı işlemler için kullanılacaktır. %{commit_email_link_start}Daha fazla bilgi edinin%{commit_email_link_end}"
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr "Bu ifade ve mesaj profilinizde ve arayüz boyunca görünecektir."
@@ -8510,13 +10030,16 @@ msgstr "Bu ifade ve mesaj profilinizde ve arayüz boyunca görünecektir."
msgid "Profiles|This information will appear on your profile"
msgstr "Bu bilgiler profilinizde görünecek"
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr "İki Aşamalı Kimlik Doğrulama"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
-msgstr ""
+msgstr "Onaylamak için kendi %{confirmationValue} yazınız:"
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8531,9 +10054,12 @@ msgstr "Yeni profil resmi yükle"
msgid "Profiles|Use a private email - %{email}"
msgstr "Özel bir e-posta kullan - %{email}"
-msgid "Profiles|Username change failed - %{message}"
+msgid "Profiles|User ID"
msgstr ""
+msgid "Profiles|Username change failed - %{message}"
+msgstr "Kullanıcı adı değişikliği başarısız oldu - %{message}"
+
msgid "Profiles|Username successfully changed"
msgstr "Kullanıcı adı başarıyla değiştirildi"
@@ -8550,19 +10076,22 @@ msgid "Profiles|You can change your avatar here"
msgstr "Profil resminizi buradan deÄŸiÅŸtirebilirsiniz"
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr "Profil resminizi buradan değiştirebilir veya %{gravatar_link} sitesine dönmek için mevcut resmi kaldırabilirsiniz"
+
+msgid "Profiles|You can set your current timezone here"
msgstr ""
msgid "Profiles|You can upload your avatar here"
msgstr "Profil resminizi buradan yükleyebilirsiniz"
msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
-msgstr ""
+msgstr "Profil resminizi buraya yükleyebilir veya %{gravatar_link} adresinden değiştirebilirsiniz"
msgid "Profiles|You don't have access to delete this user."
-msgstr ""
+msgstr "Bu kullanıcıyı silme yetkiniz yok."
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
-msgstr ""
+msgstr "Hesabınızı silmeden önce sahipliği devretmeniz veya bu grupları silmeniz gerekir."
msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
msgstr "LinkedIn profil adınız linkedin.com/in/profiladı"
@@ -8589,7 +10118,7 @@ msgid "Profiles|username"
msgstr "kullanıcıadı"
msgid "Profiles|website.com"
-msgstr "website.com"
+msgstr "websitesi.com"
msgid "Profiles|your account"
msgstr "hesabınız"
@@ -8625,7 +10154,7 @@ msgid "Project '%{project_name}' was successfully created."
msgstr "'%{project_name}' projesi başarıyla oluşturuldu."
msgid "Project '%{project_name}' was successfully updated."
-msgstr ""
+msgstr "'%{project_name}' projesi başarıyla güncellendi."
msgid "Project Badges"
msgstr ""
@@ -8640,11 +10169,14 @@ msgid "Project access must be granted explicitly to each user."
msgstr "Proje erişimi her kullanıcıya açıkça verilmelidir."
msgid "Project and wiki repositories"
-msgstr ""
+msgstr "Proje ve wiki depoları"
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8673,7 +10205,7 @@ msgid "Project has too many %{label_for_message} to search"
msgstr ""
msgid "Project members"
-msgstr ""
+msgstr "Proje üyeleri"
msgid "Project name"
msgstr "Proje adı"
@@ -8690,6 +10222,9 @@ msgstr ""
msgid "Project:"
msgstr "Proje:"
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "Abone ol"
@@ -8700,10 +10235,10 @@ msgid "ProjectCreationLevel|Default project creation protection"
msgstr "Öntanımlı proje oluşturma koruması"
msgid "ProjectCreationLevel|Developers + Maintainers"
-msgstr "ProjectCreationLevel|GeliÅŸtirici + Sorumlu"
+msgstr "GeliÅŸtirici + Sorumlu"
msgid "ProjectCreationLevel|Maintainers"
-msgstr "ProjectCreationLevel|Sorumlu"
+msgstr "Sorumlu"
msgid "ProjectCreationLevel|No one"
msgstr "Hiç kimse"
@@ -8741,6 +10276,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8748,6 +10301,9 @@ msgid "ProjectSettings|Contact an admin to change this setting."
msgstr ""
msgid "ProjectSettings|Customize your project badges."
+msgstr "Proje rozetlerinizi özelleştirin."
+
+msgid "ProjectSettings|Every merge creates a merge commit"
msgstr ""
msgid "ProjectSettings|Failed to protect the tag"
@@ -8756,10 +10312,49 @@ msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
+msgstr "Rozetler hakkında daha fazla bilgi edinin."
+
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr "Birleştirme seçenekleri"
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr "Bu depoya yalnızca imzalanmış işlemler yollanabilir."
+
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
msgstr ""
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
@@ -8771,12 +10366,72 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgstr "Kullanıcılar, yalnızca kendi doğrulanmış e-postalarından biriyle taahhüt edilen bu depoya taahhütte bulunabilir."
+
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
msgstr ""
msgid "Projects"
msgstr "Projeler"
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8796,19 +10451,19 @@ msgid "ProjectsDropdown|Frequently visited"
msgstr ""
msgid "ProjectsDropdown|Loading projects"
-msgstr ""
+msgstr "Projeler yükleniyor"
msgid "ProjectsDropdown|Projects you visit often will appear here"
-msgstr ""
+msgstr "Sık ziyaret ettiğiniz projeler burada görünecektir"
msgid "ProjectsDropdown|Search your projects"
-msgstr ""
+msgstr "Projelerinizi arayın"
msgid "ProjectsDropdown|Something went wrong on our end."
msgstr ""
msgid "ProjectsDropdown|Sorry, no projects matched your search"
-msgstr ""
+msgstr "Üzgünüz, aramanızla eşleşen hiçbir proje yok"
msgid "ProjectsDropdown|This feature requires browser localStorage support"
msgstr ""
@@ -8931,6 +10586,15 @@ msgid "Promote to Group Milestone"
msgstr ""
msgid "Promote to group label"
+msgstr "Grup etiketini tanıtın"
+
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
msgstr ""
msgid "Promotions|Don't show me this again"
@@ -8951,25 +10615,28 @@ msgstr ""
msgid "Protected"
msgstr ""
-msgid "Protected Environments"
+msgid "Protected Branch"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Environment"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Environment"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr "%{environment_name} geliştiriciler için yazılabilir olacak. Emin misiniz?"
+
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
-msgid "ProtectedEnvironment|Protect"
+msgid "ProtectedEnvironment|Environment"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
+msgid "ProtectedEnvironment|Protect"
msgstr ""
msgid "ProtectedEnvironment|Protect an environment"
@@ -8978,9 +10645,18 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -9029,9 +10705,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr "Yollama Kuralı başarıyla güncellendi."
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr "Yollama Kuralları başarıyla güncellendi."
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9039,7 +10721,7 @@ msgid "Push an existing folder"
msgstr ""
msgid "Push events"
-msgstr ""
+msgstr "Yollama etkinlikleri"
msgid "Push project from command line"
msgstr ""
@@ -9056,12 +10738,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr "%{user_name}, \"%{ref}\" yeni dalı yolladı."
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr "Pushover, Android cihazı, iPhone, iPad ve Masaüstü bilgisayar ile gerçek zamanlı bildirimler almayı kolaylaştırır."
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr ""
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9075,7 +10799,7 @@ msgid "Read more"
msgstr ""
msgid "Read more about environments"
-msgstr ""
+msgstr "Ortamlar hakkında daha fazla bilgi edinin"
msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
@@ -9086,15 +10810,24 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr "Son aramalar"
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
@@ -9106,27 +10839,48 @@ msgstr ""
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Güncellenmiş durumu göstermek için bir saniye içinde yenilenecek..."
+msgstr[1] "Güncellenmiş durumu göstermek için %d saniye içinde yenilenecek..."
+
+msgid "Regenerate instance ID"
+msgstr ""
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9140,7 +10894,7 @@ msgid "Related Deployed Jobs"
msgstr ""
msgid "Related Issues"
-msgstr ""
+msgstr "Ä°lgili Sorunlar"
msgid "Related Jobs"
msgstr ""
@@ -9151,6 +10905,9 @@ msgstr ""
msgid "Related Merged Requests"
msgstr "Ä°lgili BirleÅŸtirme Talepleri"
+msgid "Related issues"
+msgstr ""
+
msgid "Related merge requests"
msgstr ""
@@ -9163,6 +10920,9 @@ msgstr ""
msgid "Remind later"
msgstr ""
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9172,34 +10932,49 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
msgstr ""
+msgid "Remove all or specific label(s)"
+msgstr "Tüm veya belirli etiketleri kaldır"
+
msgid "Remove approvers"
msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9214,6 +10989,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9242,7 +11035,10 @@ msgid "Repair authentication"
msgstr ""
msgid "Replace"
-msgstr ""
+msgstr "DeÄŸiÅŸtirme:"
+
+msgid "Replace all label(s)"
+msgstr "Tüm etiketleri değiştir"
msgid "Reply to comment"
msgstr ""
@@ -9253,7 +11049,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9268,6 +11064,9 @@ msgstr ""
msgid "Reports|Class"
msgstr "Sınıf"
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9307,12 +11106,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9335,7 +11128,7 @@ msgid "Repository cleanup has started. You will receive an email once the cleanu
msgstr ""
msgid "Repository has no locks."
-msgstr ""
+msgstr "Depo kilidi yok."
msgid "Repository maintenance"
msgstr ""
@@ -9367,6 +11160,12 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] ""
@@ -9377,6 +11176,9 @@ msgid_plural "Requires %d more approvals."
msgstr[0] ""
msgstr[1] ""
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr ""
@@ -9416,6 +11218,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9458,6 +11269,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9485,7 +11299,7 @@ msgid "Reviewing"
msgstr ""
msgid "Reviewing (merge request !%{mergeRequestId})"
-msgstr ""
+msgstr "Ä°nceleme (birleÅŸtirme isteÄŸi !%{mergeRequestId})"
msgid "Revoke"
msgstr ""
@@ -9496,9 +11310,15 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
-msgid "Roadmap"
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
msgstr ""
+msgid "Roadmap"
+msgstr "Yol haritası"
+
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
@@ -9527,10 +11347,10 @@ msgid "Runner token"
msgstr ""
msgid "Runner was not updated."
-msgstr ""
+msgstr "Çalıştırıcı güncellenemedi."
msgid "Runner was successfully updated."
-msgstr ""
+msgstr "Çalıştırıcı başarıyla güncellendi."
msgid "Runner will not receive any new jobs"
msgstr ""
@@ -9560,13 +11380,13 @@ msgid "Runners page."
msgstr ""
msgid "Runners|You have used all your shared Runners pipeline minutes."
-msgstr ""
+msgstr "Tüm paylaşılan Çalıştırıcı iş hattı dakikalarınızı kullandınız."
msgid "Running"
-msgstr ""
+msgstr "Çalışıyor"
msgid "Running…"
-msgstr ""
+msgstr "Çalışıyor…"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
@@ -9580,6 +11400,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr "SSH Anahtarları"
@@ -9589,6 +11412,9 @@ msgstr ""
msgid "SSH host keys"
msgstr "SSH ana bilgisayar anahtarları"
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9604,6 +11430,9 @@ msgstr ""
msgid "Save Changes"
msgstr "DeÄŸiÅŸiklikleri Kaydet"
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr "Uygulamayı kaydet"
@@ -9616,6 +11445,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -9644,10 +11476,10 @@ msgid "Scope"
msgstr ""
msgid "Scope not supported with disabled 'users_search' feature!"
-msgstr ""
+msgstr "Kapsam, devre dışı 'users_search' özelliği ile desteklenmiyor!"
msgid "Scoped issue boards"
-msgstr ""
+msgstr "Kapsamlı sorun panoları"
msgid "Scoped label"
msgstr ""
@@ -9676,9 +11508,21 @@ msgstr "Dalları ve etiketleri ara"
msgid "Search files"
msgstr "Dosyaları ara"
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr "Projeleri, sorunları vb. arayın."
+msgid "Search forks"
+msgstr "Arama çatalları"
+
msgid "Search groups"
msgstr "Grupları ara"
@@ -9700,6 +11544,9 @@ msgstr "Proje ara"
msgid "Search projects"
msgstr "Projeleri ara"
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr "Kullanıcıları ara"
@@ -9710,19 +11557,19 @@ msgid "Search your projects"
msgstr "Projelerinizi arayın"
msgid "SearchAutocomplete|All GitLab"
-msgstr ""
+msgstr "Tüm GitLab"
msgid "SearchAutocomplete|Issues I've created"
-msgstr "OluÅŸturduÄŸum Sorunlar"
+msgstr "OluÅŸturduÄŸum sorunlar"
msgid "SearchAutocomplete|Issues assigned to me"
msgstr "Bana atanan sorunlar"
msgid "SearchAutocomplete|Merge requests I've created"
-msgstr "OluÅŸturduÄŸum birleÅŸtirme istekleri"
+msgstr "OluÅŸturduÄŸum istekleri birleÅŸtir"
msgid "SearchAutocomplete|Merge requests assigned to me"
-msgstr "Bana atanan birleÅŸtirme istekleri"
+msgstr "Bana atanan istekleri birleÅŸtir"
msgid "SearchAutocomplete|in all GitLab"
msgstr "Tüm GitLab'da"
@@ -9734,7 +11581,7 @@ msgid "SearchAutocomplete|in this project"
msgstr "Bu projede"
msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for \"%{term}\""
-msgstr ""
+msgstr "\"%{term}\" için %{from} - %{to} / %{count} %{scope}"
msgid "Seats currently in use"
msgstr ""
@@ -9770,14 +11617,11 @@ msgid "Security Reports|Dismiss vulnerability"
msgstr ""
msgid "Security Reports|Learn more about setting up your dashboard"
-msgstr ""
+msgstr "Gösterge panonuzu ayarlama hakkında daha fazla bilgi edinin"
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9808,12 +11652,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9826,6 +11682,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9853,6 +11715,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9887,6 +11752,9 @@ msgid "Selecting a GitLab user will add a link to the GitLab user in the descrip
msgstr ""
msgid "Send an email notification to Developers."
+msgstr "Geliştiricilere bir e-posta bildirimi gönderin."
+
+msgid "Send confirmation email"
msgstr ""
msgid "Send email"
@@ -9970,6 +11838,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr "Servis Masası"
@@ -9980,7 +11851,7 @@ msgid "Service URL"
msgstr ""
msgid "Session duration (minutes)"
-msgstr ""
+msgstr "Oturum süresi (dakika)"
msgid "Session expiration, projects limit and attachment size."
msgstr "Oturum zaman aşımı, proje sınırı ve ek boyutu."
@@ -10000,21 +11871,24 @@ msgstr "Bu gruptaki projeler için bir şablon deposu ayarlayın"
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr "Varsayılanı ayarlayın ve görünürlük seviyelerini sınırlayın. İçe aktarma kaynaklarını ve git erişim protokolünü yapılandırın."
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
+msgid "Set milestone"
+msgstr ""
+
msgid "Set new password"
msgstr "Yeni parola ayarla"
msgid "Set notification email for abuse reports."
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
-msgstr ""
-
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -10030,6 +11904,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -10051,32 +11928,47 @@ msgstr "Yeni ÅŸifre ayarla"
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr "ÅŸifre ayarla"
msgid "SetStatusModal|Add status emoji"
-msgstr "SetStatusModal|Durum ifadesi ekle"
+msgstr "Durum ifadesi ekle"
msgid "SetStatusModal|Clear status"
-msgstr "SetStatusModal|Durumu temizle"
+msgstr "Durumu temizle"
msgid "SetStatusModal|Edit status"
-msgstr "SetStatusModal|Durumu düzenle"
+msgstr "Durumu düzenle"
msgid "SetStatusModal|Remove status"
-msgstr "SetStatusModal|Durumu kaldır"
+msgstr "Durumu kaldır"
msgid "SetStatusModal|Set a status"
-msgstr "SetStatusModal|Bir durum ayarla"
+msgstr "Bir durum ayarla"
msgid "SetStatusModal|Set status"
-msgstr "SetStatusModal|Durum ayarla"
+msgstr "Durum ayarla"
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
-msgstr ""
+msgstr "Üzgünüz, durumunuzu belirleyemedik. Lütfen daha sonra tekrar deneyin."
msgid "SetStatusModal|What's your status?"
-msgstr "SetStatusModal|Durumunuz nedir?"
+msgstr "Durumunuz nedir?"
+
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
msgid "Settings"
msgstr ""
@@ -10093,21 +11985,33 @@ msgstr ""
msgid "Shared projects"
msgstr ""
-msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgid "Shared runners help link"
msgstr ""
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr "Bu ad alanı için iş hattı dakikalarını sıfırlayarak, şu anda kullanılan dakikalar sıfıra ayarlanır."
+
msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
-msgstr ""
+msgstr "İş hattı dakikalarını sıfırla"
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
-msgstr ""
+msgstr "Kullanılan iş hattı dakikalarını sıfırla"
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr ""
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr ""
@@ -10123,9 +12027,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10179,12 +12080,30 @@ msgstr ""
msgid "Sign out"
msgstr "Oturumu kapat"
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10194,6 +12113,9 @@ msgstr ""
msgid "Similar issues"
msgstr "Benzer sorunlar"
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr ""
@@ -10203,6 +12125,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10272,6 +12197,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10290,6 +12218,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10314,18 +12245,21 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
msgstr ""
msgid "Something went wrong, unable to search projects"
-msgstr ""
+msgstr "Bir şeyler ters gitti, projeler aranamıyor"
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr "Üzgünüz, aramanızla eşleşen epik yok"
@@ -10369,7 +12303,7 @@ msgid "SortOptions|Largest repository"
msgstr "En büyük depo"
msgid "SortOptions|Last Contact"
-msgstr ""
+msgstr "Son iletiÅŸim"
msgid "SortOptions|Last created"
msgstr "Son oluÅŸturulan"
@@ -10381,28 +12315,31 @@ msgid "SortOptions|Last updated"
msgstr "Son güncelleme"
msgid "SortOptions|Least popular"
-msgstr ""
+msgstr "En az popüler"
msgid "SortOptions|Less weight"
msgstr "Daha az ağırlık"
+msgid "SortOptions|Manual"
+msgstr ""
+
msgid "SortOptions|Milestone due date"
msgstr "Dönüm noktası bitiş tarihi"
msgid "SortOptions|Milestone due later"
-msgstr ""
+msgstr "Dönüm noktası daha sonra"
msgid "SortOptions|Milestone due soon"
-msgstr ""
+msgstr "Dönüm noktası yakında"
msgid "SortOptions|More weight"
msgstr "Daha fazla ağırlık"
msgid "SortOptions|Most popular"
-msgstr ""
+msgstr "En popüler"
msgid "SortOptions|Most stars"
-msgstr ""
+msgstr "En çok yıldızlı"
msgid "SortOptions|Name"
msgstr "Ä°sim"
@@ -10414,7 +12351,7 @@ msgid "SortOptions|Name, descending"
msgstr "Ä°sim, azalan"
msgid "SortOptions|Oldest created"
-msgstr ""
+msgstr "En eski oluÅŸturulan"
msgid "SortOptions|Oldest joined"
msgstr "En eski katılan"
@@ -10423,13 +12360,13 @@ msgid "SortOptions|Oldest last activity"
msgstr "En son etkinlik"
msgid "SortOptions|Oldest sign in"
-msgstr ""
+msgstr "En eski oturum açma"
msgid "SortOptions|Oldest updated"
msgstr "En eski güncelleme"
msgid "SortOptions|Popularity"
-msgstr ""
+msgstr "Popülerlik"
msgid "SortOptions|Priority"
msgstr "Öncelik"
@@ -10440,6 +12377,12 @@ msgstr "Son etkinlik"
msgid "SortOptions|Recent sign in"
msgstr "Son giriÅŸ"
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr "Başlangıç ​​tarihi"
@@ -10512,23 +12455,26 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
msgid "Starred Projects"
-msgstr ""
+msgstr "Yıldızlı Projeler"
msgid "Starred Projects' Activity"
-msgstr ""
+msgstr "Yıldızlı Projelerin Etkinliği"
msgid "Starred projects"
-msgstr ""
+msgstr "Yıldızlı projeler"
msgid "StarredProjectsEmptyState|Visit a project page and press on a star icon. Then, you can find the project on this page."
-msgstr ""
+msgstr "Bir proje sayfasını ziyaret edin ve bir yıldız simgesine tıklayın. Ardından projeyi bu sayfada bulabilirsiniz."
msgid "StarredProjectsEmptyState|You don't have starred projects yet."
-msgstr ""
+msgstr "Henüz yıldızlı bir projeniz yok."
msgid "Stars"
msgstr ""
@@ -10536,29 +12482,32 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
msgid "Start a %{new_merge_request} with these changes"
-msgstr ""
+msgstr "Bu değişiklikler ile bir %{new_merge_request} başlatın"
msgid "Start a new merge request"
msgstr ""
msgid "Start a review"
-msgstr ""
+msgstr "Ä°nceleme baÅŸlat"
msgid "Start and due date"
msgstr ""
msgid "Start cleanup"
-msgstr ""
+msgstr "Temizlemeye baÅŸla"
msgid "Start date"
-msgstr ""
+msgstr "BaÅŸlama tarihi"
msgid "Start discussion"
-msgstr ""
+msgstr "Tartışmaya başla"
msgid "Start discussion & close %{noteable_name}"
msgstr ""
@@ -10566,6 +12515,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -10582,7 +12537,7 @@ msgid "Started asynchronous removal of all repository check states."
msgstr ""
msgid "Starting..."
-msgstr ""
+msgstr "Başlatılıyor..."
msgid "Starts %{startsIn}"
msgstr ""
@@ -10594,7 +12549,7 @@ msgid "State your message to activate"
msgstr ""
msgid "Status"
-msgstr ""
+msgstr "Durum"
msgid "Status:"
msgstr "Durum:"
@@ -10626,12 +12581,18 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr "Alt gruplar"
msgid "Subgroups and projects"
msgstr "Alt gruplar ve projeler"
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr "Spam olarak gönder"
@@ -10662,11 +12623,14 @@ msgstr "Takvime abone ol"
msgid "Subscribed"
msgstr "Abone"
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
msgid "SubscriptionTable|Free"
-msgstr ""
+msgstr "Ãœcretsiz"
msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
msgstr ""
@@ -10687,7 +12651,7 @@ msgid "SubscriptionTable|Max seats used"
msgstr ""
msgid "SubscriptionTable|Next invoice"
-msgstr ""
+msgstr "Sonraki fatura"
msgid "SubscriptionTable|Seats currently in use"
msgstr ""
@@ -10702,13 +12666,13 @@ msgid "SubscriptionTable|Subscription end date"
msgstr ""
msgid "SubscriptionTable|Subscription start date"
-msgstr ""
+msgstr "Abonelik başlangıç tarihi"
msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
msgstr ""
msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
-msgstr ""
+msgstr "Bu, aboneliğin başlamasından bu yana aynı anda var olan en yüksek kullanıcı sayısıdır."
msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
msgstr ""
@@ -10734,6 +12698,9 @@ msgstr "Kullanım"
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr "Kullanım sayımı günde bir kez 12:00 ÖS yapılır."
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10758,6 +12725,69 @@ msgstr ""
msgid "Suggested change"
msgstr ""
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr ""
@@ -10770,6 +12800,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10792,7 +12828,7 @@ msgid "System header and footer"
msgstr ""
msgid "System hook was successfully updated."
-msgstr ""
+msgstr "Sistem kancası başarıyla güncellendi."
msgid "System metrics (Custom)"
msgstr ""
@@ -10800,18 +12836,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr "Etiketler"
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr "Etiketler:"
@@ -10825,7 +12873,7 @@ msgid "TagsPage|Can't find HEAD commit for this tag"
msgstr ""
msgid "TagsPage|Cancel"
-msgstr "TagsPage|Ä°ptal"
+msgstr "Ä°ptal"
msgid "TagsPage|Create tag"
msgstr ""
@@ -10893,6 +12941,9 @@ msgstr "Hedef dal"
msgid "Team"
msgstr "Ekip"
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr "Åžablon"
@@ -10905,6 +12956,9 @@ msgstr "Uçbirim"
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "Hizmet Koşulları Sözleşmesi ve Gizlilik Politikası"
@@ -10920,6 +12974,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10935,7 +13016,7 @@ msgstr[0] ""
msgstr[1] ""
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
-msgstr ""
+msgstr "GitLab'daki Gelişmiş Genel arama, size zaman kazandıran güçlü bir arama hizmetidir. Yinelenen kod oluşturmak ve zaman kaybetmek yerine, artık kendi projenize yardımcı olabilecek diğer ekiplerin içinde kod arayabilirsiniz."
msgid "The CSV export will be created in the background. Once finished, it will be sent to <strong>%{email}</strong> in an attachment."
msgstr ""
@@ -10953,11 +13034,14 @@ msgid "The X509 Certificate to use when mutual TLS is required to communicate wi
msgstr ""
msgid "The amount of seconds after which a request to get a secondary node status will time out."
-msgstr ""
+msgstr "İkincil düğüm durumu alma isteğinin zaman aşımına uğrayacağı saniye cinsinden süre."
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10973,6 +13057,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -11030,6 +13117,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr ""
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -11048,6 +13144,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11072,9 +13174,21 @@ msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11084,15 +13198,21 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
-msgid "The remote repository is being updated..."
+msgid "The remote mirror took to long to complete."
msgstr ""
+msgid "The remote repository is being updated..."
+msgstr "Uzak depo güncelleniyor..."
+
msgid "The repository for this project does not exist."
msgstr ""
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr "Depo güncelleniyor..."
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11132,6 +13252,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11153,15 +13276,30 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr "Henüz arşivlenmiş proje yok"
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr ""
@@ -11195,9 +13333,24 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr ""
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr ""
@@ -11213,6 +13366,12 @@ msgstr "Kullanıcı etkinlik takvimi yüklenirken bir hata oluştu."
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr "Grup iş hattı dakikaları sıfırlanırken bir hata oluştu."
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr "Kullanıcı iş hattı dakikaları sıfırlanırken bir hata oluştu."
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11231,6 +13390,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11243,6 +13405,9 @@ msgstr ""
msgid "Third party offers"
msgstr "Üçüncü taraf teklifleri"
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11255,18 +13420,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11291,6 +13468,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11303,6 +13486,9 @@ msgstr "Bu dizin"
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11312,24 +13498,33 @@ msgstr "Bu grup"
msgid "This group does not provide any group Runners yet."
msgstr ""
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr "Bu gizli bir sorundur."
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
+msgid "This is your current session"
+msgstr ""
+
msgid "This issue is confidential"
msgstr "Bu sorun gizlidir"
-msgid "This issue is confidential and locked."
-msgstr "Bu sorun gizli ve kilitli."
-
msgid "This issue is locked."
msgstr "Bu sorun kilitlendi."
@@ -11399,12 +13594,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr "Bu birleÅŸtirme isteÄŸi kilitlendi."
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11477,6 +13666,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr ""
@@ -11592,7 +13787,7 @@ msgid "Timeago|1 year remaining"
msgstr "1 yıl kaldı"
msgid "Timeago|Past due"
-msgstr "Vadesi geçmiş"
+msgstr "Geçmiş ödeme tarihi"
msgid "Timeago|in %s days"
msgstr "%s gün içinde"
@@ -11661,6 +13856,9 @@ msgstr "Ä°pucu:"
msgid "Title"
msgstr "Başlık"
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr "Başlıklar ve dosya adları"
@@ -11676,6 +13874,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11742,6 +13943,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11758,10 +13962,10 @@ msgid "To view the roadmap, add a start or due date to one of your epics in this
msgstr ""
msgid "To widen your search, change or remove filters above"
-msgstr ""
+msgstr "Aramanızı genişletmek için yukarıdaki filtreleri değiştirin veya kaldırın"
msgid "To widen your search, change or remove filters."
-msgstr ""
+msgstr "Aramanızı genişletmek için süzgeçlerinizi değiştirin veya kaldırın."
msgid "Today"
msgstr "Bugün"
@@ -11778,6 +13982,9 @@ msgstr "Yapılacaklar"
msgid "Toggle Sidebar"
msgstr "Kenar çubuğunu değiştir"
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11790,16 +13997,25 @@ msgstr ""
msgid "Toggle discussion"
msgstr "Tartışmayı değiştir"
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Gezinmeyi deÄŸiÅŸtir"
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Kenar çubuğunu göster/gizle"
msgid "ToggleButton|Toggle Status: OFF"
-msgstr ""
+msgstr "DeÄŸiÅŸtirme Durumu: KAPALI"
msgid "ToggleButton|Toggle Status: ON"
+msgstr "Değiştirme Durumu: AÇIK"
+
+msgid "Toggles :%{name}: emoji award."
msgstr ""
msgid "Token"
@@ -11844,6 +14060,42 @@ msgstr ""
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
@@ -11875,7 +14127,7 @@ msgid "Trigger was re-assigned."
msgstr ""
msgid "Trigger was successfully updated."
-msgstr ""
+msgstr "Tetikleyici başarıyla güncellendi."
msgid "Triggerer"
msgstr ""
@@ -11893,17 +14145,32 @@ msgid "Try again?"
msgstr "Tekrar denensin mi?"
msgid "Try all GitLab has to offer for 30 days."
+msgstr "GitLab’ın sunduğu her şeyi 30 gün boyunca deneyin."
+
+msgid "Try to fork again"
msgstr ""
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "Servis Masasını Aç"
msgid "Twitter"
msgstr "Twitter"
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11913,24 +14180,42 @@ msgstr "İki adımlı kimlik doğrulama"
msgid "Type"
msgstr "Tür"
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11949,18 +14234,33 @@ msgstr ""
msgid "Unknown"
msgstr "Bilinmeyen"
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr "Kilidi aç"
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr "Kilitli"
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr "Çözülmeyen tartışma"
@@ -12030,12 +14330,24 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
-msgid "Updated"
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
msgstr ""
-msgid "Updated %{updated_at} by %{updated_by}"
+msgid "UpdateProject|Could not set the default branch"
msgstr ""
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr "Proje güncellenemedi!"
+
+msgid "Updated"
+msgstr "Güncellendi:"
+
+msgid "Updated %{updated_at} by %{updated_by}"
+msgstr "%{updated_by} tarafından %{updated_at} zamanında güncellendi"
+
msgid "Updating"
msgstr "Güncelleniyor"
@@ -12046,7 +14358,7 @@ msgid "Upgrade your plan"
msgstr ""
msgid "Upgrade your plan to activate Advanced Global Search."
-msgstr ""
+msgstr "Gelişmiş Genel aramayı etkinleştirmek için planınızı yükseltin."
msgid "Upgrade your plan to activate Contribution Analytics."
msgstr ""
@@ -12058,7 +14370,7 @@ msgid "Upgrade your plan to activate Issue weight."
msgstr ""
msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
+msgstr "Sorun panolarını geliştirmek için planınızı yükseltin."
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
@@ -12081,6 +14393,9 @@ msgstr "Sertifikanız için özel bir anahtar yükleyin"
msgid "Upload file"
msgstr "Dosya yükle"
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12090,6 +14405,9 @@ msgstr "yüklemek için tıklayın"
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12108,6 +14426,54 @@ msgstr ""
msgid "Usage statistics"
msgstr "Kullanım istatistikleri"
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12117,6 +14483,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12166,7 +14538,7 @@ msgid "User identity was successfully removed."
msgstr ""
msgid "User identity was successfully updated."
-msgstr ""
+msgstr "Kullanıcı kimliği başarıyla güncellendi."
msgid "User key was successfully removed."
msgstr ""
@@ -12174,8 +14546,11 @@ msgstr ""
msgid "User map"
msgstr "Kullanıcı haritası"
+msgid "User pipeline minutes were successfully reset."
+msgstr "Kullanıcı iş hattı kayıtları başarıyla sıfırlandı."
+
msgid "User settings"
-msgstr ""
+msgstr "Kullanıcı ayarları"
msgid "User was successfully created."
msgstr ""
@@ -12184,9 +14559,144 @@ msgid "User was successfully removed from group and any subresources."
msgstr ""
msgid "User was successfully removed from project."
-msgstr ""
+msgstr "Kullanıcı projeden başarıyla kaldırıldı."
msgid "User was successfully updated."
+msgstr "Kullanıcı başarıyla güncelleştirildi."
+
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
msgstr ""
msgid "UserProfile|Activity"
@@ -12214,7 +14724,7 @@ msgid "UserProfile|Join or create a group to start contributing by commenting on
msgstr "Konularda yorum veya birleştirme istekleri göndererek katkıda bulunmak için bir grup oluşturun veya katılın!"
msgid "UserProfile|Most Recent Activity"
-msgstr "En Son Etkinlik"
+msgstr "En son etkinlik"
msgid "UserProfile|No snippets found."
msgstr "Parçacık bulunamadı."
@@ -12262,7 +14772,16 @@ msgid "UserProfile|You haven't created any snippets."
msgstr "Herhangi bir parçacık oluşturmadınız."
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
-msgstr "Projeleriniz tercihen, genel ve dahili olarak yada anonim olarak kullanılabilir."
+msgstr "Projeleriniz istediğiniz gibi; genel ve dahili olarak yada gizli olarak kullanılabilir."
+
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
msgid "Users"
msgstr "Kullanıcılar"
@@ -12279,9 +14798,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12316,7 +14853,7 @@ msgid "Verification information"
msgstr "DoÄŸrulama bilgileri"
msgid "Verification status"
-msgstr ""
+msgstr "DoÄŸrulama durumu"
msgid "Verified"
msgstr "Doğrulanmış"
@@ -12327,12 +14864,18 @@ msgstr "Sürüm"
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12342,6 +14885,9 @@ msgstr ""
msgid "View file @ "
msgstr "Dosyayı görüntüle @ "
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr "Grup etiketlerini görüntüle"
@@ -12351,6 +14897,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr "GitLab'da görüntüle"
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12378,6 +14927,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr "Görünürlük ve erişim kontrolleri"
@@ -12388,7 +14940,7 @@ msgid "Visibility level:"
msgstr "Görünürlük seviyesi:"
msgid "Visibility, project features, permissions"
-msgstr ""
+msgstr "Görünürlük, proje özellikleri, izinler"
msgid "Visibility:"
msgstr "Görünürlük:"
@@ -12405,6 +14957,33 @@ msgstr "Genel"
msgid "VisibilityLevel|Unknown"
msgstr "Bilinmeyen"
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12447,6 +15026,9 @@ msgstr "Rapor Türü"
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -12465,6 +15047,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12474,6 +15059,9 @@ msgstr ""
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -12495,6 +15083,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr "Haftalar"
@@ -12504,13 +15095,16 @@ msgstr "Ağırlık"
msgid "Weight %{weight}"
msgstr "Ağırlık %{weight}"
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12524,6 +15118,9 @@ msgstr[1] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12534,10 +15131,10 @@ msgid "Wiki"
msgstr "Wiki"
msgid "Wiki was successfully updated."
-msgstr ""
+msgstr "Wiki başarıyla güncellendi."
msgid "WikiClone|Clone your wiki"
-msgstr "Wiki'nizi kopyalayın"
+msgstr "Viki'nizi kopyalayın"
msgid "WikiClone|Git Access"
msgstr "Git EriÅŸimi"
@@ -12642,7 +15239,7 @@ msgid "WikiPage|Write your content or drag files here…"
msgstr ""
msgid "Wiki|Create Page"
-msgstr "Sayfa OluÅŸtur"
+msgstr "Sayfa oluÅŸtur"
msgid "Wiki|Create page"
msgstr "Sayfa oluÅŸtur"
@@ -12651,10 +15248,10 @@ msgid "Wiki|Created date"
msgstr ""
msgid "Wiki|Edit Page"
-msgstr "Sayfayı Düzenle"
+msgstr "Sayfayı düzenle"
msgid "Wiki|More Pages"
-msgstr "Daha Fazla Sayfa"
+msgstr "Daha fazla sayfa"
msgid "Wiki|New page"
msgstr "Yeni sayfa"
@@ -12704,6 +15301,9 @@ msgstr ""
msgid "Yes"
msgstr "Evet"
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr "Evet, bunu ekle"
@@ -12719,7 +15319,13 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
@@ -12731,6 +15337,9 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12746,6 +15355,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12756,7 +15371,7 @@ msgid "You can also upload existing files from your computer using the instructi
msgstr ""
msgid "You can create files directly in GitLab using one of the following options."
-msgstr ""
+msgstr "Aşağıdaki seçeneklerden birini kullanarak dosyaları doğrudan GitLab'da oluşturabilirsiniz."
msgid "You can easily contribute to them by requesting to join these groups."
msgstr "Bu gruplara katılmayı talep ederek onlara kolayca katkıda bulunabilirsiniz."
@@ -12764,6 +15379,15 @@ msgstr "Bu gruplara katılmayı talep ederek onlara kolayca katkıda bulunabilir
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12788,9 +15412,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12821,12 +15451,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr "Herhangi bir uygulamanız yok"
@@ -12836,6 +15475,12 @@ msgstr "Herhangi bir yetkili uygulamanız yok"
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12866,6 +15511,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12878,6 +15532,9 @@ msgstr ""
msgid "You need permission."
msgstr "İzin almanız gerekli."
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12890,6 +15547,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12906,13 +15566,13 @@ msgid "You will only receive notifications for the events you choose"
msgstr "Yalnızca seçtiğiniz etkinlikler için bildirim alacaksınız"
msgid "You will only receive notifications for threads you have participated in"
-msgstr ""
+msgstr "Sadece katıldığınız konular için bildirimler alacaksınız"
msgid "You will receive notifications for any activity"
msgstr "Herhangi bir etkinlik için bildirim alacaksınız"
msgid "You will receive notifications only for comments in which you were @mentioned"
-msgstr ""
+msgstr "Yalnızca sizden @bahsedilen yorumlar için bildirim alacaksınız"
msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
msgstr ""
@@ -12923,6 +15583,9 @@ msgstr "Profilinize %{add_ssh_key_link} kadar proje kodunu SSH üzerinden çekem
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "Profilinize bir SSH anahtarı ekleyene kadar proje kodunu SSH üzerinden çekemez veya yollayamazsınız"
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12944,27 +15607,51 @@ msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr ""
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr "YouTube"
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr "Gruplarınız"
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr "Projeleriniz (öntanımlı)"
msgid "Your Projects' Activity"
msgstr "Projelerinizin EtkinliÄŸi"
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr "Yapacaklarınız"
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12998,7 +15685,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -13016,6 +15706,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr "Adınız"
@@ -13049,10 +15742,13 @@ msgstr "önce"
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
msgstr ""
-msgid "at"
+msgid "among other things"
msgstr ""
msgid "attach a new file"
@@ -13067,6 +15763,21 @@ msgstr "dal adı"
msgid "by"
msgstr "tarafından"
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13087,52 +15798,52 @@ msgstr ""
msgid "ciReport|%{reportType} %{status} detected %{dismissedCount} dismissed vulnerability"
msgid_plural "ciReport|%{reportType} %{status} detected %{dismissedCount} dismissed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{reportType} %{status} %{dismissedCount} reddedilen güvenlik açığı tespit edildi"
+msgstr[1] "%{reportType} %{status} %{dismissedCount} reddedilen güvenlik açığı tespit edildi"
msgid "ciReport|%{reportType} %{status} detected %{dismissedCount} dismissed vulnerability for the source branch only"
msgid_plural "ciReport|%{reportType} %{status} detected %{dismissedCount} dismissed vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{reportType} %{status} yalnızca kaynak dal için %{dismissedCount} reddedilen güvenlik açığı tespit edildi"
+msgstr[1] "%{reportType} %{status} yalnızca kaynak dal için %{dismissedCount} reddedilen güvenlik açığı tespit edildi"
msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{reportType} %{status} %{fixedCount} sabit güvenlik açığı tespit edildi"
+msgstr[1] "%{reportType} %{status} %{fixedCount} sabit güvenlik açığı tespit edildi"
msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed, and %{dismissedCount} dismissed vulnerabilities"
-msgstr ""
+msgstr "%{reportType} %{status} %{fixedCount} sabit ve %{dismissedCount} reddedilmiş güvenlik açığı tespit edildi"
msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{reportType} %{status} %{newCount} yeni güvenlik açığı tespit edildi"
+msgstr[1] "%{reportType} %{status} %{newCount} yeni güvenlik açığı tespit edildi"
msgid "ciReport|%{reportType} %{status} detected %{newCount} new, %{fixedCount} fixed, and %{dismissedCount} dismissed vulnerabilities"
-msgstr ""
+msgstr "%{reportType} %{status} %{newCount} yeni, %{fixedCount} sabit ve %{dismissedCount} reddedilmiş güvenlik açığı tespit edildi"
msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{dismissedCount} dismissed vulnerabilities"
-msgstr ""
+msgstr "%{reportType} %{status} %{newCount} yeni ve %{dismissedCount} reddedilmiş güvenlik açığı tespit edildi"
msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{dismissedCount} dismissed vulnerabilities for the source branch only"
-msgstr ""
+msgstr "%{reportType} %{status} yalnızca kaynak dal için %{newCount} yeni ve %{dismissedCount} reddedilen güvenlik açığı tespit etti"
msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
-msgstr ""
+msgstr "%{reportType} %{status} %{newCount} yeni ve %{fixedCount} sabit güvenlik tespit edildi"
msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{reportType} %{status} yalnızca kaynak dal için %{newCount} güvenlik açığı tespit edildi"
+msgstr[1] "%{reportType} %{status} yalnızca kaynak dal için %{newCount} güvenlik açığı tespit edildi"
msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
-msgstr ""
+msgstr "%{reportType} %{status} yeni güvenlik açığı tespit edilmedi"
msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
-msgstr ""
+msgstr "%{reportType} %{status} güvenlik açığı tespit edilmedi"
msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
-msgstr ""
+msgstr "%{reportType} %{status} yalnızca kaynak dal için hiçbir güvenlik açığı tespit edilmedi"
msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
@@ -13160,9 +15871,12 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|All projects"
+msgid "ciReport|All confidence levels"
msgstr ""
+msgid "ciReport|All projects"
+msgstr "Tüm projeler"
+
msgid "ciReport|All report types"
msgstr ""
@@ -13193,9 +15907,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13211,12 +15922,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr "Açıklama"
-msgid "ciReport|Dismiss vulnerability"
-msgstr "Güvenlik açığını reddet"
-
-msgid "ciReport|Dismissed by"
-msgstr "Reddeden:"
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13335,9 +16040,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13355,12 +16057,12 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr "Raporun tamamını görüntüle"
-msgid "ciReport|on pipeline"
-msgstr "iş hattında"
-
msgid "commented on %{link_to_project}"
msgstr "Yorumladı: %{link_to_project}"
+msgid "commit %{commit_id}"
+msgstr ""
+
msgid "confidence|Confirmed"
msgstr ""
@@ -13400,6 +16102,9 @@ msgstr "özel anahtar okunamadı, şifre doğru mu?"
msgid "customize"
msgstr "özelleştir"
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] "gün"
@@ -13430,9 +16135,15 @@ msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr "etkin"
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13445,6 +16156,12 @@ msgstr "hata kodu:"
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13469,6 +16186,9 @@ msgstr ""
msgid "group"
msgstr "grup"
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr "burada"
@@ -13498,6 +16218,12 @@ msgid_plural "instances completed"
msgstr[0] ""
msgstr[1] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13507,6 +16233,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13525,6 +16254,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13551,6 +16283,9 @@ msgid_plural "merge requests"
msgstr[0] "birleÅŸtirme isteÄŸi"
msgstr[1] "birleÅŸtirme isteÄŸi"
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13578,8 +16313,8 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
-msgstr "Onay ekle"
+msgid "mrWidget|Added to the merge train by"
+msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -13593,6 +16328,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "Onayınızı gönderirken bir hata oluştu."
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr "Onayla"
@@ -13603,7 +16341,7 @@ msgid "mrWidget|Approved by"
msgstr "Onaylandı"
msgid "mrWidget|Cancel automatic merge"
-msgstr "mrWidget|Otomatik birleÅŸtirmeyi iptal et"
+msgstr "Otomatik birleÅŸtirmeyi iptal et"
msgid "mrWidget|Check out branch"
msgstr "Dalı kontrol et"
@@ -13647,6 +16385,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13665,18 +16406,15 @@ msgstr "BirleÅŸtir"
msgid "mrWidget|Merge failed."
msgstr "Birleştirme başarısız."
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
+msgstr ""
+
msgid "mrWidget|Merge locally"
msgstr "Yerel olarak birleÅŸtir"
-msgid "mrWidget|Merge request approved"
-msgstr "Birleştirme isteği onaylandı"
-
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr "BirleÅŸtiren"
@@ -13707,22 +16445,12 @@ msgstr "Åžimdi yenile"
msgid "mrWidget|Refreshing now"
msgstr "Åžimdi yenileniyor"
-msgid "mrWidget|Remove your approval"
-msgstr "Onayınızı kaldırın"
+msgid "mrWidget|Remove from merge train"
+msgstr ""
msgid "mrWidget|Request to merge"
msgstr "BirleÅŸtirme isteÄŸi"
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13807,15 +16535,30 @@ msgstr "komut satırı"
msgid "mrWidget|into"
msgstr ""
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr "10 dakika ile 1 ay arasında olması gerekiyor"
+
msgid "new merge request"
msgstr "yeni birleÅŸtirme isteÄŸi"
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr "yok"
@@ -13925,7 +16668,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13934,18 +16677,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr "kaynak"
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr "başladı"
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13979,12 +16734,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr "GitLab'da görüntüle"
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/uk/gitlab.po b/locale/uk/gitlab.po
index c99fee40c16..aac293d531e 100644
--- a/locale/uk/gitlab.po
+++ b/locale/uk/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Ukrainian\n"
"Language: uk_UA\n"
"MIME-Version: 1.0\n"
@@ -13,19 +13,16 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: uk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-13 17:07\n"
+"PO-Revision-Date: 2019-06-14 10:20\n"
msgid " Please sign in."
-msgstr ""
-
-msgid " Status"
-msgstr " СтатуÑ"
+msgstr " Будь лаÑка, увійдіть."
msgid " Try to %{action} this file again."
-msgstr ""
+msgstr " Спробуйте %{action} цей файл знову."
msgid " You need to do this before %{grace_period_deadline}."
-msgstr ""
+msgstr " Ви повинні зробити це до %{grace_period_deadline}."
msgid " and"
msgstr " Ñ–"
@@ -77,6 +74,13 @@ msgstr[3] "%d комітів позаду"
msgid "%d commits"
msgstr "%d комітів"
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] "%d внеÑок"
+msgstr[1] "%d внеÑки"
+msgstr[2] "%d внеÑків"
+msgstr[3] "%d внеÑків"
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d екÑпортер"
@@ -126,6 +130,13 @@ msgstr[1] "%d запита на злиттÑ"
msgstr[2] "%d запитів на злиттÑ"
msgstr[3] "%d запитів на злиттÑ"
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d метрика"
@@ -133,6 +144,13 @@ msgstr[1] "%d метрики"
msgstr[2] "%d метрик"
msgstr[3] "%d метрик"
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] "ще %d коментар"
+msgstr[1] "ще %d коментарі"
+msgstr[2] "ще %d коментарів"
+msgstr[3] "ще %d коментарів"
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] "%d проіндекÑована зміна"
@@ -163,11 +181,8 @@ msgstr "ÐžÐ±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ %{authorsName}"
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} закомітив %{commit_timeago}"
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr "%{counter_storage} (%{counter_repositories} репозиторій, %{counter_build_artifacts} артефактів збірки, %{counter_lfs_objects} LFS)"
-
-msgid "%{count} %{alerts}"
-msgstr "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
+msgstr "%{counter_repositories} репозиторіїв, %{counter_wikis} вікі, %{counter_build_artifacts} артефактів збірки, %{counter_lfs_objects} об’єктів LFS"
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
@@ -205,6 +220,12 @@ msgstr[1] "%{count} коментарі в очікуванні"
msgstr[2] "%{count} коментарів в очікуванні"
msgstr[3] "%{count} коментарів в очікуванні"
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr "%{edit_in_new_fork_notice} Спробуйте вибрати (cherry-pick) цей коміт знову."
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr "%{edit_in_new_fork_notice} Спробуйте анулювати цей коміт знову."
+
msgid "%{filePath} deleted"
msgstr "%{filePath} видалено"
@@ -217,14 +238,26 @@ msgstr "%{gitlab_ci_yml} не знайдено в цьому коміті"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}Групи%{group_docs_link_end} дозволÑÑŽÑ‚ÑŒ вам керувати Ñ– взаємодіÑти між кількома проектами. Члени групи мають доÑтуп до уÑÑ–Ñ… Ñ—Ñ— проектів."
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr "%{group_name} викориÑтовує облікові запиÑи керовані групою. Вам необхідно Ñтворити новий обліковий Ð·Ð°Ð¿Ð¸Ñ GitLab, Ñкий буде керуватиÑÑ %{group_name}."
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} буде видалено! Ви впевнені?"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} недоÑтупний"
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} Ñ” безкоштовним, автоматизованим та відкритим центром Ñертифікації (CA), Ñкий випуÑкає цифрові Ñертифікати Ð´Ð»Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð½Ñ HTTPS (SSL/TLS) Ð´Ð»Ñ Ð²ÐµÐ±Ñайтів."
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr "%{level_name} не дозволено в %{group_level_name} групі."
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr "%{level_name} не допуÑкаєтьÑÑ, оÑкільки проект-джерело цього форку має нижчу видиміÑÑ‚ÑŒ."
+
msgid "%{level_name} visibility has been restricted by the administrator."
-msgstr ""
+msgstr "%{level_name} видиміÑÑ‚ÑŒ обмежена адмініÑтратором."
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "%{link_start}Читати більше%{link_end} про дозволи ролей"
@@ -236,7 +269,13 @@ msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} заблоковано кориÑтувачем GitLab %{lock_user_id}"
msgid "%{mrText}, this issue will be closed automatically."
-msgstr ""
+msgstr "%{mrText}, Ñ†Ñ Ð·Ð°Ð´Ð°Ñ‡Ð° буде закрита автоматично."
+
+msgid "%{name} contained %{resultsString}"
+msgstr "%{name} міÑтить %{resultsString}"
+
+msgid "%{name} found %{resultsString}"
+msgstr "%{name} знайдено %{resultsString}"
msgid "%{name}'s avatar"
msgstr "Ðватар %{name}"
@@ -251,13 +290,25 @@ msgid "%{percent}%% complete"
msgstr "%{percent}%% завершено"
msgid "%{service_title} activated."
-msgstr ""
+msgstr "%{service_title} активовано."
msgid "%{service_title} settings saved, but not activated."
-msgstr ""
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ %{service_title} збережено, але не активовано."
+
+msgid "%{size} GiB"
+msgstr "%{size} GiB"
+
+msgid "%{size} KiB"
+msgstr "%{size} KiB"
+
+msgid "%{size} MiB"
+msgstr "%{size} MiB"
+
+msgid "%{size} bytes"
+msgstr "%{size} байт"
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
-msgstr ""
+msgstr "%{spammable_titlecase} було уÑпішно відправлено до Akismet."
msgid "%{state} epics"
msgstr "%{state} епіки"
@@ -296,6 +347,9 @@ msgstr[3] "%{text} %{files} файлів"
msgid "%{text} is available"
msgstr "%{text} доÑтупний"
+msgid "%{title} %{operator} %{threshold}"
+msgstr "%{title} %{operator} %{threshold}"
+
msgid "%{title} changes"
msgstr "%{title} зміни"
@@ -308,9 +362,31 @@ msgstr "%{usage_ping_link_start}ДовідатиÑÑŒ більше%{usage_ping_li
msgid "%{user_name} profile page"
msgstr "%{user_name} Ñторінка профілю"
-msgid "(No changes)"
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr "%{verb} %{time_spent_value} витрачено чаÑу."
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr "\"%{level}\" не Ñ” допуÑтимим рівнем видимоÑÑ‚Ñ–"
+
+msgid "'%{source}' is not a import source"
+msgstr "\"%{source}\" не є джерелом імпорту"
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "(%{mrCount} merged)"
msgstr ""
+msgid "(No changes)"
+msgstr "(Ðемає змін)"
+
+msgid "(check progress)"
+msgstr "(перевірити прогреÑ)"
+
msgid "(external source)"
msgstr "(зовнішнє джерело)"
@@ -335,6 +411,9 @@ msgstr "- Runner призупинено і він не зможе виконув
msgid "- show less"
msgstr "- показати менше"
+msgid "0 for unlimited"
+msgstr "0 Ð´Ð»Ñ Ð½ÐµÐ¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð¾Ð³Ð¾"
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] "1 %{type} доповненнÑ"
@@ -357,21 +436,21 @@ msgstr[2] "%d днів"
msgstr[3] "%d днів"
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] "1 закрита задача"
-msgstr[1] "%d закриті задачі"
-msgstr[2] "%d закритих задач"
-msgstr[3] "%d закритих задач"
+msgstr[1] "%{issues} закриті задачі"
+msgstr[2] "%{issues} закритих задач"
+msgstr[3] "%{issues} закритих задач"
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] "1 закритий запит на злиттÑ"
-msgstr[1] "%d закритих запити на злиттÑ"
-msgstr[2] "%d закритих запитів на злиттÑ"
-msgstr[3] "%d закритих запитів на злиттÑ"
+msgstr[1] "%{merge_requests} закритих запити на злиттÑ"
+msgstr[2] "%{merge_requests} закритих запитів на злиттÑ"
+msgstr[3] "%{merge_requests} закритих запитів на злиттÑ"
msgid "1 day"
-msgstr ""
+msgstr "1 день"
msgid "1 group"
msgid_plural "%d groups"
@@ -381,25 +460,25 @@ msgstr[2] "%d груп"
msgstr[3] "%d груп"
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] "1 заÑтоÑований запит на злиттÑ"
-msgstr[1] "%d заÑтоÑованих запити на злиттÑ"
-msgstr[2] "%d заÑтоÑованих запитів на злиттÑ"
-msgstr[3] "%d заÑтоÑованих запитів на злиттÑ"
+msgstr[1] "%{merge_requests} заÑтоÑованих запити на злиттÑ"
+msgstr[2] "%{merge_requests} заÑтоÑованих запитів на злиттÑ"
+msgstr[3] "%{merge_requests} заÑтоÑованих запитів на злиттÑ"
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] "1 відкрита задача"
-msgstr[1] "%d відкриті задачі"
-msgstr[2] "%d відкритих задач"
-msgstr[3] "%d відкритих задач"
+msgstr[1] "%{issues} відкриті задачі"
+msgstr[2] "%{issues} відкритих задач"
+msgstr[3] "%{issues} відкритих задач"
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
+msgid_plural "%{merge_requests} open merge requests"
msgstr[0] "1 відкритий запит на злиттÑ"
-msgstr[1] "%d відкритих запити на злиттÑ"
-msgstr[2] "%d відкритих запитів на злиттÑ"
-msgstr[3] "%d відкритих запитів на злиттÑ"
+msgstr[1] "%{merge_requests} відкритих запити на злиттÑ"
+msgstr[2] "%{merge_requests} відкритих запитів на злиттÑ"
+msgstr[3] "%{merge_requests} відкритих запитів на злиттÑ"
msgid "1 pipeline"
msgid_plural "%d pipelines"
@@ -423,25 +502,40 @@ msgstr[2] "%d кориÑтувачів"
msgstr[3] "%d кориÑтувачів"
msgid "1 week"
-msgstr ""
+msgstr "1 тиждень"
+
+msgid "1-9 contributions"
+msgstr "1-9 внеÑків"
+
+msgid "10-19 contributions"
+msgstr "10-19 внеÑків"
msgid "1st contribution!"
msgstr "Перший внеÑок!"
+msgid "20-29 contributions"
+msgstr "20-29 внеÑків"
+
msgid "2FA"
msgstr "двофакторна автентифікаціÑ"
msgid "2FA enabled"
msgstr "Двофакторна Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð°"
+msgid "2FADevice|Registered On"
+msgstr "ЗареєÑтровано"
+
msgid "3 days"
-msgstr ""
+msgstr "3 дні"
msgid "3 hours"
-msgstr ""
+msgstr "3 години"
msgid "30 minutes"
-msgstr ""
+msgstr "30 хвилин"
+
+msgid "30+ contributions"
+msgstr "30+ внеÑків"
msgid "403|Please contact your GitLab administrator to get permission."
msgstr "Будь лаÑка, звернітьÑÑ Ð´Ð¾ адмініÑтратора GitLab, щоб отримати дозвіл."
@@ -459,7 +553,7 @@ msgid "404|Please contact your GitLab administrator if you think this is a mista
msgstr "Будь лаÑка, звернітьÑÑ Ð´Ð¾ адмініÑтратора GitLab, Ñкщо ви вважаєте, що це помилка."
msgid "8 hours"
-msgstr ""
+msgstr "8 годин"
msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
msgstr "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> додаÑÑ‚ÑŒ \"<a href=\"#\">@johnsmith</a>\" до вÑÑ–Ñ… задач та коментарів, що були Ñтворені johnsmith@example.com, а також призначить на <a href=\"#\">@johnsmith</a> уÑÑ– задачі, Ñкі були призначені на на johnsmith@example.com."
@@ -473,6 +567,9 @@ msgstr "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> дод
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> додаÑÑ‚ÑŒ \"<a href=\"#\">johnsmith@example.com</a>\" до вÑÑ–Ñ… задач та коментарів, Ñкі були Ñтворені johnsmith@example.com. За замовчуваннÑм Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача та його електронна адреÑа заблоковані Ð´Ð»Ñ Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑ‡ÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ñ„Ñ–Ð´ÐµÐ½Ñ†Ñ–Ð¹Ð½Ð¾ÑÑ‚Ñ–. ВикориÑтовуйте цю опцію, Ñкщо ви хочете показувати електронну адреÑу повніÑÑ‚ÑŽ."
+msgid "<no name set>"
+msgstr "<Ñ–Ð¼â€™Ñ Ð½Ðµ задане>"
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr "<strong>%{changedFilesLength} неіндекÑованих</strong> та <strong>%{stagedFilesLength} індекÑованих</strong> змін"
@@ -509,26 +606,26 @@ msgstr "Сайт Hugo, Ñкий викориÑтовує Netlify Ð´Ð»Ñ CI/CD з
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr "Сайт Jekyll, Ñкий викориÑтовує Netlify Ð´Ð»Ñ CI/CD заміÑÑ‚ÑŒ GitLab, але вÑе ще з уÑіма іншими чудовими функціÑми GitLab."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
+msgstr "Обліковий Ð·Ð°Ð¿Ð¸Ñ Let's Encrypt буде налаштовано Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— інÑталÑції GitLab за допомогою вашої адреÑи електронної пошти. Ви будете отримувати лиÑти Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ñ‚ÐµÑ€Ð¼Ñ–Ð½Ñƒ дії Ñертифікатів."
+
msgid "A default branch cannot be chosen for an empty project."
msgstr "Гілку за замовчуваннÑм не може бути обрано Ð´Ð»Ñ Ð¿Ð¾Ñ€Ð¾Ð¶Ð½ÑŒÐ¾Ð³Ð¾ проекту."
msgid "A deleted user"
msgstr "Видалений кориÑтувач"
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr "УчаÑник команди GitLab по боротьбі з порушеннÑми розглÑне ваш звіт Ñкомога швидше."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
+msgstr "Форк - це ÐºÐ¾Ð¿Ñ–Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñƒ.<br />Форк репозиторію дозволÑÑ” вноÑити зміни без впливу на оригінальний проект."
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
-msgstr ""
-
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
-msgstr ""
+msgid "A member of the abuse team will review your report as soon as possible."
+msgstr "УчаÑник команди по боротьбі з порушеннÑми розглÑне ваш звіт Ñкомога швидше."
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr "У вашому форку буде Ñтворено нову гілку, а також буде ініційований новий запит на злиттÑ."
msgid "A new impersonation token has been created."
-msgstr ""
+msgstr "Створено новий токен імітуваннÑ."
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr "Сайт на HTML, Ñкий викориÑтовує Netlify Ð´Ð»Ñ CI/CD заміÑÑ‚ÑŒ GitLab, але вÑе ще з уÑіма іншими чудовими функціÑми GitLab."
@@ -549,7 +646,10 @@ msgid "A user with write access to the source branch selected this option"
msgstr "КориÑтувач із правом запиÑу в гілку-джерело вибрав цей варіант"
msgid "API Help"
-msgstr ""
+msgstr "Довідка API"
+
+msgid "API Token"
+msgstr "API-токен"
msgid "About GitLab"
msgstr "Про GitLab"
@@ -582,7 +682,7 @@ msgid "Access Tokens"
msgstr "Токени доÑтупу"
msgid "Access denied for your LDAP account."
-msgstr ""
+msgstr "ДоÑтуп до вашого облікового запиÑу LDAP заборонено."
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "ДоÑтуп заборонено! Будь-лаÑка, перевірте, чи ви можете додавати ключі Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾ цього Ñховища."
@@ -591,22 +691,34 @@ msgid "Access expiration date"
msgstr "Дата Ð¿Ñ€Ð¸Ð¿Ð¸Ð½ÐµÐ½Ð½Ñ Ð´Ð¾Ñтупу"
msgid "Access forbidden. Check your access level."
-msgstr ""
+msgstr "ДоÑтуп заборонено. Перевірте рівень доÑтупу."
msgid "Access to '%{classification_label}' not allowed"
msgstr "ДоÑтуп до \"%{classification_label}\" заборонено"
+msgid "AccessDropdown|Groups"
+msgstr "Групи"
+
+msgid "AccessDropdown|Roles"
+msgstr "Ролі"
+
+msgid "AccessDropdown|Users"
+msgstr "КориÑтувачі"
+
msgid "Account"
msgstr "Обліковий запиÑ"
msgid "Account and limit"
msgstr "Обліковий Ð·Ð°Ð¿Ð¸Ñ Ñ‚Ð° ліміт"
+msgid "Account: %{account}"
+msgstr "Обліковий запиÑ: %{account}"
+
msgid "Action to take when receiving an alert."
msgstr "Дії Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸ отриманні попередженнÑ."
msgid "Activate Service Desk"
-msgstr ""
+msgstr "Ðктивувати Службу підтримки"
msgid "Active"
msgstr "Ðктивний"
@@ -627,7 +739,7 @@ msgid "Add CONTRIBUTING"
msgstr "Додати CONTRIBUTING"
msgid "Add Group Webhooks and GitLab Enterprise Edition."
-msgstr "Додайте групові веб-гуки та GitLab Enterprise Edition."
+msgstr "Додайте групові веб-хуки та GitLab Enterprise Edition."
msgid "Add Jaeger URL"
msgstr "Додати URL-адреÑу Jaeger"
@@ -638,6 +750,9 @@ msgstr "Додати Kubernetes-клаÑтер"
msgid "Add README"
msgstr "Додати інÑтрукцію (README)"
+msgid "Add a GPG key"
+msgstr "Додати GPG ключ"
+
msgid "Add a bullet list"
msgstr "Додати ненумерований ÑпиÑок"
@@ -659,11 +774,17 @@ msgstr "Додати таблицю"
msgid "Add a task list"
msgstr "Додати ÑпиÑок завдань"
+msgid "Add a todo"
+msgstr "Додати нагадуваннÑ"
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Створіть додатковий текÑÑ‚, Ñкий буде приÑутній у вÑÑ–Ñ… повідомленнÑÑ… електронної пошти. МакÑимальна кількіÑÑ‚ÑŒ Ñимволів — %{character_limit}"
-msgid "Add approver(s)"
-msgstr "Додати затверджуючих оÑіб"
+msgid "Add an SSH key"
+msgstr "Додати SSH ключ"
+
+msgid "Add an issue"
+msgstr "Додати задачу"
msgid "Add approvers"
msgstr "Додати затверджуючих оÑіб"
@@ -671,9 +792,15 @@ msgstr "Додати затверджуючих оÑіб"
msgid "Add bold text"
msgstr "Додати жирний текÑÑ‚"
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr "Додати коментар"
+msgid "Add email address"
+msgstr "Додати email адреÑу"
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "Додати заголовок Ñ– футер в електронні лиÑти. Будь лаÑка, зверніть увагу, що Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñƒ будуть викориÑтовуватиÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ в інтерфейÑÑ– заÑтоÑунку"
@@ -683,11 +810,14 @@ msgstr "Додати коментар до зображеннÑ"
msgid "Add italic text"
msgstr "Додати курÑивний текÑÑ‚"
+msgid "Add label(s)"
+msgstr "Додати мітку(-ки)"
+
msgid "Add license"
msgstr "Додати ліцензію"
msgid "Add list"
-msgstr ""
+msgstr "Додати ÑпиÑок"
msgid "Add new application"
msgstr "Додати новий додаток"
@@ -695,9 +825,18 @@ msgstr "Додати новий додаток"
msgid "Add new directory"
msgstr "Додати новий каталог"
+msgid "Add or subtract spent time"
+msgstr "Додати або віднÑти витрачений чаÑ"
+
msgid "Add reaction"
msgstr "Додати реакцію"
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr "Додати до проекту"
@@ -710,24 +849,36 @@ msgstr "Додати нагадуваннÑ"
msgid "Add user(s) to the group:"
msgstr "Додати кориÑтувачів до групу:"
-msgid "Add users or groups who are allowed to approve every merge request"
-msgstr "Додайте кориÑтувачів або групи, Ñким дозволено затверджувати будь-Ñкий запит на злиттÑ"
-
msgid "Add users to group"
msgstr "Додати кориÑтувача до групи"
+msgid "AddMember|No users specified."
+msgstr "Жодного кориÑтувача не вказано."
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
+msgstr "Вказано занадто багато кориÑтувачів (ліміт — %{user_limit})"
+
msgid "Added at"
msgstr "Додано"
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð½Ð¾Ð²Ð¸Ñ… проектів Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ інÑтанÑу GitLab заборонено. ЗвернітьÑÑ Ð´Ð¾ Ñвого адмініÑтратора GitLab, щоб отримати дозвіл"
+msgid "Additional minutes"
+msgstr "Додаткові хвилини"
+
msgid "Additional text"
msgstr "Додатковий текÑÑ‚"
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr "Додає"
+
+msgid "Adds %{epic_ref} as child epic."
msgstr ""
+msgid "Adds a todo."
+msgstr "Додає нагадуваннÑ."
+
msgid "Admin Area"
msgstr "ОблаÑÑ‚ÑŒ адмініÑтратора"
@@ -735,7 +886,10 @@ msgid "Admin Overview"
msgstr "ОглÑд адмініÑтратора"
msgid "Admin Section"
-msgstr ""
+msgstr "Розділ ÐдмініÑтруваннÑ"
+
+msgid "Admin notes"
+msgstr "Ðотатки адмініÑтратора"
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити кориÑтувача %{username}. Пов’Ñзані з ним задачі, запити на злиттÑ, Ñ– групи будуть переведені на ÑиÑтемного кориÑтувача \"Ghost-user\". Щоб уникнути втрати даних, розглÑньте можливіÑÑ‚ÑŒ %{strong_start}Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача%{strong_end} заміÑÑ‚ÑŒ видаленнÑ. ПіÑÐ»Ñ %{strong_start}Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача%{strong_end}, його неможливо буде відновити."
@@ -758,6 +912,9 @@ msgstr "Зупинка завдань пройшла невдало"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "Зараз ви зупинете вÑÑ– завданнÑ. Це обірве уÑÑ– запущені завданнÑ."
+msgid "AdminNote|Note"
+msgstr "Примітка"
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити проект %{projectName}, його репозиторій та вÑÑ– пов'Ñзані реÑурÑи, включаючи задачі, запити на злиттÑ, тощо. ПіÑÐ»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ‚Ð° натиÑÐ½ÐµÐ½Ð½Ñ Ð½Ð° кнопку %{strong_start}Видалити проект%{strong_end}, його неможливо буде відновити."
@@ -864,7 +1021,7 @@ msgid "Advanced permissions, Large File Storage and Two-Factor authentication se
msgstr "Додаткові дозволи, Ñховище великих файлів (LFS) Ñ– Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð²Ð¾Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾Ñ— автентифікації."
msgid "Advanced search functionality"
-msgstr ""
+msgstr "Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð¾Ð³Ð¾ пошуку"
msgid "Advanced settings"
msgstr "Додаткові параметри"
@@ -872,6 +1029,9 @@ msgstr "Додаткові параметри"
msgid "After a successful password update you will be redirected to login screen."
msgstr "ПіÑÐ»Ñ ÑƒÑпішного Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð²Ð¸ перейдете на екран входу."
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "ПопередженнÑ"
@@ -891,23 +1051,32 @@ msgstr "Ð’ÑÑ– учаÑники"
msgid "All changes are committed"
msgstr "Ð’ÑÑ– зміни закомічені"
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Ð’ÑÑ– функції Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… проектів берутьÑÑ Ñ–Ð· шаблонів або під Ñ‡Ð°Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ, але ви можете вимикати Ñ—Ñ… пізніше в налаштуваннÑÑ… проекту."
+msgid "All groups and projects"
+msgstr "Ð’ÑÑ– групи та проекти"
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr "Ð’ÑÑ– задачі Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ етапу закриті. Ви можете закрити цей етап."
msgid "All merge conflicts were resolved. The merge request can now be merged."
-msgstr ""
+msgstr "УÑÑ– конфлікти Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ð¸Ñ€Ñ–ÑˆÐµÐ½Ð¾. Тепер запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¼Ð¾Ð¶Ð½Ð° об'єднати."
+
+msgid "All projects"
+msgstr "Ð’ÑÑ– проекти"
msgid "All todos were marked as done."
-msgstr ""
+msgstr "Ð’ÑÑ– Ð½Ð°Ð³Ð°Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ñ– Ñк виконані."
msgid "All users"
msgstr "Ð’ÑÑ– кориÑтувачі"
msgid "All users must have a name."
-msgstr ""
+msgstr "Ð’ÑÑ– кориÑтувачі повинні мати імена."
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "Дозволити вхід через \"%{group_name}\""
@@ -934,7 +1103,7 @@ msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
msgstr "Дозволити Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ñ–Ð°Ð³Ñ€Ð°Ð¼ PlantUML в документах Asciidoc."
msgid "Allow requests to the local network from hooks and services."
-msgstr "Дозволити запити до локальної мережі із гуків та ÑервіÑів."
+msgstr "Дозволити запити до локальної мережі із хуків та ÑервіÑів."
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr "Дозволити цьому ключеві також відправлÑти зміни в репозиторій? (За замовчуваннÑм дозволÑєтьÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ отримувати.)"
@@ -972,9 +1141,6 @@ msgstr "Крім того, ви можете викориÑтовувати %{pe
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr "Ð§Ð°Ñ (в годинах), впродовж Ñкого кориÑтувачам дозволено пропуÑкати примуÑове Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð²Ð¾Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾Ñ— автентифікації"
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr "ПіÑÐ»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ„Ð¾Ñ€Ð¼Ð¸ буде автоматично згенеровано SSH ключ. Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації, звернітьÑÑ Ð´Ð¾ документіції."
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr "Додаток під назвою %{link_to_client} запитує доÑтуп до вашого GitLab аккаунту."
@@ -1008,12 +1174,15 @@ msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ пÐ
msgid "An error occurred when toggling the notification subscription"
msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð·Ð¼Ñ–Ð½Ð¸ підпиÑки на ÑповіщеннÑ"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr "Помилка при вирішенні коментарÑ. Будь лаÑка, Ñпробуйте знову."
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr "Помилка при вирішенні обговореннÑ. Будь лаÑка, Ñпробуйте знову."
+
msgid "An error occurred when updating the issue weight"
msgstr "Збій під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ð°Ð³Ð¸ задачі"
-msgid "An error occurred while adding approver"
-msgstr "Помилка при додаванні затверджуючої оÑоби"
-
msgid "An error occurred while deleting the approvers group"
msgstr "Помилка при видаленні групи затверджуючих оÑіб"
@@ -1024,7 +1193,7 @@ msgid "An error occurred while detecting host keys"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при виÑвленні ключів хоÑта"
msgid "An error occurred while disabling Service Desk."
-msgstr ""
+msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð¡Ð»ÑƒÐ¶Ð±Ð¸ підтримки."
msgid "An error occurred while dismissing the alert. Refresh the page and try again."
msgstr "Помилка при відхиленні попередженнÑ. Оновіть Ñторінку та Ñпробуйте знову."
@@ -1033,7 +1202,16 @@ msgid "An error occurred while dismissing the feature highlight. Refresh the pag
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при відхиленні Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ функцію. Оновіть Ñторінку Ñ– Ñпробуйте знову."
msgid "An error occurred while enabling Service Desk."
-msgstr ""
+msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð¡Ð»ÑƒÐ¶Ð±Ð¸ підтримки."
+
+msgid "An error occurred while fetching environments."
+msgstr "Помилка при отриманні Ñередовищ."
+
+msgid "An error occurred while fetching folder content."
+msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні вміÑту папки."
+
+msgid "An error occurred while fetching label colors."
+msgstr "Помилка при отриманні кольорів міток."
msgid "An error occurred while fetching markdown preview"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при попередньому переглÑді markdown"
@@ -1041,14 +1219,20 @@ msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при попередньому перег
msgid "An error occurred while fetching pending comments"
msgstr "Помилка при отриманні коментарів в очікуванні"
+msgid "An error occurred while fetching projects autocomplete."
+msgstr "Помилка при отриманні Ð°Ð²Ñ‚Ð¾Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñ–Ð²."
+
msgid "An error occurred while fetching sidebar data"
msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… Ð´Ð»Ñ Ð±Ñ–Ñ‡Ð½Ð¾Ñ— панелі"
-msgid "An error occurred while fetching stages."
-msgstr "Помилка при отриманні Ñтадій."
-
msgid "An error occurred while fetching the Service Desk address."
-msgstr ""
+msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð°Ð´Ñ€ÐµÑи Служби підтримки."
+
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr "Помилка при отриманні ÑпиÑків дошки. Будь лаÑка, Ñпробуйте знову."
+
+msgid "An error occurred while fetching the builds."
+msgstr "Помилка при отриманні збірок."
msgid "An error occurred while fetching the job log."
msgstr "Помилка при отриманні логів завданнÑ."
@@ -1065,6 +1249,9 @@ msgstr "Помилка при отриманні данних конвеєра."
msgid "An error occurred while fetching the releases. Please try again."
msgstr "Помилка при отриманні релізів. Будь лаÑка, Ñпробуйте знову."
+msgid "An error occurred while fetching this tab."
+msgstr "Помилка при отриманні цієї вкладки."
+
msgid "An error occurred while getting projects"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні проектів"
@@ -1081,7 +1268,7 @@ msgid "An error occurred while loading commit signatures"
msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при завантаженні підпиÑів комітів"
msgid "An error occurred while loading designs. Please try again."
-msgstr ""
+msgstr "Помилка при завантаженні дизайнів. Будь лаÑка, Ñпробуйте знову."
msgid "An error occurred while loading diff"
msgstr "Помилка при завантаженні разниці (diff)"
@@ -1098,8 +1285,11 @@ msgstr "Помилка при завантаженні даних підпиÑк
msgid "An error occurred while making the request."
msgstr "Помилка при Ñтворенні запиту."
-msgid "An error occurred while removing approver"
-msgstr "Помилка при видаленні затверджуючої оÑоби"
+msgid "An error occurred while moving the issue."
+msgstr "Помилка при переміщенні задачі."
+
+msgid "An error occurred while parsing recent searches"
+msgstr "Помилка при обробці Ñ–Ñторії пошуків"
msgid "An error occurred while removing epics."
msgstr "Помилка при видаленні епіків."
@@ -1152,6 +1342,9 @@ msgstr "Помилка при отриманні логу завданнÑ."
msgid "An error occurred whilst fetching the latest pipeline."
msgstr "Помилка при отриманні оÑтаннього конвеєра."
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні файлів Ð´Ð»Ñ - %{branchId}"
+
msgid "An error occurred whilst loading all the files."
msgstr "Помилка при завантаженні вÑÑ–Ñ… файлів."
@@ -1209,17 +1402,29 @@ msgstr "Будь-Ñкий"
msgid "Any Label"
msgstr "Будь-Ñка мітка"
+msgid "Any Milestone"
+msgstr "Будь-Ñкий етап"
+
msgid "Any encrypted tokens"
-msgstr ""
+msgstr "Будь-Ñкі зашифровані токени"
+
+msgid "Any namespace"
+msgstr "Будь-Ñкий проÑÑ‚Ñ–Ñ€ імен"
msgid "Appearance"
msgstr "Зовнішній виглÑд"
msgid "Appearance was successfully created."
-msgstr ""
+msgstr "ВиглÑд уÑпішно Ñтворено."
msgid "Appearance was successfully updated."
-msgstr ""
+msgstr "ВиглÑд уÑпішно оновлено."
+
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr "Додати коментар з %{TABLEFLIP}"
+
+msgid "Append the comment with %{shrug}"
+msgstr "Додати коментар з %{shrug}"
msgid "Application"
msgstr "Додаток"
@@ -1228,13 +1433,16 @@ msgid "Application ID"
msgstr "Ідентифікатор заÑтоÑунку"
msgid "Application settings saved successfully"
-msgstr ""
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°ÑтоÑунку уÑпішно збережено"
+
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr "ЗаÑтоÑунок видалено, але не вдалоÑÑ Ð·Ð½Ð¸Ñ‰Ð¸Ñ‚Ð¸: %{error_message}"
msgid "Application was successfully destroyed."
-msgstr ""
+msgstr "ЗаÑтоÑунок було уÑпішно знищено."
msgid "Application was successfully updated."
-msgstr ""
+msgstr "ЗаÑтоÑунок було уÑпішно оновлено."
msgid "Application: %{name}"
msgstr "Додаток: %{name}"
@@ -1248,6 +1456,18 @@ msgstr "ЗаÑтоÑовано"
msgid "Apply suggestion"
msgstr "ЗаÑтоÑувати пропозицію"
+msgid "Applying command"
+msgstr "Ð’Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð¸"
+
+msgid "Applying command to %{commandDescription}"
+msgstr "Ð’Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð¸ Ð´Ð»Ñ %{commandDescription}"
+
+msgid "Applying multiple commands"
+msgstr "Ð’Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð´ÐµÐºÑ–Ð»ÑŒÐºÐ¾Ñ… команд"
+
+msgid "Applying suggestion"
+msgstr "ЗаÑтоÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ñ—"
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] "%d учаÑник"
@@ -1297,12 +1517,6 @@ msgstr "наприклад QA, безпека і т. д."
msgid "Approvals"
msgstr "ЗатвердженнÑ"
-msgid "Approvals required"
-msgstr "Потрібні затвердженнÑ"
-
-msgid "Approvers"
-msgstr "Затверджуючі оÑоби"
-
msgid "Apr"
msgstr "квіт."
@@ -1313,7 +1527,7 @@ msgid "Archive jobs"
msgstr "Ðрхівувати завданнÑ"
msgid "Archive project"
-msgstr ""
+msgstr "Ðрхівувати проект"
msgid "Archived project! Repository and other project resources are read-only"
msgstr "Ðрхівований проект! Репозиторій та інші реÑурÑи проекту доÑтупні лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ"
@@ -1322,16 +1536,28 @@ msgid "Archived projects"
msgstr "Заархівовані проекти"
msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. <strong>The repository cannot be committed to, and no issues, comments or other entities can be created.</strong>"
-msgstr ""
+msgstr "ÐÑ€Ñ…Ñ–Ð²ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñƒ зробить його доÑтупним лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ. Він буде прихований з панелі ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ– не відображатиметьÑÑ Ð² пошуках. <strong>Ð’ репозиторій не можна буде комітити, Ñ– не можливо буде Ñтворити жодних задач, коментарів чи інших об'єктів.</strong>"
msgid "Are you sure"
msgstr "Ви впевнені"
msgid "Are you sure that you want to archive this project?"
-msgstr ""
+msgstr "Ви впевнені, що хочете заархівувати цей проект?"
msgid "Are you sure that you want to unarchive this project?"
-msgstr ""
+msgstr "Ви впевнені, що хочете розархівувати цей проект?"
+
+msgid "Are you sure you want to cancel creating this comment?"
+msgstr "Ви впевнені, що хочете ÑкаÑувати цей коментар?"
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr "Ви впевнені, що хочете ÑкаÑувати Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ коментарÑ?"
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
+msgstr "Ви впевнені, що хочете видалити цей приÑтрій? Цю дію неможливо ÑкаÑувати."
+
+msgid "Are you sure you want to delete this list?"
+msgstr "Ви впевнені у тому, що хочете видалити цей ÑпиÑок?"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Ви впевнені, що хочете видалити цей розклад Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ð°?"
@@ -1346,7 +1572,7 @@ msgid "Are you sure you want to lose your issue information?"
msgstr "Ви впевнені, що хочете втратити інформацію про задачу?"
msgid "Are you sure you want to permanently delete this license?"
-msgstr ""
+msgstr "Ви дійÑно бажаєте оÑтаточно видалити цю ліцензію?"
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr "Ви впевнені, що хочете повторно згенерувати відкритий ключ? Вам доведетьÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ відкритий ключ на віддаленому Ñервері, перш ніж Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÑŽÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ñ€Ð°Ñ†ÑŽÑ” знову."
@@ -1354,18 +1580,6 @@ msgstr "Ви впевнені, що хочете повторно згенеру
msgid "Are you sure you want to remove %{group_name}?"
msgstr "Ви впевнені, що хочете видалити %{group_name}?"
-msgid "Are you sure you want to remove approver %{name}"
-msgstr "Ви впевнені, що хочете видалити затверджуючу оÑобу %{name}"
-
-msgid "Are you sure you want to remove approver %{name}?"
-msgstr "Ви впевнені, що хочете видалити затверджуючу оÑобу %{name}?"
-
-msgid "Are you sure you want to remove group %{name}"
-msgstr "Ви впевнені, що хочете видалити групу %{name}"
-
-msgid "Are you sure you want to remove group %{name}?"
-msgstr "Ви впевнені, що хочете видалити групу %{name}?"
-
msgid "Are you sure you want to remove the attachment?"
msgstr "Ви впевнені, що бажаєте видалити вкладеннÑ?"
@@ -1376,11 +1590,14 @@ msgid "Are you sure you want to reset registration token?"
msgstr "Ви впевнені, що бажаєте перегенерувати реєÑтраційний токен?"
msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
+msgstr "Ви впевнені, що хочете Ñкинути токен SCIM? Ð’Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ SCIM переÑтане працювати доти, поки новий токен не буде оновлено."
msgid "Are you sure you want to reset the health check token?"
msgstr "Ви впевнені, що Ви хочете перегенерувати цей ключ перевірки працездатноÑÑ‚Ñ–?"
+msgid "Are you sure you want to revoke this nickname?"
+msgstr "Ви впевнені, що хочете ÑкаÑувати цей пÑевдонім?"
+
msgid "Are you sure you want to stop this environment?"
msgstr "Ви впевнені що хочете зупинити це Ñередовище?"
@@ -1393,12 +1610,36 @@ msgstr "Ви дійÑно бажаєте ÑкаÑувати підпиÑку нÐ
msgid "Are you sure?"
msgstr "Ви впевнені?"
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr "ID артефакту"
msgid "Artifacts"
msgstr "Ðртефакти"
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr "%{user} відправив код в гілку %{branch} проекту %{project_name} (%{commit_url}):"
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr "Asana — командна робота без електронної пошти"
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr "Розділений комами ÑпиÑок гілок, Ñкі будуть автоматично перевірÑтиÑÑ. Залиште порожнім, щоб включити уÑÑ– гілки."
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr "ОÑобиÑтий токен доÑтупу кориÑтувача. КориÑтувач повинен мати доÑтуп до завданнÑ, уÑÑ– коментарі будуть відноÑитиÑÑ Ð´Ð¾ нього."
+
msgid "Ascending"
msgstr "За зроÑтаннÑм"
@@ -1411,6 +1652,9 @@ msgstr "URL-адреÑа Ñлужби обробника тверджень"
msgid "Assets"
msgstr "РеÑурÑи"
+msgid "Assign"
+msgstr "Призначити"
+
msgid "Assign custom color like #FF0000"
msgstr "Призначити влаÑний колір типу #FF0000"
@@ -1426,6 +1670,12 @@ msgstr "Призначити деÑкі задачі до цього етапу.
msgid "Assign to"
msgstr "Призначити"
+msgid "Assign yourself to these issues"
+msgstr "Призначити ці задачі Ñобі"
+
+msgid "Assign yourself to this issue"
+msgstr "Призначити цю задачу Ñобі"
+
msgid "Assigned Issues"
msgstr "Призначені задачі"
@@ -1456,6 +1706,16 @@ msgstr "Прикріпити файл"
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Прикріпити файл за допомогою перетÑÐ³ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ %{upload_link}"
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ"
+msgstr[1] "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ %d файлів"
+msgstr[2] "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ %d файлів"
+msgstr[3] "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ %d файлів"
+
+msgid "Attaching the file failed."
+msgstr "Ðе вдалоÑÑ Ð¿Ñ€Ð¸ÐºÑ€Ñ–Ð¿Ð¸Ñ‚Ð¸ файл."
+
msgid "Audit Events"
msgstr "Події аудиту"
@@ -1469,7 +1729,7 @@ msgid "Authentication Log"
msgstr "Журнал автентифікації"
msgid "Authentication failed: %{error_message}"
-msgstr ""
+msgstr "Помилка автентифікації: %{error_message}"
msgid "Authentication log"
msgstr "Журнал автентифікації"
@@ -1478,10 +1738,10 @@ msgid "Authentication method"
msgstr "Метод автентифікації"
msgid "Authentication method updated"
-msgstr ""
+msgstr "Метод автентифікації оновлено"
msgid "Authentication via U2F device failed."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ автентифікацію через U2F приÑтрій."
msgid "Author"
msgstr "Ðвтор"
@@ -1502,7 +1762,7 @@ msgid "Authorize %{link_to_client} to use your account?"
msgstr "ÐвторизуватиÑÑ %{link_to_client} викориÑтовуючи ваш аккаунт?"
msgid "Authorized %{new_chat_name}"
-msgstr ""
+msgstr "Ðвторизовано %{new_chat_name}"
msgid "Authorized At"
msgstr "Ðвторизовано у"
@@ -1543,15 +1803,24 @@ msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ в %{link_to_documentation}"
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr "Конвеєр Auto DevOps увімкнено Ñ– буде викориÑтовуватиÑÑ, Ñкщо не знайдено жодного альтернативного файлу конфігурації CI. %{more_information_link}"
-msgid "Automatically marked as default internal user"
-msgstr "Ðвтоматично позначено Ñк внутрішній кориÑтувач за замовчуваннÑм"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically marked as default internal user"
+msgstr "Ðвтоматично позначено Ñк внутрішній кориÑтувач за замовчуваннÑм"
+
msgid "Automatically resolved"
msgstr "Вирішено автоматично"
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr "Примітка"
+
msgid "Available"
msgstr "ДоÑтупно"
@@ -1663,6 +1932,30 @@ msgstr "Ваші значки"
msgid "Badges|e.g. %{exampleUrl}"
msgstr "напр. %{exampleUrl}"
+msgid "Badge|New"
+msgstr "Ðовий"
+
+msgid "Balsamiq file could not be loaded."
+msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ файл Balsamiq."
+
+msgid "BambooService|A continuous integration and build server"
+msgstr "Сервер безперервної інтеграції та збірки"
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr "Atlassian Bamboo CI"
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr "Видалити вÑÑ– коментарі в очікуванні"
@@ -1765,12 +2058,35 @@ msgstr "Заблокувати"
msgid "Blocked"
msgstr "Заблокований"
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Blog"
msgstr "Блог"
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr "Дошки"
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "Гілка %{branchName} відÑÑƒÑ‚Ð½Ñ Ð² репозиторії цього проекту."
@@ -1786,6 +2102,9 @@ msgstr "Гілка вже Ñ–Ñнує"
msgid "Branch name"
msgstr "Ðазва гілки"
+msgid "Branch not loaded - %{branchId}"
+msgstr "Гілку не завантажено: %{branchId}"
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Пошук гілок"
@@ -1916,10 +2235,10 @@ msgid "Branches|protected"
msgstr "захищена"
msgid "Broadcast Message was successfully created."
-msgstr ""
+msgstr "ÐžÐ³Ð¾Ð»Ð¾ÑˆÐµÐ½Ð½Ñ ÑƒÑпішно Ñтворено."
msgid "Broadcast Message was successfully updated."
-msgstr ""
+msgstr "ÐžÐ³Ð¾Ð»Ð¾ÑˆÐµÐ½Ð½Ñ ÑƒÑпішно оновлено."
msgid "Browse Directory"
msgstr "ПереглÑнути каталог"
@@ -1936,6 +2255,21 @@ msgstr "ПереглÑд файлів"
msgid "Built-in"
msgstr "Вбудований"
+msgid "BurndownChartLabel|Guideline"
+msgstr "Керівництво"
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr "Відкриті задачі"
+
+msgid "BurndownChartLabel|Progress"
+msgstr "ПрогреÑ"
+
+msgid "BurndownChartLabel|Remaining"
+msgstr "ЗалишилоÑÑŒ"
+
msgid "Business"
msgstr "БізнеÑ"
@@ -1943,10 +2277,10 @@ msgid "Business metrics (Custom)"
msgstr "Ð‘Ñ–Ð·Ð½ÐµÑ Ð¼ÐµÑ‚Ñ€Ð¸ÐºÐ¸ (ВлаÑні)"
msgid "Buy EE"
-msgstr ""
+msgstr "Купити ЕЕ"
msgid "Buy GitLab Enterprise Edition"
-msgstr ""
+msgstr "Купити GitLab Enterprise Edition"
msgid "By %{user_name}"
msgstr "Від %{user_name}"
@@ -1954,6 +2288,9 @@ msgstr "Від %{user_name}"
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr "За замовчуваннÑм GitLab відправлÑÑ” електронні лиÑти в форматі HTML та у звичайному текÑтовому форматі, щоб поштові клієнти могли вибирати Ñкий з форматів викориÑтовувати. Вимкніть це налаштуваннÑ, Ñкщо ви хочете відправлÑти лиÑти лише у звичайному текÑтовому форматі."
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr "За замовчуваннÑм уÑÑ– проекти та групи будуть викориÑтовувати глобальні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñповіщень."
+
msgid "ByAuthor|by"
msgstr "від"
@@ -1973,7 +2310,7 @@ msgid "CI Lint"
msgstr "Перевірка CI конфігурації"
msgid "CI variables"
-msgstr ""
+msgstr "Змінні CI"
msgid "CI will run using the credentials assigned above."
msgstr "CI буде працювати з викориÑтаннÑм облікових даних, визначених вище."
@@ -2009,7 +2346,7 @@ msgid "CICD|Default to Auto DevOps pipeline"
msgstr "За замовчуваннÑм Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ð° Auto DevOps"
msgid "CICD|Default to Auto DevOps pipeline for all projects"
-msgstr ""
+msgstr "ВикориÑтовувати Auto DevOps конвеєр за замовчуваннÑм Ð´Ð»Ñ ÑƒÑÑ–Ñ… проектів"
msgid "CICD|Deployment strategy"
msgstr "Ð¡Ñ‚Ñ€Ð°Ñ‚ÐµÐ³Ñ–Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ"
@@ -2033,7 +2370,7 @@ msgid "CICD|instance enabled"
msgstr "ІнÑÑ‚Ð°Ð½Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð¾"
msgid "CONTRIBUTING"
-msgstr ""
+msgstr "CONTRIBUTING"
msgid "Callback URL"
msgstr "URL зворотнього виклику"
@@ -2044,7 +2381,13 @@ msgstr "Можна змінювати необхідні затвердженнÑ
msgid "Can't find HEAD commit for this branch"
msgstr "Ðе можу знайти HEAD-коміт Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— гілки"
+msgid "Can't find variable: ZiteReader"
+msgstr "Ðеможливо знайти змінну: ZiteReader"
+
msgid "Can't remove group members without group managed account"
+msgstr "Ðеможливо видалити учаÑників групи без облікових запиÑів, що керуютьÑÑ Ð³Ñ€ÑƒÐ¿Ð¾ÑŽ"
+
+msgid "Can't scan the code?"
msgstr ""
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
@@ -2068,11 +2411,17 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr "Ðеможливо змінити керований клаÑтер Kubernetes"
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr ""
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr "Ðеможливо показати попередній переглÑд. Ð”Ð»Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑду файлів Sketch, вони повинні мати формат, введений верÑією 43 або вище."
+
msgid "Cannot skip two factor authentication setup"
-msgstr ""
+msgstr "Ðеможливо пропуÑтити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð²Ð¾Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾Ñ— автентифікації"
msgid "Capacity threshold"
msgstr ""
@@ -2086,8 +2435,14 @@ msgstr "Сертифікат (PEM)"
msgid "Change Weight"
msgstr "Змінити вагу"
+msgid "Change assignee(s)"
+msgstr "Змінити виконавцÑ(ців)"
+
+msgid "Change assignee(s)."
+msgstr "Змінити виконавцÑ(ців)."
+
msgid "Change path"
-msgstr ""
+msgstr "Змінити шлÑÑ…"
msgid "Change permissions"
msgstr "Змінити права доÑтупу"
@@ -2098,6 +2453,15 @@ msgstr "Змінити шаблон"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "Змініть це значеннÑ, щоб вплинути на чаÑтоту Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ–Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñу GitLab."
+msgid "Change title"
+msgstr "Змінити заголовок"
+
+msgid "Change your password"
+msgstr "Змінити пароль"
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "Вибрати в гілці"
@@ -2122,6 +2486,12 @@ msgstr "Зміни відображаютьÑÑ Ñ‚Ð°Ðº, ніби <b>редакц
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr "Змінює заголовок на \"%{title_param}\"."
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr "СтатиÑтика"
@@ -2149,6 +2519,9 @@ msgstr "Перевірка ÑтатуÑу затвердженнÑ"
msgid "Checking branch availability..."
msgstr "Перевірка доÑтупноÑÑ‚Ñ– гілки..."
+msgid "Checking username availability..."
+msgstr "Перевірка доÑтупноÑÑ‚Ñ– імені кориÑтувача..."
+
msgid "Cherry-pick this commit"
msgstr "Вибрати (cherry-pick) цей коміт"
@@ -2170,6 +2543,9 @@ msgstr "Виберіть файл"
msgid "Choose a role permission"
msgstr "Вибрати роль"
+msgid "Choose a template"
+msgstr "Виберіть шаблон"
+
msgid "Choose a template..."
msgstr "Виберіть тему-шаблон..."
@@ -2183,7 +2559,7 @@ msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent
msgstr "Оберіть між <code>clone</code> та<code>fetch</code> щоб отримати найновіший код програми"
msgid "Choose file…"
-msgstr ""
+msgstr "Виберіть файл…"
msgid "Choose the top-level group for your repository imports."
msgstr "Оберіть групу найвищого Ñ€Ñ–Ð²Ð½Ñ Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ репозиторіїв."
@@ -2200,7 +2576,7 @@ msgstr "Виберіть, Ñкі репозиторії ви хочете під
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr "Виберіть Ñегменти Ð´Ð»Ñ Ñинхронізації на цей вторинний вузол."
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2228,7 +2604,7 @@ msgid "CiStatusLabel|pending"
msgstr "в очікуванні"
msgid "CiStatusLabel|preparing"
-msgstr ""
+msgstr "підготовка"
msgid "CiStatusLabel|skipped"
msgstr "пропущено"
@@ -2264,7 +2640,7 @@ msgid "CiStatusText|pending"
msgstr "в очікуванні"
msgid "CiStatusText|preparing"
-msgstr ""
+msgstr "підготовка"
msgid "CiStatusText|skipped"
msgstr "пропущено"
@@ -2272,17 +2648,35 @@ msgstr "пропущено"
msgid "CiStatus|running"
msgstr "виконуєтьÑÑ"
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr "Ðеможливо викориÑтовувати приховану змінну із поточним значеннÑм"
+
msgid "CiVariables|Input variable key"
msgstr "Ключ вхідної змінної"
msgid "CiVariables|Input variable value"
msgstr "Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð²Ñ…Ñ–Ð´Ð½Ð¾Ñ— змінної"
+msgid "CiVariables|Key"
+msgstr "Ключ"
+
+msgid "CiVariables|Masked"
+msgstr "Приховано"
+
msgid "CiVariables|Remove variable row"
msgstr "Видалити Ñ€Ñдок змінних"
-msgid "CiVariables|This variable will not be masked"
-msgstr ""
+msgid "CiVariables|Scope"
+msgstr "Межі"
+
+msgid "CiVariables|State"
+msgstr "Стан"
+
+msgid "CiVariables|Type"
+msgstr "Тип"
+
+msgid "CiVariables|Value"
+msgstr "ЗначеннÑ"
msgid "CiVariable|* (All environments)"
msgstr "* (Ð’ÑÑ– Ñередовища)"
@@ -2297,7 +2691,7 @@ msgid "CiVariable|Error occurred while saving variables"
msgstr "Помилка при збереженні змінних"
msgid "CiVariable|Masked"
-msgstr ""
+msgstr "Приховано"
msgid "CiVariable|New environment"
msgstr "Ðове Ñередовище"
@@ -2309,7 +2703,7 @@ msgid "CiVariable|Search environments"
msgstr "Пошук Ñередовищ"
msgid "CiVariable|Toggle masked"
-msgstr ""
+msgstr "Ввімкнути/вимкнути приховуваннÑ"
msgid "CiVariable|Toggle protected"
msgstr "Ввімкнути/вимкнути захиÑÑ‚"
@@ -2318,7 +2712,7 @@ msgid "CiVariable|Validation failed"
msgstr "Перевірка невдала"
msgid "Classification Label (optional)"
-msgstr ""
+msgstr "Мітка клаÑифікації (необов'Ñзково)"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "не доÑтупно: %{reason}"
@@ -2335,9 +2729,18 @@ msgstr "ОчиÑтити пошук"
msgid "Clear search input"
msgstr "ОчиÑтити поле вводу"
+msgid "Clear weight"
+msgstr "ОчиÑтити вагу"
+
+msgid "Clears weight."
+msgstr "Очищає вагу."
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr "Клікніть по будь-Ñкому <strong>імені проекту</strong> зі ÑпиÑку нижче Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб перейти до етапу проекту."
+msgid "Click here"
+msgstr "ÐатиÑніть тут"
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr "ÐатиÑніть кнопку <strong>ЗавантаженнÑ</strong> Ñ– зачекайте поки Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ðµ завершитьÑÑ."
@@ -2392,6 +2795,9 @@ msgstr "Закрити епік"
msgid "Close milestone"
msgstr "Закрити етап"
+msgid "Close sidebar"
+msgstr "Закрити бічну панель"
+
msgid "Closed"
msgstr "Закрито"
@@ -2410,9 +2816,15 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} були уÑпішно вÑтановлені на ваш Kubernetes-клаÑтер"
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr "%{title} уÑпішно видалено."
+
+msgid "ClusterIntegration|%{title} updated successfully."
msgstr "%{title} уÑпішно оновлено."
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
+msgstr "Токен ÑервіÑу, що дає доÑтуп до %{code}kube-system%{end_code} із правами %{code}cluster-admin%{end_code}."
+
msgid "ClusterIntegration|API URL"
msgstr "API URL"
@@ -2428,12 +2840,24 @@ msgstr "Додати інтеграцію із клаÑтером Kubernetes"
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ ÐºÐ»Ð°Ñтера Kubernetes до вашої групи автоматично зробить його доÑтупним у вÑÑ–Ñ… ваших проектах. ВикориÑтовуйте Review Apps, розгортайте заÑтоÑунки Ñ– легко запуÑкайте Ñвої конвеєри Ð´Ð»Ñ Ð²ÑÑ–Ñ… проектів з викориÑтаннÑм цього клаÑтера."
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ— до вашої групи надаÑÑ‚ÑŒ доÑтуп до клаÑтера у вÑÑ–Ñ… ваших проектах."
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Детальні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ— із цим Kubernetes-клаÑтером"
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2449,6 +2873,9 @@ msgstr "Помилка при отриманні ваших проектів: %{
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr "Помилка при отриманні типів машин зони: %{error}"
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr "ЗаÑтоÑунки"
@@ -2507,7 +2934,7 @@ msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr "Скопіювати Ñ–Ð¼â€™Ñ Kubernetes-клаÑтера"
msgid "ClusterIntegration|Copy Service Token"
-msgstr ""
+msgstr "Скопіювати токен ÑервіÑа"
msgid "ClusterIntegration|Create Kubernetes cluster"
msgstr "Створити Kubernetes-клаÑтер"
@@ -2557,6 +2984,9 @@ msgstr "GitLab Runner"
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Проект Google Cloud Platform"
@@ -2593,19 +3023,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr "Ingress дозволÑÑ” вам маршрутизувати запити до Ñлужб на оÑнові запитаного хоÑта або шлÑху, об'єднуючи Ñ€Ñд ÑервіÑів в одну точку входу."
-msgid "ClusterIntegration|Install"
-msgstr "Ð’Ñтановити"
-
-msgid "ClusterIntegration|Installed"
-msgstr "Ð’Ñтановлений"
-
-msgid "ClusterIntegration|Installing"
-msgstr "Ð’ÑтановленнÑ"
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2638,6 +3059,9 @@ msgstr "Доменне ім'Ñ Knative:"
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2674,6 +3098,9 @@ msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Kubernetes"
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про групові клаÑтери Kubernetes"
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr "Let's Encrypt"
@@ -2683,9 +3110,6 @@ msgstr "Тип машини"
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr "ВпевнітьÑÑ, що ваш обліковий Ð·Ð°Ð¿Ð¸Ñ %{link_to_requirements} Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Kubernetes-клаÑтерів"
-msgid "ClusterIntegration|Manage"
-msgstr "УправліннÑ"
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr "Керуйте вашим Kubernetes-клаÑтером за допомогою %{link_gke}"
@@ -2749,7 +3173,7 @@ msgstr "При бажанні ви можете замінити це на ваÑ
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "Запит про початок вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ðµ виконано"
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2786,10 +3210,10 @@ msgid "ClusterIntegration|Select zone to choose machine type"
msgstr "Виберіть зону, щоб вибрати тип машин"
msgid "ClusterIntegration|Service Token"
-msgstr ""
+msgstr "Токен СервіÑа"
msgid "ClusterIntegration|Service token is required."
-msgstr ""
+msgstr "Токен ÑервіÑа Ñ” обов'Ñзковим."
msgid "ClusterIntegration|Show"
msgstr "Показати"
@@ -2803,12 +3227,36 @@ msgstr "Помилка при Ñтворенні вашого Kubernetes-клаÑ
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "Під Ñ‡Ð°Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ %{title} ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr "Під Ñ‡Ð°Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ %{title} ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr "Ð—Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð¾Ð¼ÐµÐ½Ñƒ дозволить вам викориÑтовувати фази Auto Review Apps та Auto Deploy Ð´Ð»Ñ %{auto_devops_start}Auto DevOps%{auto_devops_end}. Домен повинен мати шаблон DNS, що задовільнÑÑ” цей домен."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
+msgstr "Сертифікат Kubernetes, що викориÑтовуєтьÑÑ Ð´Ð»Ñ Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ— в клаÑтері."
+
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
+msgstr ""
+
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
+msgstr ""
+
msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
+msgstr ""
+
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr "Цей обліковий Ð·Ð°Ð¿Ð¸Ñ Ð¿Ð¾Ð²Ð¸Ð½ÐµÐ½ мати наÑтупні права Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Kubernetes-клаÑтера в %{link_to_container_project}"
@@ -2821,23 +3269,11 @@ msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "Увімкнути/вимкнути Kubernetes-клаÑтер"
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
-msgstr ""
-
-msgid "ClusterIntegration|Updating"
-msgstr "ОновленнÑ"
-
-msgid "ClusterIntegration|Upgrade"
-msgstr "Оновити"
-
-msgid "ClusterIntegration|Upgrade failed"
-msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr "Видалити %{appTitle}"
-msgid "ClusterIntegration|Upgraded"
-msgstr "Оновлено"
-
-msgid "ClusterIntegration|Upgrading"
-msgstr ""
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸. Перевірте журнал та Ñпробуйте ще раз."
msgid "ClusterIntegration|Validating project billing status"
msgstr "Перевірка Ñтану білінгу проекта"
@@ -2848,6 +3284,9 @@ msgstr "Ми не змогли перевірити, що один із ваши
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "За допомогою підключеного до цього проекту Kubernetes-клаÑтера, ви можете викориÑтовувати Review Apps, розгортати ваші проекти, запуÑкати конвеєри збірки тощо."
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr "Перед вÑтановленнÑм заÑтоÑунків нижче, необхідно вÑтановити Helm Tiller"
@@ -2857,6 +3296,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð¿Ð¾Ð²Ð¸Ð½ÐµÐ½ мати %{link_to_kubernetes_engine}"
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr "Зона"
@@ -2873,7 +3315,7 @@ msgid "ClusterIntegration|meets the requirements"
msgstr "задовольнÑÑ” вимогам"
msgid "ClusterIntegration|pricing"
-msgstr ""
+msgstr "вартіÑÑ‚ÑŒ"
msgid "ClusterIntegration|properly configured"
msgstr "правильно налаштований"
@@ -2908,9 +3350,15 @@ msgstr "Згорнути ÑпиÑок затверджуючих оÑіб"
msgid "Collapse sidebar"
msgstr "Згорнути панель"
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr "ІнÑтрукції Ð´Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð½Ð¾Ð³Ð¾ Ñ€Ñдка"
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr "Коментар"
@@ -2929,6 +3377,9 @@ msgstr "Залишити коментар Ñ– повторно відкрити Ð
msgid "Comment form position"
msgstr "Ð Ð¾Ð·Ñ‚Ð°ÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð¾Ñ€Ð¼Ð¸ коментарÑ"
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr "Коментарі"
@@ -3003,7 +3454,7 @@ msgid "Commit…"
msgstr "Коміт…"
msgid "Company"
-msgstr ""
+msgstr "КомпаніÑ"
msgid "Compare"
msgstr "ПорівнÑти"
@@ -3050,6 +3501,9 @@ msgstr "Ðалаштувати runner'ів GitLab Ð´Ð»Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÑƒ вико
msgid "Configure Gitaly timeouts."
msgstr "Ðалаштувати таймаути Gitaly."
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð’Ñ–Ð´ÑтеженнÑ"
@@ -3075,9 +3529,15 @@ msgid "Configure the way a user creates a new account."
msgstr "Ðалаштувати ÑпоÑіб ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувачем нового облікового запиÑу."
msgid "Confirm"
+msgstr "Підтвердити"
+
+msgid "Confirmation email sent to %{email}"
msgstr ""
msgid "Confirmation required"
+msgstr "Ðеобхідне підтвердженнÑ"
+
+msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr ""
msgid "Connect"
@@ -3092,9 +3552,15 @@ msgstr "Підключити репозиторії з GitHub"
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr "Підключіть ваші зовнішні репозиторії, Ñ– CI/CD конвеєри будуть запуÑкатиÑÑ Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… комітів. Створений GitLab-проект буде мати лише CI/CD фунції."
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr "З'єднаннÑ..."
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3158,6 +3624,9 @@ msgstr "За допомогою вбудованого в GitLab реєÑтру
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr "Ви також можете викориÑтовувати %{deploy_token} Ð´Ð»Ñ Ð´Ð¾Ñтупу тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð´Ð¾ образів у реєÑтрі."
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr "ВміÑÑ‚ .gitlab-ci.yml"
@@ -3203,6 +3672,9 @@ msgstr "Коміти в %{branch_name}, за винÑтком комітів зÐ
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr "Будь лаÑка, зачекайте, Ñ†Ñ Ñторінка автоматично оновитьÑÑ, коли буде готова."
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr "Керувати відображеннÑм Ñторонніх пропозицій."
@@ -3212,6 +3684,9 @@ msgstr "Задати макÑимальну кількіÑÑ‚ÑŒ потоків д
msgid "ConvDev Index"
msgstr "Ð†Ð½Ð´ÐµÐºÑ ConvDev"
+msgid "Copied"
+msgstr "Скопійовано"
+
msgid "Copy %{http_label} clone URL"
msgstr "Скопіювати URL Ð´Ð»Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· %{http_label}"
@@ -3230,9 +3705,6 @@ msgstr "Скопіювати URL Ð´Ð»Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· SSH"
msgid "Copy SSH public key"
msgstr "Скопіювати публічний ключ SSH"
-msgid "Copy SSH public key to clipboard"
-msgstr "Скопіюйте відкритий SSH-ключ в буфер обміну"
-
msgid "Copy URL to clipboard"
msgstr "Скопіювати URL в буфер обміну"
@@ -3248,6 +3720,12 @@ msgstr "Скопіювати ідентифікатор в буфер обмін
msgid "Copy file path to clipboard"
msgstr "Скопіювати шлÑÑ… до файлу в буфер обміну"
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr "Скопіювати мітки та етап із %{source_issuable_reference}."
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr "Скопіювати мітки та етап з іншої задачі чи запиту на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð² цьому проекті"
+
msgid "Copy link"
msgstr "Скопіювати поÑиланнÑ"
@@ -3257,6 +3735,9 @@ msgstr "Скопіювати поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð² буфер обміну"
msgid "Copy secret to clipboard"
msgstr "Скопіювати Ñекрет в буфер обміну"
+msgid "Copy source to clipboard"
+msgstr "Скопіювати джерело в буфер обміну"
+
msgid "Copy to clipboard"
msgstr "Копіювати в буфер обміну"
@@ -3264,25 +3745,31 @@ msgid "Copy token to clipboard"
msgstr "Скопіювати токен в буфер обміну"
msgid "Could not authorize chat nickname. Try again!"
+msgstr "Ðе вдалоÑÑ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·ÑƒÐ²Ð°Ñ‚Ð¸ пÑевдонім Ð´Ð»Ñ Ñ‡Ð°Ñ‚Ñƒ. Спробуйте ще раз!"
+
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
msgstr ""
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ пÑевдонім Ð´Ð»Ñ Ñ‡Ð°Ñ‚Ñƒ %{chat_name}."
msgid "Could not remove the trigger."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ тригер."
msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ ÑÑ‚Ð°Ñ‚ÑƒÑ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ð°. Ð”Ð»Ñ ÑƒÑÑƒÐ½ÐµÐ½Ð½Ñ Ð½ÐµÐ¿Ð¾Ð»Ð°Ð´Ð¾Ðº, прочитайте %{linkStart}документацію%{linkEnd}"
msgid "Could not revoke impersonation token %{token_name}."
-msgstr ""
+msgstr "Ðеможливо відкликати токен Ñ–Ð¼Ñ–Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ %{token_name}."
msgid "Could not revoke personal access token %{personal_access_token_name}."
msgstr ""
@@ -3300,11 +3787,20 @@ msgid "Create New Domain"
msgstr "Створити новий домен"
msgid "Create a GitLab account first, and then connect it to your %{label} account."
+msgstr "Спочатку Ñтворіть обліковий Ð·Ð°Ð¿Ð¸Ñ GitLab, а потім приєднайте його до облікового запиÑу %{label}."
+
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
msgstr ""
+msgid "Create a merge request."
+msgstr "Створити запит на злиттÑ."
+
msgid "Create a new branch"
msgstr "Створити нову гілку"
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr "Створити нову задачу"
@@ -3377,6 +3873,12 @@ msgstr "Створити мітку проекту"
msgid "Create your first page"
msgstr "Створити вашу першу Ñторінку"
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr "Тег"
@@ -3392,12 +3894,27 @@ msgstr "Створено в"
msgid "Created by me"
msgstr "Створено мною"
+msgid "Created issue %{issueLink}"
+msgstr "Створено задачу %{issueLink}"
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr "Створено задачу %{issueLink} в %{projectLink}"
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr "Створений"
msgid "Created on:"
msgstr "Створено:"
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr "Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÐµÐ¿Ñ–ÐºÑƒ"
@@ -3416,6 +3933,9 @@ msgstr "Поточний проект"
msgid "Current node"
msgstr "Поточний вузол"
+msgid "Current password"
+msgstr "Поточний пароль"
+
msgid "CurrentUser|Profile"
msgstr "Профіль"
@@ -3494,7 +4014,19 @@ msgstr "Ð’ÑÑ–"
msgid "DashboardProjects|Personal"
msgstr "ОÑобиÑÑ‚Ñ–"
+msgid "DashboardProjects|Trending"
+msgstr "ПопулÑрні"
+
msgid "Dashboards"
+msgstr "Панелі керуваннÑ"
+
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr "%{firstProject} Ñ– %{secondProject}"
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr "%{firstProject}, %{rest}, Ñ– %{secondProject}"
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Data is still calculating..."
@@ -3503,6 +4035,18 @@ msgstr "Дані вÑе ще обчиÑлюютьÑÑ..."
msgid "Date picker"
msgstr "Вибір дати"
+msgid "DayTitle|F"
+msgstr "Пт"
+
+msgid "DayTitle|M"
+msgstr "Пн"
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr "Ср"
+
msgid "Debug"
msgstr "Відладка"
@@ -3537,6 +4081,9 @@ msgid "Default first day of the week in calendars and date pickers."
msgstr "Перший день Ñ‚Ð¸Ð¶Ð½Ñ Ð·Ð° замовчуваннÑм в календарÑÑ… та при виборі дати."
msgid "Default issue template"
+msgstr "Шаблон задач за замовчуваннÑм"
+
+msgid "Default project deletion protection"
msgstr ""
msgid "Default: Directly import the Google Code email address or username"
@@ -3579,7 +4126,7 @@ msgid "Delete comment"
msgstr "Видалити коментар"
msgid "Delete license"
-msgstr ""
+msgstr "Видалити ліцензію"
msgid "Delete list"
msgstr "Видалити ÑпиÑок"
@@ -3590,14 +4137,29 @@ msgstr "Видалити гілку-джерело"
msgid "Delete this attachment"
msgstr "Видалити це вкладеннÑ"
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr "Помилка при видаленні репозиторію проекту. Будь лаÑка, Ñпробуйте знову, або зв'ÑжітьÑÑ Ñ–Ð· адмініÑтратором."
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr "Помилка при видаленні деÑких тегів в реєÑтрі контейнерів проекту. Будь лаÑка, Ñпробуйте знову, або зв'ÑжітьÑÑ Ñ–Ð· адмініÑтратором."
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr "Помилка при видаленні вікі проекту. Будь лаÑка, Ñпробуйте знову, або зв'ÑжітьÑÑ Ñ–Ð· адмініÑтратором."
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr "Помилка при відновленні репозиторію проекту. Будь лаÑка, Ñпробуйте знову, або зв'ÑжітьÑÑ Ñ–Ð· адмініÑтратором."
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr "Помилка при відновленні вікі репозиторію. Будь лаÑка, Ñпробуйте знову, або зв'ÑжітьÑÑ Ñ–Ð· адмініÑтратором."
+
msgid "Deleted"
msgstr "Видалено"
msgid "Deleted chat nickname: %{chat_name}!"
-msgstr ""
+msgstr "Видалено пÑевдонім Ð´Ð»Ñ Ñ‡Ð°Ñ‚Ñƒ: %{chat_name}!"
msgid "Deleting the license failed."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ ліцензію."
msgid "Deleting the license failed. The license was not found."
msgstr ""
@@ -3606,11 +4168,59 @@ msgid "Deleting the license failed. You are not permitted to perform this action
msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
-msgstr ""
+msgstr "Відмовлено в авторизації пÑевдоніму Ð´Ð»Ñ Ñ‡Ð°Ñ‚Ñƒ %{user_name}."
msgid "Deny"
msgstr "Заборонити"
+msgid "Dependencies"
+msgstr "ЗалежноÑÑ‚Ñ–"
+
+msgid "Dependencies|Component"
+msgstr "Компонент"
+
+msgid "Dependencies|Component name"
+msgstr "Ім'Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ‚Ð°"
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr "РозташуваннÑ"
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr "ВерÑÑ–Ñ"
+
+msgid "Dependency List"
+msgstr "СпиÑок залежноÑтей"
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "РозгортаннÑ"
@@ -3772,34 +4382,37 @@ msgid "Description:"
msgstr "ОпиÑ:"
msgid "DesignManagement|%{current_design} of %{designs_count}"
-msgstr ""
+msgstr "%{current_design} з %{designs_count}"
msgid "DesignManagement|Could not find design, please try again."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ дизайн, будь лаÑка, Ñпробуйте знову."
msgid "DesignManagement|Error uploading a new design. Please try again"
-msgstr ""
+msgstr "Помилка при завантаженні нового дизайну. Будь лаÑка, Ñпробуйте знову"
msgid "DesignManagement|Go back to designs"
-msgstr ""
+msgstr "ПовернутиÑÑ Ð´Ð¾ дизайнів"
msgid "DesignManagement|Go to next design"
-msgstr ""
+msgstr "Перейти до наÑтупного дизайну"
msgid "DesignManagement|Go to previous design"
-msgstr ""
+msgstr "Перейти до попереднього дизайну"
+
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr "МакÑимальна кількіÑÑ‚ÑŒ дизайнів, Ñкі можна завантажити — %{upload_limit}. Будь лаÑка, Ñпробуйте знову."
msgid "DesignManagement|The one place for your designs"
-msgstr ""
+msgstr "Єдине міÑце Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… дизайнів"
msgid "DesignManagement|Upload and view the latest designs for this issue. Consistent and easy to find, so everyone is up to date."
-msgstr ""
+msgstr "Завантажити та переглÑнути оÑтанні дизайни Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— задачі. ПоÑлідовно та легко Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ, щоб вÑÑ– бачили актуальну інформацію."
msgid "DesignManagement|Upload designs"
-msgstr ""
+msgstr "Завантажити дизайни"
msgid "Designs"
-msgstr ""
+msgstr "Дизайни"
msgid "Destroy"
msgstr "Знищити"
@@ -3843,9 +4456,15 @@ msgstr "Вимкнути групові Runner'и"
msgid "Disable shared Runners"
msgstr "Вимкнути загальні Runner'и"
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr "Вимкнено"
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr "Відхилити"
@@ -3867,6 +4486,12 @@ msgstr "Видалити чернетку"
msgid "Discard review"
msgstr "Відхилити перевірку"
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr "Відкрийте GitLab Geo"
@@ -3897,18 +4522,42 @@ msgstr "Видалити Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ запит на злиÑ
msgid "Dismiss trial promotion"
msgstr "Відхилити пробну верÑÑ–ÑŽ"
+msgid "Dismissed"
+msgstr "Відхилено"
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr "Ви хочете налаштувати, Ñк адреÑи електронної пошти та імена кориÑтувачів будуть імпортовані з Google Code в GitLab?"
+msgid "Dockerfile"
+msgstr "Dockerfile"
+
msgid "Documentation for popular identity providers"
msgstr "Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ Ð´Ð»Ñ Ð¿Ð¾ÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ… провайдерів ідентифікації"
msgid "Domain"
msgstr "Домен"
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr "Ðе показувати знову"
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr "Готово"
@@ -3921,26 +4570,20 @@ msgstr "Завантажити артефакти"
msgid "Download asset"
msgstr "Завантажити реÑурÑ"
-msgid "Download export"
+msgid "Download codes"
msgstr ""
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
-msgstr ""
-
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
-msgstr ""
+msgid "Download license"
+msgstr "Завантажити ліцензію"
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
-msgstr ""
+msgid "Download this directory"
+msgstr "Завантажити цей каталог"
msgid "DownloadCommit|Email Patches"
msgstr "Email-патчі"
@@ -3981,6 +4624,9 @@ msgstr "Редагувати мітку"
msgid "Edit Milestone"
msgstr "Редагувати етап"
+msgid "Edit Password"
+msgstr "Редагувати пароль"
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "Редагувати Розклад Конвеєра %{id}"
@@ -4017,6 +4663,12 @@ msgstr "Редагувати публічний ключ Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°
msgid "Elasticsearch"
msgstr "Elasticsearch"
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr "Розпочато індекÑацію Elasticsearch"
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr "Ð†Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ð· Elasticsearch. Elasticsearch AWS IAM."
@@ -4030,11 +4682,14 @@ msgid "Email"
msgstr "Електронна пошта"
msgid "Email address"
-msgstr ""
+msgstr "ÐдреÑа електронної пошти"
msgid "Email patch"
msgstr "Email-патч"
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -4059,9 +4714,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr "ÐдреÑи електронної пошти"
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr "Вбудувати"
@@ -4086,6 +4771,9 @@ msgstr "Увімкнути автентифікацію SAML Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— гÑ
msgid "Enable Sentry for error reporting and logging."
msgstr "Увімкнути Sentry Ð´Ð»Ñ Ð·Ð²Ñ–Ñ‚Ñ–Ð² про помилки та логуваннÑ."
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr "Включити і налаштувати метрики InfluxDB."
@@ -4122,9 +4810,6 @@ msgstr "Увімкнути reCAPTCHA або Akismet та вÑтановити о
msgid "Enable shared Runners"
msgstr "Увімкнути загальні Runner'и"
-msgid "Enable the Performance Bar for a given group."
-msgstr "Увімкнути панель продуктивноÑÑ‚Ñ– Ð´Ð»Ñ Ð´Ð°Ð½Ð¾Ñ— групи."
-
msgid "Enable two-factor authentication"
msgstr "Увімкнути двофакторну автентифікацію"
@@ -4150,17 +4835,23 @@ msgid "Enabling this will only make licensed EE features available to projects i
msgstr ""
msgid "End date"
-msgstr ""
+msgstr "Дата завершеннÑ"
msgid "Ends at (UTC)"
msgstr "ЗавершуєтьÑÑ Ð¾ (за Грінвічем)"
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr "Введіть URL-адреÑу вашого Bitbucket Server Ñ– ключ доÑтупу"
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr "Введіть Ð¾Ð¿Ð¸Ñ Ð·Ð°Ð´Ð°Ñ‡Ñ–"
@@ -4173,7 +4864,10 @@ msgstr "Введіть Ð¾Ð¿Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на злиттÑ"
msgid "Enter the merge request title"
msgstr "Введіть назву запиту на злиттÑ"
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4185,9 +4879,33 @@ msgstr "Середовище:"
msgid "Environments"
msgstr "Середовища"
+msgid "Environments Dashboard"
+msgstr "Панель ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñередовищами"
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr "Середовища дозволÑÑŽÑ‚ÑŒ відÑтежувати Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ заÑтоÑунку %{link_to_read_more}."
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr "Додати проект до панелі керуваннÑ"
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr "Додати проекти"
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr "ЗавданнÑ: %{job}"
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr "Додаткові дії"
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr "Видалити"
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "Виникла помилка при завантаженні Ñередовищ."
@@ -4323,18 +5041,51 @@ msgstr "План-графік епіків"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr "Епіки дозволÑÑŽÑ‚ÑŒ керувати вашим портфелем проектів ефективніше та з меншими зуÑиллÑми"
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr "Додати епік"
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при збереженні дати %{epicDateType}"
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr "Як Ñ Ð¼Ð¾Ð¶Ñƒ це вирішити?"
msgid "Epics|More information"
msgstr "Детальніше"
+msgid "Epics|Remove epic"
+msgstr "Видалити епік"
+
+msgid "Epics|Remove issue"
+msgstr "Видалити задачу"
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr "Ці дати впливають на те, Ñк ваші епіки відображатимутьÑÑ Ð½Ð° плані-графіку. Дати з етапів берутьÑÑ Ð· етапів, призначених до задач у цьому епіку. Ви також можете задавати фікÑовані дати, або видалÑти Ñ—Ñ…."
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr "Щоб запланувати %{epicDateType} дату вашого епіку на оÑнові етапів, призначте етап з %{epicDateType} датою Ð´Ð»Ñ Ð±ÑƒÐ´ÑŒ-Ñкої задачі в цьому епіку."
@@ -4371,9 +5122,15 @@ msgstr "Помилка Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¼Ñ–Ñ‚Ð¾Ðº."
msgid "Error fetching network graph."
msgstr "Помилка при отриманні графа мережі."
+msgid "Error fetching projects"
+msgstr "Помилка Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñ–Ð²"
+
msgid "Error fetching refs"
msgstr "Помилка Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ refs"
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr "Помилка при отриманні данних про викориÑтаннÑ."
@@ -4383,6 +5140,12 @@ msgstr "Помилка при завантаженні даних про гілÐ
msgid "Error loading branches."
msgstr "Помилка при завантаженні гілок."
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
msgstr "Помилка при завантаженні оÑтаннього коміту."
@@ -4392,6 +5155,9 @@ msgstr "Помилка Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ перÐ
msgid "Error loading merge requests."
msgstr "Помилка при завантаженні запитів на злиттÑ."
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr "Помилка при завантаженні даних проекту. Будь лаÑка, Ñпробуйте знову."
@@ -4401,17 +5167,23 @@ msgstr "Помилка при завантаженні типів шаблоні
msgid "Error loading template."
msgstr "Помилка при завантаженні шаблону."
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´Ð¿Ð¸Ñки на ÑповіщеннÑ"
msgid "Error occurred. User was not blocked"
-msgstr ""
+msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. КориÑтувач не був заблокований"
msgid "Error occurred. User was not confirmed"
msgstr ""
msgid "Error occurred. User was not unblocked"
-msgstr ""
+msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. КориÑтувач не був розблокований"
msgid "Error occurred. User was not unlocked"
msgstr ""
@@ -4432,16 +5204,22 @@ msgid "Error updating todo status."
msgstr "Помилка при оновленні ÑтатуÑу нагадуваннÑ."
msgid "Error uploading file"
+msgstr "Помилка Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ"
+
+msgid "Error uploading file: %{stripped}"
msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr "Помилка при завантаженні запита на злиттÑ. Будь лаÑка, Ñпробуйте знову."
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
msgid "Error with Akismet. Please check the logs for more info."
-msgstr ""
+msgstr "Помилка з Akismet. Будь лаÑка, перевірте журнали Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації."
msgid "Error:"
msgstr "Помилка:"
@@ -4533,6 +5311,9 @@ msgstr "Ð’Ñе, що потрібно Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñайту на
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr "Ð’Ñе, що потрібно Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñайту на GitLab Pages за допомогою проÑтого HTML."
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4555,7 +5336,7 @@ msgid "Expiration date"
msgstr "Термін дії"
msgid "Expired"
-msgstr ""
+msgstr "Термін дії закінчивÑÑ"
msgid "Expired %{expiredOn}"
msgstr "Минув(-ло) %{expiredOn}"
@@ -4591,7 +5372,7 @@ msgid "Export issues"
msgstr "ЕкÑпортувати задачі"
msgid "Export project"
-msgstr ""
+msgstr "ЕкÑпорт проекту"
msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
msgstr ""
@@ -4620,6 +5401,27 @@ msgstr "Мітка клаÑифікації"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "Якщо клаÑифікаційну мітку не вÑтановлено, викориÑтовуватиметьÑÑ Ñтандартна мітка `%{default_label}`."
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr "Ð—Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ керуваннÑ"
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr "Повна URL-адреÑа панелі керуваннÑ"
+
+msgid "ExternalWikiService|External Wiki"
+msgstr "Ð—Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ Ð²Ñ–ÐºÑ–"
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr "Facebook"
@@ -4629,25 +5431,58 @@ msgstr "Ðевдало"
msgid "Failed Jobs"
msgstr "Провалені завданнÑ"
+msgid "Failed create wiki"
+msgstr "Ðе вдалоÑÑ Ñтворити вікі"
+
msgid "Failed to change the owner"
msgstr "Ðе вдалоÑÑ Ð·Ð¼Ñ–Ð½Ð¸Ñ‚Ð¸ влаÑника"
msgid "Failed to check related branches."
msgstr "Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€Ð¸Ñ‚Ð¸ пов’Ñзані гілки."
-msgid "Failed to create resources"
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
msgstr ""
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
+msgid "Failed to create resources"
+msgstr "Ðе вдалоÑÑ Ñтворити реÑурÑ"
+
msgid "Failed to deploy to"
msgstr "Ðе вдалоÑÑ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ð½ÑƒÑ‚Ð¸ до"
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr "Ðе вдалоÑÑ Ð²Ñтановити."
+
msgid "Failed to load emoji list."
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ ÑпиÑок Ñмайликів."
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
+msgstr "Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÐ½ÐµÑти мітку через внутрішню проблему. Будь лаÑка, звернітьÑÑ Ð´Ð¾ адмініÑтраторів."
+
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
msgstr ""
msgid "Failed to remove issue from board, please try again."
@@ -4660,38 +5495,56 @@ msgid "Failed to remove the pipeline schedule"
msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ розклад конвеєра"
msgid "Failed to remove user identity."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ ідентифікацію кориÑтувача."
msgid "Failed to remove user key."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ ключ кориÑтувача."
msgid "Failed to reset key. Please try again."
msgstr ""
-msgid "Failed to save new settings"
+msgid "Failed to save comment!"
+msgstr "Ðе вдалоÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ коментар!"
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
msgstr ""
+msgid "Failed to save new settings"
+msgstr "Ðе вдалоÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ нові параметри"
+
msgid "Failed to save preferences (%{error_message})."
msgstr ""
msgid "Failed to save preferences."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ налаштуваннÑ."
msgid "Failed to signing using smartcard authentication"
msgstr "Ðе вдалоÑÑ Ð¿Ñ–Ð´Ð¿Ð¸Ñати з викориÑтаннÑм перевірки автентичноÑÑ‚Ñ– Ñмарт-карти"
+msgid "Failed to update branch!"
+msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ гілку!"
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ задачі. Будь лаÑка, Ñпробуйте ще раз."
+msgid "Failed to update tag!"
+msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ тег!"
+
+msgid "Failed to update."
+msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸."
+
+msgid "Failed to upgrade."
+msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸."
+
msgid "Failed to upload object map file"
msgstr ""
msgid "Failure"
msgstr "Помилка"
-msgid "Fast-forward merge"
-msgstr ""
-
msgid "Fast-forward merge without a merge commit"
msgstr ""
@@ -4704,6 +5557,12 @@ msgstr ""
msgid "Feature Flags"
msgstr "Перемикачі функцій"
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr "* (УÑÑ– Ñередовища)"
@@ -4767,8 +5626,8 @@ msgstr "Ðеактивний"
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr "Ðеактивний перемикач функції Ð´Ð»Ñ %{scope}"
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
-msgstr "Ð’Ñтановіть %{docs_link_start}ÑуміÑну клієнтÑьку бібліотеку%{docs_link_end} Ñ– вкажіть URL адреÑу API, назву заÑтоÑунку та ідентифікатор інÑтанÑа під Ñ‡Ð°Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
+msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr "Ідентифікатор ІнÑтанÑу"
@@ -4779,9 +5638,6 @@ msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ñ‡Ñ–Ð² функцій"
msgid "FeatureFlags|More Information"
msgstr "Більше інформації"
-msgid "FeatureFlags|More information"
-msgstr "Більше інформації"
-
msgid "FeatureFlags|Name"
msgstr "Ðазва"
@@ -4792,7 +5648,7 @@ msgid "FeatureFlags|New Feature Flag"
msgstr "Ðовий перемикач функції"
msgid "FeatureFlags|Protected"
-msgstr ""
+msgstr "Захищено"
msgid "FeatureFlags|Status"
msgstr "СтатуÑ"
@@ -4864,6 +5720,12 @@ msgstr "Помилка Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ."
msgid "Files"
msgstr "Файли"
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr "Заповніть Ð¿Ð¾Ð»Ñ Ð½Ð¸Ð¶Ñ‡Ðµ, увімкніть <strong>%{enable_label}</strong> та натиÑніть <strong>%{save_changes}</strong>"
@@ -4912,6 +5774,9 @@ msgstr "Знайдіть щойно розпакований <code>Takeout/Googl
msgid "Fingerprint"
msgstr "Відбиток"
+msgid "Fingerprint:"
+msgstr "Відбиток:"
+
msgid "Fingerprints"
msgstr "Відбитки пальців"
@@ -4921,6 +5786,9 @@ msgstr "Спочатку завершіть Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ п
msgid "Finish review"
msgstr "Завершити перевірку"
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr "Завершено"
@@ -4945,6 +5813,12 @@ msgstr "Виправлена дата початку"
msgid "Fixed:"
msgstr "Виправлено:"
+msgid "FlowdockService|Flowdock Git source token"
+msgstr "Токен джерела Git Ð´Ð»Ñ Flowdock"
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr "Flowdock — це веб заÑтоÑунок Ð´Ð»Ñ Ð²Ð·Ð°Ñ”Ð¼Ð¾Ð´Ñ–Ñ— технічних команд."
+
msgid "FogBugz Email"
msgstr "ÐдреÑа електронної пошти FogBugz"
@@ -4990,6 +5864,15 @@ msgstr "Ð”Ð»Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¸Ñ… проектів будь-Ñкий кориÑÑ
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr "Ð”Ð»Ñ Ð¿ÑƒÐ±Ð»Ñ–Ñ‡Ð½Ð¸Ñ… проектів будь-Ñкий зареєÑтрований кориÑтувач може переглÑдати конвеєри та отримати доÑтуп до інформації про роботу (логи та артефакти)"
+msgid "Fork"
+msgstr "Форк"
+
+msgid "Fork Error!"
+msgstr "Помилка форку!"
+
+msgid "Fork project"
+msgstr "Форк проекту"
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "Форк від"
@@ -4999,6 +5882,9 @@ msgstr "Форк із %{project_name} (видалено)"
msgid "Forking in progress"
msgstr "ВідбуваєтьÑÑ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ„Ð¾Ñ€ÐºÑƒ"
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr "Форки"
@@ -5017,6 +5903,9 @@ msgstr "Знайдено помилки у вашому .gitlab-ci.yml:"
msgid "Free Trial of GitLab.com Gold"
msgstr "Безкоштовна пробна верÑÑ–Ñ GitLab.com Gold"
+msgid "Friday"
+msgstr "П'ÑтницÑ"
+
msgid "From %{providerTitle}"
msgstr "З %{providerTitle}"
@@ -5047,12 +5936,18 @@ msgstr "З етапів:"
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr "Із Ñторінки деталей Kubernetes-клаÑтера, вÑтановіть runner зі ÑпиÑку заÑтоÑунків"
+msgid "Full name"
+msgstr "Повне ім'Ñ"
+
msgid "GPG Key ID:"
msgstr "Ідентифікатор ключа GPG:"
msgid "GPG Keys"
msgstr "GPG ключі"
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr "ÐŸÑ–Ð´Ð¿Ð¸Ñ GPG (завантаженнÑ...)"
@@ -5117,7 +6012,7 @@ msgid "GeoNodes|Health status"
msgstr "Стан працездатноÑÑ‚Ñ–"
msgid "GeoNodes|Internal URL"
-msgstr ""
+msgstr "Внутрішній URL"
msgid "GeoNodes|Last event ID processed by cursor"
msgstr "ОÑтанній ідентифікатор події, оброблений курÑором"
@@ -5309,7 +6204,7 @@ msgid "Geo|In sync"
msgstr "Синхронізовано"
msgid "Geo|Internal URL"
-msgstr ""
+msgstr "Внутрішній URL"
msgid "Geo|Last repository check run"
msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ Ð·Ð°Ð¿ÑƒÑк перевірки репозиторію"
@@ -5345,7 +6240,7 @@ msgid "Geo|Please refer to Geo Troubleshooting."
msgstr ""
msgid "Geo|Project"
-msgstr ""
+msgstr "Проект"
msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
msgstr "Проект (ID: %{project_id}) більше не Ñ–Ñнує на оÑновному вузлі. Поточний Ð·Ð°Ð¿Ð¸Ñ Ð¼Ð¾Ð¶Ð½Ð° безпечно видалити, оÑкільки це не видалÑÑ” жодних даних на диÑку."
@@ -5410,6 +6305,12 @@ msgstr "Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð½ÐµÐ²Ð´Ð°Ð»Ð°: %{error}"
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr "Це — первинний вузол"
@@ -5467,6 +6368,9 @@ msgstr "Git"
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr "Глобальні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Git"
@@ -5476,6 +6380,9 @@ msgstr "URL Git-репозиторіÑ"
msgid "Git revision"
msgstr "Git-редакціÑ"
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr "Git Ñтратегії Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²"
@@ -5489,7 +6396,7 @@ msgid "GitLab CI Linter has been moved"
msgstr "GitLab CI Linter був перенеÑений"
msgid "GitLab Enterprise Edition %{plan}"
-msgstr ""
+msgstr "GitLab Enterprise Edition %{plan}"
msgid "GitLab Geo"
msgstr "GitLab Geo"
@@ -5507,7 +6414,7 @@ msgid "GitLab User"
msgstr "GitLab КориÑтувач"
msgid "GitLab allows you to continue using your license even if you exceed the number of seats you purchased. You will be required to pay for these seats when you renew your license."
-msgstr ""
+msgstr "GitLab дозволÑÑ” вам викориÑтовувати вашу підпиÑку, навіть Ñкщо ви перевищили кількіÑÑ‚ÑŒ придбаних міÑць. Вам треба буде заплатити за ці міÑÑ†Ñ Ð¿Ñ€Ð¸ Ñ—Ñ— поновленні."
msgid "GitLab metadata URL"
msgstr ""
@@ -5516,7 +6423,7 @@ msgid "GitLab project export"
msgstr "ЕкÑпорт проекту GitLab"
msgid "GitLab restart is required to apply changes"
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð·Ð°ÑтоÑÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð¼Ñ–Ð½ необхідне Ð¿ÐµÑ€ÐµÐ·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ GitLab"
msgid "GitLab single sign on URL"
msgstr "URL єдиного входу GitLab"
@@ -5548,11 +6455,14 @@ msgstr "Імпорт з Gitea"
msgid "Given access %{time_ago}"
msgstr "Ðадано доÑтуп %{time_ago}"
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr "ПовернутиÑÑ"
msgid "Go Micro is a framework for micro service development."
-msgstr ""
+msgstr "Go Micro — це фреймворк Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±ÐºÐ¸ мікроÑервіÑів."
msgid "Go back"
msgstr "ПовернутиÑÑ"
@@ -5566,9 +6476,18 @@ msgstr "Перейти до"
msgid "Go to %{link_to_google_takeout}."
msgstr "Перейти до %{link_to_google_takeout}."
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr "Перейти до проекту"
+msgid "Go to your fork"
+msgstr "Перейти до вашого форку"
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr "Імпорт з Google Code"
@@ -5644,15 +6563,21 @@ msgstr "Ðазва групи"
msgid "Group overview content"
msgstr "ВміÑÑ‚ оглÑдової Ñторінки групи"
-msgid "Group was successfully updated."
+msgid "Group pipeline minutes were successfully reset."
msgstr ""
+msgid "Group was successfully updated."
+msgstr "Групу уÑпішно оновлено."
+
msgid "Group:"
msgstr "Група:"
msgid "Group: %{group_name}"
msgstr "Група: %{group_name}"
+msgid "Group: %{name}"
+msgstr "Група: %{name}"
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr "Від %{dateWord}"
@@ -5666,7 +6591,7 @@ msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timelin
msgstr "План-графік епіків відображає Ñтан ваших епіків у чаÑÑ–"
msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of the %{linkStart}child epics%{linkEnd}."
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду плану-графіку додайте дату початку або Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ одного із %{linkStart}епіків-дітей%{linkEnd}."
msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
msgstr "Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду плану-графіку, додайте дату початку чи Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ð´Ð¾ одного з ваших епіків в цій групі або Ñ—Ñ— підгрупах; від %{startDate} до %{endDate}."
@@ -5678,67 +6603,76 @@ msgid "GroupRoadmap|Until %{dateWord}"
msgstr "До %{dateWord}"
msgid "GroupSAML|Certificate fingerprint"
-msgstr ""
+msgstr "Відбиток Ñертифікату"
-msgid "GroupSAML|Enable SAML authentication for this group"
-msgstr ""
+msgid "GroupSAML|Configuration"
+msgstr "ÐалаштуваннÑ"
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
-msgstr ""
+msgid "GroupSAML|Enable SAML authentication for this group."
+msgstr "Увімкнути автентифікацію через SAML Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи."
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
-msgstr ""
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgstr "Зробити обов'Ñзковою SSO автентифікацію Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи."
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
+msgstr "Зобов'Ñзати кориÑтувачів Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи мати окремі облікові запиÑи керовані нею."
msgid "GroupSAML|Enforced SSO"
-msgstr ""
+msgstr "Обов'Ñзкове SSO"
msgid "GroupSAML|Generate a SCIM token"
-msgstr ""
+msgstr "Створити токен SCIM"
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
-msgstr ""
-
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
+msgstr "Згенерувати токен SCIM Ð´Ð»Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑиÑтеми ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ñ–Ð¶Ð´Ð¾Ð¼ÐµÐ½Ð½Ð¾ÑŽ ідентифікацією."
msgid "GroupSAML|Identity provider single sign on URL"
-msgstr ""
+msgstr "URL провайдера ідентифікації Ð´Ð»Ñ Ñ”Ð´Ð¸Ð½Ð¾Ð³Ð¾ входу"
msgid "GroupSAML|Make sure you save this token — you won't be able to access it again."
-msgstr ""
+msgstr "ПереконайтеÑÑ, що ви зберегли цей токен, бо ви не зможете отримати доÑтуп до нього знову."
msgid "GroupSAML|Manage your group’s membership while adding another level of security with SAML."
-msgstr ""
+msgstr "Керуйте членÑтвом у вашій групі додаючи ще один рівень безпеки із SAML."
msgid "GroupSAML|Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
-msgstr ""
+msgstr "УчаÑники будуть перенаправлені Ñюди, коли будуть заходити до вашої групи. Отримайте його від Ñвого провайдера ідентифікації, де вона також може називатиÑÑ \"SSO Service Location\", \"SAML Token Issuance Endpoint\", або \"SAML 2.0/W-Federation URL\"."
msgid "GroupSAML|SAML Single Sign On"
-msgstr ""
+msgstr "Єдиний вхід через SAML"
msgid "GroupSAML|SAML Single Sign On Settings"
-msgstr ""
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ”Ð´Ð¸Ð½Ð¾Ð³Ð¾ входу через SAML"
msgid "GroupSAML|SCIM API endpoint URL"
msgstr ""
msgid "GroupSAML|SCIM Token"
-msgstr ""
+msgstr "Токен SCIM"
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
-msgstr ""
+msgstr "SHA1-відбиток Ñертифікату Ð´Ð»Ñ Ð¿Ñ–Ð´Ð¿Ð¸Ñу SAML токена. Отримайте його від провайдера ідентифікації, де він також може називатиÑÑ \"Thumbprint\"."
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
+msgstr "Токен SCIM зараз приховоно. Щоб знову побачити Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‚Ð¾ÐºÐµÐ½Ð° вам потрібно "
+
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr "Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб зробити SSO автентифікацію обов'Ñзковою, Ñпочатку вам треба увімкнути автентифікацію через SAML."
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr "Ð”Ð»Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¸Ñ… запиÑів керованих групою, Ñпочатку необхідно увімкнути обов'Ñзкове SSO."
msgid "GroupSAML|Toggle SAML authentication"
-msgstr ""
+msgstr "Увімкнути/вимкнути автентифікацію SAML"
+
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr "При активаціх облікових запиÑів керованих групою, вÑÑ– кориÑтувачі, що не мають облікового запиÑу керованого групою, будуть виключеню з неї."
msgid "GroupSAML|Your SCIM token"
-msgstr ""
+msgstr "Ваш токен SCIM"
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
-msgstr ""
+msgstr "Конвеєр Auto DevOps оновлено Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи"
msgid "GroupSettings|Auto DevOps will automatically build, test and deploy your application based on a predefined Continuous Integration and Delivery configuration. %{auto_devops_start}Learn more about Auto DevOps%{auto_devops_end}"
msgstr ""
@@ -5774,7 +6708,7 @@ msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI conf
msgstr "Конвеєр Auto DevOps буде запущено, Ñкщо не буде знайдено альтернативного файлу конфігуріції CI."
msgid "GroupSettings|There was a problem updating Auto DevOps pipeline: %{error_messages}."
-msgstr ""
+msgstr "Проблема при оновленні конвеєра Auto DevOps: %{error_messages}."
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "Цей параметр заÑтоÑовано до %{ancestor_group} Ñ– його було перевизначено в цій підгрупі."
@@ -5797,6 +6731,9 @@ msgstr "Видалити Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñпільного доÑтупу
msgid "Groups"
msgstr "Групи"
+msgid "Groups (%{count})"
+msgstr "Групи (%{count})"
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr "Групи також можуть бути вкладеними при викориÑтанні %{subgroup_docs_link_start}підгруп%{subgroup_docs_link_end}."
@@ -5866,11 +6803,14 @@ msgstr "Жодна группа чи проект не задовольнÑÑ” п
msgid "GroupsTree|Search by name"
msgstr "Пошук за іменем"
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr "Електронна пошта Ð´Ð»Ñ Ð·Ð²ÐµÑ€Ñ‚Ð°Ð½ÑŒ кориÑтувачів"
msgid "Header logo was successfully removed."
-msgstr ""
+msgstr "Логотип в заголовку уÑпішно видалено."
msgid "Header message"
msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ°"
@@ -5893,6 +6833,9 @@ msgstr "Проблем із здоров'Ñм не виÑвлено"
msgid "HealthCheck|Unhealthy"
msgstr "Ðездоровий"
+msgid "Hello there"
+msgstr "Привіт"
+
msgid "Help"
msgstr "Допомога"
@@ -5902,12 +6845,15 @@ msgstr "Сторінка довідки"
msgid "Help page text and support page url."
msgstr "ТекÑÑ‚ Ñторінки довідки та url-адреÑа Ñторінки підтримки."
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
-msgstr "Це відкритий (публічний) SSH ключ, Ñкий потрібно додати на віддалений Ñервер. Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації, звернітьÑÑ Ð´Ð¾ документації."
+msgid "Hide archived projects"
+msgstr "Сховати архівовані проекти"
msgid "Hide file browser"
msgstr "Сховати файловий менеджер"
+msgid "Hide group projects"
+msgstr "Приховати проекти групи"
+
msgid "Hide host keys manual input"
msgstr "Сховати ввід ключів хоÑта"
@@ -5917,6 +6863,9 @@ msgstr "Сховати маркетингові розділи із допомо
msgid "Hide payload"
msgstr "Приховати кориÑне навантаженнÑ"
+msgid "Hide shared projects"
+msgstr "Сховати Ñпільні проекти"
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Сховати значеннÑ"
@@ -5928,24 +6877,36 @@ msgid "Hide values"
msgstr "Сховати значеннÑ"
msgid "Highest role:"
-msgstr ""
+msgstr "Ðайвища роль:"
msgid "History"
msgstr "ІÑторіÑ"
+msgid "History of authentications"
+msgstr "ІÑÑ‚Ð¾Ñ€Ñ–Ñ Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ð¹"
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr "Ðевдале Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ñ…ÑƒÐºÐ°. ПереконайтеÑÑ, що Ñ†Ñ Ð³Ñ€ÑƒÐ¿Ð° має проект із комітами."
+
msgid "Hook was successfully created."
-msgstr ""
+msgstr "Хук уÑпішно Ñтворено."
msgid "Hook was successfully updated."
-msgstr ""
+msgstr "Хук уÑпішно оновлено."
msgid "Housekeeping"
-msgstr ""
+msgstr "ОчищеннÑ"
msgid "Housekeeping successfully started"
msgstr "ÐžÑ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ ÑƒÑпішно розпочато"
msgid "Housekeeping, export, path, transfer, remove, archive."
+msgstr "ОчищеннÑ, екÑпорт, шлÑÑ…, перенеÑеннÑ, видаленнÑ, архівуваннÑ."
+
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
msgstr ""
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
@@ -5957,6 +6918,12 @@ msgstr "Я приймаю %{terms_link}"
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr "Я погоджуюÑÑŒ з Правилами кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑервіÑом Ñ– політикою конфіденційноÑÑ‚Ñ–"
+msgid "I forgot my password"
+msgstr "Я забув пароль"
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr "ID"
@@ -6026,11 +6993,20 @@ msgstr "Якщо увімкнено"
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr "Якщо це дозволено, доÑтуп до проектів буде перевірÑтиÑÑ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾ÑŽ Ñлужбою з викориÑтаннÑм Ñ—Ñ… мітки клаÑифікації."
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr "При викориÑтанні GitHub, ви побачите ÑтатуÑи конвеєрів Ð´Ð»Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñ–Ð² Ñ– запитів на злиттÑ. %{more_info_link}"
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
-msgstr "Якщо ваш HTTP-репозиторій не Ñ” публічним, додайте дані Ð´Ð»Ñ Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ— до URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
+msgstr ""
msgid "ImageDiffViewer|2-up"
msgstr "2 поруч"
@@ -6042,7 +7018,7 @@ msgid "ImageDiffViewer|Swipe"
msgstr "Ðакладені (проведеннÑ)"
msgid "Impersonation has been disabled"
-msgstr "УоÑÐ¾Ð±Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¾ вимкнено"
+msgstr "Ð†Ð¼Ñ–Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¾ вимкнено"
msgid "Import"
msgstr "Імпорт"
@@ -6110,25 +7086,46 @@ msgstr "Імпорт репозиторіїв з GitHub"
msgid "Import repository"
msgstr "Імпорт репозиторію"
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
msgid "Import/Export illustration"
-msgstr ""
+msgstr "Імпорт/екÑпорт ілюÑтрацій"
msgid "ImportButtons|Connect repositories from"
msgstr "Підключити репозиторії із"
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr "Заблокований URL Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ: %{message}"
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr "Помилка при імпортуванні репозиторію %{project_safe_import_url} в %{project_full_path} - %{message}"
+
msgid "ImportProjects|Importing the project failed"
-msgstr ""
+msgstr "Ð†Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñƒ невдале"
msgid "ImportProjects|Requesting your %{provider} repositories failed"
-msgstr ""
+msgstr "Запит ваших %{provider} репозиторіїв пройшов невдало"
msgid "ImportProjects|Select the projects you want to import"
-msgstr ""
+msgstr "Виберіть проекти Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ"
+
+msgid "ImportProjects|The remote data could not be imported."
+msgstr "Віддалені дані не можуть бути імпортовані."
+
+msgid "ImportProjects|The repository could not be created."
+msgstr "Репозиторій не може бути Ñтворено."
msgid "ImportProjects|Updating the imported projects failed"
+msgstr "ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¾Ð²Ð°Ð½Ð¸Ñ… проектів пройшло невдало"
+
+msgid "Improve Issue boards"
msgstr ""
msgid "Improve Issue boards with GitLab Enterprise Edition."
@@ -6159,7 +7156,7 @@ msgid "Include a Terms of Service agreement and Privacy Policy that all users mu
msgstr "Включити угоду про Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг та правила конфіденційноÑÑ‚Ñ–, Ñкі повинні прийнÑти вÑÑ– кориÑтувачі."
msgid "Include author name in notification email body"
-msgstr ""
+msgstr "Вказати ім'Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð° в тілі ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¿Ð¾ електронній пошті"
msgid "Include merge request description"
msgstr "Додайте Ð¾Ð¿Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на злиттÑ"
@@ -6182,12 +7179,21 @@ msgstr "Включає Ñтруктуру MVC, mvnw Ñ– pom.xml, щоб допоÐ
msgid "Incompatible Project"
msgstr "ÐеÑуміÑний проект"
+msgid "Incompatible options set!"
+msgstr "Ð’Ñтановлено неÑуміÑні параметри!"
+
+msgid "Indexing"
+msgstr "ІндекÑаціÑ"
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr "Вказує на те, чи може даний runner виконувати Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð±ÐµÐ· тегів"
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr "Вбудований"
@@ -6209,12 +7215,24 @@ msgstr "Додати пропозицію"
msgid "Insights"
msgstr "СтатиÑтика (Insights)"
+msgid "Install"
+msgstr "Ð’Ñтановити"
+
msgid "Install GitLab Runner"
msgstr "Ð’Ñтановити GitLab Runner"
msgid "Install Runner on Kubernetes"
msgstr "Ð’Ñтановити Runner на Kubernetes"
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr "Ð’Ñтановлено"
+
+msgid "Installing"
+msgstr "Ð’ÑтановленнÑ"
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] "ІнÑтанÑ"
@@ -6264,18 +7282,42 @@ msgstr "ПредÑтавлÑємо аналітику циклу"
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr "Ðеправильна дата"
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr "Ðекорректний ввід, будь лаÑка, уникайте Ñмайликів"
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6285,6 +7327,9 @@ msgstr "ЗапрошеннÑ"
msgid "Invite"
msgstr "ЗапрошеннÑ"
+msgid "Invite \"%{trimmed}\" by email"
+msgstr "ЗапроÑити \"%{trimmed}\" за електронною поштою"
+
msgid "Invite group"
msgstr "ЗапроÑити групу"
@@ -6297,6 +7342,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6315,6 +7363,12 @@ msgstr "Задачі"
msgid "Issue template (optional)"
msgstr "Шаблон задачі (необов’Ñзково)"
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr "Дошка"
@@ -6346,7 +7400,7 @@ msgid "Issues closed"
msgstr "Задачі закриті"
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
-msgstr ""
+msgstr "Задачі з коментарÑми, запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð· порівнÑннÑми (diff) та коментарÑми, мітки, етапи, Ñніпети та інші об'єкти в проекті"
msgid "Issues, merge requests, pushes, and comments."
msgstr "Задачі, запити на злиттÑ, Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð´Ñƒ Ñ– коментарі."
@@ -6390,6 +7444,48 @@ msgstr "Ñіч."
msgid "January"
msgstr "Ñічень"
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr "Пароль або API токен"
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr "ВикориÑтовуйте пароль Ð´Ð»Ñ Ñерверної верÑÑ–Ñ— та API токен Ð´Ð»Ñ Ñ…Ð¼Ð°Ñ€Ð½Ð¾Ñ— верÑÑ–Ñ—"
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr "ЗавданнÑ"
@@ -6415,7 +7511,7 @@ msgid "Job is stuck. Check runners."
msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ðµ. Перевірте runner'и."
msgid "Job traces and artifacts"
-msgstr ""
+msgstr "Логи завдань та артефакти"
msgid "Job was retried"
msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¾ перезапущене"
@@ -6448,7 +7544,7 @@ msgid "Job|Keep"
msgstr "Залишити"
msgid "Job|Pipeline"
-msgstr ""
+msgstr "Конвеєр"
msgid "Job|Scroll to bottom"
msgstr "Прокрутити вниз"
@@ -6486,6 +7582,12 @@ msgstr "лип."
msgid "July"
msgstr "липень"
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr "чер."
@@ -6495,6 +7597,9 @@ msgstr "червень"
msgid "Key (PEM)"
msgstr "Ключ (PEM)"
+msgid "Key: %{key}"
+msgstr "Ключ: %{key}"
+
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -6519,17 +7624,23 @@ msgstr "Kubernetes-клаÑтер уÑпішно оновлено."
msgid "Kubernetes configured"
msgstr "Kubernetes налаштовано"
+msgid "Kubernetes error: %{error_code}"
+msgstr "Помилка Kubernetes: %{error_code}"
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr "СпоÑіб Інтеграції Kubernetes Ñк ÑервіÑа заÑтарів. %{deprecated_message_content} ваші Kubernetes-клаÑтери за допомогою нової Ñторінки <a href=\"%{url}\"/>КлаÑтери Kubernetes</a>"
msgid "LDAP settings"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ LDAP"
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr "ВідбуваєтьÑÑ ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ LDAP. Вона може зайнÑти кілька хвилин. Оновлюйте Ñторінку, щоб бачити зміни."
+
msgid "LFS"
msgstr "LFS"
msgid "LFS objects"
-msgstr ""
+msgstr "LFS-об’єкти"
msgid "LFSStatus|Disabled"
msgstr "Вимкнено"
@@ -6537,6 +7648,9 @@ msgstr "Вимкнено"
msgid "LFSStatus|Enabled"
msgstr "Увімкнено"
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr "Мітка"
@@ -6547,13 +7661,13 @@ msgid "Label lists show all issues with the selected label."
msgstr "Ð’ ÑпиÑках на оÑнові міток відображаютьÑÑ Ð»Ð¸ÑˆÐµ Ñ‚Ñ– задачі, Ñкі мають вибрану мітку."
msgid "Label was created"
-msgstr ""
+msgstr "Мітка була Ñтворена"
msgid "Label was removed"
-msgstr ""
+msgstr "Мітку було видалено"
msgid "Label was successfully updated."
-msgstr ""
+msgstr "Мітку було уÑпішно оновлено."
msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
msgstr "%{firstLabelName} + %{remainingLabelCount} ще"
@@ -6585,6 +7699,9 @@ msgstr "ПеренеÑти мітку"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr "ПеренеÑÐµÐ½Ð½Ñ %{labelTitle} на рівень групи зробить Ñ—Ñ— доÑтупною Ð´Ð»Ñ Ð²ÑÑ–Ñ… проектів в групі %{groupName}. ІÑнуючі проектні мітки із такими ж іменами будуть об'єднані. Дана Ð´Ñ–Ñ Ð½Ðµ може бути ÑкаÑована."
+msgid "Labels|and %{count} more"
+msgstr "і ще %{count}"
+
msgid "Language"
msgstr "Мова"
@@ -6601,6 +7718,9 @@ msgstr[3] "ОÑтанніх %d днів"
msgid "Last Pipeline"
msgstr "ОÑтанній Конвеєр"
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ñ–ÑÑ‚ÑŒ"
@@ -6628,6 +7748,12 @@ msgstr "ОÑтаннє оновленнÑ"
msgid "Last updated"
msgstr "ВоÑтаннє оновленно"
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
msgid "LastPushEvent|You pushed to"
msgstr "Ви відправили зміни до"
@@ -6643,6 +7769,12 @@ msgstr "ОÑтанній конвеєр Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— гілки"
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr "ДізнайтеÑÑ Ñк%{link_start}зробити внеÑок до вбудованих шаблонів%{link_end}"
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6661,6 +7793,9 @@ msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Kubernetes"
msgid "Learn more about Web Terminal"
msgstr "ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Веб-термінал"
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про затвердженнÑ."
@@ -6673,6 +7808,9 @@ msgstr "Докладніше про шаблони проектів на рівÐ
msgid "Learn more about signing commits"
msgstr "Докладніше про підпиÑÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñ–Ð²"
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr "ДізнайтеÑÑŒ більше"
@@ -6694,6 +7832,12 @@ msgstr "Залишити проект"
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr "Залиште параметри \"Тип файлу\" та \"Метод доÑтавки\" із значеннÑми по замовчуванню."
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr "ЛіцензіÑ"
@@ -6769,9 +7913,12 @@ msgstr "URL"
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ ліцензію %{name} із цього проекту."
-msgid "Licensed to"
+msgid "Licensed Features"
msgstr ""
+msgid "Licensed to"
+msgstr "Ð›Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñ Ð½Ð°Ð»ÐµÐ¶Ð¸Ñ‚ÑŒ"
+
msgid "Licenses"
msgstr "Ліцензії"
@@ -6785,6 +7932,9 @@ msgstr[1] "Показ обмежено тільки %d подіÑми"
msgstr[2] "Показ обмежено тільки %d подіÑми"
msgstr[3] "Показ обмежено тільки %d подіÑми"
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -6815,6 +7965,9 @@ msgstr "Попередній переглÑд"
msgid "Loading contribution stats for group members"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÑтатиÑтики учаÑників групи"
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ IDE GitLab..."
@@ -6836,6 +7989,9 @@ msgstr "Заблокувати %{issuableDisplayName}"
msgid "Lock not found"
msgstr "Ð‘Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ знайдено"
+msgid "Lock the discussion"
+msgstr "Заблокувати обговореннÑ"
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr "Заблокувати цю %{issuableDisplayName}? Лише <strong>учаÑники проекту</strong> зможуть коментувати."
@@ -6854,11 +8010,14 @@ msgstr "Закріплено за поточними проектами"
msgid "Locks give the ability to lock specific file or folder."
msgstr "Ð‘Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð¾Ð¶Ðµ бути заÑтоÑоване до конкретного файлу або директорії."
+msgid "Locks the discussion"
+msgstr "Блокує обговореннÑ"
+
msgid "Login with smartcard"
msgstr "Вхід за допомогою Ñмарт-картки"
msgid "Logo was successfully removed."
-msgstr ""
+msgstr "Логотип було уÑпішно видалено."
msgid "Logs"
msgstr "Логи"
@@ -6878,15 +8037,24 @@ msgstr "Показувати лише зміни"
msgid "MRDiff|Show full file"
msgstr "Показувати файл повніÑÑ‚ÑŽ"
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr "Зробіть кожного учаÑника команди більш продуктивним незалежно від його міÑцезнаходженнÑ. GitLab Geo Ñтворює копії \"тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ\" вашого GitLab Ñервера, щоб Ñкоротити Ñ‡Ð°Ñ Ð´Ð»Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ– Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ ÐºÐ¾Ð´Ñƒ з великих репозиторіїв."
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr "ПереконайтеÑÑ, що ви ввійшли за допомогою облікового запиÑу, Ñкому належать проекти, що потрібно імпортувати."
-msgid "Manage"
+msgid "Makes this issue confidential"
msgstr ""
+msgid "Manage"
+msgstr "Керувати"
+
msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñми Git за допомогою детального контролю доÑтупу збереже ваш код в безпеці. Виконуйте переглÑд коду та покращуйте Ñпівпрацю за допомогою запитів на злиттÑ. Кожен проект може також мати трекер задач та вікі."
@@ -6944,6 +8112,15 @@ msgstr "бер."
msgid "March"
msgstr "березень"
+msgid "Mark as resolved"
+msgstr "Позначити Ñк вирішене"
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
msgstr "Відмітити Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð¸Ð¼"
@@ -6951,11 +8128,20 @@ msgid "Markdown"
msgstr "Markdown"
msgid "Markdown Help"
-msgstr ""
+msgstr "Довідка по Markdown"
msgid "Markdown enabled"
msgstr "Markdown увімкнено"
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr "Позначає Ð½Ð°Ð³Ð°Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð¸Ð¼."
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr "Maven-метадані"
@@ -6963,7 +8149,7 @@ msgid "Max access level"
msgstr "МакÑимальний рівень доÑтупу"
msgid "Max seats used"
-msgstr ""
+msgstr "МакÑимальна кількіÑÑ‚ÑŒ викориÑтаних міÑць"
msgid "Maximum artifacts size (MB)"
msgstr "МакÑимальний розмір артефактів (МБ)"
@@ -6980,6 +8166,9 @@ msgstr "МакÑимальна затримка (хвилини)"
msgid "Maximum job timeout"
msgstr "МакÑимальний Ñ‡Ð°Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ"
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -7010,6 +8199,9 @@ msgstr "УчаÑники можуть будуть додані <i>КерівнÐ
msgid "Members of <strong>%{project_name}</strong>"
msgstr "УчаÑники <strong>%{project_name}</strong>"
+msgid "Merge"
+msgstr "ЗлиттÑ"
+
msgid "Merge Request"
msgstr "Запит на злиттÑ"
@@ -7022,15 +8214,9 @@ msgstr "Запити на злиттÑ"
msgid "Merge Requests created"
msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð±ÑƒÐ»Ð¾ Ñтворено"
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñƒ-злиттÑ"
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr "Події злиттÑ"
@@ -7040,12 +8226,6 @@ msgstr "Злити негайно"
msgid "Merge in progress"
msgstr "Ð—Ð»Ð¸Ñ‚Ñ‚Ñ Ð² процеÑÑ–"
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr "Запит на злиттÑ"
@@ -7064,6 +8244,30 @@ msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ â€” це ÑпоÑіб запропонувÐ
msgid "Merge when pipeline succeeds"
msgstr "Злити, коли конвеєр уÑпішно завершитьÑÑ"
+msgid "MergeConflict|Commit to source branch"
+msgstr "Закомітити в гілку-джерело"
+
+msgid "MergeConflict|Committing..."
+msgstr "Коміт..."
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr "HEAD//ваші зміни"
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr "конфлікт"
+
+msgid "MergeConflict|conflicts"
+msgstr "конфлікти"
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr "Додати відповідь"
@@ -7082,6 +8286,9 @@ msgstr "ÐžÐ±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ вирішеним"
msgid "MergeRequests|Discussion will be unresolved"
msgstr "ÐžÐ±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ невирішеним"
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr "ÐевдалоÑÑ Ð¾Ð±â€™Ñ”Ð´Ð½Ð°Ñ‚Ð¸ коміти. Це повинно бути виконано вручну."
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr "Перейти до наÑтупного невирішеного обговореннÑ"
@@ -7094,6 +8301,9 @@ msgstr "Вирішити це Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð² новій задачі"
msgid "MergeRequests|Saving the comment failed"
msgstr "Помилка при збереженні коментарÑ"
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr "ÐžÐ±â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñ–Ð² відхилено: інше Ð¾Ð±â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð²Ð¶Ðµ відбуваєтьÑÑ."
+
msgid "MergeRequests|Toggle comments for this file"
msgstr "Увімкнути або вимкнути коментарі Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ файлу"
@@ -7127,8 +8337,8 @@ msgstr "%{paragraphStart} Ð¾Ð¿Ð¸Ñ Ð·Ð¼Ñ–Ð½ÐµÐ½Ð¾ %{descriptionChangedTimes} Ñ€Ð
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr "Помилка при заванаженні повного порівнÑннÑ. Будь лаÑка, Ñпробуйте знову."
-msgid "MergeRequest|Filter files"
-msgstr "Фільтр файлів"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
+msgstr "Фільтрувати файли або шукати за допомогою%{modifier_key}+p"
msgid "MergeRequest|No files found"
msgstr "Файлів не знайдено"
@@ -7137,11 +8347,17 @@ msgid "Merged"
msgstr "Злито"
msgid "Merged branches are being deleted. This can take some time depending on the number of branches. Please refresh the page to see changes."
-msgstr ""
+msgstr "Злиті гілки в процеÑÑ– видаленнÑ. Це може зайнÑти деÑкий Ñ‡Ð°Ñ Ð² залежноÑÑ‚Ñ– від Ñ—Ñ… кількоÑÑ‚Ñ–. Будь лаÑка, оновіть Ñторінку, щоб побачити зміни."
msgid "Messages"
msgstr "ПовідомленнÑ"
+msgid "Metric was successfully added."
+msgstr "Метрику уÑпішно додано."
+
+msgid "Metric was successfully updated."
+msgstr "Метрику уÑпішно оновлено."
+
msgid "Metrics"
msgstr "Метрики"
@@ -7157,6 +8373,9 @@ msgstr "Метрики та профілюваннÑ"
msgid "Metrics for environment"
msgstr "Метрики Ð´Ð»Ñ Ñередовища"
+msgid "Metrics|Add metric"
+msgstr "Додати метрику"
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "Перевірте документацію CI/CD щодо Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð² Ñередовищі"
@@ -7196,9 +8415,6 @@ msgstr "Ðова метрика"
msgid "Metrics|No deployed environments"
msgstr "Ðемає розгорнутих Ñередовищ"
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr "Запит PromQL Ñ” дійÑним"
@@ -7206,7 +8422,7 @@ msgid "Metrics|Prometheus Query Documentation"
msgstr "Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ Ð¿Ð¾ запитам Prometheus"
msgid "Metrics|Show last"
-msgstr ""
+msgstr "Показати оÑтанні"
msgid "Metrics|There was an error fetching the environments data, please try again"
msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ— про Ñередовища. Будь лаÑка, Ñпробуйте ще раз"
@@ -7244,14 +8460,26 @@ msgstr "Ðазва оÑÑ– Y"
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити цю метрику. Це не можна відмінити."
+msgid "Metrics|e.g. HTTP requests"
+msgstr "напр. HTTP-запити"
+
+msgid "Metrics|e.g. Requests/second"
+msgstr "напр. запитів/Ñек"
+
msgid "Metrics|e.g. Throughput"
msgstr "напр. пропуÑкна здатніÑÑ‚ÑŒ"
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr "напр. rate(http_requests_total[5m])"
+
+msgid "Metrics|e.g. req/sec"
+msgstr "напр. зап/Ñек"
+
msgid "Migrated %{success_count}/%{total_count} files."
-msgstr ""
+msgstr "ПеренеÑено %{success_count}/%{total_count} файлів."
msgid "Migration successful."
-msgstr ""
+msgstr "ÐœÑ–Ð³Ñ€Ð°Ñ†Ñ–Ñ ÑƒÑпішна."
msgid "Milestone"
msgstr "Етап"
@@ -7271,9 +8499,6 @@ msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити етап %
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити етап %{milestoneTitle}. Ðаразі цей етап не викориÑтовуєтьÑÑ Ð² жодних задачах або запитах на злиттÑ."
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr "<p>%{milestonePromotion}</p> %{finalWarning}"
-
msgid "Milestones|Delete milestone"
msgstr "Видалити етап"
@@ -7292,8 +8517,8 @@ msgstr "ПеренеÑти %{milestoneTitle} на рівень групи?"
msgid "Milestones|Promote Milestone"
msgstr "ПеренеÑти етап"
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
-msgstr "ПеренеÑÐµÐ½Ð½Ñ %{milestone} на рівень групи зробить його доÑтупним Ð´Ð»Ñ Ð²ÑÑ–Ñ… проектів в групі %{groupName}. ІÑнуючі проектні етапи з такими ж іменами будуть об'єднані. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
+msgstr "ПеренеÑÐµÐ½Ð½Ñ %{milestoneTitle} на рівень групи зробить його доÑтупним Ð´Ð»Ñ Ð²ÑÑ–Ñ… проектів в групі %{groupName}. ІÑнуючі проектні етапи з такими ж заголовками будуть об'єднані."
msgid "Milestones|This action cannot be reversed."
msgstr "Цю дію не можна ÑкаÑувати."
@@ -7301,6 +8526,15 @@ msgstr "Цю дію не можна ÑкаÑувати."
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr "Хвилин"
+
msgid "Mirror a repository"
msgstr "Віддзеркалити репозиторій"
@@ -7320,6 +8554,18 @@ msgid "Mirroring repositories"
msgstr "Ð’Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ—Ð²"
msgid "Mirroring settings were successfully updated."
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¸ уÑпішно змінені."
+
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¸ уÑпішно змінені. Проект оновлюєтьÑÑ."
+
+msgid "Mirroring was successfully disabled."
+msgstr "Ð’Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ ÑƒÑпішно вимкнено."
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr "Ð’Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ñтупне тільки Ñкщо Ñ†Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ð¾Ð½Ð°Ð»ÑŒÐ½Ñ–ÑÑ‚ÑŒ включена в план Ð´Ð»Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ð¾Ð³Ð¾ кориÑтувача або групи."
+
+msgid "Missing commit signatures endpoint!"
msgstr ""
msgid "MissingSSHKeyWarningLink|add an SSH key"
@@ -7382,6 +8628,24 @@ msgstr "ПереміÑтити"
msgid "Move issue"
msgstr "ПереміÑтити задачу"
+msgid "Move issue from one column of the board to another"
+msgstr "ПереміÑтити задачу із однієї колонки дошки до іншої"
+
+msgid "Move this issue to another project."
+msgstr "ПереміÑтити цю задачу до іншого проекту."
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr "Ðеможливо переміÑтити задачу через недоÑтатній набір дозволів!"
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr "Ðеможливо перенеÑти задачу до проекту, в Ñкому вона знаходитьÑÑ!"
+
+msgid "Moves issue to %{label} column in the board."
+msgstr "ПереміÑтити задачу в колонку %{label} на дошці."
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr "Переміщує задачі до %{path_to_project}."
+
msgid "Multiple issue boards"
msgstr "Кілька дошок обговореннÑ"
@@ -7394,6 +8658,9 @@ msgstr ""
msgid "Name"
msgstr "Ім’Ñ"
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr "Ðазвіть нову мітку"
@@ -7407,7 +8674,7 @@ msgid "Namespaces to index"
msgstr ""
msgid "Naming, topics, avatar"
-msgstr ""
+msgstr "ІменуваннÑ, теми, аватар"
msgid "Naming, visibility"
msgstr "ÐайменуваннÑ, видиміÑÑ‚ÑŒ"
@@ -7491,6 +8758,9 @@ msgstr "Ðове Ñередовище"
msgid "New epic"
msgstr "Ðовий епік"
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr "Ðовий файл"
@@ -7515,6 +8785,9 @@ msgstr "Ðовий запит на злиттÑ"
msgid "New milestone"
msgstr "Ðовий етап"
+msgid "New password"
+msgstr "Ðовий пароль"
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr "Ðові конвеєри ÑкаÑують Ñтарі, що очікують на тій же гілці"
@@ -7545,6 +8818,12 @@ msgstr "Ðовий..."
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr "Далі"
+
+msgid "Nickname"
+msgstr "ПÑевдонім"
+
msgid "No"
msgstr "ÐÑ–"
@@ -7554,12 +8833,21 @@ msgstr "Ðемає репозиторіїв %{providerTitle} Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚
msgid "No Label"
msgstr "Без Мітки"
+msgid "No Milestone"
+msgstr "Етап відÑутній"
+
msgid "No Tag"
msgstr "Ðемає тегів"
msgid "No activities found"
msgstr "Ðе знайднено активноÑтей"
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr "Гілок не знайдено"
@@ -7575,6 +8863,9 @@ msgstr "Ðеможливо з'єднатиÑÑŒ із Ñервером Gitaly, бÑ
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr "Ð’ цьому проекті немає жодного образа контейнера. Додайте його за інÑтрукціÑми вище."
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr "ВнеÑки не знайдено"
@@ -7599,6 +8890,9 @@ msgstr "Файл не вибрано"
msgid "No file selected"
msgstr "Файл не вибраний"
+msgid "No files"
+msgstr "Ðемає файлів"
+
msgid "No files found."
msgstr "Ðе знайдено жодного файлу."
@@ -7606,7 +8900,7 @@ msgid "No issues for the selected time period."
msgstr "Ðемає задач за вибраний період чаÑу."
msgid "No job trace"
-msgstr ""
+msgstr "Ðемає логу завданнÑ"
msgid "No labels with such name or description"
msgstr "Ðемає міток з таким іменем або опиÑом"
@@ -7620,9 +8914,6 @@ msgstr ""
msgid "No matching results"
msgstr "Ðемає відповідних результатів"
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr "Ðемає запитів на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð° вибраний період чаÑу."
@@ -7638,6 +8929,9 @@ msgstr "Ðемає етапів Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ñƒ"
msgid "No other labels with such name or description"
msgstr "Ðемає інших міток з таким іменем або опиÑом"
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr "Попереднього переглÑду Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ типу файлів немає"
@@ -7665,6 +8959,12 @@ msgstr "Ðемає дати початку"
msgid "No, directly import the existing email addresses and usernames."
msgstr "ÐÑ–, безпоÑередньо імпортувати Ñ–Ñнуючі адреÑи електронної пошти та імена кориÑтувачів."
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr "Вузли"
@@ -7687,7 +8987,7 @@ msgid "Not enough data"
msgstr "ÐедоÑтатньо даних"
msgid "Not found."
-msgstr ""
+msgstr "Ðе знайдено."
msgid "Not now"
msgstr "Пізніше"
@@ -7713,6 +9013,9 @@ msgstr "Примітка: звернітьÑÑ Ð´Ð¾ вашого адмініÑÑ
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr "Примітка: звернітьÑÑ Ð´Ð¾ вашого адмініÑтратора GitLab, щоб налаштувати %{github_integration_link}, Ñкий дозволить входити за допомогою GitHub та імпортувати репозиторії без генерації перÑонального токена доÑтупу."
+msgid "NoteForm|Note"
+msgstr "Примітка"
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "Ви впевнені, що хочете ÑкаÑувати цей коментар?"
@@ -7728,6 +9031,12 @@ msgstr "Показати тільки коментарі"
msgid "Notes|Show history only"
msgstr "Показати лише Ñ–Ñторію"
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ події"
@@ -7737,6 +9046,9 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñповіщень"
msgid "Notification setting - %{notification_title}"
msgstr "Параметр ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ - %{notification_title}"
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "Задача закрита"
@@ -7791,6 +9103,9 @@ msgstr "Берете учаÑÑ‚ÑŒ"
msgid "NotificationLevel|Watch"
msgstr "ВідÑтежувати"
+msgid "NotificationSetting|Custom"
+msgstr "ВлаÑний"
+
msgid "Notifications"
msgstr "СповіщеннÑ"
@@ -7806,6 +9121,12 @@ msgstr "лиÑÑ‚."
msgid "November"
msgstr "лиÑтопад"
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr "OK"
@@ -7821,8 +9142,14 @@ msgstr "жовтень"
msgid "OfSearchInADropdown|Filter"
msgstr "Фільтр"
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
-msgstr "ПіÑÐ»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ репозиторії можуть бути віддзеркалені через SSH. ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
+msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
msgstr ""
@@ -7846,14 +9173,14 @@ msgstr "Один або декілька ваших проектів Bitbucket Ð
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "Один або декілька ваших проектів Google Code не можна імпортувати безпоÑередньо в GitLab, оÑкільки вони викориÑтовують Subversion або Mercurial Ð´Ð»Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŽ верÑій заміÑÑ‚ÑŒ Git."
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
+msgstr ""
+
msgid "Only admins"
msgstr "Тільки Ðдміни"
-msgid "Only allow merge requests to be merged if all discussions are resolved"
-msgstr ""
-
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
-msgstr ""
+msgid "Only admins can delete project"
+msgstr "Тільки адмініÑтратори можуть видалÑти проект"
msgid "Only mirror protected branches"
msgstr "Віддзеркалювати лише захищені гілки"
@@ -7870,6 +9197,9 @@ msgstr "Тільки учаÑники проекту можуть залишат
msgid "Only project members will be imported. Group members will be skipped."
msgstr "Лише учаÑника проекту будуть імпортовані. УчаÑники групи будуть пропущені."
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr "Ой, а ви впевнені?"
@@ -7915,6 +9245,12 @@ msgstr "Відкрито"
msgid "Opens in a new window"
msgstr "ВідкриваєтьÑÑ Ñƒ новому вікні"
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr "Операції"
@@ -7928,22 +9264,19 @@ msgid "OperationsDashboard|Add a project to the dashboard"
msgstr "Додайте проект до панелі керуваннÑ"
msgid "OperationsDashboard|Add projects"
-msgstr ""
+msgstr "Додати проекти"
msgid "OperationsDashboard|More information"
-msgstr ""
+msgstr "Детальніше"
msgid "OperationsDashboard|Operations Dashboard"
-msgstr ""
+msgstr "Панель ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñми"
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr "Панель ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñми міÑтить інформацію про Ñтан кожного з проектів разом зі Ñтаном його конвеєрів та попереджень."
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr "Ðеможливо додати %{invalidProjects}. Панель ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñми доÑтупна Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ñ–Ñ‡Ð½Ð¸Ñ… та приватних проектів в групах із тарифним планом Gold."
-
msgid "Optional"
-msgstr ""
+msgstr "Ðеобов'Ñзково"
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "За необхідноÑÑ‚Ñ– ви можете %{link_to_customize} Ñк адреÑи електронної почти та імена кориÑтувачів FobBugz будуть імпортовані у GitLab."
@@ -7963,6 +9296,9 @@ msgstr "Інші мітки"
msgid "Other information"
msgstr "Інша інформаціÑ"
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr "Вихідні запити"
@@ -7972,6 +9308,12 @@ msgstr "ОглÑд"
msgid "Overwrite diverged branches"
msgstr "ПерезапиÑати розбіжні гілки"
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr "Ті, що належать мені"
+
msgid "Owner"
msgstr "ВлаÑник"
@@ -7985,10 +9327,10 @@ msgid "Packages"
msgstr "Пакети"
msgid "Page not found"
-msgstr ""
+msgstr "Сторінку не знайдено"
msgid "Page was successfully deleted"
-msgstr ""
+msgstr "Сторінку було уÑпішно видалено"
msgid "Pages"
msgstr "Сторінки"
@@ -7999,6 +9341,9 @@ msgstr "Домен Pages"
msgid "Pages Domains"
msgstr "Домени Pages"
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ Â»"
@@ -8020,7 +9365,19 @@ msgstr "ЧаÑтина змін у запиті на злиттÑ"
msgid "Password"
msgstr "Пароль"
+msgid "Password (optional)"
+msgstr "Пароль (необов'Ñзково)"
+
msgid "Password authentication is unavailable."
+msgstr "Парольна Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ Ð½ÐµÐ´Ð¾Ñтупна."
+
+msgid "Password confirmation"
+msgstr "ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»ÑŽ"
+
+msgid "Password successfully changed"
+msgstr "Пароль змінено уÑпішно"
+
+msgid "Password was successfully updated. Please login with it"
msgstr ""
msgid "Past due"
@@ -8035,14 +9392,14 @@ msgstr "Ð’Ñтавити поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° епік"
msgid "Paste issue link"
msgstr "Ð’Ñтавити поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° задачу"
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
-msgstr "Ð’Ñтавте Ñвій відкритий ключ SSH, Ñкий зазвичай знаходитьÑÑ Ñƒ файлі '~/.ssh/id_rsa.pub' Ñ– починаєтьÑÑ Ð· 'ssh-rsa'. Ðе викориÑтовуйте Ñвій приватний ключ SSH."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
msgid "Path"
-msgstr ""
+msgstr "ШлÑÑ…"
msgid "Path, transfer, remove"
-msgstr "ШлÑÑ…, передача, видаленнÑ"
+msgstr "ШлÑÑ…, перенеÑеннÑ, видаленнÑ"
msgid "Path:"
msgstr "ШлÑÑ…:"
@@ -8062,6 +9419,9 @@ msgstr "В очікуванні"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr "Люди без дозволу ніколи не отримуватимуть Ñповіщень Ñ– не зможуть коментувати."
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr "Виконуйте такі розширені операції, Ñк зміна шлÑху, перенеÑÐµÐ½Ð½Ñ Ñ‡Ð¸ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð³Ñ€ÑƒÐ¿Ð¸."
@@ -8083,12 +9443,27 @@ msgstr "Токену перÑонального доÑтупу"
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr "Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿ÐµÑ€Ñональних проектів не дозволено. Будь лаÑка, звернітьÑÑ Ð´Ð¾ Ñвого адмініÑтратор із питаннÑми"
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr "Виберіть ім'Ñ"
+msgid "Pin code"
+msgstr "PIN-код"
+
msgid "Pipeline"
msgstr "Конвеєр"
+msgid "Pipeline ID (IID)"
+msgstr "Ідентифікатор конвеєра (IID)"
+
msgid "Pipeline Schedule"
msgstr "Розклад Конвеєра"
@@ -8105,7 +9480,7 @@ msgid "Pipeline triggers"
msgstr "Тригери конвеєру"
msgid "Pipeline: %{status}"
-msgstr ""
+msgstr "Конвеєр: %{status}"
msgid "PipelineCharts|Failed:"
msgstr "Ðевдалі:"
@@ -8167,6 +9542,9 @@ msgstr "Конвеєри"
msgid "Pipelines charts"
msgstr "СтатиÑтика конвеєрів"
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr "Конвеєри за оÑтанній міÑÑць"
@@ -8176,12 +9554,15 @@ msgstr "Конвеєри за оÑтанній тиждень"
msgid "Pipelines for last year"
msgstr "Конвеєри за оÑтанній рік"
-msgid "Pipelines need to be configured to enable this feature."
-msgstr "Ðеобхідно налаштувати конвеєри щоб увімкнути цю функцію."
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
+msgstr "API"
+
msgid "Pipelines|Build with confidence"
msgstr "Виконуйте збірки із впевненіÑÑ‚ÑŽ"
@@ -8200,6 +9581,9 @@ msgstr "Розпочати роботу з Конвеєрами"
msgid "Pipelines|Loading Pipelines"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²"
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "Кеш проекту уÑпішно очищено."
@@ -8225,7 +9609,7 @@ msgid "Pipeline|Commit"
msgstr "Коміт"
msgid "Pipeline|Coverage"
-msgstr ""
+msgstr "ПокриттÑ"
msgid "Pipeline|Duration"
msgstr "ТриваліÑÑ‚ÑŒ"
@@ -8240,7 +9624,7 @@ msgid "Pipeline|Run Pipeline"
msgstr "ЗапуÑтити Конвеєр"
msgid "Pipeline|Run for"
-msgstr ""
+msgstr "ЗапуÑтити длÑ"
msgid "Pipeline|Search branches"
msgstr "Пошук гілки"
@@ -8260,6 +9644,9 @@ msgstr "Зупинити конвеєр"
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr "Зупинити конвеєр #%{pipelineId}?"
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr "Змінні"
@@ -8290,6 +9677,15 @@ msgstr "зі Ñтадією"
msgid "Pipeline|with stages"
msgstr "зі ÑтадіÑми"
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr "API токен Pivotal Tracker."
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr "ПроÑте порівнÑннÑ"
@@ -8299,12 +9695,30 @@ msgstr "PlantUML"
msgid "Play"
msgstr "Відтворити"
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr "Будь лаÑка, %{link_to_register} або %{link_to_sign_in} щоб прокоментувати"
msgid "Please accept the Terms of Service before continuing."
msgstr "Будь лаÑка, Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸Ð¹Ð¼Ñ–Ñ‚ÑŒ умови Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг."
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr "Будь лаÑка задайте URL групи без Ñпеціальних Ñимволів."
@@ -8335,6 +9749,9 @@ msgstr "Будь лаÑка, введіть чиÑло більше за %{numbe
msgid "Please enter a valid number"
msgstr "Будь лаÑка, введіть дійÑний номер"
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr "Введіть опиÑове ім'Ñ Ð³Ñ€ÑƒÐ¿Ð¸."
@@ -8347,9 +9764,18 @@ msgstr "Зверніть увагу, що Ñ†Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð° не Ñ” чаÑÑ‚
msgid "Please provide a name"
msgstr "Будь лаÑка, задайте ім’Ñ"
-msgid "Please select a group."
+msgid "Please provide a valid email address."
+msgstr "Будь лаÑка, вкажіть дійÑну e-mail адреÑу."
+
+msgid "Please retype the email address."
msgstr ""
+msgid "Please select a file"
+msgstr "Будь лаÑка, виберіть файл"
+
+msgid "Please select a group."
+msgstr "Будь лаÑка, оберіть групу."
+
msgid "Please select and add a member"
msgstr "Будь лаÑка, виберіть Ñ– додайте учаÑника"
@@ -8368,11 +9794,11 @@ msgstr "Будь лаÑка, Ñпробуйте ще раз"
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr "Будь лаÑка, оновіть PostgreSQL до верÑÑ–Ñ— 9.6 або вище. Стан реплікації не може бути доÑтовірно визначений у поточній верÑÑ–Ñ—."
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
-msgstr "Будь лаÑка, викориÑтовуйте цю форму, щоб повідомлÑти GitLab про кориÑтувачів, Ñкі Ñтворюють задачі Ñ– коментарі зі Ñпамом, або поводÑÑ‚ÑŒÑÑ Ð½ÐµÐ²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¾."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
+msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
-msgstr ""
+msgstr "Будь лаÑка, зачекайте, Ñ†Ñ Ñторінка автоматично оновитьÑÑ, коли буде готова."
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr "Будь лаÑка, почекайте поки ми з’єднуємоÑÑ Ñ–Ð· вашим репозиторієм. Оновлюйте Ñторінку за бажаннÑм."
@@ -8384,14 +9810,68 @@ msgid "Preferences"
msgstr "ÐалаштуваннÑ"
msgid "Preferences saved."
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð¾."
+
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr "Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу у 24-годинному форматі"
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr "Ðаприклад: 30 хвилин тому."
+
+msgid "Preferences|Layout width"
msgstr ""
msgid "Preferences|Navigation theme"
msgstr "Тема навігації"
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr "Ці Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÐ³ÑƒÐ»ÑŽÑŽÑ‚ÑŒ Ñк Ð´Ð»Ñ Ð²Ð°Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶Ð°Ñ‚Ð¸Ð¼ÐµÑ‚ÑŒÑÑ Ð´Ð°Ñ‚Ð° Ñ– чаÑ."
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr "Ð¦Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ Ñ” екÑпериментальною Ñ– переклади ще не завершені"
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr "Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу"
+
+msgid "Preferences|Time format"
+msgstr "Формат чаÑу"
+
+msgid "Preferences|Time preferences"
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡Ð°Ñу"
+
+msgid "Preferences|Use relative times"
+msgstr "ВикориÑтовувати відноÑний чаÑ"
+
+msgid "Press %{key}-C to copy"
+msgstr "ÐатиÑніть %{key}-C, щоб Ñкопіювати"
+
msgid "Press Enter or click to search"
msgstr "Ð”Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ натиÑніть Enter або клікніть"
@@ -8407,12 +9887,18 @@ msgstr ""
msgid "Preview"
msgstr "Попередній переглÑд"
+msgid "Preview Markdown"
+msgstr "Попередній переглÑд Markdown"
+
msgid "Preview changes"
-msgstr ""
+msgstr "Попередній переглÑд змін"
msgid "Preview payload"
msgstr "Попередній переглÑд кориÑного навантаженнÑ"
+msgid "Previous Artifacts"
+msgstr "Попередні артефакти"
+
msgid "Primary"
msgstr "Головний"
@@ -8438,17 +9924,26 @@ msgid "Private - The group and its projects can only be viewed by members."
msgstr "Приватна — цю групу та Ñ—Ñ— проекти можуть бачити тільки Ñ—Ñ— кориÑтувачі."
msgid "Private group(s)"
-msgstr ""
+msgstr "Приватна група(и)"
+
+msgid "Private profile"
+msgstr "Приватний профіль"
msgid "Private projects can be created in your personal namespace with:"
msgstr "Приватні проекти можуть бути Ñтворені у вашому перÑональному проÑторі імен з:"
+msgid "Proceed"
+msgstr "Продовжити"
+
msgid "Profile"
msgstr "Профіль"
msgid "Profile Settings"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ„Ñ–Ð»ÑŽ"
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити %{yourAccount}, а також вÑÑ– задачі, запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° групи, пов'Ñзані з вашим обліковим запиÑом. ПіÑÐ»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ %{deleteAccount}, його неможливо буде відновити."
@@ -8479,6 +9974,9 @@ msgstr "Обрізка аватарів"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "Ðватар буде видалено. Ви впевнені?"
+msgid "Profiles|Bio"
+msgstr "Про Ñебе"
+
msgid "Profiles|Change username"
msgstr "Змінити ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
@@ -8500,6 +9998,9 @@ msgstr "ОчиÑтити ÑтатуÑ"
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr "Клікніть на іконку, щоб активувати вхід за допомогою одного із наÑтупних ÑервіÑів"
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr "Приєднати"
@@ -8512,6 +10013,9 @@ msgstr "Поточний шлÑÑ…: %{path}"
msgid "Profiles|Current status"
msgstr "Поточний Ñтан"
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr "Видалити обліковий запиÑ"
@@ -8539,6 +10043,18 @@ msgstr "Редагувати профіль"
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr "Введіть ваше ім'Ñ, щоб люди, Ñких ви знаєте, могли Ð²Ð°Ñ ÑƒÐ¿Ñ–Ð·Ð½Ð°Ñ‚Ð¸"
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr "Повне ім'Ñ"
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr "Підвищити рівень безпеки вашого облікового запиÑу за допомогою ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð´Ð²Ð¾Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾Ñ— автентифікації (2FA)"
@@ -8548,9 +10064,15 @@ msgstr "Ðеправильний пароль"
msgid "Profiles|Invalid username"
msgstr "Ðеправильне ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
+msgid "Profiles|Key"
+msgstr "Ключ"
+
msgid "Profiles|Learn more"
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ"
+msgid "Profiles|Location"
+msgstr "РозташуваннÑ"
+
msgid "Profiles|Made a private contribution"
msgstr "Cтворив приватний внеÑок"
@@ -8560,18 +10082,33 @@ msgstr "Головні налаштуваннÑ"
msgid "Profiles|No file chosen"
msgstr "Файл не вибрано"
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr "ОрганізаціÑ"
+
msgid "Profiles|Path"
msgstr "ШлÑÑ…"
msgid "Profiles|Position and size your new avatar"
msgstr "Спозиціонуйте ваш аватар та задайте його розмір"
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr "Приватні внеÑки"
+msgid "Profiles|Profile was successfully updated"
+msgstr "Профіль було уÑпішно оновлено"
+
msgid "Profiles|Public Avatar"
msgstr "Публічний аватар"
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr "Видалити аватар"
@@ -8590,9 +10127,6 @@ msgstr "Розкажіть про Ñебе в межах 250 Ñимволів"
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "МакÑимальний розмір файлу 200КБ."
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "Це не Ñхоже на публічниц ключ SSH. Ви впевнені, що хочете його додати?"
@@ -8608,14 +10142,17 @@ msgstr "Цей Ñмайлик та Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ´ÑƒÑ‚ÑŒ покÐ
msgid "Profiles|This information will appear on your profile"
msgstr "Ð¦Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð±ÑƒÐ´Ðµ відображатиÑÑ Ñƒ вашому профілі"
+msgid "Profiles|Time settings"
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡Ð°Ñу"
+
msgid "Profiles|Two-Factor Authentication"
msgstr "Двофакторна автентифікаціÑ"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Введіть ваш %{confirmationValue} Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ:"
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
-msgstr "Зазвичай починаєтьÑÑ Ð· \"ssh-rsa ...\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
+msgstr ""
msgid "Profiles|Update profile settings"
msgstr "Оновити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ„Ñ–Ð»ÑŽ"
@@ -8629,6 +10166,9 @@ msgstr "Завантажити новий аватар"
msgid "Profiles|Use a private email - %{email}"
msgstr "ВикориÑтовувати приватну адреÑу електронної пошти - %{email}"
+msgid "Profiles|User ID"
+msgstr "Ідентифікатор кориÑтувача"
+
msgid "Profiles|Username change failed - %{message}"
msgstr "Помилка при збереженні імені кориÑтувача - %{message}"
@@ -8650,6 +10190,9 @@ msgstr "Тут ви можете змінити Ñвій аватар"
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr "Тут ви можете змінити Ñвій аватар або видалити його та повернутиÑÑ Ð´Ð¾ %{gravatar_link}"
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr "Тут ви можете завантажити Ñвій аватар"
@@ -8708,10 +10251,10 @@ msgid "Project \"%{name}\" is no longer available. Select another project to con
msgstr "Проект \"%{name}\" більше не доÑтупний. Щоб продовжити виберіть інший проект."
msgid "Project %{project_repo} could not be found"
-msgstr ""
+msgstr "Проект %{project_repo} не знайдено"
msgid "Project '%{project_name}' is being imported."
-msgstr ""
+msgstr "Проект \"%{project_name}\" імпортуєтьÑÑ."
msgid "Project '%{project_name}' is in the process of being deleted."
msgstr "Проект '%{project_name}' перебуває в процеÑÑ– видаленнÑ."
@@ -8729,7 +10272,7 @@ msgid "Project Badges"
msgstr "Значки проекту"
msgid "Project ID"
-msgstr ""
+msgstr "Ідентифікатор проекту"
msgid "Project URL"
msgstr "URL-адреÑа проекту"
@@ -8738,16 +10281,19 @@ msgid "Project access must be granted explicitly to each user."
msgstr "ДоÑтуп до проекту повинен надаватиÑÑ ÐºÐ¾Ð¶Ð½Ð¾Ð¼Ñƒ кориÑтувачеві."
msgid "Project and wiki repositories"
-msgstr ""
+msgstr "Репозиторії проекту та вікі"
msgid "Project avatar"
msgstr "Ðватар проекту"
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
msgid "Project description (optional)"
-msgstr ""
+msgstr "ÐžÐ¿Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñƒ (необов'Ñзково)"
msgid "Project details"
msgstr "Деталі проекту"
@@ -8756,7 +10302,7 @@ msgid "Project export could not be deleted."
msgstr "Ðеможливо видалити екÑпорт проекту."
msgid "Project export enabled"
-msgstr ""
+msgstr "ЕкÑпорт проекту ввімкнено"
msgid "Project export has been deleted."
msgstr "ЕкÑпорт проекту видалений."
@@ -8783,11 +10329,14 @@ msgid "Project uploads"
msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
-msgstr ""
+msgstr "Рівень видимоÑÑ‚Ñ– проекту буде змінено відповідно до правил проÑтору імен під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ½ÐµÑÐµÐ½Ð½Ñ Ð´Ð¾ групи."
msgid "Project:"
msgstr "Проект:"
+msgid "Project: %{name}"
+msgstr "Проект %{name}"
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "ПідпиÑатиÑÑ"
@@ -8839,6 +10388,24 @@ msgstr "Ви повинні увійти, щоб додати проект в о
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "ID проекту: %{project_id}"
+msgid "ProjectSelect| or group"
+msgstr "або групу"
+
+msgid "ProjectSelect|Search for project"
+msgstr "Пошук проекту"
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr "Значки"
@@ -8848,18 +10415,60 @@ msgstr "ЗвернітьÑÑ Ð´Ð¾ адмініÑтратора, щоб змінÐ
msgid "ProjectSettings|Customize your project badges."
msgstr "Ðалаштувати значки проекту."
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr "Помилка при захиÑÑ‚Ñ– тегу"
msgid "ProjectSettings|Failed to update tag!"
msgstr "Помилка при оновленні тегу!"
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про значки."
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Тільки підпиÑані коміти можуть бути надіÑлані в цей репозиторій."
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr "Цей параметр заÑтоÑовуєтьÑÑ Ð½Ð° рівні Ñервера та може бути перевизначений адмініÑтратором."
@@ -8869,14 +10478,74 @@ msgstr "Цей параметр заÑтоÑовуєтьÑÑ Ð½Ð° рівні ÑÐ
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "Цей параметр буде заÑтоÑовано до вÑÑ–Ñ… проектів, Ñкщо адмініÑтратор не змінить його."
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr "КориÑтувачі можуть відправлÑти в цей репозиторій лише Ñ‚Ñ– коміти, Ñкі міÑÑ‚ÑÑ‚ÑŒ одну із їхніх підтверджених Ð°Ð´Ñ€ÐµÑ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти."
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ".NET Core"
+
+msgid "ProjectTemplates|Android"
+msgstr "Android"
+
+msgid "ProjectTemplates|Go Micro"
+msgstr "Go Micro"
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr "Netlify/GitBook"
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr "Netlify/Hexo"
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr "Netlify/Hugo"
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr "Netlify/Jekyll"
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr "Netrify/Plain HTML"
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr "NodeJS Express"
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr "Pages/GitBook"
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr "Pages/Hexo"
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr "Pages/Hugo"
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr "Pages/Jekyll"
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr "Pages/проÑтий HTML"
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr "Ruby on Rails"
+
+msgid "ProjectTemplates|Spring"
+msgstr "Spring"
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr "iOS (Swift)"
+
msgid "Projects"
msgstr "Проекти"
+msgid "Projects (%{count})"
+msgstr "Проекти (%{count})"
+
msgid "Projects Successfully Retrieved"
-msgstr ""
+msgstr "Проекти уÑпішно отримано"
msgid "Projects shared with %{group_name}"
msgstr "Спільні проекти з %{group_name}"
@@ -8885,10 +10554,10 @@ msgid "Projects that belong to a group are prefixed with the group namespace. Ex
msgstr "Проекти, що належать до групи, викориÑтовують Ñ—Ñ— ім'Ñ Ñк префікÑ. ІÑнуючі проекти можуть бути переміщені в групу."
msgid "Projects to index"
-msgstr ""
+msgstr "Проекти Ð´Ð»Ñ Ñ–Ð½Ð´ÐµÐºÑуваннÑ"
msgid "Projects with write access"
-msgstr ""
+msgstr "Проекти з правом на запиÑ"
msgid "ProjectsDropdown|Frequently visited"
msgstr "ЧаÑто відвідувані"
@@ -8939,7 +10608,7 @@ msgid "PrometheusAlerts|Operator"
msgstr "Оператор"
msgid "PrometheusAlerts|Select query"
-msgstr ""
+msgstr "Вибрати запит"
msgid "PrometheusAlerts|Threshold"
msgstr "Поріг"
@@ -9031,6 +10700,15 @@ msgstr "ПеренеÑти Етап на рівень групи"
msgid "Promote to group label"
msgstr "ПеренеÑти мітку на рівень групи"
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr "Проект не належить жодній групі."
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr "Більше не показувати це"
@@ -9049,36 +10727,48 @@ msgstr ""
msgid "Protected"
msgstr "Захищено"
+msgid "Protected Branch"
+msgstr "Захищена гілка"
+
+msgid "Protected Environment"
+msgstr "Захищене Ñередовище"
+
msgid "Protected Environments"
msgstr "Захищені Ñередовища"
+msgid "Protected Tag"
+msgstr "Захищений тег"
+
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} буде доÑупне Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñу Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÑ–Ð². Ви впевнені?"
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "Ð Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÐµÐ½Ð¾"
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
-msgstr "Виберіть Ð´Ð»Ñ ÐºÐ¾Ð³Ð¾ доÑтупне розгортаннÑ"
-
msgid "ProtectedEnvironment|Environment"
msgstr "Середовище"
msgid "ProtectedEnvironment|Protect"
msgstr "ЗахиÑтити"
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr "Захищайте Середовища Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб обмежити коло оÑіб, здатних здійÑнювати розгортаннÑ."
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr "ЗахиÑити Ñередовище"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr "ЗахиÑтити Середовище (%{protected_environments_count})"
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr "ЗахиÑÑ‚ Ñередовища обмежує коло кориÑтувачів, здатних здійÑнювати розгортаннÑ."
+
msgid "ProtectedEnvironment|Select an environment"
msgstr "Виберіть Ñередовище"
+msgid "ProtectedEnvironment|Select users"
+msgstr "Виберіть кориÑтувачів"
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr "Виберіть кориÑтувачів Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñ‚Ð° ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ñ‡Ð°Ð¼Ð¸ функцій"
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr "Ðаразі немає захищених Ñередовищ, захиÑÑ‚Ñ–Ñ‚ÑŒ Ñередовище за допомогою форми, що знаходитьÑÑ Ð²Ð¸Ñ‰Ðµ."
@@ -9127,9 +10817,15 @@ msgstr "Отримати (pull)"
msgid "Push"
msgstr "Відправити (push)"
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr "Push-правила"
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr "Відправити Ñ–Ñнуючий репозиторій Git"
@@ -9154,12 +10850,54 @@ msgstr "Відправлено"
msgid "Pushes"
msgstr "Відправки (push)"
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr "%{user_name} видалив гілку \"%{ref}\"."
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr "%{user_name} відправив код до гілки \"%{ref}\"."
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr "%{user_name} відправив нову гілку \"%{ref}\"."
+
+msgid "PushoverService|High Priority"
+msgstr "ВиÑокий пріоритет"
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr "Залиште порожнім Ð´Ð»Ñ ÑƒÑÑ–Ñ… активних приÑтроїв"
+
+msgid "PushoverService|Low Priority"
+msgstr "Ðизький пріоритет"
+
+msgid "PushoverService|Lowest Priority"
+msgstr "Ðайнижчий пріоритет"
+
+msgid "PushoverService|Normal Priority"
+msgstr "Ðормальний пріоритет"
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr "Pushover дозволÑÑ” легко отримувати ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð² реальному чаÑÑ– на ваших приÑтроÑÑ… Android, iPhone, iPad та комп'ютерах."
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr "ПереглÑнути проект %{project_full_name}"
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr "Загальна кількіÑÑ‚ÑŒ комітів: %{total_commits_count}"
+
+msgid "PushoverService|Your application key"
+msgstr "Ваш ключ заÑтоÑунку"
+
+msgid "PushoverService|Your user key"
+msgstr "Ваш ключ кориÑтувача"
+
msgid "Quarters"
msgstr "Квартали"
msgid "Query"
msgstr "Запит"
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr "Швидкі дії можна викориÑтовувати в опиÑах задач Ñ– коментарÑÑ…."
@@ -9184,15 +10922,24 @@ msgstr "Фунції реального чаÑу"
msgid "Receive alerts from manually configured Prometheus servers."
msgstr "Отримувати Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ налаштованого вручну Ñервера Prometheus."
-msgid "Recent"
+msgid "Receive notifications about your own activity"
msgstr ""
+msgid "Recent"
+msgstr "ОÑтанні"
+
msgid "Recent Project Activity"
+msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð½Ð° активніÑÑ‚ÑŒ"
+
+msgid "Recent Searches Service is unavailable"
msgstr ""
msgid "Recent searches"
msgstr "ОÑтанні пошукові запити"
+msgid "Recovery Codes"
+msgstr "Коди відновленнÑ"
+
msgid "Redirect to SAML provider to test configuration"
msgstr "Перенаправити до SAML провайдера Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ конфігурації"
@@ -9209,27 +10956,48 @@ msgstr[1] "ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· %d Ñекунди Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°
msgstr[2] "ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· %d Ñекунд Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð°ÐºÑ‚ÑƒÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ñтану..."
msgstr[3] "ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· %d Ñекунд Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð°ÐºÑ‚ÑƒÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ñтану..."
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr "Створити ключ заново"
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr "Шаблон у виглÑді регулÑрного виразу"
+msgid "Register"
+msgstr "ЗареєÑтруватиÑÑ"
+
msgid "Register / Sign In"
msgstr "ЗареєÑтруватиÑÑ / Увійти"
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr "ЗареєÑтрувати приÑтрій U2F"
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr "ЗареєÑтруйте Ñ– переглÑдайте ваші Runner’и Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи."
msgid "Register and see your runners for this project."
msgstr "ЗареєÑтруйте Ñ– переглÑдайте ваші Runner’и Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту."
-msgid "Registration"
+msgid "Register with two-factor app"
msgstr ""
+msgid "Registration"
+msgstr "РеєÑтраціÑ"
+
msgid "Registry"
msgstr "РеєÑÑ‚Ñ€"
@@ -9251,6 +11019,9 @@ msgstr "Пов'Ñзані запити на злиттÑ"
msgid "Related Merged Requests"
msgstr "Пов'Ñзані виконані запити"
+msgid "Related issues"
+msgstr "Пов’Ñзані задачі"
+
msgid "Related merge requests"
msgstr "Пов'Ñзані запити на злиттÑ"
@@ -9263,6 +11034,9 @@ msgstr ""
msgid "Remind later"
msgstr "Ðагадати пізніше"
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr "Видалити"
@@ -9272,8 +11046,11 @@ msgstr "Видалити Runner"
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr "ВидалÑти вÑÑ– Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñƒ запитах на злиттÑ, коли у гілці-джерелі з'ÑвлÑÑŽÑ‚ÑŒÑÑ Ð½Ð¾Ð²Ñ– коміти"
-msgid "Remove approver"
-msgstr "Видалити затверджуючу оÑобу"
+msgid "Remove all or specific assignee(s)"
+msgstr ""
+
+msgid "Remove all or specific label(s)"
+msgstr "Видалити уÑÑ– або певні мітки(-ку)"
msgid "Remove approvers"
msgstr "Видалити затверджуючих оÑіб"
@@ -9281,29 +11058,41 @@ msgstr "Видалити затверджуючих оÑіб"
msgid "Remove approvers?"
msgstr "Видалити затверджуючих оÑіб?"
+msgid "Remove assignee"
+msgstr "Видалити виконавцÑ"
+
msgid "Remove avatar"
msgstr "Видалити аватар"
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr "Видалити заплановану дату завершеннÑ"
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr "Видалити групу"
+msgid "Remove milestone"
+msgstr "Видалити етап"
+
msgid "Remove priority"
msgstr "Видалити пріоритет"
msgid "Remove project"
msgstr "Видалити проект"
-msgid "Remove this label? Are you sure?"
-msgstr ""
+msgid "Remove spent time"
+msgstr "Видалити витрачений чаÑ"
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
-msgstr ""
+msgid "Remove time estimate"
+msgstr "Видалити запланований чаÑ"
msgid "Removed"
-msgstr ""
+msgstr "Видалено"
msgid "Removed %{type} with id %{id}"
msgstr ""
@@ -9312,13 +11101,31 @@ msgid "Removed group can not be restored!"
msgstr "Видалену групу неможливо відновити!"
msgid "Removed projects cannot be restored!"
+msgstr "Видалені проекти неможливо відновити!"
+
+msgid "Removes %{epic_ref} from child epics."
msgstr ""
+msgid "Removes %{milestone_reference} milestone."
+msgstr "ВидалÑÑ” етап %{milestone_reference}."
+
+msgid "Removes all labels."
+msgstr "ВидалÑÑ” вÑÑ– мітки."
+
+msgid "Removes spent time."
+msgstr "ВидалÑÑ” витрачений чаÑ."
+
+msgid "Removes the due date."
+msgstr "ВидалÑÑ” дату завершеннÑ."
+
+msgid "Removes time estimate."
+msgstr "ВидалÑÑ” запланований чаÑ."
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð³Ñ€ÑƒÐ¿Ð¸ призведе до Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð²ÑÑ–Ñ… Ñ—Ñ— дочірніх проектів Ñ– реÑурÑів."
msgid "Removing license…"
-msgstr ""
+msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñ—â€¦"
msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
msgstr ""
@@ -9342,7 +11149,10 @@ msgid "Repair authentication"
msgstr "Відновити автентифікацію"
msgid "Replace"
-msgstr ""
+msgstr "Замінити"
+
+msgid "Replace all label(s)"
+msgstr "Замінити вÑÑ– мітки(-ку)"
msgid "Reply to comment"
msgstr "ВідповіÑти на коментар"
@@ -9353,8 +11163,8 @@ msgstr "ВідповіÑти на це електронне повідомлен
msgid "Repo by URL"
msgstr "Репозиторії по URL"
-msgid "Report abuse to GitLab"
-msgstr "Повідомити GitLab про порушеннÑ"
+msgid "Report abuse to admin"
+msgstr "Повідомити адмініÑтратора про порушеннÑ"
msgid "Reporting"
msgstr "ЗвітуваннÑ"
@@ -9368,6 +11178,9 @@ msgstr "Дії"
msgid "Reports|Class"
msgstr "КлаÑ"
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr "ВпевненіÑÑ‚ÑŒ"
@@ -9390,7 +11203,7 @@ msgid "Reports|Metrics reports failed loading results"
msgstr ""
msgid "Reports|Severity"
-msgstr "СерйозніÑÑ‚ÑŒ"
+msgstr "Рівень"
msgid "Reports|System output"
msgstr "СиÑтемний вивід"
@@ -9407,12 +11220,6 @@ msgstr "Результати Ð´Ð»Ñ Ñ‚ÐµÑтового звіту оброблÑ
msgid "Reports|Vulnerability"
msgstr "ВразливіÑÑ‚ÑŒ"
-msgid "Reports|issue"
-msgstr "задача"
-
-msgid "Reports|merge request"
-msgstr "запит на злиттÑ"
-
msgid "Reports|no changed test results"
msgstr "результати теÑтів не змінилиÑÑ"
@@ -9426,7 +11233,7 @@ msgid "Repository URL"
msgstr "URL репозиторіÑ"
msgid "Repository check was triggered."
-msgstr ""
+msgstr "Перевірку репозиторію запущено."
msgid "Repository cleanup"
msgstr "ÐžÑ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–ÑŽ"
@@ -9467,19 +11274,28 @@ msgstr "Вимагати від уÑÑ–Ñ… кориÑтувачів приймат
msgid "Require approval from code owners"
msgstr "Вимагати Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ влаÑників коду"
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Ðеобхідно Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ %{names}."
+msgstr[1] "Ðеобхідно ще %{count} Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ %{names}."
+msgstr[2] "Ðеобхідно ще %{count} затверджень від %{names}."
+msgstr[3] "Ðеобхідно ще %{count} затверджень від %{names}."
msgid "Requires approval."
msgid_plural "Requires %d more approvals."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Ðеобхідно затвердженнÑ."
+msgstr[1] "Ðеобхідно ще %d затвердженнÑ."
+msgstr[2] "Ðеобхідно ще %d затверджень."
+msgstr[3] "Ðеобхідно ще %d затверджень."
+
+msgid "Resend confirmation email"
+msgstr ""
msgid "Resend invite"
msgstr "Повторно надіÑлати запрошеннÑ"
@@ -9520,6 +11336,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr "Відповідь"
@@ -9562,6 +11387,9 @@ msgstr "Повторити це завданнÑ"
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr "Повторити перевірку"
@@ -9597,11 +11425,17 @@ msgid "Revoke"
msgstr "Відкликати"
msgid "Revoked impersonation token %{token_name}!"
-msgstr ""
+msgstr "Відкликано токен Ñ–Ð¼Ñ–Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ %{token_name}!"
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr "додаваннÑ"
+
+msgid "RightSidebar|deleting the"
+msgstr "видаленнÑ"
+
msgid "Roadmap"
msgstr "План-графік"
@@ -9609,7 +11443,7 @@ msgid "Run CI/CD pipelines for external repositories"
msgstr "ЗапуÑтити CI/CD конвеєри Ð´Ð»Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ–Ñ… репозиторіїв"
msgid "Run housekeeping"
-msgstr ""
+msgstr "ЗапуÑтити очищеннÑ"
msgid "Run tests against your code live using the Web Terminal"
msgstr "ПротеÑтувати ваш запущений код за допомогою Веб-терміналу"
@@ -9633,10 +11467,10 @@ msgid "Runner token"
msgstr "Токен Runner'а"
msgid "Runner was not updated."
-msgstr ""
+msgstr "Runner не було оновлено."
msgid "Runner was successfully updated."
-msgstr ""
+msgstr "Runner оновлено уÑпішно."
msgid "Runner will not receive any new jobs"
msgstr "Runner не отримуватиме нових завдань"
@@ -9672,10 +11506,10 @@ msgid "Running"
msgstr "ВиконуєтьÑÑ"
msgid "Running…"
-msgstr ""
+msgstr "ВиконуєтьÑÑ…"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
-msgstr ""
+msgstr "Виконує Ñ€Ñд задач по очищенню поточного репозиторію, таких Ñк ÑтиÑÐ½ÐµÐ½Ð½Ñ Ñ€ÐµÐ´Ð°ÐºÑ†Ñ–Ð¹ файлів та Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð½ÐµÐ´Ð¾ÑÑжних об'єктів."
msgid "SAML SSO"
msgstr "Єдиний вхід SAML"
@@ -9686,15 +11520,21 @@ msgstr "Єдиний вхід SAML Ð´Ð»Ñ %{group_name}"
msgid "SAML for %{group_name}"
msgstr "SAML Ð´Ð»Ñ %{group_name}"
+msgid "SSH Key"
+msgstr "SSH ключ"
+
msgid "SSH Keys"
msgstr "Ключі SSH"
msgid "SSH Keys Help"
-msgstr ""
+msgstr "Допомога по SSH ключам"
msgid "SSH host keys"
msgstr "SSH-ключі хоÑта"
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr "Відкритий SSH-ключ"
@@ -9710,6 +11550,9 @@ msgstr "Зберегти"
msgid "Save Changes"
msgstr "Зберегти зміни"
+msgid "Save anyway"
+msgstr "Ð’Ñе одно зберегти"
+
msgid "Save application"
msgstr "Зберегти заÑтоÑунок"
@@ -9722,6 +11565,9 @@ msgstr "Зберегти зміни перед теÑтуваннÑм"
msgid "Save comment"
msgstr "Зберегти коментар"
+msgid "Save password"
+msgstr "Зберегти пароль"
+
msgid "Save pipeline schedule"
msgstr "Зберегти розклад конвеєра"
@@ -9729,7 +11575,7 @@ msgid "Save variables"
msgstr "Зберегти змінні"
msgid "Saving project."
-msgstr ""
+msgstr "Ð—Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñƒ."
msgid "Schedule a new pipeline"
msgstr "Розклад нового конвеєра"
@@ -9782,9 +11628,21 @@ msgstr "Пошук гілок та тегів"
msgid "Search files"
msgstr "Пошук файлів"
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr "Шукати групу"
+
+msgid "Search for a user"
+msgstr "Пошук кориÑтувача"
+
msgid "Search for projects, issues, etc."
msgstr "Пошук в проектах, задачах і т. д."
+msgid "Search forks"
+msgstr "Пошук форків"
+
msgid "Search groups"
msgstr "Пошук в групах"
@@ -9806,6 +11664,9 @@ msgstr "Пошук в проекті"
msgid "Search projects"
msgstr "Пошук проектів"
+msgid "Search projects..."
+msgstr "Пошук проектів..."
+
msgid "Search users"
msgstr "Пошук кориÑтувачів"
@@ -9840,13 +11701,13 @@ msgid "SearchAutocomplete|in this project"
msgstr "в цьому проекті"
msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for \"%{term}\""
-msgstr ""
+msgstr "Показано %{from} - %{to} з %{count} %{scope} Ð´Ð»Ñ \"%{term}\""
msgid "Seats currently in use"
-msgstr ""
+msgstr "МіÑцÑ, Ñкі зараз викориÑтовуютьÑÑ"
msgid "Seats in license"
-msgstr ""
+msgstr "КількіÑÑ‚ÑŒ міÑць у ліцензії"
msgid "Secret"
msgstr "Секрет"
@@ -9881,9 +11742,6 @@ msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð°Ñˆ
msgid "Security Reports|More info"
msgstr "Детальніше"
-msgid "Security Reports|No Vulnerabilities"
-msgstr "Ðемає вразливоÑтей"
-
msgid "Security Reports|There was an error creating the issue."
msgstr "Помилка при Ñтворенні задачі."
@@ -9914,12 +11772,24 @@ msgstr "Панель безпеки"
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr "Ðа панелі безпеки відображаєтьÑÑ Ð¾Ñтанній звіт про безпеку. ВикориÑтовуйте його Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ та Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ñ€Ð°Ð·Ð»Ð¸Ð²Ð¾Ñтей."
+msgid "SecurityDashboard|Confidence"
+msgstr "ВпевненіÑÑ‚ÑŒ"
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr "Моніторинг вразливоÑтей у вашому коді"
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr "Конвеєр %{pipelineLink} запущено"
+msgid "SecurityDashboard|Project"
+msgstr "Проект"
+
+msgid "SecurityDashboard|Report type"
+msgstr "Тип звіту"
+
+msgid "SecurityDashboard|Severity"
+msgstr "Рівень"
+
msgid "See metrics"
msgstr "ПереглÑнути метрики"
@@ -9932,6 +11802,12 @@ msgstr "Вибрати"
msgid "Select Archive Format"
msgstr "Виберіть формат архіву"
+msgid "Select Page"
+msgstr "Вибрати Ñторінку"
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr "Виберіть групу Ð´Ð»Ñ Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ"
@@ -9959,6 +11835,9 @@ msgstr "Виберіть Ñ–Ñнуючий клаÑтер Kubernetes або ÑÑ‚Ð
msgid "Select branch/tag"
msgstr "Виберіть гілку або тег"
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr "Виберіть учаÑників Ð´Ð»Ñ Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ"
@@ -9995,6 +11874,9 @@ msgstr "При виборі кориÑтувача Gitlab поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð
msgid "Send an email notification to Developers."
msgstr "Відправити ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÐ°Ð¼Ð¸ електронною поштою."
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr "ÐадіÑлати лиÑта"
@@ -10011,7 +11893,7 @@ msgid "Sep"
msgstr "вер."
msgid "Separate topics with commas."
-msgstr ""
+msgstr "ВідділÑйте теми комами."
msgid "September"
msgstr "вереÑень"
@@ -10026,22 +11908,22 @@ msgid "Serverless"
msgstr "Serverless"
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð¼ÐµÑ‚Ñ€Ð¸Ðº викликів функцій необхідно Ñпочатку вÑтановити Prometheus."
msgid "ServerlessDetails|Install Prometheus"
-msgstr ""
+msgstr "Ð’Ñтановити Prometheus"
msgid "ServerlessDetails|Invocation metrics loading or not available at this time."
-msgstr ""
+msgstr "Метрики викликів функцій наразі завантажуютьÑÑ Ð°Ð±Ð¾ недоÑтупні."
msgid "ServerlessDetails|Invocations"
-msgstr ""
+msgstr "Виклики"
msgid "ServerlessDetails|Kubernetes Pods"
msgstr "Pod'и Kubernetes"
msgid "ServerlessDetails|More information"
-msgstr ""
+msgstr "Детальніше"
msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
msgstr "КількіÑÑ‚ÑŒ pod'ів Kubernetes у викориÑтанні на оÑнові необхідноÑÑ‚Ñ– протÑгом періоду чаÑу."
@@ -10076,6 +11958,9 @@ msgstr "Ðемає доÑтупних функцій"
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr "Ðаразі немає даних про функції від Knative. Це може бути викликано різними причинами, зокрема:"
+msgid "Service"
+msgstr "СервіÑ"
+
msgid "Service Desk"
msgstr "Service Desk"
@@ -10086,13 +11971,13 @@ msgid "Service URL"
msgstr "URL ÑервіÑу"
msgid "Session duration (minutes)"
-msgstr ""
+msgstr "ТриваліÑÑ‚ÑŒ ÑеÑÑ–Ñ— (у хвилинах)"
msgid "Session expiration, projects limit and attachment size."
msgstr "Термін дії ÑеÑÑ–Ñ—, проектні ліміти та розміри вкладень."
msgid "Set a default template for issue descriptions."
-msgstr ""
+msgstr "Ð’Ñтановити шаблон за замовчуваннÑм Ð´Ð»Ñ Ð¾Ð¿Ð¸Ñу задач."
msgid "Set a number of approvals required, the approvers and other approval settings."
msgstr "Ð’Ñтановіть кількіÑÑ‚ÑŒ необхідних затверджень, затверджуючих оÑіб та інші параметри затвердженнÑ."
@@ -10106,21 +11991,24 @@ msgstr "Вибрати шаблон репозиторію Ð´Ð»Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñ–
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr "Ð’Ñтановіть Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð° замовчуваннÑм Ñ– обмежте рівні видимоÑÑ‚Ñ–. Ðалаштуйте джерела імпорту Ñ– протокол доÑтупу git."
+msgid "Set due date"
+msgstr "Ð’Ñтановити дату завершеннÑ"
+
msgid "Set instance-wide template repository"
msgstr "Ð’Ñтановити репозиторій шаблонів Ð´Ð»Ñ Ð²Ñього інÑтанÑу"
msgid "Set max session time for web terminal."
msgstr "МакÑимальний термін дії ÑеÑÑ–Ñ— Ð´Ð»Ñ Ð²ÐµÐ±-терміналу."
+msgid "Set milestone"
+msgstr "Ð’Ñтановити етап"
+
msgid "Set new password"
msgstr "Ð’Ñтановити новий пароль"
msgid "Set notification email for abuse reports."
msgstr "Ðалаштувати ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¿Ð¾ електронній пошті Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ про зловживаннÑ."
-msgid "Set number of approvers required before open merge requests can be merged"
-msgstr "Ð’Ñтановити необхідну кількіÑÑ‚ÑŒ затверджуючих оÑіб перед тим, Ñк відкритий запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¼Ð¾Ð¶Ðµ бути злитий"
-
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr "Ð’Ñтановіть вимоги Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ кориÑтувачів. Увімкніть обов’Ñзкову двофакторну автентифікацію."
@@ -10131,11 +12019,14 @@ msgid "Set the duration for which the jobs will be considered as old and expired
msgstr ""
msgid "Set the maximum file size for each job's artifacts"
-msgstr ""
+msgstr "Ð’Ñтановити макÑимальний розмір файлу Ð´Ð»Ñ Ð°Ñ€Ñ‚ÐµÑ„Ð°ÐºÑ‚Ñ–Ð² кожного завданнÑ"
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr "Ð’Ñтановити запланований чаÑ"
+
msgid "Set up CI/CD"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CI/CD"
@@ -10157,6 +12048,9 @@ msgstr "Ð’Ñтановити новий пароль"
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr "Ðалаштуйте Ñвій проект, щоб автоматично відправлÑти/отримувати зміни з іншого репозиторію. Гілки, теги та коміти автоматично будуть ÑинхронізуватиÑÑ."
+msgid "Set weight"
+msgstr "Ð’Ñтановити вагу"
+
msgid "SetPasswordToCloneLink|set a password"
msgstr "вÑтановити пароль"
@@ -10184,6 +12078,18 @@ msgstr "Вибачте, нам не вдалоÑÑ Ð²Ñтановити ваш Ñ
msgid "SetStatusModal|What's your status?"
msgstr "Який ваш ÑтатуÑ?"
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr "ÐалаштуваннÑ"
@@ -10199,6 +12105,9 @@ msgstr "Загальні Runner'и"
msgid "Shared projects"
msgstr "Спільні проекти"
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr "При обнуленні хвилин конвеєрів Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проÑтору імен, кількіÑÑ‚ÑŒ вже викориÑтаних хвилин буде дорівнювати 0."
@@ -10211,9 +12120,18 @@ msgstr "Обнулити викориÑтані хвилини в конвеєр
msgid "Sherlock Transactions"
msgstr "Sherlock транзакції"
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
msgstr "Показати вÑÑŽ активніÑÑ‚ÑŒ"
+msgid "Show archived projects"
+msgstr "Показати архівовані проекти"
+
+msgid "Show archived projects only"
+msgstr ""
+
msgid "Show command"
msgstr "Показати команду"
@@ -10229,9 +12147,6 @@ msgstr "Показати файловий менеджер"
msgid "Show latest version"
msgstr "Показати оÑтанню верÑÑ–ÑŽ"
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr "Показати батьківÑькі Ñторінки"
@@ -10287,21 +12202,42 @@ msgstr "Увійти за допомогою Ñмарт-карти"
msgid "Sign out"
msgstr "Вийти"
+msgid "Sign out & Register"
+msgstr "Вийти Ñ– зареєÑтруватиÑÑ"
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr "РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾Ð¹ÑˆÐ»Ð° уÑпішно! Будь лаÑка, підтвердіть Ñвою адреÑу електронної пошти Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ."
+
msgid "Sign-in restrictions"
msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ"
msgid "Sign-up restrictions"
msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ€ÐµÑ”Ñтрації"
-msgid "Signing in using %{label} has been disabled"
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
msgstr ""
-msgid "Signing in using your %{label} account without a pre-existing GitLab account is not allowed."
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
msgstr ""
+msgid "Signed in with %{authentication} authentication"
+msgstr "Вхід відбувÑÑ Ð·Ð° допомогою %{authentication}"
+
+msgid "Signing in using %{label} has been disabled"
+msgstr "Вхід за допомогою %{label} вимкнено"
+
+msgid "Signing in using your %{label} account without a pre-existing GitLab account is not allowed."
+msgstr "Вхід за допомогою облікового запиÑу %{label} без Ñ–Ñнуючого облікового запиÑу GitLab не дозволено."
+
msgid "Similar issues"
msgstr "Подібні задачі"
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr "Розмір"
@@ -10311,6 +12247,9 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð¾Ð·Ð¼Ñ–Ñ€Ñƒ та домену Ð´Ð»Ñ ÑтаÑ
msgid "Size limit per repository (MB)"
msgstr "МакÑимальний розмір Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ репозиторію (МБ)"
+msgid "Skip this for now"
+msgstr "Поки що пропуÑтити це"
+
msgid "Slack application"
msgstr "заÑтоÑунок Slack"
@@ -10380,6 +12319,9 @@ msgstr "ЩоÑÑŒ пішло не так, при Ñпробі зміни Ñтан
msgid "Something went wrong when toggling the button"
msgstr "Помилка при перемиканні кнопки"
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr "Помилка при заÑтоÑуванні пропозиції. Будь лаÑка, Ñпробуйте знову."
@@ -10398,6 +12340,9 @@ msgstr "Проблема при отриманні коментарів. БудÑ
msgid "Something went wrong while fetching group member contributions"
msgstr "Помилка при завантаженні внеÑків учаÑників групи"
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10422,8 +12367,8 @@ msgstr "Помилка при завершенні обговореннÑ. БуÐ
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr "Проблема, не вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ %{project} до панелі керуваннÑ"
-msgid "Something went wrong, unable to get operations projects"
-msgstr "Проблема, не вдаєтьÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ операційні проекти"
+msgid "Something went wrong, unable to get projects"
+msgstr ""
msgid "Something went wrong, unable to remove project"
msgstr "Проблема, не вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ проект"
@@ -10434,6 +12379,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr "ЩоÑÑŒ пішло не так. Будь лаÑка Ñпробуйте ще раз."
+msgid "Something went wrong. Try again later."
+msgstr "ЩоÑÑŒ пішло не так. Спробуйте пізніше."
+
msgid "Sorry, no epics matched your search"
msgstr "Вибачте, жоден епік не задовольнÑÑ” критеріÑм вашого пошуку"
@@ -10494,6 +12442,9 @@ msgstr "Ðайменш популÑрний"
msgid "SortOptions|Less weight"
msgstr "Менша вага"
+msgid "SortOptions|Manual"
+msgstr "Вручну"
+
msgid "SortOptions|Milestone due date"
msgstr "Дата Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ ÐµÑ‚Ð°Ð¿Ñƒ"
@@ -10548,6 +12499,12 @@ msgstr "Ðайновіша оÑÑ‚Ð°Ð½Ð½Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ñ–ÑÑ‚ÑŒ"
msgid "SortOptions|Recent sign in"
msgstr "Ðещодавно зареєÑтровані"
+msgid "SortOptions|Sort direction"
+msgstr "ÐапрÑмок ÑортуваннÑ"
+
+msgid "SortOptions|Stars"
+msgstr "Обрані"
+
msgid "SortOptions|Start date"
msgstr "Дата початку"
@@ -10620,6 +12577,9 @@ msgstr "ПроіндекÑовано %{type}"
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr "Позначте мітку, щоб зробити Ñ—Ñ— пріоритетною. ПеретÑгуйте пріоритетні мітки Ð´Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸ Ñ—Ñ… відноÑного пріоритету."
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr "В обрані"
@@ -10644,6 +12604,9 @@ msgstr "У обраному"
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr "Почати індекÑуваннÑ"
+
msgid "Start Web Terminal"
msgstr "ЗапуÑтити Веб-Термінал"
@@ -10674,6 +12637,12 @@ msgstr "Розпочати Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð° закрити %{noteable
msgid "Start discussion & reopen %{noteable_name}"
msgstr "Розпочати Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ– повторно відкрити %{noteable_name}"
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "ЗапуÑÑ‚Ñ–Ñ‚ÑŒ Runner!"
@@ -10734,12 +12703,18 @@ msgstr "Сховище"
msgid "Storage:"
msgstr "Сховище:"
+msgid "StorageSize|Unknown"
+msgstr "Ðевідомо"
+
msgid "Subgroups"
msgstr "Підгрупи"
msgid "Subgroups and projects"
msgstr "Підгрупи та проекти"
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr "Позначити Ñк Ñпам"
@@ -10770,6 +12745,9 @@ msgstr "ПідпиÑатиÑÑ Ð½Ð° календар"
msgid "Subscribed"
msgstr "Ви підпиÑані"
+msgid "Subscription"
+msgstr "ПідпиÑка"
+
msgid "SubscriptionTable|Billing"
msgstr "Білінг"
@@ -10777,7 +12755,7 @@ msgid "SubscriptionTable|Free"
msgstr "Безкоштовно"
msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
-msgstr ""
+msgstr "GitLab дозволÑÑ” вам викориÑтовувати вашу підпиÑку, навіть Ñкщо ви перевищили кількіÑÑ‚ÑŒ придбаних міÑць. Вам треба буде заплатити за ці міÑÑ†Ñ Ð¿Ñ€Ð¸ Ñ—Ñ— поновленні."
msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
msgstr "GitLab.com %{planName} %{suffix}"
@@ -10792,19 +12770,19 @@ msgid "SubscriptionTable|Manage"
msgstr "УправліннÑ"
msgid "SubscriptionTable|Max seats used"
-msgstr ""
+msgstr "МакÑимальна кількіÑÑ‚ÑŒ викориÑтаних міÑць"
msgid "SubscriptionTable|Next invoice"
msgstr "ÐаÑтупний рахунок-фактура"
msgid "SubscriptionTable|Seats currently in use"
-msgstr ""
+msgstr "МіÑцÑ, Ñкі зараз викориÑтовуютьÑÑ"
msgid "SubscriptionTable|Seats in subscription"
-msgstr ""
+msgstr "МіÑÑ†Ñ Ð² підпиÑці"
msgid "SubscriptionTable|Seats owed"
-msgstr ""
+msgstr "Заборговані міÑцÑ"
msgid "SubscriptionTable|Subscription end date"
msgstr "Дата Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð¿Ñ–Ð´Ð¿Ð¸Ñки"
@@ -10822,7 +12800,7 @@ msgid "SubscriptionTable|This is the next date when the GitLab.com team is sched
msgstr "Це — наÑтупний момент, коли команда GitLab.com зв'ÑжетьÑÑ Ð· вами Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð°Ñ…ÑƒÐ½ÐºÑ–Ð²."
msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
-msgstr ""
+msgstr "Це — кількіÑÑ‚ÑŒ міÑць, Ñку вам необхідно буде придбати, Ñкщо ви перейдете на платний тарифний план."
msgid "SubscriptionTable|Trial"
msgstr "Пробна верÑÑ–Ñ"
@@ -10840,32 +12818,98 @@ msgid "SubscriptionTable|Usage"
msgstr "ВикориÑтаннÑ"
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr "Облік викориÑÑ‚Ð°Ð½Ð½Ñ Ð²Ð¸ÐºÐ¾Ð½ÑƒÑ”Ñ‚ÑŒÑÑ Ð¾Ð´Ð¸Ð½ раз на день о 12:00."
+
+msgid "Subtracts"
msgstr ""
msgid "Successfully blocked"
-msgstr ""
+msgstr "УÑпішно заблоковано"
msgid "Successfully confirmed"
-msgstr ""
+msgstr "УÑпішно підтверджено"
msgid "Successfully deleted U2F device."
-msgstr ""
+msgstr "УÑпішно видалено приÑтрій U2F."
msgid "Successfully removed email."
-msgstr ""
+msgstr "УÑпішно видалено адреÑу електронної пошти."
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
-msgstr ""
+msgstr "УÑпішно заплановано контейнер Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку. Перейдіть на %{pipelines_link_start}Ñторінку конвеєрів%{pipelines_link_end} Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð¸Ñ†ÑŒ."
msgid "Successfully unblocked"
-msgstr ""
+msgstr "УÑпішно розблоковано"
msgid "Successfully unlocked"
-msgstr ""
+msgstr "УÑпішно розблоковано"
msgid "Suggested change"
msgstr "Пропонована зміна"
+msgid "SuggestedColors|Bright green"
+msgstr "ЯÑкраво-зелений"
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr "Темно-Ñірувато-блакитний"
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr "Фейхоа"
+
+msgid "SuggestedColors|Lime green"
+msgstr "Зелений лайм"
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr "ЧиÑтий червоний"
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr "Ðœ'Ñкий помаранчевий"
+
+msgid "SuggestedColors|Soft red"
+msgstr "Ðœ'Ñкий червоний"
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
msgid "Sunday"
msgstr "ÐеділÑ"
@@ -10878,6 +12922,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr "Перейти в гілку/тег"
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr "Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ Ñинхронізацію"
@@ -10885,10 +12935,10 @@ msgid "System"
msgstr "СиÑтемні"
msgid "System Hooks"
-msgstr "СиÑтемні гуки"
+msgstr "СиÑтемні хуки"
msgid "System Hooks Help"
-msgstr ""
+msgstr "Допомога по ÑиÑтемним хукам"
msgid "System Info"
msgstr "Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ ÑиÑтему"
@@ -10900,7 +12950,7 @@ msgid "System header and footer"
msgstr "Заголовок Ñ– футер ÑиÑтеми"
msgid "System hook was successfully updated."
-msgstr ""
+msgstr "СиÑтемний хук уÑпішно оновлено."
msgid "System metrics (Custom)"
msgstr "СиÑтемні метрики (ВлаÑні)"
@@ -10908,18 +12958,30 @@ msgstr "СиÑтемні метрики (ВлаÑні)"
msgid "System metrics (Kubernetes)"
msgstr "СиÑтемні метрики (Kubernetes)"
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr "Тег"
msgid "Tag list:"
msgstr "СпиÑок тегів:"
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr "Теги"
msgid "Tags feed"
msgstr "Канал тегів"
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr "Теги:"
@@ -11001,6 +13063,9 @@ msgstr "Цільова гілка"
msgid "Team"
msgstr "Команда"
+msgid "Team domain"
+msgstr "Домен команди"
+
msgid "Template"
msgstr "Шаблон"
@@ -11013,6 +13078,9 @@ msgstr "Термінал"
msgid "Terminal for environment"
msgstr "Термінал Ð´Ð»Ñ Ñередовища"
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "Угода про Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг Ñ– політика конфіденційноÑÑ‚Ñ–"
@@ -11026,8 +13094,35 @@ msgid "Test coverage parsing"
msgstr "Пошук результатів Ð¿Ð¾ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñ‚ÐµÑтами"
msgid "Test failed."
+msgstr "ТеÑÑ‚ не пройдено."
+
+msgid "Test settings and save changes"
msgstr ""
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr "ПереконайтеÑÑ, що один із ваших проектів має запити на злиттÑ."
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr "ПереконайтеÑÑ, що проект має CI завданнÑ."
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr "ПереконайтеÑÑ, що проект має CI конвеєри."
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr "ПереконайтеÑÑ, що проект має принаймні один коміт."
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr "ПереконайтеÑÑ, що проект має задачі."
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr "ПереконайтеÑÑ, що проект має запити на злиттÑ."
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr "ПереконайтеÑÑ, що проект має нотатки."
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr "ПереконайтеÑÑ, що вікі увімкнено Ñ– вона має Ñторінки."
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -11068,6 +13163,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr "ПідÑвітка Ñимволів дозволÑÑ” обмежувати заголовок до %{titleLength} Ñимволів Ñ– обмежувати довжину Ñ€Ñдків тіла %{bodyLength} Ñимволами Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб вони залишаютьÑÑ Ñ‡Ð¸Ñ‚Ð°Ð±ÐµÐ»ÑŒÐ½Ð¸Ð¼Ð¸ в git."
@@ -11083,6 +13181,9 @@ msgstr "Ð—â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ припинено піÑÐ»Ñ %{timeout}. Ð
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr "Ð Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð½Ð° %{environmentLink} не уÑпішне."
@@ -11093,34 +13194,34 @@ msgid "The entered user map is not a valid JSON user map."
msgstr ""
msgid "The file has been successfully created."
-msgstr ""
+msgstr "Файл уÑпішно Ñтворено."
msgid "The file has been successfully deleted."
-msgstr ""
+msgstr "Файл уÑпішно видалено."
msgid "The following items will NOT be exported:"
-msgstr ""
+msgstr "ÐаÑтупні елементи ÐЕ будуть екÑпортовані:"
msgid "The following items will be exported:"
-msgstr ""
+msgstr "ÐаÑтупні елементи будуть екÑпортовані:"
msgid "The fork relationship has been removed."
msgstr "Зв'Ñзок форку видалено."
msgid "The global settings require you to enable Two-Factor Authentication for your account."
-msgstr ""
+msgstr "Глобальні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ð¼Ð°Ð³Ð°ÑŽÑ‚ÑŒ, щоб ви увімкнули двофакторну автентифікацію Ð´Ð»Ñ Ñвого облікового запиÑу."
msgid "The group and any internal projects can be viewed by any logged in user."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
-msgstr ""
+msgstr "Ð¦Ñ Ð³Ñ€ÑƒÐ¿Ð° та будь-Ñкі проекти можуть переглÑдатиÑÑ Ð±ÐµÐ· жодної автентифікації."
msgid "The group and its projects can only be viewed by members."
msgstr ""
msgid "The group settings for %{group_links} require you to enable Two-Factor Authentication for your account. You can %{leave_group_links}."
-msgstr ""
+msgstr "Групові Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ %{group_links} вимагають, щоб ви увімкнули двофакторну автентифікацію Ð´Ð»Ñ Ñвого облікового запиÑу. Ви можете %{leave_group_links}."
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Імпорт буде припинено піÑÐ»Ñ %{timeout}. Ð”Ð»Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ—Ð², Ñким потрібно більше чаÑу, викориÑтовуйте комбінацію clone/push."
@@ -11140,6 +13241,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ Ð—Ð°Ð´Ð°Ñ‡Ð° показує, Ñкільки чаÑу потрібно від ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡Ñ– до Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ñ—Ñ— до ÑкогоÑÑŒ етапу, або Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡Ñ– на дошку. Почніть Ñтворювати задачі, щоб переглÑдати дані Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— Ñтадії."
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr "МакÑимальний розмір файлу — %{size}."
@@ -11158,6 +13268,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "Пароль, Ñкий потрібен Ð´Ð»Ñ Ð´ÐµÑˆÐ¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¾Ð³Ð¾ ключа. Він Ñ” необов’Ñзковим Ñ– зберігаєтьÑÑ Ñƒ зашифрованому виглÑді."
@@ -11182,18 +13298,33 @@ msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ Production показує загальний Ñ‡Ð°Ñ Ð¼Ñ–Ð¶
msgid "The project can be accessed by any logged in user."
msgstr "ДоÑтуп до проекту можливий будь-Ñким зареєÑтрованим кориÑтувачем."
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr "ДоÑтуп до проекту можливий без будь-Ñкої перевірки автентичноÑÑ‚Ñ–."
-msgid "The project was successfully forked."
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
+msgid "The project is still being deleted. Please try again later."
+msgstr "Проект вÑе ще видалÑєтьÑÑ. Будь лаÑка, Ñпробуйте знову."
+
+msgid "The project was successfully forked."
+msgstr "УÑпішно Ñтворено форк проекту."
+
msgid "The project was successfully imported."
-msgstr ""
+msgstr "Проект уÑпішно імпортовано."
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr "Збір даних пÑевдонімізованих данних вимкнено. Коли його буде увімкнено GitLab запуÑтить фонове завданнÑ, Ñке буде Ñтворювати пÑевдонімізовані CSV-файли бази даних GitLab, Ñкі будуть надÑилатиÑÑ Ð´Ð¾ вашого налаштованого Ñховища об'єктів."
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11203,6 +13334,9 @@ msgstr "Репозиторій Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту не Ñ–Ñнує.
msgid "The repository for this project is empty"
msgstr "Репозиторій цього проекту порожній"
+msgid "The repository is being updated..."
+msgstr "Репозиторій оновлюєтьÑÑ..."
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr "Репозиторій має бути доÑтупним через <code>http://</code>, <code>https://</code> або <code>git://</code>."
@@ -11219,16 +13353,16 @@ msgid "The schedule time must be in the future!"
msgstr ""
msgid "The snippet can be accessed without any authentication."
-msgstr ""
+msgstr "ДоÑтуп до Ñніпета можливий без будь-Ñкої автентифікації."
msgid "The snippet is visible only to me."
-msgstr ""
+msgstr "Цей Ñніпет Ñ” видим лише Ð´Ð»Ñ Ð¼ÐµÐ½Ðµ."
msgid "The snippet is visible only to project members."
-msgstr ""
+msgstr "Цей Ñніпет видимий тільки Ð´Ð»Ñ ÑƒÑ‡Ð°Ñників проекту."
msgid "The snippet is visible to any logged in user."
-msgstr ""
+msgstr "Цей Ñніпет видимий Ð´Ð»Ñ Ð±ÑƒÐ´ÑŒ-Ñкого зареєÑтрованого кориÑтувача."
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ Staging показує Ñ‡Ð°Ñ Ð¼Ñ–Ð¶ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° розгортаннÑм коду у production. Дані автоматично додаютьÑÑ Ð¿Ñ–ÑÐ»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñƒ production вперше."
@@ -11242,17 +13376,20 @@ msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ Ð¢ÐµÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾ÐºÐ°Ð·ÑƒÑ” чаÑ, Ñкий GitLab
msgid "The time taken by each data entry gathered by that stage."
msgstr "ЧаÑ, витрачений на кожен елемент, зібраний на цій Ñтадії."
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr "Ð§Ð°Ñ Ð´Ñ–Ñ— Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñплине через %{number_of_minutes} хвилин. Ð”Ð»Ñ Ð²ÐµÐ»Ð¸ÐºÐ¸Ñ… репозиторіїв викориÑтовуйте комбінацію clone/push."
msgid "The uploaded file is not a valid Google Takeout archive."
-msgstr ""
+msgstr "Завантажений файл не є коректним архівом Google Takeout."
msgid "The usage ping is disabled, and cannot be configured through this form."
msgstr "Збір даних про викориÑÑ‚Ð°Ð½Ð½Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð¾, Ñ– це не можна налаштувати через цю форму."
msgid "The user is being deleted."
-msgstr ""
+msgstr "КориÑтувач видалÑєтьÑÑ."
msgid "The user map has been saved. Continue by selecting the projects you want to import."
msgstr ""
@@ -11263,15 +13400,30 @@ msgstr "Мапа кориÑтувачів — це JSON-документ, Ñки
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr "Мапа кориÑтувачів — це правила Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів FogBugz, Ñкі приймали учаÑÑ‚ÑŒ у ваших проектах до Gitlab (зокрема Ñ—Ñ… імен та Ð°Ð´Ñ€ÐµÑ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти). Ви можете вноÑити зміни шлÑхом Ð·Ð°Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ– нижче."
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "Середнє Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð² Ñ€Ñдку. Приклад: між 3, 5, 9, Ñередніми 5, між 3, 5, 7, 8, Ñередніми (5 + 7) / 2 = 6."
-msgid "There are no approvers"
-msgstr "Ðемає затверджуючих оÑіб"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
+msgstr ""
msgid "There are no archived projects yet"
msgstr "Ðаразі немає жодного архівованого проекту"
+msgid "There are no charts configured for this page"
+msgstr ""
+
msgid "There are no closed issues"
msgstr "Закритих задач немає"
@@ -11305,9 +13457,24 @@ msgstr "Ðемає індекÑованих змін"
msgid "There are no unstaged changes"
msgstr "Ðемає неіндекÑованих змін"
+msgid "There is already a repository with that name on disk"
+msgstr "Ðа диÑку вже Ñ–Ñнує репозиторій за таким ім’Ñм"
+
+msgid "There was a problem communicating with your device."
+msgstr "Проблема Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð´Ð¾ вашого приÑтрою."
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
msgstr "Помилка при додаванні нагадуваннÑ."
+msgid "There was an error creating the issue"
+msgstr ""
+
msgid "There was an error deleting the todo."
msgstr "Помилка при видаленні задачі."
@@ -11321,6 +13488,12 @@ msgid "There was an error loading users activity calendar."
msgstr "Помилка при завантаженні ÐºÐ°Ð»ÐµÐ½Ð´Ð°Ñ€Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð¾ÑÑ‚Ñ– кориÑтувачів."
msgid "There was an error removing the e-mail."
+msgstr "Помилка при видаленні адреÑи електронної пошти."
+
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
msgstr ""
msgid "There was an error saving your changes."
@@ -11341,6 +13514,9 @@ msgstr "Помилка при підпиÑці на цю мітку."
msgid "There was an error when unsubscribing from this label."
msgstr "Помилка при відпиÑці від цієї мітки."
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11353,6 +13529,9 @@ msgstr "Ðими можна керувати за допомогою %{link}."
msgid "Third party offers"
msgstr "Сторонні пропозиції"
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr "Ð¦Ñ %{issuableDisplayName} заблокована. Лише учаÑники проекту можуть коментувати."
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr "Ð¦Ñ %{issuable} заблокована. Лише <strong>учаÑники проекту</strong> можуть коментувати."
@@ -11365,18 +13544,30 @@ msgstr "Цей інÑÑ‚Ð°Ð½Ñ GitLab ще немає загальних Runner'Ñ
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr "Цей заÑтоÑунок було Ñтворено %{link_to_owner}."
msgid "This application will be able to:"
msgstr "Ð¦Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð° зможе:"
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr "ВидиміÑÑ‚ÑŒ цієї дошки обмежена"
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr "Ð¦Ñ Ð³Ñ–Ð»ÐºÐ° була змінена піÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾ моменту, коли ви почали Ñ—Ñ— редагувати. Ви хотіли б Ñтворити нову?"
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11401,6 +13592,12 @@ msgstr "Ð¦Ñ Ð´Ð°Ñ‚Ð° наÑтупає пізніше дати закінченÐ
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr "Ð¦Ñ Ð´Ð°Ñ‚Ð° Ñ” більш ранньою, ніж дата початку, тому цей епік не відображатиметьÑÑ Ð² плані-графіку."
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr "Це порівнÑÐ½Ð½Ñ Ð·Ð³Ð¾Ñ€Ð½ÑƒÑ‚Ð¾."
@@ -11413,6 +13610,9 @@ msgstr "Цей каталог"
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr "Цей домен не підтверджено. Щоб увімкнути доÑтуп, потрібно підтвердити право влаÑноÑÑ‚Ñ–."
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr "Це поле Ñ” обов'Ñзковим."
@@ -11422,24 +13622,33 @@ msgstr "Ð¦Ñ Ð³Ñ€ÑƒÐ¿Ð°"
msgid "This group does not provide any group Runners yet."
msgstr "Ð¦Ñ Ð³Ñ€ÑƒÐ¿Ð° ще не має жодного групового Runner’а."
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr "Це конфіденційна задача."
msgid "This is a delayed job to run in %{remainingTime}"
msgstr "Це завданнÑ, відкладено на %{remainingTime}"
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr "Це ÑпиÑок приÑтроїв, з котрих заходили в Ваш аккаунт. Завершіть будь-Ñкі підозрілі ÑеанÑи."
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr "Це перший запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ñ–Ð´ цього автора Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту."
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
-msgstr ""
+msgstr "Це макÑимальна кількіÑÑ‚ÑŒ кориÑтувачів, Ñкі Ñ–Ñнували одночаÑно з моменту початку ліцензії. Це мінімальна кількіÑÑ‚ÑŒ міÑць, Ñкі потрібно придбати при продовженні ліцензії."
+
+msgid "This is your current session"
+msgstr "Це ваш поточний ÑеанÑ"
msgid "This issue is confidential"
msgstr "Ð¦Ñ Ð·Ð°Ð´Ð°Ñ‡Ð° Ñ” конфіденційною"
-msgid "This issue is confidential and locked."
-msgstr "Ð¦Ñ Ð·Ð°Ð´Ð°Ñ‡Ð° конфіденційна Ñ– заблокована."
-
msgid "This issue is locked."
msgstr "Ð¦Ñ Ð·Ð°Ð´Ð°Ñ‡Ð° заблокована."
@@ -11509,12 +13718,6 @@ msgstr "Це означає, що ви не можете відправлÑти
msgid "This merge request is locked."
msgstr "Цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ð¾."
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr "Цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¼Ð°Ñ” бути затверджений учаÑниками цих груп. Ви можете змінити проектні налаштуваннÑ, вÑтановивши ваш влаÑний ÑпиÑок затверджуючих оÑіб."
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr "Цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¼Ð°Ñ” бути затверджений цими кориÑтувачами. Ви можете змінити проектні налаштуваннÑ, вÑтановивши ваш влаÑний ÑпиÑок затверджуючих оÑіб."
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11567,7 +13770,7 @@ msgid "This timeout will take precedence when lower than project-defined timeout
msgstr ""
msgid "This user cannot be unlocked manually from GitLab"
-msgstr ""
+msgstr "Цей кориÑтувач не може бути розблокований вручну в GitLab"
msgid "This user has no identities"
msgstr "Цей кориÑтувач не має ідентифікацій"
@@ -11587,6 +13790,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr "Ці Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти автоматично Ñтануть обговореннÑми задач, Ñкі відображатимутьÑÑ Ñ‚ÑƒÑ‚ (причому коментарі Ñтануть чаÑтиною перепиÑки)."
+msgid "Thursday"
+msgstr "Четвер"
+
+msgid "Time based: Yes"
+msgstr "Ðа оÑнові чаÑу: Так"
+
msgid "Time before an issue gets scheduled"
msgstr "Ð§Ð°Ñ Ð´Ð¾ початку потраплÑÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡ в планувальник"
@@ -11775,6 +13984,9 @@ msgstr "Порада:"
msgid "Title"
msgstr "Заголовок"
+msgid "Title:"
+msgstr "Заголовок:"
+
msgid "Titles and Filenames"
msgstr "Заголовки та імена файлів"
@@ -11790,6 +14002,9 @@ msgstr "Щоб отримати доÑтуп до цього домену, ÑÑ‚Ð
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr "Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб додати ключ SSH вам необхідно %{generate_link_start}згенерувати його%{link_end} або викориÑтати %{existing_link_start}Ñ–Ñнуючий ключ%{link_end}."
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr "Ð”Ð»Ñ Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ—Ð² з GitHub, ви можете викориÑтовувати %{personal_access_token_link}. Коли ви Ñтворюватимете ваш перÑональний токен доÑтупу, вам потрібно буде вибрати облаÑÑ‚ÑŒ дії <code>repo</code>, щоб ми могли відобразити ÑпиÑок ваших публічних та приватних репозиторіїв, доÑтупних Ð´Ð»Ñ Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ."
@@ -11851,11 +14066,14 @@ msgid "To preserve performance only <strong>%{display_size} of %{real_size}</str
msgstr "Ð”Ð»Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ ÑˆÐ²Ð¸Ð´ÐºÐ¾Ð´Ñ–Ñ— відображаютьÑÑ Ð»Ð¸ÑˆÐµ <strong>%{display_size} із %{real_size}</strong> файлів."
msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½ÑŒ від ÑервіÑів Prometheus, Ñкі Ñконфігуровані вручну, додайте наÑтупний URL та ключ авторизаціх до вашого конфігураційного файлу веб-хуків Prometheus. ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про %{linkStart}ÐºÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€ÑƒÐ²Ð°Ð½Ñ Prometheus%{linkEnd} Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб відправлÑти Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ Ñ–Ð· Gitlab."
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr "Щоб налаштувати автентифікацію SAML Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ñ— групи через провайдера ідентифікації такої Ñк Azure, Okta, Onelogin, Ping Identity або вашого влаÑного поÑтачальника SAML 2.0:"
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr "Ð”Ð»Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¸Ñ… завдань ви можете додати Runner’и до вашої групи"
@@ -11884,7 +14102,7 @@ msgid "Todo"
msgstr "ÐагдуваннÑ"
msgid "Todo was successfully marked as done."
-msgstr ""
+msgstr "ÐÐ°Ð³Ð°Ð´ÑƒÐ²Ð°Ð½Ð½Ñ ÑƒÑпішно позначене Ñк виконане."
msgid "Todos"
msgstr "ÐагадуваннÑ"
@@ -11892,6 +14110,9 @@ msgstr "ÐагадуваннÑ"
msgid "Toggle Sidebar"
msgstr "Перемикач бічної панелі"
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr "Увімкнути або вимкнути коментарі Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ файлу"
@@ -11904,9 +14125,15 @@ msgstr "Відкрити або закрити ÑпиÑок комітів"
msgid "Toggle discussion"
msgstr "Перемикач диÑкуÑÑ–Ñ—"
+msgid "Toggle emoji award"
+msgstr "Увімкнути/вимкнути Ñмайлики-нагороди"
+
msgid "Toggle navigation"
msgstr "Переключити навігацію"
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "Перемикач бічної панелі"
@@ -11916,6 +14143,9 @@ msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿ÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ñ‡Ð°: ВИМКÐЕÐО"
msgid "ToggleButton|Toggle Status: ON"
msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿ÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ñ‡Ð°: УВІМКÐЕÐО"
+msgid "Toggles :%{name}: emoji award."
+msgstr "Вмикає/вимикає %{name} Ñмайлик-нагороду."
+
msgid "Token"
msgstr "Токен"
@@ -11926,10 +14156,10 @@ msgid "Too many changes to show."
msgstr "Забагато змін Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ñƒ."
msgid "Topics"
-msgstr ""
+msgstr "Теми"
msgid "Total"
-msgstr ""
+msgstr "Ð’Ñього"
msgid "Total Contributions"
msgstr "Загальна кількіÑÑ‚ÑŒ внеÑків"
@@ -11956,7 +14186,43 @@ msgid "Track time with quick actions"
msgstr "ВідÑтежуйте Ñ‡Ð°Ñ Ð·Ð° допомогою швидких дій"
msgid "Transfer project"
-msgstr ""
+msgstr "ПеренеÑти проект"
+
+msgid "TransferGroup|Database is not supported."
+msgstr "База даних не підтримуєтьÑÑ."
+
+msgid "TransferGroup|Group is already a root group."
+msgstr "Група вже є кореневою."
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr "Група вже пов'Ñзана із батьківÑькою групою."
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr "Ð¦Ñ Ð±Ð°Ñ‚ÑŒÐºÑ–Ð²Ñька група уже міÑтить підгрупу з тим же шлÑхом."
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr "ПеренеÑÐµÐ½Ð½Ñ Ð½ÐµÐ²Ð´Ð°Ð»Ðµ: %{error_message}"
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr "У Ð²Ð°Ñ Ð½ÐµÐ´Ð¾Ñтатньо прав."
+
+msgid "TransferProject|Cannot move project"
+msgstr "Ðеможливо переміÑтити проект"
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr "Будь лаÑка, виберіть новий проÑÑ‚Ñ–Ñ€ імен Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ проекту."
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr "Проект не може бути переміщений, тому що в реєÑтрі контейнерів приÑутні теги"
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr "Ð’ цільовому проÑторі імен вже Ñ–Ñнує проект із таким же іменем або шлÑхом"
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr "ПеренеÑÐµÐ½Ð½Ñ Ð½ÐµÐ²Ð´Ð°Ð»Ðµ, будь лаÑка, зв'ÑжітьÑÑ Ñ–Ð· адмініÑтратором."
+
+msgid "Tree"
+msgstr "Дерево"
msgid "Tree view"
msgstr "У виглÑді дерева"
@@ -11971,7 +14237,7 @@ msgid "Trigger pipelines when branches or tags are updated from the upstream rep
msgstr "Викликати конвеєри, коли гілки або теги оновлюютьÑÑ Ð² репозиторії upstream. Ð’ залежноÑÑ‚Ñ– від активноÑÑ‚Ñ– в репозиторії upstream, це може значно збільшити Ð½Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð° CI runner'и. Вмикайте це тільки тоді, коли знаєте, що вони впораютьÑÑ Ð· навантаженнÑм."
msgid "Trigger removed."
-msgstr ""
+msgstr "Тригер видалено."
msgid "Trigger this manual action"
msgstr "ЗапуÑтити цю ручну дію"
@@ -11983,16 +14249,16 @@ msgid "Trigger variables:"
msgstr "Змінні тригера:"
msgid "Trigger was created successfully."
-msgstr ""
+msgstr "Тригер Ñтворено уÑпішно."
msgid "Trigger was re-assigned."
-msgstr ""
+msgstr "Тригер було перепризначено."
msgid "Trigger was successfully updated."
-msgstr ""
+msgstr "Тригер уÑпішно оновлено."
msgid "Triggerer"
-msgstr ""
+msgstr "Запущено"
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr "Тригери можуть примуÑово перезібрати гілку або тег через API. Ці токени дозволÑÑŽÑ‚ÑŒ діÑти від імені кориÑтувача: в тому чиÑлі отримувати доÑтуп до його проектів та проектних прав доÑтупу."
@@ -12009,44 +14275,77 @@ msgstr "Спробуйте ще раз?"
msgid "Try all GitLab has to offer for 30 days."
msgstr "Спробуйте вÑÑ– функції GitLab протÑгом 30 днів."
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr "ВідбуваєтьÑÑ Ð·'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ñ–Ð· вашим приÑтроєм. Підключіть його (Ñкщо ви цього ще не зробили) Ñ– натиÑніть кнопку на ньому зараз."
+msgid "Tuesday"
+msgstr "Вівторок"
+
msgid "Turn on Service Desk"
msgstr "Ввімкнути Service Desk"
msgid "Twitter"
msgstr "Twitter"
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
msgstr ""
+msgid "Two-factor Authentication has been disabled for this user"
+msgstr "Двофакторну автентифікацію було вимкнено Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ кориÑтувача"
+
msgid "Two-factor authentication"
msgstr "Двофакторна автентифікаціÑ"
msgid "Type"
msgstr "Тип"
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr "U2F працює лише з веб-Ñайтами з підтримкою HTTPS. Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð±Ñ–Ð»ÑŒÑˆ детальної інформації звернітьÑÑ Ð´Ð¾ адмініÑтратора."
+
msgid "URL"
msgstr "URL"
msgid "Unable to connect to server: %{error}"
+msgstr "Ðе вдалоÑÑ Ð·Ð²â€™ÑзатиÑÑ Ñ–Ð· Ñервером: %{error}"
+
+msgid "Unable to generate new instance ID"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr "Ðеможливо завантажити порівнÑÐ½Ð½Ñ (diff). %{button_try_again}"
-msgid "Unable to schedule a pipeline to run immediately"
+msgid "Unable to resolve"
msgstr ""
+msgid "Unable to schedule a pipeline to run immediately"
+msgstr "ÐевдалоÑÑ Ð·Ð°Ð¿ÑƒÑтити конвеєр негайно"
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "Ðеможливо увійти до групи за допомогою SAML через \"%{reason}\""
+msgid "Unable to update label prioritization at this time"
+msgstr "Ðаразі неможливо оновити пріоретизацію міток"
+
msgid "Unable to update this epic at this time."
msgstr "Ðеможливо оновити цей епік в даний момент."
+msgid "Unable to update this issue at this time."
+msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ цю задачу зараз."
+
msgid "Unarchive project"
-msgstr ""
+msgstr "Розархівувати проект"
msgid "Unarchiving the project will restore people's ability to make changes to it. The repository can be committed to, and issues, comments and other entities can be created. <strong>Once active this project shows up in the search and on the dashboard.</strong>"
msgstr ""
@@ -12063,18 +14362,33 @@ msgstr "Ðа жаль, ваше Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ—
msgid "Unknown"
msgstr "Ðевідомо"
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr "Ðевідома ÑÑ‚Ñ€Ð°Ñ‚ÐµÐ³Ñ–Ñ ÑˆÐ¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ: %{encrypted_strategy}!"
+
+msgid "Unknown format"
+msgstr "Ðевідомий формат"
+
+msgid "Unknown response text"
+msgstr "Ðевідомий текÑÑ‚ відповіді"
+
msgid "Unlimited"
-msgstr ""
+msgstr "Без обмежень"
msgid "Unlock"
msgstr "Розблокувати"
+msgid "Unlock the discussion"
+msgstr "Розблокувати обговореннÑ"
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr "Розблокувати %{issuableDisplayName}? <strong>Будь-хто</strong> зможе залишати коментарі."
msgid "Unlocked"
msgstr "Розблоковано"
+msgid "Unlocks the discussion"
+msgstr "Розблоковує обговореннÑ"
+
msgid "Unresolve discussion"
msgstr "Повторно відкрити обговореннÑ"
@@ -12142,13 +14456,25 @@ msgid "Update your group name, description, avatar, and visibility."
msgstr "Оновіть Ñ–Ð¼â€™Ñ Ð³Ñ€ÑƒÐ¿Ð¸, опиÑ, аватар та видиміÑÑ‚ÑŒ."
msgid "Update your project name, topics, description and avatar."
-msgstr ""
+msgstr "Оновіть ім'Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñƒ, теми, Ð¾Ð¿Ð¸Ñ Ñ‚Ð° аватар."
+
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr "Ðеможливо перейменувати проект, тому що він має теги в реєÑтрі контейнерів!"
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr "Ðеможливо вÑтановити гілку за замовчуваннÑм"
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr "Ðовий рівень видимоÑÑ‚Ñ– не допуÑкаєтьÑÑ!"
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr "Проект не може бути оновлений!"
msgid "Updated"
msgstr "Оновлено"
msgid "Updated %{updated_at} by %{updated_by}"
-msgstr ""
+msgstr "Оновлено %{updated_at} %{updated_by}"
msgid "Updating"
msgstr "ОновленнÑ"
@@ -12166,7 +14492,7 @@ msgid "Upgrade your plan to activate Contribution Analytics."
msgstr "Перейдіть на вищий тарифний план Ð´Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ— Ðналітики учаÑників."
msgid "Upgrade your plan to activate Group Webhooks."
-msgstr "Перейдіть на вищий тарифний план щоб активувати групові веб-гуки."
+msgstr "Перейдіть на вищий тарифний план щоб активувати групові веб-хуки."
msgid "Upgrade your plan to activate Issue weight."
msgstr "Перейдіть на вищий тарифний план щоб активувати вагу обговорень задач."
@@ -12195,6 +14521,9 @@ msgstr "Завантажити приватний ключ Ð´Ð»Ñ Ñертифі
msgid "Upload file"
msgstr "ÐадіÑлати файл"
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12202,19 +14531,22 @@ msgid "UploadLink|click to upload"
msgstr "ÐатиÑніть, щоб надіÑлати"
msgid "Uploaded on"
+msgstr "Завантажено на"
+
+msgid "Uploading changes to terminal"
msgstr ""
msgid "Uploads"
msgstr ""
msgid "Upstream"
-msgstr ""
+msgstr "Попередній"
msgid "Upvotes"
msgstr "Лайки"
msgid "Usage"
-msgstr ""
+msgstr "ВикориÑтано"
msgid "Usage ping is not enabled"
msgstr "Збір даних про викориÑÑ‚Ð°Ð½Ð½Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð¾"
@@ -12222,6 +14554,54 @@ msgstr "Збір даних про викориÑÑ‚Ð°Ð½Ð½Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð¾"
msgid "Usage statistics"
msgstr "СтатиÑтика викориÑтаннÑ"
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr "Ðртефакти"
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr "Купити додаткові хвилини"
+
+msgid "UsageQuota|Current period usage"
+msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð·Ð° поточний період"
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr "Конвеєри"
+
+msgid "UsageQuota|Repository"
+msgstr "Репозиторій"
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr "Без обмежень"
+
+msgid "UsageQuota|Usage"
+msgstr "ВикориÑтаннÑ"
+
+msgid "UsageQuota|Usage Quotas"
+msgstr "Квоти на викориÑтаннÑ"
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð³Ñ€ÑƒÐ¿Ð¾Ð²Ð¸Ñ… реÑурÑів у проектах групи %{strong_start}%{group_name}%{strong_end}"
+
+msgid "UsageQuota|Usage since"
+msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð²Ñ–Ð´"
+
+msgid "UsageQuota|Wiki"
+msgstr "Вікі"
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12231,6 +14611,12 @@ msgstr "ВикориÑтовувати <code>%{native_redirect_uri}</code> длÑ
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "ВикориÑтовуйте Service Desk Ð´Ð»Ñ Ð·Ð²â€™Ñзку з вашими кориÑтувачами (наприклад, щоб запропонувати клієнтÑьку підтримку) через електронну пошту безпоÑередньо із GitLab"
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr "ВикориÑтовуйте групові етапи, щоб керувати у одному етапі задачі з різних проектів."
@@ -12256,7 +14642,7 @@ msgid "Used to help configure your identity provider"
msgstr "ВикориÑтовуєтьÑÑ Ð´Ð»Ñ Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¸ в налаштуванні провайдера ідентифікації"
msgid "User %{current_user_username} has started impersonating %{username}"
-msgstr ""
+msgstr "КориÑтувач %{current_user_username} розпочав Ñ–Ð¼Ñ–Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ %{username}"
msgid "User %{username} was successfully removed."
msgstr ""
@@ -12288,9 +14674,12 @@ msgstr ""
msgid "User map"
msgstr "Мапа кориÑтувачів"
-msgid "User settings"
+msgid "User pipeline minutes were successfully reset."
msgstr ""
+msgid "User settings"
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
+
msgid "User was successfully created."
msgstr ""
@@ -12303,6 +14692,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr "Створити проект"
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr "Зрозуміло"
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr "ÐÑ–, дÑкую"
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr "ÐктивніÑÑ‚ÑŒ"
@@ -12378,6 +14902,15 @@ msgstr "Ви ще не Ñтворили жодних Ñніпетів."
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr "За вашим вибором ваші проекти можуть бути доÑтупні публічно, внутрішньо або приватно."
+msgid "Username (optional)"
+msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача (необов'Ñзково)"
+
+msgid "Username is already taken."
+msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача вже зайнÑто."
+
+msgid "Username is available."
+msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача доÑтупне."
+
msgid "Users"
msgstr "КориÑтувачі"
@@ -12391,11 +14924,29 @@ msgid "Users were successfully added."
msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
+msgstr "КориÑтувачі із роллю ГіÑÑ‚ÑŒ або Ñ‚Ñ–, що не належать до жодного проекту або групи не враховуютьÑÑ Ð¿Ñ€Ð¸ підрахунку міÑць."
+
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr "Виконавець"
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr "Перевірити"
@@ -12406,13 +14957,13 @@ msgid "Validations failed."
msgstr ""
msgid "Validity"
-msgstr ""
+msgstr "Термін дії"
msgid "Value"
msgstr "ЗначеннÑ"
msgid "Variables"
-msgstr ""
+msgstr "Змінні"
msgid "Various container registry settings."
msgstr "Різноманітні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÑ”Ñтру контейнерів."
@@ -12441,12 +14992,18 @@ msgstr "ВерÑÑ–Ñ"
msgid "View app"
msgstr "ПереглÑнути заÑтоÑунок"
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr "ПереглÑнути розгортаннÑ"
msgid "View details: %{details_url}"
msgstr "ПереглÑнути деталі: %{details_url}"
+msgid "View documentation"
+msgstr "ПереглÑнути документацію"
+
msgid "View eligible approvers"
msgstr "ПереглÑнути доÑтупних оÑіб Ð´Ð»Ñ Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ"
@@ -12456,6 +15013,9 @@ msgstr "ПереглÑнути ÑпиÑок епіків"
msgid "View file @ "
msgstr "ПереглÑд файла @ "
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr "ПереглÑнути мітки групи"
@@ -12465,9 +15025,12 @@ msgstr "ПереглÑнути в Sentry"
msgid "View it on GitLab"
msgstr "ПереглÑнути це на GitLab"
-msgid "View job trace"
+msgid "View job"
msgstr ""
+msgid "View job trace"
+msgstr "ПереглÑнути лог завданнÑ"
+
msgid "View jobs"
msgstr "ПереглÑнути завданнÑ"
@@ -12492,6 +15055,9 @@ msgstr "ПереглÑнути документацію"
msgid "Viewing commit"
msgstr "ПереглÑд коміту"
+msgid "Visibility"
+msgstr "ВидиміÑÑ‚ÑŒ"
+
msgid "Visibility and access controls"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑ‚Ñ– та доÑтупу"
@@ -12502,7 +15068,7 @@ msgid "Visibility level:"
msgstr "Рівень видимоÑÑ‚Ñ–:"
msgid "Visibility, project features, permissions"
-msgstr ""
+msgstr "ВидиміÑÑ‚ÑŒ, оÑобливоÑÑ‚Ñ– проекту, дозволи"
msgid "Visibility:"
msgstr "ВидиміÑÑ‚ÑŒ:"
@@ -12519,6 +15085,33 @@ msgstr "Публічний"
msgid "VisibilityLevel|Unknown"
msgstr "Ðевідомий"
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr "%{stepStart}Крок 1%{stepEnd}. Скопіюйте наÑтупний Ñкрипт:"
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr "%{stepStart}Крок 2%{stepEnd}. Додайте його до %{headTags} Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ñ— Ñторінки вашого заÑтоÑунку. "
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr "%{stepStart}Крок 3%{stepEnd}. Відкрийте review app та введіть перÑональний токен доÑтупу викориÑтовуючи %{linkStart}перÑональний токен доÑтупу%{linkEnd}."
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr "%{stepStart}Крок 4%{stepEnd}. Тепер ви можете залишати відгуки прÑмо із review app."
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð½Ð°Ñтупного Ñкрипта до вашого коду дозволÑÑ” залишати відгуки прÑмо з review app. Ðадані відгуки разом з метаданними будуть автоматично включені в Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на злиттÑ."
+
+msgid "VisualReviewApp|Open review app"
+msgstr "Відкрити review app"
+
+msgid "VisualReviewApp|Review"
+msgstr "ПереглÑд"
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr "ПереглÑдайте Ñ– надавайте відгуки прÑмо із review app"
+
+msgid "Vulnerabilities"
+msgstr "ВразливоÑÑ‚Ñ–"
+
msgid "Vulnerability Chart"
msgstr "СтатиÑтика вразливоÑтей"
@@ -12541,7 +15134,7 @@ msgid "Vulnerability|Identifiers"
msgstr "Ідентифікатори"
msgid "Vulnerability|Image"
-msgstr ""
+msgstr "Образ"
msgid "Vulnerability|Instances"
msgstr "ІнÑтанÑи"
@@ -12550,7 +15143,7 @@ msgid "Vulnerability|Links"
msgstr "ПоÑиланнÑ"
msgid "Vulnerability|Namespace"
-msgstr ""
+msgstr "ПроÑÑ‚Ñ–Ñ€ імен"
msgid "Vulnerability|Project"
msgstr "Проект"
@@ -12561,6 +15154,9 @@ msgstr "Тип звіту"
msgid "Vulnerability|Severity"
msgstr "Рівень"
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Хочете побачити дані? Будь лаÑка, попроÑить у адмініÑтратора доÑтуп."
@@ -12579,6 +15175,9 @@ msgstr "Ми не змогли визначити шлÑÑ… до видаленн
msgid "We couldn't find any results matching"
msgstr "Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ відповідні результати"
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "Ми виÑвили потенційний Ñпам у %{humanized_resource_name}. Будь лаÑка, введіть цей код Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ reCAPTCHA, щоб продовжити."
@@ -12588,6 +15187,9 @@ msgstr "Ми не маємо доÑтатньо даних Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°
msgid "We heard back from your U2F device. You have been authenticated."
msgstr "Ми отримали відповідь від вашого приÑтрою U2F. Ви пройшли автентифікацію."
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "Ми хочемо бути впевнені, що це ви, будь лаÑка, підтвердіть, що ви не робот."
@@ -12601,13 +15203,16 @@ msgid "Web terminal"
msgstr "Веб-термінал"
msgid "Webhooks"
-msgstr ""
+msgstr "Веб-хуки"
msgid "Webhooks Help"
-msgstr ""
+msgstr "Допомога по веб-хукам"
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
-msgstr "Веб-гук дозволÑÑ” вам викликати URL Ñкщо, наприклад, був відправлений новий код або Ñтворено нову задачу. Ви можете налаштувати його так, щоб він реагував на певні події (відправки коду, задачі або запити на злиттÑ). Групові веб-гуки заÑтоÑовуютьÑÑ Ð´Ð¾ вÑÑ–Ñ… проектів в групі Ñ– дозволÑÑŽÑ‚ÑŒ вам Ñтандартизувати Ñ—Ñ… Ð´Ð»Ñ Ð²Ñієї вашої групи."
+msgstr "Веб-хук дозволÑÑ” вам викликати URL Ñкщо, наприклад, був відправлений новий код або Ñтворено нову задачу. Ви можете налаштувати його так, щоб він реагував на певні події (відправки коду, задачі або запити на злиттÑ). Групові веб-хуки заÑтоÑовуютьÑÑ Ð´Ð¾ вÑÑ–Ñ… проектів в групі Ñ– дозволÑÑŽÑ‚ÑŒ вам Ñтандартизувати Ñ—Ñ… Ð´Ð»Ñ Ð²Ñієї вашої групи."
+
+msgid "Wednesday"
+msgstr "Середа"
msgid "Weeks"
msgstr "Тижні"
@@ -12618,15 +15223,18 @@ msgstr "Вага"
msgid "Weight %{weight}"
msgstr "Вага %{weight}"
+msgid "Welcome to the Guided GitLab Tour"
+msgstr ""
+
+msgid "Welcome to your Issue Board!"
+msgstr ""
+
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Коли runner закріплений (за проектами), його не можна викориÑтовувати в інших проектах"
msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr "Якщо увімкнено, кориÑтувачі не можуть викориÑтовувати GitLab, поки вони не приймуть умови."
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr "Якщо залишити URL порожнім, можна вÑтановлювати мітки клаÑифікації без Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ð¹ проекту та Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾Ñ— авторизації."
@@ -12640,6 +15248,9 @@ msgstr[3] ""
msgid "When:"
msgstr "Коли:"
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr "Хто може бачити цю групу?"
@@ -12764,7 +15375,7 @@ msgid "Wiki|Create page"
msgstr "Створити Ñторінку"
msgid "Wiki|Created date"
-msgstr ""
+msgstr "Дата ÑтвореннÑ"
msgid "Wiki|Edit Page"
msgstr "Ð ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ cторінки"
@@ -12785,7 +15396,7 @@ msgid "Wiki|Pages"
msgstr "Сторінки"
msgid "Wiki|Title"
-msgstr ""
+msgstr "Заголовок"
msgid "Wiki|Wiki Pages"
msgstr "Вікі-Ñторінки"
@@ -12800,7 +15411,7 @@ msgid "Withdraw Access Request"
msgstr "СкаÑувати запит доÑтупу"
msgid "Workflow Help"
-msgstr ""
+msgstr "Довідка по робочому процеÑу"
msgid "Write"
msgstr "ÐапиÑати"
@@ -12820,6 +15431,9 @@ msgstr ""
msgid "Yes"
msgstr "Так"
+msgid "Yes or No"
+msgstr "Так або ні"
+
msgid "Yes, add it"
msgstr "Так, додати це"
@@ -12835,8 +15449,14 @@ msgstr "Ви"
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr "Ви — адмініÑтратор, а це означає, що Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупу Ð´Ð»Ñ <strong>%{client_name}</strong> дозволить їм взаємодіÑти з GitLab Ñк адмініÑтратору. Продовжуйте обережно."
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "Ви хочете видалити %{group_name}. Видалені групи ÐЕ МОЖÐРбуду відновити! Ви ÐБСОЛЮТÐО впевнені?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "Ви хочете видалити %{project_full_name}. Видалений проект ÐЕ МОЖЕ бути відновлений! Ви ÐБСОЛЮТÐО впевнені?"
@@ -12847,9 +15467,12 @@ msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ зв'Ñзок з форка Ð
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr "Ви збираєтеÑÑ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‚Ð¸ проект %{project_full_name} іншому влаÑнику. Ви ÐБСОЛЮТÐО впевнені?"
-msgid "You are now impersonating %{username}"
+msgid "You are not allowed to unlink your primary login account"
msgstr ""
+msgid "You are now impersonating %{username}"
+msgstr "Зараз ви імітуєте %{username}"
+
msgid "You are on a read-only GitLab instance."
msgstr "Ви знаходитеÑÑ Ð½Ð° інÑтанÑÑ– Gitlab \"тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ\"."
@@ -12862,6 +15485,12 @@ msgstr "ЗаміÑÑ‚ÑŒ цього ви можете %{linkStart}переглÑн
msgid "You can also create a project from the command line."
msgstr "Ви також можете Ñтворити проект із командного Ñ€Ñдка."
+msgid "You can also press &#8984;-Enter"
+msgstr "Ви також можете натиÑнути &#8984;-Enter"
+
+msgid "You can also press Ctrl-Enter"
+msgstr "Ви також можете натиÑнути Ctrl-Enter"
+
msgid "You can also star a label to make it a priority label."
msgstr "Ви можете додати мітку в обрані, щоб зробити її пріоритетною."
@@ -12880,6 +15509,15 @@ msgstr "Ви можете легко робити внеÑки до них, за
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr "Ви можете легко вÑтановити Runner на клаÑтері Kubernetes. %{link_to_help_page}"
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr "Ви можете запроÑити нового учаÑника до <strong>%{project_name}</strong> або запроÑити іншу групу."
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr "Ви можете запроÑити нового учаÑника до <strong>%{project_name}</strong>."
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr "Ви можете запроÑити нову групу до <strong>%{project_name}</strong>."
+
msgid "You can move around the graph by using the arrow keys."
msgstr "Ви можете переÑуватиÑÑ Ð¿Ð¾ графіку за допомогою клавіш зі Ñтрілками."
@@ -12899,25 +15537,31 @@ msgid "You can only merge once the items above are resolved"
msgstr "Ви можете зливати лише коли вищезгадані пункти будуть вирішені"
msgid "You can only transfer the project to namespaces you manage."
-msgstr ""
+msgstr "Ви можете переміщувати проект тільки в проÑтори імен, Ñкими ви керуєте."
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "Ви можете розв’Ñзати цей конфлікт Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð° допомогою інтерактивного режиму (викориÑтовуючи кнопки %{use_ours} та %{use_theirs}), або безпоÑередньо редагуючи файли. Закомітити зміни у %{branch_name}"
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr "Ви можете налаштувати Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð½Ð° викориÑÑ‚Ð°Ð½Ð½Ñ Runnir'ів з конкретними тегами. РозділÑйте теги комами."
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr "Ви можете перевірити Ñвій .gitlab-ci.yml у %{linkStart}CI Lint%{linkEnd}."
msgid "You cannot impersonate a blocked user"
-msgstr ""
+msgstr "Ви не можете імітувати заблокованого кориÑтувача"
msgid "You cannot impersonate a user who cannot log in"
-msgstr ""
+msgstr "Ви не можете імітувати кориÑтувача, Ñкий не може увійти"
msgid "You cannot impersonate an internal user"
-msgstr ""
+msgstr "Ви не можете імітувати внутрішнього кориÑтувача"
msgid "You cannot play this scheduled pipeline at the moment. Please wait a minute."
msgstr ""
@@ -12929,20 +15573,29 @@ msgid "You cannot write to this read-only GitLab instance."
msgstr "Ви не можете запиÑувати на цей \"тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ\" інÑÑ‚Ð°Ð½Ñ GitLab."
msgid "You could not create a new trigger."
-msgstr ""
+msgstr "Ви не змогли Ñтворити новий тригер."
msgid "You could not take ownership of trigger."
-msgstr ""
+msgstr "Ви не змогли Ñтати влаÑником тригеру."
msgid "You do not have any subscriptions yet"
msgstr "У Ð²Ð°Ñ Ñ‰Ðµ немає підпиÑок"
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr "Ви не маєте дозволу запуÑкати Веб-термінал. Будь лаÑка, звернітьÑÑ Ð´Ð¾ адмініÑтратора проекту."
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” необхідних прав доÑтупу, щоб перевизначити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñинхронізації LDAP-груп."
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” активних імен Ð´Ð»Ñ Ñ‡Ð°Ñ‚Ñ–Ð²."
+
msgid "You don't have any applications"
msgstr "Ви не маєте ніÑких заÑтоÑунків"
@@ -12952,14 +15605,20 @@ msgstr "Ви не маєте ніÑких авторизованих заÑтоÑ
msgid "You don't have any deployments right now."
msgstr "Ðаразі у Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” ніÑких розгортань."
-msgid "You have been granted %{member_human_access} access to %{label}."
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{member_human_access} access to %{label}."
+msgstr "Вам надано %{member_human_access} доÑтуп до %{label}."
+
msgid "You have been unsubscribed from this thread."
msgstr ""
msgid "You have declined the invitation to join %{label}."
-msgstr ""
+msgstr "Ви відхилили Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ñ‚Ð¸ÑÑ Ð´Ð¾ %{label}."
msgid "You have no permissions"
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” прав доÑтупу"
@@ -12982,11 +15641,20 @@ msgstr "Ви повинні прийнÑти правила кориÑтуван
msgid "You must have maintainer access to force delete a lock"
msgstr "Ви повинні мати доÑтуп керівника Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð¼ÑƒÑового Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ "
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr "Ð”Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ— функції Ð‘Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¤Ð°Ð¹Ð»Ñ–Ð² вам потрібна інша ліцензіÑ"
msgid "You need a different license to use Geo replication."
-msgstr ""
+msgstr "Вам потрібна інша Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñ Ð½Ð° викориÑÑ‚Ð°Ð½Ð½Ñ Ð³ÐµÐ¾Ð³Ñ€Ð°Ñ„Ñ–Ñ‡Ð½Ð¾Ñ— реплікації."
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr "Вам потрібна верÑÑ–Ñ git-lfs верÑÑ–Ñ— %{min_git_lfs_version} (або новіша), щоб продовжити. Будь лаÑка, відвідайте Ñторінку https://git-lfs.github.com"
@@ -12994,6 +15662,9 @@ msgstr "Вам потрібна верÑÑ–Ñ git-lfs верÑÑ–Ñ— %{min_git_lfs_
msgid "You need permission."
msgstr "Вам потрібен дозвіл"
+msgid "You need to be logged in."
+msgstr "Ви повинні увійти."
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr "Вам треба зареєÑтрувати програму Ð´Ð»Ñ Ð´Ð²Ð¾Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾Ñ— автентифікації перед налаштуваннÑм приÑтрою U2F."
@@ -13001,9 +15672,12 @@ msgid "You need to specify both an Access Token and a Host URL."
msgstr ""
msgid "You need to upload a GitLab project export archive (ending in .gz)."
-msgstr ""
+msgstr "Ви повинні завантажити екÑпортований архів проекту Gitlab (що закінчуєтьÑÑ Ð½Ð° .gz)."
msgid "You need to upload a Google Takeout archive."
+msgstr "Вам потрібно завантажити архів Google Takeout."
+
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
msgstr ""
msgid "You will lose all changes you've made to this file. This action cannot be undone."
@@ -13039,6 +15713,9 @@ msgstr "Ви не зможете відправлÑти та отримуватÐ
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "Ви не зможете відправлÑти та отримувати код проекту через SSH, поки не додаÑте в Ñвій профіль SSH ключ"
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr "Вам необхідно викориÑтовувати різні імена гілок Ð´Ð»Ñ ÐºÐ¾Ñ€ÐµÐºÑ‚Ð½Ð¾Ð³Ð¾ порівнÑннÑ."
@@ -13060,32 +15737,56 @@ msgstr "Ви отримали цей електронний лиÑÑ‚, оÑкіл
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr "Ви отримали це Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð½Ð° %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr "YouTube"
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr "Ваші ключі GPG (%{count})"
+
msgid "Your Groups"
msgstr "Ваші групи"
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr "Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ ваш Kubernetes-клаÑтер вÑе ще доÑтупна Ð´Ð»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð° цій Ñторінці, але ми радимо вимкнути Ñ– повторно налаштувати"
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr "Ваші проекти (за замовчуваннÑм)"
msgid "Your Projects' Activity"
msgstr "ÐктивніÑÑ‚ÑŒ ваших проектів"
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr "Ваші ключі SSH (%{count})"
+
msgid "Your Todos"
msgstr "Ваші ÐагадуваннÑ"
+msgid "Your U2F device did not send a valid JSON response."
+msgstr "Ваш приÑтрій U2F не надіÑлав коректну відповідь JSON."
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr "Ваш приÑтрій U2F має бути налаштований. Підключіть його (Ñкщо ви цього ще не зробили) Ñ– натиÑніть кнопку зліва."
msgid "Your U2F device was registered!"
-msgstr ""
+msgstr "Ваш приÑтрій U2F уÑпішно зареєÑтровано!"
msgid "Your access request to the %{source_type} has been withdrawn."
msgstr ""
@@ -13112,10 +15813,13 @@ msgid "Your changes have been saved"
msgstr "Ваші зміни було збережено"
msgid "Your changes have been successfully committed."
+msgstr "Ваші зміни уÑпішно закомічено."
+
+msgid "Your comment could not be submitted! Please check your network connection and try again."
msgstr ""
-msgid "Your comment will not be visible to the public."
-msgstr "Ваш коментар не буде видимим Ð´Ð»Ñ Ð²ÑÑ–Ñ…."
+msgid "Your comment could not be updated! Please check your network connection and try again."
+msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
msgstr ""
@@ -13132,17 +15836,20 @@ msgstr "Ваші задачі імпортуютьÑÑ. ПіÑÐ»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐ
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr "Ваші задачі будуть імпортовані в фоні. ПіÑÐ»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð²Ð¸ отримаєте Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾ електронній пошті із підтвердженнÑм."
+msgid "Your message here"
+msgstr "Ваше Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ‚ÑƒÑ‚"
+
msgid "Your name"
msgstr "Ваше ім'Ñ"
msgid "Your new SCIM token"
-msgstr ""
+msgstr "Ваш новий токен SCIM"
msgid "Your new personal access token has been created."
msgstr ""
msgid "Your password reset token has expired."
-msgstr ""
+msgstr "Ваш токен Ð´Ð»Ñ ÑÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»ÑŽ заÑтарів."
msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
msgstr "Ваш ліміт проектів Ñкладає %{limit}! Будь лаÑка, звернітьÑÑ Ð´Ð¾ адмініÑтратора, щоб його збільшити"
@@ -13165,12 +15872,15 @@ msgstr "тому"
msgid "allowed to fail"
msgstr "невдача дозволена"
+msgid "already being used for another group or project milestone."
+msgstr ""
+
+msgid "already shared with this group"
+msgstr ""
+
msgid "among other things"
msgstr "тощо"
-msgid "at"
-msgstr "в"
-
msgid "attach a new file"
msgstr "прикріпити новий файл"
@@ -13183,6 +15893,21 @@ msgstr "ім'Ñ Ð³Ñ–Ð»ÐºÐ¸"
msgid "by"
msgstr "від"
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr "%{linkStartTag}ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚ÐµÐ¹Ð½ÐµÑ€Ñ–Ð² %{linkEndTag}"
@@ -13277,7 +16002,7 @@ msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr "%{reportType}: Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸Ð·Ð²ÐµÐ»Ð¾ до помилки"
msgid "ciReport|%{vulnerability} in %{featurename}"
-msgstr ""
+msgstr "%{vulnerability} в %{featurename}"
msgid "ciReport|(errors when loading results)"
msgstr "(помилки під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ñ–Ð²)"
@@ -13288,14 +16013,17 @@ msgstr "(завантажуєтьÑÑ)"
msgid "ciReport|(is loading, errors when loading results)"
msgstr "(завантажуєтьÑÑ, помилки під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ñ–Ð²)"
+msgid "ciReport|All confidence levels"
+msgstr "УÑÑ– рівні впевненоÑÑ‚Ñ–"
+
msgid "ciReport|All projects"
-msgstr ""
+msgstr "Ð’ÑÑ– проекти"
msgid "ciReport|All report types"
-msgstr ""
+msgstr "Ð’ÑÑ– типи звітів"
msgid "ciReport|All severities"
-msgstr ""
+msgstr "Ð’ÑÑ– рівні"
msgid "ciReport|Class"
msgstr "КлаÑ"
@@ -13321,9 +16049,6 @@ msgstr "Створити задачу"
msgid "ciReport|Create merge request"
msgstr "Створити запит на злиттÑ"
-msgid "ciReport|Created %{eventType}"
-msgstr "Створено %{eventType}"
-
msgid "ciReport|DAST"
msgstr "DAST"
@@ -13339,12 +16064,6 @@ msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей"
msgid "ciReport|Description"
msgstr "ОпиÑ"
-msgid "ciReport|Dismiss vulnerability"
-msgstr "Відхилити вразливіÑÑ‚ÑŒ"
-
-msgid "ciReport|Dismissed by"
-msgstr "Відхилено"
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr "Завантажити або заÑтоÑувати патч, щоб виправити цю вразливіÑÑ‚ÑŒ."
@@ -13367,7 +16086,7 @@ msgid "ciReport|Identifiers"
msgstr "Ідентифікатори"
msgid "ciReport|Image"
-msgstr ""
+msgstr "Образ"
msgid "ciReport|Implement this solution by creating a merge request"
msgstr "Реалізувати це рішеннÑ, Ñтворивши запит на злиттÑ"
@@ -13435,7 +16154,7 @@ msgid "ciReport|Security scanning failed loading any results"
msgstr "Помилка при завантаженні результатів перевірки безпеки"
msgid "ciReport|Severity"
-msgstr "СерйозніÑÑ‚ÑŒ"
+msgstr "Рівень"
msgid "ciReport|Solution"
msgstr "РішеннÑ"
@@ -13467,17 +16186,14 @@ msgstr "Помилка при завантаженні звіту по ÑканÑ
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr "Помилка при відміні відхиленнÑ. Будь лаÑка, Ñпробуйте знову."
-msgid "ciReport|Undo dismiss"
-msgstr "Відмінити відхиленнÑ"
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr "Оновити %{name} з %{version} до %{fixed}."
msgid "ciReport|Upgrade %{name} to %{fixed}."
-msgstr ""
+msgstr "Оновити %{name} до %{fixed}."
msgid "ciReport|Upgrade to %{fixed}."
-msgstr ""
+msgstr "Оновити до %{fixed}."
msgid "ciReport|Used by %{packagesString}"
msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
@@ -13489,35 +16205,35 @@ msgstr[3] "ВикориÑтовуєтьÑÑ %{packagesString} Ñ– %{lastPackage}"
msgid "ciReport|View full report"
msgstr "ПереглÑнути повний звіт"
-msgid "ciReport|on pipeline"
-msgstr "в конвеєрі"
-
msgid "commented on %{link_to_project}"
msgstr "прокоментовано в %{link_to_project}"
+msgid "commit %{commit_id}"
+msgstr "коміт %{commit_id}"
+
msgid "confidence|Confirmed"
-msgstr ""
+msgstr "Підтверджений"
msgid "confidence|Experimental"
-msgstr ""
+msgstr "ЕкÑпериментальний"
msgid "confidence|High"
-msgstr ""
+msgstr "ВиÑокий"
msgid "confidence|Ignore"
-msgstr ""
+msgstr "Ігнорувати"
msgid "confidence|Low"
-msgstr ""
+msgstr "Ðизький"
msgid "confidence|Medium"
-msgstr ""
+msgstr "Середній"
msgid "confidence|Undefined"
-msgstr ""
+msgstr "Ðевизначений"
msgid "confidence|Unknown"
-msgstr ""
+msgstr "Ðевідомо"
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr "Ви вимикаєте конфіденційніÑÑ‚ÑŒ. Це означає, що <strong>будь-хто</strong> зможе бачити Ñ– залишати коментарі Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— задачі."
@@ -13534,6 +16250,9 @@ msgstr "неможливо зчитати приватний ключ, чи Ñ” Ð
msgid "customize"
msgstr "налаштувати"
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] "день"
@@ -13570,9 +16289,15 @@ msgstr[1] "чернетки"
msgstr[2] "чернеток"
msgstr[3] "чернеток"
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr "увімкнено"
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr "епік"
@@ -13585,20 +16310,26 @@ msgstr "код помилки:"
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr "%{slash_command} перезапиÑує запланований Ñ‡Ð°Ñ Ð¾Ñтаннім значеннÑм."
-msgid "failed"
+msgid "expired on %{milestone_due_date}"
msgstr ""
-msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch}"
+msgid "expires on %{milestone_due_date}"
msgstr ""
+msgid "failed"
+msgstr "невдало"
+
+msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch}"
+msgstr "Ð´Ð»Ñ %{link_to_merge_request} з %{link_to_merge_request_source_branch}"
+
msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch} into %{link_to_merge_request_target_branch}"
-msgstr ""
+msgstr "Ð´Ð»Ñ %{link_to_merge_request} з %{link_to_merge_request_source_branch} в %{link_to_merge_request_target_branch}"
msgid "for %{link_to_pipeline_ref}"
-msgstr ""
+msgstr "Ð´Ð»Ñ %{link_to_pipeline_ref}"
msgid "for %{ref}"
-msgstr ""
+msgstr "Ð´Ð»Ñ %{ref}"
msgid "for this project"
msgstr "Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту"
@@ -13609,6 +16340,9 @@ msgstr "від"
msgid "group"
msgstr "група"
+msgid "has already been taken"
+msgstr "уже викориÑтовуєтьÑÑ"
+
msgid "here"
msgstr "тут"
@@ -13640,6 +16374,12 @@ msgstr[1] "завершені інÑтанÑи"
msgstr[2] "завершених інÑтанÑів"
msgstr[3] "завершених інÑтанÑів"
+msgid "invalid milestone state `%{state}`"
+msgstr "некоректний Ñтан етапу '%{state}'"
+
+msgid "is enabled."
+msgstr "увімкнено."
+
msgid "is invalid because there is downstream lock"
msgstr "неправильний через наÑвніÑÑ‚ÑŒ блокувань на нижчих рівнÑÑ…"
@@ -13649,6 +16389,9 @@ msgstr "неправильний через наÑвніÑÑ‚ÑŒ блокуванÑ
msgid "is not a valid X509 certificate."
msgstr "не відповідний Ñертифікат X509."
+msgid "is not an email you own"
+msgstr "не Ñ” адреÑою електронної пошти, Ñкою ви володієте"
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13667,6 +16410,9 @@ msgstr "зберігаєтьÑÑ Ð² LFS"
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr "оÑтанній"
@@ -13677,7 +16423,7 @@ msgid "latest version"
msgstr "оÑÑ‚Ð°Ð½Ð½Ñ Ð²ÐµÑ€ÑÑ–Ñ"
msgid "leave %{group_name}"
-msgstr ""
+msgstr "залишити %{group_name}"
msgid "license management"
msgstr "керувати ліцензіÑми"
@@ -13686,7 +16432,7 @@ msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "заблоковано %{path_lock_user_name} %{created_at}"
msgid "manual"
-msgstr ""
+msgstr "вручну"
msgid "merge request"
msgid_plural "merge requests"
@@ -13695,6 +16441,9 @@ msgstr[1] "запити на злиттÑ"
msgstr[2] "запитів на злиттÑ"
msgstr[3] "запитів на злиттÑ"
+msgid "milestone should belong either to a project or a group."
+msgstr "етап повинен належати до проекту або до групи."
+
msgid "missing"
msgstr "відÑутні"
@@ -13722,8 +16471,8 @@ msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ %{metricsLinkStart} пам’ÑÑ‚Ñ– %{metricsLi
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ %{metricsLinkStart} пам’ÑÑ‚Ñ– %{metricsLinkEnd} %{emphasisStart} не змінилоÑÑ %{emphasisEnd} %{memoryFrom}Мб"
-msgid "mrWidget|Add approval"
-msgstr "Додати затвердженнÑ"
+msgid "mrWidget|Added to the merge train by"
+msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "ДозволÑÑ” коміти від учаÑників, Ñкі можуть зливати до цільової гілки"
@@ -13737,6 +16486,9 @@ msgstr "Помилка при отриманні даних про затверÐ
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "Помилка при обробці вашого затвердженнÑ."
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr "Затвердити"
@@ -13791,6 +16543,9 @@ msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ ÑтатиÑтику розг
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr "Fast-forward Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð½ÐµÐ¼Ð¾Ð¶Ð»Ð¸Ð²Ðµ. Ð”Ð»Ñ Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиту, Ñпочатку виконайте локальний rebase."
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr "Якщо гілка %{branch} Ñ–Ñнує у вашому локальному репозиторії, то ви можете заÑтоÑувати цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ за допомогою"
@@ -13809,18 +16564,15 @@ msgstr "ЗлиттÑ"
msgid "mrWidget|Merge failed."
msgstr "Ð—Ð»Ð¸Ñ‚Ñ‚Ñ Ð¿Ñ€Ð¾Ð¹ÑˆÐ»Ð¾ невдало."
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
+msgstr ""
+
msgid "mrWidget|Merge locally"
msgstr "Злити локально"
-msgid "mrWidget|Merge request approved"
-msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð¾"
-
msgid "mrWidget|Merge request approved."
msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð¾."
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð±ÑƒÐ»Ð¾ затверджено; Ви можете затвердити додатково"
-
msgid "mrWidget|Merged by"
msgstr "Злито"
@@ -13851,26 +16603,12 @@ msgstr "Оновити зараз"
msgid "mrWidget|Refreshing now"
msgstr "ВідбуваєтьÑÑ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ"
-msgid "mrWidget|Remove your approval"
-msgstr "Видалити ваше затвердженнÑ"
+msgid "mrWidget|Remove from merge train"
+msgstr ""
msgid "mrWidget|Request to merge"
msgstr "Запит на злиттÑ"
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] "Ðеобхідне ще 1 ÑхваленнÑ"
-msgstr[1] "Ðеобхідно ще %d ÑхваленнÑ"
-msgstr[2] "Ðеобхідно ще %d Ñхвалень"
-msgstr[3] "Ðеобхідно ще %d Ñхвалень"
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] "Ðеобхідне ще 1 ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´"
-msgstr[1] "Ðеобхідно ще %d ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´"
-msgstr[2] "Ðеобхідно ще %d Ñхвалень від"
-msgstr[3] "Ðеобхідно ще %d Ñхвалень від"
-
msgid "mrWidget|Resolve conflicts"
msgstr "Вирішити конфлікти"
@@ -13955,15 +16693,30 @@ msgstr "командного Ñ€Ñдка"
msgid "mrWidget|into"
msgstr "в"
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr "буде злито автоматично, коли конвеєр завершитьÑÑ ÑƒÑпішно"
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr "повинна бути пізніша за дату початку"
+
msgid "n/a"
msgstr "н/д"
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr "має бути між 10 хвилинами та 1 міÑÑцем"
+
msgid "new merge request"
msgstr "Ðовий запит на злиттÑ"
+msgid "no contributions"
+msgstr ""
+
msgid "none"
msgstr "немає"
@@ -14004,10 +16757,10 @@ msgstr "оÑобиÑтий токен доÑтупу"
msgid "point"
msgid_plural "points"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "бал"
+msgstr[1] "бали"
+msgstr[2] "балів"
+msgstr[3] "балів"
msgid "private"
msgstr "приватний"
@@ -14063,28 +16816,28 @@ msgid "security Reports|There was an error creating the merge request"
msgstr "помилка при Ñтворенні запиту на злиттÑ"
msgid "severity|Critical"
-msgstr ""
+msgstr "Критичний"
msgid "severity|High"
-msgstr ""
+msgstr "ВиÑокий"
msgid "severity|Info"
-msgstr ""
+msgstr "Інформаційний"
msgid "severity|Low"
-msgstr ""
+msgstr "Ðизький"
msgid "severity|Medium"
-msgstr ""
+msgstr "Середній"
msgid "severity|Undefined"
-msgstr ""
+msgstr "Ðевизначений"
msgid "severity|Unknown"
-msgstr ""
+msgstr "Ðевідомий"
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
-msgstr "має бути вищим за %{access}, уÑпадкованого з групи %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
+msgstr ""
msgid "show less"
msgstr "показати менше"
@@ -14092,23 +16845,35 @@ msgstr "показати менше"
msgid "sign in"
msgstr "увійти"
+msgid "sort:"
+msgstr "Ñортувати:"
+
msgid "source"
msgstr "джерело"
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} оновлює Ñуму витраченого чаÑу."
msgid "started"
msgstr "розпочато"
+msgid "started on %{milestone_start_date}"
+msgstr "розпочато %{milestone_start_date}"
+
+msgid "starts on %{milestone_start_date}"
+msgstr "розпочинаєтьÑÑ %{milestone_start_date}"
+
msgid "stuck"
msgstr "заблоковано"
msgid "success"
-msgstr ""
+msgstr "уÑпіх"
msgid "syntax is correct"
msgstr "ÑинтакÑÐ¸Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð¸Ð¹"
@@ -14137,12 +16902,33 @@ msgstr "викориÑтовує клаÑтери Kubernetes Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€
msgid "verify ownership"
msgstr "перевірити право влаÑноÑÑ‚Ñ–"
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr "переглÑнути це на GitLab"
msgid "view the blob"
msgstr "переглÑнути бінарні дані"
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr "Відхилити вразливіÑÑ‚ÑŒ"
+
+msgid "vulnerability|Undo dismiss"
+msgstr "Відмінити відхиленнÑ"
+
+msgid "vulnerability|dismissed"
+msgstr "відхилено"
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "з %{additions} додаваннÑми Ñ– %{deletions} видаленнÑми."
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index 7ab1b5ecfe7..cd245f36bab 100644
--- a/locale/zh_CN/gitlab.po
+++ b/locale/zh_CN/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Chinese Simplified\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
@@ -13,19 +13,16 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: zh-CN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:36\n"
+"PO-Revision-Date: 2019-06-14 10:19\n"
msgid " Please sign in."
-msgstr ""
-
-msgid " Status"
-msgstr "状æ€"
+msgstr " 请登录。"
msgid " Try to %{action} this file again."
-msgstr ""
+msgstr "å†æ¬¡å°è¯•%{action}此文件。"
msgid " You need to do this before %{grace_period_deadline}."
-msgstr ""
+msgstr " 您需è¦åœ¨ %{grace_period_deadline} 之å‰æ‰§è¡Œæ­¤æ“作。"
msgid " and"
msgstr "和"
@@ -62,6 +59,10 @@ msgstr[0] "è½åŽ %d 个æ交"
msgid "%d commits"
msgstr "%d 次æ交"
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] "%d个贡献"
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d 导出器"
@@ -90,10 +91,18 @@ msgid "%d merge request"
msgid_plural "%d merge requests"
msgstr[0] "%d 个åˆå¹¶è¯·æ±‚"
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d 个指标"
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] "%d个更多评论"
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] "%d 个已暂存的修改"
@@ -115,11 +124,8 @@ msgstr "%{authorsName}的讨论"
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "ç”± %{commit_author_link} æ交于 %{commit_timeago}"
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr "%{counter_storage} (%{counter_repositories} 个存储库, %{counter_build_artifacts} 个构建产物, %{counter_lfs_objects} 个LFS对象)"
-
-msgid "%{count} %{alerts}"
-msgstr "%{count}个%{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
+msgstr "%{counter_repositories}个仓库, %{counter_wikis}个wikis, %{counter_build_artifacts}个构建产物, %{counter_lfs_objects}个LFS"
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
@@ -148,6 +154,12 @@ msgid "%{count} pending comment"
msgid_plural "%{count} pending comments"
msgstr[0] "%{count}个待处ç†çš„评论"
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr "%{edit_in_new_fork_notice} å°è¯•å†æ¬¡æ‹£é€‰æ­¤æ交。"
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr "%{edit_in_new_fork_notice} Try to revert this commit again."
+
msgid "%{filePath} deleted"
msgstr "%{filePath} 已删除"
@@ -160,14 +172,26 @@ msgstr "在此æ交中找ä¸åˆ° %{gitlab_ci_yml}"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}群组%{group_docs_link_end} å…许您管ç†ã€å作多个项目。群组的æˆå‘˜å¯ä»¥è®¿é—®ç¾¤ç»„下的所有项目。"
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr "%{group_name}使用由群组管ç†çš„å¸æˆ·ã€‚您需è¦åˆ›å»ºä¸€ä¸ªæ–°çš„GitLabå¸æˆ·ï¼Œè¯¥å¸æˆ·å°†é€šè¿‡%{group_name}组æ¥ç®¡ç†ã€‚"
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} 将被删除ï¼æ‚¨ç¡®å®šå—?"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message}ä¸å¯ç”¨"
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} 是一个å…费且自动化的和开放的è¯ä¹¦é¢å‘机构(CA),æ供数字è¯ä¹¦ä»¥ä¾¿ä¸ºç½‘ç«™å¯ç”¨HTTPS(SSL / TLS)。"
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr "%{level_name} ä¸å…许在 %{group_level_name} 组。"
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr "由于派生的æºé¡¹ç›®å¯è§æ€§è¾ƒä½Žï¼Œå› æ­¤ä¸å…许使用%{level_name}。"
+
msgid "%{level_name} visibility has been restricted by the administrator."
-msgstr ""
+msgstr "%{level_name} å¯è§æ€§å·²å—到管ç†å‘˜çš„é™åˆ¶ã€‚"
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "%{link_start}查看更多%{link_end} 关于角色æƒé™"
@@ -179,7 +203,13 @@ msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} 被GitLab用户 %{lock_user_id} é”定"
msgid "%{mrText}, this issue will be closed automatically."
-msgstr ""
+msgstr "%{mrText},此议题将自动关闭。"
+
+msgid "%{name} contained %{resultsString}"
+msgstr "%{name} åŒ…å« %{resultsString}"
+
+msgid "%{name} found %{resultsString}"
+msgstr "%{name} 找到了 %{resultsString}"
msgid "%{name}'s avatar"
msgstr "%{name} 的头åƒ"
@@ -194,16 +224,28 @@ msgid "%{percent}%% complete"
msgstr "å·²å®Œæˆ %{percent}%%"
msgid "%{service_title} activated."
-msgstr ""
+msgstr "%{service_title} 已激活。"
msgid "%{service_title} settings saved, but not activated."
-msgstr ""
+msgstr "%{service_title} 设置已ä¿å­˜ï¼Œä½†æœªæ¿€æ´»ã€‚"
+
+msgid "%{size} GiB"
+msgstr "%{size}G字节"
+
+msgid "%{size} KiB"
+msgstr "%{size}K字节"
+
+msgid "%{size} MiB"
+msgstr "%{size}M字节"
+
+msgid "%{size} bytes"
+msgstr "%{size}字节"
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
-msgstr ""
+msgstr "%{spammable_titlecase} æˆåŠŸåœ°æ交给 Akismet。"
msgid "%{state} epics"
-msgstr "epic %{state}"
+msgstr "%{state}å²è¯—"
msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
@@ -214,7 +256,7 @@ msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] "%{strong_start}%{commit_count}%{strong_end} 次æ交"
msgid "%{strong_start}%{human_size}%{strong_end} Files"
-msgstr "%{strong_start}%{human_size}%{strong_end} 个文件"
+msgstr "%{strong_start}%{human_size}%{strong_end} 文件"
msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
@@ -227,6 +269,9 @@ msgstr[0] "%{text}%{files}"
msgid "%{text} is available"
msgstr "%{text}å¯ç”¨"
+msgid "%{title} %{operator} %{threshold}"
+msgstr "%{title} %{operator} %{threshold}"
+
msgid "%{title} changes"
msgstr "%{title}更改"
@@ -239,9 +284,28 @@ msgstr "%{usage_ping_link_start}了解更多%{usage_ping_link_end}关于GitLab I
msgid "%{user_name} profile page"
msgstr "%{user_name}的个人资料"
-msgid "(No changes)"
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr "%{verb} 耗时 %{time_spent_value}"
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr "“%{level}â€ä¸æ˜¯æœ‰æ•ˆçš„å¯è§æ€§çº§åˆ«"
+
+msgid "'%{source}' is not a import source"
+msgstr "'%{source}'ä¸æ˜¯ä¸€ä¸ªå¯¼å…¥æº"
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+
+msgid "(%{mrCount} merged)"
msgstr ""
+msgid "(No changes)"
+msgstr "(æ— å˜æ›´å†…容)"
+
+msgid "(check progress)"
+msgstr "(检查进度)"
+
msgid "(external source)"
msgstr "(外部资æº)"
@@ -266,6 +330,9 @@ msgstr "- Runner已暂åœï¼Œæš‚æ—¶ä¸ä¼šæŽ¥å—新的作业"
msgid "- show less"
msgstr "- 显示较少"
+msgid "0 for unlimited"
+msgstr "0 表示无é™åˆ¶"
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] "%{count} 个 %{type} 的添加"
@@ -279,31 +346,31 @@ msgid_plural "%d Days"
msgstr[0] "%d天"
msgid "1 closed issue"
-msgid_plural "%d closed issues"
-msgstr[0] "%d 个已关闭的议题"
+msgid_plural "%{issues} closed issues"
+msgstr[0] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
-msgstr[0] "%d 个已关闭的åˆå¹¶è¯·æ±‚"
+msgid_plural "%{merge_requests} closed merge requests"
+msgstr[0] ""
msgid "1 day"
-msgstr ""
+msgstr "1天"
msgid "1 group"
msgid_plural "%d groups"
msgstr[0] "%d 个群组"
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
-msgstr[0] "%d 个已åˆå¹¶çš„åˆå¹¶è¯·æ±‚"
+msgid_plural "%{merge_requests} merged merge requests"
+msgstr[0] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
-msgstr[0] "%d 个开å¯ä¸­çš„议题"
+msgid_plural "%{issues} open issues"
+msgstr[0] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
-msgstr[0] "%d 个开å¯ä¸­çš„åˆå¹¶è¯·æ±‚"
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] ""
msgid "1 pipeline"
msgid_plural "%d pipelines"
@@ -318,25 +385,40 @@ msgid_plural "%d users"
msgstr[0] "%d ä½ç”¨æˆ·"
msgid "1 week"
-msgstr ""
+msgstr "1周"
+
+msgid "1-9 contributions"
+msgstr "1-9项贡献"
+
+msgid "10-19 contributions"
+msgstr "10-19项贡献"
msgid "1st contribution!"
msgstr "最高贡献"
+msgid "20-29 contributions"
+msgstr "20-29项贡献"
+
msgid "2FA"
-msgstr "åŒå› å­éªŒè¯"
+msgstr "åŒé‡è®¤è¯"
msgid "2FA enabled"
-msgstr "å¯ç”¨åŒé‡è®¤è¯"
+msgstr "åŒé‡è®¤è¯å¼€å¯"
+
+msgid "2FADevice|Registered On"
+msgstr "注册于"
msgid "3 days"
-msgstr ""
+msgstr "3天"
msgid "3 hours"
-msgstr ""
+msgstr "3å°æ—¶"
msgid "30 minutes"
-msgstr ""
+msgstr "30分钟"
+
+msgid "30+ contributions"
+msgstr "30+项贡献"
msgid "403|Please contact your GitLab administrator to get permission."
msgstr "请è”系您的 GitLab 管ç†å‘˜èŽ·å–访问æƒé™ã€‚"
@@ -354,7 +436,7 @@ msgid "404|Please contact your GitLab administrator if you think this is a mista
msgstr "如果您觉得这是一个错误的æ示信æ¯ï¼Œè¯·è”系您的 GitLab 管ç†å‘˜ã€‚"
msgid "8 hours"
-msgstr ""
+msgstr "8å°æ—¶"
msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
msgstr "<code>“johnsmith@example.comâ€ï¼šâ€œ@ johnsmithâ€</code> 将会把“By <a href=\"#\">@johnsmith</a>â€æ·»åŠ åˆ°åŽŸæœ¬ç”±johnsmith@example.com创建的所有议题和评论中,并将 <a href=\"#\">@johnsmith</a> 设为原本分é…ç»™johnsmith@example.com所有问题的å—让人。"
@@ -368,6 +450,9 @@ msgstr "<code>“johnsmith@example.comâ€ï¼šâ€œ@ johnsmithâ€</code> 将会把\"
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr "<code>“johnsmith@example.comâ€ï¼šâ€œ@ johnsmithâ€</code> 将会把“By <a href=\"#\">@johnsmith</a>â€æ·»åŠ åˆ°åŽŸæœ¬ç”±johnsmith@example.com创建的所有议题和评论中。 为ä¿æŠ¤ç”¨æˆ·çš„éšç§ï¼Œç”µå­é‚®ä»¶åœ°å€æˆ–用户å默认将被å±è”½ã€‚如需显示完整邮件地å€ï¼Œå¯ä½¿ç”¨æ­¤é€‰é¡¹ã€‚"
+msgid "<no name set>"
+msgstr "<未设置å称>"
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr "<strong>%{changedFilesLength} 未暂存</strong> å’Œ <strong>%{stagedFilesLength} 已暂存</strong> å˜æ›´å†…容"
@@ -404,26 +489,26 @@ msgstr "一个Hugo站点,它使用NetLifyæ¥ä»£æ›¿Gitlabçš„CI/CD,但ä»ç„¶å…
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr "一个Jekyll站点,它使用NetLifyæ¥ä»£æ›¿Gitlabçš„CI/CD,但ä»ç„¶å…·æœ‰æ‰€æœ‰å…¶ä»–主è¦çš„Gitlab功能。"
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
+msgstr "将使用您的电å­é‚®ä»¶åœ°å€ä¸ºæ­¤GitLab安装并é…ç½®Let's Encryptå¸æˆ·ã€‚您将收到è¯ä¹¦å³å°†åˆ°æœŸçš„警告电å­é‚®ä»¶ã€‚"
+
msgid "A default branch cannot be chosen for an empty project."
msgstr "无法为空项目选择默认分支。"
msgid "A deleted user"
msgstr "已删除的用户"
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr "GitLab滥用审查团队将会尽快查看您的报告。"
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
+msgstr "派生是项目的副本。<br />仓库的派生å…许您在ä¸å½±å“原始项目的情况下进行更改。"
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
-msgstr ""
-
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr "将在派生(fork)项目中中创建一个新的分支, 并开å¯ä¸€ä¸ªæ–°çš„åˆå¹¶è¯·æ±‚。"
msgid "A new impersonation token has been created."
-msgstr ""
+msgstr "已创建新的身份模拟令牌。"
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr "一个纯HTML站点,它使用NetLifyæ¥ä»£æ›¿Gitlabçš„CI/CD,但ä»ç„¶å…·æœ‰æ‰€æœ‰å…¶ä»–主è¦çš„Gitlab功能。"
@@ -438,13 +523,16 @@ msgid "A ready-to-go template for use with iOS Swift apps."
msgstr "适用于iOS Swift应用的éšæ—¶å¯ç”¨çš„模æ¿ã€‚"
msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
-msgstr "用于在作业跟踪中查找匹é…测试覆盖率输出的正则表达å¼ã€‚留空则ç¦ç”¨"
+msgstr "用于在作业日志中查找匹é…测试覆盖率输出的正则表达å¼ã€‚留空则ç¦ç”¨"
msgid "A user with write access to the source branch selected this option"
msgstr "具有对æºåˆ†æ”¯çš„写入æƒé™çš„用户选择了此选项"
msgid "API Help"
-msgstr ""
+msgstr "API帮助"
+
+msgid "API Token"
+msgstr "API令牌"
msgid "About GitLab"
msgstr "关于 GitLab"
@@ -477,31 +565,43 @@ msgid "Access Tokens"
msgstr "访问令牌"
msgid "Access denied for your LDAP account."
-msgstr ""
+msgstr "无法使用您的LDAPå¸æˆ·è¿›è¡Œç™»å½•ã€‚"
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "æ‹’ç»è®¿é—®ï¼è¯·æ ¸æŸ¥æ‚¨æ˜¯å¦æœ‰æƒé™å°†éƒ¨ç½²å¯†é’¥æ·»åŠ åˆ°æ­¤ä»“库。"
msgid "Access expiration date"
-msgstr "访问到期日期"
+msgstr "访问过期时间"
msgid "Access forbidden. Check your access level."
-msgstr ""
+msgstr "访问被ç¦æ­¢ã€‚检查您的访问æƒé™ã€‚"
msgid "Access to '%{classification_label}' not allowed"
msgstr "ä¸å…许访问%{classification_label}"
+msgid "AccessDropdown|Groups"
+msgstr "群组"
+
+msgid "AccessDropdown|Roles"
+msgstr "角色"
+
+msgid "AccessDropdown|Users"
+msgstr "用户"
+
msgid "Account"
msgstr "å¸å·"
msgid "Account and limit"
msgstr "å¸æˆ·å’Œé™åˆ¶"
+msgid "Account: %{account}"
+msgstr "å¸æˆ·ï¼š%{account}"
+
msgid "Action to take when receiving an alert."
msgstr "接收警报时è¦æ‰§è¡Œçš„æ“作。"
msgid "Activate Service Desk"
-msgstr ""
+msgstr "å¯ç”¨æœåŠ¡å°"
msgid "Active"
msgstr "å¯ç”¨"
@@ -533,6 +633,9 @@ msgstr "添加 Kubernetes 集群"
msgid "Add README"
msgstr "添加自述文件"
+msgid "Add a GPG key"
+msgstr "添加GPG密钥"
+
msgid "Add a bullet list"
msgstr "添加一个符å·åˆ—表"
@@ -554,11 +657,17 @@ msgstr "添加表格"
msgid "Add a task list"
msgstr "添加任务列表"
+msgid "Add a todo"
+msgstr "添加一个待办事项"
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "添加包å«åœ¨æ‰€æœ‰ç”µå­é‚®ä»¶ä¸­çš„附加文本。 长度ä¸è¶…过%{character_limit} 字符"
-msgid "Add approver(s)"
-msgstr "添加核准人"
+msgid "Add an SSH key"
+msgstr "添加SSH密钥"
+
+msgid "Add an issue"
+msgstr ""
msgid "Add approvers"
msgstr "添加核准人"
@@ -566,9 +675,15 @@ msgstr "添加核准人"
msgid "Add bold text"
msgstr "添加粗体文本"
+msgid "Add child epic to an epic"
+msgstr "添加å­å²è¯—到å²è¯—"
+
msgid "Add comment now"
msgstr "ç«‹å³æ·»åŠ è¯„论"
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "添加页眉和页脚到电å­é‚®ä»¶ã€‚请注æ„,颜色设置仅适用于应用程åºç•Œé¢"
@@ -578,11 +693,14 @@ msgstr "添加图片评论"
msgid "Add italic text"
msgstr "添加斜体文本"
+msgid "Add label(s)"
+msgstr "添加标记"
+
msgid "Add license"
msgstr "添加许å¯è¯"
msgid "Add list"
-msgstr ""
+msgstr "添加列表"
msgid "Add new application"
msgstr "新建应用"
@@ -590,9 +708,18 @@ msgstr "新建应用"
msgid "Add new directory"
msgstr "添加目录"
+msgid "Add or subtract spent time"
+msgstr "增加或å‡å°‘耗时"
+
msgid "Add reaction"
msgstr "添加回应"
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr "添加到项目"
@@ -605,23 +732,35 @@ msgstr "添加待办事项"
msgid "Add user(s) to the group:"
msgstr "å‘群组添加用户"
-msgid "Add users or groups who are allowed to approve every merge request"
-msgstr "添加å…许批准æ¯ä¸ªåˆå¹¶è¯·æ±‚的用户或群组"
-
msgid "Add users to group"
msgstr "将用户加入群组"
+msgid "AddMember|No users specified."
+msgstr "未指定用户。"
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
+msgstr "已指定太多用户(é™åˆ¶ä¸º %{user_limit})"
+
msgid "Added at"
-msgstr "添加于"
+msgstr "添加时间"
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr "当å‰GitLab实例ç¦æ­¢æ·»åŠ æ–°åº”用程åºã€‚请è”系您的GitLab管ç†å‘˜ä»¥èŽ·å¾—相关æƒé™ã€‚"
+msgid "Additional minutes"
+msgstr "é¢å¤–的分钟数"
+
msgid "Additional text"
msgstr "附加文本"
-msgid "Aditional minutes"
-msgstr ""
+msgid "Adds"
+msgstr "添加"
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr "添加%{epic_ref}作为å­å²è¯—。"
+
+msgid "Adds a todo."
+msgstr "添加一个待办事项."
msgid "Admin Area"
msgstr "管ç†ä¸­å¿ƒ"
@@ -630,7 +769,10 @@ msgid "Admin Overview"
msgstr "管ç†æ¦‚览"
msgid "Admin Section"
-msgstr ""
+msgstr "管ç†éƒ¨åˆ†"
+
+msgid "Admin notes"
+msgstr "管ç†å‘˜å¤‡æ³¨"
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr "您å³å°†æ°¸ä¹…删除用户 %{username}。该用户的议题ã€åˆå¹¶è¯·æ±‚以åŠé“¾æŽ¥åˆ°è¯¥ç”¨æˆ·çš„群组将被转移到系统的“Ghost用户â€ã€‚为é¿å…æ•°æ®ä¸¢å¤±ï¼Œå»ºè®®æ‚¨ä½¿ç”¨ %{strong_start}ç¦ç”¨ç”¨æˆ·%{strong_end} 功能。一旦您 %{strong_start}删除用户%{strong_end},将无法撤消或æ¢å¤ã€‚"
@@ -653,8 +795,11 @@ msgstr "åœæ­¢ä½œä¸šå¤±è´¥"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "您å³å°†åœæ­¢æ‰€æœ‰ä½œä¸šã€‚这会中断并结æŸæ‰€æœ‰æ­£åœ¨è¿è¡Œçš„作业。"
+msgid "AdminNote|Note"
+msgstr " 备注"
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
-msgstr "您å³å°†æ°¸ä¹…删除项目 %{projectName},其存储库以åŠæ‰€æœ‰ç›¸å…³èµ„æºï¼ŒåŒ…括问题ã€åˆå¹¶è¯·æ±‚等。一旦确认并点击 %{strong_start}删除项目%{strong_end},将无法撤消或æ¢å¤ã€‚"
+msgstr "您å³å°†æ°¸ä¹…删除项目 %{projectName},其仓库以åŠæ‰€æœ‰ç›¸å…³èµ„æºï¼ŒåŒ…括问题ã€åˆå¹¶è¯·æ±‚等。一旦确认并点击 %{strong_start}删除项目%{strong_end},将无法撤消或æ¢å¤ã€‚"
msgid "AdminProjects|Delete"
msgstr "删除"
@@ -669,7 +814,7 @@ msgid "AdminSettings|Auto DevOps domain"
msgstr "Auto DevOps 域"
msgid "AdminSettings|Enable shared runners for new projects"
-msgstr "为新项目å¯ç”¨å…±äº«è¿è¡Œå™¨"
+msgstr "为新项目å¯ç”¨å…±äº«Runner"
msgid "AdminSettings|Environment variables are protected by default"
msgstr "环境å˜é‡é»˜è®¤å—ä¿æŠ¤"
@@ -681,10 +826,10 @@ msgid "AdminSettings|When creating a new environment variable it will be protect
msgstr "创建一个新的环境å˜é‡æ—¶ï¼Œå®ƒä¼šè¢«é»˜è®¤ä¿æŠ¤ã€‚"
msgid "AdminUsers|2FA Disabled"
-msgstr "ç¦ç”¨åŒå› å­éªŒè¯"
+msgstr "åŒé‡è®¤è¯å…³é—­"
msgid "AdminUsers|2FA Enabled"
-msgstr "å¯ç”¨åŒå› å­éªŒè¯"
+msgstr "å¯ç”¨åŒé‡è®¤è¯"
msgid "AdminUsers|Active"
msgstr "活跃"
@@ -699,10 +844,10 @@ msgid "AdminUsers|Block user"
msgstr "ç¦ç”¨ç”¨æˆ·"
msgid "AdminUsers|Blocked"
-msgstr "å·²å±è”½"
+msgstr "å·²ç¦ç”¨"
msgid "AdminUsers|Cannot unblock LDAP blocked users"
-msgstr "无法解除已å±è”½çš„ LDAP 用户"
+msgstr "无法解除已ç¦ç”¨çš„LDAP用户"
msgid "AdminUsers|Delete User %{username} and contributions?"
msgstr "删除用户 %{username} 以åŠç›¸å…³è´¡çŒ®å—?"
@@ -747,19 +892,19 @@ msgid "AdminUsers|To confirm, type %{username}"
msgstr "请输入 %{username} æ¥ç¡®è®¤"
msgid "AdminUsers|User will be blocked"
-msgstr "用户将被å±è”½"
+msgstr "用户将被ç¦ç”¨"
msgid "AdminUsers|Without projects"
-msgstr "没有项目"
+msgstr "无项目"
msgid "Advanced"
msgstr "高级"
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
-msgstr "高级æƒé™ï¼Œå¤§æ–‡ä»¶å­˜å‚¨å’ŒåŒé‡è®¤è¯è®¾ç½®ã€‚"
+msgstr "高级æƒé™ï¼Œå¤§æ–‡ä»¶å­˜å‚¨(LFS)å’ŒåŒé‡è®¤è¯è®¾ç½®ã€‚"
msgid "Advanced search functionality"
-msgstr ""
+msgstr "高级æœç´¢åŠŸèƒ½"
msgid "Advanced settings"
msgstr "高级设置"
@@ -767,6 +912,9 @@ msgstr "高级设置"
msgid "After a successful password update you will be redirected to login screen."
msgstr "密ç æ›´æ–°æˆåŠŸåŽï¼Œæ‚¨å°†è¢«é‡å®šå‘到登录页é¢ã€‚"
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr "密ç æ›´æ–°æˆåŠŸåŽï¼Œæ‚¨å°†è¢«é‡å®šå‘到登录页é¢ï¼Œæ‚¨å¯ä»¥ä½¿ç”¨æ–°å¯†ç é‡æ–°ç™»å½•ã€‚"
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "警报"
@@ -783,23 +931,32 @@ msgstr "所有æˆå‘˜"
msgid "All changes are committed"
msgstr "所有更改å‡å·²æ交"
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "从模æ¿æˆ–导入时为空白项目将å¯ç”¨æ‰€æœ‰åŠŸèƒ½ï¼Œä½†å¯ä»¥åœ¨é¡¹ç›®è®¾ç½®ä¸­å°†å…¶ç¦ç”¨ã€‚"
+msgid "All groups and projects"
+msgstr "所有群组和项目"
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr "这个里程碑的所有议题都已关闭。现在您å¯ä»¥å…³é—­è¿™ä¸ªé‡Œç¨‹ç¢‘。"
msgid "All merge conflicts were resolved. The merge request can now be merged."
-msgstr ""
+msgstr "所有åˆå¹¶å†²çªéƒ½å·²è§£å†³ã€‚æ­¤åˆå¹¶è¯·æ±‚现在å¯ä»¥åˆå¹¶ã€‚"
+
+msgid "All projects"
+msgstr "所有项目"
msgid "All todos were marked as done."
-msgstr ""
+msgstr "所有待办事项都标记为已完æˆã€‚"
msgid "All users"
msgstr "所有用户"
msgid "All users must have a name."
-msgstr ""
+msgstr "所有的用户都必须具有å称。"
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "å…许“%{group_name}â€ä»¥æ‚¨çš„身份登录"
@@ -820,7 +977,7 @@ msgid "Allow projects within this group to use Git LFS"
msgstr "å…许该群组中的项目使用Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
-msgstr "å…许所有人访问æµæ°´çº¿å’Œä½œä¸šè¯¦æƒ…,包括输出日志和工件"
+msgstr "å…许所有人访问æµæ°´çº¿å’Œä½œä¸šè¯¦æƒ…,包括输出日志和产物"
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
msgstr "å…许在Asciidoc文档中渲染PlantUML图。"
@@ -829,7 +986,7 @@ msgid "Allow requests to the local network from hooks and services."
msgstr "å…许æ¥è‡ªé’©å­å’ŒæœåŠ¡çš„对本地网络的请求。"
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
-msgstr "åŒæ—¶å…许此秘钥推é€æ–‡ä»¶åˆ°å­˜å‚¨åº“å—?(默认åªæ‹¥æœ‰æ‹‰å–æƒé™)"
+msgstr "åŒæ—¶å…许此秘钥推é€æ–‡ä»¶åˆ°ä»“库å—?(默认åªæ‹¥æœ‰æ‹‰å–æƒé™)"
msgid "Allow users to register any application to use GitLab as an OAuth provider"
msgstr "å…许用户注册任何应用程åºï¼Œä½¿ç”¨ GitLab 作为 OAuth æ供者"
@@ -864,9 +1021,6 @@ msgstr "此外,也å¯ä»¥ä½¿ç”¨ %{personal_access_token_link}。创建Personal
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr "å…许用户跳过强制é…ç½®åŒé‡è®¤è¯çš„时间(以å°æ—¶ä¸ºå•ä½ï¼‰"
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr "在æ交表å•æ—¶å°†è‡ªåŠ¨ç”Ÿæˆ SSH 密钥。有关详细信æ¯, 请å‚阅文档。"
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr "应用%{link_to_client}请求访问您的 GitLab å¸æˆ·ã€‚"
@@ -900,12 +1054,15 @@ msgstr "预览 blob 时出错"
msgid "An error occurred when toggling the notification subscription"
msgstr "切æ¢é€šçŸ¥è®¢é˜…æ—¶å‘生错误"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr "å°è¯•è§£å†³è¯„论时出错。请å†è¯•ä¸€æ¬¡ã€‚"
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr "å°è¯•è§£å†³è®¨è®ºæ—¶å‡ºé”™ã€‚请å†è¯•ä¸€æ¬¡ã€‚"
+
msgid "An error occurred when updating the issue weight"
msgstr "更新议题æƒé‡æ—¶å‘生错误"
-msgid "An error occurred while adding approver"
-msgstr "添加审批者时出错"
-
msgid "An error occurred while deleting the approvers group"
msgstr "删除核准人群组时å‘生错误"
@@ -916,7 +1073,7 @@ msgid "An error occurred while detecting host keys"
msgstr "检测主机密钥时å‘生错误"
msgid "An error occurred while disabling Service Desk."
-msgstr ""
+msgstr "ç¦ç”¨æœåŠ¡å°æ—¶å‘生错误。"
msgid "An error occurred while dismissing the alert. Refresh the page and try again."
msgstr "消除警告时å‘生错误。请刷新页é¢å¹¶å†æ¬¡å°è¯•ã€‚"
@@ -925,7 +1082,16 @@ msgid "An error occurred while dismissing the feature highlight. Refresh the pag
msgstr "关闭功能çªå‡ºæ˜¾ç¤ºæ—¶å‘生错误。请刷新页é¢å¹¶å†æ¬¡å°è¯•ã€‚"
msgid "An error occurred while enabling Service Desk."
-msgstr ""
+msgstr "å¯ç”¨æœåŠ¡å°æ—¶å‘生错误。"
+
+msgid "An error occurred while fetching environments."
+msgstr "获å–环境时出错。"
+
+msgid "An error occurred while fetching folder content."
+msgstr "获å–文件夹内容时å‘生错误."
+
+msgid "An error occurred while fetching label colors."
+msgstr "获å–标记颜色时出错。"
msgid "An error occurred while fetching markdown preview"
msgstr "èŽ·å– markdown 预览时出错"
@@ -933,14 +1099,20 @@ msgstr "èŽ·å– markdown 预览时出错"
msgid "An error occurred while fetching pending comments"
msgstr "获å–待处ç†è¯„论时å‘生错误"
+msgid "An error occurred while fetching projects autocomplete."
+msgstr "获å–项目自动完æˆæ—¶å‡ºé”™ã€‚"
+
msgid "An error occurred while fetching sidebar data"
msgstr "获å–侧边æ æ•°æ®æ—¶å‘生错误"
-msgid "An error occurred while fetching stages."
-msgstr "获å–阶段时å‘生错误"
-
msgid "An error occurred while fetching the Service Desk address."
-msgstr ""
+msgstr "获å–æœåŠ¡å°åœ°å€æ—¶å‘生错误。"
+
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr "读å–看æ¿åˆ—表时出错。请å†è¯•ä¸€æ¬¡ã€‚"
+
+msgid "An error occurred while fetching the builds."
+msgstr "获å–该构建时å‘生了一个错误。"
msgid "An error occurred while fetching the job log."
msgstr "获å–作业日志时å‘生错误。"
@@ -957,6 +1129,9 @@ msgstr "获å–æµæ°´çº¿æ—¶å‘生错误"
msgid "An error occurred while fetching the releases. Please try again."
msgstr "获å–版本时å‘生错误。请é‡è¯•ã€‚"
+msgid "An error occurred while fetching this tab."
+msgstr "获å–æ­¤é¢æ¿æ—¶å‘生了一个错误。"
+
msgid "An error occurred while getting projects"
msgstr "获å–项目时å‘生错误"
@@ -990,11 +1165,14 @@ msgstr "加载订阅信æ¯æ—¶å‘生错误。"
msgid "An error occurred while making the request."
msgstr "å‘é€è¯·æ±‚æ—¶å‘生错误。"
-msgid "An error occurred while removing approver"
-msgstr "删除批准者时å‘生错误"
+msgid "An error occurred while moving the issue."
+msgstr "移动议题时出错。"
+
+msgid "An error occurred while parsing recent searches"
+msgstr "解æžæœ€è¿‘æœç´¢æ—¶å‘生错误"
msgid "An error occurred while removing epics."
-msgstr "删除 epic æ—¶å‘生错误。"
+msgstr "删除å²è¯—æ—¶å‘生错误。"
msgid "An error occurred while removing issues."
msgstr "删除议题时å‘生错误。"
@@ -1039,11 +1217,14 @@ msgid "An error occurred whilst committing your changes."
msgstr "æ交更改时å‘生错误。"
msgid "An error occurred whilst fetching the job trace."
-msgstr "获å–作业跟踪时å‘生错误。"
+msgstr "获å–作业日志时å‘生错误。"
msgid "An error occurred whilst fetching the latest pipeline."
msgstr "获å–最新æµæ°´çº¿æ—¶å‘生错误。"
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr "获å–文件 - %{branchId} 时出错"
+
msgid "An error occurred whilst loading all the files."
msgstr "加载所有文件时å‘生错误。"
@@ -1072,7 +1253,7 @@ msgid "An unexpected error occurred while checking the project environment."
msgstr "检查项目环境时å‘生æ„外错误。"
msgid "An unexpected error occurred while checking the project runners."
-msgstr "检查项目è¿è¡Œå™¨æ—¶å‘生æ„外错误。"
+msgstr "检查项目Runneræ—¶å‘生æ„外错误。"
msgid "An unexpected error occurred while communicating with the Web Terminal."
msgstr "与Web终端通信时å‘生æ„外错误。"
@@ -1101,17 +1282,29 @@ msgstr "任何"
msgid "Any Label"
msgstr "任何标记"
+msgid "Any Milestone"
+msgstr "任何里程碑"
+
msgid "Any encrypted tokens"
-msgstr ""
+msgstr "任何加密的令牌"
+
+msgid "Any namespace"
+msgstr "任何命å空间"
msgid "Appearance"
msgstr "外观"
msgid "Appearance was successfully created."
-msgstr ""
+msgstr "å·²æˆåŠŸåˆ›å»ºå¤–观。"
msgid "Appearance was successfully updated."
-msgstr ""
+msgstr "外观更新æˆåŠŸã€‚"
+
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr "追加 %{TABLEFLIP} 到评论"
+
+msgid "Append the comment with %{shrug}"
+msgstr "追加 %{shrug} 到评论"
msgid "Application"
msgstr "应用"
@@ -1120,13 +1313,16 @@ msgid "Application ID"
msgstr "应用程åºID"
msgid "Application settings saved successfully"
-msgstr ""
+msgstr "应用程åºè®¾ç½®ä¿å­˜æˆåŠŸ"
+
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr "应用已å¸è½½ä½†æœªèƒ½æ¸…除: %{error_message}"
msgid "Application was successfully destroyed."
-msgstr ""
+msgstr "应用程åºå·²æˆåŠŸåˆ é™¤ã€‚"
msgid "Application was successfully updated."
-msgstr ""
+msgstr "应用程åºå·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Application: %{name}"
msgstr "应用:%{name}"
@@ -1140,6 +1336,18 @@ msgstr "已应用"
msgid "Apply suggestion"
msgstr "应用建议"
+msgid "Applying command"
+msgstr "正在执行命令"
+
+msgid "Applying command to %{commandDescription}"
+msgstr "正在执行命令以 %{commandDescription}"
+
+msgid "Applying multiple commands"
+msgstr "正在执行多个命令"
+
+msgid "Applying suggestion"
+msgstr "正在应用建议"
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] "%d æˆå‘˜"
@@ -1177,12 +1385,6 @@ msgstr "例如质é‡ä¿è¯ã€å®‰å…¨ç­‰ç­‰ã€‚"
msgid "Approvals"
msgstr "核准"
-msgid "Approvals required"
-msgstr "需è¦æ ¸å‡†"
-
-msgid "Approvers"
-msgstr "核准人"
-
msgid "Apr"
msgstr "4月"
@@ -1190,10 +1392,10 @@ msgid "April"
msgstr "4月"
msgid "Archive jobs"
-msgstr "存档作业"
+msgstr "归档作业"
msgid "Archive project"
-msgstr ""
+msgstr "归档项目"
msgid "Archived project! Repository and other project resources are read-only"
msgstr "已归档项目ï¼ä»“库和其他项目资æºå‡ä¸ºåªè¯»"
@@ -1202,16 +1404,28 @@ msgid "Archived projects"
msgstr "归档项目"
msgid "Archiving the project will make it entirely read-only. It is hidden from the dashboard and doesn't show up in searches. <strong>The repository cannot be committed to, and no issues, comments or other entities can be created.</strong>"
-msgstr ""
+msgstr "归档项目将使其完全åªè¯»ã€‚它将在ä¸ä¼šæ˜¾ç¤ºåœ¨ä»ªè¡¨æ¿åŠæœç´¢ç»“果中。 <strong>代ç å°†æ— æ³•æ交到仓库,也无法创建任何议题ã€æ³¨é‡Šæˆ–其他对象。</strong>"
msgid "Are you sure"
msgstr "您确定å—"
msgid "Are you sure that you want to archive this project?"
-msgstr ""
+msgstr "确定è¦å½’档此项目å—?"
msgid "Are you sure that you want to unarchive this project?"
-msgstr ""
+msgstr "确定è¦å–消归档此项目å—?"
+
+msgid "Are you sure you want to cancel creating this comment?"
+msgstr "确定è¦å–消创建此评论å—?"
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr "确定è¦å–消编辑此评论å—?"
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
+msgstr "您确定è¦åˆ é™¤æ­¤è®¾å¤‡å—?此æ“作无法撤销。"
+
+msgid "Are you sure you want to delete this list?"
+msgstr "确定è¦åˆ é™¤æ­¤åˆ—表å—?"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "确定è¦åˆ é™¤æ­¤æµæ°´çº¿è®¡åˆ’å—?"
@@ -1226,7 +1440,7 @@ msgid "Are you sure you want to lose your issue information?"
msgstr "您确定è¦ä¸¢å¼ƒè®®é¢˜ä¿¡æ¯å—?"
msgid "Are you sure you want to permanently delete this license?"
-msgstr ""
+msgstr "确定è¦æ°¸ä¹…删除此许å¯è¯ï¼Ÿ"
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr "您确定è¦é‡æ–°ç”Ÿæˆå…¬é’¥å—?在镜åƒå†æ¬¡è¿è¡Œä¹‹å‰ï¼Œæ‚¨å¿…须更新远程æœåŠ¡å™¨ä¸Šçš„公钥。"
@@ -1234,18 +1448,6 @@ msgstr "您确定è¦é‡æ–°ç”Ÿæˆå…¬é’¥å—?在镜åƒå†æ¬¡è¿è¡Œä¹‹å‰ï¼Œæ‚¨å¿…
msgid "Are you sure you want to remove %{group_name}?"
msgstr "确定移除群组 %{group_name} å—?"
-msgid "Are you sure you want to remove approver %{name}"
-msgstr "您确定è¦åˆ é™¤æ ¸å‡†è€… %{name} å—"
-
-msgid "Are you sure you want to remove approver %{name}?"
-msgstr "您确定è¦åˆ é™¤æ ¸å‡†è€… %{name} å—?"
-
-msgid "Are you sure you want to remove group %{name}"
-msgstr "您确定è¦åˆ é™¤ %{name} 群组å—"
-
-msgid "Are you sure you want to remove group %{name}?"
-msgstr "您确定è¦åˆ é™¤ %{name} 群组å—?"
-
msgid "Are you sure you want to remove the attachment?"
msgstr "您确定è¦åˆ é™¤æ­¤é™„件?"
@@ -1256,11 +1458,14 @@ msgid "Are you sure you want to reset registration token?"
msgstr "确定è¦é‡ç½®æ³¨å†Œä»¤ç‰Œå—?"
msgid "Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
-msgstr ""
+msgstr "您确定è¦é‡ç½®SCIM令牌å—?在完æˆæ–°ä»¤ç‰Œæ›´æ–°ä¹‹å‰ï¼ŒSCIMé…置将åœæ­¢å·¥ä½œã€‚"
msgid "Are you sure you want to reset the health check token?"
msgstr "确定è¦é‡ç½®è¿è¡ŒçŠ¶å†µæ£€æŸ¥ä»¤ç‰Œå—?"
+msgid "Are you sure you want to revoke this nickname?"
+msgstr "您确定è¦å–消此昵称?"
+
msgid "Are you sure you want to stop this environment?"
msgstr "是å¦ç¡®å®šç»ˆæ­¢å½“å‰çŽ¯å¢ƒï¼Ÿ"
@@ -1273,12 +1478,36 @@ msgstr "您确定è¦å–消订阅 %{type}:%{link_to_noteable_text}å—?"
msgid "Are you sure?"
msgstr "确定å—?"
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr "您确定è¦æ’¤é”€ä¹ˆï¼Ÿæ‰€æœ‰ä½¿ç”¨è¯¥GPG密钥签åçš„æ交都会被å˜ä¸ºæœªç»éªŒè¯ã€‚"
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr "您确认è¦åˆ é™¤GPG密钥么?删除此GPG密钥ä¸ä¼šå½±å“å·²ç»ç­¾åçš„æ交。"
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr "你确定å—?这将使您的已注册应用和U2F设备失效。"
+
msgid "Artifact ID"
msgstr "作业产物ID"
msgid "Artifacts"
msgstr "产物"
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr "由于仅有部分æµè§ˆå™¨æ”¯æŒU2F设备,我们è¦æ±‚您在使用U2F设备之å‰è®¾ç½®ä¸€ä¸ªåŒé‡è®¤è¯åº”用。这样å³ä½¿æ‚¨ä½¿ç”¨ä¸æ”¯æŒU2Fçš„æµè§ˆå™¨æ‚¨ä¹Ÿå¯ä»¥ç™»å½•ã€‚"
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr "%{user} 推é€åˆ° %{project_name} 的分支%{branch} ( %{commit_url} ): "
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr "Asana - 无需电å­é‚®ä»¶å®žçŽ°å›¢é˜Ÿå作"
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr "以逗å·åˆ†éš”的分支列表。列表中的分支会被自动检查。留空则包括所有分支。"
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr "用户个人访问令牌。用户必须能够访问任务,所有评论都将归于此用户。"
+
msgid "Ascending"
msgstr "å‡åºæŽ’列"
@@ -1291,6 +1520,9 @@ msgstr "断言消费者æœåŠ¡ URL"
msgid "Assets"
msgstr "资æº"
+msgid "Assign"
+msgstr "指派"
+
msgid "Assign custom color like #FF0000"
msgstr "分é…自定义颜色,如FF0000"
@@ -1306,6 +1538,12 @@ msgstr "为此里程碑分é…一些议题。"
msgid "Assign to"
msgstr "分é…到"
+msgid "Assign yourself to these issues"
+msgstr "将这些议题分é…给自己"
+
+msgid "Assign yourself to this issue"
+msgstr "将此议题分é…给自己"
+
msgid "Assigned Issues"
msgstr "已分é…议题"
@@ -1325,16 +1563,23 @@ msgid "Assignee lists show all issues assigned to the selected user."
msgstr "指派列表显示分é…给选定用户的所有议题。"
msgid "Assignee(s)"
-msgstr "指派"
+msgstr "指派人"
msgid "At least one approval from a code owner is required to change files matching the respective CODEOWNER rules."
msgstr "至少需è¦ä¸€ä¸ªä»£ç æ‰€æœ‰è€…批准,以便更改符åˆç›¸åº”çš„ CODEEWNER 规则的文件。"
msgid "Attach a file"
-msgstr "附加文件"
+msgstr "添加附件"
msgid "Attach a file by drag &amp; drop or %{upload_link}"
-msgstr "拖放文件到此处或者 %{upload_link}"
+msgstr "拖放文件到此处或者%{upload_link}作为附件"
+
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] "添加%d个附件"
+
+msgid "Attaching the file failed."
+msgstr "添加附件失败。"
msgid "Audit Events"
msgstr "审计事件"
@@ -1349,7 +1594,7 @@ msgid "Authentication Log"
msgstr "认è¯æ—¥å¿—"
msgid "Authentication failed: %{error_message}"
-msgstr ""
+msgstr "身份验è¯å¤±è´¥ï¼š %{error_message}"
msgid "Authentication log"
msgstr "认è¯æ—¥å¿—"
@@ -1358,10 +1603,10 @@ msgid "Authentication method"
msgstr "验è¯æ–¹å¼"
msgid "Authentication method updated"
-msgstr ""
+msgstr "身份验è¯æ–¹æ³•å·²æ›´æ–°"
msgid "Authentication via U2F device failed."
-msgstr ""
+msgstr "通过U2F设备进行身份验è¯å¤±è´¥ã€‚"
msgid "Author"
msgstr "作者"
@@ -1382,7 +1627,7 @@ msgid "Authorize %{link_to_client} to use your account?"
msgstr "æŽˆæƒ %{link_to_client} 使用您的å¸æˆ·ï¼Ÿ"
msgid "Authorized %{new_chat_name}"
-msgstr ""
+msgstr "已授æƒç»™ %{new_chat_name}"
msgid "Authorized At"
msgstr "授æƒäºŽ"
@@ -1423,15 +1668,24 @@ msgstr "想了解更多请访问 %{link_to_documentation}"
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr "Auto DevOpsæµæ°´çº¿å·²å¯ç”¨ã€‚如果未找到CIé…置文件,将使用该æµæ°´çº¿ã€‚ %{more_information_link}"
-msgid "Automatically marked as default internal user"
-msgstr "自动标记为默认内部用户"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically marked as default internal user"
+msgstr "自动标记为默认内部用户"
+
msgid "Automatically resolved"
msgstr "自动解决"
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr "æ¯å°æ—¶è‡ªåŠ¨ä»Žä¸Šæ¸¸ä»“库更新此项目的分支和标记。"
+
+msgid "Autosave|Note"
+msgstr "注æ„"
+
msgid "Available"
msgstr "å¯ç”¨çš„"
@@ -1439,10 +1693,10 @@ msgid "Available group Runners: %{runners}"
msgstr "å¯ç”¨çš„群组 Runner: %{runners}"
msgid "Available shared Runners:"
-msgstr "å¯ç”¨çš„共享è¿è¡Œå™¨ï¼š"
+msgstr "å¯ç”¨çš„共享Runner:"
msgid "Available specific runners"
-msgstr "å¯ç”¨çš„特定è¿è¡Œå™¨"
+msgstr "å¯ç”¨çš„指定Runner"
msgid "Avatar for %{assigneeName}"
msgstr "%{assigneeName} 头åƒ"
@@ -1543,6 +1797,30 @@ msgstr "您的徽章"
msgid "Badges|e.g. %{exampleUrl}"
msgstr "例如 %{exampleUrl}"
+msgid "Badge|New"
+msgstr "新建"
+
+msgid "Balsamiq file could not be loaded."
+msgstr "无法加载 balsamiq 文件。"
+
+msgid "BambooService|A continuous integration and build server"
+msgstr "一个æŒç»­é›†æˆå’Œæž„建æœåŠ¡å™¨"
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr "具有API访问æƒé™çš„用户,如果适用。"
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr "Atlassian Bamboo CI"
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr "Bamboo构建计划密钥,如KEY"
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr "Bamboo 根地å€ï¼Œä¾‹å¦‚:https://bambo.example.com"
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr "您必须在Bamboo中设置自动版本标签和仓库触å‘器。"
+
msgid "BatchComments|Delete all pending comments"
msgstr "删除所有待处ç†çš„评论"
@@ -1553,10 +1831,10 @@ msgid "BatchComments|You're about to discard your review which will delete all o
msgstr "您å³å°†æ”¾å¼ƒæ‚¨çš„评审,该æ“作将删除所有待处ç†çš„评论。请注æ„已删除评论 %{strong_start}ä¸èƒ½%{strong_end} æ¢å¤ã€‚"
msgid "Be careful. Changing the project's namespace can have unintended side effects."
-msgstr ""
+msgstr "请注æ„,更改项目的命å空间å¯èƒ½ä¼šäº§ç”Ÿéžé¢„期的副作用。"
msgid "Be careful. Renaming a project's repository can have unintended side effects."
-msgstr ""
+msgstr "å°å¿ƒã€‚é‡å‘½å项目的仓库å¯èƒ½ä¼šäº§ç”Ÿæ„想ä¸åˆ°çš„副作用。"
msgid "Begin with the selected commit"
msgstr "从选定的æ交开始"
@@ -1643,14 +1921,31 @@ msgid "Block"
msgstr "å±è”½"
msgid "Blocked"
-msgstr "å·²å±è”½"
+msgstr "å·²ç¦ç”¨"
+
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
msgid "Blog"
msgstr "åšå®¢"
+msgid "Blue helpers indicate an action to be taken."
+msgstr "è“色助手表示需è¦é‡‡å–的行动。"
+
msgid "Boards"
msgstr "看æ¿"
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "未在此项目的仓库中找到 %{branchName} 分支。"
@@ -1666,6 +1961,9 @@ msgstr "分支已被采用"
msgid "Branch name"
msgstr "分支å称"
+msgid "Branch not loaded - %{branchId}"
+msgstr "分支未载入 - %{branchId}"
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "æœç´¢åˆ†æ”¯"
@@ -1796,10 +2094,10 @@ msgid "Branches|protected"
msgstr "å—ä¿æŠ¤"
msgid "Broadcast Message was successfully created."
-msgstr ""
+msgstr "广播消æ¯å·²æˆåŠŸåˆ›å»ºã€‚"
msgid "Broadcast Message was successfully updated."
-msgstr ""
+msgstr "广播消æ¯å·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Browse Directory"
msgstr "æµè§ˆç›®å½•"
@@ -1816,6 +2114,21 @@ msgstr "æµè§ˆæ–‡ä»¶"
msgid "Built-in"
msgstr "内置"
+msgid "BurndownChartLabel|Guideline"
+msgstr "指å—"
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr "未解决议题æƒé‡"
+
+msgid "BurndownChartLabel|Open issues"
+msgstr "未解决议题"
+
+msgid "BurndownChartLabel|Progress"
+msgstr "进度"
+
+msgid "BurndownChartLabel|Remaining"
+msgstr "剩余"
+
msgid "Business"
msgstr "商业"
@@ -1823,10 +2136,10 @@ msgid "Business metrics (Custom)"
msgstr "业务指标(自定义)"
msgid "Buy EE"
-msgstr ""
+msgstr "è´­ä¹°ä¼ä¸šç‰ˆ"
msgid "Buy GitLab Enterprise Edition"
-msgstr ""
+msgstr "è´­ä¹°GitLabä¼ä¸šç‰ˆ"
msgid "By %{user_name}"
msgstr "ç”± %{user_name}"
@@ -1834,6 +2147,9 @@ msgstr "ç”± %{user_name}"
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr "默认情况下,GitLab 以 HTML 和纯文本格å¼å‘é€ç”µå­é‚®ä»¶ï¼Œå› æ­¤é‚®ä»¶å®¢æˆ·ç«¯å¯ä»¥é€‰æ‹©ä½¿ç”¨å“ªç§æ ¼å¼ã€‚如果您åªæƒ³ä»¥çº¯æ–‡æœ¬æ ¼å¼å‘é€ç”µå­é‚®ä»¶ï¼Œè¯·ç¦ç”¨æ­¤é€‰é¡¹ã€‚"
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr "默认情况下,所有项目和群组将使用全局通知设置。"
+
msgid "ByAuthor|by"
msgstr "作者:"
@@ -1853,7 +2169,7 @@ msgid "CI Lint"
msgstr "CI Lint"
msgid "CI variables"
-msgstr ""
+msgstr "CI å˜é‡"
msgid "CI will run using the credentials assigned above."
msgstr "CI将使用上é¢æŒ‡å®šçš„凭æ®è¿è¡Œã€‚"
@@ -1889,7 +2205,7 @@ msgid "CICD|Default to Auto DevOps pipeline"
msgstr "默认为Auto DevOpsæµæ°´çº¿"
msgid "CICD|Default to Auto DevOps pipeline for all projects"
-msgstr "所有项目默认的 Auto DevOps æµæ°´çº¿"
+msgstr "所有项目默认使用Auto DevOpsæµæ°´çº¿"
msgid "CICD|Deployment strategy"
msgstr "部署策略"
@@ -1924,9 +2240,15 @@ msgstr "å¯ä»¥è¦†ç›–æ¯ä¸ªåˆå¹¶è¯·æ±‚所需的核准人和核准信æ¯"
msgid "Can't find HEAD commit for this branch"
msgstr "无法找到此分支的 HEAD æ交"
+msgid "Can't find variable: ZiteReader"
+msgstr "找ä¸åˆ°å˜é‡: ZiteReader"
+
msgid "Can't remove group members without group managed account"
msgstr "当群组没有管ç†å‘˜æ—¶, 无法删除群组æˆå‘˜"
+msgid "Can't scan the code?"
+msgstr "无法扫æ二维ç ï¼Ÿ"
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr "金ä¸é›€éƒ¨ç½²æ˜¯ä¸€é¡¹æµè¡Œçš„CI策略,其中一å°éƒ¨åˆ†èŠ‚点更新到您的新版本应用。"
@@ -1940,19 +2262,25 @@ msgid "Cannot be merged automatically"
msgstr "无法自动åˆå¹¶"
msgid "Cannot create the abuse report. The user has been deleted."
-msgstr ""
+msgstr "无法创建滥用报告。用户已被删除。"
msgid "Cannot create the abuse report. This user has been blocked."
-msgstr ""
+msgstr "无法创建滥用报告。此用户已被ç¦ç”¨ã€‚"
msgid "Cannot modify managed Kubernetes cluster"
msgstr "无法修改托管的 Kubernetes 集群"
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr "无法通过内部ID引用群组里程碑ï¼"
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr "无法渲染镜åƒã€‚已超出最大字符数(%{charLimit})。"
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr "无法显示预览。如需预览,è‰å›¾æ–‡ä»¶å¿…须具有Sketch 43åŠä»¥ä¸Šç‰ˆæœ¬çš„文件格å¼ã€‚"
+
msgid "Cannot skip two factor authentication setup"
-msgstr ""
+msgstr "无法跳过åŒé‡è®¤è¯è®¾ç½®"
msgid "Capacity threshold"
msgstr "容é‡é˜ˆå€¼"
@@ -1966,8 +2294,14 @@ msgstr "è¯ä¹¦(PEM)"
msgid "Change Weight"
msgstr "更改æƒé‡"
+msgid "Change assignee(s)"
+msgstr "更改指派人"
+
+msgid "Change assignee(s)."
+msgstr "更改指派人。"
+
msgid "Change path"
-msgstr ""
+msgstr "更改路径"
msgid "Change permissions"
msgstr "更改æƒé™"
@@ -1978,6 +2312,15 @@ msgstr "更改模æ¿"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "更改此值以影å“GitLab UI拉å–更新的频率。"
+msgid "Change title"
+msgstr "更改标题"
+
+msgid "Change your password"
+msgstr "更改您的密ç "
+
+msgid "Change your password or recover your current one"
+msgstr "更改您的密ç æˆ–æ¢å¤å½“å‰å¯†ç "
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "选择分支"
@@ -2002,6 +2345,12 @@ msgstr "差异显示方å¼ä¾<b>æº</b>版本åˆå¹¶åˆ°<b>目标</b>版本的形å
msgid "Changes suppressed. Click to show."
msgstr "仅显示部分。点此显示全部。"
+msgid "Changes the title to \"%{title_param}\"."
+msgstr "将标题更改为“%{title_param}â€ã€‚"
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr "在索引 %{link_start}é‡æ–°åˆ›å»º%{link_end} 之å‰ï¼Œæ›´æ”¹å°†ä¸ä¼šå‘生。"
+
msgid "Charts"
msgstr "统计图"
@@ -2029,6 +2378,9 @@ msgstr "检查批准状æ€"
msgid "Checking branch availability..."
msgstr "正在检查分支的å¯ç”¨æ€§..."
+msgid "Checking username availability..."
+msgstr "检查用户å是å¦å¯ç”¨..."
+
msgid "Cherry-pick this commit"
msgstr "拣选此æ交"
@@ -2050,6 +2402,9 @@ msgstr "选择一个文件"
msgid "Choose a role permission"
msgstr "选择角色æƒé™"
+msgid "Choose a template"
+msgstr "选择一个模æ¿"
+
msgid "Choose a template..."
msgstr "选择模æ¿..."
@@ -2063,13 +2418,13 @@ msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent
msgstr "选择 <code>克隆</code> 或 <code>拉å–</code> 以获å–最近的应用程åºä»£ç "
msgid "Choose file…"
-msgstr ""
+msgstr "选择文件…"
msgid "Choose the top-level group for your repository imports."
-msgstr "选择存储库导入的顶级群组。"
+msgstr "选择仓库导入的顶级群组。"
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
-msgstr "选择å¯è§æ€§çº§åˆ«ï¼Œå¯ç”¨/ç¦ç”¨é¡¹ç›®åŠŸèƒ½ï¼ˆè®®é¢˜ï¼Œå­˜å‚¨åº“,wiki,代ç ç‰‡æ®µï¼‰å¹¶è®¾ç½®æƒé™ã€‚"
+msgstr "选择å¯è§æ€§çº§åˆ«ï¼Œå¯ç”¨/ç¦ç”¨é¡¹ç›®åŠŸèƒ½ï¼ˆè®®é¢˜ï¼Œä»“库,wiki,代ç ç‰‡æ®µï¼‰å¹¶è®¾ç½®æƒé™ã€‚"
msgid "Choose what content you want to see on a group’s overview page"
msgstr "选择è¦åœ¨ç¾¤ç»„概述页é¢ä¸Šçœ‹åˆ°çš„内容"
@@ -2080,8 +2435,8 @@ msgstr "请选择è¦è¿žæŽ¥å¹¶è¿è¡Œ CI/CD æµæ°´çº¿çš„代ç ä»“库。"
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr "选择è¦åŒæ­¥åˆ°æ­¤æ¬¡èŠ‚点的切片。"
-msgid "Choose your merge method, set up a default merge request description template."
-msgstr "选择åˆå¹¶æ–¹æ³•ï¼Œè®¾ç½®é»˜è®¤åˆå¹¶è¯·æ±‚æ述模æ¿ã€‚"
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
+msgstr "选择åˆå¹¶æ–¹æ³•ã€é€‰é¡¹ã€æ£€æŸ¥å¹¶è®¾ç½®é»˜è®¤åˆå¹¶è¯·æ±‚说明模æ¿ã€‚"
msgid "CiStatusLabel|canceled"
msgstr "å·²å–消"
@@ -2108,7 +2463,7 @@ msgid "CiStatusLabel|pending"
msgstr "等待中"
msgid "CiStatusLabel|preparing"
-msgstr ""
+msgstr "准备"
msgid "CiStatusLabel|skipped"
msgstr "已跳过"
@@ -2144,7 +2499,7 @@ msgid "CiStatusText|pending"
msgstr "等待中"
msgid "CiStatusText|preparing"
-msgstr ""
+msgstr "准备"
msgid "CiStatusText|skipped"
msgstr "已跳过"
@@ -2152,17 +2507,35 @@ msgstr "已跳过"
msgid "CiStatus|running"
msgstr "è¿è¡Œä¸­"
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr "当å‰å€¼æ— æ³•ä½¿ç”¨éšè—å˜é‡"
+
msgid "CiVariables|Input variable key"
msgstr "输入å˜é‡çš„å称"
msgid "CiVariables|Input variable value"
msgstr "输入å˜é‡çš„值"
+msgid "CiVariables|Key"
+msgstr "é”®"
+
+msgid "CiVariables|Masked"
+msgstr "éšè—"
+
msgid "CiVariables|Remove variable row"
msgstr "删除å˜é‡è¡Œ"
-msgid "CiVariables|This variable will not be masked"
-msgstr ""
+msgid "CiVariables|Scope"
+msgstr "范围"
+
+msgid "CiVariables|State"
+msgstr "状æ€"
+
+msgid "CiVariables|Type"
+msgstr "类型"
+
+msgid "CiVariables|Value"
+msgstr "值"
msgid "CiVariable|* (All environments)"
msgstr "* (所有环境)"
@@ -2177,7 +2550,7 @@ msgid "CiVariable|Error occurred while saving variables"
msgstr "ä¿å­˜å˜é‡æ—¶å‡ºé”™"
msgid "CiVariable|Masked"
-msgstr ""
+msgstr "å·²éšè—"
msgid "CiVariable|New environment"
msgstr "新建环境"
@@ -2189,7 +2562,7 @@ msgid "CiVariable|Search environments"
msgstr "æœç´¢çŽ¯å¢ƒ"
msgid "CiVariable|Toggle masked"
-msgstr ""
+msgstr "切æ¢éšè—"
msgid "CiVariable|Toggle protected"
msgstr "开关ä¿æŠ¤çŠ¶æ€"
@@ -2198,7 +2571,7 @@ msgid "CiVariable|Validation failed"
msgstr "验è¯å¤±è´¥"
msgid "Classification Label (optional)"
-msgstr ""
+msgstr "分类标签(å¯é€‰)"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "ä¸å¯ç”¨: %{reason}"
@@ -2215,9 +2588,18 @@ msgstr "清除æœç´¢"
msgid "Clear search input"
msgstr "清除æœç´¢è¾“å…¥"
+msgid "Clear weight"
+msgstr "清除æƒé‡"
+
+msgid "Clears weight."
+msgstr "清除æƒé‡"
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr "å•å‡»ä¸‹é¢é¡¹ç›®åˆ—表中的任何 <strong>项目å称</strong> 跳转到项目里程碑。"
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr "点击 <strong>下载</strong> 按钮,等待下载完æˆã€‚"
@@ -2267,11 +2649,14 @@ msgid "Close"
msgstr "关闭"
msgid "Close epic"
-msgstr "关闭epic"
+msgstr "关闭å²è¯—"
msgid "Close milestone"
msgstr "关闭里程碑"
+msgid "Close sidebar"
+msgstr "关闭侧边æ "
+
msgid "Closed"
msgstr "已关闭"
@@ -2290,14 +2675,20 @@ msgstr "是此群集的默认环境范围。这æ„味ç€æ‰€æœ‰ä½œä¸šéƒ½å°†ä½¿ç”¨
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} å·²æˆåŠŸå®‰è£…到Kubernetes集群上"
-msgid "ClusterIntegration|%{title} upgraded successfully."
-msgstr "%{title} å‡çº§æˆåŠŸã€‚"
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr "%{title} å·²æˆåŠŸå¸è½½ã€‚"
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
+msgstr "在%{code}kube-system%{end_code}具有%{code}cluster-admin%{end_code}æƒé™çš„æœåŠ¡ä»¤ç‰Œ"
msgid "ClusterIntegration|API URL"
msgstr "API地å€"
msgid "ClusterIntegration|API URL should be a valid http/https url."
-msgstr ""
+msgstr "API URL应该是有效的 http/https URL。"
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr "添加 Kubernetes 集群"
@@ -2308,12 +2699,24 @@ msgstr "添加Kubernetes集群集æˆ"
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr "å°†Kubernetes集群添加到群组åŽï¼Œç¾¤ç»„中的所有项目都将共享该集群。您å¯ä»¥åœ¨åŒä¸€é›†ç¾¤ä¸Šä½¿ç”¨è¯„审应用ã€éƒ¨ç½²åº”用以åŠè¿è¡Œç¾¤é›†ä¸­æ‰€æœ‰é¡¹ç›®çš„æµæ°´çº¿ã€‚"
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr "添加Kubernetes集群将自动在所有项目中共享集群。此集æˆå¯ç”¨äºŽå®¡é˜…ã€éƒ¨ç½²åº”用程åºï¼Œä»¥åŠä½¿ç”¨åŒä¸€ç¾¤é›†è¿è¡Œæ‰€æœ‰é¡¹ç›®çš„æµæ°´çº¿ã€‚"
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr "添加集æˆåˆ°ç¾¤ç»„åŽï¼Œå¯ä»¥åœ¨ç¾¤ç»„中的所有项目中共享集群。"
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr "添加集æˆåŽï¼Œå¯ä»¥åœ¨æ‰€æœ‰é¡¹ç›®ä¸­å…±äº«é›†ç¾¤ã€‚"
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Kubernetes集群集æˆçš„高级选项"
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr "所有数æ®å°†è¢«åˆ é™¤ï¼Œæ— æ³•æ¢å¤ã€‚"
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr "å…许 GitLab 管ç†æ­¤é›†ç¾¤çš„命å空间和æœåŠ¡è´¦æˆ·ã€‚"
+
msgid "ClusterIntegration|Alternatively"
msgstr "除外"
@@ -2329,11 +2732,14 @@ msgstr "å°è¯•èŽ·å–您的项目时å‘生错误:%{error}"
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr "å°è¯•èŽ·å–设备类型时å‘生错误:%{error}"
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr "任何正在è¿è¡Œçš„æµæ°´çº¿å°†è¢«å–消。"
+
msgid "ClusterIntegration|Applications"
msgstr "应用程åº"
msgid "ClusterIntegration|Apply for credit"
-msgstr "申请信用"
+msgstr "申请é¢åº¦"
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
msgstr "确定è¦åˆ é™¤æ­¤Kubernetes集群的集æˆå—?注æ„这并ä¸ä¼šåˆ é™¤å®žé™…çš„Kubernetes集群本身。"
@@ -2363,7 +2769,7 @@ msgid "ClusterIntegration|Cluster health"
msgstr "集群è¿è¡ŒçŠ¶å†µ"
msgid "ClusterIntegration|Cluster name is required."
-msgstr ""
+msgstr "群集å称为必填项。"
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
msgstr "通过选择匹é…的环境范围的最近集群。例如,项目群集将优先于群组群集。"
@@ -2387,13 +2793,13 @@ msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr "å¤åˆ¶Kubernetes集群å称"
msgid "ClusterIntegration|Copy Service Token"
-msgstr ""
+msgstr "å¤åˆ¶æœåŠ¡ä»¤ç‰Œ"
msgid "ClusterIntegration|Create Kubernetes cluster"
msgstr "创建Kubernetes集群"
msgid "ClusterIntegration|Did you know?"
-msgstr "您了解å—?"
+msgstr "你是å¦äº†è§£ï¼Ÿ"
msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
msgstr "å¯ç”¨æˆ–ç¦ç”¨GitLab与Kubernetes群集的连接。"
@@ -2435,7 +2841,10 @@ msgid "ClusterIntegration|GitLab Runner"
msgstr "GitLab Runner"
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
-msgstr ""
+msgstr "GitLab Runner连接到仓库并执行CI/CD作业,返回结果并将应用程åºéƒ¨ç½²åˆ°ç”Ÿäº§çŽ¯å¢ƒã€‚"
+
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr "GitLab管ç†çš„集群"
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Google 云平å°é¡¹ç›®"
@@ -2473,20 +2882,11 @@ msgstr "Ingress 节点"
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr "Ingress为您æ供了一ç§åŸºäºŽè¯·æ±‚主机或路径将请求路由到æœåŠ¡çš„方法,将多个æœåŠ¡é›†ä¸­åˆ°ä¸€ä¸ªå…¥å£ç‚¹ã€‚"
-msgid "ClusterIntegration|Install"
-msgstr "安装"
-
-msgid "ClusterIntegration|Installed"
-msgstr "已安装"
-
-msgid "ClusterIntegration|Installing"
-msgstr "安装中"
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr "安装 Ingress å¯èƒ½ä¼šäº§ç”Ÿé¢å¤–费用。了解更多 %{pricingLink}。"
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
-msgstr "安装 Knative å¯èƒ½ä¼šäº§ç”Ÿé¢å¤–费用。了解更多 %{pricingLink}。"
+msgid "ClusterIntegration|Instance cluster"
+msgstr "实例集群"
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
msgstr "集æˆKubernetes集群自动化"
@@ -2518,6 +2918,9 @@ msgstr "Knative域å:"
msgid "ClusterIntegration|Knative Endpoint:"
msgstr "Knative 节点:"
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr "Knative域åå·²æˆåŠŸæ›´æ–°ã€‚"
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr "Knative扩展了Kubernetes,æ供了一组中间件组件,这些组件对于构建å¯åœ¨ä»»ä½•åœ°æ–¹è¿è¡ŒçŽ°ä»£çš„ã€ä»¥å¼€æºä¸ºä¸­å¿ƒå’ŒåŸºäºŽå®¹å™¨çš„应用程åºè‡³å…³é‡è¦ï¼šåœ¨æœ¬åœ°ï¼Œåœ¨äº‘中,甚至在第三方数æ®ä¸­å¿ƒã€‚"
@@ -2540,7 +2943,7 @@ msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, depl
msgstr "通过Kubernetes群集集æˆï¼Œå¯ä»¥è½»æ¾åœ°ä½¿ç”¨è¯„审应用ã€éƒ¨ç½²åº”用ã€è¿è¡Œæµæ°´çº¿ç­‰ç­‰ã€‚"
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
-msgstr "Kubernetes 集群å¯ç”¨äºŽéƒ¨ç½²åº”用程åºå’Œæ供此项目的审阅应用"
+msgstr "Kubernetes 集群å¯ç”¨äºŽéƒ¨ç½²åº”用程åºå’Œæ供此项目的评审应用"
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr "进一步了解 %{help_link_start_machine_type}实例类型%{help_link_end} å’Œ %{help_link_start_pricing}定价信æ¯%{help_link_end}。"
@@ -2554,6 +2957,9 @@ msgstr "了解更多的Kubernetesä¿¡æ¯"
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr "了解更多的群组级Kubernetes集群信æ¯"
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr "了解有关实例级Kubernetes集群更多信æ¯"
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr "Let's Encrypt"
@@ -2563,9 +2969,6 @@ msgstr "机器类型"
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr "请确ä¿æ‚¨çš„å¸æˆ·%{link_to_requirements}å¯ä»¥åˆ›å»º Kubernetes 集群"
-msgid "ClusterIntegration|Manage"
-msgstr "管ç†"
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr "通过访问 %{link_gke} ç®¡ç† Kubernetes 集群"
@@ -2585,7 +2988,7 @@ msgid "ClusterIntegration|Number of nodes"
msgstr "节点数é‡"
msgid "ClusterIntegration|Number of nodes must be a numerical value."
-msgstr ""
+msgstr "节点数必须是数值。"
msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
msgstr "请输入Kubernetes集群的访问信æ¯ã€‚如需帮助,å¯ä»¥é˜…读Kubernetes集群的 %{link_to_help_page}"
@@ -2627,10 +3030,10 @@ msgid "ClusterIntegration|Replace this with your own hostname if you want. If yo
msgstr "如果需è¦ï¼Œå¯å°†å…¶æ›¿æ¢ä¸ºæ‚¨è‡ªå·±çš„主机å。如果这样åšï¼Œè¯·å°†ä¸»æœºå从上级指å‘Ingress IP地å€ã€‚"
msgid "ClusterIntegration|Request to begin installing failed"
-msgstr "请求安装失败"
+msgstr "请求å¯åŠ¨å®‰è£…失败"
-msgid "ClusterIntegration|Retry update"
-msgstr "é‡è¯•æ›´æ–°"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
+msgstr "请求å¯åŠ¨å¸è½½å¤±è´¥"
msgid "ClusterIntegration|Save changes"
msgstr "ä¿å­˜æ›´æ”¹"
@@ -2666,10 +3069,10 @@ msgid "ClusterIntegration|Select zone to choose machine type"
msgstr "按地域选择实例类型"
msgid "ClusterIntegration|Service Token"
-msgstr ""
+msgstr "æœåŠ¡ä»¤ç‰Œ"
msgid "ClusterIntegration|Service token is required."
-msgstr ""
+msgstr "æœåŠ¡ä»¤ç‰Œæ˜¯å¿…需的。"
msgid "ClusterIntegration|Show"
msgstr "显示"
@@ -2683,12 +3086,36 @@ msgstr "在 Google Kubernetes Engine 上创建Kubernetes集群时å‘生错误"
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "安装 %{title} æ—¶å‘生故障"
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr "å¸è½½ %{title} 时出错"
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr "æ›´æ–°Knative域å时出错。"
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr "指定域将å…许您使用自动评审应用程åºå’Œè‡ªåŠ¨éƒ¨ç½²é˜¶æ®µè¿›è¡Œ %{auto_devops_start}Auto DevOps%{auto_devops_end}。域应é…置与域匹é…的通é…符DNS。"
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
+msgstr "用于对群集进行身份验è¯çš„ Kubernetes è¯ä¹¦ã€‚"
+
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
+msgstr "用于访问 Kubernetes API 的 URL。"
+
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
+msgstr "å…³è”IP将被删除,ä¸èƒ½æ¢å¤ã€‚"
+
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
+msgstr "相关è¯ä¹¦å°†è¢«åˆ é™¤ï¼Œå¹¶ä¸”ä¸èƒ½æ¢å¤ã€‚"
+
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
+msgstr "å…³è”çš„è´Ÿè½½å‡è¡¡å™¨å’ŒIP将被删除,无法还原。"
+
msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr "节点正在分é…中。如果需è¦å¾ˆé•¿æ—¶é—´ï¼Œè¯·æ£€æŸ¥æ‚¨çš„ Kubernetes 集群或 Google Kubernetes Engine 上的é…é¢ã€‚"
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
+msgstr "群集身份验è¯æ—¶å‡ºçŽ°é—®é¢˜ã€‚请确ä¿æ‚¨çš„CAè¯ä¹¦å’Œä»¤ç‰Œæœ‰æ•ˆã€‚"
+
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr "该å¸æˆ·éœ€å…·å¤‡åœ¨å¦‚下指定的%{link_to_container_project}中创建 Kubernetes集群的æƒé™"
@@ -2701,24 +3128,12 @@ msgstr "è¦åœ¨éƒ¨ç½²åŽè®¿é—®æ‚¨çš„应用程åºï¼Œè¯·å°†é€šé…符 DNS æŒ‡å‘ Kna
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "开关Kubernetes 集群"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr "å¸è½½ %{appTitle}"
+
msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr "更新失败。请检查日志,然åŽé‡è¯•ã€‚"
-msgid "ClusterIntegration|Updating"
-msgstr "更新中"
-
-msgid "ClusterIntegration|Upgrade"
-msgstr "å‡çº§"
-
-msgid "ClusterIntegration|Upgrade failed"
-msgstr "å‡çº§å¤±è´¥"
-
-msgid "ClusterIntegration|Upgraded"
-msgstr "å·²å‡çº§"
-
-msgid "ClusterIntegration|Upgrading"
-msgstr "å‡çº§ä¸­"
-
msgid "ClusterIntegration|Validating project billing status"
msgstr "验è¯é¡¹ç›®è´¦å•çŠ¶æ€"
@@ -2726,7 +3141,10 @@ msgid "ClusterIntegration|We could not verify that one of your projects on GCP h
msgstr "无法验è¯æ‚¨åœ¨ GCP 上的æŸä¸ªé¡¹ç›®æ˜¯å¦å¯ç”¨äº†è®¡è´¹ã€‚请é‡è¯•ã€‚"
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr "使用与此项目关è”çš„Kubernetes集群,å¯ä»¥æ–¹ä¾¿åœ°ä½¿ç”¨å®¡é˜…应用,部署应用程åºï¼Œè¿è¡Œæµæ°´çº¿ç­‰ç­‰ã€‚"
+msgstr "使用与此项目关è”çš„Kubernetes集群,å¯ä»¥æ–¹ä¾¿åœ°ä½¿ç”¨è¯„审应用,部署应用程åºï¼Œè¿è¡Œæµæ°´çº¿ç­‰ç­‰ã€‚"
+
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr "您å³å°†ä»Žæ‚¨çš„集群中å¸è½½ %{appTitle}。"
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr "在安装以下应用程åºä¹‹å‰ï¼Œå¿…须先安装Helm Tiller"
@@ -2737,6 +3155,9 @@ msgstr "您必须具有已å¯ç”¨RBAC的群集æ‰èƒ½å®‰è£…Knative。"
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "您的å¸æˆ·å¿…须有æƒé™%{link_to_kubernetes_engine}"
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr "您的 API 无法访问。请确ä¿æ‚¨çš„ API URL 正确。"
+
msgid "ClusterIntegration|Zone"
msgstr "地域"
@@ -2788,9 +3209,15 @@ msgstr "折å æ ¸å‡†äºº"
msgid "Collapse sidebar"
msgstr "收起侧边æ "
+msgid "ComboSearch is not defined"
+msgstr "ComboSearch未定义"
+
msgid "Command line instructions"
msgstr "命令行指引"
+msgid "Commands applied"
+msgstr "命令已执行"
+
msgid "Comment"
msgstr "添加评论"
@@ -2809,6 +3236,9 @@ msgstr "添加评论并将讨论å˜ä¸ºæœªå†³"
msgid "Comment form position"
msgstr "评论框ä½ç½®"
+msgid "Comment is being updated"
+msgstr "评论正在更新"
+
msgid "Comments"
msgstr "评论"
@@ -2880,7 +3310,7 @@ msgid "Commit…"
msgstr "æ交..."
msgid "Company"
-msgstr ""
+msgstr "å…¬å¸"
msgid "Compare"
msgstr "比较"
@@ -2916,10 +3346,10 @@ msgid "CompareBranches|There isn't anything to compare."
msgstr "无需比较。"
msgid "Confidential"
-msgstr "机密"
+msgstr "ç§å¯†"
msgid "Confidentiality"
-msgstr "ä¿å¯†æ€§"
+msgstr "ç§å¯†æ€§"
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr "é…ç½® GitLab Runner 以开始使用Web终端。 %{helpStart}了解更多。%{helpEnd}"
@@ -2927,6 +3357,9 @@ msgstr "é…ç½® GitLab Runner 以开始使用Web终端。 %{helpStart}了解更å¤
msgid "Configure Gitaly timeouts."
msgstr "é…ç½®Gitaly超时时间。"
+msgid "Configure Let's Encrypt"
+msgstr "é…ç½® Let's Encrypt"
+
msgid "Configure Tracing"
msgstr "é…置跟踪"
@@ -2952,10 +3385,16 @@ msgid "Configure the way a user creates a new account."
msgstr "é…置用户创建新å¸æˆ·çš„æ–¹å¼ã€‚"
msgid "Confirm"
+msgstr "确认"
+
+msgid "Confirmation email sent to %{email}"
msgstr ""
msgid "Confirmation required"
-msgstr ""
+msgstr "需è¦ç¡®è®¤"
+
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr "æ­å–œï¼æ‚¨å·²å¯ç”¨äº†åŒé‡è®¤è¯ï¼"
msgid "Connect"
msgstr "连接"
@@ -2969,44 +3408,50 @@ msgstr "从 Github 中导入代ç ä»“库"
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr "连接外部仓库åŽï¼Œæ–°æ交将会å¯åŠ¨CI/CDæµæ°´çº¿ã€‚ä»…å¯ç”¨CI/CD功能的Gitlab项目将会被创建。"
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr "正在连接..."
+msgid "Connection failure"
+msgstr "连接失败"
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
-msgstr ""
+msgstr "请è”ç³» %{namespace_name} 群组的所有者以å‡çº§è®¡åˆ’。"
msgid "Contact owner %{link_start}%{owner_name}%{link_end} to upgrade the plan."
-msgstr ""
+msgstr "请è”系所有者 %{link_start}%{owner_name}%{link_end} 以å‡çº§è®¡åˆ’。"
msgid "Contact sales to upgrade"
msgstr "è”系销售人员进行å‡çº§"
msgid "Contact your Administrator to upgrade your license."
-msgstr ""
+msgstr "请与管ç†å‘˜è”系以å‡çº§è®¸å¯è¯ã€‚"
msgid "Container Registry"
-msgstr "容器注册表"
+msgstr "容器镜åƒåº“"
msgid "Container registry images"
-msgstr ""
+msgstr "容器镜åƒåº“é•œåƒ"
msgid "ContainerRegistry|Created"
-msgstr "已创建"
+msgstr "创建时间"
msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
-msgstr "首先使用您的 GitLab 用户å和密ç ç™»å½• GitLab 的容器注册表。如果您已ç»%{link_2fa},则需è¦ä½¿ç”¨%{link_token}:"
+msgstr "首先使用您的 GitLab 用户å和密ç ç™»å½• GitLab 的容器镜åƒåº“。如果您已ç»%{link_2fa},则需è¦ä½¿ç”¨%{link_token}:"
msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
msgstr "GitLab 最多支æŒ3个级别的镜åƒå‘½å。以下镜åƒå称示例对当å‰é¡¹ç›®æœ‰æ•ˆï¼š"
msgid "ContainerRegistry|How to use the Container Registry"
-msgstr "如何使用容器注册表"
+msgstr "如何使用容器镜åƒåº“"
msgid "ContainerRegistry|Learn more about"
msgstr "进一步了解"
msgid "ContainerRegistry|No tags in Container Registry for this container image."
-msgstr "容器注册表中没有此容器镜åƒçš„标签。"
+msgstr "容器镜åƒåº“中没有此容器镜åƒçš„标签。"
msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
msgstr "登录åŽæ‚¨å¯ä»¥ä½¿ç”¨é€šç”¨çš„%{build}å’Œ%{push}命令创建和上传容器镜åƒ"
@@ -3030,11 +3475,14 @@ msgid "ContainerRegistry|Use different image names"
msgstr "使用ä¸åŒçš„é•œåƒå称"
msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
-msgstr "通过使用GitLab内置的Docker容器注册表,æ¯ä¸ªé¡¹ç›®éƒ½å¯ä»¥æœ‰ç‹¬ç«‹çš„空间æ¥å­˜å‚¨Dockeré•œåƒã€‚"
+msgstr "通过使用GitLab内置的Docker容器镜åƒåº“,æ¯ä¸ªé¡¹ç›®éƒ½å¯ä»¥æœ‰ç‹¬ç«‹çš„空间æ¥å­˜å‚¨Dockeré•œåƒã€‚"
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr "您也å¯ä»¥ä½¿ç”¨ %{deploy_token} 以åªè¯»æ–¹å¼è®¿é—®é•œåƒåº“çš„é•œåƒã€‚"
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr "包å«å›¾åƒ(%{size})çš„%{count}个blob"
+
msgid "Contents of .gitlab-ci.yml"
msgstr ".gitlab-ci.yml的内容"
@@ -3054,7 +3502,7 @@ msgid "Contribution"
msgstr "贡献"
msgid "Contribution Analytics"
-msgstr "贡献分æž"
+msgstr "贡献度分æž"
msgid "Contribution Charts"
msgstr "贡献图表"
@@ -3080,15 +3528,21 @@ msgstr "%{branch_name} 分支上的æ交,ä¸å«åˆå¹¶æ交。é™6000次。"
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr "请ç¨å€™ï¼Œå›¾è¡¨æž„建完æˆåŽé¡µé¢ä¼šè‡ªåŠ¨åˆ·æ–°ã€‚"
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr "控制第三方优惠的显示。"
msgid "Control the maximum concurrency of repository backfill for this secondary node"
-msgstr "控制此次è¦èŠ‚点的åŒæ­¥å­˜å‚¨åº“的最大并å‘"
+msgstr "控制此次è¦èŠ‚点的åŒæ­¥ä»“库的最大并å‘"
msgid "ConvDev Index"
msgstr "ConvDev指数"
+msgid "Copied"
+msgstr "å·²å¤åˆ¶"
+
msgid "Copy %{http_label} clone URL"
msgstr "å¤åˆ¶ %{http_label} 克隆地å€"
@@ -3107,9 +3561,6 @@ msgstr "å¤åˆ¶SSH克隆URL"
msgid "Copy SSH public key"
msgstr "å¤åˆ¶SSH公钥"
-msgid "Copy SSH public key to clipboard"
-msgstr "å°† SSH 公钥å¤åˆ¶åˆ°å‰ªè´´æ¿"
-
msgid "Copy URL to clipboard"
msgstr "å¤åˆ¶ URL 到剪贴æ¿"
@@ -3125,6 +3576,12 @@ msgstr "å¤åˆ¶æ交 SHA 的值到剪贴æ¿"
msgid "Copy file path to clipboard"
msgstr "将文件路径å¤åˆ¶åˆ°å‰ªè´´æ¿"
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr "从 %{source_issuable_reference} å¤åˆ¶æ ‡è®°å’Œé‡Œç¨‹ç¢‘。"
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr "从当å‰é¡¹ç›®ä¸­å…¶ä»–议题或åˆå¹¶è¯·æ±‚å¤åˆ¶æ ‡è®°å’Œé‡Œç¨‹ç¢‘"
+
msgid "Copy link"
msgstr "å¤åˆ¶é“¾æŽ¥"
@@ -3134,6 +3591,9 @@ msgstr "将标识å¤åˆ¶åˆ°å‰ªè´´æ¿"
msgid "Copy secret to clipboard"
msgstr "å¤åˆ¶å¯†ç åˆ°å‰ªè´´æ¿"
+msgid "Copy source to clipboard"
+msgstr "å¤åˆ¶æºåˆ°å‰ªè´´æ¿"
+
msgid "Copy to clipboard"
msgstr "å¤åˆ¶åˆ°å‰ªè´´æ¿"
@@ -3141,28 +3601,34 @@ msgid "Copy token to clipboard"
msgstr "将令牌å¤åˆ¶åˆ°å‰ªè´´æ¿"
msgid "Could not authorize chat nickname. Try again!"
-msgstr ""
+msgstr "无法授æƒèŠå¤©æ˜µç§°ã€‚å†è¯•ä¸€æ¬¡ï¼"
+
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr "无法更改HEAD:分支“%{branch}â€ä¸å­˜åœ¨"
msgid "Could not connect to FogBugz, check your URL"
+msgstr "无法连接到 FogBugz,请检查您的 URL"
+
+msgid "Could not connect to Web IDE file mirror service."
msgstr ""
msgid "Could not create Wiki Repository at this time. Please try again later."
-msgstr ""
+msgstr "ç›®å‰æ— æ³•åˆ›å»º Wiki 仓库。请ç¨åŽå†è¯•ã€‚"
msgid "Could not delete chat nickname %{chat_name}."
-msgstr ""
+msgstr "无法删除èŠå¤©æ˜µç§° %{chat_name}。"
msgid "Could not remove the trigger."
-msgstr ""
+msgstr "无法删除触å‘器。"
msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
msgstr "无法获å–æµæ°´çº¿çŠ¶æ€ã€‚有关故障排除步骤,请å‚阅 %{linkStart}文档%{linkEnd}。"
msgid "Could not revoke impersonation token %{token_name}."
-msgstr ""
+msgstr "无法撤消身份模拟令牌 %{token_name}。"
msgid "Could not revoke personal access token %{personal_access_token_name}."
-msgstr ""
+msgstr "无法撤消个人访问令牌 %{personal_access_token_name}。"
msgid "Coverage"
msgstr "覆盖率"
@@ -3177,16 +3643,25 @@ msgid "Create New Domain"
msgstr "创建新域"
msgid "Create a GitLab account first, and then connect it to your %{label} account."
-msgstr ""
+msgstr "请先创建一个GitLabå¸æˆ·ï¼Œç„¶åŽå°†å…¶è¿žæŽ¥åˆ°æ‚¨çš„ %{label} å¸æˆ·ã€‚"
+
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr "创建本地代ç†ï¼Œç”¨äºŽå­˜å‚¨é¢‘ç¹ä½¿ç”¨çš„上游镜åƒã€‚ %{link_start}了解更多%{link_end} 关于ä¾èµ–代ç†çš„内容。"
+
+msgid "Create a merge request."
+msgstr "创建一个åˆå¹¶è¯·æ±‚."
msgid "Create a new branch"
msgstr "创建一个新分支"
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr "当å‰æ— æ–‡ä»¶ã€‚请先创建一个新文件。然åŽæ‚¨å°†èƒ½å¤Ÿæ交您的更改。"
+
msgid "Create a new issue"
msgstr "创建新议题"
msgid "Create a new repository"
-msgstr "创建一个新存储库"
+msgstr "创建一个新仓库"
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "在å¸æˆ·ä¸Šåˆ›å»ºä¸ªäººè®¿é—®ä»¤ç‰Œï¼Œä»¥é€šè¿‡ %{protocol} æ¥æ‹‰å–或推é€ã€‚"
@@ -3207,7 +3682,7 @@ msgid "Create empty repository"
msgstr "创建空的仓库"
msgid "Create epic"
-msgstr "创建epic"
+msgstr "创建å²è¯—"
msgid "Create file"
msgstr "创建文件"
@@ -3254,6 +3729,12 @@ msgstr "创建项目标记"
msgid "Create your first page"
msgstr "创建您的第一个页é¢"
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr "您无æƒåœ¨æ­¤ç¾¤ç»„中创建å­ç¾¤ç»„。"
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr "您无æƒåˆ›å»ºç¾¤ç»„。"
+
msgid "CreateTag|Tag"
msgstr "标签"
@@ -3261,7 +3742,7 @@ msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "创建个人访问令牌"
msgid "Created"
-msgstr "已创建"
+msgstr "创建时间"
msgid "Created At"
msgstr "创建于"
@@ -3269,14 +3750,29 @@ msgstr "创建于"
msgid "Created by me"
msgstr "由我创建"
+msgid "Created issue %{issueLink}"
+msgstr "创建议题 %{issueLink}"
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr "在 %{projectLink} 中创建议题 %{issueLink}"
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr "创建åˆå¹¶è¯·æ±‚ %{mergeRequestLink}"
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr "在 %{projectLink} 中创建åˆå¹¶è¯·æ±‚ %{mergeRequestLink}"
+
msgid "Created on"
msgstr "创建于"
msgid "Created on:"
msgstr "创建于:"
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr "创建分支“%{branch_name}â€åŠç›¸åº”çš„åˆå¹¶è¯·æ±‚以解决此议题"
+
msgid "Creating epic"
-msgstr "创建epic中"
+msgstr "创建å²è¯—中"
msgid "Cron Timezone"
msgstr "Cron 时区"
@@ -3293,6 +3789,9 @@ msgstr "当å‰é¡¹ç›®"
msgid "Current node"
msgstr "当å‰èŠ‚点"
+msgid "Current password"
+msgstr "当å‰å¯†ç "
+
msgid "CurrentUser|Profile"
msgstr "用户资料"
@@ -3371,8 +3870,20 @@ msgstr "所有"
msgid "DashboardProjects|Personal"
msgstr "个人"
+msgid "DashboardProjects|Trending"
+msgstr "热门"
+
msgid "Dashboards"
-msgstr ""
+msgstr "仪表æ¿"
+
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr "%{firstProject} 和 %{secondProject}"
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr "%{firstProject}ã€%{rest} å’Œ %{secondProject}"
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
+msgstr "无法添加 %{invalidProjects}。 当å‰ä»ªè¡¨æ¿å¯ç”¨äºŽå…¬å¼€é¡¹ç›®ä»¥åŠå…·æœ‰Gold方案的群组中的ç§æœ‰é¡¹ç›®ã€‚"
msgid "Data is still calculating..."
msgstr "æ•°æ®ä»åœ¨è®¡ç®—中……"
@@ -3380,6 +3891,18 @@ msgstr "æ•°æ®ä»åœ¨è®¡ç®—中……"
msgid "Date picker"
msgstr "日期选择器"
+msgid "DayTitle|F"
+msgstr "五"
+
+msgid "DayTitle|M"
+msgstr "一"
+
+msgid "DayTitle|S"
+msgstr "æ—¥"
+
+msgid "DayTitle|W"
+msgstr "三"
+
msgid "Debug"
msgstr "调试"
@@ -3399,13 +3922,13 @@ msgid "Default Branch"
msgstr "默认分支"
msgid "Default artifacts expiration"
-msgstr "默认工件过期时间"
+msgstr "默认产物过期时间"
msgid "Default classification label"
msgstr "默认分类标记"
msgid "Default description template for issues"
-msgstr ""
+msgstr "议题的默认æ述模æ¿"
msgid "Default first day of the week"
msgstr "æ¯å‘¨çš„默认起始日"
@@ -3414,6 +3937,9 @@ msgid "Default first day of the week in calendars and date pickers."
msgstr "在日期选择器中显示æ¯å‘¨é»˜è®¤çš„起始日。"
msgid "Default issue template"
+msgstr "默认议题模æ¿"
+
+msgid "Default project deletion protection"
msgstr ""
msgid "Default: Directly import the Google Code email address or username"
@@ -3456,7 +3982,7 @@ msgid "Delete comment"
msgstr "删除评论"
msgid "Delete license"
-msgstr ""
+msgstr "删除许å¯è¯"
msgid "Delete list"
msgstr "删除列表"
@@ -3467,27 +3993,90 @@ msgstr "删除æºåˆ†æ”¯"
msgid "Delete this attachment"
msgstr "删除此附件"
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr "删除项目仓库失败。请é‡è¯•æˆ–è”系管ç†å‘˜ã€‚"
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr "删除项目容器镜åƒåº“中的æŸäº›æ ‡ç­¾å¤±è´¥ã€‚请é‡è¯•æˆ–è”系管ç†å‘˜ã€‚"
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr "删除wiki仓库失败。请é‡è¯•æˆ–è”系管ç†å‘˜ã€‚"
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr "æ¢å¤é¡¹ç›®ä»“库失败。请è”系管ç†å‘˜ã€‚"
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr "æ¢å¤wiki仓库失败。请è”系管ç†å‘˜ã€‚"
+
msgid "Deleted"
msgstr "已删除"
msgid "Deleted chat nickname: %{chat_name}!"
-msgstr ""
+msgstr "已删除èŠå¤©çš„昵称: %{chat_name}!"
msgid "Deleting the license failed."
-msgstr ""
+msgstr "删除许å¯è¯å¤±è´¥ã€‚"
msgid "Deleting the license failed. The license was not found."
-msgstr ""
+msgstr "删除许å¯è¯å¤±è´¥ã€‚找ä¸åˆ°è®¸å¯è¯ã€‚"
msgid "Deleting the license failed. You are not permitted to perform this action."
-msgstr ""
+msgstr "删除许å¯è¯å¤±è´¥ã€‚ä¸å…许您执行此æ“作。"
msgid "Denied authorization of chat nickname %{user_name}."
-msgstr ""
+msgstr "æ‹’ç»èŠå¤©æ˜µç§° %{user_name} 的授æƒã€‚"
msgid "Deny"
msgstr "æ‹’ç»"
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr "ä¾èµ–代ç†"
+
+msgid "Dependency proxy"
+msgstr "ä¾èµ–代ç†"
+
+msgid "Dependency proxy URL"
+msgstr "ä¾èµ–代ç†URL"
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr "ä¾èµ–代ç†åŠŸèƒ½ç›®å‰ä»…é™äºŽå…¬å¼€ç¾¤ç»„。"
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr " 开关ä¾èµ–代ç†"
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "部署"
@@ -3496,7 +4085,7 @@ msgid "Deploy Keys"
msgstr "部署密钥"
msgid "Deploy key was successfully updated."
-msgstr ""
+msgstr "部署密钥已æˆåŠŸæ›´æ–°ã€‚"
msgid "DeployKeys|+%{count} others"
msgstr "+%{count} 其他"
@@ -3508,7 +4097,7 @@ msgid "DeployKeys|Deploy key"
msgstr "部署密钥"
msgid "DeployKeys|Enabled deploy keys"
-msgstr "å¯ç”¨éƒ¨ç½²å¯†é’¥"
+msgstr "å·²å¯ç”¨çš„部署密钥"
msgid "DeployKeys|Error enabling deploy key"
msgstr "å¯ç”¨éƒ¨ç½²å¯†é’¥å‡ºé”™"
@@ -3529,7 +4118,7 @@ msgid "DeployKeys|No deploy keys found. Create one with the form above."
msgstr "没有找到部署密钥。请使用上é¢çš„表å•åˆ›å»ºéƒ¨ç½²å¯†é’¥ã€‚"
msgid "DeployKeys|Privately accessible deploy keys"
-msgstr "ç§äººè®¿é—®çš„部署密钥"
+msgstr "ç§æœ‰è®¿é—®çš„部署密钥"
msgid "DeployKeys|Project usage"
msgstr "项目使用情况"
@@ -3553,7 +4142,7 @@ msgid "DeployTokens|Add a deploy token"
msgstr "添加一个部署令牌"
msgid "DeployTokens|Allows read-only access to the registry images"
-msgstr "å…许对容器注册表镜åƒè¿›è¡Œåªè¯»è®¿é—®"
+msgstr "å…许对容器镜åƒåº“é•œåƒè¿›è¡Œåªè¯»è®¿é—®"
msgid "DeployTokens|Allows read-only access to the repository"
msgstr "å…许对仓库进行åªè¯»è®¿é—®"
@@ -3568,13 +4157,13 @@ msgid "DeployTokens|Create deploy token"
msgstr "创建部署令牌"
msgid "DeployTokens|Created"
-msgstr "已创建"
+msgstr "创建时间"
msgid "DeployTokens|Deploy Tokens"
msgstr "部署令牌"
msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
-msgstr "部署令牌å¯ä»¥å¯¹ä»“库和容器注册表中的镜åƒè¿›è¡Œåªè¯»è®¿é—®ã€‚"
+msgstr "部署令牌å¯ä»¥å¯¹ä»“库和容器镜åƒåº“中的镜åƒè¿›è¡Œåªè¯»è®¿é—®ã€‚"
msgid "DeployTokens|Expires"
msgstr "到期"
@@ -3637,7 +4226,7 @@ msgid "Description"
msgstr "æè¿°"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
-msgstr ""
+msgstr "使用%{link_start}GitLab风格Markdown%{link_end}解æžçš„æè¿°"
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr "æ述模æ¿å…许您为项目的问题和åˆå¹¶è¯·æ±‚定义æ述字段的特定模æ¿ã€‚"
@@ -3646,31 +4235,34 @@ msgid "Description:"
msgstr "æè¿°:"
msgid "DesignManagement|%{current_design} of %{designs_count}"
-msgstr ""
+msgstr "%{current_design}/%{designs_count}"
msgid "DesignManagement|Could not find design, please try again."
-msgstr ""
+msgstr "无法找到设计,请å†è¯•ä¸€æ¬¡ã€‚"
msgid "DesignManagement|Error uploading a new design. Please try again"
-msgstr ""
+msgstr "上传新设计时出错。请å†è¯•ä¸€æ¬¡"
msgid "DesignManagement|Go back to designs"
-msgstr ""
+msgstr "返回到设计"
msgid "DesignManagement|Go to next design"
-msgstr ""
+msgstr "转到下一个设计"
msgid "DesignManagement|Go to previous design"
-msgstr ""
+msgstr "转到上一个设计"
+
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr "å…许上传的设计最大数é‡ä¸º %{upload_limit}。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "DesignManagement|The one place for your designs"
-msgstr ""
+msgstr "您的设计的一个地方"
msgid "DesignManagement|Upload and view the latest designs for this issue. Consistent and easy to find, so everyone is up to date."
-msgstr ""
+msgstr "上传并查看此议题的最新设计。兼容且易于查找,因此æ¯ä¸ªäººéƒ½æ˜¯æœ€æ–°çš„。"
msgid "DesignManagement|Upload designs"
-msgstr ""
+msgstr "上传设计"
msgid "Designs"
msgstr "设计"
@@ -3715,11 +4307,17 @@ msgid "Disable group Runners"
msgstr "ç¦ç”¨ç¾¤ç»„Runner"
msgid "Disable shared Runners"
-msgstr "ç¦ç”¨å…±äº«è¿è¡Œå™¨"
+msgstr "ç¦ç”¨å…±äº«Runner"
+
+msgid "Disable two-factor authentication"
+msgstr "ç¦ç”¨åŒé‡è®¤è¯"
msgid "Disabled"
msgstr "å·²ç¦ç”¨"
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr "ç¦ç”¨é•œåƒåªèƒ½ç”±å®žä¾‹æ‰€æœ‰è€…å¯ç”¨ã€‚建议您删除。"
+
msgid "Discard"
msgstr "放弃"
@@ -3741,8 +4339,14 @@ msgstr "å–消"
msgid "Discard review"
msgstr "放弃评审"
+msgid "DiscordService|Discord Notifications"
+msgstr "Discord 通知"
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr "在 Discord 中接收事件通知"
+
msgid "Discover GitLab Geo"
-msgstr "å‘现GitLab Geo"
+msgstr "探索GitLab Geo"
msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr "æµè§ˆé¡¹ç›®ï¼Œç¾¤ç»„和代ç ç‰‡æ®µã€‚与他人分享您的项目"
@@ -3771,18 +4375,42 @@ msgstr "关闭åˆå¹¶è¯·æ±‚推广"
msgid "Dismiss trial promotion"
msgstr "关闭试用推è"
+msgid "Dismissed"
+msgstr "已忽略"
+
+msgid "Dismissed at %{projectLink}"
+msgstr "在%{projectLink}中忽略"
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr "在æµæ°´çº¿%{pipelineLink}上忽略"
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr "在%{projectLink} 中的æµæ°´çº¿ %{pipelineLink}上忽略"
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr "您想自定义如何将Google Code电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·å导入GitLabå—?"
+msgid "Dockerfile"
+msgstr "Dockerfile"
+
msgid "Documentation for popular identity providers"
msgstr "常è§çš„身份验è¯æ供商的相关文档"
msgid "Domain"
msgstr "域å"
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr "域验è¯æ˜¯å…¬å…± GitLab 站点的基本安全措施。用户需è¦è¯æ˜Žä»–们在å¯ç”¨åŸŸä¹‹å‰æ‹¥æœ‰åŸŸçš„所有æƒ"
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr "ä¸è¦æŠŠGPG密钥中的ç§é’¥éƒ¨åˆ†è´´è¿‡æ¥ï¼Œè¯·åªç²˜è´´å…¬é’¥éƒ¨åˆ†ï¼Œå…¶å¼€å§‹äºŽ '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+
msgid "Don't show again"
msgstr "ä¸å†æ˜¾ç¤º"
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr "ä¸ç”¨æ‹…心,您å¯ä»¥é€šè¿‡å•å‡»å³ä¸Šè§’的帮助图标æ¥è®¿é—®æ­¤å¯¼è§ˆï¼Œç„¶åŽé€‰æ‹© <strong>Learn GitLab</strong>。"
+
msgid "Done"
msgstr "完æˆ"
@@ -3790,31 +4418,25 @@ msgid "Download"
msgstr "下载"
msgid "Download artifacts"
-msgstr "下载工件"
+msgstr "下载产物"
msgid "Download asset"
msgstr "下载资æº"
+msgid "Download codes"
+msgstr "下载代ç "
+
msgid "Download export"
-msgstr ""
+msgstr "下载导出"
msgid "Download license"
-msgstr ""
+msgstr "下载许å¯è¯"
-msgid "Download tar"
-msgstr ""
-
-msgid "Download tar.bz2"
-msgstr ""
-
-msgid "Download tar.gz"
-msgstr ""
-
-msgid "Download zip"
-msgstr ""
+msgid "Download source code"
+msgstr "下载æºä»£ç "
-msgid "DownloadArtifacts|Download"
-msgstr ""
+msgid "Download this directory"
+msgstr "下载此目录"
msgid "DownloadCommit|Email Patches"
msgstr "电å­é‚®ä»¶è¡¥ä¸"
@@ -3855,6 +4477,9 @@ msgstr "编辑标签"
msgid "Edit Milestone"
msgstr "编辑里程碑"
+msgid "Edit Password"
+msgstr "编辑密ç "
+
msgid "Edit Pipeline Schedule %{id}"
msgstr "编辑 %{id} æµæ°´çº¿è®¡åˆ’"
@@ -3891,51 +4516,90 @@ msgstr "编辑公共部署密钥"
msgid "Elasticsearch"
msgstr "Elasticsearch"
+msgid "Elasticsearch indexing restrictions"
+msgstr "Elasticsearch索引é™åˆ¶"
+
+msgid "Elasticsearch indexing started"
+msgstr "Elasticsearch索引已å¯åŠ¨"
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr "Elasticsearch集æˆåŠElasticsearch AWS IAM。"
msgid "Elastic|None. Select namespaces to index."
-msgstr ""
+msgstr "无。请选择è¦å»ºç«‹ç´¢å¼•çš„命å空间。"
msgid "Elastic|None. Select projects to index."
-msgstr ""
+msgstr "无。请选择è¦å»ºç«‹ç´¢å¼•çš„项目。"
msgid "Email"
msgstr "电å­é‚®ä»¶"
msgid "Email address"
-msgstr ""
+msgstr "电å­é‚®ä»¶åœ°å€"
msgid "Email patch"
msgstr "电å­é‚®ä»¶è¡¥ä¸"
+msgid "Email the pipelines status to a list of recipients."
+msgstr "å°†æµæ°´çº¿çŠ¶æ€é€šè¿‡ç”µå­é‚®ä»¶å‘é€ç»™å¤šä¸ªæ”¶ä»¶äººã€‚"
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
-msgstr ""
+msgstr "电å­é‚®ä»¶å†…容空白。请确ä¿æ‚¨çš„回å¤ä½äºŽç”µå­é‚®ä»¶çš„顶部,因为我们无法处ç†å†…è”回å¤ã€‚"
msgid "EmailError|The thread you are replying to no longer exists, perhaps it was deleted? If you believe this is in error, contact a staff member."
-msgstr ""
+msgstr "您回å¤çš„主题ä¸å†å­˜åœ¨ï¼Œå¯èƒ½å·²è¢«åˆ é™¤ã€‚如果您认为这是错误的,请è”系系统管ç†å‘˜ã€‚"
msgid "EmailError|We couldn't figure out what the email is for. Please create your issue or comment through the web interface."
-msgstr ""
+msgstr "我们无法弄清楚电å­é‚®ä»¶çš„用途。请通过WEB页é¢åˆ›å»ºæ‚¨çš„议题或评论。"
msgid "EmailError|We couldn't figure out what the email is in reply to. Please create your comment through the web interface."
-msgstr ""
+msgstr "我们无法弄清楚电å­é‚®ä»¶çš„回å¤å†…容。请通过WEB页é¢åˆ›å»ºæ‚¨çš„评论。"
msgid "EmailError|We couldn't figure out what user corresponds to the email. Please create your comment through the web interface."
-msgstr ""
+msgstr "我们无法确定用户对应的电å­é‚®ä»¶ã€‚请通过WEB页é¢åˆ›å»ºæ‚¨çš„评论。"
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
-msgstr ""
+msgstr "我们找ä¸åˆ°è¯¥é¡¹ç›®ã€‚请检查是å¦æœ‰æ‹¼å†™é”™è¯¯ã€‚"
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
-msgstr ""
+msgstr "ä¸å…许您执行此æ“作。如果您认为这是错误的,请è”系系统管ç†å‘˜ã€‚"
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
-msgstr ""
+msgstr "您的å¸æˆ·å·²è¢«ç¦ç”¨ã€‚如果您认为这是错误的,请è”系系统管ç†å‘˜ã€‚"
+
+msgid "EmailToken|reset it"
+msgstr "é‡ç½®ä»¤ç‰Œ"
+
+msgid "EmailToken|resetting..."
+msgstr "正在é‡ç½®..."
msgid "Emails"
msgstr "电å­é‚®ä»¶"
+msgid "Emails separated by comma"
+msgstr "以逗å·åˆ†éš”的电å­é‚®ä»¶åœ°å€"
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr "ç¦ç”¨ä»£ç å·®å¼‚"
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr "ä¸åœ¨é€šçŸ¥ä¸­åŒ…å«å¯èƒ½æ•æ„Ÿçš„代ç å·®å¼‚。"
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr "å°†æ¯ä¸ªæŽ¨é€çš„æ交和差异通过电å­é‚®ä»¶å‘é€ç»™ä¸€ä¸ªæ”¶ä»¶äººåˆ—表。"
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr "推é€æ—¶å‘é€ç”µå­é‚®ä»¶"
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr "由空格分隔的多个电å­é‚®ä»¶åœ°å€"
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr "å‘é€è‡ªæ交者"
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr "如果这个域å是 GitLab 域å的一部分(例如%{domains}),则从æ交者电å­é‚®ä»¶åœ°å€å‘é€é€šçŸ¥ 。"
+
msgid "Embed"
msgstr "嵌入"
@@ -3960,6 +4624,9 @@ msgstr "为此群组å¯ç”¨ SAML 身份验è¯"
msgid "Enable Sentry for error reporting and logging."
msgstr "å¯ç”¨S​​entry进行错误报告和日志记录。"
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr "å¯ç”¨å¹¶é…ç½®InfluxDB指标。"
@@ -3994,13 +4661,10 @@ msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr "å¯ç”¨reCAPTCHA或Akismet并设置IPé™åˆ¶ã€‚"
msgid "Enable shared Runners"
-msgstr "å¯ç”¨å…±äº«çš„è¿è¡Œå™¨"
-
-msgid "Enable the Performance Bar for a given group."
-msgstr "对指定群组å¯ç”¨æ€§èƒ½æ ã€‚"
+msgstr "å¯ç”¨å…±äº«Runner"
msgid "Enable two-factor authentication"
-msgstr "å¯ç”¨åŒå› ç´ èº«ä»½éªŒè¯"
+msgstr "å¯ç”¨åŒé‡è®¤è¯"
msgid "Enable usage ping"
msgstr "å¯ç”¨ä½¿ç”¨æƒ…况检测(usage ping)"
@@ -4009,7 +4673,7 @@ msgid "Enable usage ping to get an overview of how you are using GitLab from a f
msgstr "å¯ç”¨ä½¿ç”¨æƒ…况检测(usage ping)以从功能角度总体上了解您如何使用GitLab。"
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
-msgstr ""
+msgstr "å¯ç”¨/ç¦ç”¨æœåŠ¡å°ã€‚ %{link_start}了解有关æœåŠ¡å°%{link_end}的更多信æ¯ã€‚"
msgid "Enabled"
msgstr "å·²å¯ç”¨"
@@ -4024,17 +4688,23 @@ msgid "Enabling this will only make licensed EE features available to projects i
msgstr "此功能仅在 GitLab EE 许å¯ä¸‹å¯ç”¨ã€‚如果è¦å¯ç”¨ï¼Œè¯·ç¡®è®¤å‘½å空间包å«æ­¤åŠŸèƒ½æˆ–者是公开项目。"
msgid "End date"
-msgstr ""
+msgstr "结æŸæ—¥æœŸ"
msgid "Ends at (UTC)"
msgstr "结æŸäºŽ(UTC)"
+msgid "Enforce DNS rebinding attack protection"
+msgstr "强制DNSé‡æ–°ç»‘定攻击ä¿æŠ¤"
+
msgid "Enter at least three characters to search"
-msgstr ""
+msgstr "请至少输入三个字符æ‰å¯æœç´¢"
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr "输入您的BitbucketæœåŠ¡å™¨URL和个人访问令牌"
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr "在下é¢è¾“入您的Phabricator Server URL和个人访问令牌"
+
msgid "Enter the issue description"
msgstr "输入议题æè¿°"
@@ -4047,7 +4717,10 @@ msgstr "输入åˆå¹¶è¯·æ±‚说明"
msgid "Enter the merge request title"
msgstr "输入åˆå¹¶è¯·æ±‚标题"
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr "您正在查看最åŽæ›´æ–°çš„环境"
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4059,9 +4732,33 @@ msgstr "环境:"
msgid "Environments"
msgstr "环境"
+msgid "Environments Dashboard"
+msgstr "环境仪表æ¿"
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr "环境å…许您跟踪应用程åºçš„部署 %{link_to_read_more}。"
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr "将项目添加到仪表æ¿"
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr "添加项目"
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr "环境仪表æ¿"
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr "作业:%{job}"
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr "更多æ“作"
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr "删除"
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr "环境仪表æ¿æä¾›æ¯ä¸ªé¡¹ç›®çŽ¯å¢ƒçŠ¶æ€çš„摘è¦ï¼ŒåŒ…括æµæ°´çº¿å’Œè­¦æŠ¥çŠ¶æ€ã€‚"
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "获å–环境时å‘生错误。"
@@ -4186,31 +4883,64 @@ msgid "Environments|protected"
msgstr "å—ä¿æŠ¤çš„"
msgid "Epic"
-msgstr "Epic"
+msgstr "å²è¯—"
msgid "Epics"
-msgstr "Epic"
+msgstr "å²è¯—"
msgid "Epics Roadmap"
-msgstr "Epic路线图"
+msgstr "å²è¯—路线图"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
-msgstr "利用 Epic,产å“线管ç†ä¼šå˜å¾—æ›´è½»æ¾ä¸”更高效"
+msgstr "有效利用å²è¯—,您的产å“线管ç†ä¼šå˜å¾—æ›´è½»æ¾é«˜æ•ˆ"
+
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr "ä¿å­˜ %{epicDateType} 日期时å‘生错误"
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr "我该如何解决该问题?"
msgid "Epics|More information"
msgstr "更多信æ¯"
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
-msgstr "è¿™äº›æ—¥æœŸä¼šå½±å“ epic 在路线图中的显示方å¼ã€‚里程碑日期æ¥è‡ªäºŽå²è¯—故事中的议题所属的里程碑。您还å¯ä»¥è®¾ç½®å›ºå®šæ—¥æœŸæˆ–完全删除它们。"
+msgstr "这些日期会影å“å²è¯—在路线图中的显示方å¼ã€‚里程碑日期æ¥è‡ªäºŽå²è¯—故事中的议题所属的里程碑。您还å¯ä»¥è®¾ç½®å›ºå®šæ—¥æœŸæˆ–完全删除它们。"
+
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
-msgstr "如需根æ®é‡Œç¨‹ç¢‘æ¥å®‰æŽ’ epic çš„ %{epicDateType} 日期,请为 epic 中的任一议题指定带有 %{epicDateType} 日期的里程碑。"
+msgstr "如需根æ®é‡Œç¨‹ç¢‘æ¥å®‰æŽ’å²è¯—çš„ %{epicDateType} 日期,请为å²è¯—中的任一议题指定带有 %{epicDateType} 日期的里程碑。"
msgid "Epics|due"
msgstr "到期"
@@ -4231,7 +4961,7 @@ msgid "Error creating a new path"
msgstr "创建新路径时出错"
msgid "Error creating epic"
-msgstr "创建 epic 时出错"
+msgstr "创建 å²è¯— 时出错"
msgid "Error deleting %{issuableType}"
msgstr "删除 %{issuableType} 时出错"
@@ -4245,9 +4975,15 @@ msgstr "获å–标记时出错。"
msgid "Error fetching network graph."
msgstr "获å–网络图时出错。"
+msgid "Error fetching projects"
+msgstr "获å–项目时出错"
+
msgid "Error fetching refs"
msgstr "获å–refs时出错。"
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr "获å–使用情况(usage ping)æ•°æ®æ—¶å‡ºé”™ã€‚"
@@ -4257,6 +4993,12 @@ msgstr "加载分支数æ®å¤±è´¥ï¼Œè¯·é‡è¯•ã€‚"
msgid "Error loading branches."
msgstr "加载分支时出错。"
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr "加载文件查看器时出错。"
+
msgid "Error loading last commit."
msgstr "加载最åŽä¸€æ¬¡æ交失败。"
@@ -4266,6 +5008,9 @@ msgstr "加载Markdown预览时出错"
msgid "Error loading merge requests."
msgstr "加载åˆå¹¶è¯·æ±‚时出错。"
+msgid "Error loading milestone tab"
+msgstr "加载里程碑é¢æ¿æ—¶å‘生错误"
+
msgid "Error loading project data. Please try again."
msgstr "加载项目数æ®å¤±è´¥ï¼Œè¯·é‡è¯•ã€‚"
@@ -4275,20 +5020,26 @@ msgstr "加载模æ¿ç±»åž‹æ—¶å‡ºé”™ã€‚"
msgid "Error loading template."
msgstr "加载模æ¿æ—¶å‡ºé”™ã€‚"
+msgid "Error loading viewer"
+msgstr "加载查看器时出错"
+
+msgid "Error occurred when fetching sidebar data"
+msgstr "获å–侧边æ æ•°æ®æ—¶å‡ºé”™"
+
msgid "Error occurred when toggling the notification subscription"
msgstr "切æ¢é€šçŸ¥è®¢é˜…æ—¶å‘生错误"
msgid "Error occurred. User was not blocked"
-msgstr ""
+msgstr "å‘生了错误。用户未被ç¦ç”¨"
msgid "Error occurred. User was not confirmed"
-msgstr ""
+msgstr "å‘生了错误。用户尚未得到确认"
msgid "Error occurred. User was not unblocked"
-msgstr ""
+msgstr "å‘生了错误。用户未解除ç¦ç”¨"
msgid "Error occurred. User was not unlocked"
-msgstr ""
+msgstr "å‘生了错误。用户未解除é”定"
msgid "Error rendering markdown preview"
msgstr "渲染Markdown预览时出错"
@@ -4306,16 +5057,22 @@ msgid "Error updating todo status."
msgstr "更新待办事项状æ€æ—¶å‡ºé”™ã€‚"
msgid "Error uploading file"
-msgstr ""
+msgstr "上传文件时出错"
+
+msgid "Error uploading file: %{stripped}"
+msgstr "上传文件时出错: %{stripped}"
msgid "Error while loading the merge request. Please try again."
msgstr "加载åˆå¹¶è¯·æ±‚时出错。请å†è¯•ä¸€æ¬¡ã€‚"
+msgid "Error while loading the project data. Please try again."
+msgstr "加载项目数æ®æ—¶å‡ºé”™ã€‚请é‡è¯•ã€‚"
+
msgid "Error while migrating %{upload_id}: %{error_message}"
-msgstr ""
+msgstr "è¿ç§» %{upload_id} 时出错 : %{error_message}"
msgid "Error with Akismet. Please check the logs for more info."
-msgstr ""
+msgstr "Akismet 错误。请检查日志以获å–更多信æ¯ã€‚"
msgid "Error:"
msgstr "错误:"
@@ -4407,6 +5164,9 @@ msgstr "使用Jekyll创建GitLab Pages站点所需的一切。"
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr "使用纯HTML创建GitLab Pages网站所需的一切。"
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr "策略以外:"
@@ -4429,7 +5189,7 @@ msgid "Expiration date"
msgstr "到期时间"
msgid "Expired"
-msgstr ""
+msgstr "已过期"
msgid "Expired %{expiredOn}"
msgstr "已在 %{expiredOn} 过期"
@@ -4465,10 +5225,10 @@ msgid "Export issues"
msgstr "导出议题"
msgid "Export project"
-msgstr ""
+msgstr "导出项目"
msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
-msgstr ""
+msgstr "导出此项目åŠå…¶æ‰€æœ‰ç›¸å…³æ•°æ®ï¼Œä»¥ä¾¿å°†é¡¹ç›®ç§»åŠ¨åˆ°æ–°çš„GitLab实例。导出完æˆåŽï¼Œæ‚¨å¯ä»¥ä»Žâ€œæ–°å»ºé¡¹ç›®â€é¡µé¢å¯¼å…¥æ–‡ä»¶ã€‚"
msgid "External Classification Policy Authorization"
msgstr "外部分类政策授æƒ"
@@ -4494,6 +5254,27 @@ msgstr "分类标签"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "未设置分类标签的时候,将使用默认的分类标签`%{default_label}`。"
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr "å‘指标仪表æ¿æ·»åŠ ä¸€ä¸ªæŒ‰é’®ï¼Œç›´æŽ¥é“¾æŽ¥åˆ°æ‚¨çŽ°æœ‰çš„外部仪表æ¿ã€‚"
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr "输入您想è¦é“¾æŽ¥åˆ°ä»ªè¡¨ç›˜çš„ URL"
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr "外部仪表æ¿"
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr "完整的仪表盘URL"
+
+msgid "ExternalWikiService|External Wiki"
+msgstr "外部 Wiki"
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr "使用指å‘外部 Wiki 的链接替æ¢å†…部 Wiki 的链接。"
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr "外部Wiki的URL"
+
msgid "Facebook"
msgstr "Facebook"
@@ -4503,26 +5284,59 @@ msgstr "已失败"
msgid "Failed Jobs"
msgstr "失败的作业"
+msgid "Failed create wiki"
+msgstr "创建 Wiki 失败"
+
msgid "Failed to change the owner"
msgstr "无法å˜æ›´æ‰€æœ‰è€…"
msgid "Failed to check related branches."
msgstr "无法检查相关分支。"
+msgid "Failed to connect to the prometheus server"
+msgstr "无法连接PrometheusæœåŠ¡å™¨"
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr "创建åˆå¹¶è¯·æ±‚失败。请é‡è¯•ã€‚"
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr "无法为此问题创建分支。请å†è¯•ä¸€æ¬¡ã€‚"
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr "无法通过 gitlab-shell 创建仓库"
+
msgid "Failed to create resources"
-msgstr ""
+msgstr "创建资æºå¤±è´¥"
msgid "Failed to deploy to"
msgstr "无法部署到"
+msgid "Failed to get ref."
+msgstr "获å–ref失败。"
+
+msgid "Failed to install."
+msgstr "安装失败。"
+
msgid "Failed to load emoji list."
msgstr "无法加载表情列表。"
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr "无法从Sentry加载错误。错误消æ¯: %{errorMessage}"
+msgid "Failed to load groups & users."
+msgstr "加载群组和用户失败。"
+
+msgid "Failed to load related branches"
+msgstr "加载相关分支失败"
+
msgid "Failed to promote label due to internal error. Please contact administrators."
-msgstr ""
+msgstr "由于内部错误而无法å‡çº§æ ‡è®°ã€‚请è”系管ç†å‘˜ã€‚"
+
+msgid "Failed to protect the branch"
+msgstr "ä¿æŠ¤åˆ†æ”¯å¤±è´¥"
+
+msgid "Failed to protect the environment"
+msgstr "ä¿æŠ¤çŽ¯å¢ƒå¤±è´¥"
msgid "Failed to remove issue from board, please try again."
msgstr "无法从看æ¿ç§»é™¤è®®é¢˜ï¼Œè¯·é‡è¯•ã€‚"
@@ -4534,50 +5348,74 @@ msgid "Failed to remove the pipeline schedule"
msgstr "无法删除æµæ°´çº¿è®¡åˆ’"
msgid "Failed to remove user identity."
-msgstr ""
+msgstr "无法删除用户标识。"
msgid "Failed to remove user key."
-msgstr ""
+msgstr "无法删除用户密钥。"
msgid "Failed to reset key. Please try again."
msgstr "é‡ç½®å¯†é’¥å¤±è´¥ã€‚请é‡è¯•ã€‚"
+msgid "Failed to save comment!"
+msgstr "ä¿å­˜è¯„论失败ï¼"
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr "ä¿å­˜åˆå¹¶å†²çªè§£å†³åŠžæ³•å¤±è´¥ã€‚请é‡è¯•ï¼"
+
msgid "Failed to save new settings"
-msgstr ""
+msgstr "无法ä¿å­˜æ–°è®¾ç½®"
msgid "Failed to save preferences (%{error_message})."
-msgstr ""
+msgstr "无法ä¿å­˜å好设置(%{error_message})。"
msgid "Failed to save preferences."
-msgstr ""
+msgstr "无法ä¿å­˜å好设置。"
msgid "Failed to signing using smartcard authentication"
msgstr "无法使用智能å¡èº«ä»½éªŒè¯è¿›è¡Œç™»å½•"
+msgid "Failed to update branch!"
+msgstr "更新分支失败ï¼"
+
+msgid "Failed to update environment!"
+msgstr "更新环境失败ï¼"
+
msgid "Failed to update issues, please try again."
msgstr "更新议题失败, 请é‡è¯•"
+msgid "Failed to update tag!"
+msgstr "更新标签失败ï¼"
+
+msgid "Failed to update."
+msgstr "更新失败。"
+
+msgid "Failed to upgrade."
+msgstr "å‡çº§å¤±è´¥ã€‚"
+
msgid "Failed to upload object map file"
msgstr "上传对象映射文件失败"
msgid "Failure"
msgstr "失败"
-msgid "Fast-forward merge"
-msgstr ""
-
msgid "Fast-forward merge without a merge commit"
-msgstr "没有åˆå¹¶æ交的快进åˆå¹¶"
+msgstr "æ— åˆå¹¶æ交的快进å¼åˆå¹¶"
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr "速度更快,因其é‡ç”¨äº†é¡¹ç›®çš„工作空间(如果它ä¸å­˜åœ¨ï¼Œå°†å›žé€€åˆ°å…‹éš†ï¼‰"
msgid "Favicon was successfully removed."
-msgstr ""
+msgstr "网站图标已被æˆåŠŸåˆ é™¤ã€‚"
msgid "Feature Flags"
msgstr "功能标志"
+msgid "Feature flag was not removed."
+msgstr "功能标志未被删除。"
+
+msgid "Feature flag was successfully removed."
+msgstr "功能标志已æˆåŠŸåˆ é™¤ã€‚"
+
msgid "FeatureFlags|* (All Environments)"
msgstr "*(所有环境)"
@@ -4641,8 +5479,8 @@ msgstr "未å¯ç”¨"
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr "%{scope} çš„éžæ´»åŠ¨æ ‡å¿—"
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
-msgstr "安装 %{docs_link_start}兼容的客户端库%{docs_link_end} ,并在é…置指定API URLã€åº”用å称和实例ID。"
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
+msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr "实例ID"
@@ -4653,9 +5491,6 @@ msgstr "加载功能标志"
msgid "FeatureFlags|More Information"
msgstr "更多信æ¯"
-msgid "FeatureFlags|More information"
-msgstr "更多信æ¯"
-
msgid "FeatureFlags|Name"
msgstr "å称"
@@ -4666,7 +5501,7 @@ msgid "FeatureFlags|New Feature Flag"
msgstr "新建功能标志"
msgid "FeatureFlags|Protected"
-msgstr ""
+msgstr "å—ä¿æŠ¤"
msgid "FeatureFlags|Status"
msgstr "状æ€"
@@ -4693,16 +5528,16 @@ msgid "February"
msgstr "2月"
msgid "Fetching incoming email"
-msgstr ""
+msgstr "获å–接收邮件地å€"
msgid "Fetching licenses failed."
-msgstr ""
+msgstr "获å–许å¯è¯å¤±è´¥ã€‚"
msgid "Fetching licenses failed. The request endpoint was not found."
-msgstr ""
+msgstr "获å–许å¯è¯å¤±è´¥ã€‚找ä¸åˆ°è¯·æ±‚端点。"
msgid "Fetching licenses failed. You are not permitted to perform this action."
-msgstr ""
+msgstr "获å–许å¯è¯å¤±è´¥ã€‚当å‰æƒé™æ— æ³•æ‰§è¡Œæ­¤æ“作。"
msgid "Fields on this page are now uneditable, you can configure"
msgstr "当å‰é¡µé¢ä¸Šçš„字段ä¸å¯ç¼–辑,å¯ä»¥é…ç½®"
@@ -4735,6 +5570,12 @@ msgstr "文件上传错误。"
msgid "Files"
msgstr "文件"
+msgid "Files breadcrumb"
+msgstr "文件导航"
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr "æ交引用%{ref}路径%{path}中的文件,目录和å­æ¨¡å—"
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr "填写下é¢çš„字段,å¯ç”¨<strong>%{enable_label}</strong>,然åŽç‚¹å‡»<strong>%{save_changes}</strong>"
@@ -4754,7 +5595,7 @@ msgid "Filter by milestone name"
msgstr "按里程碑å称过滤"
msgid "Filter by two-factor authentication"
-msgstr "按åŒé‡èº«ä»½éªŒè¯è¿‡æ»¤"
+msgstr "按åŒé‡è®¤è¯è¿‡æ»¤"
msgid "Filter results by group"
msgstr "按群组过滤结果"
@@ -4783,6 +5624,9 @@ msgstr "查找新æå–çš„ <code>Takeout/Google Code项目托管/GoogleCodeProje
msgid "Fingerprint"
msgstr "指纹"
+msgid "Fingerprint:"
+msgstr "指纹:"
+
msgid "Fingerprints"
msgstr "指纹"
@@ -4792,6 +5636,9 @@ msgstr "先完æˆæ­¤æ¶ˆæ¯çš„编辑ï¼"
msgid "Finish review"
msgstr "完æˆè¯„审"
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr "完æˆæ‚¨çš„<strong>%{group_name}</strong>专用å¸æˆ·è®¾ç½®ã€‚"
+
msgid "Finished"
msgstr "已完æˆ"
@@ -4816,6 +5663,12 @@ msgstr "ä¿®å¤å¼€å§‹æ—¥æœŸ"
msgid "Fixed:"
msgstr "ä¿®å¤ï¼š"
+msgid "FlowdockService|Flowdock Git source token"
+msgstr "Flowdockçš„Gitæºä»¤ç‰Œ"
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr "Flowdock是一个é¢å‘技术团队å作的Web应用程åºã€‚"
+
msgid "FogBugz Email"
msgstr "FogBugz电å­é‚®ä»¶"
@@ -4841,7 +5694,7 @@ msgid "Footer message"
msgstr "页脚消æ¯"
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
-msgstr "对于内部项目,任何已登录的用户都å¯ä»¥æŸ¥çœ‹æµæ°´çº¿å¹¶è®¿é—®ä½œä¸šè¯¦æƒ…(输出日志和工件)"
+msgstr "对于内部项目,任何已登录的用户都å¯ä»¥æŸ¥çœ‹æµæ°´çº¿å¹¶è®¿é—®ä½œä¸šè¯¦æƒ…(输出日志和产物)"
msgid "For more info, read the documentation."
msgstr "有关详细信æ¯ï¼Œè¯·é˜…读文档。"
@@ -4856,10 +5709,19 @@ msgid "For more information, see the documentation on %{deactivating_usage_ping_
msgstr "欲了解更多相关信æ¯ï¼Œè¯·å‚阅 %{deactivating_usage_ping_link_start}使用情况检测(usage ping)%{deactivating_usage_ping_link_end}的文档。"
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr "对于ç§æœ‰é¡¹ç›®ï¼Œä»»ä½•æˆå‘˜ï¼ˆè®¿å®¢æˆ–更高级别)都å¯ä»¥æŸ¥çœ‹æµæ°´çº¿å¹¶è®¿é—®ä½œä¸šè¯¦æƒ…(输出日志和工件)"
+msgstr "对于ç§æœ‰é¡¹ç›®ï¼Œä»»ä½•æˆå‘˜ï¼ˆè®¿å®¢æˆ–更高级别)都å¯ä»¥æŸ¥çœ‹æµæ°´çº¿å¹¶è®¿é—®ä½œä¸šè¯¦æƒ…(输出日志和产物)"
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr "对于公开项目,任何人都å¯ä»¥æŸ¥çœ‹æµæ°´çº¿å¹¶è®¿é—®ä½œä¸šè¯¦æƒ…(输出日志和工件)"
+msgstr "对于公开项目,任何人都å¯ä»¥æŸ¥çœ‹æµæ°´çº¿å¹¶è®¿é—®ä½œä¸šè¯¦æƒ…(输出日志和产物)"
+
+msgid "Fork"
+msgstr "派生"
+
+msgid "Fork Error!"
+msgstr "派生错误ï¼"
+
+msgid "Fork project"
+msgstr "派生项目"
msgid "ForkedFromProjectPath|Forked from"
msgstr "派生自"
@@ -4870,6 +5732,9 @@ msgstr "派生自 %{project_name} (已删除)"
msgid "Forking in progress"
msgstr "派生(Fork)中"
+msgid "Forking repository"
+msgstr "仓库派生中"
+
msgid "Forks"
msgstr "派生"
@@ -4877,7 +5742,7 @@ msgid "Format"
msgstr "æ ¼å¼"
msgid "Forward external support email address to"
-msgstr ""
+msgstr "转å‘外部支æŒç”µå­é‚®ä»¶åœ°å€åˆ°"
msgid "Found errors in your %{gitlab_ci_yml}:"
msgstr "在您的 %{gitlab_ci_yml} 中找到错误:"
@@ -4888,8 +5753,11 @@ msgstr "在.gitlab-ci.yml中å‘现错误:"
msgid "Free Trial of GitLab.com Gold"
msgstr "å…费试用gitlab.comçš„Gold计划"
+msgid "Friday"
+msgstr "星期五"
+
msgid "From %{providerTitle}"
-msgstr "æ¥è‡ª%{providerTitle}"
+msgstr "%{providerTitle}æºåœ°å€"
msgid "From Bitbucket"
msgstr "æ¥è‡ªBitbucket"
@@ -4918,12 +5786,18 @@ msgstr "æ¥è‡ªé‡Œç¨‹ç¢‘:"
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr "在Kubernetes集群详细信æ¯è§†å›¾ä¸­ï¼Œä»Žåº”用程åºåˆ—表中安装Runner"
+msgid "Full name"
+msgstr "å…¨å"
+
msgid "GPG Key ID:"
msgstr "GPG密钥ID:"
msgid "GPG Keys"
msgstr "GPG 密钥"
+msgid "GPG keys allow you to verify signed commits."
+msgstr "GPG密钥å…许您对签åçš„æ交进行验è¯ã€‚"
+
msgid "GPG signature (loading...)"
msgstr "GPGç­¾å(加载中...)"
@@ -4943,7 +5817,7 @@ msgid "Generate key"
msgstr "生æˆå¯†é’¥"
msgid "Generate new export"
-msgstr ""
+msgstr "生æˆæ–°çš„导出"
msgid "Geo"
msgstr "Geo"
@@ -4988,7 +5862,7 @@ msgid "GeoNodes|Health status"
msgstr "è¿è¡ŒçŠ¶å†µçŠ¶æ€"
msgid "GeoNodes|Internal URL"
-msgstr ""
+msgstr "内部URL"
msgid "GeoNodes|Last event ID processed by cursor"
msgstr "游标处ç†çš„最åŽäº‹ä»¶ID"
@@ -5036,7 +5910,7 @@ msgid "GeoNodes|Out of sync"
msgstr "ä¸åŒæ­¥"
msgid "GeoNodes|Pausing replication stops the sync process."
-msgstr ""
+msgstr "æš‚åœå¤åˆ¶å°†åœæ­¢åŒæ­¥è¿›ç¨‹ã€‚"
msgid "GeoNodes|Removing a primary node stops the sync process for all nodes. Syncing cannot be resumed without losing some data on all secondaries. In this case we would recommend setting up all nodes from scratch. Are you sure?"
msgstr "删除主节点会åœæ­¢æ‰€æœ‰èŠ‚点的åŒæ­¥è¿›ç¨‹ã€‚如果ä¸ä¸¢å¤±æ‰€æœ‰è¾…助节点上的æŸäº›æ•°æ®ï¼Œåˆ™æ— æ³•æ¢å¤åŒæ­¥ã€‚在这ç§æƒ…况下,我们建议é‡æ–°è®¾ç½®æ‰€æœ‰èŠ‚点。你确定å—?"
@@ -5117,7 +5991,7 @@ msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
msgstr "已与主节点上对应项验è¯çš„Wiki"
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
-msgstr "使用 %{geo} ,您å¯ä»¥åœ¨ä»»ä½•åœ°æ–¹å®‰è£…特殊的åªè¯»å’Œå¤åˆ¶å®žä¾‹ã€‚在添加节点之å‰ï¼Œè¯·æŒ‰ç…§ %{instructions} 出现的确切顺åºæ‰§è¡Œ 。"
+msgstr "通过%{geo} ,您å¯ä»¥åœ¨ä»»ä½•åœ°æ–¹å®‰è£…特殊的åªè¯»å’Œå¤åˆ¶çš„GitLab实例。在添加节点之å‰ï¼Œè¯·ä¸¥æ ¼æŒ‰ç…§ %{instructions}中所列的顺åºæ‰§è¡Œ 。"
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
msgstr "当å‰Geo节点é…置使用ä¸å®‰å…¨çš„HTTP连接, 建议使用HTTPS。"
@@ -5150,19 +6024,19 @@ msgid "Geo|Choose which groups you wish to synchronize to this secondary node."
msgstr "选择è¦ä¸Žæ­¤è¾…助节点åŒæ­¥çš„群组。"
msgid "Geo|Control the maximum concurrency of LFS/attachment backfill for this secondary node"
-msgstr "控制此辅助节点的 LFS/附件 回写的最大并å‘"
+msgstr "控制此辅助节点的 LFS/附件回写的最大并å‘"
msgid "Geo|Control the maximum concurrency of verification operations for this Geo node"
msgstr "控制此 Geo 节点的验è¯æ“作的最大并å‘"
msgid "Geo|Control the minimum interval in days that a repository should be reverified for this primary node"
-msgstr "控制此主节点é‡æ–°éªŒè¯å­˜å‚¨åº“的最å°é—´éš”天数"
+msgstr "控制此主节点é‡æ–°éªŒè¯ä»“库的最å°é—´éš”天数"
msgid "Geo|Could not remove tracking entry for an existing project."
msgstr "无法删除现有项目的跟踪æ¡ç›®ã€‚"
msgid "Geo|Could not remove tracking entry for an existing upload."
-msgstr ""
+msgstr "无法删除现有上传的跟踪æ¡ç›®ã€‚"
msgid "Geo|Failed"
msgstr "失败"
@@ -5180,10 +6054,10 @@ msgid "Geo|In sync"
msgstr "å·²åŒæ­¥"
msgid "Geo|Internal URL"
-msgstr ""
+msgstr "内部 URL"
msgid "Geo|Last repository check run"
-msgstr "上次存储库的è¿è¡Œæ£€æŸ¥"
+msgstr "上次仓库的è¿è¡Œæ£€æŸ¥"
msgid "Geo|Last successful sync"
msgstr "最近一次æˆåŠŸçš„åŒæ­¥"
@@ -5213,10 +6087,10 @@ msgid "Geo|Pending verification"
msgstr "待验è¯"
msgid "Geo|Please refer to Geo Troubleshooting."
-msgstr ""
+msgstr "请å‚阅 Geo 疑难解答。"
msgid "Geo|Project"
-msgstr ""
+msgstr "项目"
msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
msgstr "项目(ID: %{project_id})å·²ä¸å†å­˜åœ¨äºŽä¸»èŠ‚点。 当å‰é¡¹å¯ä»¥è¢«å®‰å…¨çš„删除,因为这并ä¸ä¼šåˆ é™¤ä»»ä½•ç£ç›˜ä¸Šçš„有用数æ®ã€‚"
@@ -5267,19 +6141,25 @@ msgid "Geo|Status"
msgstr "状æ€"
msgid "Geo|Sync"
-msgstr ""
+msgstr "åŒæ­¥"
msgid "Geo|Synced"
msgstr "åŒæ­¥"
msgid "Geo|Synced at"
-msgstr ""
+msgstr "åŒæ­¥äºŽ"
msgid "Geo|Synchronization failed - %{error}"
msgstr "åŒæ­¥å¤±è´¥ - %{error}"
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
-msgstr ""
+msgstr "在主节点上定义的URL,辅助节点应使用该URL与其è”系。如果未设置,则返回“urlâ€"
+
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr "æ•°æ®åº“当å‰è½åŽäºŽä¸»èŠ‚点%{db_lag}。"
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr "当å‰èŠ‚点è½åŽäºŽä¸»èŠ‚点%{minutes_behind}。"
msgid "Geo|This is a primary node"
msgstr "这是主节点"
@@ -5288,7 +6168,7 @@ msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
msgstr "å·²æˆåŠŸåˆ é™¤é¡¹ç›® (%{project_id}) 的跟踪项。"
msgid "Geo|Tracking entry for upload (%{type}/%{id}) was successfully removed."
-msgstr ""
+msgstr "上传 (%{type}/%{id}) 跟踪æ¡ç›®å·²æˆåŠŸåˆ é™¤ã€‚"
msgid "Geo|Tracking entry will be removed. Are you sure?"
msgstr "跟踪项将被删除。 确定继续å—?"
@@ -5336,7 +6216,10 @@ msgid "Git"
msgstr "Git"
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
-msgstr ""
+msgstr "æ­¤ GitLab æœåŠ¡å™¨ä¸Šæœªå¯ç”¨ Git LFS,请è”系管ç†å‘˜ã€‚"
+
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr "如果 %{docs_link_start}为项目å¯ç”¨%{docs_link_end}了LFS,则Git LFS对象将在拉å–é•œåƒæ—¶åŒæ­¥ï¼Œ 但<strong>ä¸ä¼š</strong> 在推é€é•œåƒæ—¶åŒæ­¥ã€‚"
msgid "Git global setup"
msgstr "Git 全局设置"
@@ -5347,6 +6230,9 @@ msgstr "Git仓库URL"
msgid "Git revision"
msgstr "Gitæ交版本"
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr "æµæ°´çº¿çš„Gitç­–ç•¥"
@@ -5360,7 +6246,7 @@ msgid "GitLab CI Linter has been moved"
msgstr "GitLab CI Linter已被转移"
msgid "GitLab Enterprise Edition %{plan}"
-msgstr ""
+msgstr "GitLab ä¼ä¸šç‰ˆ %{plan}"
msgid "GitLab Geo"
msgstr "GitLab Geo"
@@ -5378,7 +6264,7 @@ msgid "GitLab User"
msgstr "GitLab用户"
msgid "GitLab allows you to continue using your license even if you exceed the number of seats you purchased. You will be required to pay for these seats when you renew your license."
-msgstr ""
+msgstr "å³ä½¿ç³»ç»Ÿä¸­çš„用户数已ç»è¶…过了许å¯ä¸­çš„数目,GitLabä¾ç„¶å…许继续使用当å‰è®¸å¯ã€‚续订许å¯æ—¶ï¼Œæ‚¨éœ€è¦æ”¯ä»˜è¿™äº›ç”¨æˆ·çš„费用。"
msgid "GitLab metadata URL"
msgstr "GitLab å…ƒæ•°æ® URL"
@@ -5417,7 +6303,10 @@ msgid "Gitea Import"
msgstr "从Gitea导入"
msgid "Given access %{time_ago}"
-msgstr "%{time_ago} 之å‰æŽˆæƒè®¿é—®"
+msgstr "%{time_ago}授æƒè®¿é—®"
+
+msgid "Global notification settings"
+msgstr "全局通知设置"
msgid "Go Back"
msgstr "返回"
@@ -5437,8 +6326,17 @@ msgstr "转到"
msgid "Go to %{link_to_google_takeout}."
msgstr "转至 %{link_to_google_takeout}。"
+msgid "Go to parent"
+msgstr "转到上一级"
+
msgid "Go to project"
-msgstr "转到项目"
+msgstr "跳转到项目"
+
+msgid "Go to your fork"
+msgstr "跳转到你的派生项目"
+
+msgid "Golden Tanuki"
+msgstr ""
msgid "Google Code import"
msgstr "从Google Code导入"
@@ -5465,10 +6363,10 @@ msgid "Group"
msgstr "群组"
msgid "Group %{group_name} was scheduled for deletion."
-msgstr ""
+msgstr "群组%{group_name}已安排删除。"
msgid "Group %{group_name} was successfully created."
-msgstr ""
+msgstr "群组 %{group_name} å·²æˆåŠŸåˆ›å»ºã€‚"
msgid "Group CI/CD settings"
msgstr "群组 CI/CD 设置"
@@ -5480,7 +6378,7 @@ msgid "Group ID"
msgstr "群组 ID"
msgid "Group ID: %{group_id}"
-msgstr "群组 ID:%{group_id}"
+msgstr "群组ID:%{group_id}"
msgid "Group Runners"
msgstr "群组Runner"
@@ -5515,8 +6413,11 @@ msgstr "群组å称"
msgid "Group overview content"
msgstr "群组概述内容"
+msgid "Group pipeline minutes were successfully reset."
+msgstr "群组æµæ°´çº¿åˆ†é’Ÿæ•°å·²æˆåŠŸé‡ç½®ã€‚"
+
msgid "Group was successfully updated."
-msgstr ""
+msgstr "群组已æˆåŠŸæ›´æ–°ã€‚"
msgid "Group:"
msgstr "群组:"
@@ -5524,23 +6425,26 @@ msgstr "群组:"
msgid "Group: %{group_name}"
msgstr "群组:%{group_name}"
+msgid "Group: %{name}"
+msgstr "群组: %{name}"
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr "从 %{dateWord} 起"
msgid "GroupRoadmap|Something went wrong while fetching epics"
-msgstr "è¯»å– epic 时出错"
+msgstr "è¯»å– å²è¯— 时出错"
msgid "GroupRoadmap|Sorry, no epics matched your search"
-msgstr "对ä¸èµ·ï¼Œæœªæœç´¢åˆ°ä»»ä½•ç¬¦åˆæ¡ä»¶çš„ epic"
+msgstr "对ä¸èµ·ï¼Œæœªæœç´¢åˆ°ä»»ä½•ç¬¦åˆæ¡ä»¶çš„ å²è¯—"
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
-msgstr "路线图显示了epic 沿ç€æ—¶é—´çº¿çš„进展情况"
+msgstr "路线图显示了å²è¯— 沿ç€æ—¶é—´çº¿çš„进展情况"
msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of the %{linkStart}child epics%{linkEnd}."
-msgstr ""
+msgstr "è¦æŸ¥çœ‹è·¯çº¿å›¾ï¼Œè¯·è‡³å°‘为一个%{linkStart}å­å²è¯—%{linkEnd}添加开始或截止日期。"
msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
-msgstr "è¦æŸ¥çœ‹è·¯çº¿å›¾ï¼Œè¯·åœ¨æ­¤ç¾¤ç»„或其å­ç¾¤ç»„中的一个 epic 中添加开始日期或截止日期;从 %{startDate} 到 %{endDate}。"
+msgstr "è¦æŸ¥çœ‹è·¯çº¿å›¾ï¼Œè¯·åœ¨æ­¤ç¾¤ç»„或其å­ç¾¤ç»„中的一个 å²è¯— 中添加开始日期或截止日期;从 %{startDate} 到 %{endDate}。"
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
msgstr "è¦æ‰©å¤§æ‚¨çš„æœç´¢ï¼Œè¯·æ›´æ”¹æˆ–移除过滤器,从 %{startDate} 到 %{endDate}。"
@@ -5549,64 +6453,73 @@ msgid "GroupRoadmap|Until %{dateWord}"
msgstr "直到 %{dateWord}"
msgid "GroupSAML|Certificate fingerprint"
-msgstr ""
+msgstr "è¯ä¹¦æŒ‡çº¹"
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
-msgstr ""
+msgid "GroupSAML|Enable SAML authentication for this group."
+msgstr "为此群组å¯ç”¨SAML身份验è¯ã€‚"
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
-msgstr ""
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgstr "为此群组强制执行仅SSO身份验è¯ã€‚"
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
+msgstr "强制用户为该群组设置专用的由群组管ç†å¸æˆ·ã€‚"
msgid "GroupSAML|Enforced SSO"
-msgstr ""
+msgstr "强制 SSO"
msgid "GroupSAML|Generate a SCIM token"
-msgstr ""
+msgstr "ç”Ÿæˆ SCIM 令牌"
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
-msgstr ""
-
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
+msgstr "ç”Ÿæˆ SCIM 令牌以设置系统进行跨域身份管ç†ã€‚"
msgid "GroupSAML|Identity provider single sign on URL"
-msgstr ""
+msgstr "身份验è¯æ供商å•ç‚¹ç™»å½• URL"
msgid "GroupSAML|Make sure you save this token — you won't be able to access it again."
-msgstr ""
+msgstr "请妥善ä¿å­˜æ­¤ä»¤ç‰Œ-您将无法å†æ¬¡è®¿é—®å®ƒçš„内容。"
msgid "GroupSAML|Manage your group’s membership while adding another level of security with SAML."
-msgstr ""
+msgstr "通过SAML管ç†ç¾¤ç»„æˆå‘˜ï¼Œè¿›ä¸€æ­¥æ高安全性。"
msgid "GroupSAML|Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
-msgstr ""
+msgstr "群组æˆå‘˜åœ¨ç™»å½•æ‚¨çš„群组时会跳转到此处。请从您的身份认è¯æ供商处获得该信æ¯ã€‚它å¯èƒ½å«åšâ€œSSOæœåŠ¡ä½ç½®ï¼ˆSSO Service Location)â€ï¼Œâ€œSAML令牌é¢å‘点(SAML Token Issuance Endpoint)â€æˆ–“SAML 2.0/W-Federation URLâ€ã€‚"
msgid "GroupSAML|SAML Single Sign On"
-msgstr ""
+msgstr "SAML å•ç‚¹ç™»å½•"
msgid "GroupSAML|SAML Single Sign On Settings"
-msgstr ""
+msgstr "SAML å•ç‚¹ç™»å½•è®¾ç½®"
msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
+msgstr "SCIM API 端点 URL"
msgid "GroupSAML|SCIM Token"
-msgstr ""
+msgstr "SCIM 令牌"
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
-msgstr ""
+msgstr "SAML令牌签åè¯ä¹¦çš„SHA1指纹。请从身份验è¯æ供商处获å–(也å¯ä»¥è¢«ç§°ä¸ºâ€œæ‹‡æŒ‡çº¹â€ï¼‰ã€‚"
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
+msgstr "SCIM 令牌现在已éšè—。è¦å†æ¬¡æŸ¥çœ‹ä»¤ç‰Œçš„å€¼ï¼Œæ‚¨éœ€è¦ "
+
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr "为了能够å¯ç”¨å¼ºåˆ¶SSO,首先需è¦å¯ç”¨SAML身份验è¯ã€‚"
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr "为了能够å¯ç”¨ç”±ç¾¤ç»„管ç†å¸æˆ·ï¼Œé¦–先需è¦å¯ç”¨å¼ºåˆ¶SSO。"
msgid "GroupSAML|Toggle SAML authentication"
-msgstr ""
+msgstr "åˆ‡æ¢ SAML 身份验è¯"
+
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr "å¯ç”¨ç”±ç¾¤ç»„管ç†å¸æˆ·åŽï¼Œæ‰€æœ‰æ²¡æœ‰ç”±ç¾¤ç»„管ç†å¸æˆ·çš„用户将被从群组中排除在外。"
msgid "GroupSAML|Your SCIM token"
-msgstr ""
+msgstr "您的 SCIM 令牌"
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr "已为群组更新 Auto DevOps æµæ°´çº¿"
@@ -5633,7 +6546,7 @@ msgid "GroupSettings|Learn more about group-level project templates."
msgstr "了解更多关于群组级项目模æ¿"
msgid "GroupSettings|New runners registration token has been generated!"
-msgstr ""
+msgstr "已生æˆæ–°çš„Runner注册令牌ï¼"
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "ç¦æ­¢ä¸Žå…¶ä»–群组共享 %{group} 中的项目"
@@ -5668,6 +6581,9 @@ msgstr "从 %{ancestor_group_name} 中删除共享群组é”"
msgid "Groups"
msgstr "群组"
+msgid "Groups (%{count})"
+msgstr "群组(%{count})"
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr "也å¯ä»¥é€šè¿‡åˆ›å»º %{subgroup_docs_link_start}å­ç¾¤ç»„æ¥åµŒå¥—群组%{subgroup_docs_link_end}。"
@@ -5720,10 +6636,10 @@ msgid "GroupsTree|Edit group"
msgstr "编辑群组"
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
-msgstr "无法离开群组。请确ä¿æ‚¨ä¸æ˜¯å”¯ä¸€çš„所有者。"
+msgstr "无法退出群组。请确ä¿æ‚¨ä¸æ˜¯å”¯ä¸€çš„群组所有者。"
msgid "GroupsTree|Leave this group"
-msgstr "离开这个群组"
+msgstr "退出此群组"
msgid "GroupsTree|Loading groups"
msgstr "加载群组中"
@@ -5737,11 +6653,14 @@ msgstr "没有任何群组或项目符åˆæ‚¨çš„æœç´¢"
msgid "GroupsTree|Search by name"
msgstr "按å称æœç´¢"
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr "HTTP Basic:访问被拒ç»\\n您必须使用具有'api'æƒé™çš„个人访问令牌。\\n您å¯ä»¥åœ¨ %{profile_personal_access_tokens_url}中生æˆä¸€ä¸ª"
+
msgid "Have your users email"
msgstr "请让用户å‘é€ç”µå­é‚®ä»¶è‡³"
msgid "Header logo was successfully removed."
-msgstr ""
+msgstr "标题徽标已æˆåŠŸåˆ é™¤ã€‚"
msgid "Header message"
msgstr "页头消æ¯"
@@ -5764,6 +6683,9 @@ msgstr "未检测到è¿è¡ŒçŠ¶å†µé—®é¢˜"
msgid "HealthCheck|Unhealthy"
msgstr "éžå¥åº·"
+msgid "Hello there"
+msgstr "你好"
+
msgid "Help"
msgstr "帮助"
@@ -5773,21 +6695,27 @@ msgstr "帮助页é¢"
msgid "Help page text and support page url."
msgstr "帮助页é¢æ–‡æœ¬å’Œæ”¯æŒé¡µé¢ç½‘å€ã€‚"
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
-msgstr "以下是需è¦æ·»åŠ åˆ°è¿œç¨‹æœåŠ¡å™¨çš„SSH公钥。有关更多信æ¯ï¼Œè¯·å‚阅文档。"
+msgid "Hide archived projects"
+msgstr "éšè—已归档的项目"
msgid "Hide file browser"
msgstr "éšè—文件æµè§ˆå™¨"
+msgid "Hide group projects"
+msgstr "éšè—群组项目"
+
msgid "Hide host keys manual input"
msgstr "éšè—主机密钥手动输入"
msgid "Hide marketing-related entries from help"
-msgstr "从帮助中éšè—与è¥é”€æœ‰å…³çš„æ¡ç›®"
+msgstr "在帮助中éšè—与市场推广有关的æ¡ç›®"
msgid "Hide payload"
msgstr "éšè—上传数æ®"
+msgid "Hide shared projects"
+msgstr "éšè—共享项目"
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "éšè—值"
@@ -5796,19 +6724,25 @@ msgid "Hide values"
msgstr "éšè—值"
msgid "Highest role:"
-msgstr ""
+msgstr "顶级角色:"
msgid "History"
msgstr "历å²"
+msgid "History of authentications"
+msgstr "身份验è¯çš„历å²"
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr "Hook 执行失败。确ä¿ç¾¤ç»„有一个包å«æ交的项目。"
+
msgid "Hook was successfully created."
-msgstr ""
+msgstr "Hook å·²æˆåŠŸåˆ›å»ºã€‚"
msgid "Hook was successfully updated."
-msgstr ""
+msgstr "é’©å­å·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Housekeeping"
-msgstr ""
+msgstr "例行维护"
msgid "Housekeeping successfully started"
msgstr "已开始维护"
@@ -5816,6 +6750,12 @@ msgstr "已开始维护"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr "管家,导出,路径,转移,删除,存档。"
+msgid "How many replicas each Elasticsearch shard has."
+msgstr "æ¯ä¸ªElasticsearch分片有多少个副本。"
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr "å°†Elasticsearch索引拆分æˆå¤šå°‘个分片。"
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr "但是,您已ç»æ˜¯ %{member_source} çš„æˆå‘˜ã€‚请使用其他å¸æˆ·ç™»å½•ä»¥æŽ¥å—邀请。"
@@ -5825,6 +6765,12 @@ msgstr "æˆ‘æŽ¥å— %{terms_link}"
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr "æœåŠ¡æ¡æ¬¾å’Œéšç§æ”¿ç­–"
+msgid "I forgot my password"
+msgstr "我忘记了密ç "
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr "我已阅读并åŒæ„Let's Encrypt %{link_start}æœåŠ¡æ¡æ¬¾%{link_end}"
+
msgid "ID"
msgstr "ID"
@@ -5894,11 +6840,20 @@ msgstr "如果已å¯ç”¨"
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr "如果å¯ç”¨ï¼Œåˆ™ä½¿ç”¨å¤–部æœåŠ¡ä¸Šçš„分类标签æ¥éªŒè¯å¯¹é¡¹ç›®çš„访问æƒé™ã€‚"
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr "如果这是一个错误,你å¯ä»¥%{leave_link_start}退出%{source_type}%{link_end}。"
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr "如果这是一个错误,你å¯ä»¥é€€å‡º%{source_type}。"
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr "如使用 GitHub,GitHubçš„æ交(commits)和拉å–请求(pull request) 页é¢å°†æ˜¾ç¤ºæµæ°´çº¿çŠ¶æ€ã€‚ %{more_info_link}"
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
-msgstr "如果HTTP仓库ä¸å¯å…¬å¼€è®¿é—®ï¼Œè¯·å°†èº«ä»½éªŒè¯ä¿¡æ¯æ·»åŠ åˆ°URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr "如果您丢失了æ¢å¤ç ï¼Œæ‚¨å¯ä»¥ç”Ÿæˆæ–°çš„æ¢å¤ç ï¼Œæ‰€æœ‰ä»¥å‰çš„æ¢å¤ç å°†å¤±æ•ˆã€‚"
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
+msgstr "如果您的HTTP仓库无法公开访问,需在地å€ä¸­æ·»åŠ å‡­æ®ã€‚"
msgid "ImageDiffViewer|2-up"
msgstr "并列(2-up)"
@@ -5910,7 +6865,7 @@ msgid "ImageDiffViewer|Swipe"
msgstr "滑动"
msgid "Impersonation has been disabled"
-msgstr "模拟已被ç¦ç”¨"
+msgstr "身份模拟已被ç¦ç”¨"
msgid "Import"
msgstr "导入"
@@ -5970,7 +6925,7 @@ msgid "Import projects from Google Code"
msgstr "从Google Code导入项目"
msgid "Import repositories from Bitbucket Server"
-msgstr "从Bitbucket导入存储库"
+msgstr "从Bitbucket导入仓库"
msgid "Import repositories from GitHub"
msgstr "从 GitHub 导入仓库"
@@ -5978,6 +6933,12 @@ msgstr "从 GitHub 导入仓库"
msgid "Import repository"
msgstr "导入仓库"
+msgid "Import tasks"
+msgstr "导入任务"
+
+msgid "Import tasks from Phabricator into issues"
+msgstr "从Pharbricator导入任务到议题"
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr "导入超时。耗时已超过 %{import_jobs_expiration} 秒"
@@ -5987,23 +6948,38 @@ msgstr "导入/导出æ’图"
msgid "ImportButtons|Connect repositories from"
msgstr "用以下方å¼è¿žæŽ¥å‚¨å­˜åº“"
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr "ç¦æ­¢çš„导入URL: %{message}"
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr "将仓库 %{project_safe_import_url} 导入到 %{project_full_path} 时出错:%{message}"
+
msgid "ImportProjects|Importing the project failed"
msgstr "导入项目失败"
msgid "ImportProjects|Requesting your %{provider} repositories failed"
-msgstr "获å–您的%{provider}存储库失败"
+msgstr "获å–您的%{provider}仓库失败"
msgid "ImportProjects|Select the projects you want to import"
msgstr "选择è¦å¯¼å…¥çš„项目"
+msgid "ImportProjects|The remote data could not be imported."
+msgstr "无法导入远程数æ®ã€‚"
+
+msgid "ImportProjects|The repository could not be created."
+msgstr "无法创建仓库。"
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr "更新已导入的项目失败"
+msgid "Improve Issue boards"
+msgstr "增强议题看æ¿"
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr "使用 GitLab ä¼ä¸šç‰ˆçš„增强议题看æ¿ã€‚"
msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
-msgstr ""
+msgstr "使用GitLab Enterprise Edition以获得增强的åˆå¹¶è¯·æ±‚功能和官方客户支æŒã€‚"
msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
msgstr "使用GitLab ä¼ä¸šç‰ˆè®®é¢˜æƒé‡å¸¦æ¥çš„增强议题管ç†åŠŸèƒ½ã€‚"
@@ -6050,12 +7026,21 @@ msgstr "包括一个MVC 结构,mvw å’Œ pom.xml æ¥å¸®åŠ©æ‚¨å¼€å§‹ã€‚"
msgid "Incompatible Project"
msgstr "ä¸å…¼å®¹çš„项目"
+msgid "Incompatible options set!"
+msgstr "设置了ä¸å…¼å®¹çš„选项ï¼"
+
+msgid "Indexing"
+msgstr "正在索引"
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr "指示此runner是å¦å¯ä»¥é€‰æ‹©æ— æ ‡è®°çš„作业"
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr "通知用户没有上传 SSH 密钥,如果没有 SSH 秘钥,将无法通过 SSH 推é€ã€‚"
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr "其他Pages模æ¿çš„ä¿¡æ¯åŠå®‰è£…指å—å¯ä»¥åœ¨%{pages_getting_started_guide}中找到."
+
msgid "Inline"
msgstr "内è”"
@@ -6063,7 +7048,7 @@ msgid "Input host keys manually"
msgstr "手动输入主机密钥"
msgid "Input your repository URL"
-msgstr "输入您的存储库URL"
+msgstr "输入您的仓库URL"
msgid "Insert a quote"
msgstr "æ’入引用"
@@ -6077,18 +7062,30 @@ msgstr "æ’入建议"
msgid "Insights"
msgstr "洞察"
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr "安装GitLab Runner"
msgid "Install Runner on Kubernetes"
msgstr "在Kubernetes上安装Runner"
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr "请先从您的应用程åºåº“安装软件令牌验è¯å™¨ï¼Œå¦‚%{free_otp_link}或者谷歌验è¯å™¨ï¼Œç„¶åŽæ‰«æ这个QRç ã€‚更多信æ¯å¯ä»¥åœ¨æ­¤%{help_link_start}文档%{help_link_end}中找到。"
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] "实例"
msgid "Instance Statistics"
-msgstr "实例统计"
+msgstr "本站统计"
msgid "Instance Statistics visibility"
msgstr "实例统计信æ¯å¯è§æ€§"
@@ -6097,7 +7094,7 @@ msgid "Instance does not support multiple Kubernetes clusters"
msgstr "实例ä¸æ”¯æŒå¤šä¸ªKubernetes集群"
msgid "Instance license"
-msgstr ""
+msgstr "实例许å¯è¯"
msgid "Integrations"
msgstr "集æˆ"
@@ -6106,7 +7103,7 @@ msgid "Integrations Settings"
msgstr "集æˆè®¾ç½®"
msgid "Interested parties can even contribute by pushing commits if they want to."
-msgstr "相关人员甚至å¯ä»¥é€šè¿‡æŽ¨é€æ交æ¥ä¸ºé¡¹ç›®ä½œå‡ºè´¡çŒ®ã€‚"
+msgstr "用户å¯ä»¥é€šè¿‡æŽ¨é€æ交æ¥å¯¹é¡¹ç›®ä½œå‡ºè´¡çŒ®ã€‚"
msgid "Internal"
msgstr "内部"
@@ -6127,29 +7124,56 @@ msgid "Introducing Cycle Analytics"
msgstr "周期分æžç®€ä»‹"
msgid "Introducing Your Conversational Development Index"
-msgstr "介ç»æ‚¨çš„会è¯å‘展指数"
+msgstr "了解您的会è¯å¼€å‘指数"
+
+msgid "Invalid Insights config file detected"
+msgstr "检测到无效的 Insights é…置文件"
msgid "Invalid Login or password"
+msgstr "登录å或密ç æ— æ•ˆ"
+
+msgid "Invalid date"
msgstr ""
+msgid "Invalid feature"
+msgstr "无效的功能"
+
+msgid "Invalid field"
+msgstr "无效字段。"
+
msgid "Invalid file."
-msgstr ""
+msgstr "无效的文件。"
+
+msgid "Invalid import params"
+msgstr "无效导入å‚æ•°"
msgid "Invalid input, please avoid emojis"
-msgstr "输入无效,请é¿å…使用emoji符å·"
+msgstr "输入无效,请é¿å…使用表情符å·"
msgid "Invalid pin code"
+msgstr "无效的 pin ç "
+
+msgid "Invalid query"
msgstr ""
-msgid "Invalid two-factor code."
+msgid "Invalid repository path"
+msgstr "无效的仓库路径"
+
+msgid "Invalid server response"
msgstr ""
+msgid "Invalid two-factor code."
+msgstr "无效的åŒé‡è®¤è¯ç ã€‚"
+
msgid "Invitation"
msgstr "邀请"
msgid "Invite"
msgstr "邀请"
+msgid "Invite \"%{trimmed}\" by email"
+msgstr "通过电å­é‚®ä»¶é‚€è¯·â€œ%{trimmed}â€"
+
msgid "Invite group"
msgstr "邀请群组"
@@ -6162,6 +7186,9 @@ msgstr "调用计数"
msgid "Invoke Time"
msgstr "调用时间"
+msgid "Is using license seat:"
+msgstr "正在使用许å¯è¯ï¼š"
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr "已关闭(%{moved_link_start}已移动%{moved_link_end})"
@@ -6180,6 +7207,12 @@ msgstr "议题事件"
msgid "Issue template (optional)"
msgstr "è®®é¢˜æ¨¡æ¿ (å¯é€‰)"
+msgid "Issue update failed"
+msgstr "议题更新失败"
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr "看æ¿"
@@ -6211,7 +7244,7 @@ msgid "Issues closed"
msgstr "关闭议题"
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
-msgstr ""
+msgstr "议题评论,åˆå¹¶è¯·æ±‚的差异和评论,标记,里程碑,代ç ç‰‡æ®µå’Œå…¶ä»–项目实体"
msgid "Issues, merge requests, pushes, and comments."
msgstr "议题,åˆå¹¶è¯·æ±‚,推é€åŠè¯„论。"
@@ -6241,7 +7274,7 @@ msgid "It must have a header row and at least two columns: the first column is t
msgstr "它必须有标题行和至少有两列:第一æ æ˜¯è®®é¢˜æ ‡é¢˜ï¼Œç¬¬äºŒæ æ˜¯è®®é¢˜æ述。自动检测分隔符。"
msgid "It's you"
-msgstr "这是您"
+msgstr "你自己"
msgid "Jaeger URL"
msgstr "Jaeger 地å€"
@@ -6255,11 +7288,53 @@ msgstr "1月"
msgid "January"
msgstr "1月"
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr "%{noteable_model_name} 事件已ç¦ç”¨ã€‚"
+
+msgid "JiraService|If different from Web URL"
+msgstr "如果与 Web URL ä¸åŒ"
+
+msgid "JiraService|JIRA API URL"
+msgstr "JIRA API URL"
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr "在æ交中引用议题时将创建 JIRA 评论。"
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr "在åˆå¹¶è¯·æ±‚中引用议题时将创建 JIRA 评论。"
+
+msgid "JiraService|Jira issue tracker"
+msgstr "Jira 议题跟踪"
+
+msgid "JiraService|Password or API token"
+msgstr "密ç æˆ– API 令牌"
+
+msgid "JiraService|Transition ID(s)"
+msgstr "转æ¢ID"
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr "使用“, â€æˆ–“; â€åˆ†éš”多个转æ¢ID"
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr "为æœåŠ¡å™¨ç‰ˆæœ¬ä½¿ç”¨å¯†ç , 为云版本使用 API 令牌"
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr "为æœåŠ¡å™¨ç‰ˆæœ¬ä½¿ç”¨ç”¨æˆ·å,为云版本使用电å­é‚®ä»¶"
+
+msgid "JiraService|Username or Email"
+msgstr "用户å或电å­é‚®ä»¶"
+
+msgid "JiraService|Web URL"
+msgstr "Web URL"
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr "转æ¢IDåªèƒ½åŒ…å«æ•°å­—或用“, â€æˆ–“; â€åˆ†éš”çš„æ•°å­—"
+
msgid "Job"
msgstr "作业"
msgid "Job Failed #%{build_id}"
-msgstr ""
+msgstr "作业 #%{build_id} 已失败 "
msgid "Job ID"
msgstr "作业 ID"
@@ -6268,19 +7343,19 @@ msgid "Job has been erased"
msgstr "作业已被删除"
msgid "Job has been successfully erased!"
-msgstr ""
+msgstr "作业已æˆåŠŸåˆ é™¤!"
msgid "Job has wrong arguments format."
-msgstr ""
+msgstr "作业的å‚æ•°æ ¼å¼é”™è¯¯ã€‚"
msgid "Job is missing the `model_type` argument."
-msgstr ""
+msgstr "作业缺少 `model_type` å‚数。"
msgid "Job is stuck. Check runners."
-msgstr "作业å¡ä½äº†ã€‚请检查è¿è¡Œå™¨ã€‚"
+msgstr "作业已å¡ä½ã€‚请检查Runner。"
msgid "Job traces and artifacts"
-msgstr ""
+msgstr "作业日志和产物"
msgid "Job was retried"
msgstr "作业已é‡è¯•"
@@ -6313,7 +7388,7 @@ msgid "Job|Keep"
msgstr "ä¿æŒ"
msgid "Job|Pipeline"
-msgstr ""
+msgstr "æµæ°´çº¿"
msgid "Job|Scroll to bottom"
msgstr "滚动到底部"
@@ -6328,22 +7403,22 @@ msgid "Job|The artifacts were removed"
msgstr "作业产物已被删除"
msgid "Job|The artifacts will be removed"
-msgstr "工件将被删除"
+msgstr "产物将被删除"
msgid "Job|This job failed because the necessary resources were not successfully created."
-msgstr ""
+msgstr "此作业已失败, 因为未æˆåŠŸåˆ›å»ºå¿…è¦çš„资æºã€‚"
msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
-msgstr "此作业å¡ä½äº†ï¼Œå› ä¸ºè¯¥é¡¹ç›®æ²¡æœ‰åœ¨çº¿åˆ†é…任何è¿è¡Œå™¨ã€‚"
+msgstr "此作业已å¡ä½ï¼Œå› ä¸ºè¯¥é¡¹ç›®æ²¡æœ‰åˆ†é…任何å¯ç”¨Runner。"
msgid "Job|for"
-msgstr ""
+msgstr "于"
msgid "Job|into"
-msgstr ""
+msgstr "åˆå¹¶å…¥"
msgid "Job|with"
-msgstr ""
+msgstr "ç”±"
msgid "Jul"
msgstr "7月"
@@ -6351,6 +7426,12 @@ msgstr "7月"
msgid "July"
msgstr "7月"
+msgid "Jump to first unresolved discussion"
+msgstr "跳转到第一个未解决的讨论"
+
+msgid "Jump to next unresolved discussion"
+msgstr "跳转到下一个未解决的讨论"
+
msgid "Jun"
msgstr "6月"
@@ -6360,6 +7441,9 @@ msgstr "6月"
msgid "Key (PEM)"
msgstr "秘钥 (PEM)"
+msgid "Key: %{key}"
+msgstr "密钥: %{key}"
+
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -6384,17 +7468,23 @@ msgstr "Kubernetes集群已æˆåŠŸæ›´æ–°ã€‚"
msgid "Kubernetes configured"
msgstr "Kuberneteså·²é…ç½®"
+msgid "Kubernetes error: %{error_code}"
+msgstr "Kubinentes 错误: %{error_code}"
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr "KubernetesæœåŠ¡é›†æˆå³å°†è¢«åœç”¨ã€‚ 请使用新的 <a href=\"%{url}\"/>Kubernetes集群</a> 页é¢%{deprecated_message_content} Kubernetes集群"
msgid "LDAP settings"
msgstr "LDAP 设置"
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr "LDAPåŒæ­¥æ­£åœ¨è¿›è¡Œä¸­ã€‚此过程å¯èƒ½éœ€è¦å‡ åˆ†é’Ÿã€‚请刷新页é¢ä»¥æŸ¥çœ‹æ›´æ”¹ã€‚"
+
msgid "LFS"
msgstr "LFS"
msgid "LFS objects"
-msgstr ""
+msgstr "LFS 对象"
msgid "LFSStatus|Disabled"
msgstr "åœç”¨"
@@ -6402,6 +7492,9 @@ msgstr "åœç”¨"
msgid "LFSStatus|Enabled"
msgstr "å¯ç”¨"
+msgid "LICENSE"
+msgstr "许å¯è¯"
+
msgid "Label"
msgstr "标记"
@@ -6412,13 +7505,13 @@ msgid "Label lists show all issues with the selected label."
msgstr "标记列表显示具有所选标记的所有议题。"
msgid "Label was created"
-msgstr ""
+msgstr "标记已创建"
msgid "Label was removed"
-msgstr ""
+msgstr "标记已删除"
msgid "Label was successfully updated."
-msgstr ""
+msgstr "标记已更新。"
msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
msgstr "%{firstLabelName} +%{remainingLabelCount} 更多"
@@ -6448,13 +7541,16 @@ msgid "Labels|Promote Label"
msgstr "å‡çº§æ ‡è®°"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
-msgstr "æå‡ %{labelTitle} 将使其å¯ç”¨äºŽ %{groupName} 内的所有项目。现有的åŒå项目标记将被åˆå¹¶ã€‚该æ“作ä¸å¯æ’¤é”€ã€‚"
+msgstr "æå‡%{labelTitle}将使其å¯ç”¨äºŽ%{groupName}内的所有项目。现有的åŒå项目标记将被åˆå¹¶ã€‚该æ“作ä¸å¯æ’¤é”€ã€‚"
+
+msgid "Labels|and %{count} more"
+msgstr "以åŠå…¶ä½™%{count}项"
msgid "Language"
msgstr "语言"
msgid "Large File Storage"
-msgstr "大文件存储"
+msgstr "大文件存储(LFS)"
msgid "Last %d day"
msgid_plural "Last %d days"
@@ -6463,6 +7559,9 @@ msgstr[0] "最近 %d 天"
msgid "Last Pipeline"
msgstr "最新æµæ°´çº¿"
+msgid "Last accessed on"
+msgstr "最åŽè®¿é—®æ—¶é—´"
+
msgid "Last activity"
msgstr "上次活动"
@@ -6490,6 +7589,12 @@ msgstr "最åŽæ›´æ–°"
msgid "Last updated"
msgstr "最近更新"
+msgid "Last used"
+msgstr "最åŽä½¿ç”¨"
+
+msgid "Last used on:"
+msgstr "上次使用于:"
+
msgid "LastPushEvent|You pushed to"
msgstr "您推é€äº†"
@@ -6503,7 +7608,13 @@ msgid "Latest pipeline for this branch"
msgstr "该分支的最新æµæ°´çº¿"
msgid "Lead"
-msgstr "超å‰"
+msgstr "最高"
+
+msgid "Learn GitLab"
+msgstr "学习GitLab"
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr "了解如何 %{link_start}贡献到内置的模æ¿%{link_end}"
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr "了解GitLab如何 %{no_packages_link_start}å‘布和共享您的包%{no_packages_link_end}。"
@@ -6523,6 +7634,9 @@ msgstr "进一步了解关于Kubernetesçš„ä¿¡æ¯"
msgid "Learn more about Web Terminal"
msgstr "了解更多关于 Web 终端"
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr "了解有关核准的更多信æ¯ã€‚"
@@ -6535,6 +7649,9 @@ msgstr "了解更多关于群组级项目模æ¿"
msgid "Learn more about signing commits"
msgstr "了解更多有关签åæ交的详细信æ¯"
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr "了解更多"
@@ -6542,10 +7659,10 @@ msgid "Learn more in the|pipeline schedules documentation"
msgstr "æµæ°´çº¿è®¡åˆ’文档"
msgid "Leave"
-msgstr "离开"
+msgstr "退出"
msgid "Leave edit mode? All unsaved changes will be lost."
-msgstr ""
+msgstr "退出编辑模å¼ï¼Ÿæ‰€æœ‰æœªä¿å­˜çš„更改都将丢失。"
msgid "Leave group"
msgstr "退出群组"
@@ -6556,6 +7673,12 @@ msgstr "退出项目"
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr "使用默认值设定 \"文件类型\" 和 \"交付方法\""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr "Let's Encryptä¸æŽ¥å—example.com的电å­é‚®ä»¶"
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr "许å¯è¯"
@@ -6631,19 +7754,25 @@ msgstr "URL"
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr "您å³å°†ä»Žé¡¹ç›® %{name} 中删除许å¯è¯ã€‚"
+msgid "Licensed Features"
+msgstr "需è¦è®¸å¯çš„功能"
+
msgid "Licensed to"
-msgstr ""
+msgstr "授æƒç»™"
msgid "Licenses"
msgstr "许å¯è¯"
msgid "Limit namespaces and projects that can be indexed"
-msgstr ""
+msgstr "é™åˆ¶å¯ç´¢å¼•å‘½å空间和项目"
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
msgstr[0] "最多显示 %d 个事件"
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr "领英(LinkedIn)"
@@ -6651,13 +7780,13 @@ msgid "List"
msgstr "列表"
msgid "List Your Gitea Repositories"
-msgstr "列出Gitea存储库"
+msgstr "列出Gitea仓库"
msgid "List available repositories"
-msgstr "列出å¯ç”¨å­˜å‚¨åº“"
+msgstr "列出å¯ç”¨ä»“库"
msgid "List of IPs and CIDRs of allowed secondary nodes. Comma-separated, e.g. \"1.1.1.1, 2.2.2.0/24\""
-msgstr ""
+msgstr "å…许的辅助节点IPå’ŒCIDR列表。以逗å·åˆ†éš”,例如“1.1.1.1,2.2.2.0/24â€"
msgid "List view"
msgstr "列表视图"
@@ -6674,6 +7803,9 @@ msgstr "实时预览"
msgid "Loading contribution stats for group members"
msgstr "加载群组æˆå‘˜çš„贡献统计信æ¯"
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr "加载GitLab IDE..."
@@ -6684,7 +7816,7 @@ msgid "Loading…"
msgstr "正在加载..."
msgid "Localization"
-msgstr "本土化"
+msgstr "本地化"
msgid "Lock"
msgstr "é”定"
@@ -6695,6 +7827,9 @@ msgstr "é”定 %{issuableDisplayName}"
msgid "Lock not found"
msgstr "未找到é”"
+msgid "Lock the discussion"
+msgstr "é”定讨论"
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr "é”定%{issuableDisplayName}?åªæœ‰ <strong>项目æˆå‘˜</strong> å¯ä»¥å‘表评论。"
@@ -6713,11 +7848,14 @@ msgstr "å·²é”定到目å‰çš„项目"
msgid "Locks give the ability to lock specific file or folder."
msgstr "加é”å¯ä»¥é”定特定的文件或文件夹。"
+msgid "Locks the discussion"
+msgstr "é”定讨论"
+
msgid "Login with smartcard"
msgstr "使用智能å¡ç™»å½•"
msgid "Logo was successfully removed."
-msgstr ""
+msgstr "徽标已æˆåŠŸåˆ é™¤ã€‚"
msgid "Logs"
msgstr "日志"
@@ -6737,17 +7875,26 @@ msgstr "åªæŸ¥çœ‹å˜æ›´å†…容"
msgid "MRDiff|Show full file"
msgstr "显示全部文件"
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr "使用Web IDE在æµè§ˆå™¨ä¸­åˆ›å»ºå’ŒæŸ¥çœ‹æ›´æ”¹"
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
-msgstr "GitLab Geo å¯ä»¥åˆ›å»º GitLab 实例的åªè¯»é•œåƒ, 使得从远端克隆和拉å–大型代ç ä»“库的时间大大缩短,从而æ高团队æˆå‘˜çš„工作效率。"
+msgstr "GitLab Geoå¯ä»¥åˆ›å»ºGitLab实例的åªè¯»é•œåƒ, 使得从远端克隆和拉å–大型代ç ä»“库的时间大大缩短,从而æ高团队æˆå‘˜çš„工作效率。"
+
+msgid "Make issue confidential."
+msgstr "将议题设置为ç§å¯†ã€‚"
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr "ç¡®ä¿æ‚¨å·²ç™»å½•åˆ°æ¬²å¯¼å…¥é¡¹ç›®æ‰€æœ‰è€…çš„å¸æˆ·ã€‚"
+msgid "Makes this issue confidential"
+msgstr "将此议题设置为ç§å¯†"
+
msgid "Manage"
-msgstr ""
+msgstr "管ç†"
msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
-msgstr "通过细粒度的访问控制æ¥ç®¡ç†Git存储库,确ä¿æ‚¨çš„代ç å®‰å…¨ã€‚执行代ç å®¡æŸ¥å¹¶é€šè¿‡åˆå¹¶è¯·æ±‚的实现更紧密的开å‘å作。æ¯ä¸ªé¡¹ç›®è¿˜å¯ä»¥é…置议题跟踪和wiki。"
+msgstr "通过细粒度的访问控制æ¥ç®¡ç†Git仓库,确ä¿æ‚¨çš„代ç å®‰å…¨ã€‚执行代ç å®¡æŸ¥å¹¶é€šè¿‡åˆå¹¶è¯·æ±‚的实现更紧密的开å‘å作。æ¯ä¸ªé¡¹ç›®è¿˜å¯ä»¥é…置议题跟踪和wiki。"
msgid "Manage Web IDE features"
msgstr "管ç†Web IDE功能"
@@ -6774,7 +7921,7 @@ msgid "Manage project labels"
msgstr "管ç†é¡¹ç›®æ ‡è®°"
msgid "Manage two-factor authentication"
-msgstr "管ç†åŒå› ç´ èº«ä»½éªŒè¯"
+msgstr "管ç†åŒé‡è®¤è¯"
msgid "Manifest"
msgstr "Manifest"
@@ -6803,6 +7950,15 @@ msgstr "3月"
msgid "March"
msgstr "3月"
+msgid "Mark as resolved"
+msgstr "标记为已解决"
+
+msgid "Mark comment as resolved"
+msgstr "将评论标记为已解决"
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr "将此议题标记为å¦ä¸€ä¸ªè®®é¢˜çš„é‡å¤"
+
msgid "Mark todo as done"
msgstr "标记为已完æˆ"
@@ -6810,11 +7966,20 @@ msgid "Markdown"
msgstr "Markdown"
msgid "Markdown Help"
-msgstr ""
+msgstr "Markdown帮助"
msgid "Markdown enabled"
msgstr "支æŒMarkdownæ ¼å¼"
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr "将此议题标记为 %{duplicate_reference} çš„é‡å¤ã€‚"
+
+msgid "Marks todo as done."
+msgstr "将待办事项标记为已完æˆã€‚"
+
+msgid "Match not found; try refining your search query."
+msgstr "未找到匹é…;请å°è¯•æ›´æ”¹æŸ¥è¯¢æ¡ä»¶ã€‚"
+
msgid "Maven Metadata"
msgstr "Maven 元数æ®"
@@ -6822,10 +7987,10 @@ msgid "Max access level"
msgstr "最高访问级别"
msgid "Max seats used"
-msgstr ""
+msgstr "已使用的用户数é‡"
msgid "Maximum artifacts size (MB)"
-msgstr "最大工件大å°ï¼ˆMB)"
+msgstr "最大产物大å°ï¼ˆMB)"
msgid "Maximum attachment size (MB)"
msgstr "æœ€å¤§é™„ä»¶å¤§å° (MB)"
@@ -6839,6 +8004,9 @@ msgstr "最大延迟 (分钟)"
msgid "Maximum job timeout"
msgstr "最大作业超时"
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr "作业最大超时设置无效"
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr "å¯ä»¥åŒæ—¶åŒæ­¥çš„最大镜åƒæ•°ã€‚"
@@ -6869,11 +8037,14 @@ msgstr "项目 <i>维护者</i> 或 <i>所有者</i>å¯ä»¥æ·»åŠ æˆå‘˜"
msgid "Members of <strong>%{project_name}</strong>"
msgstr "<strong>%{project_name}</strong>çš„æˆå‘˜"
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr "åˆå¹¶è¯·æ±‚"
msgid "Merge Request Approvals"
-msgstr ""
+msgstr "åˆå¹¶è¯·æ±‚核准"
msgid "Merge Requests"
msgstr "åˆå¹¶è¯·æ±‚"
@@ -6881,15 +8052,9 @@ msgstr "åˆå¹¶è¯·æ±‚"
msgid "Merge Requests created"
msgstr "创建åˆå¹¶è¯·æ±‚"
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr "åˆå¹¶æ交消æ¯"
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr "åˆå¹¶äº‹ä»¶"
@@ -6899,12 +8064,6 @@ msgstr "ç«‹å³åˆå¹¶"
msgid "Merge in progress"
msgstr "正在åˆå¹¶"
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr "åˆå¹¶æµæ°´çº¿å°†å°è¯•åœ¨åˆå¹¶æ—¶éªŒè¯åˆå¹¶åŽçš„结果"
-
msgid "Merge request"
msgstr "åˆå¹¶è¯·æ±‚"
@@ -6912,17 +8071,41 @@ msgid "Merge request approvals"
msgstr "åˆå¹¶è¯·æ±‚批准"
msgid "Merge request approvals allow you to set the number of necessary approvals and predefine a list of approvers that will need to approve every merge request in a project."
-msgstr ""
+msgstr "åˆå¹¶è¯·æ±‚核准å…许您设置必è¦æ ¸å‡†çš„æ•°é‡ï¼Œå¹¶é¢„定义项目中æ¯ä¸ªåˆå¹¶è¯·æ±‚的核准者列表。"
msgid "Merge requests"
msgstr "åˆå¹¶è¯·æ±‚"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
-msgstr "åˆå¹¶è¯·æ±‚用于æ出对项目的更改与他人讨论"
+msgstr "åˆå¹¶è¯·æ±‚用于æ出对项目的更改并与他人进行讨论"
msgid "Merge when pipeline succeeds"
msgstr "当æµæ°´çº¿æˆåŠŸæ—¶åˆå¹¶"
+msgid "MergeConflict|Commit to source branch"
+msgstr "æ交到æºåˆ†æ”¯"
+
+msgid "MergeConflict|Committing..."
+msgstr "æ交..."
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr "HEAD //我们的更改"
+
+msgid "MergeConflict|Use ours"
+msgstr "使用我们的"
+
+msgid "MergeConflict|Use theirs"
+msgstr "使用他们的"
+
+msgid "MergeConflict|conflict"
+msgstr "冲çª"
+
+msgid "MergeConflict|conflicts"
+msgstr "冲çª"
+
+msgid "MergeConflict|origin//their changes"
+msgstr "æ¥æº//他们的更改"
+
msgid "MergeRequests|Add a reply"
msgstr "添加回å¤"
@@ -6941,6 +8124,9 @@ msgstr "讨论并解决"
msgid "MergeRequests|Discussion will be unresolved"
msgstr "讨论并未解决"
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr "无法压缩(Squash)。应该手动完æˆã€‚"
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr "跳转到下一个未解决的讨论"
@@ -6953,6 +8139,9 @@ msgstr "在新议题中解决此讨论"
msgid "MergeRequests|Saving the comment failed"
msgstr "ä¿å­˜è¯„论失败"
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr "压缩(Squash)任务已å–消:å¦ä¸€ä¸ªåŽ‹ç¼©å·²åœ¨è¿›è¡Œä¸­ã€‚"
+
msgid "MergeRequests|Toggle comments for this file"
msgstr "开关此文件的讨论"
@@ -6986,8 +8175,8 @@ msgstr "%{paragraphStart}%{timeDifferenceMinutes}%{descriptionChangedTimes}次æ›
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr "加载完整差异时出错。请å†è¯•ä¸€æ¬¡ã€‚"
-msgid "MergeRequest|Filter files"
-msgstr "过滤文件"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
+msgstr "过滤文件或使用 %{modifier_key}+ pæœç´¢"
msgid "MergeRequest|No files found"
msgstr "未找到任何文件"
@@ -6996,11 +8185,17 @@ msgid "Merged"
msgstr "å·²åˆå¹¶"
msgid "Merged branches are being deleted. This can take some time depending on the number of branches. Please refresh the page to see changes."
-msgstr ""
+msgstr "å·²åˆå¹¶åˆ†æ”¯æ­£åœ¨è¢«åˆ é™¤ã€‚该æ“作å¯èƒ½éœ€è¦ä¸€äº›æ—¶é—´ï¼Œå…·ä½“å–决于分支的数é‡ã€‚请刷新页é¢ä»¥æŸ¥çœ‹æ›´æ–°ã€‚"
msgid "Messages"
msgstr "消æ¯"
+msgid "Metric was successfully added."
+msgstr "指标已æˆåŠŸæ·»åŠ ã€‚"
+
+msgid "Metric was successfully updated."
+msgstr "指标已æˆåŠŸæ›´æ–°ã€‚"
+
msgid "Metrics"
msgstr "指标"
@@ -7016,6 +8211,9 @@ msgstr "指标和分æž"
msgid "Metrics for environment"
msgstr "环境指标"
+msgid "Metrics|Add metric"
+msgstr "添加指标"
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "查看有关部署到环境的CI/CD文档"
@@ -7055,9 +8253,6 @@ msgstr "创建指标"
msgid "Metrics|No deployed environments"
msgstr "应用未部署到任何环境"
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr "PromotQL 查询有效"
@@ -7065,7 +8260,7 @@ msgid "Metrics|Prometheus Query Documentation"
msgstr "Prometheus查询文档"
msgid "Metrics|Show last"
-msgstr ""
+msgstr "显示最åŽ"
msgid "Metrics|There was an error fetching the environments data, please try again"
msgstr "获å–环境数æ®æ—¶å‡ºé”™ï¼Œè¯·é‡è¯•"
@@ -7103,14 +8298,26 @@ msgstr "Y轴标签"
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr "您å³å°†æ°¸ä¹…删除此指标且无法撤消。"
+msgid "Metrics|e.g. HTTP requests"
+msgstr "例如:HTTP 请求"
+
+msgid "Metrics|e.g. Requests/second"
+msgstr "例如:请求/秒"
+
msgid "Metrics|e.g. Throughput"
msgstr "例如:åžåé‡"
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr "例如:速率(http_requests_total[5m])"
+
+msgid "Metrics|e.g. req/sec"
+msgstr "例如:req / sec"
+
msgid "Migrated %{success_count}/%{total_count} files."
-msgstr ""
+msgstr "å·²è¿ç§» %{success_count}/%{total_count} 文件。"
msgid "Migration successful."
-msgstr ""
+msgstr "è¿ç§»æˆåŠŸã€‚"
msgid "Milestone"
msgstr "里程碑"
@@ -7130,9 +8337,6 @@ msgstr "您å³å°†æ°¸ä¹…删除里程碑 %{milestoneTitle} 并将其从 %{issuesWi
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr "您å³å°†æ°¸ä¹…删除里程碑 %{milestoneTitle}。此里程碑当å‰æœªç”¨äºŽä»»ä½•è®®é¢˜æˆ–åˆå¹¶è¯·æ±‚。"
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr "<p>%{milestonePromotion}</p> %{finalWarning}"
-
msgid "Milestones|Delete milestone"
msgstr "删除里程碑"
@@ -7151,8 +8355,8 @@ msgstr "å°† %{milestoneTitle} å‡çº§ä¸ºç¾¤ç»„里程碑?"
msgid "Milestones|Promote Milestone"
msgstr "å‡çº§é‡Œç¨‹ç¢‘"
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
-msgstr "æå‡ %{milestone} 将使其å¯ç”¨äºŽ %{groupName} 内的所有项目。现有的åŒå项目里程碑将被åˆå¹¶ã€‚ "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
+msgstr "æå‡%{milestoneTitle}åŽï¼Œè¯¥é‡Œç¨‹ç¢‘å°†å¯ç”¨äºŽ%{groupName}群组内的所有项目。如果现有项目里程碑具有相åŒæ ‡é¢˜ï¼Œè¿™äº›é¡¹ç›®é‡Œç¨‹ç¢‘被åˆå¹¶å…¥ç¾¤ç»„里程碑。"
msgid "Milestones|This action cannot be reversed."
msgstr "该æ“作无法撤销。"
@@ -7160,26 +8364,47 @@ msgstr "该æ“作无法撤销。"
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr "在我们预先安排更多镜åƒä¹‹å‰å¯ç”¨çš„最å°å®¹é‡ã€‚"
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr "最å°é•¿åº¦ä¸º%{minimum_password_length}个字符"
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr "最å°é•¿åº¦ä¸º%{minimum_password_length}个字符。"
+
+msgid "Minutes"
+msgstr "分钟"
+
msgid "Mirror a repository"
-msgstr "é•œåƒå­˜å‚¨åº“"
+msgstr "é•œåƒä»“库"
msgid "Mirror direction"
msgstr "é•œåƒæ–¹å‘"
msgid "Mirror repository"
-msgstr "é•œåƒå­˜å‚¨åº“"
+msgstr "é•œåƒä»“库"
msgid "Mirror user"
msgstr "é•œåƒç”¨æˆ·"
msgid "Mirrored repositories"
-msgstr "é•œåƒçš„存储库"
+msgstr "é•œåƒçš„仓库"
msgid "Mirroring repositories"
-msgstr "é•œåƒå­˜å‚¨åº“"
+msgstr "é•œåƒä»“库"
msgid "Mirroring settings were successfully updated."
-msgstr ""
+msgstr "é•œåƒè®¾ç½®å·²æˆåŠŸæ›´æ–°ã€‚"
+
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr "é•œåƒè®¾ç½®å·²æˆåŠŸæ›´æ–°ã€‚正在更新该项目。"
+
+msgid "Mirroring was successfully disabled."
+msgstr "é•œåƒå·²æˆåŠŸç¦ç”¨ã€‚"
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr "åªæœ‰åœ¨æ‰€é€‰ç¾¤ç»„或用户的计划中包å«é•œåƒåŠŸèƒ½æ—¶ï¼Œæ‰èƒ½ä½¿ç”¨ã€‚"
+
+msgid "Missing commit signatures endpoint!"
+msgstr "缺少æ交签å节点ï¼"
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "新建 SSH 公钥"
@@ -7233,7 +8458,7 @@ msgid "Most stars"
msgstr "最多星标"
msgid "Mount point %{mounted_as} not found in %{model_class}."
-msgstr ""
+msgstr "%{model_class} 中未找到挂载点 %{mounted_as}。"
msgid "Move"
msgstr "移动"
@@ -7241,18 +8466,39 @@ msgstr "移动"
msgid "Move issue"
msgstr "移动议题"
+msgid "Move issue from one column of the board to another"
+msgstr "将议题从看æ¿çš„一列移到å¦ä¸€åˆ—"
+
+msgid "Move this issue to another project."
+msgstr "将此议题移至å¦ä¸€ä¸ªé¡¹ç›®ã€‚"
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr "由于æƒé™ä¸è¶³è€Œæ— æ³•ç§»åŠ¨è®®é¢˜!"
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr "无法将议题移动到æºé¡¹ç›®ä¸­!"
+
+msgid "Moves issue to %{label} column in the board."
+msgstr "将议题移至看æ¿çš„ %{label} 列中。"
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr "将此议题移动到 %{path_to_project}。"
+
msgid "Multiple issue boards"
msgstr "多é‡è®®é¢˜çœ‹æ¿"
msgid "Multiple model types found: %{model_types}"
-msgstr ""
+msgstr "找到多个模型类型: %{model_types}"
msgid "Multiple uploaders found: %{uploader_types}"
-msgstr ""
+msgstr "找到多个上传器: %{uploader_types}"
msgid "Name"
msgstr "å称"
+msgid "Name has already been taken"
+msgstr "å称已被使用"
+
msgid "Name new label"
msgstr "命å新标记"
@@ -7263,10 +8509,10 @@ msgid "Name:"
msgstr "å称:"
msgid "Namespaces to index"
-msgstr ""
+msgstr "è¦ç´¢å¼•çš„命å空间"
msgid "Naming, topics, avatar"
-msgstr ""
+msgstr "命å,主题,头åƒ"
msgid "Naming, visibility"
msgstr "å称与å¯è§æ€§"
@@ -7336,7 +8582,7 @@ msgid "New branch unavailable"
msgstr "新分支ä¸å¯ç”¨"
msgid "New deploy key"
-msgstr "新的部署密钥"
+msgstr "新建部署密钥"
msgid "New directory"
msgstr "新建目录"
@@ -7345,7 +8591,10 @@ msgid "New environment"
msgstr "新环境"
msgid "New epic"
-msgstr "æ–°epic"
+msgstr "新建å²è¯—"
+
+msgid "New epic title"
+msgstr ""
msgid "New file"
msgstr "新建文件"
@@ -7354,7 +8603,7 @@ msgid "New group"
msgstr "新建群组"
msgid "New health check access token has been generated!"
-msgstr ""
+msgstr "已生æˆæ–°çš„è¿è¡ŒçŠ¶å†µæ£€æŸ¥è®¿é—®ä»¤ç‰Œï¼"
msgid "New identity"
msgstr "新建身份标识"
@@ -7371,6 +8620,9 @@ msgstr "新建åˆå¹¶è¯·æ±‚"
msgid "New milestone"
msgstr "新里程碑"
+msgid "New password"
+msgstr "新密ç "
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr "æ–°æµæ°´çº¿å°†å–消åŒä¸€åˆ†æ”¯ä¸Šè¾ƒæ—§çš„待处ç†æµæ°´çº¿"
@@ -7378,7 +8630,7 @@ msgid "New project"
msgstr "新建项目"
msgid "New runners registration token has been generated!"
-msgstr ""
+msgstr "已生æˆæ–°çš„Runner注册令牌ï¼"
msgid "New schedule"
msgstr "新建计划"
@@ -7401,21 +8653,36 @@ msgstr "新建..."
msgid "Newly registered users will by default be external"
msgstr "默认情况下,新注册的用户将是外部用户"
+msgid "Next"
+msgstr "下一个"
+
+msgid "Nickname"
+msgstr "昵称"
+
msgid "No"
msgstr "å¦"
msgid "No %{providerTitle} repositories available to import"
-msgstr "æ— %{providerTitle} 存储库å¯ä¾›å¯¼å…¥"
+msgstr "æ— %{providerTitle} 仓库å¯ä¾›å¯¼å…¥"
msgid "No Label"
msgstr "无标记"
+msgid "No Milestone"
+msgstr "无里程碑"
+
msgid "No Tag"
msgstr "无标签"
msgid "No activities found"
msgstr "没有å‘现任何活动"
+msgid "No available namespaces to fork the project."
+msgstr "没有å¯ç”¨çš„命å空间æ¥æ´¾ç”Ÿé¡¹ç›®ã€‚"
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr "未å‘现分支"
@@ -7431,6 +8698,9 @@ msgstr "无法连接到GitalyæœåŠ¡å™¨ï¼Œè¯·æ£€æŸ¥ç›¸å…³æ—¥å¿—ï¼"
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr "此项目当å‰æœªå­˜å‚¨å®¹å™¨é•œåƒã€‚如需使用,请å‚照上述说明新建容器镜åƒã€‚"
+msgid "No contributions"
+msgstr "无贡献"
+
msgid "No contributions were found"
msgstr "未找到任何贡献者"
@@ -7455,6 +8725,9 @@ msgstr "未选定任何文件"
msgid "No file selected"
msgstr "未选择任何文件"
+msgid "No files"
+msgstr "没有文件"
+
msgid "No files found."
msgstr "未找到文件。"
@@ -7462,7 +8735,7 @@ msgid "No issues for the selected time period."
msgstr "所选时间段无议题。"
msgid "No job trace"
-msgstr ""
+msgstr "没有作业日志"
msgid "No labels with such name or description"
msgstr "没有具有此类å称或æ述的标记"
@@ -7471,14 +8744,11 @@ msgid "No license. All rights reserved"
msgstr "未设定许å¯è¯ã€‚版æƒæ‰€æœ‰ã€‚"
msgid "No licenses found."
-msgstr ""
+msgstr "未找到许å¯è¯ã€‚"
msgid "No matching results"
msgstr "没有匹é…的结果"
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr "所选时间段无åˆå¹¶è¯·æ±‚。"
@@ -7494,6 +8764,9 @@ msgstr "没有è¦æ˜¾ç¤ºçš„里程碑"
msgid "No other labels with such name or description"
msgstr "没有其他具有此类å称或æ述的标记"
+msgid "No parent group"
+msgstr "父群组ä¸å­˜åœ¨"
+
msgid "No preview for this file type"
msgstr "无法预览此类型文件"
@@ -7521,6 +8794,12 @@ msgstr "没有开始日期"
msgid "No, directly import the existing email addresses and usernames."
msgstr "å¦, 请直接导入现有电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·å。"
+msgid "Node was successfully created."
+msgstr "节点已æˆåŠŸåˆ›å»ºã€‚"
+
+msgid "Node was successfully updated."
+msgstr "节点已æˆåŠŸæ›´æ–°ã€‚"
+
msgid "Nodes"
msgstr "节点"
@@ -7537,19 +8816,19 @@ msgid "Not available for protected branches"
msgstr "对å—ä¿æŠ¤çš„分支ä¸å¯ç”¨"
msgid "Not confidential"
-msgstr "éžæœºå¯†"
+msgstr "éžç§å¯†"
msgid "Not enough data"
msgstr "æ•°æ®ä¸è¶³"
msgid "Not found."
-msgstr ""
+msgstr "未找到。"
msgid "Not now"
msgstr "æš‚ä¸"
msgid "Not ready yet. Try again later."
-msgstr ""
+msgstr "还没有准备好。请ç¨åŽå†è¯•ã€‚"
msgid "Not started"
msgstr "未开始"
@@ -7569,6 +8848,9 @@ msgstr "æ示:如GitLab管ç†å‘˜é…ç½® %{github_integration_link},将å…许
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr "æ示:如GitLab管ç†å‘˜é…ç½® %{github_integration_link},将å…许通过GitHub登录并å…许导入Github代ç ä»“库而ä¸éœ€è¦ä¸ªäººè®¿é—®ä»¤ç‰Œã€‚"
+msgid "NoteForm|Note"
+msgstr "注æ„"
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "确定è¦å–消此评论å—?"
@@ -7584,6 +8866,12 @@ msgstr "仅显示评论"
msgid "Notes|Show history only"
msgstr "仅显示历å²è®°å½•"
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr "自您开始编辑以æ¥ï¼Œæ­¤è¯„论已更改,请查看 %{open_link}更新过的评论%{close_link} 以确ä¿ä¿¡æ¯ä¸ä¼šä¸¢å¤±"
+
+msgid "Nothing to preview."
+msgstr "没有å¯é¢„览的内容。"
+
msgid "Notification events"
msgstr "通知事件"
@@ -7593,6 +8881,9 @@ msgstr "无法预览此类型文件"
msgid "Notification setting - %{notification_title}"
msgstr "通知设置 - %{notification_title}"
+msgid "Notification settings saved"
+msgstr "通知设置已ä¿å­˜"
+
msgid "NotificationEvent|Close issue"
msgstr "关闭议题"
@@ -7606,7 +8897,7 @@ msgid "NotificationEvent|Merge merge request"
msgstr "åˆå¹¶è¯·æ±‚被åˆå¹¶"
msgid "NotificationEvent|New epic"
-msgstr "æ–°epic"
+msgstr "æ–°å²è¯—"
msgid "NotificationEvent|New issue"
msgstr "新建议题"
@@ -7647,6 +8938,9 @@ msgstr "å‚与"
msgid "NotificationLevel|Watch"
msgstr "关注"
+msgid "NotificationSetting|Custom"
+msgstr "自定义"
+
msgid "Notifications"
msgstr "通知"
@@ -7662,11 +8956,17 @@ msgstr "å一"
msgid "November"
msgstr "å一月"
+msgid "Number of Elasticsearch replicas"
+msgstr "Elasticsearch副本的数é‡"
+
+msgid "Number of Elasticsearch shards"
+msgstr "Elasticsearch分片数"
+
msgid "OK"
msgstr "确定"
msgid "Object does not exist on the server or you don't have permissions to access it"
-msgstr ""
+msgstr "对象在æœåŠ¡å™¨ä¸Šä¸å­˜åœ¨, 或者您没有访问它的æƒé™"
msgid "Oct"
msgstr "10月"
@@ -7677,21 +8977,27 @@ msgstr "10月"
msgid "OfSearchInADropdown|Filter"
msgstr "过滤"
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
-msgstr "仓库导入åŽï¼Œå¯ä»¥é€šè¿‡ SSH 拉å–é•œåƒã€‚了解更多 %{ssh_link}"
+msgid "Ok let's go"
+msgstr "好的,我们开始å§"
+
+msgid "Onboarding"
+msgstr "新手上路"
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
+msgstr "仓库导入åŽï¼Œå¯ä»¥é€šè¿‡SSH进行镜åƒã€‚点击%{link_start}此处%{link_end}了解更多."
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
-msgstr ""
+msgstr "删除åŽå°†æ— æ³•æ¢å¤æ´¾ç”Ÿå…³ç³»ï¼Œæ‚¨å°†æ— æ³•å†å‘æºé¡¹ç›®å‘é€åˆå¹¶è¯·æ±‚。"
msgid "Once the exported file is ready, you will receive a notification email with a download link, or you can download it from this page."
-msgstr ""
+msgstr "导出的文件准备就绪åŽï¼Œæ‚¨å°†æ”¶åˆ°å¸¦æœ‰ä¸‹è½½é“¾æŽ¥çš„通知电å­é‚®ä»¶ï¼Œæˆ–者您å¯ä»¥ä»Žæ­¤é¡µé¢ä¸‹è½½ã€‚"
msgid "One more item"
msgid_plural "%d more items"
msgstr[0] "其余%d项"
msgid "One or more groups that you don't have access to."
-msgstr ""
+msgstr "您无æƒè®¿é—®çš„一个或多个群组。"
msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "您的一个或多个Bitbucket项目无法直接导入GitLab,因为它们使用Subversion或Mercurial进行版本控制,而ä¸æ˜¯Git。"
@@ -7699,13 +9005,13 @@ msgstr "您的一个或多个Bitbucket项目无法直接导入GitLab,因为它
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "您的一个或多个Google Code项目无法直接导入GitLab,因为它们使用Subversion或Mercurial进行版本控制,而ä¸æ˜¯Git。"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
+msgstr ""
+
msgid "Only admins"
msgstr "仅管ç†å‘˜"
-msgid "Only allow merge requests to be merged if all discussions are resolved"
-msgstr ""
-
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7723,6 +9029,9 @@ msgstr "åªæœ‰é¡¹ç›®æˆå‘˜å¯ä»¥å‘表评论。"
msgid "Only project members will be imported. Group members will be skipped."
msgstr "仅导入项目æˆå‘˜ã€‚群组æˆå‘˜å°†è¢«è·³è¿‡ã€‚"
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr "仅支æŒè¿™äº›æ‰©å±•: %{extension_list}"
+
msgid "Oops, are you sure?"
msgstr "å•Š~~, 确定å—?"
@@ -7745,7 +9054,7 @@ msgid "Open projects"
msgstr "打开项目"
msgid "Open raw"
-msgstr ""
+msgstr "打开原始文件"
msgid "Open sidebar"
msgstr "打开侧边æ "
@@ -7768,6 +9077,12 @@ msgstr "创建于"
msgid "Opens in a new window"
msgstr "打开一个新窗å£"
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr "æ“作失败。请检查 Pod 日志 %{pod_name} 了解更多信æ¯ã€‚"
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr "æ“作超时。请检查 Pod 日志 %{pod_name} 了解更多信æ¯ã€‚"
+
msgid "Operations"
msgstr "è¿ç»´"
@@ -7781,20 +9096,17 @@ msgid "OperationsDashboard|Add a project to the dashboard"
msgstr "将项目添加到仪表æ¿"
msgid "OperationsDashboard|Add projects"
-msgstr ""
+msgstr "添加项目"
msgid "OperationsDashboard|More information"
-msgstr ""
+msgstr "更多信æ¯"
msgid "OperationsDashboard|Operations Dashboard"
-msgstr ""
+msgstr "è¿ç»´é¢æ¿"
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr "è¿ç»´ä»ªè¡¨æ¿æä¾›æ¯ä¸ªé¡¹ç›®çš„è¿è¡ŒçŠ¶å†µçš„摘è¦ï¼ŒåŒ…括æµæ°´çº¿å’Œè­¦æŠ¥çŠ¶æ€ã€‚"
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr "无法添加 %{invalidProjects}。 æ“作仪表æ¿å¯ç”¨äºŽå…¬å…±é¡¹ç›®ä»¥åŠå…·æœ‰Gold方案的群组中的ç§æœ‰é¡¹ç›®ã€‚"
-
msgid "Optional"
msgstr "å¯é€‰çš„"
@@ -7816,6 +9128,9 @@ msgstr "其他标记"
msgid "Other information"
msgstr "其他信æ¯"
+msgid "Other merge requests block this MR"
+msgstr "其他åˆå¹¶è¯·æ±‚阻止了此MR"
+
msgid "Outbound requests"
msgstr "外å‘请求"
@@ -7825,6 +9140,12 @@ msgstr "概览"
msgid "Overwrite diverged branches"
msgstr "覆盖分å‰åˆ†æ”¯"
+msgid "Owned by anyone"
+msgstr "拥有者为任何人"
+
+msgid "Owned by me"
+msgstr "拥有者为我"
+
msgid "Owner"
msgstr "所有者"
@@ -7838,10 +9159,10 @@ msgid "Packages"
msgstr "软件包"
msgid "Page not found"
-msgstr ""
+msgstr "找ä¸åˆ°é¡µé¢"
msgid "Page was successfully deleted"
-msgstr ""
+msgstr "页é¢å·²æˆåŠŸåˆ é™¤"
msgid "Pages"
msgstr "Pages"
@@ -7852,6 +9173,9 @@ msgstr "Pages域å"
msgid "Pages Domains"
msgstr "Pages域å"
+msgid "Pages getting started guide"
+msgstr "Pages 入门指å—"
+
msgid "Pagination|Last »"
msgstr "尾页 »"
@@ -7873,8 +9197,20 @@ msgstr "包å«äºŽåˆå¹¶è¯·æ±‚å˜æ›´ä¸­"
msgid "Password"
msgstr "密ç "
+msgid "Password (optional)"
+msgstr "å¯†ç  (å¯é€‰)"
+
msgid "Password authentication is unavailable."
-msgstr ""
+msgstr "密ç éªŒè¯ä¸å¯ç”¨ã€‚"
+
+msgid "Password confirmation"
+msgstr "密ç ç¡®è®¤"
+
+msgid "Password successfully changed"
+msgstr "密ç ä¿®æ”¹æˆåŠŸ"
+
+msgid "Password was successfully updated. Please login with it"
+msgstr "密ç æ›´æ–°æˆåŠŸã€‚请登录"
msgid "Past due"
msgstr "逾期"
@@ -7883,16 +9219,16 @@ msgid "Paste a machine public key here. Read more about how to generate it %{lin
msgstr "在此处粘贴计算机公钥。在%{link_start}这里%{link_end}了解更多关于如何产生公钥"
msgid "Paste epic link"
-msgstr "粘贴epic链接"
+msgstr "粘贴å²è¯—链接"
msgid "Paste issue link"
msgstr "粘贴议题链接"
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
-msgstr "粘贴您的 SSH 公钥,通常包å«åœ¨ '~/.ssh/id_rsa.pub' 文件中,并以 'ssh-rsa' 开头。ä¸è¦ä½¿ç”¨æ‚¨çš„ SSH ç§é’¥ã€‚"
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
msgid "Path"
-msgstr ""
+msgstr "路径"
msgid "Path, transfer, remove"
msgstr "路径,转移,删除"
@@ -7904,7 +9240,7 @@ msgid "Pause"
msgstr "æš‚åœ"
msgid "Pause replication"
-msgstr ""
+msgstr "æš‚åœå¤åˆ¶"
msgid "Paused Runners don't accept new jobs"
msgstr "æš‚åœçš„ Runner ä¸æŽ¥å—新作业"
@@ -7915,6 +9251,9 @@ msgstr "等待中"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr "未ç»è®¸å¯çš„用户将无法收到通知,也无法评论。"
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr "执行高级选项,例如更改路径,移动或删除群组。"
@@ -7925,7 +9264,7 @@ msgid "Permissions"
msgstr "æƒé™"
msgid "Permissions Help"
-msgstr ""
+msgstr "æƒé™å¸®åŠ©"
msgid "Permissions, LFS, 2FA"
msgstr "æƒé™ï¼ŒLFS,2FA"
@@ -7936,12 +9275,27 @@ msgstr "个人访问凭è¯"
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr "ä¸å…许创建个人项目。如有疑问,请è”系您的管ç†å‘˜"
+msgid "Phabricator Server Import"
+msgstr "PhabricatoræœåŠ¡å™¨å¯¼å…¥"
+
+msgid "Phabricator Server URL"
+msgstr "PharibatoræœåŠ¡å™¨URL"
+
+msgid "Phabricator Tasks"
+msgstr "Phabricator任务"
+
msgid "Pick a name"
msgstr "选择一个å称"
+msgid "Pin code"
+msgstr "Pinç "
+
msgid "Pipeline"
msgstr "æµæ°´çº¿"
+msgid "Pipeline ID (IID)"
+msgstr "æµæ°´çº¿ID (IID)"
+
msgid "Pipeline Schedule"
msgstr "æµæ°´çº¿è®¡åˆ’"
@@ -7958,7 +9312,7 @@ msgid "Pipeline triggers"
msgstr "æµæ°´çº¿è§¦å‘器"
msgid "Pipeline: %{status}"
-msgstr ""
+msgstr "æµæ°´çº¿: %{status}"
msgid "PipelineCharts|Failed:"
msgstr "失败:"
@@ -8020,6 +9374,9 @@ msgstr "æµæ°´çº¿"
msgid "Pipelines charts"
msgstr "æµæ°´çº¿ç»Ÿè®¡å›¾"
+msgid "Pipelines emails"
+msgstr "æµæ°´çº¿ç”µå­é‚®ä»¶"
+
msgid "Pipelines for last month"
msgstr "上个月的æµæ°´çº¿"
@@ -8029,12 +9386,15 @@ msgstr "上周的æµæ°´çº¿"
msgid "Pipelines for last year"
msgstr "去年的æµæ°´çº¿"
-msgid "Pipelines need to be configured to enable this feature."
-msgstr "需è¦é…ç½®æµæ°´çº¿ä»¥å¯ç”¨æ­¤åŠŸèƒ½ã€‚"
-
msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgstr "“%{project_name}â€çš„æµæ°´çº¿è®¾ç½®å·²æˆåŠŸæ›´æ–°ã€‚"
+
+msgid "Pipelines| to purchase more minutes."
msgstr ""
+msgid "Pipelines|API"
+msgstr "API"
+
msgid "Pipelines|Build with confidence"
msgstr "自信地构建"
@@ -8053,6 +9413,9 @@ msgstr "æµæ°´çº¿å…¥é—¨"
msgid "Pipelines|Loading Pipelines"
msgstr "载入æµæ°´çº¿"
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "项目缓存é‡ç½®æˆåŠŸã€‚"
@@ -8078,7 +9441,7 @@ msgid "Pipeline|Commit"
msgstr "æ交"
msgid "Pipeline|Coverage"
-msgstr ""
+msgstr "覆盖率"
msgid "Pipeline|Duration"
msgstr "时长"
@@ -8093,7 +9456,7 @@ msgid "Pipeline|Run Pipeline"
msgstr "è¿è¡Œæµæ°´çº¿"
msgid "Pipeline|Run for"
-msgstr ""
+msgstr "è¿è¡ŒäºŽ"
msgid "Pipeline|Search branches"
msgstr "æœç´¢åˆ†æ”¯"
@@ -8113,6 +9476,9 @@ msgstr "åœæ­¢æµæ°´çº¿"
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr "åœæ­¢æµæ°´çº¿ï¼ƒ%{pipelineId}å—?"
+msgid "Pipeline|Triggerer"
+msgstr "触å‘者"
+
msgid "Pipeline|Variables"
msgstr "å˜é‡"
@@ -8123,25 +9489,34 @@ msgid "Pipeline|all"
msgstr "所有"
msgid "Pipeline|for"
-msgstr ""
+msgstr "使用æ交"
msgid "Pipeline|into"
-msgstr ""
+msgstr "åˆå¹¶åˆ°"
msgid "Pipeline|on"
-msgstr ""
+msgstr "于"
msgid "Pipeline|success"
msgstr "æˆåŠŸ"
msgid "Pipeline|with"
-msgstr ""
+msgstr "ç”±"
msgid "Pipeline|with stage"
-msgstr "于阶段"
+msgstr ",包å«é˜¶æ®µ"
msgid "Pipeline|with stages"
-msgstr "于阶段"
+msgstr ",包å«é˜¶æ®µ"
+
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr "将自动检查的以逗å·åˆ†éš”的分支列表。空白则包括所有分支。"
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr "Pivotal Tracker API令牌。"
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr "项目管ç†è½¯ä»¶ (æºæ交端点)"
msgid "Plain diff"
msgstr "文本差异"
@@ -8152,17 +9527,35 @@ msgstr "PlantUML"
msgid "Play"
msgstr "è¿è¡Œ"
+msgid "Play all manual"
+msgstr "è¿è¡Œæ‰€æœ‰æ‰‹åŠ¨ä½œä¸š"
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr "想è¦è¯„论请 %{link_to_register} 或 %{link_to_sign_in}"
msgid "Please accept the Terms of Service before continuing."
msgstr "请接å—æœåŠ¡æ¡æ¬¾ä»¥ç»§ç»­ã€‚"
+msgid "Please add a comment in the text area above"
+msgstr "请在上é¢æ–‡æœ¬æ¡†æ·»åŠ è¯„论"
+
+msgid "Please add a list to your board first"
+msgstr "请先å‘看æ¿æ·»åŠ ä¸€åˆ—"
+
+msgid "Please check the configuration file for this chart"
+msgstr "请检查此图表的é…置文件"
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr "请检查é…置文件以确ä¿å·²å£°æ˜Žäº†ä¸€ç»„图表。"
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr "请检查é…置文件以确ä¿å®ƒå¯ç”¨ä¸”YAML有效"
+
msgid "Please choose a group URL with no special characters."
msgstr "请选择无特殊字符的群组URL。"
msgid "Please complete your profile with email address"
-msgstr ""
+msgstr "请在您的个人资料中填写电å­é‚®ä»¶åœ°å€"
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr "请将它们先%{link_to_git}, 然åŽå†æ¬¡ä½¿ç”¨%{link_to_import_flow}。"
@@ -8171,7 +9564,7 @@ msgid "Please convert them to Git on Google Code, and go through the %{link_to_i
msgstr "请将它们先在Google Code中转为Git, 然åŽå†æ¬¡ä½¿ç”¨%{link_to_import_flow}。"
msgid "Please create a password for your new account."
-msgstr ""
+msgstr "请为您的新å¸æˆ·åˆ›å»ºå¯†ç ã€‚"
msgid "Please create a username with only alphanumeric characters."
msgstr "请创建仅包å«å­—æ¯å’Œæ•°å­—的用户å。"
@@ -8188,6 +9581,9 @@ msgstr "请输入大于%{number}(æ¥è‡ªé¡¹ç›®è®¾ç½®)çš„æ•°å­—"
msgid "Please enter a valid number"
msgstr "请输入有效的数字"
+msgid "Please enter or upload a license."
+msgstr "请输入或上传一个许å¯è¯ã€‚"
+
msgid "Please fill in a descriptive name for your group."
msgstr "请为您的群组填写æ述性å称。"
@@ -8200,8 +9596,17 @@ msgstr "请注æ„,GitLabä¸æ供此应用程åºï¼Œæ‚¨åº”该在å…许访问之
msgid "Please provide a name"
msgstr "请æä¾›å称"
+msgid "Please provide a valid email address."
+msgstr "请æ供有效的电å­é‚®ä»¶åœ°å€ã€‚"
+
+msgid "Please retype the email address."
+msgstr "请å†æ¬¡è¾“入电å­é‚®ä»¶åœ°å€ã€‚"
+
+msgid "Please select a file"
+msgstr "请选择一个文件"
+
msgid "Please select a group."
-msgstr ""
+msgstr "请选择一个群组。"
msgid "Please select and add a member"
msgstr "请选择并添加一个æˆå‘˜"
@@ -8221,11 +9626,11 @@ msgstr "请å†è¯•ä¸€æ¬¡"
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr "请将PostgreSQLå‡çº§åˆ°9.6或更高版本。使用当å‰ç‰ˆæœ¬æ— æ³•å¯é åœ°ç¡®å®šå¤åˆ¶çš„状æ€ã€‚"
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
-msgstr "请使用此表å•å‘GitLab报告创建垃圾议题ã€è¯„论或有ä¸å½“行为的用户。"
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
+msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
-msgstr ""
+msgstr "请ç¨ç­‰ç‰‡åˆ»ï¼Œæ­¤é¡µé¢åœ¨å°±ç»ªæ—¶ä¼šè‡ªåŠ¨åˆ·æ–°ã€‚"
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr "连接代ç ä»“库中,请ç¨å€™ã€‚å¯åœ¨ä»»æ„时刻刷新以获å–当å‰çŠ¶æ€ã€‚"
@@ -8237,14 +9642,68 @@ msgid "Preferences"
msgstr "å好设置"
msgid "Preferences saved."
+msgstr "å好设置已ä¿å­˜ã€‚"
+
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr "以24å°æ—¶æ ¼å¼æ˜¾ç¤ºæ—¶é—´"
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr "例如:30分钟å‰"
+
+msgid "Preferences|Layout width"
msgstr ""
msgid "Preferences|Navigation theme"
msgstr "导航主题"
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr "这些设置将更新您的日期和时间显示方å¼ã€‚"
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr "此功能当åˆå¤„于实验阶段,翻译尚未全部完æˆã€‚"
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr "时间显示"
+
+msgid "Preferences|Time format"
+msgstr "时间格å¼"
+
+msgid "Preferences|Time preferences"
+msgstr "时间å好"
+
+msgid "Preferences|Use relative times"
+msgstr "使用相对时间"
+
+msgid "Press %{key}-C to copy"
+msgstr "按 %{key}-C å¤åˆ¶"
+
msgid "Press Enter or click to search"
msgstr "按 回车键或å•å‡»ä»¥æœç´¢"
@@ -8252,20 +9711,26 @@ msgid "Prevent adding new members to project membership within this group"
msgstr "ç¦æ­¢å‘当å‰ç¾¤ç»„添加æˆå‘˜"
msgid "Prevent approval of merge requests by merge request author"
-msgstr ""
+msgstr "阻止åˆå¹¶è¯·æ±‚作者核准åˆå¹¶è¯·æ±‚"
msgid "Prevent approval of merge requests by merge request committers"
-msgstr ""
+msgstr "阻止åˆå¹¶è¯·æ±‚æ交者核准åˆå¹¶è¯·æ±‚"
msgid "Preview"
msgstr "预览"
+msgid "Preview Markdown"
+msgstr "Markdown预览"
+
msgid "Preview changes"
-msgstr ""
+msgstr "预览更改"
msgid "Preview payload"
msgstr "预览上传数æ®"
+msgid "Previous Artifacts"
+msgstr "å‰ä¸€ä¸ªäº§ç‰©"
+
msgid "Primary"
msgstr "主è¦"
@@ -8291,17 +9756,26 @@ msgid "Private - The group and its projects can only be viewed by members."
msgstr "ç§äºº - 群组åŠå…¶é¡¹ç›®åªèƒ½ç”±æˆå‘˜æŸ¥çœ‹ã€‚"
msgid "Private group(s)"
-msgstr ""
+msgstr "ç§æœ‰ç¾¤ç»„"
+
+msgid "Private profile"
+msgstr "éžå…¬å¼€èµ„æ–™"
msgid "Private projects can be created in your personal namespace with:"
msgstr "ç§æœ‰é¡¹ç›®å¯ä»¥åœ¨ä¸ªäººå称空间中创建:"
+msgid "Proceed"
+msgstr "继续"
+
msgid "Profile"
msgstr "用户资料"
msgid "Profile Settings"
msgstr "个人资料设置"
+msgid "ProfileSession|on"
+msgstr "于"
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr "您å³å°†æ°¸ä¹…删除 %{yourAccount},以åŠä¸Žæ‚¨çš„å¸æˆ·å…³è”的所有议题,åˆå¹¶è¯·æ±‚和群组。一旦确认 %{deleteAccount},此æ“作便无法撤销和æ¢å¤ã€‚"
@@ -8332,6 +9806,9 @@ msgstr "头åƒè£å‰ª"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "å³å°†åˆ é™¤å¤´åƒã€‚确定继续å—?"
+msgid "Profiles|Bio"
+msgstr "简历"
+
msgid "Profiles|Change username"
msgstr "更改用户å"
@@ -8342,7 +9819,7 @@ msgid "Profiles|Choose file..."
msgstr "选择文件..."
msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
-msgstr "选择在公开个人资料中显示ç§æœ‰é¡¹ç›®çš„贡献,但ä¸æ˜¾ç¤ºä»»ä½•é¡¹ç›®ï¼Œå­˜å‚¨åº“或组织信æ¯"
+msgstr "选择在公开个人资料中显示ç§æœ‰é¡¹ç›®çš„贡献,但ä¸æ˜¾ç¤ºä»»ä½•é¡¹ç›®ï¼Œä»“库或组织信æ¯"
msgid "Profiles|City, country"
msgstr "城市,国家"
@@ -8353,6 +9830,9 @@ msgstr "清除状æ€"
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr "å•å‡»å›¾æ ‡ä»¥ä½¿ç”¨ä»¥ä¸‹æœåŠ¡ä¹‹ä¸€æ¿€æ´»ç™»å½•"
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr "连接"
@@ -8365,6 +9845,9 @@ msgstr "当å‰è·¯å¾„: %{path}"
msgid "Profiles|Current status"
msgstr "当å‰çŠ¶æ€"
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr "删除å¸æˆ·"
@@ -8384,7 +9867,7 @@ msgid "Profiles|Do not show on profile"
msgstr "ä¸åœ¨ä¸ªäººèµ„料中显示"
msgid "Profiles|Don't display activity-related personal information on your profiles"
-msgstr "ä¸è¦åœ¨ä¸ªäººèµ„料上显示与活动相关的个人信æ¯"
+msgstr "ä¸åœ¨ä¸ªäººèµ„料中显示与活动相关的个人信æ¯"
msgid "Profiles|Edit Profile"
msgstr "编辑个人资料"
@@ -8392,6 +9875,18 @@ msgstr "编辑个人资料"
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr "输入您的姓å,以便大家认识您"
+msgid "Profiles|Feed token was successfully reset"
+msgstr "ä¿¡æ¯åŠ¨æ€ä»¤ç‰Œå·²æˆåŠŸé‡ç½®"
+
+msgid "Profiles|Full name"
+msgstr "å…¨å"
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr "在个人资料中包å«éžå…¬å¼€è´¡çŒ®"
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr "接收邮件令牌已é‡ç½®"
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr "å¯ç”¨åŒé‡èº«ä»½è®¤è¯ï¼ˆ2FA),æ高账户安全性"
@@ -8401,9 +9896,15 @@ msgstr "密ç æ— æ•ˆ"
msgid "Profiles|Invalid username"
msgstr "用户å无效"
+msgid "Profiles|Key"
+msgstr "密钥"
+
msgid "Profiles|Learn more"
msgstr "了解更多"
+msgid "Profiles|Location"
+msgstr "ä½ç½®"
+
msgid "Profiles|Made a private contribution"
msgstr "作出了ç§æœ‰è´¡çŒ®"
@@ -8413,18 +9914,33 @@ msgstr "主è¦è®¾ç½®"
msgid "Profiles|No file chosen"
msgstr "未选择文件"
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr "组织"
+
msgid "Profiles|Path"
msgstr "路径"
msgid "Profiles|Position and size your new avatar"
msgstr "您新头åƒçš„ä½ç½®å’Œå¤§å°"
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr "éžå…¬å¼€è´¡çŒ®"
+msgid "Profiles|Profile was successfully updated"
+msgstr "个人资料已æˆåŠŸæ›´æ–°"
+
msgid "Profiles|Public Avatar"
msgstr "公开头åƒ"
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr "删除头åƒ"
@@ -8443,9 +9959,6 @@ msgstr "请用少于250字符æ述您自己"
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "å…许的最大文件大å°ä¸º200KB。"
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "这看起æ¥ä¸åƒ SSH 公钥,确定è¦æ·»åŠ å®ƒå—?"
@@ -8453,7 +9966,7 @@ msgid "Profiles|This email will be displayed on your public profile"
msgstr "此电å­é‚®ä»¶å°†æ˜¾ç¤ºåœ¨æ‚¨çš„公开个人资料中。"
msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{commit_email_link_start}Learn more%{commit_email_link_end}"
-msgstr ""
+msgstr "此电å­é‚®ä»¶å°†ç”¨äºŽåŸºäºŽWebçš„æ“作,例如编辑和åˆå¹¶ã€‚ %{commit_email_link_start}更多信æ¯%{commit_email_link_end}"
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr "此表情符å·å’Œæ¶ˆæ¯ä¼šæ˜¾ç¤ºåœ¨æ‚¨çš„个人资料和界é¢ä¸­ã€‚"
@@ -8461,14 +9974,17 @@ msgstr "此表情符å·å’Œæ¶ˆæ¯ä¼šæ˜¾ç¤ºåœ¨æ‚¨çš„个人资料和界é¢ä¸­ã€‚"
msgid "Profiles|This information will appear on your profile"
msgstr "此信æ¯å°†æ˜¾ç¤ºåœ¨æ‚¨çš„个人资料中"
+msgid "Profiles|Time settings"
+msgstr "时间设置"
+
msgid "Profiles|Two-Factor Authentication"
-msgstr "åŒå› ç´ èº«ä»½éªŒè¯"
+msgstr "åŒé‡è®¤è¯"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "键入您的 %{confirmationValue} 以确认:"
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
-msgstr "通常以“ssh-rsa ...â€å¼€å¤´"
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
+msgstr ""
msgid "Profiles|Update profile settings"
msgstr "更新个人资料设置"
@@ -8482,6 +9998,9 @@ msgstr "上传新头åƒ"
msgid "Profiles|Use a private email - %{email}"
msgstr "使用ç§äººç”µå­é‚®ä»¶ - %{email}"
+msgid "Profiles|User ID"
+msgstr "用户ID"
+
msgid "Profiles|Username change failed - %{message}"
msgstr "用户å更改失败 - %{message}"
@@ -8495,7 +10014,7 @@ msgid "Profiles|What's your status?"
msgstr "您当å‰çš„状æ€ï¼Ÿ"
msgid "Profiles|Who you represent or work for"
-msgstr "您代表è°æˆ–为è°å·¥ä½œ"
+msgstr "您代表或工作的å•ä½ç»„织"
msgid "Profiles|You can change your avatar here"
msgstr "å¯ä»¥åœ¨è¿™é‡Œä¿®æ”¹æ‚¨çš„头åƒ"
@@ -8503,6 +10022,9 @@ msgstr "å¯ä»¥åœ¨è¿™é‡Œä¿®æ”¹æ‚¨çš„头åƒ"
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr "您å¯ä»¥åœ¨è¿™é‡Œä¿®æ”¹å¤´åƒæˆ–删除当å‰å¤´åƒå¹¶æ¢å¤ä¸º %{gravatar_link}"
+msgid "Profiles|You can set your current timezone here"
+msgstr "您å¯ä»¥åœ¨æ­¤è®¾ç½®å½“å‰æ—¶åŒº"
+
msgid "Profiles|You can upload your avatar here"
msgstr "å¯ä»¥åœ¨è¿™é‡Œä¸Šä¼ æ‚¨çš„头åƒ"
@@ -8561,10 +10083,10 @@ msgid "Project \"%{name}\" is no longer available. Select another project to con
msgstr "项目“%{name}â€ä¸å†å¯ç”¨ã€‚选择å¦ä¸€ä¸ªé¡¹ç›®ä»¥ç»§ç»­ã€‚"
msgid "Project %{project_repo} could not be found"
-msgstr ""
+msgstr "无法找到项目 %{project_repo}"
msgid "Project '%{project_name}' is being imported."
-msgstr ""
+msgstr "正在导入项目 \"%{project_name}\"。"
msgid "Project '%{project_name}' is in the process of being deleted."
msgstr "项目 “%{project_name}†正在被删除。"
@@ -8582,7 +10104,7 @@ msgid "Project Badges"
msgstr "项目徽章"
msgid "Project ID"
-msgstr ""
+msgstr "项目ID"
msgid "Project URL"
msgstr "项目 URL"
@@ -8591,16 +10113,19 @@ msgid "Project access must be granted explicitly to each user."
msgstr "项目访问æƒé™å¿…须明确授æƒç»™æ¯ä¸ªç”¨æˆ·ã€‚"
msgid "Project and wiki repositories"
-msgstr ""
+msgstr "项目和wiki仓库"
msgid "Project avatar"
msgstr "项目头åƒ"
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr "项目ä¸èƒ½åˆ†äº«ç»™å½“å‰æ‰€åœ¨çš„群组或其任一级父群组。"
+
msgid "Project configuration, including services"
-msgstr ""
+msgstr "项目é…ç½®, 包括æœåŠ¡"
msgid "Project description (optional)"
-msgstr ""
+msgstr "项目æè¿° (å¯é€‰)"
msgid "Project details"
msgstr "项目详情"
@@ -8633,14 +10158,17 @@ msgid "Project slug"
msgstr "项目标识串"
msgid "Project uploads"
-msgstr ""
+msgstr "项目上传"
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
-msgstr ""
+msgstr "当项目转移到群组åŽï¼Œå…¶å¯è§æ€§çº§åˆ«å°†æ›´æ”¹ä¸ºä¸Žå‘½å空间规则匹é…。"
msgid "Project:"
msgstr "项目:"
+msgid "Project: %{name}"
+msgstr "项目: %{name}"
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "订阅"
@@ -8692,6 +10220,24 @@ msgstr "登录åŽæ‰èƒ½æ˜Ÿæ ‡é¡¹ç›®"
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "项目ID:%{project_id}"
+msgid "ProjectSelect| or group"
+msgstr "或群组"
+
+msgid "ProjectSelect|Search for project"
+msgstr "æœç´¢é¡¹ç›®"
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr "å½±å“åˆå¹¶æ‰§è¡Œæ–¹å¼å’Œæ—¶é—´çš„其他åˆå¹¶è¯·æ±‚功能"
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr "所有讨论都必须解决"
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr "自动解决过期的åˆå¹¶è¯·æ±‚差异相关讨论"
+
msgid "ProjectSettings|Badges"
msgstr "徽章"
@@ -8701,18 +10247,60 @@ msgstr "è”系管ç†å‘˜æ›´æ”¹æ­¤è®¾ç½®ã€‚"
msgid "ProjectSettings|Customize your project badges."
msgstr "自定义您的项目徽章。"
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr "æ¯æ¬¡åˆå¹¶éƒ½ä¼šåˆ›å»ºåˆå¹¶æ交"
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr "ä¿æŠ¤æ ‡ç­¾å¤±è´¥"
msgid "ProjectSettings|Failed to update tag!"
msgstr "更新标签失败ï¼"
+msgid "ProjectSettings|Fast-forward merge"
+msgstr "å¿«è¿›å¼(Fast-forward)åˆå¹¶"
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr "ä»…å¿«è¿›å¼(Fast-forward)åˆå¹¶"
+
msgid "ProjectSettings|Learn more about badges."
msgstr "了解有关徽章的更多信æ¯ã€‚"
+msgid "ProjectSettings|Merge checks"
+msgstr "åˆå¹¶æ£€æŸ¥"
+
+msgid "ProjectSettings|Merge commit"
+msgstr "åˆå¹¶æ交"
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr "åˆå¹¶æ交与åŠçº¿æ€§åŽ†å²è®°å½•"
+
+msgid "ProjectSettings|Merge method"
+msgstr "åˆå¹¶æ–¹æ³•"
+
+msgid "ProjectSettings|Merge options"
+msgstr "åˆå¹¶é€‰é¡¹"
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr "åˆå¹¶æµæ°´çº¿å°†å°è¯•åœ¨è¿›è¡Œå®žé™…åˆå¹¶ä¹‹å‰éªŒè¯åˆå¹¶ç»“æžœ"
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr "项目设置|未创建åˆå¹¶æ交"
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "åªæœ‰å·²ç­¾ç½²æ交æ‰å¯ä»¥æŽ¨é€åˆ°æ­¤ä»“库。"
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr "项目设置|æµæ°´çº¿å¿…é¡»æˆåŠŸ"
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr "需é…ç½®æµæ°´çº¿ä»¥å¯ç”¨æ­¤åŠŸèƒ½ã€‚"
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr "从命令行推é€æ—¶æ˜¾ç¤ºåˆ›å»º/查看åˆå¹¶è¯·æ±‚的链接"
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr "åˆå¹¶è¯·æ±‚在通过这些检查åŽæ‰å¯è¢«åˆå¹¶"
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr "此设置已应用于æœåŠ¡å™¨çº§åˆ«ï¼Œå¯ç”±ç®¡ç†å‘˜ä¿®æ”¹ã€‚"
@@ -8722,12 +10310,72 @@ msgstr "此设置应用于æœåŠ¡å™¨çº§åˆ«ï¼Œä½†å·²è¢«è¯¥é¡¹ç›®è¦†ç›–。"
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "此设置将应用于所有项目,除éžè¢«ç®¡ç†å‘˜è¦†ç›–。"
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr "这将对åˆå¹¶è¯·æ±‚完æˆæ—¶çš„æ交历å²è®°å½•äº§ç”Ÿå½±å“"
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
-msgstr "用户åªèƒ½é€šè¿‡è‡ªå·±å·²éªŒè¯çš„电å­é‚®ä»¶åœ°å€å°†æ交到此存储库中。"
+msgstr "用户åªèƒ½é€šè¿‡è‡ªå·±å·²éªŒè¯çš„电å­é‚®ä»¶åœ°å€å°†æ交到此仓库中。"
+
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr "项目设置 |当出现冲çªæ—¶ï¼Œç”¨æˆ·å¯ä»¥é€‰æ‹©rebase"
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ".NET Core"
+
+msgid "ProjectTemplates|Android"
+msgstr "Android"
+
+msgid "ProjectTemplates|Go Micro"
+msgstr "Go Micro"
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr "Netlify/GitBook"
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr "Nettify/Hexo"
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr "Netrify/Hugo"
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr "Nettlity/Jekyll"
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr "Netrify/Plain HTML"
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr "NodeJS Express"
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr "Pages/GitBook"
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr "Pages/hexo"
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr "Pages/Hugo"
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr "Pages/Jekyll"
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr "Pages/Plain HTML"
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr "Ruby on Rails"
+
+msgid "ProjectTemplates|Spring"
+msgstr "Spring"
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr "iOS (Swift)"
msgid "Projects"
msgstr "项目"
+msgid "Projects (%{count})"
+msgstr "项目 (%{count})"
+
msgid "Projects Successfully Retrieved"
msgstr "项目æˆåŠŸè¯»å–"
@@ -8738,7 +10386,7 @@ msgid "Projects that belong to a group are prefixed with the group namespace. Ex
msgstr "属于群组的项目以群组å称为å‰ç¼€ã€‚现有项目å¯ä»¥ç§»åŠ¨åˆ°ä¸€ä¸ªç¾¤ç»„中。"
msgid "Projects to index"
-msgstr ""
+msgstr "è¦ç´¢å¼•çš„项目"
msgid "Projects with write access"
msgstr "具有写入æƒé™çš„项目"
@@ -8792,7 +10440,7 @@ msgid "PrometheusAlerts|Operator"
msgstr "æ“作符"
msgid "PrometheusAlerts|Select query"
-msgstr ""
+msgstr "选择查询"
msgid "PrometheusAlerts|Threshold"
msgstr "阈值"
@@ -8884,6 +10532,15 @@ msgstr "å‡çº§åˆ°ç¾¤ç»„里程碑"
msgid "Promote to group label"
msgstr "å‡çº§åˆ°ç¾¤ç»„标记"
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr "åªèƒ½å‡çº§é¡¹ç›®é‡Œç¨‹ç¢‘。"
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr "项目ä¸å±žäºŽä»»ä½•ä¸€ä¸ªç¾¤ç»„。"
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr "å‡çº§å¤±è´¥ - %{message}"
+
msgid "Promotions|Don't show me this again"
msgstr "ä¸å†æ˜¾ç¤º"
@@ -8902,36 +10559,48 @@ msgstr "æ示用户上传 SSH 密钥"
msgid "Protected"
msgstr "å—ä¿æŠ¤"
+msgid "Protected Branch"
+msgstr "ä¿æŠ¤åˆ†æ”¯"
+
+msgid "Protected Environment"
+msgstr "å—ä¿æŠ¤çš„环境"
+
msgid "Protected Environments"
msgstr "å—ä¿æŠ¤çš„环境"
+msgid "Protected Tag"
+msgstr "å—ä¿æŠ¤çš„标签"
+
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} 将对开å‘人员å¯å†™ã€‚确定继续å—?"
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "å…许部署"
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
-msgstr "选择å…许部署的人员"
-
msgid "ProtectedEnvironment|Environment"
msgstr "环境"
msgid "ProtectedEnvironment|Protect"
msgstr "ä¿æŠ¤"
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr "ä¿æŠ¤éƒ¨ç½²çŽ¯å¢ƒä»¥é™åˆ¶å¯æ‰§è¡Œéƒ¨ç½²çš„人员身份。"
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr "ä¿æŠ¤éƒ¨ç½²çŽ¯å¢ƒ"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr "å—ä¿æŠ¤çš„环境 (%{protected_environments_count})"
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr "ä¿æŠ¤çŽ¯å¢ƒä¼šé™åˆ¶å¯ä»¥æ‰§è¡Œéƒ¨ç½²çš„用户的范围。"
+
msgid "ProtectedEnvironment|Select an environment"
msgstr "选择一个环境"
+msgid "ProtectedEnvironment|Select users"
+msgstr "选择用户"
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr "选择用户æ¥éƒ¨ç½²å’Œç®¡ç†åŠŸèƒ½æ ‡å¿—设置"
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr "ç›®å‰æ— å—ä¿æŠ¤çš„环境,请使用上述表å•ä¿æŠ¤éƒ¨ç½²çŽ¯å¢ƒã€‚"
@@ -8966,7 +10635,7 @@ msgid "Public - The project can be accessed without any authentication."
msgstr "公开 - 无需任何身份验è¯å³å¯è®¿é—®è¯¥é¡¹ç›®ã€‚"
msgid "Public Access Help"
-msgstr ""
+msgstr "公开访问帮助"
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr "公共部署密钥(%{deploy_keys_count})"
@@ -8980,11 +10649,17 @@ msgstr "拉å–"
msgid "Push"
msgstr "推é€"
+msgid "Push Rule updated successfully."
+msgstr "推é€è§„则已æˆåŠŸæ›´æ–°ã€‚"
+
msgid "Push Rules"
msgstr "推é€è§„则"
+msgid "Push Rules updated successfully."
+msgstr "推é€è§„则已æˆåŠŸæ›´æ–°ã€‚"
+
msgid "Push an existing Git repository"
-msgstr "推é€çŽ°æœ‰çš„ Git 存储库"
+msgstr "推é€çŽ°æœ‰çš„ Git 仓库"
msgid "Push an existing folder"
msgstr "推é€çŽ°æœ‰æ–‡ä»¶å¤¹"
@@ -9007,12 +10682,54 @@ msgstr "已推é€"
msgid "Pushes"
msgstr "推é€"
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr "%{user_name} 已删除分支“%{ref}â€ã€‚"
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr "%{user_name} 推é€åˆ†æ”¯ \"%{ref}\"。"
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr "%{user_name} 已推é€æ–°åˆ†æ”¯ \"%{ref}\"。"
+
+msgid "PushoverService|High Priority"
+msgstr "高优先级"
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr "留空为所有活动设备"
+
+msgid "PushoverService|Low Priority"
+msgstr "低优先级"
+
+msgid "PushoverService|Lowest Priority"
+msgstr "最低优先级"
+
+msgid "PushoverService|Normal Priority"
+msgstr "正常优先级"
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr "Pushoverå¯è®©æ‚¨è½»æ¾åœ¨Android设备,iPhone,iPad和桌é¢ä¸ŠèŽ·å¾—实时通知。"
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr "å‚è§é¡¹ç›® %{project_full_name}"
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr "总æ交次数:%{total_commits_count}"
+
+msgid "PushoverService|Your application key"
+msgstr "您的应用程åºå¯†é’¥"
+
+msgid "PushoverService|Your user key"
+msgstr "您的用户密钥"
+
msgid "Quarters"
msgstr "季度"
msgid "Query"
msgstr "查询"
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr "快速æ“作å¯ç”¨äºŽè®®é¢˜æ述和评论框。"
@@ -9020,7 +10737,7 @@ msgid "README"
msgstr "自述文件"
msgid "Rake Tasks Help"
-msgstr ""
+msgstr "Rake任务帮助"
msgid "Read more"
msgstr "进一步了解"
@@ -9037,15 +10754,24 @@ msgstr "实时功能"
msgid "Receive alerts from manually configured Prometheus servers."
msgstr "从手动é…置的 Prometheus æœåŠ¡å™¨æŽ¥æ”¶è­¦æŠ¥ã€‚"
+msgid "Receive notifications about your own activity"
+msgstr "接收关于您自己活动的通知"
+
msgid "Recent"
msgstr "最近"
msgid "Recent Project Activity"
msgstr "最近的项目活动"
+msgid "Recent Searches Service is unavailable"
+msgstr "最近æœç´¢æœåŠ¡ä¸å¯ç”¨"
+
msgid "Recent searches"
msgstr "最近的æœç´¢"
+msgid "Recovery Codes"
+msgstr "æ¢å¤ç "
+
msgid "Redirect to SAML provider to test configuration"
msgstr "跳转到SAML供应商以测试é…ç½®"
@@ -9059,29 +10785,50 @@ msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] "%d 秒åŽåˆ·æ–°ä»¥æ˜¾ç¤ºæ›´æ–°çŠ¶æ€..."
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr "é‡æ–°ç”Ÿæˆå¯†é’¥"
+msgid "Regenerate recovery codes"
+msgstr "é‡æ–°ç”Ÿæˆæ¢å¤ç "
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr "正则表达å¼"
+msgid "Register"
+msgstr "注册"
+
msgid "Register / Sign In"
msgstr "注册/登录"
+msgid "Register Two-Factor Authenticator"
+msgstr "注册åŒé‡è®¤è¯"
+
msgid "Register U2F device"
msgstr "注册U2F设备"
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr "注册通用åŒé‡è®¤è¯è®¾å¤‡(U2F)"
+
msgid "Register and see your runners for this group."
msgstr "注册并查看当å‰ç¾¤ç»„çš„Runner。"
msgid "Register and see your runners for this project."
msgstr "注册和查看当å‰é¡¹ç›®çš„ Runner"
+msgid "Register with two-factor app"
+msgstr "使用åŒé‡è®¤è¯åº”用注册"
+
msgid "Registration"
-msgstr ""
+msgstr "注册"
msgid "Registry"
-msgstr "注册表"
+msgstr "é•œåƒåº“"
msgid "Related Commits"
msgstr "相关的æ交"
@@ -9101,6 +10848,9 @@ msgstr "相关的åˆå¹¶è¯·æ±‚"
msgid "Related Merged Requests"
msgstr "相关已åˆå¹¶çš„åˆå¹¶è¯·æ±‚"
+msgid "Related issues"
+msgstr "相关的议题"
+
msgid "Related merge requests"
msgstr "相关åˆå¹¶è¯·æ±‚"
@@ -9113,6 +10863,9 @@ msgstr "版本标志ç€é¡¹ç›®çš„å‘展历å²ä¸­çš„具体节点,传达相关的
msgid "Remind later"
msgstr "ç¨åŽæ醒"
+msgid "Remote object has no absolute path."
+msgstr "远程对象没有ç»å¯¹è·¯å¾„。"
+
msgid "Remove"
msgstr "删除"
@@ -9122,8 +10875,11 @@ msgstr "移除Runner"
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr "将新的æ交推é€åˆ°å…¶æºåˆ†æ”¯æ—¶ï¼Œåˆ é™¤åˆå¹¶è¯·æ±‚中的所有核准"
-msgid "Remove approver"
-msgstr "删除核准人"
+msgid "Remove all or specific assignee(s)"
+msgstr "删除所有或特定指派人"
+
+msgid "Remove all or specific label(s)"
+msgstr "删除所有或特定标记"
msgid "Remove approvers"
msgstr "删除核准人"
@@ -9131,47 +10887,77 @@ msgstr "删除核准人"
msgid "Remove approvers?"
msgstr "删除核准人?"
+msgid "Remove assignee"
+msgstr "删除指派人"
+
msgid "Remove avatar"
msgstr "删除头åƒ"
+msgid "Remove child epic from an epic"
+msgstr "从å²è¯—中删除å­å²è¯—"
+
+msgid "Remove due date"
+msgstr "删除截止日期"
+
msgid "Remove fork relationship"
-msgstr ""
+msgstr "删除派生关系"
msgid "Remove group"
msgstr "删除群组"
+msgid "Remove milestone"
+msgstr "删除里程碑"
+
msgid "Remove priority"
msgstr "删除优先级"
msgid "Remove project"
msgstr "删除项目"
-msgid "Remove this label? Are you sure?"
-msgstr ""
+msgid "Remove spent time"
+msgstr "删除消耗时间"
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
-msgstr ""
+msgid "Remove time estimate"
+msgstr "删除时间估计"
msgid "Removed"
-msgstr ""
+msgstr "已删除"
msgid "Removed %{type} with id %{id}"
-msgstr ""
+msgstr "已删除 %{type} 的 id %{id}"
msgid "Removed group can not be restored!"
msgstr "已删除的群组无法æ¢å¤ï¼"
msgid "Removed projects cannot be restored!"
-msgstr ""
+msgstr "已删除的项目无法æ¢å¤!"
+
+msgid "Removes %{epic_ref} from child epics."
+msgstr "从å­å²è¯—中删除%{epic_ref}。"
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr "删除里程碑%{milestone_reference}。"
+
+msgid "Removes all labels."
+msgstr "删除所有标记。"
+
+msgid "Removes spent time."
+msgstr "删除消耗时间."
+
+msgid "Removes the due date."
+msgstr "删除截止日期."
+
+msgid "Removes time estimate."
+msgstr "删除时间估计。"
msgid "Removing group will cause all child projects and resources to be removed."
msgstr "删除群组将导致所有å­é¡¹ç›®å’Œèµ„æºè¢«åˆ é™¤ã€‚"
msgid "Removing license…"
-msgstr ""
+msgstr "删除许å¯è¯â€¦"
msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
+msgstr "删除项目将删除其仓库和所有相关资æºï¼ŒåŒ…括议题ã€åˆå¹¶è¯·æ±‚等。"
msgid "Rename"
msgstr "é‡å‘½å"
@@ -9183,7 +10969,7 @@ msgid "Rename folder"
msgstr "é‡å‘½å文件夹"
msgid "Reopen epic"
-msgstr "é‡æ–°å¼€å¯epic"
+msgstr "é‡æ–°å¼€å¯å²è¯—"
msgid "Reopen milestone"
msgstr "é‡æ–°æ‰“开里程碑"
@@ -9192,7 +10978,10 @@ msgid "Repair authentication"
msgstr "ä¿®å¤è®¤è¯"
msgid "Replace"
-msgstr ""
+msgstr "替æ¢"
+
+msgid "Replace all label(s)"
+msgstr "替æ¢æ‰€æœ‰æ ‡è®°"
msgid "Reply to comment"
msgstr "回å¤è¯„论"
@@ -9203,8 +10992,8 @@ msgstr "直接回å¤æ­¤é‚®ä»¶æˆ– %{view_it_on_gitlab}。"
msgid "Repo by URL"
msgstr "从 URL 导入仓库"
-msgid "Report abuse to GitLab"
-msgstr "å‘GitLab举报滥用行为"
+msgid "Report abuse to admin"
+msgstr ""
msgid "Reporting"
msgstr "报告"
@@ -9218,6 +11007,9 @@ msgstr "æ“作"
msgid "Reports|Class"
msgstr "ç±»"
+msgid "Reports|Classname"
+msgstr "ç±»å"
+
msgid "Reports|Confidence"
msgstr "置信水平"
@@ -9228,19 +11020,19 @@ msgid "Reports|Failure"
msgstr "失败"
msgid "Reports|Metrics reports are loading"
-msgstr ""
+msgstr "正在加载指标报告"
msgid "Reports|Metrics reports changed on %{numberOfChanges} %{pointsString}"
-msgstr ""
+msgstr "指标报告有%{numberOfChanges}处å˜åŒ–,共%{pointsString}"
msgid "Reports|Metrics reports did not change"
-msgstr ""
+msgstr "指标报告无å˜åŒ–"
msgid "Reports|Metrics reports failed loading results"
-msgstr ""
+msgstr "指标报告加载结果失败"
msgid "Reports|Severity"
-msgstr "严é‡æ€§"
+msgstr "严é‡çº§åˆ«"
msgid "Reports|System output"
msgstr "系统输出"
@@ -9257,12 +11049,6 @@ msgstr "测试总结报告解æžä¸­"
msgid "Reports|Vulnerability"
msgstr "æ¼æ´ž"
-msgid "Reports|issue"
-msgstr "议题"
-
-msgid "Reports|merge request"
-msgstr "åˆå¹¶è¯·æ±‚"
-
msgid "Reports|no changed test results"
msgstr "未å‘生å˜åŒ–的测试结果"
@@ -9270,19 +11056,19 @@ msgid "Repository"
msgstr "仓库"
msgid "Repository Settings"
-msgstr "存储库设置"
+msgstr "仓库设置"
msgid "Repository URL"
msgstr "仓库地å€"
msgid "Repository check was triggered."
-msgstr ""
+msgstr "已触å‘仓库检查。"
msgid "Repository cleanup"
-msgstr "存储库清ç†"
+msgstr "仓库清ç†"
msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
-msgstr "存储库清ç†å·²ç»å¼€å§‹ã€‚一旦清ç†å®Œæˆï¼Œæ‚¨å°†æ”¶åˆ°ä¸€å°ç”µå­é‚®ä»¶ã€‚"
+msgstr "仓库清ç†å·²ç»å¼€å§‹ã€‚一旦清ç†å®Œæˆï¼Œæ‚¨å°†æ”¶åˆ°ä¸€å°ç”µå­é‚®ä»¶ã€‚"
msgid "Repository has no locks."
msgstr "当å‰ä»“库无加é”文件。"
@@ -9317,6 +11103,12 @@ msgstr "è¦æ±‚所有用户在访问GitLab时接å—æœåŠ¡æ¡æ¬¾å’Œéšç§æ”¿ç­–。
msgid "Require approval from code owners"
msgstr "需è¦ä»£ç æ‰€æœ‰è€…的核准"
+msgid "Require user password to approve"
+msgstr "需è¦ç”¨æˆ·å¯†ç æ‰èƒ½æ‰¹å‡†"
+
+msgid "Require users to prove ownership of custom domains"
+msgstr "è¦æ±‚用户è¯æ˜Žè‡ªå®šä¹‰åŸŸçš„所有æƒ"
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
msgstr[0] "éœ€è¦ %{count} 个 %{names} 的核准"
@@ -9325,6 +11117,9 @@ msgid "Requires approval."
msgid_plural "Requires %d more approvals."
msgstr[0] "éœ€è¦ %d 个核准"
+msgid "Resend confirmation email"
+msgstr ""
+
msgid "Resend invite"
msgstr "é‡æ–°å‘é€é‚€è¯·"
@@ -9359,16 +11154,25 @@ msgid "Resolved"
msgstr "已解决"
msgid "Resolved 1 discussion."
-msgstr ""
+msgstr "已解决 1 个讨论。"
msgid "Resolved all discussions."
-msgstr ""
+msgstr "已解决所有讨论。"
+
+msgid "Resolved by %{name}"
+msgstr "由%{name}解决"
+
+msgid "Resolved by %{resolvedByName}"
+msgstr "由 %{resolvedByName} 解决"
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr "解æžä¸€æ¬¡ IP 地å€å¹¶ä½¿ç”¨å®ƒä»¬æ交请求"
msgid "Response"
msgstr "å“应"
msgid "Response didn't include `service_desk_address`"
-msgstr ""
+msgstr "å“应ä¸åŒ…括`service_desk_address`"
msgid "Response metrics (AWS ELB)"
msgstr "å“应指标(AWS ELB)"
@@ -9395,7 +11199,7 @@ msgid "Resume"
msgstr "æ¢å¤"
msgid "Resume replication"
-msgstr ""
+msgstr "æ¢å¤å¤åˆ¶"
msgid "Retry"
msgstr "é‡è¯•"
@@ -9404,6 +11208,9 @@ msgid "Retry this job"
msgstr "é‡è¯•å½“å‰ä½œä¸š"
msgid "Retry this job in order to create the necessary resources."
+msgstr "é‡è¯•æ­¤ä½œä¸šä»¥åˆ›å»ºå¿…è¦çš„资æºã€‚"
+
+msgid "Retry update"
msgstr ""
msgid "Retry verification"
@@ -9438,10 +11245,16 @@ msgid "Revoke"
msgstr "撤销"
msgid "Revoked impersonation token %{token_name}!"
-msgstr ""
+msgstr "撤销身份模拟令牌 %{token_name}ï¼"
msgid "Revoked personal access token %{personal_access_token_name}!"
-msgstr ""
+msgstr "撤销个人访问令牌 %{personal_access_token_name}ï¼"
+
+msgid "RightSidebar|adding a"
+msgstr "添加"
+
+msgid "RightSidebar|deleting the"
+msgstr "删除"
msgid "Roadmap"
msgstr "路线图"
@@ -9450,7 +11263,7 @@ msgid "Run CI/CD pipelines for external repositories"
msgstr "使用外部仓库的CI/CDæµæ°´çº¿"
msgid "Run housekeeping"
-msgstr ""
+msgstr "è¿è¡Œä¾‹è¡Œç»´æŠ¤"
msgid "Run tests against your code live using the Web Terminal"
msgstr "使用Web终端对您的代ç è¿›è¡Œå®žæ—¶æµ‹è¯•"
@@ -9474,10 +11287,10 @@ msgid "Runner token"
msgstr "Runner 令牌"
msgid "Runner was not updated."
-msgstr ""
+msgstr "Runner未更新。"
msgid "Runner was successfully updated."
-msgstr ""
+msgstr "Runnerå·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Runner will not receive any new jobs"
msgstr "Runnerä¸ä¼šæŽ¥å—新的作业"
@@ -9489,7 +11302,7 @@ msgid "Runners API"
msgstr "Runners API"
msgid "Runners activated for this project"
-msgstr "此项目已激活的è¿è¡Œå™¨"
+msgstr "此项目已激活的Runner"
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr "Runnerå¯ä»¥æ”¾åœ¨ä¸åŒçš„用户ã€æœåŠ¡å™¨ï¼Œç”šè‡³æœ¬åœ°æœºå™¨ä¸Šã€‚"
@@ -9516,7 +11329,7 @@ msgid "Running…"
msgstr "è¿è¡Œä¸­..."
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
-msgstr ""
+msgstr "在当å‰ä»“库中è¿è¡Œä¸€äº›ä¾‹è¡Œç»´æŠ¤ä»»åŠ¡ï¼Œä¾‹å¦‚压缩文件修订和删除无法访问的对象。"
msgid "SAML SSO"
msgstr "SAML SSO(å•ç‚¹ç™»å½•)"
@@ -9527,15 +11340,21 @@ msgstr "群组%{group_name} 的 SAML SSO"
msgid "SAML for %{group_name}"
msgstr "%{group_name} çš„ SAML"
+msgid "SSH Key"
+msgstr "SSH密钥"
+
msgid "SSH Keys"
msgstr "SSH 密钥"
msgid "SSH Keys Help"
-msgstr ""
+msgstr "SSH 密钥帮助"
msgid "SSH host keys"
msgstr "SSH主机密钥"
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr "SSH密钥用于在您的电脑和GitLab建立安全连接。"
+
msgid "SSH public key"
msgstr "SSH公钥"
@@ -9551,6 +11370,9 @@ msgstr "ä¿å­˜"
msgid "Save Changes"
msgstr "ä¿å­˜ä¿®æ”¹"
+msgid "Save anyway"
+msgstr "ä»ç„¶ä¿å­˜"
+
msgid "Save application"
msgstr "ä¿å­˜åº”用"
@@ -9563,6 +11385,9 @@ msgstr "测试å‰ä¿å­˜æ›´æ”¹"
msgid "Save comment"
msgstr "ä¿å­˜è¯„论"
+msgid "Save password"
+msgstr "ä¿å­˜å¯†ç "
+
msgid "Save pipeline schedule"
msgstr "ä¿å­˜æµæ°´çº¿è®¡åˆ’"
@@ -9570,7 +11395,7 @@ msgid "Save variables"
msgstr "ä¿å­˜å˜é‡"
msgid "Saving project."
-msgstr ""
+msgstr "正在ä¿å­˜é¡¹ç›®ã€‚"
msgid "Schedule a new pipeline"
msgstr "新建æµæ°´çº¿è®¡åˆ’"
@@ -9597,7 +11422,7 @@ msgid "Scoped issue boards"
msgstr "指定范围的议题看æ¿"
msgid "Scoped label"
-msgstr ""
+msgstr "有范围标记"
msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
msgstr "å‘下滚动到 <strong>Google Code项目托管</strong> 并通过å³ä¾§çš„开关å¯ç”¨ã€‚"
@@ -9623,9 +11448,21 @@ msgstr "æœç´¢åˆ†æ”¯å’Œæ ‡ç­¾"
msgid "Search files"
msgstr "æœç´¢æ–‡ä»¶"
+msgid "Search for a LDAP group"
+msgstr "æœç´¢LDAP组"
+
+msgid "Search for a group"
+msgstr "æœç´¢ç¾¤ç»„"
+
+msgid "Search for a user"
+msgstr "æœç´¢ç”¨æˆ·"
+
msgid "Search for projects, issues, etc."
msgstr "æœç´¢é¡¹ç›®ã€è®®é¢˜ç­‰ç­‰â€¦"
+msgid "Search forks"
+msgstr "æœç´¢æ´¾ç”Ÿ"
+
msgid "Search groups"
msgstr "æœç´¢ç¾¤ç»„"
@@ -9647,6 +11484,9 @@ msgstr "æœç´¢é¡¹ç›®"
msgid "Search projects"
msgstr "æœç´¢é¡¹ç›®"
+msgid "Search projects..."
+msgstr "æœç´¢é¡¹ç›®..."
+
msgid "Search users"
msgstr "æœç´¢ç”¨æˆ·"
@@ -9681,13 +11521,13 @@ msgid "SearchAutocomplete|in this project"
msgstr "在此项目"
msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for \"%{term}\""
-msgstr ""
+msgstr "显示%{scope}中共%{count}项\"%{term}\"的第%{from}项 - 第%{to}项"
msgid "Seats currently in use"
-msgstr ""
+msgstr "当å‰æ­£åœ¨ä½¿ç”¨çš„用户数é‡"
msgid "Seats in license"
-msgstr ""
+msgstr "许å¯è¯ç”¨æˆ·æ•°é‡"
msgid "Secret"
msgstr "密ç "
@@ -9722,9 +11562,6 @@ msgstr "了解更多关于您的仪表æ¿è®¾ç½®"
msgid "Security Reports|More info"
msgstr "更多信æ¯"
-msgid "Security Reports|No Vulnerabilities"
-msgstr "æ— æ¼æ´ž"
-
msgid "Security Reports|There was an error creating the issue."
msgstr "创建议题时出错。"
@@ -9755,12 +11592,24 @@ msgstr "安全仪表盘"
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr "安全仪表æ¿æ˜¾ç¤ºæœ€æ–°çš„安全报告。用它æ¥æŸ¥æ‰¾å’Œä¿®å¤æ¼æ´žã€‚"
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr "监控代ç ä¸­çš„æ¼æ´ž"
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr "æµæ°´çº¿ %{pipelineLink} 已触å‘"
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr "查看指标"
@@ -9773,6 +11622,12 @@ msgstr "选择"
msgid "Select Archive Format"
msgstr "选择下载格å¼"
+msgid "Select Page"
+msgstr "选择页é¢"
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr "请先从左侧边æ é€‰æ‹©ä¸€ä¸ªæ–‡ä»¶å¼€å§‹ç¼–辑,然åŽå°±å¯ä»¥æ交您的更改了。"
+
msgid "Select a group to invite"
msgstr "选择è¦é‚€è¯·çš„组"
@@ -9780,13 +11635,13 @@ msgid "Select a namespace to fork the project"
msgstr "选择一个命å空间æ¥æ´¾ç”Ÿé¡¹ç›®"
msgid "Select a new namespace"
-msgstr ""
+msgstr "选择一个新的命å空间"
msgid "Select a project to read Insights configuration file"
msgstr "选择è¦è¯»å– Insights é…置文件的项目"
msgid "Select a repository"
-msgstr "选择一个存储库"
+msgstr "选择一个仓库"
msgid "Select a template repository"
msgstr "选择模æ¿ä»“库"
@@ -9800,6 +11655,9 @@ msgstr "选择一个既有的Kubernetes集群或者创建一个新的"
msgid "Select branch/tag"
msgstr "选择分支/标签"
+msgid "Select group or project"
+msgstr "选择群组或项目"
+
msgid "Select members to invite"
msgstr "选择è¦é‚€è¯·çš„æˆå‘˜"
@@ -9825,7 +11683,7 @@ msgid "Select the branch you want to set as the default for this project. All me
msgstr "选择当å‰é¡¹ç›®çš„默认分支。除éžå¦è¡ŒæŒ‡å®šï¼Œå¦åˆ™æ‰€æœ‰åˆå¹¶è¯·æ±‚å’Œæ交都将指å‘此分支。"
msgid "Select the custom project template source group."
-msgstr "选择自定义项目模æ¿æºç»„。"
+msgstr "选择自定义项目模æ¿æºç¾¤ç»„。"
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr "éžç®¡ç†å‘˜ç”¨æˆ·æ— æ³•ä¸ºç¾¤ç»„ã€é¡¹ç›®æˆ–代ç ç‰‡æ®µä½¿ç”¨æ‰€é€‰çº§åˆ«ã€‚如果公共级别å—到é™åˆ¶ï¼Œåˆ™ç”¨æˆ·é…置文件仅对登录用户å¯è§ã€‚"
@@ -9836,6 +11694,9 @@ msgstr "选中GitLab用户将在议题和评论的æ述中加入指å‘该GitLab
msgid "Send an email notification to Developers."
msgstr "å‘å¼€å‘人员å‘é€ç”µå­é‚®ä»¶é€šçŸ¥ã€‚"
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr "å‘é€ç”µå­é‚®ä»¶"
@@ -9852,13 +11713,13 @@ msgid "Sep"
msgstr "9月"
msgid "Separate topics with commas."
-msgstr ""
+msgstr "用逗å·åˆ†éš”主题。"
msgid "September"
msgstr "9月"
msgid "Server supports batch API only, please update your Git LFS client to version 1.0.1 and up."
-msgstr ""
+msgstr "æœåŠ¡å™¨ä»…支æŒæ‰¹å¤„ç†API,请将您的Git LFS客户端更新到1.0.1åŠæ›´é«˜ç‰ˆæœ¬ã€‚"
msgid "Server version"
msgstr "æœåŠ¡å™¨ç‰ˆæœ¬"
@@ -9867,22 +11728,22 @@ msgid "Serverless"
msgstr "Serverless"
msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
-msgstr ""
+msgstr "函数调用指标需è¦é¦–先安装Prometheus。"
msgid "ServerlessDetails|Install Prometheus"
-msgstr ""
+msgstr "安装Prometheus"
msgid "ServerlessDetails|Invocation metrics loading or not available at this time."
-msgstr ""
+msgstr "调用指标目å‰æ­£åœ¨åŠ è½½æˆ–ä¸å¯ç”¨ã€‚"
msgid "ServerlessDetails|Invocations"
-msgstr ""
+msgstr "调用次数"
msgid "ServerlessDetails|Kubernetes Pods"
msgstr "Kubernestes Pods"
msgid "ServerlessDetails|More information"
-msgstr ""
+msgstr "更多信æ¯"
msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
msgstr "æ ¹æ®éœ€è¦éšæ—¶é—´æŽ¨ç§»ä½¿ç”¨çš„Kubernetes Podæ•°é‡ã€‚"
@@ -9917,6 +11778,9 @@ msgstr "没有å¯ç”¨çš„功能"
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr " Knativeç›®å‰æ²¡æœ‰å¯ç”¨çš„功能数æ®ã€‚è¿™å¯èƒ½æœ‰å¤šç§åŽŸå› ï¼ŒåŒ…括:"
+msgid "Service"
+msgstr "æœåŠ¡"
+
msgid "Service Desk"
msgstr "æœåŠ¡å°"
@@ -9933,7 +11797,7 @@ msgid "Session expiration, projects limit and attachment size."
msgstr "会è¯æœ‰æ•ˆæœŸï¼Œé¡¹ç›®é™åˆ¶åŠé™„件大å°ã€‚"
msgid "Set a default template for issue descriptions."
-msgstr ""
+msgstr "设置议题æ述的默认模æ¿ã€‚"
msgid "Set a number of approvals required, the approvers and other approval settings."
msgstr "设置所需的核准数é‡ï¼Œæ ¸å‡†è€…和其他核准设置。"
@@ -9947,35 +11811,41 @@ msgstr "为该群组中的项目设置模æ¿ä»“库"
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr "设定缺çœåŠå—é™å¯è§æ€§çº§åˆ«ã€‚é…置导入æ¥æºåŠgit访问å议。"
+msgid "Set due date"
+msgstr "设置截止日期"
+
msgid "Set instance-wide template repository"
-msgstr "设置实例范围的模æ¿å­˜å‚¨åº“"
+msgstr "设置实例范围的模æ¿ä»“库"
msgid "Set max session time for web terminal."
msgstr "为Web终端设置最长会è¯æ—¶é—´ã€‚"
+msgid "Set milestone"
+msgstr "设置里程碑"
+
msgid "Set new password"
msgstr "设置新密ç "
msgid "Set notification email for abuse reports."
msgstr "为滥用报告设置通知电å­é‚®ä»¶ã€‚"
-msgid "Set number of approvers required before open merge requests can be merged"
-msgstr "设置åˆå¹¶æœªå…³é—­çš„åˆå¹¶è¯·æ±‚之å‰æ‰€éœ€çš„核准人数é‡"
-
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr "设定用户登录的æ¡ä»¶ã€‚å¯ç”¨å¼ºåˆ¶åŒé‡è®¤è¯ã€‚"
msgid "Set the default expiration time for each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: <code>4 mins 2 sec</code>, <code>2h42min</code>."
-msgstr "设置æ¯ä¸ªä½œä¸šçš„工件的默认到期时间。 0 表示无é™åˆ¶ã€‚默认以秒为å•ä½ï¼Œä½†æ‚¨å¯ä»¥å®šä¹‰æ›¿ä»£æ–¹æ¡ˆã€‚例如:<code>4 mins 2 sec</code>, <code>2h42min</code>.。"
+msgstr "设置æ¯ä¸ªä½œä¸šçš„产物的默认到期时间。 0 表示无é™åˆ¶ã€‚默认以秒为å•ä½ï¼Œä½†æ‚¨å¯ä»¥å®šä¹‰æ›¿ä»£æ–¹æ¡ˆã€‚例如:<code>4 mins 2 sec</code>, <code>2h42min</code>.。"
msgid "Set the duration for which the jobs will be considered as old and expired. Once that time passes, the jobs will be archived and no longer able to be retried. Make it empty to never expire jobs. It has to be no less than 1 day, for example: <code>15 days</code>, <code>1 month</code>, <code>2 years</code>."
-msgstr "设置作业的过期时间。一旦逾期,作业将被存档并且ä¸èƒ½é‡è¯•ã€‚留空,则永ä¸è¿‡æœŸã€‚它必须设置为 1 天以上,例如: <code>15 days</code>, <code>1 month</code>, <code>2 years</code>。"
+msgstr "设置作业的过期时间。一旦逾期,作业将被归档并且ä¸èƒ½é‡è¯•ã€‚留空则永ä¸è¿‡æœŸã€‚必须设置为 1 天以上,例如: <code>15 days</code>, <code>1 month</code>, <code>2 years</code>。"
msgid "Set the maximum file size for each job's artifacts"
-msgstr "设置æ¯ä¸ªä½œä¸šçš„工件文件的最大大å°"
+msgstr "设置æ¯ä¸ªä½œä¸šçš„产物文件的最大大å°"
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
-msgstr "设置群组æ¯ä¸ªæœˆå¯åœ¨å…±äº«è¿è¡Œå™¨ä¸Šä½¿ç”¨çš„最大æµæ°´çº¿åˆ†é’Ÿæ•°ã€‚ 0 表示无é™åˆ¶ã€‚"
+msgstr "设置群组æ¯ä¸ªæœˆå¯åœ¨å…±äº«Runner上使用的最大æµæ°´çº¿åˆ†é’Ÿæ•°ã€‚ 0 表示无é™åˆ¶ã€‚"
+
+msgid "Set time estimate"
+msgstr "设置时间估计"
msgid "Set up CI/CD"
msgstr "é…ç½® CI/CD"
@@ -9984,7 +11854,7 @@ msgid "Set up a %{type} Runner manually"
msgstr "手动设置%{type} Runner "
msgid "Set up a specific Runner automatically"
-msgstr "自动创建专用Runner"
+msgstr "自动创建指定Runner"
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr "æ ¹æ®%{docsLinkStart}文档%{icon}%{docsLinkEnd}设置断言/属性/声明(email,first_name,last_name)和NameID"
@@ -9996,7 +11866,10 @@ msgid "Set up new password"
msgstr "设置新密ç "
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
-msgstr "设置项目以自动推é€å’Œ/或从å¦ä¸€ä¸ªå­˜å‚¨åº“中æå–更改。分支,标签和æ交将自动åŒæ­¥ã€‚"
+msgstr "设置项目以自动推é€å’Œ/或从å¦ä¸€ä¸ªä»“库中æå–更改。分支,标签和æ交将自动åŒæ­¥ã€‚"
+
+msgid "Set weight"
+msgstr "设置æƒé‡"
msgid "SetPasswordToCloneLink|set a password"
msgstr "设置密ç "
@@ -10025,6 +11898,18 @@ msgstr "对ä¸èµ·ï¼Œæˆ‘们无法设置您的状æ€ã€‚请ç¨åŽå†è¯•ã€‚"
msgid "SetStatusModal|What's your status?"
msgstr "您的状æ€æ˜¯ä»€ä¹ˆï¼Ÿ"
+msgid "Sets the due date to %{due_date}."
+msgstr "将截止日期设置为 %{due_date}。"
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr "将里程碑设置为 %{milestone_reference}。"
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr "将时间估计设置为 %{time_estimate}。"
+
+msgid "Sets weight to %{weight}."
+msgstr "å°†æƒé‡è®¾ç½®ä¸º %{weight}。"
+
msgid "Settings"
msgstr "设置"
@@ -10040,6 +11925,9 @@ msgstr "共享Runner"
msgid "Shared projects"
msgstr "分享项目"
+msgid "Shared runners help link"
+msgstr "共享Runner帮助链接"
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr "通过é‡ç½®æ­¤å‘½å空间的æµæ°´çº¿åˆ†é’Ÿæ•°ï¼Œå½“å‰ä½¿ç”¨çš„分钟数将被归零。"
@@ -10052,9 +11940,18 @@ msgstr "é‡ç½®å·²ç”¨æµæ°´çº¿åˆ†é’Ÿæ•°"
msgid "Sherlock Transactions"
msgstr "Sherlock事物"
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr "如果您一旦丢失手机或无法访问一次性密ç å¯†ä¿ï¼Œæ‚¨å¯ä»¥ä½¿ç”¨æ¢å¤ç æ¥é‡æ–°èŽ·å¾—您的å¸æˆ·è®¿é—®æƒé™ã€‚æ¯ä¸ªæ¢å¤ç ä»…å¯ä½¿ç”¨ä¸€æ¬¡ã€‚请将它们ä¿å­˜åœ¨å®‰å…¨çš„地方,å¦åˆ™ä¸¢å¤±åŽä½ %{b_start}å°†%{b_end}无法访问您的å¸æˆ·ã€‚"
+
msgid "Show all activity"
msgstr "显示所有活动"
+msgid "Show archived projects"
+msgstr "显示已归档的项目"
+
+msgid "Show archived projects only"
+msgstr "仅显示已归档项目"
+
msgid "Show command"
msgstr "显示相关命令"
@@ -10070,9 +11967,6 @@ msgstr "显示文件æµè§ˆå™¨"
msgid "Show latest version"
msgstr "显示最新版本"
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr "查看上级页é¢"
@@ -10125,21 +12019,42 @@ msgstr "使用智能å¡ç™»å½•"
msgid "Sign out"
msgstr "退出"
+msgid "Sign out & Register"
+msgstr "退出并注册"
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr "注册æˆåŠŸï¼è¯·ç¡®è®¤æ‚¨çš„电å­é‚®ä»¶ä»¥ç™»å½•ã€‚"
+
msgid "Sign-in restrictions"
msgstr "登录é™åˆ¶"
msgid "Sign-up restrictions"
msgstr "注册é™åˆ¶"
-msgid "Signing in using %{label} has been disabled"
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
msgstr ""
-msgid "Signing in using your %{label} account without a pre-existing GitLab account is not allowed."
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
msgstr ""
+msgid "Signed in"
+msgstr "已登录"
+
+msgid "Signed in with %{authentication} authentication"
+msgstr "使用%{authentication}进行身份验è¯"
+
+msgid "Signing in using %{label} has been disabled"
+msgstr "使用 %{label} 登录已被ç¦ç”¨"
+
+msgid "Signing in using your %{label} account without a pre-existing GitLab account is not allowed."
+msgstr "没有预先存在的GitLabå¸æˆ·çš„情况下无法使用您的%{label}å¸æˆ·ç™»å½•ã€‚"
+
msgid "Similar issues"
msgstr "相似议题"
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr "大å°"
@@ -10147,7 +12062,10 @@ msgid "Size and domain settings for static websites"
msgstr "é™æ€ç½‘站的大å°å’ŒåŸŸè®¾ç½®"
msgid "Size limit per repository (MB)"
-msgstr "æ¯ä¸ªå­˜å‚¨åº“的大å°é™åˆ¶ (MB)"
+msgstr "æ¯ä¸ªä»“库的大å°é™åˆ¶ (MB)"
+
+msgid "Skip this for now"
+msgstr "暂时跳过"
msgid "Slack application"
msgstr "Slack应用"
@@ -10174,13 +12092,13 @@ msgid "SnippetsEmptyState|Explore public snippets"
msgstr "探索公共代ç ç‰‡æ®µ"
msgid "SnippetsEmptyState|New snippet"
-msgstr "新代ç ç‰‡æ®µ"
+msgstr "新建代ç ç‰‡æ®µ"
msgid "SnippetsEmptyState|No snippets found"
msgstr "当å‰æ— ä»£ç ç‰‡æ®µ"
msgid "SnippetsEmptyState|Snippets are small pieces of code or notes that you want to keep."
-msgstr "代ç ç‰‡æ®µæ˜¯æ‚¨å¸Œæœ›ä¿ç•™çš„å°æ®µä»£ç æˆ–笔记。"
+msgstr "代ç ç‰‡å¯ä»¥ç”¨æ¥ä¿å­˜çš„å°æ®µä»£ç æˆ–笔记。"
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr "没有è¦æ˜¾ç¤ºçš„代ç ç‰‡æ®µã€‚"
@@ -10218,6 +12136,9 @@ msgstr "è¯•å›¾æ”¹å˜ %{issuableDisplayName} çš„é”定状æ€æ—¶å‡ºé”™äº†"
msgid "Something went wrong when toggling the button"
msgstr "点击按钮时出错"
+msgid "Something went wrong while adding your award. Please try again."
+msgstr "添加赞èµæ—¶å‡ºé”™ã€‚请å†è¯•ä¸€æ¬¡ã€‚"
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr "应用åŒæ„时出了点问题。请å†è¯•ä¸€æ¬¡ã€‚"
@@ -10236,8 +12157,11 @@ msgstr "获å–评论时出错。请ç¨åŽé‡è¯•ã€‚"
msgid "Something went wrong while fetching group member contributions"
msgstr "获å–群组æˆå‘˜è´¡çŒ®æ—¶å‡ºé”™"
+msgid "Something went wrong while fetching latest comments."
+msgstr "获å–最新评论时出错。"
+
msgid "Something went wrong while fetching related merge requests."
-msgstr ""
+msgstr "获å–相关的åˆå¹¶è¯·æ±‚时出错了。"
msgid "Something went wrong while fetching the environments for this merge request. Please try again."
msgstr "获å–æ­¤åˆå¹¶è¯·æ±‚的环境时出错,请ç¨åŽé‡è¯•ã€‚"
@@ -10246,7 +12170,7 @@ msgid "Something went wrong while fetching the projects."
msgstr "拉å–项目时å‘生错误。"
msgid "Something went wrong while fetching the registry list."
-msgstr "拉å–注册表列表时å‘生错误。"
+msgstr "拉å–é•œåƒåº“列表时å‘生错误。"
msgid "Something went wrong while merging this merge request. Please try again."
msgstr "åˆå¹¶æ­¤åˆå¹¶è¯·æ±‚时出错。请é‡è¯•ã€‚"
@@ -10260,20 +12184,23 @@ msgstr "解决当å‰è®¨è®ºæ—¶å‡ºé”™ï¼Œè¯·é‡è¯•ã€‚"
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr "å°†%{project} 添加到仪表æ¿æ—¶å‡ºé”™"
-msgid "Something went wrong, unable to get operations projects"
-msgstr "获å–æ“作项目时出错"
+msgid "Something went wrong, unable to get projects"
+msgstr "出现了错误,无法获å–项目"
msgid "Something went wrong, unable to remove project"
msgstr "删除项目时出错"
msgid "Something went wrong, unable to search projects"
-msgstr ""
+msgstr "出错了,无法æœç´¢é¡¹ç›®"
msgid "Something went wrong. Please try again."
msgstr "出现错误。请é‡è¯•ã€‚"
+msgid "Something went wrong. Try again later."
+msgstr "出现错误。请ç¨åŽå†è¯•ã€‚"
+
msgid "Sorry, no epics matched your search"
-msgstr "对ä¸èµ·ï¼Œæœªæœç´¢åˆ°ä»»ä½•ç¬¦åˆæ¡ä»¶çš„epic"
+msgstr "对ä¸èµ·ï¼Œæœªæœç´¢åˆ°ä»»ä½•ç¬¦åˆæ¡ä»¶çš„å²è¯—"
msgid "Sorry, no projects matched your search"
msgstr "对ä¸èµ·ï¼Œæœªæœç´¢åˆ°ä»»ä½•ç¬¦åˆæ¡ä»¶çš„项目"
@@ -10315,7 +12242,7 @@ msgid "SortOptions|Largest repository"
msgstr "最大仓库"
msgid "SortOptions|Last Contact"
-msgstr "最åŽè”系人"
+msgstr "最åŽè”ç³»"
msgid "SortOptions|Last created"
msgstr "最近创建"
@@ -10332,6 +12259,9 @@ msgstr "最ä¸å—欢迎"
msgid "SortOptions|Less weight"
msgstr "é™ä½Žæƒé‡"
+msgid "SortOptions|Manual"
+msgstr "手动"
+
msgid "SortOptions|Milestone due date"
msgstr "里程碑截止日期"
@@ -10386,6 +12316,12 @@ msgstr "最近一次活动"
msgid "SortOptions|Recent sign in"
msgstr "最近登录"
+msgid "SortOptions|Sort direction"
+msgstr "排åºæ–¹å‘"
+
+msgid "SortOptions|Stars"
+msgstr "Stars"
+
msgid "SortOptions|Start date"
msgstr "开始日期"
@@ -10417,13 +12353,13 @@ msgid "Spam Logs"
msgstr "垃圾信æ¯æ—¥å¿—"
msgid "Spam and Anti-bot Protection"
-msgstr "垃圾邮件åŠé˜²æœºå™¨äººä¿æŠ¤"
+msgstr "垃圾信æ¯åŠé˜²æœºå™¨äººä¿æŠ¤"
msgid "Spam log successfully submitted as ham."
-msgstr ""
+msgstr "垃圾信æ¯æ—¥å¿—å·²æˆåŠŸæ”¹ä¸ºæœ‰æ•ˆä¿¡æ¯æ交。"
msgid "Specific Runners"
-msgstr "专用Runner"
+msgstr "指定Runner"
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr "指定电å­é‚®ä»¶åœ°å€æ­£åˆ™è¡¨è¾¾å¼æ¨¡å¼ä»¥æ ‡è¯†é»˜è®¤å†…部用户。"
@@ -10458,6 +12394,9 @@ msgstr "已暂存的 %{type}"
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr "把一个标记加上星标,å¯å°†å…¶å˜ä¸ºä¼˜å…ˆæ ‡è®°ã€‚通过拖放æ¥è°ƒæ•´ä¼˜å…ˆæ ‡è®°çš„顺åºï¼Œå¯ä»¥æ”¹å˜ä»–们的相对优先级。"
+msgid "Star toggle failed. Try again later."
+msgstr "星标开关失败。请ç¨åŽå†è¯•ã€‚"
+
msgid "StarProject|Star"
msgstr "星标"
@@ -10480,7 +12419,10 @@ msgid "Stars"
msgstr "星标"
msgid "Start GitLab Ultimate trial"
-msgstr ""
+msgstr "å¯åŠ¨ GitLab Ultimate 试用"
+
+msgid "Start Indexing"
+msgstr "开始索引"
msgid "Start Web Terminal"
msgstr "å¯åŠ¨Web终端"
@@ -10489,7 +12431,7 @@ msgid "Start a %{new_merge_request} with these changes"
msgstr "由此更改 %{new_merge_request}"
msgid "Start a new merge request"
-msgstr ""
+msgstr "开始一个新的åˆå¹¶è¯·æ±‚"
msgid "Start a review"
msgstr "开始一个评审"
@@ -10512,6 +12454,12 @@ msgstr "开始讨论并关闭 %{noteable_name}"
msgid "Start discussion & reopen %{noteable_name}"
msgstr "开始讨论并é‡æ–°æ‰“å¼€ %{noteable_name}"
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "å¯åŠ¨ Runner!"
@@ -10525,7 +12473,7 @@ msgid "Started %{startsIn}"
msgstr "已开始 %{startsIn}"
msgid "Started asynchronous removal of all repository check states."
-msgstr ""
+msgstr "已开始所有仓库检查状æ€çš„异步删除。"
msgid "Starting..."
msgstr "正在å¯åŠ¨..."
@@ -10572,12 +12520,18 @@ msgstr "存储"
msgid "Storage:"
msgstr "存储:"
+msgid "StorageSize|Unknown"
+msgstr "未知"
+
msgid "Subgroups"
msgstr "å­ç¾¤ç»„"
msgid "Subgroups and projects"
msgstr "å­ç»„和项目"
+msgid "Subkeys"
+msgstr "å­å¯†é’¥"
+
msgid "Submit as spam"
msgstr "垃圾信æ¯ä¸¾æŠ¥"
@@ -10608,6 +12562,9 @@ msgstr "订阅日历"
msgid "Subscribed"
msgstr "已订阅"
+msgid "Subscription"
+msgstr "订阅"
+
msgid "SubscriptionTable|Billing"
msgstr "è´¦å•"
@@ -10615,7 +12572,7 @@ msgid "SubscriptionTable|Free"
msgstr "å…è´¹"
msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
-msgstr "GitLab å…许您继续使用您的订阅,å³ä½¿æ‚¨å·²è¶…过您购买的最大使用人数。您必须在续订时支付这些订阅。"
+msgstr "GitLab å…许您继续使用您的订阅,å³ä½¿æ‚¨å·²è¶…过您购买的最大用户数é‡ã€‚您必须在续订时支付这些订阅。"
msgid "SubscriptionTable|GitLab.com %{planName} %{suffix}"
msgstr "GitLab.com %{planName} %{suffix}"
@@ -10630,19 +12587,19 @@ msgid "SubscriptionTable|Manage"
msgstr "管ç†"
msgid "SubscriptionTable|Max seats used"
-msgstr "最大的使用人数"
+msgstr "已使用的最大用户数é‡"
msgid "SubscriptionTable|Next invoice"
msgstr "下一张å‘票"
msgid "SubscriptionTable|Seats currently in use"
-msgstr "当å‰æ­£åœ¨ä½¿ç”¨çš„人数"
+msgstr "当å‰æ­£åœ¨ä½¿ç”¨çš„用户数é‡"
msgid "SubscriptionTable|Seats in subscription"
-msgstr "订阅中的人数"
+msgstr "订阅中的用户数é‡"
msgid "SubscriptionTable|Seats owed"
-msgstr "欠款人数"
+msgstr "欠款用户数é‡"
msgid "SubscriptionTable|Subscription end date"
msgstr "订阅结æŸæ—¥æœŸ"
@@ -10660,7 +12617,7 @@ msgid "SubscriptionTable|This is the next date when the GitLab.com team is sched
msgstr "这是 GitLab.com 团队下一次与您è”系的时间,关于您的欠款。"
msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
-msgstr "这是您更新到付费方案时需è¦è´­ä¹°çš„最大使用人数。"
+msgstr "这是您更新到付费方案时需è¦è´­ä¹°çš„最大用户数é‡ã€‚"
msgid "SubscriptionTable|Trial"
msgstr "试用"
@@ -10680,30 +12637,96 @@ msgstr "使用情况"
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr "使用次数将在æ¯å¤©ä¸­åˆ12:00进行更新。"
+msgid "Subtracts"
+msgstr "å‡åŽ»"
+
msgid "Successfully blocked"
-msgstr ""
+msgstr "æˆåŠŸç¦ç”¨"
msgid "Successfully confirmed"
-msgstr ""
+msgstr "æˆåŠŸç¡®è®¤"
msgid "Successfully deleted U2F device."
-msgstr ""
+msgstr "æˆåŠŸåˆ é™¤ U2F 设备。"
msgid "Successfully removed email."
-msgstr ""
+msgstr "æˆåŠŸåˆ é™¤ç”µå­é‚®ä»¶ã€‚"
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
-msgstr ""
+msgstr "æµæ°´çº¿å·²å®‰æŽ’è¿è¡Œã€‚请查看 %{pipelines_link_start}æµæ°´çº¿é¡µé¢%{pipelines_link_end}ä»¥äº†è§£è¯¦ç»†ä¿¡æ¯ ã€‚"
msgid "Successfully unblocked"
-msgstr ""
+msgstr "æˆåŠŸè§£é™¤ç¦ç”¨"
msgid "Successfully unlocked"
-msgstr ""
+msgstr "æˆåŠŸè§£é™¤ç¦ç”¨"
msgid "Suggested change"
msgstr "å˜æ›´å»ºè®®"
+msgid "SuggestedColors|Bright green"
+msgstr "亮绿色"
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr "æ·±ç°é’色"
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr "暗中è“色"
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr "暗中橙色"
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr "暗中粉红色"
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr "暗中紫色"
+
+msgid "SuggestedColors|Feijoa"
+msgstr "æ–济果绿"
+
+msgid "SuggestedColors|Lime green"
+msgstr "ç°ç»¿è‰²"
+
+msgid "SuggestedColors|Moderate blue"
+msgstr "中è“色"
+
+msgid "SuggestedColors|Pure red"
+msgstr "纯红色"
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr "略微ä¸é¥±å’Œè“色"
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr "略微ä¸é¥±å’Œç»¿è‰²"
+
+msgid "SuggestedColors|Soft orange"
+msgstr "浅橙色"
+
+msgid "SuggestedColors|Soft red"
+msgstr "浅红色"
+
+msgid "SuggestedColors|Strong pink"
+msgstr "深粉色"
+
+msgid "SuggestedColors|Strong red"
+msgstr "深红色"
+
+msgid "SuggestedColors|Strong yellow"
+msgstr "深黄色"
+
+msgid "SuggestedColors|UA blue"
+msgstr "æš—è“色"
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr "æžæš—ä¸é¥±å’Œè“色"
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr "æžæš—ç°ç»¿è‰²"
+
+msgid "SuggestedColors|Very pale orange"
+msgstr "æžæ·¡æ©™è‰²"
+
msgid "Sunday"
msgstr "星期日"
@@ -10711,11 +12734,17 @@ msgid "Support for custom certificates is disabled. Ask your system's administra
msgstr "对自定义è¯ä¹¦çš„支æŒå·²ç¦ç”¨ã€‚请è”系系统管ç†å‘˜æ¥å¯ç”¨å®ƒã€‚"
msgid "Support page URL"
-msgstr "支æŒé¡µé¢ URL"
+msgstr "支æŒé¡µé¢ç½‘å€"
msgid "Switch branch/tag"
msgstr "切æ¢åˆ†æ”¯/标签"
+msgid "Switch to GitLab Next"
+msgstr "切æ¢åˆ°GitLab Next"
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr "切æ¢åˆ°æºå°†å…¶å¤åˆ¶åˆ°å‰ªè´´æ¿"
+
msgid "Sync information"
msgstr "åŒæ­¥ä¿¡æ¯"
@@ -10726,7 +12755,7 @@ msgid "System Hooks"
msgstr "系统钩å­"
msgid "System Hooks Help"
-msgstr ""
+msgstr "系统钩å­å¸®åŠ©"
msgid "System Info"
msgstr "系统信æ¯"
@@ -10738,7 +12767,7 @@ msgid "System header and footer"
msgstr "系统页头和页脚"
msgid "System hook was successfully updated."
-msgstr ""
+msgstr "系统钩å­å·²æˆåŠŸæ›´æ–°ã€‚"
msgid "System metrics (Custom)"
msgstr "系统指标(自定义)"
@@ -10746,18 +12775,30 @@ msgstr "系统指标(自定义)"
msgid "System metrics (Kubernetes)"
msgstr "系统指标(Kubernetes)"
+msgid "Table of Contents"
+msgstr "目录"
+
msgid "Tag"
msgstr "标签"
msgid "Tag list:"
msgstr "标签列表:"
+msgid "Tag this commit."
+msgstr "为此æ交打标签。"
+
msgid "Tags"
msgstr "标签"
msgid "Tags feed"
msgstr "标签动æ€"
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr "使用“%{message}â€å°†æ­¤æ交设置%{tag_name}标签。"
+
+msgid "Tags this commit to %{tag_name}."
+msgstr "将此æ交设置%{tag_name}标签。"
+
msgid "Tags:"
msgstr "标签:"
@@ -10839,6 +12880,9 @@ msgstr "目标分支"
msgid "Team"
msgstr "团队"
+msgid "Team domain"
+msgstr "团队域"
+
msgid "Template"
msgstr "模æ¿"
@@ -10851,6 +12895,9 @@ msgstr "终端"
msgid "Terminal for environment"
msgstr "环境终端"
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "æœåŠ¡æ¡æ¬¾å议和éšç§æ”¿ç­–"
@@ -10864,10 +12911,37 @@ msgid "Test coverage parsing"
msgstr "测试覆盖率解æž"
msgid "Test failed."
-msgstr ""
+msgstr "测试失败。"
+
+msgid "Test settings and save changes"
+msgstr "测试设置并ä¿å­˜ä¿®æ”¹"
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr "ç¡®ä¿æ‚¨çš„任一项目中有åˆå¹¶è¯·æ±‚。"
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr "ç¡®ä¿é¡¹ç›®å…·æœ‰CI作业。"
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr "ç¡®ä¿é¡¹ç›®å…·æœ‰CIæµæ°´çº¿ã€‚"
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr "ç¡®ä¿é¡¹ç›®è‡³å°‘有一次æ交。"
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr "ç¡®ä¿é¡¹ç›®æœ‰è®®é¢˜ã€‚"
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr "ç¡®ä¿é¡¹ç›®æœ‰åˆå¹¶è¯·æ±‚。"
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr "ç¡®ä¿é¡¹ç›®æœ‰æ³¨é‡Šã€‚"
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr "ç¡®ä¿wikiå·²å¯ç”¨å¹¶å…·æœ‰é¡µé¢ã€‚"
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
-msgstr ""
+msgstr "感谢您的报告。 GitLab管ç†å‘˜å°†å°½å¿«è¿›è¡Œè°ƒæŸ¥ã€‚"
msgid "Thanks! Don't show me this again"
msgstr "ä¸å†æ˜¾ç¤º"
@@ -10877,7 +12951,7 @@ msgstr "群组“%{group_path}â€å…许您使用SSO以登录å¸æˆ·"
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
-msgstr[0] ""
+msgstr[0] "%{type} 包å«ä»¥ä¸‹é”™è¯¯ï¼š"
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr "GitLab 中的高级全局æœç´¢åŠŸèƒ½æ˜¯ä¸€ä¸ªå¼ºå¤§ä¸”节çœæ‚¨çš„时间的æœç´¢æœåŠ¡ã€‚您å¯ä»¥æœç´¢å…¶ä»–团队的代ç ä»¥å¸®åŠ©æ‚¨å®Œå–„自己项目中的代ç ã€‚从而é¿å…创建é‡å¤çš„代ç æˆ–浪费时间。"
@@ -10898,11 +12972,14 @@ msgid "The X509 Certificate to use when mutual TLS is required to communicate wi
msgstr "在需è¦ç›¸äº’ TLS 与外部授æƒæœåŠ¡é€šä¿¡æ—¶ä½¿ç”¨çš„ X509 è¯ä¹¦ã€‚如果ä¿ç•™ä¸ºç©º, 则在访问 HTTPS æ—¶ä»ç„¶éªŒè¯æœåŠ¡å™¨è¯ä¹¦ã€‚"
msgid "The amount of seconds after which a request to get a secondary node status will time out."
-msgstr ""
+msgstr "获å–辅助节点状æ€è¯·æ±‚超时的秒数。"
msgid "The branch for this project has no active pipeline configuration."
msgstr "此项目的分支没有活跃的æµæ°´çº¿é…置。"
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr "字符çªå‡ºæ˜¾ç¤ºå™¨å¸®åŠ©æ‚¨å°†ä¸»é¢˜è¡Œä¿æŒä¸º %{titleLength} 字符并将正文包装为 %{bodyLength} 以便它们在git中å¯è¯»ã€‚"
@@ -10916,65 +12993,77 @@ msgid "The connection will time out after %{timeout}. For repositories that take
msgstr "该连接将在 %{timeout}åŽè¶…时。如仓库导入耗时超过该时间,请使用克隆/推é€ç»„åˆã€‚"
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
+msgstr "此页é¢çš„内容未以UTF-8ç¼–ç ã€‚编辑åªèƒ½é€šè¿‡Git仓库进行。"
+
+msgid "The dependency list details information about the components used within your project."
msgstr ""
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr "将此作业部署为 %{environmentLink} 并未æˆåŠŸã€‚"
msgid "The directory has been successfully created."
-msgstr ""
+msgstr "目录已æˆåŠŸåˆ›å»ºã€‚"
msgid "The entered user map is not a valid JSON user map."
-msgstr ""
+msgstr "输入的用户映射ä¸æ˜¯æœ‰æ•ˆçš„JSON用户映射。"
msgid "The file has been successfully created."
-msgstr ""
+msgstr "文件已æˆåŠŸåˆ›å»ºã€‚"
msgid "The file has been successfully deleted."
-msgstr ""
+msgstr "文件已æˆåŠŸåˆ é™¤ã€‚"
msgid "The following items will NOT be exported:"
-msgstr ""
+msgstr "以下项目将ä¸ä¼šè¢«å¯¼å‡ºï¼š"
msgid "The following items will be exported:"
-msgstr ""
+msgstr "以下项目将会被导出:"
msgid "The fork relationship has been removed."
msgstr "派生关系已被删除。"
msgid "The global settings require you to enable Two-Factor Authentication for your account."
-msgstr ""
+msgstr "系统设置è¦æ±‚您为å¸æˆ·å¯ç”¨åŒé‡è®¤è¯ã€‚"
msgid "The group and any internal projects can be viewed by any logged in user."
-msgstr ""
+msgstr "任何登录的用户都å¯ä»¥æŸ¥çœ‹è¯¥ç¾¤ç»„和任何内部项目。"
msgid "The group and any public projects can be viewed without any authentication."
-msgstr ""
+msgstr "群组和任何公共项目å¯ä»¥åœ¨æ²¡æœ‰ä»»ä½•èº«ä»½éªŒè¯çš„情况下查看。"
msgid "The group and its projects can only be viewed by members."
-msgstr ""
+msgstr "群组åŠå…¶é¡¹ç›®åªèƒ½ç”±æˆå‘˜æŸ¥çœ‹ã€‚"
msgid "The group settings for %{group_links} require you to enable Two-Factor Authentication for your account. You can %{leave_group_links}."
-msgstr ""
+msgstr "%{group_links} 的群组设置è¦æ±‚您为å¸æˆ·å¯ç”¨åŒé‡è®¤è¯ã€‚你也å¯ä»¥ %{leave_group_links}。"
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "该导入过程将在 %{timeout}åŽè¶…时。对于需è¦é•¿äºŽè¯¥æ—¶é—´æ‰èƒ½å¯¼å…¥çš„仓库,请使用克隆/推é€ç»„åˆã€‚"
msgid "The invitation could not be accepted."
-msgstr ""
+msgstr "无法接å—邀请。"
msgid "The invitation could not be declined."
-msgstr ""
+msgstr "无法拒ç»é‚€è¯·"
msgid "The invitation has already been accepted."
-msgstr ""
+msgstr "邀请已被接å—。"
msgid "The invitation was successfully resent."
-msgstr ""
+msgstr "邀请已é‡æ–°å‘é€ã€‚"
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "议题阶段概述了从创建议题到将议题添加到里程碑或议题看æ¿æ‰€èŠ±è´¹çš„时间。创建第一个议题åŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„.。"
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr "许å¯è¯å·²è¢«åˆ é™¤ã€‚ GitLabå·²ç»å›žé€€åˆ°å‰ä¸€ä¸ªè®¸å¯è¯ã€‚"
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr "许å¯è¯å·²è¢«åˆ é™¤ã€‚ GitLab当å‰æ— æœ‰æ•ˆçš„许å¯è¯ã€‚"
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr "许å¯è¯å·²æˆåŠŸä¸Šä¼ ï¼ŒçŽ°åœ¨å¤„于激活状æ€ã€‚详细信æ¯å¦‚下。"
+
msgid "The maximum file size allowed is %{size}."
msgstr "å…许的最大文件大å°ä¸º %{size}。"
@@ -10982,17 +13071,23 @@ msgid "The maximum file size allowed is 200KB."
msgstr "文件大å°é™åˆ¶ä¸º 200KB。"
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
-msgstr ""
+msgstr "GitLab无法解决此åˆå¹¶è¯·æ±‚çš„åˆå¹¶å†²çªã€‚请å°è¯•åœ¨æœ¬åœ°è§£å†³å®ƒä»¬ã€‚"
msgid "The merge conflicts for this merge request have already been resolved."
-msgstr ""
+msgstr "æ­¤åˆå¹¶è¯·æ±‚çš„åˆå¹¶å†²çªå·²è§£å†³ã€‚"
msgid "The merge conflicts for this merge request have already been resolved. Please return to the merge request."
-msgstr ""
+msgstr "æ­¤åˆå¹¶è¯·æ±‚çš„åˆå¹¶å†²çªå·²å¾—到解决。请返回åˆå¹¶è¯·æ±‚。"
msgid "The name %{entryName} is already taken in this directory."
msgstr "å称%{entryName}在此目录中已使用。"
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr "上载记录无法找到相应文件的次数"
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "解密ç§é’¥æ‰€éœ€çš„密ç çŸ­è¯­ã€‚该项为å¯é€‰é¡¹, 并且内容被加密存储。"
@@ -11017,20 +13112,35 @@ msgstr "生产阶段概述了从创建一个议题到将代ç éƒ¨ç½²åˆ°ç”Ÿäº§çŽ¯
msgid "The project can be accessed by any logged in user."
msgstr "该项目å…许所有已登录到当å‰GitLabæœåŠ¡å™¨çš„用户访问。"
+msgid "The project can be accessed by any user who is logged in."
+msgstr "任何登录的用户都å¯ä»¥è®¿é—®è¯¥é¡¹ç›®ã€‚"
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr "任何人都å¯ä»¥è®¿é—®è¯¥é¡¹ç›®ï¼Œä¸è®ºç”¨æˆ·æ˜¯å¦è®¤è¯ã€‚"
+
msgid "The project can be accessed without any authentication."
msgstr "该项目å…许任何人访问。"
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr "项目åªèƒ½ç”±é¡¹ç›®æˆå‘˜è®¿é—®ã€‚必须明确地å‘æ¯ä¸ªç”¨æˆ·æŽˆäºˆè®¿é—®æƒé™ã€‚"
+
+msgid "The project is still being deleted. Please try again later."
+msgstr "该项目ä»åœ¨åˆ é™¤ä¸­ã€‚请ç¨åŽå†è¯•ã€‚"
+
msgid "The project was successfully forked."
-msgstr ""
+msgstr "该项目æˆåŠŸæ´¾ç”Ÿã€‚"
msgid "The project was successfully imported."
-msgstr ""
+msgstr "该项目已æˆåŠŸå¯¼å…¥ã€‚"
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr "匿å化数æ®æœé›†å·²ç¦ç”¨ã€‚该功能å¯ç”¨æ—¶ï¼ŒGitLab会è¿è¡ŒåŽå°ä»»åŠ¡ï¼Œç”Ÿæˆæ•°æ®åº“的匿å化CSV,并上传到预先设定的对象存储目录。"
+msgid "The remote mirror took to long to complete."
+msgstr "远程仓库镜åƒè¶…时未完æˆã€‚"
+
msgid "The remote repository is being updated..."
-msgstr ""
+msgstr "远程仓库正在更新......"
msgid "The repository for this project does not exist."
msgstr "此项目的仓库ä¸å­˜åœ¨ã€‚"
@@ -11038,6 +13148,9 @@ msgstr "此项目的仓库ä¸å­˜åœ¨ã€‚"
msgid "The repository for this project is empty"
msgstr "该项目的仓库是空的"
+msgid "The repository is being updated..."
+msgstr "仓库正在更新......"
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr "该仓库必须å¯é€šè¿‡<code>http://</code>, <code>https://</code> 或 <code>git://</code>进行访问。"
@@ -11048,22 +13161,22 @@ msgid "The review stage shows the time from creating the merge request to mergin
msgstr "审阅阶段概述了从创建åˆå¹¶è¯·æ±‚到被åˆå¹¶çš„时间。当创建第一个åˆå¹¶è¯·æ±‚åŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„。"
msgid "The roadmap shows the progress of your epics along a timeline"
-msgstr "路线图显示了 epic 沿ç€æ—¶é—´çº¿çš„进展情况"
+msgstr "路线图显示了 å²è¯— 沿ç€æ—¶é—´çº¿çš„进展情况"
msgid "The schedule time must be in the future!"
-msgstr ""
+msgstr "计划è¿è¡Œæ—¶é—´å¿…须在将æ¥ï¼"
msgid "The snippet can be accessed without any authentication."
-msgstr ""
+msgstr "无需任何身份验è¯å³å¯è®¿é—®è¯¥ä»£ç ç‰‡æ®µã€‚"
msgid "The snippet is visible only to me."
-msgstr ""
+msgstr "该代ç ç‰‡æ®µä»…对我å¯è§ã€‚"
msgid "The snippet is visible only to project members."
-msgstr ""
+msgstr "该代ç ç‰‡æ®µä»…对项目æˆå‘˜å¯è§ã€‚"
msgid "The snippet is visible to any logged in user."
-msgstr ""
+msgstr "任何登录用户都å¯ä»¥çœ‹åˆ°è¯¥ä»£ç ç‰‡æ®µã€‚"
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "预å‘布阶段概述了从åˆå¹¶è¯·æ±‚被åˆå¹¶åˆ°éƒ¨ç½²è‡³ç”Ÿäº§çŽ¯å¢ƒçš„总时间。首次部署到生产环境åŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„。"
@@ -11077,20 +13190,23 @@ msgstr "测试阶段概述了 GitLab CI 为相关åˆå¹¶è¯·æ±‚è¿è¡Œæ¯ä¸ªæµæ°´ç
msgid "The time taken by each data entry gathered by that stage."
msgstr "该阶段æ¯æ¡æ•°æ®æ‰€èŠ±çš„时间"
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr "Geo节点的唯一标识符。如果在 gitlab. rb 中设置, åˆ™éœ€åŒ¹é… \"geo_node_name\", å¦åˆ™å¿…须与 \"external_url\" 匹é…"
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
-msgstr "æ›´æ–°æ“作将在 %{number_of_minutes} 分钟åŽè¶…时。对于大型存储库,请使用clone/push组åˆã€‚"
+msgstr "æ›´æ–°æ“作将在 %{number_of_minutes} 分钟åŽè¶…时。对于大型仓库,请使用clone/push组åˆã€‚"
msgid "The uploaded file is not a valid Google Takeout archive."
-msgstr ""
+msgstr "上传的文件ä¸æ˜¯æœ‰æ•ˆçš„ Google Takeout 档案。"
msgid "The usage ping is disabled, and cannot be configured through this form."
msgstr "使用情况检测(usage ping)å·²ç¦ç”¨ï¼Œæ— æ³•é€šè¿‡æ­¤è¡¨å•è¿›è¡Œé…置。"
msgid "The user is being deleted."
-msgstr ""
+msgstr "用户正在被删除。"
msgid "The user map has been saved. Continue by selecting the projects you want to import."
-msgstr ""
+msgstr "用户映射已ä¿å­˜ã€‚请选择è¦å¯¼å…¥çš„项目以继续。"
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr "用户映射是一个JSON文档,将å‚与项目的Google Code用户映射到他们将导入GitLab的电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·åçš„æ–¹å¼ã€‚您å¯ä»¥é€šè¿‡æ›´æ”¹ <code>:</code>å³ä¾§çš„值æ¥æ›´æ”¹æ­¤å€¼ã€‚请务必在左侧ä¿ç•™å‘¨å›´çš„åŒå¼•å·ï¼Œå…¶ä»–标点符å·ä»¥åŠç”µå­é‚®ä»¶åœ°å€æˆ–用户å。"
@@ -11098,15 +13214,30 @@ msgstr "用户映射是一个JSON文档,将å‚与项目的Google Code用户映
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr "用户映射是å‚与项目的 FogBugz 用户的电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·å将被导入 GitLab çš„æ–¹å¼ã€‚您å¯ä»¥é€šè¿‡ä»¥ä¸‹è¡¨æ ¼æ¥ä¿®æ”¹æ˜ å°„关系。"
+msgid "The user-facing URL of the Geo node."
+msgstr "é¢å‘用户的Geo节点URL。"
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "中ä½æ•°æ˜¯ä¸€ä¸ªæ•°åˆ—中最中间的值。例如在 3ã€5ã€9 之间,中ä½æ•°æ˜¯ 5。在 3ã€5ã€7ã€8 之间,中ä½æ•°æ˜¯ (5 + 7)/ 2 = 6。"
-msgid "There are no approvers"
-msgstr "没有核准人"
+msgid "There are no GPG keys associated with this account."
+msgstr "没有与此账户关è”çš„GPG密钥。"
+
+msgid "There are no GPG keys with access to your account."
+msgstr "没有å¯è®¿é—®æ‚¨çš„å¸æˆ·çš„GPG密钥。"
+
+msgid "There are no SSH keys associated with this account."
+msgstr "没有与此账户关è”çš„SSH密钥。"
+
+msgid "There are no SSH keys with access to your account."
+msgstr "没有å¯è®¿é—®æ‚¨å¸æˆ·çš„SSH密钥。"
msgid "There are no archived projects yet"
msgstr "当å‰å°šæ— å·²å½’档的项目"
+msgid "There are no charts configured for this page"
+msgstr "没有为此页é¢é…置图表"
+
msgid "There are no closed issues"
msgstr "没有已关闭的议题"
@@ -11140,23 +13271,44 @@ msgstr "无已暂存的修改"
msgid "There are no unstaged changes"
msgstr "无未暂存的修改"
+msgid "There is already a repository with that name on disk"
+msgstr "ç£ç›˜ä¸Šå·²å­˜åœ¨å…·æœ‰è¯¥å称的仓库"
+
+msgid "There was a problem communicating with your device."
+msgstr "与您的设备通信时出现问题。"
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr "%{message}待办事项时出现错误"
+
msgid "There was an error adding a todo."
-msgstr "添加待办事项时出现错误"
+msgstr "添加待办事项时出现错误。"
+
+msgid "There was an error creating the issue"
+msgstr ""
msgid "There was an error deleting the todo."
msgstr "删除待办事项时出现错误。"
msgid "There was an error fetching configuration for charts"
-msgstr ""
+msgstr "获å–图表的é…置时出错"
msgid "There was an error gathering the chart data"
-msgstr ""
+msgstr "收集图表数æ®æ—¶å‡ºé”™"
msgid "There was an error loading users activity calendar."
msgstr "加载用户活动日历时出错。"
msgid "There was an error removing the e-mail."
-msgstr ""
+msgstr "删除电å­é‚®ä»¶æ—¶å‡ºé”™ã€‚"
+
+msgid "There was an error resetting group pipeline minutes."
+msgstr "é‡ç½®ç¾¤ç»„æµæ°´çº¿åˆ†é’Ÿæ•°æ—¶å‡ºé”™ã€‚"
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr "é‡ç½®ç”¨æˆ·æµæ°´çº¿åˆ†é’Ÿæ•°æ—¶å‡ºé”™ã€‚"
msgid "There was an error saving your changes."
msgstr "ä¿å­˜å˜æ›´æ—¶å‡ºé”™ã€‚"
@@ -11176,18 +13328,24 @@ msgstr "订阅此标记时出错。"
msgid "There was an error when unsubscribing from this label."
msgstr "å–消订阅此标记时出错。"
+msgid "There was an error while fetching cycle analytics data."
+msgstr "获å–周期分æžæ•°æ®æ—¶å‡ºé”™ã€‚"
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
+msgstr "reCAPTCHA 验è¯é”™è¯¯ã€‚请å†æ¬¡éªŒè¯ reCAPTCHA。"
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
msgstr "这些现有的议题具有类似的标题。在那里评论å¯èƒ½æ›´å¥½ï¼Œè€Œä¸æ˜¯åˆ›å»ºå¦ä¸€ä¸ªç±»ä¼¼çš„问题。"
msgid "They can be managed using the %{link}."
-msgstr "他们å¯ä»¥é€šè¿‡ %{link} 进行管ç†ã€‚"
+msgstr "å¯ä»¥ä½¿ç”¨ %{link} 进行托管。"
msgid "Third party offers"
msgstr "第三方优惠"
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr "这个 %{issuable} 已被é”定。åªæœ‰ <strong>项目æˆå‘˜</strong> å¯ä»¥å‘表评论。"
@@ -11198,7 +13356,10 @@ msgid "This GitLab instance does not provide any shared Runners yet. Instance ad
msgstr "æ­¤GitLab实例尚未æ供任何共享Runner。管ç†å‘˜å¯ä»¥åœ¨ç®¡ç†åŒºåŸŸä¸­æ³¨å†Œå…±äº«Runner。"
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
-msgstr ""
+msgstr "æ­¤æ“作å¯èƒ½å¯¼è‡´æ•°æ®ä¸¢å¤±ã€‚为防止æ„外,我们会è¦æ±‚您确认您的æ“作。"
+
+msgid "This also resolves the discussion"
+msgstr "这也解决了讨论"
msgid "This application was created by %{link_to_owner}."
msgstr "这个应用程åºæ˜¯ç”± %{link_to_owner} 创建的。"
@@ -11206,12 +13367,21 @@ msgstr "这个应用程åºæ˜¯ç”± %{link_to_owner} 创建的。"
msgid "This application will be able to:"
msgstr "此应用程åºå°†å¯ä»¥ï¼š"
+msgid "This block is self-referential"
+msgstr "该阻塞为自我引用"
+
msgid "This board's scope is reduced"
msgstr "此看æ¿èŒƒå›´ç¼©å°äº†"
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr "自您开始编辑åŽ, 此分支已更改。您想创建一个新的分支å—?"
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr "无法显示此图表"
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr "æ­¤æ交是åˆå¹¶è¯·æ±‚ %{link_to_merge_request} 的一部分。此处创建的评论将在该åˆå¹¶è¯·æ±‚的上下文中创建。"
@@ -11228,13 +13398,19 @@ msgid "This commit was signed with an <strong>unverified</strong> signature."
msgstr "æ­¤æ交使用 <strong>未ç»éªŒè¯çš„</strong> ç­¾å进行签å。"
msgid "This container registry has been scheduled for deletion."
-msgstr "此容器注册表已安排删除。"
+msgstr "此容器镜åƒåº“已安排删除。"
msgid "This date is after the due date, so this epic won't appear in the roadmap."
-msgstr "此日期在截止日期之åŽï¼Œå› æ­¤è¯¥ epic ä¸ä¼šå‡ºçŽ°åœ¨è·¯çº¿å›¾ä¸­ã€‚"
+msgstr "此日期在截止日期之åŽï¼Œå› æ­¤è¯¥ å²è¯— ä¸ä¼šå‡ºçŽ°åœ¨è·¯çº¿å›¾ä¸­ã€‚"
msgid "This date is before the start date, so this epic won't appear in the roadmap."
-msgstr "此日期在开始日期之å‰ï¼Œå› æ­¤è¯¥ epic ä¸ä¼šå‡ºçŽ°åœ¨è·¯çº¿å›¾ä¸­ã€‚"
+msgstr "此日期在开始日期之å‰ï¼Œå› æ­¤è¯¥ å²è¯— ä¸ä¼šå‡ºçŽ°åœ¨è·¯çº¿å›¾ä¸­ã€‚"
+
+msgid "This device has already been registered with us."
+msgstr "此设备已注册。"
+
+msgid "This device has not been registered with us."
+msgstr "此设备未注册。"
msgid "This diff is collapsed."
msgstr "此差异已折å ã€‚"
@@ -11248,6 +13424,9 @@ msgstr "当å‰ç›®å½•"
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr "此域å未ç»è¿‡éªŒè¯ã€‚在å¯ç”¨è®¿é—®æƒé™ä¹‹å‰ï¼Œæ‚¨éœ€è¦éªŒè¯æ‰€æœ‰æƒã€‚"
+msgid "This environment has no deployments yet."
+msgstr "此环境还没有部署。"
+
msgid "This field is required."
msgstr "该字段是必填字段。"
@@ -11257,23 +13436,32 @@ msgstr "当å‰ç¾¤ç»„"
msgid "This group does not provide any group Runners yet."
msgstr "该群组未æ供任何群组Runner。"
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr "此用户为“幽çµç”¨æˆ·â€ï¼Œç”¨äºŽæŒæœ‰è¢«åˆ é™¤ç”¨æˆ·çš„所有议题。该用户无法被删除。"
+
msgid "This is a confidential issue."
-msgstr "这是一个机密议题。"
+msgstr "这是一个ç§å¯†è®®é¢˜ã€‚"
msgid "This is a delayed job to run in %{remainingTime}"
msgstr "这是一个将在%{remainingTime}åŽè¿è¡Œçš„延时作业。"
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr "这是已登录到您å¸æˆ·çš„设备列表。您å¯ä»¥åˆ é™¤ä»»ä½•æ‚¨æ— æ³•è¯†åˆ«çš„会è¯ã€‚"
+
+msgid "This is a security log of important events involving your account."
+msgstr "这是一个涉åŠæ‚¨çš„å¸æˆ·é‡è¦äº‹ä»¶çš„安全日志。"
+
msgid "This is the author's first Merge Request to this project."
msgstr "这是作者为当å‰é¡¹ç›®è´¡çŒ®çš„第一个åˆå¹¶è¯·æ±‚。"
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
-msgstr ""
+msgstr "这是自许å¯è¯å¯ç”¨ä»¥æ¥åŒæ—¶å­˜åœ¨çš„最大用户数。续订许å¯è¯æ—¶ï¼Œæ‚¨æœ€å°‘需è¦è´­ä¹°æ­¤æ•°é‡çš„用户数。"
-msgid "This issue is confidential"
-msgstr "当å‰è®®é¢˜ä¸ºæœºå¯†è®®é¢˜"
+msgid "This is your current session"
+msgstr "这是您当å‰çš„会è¯"
-msgid "This issue is confidential and locked."
-msgstr "这个是机密且已é”定的议题。"
+msgid "This issue is confidential"
+msgstr "当å‰è®®é¢˜ä¸ºç§å¯†è®®é¢˜"
msgid "This issue is locked."
msgstr "此议题已é”定。"
@@ -11318,16 +13506,16 @@ msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr "作业挂起中,等待进入队列"
msgid "This job is performing tasks that must complete before it can start"
-msgstr ""
+msgstr "此作业正在处ç†ä½œä¸šå¯åŠ¨å‰å¿…须完æˆçš„任务"
msgid "This job is preparing to start"
-msgstr ""
+msgstr "此作业正准备开始"
msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
-msgstr "此作业被å¡ä½äº†ï¼Œå› ä¸ºæ‚¨æ²¡æœ‰ä»»ä½•åœ¨çº¿æ´»è·ƒçš„在è¿è¡Œå™¨ï¼Œå¹¶åˆ†é…了这些标签:"
+msgstr "此作业已å¡ä½ï¼Œå› ä¸ºæ‚¨æœªåˆ†é…任何具有这些标签的å¯ç”¨Runner:"
msgid "This job is stuck because you don't have any active runners that can run this job."
-msgstr "由于您没有任何å¯ä»¥è¿è¡Œæ­¤ä½œä¸šçš„活跃è¿è¡Œå™¨ï¼Œå› æ­¤ä½œä¸šå¡ä½äº†ã€‚"
+msgstr "由于您没有任何å¯ä»¥è¿è¡Œæ­¤ä½œä¸šçš„å¯ç”¨Runner,因此作业å¡ä½äº†ã€‚"
msgid "This job is the most recent deployment to %{link}."
msgstr "此作业最近部署到 %{link}。"
@@ -11344,14 +13532,8 @@ msgstr "在创建一个空的仓库或导入现有仓库之å‰ï¼Œå°†æ— æ³•æŽ¨é€
msgid "This merge request is locked."
msgstr "æ­¤åˆå¹¶è¯·æ±‚å·²é”定。"
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr "æ­¤åˆå¹¶è¯·æ±‚必须由这些群组的æˆå‘˜æ ¸å‡†ã€‚您å¯ä»¥é€šè¿‡è®¾ç½®è‡ªå·±çš„核准人列表æ¥è¦†ç›–项目设置。"
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr "æ­¤åˆå¹¶è¯·æ±‚必须得到这些用户的核准。您å¯ä»¥é€šè¿‡è®¾ç½®è‡ªå·±çš„核准人列表æ¥è¦†ç›–项目设置。"
-
msgid "This namespace has already been taken! Please choose another one."
-msgstr ""
+msgstr "此命å空间已被使用ï¼è¯·é€‰æ‹©å…¶ä»–命å空间。"
msgid "This option is disabled as you don't have write permissions for the current branch"
msgstr "由于您没有当å‰åˆ†æ”¯çš„写入æƒé™ï¼Œå› æ­¤ç¦ç”¨æ­¤é€‰é¡¹"
@@ -11363,7 +13545,7 @@ msgid "This page will be removed in a future release."
msgstr "此页é¢å°†åœ¨å°†æ¥çš„版本中删除。"
msgid "This pipeline is run on the source branch"
-msgstr ""
+msgstr "æ­¤æµæ°´çº¿åœ¨æºåˆ†æ”¯ä¸Šè¿è¡Œ"
msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
msgstr "æ­¤æµæ°´çº¿ä½¿ç”¨äº† %{strongStart}Auto DevOps 预先定义的并已å¯ç”¨çš„ CI/CD é…置。%{strongEnd}"
@@ -11387,7 +13569,7 @@ msgid "This repository"
msgstr "当å‰ä»“库"
msgid "This repository is currently empty. A new Auto DevOps pipeline will be created after a new file has been pushed to a branch."
-msgstr ""
+msgstr "此仓库目å‰ä¸ºç©ºã€‚将新文件推é€åˆ°åˆ†æ”¯åŽï¼Œå°†åˆ›å»ºæ–°çš„Auto DevOpsæµæ°´çº¿ã€‚"
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr "æ­¤Runner仅在å—ä¿æŠ¤åˆ†æ”¯ä¸Šè§¦å‘çš„æµæ°´çº¿ä¸Šè¿è¡Œ"
@@ -11402,7 +13584,7 @@ msgid "This timeout will take precedence when lower than project-defined timeout
msgstr "当低于项目定义的超时时,此超时将优先,并å¯æŽ¥å—英文语å¥ï¼Œå¦‚“1 hourâ€ã€‚默认å•ä½ä¸ºç§’。"
msgid "This user cannot be unlocked manually from GitLab"
-msgstr ""
+msgstr "无法从GitLab手动解ç¦æ­¤ç”¨æˆ·"
msgid "This user has no identities"
msgstr "该用户无身份标识"
@@ -11417,11 +13599,17 @@ msgid "This will redirect you to an external sign in page."
msgstr "这会将您é‡å®šå‘到外部登录页é¢ã€‚"
msgid "This will remove the fork relationship to source project"
-msgstr ""
+msgstr "æ­¤æ“作将删除与æºé¡¹ç›®çš„派生关系"
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr "这些电å­é‚®ä»¶è‡ªåŠ¨ç”Ÿæˆä¸ºè®®é¢˜(评论生æˆä¸ºç”µå­é‚®ä»¶ä¼šè¯)并在此处列出。"
+msgid "Thursday"
+msgstr "星期四"
+
+msgid "Time based: Yes"
+msgstr "基于时间:是"
+
msgid "Time before an issue gets scheduled"
msgstr "议题被列入日程表的时间"
@@ -11429,7 +13617,7 @@ msgid "Time before an issue starts implementation"
msgstr "开始进行编ç å‰çš„时间"
msgid "Time before enforced"
-msgstr "强制å‰æ—¶é—´"
+msgstr "宽容时间"
msgid "Time between merge request creation and merge/close"
msgstr "从创建åˆå¹¶è¯·æ±‚到被åˆå¹¶æˆ–关闭的时间"
@@ -11462,61 +13650,61 @@ msgid "TimeTracking|Spent"
msgstr "已用:"
msgid "Timeago|%s days ago"
-msgstr " %s 天å‰"
+msgstr " %s天å‰"
msgid "Timeago|%s days remaining"
-msgstr "剩余 %s 天"
+msgstr "剩余%s天"
msgid "Timeago|%s hours ago"
-msgstr "%s å°æ—¶å‰"
+msgstr "%så°æ—¶å‰"
msgid "Timeago|%s hours remaining"
-msgstr "剩余 %s å°æ—¶"
+msgstr "剩余%så°æ—¶"
msgid "Timeago|%s minutes ago"
-msgstr " %s 分钟å‰"
+msgstr " %s分钟å‰"
msgid "Timeago|%s minutes remaining"
-msgstr "剩余 %s 分钟"
+msgstr "剩余%s分钟"
msgid "Timeago|%s months ago"
-msgstr " %s 个月å‰"
+msgstr " %s个月å‰"
msgid "Timeago|%s months remaining"
-msgstr "剩余 %s 月"
+msgstr "剩余%s月"
msgid "Timeago|%s seconds remaining"
-msgstr "剩余 %s 秒"
+msgstr "剩余%s秒"
msgid "Timeago|%s weeks ago"
-msgstr " %s 星期å‰"
+msgstr " %s星期å‰"
msgid "Timeago|%s weeks remaining"
-msgstr "剩余 %s 星期"
+msgstr "剩余%s星期"
msgid "Timeago|%s years ago"
-msgstr " %s å¹´å‰"
+msgstr " %så¹´å‰"
msgid "Timeago|%s years remaining"
-msgstr "剩余 %s 年"
+msgstr "剩余%s年"
msgid "Timeago|1 day ago"
msgstr "1天å‰"
msgid "Timeago|1 day remaining"
-msgstr "剩余 1 天"
+msgstr "剩余1天"
msgid "Timeago|1 hour ago"
msgstr "1å°æ—¶å‰"
msgid "Timeago|1 hour remaining"
-msgstr "剩余 1 å°æ—¶"
+msgstr "剩余1å°æ—¶"
msgid "Timeago|1 minute ago"
msgstr "1分钟å‰"
msgid "Timeago|1 minute remaining"
-msgstr "剩余 1 分钟"
+msgstr "剩余1分钟"
msgid "Timeago|1 month ago"
msgstr "1个月å‰"
@@ -11528,55 +13716,55 @@ msgid "Timeago|1 week ago"
msgstr "1星期å‰"
msgid "Timeago|1 week remaining"
-msgstr "剩余 1 星期"
+msgstr "剩余1星期"
msgid "Timeago|1 year ago"
msgstr "1å¹´å‰"
msgid "Timeago|1 year remaining"
-msgstr "剩余 1 年"
+msgstr "剩余1年"
msgid "Timeago|Past due"
msgstr "逾期"
msgid "Timeago|in %s days"
-msgstr " %s 天åŽ"
+msgstr " %s天åŽ"
msgid "Timeago|in %s hours"
-msgstr " %s å°æ—¶åŽ"
+msgstr "%så°æ—¶åŽ"
msgid "Timeago|in %s minutes"
-msgstr " %s 分钟åŽ"
+msgstr "%s分钟åŽ"
msgid "Timeago|in %s months"
msgstr " %s个月åŽ"
msgid "Timeago|in %s seconds"
-msgstr " %s 秒åŽ"
+msgstr "%s秒åŽ"
msgid "Timeago|in %s weeks"
-msgstr " %s 星期åŽ"
+msgstr "%s星期åŽ"
msgid "Timeago|in %s years"
-msgstr " %s å¹´åŽ"
+msgstr "%så¹´åŽ"
msgid "Timeago|in 1 day"
-msgstr " 1 天åŽ"
+msgstr "1天åŽ"
msgid "Timeago|in 1 hour"
-msgstr " 1 å°æ—¶åŽ"
+msgstr "1å°æ—¶åŽ"
msgid "Timeago|in 1 minute"
-msgstr " 1 分钟åŽ"
+msgstr "1分钟åŽ"
msgid "Timeago|in 1 month"
-msgstr " 1 月åŽ"
+msgstr "1月åŽ"
msgid "Timeago|in 1 week"
-msgstr " 1 星期åŽ"
+msgstr "1星期åŽ"
msgid "Timeago|in 1 year"
-msgstr " 1 å¹´åŽ"
+msgstr "1å¹´åŽ"
msgid "Timeago|just now"
msgstr "刚刚"
@@ -11604,6 +13792,9 @@ msgstr "æ示:"
msgid "Title"
msgstr "标题"
+msgid "Title:"
+msgstr "标题:"
+
msgid "Titles and Filenames"
msgstr "标题和文件å称"
@@ -11611,7 +13802,7 @@ msgid "To %{link_to_help} of your domain, add the above key to a TXT record with
msgstr "è¦%{link_to_help}到您的域å,请将上述密钥添加到DNSé…置中的TXT记录。"
msgid "To GitLab"
-msgstr "到GitLab"
+msgstr "GitLab目标路径"
msgid "To access this domain create a new DNS record"
msgstr "è¦è®¿é—®æ­¤åŸŸï¼Œè¯·åˆ›å»ºæ–°çš„DNS记录"
@@ -11619,11 +13810,14 @@ msgstr "è¦è®¿é—®æ­¤åŸŸï¼Œè¯·åˆ›å»ºæ–°çš„DNS记录"
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr "è¦æ·»åŠ ä¸€ä¸ª SSH 密钥, æ‚¨éœ€è¦ %{generate_link_start} 生æˆä¸€ä¸ª %{link_end} 或使用一个 %{existing_link_start} 现有的 key%{link_end}。"
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr "如需手动添加æ¡ç›®ï¼Œè¯·åœ¨æ‰‹æœºåº”用中æ供以下信æ¯ã€‚"
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr "å¯ä»¥ä½¿ç”¨ %{personal_access_token_link} 连接GitHub仓库。当创建个人访问令牌时,需è¦é€‰æ‹© <code>repo</code> 范围,以显示å¯ä¾›è¿žæŽ¥çš„公开和ç§æœ‰çš„仓库列表。"
msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
-msgstr "è¦è¿žæŽ¥GitHub存储库,首先需è¦æŽˆæƒGitLab访问列表中的GitHub仓库:"
+msgstr "è¦è¿žæŽ¥GitHub仓库,首先需è¦æŽˆæƒGitLab访问列表中的GitHub仓库:"
msgid "To connect an SVN repository, check out %{svn_link}."
msgstr "如è¦è¿žæŽ¥SVN仓库,请查看 %{svn_link}。"
@@ -11685,11 +13879,14 @@ msgstr "è¦ä»Žæ‰‹åŠ¨é…置的PrometheusæœåŠ¡æŽ¥æ”¶è­¦æŠ¥ï¼Œè¯·å°†ä»¥ä¸‹URLå’ŒæŽ
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr "通过Azure,Okta,Onelogin,Ping Identity或自定义SAML 2.0等身份验è¯ç¨‹åºä¸ºæ‚¨çš„群组设置SAML身份验è¯ï¼š"
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr "è‹¥è¦æŒ‡å®šæ‚¨æ‰€å±žçš„群组的æ¯ä¸ªé¡¹ç›®çš„通知级别,您需è¦è®¿é—®é¡¹ç›®é¡µé¢ï¼Œæ›´æ”¹é€šçŸ¥çº§åˆ«ã€‚"
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr "è¦å¼€å§‹æ‰§è¡Œä»»åŠ¡ï¼Œè¯·æŠŠRunner加到群组中"
msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr "è¦å¼€å§‹ä½¿ç”¨ä½œä¸šï¼Œæ‚¨å¯ä»¥å‘项目添加特定的è¿è¡Œå™¨æˆ–使用共享的è¿è¡Œå™¨"
+msgstr "è¦å¼€å§‹ä½¿ç”¨ä½œä¸šï¼Œæ‚¨å¯ä»¥å‘项目添加指定Runner或使用共享Runner"
msgid "To this GitLab instance"
msgstr "转至此GitLab实例"
@@ -11698,7 +13895,7 @@ msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' in
msgstr "如需验è¯GitLab CI设置,请访问当å‰é¡¹ç›®çš„'CI/CD → æµæ°´çº¿',然åŽç‚¹å‡»'CI Lint'按钮。"
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr "如需查看路线图,请将计划的开始或结æŸæ—¥æœŸæ·»åŠ åˆ°å½“å‰ç¾¤ç»„或其å­ç»„中的æŸä¸ª epic。在月视图中,åªæ˜¾ç¤ºä¸Šä¸ªæœˆï¼Œæœ¬æœˆä»¥åŠæŽ¥ä¸‹æ¥5个月的 epic."
+msgstr "如需查看路线图,请将计划的开始或结æŸæ—¥æœŸæ·»åŠ åˆ°å½“å‰ç¾¤ç»„或其å­ç»„中的æŸä¸ª å²è¯—。在月视图中,åªæ˜¾ç¤ºä¸Šä¸ªæœˆï¼Œæœ¬æœˆä»¥åŠæŽ¥ä¸‹æ¥5个月的 å²è¯—."
msgid "To widen your search, change or remove filters above"
msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„过滤器"
@@ -11713,7 +13910,7 @@ msgid "Todo"
msgstr "待办事项"
msgid "Todo was successfully marked as done."
-msgstr ""
+msgstr "待办事项已标记为完æˆã€‚"
msgid "Todos"
msgstr "待办事项"
@@ -11721,6 +13918,9 @@ msgstr "待办事项"
msgid "Toggle Sidebar"
msgstr "切æ¢ä¾§è¾¹æ "
+msgid "Toggle backtrace"
+msgstr "切æ¢è°ƒç”¨æ ˆå›žæº¯(backtrace)"
+
msgid "Toggle comments for this file"
msgstr "切æ¢æ­¤æ–‡ä»¶çš„评论"
@@ -11733,9 +13933,15 @@ msgstr "切æ¢æ交列表"
msgid "Toggle discussion"
msgstr "开关讨论"
+msgid "Toggle emoji award"
+msgstr "切æ¢è¡¨æƒ…符å·èµžèµ"
+
msgid "Toggle navigation"
msgstr "切æ¢å¯¼èˆª"
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "切æ¢è¾¹æ "
@@ -11745,6 +13951,9 @@ msgstr "开关状æ€ï¼šå…³é—­"
msgid "ToggleButton|Toggle Status: ON"
msgstr "开关状æ€ï¼šå¼€å¯"
+msgid "Toggles :%{name}: emoji award."
+msgstr "åˆ‡æ¢ :%{name}: 表情符å·èµžèµã€‚"
+
msgid "Token"
msgstr "令牌"
@@ -11755,10 +13964,10 @@ msgid "Too many changes to show."
msgstr "è¦æ˜¾ç¤ºçš„å˜æ›´å¤ªå¤šã€‚"
msgid "Topics"
-msgstr ""
+msgstr "主题"
msgid "Total"
-msgstr ""
+msgstr "全部"
msgid "Total Contributions"
msgstr "贡献总计"
@@ -11785,6 +13994,42 @@ msgid "Track time with quick actions"
msgstr "使用快æ·æ“作æ¥ç»Ÿè®¡å·¥æ—¶"
msgid "Transfer project"
+msgstr "转移项目"
+
+msgid "TransferGroup|Database is not supported."
+msgstr "ä¸æ”¯æŒçš„æ•°æ®åº“。"
+
+msgid "TransferGroup|Group is already a root group."
+msgstr "群组已ç»æ˜¯ä¸€ä¸ªæ ¹ç¾¤ç»„。"
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr "群组已与父群组关è”。"
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr "父群组已ç»æœ‰ä¸€ä¸ªå…·æœ‰ç›¸åŒè·¯å¾„çš„å­ç¾¤ç»„。"
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr "转移失败: %{error_message}"
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr "您没有足够的æƒé™ã€‚"
+
+msgid "TransferProject|Cannot move project"
+msgstr "无法移动项目"
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr "请为项目选择新命å空间。"
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr "项目无法转移,因为标签存在于其容器镜åƒåº“中"
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr "目标命å空间中已存在具有相åŒå称或路径的项目"
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr "转移失败,请è”系管ç†å‘˜ã€‚"
+
+msgid "Tree"
msgstr ""
msgid "Tree view"
@@ -11800,7 +14045,7 @@ msgid "Trigger pipelines when branches or tags are updated from the upstream rep
msgstr "从上游仓库更新分支或标记时触å‘æµæ°´çº¿ã€‚如上游仓库更新频ç¹ï¼ŒCI Runnerçš„è´Ÿè·å¯èƒ½ä¼šå¤§å¤§å¢žåŠ ã€‚åªæœ‰æ˜Žç¡®CI Runner的处ç†èƒ½åŠ›èƒ½å¤Ÿæ‰¿å—这样的负è·æ—¶ï¼Œæ‰åº”å¯ç”¨æ­¤åŠŸèƒ½ã€‚"
msgid "Trigger removed."
-msgstr ""
+msgstr "触å‘器已删除。"
msgid "Trigger this manual action"
msgstr "触å‘此手动æ“作"
@@ -11812,19 +14057,19 @@ msgid "Trigger variables:"
msgstr "触å‘å˜é‡ï¼š"
msgid "Trigger was created successfully."
-msgstr ""
+msgstr "触å‘器已æˆåŠŸåˆ›å»ºã€‚"
msgid "Trigger was re-assigned."
-msgstr ""
+msgstr "触å‘器已é‡æ–°åˆ†é…。"
msgid "Trigger was successfully updated."
-msgstr ""
+msgstr "触å‘器已æˆåŠŸæ›´æ–°ã€‚"
msgid "Triggerer"
-msgstr "触å‘器"
+msgstr "触å‘者"
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
-msgstr "触å‘器å¯ä»¥é€šè¿‡ API 调用使特定的分支或标记被é‡æ–°æž„建,这些 token å¯ä»£è¡¨ä¸Žå…¶å…³è”的用户(包括该用户对项目的访问æƒé™ï¼‰"
+msgstr "触å‘器å¯ä»¥é€šè¿‡ API 调用使特定的分支或标签被é‡æ–°æž„建,这些 token å¯ä½¿ç”¨ä¸Žå…¶å…³è”的用户(包括该用户对项目的访问æƒé™)的身份"
msgid "Troubleshoot and monitor your application with tracing"
msgstr "使用跟踪对应用程åºè¿›è¡Œæ•…障排除与监控"
@@ -11838,17 +14083,32 @@ msgstr "é‡è¯•ï¼Ÿ"
msgid "Try all GitLab has to offer for 30 days."
msgstr "30天内体验GitLab的所有功能。"
+msgid "Try to fork again"
+msgstr "å°è¯•å†æ¬¡æ´¾ç”Ÿ"
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr "å°è¯•ä¸Žæ‚¨çš„设备通信。请将其æ’入并立å³æŒ‰ä¸‹ä¸Šçš„按钮。"
+msgid "Tuesday"
+msgstr "星期二"
+
msgid "Turn on Service Desk"
msgstr "å¯ç”¨æœåŠ¡å°"
msgid "Twitter"
msgstr "Twitter"
+msgid "Two-Factor Authentication"
+msgstr "åŒé‡è®¤è¯"
+
+msgid "Two-factor Authentication"
+msgstr "åŒé‡è®¤è¯"
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr "åŒé‡è®¤è¯æ¢å¤ç "
+
msgid "Two-factor Authentication has been disabled for this user"
-msgstr ""
+msgstr "此用户已ç¦ç”¨åŒé‡è®¤è¯"
msgid "Two-factor authentication"
msgstr "åŒé‡è®¤è¯"
@@ -11856,29 +14116,47 @@ msgstr "åŒé‡è®¤è¯"
msgid "Type"
msgstr "类型"
+msgid "U2F Devices (%{length})"
+msgstr "U2F设备(%{length})"
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr "U2Fåªæ”¯æŒåœ¨HTTPS的网站。请è”系管ç†å‘˜èŽ·å¾—更多信æ¯"
+
msgid "URL"
msgstr "URL"
msgid "Unable to connect to server: %{error}"
+msgstr "无法连接到æœåŠ¡å™¨: %{error}"
+
+msgid "Unable to generate new instance ID"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr "无法加载差异。 %{button_try_again}"
+msgid "Unable to resolve"
+msgstr "无法解决"
+
msgid "Unable to schedule a pipeline to run immediately"
-msgstr ""
+msgstr "无法安排æµæ°´çº¿ç«‹å³è¿è¡Œ"
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "由于\"%{reason}\"的原因,您暂时ä¸èƒ½è¿›å…¥é…置了SAML 的群组"
+msgid "Unable to update label prioritization at this time"
+msgstr "ç›®å‰æ— æ³•æ›´æ–°æ ‡è®°ä¼˜å…ˆçº§"
+
msgid "Unable to update this epic at this time."
-msgstr "当å‰æ— æ³•æ›´æ–°æ­¤ epic。"
+msgstr "当å‰æ— æ³•æ›´æ–°æ­¤ å²è¯—。"
+
+msgid "Unable to update this issue at this time."
+msgstr "当å‰æ— æ³•æ›´æ–°è¿™ä¸ªè®®é¢˜ã€‚"
msgid "Unarchive project"
-msgstr ""
+msgstr "å–消归档项目"
msgid "Unarchiving the project will restore people's ability to make changes to it. The repository can be committed to, and issues, comments and other entities can be created. <strong>Once active this project shows up in the search and on the dashboard.</strong>"
-msgstr ""
+msgstr "å–消项目存档将æ¢å¤ç”¨æˆ·å¯¹å…¶è¿›è¡Œæ›´æ”¹çš„能力。用户å¯ä»¥å°†æ交推é€åˆ°ä»“库, 并且å¯ä»¥åˆ›å»ºè®®é¢˜ã€è¯„论和其他对象。 <strong>此项目激活åŽ, 将显示在æœç´¢å’Œä»ªè¡¨æ¿ä¸Šã€‚</strong>"
msgid "Unblock"
msgstr "解除é”定"
@@ -11892,18 +14170,33 @@ msgstr "很é—憾,您å‘é€ç»™GitLab的电å­é‚®ä»¶æ— æ³•å¤„ç†ã€‚"
msgid "Unknown"
msgstr "未知的"
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr "未知的加密策略: %{encrypted_strategy}!"
+
+msgid "Unknown format"
+msgstr "未知的格å¼"
+
+msgid "Unknown response text"
+msgstr "未知的å“应文本"
+
msgid "Unlimited"
-msgstr ""
+msgstr "æ— é™"
msgid "Unlock"
msgstr "解é”"
+msgid "Unlock the discussion"
+msgstr "解é”讨论"
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr "è§£é” %{issuableDisplayName} ? <strong>所有人</strong> 都将å¯ä»¥å‘表评论。"
msgid "Unlocked"
msgstr "已解é”"
+msgid "Unlocks the discussion"
+msgstr "解é”讨论"
+
msgid "Unresolve discussion"
msgstr "待解决的讨论"
@@ -11965,19 +14258,31 @@ msgid "Update now"
msgstr "ç«‹å³æ›´æ–°"
msgid "Update your bookmarked URLs as filtered/sorted branches URL has been changed."
-msgstr ""
+msgstr "请更新您的书签 Url, 因为筛选/排åºçš„分支 URL 已更改。"
msgid "Update your group name, description, avatar, and visibility."
msgstr "更新您的群组å称ã€è¯´æ˜Žã€å¤´åƒä»¥åŠå¯è§æ€§ã€‚"
msgid "Update your project name, topics, description and avatar."
-msgstr ""
+msgstr "更新您的项目å称,主题,æ述和头åƒã€‚"
+
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr "因为项目容器镜åƒåº“已有标签,无法更新当å‰é¡¹ç›®ï¼"
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr "无法设置默认分支"
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr "ä¸å…许新的å¯è§æ€§çº§åˆ«ï¼"
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr "项目无法更新ï¼"
msgid "Updated"
msgstr "已更新"
msgid "Updated %{updated_at} by %{updated_by}"
-msgstr ""
+msgstr "由%{updated_by}更新于%{updated_at}"
msgid "Updating"
msgstr "更新中"
@@ -11986,13 +14291,13 @@ msgid "Upgrade plan to unlock Canary Deployments feature"
msgstr "å‡çº§åˆ°å¯ä½¿ç”¨é‡‘ä¸é›€éƒ¨ç½²åŠŸèƒ½çš„方案"
msgid "Upgrade your plan"
-msgstr ""
+msgstr "å‡çº§æ‚¨çš„订阅计划"
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr "å‡çº§æ‚¨çš„订阅计划以å¯ç”¨é«˜çº§å…¨å±€æœç´¢ã€‚"
msgid "Upgrade your plan to activate Contribution Analytics."
-msgstr "å‡çº§æ‚¨çš„订阅计划以å¯ç”¨è´¡çŒ®åˆ†æžã€‚"
+msgstr "å‡çº§æ‚¨çš„订阅计划以å¯ç”¨è´¡çŒ®åº¦åˆ†æžã€‚"
msgid "Upgrade your plan to activate Group Webhooks."
msgstr "å‡çº§æ‚¨çš„订阅计划以å¯ç”¨ç¾¤ç»„Webhook。"
@@ -12004,7 +14309,7 @@ msgid "Upgrade your plan to improve Issue boards."
msgstr "å‡çº§æ‚¨çš„订阅计划以使用增强的议题看æ¿ã€‚"
msgid "Upgrade your plan to improve Merge Requests."
-msgstr ""
+msgstr "å‡çº§æ‚¨çš„订阅计划以使用增强的åˆå¹¶è¯·æ±‚。"
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr "在这里上传 <code>GoogleCodeProjectHosting.json</code>:"
@@ -12024,6 +14329,9 @@ msgstr "为您的è¯ä¹¦ä¸Šä¼ ä¸€ä¸ªç§é’¥"
msgid "Upload file"
msgstr "上传文件"
+msgid "Upload file does not exist"
+msgstr "上传的文件ä¸å­˜åœ¨"
+
msgid "Upload object map"
msgstr "上传对象图"
@@ -12031,10 +14339,13 @@ msgid "UploadLink|click to upload"
msgstr "点击上传"
msgid "Uploaded on"
+msgstr "上传于"
+
+msgid "Uploading changes to terminal"
msgstr ""
msgid "Uploads"
-msgstr ""
+msgstr "上传"
msgid "Upstream"
msgstr "上游"
@@ -12043,7 +14354,7 @@ msgid "Upvotes"
msgstr "顶"
msgid "Usage"
-msgstr ""
+msgstr "使用情况"
msgid "Usage ping is not enabled"
msgstr "使用情况检测(usage ping)未å¯ç”¨"
@@ -12051,15 +14362,69 @@ msgstr "使用情况检测(usage ping)未å¯ç”¨"
msgid "Usage statistics"
msgstr "使用情况统计"
-msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr "è´­ä¹°é¢å¤–分钟数"
+
+msgid "UsageQuota|Current period usage"
+msgstr "当å‰å‘¨æœŸä½¿ç”¨é‡"
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr "æµæ°´çº¿"
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr ""
+msgid "UsageQuota|Unlimited"
+msgstr "æ— é™"
+
+msgid "UsageQuota|Usage"
+msgstr "使用é‡"
+
+msgid "UsageQuota|Usage Quotas"
+msgstr "使用é‡é…é¢"
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr "%{strong_start}%{group_name}%{strong_end}群组中的项目使用群组资æºçŠ¶å†µ"
+
+msgid "UsageQuota|Usage since"
+msgstr "使用é‡è‡ª"
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
+msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
+msgstr "使用 %{code_start}::%{code_end} 创建 %{link_start}有范围标签集%{link_end} (例如 %{code_start}priority::1%{code_end})"
+
msgid "Use <code>%{native_redirect_uri}</code> for local tests"
msgstr "使用<code>%{native_redirect_uri}</code>进行本地测试"
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "在GitLab内部使用æœåŠ¡å°é€šè¿‡ç”µå­é‚®ä»¶ä¸Žç”¨æˆ·è”系(例如æ供客户支æŒï¼‰"
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr "使用硬件设备添加第二个身份验è¯å› ç´ ã€‚"
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr "在您的手机或计算机上使用一次密ç éªŒè¯å™¨å¯ç”¨åŒé‡è®¤è¯ (2FA)。"
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr "使用群组里程碑å¯ä»¥ç»Ÿä¸€ç®¡ç†å¤šä¸ªé¡¹ç›®ä¸­åŒä¸€é‡Œç¨‹ç¢‘的议题。"
@@ -12085,10 +14450,10 @@ msgid "Used to help configure your identity provider"
msgstr "用于帮助é…置您的身份æ供者"
msgid "User %{current_user_username} has started impersonating %{username}"
-msgstr ""
+msgstr "用户 %{current_user_username} 已开始使用%{username}的身份"
msgid "User %{username} was successfully removed."
-msgstr ""
+msgstr "用户 %{username} å·²æˆåŠŸåˆ é™¤ã€‚"
msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr "用户世代表仅在å¯ç”¨ %{usage_ping_link_start}使用情况检测(usage ping)%{usage_ping_link_end} 时显示。"
@@ -12103,33 +14468,171 @@ msgid "User and IP Rate Limits"
msgstr "用户和IP频率é™åˆ¶"
msgid "User identity was successfully created."
-msgstr ""
+msgstr "å·²æˆåŠŸåˆ›å»ºç”¨æˆ·æ ‡è¯†ã€‚"
msgid "User identity was successfully removed."
-msgstr ""
+msgstr "å·²æˆåŠŸåˆ é™¤ç”¨æˆ·æ ‡è¯†ã€‚"
msgid "User identity was successfully updated."
-msgstr ""
+msgstr "å·²æˆåŠŸæ›´æ–°ç”¨æˆ·æ ‡è¯†ã€‚"
msgid "User key was successfully removed."
-msgstr ""
+msgstr "用户密钥已æˆåŠŸåˆ é™¤ã€‚"
msgid "User map"
msgstr "用户映射"
+msgid "User pipeline minutes were successfully reset."
+msgstr "用户æµæ°´çº¿åˆ†é’Ÿæ•°å·²æˆåŠŸé‡ç½®ã€‚"
+
msgid "User settings"
-msgstr ""
+msgstr "用户设置"
msgid "User was successfully created."
-msgstr ""
+msgstr "用户已æˆåŠŸåˆ›å»ºã€‚"
msgid "User was successfully removed from group and any subresources."
-msgstr ""
+msgstr "å·²æˆåŠŸä»Žç¾¤ç»„和任何å­èµ„æºä¸­åˆ é™¤ç”¨æˆ·ã€‚"
msgid "User was successfully removed from project."
-msgstr ""
+msgstr "用户已æˆåŠŸä»Žé¡¹ç›®ä¸­åˆ é™¤ã€‚"
msgid "User was successfully updated."
+msgstr "用户已æˆåŠŸæ›´æ–°ã€‚"
+
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
msgstr ""
msgid "UserProfile|Activity"
@@ -12207,23 +14710,50 @@ msgstr "您还没有创建任何代ç ç‰‡æ®µ"
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr "您的项目å¯ä»¥æ ¹æ®æ‚¨çš„选择公开ã€å†…部或ç§ä¸‹æ供。"
+msgid "Username (optional)"
+msgstr "用户å (å¯é€‰)"
+
+msgid "Username is already taken."
+msgstr "用户å已被使用。"
+
+msgid "Username is available."
+msgstr "用户åå¯ç”¨ã€‚"
+
msgid "Users"
msgstr "用户"
msgid "Users outside of license"
-msgstr ""
+msgstr "超出许å¯æ•°ç›®çš„用户"
msgid "Users requesting access to"
msgstr "请求访问的用户"
msgid "Users were successfully added."
-msgstr ""
+msgstr "å·²æˆåŠŸæ·»åŠ ç”¨æˆ·ã€‚"
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
-msgstr ""
+msgstr "具有访客角色的用户或ä¸å±žäºŽä»»ä½•é¡¹ç›®æˆ–群组的用户将ä¸è®¡å…¥ä½¿ç”¨ä¸­çš„用户数é‡ã€‚"
+
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr "%{name} + 其余%{length}ä½"
+
+msgid "UsersSelect|Any User"
+msgstr "任何用户"
+
+msgid "UsersSelect|Assignee"
+msgstr "指派人"
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr "没有指派人 - %{openingTag}分é…给自己%{closingTag}"
+
+msgid "UsersSelect|Unassigned"
+msgstr "未分é…"
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
-msgstr ""
+msgstr "使用 %{code_start}::%{code_end} 表示 %{link_start}范围标签集%{link_end}"
+
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr "当缺少加密字段时,使用必è¦çš„加密策略ï¼"
msgid "Validate"
msgstr "验è¯"
@@ -12232,25 +14762,25 @@ msgid "Validate your GitLab CI configuration file"
msgstr "验è¯æ‚¨çš„GitLab CIé…置文件"
msgid "Validations failed."
-msgstr ""
+msgstr "验è¯å¤±è´¥ã€‚"
msgid "Validity"
-msgstr ""
+msgstr "有效期"
msgid "Value"
msgstr "值"
msgid "Variables"
-msgstr ""
+msgstr "å˜é‡"
msgid "Various container registry settings."
-msgstr "容器注册表相关设置。"
+msgstr "容器镜åƒåº“相关设置。"
msgid "Various email settings."
msgstr "电å­é‚®ä»¶ç›¸å…³è®¾ç½®"
msgid "Various localization settings."
-msgstr "å„ç§æœ¬åœ°åŒ–设置。"
+msgstr "å„项本地化设置。"
msgid "Various settings that affect GitLab performance."
msgstr "å½±å“GitLab性能相关设置。"
@@ -12270,21 +14800,30 @@ msgstr "版本"
msgid "View app"
msgstr "查看应用程åº"
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr "查看部署"
msgid "View details: %{details_url}"
msgstr "查看详细信æ¯: %{details_url}"
+msgid "View documentation"
+msgstr "查看文档"
+
msgid "View eligible approvers"
msgstr "查看符åˆæ¡ä»¶çš„核准人"
msgid "View epics list"
-msgstr "查看 epic 列表"
+msgstr "查看å²è¯—列表"
msgid "View file @ "
msgstr "æµè§ˆæ–‡ä»¶ @ "
+msgid "View full dashboard"
+msgstr "查看完整仪表æ¿"
+
msgid "View group labels"
msgstr "查看群组标记"
@@ -12294,9 +14833,12 @@ msgstr "在Sentry中查看"
msgid "View it on GitLab"
msgstr "使用GitLab查看"
-msgid "View job trace"
+msgid "View job"
msgstr ""
+msgid "View job trace"
+msgstr "查看作业日志"
+
msgid "View jobs"
msgstr "查看作业"
@@ -12321,6 +14863,9 @@ msgstr "查看文档"
msgid "Viewing commit"
msgstr "查看æ交"
+msgid "Visibility"
+msgstr "å¯è§æ€§"
+
msgid "Visibility and access controls"
msgstr "å¯è§æ€§ä¸Žè®¿é—®æŽ§åˆ¶"
@@ -12348,6 +14893,33 @@ msgstr "公开"
msgid "VisibilityLevel|Unknown"
msgstr "未知"
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr "%{stepStart}步骤 1%{stepEnd}. å¤åˆ¶ä»¥ä¸‹è„šæœ¬ï¼š"
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr "%{stepStart}步骤 2%{stepEnd}. 把它添加到您的应用程åºçš„æ¯ä¸€é¡µçš„%{headTags}。 "
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr "%{stepStart}步骤 3%{stepEnd}. 打开评审应用,并在 %{linkStart}个人访问令牌%{linkEnd}åŽæ供一个个人访问令牌。"
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr "%{stepStart}步骤 4%{stepEnd}. 您现在å¯ä»¥åœ¨è¯„审应用中留下å馈。"
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr "添加以下脚本到您的代ç åŽï¼Œè¿™æ ·å¯ä»¥åœ¨è¯„审应用中直接留下å馈。å馈将自动æ交给此åˆå¹¶è¯·æ±‚的讨论,包括元数æ®ã€‚"
+
+msgid "VisualReviewApp|Open review app"
+msgstr "打开评审应用"
+
+msgid "VisualReviewApp|Review"
+msgstr "评审"
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr "在评审应用中进行评审并直接给出å馈æ„è§"
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr "æ¼æ´žå›¾è¡¨"
@@ -12370,7 +14942,7 @@ msgid "Vulnerability|Identifiers"
msgstr "标识"
msgid "Vulnerability|Image"
-msgstr ""
+msgstr "é•œåƒ"
msgid "Vulnerability|Instances"
msgstr "实例"
@@ -12379,7 +14951,7 @@ msgid "Vulnerability|Links"
msgstr "链接"
msgid "Vulnerability|Namespace"
-msgstr ""
+msgstr "命å空间"
msgid "Vulnerability|Project"
msgstr "项目"
@@ -12388,19 +14960,22 @@ msgid "Vulnerability|Report Type"
msgstr "报告类型"
msgid "Vulnerability|Severity"
-msgstr "严é‡æ€§"
+msgstr "严é‡çº§åˆ«"
+
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr "等待æºåŠ è½½ä»¥å°†å…¶å¤åˆ¶åˆ°å‰ªè´´æ¿"
msgid "Want to see the data? Please ask an administrator for access."
msgstr "æƒé™ä¸è¶³ã€‚如需查看相关数æ®ï¼Œè¯·å‘管ç†å‘˜ç”³è¯·æƒé™ã€‚"
msgid "We can't find an epic that matches what you are looking for."
-msgstr "我们找ä¸åˆ°ç¬¦åˆæ‚¨è¦æ±‚çš„epic。"
+msgstr "我们找ä¸åˆ°ç¬¦åˆæ‚¨è¦æ±‚çš„å²è¯—。"
msgid "We can't find an issue that matches what you are looking for."
msgstr "我们找ä¸åˆ°ä¸Žæ‚¨è¦æŸ¥æ‰¾çš„内容相匹é…的议题。"
msgid "We could not determine the path to remove the epic"
-msgstr "我们无法确定删除epic的路径"
+msgstr "我们无法确定删除å²è¯—的路径"
msgid "We could not determine the path to remove the issue"
msgstr "我们无法确定删除议题的路径"
@@ -12408,6 +14983,9 @@ msgstr "我们无法确定删除议题的路径"
msgid "We couldn't find any results matching"
msgstr "我们找ä¸åˆ°ä»»ä½•åŒ¹é…的结果"
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr "我们创建了一个简短的指å—,帮助您了解GitLab的基础知识以åŠå®ƒå°†å¦‚何帮助您更好地完æˆå·¥ä½œã€‚它应该åªéœ€è¦å‡ åˆ†é’Ÿã€‚您将å—到两ç§ç±»åž‹çš„帮助的指导,å¯é€šè¿‡é¢œè‰²è¯†åˆ«ã€‚"
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "我们在%{humanized_resource_name}检测到潜在滥用行为。请输入此reCAPTCHA验è¯ç å¹¶ç»§ç»­ã€‚"
@@ -12417,6 +14995,9 @@ msgstr "该阶段的数æ®ä¸è¶³ï¼Œæ— æ³•æ˜¾ç¤ºã€‚"
msgid "We heard back from your U2F device. You have been authenticated."
msgstr "我们从您的U2F设备收到了回å¤ã€‚您已通过身份验è¯ã€‚"
+msgid "We sent you an email with reset password instructions"
+msgstr "我们å‘é€äº†ä¸€å°å¸¦æœ‰é‡ç½®å¯†ç ä¿¡æ¯çš„电å­é‚®ä»¶"
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "我们è¦ç¡®å®šæ‚¨æ˜¯ä¸æ˜¯æœºå™¨äººã€‚"
@@ -12430,14 +15011,17 @@ msgid "Web terminal"
msgstr "Web终端"
msgid "Webhooks"
-msgstr ""
+msgstr "Webhooks"
msgid "Webhooks Help"
-msgstr ""
+msgstr "Webhooks帮助"
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr "如果有新的推é€æˆ–新的议题,Webhook将自动触å‘您设置URL。 您å¯ä»¥é…ç½® Webhook æ¥ç›‘å¬ç‰¹å®šäº‹ä»¶ï¼Œå¦‚推é€ã€è®®é¢˜æˆ–åˆå¹¶è¯·æ±‚。 群组 Webhook 适用于群组中的所有项目,便于您在整个群组中标准化webhook功能。"
+msgid "Wednesday"
+msgstr "星期三"
+
msgid "Weeks"
msgstr "星期"
@@ -12447,25 +15031,31 @@ msgstr "æƒé‡"
msgid "Weight %{weight}"
msgstr "æƒé‡ %{weight}"
+msgid "Welcome to the Guided GitLab Tour"
+msgstr "欢迎æ¥åˆ°Guided GitLab Tour"
+
+msgid "Welcome to your Issue Board!"
+msgstr "欢迎使用议题看æ¿"
+
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "当Runner被é”定时,ä¸èƒ½å°†å…¶åˆ†é…给其他项目"
msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr "该项å¯ç”¨åŽï¼Œç”¨æˆ·åœ¨æŽ¥å—æ¡æ¬¾è¢«å‰å°†ä¸èƒ½ä½¿ç”¨GitLab。"
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr "å°†URLä¿ç•™ä¸ºç©ºç™½æ—¶ï¼Œä»å¯æŒ‡å®šåˆ†ç±»æ ‡ç­¾ï¼Œè€Œæ— éœ€ç¦ç”¨è·¨é¡¹ç›®åŠŸèƒ½æˆ–执行外部授æƒæ£€æŸ¥ã€‚"
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
-msgstr[0] ""
+msgstr[0] "当åˆå¹¶è¯·æ±‚被接å—æ—¶"
msgid "When:"
msgstr "当:"
+msgid "White helpers give contextual information."
+msgstr "白色助手给出了上下文信æ¯ã€‚"
+
msgid "Who can see this group?"
msgstr "哪些人å¯ä»¥çœ‹åˆ°è¿™ä¸ªç¾¤ç»„?"
@@ -12476,7 +15066,7 @@ msgid "Wiki"
msgstr "Wiki"
msgid "Wiki was successfully updated."
-msgstr ""
+msgstr "Wikiå·²æˆåŠŸæ›´æ–°ã€‚"
msgid "WikiClone|Clone your wiki"
msgstr "克隆您的 wiki"
@@ -12509,7 +15099,7 @@ msgid "WikiEmptyIssueMessage|issue tracker"
msgstr "议题跟踪"
msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
-msgstr "您å¯ä»¥ä½¿ç”¨ Wiki æ¥ä¿å­˜é¡¹ç›®çš„详细信æ¯ï¼Œä¾‹å¦‚:创建该项目的原因ã€é¡¹ç›®çš„原则或者项目的使用说明等等。"
+msgstr "您å¯ä»¥ä½¿ç”¨ Wiki æ¥ä¿å­˜é¡¹ç›®çš„详细信æ¯ï¼Œä¾‹å¦‚:创建该项目的原因, 项目的原ç†åŠé¡¹ç›®çš„使用说明等等。"
msgid "WikiEmpty|Create your first page"
msgstr "创建您的第一个页é¢"
@@ -12590,7 +15180,7 @@ msgid "Wiki|Create page"
msgstr "创建页é¢"
msgid "Wiki|Created date"
-msgstr ""
+msgstr "创建日期"
msgid "Wiki|Edit Page"
msgstr "修改页é¢"
@@ -12611,7 +15201,7 @@ msgid "Wiki|Pages"
msgstr "页é¢"
msgid "Wiki|Title"
-msgstr ""
+msgstr "标题"
msgid "Wiki|Wiki Pages"
msgstr "Wiki 页é¢"
@@ -12620,16 +15210,16 @@ msgid "Will deploy to"
msgstr "将部署到"
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
-msgstr "通过贡献分æžï¼Œæ‚¨å¯ä»¥ä»Žæ€»ä½“上了解您的组织åŠå…¶æˆå‘˜çš„议题〠åˆå¹¶è¯·æ±‚和推é€æ´»åŠ¨çš„情况。"
+msgstr "通过贡献度分æžï¼Œæ‚¨å¯ä»¥ä»Žæ€»ä½“上了解您的组织åŠå…¶æˆå‘˜çš„议题〠åˆå¹¶è¯·æ±‚和推é€æ´»åŠ¨çš„情况。"
msgid "Withdraw Access Request"
msgstr "å–消æƒé™ç”³è¯·"
msgid "Workflow Help"
-msgstr ""
+msgstr "工作æµå¸®åŠ©"
msgid "Write"
-msgstr "写"
+msgstr "编辑"
msgid "Write a comment or drag your files here…"
msgstr "在此写评论或拖动您的文件到这里…"
@@ -12641,11 +15231,14 @@ msgid "Write milestone description..."
msgstr "写入里程碑æè¿°..."
msgid "Wrong extern UID provided. Make sure Auth0 is configured correctly."
-msgstr ""
+msgstr "æ供了错误的外部UID。请正确é…ç½®Auth0。"
msgid "Yes"
msgstr "是"
+msgid "Yes or No"
+msgstr "是或å¦"
+
msgid "Yes, add it"
msgstr "是的,添加它"
@@ -12656,13 +15249,19 @@ msgid "Yesterday"
msgstr "昨天"
msgid "You"
-msgstr "您"
+msgstr "当å‰"
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr "您是一å管ç†å‘˜ï¼Œè¿™æ„味ç€æŽˆäºˆå¯¹ <strong>%{client_name}</strong> 访问æƒé™å°†å…许他们作为管ç†å‘˜ä¸ŽGitLab进行交互。请谨慎æ“作。"
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "å³å°†åˆ é™¤ %{group_name}。已删除的群组无法æ¢å¤ï¼ç¡®å®šç»§ç»­å—?"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr "您正在å°è¯•åˆ é™¤å…ˆå‰å·²æ›´æ–°çš„文件。"
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr "您正在å°è¯•æ›´æ–°çš„文件自您开始编辑以æ¥å·²ç»å‘生更改。"
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr "您将删除%{group_name},这也将删除其所有å­ç¾¤ç»„和项目。删除的群组无法æ¢å¤ï¼ç¡®å®šç»§ç»­ï¼Ÿ"
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "å°†è¦åˆ é™¤ %{project_full_name}。删除åŽå°†æ— æ³•æ¢å¤ï¼ç¡®å®šæ‰§è¡Œæ­¤æ“作?"
@@ -12673,8 +15272,11 @@ msgstr "å³å°†åˆ é™¤ä¸Žæºé¡¹ç›® %{forked_from_project} 的派生关系。确定
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr "å°†è¦æŠŠ %{project_full_name} 转移给å¦ä¸€ä¸ªæ‰€æœ‰è€…。确定执行此æ“作?"
+msgid "You are not allowed to unlink your primary login account"
+msgstr "您ä¸èƒ½å–消与主登录å¸æˆ·çš„å…³è”"
+
msgid "You are now impersonating %{username}"
-msgstr ""
+msgstr "您正在使用%{username}的身份"
msgid "You are on a read-only GitLab instance."
msgstr "当å‰æ­£åœ¨è®¿é—®åªè¯» GitLab 实例。"
@@ -12688,6 +15290,12 @@ msgstr "您å¯ä»¥ %{linkStart}查看BLOB%{linkEnd} 代替。"
msgid "You can also create a project from the command line."
msgstr "您也å¯ä»¥é€šè¿‡å‘½ä»¤è¡Œæ¥åˆ›å»ºæ–°é¡¹ç›®ã€‚"
+msgid "You can also press &#8984;-Enter"
+msgstr "您也å¯ä»¥æŒ‰ &#8984;-Enter"
+
+msgid "You can also press Ctrl-Enter"
+msgstr "您也å¯ä»¥æŒ‰ Ctrl-Enter"
+
msgid "You can also star a label to make it a priority label."
msgstr "å¯ä»¥é€šè¿‡ä¸ºæ ‡è®°è®¾ç½®æ˜Ÿæ ‡æ¥æ高其优先级。"
@@ -12706,14 +15314,23 @@ msgstr "您å¯ä»¥è¯·æ±‚加入这些群组,以便为群组项目åšå‡ºè´¡çŒ®ã€‚
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr "å¯ä»¥è½»æ¾åœ°åœ¨Kubernetes集群上安装Runner。 %{link_to_help_page}"
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr "您å¯ä»¥é‚€è¯·ä¸€ä¸ªæ–°æˆå‘˜æˆ–å¦ä¸€ä¸ªç¾¤ç»„加入<strong>%{project_name}</strong>。"
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr "您å¯ä»¥é‚€è¯·ä¸€ä¸ªæ–°æˆå‘˜åŠ å…¥<strong>%{project_name}</strong>。"
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr "您å¯ä»¥é‚€è¯·å¦ä¸€ä¸ªç¾¤ç»„加入<strong>%{project_name}</strong>。"
+
msgid "You can move around the graph by using the arrow keys."
msgstr "å¯ä»¥ä½¿ç”¨æ–¹å‘键移动图形。"
msgid "You can now submit a merge request to get this change into the original branch."
-msgstr ""
+msgstr "您现在å¯ä»¥æ交åˆå¹¶è¯·æ±‚以将此更改å‘é€åˆ°æºåˆ†æ”¯ã€‚"
msgid "You can now submit a merge request to get this change into the original project."
-msgstr ""
+msgstr "您现在å¯ä»¥æ交åˆå¹¶è¯·æ±‚以将此更改添加到æºé¡¹ç›®ä¸­ã€‚"
msgid "You can only add files when you are on a branch"
msgstr "åªèƒ½åœ¨åˆ†æ”¯ä¸Šæ·»åŠ æ–‡ä»¶"
@@ -12725,28 +15342,34 @@ msgid "You can only merge once the items above are resolved"
msgstr "åªæœ‰è§£å†³äº†ä¸Šè¿°é¡¹ç›®åŽæ‰èƒ½åˆå¹¶"
msgid "You can only transfer the project to namespaces you manage."
-msgstr ""
+msgstr "您åªèƒ½å°†é¡¹ç›®è½¬ç§»åˆ°æ‚¨ç®¡ç†çš„命å空间。"
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "您å¯ä»¥ä½¿ç”¨äº¤äº’模å¼ï¼Œé€šè¿‡é€‰æ‹© %{use_ours} 或 %{use_theirs} 按钮æ¥è§£å†³åˆå¹¶å†²çªã€‚也å¯ä»¥é€šè¿‡ç›´æŽ¥ç¼–辑文件æ¥è§£å†³åˆå¹¶å†²çªã€‚然åŽå°†è¿™äº›æ›´æ”¹æ交到 %{branch_name}"
+msgid "You can see your chat accounts."
+msgstr "您å¯ä»¥æŸ¥çœ‹æ‚¨çš„èŠå¤©è´¦æˆ·ã€‚"
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr "您å¯ä»¥å°†ä½œä¸šè®¾ç½®ä¸ºä»…使用具有特定标签的Runners。请使用逗å·åˆ†éš”ä¸åŒæ ‡ç­¾ã€‚"
+msgid "You can specify notification level per group or per project."
+msgstr "您å¯ä»¥æŒ‡å®šæ¯ä¸ªç¾¤ç»„或æ¯ä¸ªé¡¹ç›®çš„通知级别。"
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr "您也å¯ä»¥é€šè¿‡%{linkStart}Lint%{linkEnd}测试.gitlab-ci.yml."
msgid "You cannot impersonate a blocked user"
-msgstr ""
+msgstr "您无法使用被ç¦ç”¨ç”¨æˆ·çš„身份"
msgid "You cannot impersonate a user who cannot log in"
-msgstr ""
+msgstr "您无法仿使用无法登录用户的身份"
msgid "You cannot impersonate an internal user"
-msgstr ""
+msgstr "您无法使用内部用户的身份"
msgid "You cannot play this scheduled pipeline at the moment. Please wait a minute."
-msgstr ""
+msgstr "您目å‰æ— æ³•è¿è¡Œæ­¤æµæ°´çº¿è®¡åˆ’。请ç¨å€™ã€‚"
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr "您ä¸èƒ½å†™å…¥åªè¯»çš„æ¬¡è¦ GitLab Geo 实例。请改用%{link_to_primary_node}。"
@@ -12755,20 +15378,29 @@ msgid "You cannot write to this read-only GitLab instance."
msgstr "您ä¸èƒ½å†™å…¥è¿™ä¸ªåªè¯»çš„ GitLab 实例。"
msgid "You could not create a new trigger."
-msgstr ""
+msgstr "您无法创建新的触å‘器。"
msgid "You could not take ownership of trigger."
-msgstr ""
+msgstr "你无法å–得触å‘器的所有æƒã€‚"
msgid "You do not have any subscriptions yet"
msgstr "您当å‰å°šæœªè®¢é˜…任何计划"
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr "您没有æƒé™é€€å‡º%{namespaceType}。"
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr "您无æƒè¿è¡ŒWeb终端。请è”系项目管ç†å‘˜ã€‚"
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr "您没有更改LDAP组åŒæ­¥ä¸­è®¾ç½®çš„相应æƒé™ã€‚"
+msgid "You don't have any U2F devices registered yet."
+msgstr "您还没有注册任何U2F设备。"
+
+msgid "You don't have any active chat names."
+msgstr "您没有任何活动èŠå¤©ã€‚"
+
msgid "You don't have any applications"
msgstr "您没有任何应用程åº"
@@ -12778,14 +15410,20 @@ msgstr "您没有任何授æƒçš„应用"
msgid "You don't have any deployments right now."
msgstr "您现在没有任何部署。"
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr "你已被授予 %{access_level} 访问 %{source_link} %{source_type} çš„æƒé™ã€‚"
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr "你已被授予 %{access_level} 访问 %{source_name} %{source_type} çš„æƒé™ã€‚"
+
msgid "You have been granted %{member_human_access} access to %{label}."
-msgstr ""
+msgstr "您已被授予 %{member_human_access} 访问æƒé™ %{label}。"
msgid "You have been unsubscribed from this thread."
-msgstr ""
+msgstr "您已å–消订阅该主题。"
msgid "You have declined the invitation to join %{label}."
-msgstr ""
+msgstr "您已拒ç»åŠ å…¥%{label}的邀请。"
msgid "You have no permissions"
msgstr "没有æƒé™"
@@ -12797,7 +15435,7 @@ msgid "You have reached your project limit"
msgstr "您已达到项目数é‡é™åˆ¶"
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
-msgstr ""
+msgstr "ä½ å·²ç»ä»Žâ€œ%{membershipable_human_name}†%{source_type}退出。"
msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
msgstr "您还å¯ä»¥é€šè¿‡åœ¨å˜é‡é”®å‰é¢åŠ ä¸Š<code>K8S_SECRET_</code>æ¥æ·»åŠ å¯ç”¨äºŽæ­£åœ¨è¿è¡Œçš„应用程åºçš„å˜é‡ã€‚"
@@ -12808,11 +15446,20 @@ msgstr "您必须接å—我们的æœåŠ¡æ¡æ¬¾å’Œéšç§æ”¿ç­–æ‰èƒ½æ³¨å†Œå¸æˆ·"
msgid "You must have maintainer access to force delete a lock"
msgstr "必须拥有维护者æƒé™æ‰èƒ½å¼ºåˆ¶åˆ é™¤é”"
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr "在创建派生之å‰ï¼Œæ‚¨å¿…须具有在命å空间中创建项目的æƒé™ã€‚"
+
+msgid "You must provide a valid current password"
+msgstr "您必须æ供一个有效的当å‰å¯†ç "
+
+msgid "You must provide your current password in order to change it."
+msgstr "您必须æ供当å‰å¯†ç æ‰èƒ½è¿›è¡Œæ›´æ”¹ã€‚"
+
msgid "You need a different license to enable FileLocks feature"
msgstr "需è¦ä½¿ç”¨ä¸Žå½“å‰ä¸åŒçš„许å¯(license) æ‰èƒ½å¯ç”¨FileLocks功能"
msgid "You need a different license to use Geo replication."
-msgstr ""
+msgstr "您需è¦å…¶ä»–等级的许å¯è¯æ‰å¯ä»¥ä½¿ç”¨geoå¤åˆ¶."
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
msgstr "您需è¦git-lfs版本 %{min_git_lfs_version} (或更高版本)æ‰èƒ½ç»§ç»­ã€‚请访问https://git-lfs.github.com"
@@ -12820,17 +15467,23 @@ msgstr "您需è¦git-lfs版本 %{min_git_lfs_version} (或更高版本)æ‰èƒ
msgid "You need permission."
msgstr "需è¦ç›¸å…³çš„æƒé™ã€‚"
+msgid "You need to be logged in."
+msgstr "您必须先登录。"
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
-msgstr "在设置U2F设备之å‰ï¼Œæ‚¨éœ€è¦æ³¨å†ŒåŒå› ç´ èº«ä»½éªŒè¯åº”用程åºã€‚"
+msgstr "在设置U2F设备之å‰ï¼Œæ‚¨éœ€è¦æ³¨å†ŒåŒé‡è®¤è¯åº”用程åºã€‚"
msgid "You need to specify both an Access Token and a Host URL."
-msgstr ""
+msgstr "您需è¦åŒæ—¶æŒ‡å®šè®¿é—®ä»¤ç‰Œå’Œä¸»æœºURL。"
msgid "You need to upload a GitLab project export archive (ending in .gz)."
-msgstr ""
+msgstr "您需è¦ä¸Šä¼ GitLab项目导出文件(以.gz结尾)."
msgid "You need to upload a Google Takeout archive."
-msgstr ""
+msgstr "您需è¦ä¸Šä¼ Google Takeout文件。"
+
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr "您å°è¯•æ´¾ç”Ÿ %{link_to_the_project} 但由于以下原因导致失败:"
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr "您将丢失对此文件所åšçš„所有更改。此æ“作无法撤消。"
@@ -12839,7 +15492,7 @@ msgid "You will lose all the unstaged changes you've made in this project. This
msgstr "您将丢失在此项目中所åšçš„所有未暂存的修改,此æ“作无法撤消。"
msgid "You will need to update your local repositories to point to the new location."
-msgstr ""
+msgstr "您需è¦æ›´æ–°æœ¬åœ°ä»“库以指å‘æ–°ä½ç½®ã€‚"
msgid "You will not get any notifications via email"
msgstr "ä¸ä¼šæ”¶åˆ°ä»»ä½•é€šçŸ¥é‚®ä»¶"
@@ -12865,17 +15518,20 @@ msgstr "在账å·ä¸­ %{add_ssh_key_link} 之å‰å°†æ— æ³•é€šè¿‡ SSH 拉å–或推é
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "在您的个人资料中添加SSH密钥之å‰ï¼Œæ‚¨ä¸èƒ½é€šè¿‡SSHæ¥æ‹‰å–或推é€é¡¹ç›®ä»£ç ã€‚"
+msgid "You'll be signed out from your current account automatically."
+msgstr "您将自动从当å‰å¸æˆ·é€€å‡ºã€‚"
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr "需è¦ä½¿ç”¨ä¸åŒçš„分支æ‰èƒ½è¿›è¡Œæœ‰æ•ˆçš„比较。"
msgid "You're not allowed to make changes to this project directly. A fork of this project has been created that you can make changes in, so you can submit a merge request."
-msgstr ""
+msgstr "您ä¸èƒ½ç›´æŽ¥å¯¹æ­¤é¡¹ç›®è¿›è¡Œæ›´æ”¹ã€‚此项目的派生项目已ç»åˆ›å»ºï¼Œæ‚¨å¯ä»¥åœ¨æ´¾ç”Ÿé¡¹ç›®ä¸­è¿›è¡Œæ›´æ”¹ï¼Œä»¥ä¾¿æ交åˆå¹¶è¯·æ±‚。"
msgid "You're not allowed to make changes to this project directly. A fork of this project is being created that you can make changes in, so you can submit a merge request."
-msgstr ""
+msgstr "您ä¸èƒ½ç›´æŽ¥å¯¹æ­¤é¡¹ç›®è¿›è¡Œæ›´æ”¹ã€‚此项目的派生项目正在创建,您å¯ä»¥åœ¨æ´¾ç”Ÿé¡¹ç›®ä¸­è¿›è¡Œæ›´æ”¹ï¼Œä»¥ä¾¿æ交åˆå¹¶è¯·æ±‚。"
msgid "You're only seeing %{startTag}other activity%{endTag} in the feed. To add a comment, switch to one of the following options."
-msgstr "您åªèƒ½åœ¨ä¿¡æ¯æµä¸­çœ‹åˆ° %{startTag}其他活动%{endTag} 。è¦æ·»åŠ è¯„论,请切æ¢åˆ°ä»¥ä¸‹é€‰é¡¹ä¹‹ä¸€ã€‚"
+msgstr "您åªèƒ½åœ¨ä¿¡æ¯åŠ¨æ€ä¸­çœ‹åˆ° %{startTag}其他活动%{endTag} 。è¦æ·»åŠ è¯„论,请切æ¢åˆ°ä»¥ä¸‹é€‰é¡¹ä¹‹ä¸€ã€‚"
msgid "You're receiving this email because %{reason}."
msgstr "您收到此电å­é‚®ä»¶ï¼Œæ˜¯å› ä¸º%{reason}。"
@@ -12886,11 +15542,23 @@ msgstr "您收到这å°ç”µå­é‚®ä»¶ï¼Œæ˜¯å› ä¸ºæ‚¨åœ¨ %{host} 拥有å¸æˆ·ã€‚"
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr "您收到这å°ç”µå­é‚®ä»¶æ˜¯å› ä¸ºä½ åœ¨ %{host} 拥有å¸æˆ·ã€‚ %{manage_notifications_link} &middot; %{help_link}"
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr "您已ç»ä½¿ç”¨ä¸€æ¬¡å¯†ç éªŒè¯å™¨å¯ç”¨äº†åŒé‡è®¤è¯ã€‚如果您è¦æ³¨å†Œä¸åŒçš„设备,您必须先ç¦ç”¨åŒé‡è®¤è¯ã€‚"
+
msgid "YouTube"
msgstr "YouTube"
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
-msgstr "您的会è¯å¼€å‘指数概述了从功能角度使用GitLabçš„æ–¹å¼ã€‚查看您与其他组织的比较,å‘现您未使用的功能,并通过åšå®¢æ–‡ç« å’Œç™½çš®ä¹¦äº†è§£æœ€ä½³å®žè·µã€‚"
+msgstr "会è¯å¼€å‘指数从功能角度上展现了GitLab的使用情况。您å¯ä»¥æŸ¥çœ‹ä¸Žå…¶ä»–组织的比较,探索未使用的功能,并通过åšå®¢æ–‡ç« å’Œç™½çš®ä¹¦äº†è§£æœ€ä½³å®žè·µã€‚"
+
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr "您的GPG密钥 (%{count})"
msgid "Your Groups"
msgstr "您的群组"
@@ -12898,26 +15566,38 @@ msgstr "您的群组"
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr "在此页é¢ä¸Šçš„Kubernetes集群信æ¯ä»å¯ç¼–辑,但建议您ç¦ç”¨å¹¶é‡æ–°é…ç½®"
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr "您的项目 (默认值)"
msgid "Your Projects' Activity"
msgstr "您的项目动æ€"
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr "您的SSH密钥(%{count})"
+
msgid "Your Todos"
msgstr "您的待办事项"
+msgid "Your U2F device did not send a valid JSON response."
+msgstr "您的 U2F 设备没有å‘é€æœ‰æ•ˆçš„ JSON å“应。"
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr "您的 U2F 设备需è¦è®¾ç½®ã€‚请将将其æ’入,并点击左边的按钮。"
msgid "Your U2F device was registered!"
-msgstr ""
+msgstr "您的 U2F 设备已注册ï¼"
msgid "Your access request to the %{source_type} has been withdrawn."
-msgstr ""
+msgstr "您对 %{source_type} 访问请求已被撤消。"
msgid "Your account uses dedicated credentials for the \"%{group_name}\" group and can only be updated through SSO."
-msgstr ""
+msgstr "您的å¸æˆ·ä½¿ç”¨ç¾¤ç»„“%{group_name}â€çš„专用凭æ®ï¼Œå¹¶ä¸”åªèƒ½é€šè¿‡SSO进行更新。"
msgid "Your applications (%{size})"
msgstr "您的应用程åº(%{size})"
@@ -12938,13 +15618,16 @@ msgid "Your changes have been saved"
msgstr "您的更改已ä¿å­˜"
msgid "Your changes have been successfully committed."
-msgstr ""
+msgstr "您的更改已æˆåŠŸæ交。"
+
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr "您的评论无法æ交ï¼è¯·æ£€æŸ¥æ‚¨çš„网络连接,然åŽé‡è¯•ã€‚"
-msgid "Your comment will not be visible to the public."
-msgstr "您的评论将ä¸ä¼šå…¬å¼€æ˜¾ç¤ºã€‚"
+msgid "Your comment could not be updated! Please check your network connection and try again."
+msgstr "您的评论无法更新ï¼è¯·æ£€æŸ¥æ‚¨çš„网络连接,然åŽé‡è¯•ã€‚"
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
-msgstr ""
+msgstr "您的部署æœåŠ¡å°†å¤±æ•ˆï¼Œéœ€è¦åœ¨é‡å‘½ååŽæ‰‹åŠ¨ä¿®å¤æœåŠ¡ã€‚"
msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
msgstr "您的设备已æˆåŠŸè®¾ç½®ï¼è¯·ç»™å®ƒå‘½å并将其注册到GitLabæœåŠ¡å™¨ã€‚"
@@ -12958,17 +15641,20 @@ msgstr "您的议题正在导入。完æˆåŽï¼Œæ‚¨å°†æ”¶åˆ°ä¸€å°ç¡®è®¤ç”µå­é‚®
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr "您的议题将在åŽå°å¯¼å…¥ã€‚完æˆåŽï¼Œæ‚¨å°†æ”¶åˆ°ä¸€å°ç¡®è®¤ç”µå­é‚®ä»¶ã€‚"
+msgid "Your message here"
+msgstr "您的消æ¯æ˜¾ç¤ºäºŽæ­¤"
+
msgid "Your name"
msgstr "您的åå­—"
msgid "Your new SCIM token"
-msgstr ""
+msgstr "您的新 SCIM 令牌"
msgid "Your new personal access token has been created."
-msgstr ""
+msgstr "您的新个人访问令牌已创建。"
msgid "Your password reset token has expired."
-msgstr ""
+msgstr "您的密ç é‡ç½®ä»¤ç‰Œå·²è¿‡æœŸã€‚"
msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
msgstr "您的被é™åˆ¶ä¸ºæœ€å¤§ %{limit} 个项目ï¼è¯·ä¸Žæ‚¨çš„管ç†å‘˜è”系以增加它"
@@ -12977,7 +15663,7 @@ msgid "Your projects"
msgstr "您的项目"
msgid "Your request for access has been queued for review."
-msgstr ""
+msgstr "您的访问请求已进入审核队列。"
msgid "a deleted user"
msgstr "已删除的用户"
@@ -12991,14 +15677,17 @@ msgstr "å‰"
msgid "allowed to fail"
msgstr "å…许失败"
+msgid "already being used for another group or project milestone."
+msgstr "å·²ç»ç”¨äºŽå¦ä¸€ç¾¤ç»„或项目里程碑。"
+
+msgid "already shared with this group"
+msgstr "已与该群组分享"
+
msgid "among other things"
msgstr "åŠå…¶ä»–功能"
-msgid "at"
-msgstr "于"
-
msgid "attach a new file"
-msgstr "附加一个文件"
+msgstr "添加新附件"
msgid "authored"
msgstr "编写于"
@@ -13009,6 +15698,21 @@ msgstr "分支å称"
msgid "by"
msgstr "æ¥è‡ª"
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr "如果个人项目具有容器镜åƒåº“标签,则无法更改。"
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr "除éžæ‰€æœ‰åŸŸéƒ½å…·æœ‰TLSè¯ä¹¦ï¼Œå¦åˆ™æ— æ³•å¯ç”¨"
+
+msgid "cannot block others"
+msgstr "ä¸ä¼šé˜»å¡žå…¶ä»–"
+
+msgid "cannot include leading slash or directory traversal."
+msgstr "ä¸èƒ½ä»¥æ–œçº¿å¼€å¤´æˆ–转到仓库以外目录。"
+
+msgid "cannot itself be blocked"
+msgstr "本身ä¸èƒ½è¢«é˜»å¡ž"
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr "%{linkStartTag}了解更多有关容器安全扫æçš„ä¿¡æ¯ %{linkEndTag}"
@@ -13085,7 +15789,7 @@ msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr "%{reportType}:å‘生一个错误"
msgid "ciReport|%{vulnerability} in %{featurename}"
-msgstr ""
+msgstr "%{featurename}中的%{vulnerability}"
msgid "ciReport|(errors when loading results)"
msgstr "(加载结果时出错)"
@@ -13096,14 +15800,17 @@ msgstr "(加载中)"
msgid "ciReport|(is loading, errors when loading results)"
msgstr "(正在加载,加载结果时出错)"
+msgid "ciReport|All confidence levels"
+msgstr "所有置信水平"
+
msgid "ciReport|All projects"
-msgstr ""
+msgstr "所有项目"
msgid "ciReport|All report types"
-msgstr ""
+msgstr "所有报告类型"
msgid "ciReport|All severities"
-msgstr ""
+msgstr "全部严é‡çº§åˆ«"
msgid "ciReport|Class"
msgstr "ç±»"
@@ -13129,9 +15836,6 @@ msgstr "创建议题"
msgid "ciReport|Create merge request"
msgstr "创建åˆå¹¶è¯·æ±‚"
-msgid "ciReport|Created %{eventType}"
-msgstr "已创建 %{eventType}"
-
msgid "ciReport|DAST"
msgstr "DAST"
@@ -13147,12 +15851,6 @@ msgstr "ä¾èµ–项扫æ"
msgid "ciReport|Description"
msgstr "说明"
-msgid "ciReport|Dismiss vulnerability"
-msgstr "忽略æ¼æ´ž"
-
-msgid "ciReport|Dismissed by"
-msgstr "忽略æ“作æ¥è‡ª"
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr "下载并应用此修补程åºä»¥ä¿®å¤æ­¤æ¼æ´žã€‚"
@@ -13175,7 +15873,7 @@ msgid "ciReport|Identifiers"
msgstr "标识符"
msgid "ciReport|Image"
-msgstr ""
+msgstr "é•œåƒ"
msgid "ciReport|Implement this solution by creating a merge request"
msgstr "通过创建åˆå¹¶è¯·æ±‚æ¥å®žçŽ°æ­¤è§£å†³æ–¹æ¡ˆ"
@@ -13237,7 +15935,7 @@ msgid "ciReport|Security scanning failed loading any results"
msgstr "安全扫æ无法加载任何结果"
msgid "ciReport|Severity"
-msgstr "严é‡æ€§"
+msgstr "严é‡çº§åˆ«"
msgid "ciReport|Solution"
msgstr "解决方案"
@@ -13269,17 +15967,14 @@ msgstr "加载ä¾èµ–项扫æ报告时出错"
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr "å–消忽略æ“作时å‘生错误。请å†è¯•ä¸€æ¬¡ã€‚"
-msgid "ciReport|Undo dismiss"
-msgstr "撤消解除"
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr "å°† %{name} 从 %{version} å‡çº§åˆ° %{fixed}。"
msgid "ciReport|Upgrade %{name} to %{fixed}."
-msgstr ""
+msgstr "å‡çº§ %{name} 到 %{fixed}。"
msgid "ciReport|Upgrade to %{fixed}."
-msgstr ""
+msgstr "å‡çº§åˆ° %{fixed}。"
msgid "ciReport|Used by %{packagesString}"
msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
@@ -13288,35 +15983,35 @@ msgstr[0] "已用于 %{packagesString} 和 %{lastPackage}"
msgid "ciReport|View full report"
msgstr "查看完整报告"
-msgid "ciReport|on pipeline"
-msgstr "于æµæ°´çº¿"
-
msgid "commented on %{link_to_project}"
msgstr "评论 %{link_to_project}"
-msgid "confidence|Confirmed"
+msgid "commit %{commit_id}"
msgstr ""
+msgid "confidence|Confirmed"
+msgstr "已确认"
+
msgid "confidence|Experimental"
-msgstr ""
+msgstr "实验性"
msgid "confidence|High"
-msgstr ""
+msgstr "高"
msgid "confidence|Ignore"
-msgstr ""
+msgstr "忽略"
msgid "confidence|Low"
-msgstr ""
+msgstr "低"
msgid "confidence|Medium"
-msgstr ""
+msgstr "中"
msgid "confidence|Undefined"
-msgstr ""
+msgstr "未定义"
msgid "confidence|Unknown"
-msgstr ""
+msgstr "未知"
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr "å³å°†å…³é—­ç§å¯†æ€§ã€‚这将使得 <strong>所有用户</strong>都å¯ä»¥æŸ¥çœ‹å¹¶ä¸”评论当å‰è®®é¢˜ã€‚"
@@ -13333,6 +16028,9 @@ msgstr "无法读å–ç§é’¥ï¼Œå¯†ç çŸ­è¯­æ˜¯å¦æ­£ç¡®ï¼Ÿ"
msgid "customize"
msgstr "自定义"
+msgid "date must not be after 9999-12-31"
+msgstr "日期ä¸èƒ½åœ¨9999-12-31之åŽ"
+
msgid "day"
msgid_plural "days"
msgstr[0] "天"
@@ -13344,7 +16042,7 @@ msgid "deploy token"
msgstr "部署令牌"
msgid "detached"
-msgstr ""
+msgstr "已游离"
msgid "disabled"
msgstr "å·²ç¦ç”¨"
@@ -13360,11 +16058,17 @@ msgid "draft"
msgid_plural "drafts"
msgstr[0] "è‰ç¨¿"
+msgid "element is not a hierarchy"
+msgstr "此元素并éžç¾¤ç»„层级"
+
msgid "enabled"
msgstr "å·²å¯ç”¨"
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr "加密:必须是 :requiredã€:optional 或 :migrating 之一"
+
msgid "epic"
-msgstr "epic"
+msgstr "å²è¯—"
msgid "error"
msgstr "错误"
@@ -13375,20 +16079,26 @@ msgstr "错误代ç ï¼š"
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr "最åŽä¸€æ¬¡%{slash_command} 命令将更新预计时间。"
+msgid "expired on %{milestone_due_date}"
+msgstr "过期于 %{milestone_due_date}"
+
+msgid "expires on %{milestone_due_date}"
+msgstr "过期于 %{milestone_due_date}"
+
msgid "failed"
-msgstr ""
+msgstr "已失败"
msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch}"
-msgstr ""
+msgstr "使用%{link_to_merge_request}于%{link_to_merge_request_source_branch}"
msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch} into %{link_to_merge_request_target_branch}"
-msgstr ""
+msgstr "使用%{link_to_merge_request}ç”±%{link_to_merge_request_source_branch}åˆå¹¶åˆ°%{link_to_merge_request_target_branch}"
msgid "for %{link_to_pipeline_ref}"
-msgstr ""
+msgstr "于%{link_to_pipeline_ref}"
msgid "for %{ref}"
-msgstr ""
+msgstr "于%{ref}"
msgid "for this project"
msgstr "对于这个项目"
@@ -13399,6 +16109,9 @@ msgstr "æ¥è‡ª"
msgid "group"
msgstr "群组"
+msgid "has already been taken"
+msgstr "å·²ç»è¢«ä½¿ç”¨"
+
msgid "here"
msgstr "此处"
@@ -13427,6 +16140,12 @@ msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] "实例已完æˆ"
+msgid "invalid milestone state `%{state}`"
+msgstr "æ— æ•ˆçš„é‡Œç¨‹ç¢‘çŠ¶æ€ `%{state}`"
+
+msgid "is enabled."
+msgstr "å·²å¯ç”¨ã€‚"
+
msgid "is invalid because there is downstream lock"
msgstr "因下游é”定而无效"
@@ -13436,6 +16155,9 @@ msgstr "因上游é”定而无效"
msgid "is not a valid X509 certificate."
msgstr "ä¸æ˜¯æœ‰æ•ˆçš„X509è¯ä¹¦ã€‚"
+msgid "is not an email you own"
+msgstr "ä¸æ˜¯æ‚¨è‡ªå·±çš„电å­é‚®ä»¶"
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr "ä¸å±žäºŽæ‹¥æœ‰æ¨¡æ¿çš„群组层次结构"
@@ -13454,6 +16176,9 @@ msgstr "它存储在LFS中"
msgid "it is too large"
msgstr "它太大了"
+msgid "jigsaw is not defined"
+msgstr "拼图未定义"
+
msgid "latest"
msgstr "最新"
@@ -13464,7 +16189,7 @@ msgid "latest version"
msgstr "最新版本"
msgid "leave %{group_name}"
-msgstr ""
+msgstr "退出%{group_name}"
msgid "license management"
msgstr "许å¯è¯ç®¡ç†"
@@ -13479,6 +16204,9 @@ msgid "merge request"
msgid_plural "merge requests"
msgstr[0] "åˆå¹¶è¯·æ±‚"
+msgid "milestone should belong either to a project or a group."
+msgstr "里程碑应该属于一个项目或一个群组。"
+
msgid "missing"
msgstr "丢失"
@@ -13506,8 +16234,8 @@ msgstr "%{metricsLinkStart} 内存 %{metricsLinkEnd} å ç”¨ %{emphasisStart} 上
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "%{metricsLinkStart} 内存 %{metricsLinkEnd} å ç”¨ %{emphasisStart} æ— å˜åŒ– %{emphasisEnd}, ä¿æŒåœ¨ %{memoryFrom}MB"
-msgid "mrWidget|Add approval"
-msgstr "添加批准"
+msgid "mrWidget|Added to the merge train by"
+msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "å…许具有åˆå¹¶åˆ°ç›®æ ‡åˆ†æ”¯æƒé™çš„æˆå‘˜æ交"
@@ -13521,6 +16249,9 @@ msgstr "检索此åˆå¹¶è¯·æ±‚的核准数æ®æ—¶å‘生错误。"
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "æ交批准时å‘生错误。"
+msgid "mrWidget|Approval password is invalid."
+msgstr "批准密ç æ— æ•ˆ"
+
msgid "mrWidget|Approve"
msgstr "批准"
@@ -13573,7 +16304,10 @@ msgid "mrWidget|Failed to load deployment statistics"
msgstr "无法加载部署统计信æ¯"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
-msgstr "无法进行快进åˆå¹¶ã€‚è¦åˆå¹¶æ­¤è¯·æ±‚,请先在本地进行rebase。"
+msgstr "无法进行快进å¼åˆå¹¶ã€‚è¦åˆå¹¶æ­¤è¯·æ±‚,请先在本地进行rebase。"
+
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr "派生åˆå¹¶è¯·æ±‚无法创建验è¯åˆå¹¶ç»“果的åˆå¹¶è¯·æ±‚æµæ°´çº¿"
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr "如果 %{branch} 分支存在于本地仓库中,则å¯ä»¥æ‰‹åŠ¨åˆå¹¶è¯¥åˆå¹¶è¯·æ±‚。需使用"
@@ -13593,18 +16327,15 @@ msgstr "åˆå¹¶"
msgid "mrWidget|Merge failed."
msgstr "åˆå¹¶å¤±è´¥ã€‚"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
+msgstr ""
+
msgid "mrWidget|Merge locally"
msgstr "本地åˆå¹¶"
-msgid "mrWidget|Merge request approved"
-msgstr "åˆå¹¶è¯·æ±‚已批准"
-
msgid "mrWidget|Merge request approved."
msgstr "åˆå¹¶è¯·æ±‚已核准。"
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr "åˆå¹¶è¯·æ±‚已被批准; ä»å¯ä»¥æ·»åŠ é¢å¤–批准"
-
msgid "mrWidget|Merged by"
msgstr "åˆå¹¶è€…:"
@@ -13635,20 +16366,12 @@ msgstr "ç«‹å³åˆ·æ–°"
msgid "mrWidget|Refreshing now"
msgstr "ç«‹å³åˆ·æ–°"
-msgid "mrWidget|Remove your approval"
-msgstr "删除您的批准"
+msgid "mrWidget|Remove from merge train"
+msgstr ""
msgid "mrWidget|Request to merge"
msgstr "请求åˆå¹¶"
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] "还需è¦%d个批准"
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] "需è¦é¢å¤– %d 个批准"
-
msgid "mrWidget|Resolve conflicts"
msgstr "解决冲çª"
@@ -13733,15 +16456,30 @@ msgstr "命令行"
msgid "mrWidget|into"
msgstr "å…¥"
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr "æµæ°´çº¿æˆåŠŸæ—¶è‡ªåŠ¨åˆå¹¶"
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr "必须大于开始日期"
+
msgid "n/a"
msgstr "ä¸é€‚用"
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr "需è¦åœ¨10分钟到1个月之间"
+
msgid "new merge request"
msgstr "新建åˆå¹¶è¯·æ±‚"
+msgid "no contributions"
+msgstr "无贡献"
+
msgid "none"
msgstr "æ— "
@@ -13776,7 +16514,7 @@ msgstr "个人访问令牌"
msgid "point"
msgid_plural "points"
-msgstr[0] ""
+msgstr[0] "点"
msgid "private"
msgstr "ç§æœ‰"
@@ -13785,7 +16523,7 @@ msgid "private key does not match certificate."
msgstr "ç§é’¥ä¸Žè¯ä¹¦ä¸åŒ¹é…。"
msgid "processing"
-msgstr ""
+msgstr "处ç†ä¸­"
msgid "project"
msgid_plural "projects"
@@ -13817,7 +16555,7 @@ msgid_plural "replies"
msgstr[0] "æ¡å›žå¤"
msgid "reset it."
-msgstr ""
+msgstr "é‡ç½®å®ƒã€‚"
msgid "score"
msgstr "分"
@@ -13826,28 +16564,28 @@ msgid "security Reports|There was an error creating the merge request"
msgstr "创建åˆå¹¶è¯·æ±‚时出错"
msgid "severity|Critical"
-msgstr ""
+msgstr "关键"
msgid "severity|High"
-msgstr ""
+msgstr "高"
msgid "severity|Info"
-msgstr ""
+msgstr "ä¿¡æ¯"
msgid "severity|Low"
-msgstr ""
+msgstr "低"
msgid "severity|Medium"
-msgstr ""
+msgstr "中"
msgid "severity|Undefined"
-msgstr ""
+msgstr "未定义"
msgid "severity|Unknown"
-msgstr ""
+msgstr "未知"
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
-msgstr "应该从高于%{group_name} 群组继承æˆå‘˜èº«ä»½%{access}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
+msgstr "应该从高于或等于从%{group_name} 群组继承的æˆå‘˜èº«ä»½%{access}"
msgid "show less"
msgstr "显示较少"
@@ -13855,23 +16593,35 @@ msgstr "显示较少"
msgid "sign in"
msgstr "登录"
+msgid "sort:"
+msgstr "排åºï¼š"
+
msgid "source"
msgstr "æº"
msgid "source diff"
msgstr "æºå·®å¼‚"
+msgid "specified top is not part of the tree"
+msgstr "指定的顶级ä¸å±žäºŽç¾¤ç»„层级"
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} 将会更新消耗的总时长。"
msgid "started"
msgstr "已开始"
+msgid "started on %{milestone_start_date}"
+msgstr "开始于 %{milestone_start_date}"
+
+msgid "starts on %{milestone_start_date}"
+msgstr "开始于 %{milestone_start_date}"
+
msgid "stuck"
msgstr "å¡ä½"
msgid "success"
-msgstr ""
+msgstr "æˆåŠŸ"
msgid "syntax is correct"
msgstr "语法是正确的"
@@ -13900,12 +16650,33 @@ msgstr "使用 Kubernetes 集群æ¥éƒ¨ç½²ä»£ç ï¼"
msgid "verify ownership"
msgstr "验è¯æ‰€æœ‰æƒ"
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr "使用GitLab查看"
msgid "view the blob"
msgstr "查看blob"
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr "为忽略添加评论或原因"
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr "添加评论并忽略"
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr "忽略æ¼æ´ž"
+
+msgid "vulnerability|Undo dismiss"
+msgstr "撤销忽略"
+
+msgid "vulnerability|dismissed"
+msgstr "已忽略"
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "å…± %{additions} æ¡æ–°å¢ž, %{deletions} æ¡åˆ é™¤."
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index 8882be94797..09c414249b3 100644
--- a/locale/zh_HK/gitlab.po
+++ b/locale/zh_HK/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Chinese Traditional, Hong Kong\n"
"Language: zh_HK\n"
"MIME-Version: 1.0\n"
@@ -13,159 +13,183 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: zh-HK\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:36\n"
+"PO-Revision-Date: 2019-06-14 10:23\n"
msgid " Please sign in."
-msgstr ""
-
-msgid " Status"
-msgstr ""
+msgstr "請登入您的帳戶"
msgid " Try to %{action} this file again."
-msgstr ""
+msgstr "請嘗試å†%{action}此檔案。"
msgid " You need to do this before %{grace_period_deadline}."
-msgstr ""
+msgstr " 您需è¦åœ¨ %{grace_period_deadline} 之å‰åŸ·è¡Œæ­¤æ“作。"
msgid " and"
-msgstr ""
+msgstr " 和"
msgid " degraded on %d point"
msgid_plural " degraded on %d points"
-msgstr[0] ""
+msgstr[0] " é™ä½Ž %d 點"
msgid " improved on %d point"
msgid_plural " improved on %d points"
-msgstr[0] ""
+msgstr[0] " æ高 %d 分"
msgid " or "
-msgstr ""
+msgstr "或"
msgid " or <#epic id>"
msgstr ""
msgid " or <#issue id>"
-msgstr ""
+msgstr "或 <#issue id>"
msgid "%d comment"
msgid_plural "%d comments"
-msgstr[0] ""
+msgstr[0] "%d 則留言"
msgid "%d commit"
msgid_plural "%d commits"
-msgstr[0] " %d 次æ交"
+msgstr[0] "%d 個æ交"
msgid "%d commit behind"
msgid_plural "%d commits behind"
-msgstr[0] ""
+msgstr[0] "è½å¾Œ %d 個æ交"
msgid "%d commits"
-msgstr ""
+msgstr "%d 個æ交"
+
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
msgid "%d exporter"
msgid_plural "%d exporters"
-msgstr[0] ""
+msgstr[0] "%d 導出"
msgid "%d failed test result"
msgid_plural "%d failed test results"
-msgstr[0] ""
+msgstr[0] "%d 個失敗測試çµæžœ"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
-msgstr[0] ""
+msgstr[0] "%d 個已修復測試çµæžœ"
msgid "%d issue"
msgid_plural "%d issues"
-msgstr[0] ""
+msgstr[0] "%d 個議題"
msgid "%d issue selected"
msgid_plural "%d issues selected"
-msgstr[0] ""
+msgstr[0] "å·²é¸ %d 個議題"
msgid "%d layer"
msgid_plural "%d layers"
-msgstr[0] ""
+msgstr[0] "%d 個圖層"
msgid "%d merge request"
msgid_plural "%d merge requests"
+msgstr[0] "%d 個åˆä½µè«‹æ±‚"
+
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgid "%d metric"
msgid_plural "%d metrics"
+msgstr[0] "%d 指標"
+
+msgid "%d more comment"
+msgid_plural "%d more comments"
msgstr[0] ""
msgid "%d staged change"
msgid_plural "%d staged changes"
-msgstr[0] ""
+msgstr[0] "%d 個暫存變更"
msgid "%d unstaged change"
msgid_plural "%d unstaged changes"
-msgstr[0] ""
+msgstr[0] "%d 個未暫存變更"
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] "為æ高é é¢åŠ è¼‰é€Ÿåº¦åŠæ€§èƒ½ï¼Œå·²çœç•¥äº† %s 次æ交。"
msgid "%{actionText} & %{openOrClose} %{noteable}"
-msgstr ""
+msgstr "%{actionText} 和 %{openOrClose} %{noteable}"
msgid "%{authorsName}'s discussion"
-msgstr ""
+msgstr "%{authorsName} 的討論"
msgid "%{commit_author_link} authored %{commit_timeago}"
-msgstr ""
+msgstr "ç”± %{commit_author_link} æ交於 %{commit_timeago}"
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr ""
-
-msgid "%{count} %{alerts}"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
msgstr ""
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
-msgstr[0] ""
+msgstr[0] "éœ€è¦ %{count} 個由 %{name} 的批准"
msgid "%{count} approvals from %{name}"
-msgstr ""
+msgstr "éœ€è¦ %{count} 個由 %{name} 的批准"
msgid "%{count} more"
-msgstr ""
+msgstr "還有 %{count} 項"
msgid "%{count} more assignees"
-msgstr ""
+msgstr "%{count} å以上的指派人"
msgid "%{count} of %{required} approvals from %{name}"
-msgstr ""
+msgstr "%{name} 的 %{count}/%{required} 個批准"
msgid "%{count} of %{total}"
-msgstr ""
+msgstr "%{count} / %{total}"
msgid "%{count} participant"
msgid_plural "%{count} participants"
-msgstr[0] ""
+msgstr[0] "%{count} ä½åƒèˆ‡è€…"
msgid "%{count} pending comment"
msgid_plural "%{count} pending comments"
-msgstr[0] ""
+msgstr[0] "%{count} 個待處ç†è©•è«–"
-msgid "%{filePath} deleted"
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
msgstr ""
-msgid "%{firstLabel} +%{labelCount} more"
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
msgstr ""
+msgid "%{filePath} deleted"
+msgstr "已刪除 %{filePath}"
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr "%{firstLabel} +%{labelCount} 更多"
+
msgid "%{gitlab_ci_yml} not found in this commit"
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr "%{group_docs_link_start}群組%{group_docs_link_end}å…許您管ç†ã€å”作多個項目。群組的æˆå“¡å¯ä»¥è¨ªå•ç¾¤çµ„下的所有項目。"
+
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
-msgstr ""
+msgstr "將會移除 %{issuableType}ï¼ç¢ºå®šï¼Ÿ"
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -173,25 +197,31 @@ msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr ""
msgid "%{loadingIcon} Started"
-msgstr ""
+msgstr "%{loadingIcon} 開始"
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
-msgstr ""
+msgstr "%{lock_path} 被使用者 %{lock_user_id} 鎖定"
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
-msgid "%{name}'s avatar"
+msgid "%{name} contained %{resultsString}"
msgstr ""
-msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgid "%{name} found %{resultsString}"
msgstr ""
+msgid "%{name}'s avatar"
+msgstr "%{name} çš„é ­åƒ"
+
+msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgstr "%{number_commits_behind} 個è½å¾Œæ–¼ %{default_branch} 分支的æ交,%{number_commits_ahead} 個超å‰çš„æ交"
+
msgid "%{openOrClose} %{noteable}"
-msgstr ""
+msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
-msgstr ""
+msgstr "%{percent}%% 完æˆ"
msgid "%{service_title} activated."
msgstr ""
@@ -199,6 +229,18 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -222,48 +264,73 @@ msgstr[0] ""
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
-msgstr[0] ""
+msgstr[0] "%{text} %{files} 個檔案"
msgid "%{text} is available"
+msgstr "%{text} å¯ç”¨"
+
+msgid "%{title} %{operator} %{threshold}"
msgstr ""
msgid "%{title} changes"
-msgstr ""
+msgstr "%{title} 變更"
msgid "%{unstaged} unstaged and %{staged} staged changes"
-msgstr ""
+msgstr "%{unstaged} 個未暫存和 %{staged} 個已暫存變更"
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
-msgstr ""
+msgstr "%{usage_ping_link_start}了解更多%{usage_ping_link_end} 關於與GitLab Inc.共享的信æ¯"
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
msgid "+ %{count} more"
-msgstr ""
+msgstr "+ %{count} 以上"
msgid "+ %{moreCount} more"
-msgstr ""
+msgstr "+ %{moreCount} 更多"
msgid "+%{extraOptionCount} more"
msgstr ""
msgid ", or "
-msgstr ""
+msgstr "或"
msgid "- Runner is active and can process any new jobs"
-msgstr ""
+msgstr "- 執行器為啟用狀態,並且å¯ä»¥è™•ç†æ–°çš„任何工作。"
msgid "- Runner is paused and will not receive any new jobs"
-msgstr ""
+msgstr "- 執行器為暫åœç‹€æ…‹ï¼Œä¸”å°‡ä¸æœƒæŽ¥å—任何新的工作"
msgid "- show less"
+msgstr "顯示較少"
+
+msgid "0 for unlimited"
msgstr ""
msgid "1 %{type} addition"
@@ -276,34 +343,34 @@ msgstr[0] "%{count}%{type} 個變更"
msgid "1 Day"
msgid_plural "%d Days"
-msgstr[0] ""
+msgstr[0] "%d 天"
msgid "1 closed issue"
-msgid_plural "%d closed issues"
+msgid_plural "%{issues} closed issues"
msgstr[0] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
+msgid_plural "%{merge_requests} closed merge requests"
msgstr[0] ""
msgid "1 day"
-msgstr ""
+msgstr "1 天"
msgid "1 group"
msgid_plural "%d groups"
-msgstr[0] ""
+msgstr[0] "%d 個群組"
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
+msgid_plural "%{merge_requests} merged merge requests"
msgstr[0] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
+msgid_plural "%{issues} open issues"
msgstr[0] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
-msgstr[0] ""
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] "%{merge_requests} 個開啟åˆä½µè«‹æ±‚"
msgid "1 pipeline"
msgid_plural "%d pipelines"
@@ -311,63 +378,81 @@ msgstr[0] "%d æ¢æµæ°´ç·š"
msgid "1 role"
msgid_plural "%d roles"
-msgstr[0] ""
+msgstr[0] "%d 個角色"
msgid "1 user"
msgid_plural "%d users"
-msgstr[0] ""
+msgstr[0] "%d 個用戶"
msgid "1 week"
+msgstr "1 星期"
+
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
msgstr ""
msgid "1st contribution!"
+msgstr "第一個貢ç»!"
+
+msgid "20-29 contributions"
msgstr ""
msgid "2FA"
-msgstr ""
+msgstr "é›™é‡èªè­‰"
msgid "2FA enabled"
+msgstr "已啟用雙é‡èªè­‰"
+
+msgid "2FADevice|Registered On"
msgstr ""
msgid "3 days"
-msgstr ""
+msgstr "3 天"
msgid "3 hours"
-msgstr ""
+msgstr "3 å°æ™‚"
msgid "30 minutes"
+msgstr "30 分é˜"
+
+msgid "30+ contributions"
msgstr ""
msgid "403|Please contact your GitLab administrator to get permission."
-msgstr ""
+msgstr "403|è«‹å‘ä½ çš„ GitLab 管ç†å“¡ç”³è«‹ä½¿ç”¨æ¬Šé™ã€‚"
msgid "403|You don't have the permission to access this page."
-msgstr ""
+msgstr "您無權使用這個é é¢ã€‚"
msgid "404|Make sure the address is correct and the page hasn't moved."
-msgstr ""
+msgstr "404 |請確ä¿ç¶²å€æ­£ç¢ºä¸”網é ä½ç½®æ²’有被更改。"
msgid "404|Page Not Found"
-msgstr ""
+msgstr "無法找到網é "
msgid "404|Please contact your GitLab administrator if you think this is a mistake."
-msgstr ""
+msgstr "404 |如果您èªç‚ºé€™æ˜¯éŒ¯èª¤ï¼Œè«‹è¯ç¹«æ‚¨çš„GitLab管ç†å“¡ã€‚"
msgid "8 hours"
-msgstr ""
+msgstr "8 å°æ™‚"
msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> 將會在所有原本由 johnsmith@example.com 建立的議題和留言中加上「來自 <a href=\"#\">@johnsmith</a>ã€ä¸¦å°‡åŽŸæœ¬åˆ†é…給 johnsmith@example.com 的所有議題設定 <a href=\"#\">@johnsmith</a> 為被指派人。"
msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"John Smith\"</code> 將會在所有原本由 johnsmith@example.com 建立的跟進事宣和留言中加上「來自 John Smithã€ã€‚"
msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> 將會在所有原本由 johnsmith@example.com 建立的議題和留言中加上「來自 johnsm...@example.comã€ã€‚é›»å­ä¿¡ç®±ä½å€æˆ–使用者å稱將å—é®è”½ï¼Œä¿éšœç”¨å®¶ç§éš±ã€‚"
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr ""
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
@@ -378,13 +463,13 @@ msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</stron
msgstr ""
msgid "<strong>%{group_name}</strong> group members"
-msgstr ""
+msgstr "<strong>%{group_name}</strong> 群組æˆå“¡"
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
msgid "<strong>Deletes</strong> source branch"
-msgstr ""
+msgstr "<strong>刪除</strong>來æºåˆ†æ”¯"
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -404,23 +489,23 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
-msgid "A default branch cannot be chosen for an empty project."
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
-msgid "A deleted user"
+msgid "A default branch cannot be chosen for an empty project."
msgstr ""
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgid "A deleted user"
msgstr ""
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
-msgstr ""
+msgstr "將會å†å‰µå»ºä¸€å€‹æ–°çš„分支,並建立一個新的åˆä½µè«‹æ±‚。"
msgid "A new impersonation token has been created."
msgstr ""
@@ -429,7 +514,7 @@ msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but stil
msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
+msgstr "一個專案æ供了以下功能,存放你的文件(存儲庫),計劃你的工作(è­°é¡Œ),並發布你的文件(維基), %{among_other_things_link}。"
msgid "A ready-to-go template for use with Android apps."
msgstr ""
@@ -441,11 +526,14 @@ msgid "A regular expression that will be used to find the test coverage output i
msgstr ""
msgid "A user with write access to the source branch selected this option"
-msgstr ""
+msgstr "一個有存å–原始分支權é™çš„使用者,é¸æ“‡äº†æ­¤é …ç›®"
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr ""
@@ -459,22 +547,22 @@ msgid "About this feature"
msgstr ""
msgid "Abuse Reports"
-msgstr ""
+msgstr "濫用報告"
msgid "Abuse reports"
-msgstr ""
+msgstr "濫用報告"
msgid "Accept invitation"
msgstr ""
msgid "Accept terms"
-msgstr ""
+msgstr "接å—æ¢æ¬¾"
msgid "Accepted MR"
msgstr ""
msgid "Access Tokens"
-msgstr ""
+msgstr "å­˜å–憑證 (access token)"
msgid "Access denied for your LDAP account."
msgstr ""
@@ -491,12 +579,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
-msgid "Account"
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
msgstr ""
+msgid "AccessDropdown|Users"
+msgstr ""
+
+msgid "Account"
+msgstr "帳戶"
+
msgid "Account and limit"
msgstr ""
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -513,13 +613,13 @@ msgid "Activity"
msgstr "活動"
msgid "Add"
-msgstr ""
+msgstr "增加"
msgid "Add CHANGELOG"
-msgstr ""
+msgstr "新增 CHANGELOG"
msgid "Add CONTRIBUTING"
-msgstr ""
+msgstr "新增 CONTRIBUTING"
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -528,56 +628,74 @@ msgid "Add Jaeger URL"
msgstr ""
msgid "Add Kubernetes cluster"
-msgstr ""
+msgstr "增加 Kubernetes å¢é›†"
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
msgid "Add a general comment to this %{noteable_name}."
-msgstr ""
+msgstr "å° %{noteable_name} 新增一般留言。"
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
msgid "Add a link"
-msgstr ""
+msgstr "新增連çµ"
msgid "Add a numbered list"
msgstr ""
msgid "Add a table"
-msgstr ""
+msgstr "新增表格"
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr "新增待辦事項"
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
-msgid "Add approver(s)"
+msgid "Add an SSH key"
msgstr ""
-msgid "Add approvers"
+msgid "Add an issue"
msgstr ""
+msgid "Add approvers"
+msgstr "新增批准人"
+
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
+msgstr "ç«‹å³ç•™è¨€"
+
+msgid "Add email address"
msgstr ""
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
msgid "Add image comment"
-msgstr ""
+msgstr "增加圖片留言"
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr "新增標籤"
+
msgid "Add license"
msgstr ""
@@ -590,9 +708,18 @@ msgstr ""
msgid "Add new directory"
msgstr "添加新目錄"
+msgid "Add or subtract spent time"
+msgstr "增加或減少所花時間"
+
msgid "Add reaction"
msgstr ""
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -600,15 +727,18 @@ msgid "Add to review"
msgstr ""
msgid "Add todo"
-msgstr ""
+msgstr "增加待辦事項"
msgid "Add user(s) to the group:"
msgstr ""
-msgid "Add users or groups who are allowed to approve every merge request"
+msgid "Add users to group"
+msgstr ""
+
+msgid "AddMember|No users specified."
msgstr ""
-msgid "Add users to group"
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
msgstr ""
msgid "Added at"
@@ -617,53 +747,68 @@ msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
+msgid "Additional minutes"
+msgstr "é¡å¤–的筆記"
+
msgid "Additional text"
-msgstr ""
+msgstr "附加文字"
-msgid "Aditional minutes"
+msgid "Adds"
+msgstr "增加"
+
+msgid "Adds %{epic_ref} as child epic."
msgstr ""
+msgid "Adds a todo."
+msgstr "新增待辦事項。"
+
msgid "Admin Area"
-msgstr ""
+msgstr "管ç†å€åŸŸ"
msgid "Admin Overview"
-msgstr ""
+msgstr "管ç†ç¸½è¦½"
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "您正打算永久刪除 %{username} 使用者。這將會刪除連çµåˆ°é€™äº›ä½¿ç”¨è€…的所有議題ã€åˆä½µè«‹æ±‚與群組。若è¦é¿å…資料éºå¤±ï¼Œè«‹è€ƒæ…®æ”¹ç”¨%{strong_start}å°éŽ–使用者%{strong_end}功能,因為%{strong_start}刪除使用者%{strong_end}動作一執行就無法復原。"
msgid "AdminArea|Stop all jobs"
-msgstr ""
+msgstr "åœæ­¢æ‰€æœ‰ä»»å‹™"
msgid "AdminArea|Stop all jobs?"
-msgstr ""
+msgstr "è¦åœæ­¢æ‰€æœ‰ä»»å‹™å—Žï¼Ÿ"
msgid "AdminArea|Stop jobs"
-msgstr ""
+msgstr "åœæ­¢ä»»å‹™"
msgid "AdminArea|Stopping jobs failed"
-msgstr ""
+msgstr "åœæ­¢ä»»å‹™å¤±æ•—"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
+msgstr "您將åœæ­¢æ‰€æœ‰ä»»å‹™ï¼Œé€™å°‡æœƒæš«åœæ‰€æœ‰æ­£åœ¨é‹è¡Œçš„任務。"
+
+msgid "AdminNote|Note"
msgstr ""
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "項目管ç†|你正打算永久刪除項目 %{projectName},其儲存庫,以åŠæ‰€æœ‰ç›¸é—œè³‡æºå¦‚議題,版本åˆä½µè«‹æ±‚等等。如確èªä¸¦æŒ‰ä¸‹%{strong_start}刪除項目%{strong_end}後,此æ“作將無法復原。"
msgid "AdminProjects|Delete"
-msgstr ""
+msgstr "刪除"
msgid "AdminProjects|Delete Project %{projectName}?"
-msgstr ""
+msgstr "刪除項目 %{projectName}?"
msgid "AdminProjects|Delete project"
-msgstr ""
+msgstr "刪除項目"
msgid "AdminSettings|Auto DevOps domain"
msgstr ""
@@ -675,7 +820,7 @@ msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
-msgstr ""
+msgstr "為æ¯å€‹é …目的自動複閱應用åŠè‡ªå‹•éƒ¨ç½²æŒ‡å®šä¸€å€‹é è¨­çš„網域"
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -687,37 +832,37 @@ msgid "AdminUsers|2FA Enabled"
msgstr ""
msgid "AdminUsers|Active"
-msgstr ""
+msgstr "æ´»èº"
msgid "AdminUsers|Admin"
-msgstr ""
+msgstr "管ç†å“¡"
msgid "AdminUsers|Admins"
-msgstr ""
+msgstr "管ç†å“¡"
msgid "AdminUsers|Block user"
-msgstr ""
+msgstr "å°éŽ–使用者"
msgid "AdminUsers|Blocked"
-msgstr ""
+msgstr "å·²å°éŽ–"
msgid "AdminUsers|Cannot unblock LDAP blocked users"
-msgstr ""
+msgstr "無法解å°éŽ–已被å°éŽ–çš„ LDAP 使用者"
msgid "AdminUsers|Delete User %{username} and contributions?"
-msgstr ""
+msgstr "刪除使用者 %{username} åŠå…¶è²¢ç»ï¼Ÿ"
msgid "AdminUsers|Delete User %{username}?"
-msgstr ""
+msgstr "刪除使用者 %{username} ?"
msgid "AdminUsers|Delete user"
-msgstr ""
+msgstr "刪除使用者"
msgid "AdminUsers|Delete user and contributions"
-msgstr ""
+msgstr "刪除使用者åŠå…¶è²¢ç»"
msgid "AdminUsers|External"
-msgstr ""
+msgstr "外部"
msgid "AdminUsers|It's you!"
msgstr ""
@@ -741,10 +886,10 @@ msgid "AdminUsers|Sort by"
msgstr ""
msgid "AdminUsers|To confirm, type %{projectName}"
-msgstr ""
+msgstr "請輸入 %{projectName} 以進行確èª"
msgid "AdminUsers|To confirm, type %{username}"
-msgstr ""
+msgstr "請輸入 %{username} 以進行確èª"
msgid "AdminUsers|User will be blocked"
msgstr ""
@@ -756,20 +901,23 @@ msgid "Advanced"
msgstr ""
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
-msgstr ""
+msgstr "é€²éšŽæ¬Šé™ ï¼Œå¤§æª”æ¡ˆå„²å­˜èˆ‡é›™é‡é‘‘證設定"
msgid "Advanced search functionality"
msgstr ""
msgid "Advanced settings"
-msgstr ""
+msgstr "進階設定"
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
-msgstr[0] ""
+msgstr[0] "æ示"
msgid "Alerts"
msgstr ""
@@ -781,22 +929,31 @@ msgid "All Members"
msgstr ""
msgid "All changes are committed"
+msgstr "所有改變都已經æ交"
+
+msgid "All email addresses will be used to identify your commits."
msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr "從模æ¿å»ºç«‹æˆ–導入專案時將啟用所有功能,您å¯ä»¥åœ¨å°ˆæ¡ˆè¨­ç½®ä¸­å°‡å…¶é—œé–‰ã€‚"
+
+msgid "All groups and projects"
msgstr ""
msgid "All issues for this milestone are closed. You may close this milestone now."
-msgstr ""
+msgstr "此里程碑è£çš„所有議題å‡å·²é—œé–‰ã€‚ä½ ç¾åœ¨å¯ä»¥é—œé–‰æ­¤é‡Œç¨‹ç¢‘。"
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
-msgid "All todos were marked as done."
+msgid "All projects"
msgstr ""
+msgid "All todos were marked as done."
+msgstr "所有待辦事項都標記為已完æˆã€‚"
+
msgid "All users"
-msgstr ""
+msgstr "所有使用者"
msgid "All users must have a name."
msgstr ""
@@ -805,7 +962,7 @@ msgid "Allow \"%{group_name}\" to sign you in"
msgstr ""
msgid "Allow commits from members who can merge to the target branch."
-msgstr ""
+msgstr "容許授權開發者å‘å…±åŒå”作分支æ交"
msgid "Allow group owners to manage LDAP-related settings"
msgstr ""
@@ -817,16 +974,16 @@ msgid "Allow only the selected protocols to be used for Git access."
msgstr ""
msgid "Allow projects within this group to use Git LFS"
-msgstr ""
+msgstr "容許本項目採用 Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
-msgstr ""
+msgstr "å…許在 Asciidoc 文件中渲染 PlantUML 圖片"
msgid "Allow requests to the local network from hooks and services."
-msgstr ""
+msgstr "å…許來自鉤å­å’Œæœå‹™çš„å°æœ¬åœ°ç¶²çµ¡çš„請求。"
msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
msgstr ""
@@ -844,7 +1001,7 @@ msgid "Allowed to fail"
msgstr ""
msgid "Allows you to add and manage Kubernetes clusters."
-msgstr ""
+msgstr "å…許您增加和管ç†Kuberneteså¢é›†ã€‚"
msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
msgstr ""
@@ -864,9 +1021,6 @@ msgstr ""
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -895,17 +1049,20 @@ msgid "An error occurred fetching the dropdown data."
msgstr ""
msgid "An error occurred previewing the blob"
-msgstr ""
+msgstr "é è¦½ blob 檔案時發生錯誤"
msgid "An error occurred when toggling the notification subscription"
-msgstr ""
+msgstr "切æ›è¨‚閱通知時發生錯誤"
-msgid "An error occurred when updating the issue weight"
+msgid "An error occurred when trying to resolve a comment. Please try again."
msgstr ""
-msgid "An error occurred while adding approver"
+msgid "An error occurred when trying to resolve a discussion. Please try again."
msgstr ""
+msgid "An error occurred when updating the issue weight"
+msgstr "更新議題權é‡æ™‚發生錯誤"
+
msgid "An error occurred while deleting the approvers group"
msgstr ""
@@ -919,27 +1076,42 @@ msgid "An error occurred while disabling Service Desk."
msgstr ""
msgid "An error occurred while dismissing the alert. Refresh the page and try again."
-msgstr ""
+msgstr "當解除通知時錯誤發生。請嘗試é‡æ–°æ•´ç†é é¢ä¸¦é‡è©¦ã€‚"
msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
-msgstr ""
+msgstr "解除亮高顯示時發生錯誤,請é‡æ–°æ•´ç†é é¢å†æ¬¡å˜—試。"
msgid "An error occurred while enabling Service Desk."
msgstr ""
-msgid "An error occurred while fetching markdown preview"
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
msgstr ""
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
+msgid "An error occurred while fetching markdown preview"
+msgstr "è®€å– markdown é è¦½æ™‚發生錯誤"
+
msgid "An error occurred while fetching pending comments"
msgstr ""
+msgid "An error occurred while fetching projects autocomplete."
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
+msgstr "讀å–å´é‚Šæ¬„資料時發生錯誤"
+
+msgid "An error occurred while fetching the Service Desk address."
msgstr ""
-msgid "An error occurred while fetching stages."
+msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
-msgid "An error occurred while fetching the Service Desk address."
+msgid "An error occurred while fetching the builds."
msgstr ""
msgid "An error occurred while fetching the job log."
@@ -952,14 +1124,17 @@ msgid "An error occurred while fetching the jobs."
msgstr ""
msgid "An error occurred while fetching the pipeline."
-msgstr ""
+msgstr "讀å–æµæ°´ç·šæ™‚發生錯誤"
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
-msgid "An error occurred while getting projects"
+msgid "An error occurred while fetching this tab."
msgstr ""
+msgid "An error occurred while getting projects"
+msgstr "讀å–專案時發生錯誤"
+
msgid "An error occurred while importing project: %{details}"
msgstr ""
@@ -970,7 +1145,7 @@ msgid "An error occurred while loading chart data"
msgstr ""
msgid "An error occurred while loading commit signatures"
-msgstr ""
+msgstr "載入上交簽署時發生錯誤"
msgid "An error occurred while loading designs. Please try again."
msgstr ""
@@ -990,7 +1165,10 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr ""
-msgid "An error occurred while removing approver"
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
msgstr ""
msgid "An error occurred while removing epics."
@@ -1015,16 +1193,16 @@ msgid "An error occurred while saving LDAP override status. Please try again."
msgstr ""
msgid "An error occurred while saving assignees"
-msgstr ""
+msgstr "儲存指派人時發生錯誤"
msgid "An error occurred while saving the approval settings"
msgstr ""
msgid "An error occurred while subscribing to notifications."
-msgstr ""
+msgstr "訂閱通知時出錯"
msgid "An error occurred while unsubscribing to notifications."
-msgstr ""
+msgstr "å–消訂閱通知時出錯"
msgid "An error occurred while updating approvers"
msgstr ""
@@ -1044,6 +1222,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1101,18 +1282,30 @@ msgstr ""
msgid "Any Label"
msgstr ""
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
-msgid "Appearance"
+msgid "Any namespace"
msgstr ""
+msgid "Appearance"
+msgstr "外觀"
+
msgid "Appearance was successfully created."
msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr ""
@@ -1122,6 +1315,9 @@ msgstr ""
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1132,7 +1328,7 @@ msgid "Application: %{name}"
msgstr ""
msgid "Applications"
-msgstr ""
+msgstr "應用程å¼"
msgid "Applied"
msgstr ""
@@ -1140,6 +1336,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1175,19 +1383,13 @@ msgid "ApprovalRule|e.g. QA, Security, etc."
msgstr ""
msgid "Approvals"
-msgstr ""
-
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
+msgstr "批准"
msgid "Apr"
-msgstr ""
+msgstr "四月"
msgid "April"
-msgstr ""
+msgstr "四月"
msgid "Archive jobs"
msgstr ""
@@ -1205,7 +1407,7 @@ msgid "Archiving the project will make it entirely read-only. It is hidden from
msgstr ""
msgid "Are you sure"
-msgstr ""
+msgstr "確定?"
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -1213,6 +1415,18 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
+msgid "Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr ""
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to delete this list?"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "確定è¦åˆªé™¤æ­¤æµæ°´ç·šè¨ˆåŠƒå—Žï¼Ÿ"
@@ -1234,18 +1448,6 @@ msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
-msgid "Are you sure you want to remove approver %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove approver %{name}?"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}?"
-msgstr ""
-
msgid "Are you sure you want to remove the attachment?"
msgstr ""
@@ -1261,6 +1463,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr "確定è¦é‡ç½®å¥åº·æª¢æŸ¥ä»¤ç‰Œå—Žï¼Ÿ"
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -1273,12 +1478,36 @@ msgstr ""
msgid "Are you sure?"
msgstr "確定嗎?"
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
msgstr ""
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr ""
@@ -1291,21 +1520,30 @@ msgstr ""
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr "指派"
+
msgid "Assign custom color like #FF0000"
msgstr ""
msgid "Assign labels"
-msgstr ""
+msgstr "指派標籤"
msgid "Assign milestone"
-msgstr ""
+msgstr "指派里程碑"
msgid "Assign some issues to this milestone."
-msgstr ""
+msgstr "分é…一些議題到這個里程碑。"
msgid "Assign to"
msgstr ""
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr ""
@@ -1316,16 +1554,16 @@ msgid "Assigned to me"
msgstr ""
msgid "Assignee"
-msgstr ""
+msgstr "指派人"
msgid "Assignee lists not available with your current license"
-msgstr ""
+msgstr "您目å‰çš„許å¯è­‰ä¸æ”¯æ´æŒ‡æ´¾äººåå–®"
msgid "Assignee lists show all issues assigned to the selected user."
-msgstr ""
+msgstr "指派人å單顯示了分é…給é¸å®šä½¿ç”¨è€…的所有議題。"
msgid "Assignee(s)"
-msgstr ""
+msgstr "指派人"
msgid "At least one approval from a code owner is required to change files matching the respective CODEOWNER rules."
msgstr ""
@@ -1336,14 +1574,21 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "拖放文件到此處或者 %{upload_link}"
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr ""
msgid "Aug"
-msgstr ""
+msgstr "八月"
msgid "August"
-msgstr ""
+msgstr "八月"
msgid "Authentication Log"
msgstr ""
@@ -1423,15 +1668,24 @@ msgstr ""
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr ""
-msgid "Automatically marked as default internal user"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
msgstr ""
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
msgstr ""
msgid "Automatically resolved"
msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -1445,7 +1699,7 @@ msgid "Available specific runners"
msgstr ""
msgid "Avatar for %{assigneeName}"
-msgstr ""
+msgstr "%{assigneeName} çš„é ­åƒ"
msgid "Avatar for %{name}"
msgstr ""
@@ -1487,62 +1741,86 @@ msgid "Badges|Delete badge"
msgstr ""
msgid "Badges|Delete badge?"
-msgstr ""
+msgstr "你確定è¦åˆªé™¤å¾½ç« å—Žï¼Ÿ"
msgid "Badges|Deleting the badge failed, please try again."
-msgstr ""
+msgstr "刪除徽章失敗,請ç¨å€™é‡è©¦"
msgid "Badges|Group Badge"
-msgstr ""
+msgstr "群組徽章"
msgid "Badges|Link"
-msgstr ""
+msgstr "連çµ"
msgid "Badges|No badge image"
-msgstr ""
+msgstr "沒有徽章圖片"
msgid "Badges|No image to preview"
-msgstr ""
+msgstr "沒有圖片å¯ä»¥é è¦½"
msgid "Badges|Please fill in a valid URL"
msgstr ""
msgid "Badges|Project Badge"
-msgstr ""
+msgstr "專案徽章"
msgid "Badges|Reload badge image"
-msgstr ""
+msgstr "é‡æ–°è®€å–徽章圖片"
msgid "Badges|Save changes"
-msgstr ""
+msgstr "儲存變更"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
-msgstr ""
+msgstr "儲存徽章失敗,請檢查輸入的連çµä¸¦é‡è©¦ã€‚"
msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr ""
+msgstr "%{docsLinkStart} 變數%{docsLinkEnd} GitLab 支æ´ï¼š%{placeholders}"
msgid "Badges|The badge was deleted."
-msgstr ""
+msgstr "此徽章已移除"
msgid "Badges|The badge was saved."
-msgstr ""
+msgstr "此徽章已儲存。"
msgid "Badges|This group has no badges"
-msgstr ""
+msgstr "此群組無徽章。"
msgid "Badges|This project has no badges"
-msgstr ""
+msgstr "此專案無徽章"
msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
msgstr ""
msgid "Badges|Your badges"
-msgstr ""
+msgstr "您的徽章"
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr ""
@@ -1559,7 +1837,7 @@ msgid "Be careful. Renaming a project's repository can have unintended side effe
msgstr ""
msgid "Begin with the selected commit"
-msgstr ""
+msgstr "從é¸å®šçš„變更紀錄開始"
msgid "Below are examples of regex for existing tools:"
msgstr ""
@@ -1628,7 +1906,7 @@ msgid "BillingPlans|monthly"
msgstr ""
msgid "BillingPlans|paid annually at %{price_per_year}"
-msgstr ""
+msgstr "æ¯å¹´æ”¶å– %{price_per_year}"
msgid "BillingPlans|per user"
msgstr ""
@@ -1645,12 +1923,29 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+
msgid "Blog"
msgstr ""
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr ""
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
@@ -1658,12 +1953,15 @@ msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy
msgstr "分支 <strong>%{branch_name}</strong> 已創建。如需設置自動部署, è«‹é¸æ“‡åˆé©çš„ GitLab CI Yaml 模æ¿ä½µæ交更改。%{link_to_autodeploy_doc}"
msgid "Branch has changed"
-msgstr ""
+msgstr "分支已變更"
msgid "Branch is already taken"
-msgstr ""
+msgstr "分支已被採å–"
msgid "Branch name"
+msgstr "分支å稱"
+
+msgid "Branch not loaded - %{branchId}"
msgstr ""
msgid "BranchSwitcherPlaceholder|Search branches"
@@ -1676,31 +1974,31 @@ msgid "Branches"
msgstr "分支"
msgid "Branches|Active"
-msgstr ""
+msgstr "æ´»èºçš„"
msgid "Branches|Active branches"
-msgstr ""
+msgstr "æ´»èºçš„分支"
msgid "Branches|All"
-msgstr ""
+msgstr "全部"
msgid "Branches|Cant find HEAD commit for this branch"
-msgstr ""
+msgstr "找ä¸åˆ°æ­¤åˆ†æ”¯çš„ HEAD 更動。"
msgid "Branches|Compare"
-msgstr ""
+msgstr "比較"
msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
-msgstr ""
+msgstr "移除所有已經åˆä½µåˆ° %{default_branch} 的分支。"
msgid "Branches|Delete branch"
-msgstr ""
+msgstr "移除分支"
msgid "Branches|Delete merged branches"
-msgstr ""
+msgstr "移除已經åˆä½µçš„分支"
msgid "Branches|Delete protected branch"
-msgstr ""
+msgstr "移除å—ä¿è­·çš„分支"
msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr ""
@@ -1718,10 +2016,10 @@ msgid "Branches|Merged into %{default_branch}"
msgstr ""
msgid "Branches|New branch"
-msgstr ""
+msgstr "新增分支"
msgid "Branches|No branches to show"
-msgstr ""
+msgstr "找ä¸åˆ°åˆ†æ”¯"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
msgstr ""
@@ -1816,6 +2114,21 @@ msgstr "ç€è¦½æ–‡ä»¶"
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1834,6 +2147,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "作者:"
@@ -1924,9 +2240,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr ""
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1948,9 +2270,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr "無法通éŽå…§éƒ¨ID引用組里程碑ï¼"
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -1964,7 +2292,13 @@ msgid "Certificate (PEM)"
msgstr ""
msgid "Change Weight"
-msgstr ""
+msgstr "更改權é‡"
+
+msgid "Change assignee(s)"
+msgstr "更改指派人"
+
+msgid "Change assignee(s)."
+msgstr "更改指派人。"
msgid "Change path"
msgstr ""
@@ -1978,6 +2312,15 @@ msgstr ""
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr ""
+msgid "Change title"
+msgstr "更改標題"
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "挑é¸åˆ°åˆ†æ”¯"
@@ -1994,7 +2337,7 @@ msgid "ChangeTypeAction|This will create a new commit in order to revert the exi
msgstr ""
msgid "Changes"
-msgstr ""
+msgstr "變更"
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
@@ -2002,6 +2345,12 @@ msgstr ""
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr "將標題改為「%{title_param}ã€ã€‚"
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr "統計圖"
@@ -2029,6 +2378,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr "優é¸æ­¤æ交"
@@ -2050,6 +2402,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr ""
@@ -2080,7 +2435,7 @@ msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2152,16 +2507,34 @@ msgstr "已跳éŽ"
msgid "CiStatus|running"
msgstr "é‹è¡Œä¸­"
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2215,14 +2588,23 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
+msgstr "在專案列表點擊任何<strong>專案å稱</strong>,將轉跳到專案的里程碑。"
+
+msgid "Click here"
msgstr ""
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
-msgstr ""
+msgstr "點擊左上角的<strong>æå‡</strong>按鈕,將æå‡è‡³ç¾¤çµ„里程碑。"
msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
msgstr ""
@@ -2270,13 +2652,16 @@ msgid "Close epic"
msgstr ""
msgid "Close milestone"
-msgstr ""
+msgstr "關閉里程碑"
+
+msgid "Close sidebar"
+msgstr "關閉å´é‚Šæ¬„"
msgid "Closed"
-msgstr ""
+msgstr "已關閉"
msgid "Closed issues"
-msgstr ""
+msgstr "已關閉議題"
msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
msgstr ""
@@ -2290,7 +2675,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2308,12 +2699,24 @@ msgstr ""
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2329,6 +2732,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr ""
@@ -2437,6 +2843,9 @@ msgstr ""
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr ""
@@ -2473,19 +2882,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
-msgid "ClusterIntegration|Install"
-msgstr ""
-
-msgid "ClusterIntegration|Installed"
-msgstr ""
-
-msgid "ClusterIntegration|Installing"
-msgstr ""
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2518,6 +2918,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2554,6 +2957,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2563,9 +2969,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Manage"
-msgstr ""
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
@@ -2629,7 +3032,7 @@ msgstr ""
msgid "ClusterIntegration|Request to begin installing failed"
msgstr ""
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2683,40 +3086,52 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr ""
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
-msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
-msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
-msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
msgstr ""
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|Updating"
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
-msgid "ClusterIntegration|Upgrade"
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Upgrade failed"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2728,6 +3143,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr ""
@@ -2737,6 +3155,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr ""
@@ -2786,27 +3207,36 @@ msgid "Collapse approvers"
msgstr ""
msgid "Collapse sidebar"
+msgstr "收起å´é‚Šæ¬„"
+
+msgid "ComboSearch is not defined"
msgstr ""
msgid "Command line instructions"
msgstr ""
-msgid "Comment"
+msgid "Commands applied"
msgstr ""
+msgid "Comment"
+msgstr "留言"
+
msgid "Comment & close %{noteable_name}"
-msgstr ""
+msgstr "留言並關閉 %{noteable_name}"
msgid "Comment & reopen %{noteable_name}"
-msgstr ""
+msgstr "留言並é‡æ–°é–‹å•Ÿ %{noteable_name}"
msgid "Comment & resolve discussion"
-msgstr ""
+msgstr "留言並關閉討論"
msgid "Comment & unresolve discussion"
-msgstr ""
+msgstr "留言並é‡æ–°è¨Žè«–"
msgid "Comment form position"
+msgstr "留言框ä½ç½®"
+
+msgid "Comment is being updated"
msgstr ""
msgid "Comments"
@@ -2868,7 +3298,7 @@ msgid "Commits|Commit: %{commitText}"
msgstr ""
msgid "Commits|History"
-msgstr "æ­·å²"
+msgstr "æ­·å²ç´€éŒ„"
msgid "Commits|No related merge requests found"
msgstr ""
@@ -2895,7 +3325,7 @@ msgid "Compare changes"
msgstr ""
msgid "Compare changes with the last commit"
-msgstr ""
+msgstr "與最後æ交進行比較"
msgid "Compare changes with the merge request target branch"
msgstr ""
@@ -2916,10 +3346,10 @@ msgid "CompareBranches|There isn't anything to compare."
msgstr ""
msgid "Confidential"
-msgstr ""
+msgstr "隱密"
msgid "Confidentiality"
-msgstr ""
+msgstr "隱密的"
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
@@ -2927,6 +3357,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -2954,9 +3387,15 @@ msgstr ""
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr ""
@@ -2969,9 +3408,15 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr ""
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3035,6 +3480,9 @@ msgstr ""
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3048,7 +3496,7 @@ msgid "Continuous Integration and Deployment"
msgstr ""
msgid "Contribute to GitLab"
-msgstr ""
+msgstr "為 GitLab è²¢ç»"
msgid "Contribution"
msgstr ""
@@ -3080,6 +3528,9 @@ msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr ""
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr ""
@@ -3089,6 +3540,9 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3107,9 +3561,6 @@ msgstr ""
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr ""
-
msgid "Copy URL to clipboard"
msgstr "複製URL到剪貼æ¿"
@@ -3123,6 +3574,12 @@ msgid "Copy commit SHA to clipboard"
msgstr "複製æ交 SHA 到剪貼æ¿"
msgid "Copy file path to clipboard"
+msgstr "複製檔案路徑到剪貼簿"
+
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr "從 %{source_issuable_reference} 複製標籤和里程碑。"
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
msgstr ""
msgid "Copy link"
@@ -3134,6 +3591,9 @@ msgstr ""
msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy source to clipboard"
+msgstr "將代碼複製到剪貼簿"
+
msgid "Copy to clipboard"
msgstr ""
@@ -3143,9 +3603,15 @@ msgstr ""
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3179,12 +3645,21 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr "建立åˆä½µè«‹æ±‚。"
+
msgid "Create a new branch"
msgstr ""
-msgid "Create a new issue"
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
msgstr ""
+msgid "Create a new issue"
+msgstr "建立新議題"
+
msgid "Create a new repository"
msgstr ""
@@ -3192,10 +3667,10 @@ msgid "Create a personal access token on your account to pull or push via %{prot
msgstr "在帳戶上創建個人訪å•ä»¤ç‰Œï¼Œä»¥é€šéŽ %{protocol} 來拉å–或推é€ã€‚"
msgid "Create an issue. Issues are created for each alert triggered."
-msgstr ""
+msgstr "建立議題。為已觸發的æ¯å€‹è­¦å ±å»ºç«‹è­°é¡Œã€‚"
msgid "Create branch"
-msgstr ""
+msgstr "建立分支"
msgid "Create commit"
msgstr ""
@@ -3216,19 +3691,19 @@ msgid "Create group"
msgstr ""
msgid "Create group label"
-msgstr ""
+msgstr "建立群組標籤"
msgid "Create lists from labels. Issues with that label appear in that list."
-msgstr ""
+msgstr "建立標籤列表。å«æœ‰æ­¤æ¨™ç±¤çš„議題將會在清單中顯示。"
msgid "Create merge request"
msgstr "創建åˆä½µè«‹æ±‚"
msgid "Create merge request and branch"
-msgstr ""
+msgstr "建立åˆä½µè«‹æ±‚åŠåˆ†æ”¯"
msgid "Create milestone"
-msgstr ""
+msgstr "建立里程碑"
msgid "Create new branch"
msgstr ""
@@ -3243,17 +3718,23 @@ msgid "Create new file or directory"
msgstr ""
msgid "Create new label"
-msgstr ""
+msgstr "建立新標籤"
msgid "Create new..."
msgstr "創建..."
msgid "Create project label"
-msgstr ""
+msgstr "建立專案標籤"
msgid "Create your first page"
msgstr ""
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr "標籤"
@@ -3269,12 +3750,27 @@ msgstr ""
msgid "Created by me"
msgstr ""
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr ""
msgid "Created on:"
msgstr ""
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
msgstr ""
@@ -3293,6 +3789,9 @@ msgstr ""
msgid "Current node"
msgstr ""
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr ""
@@ -3371,7 +3870,19 @@ msgstr ""
msgid "DashboardProjects|Personal"
msgstr ""
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
+msgstr "儀表æ¿"
+
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Data is still calculating..."
@@ -3380,20 +3891,32 @@ msgstr ""
msgid "Date picker"
msgstr ""
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr ""
msgid "Dec"
-msgstr ""
+msgstr "å二月"
msgid "December"
-msgstr ""
+msgstr "å二月"
msgid "Decline"
-msgstr ""
+msgstr "拒絕"
msgid "Decline and sign out"
-msgstr ""
+msgstr "拒絕並登出"
msgid "Default Branch"
msgstr ""
@@ -3416,6 +3939,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr ""
@@ -3453,7 +3979,7 @@ msgid "Delete Snippet"
msgstr ""
msgid "Delete comment"
-msgstr ""
+msgstr "刪除留言"
msgid "Delete license"
msgstr ""
@@ -3467,6 +3993,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr ""
@@ -3488,6 +4029,54 @@ msgstr ""
msgid "Deny"
msgstr ""
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "部署"
@@ -3663,6 +4252,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3717,9 +4309,15 @@ msgstr ""
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -3741,6 +4339,12 @@ msgstr ""
msgid "Discard review"
msgstr ""
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3754,7 +4358,7 @@ msgid "Discuss a specific suggestion or question that needs to be resolved"
msgstr ""
msgid "Discussion"
-msgstr ""
+msgstr "討論"
msgid "Dismiss"
msgstr ""
@@ -3771,18 +4375,42 @@ msgstr ""
msgid "Dismiss trial promotion"
msgstr ""
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
+msgid "Dockerfile"
+msgstr "Dockerfile"
+
msgid "Documentation for popular identity providers"
msgstr ""
msgid "Domain"
msgstr ""
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr "ä¸å†é¡¯ç¤º"
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr ""
@@ -3795,25 +4423,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
-msgstr ""
-
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
+msgid "Download codes"
msgstr ""
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3832,7 +4454,7 @@ msgid "Downvotes"
msgstr ""
msgid "Due date"
-msgstr ""
+msgstr "截止日期"
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr ""
@@ -3853,6 +4475,9 @@ msgid "Edit Label"
msgstr ""
msgid "Edit Milestone"
+msgstr "編輯里程碑"
+
+msgid "Edit Password"
msgstr ""
msgid "Edit Pipeline Schedule %{id}"
@@ -3865,7 +4490,7 @@ msgid "Edit application"
msgstr ""
msgid "Edit comment"
-msgstr ""
+msgstr "編輯留言"
msgid "Edit environment"
msgstr ""
@@ -3883,7 +4508,7 @@ msgid "Edit identity for %{user_name}"
msgstr ""
msgid "Edit issues"
-msgstr ""
+msgstr "編輯議題"
msgid "Edit public deploy key"
msgstr ""
@@ -3891,6 +4516,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
@@ -3909,6 +4540,9 @@ msgstr ""
msgid "Email patch"
msgstr ""
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3933,9 +4567,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr ""
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr ""
@@ -3960,6 +4624,9 @@ msgstr ""
msgid "Enable Sentry for error reporting and logging."
msgstr ""
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -3996,9 +4663,6 @@ msgstr ""
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr ""
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4029,17 +4693,23 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr ""
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
-msgid "Enter the issue description"
+msgid "Enter in your Phabricator Server URL and personal access token below"
msgstr ""
+msgid "Enter the issue description"
+msgstr "輸入議題說明"
+
msgid "Enter the issue title"
-msgstr ""
+msgstr "輸入議題標題"
msgid "Enter the merge request description"
msgstr ""
@@ -4047,7 +4717,10 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4059,9 +4732,33 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -4197,20 +4894,53 @@ msgstr ""
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr ""
msgid "Epics|More information"
msgstr ""
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
+msgstr "這些日期會影響在開發è—圖中 Epic 的顯示方å¼ã€‚來自里程碑的日期來自å°æ‡‰åˆ° Epic 中議題的里程碑。您也å¯ä»¥è¨­å®šå›ºå®šæ—¥æœŸã€æˆ–是完全移除它們。"
+
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
-msgstr ""
+msgstr "è‹¥è¦æŽ’程基於里程碑的 Epic %{epicDateType} 日期,請å°ä»»ä½• Epic 中的議題指定 %{epicDateType} 日期的里程碑。"
msgid "Epics|due"
msgstr ""
@@ -4240,14 +4970,20 @@ msgid "Error fetching contributors data."
msgstr ""
msgid "Error fetching labels."
-msgstr ""
+msgstr "讀å–標籤時發生錯誤。"
msgid "Error fetching network graph."
msgstr ""
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr ""
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr ""
@@ -4257,15 +4993,24 @@ msgstr ""
msgid "Error loading branches."
msgstr ""
-msgid "Error loading last commit."
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
msgstr ""
+msgid "Error loading last commit."
+msgstr "載入最後æ交時失敗。"
+
msgid "Error loading markdown preview"
msgstr ""
msgid "Error loading merge requests."
msgstr ""
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr ""
@@ -4275,6 +5020,12 @@ msgstr ""
msgid "Error loading template."
msgstr ""
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr ""
@@ -4294,23 +5045,29 @@ msgid "Error rendering markdown preview"
msgstr ""
msgid "Error saving label update."
-msgstr ""
+msgstr "更新標籤時發生錯誤。"
msgid "Error updating %{issuableType}"
msgstr ""
msgid "Error updating status for all todos."
-msgstr ""
+msgstr "更新所有待辦事項的狀態時發生錯誤。"
msgid "Error updating todo status."
-msgstr ""
+msgstr "更新待辦事項狀態時發生錯誤。"
msgid "Error uploading file"
+msgstr "上傳檔案時出錯"
+
+msgid "Error uploading file: %{stripped}"
msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4407,6 +5164,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4494,6 +5254,27 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -4503,30 +5284,63 @@ msgstr ""
msgid "Failed Jobs"
msgstr ""
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr "無法變更所有者"
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
msgstr ""
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
-msgid "Failed to remove issue from board, please try again."
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
msgstr ""
+msgid "Failed to remove issue from board, please try again."
+msgstr "從看æ¿åˆªé™¤è­°é¡Œæ™‚發生錯誤,請ç¨å€™é‡è©¦ã€‚"
+
msgid "Failed to remove mirror."
msgstr ""
@@ -4542,6 +5356,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4554,16 +5374,28 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
+msgstr "更新議題時發生錯誤,請ç¨å¾Œé‡è©¦ã€‚"
+
+msgid "Failed to update tag!"
msgstr ""
-msgid "Failed to upload object map file"
+msgid "Failed to update."
msgstr ""
-msgid "Failure"
+msgid "Failed to upgrade."
msgstr ""
-msgid "Fast-forward merge"
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failure"
msgstr ""
msgid "Fast-forward merge without a merge commit"
@@ -4578,6 +5410,12 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4641,7 +5479,7 @@ msgstr ""
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -4653,9 +5491,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr ""
-
msgid "FeatureFlags|Name"
msgstr ""
@@ -4687,10 +5522,10 @@ msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
msgid "Feb"
-msgstr ""
+msgstr "二月"
msgid "February"
-msgstr ""
+msgstr "二月"
msgid "Fetching incoming email"
msgstr ""
@@ -4735,6 +5570,12 @@ msgstr ""
msgid "Files"
msgstr "文件"
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
@@ -4751,7 +5592,7 @@ msgid "Filter by commit message"
msgstr "按æ交消æ¯éŽæ¿¾"
msgid "Filter by milestone name"
-msgstr ""
+msgstr "é€éŽé‡Œç¨‹ç¢‘å稱篩é¸"
msgid "Filter by two-factor authentication"
msgstr ""
@@ -4783,6 +5624,9 @@ msgstr ""
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr ""
@@ -4792,6 +5636,9 @@ msgstr ""
msgid "Finish review"
msgstr ""
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -4808,7 +5655,7 @@ msgid "Fixed date"
msgstr ""
msgid "Fixed due date"
-msgstr ""
+msgstr "固定截止日期"
msgid "Fixed start date"
msgstr ""
@@ -4816,6 +5663,12 @@ msgstr ""
msgid "Fixed:"
msgstr ""
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr ""
@@ -4861,6 +5714,15 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "派生自"
@@ -4870,6 +5732,9 @@ msgstr ""
msgid "Forking in progress"
msgstr ""
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4888,6 +5753,9 @@ msgstr ""
msgid "Free Trial of GitLab.com Gold"
msgstr ""
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4913,17 +5781,23 @@ msgid "From merge request merge until deploy to production"
msgstr "從åˆä½µè«‹æ±‚çš„åˆä½µåˆ°éƒ¨ç½²è‡³ç”Ÿç”¢ç’°å¢ƒ"
msgid "From milestones:"
-msgstr ""
+msgstr "來自里程碑:"
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr ""
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -4937,7 +5811,7 @@ msgid "General pipelines"
msgstr ""
msgid "Generate a default set of labels"
-msgstr ""
+msgstr "產生é è¨­çš„標籤"
msgid "Generate key"
msgstr ""
@@ -5281,6 +6155,12 @@ msgstr ""
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5338,6 +6218,9 @@ msgstr ""
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5347,6 +6230,9 @@ msgstr ""
msgid "Git revision"
msgstr ""
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr ""
@@ -5419,6 +6305,9 @@ msgstr ""
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -5437,9 +6326,18 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr ""
@@ -5515,6 +6413,9 @@ msgstr ""
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5524,6 +6425,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr ""
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr ""
@@ -5551,13 +6455,16 @@ msgstr ""
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5569,9 +6476,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5602,9 +6506,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5666,6 +6579,9 @@ msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name
msgstr ""
msgid "Groups"
+msgstr "群組"
+
+msgid "Groups (%{count})"
msgstr ""
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
@@ -5737,6 +6653,9 @@ msgstr ""
msgid "GroupsTree|Search by name"
msgstr ""
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr ""
@@ -5764,21 +6683,27 @@ msgstr "沒有檢測到å¥åº·å•é¡Œ"
msgid "HealthCheck|Unhealthy"
msgstr "ä¸è‰¯"
-msgid "Help"
+msgid "Hello there"
msgstr ""
+msgid "Help"
+msgstr "説明"
+
msgid "Help page"
-msgstr ""
+msgstr "說明é é¢"
msgid "Help page text and support page url."
msgstr ""
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgid "Hide archived projects"
msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr ""
@@ -5788,6 +6713,9 @@ msgstr ""
msgid "Hide payload"
msgstr ""
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -5799,6 +6727,12 @@ msgid "Highest role:"
msgstr ""
msgid "History"
+msgstr "æ­·å²ç´€éŒ„"
+
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
msgstr ""
msgid "Hook was successfully created."
@@ -5816,6 +6750,12 @@ msgstr "已開始維護"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5825,6 +6765,12 @@ msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr ""
@@ -5894,10 +6840,19 @@ msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "ImageDiffViewer|2-up"
@@ -5978,6 +6933,12 @@ msgstr ""
msgid "Import repository"
msgstr "導入存儲庫"
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -5987,6 +6948,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr ""
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -5996,9 +6963,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr ""
@@ -6050,12 +7026,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr ""
@@ -6077,12 +7062,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
msgstr ""
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] ""
@@ -6129,18 +7126,42 @@ msgstr "週期分æžç°¡ä»‹"
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6150,6 +7171,9 @@ msgstr ""
msgid "Invite"
msgstr ""
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6162,6 +7186,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6175,14 +7202,20 @@ msgid "Issue board focus mode"
msgstr ""
msgid "Issue events"
-msgstr "議題事件 (issue event)"
+msgstr "議題事件"
msgid "Issue template (optional)"
msgstr ""
-msgid "IssueBoards|Board"
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
msgstr ""
+msgid "IssueBoards|Board"
+msgstr "看æ¿"
+
msgid "IssueBoards|Boards"
msgstr ""
@@ -6202,7 +7235,7 @@ msgid "IssueBoards|Switch board"
msgstr ""
msgid "Issues"
-msgstr ""
+msgstr "議題"
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
msgstr ""
@@ -6214,7 +7247,7 @@ msgid "Issues with comments, merge requests with diffs and comments, labels, mil
msgstr ""
msgid "Issues, merge requests, pushes, and comments."
-msgstr ""
+msgstr "è­°é¡Œã€åˆä½µè«‹æ±‚ã€æŽ¨é€åŠç•™è¨€ã€‚"
msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
msgstr ""
@@ -6250,9 +7283,51 @@ msgid "Jaeger tracing"
msgstr ""
msgid "Jan"
-msgstr ""
+msgstr "一月"
msgid "January"
+msgstr "一月"
+
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
msgstr ""
msgid "Job"
@@ -6346,20 +7421,29 @@ msgid "Job|with"
msgstr ""
msgid "Jul"
-msgstr ""
+msgstr "七月"
msgid "July"
+msgstr "七月"
+
+msgid "Jump to first unresolved discussion"
msgstr ""
-msgid "Jun"
+msgid "Jump to next unresolved discussion"
msgstr ""
+msgid "Jun"
+msgstr "六月"
+
msgid "June"
-msgstr ""
+msgstr "六月"
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr ""
@@ -6384,12 +7468,18 @@ msgstr ""
msgid "Kubernetes configured"
msgstr ""
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr ""
@@ -6402,9 +7492,12 @@ msgstr "åœç”¨"
msgid "LFSStatus|Enabled"
msgstr "啟用"
-msgid "Label"
+msgid "LICENSE"
msgstr ""
+msgid "Label"
+msgstr "標籤"
+
msgid "Label actions dropdown"
msgstr ""
@@ -6421,35 +7514,38 @@ msgid "Label was successfully updated."
msgstr ""
msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
-msgstr ""
+msgstr "%{firstLabelName} +%{remainingLabelCount} 更多"
msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
-msgstr ""
+msgstr "%{labelsString},和%{remainingLabelCount} 更多"
msgid "LabelSelect|Labels"
msgstr ""
msgid "Labels"
-msgstr ""
+msgstr "標籤"
msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
-msgstr ""
+msgstr "標籤å¯ä»¥æ‡‰ç”¨æ–¼ %{features}。群組標籤å¯ä»¥ç”¨æ–¼ä»»ä½•ç¾¤çµ„內的專案。"
msgid "Labels can be applied to issues and merge requests to categorize them."
-msgstr ""
+msgstr "標籤å¯ä»¥ç”¨æ–¼è­°é¡Œå’Œåˆä½µè«‹æ±‚以å°å®ƒå€‘進行分類。"
msgid "Labels can be applied to issues and merge requests."
-msgstr ""
+msgstr "標籤å¯ä»¥ç”¨æ–¼è­°é¡Œå’Œåˆä½µè«‹æ±‚。"
msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
-msgstr ""
+msgstr "<span>è¦è®“標籤</span> %{labelTitle} <span>æå‡åˆ°ç¾¤çµ„標籤嗎?</span>"
msgid "Labels|Promote Label"
-msgstr ""
+msgstr "æå‡æ¨™ç±¤"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6463,6 +7559,9 @@ msgstr[0] "最近 %d 天"
msgid "Last Pipeline"
msgstr "最新æµæ°´ç·š"
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
@@ -6485,9 +7584,15 @@ msgid "Last seen"
msgstr ""
msgid "Last update"
-msgstr ""
+msgstr "最後更新"
msgid "Last updated"
+msgstr "最後更新"
+
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
msgstr ""
msgid "LastPushEvent|You pushed to"
@@ -6505,6 +7610,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6512,7 +7623,7 @@ msgid "Learn more"
msgstr ""
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
-msgstr ""
+msgstr "了解更多有關 %{issue_boards_url} 的資訊,å¯ä»¥é€éŽæ¨™ç±¤ã€æŒ‡æ´¾äººã€é‡Œç¨‹ç¢‘來建立追蹤議題列表。如果您發ç¾è­°é¡Œçœ‹æ¿ä¸Šå°‘了一些資訊,請在 %{gitlab_issues_url} 建立議題。"
msgid "Learn more about Auto DevOps"
msgstr ""
@@ -6523,6 +7634,9 @@ msgstr ""
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6535,6 +7649,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr "了解更多"
@@ -6556,6 +7673,12 @@ msgstr "退出項目"
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr ""
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr ""
@@ -6631,6 +7754,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6644,6 +7770,9 @@ msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr ""
@@ -6660,7 +7789,7 @@ msgid "List of IPs and CIDRs of allowed secondary nodes. Comma-separated, e.g. \
msgstr ""
msgid "List view"
-msgstr ""
+msgstr "列表顯示"
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -6674,6 +7803,9 @@ msgstr ""
msgid "Loading contribution stats for group members"
msgstr ""
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -6687,7 +7819,7 @@ msgid "Localization"
msgstr ""
msgid "Lock"
-msgstr ""
+msgstr "鎖定"
msgid "Lock %{issuableDisplayName}"
msgstr ""
@@ -6695,6 +7827,9 @@ msgstr ""
msgid "Lock not found"
msgstr ""
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -6713,6 +7848,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr ""
@@ -6737,12 +7875,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr ""
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6750,13 +7897,13 @@ msgid "Manage Git repositories with fine-grained access controls that keep your
msgstr ""
msgid "Manage Web IDE features"
-msgstr ""
+msgstr "管ç†ç¶²é  IDE 功能"
msgid "Manage access"
msgstr ""
msgid "Manage all notifications"
-msgstr ""
+msgstr "管ç†æ‰€æœ‰é€šçŸ¥"
msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
msgstr ""
@@ -6765,13 +7912,13 @@ msgid "Manage applications that you've authorized to use your account."
msgstr ""
msgid "Manage group labels"
-msgstr ""
+msgstr "管ç†ç¾¤çµ„標籤"
msgid "Manage labels"
-msgstr ""
+msgstr "管ç†æ¨™ç±¤"
msgid "Manage project labels"
-msgstr ""
+msgstr "管ç†å°ˆæ¡ˆæ¨™ç±¤"
msgid "Manage two-factor authentication"
msgstr ""
@@ -6798,14 +7945,23 @@ msgid "Map a Google Code user to a full name"
msgstr ""
msgid "Mar"
-msgstr ""
+msgstr "三月"
msgid "March"
+msgstr "三月"
+
+msgid "Mark as resolved"
msgstr ""
-msgid "Mark todo as done"
+msgid "Mark comment as resolved"
msgstr ""
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
+msgid "Mark todo as done"
+msgstr "將待辦事項標記為已完æˆ"
+
msgid "Markdown"
msgstr ""
@@ -6815,6 +7971,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr "將待辦事項標記為已完æˆã€‚"
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
@@ -6839,6 +8004,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr ""
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6849,7 +8017,7 @@ msgid "Maximum time between updates that a mirror can have when scheduled to syn
msgstr ""
msgid "May"
-msgstr ""
+msgstr "五月"
msgid "Median"
msgstr "中ä½æ•¸"
@@ -6869,27 +8037,24 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
-msgid "Merge Request"
+msgid "Merge"
msgstr ""
+msgid "Merge Request"
+msgstr "åˆä½µè«‹æ±‚"
+
msgid "Merge Request Approvals"
msgstr ""
msgid "Merge Requests"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "Merge Requests created"
msgstr ""
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr "åˆä½µäº‹ä»¶ (merge event)"
@@ -6899,14 +8064,8 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "Merge request approvals"
msgstr ""
@@ -6915,7 +8074,7 @@ msgid "Merge request approvals allow you to set the number of necessary approval
msgstr ""
msgid "Merge requests"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
@@ -6923,6 +8082,30 @@ msgstr ""
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6941,6 +8124,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -6953,6 +8139,9 @@ msgstr ""
msgid "MergeRequests|Saving the comment failed"
msgstr ""
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
@@ -6960,7 +8149,7 @@ msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
-msgstr ""
+msgstr "檢視å–代檔案@ %{commitId}"
msgid "MergeRequests|commented on commit %{commitLink}"
msgstr ""
@@ -6986,14 +8175,14 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgstr ""
msgid "MergeRequest|No files found"
msgstr ""
msgid "Merged"
-msgstr ""
+msgstr "å·²åˆä½µ"
msgid "Merged branches are being deleted. This can take some time depending on the number of branches. Please refresh the page to see changes."
msgstr ""
@@ -7001,6 +8190,12 @@ msgstr ""
msgid "Messages"
msgstr ""
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -7016,6 +8211,9 @@ msgstr ""
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -7055,9 +8253,6 @@ msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7103,9 +8298,21 @@ msgstr ""
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr ""
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7113,53 +8320,59 @@ msgid "Migration successful."
msgstr ""
msgid "Milestone"
-msgstr ""
+msgstr "里程碑"
msgid "Milestone lists not available with your current license"
-msgstr ""
+msgstr "ç›®å‰è¨±å¯è­‰ç„¡æ³•ä½¿ç”¨é‡Œç¨‹ç¢‘列表"
msgid "Milestone lists show all issues from the selected milestone."
-msgstr ""
+msgstr "里程碑列表將顯示所é¸é‡Œç¨‹ç¢‘的所有議題"
msgid "Milestones"
-msgstr ""
+msgstr "里程碑"
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
-msgstr ""
+msgstr "ä½ å³å°‡æ°¸ä¹…刪除里程碑 %{milestoneTitle} 並將其中 %{issuesWithCount} å’Œ %{mergeRequestsWithCount}. 一但刪除後,將無法復原或復原。"
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
-msgstr ""
-
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
+msgstr "ä½ å³å°‡æ°¸ä¹…刪除里程碑 %{milestoneTitle}。此里程碑裡目å‰æ²’有任何議題或åˆä½µè«‹æ±‚。"
msgid "Milestones|Delete milestone"
-msgstr ""
+msgstr "刪除里程碑"
msgid "Milestones|Delete milestone %{milestoneTitle}?"
-msgstr ""
+msgstr "刪除里程碑 %{milestoneTitle} ?"
msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
-msgstr ""
+msgstr "刪除里程碑 %{milestoneTitle} 時發生錯誤"
msgid "Milestones|Milestone %{milestoneTitle} was not found"
-msgstr ""
+msgstr "找ä¸åˆ°é‡Œç¨‹ç¢‘ %{milestoneTitle}"
msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
-msgstr ""
+msgstr "å°‡ %{milestoneTitle} æå‡æˆç¾¤çµ„里程碑?"
msgid "Milestones|Promote Milestone"
-msgstr ""
+msgstr "æå‡é‡Œç¨‹ç¢‘"
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
msgstr ""
msgid "Milestones|This action cannot be reversed."
-msgstr ""
+msgstr "這動作無法復原。"
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr ""
@@ -7181,6 +8394,18 @@ msgstr ""
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "添加壹個 SSH 公鑰"
@@ -7197,10 +8422,10 @@ msgid "Modify commit messages"
msgstr ""
msgid "Modify merge commit"
-msgstr ""
+msgstr "修改åˆä½µæ交"
msgid "Monday"
-msgstr ""
+msgstr "星期一"
msgid "Monitor your errors by integrating with Sentry"
msgstr ""
@@ -7209,7 +8434,7 @@ msgid "Monitoring"
msgstr ""
msgid "Months"
-msgstr ""
+msgstr "月"
msgid "More"
msgstr ""
@@ -7239,6 +8464,24 @@ msgid "Move"
msgstr ""
msgid "Move issue"
+msgstr "移動議題"
+
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
msgstr ""
msgid "Multiple issue boards"
@@ -7253,6 +8496,9 @@ msgstr ""
msgid "Name"
msgstr ""
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr ""
@@ -7302,20 +8548,20 @@ msgid "New Environment"
msgstr ""
msgid "New Group"
-msgstr ""
+msgstr "新群組"
msgid "New Identity"
msgstr ""
msgid "New Issue"
msgid_plural "New Issues"
-msgstr[0] "新建議題"
+msgstr[0] "新議題"
msgid "New Label"
msgstr ""
msgid "New Milestone"
-msgstr ""
+msgstr "新建里程碑"
msgid "New Pages Domain"
msgstr ""
@@ -7347,11 +8593,14 @@ msgstr ""
msgid "New epic"
msgstr ""
+msgid "New epic title"
+msgstr ""
+
msgid "New file"
msgstr "新增文件"
msgid "New group"
-msgstr ""
+msgstr "新群組"
msgid "New health check access token has been generated!"
msgstr ""
@@ -7366,16 +8615,19 @@ msgid "New label"
msgstr ""
msgid "New merge request"
-msgstr "新增åˆä½µè«‹æ±‚"
+msgstr "æ–°åˆä½µè«‹æ±‚"
msgid "New milestone"
+msgstr "新建里程碑"
+
+msgid "New password"
msgstr ""
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
msgid "New project"
-msgstr ""
+msgstr "新專案"
msgid "New runners registration token has been generated!"
msgstr ""
@@ -7387,7 +8639,7 @@ msgid "New snippet"
msgstr "新代碼片段"
msgid "New subgroup"
-msgstr ""
+msgstr "æ–°å­ç¾¤çµ„"
msgid "New tag"
msgstr "新增標籤"
@@ -7401,6 +8653,12 @@ msgstr ""
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr ""
@@ -7410,12 +8668,21 @@ msgstr ""
msgid "No Label"
msgstr ""
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr ""
@@ -7431,6 +8698,9 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr ""
@@ -7441,13 +8711,13 @@ msgid "No details available"
msgstr ""
msgid "No due date"
-msgstr ""
+msgstr "沒有截止日期"
msgid "No errors to display."
msgstr ""
msgid "No estimate or time spent"
-msgstr ""
+msgstr "沒有é ä¼°æˆ–花費時間"
msgid "No file chosen"
msgstr ""
@@ -7455,6 +8725,9 @@ msgstr ""
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr ""
@@ -7476,9 +8749,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr ""
@@ -7489,11 +8759,14 @@ msgid "No messages were logged"
msgstr ""
msgid "No milestones to show"
-msgstr ""
+msgstr "沒有è¦é¡¯ç¤ºçš„里程碑"
msgid "No other labels with such name or description"
msgstr ""
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7521,11 +8794,17 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr ""
msgid "None"
-msgstr ""
+msgstr "ç„¡"
msgid "Not available"
msgstr "ä¸å¯ç”¨"
@@ -7537,7 +8816,7 @@ msgid "Not available for protected branches"
msgstr ""
msgid "Not confidential"
-msgstr ""
+msgstr "éžéš±å¯†"
msgid "Not enough data"
msgstr "數據ä¸è¶³"
@@ -7569,6 +8848,9 @@ msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
@@ -7576,12 +8858,18 @@ msgid "Notes|Collapse replies"
msgstr ""
msgid "Notes|Show all activity"
-msgstr ""
+msgstr "顯示所有活動"
msgid "Notes|Show comments only"
-msgstr ""
+msgstr "åªé¡¯ç¤ºç•™è¨€"
msgid "Notes|Show history only"
+msgstr "åªé¡¯ç¤ºæ­·å²ç´€éŒ„"
+
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
msgstr ""
msgid "Notification events"
@@ -7593,6 +8881,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "關閉議題"
@@ -7609,7 +8900,7 @@ msgid "NotificationEvent|New epic"
msgstr ""
msgid "NotificationEvent|New issue"
-msgstr "新增議題"
+msgstr "新議題"
msgid "NotificationEvent|New merge request"
msgstr "æ–°åˆä½µè«‹æ±‚"
@@ -7647,19 +8938,28 @@ msgstr "åƒèˆ‡"
msgid "NotificationLevel|Watch"
msgstr "關注"
-msgid "Notifications"
+msgid "NotificationSetting|Custom"
msgstr ""
+msgid "Notifications"
+msgstr "通知"
+
msgid "Notifications off"
-msgstr ""
+msgstr "關閉通知"
msgid "Notifications on"
-msgstr ""
+msgstr "開啟通知"
msgid "Nov"
-msgstr ""
+msgstr "å一月"
msgid "November"
+msgstr "å一月"
+
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
msgstr ""
msgid "OK"
@@ -7669,15 +8969,21 @@ msgid "Object does not exist on the server or you don't have permissions to acce
msgstr ""
msgid "Oct"
-msgstr ""
+msgstr "å月"
msgid "October"
-msgstr ""
+msgstr "å月"
msgid "OfSearchInADropdown|Filter"
msgstr "篩é¸"
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
@@ -7699,13 +9005,13 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Only admins"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
msgstr ""
-msgid "Only allow merge requests to be merged if all discussions are resolved"
+msgid "Only admins"
msgstr ""
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7723,6 +9029,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr ""
@@ -7745,7 +9054,7 @@ msgid "Open projects"
msgstr ""
msgid "Open raw"
-msgstr ""
+msgstr "打開原文件"
msgid "Open sidebar"
msgstr ""
@@ -7768,6 +9077,12 @@ msgstr "開始於"
msgid "Opens in a new window"
msgstr ""
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr ""
@@ -7792,9 +9107,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr ""
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7816,15 +9128,24 @@ msgstr ""
msgid "Other information"
msgstr ""
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr ""
msgid "Overview"
-msgstr ""
+msgstr "概覽"
msgid "Overwrite diverged branches"
msgstr ""
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr "所有者"
@@ -7852,6 +9173,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr ""
@@ -7873,9 +9197,21 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7888,7 +9224,7 @@ msgstr ""
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
msgid "Path"
@@ -7915,6 +9251,9 @@ msgstr ""
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr ""
@@ -7936,12 +9275,27 @@ msgstr ""
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr "æµæ°´ç·š"
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr "æµæ°´ç·šè¨ˆåŠƒ"
@@ -8020,19 +9374,25 @@ msgstr "æµæ°´ç·š"
msgid "Pipelines charts"
msgstr "æµæ°´ç·šåœ–表"
-msgid "Pipelines for last month"
+msgid "Pipelines emails"
msgstr ""
+msgid "Pipelines for last month"
+msgstr "上個月的æµæ°´ç·š"
+
msgid "Pipelines for last week"
msgstr ""
msgid "Pipelines for last year"
+msgstr "去年的æµæ°´ç·š"
+
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines| to purchase more minutes."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8053,6 +9413,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -8102,7 +9465,7 @@ msgid "Pipeline|Specify variable values to be used in this run. The values speci
msgstr ""
msgid "Pipeline|Stages"
-msgstr ""
+msgstr "階段"
msgid "Pipeline|Status"
msgstr ""
@@ -8113,6 +9476,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr ""
@@ -8143,6 +9509,15 @@ msgstr "於階段"
msgid "Pipeline|with stages"
msgstr "於階段"
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr ""
@@ -8152,12 +9527,30 @@ msgstr ""
msgid "Play"
msgstr ""
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr ""
@@ -8188,6 +9581,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr ""
@@ -8200,6 +9596,15 @@ msgstr ""
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8221,7 +9626,7 @@ msgstr ""
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
@@ -8239,12 +9644,66 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr ""
@@ -8258,6 +9717,9 @@ msgid "Prevent approval of merge requests by merge request committers"
msgstr ""
msgid "Preview"
+msgstr "é è¦½"
+
+msgid "Preview Markdown"
msgstr ""
msgid "Preview changes"
@@ -8266,6 +9728,9 @@ msgstr ""
msgid "Preview payload"
msgstr ""
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -8293,13 +9758,22 @@ msgstr ""
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
-msgid "Profile"
+msgid "Proceed"
msgstr ""
+msgid "Profile"
+msgstr "個人資料"
+
msgid "Profile Settings"
+msgstr "個人資料設定"
+
+msgid "ProfileSession|on"
msgstr ""
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
@@ -8332,6 +9806,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -8353,6 +9830,9 @@ msgstr ""
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8365,6 +9845,9 @@ msgstr ""
msgid "Profiles|Current status"
msgstr ""
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -8392,6 +9875,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8401,9 +9896,15 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -8413,18 +9914,33 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
msgid "Profiles|Position and size your new avatar"
msgstr ""
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr ""
@@ -8443,9 +9959,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
@@ -8461,13 +9974,16 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
msgstr ""
msgid "Profiles|Update profile settings"
@@ -8482,6 +9998,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -8503,6 +10022,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
@@ -8596,6 +10118,9 @@ msgstr ""
msgid "Project avatar"
msgstr ""
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8641,6 +10166,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "訂閱"
@@ -8692,6 +10220,24 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr ""
@@ -8701,18 +10247,60 @@ msgstr ""
msgid "ProjectSettings|Customize your project badges."
msgstr ""
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr ""
msgid "ProjectSettings|Failed to update tag!"
msgstr ""
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr ""
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr ""
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr ""
@@ -8722,10 +10310,70 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
+msgstr "專案"
+
+msgid "Projects (%{count})"
msgstr ""
msgid "Projects Successfully Retrieved"
@@ -8876,14 +10524,23 @@ msgid "Promote"
msgstr ""
msgid "Promote these project milestones into a group milestone."
-msgstr ""
+msgstr "將這些專案里程碑æå‡æˆç¾¤çµ„里程碑。"
msgid "Promote to Group Milestone"
-msgstr ""
+msgstr "æå‡è‡³ç¾¤çµ„里程碑"
msgid "Promote to group label"
msgstr ""
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -8902,16 +10559,22 @@ msgstr ""
msgid "Protected"
msgstr ""
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr ""
-msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgid "Protected Tag"
msgstr ""
-msgid "ProtectedEnvironment|Allowed to deploy"
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
@@ -8920,18 +10583,24 @@ msgstr ""
msgid "ProtectedEnvironment|Protect"
msgstr ""
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr ""
@@ -8980,9 +10649,15 @@ msgstr ""
msgid "Push"
msgstr ""
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr ""
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9007,12 +10682,54 @@ msgstr ""
msgid "Pushes"
msgstr ""
-msgid "Quarters"
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
msgstr ""
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
+msgid "Quarters"
+msgstr "季度"
+
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr ""
@@ -9037,20 +10754,29 @@ msgstr ""
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr ""
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr ""
msgid "Reference:"
-msgstr ""
+msgstr "åƒè€ƒä¾†æºï¼š"
msgid "Refresh"
msgstr ""
@@ -9059,24 +10785,45 @@ msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr ""
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr ""
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
msgid "Register and see your runners for this project."
msgstr ""
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9090,7 +10837,7 @@ msgid "Related Deployed Jobs"
msgstr "相關的部署作業"
msgid "Related Issues"
-msgstr "相關的議題"
+msgstr "相關議題"
msgid "Related Jobs"
msgstr "相關的作業"
@@ -9101,6 +10848,9 @@ msgstr "相關的åˆä½µè«‹æ±‚"
msgid "Related Merged Requests"
msgstr "相關已åˆä½µçš„åˆä½µè«‹æ±‚"
+msgid "Related issues"
+msgstr "相關議題"
+
msgid "Related merge requests"
msgstr ""
@@ -9113,6 +10863,9 @@ msgstr ""
msgid "Remind later"
msgstr "ç¨å¾Œæ醒"
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr ""
@@ -9122,7 +10875,10 @@ msgstr ""
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr "移除全部或特定指派人"
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9131,25 +10887,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr "移除指派人"
+
msgid "Remove avatar"
msgstr ""
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr "刪除截止日期"
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr ""
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr "刪除項目"
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9164,6 +10932,24 @@ msgstr ""
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr "刪除截止日期"
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
@@ -9186,12 +10972,15 @@ msgid "Reopen epic"
msgstr ""
msgid "Reopen milestone"
-msgstr ""
+msgstr "é‡æ–°é–‹å•Ÿé‡Œç¨‹ç¢‘"
msgid "Repair authentication"
msgstr ""
msgid "Replace"
+msgstr "å–代"
+
+msgid "Replace all label(s)"
msgstr ""
msgid "Reply to comment"
@@ -9203,7 +10992,7 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
-msgid "Report abuse to GitLab"
+msgid "Report abuse to admin"
msgstr ""
msgid "Reporting"
@@ -9218,6 +11007,9 @@ msgstr ""
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr ""
@@ -9257,12 +11049,6 @@ msgstr ""
msgid "Reports|Vulnerability"
msgstr ""
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr ""
@@ -9317,13 +11103,22 @@ msgstr ""
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
-msgstr[0] ""
+msgstr[0] "從 %{names} éœ€è¦ %{count} 批准。"
msgid "Requires approval."
msgid_plural "Requires %d more approvals."
-msgstr[0] ""
+msgstr[0] "éœ€è¦ %d 個批准。"
+
+msgid "Resend confirmation email"
+msgstr ""
msgid "Resend invite"
msgstr ""
@@ -9364,6 +11159,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9406,6 +11210,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr ""
@@ -9443,6 +11250,12 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
msgstr ""
@@ -9527,6 +11340,9 @@ msgstr ""
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr ""
@@ -9536,6 +11352,9 @@ msgstr ""
msgid "SSH host keys"
msgstr ""
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr ""
@@ -9543,7 +11362,7 @@ msgid "SSL Verification"
msgstr ""
msgid "Saturday"
-msgstr ""
+msgstr "星期六"
msgid "Save"
msgstr ""
@@ -9551,6 +11370,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr ""
@@ -9563,6 +11385,9 @@ msgstr ""
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "ä¿å­˜æµæ°´ç·šè¨ˆåŠƒ"
@@ -9623,9 +11448,21 @@ msgstr "æœç´¢åˆ†æ”¯å’Œæ¨™ç±¤"
msgid "Search files"
msgstr ""
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr ""
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9633,7 +11470,7 @@ msgid "Search merge requests"
msgstr ""
msgid "Search milestones"
-msgstr ""
+msgstr "æœå°‹é‡Œç¨‹ç¢‘"
msgid "Search or filter results..."
msgstr ""
@@ -9647,6 +11484,9 @@ msgstr ""
msgid "Search projects"
msgstr ""
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -9722,9 +11562,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr ""
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr ""
@@ -9755,12 +11592,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr ""
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9773,6 +11622,12 @@ msgstr ""
msgid "Select Archive Format"
msgstr "é¸æ“‡ä¸‹è¼‰æ ¼å¼"
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr ""
@@ -9798,6 +11653,9 @@ msgid "Select an existing Kubernetes cluster or create a new one"
msgstr ""
msgid "Select branch/tag"
+msgstr "é¸æ“‡åˆ†æ”¯/標籤"
+
+msgid "Select group or project"
msgstr ""
msgid "Select members to invite"
@@ -9816,7 +11674,7 @@ msgid "Select projects you want to import."
msgstr ""
msgid "Select source branch"
-msgstr ""
+msgstr "é¸æ“‡ä¾†æºåˆ†æ”¯"
msgid "Select target branch"
msgstr "é¸æ“‡ç›®æ¨™åˆ†æ”¯"
@@ -9836,6 +11694,9 @@ msgstr ""
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr ""
@@ -9849,13 +11710,13 @@ msgid "Sentry API URL"
msgstr ""
msgid "Sep"
-msgstr ""
+msgstr "ä¹æœˆ"
msgid "Separate topics with commas."
msgstr ""
msgid "September"
-msgstr ""
+msgstr "ä¹æœˆ"
msgid "Server supports batch API only, please update your Git LFS client to version 1.0.1 and up."
msgstr ""
@@ -9917,6 +11778,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr ""
@@ -9947,19 +11811,22 @@ msgstr ""
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""
-msgid "Set new password"
+msgid "Set milestone"
msgstr ""
-msgid "Set notification email for abuse reports."
+msgid "Set new password"
msgstr ""
-msgid "Set number of approvers required before open merge requests can be merged"
+msgid "Set notification email for abuse reports."
msgstr ""
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
@@ -9977,6 +11844,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr ""
@@ -9998,6 +11868,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr "設置密碼"
@@ -10008,7 +11881,7 @@ msgid "SetStatusModal|Clear status"
msgstr ""
msgid "SetStatusModal|Edit status"
-msgstr ""
+msgstr "編輯狀態"
msgid "SetStatusModal|Remove status"
msgstr ""
@@ -10025,6 +11898,18 @@ msgstr ""
msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -10040,6 +11925,9 @@ msgstr ""
msgid "Shared projects"
msgstr ""
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -10052,14 +11940,23 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
+msgstr "顯示所有活動"
+
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
msgstr ""
msgid "Show command"
msgstr ""
msgid "Show comments only"
-msgstr ""
+msgstr "åªé¡¯ç¤ºç•™è¨€"
msgid "Show complete raw log"
msgstr ""
@@ -10070,9 +11967,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -10093,13 +11987,13 @@ msgid "Sidebar|Change weight"
msgstr ""
msgid "Sidebar|None"
-msgstr ""
+msgstr "ç„¡"
msgid "Sidebar|Only numeral characters allowed"
msgstr ""
msgid "Sidebar|Weight"
-msgstr ""
+msgstr "權é‡"
msgid "Sign in"
msgstr ""
@@ -10123,6 +12017,12 @@ msgid "Sign in with smart card"
msgstr ""
msgid "Sign out"
+msgstr "登出"
+
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
msgstr ""
msgid "Sign-in restrictions"
@@ -10131,6 +12031,18 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10138,6 +12050,9 @@ msgid "Signing in using your %{label} account without a pre-existing GitLab acco
msgstr ""
msgid "Similar issues"
+msgstr "相似議題"
+
+msgid "Single or combined queries"
msgstr ""
msgid "Size"
@@ -10149,6 +12064,9 @@ msgstr ""
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr ""
@@ -10168,7 +12086,7 @@ msgid "Snippet Contents"
msgstr ""
msgid "Snippets"
-msgstr ""
+msgstr "程å¼ç¢¼ç‰‡æ®µ"
msgid "SnippetsEmptyState|Explore public snippets"
msgstr ""
@@ -10218,6 +12136,9 @@ msgstr ""
msgid "Something went wrong when toggling the button"
msgstr ""
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10236,6 +12157,9 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10260,7 +12184,7 @@ msgstr ""
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get operations projects"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to remove project"
@@ -10272,6 +12196,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr ""
@@ -10297,7 +12224,7 @@ msgid "SortOptions|Created date"
msgstr ""
msgid "SortOptions|Due date"
-msgstr ""
+msgstr "截止日期"
msgid "SortOptions|Due later"
msgstr ""
@@ -10324,7 +12251,7 @@ msgid "SortOptions|Last joined"
msgstr ""
msgid "SortOptions|Last updated"
-msgstr ""
+msgstr "最後更新"
msgid "SortOptions|Least popular"
msgstr ""
@@ -10332,14 +12259,17 @@ msgstr ""
msgid "SortOptions|Less weight"
msgstr ""
-msgid "SortOptions|Milestone due date"
+msgid "SortOptions|Manual"
msgstr ""
+msgid "SortOptions|Milestone due date"
+msgstr "里程碑截止日期"
+
msgid "SortOptions|Milestone due later"
msgstr ""
msgid "SortOptions|Milestone due soon"
-msgstr ""
+msgstr "å³å°‡æˆªæ­¢çš„里程碑"
msgid "SortOptions|More weight"
msgstr ""
@@ -10386,6 +12316,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr ""
@@ -10396,7 +12332,7 @@ msgid "SortOptions|Start soon"
msgstr ""
msgid "SortOptions|Weight"
-msgstr ""
+msgstr "權é‡"
msgid "Source"
msgstr ""
@@ -10458,6 +12394,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr "星標"
@@ -10482,6 +12421,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10489,7 +12431,7 @@ msgid "Start a %{new_merge_request} with these changes"
msgstr "由此更改 %{new_merge_request}"
msgid "Start a new merge request"
-msgstr ""
+msgstr "開始一個新的åˆä½µè«‹æ±‚"
msgid "Start a review"
msgstr ""
@@ -10512,6 +12454,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "é‹ä½œ Runner!"
@@ -10572,17 +12520,23 @@ msgstr ""
msgid "Storage:"
msgstr ""
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr ""
msgid "Subgroups and projects"
msgstr ""
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
msgid "Submit feedback"
-msgstr ""
+msgstr "æ交æ„見"
msgid "Submit review"
msgstr ""
@@ -10608,6 +12562,9 @@ msgstr ""
msgid "Subscribed"
msgstr ""
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10680,6 +12637,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10704,9 +12664,72 @@ msgstr ""
msgid "Suggested change"
msgstr ""
-msgid "Sunday"
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
msgstr ""
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
+msgid "Sunday"
+msgstr "星期日"
+
msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
@@ -10716,6 +12739,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr "切æ›åˆ†æ”¯/標籤"
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -10746,18 +12775,30 @@ msgstr ""
msgid "System metrics (Kubernetes)"
msgstr ""
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr "標籤"
msgid "Tags feed"
msgstr ""
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr ""
@@ -10834,11 +12875,14 @@ msgid "Target Branch"
msgstr "目標分支"
msgid "Target branch"
-msgstr ""
+msgstr "目標分支"
msgid "Team"
msgstr "團隊"
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr ""
@@ -10851,6 +12895,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -10866,6 +12913,33 @@ msgstr ""
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10903,6 +12977,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10918,6 +12995,9 @@ msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr ""
@@ -10975,6 +13055,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "議題階段概述了從創建議題到將議題添加到è£ç¨‹ç¢‘或議題看æ¿æ‰€èŠ±è²»çš„時間。創建第壹個議題後,數據將自動添加到此處.。"
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -10993,6 +13082,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -11017,9 +13112,21 @@ msgstr "生產階段概述了從創建議題到將代碼部署到生產環境的
msgid "The project can be accessed by any logged in user."
msgstr "該項目å…許已登錄的用戶訪å•ã€‚"
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr "該項目å…許任何人訪å•ã€‚"
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11029,6 +13136,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr ""
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11038,6 +13148,9 @@ msgstr "此項目的存儲庫ä¸å­˜åœ¨ã€‚"
msgid "The repository for this project is empty"
msgstr ""
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
@@ -11077,6 +13190,9 @@ msgstr "測試階段概述了 GitLab CI 為相關åˆä½µè«‹æ±‚é‹è¡Œæ¯å€‹æµæ°´ç
msgid "The time taken by each data entry gathered by that stage."
msgstr "該階段æ¯æ¢æ•¸æ“šæ‰€èŠ±çš„時間"
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -11098,26 +13214,41 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "中ä½æ•¸æ˜¯å£¹å€‹æ•¸åˆ—中最中間的值。例如在 3ã€5ã€9 之間,中ä½æ•¸æ˜¯ 5。在 3ã€5ã€7ã€8 之間,中ä½æ•¸æ˜¯ (5 + 7)/ 2 = 6。"
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr ""
-msgid "There are no closed issues"
+msgid "There are no charts configured for this page"
msgstr ""
+msgid "There are no closed issues"
+msgstr "沒有已關閉的議題"
+
msgid "There are no closed merge requests"
-msgstr ""
+msgstr "沒有已關閉的åˆä½µè«‹æ±‚"
msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
msgstr ""
msgid "There are no issues to show"
-msgstr ""
+msgstr "沒有å¯ä»¥é¡¯ç¤ºçš„è­°é¡Œ"
msgid "There are no labels yet"
msgstr ""
@@ -11140,11 +13271,26 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
+msgstr "增新待辦事項時出錯。"
+
+msgid "There was an error creating the issue"
msgstr ""
msgid "There was an error deleting the todo."
-msgstr ""
+msgstr "刪除待辦事項時出錯。"
msgid "There was an error fetching configuration for charts"
msgstr ""
@@ -11158,6 +13304,12 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11176,6 +13328,9 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11188,6 +13343,9 @@ msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11200,18 +13358,30 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11236,6 +13406,12 @@ msgstr ""
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr ""
@@ -11248,6 +13424,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11257,26 +13436,35 @@ msgstr ""
msgid "This group does not provide any group Runners yet."
msgstr ""
-msgid "This is a confidential issue."
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
msgstr ""
+msgid "This is a confidential issue."
+msgstr "這是個隱密議題。"
+
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
-msgid "This issue is confidential"
+msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential and locked."
-msgstr ""
+msgid "This issue is confidential"
+msgstr "這個議題是隱密的"
msgid "This issue is locked."
-msgstr ""
+msgstr "這個議題已被鎖定。"
msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
msgstr ""
@@ -11344,12 +13532,6 @@ msgstr "在創建壹個空的存儲庫或導入ç¾æœ‰å­˜å„²åº«ä¹‹å‰ï¼Œæ‚¨å°‡ç„¡
msgid "This merge request is locked."
msgstr ""
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11372,7 +13554,7 @@ msgid "This pipeline makes use of a predefined CI/CD configuration enabled by <b
msgstr ""
msgid "This project"
-msgstr ""
+msgstr "這個專案"
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
@@ -11422,6 +13604,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr "議題被列入日程表的時間"
@@ -11447,19 +13635,19 @@ msgid "Time spent"
msgstr ""
msgid "Time tracking"
-msgstr ""
+msgstr "時間追蹤"
msgid "Time until first merge request"
msgstr "創建第壹個åˆä½µè«‹æ±‚之å‰çš„時間"
msgid "TimeTrackingEstimated|Est"
-msgstr ""
+msgstr "é ä¼°"
msgid "TimeTracking|Estimated:"
-msgstr ""
+msgstr "é ä¼°ï¼š"
msgid "TimeTracking|Spent"
-msgstr ""
+msgstr "已花費:"
msgid "Timeago|%s days ago"
msgstr " %s 天å‰"
@@ -11501,7 +13689,7 @@ msgid "Timeago|%s years remaining"
msgstr "剩餘 %s 年"
msgid "Timeago|1 day ago"
-msgstr ""
+msgstr "1 天å‰"
msgid "Timeago|1 day remaining"
msgstr "剩餘 1 天"
@@ -11519,7 +13707,7 @@ msgid "Timeago|1 minute remaining"
msgstr "剩餘 1 分é˜"
msgid "Timeago|1 month ago"
-msgstr ""
+msgstr "1 個月å‰"
msgid "Timeago|1 month remaining"
msgstr "剩餘 1 個月"
@@ -11531,7 +13719,7 @@ msgid "Timeago|1 week remaining"
msgstr "剩餘 1 星期"
msgid "Timeago|1 year ago"
-msgstr ""
+msgstr "1 å¹´å‰"
msgid "Timeago|1 year remaining"
msgstr "剩餘 1 年"
@@ -11570,7 +13758,7 @@ msgid "Timeago|in 1 minute"
msgstr " 1 分é˜å¾Œ"
msgid "Timeago|in 1 month"
-msgstr " 1 月後"
+msgstr " 1 個月後"
msgid "Timeago|in 1 week"
msgstr " 1 星期後"
@@ -11604,6 +13792,9 @@ msgstr ""
msgid "Title"
msgstr ""
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11619,6 +13810,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr ""
@@ -11685,6 +13879,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
@@ -11707,20 +13904,23 @@ msgid "To widen your search, change or remove filters."
msgstr ""
msgid "Today"
-msgstr ""
+msgstr "今天"
msgid "Todo"
-msgstr ""
+msgstr "待辦事項"
msgid "Todo was successfully marked as done."
-msgstr ""
+msgstr "待辦事項已æˆåŠŸåœ°æ¨™è¨˜ç‚ºå·²å®Œæˆã€‚"
msgid "Todos"
-msgstr ""
+msgstr "待辦事項"
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11733,9 +13933,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr ""
@@ -11745,6 +13951,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr ""
@@ -11787,9 +13996,45 @@ msgstr ""
msgid "Transfer project"
msgstr ""
-msgid "Tree view"
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
msgstr ""
+msgid "Tree"
+msgstr ""
+
+msgid "Tree view"
+msgstr "樹狀顯示"
+
msgid "Trending"
msgstr ""
@@ -11838,15 +14083,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr ""
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11856,24 +14116,42 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr ""
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11892,18 +14170,33 @@ msgstr ""
msgid "Unknown"
msgstr ""
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr ""
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
msgstr ""
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr ""
@@ -11944,7 +14237,7 @@ msgid "Unsubscribe from %{type}"
msgstr ""
msgid "Unverified"
-msgstr ""
+msgstr "未驗證"
msgid "Up to date"
msgstr ""
@@ -11973,6 +14266,18 @@ msgstr ""
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12024,6 +14329,9 @@ msgstr ""
msgid "Upload file"
msgstr "上傳文件"
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12033,6 +14341,9 @@ msgstr "點擊上傳"
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12051,6 +14362,54 @@ msgstr ""
msgid "Usage statistics"
msgstr ""
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12060,6 +14419,12 @@ msgstr ""
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr ""
@@ -12117,6 +14482,9 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12132,14 +14500,149 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
-msgid "UserProfile|Activity"
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
msgstr ""
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr "活動"
+
msgid "UserProfile|Already reported for abuse"
msgstr ""
msgid "UserProfile|Contributed projects"
-msgstr ""
+msgstr "è²¢ç»çš„專案"
msgid "UserProfile|Edit profile"
msgstr ""
@@ -12148,7 +14651,7 @@ msgid "UserProfile|Explore public groups to find projects to contribute to."
msgstr ""
msgid "UserProfile|Groups"
-msgstr ""
+msgstr "群組"
msgid "UserProfile|Groups are the best way to manage projects and members."
msgstr ""
@@ -12163,16 +14666,16 @@ msgid "UserProfile|No snippets found."
msgstr ""
msgid "UserProfile|Overview"
-msgstr ""
+msgstr "概覽"
msgid "UserProfile|Personal projects"
-msgstr ""
+msgstr "個人專案"
msgid "UserProfile|Report abuse"
msgstr ""
msgid "UserProfile|Snippets"
-msgstr ""
+msgstr "程å¼ç¢¼ç‰‡æ®µ"
msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
msgstr ""
@@ -12207,6 +14710,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr ""
@@ -12222,9 +14734,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12262,7 +14792,7 @@ msgid "Verification status"
msgstr ""
msgid "Verified"
-msgstr ""
+msgstr "已驗證"
msgid "Version"
msgstr ""
@@ -12270,12 +14800,18 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12285,15 +14821,21 @@ msgstr ""
msgid "View file @ "
msgstr ""
-msgid "View group labels"
+msgid "View full dashboard"
msgstr ""
+msgid "View group labels"
+msgstr "查看群組標籤"
+
msgid "View in Sentry"
msgstr ""
msgid "View it on GitLab"
msgstr ""
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12301,7 +14843,7 @@ msgid "View jobs"
msgstr ""
msgid "View labels"
-msgstr ""
+msgstr "顯示標籤"
msgid "View log"
msgstr ""
@@ -12310,10 +14852,10 @@ msgid "View open merge request"
msgstr "查看開啟的åˆä¸¦è«‹æ±‚"
msgid "View project labels"
-msgstr ""
+msgstr "查看專案標籤"
msgid "View replaced file @ "
-msgstr ""
+msgstr "檢視已å–代檔案 @ "
msgid "View the documentation"
msgstr ""
@@ -12321,6 +14863,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
@@ -12348,6 +14893,33 @@ msgstr "公開"
msgid "VisibilityLevel|Unknown"
msgstr "未知"
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12390,6 +14962,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "權é™ä¸è¶³ã€‚如需查看相關數據,請å‘管ç†å“¡ç”³è«‹æ¬Šé™ã€‚"
@@ -12408,6 +14983,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr ""
@@ -12417,11 +14995,14 @@ msgstr "該階段的數據ä¸è¶³ï¼Œç„¡æ³•é¡¯ç¤ºã€‚"
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
msgid "Web IDE"
-msgstr ""
+msgstr "ç¶²é  IDE"
msgid "Web Terminal"
msgstr ""
@@ -12438,22 +15019,28 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
-msgid "Weeks"
+msgid "Wednesday"
msgstr ""
+msgid "Weeks"
+msgstr "星期"
+
msgid "Weight"
-msgstr ""
+msgstr "權é‡"
msgid "Weight %{weight}"
+msgstr "æ¬Šé‡ %{weight}"
+
+msgid "Welcome to the Guided GitLab Tour"
msgstr ""
-msgid "When a runner is locked, it cannot be assigned to other projects"
+msgid "Welcome to your Issue Board!"
msgstr ""
-msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
@@ -12466,6 +15053,9 @@ msgstr[0] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr ""
@@ -12629,10 +15219,10 @@ msgid "Workflow Help"
msgstr ""
msgid "Write"
-msgstr ""
+msgstr "寫"
msgid "Write a comment or drag your files here…"
-msgstr ""
+msgstr "寫評論或拖動你的文件到這裡"
msgid "Write access allowed"
msgstr ""
@@ -12646,6 +15236,9 @@ msgstr ""
msgid "Yes"
msgstr ""
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr ""
@@ -12653,7 +15246,7 @@ msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
msgid "Yesterday"
-msgstr ""
+msgstr "昨天"
msgid "You"
msgstr ""
@@ -12661,8 +15254,14 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "å³å°‡åˆªé™¤ %{group_name}。已刪除的群組無法æ¢å¾©ï¼ç¢ºå®šç¹¼çºŒå—Žï¼Ÿ"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
@@ -12673,6 +15272,9 @@ msgstr "å³å°‡åˆªé™¤èˆ‡æºé …ç›® %{forked_from_project} 的派生關系。確定
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12688,6 +15290,12 @@ msgstr ""
msgid "You can also create a project from the command line."
msgstr ""
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr ""
@@ -12706,6 +15314,15 @@ msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr ""
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -12730,9 +15347,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
@@ -12763,12 +15386,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
@@ -12778,6 +15410,12 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12808,6 +15446,15 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -12820,6 +15467,9 @@ msgstr ""
msgid "You need permission."
msgstr "需è¦ç›¸é—œçš„權é™ã€‚"
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12832,6 +15482,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12865,6 +15518,9 @@ msgstr "在賬號中 %{add_ssh_key_link} 之å‰å°‡ç„¡æ³•é€šéŽ SSH 拉å–或推é
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr ""
@@ -12884,27 +15540,51 @@ msgid "You're receiving this email because of your account on %{host}."
msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr "你收到此電å­éƒµä»¶æ˜¯å› ç‚ºä½ çš„帳戶在 %{host}. %{manage_notifications_link} &middot; %{help_link}"
+
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
msgstr ""
msgid "YouTube"
msgstr ""
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr ""
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr ""
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr ""
msgid "Your Projects' Activity"
msgstr ""
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
+msgstr "您的待辦事項"
+
+msgid "Your U2F device did not send a valid JSON response."
msgstr ""
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
@@ -12940,7 +15620,10 @@ msgstr ""
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
@@ -12958,6 +15641,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr "您的åå­—"
@@ -12991,24 +15677,42 @@ msgstr ""
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
+msgid "already being used for another group or project milestone."
msgstr ""
-msgid "at"
+msgid "already shared with this group"
+msgstr ""
+
+msgid "among other things"
msgstr ""
msgid "attach a new file"
msgstr ""
msgid "authored"
-msgstr ""
+msgstr "編輯於"
msgid "branch name"
-msgstr ""
+msgstr "分支å稱"
msgid "by"
msgstr ""
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -13096,6 +15800,9 @@ msgstr ""
msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13129,9 +15836,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr ""
@@ -13147,12 +15851,6 @@ msgstr ""
msgid "ciReport|Description"
msgstr ""
-msgid "ciReport|Dismiss vulnerability"
-msgstr ""
-
-msgid "ciReport|Dismissed by"
-msgstr ""
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13219,7 +15917,7 @@ msgid "ciReport|Namespace"
msgstr ""
msgid "ciReport|No changes to code quality"
-msgstr ""
+msgstr "程å¼ç¢¼å“質沒有變更"
msgid "ciReport|No changes to performance metrics"
msgstr ""
@@ -13269,9 +15967,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -13288,10 +15983,10 @@ msgstr[0] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|on pipeline"
+msgid "commented on %{link_to_project}"
msgstr ""
-msgid "commented on %{link_to_project}"
+msgid "commit %{commit_id}"
msgstr ""
msgid "confidence|Confirmed"
@@ -13333,6 +16028,9 @@ msgstr ""
msgid "customize"
msgstr ""
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] "天"
@@ -13360,9 +16058,15 @@ msgid "draft"
msgid_plural "drafts"
msgstr[0] ""
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr ""
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
msgid "epic"
msgstr ""
@@ -13375,6 +16079,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13391,7 +16101,7 @@ msgid "for %{ref}"
msgstr ""
msgid "for this project"
-msgstr ""
+msgstr "為此專案"
msgid "from"
msgstr ""
@@ -13399,6 +16109,9 @@ msgstr ""
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -13427,6 +16140,12 @@ msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr ""
@@ -13436,6 +16155,9 @@ msgstr ""
msgid "is not a valid X509 certificate."
msgstr ""
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13454,6 +16176,9 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
@@ -13479,6 +16204,9 @@ msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13506,7 +16234,7 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|Add approval"
+msgid "mrWidget|Added to the merge train by"
msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
@@ -13521,6 +16249,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr ""
@@ -13546,10 +16277,10 @@ msgid "mrWidget|Cherry-pick this merge request in a new merge request"
msgstr ""
msgid "mrWidget|Closed"
-msgstr ""
+msgstr "關閉"
msgid "mrWidget|Closed by"
-msgstr ""
+msgstr "關閉"
msgid "mrWidget|Closes"
msgstr ""
@@ -13575,6 +16306,9 @@ msgstr ""
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr ""
@@ -13585,7 +16319,7 @@ msgid "mrWidget|Loading deployment statistics"
msgstr ""
msgid "mrWidget|Mentions"
-msgstr ""
+msgstr "æ到"
msgid "mrWidget|Merge"
msgstr ""
@@ -13593,18 +16327,15 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge locally"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
msgstr ""
-msgid "mrWidget|Merge request approved"
+msgid "mrWidget|Merge locally"
msgstr ""
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
-
msgid "mrWidget|Merged by"
msgstr ""
@@ -13615,7 +16346,7 @@ msgid "mrWidget|No approval required; you can still approve"
msgstr ""
msgid "mrWidget|Open in Web IDE"
-msgstr ""
+msgstr "åœ¨ç¶²é  IDE 中開啟"
msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
msgstr ""
@@ -13635,19 +16366,11 @@ msgstr ""
msgid "mrWidget|Refreshing now"
msgstr ""
-msgid "mrWidget|Remove your approval"
+msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
-msgstr ""
-
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
+msgstr "請求åˆä½µ"
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -13731,20 +16454,35 @@ msgid "mrWidget|command line"
msgstr ""
msgid "mrWidget|into"
+msgstr "進入"
+
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr ""
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
-msgstr "新建åˆä½µè«‹æ±‚"
+msgstr "æ–°åˆä½µè«‹æ±‚"
-msgid "none"
+msgid "no contributions"
msgstr ""
+msgid "none"
+msgstr "ç„¡"
+
msgid "notification emails"
msgstr "通知郵件"
@@ -13792,7 +16530,7 @@ msgid_plural "projects"
msgstr[0] ""
msgid "quick actions"
-msgstr ""
+msgstr "快速æ“作"
msgid "register"
msgstr ""
@@ -13804,10 +16542,10 @@ msgid "remove"
msgstr ""
msgid "remove due date"
-msgstr ""
+msgstr "刪除截止日期"
msgid "remove weight"
-msgstr ""
+msgstr "移除權é‡"
msgid "rendered diff"
msgstr ""
@@ -13846,7 +16584,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13855,18 +16593,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr ""
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr ""
msgid "started"
msgstr ""
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13900,12 +16650,33 @@ msgstr ""
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr ""
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index 1522f1c96ad..784d722e453 100644
--- a/locale/zh_TW/gitlab.po
+++ b/locale/zh_TW/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <community@gitlab.com>\n"
+"Last-Translator: GitLab (gitlab)\n"
"Language-Team: Chinese Traditional\n"
"Language: zh_TW\n"
"MIME-Version: 1.0\n"
@@ -13,14 +13,11 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: zh-TW\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2019-04-12 12:36\n"
+"PO-Revision-Date: 2019-06-14 10:23\n"
msgid " Please sign in."
msgstr ""
-msgid " Status"
-msgstr " 狀態"
-
msgid " Try to %{action} this file again."
msgstr ""
@@ -42,7 +39,7 @@ msgid " or "
msgstr ""
msgid " or <#epic id>"
-msgstr ""
+msgstr " 或 <#å²è©© id>"
msgid " or <#issue id>"
msgstr ""
@@ -62,6 +59,10 @@ msgstr[0] "è½å¾Œäº† %d 則æ交"
msgid "%d commits"
msgstr ""
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d 個匯出工具"
@@ -90,10 +91,18 @@ msgid "%d merge request"
msgid_plural "%d merge requests"
msgstr[0] "%d 個åˆä½µè«‹æ±‚"
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d 個指標"
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+
msgid "%d staged change"
msgid_plural "%d staged changes"
msgstr[0] "%d 個暫存變更"
@@ -115,11 +124,8 @@ msgstr "%{authorsName} 建立的討論"
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} 已在 %{commit_timeago} é€äº¤"
-msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
-msgstr "%{counter_storage}ï¼ˆå…§å« %{counter_repositories} 個版本庫ã€%{counter_build_artifacts} 個編譯æˆå“ä»¥åŠ %{counter_lfs_objects} 個 LFS 儲存空間)"
-
-msgid "%{count} %{alerts}"
-msgstr "%{count} 個 %{alerts} æ醒"
+msgid "%{counter_repositories} repositories, %{counter_wikis} wikis, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS"
+msgstr ""
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
@@ -132,7 +138,7 @@ msgid "%{count} more"
msgstr ""
msgid "%{count} more assignees"
-msgstr "%{count} å以上的被指派者"
+msgstr "%{count} å以上的被指派人"
msgid "%{count} of %{required} approvals from %{name}"
msgstr ""
@@ -148,6 +154,12 @@ msgid "%{count} pending comment"
msgid_plural "%{count} pending comments"
msgstr[0] "%{count} 則待檢閱留言"
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
msgid "%{filePath} deleted"
msgstr "已刪除 %{filePath} 檔案"
@@ -160,12 +172,24 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}群組%{group_docs_link_end} 讓您能跨管ç†ä»¥åŠå”作多個專案。群組的æˆå“¡å¯ä»¥å­˜å–群組之下的所有專案。"
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "將移除 %{issuableType}ï¼ç¢ºå®šï¼Ÿ"
msgid "%{label_for_message} unavailable"
msgstr ""
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
msgid "%{level_name} visibility has been restricted by the administrator."
msgstr ""
@@ -181,6 +205,12 @@ msgstr "%{lock_path} 被 GitLab 使用者 %{lock_user_id} 鎖定"
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
msgid "%{name}'s avatar"
msgstr "%{name} 的大頭貼"
@@ -199,11 +229,23 @@ msgstr ""
msgid "%{service_title} settings saved, but not activated."
msgstr ""
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
msgid "%{state} epics"
-msgstr ""
+msgstr "%{state} å²è©©"
msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
@@ -227,6 +269,9 @@ msgstr[0] "%{text} %{files} 個檔案"
msgid "%{text} is available"
msgstr "%{text} å¯ä¾›ä½¿ç”¨"
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
msgid "%{title} changes"
msgstr "%{title} 變更"
@@ -239,9 +284,28 @@ msgstr "%{usage_ping_link_start}得知更多%{usage_ping_link_end}會分享給 G
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
+msgid "(check progress)"
+msgstr ""
+
msgid "(external source)"
msgstr ""
@@ -266,6 +330,9 @@ msgstr "-執行器為暫åœç‹€æ…‹ï¼Œå°‡ä¸æŽ¥æ”¶æ–°çš„作業"
msgid "- show less"
msgstr "- 顯示較少內容"
+msgid "0 for unlimited"
+msgstr ""
+
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
msgstr[0] "%{count} 個 %{type} 新增"
@@ -276,34 +343,34 @@ msgstr[0] "%{count} 個 %{type} 變更"
msgid "1 Day"
msgid_plural "%d Days"
-msgstr[0] ""
+msgstr[0] "%d 天"
msgid "1 closed issue"
-msgid_plural "%d closed issues"
-msgstr[0] "%d 個關閉的議題"
+msgid_plural "%{issues} closed issues"
+msgstr[0] ""
msgid "1 closed merge request"
-msgid_plural "%d closed merge requests"
-msgstr[0] "%d 個關閉的åˆä½µè«‹æ±‚"
+msgid_plural "%{merge_requests} closed merge requests"
+msgstr[0] ""
msgid "1 day"
-msgstr ""
+msgstr "1 天"
msgid "1 group"
msgid_plural "%d groups"
msgstr[0] "%d 個群組"
msgid "1 merged merge request"
-msgid_plural "%d merged merge requests"
-msgstr[0] "%d 個已åˆä½µçš„åˆä½µè«‹æ±‚"
+msgid_plural "%{merge_requests} merged merge requests"
+msgstr[0] ""
msgid "1 open issue"
-msgid_plural "%d open issues"
-msgstr[0] "%d 個進行中議題"
+msgid_plural "%{issues} open issues"
+msgstr[0] ""
msgid "1 open merge request"
-msgid_plural "%d open merge requests"
-msgstr[0] "%d 個進行中åˆä½µè«‹æ±‚"
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] ""
msgid "1 pipeline"
msgid_plural "%d pipelines"
@@ -320,24 +387,39 @@ msgstr[0] "%d ä½ä½¿ç”¨è€…"
msgid "1 week"
msgstr ""
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
msgid "1st contribution!"
msgstr "您的第一次貢ç»ï¼"
+msgid "20-29 contributions"
+msgstr ""
+
msgid "2FA"
msgstr ""
msgid "2FA enabled"
msgstr "已啟用兩步驟驗證"
-msgid "3 days"
+msgid "2FADevice|Registered On"
msgstr ""
+msgid "3 days"
+msgstr "3 天"
+
msgid "3 hours"
msgstr ""
msgid "30 minutes"
msgstr ""
+msgid "30+ contributions"
+msgstr ""
+
msgid "403|Please contact your GitLab administrator to get permission."
msgstr ""
@@ -357,7 +439,7 @@ msgid "8 hours"
msgstr ""
msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
-msgstr "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> 將會在所有原本由 johnsmith@example.com 建立的議題和留言中加上「來自 <a href=\"#\">@johnsmith</a>ã€ä¸¦å°‡åŽŸæœ¬åˆ†é…給 johnsmith@example.com 的所有議題設定 <a href=\"#\">@johnsmith</a> 為被指派者。"
+msgstr "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> 將會在所有原本由 johnsmith@example.com 建立的議題和留言中加上「來自 <a href=\"#\">@johnsmith</a>ã€ä¸¦å°‡åŽŸæœ¬åˆ†é…給 johnsmith@example.com 的所有議題設定 <a href=\"#\">@johnsmith</a> 為被指派人。"
msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
msgstr "<code>\"johnsmith@example.com\": \"John Smith\"</code> 將會在所有原本由 johnsmith@example.com 建立的議題和留言中加上「來自 John Smithã€ã€‚"
@@ -368,6 +450,9 @@ msgstr "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> 將會
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> 將會在所有原本由 johnsmith@example.com 建立的議題和留言中加上「來自 <a href=\"#\">johnsmith@example.com</a>ã€ã€‚é è¨­ç‹€æ…‹é›»å­ä¿¡ç®±ä½å€æˆ–使用者å稱將被é®è”½ä»¥ä¿è­·ä½¿ç”¨è€…çš„éš±ç§å®‰å…¨ï¼Œå¦‚果您想è¦é¡¯ç¤ºå®Œæ•´çš„é›»å­ä¿¡ç®±ä½å€ï¼Œè«‹ä½¿ç”¨æ­¤é¸é …。"
+msgid "<no name set>"
+msgstr ""
+
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr "<strong>%{changedFilesLength} 個未暫存</strong>和 <strong>%{stagedFilesLength} 個已暫存</strong>變更"
@@ -404,19 +489,19 @@ msgstr ""
msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
+msgstr ""
+
msgid "A default branch cannot be chosen for an empty project."
msgstr "無法å°ä¸€å€‹ç©ºå°ˆæ¡ˆé¸æ“‡é è¨­åˆ†æ”¯ã€‚"
msgid "A deleted user"
msgstr "已刪除使用者"
-msgid "A member of GitLab's abuse team will review your report as soon as possible."
-msgstr "GitLab 濫用檢閱團隊的æˆå“¡å°‡æœƒç›¡å¿«æª¢é–±ä½ çš„回報。"
-
-msgid "A merge commit is created for every merge, and merging is allowed as long as there are no conflicts."
+msgid "A fork is a copy of a project.<br />Forking a repository allows you to make changes without affecting the original project."
msgstr ""
-msgid "A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible. This way you could make sure that if this merge request would build, after merging to target branch it would also build."
+msgid "A member of the abuse team will review your report as soon as possible."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
@@ -446,6 +531,9 @@ msgstr "一ä½æœ‰ä¾†æºåˆ†æ”¯å¯«å…¥æ¬Šé™çš„使用者é¸æ“‡äº†é€™å€‹é¸é …"
msgid "API Help"
msgstr ""
+msgid "API Token"
+msgstr ""
+
msgid "About GitLab"
msgstr "關於 GitLab"
@@ -453,7 +541,7 @@ msgid "About GitLab CE"
msgstr "關於 GitLab CE"
msgid "About auto deploy"
-msgstr "關於自動部署"
+msgstr "關於自動佈署"
msgid "About this feature"
msgstr "關於此功能"
@@ -480,7 +568,7 @@ msgid "Access denied for your LDAP account."
msgstr ""
msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "å­˜å–被拒ï¼è«‹æª¢æŸ¥æ‚¨æ˜¯å¦å¯ä»¥åœ¨æ­¤ç‰ˆæœ¬åº«éƒ¨å±¬é‡‘鑰。"
+msgstr "å­˜å–被拒ï¼è«‹æª¢æŸ¥æ‚¨æ˜¯å¦å¯ä»¥åœ¨æ­¤ç‰ˆæœ¬åº«ä½ˆç½²é‡‘鑰。"
msgid "Access expiration date"
msgstr "å­˜å–éŽæœŸæ—¥æœŸ"
@@ -491,12 +579,24 @@ msgstr ""
msgid "Access to '%{classification_label}' not allowed"
msgstr "您ä¸å…許存å–「%{classification_label}ã€"
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
msgid "Account"
msgstr "帳號"
msgid "Account and limit"
msgstr "帳號與é™åˆ¶"
+msgid "Account: %{account}"
+msgstr ""
+
msgid "Action to take when receiving an alert."
msgstr ""
@@ -533,6 +633,9 @@ msgstr "新增 Kubernetes å¢é›†"
msgid "Add README"
msgstr ""
+msgid "Add a GPG key"
+msgstr ""
+
msgid "Add a bullet list"
msgstr ""
@@ -554,10 +657,16 @@ msgstr "新增表格"
msgid "Add a task list"
msgstr ""
+msgid "Add a todo"
+msgstr "新增待辦事項"
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "新增顯示於所有電å­éƒµä»¶å°è©±çš„附加文字。最多 %{character_limit} 個字元。"
-msgid "Add approver(s)"
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an issue"
msgstr ""
msgid "Add approvers"
@@ -566,9 +675,15 @@ msgstr ""
msgid "Add bold text"
msgstr ""
+msgid "Add child epic to an epic"
+msgstr ""
+
msgid "Add comment now"
msgstr "ç«‹å³ç•™è¨€"
+msgid "Add email address"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -578,6 +693,9 @@ msgstr "增加圖片留言"
msgid "Add italic text"
msgstr ""
+msgid "Add label(s)"
+msgstr ""
+
msgid "Add license"
msgstr "新增授權資訊"
@@ -590,9 +708,18 @@ msgstr "新增應用程å¼"
msgid "Add new directory"
msgstr "新增資料夾"
+msgid "Add or subtract spent time"
+msgstr ""
+
msgid "Add reaction"
msgstr "新增回應"
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
msgid "Add to project"
msgstr ""
@@ -605,24 +732,36 @@ msgstr "新增待辦事項"
msgid "Add user(s) to the group:"
msgstr "將使用者加到群組:"
-msgid "Add users or groups who are allowed to approve every merge request"
-msgstr ""
-
msgid "Add users to group"
msgstr "將使用者加到群組"
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
+msgstr ""
+
msgid "Added at"
msgstr ""
msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr "您的 GitLab 執行個體已åœç”¨ã€Œæ–°å¢žæ‡‰ç”¨ç¨‹å¼ã€åŠŸèƒ½ã€‚è«‹è¯çµ¡æ‚¨çš„ GitLab 管ç†å“¡å–得新增權é™"
+msgid "Additional minutes"
+msgstr ""
+
msgid "Additional text"
msgstr "附加文字"
-msgid "Aditional minutes"
+msgid "Adds"
msgstr ""
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds a todo."
+msgstr "新增待辦事項。"
+
msgid "Admin Area"
msgstr "管ç†å€å¡Š"
@@ -632,6 +771,9 @@ msgstr "管ç†æ¦‚覽"
msgid "Admin Section"
msgstr ""
+msgid "Admin notes"
+msgstr ""
+
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr "您正打算永久刪除 %{username} 使用者。連çµåˆ°é€™äº›ä½¿ç”¨è€…çš„è­°é¡Œã€åˆä½µè«‹æ±‚與群組將會移轉到系統全域的使用者「Ghost-userã€ã€‚è‹¥è¦é¿å…資料éºå¤±ï¼Œè«‹è€ƒæ…®æ”¹ç”¨%{strong_start}å°éŽ–使用者%{strong_end}功能,因為%{strong_start}刪除使用者%{strong_end} 動作一執行就無法復原。"
@@ -653,6 +795,9 @@ msgstr "åœæ­¢ä½œæ¥­å¤±æ•—"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "您正打算åœæ­¢æ‰€æœ‰ä½œæ¥­ï¼Œé€™å°‡æš«åœæ‰€æœ‰æ­£åœ¨åŸ·è¡Œä¸­çš„作業。"
+msgid "AdminNote|Note"
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr "您正打算永久刪除 %{projectName} 專案與其版本庫ã€å’Œæ‰€æœ‰ç›¸é—œçš„資æºï¼ŒåŒ…å«è­°é¡Œã€åˆä½µè«‹æ±‚等等…當您確èªä¸¦æŒ‰ä¸‹%{strong_start}刪除專案%{strong_end},將無法復原此動作。"
@@ -675,7 +820,7 @@ msgid "AdminSettings|Environment variables are protected by default"
msgstr ""
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
-msgstr "å°æ¯å€‹å°ˆæ¡ˆçš„「自動檢閱應用程å¼ç¨‹å¼ã€å’Œã€Œè‡ªå‹•éƒ¨å±¬éšŽæ®µã€æŒ‡å®šé è¨­ç¶²åŸŸã€‚"
+msgstr "å°æ¯å€‹å°ˆæ¡ˆçš„「自動檢閱應用程å¼ç¨‹å¼ã€å’Œã€Œè‡ªå‹•ä½ˆç½²éšŽæ®µã€æŒ‡å®šé è¨­ç¶²åŸŸã€‚"
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -767,6 +912,9 @@ msgstr "進階設定"
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
msgid "Alert"
msgid_plural "Alerts"
msgstr[0] "通知"
@@ -783,18 +931,27 @@ msgstr ""
msgid "All changes are committed"
msgstr "å·²æ交所有變更"
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "已經å°ç©ºç™½ã€ä¾†è‡ªæ¨¡æ¿ä»¥åŠåŒ¯å…¥çš„專案啟用所有功能,但您ä»ä¹‹å¾Œåœ¨ã€Œå°ˆæ¡ˆè¨­å®šã€åœç”¨ä¸æƒ³è¦çš„功能。"
-msgid "All issues for this milestone are closed. You may close this milestone now."
+msgid "All groups and projects"
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr "此里程碑è£çš„所有議題å‡å·²é—œé–‰ã€‚ä½ ç¾åœ¨å¯ä»¥é—œé–‰æ­¤é‡Œç¨‹ç¢‘。"
+
msgid "All merge conflicts were resolved. The merge request can now be merged."
msgstr ""
-msgid "All todos were marked as done."
+msgid "All projects"
msgstr ""
+msgid "All todos were marked as done."
+msgstr "所有待辦事項都標記為已完æˆã€‚"
+
msgid "All users"
msgstr "所有使用者"
@@ -864,9 +1021,6 @@ msgstr "或者,你能使用 %{personal_access_token_link} 連çµã€‚當你è¦å»
msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr "å…許使用者跳éŽå¼·åˆ¶è¨­å®šå…©æ­¥é©Ÿé©—證的時間(å°æ™‚)"
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr "æ交此表單時將會自動產生 SSH 金鑰。若須更多資訊請åƒè€ƒæª”案。"
-
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr "一個自稱 %{link_to_client} 的應用程å¼è«‹æ±‚您 GitLab 帳號的存å–權。"
@@ -900,12 +1054,15 @@ msgstr "é è¦½ blob 檔案時發生錯誤"
msgid "An error occurred when toggling the notification subscription"
msgstr "切æ›è¨‚閱通知時發生錯誤"
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
msgid "An error occurred when updating the issue weight"
msgstr "更新議題權é‡æ™‚發生錯誤"
-msgid "An error occurred while adding approver"
-msgstr "增加審核者時發生錯誤"
-
msgid "An error occurred while deleting the approvers group"
msgstr ""
@@ -927,21 +1084,36 @@ msgstr "解除çªé¡¯é¡¯ç¤ºæ™‚發生錯誤,請é‡æ–°æ•´ç†é é¢å¾Œå†æ¬¡å˜—試
msgid "An error occurred while enabling Service Desk."
msgstr ""
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
msgid "An error occurred while fetching markdown preview"
msgstr "å–å¾— Markdown é è¦½çµæžœæ™‚發生錯誤"
msgid "An error occurred while fetching pending comments"
msgstr "讀å–待處ç†ç•™è¨€æ™‚發生錯誤"
+msgid "An error occurred while fetching projects autocomplete."
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "讀å–å´é‚Šæ¬„資料時發生錯誤"
-msgid "An error occurred while fetching stages."
-msgstr "抓å–狀態時發生錯誤。"
-
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
msgid "An error occurred while fetching the job log."
msgstr "抓å–工作記錄時發生錯誤。"
@@ -957,6 +1129,9 @@ msgstr "讀å–管線時發生錯誤"
msgid "An error occurred while fetching the releases. Please try again."
msgstr ""
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
msgid "An error occurred while getting projects"
msgstr "å–得專案時發生錯誤"
@@ -990,12 +1165,15 @@ msgstr ""
msgid "An error occurred while making the request."
msgstr "建立請求時發生錯誤"
-msgid "An error occurred while removing approver"
-msgstr "刪除審核者時發生錯誤"
+msgid "An error occurred while moving the issue."
+msgstr ""
-msgid "An error occurred while removing epics."
+msgid "An error occurred while parsing recent searches"
msgstr ""
+msgid "An error occurred while removing epics."
+msgstr "刪除å²è©©æ™‚發生錯誤。"
+
msgid "An error occurred while removing issues."
msgstr ""
@@ -1044,6 +1222,9 @@ msgstr ""
msgid "An error occurred whilst fetching the latest pipeline."
msgstr ""
+msgid "An error occurred whilst getting files for - %{branchId}"
+msgstr ""
+
msgid "An error occurred whilst loading all the files."
msgstr ""
@@ -1101,9 +1282,15 @@ msgstr "任何"
msgid "Any Label"
msgstr "ä»»æ„標籤"
+msgid "Any Milestone"
+msgstr ""
+
msgid "Any encrypted tokens"
msgstr ""
+msgid "Any namespace"
+msgstr ""
+
msgid "Appearance"
msgstr "外觀"
@@ -1113,6 +1300,12 @@ msgstr ""
msgid "Appearance was successfully updated."
msgstr ""
+msgid "Append the comment with %{TABLEFLIP}"
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
msgid "Application"
msgstr "應用程å¼"
@@ -1122,6 +1315,9 @@ msgstr "æ‡‰ç”¨ç¨‹å¼ ID"
msgid "Application settings saved successfully"
msgstr ""
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
msgid "Application was successfully destroyed."
msgstr ""
@@ -1140,6 +1336,18 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion"
+msgstr ""
+
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
msgstr[0] ""
@@ -1177,12 +1385,6 @@ msgstr ""
msgid "Approvals"
msgstr ""
-msgid "Approvals required"
-msgstr ""
-
-msgid "Approvers"
-msgstr ""
-
msgid "Apr"
msgstr "四月"
@@ -1213,6 +1415,18 @@ msgstr ""
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
+msgid "Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr ""
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to delete this list?"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "確定è¦åˆªé™¤æ­¤æŽ’程管線嗎?"
@@ -1234,18 +1448,6 @@ msgstr "確èªé‡æ–°ç”¢ç”Ÿå…¬é‘°ï¼Ÿæ‚¨å°‡éœ€è¦åœ¨é‡æ–°é‹ä½œé¡åƒå‰ï¼Œæ›´æ–°
msgid "Are you sure you want to remove %{group_name}?"
msgstr "確定移除 %{group_name}?"
-msgid "Are you sure you want to remove approver %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove approver %{name}?"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}"
-msgstr ""
-
-msgid "Are you sure you want to remove group %{name}?"
-msgstr ""
-
msgid "Are you sure you want to remove the attachment?"
msgstr ""
@@ -1261,6 +1463,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr "確定è¦é‡è¨­å¥åº·æª¢æŸ¥å­˜å–憑證嗎?"
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr "確定è¦åœæ­¢æ­¤ç’°å¢ƒå—Žï¼Ÿ"
@@ -1273,12 +1478,36 @@ msgstr ""
msgid "Are you sure?"
msgstr "確定?"
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
msgid "Artifact ID"
msgstr "æˆå“ ID"
msgid "Artifacts"
msgstr "æˆå“"
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
msgid "Ascending"
msgstr "é †åº"
@@ -1291,6 +1520,9 @@ msgstr "Assertion 客戶æœå‹™é€£çµ"
msgid "Assets"
msgstr ""
+msgid "Assign"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr "指定自訂é¡è‰²ï¼Œä¾‹å¦‚ #FF0000"
@@ -1301,11 +1533,17 @@ msgid "Assign milestone"
msgstr "指派里程碑"
msgid "Assign some issues to this milestone."
-msgstr ""
+msgstr "分é…一些議題到這個里程碑。"
msgid "Assign to"
msgstr "指派å°è±¡"
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
msgid "Assigned Issues"
msgstr "已指派的議題"
@@ -1319,13 +1557,13 @@ msgid "Assignee"
msgstr "指派人"
msgid "Assignee lists not available with your current license"
-msgstr "被指派者åå–®ä¸æ”¯æ´æ‚¨ç›®å‰çš„授權"
+msgstr "被指派人åå–®ä¸æ”¯æ´æ‚¨ç›®å‰çš„授權"
msgid "Assignee lists show all issues assigned to the selected user."
msgstr "指派列表顯示了分é…給é¸å®šä½¿ç”¨è€…的所有議題"
msgid "Assignee(s)"
-msgstr "執行者"
+msgstr "指派人"
msgid "At least one approval from a code owner is required to change files matching the respective CODEOWNER rules."
msgstr ""
@@ -1336,6 +1574,13 @@ msgstr ""
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "拖放檔案或者使用 %{upload_link} 連çµé™„加檔案"
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
msgid "Audit Events"
msgstr "審計活動"
@@ -1415,7 +1660,7 @@ msgid "AutoDevOps|Enable in settings"
msgstr "在設定中啟用"
msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
-msgstr "將根據é å…ˆè¨­å®šçš„ CI / CD 組態檔案來自動編譯ã€æ¸¬è©¦ä»¥åŠéƒ¨å±¬æ‚¨çš„應用程å¼ã€‚"
+msgstr "將根據é å…ˆè¨­å®šçš„ CI / CD 組態檔案來自動編譯ã€æ¸¬è©¦ä»¥åŠä½ˆç½²æ‚¨çš„應用程å¼ã€‚"
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "在 %{link_to_documentation} 了解更多"
@@ -1423,13 +1668,22 @@ msgstr "在 %{link_to_documentation} 了解更多"
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
msgstr "自動 DevOps 管線已經啟用,且會在沒有替代 CI 組態檔案å¯ç”¨çš„情æ³ä¸‹ä½¿ç”¨ã€‚%{more_information_link}"
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
msgid "Automatically marked as default internal user"
msgstr "自動標記為é è¨­æœ¬æ©Ÿä½¿ç”¨è€…"
-msgid "Automatically resolve merge request diff discussions when they become outdated"
+msgid "Automatically resolved"
msgstr ""
-msgid "Automatically resolved"
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
msgstr ""
msgid "Available"
@@ -1445,7 +1699,7 @@ msgid "Available specific runners"
msgstr ""
msgid "Avatar for %{assigneeName}"
-msgstr ""
+msgstr "%{assigneeName} çš„é ­åƒ"
msgid "Avatar for %{name}"
msgstr ""
@@ -1543,6 +1797,30 @@ msgstr "您的徽章"
msgid "Badges|e.g. %{exampleUrl}"
msgstr "例如 %{exampleUrl}"
+msgid "Badge|New"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
msgid "BatchComments|Delete all pending comments"
msgstr "刪除所有待處ç†çš„留言"
@@ -1645,17 +1923,34 @@ msgstr ""
msgid "Blocked"
msgstr ""
+msgid "Blocked by %d merge request"
+msgid_plural "Blocked by %d merge requests"
+msgstr[0] ""
+
+msgid "Blocked by <strong>%d closed</strong> merge request."
+msgid_plural "Blocked by <strong>%d closed</strong> merge requests."
+msgstr[0] ""
+
msgid "Blog"
msgstr "部è½æ ¼"
+msgid "Blue helpers indicate an action to be taken."
+msgstr ""
+
msgid "Boards"
msgstr "看æ¿"
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "在這個專案的版本庫中找ä¸åˆ° %{branchName} 分支。"
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr "已建立分支 <strong>%{branch_name}</strong>。如需設定自動部署,請在é¸æ“‡ GitLab CI Yaml 模æ¿å¾Œæ交您的變更。å¯åƒé–±ï¼š%{link_to_autodeploy_doc}"
+msgstr "已建立分支 <strong>%{branch_name}</strong>。如需設定自動佈署,請在é¸æ“‡ GitLab CI Yaml 模æ¿å¾Œæ交您的變更。å¯åƒé–±ï¼š%{link_to_autodeploy_doc}"
msgid "Branch has changed"
msgstr "分支已變更"
@@ -1666,6 +1961,9 @@ msgstr "å·²é¸æ“‡æ­¤åˆ†æ”¯ã€‚"
msgid "Branch name"
msgstr "分支å稱"
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "æœå°‹åˆ†æ”¯"
@@ -1816,6 +2114,21 @@ msgstr "ç€è¦½æª”案"
msgid "Built-in"
msgstr ""
+msgid "BurndownChartLabel|Guideline"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "BurndownChartLabel|Progress"
+msgstr ""
+
+msgid "BurndownChartLabel|Remaining"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -1834,6 +2147,9 @@ msgstr ""
msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
msgstr ""
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "作者:"
@@ -1874,16 +2190,16 @@ msgid "CICD|Auto DevOps"
msgstr "自動 DevOps"
msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
-msgstr "自動 DevOps 將會自動編譯ã€æ¸¬è©¦ã€ä¸¦åœ¨åŸºæ–¼é ç·¨è­¯ã€Œä¸é–“æ–·æ•´åˆã€å’Œã€Œå‚³éžã€è¨­å®šçš„環境部署您的應用程å¼"
+msgstr "自動 DevOps 將會自動編譯ã€æ¸¬è©¦ã€ä¸¦åœ¨åŸºæ–¼é ç·¨è­¯ã€Œä¸é–“æ–·æ•´åˆã€å’Œã€Œå‚³éžã€è¨­å®šçš„環境佈署您的應用程å¼"
msgid "CICD|Automatic deployment to staging, manual deployment to production"
-msgstr "至動部屬到模擬環境,手動部屬到正å¼ç’°å¢ƒ"
+msgstr "自動佈署到暫時環境,手動佈署到生產環境"
msgid "CICD|Continuous deployment to production"
-msgstr "æŒçºŒéƒ¨å±¬åˆ°æ­£å¼ç’°å¢ƒ"
+msgstr "æŒçºŒä½ˆç½²åˆ°æ­£å¼ç’°å¢ƒ"
msgid "CICD|Continuous deployment to production using timed incremental rollout"
-msgstr "使用定時增é‡éƒ¨ç½²ï¼ŒæŒçºŒéƒ¨ç½²åˆ°æ­£å¼ç’°å¢ƒ"
+msgstr "使用定時增é‡ä½ˆç½²ï¼ŒæŒçºŒä½ˆç½²åˆ°æ­£å¼ç’°å¢ƒ"
msgid "CICD|Default to Auto DevOps pipeline"
msgstr "é è¨­ä½¿ç”¨è‡ªå‹• DevOps 管線"
@@ -1892,7 +2208,7 @@ msgid "CICD|Default to Auto DevOps pipeline for all projects"
msgstr ""
msgid "CICD|Deployment strategy"
-msgstr "部屬策略"
+msgstr "佈署策略"
msgid "CICD|Jobs"
msgstr "作業"
@@ -1924,9 +2240,15 @@ msgstr ""
msgid "Can't find HEAD commit for this branch"
msgstr "找ä¸åˆ°æ­¤åˆ†æ”¯çš„ HEAD 變更。"
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
msgid "Can't remove group members without group managed account"
msgstr ""
+msgid "Can't scan the code?"
+msgstr ""
+
msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
msgstr ""
@@ -1948,9 +2270,15 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr "無法變更被管ç†çš„ Kubernetes å¢é›†"
+msgid "Cannot refer to a group milestone by an internal id!"
+msgstr "無法通éŽå…§éƒ¨ID引用組里程碑ï¼"
+
msgid "Cannot render the image. Maximum character count (%{charLimit}) has been exceeded."
msgstr ""
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
msgid "Cannot skip two factor authentication setup"
msgstr ""
@@ -1966,6 +2294,12 @@ msgstr ""
msgid "Change Weight"
msgstr "變更權é‡"
+msgid "Change assignee(s)"
+msgstr "變更指派人"
+
+msgid "Change assignee(s)."
+msgstr "變更指派人。"
+
msgid "Change path"
msgstr ""
@@ -1978,6 +2312,15 @@ msgstr "變更模æ¿"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "變更此數值將影響到 GitLab UI 拉å–更新的頻率。"
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "æ€é¸è‡³åˆ†æ”¯"
@@ -2002,6 +2345,12 @@ msgstr "è‹¥<b>來æº</b>修訂版正è¦åˆä½µåˆ°<b>目標</b>修訂版時顯示è
msgid "Changes suppressed. Click to show."
msgstr ""
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
msgid "Charts"
msgstr "統計圖表"
@@ -2029,6 +2378,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr "正在檢查分支å¯ç”¨æ€§â€¦"
+msgid "Checking username availability..."
+msgstr ""
+
msgid "Cherry-pick this commit"
msgstr "æ€é¸æ­¤æ交"
@@ -2050,6 +2402,9 @@ msgstr ""
msgid "Choose a role permission"
msgstr ""
+msgid "Choose a template"
+msgstr ""
+
msgid "Choose a template..."
msgstr "é¸æ“‡æ¨¡æ¿â€¦"
@@ -2080,7 +2435,7 @@ msgstr "é¸æ“‡ä½ æƒ³è¦é€£ç·šä¸¦åŸ·è¡Œ CI / CD 管線的版本庫。"
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr "é¸æ“‡ä½ æƒ³è¦ç”¨ä¾†èˆ‡é€™å€‹æ¬¡è¦ç¯€é»žåŒæ­¥çš„碎片 (shards)。"
-msgid "Choose your merge method, set up a default merge request description template."
+msgid "Choose your merge method, options, checks, and set up a default merge request description template."
msgstr ""
msgid "CiStatusLabel|canceled"
@@ -2152,16 +2507,34 @@ msgstr "已跳éŽ"
msgid "CiStatus|running"
msgstr "執行中"
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
msgid "CiVariables|Input variable key"
msgstr "輸入變數å稱"
msgid "CiVariables|Input variable value"
msgstr "輸入變數值"
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr "移除變數欄"
-msgid "CiVariables|This variable will not be masked"
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
msgstr ""
msgid "CiVariable|* (All environments)"
@@ -2215,14 +2588,23 @@ msgstr "清除æœå°‹"
msgid "Clear search input"
msgstr "清除æœå°‹ç´€éŒ„"
+msgid "Clear weight"
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr "在專案列表點é¸ä»»ä½•<strong>專案å稱</strong>,將轉跳到專案的里程碑。"
+msgid "Click here"
+msgstr ""
+
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr "é»žé¸ <strong>下載</strong> 按鈕並等待下載完æˆã€‚"
msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
-msgstr "點é¸å·¦ä¸Šè§’çš„<strong>æå‡</strong>按鈕,將æå‡è‡³ç¾¤çµ„里程碑。"
+msgstr "點é¸å·¦ä¸Šè§’çš„<strong>æå‡</strong>按鈕以æå‡è‡³ç¾¤çµ„里程碑。"
msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
msgstr "點é¸å³å´çš„ <strong>ä¸é¸æ“‡</strong> 按鈕,因為我們åªéœ€è¦ã€ŒGoogle Code 專案寄存ã€ã€‚"
@@ -2267,9 +2649,12 @@ msgid "Close"
msgstr "關閉"
msgid "Close epic"
-msgstr "關閉 Epic"
+msgstr "關閉å²è©©"
msgid "Close milestone"
+msgstr "關閉里程碑"
+
+msgid "Close sidebar"
msgstr ""
msgid "Closed"
@@ -2290,7 +2675,13 @@ msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} 已順利安è£åˆ°æ‚¨çš„ Kubernetes å¢é›†"
-msgid "ClusterIntegration|%{title} upgraded successfully."
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -2306,14 +2697,26 @@ msgid "ClusterIntegration|Add a Kubernetes cluster integration"
msgstr "增加 Kubernetes å¢é›†æ•´åˆ"
msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
-msgstr "å°‡ Kubernetes å¢é›†æ–°å¢žåˆ°ç¾¤çµ„後,群組中的所有專案都分享å¢é›†ï¼Œç”¨æ–¼æª¢é–±ã€éƒ¨ç½²ä½ çš„應用程å¼ï¼Œä»¥åŠæ›´æ˜“於執行你的作業管線"
+msgstr "å°‡ Kubernetes å¢é›†æ–°å¢žåˆ°ç¾¤çµ„後,群組中的所有專案都分享å¢é›†ï¼Œç”¨æ–¼æª¢é–±ã€ä½ˆç½²ä½ çš„應用程å¼ï¼Œä»¥åŠæ›´æ˜“於執行你的作業管線"
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr "增加整åˆåˆ°ä½ çš„群組,以便在群組中的專案分享å¢é›†ã€‚"
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Kubernetes å¢é›†æ•´åˆçš„進階設定"
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
msgid "ClusterIntegration|Alternatively"
msgstr ""
@@ -2329,6 +2732,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
msgid "ClusterIntegration|Applications"
msgstr "應用程å¼"
@@ -2437,6 +2843,9 @@ msgstr "GitLab 執行器"
msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
msgstr ""
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Google 雲端專案"
@@ -2473,19 +2882,10 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr "Ingress 為您æ供了一種將請求伺æœå™¨æˆ–路徑路由到æœå‹™çš„方法,將多個æœå‹™é›†ä¸­åˆ°ä¸€å€‹å…¥å£é»žã€‚"
-msgid "ClusterIntegration|Install"
-msgstr "安è£"
-
-msgid "ClusterIntegration|Installed"
-msgstr "已安è£"
-
-msgid "ClusterIntegration|Installing"
-msgstr "安è£ä¸­"
-
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
+msgid "ClusterIntegration|Instance cluster"
msgstr ""
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
@@ -2518,6 +2918,9 @@ msgstr "Knative 網域å稱"
msgid "ClusterIntegration|Knative Endpoint:"
msgstr ""
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
@@ -2537,10 +2940,10 @@ msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google
msgstr "Kubernetes å¢é›†å·²ç¶“æˆåŠŸåœ¨ Google Kubernetes Engine 建立,é‡æ–°æ•´ç†æ­¤é é¢å¾Œå°‡å¯çœ‹åˆ° Kubernetes å¢é›†çš„詳細資訊"
msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr "é€éŽ Kubernetes å¢é›†æ•´åˆï¼Œå¯ä»¥è®“你輕鬆使用程å¼ç¢¼æª¢é–±å·¥å…·ã€éƒ¨ç½²æ‚¨çš„應用程å¼ã€åŸ·è¡Œç®¡ç·šç­‰ã€‚"
+msgstr "é€éŽ Kubernetes å¢é›†æ•´åˆï¼Œå¯ä»¥è®“你輕鬆使用程å¼ç¢¼æª¢é–±å·¥å…·ã€ä½ˆç½²æ‚¨çš„應用程å¼ã€åŸ·è¡Œç®¡ç·šç­‰ã€‚"
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
-msgstr "Kubernetes å¢é›†å¯ä»¥ç”¨æ–¼éƒ¨ç½²æ‡‰ç”¨ç¨‹å¼ã€ä»¥åŠæ供此專案程å¼ç¢¼æª¢é–±å·¥å…·"
+msgstr "Kubernetes å¢é›†å¯ä»¥ç”¨æ–¼ä½ˆç½²æ‡‰ç”¨ç¨‹å¼ã€ä»¥åŠæ供此專案程å¼ç¢¼æª¢é–±å·¥å…·"
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr "了解有關 %{help_link_start_machine_type}機器類型%{help_link_end} 和 %{help_link_start_pricing}定價%{help_link_end} 的詳細資訊。"
@@ -2554,6 +2957,9 @@ msgstr "了解關於 Kubernetes 的更多資訊"
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr "了解關於群組 Kubernetes å¢é›†çš„更多資訊"
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
@@ -2563,9 +2969,6 @@ msgstr "機器類型"
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr "請確èªæ‚¨çš„帳號 %{link_to_requirements} 是å¦å¯ä»¥å»ºç«‹ Kubernetes å¢é›†"
-msgid "ClusterIntegration|Manage"
-msgstr "管ç†"
-
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr "請造訪 %{link_gke} 管ç†æ‚¨çš„ Kubernetes å¢é›†"
@@ -2629,7 +3032,7 @@ msgstr "若想è¦è«‹å–代此為您自己的主機å稱。如果您這麼åšï¼Œ
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "請求開始安è£å¤±æ•—"
-msgid "ClusterIntegration|Retry update"
+msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Save changes"
@@ -2683,12 +3086,36 @@ msgstr "在 Google Kubernetes Engine 建立å¢é›†æ™‚發生錯誤"
msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "å®‰è£ %{title} 時發生錯誤"
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr ""
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
+msgstr ""
+
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
+msgstr ""
+
+msgid "ClusterIntegration|The associated IP will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
+msgstr ""
+
msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
+msgstr ""
+
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr "此帳號必須è¦æœ‰ %{link_to_container_project} 底下è¦æ±‚的權é™æ‰èƒ½å»ºç«‹ Kubernetes å¢é›†"
@@ -2701,22 +3128,10 @@ msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "åˆ‡æ› Kubernetes å¢é›†"
-msgid "ClusterIntegration|Update failed. Please check the logs and try again."
-msgstr ""
-
-msgid "ClusterIntegration|Updating"
-msgstr ""
-
-msgid "ClusterIntegration|Upgrade"
-msgstr ""
-
-msgid "ClusterIntegration|Upgrade failed"
-msgstr ""
-
-msgid "ClusterIntegration|Upgraded"
+msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
-msgid "ClusterIntegration|Upgrading"
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
@@ -2726,7 +3141,10 @@ msgid "ClusterIntegration|We could not verify that one of your projects on GCP h
msgstr "我們無法驗證您其中一個在 GCP 上的專案是å¦å•Ÿç”¨å¸³å–®åŠŸèƒ½ã€‚è«‹é‡è©¦ã€‚"
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr "當 Kubernetes 節點關è¯åˆ°æ­¤å°ˆæ¡ˆï¼Œå³å¯æª¢é–±å’Œéƒ¨å±¬æ‡‰ç”¨ç¨‹å¼ã€åŸ·è¡Œç®¡ç·šä»¥åŠç”¨æ›´ç°¡å–®çš„æ–¹å¼åšæ›´å¤šçš„事情。"
+msgstr "當 Kubernetes 節點關è¯åˆ°æ­¤å°ˆæ¡ˆï¼Œå³å¯æª¢é–±å’Œä½ˆç½²æ‡‰ç”¨ç¨‹å¼ã€åŸ·è¡Œç®¡ç·šä»¥åŠç”¨æ›´ç°¡å–®çš„æ–¹å¼åšæ›´å¤šçš„事情。"
+
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
msgstr "在安è£ä¸‹æ–¹çš„應用程å¼å‰ï¼Œæ‚¨å¿…é ˆå…ˆå®‰è£ Helm Tiller"
@@ -2737,6 +3155,9 @@ msgstr ""
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "您的帳號必須有 %{link_to_kubernetes_engine}"
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
msgid "ClusterIntegration|Zone"
msgstr "å€åŸŸ"
@@ -2788,17 +3209,23 @@ msgstr ""
msgid "Collapse sidebar"
msgstr "收起å´é‚Šæ¬„"
+msgid "ComboSearch is not defined"
+msgstr ""
+
msgid "Command line instructions"
msgstr ""
+msgid "Commands applied"
+msgstr ""
+
msgid "Comment"
msgstr "留言"
msgid "Comment & close %{noteable_name}"
-msgstr ""
+msgstr "留言並關閉 %{noteable_name}"
msgid "Comment & reopen %{noteable_name}"
-msgstr ""
+msgstr "留言並é‡æ–°é–‹å•Ÿ %{noteable_name}"
msgid "Comment & resolve discussion"
msgstr "留言並關閉討論"
@@ -2809,6 +3236,9 @@ msgstr "留言並é‡æ–°è¨Žè«–"
msgid "Comment form position"
msgstr "留言框ä½ç½®"
+msgid "Comment is being updated"
+msgstr ""
+
msgid "Comments"
msgstr "留言"
@@ -2895,7 +3325,7 @@ msgid "Compare changes"
msgstr ""
msgid "Compare changes with the last commit"
-msgstr "與上一次的æ交記錄進行比較"
+msgstr "與最後æ交進行比較"
msgid "Compare changes with the merge request target branch"
msgstr "將變更與åˆä½µè«‹æ±‚目標分支進行比較"
@@ -2927,6 +3357,9 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr "設定 Gitaly 延é²éŽä¹…。"
+msgid "Configure Let's Encrypt"
+msgstr ""
+
msgid "Configure Tracing"
msgstr "設定追蹤"
@@ -2954,9 +3387,15 @@ msgstr "設定使用者建立新帳號的方å¼ã€‚"
msgid "Confirm"
msgstr ""
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
msgid "Confirmation required"
msgstr ""
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
msgid "Connect"
msgstr "連線"
@@ -2969,9 +3408,15 @@ msgstr "é€£çµ GitHub 版本庫"
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr "連çµæ‚¨çš„外部版本庫,CI / CD 管線將會為新的æ交執行。åªæœƒå»ºç«‹åªå•Ÿç”¨ CI / CD 功能的 GitLab 專案。"
+msgid "Connecting to terminal sync service"
+msgstr ""
+
msgid "Connecting..."
msgstr "正在連çµâ€¦"
+msgid "Connection failure"
+msgstr ""
+
msgid "Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -3035,6 +3480,9 @@ msgstr "å°‡ Docker 容器登錄表整åˆåˆ° GitLab 後,æ¯å€‹å°ˆæ¡ˆéƒ½èƒ½æœ‰è‡
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr "您也å¯ä»¥ä½¿ç”¨ %{deploy_token} 為 Registry 映åƒæª”進行唯讀存å–"
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
msgid "Contents of .gitlab-ci.yml"
msgstr ""
@@ -3045,10 +3493,10 @@ msgid "Continue to the next step"
msgstr "繼續下個步驟"
msgid "Continuous Integration and Deployment"
-msgstr "ä¸é–“æ–·æ•´åˆèˆ‡éƒ¨å±¬"
+msgstr "æŒçºŒæ•´åˆèˆ‡ä½ˆç½²"
msgid "Contribute to GitLab"
-msgstr "è²¢ç»çµ¦GitLab"
+msgstr "為 GitLab è²¢ç»"
msgid "Contribution"
msgstr "è²¢ç»"
@@ -3080,6 +3528,9 @@ msgstr "æ交到 %{branch_name},ä¸åŒ…å«åˆä½µæ交。é™åˆ¶æœ€å¤šé¡¯ç¤º 6,
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
msgstr "è«‹ç¨å¾…片刻,這個é é¢åœ¨æº–備好後自動é‡æ–°æ•´ç†ã€‚"
+msgid "Control emails linked to your account"
+msgstr ""
+
msgid "Control the display of third party offers."
msgstr "控制第三方æ供的顯示方å¼ã€‚"
@@ -3089,6 +3540,9 @@ msgstr "控制此次è¦ç¯€é»žçš„版本庫最大並行é‡"
msgid "ConvDev Index"
msgstr "ConvDev 索引"
+msgid "Copied"
+msgstr ""
+
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -3107,9 +3561,6 @@ msgstr "複製 SSH 的複製 (clone) URL"
msgid "Copy SSH public key"
msgstr ""
-msgid "Copy SSH public key to clipboard"
-msgstr "複製 SSH 公鑰到剪貼簿"
-
msgid "Copy URL to clipboard"
msgstr "複製網å€åˆ°å‰ªè²¼ç°¿"
@@ -3125,6 +3576,12 @@ msgstr "複製æ交記錄的 SHA 值到剪貼簿"
msgid "Copy file path to clipboard"
msgstr "複製檔案路徑到剪貼簿"
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr "從 %{source_issuable_reference} 複製標籤和里程碑。"
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
msgid "Copy link"
msgstr "複製連çµ"
@@ -3134,6 +3591,9 @@ msgstr "複製åƒç…§åˆ°å‰ªè²¼ç°¿"
msgid "Copy secret to clipboard"
msgstr "複製密碼到剪貼簿"
+msgid "Copy source to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr "複製至剪貼簿"
@@ -3143,9 +3603,15 @@ msgstr "複製憑證到剪貼簿"
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
msgid "Could not create Wiki Repository at this time. Please try again later."
msgstr ""
@@ -3179,9 +3645,18 @@ msgstr ""
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr ""
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request."
+msgstr ""
+
msgid "Create a new branch"
msgstr "建立新分支"
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Create a new issue"
msgstr "建立新議題"
@@ -3207,7 +3682,7 @@ msgid "Create empty repository"
msgstr "建立空的版本庫"
msgid "Create epic"
-msgstr "建立 epic"
+msgstr "建立å²è©©"
msgid "Create file"
msgstr "新增檔案"
@@ -3228,7 +3703,7 @@ msgid "Create merge request and branch"
msgstr "建立åˆä½µè«‹æ±‚åŠåˆ†æ”¯"
msgid "Create milestone"
-msgstr ""
+msgstr "建立里程碑"
msgid "Create new branch"
msgstr "新增分支"
@@ -3254,6 +3729,12 @@ msgstr "建立專案標籤"
msgid "Create your first page"
msgstr "建立您的第一個é é¢"
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr "標籤"
@@ -3269,14 +3750,29 @@ msgstr "建立於"
msgid "Created by me"
msgstr "由我建立"
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
msgid "Created on"
msgstr "建立於"
msgid "Created on:"
msgstr "建立於:"
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
+msgstr ""
+
msgid "Creating epic"
-msgstr "建立 epic"
+msgstr "正在建​立å²è©©"
msgid "Cron Timezone"
msgstr "Cron 時å€"
@@ -3293,6 +3789,9 @@ msgstr ""
msgid "Current node"
msgstr "ç›®å‰ç¯€é»ž"
+msgid "Current password"
+msgstr ""
+
msgid "CurrentUser|Profile"
msgstr "個人資料"
@@ -3371,7 +3870,19 @@ msgstr "全部"
msgid "DashboardProjects|Personal"
msgstr "個人"
+msgid "DashboardProjects|Trending"
+msgstr ""
+
msgid "Dashboards"
+msgstr "儀表æ¿"
+
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Gold plan."
msgstr ""
msgid "Data is still calculating..."
@@ -3380,6 +3891,18 @@ msgstr ""
msgid "Date picker"
msgstr "日期é¸æ“‡å™¨"
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
msgid "Debug"
msgstr "除錯"
@@ -3390,7 +3913,7 @@ msgid "December"
msgstr "å二月"
msgid "Decline"
-msgstr ""
+msgstr "拒絕"
msgid "Decline and sign out"
msgstr "拒絕並登出"
@@ -3416,6 +3939,9 @@ msgstr ""
msgid "Default issue template"
msgstr ""
+msgid "Default project deletion protection"
+msgstr ""
+
msgid "Default: Directly import the Google Code email address or username"
msgstr "é è¨­å€¼ï¼šç›´æŽ¥åŒ¯å…¥ Google Code çš„é›»å­éƒµä»¶ä½å€æˆ–使用者å稱"
@@ -3467,6 +3993,21 @@ msgstr ""
msgid "Delete this attachment"
msgstr ""
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
msgid "Deleted"
msgstr "已刪除"
@@ -3488,12 +4029,60 @@ msgstr ""
msgid "Deny"
msgstr "拒絕"
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Version"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
msgid "Deploy"
msgid_plural "Deploys"
-msgstr[0] "部署"
+msgstr[0] "佈署"
msgid "Deploy Keys"
-msgstr "部署金鑰"
+msgstr "佈署金鑰"
msgid "Deploy key was successfully updated."
msgstr ""
@@ -3505,37 +4094,37 @@ msgid "DeployKeys|Current project"
msgstr "ç›®å‰å°ˆæ¡ˆ"
msgid "DeployKeys|Deploy key"
-msgstr "部屬金鑰"
+msgstr "佈署金鑰"
msgid "DeployKeys|Enabled deploy keys"
-msgstr "已啟用部署金鑰"
+msgstr "已啟用佈署金鑰"
msgid "DeployKeys|Error enabling deploy key"
-msgstr "啟用部署金鑰時失敗"
+msgstr "啟用佈署金鑰時失敗"
msgid "DeployKeys|Error getting deploy keys"
-msgstr "å–得部署金鑰時失敗"
+msgstr "å–得佈署金鑰時失敗"
msgid "DeployKeys|Error removing deploy key"
-msgstr "移除部屬金鑰時失敗"
+msgstr "移除佈署金鑰時失敗"
msgid "DeployKeys|Expand %{count} other projects"
msgstr "展開其他 %{count} 個專案"
msgid "DeployKeys|Loading deploy keys"
-msgstr "正在載入部署金鑰"
+msgstr "正在載入佈署金鑰"
msgid "DeployKeys|No deploy keys found. Create one with the form above."
-msgstr "找ä¸åˆ°ä»»ä½•éƒ¨å±¬é‡‘鑰。請使用上é¢çš„表格建立一個。"
+msgstr "找ä¸åˆ°ä»»ä½•ä½ˆç½²é‡‘鑰。請使用上é¢çš„表格建立一個。"
msgid "DeployKeys|Privately accessible deploy keys"
-msgstr "å¯å­˜å–çš„ç§äººéƒ¨ç½²é‡‘é‘°"
+msgstr "å¯å­˜å–çš„ç§äººä½ˆç½²é‡‘é‘°"
msgid "DeployKeys|Project usage"
msgstr "專案用é‡"
msgid "DeployKeys|Publicly accessible deploy keys"
-msgstr "å¯å­˜å–的公開部署金鑰"
+msgstr "å¯å­˜å–的公開佈署金鑰"
msgid "DeployKeys|Read access only"
msgstr "唯讀存å–"
@@ -3544,13 +4133,13 @@ msgid "DeployKeys|Write access allowed"
msgstr "å·²å…許寫入權é™"
msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
-msgstr "你準備è¦ç§»é™¤é€™å€‹éƒ¨ç½²é‡‘鑰,確定?"
+msgstr "你準備è¦ç§»é™¤é€™å€‹ä½ˆç½²é‡‘鑰,確定?"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
-msgstr "啟用部屬憑證(%{active_tokens})"
+msgstr "啟用佈署憑證(%{active_tokens})"
msgid "DeployTokens|Add a deploy token"
-msgstr "建立一個部屬憑證"
+msgstr "建立一個佈署憑證"
msgid "DeployTokens|Allows read-only access to the registry images"
msgstr "å…許 Registry 映åƒæª”的唯讀存å–"
@@ -3559,22 +4148,22 @@ msgid "DeployTokens|Allows read-only access to the repository"
msgstr "å…許此版本庫的唯讀存å–"
msgid "DeployTokens|Copy deploy token to clipboard"
-msgstr "複製部署憑證至剪貼簿"
+msgstr "複製佈署憑證至剪貼簿"
msgid "DeployTokens|Copy username to clipboard"
msgstr "複製使用者å稱到剪貼簿"
msgid "DeployTokens|Create deploy token"
-msgstr "建立部屬憑證"
+msgstr "建立佈署憑證"
msgid "DeployTokens|Created"
msgstr "已建立"
msgid "DeployTokens|Deploy Tokens"
-msgstr "部屬憑證"
+msgstr "佈署憑證"
msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
-msgstr "部屬憑證å…許您版本庫的唯讀存å–與 Registry 映åƒæª”。"
+msgstr "佈署憑證å…許您版本庫的唯讀存å–與 Registry 映åƒæª”。"
msgid "DeployTokens|Expires"
msgstr "éŽæœŸçš„"
@@ -3583,7 +4172,7 @@ msgid "DeployTokens|Name"
msgstr "å稱"
msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
-msgstr "為您的應用程å¼å–個å稱,然後我們將會給您一個ç¨ç‰¹çš„部屬憑證。"
+msgstr "為您的應用程å¼å–個å稱,然後我們將會給您一個ç¨ç‰¹çš„佈署憑證。"
msgid "DeployTokens|Revoke"
msgstr "撤回"
@@ -3598,7 +4187,7 @@ msgid "DeployTokens|This action cannot be undone."
msgstr "此動作將無法還原。"
msgid "DeployTokens|This project has no active Deploy Tokens."
-msgstr "此專案沒有任何啟用的部屬憑證。"
+msgstr "此專案沒有任何啟用的佈署憑證。"
msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
msgstr "把這個憑證當åšå¯†ç¢¼ä½¿ç”¨ã€‚ä¿è­‰ä½ å„²å­˜äº†å®ƒ - 因為你將無法å†æ¬¡å­˜å–它。"
@@ -3613,19 +4202,19 @@ msgid "DeployTokens|You are about to revoke"
msgstr "您正打算復原"
msgid "DeployTokens|Your New Deploy Token"
-msgstr "您的新部屬憑證"
+msgstr "您的新佈署憑證"
msgid "DeployTokens|Your new project deploy token has been created."
-msgstr "您的新專案部屬憑證已經建立。"
+msgstr "您的新專案佈署憑證已經建立。"
msgid "Deployed"
msgstr ""
msgid "Deployed to"
-msgstr "已部署到"
+msgstr "已佈署到"
msgid "Deploying to"
-msgstr "正在部署到"
+msgstr "正在佈署到"
msgid "Deprioritize label"
msgstr "優先標籤"
@@ -3663,6 +4252,9 @@ msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
msgid "DesignManagement|The one place for your designs"
msgstr ""
@@ -3717,9 +4309,15 @@ msgstr "åœç”¨ç¾¤çµ„執行器"
msgid "Disable shared Runners"
msgstr ""
+msgid "Disable two-factor authentication"
+msgstr ""
+
msgid "Disabled"
msgstr ""
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
msgid "Discard"
msgstr "æ¨æ£„"
@@ -3741,6 +4339,12 @@ msgstr "放棄è‰ç¨¿"
msgid "Discard review"
msgstr "放棄檢閱"
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
msgid "Discover GitLab Geo"
msgstr ""
@@ -3754,7 +4358,7 @@ msgid "Discuss a specific suggestion or question that needs to be resolved"
msgstr ""
msgid "Discussion"
-msgstr ""
+msgstr "討論"
msgid "Dismiss"
msgstr "忽略"
@@ -3771,18 +4375,42 @@ msgstr "忽略åˆä½µè«‹æ±‚的促銷廣告"
msgid "Dismiss trial promotion"
msgstr "å–消試用版å‡ç´š"
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr "是å¦è¦è‡ªè¨‚å°‡ Google Code çš„é›»å­ä¿¡ç®±ä½å€å’Œä½¿ç”¨è€…å稱匯入到 GitLab çš„æ–¹å¼ï¼Ÿ"
+msgid "Dockerfile"
+msgstr ""
+
msgid "Documentation for popular identity providers"
msgstr "知å身份æ供商的檔案"
msgid "Domain"
msgstr "網域"
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
msgid "Don't show again"
msgstr "ä¸å†é¡¯ç¤º"
+msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
+msgstr ""
+
msgid "Done"
msgstr "完æˆ"
@@ -3795,25 +4423,19 @@ msgstr ""
msgid "Download asset"
msgstr ""
-msgid "Download export"
+msgid "Download codes"
msgstr ""
-msgid "Download license"
-msgstr ""
-
-msgid "Download tar"
-msgstr ""
-
-msgid "Download tar.bz2"
+msgid "Download export"
msgstr ""
-msgid "Download tar.gz"
+msgid "Download license"
msgstr ""
-msgid "Download zip"
+msgid "Download source code"
msgstr ""
-msgid "DownloadArtifacts|Download"
+msgid "Download this directory"
msgstr ""
msgid "DownloadCommit|Email Patches"
@@ -3853,6 +4475,9 @@ msgid "Edit Label"
msgstr "編輯標籤"
msgid "Edit Milestone"
+msgstr "編輯里程碑"
+
+msgid "Edit Password"
msgstr ""
msgid "Edit Pipeline Schedule %{id}"
@@ -3865,7 +4490,7 @@ msgid "Edit application"
msgstr "編輯應用程å¼"
msgid "Edit comment"
-msgstr ""
+msgstr "編輯留言"
msgid "Edit environment"
msgstr ""
@@ -3891,6 +4516,12 @@ msgstr ""
msgid "Elasticsearch"
msgstr "Elasticsearch"
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr "Elasticsearch æ•´åˆã€‚ Elasticsearch AWS IAM。"
@@ -3909,6 +4540,9 @@ msgstr ""
msgid "Email patch"
msgstr "é›»å­éƒµä»¶è£œä¸"
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
msgstr ""
@@ -3933,9 +4567,39 @@ msgstr ""
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr ""
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
msgid "Emails"
msgstr "é›»å­éƒµä»¶"
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
msgid "Embed"
msgstr "內嵌"
@@ -3960,6 +4624,9 @@ msgstr "為此群組啟用 SAML 驗證"
msgid "Enable Sentry for error reporting and logging."
msgstr "為錯誤報告與記錄啟用 Sentry。"
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
msgid "Enable and configure InfluxDB metrics."
msgstr "啟用與設定 InfluxDB 指標。"
@@ -3996,9 +4663,6 @@ msgstr "啟用 reCAPTCHA 或 Akismet 並設定 IP 上é™ã€‚"
msgid "Enable shared Runners"
msgstr ""
-msgid "Enable the Performance Bar for a given group."
-msgstr "啟用æ供群組的效能桿。"
-
msgid "Enable two-factor authentication"
msgstr ""
@@ -4029,12 +4693,18 @@ msgstr ""
msgid "Ends at (UTC)"
msgstr "æ–¼ (UTC) çµæŸ"
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
msgid "Enter at least three characters to search"
msgstr ""
msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr "在底下輸入您的 BitBucket 伺æœå™¨ URL 和個人存å–憑證"
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
msgid "Enter the issue description"
msgstr "請輸入議題說明"
@@ -4047,7 +4717,10 @@ msgstr "請輸入åˆä½µè«‹æ±‚說明"
msgid "Enter the merge request title"
msgstr "請請輸入åˆä½µè«‹æ±‚標題"
-msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they will be masked by default so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
+msgid "EnviornmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. Additionally, they can be masked so they are hidden in job logs, though they must match certain regexp requirements to do so. You can use environment variables for passwords, secret keys, or whatever you want."
msgstr ""
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
@@ -4059,9 +4732,33 @@ msgstr ""
msgid "Environments"
msgstr "環境"
+msgid "Environments Dashboard"
+msgstr ""
+
msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
msgstr ""
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr "抓å–環境時發生錯誤。"
@@ -4084,10 +4781,10 @@ msgid "Environments|Commit"
msgstr "æ交"
msgid "Environments|Deploy to..."
-msgstr "部屬到…"
+msgstr "佈署到…"
msgid "Environments|Deployment"
-msgstr "部署"
+msgstr "佈署"
msgid "Environments|Environment"
msgstr "環境"
@@ -4096,7 +4793,7 @@ msgid "Environments|Environments"
msgstr "環境"
msgid "Environments|Environments are places where code gets deployed, such as staging or production."
-msgstr "《環境》是部署程å¼ç¢¼çš„ä½ç½®ï¼Œä¾‹å¦‚階段或生產環境。"
+msgstr "《環境》是佈署程å¼ç¢¼çš„ä½ç½®ï¼Œä¾‹å¦‚階段或生產環境。"
msgid "Environments|Job"
msgstr "作業"
@@ -4108,7 +4805,7 @@ msgid "Environments|New environment"
msgstr "建立環境"
msgid "Environments|No deployments yet"
-msgstr "尚未部署"
+msgstr "尚未佈署"
msgid "Environments|No pod name has been specified"
msgstr "沒有指定 pod å稱"
@@ -4135,7 +4832,7 @@ msgid "Environments|Re-deploy environment %{name}?"
msgstr ""
msgid "Environments|Re-deploy to environment"
-msgstr "é‡æ–°éƒ¨å±¬ç’°å¢ƒ"
+msgstr "é‡æ–°ä½ˆç½²ç’°å¢ƒ"
msgid "Environments|Read more about environments"
msgstr "了解有關環境的更多資訊"
@@ -4186,29 +4883,62 @@ msgid "Environments|protected"
msgstr "å—ä¿è­·çš„"
msgid "Epic"
-msgstr "Epic"
+msgstr "å²è©©"
msgid "Epics"
-msgstr "Epic"
+msgstr "å²è©©"
msgid "Epics Roadmap"
-msgstr "Epics 開發è—圖"
+msgstr "å²è©©è·¯ç·šåœ–"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr "Epics 讓你能更有效率且花費更少功夫的管ç†æ‚¨å°ˆæ¡ˆçš„組åˆã€‚"
+msgid "Epics|%{epicsCount} epics and %{issuesCount} issues"
+msgstr ""
+
+msgid "Epics|Add an epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic as a child epic."
+msgstr ""
+
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr ""
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Create an epic within this group and add it as a child epic."
+msgstr ""
+
+msgid "Epics|Create new epic"
+msgstr ""
+
msgid "Epics|How can I solve this?"
msgstr "該怎麼解決這個?"
msgid "Epics|More information"
msgstr "更多資訊"
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr "這些日期會影響在開發è—圖中 Epic 的顯示方å¼ã€‚來自里程碑的日期來自å°æ‡‰åˆ° Epic 中議題的里程碑。您也å¯ä»¥è¨­å®šå›ºå®šæ—¥æœŸã€æˆ–是完全移除它們。"
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr "è‹¥è¦æŽ’程基於里程碑的 Epic %{epicDateType} 日期,請å°ä»»ä½• Epic 中的議題指定 %{epicDateType} 日期的里程碑。"
@@ -4231,7 +4961,7 @@ msgid "Error creating a new path"
msgstr ""
msgid "Error creating epic"
-msgstr "建立 epic 時發生錯誤"
+msgstr "建立å²è©©æ™‚發生錯誤"
msgid "Error deleting %{issuableType}"
msgstr ""
@@ -4245,9 +4975,15 @@ msgstr "抓å–標籤時發生錯誤。"
msgid "Error fetching network graph."
msgstr "抓å–分支圖時發生錯誤。"
+msgid "Error fetching projects"
+msgstr ""
+
msgid "Error fetching refs"
msgstr "抓å–åƒç…§æ™‚發生錯誤。"
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
msgid "Error fetching usage ping data."
msgstr "讀å–ä½¿ç”¨æƒ…æ³ ping 資料時發生錯誤。"
@@ -4257,8 +4993,14 @@ msgstr "載入分支資料時錯誤,請é‡è©¦ã€‚"
msgid "Error loading branches."
msgstr "載入分支時發生錯誤。"
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
msgid "Error loading last commit."
-msgstr "載入最新æ交記錄時失敗。"
+msgstr "載入最後æ交時失敗。"
msgid "Error loading markdown preview"
msgstr "載入 Markdown é è¦½æ™‚發生å•é¡Œ"
@@ -4266,6 +5008,9 @@ msgstr "載入 Markdown é è¦½æ™‚發生å•é¡Œ"
msgid "Error loading merge requests."
msgstr "載入åˆä½µè«‹æ±‚時錯誤。"
+msgid "Error loading milestone tab"
+msgstr ""
+
msgid "Error loading project data. Please try again."
msgstr "載入專案資料時錯誤,請é‡è©¦ã€‚"
@@ -4275,6 +5020,12 @@ msgstr "載入模æ¿é¡žåž‹æ™‚發生錯誤。"
msgid "Error loading template."
msgstr "載入模æ¿æ™‚發生錯誤。"
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
msgid "Error occurred when toggling the notification subscription"
msgstr "切æ›è¨‚閱通知時發生錯誤"
@@ -4308,9 +5059,15 @@ msgstr "更新待辦事項狀態時發生錯誤。"
msgid "Error uploading file"
msgstr ""
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
msgid "Error while loading the merge request. Please try again."
msgstr "載入åˆä½µè«‹æ±‚時出錯。請é‡è©¦ã€‚"
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
@@ -4407,6 +5164,9 @@ msgstr ""
msgid "Everything you need to create a GitLab Pages site using plain HTML."
msgstr ""
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
msgid "Except policy:"
msgstr ""
@@ -4494,6 +5254,27 @@ msgstr "分類標籤"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "當沒有設定分類標籤時,將會使用é è¨­æ¨™ç±¤ `%{default_label}`。"
+msgid "ExternalMetrics|Add a button to the metrics dashboard linking directly to your existing external dashboards."
+msgstr ""
+
+msgid "ExternalMetrics|Enter the URL of the dashboard you want to link to"
+msgstr ""
+
+msgid "ExternalMetrics|External Dashboard"
+msgstr ""
+
+msgid "ExternalMetrics|Full dashboard URL"
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
msgid "Facebook"
msgstr "Facebook"
@@ -4503,17 +5284,38 @@ msgstr "失敗"
msgid "Failed Jobs"
msgstr "失敗的作業"
+msgid "Failed create wiki"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr "無法變更所有者"
msgid "Failed to check related branches."
msgstr "檢查相關分支失敗。"
+msgid "Failed to connect to the prometheus server"
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create repository via gitlab-shell"
+msgstr ""
+
msgid "Failed to create resources"
msgstr ""
msgid "Failed to deploy to"
-msgstr "無法部署到"
+msgstr "無法佈署到"
+
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
msgid "Failed to load emoji list."
msgstr "無法讀å–表情符號列表。"
@@ -4521,9 +5323,21 @@ msgstr "無法讀å–表情符號列表。"
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
msgstr ""
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr "從看æ¿åˆªé™¤è­°é¡Œæ™‚發生錯誤,請ç¨å€™é‡è©¦ã€‚"
@@ -4542,6 +5356,12 @@ msgstr ""
msgid "Failed to reset key. Please try again."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
msgid "Failed to save new settings"
msgstr ""
@@ -4554,18 +5374,30 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr "無法é€éŽ smartcard 進行èªè­‰"
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr "更新議題時發生錯誤,請ç¨å¾Œé‡è©¦ã€‚"
+msgid "Failed to update tag!"
+msgstr ""
+
+msgid "Failed to update."
+msgstr ""
+
+msgid "Failed to upgrade."
+msgstr ""
+
msgid "Failed to upload object map file"
msgstr ""
msgid "Failure"
msgstr "失敗"
-msgid "Fast-forward merge"
-msgstr ""
-
msgid "Fast-forward merge without a merge commit"
msgstr ""
@@ -4578,6 +5410,12 @@ msgstr ""
msgid "Feature Flags"
msgstr "功能標籤"
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
msgid "FeatureFlags|* (All Environments)"
msgstr ""
@@ -4641,8 +5479,8 @@ msgstr "åœç”¨"
msgid "FeatureFlags|Inactive flag for %{scope}"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
-msgstr "å®‰è£ %{docs_link_start} 相容的使用者端 %{docs_link_end},並在設定é é¢æŒ‡å®š API URLã€æ‡‰ç”¨ç¨‹å¼å’Œå¯¦ä¾‹ ID。"
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
+msgstr ""
msgid "FeatureFlags|Instance ID"
msgstr "實例 ID"
@@ -4653,9 +5491,6 @@ msgstr ""
msgid "FeatureFlags|More Information"
msgstr ""
-msgid "FeatureFlags|More information"
-msgstr "更多資訊"
-
msgid "FeatureFlags|Name"
msgstr "å稱"
@@ -4735,6 +5570,12 @@ msgstr ""
msgid "Files"
msgstr "檔案"
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr "填寫以下的欄ä½ï¼Œé–‹å•Ÿ <strong>%{enable_label}</strong> 後按下 <strong>%{save_changes}</strong>"
@@ -4751,7 +5592,7 @@ msgid "Filter by commit message"
msgstr "僅篩é¸æ交訊æ¯"
msgid "Filter by milestone name"
-msgstr ""
+msgstr "é€éŽé‡Œç¨‹ç¢‘å稱篩é¸"
msgid "Filter by two-factor authentication"
msgstr ""
@@ -4783,6 +5624,9 @@ msgstr "找到新æå–çš„ <code>Takeout/Google Code Project Hosting/GoogleCodeP
msgid "Fingerprint"
msgstr ""
+msgid "Fingerprint:"
+msgstr ""
+
msgid "Fingerprints"
msgstr "數ä½æŒ‡ç´‹:"
@@ -4792,6 +5636,9 @@ msgstr ""
msgid "Finish review"
msgstr "完æˆæª¢é–±"
+msgid "Finish setting up your dedicated account for <strong>%{group_name}</strong>."
+msgstr ""
+
msgid "Finished"
msgstr "已完æˆ"
@@ -4808,7 +5655,7 @@ msgid "Fixed date"
msgstr "修復日期"
msgid "Fixed due date"
-msgstr "修復的截止日期"
+msgstr "固定截止日期"
msgid "Fixed start date"
msgstr "修復的開始日期"
@@ -4816,6 +5663,12 @@ msgstr "修復的開始日期"
msgid "Fixed:"
msgstr "已修復:"
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
msgid "FogBugz Email"
msgstr "FogBugz é›»å­ä¿¡ç®±"
@@ -4861,6 +5714,15 @@ msgstr "å°æ–¼ç§äººå°ˆæ¡ˆï¼Œä»»ä½•æˆå“¡ (訪客或以上) 都å¯ä»¥æª¢è¦–管ç·
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr "å°æ–¼å…¬é–‹å°ˆæ¡ˆï¼Œä»»ä½•äººéƒ½å¯ä»¥æª¢è¦–管線並存å–工作詳細資訊 (輸出記錄和æˆå“)"
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
msgid "ForkedFromProjectPath|Forked from"
msgstr "分支自"
@@ -4870,6 +5732,9 @@ msgstr "從 %{project_name} 分支(已刪除)"
msgid "Forking in progress"
msgstr "正在建立分å‰"
+msgid "Forking repository"
+msgstr ""
+
msgid "Forks"
msgstr ""
@@ -4888,6 +5753,9 @@ msgstr "在您的 .gitlab-ci.yml 中找到錯誤:"
msgid "Free Trial of GitLab.com Gold"
msgstr "å…費試用 GitLab.com 黃金計畫"
+msgid "Friday"
+msgstr ""
+
msgid "From %{providerTitle}"
msgstr ""
@@ -4907,10 +5775,10 @@ msgid "From Google Code"
msgstr "從 Google Code"
msgid "From issue creation until deploy to production"
-msgstr "從議題建立直到部署至生產環境"
+msgstr "從議題建立直到佈署至生產環境"
msgid "From merge request merge until deploy to production"
-msgstr "從åˆä½µè«‹æ±‚被åˆä½µï¼Œåˆ°éƒ¨å±¬åˆ°ç”Ÿç”¢ç’°å¢ƒæœŸé–“"
+msgstr "從åˆä½µè«‹æ±‚被åˆä½µï¼Œåˆ°ä½ˆç½²åˆ°ç”Ÿç”¢ç’°å¢ƒæœŸé–“"
msgid "From milestones:"
msgstr "來自里程碑:"
@@ -4918,12 +5786,18 @@ msgstr "來自里程碑:"
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr "從 Kubernetes å¢é›†è©³ç´°è³‡æ–™é ï¼Œå¾žæ‡‰ç”¨ç¨‹å¼åˆ—表中安è£åŸ·è¡Œå™¨"
+msgid "Full name"
+msgstr ""
+
msgid "GPG Key ID:"
msgstr ""
msgid "GPG Keys"
msgstr "GPG 金鑰"
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
msgid "GPG signature (loading...)"
msgstr ""
@@ -5281,6 +6155,12 @@ msgstr "åŒæ­¥å¤±æ•— - %{error}"
msgid "Geo|The URL defined on the primary node that secondary nodes should use to contact it. Returns `url` if not set"
msgstr ""
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
msgid "Geo|This is a primary node"
msgstr ""
@@ -5338,6 +6218,9 @@ msgstr "Git"
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr ""
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will <strong>not</strong> be synced in push mirrors."
+msgstr ""
+
msgid "Git global setup"
msgstr ""
@@ -5347,6 +6230,9 @@ msgstr "Git 版本庫網å€"
msgid "Git revision"
msgstr "Git 修訂版"
+msgid "Git shallow clone"
+msgstr ""
+
msgid "Git strategy for pipelines"
msgstr "Git 管線策略"
@@ -5419,6 +6305,9 @@ msgstr "匯入 Gitea"
msgid "Given access %{time_ago}"
msgstr ""
+msgid "Global notification settings"
+msgstr ""
+
msgid "Go Back"
msgstr "返回"
@@ -5437,9 +6326,18 @@ msgstr "å‰å¾€"
msgid "Go to %{link_to_google_takeout}."
msgstr "å‰å¾€ %{link_to_google_takeout}。"
+msgid "Go to parent"
+msgstr ""
+
msgid "Go to project"
msgstr ""
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Golden Tanuki"
+msgstr ""
+
msgid "Google Code import"
msgstr "匯入 Google Code"
@@ -5515,6 +6413,9 @@ msgstr "群組å稱"
msgid "Group overview content"
msgstr ""
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
msgid "Group was successfully updated."
msgstr ""
@@ -5524,6 +6425,9 @@ msgstr ""
msgid "Group: %{group_name}"
msgstr "群組:%{group_name}"
+msgid "Group: %{name}"
+msgstr ""
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr "從 %{dateWord}"
@@ -5551,13 +6455,16 @@ msgstr "直到 %{dateWord}"
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
-msgid "GroupSAML|Enable SAML authentication for this group"
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce SSO-only authentication for this group"
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
msgstr ""
-msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group"
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
msgstr ""
msgid "GroupSAML|Enforced SSO"
@@ -5569,9 +6476,6 @@ msgstr ""
msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
msgstr ""
-msgid "GroupSAML|Group managed accounts"
-msgstr ""
-
msgid "GroupSAML|Identity provider single sign on URL"
msgstr ""
@@ -5602,9 +6506,18 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
msgid "GroupSAML|Toggle SAML authentication"
msgstr ""
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
msgid "GroupSAML|Your SCIM token"
msgstr ""
@@ -5668,6 +6581,9 @@ msgstr "移除 %{ancestor_group_name} 的群組分享鎖"
msgid "Groups"
msgstr "群組"
+msgid "Groups (%{count})"
+msgstr ""
+
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr "群組也å¯ä»¥å»ºç«‹ %{subgroup_docs_link_start}å­ç¾¤çµ„%{subgroup_docs_link_end}。"
@@ -5737,6 +6653,9 @@ msgstr "沒有符åˆæ‚¨æœå°‹çš„群組或專案"
msgid "GroupsTree|Search by name"
msgstr "ä¾å稱æœå°‹"
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
msgid "Have your users email"
msgstr "有來自您使用者的信件"
@@ -5764,6 +6683,9 @@ msgstr "未åµæ¸¬åˆ°å¥åº·å•é¡Œ"
msgid "HealthCheck|Unhealthy"
msgstr "å¥åº·ç‹€æ…‹ä¸è‰¯"
+msgid "Hello there"
+msgstr ""
+
msgid "Help"
msgstr "說明"
@@ -5773,12 +6695,15 @@ msgstr "說明é é¢"
msgid "Help page text and support page url."
msgstr "說明é é¢æ–‡å­—與支æ´é é¢é€£çµ"
-msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
-msgstr "這裡是è¦åŠ é€²åŽ»é ç«¯ä¼ºæœå™¨çš„公共 SSH 金鑰。欲知更多資訊,請åƒè€ƒæª”案。"
+msgid "Hide archived projects"
+msgstr ""
msgid "Hide file browser"
msgstr ""
+msgid "Hide group projects"
+msgstr ""
+
msgid "Hide host keys manual input"
msgstr "éš±è—主機金鑰手動輸入"
@@ -5788,6 +6713,9 @@ msgstr ""
msgid "Hide payload"
msgstr "éš±è—酬載"
+msgid "Hide shared projects"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "éš±è—數值"
@@ -5801,6 +6729,12 @@ msgstr ""
msgid "History"
msgstr "æ­·å²è¨˜éŒ„"
+msgid "History of authentications"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
msgid "Hook was successfully created."
msgstr ""
@@ -5816,6 +6750,12 @@ msgstr "已順利開始維護程åº"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -5825,6 +6765,12 @@ msgstr "æˆ‘æŽ¥å— %{terms_link}"
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr "æœå‹™æ¢æ¬¾å’Œéš±ç§æ”¿ç­–"
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end}"
+msgstr ""
+
msgid "ID"
msgstr "ID"
@@ -5894,11 +6840,20 @@ msgstr "如果啟用"
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr "如果啟用,將會使用其分類標籤在外部æœå‹™ä¸Šé©—證專案的存å–。"
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
msgstr "如果使用 GitHub,你將會看到用於æ交與推é€è«‹æ±‚çš„ GitHub 管線狀態。%{more_info_link}"
-msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
-msgstr "如果你的 HTTP 版本庫沒有公開存å–,請增加驗證欄ä½åˆ°ç¶²å€ä¸Šï¼š<code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
+msgstr ""
msgid "ImageDiffViewer|2-up"
msgstr "2-up"
@@ -5978,6 +6933,12 @@ msgstr "從 GitHub 匯入版本庫"
msgid "Import repository"
msgstr "匯入版本庫"
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
msgstr ""
@@ -5987,6 +6948,12 @@ msgstr ""
msgid "ImportButtons|Connect repositories from"
msgstr "連線版本庫自"
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -5996,9 +6963,18 @@ msgstr ""
msgid "ImportProjects|Select the projects you want to import"
msgstr ""
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
msgid "ImportProjects|Updating the imported projects failed"
msgstr ""
+msgid "Improve Issue boards"
+msgstr ""
+
msgid "Improve Issue boards with GitLab Enterprise Edition."
msgstr "改善 GitLab ä¼æ¥­ç‰ˆæœ¬çš„議題看æ¿ã€‚"
@@ -6050,12 +7026,21 @@ msgstr ""
msgid "Incompatible Project"
msgstr "ä¸ç›¸å®¹çš„專案"
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Indexing"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr "指示這個執行器是å¦èƒ½é¸æ“‡æ²’有標籤的工作"
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
msgstr ""
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
msgid "Inline"
msgstr "內嵌"
@@ -6077,12 +7062,24 @@ msgstr ""
msgid "Insights"
msgstr ""
+msgid "Install"
+msgstr ""
+
msgid "Install GitLab Runner"
msgstr "å®‰è£ GitLab 執行器"
msgid "Install Runner on Kubernetes"
msgstr "在 Kubernetes 上安è£åŸ·è¡Œå™¨"
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
msgid "Instance"
msgid_plural "Instances"
msgstr[0] "實例"
@@ -6129,18 +7126,42 @@ msgstr "週期分æžç°¡ä»‹"
msgid "Introducing Your Conversational Development Index"
msgstr ""
+msgid "Invalid Insights config file detected"
+msgstr ""
+
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
msgid "Invalid file."
msgstr ""
+msgid "Invalid import params"
+msgstr ""
+
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invalid pin code"
msgstr ""
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
msgid "Invalid two-factor code."
msgstr ""
@@ -6150,6 +7171,9 @@ msgstr ""
msgid "Invite"
msgstr "邀請"
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
msgid "Invite group"
msgstr ""
@@ -6162,6 +7186,9 @@ msgstr ""
msgid "Invoke Time"
msgstr ""
+msgid "Is using license seat:"
+msgstr ""
+
msgid "IssuableStatus|Closed (%{moved_link_start}moved%{moved_link_end})"
msgstr ""
@@ -6180,6 +7207,12 @@ msgstr "議題事件"
msgid "Issue template (optional)"
msgstr ""
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
msgid "IssueBoards|Board"
msgstr "看æ¿"
@@ -6214,7 +7247,7 @@ msgid "Issues with comments, merge requests with diffs and comments, labels, mil
msgstr ""
msgid "Issues, merge requests, pushes, and comments."
-msgstr ""
+msgstr "è­°é¡Œã€åˆä½µè«‹æ±‚ã€æŽ¨é€åŠç•™è¨€ã€‚"
msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
msgstr "在您為專案建立議題後,我們開始追蹤並顯示它們的指標"
@@ -6255,6 +7288,48 @@ msgstr "一月"
msgid "January"
msgstr "一月"
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|JIRA API URL"
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|JIRA comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+msgid "JiraService|Use , or ; to separate multiple transition IDs"
+msgstr ""
+
+msgid "JiraService|Use a password for server version and an API token for cloud version"
+msgstr ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
msgid "Job"
msgstr "作業"
@@ -6351,6 +7426,12 @@ msgstr "七月"
msgid "July"
msgstr "七月"
+msgid "Jump to first unresolved discussion"
+msgstr ""
+
+msgid "Jump to next unresolved discussion"
+msgstr ""
+
msgid "Jun"
msgstr "六月"
@@ -6360,6 +7441,9 @@ msgstr "六月"
msgid "Key (PEM)"
msgstr ""
+msgid "Key: %{key}"
+msgstr ""
+
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -6384,12 +7468,18 @@ msgstr "Kubernetes å¢é›†å·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Kubernetes configured"
msgstr "Kubernetes 已設定"
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr "Kubernetes æœå‹™æ•´åˆå·²è¢«æ£„用。%{deprecated_message_content} 而ç¾åœ¨æ‚¨çš„ Kubernetes å¢é›†å·²æ”¹ç”¨æ–°çš„ <a href=\"%{url}\"/>Kubernetes å¢é›†</a> é é¢"
msgid "LDAP settings"
msgstr ""
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
msgid "LFS"
msgstr "LFS"
@@ -6402,6 +7492,9 @@ msgstr "åœç”¨"
msgid "LFSStatus|Enabled"
msgstr "啟用"
+msgid "LICENSE"
+msgstr ""
+
msgid "Label"
msgstr "標籤"
@@ -6450,6 +7543,9 @@ msgstr "æå‡æ¨™ç±¤"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr "æå‡ %{labelTitle} å°‡å¯ä»¥è®“所有 %{groupName} 內的專案都使用此標籤。ç¾æœ‰ç›¸åŒå稱的標籤將被åˆä½µã€‚該æ“作ä¸å¯å¾©åŽŸã€‚"
+msgid "Labels|and %{count} more"
+msgstr ""
+
msgid "Language"
msgstr ""
@@ -6463,11 +7559,14 @@ msgstr[0] "最近 %d 天"
msgid "Last Pipeline"
msgstr "最近一次管線"
+msgid "Last accessed on"
+msgstr ""
+
msgid "Last activity"
msgstr ""
msgid "Last commit"
-msgstr "最後一次æ交"
+msgstr "最後æ交"
msgid "Last contact"
msgstr "上次è¯ç¹«æ–¼"
@@ -6485,10 +7584,16 @@ msgid "Last seen"
msgstr ""
msgid "Last update"
-msgstr "上次更新"
+msgstr "最後更新"
msgid "Last updated"
-msgstr "上次更新"
+msgstr "最後更新"
+
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
msgid "LastPushEvent|You pushed to"
msgstr "您推é€äº†"
@@ -6505,6 +7610,12 @@ msgstr ""
msgid "Lead"
msgstr ""
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
msgstr ""
@@ -6523,6 +7634,9 @@ msgstr "了解更多端於 Kubernetes 的資訊"
msgid "Learn more about Web Terminal"
msgstr ""
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "Learn more about approvals."
msgstr ""
@@ -6535,6 +7649,9 @@ msgstr ""
msgid "Learn more about signing commits"
msgstr ""
+msgid "Learn more about the dependency list"
+msgstr ""
+
msgid "Learn more in the"
msgstr "進一步了解於"
@@ -6556,6 +7673,12 @@ msgstr "退出專案"
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
msgstr "å°‡\"檔案類型\"å’Œ\"傳éžæ–¹æ³•\"é¸é …ä¿ç•™ç‚ºå…¶é è¨­å€¼ã€‚"
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
msgid "License"
msgstr "授權"
@@ -6631,6 +7754,9 @@ msgstr "URL"
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr "您正打算從此專案移除此授權:%{name}"
+msgid "Licensed Features"
+msgstr ""
+
msgid "Licensed to"
msgstr ""
@@ -6644,6 +7770,9 @@ msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
msgstr[0] "é™åˆ¶æœ€å¤šé¡¯ç¤º %d 個活動"
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -6674,6 +7803,9 @@ msgstr "å³æ™‚é è¦½"
msgid "Loading contribution stats for group members"
msgstr "正在讀å–群組æˆå“¡çš„è²¢ç»çµ±è¨ˆ"
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr "è®€å– GitLab IDE…"
@@ -6695,6 +7827,9 @@ msgstr "鎖定 %{issuableDisplayName}"
msgid "Lock not found"
msgstr "找ä¸åˆ°éŽ–定的檔案"
+msgid "Lock the discussion"
+msgstr ""
+
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr "鎖定此 %{issuableDisplayName}? åªæœ‰ <strong>專案æˆå“¡</strong>æ‰å¯ä»¥ç™¼è¡¨ç•™è¨€ã€‚"
@@ -6713,6 +7848,9 @@ msgstr "已鎖定目å‰å°ˆæ¡ˆ"
msgid "Locks give the ability to lock specific file or folder."
msgstr "《鎖定》æ供了鎖定特定檔案或資料夾的能力。"
+msgid "Locks the discussion"
+msgstr ""
+
msgid "Login with smartcard"
msgstr "使用 smartcard 登入"
@@ -6737,12 +7875,21 @@ msgstr ""
msgid "MRDiff|Show full file"
msgstr ""
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr "無論身在何處,都能讓您團隊中的æ¯å€‹äººéƒ½æ›´æœ‰æ•ˆçŽ‡ã€‚GitLab Geo 建立了您 GitLab 主機的唯讀é¡åƒï¼Œæ‰€ä»¥æ‚¨å¯ä»¥ç¸®çŸ­è¤‡è£½å’ŒæŠ“å–大型版本庫的時間。"
+msgid "Make issue confidential."
+msgstr ""
+
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
msgstr "請確ä¿æ‚¨å·²ç¶“登入æ“有您è¦åŒ¯å…¥çš„專案的帳號。"
+msgid "Makes this issue confidential"
+msgstr ""
+
msgid "Manage"
msgstr ""
@@ -6750,7 +7897,7 @@ msgid "Manage Git repositories with fine-grained access controls that keep your
msgstr "使用細粒度的存å–æŽ§åˆ¶ä¾†ç®¡ç† Git 版本庫以確ä¿æ‚¨çš„程å¼ç¢¼å®‰å…¨ã€‚執行程å¼ç¢¼å¯©é–±ä¸¦å¢žå¼·èˆ‡åˆä½µè«‹æ±‚çš„å”作。æ¯å€‹å°ˆæ¡ˆé‚„å¯ä»¥æœ‰è­°é¡Œè¿½è¹¤å’Œ Wiki。"
msgid "Manage Web IDE features"
-msgstr "ç®¡ç† Web IDE 功能"
+msgstr "管ç†ç¶²é  IDE 功能"
msgid "Manage access"
msgstr "管ç†å­˜å–"
@@ -6803,8 +7950,17 @@ msgstr "三月"
msgid "March"
msgstr "三月"
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark comment as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
msgid "Mark todo as done"
-msgstr "標記「å³å°‡å®Œæˆã€ç‚ºå®Œæˆã€‚"
+msgstr "將待辦事項標記為已完æˆ"
msgid "Markdown"
msgstr ""
@@ -6815,6 +7971,15 @@ msgstr ""
msgid "Markdown enabled"
msgstr "已啟用 Markdown"
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks todo as done."
+msgstr "將待辦事項標記為已完æˆã€‚"
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
msgid "Maven Metadata"
msgstr "Maven 詮釋資料"
@@ -6839,6 +8004,9 @@ msgstr ""
msgid "Maximum job timeout"
msgstr "最大工作逾時"
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
msgid "Maximum number of mirrors that can be synchronizing at the same time."
msgstr ""
@@ -6869,6 +8037,9 @@ msgstr ""
msgid "Members of <strong>%{project_name}</strong>"
msgstr ""
+msgid "Merge"
+msgstr ""
+
msgid "Merge Request"
msgstr "åˆä½µè«‹æ±‚"
@@ -6881,15 +8052,9 @@ msgstr "åˆä½µè«‹æ±‚"
msgid "Merge Requests created"
msgstr "已建立åˆä½µè«‹æ±‚"
-msgid "Merge commit"
-msgstr ""
-
msgid "Merge commit message"
msgstr ""
-msgid "Merge commit with semi-linear history"
-msgstr ""
-
msgid "Merge events"
msgstr "åˆä½µäº‹ä»¶"
@@ -6899,12 +8064,6 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
-msgid "Merge method"
-msgstr ""
-
-msgid "Merge pipelines will try to validate the post-merge result prior to merging"
-msgstr ""
-
msgid "Merge request"
msgstr "åˆä½µè«‹æ±‚"
@@ -6923,6 +8082,30 @@ msgstr "「åˆä½µè«‹æ±‚ã€æ˜¯ä¸€å€‹è®“其他人æ出變更建議並討論的地
msgid "Merge when pipeline succeeds"
msgstr ""
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
msgid "MergeRequests|Add a reply"
msgstr ""
@@ -6941,6 +8124,9 @@ msgstr ""
msgid "MergeRequests|Discussion will be unresolved"
msgstr ""
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
msgid "MergeRequests|Jump to next unresolved discussion"
msgstr ""
@@ -6953,6 +8139,9 @@ msgstr "çµæŸè©²è¨Žè«–,並為它å¦å»ºè­°é¡Œã€‚"
msgid "MergeRequests|Saving the comment failed"
msgstr "儲存留言失敗"
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
msgid "MergeRequests|Toggle comments for this file"
msgstr "切æ›æ­¤æª”案的註釋"
@@ -6986,8 +8175,8 @@ msgstr "%{paragraphStart} %{timeDifferenceMinutes} 修改了 %{descriptionChange
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
-msgid "MergeRequest|Filter files"
-msgstr "篩é¸æª”案"
+msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
+msgstr ""
msgid "MergeRequest|No files found"
msgstr "沒有找到任何檔案"
@@ -7001,6 +8190,12 @@ msgstr ""
msgid "Messages"
msgstr "訊æ¯"
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
msgid "Metrics"
msgstr "指標"
@@ -7016,8 +8211,11 @@ msgstr "指標和分æž"
msgid "Metrics for environment"
msgstr ""
+msgid "Metrics|Add metric"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
-msgstr "檢視有關部署到環境的 CI / CD 檔案。"
+msgstr "檢視有關佈署到環境的 CI / CD 檔案。"
msgid "Metrics|Create metric"
msgstr "建立指標"
@@ -7055,9 +8253,6 @@ msgstr "建立指標"
msgid "Metrics|No deployed environments"
msgstr "沒有已經佈署的環境"
-msgid "Metrics|Not enough data to display"
-msgstr ""
-
msgid "Metrics|PromQL query is valid"
msgstr ""
@@ -7071,10 +8266,10 @@ msgid "Metrics|There was an error fetching the environments data, please try aga
msgstr "å–得環境資訊時發生錯誤,請é‡è©¦ã€‚"
msgid "Metrics|There was an error getting deployment information."
-msgstr "å–得部署資訊時發生錯誤。"
+msgstr "å–得佈署資訊時發生錯誤。"
msgid "Metrics|There was an error getting environments information."
-msgstr "å–得部署資訊時發生錯誤。"
+msgstr "å–得佈署資訊時發生錯誤。"
msgid "Metrics|There was an error trying to validate your query"
msgstr ""
@@ -7083,7 +8278,7 @@ msgid "Metrics|There was an error while retrieving metrics"
msgstr "檢索度é‡æ¨™æº–時出錯"
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
-msgstr "來自 Prometheus 節點的éžé æœŸéƒ¨å±¬è³‡æ–™å›žæ‡‰"
+msgstr "來自 Prometheus 節點的éžé æœŸä½ˆç½²è³‡æ–™å›žæ‡‰"
msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
msgstr "來自 Prometheus 節點的éžé æœŸæŒ‡æ¨™è³‡æ–™å›žæ‡‰"
@@ -7103,9 +8298,21 @@ msgstr "Y 軸標籤"
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
msgstr ""
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
msgid "Metrics|e.g. Throughput"
msgstr "例如:Throughput"
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
@@ -7130,9 +8337,6 @@ msgstr "ä½ å³å°‡æ°¸ä¹…刪除里程碑 %{milestoneTitle} 並將其中 %{issuesWi
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr "ä½ å³å°‡æ°¸ä¹…刪除里程碑 %{milestoneTitle}。此里程碑裡目å‰æ²’有任何議題或åˆä½µè«‹æ±‚。"
-msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr "<p>%{milestonePromotion}</p> %{finalWarning}"
-
msgid "Milestones|Delete milestone"
msgstr "刪除里程碑"
@@ -7151,8 +8355,8 @@ msgstr "å°‡ %{milestoneTitle} æå‡æˆç¾¤çµ„里程碑?"
msgid "Milestones|Promote Milestone"
msgstr "æå‡é‡Œç¨‹ç¢‘"
-msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
-msgstr "æå‡ %{milestone} 後,所有 %{groupName} 裡的專案都å¯ä»¥ä½¿ç”¨è©²é‡Œç¨‹ç¢‘。如果已經有相åŒå稱的里程碑將會兩者åˆä½µã€‚ "
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
+msgstr ""
msgid "Milestones|This action cannot be reversed."
msgstr "這動作無法復原。"
@@ -7160,6 +8364,15 @@ msgstr "這動作無法復原。"
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
msgid "Mirror a repository"
msgstr "å°ä¸€å€‹ç‰ˆæœ¬åº«é¡åƒ"
@@ -7176,11 +8389,23 @@ msgid "Mirrored repositories"
msgstr "å·²é¡åƒçš„版本庫"
msgid "Mirroring repositories"
-msgstr "正在é¡åƒç‰ˆæœ¬åº«"
+msgstr "é¡åƒç‰ˆæœ¬åº«"
msgid "Mirroring settings were successfully updated."
msgstr ""
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "新增 SSH 金鑰"
@@ -7197,10 +8422,10 @@ msgid "Modify commit messages"
msgstr ""
msgid "Modify merge commit"
-msgstr ""
+msgstr "修改åˆä½µæ交"
msgid "Monday"
-msgstr ""
+msgstr "星期一"
msgid "Monitor your errors by integrating with Sentry"
msgstr ""
@@ -7241,6 +8466,24 @@ msgstr "移動"
msgid "Move issue"
msgstr "移動議題"
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
msgid "Multiple issue boards"
msgstr "多個議題看æ¿"
@@ -7253,6 +8496,9 @@ msgstr ""
msgid "Name"
msgstr "å稱"
+msgid "Name has already been taken"
+msgstr ""
+
msgid "Name new label"
msgstr "命å新標籤"
@@ -7315,7 +8561,7 @@ msgid "New Label"
msgstr "新增標籤"
msgid "New Milestone"
-msgstr ""
+msgstr "新建里程碑"
msgid "New Pages Domain"
msgstr ""
@@ -7345,7 +8591,10 @@ msgid "New environment"
msgstr ""
msgid "New epic"
-msgstr "æ–°çš„ Epic"
+msgstr "æ–°å²è©©"
+
+msgid "New epic title"
+msgstr ""
msgid "New file"
msgstr "新增檔案"
@@ -7369,6 +8618,9 @@ msgid "New merge request"
msgstr "新增åˆä½µè«‹æ±‚"
msgid "New milestone"
+msgstr "新建里程碑"
+
+msgid "New password"
msgstr ""
msgid "New pipelines will cancel older, pending pipelines on the same branch"
@@ -7401,6 +8653,12 @@ msgstr "新增…"
msgid "Newly registered users will by default be external"
msgstr ""
+msgid "Next"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
msgid "No"
msgstr "å¦"
@@ -7410,12 +8668,21 @@ msgstr ""
msgid "No Label"
msgstr "沒有標籤"
+msgid "No Milestone"
+msgstr ""
+
msgid "No Tag"
msgstr ""
msgid "No activities found"
msgstr ""
+msgid "No available namespaces to fork the project."
+msgstr ""
+
+msgid "No blocking merge requests "
+msgstr ""
+
msgid "No branches found"
msgstr "找ä¸åˆ°åˆ†æ”¯"
@@ -7431,6 +8698,9 @@ msgstr "無法連線到 Gitaly 伺æœå™¨ï¼Œè«‹æª¢æŸ¥æ—¥èªŒè¨˜éŒ„ï¼"
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr "此專案目å‰æ²’有儲存容器映åƒï¼Œè«‹ä¾ç…§ä¸Šè¿°èªªæ˜Žæ–°å¢žå®¹å™¨æ˜ åƒã€‚"
+msgid "No contributions"
+msgstr ""
+
msgid "No contributions were found"
msgstr "找ä¸åˆ°è²¢ç»"
@@ -7441,7 +8711,7 @@ msgid "No details available"
msgstr ""
msgid "No due date"
-msgstr "沒有到期時間"
+msgstr "沒有截止日期"
msgid "No errors to display."
msgstr ""
@@ -7455,6 +8725,9 @@ msgstr "未é¸æ“‡ä»»ä½•æª”案"
msgid "No file selected"
msgstr ""
+msgid "No files"
+msgstr ""
+
msgid "No files found."
msgstr "找ä¸åˆ°ä»»ä½•æª”案"
@@ -7476,9 +8749,6 @@ msgstr ""
msgid "No matching results"
msgstr ""
-msgid "No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "No merge requests for the selected time period."
msgstr "é¸å–的時間範åœä¸­æ²’有åˆä½µè«‹æ±‚。"
@@ -7489,11 +8759,14 @@ msgid "No messages were logged"
msgstr "沒有訊æ¯è¢«è¨˜éŒ„"
msgid "No milestones to show"
-msgstr ""
+msgstr "沒有è¦é¡¯ç¤ºçš„里程碑"
msgid "No other labels with such name or description"
msgstr "沒有其他具有此類å稱或æ述的標籤"
+msgid "No parent group"
+msgstr ""
+
msgid "No preview for this file type"
msgstr ""
@@ -7521,6 +8794,12 @@ msgstr ""
msgid "No, directly import the existing email addresses and usernames."
msgstr "ä¸ï¼Œç›´æŽ¥åŒ¯å…¥ç¾æœ‰çš„é›»å­éƒµä»¶ä½å€å’Œä½¿ç”¨è€…å稱。"
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
msgid "Nodes"
msgstr "節點"
@@ -7569,6 +8848,9 @@ msgstr "注æ„:請考慮讓您的 GitLab 管ç†å“¡è¨­å®š %{github_integration_
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr "注æ„:請考慮讓您的 GitLab 管ç†å“¡è¨­å®š %{github_integration_link},這將å…許使用者é€éŽ GitHub 登入並å…許匯入版本庫而ä¸ç”Ÿæˆå€‹äººå­˜å–憑證。"
+msgid "NoteForm|Note"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "您確定è¦å–消建立此留言嗎?"
@@ -7584,6 +8866,12 @@ msgstr "åªé¡¯ç¤ºç•™è¨€"
msgid "Notes|Show history only"
msgstr "åªé¡¯ç¤ºæ­·å²ç´€éŒ„"
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
msgid "Notification events"
msgstr "通知事件"
@@ -7593,6 +8881,9 @@ msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
+msgid "Notification settings saved"
+msgstr ""
+
msgid "NotificationEvent|Close issue"
msgstr "關閉議題"
@@ -7647,6 +8938,9 @@ msgstr "åƒèˆ‡"
msgid "NotificationLevel|Watch"
msgstr "關注"
+msgid "NotificationSetting|Custom"
+msgstr ""
+
msgid "Notifications"
msgstr "通知"
@@ -7662,6 +8956,12 @@ msgstr "å一月"
msgid "November"
msgstr "å一月"
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
msgid "OK"
msgstr "確定"
@@ -7677,8 +8977,14 @@ msgstr "å月"
msgid "OfSearchInADropdown|Filter"
msgstr "篩é¸"
-msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
-msgstr "一旦匯入,就å¯ä»¥é€éŽ SSH é¡åƒç‰ˆæœ¬åº«ã€‚閱讀 %{ssh_link} 以了解更多資訊"
+msgid "Ok let's go"
+msgstr ""
+
+msgid "Onboarding"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
+msgstr ""
msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
msgstr ""
@@ -7699,13 +9005,13 @@ msgstr "您的一個或多個 Bitbucket 專案無法直接匯入 GitLab,因為
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "您的一個或多個 Google Code 專案無法直接匯入 GitLab,因為它們使用 Subversion 或 Mercurial 進行版本控管,而ä¸æ˜¯Git。"
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
+msgstr ""
+
msgid "Only admins"
msgstr "僅管ç†å“¡"
-msgid "Only allow merge requests to be merged if all discussions are resolved"
-msgstr ""
-
-msgid "Only allow merge requests to be merged if the pipeline succeeds"
+msgid "Only admins can delete project"
msgstr ""
msgid "Only mirror protected branches"
@@ -7723,6 +9029,9 @@ msgstr "僅群組æˆå“¡æ‰èƒ½ç•™è¨€ã€‚"
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only these extensions are supported: %{extension_list}"
+msgstr ""
+
msgid "Oops, are you sure?"
msgstr "喔喔…確定?"
@@ -7745,7 +9054,7 @@ msgid "Open projects"
msgstr "打開專案"
msgid "Open raw"
-msgstr ""
+msgstr "打開原文件"
msgid "Open sidebar"
msgstr "é–‹å•Ÿå´é‚Šæ¬„"
@@ -7768,6 +9077,12 @@ msgstr "開啟時間"
msgid "Opens in a new window"
msgstr "在新視窗開啟"
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
msgid "Operations"
msgstr "動作"
@@ -7792,9 +9107,6 @@ msgstr ""
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr "維é‹å„€è¡¨æ¿æä¾›æ¯å€‹å°ˆæ¡ˆçš„執行狀æ³æ‘˜è¦ï¼ŒåŒ…括管線和警示狀態。"
-msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for public projects, and private projects in groups with a Gold plan."
-msgstr ""
-
msgid "Optional"
msgstr ""
@@ -7816,6 +9128,9 @@ msgstr "其他標籤"
msgid "Other information"
msgstr "其他資訊"
+msgid "Other merge requests block this MR"
+msgstr ""
+
msgid "Outbound requests"
msgstr "Outbound 請求"
@@ -7825,6 +9140,12 @@ msgstr "概覽"
msgid "Overwrite diverged branches"
msgstr "覆寫有分歧的分支"
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
msgid "Owner"
msgstr "所有者"
@@ -7852,6 +9173,9 @@ msgstr ""
msgid "Pages Domains"
msgstr ""
+msgid "Pages getting started guide"
+msgstr ""
+
msgid "Pagination|Last »"
msgstr "æœ€æœ«é  Â»"
@@ -7873,9 +9197,21 @@ msgstr "åˆä½µè«‹æ±‚變更的部分"
msgid "Password"
msgstr "密碼"
+msgid "Password (optional)"
+msgstr ""
+
msgid "Password authentication is unavailable."
msgstr ""
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please login with it"
+msgstr ""
+
msgid "Past due"
msgstr ""
@@ -7883,13 +9219,13 @@ msgid "Paste a machine public key here. Read more about how to generate it %{lin
msgstr ""
msgid "Paste epic link"
-msgstr ""
+msgstr "貼上å²è©©é€£çµ"
msgid "Paste issue link"
msgstr ""
-msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
-msgstr "貼上您的SSH公鑰,通常放置在 '~/.ssh/id_rsa.pub',並以 'ssh-rsa' 開頭。ä¸è¦ä½¿ç”¨æ‚¨çš„SSHç§é‘°ã€‚"
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
msgid "Path"
msgstr ""
@@ -7915,6 +9251,9 @@ msgstr "等待處ç†"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr "未經許å¯çš„使用者將無法收到通知也無法留言。"
+msgid "People without permission will never get a notification."
+msgstr ""
+
msgid "Perform advanced options such as changing path, transferring, or removing the group."
msgstr "執行進階é¸é …,例如變更路徑ã€å‚³è¼¸æˆ–移除群組。"
@@ -7936,12 +9275,27 @@ msgstr "個人訪å•æ†‘è­‰"
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
msgstr ""
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
msgid "Pick a name"
msgstr ""
+msgid "Pin code"
+msgstr ""
+
msgid "Pipeline"
msgstr "管線"
+msgid "Pipeline ID (IID)"
+msgstr ""
+
msgid "Pipeline Schedule"
msgstr "排程管線"
@@ -8020,6 +9374,9 @@ msgstr "管線"
msgid "Pipelines charts"
msgstr "管線圖表"
+msgid "Pipelines emails"
+msgstr ""
+
msgid "Pipelines for last month"
msgstr "上個月的管線"
@@ -8029,10 +9386,13 @@ msgstr "上週的管線"
msgid "Pipelines for last year"
msgstr "去年的管線"
-msgid "Pipelines need to be configured to enable this feature."
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgid "Pipelines| to purchase more minutes."
+msgstr ""
+
+msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
@@ -8045,7 +9405,7 @@ msgid "Pipelines|Clear Runner Caches"
msgstr "清除執行器快å–"
msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
-msgstr "ä¸é–“æ–·æ•´åˆå¯ä»¥é€éŽè‡ªå‹•æ¸¬è©¦ä¾†å¹«åŠ©æ•æ‰éŒ¯èª¤ï¼Œè€ŒæŒçºŒéƒ¨ç½²å¯ä»¥å¹«åŠ©ä½ äº¤ä»˜ç”¢å“至正å¼ç’°å¢ƒã€‚"
+msgstr "ä¸é–“æ–·æ•´åˆå¯ä»¥é€éŽè‡ªå‹•æ¸¬è©¦ä¾†å¹«åŠ©æ•æ‰éŒ¯èª¤ï¼Œè€ŒæŒçºŒä½ˆç½²å¯ä»¥å¹«åŠ©ä½ äº¤ä»˜ç”¢å“至正å¼ç’°å¢ƒã€‚"
msgid "Pipelines|Get started with Pipelines"
msgstr "嘗試管線功能"
@@ -8053,6 +9413,9 @@ msgstr "嘗試管線功能"
msgid "Pipelines|Loading Pipelines"
msgstr "讀å–管線"
+msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "專案快å–已經æˆåŠŸé‡è¨­ã€‚"
@@ -8113,6 +9476,9 @@ msgstr "åœæ­¢ç®¡ç·š"
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr "åœæ­¢ç®¡ç·š #%{pipelineId}?"
+msgid "Pipeline|Triggerer"
+msgstr ""
+
msgid "Pipeline|Variables"
msgstr "變數"
@@ -8143,6 +9509,15 @@ msgstr "與階段"
msgid "Pipeline|with stages"
msgstr "與階段"
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
msgid "Plain diff"
msgstr "本文差異"
@@ -8152,12 +9527,30 @@ msgstr "PlantUML"
msgid "Play"
msgstr "執行"
+msgid "Play all manual"
+msgstr ""
+
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr "在繼續之å‰ï¼Œè«‹åŒæ„æœå‹™æ¢æ¬¾"
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
msgid "Please choose a group URL with no special characters."
msgstr "è«‹é¸æ“‡æ²’有特殊符號的群組網å€ã€‚"
@@ -8188,6 +9581,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter or upload a license."
+msgstr ""
+
msgid "Please fill in a descriptive name for your group."
msgstr "請為您的群組填寫æ述性å稱。"
@@ -8200,6 +9596,15 @@ msgstr "請注æ„,這個應用程å¼ä¸æ˜¯ç”± GitLab 所æ供的,您應該å
msgid "Please provide a name"
msgstr ""
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
msgid "Please select a group."
msgstr ""
@@ -8221,8 +9626,8 @@ msgstr "è«‹å†è©¦ä¸€æ¬¡"
msgid "Please upgrade PostgreSQL to version 9.6 or greater. The status of the replication cannot be determined reliably with the current version."
msgstr ""
-msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
-msgstr "è«‹ä½¿ç”¨æ­¤è¡¨å–®å‘ GitLab 報告建立垃圾議題ã€ç•™è¨€æˆ–有ä¸ç•¶è¡Œç‚ºçš„使用者。"
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
+msgstr ""
msgid "Please wait a moment, this page will automatically refresh when ready."
msgstr ""
@@ -8239,12 +9644,66 @@ msgstr "å好設定"
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (100%%) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Default dashboard"
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr "導航主題"
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
msgid "Press Enter or click to search"
msgstr "按下 Enter 或點é¸ä»¥æœå°‹"
@@ -8260,12 +9719,18 @@ msgstr ""
msgid "Preview"
msgstr "é è¦½"
+msgid "Preview Markdown"
+msgstr ""
+
msgid "Preview changes"
msgstr ""
msgid "Preview payload"
msgstr "é è¦½æœ‰æ•ˆè² è¼‰"
+msgid "Previous Artifacts"
+msgstr ""
+
msgid "Primary"
msgstr "主è¦"
@@ -8293,15 +9758,24 @@ msgstr "ç§äººå°ˆæ¡ˆ - 群組與å­å°ˆæ¡ˆåªèƒ½è¢«ç¾¤çµ„æˆå“¡æª¢è¦–。"
msgid "Private group(s)"
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr "å¯ä»¥åœ¨æ‚¨çš„個人命å空間中建立ç§äººå°ˆæ¡ˆ:"
+msgid "Proceed"
+msgstr ""
+
msgid "Profile"
msgstr "個人資料"
msgid "Profile Settings"
msgstr "個人資料設定"
+msgid "ProfileSession|on"
+msgstr ""
+
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
msgstr "ä½ å³å°‡æ°¸ä¹…刪除 %{yourAccount},以åŠèˆ‡æ‚¨çš„帳號相關的所有議題ã€åˆä½µè«‹æ±‚åŠç¾¤çµ„ã€‚ä¸€ä½†ç¢ºèª %{deleteAccount},他就無法復原或復原。"
@@ -8332,6 +9806,9 @@ msgstr "è£å‰ªé ­è²¼"
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr "將會移除頭貼,確定?"
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr "變更使用者å稱"
@@ -8353,6 +9830,9 @@ msgstr "清除狀態"
msgid "Profiles|Click on icon to activate signin with one of the following services"
msgstr ""
+msgid "Profiles|Commit email"
+msgstr ""
+
msgid "Profiles|Connect"
msgstr ""
@@ -8365,6 +9845,9 @@ msgstr "ç›®å‰è·¯å¾‘:%{path}"
msgid "Profiles|Current status"
msgstr "ç›®å‰ç‹€æ…‹"
+msgid "Profiles|Default notification email"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr "刪除帳號"
@@ -8392,6 +9875,18 @@ msgstr "編輯個人檔案"
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -8401,9 +9896,15 @@ msgstr "密碼無效"
msgid "Profiles|Invalid username"
msgstr "使用者å稱無效"
+msgid "Profiles|Key"
+msgstr ""
+
msgid "Profiles|Learn more"
msgstr "了解更多"
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr "ç§äººè²¢ç»"
@@ -8413,18 +9914,33 @@ msgstr "主è¦è¨­å®š"
msgid "Profiles|No file chosen"
msgstr "未é¸æ“‡æª”案"
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr "ä½ç½®"
msgid "Profiles|Position and size your new avatar"
msgstr "定ä½ä¸¦èª¿æ•´æ‚¨æ–°é ­è²¼çš„大å°"
+msgid "Profiles|Primary email"
+msgstr ""
+
msgid "Profiles|Private contributions"
msgstr "ç§äººè²¢ç»"
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr "公開頭貼"
+msgid "Profiles|Public email"
+msgstr ""
+
msgid "Profiles|Remove avatar"
msgstr "移除頭貼"
@@ -8443,9 +9959,6 @@ msgstr ""
msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "檔案必須è¦åœ¨ 200KB 以下。"
-msgid "Profiles|There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
-
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "這看起來ä¸åƒæ˜¯ SSH 公鑰,您確定è¦å¢žåŠ å®ƒå—Žï¼Ÿ"
@@ -8461,14 +9974,17 @@ msgstr "這個表情符號和訊æ¯å°‡é¡¯ç¤ºæ–¼æ‚¨çš„個人資料和整個工作
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "輸入 %{confirmationValue} 確èªï¼š"
-msgid "Profiles|Typically starts with \"ssh-rsa …\""
-msgstr "通常以 \"ssh-rsa …\" 起頭"
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
+msgstr ""
msgid "Profiles|Update profile settings"
msgstr "更新個人資料設定"
@@ -8482,6 +9998,9 @@ msgstr "上傳新的頭åƒ"
msgid "Profiles|Use a private email - %{email}"
msgstr "使用ç§äººé›»å­éƒµä»¶ - %{email}"
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr "使用者å稱變更失敗 - %{message}"
@@ -8503,6 +10022,9 @@ msgstr "ä½ å¯ä»¥åœ¨é€™è£¡ä¿®æ”¹ä½ çš„é ­åƒ"
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr "ä½ å¯ä»¥åœ¨é€™è£¡ä¿®æ”¹ä½ çš„é ­åƒæˆ–åˆªé™¤ä½ çš„é ­æ€§ä¸¦å¾©åŽŸæˆ %{gravatar_link}"
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr "ä½ å¯ä»¥åœ¨é€™è£¡ä¸Šå‚³ä½ çš„é ­åƒ"
@@ -8596,6 +10118,9 @@ msgstr ""
msgid "Project avatar"
msgstr "專案大頭貼"
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
msgid "Project configuration, including services"
msgstr ""
@@ -8641,6 +10166,9 @@ msgstr ""
msgid "Project:"
msgstr ""
+msgid "Project: %{name}"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "訂閱"
@@ -8692,6 +10220,24 @@ msgstr "您必須登入之後æ‰èƒ½æ”¶è—專案"
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "專案編號:%{project_id}"
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow merge trains"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
msgid "ProjectSettings|Badges"
msgstr "徵章"
@@ -8701,18 +10247,60 @@ msgstr "è¯çµ¡ç®¡ç†å“¡ä»¥è®Šæ›´é€™å€‹è¨­å®šã€‚"
msgid "ProjectSettings|Customize your project badges."
msgstr "自訂您專案的徵章。"
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
msgid "ProjectSettings|Failed to protect the tag"
msgstr "無法ä¿è­·æ¨™ç±¤"
msgid "ProjectSettings|Failed to update tag!"
msgstr "無法更新標籤ï¼"
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
msgid "ProjectSettings|Learn more about badges."
msgstr "關於徵章的更多資訊。"
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge pipelines will try to validate the post-merge result prior to merging"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "åªæœ‰å·²ç°½ç½²çš„變更æ‰èƒ½æŽ¨é€åˆ°ç‰ˆæœ¬åº«ã€‚"
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
msgstr "此設定已經套用於伺æœå™¨å±¤ç´šï¼Œä¸¦ä¸”å¯è¢«ç®¡ç†å“¡è¦†å¯«ã€‚"
@@ -8722,12 +10310,72 @@ msgstr "此設定已經套用於伺æœå™¨ç´šåˆ¥ï¼Œä½†å·²ç¶“在這個專案被覆
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr "此設定將套用於所有專案,除éžè¢«ç®¡ç†å“¡è¦†å¯«ã€‚"
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr "使用者åªèƒ½é€éŽä»–們自己通éŽé©—證的電å­ä¿¡ç®±ä¹‹ä¸€æ交,æ‰èƒ½æŽ¨é€æ交到這個版本庫。"
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
msgid "Projects"
msgstr "專案"
+msgid "Projects (%{count})"
+msgstr ""
+
msgid "Projects Successfully Retrieved"
msgstr ""
@@ -8810,7 +10458,7 @@ msgid "PrometheusService|Auto configuration"
msgstr "自動設定"
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
-msgstr "在你的群集上自動部署和設定 Prometheus 以監控您的專案環境"
+msgstr "在你的群集上自動佈署和設定 Prometheus 以監控您的專案環境"
msgid "PrometheusService|Common metrics"
msgstr "常見指標"
@@ -8858,7 +10506,7 @@ msgid "PrometheusService|Prometheus is being automatically managed on your clust
msgstr "Prometheus 正在自動管ç†æ‚¨çš„å¢é›†"
msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
-msgstr "這些指標åªæœƒåœ¨ä½ ç¬¬ä¸€æ¬¡éƒ¨å±¬ç’°å¢ƒæ™‚æ‰æœƒç›£æŽ§"
+msgstr "這些指標åªæœƒåœ¨ä½ ç¬¬ä¸€æ¬¡ä½ˆç½²ç’°å¢ƒæ™‚æ‰æœƒç›£æŽ§"
msgid "PrometheusService|Time-series monitoring service"
msgstr "時間åºåˆ—監控æœå‹™"
@@ -8870,13 +10518,13 @@ msgid "PrometheusService|To enable the installation of Prometheus on your cluste
msgstr "如果å…è¨±å®‰è£ Prometheus 在您的群集上,請å–消下é¢çš„手動設定"
msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
-msgstr "等您首次部署到環境後以查詢常用指標"
+msgstr "等您首次佈署到環境後以查詢常用指標"
msgid "Promote"
msgstr "æå‡"
msgid "Promote these project milestones into a group milestone."
-msgstr "將這些專案里程碑æå‡æˆä¸€å€‹ç¾¤çµ„里程碑。"
+msgstr "將這些專案里程碑æå‡æˆç¾¤çµ„里程碑。"
msgid "Promote to Group Milestone"
msgstr "æå‡è‡³ç¾¤çµ„里程碑"
@@ -8884,6 +10532,15 @@ msgstr "æå‡è‡³ç¾¤çµ„里程碑"
msgid "Promote to group label"
msgstr "æå‡è‡³ç¾¤çµ„標籤"
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
msgid "Promotions|Don't show me this again"
msgstr "ä¸è¦å†é¡¯ç¤º"
@@ -8902,36 +10559,48 @@ msgstr ""
msgid "Protected"
msgstr "å—ä¿è­·"
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
msgid "Protected Environments"
msgstr "å—ä¿è­·ç’°å¢ƒ"
+msgid "Protected Tag"
+msgstr ""
+
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} 將開放開發者的寫入權é™ï¼Œç¢ºèªï¼Ÿ"
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "å…許佈署"
-msgid "ProtectedEnvironment|Choose who is allowed to deploy"
-msgstr "é¸æ“‡å…許佈署的æˆå“¡"
-
msgid "ProtectedEnvironment|Environment"
msgstr "環境"
msgid "ProtectedEnvironment|Protect"
msgstr "ä¿è­·"
-msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr "ä¿è­·ç’°å¢ƒæ˜¯ç‚ºäº†è¦é™åˆ¶èƒ½åŸ·è¡Œä½ˆç½²çš„æˆå“¡ã€‚"
-
msgid "ProtectedEnvironment|Protect an environment"
msgstr "ä¿è­·ç’°å¢ƒ"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr "ä¿è­·ç’°å¢ƒ (%{protected_environments_count})"
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
msgid "ProtectedEnvironment|Select an environment"
msgstr "é¸æ“‡ç’°å¢ƒ"
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
msgstr "ç›®å‰æ²’有å—ä¿è­·çš„環境,請從下方表格é¸æ“‡è¦ä¿è­·çš„環境。"
@@ -8980,9 +10649,15 @@ msgstr "拉å–"
msgid "Push"
msgstr "推é€"
+msgid "Push Rule updated successfully."
+msgstr ""
+
msgid "Push Rules"
msgstr "推é€è¦å‰‡"
+msgid "Push Rules updated successfully."
+msgstr ""
+
msgid "Push an existing Git repository"
msgstr ""
@@ -9007,12 +10682,54 @@ msgstr "推é€çš„"
msgid "Pushes"
msgstr "推é€"
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
msgid "Quarters"
msgstr "季度"
msgid "Query"
msgstr ""
+msgid "Query is valid"
+msgstr ""
+
msgid "Quick actions can be used in the issues description and comment boxes."
msgstr "「快速æ“作ã€èƒ½ç”¨æ–¼è­°é¡Œæ述和留言框。"
@@ -9037,15 +10754,24 @@ msgstr "å³æ™‚功能"
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
+msgid "Receive notifications about your own activity"
+msgstr ""
+
msgid "Recent"
msgstr ""
msgid "Recent Project Activity"
msgstr ""
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
msgid "Recent searches"
msgstr "最近æœå°‹"
+msgid "Recovery Codes"
+msgstr ""
+
msgid "Redirect to SAML provider to test configuration"
msgstr "é‡æ–°å°Žå‘到 SAML 供應商,以測試設定"
@@ -9059,24 +10785,45 @@ msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] "æ¯ %d é‡æ–°æ•´ç†ä»¥æª¢è¦–更新的狀態…"
+msgid "Regenerate instance ID"
+msgstr ""
+
msgid "Regenerate key"
msgstr "é‡æ–°ç”¢ç”Ÿé‡‘é‘°"
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
msgid "Regex pattern"
msgstr "æ­£è¦è¡¨ç¤ºå¼"
+msgid "Register"
+msgstr ""
+
msgid "Register / Sign In"
msgstr "註冊 / 登入"
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
msgid "Register U2F device"
msgstr ""
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr "註冊ã€ä¸¦è§€å¯Ÿæ‚¨åœ¨é€™å€‹ç¾¤çµ„的執行器。"
msgid "Register and see your runners for this project."
msgstr "註冊ã€ä¸¦è§€å¯Ÿæ‚¨åœ¨é€™å€‹å°ˆæ¡ˆçš„執行器。"
+msgid "Register with two-factor app"
+msgstr ""
+
msgid "Registration"
msgstr ""
@@ -9087,7 +10834,7 @@ msgid "Related Commits"
msgstr "相關æ交"
msgid "Related Deployed Jobs"
-msgstr "相關部署作業"
+msgstr "相關佈署作業"
msgid "Related Issues"
msgstr "相關議題"
@@ -9101,6 +10848,9 @@ msgstr "相關åˆä½µè«‹æ±‚"
msgid "Related Merged Requests"
msgstr "相關已åˆä½µè«‹æ±‚"
+msgid "Related issues"
+msgstr "相關議題"
+
msgid "Related merge requests"
msgstr "相關的åˆä½µè«‹æ±‚"
@@ -9113,6 +10863,9 @@ msgstr ""
msgid "Remind later"
msgstr "ç¨å¾Œæ醒"
+msgid "Remote object has no absolute path."
+msgstr ""
+
msgid "Remove"
msgstr "移除"
@@ -9122,7 +10875,10 @@ msgstr "移除執行器"
msgid "Remove all approvals in a merge request when new commits are pushed to its source branch"
msgstr ""
-msgid "Remove approver"
+msgid "Remove all or specific assignee(s)"
+msgstr "移除全部或特定指派人"
+
+msgid "Remove all or specific label(s)"
msgstr ""
msgid "Remove approvers"
@@ -9131,25 +10887,37 @@ msgstr ""
msgid "Remove approvers?"
msgstr ""
+msgid "Remove assignee"
+msgstr "移除指派人"
+
msgid "Remove avatar"
msgstr "移除大頭貼"
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
msgid "Remove fork relationship"
msgstr ""
msgid "Remove group"
msgstr "刪除群組"
+msgid "Remove milestone"
+msgstr ""
+
msgid "Remove priority"
msgstr "刪除優先權"
msgid "Remove project"
msgstr "移除專案"
-msgid "Remove this label? Are you sure?"
+msgid "Remove spent time"
msgstr ""
-msgid "Remove this label? This will affect all projects within the group. Are you sure?"
+msgid "Remove time estimate"
msgstr ""
msgid "Removed"
@@ -9164,6 +10932,24 @@ msgstr "刪除的群組將無法復原ï¼"
msgid "Removed projects cannot be restored!"
msgstr ""
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
msgid "Removing group will cause all child projects and resources to be removed."
msgstr "刪除群組將導致所有å­å°ˆæ¡ˆå’Œè³‡æºè¢«åˆªé™¤ã€‚"
@@ -9183,15 +10969,18 @@ msgid "Rename folder"
msgstr "é‡æ–°å‘½å資料夾"
msgid "Reopen epic"
-msgstr "é‡æ–°é–‹å•Ÿ Epic"
+msgstr "é‡æ–°é–‹å•Ÿå²è©©"
msgid "Reopen milestone"
-msgstr ""
+msgstr "é‡æ–°æ‰“開里程碑"
msgid "Repair authentication"
msgstr "修復èªè­‰"
msgid "Replace"
+msgstr "å–代"
+
+msgid "Replace all label(s)"
msgstr ""
msgid "Reply to comment"
@@ -9203,8 +10992,8 @@ msgstr "直接回復此電å­ä¿¡ç®±æˆ– %{view_it_on_gitlab}。"
msgid "Repo by URL"
msgstr "來自 URL 的版本庫"
-msgid "Report abuse to GitLab"
-msgstr "å‘ GitLab 回報濫用行為"
+msgid "Report abuse to admin"
+msgstr ""
msgid "Reporting"
msgstr "報告"
@@ -9218,6 +11007,9 @@ msgstr "æ“作"
msgid "Reports|Class"
msgstr "類別"
+msgid "Reports|Classname"
+msgstr ""
+
msgid "Reports|Confidence"
msgstr "ä¿¡ä»»"
@@ -9257,12 +11049,6 @@ msgstr "正在解æžæ¸¬è©¦æ‘˜è¦çµæžœ"
msgid "Reports|Vulnerability"
msgstr "風險"
-msgid "Reports|issue"
-msgstr ""
-
-msgid "Reports|merge request"
-msgstr ""
-
msgid "Reports|no changed test results"
msgstr "沒有變更的測試çµæžœ"
@@ -9317,13 +11103,22 @@ msgstr "è¦æ±‚所有使用者在訪å•GitLab時接å—æœå‹™æ¢æ¬¾å’Œéš±ç§æ”¿ç­–
msgid "Require approval from code owners"
msgstr ""
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
msgid "Requires approval from %{names}."
msgid_plural "Requires %{count} more approvals from %{names}."
-msgstr[0] ""
+msgstr[0] "從 %{names} éœ€è¦ %{count} 核准。"
msgid "Requires approval."
msgid_plural "Requires %d more approvals."
-msgstr[0] ""
+msgstr[0] "éœ€è¦ %d 個核准。"
+
+msgid "Resend confirmation email"
+msgstr ""
msgid "Resend invite"
msgstr ""
@@ -9364,6 +11159,15 @@ msgstr ""
msgid "Resolved all discussions."
msgstr ""
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
msgid "Response"
msgstr ""
@@ -9406,6 +11210,9 @@ msgstr "é‡è©¦æ­¤å·¥ä½œ"
msgid "Retry this job in order to create the necessary resources."
msgstr ""
+msgid "Retry update"
+msgstr ""
+
msgid "Retry verification"
msgstr "é‡è©¦é©—è­‰"
@@ -9443,8 +11250,14 @@ msgstr ""
msgid "Revoked personal access token %{personal_access_token_name}!"
msgstr ""
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
msgid "Roadmap"
-msgstr "開發è—圖"
+msgstr "路線圖"
msgid "Run CI/CD pipelines for external repositories"
msgstr "執行外部版本庫的 CI / CD 管線。"
@@ -9527,6 +11340,9 @@ msgstr "%{group_name} çš„ SAML SSO"
msgid "SAML for %{group_name}"
msgstr ""
+msgid "SSH Key"
+msgstr ""
+
msgid "SSH Keys"
msgstr "SSH 金鑰"
@@ -9536,6 +11352,9 @@ msgstr ""
msgid "SSH host keys"
msgstr "SSH 主機金鑰"
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
msgid "SSH public key"
msgstr "SSH 公鑰"
@@ -9543,7 +11362,7 @@ msgid "SSL Verification"
msgstr "SSL é©—è­‰"
msgid "Saturday"
-msgstr ""
+msgstr "星期六"
msgid "Save"
msgstr "儲存"
@@ -9551,6 +11370,9 @@ msgstr "儲存"
msgid "Save Changes"
msgstr ""
+msgid "Save anyway"
+msgstr ""
+
msgid "Save application"
msgstr "儲存應用程å¼"
@@ -9563,6 +11385,9 @@ msgstr "測試å‰å„²å­˜ä¿®æ”¹"
msgid "Save comment"
msgstr ""
+msgid "Save password"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "儲存排程管線"
@@ -9623,9 +11448,21 @@ msgstr "æœå°‹åˆ†æ”¯å’Œæ¨™ç±¤"
msgid "Search files"
msgstr "æœå°‹æª”案"
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
msgid "Search for projects, issues, etc."
msgstr "æœå°‹å°ˆæ¡ˆã€è­°é¡Œç­‰ç­‰"
+msgid "Search forks"
+msgstr ""
+
msgid "Search groups"
msgstr ""
@@ -9647,6 +11484,9 @@ msgstr "æœå°‹å°ˆæ¡ˆ"
msgid "Search projects"
msgstr "æœå°‹å°ˆæ¡ˆ"
+msgid "Search projects..."
+msgstr ""
+
msgid "Search users"
msgstr "æœå°‹ä½¿ç”¨è€…"
@@ -9722,9 +11562,6 @@ msgstr ""
msgid "Security Reports|More info"
msgstr "更多資訊"
-msgid "Security Reports|No Vulnerabilities"
-msgstr ""
-
msgid "Security Reports|There was an error creating the issue."
msgstr "建立議題時發生錯誤。"
@@ -9755,12 +11592,24 @@ msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr "安全儀表æ¿å°‡é¡¯ç¤ºæœ€æ–°çš„安全報告。用它來尋找和修補æ¼æ´žã€‚"
+msgid "SecurityDashboard|Confidence"
+msgstr ""
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr "監控程å¼ç¢¼ä¸­çš„æ¼æ´ž"
msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr "觸發了管線 %{pipelineLink}"
+msgid "SecurityDashboard|Project"
+msgstr ""
+
+msgid "SecurityDashboard|Report type"
+msgstr ""
+
+msgid "SecurityDashboard|Severity"
+msgstr ""
+
msgid "See metrics"
msgstr ""
@@ -9773,6 +11622,12 @@ msgstr "é¸æ“‡"
msgid "Select Archive Format"
msgstr "é¸æ“‡å°å­˜æª”æ ¼å¼"
+msgid "Select Page"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
msgid "Select a group to invite"
msgstr "é¸æ“‡è¦é‚€è«‹çš„群組"
@@ -9800,6 +11655,9 @@ msgstr "é¸æ“‡ä¸€å€‹ç¾æœ‰çš„ Kubernetes å¢é›†æˆ–新增一個"
msgid "Select branch/tag"
msgstr "é¸æ“‡åˆ†æ”¯æˆ–標籤"
+msgid "Select group or project"
+msgstr ""
+
msgid "Select members to invite"
msgstr ""
@@ -9836,6 +11694,9 @@ msgstr "é¸æ“‡ GitLab 使用者將在議題和留言的æè¿°ä¸­æ–°å¢žæŒ‡å‘ Git
msgid "Send an email notification to Developers."
msgstr ""
+msgid "Send confirmation email"
+msgstr ""
+
msgid "Send email"
msgstr "傳é€é›»å­éƒµä»¶"
@@ -9917,6 +11778,9 @@ msgstr ""
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Service"
+msgstr ""
+
msgid "Service Desk"
msgstr "æœå‹™å€"
@@ -9947,21 +11811,24 @@ msgstr "為該群組中的專案設定模æ¿ç‰ˆæœ¬åº«"
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr "設定為é è¨­å€¼ï¼Œä¸¦é™åˆ¶å¯è¦‹ç­‰ç´šã€‚設定匯入來æºå’Œ git å­˜å–連線å”定。"
+msgid "Set due date"
+msgstr ""
+
msgid "Set instance-wide template repository"
msgstr "設定實例範åœçš„模æ¿ç‰ˆæœ¬åº«"
msgid "Set max session time for web terminal."
msgstr "為網é çµ‚端器設定最長工作階段時間"
+msgid "Set milestone"
+msgstr ""
+
msgid "Set new password"
msgstr ""
msgid "Set notification email for abuse reports."
msgstr "為濫用回報設定通知電å­ä¿¡ç®±ã€‚"
-msgid "Set number of approvers required before open merge requests can be merged"
-msgstr ""
-
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr "設定使用者登入的需求。啟用強制性的兩步驟驗證。"
@@ -9977,6 +11844,9 @@ msgstr ""
msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
msgstr ""
+msgid "Set time estimate"
+msgstr ""
+
msgid "Set up CI/CD"
msgstr "設定 CI / CD"
@@ -9998,6 +11868,9 @@ msgstr ""
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr "設定你的專案以自動推é€å’Œ/或從å¦ä¸€å€‹ç‰ˆæœ¬åº«æ‹‰å–變更。分支ã€æ¨™ç±¤åŠæ交將會自動åŒæ­¥ã€‚"
+msgid "Set weight"
+msgstr ""
+
msgid "SetPasswordToCloneLink|set a password"
msgstr "設定密碼"
@@ -10025,6 +11898,18 @@ msgstr "抱歉,我們無法設定您的狀態,請ç¨å€™åœ¨è©¦ã€‚"
msgid "SetStatusModal|What's your status?"
msgstr "你的狀態是什麼?"
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
msgid "Settings"
msgstr "設定"
@@ -10040,6 +11925,9 @@ msgstr "分享的執行器"
msgid "Shared projects"
msgstr "已分享專案"
+msgid "Shared runners help link"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr "é€éŽé‡è¨­æ­¤å‘½å空間的管線執行時間,目å‰ä½¿ç”¨çš„執行時間將會被歸零。"
@@ -10052,14 +11940,23 @@ msgstr "é‡è¨­ç®¡ç·šå·²ç”¨æ™‚é–“"
msgid "Sherlock Transactions"
msgstr "Sherlock 交易"
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
msgid "Show all activity"
+msgstr "顯示所有活動"
+
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
msgstr ""
msgid "Show command"
msgstr "顯示指令"
msgid "Show comments only"
-msgstr ""
+msgstr "åªé¡¯ç¤ºç•™è¨€"
msgid "Show complete raw log"
msgstr "顯示完整的原始記錄"
@@ -10070,9 +11967,6 @@ msgstr ""
msgid "Show latest version"
msgstr "顯示最新版本"
-msgid "Show link to create/view merge request when pushing from the command line"
-msgstr ""
-
msgid "Show parent pages"
msgstr "顯示上層é é¢"
@@ -10125,12 +12019,30 @@ msgstr ""
msgid "Sign out"
msgstr "登出"
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
msgid "Sign-in restrictions"
msgstr "登入é™åˆ¶"
msgid "Sign-up restrictions"
msgstr "註冊é™åˆ¶"
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -10140,6 +12052,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Single or combined queries"
+msgstr ""
+
msgid "Size"
msgstr "大å°"
@@ -10149,6 +12064,9 @@ msgstr "為éœæ…‹ç¶²ç«™çš„大å°èˆ‡ç¶²åŸŸè¨­å®š"
msgid "Size limit per repository (MB)"
msgstr ""
+msgid "Skip this for now"
+msgstr ""
+
msgid "Slack application"
msgstr "Slack 應用程å¼"
@@ -10218,6 +12136,9 @@ msgstr "試圖改變 %{issuableDisplayName} 的鎖定狀態時發生錯誤"
msgid "Something went wrong when toggling the button"
msgstr "切æ›æŒ‰éˆ•æ™‚發生錯誤"
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
msgid "Something went wrong while applying the suggestion. Please try again."
msgstr ""
@@ -10236,6 +12157,9 @@ msgstr "讀å–留言時發生錯誤,請ç¨å€™é‡è©¦ã€‚"
msgid "Something went wrong while fetching group member contributions"
msgstr "å–得群組æˆå“¡è²¢ç»æ™‚發生錯誤。"
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
msgid "Something went wrong while fetching related merge requests."
msgstr ""
@@ -10260,8 +12184,8 @@ msgstr "解決此議題時出ç¾å•é¡Œã€‚è«‹å†è©¦ä¸€æ¬¡ã€‚"
msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr "å°‡ %{project} 新增到儀表æ¿æ™‚發生錯誤"
-msgid "Something went wrong, unable to get operations projects"
-msgstr "讀å–專案時發生錯誤"
+msgid "Something went wrong, unable to get projects"
+msgstr ""
msgid "Something went wrong, unable to remove project"
msgstr "刪除專案時發生錯誤"
@@ -10272,6 +12196,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr "發生未知錯誤,請ç¨å¾Œå†è©¦ã€‚"
+msgid "Something went wrong. Try again later."
+msgstr ""
+
msgid "Sorry, no epics matched your search"
msgstr "抱歉,沒有符åˆæ‚¨æœå°‹çš„ Epic"
@@ -10324,7 +12251,7 @@ msgid "SortOptions|Last joined"
msgstr "最近加入"
msgid "SortOptions|Last updated"
-msgstr "最近更新"
+msgstr "最後更新"
msgid "SortOptions|Least popular"
msgstr "最ä¸å—æ­¡è¿Ž"
@@ -10332,12 +12259,15 @@ msgstr "最ä¸å—æ­¡è¿Ž"
msgid "SortOptions|Less weight"
msgstr "é™ä½Žæ¬Šé‡"
-msgid "SortOptions|Milestone due date"
+msgid "SortOptions|Manual"
msgstr ""
-msgid "SortOptions|Milestone due later"
+msgid "SortOptions|Milestone due date"
msgstr "里程碑截止日期"
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
msgid "SortOptions|Milestone due soon"
msgstr "å³å°‡æˆªæ­¢çš„里程碑"
@@ -10386,6 +12316,12 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr "最近登入"
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
msgid "SortOptions|Start date"
msgstr "開始日期"
@@ -10458,6 +12394,9 @@ msgstr "已暫存的 %{type}"
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr "為一個標籤標上星號,使其æˆç‚ºå„ªå…ˆæ¨™ç±¤ã€‚é€éŽæ‹–動指令優先標籤變更其相å°å„ªå…ˆåº¦ã€‚"
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
msgid "StarProject|Star"
msgstr "收è—"
@@ -10482,6 +12421,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
+msgid "Start Indexing"
+msgstr ""
+
msgid "Start Web Terminal"
msgstr ""
@@ -10489,7 +12431,7 @@ msgid "Start a %{new_merge_request} with these changes"
msgstr "建立包å«é€™äº›è®Šå‹•çš„ %{new_merge_request}"
msgid "Start a new merge request"
-msgstr ""
+msgstr "開始一個新的åˆä½µè«‹æ±‚"
msgid "Start a review"
msgstr "開始檢閱"
@@ -10512,6 +12454,12 @@ msgstr ""
msgid "Start discussion & reopen %{noteable_name}"
msgstr ""
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "啟動執行器ï¼"
@@ -10561,7 +12509,7 @@ msgid "Stopped"
msgstr "å·²åœæ­¢"
msgid "Stopping this environment is currently not possible as a deployment is in progress"
-msgstr "由於該環境正在部署,所以目å‰ç„¡æ³•åœæ­¢"
+msgstr "由於該環境正在佈署,所以目å‰ç„¡æ³•åœæ­¢"
msgid "Stopping..."
msgstr ""
@@ -10572,17 +12520,23 @@ msgstr "儲存空間"
msgid "Storage:"
msgstr "儲存空間:"
+msgid "StorageSize|Unknown"
+msgstr ""
+
msgid "Subgroups"
msgstr "å­ç¾¤çµ„"
msgid "Subgroups and projects"
msgstr "å­ç¾¤çµ„和專案"
+msgid "Subkeys"
+msgstr ""
+
msgid "Submit as spam"
msgstr "以垃圾訊æ¯æ交"
msgid "Submit feedback"
-msgstr ""
+msgstr "æ交æ„見"
msgid "Submit review"
msgstr "æ交檢閱"
@@ -10608,6 +12562,9 @@ msgstr ""
msgid "Subscribed"
msgstr "已訂閱"
+msgid "Subscription"
+msgstr ""
+
msgid "SubscriptionTable|Billing"
msgstr ""
@@ -10680,6 +12637,9 @@ msgstr ""
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
+msgid "Subtracts"
+msgstr ""
+
msgid "Successfully blocked"
msgstr ""
@@ -10704,9 +12664,72 @@ msgstr ""
msgid "Suggested change"
msgstr ""
-msgid "Sunday"
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
msgstr ""
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
+msgid "Sunday"
+msgstr "星期日"
+
msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
@@ -10716,6 +12739,12 @@ msgstr ""
msgid "Switch branch/tag"
msgstr "切æ›åˆ†æ”¯/標籤"
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy it to the clipboard"
+msgstr ""
+
msgid "Sync information"
msgstr "åŒæ­¥è©³ç´°è³‡è¨Š"
@@ -10746,18 +12775,30 @@ msgstr "系統指標 (自訂)"
msgid "System metrics (Kubernetes)"
msgstr "系統指標 (Kubernetes)"
+msgid "Table of Contents"
+msgstr ""
+
msgid "Tag"
msgstr ""
msgid "Tag list:"
msgstr ""
+msgid "Tag this commit."
+msgstr ""
+
msgid "Tags"
msgstr "標籤"
msgid "Tags feed"
msgstr "標籤動態"
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
msgid "Tags:"
msgstr "標籤:"
@@ -10839,6 +12880,9 @@ msgstr "目標分支"
msgid "Team"
msgstr "團隊"
+msgid "Team domain"
+msgstr ""
+
msgid "Template"
msgstr "模æ¿"
@@ -10851,6 +12895,9 @@ msgstr ""
msgid "Terminal for environment"
msgstr ""
+msgid "Terminal sync service is running"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "æœå‹™æ¢æ¬¾å”議和隱ç§æ”¿ç­–"
@@ -10866,6 +12913,33 @@ msgstr "測試覆蓋率分æž"
msgid "Test failed."
msgstr ""
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has at least one commit."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -10903,6 +12977,9 @@ msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
+msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+msgstr ""
+
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr "文字çªé¡¯å°‡å¹«åŠ©ä½ å°‡ä¸»é¡Œä¿æŒç‚º %{titleLength} 個字,並且將正文包è£ç‚º %{bodyLength} 個字,以便它們å¯ä»¥åœ¨ git 中閱讀。"
@@ -10918,6 +12995,9 @@ msgstr "該連線將在 %{timeout} 之後逾時。å°æ–¼éœ€è¦ä½¿ç”¨æ›´é•·æ™‚é–“
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr ""
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
msgid "The deployment of this job to %{environmentLink} did not succeed."
msgstr "å° %{environmentLink} 作業的佈署並未æˆåŠŸã€‚"
@@ -10975,6 +13055,15 @@ msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "議題階段顯示從議題建立到設定里程碑所花的時間,或是議題被分類到議題看æ¿ä¸­æ‰€èŠ±çš„時間。建立第一個議題後,資料將自動填入。"
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -10993,6 +13082,12 @@ msgstr ""
msgid "The name %{entryName} is already taken in this directory."
msgstr ""
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "解密ç§é‘°æ‰€éœ€çš„密碼。這是é¸ç”¨ä¸”該值將會被加密儲存。"
@@ -11012,14 +13107,26 @@ msgid "The private key to use when a client certificate is provided. This value
msgstr "æ供使用者端憑證時所使用的ç§é‘°ã€‚æ­¤ç§é‘°å°‡æœƒè¢«åŠ å¯†å„²å­˜ã€‚"
msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
-msgstr "營é‹éšŽæ®µé¡¯ç¤ºå¾žå»ºç«‹è­°é¡Œåˆ°éƒ¨ç½²ç¨‹å¼ä¸Šç·šæ‰€èŠ±çš„時間。完æˆå¾žç™¼æƒ³åˆ°ä¸Šç·šçš„完整開發週期後,資料將自動填入。"
+msgstr "營é‹éšŽæ®µé¡¯ç¤ºå¾žå»ºç«‹è­°é¡Œåˆ°ä½ˆç½²ç¨‹å¼ä¸Šç·šæ‰€èŠ±çš„時間。完æˆå¾žç™¼æƒ³åˆ°ä¸Šç·šçš„完整開發週期後,資料將自動填入。"
msgid "The project can be accessed by any logged in user."
msgstr "本專案å¯è®“任何已登入的使用者存å–"
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
msgid "The project can be accessed without any authentication."
msgstr "本專案å¯è®“任何人存å–"
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
msgid "The project was successfully forked."
msgstr ""
@@ -11029,6 +13136,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr "Pseudonymizer 資料è’集已經åœç”¨ã€‚如果啟用,GitLab 將會執行一個背景作業 -- 其將會產生 GitLab 資料庫的å‡å CSV,使其å¯ä»¥ä¸Šå‚³åˆ°æ‚¨è¨­å®šçš„物件儲存資料夾。"
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
msgid "The remote repository is being updated..."
msgstr ""
@@ -11038,6 +13148,9 @@ msgstr "本專案沒有版本庫"
msgid "The repository for this project is empty"
msgstr "這個專案的版本庫是空的"
+msgid "The repository is being updated..."
+msgstr ""
+
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr "該存儲庫必須å¯é€éŽ <code>http://</code>, <code>https://</code> 或 <code>git://</code>訪å•ã€‚"
@@ -11066,7 +13179,7 @@ msgid "The snippet is visible to any logged in user."
msgstr ""
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
-msgstr "試營é‹æ®µé¡¯ç¤ºå¾žåˆä½µè«‹æ±‚被åˆä½µå¾Œè‡³éƒ¨ç½²ç‡Ÿé‹çš„時間。當第一次部署營é‹å¾Œï¼Œè³‡æ–™å°‡è‡ªå‹•å¡«å…¥"
+msgstr "試營é‹æ®µé¡¯ç¤ºå¾žåˆä½µè«‹æ±‚被åˆä½µå¾Œè‡³ä½ˆç½²ç‡Ÿé‹çš„時間。當第一次佈署營é‹å¾Œï¼Œè³‡æ–™å°‡è‡ªå‹•å¡«å…¥"
msgid "The tabs below will be removed in a future version"
msgstr "底下的分é å°‡æœƒåœ¨æœªä¾†ç‰ˆæœ¬ä¸­ç§»é™¤"
@@ -11077,6 +13190,9 @@ msgstr "測試階段顯示相關åˆä½µè«‹æ±‚的管線所花的時間。當第一
msgid "The time taken by each data entry gathered by that stage."
msgstr "該階段中æ¯ä¸€å€‹è³‡æ–™é …目所花的時間。"
+msgid "The unique identifier for the Geo node. Must match `geo_node_name` if it is set in gitlab.rb, otherwise it must match `external_url`"
+msgstr ""
+
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr "更新動作將會在 %{number_of_minutes} 分é˜å¾Œé€¾æ™‚。å°æ–¼å¤§åž‹ç‰ˆæœ¬åº«ï¼Œè«‹ä½¿ç”¨ clone/push 組åˆã€‚"
@@ -11098,20 +13214,35 @@ msgstr "å°æ‡‰ä½¿ç”¨è€…是一個JSON檔,是將åƒèˆ‡å°ˆæ¡ˆçš„ Google Code 使ç
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr "使用者å°æ‡‰æ˜¯å°‡åƒèˆ‡å°ˆæ¡ˆçš„ FogBugz 使用者與其電å­éƒµä»¶å’Œä½¿ç”¨è€…å稱匯入 GitLab çš„æ–¹å¼ã€‚您å¯ä»¥é€éŽå¡«å¯«ä¸‹æ–¹çš„表單來變更此設定。"
+msgid "The user-facing URL of the Geo node."
+msgstr ""
+
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "中ä½æ•¸æ˜¯ä¸€å€‹æ•¸åˆ—中最中間的值。例如在 3ã€5ã€9 之間,中ä½æ•¸æ˜¯ 5。在 3ã€5ã€7ã€8 之間,中ä½æ•¸æ˜¯ (5 + 7)/ 2 = 6。"
-msgid "There are no approvers"
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
msgstr ""
msgid "There are no archived projects yet"
msgstr "此處沒有已å°å­˜å°ˆæ¡ˆ"
-msgid "There are no closed issues"
+msgid "There are no charts configured for this page"
msgstr ""
+msgid "There are no closed issues"
+msgstr "沒有已關閉的議題"
+
msgid "There are no closed merge requests"
-msgstr ""
+msgstr "沒有已關閉的åˆä½µè«‹æ±‚"
msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
msgstr ""
@@ -11140,8 +13271,23 @@ msgstr "此處沒有暫存的變更"
msgid "There are no unstaged changes"
msgstr "此處沒有未暫存的變更"
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
msgid "There was an error adding a todo."
-msgstr "加入待辦事項時出錯。"
+msgstr "增新待辦事項時出錯。"
+
+msgid "There was an error creating the issue"
+msgstr ""
msgid "There was an error deleting the todo."
msgstr "刪除待辦事項時出錯。"
@@ -11158,6 +13304,12 @@ msgstr "讀å–使用者行事曆活動時發生錯誤"
msgid "There was an error removing the e-mail."
msgstr ""
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
msgid "There was an error saving your changes."
msgstr ""
@@ -11176,6 +13328,9 @@ msgstr "訂閱此標籤時出ç¾éŒ¯èª¤ã€‚"
msgid "There was an error when unsubscribing from this label."
msgstr "å–消訂閱此標籤時出ç¾éŒ¯èª¤ã€‚"
+msgid "There was an error while fetching cycle analytics data."
+msgstr ""
+
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -11188,6 +13343,9 @@ msgstr "å…¶å¯ä»¥ä½¿ç”¨ %{link} 進行管ç†ã€‚"
msgid "Third party offers"
msgstr "第三方æä¾›"
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
@@ -11200,18 +13358,30 @@ msgstr "æ­¤ GitLab 實例ä¸æ供任何分享的執行器。實例管ç†å“¡å¯ä
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
+msgid "This also resolves the discussion"
+msgstr ""
+
msgid "This application was created by %{link_to_owner}."
msgstr "這個應用程å¼æ˜¯ç”± %{link_to_owner} 建立的。"
msgid "This application will be able to:"
msgstr "此應用程å¼å°‡å¯ä»¥ï¼š"
+msgid "This block is self-referential"
+msgstr ""
+
msgid "This board's scope is reduced"
msgstr "已縮å°æ­¤çœ‹æ¿ç¯„åœ"
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr "自上次編輯以來此分支已經變更éŽã€‚是å¦å»ºç«‹æ–°åˆ†æ”¯ï¼Ÿ"
+msgid "This certificate is automatically managed by Let's Encrypt"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -11236,6 +13406,12 @@ msgstr "此日期晚於çµæŸæ—¥æœŸï¼Œå› æ­¤é€™å€‹ Epic å°‡ä¸æœƒåœ¨é–‹ç™¼è—圖
msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr "此日期早於開始日期,因此這個 Epic å°‡ä¸æœƒåœ¨é–‹ç™¼è—圖中顯示。"
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
msgid "This diff is collapsed."
msgstr "此差異已折疊。"
@@ -11248,6 +13424,9 @@ msgstr "這個資料夾"
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This environment has no deployments yet."
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -11257,29 +13436,38 @@ msgstr "此群組"
msgid "This group does not provide any group Runners yet."
msgstr "這群組尚未æ供任何群組執行器。"
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
msgid "This is a confidential issue."
msgstr "這是個隱密å•é¡Œã€‚"
msgid "This is a delayed job to run in %{remainingTime}"
msgstr "這這是一個延é²æ€§çš„工作,將在 %{remainingTime} 後執行"
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr "這是作者第一次åˆä½µè«‹æ±‚至本專案。"
msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
msgstr ""
+msgid "This is your current session"
+msgstr ""
+
msgid "This issue is confidential"
msgstr "這個議題是ä¿å¯†çš„"
-msgid "This issue is confidential and locked."
-msgstr "這個å•é¡Œæ˜¯ä¿å¯†ä¸”鎖定的。"
-
msgid "This issue is locked."
msgstr "這個å•é¡Œå·²è¢«éŽ–定。"
msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
-msgstr "這項作業將由使用者觸發,這通常用於部署應用程å¼åˆ°æ­£å¼ç’°å¢ƒ"
+msgstr "這項作業將由使用者觸發,這通常用於佈署應用程å¼åˆ°æ­£å¼ç’°å¢ƒ"
msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
msgstr "這項工作需è¦ä¸Šä¸€å€‹å·¥ä½œæˆåŠŸæ™‚æ‰èƒ½è§¸ç™¼åŸ·è¡Œå·¥ä½œ"
@@ -11300,19 +13488,19 @@ msgid "This job has not started yet"
msgstr "這份作業還沒有開始執行"
msgid "This job is an out-of-date deployment to %{environmentLink}."
-msgstr "這個工作已經逾時,無法部署到 %{environmentLink}。"
+msgstr "這個工作已經逾時,無法佈署到 %{environmentLink}。"
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
-msgstr "這個專案已經逾時,無法部署到 %{environmentLink}。檢視最新的部署 %{deploymentLink}。"
+msgstr "這個專案已經逾時,無法佈署到 %{environmentLink}。檢視最新的佈署 %{deploymentLink}。"
msgid "This job is archived. Only the complete pipeline can be retried."
msgstr "這個工作已經歸檔。åªèƒ½é‡æ–°åŸ·è¡Œæ•´å€‹ç®¡ç·šã€‚"
msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
-msgstr "這個工作將部署到 %{environmentLink} 並將覆蓋既有的部署 %{deploymentLink}。"
+msgstr "這個工作將佈署到 %{environmentLink} 並將覆蓋既有的佈署 %{deploymentLink}。"
msgid "This job is creating a deployment to %{environmentLink}."
-msgstr "這個工作正在部署到 %{environmentLink}。"
+msgstr "這個工作正在佈署到 %{environmentLink}。"
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr "這份作業ä½æ–¼ç­‰å¾…狀態,等待執行器來執行"
@@ -11330,7 +13518,7 @@ msgid "This job is stuck because you don't have any active runners that can run
msgstr ""
msgid "This job is the most recent deployment to %{link}."
-msgstr "這個工作最近部署到 %{link}。"
+msgstr "這個工作最近佈署到 %{link}。"
msgid "This job requires a manual action"
msgstr "這份作業需è¦æ‰‹å‹•åŸ·è¡Œ"
@@ -11344,12 +13532,6 @@ msgstr "這代表在您建立一個空的版本庫或是匯入一個ç¾å­˜çš„版
msgid "This merge request is locked."
msgstr "這個åˆä½µè«‹æ±‚已被鎖定。"
-msgid "This merge request must be approved by members of these groups. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
-msgid "This merge request must be approved by these users. You can override the project settings by setting your own list of approvers."
-msgstr ""
-
msgid "This namespace has already been taken! Please choose another one."
msgstr ""
@@ -11422,6 +13604,12 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr "這裡列出了那些自動æˆç‚ºè­°é¡Œçš„é›»å­éƒµä»¶ï¼ˆå¾žç•™è¨€è®Šæˆçš„é›»å­éƒµä»¶å°è©±ï¼‰"
+msgid "Thursday"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr "議題被列入日程表的時間"
@@ -11604,6 +13792,9 @@ msgstr "æ示:"
msgid "Title"
msgstr "標題"
+msgid "Title:"
+msgstr ""
+
msgid "Titles and Filenames"
msgstr ""
@@ -11619,6 +13810,9 @@ msgstr ""
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr "è¦æ–°å¢žSSHå¯†é‘°ï¼Œä½ éœ€è¦ %{generate_link_start}產生一個%{link_end} 或使用 %{existing_link_start}ç¾æœ‰çš„密鑰%{link_end}。"
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
msgstr "è‹¥è¦é€£ç·šåˆ° GitHub 版本庫,您å¯ä»¥ä½¿ç”¨ %{personal_access_token_link} 連çµã€‚當您建立了您的個人存å–憑證,您將需è¦é¸æ“‡ <code>版本庫</code> 範åœï¼Œæ‰€ä»¥æˆ‘們å¯ä»¥é¡¯ç¤ºæ‚¨å¯ä¾›é€£ç·šçš„公開與ç§äººç‰ˆæœ¬åº«åˆ—表。"
@@ -11685,6 +13879,9 @@ msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr "è‹¥è¦é€éŽèº«ä»½æ供者(例如 Azureã€Oktaã€Oneloginã€Ping Identity 或您自訂的 SAML 2.0 æ供者)設定 SAML èªè­‰ï¼š"
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr "è‹¥è¦é–‹å§‹æ供您的工作,您å¯ä»¥å¢žåŠ åŸ·è¡Œå™¨è‡³é€™å€‹ç¾¤çµ„"
@@ -11713,7 +13910,7 @@ msgid "Todo"
msgstr "待辦事項"
msgid "Todo was successfully marked as done."
-msgstr ""
+msgstr "待辦事項已æˆåŠŸåœ°æ¨™è¨˜ç‚ºå·²å®Œæˆã€‚"
msgid "Todos"
msgstr "待辦事項"
@@ -11721,6 +13918,9 @@ msgstr "待辦事項"
msgid "Toggle Sidebar"
msgstr "展開 / 收起å´é‚Šæ¬„"
+msgid "Toggle backtrace"
+msgstr ""
+
msgid "Toggle comments for this file"
msgstr ""
@@ -11733,9 +13933,15 @@ msgstr ""
msgid "Toggle discussion"
msgstr "切æ›è¨Žè«–"
+msgid "Toggle emoji award"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "切æ›å°Žèˆªæ¬„"
+msgid "Toggle project"
+msgstr ""
+
msgid "Toggle sidebar"
msgstr "切æ›å´é‚Šæ¬„"
@@ -11745,6 +13951,9 @@ msgstr "切æ›ç‹€æ…‹ï¼šé—œé–‰"
msgid "ToggleButton|Toggle Status: ON"
msgstr "切æ›ç‹€æ…‹ï¼šé–‹å•Ÿ"
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
msgid "Token"
msgstr "憑證"
@@ -11787,6 +13996,42 @@ msgstr "快速使用時間追蹤工具"
msgid "Transfer project"
msgstr ""
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr "樹狀顯示"
@@ -11838,15 +14083,30 @@ msgstr ""
msgid "Try all GitLab has to offer for 30 days."
msgstr "試用 GitLab 的所有功能 30 天。"
+msgid "Try to fork again"
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
+msgid "Tuesday"
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "é–‹å•Ÿæœå‹™å€"
msgid "Twitter"
msgstr "Twitter"
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
msgid "Two-factor Authentication has been disabled for this user"
msgstr ""
@@ -11856,24 +14116,42 @@ msgstr "兩步驟驗證"
msgid "Type"
msgstr "é¡žåž‹"
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "URL"
msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to generate new instance ID"
+msgstr ""
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr "無法載入差異。%{button_try_again}"
+msgid "Unable to resolve"
+msgstr ""
+
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "因為「%{reason}ã€ï¼Œæ‰€ä»¥ç„¡æ³•è®“ä½ é€éŽ SAML 登入這個群組。"
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
msgid "Unable to update this epic at this time."
msgstr "ç›®å‰ç„¡æ³•æ›´æ–°æ­¤ epic。"
+msgid "Unable to update this issue at this time."
+msgstr ""
+
msgid "Unarchive project"
msgstr ""
@@ -11892,18 +14170,33 @@ msgstr ""
msgid "Unknown"
msgstr "未知"
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
msgid "Unlimited"
msgstr ""
msgid "Unlock"
msgstr "解鎖"
+msgid "Unlock the discussion"
+msgstr ""
+
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr "解鎖這個%{issuableDisplayName}?<strong>所有人</strong>都å¯ä»¥ç™¼è¡¨ç•™è¨€ã€‚"
msgid "Unlocked"
msgstr "已解鎖"
+msgid "Unlocks the discussion"
+msgstr ""
+
msgid "Unresolve discussion"
msgstr "é‡æ–°è¨Žè«–"
@@ -11973,6 +14266,18 @@ msgstr "更新你的群組å稱ã€èªªæ˜Žã€é ­åƒåŠå¯è¦‹æ€§ã€‚"
msgid "Update your project name, topics, description and avatar."
msgstr ""
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
msgid "Updated"
msgstr ""
@@ -12024,6 +14329,9 @@ msgstr ""
msgid "Upload file"
msgstr "上傳檔案"
+msgid "Upload file does not exist"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -12033,6 +14341,9 @@ msgstr "點é¸ä¸Šå‚³"
msgid "Uploaded on"
msgstr ""
+msgid "Uploading changes to terminal"
+msgstr ""
+
msgid "Uploads"
msgstr ""
@@ -12051,6 +14362,54 @@ msgstr "使用情æ³åµæ¸¬æœªå•Ÿå‹•"
msgid "Usage statistics"
msgstr "使用情形統計資料"
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
@@ -12060,6 +14419,12 @@ msgstr "使用 <code>%{native_redirect_uri}</code> 進行本機測試"
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "使用æœå‹™å°åœ¨ GitLab 內部é€éŽé›»å­éƒµä»¶èˆ‡ä½¿ç”¨è€…è¯çµ¡ (例如æ供客戶æœå‹™)"
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
msgstr "使用群組里程碑從多個專案中於åŒä¸€å€‹é‡Œç¨‹ç¢‘管ç†è­°é¡Œã€‚"
@@ -12117,6 +14482,9 @@ msgstr ""
msgid "User map"
msgstr "使用者地圖"
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
msgid "User settings"
msgstr ""
@@ -12132,6 +14500,141 @@ msgstr ""
msgid "User was successfully updated."
msgstr ""
+msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
+msgstr ""
+
+msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
+msgstr ""
+
+msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
+msgstr ""
+
+msgid "UserOnboardingTour|Adding other memembers to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
+msgstr ""
+
+msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
+msgstr ""
+
+msgid "UserOnboardingTour|Click to open the latest commit to see its details."
+msgstr ""
+
+msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Create a project"
+msgstr ""
+
+msgid "UserOnboardingTour|Exit 'Learn GitLab'"
+msgstr ""
+
+msgid "UserOnboardingTour|Got it"
+msgstr ""
+
+msgid "UserOnboardingTour|Guided GitLab Tour"
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Choose a way to create a project and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
+msgstr ""
+
+msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
+msgstr ""
+
+msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request, from a branch or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
+msgstr ""
+
+msgid "UserOnboardingTour|Invite colleagues"
+msgstr ""
+
+msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progess in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks like when the list is filtered by a label."
+msgstr ""
+
+msgid "UserOnboardingTour|Learn GitLab"
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|No thanks"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, let's go"
+msgstr ""
+
+msgid "UserOnboardingTour|Ok, show me"
+msgstr ""
+
+msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
+msgstr ""
+
+msgid "UserOnboardingTour|Restart this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Skip this step"
+msgstr ""
+
+msgid "UserOnboardingTour|Sweet! Your project was created is is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
+msgstr ""
+
+msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
+msgstr ""
+
+msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for merge requests. Now for the finla part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
+msgstr ""
+
+msgid "UserOnboardingTour|The structure of this page is very similar to the onfe of issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Below, alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
+msgstr ""
+
+msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
+msgstr ""
+
+msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
+msgstr ""
+
+msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
+msgstr ""
+
+msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore around and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure, you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down, below the file strcture, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
+msgstr ""
+
+msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we uese to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaboreate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
msgid "UserProfile|Activity"
msgstr "活動"
@@ -12163,7 +14666,7 @@ msgid "UserProfile|No snippets found."
msgstr ""
msgid "UserProfile|Overview"
-msgstr "概述"
+msgstr "概覽"
msgid "UserProfile|Personal projects"
msgstr "個人專案"
@@ -12207,6 +14710,15 @@ msgstr ""
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
msgstr ""
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
msgid "Users"
msgstr "使用者"
@@ -12222,9 +14734,27 @@ msgstr ""
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
msgid "Validate"
msgstr ""
@@ -12270,12 +14800,18 @@ msgstr "版本"
msgid "View app"
msgstr "檢視應用程å¼"
+msgid "View dependency details for your project"
+msgstr ""
+
msgid "View deployment"
msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -12285,6 +14821,9 @@ msgstr "檢視 Epic 列表"
msgid "View file @ "
msgstr "ç€è¦½æª”案 @ "
+msgid "View full dashboard"
+msgstr ""
+
msgid "View group labels"
msgstr "檢視群組標籤"
@@ -12294,6 +14833,9 @@ msgstr ""
msgid "View it on GitLab"
msgstr "在 GitLab 上檢視"
+msgid "View job"
+msgstr ""
+
msgid "View job trace"
msgstr ""
@@ -12313,7 +14855,7 @@ msgid "View project labels"
msgstr "檢視專案標籤"
msgid "View replaced file @ "
-msgstr "ç€è¦½å·²å–代檔案 @ "
+msgstr "檢視已å–代檔案 @ "
msgid "View the documentation"
msgstr "檢視檔案"
@@ -12321,6 +14863,9 @@ msgstr "檢視檔案"
msgid "Viewing commit"
msgstr ""
+msgid "Visibility"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr "å¯è¦‹æ€§èˆ‡å­˜å–控制"
@@ -12348,6 +14893,33 @@ msgstr "公開"
msgid "VisibilityLevel|Unknown"
msgstr "ä¸æ˜Ž"
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} of every page of your application. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. Open the review app and provide a personal access token following %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. You are now able to leave feedback from within the review app."
+msgstr ""
+
+msgid "VisualReviewApp|Adding the following script to your code makes it possible to directly leave feedback inside of the review app. Feedback given will get submitted automatically to this merge request’s discussion, including metadata."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Review and give feedback directly from within the review app"
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
msgid "Vulnerability Chart"
msgstr ""
@@ -12390,6 +14962,9 @@ msgstr ""
msgid "Vulnerability|Severity"
msgstr "åš´é‡æ€§"
+msgid "Wait for the source to load to copy it to the clipboard"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "權é™ä¸è¶³ã€‚如需檢視相關資料,請å‘管ç†å“¡ç”³è«‹æ¬Šé™ã€‚"
@@ -12408,6 +14983,9 @@ msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
+msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You willl be guided by two types of helpers, best recognized by their color."
+msgstr ""
+
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
msgstr "我們åµæ¸¬åˆ° %{humanized_resource_name} 潛在垃圾郵件。請驗證 reCAPTCHA 之後å†ç¹¼çºŒã€‚"
@@ -12417,6 +14995,9 @@ msgstr "應該階段的資料ä¸è¶³è€Œç„¡æ³•é¡¯ç¤ºç›¸é—œè³‡è¨Š"
msgid "We heard back from your U2F device. You have been authenticated."
msgstr ""
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "我們è¦ç¢ºå®šä½ ä¸æ˜¯æ©Ÿå™¨äººã€‚"
@@ -12438,6 +15019,9 @@ msgstr ""
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr "Webhooks å…許你觸發 URL,例如推é€äº†æ–°çš„程å¼ç¢¼ã€æˆ–是建立了新的議題。您å¯ä»¥è¨­å®š Webhook 以監è½æŒ‡å®šçš„活動,例如推é€ã€è­°é¡Œæˆ–åˆä½µè«‹æ±‚。群組 Webhooks 將套用至群組中的所有專案,å…許你è¦ç¯„整個群組中的 Webhook 的功能。"
+msgid "Wednesday"
+msgstr ""
+
msgid "Weeks"
msgstr "週"
@@ -12447,15 +15031,18 @@ msgstr "權é‡"
msgid "Weight %{weight}"
msgstr "æ¬Šé‡ %{weight}"
+msgid "Welcome to the Guided GitLab Tour"
+msgstr ""
+
+msgid "Welcome to your Issue Board!"
+msgstr ""
+
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "當執行器被鎖定,其將ä¸èƒ½è¢«å…¶ä»–專案指定。"
msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr "當啟用,使用者在接å—æ¢æ¬¾ä¹‹å‰éƒ½ä¸èƒ½ä½¿ç”¨ GitLab。"
-msgid "When fast-forward merge is not possible, the user is given the option to rebase."
-msgstr ""
-
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr "當 URL 留空時,還是å¯ä»¥æŒ‡å®šåˆ†é¡žæ¨™ç±¤ï¼Œè€Œä¸”ä¸å¿…åœç”¨è·¨å°ˆæ¡ˆåŠŸèƒ½æˆ–執行外部授權檢查。"
@@ -12466,6 +15053,9 @@ msgstr[0] ""
msgid "When:"
msgstr ""
+msgid "White helpers give contextual information."
+msgstr ""
+
msgid "Who can see this group?"
msgstr "誰å¯ä»¥çœ‹åˆ°é€™å€‹ç¾¤çµ„?"
@@ -12629,10 +15219,10 @@ msgid "Workflow Help"
msgstr ""
msgid "Write"
-msgstr ""
+msgstr "寫"
msgid "Write a comment or drag your files here…"
-msgstr ""
+msgstr "寫評論或拖動你的文件到這裡"
msgid "Write access allowed"
msgstr ""
@@ -12646,6 +15236,9 @@ msgstr ""
msgid "Yes"
msgstr "是"
+msgid "Yes or No"
+msgstr ""
+
msgid "Yes, add it"
msgstr "是的,新增它"
@@ -12661,8 +15254,14 @@ msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr "您是一å管ç†å“¡ï¼Œé€™æ„味著如果授予 <strong>%{client_name}</strong> 訪å•æ¬Šé™ï¼Œå°‡å…許他們作為管ç†å“¡èˆ‡GitLab進行互動。請謹慎行事。"
-msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "å°‡è¦åˆªé™¤ %{group_name}。被刪除的群組無法復原ï¼çœŸçš„「確定ã€è¦é€™éº¼åšå—Žï¼Ÿ"
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "å°‡è¦åˆªé™¤ %{project_full_name}。被刪除的專案無法復原ï¼çœŸçš„「確定ã€è¦é€™éº¼åšå—Žï¼Ÿ"
@@ -12673,6 +15272,9 @@ msgstr "å°‡è¦åˆªé™¤æœ¬åˆ†æ”¯å°ˆæ¡ˆèˆ‡ä¸»å¹¹ %{forked_from_project} 的所有關
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr "å°‡è¦æŠŠ %{project_full_name} 的所有權轉移給å¦ä¸€å€‹äººã€‚真的「確定ã€è¦é€™éº¼åšå—Žï¼Ÿ"
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -12688,6 +15290,12 @@ msgstr "您å¯ä»¥ %{linkStart}檢視BLOB%{linkEnd} 。"
msgid "You can also create a project from the command line."
msgstr "您也å¯ä»¥å¾žæŒ‡ä»¤æ–°å¢žä¸€å€‹å°ˆæ¡ˆã€‚"
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
msgid "You can also star a label to make it a priority label."
msgstr "您還å¯ä»¥ç‚ºæŸå€‹æ¨™ç±¤åŠ ä¸Šæ˜Ÿæ˜Ÿï¼Œä½¿å…¶æˆç‚ºå„ªå…ˆæ¨™ç±¤ã€‚"
@@ -12706,6 +15314,15 @@ msgstr "您å¯ä»¥é€éŽè«‹æ±‚加入這些群組,來輕鬆地為他們åšå‡ºè²¢
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
msgstr "您å¯ä»¥è¼•é¬†åœ°åœ¨ Kubernetes å¢é›†ä¸Šå®‰è£åŸ·è¡Œå™¨ã€‚ %{link_to_help_page}"
+msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgstr ""
+
+msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgstr ""
+
msgid "You can move around the graph by using the arrow keys."
msgstr "您å¯ä»¥ä½¿ç”¨ä¸Šä¸‹å·¦å³éµç§»å‹•åœ–形。"
@@ -12730,9 +15347,15 @@ msgstr ""
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "您å¯ä»¥é€éŽä½¿ç”¨äº’動模å¼é¸æ“‡ %{use_ours} 或 %{use_theirs} 按鈕ã€æˆ–者是直接編輯檔案來解決åˆä½µè¡çªï¼Œä¸¦å°‡é€™äº›è®Šæ›´æ交到 %{branch_name}。"
+msgid "You can see your chat accounts."
+msgstr ""
+
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr "您å¯ä»¥å°‡å·¥ä½œè¨­å®šç‚ºæ­¢ä½¿ç”¨å…·æœ‰ç‰¹åˆ¥æ¨™ç±¤çš„執行器。請使用逗號分隔ä¸åŒçš„標籤。"
+msgid "You can specify notification level per group or per project."
+msgstr ""
+
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr "您å¯ä»¥é€éŽ %{linkStart}CI Lint%{linkEnd} 測試 .gitlab-ci.yml"
@@ -12763,12 +15386,21 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr "你還沒有任何訂閱"
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
msgstr ""
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr "您沒有權é™ä¾†è¦†è“‹ LDAP 群組åŒæ­¥è¨­å®šã€‚"
+msgid "You don't have any U2F devices registered yet."
+msgstr ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
msgid "You don't have any applications"
msgstr "您沒有任何應用程å¼"
@@ -12778,6 +15410,12 @@ msgstr "您沒有任何已授權的應用程å¼"
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
msgid "You have been granted %{member_human_access} access to %{label}."
msgstr ""
@@ -12808,6 +15446,15 @@ msgstr "您必須接å—我們的æœå‹™æ¢æ¬¾å’Œéš±ç§æ”¿ç­–æ‰èƒ½è¨»å†Šå¸³è™Ÿ"
msgid "You must have maintainer access to force delete a lock"
msgstr "您必須æ“有維護者存å–æ‰èƒ½å¼·åˆ¶ç§»é™¤éŽ–定"
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
msgid "You need a different license to enable FileLocks feature"
msgstr "您需è¦ä½¿ç”¨ä¸åŒçš„授權以啟用 FileLocks 功能"
@@ -12820,6 +15467,9 @@ msgstr "æ‚¨éœ€è¦ git-lfs 版本 %{min_git_lfs_version} (或更高版本) æ‰èƒ½
msgid "You need permission."
msgstr "需è¦æ¬Šé™æ‰èƒ½é€™éº¼åšã€‚"
+msgid "You need to be logged in."
+msgstr ""
+
msgid "You need to register a two-factor authentication app before you can set up a U2F device."
msgstr ""
@@ -12832,6 +15482,9 @@ msgstr ""
msgid "You need to upload a Google Takeout archive."
msgstr ""
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -12865,6 +15518,9 @@ msgstr "在個人帳號中 %{add_ssh_key_link} 之å‰ï¼Œ 將無法使用 SSH 上
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "在您的個人資料中新增 SSH 密鑰之å‰ï¼Œä½ ä¸èƒ½é€éŽ SSH 來拉å–或推é€å°ˆæ¡ˆç¨‹å¼ç¢¼ã€‚"
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
msgid "You'll need to use different branch names to get a valid comparison."
msgstr "你需è¦é¸æ“‡å…©å€‹ä¸åŒçš„分支,æ‰èƒ½é€²è¡Œæ¯”較。"
@@ -12886,27 +15542,51 @@ msgstr "您收到此電å­éƒµä»¶æ˜¯å› ç‚ºæ‚¨çš„帳號在 %{host}."
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgstr "你收到此電å­éƒµä»¶æ˜¯å› ç‚ºä½ çš„帳號在 %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
msgid "YouTube"
msgstr "YouTube"
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
msgid "Your Conversational Development Index gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
msgid "Your Groups"
msgstr "你的群組"
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
msgstr "您的Kuberneteså¢é›†è³‡è¨Šä»ç„¶å¯ä»¥ç·¨è¼¯ï¼Œä½†å»ºè­°æ‚¨ç¦ç”¨ä¸¦é‡æ–°è¨­å®šã€‚"
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
msgid "Your Projects (default)"
msgstr "您的專案(é è¨­å€¼ï¼‰"
msgid "Your Projects' Activity"
msgstr "您的專案活動"
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
msgid "Your Todos"
msgstr "您的待辦事項"
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
msgstr ""
@@ -12940,8 +15620,11 @@ msgstr "您的修改已經儲存"
msgid "Your changes have been successfully committed."
msgstr ""
-msgid "Your comment will not be visible to the public."
-msgstr "你的留言將ä¸æœƒè¢«å…¬é–‹ã€‚"
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
+msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
msgstr ""
@@ -12958,6 +15641,9 @@ msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
msgstr ""
+msgid "Your message here"
+msgstr ""
+
msgid "Your name"
msgstr "您的åå­—"
@@ -12991,17 +15677,20 @@ msgstr "之å‰"
msgid "allowed to fail"
msgstr ""
-msgid "among other things"
-msgstr "除了其他事情"
+msgid "already being used for another group or project milestone."
+msgstr ""
-msgid "at"
+msgid "already shared with this group"
msgstr ""
+msgid "among other things"
+msgstr "除了其他事情"
+
msgid "attach a new file"
msgstr ""
msgid "authored"
-msgstr ""
+msgstr "編輯於"
msgid "branch name"
msgstr "分支å稱"
@@ -13009,6 +15698,21 @@ msgstr "分支å稱"
msgid "by"
msgstr "來自"
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr "%{linkStartTag}關於容器掃æ的更多資訊%{linkEndTag}"
@@ -13096,6 +15800,9 @@ msgstr "(正在載入)"
msgid "ciReport|(is loading, errors when loading results)"
msgstr "(正在載入,當載入çµæžœæ™‚發生錯誤)"
+msgid "ciReport|All confidence levels"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -13129,9 +15836,6 @@ msgstr ""
msgid "ciReport|Create merge request"
msgstr ""
-msgid "ciReport|Created %{eventType}"
-msgstr ""
-
msgid "ciReport|DAST"
msgstr "DAST"
@@ -13147,12 +15851,6 @@ msgstr "正在掃æä¾è³´é—œä¿‚"
msgid "ciReport|Description"
msgstr "說明"
-msgid "ciReport|Dismiss vulnerability"
-msgstr "忽略æ¼æ´ž"
-
-msgid "ciReport|Dismissed by"
-msgstr "忽略由"
-
msgid "ciReport|Download and apply the patch to fix this vulnerability."
msgstr ""
@@ -13219,7 +15917,7 @@ msgid "ciReport|Namespace"
msgstr "命å空間"
msgid "ciReport|No changes to code quality"
-msgstr "沒有程å¼ç¢¼å“質的變更"
+msgstr "程å¼ç¢¼å“質沒有變更"
msgid "ciReport|No changes to performance metrics"
msgstr "沒有效能指標的變動"
@@ -13269,9 +15967,6 @@ msgstr "載入相ä¾æ€§æŽƒæ報告時發生錯誤。"
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr "撤回é§å›žæ™‚發生錯誤。請é‡è©¦ã€‚"
-msgid "ciReport|Undo dismiss"
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr "å°‡ %{name} 從 %{version} å‡ç´šåˆ° %{fixed}。"
@@ -13288,12 +15983,12 @@ msgstr[0] "由 %{packagesString} 和 %{lastPackage} 使用"
msgid "ciReport|View full report"
msgstr "檢視完整報告"
-msgid "ciReport|on pipeline"
-msgstr "管線上"
-
msgid "commented on %{link_to_project}"
msgstr ""
+msgid "commit %{commit_id}"
+msgstr ""
+
msgid "confidence|Confirmed"
msgstr ""
@@ -13333,6 +16028,9 @@ msgstr "無法存å–ç§é‘°ï¼Œæª¢æŸ¥å¯†ç¢¼æ˜¯å¦æ­£ç¢ºï¼Ÿ"
msgid "customize"
msgstr "自訂"
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] "æ—¥"
@@ -13341,7 +16039,7 @@ msgid "deleted"
msgstr ""
msgid "deploy token"
-msgstr "部署憑證"
+msgstr "佈署憑證"
msgid "detached"
msgstr ""
@@ -13360,12 +16058,18 @@ msgid "draft"
msgid_plural "drafts"
msgstr[0] "è‰ç¨¿"
+msgid "element is not a hierarchy"
+msgstr ""
+
msgid "enabled"
msgstr "已啟用"
-msgid "epic"
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
msgstr ""
+msgid "epic"
+msgstr "å²è©©"
+
msgid "error"
msgstr ""
@@ -13375,6 +16079,12 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr "%{slash_command} 將更新é ä¼°èŠ±è²»æ™‚間。"
+msgid "expired on %{milestone_due_date}"
+msgstr ""
+
+msgid "expires on %{milestone_due_date}"
+msgstr ""
+
msgid "failed"
msgstr ""
@@ -13399,6 +16109,9 @@ msgstr "來自"
msgid "group"
msgstr ""
+msgid "has already been taken"
+msgstr ""
+
msgid "here"
msgstr "這裡"
@@ -13427,6 +16140,12 @@ msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] "實例完æˆ"
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
msgid "is invalid because there is downstream lock"
msgstr "因為下游鎖定,所以無效"
@@ -13436,6 +16155,9 @@ msgstr "因上游鎖定而無效"
msgid "is not a valid X509 certificate."
msgstr "éžæœ‰æ•ˆ X509 憑證。"
+msgid "is not an email you own"
+msgstr ""
+
msgid "is out of the hierarchy of the Group owning the template"
msgstr ""
@@ -13454,11 +16176,14 @@ msgstr ""
msgid "it is too large"
msgstr ""
+msgid "jigsaw is not defined"
+msgstr ""
+
msgid "latest"
msgstr ""
msgid "latest deployment"
-msgstr "最新的部署"
+msgstr "最新的佈署"
msgid "latest version"
msgstr "最新版本"
@@ -13479,6 +16204,9 @@ msgid "merge request"
msgid_plural "merge requests"
msgstr[0] "åˆä½µè«‹æ±‚"
+msgid "milestone should belong either to a project or a group."
+msgstr ""
+
msgid "missing"
msgstr ""
@@ -13506,8 +16234,8 @@ msgstr "%{metricsLinkStart} 記憶體 %{metricsLinkEnd} 使用 %{emphasisStart}
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "%{metricsLinkStart} 記憶體 %{metricsLinkEnd} 使用 %{emphasisStart} 沒有發生變化 %{emphasisEnd} 於 %{memoryFrom} MB"
-msgid "mrWidget|Add approval"
-msgstr "新增批准"
+msgid "mrWidget|Added to the merge train by"
+msgstr ""
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "å…許å¯ä»¥åˆä½µåˆ°ç›®æ¨™åˆ†æ”¯çš„æˆå“¡æ交"
@@ -13521,6 +16249,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "æ交你的請批準時發生錯誤。"
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
msgid "mrWidget|Approve"
msgstr "批准"
@@ -13561,7 +16292,7 @@ msgid "mrWidget|Delete source branch"
msgstr ""
msgid "mrWidget|Deployment statistics are not available currently"
-msgstr "ç›®å‰ç„¡æ³•ä½¿ç”¨éƒ¨ç½²çš„統計資料"
+msgstr "ç›®å‰ç„¡æ³•ä½¿ç”¨ä½ˆç½²çš„統計資料"
msgid "mrWidget|Did not close"
msgstr "沒有關閉"
@@ -13570,11 +16301,14 @@ msgid "mrWidget|Email patches"
msgstr "Email 補ä¸"
msgid "mrWidget|Failed to load deployment statistics"
-msgstr "讀å–部署統計資料時發生錯誤"
+msgstr "讀å–佈署統計資料時發生錯誤"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr "無法進行快速åˆä½µã€‚è¦åˆä½µæ­¤è«‹æ±‚,請先在本定進行 rebase。"
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr "如果 %{branch} 分支存在於您的本機版本庫,你å¯ä»¥æ‰‹å‹•åˆä½µæ­¤åˆä½µè«‹æ±‚,藉由"
@@ -13582,7 +16316,7 @@ msgid "mrWidget|If the %{missingBranchName} branch exists in your local reposito
msgstr "如果 %{missingBranchName} 分支徂在於您的本機版本庫,您å¯ä»¥æ‰‹å‹•åˆä½µæ­¤åˆä½µè«‹æ±‚藉由此指令"
msgid "mrWidget|Loading deployment statistics"
-msgstr "讀å–部署統計資料"
+msgstr "讀å–佈署統計資料"
msgid "mrWidget|Mentions"
msgstr "æ到"
@@ -13593,18 +16327,15 @@ msgstr "åˆä½µ"
msgid "mrWidget|Merge failed."
msgstr "åˆä½µå¤±æ•—"
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
+msgstr ""
+
msgid "mrWidget|Merge locally"
msgstr "本機åˆä½µ"
-msgid "mrWidget|Merge request approved"
-msgstr "åˆä½µè«‹æ±‚已經批准"
-
msgid "mrWidget|Merge request approved."
msgstr ""
-msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr "åˆä½µè«‹æ±‚已經被批准; ä½ å¯ä»¥å¦å¤–批准"
-
msgid "mrWidget|Merged by"
msgstr "åˆä½µè€…"
@@ -13635,20 +16366,12 @@ msgstr "ç«‹å³é‡æ–°æ•´ç†"
msgid "mrWidget|Refreshing now"
msgstr "ç«‹å³é‡æ–°æ•´ç†"
-msgid "mrWidget|Remove your approval"
-msgstr "移除您的批准"
+msgid "mrWidget|Remove from merge train"
+msgstr ""
msgid "mrWidget|Request to merge"
msgstr "請求åˆä½µ"
-msgid "mrWidget|Requires 1 more approval"
-msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] "éœ€è¦ %d 個批准"
-
-msgid "mrWidget|Requires 1 more approval by"
-msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] "éœ€è¦ %d 個來自該使用者的批准:"
-
msgid "mrWidget|Resolve conflicts"
msgstr "解決è¡çª"
@@ -13733,18 +16456,33 @@ msgstr "指令"
msgid "mrWidget|into"
msgstr "進入"
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr "當管線完æˆæ™‚將會被自動åˆä½µ"
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
msgid "n/a"
msgstr "未知"
+msgid "needs to be beetween 10 minutes and 1 month"
+msgstr ""
+
msgid "new merge request"
msgstr "建立åˆä½µè«‹æ±‚"
-msgid "none"
+msgid "no contributions"
msgstr ""
+msgid "none"
+msgstr "ç„¡"
+
msgid "notification emails"
msgstr "通知信"
@@ -13792,7 +16530,7 @@ msgid_plural "projects"
msgstr[0] "專案"
msgid "quick actions"
-msgstr ""
+msgstr "快速æ“作"
msgid "register"
msgstr ""
@@ -13846,7 +16584,7 @@ msgstr ""
msgid "severity|Unknown"
msgstr ""
-msgid "should be higher than %{access} inherited membership from group %{group_name}"
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
msgid "show less"
@@ -13855,18 +16593,30 @@ msgstr ""
msgid "sign in"
msgstr ""
+msgid "sort:"
+msgstr ""
+
msgid "source"
msgstr "來æº"
msgid "source diff"
msgstr ""
+msgid "specified top is not part of the tree"
+msgstr ""
+
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} 將會更新ã€åŠ ç¸½æ‰€èŠ±è²»çš„時間"
msgid "started"
msgstr "已開始"
+msgid "started on %{milestone_start_date}"
+msgstr ""
+
+msgid "starts on %{milestone_start_date}"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -13895,17 +16645,38 @@ msgid "username"
msgstr "使用者å稱"
msgid "uses Kubernetes clusters to deploy your code!"
-msgstr "使用 Kubernetes å¢é›†éƒ¨ç½²æ‚¨çš„程å¼ç¢¼!"
+msgstr "使用 Kubernetes å¢é›†ä½ˆç½²æ‚¨çš„程å¼ç¢¼!"
msgid "verify ownership"
msgstr ""
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
msgid "view it on GitLab"
msgstr "在 GitLab 上檢視"
msgid "view the blob"
msgstr ""
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
msgid "with %{additions} additions, %{deletions} deletions."
msgstr "共增加 %{additions} ,刪除 %{deletions}"
diff --git a/package.json b/package.json
index 1cb9f7a9ade..4f61c73698c 100644
--- a/package.json
+++ b/package.json
@@ -1,14 +1,17 @@
{
"private": true,
"scripts": {
+ "check-dependencies": "yarn check --integrity",
"clean": "rm -rf public/assets tmp/cache/*-loader",
"dev-server": "NODE_OPTIONS=\"--max-old-space-size=3584\" nodemon -w 'config/webpack.config.js' --exec 'webpack-dev-server --config config/webpack.config.js'",
"eslint": "eslint --max-warnings 0 --report-unused-disable-directives --ext .js,.vue .",
"eslint-fix": "eslint --max-warnings 0 --report-unused-disable-directives --ext .js,.vue --fix .",
"eslint-report": "eslint --max-warnings 0 --ext .js,.vue --format html --output-file ./eslint-report.html --no-inline-config .",
- "jest": "BABEL_ENV=jest jest",
- "jest-debug": "BABEL_ENV=jest node --inspect-brk node_modules/.bin/jest --runInBand",
+ "prejest": "yarn check-dependencies",
+ "jest": "jest",
+ "jest-debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
"jsdoc": "jsdoc -c config/jsdocs.config.js",
+ "prekarma": "yarn check-dependencies",
"karma": "BABEL_ENV=${BABEL_ENV:=karma} karma start --single-run true config/karma.config.js",
"karma-coverage": "BABEL_ENV=coverage karma start --single-run true config/karma.config.js",
"karma-start": "BABEL_ENV=karma karma start config/karma.config.js",
@@ -20,23 +23,26 @@
"stylelint": "node node_modules/stylelint/bin/stylelint.js app/assets/stylesheets/**/*.* ee/app/assets/stylesheets/**/*.* !**/vendors/** --custom-formatter node_modules/stylelint-error-string-formatter",
"stylelint-file": "node node_modules/stylelint/bin/stylelint.js",
"stylelint-create-utility-map": "node scripts/frontend/stylelint/stylelint-utility-map.js",
- "test": "yarn jest && yarn karma",
+ "test": "node scripts/frontend/test",
"webpack": "NODE_OPTIONS=\"--max-old-space-size=3584\" webpack --config config/webpack.config.js",
- "webpack-prod": "NODE_OPTIONS=\"--max-old-space-size=3584\" NODE_ENV=production webpack --config config/webpack.config.js"
+ "webpack-prod": "NODE_OPTIONS=\"--max-old-space-size=3584\" NODE_ENV=production webpack --config config/webpack.config.js",
+ "webpack-vrt": "NODE_OPTIONS=\"--max-old-space-size=3584\" NODE_ENV=production webpack --config config/webpack.config.review_toolbar.js"
},
"dependencies": {
- "@babel/core": "^7.2.2",
- "@babel/plugin-proposal-class-properties": "^7.3.0",
+ "@babel/core": "^7.4.4",
+ "@babel/plugin-proposal-class-properties": "^7.4.4",
"@babel/plugin-proposal-json-strings": "^7.2.0",
- "@babel/plugin-proposal-private-methods": "^7.3.0",
+ "@babel/plugin-proposal-private-methods": "^7.4.4",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/plugin-syntax-import-meta": "^7.2.0",
- "@babel/preset-env": "^7.3.1",
+ "@babel/preset-env": "^7.4.4",
"@gitlab/csslab": "^1.9.0",
- "@gitlab/svgs": "^1.59.0",
- "@gitlab/ui": "^3.3.0",
+ "@gitlab/svgs": "^1.63.0",
+ "@gitlab/ui": "^4.0.0",
"apollo-cache-inmemory": "^1.5.1",
"apollo-client": "^2.5.1",
+ "apollo-link": "^1.2.11",
+ "apollo-link-batch-http": "^1.2.11",
"apollo-upload-client": "^10.0.0",
"at.js": "^1.5.4",
"autosize": "^4.0.0",
@@ -50,7 +56,7 @@
"clipboard": "^1.7.1",
"codesandbox-api": "^0.0.20",
"compression-webpack-plugin": "^2.0.0",
- "core-js": "^2.4.1",
+ "core-js": "^3.1.3",
"cropper": "^2.3.0",
"css-loader": "^1.0.0",
"d3": "^4.13.0",
@@ -90,10 +96,11 @@
"jszip-utils": "^0.0.2",
"katex": "^0.10.0",
"marked": "^0.3.12",
- "mermaid": "^8.0.0-rc.8",
+ "mermaid": "^8.0.0",
"monaco-editor": "^0.15.6",
"monaco-editor-webpack-plugin": "^1.7.0",
"mousetrap": "^1.4.6",
+ "pdfjs-dist": "^2.0.943",
"pikaday": "^1.6.1",
"popper.js": "^1.14.7",
"prismjs": "^1.6.0",
@@ -139,7 +146,8 @@
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.2.0",
- "@gitlab/eslint-config": "^1.5.0",
+ "@gitlab/eslint-config": "^1.6.0",
+ "@gitlab/eslint-plugin-i18n": "^1.0.0",
"@vue/test-utils": "^1.0.0-beta.25",
"axios-mock-adapter": "^1.15.0",
"babel-jest": "^24.1.0",
@@ -179,7 +187,7 @@
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^4.0.0-beta.0",
"md5": "^2.2.1",
- "node-sass": "^4.11.0",
+ "node-sass": "^4.12.0",
"nodemon": "^1.18.9",
"pixelmatch": "^4.0.2",
"postcss": "^7.0.14",
diff --git a/qa/Dockerfile b/qa/Dockerfile
index ca7f9accb70..74be373b8e8 100644
--- a/qa/Dockerfile
+++ b/qa/Dockerfile
@@ -1,4 +1,4 @@
-FROM ruby:2.5-stretch
+FROM ruby:2.6-stretch
LABEL maintainer "Grzegorz Bizon <grzegorz@gitlab.com>"
ENV DEBIAN_FRONTEND noninteractive
diff --git a/qa/Gemfile b/qa/Gemfile
index 38e95ba2d65..12994b85322 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -7,6 +7,7 @@ gem 'rake', '~> 12.3.0'
gem 'rspec', '~> 3.7'
gem 'selenium-webdriver', '~> 3.12'
gem 'airborne', '~> 0.2.13'
-gem 'nokogiri', '~> 1.10.1'
+gem 'nokogiri', '~> 1.10.3'
gem 'rspec-retry', '~> 0.6.1'
gem 'faker', '~> 1.6', '>= 1.6.6'
+gem 'knapsack', '~> 1.17'
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index 9d3d42fb6ae..6b0635ed0e2 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -39,6 +39,8 @@ GEM
domain_name (~> 0.5)
i18n (0.9.1)
concurrent-ruby (~> 1.0)
+ knapsack (1.17.1)
+ rake
launchy (2.4.3)
addressable (~> 2.3)
method_source (0.9.0)
@@ -49,7 +51,7 @@ GEM
mini_portile2 (2.4.0)
minitest (5.11.1)
netrc (0.11.0)
- nokogiri (1.10.2)
+ nokogiri (1.10.3)
mini_portile2 (~> 2.4.0)
pry (0.11.3)
coderay (~> 1.1.0)
@@ -102,7 +104,8 @@ DEPENDENCIES
capybara (~> 2.16.1)
capybara-screenshot (~> 1.0.18)
faker (~> 1.6, >= 1.6.6)
- nokogiri (~> 1.10.1)
+ knapsack (~> 1.17)
+ nokogiri (~> 1.10.3)
pry-byebug (~> 3.5.1)
rake (~> 12.3.0)
rspec (~> 3.7)
diff --git a/qa/README.md b/qa/README.md
index 8efdd8514f1..ef6f202464d 100644
--- a/qa/README.md
+++ b/qa/README.md
@@ -1,6 +1,6 @@
# GitLab QA - End-to-end tests for GitLab
-This directory contains [end-to-end tests](doc/development/testing_guide/end_to_end_tests.md)
+This directory contains [end-to-end tests](../../../doc/development/testing_guide/end_to_end/index.md)
for GitLab. It includes the test framework and the tests themselves.
The tests can be found in `qa/specs/features` (not to be confused with the unit
@@ -29,7 +29,7 @@ verify coupling between page objects implemented as a part of GitLab QA
and corresponding views / partials / selectors in CE / EE.
Whenever `qa:selectors` job fails in your merge request, you are supposed to
-fix [page objects](qa/page/README.md). You should also trigger end-to-end tests
+fix [page objects](../doc/development/testing_guide/end_to_end/page_objects.md). You should also trigger end-to-end tests
using `package-and-qa` manual action, to test if everything works fine.
## How can I use it?
@@ -49,8 +49,10 @@ will need to [modify your GDK setup](https://gitlab.com/gitlab-org/gitlab-qa/blo
### Writing tests
-1. [Using page objects](qa/page/README.md)
-2. [Style guide](STYLE_GUIDE.md)
+- [Writing tests from scratch tutorial](../doc/development/testing_guide/end_to_end/quick_start_guide.md)
+ - [Best practices](../doc/development/testing_guide/best_practices.md)
+ - [Using page objects](../doc/development/testing_guide/end_to_end/page_objects.md)
+ - [Guidelines](../doc/development/testing_guide/index.md)
### Running specific tests
diff --git a/qa/STYLE_GUIDE.md b/qa/STYLE_GUIDE.md
deleted file mode 100644
index 900f7456e1a..00000000000
--- a/qa/STYLE_GUIDE.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# Style guide for writing GUI tests
-
-This document describes the conventions used at GitLab for writing GUI tests using the GitLab QA project.
-
-## `click_` versus `go_to_`
-
-### When to use `click_`?
-
-When clicking in a single link to navigate, use `click_`.
-
-E.g.:
-
-```ruby
-def click_ci_cd_pipelines
- within_sidebar do
- click_element :link_pipelines
- end
-end
-```
-
-From a testing perspective, if we want to check that clicking a link, or a button (a single interaction) is working as intended, we would want the test to read as:
-
-- Click a certain element
-- Verify the action took place
-
-### When to use `go_to_`?
-
-When interacting with multiple elements to go to a page, use `go_to_`.
-
-E.g.:
-
-```ruby
-def go_to_operations_environments
- hover_operations do
- within_submenu do
- click_element(:operations_environments_link)
- end
- end
-end
-```
-
-`go_to_` fits the definition of interacting with multiple elements very well given it's more of a meta-navigation action that includes multiple interactions.
-
-Notice that in the above example, before clicking the `:operations_environments_link`, another element is hovered over.
-
-> We can create these methods as helpers to abstract multi-step navigation. \ No newline at end of file
diff --git a/qa/knapsack/gitlab-ce/review-qa-all_master_report.json b/qa/knapsack/gitlab-ce/review-qa-all_master_report.json
new file mode 100644
index 00000000000..f147346ba0f
--- /dev/null
+++ b/qa/knapsack/gitlab-ce/review-qa-all_master_report.json
@@ -0,0 +1,42 @@
+{
+ "qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb": 9.697327613830566,
+ "qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb": 46.54227638244629,
+ "qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb": 10.214765310287476,
+ "qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb": 7.882027864456177,
+ "qa/specs/features/api/3_create/repository/files_spec.rb": 5.015859127044678,
+ "qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb": 12.772682905197144,
+ "qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb": 29.76174831390381,
+ "qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb": 22.800872802734375,
+ "qa/specs/features/browser_ui/1_manage/login/register_spec.rb": 22.320587396621704,
+ "qa/specs/features/api/1_manage/users_spec.rb": 0.6089541912078857,
+ "qa/specs/features/browser_ui/3_create/repository/clone_spec.rb": 0.9618203639984131,
+ "qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb": 13.403101205825806,
+ "qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb": 8.810423135757446,
+ "qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb": 7.730542182922363,
+ "qa/specs/features/browser_ui/3_create/repository/add_ssh_key_spec.rb": 16.18057894706726,
+ "qa/specs/features/browser_ui/4_verify/ci_variable/add_ci_variable_spec.rb": 8.31815505027771,
+ "qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb": 9.48607873916626,
+ "qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb": 19.552733182907104,
+ "qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb": 17.273863554000854,
+ "qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb": 8.281434059143066,
+ "qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb": 18.047621726989746,
+ "qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb": 7.422840595245361,
+ "qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb": 3.438166856765747,
+ "qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb": 18.679633855819702,
+ "qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb": 27.943300485610962,
+ "qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb": 39.17585229873657,
+ "qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb": 40.09336972236633,
+ "qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb": 3.705310821533203,
+ "qa/specs/features/browser_ui/3_create/snippet/create_snippet_spec.rb": 5.812374591827393,
+ "qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb": 92.46774697303772,
+ "qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb": 100.28881478309631,
+ "qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb": 23.710937023162842,
+ "qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb": 20.58603596687317,
+ "qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb": 25.460349321365356,
+ "qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb": 19.459370374679565,
+ "qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb": 6.731764793395996,
+ "qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb": 15.342933893203735,
+ "qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb": 11.280649185180664,
+ "qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb": 57.48992609977722,
+ "qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb": 32.5517954826355
+} \ No newline at end of file
diff --git a/qa/qa.rb b/qa/qa.rb
index 672f4aa928a..944dcc31917 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -130,6 +130,7 @@ module QA
autoload :View, 'qa/page/view'
autoload :Element, 'qa/page/element'
autoload :Validator, 'qa/page/validator'
+ autoload :Validatable, 'qa/page/validatable'
module Main
autoload :Login, 'qa/page/main/login'
@@ -275,6 +276,7 @@ module QA
module Layout
autoload :Banner, 'qa/page/layout/banner'
+ autoload :PerformanceBar, 'qa/page/layout/performance_bar'
end
module Label
@@ -293,10 +295,12 @@ module QA
module Settings
autoload :Repository, 'qa/page/admin/settings/repository'
autoload :General, 'qa/page/admin/settings/general'
+ autoload :MetricsAndProfiling, 'qa/page/admin/settings/metrics_and_profiling'
module Component
autoload :RepositoryStorage, 'qa/page/admin/settings/component/repository_storage'
autoload :AccountAndLimit, 'qa/page/admin/settings/component/account_and_limit'
+ autoload :PerformanceBar, 'qa/page/admin/settings/component/performance_bar'
end
end
end
diff --git a/qa/qa/ce/strategy.rb b/qa/qa/ce/strategy.rb
index d7748a976f0..018a1eb1bfc 100644
--- a/qa/qa/ce/strategy.rb
+++ b/qa/qa/ce/strategy.rb
@@ -12,8 +12,9 @@ module QA
def perform_before_hooks
# The login page could take some time to load the first time it is visited.
# We visit the login page and wait for it to properly load only once before the tests.
- QA::Runtime::Browser.visit(:gitlab, QA::Page::Main::Login)
- QA::Page::Main::Login.perform(&:assert_page_loaded)
+ QA::Support::Retrier.retry_on_exception do
+ QA::Runtime::Browser.visit(:gitlab, QA::Page::Main::Login)
+ end
end
end
end
diff --git a/qa/qa/fixtures/auto_devops_rack/Dockerfile b/qa/qa/fixtures/auto_devops_rack/Dockerfile
new file mode 100644
index 00000000000..1f59c23ea88
--- /dev/null
+++ b/qa/qa/fixtures/auto_devops_rack/Dockerfile
@@ -0,0 +1,9 @@
+FROM ruby:2.6.3-alpine
+ADD ./ /app/
+WORKDIR /app
+ENV RACK_ENV production
+ENV PORT 5000
+EXPOSE 5000
+
+RUN bundle install
+CMD ["bundle","exec", "rackup", "-p", "5000"]
diff --git a/qa/qa/git/repository.rb b/qa/qa/git/repository.rb
index b3bad40a90f..84353e3d0c7 100644
--- a/qa/qa/git/repository.rb
+++ b/qa/qa/git/repository.rb
@@ -251,7 +251,7 @@ module QA
end
def netrc_already_contains_content?
- read_netrc_content.grep(/^#{netrc_content}$/).any?
+ read_netrc_content.grep(/^#{Regexp.escape(netrc_content)}$/).any?
end
end
end
diff --git a/qa/qa/page/README.md b/qa/qa/page/README.md
deleted file mode 100644
index d0de33892c4..00000000000
--- a/qa/qa/page/README.md
+++ /dev/null
@@ -1,134 +0,0 @@
-# Page objects in GitLab QA
-
-In GitLab QA we are using a known pattern, called _Page Objects_.
-
-This means that we have built an abstraction for all GitLab pages that we use
-to drive GitLab QA scenarios. Whenever we do something on a page, like filling
-in a form, or clicking a button, we do that only through a page object
-associated with this area of GitLab.
-
-For example, when GitLab QA test harness signs in into GitLab, it needs to fill
-in a user login and user password. In order to do that, we have a class, called
-`Page::Main::Login` and `sign_in_using_credentials` methods, that is the only
-piece of the code, that has knowledge about `user_login` and `user_password`
-fields.
-
-## Why do we need that?
-
-We need page objects, because we need to reduce duplication and avoid problems
-whenever someone changes some selectors in GitLab's source code.
-
-Imagine that we have a hundred specs in GitLab QA, and we need to sign into
-GitLab each time, before we make assertions. Without a page object one would
-need to rely on volatile helpers or invoke Capybara methods directly. Imagine
-invoking `fill_in :user_login` in every `*_spec.rb` file / test example.
-
-When someone later changes `t.text_field :login` in the view associated with
-this page to `t.text_field :username` it will generate a different field
-identifier, what would effectively break all tests.
-
-Because we are using `Page::Main::Login.act { sign_in_using_credentials }`
-everywhere, when we want to sign into GitLab, the page object is the single
-source of truth, and we will need to update `fill_in :user_login`
-to `fill_in :user_username` only in a one place.
-
-## What problems did we have in the past?
-
-We do not run QA tests for every commit, because of performance reasons, and
-the time it would take to build packages and test everything.
-
-That is why when someone changes `t.text_field :login` to
-`t.text_field :username` in the _new session_ view we won't know about this
-change until our GitLab QA nightly pipeline fails, or until someone triggers
-`package-and-qa` action in their merge request.
-
-Obviously such a change would break all tests. We call this problem a _fragile
-tests problem_.
-
-In order to make GitLab QA more reliable and robust, we had to solve this
-problem by introducing coupling between GitLab CE / EE views and GitLab QA.
-
-## How did we solve fragile tests problem?
-
-Currently, when you add a new `Page::Base` derived class, you will also need to
-define all selectors that your page objects depends on.
-
-Whenever you push your code to CE / EE repository, `qa:selectors` sanity test
-job is going to be run as a part of a CI pipeline.
-
-This test is going to validate all page objects that we have implemented in
-`qa/page` directory. When it fails, you will be notified about missing
-or invalid views / selectors definition.
-
-## How to properly implement a page object?
-
-We have built a DSL to define coupling between a page object and GitLab views
-it is actually implemented by. See an example below.
-
-```ruby
-module Page
- module Main
- class Login < Page::Base
- view 'app/views/devise/passwords/edit.html.haml' do
- element :password_field
- element :password_confirmation
- element :change_password_button
- end
-
- view 'app/views/devise/sessions/_new_base.html.haml' do
- element :login_field
- element :password_field
- element :sign_in_button
- end
-
- # ...
- end
-end
-```
-
-The `view` DSL method declares the filename of the view where an
-`element` is implemented.
-
-The `element` DSL method in turn declares an element for which a corresponding
-`qa-element-name-dasherized` CSS class need to be added to the view file.
-
-You can also define a value (String or Regexp) to match to the actual view
-code but **this is deprecated** in favor of the above method for two reasons:
-
-- Consistency: there is only one way to define an element
-- Separation of concerns: QA uses dedicated CSS classes instead of reusing code
- or classes used by other components (e.g. `js-*` classes etc.)
-
-```ruby
-view 'app/views/my/view.html.haml' do
- # Implicitly require `.qa-logout-button` CSS class to be present in the view
- element :logout_button
-
- ## This is deprecated and forbidden by the `QA/ElementWithPattern` RuboCop cop.
- # Require `f.submit "Sign in"` to be present in `my/view.html.haml
- element :my_button, 'f.submit "Sign in"' # rubocop:disable QA/ElementWithPattern
-
- ## This is deprecated and forbidden by the `QA/ElementWithPattern` RuboCop cop.
- # Match every line in `my/view.html.haml` against
- # `/link_to .* "My Profile"/` regexp.
- element :profile_link, /link_to .* "My Profile"/ # rubocop:disable QA/ElementWithPattern
-end
-```
-
-## Running the test locally
-
-During development, you can run the `qa:selectors` test by running
-
-```shell
-bin/qa Test::Sanity::Selectors
-```
-
-from within the `qa` directory.
-
-## Where to ask for help?
-
-If you need more information, ask for help on `#quality` channel on Slack
-(internal, GitLab Team only).
-
-If you are not a Team Member, and you still need help to contribute, please
-open an issue in GitLab CE issue tracker with the `~QA` label.
diff --git a/qa/qa/page/admin/menu.rb b/qa/qa/page/admin/menu.rb
index 25564f2dc6e..eea5717f5a7 100644
--- a/qa/qa/page/admin/menu.rb
+++ b/qa/qa/page/admin/menu.rb
@@ -10,6 +10,7 @@ module QA
element :admin_settings_item
element :admin_settings_repository_item
element :admin_settings_general_item
+ element :admin_settings_metrics_and_profiling_item
end
def go_to_repository_settings
@@ -28,6 +29,14 @@ module QA
end
end
+ def go_to_metrics_and_profiling_settings
+ hover_settings do
+ within_submenu do
+ click_element :admin_settings_metrics_and_profiling_item
+ end
+ end
+ end
+
private
def hover_settings
diff --git a/qa/qa/page/admin/settings/component/performance_bar.rb b/qa/qa/page/admin/settings/component/performance_bar.rb
new file mode 100644
index 00000000000..bc29efb64c0
--- /dev/null
+++ b/qa/qa/page/admin/settings/component/performance_bar.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Admin
+ module Settings
+ module Component
+ class PerformanceBar < Page::Base
+ view 'app/views/admin/application_settings/_performance_bar.html.haml' do
+ element :enable_performance_bar_checkbox
+ element :save_changes_button
+ end
+
+ def enable_performance_bar
+ click_element :enable_performance_bar_checkbox
+ Capybara.current_session.driver.browser.manage.add_cookie(name: 'perf_bar_enabled', value: 'true')
+ end
+
+ def save_settings
+ click_element :save_changes_button
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/admin/settings/metrics_and_profiling.rb b/qa/qa/page/admin/settings/metrics_and_profiling.rb
new file mode 100644
index 00000000000..e10a92d7a54
--- /dev/null
+++ b/qa/qa/page/admin/settings/metrics_and_profiling.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Admin
+ module Settings
+ class MetricsAndProfiling < Page::Base
+ include QA::Page::Settings::Common
+
+ view 'app/views/admin/application_settings/metrics_and_profiling.html.haml' do
+ element :performance_bar_settings
+ end
+
+ def expand_performance_bar(&block)
+ expand_section(:performance_bar_settings) do
+ Component::PerformanceBar.perform(&block)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb
index 9fabf83e2ce..d0fe2987b0a 100644
--- a/qa/qa/page/base.rb
+++ b/qa/qa/page/base.rb
@@ -8,6 +8,7 @@ module QA
prepend Support::Page::Logging if Runtime::Env.debug?
include Capybara::DSL
include Scenario::Actable
+ extend Validatable
extend SingleForwardable
ElementNotFound = Class.new(RuntimeError)
@@ -77,8 +78,12 @@ module QA
page.evaluate_script('xhr.status') == 200
end
- def find_element(name, text: nil, wait: Capybara.default_max_wait_time)
- find(element_selector_css(name), wait: wait, text: text)
+ def find_element(name, **kwargs)
+ find(element_selector_css(name), kwargs)
+ end
+
+ def active_element?(name)
+ find_element(name, class: 'active')
end
def all_elements(name)
@@ -93,8 +98,10 @@ module QA
find_element(name).set(false)
end
- def click_element(name)
+ # replace with (..., page = self.class)
+ def click_element(name, page = nil)
find_element(name).click
+ page.validate_elements_present! if page
end
def fill_element(name, content)
@@ -113,8 +120,8 @@ module QA
has_css?(element_selector_css(name), wait: wait, text: text)
end
- def has_no_element?(name, wait: Capybara.default_max_wait_time)
- has_no_css?(element_selector_css(name), wait: wait)
+ def has_no_element?(name, text: nil, wait: Capybara.default_max_wait_time)
+ has_no_css?(element_selector_css(name), wait: wait, text: text)
end
def has_text?(text)
@@ -129,8 +136,17 @@ module QA
has_no_css?('.fa-spinner', wait: Capybara.default_max_wait_time)
end
- def within_element(name)
- page.within(element_selector_css(name)) do
+ def wait_for_animated_element(name)
+ # It would be ideal if we could detect when the animation is complete
+ # but in some cases there's nothing we can easily access via capybara
+ # so instead we wait for the element, and then we wait a little longer
+ raise ElementNotFound, %Q(Couldn't find element named "#{name}") unless has_element?(name)
+
+ sleep 1
+ end
+
+ def within_element(name, text: nil)
+ page.within(element_selector_css(name), text: text) do
yield
end
end
@@ -181,6 +197,10 @@ module QA
views.map(&:elements).flatten
end
+ def send_keys_to_element(name, keys)
+ find_element(name).send_keys(keys)
+ end
+
class DSL
attr_reader :views
diff --git a/qa/qa/page/component/note.rb b/qa/qa/page/component/note.rb
index f5add6bc9b5..07e191f1c9b 100644
--- a/qa/qa/page/component/note.rb
+++ b/qa/qa/page/component/note.rb
@@ -15,7 +15,7 @@ module QA
element :reply_comment_button
end
- base.view 'app/assets/javascripts/notes/components/noteable_discussion.vue' do
+ base.view 'app/assets/javascripts/notes/components/discussion_actions.vue' do
element :discussion_reply
end
diff --git a/qa/qa/page/element.rb b/qa/qa/page/element.rb
index d92e71467fe..7a01320901d 100644
--- a/qa/qa/page/element.rb
+++ b/qa/qa/page/element.rb
@@ -1,28 +1,41 @@
# frozen_string_literal: true
+require 'active_support/core_ext/array/extract_options'
+
module QA
module Page
class Element
- attr_reader :name
+ attr_reader :name, :attributes
- def initialize(name, pattern = nil)
+ def initialize(name, *options)
@name = name
- @pattern = pattern || selector
+ @attributes = options.extract_options!
+ @attributes[:pattern] ||= selector
+
+ options.each do |option|
+ if option.is_a?(String) || option.is_a?(Regexp)
+ @attributes[:pattern] = option
+ end
+ end
end
def selector
"qa-#{@name.to_s.tr('_', '-')}"
end
+ def required?
+ !!@attributes[:required]
+ end
+
def selector_css
".#{selector}"
end
def expression
- if @pattern.is_a?(String)
- @_regexp ||= Regexp.new(Regexp.escape(@pattern))
+ if @attributes[:pattern].is_a?(String)
+ @_regexp ||= Regexp.new(Regexp.escape(@attributes[:pattern]))
else
- @pattern
+ @attributes[:pattern]
end
end
diff --git a/qa/qa/page/file/form.rb b/qa/qa/page/file/form.rb
index dd9a9e054e1..e42de7d65c5 100644
--- a/qa/qa/page/file/form.rb
+++ b/qa/qa/page/file/form.rb
@@ -38,6 +38,8 @@ module QA
def commit_changes
click_on 'Commit changes'
+
+ finished_loading?
end
def select_template(template_type, template)
diff --git a/qa/qa/page/layout/performance_bar.rb b/qa/qa/page/layout/performance_bar.rb
new file mode 100644
index 00000000000..0cfef6a5705
--- /dev/null
+++ b/qa/qa/page/layout/performance_bar.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Layout
+ class PerformanceBar < Page::Base
+ view 'app/assets/javascripts/performance_bar/components/performance_bar_app.vue' do
+ element :performance_bar
+ end
+
+ view 'app/assets/javascripts/performance_bar/components/detailed_metric.vue' do
+ element :performance_bar_detailed_metric
+ end
+
+ view 'app/assets/javascripts/performance_bar/components/request_selector.vue' do
+ element :performance_bar_request
+ end
+
+ def has_performance_bar?
+ has_element?(:performance_bar)
+ end
+
+ def has_detailed_metrics?
+ all_elements(:performance_bar_detailed_metric).all? do |metric|
+ metric.has_text?(%r{\d+ms / \d+})
+ end
+ end
+
+ def has_request_for?(path)
+ has_element?(:performance_bar_request, text: path)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb
index 99b3d1b83d3..8970eeb6678 100644
--- a/qa/qa/page/main/login.rb
+++ b/qa/qa/page/main/login.rb
@@ -39,19 +39,7 @@ module QA
end
view 'app/views/layouts/devise.html.haml' do
- element :login_page
- end
-
- def assert_page_loaded
- unless page_loaded?
- raise QA::Runtime::Browser::NotRespondingError, "Login page did not load at #{QA::Page::Main::Login.perform(&:current_url)}"
- end
- end
-
- def page_loaded?
- wait(max: 60) do
- has_element?(:login_page)
- end
+ element :login_page, required: true
end
def sign_in_using_credentials(user = nil)
@@ -159,7 +147,7 @@ module QA
fill_element :login_field, user.username
fill_element :password_field, user.password
- click_element :sign_in_button
+ click_element :sign_in_button, Page::Main::Menu
end
def set_initial_password_if_present
diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb
index e98d531c86e..5eb24d2d2ba 100644
--- a/qa/qa/page/main/menu.rb
+++ b/qa/qa/page/main/menu.rb
@@ -10,15 +10,15 @@ module QA
end
view 'app/views/layouts/header/_default.html.haml' do
- element :navbar
- element :user_avatar
+ element :navbar, required: true
+ element :user_avatar, required: true
element :user_menu, '.dropdown-menu' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/layouts/nav/_dashboard.html.haml' do
element :admin_area_link
- element :projects_dropdown
- element :groups_dropdown
+ element :projects_dropdown, required: true
+ element :groups_dropdown, required: true
element :snippets_link
end
diff --git a/qa/qa/page/project/branches/show.rb b/qa/qa/page/project/branches/show.rb
index 922a6ddb086..480fc7d78cb 100644
--- a/qa/qa/page/project/branches/show.rb
+++ b/qa/qa/page/project/branches/show.rb
@@ -7,6 +7,7 @@ module QA
class Show < Page::Base
view 'app/views/projects/branches/_branch.html.haml' do
element :remove_btn
+ element :branch_name
end
view 'app/views/projects/branches/_panel.html.haml' do
element :all_branches
@@ -27,10 +28,10 @@ module QA
finished_loading?
end
- def has_branch_title?(branch_title)
- within_element(:all_branches) do
- within(".item-title") do
- has_text?(branch_title)
+ def has_no_branch?(branch_name, reload: false)
+ wait(reload: reload) do
+ within_element(:all_branches) do
+ has_no_element?(:branch_name, text: branch_name)
end
end
end
@@ -48,15 +49,6 @@ module QA
click_element(:delete_merged_branches)
end
end
-
- def wait_for_texts_not_to_be_visible(texts)
- text_not_visible = wait do
- texts.all? do |text|
- has_no_text?(text)
- end
- end
- raise "Expected text(s) #{texts} not to be visible" unless text_not_visible
- end
end
end
end
diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb
index 9df3db1bba0..b59540d0377 100644
--- a/qa/qa/page/project/issue/show.rb
+++ b/qa/qa/page/project/issue/show.rb
@@ -8,11 +8,6 @@ module QA
include Page::Component::Issuable::Common
include Page::Component::Note
- view 'app/views/shared/notes/_form.html.haml' do
- element :new_note_form, 'new-note' # rubocop:disable QA/ElementWithPattern
- element :new_note_form, 'attr: :note' # rubocop:disable QA/ElementWithPattern
- end
-
view 'app/assets/javascripts/notes/components/comment_form.vue' do
element :comment_button
element :comment_input
@@ -27,9 +22,25 @@ module QA
element :noteable_note_item
end
+ view 'app/helpers/dropdowns_helper.rb' do
+ element :dropdown_input_field
+ end
+
+ view 'app/views/shared/notes/_form.html.haml' do
+ element :new_note_form, 'new-note' # rubocop:disable QA/ElementWithPattern
+ element :new_note_form, 'attr: :note' # rubocop:disable QA/ElementWithPattern
+ end
+
+ view 'app/views/shared/issuable/_sidebar.html.haml' do
+ element :labels_block
+ element :edit_link_labels
+ element :dropdown_menu_labels
+ end
+
# Adds a comment to an issue
# attachment option should be an absolute path
- def comment(text, attachment: nil)
+ def comment(text, attachment: nil, filter: :all_activities)
+ method("select_#{filter}_filter").call
fill_element :comment_input, text
unless attachment.nil?
@@ -46,6 +57,10 @@ module QA
end
end
+ def select_all_activities_filter
+ select_filter_with_text('Show all activity')
+ end
+
def select_comments_only_filter
select_filter_with_text('Show comments only')
end
@@ -54,8 +69,26 @@ module QA
select_filter_with_text('Show history only')
end
- def select_all_activities_filter
- select_filter_with_text('Show all activity')
+ def select_labels_and_refresh(labels)
+ click_element(:edit_link_labels)
+
+ labels.each do |label|
+ within_element(:dropdown_menu_labels, text: label) do
+ send_keys_to_element(:dropdown_input_field, [label, :enter])
+ end
+ end
+
+ click_body
+
+ labels.each do |label|
+ has_element?(:labels_block, text: label)
+ end
+
+ refresh
+ end
+
+ def text_of_labels_block
+ find_element(:labels_block)
end
private
diff --git a/qa/qa/page/project/new.rb b/qa/qa/page/project/new.rb
index 4f26ca5037c..defd85a5740 100644
--- a/qa/qa/page/project/new.rb
+++ b/qa/qa/page/project/new.rb
@@ -12,6 +12,7 @@ module QA
end
view 'app/views/projects/_new_project_fields.html.haml' do
+ element :initialize_with_readme_checkbox
element :project_namespace_select
element :project_namespace_field, 'namespaces_options' # rubocop:disable QA/ElementWithPattern
element :project_name, 'text_field :name' # rubocop:disable QA/ElementWithPattern
@@ -64,6 +65,10 @@ module QA
def click_github_link
click_link 'GitHub'
end
+
+ def enable_initialize_with_readme
+ check_element :initialize_with_readme_checkbox
+ end
end
end
end
diff --git a/qa/qa/page/project/operations/kubernetes/show.rb b/qa/qa/page/project/operations/kubernetes/show.rb
index 4096f57b7db..c81e13e9b91 100644
--- a/qa/qa/page/project/operations/kubernetes/show.rb
+++ b/qa/qa/page/project/operations/kubernetes/show.rb
@@ -8,8 +8,8 @@ module QA
class Show < Page::Base
view 'app/assets/javascripts/clusters/components/application_row.vue' do
element :application_row, 'js-cluster-application-row-${this.id}' # rubocop:disable QA/ElementWithPattern
- element :install_button, "s__('ClusterIntegration|Install')" # rubocop:disable QA/ElementWithPattern
- element :installed_button, "s__('ClusterIntegration|Installed')" # rubocop:disable QA/ElementWithPattern
+ element :install_button, "__('Install')" # rubocop:disable QA/ElementWithPattern
+ element :installed_button, "__('Installed')" # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/clusters/components/applications.vue' do
diff --git a/qa/qa/page/project/settings/ci_cd.rb b/qa/qa/page/project/settings/ci_cd.rb
index 44a62cf6ccf..b8c5c563da6 100644
--- a/qa/qa/page/project/settings/ci_cd.rb
+++ b/qa/qa/page/project/settings/ci_cd.rb
@@ -1,4 +1,3 @@
-# rubocop:disable Naming/FileName
# frozen_string_literal: true
module QA
diff --git a/qa/qa/page/project/settings/ci_variables.rb b/qa/qa/page/project/settings/ci_variables.rb
index 567fe6f83c8..3621e618bf2 100644
--- a/qa/qa/page/project/settings/ci_variables.rb
+++ b/qa/qa/page/project/settings/ci_variables.rb
@@ -11,6 +11,7 @@ module QA
element :variable_row, '.ci-variable-row-body' # rubocop:disable QA/ElementWithPattern
element :variable_key, '.qa-ci-variable-input-key' # rubocop:disable QA/ElementWithPattern
element :variable_value, '.qa-ci-variable-input-value' # rubocop:disable QA/ElementWithPattern
+ element :variable_masked
end
view 'app/views/ci/variables/_index.html.haml' do
@@ -18,7 +19,7 @@ module QA
element :reveal_values, '.js-secret-value-reveal-button' # rubocop:disable QA/ElementWithPattern
end
- def fill_variable(key, value)
+ def fill_variable(key, value, masked)
keys = all_elements(:ci_variable_input_key)
index = keys.size - 1
@@ -32,6 +33,9 @@ module QA
# The code was inspired from:
# https://github.com/teamcapybara/capybara/blob/679548cea10773d45e32808f4d964377cfe5e892/lib/capybara/selenium/node.rb#L217
execute_script("arguments[0].value = #{value.to_json}", node)
+
+ masked_node = all_elements(:variable_masked)[index]
+ toggle_masked(masked_node, masked)
end
def save_variables
@@ -47,6 +51,24 @@ module QA
find('.qa-ci-variable-input-value').value
end
end
+
+ private
+
+ def toggle_masked(masked_node, masked)
+ wait(reload: false) do
+ masked_node.click
+
+ masked ? masked_enabled?(masked_node) : masked_disabled?(masked_node)
+ end
+ end
+
+ def masked_enabled?(masked_node)
+ masked_node[:class].include?('is-checked')
+ end
+
+ def masked_disabled?(masked_node)
+ !masked_enabled?(masked_node)
+ end
end
end
end
diff --git a/qa/qa/page/project/web_ide/edit.rb b/qa/qa/page/project/web_ide/edit.rb
index ff7cc04e352..b5a36862389 100644
--- a/qa/qa/page/project/web_ide/edit.rb
+++ b/qa/qa/page/project/web_ide/edit.rb
@@ -7,6 +7,10 @@ module QA
class Edit < Page::Base
include Page::Component::DropdownFilter
+ view 'app/assets/javascripts/ide/components/activity_bar.vue' do
+ element :commit_mode_tab
+ end
+
view 'app/assets/javascripts/ide/components/ide_tree.vue' do
element :new_file
end
@@ -17,6 +21,7 @@ module QA
view 'app/assets/javascripts/ide/components/new_dropdown/modal.vue' do
element :full_file_path
+ element :new_file_modal
element :template_list
end
@@ -42,12 +47,19 @@ module QA
def create_new_file_from_template(file_name, template)
click_element :new_file
+
+ # Wait for the modal animation to complete before clicking on the file name
+ wait_for_animated_element(:new_file_modal)
+
within_element(:template_list) do
click_on file_name
rescue Capybara::ElementNotFound
raise ElementNotFound, %Q(Couldn't find file template named "#{file_name}". Please confirm that it is a valid option.)
end
+ # Wait for the modal to fade out too
+ has_no_element?(:new_file_modal)
+
wait(reload: false) do
within_element(:file_templates_bar) do
click_element :file_template_dropdown
@@ -63,10 +75,16 @@ module QA
end
def commit_changes
+ # Clicking :begin_commit_button the first time switches from the
+ # edit to the commit view
+ click_element :begin_commit_button
+ active_element? :commit_mode_tab
+
+ # We need to click :begin_commit_button again
click_element :begin_commit_button
- # After clicking :begin_commit_button there is an animation that
- # hides :begin_commit_button and shows :commit_button
+ # After clicking :begin_commit_button the 2nd time there is an
+ # animation that hides :begin_commit_button and shows :commit_button
#
# Wait for the animation to complete before clicking :commit_button
# otherwise the click will quietly do nothing.
@@ -75,7 +93,10 @@ module QA
has_element?(:commit_button)
end
- # Retry the attempt to click :commit_button just in case part of the
+ # At this point we're ready to commit and the button should be
+ # labelled "Stage & Commit"
+ #
+ # Click :commit_button and keep retrying just in case part of the
# animation is still in process even when the buttons have the
# expected visibility.
commit_success_msg_shown = retry_until do
diff --git a/qa/qa/page/validatable.rb b/qa/qa/page/validatable.rb
new file mode 100644
index 00000000000..8467d261285
--- /dev/null
+++ b/qa/qa/page/validatable.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Validatable
+ PageValidationError = Class.new(StandardError)
+
+ def validate_elements_present!
+ base_page = self.new
+
+ elements.each do |element|
+ next unless element.required?
+
+ # TODO: this wait needs to be replaced by the wait class
+ unless base_page.has_element?(element.name, wait: 60)
+ raise Validatable::PageValidationError, "#{element.name} did not appear on #{self.name} as expected"
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/view.rb b/qa/qa/page/view.rb
index 96f3917a8ab..613059b2d32 100644
--- a/qa/qa/page/view.rb
+++ b/qa/qa/page/view.rb
@@ -50,8 +50,8 @@ module QA
@elements = []
end
- def element(name, pattern = nil)
- @elements.push(Page::Element.new(name, pattern))
+ def element(name, *args)
+ @elements.push(Page::Element.new(name, *args))
end
end
end
diff --git a/qa/qa/resource/README.md b/qa/qa/resource/README.md
deleted file mode 100644
index 4cdeb3f42a2..00000000000
--- a/qa/qa/resource/README.md
+++ /dev/null
@@ -1,392 +0,0 @@
-# Resource class in GitLab QA
-
-Resources are primarily created using Browser UI steps, but can also
-be created via the API.
-
-## How to properly implement a resource class?
-
-All resource classes should inherit from [`Resource::Base`](./base.rb).
-
-There is only one mandatory method to implement to define a resource class.
-This is the `#fabricate!` method, which is used to build the resource via the
-browser UI. Note that you should only use [Page objects](../page/README.md) to
-interact with a Web page in this method.
-
-Here is an imaginary example:
-
-```ruby
-module QA
- module Resource
- class Shirt < Base
- attr_accessor :name
-
- def fabricate!
- Page::Dashboard::Index.perform do |dashboard_index|
- dashboard_index.go_to_new_shirt
- end
-
- Page::Shirt::New.perform do |shirt_new|
- shirt_new.set_name(name)
- shirt_new.create_shirt!
- end
- end
- end
- end
-end
-```
-
-### Define API implementation
-
-A resource class may also implement the three following methods to be able to
-create the resource via the public GitLab API:
-
-- `#api_get_path`: The `GET` path to fetch an existing resource.
-- `#api_post_path`: The `POST` path to create a new resource.
-- `#api_post_body`: The `POST` body (as a Ruby hash) to create a new resource.
-
-Let's take the `Shirt` resource class, and add these three API methods:
-
-```ruby
-module QA
- module Resource
- class Shirt < Base
- attr_accessor :name
-
- def fabricate!
- # ... same as before
- end
-
- def api_get_path
- "/shirt/#{name}"
- end
-
- def api_post_path
- "/shirts"
- end
-
- def api_post_body
- {
- name: name
- }
- end
- end
- end
-end
-```
-
-The [`Project` resource](./project.rb) is a good real example of Browser
-UI and API implementations.
-
-#### Resource attributes
-
-A resource may need another resource to exist first. For instance, a project
-needs a group to be created in.
-
-To define a resource attribute, you can use the `attribute` method with a
-block using the other resource class to fabricate the resource.
-
-That will allow access to the other resource from your resource object's
-methods. You would usually use it in `#fabricate!`, `#api_get_path`,
-`#api_post_path`, `#api_post_body`.
-
-Let's take the `Shirt` resource class, and add a `project` attribute to it:
-
-```ruby
-module QA
- module Resource
- class Shirt < Base
- attr_accessor :name
-
- attribute :project do
- Project.fabricate! do |resource|
- resource.name = 'project-to-create-a-shirt'
- end
- end
-
- def fabricate!
- project.visit!
-
- Page::Project::Show.perform do |project_show|
- project_show.go_to_new_shirt
- end
-
- Page::Shirt::New.perform do |shirt_new|
- shirt_new.set_name(name)
- shirt_new.create_shirt!
- end
- end
-
- def api_get_path
- "/project/#{project.path}/shirt/#{name}"
- end
-
- def api_post_path
- "/project/#{project.path}/shirts"
- end
-
- def api_post_body
- {
- name: name
- }
- end
- end
- end
-end
-```
-
-**Note that all the attributes are lazily constructed. This means if you want
-a specific attribute to be fabricated first, you'll need to call the
-attribute method first even if you're not using it.**
-
-#### Product data attributes
-
-Once created, you may want to populate a resource with attributes that can be
-found in the Web page, or in the API response.
-For instance, once you create a project, you may want to store its repository
-SSH URL as an attribute.
-
-Again we could use the `attribute` method with a block, using a page object
-to retrieve the data on the page.
-
-Let's take the `Shirt` resource class, and define a `:brand` attribute:
-
-```ruby
-module QA
- module Resource
- class Shirt < Base
- attr_accessor :name
-
- attribute :project do
- Project.fabricate! do |resource|
- resource.name = 'project-to-create-a-shirt'
- end
- end
-
- # Attribute populated from the Browser UI (using the block)
- attribute :brand do
- Page::Shirt::Show.perform do |shirt_show|
- shirt_show.fetch_brand_from_page
- end
- end
-
- # ... same as before
- end
- end
-end
-```
-
-**Note again that all the attributes are lazily constructed. This means if
-you call `shirt.brand` after moving to the other page, it'll not properly
-retrieve the data because we're no longer on the expected page.**
-
-Consider this:
-
-```ruby
-shirt =
- QA::Resource::Shirt.fabricate! do |resource|
- resource.name = "GitLab QA"
- end
-
-shirt.project.visit!
-
-shirt.brand # => FAIL!
-```
-
-The above example will fail because now we're on the project page, trying to
-construct the brand data from the shirt page, however we moved to the project
-page already. There are two ways to solve this, one is that we could try to
-retrieve the brand before visiting the project again:
-
-```ruby
-shirt =
- QA::Resource::Shirt.fabricate! do |resource|
- resource.name = "GitLab QA"
- end
-
-shirt.brand # => OK!
-
-shirt.project.visit!
-
-shirt.brand # => OK!
-```
-
-The attribute will be stored in the instance therefore all the following calls
-will be fine, using the data previously constructed. If we think that this
-might be too brittle, we could eagerly construct the data right before
-ending fabrication:
-
-```ruby
-module QA
- module Resource
- class Shirt < Base
- # ... same as before
-
- def fabricate!
- project.visit!
-
- Page::Project::Show.perform do |project_show|
- project_show.go_to_new_shirt
- end
-
- Page::Shirt::New.perform do |shirt_new|
- shirt_new.set_name(name)
- shirt_new.create_shirt!
- end
-
- populate(:brand) # Eagerly construct the data
- end
- end
- end
-end
-```
-
-The `populate` method will iterate through its arguments and call each
-attribute respectively. Here `populate(:brand)` has the same effect as
-just `brand`. Using the populate method makes the intention clearer.
-
-With this, it will make sure we construct the data right after we create the
-shirt. The drawback is that this will always construct the data when the
-resource is fabricated even if we don't need to use the data.
-
-Alternatively, we could just make sure we're on the right page before
-constructing the brand data:
-
-```ruby
-module QA
- module Resource
- class Shirt < Base
- attr_accessor :name
-
- attribute :project do
- Project.fabricate! do |resource|
- resource.name = 'project-to-create-a-shirt'
- end
- end
-
- # Attribute populated from the Browser UI (using the block)
- attribute :brand do
- back_url = current_url
- visit!
-
- Page::Shirt::Show.perform do |shirt_show|
- shirt_show.fetch_brand_from_page
- end
-
- visit(back_url)
- end
-
- # ... same as before
- end
- end
-end
-```
-
-This will make sure it's on the shirt page before constructing brand, and
-move back to the previous page to avoid breaking the state.
-
-#### Define an attribute based on an API response
-
-Sometimes, you want to define a resource attribute based on the API response
-from its `GET` or `POST` request. For instance, if the creation of a shirt via
-the API returns
-
-```ruby
-{
- brand: 'a-brand-new-brand',
- style: 't-shirt',
- materials: [[:cotton, 80], [:polyamide, 20]]
-}
-```
-
-you may want to store `style` as-is in the resource, and fetch the first value
-of the first `materials` item in a `main_fabric` attribute.
-
-Let's take the `Shirt` resource class, and define a `:style` and a
-`:main_fabric` attributes:
-
-```ruby
-module QA
- module Resource
- class Shirt < Base
- # ... same as before
-
- # @style from the instance if present,
- # or fetched from the API response if present,
- # or a QA::Resource::Base::NoValueError is raised otherwise
- attribute :style
-
- # If @main_fabric is not present,
- # and if the API does not contain this field, this block will be
- # used to construct the value based on the API response, and
- # store the result in @main_fabric
- attribute :main_fabric do
- api_response.&dig(:materials, 0, 0)
- end
-
- # ... same as before
- end
- end
-end
-```
-
-**Notes on attributes precedence:**
-
-- resource instance variables have the highest precedence
-- attributes from the API response take precedence over attributes from the
- block (usually from Browser UI)
-- attributes without a value will raise a `QA::Resource::Base::NoValueError` error
-
-## Creating resources in your tests
-
-To create a resource in your tests, you can call the `.fabricate!` method on
-the resource class.
-Note that if the resource class supports API fabrication, this will use this
-fabrication by default.
-
-Here is an example that will use the API fabrication method under the hood
-since it's supported by the `Shirt` resource class:
-
-```ruby
-my_shirt = Resource::Shirt.fabricate! do |shirt|
- shirt.name = 'my-shirt'
-end
-
-expect(page).to have_text(my_shirt.name) # => "my-shirt" from the resource's instance variable
-expect(page).to have_text(my_shirt.brand) # => "a-brand-new-brand" from the API response
-expect(page).to have_text(my_shirt.style) # => "t-shirt" from the API response
-expect(page).to have_text(my_shirt.main_fabric) # => "cotton" from the API response via the block
-```
-
-If you explicitly want to use the Browser UI fabrication method, you can call
-the `.fabricate_via_browser_ui!` method instead:
-
-```ruby
-my_shirt = Resource::Shirt.fabricate_via_browser_ui! do |shirt|
- shirt.name = 'my-shirt'
-end
-
-expect(page).to have_text(my_shirt.name) # => "my-shirt" from the resource's instance variable
-expect(page).to have_text(my_shirt.brand) # => the brand name fetched from the `Page::Shirt::Show` page via the block
-expect(page).to have_text(my_shirt.style) # => QA::Resource::Base::NoValueError will be raised because no API response nor a block is provided
-expect(page).to have_text(my_shirt.main_fabric) # => QA::Resource::Base::NoValueError will be raised because no API response and the block didn't provide a value (because it's also based on the API response)
-```
-
-You can also explicitly use the API fabrication method, by calling the
-`.fabricate_via_api!` method:
-
-```ruby
-my_shirt = Resource::Shirt.fabricate_via_api! do |shirt|
- shirt.name = 'my-shirt'
-end
-```
-
-In this case, the result will be similar to calling
-`Resource::Shirt.fabricate!`.
-
-## Where to ask for help?
-
-If you need more information, ask for help on `#quality` channel on Slack
-(internal, GitLab Team only).
-
-If you are not a Team Member, and you still need help to contribute, please
-open an issue in GitLab CE issue tracker with the `~QA` label.
diff --git a/qa/qa/resource/base.rb b/qa/qa/resource/base.rb
index 523d92c7ef3..283fc6cdbcb 100644
--- a/qa/qa/resource/base.rb
+++ b/qa/qa/resource/base.rb
@@ -15,6 +15,38 @@ module QA
def_delegators :evaluator, :attribute
+ def self.fabricate!(*args, &prepare_block)
+ fabricate_via_api!(*args, &prepare_block)
+ rescue NotImplementedError
+ fabricate_via_browser_ui!(*args, &prepare_block)
+ end
+
+ def self.fabricate_via_browser_ui!(*args, &prepare_block)
+ options = args.extract_options!
+ resource = options.fetch(:resource) { new }
+ parents = options.fetch(:parents) { [] }
+
+ do_fabricate!(resource: resource, prepare_block: prepare_block, parents: parents) do
+ log_fabrication(:browser_ui, resource, parents, args) { resource.fabricate!(*args) }
+
+ current_url
+ end
+ end
+
+ def self.fabricate_via_api!(*args, &prepare_block)
+ options = args.extract_options!
+ resource = options.fetch(:resource) { new }
+ parents = options.fetch(:parents) { [] }
+
+ raise NotImplementedError unless resource.api_support?
+
+ resource.eager_load_api_client!
+
+ do_fabricate!(resource: resource, prepare_block: prepare_block, parents: parents) do
+ log_fabrication(:api, resource, parents, args) { resource.fabricate_via_api! }
+ end
+ end
+
def fabricate!(*_args)
raise NotImplementedError
end
@@ -55,38 +87,6 @@ module QA
QA::Runtime::Logger.info "<#{self.class}> Attribute #{name.inspect} has both API response `#{api_value}` and a block. API response will be picked. Block will be ignored."
end
- def self.fabricate!(*args, &prepare_block)
- fabricate_via_api!(*args, &prepare_block)
- rescue NotImplementedError
- fabricate_via_browser_ui!(*args, &prepare_block)
- end
-
- def self.fabricate_via_browser_ui!(*args, &prepare_block)
- options = args.extract_options!
- resource = options.fetch(:resource) { new }
- parents = options.fetch(:parents) { [] }
-
- do_fabricate!(resource: resource, prepare_block: prepare_block, parents: parents) do
- log_fabrication(:browser_ui, resource, parents, args) { resource.fabricate!(*args) }
-
- current_url
- end
- end
-
- def self.fabricate_via_api!(*args, &prepare_block)
- options = args.extract_options!
- resource = options.fetch(:resource) { new }
- parents = options.fetch(:parents) { [] }
-
- raise NotImplementedError unless resource.api_support?
-
- resource.eager_load_api_client!
-
- do_fabricate!(resource: resource, prepare_block: prepare_block, parents: parents) do
- log_fabrication(:api, resource, parents, args) { resource.fabricate_via_api! }
- end
- end
-
def self.do_fabricate!(resource:, prepare_block:, parents: [])
prepare_block.call(resource) if prepare_block
diff --git a/qa/qa/resource/ci_variable.rb b/qa/qa/resource/ci_variable.rb
index d82de4cb816..b178a64b72d 100644
--- a/qa/qa/resource/ci_variable.rb
+++ b/qa/qa/resource/ci_variable.rb
@@ -3,7 +3,7 @@
module QA
module Resource
class CiVariable < Base
- attr_accessor :key, :value
+ attr_accessor :key, :value, :masked
attribute :project do
Project.fabricate! do |resource|
@@ -19,12 +19,40 @@ module QA
Page::Project::Settings::CICD.perform do |setting|
setting.expand_ci_variables do |page|
- page.fill_variable(key, value)
+ page.fill_variable(key, value, masked)
page.save_variables
end
end
end
+
+ def fabricate_via_api!
+ resource_web_url(api_get)
+ rescue ResourceNotFoundError
+ super
+ end
+
+ def resource_web_url(resource)
+ super
+ rescue ResourceURLMissingError
+ # this particular resource does not expose a web_url property
+ end
+
+ def api_get_path
+ "/projects/#{project.id}/variables/#{key}"
+ end
+
+ def api_post_path
+ "/projects/#{project.id}/variables"
+ end
+
+ def api_post_body
+ {
+ key: key,
+ value: value,
+ masked: masked
+ }
+ end
end
end
end
diff --git a/qa/qa/resource/file.rb b/qa/qa/resource/file.rb
index 57e82ac19ad..ca74654bf90 100644
--- a/qa/qa/resource/file.rb
+++ b/qa/qa/resource/file.rb
@@ -3,9 +3,12 @@
module QA
module Resource
class File < Base
- attr_accessor :name,
+ attr_accessor :author_email,
+ :author_name,
+ :branch,
:content,
- :commit_message
+ :commit_message,
+ :name
attribute :project do
Project.fabricate! do |resource|
@@ -31,6 +34,30 @@ module QA
page.commit_changes
end
end
+
+ def resource_web_url(resource)
+ super
+ rescue ResourceURLMissingError
+ # this particular resource does not expose a web_url property
+ end
+
+ def api_get_path
+ "/projects/#{CGI.escape(project.path_with_namespace)}/repository/files/#{CGI.escape(@name)}"
+ end
+
+ def api_post_path
+ api_get_path
+ end
+
+ def api_post_body
+ {
+ branch: @branch || "master",
+ author_email: @author_email || Runtime::User.default_email,
+ author_name: @author_name || Runtime::User.username,
+ content: content,
+ commit_message: commit_message
+ }
+ end
end
end
end
diff --git a/qa/qa/resource/issue.rb b/qa/qa/resource/issue.rb
index 2c2f27fe231..9c57a0f5afb 100644
--- a/qa/qa/resource/issue.rb
+++ b/qa/qa/resource/issue.rb
@@ -12,6 +12,8 @@ module QA
end
end
+ attribute :id
+ attribute :labels
attribute :title
def fabricate!
@@ -25,6 +27,21 @@ module QA
page.create_new_issue
end
end
+
+ def api_get_path
+ "/projects/#{project.id}/issues/#{id}"
+ end
+
+ def api_post_path
+ "/projects/#{project.id}/issues"
+ end
+
+ def api_post_body
+ {
+ labels: [labels],
+ title: title
+ }
+ end
end
end
end
diff --git a/qa/qa/resource/label.rb b/qa/qa/resource/label.rb
index 7c899db31f3..5a681a5fe9f 100644
--- a/qa/qa/resource/label.rb
+++ b/qa/qa/resource/label.rb
@@ -34,6 +34,27 @@ module QA
page.click_label_create_button
end
end
+
+ def resource_web_url(resource)
+ super
+ rescue ResourceURLMissingError
+ # this particular resource does not expose a web_url property
+ end
+
+ def api_get_path
+ raise NotImplementedError, "The Labels API doesn't expose a single-resource endpoint so this method cannot be properly implemented."
+ end
+
+ def api_post_path
+ "/projects/#{project}/labels"
+ end
+
+ def api_post_body
+ {
+ color: @color,
+ name: @title
+ }
+ end
end
end
end
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index de1e9f04c36..d706439a891 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -7,6 +7,9 @@ module QA
class Project < Base
include Events::Project
+ attr_writer :initialize_with_readme
+
+ attribute :id
attribute :name
attribute :description
@@ -32,6 +35,7 @@ module QA
def initialize
@description = 'My awesome project'
+ @initialize_with_readme = false
end
def name=(raw_name)
@@ -48,6 +52,7 @@ module QA
page.choose_name(@name)
page.add_description(@description)
page.set_visibility('Public')
+ page.enable_initialize_with_readme if @initialize_with_readme
page.create_new_project
end
end
@@ -72,7 +77,8 @@ module QA
path: name,
name: name,
description: description,
- visibility: 'public'
+ visibility: 'public',
+ initialize_with_readme: @initialize_with_readme
}
end
diff --git a/qa/qa/resource/repository/project_push.rb b/qa/qa/resource/repository/project_push.rb
index cad89ebb0bb..e98880ce195 100644
--- a/qa/qa/resource/repository/project_push.rb
+++ b/qa/qa/resource/repository/project_push.rb
@@ -32,8 +32,8 @@ module QA
def fabricate!
super
- project.visit!
project.wait_for_push @commit_message if @wait_for_push
+ project.visit!
end
end
end
diff --git a/qa/qa/runtime/api/client.rb b/qa/qa/runtime/api/client.rb
index 58de01705d7..40a3bc85195 100644
--- a/qa/qa/runtime/api/client.rb
+++ b/qa/qa/runtime/api/client.rb
@@ -25,15 +25,12 @@ module QA
private
def create_personal_access_token
- if @is_new_session
- Runtime::Browser.visit(@address, Page::Main::Login) { do_create_personal_access_token }
- else
- do_create_personal_access_token
- end
+ Runtime::Browser.visit(@address, Page::Main::Login) if @is_new_session
+ do_create_personal_access_token
end
def do_create_personal_access_token
- Page::Main::Login.act { sign_in_using_credentials }
+ Page::Main::Login.perform(&:sign_in_using_credentials)
Resource::PersonalAccessToken.fabricate!.access_token
end
end
diff --git a/qa/qa/runtime/browser.rb b/qa/qa/runtime/browser.rb
index a5218fc9ab1..3bf4b3bbbfb 100644
--- a/qa/qa/runtime/browser.rb
+++ b/qa/qa/runtime/browser.rb
@@ -33,6 +33,7 @@ module QA
def self.visit(address, page = nil, &block)
new.visit(address, page, &block)
+ page.validate_elements_present!
end
def self.configure!
@@ -76,6 +77,9 @@ module QA
# https://developers.google.com/web/updates/2017/04/headless-chrome#cli
options.add_argument("disable-gpu")
end
+
+ # Disable /dev/shm use in CI. See https://gitlab.com/gitlab-org/gitlab-ee/issues/4252
+ options.add_argument("disable-dev-shm-usage") if QA::Runtime::Env.running_in_ci?
end
# Use the same profile on QA runs if CHROME_REUSE_PROFILE is true.
@@ -85,9 +89,6 @@ module QA
options.add_argument("user-data-dir=#{qa_profile_dir}")
end
- # Disable /dev/shm use in CI. See https://gitlab.com/gitlab-org/gitlab-ee/issues/4252
- options.add_argument("disable-dev-shm-usage") if QA::Runtime::Env.running_in_ci?
-
selenium_options = {
browser: QA::Runtime::Env.browser,
clear_local_storage: true,
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index 03cae3c1fe6..82510dfa03c 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -136,6 +136,10 @@ module QA
ENV['GITLAB_QA_PASSWORD_2']
end
+ def knapsack?
+ !!(ENV['KNAPSACK_GENERATE_REPORT'] || ENV['KNAPSACK_REPORT_PATH'] || ENV['KNAPSACK_TEST_FILE_PATTERN'])
+ end
+
def ldap_username
@ldap_username ||= ENV['GITLAB_LDAP_USERNAME']
end
diff --git a/qa/qa/runtime/key/ecdsa.rb b/qa/qa/runtime/key/ecdsa.rb
index 6e5c0a2deca..46a1e5f54cf 100644
--- a/qa/qa/runtime/key/ecdsa.rb
+++ b/qa/qa/runtime/key/ecdsa.rb
@@ -1,4 +1,3 @@
-# rubocop:disable Naming/FileName
# frozen_string_literal: true
module QA
diff --git a/qa/qa/runtime/key/ed25519.rb b/qa/qa/runtime/key/ed25519.rb
index 53b556d744d..3a3567d55da 100644
--- a/qa/qa/runtime/key/ed25519.rb
+++ b/qa/qa/runtime/key/ed25519.rb
@@ -1,4 +1,3 @@
-# rubocop:disable Naming/FileName
# frozen_string_literal: true
module QA
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb
index 71c06b3410f..cf225a639b6 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb
@@ -7,16 +7,12 @@ module QA
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- # TODO, since `Signed in successfully` message was removed
- # this is the only way to tell if user is signed in correctly.
- #
Page::Main::Menu.perform do |menu|
expect(menu).to have_personal_area
end
Page::Main::Menu.perform do |menu|
menu.sign_out
- expect(menu).not_to have_personal_area
end
Page::Main::Login.perform do |form|
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
index a397df03bd2..72dde4e5bd8 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
@@ -7,9 +7,6 @@ module QA
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- # TODO, since `Signed in successfully` message was removed
- # this is the only way to tell if user is signed in correctly.
- #
Page::Main::Menu.perform do |menu|
expect(menu).to have_personal_area
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb
index b1d641b507f..67610b62ed7 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb
@@ -4,16 +4,14 @@ module QA
context 'Manage', :orchestrated, :mattermost do
describe 'Mattermost login' do
it 'user logs into Mattermost using GitLab OAuth' do
- Runtime::Browser.visit(:gitlab, Page::Main::Login) do
- Page::Main::Login.act { sign_in_using_credentials }
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.perform(&:sign_in_using_credentials)
- Runtime::Browser.visit(:mattermost, Page::Mattermost::Login) do
- Page::Mattermost::Login.act { sign_in_using_oauth }
+ Runtime::Browser.visit(:mattermost, Page::Mattermost::Login)
+ Page::Mattermost::Login.perform(&:sign_in_using_oauth)
- Page::Mattermost::Main.perform do |page|
- expect(page).to have_content(/(Welcome to: Mattermost|Logout GitLab Mattermost)/)
- end
- end
+ Page::Mattermost::Main.perform do |page|
+ expect(page).to have_content(/(Welcome to: Mattermost|Logout GitLab Mattermost)/)
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb
index a118176eb8a..15cd59f041b 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
module QA
- context 'Manage', :orchestrated, :oauth do
+ # https://gitlab.com/gitlab-org/quality/nightly/issues/100
+ context 'Manage', :orchestrated, :oauth, :quarantine do
describe 'OAuth login' do
it 'User logs in to GitLab with GitHub OAuth' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb
index 185837edacf..a0e3fe0d91a 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb
@@ -7,9 +7,6 @@ module QA
Resource::User.fabricate_via_browser_ui!
- # TODO, since `Signed in successfully` message was removed
- # this is the only way to tell if user is signed in correctly.
- #
Page::Main::Menu.perform do |menu|
expect(menu).to have_personal_area
end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
index fa779bd1f4e..4478ea41662 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
@@ -9,7 +9,7 @@ module QA
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_credentials)
- Resource::Issue.fabricate! do |issue|
+ Resource::Issue.fabricate_via_browser_ui! do |issue|
issue.title = issue_title
end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
index 358ab04eadc..1eea3efec7f 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
@@ -13,7 +13,8 @@ module QA
expect(page).to have_content(issue_title)
end
- context 'when using attachments in comments', :object_storage do
+ # Failure issue: https://gitlab.com/gitlab-org/quality/nightly/issues/101
+ context 'when using attachments in comments', :object_storage, :quarantine do
let(:file_to_attach) do
File.absolute_path(File.join('spec', 'fixtures', 'banana_sample.gif'))
end
@@ -22,7 +23,6 @@ module QA
create_issue
Page::Project::Issue::Show.perform do |show|
- show.select_all_activities_filter
show.comment('See attached banana for scale', attachment: file_to_attach)
show.refresh
@@ -42,7 +42,7 @@ module QA
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- Resource::Issue.fabricate! do |issue|
+ Resource::Issue.fabricate_via_browser_ui! do |issue|
issue.title = issue_title
end
end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb
index ac34f72bb8f..ad2773b41ac 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb
@@ -5,20 +5,19 @@ module QA
describe 'filter issue comments activities' do
let(:issue_title) { 'issue title' }
- it 'user filters comments and activites in an issue' do
+ it 'user filters comments and activities in an issue' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- Resource::Issue.fabricate! do |issue|
+ Resource::Issue.fabricate_via_browser_ui! do |issue|
issue.title = issue_title
end
expect(page).to have_content(issue_title)
Page::Project::Issue::Show.perform do |show_page|
- show_page.select_comments_only_filter
- show_page.comment('/confidential')
- show_page.comment('My own comment')
+ show_page.comment('/confidential', filter: :comments_only)
+ show_page.comment('My own comment', filter: :comments_only)
expect(show_page).not_to have_content("made the issue confidential")
expect(show_page).to have_content("My own comment")
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb
index f97b0e56ca2..530fc684437 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
module QA
- # Failure issue: https://gitlab.com/gitlab-org/quality/staging/issues/53
- context 'Plan', :quarantine do
+ context 'Plan' do
describe 'issue suggestions' do
let(:issue_title) { 'Issue Lists are awesome' }
@@ -10,12 +9,12 @@ module QA
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_credentials)
- project = Resource::Project.fabricate! do |resource|
+ project = Resource::Project.fabricate_via_api! do |resource|
resource.name = 'project-for-issue-suggestions'
resource.description = 'project for issue suggestions'
end
- Resource::Issue.fabricate! do |issue|
+ Resource::Issue.fabricate_via_browser_ui! do |issue|
issue.title = issue_title
issue.project = project
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
index 0ff71baed90..cd1c7545944 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
@@ -23,7 +23,7 @@ module QA
expect(page).to have_content(merge_request_title)
expect(page).to have_content(merge_request_description)
- expect(page).to have_content(/Opened [\w\s]+ ago/)
+ expect(page).to have_content('Opened just now')
end
it 'user creates a new merge request with a milestone and label' do
@@ -41,7 +41,7 @@ module QA
milestone.project = current_project
end
- new_label = Resource::Label.fabricate! do |label|
+ new_label = Resource::Label.fabricate_via_browser_ui! do |label|
label.project = current_project
label.title = 'qa-mr-test-label'
label.description = 'Merge Request label'
@@ -62,7 +62,7 @@ module QA
Page::MergeRequest::Show.perform do |merge_request|
expect(merge_request).to have_content(merge_request_title)
expect(merge_request).to have_content(merge_request_description)
- expect(merge_request).to have_content(/Opened [\w\s]+ ago/)
+ expect(merge_request).to have_content('Opened just now')
expect(merge_request).to have_assignee(gitlab_account_username)
expect(merge_request).to have_label(new_label.title)
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb
index 9e48ee7ca2a..db33c6330ff 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
module QA
- context 'Create' do
+ # https://gitlab.com/gitlab-org/quality/staging/issues/55
+ context 'Create', :quarantine do
describe 'Download merge request patch and diff' do
before(:context) do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb
index de5c535c757..2750b171a85 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb
@@ -2,7 +2,8 @@
module QA
context 'Create' do
- describe 'File templates' do
+ # Issue: https://gitlab.com/gitlab-org/quality/nightly/issues/97
+ describe 'File templates', :quarantine do
include Runtime::Fixtures
def login
@@ -16,14 +17,7 @@ module QA
@project = Resource::Project.fabricate! do |project|
project.name = 'file-template-project'
project.description = 'Add file templates via the Files view'
- end
-
- # There's no 'New File' dropdown when the project is blank, so we first
- # add a dummy file so that the dropdown will appear
- Resource::File.fabricate! do |file|
- file.project = @project
- file.name = 'README.md'
- file.content = '# Readme'
+ project.initialize_with_readme = true
end
Page::Main::Menu.perform(&:sign_out)
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
index daeee665c93..37a784248d4 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
module QA
- context 'Create' do
+ # Failure issue: https://gitlab.com/gitlab-org/quality/nightly/issues/62
+ context 'Create', :quarantine do
describe 'Create, list, and delete branches via web' do
master_branch = 'master'
second_branch = 'second-branch'
@@ -72,10 +73,9 @@ module QA
Page::Project::Branches::Show.perform do |branches_view|
branches_view.delete_branch(third_branch)
+ expect(branches_view).to have_no_branch(third_branch)
end
- expect(page).not_to have_content(third_branch)
-
Page::Project::Branches::Show.perform(&:delete_merged_branches)
expect(page).to have_content(
@@ -84,8 +84,7 @@ module QA
page.refresh
Page::Project::Branches::Show.perform do |branches_view|
- branches_view.wait_for_texts_not_to_be_visible([commit_message_of_second_branch])
- expect(branches_view).not_to have_branch_title(second_branch)
+ expect(branches_view).to have_no_branch(second_branch, reload: true)
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb
index 46346d1b984..d345fbfe995 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb
@@ -12,7 +12,7 @@ module QA
file_content = 'QA Test - File content'
commit_message_for_create = 'QA Test - Create new file'
- Resource::File.fabricate! do |file|
+ Resource::File.fabricate_via_browser_ui! do |file|
file.name = file_name
file.content = file_content
file.commit_message = commit_message_for_create
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb
index a544efb35ee..5bfafdfa041 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb
@@ -26,6 +26,8 @@ module QA
Page::Main::Login.perform(&:sign_in_using_credentials)
set_file_size_limit('')
+
+ Page::Main::Menu.perform(&:sign_out)
end
it 'push successful when the file size is under the limit' do
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb
index b7400cdca97..680c5e21fa4 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb
@@ -3,13 +3,16 @@
module QA
context 'Create' do
# failure reported: https://gitlab.com/gitlab-org/quality/nightly/issues/42
- # also failing in staging until the fix is picked into the next release:
- # https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24533
describe 'Commit data', :quarantine do
before(:context) do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_credentials)
+ # Get the user's details to confirm they're included in the email patch
+ @user = Resource::User.fabricate_via_api! do |user|
+ user.username = Runtime::User.username
+ end
+
project_push = Resource::Repository::ProjectPush.fabricate! do |push|
push.file_name = 'README.md'
push.file_content = '# This is a test project'
@@ -21,12 +24,13 @@ module QA
# add second file to repo to enable diff from initial commit
@commit_message = 'Add second file'
- Page::Project::Show.perform(&:create_new_file!)
- Page::File::Form.perform do |f|
- f.add_name('second')
- f.add_content('second file content')
- f.add_commit_message(@commit_message)
- f.commit_changes
+ Resource::File.fabricate_via_api! do |file|
+ file.project = @project
+ file.name = 'second'
+ file.content = 'second file content'
+ file.commit_message = @commit_message
+ file.author_name = @user.name
+ file.author_email = @user.public_email
end
end
@@ -42,15 +46,11 @@ module QA
end
it 'user views raw email patch' do
- user = Resource::User.fabricate_via_api! do |user|
- user.username = Runtime::User.username
- end
-
view_commit
Page::Project::Commit::Show.perform(&:select_email_patches)
- expect(page).to have_content("From: #{user.name} <#{user.public_email}>")
+ expect(page).to have_content("From: #{@user.name} <#{@user.public_email}>")
expect(page).to have_content('Subject: [PATCH] Add second file')
expect(page).to have_content('diff --git a/second b/second')
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb
index 66cd712afb0..078d3b2b5b1 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb
@@ -17,16 +17,7 @@ module QA
@project = Resource::Project.fabricate! do |project|
project.name = 'file-template-project'
project.description = 'Add file templates via the Web IDE'
- end
- @project.visit!
-
- # Add a file via the regular Files view because the Web IDE isn't
- # available unless there is a file present
- Page::Project::Show.perform(&:create_first_new_file!)
- Page::File::Form.perform do |page|
- page.add_name('dummy')
- page.add_content('Enable the Web IDE')
- page.commit_changes
+ project.initialize_with_readme = true
end
Page::Main::Menu.perform(&:sign_out)
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb
index 309ae6cd986..e689ba4c69c 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb
@@ -3,11 +3,6 @@
module QA
context 'Create' do
describe 'Wiki management' do
- def validate_content(content)
- expect(page).to have_content('Wiki was successfully updated')
- expect(page).to have_content(/#{content}/)
- end
-
it 'user creates, edits, clones, and pushes to the wiki' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_credentials)
@@ -38,6 +33,11 @@ module QA
expect(page).to have_content('My Third Wiki Content')
end
+
+ def validate_content(content)
+ expect(page).to have_content('Wiki was successfully updated')
+ expect(page).to have_content(/#{content}/)
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_ci_variable_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_ci_variable_spec.rb
index 33f342edb08..b060f15168c 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_ci_variable_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_ci_variable_spec.rb
@@ -3,15 +3,26 @@
module QA
context 'Verify' do
describe 'CI variable support' do
- it 'user adds a CI variable' do
+ it 'user adds a CI variable', :smoke do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.act { sign_in_using_credentials }
+ Page::Main::Login.perform(&:sign_in_using_credentials)
+
+ project = Resource::Project.fabricate! do |project|
+ project.name = 'project-with-ci-variables'
+ project.description = 'project with CI variables'
+ end
Resource::CiVariable.fabricate! do |resource|
+ resource.project = project
resource.key = 'VARIABLE_KEY'
resource.value = 'some_CI_variable'
+ resource.masked = false
end
+ project.visit!
+
+ Page::Project::Menu.perform(&:go_to_ci_cd_settings)
+
Page::Project::Settings::CICD.perform do |settings|
settings.expand_ci_variables do |page|
expect(page).to have_field(with: 'VARIABLE_KEY')
diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
index 609155da855..2fe4e4d9d1f 100644
--- a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
@@ -60,6 +60,7 @@ module QA
resource.project = @project
resource.key = deploy_key_name
resource.value = key.private_key
+ resource.masked = false
end
gitlab_ci = <<~YAML
diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
index 0971e551db1..5ca9ddb6b19 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
@@ -9,7 +9,7 @@ module QA
Page::Main::Login.perform(&:sign_in_using_credentials)
end
- # Transient failure issue: https://gitlab.com/gitlab-org/quality/nightly/issues/68
+ # Failure issue: https://gitlab.com/gitlab-org/quality/nightly/issues/108
describe 'Auto DevOps support', :orchestrated, :kubernetes, :quarantine do
context 'when rbac is enabled' do
before(:all) do
@@ -34,6 +34,7 @@ module QA
resource.project = @project
resource.key = 'CODE_QUALITY_DISABLED'
resource.value = '1'
+ resource.masked = false
end
# Set an application secret CI variable (prefixed with K8S_SECRET_)
@@ -41,6 +42,7 @@ module QA
resource.project = @project
resource.key = 'K8S_SECRET_OPTIONAL_MESSAGE'
resource.value = 'you_can_see_this_variable'
+ resource.masked = false
end
# Connect K8s cluster
diff --git a/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb b/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb
new file mode 100644
index 00000000000..a04efb94def
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Performance bar' do
+ context 'when logged in as an admin user' do
+ before do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.perform(&:sign_in_using_admin_credentials)
+ Page::Main::Menu.perform(&:click_admin_area)
+ Page::Admin::Menu.perform(&:go_to_metrics_and_profiling_settings)
+
+ Page::Admin::Settings::MetricsAndProfiling.perform do |setting|
+ setting.expand_performance_bar do |page|
+ page.enable_performance_bar
+ page.save_settings
+ end
+ end
+ end
+
+ it 'shows results for the original request and AJAX requests' do
+ # Issue pages always make AJAX requests
+ Resource::Issue.fabricate_via_browser_ui! do |issue|
+ issue.title = 'Performance bar test'
+ end
+
+ Page::Layout::PerformanceBar.perform do |page|
+ expect(page).to have_performance_bar
+ expect(page).to have_detailed_metrics
+ expect(page).to have_request_for('realtime_changes') # Always requested on issue pages
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/helpers/quarantine.rb b/qa/qa/specs/helpers/quarantine.rb
index 52cb05fcd13..ca0ce32e74f 100644
--- a/qa/qa/specs/helpers/quarantine.rb
+++ b/qa/qa/specs/helpers/quarantine.rb
@@ -20,6 +20,14 @@ module QA::Specs::Helpers
end
end
+ # Skip the entire context if a context is quarantined. This avoids running
+ # before blocks unnecessarily.
+ def skip_or_run_quarantined_contexts(filters, example)
+ return unless example.metadata.key?(:quarantine)
+
+ skip_or_run_quarantined_tests_or_contexts(filters, example)
+ end
+
# Skip tests in quarantine unless we explicitly focus on them.
def skip_or_run_quarantined_tests_or_contexts(filters, example)
if filters.key?(:quarantine)
@@ -39,14 +47,6 @@ module QA::Specs::Helpers
end
end
- # Skip the entire context if a context is quarantined. This avoids running
- # before blocks unnecessarily.
- def skip_or_run_quarantined_contexts(filters, example)
- return unless example.metadata.key?(:quarantine)
-
- skip_or_run_quarantined_tests_or_contexts(filters, example)
- end
-
def filters_other_than_quarantine(filter)
filter.reject { |key, _| key == :quarantine }
end
diff --git a/qa/qa/specs/runner.rb b/qa/qa/specs/runner.rb
index 306913dafa6..f1cb9378de8 100644
--- a/qa/qa/specs/runner.rb
+++ b/qa/qa/specs/runner.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
require 'rspec/core'
+require 'rspec/expectations'
+require 'knapsack'
module QA
module Specs
@@ -32,10 +34,25 @@ module QA
end
args.push(options)
- args.push(DEFAULT_TEST_PATH_ARGS) unless options.any? { |opt| opt =~ %r{/features/} }
Runtime::Browser.configure!
+ if Runtime::Env.knapsack?
+ allocator = Knapsack::AllocatorBuilder.new(Knapsack::Adapters::RSpecAdapter).allocator
+
+ QA::Runtime::Logger.info ''
+ QA::Runtime::Logger.info 'Report specs:'
+ QA::Runtime::Logger.info allocator.report_node_tests.join(', ')
+ QA::Runtime::Logger.info ''
+ QA::Runtime::Logger.info 'Leftover specs:'
+ QA::Runtime::Logger.info allocator.leftover_node_tests.join(', ')
+ QA::Runtime::Logger.info ''
+
+ args.push(['--', allocator.node_tests])
+ else
+ args.push(DEFAULT_TEST_PATH_ARGS) unless options.any? { |opt| opt =~ %r{/features/} }
+ end
+
RSpec::Core::Runner.run(args.flatten, $stderr, $stdout).tap do |status|
abort if status.nonzero?
end
diff --git a/qa/qa/support/page/logging.rb b/qa/qa/support/page/logging.rb
index 69b6332ecce..93d8fa99c0a 100644
--- a/qa/qa/support/page/logging.rb
+++ b/qa/qa/support/page/logging.rb
@@ -33,11 +33,8 @@ module QA
exists
end
- def find_element(name, text: nil, wait: Capybara.default_max_wait_time)
- msg = ["finding :#{name}"]
- msg << %Q(with text "#{text}") if text
- msg << "(wait: #{wait})"
- log(msg.compact.join(' '))
+ def find_element(name, **kwargs)
+ log("finding :#{name} with args #{kwargs}")
element = super
@@ -56,8 +53,11 @@ module QA
elements
end
- def click_element(name)
- log("clicking :#{name}")
+ def click_element(name, page = nil)
+ msg = ["clicking :#{name}"]
+ msg << ", expecting to be at #{page.class}" if page
+
+ log(msg.compact.join(' '))
super
end
@@ -76,23 +76,18 @@ module QA
super
end
- def has_element?(name, text: nil, wait: Capybara.default_max_wait_time)
+ def has_element?(name, **kwargs)
found = super
- msg = ["has_element? :#{name}"]
- msg << %Q(with text "#{text}") if text
- msg << "(wait: #{wait})"
- msg << "returned: #{found}"
-
- log(msg.compact.join(' '))
+ log_has_element_or_not('has_element?', name, found, **kwargs)
found
end
- def has_no_element?(name, wait: Capybara.default_max_wait_time)
+ def has_no_element?(name, **kwargs)
found = super
- log("has_no_element? :#{name} returned #{found}")
+ log_has_element_or_not('has_no_element?', name, found, **kwargs)
found
end
@@ -124,7 +119,13 @@ module QA
loaded
end
- def within_element(name)
+ def wait_for_animated_element(name)
+ log("waiting for animated element: #{name}")
+
+ super
+ end
+
+ def within_element(name, text: nil)
log("within element :#{name}")
element = super
@@ -149,6 +150,15 @@ module QA
def log(msg)
QA::Runtime::Logger.debug(msg)
end
+
+ def log_has_element_or_not(method, name, found, **kwargs)
+ msg = ["#{method} :#{name}"]
+ msg << %Q(with text "#{kwargs[:text]}") if kwargs[:text]
+ msg << "(wait: #{kwargs[:wait] || Capybara.default_max_wait_time})"
+ msg << "returned: #{found}"
+
+ log(msg.compact.join(' '))
+ end
end
end
end
diff --git a/qa/qa/support/waiter.rb b/qa/qa/support/waiter.rb
index 21a399b4a5f..fdcf2d7e157 100644
--- a/qa/qa/support/waiter.rb
+++ b/qa/qa/support/waiter.rb
@@ -3,9 +3,11 @@
module QA
module Support
module Waiter
+ DEFAULT_MAX_WAIT_TIME = 60
+
module_function
- def wait(max: 60, interval: 0.1)
+ def wait(max: DEFAULT_MAX_WAIT_TIME, interval: 0.1)
QA::Runtime::Logger.debug("with wait: max #{max}; interval #{interval}")
start = Time.now
diff --git a/qa/qa/vendor/github/page/login.rb b/qa/qa/vendor/github/page/login.rb
index 6d8f9aa7c12..120ba6e6c06 100644
--- a/qa/qa/vendor/github/page/login.rb
+++ b/qa/qa/vendor/github/page/login.rb
@@ -12,9 +12,7 @@ module QA
fill_in 'password', with: QA::Runtime::Env.github_password
click_on 'Sign in'
- unless has_no_text?("Authorize GitLab-OAuth")
- click_on 'Authorize gitlab-qa' if has_button?('Authorize gitlab-qa')
- end
+ click_on 'Authorize gitlab-qa' if has_button?('Authorize gitlab-qa')
end
end
end
diff --git a/qa/spec/git/repository_spec.rb b/qa/spec/git/repository_spec.rb
index 776dce31d4f..5198eb6f58b 100644
--- a/qa/spec/git/repository_spec.rb
+++ b/qa/spec/git/repository_spec.rb
@@ -116,6 +116,15 @@ describe QA::Git::Repository do
expect(File.read(File.join(tmp_netrc_dir, '.netrc')))
.to eq("machine foo login user password foo\n")
end
+
+ it 'adds credentials with special characters' do
+ password = %q[!"#$%&')(*+,-./:;<=>?]
+ repository.username = 'user'
+ repository.password = password
+
+ expect(File.read(File.join(tmp_netrc_dir, '.netrc')))
+ .to eq("machine foo login user password #{password}\n")
+ end
end
end
end
diff --git a/qa/spec/page/element_spec.rb b/qa/spec/page/element_spec.rb
index d5d6dff69da..f746fe06e40 100644
--- a/qa/spec/page/element_spec.rb
+++ b/qa/spec/page/element_spec.rb
@@ -50,4 +50,60 @@ describe QA::Page::Element do
expect(subject.matches?('some_name selector')).to be false
end
end
+
+ describe 'attributes' do
+ context 'element with no args' do
+ subject { described_class.new(:something) }
+
+ it 'defaults pattern to #selector' do
+ expect(subject.attributes[:pattern]).to eq 'qa-something'
+ expect(subject.attributes[:pattern]).to eq subject.selector
+ end
+
+ it 'is not required by default' do
+ expect(subject.required?).to be false
+ end
+ end
+
+ context 'element with a pattern' do
+ subject { described_class.new(:something, /link_to 'something'/) }
+
+ it 'has an attribute[pattern] of the pattern' do
+ expect(subject.attributes[:pattern]).to eq /link_to 'something'/
+ end
+
+ it 'is not required by default' do
+ expect(subject.required?).to be false
+ end
+ end
+
+ context 'element with requirement; no pattern' do
+ subject { described_class.new(:something, required: true) }
+
+ it 'has an attribute[pattern] of the selector' do
+ expect(subject.attributes[:pattern]).to eq 'qa-something'
+ expect(subject.attributes[:pattern]).to eq subject.selector
+ end
+
+ it 'is required' do
+ expect(subject.required?).to be true
+ end
+ end
+
+ context 'element with requirement and pattern' do
+ subject { described_class.new(:something, /link_to 'something_else_entirely'/, required: true) }
+
+ it 'has an attribute[pattern] of the passed pattern' do
+ expect(subject.attributes[:pattern]).to eq /link_to 'something_else_entirely'/
+ end
+
+ it 'is required' do
+ expect(subject.required?).to be true
+ end
+
+ it 'has a selector of the name' do
+ expect(subject.selector).to eq 'qa-something'
+ end
+ end
+ end
end
diff --git a/qa/spec/page/logging_spec.rb b/qa/spec/page/logging_spec.rb
index 707a7ff6d98..0f1ed039149 100644
--- a/qa/spec/page/logging_spec.rb
+++ b/qa/spec/page/logging_spec.rb
@@ -64,11 +64,21 @@ describe QA::Support::Page::Logging do
it 'logs find_element with text' do
expect { subject.find_element(:element, text: 'foo') }
- .to output(/finding :element with text "foo"/).to_stdout_from_any_process
+ .to output(/finding :element with args {:text=>"foo"}/).to_stdout_from_any_process
expect { subject.find_element(:element, text: 'foo') }
.to output(/found :element/).to_stdout_from_any_process
end
+ it 'logs find_element with wait' do
+ expect { subject.find_element(:element, wait: 0) }
+ .to output(/finding :element with args {:wait=>0}/).to_stdout_from_any_process
+ end
+
+ it 'logs find_element with class' do
+ expect { subject.find_element(:element, class: 'active') }
+ .to output(/finding :element with args {:class=>\"active\"}/).to_stdout_from_any_process
+ end
+
it 'logs click_element' do
expect { subject.click_element(:element) }
.to output(/clicking :element/).to_stdout_from_any_process
@@ -93,7 +103,14 @@ describe QA::Support::Page::Logging do
allow(page).to receive(:has_no_css?).and_return(true)
expect { subject.has_no_element?(:element) }
- .to output(/has_no_element\? :element returned true/).to_stdout_from_any_process
+ .to output(/has_no_element\? :element \(wait: 2\) returned: true/).to_stdout_from_any_process
+ end
+
+ it 'logs has_no_element? with text' do
+ allow(page).to receive(:has_no_css?).and_return(true)
+
+ expect { subject.has_no_element?(:element, text: "more text") }
+ .to output(/has_no_element\? :element with text \"more text\" \(wait: 2\) returned: true/).to_stdout_from_any_process
end
it 'logs has_text?' do
@@ -118,9 +135,9 @@ describe QA::Support::Page::Logging do
end
it 'logs within_element' do
- expect { subject.within_element(:element) }
+ expect { subject.within_element(:element, text: nil) }
.to output(/within element :element/).to_stdout_from_any_process
- expect { subject.within_element(:element) }
+ expect { subject.within_element(:element, text: nil) }
.to output(/end within element :element/).to_stdout_from_any_process
end
diff --git a/qa/spec/runtime/env_spec.rb b/qa/spec/runtime/env_spec.rb
index 04085efe2ce..2560695ef2e 100644
--- a/qa/spec/runtime/env_spec.rb
+++ b/qa/spec/runtime/env_spec.rb
@@ -168,6 +168,30 @@ describe QA::Runtime::Env do
end
end
+ describe '.knapsack?' do
+ it 'returns true if KNAPSACK_GENERATE_REPORT is defined' do
+ stub_env('KNAPSACK_GENERATE_REPORT', 'true')
+
+ expect(described_class.knapsack?).to be_truthy
+ end
+
+ it 'returns true if KNAPSACK_REPORT_PATH is defined' do
+ stub_env('KNAPSACK_REPORT_PATH', '/a/path')
+
+ expect(described_class.knapsack?).to be_truthy
+ end
+
+ it 'returns true if KNAPSACK_TEST_FILE_PATTERN is defined' do
+ stub_env('KNAPSACK_TEST_FILE_PATTERN', '/a/**/pattern')
+
+ expect(described_class.knapsack?).to be_truthy
+ end
+
+ it 'returns false if neither KNAPSACK_GENERATE_REPORT nor KNAPSACK_REPORT_PATH nor KNAPSACK_TEST_FILE_PATTERN are defined' do
+ expect(described_class.knapsack?).to be_falsey
+ end
+ end
+
describe '.require_github_access_token!' do
it 'raises ArgumentError if GITHUB_ACCESS_TOKEN is not defined' do
stub_env('GITHUB_ACCESS_TOKEN', nil)
diff --git a/qa/spec/spec_helper.rb b/qa/spec/spec_helper.rb
index 24ff1523ba7..f25dbf3a8ab 100644
--- a/qa/spec/spec_helper.rb
+++ b/qa/spec/spec_helper.rb
@@ -3,6 +3,11 @@
require_relative '../qa'
require 'rspec/retry'
+if ENV['CI'] && QA::Runtime::Env.knapsack? && !ENV['NO_KNAPSACK']
+ require 'knapsack'
+ Knapsack::Adapters::RSpecAdapter.bind
+end
+
%w[helpers shared_examples].each do |d|
Dir[::File.join(__dir__, d, '**', '*.rb')].each { |f| require f }
end
@@ -35,8 +40,10 @@ RSpec.configure do |config|
# show exception that triggers a retry if verbose_retry is set to true
config.display_try_failure_messages = true
- config.around do |example|
- retry_times = example.metadata.keys.include?(:quarantine) ? 1 : 2
- example.run_with_retry retry: retry_times
+ if ENV['CI']
+ config.around do |example|
+ retry_times = example.metadata.keys.include?(:quarantine) ? 1 : 2
+ example.run_with_retry retry: retry_times
+ end
end
end
diff --git a/rubocop/cop/code_reuse/active_record.rb b/rubocop/cop/code_reuse/active_record.rb
index 2be8f7c11aa..1e650abfceb 100644
--- a/rubocop/cop/code_reuse/active_record.rb
+++ b/rubocop/cop/code_reuse/active_record.rb
@@ -9,7 +9,8 @@ module RuboCop
class ActiveRecord < RuboCop::Cop::Cop
include CodeReuseHelpers
- MSG = 'This method can only be used inside an ActiveRecord model'
+ MSG = 'This method can only be used inside an ActiveRecord model: ' \
+ 'https://gitlab.com/gitlab-org/gitlab-ce/issues/49653'
# Various methods from ActiveRecord::Querying that are blacklisted. We
# exclude some generic ones such as `any?` and `first`, as these may
diff --git a/rubocop/cop/gitlab/finder_with_find_by.rb b/rubocop/cop/gitlab/finder_with_find_by.rb
index f45a37ddc06..764a5073143 100644
--- a/rubocop/cop/gitlab/finder_with_find_by.rb
+++ b/rubocop/cop/gitlab/finder_with_find_by.rb
@@ -2,7 +2,7 @@ module RuboCop
module Cop
module Gitlab
class FinderWithFindBy < RuboCop::Cop::Cop
- FIND_PATTERN = /\Afind(_by\!?)?\z/
+ FIND_PATTERN = /\Afind(_by\!?)?\z/.freeze
ALLOWED_MODULES = ['FinderMethods'].freeze
def message(used_method)
@@ -36,7 +36,7 @@ module RuboCop
def find_on_execute?(node)
chained_on_node = node.descendants.first
node.method_name.to_s =~ FIND_PATTERN &&
- chained_on_node&.method_name == :execute
+ chained_on_node.is_a?(RuboCop::AST::SendNode) && chained_on_node.method_name == :execute
end
def allowed_module?(node)
diff --git a/rubocop/cop/include_action_view_context.rb b/rubocop/cop/include_action_view_context.rb
new file mode 100644
index 00000000000..14662a33e95
--- /dev/null
+++ b/rubocop/cop/include_action_view_context.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require_relative '../spec_helpers'
+
+module RuboCop
+ module Cop
+ # Cop that makes sure workers include `::Gitlab::ActionViewOutput::Context`, not `ActionView::Context`.
+ class IncludeActionViewContext < RuboCop::Cop::Cop
+ include SpecHelpers
+
+ MSG = 'Include `::Gitlab::ActionViewOutput::Context`, not `ActionView::Context`, for Rails 5.'.freeze
+
+ def_node_matcher :includes_action_view_context?, <<~PATTERN
+ (send nil? :include (const (const nil? :ActionView) :Context))
+ PATTERN
+
+ def on_send(node)
+ return if in_spec?(node)
+ return unless includes_action_view_context?(node)
+
+ add_offense(node.arguments.first, location: :expression)
+ end
+
+ def autocorrect(node)
+ lambda do |corrector|
+ corrector.replace(node.source_range, '::Gitlab::ActionViewOutput::Context')
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/qa/element_with_pattern.rb b/rubocop/cop/qa/element_with_pattern.rb
index 9d80946f1ba..d14eeaaeaf3 100644
--- a/rubocop/cop/qa/element_with_pattern.rb
+++ b/rubocop/cop/qa/element_with_pattern.rb
@@ -1,18 +1,21 @@
+# frozen_string_literal: true
+
require_relative '../../qa_helpers'
module RuboCop
module Cop
module QA
- # This cop checks for the usage of factories in migration specs
+ # This cop checks for the usage of patterns in QA elements
#
# @example
#
# # bad
- # let(:user) { create(:user) }
+ # element :some_element, "link_to 'something'"
+ # element :some_element, /link_to 'something'/
#
# # good
- # let(:users) { table(:users) }
- # let(:user) { users.create!(name: 'User 1', username: 'user1') }
+ # element :some_element
+ # element :some_element, required: true
class ElementWithPattern < RuboCop::Cop::Cop
include QAHelpers
@@ -22,10 +25,13 @@ module RuboCop
return unless in_qa_file?(node)
return unless method_name(node).to_s == 'element'
- element_name, pattern = node.arguments
- return unless pattern
+ element_name, *args = node.arguments
+
+ return if args.first.nil?
- add_offense(node, location: pattern.source_range, message: MESSAGE % "qa-#{element_name.value.to_s.tr('_', '-')}")
+ args.first.each_node(:str) do |arg|
+ add_offense(arg, message: MESSAGE % "qa-#{element_name.value.to_s.tr('_', '-')}")
+ end
end
private
diff --git a/rubocop/qa_helpers.rb b/rubocop/qa_helpers.rb
index f4adf7f4e9f..95875d64727 100644
--- a/rubocop/qa_helpers.rb
+++ b/rubocop/qa_helpers.rb
@@ -5,7 +5,7 @@ module RuboCop
def in_qa_file?(node)
path = node.location.expression.source_buffer.name
- path.start_with?(File.join(Dir.pwd, 'qa'))
+ path.start_with?(File.join(RuboCop::PathUtil.pwd, 'qa'))
end
end
end
diff --git a/rubocop/rubocop.rb b/rubocop/rubocop.rb
index 50eab6f9270..e2a19978839 100644
--- a/rubocop/rubocop.rb
+++ b/rubocop/rubocop.rb
@@ -1,9 +1,9 @@
-# rubocop:disable Naming/FileName
require_relative 'cop/gitlab/module_with_instance_variables'
require_relative 'cop/gitlab/predicate_memoization'
require_relative 'cop/gitlab/httparty'
require_relative 'cop/gitlab/finder_with_find_by'
require_relative 'cop/gitlab/union'
+require_relative 'cop/include_action_view_context'
require_relative 'cop/include_sidekiq_worker'
require_relative 'cop/safe_params'
require_relative 'cop/active_record_association_reload'
diff --git a/rubocop/spec_helpers.rb b/rubocop/spec_helpers.rb
index 63c1b975a65..ecd77c4351d 100644
--- a/rubocop/spec_helpers.rb
+++ b/rubocop/spec_helpers.rb
@@ -6,14 +6,16 @@ module RuboCop
# Returns true if the given node originated from the spec directory.
def in_spec?(node)
path = node.location.expression.source_buffer.name
+ pwd = RuboCop::PathUtil.pwd
!SPEC_HELPERS.include?(File.basename(path)) &&
- path.start_with?(File.join(Dir.pwd, 'spec'), File.join(Dir.pwd, 'ee', 'spec'))
+ path.start_with?(File.join(pwd, 'spec'), File.join(pwd, 'ee', 'spec'))
end
def migration_directories
@migration_directories ||= MIGRATION_SPEC_DIRECTORIES.map do |dir|
- [File.join(Dir.pwd, dir), File.join(Dir.pwd, 'ee', dir)]
+ pwd = RuboCop::PathUtil.pwd
+ [File.join(pwd, dir), File.join(pwd, 'ee', dir)]
end.flatten
end
diff --git a/scripts/clean-old-cached-assets b/scripts/clean-old-cached-assets
index 7a3a62a477a..8bdd3a9cdb6 100755
--- a/scripts/clean-old-cached-assets
+++ b/scripts/clean-old-cached-assets
@@ -1,6 +1,6 @@
#!/bin/bash
-# Clean up cached files that are older than 1 week
-find tmp/cache/assets/sprockets/ -type f -mtime +7 -execdir rm -- "{}" \;
+# Clean up cached files that are older than 4 days
+find tmp/cache/assets/sprockets/ -type f -mtime +4 -execdir rm -- "{}" \;
du -d 0 -h tmp/cache/assets/sprockets | cut -f1 | xargs -I % echo "tmp/cache/assets/sprockets/ is currently %"
diff --git a/scripts/frontend/stylelint/stylelint-utility-map.js b/scripts/frontend/stylelint/stylelint-utility-map.js
index 7e012b157b3..941198e82a4 100644
--- a/scripts/frontend/stylelint/stylelint-utility-map.js
+++ b/scripts/frontend/stylelint/stylelint-utility-map.js
@@ -29,7 +29,7 @@ sass.render(
// We just use postcss to create a CSS tree
postcss([])
.process(cssResult, {
- // This supresses a postcss warning
+ // This suppresses a postcss warning
from: undefined,
})
.then(result => {
diff --git a/scripts/frontend/test.js b/scripts/frontend/test.js
new file mode 100755
index 00000000000..dab7176f8c1
--- /dev/null
+++ b/scripts/frontend/test.js
@@ -0,0 +1,114 @@
+#!/usr/bin/env node
+
+const { spawn } = require('child_process');
+const { EOL } = require('os');
+const program = require('commander');
+const chalk = require('chalk');
+
+const JEST_ROUTE = 'spec/frontend';
+const KARMA_ROUTE = 'spec/javascripts';
+const COMMON_ARGS = ['--colors'];
+const JEST_ARGS = ['--passWithNoTests'];
+const KARMA_ARGS = ['--no-fail-on-empty-test-suite'];
+const SUCCESS_CODE = 0;
+
+program
+ .version('0.1.0')
+ .usage('[options] <file ...>')
+ .option('-p, --parallel', 'Run tests suites in parallel')
+ .parse(process.argv);
+
+const isSuccess = code => code === SUCCESS_CODE;
+
+const combineExitCodes = codes => {
+ const firstFail = codes.find(x => !isSuccess(x));
+
+ return firstFail === undefined ? SUCCESS_CODE : firstFail;
+};
+
+const skipIfFail = fn => code => (isSuccess(code) ? fn() : code);
+
+const endWithEOL = str => (str[str.length - 1] === '\n' ? str : `${str}${EOL}`);
+
+const runTests = paths => {
+ if (program.parallel) {
+ return Promise.all([runJest(paths), runKarma(paths)]).then(combineExitCodes);
+ } else {
+ return runJest(paths).then(skipIfFail(() => runKarma(paths)));
+ }
+};
+
+const spawnYarnScript = (cmd, args) => {
+ return new Promise((resolve, reject) => {
+ const proc = spawn('yarn', ['run', cmd, ...args]);
+ const output = data => {
+ const text = data
+ .toString()
+ .split(/\r?\n/g)
+ .map((line, idx, { length }) =>
+ idx === length - 1 && !line ? line : `${chalk.gray(cmd)}: ${line}`,
+ )
+ .join(EOL);
+
+ return endWithEOL(text);
+ };
+
+ proc.stdout.on('data', data => {
+ process.stdout.write(output(data));
+ });
+
+ proc.stderr.on('data', data => {
+ process.stderr.write(output(data));
+ });
+
+ proc.on('close', code => {
+ process.stdout.write(output(`exited with code ${code}`));
+
+ // We resolve even on a failure code because a `reject` would cause
+ // Promise.all to reject immediately (without waiting for other promises)
+ // to finish.
+ resolve(code);
+ });
+ });
+};
+
+const runJest = args => {
+ return spawnYarnScript('jest', [...JEST_ARGS, ...COMMON_ARGS, ...toJestArgs(args)]);
+};
+
+const runKarma = args => {
+ return spawnYarnScript('karma', [...KARMA_ARGS, ...COMMON_ARGS, ...toKarmaArgs(args)]);
+};
+
+const replacePath = to => path =>
+ path
+ .replace(JEST_ROUTE, to)
+ .replace(KARMA_ROUTE, to)
+ .replace('app/assets/javascripts', to);
+
+const replacePathForJest = replacePath(JEST_ROUTE);
+
+const replacePathForKarma = replacePath(KARMA_ROUTE);
+
+const toJestArgs = paths => paths.map(replacePathForJest);
+
+const toKarmaArgs = paths =>
+ paths.reduce((acc, path) => acc.concat('-f', replacePathForKarma(path)), []);
+
+const main = paths => {
+ runTests(paths).then(code => {
+ console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
+ if (isSuccess(code)) {
+ console.log(chalk.bgGreen(chalk.black('All tests passed :)')));
+ } else {
+ console.log(chalk.bgRed(chalk.white(`Some tests failed :(`)));
+ }
+ console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
+
+ if (!isSuccess(code)) {
+ process.exit(code);
+ }
+ });
+};
+
+main(program.args);
diff --git a/scripts/lint-doc.sh b/scripts/lint-doc.sh
index bc73225c1bf..2055ce7f09d 100755
--- a/scripts/lint-doc.sh
+++ b/scripts/lint-doc.sh
@@ -35,7 +35,7 @@ fi
# Do not use 'README.md', instead use 'index.md'
# Number of 'README.md's as of 2018-03-26
-NUMBER_READMES_CE=43
+NUMBER_READMES_CE=46
NUMBER_READMES_EE=46
FIND_READMES=$(find doc/ -name "README.md" | wc -l)
echo '=> Checking for new README.md files...'
diff --git a/scripts/prepare_build.sh b/scripts/prepare_build.sh
index 58b74f2f07d..9b0d5d4f719 100644
--- a/scripts/prepare_build.sh
+++ b/scripts/prepare_build.sh
@@ -5,6 +5,7 @@ export USE_BUNDLE_INSTALL=${USE_BUNDLE_INSTALL:-true}
export BUNDLE_INSTALL_FLAGS="--without=production --jobs=$(nproc) --path=vendor --retry=3 --quiet"
if [ "$USE_BUNDLE_INSTALL" != "false" ]; then
+ bundle --version
bundle install --clean $BUNDLE_INSTALL_FLAGS && bundle check
fi
@@ -16,12 +17,10 @@ cp config/gitlab.yml.example config/gitlab.yml
sed -i 's/bin_path: \/usr\/bin\/git/bin_path: \/usr\/local\/bin\/git/' config/gitlab.yml
# Determine the database by looking at the job name.
-# For example, we'll get pg if the job is `rspec-pg 19 20`
-export GITLAB_DATABASE=$(echo $CI_JOB_NAME | cut -f1 -d' ' | cut -f2 -d-)
-
-# This would make the default database postgresql, and we could also use
-# pg to mean postgresql.
-if [ "$GITLAB_DATABASE" != 'mysql' ]; then
+# This would make the default database postgresql.
+if [[ "${CI_JOB_NAME#*mysql}" != "$CI_JOB_NAME" ]]; then
+ export GITLAB_DATABASE='mysql'
+else
export GITLAB_DATABASE='postgresql'
fi
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
index 22e47ce2c0a..9455e462617 100755
--- a/scripts/review_apps/review-apps.sh
+++ b/scripts/review_apps/review-apps.sh
@@ -1,26 +1,6 @@
[[ "$TRACE" ]] && set -x
export TILLER_NAMESPACE="$KUBE_NAMESPACE"
-function echoerr() {
- local header="${2}"
-
- if [ -n "${header}" ]; then
- printf "\n\033[0;31m** %s **\n\033[0m" "${1}" >&2;
- else
- printf "\033[0;31m%s\n\033[0m" "${1}" >&2;
- fi
-}
-
-function echoinfo() {
- local header="${2}"
-
- if [ -n "${header}" ]; then
- printf "\n\033[0;33m** %s **\n\033[0m" "${1}" >&2;
- else
- printf "\033[0;33m%s\n\033[0m" "${1}" >&2;
- fi
-}
-
function deployExists() {
local namespace="${1}"
local deploy="${2}"
@@ -68,7 +48,7 @@ function delete() {
echoinfo "Deleting release '$name'..." true
- helm delete --purge "$name" || true
+ helm delete --purge "$name"
}
function cleanup() {
@@ -81,8 +61,8 @@ function cleanup() {
kubectl -n "$KUBE_NAMESPACE" delete \
ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa \
- -l release="$CI_ENVIRONMENT_SLUG" \
- || true
+ --now --ignore-not-found --include-uninitialized \
+ -l release="$CI_ENVIRONMENT_SLUG"
}
function get_pod() {
@@ -109,7 +89,7 @@ function perform_review_app_deployment() {
ensure_namespace
install_tiller
install_external_dns
- time deploy || true
+ time deploy
wait_for_review_app_to_be_accessible
add_license
}
@@ -236,6 +216,7 @@ HELM_CMD=$(cat << EOF
--set global.ingress.configureCertmanager=false \
--set global.ingress.tls.secretName=tls-cert \
--set global.ingress.annotations."external-dns\.alpha\.kubernetes\.io/ttl"="10"
+ --set nginx-ingress.controller.service.enableHttp=false \
--set nginx-ingress.defaultBackend.resources.requests.memory=7Mi \
--set nginx-ingress.controller.resources.requests.memory=440M \
--set nginx-ingress.controller.replicaCount=2 \
@@ -270,7 +251,7 @@ EOF
echoinfo "Deploying with:"
echoinfo "${HELM_CMD}"
- eval $HELM_CMD
+ eval $HELM_CMD || true
}
function wait_for_review_app_to_be_accessible() {
@@ -328,80 +309,3 @@ function add_license() {
puts "License added";
'
}
-
-function get_job_id() {
- local job_name="${1}"
- local query_string="${2:+&${2}}"
-
- local max_page=3
- local page=1
-
- while true; do
- local url="https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/pipelines/${CI_PIPELINE_ID}/jobs?per_page=100&page=${page}${query_string}"
- echoinfo "GET ${url}"
-
- local job_id
- job_id=$(curl --silent --show-error --header "PRIVATE-TOKEN: ${API_TOKEN}" "${url}" | jq "map(select(.name == \"${job_name}\")) | map(.id) | last")
- [[ "${job_id}" == "null" && "${page}" -lt "$max_page" ]] || break
-
- let "page++"
- done
-
- if [[ "${job_id}" == "" ]]; then
- echoerr "The '${job_name}' job ID couldn't be retrieved!"
- else
- echoinfo "The '${job_name}' job ID is ${job_id}"
- echo "${job_id}"
- fi
-}
-
-function play_job() {
- local job_name="${1}"
- local job_id
- job_id=$(get_job_id "${job_name}" "scope=manual");
- if [ -z "${job_id}" ]; then return; fi
-
- local url="https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/jobs/${job_id}/play"
- echoinfo "POST ${url}"
-
- local job_url
- job_url=$(curl --silent --show-error --request POST --header "PRIVATE-TOKEN: ${API_TOKEN}" "${url}" | jq ".web_url")
- echoinfo "Manual job '${job_name}' started at: ${job_url}"
-}
-
-function wait_for_job_to_be_done() {
- local job_name="${1}"
- local query_string="${2}"
- local job_id
- job_id=$(get_job_id "${job_name}" "${query_string}")
- if [ -z "${job_id}" ]; then return; fi
-
- echoinfo "Waiting for the '${job_name}' job to finish..."
-
- local url="https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/jobs/${job_id}"
- echoinfo "GET ${url}"
-
- # In case the job hasn't finished yet. Keep trying until the job times out.
- local interval=30
- local elapsed_seconds=0
- while true; do
- local job_status
- job_status=$(curl --silent --show-error --header "PRIVATE-TOKEN: ${API_TOKEN}" "${url}" | jq ".status" | sed -e s/\"//g)
- [[ "${job_status}" == "pending" || "${job_status}" == "running" ]] || break
-
- printf "."
- let "elapsed_seconds+=interval"
- sleep ${interval}
- done
-
- local elapsed_minutes=$((elapsed_seconds / 60))
- echoinfo "Waited '${job_name}' for ${elapsed_minutes} minutes."
-
- if [[ "${job_status}" == "failed" ]]; then
- echoerr "The '${job_name}' failed."
- elif [[ "${job_status}" == "manual" ]]; then
- echoinfo "The '${job_name}' is manual."
- else
- echoinfo "The '${job_name}' passed."
- fi
-}
diff --git a/scripts/utils.sh b/scripts/utils.sh
index 2d2ba115563..4a6567b8a62 100644
--- a/scripts/utils.sh
+++ b/scripts/utils.sh
@@ -1,4 +1,4 @@
-retry() {
+function retry() {
if eval "$@"; then
return 0
fi
@@ -13,15 +13,15 @@ retry() {
return 1
}
-setup_db_user_only() {
+function setup_db_user_only() {
if [ "$GITLAB_DATABASE" = "postgresql" ]; then
- . scripts/create_postgres_user.sh
+ source scripts/create_postgres_user.sh
else
- . scripts/create_mysql_user.sh
+ source scripts/create_mysql_user.sh
fi
}
-setup_db() {
+function setup_db() {
setup_db_user_only
bundle exec rake db:drop db:create db:schema:load db:migrate
@@ -30,3 +30,129 @@ setup_db() {
bundle exec rake add_limits_mysql
fi
}
+
+function install_api_client_dependencies_with_apk() {
+ apk add --update openssl curl jq
+}
+
+function install_api_client_dependencies_with_apt() {
+ apt update && apt install jq -y
+}
+
+function install_gitlab_gem() {
+ gem install gitlab --no-document
+}
+
+function echoerr() {
+ local header="${2}"
+
+ if [ -n "${header}" ]; then
+ printf "\n\033[0;31m** %s **\n\033[0m" "${1}" >&2;
+ else
+ printf "\033[0;31m%s\n\033[0m" "${1}" >&2;
+ fi
+}
+
+function echoinfo() {
+ local header="${2}"
+
+ if [ -n "${header}" ]; then
+ printf "\n\033[0;33m** %s **\n\033[0m" "${1}" >&2;
+ else
+ printf "\033[0;33m%s\n\033[0m" "${1}" >&2;
+ fi
+}
+
+function get_job_id() {
+ local job_name="${1}"
+ local query_string="${2:+&${2}}"
+ local api_token="${API_TOKEN-${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}}"
+ if [ -z "${api_token}" ]; then
+ echoerr "Please provide an API token with \$API_TOKEN or \$GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN."
+ return
+ fi
+
+ local max_page=3
+ local page=1
+
+ while true; do
+ local url="https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/pipelines/${CI_PIPELINE_ID}/jobs?per_page=100&page=${page}${query_string}"
+ echoinfo "GET ${url}"
+
+ local job_id
+ job_id=$(curl --silent --show-error --header "PRIVATE-TOKEN: ${api_token}" "${url}" | jq "map(select(.name == \"${job_name}\")) | map(.id) | last")
+ [[ "${job_id}" == "null" && "${page}" -lt "$max_page" ]] || break
+
+ let "page++"
+ done
+
+ if [[ "${job_id}" == "" ]]; then
+ echoerr "The '${job_name}' job ID couldn't be retrieved!"
+ else
+ echoinfo "The '${job_name}' job ID is ${job_id}"
+ echo "${job_id}"
+ fi
+}
+
+function play_job() {
+ local job_name="${1}"
+ local job_id
+ job_id=$(get_job_id "${job_name}" "scope=manual");
+ if [ -z "${job_id}" ]; then return; fi
+
+ local api_token="${API_TOKEN-${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}}"
+ if [ -z "${api_token}" ]; then
+ echoerr "Please provide an API token with \$API_TOKEN or \$GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN."
+ return
+ fi
+
+ local url="https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/jobs/${job_id}/play"
+ echoinfo "POST ${url}"
+
+ local job_url
+ job_url=$(curl --silent --show-error --request POST --header "PRIVATE-TOKEN: ${api_token}" "${url}" | jq ".web_url")
+ echoinfo "Manual job '${job_name}' started at: ${job_url}"
+}
+
+function wait_for_job_to_be_done() {
+ local job_name="${1}"
+ local query_string="${2}"
+ local job_id
+ job_id=$(get_job_id "${job_name}" "${query_string}")
+ if [ -z "${job_id}" ]; then return; fi
+
+ local api_token="${API_TOKEN-${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}}"
+ if [ -z "${api_token}" ]; then
+ echoerr "Please provide an API token with \$API_TOKEN or \$GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN."
+ return
+ fi
+
+ echoinfo "Waiting for the '${job_name}' job to finish..."
+
+ local url="https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/jobs/${job_id}"
+ echoinfo "GET ${url}"
+
+ # In case the job hasn't finished yet. Keep trying until the job times out.
+ local interval=30
+ local elapsed_seconds=0
+ while true; do
+ local job_status
+ job_status=$(curl --silent --show-error --header "PRIVATE-TOKEN: ${api_token}" "${url}" | jq ".status" | sed -e s/\"//g)
+ [[ "${job_status}" == "pending" || "${job_status}" == "running" ]] || break
+
+ printf "."
+ let "elapsed_seconds+=interval"
+ sleep ${interval}
+ done
+
+ local elapsed_minutes=$((elapsed_seconds / 60))
+ echoinfo "Waited '${job_name}' for ${elapsed_minutes} minutes."
+
+ if [[ "${job_status}" == "failed" ]]; then
+ echoerr "The '${job_name}' failed."
+ elif [[ "${job_status}" == "manual" ]]; then
+ echoinfo "The '${job_name}' is manual."
+ else
+ echoinfo "The '${job_name}' passed."
+ fi
+}
diff --git a/security.txt b/security.txt
new file mode 100644
index 00000000000..f7adb43fda6
--- /dev/null
+++ b/security.txt
@@ -0,0 +1,6 @@
+Contact: security@gitlab.com
+Acknowledgments: https://about.gitlab.com/security/vulnerability-acknowledgements/
+Preferred-Languages: en
+Canonical: https://about.gitlab.com/security/disclosure/
+Policy: https://hackerone.com/gitlab
+Hiring: https://about.gitlab.com/jobs/
diff --git a/spec/controllers/acme_challenges_controller_spec.rb b/spec/controllers/acme_challenges_controller_spec.rb
new file mode 100644
index 00000000000..cee06bed27b
--- /dev/null
+++ b/spec/controllers/acme_challenges_controller_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe AcmeChallengesController do
+ describe '#show' do
+ let!(:acme_order) { create(:pages_domain_acme_order) }
+
+ def make_request(domain, token)
+ get(:show, params: { domain: domain, token: token })
+ end
+
+ before do
+ make_request(domain, token)
+ end
+
+ context 'with right domain and token' do
+ let(:domain) { acme_order.pages_domain.domain }
+ let(:token) { acme_order.challenge_token }
+
+ it 'renders acme challenge file content' do
+ expect(response.body).to eq(acme_order.challenge_file_content)
+ end
+ end
+
+ context 'when domain is invalid' do
+ let(:domain) { 'somewrongdomain.com' }
+ let(:token) { acme_order.challenge_token }
+
+ it 'renders not found' do
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'when token is invalid' do
+ let(:domain) { acme_order.pages_domain.domain }
+ let(:token) { 'wrongtoken' }
+
+ it 'renders not found' do
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+end
diff --git a/spec/controllers/admin/clusters/applications_controller_spec.rb b/spec/controllers/admin/clusters/applications_controller_spec.rb
new file mode 100644
index 00000000000..76f261e7d3f
--- /dev/null
+++ b/spec/controllers/admin/clusters/applications_controller_spec.rb
@@ -0,0 +1,149 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Admin::Clusters::ApplicationsController do
+ include AccessMatchersForController
+
+ def current_application
+ Clusters::Cluster::APPLICATIONS[application]
+ end
+
+ shared_examples 'a secure endpoint' do
+ it { expect { subject }.to be_allowed_for(:admin) }
+ it { expect { subject }.to be_denied_for(:user) }
+ it { expect { subject }.to be_denied_for(:external) }
+
+ context 'when instance clusters are disabled' do
+ before do
+ stub_feature_flags(instance_clusters: false)
+ end
+
+ it 'returns 404' do
+ is_expected.to have_http_status(:not_found)
+ end
+ end
+ end
+
+ let(:cluster) { create(:cluster, :instance, :provided_by_gcp) }
+
+ describe 'POST create' do
+ subject do
+ post :create, params: params
+ end
+
+ let(:application) { 'helm' }
+ let(:params) { { application: application, id: cluster.id } }
+
+ describe 'functionality' do
+ let(:admin) { create(:admin) }
+
+ before do
+ sign_in(admin)
+ end
+
+ it 'schedule an application installation' do
+ expect(ClusterInstallAppWorker).to receive(:perform_async).with(application, anything).once
+
+ expect { subject }.to change { current_application.count }
+ expect(response).to have_http_status(:no_content)
+ expect(cluster.application_helm).to be_scheduled
+ end
+
+ context 'when cluster do not exists' do
+ before do
+ cluster.destroy!
+ end
+
+ it 'return 404' do
+ expect { subject }.not_to change { current_application.count }
+ expect(response).to have_http_status(:not_found)
+ end
+ end
+
+ context 'when application is unknown' do
+ let(:application) { 'unkwnown-app' }
+
+ it 'return 404' do
+ is_expected.to have_http_status(:not_found)
+ end
+ end
+
+ context 'when application is already installing' do
+ before do
+ create(:clusters_applications_helm, :installing, cluster: cluster)
+ end
+
+ it 'returns 400' do
+ is_expected.to have_http_status(:bad_request)
+ end
+ end
+ end
+
+ describe 'security' do
+ before do
+ allow(ClusterInstallAppWorker).to receive(:perform_async)
+ end
+
+ it_behaves_like 'a secure endpoint'
+ end
+ end
+
+ describe 'PATCH update' do
+ subject do
+ patch :update, params: params
+ end
+
+ let!(:application) { create(:clusters_applications_cert_managers, :installed, cluster: cluster) }
+ let(:application_name) { application.name }
+ let(:params) { { application: application_name, id: cluster.id, email: "new-email@example.com" } }
+
+ describe 'functionality' do
+ let(:admin) { create(:admin) }
+
+ before do
+ sign_in(admin)
+ end
+
+ context "when cluster and app exists" do
+ it "schedules an application update" do
+ expect(ClusterPatchAppWorker).to receive(:perform_async).with(application.name, anything).once
+
+ is_expected.to have_http_status(:no_content)
+
+ expect(cluster.application_cert_manager).to be_scheduled
+ end
+ end
+
+ context 'when cluster do not exists' do
+ before do
+ cluster.destroy!
+ end
+
+ it { is_expected.to have_http_status(:not_found) }
+ end
+
+ context 'when application is unknown' do
+ let(:application_name) { 'unkwnown-app' }
+
+ it { is_expected.to have_http_status(:not_found) }
+ end
+
+ context 'when application is already scheduled' do
+ before do
+ application.make_scheduled!
+ end
+
+ it { is_expected.to have_http_status(:bad_request) }
+ end
+ end
+
+ describe 'security' do
+ before do
+ allow(ClusterPatchAppWorker).to receive(:perform_async)
+ end
+
+ it_behaves_like 'a secure endpoint'
+ end
+ end
+end
diff --git a/spec/controllers/admin/clusters_controller_spec.rb b/spec/controllers/admin/clusters_controller_spec.rb
new file mode 100644
index 00000000000..7b77cb186a4
--- /dev/null
+++ b/spec/controllers/admin/clusters_controller_spec.rb
@@ -0,0 +1,540 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Admin::ClustersController do
+ include AccessMatchersForController
+ include GoogleApi::CloudPlatformHelpers
+
+ let(:admin) { create(:admin) }
+
+ before do
+ sign_in(admin)
+ end
+
+ describe 'GET #index' do
+ def get_index(params = {})
+ get :index, params: params
+ end
+
+ context 'when feature flag is not enabled' do
+ before do
+ stub_feature_flags(instance_clusters: false)
+ end
+
+ it 'responds with not found' do
+ get_index
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'when feature flag is enabled' do
+ before do
+ stub_feature_flags(instance_clusters: true)
+ end
+
+ describe 'functionality' do
+ context 'when instance has one or more clusters' do
+ let!(:enabled_cluster) do
+ create(:cluster, :provided_by_gcp, :instance)
+ end
+
+ let!(:disabled_cluster) do
+ create(:cluster, :disabled, :provided_by_gcp, :production_environment, :instance)
+ end
+
+ it 'lists available clusters' do
+ get_index
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template(:index)
+ expect(assigns(:clusters)).to match_array([enabled_cluster, disabled_cluster])
+ end
+
+ context 'when page is specified' do
+ let(:last_page) { Clusters::Cluster.instance_type.page.total_pages }
+
+ before do
+ allow(Clusters::Cluster).to receive(:paginates_per).and_return(1)
+ create_list(:cluster, 2, :provided_by_gcp, :production_environment, :instance)
+ end
+
+ it 'redirects to the page' do
+ get_index(page: last_page)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(assigns(:clusters).current_page).to eq(last_page)
+ end
+ end
+ end
+
+ context 'when instance does not have a cluster' do
+ it 'returns an empty state page' do
+ get_index
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template(:index, partial: :empty_state)
+ expect(assigns(:clusters)).to eq([])
+ end
+ end
+ end
+ end
+
+ describe 'security' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :instance) }
+
+ it { expect { get_index }.to be_allowed_for(:admin) }
+ it { expect { get_index }.to be_denied_for(:user) }
+ it { expect { get_index }.to be_denied_for(:external) }
+ end
+ end
+
+ describe 'GET #new' do
+ def get_new
+ get :new
+ end
+
+ describe 'functionality for new cluster' do
+ context 'when omniauth has been configured' do
+ let(:key) { 'secret-key' }
+ let(:session_key_for_redirect_uri) do
+ GoogleApi::CloudPlatform::Client.session_key_for_redirect_uri(key)
+ end
+
+ before do
+ allow(SecureRandom).to receive(:hex).and_return(key)
+ end
+
+ it 'has authorize_url' do
+ get_new
+
+ expect(assigns(:authorize_url)).to include(key)
+ expect(session[session_key_for_redirect_uri]).to eq(new_admin_cluster_path)
+ end
+ end
+
+ context 'when omniauth has not configured' do
+ before do
+ stub_omniauth_setting(providers: [])
+ end
+
+ it 'does not have authorize_url' do
+ get_new
+
+ expect(assigns(:authorize_url)).to be_nil
+ end
+ end
+
+ context 'when access token is valid' do
+ before do
+ stub_google_api_validate_token
+ end
+
+ it 'has new object' do
+ get_new
+
+ expect(assigns(:gcp_cluster)).to be_an_instance_of(Clusters::ClusterPresenter)
+ end
+ end
+
+ context 'when access token is expired' do
+ before do
+ stub_google_api_expired_token
+ end
+
+ it { expect(@valid_gcp_token).to be_falsey }
+ end
+
+ context 'when access token is not stored in session' do
+ it { expect(@valid_gcp_token).to be_falsey }
+ end
+ end
+
+ describe 'functionality for existing cluster' do
+ it 'has new object' do
+ get_new
+
+ expect(assigns(:user_cluster)).to be_an_instance_of(Clusters::ClusterPresenter)
+ end
+ end
+
+ describe 'security' do
+ it { expect { get_new }.to be_allowed_for(:admin) }
+ it { expect { get_new }.to be_denied_for(:user) }
+ it { expect { get_new }.to be_denied_for(:external) }
+ end
+ end
+
+ describe 'POST #create_gcp' do
+ let(:legacy_abac_param) { 'true' }
+ let(:params) do
+ {
+ cluster: {
+ name: 'new-cluster',
+ provider_gcp_attributes: {
+ gcp_project_id: 'gcp-project-12345',
+ legacy_abac: legacy_abac_param
+ }
+ }
+ }
+ end
+
+ def post_create_gcp
+ post :create_gcp, params: params
+ end
+
+ describe 'functionality' do
+ context 'when access token is valid' do
+ before do
+ stub_google_api_validate_token
+ end
+
+ it 'creates a new cluster' do
+ expect(ClusterProvisionWorker).to receive(:perform_async)
+ expect { post_create_gcp }.to change { Clusters::Cluster.count }
+ .and change { Clusters::Providers::Gcp.count }
+
+ cluster = Clusters::Cluster.instance_type.first
+
+ expect(response).to redirect_to(admin_cluster_path(cluster))
+ expect(cluster).to be_gcp
+ expect(cluster).to be_kubernetes
+ expect(cluster.provider_gcp).to be_legacy_abac
+ end
+
+ context 'when legacy_abac param is false' do
+ let(:legacy_abac_param) { 'false' }
+
+ it 'creates a new cluster with legacy_abac_disabled' do
+ expect(ClusterProvisionWorker).to receive(:perform_async)
+ expect { post_create_gcp }.to change { Clusters::Cluster.count }
+ .and change { Clusters::Providers::Gcp.count }
+ expect(Clusters::Cluster.instance_type.first.provider_gcp).not_to be_legacy_abac
+ end
+ end
+ end
+
+ context 'when access token is expired' do
+ before do
+ stub_google_api_expired_token
+ end
+
+ it { expect(@valid_gcp_token).to be_falsey }
+ end
+
+ context 'when access token is not stored in session' do
+ it { expect(@valid_gcp_token).to be_falsey }
+ end
+ end
+
+ describe 'security' do
+ before do
+ allow_any_instance_of(described_class)
+ .to receive(:token_in_session).and_return('token')
+ allow_any_instance_of(described_class)
+ .to receive(:expires_at_in_session).and_return(1.hour.since.to_i.to_s)
+ allow_any_instance_of(GoogleApi::CloudPlatform::Client)
+ .to receive(:projects_zones_clusters_create) do
+ OpenStruct.new(
+ self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123',
+ status: 'RUNNING'
+ )
+ end
+
+ allow(WaitForClusterCreationWorker).to receive(:perform_in).and_return(nil)
+ end
+
+ it { expect { post_create_gcp }.to be_allowed_for(:admin) }
+ it { expect { post_create_gcp }.to be_denied_for(:user) }
+ it { expect { post_create_gcp }.to be_denied_for(:external) }
+ end
+ end
+
+ describe 'POST #create_user' do
+ let(:params) do
+ {
+ cluster: {
+ name: 'new-cluster',
+ platform_kubernetes_attributes: {
+ api_url: 'http://my-url',
+ token: 'test'
+ }
+ }
+ }
+ end
+
+ def post_create_user
+ post :create_user, params: params
+ end
+
+ describe 'functionality' do
+ context 'when creates a cluster' do
+ it 'creates a new cluster' do
+ expect(ClusterProvisionWorker).to receive(:perform_async)
+
+ expect { post_create_user }.to change { Clusters::Cluster.count }
+ .and change { Clusters::Platforms::Kubernetes.count }
+
+ cluster = Clusters::Cluster.instance_type.first
+
+ expect(response).to redirect_to(admin_cluster_path(cluster))
+ expect(cluster).to be_user
+ expect(cluster).to be_kubernetes
+ end
+ end
+
+ context 'when creates a RBAC-enabled cluster' do
+ let(:params) do
+ {
+ cluster: {
+ name: 'new-cluster',
+ platform_kubernetes_attributes: {
+ api_url: 'http://my-url',
+ token: 'test',
+ authorization_type: 'rbac'
+ }
+ }
+ }
+ end
+
+ it 'creates a new cluster' do
+ expect(ClusterProvisionWorker).to receive(:perform_async)
+
+ expect { post_create_user }.to change { Clusters::Cluster.count }
+ .and change { Clusters::Platforms::Kubernetes.count }
+
+ cluster = Clusters::Cluster.instance_type.first
+
+ expect(response).to redirect_to(admin_cluster_path(cluster))
+ expect(cluster).to be_user
+ expect(cluster).to be_kubernetes
+ expect(cluster).to be_platform_kubernetes_rbac
+ end
+ end
+ end
+
+ describe 'security' do
+ it { expect { post_create_user }.to be_allowed_for(:admin) }
+ it { expect { post_create_user }.to be_denied_for(:user) }
+ it { expect { post_create_user }.to be_denied_for(:external) }
+ end
+ end
+
+ describe 'GET #cluster_status' do
+ let(:cluster) { create(:cluster, :providing_by_gcp, :instance) }
+
+ def get_cluster_status
+ get :cluster_status,
+ params: {
+ id: cluster
+ },
+ format: :json
+ end
+
+ describe 'functionality' do
+ it 'responds with matching schema' do
+ get_cluster_status
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('cluster_status')
+ end
+
+ it 'invokes schedule_status_update on each application' do
+ expect_any_instance_of(Clusters::Applications::Ingress).to receive(:schedule_status_update)
+
+ get_cluster_status
+ end
+ end
+
+ describe 'security' do
+ it { expect { get_cluster_status }.to be_allowed_for(:admin) }
+ it { expect { get_cluster_status }.to be_denied_for(:user) }
+ it { expect { get_cluster_status }.to be_denied_for(:external) }
+ end
+ end
+
+ describe 'GET #show' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :instance) }
+
+ def get_show
+ get :show,
+ params: {
+ id: cluster
+ }
+ end
+
+ describe 'functionality' do
+ it 'responds successfully' do
+ get_show
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(assigns(:cluster)).to eq(cluster)
+ end
+ end
+
+ describe 'security' do
+ it { expect { get_show }.to be_allowed_for(:admin) }
+ it { expect { get_show }.to be_denied_for(:user) }
+ it { expect { get_show }.to be_denied_for(:external) }
+ end
+ end
+
+ describe 'PUT #update' do
+ def put_update(format: :html)
+ put :update, params: params.merge(
+ id: cluster,
+ format: format
+ )
+ end
+
+ let(:cluster) { create(:cluster, :provided_by_user, :instance) }
+ let(:domain) { 'test-domain.com' }
+
+ let(:params) do
+ {
+ cluster: {
+ enabled: false,
+ name: 'my-new-cluster-name',
+ base_domain: domain
+ }
+ }
+ end
+
+ it 'updates and redirects back to show page' do
+ put_update
+
+ cluster.reload
+ expect(response).to redirect_to(admin_cluster_path(cluster))
+ expect(flash[:notice]).to eq('Kubernetes cluster was successfully updated.')
+ expect(cluster.enabled).to be_falsey
+ expect(cluster.name).to eq('my-new-cluster-name')
+ expect(cluster.domain).to eq('test-domain.com')
+ end
+
+ context 'when domain is invalid' do
+ let(:domain) { 'http://not-a-valid-domain' }
+
+ it 'does not update cluster attributes' do
+ put_update
+
+ cluster.reload
+ expect(response).to render_template(:show)
+ expect(cluster.name).not_to eq('my-new-cluster-name')
+ expect(cluster.domain).not_to eq('test-domain.com')
+ end
+ end
+
+ context 'when format is json' do
+ context 'when changing parameters' do
+ context 'when valid parameters are used' do
+ let(:params) do
+ {
+ cluster: {
+ enabled: false,
+ name: 'my-new-cluster-name',
+ domain: domain
+ }
+ }
+ end
+
+ it 'updates and redirects back to show page' do
+ put_update(format: :json)
+
+ cluster.reload
+ expect(response).to have_http_status(:no_content)
+ expect(cluster.enabled).to be_falsey
+ expect(cluster.name).to eq('my-new-cluster-name')
+ end
+ end
+
+ context 'when invalid parameters are used' do
+ let(:params) do
+ {
+ cluster: {
+ enabled: false,
+ name: ''
+ }
+ }
+ end
+
+ it 'rejects changes' do
+ put_update(format: :json)
+
+ expect(response).to have_http_status(:bad_request)
+ end
+ end
+ end
+ end
+
+ describe 'security' do
+ set(:cluster) { create(:cluster, :provided_by_gcp, :instance) }
+
+ it { expect { put_update }.to be_allowed_for(:admin) }
+ it { expect { put_update }.to be_denied_for(:user) }
+ it { expect { put_update }.to be_denied_for(:external) }
+ end
+ end
+
+ describe 'DELETE #destroy' do
+ let!(:cluster) { create(:cluster, :provided_by_gcp, :production_environment, :instance) }
+
+ def delete_destroy
+ delete :destroy,
+ params: {
+ id: cluster
+ }
+ end
+
+ describe 'functionality' do
+ context 'when cluster is provided by GCP' do
+ context 'when cluster is created' do
+ it 'destroys and redirects back to clusters list' do
+ expect { delete_destroy }
+ .to change { Clusters::Cluster.count }.by(-1)
+ .and change { Clusters::Platforms::Kubernetes.count }.by(-1)
+ .and change { Clusters::Providers::Gcp.count }.by(-1)
+
+ expect(response).to redirect_to(admin_clusters_path)
+ expect(flash[:notice]).to eq('Kubernetes cluster integration was successfully removed.')
+ end
+ end
+
+ context 'when cluster is being created' do
+ let!(:cluster) { create(:cluster, :providing_by_gcp, :production_environment, :instance) }
+
+ it 'destroys and redirects back to clusters list' do
+ expect { delete_destroy }
+ .to change { Clusters::Cluster.count }.by(-1)
+ .and change { Clusters::Providers::Gcp.count }.by(-1)
+
+ expect(response).to redirect_to(admin_clusters_path)
+ expect(flash[:notice]).to eq('Kubernetes cluster integration was successfully removed.')
+ end
+ end
+ end
+
+ context 'when cluster is provided by user' do
+ let!(:cluster) { create(:cluster, :provided_by_user, :production_environment, :instance) }
+
+ it 'destroys and redirects back to clusters list' do
+ expect { delete_destroy }
+ .to change { Clusters::Cluster.count }.by(-1)
+ .and change { Clusters::Platforms::Kubernetes.count }.by(-1)
+ .and change { Clusters::Providers::Gcp.count }.by(0)
+
+ expect(response).to redirect_to(admin_clusters_path)
+ expect(flash[:notice]).to eq('Kubernetes cluster integration was successfully removed.')
+ end
+ end
+ end
+
+ describe 'security' do
+ set(:cluster) { create(:cluster, :provided_by_gcp, :production_environment, :instance) }
+
+ it { expect { delete_destroy }.to be_allowed_for(:admin) }
+ it { expect { delete_destroy }.to be_denied_for(:user) }
+ it { expect { delete_destroy }.to be_denied_for(:external) }
+ end
+ end
+end
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index a5ecb475ce3..40669ec5451 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -206,8 +206,19 @@ describe ApplicationController do
describe '#check_two_factor_requirement' do
subject { controller.send :check_two_factor_requirement }
+ it 'does not redirect if user has temporary oauth email' do
+ oauth_user = create(:user, email: 'temp-email-for-oauth@email.com')
+ allow(controller).to receive(:two_factor_authentication_required?).and_return(true)
+ allow(controller).to receive(:current_user).and_return(oauth_user)
+
+ expect(controller).not_to receive(:redirect_to)
+
+ subject
+ end
+
it 'does not redirect if 2FA is not required' do
allow(controller).to receive(:two_factor_authentication_required?).and_return(false)
+
expect(controller).not_to receive(:redirect_to)
subject
@@ -216,6 +227,7 @@ describe ApplicationController do
it 'does not redirect if user is not logged in' do
allow(controller).to receive(:two_factor_authentication_required?).and_return(true)
allow(controller).to receive(:current_user).and_return(nil)
+
expect(controller).not_to receive(:redirect_to)
subject
@@ -223,8 +235,9 @@ describe ApplicationController do
it 'does not redirect if user has 2FA enabled' do
allow(controller).to receive(:two_factor_authentication_required?).and_return(true)
- allow(controller).to receive(:current_user).twice.and_return(user)
+ allow(controller).to receive(:current_user).thrice.and_return(user)
allow(user).to receive(:two_factor_enabled?).and_return(true)
+
expect(controller).not_to receive(:redirect_to)
subject
@@ -232,9 +245,10 @@ describe ApplicationController do
it 'does not redirect if 2FA setup can be skipped' do
allow(controller).to receive(:two_factor_authentication_required?).and_return(true)
- allow(controller).to receive(:current_user).twice.and_return(user)
+ allow(controller).to receive(:current_user).thrice.and_return(user)
allow(user).to receive(:two_factor_enabled?).and_return(false)
allow(controller).to receive(:skip_two_factor?).and_return(true)
+
expect(controller).not_to receive(:redirect_to)
subject
@@ -242,10 +256,11 @@ describe ApplicationController do
it 'redirects to 2FA setup otherwise' do
allow(controller).to receive(:two_factor_authentication_required?).and_return(true)
- allow(controller).to receive(:current_user).twice.and_return(user)
+ allow(controller).to receive(:current_user).thrice.and_return(user)
allow(user).to receive(:two_factor_enabled?).and_return(false)
allow(controller).to receive(:skip_two_factor?).and_return(false)
allow(controller).to receive(:profile_two_factor_auth_path)
+
expect(controller).to receive(:redirect_to)
subject
@@ -462,7 +477,7 @@ describe ApplicationController do
end
it 'does log correlation id' do
- Gitlab::CorrelationId.use_id('new-id') do
+ Labkit::Correlation::CorrelationId.use_id('new-id') do
get :index
end
@@ -676,4 +691,38 @@ describe ApplicationController do
end
end
end
+
+ context 'Gitlab::Session' do
+ controller(described_class) do
+ prepend_before_action do
+ authenticate_sessionless_user!(:rss)
+ end
+
+ def index
+ if Gitlab::Session.current
+ head :created
+ else
+ head :not_found
+ end
+ end
+ end
+
+ it 'is set on web requests' do
+ sign_in(user)
+
+ get :index
+
+ expect(response).to have_gitlab_http_status(:created)
+ end
+
+ context 'with sessionless user' do
+ it 'is not set' do
+ personal_access_token = create(:personal_access_token, user: user)
+
+ get :index, format: :atom, params: { private_token: personal_access_token.token }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
end
diff --git a/spec/controllers/concerns/boards_responses_spec.rb b/spec/controllers/concerns/boards_responses_spec.rb
new file mode 100644
index 00000000000..bdebdf94761
--- /dev/null
+++ b/spec/controllers/concerns/boards_responses_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe BoardsResponses do
+ let(:controller_class) do
+ Class.new do
+ include BoardsResponses
+ end
+ end
+
+ subject(:controller) { controller_class.new }
+
+ describe '#serialize_as_json' do
+ let!(:board) { create(:board) }
+
+ it 'serializes properly' do
+ expected = { "id" => board.id }
+
+ expect(subject.serialize_as_json(board)).to include(expected)
+ end
+ end
+end
diff --git a/spec/controllers/concerns/enforces_admin_authentication_spec.rb b/spec/controllers/concerns/enforces_admin_authentication_spec.rb
new file mode 100644
index 00000000000..e6a6702fdea
--- /dev/null
+++ b/spec/controllers/concerns/enforces_admin_authentication_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe EnforcesAdminAuthentication do
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ controller(ApplicationController) do
+ # `described_class` is not available in this context
+ include EnforcesAdminAuthentication # rubocop:disable RSpec/DescribedClass
+
+ def index
+ head :ok
+ end
+ end
+
+ describe 'authenticate_admin!' do
+ context 'as an admin' do
+ let(:user) { create(:admin) }
+
+ it 'renders ok' do
+ get :index
+
+ expect(response).to have_gitlab_http_status(200)
+ end
+ end
+
+ context 'as a user' do
+ it 'renders a 404' do
+ get :index
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+end
diff --git a/spec/controllers/concerns/import_url_params_spec.rb b/spec/controllers/concerns/import_url_params_spec.rb
new file mode 100644
index 00000000000..adbe6e5d3bf
--- /dev/null
+++ b/spec/controllers/concerns/import_url_params_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ImportUrlParams do
+ let(:import_url_params) do
+ controller = OpenStruct.new(params: params).extend(described_class)
+ controller.import_url_params
+ end
+
+ context 'empty URL' do
+ let(:params) do
+ ActionController::Parameters.new(project: {
+ title: 'Test'
+ })
+ end
+
+ it 'returns empty hash' do
+ expect(import_url_params).to eq({})
+ end
+ end
+
+ context 'url and password separately provided' do
+ let(:params) do
+ ActionController::Parameters.new(project: {
+ import_url: 'https://url.com',
+ import_url_user: 'user', import_url_password: 'password'
+ })
+ end
+
+ describe '#import_url_params' do
+ it 'returns hash with import_url' do
+ expect(import_url_params).to eq(
+ import_url: "https://user:password@url.com"
+ )
+ end
+ end
+ end
+
+ context 'url with provided empty credentials' do
+ let(:params) do
+ ActionController::Parameters.new(project: {
+ import_url: 'https://user:password@url.com',
+ import_url_user: '', import_url_password: ''
+ })
+ end
+
+ describe '#import_url_params' do
+ it 'does not change the url' do
+ expect(import_url_params).to eq(
+ import_url: "https://user:password@url.com"
+ )
+ end
+ end
+ end
+end
diff --git a/spec/controllers/concerns/issuable_collections_spec.rb b/spec/controllers/concerns/issuable_collections_spec.rb
index f9d15d04719..fb2cd5ca955 100644
--- a/spec/controllers/concerns/issuable_collections_spec.rb
+++ b/spec/controllers/concerns/issuable_collections_spec.rb
@@ -108,51 +108,77 @@ describe IssuableCollections do
end
describe '#finder_options' do
- let(:params) do
- {
- assignee_id: '1',
- assignee_username: 'user1',
- author_id: '2',
- author_username: 'user2',
- authorized_only: 'yes',
- confidential: true,
- due_date: '2017-01-01',
- group_id: '3',
- iids: '4',
- label_name: ['foo'],
- milestone_title: 'bar',
- my_reaction_emoji: 'thumbsup',
- non_archived: 'true',
- project_id: '5',
- scope: 'all',
- search: 'baz',
- sort: 'priority',
- state: 'opened',
- invalid_param: 'invalid_param'
- }
- end
-
- it 'only allows whitelisted params' do
+ before do
allow(controller).to receive(:cookies).and_return({})
allow(controller).to receive(:current_user).and_return(nil)
+ end
+
+ subject { controller.send(:finder_options).to_h }
+
+ context 'scalar params' do
+ let(:params) do
+ {
+ assignee_id: '1',
+ assignee_username: 'user1',
+ author_id: '2',
+ author_username: 'user2',
+ authorized_only: 'yes',
+ confidential: true,
+ due_date: '2017-01-01',
+ group_id: '3',
+ iids: '4',
+ label_name: 'foo',
+ milestone_title: 'bar',
+ my_reaction_emoji: 'thumbsup',
+ non_archived: 'true',
+ project_id: '5',
+ scope: 'all',
+ search: 'baz',
+ sort: 'priority',
+ state: 'opened',
+ invalid_param: 'invalid_param'
+ }
+ end
+
+ it 'only allows whitelisted params' do
+ is_expected.to include({
+ 'assignee_id' => '1',
+ 'assignee_username' => 'user1',
+ 'author_id' => '2',
+ 'author_username' => 'user2',
+ 'confidential' => true,
+ 'label_name' => 'foo',
+ 'milestone_title' => 'bar',
+ 'my_reaction_emoji' => 'thumbsup',
+ 'due_date' => '2017-01-01',
+ 'scope' => 'all',
+ 'search' => 'baz',
+ 'sort' => 'priority',
+ 'state' => 'opened'
+ })
+
+ is_expected.not_to include('invalid_param')
+ end
+ end
+
+ context 'array params' do
+ let(:params) do
+ {
+ assignee_username: %w[user1 user2],
+ label_name: %w[label1 label2],
+ invalid_param: 'invalid_param',
+ invalid_array: ['param']
+ }
+ end
+
+ it 'only allows whitelisted params' do
+ is_expected.to include({
+ 'label_name' => %w[label1 label2],
+ 'assignee_username' => %w[user1 user2]
+ })
- finder_options = controller.send(:finder_options)
-
- expect(finder_options).to eq(ActionController::Parameters.new({
- 'assignee_id' => '1',
- 'assignee_username' => 'user1',
- 'author_id' => '2',
- 'author_username' => 'user2',
- 'confidential' => true,
- 'label_name' => ['foo'],
- 'milestone_title' => 'bar',
- 'my_reaction_emoji' => 'thumbsup',
- 'due_date' => '2017-01-01',
- 'scope' => 'all',
- 'search' => 'baz',
- 'sort' => 'priority',
- 'state' => 'opened'
- }).permit!)
+ is_expected.not_to include('invalid_param', 'invalid_array')
+ end
end
end
end
diff --git a/spec/controllers/concerns/project_unauthorized_spec.rb b/spec/controllers/concerns/project_unauthorized_spec.rb
index 57ac00cf4dd..5834b1ef37f 100644
--- a/spec/controllers/concerns/project_unauthorized_spec.rb
+++ b/spec/controllers/concerns/project_unauthorized_spec.rb
@@ -12,7 +12,7 @@ describe ProjectUnauthorized do
render_views
- describe '#project_unauthorized_proc' do
+ describe '.on_routable_not_found' do
controller(::Projects::ApplicationController) do
def show
head :ok
diff --git a/spec/controllers/concerns/routable_actions_spec.rb b/spec/controllers/concerns/routable_actions_spec.rb
new file mode 100644
index 00000000000..59d48c68b9c
--- /dev/null
+++ b/spec/controllers/concerns/routable_actions_spec.rb
@@ -0,0 +1,156 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe RoutableActions do
+ controller(::ApplicationController) do
+ include RoutableActions # rubocop:disable RSpec/DescribedClass
+
+ before_action :routable
+
+ def routable
+ @klass = params[:type].constantize
+ @routable = find_routable!(params[:type].constantize, params[:id])
+ end
+
+ def show
+ head :ok
+ end
+ end
+
+ def get_routable(routable)
+ get :show, params: { id: routable.full_path, type: routable.class }
+ end
+
+ describe '#find_routable!' do
+ context 'when signed in' do
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ context 'with a project' do
+ let(:routable) { create(:project) }
+
+ context 'when authorized' do
+ before do
+ routable.add_guest(user)
+ end
+
+ it 'returns the project' do
+ get_routable(routable)
+
+ expect(assigns[:routable]).to be_a(Project)
+ end
+
+ it 'allows access' do
+ get_routable(routable)
+
+ expect(response).to have_gitlab_http_status(200)
+ end
+ end
+
+ it 'prevents access when not authorized' do
+ get_routable(routable)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'with a group' do
+ let(:routable) { create(:group, :private) }
+
+ context 'when authorized' do
+ before do
+ routable.add_guest(user)
+ end
+
+ it 'returns the group' do
+ get_routable(routable)
+
+ expect(assigns[:routable]).to be_a(Group)
+ end
+
+ it 'allows access' do
+ get_routable(routable)
+
+ expect(response).to have_gitlab_http_status(200)
+ end
+ end
+
+ it 'prevents access when not authorized' do
+ get_routable(routable)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'with a user' do
+ let(:routable) { user }
+
+ it 'allows access when authorized' do
+ get_routable(routable)
+
+ expect(response).to have_gitlab_http_status(200)
+ end
+
+ it 'prevents access when unauthorized' do
+ allow(subject).to receive(:can?).and_return(false)
+
+ get_routable(user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+
+ context 'when not signed in' do
+ it 'redirects to sign in for private resouces' do
+ routable = create(:project, :private)
+
+ get_routable(routable)
+
+ expect(response).to have_gitlab_http_status(302)
+ expect(response.location).to end_with('/users/sign_in')
+ end
+ end
+ end
+
+ describe '#perform_not_found_actions' do
+ let(:routable) { create(:project) }
+
+ before do
+ sign_in(create(:user))
+ end
+
+ it 'performs multiple checks' do
+ last_check_called = false
+ checks = [proc {}, proc { last_check_called = true }]
+ allow(subject).to receive(:not_found_actions).and_return(checks)
+
+ get_routable(routable)
+
+ expect(last_check_called).to eq(true)
+ end
+
+ it 'performs checks in the context of the controller' do
+ check = lambda { |routable| redirect_to routable }
+ allow(subject).to receive(:not_found_actions).and_return([check])
+
+ get_routable(routable)
+
+ expect(response.location).to end_with(routable.to_param)
+ end
+
+ it 'skips checks once one has resulted in a render/redirect' do
+ first_check = proc { render plain: 'first' }
+ second_check = proc { render plain: 'second' }
+ allow(subject).to receive(:not_found_actions).and_return([first_check, second_check])
+
+ get_routable(routable)
+
+ expect(response.body).to eq('first')
+ end
+ end
+end
diff --git a/spec/controllers/concerns/send_file_upload_spec.rb b/spec/controllers/concerns/send_file_upload_spec.rb
index 8408578a7db..a3ce08f736c 100644
--- a/spec/controllers/concerns/send_file_upload_spec.rb
+++ b/spec/controllers/concerns/send_file_upload_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
require 'spec_helper'
@@ -13,7 +14,7 @@ describe SendFileUpload do
# user/:id
def dynamic_segment
- File.join(model.class.to_s.underscore, model.id.to_s)
+ File.join(model.class.underscore, model.id.to_s)
end
end
end
diff --git a/spec/controllers/groups/clusters_controller_spec.rb b/spec/controllers/groups/clusters_controller_spec.rb
index e5180ec5c5c..7349cb7094c 100644
--- a/spec/controllers/groups/clusters_controller_spec.rb
+++ b/spec/controllers/groups/clusters_controller_spec.rb
@@ -189,6 +189,7 @@ describe Groups::ClustersController do
{
cluster: {
name: 'new-cluster',
+ managed: '1',
provider_gcp_attributes: {
gcp_project_id: 'gcp-project-12345',
legacy_abac: legacy_abac_param
@@ -218,6 +219,7 @@ describe Groups::ClustersController do
expect(cluster).to be_gcp
expect(cluster).to be_kubernetes
expect(cluster.provider_gcp).to be_legacy_abac
+ expect(cluster).to be_managed
end
context 'when legacy_abac param is false' do
@@ -278,6 +280,7 @@ describe Groups::ClustersController do
{
cluster: {
name: 'new-cluster',
+ managed: '1',
platform_kubernetes_attributes: {
api_url: 'http://my-url',
token: 'test'
@@ -303,6 +306,7 @@ describe Groups::ClustersController do
expect(response).to redirect_to(group_cluster_path(group, cluster))
expect(cluster).to be_user
expect(cluster).to be_kubernetes
+ expect(cluster).to be_managed
end
end
@@ -334,6 +338,29 @@ describe Groups::ClustersController do
expect(cluster).to be_platform_kubernetes_rbac
end
end
+
+ context 'when creates a user-managed cluster' do
+ let(:params) do
+ {
+ cluster: {
+ name: 'new-cluster',
+ managed: '0',
+ platform_kubernetes_attributes: {
+ api_url: 'http://my-url',
+ token: 'test',
+ authorization_type: 'rbac'
+ }
+ }
+ }
+ end
+
+ it 'creates a new user-managed cluster' do
+ go
+
+ cluster = group.clusters.first
+ expect(cluster.managed?).to be_falsy
+ end
+ end
end
describe 'security' do
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
index 1cd08200552..47d7e278183 100644
--- a/spec/controllers/groups_controller_spec.rb
+++ b/spec/controllers/groups_controller_spec.rb
@@ -141,6 +141,28 @@ describe GroupsController do
end
describe 'POST #create' do
+ it 'allows creating a group' do
+ sign_in(user)
+
+ expect do
+ post :create, params: { group: { name: 'new_group', path: "new_group" } }
+ end.to change { Group.count }.by(1)
+
+ expect(response).to have_gitlab_http_status(302)
+ end
+
+ context 'authorization' do
+ it 'allows an admin to create a group' do
+ sign_in(create(:admin))
+
+ expect do
+ post :create, params: { group: { name: 'new_group', path: "new_group" } }
+ end.to change { Group.count }.by(1)
+
+ expect(response).to have_gitlab_http_status(302)
+ end
+ end
+
context 'when creating subgroups', :nested_groups do
[true, false].each do |can_create_group_status|
context "and can_create_group is #{can_create_group_status}" do
diff --git a/spec/controllers/import/fogbugz_controller_spec.rb b/spec/controllers/import/fogbugz_controller_spec.rb
index f1e0923f316..f7c813576aa 100644
--- a/spec/controllers/import/fogbugz_controller_spec.rb
+++ b/spec/controllers/import/fogbugz_controller_spec.rb
@@ -11,6 +11,44 @@ describe Import::FogbugzController do
sign_in(user)
end
+ describe 'POST #callback' do
+ let(:token) { FFaker::Lorem.characters(8) }
+ let(:uri) { 'https://example.com' }
+ let(:xml_response) { %Q(<?xml version=\"1.0\" encoding=\"UTF-8\"?><response><token><![CDATA[#{token}]]></token></response>) }
+
+ it 'attempts to contact Fogbugz server' do
+ stub_request(:post, "https://example.com/api.asp").to_return(status: 200, body: xml_response, headers: {})
+
+ post :callback, params: { uri: uri, email: 'test@example.com', password: 'mypassword' }
+
+ expect(session[:fogbugz_token]).to eq(token)
+ expect(session[:fogbugz_uri]).to eq(uri)
+ expect(response).to redirect_to(new_user_map_import_fogbugz_path)
+ end
+ end
+
+ describe 'POST #create_user_map' do
+ let(:user_map) do
+ {
+ "2" => {
+ "name" => "Test User",
+ "email" => "testuser@example.com",
+ "gitlab_user" => "3"
+ }
+ }
+ end
+
+ it 'stores the user map in the session' do
+ client = double(user_map: {})
+ expect(controller).to receive(:client).and_return(client)
+
+ post :create_user_map, params: { users: user_map }
+
+ expect(session[:fogbugz_user_map]).to eq(user_map)
+ expect(response).to redirect_to(status_import_fogbugz_path)
+ end
+ end
+
describe 'GET status' do
before do
@repo = OpenStruct.new(name: 'vim')
diff --git a/spec/controllers/import/phabricator_controller_spec.rb b/spec/controllers/import/phabricator_controller_spec.rb
new file mode 100644
index 00000000000..85085a8e996
--- /dev/null
+++ b/spec/controllers/import/phabricator_controller_spec.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Import::PhabricatorController do
+ let(:current_user) { create(:user) }
+
+ before do
+ sign_in current_user
+ end
+
+ describe 'GET #new' do
+ subject { get :new }
+
+ context 'when the import source is not available' do
+ before do
+ stub_feature_flags(phabricator_import: true)
+ stub_application_setting(import_sources: [])
+ end
+
+ it { is_expected.to have_gitlab_http_status(404) }
+ end
+
+ context 'when the feature is disabled' do
+ before do
+ stub_feature_flags(phabricator_import: false)
+ stub_application_setting(import_sources: ['phabricator'])
+ end
+
+ it { is_expected.to have_gitlab_http_status(404) }
+ end
+
+ context 'when the import is available' do
+ before do
+ stub_feature_flags(phabricator_import: true)
+ stub_application_setting(import_sources: ['phabricator'])
+ end
+
+ it { is_expected.to have_gitlab_http_status(200) }
+ end
+ end
+
+ describe 'POST #create' do
+ subject(:post_create) { post :create, params: params }
+
+ context 'with valid params' do
+ let(:params) do
+ { path: 'phab-import',
+ name: 'Phab import',
+ phabricator_server_url: 'https://phabricator.example.com',
+ api_token: 'hazaah',
+ namespace_id: current_user.namespace_id }
+ end
+
+ it 'creates a project to import' do
+ expect_next_instance_of(Gitlab::PhabricatorImport::Importer) do |importer|
+ expect(importer).to receive(:execute)
+ end
+
+ expect { post_create }.to change { current_user.namespace.projects.reload.size }.from(0).to(1)
+
+ expect(current_user.namespace.projects.last).to be_import
+ end
+ end
+
+ context 'when an import param is missing' do
+ let(:params) do
+ { path: 'phab-import',
+ name: 'Phab import',
+ phabricator_server_url: nil,
+ api_token: 'hazaah',
+ namespace_id: current_user.namespace_id }
+ end
+
+ it 'does not create the project' do
+ expect { post_create }.not_to change { current_user.namespace.projects.reload.size }
+ end
+ end
+
+ context 'when a project param is missing' do
+ let(:params) do
+ { phabricator_server_url: 'https://phabricator.example.com',
+ api_token: 'hazaah',
+ namespace_id: current_user.namespace_id }
+ end
+
+ it 'does not create the project' do
+ expect { post_create }.not_to change { current_user.namespace.projects.reload.size }
+ end
+ end
+ end
+end
diff --git a/spec/controllers/omniauth_callbacks_controller_spec.rb b/spec/controllers/omniauth_callbacks_controller_spec.rb
index 0af0eb4f942..6e374a8daa7 100644
--- a/spec/controllers/omniauth_callbacks_controller_spec.rb
+++ b/spec/controllers/omniauth_callbacks_controller_spec.rb
@@ -9,10 +9,14 @@ describe OmniauthCallbacksController, type: :controller do
let(:user) { create(:omniauth_user, extern_uid: extern_uid, provider: provider) }
before do
- mock_auth_hash(provider.to_s, +extern_uid, user.email)
+ @original_env_config_omniauth_auth = mock_auth_hash(provider.to_s, +extern_uid, user.email)
stub_omniauth_provider(provider, context: request)
end
+ after do
+ Rails.application.env_config['omniauth.auth'] = @original_env_config_omniauth_auth
+ end
+
context 'when the user is on the last sign in attempt' do
let(:extern_uid) { 'my-uid' }
diff --git a/spec/controllers/projects/avatars_controller_spec.rb b/spec/controllers/projects/avatars_controller_spec.rb
index de1b9dc0bf3..d463619ad0b 100644
--- a/spec/controllers/projects/avatars_controller_spec.rb
+++ b/spec/controllers/projects/avatars_controller_spec.rb
@@ -39,7 +39,7 @@ describe Projects::AvatarsController do
end
context 'when the avatar is stored in lfs' do
- it_behaves_like 'repository lfs file load' do
+ it_behaves_like 'a controller that can serve LFS files' do
let(:filename) { 'lfs_object.iso' }
let(:filepath) { "files/lfs/#{filename}" }
end
diff --git a/spec/controllers/projects/ci/lints_controller_spec.rb b/spec/controllers/projects/ci/lints_controller_spec.rb
index 323a32575af..cc6ac83ca38 100644
--- a/spec/controllers/projects/ci/lints_controller_spec.rb
+++ b/spec/controllers/projects/ci/lints_controller_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe Projects::Ci::LintsController do
+ include StubRequests
+
let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
@@ -70,7 +72,7 @@ describe Projects::Ci::LintsController do
context 'with a valid gitlab-ci.yml' do
before do
- WebMock.stub_request(:get, remote_file_path).to_return(body: remote_file_content)
+ stub_full_request(remote_file_path).to_return(body: remote_file_content)
project.add_developer(user)
post :create, params: { namespace_id: project.namespace, project_id: project, content: content }
diff --git a/spec/controllers/projects/clusters/applications_controller_spec.rb b/spec/controllers/projects/clusters/applications_controller_spec.rb
index cd1a01f8acc..70b34f071c8 100644
--- a/spec/controllers/projects/clusters/applications_controller_spec.rb
+++ b/spec/controllers/projects/clusters/applications_controller_spec.rb
@@ -145,4 +145,66 @@ describe Projects::Clusters::ApplicationsController do
it_behaves_like 'a secure endpoint'
end
end
+
+ describe 'DELETE destroy' do
+ subject do
+ delete :destroy, params: params.merge(namespace_id: project.namespace, project_id: project)
+ end
+
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.project }
+ let!(:application) { create(:clusters_applications_prometheus, :installed, cluster: cluster) }
+ let(:application_name) { application.name }
+ let(:params) { { application: application_name, id: cluster.id } }
+ let(:worker_class) { Clusters::Applications::UninstallWorker }
+
+ describe 'functionality' do
+ let(:user) { create(:user) }
+
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+ end
+
+ context "when cluster and app exists" do
+ it "schedules an application update" do
+ expect(worker_class).to receive(:perform_async).with(application.name, application.id).once
+
+ is_expected.to have_http_status(:no_content)
+
+ expect(cluster.application_prometheus).to be_scheduled
+ end
+ end
+
+ context 'when cluster do not exists' do
+ before do
+ cluster.destroy!
+ end
+
+ it { is_expected.to have_http_status(:not_found) }
+ end
+
+ context 'when application is unknown' do
+ let(:application_name) { 'unkwnown-app' }
+
+ it { is_expected.to have_http_status(:not_found) }
+ end
+
+ context 'when application is already scheduled' do
+ before do
+ application.make_scheduled!
+ end
+
+ it { is_expected.to have_http_status(:bad_request) }
+ end
+ end
+
+ describe 'security' do
+ before do
+ allow(worker_class).to receive(:perform_async)
+ end
+
+ it_behaves_like 'a secure endpoint'
+ end
+ end
end
diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb
index d94c18ddc02..8d37bd82d21 100644
--- a/spec/controllers/projects/clusters_controller_spec.rb
+++ b/spec/controllers/projects/clusters_controller_spec.rb
@@ -165,6 +165,7 @@ describe Projects::ClustersController do
{
cluster: {
name: 'new-cluster',
+ managed: '1',
provider_gcp_attributes: {
gcp_project_id: 'gcp-project-12345',
legacy_abac: legacy_abac_param
@@ -191,6 +192,7 @@ describe Projects::ClustersController do
expect(project.clusters.first).to be_gcp
expect(project.clusters.first).to be_kubernetes
expect(project.clusters.first.provider_gcp).to be_legacy_abac
+ expect(project.clusters.first.managed?).to be_truthy
end
context 'when legacy_abac param is false' do
@@ -251,6 +253,7 @@ describe Projects::ClustersController do
{
cluster: {
name: 'new-cluster',
+ managed: '1',
platform_kubernetes_attributes: {
api_url: 'http://my-url',
token: 'test',
@@ -302,9 +305,35 @@ describe Projects::ClustersController do
expect(response).to redirect_to(project_cluster_path(project, project.clusters.first))
- expect(project.clusters.first).to be_user
- expect(project.clusters.first).to be_kubernetes
- expect(project.clusters.first).to be_platform_kubernetes_rbac
+ cluster = project.clusters.first
+
+ expect(cluster).to be_user
+ expect(cluster).to be_kubernetes
+ expect(cluster).to be_platform_kubernetes_rbac
+ end
+ end
+
+ context 'when creates a user-managed cluster' do
+ let(:params) do
+ {
+ cluster: {
+ name: 'new-cluster',
+ managed: '0',
+ platform_kubernetes_attributes: {
+ api_url: 'http://my-url',
+ token: 'test',
+ namespace: 'aaa',
+ authorization_type: 'rbac'
+ }
+ }
+ }
+ end
+
+ it 'creates a new user-managed cluster' do
+ go
+ cluster = project.clusters.first
+
+ expect(cluster.managed?).to be_falsy
end
end
end
diff --git a/spec/controllers/projects/compare_controller_spec.rb b/spec/controllers/projects/compare_controller_spec.rb
index 1818809518d..92380a2bf09 100644
--- a/spec/controllers/projects/compare_controller_spec.rb
+++ b/spec/controllers/projects/compare_controller_spec.rb
@@ -82,7 +82,7 @@ describe Projects::CompareController do
show_request
expect(response).to be_success
- expect(assigns(:diffs).diff_files.to_a).to eq([])
+ expect(assigns(:diffs)).to eq([])
expect(assigns(:commits)).to eq([])
end
end
diff --git a/spec/controllers/projects/environments/prometheus_api_controller_spec.rb b/spec/controllers/projects/environments/prometheus_api_controller_spec.rb
index d232408b775..fdef9bc5638 100644
--- a/spec/controllers/projects/environments/prometheus_api_controller_spec.rb
+++ b/spec/controllers/projects/environments/prometheus_api_controller_spec.rb
@@ -85,12 +85,12 @@ describe Projects::Environments::PrometheusApiController do
context 'with nil result' do
let(:service_result) { nil }
- it 'returns 202 accepted' do
+ it 'returns 204 no_content' do
get :proxy, params: environment_params
expect(json_response['status']).to eq('processing')
expect(json_response['message']).to eq('Not ready yet. Try again later.')
- expect(response).to have_gitlab_http_status(:accepted)
+ expect(response).to have_gitlab_http_status(:no_content)
end
end
diff --git a/spec/controllers/projects/environments_controller_spec.rb b/spec/controllers/projects/environments_controller_spec.rb
index 75158f2e8e0..9699f2952f2 100644
--- a/spec/controllers/projects/environments_controller_spec.rb
+++ b/spec/controllers/projects/environments_controller_spec.rb
@@ -342,11 +342,9 @@ describe Projects::EnvironmentsController do
end
context 'when environment has no metrics' do
- before do
- expect(environment).to receive(:metrics).and_return(nil)
- end
-
it 'returns a metrics page' do
+ expect(environment).not_to receive(:metrics)
+
get :metrics, params: environment_params
expect(response).to be_ok
@@ -354,6 +352,8 @@ describe Projects::EnvironmentsController do
context 'when requesting metrics as JSON' do
it 'returns a metrics JSON document' do
+ expect(environment).to receive(:metrics).and_return(nil)
+
get :metrics, params: environment_params(format: :json)
expect(response).to have_gitlab_http_status(204)
@@ -383,6 +383,8 @@ describe Projects::EnvironmentsController do
end
describe 'GET #additional_metrics' do
+ let(:window_params) { { start: '1554702993.5398998', end: '1554717396.996232' } }
+
before do
allow(controller).to receive(:environment).and_return(environment)
end
@@ -394,7 +396,7 @@ describe Projects::EnvironmentsController do
context 'when requesting metrics as JSON' do
it 'returns a metrics JSON document' do
- additional_metrics
+ additional_metrics(window_params)
expect(response).to have_gitlab_http_status(204)
expect(json_response).to eq({})
@@ -414,49 +416,145 @@ describe Projects::EnvironmentsController do
end
it 'returns a metrics JSON document' do
- additional_metrics
+ additional_metrics(window_params)
expect(response).to be_ok
expect(json_response['success']).to be(true)
expect(json_response['data']).to eq({})
expect(json_response['last_update']).to eq(42)
end
+ end
- context 'when time params are provided' do
- it 'returns a metrics JSON document' do
- additional_metrics(start: '1554702993.5398998', end: '1554717396.996232')
-
- expect(response).to be_ok
- expect(json_response['success']).to be(true)
- expect(json_response['data']).to eq({})
- expect(json_response['last_update']).to eq(42)
- end
+ context 'when time params are missing' do
+ it 'raises an error when window params are missing' do
+ expect { additional_metrics }
+ .to raise_error(ActionController::ParameterMissing)
end
end
context 'when only one time param is provided' do
- context 'when :metrics_time_window feature flag is disabled' do
+ it 'raises an error when start is missing' do
+ expect { additional_metrics(end: '1552647300.651094') }
+ .to raise_error(ActionController::ParameterMissing)
+ end
+
+ it 'raises an error when end is missing' do
+ expect { additional_metrics(start: '1552647300.651094') }
+ .to raise_error(ActionController::ParameterMissing)
+ end
+ end
+ end
+
+ describe 'metrics_dashboard' do
+ context 'when prometheus endpoint is disabled' do
+ before do
+ stub_feature_flags(environment_metrics_use_prometheus_endpoint: false)
+ end
+
+ it 'responds with status code 403' do
+ get :metrics_dashboard, params: environment_params(format: :json)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ shared_examples_for '200 response' do |contains_all_dashboards: false|
+ let(:expected_keys) { %w(dashboard status) }
+
+ before do
+ expected_keys << 'all_dashboards' if contains_all_dashboards
+ end
+
+ it 'returns a json representation of the environment dashboard' do
+ get :metrics_dashboard, params: environment_params(dashboard_params)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response.keys).to contain_exactly(*expected_keys)
+ expect(json_response['dashboard']).to be_an_instance_of(Hash)
+ end
+ end
+
+ shared_examples_for 'error response' do |status_code, contains_all_dashboards: false|
+ let(:expected_keys) { %w(message status) }
+
+ before do
+ expected_keys << 'all_dashboards' if contains_all_dashboards
+ end
+
+ it 'returns an error response' do
+ get :metrics_dashboard, params: environment_params(dashboard_params)
+
+ expect(response).to have_gitlab_http_status(status_code)
+ expect(json_response.keys).to contain_exactly(*expected_keys)
+ end
+ end
+
+ shared_examples_for 'has all dashboards' do
+ it 'includes an index of all available dashboards' do
+ get :metrics_dashboard, params: environment_params(dashboard_params)
+
+ expect(json_response.keys).to include('all_dashboards')
+ expect(json_response['all_dashboards']).to be_an_instance_of(Array)
+ expect(json_response['all_dashboards']).to all( include('path', 'default') )
+ end
+ end
+
+ context 'when multiple dashboards is disabled' do
+ before do
+ stub_feature_flags(environment_metrics_show_multiple_dashboards: false)
+ end
+
+ let(:dashboard_params) { { format: :json } }
+
+ it_behaves_like '200 response'
+
+ context 'when the dashboard could not be provided' do
before do
- stub_feature_flags(metrics_time_window: false)
- expect(environment).to receive(:additional_metrics).with(no_args).and_return(nil)
+ allow(YAML).to receive(:safe_load).and_return({})
end
- it 'returns a time-window agnostic response' do
- additional_metrics(start: '1552647300.651094')
+ it_behaves_like 'error response', :unprocessable_entity
+ end
- expect(response).to have_gitlab_http_status(204)
- expect(json_response).to eq({})
- end
+ context 'when a dashboard param is specified' do
+ let(:dashboard_params) { { format: :json, dashboard: '.gitlab/dashboards/not_there_dashboard.yml' } }
+
+ it_behaves_like '200 response'
end
+ end
- it 'raises an error when start is missing' do
- expect { additional_metrics(start: '1552647300.651094') }
- .to raise_error(ActionController::ParameterMissing)
+ context 'when multiple dashboards is enabled' do
+ let(:dashboard_params) { { format: :json } }
+
+ it_behaves_like '200 response', contains_all_dashboards: true
+ it_behaves_like 'has all dashboards'
+
+ context 'when a dashboard could not be provided' do
+ before do
+ allow(YAML).to receive(:safe_load).and_return({})
+ end
+
+ it_behaves_like 'error response', :unprocessable_entity, contains_all_dashboards: true
+ it_behaves_like 'has all dashboards'
end
- it 'raises an error when end is missing' do
- expect { additional_metrics(start: '1552647300.651094') }
- .to raise_error(ActionController::ParameterMissing)
+ context 'when a dashboard param is specified' do
+ let(:dashboard_params) { { format: :json, dashboard: '.gitlab/dashboards/test.yml' } }
+
+ context 'when the dashboard is available' do
+ let(:dashboard_yml) { fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml') }
+ let(:dashboard_file) { { '.gitlab/dashboards/test.yml' => dashboard_yml } }
+ let(:project) { create(:project, :custom_repo, files: dashboard_file) }
+ let(:environment) { create(:environment, name: 'production', project: project) }
+
+ it_behaves_like '200 response', contains_all_dashboards: true
+ it_behaves_like 'has all dashboards'
+ end
+
+ context 'when the dashboard does not exist' do
+ it_behaves_like 'error response', :not_found, contains_all_dashboards: true
+ it_behaves_like 'has all dashboards'
+ end
end
end
end
diff --git a/spec/controllers/projects/graphs_controller_spec.rb b/spec/controllers/projects/graphs_controller_spec.rb
index d390e84c9b0..b5248c7f0c8 100644
--- a/spec/controllers/projects/graphs_controller_spec.rb
+++ b/spec/controllers/projects/graphs_controller_spec.rb
@@ -28,6 +28,21 @@ describe Projects::GraphsController do
end
describe 'charts' do
+ context 'with an anonymous user' do
+ let(:project) { create(:project, :repository, :public) }
+
+ before do
+ sign_out(user)
+ end
+
+ it 'renders charts with 200 status code' do
+ get(:charts, params: { namespace_id: project.namespace.path, project_id: project.path, id: 'master' })
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template(:charts)
+ end
+ end
+
context 'when languages were previously detected' do
let(:project) { create(:project, :repository, detected_repository_languages: true) }
let!(:repository_language) { create(:repository_language, project: project) }
diff --git a/spec/controllers/projects/imports_controller_spec.rb b/spec/controllers/projects/imports_controller_spec.rb
index 8d88ee7dfd6..bdc81efe3bc 100644
--- a/spec/controllers/projects/imports_controller_spec.rb
+++ b/spec/controllers/projects/imports_controller_spec.rb
@@ -122,4 +122,19 @@ describe Projects::ImportsController do
end
end
end
+
+ describe 'POST #create' do
+ let(:params) { { import_url: 'https://github.com/vim/vim.git', import_url_user: 'user', import_url_password: 'password' } }
+ let(:project) { create(:project) }
+
+ before do
+ allow(RepositoryImportWorker).to receive(:perform_async)
+
+ post :create, params: { project: params, namespace_id: project.namespace.to_param, project_id: project }
+ end
+
+ it 'sets import_url to the project' do
+ expect(project.reload.import_url).to eq('https://user:password@github.com/vim/vim.git')
+ end
+ end
end
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index 0c46b43f080..32607fc5f56 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -130,6 +130,37 @@ describe Projects::IssuesController do
end
end
+ context 'with relative_position sorting' do
+ let!(:issue_list) { create_list(:issue, 2, project: project) }
+
+ before do
+ sign_in(user)
+ project.add_developer(user)
+ allow(Kaminari.config).to receive(:default_per_page).and_return(1)
+ end
+
+ it 'overrides the number allowed on the page' do
+ get :index,
+ params: {
+ namespace_id: project.namespace.to_param,
+ project_id: project,
+ sort: 'relative_position'
+ }
+
+ expect(assigns(:issues).count).to eq 2
+ end
+
+ it 'allows the default number on the page' do
+ get :index,
+ params: {
+ namespace_id: project.namespace.to_param,
+ project_id: project
+ }
+
+ expect(assigns(:issues).count).to eq 1
+ end
+ end
+
context 'external authorization' do
before do
sign_in user
diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb
index bd30d4ee88b..490e9841492 100644
--- a/spec/controllers/projects/jobs_controller_spec.rb
+++ b/spec/controllers/projects/jobs_controller_spec.rb
@@ -101,7 +101,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
end
- describe 'GET show' do
+ describe 'GET show', :request_store do
let!(:job) { create(:ci_build, :failed, pipeline: pipeline) }
let!(:second_job) { create(:ci_build, :failed, pipeline: pipeline) }
let!(:third_job) { create(:ci_build, :failed) }
@@ -143,13 +143,24 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
project.add_developer(user)
sign_in(user)
- allow_any_instance_of(Ci::Build).to receive(:merge_request).and_return(merge_request)
+ allow_any_instance_of(Ci::Build)
+ .to receive(:merge_request)
+ .and_return(merge_request)
+ end
+
+ it 'does not serialize builds in exposed stages' do
+ get_show_json
- get_show(id: job.id, format: :json)
+ json_response.dig('pipeline', 'details', 'stages').tap do |stages|
+ expect(stages.map(&:keys).flatten)
+ .to eq %w[name title status path dropdown_path]
+ end
end
context 'when job failed' do
it 'exposes needed information' do
+ get_show_json
+
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('job/job_details')
expect(json_response['raw_path']).to match(%r{jobs/\d+/raw\z})
@@ -159,6 +170,10 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
context 'when job is running' do
+ before do
+ get_show_json
+ end
+
context 'job is cancelable' do
let(:job) { create(:ci_build, :running, pipeline: pipeline) }
@@ -181,6 +196,10 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
context 'when job has artifacts' do
+ before do
+ get_show_json
+ end
+
context 'with not expiry date' do
let(:job) { create(:ci_build, :success, :artifacts, pipeline: pipeline) }
@@ -212,6 +231,8 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
let(:job) { create(:ci_build, :success, :artifacts, pipeline: pipeline) }
it 'exposes empty state illustrations' do
+ get_show_json
+
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('job/job_details')
expect(json_response['status']['illustration']).to have_key('image')
@@ -224,6 +245,8 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
let(:job) { create(:ci_build, :success, pipeline: pipeline) }
it 'does not exposes the deployment information' do
+ get_show_json
+
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['deployment_status']).to be_nil
end
@@ -234,11 +257,20 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
let(:environment) { create(:environment, project: project, name: 'staging', state: :available) }
let(:job) { create(:ci_build, :running, environment: environment.name, pipeline: pipeline) }
+ before do
+ create(:deployment, :success, environment: environment, project: project)
+ end
+
it 'exposes the deployment information' do
+ get_show_json
+
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to match_schema('job/job_details')
- expect(json_response['deployment_status']["status"]).to eq 'creating'
- expect(json_response['deployment_status']["environment"]).not_to be_nil
+ expect(json_response.dig('deployment_status', 'status')).to eq 'creating'
+ expect(json_response.dig('deployment_status', 'environment')).not_to be_nil
+ expect(json_response.dig('deployment_status', 'environment', 'last_deployment')).not_to be_nil
+ expect(json_response.dig('deployment_status', 'environment', 'last_deployment'))
+ .not_to include('commit')
end
end
@@ -250,11 +282,11 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
before do
project.add_maintainer(user)
sign_in(user)
-
- get_show(id: job.id, format: :json)
end
it 'user can edit runner' do
+ get_show_json
+
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('job/job_details')
expect(json_response['runner']).to have_key('edit_path')
@@ -270,11 +302,11 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
before do
project.add_maintainer(user)
sign_in(user)
-
- get_show(id: job.id, format: :json)
end
it 'user can not edit runner' do
+ get_show_json
+
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('job/job_details')
expect(json_response['runner']).not_to have_key('edit_path')
@@ -289,11 +321,11 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
before do
project.add_maintainer(user)
sign_in(user)
-
- get_show(id: job.id, format: :json)
end
it 'user can not edit runner' do
+ get_show_json
+
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('job/job_details')
expect(json_response['runner']).not_to have_key('edit_path')
@@ -306,6 +338,8 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
let(:job) { create(:ci_build, :pending, pipeline: pipeline, runner: runner) }
it 'exposes needed information' do
+ get_show_json
+
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('job/job_details')
expect(json_response['runners']['online']).to be false
@@ -319,6 +353,8 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
let(:job) { create(:ci_build, :pending, pipeline: pipeline, runner: runner) }
it 'exposes needed information' do
+ get_show_json
+
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('job/job_details')
expect(json_response['runners']['online']).to be false
@@ -328,6 +364,10 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
context 'settings_path' do
+ before do
+ get_show_json
+ end
+
context 'when user is developer' do
it 'settings_path is not available' do
expect(response).to have_gitlab_http_status(:ok)
@@ -354,6 +394,8 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
context 'when no trace is available' do
it 'has_trace is false' do
+ get_show_json
+
expect(response).to match_response_schema('job/job_details')
expect(json_response['has_trace']).to be false
end
@@ -363,17 +405,21 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
let(:job) { create(:ci_build, :running, :trace_live, pipeline: pipeline) }
it "has_trace is true" do
+ get_show_json
+
expect(response).to match_response_schema('job/job_details')
expect(json_response['has_trace']).to be true
end
end
it 'exposes the stage the job belongs to' do
+ get_show_json
+
expect(json_response['stage']).to eq('test')
end
end
- context 'when requesting JSON job is triggered' do
+ context 'when requesting triggered job JSON' do
let!(:merge_request) { create(:merge_request, source_project: project) }
let(:trigger) { create(:ci_trigger, project: project) }
let(:trigger_request) { create(:ci_trigger_request, pipeline: pipeline, trigger: trigger) }
@@ -383,15 +429,15 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
project.add_developer(user)
sign_in(user)
- allow_any_instance_of(Ci::Build).to receive(:merge_request).and_return(merge_request)
+ allow_any_instance_of(Ci::Build)
+ .to receive(:merge_request)
+ .and_return(merge_request)
end
context 'with no variables' do
- before do
- get_show(id: job.id, format: :json)
- end
-
it 'exposes trigger information' do
+ get_show_json
+
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('job/job_details')
expect(json_response['trigger']['short_token']).to eq 'toke'
@@ -408,7 +454,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
before do
project.add_maintainer(user)
- get_show(id: job.id, format: :json)
+ get_show_json
end
it 'returns a job_detail' do
@@ -432,7 +478,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
context 'user is not a mantainer' do
before do
- get_show(id: job.id, format: :json)
+ get_show_json
end
it 'returns a job_detail' do
@@ -456,6 +502,11 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
end
+ def get_show_json
+ expect { get_show(id: job.id, format: :json) }
+ .not_to change { Gitlab::GitalyClient.get_request_count }
+ end
+
def get_show(**extra_params)
params = {
namespace_id: project.namespace.to_param,
@@ -790,8 +841,8 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
it 'erases artifacts' do
- expect(job.artifacts_file.exists?).to be_falsey
- expect(job.artifacts_metadata.exists?).to be_falsey
+ expect(job.artifacts_file.present?).to be_falsey
+ expect(job.artifacts_metadata.present?).to be_falsey
end
it 'erases trace' do
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index f4a18dcba51..34cbf0c8723 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -412,7 +412,7 @@ describe Projects::MergeRequestsController do
end
end
- context 'when the pipeline succeeds is passed' do
+ context 'when merge when pipeline succeeds option is passed' do
let!(:head_pipeline) do
create(:ci_empty_pipeline, project: project, sha: merge_request.diff_head_sha, ref: merge_request.source_branch, head_pipeline_of: merge_request)
end
@@ -429,8 +429,9 @@ describe Projects::MergeRequestsController do
it 'sets the MR to merge when the pipeline succeeds' do
service = double(:merge_when_pipeline_succeeds_service)
+ allow(service).to receive(:available_for?) { true }
- expect(MergeRequests::MergeWhenPipelineSucceedsService)
+ expect(AutoMerge::MergeWhenPipelineSucceedsService)
.to receive(:new).with(project, anything, anything)
.and_return(service)
expect(service).to receive(:execute).with(merge_request)
@@ -461,6 +462,30 @@ describe Projects::MergeRequestsController do
expect(json_response).to eq('status' => 'merge_when_pipeline_succeeds')
end
end
+
+ context 'when auto merge has not been enabled yet' do
+ it 'calls AutoMergeService#execute' do
+ expect_next_instance_of(AutoMergeService) do |service|
+ expect(service).to receive(:execute).with(merge_request, 'merge_when_pipeline_succeeds')
+ end
+
+ merge_when_pipeline_succeeds
+ end
+ end
+
+ context 'when auto merge has already been enabled' do
+ before do
+ merge_request.update!(auto_merge_enabled: true, merge_user: user)
+ end
+
+ it 'calls AutoMergeService#update' do
+ expect_next_instance_of(AutoMergeService) do |service|
+ expect(service).to receive(:update).with(merge_request)
+ end
+
+ merge_when_pipeline_succeeds
+ end
+ end
end
describe 'only_allow_merge_if_all_discussions_are_resolved? setting' do
@@ -713,9 +738,9 @@ describe Projects::MergeRequestsController do
end
end
- describe 'POST cancel_merge_when_pipeline_succeeds' do
+ describe 'POST cancel_auto_merge' do
subject do
- post :cancel_merge_when_pipeline_succeeds,
+ post :cancel_auto_merge,
params: {
format: :json,
namespace_id: merge_request.project.namespace.to_param,
@@ -725,14 +750,15 @@ describe Projects::MergeRequestsController do
xhr: true
end
- it 'calls MergeRequests::MergeWhenPipelineSucceedsService' do
- mwps_service = double
+ it 'calls AutoMergeService' do
+ auto_merge_service = double
- allow(MergeRequests::MergeWhenPipelineSucceedsService)
+ allow(AutoMergeService)
.to receive(:new)
- .and_return(mwps_service)
+ .and_return(auto_merge_service)
- expect(mwps_service).to receive(:cancel).with(merge_request)
+ allow(auto_merge_service).to receive(:available_strategies).with(merge_request)
+ expect(auto_merge_service).to receive(:cancel).with(merge_request)
subject
end
diff --git a/spec/controllers/projects/milestones_controller_spec.rb b/spec/controllers/projects/milestones_controller_spec.rb
index f8470a94f98..767cee7d54a 100644
--- a/spec/controllers/projects/milestones_controller_spec.rb
+++ b/spec/controllers/projects/milestones_controller_spec.rb
@@ -175,6 +175,40 @@ describe Projects::MilestonesController do
end
end
+ describe '#labels' do
+ render_views
+
+ context 'as json' do
+ let!(:guest) { create(:user, username: 'guest1') }
+ let!(:group) { create(:group, :public) }
+ let!(:project) { create(:project, :public, group: group) }
+ let!(:label) { create(:label, title: 'test_label_on_private_issue', project: project) }
+ let!(:confidential_issue) { create(:labeled_issue, confidential: true, project: project, milestone: milestone, labels: [label]) }
+
+ it 'does not render labels of private issues if user has no access' do
+ sign_in(guest)
+
+ get :labels, params: { namespace_id: group.id, project_id: project.id, id: milestone.iid }, format: :json
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response.content_type).to eq 'application/json'
+
+ expect(json_response['html']).not_to include(label.title)
+ end
+
+ it 'does render labels of private issues if user has access' do
+ sign_in(user)
+
+ get :labels, params: { namespace_id: group.id, project_id: project.id, id: milestone.iid }, format: :json
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response.content_type).to eq 'application/json'
+
+ expect(json_response['html']).to include(label.title)
+ end
+ end
+ end
+
context 'promotion succeeds' do
before do
group.add_developer(user)
diff --git a/spec/controllers/projects/pipeline_schedules_controller_spec.rb b/spec/controllers/projects/pipeline_schedules_controller_spec.rb
index eb8983a7633..850ef9c92fb 100644
--- a/spec/controllers/projects/pipeline_schedules_controller_spec.rb
+++ b/spec/controllers/projects/pipeline_schedules_controller_spec.rb
@@ -91,7 +91,7 @@ describe Projects::PipelineSchedulesController do
context 'when variables_attributes has one variable' do
let(:schedule) do
basic_param.merge({
- variables_attributes: [{ key: 'AAA', secret_value: 'AAA123' }]
+ variables_attributes: [{ key: 'AAA', secret_value: 'AAA123', variable_type: 'file' }]
})
end
@@ -105,6 +105,7 @@ describe Projects::PipelineSchedulesController do
Ci::PipelineScheduleVariable.last.tap do |v|
expect(v.key).to eq("AAA")
expect(v.value).to eq("AAA123")
+ expect(v.variable_type).to eq("file")
end
end
end
diff --git a/spec/controllers/projects/raw_controller_spec.rb b/spec/controllers/projects/raw_controller_spec.rb
index 3a89d8ce032..97acd47b4da 100644
--- a/spec/controllers/projects/raw_controller_spec.rb
+++ b/spec/controllers/projects/raw_controller_spec.rb
@@ -42,7 +42,7 @@ describe Projects::RawController do
end
end
- it_behaves_like 'repository lfs file load' do
+ it_behaves_like 'a controller that can serve LFS files' do
let(:filename) { 'lfs_object.iso' }
let(:filepath) { "be93687/files/lfs/#{filename}" }
end
diff --git a/spec/controllers/projects/serverless/functions_controller_spec.rb b/spec/controllers/projects/serverless/functions_controller_spec.rb
index 782f5f272d9..18c594acae0 100644
--- a/spec/controllers/projects/serverless/functions_controller_spec.rb
+++ b/spec/controllers/projects/serverless/functions_controller_spec.rb
@@ -8,9 +8,8 @@ describe Projects::Serverless::FunctionsController do
let(:user) { create(:user) }
let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:knative) { create(:clusters_applications_knative, :installed, cluster: cluster) }
let(:service) { cluster.platform_kubernetes }
- let(:project) { cluster.project}
+ let(:project) { cluster.project }
let(:namespace) do
create(:cluster_kubernetes_namespace,
@@ -30,17 +29,69 @@ describe Projects::Serverless::FunctionsController do
end
describe 'GET #index' do
- context 'empty cache' do
- it 'has no data' do
+ let(:expected_json) { { 'knative_installed' => knative_state, 'functions' => functions } }
+
+ context 'when cache is being read' do
+ let(:knative_state) { 'checking' }
+ let(:functions) { [] }
+
+ before do
get :index, params: params({ format: :json })
+ end
- expect(response).to have_gitlab_http_status(204)
+ it 'returns checking' do
+ expect(json_response).to eq expected_json
end
- it 'renders an html page' do
- get :index, params: params
+ it { expect(response).to have_gitlab_http_status(200) }
+ end
+
+ context 'when cache is ready' do
+ let(:knative_services_finder) { project.clusters.first.knative_services_finder(project) }
+ let(:knative_state) { true }
- expect(response).to have_gitlab_http_status(200)
+ before do
+ allow_any_instance_of(Clusters::Cluster)
+ .to receive(:knative_services_finder)
+ .and_return(knative_services_finder)
+ synchronous_reactive_cache(knative_services_finder)
+ stub_kubeclient_service_pods(
+ kube_response({ "kind" => "PodList", "items" => [] }),
+ namespace: namespace.namespace
+ )
+ end
+
+ context 'when no functions were found' do
+ let(:functions) { [] }
+
+ before do
+ stub_kubeclient_knative_services(
+ namespace: namespace.namespace,
+ response: kube_response({ "kind" => "ServiceList", "items" => [] })
+ )
+ get :index, params: params({ format: :json })
+ end
+
+ it 'returns checking' do
+ expect(json_response).to eq expected_json
+ end
+
+ it { expect(response).to have_gitlab_http_status(200) }
+ end
+
+ context 'when functions were found' do
+ let(:functions) { ["asdf"] }
+
+ before do
+ stub_kubeclient_knative_services(namespace: namespace.namespace)
+ get :index, params: params({ format: :json })
+ end
+
+ it 'returns functions' do
+ expect(json_response["functions"]).not_to be_empty
+ end
+
+ it { expect(response).to have_gitlab_http_status(200) }
end
end
end
@@ -56,11 +107,12 @@ describe Projects::Serverless::FunctionsController do
context 'valid data', :use_clean_rails_memory_store_caching do
before do
stub_kubeclient_service_pods
- stub_reactive_cache(knative,
+ stub_reactive_cache(cluster.knative_services_finder(project),
{
services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"],
pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"]
- })
+ },
+ *cluster.knative_services_finder(project).cache_args)
end
it 'has a valid function name' do
@@ -88,11 +140,12 @@ describe Projects::Serverless::FunctionsController do
describe 'GET #index with data', :use_clean_rails_memory_store_caching do
before do
stub_kubeclient_service_pods
- stub_reactive_cache(knative,
+ stub_reactive_cache(cluster.knative_services_finder(project),
{
services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"],
pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"]
- })
+ },
+ *cluster.knative_services_finder(project).cache_args)
end
it 'has data' do
@@ -100,11 +153,16 @@ describe Projects::Serverless::FunctionsController do
expect(response).to have_gitlab_http_status(200)
- expect(json_response).to contain_exactly(
- a_hash_including(
- "name" => project.name,
- "url" => "http://#{project.name}.#{namespace.namespace}.example.com"
- )
+ expect(json_response).to match(
+ {
+ "knative_installed" => "checking",
+ "functions" => [
+ a_hash_including(
+ "name" => project.name,
+ "url" => "http://#{project.name}.#{namespace.namespace}.example.com"
+ )
+ ]
+ }
)
end
diff --git a/spec/controllers/projects/settings/ci_cd_controller_spec.rb b/spec/controllers/projects/settings/ci_cd_controller_spec.rb
index fc9a0adeed2..5bfbcf6eeb5 100644
--- a/spec/controllers/projects/settings/ci_cd_controller_spec.rb
+++ b/spec/controllers/projects/settings/ci_cd_controller_spec.rb
@@ -109,7 +109,7 @@ describe Projects::Settings::CiCdController do
end
context 'when updating the auto_devops settings' do
- let(:params) { { auto_devops_attributes: { enabled: '', domain: 'mepmep.md' } } }
+ let(:params) { { auto_devops_attributes: { enabled: '' } } }
context 'following the instance default' do
let(:params) { { auto_devops_attributes: { enabled: '' } } }
@@ -191,6 +191,30 @@ describe Projects::Settings::CiCdController do
expect(project.build_timeout).to eq(5400)
end
end
+
+ context 'when build_timeout_human_readable is invalid' do
+ let(:params) { { build_timeout_human_readable: '5m' } }
+
+ it 'set specified timeout' do
+ expect(subject).to set_flash[:alert]
+ expect(response).to redirect_to(namespace_project_settings_ci_cd_path)
+ end
+ end
+
+ context 'when default_git_depth is not specified' do
+ let(:params) { { ci_cd_settings_attributes: { default_git_depth: 10 } } }
+
+ before do
+ project.ci_cd_settings.update!(default_git_depth: nil)
+ end
+
+ it 'set specified git depth' do
+ subject
+
+ project.reload
+ expect(project.ci_default_git_depth).to eq(10)
+ end
+ end
end
end
end
diff --git a/spec/controllers/projects/settings/operations_controller_spec.rb b/spec/controllers/projects/settings/operations_controller_spec.rb
index 02a392f23c2..aa9cd41ed19 100644
--- a/spec/controllers/projects/settings/operations_controller_spec.rb
+++ b/spec/controllers/projects/settings/operations_controller_spec.rb
@@ -11,15 +11,118 @@ describe Projects::Settings::OperationsController do
project.add_maintainer(user)
end
- context 'error tracking' do
- describe 'GET #show' do
- it 'renders show template' do
+ shared_examples 'PATCHable' do
+ let(:operations_update_service) { instance_double(::Projects::Operations::UpdateService) }
+ let(:operations_url) { project_settings_operations_url(project) }
+
+ let(:permitted_params) do
+ ActionController::Parameters.new(params).permit!
+ end
+
+ context 'format json' do
+ context 'when update succeeds' do
+ it 'returns success status' do
+ stub_operations_update_service_returning(status: :success)
+
+ patch :update,
+ params: project_params(project, params),
+ format: :json
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq('status' => 'success')
+ expect(flash[:notice]).to eq('Your changes have been saved')
+ end
+ end
+
+ context 'when update fails' do
+ it 'returns error' do
+ stub_operations_update_service_returning(
+ status: :error,
+ message: 'error message'
+ )
+
+ patch :update,
+ params: project_params(project, params),
+ format: :json
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['message']).to eq('error message')
+ end
+ end
+ end
+
+ private
+
+ def stub_operations_update_service_returning(return_value = {})
+ expect(::Projects::Operations::UpdateService)
+ .to receive(:new).with(project, user, permitted_params)
+ .and_return(operations_update_service)
+ expect(operations_update_service).to receive(:execute)
+ .and_return(return_value)
+ end
+ end
+
+ describe 'GET #show' do
+ it 'renders show template' do
+ get :show, params: project_params(project)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template(:show)
+ end
+
+ context 'with insufficient permissions' do
+ before do
+ project.add_reporter(user)
+ end
+
+ it 'renders 404' do
+ get :show, params: project_params(project)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'as an anonymous user' do
+ before do
+ sign_out(user)
+ end
+
+ it 'redirects to signup page' do
get :show, params: project_params(project)
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to render_template(:show)
+ expect(response).to redirect_to(new_user_session_path)
+ end
+ end
+ end
+
+ describe 'PATCH #update' do
+ context 'with insufficient permissions' do
+ before do
+ project.add_reporter(user)
+ end
+
+ it 'renders 404' do
+ patch :update, params: project_params(project)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'as an anonymous user' do
+ before do
+ sign_out(user)
+ end
+
+ it 'redirects to signup page' do
+ patch :update, params: project_params(project)
+
+ expect(response).to redirect_to(new_user_session_path)
end
+ end
+ end
+ context 'error tracking' do
+ describe 'GET #show' do
context 'with existing setting' do
let!(:error_tracking_setting) do
create(:project_error_tracking_setting, project: project)
@@ -40,37 +143,10 @@ describe Projects::Settings::OperationsController do
expect(controller.helpers.error_tracking_setting).to be_new_record
end
end
-
- context 'with insufficient permissions' do
- before do
- project.add_reporter(user)
- end
-
- it 'renders 404' do
- get :show, params: project_params(project)
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'as an anonymous user' do
- before do
- sign_out(user)
- end
-
- it 'redirects to signup page' do
- get :show, params: project_params(project)
-
- expect(response).to redirect_to(new_user_session_path)
- end
- end
end
describe 'PATCH #update' do
- let(:operations_update_service) { spy(:operations_update_service) }
- let(:operations_url) { project_settings_operations_url(project) }
-
- let(:error_tracking_params) do
+ let(:params) do
{
error_tracking_setting_attributes: {
enabled: '1',
@@ -86,79 +162,21 @@ describe Projects::Settings::OperationsController do
}
end
- let(:error_tracking_permitted) do
- ActionController::Parameters.new(error_tracking_params).permit!
- end
-
- context 'format json' do
- context 'when update succeeds' do
- before do
- stub_operations_update_service_returning(status: :success)
- end
-
- it 'returns success status' do
- patch :update,
- params: project_params(project, error_tracking_params),
- format: :json
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response).to eq('status' => 'success')
- expect(flash[:notice]).to eq('Your changes have been saved')
- end
- end
-
- context 'when update fails' do
- before do
- stub_operations_update_service_returning(
- status: :error,
- message: 'error message'
- )
- end
-
- it 'returns error' do
- patch :update,
- params: project_params(project, error_tracking_params),
- format: :json
-
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['message']).not_to be_nil
- end
- end
- end
-
- context 'with insufficient permissions' do
- before do
- project.add_reporter(user)
- end
-
- it 'renders 404' do
- patch :update, params: project_params(project)
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'as an anonymous user' do
- before do
- sign_out(user)
- end
-
- it 'redirects to signup page' do
- patch :update, params: project_params(project)
-
- expect(response).to redirect_to(new_user_session_path)
- end
- end
+ it_behaves_like 'PATCHable'
end
+ end
- private
+ context 'metrics dashboard setting' do
+ describe 'PATCH #update' do
+ let(:params) do
+ {
+ metrics_setting_attributes: {
+ external_dashboard_url: 'https://gitlab.com'
+ }
+ }
+ end
- def stub_operations_update_service_returning(return_value = {})
- expect(::Projects::Operations::UpdateService)
- .to receive(:new).with(project, user, error_tracking_permitted)
- .and_return(operations_update_service)
- expect(operations_update_service).to receive(:execute)
- .and_return(return_value)
+ it_behaves_like 'PATCHable'
end
end
diff --git a/spec/controllers/projects/stages_controller_spec.rb b/spec/controllers/projects/stages_controller_spec.rb
new file mode 100644
index 00000000000..a91e3523fd7
--- /dev/null
+++ b/spec/controllers/projects/stages_controller_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Projects::StagesController do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+
+ before do
+ sign_in(user)
+ end
+
+ describe 'POST #play_manual.json' do
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:stage_name) { 'test' }
+
+ before do
+ create_manual_build(pipeline, 'test', 'rspec 1/2')
+ create_manual_build(pipeline, 'test', 'rspec 2/2')
+
+ pipeline.reload
+ end
+
+ context 'when user does not have access' do
+ it 'returns not authorized' do
+ play_manual_stage!
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'when user has access' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ context 'when the stage does not exists' do
+ let(:stage_name) { 'deploy' }
+
+ it 'fails to play all manual' do
+ play_manual_stage!
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when the stage exists' do
+ it 'starts all manual jobs' do
+ expect(pipeline.builds.manual.count).to eq(2)
+
+ play_manual_stage!
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(pipeline.builds.manual.count).to eq(0)
+ end
+ end
+ end
+
+ def play_manual_stage!
+ post :play_manual, params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: pipeline.id,
+ stage_name: stage_name
+ }, format: :json
+ end
+
+ def create_manual_build(pipeline, stage, name)
+ create(:ci_build, :manual, pipeline: pipeline, stage: stage, name: name)
+ end
+ end
+end
diff --git a/spec/controllers/projects/wikis_controller_spec.rb b/spec/controllers/projects/wikis_controller_spec.rb
index e0a6fc52ee9..f2e0b5e5c1d 100644
--- a/spec/controllers/projects/wikis_controller_spec.rb
+++ b/spec/controllers/projects/wikis_controller_spec.rb
@@ -19,6 +19,18 @@ describe Projects::WikisController do
destroy_page(wiki_title)
end
+ describe 'GET #pages' do
+ subject { get :pages, params: { namespace_id: project.namespace, project_id: project, id: wiki_title } }
+
+ it 'does not load the pages content' do
+ expect(controller).to receive(:load_wiki).and_return(project_wiki)
+
+ expect(project_wiki).to receive(:list_pages).twice.and_call_original
+
+ subject
+ end
+ end
+
describe 'GET #show' do
render_views
@@ -28,9 +40,9 @@ describe Projects::WikisController do
expect(controller).to receive(:load_wiki).and_return(project_wiki)
# empty? call
- expect(project_wiki).to receive(:pages).with(limit: 1).and_call_original
+ expect(project_wiki).to receive(:list_pages).with(limit: 1).and_call_original
# Sidebar entries
- expect(project_wiki).to receive(:pages).with(limit: 15).and_call_original
+ expect(project_wiki).to receive(:list_pages).with(limit: 15).and_call_original
subject
@@ -104,7 +116,7 @@ describe Projects::WikisController do
subject
- expect(response).to redirect_to(project_wiki_path(project, project_wiki.pages.first))
+ expect(response).to redirect_to(project_wiki_path(project, project_wiki.list_pages.first))
end
end
@@ -138,7 +150,7 @@ describe Projects::WikisController do
allow(controller).to receive(:valid_encoding?).and_return(false)
subject
- expect(response).to redirect_to(project_wiki_path(project, project_wiki.pages.first))
+ expect(response).to redirect_to(project_wiki_path(project, project_wiki.list_pages.first))
end
end
@@ -148,7 +160,7 @@ describe Projects::WikisController do
it 'updates the page' do
subject
- wiki_page = project_wiki.pages.first
+ wiki_page = project_wiki.list_pages(load_content: true).first
expect(wiki_page.title).to eq new_title
expect(wiki_page.content).to eq new_content
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index 7f1bbebd128..8d2412f97ef 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -292,6 +292,18 @@ describe ProjectsController do
end
describe 'GET edit' do
+ it 'allows an admin user to access the page' do
+ sign_in(create(:user, :admin))
+
+ get :edit,
+ params: {
+ namespace_id: project.namespace.path,
+ id: project.path
+ }
+
+ expect(response).to have_gitlab_http_status(200)
+ end
+
it 'sets the badge API endpoint' do
sign_in(user)
project.add_maintainer(user)
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index 088c515c3a6..9a598790ff2 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -46,13 +46,17 @@ describe RegistrationsController do
end
context 'when reCAPTCHA is enabled' do
+ def fail_recaptcha
+ # Without this, `verify_recaptcha` arbitrarily returns true in test env
+ Recaptcha.configuration.skip_verify_env.delete('test')
+ end
+
before do
stub_application_setting(recaptcha_enabled: true)
end
it 'displays an error when the reCAPTCHA is not solved' do
- # Without this, `verify_recaptcha` arbitrarily returns true in test env
- Recaptcha.configuration.skip_verify_env.delete('test')
+ fail_recaptcha
post(:create, params: user_params)
@@ -70,6 +74,17 @@ describe RegistrationsController do
expect(flash[:notice]).to include 'Welcome! You have signed up successfully.'
end
+
+ it 'does not require reCAPTCHA if disabled by feature flag' do
+ stub_feature_flags(registrations_recaptcha: false)
+ fail_recaptcha
+
+ post(:create, params: user_params)
+
+ expect(controller).not_to receive(:verify_recaptcha)
+ expect(flash[:alert]).to be_nil
+ expect(flash[:notice]).to include 'Welcome! You have signed up successfully.'
+ end
end
context 'when terms are enforced' do
diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb
index 9c60f0fcd4d..4634d1d4bb3 100644
--- a/spec/controllers/search_controller_spec.rb
+++ b/spec/controllers/search_controller_spec.rb
@@ -11,6 +11,30 @@ describe SearchController do
sign_in(user)
end
+ context 'uses the right partials depending on scope' do
+ using RSpec::Parameterized::TableSyntax
+ render_views
+
+ set(:project) { create(:project, :public, :repository, :wiki_repo) }
+
+ subject { get(:show, params: { project_id: project.id, scope: scope, search: 'merge' }) }
+
+ where(:partial, :scope) do
+ '_blob' | :blobs
+ '_wiki_blob' | :wiki_blobs
+ '_commit' | :commits
+ end
+
+ with_them do
+ it do
+ project_wiki = create(:project_wiki, project: project, user: user)
+ create(:wiki_page, wiki: project_wiki, attrs: { title: 'merge', content: 'merge' })
+
+ expect(subject).to render_template("search/results/#{partial}")
+ end
+ end
+ end
+
it 'finds issue comments' do
project = create(:project, :public)
note = create(:note_on_issue, project: project)
diff --git a/spec/controllers/sent_notifications_controller_spec.rb b/spec/controllers/sent_notifications_controller_spec.rb
index 2b9df71aa3a..89857a9d21b 100644
--- a/spec/controllers/sent_notifications_controller_spec.rb
+++ b/spec/controllers/sent_notifications_controller_spec.rb
@@ -4,15 +4,31 @@ require 'rails_helper'
describe SentNotificationsController do
let(:user) { create(:user) }
- let(:project) { create(:project) }
- let(:sent_notification) { create(:sent_notification, project: project, noteable: issue, recipient: user) }
+ let(:project) { create(:project, :public) }
+ let(:private_project) { create(:project, :private) }
+ let(:sent_notification) { create(:sent_notification, project: target_project, noteable: noteable, recipient: user) }
let(:issue) do
- create(:issue, project: project, author: user) do |issue|
- issue.subscriptions.create(user: user, project: project, subscribed: true)
+ create(:issue, project: target_project) do |issue|
+ issue.subscriptions.create(user: user, project: target_project, subscribed: true)
end
end
+ let(:confidential_issue) do
+ create(:issue, project: target_project, confidential: true) do |issue|
+ issue.subscriptions.create(user: user, project: target_project, subscribed: true)
+ end
+ end
+
+ let(:merge_request) do
+ create(:merge_request, source_project: target_project, target_project: target_project) do |mr|
+ mr.subscriptions.create(user: user, project: target_project, subscribed: true)
+ end
+ end
+
+ let(:noteable) { issue }
+ let(:target_project) { project }
+
describe 'GET unsubscribe' do
context 'when the user is not logged in' do
context 'when the force param is passed' do
@@ -34,20 +50,93 @@ describe SentNotificationsController do
end
context 'when the force param is not passed' do
+ render_views
+
before do
get(:unsubscribe, params: { id: sent_notification.reply_key })
end
- it 'does not unsubscribe the user' do
- expect(issue.subscribed?(user, project)).to be_truthy
+ shared_examples 'unsubscribing as anonymous' do
+ it 'does not unsubscribe the user' do
+ expect(noteable.subscribed?(user, target_project)).to be_truthy
+ end
+
+ it 'does not set the flash message' do
+ expect(controller).not_to set_flash[:notice]
+ end
+
+ it 'renders unsubscribe page' do
+ expect(response.status).to eq(200)
+ expect(response).to render_template :unsubscribe
+ end
end
- it 'does not set the flash message' do
- expect(controller).not_to set_flash[:notice]
+ context 'when project is public' do
+ context 'when unsubscribing from issue' do
+ let(:noteable) { issue }
+
+ it 'shows issue title' do
+ expect(response.body).to include(issue.title)
+ end
+
+ it_behaves_like 'unsubscribing as anonymous'
+ end
+
+ context 'when unsubscribing from confidential issue' do
+ let(:noteable) { confidential_issue }
+
+ it 'does not show issue title' do
+ expect(response.body).not_to include(confidential_issue.title)
+ expect(response.body).to include(confidential_issue.to_reference)
+ end
+
+ it_behaves_like 'unsubscribing as anonymous'
+ end
+
+ context 'when unsubscribing from merge request' do
+ let(:noteable) { merge_request }
+
+ it 'shows merge request title' do
+ expect(response.body).to include(merge_request.title)
+ end
+
+ it_behaves_like 'unsubscribing as anonymous'
+ end
end
- it 'redirects to the login page' do
- expect(response).to render_template :unsubscribe
+ context 'when project is not public' do
+ let(:target_project) { private_project }
+
+ context 'when unsubscribing from issue' do
+ let(:noteable) { issue }
+
+ it 'shows issue title' do
+ expect(response.body).not_to include(issue.title)
+ end
+
+ it_behaves_like 'unsubscribing as anonymous'
+ end
+
+ context 'when unsubscribing from confidential issue' do
+ let(:noteable) { confidential_issue }
+
+ it 'does not show issue title' do
+ expect(response.body).not_to include(confidential_issue.title)
+ expect(response.body).to include(confidential_issue.to_reference)
+ end
+
+ it_behaves_like 'unsubscribing as anonymous'
+ end
+
+ context 'when unsubscribing from merge request' do
+ let(:noteable) { merge_request }
+
+ it 'shows merge request title' do
+ expect(response.body).not_to include(merge_request.title)
+ end
+
+ it_behaves_like 'unsubscribing as anonymous'
+ end
end
end
end
diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb
index 6bcff7f975c..9c4ddce5409 100644
--- a/spec/controllers/sessions_controller_spec.rb
+++ b/spec/controllers/sessions_controller_spec.rb
@@ -58,7 +58,26 @@ describe SessionsController do
it 'authenticates user correctly' do
post(:create, params: { user: user_params })
- expect(subject.current_user). to eq user
+ expect(subject.current_user).to eq user
+ end
+
+ context 'with password authentication disabled' do
+ before do
+ stub_application_setting(password_authentication_enabled_for_web: false)
+ end
+
+ it 'does not sign in the user' do
+ post(:create, params: { user: user_params })
+
+ expect(@request.env['warden']).not_to be_authenticated
+ expect(subject.current_user).to be_nil
+ end
+
+ it 'returns status 403' do
+ post(:create, params: { user: user_params })
+
+ expect(response.status).to eq 403
+ end
end
it 'creates an audit log record' do
@@ -153,6 +172,19 @@ describe SessionsController do
end
end
+ context 'with password authentication disabled' do
+ before do
+ stub_application_setting(password_authentication_enabled_for_web: false)
+ end
+
+ it 'allows 2FA stage of non-password login' do
+ authenticate_2fa(otp_attempt: user.current_otp)
+
+ expect(@request.env['warden']).to be_authenticated
+ expect(subject.current_user).to eq user
+ end
+ end
+
##
# See #14900 issue
#
diff --git a/spec/db/importers/common_metrics_importer_spec.rb b/spec/db/importers/common_metrics_importer_spec.rb
index 6133b17ac61..a717c8cd04d 100644
--- a/spec/db/importers/common_metrics_importer_spec.rb
+++ b/spec/db/importers/common_metrics_importer_spec.rb
@@ -23,10 +23,10 @@ describe Importers::CommonMetricsImporter do
subject { described_class.new }
context "does import common_metrics.yml" do
- let(:groups) { subject.content }
- let(:metrics) { groups.map { |group| group['metrics'] }.flatten }
- let(:queries) { metrics.map { |group| group['queries'] }.flatten }
- let(:query_ids) { queries.map { |query| query['id'] } }
+ let(:groups) { subject.content['panel_groups'] }
+ let(:panels) { groups.map { |group| group['panels'] }.flatten }
+ let(:metrics) { panels.map { |group| group['metrics'] }.flatten }
+ let(:metric_ids) { metrics.map { |metric| metric['id'] } }
before do
subject.execute
@@ -36,20 +36,20 @@ describe Importers::CommonMetricsImporter do
expect(PrometheusMetric.common.group(:group).count.count).to eq(groups.count)
end
- it "has the same amount of metrics" do
- expect(PrometheusMetric.common.group(:group, :title).count.count).to eq(metrics.count)
+ it "has the same amount of panels" do
+ expect(PrometheusMetric.common.group(:group, :title).count.count).to eq(panels.count)
end
- it "has the same amount of queries" do
- expect(PrometheusMetric.common.count).to eq(queries.count)
+ it "has the same amount of metrics" do
+ expect(PrometheusMetric.common.count).to eq(metrics.count)
end
it "does not have duplicate IDs" do
- expect(query_ids).to eq(query_ids.uniq)
+ expect(metric_ids).to eq(metric_ids.uniq)
end
it "imports all IDs" do
- expect(PrometheusMetric.common.pluck(:identifier)).to contain_exactly(*query_ids)
+ expect(PrometheusMetric.common.pluck(:identifier)).to contain_exactly(*metric_ids)
end
end
@@ -65,24 +65,26 @@ describe Importers::CommonMetricsImporter do
context 'does import properly all fields' do
let(:query_identifier) { 'response-metric' }
- let(:group) do
+ let(:dashboard) do
{
- group: 'Response metrics (NGINX Ingress)',
- metrics: [{
- title: "Throughput",
- y_label: "Requests / Sec",
- queries: [{
- id: query_identifier,
- query_range: 'my-query',
- unit: 'my-unit',
- label: 'status code'
+ panel_groups: [{
+ group: 'Response metrics (NGINX Ingress)',
+ panels: [{
+ title: "Throughput",
+ y_label: "Requests / Sec",
+ metrics: [{
+ id: query_identifier,
+ query_range: 'my-query',
+ unit: 'my-unit',
+ label: 'status code'
+ }]
}]
}]
}
end
before do
- expect(subject).to receive(:content) { [group.deep_stringify_keys] }
+ expect(subject).to receive(:content) { dashboard.deep_stringify_keys }
end
shared_examples 'stores metric' do
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index f8c494c159e..a473136b57b 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -248,17 +248,6 @@ FactoryBot.define do
runner factory: :ci_runner
end
- trait :legacy_artifacts do
- after(:create) do |build, _|
- build.update!(
- legacy_artifacts_file: fixture_file_upload(
- Rails.root.join('spec/fixtures/ci_build_artifacts.zip'), 'application/zip'),
- legacy_artifacts_metadata: fixture_file_upload(
- Rails.root.join('spec/fixtures/ci_build_artifacts_metadata.gz'), 'application/x-gzip')
- )
- end
- end
-
trait :artifacts do
after(:create) do |build|
create(:ci_job_artifact, :archive, job: build, expire_at: build.artifacts_expire_at)
diff --git a/spec/factories/ci/job_artifacts.rb b/spec/factories/ci/job_artifacts.rb
index 2c76c22ba69..542fa9775cd 100644
--- a/spec/factories/ci/job_artifacts.rb
+++ b/spec/factories/ci/job_artifacts.rb
@@ -45,9 +45,12 @@ FactoryBot.define do
file_type :archive
file_format :zip
- after(:build) do |artifact, _|
- artifact.file = fixture_file_upload(
- Rails.root.join('spec/fixtures/ci_build_artifacts.zip'), 'application/zip')
+ transient do
+ file { fixture_file_upload(Rails.root.join('spec/fixtures/ci_build_artifacts.zip'), 'application/zip') }
+ end
+
+ after(:build) do |artifact, evaluator|
+ artifact.file = evaluator.file
end
end
@@ -61,9 +64,12 @@ FactoryBot.define do
file_type :metadata
file_format :gzip
- after(:build) do |artifact, _|
- artifact.file = fixture_file_upload(
- Rails.root.join('spec/fixtures/ci_build_artifacts_metadata.gz'), 'application/x-gzip')
+ transient do
+ file { fixture_file_upload(Rails.root.join('spec/fixtures/ci_build_artifacts_metadata.gz'), 'application/x-gzip') }
+ end
+
+ after(:build) do |artifact, evaluator|
+ artifact.file = evaluator.file
end
end
diff --git a/spec/factories/ci/pipeline_schedule.rb b/spec/factories/ci/pipeline_schedule.rb
index b2b79807429..4b83ba2ac1b 100644
--- a/spec/factories/ci/pipeline_schedule.rb
+++ b/spec/factories/ci/pipeline_schedule.rb
@@ -7,6 +7,16 @@ FactoryBot.define do
description "pipeline schedule"
project
+ trait :every_minute do
+ cron '*/1 * * * *'
+ cron_timezone Gitlab::Ci::CronParser::VALID_SYNTAX_SAMPLE_TIME_ZONE
+ end
+
+ trait :hourly do
+ cron '* */1 * * *'
+ cron_timezone Gitlab::Ci::CronParser::VALID_SYNTAX_SAMPLE_TIME_ZONE
+ end
+
trait :nightly do
cron '0 1 * * *'
cron_timezone Gitlab::Ci::CronParser::VALID_SYNTAX_SAMPLE_TIME_ZONE
diff --git a/spec/factories/ci/pipeline_schedule_variables.rb b/spec/factories/ci/pipeline_schedule_variables.rb
index 8d29118e310..c85b97fbfc7 100644
--- a/spec/factories/ci/pipeline_schedule_variables.rb
+++ b/spec/factories/ci/pipeline_schedule_variables.rb
@@ -2,6 +2,7 @@ FactoryBot.define do
factory :ci_pipeline_schedule_variable, class: Ci::PipelineScheduleVariable do
sequence(:key) { |n| "VARIABLE_#{n}" }
value 'VARIABLE_VALUE'
+ variable_type 'env_var'
pipeline_schedule factory: :ci_pipeline_schedule
end
diff --git a/spec/factories/clusters/applications/helm.rb b/spec/factories/clusters/applications/helm.rb
index fe56ac5b71d..d78f01828d7 100644
--- a/spec/factories/clusters/applications/helm.rb
+++ b/spec/factories/clusters/applications/helm.rb
@@ -6,6 +6,11 @@ FactoryBot.define do
status(-2)
end
+ trait :errored do
+ status(-1)
+ status_reason 'something went wrong'
+ end
+
trait :installable do
status 0
end
@@ -30,17 +35,21 @@ FactoryBot.define do
status 5
end
- trait :errored do
- status(-1)
+ trait :update_errored do
+ status(6)
status_reason 'something went wrong'
end
- trait :update_errored do
- status(6)
+ trait :uninstalling do
+ status 7
+ end
+
+ trait :uninstall_errored do
+ status(8)
status_reason 'something went wrong'
end
- trait :timeouted do
+ trait :timed_out do
installing
updated_at { ClusterWaitForAppInstallationWorker::TIMEOUT.ago }
end
diff --git a/spec/factories/clusters/clusters.rb b/spec/factories/clusters/clusters.rb
index 97405ec7c58..6eb0194b710 100644
--- a/spec/factories/clusters/clusters.rb
+++ b/spec/factories/clusters/clusters.rb
@@ -65,7 +65,7 @@ FactoryBot.define do
domain 'example.com'
end
- trait :user_managed do
+ trait :not_managed do
managed false
end
end
diff --git a/spec/factories/deployments.rb b/spec/factories/deployments.rb
index 011c98599a3..db438ad32d3 100644
--- a/spec/factories/deployments.rb
+++ b/spec/factories/deployments.rb
@@ -1,6 +1,6 @@
FactoryBot.define do
factory :deployment, class: Deployment do
- sha '97de212e80737a608d939f648d959671fb0a0142'
+ sha 'b83d6e391c22777fca1ed3012fce84f633d7fed0'
ref 'master'
tag false
user nil
diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb
index abf0e6bccb7..0b6a43b13a9 100644
--- a/spec/factories/merge_requests.rb
+++ b/spec/factories/merge_requests.rb
@@ -95,7 +95,8 @@ FactoryBot.define do
end
trait :merge_when_pipeline_succeeds do
- merge_when_pipeline_succeeds true
+ auto_merge_enabled true
+ auto_merge_strategy AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS
merge_user { author }
end
@@ -119,7 +120,7 @@ FactoryBot.define do
trait :with_legacy_detached_merge_request_pipeline do
after(:create) do |merge_request|
- merge_request.merge_request_pipelines << create(:ci_pipeline,
+ merge_request.pipelines_for_merge_request << create(:ci_pipeline,
source: :merge_request_event,
merge_request: merge_request,
project: merge_request.source_project,
@@ -130,7 +131,7 @@ FactoryBot.define do
trait :with_detached_merge_request_pipeline do
after(:create) do |merge_request|
- merge_request.merge_request_pipelines << create(:ci_pipeline,
+ merge_request.pipelines_for_merge_request << create(:ci_pipeline,
source: :merge_request_event,
merge_request: merge_request,
project: merge_request.source_project,
@@ -147,7 +148,7 @@ FactoryBot.define do
end
after(:create) do |merge_request, evaluator|
- merge_request.merge_request_pipelines << create(:ci_pipeline,
+ merge_request.pipelines_for_merge_request << create(:ci_pipeline,
source: :merge_request_event,
merge_request: merge_request,
project: merge_request.source_project,
diff --git a/spec/factories/pages_domain_acme_orders.rb b/spec/factories/pages_domain_acme_orders.rb
new file mode 100644
index 00000000000..7f9ee1c8f9c
--- /dev/null
+++ b/spec/factories/pages_domain_acme_orders.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :pages_domain_acme_order do
+ pages_domain
+ url { 'https://example.com/' }
+ expires_at { 1.day.from_now }
+ challenge_token { 'challenge_token' }
+ challenge_file_content { 'filecontent' }
+
+ private_key { OpenSSL::PKey::RSA.new(4096).to_pem }
+
+ trait :expired do
+ expires_at { 1.day.ago }
+ end
+ end
+end
diff --git a/spec/factories/pages_domains.rb b/spec/factories/pages_domains.rb
index b74f72f2bd3..db8384877b0 100644
--- a/spec/factories/pages_domains.rb
+++ b/spec/factories/pages_domains.rb
@@ -45,6 +45,10 @@ nNp/xedE1YxutQ==
remove_at { 1.day.from_now }
end
+ trait :should_be_removed do
+ remove_at { 1.day.ago }
+ end
+
trait :unverified do
verified_at nil
end
diff --git a/spec/factories/pool_repositories.rb b/spec/factories/pool_repositories.rb
index 36e54cf44b4..8cac666069c 100644
--- a/spec/factories/pool_repositories.rb
+++ b/spec/factories/pool_repositories.rb
@@ -5,6 +5,7 @@ FactoryBot.define do
before(:create) do |pool|
pool.source_project = create(:project, :repository)
+ pool.source_project.update!(pool_repository: pool)
end
trait :scheduled do
diff --git a/spec/factories/project_auto_devops.rb b/spec/factories/project_auto_devops.rb
index 75ac7cc7687..1de42512402 100644
--- a/spec/factories/project_auto_devops.rb
+++ b/spec/factories/project_auto_devops.rb
@@ -2,7 +2,6 @@ FactoryBot.define do
factory :project_auto_devops do
project
enabled true
- domain "example.com"
deploy_strategy :continuous
trait :continuous_deployment do
diff --git a/spec/factories/project_metrics_settings.rb b/spec/factories/project_metrics_settings.rb
new file mode 100644
index 00000000000..234753f9b87
--- /dev/null
+++ b/spec/factories/project_metrics_settings.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :project_metrics_setting, class: ProjectMetricsSetting do
+ project
+ external_dashboard_url 'https://grafana.com'
+ end
+end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index ab185ab3972..743ec322885 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -260,6 +260,7 @@ FactoryBot.define do
trait(:merge_requests_enabled) { merge_requests_access_level ProjectFeature::ENABLED }
trait(:merge_requests_disabled) { merge_requests_access_level ProjectFeature::DISABLED }
trait(:merge_requests_private) { merge_requests_access_level ProjectFeature::PRIVATE }
+ trait(:merge_requests_public) { merge_requests_access_level ProjectFeature::PUBLIC }
trait(:repository_enabled) { repository_access_level ProjectFeature::ENABLED }
trait(:repository_disabled) { repository_access_level ProjectFeature::DISABLED }
trait(:repository_private) { repository_access_level ProjectFeature::PRIVATE }
diff --git a/spec/factories/uploads.rb b/spec/factories/uploads.rb
index 7256f785e1f..426abdc2a6c 100644
--- a/spec/factories/uploads.rb
+++ b/spec/factories/uploads.rb
@@ -13,7 +13,7 @@ FactoryBot.define do
end
# this needs to comply with RecordsUpload::Concern#upload_path
- path { File.join("uploads/-/system", model.class.to_s.underscore, mount_point.to_s, 'avatar.jpg') }
+ path { File.join("uploads/-/system", model.class.underscore, mount_point.to_s, 'avatar.jpg') }
trait :personal_snippet_upload do
uploader "PersonalFileUploader"
diff --git a/spec/features/admin/admin_appearance_spec.rb b/spec/features/admin/admin_appearance_spec.rb
index 83cd686818c..f6c498f7a4c 100644
--- a/spec/features/admin/admin_appearance_spec.rb
+++ b/spec/features/admin/admin_appearance_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'Admin Appearance' do
diff --git a/spec/features/admin/admin_browses_logs_spec.rb b/spec/features/admin/admin_browses_logs_spec.rb
index 02f50d7e27f..1f83d04d9aa 100644
--- a/spec/features/admin/admin_browses_logs_spec.rb
+++ b/spec/features/admin/admin_browses_logs_spec.rb
@@ -13,5 +13,6 @@ describe 'Admin browses logs' do
expect(page).to have_link 'test.log'
expect(page).to have_link 'sidekiq.log'
expect(page).to have_link 'repocheck.log'
+ expect(page).to have_link 'kubernetes.log'
end
end
diff --git a/spec/features/admin/admin_sees_project_statistics_spec.rb b/spec/features/admin/admin_sees_project_statistics_spec.rb
new file mode 100644
index 00000000000..b5323a1c76d
--- /dev/null
+++ b/spec/features/admin/admin_sees_project_statistics_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe "Admin > Admin sees project statistics" do
+ let(:current_user) { create(:admin) }
+
+ before do
+ sign_in(current_user)
+
+ visit admin_project_path(project)
+ end
+
+ context 'when project has statistics' do
+ let(:project) { create(:project, :repository) }
+
+ it "shows project statistics" do
+ expect(page).to have_content("Storage: 0 Bytes (0 Bytes repositories, 0 Bytes wikis, 0 Bytes build artifacts, 0 Bytes LFS)")
+ end
+ end
+
+ context 'when project has no statistics' do
+ let(:project) { create(:project, :repository) { |project| project.statistics.destroy } }
+
+ it "shows 'Storage: Unknown'" do
+ expect(page).to have_content("Storage: Unknown")
+ end
+ end
+end
diff --git a/spec/features/admin/admin_sees_projects_statistics_spec.rb b/spec/features/admin/admin_sees_projects_statistics_spec.rb
new file mode 100644
index 00000000000..6a6f369ac7c
--- /dev/null
+++ b/spec/features/admin/admin_sees_projects_statistics_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe "Admin > Admin sees projects statistics" do
+ let(:current_user) { create(:admin) }
+
+ before do
+ create(:project, :repository)
+ create(:project, :repository) { |project| project.statistics.destroy }
+
+ sign_in(current_user)
+
+ visit admin_projects_path
+ end
+
+ it "shows project statistics for projects that have them" do
+ expect(page.all('.stats').map(&:text)).to contain_exactly("0 Bytes", "Unknown")
+ end
+end
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index 04f39b807d7..93ccb03d822 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -230,6 +230,13 @@ describe 'Admin updates settings' do
expect(find_field('Username').value).to eq 'test_user'
expect(find('#service_push_channel').value).to eq '#test_channel'
end
+
+ it 'defaults Deployment events to false for chat notification template settings' do
+ first(:link, 'Service Templates').click
+ click_link 'Slack notifications'
+
+ expect(find_field('Deployment')).not_to be_checked
+ end
end
context 'CI/CD page' do
@@ -295,22 +302,22 @@ describe 'Admin updates settings' do
group = create(:group)
page.within('.as-performance-bar') do
- check 'Enable the Performance Bar'
+ check 'Enable access to the Performance Bar'
fill_in 'Allowed group', with: group.path
click_on 'Save changes'
end
expect(page).to have_content "Application settings saved successfully"
- expect(find_field('Enable the Performance Bar')).to be_checked
+ expect(find_field('Enable access to the Performance Bar')).to be_checked
expect(find_field('Allowed group').value).to eq group.path
page.within('.as-performance-bar') do
- uncheck 'Enable the Performance Bar'
+ uncheck 'Enable access to the Performance Bar'
click_on 'Save changes'
end
expect(page).to have_content 'Application settings saved successfully'
- expect(find_field('Enable the Performance Bar')).not_to be_checked
+ expect(find_field('Enable access to the Performance Bar')).not_to be_checked
expect(find_field('Allowed group').value).to be_nil
end
@@ -325,16 +332,19 @@ describe 'Admin updates settings' do
end
context 'Network page' do
- it 'Enable outbound requests' do
+ it 'Changes Outbound requests settings' do
visit network_admin_application_settings_path
page.within('.as-outbound') do
check 'Allow requests to the local network from hooks and services'
+ # Enabled by default
+ uncheck 'Enforce DNS rebinding attack protection'
click_button 'Save changes'
end
expect(page).to have_content "Application settings saved successfully"
expect(Gitlab::CurrentSettings.allow_local_requests_from_hooks_and_services).to be true
+ expect(Gitlab::CurrentSettings.dns_rebinding_protection_enabled).to be false
end
end
@@ -368,15 +378,50 @@ describe 'Admin updates settings' do
expect(Gitlab::CurrentSettings.pages_domain_verification_enabled?).to be_truthy
expect(page).to have_content "Application settings saved successfully"
end
+
+ context 'When pages_auto_ssl is enabled' do
+ before do
+ stub_feature_flags(pages_auto_ssl: true)
+ visit preferences_admin_application_settings_path
+ end
+
+ it "Change Pages Let's Encrypt settings" do
+ page.within('.as-pages') do
+ fill_in 'Email', with: 'my@test.example.com'
+ check "I have read and agree to the Let's Encrypt Terms of Service"
+ click_button 'Save changes'
+ end
+
+ expect(Gitlab::CurrentSettings.lets_encrypt_notification_email).to eq 'my@test.example.com'
+ expect(Gitlab::CurrentSettings.lets_encrypt_terms_of_service_accepted).to eq true
+ end
+ end
+
+ context 'When pages_auto_ssl is disabled' do
+ before do
+ stub_feature_flags(pages_auto_ssl: false)
+ visit preferences_admin_application_settings_path
+ end
+
+ it "Doesn't show Let's Encrypt options" do
+ page.within('.as-pages') do
+ expect(page).not_to have_content('Email')
+ end
+ end
+ end
end
def check_all_events
page.check('Active')
page.check('Push')
- page.check('Tag push')
- page.check('Note')
page.check('Issue')
+ page.check('Confidential issue')
page.check('Merge request')
+ page.check('Note')
+ page.check('Confidential note')
+ page.check('Tag push')
page.check('Pipeline')
+ page.check('Wiki page')
+ page.check('Deployment')
end
end
diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb
index b1c6f308bc6..29545779a34 100644
--- a/spec/features/admin/admin_users_spec.rb
+++ b/spec/features/admin/admin_users_spec.rb
@@ -34,14 +34,11 @@ describe "Admin::Users" do
expect(page).to have_button('Delete user and contributions')
end
- describe "view extra user information", :js do
- it 'does not have the user popover open' do
+ describe "view extra user information" do
+ it 'shows the user popover on hover', :js, :quarantine do
expect(page).not_to have_selector('#__BV_popover_1__')
- end
- it 'shows the user popover on hover' do
first_user_link = page.first('.js-user-link')
-
first_user_link.hover
expect(page).to have_selector('#__BV_popover_1__')
diff --git a/spec/features/atom/dashboard_issues_spec.rb b/spec/features/atom/dashboard_issues_spec.rb
index dfa1c92ea49..d523e2992db 100644
--- a/spec/features/atom/dashboard_issues_spec.rb
+++ b/spec/features/atom/dashboard_issues_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe "Dashboard Issues Feed" do
diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb
index 8f34fddbf06..b1798c11361 100644
--- a/spec/features/boards/sidebar_spec.rb
+++ b/spec/features/boards/sidebar_spec.rb
@@ -133,7 +133,7 @@ describe 'Issue Boards', :js do
close_dropdown_menu_if_visible
wait_for_requests
- expect(page).to have_content('No assignee')
+ expect(page).to have_content('None')
end
expect(card_two).not_to have_selector('.avatar')
@@ -143,7 +143,7 @@ describe 'Issue Boards', :js do
click_card(card)
page.within(find('.assignee')) do
- expect(page).to have_content('No assignee')
+ expect(page).to have_content('None')
click_button 'assign yourself'
@@ -352,6 +352,8 @@ describe 'Issue Boards', :js do
page.within('.labels') do
click_link 'Edit'
+ wait_for_requests
+
click_link 'Create project label'
fill_in 'new_label_name', with: 'test label'
first('.suggest-colors-dropdown a').click
@@ -368,6 +370,8 @@ describe 'Issue Boards', :js do
page.within('.labels') do
click_link 'Edit'
+ wait_for_requests
+
click_link 'Create project label'
fill_in 'new_label_name', with: 'test label'
first('.suggest-colors-dropdown a').click
diff --git a/spec/features/clusters/cluster_detail_page_spec.rb b/spec/features/clusters/cluster_detail_page_spec.rb
index d2e46d15730..683c57a97f8 100644
--- a/spec/features/clusters/cluster_detail_page_spec.rb
+++ b/spec/features/clusters/cluster_detail_page_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe 'Clusterable > Show page' do
+ include KubernetesHelpers
+
let(:current_user) { create(:user) }
let(:cluster_ingress_help_text_selector) { '.js-ingress-domain-help-text' }
let(:hide_modifier_selector) { '.hide' }
@@ -83,6 +85,7 @@ describe 'Clusterable > Show page' do
shared_examples 'editing a user-provided cluster' do
before do
+ stub_kubeclient_discover(cluster.platform.api_url)
clusterable.add_maintainer(current_user)
visit cluster_path
end
diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb
index 5c6c1c4fd15..e6f44aa7d20 100644
--- a/spec/features/commits_spec.rb
+++ b/spec/features/commits_spec.rb
@@ -82,14 +82,14 @@ describe 'Commits' do
it 'shows pipeline`s data' do
expect(page).to have_content pipeline.sha[0..7]
- expect(page).to have_content pipeline.git_commit_message
+ expect(page).to have_content pipeline.git_commit_message.gsub!(/\s+/, ' ')
expect(page).to have_content pipeline.user.name
end
end
context 'Download artifacts' do
before do
- build.update(legacy_artifacts_file: artifacts_file)
+ create(:ci_job_artifact, :archive, file: artifacts_file, job: build)
end
it do
@@ -119,13 +119,13 @@ describe 'Commits' do
context "when logged as reporter" do
before do
project.add_reporter(user)
- build.update(legacy_artifacts_file: artifacts_file)
+ create(:ci_job_artifact, :archive, file: artifacts_file, job: build)
visit pipeline_path(pipeline)
end
it 'Renders header', :js do
expect(page).to have_content pipeline.sha[0..7]
- expect(page).to have_content pipeline.git_commit_message
+ expect(page).to have_content pipeline.git_commit_message.gsub!(/\s+/, ' ')
expect(page).to have_content pipeline.user.name
expect(page).not_to have_link('Cancel running')
expect(page).not_to have_link('Retry')
@@ -141,13 +141,13 @@ describe 'Commits' do
project.update(
visibility_level: Gitlab::VisibilityLevel::INTERNAL,
public_builds: false)
- build.update(legacy_artifacts_file: artifacts_file)
+ create(:ci_job_artifact, :archive, file: artifacts_file, job: build)
visit pipeline_path(pipeline)
end
it do
expect(page).to have_content pipeline.sha[0..7]
- expect(page).to have_content pipeline.git_commit_message
+ expect(page).to have_content pipeline.git_commit_message.gsub!(/\s+/, ' ')
expect(page).to have_content pipeline.user.name
expect(page).not_to have_link('Cancel running')
diff --git a/spec/features/contextual_sidebar_spec.rb b/spec/features/contextual_sidebar_spec.rb
new file mode 100644
index 00000000000..88da1b7966b
--- /dev/null
+++ b/spec/features/contextual_sidebar_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Contextual sidebar', :js do
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+
+ visit project_path(project)
+ end
+
+ it 'shows flyout navs when collapsed or expanded apart from on the active item when expanded' do
+ expect(page).not_to have_selector('.js-sidebar-collapsed')
+
+ find('.qa-link-pipelines').hover
+
+ expect(page).to have_selector('.is-showing-fly-out')
+
+ find('.qa-link-project').hover
+
+ expect(page).not_to have_selector('.is-showing-fly-out')
+
+ find('.qa-toggle-sidebar').click
+
+ find('.qa-link-pipelines').hover
+
+ expect(page).to have_selector('.is-showing-fly-out')
+
+ find('.qa-link-project').hover
+
+ expect(page).to have_selector('.is-showing-fly-out')
+ end
+end
diff --git a/spec/features/dashboard/groups_list_spec.rb b/spec/features/dashboard/groups_list_spec.rb
index e75c43d5338..fb76e2b0014 100644
--- a/spec/features/dashboard/groups_list_spec.rb
+++ b/spec/features/dashboard/groups_list_spec.rb
@@ -125,7 +125,7 @@ describe 'Dashboard Groups page', :js do
end
it 'loads results for next page' do
- expect(page).to have_selector('.gl-pagination .page-item a[role=menuitemradio]', count: 2)
+ expect(page).to have_selector('.gl-pagination .page-item a.page-link', count: 3)
# Check first page
expect(page).to have_content(group2.full_name)
@@ -134,7 +134,7 @@ describe 'Dashboard Groups page', :js do
expect(page).not_to have_selector("#group-#{group.id}")
# Go to next page
- find('.gl-pagination .page-item:not(.active) a[role=menuitemradio]').click
+ find('.gl-pagination .page-item:last-of-type a.page-link').click
wait_for_requests
diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb
index 9d1c1e3acc7..d1ed64cce7f 100644
--- a/spec/features/dashboard/projects_spec.rb
+++ b/spec/features/dashboard/projects_spec.rb
@@ -112,6 +112,14 @@ describe 'Dashboard Projects' do
expect(first('.project-row')).to have_content(project_with_most_stars.title)
end
+
+ it 'shows tabs to filter by all projects or personal' do
+ visit dashboard_projects_path
+ segmented_button = page.find('.filtered-search-nav .button-filter-group')
+
+ expect(segmented_button).to have_content 'All'
+ expect(segmented_button).to have_content 'Personal'
+ end
end
context 'when on Starred projects tab', :js do
@@ -134,6 +142,12 @@ describe 'Dashboard Projects' do
expect(find('.nav-links li:nth-child(1) .badge-pill')).to have_content(1)
expect(find('.nav-links li:nth-child(2) .badge-pill')).to have_content(1)
end
+
+ it 'does not show tabs to filter by all projects or personal' do
+ visit(starred_dashboard_projects_path)
+
+ expect(page).not_to have_content '.filtered-search-nav'
+ end
end
describe 'with a pipeline', :clean_gitlab_redis_shared_state do
diff --git a/spec/features/dashboard/todos/todos_spec.rb b/spec/features/dashboard/todos/todos_spec.rb
index fd8677feab5..d58e3b2841e 100644
--- a/spec/features/dashboard/todos/todos_spec.rb
+++ b/spec/features/dashboard/todos/todos_spec.rb
@@ -17,6 +17,26 @@ describe 'Dashboard Todos' do
end
end
+ context 'when the todo references a merge request' do
+ let(:referenced_mr) { create(:merge_request, source_project: project) }
+ let(:note) { create(:note, project: project, note: "Check out #{referenced_mr.to_reference}") }
+ let!(:todo) { create(:todo, :mentioned, user: user, project: project, author: author, note: note) }
+
+ before do
+ sign_in(user)
+ visit dashboard_todos_path
+ end
+
+ it 'renders the mr link with the extra attributes' do
+ link = page.find_link(referenced_mr.to_reference)
+
+ expect(link).not_to be_nil
+ expect(link['data-iid']).to eq(referenced_mr.iid.to_s)
+ expect(link['data-project-path']).to eq(referenced_mr.project.full_path)
+ expect(link['data-mr-title']).to eq(referenced_mr.title)
+ end
+ end
+
context 'User has a todo', :js do
before do
create(:todo, :mentioned, user: user, project: project, target: issue, author: author)
diff --git a/spec/features/dashboard/user_filters_projects_spec.rb b/spec/features/dashboard/user_filters_projects_spec.rb
index cc86114e436..4410c8f887f 100644
--- a/spec/features/dashboard/user_filters_projects_spec.rb
+++ b/spec/features/dashboard/user_filters_projects_spec.rb
@@ -2,9 +2,9 @@ require 'spec_helper'
describe 'Dashboard > User filters projects' do
let(:user) { create(:user) }
- let(:project) { create(:project, name: 'Victorialand', namespace: user.namespace) }
+ let(:project) { create(:project, name: 'Victorialand', namespace: user.namespace, created_at: 2.seconds.ago, updated_at: 2.seconds.ago) }
let(:user2) { create(:user) }
- let(:project2) { create(:project, name: 'Treasure', namespace: user2.namespace) }
+ let(:project2) { create(:project, name: 'Treasure', namespace: user2.namespace, created_at: 1.second.ago, updated_at: 1.second.ago) }
before do
project.add_maintainer(user)
@@ -14,6 +14,7 @@ describe 'Dashboard > User filters projects' do
describe 'filtering personal projects' do
before do
+ stub_feature_flags(project_list_filter_bar: false)
project2.add_developer(user)
visit dashboard_projects_path
@@ -30,6 +31,7 @@ describe 'Dashboard > User filters projects' do
describe 'filtering starred projects', :js do
before do
+ stub_feature_flags(project_list_filter_bar: false)
user.toggle_star(project)
visit dashboard_projects_path
@@ -42,4 +44,187 @@ describe 'Dashboard > User filters projects' do
expect(page).not_to have_content('You don\'t have starred projects yet')
end
end
+
+ describe 'without search bar', :js do
+ before do
+ stub_feature_flags(project_list_filter_bar: false)
+
+ project2.add_developer(user)
+ visit dashboard_projects_path
+ end
+
+ it 'autocompletes searches upon typing', :js do
+ expect(page).to have_content 'Victorialand'
+ expect(page).to have_content 'Treasure'
+
+ fill_in 'project-filter-form-field', with: 'Lord beerus\n'
+
+ expect(page).not_to have_content 'Victorialand'
+ expect(page).not_to have_content 'Treasure'
+ end
+ end
+
+ describe 'with search bar', :js do
+ before do
+ stub_feature_flags(project_list_filter_bar: true)
+
+ project2.add_developer(user)
+ visit dashboard_projects_path
+ end
+
+ # TODO: move these helpers somewhere more useful
+ def click_sort_direction
+ page.find('.filtered-search-block #filtered-search-sorting-dropdown .reverse-sort-btn').click
+ end
+
+ def select_dropdown_option(selector, label)
+ dropdown = page.find(selector)
+ dropdown.click
+
+ dropdown.find('.dropdown-menu a', text: label, match: :first).click
+ end
+
+ def expect_to_see_projects(sorted_projects)
+ list = page.all('.projects-list .project-name').map(&:text)
+ expect(list).to match(sorted_projects)
+ end
+
+ describe 'Search' do
+ it 'executes when the search button is clicked' do
+ expect(page).to have_content 'Victorialand'
+ expect(page).to have_content 'Treasure'
+
+ fill_in 'project-filter-form-field', with: 'Lord vegeta\n'
+ find('.filtered-search .btn').click
+
+ expect(page).not_to have_content 'Victorialand'
+ expect(page).not_to have_content 'Treasure'
+ end
+
+ it 'will execute when i press enter' do
+ expect(page).to have_content 'Victorialand'
+ expect(page).to have_content 'Treasure'
+
+ fill_in 'project-filter-form-field', with: 'Lord frieza\n'
+ find('#project-filter-form-field').native.send_keys :enter
+
+ expect(page).not_to have_content 'Victorialand'
+ expect(page).not_to have_content 'Treasure'
+ end
+ end
+
+ describe 'Filter' do
+ before do
+ private_project = create(:project, :private, name: 'Private project', namespace: user.namespace)
+ internal_project = create(:project, :internal, name: 'Internal project', namespace: user.namespace)
+
+ private_project.add_maintainer(user)
+ internal_project.add_maintainer(user)
+ end
+
+ it 'filters private projects only' do
+ select_dropdown_option '#filtered-search-visibility-dropdown', 'Private'
+
+ expect(current_url).to match(/visibility_level=0/)
+
+ list = page.all('.projects-list .project-name').map(&:text)
+
+ expect(list).to contain_exactly("Private project", "Treasure", "Victorialand")
+ end
+
+ it 'filters internal projects only' do
+ select_dropdown_option '#filtered-search-visibility-dropdown', 'Internal'
+
+ expect(current_url).to match(/visibility_level=10/)
+
+ list = page.all('.projects-list .project-name').map(&:text)
+
+ expect(list).to contain_exactly('Internal project')
+ end
+
+ it 'filters any project' do
+ select_dropdown_option '#filtered-search-visibility-dropdown', 'Any'
+ list = page.all('.projects-list .project-name').map(&:text)
+
+ expect(list).to contain_exactly("Internal project", "Private project", "Treasure", "Victorialand")
+ end
+ end
+
+ describe 'Sorting' do
+ let(:desc_sorted_project_names) { %w[Treasure Victorialand] }
+
+ before do
+ user.toggle_star(project)
+ user.toggle_star(project2)
+ user2.toggle_star(project2)
+ end
+
+ it 'has all sorting options', :js do
+ sorting_dropdown = page.find('.filtered-search-block #filtered-search-sorting-dropdown')
+
+ expect(sorting_dropdown).to have_css '.reverse-sort-btn'
+
+ sorting_dropdown.click
+
+ ['Last updated', 'Created date', 'Name', 'Stars'].each do |label|
+ expect(sorting_dropdown).to have_content(label)
+ end
+ end
+
+ it 'defaults to "Last updated"', :js do
+ page.find('.filtered-search-block #filtered-search-sorting-dropdown').click
+ active_sorting_option = page.first('.filtered-search-block #filtered-search-sorting-dropdown .is-active')
+
+ expect(active_sorting_option).to have_content 'Last updated'
+ end
+
+ context 'Sorting by name' do
+ it 'sorts the project list' do
+ select_dropdown_option '#filtered-search-sorting-dropdown', 'Name'
+
+ expect_to_see_projects(desc_sorted_project_names)
+
+ click_sort_direction
+
+ expect_to_see_projects(desc_sorted_project_names.reverse)
+ end
+ end
+
+ context 'Sorting by Last updated' do
+ it 'sorts the project list' do
+ select_dropdown_option '#filtered-search-sorting-dropdown', 'Last updated'
+
+ expect_to_see_projects(desc_sorted_project_names)
+
+ click_sort_direction
+
+ expect_to_see_projects(desc_sorted_project_names.reverse)
+ end
+ end
+
+ context 'Sorting by Created date' do
+ it 'sorts the project list' do
+ select_dropdown_option '#filtered-search-sorting-dropdown', 'Created date'
+
+ expect_to_see_projects(desc_sorted_project_names)
+
+ click_sort_direction
+
+ expect_to_see_projects(desc_sorted_project_names.reverse)
+ end
+ end
+
+ context 'Sorting by Stars' do
+ it 'sorts the project list' do
+ select_dropdown_option '#filtered-search-sorting-dropdown', 'Stars'
+
+ expect_to_see_projects(desc_sorted_project_names)
+
+ click_sort_direction
+
+ expect_to_see_projects(desc_sorted_project_names.reverse)
+ end
+ end
+ end
+ end
end
diff --git a/spec/features/global_search_spec.rb b/spec/features/global_search_spec.rb
index d7692181453..f2ab5373d3d 100644
--- a/spec/features/global_search_spec.rb
+++ b/spec/features/global_search_spec.rb
@@ -25,4 +25,18 @@ describe 'Global search' do
expect(page).to have_selector('.gl-pagination .next')
end
end
+
+ it 'closes the dropdown on blur', :js do
+ visit dashboard_projects_path
+
+ fill_in 'search', with: "a"
+ dropdown = find('.js-dashboard-search-options')
+
+ expect(dropdown[:class]).to include 'show'
+
+ find('#search').send_keys(:backspace)
+ find('body').click
+
+ expect(dropdown[:class]).not_to include 'show'
+ end
end
diff --git a/spec/features/groups/clusters/user_spec.rb b/spec/features/groups/clusters/user_spec.rb
index b661b5cbaef..84a8691a7f2 100644
--- a/spec/features/groups/clusters/user_spec.rb
+++ b/spec/features/groups/clusters/user_spec.rb
@@ -14,6 +14,7 @@ describe 'User Cluster', :js do
allow(Groups::ClustersController).to receive(:STATUS_POLLING_INTERVAL) { 100 }
allow_any_instance_of(Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService).to receive(:execute)
+ allow_any_instance_of(Clusters::Cluster).to receive(:retrieve_connection_status).and_return(:connected)
end
context 'when user does not have a cluster and visits cluster index page' do
diff --git a/spec/features/groups/members/leave_group_spec.rb b/spec/features/groups/members/leave_group_spec.rb
index 7a91c64d7db..439803f9255 100644
--- a/spec/features/groups/members/leave_group_spec.rb
+++ b/spec/features/groups/members/leave_group_spec.rb
@@ -21,6 +21,20 @@ describe 'Groups > Members > Leave group' do
expect(group.users).not_to include(user)
end
+ it 'guest leaves the group by url param', :js do
+ group.add_guest(user)
+ group.add_owner(other_user)
+
+ visit group_path(group, leave: 1)
+
+ page.accept_confirm
+
+ expect(find('.flash-notice')).to have_content "You left the \"#{group.full_name}\" group"
+ expect(page).to have_content left_group_message(group)
+ expect(current_path).to eq(dashboard_groups_path)
+ expect(group.users).not_to include(user)
+ end
+
it 'guest leaves the group as last member' do
group.add_guest(user)
@@ -32,7 +46,7 @@ describe 'Groups > Members > Leave group' do
expect(group.users).not_to include(user)
end
- it 'owner leaves the group if they is not the last owner' do
+ it 'owner leaves the group if they are not the last owner' do
group.add_owner(user)
group.add_owner(other_user)
@@ -44,7 +58,7 @@ describe 'Groups > Members > Leave group' do
expect(group.users).not_to include(user)
end
- it 'owner can not leave the group if they is a last owner' do
+ it 'owner can not leave the group if they are the last owner' do
group.add_owner(user)
visit group_path(group)
@@ -56,6 +70,14 @@ describe 'Groups > Members > Leave group' do
expect(find(:css, '.project-members-page li', text: user.name)).not_to have_selector(:css, 'a.btn-remove')
end
+ it 'owner can not leave the group by url param if they are the last owner', :js do
+ group.add_owner(user)
+
+ visit group_path(group, leave: 1)
+
+ expect(find('.flash-alert')).to have_content 'You do not have permission to leave this group'
+ end
+
def left_group_message(group)
"You left the \"#{group.name}\""
end
diff --git a/spec/features/groups/merge_requests_spec.rb b/spec/features/groups/merge_requests_spec.rb
index e1bc4eca619..59230d6891a 100644
--- a/spec/features/groups/merge_requests_spec.rb
+++ b/spec/features/groups/merge_requests_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'Group merge requests page' do
diff --git a/spec/features/ics/dashboard_issues_spec.rb b/spec/features/ics/dashboard_issues_spec.rb
index debae0ea930..b74bbf848ac 100644
--- a/spec/features/ics/dashboard_issues_spec.rb
+++ b/spec/features/ics/dashboard_issues_spec.rb
@@ -91,7 +91,7 @@ describe 'Dashboard Issues Calendar Feed' do
expect(body).to have_text("SUMMARY:test title (in #{project.full_path})")
# line length for ics is 75 chars
- expected_description = "DESCRIPTION:Find out more at #{issue_url(issue)}".insert(75, "\r\n")
+ expected_description = "DESCRIPTION:Find out more at #{issue_url(issue)}".insert(75, ' ')
expect(body).to have_text(expected_description)
expect(body).to have_text("DTSTART;VALUE=DATE:#{Date.tomorrow.strftime('%Y%m%d')}")
expect(body).to have_text("URL:#{issue_url(issue)}")
diff --git a/spec/features/ics/group_issues_spec.rb b/spec/features/ics/group_issues_spec.rb
index 4177c7f8704..86da720c8be 100644
--- a/spec/features/ics/group_issues_spec.rb
+++ b/spec/features/ics/group_issues_spec.rb
@@ -66,7 +66,7 @@ describe 'Group Issues Calendar Feed' do
expect(body).to have_text("SUMMARY:test title (in #{project.full_path})")
# line length for ics is 75 chars
- expected_description = "DESCRIPTION:Find out more at #{issue_url(issue)}".insert(75, "\r\n")
+ expected_description = "DESCRIPTION:Find out more at #{issue_url(issue)}".insert(75, ' ')
expect(body).to have_text(expected_description)
expect(body).to have_text("DTSTART;VALUE=DATE:#{Date.tomorrow.strftime('%Y%m%d')}")
expect(body).to have_text("URL:#{issue_url(issue)}")
diff --git a/spec/features/ics/project_issues_spec.rb b/spec/features/ics/project_issues_spec.rb
index 0d9844be099..37b90c666bc 100644
--- a/spec/features/ics/project_issues_spec.rb
+++ b/spec/features/ics/project_issues_spec.rb
@@ -65,7 +65,7 @@ describe 'Project Issues Calendar Feed' do
expect(body).to have_text("SUMMARY:test title (in #{project.full_path})")
# line length for ics is 75 chars
- expected_description = "DESCRIPTION:Find out more at #{issue_url(issue)}".insert(75, "\r\n")
+ expected_description = "DESCRIPTION:Find out more at #{issue_url(issue)}".insert(75, ' ')
expect(body).to have_text(expected_description)
expect(body).to have_text("DTSTART;VALUE=DATE:#{Date.tomorrow.strftime('%Y%m%d')}")
expect(body).to have_text("URL:#{issue_url(issue)}")
diff --git a/spec/features/instance_statistics/conversational_development_index_spec.rb b/spec/features/instance_statistics/conversational_development_index_spec.rb
index d8be554d734..713cd944f8c 100644
--- a/spec/features/instance_statistics/conversational_development_index_spec.rb
+++ b/spec/features/instance_statistics/conversational_development_index_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'Conversational Development Index' do
diff --git a/spec/features/issuables/issuable_list_spec.rb b/spec/features/issuables/issuable_list_spec.rb
index 7b6e9cd66b2..225b858742d 100644
--- a/spec/features/issuables/issuable_list_spec.rb
+++ b/spec/features/issuables/issuable_list_spec.rb
@@ -76,7 +76,7 @@ describe 'issuable list' do
create(:issue, project: project, author: user)
else
create(:merge_request, source_project: project, source_branch: generate(:branch))
- source_branch = FFaker::Name.name
+ source_branch = FFaker::Lorem.characters(8)
pipeline = create(:ci_empty_pipeline, project: project, ref: source_branch, status: %w(running failed success).sample, sha: 'any')
create(:merge_request, title: FFaker::Lorem.sentence, source_project: project, source_branch: source_branch, head_pipeline: pipeline)
end
diff --git a/spec/features/issuables/sorting_list_spec.rb b/spec/features/issuables/sorting_list_spec.rb
index 0601dd47c03..3a46a4e0167 100644
--- a/spec/features/issuables/sorting_list_spec.rb
+++ b/spec/features/issuables/sorting_list_spec.rb
@@ -86,26 +86,26 @@ describe 'Sort Issuable List' do
expect(last_merge_request).to include(first_created_issuable.title)
end
end
+ end
- context 'custom sorting' do
- let(:issuable_type) { :merge_request }
+ context 'custom sorting' do
+ let(:issuable_type) { :merge_request }
- it 'supports sorting in asc and desc order' do
- visit_merge_requests_with_state(project, 'open')
+ it 'supports sorting in asc and desc order' do
+ visit_merge_requests_with_state(project, 'open')
- page.within('.issues-other-filters') do
- click_button('Created date')
- click_link('Last updated')
- end
+ page.within('.issues-other-filters') do
+ click_button('Created date')
+ click_link('Last updated')
+ end
- expect(first_merge_request).to include(last_updated_issuable.title)
- expect(last_merge_request).to include(first_updated_issuable.title)
+ expect(first_merge_request).to include(last_updated_issuable.title)
+ expect(last_merge_request).to include(first_updated_issuable.title)
- find('.issues-other-filters .filter-dropdown-container .qa-reverse-sort').click
+ find('.issues-other-filters .filter-dropdown-container .qa-reverse-sort').click
- expect(first_merge_request).to include(first_updated_issuable.title)
- expect(last_merge_request).to include(last_updated_issuable.title)
- end
+ expect(first_merge_request).to include(first_updated_issuable.title)
+ expect(last_merge_request).to include(last_updated_issuable.title)
end
end
end
diff --git a/spec/features/issues/filtered_search/dropdown_hint_spec.rb b/spec/features/issues/filtered_search/dropdown_hint_spec.rb
index 096756f19cc..1f4e9e79179 100644
--- a/spec/features/issues/filtered_search/dropdown_hint_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_hint_spec.rb
@@ -80,7 +80,7 @@ describe 'Dropdown hint', :js do
expect(page).to have_css(js_dropdown_hint, visible: false)
expect(page).to have_css('#js-dropdown-author', visible: true)
- expect_tokens([{ name: 'author' }])
+ expect_tokens([{ name: 'Author' }])
expect_filtered_search_input_empty
end
@@ -89,7 +89,7 @@ describe 'Dropdown hint', :js do
expect(page).to have_css(js_dropdown_hint, visible: false)
expect(page).to have_css('#js-dropdown-assignee', visible: true)
- expect_tokens([{ name: 'assignee' }])
+ expect_tokens([{ name: 'Assignee' }])
expect_filtered_search_input_empty
end
@@ -98,7 +98,7 @@ describe 'Dropdown hint', :js do
expect(page).to have_css(js_dropdown_hint, visible: false)
expect(page).to have_css('#js-dropdown-milestone', visible: true)
- expect_tokens([{ name: 'milestone' }])
+ expect_tokens([{ name: 'Milestone' }])
expect_filtered_search_input_empty
end
@@ -107,7 +107,7 @@ describe 'Dropdown hint', :js do
expect(page).to have_css(js_dropdown_hint, visible: false)
expect(page).to have_css('#js-dropdown-label', visible: true)
- expect_tokens([{ name: 'label' }])
+ expect_tokens([{ name: 'Label' }])
expect_filtered_search_input_empty
end
@@ -116,7 +116,7 @@ describe 'Dropdown hint', :js do
expect(page).to have_css(js_dropdown_hint, visible: false)
expect(page).to have_css('#js-dropdown-my-reaction', visible: true)
- expect_tokens([{ name: 'my-reaction' }])
+ expect_tokens([{ name: 'My-reaction' }])
expect_filtered_search_input_empty
end
@@ -125,7 +125,7 @@ describe 'Dropdown hint', :js do
expect(page).to have_css(js_dropdown_hint, visible: false)
expect(page).to have_css('#js-dropdown-confidential', visible: true)
- expect_tokens([{ name: 'confidential' }])
+ expect_tokens([{ name: 'Confidential' }])
expect_filtered_search_input_empty
end
end
@@ -137,7 +137,7 @@ describe 'Dropdown hint', :js do
expect(page).to have_css(js_dropdown_hint, visible: false)
expect(page).to have_css('#js-dropdown-author', visible: true)
- expect_tokens([{ name: 'author' }])
+ expect_tokens([{ name: 'Author' }])
expect_filtered_search_input_empty
end
@@ -147,7 +147,7 @@ describe 'Dropdown hint', :js do
expect(page).to have_css(js_dropdown_hint, visible: false)
expect(page).to have_css('#js-dropdown-assignee', visible: true)
- expect_tokens([{ name: 'assignee' }])
+ expect_tokens([{ name: 'Assignee' }])
expect_filtered_search_input_empty
end
@@ -157,7 +157,7 @@ describe 'Dropdown hint', :js do
expect(page).to have_css(js_dropdown_hint, visible: false)
expect(page).to have_css('#js-dropdown-milestone', visible: true)
- expect_tokens([{ name: 'milestone' }])
+ expect_tokens([{ name: 'Milestone' }])
expect_filtered_search_input_empty
end
@@ -167,7 +167,7 @@ describe 'Dropdown hint', :js do
expect(page).to have_css(js_dropdown_hint, visible: false)
expect(page).to have_css('#js-dropdown-label', visible: true)
- expect_tokens([{ name: 'label' }])
+ expect_tokens([{ name: 'Label' }])
expect_filtered_search_input_empty
end
@@ -177,7 +177,7 @@ describe 'Dropdown hint', :js do
expect(page).to have_css(js_dropdown_hint, visible: false)
expect(page).to have_css('#js-dropdown-my-reaction', visible: true)
- expect_tokens([{ name: 'my-reaction' }])
+ expect_tokens([{ name: 'My-reaction' }])
expect_filtered_search_input_empty
end
end
@@ -189,7 +189,7 @@ describe 'Dropdown hint', :js do
filtered_search.send_keys(:backspace)
click_hint('author')
- expect_tokens([{ name: 'author' }])
+ expect_tokens([{ name: 'Author' }])
expect_filtered_search_input_empty
end
@@ -199,7 +199,7 @@ describe 'Dropdown hint', :js do
filtered_search.send_keys(:backspace)
click_hint('assignee')
- expect_tokens([{ name: 'assignee' }])
+ expect_tokens([{ name: 'Assignee' }])
expect_filtered_search_input_empty
end
@@ -209,7 +209,7 @@ describe 'Dropdown hint', :js do
filtered_search.send_keys(:backspace)
click_hint('milestone')
- expect_tokens([{ name: 'milestone' }])
+ expect_tokens([{ name: 'Milestone' }])
expect_filtered_search_input_empty
end
@@ -219,7 +219,7 @@ describe 'Dropdown hint', :js do
filtered_search.send_keys(:backspace)
click_hint('label')
- expect_tokens([{ name: 'label' }])
+ expect_tokens([{ name: 'Label' }])
expect_filtered_search_input_empty
end
@@ -229,7 +229,7 @@ describe 'Dropdown hint', :js do
filtered_search.send_keys(:backspace)
click_hint('my-reaction')
- expect_tokens([{ name: 'my-reaction' }])
+ expect_tokens([{ name: 'My-reaction' }])
expect_filtered_search_input_empty
end
end
@@ -247,7 +247,7 @@ describe 'Dropdown hint', :js do
expect(page).to have_css(js_dropdown_hint, visible: false)
expect(page).to have_css('#js-dropdown-wip', visible: true)
- expect_tokens([{ name: 'wip' }])
+ expect_tokens([{ name: 'WIP' }])
expect_filtered_search_input_empty
end
end
diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb
index 51508b78649..5bdd9113b06 100644
--- a/spec/features/issues_spec.rb
+++ b/spec/features/issues_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'Issues' do
@@ -91,7 +93,7 @@ describe 'Issues' do
click_button 'Save changes'
page.within('.assignee') do
- expect(page).to have_content 'No assignee - assign yourself'
+ expect(page).to have_content 'None - assign yourself'
end
expect(issue.reload.assignees).to be_empty
@@ -208,7 +210,7 @@ describe 'Issues' do
let(:issue) { @issue }
it 'allows filtering by issues with no specified assignee' do
- visit project_issues_path(project, assignee_id: IssuableFinder::NONE)
+ visit project_issues_path(project, assignee_id: IssuableFinder::FILTER_NONE)
expect(page).to have_content 'foobar'
expect(page).not_to have_content 'barbaz'
@@ -465,7 +467,7 @@ describe 'Issues' do
click_link 'Edit'
click_link 'Unassigned'
first('.title').click
- expect(page).to have_content 'No assignee'
+ expect(page).to have_content 'None'
end
# wait_for_requests does not work with vue-resource at the moment
@@ -479,7 +481,7 @@ describe 'Issues' do
visit project_issue_path(project, issue2)
page.within('.assignee') do
- expect(page).to have_content "No assignee"
+ expect(page).to have_content "None"
end
page.within '.assignee' do
@@ -522,7 +524,7 @@ describe 'Issues' do
close_dropdown_menu_if_visible
page.within '.value .assign-yourself' do
- expect(page).to have_content "No assignee"
+ expect(page).to have_content "None"
end
end
end
@@ -775,10 +777,10 @@ describe 'Issues' do
wait_for_requests
- expect(page).to have_no_content 'No due date'
+ expect(page).to have_no_content 'None'
click_link 'remove due date'
- expect(page).to have_content 'No due date'
+ expect(page).to have_content 'None'
end
end
end
diff --git a/spec/features/markdown/gitlab_flavored_markdown_spec.rb b/spec/features/markdown/gitlab_flavored_markdown_spec.rb
index 6997ca48427..8fda3c7193e 100644
--- a/spec/features/markdown/gitlab_flavored_markdown_spec.rb
+++ b/spec/features/markdown/gitlab_flavored_markdown_spec.rb
@@ -20,8 +20,7 @@ describe "GitLab Flavored Markdown" do
let(:commit) { project.commit }
before do
- allow_any_instance_of(Commit).to receive(:title)
- .and_return("fix #{issue.to_reference}\n\nask #{fred.to_reference} for details")
+ create_commit("fix #{issue.to_reference}\n\nask #{fred.to_reference} for details", project, user, 'master')
end
it "renders title in commits#index" do
diff --git a/spec/features/merge_request/user_accepts_merge_request_spec.rb b/spec/features/merge_request/user_accepts_merge_request_spec.rb
index 5fa23dbb998..3d029ccec1a 100644
--- a/spec/features/merge_request/user_accepts_merge_request_spec.rb
+++ b/spec/features/merge_request/user_accepts_merge_request_spec.rb
@@ -15,8 +15,7 @@ describe 'User accepts a merge request', :js do
click_button('Merge')
- expect(page).to have_content("The changes were merged into #{merge_request.target_branch} with \
- #{merge_request.short_merge_commit_sha}")
+ expect(page).to have_content("The changes were merged into #{merge_request.target_branch} with #{merge_request.short_merge_commit_sha}")
end
context 'with removing the source branch' do
diff --git a/spec/features/merge_request/user_creates_image_diff_notes_spec.rb b/spec/features/merge_request/user_creates_image_diff_notes_spec.rb
index 65de0afae0c..3a9a06a6bc3 100644
--- a/spec/features/merge_request/user_creates_image_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_creates_image_diff_notes_spec.rb
@@ -191,29 +191,119 @@ describe 'Merge request > User creates image diff notes', :js do
end
end
- describe 'image view modes' do
- before do
- visit project_commit_path(project, '2f63565e7aac07bcdadb654e253078b727143ec4')
+ shared_examples 'swipe view' do
+ it 'moves the swipe handle' do
+ # Simulate dragging swipe view slider
+ expect { drag_and_drop_by(find('.swipe-bar'), 20, 0) }
+ .to change { find('.swipe-bar')['style'] }
+ .from(a_string_matching('left: 1px'))
end
- it 'resizes image in onion skin view mode' do
- find('.view-modes-menu .onion-skin').click
+ it 'shows both images at the same position' do
+ drag_and_drop_by(find('.swipe-bar'), 40, 0)
- expect(find('.onion-skin-frame')['style']).to match('width: 228px; height: 240px;')
+ expect(left_position('.frame.added img'))
+ .to eq(left_position('.frame.deleted img'))
end
+ end
- it 'resets onion skin view mode opacity when toggling between view modes' do
- find('.view-modes-menu .onion-skin').click
-
+ shared_examples 'onion skin' do
+ it 'resets opacity when toggling between view modes' do
# Simulate dragging onion-skin slider
drag_and_drop_by(find('.dragger'), -30, 0)
expect(find('.onion-skin-frame .frame.added', visible: false)['style']).not_to match('opacity: 1;')
+ switch_to_swipe_view
+ switch_to_onion_skin
+
+ expect(find('.onion-skin-frame .frame.added', visible: false)['style']).to match('opacity: 1;')
+ end
+ end
+
+ describe 'changes tab image diff' do
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project, target_branch: 'master', source_branch: 'deleted-image-test', author: user) }
+
+ before do
+ visit diffs_project_merge_request_path(project, merge_request)
+ click_link "Changes"
+ end
+
+ def set_image_diff_sources
+ # set path of added and deleted images to something the spec can view
+ page.execute_script("document.querySelector('.frame.added img').src = '/apple-touch-icon.png';")
+ page.execute_script("document.querySelector('.frame.deleted img').src = '/favicon.png';")
+
+ wait_for_requests
+
+ expect(find('.frame.added img', visible: false)['src']).to match('/apple-touch-icon.png')
+ expect(find('.frame.deleted img', visible: false)['src']).to match('/favicon.png')
+ end
+
+ def switch_to_swipe_view
+ # it isn't given the .swipe class in the merge request diff
+ find('.view-modes-menu li:nth-child(2)').click
+ expect(find('.view-modes-menu li.active')).to have_content('Swipe')
+
+ set_image_diff_sources
+ end
+
+ def switch_to_onion_skin
+ # it isn't given the .onion-skin class in the merge request diff
+ find('.view-modes-menu li:nth-child(3)').click
+ expect(find('.view-modes-menu li.active')).to have_content('Onion skin')
+
+ set_image_diff_sources
+ end
+
+ describe 'onion skin' do
+ before do
+ switch_to_onion_skin
+ end
+
+ it_behaves_like 'onion skin'
+ end
+
+ describe 'swipe view' do
+ before do
+ switch_to_swipe_view
+ end
+
+ it_behaves_like 'swipe view'
+ end
+ end
+
+ describe 'image view modes' do
+ before do
+ visit project_commit_path(project, '2f63565e7aac07bcdadb654e253078b727143ec4')
+ end
+
+ def switch_to_swipe_view
find('.view-modes-menu .swipe').click
+ end
+
+ def switch_to_onion_skin
find('.view-modes-menu .onion-skin').click
+ end
- expect(find('.onion-skin-frame .frame.added', visible: false)['style']).to match('opacity: 1;')
+ describe 'onion skin' do
+ before do
+ switch_to_onion_skin
+ end
+
+ it 'resizes image' do
+ expect(find('.onion-skin-frame')['style']).to match('width: 228px; height: 240px;')
+ end
+
+ it_behaves_like 'onion skin'
+ end
+
+ describe 'swipe view' do
+ before do
+ switch_to_swipe_view
+ end
+
+ it_behaves_like 'swipe view'
end
end
@@ -223,7 +313,7 @@ describe 'Merge request > User creates image diff notes', :js do
def create_image_diff_note
expand_text = 'Click to expand it.'
- page.all('a', text: expand_text).each do |element|
+ page.all('a', text: expand_text, wait: false).each do |element|
element.click
end
@@ -232,4 +322,8 @@ describe 'Merge request > User creates image diff notes', :js do
click_button 'Comment'
wait_for_requests
end
+
+ def left_position(element)
+ page.evaluate_script("document.querySelectorAll('#{element}')[0].getBoundingClientRect().left;")
+ end
end
diff --git a/spec/features/merge_request/user_creates_merge_request_spec.rb b/spec/features/merge_request/user_creates_merge_request_spec.rb
index bcc11217389..d05ef2a8f12 100644
--- a/spec/features/merge_request/user_creates_merge_request_spec.rb
+++ b/spec/features/merge_request/user_creates_merge_request_spec.rb
@@ -8,8 +8,6 @@ describe "User creates a merge request", :js do
let(:user) { create(:user) }
before do
- stub_feature_flags(approval_rules: false)
-
project.add_maintainer(user)
sign_in(user)
end
diff --git a/spec/features/merge_request/user_merges_merge_request_spec.rb b/spec/features/merge_request/user_merges_merge_request_spec.rb
index 6539e6e9208..da15a4bda4b 100644
--- a/spec/features/merge_request/user_merges_merge_request_spec.rb
+++ b/spec/features/merge_request/user_merges_merge_request_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "spec_helper"
describe "User merges a merge request", :js do
diff --git a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
index 6e54aa6006b..586b3ba170d 100644
--- a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
+++ b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
@@ -52,7 +52,7 @@ describe 'Merge request > User merges when pipeline succeeds', :js do
# so we have to wait for asynchronous call to reload it
# and have_content expectation handles that.
#
- expect(page).to have_content "Pipeline ##{pipeline.id} running"
+ expect(page).to have_content "Pipeline ##{pipeline.id} (##{pipeline.iid}) running"
end
it_behaves_like 'Merge when pipeline succeeds activator'
@@ -74,11 +74,12 @@ describe 'Merge request > User merges when pipeline succeeds', :js do
source_project: project,
title: 'Bug NS-04',
author: user,
- merge_user: user,
- merge_params: { force_remove_source_branch: '1' })
+ merge_user: user)
end
before do
+ merge_request.merge_params['force_remove_source_branch'] = '0'
+ merge_request.save!
click_link "Cancel automatic merge"
end
@@ -102,11 +103,11 @@ describe 'Merge request > User merges when pipeline succeeds', :js do
context 'when merge when pipeline succeeds is enabled' do
let(:merge_request) do
- create(:merge_request_with_diffs, :simple, source_project: project,
- author: user,
- merge_user: user,
- title: 'MepMep',
- merge_when_pipeline_succeeds: true)
+ create(:merge_request_with_diffs, :simple, :merge_when_pipeline_succeeds,
+ source_project: project,
+ author: user,
+ merge_user: user,
+ title: 'MepMep')
end
let!(:build) do
create(:ci_build, pipeline: pipeline)
@@ -158,8 +159,8 @@ describe 'Merge request > User merges when pipeline succeeds', :js do
# Wait for the `ci_status` and `merge_check` requests
wait_for_requests
- page.within('.mr-widget-body') do
- expect(page).to have_content('Something went wrong')
+ page.within('.mr-section-container') do
+ expect(page).to have_content('Merge failed: Something went wrong')
end
end
end
@@ -177,8 +178,8 @@ describe 'Merge request > User merges when pipeline succeeds', :js do
# Wait for the `ci_status` and `merge_check` requests
wait_for_requests
- page.within('.mr-widget-body') do
- expect(page).to have_content('Something went wrong')
+ page.within('.mr-section-container') do
+ expect(page).to have_content('Merge failed: Something went wrong')
end
end
end
diff --git a/spec/features/merge_request/user_sees_diff_spec.rb b/spec/features/merge_request/user_sees_diff_spec.rb
index 04b07525919..8dc5912b8be 100644
--- a/spec/features/merge_request/user_sees_diff_spec.rb
+++ b/spec/features/merge_request/user_sees_diff_spec.rb
@@ -43,8 +43,7 @@ describe 'Merge request > User sees diff', :js do
visit diffs_project_merge_request_path(project, merge_request)
page.within('.alert') do
- expect(page).to have_text("Too many changes to show. Plain diff Email patch To preserve
- performance only 3 of 3+ files are displayed.")
+ expect(page).to have_text("Too many changes to show. Plain diff Email patch To preserve performance only 3 of 3+ files are displayed.")
end
end
end
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index 40ba676ff92..393077a916f 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -160,7 +160,7 @@ describe 'Merge request > User sees merge widget', :js do
it 'shows head pipeline information' do
within '.ci-widget-content' do
- expect(page).to have_content("Pipeline ##{pipeline.id} pending " \
+ expect(page).to have_content("Pipeline ##{pipeline.id} (##{pipeline.iid}) pending " \
"for #{pipeline.short_sha} " \
"on #{pipeline.ref}")
end
@@ -189,7 +189,7 @@ describe 'Merge request > User sees merge widget', :js do
it 'shows head pipeline information' do
within '.ci-widget-content' do
- expect(page).to have_content("Pipeline ##{pipeline.id} pending " \
+ expect(page).to have_content("Pipeline ##{pipeline.id} (##{pipeline.iid}) pending " \
"for #{pipeline.short_sha} " \
"on #{merge_request.to_reference} " \
"with #{merge_request.source_branch}")
@@ -201,7 +201,7 @@ describe 'Merge request > User sees merge widget', :js do
it 'shows head pipeline information' do
within '.ci-widget-content' do
- expect(page).to have_content("Pipeline ##{pipeline.id} pending " \
+ expect(page).to have_content("Pipeline ##{pipeline.id} (##{pipeline.iid}) pending " \
"for #{pipeline.short_sha} " \
"on #{merge_request.to_reference} " \
"with #{merge_request.source_branch}")
@@ -234,7 +234,7 @@ describe 'Merge request > User sees merge widget', :js do
it 'shows head pipeline information' do
within '.ci-widget-content' do
- expect(page).to have_content("Pipeline ##{pipeline.id} pending " \
+ expect(page).to have_content("Pipeline ##{pipeline.id} (##{pipeline.iid}) pending " \
"for #{pipeline.short_sha} " \
"on #{merge_request.to_reference} " \
"with #{merge_request.source_branch} " \
@@ -248,7 +248,7 @@ describe 'Merge request > User sees merge widget', :js do
it 'shows head pipeline information' do
within '.ci-widget-content' do
- expect(page).to have_content("Pipeline ##{pipeline.id} pending " \
+ expect(page).to have_content("Pipeline ##{pipeline.id} (##{pipeline.iid}) pending " \
"for #{pipeline.short_sha} " \
"on #{merge_request.to_reference} " \
"with #{merge_request.source_branch} " \
@@ -314,7 +314,8 @@ describe 'Merge request > User sees merge widget', :js do
context 'view merge request with MWPS enabled but automatically merge fails' do
before do
merge_request.update(
- merge_when_pipeline_succeeds: true,
+ auto_merge_enabled: true,
+ auto_merge_strategy: AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS,
merge_user: merge_request.author,
merge_error: 'Something went wrong'
)
@@ -326,8 +327,8 @@ describe 'Merge request > User sees merge widget', :js do
# Wait for the `ci_status` and `merge_check` requests
wait_for_requests
- page.within('.mr-widget-body') do
- expect(page).to have_content('Something went wrong')
+ page.within('.mr-section-container') do
+ expect(page).to have_content('Merge failed: Something went wrong')
end
end
end
@@ -347,8 +348,8 @@ describe 'Merge request > User sees merge widget', :js do
# Wait for the `ci_status` and `merge_check` requests
wait_for_requests
- page.within('.mr-widget-body') do
- expect(page).to have_content('Something went wrong')
+ page.within('.mr-section-container') do
+ expect(page).to have_content('Merge failed: Something went wrong')
end
end
end
@@ -564,7 +565,7 @@ describe 'Merge request > User sees merge widget', :js do
click_button 'subtractTest'
expect(page).to have_content('6.66')
- expect(page).to have_content(sample_java_failed_message)
+ expect(page).to have_content(sample_java_failed_message.gsub!(/\s+/, ' ').strip)
end
end
end
@@ -609,7 +610,7 @@ describe 'Merge request > User sees merge widget', :js do
click_button 'Test#sum when a is 2 and b is 2 returns summary'
expect(page).to have_content('2.22')
- expect(page).to have_content(sample_rspec_failed_message)
+ expect(page).to have_content(sample_rspec_failed_message.gsub!(/\s+/, ' ').strip)
end
end
end
@@ -670,4 +671,26 @@ describe 'Merge request > User sees merge widget', :js do
end
end
end
+
+ context 'when MR has pipeline but user does not have permission' do
+ let(:sha) { project.commit(merge_request.source_branch).sha }
+ let!(:pipeline) { create(:ci_pipeline_without_jobs, status: 'success', sha: sha, project: project, ref: merge_request.source_branch) }
+
+ before do
+ project.update(
+ visibility_level: Gitlab::VisibilityLevel::PUBLIC,
+ public_builds: false
+ )
+ merge_request.update!(head_pipeline: pipeline)
+ sign_out(:user)
+
+ visit project_merge_request_path(project, merge_request)
+ end
+
+ it 'renders a CI pipeline error' do
+ within '.ci-widget' do
+ expect(page).to have_content('Could not retrieve the pipeline status.')
+ end
+ end
+ end
end
diff --git a/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb b/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb
index 5188dc3625f..dd8900a3698 100644
--- a/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb
+++ b/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb
@@ -27,7 +27,8 @@ describe 'Merge request < User sees mini pipeline graph', :js do
let(:artifacts_file2) { fixture_file_upload(File.join('spec/fixtures/dk.png'), 'image/png') }
before do
- create(:ci_build, :success, :trace_artifact, pipeline: pipeline, legacy_artifacts_file: artifacts_file1)
+ job = create(:ci_build, :success, :trace_artifact, pipeline: pipeline)
+ create(:ci_job_artifact, :archive, file: artifacts_file1, job: job)
create(:ci_build, :manual, pipeline: pipeline, when: 'manual')
end
@@ -35,7 +36,8 @@ describe 'Merge request < User sees mini pipeline graph', :js do
xit 'avoids repeated database queries' do
before = ActiveRecord::QueryRecorder.new { visit_merge_request(format: :json, serializer: 'widget') }
- create(:ci_build, :success, :trace_artifact, pipeline: pipeline, legacy_artifacts_file: artifacts_file2)
+ job = create(:ci_build, :success, :trace_artifact, pipeline: pipeline)
+ create(:ci_job_artifact, :archive, file: artifacts_file2, job: job)
create(:ci_build, :manual, pipeline: pipeline, when: 'manual')
after = ActiveRecord::QueryRecorder.new { visit_merge_request(format: :json, serializer: 'widget') }
diff --git a/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb b/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb
index 1b5dd6945e0..780de76d2c5 100644
--- a/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb
+++ b/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb
@@ -7,8 +7,8 @@ describe 'User comments on a diff', :js do
include RepoHelpers
def expect_suggestion_has_content(element, expected_changing_content, expected_suggested_content)
- changing_content = element.all(:css, '.line_holder.old').map(&:text)
- suggested_content = element.all(:css, '.line_holder.new').map(&:text)
+ changing_content = element.all(:css, '.line_holder.old').map { |el| el.text(normalize_ws: true) }
+ suggested_content = element.all(:css, '.line_holder.new').map { |el| el.text(normalize_ws: true) }
expect(changing_content).to eq(expected_changing_content)
expect(suggested_content).to eq(expected_suggested_content)
@@ -121,7 +121,7 @@ describe 'User comments on a diff', :js do
end
context 'multi-line suggestions' do
- it 'suggestion is presented' do
+ before do
click_diff_line(find("[id='#{sample_compare.changes[1][:line_code]}']"))
page.within('.js-discussion-note-form') do
@@ -130,7 +130,9 @@ describe 'User comments on a diff', :js do
end
wait_for_requests
+ end
+ it 'suggestion is presented' do
page.within('.diff-discussions') do
expect(page).to have_button('Apply suggestion')
expect(page).to have_content('Suggested change')
@@ -160,22 +162,24 @@ describe 'User comments on a diff', :js do
end
it 'suggestion is appliable' do
- click_diff_line(find("[id='#{sample_compare.changes[1][:line_code]}']"))
+ page.within('.diff-discussions') do
+ expect(page).not_to have_content('Applied')
- page.within('.js-discussion-note-form') do
- fill_in('note_note', with: "```suggestion:-3+5\n# change to a\n# comment\n# with\n# broken\n# lines\n```")
- click_button('Comment')
- end
+ click_button('Apply suggestion')
+ wait_for_requests
- wait_for_requests
+ expect(page).to have_content('Applied')
+ end
+ end
+ it 'resolves discussion when applied' do
page.within('.diff-discussions') do
- expect(page).not_to have_content('Applied')
+ expect(page).not_to have_content('Unresolve discussion')
click_button('Apply suggestion')
wait_for_requests
- expect(page).to have_content('Applied')
+ expect(page).to have_content('Unresolve discussion')
end
end
end
diff --git a/spec/features/merge_requests/user_lists_merge_requests_spec.rb b/spec/features/merge_requests/user_lists_merge_requests_spec.rb
index bd91fae1453..2dee0e26954 100644
--- a/spec/features/merge_requests/user_lists_merge_requests_spec.rb
+++ b/spec/features/merge_requests/user_lists_merge_requests_spec.rb
@@ -33,7 +33,7 @@ describe 'Merge requests > User lists merge requests' do
end
it 'filters on no assignee' do
- visit_merge_requests(project, assignee_id: IssuableFinder::NONE)
+ visit_merge_requests(project, assignee_id: IssuableFinder::FILTER_NONE)
expect(current_path).to eq(project_merge_requests_path(project))
expect(page).to have_content 'merge-test'
diff --git a/spec/features/oauth_login_spec.rb b/spec/features/oauth_login_spec.rb
index f4105730402..5ebfc32952d 100644
--- a/spec/features/oauth_login_spec.rb
+++ b/spec/features/oauth_login_spec.rb
@@ -14,7 +14,7 @@ describe 'OAuth Login', :js, :allow_forgery_protection do
end
providers = [:github, :twitter, :bitbucket, :gitlab, :google_oauth2,
- :facebook, :cas3, :auth0, :authentiq]
+ :facebook, :cas3, :auth0, :authentiq, :salesforce]
before(:all) do
# The OmniAuth `full_host` parameter doesn't get set correctly (it gets set to something like `http://localhost`
diff --git a/spec/features/profiles/user_edit_preferences_spec.rb b/spec/features/profiles/user_edit_preferences_spec.rb
new file mode 100644
index 00000000000..2d2da222998
--- /dev/null
+++ b/spec/features/profiles/user_edit_preferences_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe 'User edit preferences profile' do
+ let(:user) { create(:user) }
+
+ before do
+ stub_feature_flags(user_time_settings: true)
+ sign_in(user)
+ visit(profile_preferences_path)
+ end
+
+ it 'allows the user to toggle their time format preference' do
+ field = page.find_field("user[time_format_in_24h]")
+
+ expect(field).not_to be_checked
+
+ field.click
+
+ expect(field).to be_checked
+ end
+
+ it 'allows the user to toggle their time display preference' do
+ field = page.find_field("user[time_display_relative]")
+
+ expect(field).to be_checked
+
+ field.click
+
+ expect(field).not_to be_checked
+ end
+end
diff --git a/spec/features/profiles/user_edit_profile_spec.rb b/spec/features/profiles/user_edit_profile_spec.rb
index b43711f6ef6..a53da94ef7d 100644
--- a/spec/features/profiles/user_edit_profile_spec.rb
+++ b/spec/features/profiles/user_edit_profile_spec.rb
@@ -327,5 +327,37 @@ describe 'User edit profile' do
end
end
end
+
+ context 'User time preferences', :js do
+ let(:issue) { create(:issue, project: project)}
+ let(:project) { create(:project) }
+
+ before do
+ stub_feature_flags(user_time_settings: true)
+ end
+
+ it 'shows the user time preferences form' do
+ expect(page).to have_content('Time settings')
+ end
+
+ it 'allows the user to select a time zone from a dropdown list of options' do
+ expect(page.find('.user-time-preferences .dropdown')).not_to have_css('.show')
+
+ page.find('.user-time-preferences .js-timezone-dropdown').click
+
+ expect(page.find('.user-time-preferences .dropdown')).to have_css('.show')
+
+ page.find("a", text: "Nuku'alofa").click
+
+ tz = page.find('.user-time-preferences #user_timezone', visible: false)
+
+ expect(tz.value).to eq('Pacific/Tongatapu')
+ end
+
+ it 'timezone defaults to servers default' do
+ timezone_name = Time.zone.tzinfo.name
+ expect(page.find('.user-time-preferences #user_timezone', visible: false).value).to eq(timezone_name)
+ end
+ end
end
end
diff --git a/spec/features/project_variables_spec.rb b/spec/features/project_variables_spec.rb
index 76abc640077..95685a3c7ff 100644
--- a/spec/features/project_variables_spec.rb
+++ b/spec/features/project_variables_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'Project variables', :js do
diff --git a/spec/features/projects/branches/download_buttons_spec.rb b/spec/features/projects/branches/download_buttons_spec.rb
index c8dc72a34ec..3e75890725e 100644
--- a/spec/features/projects/branches/download_buttons_spec.rb
+++ b/spec/features/projects/branches/download_buttons_spec.rb
@@ -35,7 +35,7 @@ describe 'Download buttons in branches page' do
it 'shows download artifacts button' do
href = latest_succeeded_project_artifacts_path(project, 'binary-encoding/download', job: 'build')
- expect(page).to have_link "Download '#{build.name}'", href: href
+ expect(page).to have_link build.name, href: href
end
end
end
diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb
index fe4f737a7da..31cc09ae911 100644
--- a/spec/features/projects/clusters/user_spec.rb
+++ b/spec/features/projects/clusters/user_spec.rb
@@ -12,6 +12,7 @@ describe 'User Cluster', :js do
allow(Projects::ClustersController).to receive(:STATUS_POLLING_INTERVAL) { 100 }
allow_any_instance_of(Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService).to receive(:execute)
+ allow_any_instance_of(Clusters::Cluster).to receive(:retrieve_connection_status).and_return(:connected)
end
context 'when user does not have a cluster and visits cluster index page' do
diff --git a/spec/features/projects/clusters_spec.rb b/spec/features/projects/clusters_spec.rb
index a85e7333ba8..ce382c19fc1 100644
--- a/spec/features/projects/clusters_spec.rb
+++ b/spec/features/projects/clusters_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'Clusters', :js do
diff --git a/spec/features/projects/commits/user_browses_commits_spec.rb b/spec/features/projects/commits/user_browses_commits_spec.rb
index 574a8aefd63..a84fee34669 100644
--- a/spec/features/projects/commits/user_browses_commits_spec.rb
+++ b/spec/features/projects/commits/user_browses_commits_spec.rb
@@ -13,7 +13,7 @@ describe 'User browses commits' do
it 'renders commit' do
visit project_commit_path(project, sample_commit.id)
- expect(page).to have_content(sample_commit.message)
+ expect(page).to have_content(sample_commit.message.gsub!(/\s+/, ' '))
.and have_content("Showing #{sample_commit.files_changed_count} changed files")
.and have_content('Side-by-side')
end
@@ -61,7 +61,7 @@ describe 'User browses commits' do
it 'renders commit ci info' do
visit project_commit_path(project, sample_commit.id)
- expect(page).to have_content "Pipeline ##{pipeline.id} pending"
+ expect(page).to have_content "Pipeline ##{pipeline.id} (##{pipeline.iid}) pending"
end
end
diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb
index ab16fdee883..254e885ce46 100644
--- a/spec/features/projects/features_visibility_spec.rb
+++ b/spec/features/projects/features_visibility_spec.rb
@@ -68,7 +68,8 @@ describe 'Edit Project Settings' do
end
it "hides builds when disabled" do
- allow(Ability).to receive(:allowed?).with(member, :read_builds, project).and_return(false)
+ allow(Ability).to receive(:allowed?).and_return(true)
+ allow(Ability).to receive(:allowed?).with(member, :read_build, project).and_return(false)
visit project_pipelines_path(project)
diff --git a/spec/features/projects/files/download_buttons_spec.rb b/spec/features/projects/files/download_buttons_spec.rb
index 03cb3530e2b..111972a6b00 100644
--- a/spec/features/projects/files/download_buttons_spec.rb
+++ b/spec/features/projects/files/download_buttons_spec.rb
@@ -30,7 +30,7 @@ describe 'Projects > Files > Download buttons in files tree' do
it 'shows download artifacts button' do
href = latest_succeeded_project_artifacts_path(project, "#{project.default_branch}/download", job: 'build')
- expect(page).to have_link "Download '#{build.name}'", href: href
+ expect(page).to have_link build.name, href: href
end
end
end
diff --git a/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb b/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb
index b6dbf76bc9b..51c884201a6 100644
--- a/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb
+++ b/spec/features/projects/files/files_sort_submodules_with_folders_spec.rb
@@ -5,6 +5,8 @@ describe 'Projects > Files > User views files page' do
let(:user) { project.owner }
before do
+ stub_feature_flags(vue_file_list: false)
+
sign_in user
visit project_tree_path(project, project.repository.root_ref)
end
diff --git a/spec/features/projects/files/project_owner_creates_license_file_spec.rb b/spec/features/projects/files/project_owner_creates_license_file_spec.rb
index 6762460971f..44715261b8b 100644
--- a/spec/features/projects/files/project_owner_creates_license_file_spec.rb
+++ b/spec/features/projects/files/project_owner_creates_license_file_spec.rb
@@ -5,6 +5,7 @@ describe 'Projects > Files > Project owner creates a license file', :js do
let(:project_maintainer) { project.owner }
before do
+ stub_feature_flags(vue_file_list: false)
project.repository.delete_file(project_maintainer, 'LICENSE',
message: 'Remove LICENSE', branch_name: 'master')
sign_in(project_maintainer)
diff --git a/spec/features/projects/files/undo_template_spec.rb b/spec/features/projects/files/undo_template_spec.rb
index fa785ed10ef..91618145391 100644
--- a/spec/features/projects/files/undo_template_spec.rb
+++ b/spec/features/projects/files/undo_template_spec.rb
@@ -50,7 +50,7 @@ end
def check_content_reverted(template_content)
find('.template-selectors-undo-menu .btn-info').click
expect(page).not_to have_content(template_content)
- expect(find('.template-type-selector .dropdown-toggle-text')).to have_content
+ expect(page).to have_css('.template-type-selector .dropdown-toggle-text')
end
def select_file_template(template_selector_selector, template_name)
diff --git a/spec/features/projects/files/user_browses_files_spec.rb b/spec/features/projects/files/user_browses_files_spec.rb
index 66268355345..a5d849db8a3 100644
--- a/spec/features/projects/files/user_browses_files_spec.rb
+++ b/spec/features/projects/files/user_browses_files_spec.rb
@@ -11,6 +11,7 @@ describe "User browses files" do
let(:user) { project.owner }
before do
+ stub_feature_flags(vue_file_list: false)
stub_feature_flags(csslab: false)
sign_in(user)
end
diff --git a/spec/features/projects/files/user_browses_lfs_files_spec.rb b/spec/features/projects/files/user_browses_lfs_files_spec.rb
index d56476adb05..d5cb8f9212d 100644
--- a/spec/features/projects/files/user_browses_lfs_files_spec.rb
+++ b/spec/features/projects/files/user_browses_lfs_files_spec.rb
@@ -5,6 +5,8 @@ describe 'Projects > Files > User browses LFS files' do
let(:user) { project.owner }
before do
+ stub_feature_flags(vue_file_list: false)
+
sign_in(user)
end
diff --git a/spec/features/projects/files/user_creates_directory_spec.rb b/spec/features/projects/files/user_creates_directory_spec.rb
index 847b5f0860f..e29e867492e 100644
--- a/spec/features/projects/files/user_creates_directory_spec.rb
+++ b/spec/features/projects/files/user_creates_directory_spec.rb
@@ -11,6 +11,8 @@ describe 'Projects > Files > User creates a directory', :js do
let(:user) { create(:user) }
before do
+ stub_feature_flags(vue_file_list: false)
+
project.add_developer(user)
sign_in(user)
visit project_tree_path(project, 'master')
diff --git a/spec/features/projects/files/user_creates_files_spec.rb b/spec/features/projects/files/user_creates_files_spec.rb
index dd2964c2186..264b288ab38 100644
--- a/spec/features/projects/files/user_creates_files_spec.rb
+++ b/spec/features/projects/files/user_creates_files_spec.rb
@@ -12,6 +12,7 @@ describe 'Projects > Files > User creates files' do
let(:user) { create(:user) }
before do
+ stub_feature_flags(vue_file_list: false)
stub_feature_flags(web_ide_default: false)
project.add_maintainer(user)
@@ -173,7 +174,6 @@ describe 'Projects > Files > User creates files' do
it 'creates and commit new file in forked project', :js do
expect(page).to have_selector('.file-editor')
- expect(page).to have_content
find('#editor')
execute_script("ace.edit('editor').setValue('*.rbca')")
diff --git a/spec/features/projects/files/user_deletes_files_spec.rb b/spec/features/projects/files/user_deletes_files_spec.rb
index 614b11fa5c8..11ee87f245b 100644
--- a/spec/features/projects/files/user_deletes_files_spec.rb
+++ b/spec/features/projects/files/user_deletes_files_spec.rb
@@ -12,6 +12,8 @@ describe 'Projects > Files > User deletes files', :js do
let(:user) { create(:user) }
before do
+ stub_feature_flags(vue_file_list: false)
+
sign_in(user)
end
diff --git a/spec/features/projects/files/user_edits_files_spec.rb b/spec/features/projects/files/user_edits_files_spec.rb
index ec3930c26db..683268d064a 100644
--- a/spec/features/projects/files/user_edits_files_spec.rb
+++ b/spec/features/projects/files/user_edits_files_spec.rb
@@ -10,6 +10,7 @@ describe 'Projects > Files > User edits files', :js do
before do
stub_feature_flags(web_ide_default: false)
+ stub_feature_flags(vue_file_list: false)
sign_in(user)
end
diff --git a/spec/features/projects/files/user_replaces_files_spec.rb b/spec/features/projects/files/user_replaces_files_spec.rb
index e3da28d73c3..bfd612e4cc8 100644
--- a/spec/features/projects/files/user_replaces_files_spec.rb
+++ b/spec/features/projects/files/user_replaces_files_spec.rb
@@ -14,6 +14,8 @@ describe 'Projects > Files > User replaces files', :js do
let(:user) { create(:user) }
before do
+ stub_feature_flags(vue_file_list: false)
+
sign_in(user)
end
diff --git a/spec/features/projects/files/user_uploads_files_spec.rb b/spec/features/projects/files/user_uploads_files_spec.rb
index af3fc528a20..25ff3fdf411 100644
--- a/spec/features/projects/files/user_uploads_files_spec.rb
+++ b/spec/features/projects/files/user_uploads_files_spec.rb
@@ -14,6 +14,8 @@ describe 'Projects > Files > User uploads files' do
let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) }
before do
+ stub_feature_flags(vue_file_list: false)
+
project.add_maintainer(user)
sign_in(user)
end
diff --git a/spec/features/projects/import_export/export_file_spec.rb b/spec/features/projects/import_export/export_file_spec.rb
index f76f9ba7577..9d74a96ab3d 100644
--- a/spec/features/projects/import_export/export_file_spec.rb
+++ b/spec/features/projects/import_export/export_file_spec.rb
@@ -12,7 +12,7 @@ describe 'Import/Export - project export integration test', :js do
let(:export_path) { "#{Dir.tmpdir}/import_file_spec" }
let(:config_hash) { YAML.load_file(Gitlab::ImportExport.config_file).deep_stringify_keys }
- let(:sensitive_words) { %w[pass secret token key encrypted] }
+ let(:sensitive_words) { %w[pass secret token key encrypted html] }
let(:safe_list) do
{
token: [ProjectHook, Ci::Trigger, CommitStatus],
diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb
index 28ae90bc0de..8d2b1fc7e30 100644
--- a/spec/features/projects/import_export/import_file_spec.rb
+++ b/spec/features/projects/import_export/import_file_spec.rb
@@ -47,7 +47,6 @@ describe 'Import/Export - project import integration test', :js do
expect(project.description).to eq("Foo Bar")
expect(project.issues).not_to be_empty
expect(project.merge_requests).not_to be_empty
- expect(project_hook_exists?(project)).to be true
expect(wiki_exists?(project)).to be true
expect(project.import_state.status).to eq('finished')
end
diff --git a/spec/features/projects/jobs/permissions_spec.rb b/spec/features/projects/jobs/permissions_spec.rb
index 6ce37297a7e..b5e711997a0 100644
--- a/spec/features/projects/jobs/permissions_spec.rb
+++ b/spec/features/projects/jobs/permissions_spec.rb
@@ -90,7 +90,7 @@ describe 'Project Jobs Permissions' do
before do
archive = fixture_file_upload('spec/fixtures/ci_build_artifacts.zip')
- job.update(legacy_artifacts_file: archive)
+ create(:ci_job_artifact, :archive, file: archive, job: job)
end
context 'when public access for jobs is disabled' do
diff --git a/spec/features/projects/jobs/user_browses_job_spec.rb b/spec/features/projects/jobs/user_browses_job_spec.rb
index 908c616f2fc..54b462da87a 100644
--- a/spec/features/projects/jobs/user_browses_job_spec.rb
+++ b/spec/features/projects/jobs/user_browses_job_spec.rb
@@ -28,8 +28,8 @@ describe 'User browses a job', :js do
expect(page).to have_no_css('.artifacts')
expect(build).not_to have_trace
- expect(build.artifacts_file.exists?).to be_falsy
- expect(build.artifacts_metadata.exists?).to be_falsy
+ expect(build.artifacts_file.present?).to be_falsy
+ expect(build.artifacts_metadata.present?).to be_falsy
expect(page).to have_content('Job has been erased')
end
diff --git a/spec/features/projects/jobs/user_browses_jobs_spec.rb b/spec/features/projects/jobs/user_browses_jobs_spec.rb
index ebc20d15d67..bd6c73f4b85 100644
--- a/spec/features/projects/jobs/user_browses_jobs_spec.rb
+++ b/spec/features/projects/jobs/user_browses_jobs_spec.rb
@@ -16,6 +16,12 @@ describe 'User browses jobs' do
visit(project_jobs_path(project))
end
+ it 'shows pipeline id and IID' do
+ page.within('td.pipeline-link') do
+ expect(page).to have_content("##{pipeline.id} (##{pipeline.iid})")
+ end
+ end
+
it 'shows the coverage' do
page.within('td.coverage') do
expect(page).to have_content('99.9%')
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index 224375daf71..03562bd382e 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -129,7 +129,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
visit project_job_path(project, job)
within '.js-pipeline-info' do
- expect(page).to have_content("Pipeline ##{pipeline.id} for #{pipeline.ref}")
+ expect(page).to have_content("Pipeline ##{pipeline.id} (##{pipeline.iid}) for #{pipeline.ref}")
end
end
@@ -314,7 +314,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
context "Download artifacts", :js do
before do
- job.update(legacy_artifacts_file: artifacts_file)
+ create(:ci_job_artifact, :archive, file: artifacts_file, job: job)
visit project_job_path(project, job)
end
@@ -338,8 +338,8 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
context 'Artifacts expire date', :js do
before do
- job.update(legacy_artifacts_file: artifacts_file,
- artifacts_expire_at: expire_at)
+ create(:ci_job_artifact, :archive, file: artifacts_file, expire_at: expire_at, job: job)
+ job.update!(artifacts_expire_at: expire_at)
visit project_job_path(project, job)
end
@@ -981,7 +981,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
describe "GET /:project/jobs/:id/download", :js do
before do
- job.update(legacy_artifacts_file: artifacts_file)
+ create(:ci_job_artifact, :archive, file: artifacts_file, job: job)
visit project_job_path(project, job)
click_link 'Download'
@@ -989,7 +989,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
context "Build from other project" do
before do
- job2.update(legacy_artifacts_file: artifacts_file)
+ create(:ci_job_artifact, :archive, file: artifacts_file, job: job2)
end
it do
diff --git a/spec/features/projects/labels/update_prioritization_spec.rb b/spec/features/projects/labels/update_prioritization_spec.rb
index d36f043f880..f32b155790f 100644
--- a/spec/features/projects/labels/update_prioritization_spec.rb
+++ b/spec/features/projects/labels/update_prioritization_spec.rb
@@ -138,29 +138,41 @@ describe 'Prioritize labels' do
end
context 'as a guest' do
- it 'does not prioritize labels' do
+ before do
+ create(:label_priority, project: project, label: bug, priority: 1)
+ create(:label_priority, project: project, label: feature, priority: 2)
+
guest = create(:user)
sign_in guest
visit project_labels_path(project)
+ end
+ it 'cannot prioritize labels' do
expect(page).to have_content 'bug'
expect(page).to have_content 'wontfix'
expect(page).to have_content 'feature'
- expect(page).not_to have_css('.prioritized-labels')
expect(page).not_to have_content 'Star a label'
end
+
+ it 'cannot sort prioritized labels', :js do
+ drag_to(selector: '.prioritized-labels .label-list-item', from_index: 1, to_index: 2)
+
+ page.within('.prioritized-labels') do
+ expect(first('.label-list-item')).to have_content('bug')
+ expect(page.all('.label-list-item').last).to have_content('feature')
+ end
+ end
end
context 'as a non signed in user' do
- it 'does not prioritize labels' do
+ it 'cannot prioritize labels' do
visit project_labels_path(project)
expect(page).to have_content 'bug'
expect(page).to have_content 'wontfix'
expect(page).to have_content 'feature'
- expect(page).not_to have_css('.prioritized-labels')
expect(page).not_to have_content 'Star a label'
end
end
diff --git a/spec/features/projects/labels/user_promotes_label_spec.rb b/spec/features/projects/labels/user_promotes_label_spec.rb
new file mode 100644
index 00000000000..fdecafd4c50
--- /dev/null
+++ b/spec/features/projects/labels/user_promotes_label_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'User promotes label' do
+ set(:group) { create(:group) }
+ set(:user) { create(:user) }
+ set(:project) { create(:project, namespace: group) }
+ set(:label) { create(:label, project: project) }
+
+ context 'when user can admin group labels' do
+ before do
+ group.add_developer(user)
+ sign_in(user)
+ visit(project_labels_path(project))
+ end
+
+ it "shows label promote button" do
+ expect(page).to have_selector('.js-promote-project-label-button')
+ end
+ end
+
+ context 'when user cannot admin group labels' do
+ before do
+ project.add_developer(user)
+ sign_in(user)
+ visit(project_labels_path(project))
+ end
+
+ it "does not show label promote button" do
+ expect(page).not_to have_selector('.js-promote-project-label-button')
+ end
+ end
+end
diff --git a/spec/features/projects/labels/user_removes_labels_spec.rb b/spec/features/projects/labels/user_removes_labels_spec.rb
index b0ce03a1c31..7f49ddf560f 100644
--- a/spec/features/projects/labels/user_removes_labels_spec.rb
+++ b/spec/features/projects/labels/user_removes_labels_spec.rb
@@ -21,8 +21,11 @@ describe "User removes labels" do
page.first(".label-list-item") do
first('.js-label-options-dropdown').click
first(".remove-row").click
- first(:link, "Delete label").click
end
+
+ expect(page).to have_content("#{label.title} will be permanently deleted from #{project.name}. This cannot be undone.")
+
+ first(:link, "Delete label").click
end
expect(page).to have_content("Label was removed").and have_no_content(label.title)
@@ -38,7 +41,7 @@ describe "User removes labels" do
it "removes all labels" do
loop do
- li = page.first(".label-list-item")
+ li = page.first(".label-list-item", minimum: 0)
break unless li
li.find('.js-label-options-dropdown').click
diff --git a/spec/features/projects/labels/user_views_labels_spec.rb b/spec/features/projects/labels/user_views_labels_spec.rb
index 2c8267764bd..a6f7968c535 100644
--- a/spec/features/projects/labels/user_views_labels_spec.rb
+++ b/spec/features/projects/labels/user_views_labels_spec.rb
@@ -7,6 +7,7 @@ describe "User views labels" do
set(:user) { create(:user) }
let(:label_titles) { %w[bug enhancement feature] }
+ let!(:prioritized_label) { create(:label, project: project, title: 'prioritized-label-name', priority: 1) }
before do
label_titles.each { |title| create(:label, project: project, title: title) }
@@ -18,6 +19,10 @@ describe "User views labels" do
end
it "shows all labels" do
+ page.within('.prioritized-labels .manage-labels-list') do
+ expect(page).to have_content('prioritized-label-name')
+ end
+
page.within('.other-labels .manage-labels-list') do
label_titles.each { |title| expect(page).to have_content(title) }
end
diff --git a/spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb b/spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb
index 0ab29660189..a645b917568 100644
--- a/spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb
+++ b/spec/features/projects/members/group_member_cannot_leave_group_project_spec.rb
@@ -8,10 +8,17 @@ describe 'Projects > Members > Group member cannot leave group project' do
before do
group.add_developer(user)
sign_in(user)
- visit project_path(project)
end
it 'user does not see a "Leave project" link' do
+ visit project_path(project)
+
expect(page).not_to have_content 'Leave project'
end
+
+ it 'renders a flash message if attempting to leave by url', :js do
+ visit project_path(project, leave: 1)
+
+ expect(find('.flash-alert')).to have_content 'You do not have permission to leave this project'
+ end
end
diff --git a/spec/features/projects/members/member_leaves_project_spec.rb b/spec/features/projects/members/member_leaves_project_spec.rb
index 94b29de4686..bd2ef9c07c4 100644
--- a/spec/features/projects/members/member_leaves_project_spec.rb
+++ b/spec/features/projects/members/member_leaves_project_spec.rb
@@ -7,13 +7,24 @@ describe 'Projects > Members > Member leaves project' do
before do
project.add_developer(user)
sign_in(user)
- visit project_path(project)
end
it 'user leaves project' do
+ visit project_path(project)
+
click_link 'Leave project'
expect(current_path).to eq(dashboard_projects_path)
expect(project.users.exists?(user.id)).to be_falsey
end
+
+ it 'user leaves project by url param', :js do
+ visit project_path(project, leave: 1)
+
+ page.accept_confirm
+
+ expect(find('.flash-notice')).to have_content "You left the \"#{project.full_name}\" project"
+ expect(current_path).to eq(dashboard_projects_path)
+ expect(project.users.exists?(user.id)).to be_falsey
+ end
end
diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb
index b54ea929978..033e1afe866 100644
--- a/spec/features/projects/new_project_spec.rb
+++ b/spec/features/projects/new_project_spec.rb
@@ -63,6 +63,36 @@ describe 'New project' do
end
end
end
+
+ context 'when group visibility is private but default is internal' do
+ before do
+ stub_application_setting(default_project_visibility: Gitlab::VisibilityLevel::INTERNAL)
+ end
+
+ it 'has private selected' do
+ group = create(:group, visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ visit new_project_path(namespace_id: group.id)
+
+ page.within('#blank-project-pane') do
+ expect(find_field("project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).to be_checked
+ end
+ end
+ end
+
+ context 'when group visibility is public but user requests private' do
+ before do
+ stub_application_setting(default_project_visibility: Gitlab::VisibilityLevel::INTERNAL)
+ end
+
+ it 'has private selected' do
+ group = create(:group, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ visit new_project_path(namespace_id: group.id, project: { visibility_level: Gitlab::VisibilityLevel::PRIVATE })
+
+ page.within('#blank-project-pane') do
+ expect(find_field("project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).to be_checked
+ end
+ end
+ end
end
context 'Readme selector' do
diff --git a/spec/features/projects/pages_lets_encrypt_spec.rb b/spec/features/projects/pages_lets_encrypt_spec.rb
new file mode 100644
index 00000000000..baa217cbe58
--- /dev/null
+++ b/spec/features/projects/pages_lets_encrypt_spec.rb
@@ -0,0 +1,131 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe "Pages with Let's Encrypt", :https_pages_enabled do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:role) { :maintainer }
+ let(:certificate_pem) do
+ <<~PEM
+ -----BEGIN CERTIFICATE-----
+ MIICGzCCAYSgAwIBAgIBATANBgkqhkiG9w0BAQUFADAbMRkwFwYDVQQDExB0ZXN0
+ LWNlcnRpZmljYXRlMB4XDTE2MDIxMjE0MzIwMFoXDTIwMDQxMjE0MzIwMFowGzEZ
+ MBcGA1UEAxMQdGVzdC1jZXJ0aWZpY2F0ZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+ gYkCgYEApL4J9L0ZxFJ1hI1LPIflAlAGvm6ZEvoT4qKU5Xf2JgU7/2geNR1qlNFa
+ SvCc08Knupp5yTgmvyK/Xi09U0N82vvp4Zvr/diSc4A/RA6Mta6egLySNT438kdT
+ nY2tR5feoTLwQpX0t4IMlwGQGT5h6Of2fKmDxzuwuyffcIHqLdsCAwEAAaNvMG0w
+ DAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUxl9WSxBprB0z0ibJs3rXEk0+95AwCwYD
+ VR0PBAQDAgXgMBEGCWCGSAGG+EIBAQQEAwIGQDAeBglghkgBhvhCAQ0EERYPeGNh
+ IGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAA4GBAGC4T8SlFHK0yPSa+idGLQFQ
+ joZp2JHYvNlTPkRJ/J4TcXxBTJmArcQgTIuNoBtC+0A/SwdK4MfTCUY4vNWNdese
+ 5A4K65Nb7Oh1AdQieTBHNXXCdyFsva9/ScfQGEl7p55a52jOPs0StPd7g64uvjlg
+ YHi2yesCrOvVXt+lgPTd
+ -----END CERTIFICATE-----
+ PEM
+ end
+
+ let(:certificate_key) do
+ <<~KEY
+ -----BEGIN PRIVATE KEY-----
+ MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKS+CfS9GcRSdYSN
+ SzyH5QJQBr5umRL6E+KilOV39iYFO/9oHjUdapTRWkrwnNPCp7qaeck4Jr8iv14t
+ PVNDfNr76eGb6/3YknOAP0QOjLWunoC8kjU+N/JHU52NrUeX3qEy8EKV9LeCDJcB
+ kBk+Yejn9nypg8c7sLsn33CB6i3bAgMBAAECgYA2D26w80T7WZvazYr86BNMePpd
+ j2mIAqx32KZHzt/lhh40J/SRtX9+Kl0Y7nBoRR5Ja9u/HkAIxNxLiUjwg9r6cpg/
+ uITEF5nMt7lAk391BuI+7VOZZGbJDsq2ulPd6lO+C8Kq/PI/e4kXcIjeH6KwQsuR
+ 5vrXfBZ3sQfflaiN4QJBANBt8JY2LIGQF8o89qwUpRL5vbnKQ4IzZ5+TOl4RLR7O
+ AQpJ81tGuINghO7aunctb6rrcKJrxmEH1whzComybrMCQQDKV49nOBudRBAIgG4K
+ EnLzsRKISUHMZSJiYTYnablof8cKw1JaQduw7zgrUlLwnroSaAGX88+Jw1f5n2Lh
+ Vlg5AkBDdUGnrDLtYBCDEQYZHblrkc7ZAeCllDOWjxUV+uMqlCv8A4Ey6omvY57C
+ m6I8DkWVAQx8VPtozhvHjUw80rZHAkB55HWHAM3h13axKG0htCt7klhPsZHpx6MH
+ EPjGlXIT+aW2XiPmK3ZlCDcWIenE+lmtbOpI159Wpk8BGXs/s/xBAkEAlAY3ymgx
+ 63BDJEwvOb2IaP8lDDxNsXx9XJNVvQbv5n15vNsLHbjslHfAhAbxnLQ1fLhUPqSi
+ nNp/xedE1YxutQ==
+ -----END PRIVATE KEY-----
+ KEY
+ end
+
+ before do
+ allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
+ project.add_role(user, role)
+ sign_in(user)
+ project.namespace.update(owner: user)
+ allow_any_instance_of(Project).to receive(:pages_deployed?) { true }
+ end
+
+ context 'when the page_auto_ssl feature flag is enabled' do
+ before do
+ stub_feature_flags(pages_auto_ssl: true)
+ end
+
+ context 'when the auto SSL management is initially disabled' do
+ let(:domain) do
+ create(:pages_domain, auto_ssl_enabled: false, project: project)
+ end
+
+ it 'enables auto SSL and dynamically updates the form accordingly', :js do
+ visit edit_project_pages_domain_path(project, domain)
+
+ expect(domain.auto_ssl_enabled).to eq false
+
+ expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false'
+ expect(page).to have_field 'Certificate (PEM)', type: 'textarea'
+ expect(page).to have_field 'Key (PEM)', type: 'textarea'
+
+ find('.js-auto-ssl-toggle-container .project-feature-toggle').click
+
+ expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
+ expect(page).not_to have_field 'Certificate (PEM)', type: 'textarea'
+ expect(page).not_to have_field 'Key (PEM)', type: 'textarea'
+ expect(page).to have_content "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+
+ click_on 'Save Changes'
+
+ expect(domain.reload.auto_ssl_enabled).to eq true
+ end
+ end
+
+ context 'when the auto SSL management is initially enabled' do
+ let(:domain) do
+ create(:pages_domain, auto_ssl_enabled: true, project: project)
+ end
+
+ it 'disables auto SSL and dynamically updates the form accordingly', :js do
+ visit edit_project_pages_domain_path(project, domain)
+
+ expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
+ expect(page).to have_field 'Certificate (PEM)', type: 'textarea', disabled: true
+ expect(page).not_to have_field 'Key (PEM)', type: 'textarea'
+
+ find('.js-auto-ssl-toggle-container .project-feature-toggle').click
+
+ expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false'
+ expect(page).to have_field 'Certificate (PEM)', type: 'textarea'
+ expect(page).to have_field 'Key (PEM)', type: 'textarea'
+
+ fill_in 'Certificate (PEM)', with: certificate_pem
+ fill_in 'Key (PEM)', with: certificate_key
+
+ click_on 'Save Changes'
+
+ expect(domain.reload.auto_ssl_enabled).to eq false
+ end
+ end
+ end
+
+ context 'when the page_auto_ssl feature flag is disabled' do
+ let(:domain) do
+ create(:pages_domain, auto_ssl_enabled: false, project: project)
+ end
+
+ before do
+ stub_feature_flags(pages_auto_ssl: false)
+
+ visit edit_project_pages_domain_path(project, domain)
+ end
+
+ it "does not render the Let's Encrypt field", :js do
+ expect(page).not_to have_selector '.js-auto-ssl-toggle-container'
+ end
+ end
+end
diff --git a/spec/features/projects/pages_spec.rb b/spec/features/projects/pages_spec.rb
index f564ae34f11..9bb0ba81ef5 100644
--- a/spec/features/projects/pages_spec.rb
+++ b/spec/features/projects/pages_spec.rb
@@ -1,6 +1,7 @@
+# frozen_string_literal: true
require 'spec_helper'
-describe 'Pages' do
+shared_examples 'pages domain editing' do
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:role) { :maintainer }
@@ -287,10 +288,17 @@ describe 'Pages' do
:ci_build,
project: project,
pipeline: pipeline,
- ref: 'HEAD',
- legacy_artifacts_file: fixture_file_upload(File.join('spec/fixtures/pages.zip')),
- legacy_artifacts_metadata: fixture_file_upload(File.join('spec/fixtures/pages.zip.meta'))
- )
+ ref: 'HEAD')
+ end
+
+ let!(:artifact) do
+ create(:ci_job_artifact, :archive,
+ file: fixture_file_upload(File.join('spec/fixtures/pages.zip')), job: ci_build)
+ end
+
+ let!(:metadata) do
+ create(:ci_job_artifact, :metadata,
+ file: fixture_file_upload(File.join('spec/fixtures/pages.zip.meta')), job: ci_build)
end
before do
@@ -311,3 +319,21 @@ describe 'Pages' do
end
end
end
+
+describe 'Pages' do
+ context 'when pages_auto_ssl feature flag is disabled' do
+ before do
+ stub_feature_flags(pages_auto_ssl: false)
+ end
+
+ include_examples 'pages domain editing'
+ end
+
+ context 'when pages_auto_ssl feature flag is enabled' do
+ before do
+ stub_feature_flags(pages_auto_ssl: true)
+ end
+
+ include_examples 'pages domain editing'
+ end
+end
diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb
index b1a705f09ce..24041a51383 100644
--- a/spec/features/projects/pipeline_schedules_spec.rb
+++ b/spec/features/projects/pipeline_schedules_spec.rb
@@ -225,7 +225,7 @@ describe 'Pipeline Schedules', :js do
context 'when active is true and next_run_at is NULL' do
before do
create(:ci_pipeline_schedule, project: project, owner: user).tap do |pipeline_schedule|
- pipeline_schedule.update_attribute(:cron, nil) # Consequently next_run_at will be nil
+ pipeline_schedule.update_attribute(:next_run_at, nil) # Consequently next_run_at will be nil
end
end
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index cf334e1e4da..77f0f237d0a 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'Pipeline', :js do
@@ -89,7 +91,7 @@ describe 'Pipeline', :js do
within '.pipeline-info' do
expect(page).to have_content("#{pipeline.statuses.count} jobs " \
- "for #{pipeline.ref} ")
+ "for #{pipeline.ref}")
expect(page).to have_link(pipeline.ref,
href: project_commits_path(pipeline.project, pipeline.ref))
end
@@ -236,6 +238,20 @@ describe 'Pipeline', :js do
end
end
+ context 'when the pipeline has manual stage' do
+ before do
+ create(:ci_build, :manual, pipeline: pipeline, stage: 'publish', name: 'CentOS')
+ create(:ci_build, :manual, pipeline: pipeline, stage: 'publish', name: 'Debian')
+ create(:ci_build, :manual, pipeline: pipeline, stage: 'publish', name: 'OpenSUDE')
+
+ visit_pipeline
+ end
+
+ it 'displays play all button' do
+ expect(page).to have_selector('.js-stage-action')
+ end
+ end
+
context 'page tabs' do
before do
visit_pipeline
@@ -314,6 +330,12 @@ describe 'Pipeline', :js do
expect(page).not_to have_link(pipeline.ref)
expect(page).to have_content(pipeline.ref)
end
+
+ it 'does not render render raw HTML to the pipeline ref' do
+ page.within '.pipeline-info' do
+ expect(page).not_to have_content('<span class="ref-name"')
+ end
+ end
end
context 'when pipeline is detached merge request pipeline' do
@@ -331,11 +353,9 @@ describe 'Pipeline', :js do
merge_request.all_pipelines.last
end
- before do
+ it 'shows the pipeline information' do
visit_pipeline
- end
- it 'shows the pipeline information' do
within '.pipeline-info' do
expect(page).to have_content("#{pipeline.statuses.count} jobs " \
"for !#{merge_request.iid} " \
@@ -347,6 +367,21 @@ describe 'Pipeline', :js do
end
end
+ context 'when source branch does not exist' do
+ before do
+ project.repository.rm_branch(user, merge_request.source_branch)
+ end
+
+ it 'does not link to the source branch commit path' do
+ visit_pipeline
+
+ within '.pipeline-info' do
+ expect(page).not_to have_link(merge_request.source_branch)
+ expect(page).to have_content(merge_request.source_branch)
+ end
+ end
+ end
+
context 'when source project is a forked project' do
let(:source_project) { fork_project(project, user, repository: true) }
@@ -386,11 +421,11 @@ describe 'Pipeline', :js do
before do
pipeline.update(user: user)
-
- visit_pipeline
end
it 'shows the pipeline information' do
+ visit_pipeline
+
within '.pipeline-info' do
expect(page).to have_content("#{pipeline.statuses.count} jobs " \
"for !#{merge_request.iid} " \
@@ -405,6 +440,21 @@ describe 'Pipeline', :js do
end
end
+ context 'when target branch does not exist' do
+ before do
+ project.repository.rm_branch(user, merge_request.target_branch)
+ end
+
+ it 'does not link to the target branch commit path' do
+ visit_pipeline
+
+ within '.pipeline-info' do
+ expect(page).not_to have_link(merge_request.target_branch)
+ expect(page).to have_content(merge_request.target_branch)
+ end
+ end
+ end
+
context 'when source project is a forked project' do
let(:source_project) { fork_project(project, user, repository: true) }
diff --git a/spec/features/projects/serverless/functions_spec.rb b/spec/features/projects/serverless/functions_spec.rb
index e14934b1672..9865dbbfb3c 100644
--- a/spec/features/projects/serverless/functions_spec.rb
+++ b/spec/features/projects/serverless/functions_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
describe 'Functions', :js do
include KubernetesHelpers
+ include ReactiveCachingHelpers
let(:project) { create(:project) }
let(:user) { create(:user) }
@@ -13,44 +14,70 @@ describe 'Functions', :js do
gitlab_sign_in(user)
end
- context 'when user does not have a cluster and visits the serverless page' do
+ shared_examples "it's missing knative installation" do
before do
visit project_serverless_functions_path(project)
end
- it 'sees an empty state' do
+ it 'sees an empty state require Knative installation' do
expect(page).to have_link('Install Knative')
expect(page).to have_selector('.empty-state')
end
end
+ context 'when user does not have a cluster and visits the serverless page' do
+ it_behaves_like "it's missing knative installation"
+ end
+
context 'when the user does have a cluster and visits the serverless page' do
let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- before do
- visit project_serverless_functions_path(project)
- end
-
- it 'sees an empty state' do
- expect(page).to have_link('Install Knative')
- expect(page).to have_selector('.empty-state')
- end
+ it_behaves_like "it's missing knative installation"
end
context 'when the user has a cluster and knative installed and visits the serverless page' do
let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:service) { cluster.platform_kubernetes }
- let(:knative) { create(:clusters_applications_knative, :installed, cluster: cluster) }
- let(:project) { knative.cluster.project }
+ let(:project) { cluster.project }
+ let(:knative_services_finder) { project.clusters.first.knative_services_finder(project) }
+ let(:namespace) do
+ create(:cluster_kubernetes_namespace,
+ cluster: cluster,
+ cluster_project: cluster.cluster_project,
+ project: cluster.cluster_project.project)
+ end
before do
- stub_kubeclient_knative_services
- stub_kubeclient_service_pods
+ allow_any_instance_of(Clusters::Cluster)
+ .to receive(:knative_services_finder)
+ .and_return(knative_services_finder)
+ synchronous_reactive_cache(knative_services_finder)
+ stub_kubeclient_knative_services(stub_get_services_options)
+ stub_kubeclient_service_pods(nil, namespace: namespace.namespace)
visit project_serverless_functions_path(project)
end
- it 'sees an empty listing of serverless functions' do
- expect(page).to have_selector('.empty-state')
+ context 'when there are no functions' do
+ let(:stub_get_services_options) do
+ {
+ namespace: namespace.namespace,
+ response: kube_response({ "kind" => "ServiceList", "items" => [] })
+ }
+ end
+
+ it 'sees an empty listing of serverless functions' do
+ expect(page).to have_selector('.empty-state')
+ expect(page).not_to have_selector('.content-list')
+ end
+ end
+
+ context 'when there are functions' do
+ let(:stub_get_services_options) { { namespace: namespace.namespace } }
+
+ it 'does not see an empty listing of serverless functions' do
+ expect(page).not_to have_selector('.empty-state')
+ expect(page).to have_selector('.content-list')
+ end
end
end
end
diff --git a/spec/features/projects/settings/forked_project_settings_spec.rb b/spec/features/projects/settings/forked_project_settings_spec.rb
index dc0278370aa..df33d215602 100644
--- a/spec/features/projects/settings/forked_project_settings_spec.rb
+++ b/spec/features/projects/settings/forked_project_settings_spec.rb
@@ -7,7 +7,6 @@ describe 'Projects > Settings > For a forked project', :js do
let(:forked_project) { fork_project(original_project, user) }
before do
- stub_feature_flags(approval_rules: false)
original_project.add_maintainer(user)
forked_project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/projects/settings/integration_settings_spec.rb b/spec/features/projects/settings/integration_settings_spec.rb
index 32959969f54..016ccf63f58 100644
--- a/spec/features/projects/settings/integration_settings_spec.rb
+++ b/spec/features/projects/settings/integration_settings_spec.rb
@@ -41,7 +41,7 @@ describe 'Projects > Settings > Integration settings' do
expect(page).to have_content('Issues events')
expect(page).to have_content('Confidential issues events')
expect(page).to have_content('Note events')
- expect(page).to have_content('Merge requests events')
+ expect(page).to have_content('Merge requests events')
expect(page).to have_content('Pipeline events')
expect(page).to have_content('Wiki page events')
end
diff --git a/spec/features/projects/settings/operations_settings_spec.rb b/spec/features/projects/settings/operations_settings_spec.rb
index af56cb0d4ee..d96e243d96b 100644
--- a/spec/features/projects/settings/operations_settings_spec.rb
+++ b/spec/features/projects/settings/operations_settings_spec.rb
@@ -46,6 +46,9 @@ describe 'Projects > Settings > For a forked project', :js do
wait_for_requests
+ within '.js-error-tracking-settings' do
+ click_button('Expand')
+ end
expect(page).to have_content('Sentry API URL')
expect(page.body).to include('Error Tracking')
expect(page).to have_button('Connect')
@@ -86,6 +89,9 @@ describe 'Projects > Settings > For a forked project', :js do
wait_for_requests
+ within '.js-error-tracking-settings' do
+ click_button('Expand')
+ end
check('Active')
fill_in('error-tracking-api-host', with: 'http://sentry.example.com')
fill_in('error-tracking-token', with: 'token')
diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb
index 1259ad45791..8c7bc192c50 100644
--- a/spec/features/projects/settings/repository_settings_spec.rb
+++ b/spec/features/projects/settings/repository_settings_spec.rb
@@ -217,5 +217,36 @@ describe 'Projects > Settings > Repository settings' do
expect(RepositoryCleanupWorker.jobs.count).to eq(1)
end
end
+
+ context 'with an existing mirror', :js do
+ let(:mirrored_project) { create(:project, :repository, :remote_mirror) }
+
+ before do
+ mirrored_project.add_maintainer(user)
+
+ visit project_settings_repository_path(mirrored_project)
+ end
+
+ it 'delete remote mirrors' do
+ expect(mirrored_project.remote_mirrors.count).to eq(1)
+
+ find('.js-delete-mirror').click
+ wait_for_requests
+
+ expect(mirrored_project.remote_mirrors.count).to eq(0)
+ end
+ end
+
+ it 'shows a disabled mirror' do
+ create(:remote_mirror, project: project, enabled: false)
+
+ visit project_settings_repository_path(project)
+
+ mirror = find('.qa-mirrored-repository-row')
+
+ expect(mirror).to have_selector('.qa-delete-mirror')
+ expect(mirror).to have_selector('.qa-disabled-mirror-badge')
+ expect(mirror).not_to have_selector('.qa-update-now-button')
+ end
end
end
diff --git a/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb b/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb
index b1c2bab08c0..0739726f52c 100644
--- a/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb
+++ b/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: true
require 'spec_helper'
describe 'Projects > Settings > User manages merge request settings' do
@@ -30,16 +31,16 @@ describe 'Projects > Settings > User manages merge request settings' do
context 'when Merge Request and Pipelines are initially enabled', :js do
context 'when Pipelines are initially enabled' do
it 'shows the Merge Requests settings' do
- expect(page).to have_content('Only allow merge requests to be merged if the pipeline succeeds')
- expect(page).to have_content('Only allow merge requests to be merged if all discussions are resolved')
+ expect(page).to have_content 'Pipelines must succeed'
+ expect(page).to have_content 'All discussions must be resolved'
within('.sharing-permissions-form') do
find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .project-feature-toggle').click
find('input[value="Save changes"]').send_keys(:return)
end
- expect(page).not_to have_content('Only allow merge requests to be merged if the pipeline succeeds')
- expect(page).not_to have_content('Only allow merge requests to be merged if all discussions are resolved')
+ expect(page).not_to have_content 'Pipelines must succeed'
+ expect(page).not_to have_content 'All discussions must be resolved'
end
end
@@ -50,16 +51,16 @@ describe 'Projects > Settings > User manages merge request settings' do
end
it 'shows the Merge Requests settings that do not depend on Builds feature' do
- expect(page).not_to have_content('Only allow merge requests to be merged if the pipeline succeeds')
- expect(page).to have_content('Only allow merge requests to be merged if all discussions are resolved')
+ expect(page).to have_content 'Pipelines must succeed'
+ expect(page).to have_content 'All discussions must be resolved'
within('.sharing-permissions-form') do
find('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"] .project-feature-toggle').click
find('input[value="Save changes"]').send_keys(:return)
end
- expect(page).to have_content('Only allow merge requests to be merged if the pipeline succeeds')
- expect(page).to have_content('Only allow merge requests to be merged if all discussions are resolved')
+ expect(page).to have_content 'Pipelines must succeed'
+ expect(page).to have_content 'All discussions must be resolved'
end
end
end
@@ -71,16 +72,16 @@ describe 'Projects > Settings > User manages merge request settings' do
end
it 'does not show the Merge Requests settings' do
- expect(page).not_to have_content('Only allow merge requests to be merged if the pipeline succeeds')
- expect(page).not_to have_content('Only allow merge requests to be merged if all discussions are resolved')
+ expect(page).not_to have_content 'Pipelines must succeed'
+ expect(page).not_to have_content 'All discussions must be resolved'
within('.sharing-permissions-form') do
find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .project-feature-toggle').click
find('input[value="Save changes"]').send_keys(:return)
end
- expect(page).to have_content('Only allow merge requests to be merged if the pipeline succeeds')
- expect(page).to have_content('Only allow merge requests to be merged if all discussions are resolved')
+ expect(page).to have_content 'Pipelines must succeed'
+ expect(page).to have_content 'All discussions must be resolved'
end
end
diff --git a/spec/features/projects/show/download_buttons_spec.rb b/spec/features/projects/show/download_buttons_spec.rb
index 3a2dcc5aa55..fee5f8001b0 100644
--- a/spec/features/projects/show/download_buttons_spec.rb
+++ b/spec/features/projects/show/download_buttons_spec.rb
@@ -35,11 +35,10 @@ describe 'Projects > Show > Download buttons' do
it 'shows download artifacts button' do
href = latest_succeeded_project_artifacts_path(project, "#{project.default_branch}/download", job: 'build')
- expect(page).to have_link "Download '#{build.name}'", href: href
+ expect(page).to have_link build.name, href: href
end
it 'download links have download attribute' do
- expect(page).to have_selector('a', text: 'Download')
page.all('a', text: 'Download').each do |link|
expect(link[:download]).to eq ''
end
diff --git a/spec/features/projects/show/user_manages_notifications_spec.rb b/spec/features/projects/show/user_manages_notifications_spec.rb
index 88f3397608f..e9dd1dc0f66 100644
--- a/spec/features/projects/show/user_manages_notifications_spec.rb
+++ b/spec/features/projects/show/user_manages_notifications_spec.rb
@@ -20,6 +20,16 @@ describe 'Projects > Show > User manages notifications', :js do
click_notifications_button
expect(find('.update-notification.is-active')).to have_content('On mention')
+ expect(find('.notifications-icon use')[:'xlink:href']).to end_with('#notifications')
+ end
+
+ it 'changes the notification setting to disabled' do
+ click_notifications_button
+ click_link 'Disabled'
+
+ wait_for_requests
+
+ expect(find('.notifications-icon use')[:'xlink:href']).to end_with('#notifications-off')
end
context 'custom notification settings' do
diff --git a/spec/features/projects/show/user_sees_collaboration_links_spec.rb b/spec/features/projects/show/user_sees_collaboration_links_spec.rb
index 24777788248..46586b891e7 100644
--- a/spec/features/projects/show/user_sees_collaboration_links_spec.rb
+++ b/spec/features/projects/show/user_sees_collaboration_links_spec.rb
@@ -5,6 +5,7 @@ describe 'Projects > Show > Collaboration links' do
let(:user) { create(:user) }
before do
+ stub_feature_flags(vue_file_list: false)
project.add_developer(user)
sign_in(user)
end
diff --git a/spec/features/projects/tags/download_buttons_spec.rb b/spec/features/projects/tags/download_buttons_spec.rb
index fbfd8cee7aa..4c8ec53836a 100644
--- a/spec/features/projects/tags/download_buttons_spec.rb
+++ b/spec/features/projects/tags/download_buttons_spec.rb
@@ -36,7 +36,7 @@ describe 'Download buttons in tags page' do
it 'shows download artifacts button' do
href = latest_succeeded_project_artifacts_path(project, "#{tag}/download", job: 'build')
- expect(page).to have_link "Download '#{build.name}'", href: href
+ expect(page).to have_link build.name, href: href
end
end
end
diff --git a/spec/features/projects/tree/tree_show_spec.rb b/spec/features/projects/tree/tree_show_spec.rb
index 45e81e1c040..3ccea2db705 100644
--- a/spec/features/projects/tree/tree_show_spec.rb
+++ b/spec/features/projects/tree/tree_show_spec.rb
@@ -8,6 +8,7 @@ describe 'Projects tree', :js do
let(:test_sha) { '7975be0116940bf2ad4321f79d02a55c5f7779aa' }
before do
+ stub_feature_flags(vue_file_list: false)
project.add_maintainer(user)
sign_in(user)
end
diff --git a/spec/features/projects/tree/upload_file_spec.rb b/spec/features/projects/tree/upload_file_spec.rb
index dcf7d314f8e..e5dd2f40fdf 100644
--- a/spec/features/projects/tree/upload_file_spec.rb
+++ b/spec/features/projects/tree/upload_file_spec.rb
@@ -29,6 +29,6 @@ describe 'Multi-file editor upload file', :js do
attach_file('file-upload', txt_file)
expect(page).to have_selector('.multi-file-tab', text: 'doc_sample.txt')
- expect(find('.blob-editor-container .lines-content')['innerText']).to have_content(File.open(txt_file, &:readline))
+ expect(find('.blob-editor-container .lines-content')['innerText']).to have_content(File.open(txt_file, &:readline).gsub!(/\s+/, ' '))
end
end
diff --git a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
index bcbba6f14da..aac095bfa6b 100644
--- a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
@@ -141,7 +141,7 @@ describe "User creates wiki page" do
end
end
- it_behaves_like 'wiki file attachments'
+ it_behaves_like 'wiki file attachments', :quarantine
end
context "in a group namespace", :js do
@@ -151,7 +151,7 @@ describe "User creates wiki page" do
expect(page).to have_field("wiki[message]", with: "Create home")
end
- it "creates a page from the home page" do
+ it "creates a page from the home page", :quarantine do
page.within(".wiki-form") do
fill_in(:wiki_content, with: "My awesome wiki!")
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index ff4e6197746..b5112758475 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe 'Project' do
@@ -5,7 +7,7 @@ describe 'Project' do
include MobileHelpers
before do
- stub_feature_flags(approval_rules: false)
+ stub_feature_flags(vue_file_list: false)
end
describe 'creating from template' do
diff --git a/spec/features/protected_branches_spec.rb b/spec/features/protected_branches_spec.rb
index 0aff916ec83..0dbff5a2701 100644
--- a/spec/features/protected_branches_spec.rb
+++ b/spec/features/protected_branches_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe 'Protected Branches', :js do
+ include ProtectedBranchHelpers
+
let(:user) { create(:user) }
let(:admin) { create(:admin) }
let(:project) { create(:project, :repository) }
@@ -150,27 +152,11 @@ describe 'Protected Branches', :js do
end
describe "access control" do
- include_examples "protected branches > access control > CE"
- end
- end
-
- def set_protected_branch_name(branch_name)
- find(".js-protected-branch-select").click
- find(".dropdown-input-field").set(branch_name)
- click_on("Create wildcard #{branch_name}")
- end
-
- def set_defaults
- find(".js-allowed-to-merge").click
- within('.qa-allowed-to-merge-dropdown') do
- expect(first("li")).to have_content("Roles")
- find(:link, 'No one').click
- end
+ before do
+ stub_licensed_features(protected_refs_for_users: false)
+ end
- find(".js-allowed-to-push").click
- within('.qa-allowed-to-push-dropdown') do
- expect(first("li")).to have_content("Roles")
- find(:link, 'No one').click
+ include_examples "protected branches > access control > CE"
end
end
end
diff --git a/spec/features/protected_tags_spec.rb b/spec/features/protected_tags_spec.rb
index c8e92cd1c07..652542b1719 100644
--- a/spec/features/protected_tags_spec.rb
+++ b/spec/features/protected_tags_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe 'Protected Tags', :js do
+ include ProtectedTagHelpers
+
let(:user) { create(:user, :admin) }
let(:project) { create(:project, :repository) }
@@ -8,13 +10,6 @@ describe 'Protected Tags', :js do
sign_in(user)
end
- def set_protected_tag_name(tag_name)
- find(".js-protected-tag-select").click
- find(".dropdown-input-field").set(tag_name)
- click_on("Create wildcard #{tag_name}")
- find('.protected-tags-dropdown .dropdown-menu', visible: false)
- end
-
describe "explicit protected tags" do
it "allows creating explicit protected tags" do
visit project_protected_tags_path(project)
@@ -92,6 +87,10 @@ describe 'Protected Tags', :js do
end
describe "access control" do
+ before do
+ stub_licensed_features(protected_refs_for_users: false)
+ end
+
include_examples "protected tags > access control > CE"
end
end
diff --git a/spec/features/search/user_searches_for_commits_spec.rb b/spec/features/search/user_searches_for_commits_spec.rb
index 28cae444588..998f8521384 100644
--- a/spec/features/search/user_searches_for_commits_spec.rb
+++ b/spec/features/search/user_searches_for_commits_spec.rb
@@ -35,7 +35,7 @@ describe 'User searches for commits' do
fill_in('search', with: 'deadbeef')
click_button('Search')
- expect(page).to have_current_path('/search', only_path: true)
+ expect(page).to have_current_path('/search', ignore_query: true)
end
it 'finds multiple commits' do
diff --git a/spec/features/search/user_searches_for_wiki_pages_spec.rb b/spec/features/search/user_searches_for_wiki_pages_spec.rb
index 7225ca65492..6d4facd0649 100644
--- a/spec/features/search/user_searches_for_wiki_pages_spec.rb
+++ b/spec/features/search/user_searches_for_wiki_pages_spec.rb
@@ -14,22 +14,36 @@ describe 'User searches for wiki pages', :js do
include_examples 'top right search form'
- it 'finds a page' do
- find('.js-search-project-dropdown').click
+ shared_examples 'search wiki blobs' do
+ it 'finds a page' do
+ find('.js-search-project-dropdown').click
- page.within('.project-filter') do
- click_link(project.full_name)
- end
+ page.within('.project-filter') do
+ click_link(project.full_name)
+ end
+
+ fill_in('dashboard_search', with: 'content')
+ find('.btn-search').click
+
+ page.within('.search-filter') do
+ click_link('Wiki')
+ end
- fill_in('dashboard_search', with: 'content')
- find('.btn-search').click
+ page.within('.results') do
+ expect(find(:css, '.search-results')).to have_link(wiki_page.title, href: project_wiki_path(project, wiki_page.slug))
+ end
+ end
+ end
- page.within('.search-filter') do
- click_link('Wiki')
+ context 'when searching by content' do
+ it_behaves_like 'search wiki blobs' do
+ let(:search_term) { 'content' }
end
+ end
- page.within('.results') do
- expect(find(:css, '.search-results')).to have_link(wiki_page.title)
+ context 'when searching by title' do
+ it_behaves_like 'search wiki blobs' do
+ let(:search_term) { 'test_wiki' }
end
end
end
diff --git a/spec/features/security/profile_access_spec.rb b/spec/features/security/profile_access_spec.rb
index a198e65046f..044a47567be 100644
--- a/spec/features/security/profile_access_spec.rb
+++ b/spec/features/security/profile_access_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe "Profile access" do
diff --git a/spec/features/tags/master_creates_tag_spec.rb b/spec/features/tags/master_creates_tag_spec.rb
index db2970f3340..f80ddd050d7 100644
--- a/spec/features/tags/master_creates_tag_spec.rb
+++ b/spec/features/tags/master_creates_tag_spec.rb
@@ -39,7 +39,7 @@ describe 'Maintainer creates tag' do
project_tag_path(project, 'v3.0'))
expect(page).to have_content 'v3.0'
page.within 'pre.wrap' do
- expect(page).to have_content "Awesome tag message\n\n- hello\n- world"
+ expect(page).to have_content "Awesome tag message - hello - world"
end
end
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index 9d5780d29b0..efba303033b 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -137,7 +137,7 @@ describe 'Login' do
enter_code(user.current_otp)
- expect(page).not_to have_content('You are already signed in.')
+ expect(page).not_to have_content(I18n.t('devise.failure.already_authenticated'))
end
context 'using one-time code' do
@@ -317,7 +317,17 @@ describe 'Login' do
gitlab_sign_in(user)
expect(current_path).to eq root_path
- expect(page).not_to have_content('You are already signed in.')
+ expect(page).not_to have_content(I18n.t('devise.failure.already_authenticated'))
+ end
+
+ it 'does not show already signed in message when opening sign in page after login' do
+ expect(authentication_metrics)
+ .to increment(:user_authenticated_counter)
+
+ gitlab_sign_in(user)
+ visit new_user_session_path
+
+ expect(page).not_to have_content(I18n.t('devise.failure.already_authenticated'))
end
end
@@ -579,7 +589,7 @@ describe 'Login' do
click_button 'Accept terms'
expect(current_path).to eq(root_path)
- expect(page).not_to have_content('You are already signed in.')
+ expect(page).not_to have_content(I18n.t('devise.failure.already_authenticated'))
end
it 'does not ask for terms when the user already accepted them' do
diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb
index 957c3cfc583..1a9caf0ffbb 100644
--- a/spec/features/users/signup_spec.rb
+++ b/spec/features/users/signup_spec.rb
@@ -25,6 +25,13 @@ describe 'Signup' do
expect(find('.username')).not_to have_css '.gl-field-error-outline'
end
+ it 'does not show an error border if the username length is not longer than 255 characters' do
+ fill_in 'new_user_username', with: 'u' * 255
+ wait_for_requests
+
+ expect(find('.username')).not_to have_css '.gl-field-error-outline'
+ end
+
it 'shows an error border if the username already exists' do
existing_user = create(:user)
@@ -41,6 +48,20 @@ describe 'Signup' do
expect(find('.username')).to have_css '.gl-field-error-outline'
end
+ it 'shows an error border if the username is longer than 255 characters' do
+ fill_in 'new_user_username', with: 'u' * 256
+ wait_for_requests
+
+ expect(find('.username')).to have_css '.gl-field-error-outline'
+ end
+
+ it 'shows an error message if the username is longer than 255 characters' do
+ fill_in 'new_user_username', with: 'u' * 256
+ wait_for_requests
+
+ expect(page).to have_content("Username is too long (maximum is 255 characters).")
+ end
+
it 'shows an error message on submit if the username contains special characters' do
fill_in 'new_user_username', with: 'new$user!username'
wait_for_requests
@@ -67,14 +88,35 @@ describe 'Signup' do
before do
visit root_path
click_link 'Register'
- simulate_input('#new_user_name', 'Ehsan 🦋')
+ end
+
+ it 'does not show an error border if the user\'s fullname length is not longer than 128 characters' do
+ fill_in 'new_user_name', with: 'u' * 128
+
+ expect(find('.name')).not_to have_css '.gl-field-error-outline'
end
it 'shows an error border if the user\'s fullname contains an emoji' do
+ simulate_input('#new_user_name', 'Ehsan 🦋')
+
+ expect(find('.name')).to have_css '.gl-field-error-outline'
+ end
+
+ it 'shows an error border if the user\'s fullname is longer than 128 characters' do
+ fill_in 'new_user_name', with: 'n' * 129
+
expect(find('.name')).to have_css '.gl-field-error-outline'
end
+ it 'shows an error message if the user\'s fullname is longer than 128 characters' do
+ fill_in 'new_user_name', with: 'n' * 129
+
+ expect(page).to have_content("Name is too long (maximum is 128 characters).")
+ end
+
it 'shows an error message if the username contains emojis' do
+ simulate_input('#new_user_name', 'Ehsan 🦋')
+
expect(page).to have_content("Invalid input, please avoid emojis")
end
end
diff --git a/spec/finders/autocomplete/users_finder_spec.rb b/spec/finders/autocomplete/users_finder_spec.rb
index abd0d6b5185..bcde115b1a6 100644
--- a/spec/finders/autocomplete/users_finder_spec.rb
+++ b/spec/finders/autocomplete/users_finder_spec.rb
@@ -26,9 +26,17 @@ describe Autocomplete::UsersFinder do
it { is_expected.to match_array([project.owner]) }
context 'when author_id passed' do
- let(:params) { { author_id: user2.id } }
+ context 'and author is active' do
+ let(:params) { { author_id: user1.id } }
- it { is_expected.to match_array([project.owner, user2]) }
+ it { is_expected.to match_array([project.owner, user1]) }
+ end
+
+ context 'and author is blocked' do
+ let(:params) { { author_id: user2.id } }
+
+ it { is_expected.to match_array([project.owner]) }
+ end
end
end
@@ -104,9 +112,9 @@ describe Autocomplete::UsersFinder do
end
context 'when filtered by author_id' do
- let(:params) { { author_id: user2.id } }
+ let(:params) { { author_id: user1.id } }
- it { is_expected.to match_array([user2, user1, external_user, omniauth_user, current_user]) }
+ it { is_expected.to match_array([user1, external_user, omniauth_user, current_user]) }
end
end
end
diff --git a/spec/finders/cluster_ancestors_finder_spec.rb b/spec/finders/cluster_ancestors_finder_spec.rb
index 332086c42e2..750042b6b54 100644
--- a/spec/finders/cluster_ancestors_finder_spec.rb
+++ b/spec/finders/cluster_ancestors_finder_spec.rb
@@ -8,11 +8,15 @@ describe ClusterAncestorsFinder, '#execute' do
let(:user) { create(:user) }
let!(:project_cluster) do
- create(:cluster, :provided_by_user, cluster_type: :project_type, projects: [project])
+ create(:cluster, :provided_by_user, :project, projects: [project])
end
let!(:group_cluster) do
- create(:cluster, :provided_by_user, cluster_type: :group_type, groups: [group])
+ create(:cluster, :provided_by_user, :group, groups: [group])
+ end
+
+ let!(:instance_cluster) do
+ create(:cluster, :provided_by_user, :instance)
end
subject { described_class.new(clusterable, user).execute }
@@ -25,7 +29,7 @@ describe ClusterAncestorsFinder, '#execute' do
end
it 'returns the project clusters followed by group clusters' do
- is_expected.to eq([project_cluster, group_cluster])
+ is_expected.to eq([project_cluster, group_cluster, instance_cluster])
end
context 'nested groups', :nested_groups do
@@ -33,11 +37,11 @@ describe ClusterAncestorsFinder, '#execute' do
let(:parent_group) { create(:group) }
let!(:parent_group_cluster) do
- create(:cluster, :provided_by_user, cluster_type: :group_type, groups: [parent_group])
+ create(:cluster, :provided_by_user, :group, groups: [parent_group])
end
it 'returns the project clusters followed by group clusters ordered ascending the hierarchy' do
- is_expected.to eq([project_cluster, group_cluster, parent_group_cluster])
+ is_expected.to eq([project_cluster, group_cluster, parent_group_cluster, instance_cluster])
end
end
end
@@ -58,7 +62,7 @@ describe ClusterAncestorsFinder, '#execute' do
end
it 'returns the list of group clusters' do
- is_expected.to eq([group_cluster])
+ is_expected.to eq([group_cluster, instance_cluster])
end
context 'nested groups', :nested_groups do
@@ -66,12 +70,21 @@ describe ClusterAncestorsFinder, '#execute' do
let(:parent_group) { create(:group) }
let!(:parent_group_cluster) do
- create(:cluster, :provided_by_user, cluster_type: :group_type, groups: [parent_group])
+ create(:cluster, :provided_by_user, :group, groups: [parent_group])
end
it 'returns the list of group clusters ordered ascending the hierarchy' do
- is_expected.to eq([group_cluster, parent_group_cluster])
+ is_expected.to eq([group_cluster, parent_group_cluster, instance_cluster])
end
end
end
+
+ context 'for an instance' do
+ let(:clusterable) { Clusters::Instance.new }
+ let(:user) { create(:admin) }
+
+ it 'returns the list of instance clusters' do
+ is_expected.to eq([instance_cluster])
+ end
+ end
end
diff --git a/spec/finders/clusters/knative_services_finder_spec.rb b/spec/finders/clusters/knative_services_finder_spec.rb
new file mode 100644
index 00000000000..b731c2bd6bf
--- /dev/null
+++ b/spec/finders/clusters/knative_services_finder_spec.rb
@@ -0,0 +1,105 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Clusters::KnativeServicesFinder do
+ include KubernetesHelpers
+ include ReactiveCachingHelpers
+
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:service) { cluster.platform_kubernetes }
+ let(:project) { cluster.cluster_project.project }
+ let(:namespace) do
+ create(:cluster_kubernetes_namespace,
+ cluster: cluster,
+ cluster_project: cluster.cluster_project,
+ project: project)
+ end
+
+ before do
+ stub_kubeclient_knative_services(namespace: namespace.namespace)
+ stub_kubeclient_service_pods(
+ kube_response(
+ kube_knative_pods_body(
+ project.name, namespace.namespace
+ )
+ ),
+ namespace: namespace.namespace
+ )
+ end
+
+ shared_examples 'a cached data' do
+ it 'has an unintialized cache' do
+ is_expected.to be_blank
+ end
+
+ context 'when using synchronous reactive cache' do
+ before do
+ synchronous_reactive_cache(cluster.knative_services_finder(project))
+ end
+
+ context 'when there are functions for cluster namespace' do
+ it { is_expected.not_to be_blank }
+ end
+
+ context 'when there are no functions for cluster namespace' do
+ before do
+ stub_kubeclient_knative_services(
+ namespace: namespace.namespace,
+ response: kube_response({ "kind" => "ServiceList", "items" => [] })
+ )
+ stub_kubeclient_service_pods(
+ kube_response({ "kind" => "PodList", "items" => [] }),
+ namespace: namespace.namespace
+ )
+ end
+
+ it { is_expected.to be_blank }
+ end
+ end
+ end
+
+ describe '#service_pod_details' do
+ subject { cluster.knative_services_finder(project).service_pod_details(project.name) }
+
+ it_behaves_like 'a cached data'
+ end
+
+ describe '#services' do
+ subject { cluster.knative_services_finder(project).services }
+
+ it_behaves_like 'a cached data'
+ end
+
+ describe '#knative_detected' do
+ subject { cluster.knative_services_finder(project).knative_detected }
+ before do
+ synchronous_reactive_cache(cluster.knative_services_finder(project))
+ end
+
+ context 'when knative is installed' do
+ before do
+ stub_kubeclient_discover(service.api_url)
+ end
+
+ it { is_expected.to be_truthy }
+ it "discovers knative installation" do
+ expect { subject }
+ .to change { cluster.kubeclient.knative_client.discovered }
+ .from(false)
+ .to(true)
+ end
+ end
+
+ context 'when knative is not installed' do
+ before do
+ stub_kubeclient_discover_knative_not_found(service.api_url)
+ end
+
+ it { is_expected.to be_falsy }
+ it "does not discover knative installation" do
+ expect { subject }.not_to change { cluster.kubeclient.knative_client.discovered }
+ end
+ end
+ end
+end
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index 6a47cd013f8..bf38d083ca6 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -241,14 +241,6 @@ describe IssuesFinder do
end
end
- context 'filtering by legacy No+Label' do
- let(:params) { { label_name: Label::NONE } }
-
- it 'returns issues with no labels' do
- expect(issues).to contain_exactly(issue1, issue3, issue4)
- end
- end
-
context 'filtering by any label' do
let(:params) { { label_name: described_class::FILTER_ANY } }
@@ -641,9 +633,7 @@ describe IssuesFinder do
end
it 'filters by confidentiality' do
- expect(Issue).to receive(:where).with(a_string_matching('confidential'), anything)
-
- subject
+ expect(subject.to_sql).to match("issues.confidential")
end
end
@@ -660,9 +650,7 @@ describe IssuesFinder do
end
it 'filters by confidentiality' do
- expect(Issue).to receive(:where).with(a_string_matching('confidential'), anything)
-
- subject
+ expect(subject.to_sql).to match("issues.confidential")
end
end
diff --git a/spec/finders/members_finder_spec.rb b/spec/finders/members_finder_spec.rb
index db48f00cd74..83348457caa 100644
--- a/spec/finders/members_finder_spec.rb
+++ b/spec/finders/members_finder_spec.rb
@@ -1,13 +1,13 @@
require 'spec_helper'
describe MembersFinder, '#execute' do
- let(:group) { create(:group) }
- let(:nested_group) { create(:group, :access_requestable, parent: group) }
- let(:project) { create(:project, namespace: nested_group) }
- let(:user1) { create(:user) }
- let(:user2) { create(:user) }
- let(:user3) { create(:user) }
- let(:user4) { create(:user) }
+ set(:group) { create(:group) }
+ set(:nested_group) { create(:group, :access_requestable, parent: group) }
+ set(:project) { create(:project, namespace: nested_group) }
+ set(:user1) { create(:user) }
+ set(:user2) { create(:user) }
+ set(:user3) { create(:user) }
+ set(:user4) { create(:user) }
it 'returns members for project and parent groups', :nested_groups do
nested_group.request_access(user1)
@@ -31,4 +31,34 @@ describe MembersFinder, '#execute' do
expect(result.to_a).to match_array([member1, member2, member3])
end
+
+ context 'when include_invited_groups_members == true', :nested_groups do
+ subject { described_class.new(project, user2).execute(include_invited_groups_members: true) }
+
+ set(:linked_group) { create(:group, :public, :access_requestable) }
+ set(:nested_linked_group) { create(:group, parent: linked_group) }
+ set(:linked_group_member) { linked_group.add_developer(user1) }
+ set(:nested_linked_group_member) { nested_linked_group.add_developer(user2) }
+
+ it 'includes all the invited_groups members including members inherited from ancestor groups', :nested_groups do
+ create(:project_group_link, project: project, group: nested_linked_group)
+
+ expect(subject).to contain_exactly(linked_group_member, nested_linked_group_member)
+ end
+
+ it 'includes all the invited_groups members' do
+ create(:project_group_link, project: project, group: linked_group)
+
+ expect(subject).to contain_exactly(linked_group_member)
+ end
+
+ it 'excludes group_members not visible to the user' do
+ create(:project_group_link, project: project, group: linked_group)
+ private_linked_group = create(:group, :private)
+ private_linked_group.add_developer(user3)
+ create(:project_group_link, project: project, group: private_linked_group)
+
+ expect(subject).to contain_exactly(linked_group_member)
+ end
+ end
end
diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb
index 117f4a03735..da5e9dab058 100644
--- a/spec/finders/merge_requests_finder_spec.rb
+++ b/spec/finders/merge_requests_finder_spec.rb
@@ -31,7 +31,7 @@ describe MergeRequestsFinder do
end
context 'filtering by group' do
- it 'includes all merge requests when user has access exceluding merge requests from projects the user does not have access to' do
+ it 'includes all merge requests when user has access excluding merge requests from projects the user does not have access to' do
private_project = allow_gitaly_n_plus_1 { create(:project, :private, group: group) }
private_project.add_guest(user)
create(:merge_request, :simple, author: user, source_project: private_project, target_project: private_project)
diff --git a/spec/finders/projects/serverless/functions_finder_spec.rb b/spec/finders/projects/serverless/functions_finder_spec.rb
index 3ad38207da4..8aea45b457c 100644
--- a/spec/finders/projects/serverless/functions_finder_spec.rb
+++ b/spec/finders/projects/serverless/functions_finder_spec.rb
@@ -10,7 +10,7 @@ describe Projects::Serverless::FunctionsFinder do
let(:user) { create(:user) }
let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:service) { cluster.platform_kubernetes }
- let(:project) { cluster.project}
+ let(:project) { cluster.project }
let(:namespace) do
create(:cluster_kubernetes_namespace,
@@ -23,9 +23,45 @@ describe Projects::Serverless::FunctionsFinder do
project.add_maintainer(user)
end
+ describe '#installed' do
+ it 'when reactive_caching is still fetching data' do
+ expect(described_class.new(project).knative_installed).to eq 'checking'
+ end
+
+ context 'when reactive_caching has finished' do
+ let(:knative_services_finder) { project.clusters.first.knative_services_finder(project) }
+
+ before do
+ allow_any_instance_of(Clusters::Cluster)
+ .to receive(:knative_services_finder)
+ .and_return(knative_services_finder)
+ synchronous_reactive_cache(knative_services_finder)
+ end
+
+ context 'when knative is not installed' do
+ it 'returns false' do
+ stub_kubeclient_discover_knative_not_found(service.api_url)
+
+ expect(described_class.new(project).knative_installed).to eq false
+ end
+ end
+
+ context 'reactive_caching is finished and knative is installed' do
+ let(:knative_services_finder) { project.clusters.first.knative_services_finder(project) }
+
+ it 'returns true' do
+ stub_kubeclient_knative_services(namespace: namespace.namespace)
+ stub_kubeclient_service_pods(nil, namespace: namespace.namespace)
+
+ expect(described_class.new(project).knative_installed).to be true
+ end
+ end
+ end
+ end
+
describe 'retrieve data from knative' do
- it 'does not have knative installed' do
- expect(described_class.new(project).execute).to be_empty
+ context 'does not have knative installed' do
+ it { expect(described_class.new(project).execute).to be_empty }
end
context 'has knative installed' do
@@ -38,22 +74,24 @@ describe Projects::Serverless::FunctionsFinder do
it 'there are functions', :use_clean_rails_memory_store_caching do
stub_kubeclient_service_pods
- stub_reactive_cache(knative,
+ stub_reactive_cache(cluster.knative_services_finder(project),
{
services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"],
pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"]
- })
+ },
+ *cluster.knative_services_finder(project).cache_args)
expect(finder.execute).not_to be_empty
end
it 'has a function', :use_clean_rails_memory_store_caching do
stub_kubeclient_service_pods
- stub_reactive_cache(knative,
+ stub_reactive_cache(cluster.knative_services_finder(project),
{
services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"],
pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"]
- })
+ },
+ *cluster.knative_services_finder(project).cache_args)
result = finder.service(cluster.environment_scope, cluster.project.name)
expect(result).not_to be_empty
@@ -84,20 +122,4 @@ describe Projects::Serverless::FunctionsFinder do
end
end
end
-
- describe 'verify if knative is installed' do
- context 'knative is not installed' do
- it 'does not have knative installed' do
- expect(described_class.new(project).installed?).to be false
- end
- end
-
- context 'knative is installed' do
- let!(:knative) { create(:clusters_applications_knative, :installed, cluster: cluster) }
-
- it 'does have knative installed' do
- expect(described_class.new(project).installed?).to be true
- end
- end
- end
end
diff --git a/spec/fixtures/api/schemas/cluster_status.json b/spec/fixtures/api/schemas/cluster_status.json
index 9da07a0b253..695175689b9 100644
--- a/spec/fixtures/api/schemas/cluster_status.json
+++ b/spec/fixtures/api/schemas/cluster_status.json
@@ -36,7 +36,8 @@
"external_hostname": { "type": ["string", "null"] },
"hostname": { "type": ["string", "null"] },
"email": { "type": ["string", "null"] },
- "update_available": { "type": ["boolean", "null"] }
+ "update_available": { "type": ["boolean", "null"] },
+ "can_uninstall": { "type": "boolean" }
},
"required" : [ "name", "status" ]
}
diff --git a/spec/fixtures/api/schemas/entities/issue.json b/spec/fixtures/api/schemas/entities/issue.json
index 162fb9c8108..9898819ef75 100644
--- a/spec/fixtures/api/schemas/entities/issue.json
+++ b/spec/fixtures/api/schemas/entities/issue.json
@@ -5,7 +5,7 @@
"iid": { "type": "integer" },
"author_id": { "type": "integer" },
"description": { "type": ["string", "null"] },
- "lock_version": { "type": ["string", "null"] },
+ "lock_version": { "type": ["integer", "null"] },
"milestone_id": { "type": ["string", "null"] },
"title": { "type": "string" },
"moved_to_id": { "type": ["integer", "null"] },
diff --git a/spec/fixtures/api/schemas/entities/merge_request_basic.json b/spec/fixtures/api/schemas/entities/merge_request_basic.json
index 88a600398b1..ac0a0314455 100644
--- a/spec/fixtures/api/schemas/entities/merge_request_basic.json
+++ b/spec/fixtures/api/schemas/entities/merge_request_basic.json
@@ -23,7 +23,7 @@
},
"task_status": { "type": "string" },
"task_status_short": { "type": "string" },
- "lock_version": { "type": ["string", "null"] }
+ "lock_version": { "type": ["integer", "null"] }
},
"additionalProperties": false
}
diff --git a/spec/fixtures/api/schemas/entities/test_case.json b/spec/fixtures/api/schemas/entities/test_case.json
index c9ba1f3ad18..70f6edeeeb7 100644
--- a/spec/fixtures/api/schemas/entities/test_case.json
+++ b/spec/fixtures/api/schemas/entities/test_case.json
@@ -7,6 +7,7 @@
"properties": {
"status": { "type": "string" },
"name": { "type": "string" },
+ "classname": { "type": "string" },
"execution_time": { "type": "float" },
"system_output": { "type": ["string", "null"] },
"stack_trace": { "type": ["string", "null"] }
diff --git a/spec/fixtures/api/schemas/environment.json b/spec/fixtures/api/schemas/environment.json
index 9a10ab18c30..5b1e3c049fa 100644
--- a/spec/fixtures/api/schemas/environment.json
+++ b/spec/fixtures/api/schemas/environment.json
@@ -31,7 +31,11 @@
"last_deployment": {
"oneOf": [
{ "type": "null" },
- { "$ref": "deployment.json" }
+ { "$ref": "deployment.json" },
+ {
+ "name": { "type": "string" },
+ "build_path": { "type": "string" }
+ }
]
}
},
diff --git a/spec/fixtures/api/schemas/pipeline_schedule.json b/spec/fixtures/api/schemas/pipeline_schedule.json
index c76c6945117..690c4a7d4e8 100644
--- a/spec/fixtures/api/schemas/pipeline_schedule.json
+++ b/spec/fixtures/api/schemas/pipeline_schedule.json
@@ -33,7 +33,7 @@
"additionalProperties": false
},
"variables": {
- "type": ["array", "null"],
+ "type": "array",
"items": { "$ref": "pipeline_schedule_variable.json" }
}
},
diff --git a/spec/fixtures/api/schemas/pipeline_schedule_variable.json b/spec/fixtures/api/schemas/pipeline_schedule_variable.json
index f7ccb2d44a0..022d36cb88c 100644
--- a/spec/fixtures/api/schemas/pipeline_schedule_variable.json
+++ b/spec/fixtures/api/schemas/pipeline_schedule_variable.json
@@ -1,8 +1,14 @@
{
- "type": ["object", "null"],
+ "type": "object",
+ "required": [
+ "key",
+ "value",
+ "variable_type"
+ ],
"properties": {
"key": { "type": "string" },
- "value": { "type": "string" }
+ "value": { "type": "string" },
+ "variable_type": { "type": "string" }
},
"additionalProperties": false
}
diff --git a/spec/fixtures/api/schemas/public_api/v4/job.json b/spec/fixtures/api/schemas/public_api/v4/job.json
index 454935422a0..c038ae0a664 100644
--- a/spec/fixtures/api/schemas/public_api/v4/job.json
+++ b/spec/fixtures/api/schemas/public_api/v4/job.json
@@ -28,6 +28,7 @@
"ref": { "type": "string" },
"tag": { "type": "boolean" },
"coverage": { "type": ["number", "null"] },
+ "allow_failure": { "type": "boolean" },
"created_at": { "type": "string" },
"started_at": { "type": ["null", "string"] },
"finished_at": { "type": ["null", "string"] },
diff --git a/spec/fixtures/api/schemas/public_api/v4/label_basic.json b/spec/fixtures/api/schemas/public_api/v4/label_basic.json
new file mode 100644
index 00000000000..37bbdcb14fe
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/label_basic.json
@@ -0,0 +1,24 @@
+{
+ "type": "object",
+ "required": [
+ "id",
+ "name",
+ "color",
+ "description",
+ "text_color"
+ ],
+ "properties": {
+ "id": { "type": "integer" },
+ "name": { "type": "string" },
+ "color": {
+ "type": "string",
+ "pattern": "^#[0-9A-Fa-f]{3}{1,2}$"
+ },
+ "description": { "type": ["string", "null"] },
+ "text_color": {
+ "type": "string",
+ "pattern": "^#[0-9A-Fa-f]{3}{1,2}$"
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/release.json b/spec/fixtures/api/schemas/public_api/v4/release.json
index 6612c2a9911..6ea0781c1ed 100644
--- a/spec/fixtures/api/schemas/public_api/v4/release.json
+++ b/spec/fixtures/api/schemas/public_api/v4/release.json
@@ -1,12 +1,33 @@
{
"type": "object",
- "required" : [
- "tag_name",
- "description"
- ],
- "properties" : {
- "tag_name": { "type": ["string", "null"] },
- "description": { "type": "string" }
+ "required": ["name", "tag_name", "commit"],
+ "properties": {
+ "name": { "type": "string" },
+ "tag_name": { "type": "string" },
+ "description": { "type": "string" },
+ "description_html": { "type": "string" },
+ "created_at": { "type": "date" },
+ "commit": {
+ "oneOf": [{ "type": "null" }, { "$ref": "commit/basic.json" }]
+ },
+ "author": {
+ "oneOf": [{ "type": "null" }, { "$ref": "user/basic.json" }]
+ },
+ "assets": {
+ "required": ["count", "links", "sources"],
+ "properties": {
+ "count": { "type": "integer" },
+ "links": { "$ref": "../../release/links.json" },
+ "sources": {
+ "type": "array",
+ "items": {
+ "format": "zip",
+ "url": "string"
+ }
+ }
+ },
+ "additionalProperties": false
+ }
},
"additionalProperties": false
}
diff --git a/spec/fixtures/api/schemas/public_api/v4/release/release_for_guest.json b/spec/fixtures/api/schemas/public_api/v4/release/release_for_guest.json
new file mode 100644
index 00000000000..e78398ad1d5
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/release/release_for_guest.json
@@ -0,0 +1,22 @@
+{
+ "type": "object",
+ "required": ["name"],
+ "properties": {
+ "name": { "type": "string" },
+ "description": { "type": "string" },
+ "description_html": { "type": "string" },
+ "created_at": { "type": "date" },
+ "author": {
+ "oneOf": [{ "type": "null" }, { "$ref": "../user/basic.json" }]
+ },
+ "assets": {
+ "required": ["count", "links"],
+ "properties": {
+ "count": { "type": "integer" },
+ "links": { "$ref": "../../../release/links.json" }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/release/releases_for_guest.json b/spec/fixtures/api/schemas/public_api/v4/release/releases_for_guest.json
new file mode 100644
index 00000000000..c13966b28e9
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/release/releases_for_guest.json
@@ -0,0 +1,4 @@
+{
+ "type": "array",
+ "items": { "$ref": "release_for_guest.json" }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/release/tag_release.json b/spec/fixtures/api/schemas/public_api/v4/release/tag_release.json
new file mode 100644
index 00000000000..6612c2a9911
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/release/tag_release.json
@@ -0,0 +1,12 @@
+{
+ "type": "object",
+ "required" : [
+ "tag_name",
+ "description"
+ ],
+ "properties" : {
+ "tag_name": { "type": ["string", "null"] },
+ "description": { "type": "string" }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/releases.json b/spec/fixtures/api/schemas/public_api/v4/releases.json
new file mode 100644
index 00000000000..e26215707fe
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/releases.json
@@ -0,0 +1,4 @@
+{
+ "type": "array",
+ "items": { "$ref": "release.json" }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/tag.json b/spec/fixtures/api/schemas/public_api/v4/tag.json
index 10d4edb7ffb..5713ea1f526 100644
--- a/spec/fixtures/api/schemas/public_api/v4/tag.json
+++ b/spec/fixtures/api/schemas/public_api/v4/tag.json
@@ -14,7 +14,7 @@
"release": {
"oneOf": [
{ "type": "null" },
- { "$ref": "release.json" }
+ { "$ref": "release/tag_release.json" }
]
}
},
diff --git a/spec/fixtures/lib/gitlab/metrics/dashboard/sample_dashboard.yml b/spec/fixtures/lib/gitlab/metrics/dashboard/sample_dashboard.yml
new file mode 100644
index 00000000000..638ecbcc11f
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/metrics/dashboard/sample_dashboard.yml
@@ -0,0 +1,36 @@
+dashboard: 'Test Dashboard'
+priority: 1
+panel_groups:
+- group: Group A
+ priority: 1
+ panels:
+ - title: "Super Chart A1"
+ type: "area-chart"
+ y_label: "y_label"
+ weight: 1
+ metrics:
+ - id: metric_a1
+ query_range: 'query'
+ unit: unit
+ label: Legend Label
+ - title: "Super Chart A2"
+ type: "area-chart"
+ y_label: "y_label"
+ weight: 2
+ metrics:
+ - id: metric_a2
+ query_range: 'query'
+ label: Legend Label
+ unit: unit
+- group: Group B
+ priority: 10
+ panels:
+ - title: "Super Chart B"
+ type: "area-chart"
+ y_label: "y_label"
+ weight: 1
+ metrics:
+ - id: metric_b
+ query_range: 'query'
+ unit: unit
+ label: Legend Label
diff --git a/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/dashboard.json b/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/dashboard.json
new file mode 100644
index 00000000000..1ee1205e29a
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/dashboard.json
@@ -0,0 +1,13 @@
+{
+ "type": "object",
+ "required": ["dashboard", "priority", "panel_groups"],
+ "properties": {
+ "dashboard": { "type": "string" },
+ "priority": { "type": "number" },
+ "panel_groups": {
+ "type": "array",
+ "items": { "$ref": "spec/fixtures/lib/gitlab/metrics/dashboard/schemas/panel_groups.json" }
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/metrics.json b/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/metrics.json
new file mode 100644
index 00000000000..33393805464
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/metrics.json
@@ -0,0 +1,22 @@
+{
+ "type": "object",
+ "required": [
+ "unit",
+ "label",
+ "prometheus_endpoint_path"
+ ],
+ "oneOf": [
+ { "required": ["query"] },
+ { "required": ["query_range"] }
+ ],
+ "properties": {
+ "id": { "type": "string" },
+ "query_range": { "type": "string" },
+ "query": { "type": "string" },
+ "unit": { "type": "string" },
+ "label": { "type": "string" },
+ "track": { "type": "string" },
+ "prometheus_endpoint_path": { "type": "string" }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/panel_groups.json b/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/panel_groups.json
new file mode 100644
index 00000000000..d7a390adcdc
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/panel_groups.json
@@ -0,0 +1,17 @@
+{
+ "type": "object",
+ "required": [
+ "group",
+ "priority",
+ "panels"
+ ],
+ "properties": {
+ "group": { "type": "string" },
+ "priority": { "type": "number" },
+ "panels": {
+ "type": "array",
+ "items": { "$ref": "panels.json" }
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/panels.json b/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/panels.json
new file mode 100644
index 00000000000..1548daacd64
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/panels.json
@@ -0,0 +1,20 @@
+{
+ "type": "object",
+ "required": [
+ "title",
+ "y_label",
+ "weight",
+ "metrics"
+ ],
+ "properties": {
+ "title": { "type": "string" },
+ "type": { "type": "string" },
+ "y_label": { "type": "string" },
+ "weight": { "type": "number" },
+ "metrics": {
+ "type": "array",
+ "items": { "$ref": "metrics.json" }
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/phabricator_responses/auth_failed.json b/spec/fixtures/phabricator_responses/auth_failed.json
new file mode 100644
index 00000000000..50e57c0ba49
--- /dev/null
+++ b/spec/fixtures/phabricator_responses/auth_failed.json
@@ -0,0 +1 @@
+{"result":null,"error_code":"ERR-INVALID-AUTH","error_info":"API token \"api-token\" has the wrong length. API tokens should be 32 characters long."}
diff --git a/spec/fixtures/phabricator_responses/maniphest.search.json b/spec/fixtures/phabricator_responses/maniphest.search.json
new file mode 100644
index 00000000000..6a965007d0c
--- /dev/null
+++ b/spec/fixtures/phabricator_responses/maniphest.search.json
@@ -0,0 +1,98 @@
+{
+ "result": {
+ "data": [
+ {
+ "id": 283,
+ "type": "TASK",
+ "phid": "PHID-TASK-fswfs3wkowjb6cyyxtyx",
+ "fields": {
+ "name": "Things are slow",
+ "description": {
+ "raw": "Things are slow but should be fast!"
+ },
+ "authorPHID": "PHID-USER-nrtht5wijwbxquens3qr",
+ "ownerPHID": "PHID-USER-nrtht5wijwbxquens3qr",
+ "status": {
+ "value": "resolved",
+ "name": "Resolved",
+ "color": null
+ },
+ "priority": {
+ "value": 100,
+ "subpriority": 8589934592,
+ "name": "Super urgent",
+ "color": "pink"
+ },
+ "points": null,
+ "subtype": "default",
+ "closerPHID": "PHID-USER-nrtht5wijwbxquens3qr",
+ "dateClosed": 1374657042,
+ "spacePHID": null,
+ "dateCreated": 1374616241,
+ "dateModified": 1374657044,
+ "policy": {
+ "view": "users",
+ "interact": "users",
+ "edit": "users"
+ },
+ "custom.field-1": null,
+ "custom.field-2": null,
+ "custom.field-3": null
+ },
+ "attachments": {}
+ },
+ {
+ "id": 284,
+ "type": "TASK",
+ "phid": "PHID-TASK-5f73nyq5sjeh4cbmcsnb",
+ "fields": {
+ "name": "Things are broken",
+ "description": {
+ "raw": "Things are broken and should be fixed"
+ },
+ "authorPHID": "PHID-USER-nrtht5wijwbxquens3qr",
+ "ownerPHID": "PHID-USER-h425fsrixz4gjxiyr7ot",
+ "status": {
+ "value": "resolved",
+ "name": "Resolved",
+ "color": null
+ },
+ "priority": {
+ "value": 100,
+ "subpriority": 8589803520,
+ "name": "Super urgent",
+ "color": "pink"
+ },
+ "points": null,
+ "subtype": "default",
+ "closerPHID": "PHID-USER-h425fsrixz4gjxiyr7ot",
+ "dateClosed": 1375049556,
+ "spacePHID": null,
+ "dateCreated": 1374616578,
+ "dateModified": 1375049556,
+ "policy": {
+ "view": "users",
+ "interact": "users",
+ "edit": "users"
+ },
+ "custom.field-1": null,
+ "custom.field-2": null,
+ "custom.field-3": null
+ },
+ "attachments": {}
+ }
+ ],
+ "maps": {},
+ "query": {
+ "queryKey": null
+ },
+ "cursor": {
+ "limit": "2",
+ "after": "284",
+ "before": null,
+ "order": null
+ }
+ },
+ "error_code": null,
+ "error_info": null
+}
diff --git a/spec/fixtures/security-reports/dependency_list/gl-dependency-scanning-report.json b/spec/fixtures/security-reports/dependency_list/gl-dependency-scanning-report.json
new file mode 100644
index 00000000000..1e62d020026
--- /dev/null
+++ b/spec/fixtures/security-reports/dependency_list/gl-dependency-scanning-report.json
@@ -0,0 +1,422 @@
+{
+ "version": "2.1",
+ "vulnerabilities": [
+ {
+ "category": "dependency_scanning",
+ "name": "Vulnerabilities in libxml2",
+ "message": "Vulnerabilities in libxml2 in nokogiri",
+ "description": " The version of libxml2 packaged with Nokogiri contains several vulnerabilities.\r\n Nokogiri has mitigated these issues by upgrading to libxml 2.9.5.\r\n\r\n It was discovered that a type confusion error existed in libxml2. An\r\n attacker could use this to specially construct XML data that\r\n could cause a denial of service or possibly execute arbitrary\r\n code. (CVE-2017-0663)\r\n\r\n It was discovered that libxml2 did not properly validate parsed entity\r\n references. An attacker could use this to specially construct XML\r\n data that could expose sensitive information. (CVE-2017-7375)\r\n\r\n It was discovered that a buffer overflow existed in libxml2 when\r\n handling HTTP redirects. An attacker could use this to specially\r\n construct XML data that could cause a denial of service or possibly\r\n execute arbitrary code. (CVE-2017-7376)\r\n\r\n Marcel Böhme and Van-Thuan Pham discovered a buffer overflow in\r\n libxml2 when handling elements. An attacker could use this to specially\r\n construct XML data that could cause a denial of service or possibly\r\n execute arbitrary code. (CVE-2017-9047)\r\n\r\n Marcel Böhme and Van-Thuan Pham discovered a buffer overread\r\n in libxml2 when handling elements. An attacker could use this\r\n to specially construct XML data that could cause a denial of\r\n service. (CVE-2017-9048)\r\n\r\n Marcel Böhme and Van-Thuan Pham discovered multiple buffer overreads\r\n in libxml2 when handling parameter-entity references. An attacker\r\n could use these to specially construct XML data that could cause a\r\n denial of service. (CVE-2017-9049, CVE-2017-9050)",
+ "cve": "rails/Gemfile.lock:nokogiri:gemnasium:06565b64-486d-4326-b906-890d9915804d",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest version.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "rails/Gemfile.lock",
+ "dependency": {
+ "package": {
+ "name": "nokogiri"
+ },
+ "version": "1.8.0"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-06565b64-486d-4326-b906-890d9915804d",
+ "value": "06565b64-486d-4326-b906-890d9915804d",
+ "url": "https://deps.sec.gitlab.com/packages/gem/nokogiri/versions/1.8.0/advisories"
+ },
+ {
+ "type": "usn",
+ "name": "USN-3424-1",
+ "value": "USN-3424-1",
+ "url": "https://usn.ubuntu.com/3424-1/"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://github.com/sparklemotion/nokogiri/issues/1673"
+ }
+ ]
+ },
+ {
+ "category": "dependency_scanning",
+ "name": "Infinite recursion in parameter entities",
+ "message": "Infinite recursion in parameter entities in nokogiri",
+ "description": "libxml2 incorrectly handles certain parameter entities. An attacker can leverage this with specially constructed XML data to cause libxml2 to consume resources, leading to a denial of service.",
+ "cve": "rails/Gemfile.lock:nokogiri:gemnasium:6a0d56f6-2441-492a-9b14-edb95ac31919",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest version.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "rails/Gemfile.lock",
+ "dependency": {
+ "package": {
+ "name": "nokogiri"
+ },
+ "version": "1.8.0"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-6a0d56f6-2441-492a-9b14-edb95ac31919",
+ "value": "6a0d56f6-2441-492a-9b14-edb95ac31919",
+ "url": "https://deps.sec.gitlab.com/packages/gem/nokogiri/versions/1.8.0/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2017-16932",
+ "value": "CVE-2017-16932",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-16932"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-16932"
+ },
+ {
+ "url": "https://github.com/sparklemotion/nokogiri/issues/1714"
+ },
+ {
+ "url": "https://people.canonical.com/~ubuntu-security/cve/2017/CVE-2017-16932.html"
+ },
+ {
+ "url": "https://usn.ubuntu.com/usn/usn-3504-1/"
+ }
+ ]
+ },
+ {
+ "category": "dependency_scanning",
+ "name": "Denial of Service",
+ "message": "Denial of Service in nokogiri",
+ "description": "libxml2 incorrectly handles certain files. An attacker can use this issue with specially constructed XML data to cause libxml2 to consume resources, leading to a denial of service.\r\n\r\n",
+ "cve": "rails/Gemfile.lock:nokogiri:gemnasium:78658378-bd8f-4d79-81c8-07c419302426",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest version.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "rails/Gemfile.lock",
+ "dependency": {
+ "package": {
+ "name": "nokogiri"
+ },
+ "version": "1.8.0"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-78658378-bd8f-4d79-81c8-07c419302426",
+ "value": "78658378-bd8f-4d79-81c8-07c419302426",
+ "url": "https://deps.sec.gitlab.com/packages/gem/nokogiri/versions/1.8.0/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2017-15412",
+ "value": "CVE-2017-15412",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-15412"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-15412"
+ },
+ {
+ "url": "https://github.com/sparklemotion/nokogiri/issues/1714"
+ },
+ {
+ "url": "https://people.canonical.com/~ubuntu-security/cve/2017/CVE-2017-15412.html"
+ }
+ ]
+ },
+ {
+ "category": "dependency_scanning",
+ "name": "Bypass of a protection mechanism in libxslt",
+ "message": "Bypass of a protection mechanism in libxslt in nokogiri",
+ "description": "libxslt through 1.1.33 allows bypass of a protection mechanism because callers of xsltCheckRead and xsltCheckWrite permit access even upon receiving a -1 error code. xsltCheckRead can return -1 for a crafted URL that is not actually invalid and is subsequently loaded. Vendored version of libxslt has been patched to remediate this vulnerability. Note that this patch is not yet (as of 2019-04-22) in an upstream release of libxslt.",
+ "cve": "rails/Gemfile.lock:nokogiri:gemnasium:1a2e2e6e-67ba-4142-bfa1-3391f5416e4c",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest version if using vendored version of libxslt OR update the system library libxslt to a fixed version",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "rails/Gemfile.lock",
+ "dependency": {
+ "package": {
+ "name": "nokogiri"
+ },
+ "version": "1.8.0"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-1a2e2e6e-67ba-4142-bfa1-3391f5416e4c",
+ "value": "1a2e2e6e-67ba-4142-bfa1-3391f5416e4c",
+ "url": "https://deps.sec.gitlab.com/packages/gem/nokogiri/versions/1.8.0/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2019-11068",
+ "value": "CVE-2019-11068",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11068"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11068"
+ },
+ {
+ "url": "https://github.com/sparklemotion/nokogiri/issues/1892"
+ },
+ {
+ "url": "https://people.canonical.com/~ubuntu-security/cve/CVE-2019-11068"
+ },
+ {
+ "url": "https://security-tracker.debian.org/tracker/CVE-2019-11068"
+ }
+ ]
+ },
+ {
+ "category": "dependency_scanning",
+ "name": "Regular Expression Denial of Service",
+ "message": "Regular Expression Denial of Service in debug",
+ "description": "The debug module is vulnerable to regular expression denial of service when untrusted user input is passed into the `o` formatter. It takes around 50k characters to block for 2 seconds making this a low severity issue.",
+ "cve": "yarn/yarn.lock:debug:gemnasium:37283ed4-0380-40d7-ada7-2d994afcc62a",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest versions.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "yarn/yarn.lock",
+ "dependency": {
+ "package": {
+ "name": "debug"
+ },
+ "version": "1.0.5"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-37283ed4-0380-40d7-ada7-2d994afcc62a",
+ "value": "37283ed4-0380-40d7-ada7-2d994afcc62a",
+ "url": "https://deps.sec.gitlab.com/packages/npm/debug/versions/1.0.5/advisories"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://github.com/visionmedia/debug/issues/501"
+ },
+ {
+ "url": "https://github.com/visionmedia/debug/pull/504"
+ },
+ {
+ "url": "https://nodesecurity.io/advisories/534"
+ }
+ ]
+ },
+ {
+ "category": "dependency_scanning",
+ "name": "Authentication bypass via incorrect DOM traversal and canonicalization",
+ "message": "Authentication bypass via incorrect DOM traversal and canonicalization in saml2-js",
+ "description": "Some XML DOM traversal and canonicalization APIs may be inconsistent in handling of comments within XML nodes. Incorrect use of these APIs by some SAML libraries results in incorrect parsing of the inner text of XML nodes such that any inner text after the comment is lost prior to cryptographically signing the SAML message. Text after the comment therefore has no impact on the signature on the SAML message.\r\n\r\nA remote attacker can modify SAML content for a SAML service provider without invalidating the cryptographic signature, which may allow attackers to bypass primary authentication for the affected SAML service provider.",
+ "cve": "yarn/yarn.lock:saml2-js:gemnasium:9952e574-7b5b-46fa-a270-aeb694198a98",
+ "severity": "Unknown",
+ "solution": "Upgrade to fixed version.\r\n",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "yarn/yarn.lock",
+ "dependency": {
+ "package": {
+ "name": "saml2-js"
+ },
+ "version": "1.5.0"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-9952e574-7b5b-46fa-a270-aeb694198a98",
+ "value": "9952e574-7b5b-46fa-a270-aeb694198a98",
+ "url": "https://deps.sec.gitlab.com/packages/npm/saml2-js/versions/1.5.0/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2017-11429",
+ "value": "CVE-2017-11429",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-11429"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://github.com/Clever/saml2/commit/3546cb61fd541f219abda364c5b919633609ef3d#diff-af730f9f738de1c9ad87596df3f6de84R279"
+ },
+ {
+ "url": "https://github.com/Clever/saml2/issues/127"
+ },
+ {
+ "url": "https://www.kb.cert.org/vuls/id/475445"
+ }
+ ]
+ }
+ ],
+ "remediations": [],
+ "dependency_files": [
+ {
+ "path": "rails/Gemfile.lock",
+ "package_manager": "bundler",
+ "dependencies": [
+ {
+ "package": {
+ "name": "mini_portile2"
+ },
+ "version": "2.2.0"
+ },
+ {
+ "package": {
+ "name": "nokogiri"
+ },
+ "version": "1.8.0"
+ }
+ ]
+ },
+ {
+ "path": "yarn/yarn.lock",
+ "package_manager": "yarn",
+ "dependencies": [
+ {
+ "package": {
+ "name": "async"
+ },
+ "version": "0.2.10"
+ },
+ {
+ "package": {
+ "name": "async"
+ },
+ "version": "1.5.2"
+ },
+ {
+ "package": {
+ "name": "debug"
+ },
+ "version": "1.0.5"
+ },
+ {
+ "package": {
+ "name": "ejs"
+ },
+ "version": "0.8.8"
+ },
+ {
+ "package": {
+ "name": "ms"
+ },
+ "version": "2.0.0"
+ },
+ {
+ "package": {
+ "name": "node-forge"
+ },
+ "version": "0.2.24"
+ },
+ {
+ "package": {
+ "name": "saml2-js"
+ },
+ "version": "1.5.0"
+ },
+ {
+ "package": {
+ "name": "sax"
+ },
+ "version": "1.2.4"
+ },
+ {
+ "package": {
+ "name": "underscore"
+ },
+ "version": "1.9.1"
+ },
+ {
+ "package": {
+ "name": "underscore"
+ },
+ "version": "1.6.0"
+ },
+ {
+ "package": {
+ "name": "xml-crypto"
+ },
+ "version": "0.8.5"
+ },
+ {
+ "package": {
+ "name": "xml-encryption"
+ },
+ "version": "0.7.4"
+ },
+ {
+ "package": {
+ "name": "xml2js"
+ },
+ "version": "0.4.19"
+ },
+ {
+ "package": {
+ "name": "xmlbuilder"
+ },
+ "version": "2.1.0"
+ },
+ {
+ "package": {
+ "name": "xmlbuilder"
+ },
+ "version": "9.0.7"
+ },
+ {
+ "package": {
+ "name": "xmldom"
+ },
+ "version": "0.1.19"
+ },
+ {
+ "package": {
+ "name": "xmldom"
+ },
+ "version": "0.1.27"
+ },
+ {
+ "package": {
+ "name": "xpath.js"
+ },
+ "version": "1.1.0"
+ },
+ {
+ "package": {
+ "name": "xpath"
+ },
+ "version": "0.0.5"
+ }
+ ]
+ }
+ ]
+}
diff --git a/spec/fixtures/security-reports/master/gl-dast-report.json b/spec/fixtures/security-reports/master/gl-dast-report.json
index 3a308bf047e..df459d9419d 100644
--- a/spec/fixtures/security-reports/master/gl-dast-report.json
+++ b/spec/fixtures/security-reports/master/gl-dast-report.json
@@ -1,40 +1,42 @@
{
- "site": {
- "alerts": [
- {
- "sourceid": "3",
- "wascid": "15",
- "cweid": "16",
- "reference": "<p>http://msdn.microsoft.com/en-us/library/ie/gg622941%28v=vs.85%29.aspx</p><p>https://www.owasp.org/index.php/List_of_useful_HTTP_headers</p>",
- "otherinfo": "<p>This issue still applies to error type pages (401, 403, 500, etc) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.</p><p>At \"High\" threshold this scanner will not alert on client or server error responses.</p>",
- "solution": "<p>Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.</p><p>If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.</p>",
- "count": "2",
- "pluginid": "10021",
- "alert": "X-Content-Type-Options Header Missing",
- "name": "X-Content-Type-Options Header Missing",
- "riskcode": "1",
- "confidence": "2",
- "riskdesc": "Low (Medium)",
- "desc": "<p>The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.</p>",
- "instances": [
- {
- "param": "X-Content-Type-Options",
- "method": "GET",
- "uri": "http://bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io"
- },
- {
- "param": "X-Content-Type-Options",
- "method": "GET",
- "uri": "http://bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io/"
- }
- ]
- }
- ],
- "@ssl": "false",
- "@port": "80",
- "@host": "bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io",
- "@name": "http://bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io"
- },
+ "site": [
+ {
+ "alerts": [
+ {
+ "sourceid": "3",
+ "wascid": "15",
+ "cweid": "16",
+ "reference": "<p>http://msdn.microsoft.com/en-us/library/ie/gg622941%28v=vs.85%29.aspx</p><p>https://www.owasp.org/index.php/List_of_useful_HTTP_headers</p>",
+ "otherinfo": "<p>This issue still applies to error type pages (401, 403, 500, etc) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.</p><p>At \"High\" threshold this scanner will not alert on client or server error responses.</p>",
+ "solution": "<p>Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.</p><p>If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.</p>",
+ "count": "2",
+ "pluginid": "10021",
+ "alert": "X-Content-Type-Options Header Missing",
+ "name": "X-Content-Type-Options Header Missing",
+ "riskcode": "1",
+ "confidence": "2",
+ "riskdesc": "Low (Medium)",
+ "desc": "<p>The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.</p>",
+ "instances": [
+ {
+ "param": "X-Content-Type-Options",
+ "method": "GET",
+ "uri": "http://bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io"
+ },
+ {
+ "param": "X-Content-Type-Options",
+ "method": "GET",
+ "uri": "http://bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io/"
+ }
+ ]
+ }
+ ],
+ "@ssl": "false",
+ "@port": "80",
+ "@host": "bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io",
+ "@name": "http://bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io"
+ }
+ ],
"@generated": "Fri, 13 Apr 2018 09:22:01",
"@version": "2.7.0"
}
diff --git a/spec/frontend/activities_spec.js b/spec/frontend/activities_spec.js
new file mode 100644
index 00000000000..d14be3a1f26
--- /dev/null
+++ b/spec/frontend/activities_spec.js
@@ -0,0 +1,70 @@
+/* eslint-disable no-unused-expressions, no-prototype-builtins, no-new, no-shadow */
+
+import $ from 'jquery';
+import Activities from '~/activities';
+import Pager from '~/pager';
+
+describe('Activities', () => {
+ window.gon || (window.gon = {});
+ const fixtureTemplate = 'static/event_filter.html';
+ const filters = [
+ {
+ id: 'all',
+ },
+ {
+ id: 'push',
+ name: 'push events',
+ },
+ {
+ id: 'merged',
+ name: 'merge events',
+ },
+ {
+ id: 'comments',
+ },
+ {
+ id: 'team',
+ },
+ ];
+
+ function getEventName(index) {
+ const filter = filters[index];
+ return filter.hasOwnProperty('name') ? filter.name : filter.id;
+ }
+
+ function getSelector(index) {
+ const filter = filters[index];
+ return `#${filter.id}_event_filter`;
+ }
+
+ beforeEach(() => {
+ loadFixtures(fixtureTemplate);
+ jest.spyOn(Pager, 'init').mockImplementation(() => {});
+ new Activities();
+ });
+
+ for (let i = 0; i < filters.length; i += 1) {
+ (i => {
+ describe(`when selecting ${getEventName(i)}`, () => {
+ beforeEach(() => {
+ $(getSelector(i)).click();
+ });
+
+ for (let x = 0; x < filters.length; x += 1) {
+ (x => {
+ const shouldHighlight = i === x;
+ const testName = shouldHighlight ? 'should highlight' : 'should not highlight';
+
+ it(`${testName} ${getEventName(x)}`, () => {
+ expect(
+ $(getSelector(x))
+ .parent()
+ .hasClass('active'),
+ ).toEqual(shouldHighlight);
+ });
+ })(x);
+ }
+ });
+ })(i);
+ }
+});
diff --git a/spec/frontend/api_spec.js b/spec/frontend/api_spec.js
new file mode 100644
index 00000000000..6010488d9e0
--- /dev/null
+++ b/spec/frontend/api_spec.js
@@ -0,0 +1,477 @@
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import Api from '~/api';
+
+describe('Api', () => {
+ const dummyApiVersion = 'v3000';
+ const dummyUrlRoot = '/gitlab';
+ const dummyGon = {
+ api_version: dummyApiVersion,
+ relative_url_root: dummyUrlRoot,
+ };
+ let originalGon;
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ originalGon = window.gon;
+ window.gon = Object.assign({}, dummyGon);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ window.gon = originalGon;
+ });
+
+ describe('buildUrl', () => {
+ it('adds URL root and fills in API version', () => {
+ const input = '/api/:version/foo/bar';
+ const expectedOutput = `${dummyUrlRoot}/api/${dummyApiVersion}/foo/bar`;
+
+ const builtUrl = Api.buildUrl(input);
+
+ expect(builtUrl).toEqual(expectedOutput);
+ });
+
+ [null, '', '/'].forEach(root => {
+ it(`works when relative_url_root is ${root}`, () => {
+ window.gon.relative_url_root = root;
+ const input = '/api/:version/foo/bar';
+ const expectedOutput = `/api/${dummyApiVersion}/foo/bar`;
+
+ const builtUrl = Api.buildUrl(input);
+
+ expect(builtUrl).toEqual(expectedOutput);
+ });
+ });
+ });
+
+ describe('group', () => {
+ it('fetches a group', done => {
+ const groupId = '123456';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}`;
+ mock.onGet(expectedUrl).reply(200, {
+ name: 'test',
+ });
+
+ Api.group(groupId, response => {
+ expect(response.name).toBe('test');
+ done();
+ });
+ });
+ });
+
+ describe('groupMembers', () => {
+ it('fetches group members', done => {
+ const groupId = '54321';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}/members`;
+ const expectedData = [{ id: 7 }];
+ mock.onGet(expectedUrl).reply(200, expectedData);
+
+ Api.groupMembers(groupId)
+ .then(({ data }) => {
+ expect(data).toEqual(expectedData);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('groups', () => {
+ it('fetches groups', done => {
+ const query = 'dummy query';
+ const options = { unused: 'option' };
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups.json`;
+ mock.onGet(expectedUrl).reply(200, [
+ {
+ name: 'test',
+ },
+ ]);
+
+ Api.groups(query, options, response => {
+ expect(response.length).toBe(1);
+ expect(response[0].name).toBe('test');
+ done();
+ });
+ });
+ });
+
+ describe('namespaces', () => {
+ it('fetches namespaces', done => {
+ const query = 'dummy query';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/namespaces.json`;
+ mock.onGet(expectedUrl).reply(200, [
+ {
+ name: 'test',
+ },
+ ]);
+
+ Api.namespaces(query, response => {
+ expect(response.length).toBe(1);
+ expect(response[0].name).toBe('test');
+ done();
+ });
+ });
+ });
+
+ describe('projects', () => {
+ it('fetches projects with membership when logged in', done => {
+ const query = 'dummy query';
+ const options = { unused: 'option' };
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects.json`;
+ window.gon.current_user_id = 1;
+ mock.onGet(expectedUrl).reply(200, [
+ {
+ name: 'test',
+ },
+ ]);
+
+ Api.projects(query, options, response => {
+ expect(response.length).toBe(1);
+ expect(response[0].name).toBe('test');
+ done();
+ });
+ });
+
+ it('fetches projects without membership when not logged in', done => {
+ const query = 'dummy query';
+ const options = { unused: 'option' };
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects.json`;
+ mock.onGet(expectedUrl).reply(200, [
+ {
+ name: 'test',
+ },
+ ]);
+
+ Api.projects(query, options, response => {
+ expect(response.length).toBe(1);
+ expect(response[0].name).toBe('test');
+ done();
+ });
+ });
+ });
+
+ describe('projectMergeRequests', () => {
+ const projectPath = 'abc';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectPath}/merge_requests`;
+
+ it('fetches all merge requests for a project', done => {
+ const mockData = [{ source_branch: 'foo' }, { source_branch: 'bar' }];
+ mock.onGet(expectedUrl).reply(200, mockData);
+ Api.projectMergeRequests(projectPath)
+ .then(({ data }) => {
+ expect(data.length).toEqual(2);
+ expect(data[0].source_branch).toBe('foo');
+ expect(data[1].source_branch).toBe('bar');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('fetches merge requests filtered with passed params', done => {
+ const params = {
+ source_branch: 'bar',
+ };
+ const mockData = [{ source_branch: 'bar' }];
+ mock.onGet(expectedUrl, { params }).reply(200, mockData);
+
+ Api.projectMergeRequests(projectPath, params)
+ .then(({ data }) => {
+ expect(data.length).toEqual(1);
+ expect(data[0].source_branch).toBe('bar');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('projectMergeRequest', () => {
+ it('fetches a merge request', done => {
+ const projectPath = 'abc';
+ const mergeRequestId = '123456';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectPath}/merge_requests/${mergeRequestId}`;
+ mock.onGet(expectedUrl).reply(200, {
+ title: 'test',
+ });
+
+ Api.projectMergeRequest(projectPath, mergeRequestId)
+ .then(({ data }) => {
+ expect(data.title).toBe('test');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('projectMergeRequestChanges', () => {
+ it('fetches the changes of a merge request', done => {
+ const projectPath = 'abc';
+ const mergeRequestId = '123456';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectPath}/merge_requests/${mergeRequestId}/changes`;
+ mock.onGet(expectedUrl).reply(200, {
+ title: 'test',
+ });
+
+ Api.projectMergeRequestChanges(projectPath, mergeRequestId)
+ .then(({ data }) => {
+ expect(data.title).toBe('test');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('projectMergeRequestVersions', () => {
+ it('fetches the versions of a merge request', done => {
+ const projectPath = 'abc';
+ const mergeRequestId = '123456';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectPath}/merge_requests/${mergeRequestId}/versions`;
+ mock.onGet(expectedUrl).reply(200, [
+ {
+ id: 123,
+ },
+ ]);
+
+ Api.projectMergeRequestVersions(projectPath, mergeRequestId)
+ .then(({ data }) => {
+ expect(data.length).toBe(1);
+ expect(data[0].id).toBe(123);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('projectRunners', () => {
+ it('fetches the runners of a project', done => {
+ const projectPath = 7;
+ const params = { scope: 'active' };
+ const mockData = [{ id: 4 }];
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectPath}/runners`;
+ mock.onGet(expectedUrl, { params }).reply(200, mockData);
+
+ Api.projectRunners(projectPath, { params })
+ .then(({ data }) => {
+ expect(data).toEqual(mockData);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('newLabel', () => {
+ it('creates a new label', done => {
+ const namespace = 'some namespace';
+ const project = 'some project';
+ const labelData = { some: 'data' };
+ const expectedUrl = `${dummyUrlRoot}/${namespace}/${project}/-/labels`;
+ const expectedData = {
+ label: labelData,
+ };
+ mock.onPost(expectedUrl).reply(config => {
+ expect(config.data).toBe(JSON.stringify(expectedData));
+
+ return [
+ 200,
+ {
+ name: 'test',
+ },
+ ];
+ });
+
+ Api.newLabel(namespace, project, labelData, response => {
+ expect(response.name).toBe('test');
+ done();
+ });
+ });
+
+ it('creates a group label', done => {
+ const namespace = 'group/subgroup';
+ const labelData = { some: 'data' };
+ const expectedUrl = Api.buildUrl(Api.groupLabelsPath).replace(':namespace_path', namespace);
+ const expectedData = {
+ label: labelData,
+ };
+ mock.onPost(expectedUrl).reply(config => {
+ expect(config.data).toBe(JSON.stringify(expectedData));
+
+ return [
+ 200,
+ {
+ name: 'test',
+ },
+ ];
+ });
+
+ Api.newLabel(namespace, undefined, labelData, response => {
+ expect(response.name).toBe('test');
+ done();
+ });
+ });
+ });
+
+ describe('groupProjects', () => {
+ it('fetches group projects', done => {
+ const groupId = '123456';
+ const query = 'dummy query';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}/projects.json`;
+ mock.onGet(expectedUrl).reply(200, [
+ {
+ name: 'test',
+ },
+ ]);
+
+ Api.groupProjects(groupId, query, {}, response => {
+ expect(response.length).toBe(1);
+ expect(response[0].name).toBe('test');
+ done();
+ });
+ });
+ });
+
+ describe('issueTemplate', () => {
+ it('fetches an issue template', done => {
+ const namespace = 'some namespace';
+ const project = 'some project';
+ const templateKey = ' template #%?.key ';
+ const templateType = 'template type';
+ const expectedUrl = `${dummyUrlRoot}/${namespace}/${project}/templates/${templateType}/${encodeURIComponent(
+ templateKey,
+ )}`;
+ mock.onGet(expectedUrl).reply(200, 'test');
+
+ Api.issueTemplate(namespace, project, templateKey, templateType, (error, response) => {
+ expect(response).toBe('test');
+ done();
+ });
+ });
+ });
+
+ describe('projectTemplates', () => {
+ it('fetches a list of templates', done => {
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/gitlab-org%2Fgitlab-ce/templates/licenses`;
+
+ mock.onGet(expectedUrl).reply(200, 'test');
+
+ Api.projectTemplates('gitlab-org/gitlab-ce', 'licenses', {}, response => {
+ expect(response).toBe('test');
+ done();
+ });
+ });
+ });
+
+ describe('projectTemplate', () => {
+ it('fetches a single template', done => {
+ const data = { unused: 'option' };
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/gitlab-org%2Fgitlab-ce/templates/licenses/test%20license`;
+
+ mock.onGet(expectedUrl).reply(200, 'test');
+
+ Api.projectTemplate('gitlab-org/gitlab-ce', 'licenses', 'test license', data, response => {
+ expect(response).toBe('test');
+ done();
+ });
+ });
+ });
+
+ describe('users', () => {
+ it('fetches users', done => {
+ const query = 'dummy query';
+ const options = { unused: 'option' };
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/users.json`;
+ mock.onGet(expectedUrl).reply(200, [
+ {
+ name: 'test',
+ },
+ ]);
+
+ Api.users(query, options)
+ .then(({ data }) => {
+ expect(data.length).toBe(1);
+ expect(data[0].name).toBe('test');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('user', () => {
+ it('fetches single user', done => {
+ const userId = '123456';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/users/${userId}`;
+ mock.onGet(expectedUrl).reply(200, {
+ name: 'testuser',
+ });
+
+ Api.user(userId)
+ .then(({ data }) => {
+ expect(data.name).toBe('testuser');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('user status', () => {
+ it('fetches single user status', done => {
+ const userId = '123456';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/users/${userId}/status`;
+ mock.onGet(expectedUrl).reply(200, {
+ message: 'testmessage',
+ });
+
+ Api.userStatus(userId)
+ .then(({ data }) => {
+ expect(data.message).toBe('testmessage');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('commitPipelines', () => {
+ it('fetches pipelines for a given commit', done => {
+ const projectId = 'example/foobar';
+ const commitSha = 'abc123def';
+ const expectedUrl = `${dummyUrlRoot}/${projectId}/commit/${commitSha}/pipelines`;
+ mock.onGet(expectedUrl).reply(200, [
+ {
+ name: 'test',
+ },
+ ]);
+
+ Api.commitPipelines(projectId, commitSha)
+ .then(({ data }) => {
+ expect(data.length).toBe(1);
+ expect(data[0].name).toBe('test');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('createBranch', () => {
+ it('creates new branch', done => {
+ const ref = 'master';
+ const branch = 'new-branch-name';
+ const dummyProjectPath = 'gitlab-org/gitlab-ce';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${encodeURIComponent(
+ dummyProjectPath,
+ )}/repository/branches`;
+
+ jest.spyOn(axios, 'post');
+
+ mock.onPost(expectedUrl).replyOnce(200, {
+ name: branch,
+ });
+
+ Api.createBranch(dummyProjectPath, { ref, branch })
+ .then(({ data }) => {
+ expect(data.name).toBe(branch);
+ expect(axios.post).toHaveBeenCalledWith(expectedUrl, { ref, branch });
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+});
diff --git a/spec/frontend/autosave_spec.js b/spec/frontend/autosave_spec.js
new file mode 100644
index 00000000000..4d9c8f96d62
--- /dev/null
+++ b/spec/frontend/autosave_spec.js
@@ -0,0 +1,151 @@
+import $ from 'jquery';
+import Autosave from '~/autosave';
+import AccessorUtilities from '~/lib/utils/accessor';
+import { useLocalStorageSpy } from 'helpers/local_storage_helper';
+
+describe('Autosave', () => {
+ useLocalStorageSpy();
+
+ let autosave;
+ const field = $('<textarea></textarea>');
+ const key = 'key';
+
+ describe('class constructor', () => {
+ beforeEach(() => {
+ jest.spyOn(AccessorUtilities, 'isLocalStorageAccessSafe').mockReturnValue(true);
+ jest.spyOn(Autosave.prototype, 'restore').mockImplementation(() => {});
+ });
+
+ it('should set .isLocalStorageAvailable', () => {
+ autosave = new Autosave(field, key);
+
+ expect(AccessorUtilities.isLocalStorageAccessSafe).toHaveBeenCalled();
+ expect(autosave.isLocalStorageAvailable).toBe(true);
+ });
+ });
+
+ describe('restore', () => {
+ beforeEach(() => {
+ autosave = {
+ field,
+ key,
+ };
+ });
+
+ describe('if .isLocalStorageAvailable is `false`', () => {
+ beforeEach(() => {
+ autosave.isLocalStorageAvailable = false;
+
+ Autosave.prototype.restore.call(autosave);
+ });
+
+ it('should not call .getItem', () => {
+ expect(window.localStorage.getItem).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('if .isLocalStorageAvailable is `true`', () => {
+ beforeEach(() => {
+ autosave.isLocalStorageAvailable = true;
+ });
+
+ it('should call .getItem', () => {
+ Autosave.prototype.restore.call(autosave);
+
+ expect(window.localStorage.getItem).toHaveBeenCalledWith(key);
+ });
+
+ it('triggers jquery event', () => {
+ jest.spyOn(autosave.field, 'trigger').mockImplementation(() => {});
+
+ Autosave.prototype.restore.call(autosave);
+
+ expect(field.trigger).toHaveBeenCalled();
+ });
+
+ it('triggers native event', done => {
+ autosave.field.get(0).addEventListener('change', () => {
+ done();
+ });
+
+ Autosave.prototype.restore.call(autosave);
+ });
+ });
+
+ describe('if field gets deleted from DOM', () => {
+ beforeEach(() => {
+ autosave.field = $('.not-a-real-element');
+ });
+
+ it('does not trigger event', () => {
+ jest.spyOn(field, 'trigger');
+
+ expect(field.trigger).not.toHaveBeenCalled();
+ });
+ });
+ });
+
+ describe('save', () => {
+ beforeEach(() => {
+ autosave = { reset: jest.fn() };
+ autosave.field = field;
+ field.val('value');
+ });
+
+ describe('if .isLocalStorageAvailable is `false`', () => {
+ beforeEach(() => {
+ autosave.isLocalStorageAvailable = false;
+
+ Autosave.prototype.save.call(autosave);
+ });
+
+ it('should not call .setItem', () => {
+ expect(window.localStorage.setItem).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('if .isLocalStorageAvailable is `true`', () => {
+ beforeEach(() => {
+ autosave.isLocalStorageAvailable = true;
+
+ Autosave.prototype.save.call(autosave);
+ });
+
+ it('should call .setItem', () => {
+ expect(window.localStorage.setItem).toHaveBeenCalled();
+ });
+ });
+ });
+
+ describe('reset', () => {
+ beforeEach(() => {
+ autosave = {
+ key,
+ };
+ });
+
+ describe('if .isLocalStorageAvailable is `false`', () => {
+ beforeEach(() => {
+ autosave.isLocalStorageAvailable = false;
+
+ Autosave.prototype.reset.call(autosave);
+ });
+
+ it('should not call .removeItem', () => {
+ expect(window.localStorage.removeItem).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('if .isLocalStorageAvailable is `true`', () => {
+ beforeEach(() => {
+ autosave.isLocalStorageAvailable = true;
+
+ Autosave.prototype.reset.call(autosave);
+ });
+
+ it('should call .removeItem', () => {
+ expect(window.localStorage.removeItem).toHaveBeenCalledWith(key);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/boards/modal_store_spec.js b/spec/frontend/boards/modal_store_spec.js
index 3257a3fb8a3..4dd27e94d97 100644
--- a/spec/frontend/boards/modal_store_spec.js
+++ b/spec/frontend/boards/modal_store_spec.js
@@ -1,7 +1,7 @@
/* global ListIssue */
-import '~/vue_shared/models/label';
-import '~/vue_shared/models/assignee';
+import '~/boards/models/label';
+import '~/boards/models/assignee';
import '~/boards/models/issue';
import '~/boards/models/list';
import Store from '~/boards/stores/modal_store';
diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js
new file mode 100644
index 00000000000..d23393db60d
--- /dev/null
+++ b/spec/frontend/boards/stores/actions_spec.js
@@ -0,0 +1,67 @@
+import actions from '~/boards/stores/actions';
+
+const expectNotImplemented = action => {
+ it('is not implemented', () => {
+ expect(action).toThrow(new Error('Not implemented!'));
+ });
+};
+
+describe('setEndpoints', () => {
+ expectNotImplemented(actions.setEndpoints);
+});
+
+describe('fetchLists', () => {
+ expectNotImplemented(actions.fetchLists);
+});
+
+describe('generateDefaultLists', () => {
+ expectNotImplemented(actions.generateDefaultLists);
+});
+
+describe('createList', () => {
+ expectNotImplemented(actions.createList);
+});
+
+describe('updateList', () => {
+ expectNotImplemented(actions.updateList);
+});
+
+describe('deleteList', () => {
+ expectNotImplemented(actions.deleteList);
+});
+
+describe('fetchIssuesForList', () => {
+ expectNotImplemented(actions.fetchIssuesForList);
+});
+
+describe('moveIssue', () => {
+ expectNotImplemented(actions.moveIssue);
+});
+
+describe('createNewIssue', () => {
+ expectNotImplemented(actions.createNewIssue);
+});
+
+describe('fetchBacklog', () => {
+ expectNotImplemented(actions.fetchBacklog);
+});
+
+describe('bulkUpdateIssues', () => {
+ expectNotImplemented(actions.bulkUpdateIssues);
+});
+
+describe('fetchIssue', () => {
+ expectNotImplemented(actions.fetchIssue);
+});
+
+describe('toggleIssueSubscription', () => {
+ expectNotImplemented(actions.toggleIssueSubscription);
+});
+
+describe('showPage', () => {
+ expectNotImplemented(actions.showPage);
+});
+
+describe('toggleEmptyState', () => {
+ expectNotImplemented(actions.toggleEmptyState);
+});
diff --git a/spec/frontend/boards/stores/mutations_spec.js b/spec/frontend/boards/stores/mutations_spec.js
new file mode 100644
index 00000000000..aa477766978
--- /dev/null
+++ b/spec/frontend/boards/stores/mutations_spec.js
@@ -0,0 +1,91 @@
+import mutations from '~/boards/stores/mutations';
+
+const expectNotImplemented = action => {
+ it('is not implemented', () => {
+ expect(action).toThrow(new Error('Not implemented!'));
+ });
+};
+
+describe('SET_ENDPOINTS', () => {
+ expectNotImplemented(mutations.SET_ENDPOINTS);
+});
+
+describe('REQUEST_ADD_LIST', () => {
+ expectNotImplemented(mutations.REQUEST_ADD_LIST);
+});
+
+describe('RECEIVE_ADD_LIST_SUCCESS', () => {
+ expectNotImplemented(mutations.RECEIVE_ADD_LIST_SUCCESS);
+});
+
+describe('RECEIVE_ADD_LIST_ERROR', () => {
+ expectNotImplemented(mutations.RECEIVE_ADD_LIST_ERROR);
+});
+
+describe('REQUEST_UPDATE_LIST', () => {
+ expectNotImplemented(mutations.REQUEST_UPDATE_LIST);
+});
+
+describe('RECEIVE_UPDATE_LIST_SUCCESS', () => {
+ expectNotImplemented(mutations.RECEIVE_UPDATE_LIST_SUCCESS);
+});
+
+describe('RECEIVE_UPDATE_LIST_ERROR', () => {
+ expectNotImplemented(mutations.RECEIVE_UPDATE_LIST_ERROR);
+});
+
+describe('REQUEST_REMOVE_LIST', () => {
+ expectNotImplemented(mutations.REQUEST_REMOVE_LIST);
+});
+
+describe('RECEIVE_REMOVE_LIST_SUCCESS', () => {
+ expectNotImplemented(mutations.RECEIVE_REMOVE_LIST_SUCCESS);
+});
+
+describe('RECEIVE_REMOVE_LIST_ERROR', () => {
+ expectNotImplemented(mutations.RECEIVE_REMOVE_LIST_ERROR);
+});
+
+describe('REQUEST_ADD_ISSUE', () => {
+ expectNotImplemented(mutations.REQUEST_ADD_ISSUE);
+});
+
+describe('RECEIVE_ADD_ISSUE_SUCCESS', () => {
+ expectNotImplemented(mutations.RECEIVE_ADD_ISSUE_SUCCESS);
+});
+
+describe('RECEIVE_ADD_ISSUE_ERROR', () => {
+ expectNotImplemented(mutations.RECEIVE_ADD_ISSUE_ERROR);
+});
+
+describe('REQUEST_MOVE_ISSUE', () => {
+ expectNotImplemented(mutations.REQUEST_MOVE_ISSUE);
+});
+
+describe('RECEIVE_MOVE_ISSUE_SUCCESS', () => {
+ expectNotImplemented(mutations.RECEIVE_MOVE_ISSUE_SUCCESS);
+});
+
+describe('RECEIVE_MOVE_ISSUE_ERROR', () => {
+ expectNotImplemented(mutations.RECEIVE_MOVE_ISSUE_ERROR);
+});
+
+describe('REQUEST_UPDATE_ISSUE', () => {
+ expectNotImplemented(mutations.REQUEST_UPDATE_ISSUE);
+});
+
+describe('RECEIVE_UPDATE_ISSUE_SUCCESS', () => {
+ expectNotImplemented(mutations.RECEIVE_UPDATE_ISSUE_SUCCESS);
+});
+
+describe('RECEIVE_UPDATE_ISSUE_ERROR', () => {
+ expectNotImplemented(mutations.RECEIVE_UPDATE_ISSUE_ERROR);
+});
+
+describe('SET_CURRENT_PAGE', () => {
+ expectNotImplemented(mutations.SET_CURRENT_PAGE);
+});
+
+describe('TOGGLE_EMPTY_STATE', () => {
+ expectNotImplemented(mutations.TOGGLE_EMPTY_STATE);
+});
diff --git a/spec/frontend/boards/stores/state_spec.js b/spec/frontend/boards/stores/state_spec.js
new file mode 100644
index 00000000000..35490a63567
--- /dev/null
+++ b/spec/frontend/boards/stores/state_spec.js
@@ -0,0 +1,11 @@
+import createState from '~/boards/stores/state';
+
+describe('createState', () => {
+ it('is a function', () => {
+ expect(createState).toEqual(expect.any(Function));
+ });
+
+ it('returns an object', () => {
+ expect(createState()).toEqual(expect.any(Object));
+ });
+});
diff --git a/spec/frontend/clusters/clusters_bundle_spec.js b/spec/frontend/clusters/clusters_bundle_spec.js
index 33a35069004..6de06a9e2d5 100644
--- a/spec/frontend/clusters/clusters_bundle_spec.js
+++ b/spec/frontend/clusters/clusters_bundle_spec.js
@@ -1,9 +1,9 @@
import Clusters from '~/clusters/clusters_bundle';
import {
- REQUEST_SUBMITTED,
- REQUEST_FAILURE,
APPLICATION_STATUS,
INGRESS_DOMAIN_SUFFIX,
+ APPLICATIONS,
+ RUNNER,
} from '~/clusters/constants';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
@@ -11,6 +11,8 @@ import { loadHTMLFixture } from 'helpers/fixtures';
import { setTestTimeout } from 'helpers/timeout';
import $ from 'jquery';
+const { INSTALLING, INSTALLABLE, INSTALLED, UNINSTALLING } = APPLICATION_STATUS;
+
describe('Clusters', () => {
setTestTimeout(1000);
@@ -93,7 +95,7 @@ describe('Clusters', () => {
it('does not show alert when things transition from initial null state to something', () => {
cluster.checkForNewInstalls(INITIAL_APP_MAP, {
...INITIAL_APP_MAP,
- helm: { status: APPLICATION_STATUS.INSTALLABLE, title: 'Helm Tiller' },
+ helm: { status: INSTALLABLE, title: 'Helm Tiller' },
});
const flashMessage = document.querySelector('.js-cluster-application-notice .flash-text');
@@ -105,11 +107,11 @@ describe('Clusters', () => {
cluster.checkForNewInstalls(
{
...INITIAL_APP_MAP,
- helm: { status: APPLICATION_STATUS.INSTALLING, title: 'Helm Tiller' },
+ helm: { status: INSTALLING, title: 'Helm Tiller' },
},
{
...INITIAL_APP_MAP,
- helm: { status: APPLICATION_STATUS.INSTALLED, title: 'Helm Tiller' },
+ helm: { status: INSTALLED, title: 'Helm Tiller' },
},
);
@@ -125,13 +127,13 @@ describe('Clusters', () => {
cluster.checkForNewInstalls(
{
...INITIAL_APP_MAP,
- helm: { status: APPLICATION_STATUS.INSTALLING, title: 'Helm Tiller' },
- ingress: { status: APPLICATION_STATUS.INSTALLABLE, title: 'Ingress' },
+ helm: { status: INSTALLING, title: 'Helm Tiller' },
+ ingress: { status: INSTALLABLE, title: 'Ingress' },
},
{
...INITIAL_APP_MAP,
- helm: { status: APPLICATION_STATUS.INSTALLED, title: 'Helm Tiller' },
- ingress: { status: APPLICATION_STATUS.INSTALLED, title: 'Ingress' },
+ helm: { status: INSTALLED, title: 'Helm Tiller' },
+ ingress: { status: INSTALLED, title: 'Ingress' },
},
);
@@ -212,76 +214,81 @@ describe('Clusters', () => {
expect(cluster.errorContainer.classList.contains('hidden')).toBeFalsy();
});
});
- });
- describe('installApplication', () => {
- it('tries to install helm', () => {
- jest.spyOn(cluster.service, 'installApplication').mockResolvedValueOnce();
+ describe('when cluster is unreachable', () => {
+ it('should show the unreachable warning container', () => {
+ cluster.updateContainer(null, 'unreachable');
- expect(cluster.store.state.applications.helm.requestStatus).toEqual(null);
+ expect(cluster.unreachableContainer.classList.contains('hidden')).toBe(false);
+ });
+ });
- cluster.installApplication({ id: 'helm' });
+ describe('when cluster has an authentication failure', () => {
+ it('should show the authentication failure warning container', () => {
+ cluster.updateContainer(null, 'authentication_failure');
- expect(cluster.store.state.applications.helm.requestStatus).toEqual(REQUEST_SUBMITTED);
- expect(cluster.store.state.applications.helm.requestReason).toEqual(null);
- expect(cluster.service.installApplication).toHaveBeenCalledWith('helm', undefined);
+ expect(cluster.authenticationFailureContainer.classList.contains('hidden')).toBe(false);
+ });
});
+ });
- it('tries to install ingress', () => {
+ describe('installApplication', () => {
+ it.each(APPLICATIONS)('tries to install %s', applicationId => {
jest.spyOn(cluster.service, 'installApplication').mockResolvedValueOnce();
- expect(cluster.store.state.applications.ingress.requestStatus).toEqual(null);
+ cluster.store.state.applications[applicationId].status = INSTALLABLE;
- cluster.installApplication({ id: 'ingress' });
+ cluster.installApplication({ id: applicationId });
- expect(cluster.store.state.applications.ingress.requestStatus).toEqual(REQUEST_SUBMITTED);
- expect(cluster.store.state.applications.ingress.requestReason).toEqual(null);
- expect(cluster.service.installApplication).toHaveBeenCalledWith('ingress', undefined);
+ expect(cluster.store.state.applications[applicationId].status).toEqual(INSTALLING);
+ expect(cluster.store.state.applications[applicationId].requestReason).toEqual(null);
+ expect(cluster.service.installApplication).toHaveBeenCalledWith(applicationId, undefined);
});
- it('tries to install runner', () => {
- jest.spyOn(cluster.service, 'installApplication').mockResolvedValueOnce();
+ it('sets error request status when the request fails', () => {
+ jest
+ .spyOn(cluster.service, 'installApplication')
+ .mockRejectedValueOnce(new Error('STUBBED ERROR'));
- expect(cluster.store.state.applications.runner.requestStatus).toEqual(null);
+ cluster.store.state.applications.helm.status = INSTALLABLE;
+
+ const promise = cluster.installApplication({ id: 'helm' });
- cluster.installApplication({ id: 'runner' });
+ return promise.then(() => {
+ expect(cluster.store.state.applications.helm.status).toEqual(INSTALLABLE);
+ expect(cluster.store.state.applications.helm.installFailed).toBe(true);
- expect(cluster.store.state.applications.runner.requestStatus).toEqual(REQUEST_SUBMITTED);
- expect(cluster.store.state.applications.runner.requestReason).toEqual(null);
- expect(cluster.service.installApplication).toHaveBeenCalledWith('runner', undefined);
+ expect(cluster.store.state.applications.helm.requestReason).toBeDefined();
+ });
});
+ });
- it('tries to install jupyter', () => {
- jest.spyOn(cluster.service, 'installApplication').mockResolvedValueOnce();
+ describe('uninstallApplication', () => {
+ it.each(APPLICATIONS)('tries to uninstall %s', applicationId => {
+ jest.spyOn(cluster.service, 'uninstallApplication').mockResolvedValueOnce();
- expect(cluster.store.state.applications.jupyter.requestStatus).toEqual(null);
- cluster.installApplication({
- id: 'jupyter',
- params: { hostname: cluster.store.state.applications.jupyter.hostname },
- });
+ cluster.store.state.applications[applicationId].status = INSTALLED;
- expect(cluster.store.state.applications.jupyter.requestStatus).toEqual(REQUEST_SUBMITTED);
- expect(cluster.store.state.applications.jupyter.requestReason).toEqual(null);
- expect(cluster.service.installApplication).toHaveBeenCalledWith('jupyter', {
- hostname: cluster.store.state.applications.jupyter.hostname,
- });
+ cluster.uninstallApplication({ id: applicationId });
+
+ expect(cluster.store.state.applications[applicationId].status).toEqual(UNINSTALLING);
+ expect(cluster.store.state.applications[applicationId].requestReason).toEqual(null);
+ expect(cluster.service.uninstallApplication).toHaveBeenCalledWith(applicationId);
});
- it('sets error request status when the request fails', () => {
+ it('sets error request status when the uninstall request fails', () => {
jest
- .spyOn(cluster.service, 'installApplication')
+ .spyOn(cluster.service, 'uninstallApplication')
.mockRejectedValueOnce(new Error('STUBBED ERROR'));
- expect(cluster.store.state.applications.helm.requestStatus).toEqual(null);
+ cluster.store.state.applications.helm.status = INSTALLED;
- const promise = cluster.installApplication({ id: 'helm' });
-
- expect(cluster.store.state.applications.helm.requestStatus).toEqual(REQUEST_SUBMITTED);
- expect(cluster.store.state.applications.helm.requestReason).toEqual(null);
- expect(cluster.service.installApplication).toHaveBeenCalled();
+ const promise = cluster.uninstallApplication({ id: 'helm' });
return promise.then(() => {
- expect(cluster.store.state.applications.helm.requestStatus).toEqual(REQUEST_FAILURE);
+ expect(cluster.store.state.applications.helm.status).toEqual(INSTALLED);
+ expect(cluster.store.state.applications.helm.uninstallFailed).toBe(true);
+
expect(cluster.store.state.applications.helm.requestReason).toBeDefined();
});
});
@@ -315,18 +322,16 @@ describe('Clusters', () => {
});
describe('toggleIngressDomainHelpText', () => {
- const { INSTALLED, INSTALLABLE, NOT_INSTALLABLE } = APPLICATION_STATUS;
let ingressPreviousState;
let ingressNewState;
beforeEach(() => {
- ingressPreviousState = { status: INSTALLABLE };
- ingressNewState = { status: INSTALLED, externalIp: '127.0.0.1' };
+ ingressPreviousState = { externalIp: null };
+ ingressNewState = { externalIp: '127.0.0.1' };
});
- describe(`when ingress application new status is ${INSTALLED}`, () => {
+ describe(`when ingress have an external ip assigned`, () => {
beforeEach(() => {
- ingressNewState.status = INSTALLED;
cluster.toggleIngressDomainHelpText(ingressPreviousState, ingressNewState);
});
@@ -341,9 +346,10 @@ describe('Clusters', () => {
});
});
- describe(`when ingress application new status is different from ${INSTALLED}`, () => {
+ describe(`when ingress does not have an external ip assigned`, () => {
it('hides custom domain help text', () => {
- ingressNewState.status = NOT_INSTALLABLE;
+ ingressPreviousState.externalIp = '127.0.0.1';
+ ingressNewState.externalIp = null;
cluster.ingressDomainHelpText.classList.remove('hide');
cluster.toggleIngressDomainHelpText(ingressPreviousState, ingressNewState);
@@ -351,26 +357,31 @@ describe('Clusters', () => {
expect(cluster.ingressDomainHelpText.classList.contains('hide')).toEqual(true);
});
});
+ });
- describe('when ingress application new status and old status are the same', () => {
- it('does not display custom domain help text', () => {
- ingressPreviousState.status = INSTALLED;
- ingressNewState.status = ingressPreviousState.status;
+ describe('updateApplication', () => {
+ const params = { version: '1.0.0' };
+ let storeUpdateApplication;
+ let installApplication;
- cluster.toggleIngressDomainHelpText(ingressPreviousState, ingressNewState);
+ beforeEach(() => {
+ storeUpdateApplication = jest.spyOn(cluster.store, 'updateApplication');
+ installApplication = jest.spyOn(cluster.service, 'installApplication');
- expect(cluster.ingressDomainHelpText.classList.contains('hide')).toEqual(true);
- });
+ cluster.updateApplication({ id: RUNNER, params });
});
- describe(`when ingress new status is ${INSTALLED} and there isn’t an ip assigned`, () => {
- it('does not display custom domain help text', () => {
- ingressNewState.externalIp = null;
+ afterEach(() => {
+ storeUpdateApplication.mockRestore();
+ installApplication.mockRestore();
+ });
- cluster.toggleIngressDomainHelpText(ingressPreviousState, ingressNewState);
+ it('calls store updateApplication method', () => {
+ expect(storeUpdateApplication).toHaveBeenCalledWith(RUNNER);
+ });
- expect(cluster.ingressDomainHelpText.classList.contains('hide')).toEqual(true);
- });
+ it('sends installApplication request', () => {
+ expect(installApplication).toHaveBeenCalledWith(RUNNER, params);
});
});
});
diff --git a/spec/frontend/clusters/components/application_row_spec.js b/spec/frontend/clusters/components/application_row_spec.js
index b28d0075d06..9f127ccb690 100644
--- a/spec/frontend/clusters/components/application_row_spec.js
+++ b/spec/frontend/clusters/components/application_row_spec.js
@@ -1,7 +1,10 @@
import Vue from 'vue';
+import { shallowMount } from '@vue/test-utils';
import eventHub from '~/clusters/event_hub';
-import { APPLICATION_STATUS, REQUEST_SUBMITTED, REQUEST_FAILURE } from '~/clusters/constants';
+import { APPLICATION_STATUS } from '~/clusters/constants';
import applicationRow from '~/clusters/components/application_row.vue';
+import UninstallApplicationConfirmationModal from '~/clusters/components/uninstall_application_confirmation_modal.vue';
+
import mountComponent from 'helpers/vue_mount_component_helper';
import { DEFAULT_APPLICATION_STATE } from '../services/mock_data';
@@ -80,17 +83,6 @@ describe('Application Row', () => {
expect(vm.installButtonDisabled).toEqual(false);
});
- it('has loading "Installing" when APPLICATION_STATUS.SCHEDULED', () => {
- vm = mountComponent(ApplicationRow, {
- ...DEFAULT_APPLICATION_STATE,
- status: APPLICATION_STATUS.SCHEDULED,
- });
-
- expect(vm.installButtonLabel).toEqual('Installing');
- expect(vm.installButtonLoading).toEqual(true);
- expect(vm.installButtonDisabled).toEqual(true);
- });
-
it('has loading "Installing" when APPLICATION_STATUS.INSTALLING', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
@@ -102,22 +94,12 @@ describe('Application Row', () => {
expect(vm.installButtonDisabled).toEqual(true);
});
- it('has loading "Installing" when REQUEST_SUBMITTED', () => {
- vm = mountComponent(ApplicationRow, {
- ...DEFAULT_APPLICATION_STATE,
- status: APPLICATION_STATUS.INSTALLABLE,
- requestStatus: REQUEST_SUBMITTED,
- });
-
- expect(vm.installButtonLabel).toEqual('Installing');
- expect(vm.installButtonLoading).toEqual(true);
- expect(vm.installButtonDisabled).toEqual(true);
- });
-
- it('has disabled "Installed" when APPLICATION_STATUS.INSTALLED', () => {
+ it('has disabled "Installed" when application is installed and not uninstallable', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
status: APPLICATION_STATUS.INSTALLED,
+ installed: true,
+ uninstallable: false,
});
expect(vm.installButtonLabel).toEqual('Installed');
@@ -125,21 +107,23 @@ describe('Application Row', () => {
expect(vm.installButtonDisabled).toEqual(true);
});
- it('has disabled "Installed" when APPLICATION_STATUS.UPDATING', () => {
+ it('hides when application is installed and uninstallable', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
- status: APPLICATION_STATUS.UPDATING,
+ status: APPLICATION_STATUS.INSTALLED,
+ installed: true,
+ uninstallable: true,
});
+ const installBtn = vm.$el.querySelector('.js-cluster-application-install-button');
- expect(vm.installButtonLabel).toEqual('Installed');
- expect(vm.installButtonLoading).toEqual(false);
- expect(vm.installButtonDisabled).toEqual(true);
+ expect(installBtn).toBe(null);
});
- it('has enabled "Install" when APPLICATION_STATUS.ERROR', () => {
+ it('has enabled "Install" when install fails', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
- status: APPLICATION_STATUS.ERROR,
+ status: APPLICATION_STATUS.INSTALLABLE,
+ installFailed: true,
});
expect(vm.installButtonLabel).toEqual('Install');
@@ -151,7 +135,6 @@ describe('Application Row', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
status: APPLICATION_STATUS.INSTALLABLE,
- requestStatus: REQUEST_FAILURE,
});
expect(vm.installButtonLabel).toEqual('Install');
@@ -208,38 +191,92 @@ describe('Application Row', () => {
});
});
- describe('Upgrade button', () => {
+ describe('Uninstall button', () => {
+ it('displays button when app is installed and uninstallable', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ installed: true,
+ uninstallable: true,
+ status: APPLICATION_STATUS.NOT_INSTALLABLE,
+ });
+ const uninstallButton = vm.$el.querySelector('.js-cluster-application-uninstall-button');
+
+ expect(uninstallButton).toBeTruthy();
+ });
+
+ it('displays a success toast message if application uninstall was successful', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ title: 'GitLab Runner',
+ uninstallSuccessful: false,
+ });
+
+ vm.$toast = { show: jest.fn() };
+ vm.uninstallSuccessful = true;
+
+ return vm.$nextTick(() => {
+ expect(vm.$toast.show).toHaveBeenCalledWith('GitLab Runner uninstalled successfully.');
+ });
+ });
+ });
+
+ describe('when confirmation modal triggers confirm event', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = shallowMount(ApplicationRow, {
+ propsData: {
+ ...DEFAULT_APPLICATION_STATE,
+ },
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('triggers uninstallApplication event', () => {
+ jest.spyOn(eventHub, '$emit');
+ wrapper.find(UninstallApplicationConfirmationModal).vm.$emit('confirm');
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('uninstallApplication', {
+ id: DEFAULT_APPLICATION_STATE.id,
+ });
+ });
+ });
+
+ describe('Update button', () => {
it('has indeterminate state on page load', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
status: null,
});
- const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
+ const updateBtn = vm.$el.querySelector('.js-cluster-application-update-button');
- expect(upgradeBtn).toBe(null);
+ expect(updateBtn).toBe(null);
});
- it('has enabled "Upgrade" when "upgradeAvailable" is true', () => {
+ it('has enabled "Update" when "updateAvailable" is true', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
- upgradeAvailable: true,
+ updateAvailable: true,
});
- const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
+ const updateBtn = vm.$el.querySelector('.js-cluster-application-update-button');
- expect(upgradeBtn).not.toBe(null);
- expect(upgradeBtn.innerHTML).toContain('Upgrade');
+ expect(updateBtn).not.toBe(null);
+ expect(updateBtn.innerHTML).toContain('Update');
});
- it('has enabled "Retry update" when APPLICATION_STATUS.UPDATE_ERRORED', () => {
+ it('has enabled "Retry update" when update process fails', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
- status: APPLICATION_STATUS.UPDATE_ERRORED,
+ status: APPLICATION_STATUS.INSTALLED,
+ updateFailed: true,
});
- const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
+ const updateBtn = vm.$el.querySelector('.js-cluster-application-update-button');
- expect(upgradeBtn).not.toBe(null);
- expect(vm.upgradeFailed).toBe(true);
- expect(upgradeBtn.innerHTML).toContain('Retry update');
+ expect(updateBtn).not.toBe(null);
+ expect(updateBtn.innerHTML).toContain('Retry update');
});
it('has disabled "Updating" when APPLICATION_STATUS.UPDATING', () => {
@@ -247,160 +284,206 @@ describe('Application Row', () => {
...DEFAULT_APPLICATION_STATE,
status: APPLICATION_STATUS.UPDATING,
});
- const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
+ const updateBtn = vm.$el.querySelector('.js-cluster-application-update-button');
- expect(upgradeBtn).not.toBe(null);
- expect(vm.isUpgrading).toBe(true);
- expect(upgradeBtn.innerHTML).toContain('Updating');
+ expect(updateBtn).not.toBe(null);
+ expect(vm.isUpdating).toBe(true);
+ expect(updateBtn.innerHTML).toContain('Updating');
});
- it('clicking upgrade button emits event', () => {
+ it('clicking update button emits event', () => {
jest.spyOn(eventHub, '$emit');
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
- status: APPLICATION_STATUS.UPDATE_ERRORED,
+ status: APPLICATION_STATUS.INSTALLED,
+ updateAvailable: true,
});
- const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
+ const updateBtn = vm.$el.querySelector('.js-cluster-application-update-button');
- upgradeBtn.click();
+ updateBtn.click();
- expect(eventHub.$emit).toHaveBeenCalledWith('upgradeApplication', {
+ expect(eventHub.$emit).toHaveBeenCalledWith('updateApplication', {
id: DEFAULT_APPLICATION_STATE.id,
params: {},
});
});
- it('clicking disabled upgrade button emits nothing', () => {
+ it('clicking disabled update button emits nothing', () => {
jest.spyOn(eventHub, '$emit');
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
status: APPLICATION_STATUS.UPDATING,
});
- const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
+ const updateBtn = vm.$el.querySelector('.js-cluster-application-update-button');
- upgradeBtn.click();
+ updateBtn.click();
expect(eventHub.$emit).not.toHaveBeenCalled();
});
- it('displays an error message if application upgrade failed', () => {
+ it('displays an error message if application update failed', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
title: 'GitLab Runner',
- status: APPLICATION_STATUS.UPDATE_ERRORED,
+ status: APPLICATION_STATUS.INSTALLED,
+ updateFailed: true,
});
- const failureMessage = vm.$el.querySelector(
- '.js-cluster-application-upgrade-failure-message',
- );
+ const failureMessage = vm.$el.querySelector('.js-cluster-application-update-details');
expect(failureMessage).not.toBe(null);
expect(failureMessage.innerHTML).toContain(
'Update failed. Please check the logs and try again.',
);
});
+
+ it('displays a success toast message if application update was successful', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ title: 'GitLab Runner',
+ updateSuccessful: false,
+ });
+
+ vm.$toast = { show: jest.fn() };
+ vm.updateSuccessful = true;
+
+ return vm.$nextTick(() => {
+ expect(vm.$toast.show).toHaveBeenCalledWith('GitLab Runner updated successfully.');
+ });
+ });
});
describe('Version', () => {
- it('displays a version number if application has been upgraded', () => {
+ it('displays a version number if application has been updated', () => {
const version = '0.1.45';
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
- status: APPLICATION_STATUS.UPDATED,
+ status: APPLICATION_STATUS.INSTALLED,
+ updateSuccessful: true,
version,
});
- const upgradeDetails = vm.$el.querySelector('.js-cluster-application-upgrade-details');
- const versionEl = vm.$el.querySelector('.js-cluster-application-upgrade-version');
+ const updateDetails = vm.$el.querySelector('.js-cluster-application-update-details');
+ const versionEl = vm.$el.querySelector('.js-cluster-application-update-version');
- expect(upgradeDetails.innerHTML).toContain('Upgraded');
+ expect(updateDetails.innerHTML).toContain('Updated');
expect(versionEl).not.toBe(null);
expect(versionEl.innerHTML).toContain(version);
});
- it('contains a link to the chart repo if application has been upgraded', () => {
+ it('contains a link to the chart repo if application has been updated', () => {
const version = '0.1.45';
const chartRepo = 'https://gitlab.com/charts/gitlab-runner';
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
- status: APPLICATION_STATUS.UPDATED,
+ status: APPLICATION_STATUS.INSTALLED,
+ updateSuccessful: true,
chartRepo,
version,
});
- const versionEl = vm.$el.querySelector('.js-cluster-application-upgrade-version');
+ const versionEl = vm.$el.querySelector('.js-cluster-application-update-version');
expect(versionEl.href).toEqual(chartRepo);
expect(versionEl.target).toEqual('_blank');
});
- it('does not display a version number if application upgrade failed', () => {
+ it('does not display a version number if application update failed', () => {
const version = '0.1.45';
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
- status: APPLICATION_STATUS.UPDATE_ERRORED,
+ status: APPLICATION_STATUS.INSTALLED,
+ updateFailed: true,
version,
});
- const upgradeDetails = vm.$el.querySelector('.js-cluster-application-upgrade-details');
- const versionEl = vm.$el.querySelector('.js-cluster-application-upgrade-version');
+ const updateDetails = vm.$el.querySelector('.js-cluster-application-update-details');
+ const versionEl = vm.$el.querySelector('.js-cluster-application-update-version');
- expect(upgradeDetails.innerHTML).toContain('failed');
+ expect(updateDetails.innerHTML).toContain('failed');
expect(versionEl).toBe(null);
});
});
describe('Error block', () => {
- it('does not show error block when there is no error', () => {
- vm = mountComponent(ApplicationRow, {
- ...DEFAULT_APPLICATION_STATE,
- status: null,
- requestStatus: null,
+ describe('when nothing fails', () => {
+ it('does not show error block', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ });
+ const generalErrorMessage = vm.$el.querySelector(
+ '.js-cluster-application-general-error-message',
+ );
+
+ expect(generalErrorMessage).toBeNull();
});
- const generalErrorMessage = vm.$el.querySelector(
- '.js-cluster-application-general-error-message',
- );
-
- expect(generalErrorMessage).toBeNull();
});
- it('shows status reason when APPLICATION_STATUS.ERROR', () => {
+ describe('when install or uninstall fails', () => {
const statusReason = 'We broke it 0.0';
- vm = mountComponent(ApplicationRow, {
- ...DEFAULT_APPLICATION_STATE,
- status: APPLICATION_STATUS.ERROR,
- statusReason,
+ const requestReason = 'We broke the request 0.0';
+
+ beforeEach(() => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.ERROR,
+ statusReason,
+ requestReason,
+ installFailed: true,
+ });
});
- const generalErrorMessage = vm.$el.querySelector(
- '.js-cluster-application-general-error-message',
- );
- const statusErrorMessage = vm.$el.querySelector(
- '.js-cluster-application-status-error-message',
- );
- expect(generalErrorMessage.textContent.trim()).toEqual(
- `Something went wrong while installing ${DEFAULT_APPLICATION_STATE.title}`,
- );
+ it('shows status reason if it is available', () => {
+ const statusErrorMessage = vm.$el.querySelector(
+ '.js-cluster-application-status-error-message',
+ );
+
+ expect(statusErrorMessage.textContent.trim()).toEqual(statusReason);
+ });
- expect(statusErrorMessage.textContent.trim()).toEqual(statusReason);
+ it('shows request reason if it is available', () => {
+ const requestErrorMessage = vm.$el.querySelector(
+ '.js-cluster-application-request-error-message',
+ );
+
+ expect(requestErrorMessage.textContent.trim()).toEqual(requestReason);
+ });
});
- it('shows request reason when REQUEST_FAILURE', () => {
- const requestReason = 'We broke thre request 0.0';
- vm = mountComponent(ApplicationRow, {
- ...DEFAULT_APPLICATION_STATE,
- status: APPLICATION_STATUS.INSTALLABLE,
- requestStatus: REQUEST_FAILURE,
- requestReason,
+ describe('when install fails', () => {
+ beforeEach(() => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.ERROR,
+ installFailed: true,
+ });
});
- const generalErrorMessage = vm.$el.querySelector(
- '.js-cluster-application-general-error-message',
- );
- const requestErrorMessage = vm.$el.querySelector(
- '.js-cluster-application-request-error-message',
- );
- expect(generalErrorMessage.textContent.trim()).toEqual(
- `Something went wrong while installing ${DEFAULT_APPLICATION_STATE.title}`,
- );
+ it('shows a general message indicating the installation failed', () => {
+ const generalErrorMessage = vm.$el.querySelector(
+ '.js-cluster-application-general-error-message',
+ );
+
+ expect(generalErrorMessage.textContent.trim()).toEqual(
+ `Something went wrong while installing ${DEFAULT_APPLICATION_STATE.title}`,
+ );
+ });
+ });
+
+ describe('when uninstall fails', () => {
+ beforeEach(() => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.ERROR,
+ uninstallFailed: true,
+ });
+ });
+
+ it('shows a general message indicating the uninstalling failed', () => {
+ const generalErrorMessage = vm.$el.querySelector(
+ '.js-cluster-application-general-error-message',
+ );
- expect(requestErrorMessage.textContent.trim()).toEqual(requestReason);
+ expect(generalErrorMessage.textContent.trim()).toEqual(
+ `Something went wrong while uninstalling ${DEFAULT_APPLICATION_STATE.title}`,
+ );
+ });
});
});
});
diff --git a/spec/frontend/clusters/components/applications_spec.js b/spec/frontend/clusters/components/applications_spec.js
index 7c54a27d950..221ebb143be 100644
--- a/spec/frontend/clusters/components/applications_spec.js
+++ b/spec/frontend/clusters/components/applications_spec.js
@@ -1,9 +1,11 @@
import Vue from 'vue';
import applications from '~/clusters/components/applications.vue';
import { CLUSTER_TYPE } from '~/clusters/constants';
-import eventHub from '~/clusters/event_hub';
import mountComponent from 'helpers/vue_mount_component_helper';
import { APPLICATIONS_MOCK_STATE } from '../services/mock_data';
+import eventHub from '~/clusters/event_hub';
+import { shallowMount } from '@vue/test-utils';
+import KnativeDomainEditor from '~/clusters/components/knative_domain_editor.vue';
describe('Applications', () => {
let vm;
@@ -75,7 +77,7 @@ describe('Applications', () => {
});
it('renders a row for Prometheus', () => {
- expect(vm.$el.querySelector('.js-cluster-application-row-prometheus')).toBeNull();
+ expect(vm.$el.querySelector('.js-cluster-application-row-prometheus')).not.toBeNull();
});
it('renders a row for GitLab Runner', () => {
@@ -277,73 +279,48 @@ describe('Applications', () => {
});
describe('Knative application', () => {
- describe('when installed', () => {
- describe('with ip address', () => {
- const props = {
- applications: {
- ...APPLICATIONS_MOCK_STATE,
- knative: {
- title: 'Knative',
- hostname: 'example.com',
- status: 'installed',
- externalIp: '1.1.1.1',
- },
- },
- };
- it('renders ip address with a clipboard button', () => {
- vm = mountComponent(Applications, props);
-
- expect(vm.$el.querySelector('.js-knative-endpoint').value).toEqual('1.1.1.1');
+ const propsData = {
+ applications: {
+ ...APPLICATIONS_MOCK_STATE,
+ knative: {
+ title: 'Knative',
+ hostname: 'example.com',
+ status: 'installed',
+ externalIp: '1.1.1.1',
+ installed: true,
+ },
+ },
+ };
+ const newHostname = 'newhostname.com';
+ let wrapper;
+ let knativeDomainEditor;
- expect(
- vm.$el
- .querySelector('.js-knative-endpoint-clipboard-btn')
- .getAttribute('data-clipboard-text'),
- ).toEqual('1.1.1.1');
- });
-
- it('renders domain & allows editing', () => {
- expect(vm.$el.querySelector('.js-knative-domainname').value).toEqual('example.com');
- expect(vm.$el.querySelector('.js-knative-domainname').getAttribute('readonly')).toBe(
- null,
- );
- });
-
- it('renders an update/save Knative domain button', () => {
- expect(vm.$el.querySelector('.js-knative-save-domain-button')).not.toBe(null);
- });
+ beforeEach(() => {
+ wrapper = shallowMount(Applications, { propsData });
+ jest.spyOn(eventHub, '$emit');
- it('emits event when clicking Save changes button', () => {
- jest.spyOn(eventHub, '$emit');
- vm = mountComponent(Applications, props);
+ knativeDomainEditor = wrapper.find(KnativeDomainEditor);
+ });
- const saveButton = vm.$el.querySelector('.js-knative-save-domain-button');
+ afterEach(() => {
+ wrapper.destroy();
+ });
- saveButton.click();
+ it('emits saveKnativeDomain event when knative domain editor emits save event', () => {
+ knativeDomainEditor.vm.$emit('save', newHostname);
- expect(eventHub.$emit).toHaveBeenCalledWith('saveKnativeDomain', {
- id: 'knative',
- params: { hostname: 'example.com' },
- });
- });
+ expect(eventHub.$emit).toHaveBeenCalledWith('saveKnativeDomain', {
+ id: 'knative',
+ params: { hostname: newHostname },
});
+ });
- describe('without ip address', () => {
- it('renders an input text with a loading icon and an alert text', () => {
- vm = mountComponent(Applications, {
- applications: {
- ...APPLICATIONS_MOCK_STATE,
- knative: {
- title: 'Knative',
- hostname: 'example.com',
- status: 'installed',
- },
- },
- });
+ it('emits setKnativeHostname event when knative domain editor emits change event', () => {
+ wrapper.find(KnativeDomainEditor).vm.$emit('set', newHostname);
- expect(vm.$el.querySelector('.js-knative-ip-loading-icon')).not.toBe(null);
- expect(vm.$el.querySelector('.js-no-knative-endpoint-message')).not.toBe(null);
- });
+ expect(eventHub.$emit).toHaveBeenCalledWith('setKnativeHostname', {
+ id: 'knative',
+ hostname: newHostname,
});
});
});
diff --git a/spec/frontend/clusters/components/knative_domain_editor_spec.js b/spec/frontend/clusters/components/knative_domain_editor_spec.js
new file mode 100644
index 00000000000..242b5701f8b
--- /dev/null
+++ b/spec/frontend/clusters/components/knative_domain_editor_spec.js
@@ -0,0 +1,141 @@
+import { shallowMount } from '@vue/test-utils';
+import KnativeDomainEditor from '~/clusters/components/knative_domain_editor.vue';
+import LoadingButton from '~/vue_shared/components/loading_button.vue';
+import { APPLICATION_STATUS } from '~/clusters/constants';
+
+const { UPDATING } = APPLICATION_STATUS;
+
+describe('KnativeDomainEditor', () => {
+ let wrapper;
+ let knative;
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(KnativeDomainEditor, {
+ propsData: { ...props },
+ });
+ };
+
+ beforeEach(() => {
+ knative = {
+ title: 'Knative',
+ hostname: 'example.com',
+ installed: true,
+ };
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('knative has an assigned IP address', () => {
+ beforeEach(() => {
+ knative.externalIp = '1.1.1.1';
+ createComponent({ knative });
+ });
+
+ it('renders ip address with a clipboard button', () => {
+ expect(wrapper.find('.js-knative-endpoint').exists()).toBe(true);
+ expect(wrapper.find('.js-knative-endpoint').element.value).toEqual(knative.externalIp);
+ });
+
+ it('displays ip address clipboard button', () => {
+ expect(wrapper.find('.js-knative-endpoint-clipboard-btn').attributes('text')).toEqual(
+ knative.externalIp,
+ );
+ });
+
+ it('renders domain & allows editing', () => {
+ const domainNameInput = wrapper.find('.js-knative-domainname');
+
+ expect(domainNameInput.element.value).toEqual(knative.hostname);
+ expect(domainNameInput.attributes('readonly')).toBeFalsy();
+ });
+
+ it('renders an update/save Knative domain button', () => {
+ expect(wrapper.find('.js-knative-save-domain-button').exists()).toBe(true);
+ });
+ });
+
+ describe('knative without ip address', () => {
+ beforeEach(() => {
+ knative.externalIp = null;
+ createComponent({ knative });
+ });
+
+ it('renders an input text with a loading icon', () => {
+ expect(wrapper.find('.js-knative-ip-loading-icon').exists()).toBe(true);
+ });
+
+ it('renders message indicating there is not IP address assigned', () => {
+ expect(wrapper.find('.js-no-knative-endpoint-message').exists()).toBe(true);
+ });
+ });
+
+ describe('clicking save changes button', () => {
+ beforeEach(() => {
+ createComponent({ knative });
+ });
+
+ it('triggers save event and pass current knative hostname', () => {
+ wrapper.find(LoadingButton).vm.$emit('click');
+ expect(wrapper.emitted('save')[0]).toEqual([knative.hostname]);
+ });
+ });
+
+ describe('when knative domain name was saved successfully', () => {
+ beforeEach(() => {
+ createComponent({ knative });
+ });
+
+ it('displays toast indicating a successful update', () => {
+ wrapper.vm.$toast = { show: jest.fn() };
+ wrapper.setProps({ knative: Object.assign({ updateSuccessful: true }, knative) });
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(
+ 'Knative domain name was updated successfully.',
+ );
+ });
+ });
+ });
+
+ describe('when knative domain name input changes', () => {
+ it('emits "set" event with updated domain name', () => {
+ const newHostname = 'newhostname.com';
+
+ wrapper.setData({ knativeHostname: newHostname });
+
+ expect(wrapper.emitted('set')[0]).toEqual([newHostname]);
+ });
+ });
+
+ describe('when updating knative domain name failed', () => {
+ beforeEach(() => {
+ createComponent({ knative });
+ });
+
+ it('displays an error banner indicating the operation failure', () => {
+ wrapper.setProps({ knative: { updateFailed: true, ...knative } });
+
+ expect(wrapper.find('.js-cluster-knative-domain-name-failure-message').exists()).toBe(true);
+ });
+ });
+
+ describe(`when knative status is ${UPDATING}`, () => {
+ beforeEach(() => {
+ createComponent({ knative: { status: UPDATING, ...knative } });
+ });
+
+ it('renders loading spinner in save button', () => {
+ expect(wrapper.find(LoadingButton).props('loading')).toBe(true);
+ });
+
+ it('renders disabled save button', () => {
+ expect(wrapper.find(LoadingButton).props('disabled')).toBe(true);
+ });
+
+ it('renders save button with "Saving" label', () => {
+ expect(wrapper.find(LoadingButton).props('label')).toBe('Saving');
+ });
+ });
+});
diff --git a/spec/frontend/clusters/components/uninstall_application_button_spec.js b/spec/frontend/clusters/components/uninstall_application_button_spec.js
new file mode 100644
index 00000000000..9f9397d4d41
--- /dev/null
+++ b/spec/frontend/clusters/components/uninstall_application_button_spec.js
@@ -0,0 +1,32 @@
+import { shallowMount } from '@vue/test-utils';
+import UninstallApplicationButton from '~/clusters/components/uninstall_application_button.vue';
+import LoadingButton from '~/vue_shared/components/loading_button.vue';
+import { APPLICATION_STATUS } from '~/clusters/constants';
+
+const { INSTALLED, UPDATING, UNINSTALLING } = APPLICATION_STATUS;
+
+describe('UninstallApplicationButton', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(UninstallApplicationButton, {
+ propsData: { ...props },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe.each`
+ status | loading | disabled | label
+ ${INSTALLED} | ${false} | ${false} | ${'Uninstall'}
+ ${UPDATING} | ${false} | ${true} | ${'Uninstall'}
+ ${UNINSTALLING} | ${true} | ${true} | ${'Uninstalling'}
+ `('when app status is $status', ({ loading, disabled, status, label }) => {
+ it(`renders a loading=${loading}, disabled=${disabled} button with label="${label}"`, () => {
+ createComponent({ status });
+ expect(wrapper.find(LoadingButton).props()).toMatchObject({ loading, disabled, label });
+ });
+ });
+});
diff --git a/spec/frontend/clusters/components/uninstall_application_confirmation_modal_spec.js b/spec/frontend/clusters/components/uninstall_application_confirmation_modal_spec.js
new file mode 100644
index 00000000000..04808864fc0
--- /dev/null
+++ b/spec/frontend/clusters/components/uninstall_application_confirmation_modal_spec.js
@@ -0,0 +1,56 @@
+import { shallowMount } from '@vue/test-utils';
+import UninstallApplicationConfirmationModal from '~/clusters/components/uninstall_application_confirmation_modal.vue';
+import { GlModal } from '@gitlab/ui';
+import { INGRESS } from '~/clusters/constants';
+
+describe('UninstallApplicationConfirmationModal', () => {
+ let wrapper;
+ const appTitle = 'Ingress';
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(UninstallApplicationConfirmationModal, {
+ propsData: { ...props },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ beforeEach(() => {
+ createComponent({ application: INGRESS, applicationTitle: appTitle });
+ });
+
+ it(`renders a modal with a title "Uninstall ${appTitle}"`, () => {
+ expect(wrapper.find(GlModal).attributes('title')).toEqual(`Uninstall ${appTitle}`);
+ });
+
+ it(`renders a modal with an ok button labeled "Uninstall ${appTitle}"`, () => {
+ expect(wrapper.find(GlModal).attributes('ok-title')).toEqual(`Uninstall ${appTitle}`);
+ });
+
+ describe('when ok button is clicked', () => {
+ beforeEach(() => {
+ jest.spyOn(wrapper.vm, 'trackUninstallButtonClick');
+ wrapper.find(GlModal).vm.$emit('ok');
+ });
+
+ it('emits confirm event', () => {
+ expect(wrapper.emitted('confirm')).toBeTruthy();
+ });
+
+ it('calls track uninstall button click mixin', () => {
+ expect(wrapper.vm.trackUninstallButtonClick).toHaveBeenCalledWith(INGRESS);
+ });
+ });
+
+ it('displays a warning text indicating the app will be uninstalled', () => {
+ expect(wrapper.text()).toContain(`You are about to uninstall ${appTitle} from your cluster.`);
+ });
+
+ it('displays a custom warning text depending on the application', () => {
+ expect(wrapper.text()).toContain(
+ `The associated load balancer and IP will be deleted and cannot be restored.`,
+ );
+ });
+});
diff --git a/spec/frontend/clusters/services/application_state_machine_spec.js b/spec/frontend/clusters/services/application_state_machine_spec.js
new file mode 100644
index 00000000000..c146ef79be7
--- /dev/null
+++ b/spec/frontend/clusters/services/application_state_machine_spec.js
@@ -0,0 +1,162 @@
+import transitionApplicationState from '~/clusters/services/application_state_machine';
+import {
+ APPLICATION_STATUS,
+ UNINSTALL_EVENT,
+ UPDATE_EVENT,
+ INSTALL_EVENT,
+} from '~/clusters/constants';
+
+const {
+ NO_STATUS,
+ SCHEDULED,
+ NOT_INSTALLABLE,
+ INSTALLABLE,
+ INSTALLING,
+ INSTALLED,
+ ERROR,
+ UPDATING,
+ UPDATED,
+ UPDATE_ERRORED,
+ UNINSTALLING,
+ UNINSTALL_ERRORED,
+} = APPLICATION_STATUS;
+
+const NO_EFFECTS = 'no effects';
+
+describe('applicationStateMachine', () => {
+ const noEffectsToEmptyObject = effects => (typeof effects === 'string' ? {} : effects);
+
+ describe(`current state is ${NO_STATUS}`, () => {
+ it.each`
+ expectedState | event | effects
+ ${INSTALLING} | ${SCHEDULED} | ${NO_EFFECTS}
+ ${NOT_INSTALLABLE} | ${NOT_INSTALLABLE} | ${NO_EFFECTS}
+ ${INSTALLABLE} | ${INSTALLABLE} | ${NO_EFFECTS}
+ ${INSTALLING} | ${INSTALLING} | ${NO_EFFECTS}
+ ${INSTALLED} | ${INSTALLED} | ${NO_EFFECTS}
+ ${INSTALLABLE} | ${ERROR} | ${{ installFailed: true }}
+ ${UPDATING} | ${UPDATING} | ${NO_EFFECTS}
+ ${INSTALLED} | ${UPDATED} | ${NO_EFFECTS}
+ ${INSTALLED} | ${UPDATE_ERRORED} | ${{ updateFailed: true }}
+ ${UNINSTALLING} | ${UNINSTALLING} | ${NO_EFFECTS}
+ ${INSTALLED} | ${UNINSTALL_ERRORED} | ${{ uninstallFailed: true }}
+ `(`transitions to $expectedState on $event event and applies $effects`, data => {
+ const { expectedState, event, effects } = data;
+ const currentAppState = {
+ status: NO_STATUS,
+ };
+
+ expect(transitionApplicationState(currentAppState, event)).toEqual({
+ status: expectedState,
+ ...noEffectsToEmptyObject(effects),
+ });
+ });
+ });
+
+ describe(`current state is ${NOT_INSTALLABLE}`, () => {
+ it.each`
+ expectedState | event | effects
+ ${INSTALLABLE} | ${INSTALLABLE} | ${NO_EFFECTS}
+ `(`transitions to $expectedState on $event event and applies $effects`, data => {
+ const { expectedState, event, effects } = data;
+ const currentAppState = {
+ status: NOT_INSTALLABLE,
+ };
+
+ expect(transitionApplicationState(currentAppState, event)).toEqual({
+ status: expectedState,
+ ...noEffectsToEmptyObject(effects),
+ });
+ });
+ });
+
+ describe(`current state is ${INSTALLABLE}`, () => {
+ it.each`
+ expectedState | event | effects
+ ${INSTALLING} | ${INSTALL_EVENT} | ${{ installFailed: false }}
+ ${INSTALLED} | ${INSTALLED} | ${NO_EFFECTS}
+ `(`transitions to $expectedState on $event event and applies $effects`, data => {
+ const { expectedState, event, effects } = data;
+ const currentAppState = {
+ status: INSTALLABLE,
+ };
+
+ expect(transitionApplicationState(currentAppState, event)).toEqual({
+ status: expectedState,
+ ...noEffectsToEmptyObject(effects),
+ });
+ });
+ });
+
+ describe(`current state is ${INSTALLING}`, () => {
+ it.each`
+ expectedState | event | effects
+ ${INSTALLED} | ${INSTALLED} | ${NO_EFFECTS}
+ ${INSTALLABLE} | ${ERROR} | ${{ installFailed: true }}
+ `(`transitions to $expectedState on $event event and applies $effects`, data => {
+ const { expectedState, event, effects } = data;
+ const currentAppState = {
+ status: INSTALLING,
+ };
+
+ expect(transitionApplicationState(currentAppState, event)).toEqual({
+ status: expectedState,
+ ...noEffectsToEmptyObject(effects),
+ });
+ });
+ });
+
+ describe(`current state is ${INSTALLED}`, () => {
+ it.each`
+ expectedState | event | effects
+ ${UPDATING} | ${UPDATE_EVENT} | ${{ updateFailed: false, updateSuccessful: false }}
+ ${UNINSTALLING} | ${UNINSTALL_EVENT} | ${{ uninstallFailed: false, uninstallSuccessful: false }}
+ `(`transitions to $expectedState on $event event and applies $effects`, data => {
+ const { expectedState, event, effects } = data;
+ const currentAppState = {
+ status: INSTALLED,
+ };
+
+ expect(transitionApplicationState(currentAppState, event)).toEqual({
+ status: expectedState,
+ ...effects,
+ });
+ });
+ });
+
+ describe(`current state is ${UPDATING}`, () => {
+ it.each`
+ expectedState | event | effects
+ ${INSTALLED} | ${UPDATED} | ${{ updateSuccessful: true }}
+ ${INSTALLED} | ${UPDATE_ERRORED} | ${{ updateFailed: true }}
+ `(`transitions to $expectedState on $event event and applies $effects`, data => {
+ const { expectedState, event, effects } = data;
+ const currentAppState = {
+ status: UPDATING,
+ };
+
+ expect(transitionApplicationState(currentAppState, event)).toEqual({
+ status: expectedState,
+ ...effects,
+ });
+ });
+ });
+
+ describe(`current state is ${UNINSTALLING}`, () => {
+ it.each`
+ expectedState | event | effects
+ ${INSTALLABLE} | ${INSTALLABLE} | ${{ uninstallSuccessful: true }}
+ ${INSTALLED} | ${UNINSTALL_ERRORED} | ${{ uninstallFailed: true }}
+ `(`transitions to $expectedState on $event event and applies $effects`, data => {
+ const { expectedState, event, effects } = data;
+ const currentAppState = {
+ status: UNINSTALLING,
+ };
+
+ expect(transitionApplicationState(currentAppState, event)).toEqual({
+ status: expectedState,
+ ...effects,
+ });
+ });
+ });
+});
diff --git a/spec/frontend/clusters/services/mock_data.js b/spec/frontend/clusters/services/mock_data.js
index b4d1bb710e0..41ad398e924 100644
--- a/spec/frontend/clusters/services/mock_data.js
+++ b/spec/frontend/clusters/services/mock_data.js
@@ -11,6 +11,7 @@ const CLUSTERS_MOCK_DATA = {
name: 'helm',
status: APPLICATION_STATUS.INSTALLABLE,
status_reason: null,
+ can_uninstall: false,
},
{
name: 'ingress',
@@ -18,32 +19,38 @@ const CLUSTERS_MOCK_DATA = {
status_reason: 'Cannot connect',
external_ip: null,
external_hostname: null,
+ can_uninstall: false,
},
{
name: 'runner',
status: APPLICATION_STATUS.INSTALLING,
status_reason: null,
+ can_uninstall: false,
},
{
name: 'prometheus',
status: APPLICATION_STATUS.ERROR,
status_reason: 'Cannot connect',
+ can_uninstall: false,
},
{
name: 'jupyter',
status: APPLICATION_STATUS.INSTALLING,
status_reason: 'Cannot connect',
+ can_uninstall: false,
},
{
name: 'knative',
status: APPLICATION_STATUS.INSTALLING,
status_reason: 'Cannot connect',
+ can_uninstall: false,
},
{
name: 'cert_manager',
status: APPLICATION_STATUS.ERROR,
status_reason: 'Cannot connect',
email: 'test@example.com',
+ can_uninstall: false,
},
],
},
@@ -113,7 +120,6 @@ const DEFAULT_APPLICATION_STATE = {
description: 'Some description about this interesting application!',
status: null,
statusReason: null,
- requestStatus: null,
requestReason: null,
};
diff --git a/spec/frontend/clusters/stores/clusters_store_spec.js b/spec/frontend/clusters/stores/clusters_store_spec.js
index 161722ec571..f2cc413512d 100644
--- a/spec/frontend/clusters/stores/clusters_store_spec.js
+++ b/spec/frontend/clusters/stores/clusters_store_spec.js
@@ -1,5 +1,5 @@
import ClustersStore from '~/clusters/stores/clusters_store';
-import { APPLICATION_STATUS } from '~/clusters/constants';
+import { APPLICATION_INSTALLED_STATUSES, APPLICATION_STATUS, RUNNER } from '~/clusters/constants';
import { CLUSTERS_MOCK_DATA } from '../services/mock_data';
describe('Clusters Store', () => {
@@ -32,15 +32,6 @@ describe('Clusters Store', () => {
});
describe('updateAppProperty', () => {
- it('should store new request status', () => {
- expect(store.state.applications.helm.requestStatus).toEqual(null);
-
- const newStatus = APPLICATION_STATUS.INSTALLING;
- store.updateAppProperty('helm', 'requestStatus', newStatus);
-
- expect(store.state.applications.helm.requestStatus).toEqual(newStatus);
- });
-
it('should store new request reason', () => {
expect(store.state.applications.helm.requestReason).toEqual(null);
@@ -68,66 +59,112 @@ describe('Clusters Store', () => {
title: 'Helm Tiller',
status: mockResponseData.applications[0].status,
statusReason: mockResponseData.applications[0].status_reason,
- requestStatus: null,
requestReason: null,
+ installed: false,
+ installFailed: false,
+ uninstallable: false,
+ uninstallSuccessful: false,
+ uninstallFailed: false,
},
ingress: {
title: 'Ingress',
- status: mockResponseData.applications[1].status,
+ status: APPLICATION_STATUS.INSTALLABLE,
statusReason: mockResponseData.applications[1].status_reason,
- requestStatus: null,
requestReason: null,
externalIp: null,
externalHostname: null,
+ installed: false,
+ installFailed: true,
+ uninstallable: false,
+ uninstallSuccessful: false,
+ uninstallFailed: false,
},
runner: {
title: 'GitLab Runner',
status: mockResponseData.applications[2].status,
statusReason: mockResponseData.applications[2].status_reason,
- requestStatus: null,
requestReason: null,
version: mockResponseData.applications[2].version,
- upgradeAvailable: mockResponseData.applications[2].update_available,
+ updateAvailable: mockResponseData.applications[2].update_available,
chartRepo: 'https://gitlab.com/charts/gitlab-runner',
+ installed: false,
+ installFailed: false,
+ updateFailed: false,
+ updateSuccessful: false,
+ uninstallable: false,
+ uninstallSuccessful: false,
+ uninstallFailed: false,
},
prometheus: {
title: 'Prometheus',
- status: mockResponseData.applications[3].status,
+ status: APPLICATION_STATUS.INSTALLABLE,
statusReason: mockResponseData.applications[3].status_reason,
- requestStatus: null,
requestReason: null,
+ installed: false,
+ installFailed: true,
+ uninstallable: false,
+ uninstallSuccessful: false,
+ uninstallFailed: false,
},
jupyter: {
title: 'JupyterHub',
status: mockResponseData.applications[4].status,
statusReason: mockResponseData.applications[4].status_reason,
- requestStatus: null,
requestReason: null,
hostname: '',
+ installed: false,
+ installFailed: false,
+ uninstallable: false,
+ uninstallSuccessful: false,
+ uninstallFailed: false,
},
knative: {
title: 'Knative',
status: mockResponseData.applications[5].status,
statusReason: mockResponseData.applications[5].status_reason,
- requestStatus: null,
requestReason: null,
hostname: null,
isEditingHostName: false,
externalIp: null,
externalHostname: null,
+ installed: false,
+ installFailed: false,
+ uninstallable: false,
+ uninstallSuccessful: false,
+ uninstallFailed: false,
+ updateSuccessful: false,
+ updateFailed: false,
},
cert_manager: {
title: 'Cert-Manager',
- status: mockResponseData.applications[6].status,
+ status: APPLICATION_STATUS.INSTALLABLE,
+ installFailed: true,
statusReason: mockResponseData.applications[6].status_reason,
- requestStatus: null,
requestReason: null,
email: mockResponseData.applications[6].email,
+ installed: false,
+ uninstallable: false,
+ uninstallSuccessful: false,
+ uninstallFailed: false,
},
},
});
});
+ describe.each(APPLICATION_INSTALLED_STATUSES)('given the current app status is %s', status => {
+ it('marks application as installed', () => {
+ const mockResponseData =
+ CLUSTERS_MOCK_DATA.GET['/gitlab-org/gitlab-shell/clusters/2/status.json'].data;
+ const runnerAppIndex = 2;
+
+ mockResponseData.applications[runnerAppIndex].status = status;
+
+ store.updateStateFromServer(mockResponseData);
+
+ expect(store.state.applications[RUNNER].installed).toBe(true);
+ });
+ });
+
it('sets default hostname for jupyter when ingress has a ip address', () => {
const mockResponseData =
CLUSTERS_MOCK_DATA.GET['/gitlab-org/gitlab-shell/clusters/2/status.json'].data;
diff --git a/spec/frontend/environment.js b/spec/frontend/environment.js
index 34df8019a2e..a8c8688441d 100644
--- a/spec/frontend/environment.js
+++ b/spec/frontend/environment.js
@@ -24,8 +24,9 @@ class CustomEnvironment extends JSDOMEnvironment {
});
const { testEnvironmentOptions } = config;
+ const { IS_EE } = testEnvironmentOptions;
this.global.gon = {
- ee: testEnvironmentOptions.IS_EE,
+ ee: IS_EE,
};
this.rejectedPromises = [];
@@ -33,6 +34,20 @@ class CustomEnvironment extends JSDOMEnvironment {
this.global.promiseRejectionHandler = error => {
this.rejectedPromises.push(error);
};
+
+ this.global.fixturesBasePath = `${process.cwd()}/${
+ IS_EE ? 'ee/' : ''
+ }spec/javascripts/fixtures`;
+
+ // Not yet supported by JSDOM: https://github.com/jsdom/jsdom/issues/317
+ this.global.document.createRange = () => ({
+ setStart: () => {},
+ setEnd: () => {},
+ commonAncestorContainer: {
+ nodeName: 'BODY',
+ ownerDocument: this.global.document,
+ },
+ });
}
async teardown() {
diff --git a/spec/frontend/gfm_auto_complete_spec.js b/spec/frontend/gfm_auto_complete_spec.js
index ed12af925f1..8af49fd47a2 100644
--- a/spec/frontend/gfm_auto_complete_spec.js
+++ b/spec/frontend/gfm_auto_complete_spec.js
@@ -1,17 +1,14 @@
/* eslint no-param-reassign: "off" */
import $ from 'jquery';
-import GfmAutoComplete from '~/gfm_auto_complete';
+import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
import 'jquery.caret';
import 'at.js';
import { TEST_HOST } from 'helpers/test_constants';
-import { setTestTimeout } from 'helpers/timeout';
import { getJSONFixture } from 'helpers/fixtures';
-setTestTimeout(500);
-
const labelsFixture = getJSONFixture('autocomplete_sources/labels.json');
describe('GfmAutoComplete', () => {
@@ -94,7 +91,7 @@ describe('GfmAutoComplete', () => {
});
it('should quote if value contains any non-alphanumeric characters', () => {
- expect(beforeInsert(atwhoInstance, '~label-20')).toBe('~"label\\-20"');
+ expect(beforeInsert(atwhoInstance, '~label-20')).toBe('~"label-20"');
expect(beforeInsert(atwhoInstance, '~label 20')).toBe('~"label 20"');
});
@@ -102,12 +99,21 @@ describe('GfmAutoComplete', () => {
expect(beforeInsert(atwhoInstance, '~1234')).toBe('~"1234"');
});
- it('should escape Markdown emphasis characters, except in the first character', () => {
- expect(beforeInsert(atwhoInstance, '@_group')).toEqual('@\\_group');
- expect(beforeInsert(atwhoInstance, '~_bug')).toEqual('~\\_bug');
+ it('escapes Markdown strikethroughs when needed', () => {
+ expect(beforeInsert(atwhoInstance, '~a~bug')).toEqual('~"a~bug"');
+ expect(beforeInsert(atwhoInstance, '~a~~bug~~')).toEqual('~"a\\~~bug\\~~"');
+ });
+
+ it('escapes Markdown emphasis when needed', () => {
+ expect(beforeInsert(atwhoInstance, '~a_bug_')).toEqual('~a_bug\\_');
+ expect(beforeInsert(atwhoInstance, '~a _bug_')).toEqual('~"a \\_bug\\_"');
+ expect(beforeInsert(atwhoInstance, '~a*bug*')).toEqual('~"a\\*bug\\*"');
+ expect(beforeInsert(atwhoInstance, '~a *bug*')).toEqual('~"a \\*bug\\*"');
+ });
+
+ it('escapes Markdown code spans when needed', () => {
+ expect(beforeInsert(atwhoInstance, '~a`bug`')).toEqual('~"a\\`bug\\`"');
expect(beforeInsert(atwhoInstance, '~a `bug`')).toEqual('~"a \\`bug\\`"');
- expect(beforeInsert(atwhoInstance, '~a ~bug')).toEqual('~"a \\~bug"');
- expect(beforeInsert(atwhoInstance, '~a **bug')).toEqual('~"a \\*\\*bug"');
});
});
@@ -200,6 +206,38 @@ describe('GfmAutoComplete', () => {
});
});
+ describe('DefaultOptions.highlighter', () => {
+ beforeEach(() => {
+ atwhoInstance = { setting: {} };
+ });
+
+ it('should return li if no query is given', () => {
+ const liTag = '<li></li>';
+
+ const highlightedTag = gfmAutoCompleteCallbacks.highlighter.call(atwhoInstance, liTag);
+
+ expect(highlightedTag).toEqual(liTag);
+ });
+
+ it('should highlight search query in li element', () => {
+ const liTag = '<li><img src="" />string</li>';
+ const query = 's';
+
+ const highlightedTag = gfmAutoCompleteCallbacks.highlighter.call(atwhoInstance, liTag, query);
+
+ expect(highlightedTag).toEqual('<li><img src="" /> <strong>s</strong>tring </li>');
+ });
+
+ it('should highlight search query with special char in li element', () => {
+ const liTag = '<li><img src="" />te.st</li>';
+ const query = '.';
+
+ const highlightedTag = gfmAutoCompleteCallbacks.highlighter.call(atwhoInstance, liTag, query);
+
+ expect(highlightedTag).toEqual('<li><img src="" /> te<strong>.</strong>st </li>');
+ });
+ });
+
describe('isLoading', () => {
it('should be true with loading data object item', () => {
expect(GfmAutoComplete.isLoading({ name: 'loading' })).toBe(true);
diff --git a/spec/frontend/helpers/fixtures.js b/spec/frontend/helpers/fixtures.js
index f0351aa31c6..b77bcd6266e 100644
--- a/spec/frontend/helpers/fixtures.js
+++ b/spec/frontend/helpers/fixtures.js
@@ -3,10 +3,8 @@ import path from 'path';
import { ErrorWithStack } from 'jest-util';
-const fixturesBasePath = path.join(process.cwd(), 'spec', 'javascripts', 'fixtures');
-
export function getFixture(relativePath) {
- const absolutePath = path.join(fixturesBasePath, relativePath);
+ const absolutePath = path.join(global.fixturesBasePath, relativePath);
if (!fs.existsSync(absolutePath)) {
throw new ErrorWithStack(
`Fixture file ${relativePath} does not exist.
diff --git a/spec/frontend/helpers/jest_helpers.js b/spec/frontend/helpers/jest_helpers.js
new file mode 100644
index 00000000000..4a150be9935
--- /dev/null
+++ b/spec/frontend/helpers/jest_helpers.js
@@ -0,0 +1,24 @@
+/* eslint-disable import/prefer-default-export */
+
+/*
+@module
+
+This method provides convenience functions to help migrating from Karma/Jasmine to Jest.
+
+Try not to use these in new tests - this module is provided primarily for convenience of migrating tests.
+ */
+
+/**
+ * Creates a plain JS object pre-populated with Jest spy functions. Useful for making simple mocks classes.
+ *
+ * @see https://jasmine.github.io/2.0/introduction.html#section-Spies:_%3Ccode%3EcreateSpyObj%3C/code%3E
+ * @param {string} baseName Human-readable name of the object. This is used for reporting purposes.
+ * @param methods {string[]} List of method names that will be added to the spy object.
+ */
+export function createSpyObj(baseName, methods) {
+ const obj = {};
+ methods.forEach(method => {
+ obj[method] = jest.fn().mockName(`${baseName}#${method}`);
+ });
+ return obj;
+}
diff --git a/spec/frontend/helpers/jquery.js b/spec/frontend/helpers/jquery.js
new file mode 100644
index 00000000000..6421a592c0c
--- /dev/null
+++ b/spec/frontend/helpers/jquery.js
@@ -0,0 +1,6 @@
+import $ from 'jquery';
+
+global.$ = $;
+global.jQuery = $;
+
+export default $;
diff --git a/spec/frontend/helpers/local_storage_helper.js b/spec/frontend/helpers/local_storage_helper.js
new file mode 100644
index 00000000000..48e66b11767
--- /dev/null
+++ b/spec/frontend/helpers/local_storage_helper.js
@@ -0,0 +1,41 @@
+/**
+ * Manage the instance of a custom `window.localStorage`
+ *
+ * This only encapsulates the setup / teardown logic so that it can easily be
+ * reused with different implementations (i.e. a spy or a [fake][1])
+ *
+ * [1]: https://stackoverflow.com/a/41434763/1708147
+ *
+ * @param {() => any} fn Function that returns the object to use for localStorage
+ */
+const useLocalStorage = fn => {
+ const origLocalStorage = window.localStorage;
+ let currentLocalStorage;
+
+ Object.defineProperty(window, 'localStorage', {
+ get: () => currentLocalStorage,
+ });
+
+ beforeEach(() => {
+ currentLocalStorage = fn();
+ });
+
+ afterEach(() => {
+ currentLocalStorage = origLocalStorage;
+ });
+};
+
+/**
+ * Create an object with the localStorage interface but `jest.fn()` implementations.
+ */
+export const createLocalStorageSpy = () => ({
+ clear: jest.fn(),
+ getItem: jest.fn(),
+ setItem: jest.fn(),
+ removeItem: jest.fn(),
+});
+
+/**
+ * Before each test, overwrite `window.localStorage` with a spy implementation.
+ */
+export const useLocalStorageSpy = () => useLocalStorage(createLocalStorageSpy);
diff --git a/spec/frontend/helpers/vue_component_helper.js b/spec/frontend/helpers/text_helper.js
index e0fe18e5560..e0fe18e5560 100644
--- a/spec/frontend/helpers/vue_component_helper.js
+++ b/spec/frontend/helpers/text_helper.js
diff --git a/spec/frontend/helpers/timeout.js b/spec/frontend/helpers/timeout.js
index 318593a48a4..702ef0be5aa 100644
--- a/spec/frontend/helpers/timeout.js
+++ b/spec/frontend/helpers/timeout.js
@@ -1,24 +1,59 @@
-let testTimeoutInMs;
+const NS_PER_SEC = 1e9;
+const NS_PER_MS = 1e6;
+const IS_DEBUGGING = process.execArgv.join(' ').includes('--inspect-brk');
-export const setTestTimeout = newTimeoutInMs => {
- testTimeoutInMs = newTimeoutInMs;
- jest.setTimeout(newTimeoutInMs);
+let testTimeoutNS;
+
+export const setTestTimeout = newTimeoutMS => {
+ const newTimeoutNS = newTimeoutMS * NS_PER_MS;
+ // never accept a smaller timeout than the default
+ if (newTimeoutNS < testTimeoutNS) {
+ return;
+ }
+
+ testTimeoutNS = newTimeoutNS;
+ jest.setTimeout(newTimeoutMS);
+};
+
+// Allows slow tests to set their own timeout.
+// Useful for tests with jQuery, which is very slow in big DOMs.
+let temporaryTimeoutNS = null;
+export const setTestTimeoutOnce = newTimeoutMS => {
+ const newTimeoutNS = newTimeoutMS * NS_PER_MS;
+ // never accept a smaller timeout than the default
+ if (newTimeoutNS < testTimeoutNS) {
+ return;
+ }
+
+ temporaryTimeoutNS = newTimeoutNS;
};
-export const initializeTestTimeout = defaultTimeoutInMs => {
- setTestTimeout(defaultTimeoutInMs);
+export const initializeTestTimeout = defaultTimeoutMS => {
+ setTestTimeout(defaultTimeoutMS);
let testStartTime;
// https://github.com/facebook/jest/issues/6947
beforeEach(() => {
- testStartTime = Date.now();
+ testStartTime = process.hrtime();
});
afterEach(() => {
- const elapsedTimeInMs = Date.now() - testStartTime;
- if (elapsedTimeInMs > testTimeoutInMs) {
- throw new Error(`Test took too long (${elapsedTimeInMs}ms > ${testTimeoutInMs}ms)!`);
+ let timeoutNS = testTimeoutNS;
+ if (Number.isFinite(temporaryTimeoutNS)) {
+ timeoutNS = temporaryTimeoutNS;
+ temporaryTimeoutNS = null;
+ }
+
+ const [seconds, remainingNs] = process.hrtime(testStartTime);
+ const elapsedNS = seconds * NS_PER_SEC + remainingNs;
+
+ // Disable the timeout error when debugging. It is meaningless because
+ // debugging always takes longer than the test timeout.
+ if (elapsedNS > timeoutNS && !IS_DEBUGGING) {
+ throw new Error(
+ `Test took too long (${elapsedNS / NS_PER_MS}ms > ${timeoutNS / NS_PER_MS}ms)!`,
+ );
}
});
};
diff --git a/spec/frontend/helpers/vue_test_utils_helper.js b/spec/frontend/helpers/vue_test_utils_helper.js
index 19e27388eeb..121e99c9783 100644
--- a/spec/frontend/helpers/vue_test_utils_helper.js
+++ b/spec/frontend/helpers/vue_test_utils_helper.js
@@ -16,4 +16,6 @@ const vNodeContainsText = (vnode, text) =>
* @param {String} text
*/
export const shallowWrapperContainsSlotText = (shallowWrapper, slotName, text) =>
- !!shallowWrapper.vm.$slots[slotName].filter(vnode => vNodeContainsText(vnode, text)).length;
+ Boolean(
+ shallowWrapper.vm.$slots[slotName].filter(vnode => vNodeContainsText(vnode, text)).length,
+ );
diff --git a/spec/frontend/ide/components/ide_status_list_spec.js b/spec/frontend/ide/components/ide_status_list_spec.js
new file mode 100644
index 00000000000..4e0e8a9f0e3
--- /dev/null
+++ b/spec/frontend/ide/components/ide_status_list_spec.js
@@ -0,0 +1,91 @@
+import Vuex from 'vuex';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import IdeStatusList from '~/ide/components/ide_status_list';
+
+const TEST_FILE = {
+ name: 'lorem.md',
+ eol: 'LF',
+ editorRow: 3,
+ editorColumn: 23,
+ fileLanguage: 'markdown',
+};
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('ide/components/ide_status_list', () => {
+ let activeFile;
+ let store;
+ let wrapper;
+
+ const createComponent = (options = {}) => {
+ store = new Vuex.Store({
+ getters: {
+ activeFile: () => activeFile,
+ },
+ });
+
+ wrapper = shallowMount(localVue.extend(IdeStatusList), {
+ localVue,
+ sync: false,
+ store,
+ ...options,
+ });
+ };
+
+ beforeEach(() => {
+ activeFile = TEST_FILE;
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+
+ store = null;
+ wrapper = null;
+ });
+
+ const getEditorPosition = file => `${file.editorRow}:${file.editorColumn}`;
+
+ describe('with regular file', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('shows file name', () => {
+ expect(wrapper.text()).toContain(TEST_FILE.name);
+ });
+
+ it('shows file eol', () => {
+ expect(wrapper.text()).toContain(TEST_FILE.name);
+ });
+
+ it('shows file editor position', () => {
+ expect(wrapper.text()).toContain(getEditorPosition(TEST_FILE));
+ });
+
+ it('shows file language', () => {
+ expect(wrapper.text()).toContain(TEST_FILE.fileLanguage);
+ });
+ });
+
+ describe('with binary file', () => {
+ beforeEach(() => {
+ activeFile.binary = true;
+ createComponent();
+ });
+
+ it('does not show file editor position', () => {
+ expect(wrapper.text()).not.toContain(getEditorPosition(TEST_FILE));
+ });
+ });
+
+ it('adds slot as child of list', () => {
+ createComponent({
+ slots: {
+ default: ['<div class="js-test">Hello</div>', '<div class="js-test">World</div>'],
+ },
+ });
+
+ expect(wrapper.find('.ide-status-list').findAll('.js-test').length).toEqual(2);
+ });
+});
diff --git a/spec/frontend/ide/stores/modules/commit/mutations_spec.js b/spec/frontend/ide/stores/modules/commit/mutations_spec.js
index 40d47aaad03..246500a2f34 100644
--- a/spec/frontend/ide/stores/modules/commit/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/commit/mutations_spec.js
@@ -54,5 +54,20 @@ describe('IDE commit module mutations', () => {
expect(state.shouldCreateMR).toBe(false);
});
+
+ it('sets shouldCreateMR to given value when passed in', () => {
+ state.shouldCreateMR = false;
+ mutations.TOGGLE_SHOULD_CREATE_MR(state, false);
+
+ expect(state.shouldCreateMR).toBe(false);
+ });
+ });
+
+ describe('INTERACT_WITH_NEW_MR', () => {
+ it('sets interactedWithNewMR to true', () => {
+ mutations.INTERACT_WITH_NEW_MR(state);
+
+ expect(state.interactedWithNewMR).toBe(true);
+ });
});
});
diff --git a/spec/frontend/ide/stores/modules/file_templates/mutations_spec.js b/spec/frontend/ide/stores/modules/file_templates/mutations_spec.js
index 8e8b7f06ca2..6a1a826093c 100644
--- a/spec/frontend/ide/stores/modules/file_templates/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/file_templates/mutations_spec.js
@@ -2,6 +2,9 @@ import createState from '~/ide/stores/modules/file_templates/state';
import * as types from '~/ide/stores/modules/file_templates/mutation_types';
import mutations from '~/ide/stores/modules/file_templates/mutations';
+const mockFileTemplates = [['MIT'], ['CC']];
+const mockTemplateType = 'test';
+
describe('IDE file templates mutations', () => {
let state;
@@ -10,11 +13,21 @@ describe('IDE file templates mutations', () => {
});
describe(`${types.REQUEST_TEMPLATE_TYPES}`, () => {
- it('sets isLoading', () => {
+ it('sets loading to true', () => {
+ state.isLoading = false;
+
mutations[types.REQUEST_TEMPLATE_TYPES](state);
expect(state.isLoading).toBe(true);
});
+
+ it('sets templates to an empty array', () => {
+ state.templates = mockFileTemplates;
+
+ mutations[types.REQUEST_TEMPLATE_TYPES](state);
+
+ expect(state.templates).toEqual([]);
+ });
});
describe(`${types.RECEIVE_TEMPLATE_TYPES_ERROR}`, () => {
@@ -31,29 +44,33 @@ describe('IDE file templates mutations', () => {
it('sets isLoading to false', () => {
state.isLoading = true;
- mutations[types.RECEIVE_TEMPLATE_TYPES_SUCCESS](state, []);
+ mutations[types.RECEIVE_TEMPLATE_TYPES_SUCCESS](state, mockFileTemplates);
expect(state.isLoading).toBe(false);
});
- it('sets templates', () => {
- mutations[types.RECEIVE_TEMPLATE_TYPES_SUCCESS](state, ['test']);
+ it('sets templates to payload', () => {
+ state.templates = ['test'];
+
+ mutations[types.RECEIVE_TEMPLATE_TYPES_SUCCESS](state, mockFileTemplates);
- expect(state.templates).toEqual(['test']);
+ expect(state.templates).toEqual(mockFileTemplates);
});
});
describe(`${types.SET_SELECTED_TEMPLATE_TYPE}`, () => {
- it('sets selectedTemplateType', () => {
- mutations[types.SET_SELECTED_TEMPLATE_TYPE](state, 'type');
+ it('sets templates type to selected type', () => {
+ state.selectedTemplateType = '';
- expect(state.selectedTemplateType).toBe('type');
+ mutations[types.SET_SELECTED_TEMPLATE_TYPE](state, mockTemplateType);
+
+ expect(state.selectedTemplateType).toBe(mockTemplateType);
});
- it('clears templates', () => {
- state.templates = ['test'];
+ it('sets templates to empty array', () => {
+ state.templates = mockFileTemplates;
- mutations[types.SET_SELECTED_TEMPLATE_TYPE](state, 'type');
+ mutations[types.SET_SELECTED_TEMPLATE_TYPE](state, mockTemplateType);
expect(state.templates).toEqual([]);
});
@@ -61,6 +78,8 @@ describe('IDE file templates mutations', () => {
describe(`${types.SET_UPDATE_SUCCESS}`, () => {
it('sets updateSuccess', () => {
+ state.updateSuccess = false;
+
mutations[types.SET_UPDATE_SUCCESS](state, true);
expect(state.updateSuccess).toBe(true);
diff --git a/spec/frontend/ide/stores/mutations/branch_spec.js b/spec/frontend/ide/stores/mutations/branch_spec.js
index 29eb859ddaf..0900b25d5d3 100644
--- a/spec/frontend/ide/stores/mutations/branch_spec.js
+++ b/spec/frontend/ide/stores/mutations/branch_spec.js
@@ -37,4 +37,39 @@ describe('Multi-file store branch mutations', () => {
expect(localState.projects.Example.branches.master.commit.title).toBe('Example commit');
});
});
+
+ describe('SET_BRANCH_WORKING_REFERENCE', () => {
+ beforeEach(() => {
+ localState.projects = {
+ Foo: {
+ branches: {
+ bar: {},
+ },
+ },
+ };
+ });
+
+ it('sets workingReference for existing branch', () => {
+ mutations.SET_BRANCH_WORKING_REFERENCE(localState, {
+ projectId: 'Foo',
+ branchId: 'bar',
+ reference: 'foo-bar-ref',
+ });
+
+ expect(localState.projects.Foo.branches.bar.workingReference).toBe('foo-bar-ref');
+ });
+
+ it('does not fail on non-existent just yet branch', () => {
+ expect(localState.projects.Foo.branches.unknown).toBeUndefined();
+
+ mutations.SET_BRANCH_WORKING_REFERENCE(localState, {
+ projectId: 'Foo',
+ branchId: 'unknown',
+ reference: 'fun-fun-ref',
+ });
+
+ expect(localState.projects.Foo.branches.unknown).not.toBeUndefined();
+ expect(localState.projects.Foo.branches.unknown.workingReference).toBe('fun-fun-ref');
+ });
+ });
});
diff --git a/spec/frontend/ide/stores/mutations/project_spec.js b/spec/frontend/ide/stores/mutations/project_spec.js
new file mode 100644
index 00000000000..b3ce39c33d2
--- /dev/null
+++ b/spec/frontend/ide/stores/mutations/project_spec.js
@@ -0,0 +1,23 @@
+import mutations from '~/ide/stores/mutations/project';
+import state from '~/ide/stores/state';
+
+describe('Multi-file store branch mutations', () => {
+ let localState;
+
+ beforeEach(() => {
+ localState = state();
+ localState.projects = { abcproject: { empty_repo: true } };
+ });
+
+ describe('TOGGLE_EMPTY_STATE', () => {
+ it('sets empty_repo for project to passed value', () => {
+ mutations.TOGGLE_EMPTY_STATE(localState, { projectPath: 'abcproject', value: false });
+
+ expect(localState.projects.abcproject.empty_repo).toBe(false);
+
+ mutations.TOGGLE_EMPTY_STATE(localState, { projectPath: 'abcproject', value: true });
+
+ expect(localState.projects.abcproject.empty_repo).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/import_projects/components/import_projects_table_spec.js b/spec/frontend/import_projects/components/import_projects_table_spec.js
new file mode 100644
index 00000000000..17a998d0174
--- /dev/null
+++ b/spec/frontend/import_projects/components/import_projects_table_spec.js
@@ -0,0 +1,185 @@
+import Vuex from 'vuex';
+import { createLocalVue, mount } from '@vue/test-utils';
+import { state, actions, getters, mutations } from '~/import_projects/store';
+import importProjectsTable from '~/import_projects/components/import_projects_table.vue';
+import STATUS_MAP from '~/import_projects/constants';
+
+describe('ImportProjectsTable', () => {
+ let vm;
+ const providerTitle = 'THE PROVIDER';
+ const providerRepo = { id: 10, sanitizedName: 'sanitizedName', fullName: 'fullName' };
+ const importedProject = {
+ id: 1,
+ fullPath: 'fullPath',
+ importStatus: 'started',
+ providerLink: 'providerLink',
+ importSource: 'importSource',
+ };
+
+ function initStore() {
+ const stubbedActions = Object.assign({}, actions, {
+ fetchJobs: jest.fn(),
+ fetchRepos: jest.fn(actions.requestRepos),
+ fetchImport: jest.fn(actions.requestImport),
+ });
+
+ const store = new Vuex.Store({
+ state: state(),
+ actions: stubbedActions,
+ mutations,
+ getters,
+ });
+
+ return store;
+ }
+
+ function mountComponent() {
+ const localVue = createLocalVue();
+ localVue.use(Vuex);
+
+ const store = initStore();
+
+ const component = mount(importProjectsTable, {
+ localVue,
+ store,
+ propsData: {
+ providerTitle,
+ },
+ sync: false,
+ });
+
+ return component.vm;
+ }
+
+ beforeEach(() => {
+ vm = mountComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('renders a loading icon whilst repos are loading', () =>
+ vm.$nextTick().then(() => {
+ expect(vm.$el.querySelector('.js-loading-button-icon')).not.toBeNull();
+ }));
+
+ it('renders a table with imported projects and provider repos', () => {
+ vm.$store.dispatch('receiveReposSuccess', {
+ importedProjects: [importedProject],
+ providerRepos: [providerRepo],
+ namespaces: [{ path: 'path' }],
+ });
+
+ return vm.$nextTick().then(() => {
+ expect(vm.$el.querySelector('.js-loading-button-icon')).toBeNull();
+ expect(vm.$el.querySelector('.table')).not.toBeNull();
+ expect(vm.$el.querySelector('.import-jobs-from-col').innerText).toMatch(
+ `From ${providerTitle}`,
+ );
+
+ expect(vm.$el.querySelector('.js-imported-project')).not.toBeNull();
+ expect(vm.$el.querySelector('.js-provider-repo')).not.toBeNull();
+ });
+ });
+
+ it('renders an empty state if there are no imported projects or provider repos', () => {
+ vm.$store.dispatch('receiveReposSuccess', {
+ importedProjects: [],
+ providerRepos: [],
+ namespaces: [],
+ });
+
+ return vm.$nextTick().then(() => {
+ expect(vm.$el.querySelector('.js-loading-button-icon')).toBeNull();
+ expect(vm.$el.querySelector('.table')).toBeNull();
+ expect(vm.$el.innerText).toMatch(`No ${providerTitle} repositories available to import`);
+ });
+ });
+
+ it('shows loading spinner when bulk import button is clicked', () => {
+ vm.$store.dispatch('receiveReposSuccess', {
+ importedProjects: [],
+ providerRepos: [providerRepo],
+ namespaces: [{ path: 'path' }],
+ });
+
+ return vm
+ .$nextTick()
+ .then(() => {
+ expect(vm.$el.querySelector('.js-imported-project')).toBeNull();
+ expect(vm.$el.querySelector('.js-provider-repo')).not.toBeNull();
+
+ vm.$el.querySelector('.js-import-all').click();
+ })
+ .then(() => vm.$nextTick())
+ .then(() => {
+ expect(vm.$el.querySelector('.js-import-all .js-loading-button-icon')).not.toBeNull();
+ });
+ });
+
+ it('imports provider repos if bulk import button is clicked', () => {
+ mountComponent();
+
+ vm.$store.dispatch('receiveReposSuccess', {
+ importedProjects: [],
+ providerRepos: [providerRepo],
+ namespaces: [{ path: 'path' }],
+ });
+
+ return vm
+ .$nextTick()
+ .then(() => {
+ expect(vm.$el.querySelector('.js-imported-project')).toBeNull();
+ expect(vm.$el.querySelector('.js-provider-repo')).not.toBeNull();
+
+ vm.$store.dispatch('receiveImportSuccess', { importedProject, repoId: providerRepo.id });
+ })
+ .then(() => vm.$nextTick())
+ .then(() => {
+ expect(vm.$el.querySelector('.js-imported-project')).not.toBeNull();
+ expect(vm.$el.querySelector('.js-provider-repo')).toBeNull();
+ });
+ });
+
+ it('polls to update the status of imported projects', () => {
+ const updatedProjects = [
+ {
+ id: importedProject.id,
+ importStatus: 'finished',
+ },
+ ];
+
+ vm.$store.dispatch('receiveReposSuccess', {
+ importedProjects: [importedProject],
+ providerRepos: [],
+ namespaces: [{ path: 'path' }],
+ });
+
+ return vm
+ .$nextTick()
+ .then(() => {
+ const statusObject = STATUS_MAP[importedProject.importStatus];
+
+ expect(vm.$el.querySelector('.js-imported-project')).not.toBeNull();
+ expect(vm.$el.querySelector(`.${statusObject.textClass}`).textContent).toMatch(
+ statusObject.text,
+ );
+
+ expect(vm.$el.querySelector(`.ic-status_${statusObject.icon}`)).not.toBeNull();
+
+ vm.$store.dispatch('receiveJobsSuccess', updatedProjects);
+ })
+ .then(() => vm.$nextTick())
+ .then(() => {
+ const statusObject = STATUS_MAP[updatedProjects[0].importStatus];
+
+ expect(vm.$el.querySelector('.js-imported-project')).not.toBeNull();
+ expect(vm.$el.querySelector(`.${statusObject.textClass}`).textContent).toMatch(
+ statusObject.text,
+ );
+
+ expect(vm.$el.querySelector(`.ic-status_${statusObject.icon}`)).not.toBeNull();
+ });
+ });
+});
diff --git a/spec/frontend/import_projects/components/imported_project_table_row_spec.js b/spec/frontend/import_projects/components/imported_project_table_row_spec.js
new file mode 100644
index 00000000000..f95acc1edd7
--- /dev/null
+++ b/spec/frontend/import_projects/components/imported_project_table_row_spec.js
@@ -0,0 +1,58 @@
+import Vuex from 'vuex';
+import createStore from '~/import_projects/store';
+import { createLocalVue, mount } from '@vue/test-utils';
+import importedProjectTableRow from '~/import_projects/components/imported_project_table_row.vue';
+import STATUS_MAP from '~/import_projects/constants';
+
+describe('ImportedProjectTableRow', () => {
+ let vm;
+ const project = {
+ id: 1,
+ fullPath: 'fullPath',
+ importStatus: 'finished',
+ providerLink: 'providerLink',
+ importSource: 'importSource',
+ };
+
+ function mountComponent() {
+ const localVue = createLocalVue();
+ localVue.use(Vuex);
+
+ const component = mount(importedProjectTableRow, {
+ localVue,
+ store: createStore(),
+ propsData: {
+ project: {
+ ...project,
+ },
+ },
+ sync: false,
+ });
+
+ return component.vm;
+ }
+
+ beforeEach(() => {
+ vm = mountComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('renders an imported project table row', () => {
+ const providerLink = vm.$el.querySelector('.js-provider-link');
+ const statusObject = STATUS_MAP[project.importStatus];
+
+ expect(vm.$el.classList.contains('js-imported-project')).toBe(true);
+ expect(providerLink.href).toMatch(project.providerLink);
+ expect(providerLink.textContent).toMatch(project.importSource);
+ expect(vm.$el.querySelector('.js-full-path').textContent).toMatch(project.fullPath);
+ expect(vm.$el.querySelector(`.${statusObject.textClass}`).textContent).toMatch(
+ statusObject.text,
+ );
+
+ expect(vm.$el.querySelector(`.ic-status_${statusObject.icon}`)).not.toBeNull();
+ expect(vm.$el.querySelector('.js-go-to-project').href).toMatch(project.fullPath);
+ });
+});
diff --git a/spec/frontend/import_projects/components/provider_repo_table_row_spec.js b/spec/frontend/import_projects/components/provider_repo_table_row_spec.js
new file mode 100644
index 00000000000..02c786d8d0b
--- /dev/null
+++ b/spec/frontend/import_projects/components/provider_repo_table_row_spec.js
@@ -0,0 +1,104 @@
+import Vuex from 'vuex';
+import { createLocalVue, mount } from '@vue/test-utils';
+import { state, actions, getters, mutations } from '~/import_projects/store';
+import providerRepoTableRow from '~/import_projects/components/provider_repo_table_row.vue';
+import STATUS_MAP, { STATUSES } from '~/import_projects/constants';
+
+describe('ProviderRepoTableRow', () => {
+ let vm;
+ const fetchImport = jest.fn((context, data) => actions.requestImport(context, data));
+ const importPath = '/import-path';
+ const defaultTargetNamespace = 'user';
+ const ciCdOnly = true;
+ const repo = {
+ id: 10,
+ sanitizedName: 'sanitizedName',
+ fullName: 'fullName',
+ providerLink: 'providerLink',
+ };
+
+ function initStore() {
+ const stubbedActions = Object.assign({}, actions, {
+ fetchImport,
+ });
+
+ const store = new Vuex.Store({
+ state: state(),
+ actions: stubbedActions,
+ mutations,
+ getters,
+ });
+
+ return store;
+ }
+
+ function mountComponent() {
+ const localVue = createLocalVue();
+ localVue.use(Vuex);
+
+ const store = initStore();
+ store.dispatch('setInitialData', { importPath, defaultTargetNamespace, ciCdOnly });
+
+ const component = mount(providerRepoTableRow, {
+ localVue,
+ store,
+ propsData: {
+ repo,
+ },
+ sync: false,
+ });
+
+ return component.vm;
+ }
+
+ beforeEach(() => {
+ vm = mountComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('renders a provider repo table row', () => {
+ const providerLink = vm.$el.querySelector('.js-provider-link');
+ const statusObject = STATUS_MAP[STATUSES.NONE];
+
+ expect(vm.$el.classList.contains('js-provider-repo')).toBe(true);
+ expect(providerLink.href).toMatch(repo.providerLink);
+ expect(providerLink.textContent).toMatch(repo.fullName);
+ expect(vm.$el.querySelector(`.${statusObject.textClass}`).textContent).toMatch(
+ statusObject.text,
+ );
+
+ expect(vm.$el.querySelector(`.ic-status_${statusObject.icon}`)).not.toBeNull();
+ expect(vm.$el.querySelector('.js-import-button')).not.toBeNull();
+ });
+
+ it('renders a select2 namespace select', () => {
+ const dropdownTrigger = vm.$el.querySelector('.js-namespace-select');
+
+ expect(dropdownTrigger).not.toBeNull();
+ expect(dropdownTrigger.classList.contains('select2-container')).toBe(true);
+
+ dropdownTrigger.click();
+
+ expect(vm.$el.querySelector('.select2-drop')).not.toBeNull();
+ });
+
+ it('imports repo when clicking import button', () => {
+ vm.$el.querySelector('.js-import-button').click();
+
+ return vm.$nextTick().then(() => {
+ const { calls } = fetchImport.mock;
+
+ // Not using .toBeCalledWith because it expects
+ // an unmatchable and undefined 3rd argument.
+ expect(calls.length).toBe(1);
+ expect(calls[0][1]).toEqual({
+ repo,
+ newName: repo.sanitizedName,
+ targetNamespace: defaultTargetNamespace,
+ });
+ });
+ });
+});
diff --git a/spec/frontend/import_projects/store/actions_spec.js b/spec/frontend/import_projects/store/actions_spec.js
new file mode 100644
index 00000000000..6a7b90788dd
--- /dev/null
+++ b/spec/frontend/import_projects/store/actions_spec.js
@@ -0,0 +1,284 @@
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import {
+ SET_INITIAL_DATA,
+ REQUEST_REPOS,
+ RECEIVE_REPOS_SUCCESS,
+ RECEIVE_REPOS_ERROR,
+ REQUEST_IMPORT,
+ RECEIVE_IMPORT_SUCCESS,
+ RECEIVE_IMPORT_ERROR,
+ RECEIVE_JOBS_SUCCESS,
+} from '~/import_projects/store/mutation_types';
+import {
+ setInitialData,
+ requestRepos,
+ receiveReposSuccess,
+ receiveReposError,
+ fetchRepos,
+ requestImport,
+ receiveImportSuccess,
+ receiveImportError,
+ fetchImport,
+ receiveJobsSuccess,
+ fetchJobs,
+ clearJobsEtagPoll,
+ stopJobsPolling,
+} from '~/import_projects/store/actions';
+import state from '~/import_projects/store/state';
+import testAction from 'helpers/vuex_action_helper';
+import { TEST_HOST } from 'helpers/test_constants';
+
+describe('import_projects store actions', () => {
+ let localState;
+ const repoId = 1;
+ const repos = [{ id: 1 }, { id: 2 }];
+ const importPayload = { newName: 'newName', targetNamespace: 'targetNamespace', repo: { id: 1 } };
+
+ beforeEach(() => {
+ localState = state();
+ });
+
+ describe('setInitialData', () => {
+ it(`commits ${SET_INITIAL_DATA} mutation`, done => {
+ const initialData = {
+ reposPath: 'reposPath',
+ provider: 'provider',
+ jobsPath: 'jobsPath',
+ importPath: 'impapp/assets/javascripts/vue_shared/components/select2_select.vueortPath',
+ defaultTargetNamespace: 'defaultTargetNamespace',
+ ciCdOnly: 'ciCdOnly',
+ canSelectNamespace: 'canSelectNamespace',
+ };
+
+ testAction(
+ setInitialData,
+ initialData,
+ localState,
+ [{ type: SET_INITIAL_DATA, payload: initialData }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('requestRepos', () => {
+ it(`requestRepos commits ${REQUEST_REPOS} mutation`, done => {
+ testAction(
+ requestRepos,
+ null,
+ localState,
+ [{ type: REQUEST_REPOS, payload: null }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('receiveReposSuccess', () => {
+ it(`commits ${RECEIVE_REPOS_SUCCESS} mutation`, done => {
+ testAction(
+ receiveReposSuccess,
+ repos,
+ localState,
+ [{ type: RECEIVE_REPOS_SUCCESS, payload: repos }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('receiveReposError', () => {
+ it(`commits ${RECEIVE_REPOS_ERROR} mutation`, done => {
+ testAction(receiveReposError, repos, localState, [{ type: RECEIVE_REPOS_ERROR }], [], done);
+ });
+ });
+
+ describe('fetchRepos', () => {
+ let mock;
+
+ beforeEach(() => {
+ localState.reposPath = `${TEST_HOST}/endpoint.json`;
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => mock.restore());
+
+ it('dispatches requestRepos and receiveReposSuccess actions on a successful request', done => {
+ const payload = { imported_projects: [{}], provider_repos: [{}], namespaces: [{}] };
+ mock.onGet(`${TEST_HOST}/endpoint.json`).reply(200, payload);
+
+ testAction(
+ fetchRepos,
+ null,
+ localState,
+ [],
+ [
+ { type: 'requestRepos' },
+ {
+ type: 'receiveReposSuccess',
+ payload: convertObjectPropsToCamelCase(payload, { deep: true }),
+ },
+ {
+ type: 'fetchJobs',
+ },
+ ],
+ done,
+ );
+ });
+
+ it('dispatches requestRepos and receiveReposSuccess actions on an unsuccessful request', done => {
+ mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500);
+
+ testAction(
+ fetchRepos,
+ null,
+ localState,
+ [],
+ [{ type: 'requestRepos' }, { type: 'receiveReposError' }],
+ done,
+ );
+ });
+ });
+
+ describe('requestImport', () => {
+ it(`commits ${REQUEST_IMPORT} mutation`, done => {
+ testAction(
+ requestImport,
+ repoId,
+ localState,
+ [{ type: REQUEST_IMPORT, payload: repoId }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('receiveImportSuccess', () => {
+ it(`commits ${RECEIVE_IMPORT_SUCCESS} mutation`, done => {
+ const payload = { importedProject: { name: 'imported/project' }, repoId: 2 };
+
+ testAction(
+ receiveImportSuccess,
+ payload,
+ localState,
+ [{ type: RECEIVE_IMPORT_SUCCESS, payload }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('receiveImportError', () => {
+ it(`commits ${RECEIVE_IMPORT_ERROR} mutation`, done => {
+ testAction(
+ receiveImportError,
+ repoId,
+ localState,
+ [{ type: RECEIVE_IMPORT_ERROR, payload: repoId }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('fetchImport', () => {
+ let mock;
+
+ beforeEach(() => {
+ localState.importPath = `${TEST_HOST}/endpoint.json`;
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => mock.restore());
+
+ it('dispatches requestImport and receiveImportSuccess actions on a successful request', done => {
+ const importedProject = { name: 'imported/project' };
+ const importRepoId = importPayload.repo.id;
+ mock.onPost(`${TEST_HOST}/endpoint.json`).reply(200, importedProject);
+
+ testAction(
+ fetchImport,
+ importPayload,
+ localState,
+ [],
+ [
+ { type: 'requestImport', payload: importRepoId },
+ {
+ type: 'receiveImportSuccess',
+ payload: {
+ importedProject: convertObjectPropsToCamelCase(importedProject, { deep: true }),
+ repoId: importRepoId,
+ },
+ },
+ ],
+ done,
+ );
+ });
+
+ it('dispatches requestImport and receiveImportSuccess actions on an unsuccessful request', done => {
+ mock.onPost(`${TEST_HOST}/endpoint.json`).reply(500);
+
+ testAction(
+ fetchImport,
+ importPayload,
+ localState,
+ [],
+ [
+ { type: 'requestImport', payload: importPayload.repo.id },
+ { type: 'receiveImportError', payload: { repoId: importPayload.repo.id } },
+ ],
+ done,
+ );
+ });
+ });
+
+ describe('receiveJobsSuccess', () => {
+ it(`commits ${RECEIVE_JOBS_SUCCESS} mutation`, done => {
+ testAction(
+ receiveJobsSuccess,
+ repos,
+ localState,
+ [{ type: RECEIVE_JOBS_SUCCESS, payload: repos }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('fetchJobs', () => {
+ let mock;
+
+ beforeEach(() => {
+ localState.jobsPath = `${TEST_HOST}/endpoint.json`;
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ stopJobsPolling();
+ clearJobsEtagPoll();
+ });
+
+ afterEach(() => mock.restore());
+
+ it('dispatches requestJobs and receiveJobsSuccess actions on a successful request', done => {
+ const updatedProjects = [{ name: 'imported/project' }, { name: 'provider/repo' }];
+ mock.onGet(`${TEST_HOST}/endpoint.json`).reply(200, updatedProjects);
+
+ testAction(
+ fetchJobs,
+ null,
+ localState,
+ [],
+ [
+ {
+ type: 'receiveJobsSuccess',
+ payload: convertObjectPropsToCamelCase(updatedProjects, { deep: true }),
+ },
+ ],
+ done,
+ );
+ });
+ });
+});
diff --git a/spec/frontend/jobs/store/mutations_spec.js b/spec/frontend/jobs/store/mutations_spec.js
index d7908efcf13..343301b8716 100644
--- a/spec/frontend/jobs/store/mutations_spec.js
+++ b/spec/frontend/jobs/store/mutations_spec.js
@@ -150,44 +150,8 @@ describe('Jobs Store Mutations', () => {
});
});
- describe('REQUEST_STAGES', () => {
- it('sets isLoadingStages to true', () => {
- mutations[types.REQUEST_STAGES](stateCopy);
-
- expect(stateCopy.isLoadingStages).toEqual(true);
- });
- });
-
- describe('RECEIVE_STAGES_SUCCESS', () => {
- beforeEach(() => {
- mutations[types.RECEIVE_STAGES_SUCCESS](stateCopy, [{ name: 'build' }]);
- });
-
- it('sets isLoadingStages to false', () => {
- expect(stateCopy.isLoadingStages).toEqual(false);
- });
-
- it('sets stages', () => {
- expect(stateCopy.stages).toEqual([{ name: 'build' }]);
- });
- });
-
- describe('RECEIVE_STAGES_ERROR', () => {
- beforeEach(() => {
- mutations[types.RECEIVE_STAGES_ERROR](stateCopy);
- });
-
- it('sets isLoadingStages to false', () => {
- expect(stateCopy.isLoadingStages).toEqual(false);
- });
-
- it('resets stages', () => {
- expect(stateCopy.stages).toEqual([]);
- });
- });
-
describe('REQUEST_JOBS_FOR_STAGE', () => {
- it('sets isLoadingStages to true', () => {
+ it('sets isLoadingJobs to true', () => {
mutations[types.REQUEST_JOBS_FOR_STAGE](stateCopy, { name: 'deploy' });
expect(stateCopy.isLoadingJobs).toEqual(true);
diff --git a/spec/frontend/lib/utils/datetime_utility_spec.js b/spec/frontend/lib/utils/datetime_utility_spec.js
new file mode 100644
index 00000000000..9f49e68cfe8
--- /dev/null
+++ b/spec/frontend/lib/utils/datetime_utility_spec.js
@@ -0,0 +1,436 @@
+import * as datetimeUtility from '~/lib/utils/datetime_utility';
+
+describe('Date time utils', () => {
+ describe('timeFor', () => {
+ it('returns `past due` when in past', () => {
+ const date = new Date();
+ date.setFullYear(date.getFullYear() - 1);
+
+ expect(datetimeUtility.timeFor(date)).toBe('Past due');
+ });
+
+ it('returns remaining time when in the future', () => {
+ const date = new Date();
+ date.setFullYear(date.getFullYear() + 1);
+
+ // Add a day to prevent a transient error. If date is even 1 second
+ // short of a full year, timeFor will return '11 months remaining'
+ date.setDate(date.getDate() + 1);
+
+ expect(datetimeUtility.timeFor(date)).toBe('1 year remaining');
+ });
+ });
+
+ describe('get day name', () => {
+ it('should return Sunday', () => {
+ const day = datetimeUtility.getDayName(new Date('07/17/2016'));
+
+ expect(day).toBe('Sunday');
+ });
+
+ it('should return Monday', () => {
+ const day = datetimeUtility.getDayName(new Date('07/18/2016'));
+
+ expect(day).toBe('Monday');
+ });
+
+ it('should return Tuesday', () => {
+ const day = datetimeUtility.getDayName(new Date('07/19/2016'));
+
+ expect(day).toBe('Tuesday');
+ });
+
+ it('should return Wednesday', () => {
+ const day = datetimeUtility.getDayName(new Date('07/20/2016'));
+
+ expect(day).toBe('Wednesday');
+ });
+
+ it('should return Thursday', () => {
+ const day = datetimeUtility.getDayName(new Date('07/21/2016'));
+
+ expect(day).toBe('Thursday');
+ });
+
+ it('should return Friday', () => {
+ const day = datetimeUtility.getDayName(new Date('07/22/2016'));
+
+ expect(day).toBe('Friday');
+ });
+
+ it('should return Saturday', () => {
+ const day = datetimeUtility.getDayName(new Date('07/23/2016'));
+
+ expect(day).toBe('Saturday');
+ });
+ });
+
+ describe('formatDate', () => {
+ it('should format date properly', () => {
+ const formattedDate = datetimeUtility.formatDate(new Date('07/23/2016'));
+
+ expect(formattedDate).toBe('Jul 23, 2016 12:00am GMT+0000');
+ });
+
+ it('should format ISO date properly', () => {
+ const formattedDate = datetimeUtility.formatDate('2016-07-23T00:00:00.559Z');
+
+ expect(formattedDate).toBe('Jul 23, 2016 12:00am GMT+0000');
+ });
+
+ it('should throw an error if date is invalid', () => {
+ expect(() => {
+ datetimeUtility.formatDate('2016-07-23 00:00:00 UTC');
+ }).toThrow(new Error('Invalid date'));
+ });
+ });
+
+ describe('get day difference', () => {
+ it('should return 7', () => {
+ const firstDay = new Date('07/01/2016');
+ const secondDay = new Date('07/08/2016');
+ const difference = datetimeUtility.getDayDifference(firstDay, secondDay);
+
+ expect(difference).toBe(7);
+ });
+
+ it('should return 31', () => {
+ const firstDay = new Date('07/01/2016');
+ const secondDay = new Date('08/01/2016');
+ const difference = datetimeUtility.getDayDifference(firstDay, secondDay);
+
+ expect(difference).toBe(31);
+ });
+
+ it('should return 365', () => {
+ const firstDay = new Date('07/02/2015');
+ const secondDay = new Date('07/01/2016');
+ const difference = datetimeUtility.getDayDifference(firstDay, secondDay);
+
+ expect(difference).toBe(365);
+ });
+ });
+});
+
+describe('timeIntervalInWords', () => {
+ it('should return string with number of minutes and seconds', () => {
+ expect(datetimeUtility.timeIntervalInWords(9.54)).toEqual('9 seconds');
+ expect(datetimeUtility.timeIntervalInWords(1)).toEqual('1 second');
+ expect(datetimeUtility.timeIntervalInWords(200)).toEqual('3 minutes 20 seconds');
+ expect(datetimeUtility.timeIntervalInWords(6008)).toEqual('100 minutes 8 seconds');
+ });
+});
+
+describe('dateInWords', () => {
+ const date = new Date('07/01/2016');
+
+ it('should return date in words', () => {
+ expect(datetimeUtility.dateInWords(date)).toEqual('July 1, 2016');
+ });
+
+ it('should return abbreviated month name', () => {
+ expect(datetimeUtility.dateInWords(date, true)).toEqual('Jul 1, 2016');
+ });
+
+ it('should return date in words without year', () => {
+ expect(datetimeUtility.dateInWords(date, true, true)).toEqual('Jul 1');
+ });
+});
+
+describe('monthInWords', () => {
+ const date = new Date('2017-01-20');
+
+ it('returns month name from provided date', () => {
+ expect(datetimeUtility.monthInWords(date)).toBe('January');
+ });
+
+ it('returns abbreviated month name from provided date', () => {
+ expect(datetimeUtility.monthInWords(date, true)).toBe('Jan');
+ });
+});
+
+describe('totalDaysInMonth', () => {
+ it('returns number of days in a month for given date', () => {
+ // 1st Feb, 2016 (leap year)
+ expect(datetimeUtility.totalDaysInMonth(new Date(2016, 1, 1))).toBe(29);
+
+ // 1st Feb, 2017
+ expect(datetimeUtility.totalDaysInMonth(new Date(2017, 1, 1))).toBe(28);
+
+ // 1st Jan, 2017
+ expect(datetimeUtility.totalDaysInMonth(new Date(2017, 0, 1))).toBe(31);
+ });
+});
+
+describe('getSundays', () => {
+ it('returns array of dates representing all Sundays of the month', () => {
+ // December, 2017 (it has 5 Sundays)
+ const dateOfSundays = [3, 10, 17, 24, 31];
+ const sundays = datetimeUtility.getSundays(new Date(2017, 11, 1));
+
+ expect(sundays.length).toBe(5);
+ sundays.forEach((sunday, index) => {
+ expect(sunday.getDate()).toBe(dateOfSundays[index]);
+ });
+ });
+});
+
+describe('getTimeframeWindowFrom', () => {
+ it('returns array of date objects upto provided length (positive number) into the future starting from provided startDate', () => {
+ const startDate = new Date(2018, 0, 1);
+ const mockTimeframe = [
+ new Date(2018, 0, 1),
+ new Date(2018, 1, 1),
+ new Date(2018, 2, 1),
+ new Date(2018, 3, 1),
+ new Date(2018, 4, 31),
+ ];
+ const timeframe = datetimeUtility.getTimeframeWindowFrom(startDate, 5);
+
+ expect(timeframe.length).toBe(5);
+ timeframe.forEach((timeframeItem, index) => {
+ expect(timeframeItem.getFullYear()).toBe(mockTimeframe[index].getFullYear());
+ expect(timeframeItem.getMonth()).toBe(mockTimeframe[index].getMonth());
+ expect(timeframeItem.getDate()).toBe(mockTimeframe[index].getDate());
+ });
+ });
+
+ it('returns array of date objects upto provided length (negative number) into the past starting from provided startDate', () => {
+ const startDate = new Date(2018, 0, 1);
+ const mockTimeframe = [
+ new Date(2018, 0, 1),
+ new Date(2017, 11, 1),
+ new Date(2017, 10, 1),
+ new Date(2017, 9, 1),
+ new Date(2017, 8, 1),
+ ];
+ const timeframe = datetimeUtility.getTimeframeWindowFrom(startDate, -5);
+
+ expect(timeframe.length).toBe(5);
+ timeframe.forEach((timeframeItem, index) => {
+ expect(timeframeItem.getFullYear()).toBe(mockTimeframe[index].getFullYear());
+ expect(timeframeItem.getMonth()).toBe(mockTimeframe[index].getMonth());
+ expect(timeframeItem.getDate()).toBe(mockTimeframe[index].getDate());
+ });
+ });
+});
+
+describe('formatTime', () => {
+ const expectedTimestamps = [
+ [0, '00:00:00'],
+ [1000, '00:00:01'],
+ [42000, '00:00:42'],
+ [121000, '00:02:01'],
+ [10921000, '03:02:01'],
+ [108000000, '30:00:00'],
+ ];
+
+ expectedTimestamps.forEach(([milliseconds, expectedTimestamp]) => {
+ it(`formats ${milliseconds}ms as ${expectedTimestamp}`, () => {
+ expect(datetimeUtility.formatTime(milliseconds)).toBe(expectedTimestamp);
+ });
+ });
+});
+
+describe('datefix', () => {
+ describe('pad', () => {
+ it('should add a 0 when length is smaller than 2', () => {
+ expect(datetimeUtility.pad(2)).toEqual('02');
+ });
+
+ it('should not add a zero when length matches the default', () => {
+ expect(datetimeUtility.pad(12)).toEqual('12');
+ });
+
+ it('should add a 0 when length is smaller than the provided', () => {
+ expect(datetimeUtility.pad(12, 3)).toEqual('012');
+ });
+ });
+
+ describe('parsePikadayDate', () => {
+ // removed because of https://gitlab.com/gitlab-org/gitlab-ce/issues/39834
+ });
+
+ describe('pikadayToString', () => {
+ it('should format a UTC date into yyyy-mm-dd format', () => {
+ expect(datetimeUtility.pikadayToString(new Date('2020-01-29:00:00'))).toEqual('2020-01-29');
+ });
+ });
+});
+
+describe('prettyTime methods', () => {
+ const assertTimeUnits = (obj, minutes, hours, days, weeks) => {
+ expect(obj.minutes).toBe(minutes);
+ expect(obj.hours).toBe(hours);
+ expect(obj.days).toBe(days);
+ expect(obj.weeks).toBe(weeks);
+ };
+
+ describe('parseSeconds', () => {
+ it('should correctly parse a negative value', () => {
+ const zeroSeconds = datetimeUtility.parseSeconds(-1000);
+
+ assertTimeUnits(zeroSeconds, 16, 0, 0, 0);
+ });
+
+ it('should correctly parse a zero value', () => {
+ const zeroSeconds = datetimeUtility.parseSeconds(0);
+
+ assertTimeUnits(zeroSeconds, 0, 0, 0, 0);
+ });
+
+ it('should correctly parse a small non-zero second values', () => {
+ const subOneMinute = datetimeUtility.parseSeconds(10);
+ const aboveOneMinute = datetimeUtility.parseSeconds(100);
+ const manyMinutes = datetimeUtility.parseSeconds(1000);
+
+ assertTimeUnits(subOneMinute, 0, 0, 0, 0);
+ assertTimeUnits(aboveOneMinute, 1, 0, 0, 0);
+ assertTimeUnits(manyMinutes, 16, 0, 0, 0);
+ });
+
+ it('should correctly parse large second values', () => {
+ const aboveOneHour = datetimeUtility.parseSeconds(4800);
+ const aboveOneDay = datetimeUtility.parseSeconds(110000);
+ const aboveOneWeek = datetimeUtility.parseSeconds(25000000);
+
+ assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
+ assertTimeUnits(aboveOneDay, 33, 6, 3, 0);
+ assertTimeUnits(aboveOneWeek, 26, 0, 3, 173);
+ });
+
+ it('should correctly accept a custom param for hoursPerDay', () => {
+ const config = { hoursPerDay: 24 };
+
+ const aboveOneHour = datetimeUtility.parseSeconds(4800, config);
+ const aboveOneDay = datetimeUtility.parseSeconds(110000, config);
+ const aboveOneWeek = datetimeUtility.parseSeconds(25000000, config);
+
+ assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
+ assertTimeUnits(aboveOneDay, 33, 6, 1, 0);
+ assertTimeUnits(aboveOneWeek, 26, 8, 4, 57);
+ });
+
+ it('should correctly accept a custom param for daysPerWeek', () => {
+ const config = { daysPerWeek: 7 };
+
+ const aboveOneHour = datetimeUtility.parseSeconds(4800, config);
+ const aboveOneDay = datetimeUtility.parseSeconds(110000, config);
+ const aboveOneWeek = datetimeUtility.parseSeconds(25000000, config);
+
+ assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
+ assertTimeUnits(aboveOneDay, 33, 6, 3, 0);
+ assertTimeUnits(aboveOneWeek, 26, 0, 0, 124);
+ });
+
+ it('should correctly accept custom params for daysPerWeek and hoursPerDay', () => {
+ const config = { daysPerWeek: 55, hoursPerDay: 14 };
+
+ const aboveOneHour = datetimeUtility.parseSeconds(4800, config);
+ const aboveOneDay = datetimeUtility.parseSeconds(110000, config);
+ const aboveOneWeek = datetimeUtility.parseSeconds(25000000, config);
+
+ assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
+ assertTimeUnits(aboveOneDay, 33, 2, 2, 0);
+ assertTimeUnits(aboveOneWeek, 26, 0, 1, 9);
+ });
+ });
+
+ describe('stringifyTime', () => {
+ it('should stringify values with all non-zero units', () => {
+ const timeObject = {
+ weeks: 1,
+ days: 4,
+ hours: 7,
+ minutes: 20,
+ };
+
+ const timeString = datetimeUtility.stringifyTime(timeObject);
+
+ expect(timeString).toBe('1w 4d 7h 20m');
+ });
+
+ it('should stringify values with some non-zero units', () => {
+ const timeObject = {
+ weeks: 0,
+ days: 4,
+ hours: 0,
+ minutes: 20,
+ };
+
+ const timeString = datetimeUtility.stringifyTime(timeObject);
+
+ expect(timeString).toBe('4d 20m');
+ });
+
+ it('should stringify values with no non-zero units', () => {
+ const timeObject = {
+ weeks: 0,
+ days: 0,
+ hours: 0,
+ minutes: 0,
+ };
+
+ const timeString = datetimeUtility.stringifyTime(timeObject);
+
+ expect(timeString).toBe('0m');
+ });
+
+ it('should return non-condensed representation of time object', () => {
+ const timeObject = { weeks: 1, days: 0, hours: 1, minutes: 0 };
+
+ expect(datetimeUtility.stringifyTime(timeObject, true)).toEqual('1 week 1 hour');
+ });
+ });
+
+ describe('abbreviateTime', () => {
+ it('should abbreviate stringified times for weeks', () => {
+ const fullTimeString = '1w 3d 4h 5m';
+
+ expect(datetimeUtility.abbreviateTime(fullTimeString)).toBe('1w');
+ });
+
+ it('should abbreviate stringified times for non-weeks', () => {
+ const fullTimeString = '0w 3d 4h 5m';
+
+ expect(datetimeUtility.abbreviateTime(fullTimeString)).toBe('3d');
+ });
+ });
+});
+
+describe('calculateRemainingMilliseconds', () => {
+ beforeEach(() => {
+ jest.spyOn(Date, 'now').mockImplementation(() => new Date('2063-04-04T00:42:00Z').getTime());
+ });
+
+ it('calculates the remaining time for a given end date', () => {
+ const milliseconds = datetimeUtility.calculateRemainingMilliseconds('2063-04-04T01:44:03Z');
+
+ expect(milliseconds).toBe(3723000);
+ });
+
+ it('returns 0 if the end date has passed', () => {
+ const milliseconds = datetimeUtility.calculateRemainingMilliseconds('2063-04-03T00:00:00Z');
+
+ expect(milliseconds).toBe(0);
+ });
+});
+
+describe('newDate', () => {
+ it('returns new date instance from existing date instance', () => {
+ const initialDate = new Date(2019, 0, 1);
+ const copiedDate = datetimeUtility.newDate(initialDate);
+
+ expect(copiedDate.getTime()).toBe(initialDate.getTime());
+
+ initialDate.setMonth(initialDate.getMonth() + 1);
+
+ expect(copiedDate.getTime()).not.toBe(initialDate.getTime());
+ });
+
+ it('returns date instance when provided date param is not of type date or is undefined', () => {
+ const initialDate = datetimeUtility.newDate();
+
+ expect(initialDate instanceof Date).toBe(true);
+ });
+});
diff --git a/spec/frontend/lib/utils/number_utility_spec.js b/spec/frontend/lib/utils/number_utility_spec.js
index 818404bad81..77d7478d317 100644
--- a/spec/frontend/lib/utils/number_utility_spec.js
+++ b/spec/frontend/lib/utils/number_utility_spec.js
@@ -5,6 +5,7 @@ import {
bytesToGiB,
numberToHumanSize,
sum,
+ isOdd,
} from '~/lib/utils/number_utils';
describe('Number Utils', () => {
@@ -98,4 +99,14 @@ describe('Number Utils', () => {
expect([1, 2, 3, 4, 5].reduce(sum)).toEqual(15);
});
});
+
+ describe('isOdd', () => {
+ it('should return 0 with a even number', () => {
+ expect(isOdd(2)).toEqual(0);
+ });
+
+ it('should return 1 with a odd number', () => {
+ expect(isOdd(1)).toEqual(1);
+ });
+ });
});
diff --git a/spec/frontend/lib/utils/text_utility_spec.js b/spec/frontend/lib/utils/text_utility_spec.js
index 0878c1de095..9e920d59093 100644
--- a/spec/frontend/lib/utils/text_utility_spec.js
+++ b/spec/frontend/lib/utils/text_utility_spec.js
@@ -155,11 +155,11 @@ describe('text_utility', () => {
expect(textUtils.truncateNamespace('a / b')).toBe('a');
});
- it(`should return the first 2 namespaces if the namespace inlcudes exactly 2 levels`, () => {
+ it(`should return the first 2 namespaces if the namespace includes exactly 2 levels`, () => {
expect(textUtils.truncateNamespace('a / b / c')).toBe('a / b');
});
- it(`should return the first and last namespaces, separated by "...", if the namespace inlcudes more than 2 levels`, () => {
+ it(`should return the first and last namespaces, separated by "...", if the namespace includes more than 2 levels`, () => {
expect(textUtils.truncateNamespace('a / b / c / d')).toBe('a / ... / c');
expect(textUtils.truncateNamespace('a / b / c / d / e / f / g / h / i')).toBe('a / ... / h');
});
diff --git a/spec/frontend/lib/utils/url_utility_spec.js b/spec/frontend/lib/utils/url_utility_spec.js
new file mode 100644
index 00000000000..c771984a137
--- /dev/null
+++ b/spec/frontend/lib/utils/url_utility_spec.js
@@ -0,0 +1,226 @@
+import * as urlUtils from '~/lib/utils/url_utility';
+
+const setWindowLocation = value => {
+ Object.defineProperty(window, 'location', {
+ writable: true,
+ value,
+ });
+};
+
+describe('URL utility', () => {
+ describe('webIDEUrl', () => {
+ afterEach(() => {
+ gon.relative_url_root = '';
+ });
+
+ describe('without relative_url_root', () => {
+ it('returns IDE path with route', () => {
+ expect(urlUtils.webIDEUrl('/gitlab-org/gitlab-ce/merge_requests/1')).toBe(
+ '/-/ide/project/gitlab-org/gitlab-ce/merge_requests/1',
+ );
+ });
+ });
+
+ describe('with relative_url_root', () => {
+ beforeEach(() => {
+ gon.relative_url_root = '/gitlab';
+ });
+
+ it('returns IDE path with route', () => {
+ expect(urlUtils.webIDEUrl('/gitlab/gitlab-org/gitlab-ce/merge_requests/1')).toBe(
+ '/gitlab/-/ide/project/gitlab-org/gitlab-ce/merge_requests/1',
+ );
+ });
+ });
+ });
+
+ describe('mergeUrlParams', () => {
+ it('adds w', () => {
+ expect(urlUtils.mergeUrlParams({ w: 1 }, '#frag')).toBe('?w=1#frag');
+ expect(urlUtils.mergeUrlParams({ w: 1 }, '/path#frag')).toBe('/path?w=1#frag');
+ expect(urlUtils.mergeUrlParams({ w: 1 }, 'https://host/path')).toBe('https://host/path?w=1');
+ expect(urlUtils.mergeUrlParams({ w: 1 }, 'https://host/path#frag')).toBe(
+ 'https://host/path?w=1#frag',
+ );
+
+ expect(urlUtils.mergeUrlParams({ w: 1 }, 'https://h/p?k1=v1#frag')).toBe(
+ 'https://h/p?k1=v1&w=1#frag',
+ );
+ });
+
+ it('updates w', () => {
+ expect(urlUtils.mergeUrlParams({ w: 1 }, '?k1=v1&w=0#frag')).toBe('?k1=v1&w=1#frag');
+ });
+
+ it('adds multiple params', () => {
+ expect(urlUtils.mergeUrlParams({ a: 1, b: 2, c: 3 }, '#frag')).toBe('?a=1&b=2&c=3#frag');
+ });
+
+ it('adds and updates encoded params', () => {
+ expect(urlUtils.mergeUrlParams({ a: '&', q: '?' }, '?a=%23#frag')).toBe('?a=%26&q=%3F#frag');
+ });
+ });
+
+ describe('removeParams', () => {
+ describe('when url is passed', () => {
+ it('removes query param with encoded ampersand', () => {
+ const url = urlUtils.removeParams(['filter'], '/mail?filter=n%3Djoe%26l%3Dhome');
+
+ expect(url).toBe('/mail');
+ });
+
+ it('should remove param when url has no other params', () => {
+ const url = urlUtils.removeParams(['size'], '/feature/home?size=5');
+
+ expect(url).toBe('/feature/home');
+ });
+
+ it('should remove param when url has other params', () => {
+ const url = urlUtils.removeParams(['size'], '/feature/home?q=1&size=5&f=html');
+
+ expect(url).toBe('/feature/home?q=1&f=html');
+ });
+
+ it('should remove param and preserve fragment', () => {
+ const url = urlUtils.removeParams(['size'], '/feature/home?size=5#H2');
+
+ expect(url).toBe('/feature/home#H2');
+ });
+
+ it('should remove multiple params', () => {
+ const url = urlUtils.removeParams(['z', 'a'], '/home?z=11111&l=en_US&a=true#H2');
+
+ expect(url).toBe('/home?l=en_US#H2');
+ });
+ });
+ });
+
+ describe('setUrlFragment', () => {
+ it('should set fragment when url has no fragment', () => {
+ const url = urlUtils.setUrlFragment('/home/feature', 'usage');
+
+ expect(url).toBe('/home/feature#usage');
+ });
+
+ it('should set fragment when url has existing fragment', () => {
+ const url = urlUtils.setUrlFragment('/home/feature#overview', 'usage');
+
+ expect(url).toBe('/home/feature#usage');
+ });
+
+ it('should set fragment when given fragment includes #', () => {
+ const url = urlUtils.setUrlFragment('/home/feature#overview', '#install');
+
+ expect(url).toBe('/home/feature#install');
+ });
+ });
+
+ describe('getBaseURL', () => {
+ beforeEach(() => {
+ setWindowLocation({
+ protocol: 'https:',
+ host: 'gitlab.com',
+ });
+ });
+
+ it('returns correct base URL', () => {
+ expect(urlUtils.getBaseURL()).toBe('https://gitlab.com');
+ });
+ });
+
+ describe('isAbsoluteOrRootRelative', () => {
+ const validUrls = ['https://gitlab.com/', 'http://gitlab.com/', '/users/sign_in'];
+
+ const invalidUrls = [' https://gitlab.com/', './file/path', 'notanurl', '<a></a>'];
+
+ it.each(validUrls)(`returns true for %s`, url => {
+ expect(urlUtils.isAbsoluteOrRootRelative(url)).toBe(true);
+ });
+
+ it.each(invalidUrls)(`returns false for %s`, url => {
+ expect(urlUtils.isAbsoluteOrRootRelative(url)).toBe(false);
+ });
+ });
+
+ describe('isSafeUrl', () => {
+ const absoluteUrls = [
+ 'http://example.org',
+ 'http://example.org:8080',
+ 'https://example.org',
+ 'https://example.org:8080',
+ 'https://192.168.1.1',
+ ];
+
+ const rootRelativeUrls = ['/relative/link'];
+
+ const relativeUrls = ['./relative/link', '../relative/link'];
+
+ const urlsWithoutHost = ['http://', 'https://', 'https:https:https:'];
+
+ /* eslint-disable no-script-url */
+ const nonHttpUrls = [
+ 'javascript:',
+ 'javascript:alert("XSS")',
+ 'jav\tascript:alert("XSS");',
+ ' &#14; javascript:alert("XSS");',
+ 'ftp://192.168.1.1',
+ 'file:///',
+ 'file:///etc/hosts',
+ ];
+ /* eslint-enable no-script-url */
+
+ // javascript:alert('XSS')
+ const encodedJavaScriptUrls = [
+ '&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041',
+ '&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;',
+ '&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29',
+ '\\u006A\\u0061\\u0076\\u0061\\u0073\\u0063\\u0072\\u0069\\u0070\\u0074\\u003A\\u0061\\u006C\\u0065\\u0072\\u0074\\u0028\\u0027\\u0058\\u0053\\u0053\\u0027\\u0029',
+ ];
+
+ const safeUrls = [...absoluteUrls, ...rootRelativeUrls];
+ const unsafeUrls = [
+ ...relativeUrls,
+ ...urlsWithoutHost,
+ ...nonHttpUrls,
+ ...encodedJavaScriptUrls,
+ ];
+
+ describe('with URL constructor support', () => {
+ it.each(safeUrls)('returns true for %s', url => {
+ expect(urlUtils.isSafeURL(url)).toBe(true);
+ });
+
+ it.each(unsafeUrls)('returns false for %s', url => {
+ expect(urlUtils.isSafeURL(url)).toBe(false);
+ });
+ });
+ });
+
+ describe('getWebSocketProtocol', () => {
+ it.each`
+ protocol | expectation
+ ${'http:'} | ${'ws:'}
+ ${'https:'} | ${'wss:'}
+ `('returns "$expectation" with "$protocol" protocol', ({ protocol, expectation }) => {
+ setWindowLocation({
+ protocol,
+ host: 'example.com',
+ });
+
+ expect(urlUtils.getWebSocketProtocol()).toEqual(expectation);
+ });
+ });
+
+ describe('getWebSocketUrl', () => {
+ it('joins location host to path', () => {
+ setWindowLocation({
+ protocol: 'http:',
+ host: 'example.com',
+ });
+
+ const path = '/lorem/ipsum?a=bc';
+
+ expect(urlUtils.getWebSocketUrl(path)).toEqual('ws://example.com/lorem/ipsum?a=bc');
+ });
+ });
+});
diff --git a/spec/frontend/mr_popover/__snapshots__/mr_popover_spec.js.snap b/spec/frontend/mr_popover/__snapshots__/mr_popover_spec.js.snap
index 5f9f13d591d..a2a7d0ee91e 100644
--- a/spec/frontend/mr_popover/__snapshots__/mr_popover_spec.js.snap
+++ b/spec/frontend/mr_popover/__snapshots__/mr_popover_spec.js.snap
@@ -3,6 +3,7 @@
exports[`MR Popover loaded state matches the snapshot 1`] = `
<glpopover-stub
boundary="viewport"
+ cssclasses=""
placement="top"
show=""
target=""
@@ -61,6 +62,7 @@ exports[`MR Popover loaded state matches the snapshot 1`] = `
exports[`MR Popover shows skeleton-loader while apollo is loading 1`] = `
<glpopover-stub
boundary="viewport"
+ cssclasses=""
placement="top"
show=""
target=""
diff --git a/spec/frontend/mr_popover/index_spec.js b/spec/frontend/mr_popover/index_spec.js
index 8c33e52a04b..b9db2342687 100644
--- a/spec/frontend/mr_popover/index_spec.js
+++ b/spec/frontend/mr_popover/index_spec.js
@@ -7,18 +7,28 @@ createDefaultClient.default = jest.fn();
describe('initMRPopovers', () => {
let mr1;
let mr2;
+ let mr3;
beforeEach(() => {
setHTMLFixture(`
- <div id="one" class="gfm-merge_request">MR1</div>
- <div id="two" class="gfm-merge_request">MR2</div>
+ <div id="one" class="gfm-merge_request" data-mr-title="title" data-iid="1" data-project-path="group/project">
+ MR1
+ </div>
+ <div id="two" class="gfm-merge_request" data-mr-title="title" data-iid="1" data-project-path="group/project">
+ MR2
+ </div>
+ <div id="three" class="gfm-merge_request">
+ MR3
+ </div>
`);
mr1 = document.querySelector('#one');
mr2 = document.querySelector('#two');
+ mr3 = document.querySelector('#three');
mr1.addEventListener = jest.fn();
mr2.addEventListener = jest.fn();
+ mr3.addEventListener = jest.fn();
});
it('does not add the same event listener twice', () => {
@@ -27,4 +37,10 @@ describe('initMRPopovers', () => {
expect(mr1.addEventListener).toHaveBeenCalledTimes(1);
expect(mr2.addEventListener).toHaveBeenCalledTimes(1);
});
+
+ it('does not add listener if it does not have the necessary data attributes', () => {
+ initMRPopovers([mr1, mr2, mr3]);
+
+ expect(mr3.addEventListener).not.toHaveBeenCalled();
+ });
});
diff --git a/spec/frontend/notes/components/discussion_actions_spec.js b/spec/frontend/notes/components/discussion_actions_spec.js
new file mode 100644
index 00000000000..0a52c81571e
--- /dev/null
+++ b/spec/frontend/notes/components/discussion_actions_spec.js
@@ -0,0 +1,104 @@
+import createStore from '~/notes/stores';
+import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
+import { discussionMock } from '../../../javascripts/notes/mock_data';
+import DiscussionActions from '~/notes/components/discussion_actions.vue';
+import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
+import ResolveDiscussionButton from '~/notes/components/discussion_resolve_button.vue';
+import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue';
+import JumpToNextDiscussionButton from '~/notes/components/discussion_jump_to_next_button.vue';
+
+describe('DiscussionActions', () => {
+ let wrapper;
+ const createComponentFactory = (shallow = true) => props => {
+ const localVue = createLocalVue();
+ const store = createStore();
+ const mountFn = shallow ? shallowMount : mount;
+
+ wrapper = mountFn(DiscussionActions, {
+ localVue,
+ store,
+ propsData: {
+ discussion: discussionMock,
+ isResolving: false,
+ resolveButtonTitle: 'Resolve discussion',
+ resolveWithIssuePath: '/some/issue/path',
+ shouldShowJumpToNextDiscussion: true,
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('rendering', () => {
+ const createComponent = createComponentFactory();
+
+ it('renders reply placeholder, resolve discussion button, resolve with issue button and jump to next discussion button', () => {
+ createComponent();
+ expect(wrapper.find(ReplyPlaceholder).exists()).toBe(true);
+ expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(true);
+ expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(true);
+ expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(true);
+ });
+
+ it('only renders reply placholder if disccusion is not resolvable', () => {
+ const discussion = { ...discussionMock };
+ discussion.resolvable = false;
+ createComponent({ discussion });
+
+ expect(wrapper.find(ReplyPlaceholder).exists()).toBe(true);
+ expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(false);
+ expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(false);
+ expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(false);
+ });
+
+ it('does not render resolve with issue button if resolveWithIssuePath is falsy', () => {
+ createComponent({ resolveWithIssuePath: '' });
+
+ expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(false);
+ });
+
+ it('does not render jump to next discussion button if shouldShowJumpToNextDiscussion is false', () => {
+ createComponent({ shouldShowJumpToNextDiscussion: false });
+
+ expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(false);
+ });
+ });
+
+ describe('events handling', () => {
+ const createComponent = createComponentFactory(false);
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('emits showReplyForm event when clicking on reply placeholder', () => {
+ jest.spyOn(wrapper.vm, '$emit');
+ wrapper
+ .find(ReplyPlaceholder)
+ .find('button')
+ .trigger('click');
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('showReplyForm');
+ });
+
+ it('emits resolve event when clicking on resolve button', () => {
+ jest.spyOn(wrapper.vm, '$emit');
+ wrapper
+ .find(ResolveDiscussionButton)
+ .find('button')
+ .trigger('click');
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('resolve');
+ });
+
+ it('emits jumpToNextDiscussion event when clicking on jump to next discussion button', () => {
+ jest.spyOn(wrapper.vm, '$emit');
+ wrapper
+ .find(JumpToNextDiscussionButton)
+ .find('button')
+ .trigger('click');
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('jumpToNextDiscussion');
+ });
+ });
+});
diff --git a/spec/frontend/notes/components/discussion_notes_spec.js b/spec/frontend/notes/components/discussion_notes_spec.js
new file mode 100644
index 00000000000..c3204b3aaa0
--- /dev/null
+++ b/spec/frontend/notes/components/discussion_notes_spec.js
@@ -0,0 +1,139 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import '~/behaviors/markdown/render_gfm';
+import { SYSTEM_NOTE } from '~/notes/constants';
+import DiscussionNotes from '~/notes/components/discussion_notes.vue';
+import NoteableNote from '~/notes/components/noteable_note.vue';
+import PlaceholderNote from '~/vue_shared/components/notes/placeholder_note.vue';
+import PlaceholderSystemNote from '~/vue_shared/components/notes/placeholder_system_note.vue';
+import SystemNote from '~/vue_shared/components/notes/system_note.vue';
+import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
+import createStore from '~/notes/stores';
+import {
+ noteableDataMock,
+ discussionMock,
+ notesDataMock,
+} from '../../../javascripts/notes/mock_data';
+
+const localVue = createLocalVue();
+
+describe('DiscussionNotes', () => {
+ let wrapper;
+
+ const createComponent = props => {
+ const store = createStore();
+ store.dispatch('setNoteableData', noteableDataMock);
+ store.dispatch('setNotesData', notesDataMock);
+
+ wrapper = shallowMount(DiscussionNotes, {
+ localVue,
+ store,
+ propsData: {
+ discussion: discussionMock,
+ isExpanded: false,
+ shouldGroupReplies: false,
+ ...props,
+ },
+ scopedSlots: {
+ footer: '<p slot-scope="{ showReplies }">showReplies:{{showReplies}}</p>',
+ },
+ slots: {
+ 'avatar-badge': '<span class="avatar-badge-slot-content" />',
+ },
+ sync: false,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('rendering', () => {
+ it('renders an element for each note in the discussion', () => {
+ createComponent();
+ const notesCount = discussionMock.notes.length;
+ const els = wrapper.findAll(TimelineEntryItem);
+ expect(els.length).toBe(notesCount);
+ });
+
+ it('renders one element if replies groupping is enabled', () => {
+ createComponent({ shouldGroupReplies: true });
+ const els = wrapper.findAll(TimelineEntryItem);
+ expect(els.length).toBe(1);
+ });
+
+ it('uses proper component to render each note type', () => {
+ const discussion = { ...discussionMock };
+ const notesData = [
+ // PlaceholderSystemNote
+ {
+ id: 1,
+ isPlaceholderNote: true,
+ placeholderType: SYSTEM_NOTE,
+ notes: [{ body: 'PlaceholderSystemNote' }],
+ },
+ // PlaceholderNote
+ {
+ id: 2,
+ isPlaceholderNote: true,
+ notes: [{ body: 'PlaceholderNote' }],
+ },
+ // SystemNote
+ {
+ id: 3,
+ system: true,
+ note: 'SystemNote',
+ },
+ // NoteableNote
+ discussion.notes[0],
+ ];
+ discussion.notes = notesData;
+ createComponent({ discussion });
+ const notes = wrapper.findAll('.notes > li');
+
+ expect(notes.at(0).is(PlaceholderSystemNote)).toBe(true);
+ expect(notes.at(1).is(PlaceholderNote)).toBe(true);
+ expect(notes.at(2).is(SystemNote)).toBe(true);
+ expect(notes.at(3).is(NoteableNote)).toBe(true);
+ });
+
+ it('renders footer scoped slot with showReplies === true when expanded', () => {
+ createComponent({ isExpanded: true });
+ expect(wrapper.text()).toMatch('showReplies:true');
+ });
+
+ it('renders footer scoped slot with showReplies === false when collapsed', () => {
+ createComponent({ isExpanded: false });
+ expect(wrapper.text()).toMatch('showReplies:false');
+ });
+
+ it('passes down avatar-badge slot content', () => {
+ createComponent();
+ expect(wrapper.find('.avatar-badge-slot-content').exists()).toBe(true);
+ });
+ });
+
+ describe('componentData', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('should return first note object for placeholder note', () => {
+ const data = {
+ isPlaceholderNote: true,
+ notes: [{ body: 'hello world!' }],
+ };
+ const note = wrapper.vm.componentData(data);
+
+ expect(note).toEqual(data.notes[0]);
+ });
+
+ it('should return given note for nonplaceholder notes', () => {
+ const data = {
+ notes: [{ id: 12 }],
+ };
+ const note = wrapper.vm.componentData(data);
+
+ expect(note).toEqual(data);
+ });
+ });
+});
diff --git a/spec/frontend/notes/components/note_app_spec.js b/spec/frontend/notes/components/note_app_spec.js
new file mode 100644
index 00000000000..ff833d2c899
--- /dev/null
+++ b/spec/frontend/notes/components/note_app_spec.js
@@ -0,0 +1,322 @@
+import $ from 'helpers/jquery';
+import Vue from 'vue';
+import { mount, createLocalVue } from '@vue/test-utils';
+import NotesApp from '~/notes/components/notes_app.vue';
+import service from '~/notes/services/notes_service';
+import createStore from '~/notes/stores';
+import '~/behaviors/markdown/render_gfm';
+import { setTestTimeout } from 'helpers/timeout';
+// TODO: use generated fixture (https://gitlab.com/gitlab-org/gitlab-ce/issues/62491)
+import * as mockData from '../../../javascripts/notes/mock_data';
+
+const originalInterceptors = [...Vue.http.interceptors];
+
+const emptyResponseInterceptor = (request, next) => {
+ next(
+ request.respondWith(JSON.stringify([]), {
+ status: 200,
+ }),
+ );
+};
+
+setTestTimeout(1000);
+
+describe('note_app', () => {
+ let mountComponent;
+ let wrapper;
+ let store;
+
+ /**
+ * waits for fetchNotes() to complete
+ */
+ const waitForDiscussionsRequest = () =>
+ new Promise(resolve => {
+ const { vm } = wrapper.find(NotesApp);
+ const unwatch = vm.$watch('isFetching', isFetching => {
+ if (isFetching) {
+ return;
+ }
+
+ unwatch();
+ resolve();
+ });
+ });
+
+ beforeEach(() => {
+ $('body').attr('data-page', 'projects:merge_requests:show');
+
+ store = createStore();
+ mountComponent = data => {
+ const propsData = data || {
+ noteableData: mockData.noteableDataMock,
+ notesData: mockData.notesDataMock,
+ userData: mockData.userDataMock,
+ };
+ const localVue = createLocalVue();
+
+ return mount(
+ {
+ components: {
+ NotesApp,
+ },
+ template: '<div class="js-vue-notes-event"><notes-app v-bind="$attrs" /></div>',
+ },
+ {
+ attachToDocument: true,
+ propsData,
+ store,
+ localVue,
+ sync: false,
+ },
+ );
+ };
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ Vue.http.interceptors = [...originalInterceptors];
+ });
+
+ describe('set data', () => {
+ beforeEach(() => {
+ Vue.http.interceptors.push(emptyResponseInterceptor);
+ wrapper = mountComponent();
+ return waitForDiscussionsRequest();
+ });
+
+ it('should set notes data', () => {
+ expect(store.state.notesData).toEqual(mockData.notesDataMock);
+ });
+
+ it('should set issue data', () => {
+ expect(store.state.noteableData).toEqual(mockData.noteableDataMock);
+ });
+
+ it('should set user data', () => {
+ expect(store.state.userData).toEqual(mockData.userDataMock);
+ });
+
+ it('should fetch discussions', () => {
+ expect(store.state.discussions).toEqual([]);
+ });
+ });
+
+ describe('render', () => {
+ beforeEach(() => {
+ setFixtures('<div class="js-discussions-count"></div>');
+
+ Vue.http.interceptors.push(mockData.individualNoteInterceptor);
+ wrapper = mountComponent();
+ return waitForDiscussionsRequest();
+ });
+
+ it('should render list of notes', () => {
+ const note =
+ mockData.INDIVIDUAL_NOTE_RESPONSE_MAP.GET[
+ '/gitlab-org/gitlab-ce/issues/26/discussions.json'
+ ][0].notes[0];
+
+ expect(
+ wrapper
+ .find('.main-notes-list .note-header-author-name')
+ .text()
+ .trim(),
+ ).toEqual(note.author.name);
+
+ expect(wrapper.find('.main-notes-list .note-text').html()).toContain(note.note_html);
+ });
+
+ it('should render form', () => {
+ expect(wrapper.find('.js-main-target-form').name()).toEqual('form');
+ expect(wrapper.find('.js-main-target-form textarea').attributes('placeholder')).toEqual(
+ 'Write a comment or drag your files here…',
+ );
+ });
+
+ it('should not render form when commenting is disabled', () => {
+ wrapper.destroy();
+
+ store.state.commentsDisabled = true;
+ wrapper = mountComponent();
+ return waitForDiscussionsRequest().then(() => {
+ expect(wrapper.find('.js-main-target-form').exists()).toBe(false);
+ });
+ });
+
+ it('should render discussion filter note `commentsDisabled` is true', () => {
+ wrapper.destroy();
+
+ store.state.commentsDisabled = true;
+ wrapper = mountComponent();
+ return waitForDiscussionsRequest().then(() => {
+ expect(wrapper.find('.js-discussion-filter-note').exists()).toBe(true);
+ });
+ });
+
+ it('should render form comment button as disabled', () => {
+ expect(wrapper.find('.js-note-new-discussion').attributes('disabled')).toEqual('disabled');
+ });
+
+ it('updates discussions badge', () => {
+ expect(document.querySelector('.js-discussions-count').textContent).toEqual('2');
+ });
+ });
+
+ describe('while fetching data', () => {
+ beforeEach(() => {
+ Vue.http.interceptors.push(emptyResponseInterceptor);
+ wrapper = mountComponent();
+ });
+
+ afterEach(() => waitForDiscussionsRequest());
+
+ it('renders skeleton notes', () => {
+ expect(wrapper.find('.animation-container').exists()).toBe(true);
+ });
+
+ it('should render form', () => {
+ expect(wrapper.find('.js-main-target-form').name()).toEqual('form');
+ expect(wrapper.find('.js-main-target-form textarea').attributes('placeholder')).toEqual(
+ 'Write a comment or drag your files here…',
+ );
+ });
+ });
+
+ describe('update note', () => {
+ describe('individual note', () => {
+ beforeEach(() => {
+ Vue.http.interceptors.push(mockData.individualNoteInterceptor);
+ jest.spyOn(service, 'updateNote');
+ wrapper = mountComponent();
+ return waitForDiscussionsRequest().then(() => {
+ wrapper.find('.js-note-edit').trigger('click');
+ });
+ });
+
+ it('renders edit form', () => {
+ expect(wrapper.find('.js-vue-issue-note-form').exists()).toBe(true);
+ });
+
+ it('calls the service to update the note', () => {
+ wrapper.find('.js-vue-issue-note-form').value = 'this is a note';
+ wrapper.find('.js-vue-issue-save').trigger('click');
+
+ expect(service.updateNote).toHaveBeenCalled();
+ });
+ });
+
+ describe('discussion note', () => {
+ beforeEach(() => {
+ Vue.http.interceptors.push(mockData.discussionNoteInterceptor);
+ jest.spyOn(service, 'updateNote');
+ wrapper = mountComponent();
+ return waitForDiscussionsRequest().then(() => {
+ wrapper.find('.js-note-edit').trigger('click');
+ });
+ });
+
+ it('renders edit form', () => {
+ expect(wrapper.find('.js-vue-issue-note-form').exists()).toBe(true);
+ });
+
+ it('updates the note and resets the edit form', () => {
+ wrapper.find('.js-vue-issue-note-form').value = 'this is a note';
+ wrapper.find('.js-vue-issue-save').trigger('click');
+
+ expect(service.updateNote).toHaveBeenCalled();
+ });
+ });
+ });
+
+ describe('new note form', () => {
+ beforeEach(() => {
+ Vue.http.interceptors.push(mockData.individualNoteInterceptor);
+ wrapper = mountComponent();
+ return waitForDiscussionsRequest();
+ });
+
+ it('should render markdown docs url', () => {
+ const { markdownDocsPath } = mockData.notesDataMock;
+
+ expect(
+ wrapper
+ .find(`a[href="${markdownDocsPath}"]`)
+ .text()
+ .trim(),
+ ).toEqual('Markdown');
+ });
+
+ it('should render quick action docs url', () => {
+ const { quickActionsDocsPath } = mockData.notesDataMock;
+
+ expect(
+ wrapper
+ .find(`a[href="${quickActionsDocsPath}"]`)
+ .text()
+ .trim(),
+ ).toEqual('quick actions');
+ });
+ });
+
+ describe('edit form', () => {
+ beforeEach(() => {
+ Vue.http.interceptors.push(mockData.individualNoteInterceptor);
+ wrapper = mountComponent();
+ return waitForDiscussionsRequest();
+ });
+
+ it('should render markdown docs url', () => {
+ wrapper.find('.js-note-edit').trigger('click');
+ const { markdownDocsPath } = mockData.notesDataMock;
+
+ return Vue.nextTick().then(() => {
+ expect(
+ wrapper
+ .find(`.edit-note a[href="${markdownDocsPath}"]`)
+ .text()
+ .trim(),
+ ).toEqual('Markdown is supported');
+ });
+ });
+
+ it('should not render quick actions docs url', () => {
+ wrapper.find('.js-note-edit').trigger('click');
+ const { quickActionsDocsPath } = mockData.notesDataMock;
+ expect(wrapper.find(`.edit-note a[href="${quickActionsDocsPath}"]`).exists()).toBe(false);
+ });
+ });
+
+ describe('emoji awards', () => {
+ beforeEach(() => {
+ Vue.http.interceptors.push(emptyResponseInterceptor);
+ wrapper = mountComponent();
+ return waitForDiscussionsRequest();
+ });
+
+ it('dispatches toggleAward after toggleAward event', () => {
+ const toggleAwardEvent = new CustomEvent('toggleAward', {
+ detail: {
+ awardName: 'test',
+ noteId: 1,
+ },
+ });
+ const toggleAwardAction = jest.fn().mockName('toggleAward');
+ wrapper.vm.$store.hotUpdate({
+ actions: {
+ toggleAward: toggleAwardAction,
+ stopPolling() {},
+ },
+ });
+
+ wrapper.vm.$parent.$el.dispatchEvent(toggleAwardEvent);
+
+ expect(toggleAwardAction).toHaveBeenCalledTimes(1);
+ const [, payload] = toggleAwardAction.mock.calls[0];
+
+ expect(payload).toEqual({
+ awardName: 'test',
+ noteId: 1,
+ });
+ });
+ });
+});
diff --git a/spec/frontend/notes/old_notes_spec.js b/spec/frontend/notes/old_notes_spec.js
new file mode 100644
index 00000000000..b57041cf4d1
--- /dev/null
+++ b/spec/frontend/notes/old_notes_spec.js
@@ -0,0 +1,1045 @@
+/* eslint-disable import/no-commonjs, no-new */
+
+import $ from 'jquery';
+import _ from 'underscore';
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import * as urlUtility from '~/lib/utils/url_utility';
+import '~/behaviors/markdown/render_gfm';
+import { createSpyObj } from 'helpers/jest_helpers';
+import { setTestTimeoutOnce } from 'helpers/timeout';
+import { TEST_HOST } from 'helpers/test_constants';
+
+// These must be imported synchronously because they pull dependencies
+// from the DOM.
+window.jQuery = $;
+require('autosize');
+require('~/commons');
+require('~/notes');
+
+const { Notes } = window;
+const FLASH_TYPE_ALERT = 'alert';
+const NOTES_POST_PATH = /(.*)\/notes\?html=true$/;
+const fixture = 'snippets/show.html';
+let mockAxios;
+
+window.project_uploads_path = `${TEST_HOST}/uploads`;
+window.gon = window.gon || {};
+window.gl = window.gl || {};
+gl.utils = gl.utils || {};
+gl.utils.disableButtonIfEmptyField = () => {};
+
+describe('Old Notes (~/notes.js)', () => {
+ beforeEach(() => {
+ jest.useFakeTimers();
+ loadFixtures(fixture);
+
+ // Re-declare this here so that test_setup.js#beforeEach() doesn't
+ // overwrite it.
+ mockAxios = new MockAdapter(axios);
+
+ $.ajax = () => {
+ throw new Error('$.ajax should not be called through!');
+ };
+
+ // These jQuery+DOM tests are super flaky so increase the timeout to avoid
+ // random failures.
+ // It seems that running tests in parallel increases failure rate.
+ jest.setTimeout(4000);
+ setTestTimeoutOnce(4000);
+ });
+
+ afterEach(done => {
+ // The Notes component sets a polling interval. Clear it after every run.
+ // Make sure to use jest.runOnlyPendingTimers() instead of runAllTimers().
+ jest.clearAllTimers();
+
+ setImmediate(() => {
+ // Wait for any requests to resolve, otherwise we get failures about
+ // unmocked requests.
+ mockAxios.restore();
+ done();
+ });
+ });
+
+ it('loads the Notes class into the DOM', () => {
+ expect(Notes).toBeDefined();
+ expect(Notes.name).toBe('Notes');
+ });
+
+ describe('addBinding', () => {
+ it('calls postComment when comment button is clicked', () => {
+ jest.spyOn(Notes.prototype, 'postComment');
+
+ new window.Notes('', []);
+ $('.js-comment-button').click();
+ expect(Notes.prototype.postComment).toHaveBeenCalled();
+ });
+ });
+
+ describe('task lists', () => {
+ beforeEach(() => {
+ mockAxios.onAny().reply(200, {});
+ new Notes('', []);
+ });
+
+ it('modifies the Markdown field', () => {
+ const changeEvent = document.createEvent('HTMLEvents');
+ changeEvent.initEvent('change', true, true);
+ $('input[type=checkbox]')
+ .attr('checked', true)[0]
+ .dispatchEvent(changeEvent);
+
+ expect($('.js-task-list-field.original-task-list').val()).toBe('- [x] Task List Item');
+ });
+
+ it('submits an ajax request on tasklist:changed', () => {
+ jest.spyOn(axios, 'patch');
+
+ const lineNumber = 8;
+ const lineSource = '- [ ] item 8';
+ const index = 3;
+ const checked = true;
+
+ $('.js-task-list-container').trigger({
+ type: 'tasklist:changed',
+ detail: { lineNumber, lineSource, index, checked },
+ });
+
+ expect(axios.patch).toHaveBeenCalledWith(undefined, {
+ note: {
+ note: '',
+ lock_version: undefined,
+ update_task: { index, checked, line_number: lineNumber, line_source: lineSource },
+ },
+ });
+ });
+ });
+
+ describe('comments', () => {
+ let notes;
+ let autosizeSpy;
+ let textarea;
+
+ beforeEach(() => {
+ notes = new Notes('', []);
+
+ textarea = $('.js-note-text');
+ textarea.data('autosave', {
+ reset: () => {},
+ });
+ autosizeSpy = jest.fn();
+ $(textarea).on('autosize:update', autosizeSpy);
+
+ jest.spyOn(notes, 'renderNote');
+
+ $('.js-comment-button').on('click', e => {
+ const $form = $(this);
+ e.preventDefault();
+ notes.addNote($form, {});
+ notes.reenableTargetFormSubmitButton(e);
+ notes.resetMainTargetForm(e);
+ });
+ });
+
+ it('autosizes after comment submission', () => {
+ textarea.text('This is an example comment note');
+ expect(autosizeSpy).not.toHaveBeenCalled();
+ $('.js-comment-button').click();
+ expect(autosizeSpy).toHaveBeenCalled();
+ });
+
+ it('should not place escaped text in the comment box in case of error', () => {
+ const deferred = $.Deferred();
+ jest.spyOn($, 'ajax').mockReturnValueOnce(deferred);
+ $(textarea).text('A comment with `markup`.');
+
+ deferred.reject();
+ $('.js-comment-button').click();
+
+ expect($(textarea).val()).toBe('A comment with `markup`.');
+
+ $.ajax.mockRestore();
+ expect($.ajax.mock).toBeUndefined();
+ });
+ });
+
+ describe('updateNote', () => {
+ let notes;
+ let noteEntity;
+ let $notesContainer;
+
+ beforeEach(() => {
+ notes = new Notes('', []);
+ window.gon.current_username = 'root';
+ window.gon.current_user_fullname = 'Administrator';
+ const sampleComment = 'foo';
+ noteEntity = {
+ id: 1234,
+ html: `<li class="note note-row-1234 timeline-entry" id="note_1234">
+ <div class="note-text">${sampleComment}</div>
+ </li>`,
+ note: sampleComment,
+ valid: true,
+ };
+
+ $notesContainer = $('ul.main-notes-list');
+ const $form = $('form.js-main-target-form');
+ $form.find('textarea.js-note-text').val(sampleComment);
+
+ mockAxios.onPost(NOTES_POST_PATH).reply(200, noteEntity);
+ });
+
+ it('updates note and resets edit form', () => {
+ jest.spyOn(notes, 'revertNoteEditForm');
+ jest.spyOn(notes, 'setupNewNote');
+
+ $('.js-comment-button').click();
+
+ const $targetNote = $notesContainer.find(`#note_${noteEntity.id}`);
+ const updatedNote = Object.assign({}, noteEntity);
+ updatedNote.note = 'bar';
+ notes.updateNote(updatedNote, $targetNote);
+
+ expect(notes.revertNoteEditForm).toHaveBeenCalledWith($targetNote);
+ expect(notes.setupNewNote).toHaveBeenCalled();
+ });
+ });
+
+ describe('updateNoteTargetSelector', () => {
+ const hash = 'note_foo';
+ let $note;
+
+ beforeEach(() => {
+ $note = $(`<div id="${hash}"></div>`);
+ jest.spyOn($note, 'filter');
+ jest.spyOn($note, 'toggleClass');
+ });
+
+ afterEach(() => {
+ expect(typeof urlUtility.getLocationHash.mock).toBe('object');
+ urlUtility.getLocationHash.mockRestore();
+ expect(urlUtility.getLocationHash.mock).toBeUndefined();
+ expect(urlUtility.getLocationHash()).toBeNull();
+ });
+
+ // urlUtility is a dependency of the notes module. Its getLocatinHash() method should be called internally.
+
+ it('sets target when hash matches', () => {
+ jest.spyOn(urlUtility, 'getLocationHash').mockReturnValueOnce(hash);
+
+ Notes.updateNoteTargetSelector($note);
+
+ expect(urlUtility.getLocationHash).toHaveBeenCalled();
+ expect($note.filter).toHaveBeenCalledWith(`#${hash}`);
+ expect($note.toggleClass).toHaveBeenCalledWith('target', true);
+ });
+
+ it('unsets target when hash does not match', () => {
+ jest.spyOn(urlUtility, 'getLocationHash').mockReturnValueOnce('note_doesnotexist');
+
+ Notes.updateNoteTargetSelector($note);
+
+ expect(urlUtility.getLocationHash).toHaveBeenCalled();
+ expect($note.toggleClass).toHaveBeenCalledWith('target', false);
+ });
+
+ it('unsets target when there is not a hash fragment anymore', () => {
+ jest.spyOn(urlUtility, 'getLocationHash').mockReturnValueOnce(null);
+
+ Notes.updateNoteTargetSelector($note);
+
+ expect(urlUtility.getLocationHash).toHaveBeenCalled();
+ expect($note.toggleClass).toHaveBeenCalledWith('target', false);
+ });
+ });
+
+ describe('renderNote', () => {
+ let notes;
+ let note;
+ let $notesList;
+
+ beforeEach(() => {
+ note = {
+ id: 1,
+ valid: true,
+ note: 'heya',
+ html: '<div>heya</div>',
+ };
+ $notesList = createSpyObj('$notesList', ['find', 'append']);
+
+ notes = createSpyObj('notes', [
+ 'setupNewNote',
+ 'refresh',
+ 'collapseLongCommitList',
+ 'updateNotesCount',
+ 'putConflictEditWarningInPlace',
+ ]);
+ notes.taskList = createSpyObj('tasklist', ['init']);
+ notes.note_ids = [];
+ notes.updatedNotesTrackingMap = {};
+
+ jest.spyOn(Notes, 'isNewNote');
+ jest.spyOn(Notes, 'isUpdatedNote');
+ jest.spyOn(Notes, 'animateAppendNote');
+ jest.spyOn(Notes, 'animateUpdateNote');
+ });
+
+ describe('when adding note', () => {
+ it('should call .animateAppendNote', () => {
+ Notes.isNewNote.mockReturnValueOnce(true);
+ Notes.prototype.renderNote.call(notes, note, null, $notesList);
+
+ expect(Notes.animateAppendNote).toHaveBeenCalledWith(note.html, $notesList);
+ });
+ });
+
+ describe('when note was edited', () => {
+ it('should call .animateUpdateNote', () => {
+ Notes.isNewNote.mockReturnValueOnce(false);
+ Notes.isUpdatedNote.mockReturnValueOnce(true);
+ const $note = $('<div>');
+ $notesList.find.mockReturnValueOnce($note);
+ const $newNote = $(note.html);
+ Notes.animateUpdateNote.mockReturnValueOnce($newNote);
+
+ Notes.prototype.renderNote.call(notes, note, null, $notesList);
+
+ expect(Notes.animateUpdateNote).toHaveBeenCalledWith(note.html, $note);
+ expect(notes.setupNewNote).toHaveBeenCalledWith($newNote);
+ });
+
+ describe('while editing', () => {
+ it('should update textarea if nothing has been touched', () => {
+ Notes.isNewNote.mockReturnValueOnce(false);
+ Notes.isUpdatedNote.mockReturnValueOnce(true);
+ const $note = $(`<div class="is-editing">
+ <div class="original-note-content">initial</div>
+ <textarea class="js-note-text">initial</textarea>
+ </div>`);
+ $notesList.find.mockReturnValueOnce($note);
+ Notes.prototype.renderNote.call(notes, note, null, $notesList);
+
+ expect($note.find('.js-note-text').val()).toEqual(note.note);
+ });
+
+ it('should call .putConflictEditWarningInPlace', () => {
+ Notes.isNewNote.mockReturnValueOnce(false);
+ Notes.isUpdatedNote.mockReturnValueOnce(true);
+ const $note = $(`<div class="is-editing">
+ <div class="original-note-content">initial</div>
+ <textarea class="js-note-text">different</textarea>
+ </div>`);
+ $notesList.find.mockReturnValueOnce($note);
+ Notes.prototype.renderNote.call(notes, note, null, $notesList);
+
+ expect(notes.putConflictEditWarningInPlace).toHaveBeenCalledWith(note, $note);
+ });
+ });
+ });
+ });
+
+ describe('isUpdatedNote', () => {
+ it('should consider same note text as the same', () => {
+ const result = Notes.isUpdatedNote(
+ {
+ note: 'initial',
+ },
+ $(`<div>
+ <div class="original-note-content">initial</div>
+ </div>`),
+ );
+
+ expect(result).toEqual(false);
+ });
+
+ it('should consider same note with trailing newline as the same', () => {
+ const result = Notes.isUpdatedNote(
+ {
+ note: 'initial\n',
+ },
+ $(`<div>
+ <div class="original-note-content">initial\n</div>
+ </div>`),
+ );
+
+ expect(result).toEqual(false);
+ });
+
+ it('should consider different notes as different', () => {
+ const result = Notes.isUpdatedNote(
+ {
+ note: 'foo',
+ },
+ $(`<div>
+ <div class="original-note-content">bar</div>
+ </div>`),
+ );
+
+ expect(result).toEqual(true);
+ });
+ });
+
+ describe('renderDiscussionNote', () => {
+ let discussionContainer;
+ let note;
+ let notes;
+ let $form;
+ let row;
+
+ beforeEach(() => {
+ note = {
+ html: '<li></li>',
+ discussion_html: '<div></div>',
+ discussion_id: 1,
+ discussion_resolvable: false,
+ diff_discussion_html: false,
+ };
+ $form = createSpyObj('$form', ['closest', 'find']);
+ $form.length = 1;
+ row = createSpyObj('row', ['prevAll', 'first', 'find']);
+
+ notes = createSpyObj('notes', ['isParallelView', 'updateNotesCount']);
+ notes.note_ids = [];
+
+ jest.spyOn(Notes, 'isNewNote');
+ jest.spyOn(Notes, 'animateAppendNote').mockImplementation();
+ Notes.isNewNote.mockReturnValue(true);
+ notes.isParallelView.mockReturnValue(false);
+ row.prevAll.mockReturnValue(row);
+ row.first.mockReturnValue(row);
+ row.find.mockReturnValue(row);
+ });
+
+ describe('Discussion root note', () => {
+ let body;
+
+ beforeEach(() => {
+ body = createSpyObj('body', ['attr']);
+ discussionContainer = { length: 0 };
+
+ $form.closest.mockReturnValueOnce(row).mockReturnValue($form);
+ $form.find.mockReturnValue(discussionContainer);
+ body.attr.mockReturnValue('');
+ });
+
+ it('should call Notes.animateAppendNote', () => {
+ Notes.prototype.renderDiscussionNote.call(notes, note, $form);
+
+ expect(Notes.animateAppendNote).toHaveBeenCalledWith(
+ note.discussion_html,
+ $('.main-notes-list'),
+ );
+ });
+
+ it('should append to row selected with line_code', () => {
+ $form.length = 0;
+ note.discussion_line_code = 'line_code';
+ note.diff_discussion_html = '<tr></tr>';
+
+ const line = document.createElement('div');
+ line.id = note.discussion_line_code;
+ document.body.appendChild(line);
+
+ // Override mocks for this single test
+ $form.closest.mockReset();
+ $form.closest.mockReturnValue($form);
+
+ Notes.prototype.renderDiscussionNote.call(notes, note, $form);
+
+ expect(line.nextSibling.outerHTML).toEqual(note.diff_discussion_html);
+ });
+ });
+
+ describe('Discussion sub note', () => {
+ beforeEach(() => {
+ discussionContainer = { length: 1 };
+
+ $form.closest.mockReturnValueOnce(row).mockReturnValueOnce($form);
+ $form.find.mockReturnValue(discussionContainer);
+
+ Notes.prototype.renderDiscussionNote.call(notes, note, $form);
+ });
+
+ it('should call Notes.animateAppendNote', () => {
+ expect(Notes.animateAppendNote).toHaveBeenCalledWith(note.html, discussionContainer);
+ });
+ });
+ });
+
+ describe('animateAppendNote', () => {
+ let noteHTML;
+ let $notesList;
+ let $resultantNote;
+
+ beforeEach(() => {
+ noteHTML = '<div></div>';
+ $notesList = createSpyObj('$notesList', ['append']);
+
+ $resultantNote = Notes.animateAppendNote(noteHTML, $notesList);
+ });
+
+ it('should have `fade-in-full` class', () => {
+ expect($resultantNote.hasClass('fade-in-full')).toEqual(true);
+ });
+
+ it('should append note to the notes list', () => {
+ expect($notesList.append).toHaveBeenCalledWith($resultantNote);
+ });
+ });
+
+ describe('animateUpdateNote', () => {
+ let noteHTML;
+ let $note;
+ let $updatedNote;
+
+ beforeEach(() => {
+ noteHTML = '<div></div>';
+ $note = createSpyObj('$note', ['replaceWith']);
+
+ $updatedNote = Notes.animateUpdateNote(noteHTML, $note);
+ });
+
+ it('should have `fade-in` class', () => {
+ expect($updatedNote.hasClass('fade-in')).toEqual(true);
+ });
+
+ it('should call replaceWith on $note', () => {
+ expect($note.replaceWith).toHaveBeenCalledWith($updatedNote);
+ });
+ });
+
+ describe('putEditFormInPlace', () => {
+ it('should call GLForm with GFM parameter passed through', () => {
+ const notes = new Notes('', []);
+ const $el = $(`
+ <div>
+ <form></form>
+ </div>
+ `);
+
+ notes.putEditFormInPlace($el);
+
+ expect(notes.glForm.enableGFM).toBeTruthy();
+ });
+ });
+
+ describe('postComment & updateComment', () => {
+ const sampleComment = 'foo';
+ const note = {
+ id: 1234,
+ html: `<li class="note note-row-1234 timeline-entry" id="note_1234">
+ <div class="note-text">${sampleComment}</div>
+ </li>`,
+ note: sampleComment,
+ valid: true,
+ };
+ let notes;
+ let $form;
+ let $notesContainer;
+
+ function mockNotesPost() {
+ mockAxios.onPost(NOTES_POST_PATH).reply(200, note);
+ }
+
+ function mockNotesPostError() {
+ mockAxios.onPost(NOTES_POST_PATH).networkError();
+ }
+
+ beforeEach(() => {
+ notes = new Notes('', []);
+ window.gon.current_username = 'root';
+ window.gon.current_user_fullname = 'Administrator';
+ $form = $('form.js-main-target-form');
+ $notesContainer = $('ul.main-notes-list');
+ $form.find('textarea.js-note-text').val(sampleComment);
+ });
+
+ it('should show placeholder note while new comment is being posted', () => {
+ mockNotesPost();
+
+ $('.js-comment-button').click();
+
+ expect($notesContainer.find('.note.being-posted').length).toBeGreaterThan(0);
+ });
+
+ it('should remove placeholder note when new comment is done posting', done => {
+ mockNotesPost();
+
+ $('.js-comment-button').click();
+
+ setImmediate(() => {
+ expect($notesContainer.find('.note.being-posted').length).toEqual(0);
+ done();
+ });
+ });
+
+ describe('postComment', () => {
+ it('disables the submit button', done => {
+ const $submitButton = $form.find('.js-comment-submit-button');
+
+ expect($submitButton).not.toBeDisabled();
+ const dummyEvent = {
+ preventDefault() {},
+ target: $submitButton,
+ };
+ mockAxios.onPost(NOTES_POST_PATH).replyOnce(() => {
+ expect($submitButton).toBeDisabled();
+ return [200, note];
+ });
+
+ notes
+ .postComment(dummyEvent)
+ .then(() => {
+ expect($submitButton).not.toBeDisabled();
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ it('should show actual note element when new comment is done posting', done => {
+ mockNotesPost();
+
+ $('.js-comment-button').click();
+
+ setImmediate(() => {
+ expect($notesContainer.find(`#note_${note.id}`).length).toBeGreaterThan(0);
+ done();
+ });
+ });
+
+ it('should reset Form when new comment is done posting', done => {
+ mockNotesPost();
+
+ $('.js-comment-button').click();
+
+ setImmediate(() => {
+ expect($form.find('textarea.js-note-text').val()).toEqual('');
+ done();
+ });
+ });
+
+ it('should show flash error message when new comment failed to be posted', done => {
+ mockNotesPostError();
+ jest.spyOn(notes, 'addFlash');
+
+ $('.js-comment-button').click();
+
+ setImmediate(() => {
+ expect(notes.addFlash).toHaveBeenCalled();
+ // JSDom doesn't support the :visible selector yet
+ expect(notes.flashContainer.style.display).not.toBe('none');
+ done();
+ });
+ });
+
+ // This is a bad test carried over from the Karma -> Jest migration.
+ // The corresponding test in the Karma suite tests for
+ // elements and methods that don't actually exist, and gives a false
+ // positive pass.
+ /*
+ it('should show flash error message when comment failed to be updated', done => {
+ mockNotesPost();
+ jest.spyOn(notes, 'addFlash').mockName('addFlash');
+
+ $('.js-comment-button').click();
+
+ deferredPromise()
+ .then(() => {
+ const $noteEl = $notesContainer.find(`#note_${note.id}`);
+ $noteEl.find('.js-note-edit').click();
+ $noteEl.find('textarea.js-note-text').val(updatedComment);
+
+ mockNotesPostError();
+
+ $noteEl.find('.js-comment-save-button').click();
+ notes.updateComment({preventDefault: () => {}});
+ })
+ .then(() => deferredPromise())
+ .then(() => {
+ const $updatedNoteEl = $notesContainer.find(`#note_${note.id}`);
+
+ expect($updatedNoteEl.hasClass('.being-posted')).toEqual(false); // Remove being-posted visuals
+ expect(
+ $updatedNoteEl
+ .find('.note-text')
+ .text()
+ .trim(),
+ ).toEqual(sampleComment); // See if comment reverted back to original
+
+ expect(notes.addFlash).toHaveBeenCalled();
+ expect(notes.flashContainer.style.display).not.toBe('none');
+ done();
+ })
+ .catch(done.fail);
+ }, 5000);
+ */
+ });
+
+ describe('postComment with Slash commands', () => {
+ const sampleComment = '/assign @root\n/award :100:';
+ const note = {
+ commands_changes: {
+ assignee_id: 1,
+ emoji_award: '100',
+ },
+ errors: {
+ commands_only: ['Commands applied'],
+ },
+ valid: false,
+ };
+ let $form;
+ let $notesContainer;
+
+ beforeEach(() => {
+ mockAxios.onPost(NOTES_POST_PATH).reply(200, note);
+
+ new Notes('', []);
+ window.gon.current_username = 'root';
+ window.gon.current_user_fullname = 'Administrator';
+ gl.awardsHandler = {
+ addAwardToEmojiBar: () => {},
+ scrollToAwards: () => {},
+ };
+ gl.GfmAutoComplete = {
+ dataSources: {
+ commands: '/root/test-project/autocomplete_sources/commands',
+ },
+ };
+ $form = $('form.js-main-target-form');
+ $notesContainer = $('ul.main-notes-list');
+ $form.find('textarea.js-note-text').val(sampleComment);
+ });
+
+ it('should remove slash command placeholder when comment with slash commands is done posting', done => {
+ jest.spyOn(gl.awardsHandler, 'addAwardToEmojiBar');
+ $('.js-comment-button').click();
+
+ expect($notesContainer.find('.system-note.being-posted').length).toEqual(1); // Placeholder shown
+
+ setImmediate(() => {
+ expect($notesContainer.find('.system-note.being-posted').length).toEqual(0); // Placeholder removed
+ done();
+ });
+ });
+ });
+
+ describe('update comment with script tags', () => {
+ const sampleComment = '<script></script>';
+ const updatedComment = '<script></script>';
+ const note = {
+ id: 1234,
+ html: `<li class="note note-row-1234 timeline-entry" id="note_1234">
+ <div class="note-text">${sampleComment}</div>
+ </li>`,
+ note: sampleComment,
+ valid: true,
+ };
+ let $form;
+ let $notesContainer;
+
+ beforeEach(() => {
+ mockAxios.onPost(NOTES_POST_PATH).reply(200, note);
+
+ new Notes('', []);
+ window.gon.current_username = 'root';
+ window.gon.current_user_fullname = 'Administrator';
+ $form = $('form.js-main-target-form');
+ $notesContainer = $('ul.main-notes-list');
+ $form.find('textarea.js-note-text').html(sampleComment);
+ });
+
+ it('should not render a script tag', done => {
+ $('.js-comment-button').click();
+
+ setImmediate(() => {
+ const $noteEl = $notesContainer.find(`#note_${note.id}`);
+ $noteEl.find('.js-note-edit').click();
+ $noteEl.find('textarea.js-note-text').html(updatedComment);
+ $noteEl.find('.js-comment-save-button').click();
+
+ const $updatedNoteEl = $notesContainer
+ .find(`#note_${note.id}`)
+ .find('.js-task-list-container');
+
+ expect(
+ $updatedNoteEl
+ .find('.note-text')
+ .text()
+ .trim(),
+ ).toEqual('');
+
+ done();
+ });
+ });
+ });
+
+ describe('getFormData', () => {
+ let $form;
+ let sampleComment;
+ let notes;
+
+ beforeEach(() => {
+ notes = new Notes('', []);
+
+ $form = $('form');
+ sampleComment = 'foobar';
+ });
+
+ it('should return form metadata object from form reference', () => {
+ $form.find('textarea.js-note-text').val(sampleComment);
+ const { formData, formContent, formAction } = notes.getFormData($form);
+
+ expect(formData.indexOf(sampleComment)).toBeGreaterThan(-1);
+ expect(formContent).toEqual(sampleComment);
+ expect(formAction).toEqual($form.attr('action'));
+ });
+
+ it('should return form metadata with sanitized formContent from form reference', () => {
+ jest.spyOn(_, 'escape');
+
+ sampleComment = '<script>alert("Boom!");</script>';
+ $form.find('textarea.js-note-text').val(sampleComment);
+
+ const { formContent } = notes.getFormData($form);
+
+ expect(_.escape).toHaveBeenCalledWith(sampleComment);
+ expect(formContent).toEqual('&lt;script&gt;alert(&quot;Boom!&quot;);&lt;/script&gt;');
+ });
+ });
+
+ describe('hasQuickActions', () => {
+ let notes;
+
+ beforeEach(() => {
+ notes = new Notes('', []);
+ });
+
+ it('should return true when comment begins with a quick action', () => {
+ const sampleComment = '/wip\n/milestone %1.0\n/merge\n/unassign Merging this';
+ const hasQuickActions = notes.hasQuickActions(sampleComment);
+
+ expect(hasQuickActions).toBeTruthy();
+ });
+
+ it('should return false when comment does NOT begin with a quick action', () => {
+ const sampleComment = 'Hey, /unassign Merging this';
+ const hasQuickActions = notes.hasQuickActions(sampleComment);
+
+ expect(hasQuickActions).toBeFalsy();
+ });
+
+ it('should return false when comment does NOT have any quick actions', () => {
+ const sampleComment = 'Looking good, Awesome!';
+ const hasQuickActions = notes.hasQuickActions(sampleComment);
+
+ expect(hasQuickActions).toBeFalsy();
+ });
+ });
+
+ describe('stripQuickActions', () => {
+ it('should strip quick actions from the comment which begins with a quick action', () => {
+ const notes = new Notes();
+ const sampleComment = '/wip\n/milestone %1.0\n/merge\n/unassign Merging this';
+ const stripedComment = notes.stripQuickActions(sampleComment);
+
+ expect(stripedComment).toBe('');
+ });
+
+ it('should strip quick actions from the comment but leaves plain comment if it is present', () => {
+ const notes = new Notes();
+ const sampleComment = '/wip\n/milestone %1.0\n/merge\n/unassign\nMerging this';
+ const stripedComment = notes.stripQuickActions(sampleComment);
+
+ expect(stripedComment).toBe('Merging this');
+ });
+
+ it('should NOT strip string that has slashes within', () => {
+ const notes = new Notes();
+ const sampleComment = 'http://127.0.0.1:3000/root/gitlab-shell/issues/1';
+ const stripedComment = notes.stripQuickActions(sampleComment);
+
+ expect(stripedComment).toBe(sampleComment);
+ });
+ });
+
+ describe('getQuickActionDescription', () => {
+ const availableQuickActions = [
+ { name: 'close', description: 'Close this issue', params: [] },
+ { name: 'title', description: 'Change title', params: [{}] },
+ { name: 'estimate', description: 'Set time estimate', params: [{}] },
+ ];
+ let notes;
+
+ beforeEach(() => {
+ notes = new Notes();
+ });
+
+ it('should return executing quick action description when note has single quick action', () => {
+ const sampleComment = '/close';
+
+ expect(notes.getQuickActionDescription(sampleComment, availableQuickActions)).toBe(
+ 'Applying command to close this issue',
+ );
+ });
+
+ it('should return generic multiple quick action description when note has multiple quick actions', () => {
+ const sampleComment = '/close\n/title [Duplicate] Issue foobar';
+
+ expect(notes.getQuickActionDescription(sampleComment, availableQuickActions)).toBe(
+ 'Applying multiple commands',
+ );
+ });
+
+ it('should return generic quick action description when available quick actions list is not populated', () => {
+ const sampleComment = '/close\n/title [Duplicate] Issue foobar';
+
+ expect(notes.getQuickActionDescription(sampleComment)).toBe('Applying command');
+ });
+ });
+
+ describe('createPlaceholderNote', () => {
+ const sampleComment = 'foobar';
+ const uniqueId = 'b1234-a4567';
+ const currentUsername = 'root';
+ const currentUserFullname = 'Administrator';
+ const currentUserAvatar = 'avatar_url';
+ let notes;
+
+ beforeEach(() => {
+ notes = new Notes('', []);
+ });
+
+ it('should return constructed placeholder element for regular note based on form contents', () => {
+ const $tempNote = notes.createPlaceholderNote({
+ formContent: sampleComment,
+ uniqueId,
+ isDiscussionNote: false,
+ currentUsername,
+ currentUserFullname,
+ currentUserAvatar,
+ });
+ const $tempNoteHeader = $tempNote.find('.note-header');
+
+ expect($tempNote.prop('nodeName')).toEqual('LI');
+ expect($tempNote.attr('id')).toEqual(uniqueId);
+ expect($tempNote.hasClass('being-posted')).toBeTruthy();
+ expect($tempNote.hasClass('fade-in-half')).toBeTruthy();
+ $tempNote.find('.timeline-icon > a, .note-header-info > a').each((i, el) => {
+ expect(el.getAttribute('href')).toEqual(`/${currentUsername}`);
+ });
+
+ expect($tempNote.find('.timeline-icon .avatar').attr('src')).toEqual(currentUserAvatar);
+ expect($tempNote.find('.timeline-content').hasClass('discussion')).toBeFalsy();
+ expect(
+ $tempNoteHeader
+ .find('.d-none.d-sm-inline-block')
+ .text()
+ .trim(),
+ ).toEqual(currentUserFullname);
+
+ expect(
+ $tempNoteHeader
+ .find('.note-headline-light')
+ .text()
+ .trim(),
+ ).toEqual(`@${currentUsername}`);
+
+ expect(
+ $tempNote
+ .find('.note-body .note-text p')
+ .text()
+ .trim(),
+ ).toEqual(sampleComment);
+ });
+
+ it('should return constructed placeholder element for discussion note based on form contents', () => {
+ const $tempNote = notes.createPlaceholderNote({
+ formContent: sampleComment,
+ uniqueId,
+ isDiscussionNote: true,
+ currentUsername,
+ currentUserFullname,
+ });
+
+ expect($tempNote.prop('nodeName')).toEqual('LI');
+ expect($tempNote.find('.timeline-content').hasClass('discussion')).toBeTruthy();
+ });
+
+ it('should return a escaped user name', () => {
+ const currentUserFullnameXSS = 'Foo <script>alert("XSS")</script>';
+ const $tempNote = notes.createPlaceholderNote({
+ formContent: sampleComment,
+ uniqueId,
+ isDiscussionNote: false,
+ currentUsername,
+ currentUserFullname: currentUserFullnameXSS,
+ currentUserAvatar,
+ });
+ const $tempNoteHeader = $tempNote.find('.note-header');
+
+ expect(
+ $tempNoteHeader
+ .find('.d-none.d-sm-inline-block')
+ .text()
+ .trim(),
+ ).toEqual('Foo &lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;');
+ });
+ });
+
+ describe('createPlaceholderSystemNote', () => {
+ const sampleCommandDescription = 'Applying command to close this issue';
+ const uniqueId = 'b1234-a4567';
+ let notes;
+
+ beforeEach(() => {
+ notes = new Notes('', []);
+ jest.spyOn(_, 'escape');
+ });
+
+ it('should return constructed placeholder element for system note based on form contents', () => {
+ const $tempNote = notes.createPlaceholderSystemNote({
+ formContent: sampleCommandDescription,
+ uniqueId,
+ });
+
+ expect($tempNote.prop('nodeName')).toEqual('LI');
+ expect($tempNote.attr('id')).toEqual(uniqueId);
+ expect($tempNote.hasClass('being-posted')).toBeTruthy();
+ expect($tempNote.hasClass('fade-in-half')).toBeTruthy();
+ expect(
+ $tempNote
+ .find('.timeline-content i')
+ .text()
+ .trim(),
+ ).toEqual(sampleCommandDescription);
+ });
+ });
+
+ describe('appendFlash', () => {
+ it('shows a flash message', () => {
+ const notes = new Notes('', []);
+ notes.addFlash('Error message', FLASH_TYPE_ALERT, notes.parentTimeline.get(0));
+
+ const flash = $('.flash-alert')[0];
+ expect(document.contains(flash)).toBe(true);
+ expect(flash.parentNode.style.display).toBe('block');
+ });
+ });
+
+ describe('clearFlash', () => {
+ beforeEach(() => {
+ $(document).off('ajax:success');
+ });
+
+ it('hides visible flash message', () => {
+ const notes = new Notes('', []);
+ notes.addFlash('Error message 1', FLASH_TYPE_ALERT, notes.parentTimeline.get(0));
+ const flash = $('.flash-alert')[0];
+ notes.clearFlash();
+ expect(flash.parentNode.style.display).toBe('none');
+ expect(notes.flashContainer).toBeNull();
+ });
+ });
+});
diff --git a/spec/frontend/notes/stores/utils_spec.js b/spec/frontend/notes/stores/utils_spec.js
new file mode 100644
index 00000000000..b31b7491334
--- /dev/null
+++ b/spec/frontend/notes/stores/utils_spec.js
@@ -0,0 +1,17 @@
+import { hasQuickActions } from '~/notes/stores/utils';
+
+describe('hasQuickActions', () => {
+ it.each`
+ input | expected
+ ${'some comment'} | ${false}
+ ${'/quickaction'} | ${true}
+ ${'some comment with\n/quickaction'} | ${true}
+ `('returns $expected for $input', ({ input, expected }) => {
+ expect(hasQuickActions(input)).toBe(expected);
+ });
+
+ it('is stateless', () => {
+ expect(hasQuickActions('some comment')).toBe(hasQuickActions('some comment'));
+ expect(hasQuickActions('/quickaction')).toBe(hasQuickActions('/quickaction'));
+ });
+});
diff --git a/spec/frontend/operation_settings/components/external_dashboard_spec.js b/spec/frontend/operation_settings/components/external_dashboard_spec.js
new file mode 100644
index 00000000000..a881de8fbfe
--- /dev/null
+++ b/spec/frontend/operation_settings/components/external_dashboard_spec.js
@@ -0,0 +1,166 @@
+import { mount, shallowMount, createLocalVue } from '@vue/test-utils';
+import { GlButton, GlLink, GlFormGroup, GlFormInput } from '@gitlab/ui';
+import ExternalDashboard from '~/operation_settings/components/external_dashboard.vue';
+import store from '~/operation_settings/store';
+import axios from '~/lib/utils/axios_utils';
+import { refreshCurrentPage } from '~/lib/utils/url_utility';
+import createFlash from '~/flash';
+import { TEST_HOST } from 'helpers/test_constants';
+
+jest.mock('~/lib/utils/axios_utils');
+jest.mock('~/lib/utils/url_utility');
+jest.mock('~/flash');
+
+describe('operation settings external dashboard component', () => {
+ let wrapper;
+ const operationsSettingsEndpoint = `${TEST_HOST}/mock/ops/settings/endpoint`;
+ const externalDashboardUrl = `http://mock-external-domain.com/external/dashboard/url`;
+ const externalDashboardHelpPagePath = `${TEST_HOST}/help/page/path`;
+ const localVue = createLocalVue();
+ const mountComponent = (shallow = true) => {
+ const config = [
+ ExternalDashboard,
+ {
+ localVue,
+ store: store({
+ operationsSettingsEndpoint,
+ externalDashboardUrl,
+ externalDashboardHelpPagePath,
+ }),
+ },
+ ];
+ wrapper = shallow ? shallowMount(...config) : mount(...config);
+ };
+
+ afterEach(() => {
+ if (wrapper.destroy) {
+ wrapper.destroy();
+ }
+ axios.patch.mockReset();
+ refreshCurrentPage.mockReset();
+ createFlash.mockReset();
+ });
+
+ it('renders header text', () => {
+ mountComponent();
+ expect(wrapper.find('.js-section-header').text()).toBe('External Dashboard');
+ });
+
+ describe('expand/collapse button', () => {
+ it('renders as an expand button by default', () => {
+ const button = wrapper.find(GlButton);
+
+ expect(button.text()).toBe('Expand');
+ });
+ });
+
+ describe('sub-header', () => {
+ let subHeader;
+
+ beforeEach(() => {
+ mountComponent();
+ subHeader = wrapper.find('.js-section-sub-header');
+ });
+
+ it('renders descriptive text', () => {
+ expect(subHeader.text()).toContain(
+ 'Add a button to the metrics dashboard linking directly to your existing external dashboards.',
+ );
+ });
+
+ it('renders help page link', () => {
+ const link = subHeader.find(GlLink);
+
+ expect(link.text()).toBe('Learn more');
+ expect(link.attributes().href).toBe(externalDashboardHelpPagePath);
+ });
+ });
+
+ describe('form', () => {
+ describe('input label', () => {
+ let formGroup;
+
+ beforeEach(() => {
+ mountComponent();
+ formGroup = wrapper.find(GlFormGroup);
+ });
+
+ it('uses label text', () => {
+ expect(formGroup.attributes().label).toBe('Full dashboard URL');
+ });
+
+ it('uses description text', () => {
+ expect(formGroup.attributes().description).toBe(
+ 'Enter the URL of the dashboard you want to link to',
+ );
+ });
+ });
+
+ describe('input field', () => {
+ let input;
+
+ beforeEach(() => {
+ mountComponent();
+ input = wrapper.find(GlFormInput);
+ });
+
+ it('defaults to externalDashboardUrl', () => {
+ expect(input.attributes().value).toBe(externalDashboardUrl);
+ });
+
+ it('uses a placeholder', () => {
+ expect(input.attributes().placeholder).toBe('https://my-org.gitlab.io/my-dashboards');
+ });
+ });
+
+ describe('submit button', () => {
+ const findSubmitButton = () => wrapper.find('.settings-content form').find(GlButton);
+
+ const endpointRequest = [
+ operationsSettingsEndpoint,
+ {
+ project: {
+ metrics_setting_attributes: {
+ external_dashboard_url: externalDashboardUrl,
+ },
+ },
+ },
+ ];
+
+ it('renders button label', () => {
+ mountComponent();
+ const submit = findSubmitButton();
+ expect(submit.text()).toBe('Save Changes');
+ });
+
+ it('submits form on click', () => {
+ mountComponent(false);
+ axios.patch.mockResolvedValue();
+ findSubmitButton().trigger('click');
+
+ expect(axios.patch).toHaveBeenCalledWith(...endpointRequest);
+
+ return wrapper.vm.$nextTick().then(() => expect(refreshCurrentPage).toHaveBeenCalled());
+ });
+
+ it('creates flash banner on error', () => {
+ mountComponent(false);
+ const message = 'mockErrorMessage';
+ axios.patch.mockRejectedValue({ response: { data: { message } } });
+ findSubmitButton().trigger('click');
+
+ expect(axios.patch).toHaveBeenCalledWith(...endpointRequest);
+
+ return wrapper.vm
+ .$nextTick()
+ .then(jest.runAllTicks)
+ .then(() =>
+ expect(createFlash).toHaveBeenCalledWith(
+ `There was an error saving your changes. ${message}`,
+ 'alert',
+ ),
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/operation_settings/store/mutations_spec.js b/spec/frontend/operation_settings/store/mutations_spec.js
new file mode 100644
index 00000000000..1854142c89a
--- /dev/null
+++ b/spec/frontend/operation_settings/store/mutations_spec.js
@@ -0,0 +1,19 @@
+import mutations from '~/operation_settings/store/mutations';
+import createState from '~/operation_settings/store/state';
+
+describe('operation settings mutations', () => {
+ let localState;
+
+ beforeEach(() => {
+ localState = createState();
+ });
+
+ describe('SET_EXTERNAL_DASHBOARD_URL', () => {
+ it('sets externalDashboardUrl', () => {
+ const mockUrl = 'mockUrl';
+ mutations.SET_EXTERNAL_DASHBOARD_URL(localState, mockUrl);
+
+ expect(localState.externalDashboardUrl).toBe(mockUrl);
+ });
+ });
+});
diff --git a/spec/frontend/reports/components/report_item_spec.js b/spec/frontend/reports/components/report_item_spec.js
new file mode 100644
index 00000000000..bacbb399513
--- /dev/null
+++ b/spec/frontend/reports/components/report_item_spec.js
@@ -0,0 +1,33 @@
+import { shallowMount } from '@vue/test-utils';
+import { STATUS_SUCCESS } from '~/reports/constants';
+import ReportItem from '~/reports/components/report_item.vue';
+import { componentNames } from '~/reports/components/issue_body';
+
+describe('ReportItem', () => {
+ describe('showReportSectionStatusIcon', () => {
+ it('does not render CI Status Icon when showReportSectionStatusIcon is false', () => {
+ const wrapper = shallowMount(ReportItem, {
+ propsData: {
+ issue: { foo: 'bar' },
+ component: componentNames.TestIssueBody,
+ status: STATUS_SUCCESS,
+ showReportSectionStatusIcon: false,
+ },
+ });
+
+ expect(wrapper.find('issuestatusicon-stub').exists()).toBe(false);
+ });
+
+ it('shows status icon when unspecified', () => {
+ const wrapper = shallowMount(ReportItem, {
+ propsData: {
+ issue: { foo: 'bar' },
+ component: componentNames.TestIssueBody,
+ status: STATUS_SUCCESS,
+ },
+ });
+
+ expect(wrapper.find('issuestatusicon-stub').exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/reports/components/report_section_spec.js b/spec/frontend/reports/components/report_section_spec.js
index 3b609484b9e..d4a3073374a 100644
--- a/spec/frontend/reports/components/report_section_spec.js
+++ b/spec/frontend/reports/components/report_section_spec.js
@@ -197,4 +197,44 @@ describe('Report section', () => {
expect(vm.$el.querySelector('.js-collapse-btn').textContent.trim()).toEqual('Expand');
});
});
+
+ describe('Success and Error slots', () => {
+ const createComponent = status => {
+ vm = mountComponentWithSlots(ReportSection, {
+ props: {
+ status,
+ hasIssues: true,
+ },
+ slots: {
+ success: ['This is a success'],
+ loading: ['This is loading'],
+ error: ['This is an error'],
+ },
+ });
+ };
+
+ it('only renders success slot when status is "SUCCESS"', () => {
+ createComponent('SUCCESS');
+
+ expect(vm.$el.textContent.trim()).toContain('This is a success');
+ expect(vm.$el.textContent.trim()).not.toContain('This is an error');
+ expect(vm.$el.textContent.trim()).not.toContain('This is loading');
+ });
+
+ it('only renders error slot when status is "ERROR"', () => {
+ createComponent('ERROR');
+
+ expect(vm.$el.textContent.trim()).toContain('This is an error');
+ expect(vm.$el.textContent.trim()).not.toContain('This is a success');
+ expect(vm.$el.textContent.trim()).not.toContain('This is loading');
+ });
+
+ it('only renders loading slot when status is "LOADING"', () => {
+ createComponent('LOADING');
+
+ expect(vm.$el.textContent.trim()).toContain('This is loading');
+ expect(vm.$el.textContent.trim()).not.toContain('This is an error');
+ expect(vm.$el.textContent.trim()).not.toContain('This is a success');
+ });
+ });
});
diff --git a/spec/frontend/repository/components/breadcrumbs_spec.js b/spec/frontend/repository/components/breadcrumbs_spec.js
new file mode 100644
index 00000000000..068fa317a87
--- /dev/null
+++ b/spec/frontend/repository/components/breadcrumbs_spec.js
@@ -0,0 +1,44 @@
+import { shallowMount, RouterLinkStub } from '@vue/test-utils';
+import Breadcrumbs from '~/repository/components/breadcrumbs.vue';
+
+let vm;
+
+function factory(currentPath) {
+ vm = shallowMount(Breadcrumbs, {
+ propsData: {
+ currentPath,
+ },
+ stubs: {
+ RouterLink: RouterLinkStub,
+ },
+ });
+}
+
+describe('Repository breadcrumbs component', () => {
+ afterEach(() => {
+ vm.destroy();
+ });
+
+ it.each`
+ path | linkCount
+ ${'/'} | ${1}
+ ${'app'} | ${2}
+ ${'app/assets'} | ${3}
+ ${'app/assets/javascripts'} | ${4}
+ `('renders $linkCount links for path $path', ({ path, linkCount }) => {
+ factory(path);
+
+ expect(vm.findAll(RouterLinkStub).length).toEqual(linkCount);
+ });
+
+ it('renders last link as active', () => {
+ factory('app/assets');
+
+ expect(
+ vm
+ .findAll(RouterLinkStub)
+ .at(2)
+ .attributes('aria-current'),
+ ).toEqual('page');
+ });
+});
diff --git a/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap b/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap
new file mode 100644
index 00000000000..1f06d693411
--- /dev/null
+++ b/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap
@@ -0,0 +1,38 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Repository table row component renders table row 1`] = `
+<tr
+ class="tree-item file_1"
+>
+ <td
+ class="tree-item-file-name"
+ >
+ <i
+ aria-label="file"
+ class="fa fa-fw fa-file-text-o"
+ role="img"
+ />
+
+ <a
+ class="str-truncated"
+ href="https://test.com"
+ >
+
+ test
+
+ </a>
+
+ <!---->
+
+ <!---->
+ </td>
+
+ <td
+ class="d-none d-sm-table-cell tree-commit"
+ />
+
+ <td
+ class="tree-time-ago text-right"
+ />
+</tr>
+`;
diff --git a/spec/frontend/repository/components/table/index_spec.js b/spec/frontend/repository/components/table/index_spec.js
new file mode 100644
index 00000000000..827927e6d9a
--- /dev/null
+++ b/spec/frontend/repository/components/table/index_spec.js
@@ -0,0 +1,80 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlLoadingIcon } from '@gitlab/ui';
+import Table from '~/repository/components/table/index.vue';
+
+let vm;
+let $apollo;
+
+function factory(path, data = () => ({})) {
+ $apollo = {
+ query: jest.fn().mockReturnValue(Promise.resolve({ data: data() })),
+ };
+
+ vm = shallowMount(Table, {
+ propsData: {
+ path,
+ },
+ mocks: {
+ $apollo,
+ },
+ });
+}
+
+describe('Repository table component', () => {
+ afterEach(() => {
+ vm.destroy();
+ });
+
+ it.each`
+ path | ref
+ ${'/'} | ${'master'}
+ ${'app/assets'} | ${'master'}
+ ${'/'} | ${'test'}
+ `('renders table caption for $ref in $path', ({ path, ref }) => {
+ factory(path);
+
+ vm.setData({ ref });
+
+ expect(vm.find('caption').text()).toEqual(
+ `Files, directories, and submodules in the path ${path} for commit reference ${ref}`,
+ );
+ });
+
+ it('shows loading icon', () => {
+ factory('/');
+
+ vm.setData({ isLoadingFiles: true });
+
+ expect(vm.find(GlLoadingIcon).isVisible()).toBe(true);
+ });
+
+ describe('normalizeData', () => {
+ it('normalizes edge nodes', () => {
+ const output = vm.vm.normalizeData('blobs', [{ node: '1' }, { node: '2' }]);
+
+ expect(output).toEqual(['1', '2']);
+ });
+ });
+
+ describe('hasNextPage', () => {
+ it('returns undefined when hasNextPage is false', () => {
+ const output = vm.vm.hasNextPage({
+ trees: { pageInfo: { hasNextPage: false } },
+ submodules: { pageInfo: { hasNextPage: false } },
+ blobs: { pageInfo: { hasNextPage: false } },
+ });
+
+ expect(output).toBe(undefined);
+ });
+
+ it('returns pageInfo object when hasNextPage is true', () => {
+ const output = vm.vm.hasNextPage({
+ trees: { pageInfo: { hasNextPage: false } },
+ submodules: { pageInfo: { hasNextPage: false } },
+ blobs: { pageInfo: { hasNextPage: true, nextCursor: 'test' } },
+ });
+
+ expect(output).toEqual({ hasNextPage: true, nextCursor: 'test' });
+ });
+ });
+});
diff --git a/spec/frontend/repository/components/table/parent_row_spec.js b/spec/frontend/repository/components/table/parent_row_spec.js
new file mode 100644
index 00000000000..7020055271f
--- /dev/null
+++ b/spec/frontend/repository/components/table/parent_row_spec.js
@@ -0,0 +1,64 @@
+import { shallowMount, RouterLinkStub } from '@vue/test-utils';
+import ParentRow from '~/repository/components/table/parent_row.vue';
+
+let vm;
+let $router;
+
+function factory(path) {
+ $router = {
+ push: jest.fn(),
+ };
+
+ vm = shallowMount(ParentRow, {
+ propsData: {
+ commitRef: 'master',
+ path,
+ },
+ stubs: {
+ RouterLink: RouterLinkStub,
+ },
+ mocks: {
+ $router,
+ },
+ });
+}
+
+describe('Repository parent row component', () => {
+ afterEach(() => {
+ vm.destroy();
+ });
+
+ it.each`
+ path | to
+ ${'app'} | ${'/tree/master/'}
+ ${'app/assets'} | ${'/tree/master/app'}
+ `('renders link in $path to $to', ({ path, to }) => {
+ factory(path);
+
+ expect(vm.find(RouterLinkStub).props().to).toEqual({
+ path: to,
+ });
+ });
+
+ it('pushes new router when clicking row', () => {
+ factory('app/assets');
+
+ vm.find('td').trigger('click');
+
+ expect($router.push).toHaveBeenCalledWith({
+ path: '/tree/master/app',
+ });
+ });
+
+ // We test that it does not get called when clicking any internal
+ // links as this was causing multipe routes to get pushed
+ it('does not trigger router.push when clicking link', () => {
+ factory('app/assets');
+
+ vm.find('a').trigger('click');
+
+ expect($router.push).not.toHaveBeenCalledWith({
+ path: '/tree/master/app',
+ });
+ });
+});
diff --git a/spec/frontend/repository/components/table/row_spec.js b/spec/frontend/repository/components/table/row_spec.js
new file mode 100644
index 00000000000..5a345ddeacd
--- /dev/null
+++ b/spec/frontend/repository/components/table/row_spec.js
@@ -0,0 +1,143 @@
+import { shallowMount, RouterLinkStub } from '@vue/test-utils';
+import { GlBadge } from '@gitlab/ui';
+import { visitUrl } from '~/lib/utils/url_utility';
+import TableRow from '~/repository/components/table/row.vue';
+
+jest.mock('~/lib/utils/url_utility');
+
+let vm;
+let $router;
+
+function factory(propsData = {}) {
+ $router = {
+ push: jest.fn(),
+ };
+
+ vm = shallowMount(TableRow, {
+ propsData: {
+ ...propsData,
+ url: `https://test.com`,
+ },
+ mocks: {
+ $router,
+ },
+ stubs: {
+ RouterLink: RouterLinkStub,
+ },
+ });
+
+ vm.setData({ ref: 'master' });
+}
+
+describe('Repository table row component', () => {
+ afterEach(() => {
+ vm.destroy();
+ jest.clearAllMocks();
+ });
+
+ it('renders table row', () => {
+ factory({
+ id: '1',
+ path: 'test',
+ type: 'file',
+ currentPath: '/',
+ });
+
+ expect(vm.element).toMatchSnapshot();
+ });
+
+ it.each`
+ type | component | componentName
+ ${'tree'} | ${RouterLinkStub} | ${'RouterLink'}
+ ${'file'} | ${'a'} | ${'hyperlink'}
+ ${'commit'} | ${'a'} | ${'hyperlink'}
+ `('renders a $componentName for type $type', ({ type, component }) => {
+ factory({
+ id: '1',
+ path: 'test',
+ type,
+ currentPath: '/',
+ });
+
+ expect(vm.find(component).exists()).toBe(true);
+ });
+
+ it.each`
+ type | pushes
+ ${'tree'} | ${true}
+ ${'file'} | ${false}
+ ${'commit'} | ${false}
+ `('pushes new router if type $type is tree', ({ type, pushes }) => {
+ factory({
+ id: '1',
+ path: 'test',
+ type,
+ currentPath: '/',
+ });
+
+ vm.trigger('click');
+
+ if (pushes) {
+ expect($router.push).toHaveBeenCalledWith({ path: '/tree/master/test' });
+ } else {
+ expect($router.push).not.toHaveBeenCalled();
+ }
+ });
+
+ it.each`
+ type | pushes
+ ${'tree'} | ${true}
+ ${'file'} | ${false}
+ ${'commit'} | ${false}
+ `('calls visitUrl if $type is not tree', ({ type, pushes }) => {
+ factory({
+ id: '1',
+ path: 'test',
+ type,
+ currentPath: '/',
+ });
+
+ vm.trigger('click');
+
+ if (pushes) {
+ expect(visitUrl).not.toHaveBeenCalled();
+ } else {
+ expect(visitUrl).toHaveBeenCalledWith('https://test.com');
+ }
+ });
+
+ it('renders commit ID for submodule', () => {
+ factory({
+ id: '1',
+ path: 'test',
+ type: 'commit',
+ currentPath: '/',
+ });
+
+ expect(vm.find('.commit-sha').text()).toContain('1');
+ });
+
+ it('renders link with href', () => {
+ factory({
+ id: '1',
+ path: 'test',
+ type: 'blob',
+ url: 'https://test.com',
+ currentPath: '/',
+ });
+
+ expect(vm.find('a').attributes('href')).toEqual('https://test.com');
+ });
+
+ it('renders LFS badge', () => {
+ factory({
+ id: '1',
+ path: 'test',
+ type: 'commit',
+ currentPath: '/',
+ lfsOid: '1',
+ });
+
+ expect(vm.find(GlBadge).exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/repository/router_spec.js b/spec/frontend/repository/router_spec.js
new file mode 100644
index 00000000000..f61a0ccd1e6
--- /dev/null
+++ b/spec/frontend/repository/router_spec.js
@@ -0,0 +1,23 @@
+import IndexPage from '~/repository/pages/index.vue';
+import TreePage from '~/repository/pages/tree.vue';
+import createRouter from '~/repository/router';
+
+describe('Repository router spec', () => {
+ it.each`
+ path | component | componentName
+ ${'/'} | ${IndexPage} | ${'IndexPage'}
+ ${'/tree/master'} | ${TreePage} | ${'TreePage'}
+ ${'/tree/master/app/assets'} | ${TreePage} | ${'TreePage'}
+ ${'/tree/123/app/assets'} | ${null} | ${'null'}
+ `('sets component as $componentName for path "$path"', ({ path, component }) => {
+ const router = createRouter('', 'master');
+
+ const componentsForRoute = router.getMatchedComponents(path);
+
+ expect(componentsForRoute.length).toBe(component ? 1 : 0);
+
+ if (component) {
+ expect(componentsForRoute).toContain(component);
+ }
+ });
+});
diff --git a/spec/frontend/repository/utils/icon_spec.js b/spec/frontend/repository/utils/icon_spec.js
new file mode 100644
index 00000000000..3d84705f7ea
--- /dev/null
+++ b/spec/frontend/repository/utils/icon_spec.js
@@ -0,0 +1,23 @@
+import { getIconName } from '~/repository/utils/icon';
+
+describe('getIconName', () => {
+ // Tests the returning font awesome icon name
+ // We only test one for each file type to save testing a lot of different
+ // file types
+ it.each`
+ type | path | icon
+ ${'tree'} | ${''} | ${'folder'}
+ ${'commit'} | ${''} | ${'archive'}
+ ${'file'} | ${'test.pdf'} | ${'file-pdf-o'}
+ ${'file'} | ${'test.jpg'} | ${'file-image-o'}
+ ${'file'} | ${'test.zip'} | ${'file-archive-o'}
+ ${'file'} | ${'test.mp3'} | ${'file-audio-o'}
+ ${'file'} | ${'test.flv'} | ${'file-video-o'}
+ ${'file'} | ${'test.dotx'} | ${'file-word-o'}
+ ${'file'} | ${'test.xlsb'} | ${'file-excel-o'}
+ ${'file'} | ${'test.ppam'} | ${'file-powerpoint-o'}
+ ${'file'} | ${'test.js'} | ${'file-text-o'}
+ `('returns $icon for $type with path $path', ({ type, path, icon }) => {
+ expect(getIconName(type, path)).toEqual(icon);
+ });
+});
diff --git a/spec/frontend/repository/utils/title_spec.js b/spec/frontend/repository/utils/title_spec.js
new file mode 100644
index 00000000000..c4879716fd7
--- /dev/null
+++ b/spec/frontend/repository/utils/title_spec.js
@@ -0,0 +1,15 @@
+import { setTitle } from '~/repository/utils/title';
+
+describe('setTitle', () => {
+ it.each`
+ path | title
+ ${'/'} | ${'Files'}
+ ${'app'} | ${'app'}
+ ${'app/assets'} | ${'app/assets'}
+ ${'app/assets/javascripts'} | ${'app/assets/javascripts'}
+ `('sets document title as $title for $path', ({ path, title }) => {
+ setTitle(path, 'master', 'GitLab');
+
+ expect(document.title).toEqual(`${title} · master · GitLab`);
+ });
+});
diff --git a/spec/frontend/serverless/components/environment_row_spec.js b/spec/frontend/serverless/components/environment_row_spec.js
index 161a637dd75..0ad85e218dc 100644
--- a/spec/frontend/serverless/components/environment_row_spec.js
+++ b/spec/frontend/serverless/components/environment_row_spec.js
@@ -14,7 +14,7 @@ describe('environment row component', () => {
beforeEach(() => {
localVue = createLocalVue();
- vm = createComponent(localVue, translate(mockServerlessFunctions)['*'], '*');
+ vm = createComponent(localVue, translate(mockServerlessFunctions.functions)['*'], '*');
});
afterEach(() => vm.$destroy());
@@ -48,7 +48,11 @@ describe('environment row component', () => {
beforeEach(() => {
localVue = createLocalVue();
- vm = createComponent(localVue, translate(mockServerlessFunctionsDiffEnv).test, 'test');
+ vm = createComponent(
+ localVue,
+ translate(mockServerlessFunctionsDiffEnv.functions).test,
+ 'test',
+ );
});
afterEach(() => vm.$destroy());
diff --git a/spec/frontend/serverless/components/function_row_spec.js b/spec/frontend/serverless/components/function_row_spec.js
index 414fdc5cd82..979f98c4832 100644
--- a/spec/frontend/serverless/components/function_row_spec.js
+++ b/spec/frontend/serverless/components/function_row_spec.js
@@ -1,27 +1,32 @@
import functionRowComponent from '~/serverless/components/function_row.vue';
import { shallowMount } from '@vue/test-utils';
+import Timeago from '~/vue_shared/components/time_ago_tooltip.vue';
import { mockServerlessFunction } from '../mock_data';
-const createComponent = func =>
- shallowMount(functionRowComponent, { propsData: { func }, sync: false }).vm;
-
describe('functionRowComponent', () => {
- it('Parses the function details correctly', () => {
- const vm = createComponent(mockServerlessFunction);
+ let wrapper;
- expect(vm.$el.querySelector('b').innerHTML).toEqual(mockServerlessFunction.name);
- expect(vm.$el.querySelector('span').innerHTML).toEqual(mockServerlessFunction.image);
- expect(vm.$el.querySelector('timeago-stub').getAttribute('time')).not.toBe(null);
+ const createComponent = func => {
+ wrapper = shallowMount(functionRowComponent, { propsData: { func }, sync: false });
+ };
- vm.$destroy();
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Parses the function details correctly', () => {
+ createComponent(mockServerlessFunction);
+
+ expect(wrapper.find('b').text()).toBe(mockServerlessFunction.name);
+ expect(wrapper.find('span').text()).toBe(mockServerlessFunction.image);
+ expect(wrapper.find(Timeago).attributes('time')).not.toBe(null);
});
it('handles clicks correctly', () => {
- const vm = createComponent(mockServerlessFunction);
+ createComponent(mockServerlessFunction);
+ const { vm } = wrapper;
expect(vm.checkClass(vm.$el.querySelector('p'))).toBe(true); // check somewhere inside the row
-
- vm.$destroy();
});
});
diff --git a/spec/frontend/serverless/components/functions_spec.js b/spec/frontend/serverless/components/functions_spec.js
index 7af33ceaadc..d8a80f8031e 100644
--- a/spec/frontend/serverless/components/functions_spec.js
+++ b/spec/frontend/serverless/components/functions_spec.js
@@ -1,9 +1,12 @@
import Vuex from 'vuex';
+import { GlLoadingIcon } from '@gitlab/ui';
import AxiosMockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import functionsComponent from '~/serverless/components/functions.vue';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import { createStore } from '~/serverless/store';
+import EmptyState from '~/serverless/components/empty_state.vue';
+import EnvironmentRow from '~/serverless/components/environment_row.vue';
import { TEST_HOST } from 'helpers/test_constants';
import { mockServerlessFunctions } from '../mock_data';
@@ -31,11 +34,11 @@ describe('functionsComponent', () => {
});
it('should render empty state when Knative is not installed', () => {
+ store.dispatch('receiveFunctionsSuccess', { knative_installed: false });
component = shallowMount(functionsComponent, {
localVue,
store,
propsData: {
- installed: false,
clustersPath: '',
helpPath: '',
statusPath: '',
@@ -43,7 +46,7 @@ describe('functionsComponent', () => {
sync: false,
});
- expect(component.vm.$el.querySelector('emptystate-stub')).not.toBe(null);
+ expect(component.find(EmptyState).exists()).toBe(true);
});
it('should render a loading component', () => {
@@ -52,7 +55,6 @@ describe('functionsComponent', () => {
localVue,
store,
propsData: {
- installed: true,
clustersPath: '',
helpPath: '',
statusPath: '',
@@ -60,16 +62,15 @@ describe('functionsComponent', () => {
sync: false,
});
- expect(component.vm.$el.querySelector('glloadingicon-stub')).not.toBe(null);
+ expect(component.find(GlLoadingIcon).exists()).toBe(true);
});
it('should render empty state when there is no function data', () => {
- store.dispatch('receiveFunctionsNoDataSuccess');
+ store.dispatch('receiveFunctionsNoDataSuccess', { knative_installed: true });
component = shallowMount(functionsComponent, {
localVue,
store,
propsData: {
- installed: true,
clustersPath: '',
helpPath: '',
statusPath: '',
@@ -88,12 +89,31 @@ describe('functionsComponent', () => {
);
});
+ it('should render functions and a loader when functions are partially fetched', () => {
+ store.dispatch('receiveFunctionsPartial', {
+ ...mockServerlessFunctions,
+ knative_installed: 'checking',
+ });
+ component = shallowMount(functionsComponent, {
+ localVue,
+ store,
+ propsData: {
+ clustersPath: '',
+ helpPath: '',
+ statusPath: '',
+ },
+ sync: false,
+ });
+
+ expect(component.find('.js-functions-wrapper').exists()).toBe(true);
+ expect(component.find('.js-functions-loader').exists()).toBe(true);
+ });
+
it('should render the functions list', () => {
component = shallowMount(functionsComponent, {
localVue,
store,
propsData: {
- installed: true,
clustersPath: 'clustersPath',
helpPath: 'helpPath',
statusPath,
@@ -104,7 +124,7 @@ describe('functionsComponent', () => {
component.vm.$store.dispatch('receiveFunctionsSuccess', mockServerlessFunctions);
return component.vm.$nextTick().then(() => {
- expect(component.vm.$el.querySelector('environmentrow-stub')).not.toBe(null);
+ expect(component.find(EnvironmentRow).exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/serverless/components/missing_prometheus_spec.js b/spec/frontend/serverless/components/missing_prometheus_spec.js
index d0df6125290..5dbdccde2de 100644
--- a/spec/frontend/serverless/components/missing_prometheus_spec.js
+++ b/spec/frontend/serverless/components/missing_prometheus_spec.js
@@ -1,3 +1,4 @@
+import { GlButton } from '@gitlab/ui';
import missingPrometheusComponent from '~/serverless/components/missing_prometheus.vue';
import { shallowMount } from '@vue/test-utils';
@@ -9,27 +10,29 @@ const createComponent = missingData =>
missingData,
},
sync: false,
- }).vm;
+ });
describe('missingPrometheusComponent', () => {
- let vm;
+ let wrapper;
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('should render missing prometheus message', () => {
- vm = createComponent(false);
+ wrapper = createComponent(false);
+ const { vm } = wrapper;
expect(vm.$el.querySelector('.state-description').innerHTML.trim()).toContain(
'Function invocation metrics require Prometheus to be installed first.',
);
- expect(vm.$el.querySelector('glbutton-stub').getAttribute('variant')).toEqual('success');
+ expect(wrapper.find(GlButton).attributes('variant')).toBe('success');
});
it('should render no prometheus data message', () => {
- vm = createComponent(true);
+ wrapper = createComponent(true);
+ const { vm } = wrapper;
expect(vm.$el.querySelector('.state-description').innerHTML.trim()).toContain(
'Invocation metrics loading or not available at this time.',
diff --git a/spec/frontend/serverless/components/url_spec.js b/spec/frontend/serverless/components/url_spec.js
index d05a9bba103..706441e8a8b 100644
--- a/spec/frontend/serverless/components/url_spec.js
+++ b/spec/frontend/serverless/components/url_spec.js
@@ -1,6 +1,7 @@
import Vue from 'vue';
import urlComponent from '~/serverless/components/url.vue';
import { shallowMount } from '@vue/test-utils';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
const createComponent = uri =>
shallowMount(Vue.extend(urlComponent), {
@@ -8,15 +9,16 @@ const createComponent = uri =>
uri,
},
sync: false,
- }).vm;
+ });
describe('urlComponent', () => {
it('should render correctly', () => {
const uri = 'http://testfunc.apps.example.com';
- const vm = createComponent(uri);
+ const wrapper = createComponent(uri);
+ const { vm } = wrapper;
expect(vm.$el.classList.contains('clipboard-group')).toBe(true);
- expect(vm.$el.querySelector('clipboardbutton-stub').getAttribute('text')).toEqual(uri);
+ expect(wrapper.find(ClipboardButton).attributes('text')).toEqual(uri);
expect(vm.$el.querySelector('.url-text-field').innerHTML).toEqual(uri);
diff --git a/spec/frontend/serverless/mock_data.js b/spec/frontend/serverless/mock_data.js
index a2c18616324..ef616ceb37f 100644
--- a/spec/frontend/serverless/mock_data.js
+++ b/spec/frontend/serverless/mock_data.js
@@ -1,56 +1,62 @@
-export const mockServerlessFunctions = [
- {
- name: 'testfunc1',
- namespace: 'tm-example',
- environment_scope: '*',
- cluster_id: 46,
- detail_url: '/testuser/testproj/serverless/functions/*/testfunc1',
- podcount: null,
- created_at: '2019-02-05T01:01:23Z',
- url: 'http://testfunc1.tm-example.apps.example.com',
- description: 'A test service',
- image: 'knative-test-container-buildtemplate',
- },
- {
- name: 'testfunc2',
- namespace: 'tm-example',
- environment_scope: '*',
- cluster_id: 46,
- detail_url: '/testuser/testproj/serverless/functions/*/testfunc2',
- podcount: null,
- created_at: '2019-02-05T01:01:23Z',
- url: 'http://testfunc2.tm-example.apps.example.com',
- description: 'A second test service\nThis one with additional descriptions',
- image: 'knative-test-echo-buildtemplate',
- },
-];
+export const mockServerlessFunctions = {
+ knative_installed: true,
+ functions: [
+ {
+ name: 'testfunc1',
+ namespace: 'tm-example',
+ environment_scope: '*',
+ cluster_id: 46,
+ detail_url: '/testuser/testproj/serverless/functions/*/testfunc1',
+ podcount: null,
+ created_at: '2019-02-05T01:01:23Z',
+ url: 'http://testfunc1.tm-example.apps.example.com',
+ description: 'A test service',
+ image: 'knative-test-container-buildtemplate',
+ },
+ {
+ name: 'testfunc2',
+ namespace: 'tm-example',
+ environment_scope: '*',
+ cluster_id: 46,
+ detail_url: '/testuser/testproj/serverless/functions/*/testfunc2',
+ podcount: null,
+ created_at: '2019-02-05T01:01:23Z',
+ url: 'http://testfunc2.tm-example.apps.example.com',
+ description: 'A second test service\nThis one with additional descriptions',
+ image: 'knative-test-echo-buildtemplate',
+ },
+ ],
+};
-export const mockServerlessFunctionsDiffEnv = [
- {
- name: 'testfunc1',
- namespace: 'tm-example',
- environment_scope: '*',
- cluster_id: 46,
- detail_url: '/testuser/testproj/serverless/functions/*/testfunc1',
- podcount: null,
- created_at: '2019-02-05T01:01:23Z',
- url: 'http://testfunc1.tm-example.apps.example.com',
- description: 'A test service',
- image: 'knative-test-container-buildtemplate',
- },
- {
- name: 'testfunc2',
- namespace: 'tm-example',
- environment_scope: 'test',
- cluster_id: 46,
- detail_url: '/testuser/testproj/serverless/functions/*/testfunc2',
- podcount: null,
- created_at: '2019-02-05T01:01:23Z',
- url: 'http://testfunc2.tm-example.apps.example.com',
- description: 'A second test service\nThis one with additional descriptions',
- image: 'knative-test-echo-buildtemplate',
- },
-];
+export const mockServerlessFunctionsDiffEnv = {
+ knative_installed: true,
+ functions: [
+ {
+ name: 'testfunc1',
+ namespace: 'tm-example',
+ environment_scope: '*',
+ cluster_id: 46,
+ detail_url: '/testuser/testproj/serverless/functions/*/testfunc1',
+ podcount: null,
+ created_at: '2019-02-05T01:01:23Z',
+ url: 'http://testfunc1.tm-example.apps.example.com',
+ description: 'A test service',
+ image: 'knative-test-container-buildtemplate',
+ },
+ {
+ name: 'testfunc2',
+ namespace: 'tm-example',
+ environment_scope: 'test',
+ cluster_id: 46,
+ detail_url: '/testuser/testproj/serverless/functions/*/testfunc2',
+ podcount: null,
+ created_at: '2019-02-05T01:01:23Z',
+ url: 'http://testfunc2.tm-example.apps.example.com',
+ description: 'A second test service\nThis one with additional descriptions',
+ image: 'knative-test-echo-buildtemplate',
+ },
+ ],
+};
export const mockServerlessFunction = {
name: 'testfunc1',
diff --git a/spec/frontend/serverless/store/getters_spec.js b/spec/frontend/serverless/store/getters_spec.js
index fb549c8f153..92853fda37c 100644
--- a/spec/frontend/serverless/store/getters_spec.js
+++ b/spec/frontend/serverless/store/getters_spec.js
@@ -32,7 +32,7 @@ describe('Serverless Store Getters', () => {
describe('getFunctions', () => {
it('should translate the raw function array to group the functions per environment scope', () => {
- state.functions = mockServerlessFunctions;
+ state.functions = mockServerlessFunctions.functions;
const funcs = getters.getFunctions(state);
diff --git a/spec/frontend/serverless/store/mutations_spec.js b/spec/frontend/serverless/store/mutations_spec.js
index ca3053e5c38..e2771c7e5fd 100644
--- a/spec/frontend/serverless/store/mutations_spec.js
+++ b/spec/frontend/serverless/store/mutations_spec.js
@@ -19,13 +19,13 @@ describe('ServerlessMutations', () => {
expect(state.isLoading).toEqual(false);
expect(state.hasFunctionData).toEqual(true);
- expect(state.functions).toEqual(mockServerlessFunctions);
+ expect(state.functions).toEqual(mockServerlessFunctions.functions);
});
it('should ensure loading has stopped and hasFunctionData is false when there are no functions available', () => {
const state = {};
- mutations[types.RECEIVE_FUNCTIONS_NODATA_SUCCESS](state);
+ mutations[types.RECEIVE_FUNCTIONS_NODATA_SUCCESS](state, { knative_installed: true });
expect(state.isLoading).toEqual(false);
expect(state.hasFunctionData).toEqual(false);
diff --git a/spec/frontend/test_setup.js b/spec/frontend/test_setup.js
index c57e0e7cfc6..7e7cc1488b8 100644
--- a/spec/frontend/test_setup.js
+++ b/spec/frontend/test_setup.js
@@ -3,7 +3,7 @@ import * as jqueryMatchers from 'custom-jquery-matchers';
import Translate from '~/vue_shared/translate';
import axios from '~/lib/utils/axios_utils';
import { initializeTestTimeout } from './helpers/timeout';
-import { getJSONFixture, loadHTMLFixture, setHTMLFixture } from './helpers/fixtures';
+import { loadHTMLFixture, setHTMLFixture } from './helpers/fixtures';
process.on('unhandledRejection', global.promiseRejectionHandler);
@@ -15,7 +15,7 @@ afterEach(() =>
}),
);
-initializeTestTimeout(300);
+initializeTestTimeout(process.env.CI ? 5000 : 500);
// fail tests for unmocked requests
beforeEach(done => {
@@ -46,9 +46,12 @@ Object.defineProperty(global.Element.prototype, 'innerText', {
// convenience wrapper for migration from Karma
Object.assign(global, {
loadFixtures: loadHTMLFixture,
- loadJSONFixtures: getJSONFixture,
- preloadFixtures() {},
setFixtures: setHTMLFixture,
+
+ // The following functions fill the fixtures cache in Karma.
+ // This is not necessary in Jest because we make no Ajax request.
+ loadJSONFixtures() {},
+ preloadFixtures() {},
});
// custom-jquery-matchers was written for an old Jest version, we need to make it compatible
diff --git a/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js b/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js
index b356ea85cad..0f5d47b3bfe 100644
--- a/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js
+++ b/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js
@@ -4,7 +4,7 @@ describe('getStateKey', () => {
it('should return proper state name', () => {
const context = {
mergeStatus: 'checked',
- mergeWhenPipelineSucceeds: false,
+ autoMergeEnabled: false,
canMerge: true,
onlyAllowMergeIfPipelineSucceeds: false,
isPipelineFailed: false,
@@ -31,9 +31,9 @@ describe('getStateKey', () => {
expect(bound()).toEqual('notAllowedToMerge');
- context.mergeWhenPipelineSucceeds = true;
+ context.autoMergeEnabled = true;
- expect(bound()).toEqual('mergeWhenPipelineSucceeds');
+ expect(bound()).toEqual('autoMergeEnabled');
context.isSHAMismatch = true;
@@ -80,7 +80,7 @@ describe('getStateKey', () => {
it('returns rebased state key', () => {
const context = {
mergeStatus: 'checked',
- mergeWhenPipelineSucceeds: false,
+ autoMergeEnabled: false,
canMerge: true,
onlyAllowMergeIfPipelineSucceeds: true,
isPipelineFailed: true,
diff --git a/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js b/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js
new file mode 100644
index 00000000000..d1de98f4a15
--- /dev/null
+++ b/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js
@@ -0,0 +1,114 @@
+import Vue from 'vue';
+
+import IssueAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
+
+import mountComponent from 'helpers/vue_mount_component_helper';
+import { mockAssigneesList } from '../../../../javascripts/boards/mock_data';
+
+const createComponent = (assignees = mockAssigneesList, cssClass = '') => {
+ const Component = Vue.extend(IssueAssignees);
+
+ return mountComponent(Component, {
+ assignees,
+ cssClass,
+ });
+};
+
+describe('IssueAssigneesComponent', () => {
+ let vm;
+
+ beforeEach(() => {
+ vm = createComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('data', () => {
+ it('returns default data props', () => {
+ expect(vm.maxVisibleAssignees).toBe(2);
+ expect(vm.maxAssigneeAvatars).toBe(3);
+ expect(vm.maxAssignees).toBe(99);
+ });
+ });
+
+ describe('computed', () => {
+ describe('countOverLimit', () => {
+ it('should return difference between assignees count and maxVisibleAssignees', () => {
+ expect(vm.countOverLimit).toBe(mockAssigneesList.length - vm.maxVisibleAssignees);
+ });
+ });
+
+ describe('assigneesToShow', () => {
+ it('should return assignees containing only 2 items when count more than maxAssigneeAvatars', () => {
+ expect(vm.assigneesToShow.length).toBe(2);
+ });
+
+ it('should return all assignees as it is when count less than maxAssigneeAvatars', () => {
+ vm.assignees = mockAssigneesList.slice(0, 3); // Set 3 Assignees
+
+ expect(vm.assigneesToShow.length).toBe(3);
+ });
+ });
+
+ describe('assigneesCounterTooltip', () => {
+ it('should return string containing count of remaining assignees when count more than maxAssigneeAvatars', () => {
+ expect(vm.assigneesCounterTooltip).toBe('3 more assignees');
+ });
+ });
+
+ describe('shouldRenderAssigneesCounter', () => {
+ it('should return `false` when assignees count less than maxAssigneeAvatars', () => {
+ vm.assignees = mockAssigneesList.slice(0, 3); // Set 3 Assignees
+
+ expect(vm.shouldRenderAssigneesCounter).toBe(false);
+ });
+
+ it('should return `true` when assignees count more than maxAssigneeAvatars', () => {
+ expect(vm.shouldRenderAssigneesCounter).toBe(true);
+ });
+ });
+
+ describe('assigneeCounterLabel', () => {
+ it('should return count of additional assignees total assignees count more than maxAssigneeAvatars', () => {
+ expect(vm.assigneeCounterLabel).toBe('+3');
+ });
+ });
+ });
+
+ describe('methods', () => {
+ describe('avatarUrlTitle', () => {
+ it('returns string containing alt text for assignee avatar', () => {
+ expect(vm.avatarUrlTitle(mockAssigneesList[0])).toBe('Avatar for Terrell Graham');
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('renders component root element with class `issue-assignees`', () => {
+ expect(vm.$el.classList.contains('issue-assignees')).toBe(true);
+ });
+
+ it('renders assignee avatars', () => {
+ expect(vm.$el.querySelectorAll('.user-avatar-link').length).toBe(2);
+ });
+
+ it('renders assignee tooltips', () => {
+ const tooltipText = vm.$el
+ .querySelectorAll('.user-avatar-link')[0]
+ .querySelector('.js-assignee-tooltip').innerText;
+
+ expect(tooltipText).toContain('Assignee');
+ expect(tooltipText).toContain('Terrell Graham');
+ expect(tooltipText).toContain('@monserrate.gleichner');
+ });
+
+ it('renders additional assignees count', () => {
+ const avatarCounterEl = vm.$el.querySelector('.avatar-counter');
+
+ expect(avatarCounterEl.innerText.trim()).toBe('+3');
+ expect(avatarCounterEl.getAttribute('data-original-title')).toBe('3 more assignees');
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js b/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js
new file mode 100644
index 00000000000..2e93ec412b9
--- /dev/null
+++ b/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js
@@ -0,0 +1,172 @@
+import Vue from 'vue';
+import { mount } from '@vue/test-utils';
+
+import IssueMilestone from '~/vue_shared/components/issue/issue_milestone.vue';
+
+import { mockMilestone } from '../../../../javascripts/boards/mock_data';
+
+const createComponent = (milestone = mockMilestone) => {
+ const Component = Vue.extend(IssueMilestone);
+
+ return mount(Component, {
+ propsData: {
+ milestone,
+ },
+ sync: false,
+ });
+};
+
+describe('IssueMilestoneComponent', () => {
+ let wrapper;
+ let vm;
+
+ beforeEach(done => {
+ wrapper = createComponent();
+
+ ({ vm } = wrapper);
+
+ Vue.nextTick(done);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('computed', () => {
+ describe('isMilestoneStarted', () => {
+ it('should return `false` when milestoneStart prop is not defined', () => {
+ wrapper.setProps({
+ milestone: Object.assign({}, mockMilestone, {
+ start_date: '',
+ }),
+ });
+
+ expect(wrapper.vm.isMilestoneStarted).toBe(false);
+ });
+
+ it('should return `true` when milestone start date is past current date', () => {
+ wrapper.setProps({
+ milestone: Object.assign({}, mockMilestone, {
+ start_date: '1990-07-22',
+ }),
+ });
+
+ expect(wrapper.vm.isMilestoneStarted).toBe(true);
+ });
+ });
+
+ describe('isMilestonePastDue', () => {
+ it('should return `false` when milestoneDue prop is not defined', () => {
+ wrapper.setProps({
+ milestone: Object.assign({}, mockMilestone, {
+ due_date: '',
+ }),
+ });
+
+ expect(wrapper.vm.isMilestonePastDue).toBe(false);
+ });
+
+ it('should return `true` when milestone due is past current date', () => {
+ wrapper.setProps({
+ milestone: Object.assign({}, mockMilestone, {
+ due_date: '1990-07-22',
+ }),
+ });
+
+ expect(wrapper.vm.isMilestonePastDue).toBe(true);
+ });
+ });
+
+ describe('milestoneDatesAbsolute', () => {
+ it('returns string containing absolute milestone due date', () => {
+ expect(vm.milestoneDatesAbsolute).toBe('(December 31, 2019)');
+ });
+
+ it('returns string containing absolute milestone start date when due date is not present', () => {
+ wrapper.setProps({
+ milestone: Object.assign({}, mockMilestone, {
+ due_date: '',
+ }),
+ });
+
+ expect(wrapper.vm.milestoneDatesAbsolute).toBe('(January 1, 2018)');
+ });
+
+ it('returns empty string when both milestone start and due dates are not present', () => {
+ wrapper.setProps({
+ milestone: Object.assign({}, mockMilestone, {
+ start_date: '',
+ due_date: '',
+ }),
+ });
+
+ expect(wrapper.vm.milestoneDatesAbsolute).toBe('');
+ });
+ });
+
+ describe('milestoneDatesHuman', () => {
+ it('returns string containing milestone due date when date is yet to be due', () => {
+ wrapper.setProps({
+ milestone: Object.assign({}, mockMilestone, {
+ due_date: `${new Date().getFullYear() + 10}-01-01`,
+ }),
+ });
+
+ expect(wrapper.vm.milestoneDatesHuman).toContain('years remaining');
+ });
+
+ it('returns string containing milestone start date when date has already started and due date is not present', () => {
+ wrapper.setProps({
+ milestone: Object.assign({}, mockMilestone, {
+ start_date: '1990-07-22',
+ due_date: '',
+ }),
+ });
+
+ expect(wrapper.vm.milestoneDatesHuman).toContain('Started');
+ });
+
+ it('returns string containing milestone start date when date is yet to start and due date is not present', () => {
+ wrapper.setProps({
+ milestone: Object.assign({}, mockMilestone, {
+ start_date: `${new Date().getFullYear() + 10}-01-01`,
+ due_date: '',
+ }),
+ });
+
+ expect(wrapper.vm.milestoneDatesHuman).toContain('Starts');
+ });
+
+ it('returns empty string when milestone start and due dates are not present', () => {
+ wrapper.setProps({
+ milestone: Object.assign({}, mockMilestone, {
+ start_date: '',
+ due_date: '',
+ }),
+ });
+
+ expect(wrapper.vm.milestoneDatesHuman).toBe('');
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('renders component root element with class `issue-milestone-details`', () => {
+ expect(vm.$el.classList.contains('issue-milestone-details')).toBe(true);
+ });
+
+ it('renders milestone icon', () => {
+ expect(vm.$el.querySelector('svg use').getAttribute('xlink:href')).toContain('clock');
+ });
+
+ it('renders milestone title', () => {
+ expect(vm.$el.querySelector('.milestone-title').innerText.trim()).toBe(mockMilestone.title);
+ });
+
+ it('renders milestone tooltip', () => {
+ expect(vm.$el.querySelector('.js-item-milestone').innerText.trim()).toContain(
+ mockMilestone.title,
+ );
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/issue/issue_warning_spec.js b/spec/frontend/vue_shared/components/issue/issue_warning_spec.js
new file mode 100644
index 00000000000..63880b85625
--- /dev/null
+++ b/spec/frontend/vue_shared/components/issue/issue_warning_spec.js
@@ -0,0 +1,65 @@
+import Vue from 'vue';
+import issueWarning from '~/vue_shared/components/issue/issue_warning.vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
+
+const IssueWarning = Vue.extend(issueWarning);
+
+function formatWarning(string) {
+ // Replace newlines with a space then replace multiple spaces with one space
+ return string
+ .trim()
+ .replace(/\n/g, ' ')
+ .replace(/\s\s+/g, ' ');
+}
+
+describe('Issue Warning Component', () => {
+ describe('isLocked', () => {
+ it('should render locked issue warning information', () => {
+ const props = {
+ isLocked: true,
+ lockedIssueDocsPath: 'docs/issues/locked',
+ };
+ const vm = mountComponent(IssueWarning, props);
+
+ expect(
+ vm.$el.querySelector('.icon use').getAttributeNS('http://www.w3.org/1999/xlink', 'href'),
+ ).toMatch(/lock$/);
+ expect(formatWarning(vm.$el.querySelector('span').textContent)).toEqual(
+ 'This issue is locked. Only project members can comment. Learn more',
+ );
+ expect(vm.$el.querySelector('a').href).toContain(props.lockedIssueDocsPath);
+ });
+ });
+
+ describe('isConfidential', () => {
+ it('should render confidential issue warning information', () => {
+ const props = {
+ isConfidential: true,
+ confidentialIssueDocsPath: '/docs/issues/confidential',
+ };
+ const vm = mountComponent(IssueWarning, props);
+
+ expect(
+ vm.$el.querySelector('.icon use').getAttributeNS('http://www.w3.org/1999/xlink', 'href'),
+ ).toMatch(/eye-slash$/);
+ expect(formatWarning(vm.$el.querySelector('span').textContent)).toEqual(
+ 'This is a confidential issue. People without permission will never get a notification. Learn more',
+ );
+ expect(vm.$el.querySelector('a').href).toContain(props.confidentialIssueDocsPath);
+ });
+ });
+
+ describe('isLocked and isConfidential', () => {
+ it('should render locked and confidential issue warning information', () => {
+ const vm = mountComponent(IssueWarning, {
+ isLocked: true,
+ isConfidential: true,
+ });
+
+ expect(vm.$el.querySelector('.icon')).toBeFalsy();
+ expect(formatWarning(vm.$el.querySelector('span').textContent)).toEqual(
+ "This issue is confidential and locked. People without permission will never get a notification and won't be able to comment.",
+ );
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js b/spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js
new file mode 100644
index 00000000000..e43d5301a50
--- /dev/null
+++ b/spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js
@@ -0,0 +1,198 @@
+import Vue from 'vue';
+import { formatDate } from '~/lib/utils/datetime_utility';
+import { mount, createLocalVue } from '@vue/test-utils';
+import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
+import {
+ defaultAssignees,
+ defaultMilestone,
+} from '../../../../javascripts/vue_shared/components/issue/related_issuable_mock_data';
+
+describe('RelatedIssuableItem', () => {
+ let wrapper;
+ const props = {
+ idKey: 1,
+ displayReference: 'gitlab-org/gitlab-test#1',
+ pathIdSeparator: '#',
+ path: `${gl.TEST_HOST}/path`,
+ title: 'title',
+ confidential: true,
+ dueDate: '1990-12-31',
+ weight: 10,
+ createdAt: '2018-12-01T00:00:00.00Z',
+ milestone: defaultMilestone,
+ assignees: defaultAssignees,
+ eventNamespace: 'relatedIssue',
+ };
+ const slots = {
+ dueDate: '<div class="js-due-date-slot"></div>',
+ weight: '<div class="js-weight-slot"></div>',
+ };
+
+ beforeEach(() => {
+ const localVue = createLocalVue();
+
+ wrapper = mount(localVue.extend(RelatedIssuableItem), {
+ localVue,
+ slots,
+ sync: false,
+ propsData: props,
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('contains issuable-info-container class when canReorder is false', () => {
+ expect(wrapper.props('canReorder')).toBe(false);
+ expect(wrapper.find('.issuable-info-container').exists()).toBe(true);
+ });
+
+ it('does not render token state', () => {
+ expect(wrapper.find('.text-secondary svg').exists()).toBe(false);
+ });
+
+ it('does not render remove button', () => {
+ expect(wrapper.find({ ref: 'removeButton' }).exists()).toBe(false);
+ });
+
+ describe('token title', () => {
+ it('links to computedPath', () => {
+ expect(wrapper.find('.item-title a').attributes('href')).toEqual(wrapper.props('path'));
+ });
+
+ it('renders confidential icon', () => {
+ expect(wrapper.find('.confidential-icon').exists()).toBe(true);
+ });
+
+ it('renders title', () => {
+ expect(wrapper.find('.item-title a').text()).toEqual(props.title);
+ });
+ });
+
+ describe('token state', () => {
+ let tokenState;
+
+ beforeEach(done => {
+ wrapper.setProps({ state: 'opened' });
+
+ Vue.nextTick(() => {
+ tokenState = wrapper.find('.issue-token-state-icon-open');
+
+ done();
+ });
+ });
+
+ it('renders if hasState', () => {
+ expect(tokenState.exists()).toBe(true);
+ });
+
+ it('renders state title', () => {
+ const stateTitle = tokenState.attributes('data-original-title');
+ const formatedCreateDate = formatDate(props.createdAt);
+
+ expect(stateTitle).toContain('<span class="bold">Opened</span>');
+
+ expect(stateTitle).toContain(`<span class="text-tertiary">${formatedCreateDate}</span>`);
+ });
+
+ it('renders aria label', () => {
+ expect(tokenState.attributes('aria-label')).toEqual('opened');
+ });
+
+ it('renders open icon when open state', () => {
+ expect(tokenState.classes('issue-token-state-icon-open')).toBe(true);
+ });
+
+ it('renders close icon when close state', done => {
+ wrapper.setProps({
+ state: 'closed',
+ closedAt: '2018-12-01T00:00:00.00Z',
+ });
+
+ Vue.nextTick(() => {
+ expect(tokenState.classes('issue-token-state-icon-closed')).toBe(true);
+
+ done();
+ });
+ });
+ });
+
+ describe('token metadata', () => {
+ let tokenMetadata;
+
+ beforeEach(done => {
+ Vue.nextTick(() => {
+ tokenMetadata = wrapper.find('.item-meta');
+
+ done();
+ });
+ });
+
+ it('renders item path and ID', () => {
+ const pathAndID = tokenMetadata.find('.item-path-id').text();
+
+ expect(pathAndID).toContain('gitlab-org/gitlab-test');
+ expect(pathAndID).toContain('#1');
+ });
+
+ it('renders milestone icon and name', () => {
+ const milestoneIcon = tokenMetadata.find('.item-milestone svg use');
+ const milestoneTitle = tokenMetadata.find('.item-milestone .milestone-title');
+
+ expect(milestoneIcon.attributes('href')).toContain('clock');
+ expect(milestoneTitle.text()).toContain('Milestone title');
+ });
+
+ it('renders due date component', () => {
+ expect(tokenMetadata.find('.js-due-date-slot').exists()).toBe(true);
+ });
+
+ it('renders weight component', () => {
+ expect(tokenMetadata.find('.js-weight-slot').exists()).toBe(true);
+ });
+ });
+
+ describe('token assignees', () => {
+ it('renders assignees avatars', () => {
+ expect(wrapper.findAll('.item-assignees .user-avatar-link').length).toBe(2);
+ expect(wrapper.find('.item-assignees .avatar-counter').text()).toContain('+2');
+ });
+ });
+
+ describe('remove button', () => {
+ let removeBtn;
+
+ beforeEach(done => {
+ wrapper.setProps({ canRemove: true });
+ Vue.nextTick(() => {
+ removeBtn = wrapper.find({ ref: 'removeButton' });
+
+ done();
+ });
+ });
+
+ it('renders if canRemove', () => {
+ expect(removeBtn.exists()).toBe(true);
+ });
+
+ it('renders disabled button when removeDisabled', done => {
+ wrapper.vm.removeDisabled = true;
+
+ Vue.nextTick(() => {
+ expect(removeBtn.attributes('disabled')).toEqual('disabled');
+
+ done();
+ });
+ });
+
+ it('triggers onRemoveRequest when clicked', () => {
+ removeBtn.trigger('click');
+
+ const { relatedIssueRemoveRequest } = wrapper.emitted();
+
+ expect(relatedIssueRemoveRequest.length).toBe(1);
+ expect(relatedIssueRemoveRequest[0]).toEqual([props.idKey]);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js b/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js
new file mode 100644
index 00000000000..3b6f67457ad
--- /dev/null
+++ b/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js
@@ -0,0 +1,103 @@
+import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import SuggestionDiffHeader from '~/vue_shared/components/markdown/suggestion_diff_header.vue';
+
+const localVue = createLocalVue();
+
+const DEFAULT_PROPS = {
+ canApply: true,
+ isApplied: false,
+ helpPagePath: 'path_to_docs',
+};
+
+describe('Suggestion Diff component', () => {
+ let wrapper;
+
+ const createComponent = props => {
+ wrapper = shallowMount(localVue.extend(SuggestionDiffHeader), {
+ propsData: {
+ ...DEFAULT_PROPS,
+ ...props,
+ },
+ localVue,
+ sync: false,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findApplyButton = () => wrapper.find('.qa-apply-btn');
+ const findHeader = () => wrapper.find('.qa-suggestion-diff-header');
+ const findHelpButton = () => wrapper.find('.js-help-btn');
+ const findLoading = () => wrapper.find(GlLoadingIcon);
+
+ it('renders a suggestion header', () => {
+ createComponent();
+
+ const header = findHeader();
+
+ expect(header.exists()).toBe(true);
+ expect(header.html().includes('Suggested change')).toBe(true);
+ });
+
+ it('renders a help button', () => {
+ createComponent();
+
+ expect(findHelpButton().exists()).toBe(true);
+ });
+
+ it('renders an apply button', () => {
+ createComponent();
+
+ const applyBtn = findApplyButton();
+
+ expect(applyBtn.exists()).toBe(true);
+ expect(applyBtn.html().includes('Apply suggestion')).toBe(true);
+ });
+
+ it('does not render an apply button if `canApply` is set to false', () => {
+ createComponent({ canApply: false });
+
+ expect(findApplyButton().exists()).toBe(false);
+ });
+
+ describe('when apply suggestion is clicked', () => {
+ beforeEach(done => {
+ createComponent();
+
+ findApplyButton().vm.$emit('click');
+
+ wrapper.vm.$nextTick(done);
+ });
+
+ it('emits apply', () => {
+ expect(wrapper.emittedByOrder()).toEqual([{ name: 'apply', args: [expect.any(Function)] }]);
+ });
+
+ it('hides apply button', () => {
+ expect(findApplyButton().exists()).toBe(false);
+ });
+
+ it('shows loading', () => {
+ expect(findLoading().exists()).toBe(true);
+ expect(wrapper.text()).toContain('Applying suggestion');
+ });
+
+ it('when callback of apply is called, hides loading', done => {
+ const [callback] = wrapper.emitted().apply[0];
+
+ callback();
+
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ expect(findApplyButton().exists()).toBe(true);
+ expect(findLoading().exists()).toBe(false);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/modal_copy_button_spec.js b/spec/frontend/vue_shared/components/modal_copy_button_spec.js
new file mode 100644
index 00000000000..f1943861523
--- /dev/null
+++ b/spec/frontend/vue_shared/components/modal_copy_button_spec.js
@@ -0,0 +1,40 @@
+import Vue from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import modalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
+
+describe('modal copy button', () => {
+ const Component = Vue.extend(modalCopyButton);
+ let wrapper;
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ beforeEach(() => {
+ wrapper = shallowMount(Component, {
+ propsData: {
+ text: 'copy me',
+ title: 'Copy this value into Clipboard!',
+ },
+ });
+ });
+
+ describe('clipboard', () => {
+ it('should fire a `success` event on click', () => {
+ document.execCommand = jest.fn(() => true);
+ window.getSelection = jest.fn(() => ({
+ toString: jest.fn(() => 'test'),
+ removeAllRanges: jest.fn(),
+ }));
+ wrapper.trigger('click');
+ expect(wrapper.emitted().success).not.toBeEmpty();
+ expect(document.execCommand).toHaveBeenCalledWith('copy');
+ });
+ it("should propagate the clipboard error event if execCommand doesn't work", () => {
+ document.execCommand = jest.fn(() => false);
+ wrapper.trigger('click');
+ expect(wrapper.emitted().error).not.toBeEmpty();
+ expect(document.execCommand).toHaveBeenCalledWith('copy');
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/notes/placeholder_note_spec.js b/spec/frontend/vue_shared/components/notes/placeholder_note_spec.js
new file mode 100644
index 00000000000..eafff7f681e
--- /dev/null
+++ b/spec/frontend/vue_shared/components/notes/placeholder_note_spec.js
@@ -0,0 +1,51 @@
+import Vue from 'vue';
+import issuePlaceholderNote from '~/vue_shared/components/notes/placeholder_note.vue';
+import createStore from '~/notes/stores';
+import { userDataMock } from '../../../../javascripts/notes/mock_data';
+
+describe('issue placeholder system note component', () => {
+ let store;
+ let vm;
+
+ beforeEach(() => {
+ const Component = Vue.extend(issuePlaceholderNote);
+ store = createStore();
+ store.dispatch('setUserData', userDataMock);
+ vm = new Component({
+ store,
+ propsData: { note: { body: 'Foo' } },
+ }).$mount();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('user information', () => {
+ it('should render user avatar with link', () => {
+ expect(vm.$el.querySelector('.user-avatar-link').getAttribute('href')).toEqual(
+ userDataMock.path,
+ );
+
+ expect(vm.$el.querySelector('.user-avatar-link img').getAttribute('src')).toEqual(
+ `${userDataMock.avatar_url}?width=40`,
+ );
+ });
+ });
+
+ describe('note content', () => {
+ it('should render note header information', () => {
+ expect(vm.$el.querySelector('.note-header-info a').getAttribute('href')).toEqual(
+ userDataMock.path,
+ );
+
+ expect(
+ vm.$el.querySelector('.note-header-info .note-headline-light').textContent.trim(),
+ ).toEqual(`@${userDataMock.username}`);
+ });
+
+ it('should render note body', () => {
+ expect(vm.$el.querySelector('.note-text p').textContent.trim()).toEqual('Foo');
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/notes/placeholder_system_note_spec.js b/spec/frontend/vue_shared/components/notes/placeholder_system_note_spec.js
new file mode 100644
index 00000000000..976e38c15ee
--- /dev/null
+++ b/spec/frontend/vue_shared/components/notes/placeholder_system_note_spec.js
@@ -0,0 +1,27 @@
+import Vue from 'vue';
+import placeholderSystemNote from '~/vue_shared/components/notes/placeholder_system_note.vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
+
+describe('placeholder system note component', () => {
+ let PlaceholderSystemNote;
+ let vm;
+
+ beforeEach(() => {
+ PlaceholderSystemNote = Vue.extend(placeholderSystemNote);
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('should render system note placeholder with plain text', () => {
+ vm = mountComponent(PlaceholderSystemNote, {
+ note: { body: 'This is a placeholder' },
+ });
+
+ expect(vm.$el.tagName).toEqual('LI');
+ expect(vm.$el.querySelector('.timeline-content em').textContent.trim()).toEqual(
+ 'This is a placeholder',
+ );
+ });
+});
diff --git a/spec/frontend/vue_shared/components/notes/system_note_spec.js b/spec/frontend/vue_shared/components/notes/system_note_spec.js
new file mode 100644
index 00000000000..dc66150ab8d
--- /dev/null
+++ b/spec/frontend/vue_shared/components/notes/system_note_spec.js
@@ -0,0 +1,66 @@
+import Vue from 'vue';
+import issueSystemNote from '~/vue_shared/components/notes/system_note.vue';
+import createStore from '~/notes/stores';
+import initMRPopovers from '~/mr_popover/index';
+
+jest.mock('~/mr_popover/index', () => jest.fn());
+
+describe('system note component', () => {
+ let vm;
+ let props;
+
+ beforeEach(() => {
+ props = {
+ note: {
+ id: '1424',
+ author: {
+ id: 1,
+ name: 'Root',
+ username: 'root',
+ state: 'active',
+ avatar_url: 'path',
+ path: '/root',
+ },
+ note_html: '<p dir="auto">closed</p>',
+ system_note_icon_name: 'status_closed',
+ created_at: '2017-08-02T10:51:58.559Z',
+ },
+ };
+
+ const store = createStore();
+ store.dispatch('setTargetNoteHash', `note_${props.note.id}`);
+
+ const Component = Vue.extend(issueSystemNote);
+ vm = new Component({
+ store,
+ propsData: props,
+ }).$mount();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('should render a list item with correct id', () => {
+ expect(vm.$el.getAttribute('id')).toEqual(`note_${props.note.id}`);
+ });
+
+ it('should render target class is note is target note', () => {
+ expect(vm.$el.classList).toContain('target');
+ });
+
+ it('should render svg icon', () => {
+ expect(vm.$el.querySelector('.timeline-icon svg')).toBeDefined();
+ });
+
+ // Redcarpet Markdown renderer wraps text in `<p>` tags
+ // we need to strip them because they break layout of commit lists in system notes:
+ // https://gitlab.com/gitlab-org/gitlab-ce/uploads/b07a10670919254f0220d3ff5c1aa110/jqzI.png
+ it('removes wrapping paragraph from note HTML', () => {
+ expect(vm.$el.querySelector('.system-note-message').innerHTML).toEqual('<span>closed</span>');
+ });
+
+ it('should initMRPopovers onMount', () => {
+ expect(initMRPopovers).toHaveBeenCalled();
+ });
+});
diff --git a/spec/frontend/vue_shared/components/pagination_links_spec.js b/spec/frontend/vue_shared/components/pagination_links_spec.js
index d0cb3731050..efa5825d92f 100644
--- a/spec/frontend/vue_shared/components/pagination_links_spec.js
+++ b/spec/frontend/vue_shared/components/pagination_links_spec.js
@@ -1,59 +1,77 @@
-import Vue from 'vue';
+import { mount, createLocalVue } from '@vue/test-utils';
+import { GlPagination } from '@gitlab/ui';
import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
-import { s__ } from '~/locale';
-import mountComponent from '../../helpers/vue_mount_component_helper';
+import {
+ PREV,
+ NEXT,
+ LABEL_FIRST_PAGE,
+ LABEL_PREV_PAGE,
+ LABEL_NEXT_PAGE,
+ LABEL_LAST_PAGE,
+} from '~/vue_shared/components/pagination/constants';
+
+const localVue = createLocalVue();
describe('Pagination links component', () => {
- const paginationLinksComponent = Vue.extend(PaginationLinks);
- const change = page => page;
const pageInfo = {
page: 3,
perPage: 5,
total: 30,
};
const translations = {
- firstText: s__('Pagination|« First'),
- prevText: s__('Pagination|Prev'),
- nextText: s__('Pagination|Next'),
- lastText: s__('Pagination|Last »'),
+ prevText: PREV,
+ nextText: NEXT,
+ labelFirstPage: LABEL_FIRST_PAGE,
+ labelPrevPage: LABEL_PREV_PAGE,
+ labelNextPage: LABEL_NEXT_PAGE,
+ labelLastPage: LABEL_LAST_PAGE,
};
- let paginationLinks;
+ let wrapper;
let glPagination;
- let destinationComponent;
+ let changeMock;
- beforeEach(() => {
- paginationLinks = mountComponent(paginationLinksComponent, {
- change,
- pageInfo,
+ const createComponent = () => {
+ changeMock = jest.fn();
+ wrapper = mount(PaginationLinks, {
+ propsData: {
+ change: changeMock,
+ pageInfo,
+ },
+ localVue,
+ sync: false,
});
- [glPagination] = paginationLinks.$children;
- [destinationComponent] = glPagination.$children;
+ };
+
+ beforeEach(() => {
+ createComponent();
+ glPagination = wrapper.find(GlPagination);
});
afterEach(() => {
- paginationLinks.$destroy();
+ wrapper.destroy();
});
it('should provide translated text to GitLab UI pagination', () => {
Object.entries(translations).forEach(entry => {
- expect(destinationComponent[entry[0]]).toBe(entry[1]);
+ expect(glPagination.vm[entry[0]]).toBe(entry[1]);
});
});
- it('should pass change to GitLab UI pagination', () => {
- expect(Object.is(glPagination.change, change)).toBe(true);
+ it('should call change when page changes', () => {
+ wrapper.find('a').trigger('click');
+ expect(changeMock).toHaveBeenCalled();
});
it('should pass page from pageInfo to GitLab UI pagination', () => {
- expect(destinationComponent.value).toBe(pageInfo.page);
+ expect(glPagination.vm.value).toBe(pageInfo.page);
});
it('should pass per page from pageInfo to GitLab UI pagination', () => {
- expect(destinationComponent.perPage).toBe(pageInfo.perPage);
+ expect(glPagination.vm.perPage).toBe(pageInfo.perPage);
});
it('should pass total items from pageInfo to GitLab UI pagination', () => {
- expect(destinationComponent.totalRows).toBe(pageInfo.total);
+ expect(glPagination.vm.totalItems).toBe(pageInfo.total);
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js b/spec/frontend/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js
new file mode 100644
index 00000000000..691ebe43d6b
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js
@@ -0,0 +1,36 @@
+import Vue from 'vue';
+import collapsedCalendarIcon from '~/vue_shared/components/sidebar/collapsed_calendar_icon.vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
+
+describe('collapsedCalendarIcon', () => {
+ let vm;
+ beforeEach(() => {
+ const CollapsedCalendarIcon = Vue.extend(collapsedCalendarIcon);
+ vm = mountComponent(CollapsedCalendarIcon, {
+ containerClass: 'test-class',
+ text: 'text',
+ showIcon: false,
+ });
+ });
+
+ it('should add class to container', () => {
+ expect(vm.$el.classList.contains('test-class')).toEqual(true);
+ });
+
+ it('should hide calendar icon if showIcon', () => {
+ expect(vm.$el.querySelector('.fa-calendar')).toBeNull();
+ });
+
+ it('should render text', () => {
+ expect(vm.$el.querySelector('span').innerText.trim()).toEqual('text');
+ });
+
+ it('should emit click event when container is clicked', () => {
+ const click = jest.fn();
+ vm.$on('click', click);
+
+ vm.$el.click();
+
+ expect(click).toHaveBeenCalled();
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js b/spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
new file mode 100644
index 00000000000..062ebfa01c9
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
@@ -0,0 +1,86 @@
+import Vue from 'vue';
+import collapsedGroupedDatePicker from '~/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
+
+describe('collapsedGroupedDatePicker', () => {
+ let vm;
+ beforeEach(() => {
+ const CollapsedGroupedDatePicker = Vue.extend(collapsedGroupedDatePicker);
+ vm = mountComponent(CollapsedGroupedDatePicker, {
+ showToggleSidebar: true,
+ });
+ });
+
+ describe('toggleCollapse events', () => {
+ beforeEach(done => {
+ jest.spyOn(vm, 'toggleSidebar').mockImplementation(() => {});
+ vm.minDate = new Date('07/17/2016');
+ Vue.nextTick(done);
+ });
+
+ it('should emit when collapsed-calendar-icon is clicked', () => {
+ vm.$el.querySelector('.sidebar-collapsed-icon').click();
+
+ expect(vm.toggleSidebar).toHaveBeenCalled();
+ });
+ });
+
+ describe('minDate and maxDate', () => {
+ beforeEach(done => {
+ vm.minDate = new Date('07/17/2016');
+ vm.maxDate = new Date('07/17/2017');
+ Vue.nextTick(done);
+ });
+
+ it('should render both collapsed-calendar-icon', () => {
+ const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
+
+ expect(icons.length).toEqual(2);
+ expect(icons[0].innerText.trim()).toEqual('Jul 17 2016');
+ expect(icons[1].innerText.trim()).toEqual('Jul 17 2017');
+ });
+ });
+
+ describe('minDate', () => {
+ beforeEach(done => {
+ vm.minDate = new Date('07/17/2016');
+ Vue.nextTick(done);
+ });
+
+ it('should render minDate in collapsed-calendar-icon', () => {
+ const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
+
+ expect(icons.length).toEqual(1);
+ expect(icons[0].innerText.trim()).toEqual('From Jul 17 2016');
+ });
+ });
+
+ describe('maxDate', () => {
+ beforeEach(done => {
+ vm.maxDate = new Date('07/17/2017');
+ Vue.nextTick(done);
+ });
+
+ it('should render maxDate in collapsed-calendar-icon', () => {
+ const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
+
+ expect(icons.length).toEqual(1);
+ expect(icons[0].innerText.trim()).toEqual('Until Jul 17 2017');
+ });
+ });
+
+ describe('no dates', () => {
+ it('should render None', () => {
+ const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
+
+ expect(icons.length).toEqual(1);
+ expect(icons[0].innerText.trim()).toEqual('None');
+ });
+
+ it('should have tooltip as `Start and due date`', () => {
+ const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
+
+ expect(icons[0].dataset.originalTitle).toBe('Start and due date');
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js b/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js
new file mode 100644
index 00000000000..5e2bca6efc9
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js
@@ -0,0 +1,121 @@
+import Vue from 'vue';
+import sidebarDatePicker from '~/vue_shared/components/sidebar/date_picker.vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
+
+describe('sidebarDatePicker', () => {
+ let vm;
+ beforeEach(() => {
+ const SidebarDatePicker = Vue.extend(sidebarDatePicker);
+ vm = mountComponent(SidebarDatePicker, {
+ label: 'label',
+ isLoading: true,
+ });
+ });
+
+ it('should emit toggleCollapse when collapsed toggle sidebar is clicked', () => {
+ const toggleCollapse = jest.fn();
+ vm.$on('toggleCollapse', toggleCollapse);
+
+ vm.$el.querySelector('.issuable-sidebar-header .gutter-toggle').click();
+
+ expect(toggleCollapse).toHaveBeenCalled();
+ });
+
+ it('should render collapsed-calendar-icon', () => {
+ expect(vm.$el.querySelector('.sidebar-collapsed-icon')).toBeDefined();
+ });
+
+ it('should render label', () => {
+ expect(vm.$el.querySelector('.title').innerText.trim()).toEqual('label');
+ });
+
+ it('should render loading-icon when isLoading', () => {
+ expect(vm.$el.querySelector('.fa-spin')).toBeDefined();
+ });
+
+ it('should render value when not editing', () => {
+ expect(vm.$el.querySelector('.value-content')).toBeDefined();
+ });
+
+ it('should render None if there is no selectedDate', () => {
+ expect(vm.$el.querySelector('.value-content span').innerText.trim()).toEqual('None');
+ });
+
+ it('should render date-picker when editing', done => {
+ vm.editing = true;
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelector('.pika-label')).toBeDefined();
+ done();
+ });
+ });
+
+ describe('editable', () => {
+ beforeEach(done => {
+ vm.editable = true;
+ Vue.nextTick(done);
+ });
+
+ it('should render edit button', () => {
+ expect(vm.$el.querySelector('.title .btn-blank').innerText.trim()).toEqual('Edit');
+ });
+
+ it('should enable editing when edit button is clicked', done => {
+ vm.isLoading = false;
+ Vue.nextTick(() => {
+ vm.$el.querySelector('.title .btn-blank').click();
+
+ expect(vm.editing).toEqual(true);
+ done();
+ });
+ });
+ });
+
+ it('should render date if selectedDate', done => {
+ vm.selectedDate = new Date('07/07/2017');
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelector('.value-content strong').innerText.trim()).toEqual('Jul 7, 2017');
+ done();
+ });
+ });
+
+ describe('selectedDate and editable', () => {
+ beforeEach(done => {
+ vm.selectedDate = new Date('07/07/2017');
+ vm.editable = true;
+ Vue.nextTick(done);
+ });
+
+ it('should render remove button if selectedDate and editable', () => {
+ expect(vm.$el.querySelector('.value-content .btn-blank').innerText.trim()).toEqual('remove');
+ });
+
+ it('should emit saveDate when remove button is clicked', () => {
+ const saveDate = jest.fn();
+ vm.$on('saveDate', saveDate);
+
+ vm.$el.querySelector('.value-content .btn-blank').click();
+
+ expect(saveDate).toHaveBeenCalled();
+ });
+ });
+
+ describe('showToggleSidebar', () => {
+ beforeEach(done => {
+ vm.showToggleSidebar = true;
+ Vue.nextTick(done);
+ });
+
+ it('should render toggle-sidebar when showToggleSidebar', () => {
+ expect(vm.$el.querySelector('.title .gutter-toggle')).toBeDefined();
+ });
+
+ it('should emit toggleCollapse when toggle sidebar is clicked', () => {
+ const toggleCollapse = jest.fn();
+ vm.$on('toggleCollapse', toggleCollapse);
+
+ vm.$el.querySelector('.title .gutter-toggle').click();
+
+ expect(toggleCollapse).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/base_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/base_spec.js
new file mode 100644
index 00000000000..6aee616c324
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/base_spec.js
@@ -0,0 +1,134 @@
+import Vue from 'vue';
+
+import LabelsSelect from '~/labels_select';
+import baseComponent from '~/vue_shared/components/sidebar/labels_select/base.vue';
+
+import { mount } from '@vue/test-utils';
+import {
+ mockConfig,
+ mockLabels,
+} from '../../../../../javascripts/vue_shared/components/sidebar/labels_select/mock_data';
+
+const createComponent = (config = mockConfig) => {
+ const Component = Vue.extend(baseComponent);
+
+ return mount(Component, {
+ propsData: config,
+ sync: false,
+ });
+};
+
+describe('BaseComponent', () => {
+ let wrapper;
+ let vm;
+
+ beforeEach(done => {
+ wrapper = createComponent();
+
+ ({ vm } = wrapper);
+
+ Vue.nextTick(done);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('computed', () => {
+ describe('hiddenInputName', () => {
+ it('returns correct string when showCreate prop is `true`', () => {
+ expect(vm.hiddenInputName).toBe('issue[label_names][]');
+ });
+
+ it('returns correct string when showCreate prop is `false`', () => {
+ wrapper.setProps({ showCreate: false });
+
+ expect(vm.hiddenInputName).toBe('label_id[]');
+ });
+ });
+
+ describe('createLabelTitle', () => {
+ it('returns `Create project label` when `isProject` prop is true', () => {
+ expect(vm.createLabelTitle).toBe('Create project label');
+ });
+
+ it('return `Create group label` when `isProject` prop is false', () => {
+ wrapper.setProps({ isProject: false });
+
+ expect(vm.createLabelTitle).toBe('Create group label');
+ });
+ });
+
+ describe('manageLabelsTitle', () => {
+ it('returns `Manage project labels` when `isProject` prop is true', () => {
+ expect(vm.manageLabelsTitle).toBe('Manage project labels');
+ });
+
+ it('return `Manage group labels` when `isProject` prop is false', () => {
+ wrapper.setProps({ isProject: false });
+
+ expect(vm.manageLabelsTitle).toBe('Manage group labels');
+ });
+ });
+ });
+
+ describe('methods', () => {
+ describe('handleClick', () => {
+ it('emits onLabelClick event with label and list of labels as params', () => {
+ jest.spyOn(vm, '$emit').mockImplementation(() => {});
+ vm.handleClick(mockLabels[0]);
+
+ expect(vm.$emit).toHaveBeenCalledWith('onLabelClick', mockLabels[0]);
+ });
+ });
+
+ describe('handleCollapsedValueClick', () => {
+ it('emits toggleCollapse event on component', () => {
+ jest.spyOn(vm, '$emit').mockImplementation(() => {});
+ vm.handleCollapsedValueClick();
+
+ expect(vm.$emit).toHaveBeenCalledWith('toggleCollapse');
+ });
+ });
+
+ describe('handleDropdownHidden', () => {
+ it('emits onDropdownClose event on component', () => {
+ jest.spyOn(vm, '$emit').mockImplementation(() => {});
+ vm.handleDropdownHidden();
+
+ expect(vm.$emit).toHaveBeenCalledWith('onDropdownClose');
+ });
+ });
+ });
+
+ describe('mounted', () => {
+ it('creates LabelsSelect object and assigns it to `labelsDropdon` as prop', () => {
+ expect(vm.labelsDropdown instanceof LabelsSelect).toBe(true);
+ });
+ });
+
+ describe('template', () => {
+ it('renders component container element with classes `block labels`', () => {
+ expect(vm.$el.classList.contains('block')).toBe(true);
+ expect(vm.$el.classList.contains('labels')).toBe(true);
+ });
+
+ it('renders `.selectbox` element', () => {
+ expect(vm.$el.querySelector('.selectbox')).not.toBeNull();
+ expect(vm.$el.querySelector('.selectbox').getAttribute('style')).toBe('display: none;');
+ });
+
+ it('renders `.dropdown` element', () => {
+ expect(vm.$el.querySelector('.dropdown')).not.toBeNull();
+ });
+
+ it('renders `.dropdown-menu` element', () => {
+ const dropdownMenuEl = vm.$el.querySelector('.dropdown-menu');
+
+ expect(dropdownMenuEl).not.toBeNull();
+ expect(dropdownMenuEl.querySelector('.dropdown-page-one')).not.toBeNull();
+ expect(dropdownMenuEl.querySelector('.dropdown-content')).not.toBeNull();
+ expect(dropdownMenuEl.querySelector('.dropdown-loading')).not.toBeNull();
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js
new file mode 100644
index 00000000000..bb33dc6ea0f
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js
@@ -0,0 +1,97 @@
+import Vue from 'vue';
+
+import dropdownButtonComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_button.vue';
+
+import mountComponent from 'helpers/vue_mount_component_helper';
+import {
+ mockConfig,
+ mockLabels,
+} from '../../../../../javascripts/vue_shared/components/sidebar/labels_select/mock_data';
+
+const componentConfig = Object.assign({}, mockConfig, {
+ fieldName: 'label_id[]',
+ labels: mockLabels,
+ showExtraOptions: false,
+});
+
+const createComponent = (config = componentConfig) => {
+ const Component = Vue.extend(dropdownButtonComponent);
+
+ return mountComponent(Component, config);
+};
+
+describe('DropdownButtonComponent', () => {
+ let vm;
+
+ beforeEach(() => {
+ vm = createComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('computed', () => {
+ describe('dropdownToggleText', () => {
+ it('returns text as `Label` when `labels` prop is empty array', () => {
+ const mockEmptyLabels = Object.assign({}, componentConfig, { labels: [] });
+ const vmEmptyLabels = createComponent(mockEmptyLabels);
+
+ expect(vmEmptyLabels.dropdownToggleText).toBe('Label');
+ vmEmptyLabels.$destroy();
+ });
+
+ it('returns first label name with remaining label count when `labels` prop has more than one item', () => {
+ const mockMoreLabels = Object.assign({}, componentConfig, {
+ labels: mockLabels.concat(mockLabels),
+ });
+ const vmMoreLabels = createComponent(mockMoreLabels);
+
+ expect(vmMoreLabels.dropdownToggleText).toBe(
+ `Foo Label +${mockMoreLabels.labels.length - 1} more`,
+ );
+ vmMoreLabels.$destroy();
+ });
+
+ it('returns first label name when `labels` prop has only one item present', () => {
+ const singleLabel = Object.assign({}, componentConfig, {
+ labels: [mockLabels[0]],
+ });
+ const vmSingleLabel = createComponent(singleLabel);
+
+ expect(vmSingleLabel.dropdownToggleText).toBe(mockLabels[0].title);
+
+ vmSingleLabel.$destroy();
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('renders component container element of type `button`', () => {
+ expect(vm.$el.nodeName).toBe('BUTTON');
+ });
+
+ it('renders component container element with required data attributes', () => {
+ expect(vm.$el.dataset.abilityName).toBe(vm.abilityName);
+ expect(vm.$el.dataset.fieldName).toBe(vm.fieldName);
+ expect(vm.$el.dataset.issueUpdate).toBe(vm.updatePath);
+ expect(vm.$el.dataset.labels).toBe(vm.labelsPath);
+ expect(vm.$el.dataset.namespacePath).toBe(vm.namespace);
+ expect(vm.$el.dataset.showAny).not.toBeDefined();
+ });
+
+ it('renders dropdown toggle text element', () => {
+ const dropdownToggleTextEl = vm.$el.querySelector('.dropdown-toggle-text');
+
+ expect(dropdownToggleTextEl).not.toBeNull();
+ expect(dropdownToggleTextEl.innerText.trim()).toBe('Foo Label +1 more');
+ });
+
+ it('renders dropdown button icon', () => {
+ const dropdownIconEl = vm.$el.querySelector('i.fa');
+
+ expect(dropdownIconEl).not.toBeNull();
+ expect(dropdownIconEl.classList.contains('fa-chevron-down')).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js
new file mode 100644
index 00000000000..1c25d42682c
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js
@@ -0,0 +1,107 @@
+import Vue from 'vue';
+
+import dropdownCreateLabelComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue';
+
+import mountComponent from 'helpers/vue_mount_component_helper';
+import { mockSuggestedColors } from '../../../../../javascripts/vue_shared/components/sidebar/labels_select/mock_data';
+
+const createComponent = headerTitle => {
+ const Component = Vue.extend(dropdownCreateLabelComponent);
+
+ return mountComponent(Component, {
+ headerTitle,
+ });
+};
+
+describe('DropdownCreateLabelComponent', () => {
+ let vm;
+
+ beforeEach(() => {
+ gon.suggested_label_colors = mockSuggestedColors;
+ vm = createComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('created', () => {
+ it('initializes `suggestedColors` prop on component from `gon.suggested_color_labels` object', () => {
+ expect(vm.suggestedColors.length).toBe(mockSuggestedColors.length);
+ });
+ });
+
+ describe('template', () => {
+ it('renders component container element with classes `dropdown-page-two dropdown-new-label`', () => {
+ expect(vm.$el.classList.contains('dropdown-page-two', 'dropdown-new-label')).toBe(true);
+ });
+
+ it('renders `Go back` button on component header', () => {
+ const backButtonEl = vm.$el.querySelector(
+ '.dropdown-title button.dropdown-title-button.dropdown-menu-back',
+ );
+
+ expect(backButtonEl).not.toBe(null);
+ expect(backButtonEl.querySelector('.fa-arrow-left')).not.toBe(null);
+ });
+
+ it('renders component header element as `Create new label` when `headerTitle` prop is not provided', () => {
+ const headerEl = vm.$el.querySelector('.dropdown-title');
+
+ expect(headerEl.innerText.trim()).toContain('Create new label');
+ });
+
+ it('renders component header element with value of `headerTitle` prop', () => {
+ const headerTitle = 'Create project label';
+ const vmWithHeaderTitle = createComponent(headerTitle);
+ const headerEl = vmWithHeaderTitle.$el.querySelector('.dropdown-title');
+
+ expect(headerEl.innerText.trim()).toContain(headerTitle);
+ vmWithHeaderTitle.$destroy();
+ });
+
+ it('renders `Close` button on component header', () => {
+ const closeButtonEl = vm.$el.querySelector(
+ '.dropdown-title button.dropdown-title-button.dropdown-menu-close',
+ );
+
+ expect(closeButtonEl).not.toBe(null);
+ expect(closeButtonEl.querySelector('.fa-times.dropdown-menu-close-icon')).not.toBe(null);
+ });
+
+ it('renders `Name new label` input element', () => {
+ expect(vm.$el.querySelector('.dropdown-labels-error.js-label-error')).not.toBe(null);
+ expect(vm.$el.querySelector('input#new_label_name.default-dropdown-input')).not.toBe(null);
+ });
+
+ it('renders suggested colors list elements', () => {
+ const colorsListContainerEl = vm.$el.querySelector('.suggest-colors.suggest-colors-dropdown');
+
+ expect(colorsListContainerEl).not.toBe(null);
+ expect(colorsListContainerEl.querySelectorAll('a').length).toBe(mockSuggestedColors.length);
+
+ const colorItemEl = colorsListContainerEl.querySelectorAll('a')[0];
+
+ expect(colorItemEl.dataset.color).toBe(vm.suggestedColors[0]);
+ expect(colorItemEl.getAttribute('style')).toBe('background-color: rgb(0, 51, 204);');
+ });
+
+ it('renders color input element', () => {
+ expect(vm.$el.querySelector('.dropdown-label-color-input')).not.toBe(null);
+ expect(
+ vm.$el.querySelector('.dropdown-label-color-preview.js-dropdown-label-color-preview'),
+ ).not.toBe(null);
+
+ expect(vm.$el.querySelector('input#new_label_color.default-dropdown-input')).not.toBe(null);
+ });
+
+ it('renders component action buttons', () => {
+ const createBtnEl = vm.$el.querySelector('button.js-new-label-btn');
+ const cancelBtnEl = vm.$el.querySelector('button.js-cancel-label-btn');
+
+ expect(createBtnEl).not.toBe(null);
+ expect(createBtnEl.innerText.trim()).toBe('Create');
+ expect(cancelBtnEl.innerText.trim()).toBe('Cancel');
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js
new file mode 100644
index 00000000000..989901a0012
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js
@@ -0,0 +1,75 @@
+import Vue from 'vue';
+
+import dropdownFooterComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_footer.vue';
+
+import mountComponent from 'helpers/vue_mount_component_helper';
+import { mockConfig } from '../../../../../javascripts/vue_shared/components/sidebar/labels_select/mock_data';
+
+const createComponent = (
+ labelsWebUrl = mockConfig.labelsWebUrl,
+ createLabelTitle,
+ manageLabelsTitle,
+) => {
+ const Component = Vue.extend(dropdownFooterComponent);
+
+ return mountComponent(Component, {
+ labelsWebUrl,
+ createLabelTitle,
+ manageLabelsTitle,
+ });
+};
+
+describe('DropdownFooterComponent', () => {
+ const createLabelTitle = 'Create project label';
+ const manageLabelsTitle = 'Manage project labels';
+ let vm;
+
+ beforeEach(() => {
+ vm = createComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('template', () => {
+ it('renders link element with `Create new label` when `createLabelTitle` prop is not provided', () => {
+ const createLabelEl = vm.$el.querySelector('.dropdown-footer-list .dropdown-toggle-page');
+
+ expect(createLabelEl).not.toBeNull();
+ expect(createLabelEl.innerText.trim()).toBe('Create new label');
+ });
+
+ it('renders link element with value of `createLabelTitle` prop', () => {
+ const vmWithCreateLabelTitle = createComponent(mockConfig.labelsWebUrl, createLabelTitle);
+ const createLabelEl = vmWithCreateLabelTitle.$el.querySelector(
+ '.dropdown-footer-list .dropdown-toggle-page',
+ );
+
+ expect(createLabelEl.innerText.trim()).toBe(createLabelTitle);
+ vmWithCreateLabelTitle.$destroy();
+ });
+
+ it('renders link element with `Manage labels` when `manageLabelsTitle` prop is not provided', () => {
+ const manageLabelsEl = vm.$el.querySelector('.dropdown-footer-list .dropdown-external-link');
+
+ expect(manageLabelsEl).not.toBeNull();
+ expect(manageLabelsEl.getAttribute('href')).toBe(vm.labelsWebUrl);
+ expect(manageLabelsEl.innerText.trim()).toBe('Manage labels');
+ });
+
+ it('renders link element with value of `manageLabelsTitle` prop', () => {
+ const vmWithManageLabelsTitle = createComponent(
+ mockConfig.labelsWebUrl,
+ createLabelTitle,
+ manageLabelsTitle,
+ );
+ const manageLabelsEl = vmWithManageLabelsTitle.$el.querySelector(
+ '.dropdown-footer-list .dropdown-external-link',
+ );
+
+ expect(manageLabelsEl.innerText.trim()).toBe(manageLabelsTitle);
+ vmWithManageLabelsTitle.$destroy();
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js
new file mode 100644
index 00000000000..c36a82e1a35
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js
@@ -0,0 +1,40 @@
+import Vue from 'vue';
+
+import dropdownHeaderComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_header.vue';
+
+import mountComponent from 'helpers/vue_mount_component_helper';
+
+const createComponent = () => {
+ const Component = Vue.extend(dropdownHeaderComponent);
+
+ return mountComponent(Component);
+};
+
+describe('DropdownHeaderComponent', () => {
+ let vm;
+
+ beforeEach(() => {
+ vm = createComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('template', () => {
+ it('renders header text element', () => {
+ const headerEl = vm.$el.querySelector('.dropdown-title span');
+
+ expect(headerEl.innerText.trim()).toBe('Assign labels');
+ });
+
+ it('renders `Close` button element', () => {
+ const closeBtnEl = vm.$el.querySelector(
+ '.dropdown-title button.dropdown-title-button.dropdown-menu-close',
+ );
+
+ expect(closeBtnEl).not.toBeNull();
+ expect(closeBtnEl.querySelector('.fa-times.dropdown-menu-close-icon')).not.toBeNull();
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js
new file mode 100644
index 00000000000..2fffb2e495e
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js
@@ -0,0 +1,42 @@
+import Vue from 'vue';
+
+import dropdownSearchInputComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_search_input.vue';
+
+import mountComponent from 'helpers/vue_mount_component_helper';
+
+const createComponent = () => {
+ const Component = Vue.extend(dropdownSearchInputComponent);
+
+ return mountComponent(Component);
+};
+
+describe('DropdownSearchInputComponent', () => {
+ let vm;
+
+ beforeEach(() => {
+ vm = createComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('template', () => {
+ it('renders input element with type `search`', () => {
+ const inputEl = vm.$el.querySelector('input.dropdown-input-field');
+
+ expect(inputEl).not.toBeNull();
+ expect(inputEl.getAttribute('type')).toBe('search');
+ });
+
+ it('renders search icon element', () => {
+ expect(vm.$el.querySelector('.fa-search.dropdown-input-search')).not.toBeNull();
+ });
+
+ it('renders clear search icon element', () => {
+ expect(
+ vm.$el.querySelector('.fa-times.dropdown-input-clear.js-dropdown-input-clear'),
+ ).not.toBeNull();
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js
new file mode 100644
index 00000000000..1616e657c81
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js
@@ -0,0 +1,43 @@
+import Vue from 'vue';
+
+import dropdownTitleComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_title.vue';
+
+import mountComponent from 'helpers/vue_mount_component_helper';
+
+const createComponent = (canEdit = true) => {
+ const Component = Vue.extend(dropdownTitleComponent);
+
+ return mountComponent(Component, {
+ canEdit,
+ });
+};
+
+describe('DropdownTitleComponent', () => {
+ let vm;
+
+ beforeEach(() => {
+ vm = createComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('template', () => {
+ it('renders title text', () => {
+ expect(vm.$el.classList.contains('title', 'hide-collapsed')).toBe(true);
+ expect(vm.$el.innerText.trim()).toContain('Labels');
+ });
+
+ it('renders spinner icon element', () => {
+ expect(vm.$el.querySelector('.fa-spinner.fa-spin.block-loading')).not.toBeNull();
+ });
+
+ it('renders `Edit` button element', () => {
+ const editBtnEl = vm.$el.querySelector('button.edit-link.js-sidebar-dropdown-toggle');
+
+ expect(editBtnEl).not.toBeNull();
+ expect(editBtnEl.innerText.trim()).toBe('Edit');
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
new file mode 100644
index 00000000000..517f2c01c46
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
@@ -0,0 +1,97 @@
+import Vue from 'vue';
+
+import dropdownValueCollapsedComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue';
+
+import mountComponent from 'helpers/vue_mount_component_helper';
+import { mockLabels } from '../../../../../javascripts/vue_shared/components/sidebar/labels_select/mock_data';
+
+const createComponent = (labels = mockLabels) => {
+ const Component = Vue.extend(dropdownValueCollapsedComponent);
+
+ return mountComponent(Component, {
+ labels,
+ });
+};
+
+describe('DropdownValueCollapsedComponent', () => {
+ let vm;
+
+ beforeEach(() => {
+ vm = createComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('computed', () => {
+ describe('labelsList', () => {
+ it('returns default text when `labels` prop is empty array', () => {
+ const vmEmptyLabels = createComponent([]);
+
+ expect(vmEmptyLabels.labelsList).toBe('Labels');
+ vmEmptyLabels.$destroy();
+ });
+
+ it('returns labels names separated by coma when `labels` prop has more than one item', () => {
+ const labels = mockLabels.concat(mockLabels);
+ const vmMoreLabels = createComponent(labels);
+
+ const expectedText = labels.map(label => label.title).join(', ');
+
+ expect(vmMoreLabels.labelsList).toBe(expectedText);
+ vmMoreLabels.$destroy();
+ });
+
+ it('returns labels names separated by coma with remaining labels count and `and more` phrase when `labels` prop has more than five items', () => {
+ const mockMoreLabels = Object.assign([], mockLabels);
+ for (let i = 0; i < 6; i += 1) {
+ mockMoreLabels.unshift(mockLabels[0]);
+ }
+
+ const vmMoreLabels = createComponent(mockMoreLabels);
+
+ const expectedText = `${mockMoreLabels
+ .slice(0, 5)
+ .map(label => label.title)
+ .join(', ')}, and ${mockMoreLabels.length - 5} more`;
+
+ expect(vmMoreLabels.labelsList).toBe(expectedText);
+ vmMoreLabels.$destroy();
+ });
+
+ it('returns first label name when `labels` prop has only one item present', () => {
+ const text = mockLabels.map(label => label.title).join(', ');
+
+ expect(vm.labelsList).toBe(text);
+ });
+ });
+ });
+
+ describe('methods', () => {
+ describe('handleClick', () => {
+ it('emits onValueClick event on component', () => {
+ jest.spyOn(vm, '$emit').mockImplementation(() => {});
+ vm.handleClick();
+
+ expect(vm.$emit).toHaveBeenCalledWith('onValueClick');
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('renders component container element with tooltip`', () => {
+ expect(vm.$el.dataset.placement).toBe('left');
+ expect(vm.$el.dataset.container).toBe('body');
+ expect(vm.$el.dataset.originalTitle).toBe(vm.labelsList);
+ });
+
+ it('renders tags icon element', () => {
+ expect(vm.$el.querySelector('.fa-tags')).not.toBeNull();
+ });
+
+ it('renders labels count', () => {
+ expect(vm.$el.querySelector('span').innerText.trim()).toBe(`${vm.labels.length}`);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js
new file mode 100644
index 00000000000..ec143fec5d9
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js
@@ -0,0 +1,139 @@
+import Vue from 'vue';
+import $ from 'jquery';
+
+import dropdownValueComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_value.vue';
+
+import mountComponent from 'helpers/vue_mount_component_helper';
+import {
+ mockConfig,
+ mockLabels,
+} from '../../../../../javascripts/vue_shared/components/sidebar/labels_select/mock_data';
+
+const createComponent = (
+ labels = mockLabels,
+ labelFilterBasePath = mockConfig.labelFilterBasePath,
+) => {
+ const Component = Vue.extend(dropdownValueComponent);
+
+ return mountComponent(Component, {
+ labels,
+ labelFilterBasePath,
+ enableScopedLabels: true,
+ });
+};
+
+describe('DropdownValueComponent', () => {
+ let vm;
+
+ beforeEach(() => {
+ vm = createComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('computed', () => {
+ describe('isEmpty', () => {
+ it('returns true if `labels` prop is empty', () => {
+ const vmEmptyLabels = createComponent([]);
+
+ expect(vmEmptyLabels.isEmpty).toBe(true);
+ vmEmptyLabels.$destroy();
+ });
+
+ it('returns false if `labels` prop is empty', () => {
+ expect(vm.isEmpty).toBe(false);
+ });
+ });
+ });
+
+ describe('methods', () => {
+ describe('labelFilterUrl', () => {
+ it('returns URL string starting with labelFilterBasePath and encoded label.title', () => {
+ expect(
+ vm.labelFilterUrl({
+ title: 'Foo bar',
+ }),
+ ).toBe('/gitlab-org/my-project/issues?label_name[]=Foo%20bar');
+ });
+ });
+
+ describe('labelStyle', () => {
+ it('returns object with `color` & `backgroundColor` properties from label.textColor & label.color', () => {
+ const label = {
+ textColor: '#FFFFFF',
+ color: '#BADA55',
+ };
+ const styleObj = vm.labelStyle(label);
+
+ expect(styleObj.color).toBe(label.textColor);
+ expect(styleObj.backgroundColor).toBe(label.color);
+ });
+ });
+
+ describe('scopedLabelsDescription', () => {
+ it('returns html for tooltip', () => {
+ const html = vm.scopedLabelsDescription(mockLabels[1]);
+ const $el = $.parseHTML(html);
+
+ expect($el[0]).toHaveClass('scoped-label-tooltip-title');
+ expect($el[2].textContent).toEqual(mockLabels[1].description);
+ });
+ });
+
+ describe('showScopedLabels', () => {
+ it('returns true if the label is scoped label', () => {
+ expect(vm.showScopedLabels(mockLabels[1])).toBe(true);
+ });
+
+ it('returns false when label is a regular label', () => {
+ expect(vm.showScopedLabels(mockLabels[0])).toBe(false);
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('renders component container element with classes `hide-collapsed value issuable-show-labels`', () => {
+ expect(vm.$el.classList.contains('hide-collapsed', 'value', 'issuable-show-labels')).toBe(
+ true,
+ );
+ });
+
+ it('render slot content inside component when `labels` prop is empty', () => {
+ const vmEmptyLabels = createComponent([]);
+
+ expect(vmEmptyLabels.$el.querySelector('.text-secondary').innerText.trim()).toBe(
+ mockConfig.emptyValueText,
+ );
+ vmEmptyLabels.$destroy();
+ });
+
+ it('renders label element with filter URL', () => {
+ expect(vm.$el.querySelector('a').getAttribute('href')).toBe(
+ '/gitlab-org/my-project/issues?label_name[]=Foo%20Label',
+ );
+ });
+
+ it('renders label element and styles based on label details', () => {
+ const labelEl = vm.$el.querySelector('a span.badge.color-label');
+
+ expect(labelEl).not.toBeNull();
+ expect(labelEl.getAttribute('style')).toBe('background-color: rgb(186, 218, 85);');
+ expect(labelEl.innerText.trim()).toBe(mockLabels[0].title);
+ });
+
+ describe('label is of scoped-label type', () => {
+ it('renders a scoped-label-wrapper span to incorporate 2 anchors', () => {
+ expect(vm.$el.querySelector('span.scoped-label-wrapper')).not.toBeNull();
+ });
+
+ it('renders anchor tag containing question icon', () => {
+ const anchor = vm.$el.querySelector('.scoped-label-wrapper a.scoped-label');
+
+ expect(anchor).not.toBeNull();
+ expect(anchor.querySelector('i.fa-question-circle')).not.toBeNull();
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/toggle_sidebar_spec.js b/spec/frontend/vue_shared/components/sidebar/toggle_sidebar_spec.js
new file mode 100644
index 00000000000..5cf25ca6f81
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/toggle_sidebar_spec.js
@@ -0,0 +1,32 @@
+import Vue from 'vue';
+import toggleSidebar from '~/vue_shared/components/sidebar/toggle_sidebar.vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
+
+describe('toggleSidebar', () => {
+ let vm;
+ beforeEach(() => {
+ const ToggleSidebar = Vue.extend(toggleSidebar);
+ vm = mountComponent(ToggleSidebar, {
+ collapsed: true,
+ });
+ });
+
+ it('should render << when collapsed', () => {
+ expect(vm.$el.querySelector('.fa').classList.contains('fa-angle-double-left')).toEqual(true);
+ });
+
+ it('should render >> when collapsed', () => {
+ vm.collapsed = false;
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelector('.fa').classList.contains('fa-angle-double-right')).toEqual(true);
+ });
+ });
+
+ it('should emit toggle event when button clicked', () => {
+ const toggle = jest.fn();
+ vm.$on('toggle', toggle);
+ vm.$el.click();
+
+ expect(toggle).toHaveBeenCalled();
+ });
+});
diff --git a/spec/frontend/vue_shared/droplab_dropdown_button_spec.js b/spec/frontend/vue_shared/droplab_dropdown_button_spec.js
new file mode 100644
index 00000000000..22295721328
--- /dev/null
+++ b/spec/frontend/vue_shared/droplab_dropdown_button_spec.js
@@ -0,0 +1,136 @@
+import { mount, createLocalVue } from '@vue/test-utils';
+
+import DroplabDropdownButton from '~/vue_shared/components/droplab_dropdown_button.vue';
+
+const mockActions = [
+ {
+ title: 'Foo',
+ description: 'Some foo action',
+ },
+ {
+ title: 'Bar',
+ description: 'Some bar action',
+ },
+];
+
+const createComponent = ({
+ size = '',
+ dropdownClass = '',
+ actions = mockActions,
+ defaultAction = 0,
+}) => {
+ const localVue = createLocalVue();
+
+ return mount(DroplabDropdownButton, {
+ localVue,
+ propsData: {
+ size,
+ dropdownClass,
+ actions,
+ defaultAction,
+ },
+ });
+};
+
+describe('DroplabDropdownButton', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = createComponent({});
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('data', () => {
+ it('contains `selectedAction` representing value of `defaultAction` prop', () => {
+ expect(wrapper.vm.selectedAction).toBe(0);
+ });
+ });
+
+ describe('computed', () => {
+ describe('selectedActionTitle', () => {
+ it('returns string containing title of selected action', () => {
+ wrapper.setData({ selectedAction: 0 });
+
+ expect(wrapper.vm.selectedActionTitle).toBe(mockActions[0].title);
+
+ wrapper.setData({ selectedAction: 1 });
+
+ expect(wrapper.vm.selectedActionTitle).toBe(mockActions[1].title);
+ });
+ });
+
+ describe('buttonSizeClass', () => {
+ it('returns string containing button sizing class based on `size` prop', done => {
+ const wrapperWithSize = createComponent({
+ size: 'sm',
+ });
+
+ wrapperWithSize.vm.$nextTick(() => {
+ expect(wrapperWithSize.vm.buttonSizeClass).toBe('btn-sm');
+
+ done();
+ wrapperWithSize.destroy();
+ });
+ });
+ });
+ });
+
+ describe('methods', () => {
+ describe('handlePrimaryActionClick', () => {
+ it('emits `onActionClick` event on component with selectedAction object as param', () => {
+ jest.spyOn(wrapper.vm, '$emit');
+
+ wrapper.setData({ selectedAction: 0 });
+ wrapper.vm.handlePrimaryActionClick();
+
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('onActionClick', mockActions[0]);
+ });
+ });
+
+ describe('handleActionClick', () => {
+ it('emits `onActionSelect` event on component with selectedAction index as param', () => {
+ jest.spyOn(wrapper.vm, '$emit');
+
+ wrapper.vm.handleActionClick(1);
+
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('onActionSelect', 1);
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('renders default action button', () => {
+ const defaultButton = wrapper.findAll('.btn').at(0);
+
+ expect(defaultButton.text()).toBe(mockActions[0].title);
+ });
+
+ it('renders dropdown button', () => {
+ const dropdownButton = wrapper.findAll('.dropdown-toggle').at(0);
+
+ expect(dropdownButton.isVisible()).toBe(true);
+ });
+
+ it('renders dropdown actions', () => {
+ const dropdownActions = wrapper.findAll('.dropdown-menu li button');
+
+ Array(dropdownActions.length)
+ .fill()
+ .forEach((_, index) => {
+ const actionContent = dropdownActions.at(index).find('.description');
+
+ expect(actionContent.find('strong').text()).toBe(mockActions[index].title);
+ expect(actionContent.find('p').text()).toBe(mockActions[index].description);
+ });
+ });
+
+ it('renders divider between dropdown actions', () => {
+ const dropdownDivider = wrapper.find('.dropdown-menu .divider');
+
+ expect(dropdownDivider.isVisible()).toBe(true);
+ });
+ });
+});
diff --git a/spec/graphql/features/authorization_spec.rb b/spec/graphql/features/authorization_spec.rb
index 00e31568a9e..c427893f9cc 100644
--- a/spec/graphql/features/authorization_spec.rb
+++ b/spec/graphql/features/authorization_spec.rb
@@ -177,6 +177,7 @@ describe 'Gitlab::Graphql::Authorization' do
describe 'type authorizations when applied to a relay connection' do
let(:query_string) { '{ object() { edges { node { name } } } }' }
+ let(:second_test_object) { double(name: 'Second thing') }
let(:type) do
type_factory do |type|
@@ -186,22 +187,41 @@ describe 'Gitlab::Graphql::Authorization' do
let(:query_type) do
query_factory do |query|
- query.field :object, type.connection_type, null: true, resolve: ->(obj, args, ctx) { [test_object] }
+ query.field :object, type.connection_type, null: true, resolve: ->(obj, args, ctx) { [test_object, second_test_object] }
end
end
subject { result.dig('object', 'edges') }
- it 'returns the protected field when user has permission' do
+ it 'returns only the elements visible to the user' do
permit(permission_single)
- expect(subject).not_to be_empty
+ expect(subject.size).to eq 1
expect(subject.first['node']).to eq('name' => test_object.name)
end
it 'returns nil when user is not authorized' do
expect(subject).to be_empty
end
+
+ describe 'limiting connections with multiple objects' do
+ let(:query_type) do
+ query_factory do |query|
+ query.field :object, type.connection_type, null: true, resolve: ->(obj, args, ctx) do
+ [test_object, second_test_object]
+ end
+ end
+ end
+
+ let(:query_string) { '{ object(first: 1) { edges { node { name } } } }' }
+
+ it 'only checks permissions for the first object' do
+ expect(Ability).to receive(:allowed?).with(user, permission_single, test_object) { true }
+ expect(Ability).not_to receive(:allowed?).with(user, permission_single, second_test_object)
+
+ expect(subject.size).to eq(1)
+ end
+ end
end
describe 'type authorizations when applied to a basic connection' do
@@ -222,28 +242,53 @@ describe 'Gitlab::Graphql::Authorization' do
include_examples 'authorization with a single permission'
end
- describe 'when connections do not follow the correct specification' do
- let(:query_string) { '{ object() { edges { node { name }} } }' }
+ describe 'Authorizations on active record relations' do
+ let!(:visible_project) { create(:project, :private) }
+ let!(:other_project) { create(:project, :private) }
+ let!(:visible_issues) { create_list(:issue, 2, project: visible_project) }
+ let!(:other_issues) { create_list(:issue, 2, project: other_project) }
+ let!(:user) { visible_project.owner }
- let(:type) do
- bad_node = type_factory do |type|
- type.graphql_name 'BadNode'
- type.field :bad_node, GraphQL::STRING_TYPE, null: true
+ let(:issue_type) do
+ type_factory do |type|
+ type.graphql_name 'FakeIssueType'
+ type.authorize :read_issue
+ type.field :id, GraphQL::ID_TYPE, null: false
end
-
+ end
+ let(:project_type) do |type|
type_factory do |type|
- type.field :edges, [bad_node], null: true
+ type.graphql_name 'FakeProjectType'
+ type.field :test_issues, issue_type.connection_type, null: false, resolve: -> (_, _, _) { Issue.where(project: [visible_project, other_project]) }
end
end
-
let(:query_type) do
query_factory do |query|
- query.field :object, type, null: true
+ query.field :test_project, project_type, null: false, resolve: -> (_, _, _) { visible_project }
end
end
+ let(:query_string) do
+ <<~QRY
+ { testProject { testIssues(first: 3) { edges { node { id } } } } }
+ QRY
+ end
+
+ before do
+ allow(Ability).to receive(:allowed?).and_call_original
+ end
+
+ it 'renders the issues the user has access to' do
+ issue_edges = result['testProject']['testIssues']['edges']
+ issue_ids = issue_edges.map { |issue_edge| issue_edge['node']&.fetch('id') }
+
+ expect(issue_edges.size).to eq(visible_issues.size)
+ expect(issue_ids).to eq(visible_issues.map { |i| i.to_global_id.to_s })
+ end
+
+ it 'does not check access on fields that will not be rendered' do
+ expect(Ability).not_to receive(:allowed?).with(user, :read_issue, other_issues.last)
- it 'throws an error' do
- expect { result }.to raise_error(Gitlab::Graphql::Errors::ConnectionDefinitionError)
+ result
end
end
@@ -276,6 +321,8 @@ describe 'Gitlab::Graphql::Authorization' do
def execute_query(query_type)
schema = Class.new(GraphQL::Schema) do
use Gitlab::Graphql::Authorize
+ use Gitlab::Graphql::Connections
+
query(query_type)
end
diff --git a/spec/graphql/gitlab_schema_spec.rb b/spec/graphql/gitlab_schema_spec.rb
index 74e93b2c4df..4076c1f824b 100644
--- a/spec/graphql/gitlab_schema_spec.rb
+++ b/spec/graphql/gitlab_schema_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe GitlabSchema do
+ let(:user) { build :user }
+
it 'uses batch loading' do
expect(field_instrumenters).to include(BatchLoader::GraphQL)
end
@@ -33,47 +35,137 @@ describe GitlabSchema do
expect(connection).to eq(Gitlab::Graphql::Connections::KeysetConnection)
end
- context 'for different types of users' do
- it 'returns DEFAULT_MAX_COMPLEXITY for no context' do
- expect(GraphQL::Schema)
- .to receive(:execute)
- .with('query', hash_including(max_complexity: GitlabSchema::DEFAULT_MAX_COMPLEXITY))
+ describe '.execute' do
+ context 'for different types of users' do
+ context 'when no context' do
+ it 'returns DEFAULT_MAX_COMPLEXITY' do
+ expect(GraphQL::Schema)
+ .to receive(:execute)
+ .with('query', hash_including(max_complexity: GitlabSchema::DEFAULT_MAX_COMPLEXITY))
+
+ described_class.execute('query')
+ end
+ end
+
+ context 'when no user' do
+ it 'returns DEFAULT_MAX_COMPLEXITY' do
+ expect(GraphQL::Schema)
+ .to receive(:execute)
+ .with('query', hash_including(max_complexity: GitlabSchema::DEFAULT_MAX_COMPLEXITY))
+
+ described_class.execute('query', context: {})
+ end
+
+ it 'returns DEFAULT_MAX_DEPTH' do
+ expect(GraphQL::Schema)
+ .to receive(:execute)
+ .with('query', hash_including(max_depth: GitlabSchema::DEFAULT_MAX_DEPTH))
+
+ described_class.execute('query', context: {})
+ end
+ end
+
+ context 'when a logged in user' do
+ it 'returns AUTHENTICATED_COMPLEXITY' do
+ expect(GraphQL::Schema).to receive(:execute).with('query', hash_including(max_complexity: GitlabSchema::AUTHENTICATED_COMPLEXITY))
+
+ described_class.execute('query', context: { current_user: user })
+ end
+
+ it 'returns AUTHENTICATED_MAX_DEPTH' do
+ expect(GraphQL::Schema).to receive(:execute).with('query', hash_including(max_depth: GitlabSchema::AUTHENTICATED_MAX_DEPTH))
+
+ described_class.execute('query', context: { current_user: user })
+ end
+ end
+
+ context 'when an admin user' do
+ it 'returns ADMIN_COMPLEXITY' do
+ user = build :user, :admin
+
+ expect(GraphQL::Schema).to receive(:execute).with('query', hash_including(max_complexity: GitlabSchema::ADMIN_COMPLEXITY))
- described_class.execute('query')
+ described_class.execute('query', context: { current_user: user })
+ end
+ end
+
+ context 'when max_complexity passed on the query' do
+ it 'returns what was passed on the query' do
+ expect(GraphQL::Schema).to receive(:execute).with('query', hash_including(max_complexity: 1234))
+
+ described_class.execute('query', max_complexity: 1234)
+ end
+ end
+
+ context 'when max_depth passed on the query' do
+ it 'returns what was passed on the query' do
+ expect(GraphQL::Schema).to receive(:execute).with('query', hash_including(max_depth: 1234))
+
+ described_class.execute('query', max_depth: 1234)
+ end
+ end
end
+ end
- it 'returns DEFAULT_MAX_COMPLEXITY for no user' do
- expect(GraphQL::Schema)
- .to receive(:execute)
- .with('query', hash_including(max_complexity: GitlabSchema::DEFAULT_MAX_COMPLEXITY))
+ describe '.id_from_object' do
+ it 'returns a global id' do
+ expect(described_class.id_from_object(build(:project, id: 1))).to be_a(GlobalID)
+ end
- described_class.execute('query', context: {})
+ it "raises a meaningful error if a global id couldn't be generated" do
+ expect { described_class.id_from_object(build(:commit)) }
+ .to raise_error(RuntimeError, /include `GlobalID::Identification` into/i)
end
+ end
+
+ describe '.object_from_id' do
+ context 'for subclasses of `ApplicationRecord`' do
+ it 'returns the correct record' do
+ user = create(:user)
+
+ result = described_class.object_from_id(user.to_global_id.to_s)
- it 'returns AUTHENTICATED_COMPLEXITY for a logged in user' do
- user = build :user
+ expect(result.__sync).to eq(user)
+ end
- expect(GraphQL::Schema).to receive(:execute).with('query', hash_including(max_complexity: GitlabSchema::AUTHENTICATED_COMPLEXITY))
+ it 'batchloads the queries' do
+ user1 = create(:user)
+ user2 = create(:user)
- described_class.execute('query', context: { current_user: user })
+ expect do
+ [described_class.object_from_id(user1.to_global_id),
+ described_class.object_from_id(user2.to_global_id)].map(&:__sync)
+ end.not_to exceed_query_limit(1)
+ end
end
- it 'returns ADMIN_COMPLEXITY for an admin user' do
- user = build :user, :admin
+ context 'for other classes' do
+ # We cannot use an anonymous class here as `GlobalID` expects `.name` not
+ # to return `nil`
+ class TestGlobalId
+ include GlobalID::Identification
+ attr_accessor :id
- expect(GraphQL::Schema).to receive(:execute).with('query', hash_including(max_complexity: GitlabSchema::ADMIN_COMPLEXITY))
+ def initialize(id)
+ @id = id
+ end
+ end
- described_class.execute('query', context: { current_user: user })
- end
+ it 'falls back to a regular find' do
+ result = TestGlobalId.new(123)
+
+ expect(TestGlobalId).to receive(:find).with("123").and_return(result)
- it 'returns what was passed on the query' do
- expect(GraphQL::Schema).to receive(:execute).with('query', { max_complexity: 1234 })
+ expect(described_class.object_from_id(result.to_global_id)).to eq(result)
+ end
+ end
- described_class.execute('query', max_complexity: 1234)
+ it 'raises the correct error on invalid input' do
+ expect { described_class.object_from_id("bogus id") }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
end
end
def field_instrumenters
- described_class.instrumenters[:field]
+ described_class.instrumenters[:field] + described_class.instrumenters[:field_after_built_ins]
end
end
diff --git a/spec/graphql/resolvers/base_resolver_spec.rb b/spec/graphql/resolvers/base_resolver_spec.rb
index e3a34762b62..c162fdbbb47 100644
--- a/spec/graphql/resolvers/base_resolver_spec.rb
+++ b/spec/graphql/resolvers/base_resolver_spec.rb
@@ -28,4 +28,21 @@ describe Resolvers::BaseResolver do
expect(result).to eq(test: 1)
end
end
+
+ context 'when field is a connection' do
+ it 'increases complexity based on arguments' do
+ field = Types::BaseField.new(name: 'test', type: GraphQL::STRING_TYPE.connection_type, resolver_class: described_class, null: false, max_page_size: 1)
+
+ expect(field.to_graphql.complexity.call({}, { sort: 'foo' }, 1)).to eq 3
+ expect(field.to_graphql.complexity.call({}, { search: 'foo' }, 1)).to eq 7
+ end
+
+ it 'does not increase complexity when filtering by iids' do
+ field = Types::BaseField.new(name: 'test', type: GraphQL::STRING_TYPE.connection_type, resolver_class: described_class, null: false, max_page_size: 100)
+
+ expect(field.to_graphql.complexity.call({}, { sort: 'foo' }, 1)).to eq 6
+ expect(field.to_graphql.complexity.call({}, { sort: 'foo', iid: 1 }, 1)).to eq 3
+ expect(field.to_graphql.complexity.call({}, { sort: 'foo', iids: [1, 2, 3] }, 1)).to eq 3
+ end
+ end
end
diff --git a/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb b/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb
index ea7159eacf9..3140af27af5 100644
--- a/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb
+++ b/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb
@@ -46,6 +46,14 @@ describe ResolvesPipelines do
expect(resolve_pipelines({}, {})).to be_empty
end
+ it 'increases field complexity based on arguments' do
+ field = Types::BaseField.new(name: 'test', type: GraphQL::STRING_TYPE, resolver_class: resolver, null: false, max_page_size: 1)
+
+ expect(field.to_graphql.complexity.call({}, {}, 1)).to eq 2
+ expect(field.to_graphql.complexity.call({}, { sha: 'foo' }, 1)).to eq 4
+ expect(field.to_graphql.complexity.call({}, { sha: 'ref' }, 1)).to eq 4
+ end
+
def resolve_pipelines(args = {}, context = { current_user: current_user })
resolve(resolver, obj: project, args: args, ctx: context)
end
diff --git a/spec/graphql/resolvers/group_resolver_spec.rb b/spec/graphql/resolvers/group_resolver_spec.rb
new file mode 100644
index 00000000000..5eb9cd06d15
--- /dev/null
+++ b/spec/graphql/resolvers/group_resolver_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::GroupResolver do
+ include GraphqlHelpers
+
+ set(:group1) { create(:group) }
+ set(:group2) { create(:group) }
+
+ describe '#resolve' do
+ it 'batch-resolves groups by full path' do
+ paths = [group1.full_path, group2.full_path]
+
+ result = batch(max_queries: 1) do
+ paths.map { |path| resolve_group(path) }
+ end
+
+ expect(result).to contain_exactly(group1, group2)
+ end
+
+ it 'resolves an unknown full_path to nil' do
+ result = batch { resolve_group('unknown/project') }
+
+ expect(result).to be_nil
+ end
+ end
+
+ def resolve_group(full_path)
+ resolve(described_class, args: { full_path: full_path })
+ end
+end
diff --git a/spec/graphql/resolvers/issues_resolver_spec.rb b/spec/graphql/resolvers/issues_resolver_spec.rb
index 5f9c180cbb7..798fe00de97 100644
--- a/spec/graphql/resolvers/issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/issues_resolver_spec.rb
@@ -4,105 +4,127 @@ describe Resolvers::IssuesResolver do
include GraphqlHelpers
let(:current_user) { create(:user) }
- set(:project) { create(:project) }
- set(:issue1) { create(:issue, project: project, state: :opened, created_at: 3.hours.ago, updated_at: 3.hours.ago) }
- set(:issue2) { create(:issue, project: project, state: :closed, title: 'foo', created_at: 1.hour.ago, updated_at: 1.hour.ago, closed_at: 1.hour.ago) }
- set(:label1) { create(:label, project: project) }
- set(:label2) { create(:label, project: project) }
-
- before do
- project.add_developer(current_user)
- create(:label_link, label: label1, target: issue1)
- create(:label_link, label: label1, target: issue2)
- create(:label_link, label: label2, target: issue2)
- end
- describe '#resolve' do
- it 'finds all issues' do
- expect(resolve_issues).to contain_exactly(issue1, issue2)
+ context "with a project" do
+ set(:project) { create(:project) }
+ set(:issue1) { create(:issue, project: project, state: :opened, created_at: 3.hours.ago, updated_at: 3.hours.ago) }
+ set(:issue2) { create(:issue, project: project, state: :closed, title: 'foo', created_at: 1.hour.ago, updated_at: 1.hour.ago, closed_at: 1.hour.ago) }
+ set(:label1) { create(:label, project: project) }
+ set(:label2) { create(:label, project: project) }
+
+ before do
+ project.add_developer(current_user)
+ create(:label_link, label: label1, target: issue1)
+ create(:label_link, label: label1, target: issue2)
+ create(:label_link, label: label2, target: issue2)
end
- it 'filters by state' do
- expect(resolve_issues(state: 'opened')).to contain_exactly(issue1)
- expect(resolve_issues(state: 'closed')).to contain_exactly(issue2)
- end
+ describe '#resolve' do
+ it 'finds all issues' do
+ expect(resolve_issues).to contain_exactly(issue1, issue2)
+ end
- it 'filters by labels' do
- expect(resolve_issues(label_name: [label1.title])).to contain_exactly(issue1, issue2)
- expect(resolve_issues(label_name: [label1.title, label2.title])).to contain_exactly(issue2)
- end
+ it 'filters by state' do
+ expect(resolve_issues(state: 'opened')).to contain_exactly(issue1)
+ expect(resolve_issues(state: 'closed')).to contain_exactly(issue2)
+ end
- describe 'filters by created_at' do
- it 'filters by created_before' do
- expect(resolve_issues(created_before: 2.hours.ago)).to contain_exactly(issue1)
+ it 'filters by labels' do
+ expect(resolve_issues(label_name: [label1.title])).to contain_exactly(issue1, issue2)
+ expect(resolve_issues(label_name: [label1.title, label2.title])).to contain_exactly(issue2)
end
- it 'filters by created_after' do
- expect(resolve_issues(created_after: 2.hours.ago)).to contain_exactly(issue2)
+ describe 'filters by created_at' do
+ it 'filters by created_before' do
+ expect(resolve_issues(created_before: 2.hours.ago)).to contain_exactly(issue1)
+ end
+
+ it 'filters by created_after' do
+ expect(resolve_issues(created_after: 2.hours.ago)).to contain_exactly(issue2)
+ end
end
- end
- describe 'filters by updated_at' do
- it 'filters by updated_before' do
- expect(resolve_issues(updated_before: 2.hours.ago)).to contain_exactly(issue1)
+ describe 'filters by updated_at' do
+ it 'filters by updated_before' do
+ expect(resolve_issues(updated_before: 2.hours.ago)).to contain_exactly(issue1)
+ end
+
+ it 'filters by updated_after' do
+ expect(resolve_issues(updated_after: 2.hours.ago)).to contain_exactly(issue2)
+ end
end
- it 'filters by updated_after' do
- expect(resolve_issues(updated_after: 2.hours.ago)).to contain_exactly(issue2)
+ describe 'filters by closed_at' do
+ let!(:issue3) { create(:issue, project: project, state: :closed, closed_at: 3.hours.ago) }
+
+ it 'filters by closed_before' do
+ expect(resolve_issues(closed_before: 2.hours.ago)).to contain_exactly(issue3)
+ end
+
+ it 'filters by closed_after' do
+ expect(resolve_issues(closed_after: 2.hours.ago)).to contain_exactly(issue2)
+ end
end
- end
- describe 'filters by closed_at' do
- let!(:issue3) { create(:issue, project: project, state: :closed, closed_at: 3.hours.ago) }
+ it 'searches issues' do
+ expect(resolve_issues(search: 'foo')).to contain_exactly(issue2)
+ end
- it 'filters by closed_before' do
- expect(resolve_issues(closed_before: 2.hours.ago)).to contain_exactly(issue3)
+ it 'sort issues' do
+ expect(resolve_issues(sort: 'created_desc')).to eq [issue2, issue1]
end
- it 'filters by closed_after' do
- expect(resolve_issues(closed_after: 2.hours.ago)).to contain_exactly(issue2)
+ it 'returns issues user can see' do
+ project.add_guest(current_user)
+
+ create(:issue, confidential: true)
+
+ expect(resolve_issues).to contain_exactly(issue1, issue2)
end
- end
- it 'searches issues' do
- expect(resolve_issues(search: 'foo')).to contain_exactly(issue2)
- end
+ it 'finds a specific issue with iid' do
+ expect(resolve_issues(iid: issue1.iid)).to contain_exactly(issue1)
+ end
- it 'sort issues' do
- expect(resolve_issues(sort: 'created_desc')).to eq [issue2, issue1]
- end
+ it 'finds a specific issue with iids' do
+ expect(resolve_issues(iids: issue1.iid)).to contain_exactly(issue1)
+ end
- it 'returns issues user can see' do
- project.add_guest(current_user)
+ it 'finds multiple issues with iids' do
+ expect(resolve_issues(iids: [issue1.iid, issue2.iid]))
+ .to contain_exactly(issue1, issue2)
+ end
- create(:issue, confidential: true)
+ it 'finds only the issues within the project we are looking at' do
+ another_project = create(:project)
+ iids = [issue1, issue2].map(&:iid)
- expect(resolve_issues).to contain_exactly(issue1, issue2)
- end
+ iids.each do |iid|
+ create(:issue, project: another_project, iid: iid)
+ end
- it 'finds a specific issue with iid' do
- expect(resolve_issues(iid: issue1.iid)).to contain_exactly(issue1)
+ expect(resolve_issues(iids: iids)).to contain_exactly(issue1, issue2)
+ end
end
+ end
- it 'finds a specific issue with iids' do
- expect(resolve_issues(iids: issue1.iid)).to contain_exactly(issue1)
+ context "when passing a non existent, batch loaded project" do
+ let(:project) do
+ BatchLoader.for("non-existent-path").batch do |_fake_paths, loader, _|
+ loader.call("non-existent-path", nil)
+ end
end
- it 'finds multiple issues with iids' do
- expect(resolve_issues(iids: [issue1.iid, issue2.iid]))
- .to contain_exactly(issue1, issue2)
+ it "returns nil without breaking" do
+ expect(resolve_issues(iids: ["don't", "break"])).to be_empty
end
+ end
- it 'finds only the issues within the project we are looking at' do
- another_project = create(:project)
- iids = [issue1, issue2].map(&:iid)
-
- iids.each do |iid|
- create(:issue, project: another_project, iid: iid)
- end
+ it 'increases field complexity based on arguments' do
+ field = Types::BaseField.new(name: 'test', type: GraphQL::STRING_TYPE.connection_type, resolver_class: described_class, null: false, max_page_size: 100)
- expect(resolve_issues(iids: iids)).to contain_exactly(issue1, issue2)
- end
+ expect(field.to_graphql.complexity.call({}, {}, 1)).to eq 4
+ expect(field.to_graphql.complexity.call({}, { labelName: 'foo' }, 1)).to eq 8
end
def resolve_issues(args = {}, context = { current_user: current_user })
diff --git a/spec/graphql/resolvers/namespace_projects_resolver_spec.rb b/spec/graphql/resolvers/namespace_projects_resolver_spec.rb
new file mode 100644
index 00000000000..20e197e9f73
--- /dev/null
+++ b/spec/graphql/resolvers/namespace_projects_resolver_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::NamespaceProjectsResolver, :nested_groups do
+ include GraphqlHelpers
+
+ let(:current_user) { create(:user) }
+
+ context "with a group" do
+ let(:group) { create(:group) }
+ let(:namespace) { group }
+ let(:project1) { create(:project, namespace: namespace) }
+ let(:project2) { create(:project, namespace: namespace) }
+ let(:nested_group) { create(:group, parent: group) }
+ let(:nested_project) { create(:project, group: nested_group) }
+
+ before do
+ project1.add_developer(current_user)
+ project2.add_developer(current_user)
+ nested_project.add_developer(current_user)
+ end
+
+ describe '#resolve' do
+ it 'finds all projects' do
+ expect(resolve_projects).to contain_exactly(project1, project2)
+ end
+
+ it 'finds all projects including the subgroups' do
+ expect(resolve_projects(include_subgroups: true)).to contain_exactly(project1, project2, nested_project)
+ end
+
+ context 'with an user namespace' do
+ let(:namespace) { current_user.namespace }
+
+ it 'finds all projects' do
+ expect(resolve_projects).to contain_exactly(project1, project2)
+ end
+
+ it 'finds all projects including the subgroups' do
+ expect(resolve_projects(include_subgroups: true)).to contain_exactly(project1, project2)
+ end
+ end
+ end
+ end
+
+ context "when passing a non existent, batch loaded namespace" do
+ let(:namespace) do
+ BatchLoader.for("non-existent-path").batch do |_fake_paths, loader, _|
+ loader.call("non-existent-path", nil)
+ end
+ end
+
+ it "returns nil without breaking" do
+ expect(resolve_projects).to be_empty
+ end
+ end
+
+ it 'has an high complexity regardless of arguments' do
+ field = Types::BaseField.new(name: 'test', type: GraphQL::STRING_TYPE.connection_type, resolver_class: described_class, null: false, max_page_size: 100)
+
+ expect(field.to_graphql.complexity.call({}, {}, 1)).to eq 24
+ expect(field.to_graphql.complexity.call({}, { include_subgroups: true }, 1)).to eq 24
+ end
+
+ def resolve_projects(args = { include_subgroups: false }, context = { current_user: current_user })
+ resolve(described_class, obj: namespace, args: args, ctx: context)
+ end
+end
diff --git a/spec/graphql/resolvers/project_resolver_spec.rb b/spec/graphql/resolvers/project_resolver_spec.rb
index d4990c6492c..4fdbb3aa43e 100644
--- a/spec/graphql/resolvers/project_resolver_spec.rb
+++ b/spec/graphql/resolvers/project_resolver_spec.rb
@@ -26,6 +26,14 @@ describe Resolvers::ProjectResolver do
end
end
+ it 'does not increase complexity depending on number of load limits' do
+ field1 = Types::BaseField.new(name: 'test', type: GraphQL::STRING_TYPE, resolver_class: described_class, null: false, max_page_size: 100)
+ field2 = Types::BaseField.new(name: 'test', type: GraphQL::STRING_TYPE, resolver_class: described_class, null: false, max_page_size: 1)
+
+ expect(field1.to_graphql.complexity.call({}, {}, 1)).to eq 2
+ expect(field2.to_graphql.complexity.call({}, {}, 1)).to eq 2
+ end
+
def resolve_project(full_path)
resolve(described_class, args: { full_path: full_path })
end
diff --git a/spec/graphql/resolvers/tree_resolver_spec.rb b/spec/graphql/resolvers/tree_resolver_spec.rb
new file mode 100644
index 00000000000..9f95b740ab1
--- /dev/null
+++ b/spec/graphql/resolvers/tree_resolver_spec.rb
@@ -0,0 +1,35 @@
+require 'spec_helper'
+
+describe Resolvers::TreeResolver do
+ include GraphqlHelpers
+
+ let(:repository) { create(:project, :repository).repository }
+
+ describe '#resolve' do
+ it 'resolves to a tree' do
+ result = resolve_repository({ ref: "master" })
+
+ expect(result).to be_an_instance_of(Tree)
+ end
+
+ it 'resolve to a recursive tree' do
+ result = resolve_repository({ ref: "master", recursive: true })
+
+ expect(result.trees[4].path).to eq('files/html')
+ end
+
+ context 'when repository does not exist' do
+ it 'returns nil' do
+ allow(repository).to receive(:exists?).and_return(false)
+
+ result = resolve_repository({ ref: "master" })
+
+ expect(result).to be(nil)
+ end
+ end
+ end
+
+ def resolve_repository(args)
+ resolve(described_class, obj: repository, args: args)
+ end
+end
diff --git a/spec/graphql/types/base_field_spec.rb b/spec/graphql/types/base_field_spec.rb
index b5697ee5245..0d3c3e37daf 100644
--- a/spec/graphql/types/base_field_spec.rb
+++ b/spec/graphql/types/base_field_spec.rb
@@ -4,6 +4,18 @@ require 'spec_helper'
describe Types::BaseField do
context 'when considering complexity' do
+ let(:resolver) do
+ Class.new(described_class) do
+ def self.resolver_complexity(args, child_complexity:)
+ 2 if args[:foo]
+ end
+
+ def self.complexity_multiplier(args)
+ 0.01
+ end
+ end
+ end
+
it 'defaults to 1' do
field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, null: true)
@@ -15,5 +27,30 @@ describe Types::BaseField do
expect(field.to_graphql.complexity).to eq 12
end
+
+ context 'when field has a resolver proc' do
+ context 'and is a connection' do
+ let(:field) { described_class.new(name: 'test', type: GraphQL::STRING_TYPE.connection_type, resolver_class: resolver, max_page_size: 100, null: true) }
+
+ it 'sets complexity depending on arguments for resolvers' do
+ expect(field.to_graphql.complexity.call({}, {}, 2)).to eq 4
+ expect(field.to_graphql.complexity.call({}, { first: 50 }, 2)).to eq 3
+ end
+
+ it 'sets complexity depending on number load limits for resolvers' do
+ expect(field.to_graphql.complexity.call({}, { first: 1 }, 2)).to eq 2
+ expect(field.to_graphql.complexity.call({}, { first: 1, foo: true }, 2)).to eq 4
+ end
+ end
+
+ context 'and is not a connection' do
+ it 'sets complexity as normal' do
+ field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, resolver_class: resolver, max_page_size: 100, null: true)
+
+ expect(field.to_graphql.complexity.call({}, {}, 2)).to eq 2
+ expect(field.to_graphql.complexity.call({}, { first: 50 }, 2)).to eq 2
+ end
+ end
+ end
end
end
diff --git a/spec/graphql/types/group_type_spec.rb b/spec/graphql/types/group_type_spec.rb
new file mode 100644
index 00000000000..3dd5b602aa2
--- /dev/null
+++ b/spec/graphql/types/group_type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe GitlabSchema.types['Group'] do
+ it { expect(described_class).to expose_permissions_using(Types::PermissionTypes::Group) }
+
+ it { expect(described_class.graphql_name).to eq('Group') }
+
+ it { expect(described_class).to require_graphql_authorizations(:read_group) }
+end
diff --git a/spec/graphql/types/issue_type_spec.rb b/spec/graphql/types/issue_type_spec.rb
index dc37b15001f..bae560829cc 100644
--- a/spec/graphql/types/issue_type_spec.rb
+++ b/spec/graphql/types/issue_type_spec.rb
@@ -6,4 +6,10 @@ describe GitlabSchema.types['Issue'] do
it { expect(described_class.graphql_name).to eq('Issue') }
it { expect(described_class).to require_graphql_authorizations(:read_issue) }
+
+ it 'has specific fields' do
+ %i[relative_position web_path web_url reference].each do |field_name|
+ expect(described_class).to have_graphql_field(field_name)
+ end
+ end
end
diff --git a/spec/graphql/types/namespace_type_spec.rb b/spec/graphql/types/namespace_type_spec.rb
new file mode 100644
index 00000000000..b4144cc4121
--- /dev/null
+++ b/spec/graphql/types/namespace_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe GitlabSchema.types['Namespace'] do
+ it { expect(described_class.graphql_name).to eq('Namespace') }
+
+ it { expect(described_class).to have_graphql_field(:projects) }
+end
diff --git a/spec/graphql/types/project_statistics_type_spec.rb b/spec/graphql/types/project_statistics_type_spec.rb
new file mode 100644
index 00000000000..e9feac57a36
--- /dev/null
+++ b/spec/graphql/types/project_statistics_type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe GitlabSchema.types['ProjectStatistics'] do
+ it "has all the required fields" do
+ is_expected.to have_graphql_fields(:storage_size, :repository_size, :lfs_objects_size,
+ :build_artifacts_size, :packages_size, :commit_count,
+ :wiki_size)
+ end
+end
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index e0ad09bdf22..cb5ac2e3cb1 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -17,4 +17,8 @@ describe GitlabSchema.types['Project'] do
end
it { is_expected.to have_graphql_field(:pipelines) }
+
+ it { is_expected.to have_graphql_field(:repository) }
+
+ it { is_expected.to have_graphql_field(:statistics) }
end
diff --git a/spec/graphql/types/query_type_spec.rb b/spec/graphql/types/query_type_spec.rb
index 69e3ea8a4a9..af1972a2513 100644
--- a/spec/graphql/types/query_type_spec.rb
+++ b/spec/graphql/types/query_type_spec.rb
@@ -5,7 +5,17 @@ describe GitlabSchema.types['Query'] do
expect(described_class.graphql_name).to eq('Query')
end
- it { is_expected.to have_graphql_fields(:project, :echo, :metadata) }
+ it { is_expected.to have_graphql_fields(:project, :namespace, :group, :echo, :metadata) }
+
+ describe 'namespace field' do
+ subject { described_class.fields['namespace'] }
+
+ it 'finds namespaces by full path' do
+ is_expected.to have_graphql_arguments(:full_path)
+ is_expected.to have_graphql_type(Types::NamespaceType)
+ is_expected.to have_graphql_resolver(Resolvers::NamespaceResolver)
+ end
+ end
describe 'project field' do
subject { described_class.fields['project'] }
diff --git a/spec/graphql/types/repository_type_spec.rb b/spec/graphql/types/repository_type_spec.rb
new file mode 100644
index 00000000000..8a8238f2a2a
--- /dev/null
+++ b/spec/graphql/types/repository_type_spec.rb
@@ -0,0 +1,11 @@
+require 'spec_helper'
+
+describe GitlabSchema.types['Repository'] do
+ it { expect(described_class.graphql_name).to eq('Repository') }
+
+ it { expect(described_class).to require_graphql_authorizations(:download_code) }
+
+ it { is_expected.to have_graphql_field(:root_ref) }
+
+ it { is_expected.to have_graphql_field(:tree) }
+end
diff --git a/spec/graphql/types/tree/blob_type_spec.rb b/spec/graphql/types/tree/blob_type_spec.rb
new file mode 100644
index 00000000000..22c11aff90a
--- /dev/null
+++ b/spec/graphql/types/tree/blob_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Types::Tree::BlobType do
+ it { expect(described_class.graphql_name).to eq('Blob') }
+
+ it { expect(described_class).to have_graphql_fields(:id, :name, :type, :path, :flat_path, :web_url, :lfs_oid) }
+end
diff --git a/spec/graphql/types/tree/submodule_type_spec.rb b/spec/graphql/types/tree/submodule_type_spec.rb
new file mode 100644
index 00000000000..bdb3149b41c
--- /dev/null
+++ b/spec/graphql/types/tree/submodule_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Types::Tree::SubmoduleType do
+ it { expect(described_class.graphql_name).to eq('Submodule') }
+
+ it { expect(described_class).to have_graphql_fields(:id, :name, :type, :path, :flat_path) }
+end
diff --git a/spec/graphql/types/tree/tree_entry_type_spec.rb b/spec/graphql/types/tree/tree_entry_type_spec.rb
new file mode 100644
index 00000000000..ea1b6426034
--- /dev/null
+++ b/spec/graphql/types/tree/tree_entry_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Types::Tree::TreeEntryType do
+ it { expect(described_class.graphql_name).to eq('TreeEntry') }
+
+ it { expect(described_class).to have_graphql_fields(:id, :name, :type, :path, :flat_path, :web_url) }
+end
diff --git a/spec/graphql/types/tree/tree_type_spec.rb b/spec/graphql/types/tree/tree_type_spec.rb
new file mode 100644
index 00000000000..b9c5570115e
--- /dev/null
+++ b/spec/graphql/types/tree/tree_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Types::Tree::TreeType do
+ it { expect(described_class.graphql_name).to eq('Tree') }
+
+ it { expect(described_class).to have_graphql_fields(:trees, :submodules, :blobs) }
+end
diff --git a/spec/graphql/types/tree/type_enum_spec.rb b/spec/graphql/types/tree/type_enum_spec.rb
new file mode 100644
index 00000000000..4caf9e1c457
--- /dev/null
+++ b/spec/graphql/types/tree/type_enum_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Types::Tree::TypeEnum do
+ it { expect(described_class.graphql_name).to eq('EntryType') }
+
+ it 'exposes all tree entry types' do
+ expect(described_class.values.keys).to include(*%w[tree blob commit])
+ end
+end
diff --git a/spec/haml_lint/linter/no_plain_nodes_spec.rb b/spec/haml_lint/linter/no_plain_nodes_spec.rb
new file mode 100644
index 00000000000..08deb5a4e9e
--- /dev/null
+++ b/spec/haml_lint/linter/no_plain_nodes_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'haml_lint'
+require 'haml_lint/spec'
+require Rails.root.join('haml_lint/linter/no_plain_nodes')
+
+describe HamlLint::Linter::NoPlainNodes do
+ include_context 'linter'
+
+ context 'reports when a tag has an inline plain node' do
+ let(:haml) { '%tag Hello Tanuki' }
+ let(:message) { "`Hello Tanuki` is a plain node. Please use an i18n method like `= _('Hello Tanuki')`" }
+
+ it { is_expected.to report_lint message: message }
+ end
+
+ context 'reports when a tag has multiline plain nodes' do
+ let(:haml) { <<-HAML }
+ %tag
+ Hello
+ Tanuki
+ HAML
+
+ it { is_expected.to report_lint count: 1 }
+ end
+
+ context 'reports when a tag has an inline plain node with interpolation' do
+ let(:haml) { '%tag Hello #{"Tanuki"}!' } # rubocop:disable Lint/InterpolationCheck
+
+ it { is_expected.to report_lint }
+ end
+
+ context 'does not report when a tag has an inline script' do
+ let(:haml) { '%tag= "Hello Tanuki"' }
+
+ it { is_expected.not_to report_lint }
+ end
+
+ context 'does not report when a tag is empty' do
+ let(:haml) { '%tag' }
+
+ it { is_expected.not_to report_lint }
+ end
+
+ context 'reports multiple when a tag has multiline plain nodes split by non-text nodes' do
+ let(:haml) { <<-HAML }
+ %tag
+ Hello
+ .split-node There
+ Tanuki
+ HAML
+
+ it { is_expected.to report_lint count: 3 }
+ end
+end
diff --git a/spec/helpers/dashboard_helper_spec.rb b/spec/helpers/dashboard_helper_spec.rb
index 7ba24ba2956..023238ee0ae 100644
--- a/spec/helpers/dashboard_helper_spec.rb
+++ b/spec/helpers/dashboard_helper_spec.rb
@@ -21,4 +21,10 @@ describe DashboardHelper do
expect(helper.dashboard_nav_links).not_to include(:activity, :milestones)
end
end
+
+ describe '.has_start_trial?' do
+ subject { helper.has_start_trial? }
+
+ it { is_expected.to eq(false) }
+ end
end
diff --git a/spec/helpers/emails_helper_spec.rb b/spec/helpers/emails_helper_spec.rb
index 03b4c19ec22..e6aacb5b92b 100644
--- a/spec/helpers/emails_helper_spec.rb
+++ b/spec/helpers/emails_helper_spec.rb
@@ -1,6 +1,45 @@
require 'spec_helper'
describe EmailsHelper do
+ describe 'closure_reason_text' do
+ context 'when given a MergeRequest' do
+ let(:merge_request) { create(:merge_request) }
+ let(:merge_request_presenter) { merge_request.present }
+
+ context "and format is text" do
+ it "returns plain text" do
+ expect(closure_reason_text(merge_request, format: :text)).to eq("via merge request #{merge_request.to_reference} (#{merge_request_presenter.web_url})")
+ end
+ end
+
+ context "and format is HTML" do
+ it "returns HTML" do
+ expect(closure_reason_text(merge_request, format: :html)).to eq("via merge request #{link_to(merge_request.to_reference, merge_request_presenter.web_url)}")
+ end
+ end
+
+ context "and format is unknown" do
+ it "returns plain text" do
+ expect(closure_reason_text(merge_request, format: :text)).to eq("via merge request #{merge_request.to_reference} (#{merge_request_presenter.web_url})")
+ end
+ end
+ end
+
+ context 'when given a String' do
+ let(:closed_via) { "5a0eb6fd7e0f133044378c662fcbbc0d0c16dbfa" }
+
+ it "returns plain text" do
+ expect(closure_reason_text(closed_via)).to eq("via #{closed_via}")
+ end
+ end
+
+ context 'when not given anything' do
+ it "returns empty string" do
+ expect(closure_reason_text(nil)).to eq("")
+ end
+ end
+ end
+
describe 'sanitize_name' do
context 'when name contains a valid URL string' do
it 'returns name with `.` replaced with `_` to prevent mail clients from auto-linking URLs' do
diff --git a/spec/helpers/environments_helper_spec.rb b/spec/helpers/environments_helper_spec.rb
new file mode 100644
index 00000000000..2b8bf9319fc
--- /dev/null
+++ b/spec/helpers/environments_helper_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe EnvironmentsHelper do
+ set(:environment) { create(:environment) }
+ set(:project) { environment.project }
+ set(:user) { create(:user) }
+
+ describe '#metrics_data' do
+ before do
+ # This is so that this spec also passes in EE.
+ allow(helper).to receive(:current_user).and_return(user)
+ allow(helper).to receive(:can?).and_return(true)
+ end
+
+ let(:metrics_data) { helper.metrics_data(project, environment) }
+
+ it 'returns data' do
+ expect(metrics_data).to include(
+ 'settings-path' => edit_project_service_path(project, 'prometheus'),
+ 'clusters-path' => project_clusters_path(project),
+ 'current-environment-name': environment.name,
+ 'documentation-path' => help_page_path('administration/monitoring/prometheus/index.md'),
+ 'empty-getting-started-svg-path' => match_asset_path('/assets/illustrations/monitoring/getting_started.svg'),
+ 'empty-loading-svg-path' => match_asset_path('/assets/illustrations/monitoring/loading.svg'),
+ 'empty-no-data-svg-path' => match_asset_path('/assets/illustrations/monitoring/no_data.svg'),
+ 'empty-unable-to-connect-svg-path' => match_asset_path('/assets/illustrations/monitoring/unable_to_connect.svg'),
+ 'metrics-endpoint' => additional_metrics_project_environment_path(project, environment, format: :json),
+ 'deployments-endpoint' => project_environment_deployments_path(project, environment, format: :json),
+ 'environments-endpoint': project_environments_path(project, format: :json),
+ 'project-path' => project_path(project),
+ 'tags-path' => project_tags_path(project),
+ 'has-metrics' => "#{environment.has_metrics?}",
+ 'external-dashboard-url' => nil
+ )
+ end
+
+ context 'with metrics_setting' do
+ before do
+ create(:project_metrics_setting, project: project, external_dashboard_url: 'http://gitlab.com')
+ end
+
+ it 'adds external_dashboard_url' do
+ expect(metrics_data['external-dashboard-url']).to eq('http://gitlab.com')
+ end
+ end
+ end
+end
diff --git a/spec/helpers/gitlab_routing_helper_spec.rb b/spec/helpers/gitlab_routing_helper_spec.rb
index 143b28728a3..027480143bd 100644
--- a/spec/helpers/gitlab_routing_helper_spec.rb
+++ b/spec/helpers/gitlab_routing_helper_spec.rb
@@ -101,7 +101,7 @@ describe GitlabRoutingHelper do
it 'returns project milestone edit path when given entity parent is not a Group' do
milestone = create(:milestone, group: nil)
- expect(edit_milestone_path(milestone)).to eq("/#{milestone.project.full_path}/milestones/#{milestone.iid}/edit")
+ expect(edit_milestone_path(milestone)).to eq("/#{milestone.project.full_path}/-/milestones/#{milestone.iid}/edit")
end
end
end
diff --git a/spec/helpers/groups/group_members_helper_spec.rb b/spec/helpers/groups/group_members_helper_spec.rb
new file mode 100644
index 00000000000..898c330c498
--- /dev/null
+++ b/spec/helpers/groups/group_members_helper_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+describe Groups::GroupMembersHelper do
+ describe '.group_member_select_options' do
+ let(:group) { create(:group) }
+
+ before do
+ helper.instance_variable_set(:@group, group)
+ end
+
+ it 'returns an options hash' do
+ expect(helper.group_member_select_options).to include(multiple: true, scope: :all, email_user: true)
+ end
+ end
+end
diff --git a/spec/helpers/labels_helper_spec.rb b/spec/helpers/labels_helper_spec.rb
index a049b5a6133..314305d7a8e 100644
--- a/spec/helpers/labels_helper_spec.rb
+++ b/spec/helpers/labels_helper_spec.rb
@@ -6,7 +6,7 @@ describe LabelsHelper do
let(:context_project) { project }
context "when asking for a #{issuables_type} link" do
- subject { show_label_issuables_link?(label, issuables_type, project: context_project) }
+ subject { show_label_issuables_link?(label.present(issuable_subject: nil), issuables_type, project: context_project) }
context "when #{issuables_type} are enabled for the project" do
let(:project) { create(:project, "#{issuables_type}_access_level": ProjectFeature::ENABLED) }
@@ -67,27 +67,29 @@ describe LabelsHelper do
describe 'link_to_label' do
let(:project) { create(:project) }
let(:label) { create(:label, project: project) }
+ let(:subject) { nil }
+ let(:label_presenter) { label.present(issuable_subject: subject) }
context 'without subject' do
it "uses the label's project" do
- expect(link_to_label(label)).to match %r{<a href="/#{label.project.full_path}/issues\?label_name%5B%5D=#{label.name}">.*</a>}
+ expect(link_to_label(label_presenter)).to match %r{<a href="/#{label.project.full_path}/issues\?label_name%5B%5D=#{label.name}">.*</a>}
end
end
context 'with a project as subject' do
let(:namespace) { build(:namespace, name: 'foo3') }
- let(:another_project) { build(:project, namespace: namespace, name: 'bar3') }
+ let(:subject) { build(:project, namespace: namespace, name: 'bar3') }
it 'links to project issues page' do
- expect(link_to_label(label, subject: another_project)).to match %r{<a href="/foo3/bar3/issues\?label_name%5B%5D=#{label.name}">.*</a>}
+ expect(link_to_label(label_presenter)).to match %r{<a href="/foo3/bar3/issues\?label_name%5B%5D=#{label.name}">.*</a>}
end
end
context 'with a group as subject' do
- let(:group) { build(:group, name: 'bar') }
+ let(:subject) { build(:group, name: 'bar') }
it 'links to group issues page' do
- expect(link_to_label(label, subject: group)).to match %r{<a href="/groups/bar/-/issues\?label_name%5B%5D=#{label.name}">.*</a>}
+ expect(link_to_label(label_presenter)).to match %r{<a href="/groups/bar/-/issues\?label_name%5B%5D=#{label.name}">.*</a>}
end
end
@@ -95,7 +97,7 @@ describe LabelsHelper do
['issue', :issue, 'merge_request', :merge_request].each do |type|
context "set to #{type}" do
it 'links to correct page' do
- expect(link_to_label(label, type: type)).to match %r{<a href="/#{label.project.full_path}/#{type.to_s.pluralize}\?label_name%5B%5D=#{label.name}">.*</a>}
+ expect(link_to_label(label_presenter, type: type)).to match %r{<a href="/#{label.project.full_path}/#{type.to_s.pluralize}\?label_name%5B%5D=#{label.name}">.*</a>}
end
end
end
@@ -104,14 +106,14 @@ describe LabelsHelper do
context 'with a tooltip argument' do
context 'set to false' do
it 'does not include the has-tooltip class' do
- expect(link_to_label(label, tooltip: false)).not_to match /has-tooltip/
+ expect(link_to_label(label_presenter, tooltip: false)).not_to match /has-tooltip/
end
end
end
context 'with block' do
it 'passes the block to link_to' do
- link = link_to_label(label) { 'Foo' }
+ link = link_to_label(label_presenter) { 'Foo' }
expect(link).to match('Foo')
end
end
@@ -119,8 +121,8 @@ describe LabelsHelper do
context 'without block' do
it 'uses render_colored_label as the link content' do
expect(self).to receive(:render_colored_label)
- .with(label, tooltip: true).and_return('Foo')
- expect(link_to_label(label)).to match('Foo')
+ .with(label_presenter, tooltip: true).and_return('Foo')
+ expect(link_to_label(label_presenter)).to match('Foo')
end
end
end
@@ -237,16 +239,24 @@ describe LabelsHelper do
end
end
- describe 'labels_sorted_by_title' do
+ describe 'presented_labels_sorted_by_title' do
+ let(:labels) do
+ [build(:label, title: 'a'),
+ build(:label, title: 'B'),
+ build(:label, title: 'c'),
+ build(:label, title: 'D')]
+ end
+
it 'sorts labels alphabetically' do
- label1 = double(:label, title: 'a')
- label2 = double(:label, title: 'B')
- label3 = double(:label, title: 'c')
- label4 = double(:label, title: 'D')
- labels = [label1, label2, label3, label4]
+ sorted_ids = presented_labels_sorted_by_title(labels, nil).map(&:id)
+
+ expect(sorted_ids)
+ .to match_array([labels[1].id, labels[3].id, labels[0].id, labels[2].id])
+ end
- expect(labels_sorted_by_title(labels))
- .to match_array([label2, label4, label1, label3])
+ it 'returns an array of label presenters' do
+ expect(presented_labels_sorted_by_title(labels, nil))
+ .to all(be_a(LabelPresenter))
end
end
@@ -269,4 +279,21 @@ describe LabelsHelper do
expect(label.color).to eq('bar')
end
end
+
+ describe '#label_status_tooltip' do
+ let(:status) { 'unsubscribed'.inquiry }
+ subject { label_status_tooltip(label.present(issuable_subject: nil), status) }
+
+ context 'with a project label' do
+ let(:label) { create(:label, title: 'bug') }
+
+ it { is_expected.to eq('Subscribe at project level') }
+ end
+
+ context 'with a group label' do
+ let(:label) { create(:group_label, title: 'bug') }
+
+ it { is_expected.to eq('Subscribe at group level') }
+ end
+ end
end
diff --git a/spec/helpers/markup_helper_spec.rb b/spec/helpers/markup_helper_spec.rb
index c3956ba08fd..597c8f836a9 100644
--- a/spec/helpers/markup_helper_spec.rb
+++ b/spec/helpers/markup_helper_spec.rb
@@ -78,7 +78,8 @@ describe MarkupHelper do
let(:link) { '/commits/0a1b2c3d' }
let(:issues) { create_list(:issue, 2, project: project) }
- it 'handles references nested in links with all the text' do
+ # Clean the cache to make sure the title is re-rendered from the stubbed one
+ it 'handles references nested in links with all the text', :clean_gitlab_redis_cache do
allow(commit).to receive(:title).and_return("This should finally fix #{issues[0].to_reference} and #{issues[1].to_reference} for real")
actual = helper.link_to_markdown_field(commit, :title, link)
diff --git a/spec/helpers/nav_helper_spec.rb b/spec/helpers/nav_helper_spec.rb
index e840c927d59..979d89812f5 100644
--- a/spec/helpers/nav_helper_spec.rb
+++ b/spec/helpers/nav_helper_spec.rb
@@ -50,4 +50,16 @@ describe NavHelper do
expect(helper.header_links).to contain_exactly(:sign_in, :search)
end
end
+
+ context '.admin_monitoring_nav_links' do
+ subject { helper.admin_monitoring_nav_links }
+
+ it { is_expected.to all(be_a(String)) }
+ end
+
+ context '.group_issues_sub_menu_items' do
+ subject { helper.group_issues_sub_menu_items }
+
+ it { is_expected.to all(be_a(String)) }
+ end
end
diff --git a/spec/helpers/page_layout_helper_spec.rb b/spec/helpers/page_layout_helper_spec.rb
index cf98eed27f1..bf50763d06f 100644
--- a/spec/helpers/page_layout_helper_spec.rb
+++ b/spec/helpers/page_layout_helper_spec.rb
@@ -38,6 +38,14 @@ describe PageLayoutHelper do
expect(helper.page_description).to eq 'Bold Header'
end
+
+ it 'truncates before sanitizing' do
+ helper.page_description('<b>Bold</b> <img> <img> <img> <h1>Header</h1> ' * 10)
+
+ # 12 words because <img> was counted as a word
+ expect(helper.page_description)
+ .to eq('Bold Header Bold Header Bold Header Bold Header Bold Header Bold Header...')
+ end
end
describe 'page_image' do
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index 37c63807c82..3716879c458 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -445,6 +445,10 @@ describe ProjectsHelper do
Project.all
end
+ before do
+ stub_feature_flags(project_list_filter_bar: false)
+ end
+
it 'returns true when there are projects' do
expect(helper.show_projects?(projects, {})).to eq(true)
end
@@ -795,4 +799,46 @@ describe ProjectsHelper do
it { is_expected.to eq(result) }
end
end
+
+ describe '#can_import_members?' do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:owner) { project.owner }
+
+ before do
+ helper.instance_variable_set(:@project, project)
+ end
+
+ it 'returns false if user cannot admin_project_member' do
+ allow(helper).to receive(:current_user) { user }
+ expect(helper.can_import_members?).to eq false
+ end
+
+ it 'returns true if user can admin_project_member' do
+ allow(helper).to receive(:current_user) { owner }
+ expect(helper.can_import_members?).to eq true
+ end
+ end
+
+ describe '#metrics_external_dashboard_url' do
+ let(:project) { create(:project) }
+
+ before do
+ helper.instance_variable_set(:@project, project)
+ end
+
+ context 'metrics_setting exists' do
+ it 'returns external_dashboard_url' do
+ metrics_setting = create(:project_metrics_setting, project: project)
+
+ expect(helper.metrics_external_dashboard_url).to eq(metrics_setting.external_dashboard_url)
+ end
+ end
+
+ context 'metrics_setting does not exist' do
+ it 'returns nil' do
+ expect(helper.metrics_external_dashboard_url).to eq(nil)
+ end
+ end
+ end
end
diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb
index 2f59cfda0a0..da14f7f16fb 100644
--- a/spec/helpers/search_helper_spec.rb
+++ b/spec/helpers/search_helper_spec.rb
@@ -113,8 +113,10 @@ describe SearchHelper do
expect(search_filter_input_options('')[:data]['project-id']).to eq(@project.id)
end
- it 'includes project base-endpoint' do
+ it 'includes project endpoints' do
expect(search_filter_input_options('')[:data]['base-endpoint']).to eq(project_path(@project))
+ expect(search_filter_input_options('')[:data]['labels-endpoint']).to eq(project_labels_path(@project))
+ expect(search_filter_input_options('')[:data]['milestones-endpoint']).to eq(project_milestones_path(@project))
end
it 'includes autocomplete=off flag' do
@@ -131,8 +133,10 @@ describe SearchHelper do
expect(search_filter_input_options('')[:data]['project-id']).to eq(nil)
end
- it 'includes group base-endpoint' do
+ it 'includes group endpoints' do
expect(search_filter_input_options('')[:data]['base-endpoint']).to eq("/groups#{group_path(@group)}")
+ expect(search_filter_input_options('')[:data]['labels-endpoint']).to eq(group_labels_path(@group))
+ expect(search_filter_input_options('')[:data]['milestones-endpoint']).to eq(group_milestones_path(@group))
end
end
@@ -142,8 +146,10 @@ describe SearchHelper do
expect(search_filter_input_options('')[:data]['group-id']).to eq(nil)
end
- it 'includes dashboard base-endpoint' do
+ it 'includes dashboard endpoints' do
expect(search_filter_input_options('')[:data]['base-endpoint']).to eq("/dashboard")
+ expect(search_filter_input_options('')[:data]['labels-endpoint']).to eq(dashboard_labels_path)
+ expect(search_filter_input_options('')[:data]['milestones-endpoint']).to eq(dashboard_milestones_path)
end
end
end
diff --git a/spec/helpers/storage_helper_spec.rb b/spec/helpers/storage_helper_spec.rb
index 03df9deafa1..62c00964524 100644
--- a/spec/helpers/storage_helper_spec.rb
+++ b/spec/helpers/storage_helper_spec.rb
@@ -18,4 +18,29 @@ describe StorageHelper do
expect(helper.storage_counter(100_000_000_000_000_000_000_000)).to eq("86,736.2 EB")
end
end
+
+ describe "#storage_counters_details" do
+ let(:namespace) { create :namespace }
+ let(:project) do
+ create(:project,
+ namespace: namespace,
+ statistics: build(:project_statistics,
+ repository_size: 10.kilobytes,
+ wiki_size: 10.bytes,
+ lfs_objects_size: 20.gigabytes,
+ build_artifacts_size: 30.megabytes))
+ end
+
+ let(:message) { '10 KB repositories, 10 Bytes wikis, 30 MB build artifacts, 20 GB LFS' }
+
+ it 'works on ProjectStatistics' do
+ expect(helper.storage_counters_details(project.statistics)).to eq(message)
+ end
+
+ it 'works on Namespace.with_statistics' do
+ namespace_stats = Namespace.with_statistics.find(project.namespace.id)
+
+ expect(helper.storage_counters_details(namespace_stats)).to eq(message)
+ end
+ end
end
diff --git a/spec/helpers/tracking_helper_spec.rb b/spec/helpers/tracking_helper_spec.rb
new file mode 100644
index 00000000000..71505e8ea69
--- /dev/null
+++ b/spec/helpers/tracking_helper_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe TrackingHelper do
+ describe '#tracking_attrs' do
+ it 'returns an empty hash' do
+ expect(helper.tracking_attrs('a', 'b', 'c')).to eq({})
+ end
+ end
+end
diff --git a/spec/helpers/visibility_level_helper_spec.rb b/spec/helpers/visibility_level_helper_spec.rb
index e565ac8c530..25a2fcf5a81 100644
--- a/spec/helpers/visibility_level_helper_spec.rb
+++ b/spec/helpers/visibility_level_helper_spec.rb
@@ -162,4 +162,49 @@ describe VisibilityLevelHelper do
end
end
end
+
+ describe "selected_visibility_level" do
+ let(:group) { create(:group, :public) }
+ let!(:project) { create(:project, :internal, group: group) }
+ let!(:forked_project) { fork_project(project) }
+
+ using RSpec::Parameterized::TableSyntax
+
+ PUBLIC = Gitlab::VisibilityLevel::PUBLIC
+ INTERNAL = Gitlab::VisibilityLevel::INTERNAL
+ PRIVATE = Gitlab::VisibilityLevel::PRIVATE
+
+ # This is a subset of all the permutations
+ where(:requested_level, :max_allowed, :global_default_level, :restricted_levels, :expected) do
+ PUBLIC | PUBLIC | PUBLIC | [] | PUBLIC
+ PUBLIC | PUBLIC | PUBLIC | [PUBLIC] | INTERNAL
+ INTERNAL | PUBLIC | PUBLIC | [] | INTERNAL
+ INTERNAL | PRIVATE | PRIVATE | [] | PRIVATE
+ PRIVATE | PUBLIC | PUBLIC | [] | PRIVATE
+ PUBLIC | PRIVATE | INTERNAL | [] | PRIVATE
+ PUBLIC | INTERNAL | PUBLIC | [] | INTERNAL
+ PUBLIC | PRIVATE | PUBLIC | [] | PRIVATE
+ PUBLIC | INTERNAL | INTERNAL | [] | INTERNAL
+ PUBLIC | PUBLIC | INTERNAL | [] | PUBLIC
+ end
+
+ before do
+ stub_application_setting(restricted_visibility_levels: restricted_levels,
+ default_project_visibility: global_default_level)
+ end
+
+ with_them do
+ it "provides correct visibility level for forked project" do
+ project.update(visibility_level: max_allowed)
+
+ expect(selected_visibility_level(forked_project, requested_level)).to eq(expected)
+ end
+
+ it "provides correct visibiility level for project in group" do
+ project.group.update(visibility_level: max_allowed)
+
+ expect(selected_visibility_level(project, requested_level)).to eq(expected)
+ end
+ end
+ end
end
diff --git a/spec/initializers/secret_token_spec.rb b/spec/initializers/secret_token_spec.rb
index 6366be30079..726ce07a2d1 100644
--- a/spec/initializers/secret_token_spec.rb
+++ b/spec/initializers/secret_token_spec.rb
@@ -6,8 +6,8 @@ describe 'create_tokens' do
let(:secrets) { ActiveSupport::OrderedOptions.new }
- HEX_KEY = /\h{128}/
- RSA_KEY = /\A-----BEGIN RSA PRIVATE KEY-----\n.+\n-----END RSA PRIVATE KEY-----\n\Z/m
+ HEX_KEY = /\h{128}/.freeze
+ RSA_KEY = /\A-----BEGIN RSA PRIVATE KEY-----\n.+\n-----END RSA PRIVATE KEY-----\n\Z/m.freeze
before do
allow(File).to receive(:write)
diff --git a/spec/javascripts/activities_spec.js b/spec/javascripts/activities_spec.js
deleted file mode 100644
index 23b6de7e4e0..00000000000
--- a/spec/javascripts/activities_spec.js
+++ /dev/null
@@ -1,71 +0,0 @@
-/* eslint-disable no-unused-expressions, no-prototype-builtins, no-new, no-shadow */
-
-import $ from 'jquery';
-import 'vendor/jquery.endless-scroll';
-import Activities from '~/activities';
-import Pager from '~/pager';
-
-describe('Activities', () => {
- window.gon || (window.gon = {});
- const fixtureTemplate = 'static/event_filter.html';
- const filters = [
- {
- id: 'all',
- },
- {
- id: 'push',
- name: 'push events',
- },
- {
- id: 'merged',
- name: 'merge events',
- },
- {
- id: 'comments',
- },
- {
- id: 'team',
- },
- ];
-
- function getEventName(index) {
- const filter = filters[index];
- return filter.hasOwnProperty('name') ? filter.name : filter.id;
- }
-
- function getSelector(index) {
- const filter = filters[index];
- return `#${filter.id}_event_filter`;
- }
-
- beforeEach(() => {
- loadFixtures(fixtureTemplate);
- spyOn(Pager, 'init').and.stub();
- new Activities();
- });
-
- for (let i = 0; i < filters.length; i += 1) {
- (i => {
- describe(`when selecting ${getEventName(i)}`, () => {
- beforeEach(() => {
- $(getSelector(i)).click();
- });
-
- for (let x = 0; x < filters.length; x += 1) {
- (x => {
- const shouldHighlight = i === x;
- const testName = shouldHighlight ? 'should highlight' : 'should not highlight';
-
- it(`${testName} ${getEventName(x)}`, () => {
- expect(
- $(getSelector(x))
- .parent()
- .hasClass('active'),
- ).toEqual(shouldHighlight);
- });
- })(x);
- }
- });
- })(i);
- }
-});
diff --git a/spec/javascripts/api_spec.js b/spec/javascripts/api_spec.js
deleted file mode 100644
index e537e0e8afc..00000000000
--- a/spec/javascripts/api_spec.js
+++ /dev/null
@@ -1,465 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import Api from '~/api';
-
-describe('Api', () => {
- const dummyApiVersion = 'v3000';
- const dummyUrlRoot = 'http://host.invalid';
- const dummyGon = {
- api_version: dummyApiVersion,
- relative_url_root: dummyUrlRoot,
- };
- let originalGon;
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- originalGon = window.gon;
- window.gon = Object.assign({}, dummyGon);
- });
-
- afterEach(() => {
- mock.restore();
- window.gon = originalGon;
- });
-
- describe('buildUrl', () => {
- it('adds URL root and fills in API version', () => {
- const input = '/api/:version/foo/bar';
- const expectedOutput = `${dummyUrlRoot}/api/${dummyApiVersion}/foo/bar`;
-
- const builtUrl = Api.buildUrl(input);
-
- expect(builtUrl).toEqual(expectedOutput);
- });
- });
-
- describe('group', () => {
- it('fetches a group', done => {
- const groupId = '123456';
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}`;
- mock.onGet(expectedUrl).reply(200, {
- name: 'test',
- });
-
- Api.group(groupId, response => {
- expect(response.name).toBe('test');
- done();
- });
- });
- });
-
- describe('groupMembers', () => {
- it('fetches group members', done => {
- const groupId = '54321';
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}/members`;
- const expectedData = [{ id: 7 }];
- mock.onGet(expectedUrl).reply(200, expectedData);
-
- Api.groupMembers(groupId)
- .then(({ data }) => {
- expect(data).toEqual(expectedData);
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('groups', () => {
- it('fetches groups', done => {
- const query = 'dummy query';
- const options = { unused: 'option' };
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups.json`;
- mock.onGet(expectedUrl).reply(200, [
- {
- name: 'test',
- },
- ]);
-
- Api.groups(query, options, response => {
- expect(response.length).toBe(1);
- expect(response[0].name).toBe('test');
- done();
- });
- });
- });
-
- describe('namespaces', () => {
- it('fetches namespaces', done => {
- const query = 'dummy query';
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/namespaces.json`;
- mock.onGet(expectedUrl).reply(200, [
- {
- name: 'test',
- },
- ]);
-
- Api.namespaces(query, response => {
- expect(response.length).toBe(1);
- expect(response[0].name).toBe('test');
- done();
- });
- });
- });
-
- describe('projects', () => {
- it('fetches projects with membership when logged in', done => {
- const query = 'dummy query';
- const options = { unused: 'option' };
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects.json`;
- window.gon.current_user_id = 1;
- mock.onGet(expectedUrl).reply(200, [
- {
- name: 'test',
- },
- ]);
-
- Api.projects(query, options, response => {
- expect(response.length).toBe(1);
- expect(response[0].name).toBe('test');
- done();
- });
- });
-
- it('fetches projects without membership when not logged in', done => {
- const query = 'dummy query';
- const options = { unused: 'option' };
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects.json`;
- mock.onGet(expectedUrl).reply(200, [
- {
- name: 'test',
- },
- ]);
-
- Api.projects(query, options, response => {
- expect(response.length).toBe(1);
- expect(response[0].name).toBe('test');
- done();
- });
- });
- });
-
- describe('projectMergeRequests', () => {
- const projectPath = 'abc';
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectPath}/merge_requests`;
-
- it('fetches all merge requests for a project', done => {
- const mockData = [{ source_branch: 'foo' }, { source_branch: 'bar' }];
- mock.onGet(expectedUrl).reply(200, mockData);
- Api.projectMergeRequests(projectPath)
- .then(({ data }) => {
- expect(data.length).toEqual(2);
- expect(data[0].source_branch).toBe('foo');
- expect(data[1].source_branch).toBe('bar');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('fetches merge requests filtered with passed params', done => {
- const params = {
- source_branch: 'bar',
- };
- const mockData = [{ source_branch: 'bar' }];
- mock.onGet(expectedUrl, { params }).reply(200, mockData);
-
- Api.projectMergeRequests(projectPath, params)
- .then(({ data }) => {
- expect(data.length).toEqual(1);
- expect(data[0].source_branch).toBe('bar');
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('projectMergeRequest', () => {
- it('fetches a merge request', done => {
- const projectPath = 'abc';
- const mergeRequestId = '123456';
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectPath}/merge_requests/${mergeRequestId}`;
- mock.onGet(expectedUrl).reply(200, {
- title: 'test',
- });
-
- Api.projectMergeRequest(projectPath, mergeRequestId)
- .then(({ data }) => {
- expect(data.title).toBe('test');
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('projectMergeRequestChanges', () => {
- it('fetches the changes of a merge request', done => {
- const projectPath = 'abc';
- const mergeRequestId = '123456';
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectPath}/merge_requests/${mergeRequestId}/changes`;
- mock.onGet(expectedUrl).reply(200, {
- title: 'test',
- });
-
- Api.projectMergeRequestChanges(projectPath, mergeRequestId)
- .then(({ data }) => {
- expect(data.title).toBe('test');
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('projectMergeRequestVersions', () => {
- it('fetches the versions of a merge request', done => {
- const projectPath = 'abc';
- const mergeRequestId = '123456';
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectPath}/merge_requests/${mergeRequestId}/versions`;
- mock.onGet(expectedUrl).reply(200, [
- {
- id: 123,
- },
- ]);
-
- Api.projectMergeRequestVersions(projectPath, mergeRequestId)
- .then(({ data }) => {
- expect(data.length).toBe(1);
- expect(data[0].id).toBe(123);
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('projectRunners', () => {
- it('fetches the runners of a project', done => {
- const projectPath = 7;
- const params = { scope: 'active' };
- const mockData = [{ id: 4 }];
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectPath}/runners`;
- mock.onGet(expectedUrl, { params }).reply(200, mockData);
-
- Api.projectRunners(projectPath, { params })
- .then(({ data }) => {
- expect(data).toEqual(mockData);
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('newLabel', () => {
- it('creates a new label', done => {
- const namespace = 'some namespace';
- const project = 'some project';
- const labelData = { some: 'data' };
- const expectedUrl = `${dummyUrlRoot}/${namespace}/${project}/labels`;
- const expectedData = {
- label: labelData,
- };
- mock.onPost(expectedUrl).reply(config => {
- expect(config.data).toBe(JSON.stringify(expectedData));
-
- return [
- 200,
- {
- name: 'test',
- },
- ];
- });
-
- Api.newLabel(namespace, project, labelData, response => {
- expect(response.name).toBe('test');
- done();
- });
- });
-
- it('creates a group label', done => {
- const namespace = 'group/subgroup';
- const labelData = { some: 'data' };
- const expectedUrl = `${dummyUrlRoot}/groups/${namespace}/-/labels`;
- const expectedData = {
- label: labelData,
- };
- mock.onPost(expectedUrl).reply(config => {
- expect(config.data).toBe(JSON.stringify(expectedData));
-
- return [
- 200,
- {
- name: 'test',
- },
- ];
- });
-
- Api.newLabel(namespace, undefined, labelData, response => {
- expect(response.name).toBe('test');
- done();
- });
- });
- });
-
- describe('groupProjects', () => {
- it('fetches group projects', done => {
- const groupId = '123456';
- const query = 'dummy query';
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}/projects.json`;
- mock.onGet(expectedUrl).reply(200, [
- {
- name: 'test',
- },
- ]);
-
- Api.groupProjects(groupId, query, {}, response => {
- expect(response.length).toBe(1);
- expect(response[0].name).toBe('test');
- done();
- });
- });
- });
-
- describe('issueTemplate', () => {
- it('fetches an issue template', done => {
- const namespace = 'some namespace';
- const project = 'some project';
- const templateKey = ' template #%?.key ';
- const templateType = 'template type';
- const expectedUrl = `${dummyUrlRoot}/${namespace}/${project}/templates/${templateType}/${encodeURIComponent(
- templateKey,
- )}`;
- mock.onGet(expectedUrl).reply(200, 'test');
-
- Api.issueTemplate(namespace, project, templateKey, templateType, (error, response) => {
- expect(response).toBe('test');
- done();
- });
- });
- });
-
- describe('projectTemplates', () => {
- it('fetches a list of templates', done => {
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/gitlab-org%2Fgitlab-ce/templates/licenses`;
-
- mock.onGet(expectedUrl).reply(200, 'test');
-
- Api.projectTemplates('gitlab-org/gitlab-ce', 'licenses', {}, response => {
- expect(response).toBe('test');
- done();
- });
- });
- });
-
- describe('projectTemplate', () => {
- it('fetches a single template', done => {
- const data = { unused: 'option' };
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/gitlab-org%2Fgitlab-ce/templates/licenses/test%20license`;
-
- mock.onGet(expectedUrl).reply(200, 'test');
-
- Api.projectTemplate('gitlab-org/gitlab-ce', 'licenses', 'test license', data, response => {
- expect(response).toBe('test');
- done();
- });
- });
- });
-
- describe('users', () => {
- it('fetches users', done => {
- const query = 'dummy query';
- const options = { unused: 'option' };
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/users.json`;
- mock.onGet(expectedUrl).reply(200, [
- {
- name: 'test',
- },
- ]);
-
- Api.users(query, options)
- .then(({ data }) => {
- expect(data.length).toBe(1);
- expect(data[0].name).toBe('test');
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('user', () => {
- it('fetches single user', done => {
- const userId = '123456';
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/users/${userId}`;
- mock.onGet(expectedUrl).reply(200, {
- name: 'testuser',
- });
-
- Api.user(userId)
- .then(({ data }) => {
- expect(data.name).toBe('testuser');
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('user status', () => {
- it('fetches single user status', done => {
- const userId = '123456';
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/users/${userId}/status`;
- mock.onGet(expectedUrl).reply(200, {
- message: 'testmessage',
- });
-
- Api.userStatus(userId)
- .then(({ data }) => {
- expect(data.message).toBe('testmessage');
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('commitPipelines', () => {
- it('fetches pipelines for a given commit', done => {
- const projectId = 'example/foobar';
- const commitSha = 'abc123def';
- const expectedUrl = `${dummyUrlRoot}/${projectId}/commit/${commitSha}/pipelines`;
- mock.onGet(expectedUrl).reply(200, [
- {
- name: 'test',
- },
- ]);
-
- Api.commitPipelines(projectId, commitSha)
- .then(({ data }) => {
- expect(data.length).toBe(1);
- expect(data[0].name).toBe('test');
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('createBranch', () => {
- it('creates new branch', done => {
- const ref = 'master';
- const branch = 'new-branch-name';
- const dummyProjectPath = 'gitlab-org/gitlab-ce';
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${encodeURIComponent(
- dummyProjectPath,
- )}/repository/branches`;
-
- spyOn(axios, 'post').and.callThrough();
-
- mock.onPost(expectedUrl).replyOnce(200, {
- name: branch,
- });
-
- Api.createBranch(dummyProjectPath, { ref, branch })
- .then(({ data }) => {
- expect(data.name).toBe(branch);
- expect(axios.post).toHaveBeenCalledWith(expectedUrl, { ref, branch });
- })
- .then(done)
- .catch(done.fail);
- });
- });
-});
diff --git a/spec/javascripts/autosave_spec.js b/spec/javascripts/autosave_spec.js
deleted file mode 100644
index dcb1c781591..00000000000
--- a/spec/javascripts/autosave_spec.js
+++ /dev/null
@@ -1,154 +0,0 @@
-import $ from 'jquery';
-import Autosave from '~/autosave';
-import AccessorUtilities from '~/lib/utils/accessor';
-
-describe('Autosave', () => {
- let autosave;
- const field = $('<textarea></textarea>');
- const key = 'key';
-
- describe('class constructor', () => {
- beforeEach(() => {
- spyOn(AccessorUtilities, 'isLocalStorageAccessSafe').and.returnValue(true);
- spyOn(Autosave.prototype, 'restore');
- });
-
- it('should set .isLocalStorageAvailable', () => {
- autosave = new Autosave(field, key);
-
- expect(AccessorUtilities.isLocalStorageAccessSafe).toHaveBeenCalled();
- expect(autosave.isLocalStorageAvailable).toBe(true);
- });
- });
-
- describe('restore', () => {
- beforeEach(() => {
- autosave = {
- field,
- key,
- };
-
- spyOn(window.localStorage, 'getItem');
- });
-
- describe('if .isLocalStorageAvailable is `false`', () => {
- beforeEach(() => {
- autosave.isLocalStorageAvailable = false;
-
- Autosave.prototype.restore.call(autosave);
- });
-
- it('should not call .getItem', () => {
- expect(window.localStorage.getItem).not.toHaveBeenCalled();
- });
- });
-
- describe('if .isLocalStorageAvailable is `true`', () => {
- beforeEach(() => {
- autosave.isLocalStorageAvailable = true;
- });
-
- it('should call .getItem', () => {
- Autosave.prototype.restore.call(autosave);
-
- expect(window.localStorage.getItem).toHaveBeenCalledWith(key);
- });
-
- it('triggers jquery event', () => {
- spyOn(autosave.field, 'trigger').and.callThrough();
-
- Autosave.prototype.restore.call(autosave);
-
- expect(field.trigger).toHaveBeenCalled();
- });
-
- it('triggers native event', done => {
- autosave.field.get(0).addEventListener('change', () => {
- done();
- });
-
- Autosave.prototype.restore.call(autosave);
- });
- });
-
- describe('if field gets deleted from DOM', () => {
- beforeEach(() => {
- autosave.field = $('.not-a-real-element');
- });
-
- it('does not trigger event', () => {
- spyOn(field, 'trigger').and.callThrough();
-
- expect(field.trigger).not.toHaveBeenCalled();
- });
- });
- });
-
- describe('save', () => {
- beforeEach(() => {
- autosave = jasmine.createSpyObj('autosave', ['reset']);
- autosave.field = field;
- field.val('value');
-
- spyOn(window.localStorage, 'setItem');
- });
-
- describe('if .isLocalStorageAvailable is `false`', () => {
- beforeEach(() => {
- autosave.isLocalStorageAvailable = false;
-
- Autosave.prototype.save.call(autosave);
- });
-
- it('should not call .setItem', () => {
- expect(window.localStorage.setItem).not.toHaveBeenCalled();
- });
- });
-
- describe('if .isLocalStorageAvailable is `true`', () => {
- beforeEach(() => {
- autosave.isLocalStorageAvailable = true;
-
- Autosave.prototype.save.call(autosave);
- });
-
- it('should call .setItem', () => {
- expect(window.localStorage.setItem).toHaveBeenCalled();
- });
- });
- });
-
- describe('reset', () => {
- beforeEach(() => {
- autosave = {
- key,
- };
-
- spyOn(window.localStorage, 'removeItem');
- });
-
- describe('if .isLocalStorageAvailable is `false`', () => {
- beforeEach(() => {
- autosave.isLocalStorageAvailable = false;
-
- Autosave.prototype.reset.call(autosave);
- });
-
- it('should not call .removeItem', () => {
- expect(window.localStorage.removeItem).not.toHaveBeenCalled();
- });
- });
-
- describe('if .isLocalStorageAvailable is `true`', () => {
- beforeEach(() => {
- autosave.isLocalStorageAvailable = true;
-
- Autosave.prototype.reset.call(autosave);
- });
-
- it('should call .removeItem', () => {
- expect(window.localStorage.removeItem).toHaveBeenCalledWith(key);
- });
- });
- });
-});
diff --git a/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js b/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js
index 68b4f261617..33210794ba1 100644
--- a/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js
+++ b/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js
@@ -1,5 +1,7 @@
import BalsamiqViewer from '~/blob/balsamiq/balsamiq_viewer';
-import bmprPath from '../../fixtures/blob/balsamiq/test.bmpr';
+import { FIXTURES_PATH } from 'spec/test_constants';
+
+const bmprPath = `${FIXTURES_PATH}/blob/balsamiq/test.bmpr`;
describe('Balsamiq integration spec', () => {
let container;
diff --git a/spec/javascripts/blob/pdf/index_spec.js b/spec/javascripts/blob/pdf/index_spec.js
index acf87580777..6fa3890483c 100644
--- a/spec/javascripts/blob/pdf/index_spec.js
+++ b/spec/javascripts/blob/pdf/index_spec.js
@@ -1,5 +1,7 @@
import renderPDF from '~/blob/pdf';
-import testPDF from '../../fixtures/blob/pdf/test.pdf';
+import { FIXTURES_PATH } from 'spec/test_constants';
+
+const testPDF = `${FIXTURES_PATH}/blob/pdf/test.pdf`;
describe('PDF renderer', () => {
let viewer;
diff --git a/spec/javascripts/boards/board_card_spec.js b/spec/javascripts/boards/board_card_spec.js
index e1017130bed..13b708a03d5 100644
--- a/spec/javascripts/boards/board_card_spec.js
+++ b/spec/javascripts/boards/board_card_spec.js
@@ -7,8 +7,8 @@ import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import eventHub from '~/boards/eventhub';
-import '~/vue_shared/models/label';
-import '~/vue_shared/models/assignee';
+import '~/boards/models/label';
+import '~/boards/models/assignee';
import '~/boards/models/list';
import boardsStore from '~/boards/stores/boards_store';
import boardCard from '~/boards/components/board_card.vue';
diff --git a/spec/javascripts/boards/board_list_common_spec.js b/spec/javascripts/boards/board_list_common_spec.js
new file mode 100644
index 00000000000..cb337e4cc83
--- /dev/null
+++ b/spec/javascripts/boards/board_list_common_spec.js
@@ -0,0 +1,58 @@
+/* global List */
+/* global ListIssue */
+
+import MockAdapter from 'axios-mock-adapter';
+import Vue from 'vue';
+import axios from '~/lib/utils/axios_utils';
+import Sortable from 'sortablejs';
+import BoardList from '~/boards/components/board_list.vue';
+
+import '~/boards/models/issue';
+import '~/boards/models/list';
+import { listObj, boardsMockInterceptor, mockBoardService } from './mock_data';
+import boardsStore from '~/boards/stores/boards_store';
+
+window.Sortable = Sortable;
+
+export default function createComponent({ done, listIssueProps = {}, componentProps = {} }) {
+ const el = document.createElement('div');
+
+ document.body.appendChild(el);
+ const mock = new MockAdapter(axios);
+ mock.onAny().reply(boardsMockInterceptor);
+ gl.boardService = mockBoardService();
+ boardsStore.create();
+
+ const BoardListComp = Vue.extend(BoardList);
+ const list = new List(listObj);
+ const issue = new ListIssue({
+ title: 'Testing',
+ id: 1,
+ iid: 1,
+ confidential: false,
+ labels: [],
+ assignees: [],
+ ...listIssueProps,
+ });
+ list.issuesSize = 1;
+ list.issues.push(issue);
+
+ const component = new BoardListComp({
+ el,
+ propsData: {
+ disabled: false,
+ list,
+ issues: list.issues,
+ loading: false,
+ issueLinkBase: '/issues',
+ rootPath: '/',
+ ...componentProps,
+ },
+ }).$mount();
+
+ Vue.nextTick(() => {
+ done();
+ });
+
+ return { component, mock };
+}
diff --git a/spec/javascripts/boards/board_list_spec.js b/spec/javascripts/boards/board_list_spec.js
index 396fc823ef5..9c9b435d7fd 100644
--- a/spec/javascripts/boards/board_list_spec.js
+++ b/spec/javascripts/boards/board_list_spec.js
@@ -1,60 +1,13 @@
-/* global List */
-/* global ListIssue */
-
import Vue from 'vue';
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import Sortable from 'sortablejs';
-import BoardList from '~/boards/components/board_list.vue';
import eventHub from '~/boards/eventhub';
-import '~/boards/models/issue';
-import '~/boards/models/list';
-import boardsStore from '~/boards/stores/boards_store';
-import { listObj, boardsMockInterceptor, mockBoardService } from './mock_data';
-
-window.Sortable = Sortable;
+import createComponent from './board_list_common_spec';
describe('Board list component', () => {
let mock;
let component;
beforeEach(done => {
- const el = document.createElement('div');
-
- document.body.appendChild(el);
- mock = new MockAdapter(axios);
- mock.onAny().reply(boardsMockInterceptor);
- gl.boardService = mockBoardService();
- boardsStore.create();
-
- const BoardListComp = Vue.extend(BoardList);
- const list = new List(listObj);
- const issue = new ListIssue({
- title: 'Testing',
- id: 1,
- iid: 1,
- confidential: false,
- labels: [],
- assignees: [],
- });
- list.issuesSize = 1;
- list.issues.push(issue);
-
- component = new BoardListComp({
- el,
- propsData: {
- disabled: false,
- list,
- issues: list.issues,
- loading: false,
- issueLinkBase: '/issues',
- rootPath: '/',
- },
- }).$mount();
-
- Vue.nextTick(() => {
- done();
- });
+ ({ mock, component } = createComponent({ done }));
});
afterEach(() => {
diff --git a/spec/javascripts/boards/boards_store_spec.js b/spec/javascripts/boards/boards_store_spec.js
index 22f192bc7f3..e81115e10c9 100644
--- a/spec/javascripts/boards/boards_store_spec.js
+++ b/spec/javascripts/boards/boards_store_spec.js
@@ -6,12 +6,13 @@ import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import Cookies from 'js-cookie';
-import '~/vue_shared/models/label';
-import '~/vue_shared/models/assignee';
+import '~/boards/models/label';
+import '~/boards/models/assignee';
import '~/boards/models/issue';
import '~/boards/models/list';
import '~/boards/services/board_service';
import boardsStore from '~/boards/stores/boards_store';
+import eventHub from '~/boards/eventhub';
import { listObj, listObjDuplicate, boardsMockInterceptor, mockBoardService } from './mock_data';
describe('Store', () => {
@@ -44,6 +45,48 @@ describe('Store', () => {
expect(boardsStore.state.lists.length).toBe(0);
});
+ describe('addList', () => {
+ it('sorts by position', () => {
+ boardsStore.addList({ position: 2 });
+ boardsStore.addList({ position: 1 });
+
+ expect(boardsStore.state.lists[0].position).toBe(1);
+ });
+ });
+
+ describe('toggleFilter', () => {
+ const dummyFilter = 'x=42';
+ let updateTokensSpy;
+
+ beforeEach(() => {
+ updateTokensSpy = jasmine.createSpy('updateTokens');
+ eventHub.$once('updateTokens', updateTokensSpy);
+
+ // prevent using window.history
+ spyOn(boardsStore, 'updateFiltersUrl').and.callFake(() => {});
+ });
+
+ it('adds the filter if it is not present', () => {
+ boardsStore.filter.path = 'something';
+
+ boardsStore.toggleFilter(dummyFilter);
+
+ expect(boardsStore.filter.path).toEqual(`something&${dummyFilter}`);
+ expect(updateTokensSpy).toHaveBeenCalled();
+ expect(boardsStore.updateFiltersUrl).toHaveBeenCalled();
+ });
+
+ it('removes the filter if it is present', () => {
+ boardsStore.filter.path = `something&${dummyFilter}`;
+
+ boardsStore.toggleFilter(dummyFilter);
+
+ expect(boardsStore.filter.path).toEqual('something');
+ expect(updateTokensSpy).toHaveBeenCalled();
+ expect(boardsStore.updateFiltersUrl).toHaveBeenCalled();
+ });
+ });
+
describe('lists', () => {
it('creates new list without persisting to DB', () => {
boardsStore.addList(listObj);
@@ -268,4 +311,48 @@ describe('Store', () => {
});
});
});
+
+ describe('setListDetail', () => {
+ it('sets the list detail', () => {
+ boardsStore.detail.list = 'not a list';
+
+ const dummyValue = 'new list';
+ boardsStore.setListDetail(dummyValue);
+
+ expect(boardsStore.detail.list).toEqual(dummyValue);
+ });
+ });
+
+ describe('clearDetailIssue', () => {
+ it('resets issue details', () => {
+ boardsStore.detail.issue = 'something';
+
+ boardsStore.clearDetailIssue();
+
+ expect(boardsStore.detail.issue).toEqual({});
+ });
+ });
+
+ describe('setIssueDetail', () => {
+ it('sets issue details', () => {
+ boardsStore.detail.issue = 'some details';
+
+ const dummyValue = 'new details';
+ boardsStore.setIssueDetail(dummyValue);
+
+ expect(boardsStore.detail.issue).toEqual(dummyValue);
+ });
+ });
+
+ describe('startMoving', () => {
+ it('stores list and issue', () => {
+ const dummyIssue = 'some issue';
+ const dummyList = 'some list';
+
+ boardsStore.startMoving(dummyList, dummyIssue);
+
+ expect(boardsStore.moving.issue).toEqual(dummyIssue);
+ expect(boardsStore.moving.list).toEqual(dummyList);
+ });
+ });
});
diff --git a/spec/javascripts/boards/issue_card_spec.js b/spec/javascripts/boards/issue_card_spec.js
index 6eda5047dd0..8a20911cc66 100644
--- a/spec/javascripts/boards/issue_card_spec.js
+++ b/spec/javascripts/boards/issue_card_spec.js
@@ -4,8 +4,8 @@
import Vue from 'vue';
-import '~/vue_shared/models/label';
-import '~/vue_shared/models/assignee';
+import '~/boards/models/label';
+import '~/boards/models/assignee';
import '~/boards/models/issue';
import '~/boards/models/list';
import IssueCardInner from '~/boards/components/issue_card_inner.vue';
@@ -285,4 +285,10 @@ describe('Issue card component', () => {
.catch(done.fail);
});
});
+
+ describe('weights', () => {
+ it('not shows weight component', () => {
+ expect(component.$el.querySelector('.board-card-weight')).toBeNull();
+ });
+ });
});
diff --git a/spec/javascripts/boards/issue_spec.js b/spec/javascripts/boards/issue_spec.js
index e4ff3eb381f..bb7abe52eae 100644
--- a/spec/javascripts/boards/issue_spec.js
+++ b/spec/javascripts/boards/issue_spec.js
@@ -1,8 +1,8 @@
/* global ListIssue */
import Vue from 'vue';
-import '~/vue_shared/models/label';
-import '~/vue_shared/models/assignee';
+import '~/boards/models/label';
+import '~/boards/models/assignee';
import '~/boards/models/issue';
import '~/boards/models/list';
import '~/boards/services/board_service';
diff --git a/spec/javascripts/boards/list_spec.js b/spec/javascripts/boards/list_spec.js
index 0d462a6f872..15c9ff6dfb4 100644
--- a/spec/javascripts/boards/list_spec.js
+++ b/spec/javascripts/boards/list_spec.js
@@ -4,8 +4,8 @@
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import _ from 'underscore';
-import '~/vue_shared/models/label';
-import '~/vue_shared/models/assignee';
+import '~/boards/models/label';
+import '~/boards/models/assignee';
import '~/boards/models/issue';
import '~/boards/models/list';
import '~/boards/services/board_service';
@@ -45,6 +45,7 @@ describe('List model', () => {
id: _.random(10000),
title: 'test',
color: 'red',
+ text_color: 'white',
},
});
list.save();
@@ -53,6 +54,8 @@ describe('List model', () => {
expect(list.id).toBe(listObj.id);
expect(list.type).toBe('label');
expect(list.position).toBe(0);
+ expect(list.label.color).toBe('red');
+ expect(list.label.textColor).toBe('white');
done();
}, 0);
});
diff --git a/spec/javascripts/boards/mock_data.js b/spec/javascripts/boards/mock_data.js
index 14fff9223f4..9854cf49e97 100644
--- a/spec/javascripts/boards/mock_data.js
+++ b/spec/javascripts/boards/mock_data.js
@@ -16,6 +16,7 @@ export const listObj = {
title: 'Testing',
color: 'red',
description: 'testing;',
+ textColor: 'white',
},
};
@@ -46,7 +47,7 @@ export const BoardsMockData = {
},
],
},
- '/test/issue-boards/milestones.json': [
+ '/test/issue-boards/-/milestones.json': [
{
id: 1,
title: 'test',
@@ -57,10 +58,10 @@ export const BoardsMockData = {
'/test/-/boards/1/lists': listObj,
},
PUT: {
- '/test/issue-boards/board/1/lists{/id}': {},
+ '/test/issue-boards/-/board/1/lists{/id}': {},
},
DELETE: {
- '/test/issue-boards/board/1/lists{/id}': {},
+ '/test/issue-boards/-/board/1/lists{/id}': {},
},
};
@@ -70,7 +71,7 @@ export const boardsMockInterceptor = config => {
};
export const mockBoardService = (opts = {}) => {
- const boardsEndpoint = opts.boardsEndpoint || '/test/issue-boards/boards.json';
+ const boardsEndpoint = opts.boardsEndpoint || '/test/issue-boards/-/boards.json';
const listsEndpoint = opts.listsEndpoint || '/test/-/boards/1/lists';
const bulkUpdatePath = opts.bulkUpdatePath || '';
const boardId = opts.boardId || '1';
diff --git a/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js b/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js
index 481b1a4d4b0..e6a969bd855 100644
--- a/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js
+++ b/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js
@@ -32,6 +32,7 @@ describe('AjaxFormVariableList', () => {
saveButton,
errorBox,
saveEndpoint: container.dataset.saveEndpoint,
+ maskableRegex: container.dataset.maskableRegex,
});
spyOn(ajaxVariableList, 'updateRowsWithPersistedVariables').and.callThrough();
@@ -113,7 +114,7 @@ describe('AjaxFormVariableList', () => {
it('hides secret values', done => {
mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(200, {});
- const row = container.querySelector('.js-row:first-child');
+ const row = container.querySelector('.js-row');
const valueInput = row.querySelector('.js-ci-variable-input-value');
const valuePlaceholder = row.querySelector('.js-secret-value-placeholder');
@@ -220,4 +221,11 @@ describe('AjaxFormVariableList', () => {
expect(row.dataset.isPersisted).toEqual('true');
});
});
+
+ describe('maskableRegex', () => {
+ it('takes in the regex provided by the data attribute', () => {
+ expect(container.dataset.maskableRegex).toBe('^[a-zA-Z0-9_+=/-]{8,}$');
+ expect(ajaxVariableList.maskableRegex).toBe(container.dataset.maskableRegex);
+ });
+ });
});
diff --git a/spec/javascripts/ci_variable_list/ci_variable_list_spec.js b/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
index 394e60fc22c..064113e879a 100644
--- a/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
+++ b/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
@@ -150,6 +150,65 @@ describe('VariableList', () => {
.then(done)
.catch(done.fail);
});
+
+ describe('validateMaskability', () => {
+ let $row;
+
+ const maskingErrorElement = '.js-row:last-child .masking-validation-error';
+
+ beforeEach(() => {
+ $row = $wrapper.find('.js-row:last-child');
+ $row.find('.ci-variable-masked-item .js-project-feature-toggle').click();
+ });
+
+ it('has a regex provided via a data attribute', () => {
+ expect($wrapper.attr('data-maskable-regex')).toBe('^[a-zA-Z0-9_+=/-]{8,}$');
+ });
+
+ it('allows values that are 8 characters long', done => {
+ $row.find('.js-ci-variable-input-value').val('looooong');
+
+ getSetTimeoutPromise()
+ .then(() => {
+ expect($wrapper.find(maskingErrorElement)).toHaveClass('hide');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('rejects values that are shorter than 8 characters', done => {
+ $row.find('.js-ci-variable-input-value').val('short');
+
+ getSetTimeoutPromise()
+ .then(() => {
+ expect($wrapper.find(maskingErrorElement)).toBeVisible();
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('allows values with base 64 characters', done => {
+ $row.find('.js-ci-variable-input-value').val('abcABC123_+=/-');
+
+ getSetTimeoutPromise()
+ .then(() => {
+ expect($wrapper.find(maskingErrorElement)).toHaveClass('hide');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('rejects values with other special characters', done => {
+ $row.find('.js-ci-variable-input-value').val('1234567$');
+
+ getSetTimeoutPromise()
+ .then(() => {
+ expect($wrapper.find(maskingErrorElement)).toBeVisible();
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
});
describe('toggleEnableRow method', () => {
diff --git a/spec/javascripts/diffs/components/commit_item_spec.js b/spec/javascripts/diffs/components/commit_item_spec.js
index 50e45f48af3..dc3fb16eb40 100644
--- a/spec/javascripts/diffs/components/commit_item_spec.js
+++ b/spec/javascripts/diffs/components/commit_item_spec.js
@@ -1,14 +1,14 @@
import Vue from 'vue';
import { TEST_HOST } from 'spec/test_constants';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import { trimText } from 'spec/helpers/vue_component_helper';
+import { trimText } from 'spec/helpers/text_helper';
import { getTimeago } from '~/lib/utils/datetime_utility';
import CommitItem from '~/diffs/components/commit_item.vue';
import getDiffWithCommit from '../mock_data/diff_with_commit';
const TEST_AUTHOR_NAME = 'test';
const TEST_AUTHOR_EMAIL = 'test+test@gitlab.com';
-const TEST_AUTHOR_GRAVATAR = `${TEST_HOST}/avatar/test?s=36`;
+const TEST_AUTHOR_GRAVATAR = `${TEST_HOST}/avatar/test?s=40`;
const TEST_SIGNATURE_HTML = '<a>Legit commit</a>';
const TEST_PIPELINE_STATUS_PATH = `${TEST_HOST}/pipeline/status`;
@@ -18,7 +18,7 @@ const getDescExpandElement = vm =>
vm.$el.querySelector('.commit-content .text-expander.js-toggle-button');
const getShaElement = vm => vm.$el.querySelector('.commit-sha-group');
const getAvatarElement = vm => vm.$el.querySelector('.user-avatar-link');
-const getCommitterElement = vm => vm.$el.querySelector('.commiter');
+const getCommitterElement = vm => vm.$el.querySelector('.committer');
const getCommitActionsElement = vm => vm.$el.querySelector('.commit-actions');
describe('diffs/components/commit_item', () => {
@@ -65,7 +65,7 @@ describe('diffs/components/commit_item', () => {
const imgElement = avatarElement.querySelector('img');
expect(avatarElement).toHaveAttr('href', commit.author.web_url);
- expect(imgElement).toHaveClass('s36');
+ expect(imgElement).toHaveClass('s40');
expect(imgElement).toHaveAttr('alt', commit.author.name);
expect(imgElement).toHaveAttr('src', commit.author.avatar_url);
});
diff --git a/spec/javascripts/diffs/components/diff_content_spec.js b/spec/javascripts/diffs/components/diff_content_spec.js
index bc9288e4150..124bdeea45d 100644
--- a/spec/javascripts/diffs/components/diff_content_spec.js
+++ b/spec/javascripts/diffs/components/diff_content_spec.js
@@ -29,6 +29,10 @@ describe('DiffContent', () => {
});
});
+ afterEach(() => {
+ vm.$destroy();
+ });
+
describe('text based files', () => {
it('should render diff inline view', done => {
vm.$store.state.diffs.diffViewType = 'inline';
@@ -49,6 +53,16 @@ describe('DiffContent', () => {
done();
});
});
+
+ it('renders rendering more lines loading icon', done => {
+ vm.diffFile.renderingLines = true;
+
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.loading-container')).not.toBe(null);
+
+ done();
+ });
+ });
});
describe('empty files', () => {
diff --git a/spec/javascripts/diffs/components/diff_discussions_spec.js b/spec/javascripts/diffs/components/diff_discussions_spec.js
index 0bc9da5ad0f..f7f0ab83c21 100644
--- a/spec/javascripts/diffs/components/diff_discussions_spec.js
+++ b/spec/javascripts/diffs/components/diff_discussions_spec.js
@@ -1,90 +1,103 @@
-import Vue from 'vue';
+import { mount, createLocalVue } from '@vue/test-utils';
import DiffDiscussions from '~/diffs/components/diff_discussions.vue';
+import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
+import NoteableDiscussion from '~/notes/components/noteable_discussion.vue';
+import DiscussionNotes from '~/notes/components/discussion_notes.vue';
+import Icon from '~/vue_shared/components/icon.vue';
import { createStore } from '~/mr_notes/stores';
-import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import '~/behaviors/markdown/render_gfm';
import discussionsMockData from '../mock_data/diff_discussions';
+const localVue = createLocalVue();
+
describe('DiffDiscussions', () => {
- let vm;
+ let store;
+ let wrapper;
const getDiscussionsMockData = () => [Object.assign({}, discussionsMockData)];
- function createComponent(props = {}) {
- const store = createStore();
-
- vm = createComponentWithStore(Vue.extend(DiffDiscussions), store, {
- discussions: getDiscussionsMockData(),
- ...props,
- }).$mount();
- }
+ const createComponent = props => {
+ store = createStore();
+ wrapper = mount(localVue.extend(DiffDiscussions), {
+ store,
+ propsData: {
+ discussions: getDiscussionsMockData(),
+ ...props,
+ },
+ localVue,
+ sync: false,
+ });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
describe('template', () => {
it('should have notes list', () => {
createComponent();
- expect(vm.$el.querySelectorAll('.discussion .note.timeline-entry').length).toEqual(5);
+ expect(wrapper.find(NoteableDiscussion).exists()).toBe(true);
+ expect(wrapper.find(DiscussionNotes).exists()).toBe(true);
+ expect(wrapper.find(DiscussionNotes).findAll(TimelineEntryItem).length).toBe(
+ discussionsMockData.notes.length,
+ );
});
});
describe('image commenting', () => {
+ const findDiffNotesToggle = () => wrapper.find('.js-diff-notes-toggle');
+
it('renders collapsible discussion button', () => {
createComponent({ shouldCollapseDiscussions: true });
+ const diffNotesToggle = findDiffNotesToggle();
- expect(vm.$el.querySelector('.js-diff-notes-toggle')).not.toBe(null);
- expect(vm.$el.querySelector('.js-diff-notes-toggle svg')).not.toBe(null);
- expect(vm.$el.querySelector('.js-diff-notes-toggle').classList).toContain(
- 'diff-notes-collapse',
- );
+ expect(diffNotesToggle.exists()).toBe(true);
+ expect(diffNotesToggle.find(Icon).exists()).toBe(true);
+ expect(diffNotesToggle.classes('diff-notes-collapse')).toBe(true);
});
it('dispatches toggleDiscussion when clicking collapse button', () => {
createComponent({ shouldCollapseDiscussions: true });
+ spyOn(wrapper.vm.$store, 'dispatch').and.stub();
+ const diffNotesToggle = findDiffNotesToggle();
+ diffNotesToggle.trigger('click');
- spyOn(vm.$store, 'dispatch').and.stub();
-
- vm.$el.querySelector('.js-diff-notes-toggle').click();
-
- expect(vm.$store.dispatch).toHaveBeenCalledWith('toggleDiscussion', {
- discussionId: vm.discussions[0].id,
+ expect(wrapper.vm.$store.dispatch).toHaveBeenCalledWith('toggleDiscussion', {
+ discussionId: discussionsMockData.id,
});
});
- it('renders expand button when discussion is collapsed', done => {
- createComponent({ shouldCollapseDiscussions: true });
-
- vm.discussions[0].expanded = false;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.js-diff-notes-toggle').textContent.trim()).toBe('1');
- expect(vm.$el.querySelector('.js-diff-notes-toggle').className).toContain(
- 'btn-transparent badge badge-pill',
- );
+ it('renders expand button when discussion is collapsed', () => {
+ const discussions = getDiscussionsMockData();
+ discussions[0].expanded = false;
+ createComponent({ discussions, shouldCollapseDiscussions: true });
+ const diffNotesToggle = findDiffNotesToggle();
- done();
- });
+ expect(diffNotesToggle.text().trim()).toBe('1');
+ expect(diffNotesToggle.classes()).toEqual(
+ jasmine.arrayContaining(['btn-transparent', 'badge', 'badge-pill']),
+ );
});
- it('hides discussion when collapsed', done => {
- createComponent({ shouldCollapseDiscussions: true });
+ it('hides discussion when collapsed', () => {
+ const discussions = getDiscussionsMockData();
+ discussions[0].expanded = false;
+ createComponent({ discussions, shouldCollapseDiscussions: true });
- vm.discussions[0].expanded = false;
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.note-discussion').style.display).toBe('none');
-
- done();
- });
+ expect(wrapper.find(NoteableDiscussion).isVisible()).toBe(false);
});
it('renders badge on avatar', () => {
- createComponent({ renderAvatarBadge: true, discussions: [{ ...discussionsMockData }] });
-
- expect(vm.$el.querySelector('.user-avatar-link .badge-pill')).not.toBe(null);
- expect(vm.$el.querySelector('.user-avatar-link .badge-pill').textContent.trim()).toBe('1');
+ createComponent({ renderAvatarBadge: true });
+ const noteableDiscussion = wrapper.find(NoteableDiscussion);
+
+ expect(noteableDiscussion.find('.badge-pill').exists()).toBe(true);
+ expect(
+ noteableDiscussion
+ .find('.badge-pill')
+ .text()
+ .trim(),
+ ).toBe('1');
});
});
});
diff --git a/spec/javascripts/diffs/mock_data/diff_file.js b/spec/javascripts/diffs/mock_data/diff_file.js
index 32af9ea8ddd..27428197c1c 100644
--- a/spec/javascripts/diffs/mock_data/diff_file.js
+++ b/spec/javascripts/diffs/mock_data/diff_file.js
@@ -240,4 +240,5 @@ export default {
},
],
discussions: [],
+ renderingLines: false,
};
diff --git a/spec/javascripts/diffs/store/actions_spec.js b/spec/javascripts/diffs/store/actions_spec.js
index bca99caa920..f129fbb57a3 100644
--- a/spec/javascripts/diffs/store/actions_spec.js
+++ b/spec/javascripts/diffs/store/actions_spec.js
@@ -36,6 +36,7 @@ import actions, {
fetchFullDiff,
toggleFullDiff,
setFileCollapsed,
+ setExpandedDiffLines,
} from '~/diffs/store/actions';
import eventHub from '~/notes/event_hub';
import * as types from '~/diffs/store/mutation_types';
@@ -81,7 +82,7 @@ describe('DiffsStoreActions', () => {
describe('fetchDiffFiles', () => {
it('should fetch diff files', done => {
- const endpoint = '/fetch/diff/files';
+ const endpoint = '/fetch/diff/files?w=1';
const mock = new MockAdapter(axios);
const res = { diff_files: 1, merge_request_diffs: [] };
mock.onGet(endpoint).reply(200, res);
@@ -395,6 +396,7 @@ describe('DiffsStoreActions', () => {
});
describe('loadCollapsedDiff', () => {
+ const state = { showWhitespace: true };
it('should fetch data and call mutation with response and the give parameter', done => {
const file = { hash: 123, load_collapsed_diff_url: '/load/collapsed/diff/url' };
const data = { hash: 123, parallelDiffLines: [{ lineCode: 1 }] };
@@ -402,7 +404,7 @@ describe('DiffsStoreActions', () => {
const commit = jasmine.createSpy('commit');
mock.onGet(file.loadCollapsedDiffUrl).reply(200, data);
- loadCollapsedDiff({ commit, getters: { commitId: null } }, file)
+ loadCollapsedDiff({ commit, getters: { commitId: null }, state }, file)
.then(() => {
expect(commit).toHaveBeenCalledWith(types.ADD_COLLAPSED_DIFFS, { file, data });
@@ -420,10 +422,10 @@ describe('DiffsStoreActions', () => {
spyOn(axios, 'get').and.returnValue(Promise.resolve({ data: {} }));
- loadCollapsedDiff({ commit() {}, getters }, file);
+ loadCollapsedDiff({ commit() {}, getters, state }, file);
expect(axios.get).toHaveBeenCalledWith(file.load_collapsed_diff_url, {
- params: { commit_id: null },
+ params: { commit_id: null, w: '0' },
});
});
@@ -435,10 +437,10 @@ describe('DiffsStoreActions', () => {
spyOn(axios, 'get').and.returnValue(Promise.resolve({ data: {} }));
- loadCollapsedDiff({ commit() {}, getters }, file);
+ loadCollapsedDiff({ commit() {}, getters, state }, file);
expect(axios.get).toHaveBeenCalledWith(file.load_collapsed_diff_url, {
- params: { commit_id: '123' },
+ params: { commit_id: '123', w: '0' },
});
});
});
@@ -827,6 +829,10 @@ describe('DiffsStoreActions', () => {
});
describe('setShowWhitespace', () => {
+ beforeEach(() => {
+ spyOn(eventHub, '$emit').and.stub();
+ });
+
it('commits SET_SHOW_WHITESPACE', done => {
testAction(
setShowWhitespace,
@@ -854,6 +860,30 @@ describe('DiffsStoreActions', () => {
expect(window.history.pushState).toHaveBeenCalled();
});
+
+ it('calls history pushState with merged params', () => {
+ const originalPushState = window.history;
+
+ originalPushState.pushState({}, '', '?test=1');
+
+ spyOn(localStorage, 'setItem').and.stub();
+ spyOn(window.history, 'pushState').and.stub();
+
+ setShowWhitespace({ commit() {} }, { showWhitespace: true, pushState: true });
+
+ expect(window.history.pushState.calls.mostRecent().args[2]).toMatch(/(.*)\?test=1&w=0/);
+
+ originalPushState.pushState({}, '', '?');
+ });
+
+ it('emits eventHub event', () => {
+ spyOn(localStorage, 'setItem').and.stub();
+ spyOn(window.history, 'pushState').and.stub();
+
+ setShowWhitespace({ commit() {} }, { showWhitespace: true, pushState: true });
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('refetchDiffData');
+ });
});
describe('setRenderIt', () => {
@@ -879,9 +909,9 @@ describe('DiffsStoreActions', () => {
it('commits REQUEST_FULL_DIFF', done => {
testAction(
receiveFullDiffSucess,
- { filePath: 'test', data: 'test' },
+ { filePath: 'test' },
{},
- [{ type: types.RECEIVE_FULL_DIFF_SUCCESS, payload: { filePath: 'test', data: 'test' } }],
+ [{ type: types.RECEIVE_FULL_DIFF_SUCCESS, payload: { filePath: 'test' } }],
[],
done,
);
@@ -903,11 +933,8 @@ describe('DiffsStoreActions', () => {
describe('fetchFullDiff', () => {
let mock;
- let scrollToElementSpy;
beforeEach(() => {
- scrollToElementSpy = spyOnDependency(actions, 'scrollToElement').and.stub();
-
mock = new MockAdapter(axios);
});
@@ -921,28 +948,23 @@ describe('DiffsStoreActions', () => {
});
it('dispatches receiveFullDiffSucess', done => {
+ const file = {
+ context_lines_path: `${gl.TEST_HOST}/context`,
+ file_path: 'test',
+ file_hash: 'test',
+ };
testAction(
fetchFullDiff,
- { context_lines_path: `${gl.TEST_HOST}/context`, file_path: 'test', file_hash: 'test' },
+ file,
null,
[],
- [{ type: 'receiveFullDiffSucess', payload: { filePath: 'test', data: ['test'] } }],
+ [
+ { type: 'receiveFullDiffSucess', payload: { filePath: 'test' } },
+ { type: 'setExpandedDiffLines', payload: { file, data: ['test'] } },
+ ],
done,
);
});
-
- it('scrolls to element', done => {
- fetchFullDiff(
- { dispatch() {} },
- { context_lines_path: `${gl.TEST_HOST}/context`, file_path: 'test', file_hash: 'test' },
- )
- .then(() => {
- expect(scrollToElementSpy).toHaveBeenCalledWith('#test');
-
- done();
- })
- .catch(done.fail);
- });
});
describe('error', () => {
@@ -999,4 +1021,63 @@ describe('DiffsStoreActions', () => {
);
});
});
+
+ describe('setExpandedDiffLines', () => {
+ beforeEach(() => {
+ spyOnDependency(actions, 'idleCallback').and.callFake(cb => {
+ cb({ timeRemaining: () => 50 });
+ });
+ });
+
+ it('commits SET_CURRENT_VIEW_DIFF_FILE_LINES when lines less than MAX_RENDERING_DIFF_LINES', done => {
+ spyOnDependency(actions, 'convertExpandLines').and.callFake(() => ['test']);
+
+ testAction(
+ setExpandedDiffLines,
+ { file: { file_path: 'path' }, data: [] },
+ { diffViewType: 'inline' },
+ [
+ {
+ type: 'SET_HIDDEN_VIEW_DIFF_FILE_LINES',
+ payload: { filePath: 'path', lines: ['test'] },
+ },
+ {
+ type: 'SET_CURRENT_VIEW_DIFF_FILE_LINES',
+ payload: { filePath: 'path', lines: ['test'] },
+ },
+ ],
+ [],
+ done,
+ );
+ });
+
+ it('commits ADD_CURRENT_VIEW_DIFF_FILE_LINES when lines more than MAX_RENDERING_DIFF_LINES', done => {
+ const lines = new Array(501).fill().map((_, i) => `line-${i}`);
+ spyOnDependency(actions, 'convertExpandLines').and.callFake(() => lines);
+
+ testAction(
+ setExpandedDiffLines,
+ { file: { file_path: 'path' }, data: [] },
+ { diffViewType: 'inline' },
+ [
+ {
+ type: 'SET_HIDDEN_VIEW_DIFF_FILE_LINES',
+ payload: { filePath: 'path', lines },
+ },
+ {
+ type: 'SET_CURRENT_VIEW_DIFF_FILE_LINES',
+ payload: { filePath: 'path', lines: lines.slice(0, 200) },
+ },
+ { type: 'TOGGLE_DIFF_FILE_RENDERING_MORE', payload: 'path' },
+ ...new Array(301).fill().map((_, i) => ({
+ type: 'ADD_CURRENT_VIEW_DIFF_FILE_LINES',
+ payload: { filePath: 'path', line: `line-${i + 200}` },
+ })),
+ { type: 'TOGGLE_DIFF_FILE_RENDERING_MORE', payload: 'path' },
+ ],
+ [],
+ done,
+ );
+ });
+ });
});
diff --git a/spec/javascripts/diffs/store/mutations_spec.js b/spec/javascripts/diffs/store/mutations_spec.js
index 5556a994a14..fa193e1d3b9 100644
--- a/spec/javascripts/diffs/store/mutations_spec.js
+++ b/spec/javascripts/diffs/store/mutations_spec.js
@@ -756,4 +756,98 @@ describe('DiffsStoreMutations', () => {
expect(state.diffFiles[0].viewer.collapsed).toBe(true);
});
});
+
+ describe('SET_HIDDEN_VIEW_DIFF_FILE_LINES', () => {
+ [
+ { current: 'highlighted', hidden: 'parallel', diffViewType: 'inline' },
+ { current: 'parallel', hidden: 'highlighted', diffViewType: 'parallel' },
+ ].forEach(({ current, hidden, diffViewType }) => {
+ it(`sets the ${hidden} lines when diff view is ${diffViewType}`, () => {
+ const file = { file_path: 'test', parallel_diff_lines: [], highlighted_diff_lines: [] };
+ const state = {
+ diffFiles: [file],
+ diffViewType,
+ };
+
+ mutations[types.SET_HIDDEN_VIEW_DIFF_FILE_LINES](state, {
+ filePath: 'test',
+ lines: ['test'],
+ });
+
+ expect(file[`${current}_diff_lines`]).toEqual([]);
+ expect(file[`${hidden}_diff_lines`]).toEqual(['test']);
+ });
+ });
+ });
+
+ describe('SET_CURRENT_VIEW_DIFF_FILE_LINES', () => {
+ [
+ { current: 'highlighted', hidden: 'parallel', diffViewType: 'inline' },
+ { current: 'parallel', hidden: 'highlighted', diffViewType: 'parallel' },
+ ].forEach(({ current, hidden, diffViewType }) => {
+ it(`sets the ${current} lines when diff view is ${diffViewType}`, () => {
+ const file = { file_path: 'test', parallel_diff_lines: [], highlighted_diff_lines: [] };
+ const state = {
+ diffFiles: [file],
+ diffViewType,
+ };
+
+ mutations[types.SET_CURRENT_VIEW_DIFF_FILE_LINES](state, {
+ filePath: 'test',
+ lines: ['test'],
+ });
+
+ expect(file[`${current}_diff_lines`]).toEqual(['test']);
+ expect(file[`${hidden}_diff_lines`]).toEqual([]);
+ });
+ });
+ });
+
+ describe('ADD_CURRENT_VIEW_DIFF_FILE_LINES', () => {
+ [
+ { current: 'highlighted', hidden: 'parallel', diffViewType: 'inline' },
+ { current: 'parallel', hidden: 'highlighted', diffViewType: 'parallel' },
+ ].forEach(({ current, hidden, diffViewType }) => {
+ it(`pushes to ${current} lines when diff view is ${diffViewType}`, () => {
+ const file = { file_path: 'test', parallel_diff_lines: [], highlighted_diff_lines: [] };
+ const state = {
+ diffFiles: [file],
+ diffViewType,
+ };
+
+ mutations[types.ADD_CURRENT_VIEW_DIFF_FILE_LINES](state, {
+ filePath: 'test',
+ line: 'test',
+ });
+
+ expect(file[`${current}_diff_lines`]).toEqual(['test']);
+ expect(file[`${hidden}_diff_lines`]).toEqual([]);
+
+ mutations[types.ADD_CURRENT_VIEW_DIFF_FILE_LINES](state, {
+ filePath: 'test',
+ line: 'test2',
+ });
+
+ expect(file[`${current}_diff_lines`]).toEqual(['test', 'test2']);
+ expect(file[`${hidden}_diff_lines`]).toEqual([]);
+ });
+ });
+ });
+
+ describe('TOGGLE_DIFF_FILE_RENDERING_MORE', () => {
+ it('toggles renderingLines on file', () => {
+ const file = { file_path: 'test', renderingLines: false };
+ const state = {
+ diffFiles: [file],
+ };
+
+ mutations[types.TOGGLE_DIFF_FILE_RENDERING_MORE](state, 'test');
+
+ expect(file.renderingLines).toBe(true);
+
+ mutations[types.TOGGLE_DIFF_FILE_RENDERING_MORE](state, 'test');
+
+ expect(file.renderingLines).toBe(false);
+ });
+ });
});
diff --git a/spec/javascripts/dirty_submit/dirty_submit_form_spec.js b/spec/javascripts/dirty_submit/dirty_submit_form_spec.js
index 95cc90dcb0f..b1017e0c4f0 100644
--- a/spec/javascripts/dirty_submit/dirty_submit_form_spec.js
+++ b/spec/javascripts/dirty_submit/dirty_submit_form_spec.js
@@ -1,3 +1,4 @@
+import _ from 'underscore';
import DirtySubmitForm from '~/dirty_submit/dirty_submit_form';
import { getInputValue, setInputValue, createForm } from './helper';
@@ -13,46 +14,100 @@ function expectToToggleDisableOnDirtyUpdate(submit, input) {
}
describe('DirtySubmitForm', () => {
- DirtySubmitForm.THROTTLE_DURATION = 0;
+ const originalThrottleDuration = DirtySubmitForm.THROTTLE_DURATION;
- it('disables submit until there are changes', done => {
- const { form, input, submit } = createForm();
+ describe('submit button tests', () => {
+ beforeEach(() => {
+ DirtySubmitForm.THROTTLE_DURATION = 0;
+ });
- new DirtySubmitForm(form); // eslint-disable-line no-new
+ afterEach(() => {
+ DirtySubmitForm.THROTTLE_DURATION = originalThrottleDuration;
+ });
- return expectToToggleDisableOnDirtyUpdate(submit, input)
- .then(done)
- .catch(done.fail);
- });
+ it('disables submit until there are changes', done => {
+ const { form, input, submit } = createForm();
- it('disables submit until there are changes when initializing with a falsy value', done => {
- const { form, input, submit } = createForm();
- input.value = '';
+ new DirtySubmitForm(form); // eslint-disable-line no-new
- new DirtySubmitForm(form); // eslint-disable-line no-new
+ return expectToToggleDisableOnDirtyUpdate(submit, input)
+ .then(done)
+ .catch(done.fail);
+ });
- return expectToToggleDisableOnDirtyUpdate(submit, input)
- .then(done)
- .catch(done.fail);
- });
+ it('disables submit until there are changes when initializing with a falsy value', done => {
+ const { form, input, submit } = createForm();
+ input.value = '';
+
+ new DirtySubmitForm(form); // eslint-disable-line no-new
+
+ return expectToToggleDisableOnDirtyUpdate(submit, input)
+ .then(done)
+ .catch(done.fail);
+ });
- it('disables submit until there are changes for radio inputs', done => {
- const { form, input, submit } = createForm('radio');
+ it('disables submit until there are changes for radio inputs', done => {
+ const { form, input, submit } = createForm('radio');
- new DirtySubmitForm(form); // eslint-disable-line no-new
+ new DirtySubmitForm(form); // eslint-disable-line no-new
- return expectToToggleDisableOnDirtyUpdate(submit, input)
- .then(done)
- .catch(done.fail);
+ return expectToToggleDisableOnDirtyUpdate(submit, input)
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('disables submit until there are changes for checkbox inputs', done => {
+ const { form, input, submit } = createForm('checkbox');
+
+ new DirtySubmitForm(form); // eslint-disable-line no-new
+
+ return expectToToggleDisableOnDirtyUpdate(submit, input)
+ .then(done)
+ .catch(done.fail);
+ });
});
- it('disables submit until there are changes for checkbox inputs', done => {
- const { form, input, submit } = createForm('checkbox');
+ describe('throttling tests', () => {
+ beforeEach(() => {
+ jasmine.clock().install();
+ DirtySubmitForm.THROTTLE_DURATION = 100;
+ });
+
+ afterEach(() => {
+ jasmine.clock().uninstall();
+ DirtySubmitForm.THROTTLE_DURATION = originalThrottleDuration;
+ });
+
+ it('throttles updates when rapid changes are made to a single form element', () => {
+ const { form, input } = createForm();
+ const updateDirtyInputSpy = spyOn(new DirtySubmitForm(form), 'updateDirtyInput');
+
+ _.range(10).forEach(i => {
+ setInputValue(input, `change ${i}`, false);
+ });
+
+ jasmine.clock().tick(101);
+
+ expect(updateDirtyInputSpy).toHaveBeenCalledTimes(2);
+ });
+
+ it('does not throttle updates when rapid changes are made to different form elements', () => {
+ const form = document.createElement('form');
+ const range = _.range(10);
+ range.forEach(i => {
+ form.innerHTML += `<input type="text" name="input-${i}" class="js-input-${i}"/>`;
+ });
+
+ const updateDirtyInputSpy = spyOn(new DirtySubmitForm(form), 'updateDirtyInput');
+
+ range.forEach(i => {
+ const input = form.querySelector(`.js-input-${i}`);
+ setInputValue(input, `change`, false);
+ });
- new DirtySubmitForm(form); // eslint-disable-line no-new
+ jasmine.clock().tick(101);
- return expectToToggleDisableOnDirtyUpdate(submit, input)
- .then(done)
- .catch(done.fail);
+ expect(updateDirtyInputSpy).toHaveBeenCalledTimes(range.length);
+ });
});
});
diff --git a/spec/javascripts/environments/folder/environments_folder_view_spec.js b/spec/javascripts/environments/folder/environments_folder_view_spec.js
index ff15067aeac..f1c323df4be 100644
--- a/spec/javascripts/environments/folder/environments_folder_view_spec.js
+++ b/spec/javascripts/environments/folder/environments_folder_view_spec.js
@@ -3,7 +3,7 @@ import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import environmentsFolderViewComponent from '~/environments/folder/environments_folder_view.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import { removeBreakLine, removeWhitespace } from 'spec/helpers/vue_component_helper';
+import { removeBreakLine, removeWhitespace } from 'spec/helpers/text_helper';
import { environmentsList } from '../mock_data';
describe('Environments Folder View', () => {
diff --git a/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js b/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js
index a72ea6ab547..0ee13faf841 100644
--- a/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js
+++ b/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js
@@ -118,7 +118,7 @@ describe('Filtered Search Visual Tokens', () => {
describe('getEndpointWithQueryParams', () => {
it('returns `endpoint` string as is when second param `endpointQueryParams` is undefined, null or empty string', () => {
- const endpoint = 'foo/bar/labels.json';
+ const endpoint = 'foo/bar/-/labels.json';
expect(subject.getEndpointWithQueryParams(endpoint)).toBe(endpoint);
expect(subject.getEndpointWithQueryParams(endpoint, null)).toBe(endpoint);
@@ -126,7 +126,7 @@ describe('Filtered Search Visual Tokens', () => {
});
it('returns `endpoint` string with values of `endpointQueryParams`', () => {
- const endpoint = 'foo/bar/labels.json';
+ const endpoint = 'foo/bar/-/labels.json';
const singleQueryParams = '{"foo":"true"}';
const multipleQueryParams = '{"foo":"true","bar":"true"}';
diff --git a/spec/javascripts/filtered_search/visual_token_value_spec.js b/spec/javascripts/filtered_search/visual_token_value_spec.js
index 14217d460cc..d1d16afc977 100644
--- a/spec/javascripts/filtered_search/visual_token_value_spec.js
+++ b/spec/javascripts/filtered_search/visual_token_value_spec.js
@@ -156,9 +156,11 @@ describe('Filtered Search Visual Tokens', () => {
const filteredSearchInput = document.querySelector('.filtered-search');
filteredSearchInput.dataset.baseEndpoint = dummyEndpoint;
+ filteredSearchInput.dataset.labelsEndpoint = `${dummyEndpoint}/-/labels`;
+ filteredSearchInput.dataset.milestonesEndpoint = `${dummyEndpoint}/-/milestones`;
AjaxCache.internalStorage = {};
- AjaxCache.internalStorage[`${dummyEndpoint}/labels.json`] = labelData;
+ AjaxCache.internalStorage[`${filteredSearchInput.dataset.labelsEndpoint}.json`] = labelData;
});
const parseColor = color => {
diff --git a/spec/javascripts/fixtures/.gitignore b/spec/javascripts/fixtures/.gitignore
index 2507c8e7263..bed020f5b0a 100644
--- a/spec/javascripts/fixtures/.gitignore
+++ b/spec/javascripts/fixtures/.gitignore
@@ -1,3 +1,5 @@
*.html.raw
*.html
*.json
+*.pdf
+*.bmpr
diff --git a/spec/javascripts/fixtures/abuse_reports.rb b/spec/javascripts/fixtures/abuse_reports.rb
index 54b6419bcdb..e0aaecf626a 100644
--- a/spec/javascripts/fixtures/abuse_reports.rb
+++ b/spec/javascripts/fixtures/abuse_reports.rb
@@ -18,10 +18,9 @@ describe Admin::AbuseReportsController, '(JavaScript fixtures)', type: :controll
sign_in(admin)
end
- it 'abuse_reports/abuse_reports_list.html' do |example|
+ it 'abuse_reports/abuse_reports_list.html' do
get :index
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/admin_users.rb b/spec/javascripts/fixtures/admin_users.rb
index 76dbdf603da..22a5de66577 100644
--- a/spec/javascripts/fixtures/admin_users.rb
+++ b/spec/javascripts/fixtures/admin_users.rb
@@ -17,13 +17,12 @@ describe Admin::UsersController, '(JavaScript fixtures)', type: :controller do
clean_frontend_fixtures('admin/users')
end
- it 'admin/users/new_with_internal_user_regex.html' do |example|
+ it 'admin/users/new_with_internal_user_regex.html' do
stub_application_setting(user_default_external: true)
stub_application_setting(user_default_internal_regex: '^(?:(?!\.ext@).)*$\r?')
get :new
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/application_settings.rb b/spec/javascripts/fixtures/application_settings.rb
index c535e598e12..d4651fa6ece 100644
--- a/spec/javascripts/fixtures/application_settings.rb
+++ b/spec/javascripts/fixtures/application_settings.rb
@@ -23,12 +23,11 @@ describe Admin::ApplicationSettingsController, '(JavaScript fixtures)', type: :c
remove_repository(project)
end
- it 'application_settings/accounts_and_limit.html' do |example|
+ it 'application_settings/accounts_and_limit.html' do
stub_application_setting(user_default_external: false)
get :show
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/autocomplete_sources.rb b/spec/javascripts/fixtures/autocomplete_sources.rb
index c117fb7cd24..b20a0159d7d 100644
--- a/spec/javascripts/fixtures/autocomplete_sources.rb
+++ b/spec/javascripts/fixtures/autocomplete_sources.rb
@@ -18,7 +18,7 @@ describe Projects::AutocompleteSourcesController, '(JavaScript fixtures)', type:
sign_in(admin)
end
- it 'autocomplete_sources/labels.json' do |example|
+ it 'autocomplete_sources/labels.json' do
issue.labels << create(:label, project: project, title: 'bug')
issue.labels << create(:label, project: project, title: 'critical')
@@ -35,6 +35,5 @@ describe Projects::AutocompleteSourcesController, '(JavaScript fixtures)', type:
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/balsamiq.rb b/spec/javascripts/fixtures/balsamiq.rb
deleted file mode 100644
index 234e246119a..00000000000
--- a/spec/javascripts/fixtures/balsamiq.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require 'spec_helper'
-
-describe 'Balsamiq file', '(JavaScript fixtures)', type: :controller do
- include JavaScriptFixturesHelpers
-
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
- let(:project) { create(:project, :repository, namespace: namespace, path: 'balsamiq-project') }
-
- before(:all) do
- clean_frontend_fixtures('blob/balsamiq/')
- end
-
- it 'blob/balsamiq/test.bmpr' do |example|
- blob = project.repository.blob_at('b89b56d79', 'files/images/balsamiq.bmpr')
-
- store_frontend_fixture(blob.data.force_encoding('utf-8'), example.description)
- end
-end
diff --git a/spec/javascripts/fixtures/blob.rb b/spec/javascripts/fixtures/blob.rb
index db7749bc000..07670552cd5 100644
--- a/spec/javascripts/fixtures/blob.rb
+++ b/spec/javascripts/fixtures/blob.rb
@@ -22,7 +22,7 @@ describe Projects::BlobController, '(JavaScript fixtures)', type: :controller do
remove_repository(project)
end
- it 'blob/show.html' do |example|
+ it 'blob/show.html' do
get(:show, params: {
namespace_id: project.namespace,
project_id: project,
@@ -30,6 +30,5 @@ describe Projects::BlobController, '(JavaScript fixtures)', type: :controller do
})
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/boards.rb b/spec/javascripts/fixtures/boards.rb
index c4390e89578..5835721d3d5 100644
--- a/spec/javascripts/fixtures/boards.rb
+++ b/spec/javascripts/fixtures/boards.rb
@@ -17,13 +17,12 @@ describe Projects::BoardsController, '(JavaScript fixtures)', type: :controller
sign_in(admin)
end
- it 'boards/show.html' do |example|
+ it 'boards/show.html' do
get(:index, params: {
namespace_id: project.namespace,
project_id: project
})
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/branches.rb b/spec/javascripts/fixtures/branches.rb
index 5d2d6c7ec0e..204aa9b7c7a 100644
--- a/spec/javascripts/fixtures/branches.rb
+++ b/spec/javascripts/fixtures/branches.rb
@@ -21,13 +21,12 @@ describe Projects::BranchesController, '(JavaScript fixtures)', type: :controlle
remove_repository(project)
end
- it 'branches/new_branch.html' do |example|
+ it 'branches/new_branch.html' do
get :new, params: {
namespace_id: project.namespace.to_param,
project_id: project
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/clusters.rb b/spec/javascripts/fixtures/clusters.rb
index 8ebd8a41366..1076404e0e3 100644
--- a/spec/javascripts/fixtures/clusters.rb
+++ b/spec/javascripts/fixtures/clusters.rb
@@ -22,7 +22,7 @@ describe Projects::ClustersController, '(JavaScript fixtures)', type: :controlle
remove_repository(project)
end
- it 'clusters/show_cluster.html' do |example|
+ it 'clusters/show_cluster.html' do
get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -30,6 +30,5 @@ describe Projects::ClustersController, '(JavaScript fixtures)', type: :controlle
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/commit.rb b/spec/javascripts/fixtures/commit.rb
index ab10f559e4b..ff9a4bc1adc 100644
--- a/spec/javascripts/fixtures/commit.rb
+++ b/spec/javascripts/fixtures/commit.rb
@@ -19,7 +19,7 @@ describe Projects::CommitController, '(JavaScript fixtures)', type: :controller
allow(SecureRandom).to receive(:hex).and_return('securerandomhex:thereisnospoon')
end
- it 'commit/show.html' do |example|
+ it 'commit/show.html' do
params = {
namespace_id: project.namespace,
project_id: project,
@@ -29,6 +29,5 @@ describe Projects::CommitController, '(JavaScript fixtures)', type: :controller
get :show, params: params
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/deploy_keys.rb b/spec/javascripts/fixtures/deploy_keys.rb
index a333d9c0150..38eab853da2 100644
--- a/spec/javascripts/fixtures/deploy_keys.rb
+++ b/spec/javascripts/fixtures/deploy_keys.rb
@@ -24,7 +24,7 @@ describe Projects::DeployKeysController, '(JavaScript fixtures)', type: :control
render_views
- it 'deploy_keys/keys.json' do |example|
+ it 'deploy_keys/keys.json' do
create(:rsa_deploy_key_2048, public: true)
project_key = create(:deploy_key, key: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCdMHEHyhRjbhEZVddFn6lTWdgEy5Q6Bz4nwGB76xWZI5YT/1WJOMEW+sL5zYd31kk7sd3FJ5L9ft8zWMWrr/iWXQikC2cqZK24H1xy+ZUmrRuJD4qGAaIVoyyzBL+avL+lF8J5lg6YSw8gwJY/lX64/vnJHUlWw2n5BF8IFOWhiw== dummy@gitlab.com')
internal_key = create(:deploy_key, key: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDNd/UJWhPrpb+b/G5oL109y57yKuCxE+WUGJGYaj7WQKsYRJmLYh1mgjrl+KVyfsWpq4ylOxIfFSnN9xBBFN8mlb0Fma5DC7YsSsibJr3MZ19ZNBprwNcdogET7aW9I0In7Wu5f2KqI6e5W/spJHCy4JVxzVMUvk6Myab0LnJ2iQ== dummy@gitlab.com')
@@ -39,6 +39,5 @@ describe Projects::DeployKeysController, '(JavaScript fixtures)', type: :control
}, format: :json
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/groups.rb b/spec/javascripts/fixtures/groups.rb
index 16e31028b05..4d0afc3ce1a 100644
--- a/spec/javascripts/fixtures/groups.rb
+++ b/spec/javascripts/fixtures/groups.rb
@@ -18,20 +18,18 @@ describe 'Groups (JavaScript fixtures)', type: :controller do
end
describe GroupsController, '(JavaScript fixtures)', type: :controller do
- it 'groups/edit.html' do |example|
+ it 'groups/edit.html' do
get :edit, params: { id: group }
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
describe Groups::Settings::CiCdController, '(JavaScript fixtures)', type: :controller do
- it 'groups/ci_cd_settings.html' do |example|
+ it 'groups/ci_cd_settings.html' do
get :show, params: { group_id: group }
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
end
diff --git a/spec/javascripts/fixtures/issues.rb b/spec/javascripts/fixtures/issues.rb
index 0f3f9a10f94..d8d77f767de 100644
--- a/spec/javascripts/fixtures/issues.rb
+++ b/spec/javascripts/fixtures/issues.rb
@@ -21,26 +21,26 @@ describe Projects::IssuesController, '(JavaScript fixtures)', type: :controller
remove_repository(project)
end
- it 'issues/open-issue.html' do |example|
- render_issue(example.description, create(:issue, project: project))
+ it 'issues/open-issue.html' do
+ render_issue(create(:issue, project: project))
end
- it 'issues/closed-issue.html' do |example|
- render_issue(example.description, create(:closed_issue, project: project))
+ it 'issues/closed-issue.html' do
+ render_issue(create(:closed_issue, project: project))
end
- it 'issues/issue-with-task-list.html' do |example|
+ it 'issues/issue-with-task-list.html' do
issue = create(:issue, project: project, description: '- [ ] Task List Item')
- render_issue(example.description, issue)
+ render_issue(issue)
end
- it 'issues/issue_with_comment.html' do |example|
+ it 'issues/issue_with_comment.html' do
issue = create(:issue, project: project)
create(:note, project: project, noteable: issue, note: '- [ ] Task List Item').save
- render_issue(example.description, issue)
+ render_issue(issue)
end
- it 'issues/issue_list.html' do |example|
+ it 'issues/issue_list.html' do
create(:issue, project: project)
get :index, params: {
@@ -49,12 +49,11 @@ describe Projects::IssuesController, '(JavaScript fixtures)', type: :controller
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
private
- def render_issue(fixture_file_name, issue)
+ def render_issue(issue)
get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -62,7 +61,6 @@ describe Projects::IssuesController, '(JavaScript fixtures)', type: :controller
}
expect(response).to be_success
- store_frontend_fixture(response, fixture_file_name)
end
end
@@ -89,7 +87,7 @@ describe API::Issues, '(JavaScript fixtures)', type: :request do
end
end
- it 'issues/related_merge_requests.json' do |example|
+ it 'issues/related_merge_requests.json' do
user = create(:user)
project = create(:project, :public, creator_id: user.id, namespace: user.namespace)
issue_title = 'foo'
@@ -120,6 +118,5 @@ describe API::Issues, '(JavaScript fixtures)', type: :request do
get_related_merge_requests(project.id, issue.iid, user)
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/jobs.rb b/spec/javascripts/fixtures/jobs.rb
index 941235190b5..46ccd6f8c8a 100644
--- a/spec/javascripts/fixtures/jobs.rb
+++ b/spec/javascripts/fixtures/jobs.rb
@@ -32,7 +32,7 @@ describe Projects::JobsController, '(JavaScript fixtures)', type: :controller do
remove_repository(project)
end
- it 'builds/build-with-artifacts.html' do |example|
+ it 'builds/build-with-artifacts.html' do
get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -40,10 +40,9 @@ describe Projects::JobsController, '(JavaScript fixtures)', type: :controller do
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
- it 'jobs/delayed.json' do |example|
+ it 'jobs/delayed.json' do
get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -51,6 +50,5 @@ describe Projects::JobsController, '(JavaScript fixtures)', type: :controller do
}, format: :json
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/labels.rb b/spec/javascripts/fixtures/labels.rb
index 9420194e675..4d1b7317274 100644
--- a/spec/javascripts/fixtures/labels.rb
+++ b/spec/javascripts/fixtures/labels.rb
@@ -30,13 +30,12 @@ describe 'Labels (JavaScript fixtures)' do
sign_in(admin)
end
- it 'labels/group_labels.json' do |example|
+ it 'labels/group_labels.json' do
get :index, params: {
group_id: group
}, format: 'json'
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
@@ -47,14 +46,13 @@ describe 'Labels (JavaScript fixtures)' do
sign_in(admin)
end
- it 'labels/project_labels.json' do |example|
+ it 'labels/project_labels.json' do
get :index, params: {
namespace_id: group,
project_id: project
}, format: 'json'
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
end
diff --git a/spec/javascripts/fixtures/merge_requests.rb b/spec/javascripts/fixtures/merge_requests.rb
index 7df1e5cb512..05860be2291 100644
--- a/spec/javascripts/fixtures/merge_requests.rb
+++ b/spec/javascripts/fixtures/merge_requests.rb
@@ -42,52 +42,52 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont
remove_repository(project)
end
- it 'merge_requests/merge_request_of_current_user.html' do |example|
+ it 'merge_requests/merge_request_of_current_user.html' do
merge_request.update(author: admin)
- render_merge_request(example.description, merge_request)
+ render_merge_request(merge_request)
end
- it 'merge_requests/merge_request_with_task_list.html' do |example|
+ it 'merge_requests/merge_request_with_task_list.html' do
create(:ci_build, :pending, pipeline: pipeline)
- render_merge_request(example.description, merge_request)
+ render_merge_request(merge_request)
end
- it 'merge_requests/merged_merge_request.html' do |example|
+ it 'merge_requests/merged_merge_request.html' do
expect_next_instance_of(MergeRequest) do |merge_request|
allow(merge_request).to receive(:source_branch_exists?).and_return(true)
allow(merge_request).to receive(:can_remove_source_branch?).and_return(true)
end
- render_merge_request(example.description, merged_merge_request)
+ render_merge_request(merged_merge_request)
end
- it 'merge_requests/diff_comment.html' do |example|
+ it 'merge_requests/diff_comment.html' do
create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request)
create(:note_on_merge_request, author: admin, project: project, noteable: merge_request)
- render_merge_request(example.description, merge_request)
+ render_merge_request(merge_request)
end
- it 'merge_requests/merge_request_with_comment.html' do |example|
+ it 'merge_requests/merge_request_with_comment.html' do
create(:note_on_merge_request, author: admin, project: project, noteable: merge_request, note: '- [ ] Task List Item')
- render_merge_request(example.description, merge_request)
+ render_merge_request(merge_request)
end
- it 'merge_requests/discussions.json' do |example|
+ it 'merge_requests/discussions.json' do
create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request)
- render_discussions_json(merge_request, example.description)
+ render_discussions_json(merge_request)
end
- it 'merge_requests/diff_discussion.json' do |example|
+ it 'merge_requests/diff_discussion.json' do
create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request)
- render_discussions_json(merge_request, example.description)
+ render_discussions_json(merge_request)
end
- it 'merge_requests/resolved_diff_discussion.json' do |example|
+ it 'merge_requests/resolved_diff_discussion.json' do
note = create(:discussion_note_on_merge_request, :resolved, project: project, author: admin, position: position, noteable: merge_request)
create(:system_note, project: project, author: admin, noteable: merge_request, discussion_id: note.discussion.id)
- render_discussions_json(merge_request, example.description)
+ render_discussions_json(merge_request)
end
context 'with image diff' do
@@ -106,25 +106,23 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont
)
end
- it 'merge_requests/image_diff_discussion.json' do |example|
+ it 'merge_requests/image_diff_discussion.json' do
create(:diff_note_on_merge_request, project: project, noteable: merge_request2, position: image_position)
- render_discussions_json(merge_request2, example.description)
+ render_discussions_json(merge_request2)
end
end
private
- def render_discussions_json(merge_request, fixture_file_name)
+ def render_discussions_json(merge_request)
get :discussions, params: {
namespace_id: project.namespace.to_param,
project_id: project,
id: merge_request.to_param
}, format: :json
-
- store_frontend_fixture(response, fixture_file_name)
end
- def render_merge_request(fixture_file_name, merge_request)
+ def render_merge_request(merge_request)
get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -132,6 +130,5 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont
}, format: :html
expect(response).to be_success
- store_frontend_fixture(response, fixture_file_name)
end
end
diff --git a/spec/javascripts/fixtures/merge_requests_diffs.rb b/spec/javascripts/fixtures/merge_requests_diffs.rb
index 57462e74bb2..03b9b713fd8 100644
--- a/spec/javascripts/fixtures/merge_requests_diffs.rb
+++ b/spec/javascripts/fixtures/merge_requests_diffs.rb
@@ -34,29 +34,29 @@ describe Projects::MergeRequests::DiffsController, '(JavaScript fixtures)', type
remove_repository(project)
end
- it 'merge_request_diffs/with_commit.json' do |example|
+ it 'merge_request_diffs/with_commit.json' do
# Create a user that matches the selected commit author
# This is so that the "author" information will be populated
create(:user, email: selected_commit.author_email, name: selected_commit.author_name)
- render_merge_request(example.description, merge_request, commit_id: selected_commit.sha)
+ render_merge_request(merge_request, commit_id: selected_commit.sha)
end
- it 'merge_request_diffs/inline_changes_tab_with_comments.json' do |example|
+ it 'merge_request_diffs/inline_changes_tab_with_comments.json' do
create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request)
create(:note_on_merge_request, author: admin, project: project, noteable: merge_request)
- render_merge_request(example.description, merge_request)
+ render_merge_request(merge_request)
end
- it 'merge_request_diffs/parallel_changes_tab_with_comments.json' do |example|
+ it 'merge_request_diffs/parallel_changes_tab_with_comments.json' do
create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request)
create(:note_on_merge_request, author: admin, project: project, noteable: merge_request)
- render_merge_request(example.description, merge_request, view: 'parallel')
+ render_merge_request(merge_request, view: 'parallel')
end
private
- def render_merge_request(fixture_file_name, merge_request, view: 'inline', **extra_params)
+ def render_merge_request(merge_request, view: 'inline', **extra_params)
get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -66,6 +66,5 @@ describe Projects::MergeRequests::DiffsController, '(JavaScript fixtures)', type
}, format: :json
expect(response).to be_success
- store_frontend_fixture(response, fixture_file_name)
end
end
diff --git a/spec/javascripts/fixtures/pdf.rb b/spec/javascripts/fixtures/pdf.rb
deleted file mode 100644
index ef9976b9fd3..00000000000
--- a/spec/javascripts/fixtures/pdf.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require 'spec_helper'
-
-describe 'PDF file', '(JavaScript fixtures)', type: :controller do
- include JavaScriptFixturesHelpers
-
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
- let(:project) { create(:project, :repository, namespace: namespace, path: 'pdf-project') }
-
- before(:all) do
- clean_frontend_fixtures('blob/pdf/')
- end
-
- it 'blob/pdf/test.pdf' do |example|
- blob = project.repository.blob_at('e774ebd33', 'files/pdf/test.pdf')
-
- store_frontend_fixture(blob.data.force_encoding("utf-8"), example.description)
- end
-end
diff --git a/spec/javascripts/fixtures/pipeline_schedules.rb b/spec/javascripts/fixtures/pipeline_schedules.rb
index e5176a58273..aecd56e6198 100644
--- a/spec/javascripts/fixtures/pipeline_schedules.rb
+++ b/spec/javascripts/fixtures/pipeline_schedules.rb
@@ -21,7 +21,7 @@ describe Projects::PipelineSchedulesController, '(JavaScript fixtures)', type: :
sign_in(admin)
end
- it 'pipeline_schedules/edit.html' do |example|
+ it 'pipeline_schedules/edit.html' do
get :edit, params: {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -29,10 +29,9 @@ describe Projects::PipelineSchedulesController, '(JavaScript fixtures)', type: :
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
- it 'pipeline_schedules/edit_with_variables.html' do |example|
+ it 'pipeline_schedules/edit_with_variables.html' do
get :edit, params: {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -40,6 +39,5 @@ describe Projects::PipelineSchedulesController, '(JavaScript fixtures)', type: :
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/pipelines.rb b/spec/javascripts/fixtures/pipelines.rb
index 42b552e81c0..de6fcfe10f4 100644
--- a/spec/javascripts/fixtures/pipelines.rb
+++ b/spec/javascripts/fixtures/pipelines.rb
@@ -23,13 +23,12 @@ describe Projects::PipelinesController, '(JavaScript fixtures)', type: :controll
sign_in(admin)
end
- it 'pipelines/pipelines.json' do |example|
+ it 'pipelines/pipelines.json' do
get :index, params: {
namespace_id: namespace,
project_id: project
}, format: :json
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/projects.rb b/spec/javascripts/fixtures/projects.rb
index 446da83a7f9..94c59207898 100644
--- a/spec/javascripts/fixtures/projects.rb
+++ b/spec/javascripts/fixtures/projects.rb
@@ -28,49 +28,45 @@ describe 'Projects (JavaScript fixtures)', type: :controller do
end
describe ProjectsController, '(JavaScript fixtures)', type: :controller do
- it 'projects/dashboard.html' do |example|
+ it 'projects/dashboard.html' do
get :show, params: {
namespace_id: project.namespace.to_param,
id: project
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
- it 'projects/overview.html' do |example|
+ it 'projects/overview.html' do
get :show, params: {
namespace_id: project_with_repo.namespace.to_param,
id: project_with_repo
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
- it 'projects/edit.html' do |example|
+ it 'projects/edit.html' do
get :edit, params: {
namespace_id: project.namespace.to_param,
id: project
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
describe Projects::Settings::CiCdController, '(JavaScript fixtures)', type: :controller do
- it 'projects/ci_cd_settings.html' do |example|
+ it 'projects/ci_cd_settings.html' do
get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
- it 'projects/ci_cd_settings_with_variables.html' do |example|
+ it 'projects/ci_cd_settings_with_variables.html' do
create(:ci_variable, project: project_variable_populated)
create(:ci_variable, project: project_variable_populated)
@@ -80,7 +76,6 @@ describe 'Projects (JavaScript fixtures)', type: :controller do
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
end
diff --git a/spec/javascripts/fixtures/prometheus_service.rb b/spec/javascripts/fixtures/prometheus_service.rb
index 29dc95305b7..f3171fdd97b 100644
--- a/spec/javascripts/fixtures/prometheus_service.rb
+++ b/spec/javascripts/fixtures/prometheus_service.rb
@@ -22,7 +22,7 @@ describe Projects::ServicesController, '(JavaScript fixtures)', type: :controlle
remove_repository(project)
end
- it 'services/prometheus/prometheus_service.html' do |example|
+ it 'services/prometheus/prometheus_service.html' do
get :edit, params: {
namespace_id: namespace,
project_id: project,
@@ -30,6 +30,5 @@ describe Projects::ServicesController, '(JavaScript fixtures)', type: :controlle
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/raw.rb b/spec/javascripts/fixtures/raw.rb
index 82770beb39b..801c80a0112 100644
--- a/spec/javascripts/fixtures/raw.rb
+++ b/spec/javascripts/fixtures/raw.rb
@@ -1,34 +1,39 @@
require 'spec_helper'
-describe 'Raw files', '(JavaScript fixtures)', type: :controller do
+describe 'Raw files', '(JavaScript fixtures)' do
include JavaScriptFixturesHelpers
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let(:project) { create(:project, :repository, namespace: namespace, path: 'raw-project') }
+ let(:response) { @blob.data.force_encoding('UTF-8') }
before(:all) do
+ clean_frontend_fixtures('blob/balsamiq/')
clean_frontend_fixtures('blob/notebook/')
+ clean_frontend_fixtures('blob/pdf/')
end
after do
remove_repository(project)
end
- it 'blob/notebook/basic.json' do |example|
- blob = project.repository.blob_at('6d85bb69', 'files/ipython/basic.ipynb')
-
- store_frontend_fixture(blob.data, example.description)
+ it 'blob/balsamiq/test.bmpr' do
+ @blob = project.repository.blob_at('b89b56d79', 'files/images/balsamiq.bmpr')
end
- it 'blob/notebook/worksheets.json' do |example|
- blob = project.repository.blob_at('6d85bb69', 'files/ipython/worksheets.ipynb')
+ it 'blob/notebook/basic.json' do
+ @blob = project.repository.blob_at('6d85bb69', 'files/ipython/basic.ipynb')
+ end
- store_frontend_fixture(blob.data, example.description)
+ it 'blob/notebook/worksheets.json' do
+ @blob = project.repository.blob_at('6d85bb69', 'files/ipython/worksheets.ipynb')
end
- it 'blob/notebook/math.json' do |example|
- blob = project.repository.blob_at('93ee732', 'files/ipython/math.ipynb')
+ it 'blob/notebook/math.json' do
+ @blob = project.repository.blob_at('93ee732', 'files/ipython/math.ipynb')
+ end
- store_frontend_fixture(blob.data, example.description)
+ it 'blob/pdf/test.pdf' do
+ @blob = project.repository.blob_at('e774ebd33', 'files/pdf/test.pdf')
end
end
diff --git a/spec/javascripts/fixtures/search.rb b/spec/javascripts/fixtures/search.rb
index 5f5b4d4e60d..22fc546d761 100644
--- a/spec/javascripts/fixtures/search.rb
+++ b/spec/javascripts/fixtures/search.rb
@@ -9,10 +9,9 @@ describe SearchController, '(JavaScript fixtures)', type: :controller do
clean_frontend_fixtures('search/')
end
- it 'search/show.html' do |example|
+ it 'search/show.html' do
get :show
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/services.rb b/spec/javascripts/fixtures/services.rb
index dc7ee484c22..2237702ccca 100644
--- a/spec/javascripts/fixtures/services.rb
+++ b/spec/javascripts/fixtures/services.rb
@@ -22,7 +22,7 @@ describe Projects::ServicesController, '(JavaScript fixtures)', type: :controlle
remove_repository(project)
end
- it 'services/edit_service.html' do |example|
+ it 'services/edit_service.html' do
get :edit, params: {
namespace_id: namespace,
project_id: project,
@@ -30,6 +30,5 @@ describe Projects::ServicesController, '(JavaScript fixtures)', type: :controlle
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/sessions.rb b/spec/javascripts/fixtures/sessions.rb
index 8656dea696a..92b74c01c89 100644
--- a/spec/javascripts/fixtures/sessions.rb
+++ b/spec/javascripts/fixtures/sessions.rb
@@ -16,11 +16,10 @@ describe 'Sessions (JavaScript fixtures)' do
set_devise_mapping(context: @request)
end
- it 'sessions/new.html' do |example|
+ it 'sessions/new.html' do
get :new
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
end
diff --git a/spec/javascripts/fixtures/snippet.rb b/spec/javascripts/fixtures/snippet.rb
index ebc5b793166..ace84b14eb7 100644
--- a/spec/javascripts/fixtures/snippet.rb
+++ b/spec/javascripts/fixtures/snippet.rb
@@ -23,12 +23,11 @@ describe SnippetsController, '(JavaScript fixtures)', type: :controller do
remove_repository(project)
end
- it 'snippets/show.html' do |example|
+ it 'snippets/show.html' do
create(:discussion_note_on_snippet, noteable: snippet, project: project, author: admin, note: '- [ ] Task List Item')
get(:show, params: { id: snippet.to_param })
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/images/green_box.png b/spec/javascripts/fixtures/static/images/green_box.png
index cd1ff9f9ade..cd1ff9f9ade 100644
--- a/spec/javascripts/fixtures/images/green_box.png
+++ b/spec/javascripts/fixtures/static/images/green_box.png
Binary files differ
diff --git a/spec/javascripts/fixtures/one_white_pixel.png b/spec/javascripts/fixtures/static/images/one_white_pixel.png
index 073fcf40a18..073fcf40a18 100644
--- a/spec/javascripts/fixtures/one_white_pixel.png
+++ b/spec/javascripts/fixtures/static/images/one_white_pixel.png
Binary files differ
diff --git a/spec/javascripts/fixtures/images/red_box.png b/spec/javascripts/fixtures/static/images/red_box.png
index 73b2927da0f..73b2927da0f 100644
--- a/spec/javascripts/fixtures/images/red_box.png
+++ b/spec/javascripts/fixtures/static/images/red_box.png
Binary files differ
diff --git a/spec/javascripts/fixtures/projects.json b/spec/javascripts/fixtures/static/projects.json
index 68a150f602a..68a150f602a 100644
--- a/spec/javascripts/fixtures/projects.json
+++ b/spec/javascripts/fixtures/static/projects.json
diff --git a/spec/javascripts/fixtures/todos.rb b/spec/javascripts/fixtures/todos.rb
index 6e37a2e5a4c..d0c8a6eca01 100644
--- a/spec/javascripts/fixtures/todos.rb
+++ b/spec/javascripts/fixtures/todos.rb
@@ -26,11 +26,10 @@ describe 'Todos (JavaScript fixtures)' do
sign_in(admin)
end
- it 'todos/todos.html' do |example|
+ it 'todos/todos.html' do
get :index
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
@@ -41,7 +40,7 @@ describe 'Todos (JavaScript fixtures)' do
sign_in(admin)
end
- it 'todos/todos.json' do |example|
+ it 'todos/todos.json' do
post :create, params: {
namespace_id: namespace,
project_id: project,
@@ -50,7 +49,6 @@ describe 'Todos (JavaScript fixtures)' do
}, format: 'json'
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
end
diff --git a/spec/javascripts/fixtures/u2f.rb b/spec/javascripts/fixtures/u2f.rb
index 15866d65a4f..f52832b6efb 100644
--- a/spec/javascripts/fixtures/u2f.rb
+++ b/spec/javascripts/fixtures/u2f.rb
@@ -18,13 +18,12 @@ context 'U2F' do
set_devise_mapping(context: @request)
end
- it 'u2f/authenticate.html' do |example|
+ it 'u2f/authenticate.html' do
allow(controller).to receive(:find_user).and_return(user)
post :create, params: { user: { login: user.username, password: user.password } }
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
@@ -36,11 +35,10 @@ context 'U2F' do
allow_any_instance_of(Profiles::TwoFactorAuthsController).to receive(:build_qr_code).and_return('qrcode:blackandwhitesquares')
end
- it 'u2f/register.html' do |example|
+ it 'u2f/register.html' do
get :show
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
end
diff --git a/spec/javascripts/fly_out_nav_spec.js b/spec/javascripts/fly_out_nav_spec.js
index 7ef44f29c5b..4772f754937 100644
--- a/spec/javascripts/fly_out_nav_spec.js
+++ b/spec/javascripts/fly_out_nav_spec.js
@@ -14,6 +14,7 @@ import {
setSidebar,
subItemsMouseLeave,
} from '~/fly_out_nav';
+import { SIDEBAR_COLLAPSED_CLASS } from '~/contextual_sidebar';
import bp from '~/breakpoints';
describe('Fly out sidebar navigation', () => {
@@ -219,7 +220,7 @@ describe('Fly out sidebar navigation', () => {
it('shows collapsed only sub-items if icon only sidebar', () => {
const subItems = el.querySelector('.sidebar-sub-level-items');
const sidebar = document.createElement('div');
- sidebar.classList.add('sidebar-collapsed-desktop');
+ sidebar.classList.add(SIDEBAR_COLLAPSED_CLASS);
subItems.classList.add('is-fly-out-only');
setSidebar(sidebar);
@@ -296,7 +297,7 @@ describe('Fly out sidebar navigation', () => {
it('returns true when active & collapsed sidebar', () => {
const sidebar = document.createElement('div');
- sidebar.classList.add('sidebar-collapsed-desktop');
+ sidebar.classList.add(SIDEBAR_COLLAPSED_CLASS);
el.classList.add('active');
setSidebar(sidebar);
diff --git a/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js b/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js
index f00bc2eeb6d..dce8e3be148 100644
--- a/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js
+++ b/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import frequentItemsListItemComponent from '~/frequent_items/components/frequent_items_list_item.vue';
import { shallowMount } from '@vue/test-utils';
-import { trimText } from 'spec/helpers/vue_component_helper';
+import { trimText } from 'spec/helpers/text_helper';
import { mockProject } from '../mock_data'; // can also use 'mockGroup', but not useful to test here
const createComponent = () => {
diff --git a/spec/javascripts/gl_dropdown_spec.js b/spec/javascripts/gl_dropdown_spec.js
index 57e31d933ca..8c7820ddb52 100644
--- a/spec/javascripts/gl_dropdown_spec.js
+++ b/spec/javascripts/gl_dropdown_spec.js
@@ -6,7 +6,7 @@ import '~/lib/utils/common_utils';
describe('glDropdown', function describeDropdown() {
preloadFixtures('static/gl_dropdown.html');
- loadJSONFixtures('projects.json');
+ loadJSONFixtures('static/projects.json');
const NON_SELECTABLE_CLASSES =
'.divider, .separator, .dropdown-header, .dropdown-menu-empty-item';
@@ -67,7 +67,7 @@ describe('glDropdown', function describeDropdown() {
loadFixtures('static/gl_dropdown.html');
this.dropdownContainerElement = $('.dropdown.inline');
this.$dropdownMenuElement = $('.dropdown-menu', this.dropdownContainerElement);
- this.projectsData = getJSONFixture('projects.json');
+ this.projectsData = getJSONFixture('static/projects.json');
});
afterEach(() => {
diff --git a/spec/javascripts/helpers/vue_component_helper.js b/spec/javascripts/helpers/text_helper.js
index e0fe18e5560..e0fe18e5560 100644
--- a/spec/javascripts/helpers/vue_component_helper.js
+++ b/spec/javascripts/helpers/text_helper.js
diff --git a/spec/javascripts/helpers/vue_test_utils_helper.js b/spec/javascripts/helpers/vue_test_utils_helper.js
index 19e27388eeb..121e99c9783 100644
--- a/spec/javascripts/helpers/vue_test_utils_helper.js
+++ b/spec/javascripts/helpers/vue_test_utils_helper.js
@@ -16,4 +16,6 @@ const vNodeContainsText = (vnode, text) =>
* @param {String} text
*/
export const shallowWrapperContainsSlotText = (shallowWrapper, slotName, text) =>
- !!shallowWrapper.vm.$slots[slotName].filter(vnode => vNodeContainsText(vnode, text)).length;
+ Boolean(
+ shallowWrapper.vm.$slots[slotName].filter(vnode => vNodeContainsText(vnode, text)).length,
+ );
diff --git a/spec/javascripts/ide/components/commit_sidebar/actions_spec.js b/spec/javascripts/ide/components/commit_sidebar/actions_spec.js
index 23e6a055518..b903abe63fc 100644
--- a/spec/javascripts/ide/components/commit_sidebar/actions_spec.js
+++ b/spec/javascripts/ide/components/commit_sidebar/actions_spec.js
@@ -73,47 +73,4 @@ describe('IDE commit sidebar actions', () => {
expect(vm.commitToCurrentBranchText).not.toContain(injectedSrc);
});
});
-
- describe('create new MR checkbox', () => {
- it('disables `createMR` button when an MR already exists and committing to current branch', () => {
- createComponent({ hasMR: true, commitAction: consts.COMMIT_TO_CURRENT_BRANCH });
-
- expect(vm.$el.querySelector('input[type="checkbox"]').disabled).toBe(true);
- });
-
- it('does not disable checkbox if MR does not exist', () => {
- createComponent({ hasMR: false });
-
- expect(vm.$el.querySelector('input[type="checkbox"]').disabled).toBe(false);
- });
-
- it('does not disable checkbox when creating a new branch', () => {
- createComponent({ commitAction: consts.COMMIT_TO_NEW_BRANCH });
-
- expect(vm.$el.querySelector('input[type="checkbox"]').disabled).toBe(false);
- });
-
- it('toggles off new MR when switching back to commit to current branch and MR exists', () => {
- createComponent({
- commitAction: consts.COMMIT_TO_NEW_BRANCH,
- shouldCreateMR: true,
- });
- const currentBranchRadio = vm.$el.querySelector(
- `input[value="${consts.COMMIT_TO_CURRENT_BRANCH}"`,
- );
- currentBranchRadio.click();
-
- vm.$nextTick(() => {
- expect(vm.$store.state.commit.shouldCreateMR).toBe(false);
- });
- });
-
- it('toggles `shouldCreateMR` when clicking checkbox', () => {
- createComponent();
- const el = vm.$el.querySelector('input[type="checkbox"]');
- el.dispatchEvent(new Event('change'));
-
- expect(vm.$store.state.commit.shouldCreateMR).toBe(true);
- });
- });
});
diff --git a/spec/javascripts/ide/components/commit_sidebar/list_collapsed_spec.js b/spec/javascripts/ide/components/commit_sidebar/list_collapsed_spec.js
index 9af3c15a4e3..3c7d6192e2c 100644
--- a/spec/javascripts/ide/components/commit_sidebar/list_collapsed_spec.js
+++ b/spec/javascripts/ide/components/commit_sidebar/list_collapsed_spec.js
@@ -3,7 +3,7 @@ import store from '~/ide/stores';
import listCollapsed from '~/ide/components/commit_sidebar/list_collapsed.vue';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { file } from '../../helpers';
-import { removeWhitespace } from '../../../helpers/vue_component_helper';
+import { removeWhitespace } from '../../../helpers/text_helper';
describe('Multi-file editor commit sidebar list collapsed', () => {
let vm;
diff --git a/spec/javascripts/ide/components/commit_sidebar/new_merge_request_option_spec.js b/spec/javascripts/ide/components/commit_sidebar/new_merge_request_option_spec.js
new file mode 100644
index 00000000000..7017bfcd6a6
--- /dev/null
+++ b/spec/javascripts/ide/components/commit_sidebar/new_merge_request_option_spec.js
@@ -0,0 +1,73 @@
+import Vue from 'vue';
+import store from '~/ide/stores';
+import consts from '~/ide/stores/modules/commit/constants';
+import NewMergeRequestOption from '~/ide/components/commit_sidebar/new_merge_request_option.vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import { projectData } from 'spec/ide/mock_data';
+import { resetStore } from 'spec/ide/helpers';
+
+describe('create new MR checkbox', () => {
+ let vm;
+ const createComponent = ({
+ hasMR = false,
+ commitAction = consts.COMMIT_TO_NEW_BRANCH,
+ currentBranchId = 'master',
+ } = {}) => {
+ const Component = Vue.extend(NewMergeRequestOption);
+
+ vm = createComponentWithStore(Component, store);
+
+ vm.$store.state.currentBranchId = currentBranchId;
+ vm.$store.state.currentProjectId = 'abcproject';
+ vm.$store.state.commit.commitAction = commitAction;
+ Vue.set(vm.$store.state.projects, 'abcproject', { ...projectData });
+
+ if (hasMR) {
+ vm.$store.state.currentMergeRequestId = '1';
+ vm.$store.state.projects[store.state.currentProjectId].mergeRequests[
+ store.state.currentMergeRequestId
+ ] = { foo: 'bar' };
+ }
+
+ return vm.$mount();
+ };
+
+ afterEach(() => {
+ vm.$destroy();
+
+ resetStore(vm.$store);
+ });
+
+ it('is hidden when an MR already exists and committing to current branch', () => {
+ createComponent({
+ hasMR: true,
+ commitAction: consts.COMMIT_TO_CURRENT_BRANCH,
+ currentBranchId: 'feature',
+ });
+
+ expect(vm.$el.textContent).toBe('');
+ });
+
+ it('does not hide checkbox if MR does not exist', () => {
+ createComponent({ hasMR: false });
+
+ expect(vm.$el.querySelector('input[type="checkbox"]').hidden).toBe(false);
+ });
+
+ it('does not hide checkbox when creating a new branch', () => {
+ createComponent({ commitAction: consts.COMMIT_TO_NEW_BRANCH });
+
+ expect(vm.$el.querySelector('input[type="checkbox"]').hidden).toBe(false);
+ });
+
+ it('dispatches toggleShouldCreateMR when clicking checkbox', () => {
+ createComponent();
+ const el = vm.$el.querySelector('input[type="checkbox"]');
+ spyOn(vm.$store, 'dispatch');
+ el.dispatchEvent(new Event('change'));
+
+ expect(vm.$store.dispatch.calls.allArgs()).toEqual(
+ jasmine.arrayContaining([['commit/toggleShouldCreateMR', jasmine.any(Object)]]),
+ );
+ });
+});
diff --git a/spec/javascripts/ide/components/ide_review_spec.js b/spec/javascripts/ide/components/ide_review_spec.js
index b9ee22b7c1a..396c5d282d4 100644
--- a/spec/javascripts/ide/components/ide_review_spec.js
+++ b/spec/javascripts/ide/components/ide_review_spec.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import IdeReview from '~/ide/components/ide_review.vue';
import store from '~/ide/stores';
import { createComponentWithStore } from '../../helpers/vue_mount_component_helper';
-import { trimText } from '../../helpers/vue_component_helper';
+import { trimText } from '../../helpers/text_helper';
import { resetStore, file } from '../helpers';
import { projectData } from '../mock_data';
diff --git a/spec/javascripts/ide/components/ide_spec.js b/spec/javascripts/ide/components/ide_spec.js
index dc5790f6562..de4becec1cd 100644
--- a/spec/javascripts/ide/components/ide_spec.js
+++ b/spec/javascripts/ide/components/ide_spec.js
@@ -5,21 +5,53 @@ import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helpe
import { file, resetStore } from '../helpers';
import { projectData } from '../mock_data';
-describe('ide component', () => {
+function bootstrap(projData) {
+ const Component = Vue.extend(ide);
+
+ store.state.currentProjectId = 'abcproject';
+ store.state.currentBranchId = 'master';
+ store.state.projects.abcproject = Object.assign({}, projData);
+ Vue.set(store.state.trees, 'abcproject/master', {
+ tree: [],
+ loading: false,
+ });
+
+ return createComponentWithStore(Component, store, {
+ emptyStateSvgPath: 'svg',
+ noChangesStateSvgPath: 'svg',
+ committedStateSvgPath: 'svg',
+ });
+}
+
+describe('ide component, empty repo', () => {
let vm;
beforeEach(() => {
- const Component = Vue.extend(ide);
+ const emptyProjData = Object.assign({}, projectData, { empty_repo: true, branches: {} });
+ vm = bootstrap(emptyProjData);
+ vm.$mount();
+ });
- store.state.currentProjectId = 'abcproject';
- store.state.currentBranchId = 'master';
- store.state.projects.abcproject = Object.assign({}, projectData);
+ afterEach(() => {
+ vm.$destroy();
+
+ resetStore(vm.$store);
+ });
- vm = createComponentWithStore(Component, store, {
- emptyStateSvgPath: 'svg',
- noChangesStateSvgPath: 'svg',
- committedStateSvgPath: 'svg',
- }).$mount();
+ it('renders "New file" button in empty repo', done => {
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.ide-empty-state button[title="New file"]')).not.toBeNull();
+ done();
+ });
+ });
+});
+
+describe('ide component, non-empty repo', () => {
+ let vm;
+
+ beforeEach(() => {
+ vm = bootstrap(projectData);
+ vm.$mount();
});
afterEach(() => {
@@ -28,17 +60,15 @@ describe('ide component', () => {
resetStore(vm.$store);
});
- it('does not render right when no files open', () => {
- expect(vm.$el.querySelector('.panel-right')).toBeNull();
- });
+ it('shows error message when set', done => {
+ expect(vm.$el.querySelector('.flash-container')).toBe(null);
- it('renders right panel when files are open', done => {
- vm.$store.state.trees['abcproject/mybranch'] = {
- tree: [file()],
+ vm.$store.state.errorMessage = {
+ text: 'error',
};
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.panel-right')).toBeNull();
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.flash-container')).not.toBe(null);
done();
});
@@ -71,17 +101,25 @@ describe('ide component', () => {
});
});
- it('shows error message when set', done => {
- expect(vm.$el.querySelector('.flash-container')).toBe(null);
-
- vm.$store.state.errorMessage = {
- text: 'error',
- };
+ describe('non-existent branch', () => {
+ it('does not render "New file" button for non-existent branch when repo is not empty', done => {
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.ide-empty-state button[title="New file"]')).toBeNull();
+ done();
+ });
+ });
+ });
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.flash-container')).not.toBe(null);
+ describe('branch with files', () => {
+ beforeEach(() => {
+ store.state.trees['abcproject/master'].tree = [file()];
+ });
- done();
+ it('does not render "New file" button', done => {
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.ide-empty-state button[title="New file"]')).toBeNull();
+ done();
+ });
});
});
});
diff --git a/spec/javascripts/ide/components/ide_tree_list_spec.js b/spec/javascripts/ide/components/ide_tree_list_spec.js
index 4ecbdb8a55e..f63007c7dd2 100644
--- a/spec/javascripts/ide/components/ide_tree_list_spec.js
+++ b/spec/javascripts/ide/components/ide_tree_list_spec.js
@@ -7,25 +7,23 @@ import { projectData } from '../mock_data';
describe('IDE tree list', () => {
const Component = Vue.extend(IdeTreeList);
+ const normalBranchTree = [file('fileName')];
+ const emptyBranchTree = [];
let vm;
- beforeEach(() => {
+ const bootstrapWithTree = (tree = normalBranchTree) => {
store.state.currentProjectId = 'abcproject';
store.state.currentBranchId = 'master';
store.state.projects.abcproject = Object.assign({}, projectData);
Vue.set(store.state.trees, 'abcproject/master', {
- tree: [file('fileName')],
+ tree,
loading: false,
});
vm = createComponentWithStore(Component, store, {
viewerType: 'edit',
});
-
- spyOn(vm, 'updateViewer').and.callThrough();
-
- vm.$mount();
- });
+ };
afterEach(() => {
vm.$destroy();
@@ -33,22 +31,47 @@ describe('IDE tree list', () => {
resetStore(vm.$store);
});
- it('updates viewer on mount', () => {
- expect(vm.updateViewer).toHaveBeenCalledWith('edit');
- });
+ describe('normal branch', () => {
+ beforeEach(() => {
+ bootstrapWithTree();
+
+ spyOn(vm, 'updateViewer').and.callThrough();
+
+ vm.$mount();
+ });
+
+ it('updates viewer on mount', () => {
+ expect(vm.updateViewer).toHaveBeenCalledWith('edit');
+ });
+
+ it('renders loading indicator', done => {
+ store.state.trees['abcproject/master'].loading = true;
- it('renders loading indicator', done => {
- store.state.trees['abcproject/master'].loading = true;
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.multi-file-loading-container')).not.toBeNull();
+ expect(vm.$el.querySelectorAll('.multi-file-loading-container').length).toBe(3);
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.multi-file-loading-container')).not.toBeNull();
- expect(vm.$el.querySelectorAll('.multi-file-loading-container').length).toBe(3);
+ done();
+ });
+ });
- done();
+ it('renders list of files', () => {
+ expect(vm.$el.textContent).toContain('fileName');
});
});
- it('renders list of files', () => {
- expect(vm.$el.textContent).toContain('fileName');
+ describe('empty-branch state', () => {
+ beforeEach(() => {
+ bootstrapWithTree(emptyBranchTree);
+
+ spyOn(vm, 'updateViewer').and.callThrough();
+
+ vm.$mount();
+ });
+
+ it('does not load files if the branch is empty', () => {
+ expect(vm.$el.textContent).not.toContain('fileName');
+ expect(vm.$el.textContent).toContain('No files');
+ });
});
});
diff --git a/spec/javascripts/ide/components/nav_dropdown_button_spec.js b/spec/javascripts/ide/components/nav_dropdown_button_spec.js
index 0a58e260280..19b0071567a 100644
--- a/spec/javascripts/ide/components/nav_dropdown_button_spec.js
+++ b/spec/javascripts/ide/components/nav_dropdown_button_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import NavDropdownButton from '~/ide/components/nav_dropdown_button.vue';
import store from '~/ide/stores';
-import { trimText } from 'spec/helpers/vue_component_helper';
+import { trimText } from 'spec/helpers/text_helper';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { resetStore } from '../helpers';
diff --git a/spec/javascripts/ide/components/new_dropdown/upload_spec.js b/spec/javascripts/ide/components/new_dropdown/upload_spec.js
index 878e17ac805..d19af6af2d7 100644
--- a/spec/javascripts/ide/components/new_dropdown/upload_spec.js
+++ b/spec/javascripts/ide/components/new_dropdown/upload_spec.js
@@ -78,6 +78,8 @@ describe('new dropdown upload', () => {
type: 'blob',
content: 'plain text',
base64: false,
+ binary: false,
+ rawPath: '',
});
});
@@ -89,6 +91,8 @@ describe('new dropdown upload', () => {
type: 'blob',
content: binaryTarget.result.split('base64,')[1],
base64: true,
+ binary: true,
+ rawPath: binaryTarget.result,
});
});
});
diff --git a/spec/javascripts/ide/mock_data.js b/spec/javascripts/ide/mock_data.js
index 4fe826943b2..570a396c5e3 100644
--- a/spec/javascripts/ide/mock_data.js
+++ b/spec/javascripts/ide/mock_data.js
@@ -16,6 +16,7 @@ export const projectData = {
},
mergeRequests: {},
merge_requests_enabled: true,
+ default_branch: 'master',
};
export const pipelines = [
diff --git a/spec/javascripts/ide/stores/actions/file_spec.js b/spec/javascripts/ide/stores/actions/file_spec.js
index 1e5b55af4ba..dd2313dc800 100644
--- a/spec/javascripts/ide/stores/actions/file_spec.js
+++ b/spec/javascripts/ide/stores/actions/file_spec.js
@@ -10,11 +10,19 @@ import eventHub from '~/ide/eventhub';
import { file, resetStore } from '../../helpers';
import testAction from '../../../helpers/vuex_action_helper';
+const RELATIVE_URL_ROOT = '/gitlab';
+
describe('IDE store file actions', () => {
let mock;
+ let originalGon;
beforeEach(() => {
mock = new MockAdapter(axios);
+ originalGon = window.gon;
+ window.gon = {
+ ...window.gon,
+ relative_url_root: RELATIVE_URL_ROOT,
+ };
spyOn(router, 'push');
});
@@ -22,6 +30,7 @@ describe('IDE store file actions', () => {
afterEach(() => {
mock.restore();
resetStore(store);
+ window.gon = originalGon;
});
describe('closeFile', () => {
@@ -173,13 +182,13 @@ describe('IDE store file actions', () => {
spyOn(service, 'getFileData').and.callThrough();
localFile = file(`newCreate-${Math.random()}`);
- localFile.url = `${gl.TEST_HOST}/getFileDataURL`;
+ localFile.url = `project/getFileDataURL`;
store.state.entries[localFile.path] = localFile;
});
describe('success', () => {
beforeEach(() => {
- mock.onGet(`${gl.TEST_HOST}/getFileDataURL`).replyOnce(
+ mock.onGet(`${RELATIVE_URL_ROOT}/project/getFileDataURL`).replyOnce(
200,
{
blame_path: 'blame_path',
@@ -200,7 +209,9 @@ describe('IDE store file actions', () => {
store
.dispatch('getFileData', { path: localFile.path })
.then(() => {
- expect(service.getFileData).toHaveBeenCalledWith(`${gl.TEST_HOST}/getFileDataURL`);
+ expect(service.getFileData).toHaveBeenCalledWith(
+ `${RELATIVE_URL_ROOT}/project/getFileDataURL`,
+ );
done();
})
@@ -266,7 +277,7 @@ describe('IDE store file actions', () => {
describe('error', () => {
beforeEach(() => {
- mock.onGet(`${gl.TEST_HOST}/getFileDataURL`).networkError();
+ mock.onGet(`project/getFileDataURL`).networkError();
});
it('dispatches error action', done => {
@@ -708,4 +719,20 @@ describe('IDE store file actions', () => {
.catch(done.fail);
});
});
+
+ describe('triggerFilesChange', () => {
+ beforeEach(() => {
+ spyOn(eventHub, '$emit');
+ });
+
+ it('emits event that files have changed', done => {
+ store
+ .dispatch('triggerFilesChange')
+ .then(() => {
+ expect(eventHub.$emit).toHaveBeenCalledWith('ide.files.change');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
});
diff --git a/spec/javascripts/ide/stores/actions/project_spec.js b/spec/javascripts/ide/stores/actions/project_spec.js
index cd519eaed7c..8ecb6129c63 100644
--- a/spec/javascripts/ide/stores/actions/project_spec.js
+++ b/spec/javascripts/ide/stores/actions/project_spec.js
@@ -4,7 +4,7 @@ import {
refreshLastCommitData,
showBranchNotFoundError,
createNewBranchFromDefault,
- getBranchData,
+ showEmptyState,
openBranch,
} from '~/ide/stores/actions';
import store from '~/ide/stores';
@@ -196,39 +196,44 @@ describe('IDE store project actions', () => {
});
});
- describe('getBranchData', () => {
- describe('error', () => {
- it('dispatches branch not found action when response is 404', done => {
- const dispatch = jasmine.createSpy('dispatchSpy');
-
- mock.onGet(/(.*)/).replyOnce(404);
-
- getBranchData(
+ describe('showEmptyState', () => {
+ it('commits proper mutations when supplied error is 404', done => {
+ testAction(
+ showEmptyState,
+ {
+ err: {
+ response: {
+ status: 404,
+ },
+ },
+ projectId: 'abc/def',
+ branchId: 'master',
+ },
+ store.state,
+ [
{
- commit() {},
- dispatch,
- state: store.state,
+ type: 'CREATE_TREE',
+ payload: {
+ treePath: 'abc/def/master',
+ },
},
{
- projectId: 'abc/def',
- branchId: 'master-testing',
+ type: 'TOGGLE_LOADING',
+ payload: {
+ entry: store.state.trees['abc/def/master'],
+ forceValue: false,
+ },
},
- )
- .then(done.fail)
- .catch(() => {
- expect(dispatch.calls.argsFor(0)).toEqual([
- 'showBranchNotFoundError',
- 'master-testing',
- ]);
- done();
- });
- });
+ ],
+ [],
+ done,
+ );
});
});
describe('openBranch', () => {
const branch = {
- projectId: 'feature/lorem-ipsum',
+ projectId: 'abc/def',
branchId: '123-lorem',
};
@@ -238,63 +243,113 @@ describe('IDE store project actions', () => {
'foo/bar-pending': { pending: true },
'foo/bar': { pending: false },
};
-
- spyOn(store, 'dispatch').and.returnValue(Promise.resolve());
});
- it('dispatches branch actions', done => {
- openBranch(store, branch)
- .then(() => {
- expect(store.dispatch.calls.allArgs()).toEqual([
- ['setCurrentBranchId', branch.branchId],
- ['getBranchData', branch],
- ['getFiles', branch],
- ['getMergeRequestsForBranch', branch],
- ]);
- })
- .then(done)
- .catch(done.fail);
- });
+ describe('empty repo', () => {
+ beforeEach(() => {
+ spyOn(store, 'dispatch').and.returnValue(Promise.resolve());
- it('handles tree entry action, if basePath is given', done => {
- openBranch(store, { ...branch, basePath: 'foo/bar/' })
- .then(() => {
- expect(store.dispatch).toHaveBeenCalledWith(
- 'handleTreeEntryAction',
- store.state.entries['foo/bar'],
- );
- })
- .then(done)
- .catch(done.fail);
+ store.state.currentProjectId = 'abc/def';
+ store.state.projects['abc/def'] = {
+ empty_repo: true,
+ };
+ });
+
+ afterEach(() => {
+ resetStore(store);
+ });
+
+ it('dispatches showEmptyState action right away', done => {
+ openBranch(store, branch)
+ .then(() => {
+ expect(store.dispatch.calls.allArgs()).toEqual([
+ ['setCurrentBranchId', branch.branchId],
+ ['showEmptyState', branch],
+ ]);
+ done();
+ })
+ .catch(done.fail);
+ });
});
- it('does not handle tree entry action, if entry is pending', done => {
- openBranch(store, { ...branch, basePath: 'foo/bar-pending' })
- .then(() => {
- expect(store.dispatch).not.toHaveBeenCalledWith(
- 'handleTreeEntryAction',
- jasmine.anything(),
- );
- })
- .then(done)
- .catch(done.fail);
+ describe('existing branch', () => {
+ beforeEach(() => {
+ spyOn(store, 'dispatch').and.returnValue(Promise.resolve());
+ });
+
+ it('dispatches branch actions', done => {
+ openBranch(store, branch)
+ .then(() => {
+ expect(store.dispatch.calls.allArgs()).toEqual([
+ ['setCurrentBranchId', branch.branchId],
+ ['getBranchData', branch],
+ ['getMergeRequestsForBranch', branch],
+ ['getFiles', branch],
+ ]);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('handles tree entry action, if basePath is given', done => {
+ openBranch(store, { ...branch, basePath: 'foo/bar/' })
+ .then(() => {
+ expect(store.dispatch).toHaveBeenCalledWith(
+ 'handleTreeEntryAction',
+ store.state.entries['foo/bar'],
+ );
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('does not handle tree entry action, if entry is pending', done => {
+ openBranch(store, { ...branch, basePath: 'foo/bar-pending' })
+ .then(() => {
+ expect(store.dispatch).not.toHaveBeenCalledWith(
+ 'handleTreeEntryAction',
+ jasmine.anything(),
+ );
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('creates a new file supplied via URL if the file does not exist yet', done => {
+ openBranch(store, { ...branch, basePath: 'not-existent.md' })
+ .then(() => {
+ expect(store.dispatch).not.toHaveBeenCalledWith(
+ 'handleTreeEntryAction',
+ jasmine.anything(),
+ );
+
+ expect(store.dispatch).toHaveBeenCalledWith('createTempEntry', {
+ name: 'not-existent.md',
+ type: 'blob',
+ });
+ })
+ .then(done)
+ .catch(done.fail);
+ });
});
- it('creates a new file supplied via URL if the file does not exist yet', done => {
- openBranch(store, { ...branch, basePath: 'not-existent.md' })
- .then(() => {
- expect(store.dispatch).not.toHaveBeenCalledWith(
- 'handleTreeEntryAction',
- jasmine.anything(),
- );
+ describe('non-existent branch', () => {
+ beforeEach(() => {
+ spyOn(store, 'dispatch').and.returnValue(Promise.reject());
+ });
- expect(store.dispatch).toHaveBeenCalledWith('createTempEntry', {
- name: 'not-existent.md',
- type: 'blob',
- });
- })
- .then(done)
- .catch(done.fail);
+ it('dispatches correct branch actions', done => {
+ openBranch(store, branch)
+ .then(() => {
+ expect(store.dispatch.calls.allArgs()).toEqual([
+ ['setCurrentBranchId', branch.branchId],
+ ['getBranchData', branch],
+ ['showBranchNotFoundError', branch.branchId],
+ ]);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
});
});
});
diff --git a/spec/javascripts/ide/stores/actions/tree_spec.js b/spec/javascripts/ide/stores/actions/tree_spec.js
index 5ed9b9003a7..674ecdc6764 100644
--- a/spec/javascripts/ide/stores/actions/tree_spec.js
+++ b/spec/javascripts/ide/stores/actions/tree_spec.js
@@ -93,38 +93,6 @@ describe('Multi-file store tree actions', () => {
});
describe('error', () => {
- it('dispatches branch not found actions when response is 404', done => {
- const dispatch = jasmine.createSpy('dispatchSpy');
-
- store.state.projects = {
- 'abc/def': {
- web_url: `${gl.TEST_HOST}/files`,
- },
- };
-
- mock.onGet(/(.*)/).replyOnce(404);
-
- getFiles(
- {
- commit() {},
- dispatch,
- state: store.state,
- },
- {
- projectId: 'abc/def',
- branchId: 'master-testing',
- },
- )
- .then(done.fail)
- .catch(() => {
- expect(dispatch.calls.argsFor(0)).toEqual([
- 'showBranchNotFoundError',
- 'master-testing',
- ]);
- done();
- });
- });
-
it('dispatches error action', done => {
const dispatch = jasmine.createSpy('dispatchSpy');
diff --git a/spec/javascripts/ide/stores/actions_spec.js b/spec/javascripts/ide/stores/actions_spec.js
index 0b5587d02ae..37354283cab 100644
--- a/spec/javascripts/ide/stores/actions_spec.js
+++ b/spec/javascripts/ide/stores/actions_spec.js
@@ -9,12 +9,15 @@ import actions, {
setErrorMessage,
deleteEntry,
renameEntry,
+ getBranchData,
} from '~/ide/stores/actions';
+import axios from '~/lib/utils/axios_utils';
import store from '~/ide/stores';
import * as types from '~/ide/stores/mutation_types';
import router from '~/ide/ide_router';
import { resetStore, file } from '../helpers';
import testAction from '../../helpers/vuex_action_helper';
+import MockAdapter from 'axios-mock-adapter';
describe('Multi-file store actions', () => {
beforeEach(() => {
@@ -485,7 +488,7 @@ describe('Multi-file store actions', () => {
'path',
store.state,
[{ type: types.DELETE_ENTRY, payload: 'path' }],
- [{ type: 'burstUnusedSeal' }],
+ [{ type: 'burstUnusedSeal' }, { type: 'triggerFilesChange' }],
done,
);
});
@@ -507,7 +510,7 @@ describe('Multi-file store actions', () => {
payload: { path: 'test', name: 'new-name', entryPath: null, parentPath: 'parent-path' },
},
],
- [{ type: 'deleteEntry', payload: 'test' }],
+ [{ type: 'deleteEntry', payload: 'test' }, { type: 'triggerFilesChange' }],
done,
);
});
@@ -555,9 +558,71 @@ describe('Multi-file store actions', () => {
},
},
{ type: 'deleteEntry', payload: 'test' },
+ { type: 'triggerFilesChange' },
],
done,
);
});
});
+
+ describe('getBranchData', () => {
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ describe('error', () => {
+ let dispatch;
+ const callParams = [
+ {
+ commit() {},
+ state: store.state,
+ },
+ {
+ projectId: 'abc/def',
+ branchId: 'master-testing',
+ },
+ ];
+
+ beforeEach(() => {
+ dispatch = jasmine.createSpy('dispatchSpy');
+ document.body.innerHTML += '<div class="flash-container"></div>';
+ });
+
+ afterEach(() => {
+ document.querySelector('.flash-container').remove();
+ });
+
+ it('passes the error further unchanged without dispatching any action when response is 404', done => {
+ mock.onGet(/(.*)/).replyOnce(404);
+
+ getBranchData(...callParams)
+ .then(done.fail)
+ .catch(e => {
+ expect(dispatch.calls.count()).toEqual(0);
+ expect(e.response.status).toEqual(404);
+ expect(document.querySelector('.flash-alert')).toBeNull();
+ done();
+ });
+ });
+
+ it('does not pass the error further and flashes an alert if error is not 404', done => {
+ mock.onGet(/(.*)/).replyOnce(418);
+
+ getBranchData(...callParams)
+ .then(done.fail)
+ .catch(e => {
+ expect(dispatch.calls.count()).toEqual(0);
+ expect(e.response).toBeUndefined();
+ expect(document.querySelector('.flash-alert')).not.toBeNull();
+ done();
+ });
+ });
+ });
+ });
});
diff --git a/spec/javascripts/ide/stores/getters_spec.js b/spec/javascripts/ide/stores/getters_spec.js
index 9c135661997..735bbd47f55 100644
--- a/spec/javascripts/ide/stores/getters_spec.js
+++ b/spec/javascripts/ide/stores/getters_spec.js
@@ -180,6 +180,38 @@ describe('IDE store getters', () => {
});
});
+ describe('isOnDefaultBranch', () => {
+ it('returns false when no project exists', () => {
+ const localGetters = {
+ currentProject: undefined,
+ };
+
+ expect(getters.isOnDefaultBranch({}, localGetters)).toBeFalsy();
+ });
+
+ it("returns true when project's default branch matches current branch", () => {
+ const localGetters = {
+ currentProject: {
+ default_branch: 'master',
+ },
+ branchName: 'master',
+ };
+
+ expect(getters.isOnDefaultBranch({}, localGetters)).toBeTruthy();
+ });
+
+ it("returns false when project's default branch doesn't match current branch", () => {
+ const localGetters = {
+ currentProject: {
+ default_branch: 'master',
+ },
+ branchName: 'feature',
+ };
+
+ expect(getters.isOnDefaultBranch({}, localGetters)).toBeFalsy();
+ });
+ });
+
describe('packageJson', () => {
it('returns package.json entry', () => {
localState.entries['package.json'] = { name: 'package.json' };
diff --git a/spec/javascripts/ide/stores/modules/commit/actions_spec.js b/spec/javascripts/ide/stores/modules/commit/actions_spec.js
index abc97f3072c..5f7272311c8 100644
--- a/spec/javascripts/ide/stores/modules/commit/actions_spec.js
+++ b/spec/javascripts/ide/stores/modules/commit/actions_spec.js
@@ -1,9 +1,13 @@
-import actions from '~/ide/stores/actions';
+import rootActions from '~/ide/stores/actions';
import store from '~/ide/stores';
import service from '~/ide/services';
import router from '~/ide/ide_router';
import eventHub from '~/ide/eventhub';
import consts from '~/ide/stores/modules/commit/constants';
+import * as mutationTypes from '~/ide/stores/modules/commit/mutation_types';
+import * as actions from '~/ide/stores/modules/commit/actions';
+import testAction from '../../../../helpers/vuex_action_helper';
+import { commitActionTypes } from '~/ide/constants';
import { resetStore, file } from 'spec/ide/helpers';
describe('IDE commit module actions', () => {
@@ -224,7 +228,7 @@ describe('IDE commit module actions', () => {
let visitUrl;
beforeEach(() => {
- visitUrl = spyOnDependency(actions, 'visitUrl');
+ visitUrl = spyOnDependency(rootActions, 'visitUrl');
document.body.innerHTML += '<div class="flash-container"></div>';
@@ -271,6 +275,7 @@ describe('IDE commit module actions', () => {
short_id: '123',
message: 'test message',
committed_date: 'date',
+ parent_ids: '321',
stats: {
additions: '1',
deletions: '2',
@@ -294,7 +299,7 @@ describe('IDE commit module actions', () => {
commit_message: 'testing 123',
actions: [
{
- action: 'update',
+ action: commitActionTypes.update,
file_path: jasmine.anything(),
content: undefined,
encoding: jasmine.anything(),
@@ -321,7 +326,7 @@ describe('IDE commit module actions', () => {
commit_message: 'testing 123',
actions: [
{
- action: 'update',
+ action: commitActionTypes.update,
file_path: jasmine.anything(),
content: undefined,
encoding: jasmine.anything(),
@@ -462,5 +467,213 @@ describe('IDE commit module actions', () => {
.catch(done.fail);
});
});
+
+ describe('first commit of a branch', () => {
+ const COMMIT_RESPONSE = {
+ id: '123456',
+ short_id: '123',
+ message: 'test message',
+ committed_date: 'date',
+ parent_ids: [],
+ stats: {
+ additions: '1',
+ deletions: '2',
+ },
+ };
+
+ it('commits TOGGLE_EMPTY_STATE mutation on empty repo', done => {
+ spyOn(service, 'commit').and.returnValue(
+ Promise.resolve({
+ data: COMMIT_RESPONSE,
+ }),
+ );
+
+ spyOn(store, 'commit').and.callThrough();
+
+ store
+ .dispatch('commit/commitChanges')
+ .then(() => {
+ expect(store.commit.calls.allArgs()).toEqual(
+ jasmine.arrayContaining([
+ ['TOGGLE_EMPTY_STATE', jasmine.any(Object), jasmine.any(Object)],
+ ]),
+ );
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('does not commmit TOGGLE_EMPTY_STATE mutation on existing project', done => {
+ COMMIT_RESPONSE.parent_ids.push('1234');
+ spyOn(service, 'commit').and.returnValue(
+ Promise.resolve({
+ data: COMMIT_RESPONSE,
+ }),
+ );
+ spyOn(store, 'commit').and.callThrough();
+
+ store
+ .dispatch('commit/commitChanges')
+ .then(() => {
+ expect(store.commit.calls.allArgs()).not.toEqual(
+ jasmine.arrayContaining([
+ ['TOGGLE_EMPTY_STATE', jasmine.any(Object), jasmine.any(Object)],
+ ]),
+ );
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
+ });
+
+ describe('toggleShouldCreateMR', () => {
+ it('commits both toggle and interacting with MR checkbox actions', done => {
+ testAction(
+ actions.toggleShouldCreateMR,
+ {},
+ store.state,
+ [
+ { type: mutationTypes.TOGGLE_SHOULD_CREATE_MR },
+ { type: mutationTypes.INTERACT_WITH_NEW_MR },
+ ],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('setShouldCreateMR', () => {
+ beforeEach(() => {
+ store.state.projects = {
+ project: {
+ default_branch: 'master',
+ branches: {
+ master: {
+ name: 'master',
+ },
+ feature: {
+ name: 'feature',
+ },
+ },
+ },
+ };
+
+ store.state.currentProjectId = 'project';
+ });
+
+ it('sets to false when the current branch already has an MR', done => {
+ store.state.commit.currentMergeRequestId = 1;
+ store.state.commit.commitAction = consts.COMMIT_TO_CURRENT_BRANCH;
+ store.state.currentMergeRequestId = '1';
+ store.state.currentBranchId = 'feature';
+ spyOn(store, 'commit').and.callThrough();
+
+ store
+ .dispatch('commit/setShouldCreateMR')
+ .then(() => {
+ expect(store.commit.calls.allArgs()[0]).toEqual(
+ jasmine.arrayContaining([`commit/${mutationTypes.TOGGLE_SHOULD_CREATE_MR}`, false]),
+ );
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('changes to false when current branch is the default branch and user has not interacted', done => {
+ store.state.commit.interactedWithNewMR = false;
+ store.state.currentBranchId = 'master';
+ store.state.commit.commitAction = consts.COMMIT_TO_CURRENT_BRANCH;
+ spyOn(store, 'commit').and.callThrough();
+
+ store
+ .dispatch('commit/setShouldCreateMR')
+ .then(() => {
+ expect(store.commit.calls.allArgs()[0]).toEqual(
+ jasmine.arrayContaining([`commit/${mutationTypes.TOGGLE_SHOULD_CREATE_MR}`, false]),
+ );
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('changes to true when "create new branch" is selected and user has not interacted', done => {
+ store.state.commit.commitAction = consts.COMMIT_TO_NEW_BRANCH;
+ store.state.commit.interactedWithNewMR = false;
+ spyOn(store, 'commit').and.callThrough();
+
+ store
+ .dispatch('commit/setShouldCreateMR')
+ .then(() => {
+ expect(store.commit.calls.allArgs()[0]).toEqual(
+ jasmine.arrayContaining([`commit/${mutationTypes.TOGGLE_SHOULD_CREATE_MR}`, true]),
+ );
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('does not change anything if user has interacted and comitting to new branch', done => {
+ store.state.commit.commitAction = consts.COMMIT_TO_NEW_BRANCH;
+ store.state.commit.interactedWithNewMR = true;
+ spyOn(store, 'commit').and.callThrough();
+
+ store
+ .dispatch('commit/setShouldCreateMR')
+ .then(() => {
+ expect(store.commit).not.toHaveBeenCalled();
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('does not change anything if user has interacted and comitting to branch without MR', done => {
+ store.state.commit.commitAction = consts.COMMIT_TO_CURRENT_BRANCH;
+ store.state.commit.currentMergeRequestId = null;
+ store.state.commit.interactedWithNewMR = true;
+ spyOn(store, 'commit').and.callThrough();
+
+ store
+ .dispatch('commit/setShouldCreateMR')
+ .then(() => {
+ expect(store.commit).not.toHaveBeenCalled();
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('still changes to false if hiding the checkbox', done => {
+ store.state.currentBranchId = 'feature';
+ store.state.commit.commitAction = consts.COMMIT_TO_CURRENT_BRANCH;
+ store.state.currentMergeRequestId = '1';
+ store.state.commit.interactedWithNewMR = true;
+ spyOn(store, 'commit').and.callThrough();
+
+ store
+ .dispatch('commit/setShouldCreateMR')
+ .then(() => {
+ expect(store.commit.calls.allArgs()[0]).toEqual(
+ jasmine.arrayContaining([`commit/${mutationTypes.TOGGLE_SHOULD_CREATE_MR}`, false]),
+ );
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('does not change to false when on master and user has interacted even if MR exists', done => {
+ store.state.currentBranchId = 'master';
+ store.state.commit.commitAction = consts.COMMIT_TO_CURRENT_BRANCH;
+ store.state.currentMergeRequestId = '1';
+ store.state.commit.interactedWithNewMR = true;
+ spyOn(store, 'commit').and.callThrough();
+
+ store
+ .dispatch('commit/setShouldCreateMR')
+ .then(() => {
+ expect(store.commit).not.toHaveBeenCalled();
+ done();
+ })
+ .catch(done.fail);
+ });
});
});
diff --git a/spec/javascripts/ide/stores/modules/commit/getters_spec.js b/spec/javascripts/ide/stores/modules/commit/getters_spec.js
index e00fd7199d7..6e71a790deb 100644
--- a/spec/javascripts/ide/stores/modules/commit/getters_spec.js
+++ b/spec/javascripts/ide/stores/modules/commit/getters_spec.js
@@ -144,33 +144,4 @@ describe('IDE commit module getters', () => {
});
});
});
-
- describe('shouldDisableNewMrOption', () => {
- it('returns false if commitAction `COMMIT_TO_NEW_BRANCH`', () => {
- state.commitAction = consts.COMMIT_TO_NEW_BRANCH;
- const rootState = {
- currentMergeRequest: { foo: 'bar' },
- };
-
- expect(getters.shouldDisableNewMrOption(state, null, null, rootState)).toBeFalsy();
- });
-
- it('returns false if there is no current merge request', () => {
- state.commitAction = consts.COMMIT_TO_CURRENT_BRANCH;
- const rootState = {
- currentMergeRequest: null,
- };
-
- expect(getters.shouldDisableNewMrOption(state, null, null, rootState)).toBeFalsy();
- });
-
- it('returns true an MR exists and commit action is `COMMIT_TO_CURRENT_BRANCH`', () => {
- state.commitAction = consts.COMMIT_TO_CURRENT_BRANCH;
- const rootState = {
- currentMergeRequest: { foo: 'bar' },
- };
-
- expect(getters.shouldDisableNewMrOption(state, null, null, rootState)).toBeTruthy();
- });
- });
});
diff --git a/spec/javascripts/ide/stores/modules/file_templates/actions_spec.js b/spec/javascripts/ide/stores/modules/file_templates/actions_spec.js
index 734233100ab..548962c7a92 100644
--- a/spec/javascripts/ide/stores/modules/file_templates/actions_spec.js
+++ b/spec/javascripts/ide/stores/modules/file_templates/actions_spec.js
@@ -69,18 +69,16 @@ describe('IDE file templates actions', () => {
describe('fetchTemplateTypes', () => {
describe('success', () => {
- let nextPage;
+ const pages = [[{ name: 'MIT' }], [{ name: 'Apache' }], [{ name: 'CC' }]];
beforeEach(() => {
- mock.onGet(/api\/(.*)\/templates\/licenses/).replyOnce(() => [
- 200,
- [
- {
- name: 'MIT',
- },
- ],
- { 'X-NEXT-PAGE': nextPage },
- ]);
+ mock.onGet(/api\/(.*)\/templates\/licenses/).reply(({ params }) => {
+ const pageNum = params.page;
+ const page = pages[pageNum - 1];
+ const hasNextPage = pageNum < pages.length;
+
+ return [200, page, hasNextPage ? { 'X-NEXT-PAGE': pageNum + 1 } : {}];
+ });
});
it('rejects if selectedTemplateType is empty', done => {
@@ -112,43 +110,15 @@ describe('IDE file templates actions', () => {
},
{
type: 'receiveTemplateTypesSuccess',
- payload: [
- {
- name: 'MIT',
- },
- ],
- },
- ],
- done,
- );
- });
-
- it('dispatches actions for next page', done => {
- nextPage = '2';
- state.selectedTemplateType = {
- key: 'licenses',
- };
-
- testAction(
- actions.fetchTemplateTypes,
- null,
- state,
- [],
- [
- {
- type: 'requestTemplateTypes',
+ payload: pages[0],
},
{
type: 'receiveTemplateTypesSuccess',
- payload: [
- {
- name: 'MIT',
- },
- ],
+ payload: pages[0].concat(pages[1]),
},
{
- type: 'fetchTemplateTypes',
- payload: 2,
+ type: 'receiveTemplateTypesSuccess',
+ payload: pages[0].concat(pages[1]).concat(pages[2]),
},
],
done,
diff --git a/spec/javascripts/ide/stores/utils_spec.js b/spec/javascripts/ide/stores/utils_spec.js
index c4f122efdda..debe1c4acee 100644
--- a/spec/javascripts/ide/stores/utils_spec.js
+++ b/spec/javascripts/ide/stores/utils_spec.js
@@ -1,4 +1,5 @@
import * as utils from '~/ide/stores/utils';
+import { commitActionTypes } from '~/ide/constants';
import { file } from '../helpers';
describe('Multi-file store utils', () => {
@@ -107,7 +108,7 @@ describe('Multi-file store utils', () => {
commit_message: 'commit message',
actions: [
{
- action: 'update',
+ action: commitActionTypes.update,
file_path: 'staged',
content: 'updated file content',
encoding: 'text',
@@ -115,7 +116,7 @@ describe('Multi-file store utils', () => {
previous_path: undefined,
},
{
- action: 'create',
+ action: commitActionTypes.create,
file_path: 'added',
content: 'new file content',
encoding: 'base64',
@@ -123,7 +124,7 @@ describe('Multi-file store utils', () => {
previous_path: undefined,
},
{
- action: 'delete',
+ action: commitActionTypes.delete,
file_path: 'deletedFile',
content: undefined,
encoding: 'text',
@@ -170,7 +171,7 @@ describe('Multi-file store utils', () => {
commit_message: 'prebuilt test commit message',
actions: [
{
- action: 'update',
+ action: commitActionTypes.update,
file_path: 'staged',
content: 'updated file content',
encoding: 'text',
@@ -178,7 +179,7 @@ describe('Multi-file store utils', () => {
previous_path: undefined,
},
{
- action: 'create',
+ action: commitActionTypes.create,
file_path: 'added',
content: 'new file content',
encoding: 'base64',
@@ -193,19 +194,19 @@ describe('Multi-file store utils', () => {
describe('commitActionForFile', () => {
it('returns deleted for deleted file', () => {
- expect(utils.commitActionForFile({ deleted: true })).toBe('delete');
+ expect(utils.commitActionForFile({ deleted: true })).toBe(commitActionTypes.delete);
});
it('returns create for tempFile', () => {
- expect(utils.commitActionForFile({ tempFile: true })).toBe('create');
+ expect(utils.commitActionForFile({ tempFile: true })).toBe(commitActionTypes.create);
});
it('returns move for moved file', () => {
- expect(utils.commitActionForFile({ prevPath: 'test' })).toBe('move');
+ expect(utils.commitActionForFile({ prevPath: 'test' })).toBe(commitActionTypes.move);
});
it('returns update by default', () => {
- expect(utils.commitActionForFile({})).toBe('update');
+ expect(utils.commitActionForFile({})).toBe(commitActionTypes.update);
});
});
diff --git a/spec/javascripts/import_projects/components/import_projects_table_spec.js b/spec/javascripts/import_projects/components/import_projects_table_spec.js
deleted file mode 100644
index ab8642bf0dd..00000000000
--- a/spec/javascripts/import_projects/components/import_projects_table_spec.js
+++ /dev/null
@@ -1,188 +0,0 @@
-import Vue from 'vue';
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import createStore from '~/import_projects/store';
-import importProjectsTable from '~/import_projects/components/import_projects_table.vue';
-import STATUS_MAP from '~/import_projects/constants';
-import setTimeoutPromise from '../../helpers/set_timeout_promise_helper';
-
-describe('ImportProjectsTable', () => {
- let vm;
- let mock;
- let store;
- const reposPath = '/repos-path';
- const jobsPath = '/jobs-path';
- const providerTitle = 'THE PROVIDER';
- const providerRepo = { id: 10, sanitizedName: 'sanitizedName', fullName: 'fullName' };
- const importedProject = {
- id: 1,
- fullPath: 'fullPath',
- importStatus: 'started',
- providerLink: 'providerLink',
- importSource: 'importSource',
- };
-
- function createComponent() {
- const ImportProjectsTable = Vue.extend(importProjectsTable);
-
- const component = new ImportProjectsTable({
- store,
- propsData: {
- providerTitle,
- },
- }).$mount();
-
- store.dispatch('stopJobsPolling');
-
- return component;
- }
-
- beforeEach(() => {
- store = createStore();
- store.dispatch('setInitialData', { reposPath });
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- vm.$destroy();
- mock.restore();
- });
-
- it('renders a loading icon whilst repos are loading', done => {
- mock.restore(); // Stop the mock adapter from responding to the request, keeping the spinner up
-
- vm = createComponent();
-
- setTimeoutPromise()
- .then(() => {
- expect(vm.$el.querySelector('.js-loading-button-icon')).not.toBeNull();
- })
- .then(() => done())
- .catch(() => done.fail());
- });
-
- it('renders a table with imported projects and provider repos', done => {
- const response = {
- importedProjects: [importedProject],
- providerRepos: [providerRepo],
- namespaces: [{ path: 'path' }],
- };
- mock.onGet(reposPath).reply(200, response);
-
- vm = createComponent();
-
- setTimeoutPromise()
- .then(() => {
- expect(vm.$el.querySelector('.js-loading-button-icon')).toBeNull();
- expect(vm.$el.querySelector('.table')).not.toBeNull();
- expect(vm.$el.querySelector('.import-jobs-from-col').innerText).toMatch(
- `From ${providerTitle}`,
- );
-
- expect(vm.$el.querySelector('.js-imported-project')).not.toBeNull();
- expect(vm.$el.querySelector('.js-provider-repo')).not.toBeNull();
- })
- .then(() => done())
- .catch(() => done.fail());
- });
-
- it('renders an empty state if there are no imported projects or provider repos', done => {
- const response = {
- importedProjects: [],
- providerRepos: [],
- namespaces: [],
- };
- mock.onGet(reposPath).reply(200, response);
-
- vm = createComponent();
-
- setTimeoutPromise()
- .then(() => {
- expect(vm.$el.querySelector('.js-loading-button-icon')).toBeNull();
- expect(vm.$el.querySelector('.table')).toBeNull();
- expect(vm.$el.innerText).toMatch(`No ${providerTitle} repositories available to import`);
- })
- .then(() => done())
- .catch(() => done.fail());
- });
-
- it('imports provider repos if bulk import button is clicked', done => {
- const importPath = '/import-path';
- const response = {
- importedProjects: [],
- providerRepos: [providerRepo],
- namespaces: [{ path: 'path' }],
- };
-
- mock.onGet(reposPath).replyOnce(200, response);
- mock.onPost(importPath).replyOnce(200, importedProject);
-
- store.dispatch('setInitialData', { importPath });
-
- vm = createComponent();
-
- setTimeoutPromise()
- .then(() => {
- expect(vm.$el.querySelector('.js-imported-project')).toBeNull();
- expect(vm.$el.querySelector('.js-provider-repo')).not.toBeNull();
-
- vm.$el.querySelector('.js-import-all').click();
- })
- .then(() => setTimeoutPromise())
- .then(() => {
- expect(vm.$el.querySelector('.js-imported-project')).not.toBeNull();
- expect(vm.$el.querySelector('.js-provider-repo')).toBeNull();
- })
- .then(() => done())
- .catch(() => done.fail());
- });
-
- it('polls to update the status of imported projects', done => {
- const importPath = '/import-path';
- const response = {
- importedProjects: [importedProject],
- providerRepos: [],
- namespaces: [{ path: 'path' }],
- };
- const updatedProjects = [
- {
- id: importedProject.id,
- importStatus: 'finished',
- },
- ];
-
- mock.onGet(reposPath).replyOnce(200, response);
-
- store.dispatch('setInitialData', { importPath, jobsPath });
-
- vm = createComponent();
-
- setTimeoutPromise()
- .then(() => {
- const statusObject = STATUS_MAP[importedProject.importStatus];
-
- expect(vm.$el.querySelector('.js-imported-project')).not.toBeNull();
- expect(vm.$el.querySelector(`.${statusObject.textClass}`).textContent).toMatch(
- statusObject.text,
- );
-
- expect(vm.$el.querySelector(`.ic-status_${statusObject.icon}`)).not.toBeNull();
-
- mock.onGet(jobsPath).replyOnce(200, updatedProjects);
- return store.dispatch('restartJobsPolling');
- })
- .then(() => setTimeoutPromise())
- .then(() => {
- const statusObject = STATUS_MAP[updatedProjects[0].importStatus];
-
- expect(vm.$el.querySelector('.js-imported-project')).not.toBeNull();
- expect(vm.$el.querySelector(`.${statusObject.textClass}`).textContent).toMatch(
- statusObject.text,
- );
-
- expect(vm.$el.querySelector(`.ic-status_${statusObject.icon}`)).not.toBeNull();
- })
- .then(() => done())
- .catch(() => done.fail());
- });
-});
diff --git a/spec/javascripts/import_projects/components/imported_project_table_row_spec.js b/spec/javascripts/import_projects/components/imported_project_table_row_spec.js
deleted file mode 100644
index 7dac7e9ccc1..00000000000
--- a/spec/javascripts/import_projects/components/imported_project_table_row_spec.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import Vue from 'vue';
-import createStore from '~/import_projects/store';
-import importedProjectTableRow from '~/import_projects/components/imported_project_table_row.vue';
-import STATUS_MAP from '~/import_projects/constants';
-
-describe('ImportedProjectTableRow', () => {
- let vm;
- const project = {
- id: 1,
- fullPath: 'fullPath',
- importStatus: 'finished',
- providerLink: 'providerLink',
- importSource: 'importSource',
- };
-
- function createComponent() {
- const ImportedProjectTableRow = Vue.extend(importedProjectTableRow);
-
- const store = createStore();
- return new ImportedProjectTableRow({
- store,
- propsData: {
- project: {
- ...project,
- },
- },
- }).$mount();
- }
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders an imported project table row', () => {
- vm = createComponent();
-
- const providerLink = vm.$el.querySelector('.js-provider-link');
- const statusObject = STATUS_MAP[project.importStatus];
-
- expect(vm.$el.classList.contains('js-imported-project')).toBe(true);
- expect(providerLink.href).toMatch(project.providerLink);
- expect(providerLink.textContent).toMatch(project.importSource);
- expect(vm.$el.querySelector('.js-full-path').textContent).toMatch(project.fullPath);
- expect(vm.$el.querySelector(`.${statusObject.textClass}`).textContent).toMatch(
- statusObject.text,
- );
-
- expect(vm.$el.querySelector(`.ic-status_${statusObject.icon}`)).not.toBeNull();
- expect(vm.$el.querySelector('.js-go-to-project').href).toMatch(project.fullPath);
- });
-});
diff --git a/spec/javascripts/import_projects/components/provider_repo_table_row_spec.js b/spec/javascripts/import_projects/components/provider_repo_table_row_spec.js
deleted file mode 100644
index 4d2bacd2ad0..00000000000
--- a/spec/javascripts/import_projects/components/provider_repo_table_row_spec.js
+++ /dev/null
@@ -1,96 +0,0 @@
-import Vue from 'vue';
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import createStore from '~/import_projects/store';
-import providerRepoTableRow from '~/import_projects/components/provider_repo_table_row.vue';
-import STATUS_MAP, { STATUSES } from '~/import_projects/constants';
-import setTimeoutPromise from '../../helpers/set_timeout_promise_helper';
-
-describe('ProviderRepoTableRow', () => {
- let store;
- let vm;
- const repo = {
- id: 10,
- sanitizedName: 'sanitizedName',
- fullName: 'fullName',
- providerLink: 'providerLink',
- };
-
- function createComponent() {
- const ProviderRepoTableRow = Vue.extend(providerRepoTableRow);
-
- return new ProviderRepoTableRow({
- store,
- propsData: {
- repo: {
- ...repo,
- },
- },
- }).$mount();
- }
-
- beforeEach(() => {
- store = createStore();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders a provider repo table row', () => {
- vm = createComponent();
-
- const providerLink = vm.$el.querySelector('.js-provider-link');
- const statusObject = STATUS_MAP[STATUSES.NONE];
-
- expect(vm.$el.classList.contains('js-provider-repo')).toBe(true);
- expect(providerLink.href).toMatch(repo.providerLink);
- expect(providerLink.textContent).toMatch(repo.fullName);
- expect(vm.$el.querySelector(`.${statusObject.textClass}`).textContent).toMatch(
- statusObject.text,
- );
-
- expect(vm.$el.querySelector(`.ic-status_${statusObject.icon}`)).not.toBeNull();
- expect(vm.$el.querySelector('.js-import-button')).not.toBeNull();
- });
-
- it('renders a select2 namespace select', () => {
- vm = createComponent();
-
- const dropdownTrigger = vm.$el.querySelector('.js-namespace-select');
-
- expect(dropdownTrigger).not.toBeNull();
- expect(dropdownTrigger.classList.contains('select2-container')).toBe(true);
-
- dropdownTrigger.click();
-
- expect(vm.$el.querySelector('.select2-drop')).not.toBeNull();
- });
-
- it('imports repo when clicking import button', done => {
- const importPath = '/import-path';
- const defaultTargetNamespace = 'user';
- const ciCdOnly = true;
- const mock = new MockAdapter(axios);
-
- store.dispatch('setInitialData', { importPath, defaultTargetNamespace, ciCdOnly });
- mock.onPost(importPath).replyOnce(200);
- spyOn(store, 'dispatch').and.returnValue(new Promise(() => {}));
-
- vm = createComponent();
-
- vm.$el.querySelector('.js-import-button').click();
-
- setTimeoutPromise()
- .then(() => {
- expect(store.dispatch).toHaveBeenCalledWith('fetchImport', {
- repo,
- newName: repo.sanitizedName,
- targetNamespace: defaultTargetNamespace,
- });
- })
- .then(() => mock.restore())
- .then(done)
- .catch(done.fail);
- });
-});
diff --git a/spec/javascripts/import_projects/store/actions_spec.js b/spec/javascripts/import_projects/store/actions_spec.js
deleted file mode 100644
index 77850ee3283..00000000000
--- a/spec/javascripts/import_projects/store/actions_spec.js
+++ /dev/null
@@ -1,284 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import {
- SET_INITIAL_DATA,
- REQUEST_REPOS,
- RECEIVE_REPOS_SUCCESS,
- RECEIVE_REPOS_ERROR,
- REQUEST_IMPORT,
- RECEIVE_IMPORT_SUCCESS,
- RECEIVE_IMPORT_ERROR,
- RECEIVE_JOBS_SUCCESS,
-} from '~/import_projects/store/mutation_types';
-import {
- setInitialData,
- requestRepos,
- receiveReposSuccess,
- receiveReposError,
- fetchRepos,
- requestImport,
- receiveImportSuccess,
- receiveImportError,
- fetchImport,
- receiveJobsSuccess,
- fetchJobs,
- clearJobsEtagPoll,
- stopJobsPolling,
-} from '~/import_projects/store/actions';
-import state from '~/import_projects/store/state';
-import testAction from 'spec/helpers/vuex_action_helper';
-import { TEST_HOST } from 'spec/test_constants';
-
-describe('import_projects store actions', () => {
- let localState;
- const repoId = 1;
- const repos = [{ id: 1 }, { id: 2 }];
- const importPayload = { newName: 'newName', targetNamespace: 'targetNamespace', repo: { id: 1 } };
-
- beforeEach(() => {
- localState = state();
- });
-
- describe('setInitialData', () => {
- it(`commits ${SET_INITIAL_DATA} mutation`, done => {
- const initialData = {
- reposPath: 'reposPath',
- provider: 'provider',
- jobsPath: 'jobsPath',
- importPath: 'impapp/assets/javascripts/vue_shared/components/select2_select.vueortPath',
- defaultTargetNamespace: 'defaultTargetNamespace',
- ciCdOnly: 'ciCdOnly',
- canSelectNamespace: 'canSelectNamespace',
- };
-
- testAction(
- setInitialData,
- initialData,
- localState,
- [{ type: SET_INITIAL_DATA, payload: initialData }],
- [],
- done,
- );
- });
- });
-
- describe('requestRepos', () => {
- it(`requestRepos commits ${REQUEST_REPOS} mutation`, done => {
- testAction(
- requestRepos,
- null,
- localState,
- [{ type: REQUEST_REPOS, payload: null }],
- [],
- done,
- );
- });
- });
-
- describe('receiveReposSuccess', () => {
- it(`commits ${RECEIVE_REPOS_SUCCESS} mutation`, done => {
- testAction(
- receiveReposSuccess,
- repos,
- localState,
- [{ type: RECEIVE_REPOS_SUCCESS, payload: repos }],
- [],
- done,
- );
- });
- });
-
- describe('receiveReposError', () => {
- it(`commits ${RECEIVE_REPOS_ERROR} mutation`, done => {
- testAction(receiveReposError, repos, localState, [{ type: RECEIVE_REPOS_ERROR }], [], done);
- });
- });
-
- describe('fetchRepos', () => {
- let mock;
-
- beforeEach(() => {
- localState.reposPath = `${TEST_HOST}/endpoint.json`;
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => mock.restore());
-
- it('dispatches requestRepos and receiveReposSuccess actions on a successful request', done => {
- const payload = { imported_projects: [{}], provider_repos: [{}], namespaces: [{}] };
- mock.onGet(`${TEST_HOST}/endpoint.json`).reply(200, payload);
-
- testAction(
- fetchRepos,
- null,
- localState,
- [],
- [
- { type: 'requestRepos' },
- {
- type: 'receiveReposSuccess',
- payload: convertObjectPropsToCamelCase(payload, { deep: true }),
- },
- {
- type: 'fetchJobs',
- },
- ],
- done,
- );
- });
-
- it('dispatches requestRepos and receiveReposSuccess actions on an unsuccessful request', done => {
- mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500);
-
- testAction(
- fetchRepos,
- null,
- localState,
- [],
- [{ type: 'requestRepos' }, { type: 'receiveReposError' }],
- done,
- );
- });
- });
-
- describe('requestImport', () => {
- it(`commits ${REQUEST_IMPORT} mutation`, done => {
- testAction(
- requestImport,
- repoId,
- localState,
- [{ type: REQUEST_IMPORT, payload: repoId }],
- [],
- done,
- );
- });
- });
-
- describe('receiveImportSuccess', () => {
- it(`commits ${RECEIVE_IMPORT_SUCCESS} mutation`, done => {
- const payload = { importedProject: { name: 'imported/project' }, repoId: 2 };
-
- testAction(
- receiveImportSuccess,
- payload,
- localState,
- [{ type: RECEIVE_IMPORT_SUCCESS, payload }],
- [],
- done,
- );
- });
- });
-
- describe('receiveImportError', () => {
- it(`commits ${RECEIVE_IMPORT_ERROR} mutation`, done => {
- testAction(
- receiveImportError,
- repoId,
- localState,
- [{ type: RECEIVE_IMPORT_ERROR, payload: repoId }],
- [],
- done,
- );
- });
- });
-
- describe('fetchImport', () => {
- let mock;
-
- beforeEach(() => {
- localState.importPath = `${TEST_HOST}/endpoint.json`;
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => mock.restore());
-
- it('dispatches requestImport and receiveImportSuccess actions on a successful request', done => {
- const importedProject = { name: 'imported/project' };
- const importRepoId = importPayload.repo.id;
- mock.onPost(`${TEST_HOST}/endpoint.json`).reply(200, importedProject);
-
- testAction(
- fetchImport,
- importPayload,
- localState,
- [],
- [
- { type: 'requestImport', payload: importRepoId },
- {
- type: 'receiveImportSuccess',
- payload: {
- importedProject: convertObjectPropsToCamelCase(importedProject, { deep: true }),
- repoId: importRepoId,
- },
- },
- ],
- done,
- );
- });
-
- it('dispatches requestImport and receiveImportSuccess actions on an unsuccessful request', done => {
- mock.onPost(`${TEST_HOST}/endpoint.json`).reply(500);
-
- testAction(
- fetchImport,
- importPayload,
- localState,
- [],
- [
- { type: 'requestImport', payload: importPayload.repo.id },
- { type: 'receiveImportError', payload: { repoId: importPayload.repo.id } },
- ],
- done,
- );
- });
- });
-
- describe('receiveJobsSuccess', () => {
- it(`commits ${RECEIVE_JOBS_SUCCESS} mutation`, done => {
- testAction(
- receiveJobsSuccess,
- repos,
- localState,
- [{ type: RECEIVE_JOBS_SUCCESS, payload: repos }],
- [],
- done,
- );
- });
- });
-
- describe('fetchJobs', () => {
- let mock;
-
- beforeEach(() => {
- localState.jobsPath = `${TEST_HOST}/endpoint.json`;
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- stopJobsPolling();
- clearJobsEtagPoll();
- });
-
- afterEach(() => mock.restore());
-
- it('dispatches requestJobs and receiveJobsSuccess actions on a successful request', done => {
- const updatedProjects = [{ name: 'imported/project' }, { name: 'provider/repo' }];
- mock.onGet(`${TEST_HOST}/endpoint.json`).reply(200, updatedProjects);
-
- testAction(
- fetchJobs,
- null,
- localState,
- [],
- [
- {
- type: 'receiveJobsSuccess',
- payload: convertObjectPropsToCamelCase(updatedProjects, { deep: true }),
- },
- ],
- done,
- );
- });
- });
-});
diff --git a/spec/javascripts/issue_spec.js b/spec/javascripts/issue_spec.js
index 11ab6c38a55..966aee72abb 100644
--- a/spec/javascripts/issue_spec.js
+++ b/spec/javascripts/issue_spec.js
@@ -113,7 +113,6 @@ describe('Issue', function() {
mock = new MockAdapter(axios);
mock.onGet(/(.*)\/related_branches$/).reply(200, {});
- mock.onGet(/(.*)\/referenced_merge_requests$/).reply(200, {});
findElements(isIssueInitiallyOpen);
this.issue = new Issue();
diff --git a/spec/javascripts/jobs/components/artifacts_block_spec.js b/spec/javascripts/jobs/components/artifacts_block_spec.js
index 27d480ef2ea..58998d038e5 100644
--- a/spec/javascripts/jobs/components/artifacts_block_spec.js
+++ b/spec/javascripts/jobs/components/artifacts_block_spec.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import { getTimeago } from '~/lib/utils/datetime_utility';
import component from '~/jobs/components/artifacts_block.vue';
import mountComponent from '../../helpers/vue_mount_component_helper';
-import { trimText } from '../../helpers/vue_component_helper';
+import { trimText } from '../../helpers/text_helper';
describe('Artifacts block', () => {
const Component = Vue.extend(component);
diff --git a/spec/javascripts/jobs/components/job_app_spec.js b/spec/javascripts/jobs/components/job_app_spec.js
index cef40117304..f28d2c2a882 100644
--- a/spec/javascripts/jobs/components/job_app_spec.js
+++ b/spec/javascripts/jobs/components/job_app_spec.js
@@ -90,9 +90,12 @@ describe('Job App ', () => {
describe('triggered job', () => {
beforeEach(() => {
+ const aYearAgo = new Date();
+ aYearAgo.setFullYear(aYearAgo.getFullYear() - 1);
+
mock
.onGet(props.endpoint)
- .replyOnce(200, Object.assign({}, job, { started: '2017-05-24T10:59:52.000+01:00' }));
+ .replyOnce(200, Object.assign({}, job, { started: aYearAgo.toISOString() }));
vm = mountComponentWithStore(Component, { props, store });
});
diff --git a/spec/javascripts/jobs/components/sidebar_spec.js b/spec/javascripts/jobs/components/sidebar_spec.js
index 3a02351460c..740bc3d0491 100644
--- a/spec/javascripts/jobs/components/sidebar_spec.js
+++ b/spec/javascripts/jobs/components/sidebar_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import sidebarDetailsBlock from '~/jobs/components/sidebar.vue';
import createStore from '~/jobs/store';
-import job, { stages, jobsInStage } from '../mock_data';
+import job, { jobsInStage } from '../mock_data';
import { mountComponentWithStore } from '../../helpers/vue_mount_component_helper';
-import { trimText } from '../../helpers/vue_component_helper';
+import { trimText } from '../../helpers/text_helper';
describe('Sidebar details block', () => {
const SidebarComponent = Vue.extend(sidebarDetailsBlock);
@@ -131,18 +131,8 @@ describe('Sidebar details block', () => {
store.dispatch('receiveJobSuccess', job);
});
- describe('while fetching stages', () => {
- it('it does not render dropdown', () => {
- store.dispatch('requestStages');
- vm = mountComponentWithStore(SidebarComponent, { store });
-
- expect(vm.$el.querySelector('.js-selected-stage')).toBeNull();
- });
- });
-
describe('with stages', () => {
beforeEach(() => {
- store.dispatch('receiveStagesSuccess', stages);
vm = mountComponentWithStore(SidebarComponent, { store });
});
@@ -156,7 +146,6 @@ describe('Sidebar details block', () => {
describe('without jobs for stages', () => {
beforeEach(() => {
store.dispatch('receiveJobSuccess', job);
- store.dispatch('receiveStagesSuccess', stages);
vm = mountComponentWithStore(SidebarComponent, { store });
});
@@ -168,7 +157,6 @@ describe('Sidebar details block', () => {
describe('with jobs for stages', () => {
beforeEach(() => {
store.dispatch('receiveJobSuccess', job);
- store.dispatch('receiveStagesSuccess', stages);
store.dispatch('receiveJobsForStageSuccess', jobsInStage.latest_statuses);
vm = mountComponentWithStore(SidebarComponent, { store });
});
diff --git a/spec/javascripts/jobs/components/stages_dropdown_spec.js b/spec/javascripts/jobs/components/stages_dropdown_spec.js
index eccb4e13d67..e98639bf21e 100644
--- a/spec/javascripts/jobs/components/stages_dropdown_spec.js
+++ b/spec/javascripts/jobs/components/stages_dropdown_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
import component from '~/jobs/components/stages_dropdown.vue';
-import { trimText } from 'spec/helpers/vue_component_helper';
+import { trimText } from 'spec/helpers/text_helper';
import mountComponent from '../../helpers/vue_mount_component_helper';
describe('Stages Dropdown', () => {
@@ -9,6 +9,7 @@ describe('Stages Dropdown', () => {
const mockPipelineData = {
id: 28029444,
+ iid: 123,
details: {
status: {
details_path: '/gitlab-org/gitlab-ce/pipelines/28029444',
@@ -77,8 +78,8 @@ describe('Stages Dropdown', () => {
expect(vm.$el.querySelector('.dropdown .js-selected-stage').textContent).toContain('deploy');
});
- it(`renders the pipeline info text like "Pipeline #123 for source_branch"`, () => {
- const expected = `Pipeline #${pipeline.id} for ${pipeline.ref.name}`;
+ it(`renders the pipeline info text like "Pipeline #123 (#12) for source_branch"`, () => {
+ const expected = `Pipeline #${pipeline.id} (#${pipeline.iid}) for ${pipeline.ref.name}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
expect(actual).toBe(expected);
@@ -100,10 +101,10 @@ describe('Stages Dropdown', () => {
});
});
- it(`renders the pipeline info text like "Pipeline #123 for !456 with source_branch into target_branch"`, () => {
- const expected = `Pipeline #${pipeline.id} for !${pipeline.merge_request.iid} with ${
- pipeline.merge_request.source_branch
- } into ${pipeline.merge_request.target_branch}`;
+ it(`renders the pipeline info text like "Pipeline #123 (#12) for !456 with source_branch into target_branch"`, () => {
+ const expected = `Pipeline #${pipeline.id} (#${pipeline.iid}) for !${
+ pipeline.merge_request.iid
+ } with ${pipeline.merge_request.source_branch} into ${pipeline.merge_request.target_branch}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
expect(actual).toBe(expected);
@@ -143,10 +144,10 @@ describe('Stages Dropdown', () => {
});
});
- it(`renders the pipeline info like "Pipeline #123 for !456 with source_branch"`, () => {
- const expected = `Pipeline #${pipeline.id} for !${pipeline.merge_request.iid} with ${
- pipeline.merge_request.source_branch
- }`;
+ it(`renders the pipeline info like "Pipeline #123 (#12) for !456 with source_branch"`, () => {
+ const expected = `Pipeline #${pipeline.id} (#${pipeline.iid}) for !${
+ pipeline.merge_request.iid
+ } with ${pipeline.merge_request.source_branch}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
expect(actual).toBe(expected);
diff --git a/spec/javascripts/jobs/mock_data.js b/spec/javascripts/jobs/mock_data.js
index 1a7f338c5fa..88b0bb206ee 100644
--- a/spec/javascripts/jobs/mock_data.js
+++ b/spec/javascripts/jobs/mock_data.js
@@ -3,140 +3,6 @@ import { TEST_HOST } from 'spec/test_constants';
const threeWeeksAgo = new Date();
threeWeeksAgo.setDate(threeWeeksAgo.getDate() - 21);
-export default {
- id: 4757,
- name: 'test',
- build_path: '/root/ci-mock/-/jobs/4757',
- retry_path: '/root/ci-mock/-/jobs/4757/retry',
- cancel_path: '/root/ci-mock/-/jobs/4757/cancel',
- new_issue_path: '/root/ci-mock/issues/new',
- playable: false,
- created_at: threeWeeksAgo.toISOString(),
- updated_at: threeWeeksAgo.toISOString(),
- finished_at: threeWeeksAgo.toISOString(),
- queued: 9.54,
- status: {
- icon: 'status_success',
- text: 'passed',
- label: 'passed',
- group: 'success',
- has_details: true,
- details_path: `${TEST_HOST}/root/ci-mock/-/jobs/4757`,
- favicon:
- '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png',
- action: {
- icon: 'retry',
- title: 'Retry',
- path: '/root/ci-mock/-/jobs/4757/retry',
- method: 'post',
- },
- },
- coverage: 20,
- erased_at: threeWeeksAgo.toISOString(),
- erased: false,
- duration: 6.785563,
- tags: ['tag'],
- user: {
- name: 'Root',
- username: 'root',
- id: 1,
- state: 'active',
- avatar_url:
- 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
- web_url: 'http://localhost:3000/root',
- },
- erase_path: '/root/ci-mock/-/jobs/4757/erase',
- artifacts: [null],
- runner: {
- id: 1,
- description: 'local ci runner',
- edit_path: '/root/ci-mock/runners/1/edit',
- },
- pipeline: {
- id: 140,
- user: {
- name: 'Root',
- username: 'root',
- id: 1,
- state: 'active',
- avatar_url:
- 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
- web_url: 'http://localhost:3000/root',
- },
- active: false,
- coverage: null,
- source: 'unknown',
- created_at: '2017-05-24T09:59:58.634Z',
- updated_at: '2017-06-01T17:32:00.062Z',
- path: '/root/ci-mock/pipelines/140',
- flags: {
- latest: true,
- stuck: false,
- yaml_errors: false,
- retryable: false,
- cancelable: false,
- },
- details: {
- status: {
- icon: 'status_success',
- text: 'passed',
- label: 'passed',
- group: 'success',
- has_details: true,
- details_path: '/root/ci-mock/pipelines/140',
- favicon:
- '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png',
- },
- duration: 6,
- finished_at: '2017-06-01T17:32:00.042Z',
- },
- ref: {
- name: 'abc',
- path: '/root/ci-mock/commits/abc',
- tag: false,
- branch: true,
- },
- commit: {
- id: 'c58647773a6b5faf066d4ad6ff2c9fbba5f180f6',
- short_id: 'c5864777',
- title: 'Add new file',
- created_at: '2017-05-24T10:59:52.000+01:00',
- parent_ids: ['798e5f902592192afaba73f4668ae30e56eae492'],
- message: 'Add new file',
- author_name: 'Root',
- author_email: 'admin@example.com',
- authored_date: '2017-05-24T10:59:52.000+01:00',
- committer_name: 'Root',
- committer_email: 'admin@example.com',
- committed_date: '2017-05-24T10:59:52.000+01:00',
- author: {
- name: 'Root',
- username: 'root',
- id: 1,
- state: 'active',
- avatar_url:
- 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
- web_url: 'http://localhost:3000/root',
- },
- author_gravatar_url:
- 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
- commit_url:
- 'http://localhost:3000/root/ci-mock/commit/c58647773a6b5faf066d4ad6ff2c9fbba5f180f6',
- commit_path: '/root/ci-mock/commit/c58647773a6b5faf066d4ad6ff2c9fbba5f180f6',
- },
- },
- metadata: {
- timeout_human_readable: '1m 40s',
- timeout_source: 'runner',
- },
- merge_request: {
- iid: 2,
- path: '/root/ci-mock/merge_requests/2',
- },
- raw_path: '/root/ci-mock/builds/4757/raw',
- has_trace: true,
-};
-
export const stages = [
{
name: 'build',
@@ -1043,6 +909,168 @@ export const stages = [
},
];
+export default {
+ id: 4757,
+ name: 'test',
+ build_path: '/root/ci-mock/-/jobs/4757',
+ retry_path: '/root/ci-mock/-/jobs/4757/retry',
+ cancel_path: '/root/ci-mock/-/jobs/4757/cancel',
+ new_issue_path: '/root/ci-mock/issues/new',
+ playable: false,
+ created_at: threeWeeksAgo.toISOString(),
+ updated_at: threeWeeksAgo.toISOString(),
+ finished_at: threeWeeksAgo.toISOString(),
+ queued: 9.54,
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ has_details: true,
+ details_path: `${TEST_HOST}/root/ci-mock/-/jobs/4757`,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/root/ci-mock/-/jobs/4757/retry',
+ method: 'post',
+ },
+ },
+ coverage: 20,
+ erased_at: threeWeeksAgo.toISOString(),
+ erased: false,
+ duration: 6.785563,
+ tags: ['tag'],
+ user: {
+ name: 'Root',
+ username: 'root',
+ id: 1,
+ state: 'active',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
+ web_url: 'http://localhost:3000/root',
+ },
+ erase_path: '/root/ci-mock/-/jobs/4757/erase',
+ artifacts: [null],
+ runner: {
+ id: 1,
+ description: 'local ci runner',
+ edit_path: '/root/ci-mock/runners/1/edit',
+ },
+ pipeline: {
+ id: 140,
+ iid: 13,
+ user: {
+ name: 'Root',
+ username: 'root',
+ id: 1,
+ state: 'active',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
+ web_url: 'http://localhost:3000/root',
+ },
+ active: false,
+ coverage: null,
+ source: 'unknown',
+ created_at: '2017-05-24T09:59:58.634Z',
+ updated_at: '2017-06-01T17:32:00.062Z',
+ path: '/root/ci-mock/pipelines/140',
+ flags: {
+ latest: true,
+ stuck: false,
+ yaml_errors: false,
+ retryable: false,
+ cancelable: false,
+ },
+ details: {
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ has_details: true,
+ details_path: '/root/ci-mock/pipelines/140',
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png',
+ },
+ duration: 6,
+ finished_at: '2017-06-01T17:32:00.042Z',
+ stages: [
+ {
+ dropdown_path: '/jashkenas/underscore/pipelines/16/stage.json?stage=build',
+ name: 'build',
+ path: '/jashkenas/underscore/pipelines/16#build',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ },
+ title: 'build: passed',
+ },
+ {
+ dropdown_path: '/jashkenas/underscore/pipelines/16/stage.json?stage=test',
+ name: 'test',
+ path: '/jashkenas/underscore/pipelines/16#test',
+ status: {
+ icon: 'status_warning',
+ text: 'passed',
+ label: 'passed with warnings',
+ group: 'success-with-warnings',
+ },
+ title: 'test: passed with warnings',
+ },
+ ],
+ },
+ ref: {
+ name: 'abc',
+ path: '/root/ci-mock/commits/abc',
+ tag: false,
+ branch: true,
+ },
+ commit: {
+ id: 'c58647773a6b5faf066d4ad6ff2c9fbba5f180f6',
+ short_id: 'c5864777',
+ title: 'Add new file',
+ created_at: '2017-05-24T10:59:52.000+01:00',
+ parent_ids: ['798e5f902592192afaba73f4668ae30e56eae492'],
+ message: 'Add new file',
+ author_name: 'Root',
+ author_email: 'admin@example.com',
+ authored_date: '2017-05-24T10:59:52.000+01:00',
+ committer_name: 'Root',
+ committer_email: 'admin@example.com',
+ committed_date: '2017-05-24T10:59:52.000+01:00',
+ author: {
+ name: 'Root',
+ username: 'root',
+ id: 1,
+ state: 'active',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
+ web_url: 'http://localhost:3000/root',
+ },
+ author_gravatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
+ commit_url:
+ 'http://localhost:3000/root/ci-mock/commit/c58647773a6b5faf066d4ad6ff2c9fbba5f180f6',
+ commit_path: '/root/ci-mock/commit/c58647773a6b5faf066d4ad6ff2c9fbba5f180f6',
+ },
+ },
+ metadata: {
+ timeout_human_readable: '1m 40s',
+ timeout_source: 'runner',
+ },
+ merge_request: {
+ iid: 2,
+ path: '/root/ci-mock/merge_requests/2',
+ },
+ raw_path: '/root/ci-mock/builds/4757/raw',
+ has_trace: true,
+};
+
export const jobsInStage = {
name: 'build',
title: 'build: running',
diff --git a/spec/javascripts/jobs/store/actions_spec.js b/spec/javascripts/jobs/store/actions_spec.js
index 77b44995b12..7b96df85b82 100644
--- a/spec/javascripts/jobs/store/actions_spec.js
+++ b/spec/javascripts/jobs/store/actions_spec.js
@@ -16,10 +16,6 @@ import {
stopPollingTrace,
receiveTraceSuccess,
receiveTraceError,
- requestStages,
- fetchStages,
- receiveStagesSuccess,
- receiveStagesError,
requestJobsForStage,
fetchJobsForStage,
receiveJobsForStageSuccess,
@@ -307,107 +303,6 @@ describe('Job State actions', () => {
});
});
- describe('requestStages', () => {
- it('should commit REQUEST_STAGES mutation ', done => {
- testAction(requestStages, null, mockedState, [{ type: types.REQUEST_STAGES }], [], done);
- });
- });
-
- describe('fetchStages', () => {
- let mock;
-
- beforeEach(() => {
- mockedState.job.pipeline = {
- path: `${TEST_HOST}/endpoint`,
- };
- mockedState.selectedStage = 'deploy';
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- describe('success', () => {
- it('dispatches requestStages and receiveStagesSuccess, fetchJobsForStage ', done => {
- mock
- .onGet(`${TEST_HOST}/endpoint.json`)
- .replyOnce(200, { details: { stages: [{ name: 'build' }, { name: 'deploy' }] } });
-
- testAction(
- fetchStages,
- null,
- mockedState,
- [],
- [
- {
- type: 'requestStages',
- },
- {
- payload: [{ name: 'build' }, { name: 'deploy' }],
- type: 'receiveStagesSuccess',
- },
- {
- payload: { name: 'deploy' },
- type: 'fetchJobsForStage',
- },
- ],
- done,
- );
- });
- });
-
- describe('error', () => {
- beforeEach(() => {
- mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500);
- });
-
- it('dispatches requestStages and receiveStagesError ', done => {
- testAction(
- fetchStages,
- null,
- mockedState,
- [],
- [
- {
- type: 'requestStages',
- },
- {
- type: 'receiveStagesError',
- },
- ],
- done,
- );
- });
- });
- });
-
- describe('receiveStagesSuccess', () => {
- it('should commit RECEIVE_STAGES_SUCCESS mutation ', done => {
- testAction(
- receiveStagesSuccess,
- {},
- mockedState,
- [{ type: types.RECEIVE_STAGES_SUCCESS, payload: {} }],
- [],
- done,
- );
- });
- });
-
- describe('receiveStagesError', () => {
- it('should commit RECEIVE_STAGES_ERROR mutation ', done => {
- testAction(
- receiveStagesError,
- null,
- mockedState,
- [{ type: types.RECEIVE_STAGES_ERROR }],
- [],
- done,
- );
- });
- });
-
describe('requestJobsForStage', () => {
it('should commit REQUEST_JOBS_FOR_STAGE mutation ', done => {
testAction(
diff --git a/spec/javascripts/lib/utils/common_utils_spec.js b/spec/javascripts/lib/utils/common_utils_spec.js
index 0cd077a6099..296ee85089f 100644
--- a/spec/javascripts/lib/utils/common_utils_spec.js
+++ b/spec/javascripts/lib/utils/common_utils_spec.js
@@ -852,20 +852,20 @@ describe('common_utils', () => {
describe('roundOffFloat', () => {
it('Rounds off decimal places of a float number with provided precision', () => {
- expect(commonUtils.roundOffFloat(3.141592, 3)).toBe(3.142);
+ expect(commonUtils.roundOffFloat(3.141592, 3)).toBeCloseTo(3.142);
});
it('Rounds off a float number to a whole number when provided precision is zero', () => {
- expect(commonUtils.roundOffFloat(3.141592, 0)).toBe(3);
- expect(commonUtils.roundOffFloat(3.5, 0)).toBe(4);
+ expect(commonUtils.roundOffFloat(3.141592, 0)).toBeCloseTo(3);
+ expect(commonUtils.roundOffFloat(3.5, 0)).toBeCloseTo(4);
});
it('Rounds off float number to nearest 0, 10, 100, 1000 and so on when provided precision is below 0', () => {
- expect(commonUtils.roundOffFloat(34567.14159, -1)).toBe(34570);
- expect(commonUtils.roundOffFloat(34567.14159, -2)).toBe(34600);
- expect(commonUtils.roundOffFloat(34567.14159, -3)).toBe(35000);
- expect(commonUtils.roundOffFloat(34567.14159, -4)).toBe(30000);
- expect(commonUtils.roundOffFloat(34567.14159, -5)).toBe(0);
+ expect(commonUtils.roundOffFloat(34567.14159, -1)).toBeCloseTo(34570);
+ expect(commonUtils.roundOffFloat(34567.14159, -2)).toBeCloseTo(34600);
+ expect(commonUtils.roundOffFloat(34567.14159, -3)).toBeCloseTo(35000);
+ expect(commonUtils.roundOffFloat(34567.14159, -4)).toBeCloseTo(30000);
+ expect(commonUtils.roundOffFloat(34567.14159, -5)).toBeCloseTo(0);
});
});
diff --git a/spec/javascripts/lib/utils/datetime_utility_spec.js b/spec/javascripts/lib/utils/datetime_utility_spec.js
deleted file mode 100644
index 5327ec9d2a0..00000000000
--- a/spec/javascripts/lib/utils/datetime_utility_spec.js
+++ /dev/null
@@ -1,416 +0,0 @@
-import * as datetimeUtility from '~/lib/utils/datetime_utility';
-
-describe('Date time utils', () => {
- describe('timeFor', () => {
- it('returns `past due` when in past', () => {
- const date = new Date();
- date.setFullYear(date.getFullYear() - 1);
-
- expect(datetimeUtility.timeFor(date)).toBe('Past due');
- });
-
- it('returns remaining time when in the future', () => {
- const date = new Date();
- date.setFullYear(date.getFullYear() + 1);
-
- // Add a day to prevent a transient error. If date is even 1 second
- // short of a full year, timeFor will return '11 months remaining'
- date.setDate(date.getDate() + 1);
-
- expect(datetimeUtility.timeFor(date)).toBe('1 year remaining');
- });
- });
-
- describe('get day name', () => {
- it('should return Sunday', () => {
- const day = datetimeUtility.getDayName(new Date('07/17/2016'));
-
- expect(day).toBe('Sunday');
- });
-
- it('should return Monday', () => {
- const day = datetimeUtility.getDayName(new Date('07/18/2016'));
-
- expect(day).toBe('Monday');
- });
-
- it('should return Tuesday', () => {
- const day = datetimeUtility.getDayName(new Date('07/19/2016'));
-
- expect(day).toBe('Tuesday');
- });
-
- it('should return Wednesday', () => {
- const day = datetimeUtility.getDayName(new Date('07/20/2016'));
-
- expect(day).toBe('Wednesday');
- });
-
- it('should return Thursday', () => {
- const day = datetimeUtility.getDayName(new Date('07/21/2016'));
-
- expect(day).toBe('Thursday');
- });
-
- it('should return Friday', () => {
- const day = datetimeUtility.getDayName(new Date('07/22/2016'));
-
- expect(day).toBe('Friday');
- });
-
- it('should return Saturday', () => {
- const day = datetimeUtility.getDayName(new Date('07/23/2016'));
-
- expect(day).toBe('Saturday');
- });
- });
-
- describe('get day difference', () => {
- it('should return 7', () => {
- const firstDay = new Date('07/01/2016');
- const secondDay = new Date('07/08/2016');
- const difference = datetimeUtility.getDayDifference(firstDay, secondDay);
-
- expect(difference).toBe(7);
- });
-
- it('should return 31', () => {
- const firstDay = new Date('07/01/2016');
- const secondDay = new Date('08/01/2016');
- const difference = datetimeUtility.getDayDifference(firstDay, secondDay);
-
- expect(difference).toBe(31);
- });
-
- it('should return 365', () => {
- const firstDay = new Date('07/02/2015');
- const secondDay = new Date('07/01/2016');
- const difference = datetimeUtility.getDayDifference(firstDay, secondDay);
-
- expect(difference).toBe(365);
- });
- });
-});
-
-describe('timeIntervalInWords', () => {
- it('should return string with number of minutes and seconds', () => {
- expect(datetimeUtility.timeIntervalInWords(9.54)).toEqual('9 seconds');
- expect(datetimeUtility.timeIntervalInWords(1)).toEqual('1 second');
- expect(datetimeUtility.timeIntervalInWords(200)).toEqual('3 minutes 20 seconds');
- expect(datetimeUtility.timeIntervalInWords(6008)).toEqual('100 minutes 8 seconds');
- });
-});
-
-describe('dateInWords', () => {
- const date = new Date('07/01/2016');
-
- it('should return date in words', () => {
- expect(datetimeUtility.dateInWords(date)).toEqual('July 1, 2016');
- });
-
- it('should return abbreviated month name', () => {
- expect(datetimeUtility.dateInWords(date, true)).toEqual('Jul 1, 2016');
- });
-
- it('should return date in words without year', () => {
- expect(datetimeUtility.dateInWords(date, true, true)).toEqual('Jul 1');
- });
-});
-
-describe('monthInWords', () => {
- const date = new Date('2017-01-20');
-
- it('returns month name from provided date', () => {
- expect(datetimeUtility.monthInWords(date)).toBe('January');
- });
-
- it('returns abbreviated month name from provided date', () => {
- expect(datetimeUtility.monthInWords(date, true)).toBe('Jan');
- });
-});
-
-describe('totalDaysInMonth', () => {
- it('returns number of days in a month for given date', () => {
- // 1st Feb, 2016 (leap year)
- expect(datetimeUtility.totalDaysInMonth(new Date(2016, 1, 1))).toBe(29);
-
- // 1st Feb, 2017
- expect(datetimeUtility.totalDaysInMonth(new Date(2017, 1, 1))).toBe(28);
-
- // 1st Jan, 2017
- expect(datetimeUtility.totalDaysInMonth(new Date(2017, 0, 1))).toBe(31);
- });
-});
-
-describe('getSundays', () => {
- it('returns array of dates representing all Sundays of the month', () => {
- // December, 2017 (it has 5 Sundays)
- const dateOfSundays = [3, 10, 17, 24, 31];
- const sundays = datetimeUtility.getSundays(new Date(2017, 11, 1));
-
- expect(sundays.length).toBe(5);
- sundays.forEach((sunday, index) => {
- expect(sunday.getDate()).toBe(dateOfSundays[index]);
- });
- });
-});
-
-describe('getTimeframeWindowFrom', () => {
- it('returns array of date objects upto provided length (positive number) into the future starting from provided startDate', () => {
- const startDate = new Date(2018, 0, 1);
- const mockTimeframe = [
- new Date(2018, 0, 1),
- new Date(2018, 1, 1),
- new Date(2018, 2, 1),
- new Date(2018, 3, 1),
- new Date(2018, 4, 31),
- ];
- const timeframe = datetimeUtility.getTimeframeWindowFrom(startDate, 5);
-
- expect(timeframe.length).toBe(5);
- timeframe.forEach((timeframeItem, index) => {
- expect(timeframeItem.getFullYear()).toBe(mockTimeframe[index].getFullYear());
- expect(timeframeItem.getMonth()).toBe(mockTimeframe[index].getMonth());
- expect(timeframeItem.getDate()).toBe(mockTimeframe[index].getDate());
- });
- });
-
- it('returns array of date objects upto provided length (negative number) into the past starting from provided startDate', () => {
- const startDate = new Date(2018, 0, 1);
- const mockTimeframe = [
- new Date(2018, 0, 1),
- new Date(2017, 11, 1),
- new Date(2017, 10, 1),
- new Date(2017, 9, 1),
- new Date(2017, 8, 1),
- ];
- const timeframe = datetimeUtility.getTimeframeWindowFrom(startDate, -5);
-
- expect(timeframe.length).toBe(5);
- timeframe.forEach((timeframeItem, index) => {
- expect(timeframeItem.getFullYear()).toBe(mockTimeframe[index].getFullYear());
- expect(timeframeItem.getMonth()).toBe(mockTimeframe[index].getMonth());
- expect(timeframeItem.getDate()).toBe(mockTimeframe[index].getDate());
- });
- });
-});
-
-describe('formatTime', () => {
- const expectedTimestamps = [
- [0, '00:00:00'],
- [1000, '00:00:01'],
- [42000, '00:00:42'],
- [121000, '00:02:01'],
- [10921000, '03:02:01'],
- [108000000, '30:00:00'],
- ];
-
- expectedTimestamps.forEach(([milliseconds, expectedTimestamp]) => {
- it(`formats ${milliseconds}ms as ${expectedTimestamp}`, () => {
- expect(datetimeUtility.formatTime(milliseconds)).toBe(expectedTimestamp);
- });
- });
-});
-
-describe('datefix', () => {
- describe('pad', () => {
- it('should add a 0 when length is smaller than 2', () => {
- expect(datetimeUtility.pad(2)).toEqual('02');
- });
-
- it('should not add a zero when length matches the default', () => {
- expect(datetimeUtility.pad(12)).toEqual('12');
- });
-
- it('should add a 0 when length is smaller than the provided', () => {
- expect(datetimeUtility.pad(12, 3)).toEqual('012');
- });
- });
-
- describe('parsePikadayDate', () => {
- // removed because of https://gitlab.com/gitlab-org/gitlab-ce/issues/39834
- });
-
- describe('pikadayToString', () => {
- it('should format a UTC date into yyyy-mm-dd format', () => {
- expect(datetimeUtility.pikadayToString(new Date('2020-01-29:00:00'))).toEqual('2020-01-29');
- });
- });
-});
-
-describe('prettyTime methods', () => {
- const assertTimeUnits = (obj, minutes, hours, days, weeks) => {
- expect(obj.minutes).toBe(minutes);
- expect(obj.hours).toBe(hours);
- expect(obj.days).toBe(days);
- expect(obj.weeks).toBe(weeks);
- };
-
- describe('parseSeconds', () => {
- it('should correctly parse a negative value', () => {
- const zeroSeconds = datetimeUtility.parseSeconds(-1000);
-
- assertTimeUnits(zeroSeconds, 16, 0, 0, 0);
- });
-
- it('should correctly parse a zero value', () => {
- const zeroSeconds = datetimeUtility.parseSeconds(0);
-
- assertTimeUnits(zeroSeconds, 0, 0, 0, 0);
- });
-
- it('should correctly parse a small non-zero second values', () => {
- const subOneMinute = datetimeUtility.parseSeconds(10);
- const aboveOneMinute = datetimeUtility.parseSeconds(100);
- const manyMinutes = datetimeUtility.parseSeconds(1000);
-
- assertTimeUnits(subOneMinute, 0, 0, 0, 0);
- assertTimeUnits(aboveOneMinute, 1, 0, 0, 0);
- assertTimeUnits(manyMinutes, 16, 0, 0, 0);
- });
-
- it('should correctly parse large second values', () => {
- const aboveOneHour = datetimeUtility.parseSeconds(4800);
- const aboveOneDay = datetimeUtility.parseSeconds(110000);
- const aboveOneWeek = datetimeUtility.parseSeconds(25000000);
-
- assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
- assertTimeUnits(aboveOneDay, 33, 6, 3, 0);
- assertTimeUnits(aboveOneWeek, 26, 0, 3, 173);
- });
-
- it('should correctly accept a custom param for hoursPerDay', () => {
- const config = { hoursPerDay: 24 };
-
- const aboveOneHour = datetimeUtility.parseSeconds(4800, config);
- const aboveOneDay = datetimeUtility.parseSeconds(110000, config);
- const aboveOneWeek = datetimeUtility.parseSeconds(25000000, config);
-
- assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
- assertTimeUnits(aboveOneDay, 33, 6, 1, 0);
- assertTimeUnits(aboveOneWeek, 26, 8, 4, 57);
- });
-
- it('should correctly accept a custom param for daysPerWeek', () => {
- const config = { daysPerWeek: 7 };
-
- const aboveOneHour = datetimeUtility.parseSeconds(4800, config);
- const aboveOneDay = datetimeUtility.parseSeconds(110000, config);
- const aboveOneWeek = datetimeUtility.parseSeconds(25000000, config);
-
- assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
- assertTimeUnits(aboveOneDay, 33, 6, 3, 0);
- assertTimeUnits(aboveOneWeek, 26, 0, 0, 124);
- });
-
- it('should correctly accept custom params for daysPerWeek and hoursPerDay', () => {
- const config = { daysPerWeek: 55, hoursPerDay: 14 };
-
- const aboveOneHour = datetimeUtility.parseSeconds(4800, config);
- const aboveOneDay = datetimeUtility.parseSeconds(110000, config);
- const aboveOneWeek = datetimeUtility.parseSeconds(25000000, config);
-
- assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
- assertTimeUnits(aboveOneDay, 33, 2, 2, 0);
- assertTimeUnits(aboveOneWeek, 26, 0, 1, 9);
- });
- });
-
- describe('stringifyTime', () => {
- it('should stringify values with all non-zero units', () => {
- const timeObject = {
- weeks: 1,
- days: 4,
- hours: 7,
- minutes: 20,
- };
-
- const timeString = datetimeUtility.stringifyTime(timeObject);
-
- expect(timeString).toBe('1w 4d 7h 20m');
- });
-
- it('should stringify values with some non-zero units', () => {
- const timeObject = {
- weeks: 0,
- days: 4,
- hours: 0,
- minutes: 20,
- };
-
- const timeString = datetimeUtility.stringifyTime(timeObject);
-
- expect(timeString).toBe('4d 20m');
- });
-
- it('should stringify values with no non-zero units', () => {
- const timeObject = {
- weeks: 0,
- days: 0,
- hours: 0,
- minutes: 0,
- };
-
- const timeString = datetimeUtility.stringifyTime(timeObject);
-
- expect(timeString).toBe('0m');
- });
-
- it('should return non-condensed representation of time object', () => {
- const timeObject = { weeks: 1, days: 0, hours: 1, minutes: 0 };
-
- expect(datetimeUtility.stringifyTime(timeObject, true)).toEqual('1 week 1 hour');
- });
- });
-
- describe('abbreviateTime', () => {
- it('should abbreviate stringified times for weeks', () => {
- const fullTimeString = '1w 3d 4h 5m';
-
- expect(datetimeUtility.abbreviateTime(fullTimeString)).toBe('1w');
- });
-
- it('should abbreviate stringified times for non-weeks', () => {
- const fullTimeString = '0w 3d 4h 5m';
-
- expect(datetimeUtility.abbreviateTime(fullTimeString)).toBe('3d');
- });
- });
-});
-
-describe('calculateRemainingMilliseconds', () => {
- beforeEach(() => {
- spyOn(Date, 'now').and.callFake(() => new Date('2063-04-04T00:42:00Z').getTime());
- });
-
- it('calculates the remaining time for a given end date', () => {
- const milliseconds = datetimeUtility.calculateRemainingMilliseconds('2063-04-04T01:44:03Z');
-
- expect(milliseconds).toBe(3723000);
- });
-
- it('returns 0 if the end date has passed', () => {
- const milliseconds = datetimeUtility.calculateRemainingMilliseconds('2063-04-03T00:00:00Z');
-
- expect(milliseconds).toBe(0);
- });
-});
-
-describe('newDate', () => {
- it('returns new date instance from existing date instance', () => {
- const initialDate = new Date(2019, 0, 1);
- const copiedDate = datetimeUtility.newDate(initialDate);
-
- expect(copiedDate.getTime()).toBe(initialDate.getTime());
-
- initialDate.setMonth(initialDate.getMonth() + 1);
-
- expect(copiedDate.getTime()).not.toBe(initialDate.getTime());
- });
-
- it('returns date instance when provided date param is not of type date or is undefined', () => {
- const initialDate = datetimeUtility.newDate();
-
- expect(initialDate instanceof Date).toBe(true);
- });
-});
diff --git a/spec/javascripts/lib/utils/url_utility_spec.js b/spec/javascripts/lib/utils/url_utility_spec.js
deleted file mode 100644
index 381c7b2d0a6..00000000000
--- a/spec/javascripts/lib/utils/url_utility_spec.js
+++ /dev/null
@@ -1,110 +0,0 @@
-import * as urlUtils from '~/lib/utils/url_utility';
-
-describe('URL utility', () => {
- describe('webIDEUrl', () => {
- afterEach(() => {
- gon.relative_url_root = '';
- });
-
- describe('without relative_url_root', () => {
- it('returns IDE path with route', () => {
- expect(urlUtils.webIDEUrl('/gitlab-org/gitlab-ce/merge_requests/1')).toBe(
- '/-/ide/project/gitlab-org/gitlab-ce/merge_requests/1',
- );
- });
- });
-
- describe('with relative_url_root', () => {
- beforeEach(() => {
- gon.relative_url_root = '/gitlab';
- });
-
- it('returns IDE path with route', () => {
- expect(urlUtils.webIDEUrl('/gitlab/gitlab-org/gitlab-ce/merge_requests/1')).toBe(
- '/gitlab/-/ide/project/gitlab-org/gitlab-ce/merge_requests/1',
- );
- });
- });
- });
-
- describe('mergeUrlParams', () => {
- it('adds w', () => {
- expect(urlUtils.mergeUrlParams({ w: 1 }, '#frag')).toBe('?w=1#frag');
- expect(urlUtils.mergeUrlParams({ w: 1 }, '/path#frag')).toBe('/path?w=1#frag');
- expect(urlUtils.mergeUrlParams({ w: 1 }, 'https://host/path')).toBe('https://host/path?w=1');
- expect(urlUtils.mergeUrlParams({ w: 1 }, 'https://host/path#frag')).toBe(
- 'https://host/path?w=1#frag',
- );
-
- expect(urlUtils.mergeUrlParams({ w: 1 }, 'https://h/p?k1=v1#frag')).toBe(
- 'https://h/p?k1=v1&w=1#frag',
- );
- });
-
- it('updates w', () => {
- expect(urlUtils.mergeUrlParams({ w: 1 }, '?k1=v1&w=0#frag')).toBe('?k1=v1&w=1#frag');
- });
-
- it('adds multiple params', () => {
- expect(urlUtils.mergeUrlParams({ a: 1, b: 2, c: 3 }, '#frag')).toBe('?a=1&b=2&c=3#frag');
- });
-
- it('adds and updates encoded params', () => {
- expect(urlUtils.mergeUrlParams({ a: '&', q: '?' }, '?a=%23#frag')).toBe('?a=%26&q=%3F#frag');
- });
- });
-
- describe('removeParams', () => {
- describe('when url is passed', () => {
- it('removes query param with encoded ampersand', () => {
- const url = urlUtils.removeParams(['filter'], '/mail?filter=n%3Djoe%26l%3Dhome');
-
- expect(url).toBe('/mail');
- });
-
- it('should remove param when url has no other params', () => {
- const url = urlUtils.removeParams(['size'], '/feature/home?size=5');
-
- expect(url).toBe('/feature/home');
- });
-
- it('should remove param when url has other params', () => {
- const url = urlUtils.removeParams(['size'], '/feature/home?q=1&size=5&f=html');
-
- expect(url).toBe('/feature/home?q=1&f=html');
- });
-
- it('should remove param and preserve fragment', () => {
- const url = urlUtils.removeParams(['size'], '/feature/home?size=5#H2');
-
- expect(url).toBe('/feature/home#H2');
- });
-
- it('should remove multiple params', () => {
- const url = urlUtils.removeParams(['z', 'a'], '/home?z=11111&l=en_US&a=true#H2');
-
- expect(url).toBe('/home?l=en_US#H2');
- });
- });
- });
-
- describe('setUrlFragment', () => {
- it('should set fragment when url has no fragment', () => {
- const url = urlUtils.setUrlFragment('/home/feature', 'usage');
-
- expect(url).toBe('/home/feature#usage');
- });
-
- it('should set fragment when url has existing fragment', () => {
- const url = urlUtils.setUrlFragment('/home/feature#overview', 'usage');
-
- expect(url).toBe('/home/feature#usage');
- });
-
- it('should set fragment when given fragment includes #', () => {
- const url = urlUtils.setUrlFragment('/home/feature#overview', '#install');
-
- expect(url).toBe('/home/feature#install');
- });
- });
-});
diff --git a/spec/javascripts/matchers.js b/spec/javascripts/matchers.js
index 406527b08a3..7d1921cabcf 100644
--- a/spec/javascripts/matchers.js
+++ b/spec/javascripts/matchers.js
@@ -28,7 +28,7 @@ export default {
reference.getAttribute('xlink:href').endsWith(`#${iconName}`),
);
const result = {
- pass: !!matchingIcon,
+ pass: Boolean(matchingIcon),
};
if (result.pass) {
diff --git a/spec/javascripts/merge_request_spec.js b/spec/javascripts/merge_request_spec.js
index 431798c6ec3..cadcc15385f 100644
--- a/spec/javascripts/merge_request_spec.js
+++ b/spec/javascripts/merge_request_spec.js
@@ -58,7 +58,7 @@ describe('MergeRequest', function() {
{
merge_request: {
description: '- [ ] Task List Item',
- lock_version: undefined,
+ lock_version: 0,
update_task: { line_number: lineNumber, line_source: lineSource, index, checked },
},
},
diff --git a/spec/javascripts/monitoring/charts/area_spec.js b/spec/javascripts/monitoring/charts/area_spec.js
index 41a6c04efb9..ac7e0bb12a1 100644
--- a/spec/javascripts/monitoring/charts/area_spec.js
+++ b/spec/javascripts/monitoring/charts/area_spec.js
@@ -2,7 +2,8 @@ import { shallowMount } from '@vue/test-utils';
import { GlAreaChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts';
import { shallowWrapperContainsSlotText } from 'spec/helpers/vue_test_utils_helper';
import Area from '~/monitoring/components/charts/area.vue';
-import MonitoringStore from '~/monitoring/stores/monitoring_store';
+import { createStore } from '~/monitoring/stores';
+import * as types from '~/monitoring/stores/mutation_types';
import MonitoringMock, { deploymentData } from '../mock_data';
describe('Area component', () => {
@@ -13,17 +14,18 @@ describe('Area component', () => {
let spriteSpy;
beforeEach(() => {
- const store = new MonitoringStore();
- store.storeMetrics(MonitoringMock.data);
- store.storeDeploymentData(deploymentData);
+ const store = createStore();
- [mockGraphData] = store.groups[0].metrics;
+ store.commit(`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`, MonitoringMock.data);
+ store.commit(`monitoringDashboard/${types.RECEIVE_DEPLOYMENTS_DATA_SUCCESS}`, deploymentData);
+
+ [mockGraphData] = store.state.monitoringDashboard.groups[0].metrics;
areaChart = shallowMount(Area, {
propsData: {
graphData: mockGraphData,
containerWidth: 0,
- deploymentData: store.deploymentData,
+ deploymentData: store.state.monitoringDashboard.deploymentData,
},
slots: {
default: mockWidgets,
@@ -212,6 +214,20 @@ describe('Area component', () => {
});
});
+ describe('chartOptions', () => {
+ describe('yAxis formatter', () => {
+ let format;
+
+ beforeEach(() => {
+ format = areaChart.vm.chartOptions.yAxis.axisLabel.formatter;
+ });
+
+ it('rounds to 3 decimal places', () => {
+ expect(format(0.88888)).toBe('0.889');
+ });
+ });
+ });
+
describe('scatterSeries', () => {
it('utilizes deployment data', () => {
expect(areaChart.vm.scatterSeries.data).toEqual([
diff --git a/spec/javascripts/monitoring/charts/single_stat_spec.js b/spec/javascripts/monitoring/charts/single_stat_spec.js
new file mode 100644
index 00000000000..12b73002f97
--- /dev/null
+++ b/spec/javascripts/monitoring/charts/single_stat_spec.js
@@ -0,0 +1,28 @@
+import { shallowMount } from '@vue/test-utils';
+import SingleStatChart from '~/monitoring/components/charts/single_stat.vue';
+
+describe('Single Stat Chart component', () => {
+ let singleStatChart;
+
+ beforeEach(() => {
+ singleStatChart = shallowMount(SingleStatChart, {
+ propsData: {
+ title: 'Time to render',
+ value: 1,
+ unit: 'sec',
+ },
+ });
+ });
+
+ afterEach(() => {
+ singleStatChart.destroy();
+ });
+
+ describe('computed', () => {
+ describe('valueWithUnit', () => {
+ it('should interpolate the value and unit props', () => {
+ expect(singleStatChart.vm.valueWithUnit).toBe('1sec');
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/monitoring/dashboard_spec.js b/spec/javascripts/monitoring/dashboard_spec.js
index ce2c6c43c0f..f4166987aed 100644
--- a/spec/javascripts/monitoring/dashboard_spec.js
+++ b/spec/javascripts/monitoring/dashboard_spec.js
@@ -1,9 +1,16 @@
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
import Dashboard from '~/monitoring/components/dashboard.vue';
-import { timeWindows } from '~/monitoring/constants';
+import { timeWindows, timeWindowsKeyNames } from '~/monitoring/constants';
+import * as types from '~/monitoring/stores/mutation_types';
+import { createStore } from '~/monitoring/stores';
import axios from '~/lib/utils/axios_utils';
-import { metricsGroupsAPIResponse, mockApiEndpoint, environmentData } from './mock_data';
+import {
+ metricsGroupsAPIResponse,
+ mockApiEndpoint,
+ environmentData,
+ singleGroupResponse,
+} from './mock_data';
const propsData = {
hasMetrics: false,
@@ -13,13 +20,16 @@ const propsData = {
tagsPath: '/path/to/tags',
projectPath: '/path/to/project',
metricsEndpoint: mockApiEndpoint,
- deploymentEndpoint: null,
+ deploymentsEndpoint: null,
emptyGettingStartedSvgPath: '/path/to/getting-started.svg',
emptyLoadingSvgPath: '/path/to/loading.svg',
emptyNoDataSvgPath: '/path/to/no-data.svg',
emptyUnableToConnectSvgPath: '/path/to/unable-to-connect.svg',
environmentsEndpoint: '/root/hello-prometheus/environments/35',
currentEnvironmentName: 'production',
+ customMetricsAvailable: false,
+ customMetricsPath: '',
+ validateQueryPath: '',
};
export default propsData;
@@ -27,6 +37,8 @@ export default propsData;
describe('Dashboard', () => {
let DashboardComponent;
let mock;
+ let store;
+ let component;
beforeEach(() => {
setFixtures(`
@@ -39,23 +51,26 @@ describe('Dashboard', () => {
ee: false,
};
+ store = createStore();
mock = new MockAdapter(axios);
DashboardComponent = Vue.extend(Dashboard);
});
afterEach(() => {
+ component.$destroy();
mock.restore();
});
describe('no metrics are available yet', () => {
it('shows a getting started empty state when no metrics are present', () => {
- const component = new DashboardComponent({
+ component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
- propsData: { ...propsData, showTimeWindowDropdown: false },
+ propsData: { ...propsData },
+ store,
});
expect(component.$el.querySelector('.prometheus-graphs')).toBe(null);
- expect(component.state).toEqual('gettingStarted');
+ expect(component.emptyState).toEqual('gettingStarted');
});
});
@@ -65,26 +80,27 @@ describe('Dashboard', () => {
});
it('shows up a loading state', done => {
- const component = new DashboardComponent({
+ component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
- propsData: { ...propsData, hasMetrics: true, showTimeWindowDropdown: false },
+ propsData: { ...propsData, hasMetrics: true },
+ store,
});
Vue.nextTick(() => {
- expect(component.state).toEqual('loading');
+ expect(component.emptyState).toEqual('loading');
done();
});
});
it('hides the legend when showLegend is false', done => {
- const component = new DashboardComponent({
+ component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
...propsData,
hasMetrics: true,
showLegend: false,
- showTimeWindowDropdown: false,
},
+ store,
});
setTimeout(() => {
@@ -96,14 +112,14 @@ describe('Dashboard', () => {
});
it('hides the group panels when showPanels is false', done => {
- const component = new DashboardComponent({
+ component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
...propsData,
hasMetrics: true,
showPanels: false,
- showTimeWindowDropdown: false,
},
+ store,
});
setTimeout(() => {
@@ -115,85 +131,106 @@ describe('Dashboard', () => {
});
it('renders the environments dropdown with a number of environments', done => {
- const component = new DashboardComponent({
+ component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
...propsData,
hasMetrics: true,
showPanels: false,
- showTimeWindowDropdown: false,
},
+ store,
});
- component.store.storeEnvironmentsData(environmentData);
+ component.$store.commit(
+ `monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
+ environmentData,
+ );
+ component.$store.commit(
+ `monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
+ singleGroupResponse,
+ );
setTimeout(() => {
const dropdownMenuEnvironments = component.$el.querySelectorAll(
'.js-environments-dropdown .dropdown-item',
);
- expect(dropdownMenuEnvironments.length).toEqual(component.store.environmentsData.length);
+ expect(dropdownMenuEnvironments.length).toEqual(component.environments.length);
done();
});
});
it('hides the environments dropdown list when there is no environments', done => {
- const component = new DashboardComponent({
+ component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
...propsData,
hasMetrics: true,
showPanels: false,
- showTimeWindowDropdown: false,
},
+ store,
});
- component.store.storeEnvironmentsData([]);
+ component.$store.commit(`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`, []);
+ component.$store.commit(
+ `monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
+ singleGroupResponse,
+ );
- setTimeout(() => {
- const dropdownMenuEnvironments = component.$el.querySelectorAll(
- '.js-environments-dropdown .dropdown-item',
- );
+ Vue.nextTick()
+ .then(() => {
+ const dropdownMenuEnvironments = component.$el.querySelectorAll(
+ '.js-environments-dropdown .dropdown-item',
+ );
- expect(dropdownMenuEnvironments.length).toEqual(0);
- done();
- });
+ expect(dropdownMenuEnvironments.length).toEqual(0);
+ done();
+ })
+ .catch(done.fail);
});
- it('renders the environments dropdown with a single is-active element', done => {
- const component = new DashboardComponent({
+ it('renders the environments dropdown with a single active element', done => {
+ component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
...propsData,
hasMetrics: true,
showPanels: false,
- showTimeWindowDropdown: false,
},
+ store,
});
- component.store.storeEnvironmentsData(environmentData);
+ component.$store.commit(
+ `monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
+ environmentData,
+ );
+ component.$store.commit(
+ `monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
+ singleGroupResponse,
+ );
- setTimeout(() => {
- const dropdownItems = component.$el.querySelectorAll(
- '.js-environments-dropdown .dropdown-item[active="true"]',
- );
+ Vue.nextTick()
+ .then(() => {
+ const dropdownItems = component.$el.querySelectorAll(
+ '.js-environments-dropdown .dropdown-item[active="true"]',
+ );
- expect(dropdownItems.length).toEqual(1);
- expect(dropdownItems[0].textContent.trim()).toEqual(component.currentEnvironmentName);
- done();
- });
+ expect(dropdownItems.length).toEqual(1);
+ done();
+ })
+ .catch(done.fail);
});
it('hides the dropdown', done => {
- const component = new DashboardComponent({
+ component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
...propsData,
hasMetrics: true,
showPanels: false,
environmentsEndpoint: '',
- showTimeWindowDropdown: false,
},
+ store,
});
Vue.nextTick(() => {
@@ -204,46 +241,96 @@ describe('Dashboard', () => {
});
});
- it('does not show the time window dropdown when the feature flag is not set', done => {
- const component = new DashboardComponent({
+ it('renders the time window dropdown with a set of options', done => {
+ component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
...propsData,
hasMetrics: true,
showPanels: false,
- showTimeWindowDropdown: false,
},
+ store,
});
+ const numberOfTimeWindows = Object.keys(timeWindows).length;
setTimeout(() => {
const timeWindowDropdown = component.$el.querySelector('.js-time-window-dropdown');
+ const timeWindowDropdownEls = component.$el.querySelectorAll(
+ '.js-time-window-dropdown .dropdown-item',
+ );
- expect(timeWindowDropdown).toBeNull();
+ expect(timeWindowDropdown).not.toBeNull();
+ expect(timeWindowDropdownEls.length).toEqual(numberOfTimeWindows);
done();
});
});
- it('renders the time window dropdown with a set of options', done => {
- const component = new DashboardComponent({
+ it('fetches the metrics data with proper time window', done => {
+ component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
...propsData,
hasMetrics: true,
showPanels: false,
- showTimeWindowDropdown: true,
},
+ store,
+ });
+
+ spyOn(component.$store, 'dispatch').and.stub();
+ const getTimeDiffSpy = spyOnDependency(Dashboard, 'getTimeDiff');
+
+ component.$store.commit(
+ `monitoringDashboard/${types.SET_ENVIRONMENTS_ENDPOINT}`,
+ '/environments',
+ );
+ component.$store.commit(
+ `monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
+ environmentData,
+ );
+
+ component.$mount();
+
+ Vue.nextTick()
+ .then(() => {
+ expect(component.$store.dispatch).toHaveBeenCalled();
+ expect(getTimeDiffSpy).toHaveBeenCalledWith(component.selectedTimeWindow);
+
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('shows a specific time window selected from the url params', done => {
+ spyOnDependency(Dashboard, 'getParameterValues').and.returnValue(['thirtyMinutes']);
+
+ component = new DashboardComponent({
+ el: document.querySelector('.prometheus-graphs'),
+ propsData: { ...propsData, hasMetrics: true },
+ store,
});
- const numberOfTimeWindows = Object.keys(timeWindows).length;
setTimeout(() => {
- const timeWindowDropdown = component.$el.querySelector('.js-time-window-dropdown');
- const timeWindowDropdownEls = component.$el.querySelectorAll(
- '.js-time-window-dropdown .dropdown-item',
- );
+ const selectedTimeWindow = component.$el.querySelector('.js-time-window-dropdown .active');
- expect(timeWindowDropdown).not.toBeNull();
- expect(timeWindowDropdownEls.length).toEqual(numberOfTimeWindows);
+ expect(selectedTimeWindow.textContent.trim()).toEqual('30 minutes');
+ done();
+ });
+ });
+
+ it('defaults to the eight hours time window for non valid url parameters', done => {
+ spyOnDependency(Dashboard, 'getParameterValues').and.returnValue([
+ '<script>alert("XSS")</script>',
+ ]);
+
+ component = new DashboardComponent({
+ el: document.querySelector('.prometheus-graphs'),
+ propsData: { ...propsData, hasMetrics: true },
+ store,
+ });
+
+ Vue.nextTick(() => {
+ expect(component.selectedTimeWindowKey).toEqual(timeWindowsKeyNames.eightHours);
done();
});
@@ -261,14 +348,14 @@ describe('Dashboard', () => {
});
it('sets elWidth to page width when the sidebar is resized', done => {
- const component = new DashboardComponent({
+ component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
...propsData,
hasMetrics: true,
showPanels: false,
- showTimeWindowDropdown: false,
},
+ store,
});
expect(component.elWidth).toEqual(0);
@@ -288,4 +375,31 @@ describe('Dashboard', () => {
.catch(done.fail);
});
});
+
+ describe('external dashboard link', () => {
+ beforeEach(() => {
+ mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
+
+ component = new DashboardComponent({
+ el: document.querySelector('.prometheus-graphs'),
+ propsData: {
+ ...propsData,
+ hasMetrics: true,
+ showPanels: false,
+ showTimeWindowDropdown: false,
+ externalDashboardUrl: '/mockUrl',
+ },
+ store,
+ });
+ });
+
+ it('shows the link', done => {
+ setTimeout(() => {
+ expect(component.$el.querySelector('.js-external-dashboard-link').innerText).toContain(
+ 'View full dashboard',
+ );
+ done();
+ });
+ });
+ });
});
diff --git a/spec/javascripts/monitoring/helpers.js b/spec/javascripts/monitoring/helpers.js
new file mode 100644
index 00000000000..672e3b948c4
--- /dev/null
+++ b/spec/javascripts/monitoring/helpers.js
@@ -0,0 +1,8 @@
+// eslint-disable-next-line import/prefer-default-export
+export const resetStore = store => {
+ store.replaceState({
+ showEmptyState: true,
+ emptyState: 'loading',
+ groups: [],
+ });
+};
diff --git a/spec/javascripts/monitoring/mock_data.js b/spec/javascripts/monitoring/mock_data.js
index 6d4ef960c1a..82e42fe9ade 100644
--- a/spec/javascripts/monitoring/mock_data.js
+++ b/spec/javascripts/monitoring/mock_data.js
@@ -685,6 +685,47 @@ export const metricsGroupsAPIResponse = {
last_update: '2017-05-25T13:18:34.949Z',
};
+export const singleGroupResponse = [
+ {
+ group: 'System metrics (Kubernetes)',
+ priority: 5,
+ metrics: [
+ {
+ title: 'Memory Usage (Total)',
+ weight: 0,
+ y_label: 'Total Memory Used',
+ queries: [
+ {
+ query_range:
+ 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^production-(.*)",namespace="autodevops-deploy-33"}) by (job)) without (job) /1024/1024/1024',
+ unit: 'GB',
+ label: 'Total',
+ result: [
+ {
+ metric: {},
+ values: [
+ [1558453960.079, '0.0357666015625'],
+ [1558454020.079, '0.035675048828125'],
+ [1558454080.079, '0.035152435302734375'],
+ [1558454140.079, '0.035221099853515625'],
+ [1558454200.079, '0.0352325439453125'],
+ [1558454260.079, '0.03479766845703125'],
+ [1558454320.079, '0.034793853759765625'],
+ [1558454380.079, '0.034931182861328125'],
+ [1558454440.079, '0.034816741943359375'],
+ [1558454500.079, '0.034816741943359375'],
+ [1558454560.079, '0.034816741943359375'],
+ ],
+ },
+ ],
+ },
+ ],
+ id: 15,
+ },
+ ],
+ },
+];
+
export default metricsGroupsAPIResponse;
export const deploymentData = [
@@ -738,5836 +779,6 @@ export const statePaths = {
documentationPath: '/help/administration/monitoring/prometheus/index.md',
};
-export const singleRowMetricsMultipleSeries = [
- {
- title: 'Multiple Time Series',
- weight: 1,
- y_label: 'Request Rates',
- queries: [
- {
- query_range:
- 'sum(rate(nginx_responses_total{environment="production"}[2m])) by (status_code)',
- label: 'Requests',
- unit: 'Req/sec',
- result: [
- {
- metric: {
- status_code: '1xx',
- },
- values: [
- {
- time: '2017-08-27T11:01:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:02:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:03:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:04:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:05:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:06:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:07:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:08:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:09:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:10:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:11:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:12:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:13:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:14:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:15:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:16:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:17:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:18:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:19:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:20:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:21:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:22:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:23:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:24:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:25:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:26:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:27:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:28:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:29:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:30:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:31:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:32:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:33:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:34:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:35:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:36:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:37:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:38:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:39:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:40:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:41:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:42:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:43:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:44:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:45:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:46:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:47:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:48:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:49:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:50:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:51:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:52:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:53:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:54:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:55:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:56:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:57:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:58:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T11:59:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:00:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:01:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:02:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:03:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:04:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:05:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:06:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:07:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:08:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:09:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:10:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:11:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:12:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:13:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:14:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:15:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:16:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:17:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:18:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:19:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:20:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:21:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:22:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:23:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:24:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:25:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:26:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:27:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:28:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:29:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:30:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:31:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:32:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:33:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:34:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:35:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:36:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:37:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:38:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:39:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:40:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:41:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:42:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:43:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:44:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:45:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:46:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:47:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:48:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:49:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:50:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:51:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:52:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:53:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:54:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:55:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:56:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:57:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:58:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T12:59:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:00:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:01:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:02:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:03:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:04:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:05:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:06:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:07:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:08:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:09:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:10:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:11:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:12:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:13:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:14:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:15:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:16:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:17:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:18:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:19:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:20:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:21:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:22:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:23:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:24:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:25:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:26:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:27:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:28:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:29:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:30:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:31:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:32:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:33:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:34:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:35:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:36:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:37:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:38:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:39:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:40:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:41:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:42:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:43:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:44:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:45:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:46:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:47:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:48:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:49:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:50:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:51:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:52:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:53:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:54:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:55:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:56:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:57:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:58:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T13:59:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:00:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:01:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:02:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:03:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:04:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:05:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:06:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:07:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:08:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:09:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:10:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:11:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:12:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:13:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:14:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:15:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:16:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:17:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:18:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:19:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:20:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:21:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:22:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:23:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:24:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:25:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:26:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:27:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:28:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:29:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:30:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:31:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:32:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:33:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:34:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:35:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:36:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:37:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:38:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:39:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:40:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:41:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:42:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:43:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:44:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:45:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:46:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:47:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:48:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:49:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:50:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:51:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:52:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:53:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:54:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:55:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:56:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:57:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:58:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T14:59:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:00:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:01:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:02:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:03:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:04:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:05:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:06:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:07:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:08:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:09:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:10:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:11:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:12:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:13:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:14:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:15:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:16:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:17:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:18:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:19:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:20:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:21:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:22:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:23:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:24:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:25:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:26:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:27:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:28:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:29:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:30:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:31:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:32:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:33:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:34:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:35:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:36:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:37:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:38:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:39:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:40:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:41:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:42:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:43:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:44:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:45:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:46:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:47:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:48:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:49:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:50:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:51:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:52:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:53:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:54:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:55:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:56:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:57:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:58:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T15:59:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:00:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:01:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:02:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:03:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:04:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:05:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:06:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:07:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:08:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:09:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:10:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:11:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:12:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:13:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:14:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:15:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:16:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:17:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:18:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:19:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:20:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:21:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:22:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:23:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:24:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:25:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:26:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:27:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:28:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:29:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:30:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:31:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:32:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:33:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:34:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:35:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:36:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:37:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:38:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:39:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:40:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:41:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:42:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:43:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:44:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:45:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:46:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:47:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:48:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:49:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:50:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:51:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:52:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:53:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:54:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:55:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:56:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:57:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:58:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T16:59:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:00:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:01:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:02:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:03:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:04:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:05:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:06:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:07:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:08:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:09:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:10:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:11:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:12:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:13:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:14:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:15:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:16:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:17:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:18:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:19:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:20:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:21:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:22:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:23:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:24:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:25:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:26:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:27:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:28:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:29:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:30:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:31:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:32:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:33:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:34:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:35:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:36:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:37:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:38:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:39:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:40:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:41:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:42:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:43:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:44:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:45:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:46:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:47:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:48:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:49:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:50:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:51:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:52:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:53:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:54:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:55:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:56:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:57:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:58:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T17:59:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:00:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:01:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:02:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:03:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:04:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:05:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:06:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:07:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:08:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:09:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:10:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:11:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:12:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:13:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:14:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:15:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:16:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:17:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:18:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:19:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:20:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:21:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:22:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:23:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:24:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:25:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:26:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:27:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:28:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:29:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:30:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:31:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:32:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:33:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:34:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:35:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:36:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:37:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:38:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:39:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:40:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:41:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:42:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:43:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:44:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:45:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:46:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:47:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:48:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:49:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:50:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:51:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:52:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:53:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:54:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:55:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:56:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:57:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:58:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T18:59:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T19:00:51.462Z',
- value: '0',
- },
- {
- time: '2017-08-27T19:01:51.462Z',
- value: '0',
- },
- ],
- },
- {
- metric: {
- status_code: '2xx',
- },
- values: [
- {
- time: '2017-08-27T11:01:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:02:51.462Z',
- value: '1.2571428571428571',
- },
- {
- time: '2017-08-27T11:03:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T11:04:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:05:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T11:06:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:07:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T11:08:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:09:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T11:10:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T11:11:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:12:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T11:13:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:14:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T11:15:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:16:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T11:17:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:18:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T11:19:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T11:20:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T11:21:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T11:22:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:23:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:24:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:25:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T11:26:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T11:27:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T11:28:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:29:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T11:30:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:31:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T11:32:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T11:33:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:34:51.462Z',
- value: '1.333320635041571',
- },
- {
- time: '2017-08-27T11:35:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:36:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:37:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:38:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:39:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T11:40:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:41:51.462Z',
- value: '1.3333587306424883',
- },
- {
- time: '2017-08-27T11:42:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:43:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T11:44:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:45:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T11:46:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T11:47:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T11:48:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T11:49:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T11:50:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T11:51:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T11:52:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:53:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T11:54:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:55:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T11:56:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:57:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T11:58:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T11:59:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:00:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:01:51.462Z',
- value: '1.3333460318669703',
- },
- {
- time: '2017-08-27T12:02:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:03:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T12:04:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:05:51.462Z',
- value: '1.31427319739812',
- },
- {
- time: '2017-08-27T12:06:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:07:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:08:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T12:09:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:10:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:11:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:12:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T12:13:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:14:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T12:15:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:16:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:17:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:18:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:19:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:20:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:21:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T12:22:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:23:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:24:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:25:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T12:26:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:27:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T12:28:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:29:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T12:30:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:31:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T12:32:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:33:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:34:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:35:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:36:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T12:37:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:38:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T12:39:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:40:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T12:41:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:42:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:43:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:44:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:45:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T12:46:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:47:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:48:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:49:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T12:50:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:51:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T12:52:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:53:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:54:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T12:55:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T12:56:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:57:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T12:58:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T12:59:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T13:00:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T13:01:51.462Z',
- value: '1.295225759754669',
- },
- {
- time: '2017-08-27T13:02:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T13:03:51.462Z',
- value: '1.2952627669098458',
- },
- {
- time: '2017-08-27T13:04:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:05:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:06:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T13:07:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:08:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T13:09:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:10:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T13:11:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:12:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T13:13:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:14:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:15:51.462Z',
- value: '1.2571428571428571',
- },
- {
- time: '2017-08-27T13:16:51.462Z',
- value: '1.3333587306424883',
- },
- {
- time: '2017-08-27T13:17:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:18:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T13:19:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:20:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T13:21:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:22:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T13:23:51.462Z',
- value: '1.276190476190476',
- },
- {
- time: '2017-08-27T13:24:51.462Z',
- value: '1.2571428571428571',
- },
- {
- time: '2017-08-27T13:25:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T13:26:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T13:27:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T13:28:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:29:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:30:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:31:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:32:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T13:33:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:34:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T13:35:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T13:36:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:37:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T13:38:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:39:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T13:40:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:41:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T13:42:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:43:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T13:44:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:45:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T13:46:51.462Z',
- value: '1.2571428571428571',
- },
- {
- time: '2017-08-27T13:47:51.462Z',
- value: '1.276190476190476',
- },
- {
- time: '2017-08-27T13:48:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T13:49:51.462Z',
- value: '1.295225759754669',
- },
- {
- time: '2017-08-27T13:50:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T13:51:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:52:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T13:53:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:54:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T13:55:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:56:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T13:57:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T13:58:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T13:59:51.462Z',
- value: '1.295225759754669',
- },
- {
- time: '2017-08-27T14:00:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T14:01:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T14:02:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:03:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T14:04:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:05:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T14:06:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:07:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T14:08:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:09:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T14:10:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T14:11:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:12:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T14:13:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:14:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T14:15:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:16:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:17:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T14:18:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:19:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T14:20:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:21:51.462Z',
- value: '1.3333079369916765',
- },
- {
- time: '2017-08-27T14:22:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:23:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T14:24:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:25:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T14:26:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:27:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T14:28:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:29:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:30:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T14:31:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:32:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:33:51.462Z',
- value: '1.2571428571428571',
- },
- {
- time: '2017-08-27T14:34:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T14:35:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:36:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T14:37:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T14:38:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T14:39:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T14:40:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:41:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T14:42:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:43:51.462Z',
- value: '1.276190476190476',
- },
- {
- time: '2017-08-27T14:44:51.462Z',
- value: '1.2571428571428571',
- },
- {
- time: '2017-08-27T14:45:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T14:46:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:47:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T14:48:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:49:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T14:50:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:51:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T14:52:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:53:51.462Z',
- value: '1.333320635041571',
- },
- {
- time: '2017-08-27T14:54:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:55:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T14:56:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:57:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T14:58:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T14:59:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T15:00:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:01:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:02:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:03:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:04:51.462Z',
- value: '1.2571428571428571',
- },
- {
- time: '2017-08-27T15:05:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:06:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:07:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:08:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:09:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:10:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:11:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:12:51.462Z',
- value: '1.31427319739812',
- },
- {
- time: '2017-08-27T15:13:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:14:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:15:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:16:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T15:17:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:18:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:19:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:20:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T15:21:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:22:51.462Z',
- value: '1.3333460318669703',
- },
- {
- time: '2017-08-27T15:23:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:24:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:25:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:26:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:27:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:28:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:29:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:30:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:31:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T15:32:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:33:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T15:34:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:35:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T15:36:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:37:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:38:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T15:39:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:40:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:41:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:42:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:43:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:44:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:45:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:46:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:47:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:48:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:49:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T15:50:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:51:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:52:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:53:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:54:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:55:51.462Z',
- value: '1.3333587306424883',
- },
- {
- time: '2017-08-27T15:56:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T15:57:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:58:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T15:59:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:00:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T16:01:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T16:02:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:03:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:04:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:05:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T16:06:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:07:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T16:08:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T16:09:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T16:10:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T16:11:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:12:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T16:13:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:14:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T16:15:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T16:16:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T16:17:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T16:18:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:19:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T16:20:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:21:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T16:22:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:23:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T16:24:51.462Z',
- value: '1.295225759754669',
- },
- {
- time: '2017-08-27T16:25:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T16:26:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T16:27:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T16:28:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T16:29:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:30:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T16:31:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:32:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T16:33:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:34:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T16:35:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:36:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T16:37:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:38:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T16:39:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:40:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T16:41:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:42:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T16:43:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:44:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T16:45:51.462Z',
- value: '1.3142982314117277',
- },
- {
- time: '2017-08-27T16:46:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T16:47:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:48:51.462Z',
- value: '1.333320635041571',
- },
- {
- time: '2017-08-27T16:49:51.462Z',
- value: '1.31427319739812',
- },
- {
- time: '2017-08-27T16:50:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:51:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T16:52:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:53:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T16:54:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:55:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T16:56:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:57:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T16:58:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T16:59:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:00:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:01:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:02:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:03:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:04:51.462Z',
- value: '1.2952504309564854',
- },
- {
- time: '2017-08-27T17:05:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T17:06:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:07:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T17:08:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T17:09:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:10:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:11:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:12:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:13:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:14:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:15:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:16:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:17:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:18:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:19:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:20:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:21:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:22:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:23:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:24:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T17:25:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:26:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:27:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:28:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:29:51.462Z',
- value: '1.295225759754669',
- },
- {
- time: '2017-08-27T17:30:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:31:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:32:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:33:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:34:51.462Z',
- value: '1.295225759754669',
- },
- {
- time: '2017-08-27T17:35:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:36:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T17:37:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:38:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:39:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:40:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:41:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:42:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:43:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:44:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T17:45:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:46:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:47:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:48:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T17:49:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:50:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T17:51:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:52:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:53:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:54:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:55:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T17:56:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:57:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T17:58:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T17:59:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T18:00:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:01:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:02:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:03:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:04:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:05:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:06:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:07:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:08:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:09:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:10:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:11:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:12:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T18:13:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:14:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:15:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:16:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:17:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:18:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:19:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:20:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:21:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:22:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:23:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:24:51.462Z',
- value: '1.2571428571428571',
- },
- {
- time: '2017-08-27T18:25:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:26:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:27:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:28:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:29:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:30:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:31:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:32:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:33:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:34:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:35:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:36:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:37:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T18:38:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:39:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:40:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:41:51.462Z',
- value: '1.580952380952381',
- },
- {
- time: '2017-08-27T18:42:51.462Z',
- value: '1.7333333333333334',
- },
- {
- time: '2017-08-27T18:43:51.462Z',
- value: '2.057142857142857',
- },
- {
- time: '2017-08-27T18:44:51.462Z',
- value: '2.1904761904761902',
- },
- {
- time: '2017-08-27T18:45:51.462Z',
- value: '1.8285714285714287',
- },
- {
- time: '2017-08-27T18:46:51.462Z',
- value: '2.1142857142857143',
- },
- {
- time: '2017-08-27T18:47:51.462Z',
- value: '1.619047619047619',
- },
- {
- time: '2017-08-27T18:48:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:49:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:50:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T18:51:51.462Z',
- value: '1.2952504309564854',
- },
- {
- time: '2017-08-27T18:52:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:53:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:54:51.462Z',
- value: '1.3333333333333333',
- },
- {
- time: '2017-08-27T18:55:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:56:51.462Z',
- value: '1.314285714285714',
- },
- {
- time: '2017-08-27T18:57:51.462Z',
- value: '1.295238095238095',
- },
- {
- time: '2017-08-27T18:58:51.462Z',
- value: '1.7142857142857142',
- },
- {
- time: '2017-08-27T18:59:51.462Z',
- value: '1.7333333333333334',
- },
- {
- time: '2017-08-27T19:00:51.462Z',
- value: '1.3904761904761904',
- },
- {
- time: '2017-08-27T19:01:51.462Z',
- value: '1.5047619047619047',
- },
- ],
- },
- ],
- when: [
- {
- value: 'hundred(s)',
- color: 'green',
- },
- ],
- },
- ],
- },
- {
- title: 'Throughput',
- weight: 1,
- y_label: 'Requests / Sec',
- queries: [
- {
- query_range:
- "sum(rate(nginx_requests_total{server_zone!='*', server_zone!='_', container_name!='POD',environment='production'}[2m]))",
- label: 'Total',
- unit: 'req / sec',
- result: [
- {
- metric: {},
- values: [
- {
- time: '2017-08-27T11:01:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:02:51.462Z',
- value: '0.45714285714285713',
- },
- {
- time: '2017-08-27T11:03:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T11:04:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:05:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T11:06:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:07:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T11:08:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:09:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T11:10:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T11:11:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:12:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T11:13:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:14:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T11:15:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:16:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T11:17:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:18:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T11:19:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T11:20:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T11:21:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T11:22:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:23:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:24:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:25:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T11:26:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T11:27:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T11:28:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:29:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T11:30:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:31:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T11:32:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T11:33:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:34:51.462Z',
- value: '0.4952333787297264',
- },
- {
- time: '2017-08-27T11:35:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:36:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:37:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:38:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:39:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T11:40:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:41:51.462Z',
- value: '0.49524752852435283',
- },
- {
- time: '2017-08-27T11:42:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:43:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T11:44:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:45:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T11:46:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T11:47:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T11:48:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T11:49:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T11:50:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T11:51:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T11:52:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:53:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T11:54:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:55:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T11:56:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:57:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T11:58:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T11:59:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:00:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:01:51.462Z',
- value: '0.49524281183630325',
- },
- {
- time: '2017-08-27T12:02:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:03:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T12:04:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:05:51.462Z',
- value: '0.4857096599080009',
- },
- {
- time: '2017-08-27T12:06:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:07:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:08:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T12:09:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:10:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:11:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:12:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T12:13:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:14:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T12:15:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:16:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:17:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:18:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:19:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:20:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:21:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T12:22:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:23:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:24:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:25:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T12:26:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:27:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T12:28:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:29:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T12:30:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:31:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T12:32:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:33:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:34:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:35:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:36:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T12:37:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:38:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T12:39:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:40:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T12:41:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:42:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:43:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:44:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:45:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T12:46:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:47:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:48:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:49:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T12:50:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:51:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T12:52:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:53:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:54:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T12:55:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T12:56:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:57:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T12:58:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T12:59:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T13:00:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T13:01:51.462Z',
- value: '0.4761859410862754',
- },
- {
- time: '2017-08-27T13:02:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T13:03:51.462Z',
- value: '0.4761995466580315',
- },
- {
- time: '2017-08-27T13:04:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:05:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:06:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T13:07:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:08:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T13:09:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:10:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T13:11:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:12:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T13:13:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:14:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:15:51.462Z',
- value: '0.45714285714285713',
- },
- {
- time: '2017-08-27T13:16:51.462Z',
- value: '0.49524752852435283',
- },
- {
- time: '2017-08-27T13:17:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:18:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T13:19:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:20:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T13:21:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:22:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T13:23:51.462Z',
- value: '0.4666666666666667',
- },
- {
- time: '2017-08-27T13:24:51.462Z',
- value: '0.45714285714285713',
- },
- {
- time: '2017-08-27T13:25:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T13:26:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T13:27:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T13:28:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:29:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:30:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:31:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:32:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T13:33:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:34:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T13:35:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T13:36:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:37:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T13:38:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:39:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T13:40:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:41:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T13:42:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:43:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T13:44:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:45:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T13:46:51.462Z',
- value: '0.45714285714285713',
- },
- {
- time: '2017-08-27T13:47:51.462Z',
- value: '0.4666666666666667',
- },
- {
- time: '2017-08-27T13:48:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T13:49:51.462Z',
- value: '0.4761859410862754',
- },
- {
- time: '2017-08-27T13:50:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T13:51:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:52:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T13:53:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:54:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T13:55:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:56:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T13:57:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T13:58:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T13:59:51.462Z',
- value: '0.4761859410862754',
- },
- {
- time: '2017-08-27T14:00:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T14:01:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T14:02:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:03:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T14:04:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:05:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T14:06:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:07:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T14:08:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:09:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T14:10:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T14:11:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:12:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T14:13:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:14:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T14:15:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:16:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:17:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T14:18:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:19:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T14:20:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:21:51.462Z',
- value: '0.4952286623111941',
- },
- {
- time: '2017-08-27T14:22:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:23:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T14:24:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:25:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T14:26:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:27:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T14:28:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:29:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:30:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T14:31:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:32:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:33:51.462Z',
- value: '0.45714285714285713',
- },
- {
- time: '2017-08-27T14:34:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T14:35:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:36:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T14:37:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T14:38:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T14:39:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T14:40:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:41:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T14:42:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:43:51.462Z',
- value: '0.4666666666666667',
- },
- {
- time: '2017-08-27T14:44:51.462Z',
- value: '0.45714285714285713',
- },
- {
- time: '2017-08-27T14:45:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T14:46:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:47:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T14:48:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:49:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T14:50:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:51:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T14:52:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:53:51.462Z',
- value: '0.4952333787297264',
- },
- {
- time: '2017-08-27T14:54:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:55:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T14:56:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:57:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T14:58:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T14:59:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T15:00:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:01:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:02:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:03:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:04:51.462Z',
- value: '0.45714285714285713',
- },
- {
- time: '2017-08-27T15:05:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:06:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:07:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:08:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:09:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:10:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:11:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:12:51.462Z',
- value: '0.4857096599080009',
- },
- {
- time: '2017-08-27T15:13:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:14:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:15:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:16:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T15:17:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:18:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:19:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:20:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T15:21:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:22:51.462Z',
- value: '0.49524281183630325',
- },
- {
- time: '2017-08-27T15:23:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:24:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:25:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:26:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:27:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:28:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:29:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:30:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:31:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T15:32:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:33:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T15:34:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:35:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T15:36:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:37:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:38:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T15:39:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:40:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:41:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:42:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:43:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:44:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:45:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:46:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:47:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:48:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:49:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T15:50:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:51:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:52:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:53:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:54:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:55:51.462Z',
- value: '0.49524752852435283',
- },
- {
- time: '2017-08-27T15:56:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T15:57:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:58:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T15:59:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:00:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T16:01:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T16:02:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:03:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:04:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:05:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T16:06:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:07:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T16:08:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T16:09:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T16:10:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T16:11:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:12:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T16:13:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:14:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T16:15:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T16:16:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T16:17:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T16:18:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:19:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T16:20:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:21:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T16:22:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:23:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T16:24:51.462Z',
- value: '0.4761859410862754',
- },
- {
- time: '2017-08-27T16:25:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T16:26:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T16:27:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T16:28:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T16:29:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:30:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T16:31:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:32:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T16:33:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:34:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T16:35:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:36:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T16:37:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:38:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T16:39:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:40:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T16:41:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:42:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T16:43:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:44:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T16:45:51.462Z',
- value: '0.485718911608682',
- },
- {
- time: '2017-08-27T16:46:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T16:47:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:48:51.462Z',
- value: '0.4952333787297264',
- },
- {
- time: '2017-08-27T16:49:51.462Z',
- value: '0.4857096599080009',
- },
- {
- time: '2017-08-27T16:50:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:51:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T16:52:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:53:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T16:54:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:55:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T16:56:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:57:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T16:58:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T16:59:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:00:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:01:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:02:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:03:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:04:51.462Z',
- value: '0.47619501138106085',
- },
- {
- time: '2017-08-27T17:05:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T17:06:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:07:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T17:08:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T17:09:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:10:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:11:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:12:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:13:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:14:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:15:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:16:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:17:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:18:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:19:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:20:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:21:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:22:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:23:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:24:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T17:25:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:26:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:27:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:28:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:29:51.462Z',
- value: '0.4761859410862754',
- },
- {
- time: '2017-08-27T17:30:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:31:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:32:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:33:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:34:51.462Z',
- value: '0.4761859410862754',
- },
- {
- time: '2017-08-27T17:35:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:36:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T17:37:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:38:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:39:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:40:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:41:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:42:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:43:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:44:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T17:45:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:46:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:47:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:48:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T17:49:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:50:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T17:51:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:52:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:53:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:54:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:55:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T17:56:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:57:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T17:58:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T17:59:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T18:00:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:01:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:02:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:03:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:04:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:05:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:06:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:07:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:08:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:09:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:10:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:11:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:12:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T18:13:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:14:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:15:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:16:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:17:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:18:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:19:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:20:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:21:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:22:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:23:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:24:51.462Z',
- value: '0.45714285714285713',
- },
- {
- time: '2017-08-27T18:25:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:26:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:27:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:28:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:29:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:30:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:31:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:32:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:33:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:34:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:35:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:36:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:37:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T18:38:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:39:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:40:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:41:51.462Z',
- value: '0.6190476190476191',
- },
- {
- time: '2017-08-27T18:42:51.462Z',
- value: '0.6952380952380952',
- },
- {
- time: '2017-08-27T18:43:51.462Z',
- value: '0.857142857142857',
- },
- {
- time: '2017-08-27T18:44:51.462Z',
- value: '0.9238095238095239',
- },
- {
- time: '2017-08-27T18:45:51.462Z',
- value: '0.7428571428571429',
- },
- {
- time: '2017-08-27T18:46:51.462Z',
- value: '0.8857142857142857',
- },
- {
- time: '2017-08-27T18:47:51.462Z',
- value: '0.638095238095238',
- },
- {
- time: '2017-08-27T18:48:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:49:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:50:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T18:51:51.462Z',
- value: '0.47619501138106085',
- },
- {
- time: '2017-08-27T18:52:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:53:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:54:51.462Z',
- value: '0.4952380952380952',
- },
- {
- time: '2017-08-27T18:55:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:56:51.462Z',
- value: '0.4857142857142857',
- },
- {
- time: '2017-08-27T18:57:51.462Z',
- value: '0.47619047619047616',
- },
- {
- time: '2017-08-27T18:58:51.462Z',
- value: '0.6857142857142856',
- },
- {
- time: '2017-08-27T18:59:51.462Z',
- value: '0.6952380952380952',
- },
- {
- time: '2017-08-27T19:00:51.462Z',
- value: '0.5238095238095237',
- },
- {
- time: '2017-08-27T19:01:51.462Z',
- value: '0.5904761904761905',
- },
- ],
- },
- ],
- },
- ],
- },
-];
-
export const queryWithoutData = {
title: 'HTTP Error rate',
weight: 10,
@@ -6646,3 +857,68 @@ export const environmentData = [
updated_at: '2018-07-04T18:44:54.010Z',
},
];
+
+export const metricsDashboardResponse = {
+ dashboard: {
+ dashboard: 'Environment metrics',
+ priority: 1,
+ panel_groups: [
+ {
+ group: 'System metrics (Kubernetes)',
+ priority: 5,
+ panels: [
+ {
+ title: 'Memory Usage (Total)',
+ type: 'area-chart',
+ y_label: 'Total Memory Used',
+ weight: 4,
+ metrics: [
+ {
+ id: 'system_metrics_kubernetes_container_memory_total',
+ query_range:
+ 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) /1024/1024/1024',
+ label: 'Total',
+ unit: 'GB',
+ metric_id: 12,
+ prometheus_endpoint_path: 'http://test',
+ },
+ ],
+ },
+ {
+ title: 'Core Usage (Total)',
+ type: 'area-chart',
+ y_label: 'Total Cores',
+ weight: 3,
+ metrics: [
+ {
+ id: 'system_metrics_kubernetes_container_cores_total',
+ query_range:
+ 'avg(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}[15m])) by (job)) without (job)',
+ label: 'Total',
+ unit: 'cores',
+ metric_id: 13,
+ },
+ ],
+ },
+ {
+ title: 'Memory Usage (Pod average)',
+ type: 'area-chart',
+ y_label: 'Memory Used per Pod',
+ weight: 2,
+ metrics: [
+ {
+ id: 'system_metrics_kubernetes_container_memory_average',
+ query_range:
+ 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024',
+ label: 'Pod average',
+ unit: 'MB',
+ metric_id: 14,
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ status: 'success',
+};
diff --git a/spec/javascripts/monitoring/monitoring_store_spec.js b/spec/javascripts/monitoring/monitoring_store_spec.js
deleted file mode 100644
index d8a980c874d..00000000000
--- a/spec/javascripts/monitoring/monitoring_store_spec.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import MonitoringStore from '~/monitoring/stores/monitoring_store';
-import MonitoringMock, { deploymentData, environmentData } from './mock_data';
-
-describe('MonitoringStore', () => {
- const store = new MonitoringStore();
- store.storeMetrics(MonitoringMock.data);
-
- it('contains two groups that contains, one of which has two queries sorted by priority', () => {
- expect(store.groups).toBeDefined();
- expect(store.groups.length).toEqual(2);
- expect(store.groups[0].metrics.length).toEqual(2);
- });
-
- it('gets the metrics count for every group', () => {
- expect(store.getMetricsCount()).toEqual(3);
- });
-
- it('contains deployment data', () => {
- store.storeDeploymentData(deploymentData);
-
- expect(store.deploymentData).toBeDefined();
- expect(store.deploymentData.length).toEqual(3);
- expect(typeof store.deploymentData[0]).toEqual('object');
- });
-
- it('only stores environment data that contains deployments', () => {
- store.storeEnvironmentsData(environmentData);
-
- expect(store.environmentsData.length).toEqual(2);
- });
-
- it('removes the data if all the values from a query are not defined', () => {
- expect(store.groups[1].metrics[0].queries[0].result.length).toEqual(0);
- });
-});
diff --git a/spec/javascripts/monitoring/store/actions_spec.js b/spec/javascripts/monitoring/store/actions_spec.js
new file mode 100644
index 00000000000..083a01c4d74
--- /dev/null
+++ b/spec/javascripts/monitoring/store/actions_spec.js
@@ -0,0 +1,322 @@
+import axios from '~/lib/utils/axios_utils';
+import MockAdapter from 'axios-mock-adapter';
+import store from '~/monitoring/stores';
+import * as types from '~/monitoring/stores/mutation_types';
+import {
+ fetchDashboard,
+ receiveMetricsDashboardSuccess,
+ receiveMetricsDashboardFailure,
+ fetchDeploymentsData,
+ fetchEnvironmentsData,
+ fetchPrometheusMetrics,
+ fetchPrometheusMetric,
+ requestMetricsData,
+ setEndpoints,
+ setGettingStartedEmptyState,
+} from '~/monitoring/stores/actions';
+import storeState from '~/monitoring/stores/state';
+import testAction from 'spec/helpers/vuex_action_helper';
+import { resetStore } from '../helpers';
+import {
+ deploymentData,
+ environmentData,
+ metricsDashboardResponse,
+ metricsGroupsAPIResponse,
+} from '../mock_data';
+
+describe('Monitoring store actions', () => {
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ resetStore(store);
+ mock.restore();
+ });
+
+ describe('requestMetricsData', () => {
+ it('sets emptyState to loading', () => {
+ const commit = jasmine.createSpy();
+ const { state } = store;
+
+ requestMetricsData({ state, commit });
+
+ expect(commit).toHaveBeenCalledWith(types.REQUEST_METRICS_DATA);
+ });
+ });
+
+ describe('fetchDeploymentsData', () => {
+ it('commits RECEIVE_DEPLOYMENTS_DATA_SUCCESS on error', done => {
+ const dispatch = jasmine.createSpy();
+ const { state } = store;
+ state.deploymentsEndpoint = '/success';
+
+ mock.onGet(state.deploymentsEndpoint).reply(200, {
+ deployments: deploymentData,
+ });
+
+ fetchDeploymentsData({ state, dispatch })
+ .then(() => {
+ expect(dispatch).toHaveBeenCalledWith('receiveDeploymentsDataSuccess', deploymentData);
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('commits RECEIVE_DEPLOYMENTS_DATA_FAILURE on error', done => {
+ const dispatch = jasmine.createSpy();
+ const { state } = store;
+ state.deploymentsEndpoint = '/error';
+
+ mock.onGet(state.deploymentsEndpoint).reply(500);
+
+ fetchDeploymentsData({ state, dispatch })
+ .then(() => {
+ expect(dispatch).toHaveBeenCalledWith('receiveDeploymentsDataFailure');
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
+
+ describe('fetchEnvironmentsData', () => {
+ it('commits RECEIVE_ENVIRONMENTS_DATA_SUCCESS on error', done => {
+ const dispatch = jasmine.createSpy();
+ const { state } = store;
+ state.environmentsEndpoint = '/success';
+
+ mock.onGet(state.environmentsEndpoint).reply(200, {
+ environments: environmentData,
+ });
+
+ fetchEnvironmentsData({ state, dispatch })
+ .then(() => {
+ expect(dispatch).toHaveBeenCalledWith('receiveEnvironmentsDataSuccess', environmentData);
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('commits RECEIVE_ENVIRONMENTS_DATA_FAILURE on error', done => {
+ const dispatch = jasmine.createSpy();
+ const { state } = store;
+ state.environmentsEndpoint = '/error';
+
+ mock.onGet(state.environmentsEndpoint).reply(500);
+
+ fetchEnvironmentsData({ state, dispatch })
+ .then(() => {
+ expect(dispatch).toHaveBeenCalledWith('receiveEnvironmentsDataFailure');
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
+
+ describe('Set endpoints', () => {
+ let mockedState;
+
+ beforeEach(() => {
+ mockedState = storeState();
+ });
+
+ it('should commit SET_ENDPOINTS mutation', done => {
+ testAction(
+ setEndpoints,
+ {
+ metricsEndpoint: 'additional_metrics.json',
+ deploymentsEndpoint: 'deployments.json',
+ environmentsEndpoint: 'deployments.json',
+ },
+ mockedState,
+ [
+ {
+ type: types.SET_ENDPOINTS,
+ payload: {
+ metricsEndpoint: 'additional_metrics.json',
+ deploymentsEndpoint: 'deployments.json',
+ environmentsEndpoint: 'deployments.json',
+ },
+ },
+ ],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('Set empty states', () => {
+ let mockedState;
+
+ beforeEach(() => {
+ mockedState = storeState();
+ });
+
+ it('should commit SET_METRICS_ENDPOINT mutation', done => {
+ testAction(
+ setGettingStartedEmptyState,
+ null,
+ mockedState,
+ [{ type: types.SET_GETTING_STARTED_EMPTY_STATE }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('fetchDashboard', () => {
+ let dispatch;
+ let state;
+ const response = metricsDashboardResponse;
+
+ beforeEach(() => {
+ dispatch = jasmine.createSpy();
+ state = storeState();
+ state.dashboardEndpoint = '/dashboard';
+ });
+
+ it('dispatches receive and success actions', done => {
+ const params = {};
+ mock.onGet(state.dashboardEndpoint).reply(200, response);
+
+ fetchDashboard({ state, dispatch }, params)
+ .then(() => {
+ expect(dispatch).toHaveBeenCalledWith('requestMetricsDashboard');
+ expect(dispatch).toHaveBeenCalledWith('receiveMetricsDashboardSuccess', {
+ response,
+ params,
+ });
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('dispatches failure action', done => {
+ const params = {};
+ mock.onGet(state.dashboardEndpoint).reply(500);
+
+ fetchDashboard({ state, dispatch }, params)
+ .then(() => {
+ expect(dispatch).toHaveBeenCalledWith(
+ 'receiveMetricsDashboardFailure',
+ new Error('Request failed with status code 500'),
+ );
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
+
+ describe('receiveMetricsDashboardSuccess', () => {
+ let commit;
+ let dispatch;
+
+ beforeEach(() => {
+ commit = jasmine.createSpy();
+ dispatch = jasmine.createSpy();
+ });
+
+ it('stores groups ', () => {
+ const params = {};
+ const response = metricsDashboardResponse;
+
+ receiveMetricsDashboardSuccess({ commit, dispatch }, { response, params });
+
+ expect(commit).toHaveBeenCalledWith(
+ types.RECEIVE_METRICS_DATA_SUCCESS,
+ metricsDashboardResponse.dashboard.panel_groups,
+ );
+
+ expect(dispatch).toHaveBeenCalledWith('fetchPrometheusMetrics', params);
+ });
+ });
+
+ describe('receiveMetricsDashboardFailure', () => {
+ let commit;
+
+ beforeEach(() => {
+ commit = jasmine.createSpy();
+ });
+
+ it('commits failure action', () => {
+ receiveMetricsDashboardFailure({ commit });
+
+ expect(commit).toHaveBeenCalledWith(types.RECEIVE_METRICS_DATA_FAILURE, undefined);
+ });
+
+ it('commits failure action with error', () => {
+ receiveMetricsDashboardFailure({ commit }, 'uh-oh');
+
+ expect(commit).toHaveBeenCalledWith(types.RECEIVE_METRICS_DATA_FAILURE, 'uh-oh');
+ });
+ });
+
+ describe('fetchPrometheusMetrics', () => {
+ let commit;
+ let dispatch;
+
+ beforeEach(() => {
+ commit = jasmine.createSpy();
+ dispatch = jasmine.createSpy();
+ });
+
+ it('commits empty state when state.groups is empty', done => {
+ const state = storeState();
+ const params = {};
+
+ fetchPrometheusMetrics({ state, commit, dispatch }, params)
+ .then(() => {
+ expect(commit).toHaveBeenCalledWith(types.SET_NO_DATA_EMPTY_STATE);
+ expect(dispatch).not.toHaveBeenCalled();
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('dispatches fetchPrometheusMetric for each panel query', done => {
+ const params = {};
+ const state = storeState();
+ state.groups = metricsDashboardResponse.dashboard.panel_groups;
+
+ const metric = state.groups[0].panels[0].metrics[0];
+
+ fetchPrometheusMetrics({ state, commit, dispatch }, params)
+ .then(() => {
+ expect(dispatch.calls.count()).toEqual(3);
+ expect(dispatch).toHaveBeenCalledWith('fetchPrometheusMetric', { metric, params });
+ done();
+ })
+ .catch(done.fail);
+
+ done();
+ });
+ });
+
+ describe('fetchPrometheusMetric', () => {
+ it('commits prometheus query result', done => {
+ const commit = jasmine.createSpy();
+ const params = {
+ start: '1557216349.469',
+ end: '1557218149.469',
+ };
+ const metric = metricsDashboardResponse.dashboard.panel_groups[0].panels[0].metrics[0];
+ const state = storeState();
+
+ const data = metricsGroupsAPIResponse.data[0].metrics[0].queries[0];
+ const response = { data };
+ mock.onGet('http://test').reply(200, response);
+
+ fetchPrometheusMetric({ state, commit }, { metric, params });
+
+ setTimeout(() => {
+ expect(commit).toHaveBeenCalledWith(types.SET_QUERY_RESULT, {
+ metricId: metric.metric_id,
+ result: data.result,
+ });
+ done();
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/monitoring/store/mutations_spec.js b/spec/javascripts/monitoring/store/mutations_spec.js
new file mode 100644
index 00000000000..02ff5847b34
--- /dev/null
+++ b/spec/javascripts/monitoring/store/mutations_spec.js
@@ -0,0 +1,159 @@
+import mutations from '~/monitoring/stores/mutations';
+import * as types from '~/monitoring/stores/mutation_types';
+import state from '~/monitoring/stores/state';
+import { metricsGroupsAPIResponse, deploymentData, metricsDashboardResponse } from '../mock_data';
+
+describe('Monitoring mutations', () => {
+ let stateCopy;
+
+ beforeEach(() => {
+ stateCopy = state();
+ });
+
+ describe(types.RECEIVE_METRICS_DATA_SUCCESS, () => {
+ let groups;
+
+ beforeEach(() => {
+ stateCopy.groups = [];
+ groups = metricsGroupsAPIResponse.data;
+ });
+
+ it('normalizes values', () => {
+ mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
+
+ const expectedTimestamp = '2017-05-25T08:22:34.925Z';
+ const expectedValue = 0.0010794445585559514;
+ const [timestamp, value] = stateCopy.groups[0].metrics[0].queries[0].result[0].values[0];
+
+ expect(timestamp).toEqual(expectedTimestamp);
+ expect(value).toEqual(expectedValue);
+ });
+
+ it('contains two groups that contains, one of which has two queries sorted by priority', () => {
+ mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
+
+ expect(stateCopy.groups).toBeDefined();
+ expect(stateCopy.groups.length).toEqual(2);
+ expect(stateCopy.groups[0].metrics.length).toEqual(2);
+ });
+
+ it('assigns queries a metric id', () => {
+ mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
+
+ expect(stateCopy.groups[1].metrics[0].queries[0].metricId).toEqual('100');
+ });
+
+ it('removes the data if all the values from a query are not defined', () => {
+ mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
+
+ expect(stateCopy.groups[1].metrics[0].queries[0].result.length).toEqual(0);
+ });
+
+ it('assigns metric id of null if metric has no id', () => {
+ stateCopy.groups = [];
+ const noId = groups.map(group => ({
+ ...group,
+ ...{
+ metrics: group.metrics.map(metric => {
+ const { id, ...metricWithoutId } = metric;
+
+ return metricWithoutId;
+ }),
+ },
+ }));
+
+ mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, noId);
+
+ stateCopy.groups.forEach(group => {
+ group.metrics.forEach(metric => {
+ expect(metric.queries.every(query => query.metricId === null)).toBe(true);
+ });
+ });
+ });
+
+ describe('dashboard endpoint enabled', () => {
+ const dashboardGroups = metricsDashboardResponse.dashboard.panel_groups;
+
+ beforeEach(() => {
+ stateCopy.useDashboardEndpoint = true;
+ });
+
+ it('aliases group panels to metrics for backwards compatibility', () => {
+ mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, dashboardGroups);
+
+ expect(stateCopy.groups[0].metrics[0]).toBeDefined();
+ });
+
+ it('aliases panel metrics to queries for backwards compatibility', () => {
+ mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, dashboardGroups);
+
+ expect(stateCopy.groups[0].metrics[0].queries).toBeDefined();
+ });
+ });
+ });
+
+ describe(types.RECEIVE_DEPLOYMENTS_DATA_SUCCESS, () => {
+ it('stores the deployment data', () => {
+ stateCopy.deploymentData = [];
+ mutations[types.RECEIVE_DEPLOYMENTS_DATA_SUCCESS](stateCopy, deploymentData);
+
+ expect(stateCopy.deploymentData).toBeDefined();
+ expect(stateCopy.deploymentData.length).toEqual(3);
+ expect(typeof stateCopy.deploymentData[0]).toEqual('object');
+ });
+ });
+
+ describe('SET_ENDPOINTS', () => {
+ it('should set all the endpoints', () => {
+ mutations[types.SET_ENDPOINTS](stateCopy, {
+ metricsEndpoint: 'additional_metrics.json',
+ environmentsEndpoint: 'environments.json',
+ deploymentsEndpoint: 'deployments.json',
+ dashboardEndpoint: 'dashboard.json',
+ });
+
+ expect(stateCopy.metricsEndpoint).toEqual('additional_metrics.json');
+ expect(stateCopy.environmentsEndpoint).toEqual('environments.json');
+ expect(stateCopy.deploymentsEndpoint).toEqual('deployments.json');
+ expect(stateCopy.dashboardEndpoint).toEqual('dashboard.json');
+ });
+ });
+
+ describe('SET_QUERY_RESULT', () => {
+ const metricId = 12;
+ const result = [{ values: [[0, 1], [1, 1], [1, 3]] }];
+
+ beforeEach(() => {
+ stateCopy.useDashboardEndpoint = true;
+ const dashboardGroups = metricsDashboardResponse.dashboard.panel_groups;
+ mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, dashboardGroups);
+ });
+
+ it('clears empty state', () => {
+ mutations[types.SET_QUERY_RESULT](stateCopy, {
+ metricId,
+ result,
+ });
+
+ expect(stateCopy.showEmptyState).toBe(false);
+ });
+
+ it('sets metricsWithData value', () => {
+ mutations[types.SET_QUERY_RESULT](stateCopy, {
+ metricId,
+ result,
+ });
+
+ expect(stateCopy.metricsWithData).toEqual([12]);
+ });
+
+ it('does not store empty results', () => {
+ mutations[types.SET_QUERY_RESULT](stateCopy, {
+ metricId,
+ result: [],
+ });
+
+ expect(stateCopy.metricsWithData).toEqual([]);
+ });
+ });
+});
diff --git a/spec/javascripts/notes/components/note_actions_spec.js b/spec/javascripts/notes/components/note_actions_spec.js
index 0cfcc994234..1f2c07385a7 100644
--- a/spec/javascripts/notes/components/note_actions_spec.js
+++ b/spec/javascripts/notes/components/note_actions_spec.js
@@ -58,6 +58,7 @@ describe('noteActions', () => {
it('should render emoji link', () => {
expect(wrapper.find('.js-add-award').exists()).toBe(true);
+ expect(wrapper.find('.js-add-award').attributes('data-position')).toBe('right');
});
describe('actions dropdown', () => {
@@ -65,7 +66,7 @@ describe('noteActions', () => {
expect(wrapper.find('.js-note-edit').exists()).toBe(true);
});
- it('should be possible to report abuse to GitLab', () => {
+ it('should be possible to report abuse to admin', () => {
expect(wrapper.find(`a[href="${props.reportAbusePath}"]`).exists()).toBe(true);
});
diff --git a/spec/javascripts/notes/components/note_app_spec.js b/spec/javascripts/notes/components/note_app_spec.js
deleted file mode 100644
index ef876dc2941..00000000000
--- a/spec/javascripts/notes/components/note_app_spec.js
+++ /dev/null
@@ -1,331 +0,0 @@
-import $ from 'jquery';
-import _ from 'underscore';
-import Vue from 'vue';
-import { mount, createLocalVue } from '@vue/test-utils';
-import NotesApp from '~/notes/components/notes_app.vue';
-import service from '~/notes/services/notes_service';
-import createStore from '~/notes/stores';
-import '~/behaviors/markdown/render_gfm';
-import * as mockData from '../mock_data';
-
-describe('note_app', () => {
- let mountComponent;
- let wrapper;
- let store;
-
- beforeEach(() => {
- $('body').attr('data-page', 'projects:merge_requests:show');
-
- store = createStore();
- mountComponent = data => {
- const propsData = data || {
- noteableData: mockData.noteableDataMock,
- notesData: mockData.notesDataMock,
- userData: mockData.userDataMock,
- };
- const localVue = createLocalVue();
-
- return mount(
- {
- components: {
- NotesApp,
- },
- template: '<div class="js-vue-notes-event"><notes-app v-bind="$attrs" /></div>',
- },
- {
- propsData,
- store,
- localVue,
- sync: false,
- },
- );
- };
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('set data', () => {
- const responseInterceptor = (request, next) => {
- next(
- request.respondWith(JSON.stringify([]), {
- status: 200,
- }),
- );
- };
-
- beforeEach(() => {
- Vue.http.interceptors.push(responseInterceptor);
- wrapper = mountComponent();
- });
-
- afterEach(() => {
- Vue.http.interceptors = _.without(Vue.http.interceptors, responseInterceptor);
- });
-
- it('should set notes data', () => {
- expect(store.state.notesData).toEqual(mockData.notesDataMock);
- });
-
- it('should set issue data', () => {
- expect(store.state.noteableData).toEqual(mockData.noteableDataMock);
- });
-
- it('should set user data', () => {
- expect(store.state.userData).toEqual(mockData.userDataMock);
- });
-
- it('should fetch discussions', () => {
- expect(store.state.discussions).toEqual([]);
- });
- });
-
- describe('render', () => {
- beforeEach(() => {
- setFixtures('<div class="js-discussions-count"></div>');
-
- Vue.http.interceptors.push(mockData.individualNoteInterceptor);
- wrapper = mountComponent();
- });
-
- afterEach(() => {
- Vue.http.interceptors = _.without(Vue.http.interceptors, mockData.individualNoteInterceptor);
- });
-
- it('should render list of notes', done => {
- const note =
- mockData.INDIVIDUAL_NOTE_RESPONSE_MAP.GET[
- '/gitlab-org/gitlab-ce/issues/26/discussions.json'
- ][0].notes[0];
-
- setTimeout(() => {
- expect(
- wrapper
- .find('.main-notes-list .note-header-author-name')
- .text()
- .trim(),
- ).toEqual(note.author.name);
-
- expect(wrapper.find('.main-notes-list .note-text').html()).toContain(note.note_html);
- done();
- }, 0);
- });
-
- it('should render form', () => {
- expect(wrapper.find('.js-main-target-form').name()).toEqual('form');
- expect(wrapper.find('.js-main-target-form textarea').attributes('placeholder')).toEqual(
- 'Write a comment or drag your files here…',
- );
- });
-
- it('should not render form when commenting is disabled', () => {
- store.state.commentsDisabled = true;
- wrapper = mountComponent();
-
- expect(wrapper.find('.js-main-target-form').exists()).toBe(false);
- });
-
- it('should render discussion filter note `commentsDisabled` is true', () => {
- store.state.commentsDisabled = true;
- wrapper = mountComponent();
-
- expect(wrapper.find('.js-discussion-filter-note').exists()).toBe(true);
- });
-
- it('should render form comment button as disabled', () => {
- expect(wrapper.find('.js-note-new-discussion').attributes('disabled')).toEqual('disabled');
- });
-
- it('updates discussions badge', done => {
- setTimeout(() => {
- expect(document.querySelector('.js-discussions-count').textContent).toEqual('2');
-
- done();
- });
- });
- });
-
- describe('while fetching data', () => {
- beforeEach(() => {
- wrapper = mountComponent();
- });
-
- it('renders skeleton notes', () => {
- expect(wrapper.find('.animation-container').exists()).toBe(true);
- });
-
- it('should render form', () => {
- expect(wrapper.find('.js-main-target-form').name()).toEqual('form');
- expect(wrapper.find('.js-main-target-form textarea').attributes('placeholder')).toEqual(
- 'Write a comment or drag your files here…',
- );
- });
- });
-
- describe('update note', () => {
- describe('individual note', () => {
- beforeEach(done => {
- Vue.http.interceptors.push(mockData.individualNoteInterceptor);
- spyOn(service, 'updateNote').and.callThrough();
- wrapper = mountComponent();
- setTimeout(() => {
- wrapper.find('.js-note-edit').trigger('click');
- Vue.nextTick(done);
- }, 0);
- });
-
- afterEach(() => {
- Vue.http.interceptors = _.without(
- Vue.http.interceptors,
- mockData.individualNoteInterceptor,
- );
- });
-
- it('renders edit form', () => {
- expect(wrapper.find('.js-vue-issue-note-form').exists()).toBe(true);
- });
-
- it('calls the service to update the note', done => {
- wrapper.find('.js-vue-issue-note-form').value = 'this is a note';
- wrapper.find('.js-vue-issue-save').trigger('click');
-
- expect(service.updateNote).toHaveBeenCalled();
- // Wait for the requests to finish before destroying
- setTimeout(() => {
- done();
- });
- });
- });
-
- describe('discussion note', () => {
- beforeEach(done => {
- Vue.http.interceptors.push(mockData.discussionNoteInterceptor);
- spyOn(service, 'updateNote').and.callThrough();
- wrapper = mountComponent();
-
- setTimeout(() => {
- wrapper.find('.js-note-edit').trigger('click');
- Vue.nextTick(done);
- }, 0);
- });
-
- afterEach(() => {
- Vue.http.interceptors = _.without(
- Vue.http.interceptors,
- mockData.discussionNoteInterceptor,
- );
- });
-
- it('renders edit form', () => {
- expect(wrapper.find('.js-vue-issue-note-form').exists()).toBe(true);
- });
-
- it('updates the note and resets the edit form', done => {
- wrapper.find('.js-vue-issue-note-form').value = 'this is a note';
- wrapper.find('.js-vue-issue-save').trigger('click');
-
- expect(service.updateNote).toHaveBeenCalled();
- // Wait for the requests to finish before destroying
- setTimeout(() => {
- done();
- });
- });
- });
- });
-
- describe('new note form', () => {
- beforeEach(() => {
- wrapper = mountComponent();
- });
-
- it('should render markdown docs url', () => {
- const { markdownDocsPath } = mockData.notesDataMock;
-
- expect(
- wrapper
- .find(`a[href="${markdownDocsPath}"]`)
- .text()
- .trim(),
- ).toEqual('Markdown');
- });
-
- it('should render quick action docs url', () => {
- const { quickActionsDocsPath } = mockData.notesDataMock;
-
- expect(
- wrapper
- .find(`a[href="${quickActionsDocsPath}"]`)
- .text()
- .trim(),
- ).toEqual('quick actions');
- });
- });
-
- describe('edit form', () => {
- beforeEach(() => {
- Vue.http.interceptors.push(mockData.individualNoteInterceptor);
- wrapper = mountComponent();
- });
-
- afterEach(() => {
- Vue.http.interceptors = _.without(Vue.http.interceptors, mockData.individualNoteInterceptor);
- });
-
- it('should render markdown docs url', done => {
- setTimeout(() => {
- wrapper.find('.js-note-edit').trigger('click');
- const { markdownDocsPath } = mockData.notesDataMock;
-
- Vue.nextTick(() => {
- expect(
- wrapper
- .find(`.edit-note a[href="${markdownDocsPath}"]`)
- .text()
- .trim(),
- ).toEqual('Markdown is supported');
- done();
- });
- }, 0);
- });
-
- it('should not render quick actions docs url', done => {
- setTimeout(() => {
- wrapper.find('.js-note-edit').trigger('click');
- const { quickActionsDocsPath } = mockData.notesDataMock;
-
- Vue.nextTick(() => {
- expect(wrapper.find(`.edit-note a[href="${quickActionsDocsPath}"]`).exists()).toBe(false);
- done();
- });
- }, 0);
- });
- });
-
- describe('emoji awards', () => {
- it('dispatches toggleAward after toggleAward event', () => {
- const toggleAwardEvent = new CustomEvent('toggleAward', {
- detail: {
- awardName: 'test',
- noteId: 1,
- },
- });
- const toggleAwardAction = jasmine.createSpy('toggleAward');
- wrapper.vm.$store.hotUpdate({
- actions: {
- toggleAward: toggleAwardAction,
- },
- });
-
- wrapper.vm.$parent.$el.dispatchEvent(toggleAwardEvent);
-
- expect(toggleAwardAction).toHaveBeenCalledTimes(1);
- const [, payload] = toggleAwardAction.calls.argsFor(0);
-
- expect(payload).toEqual({
- awardName: 'test',
- noteId: 1,
- });
- });
- });
-});
diff --git a/spec/javascripts/notes/components/noteable_discussion_spec.js b/spec/javascripts/notes/components/noteable_discussion_spec.js
index 3304c79cdb7..efa864e7d00 100644
--- a/spec/javascripts/notes/components/noteable_discussion_spec.js
+++ b/spec/javascripts/notes/components/noteable_discussion_spec.js
@@ -130,29 +130,6 @@ describe('noteable_discussion component', () => {
});
});
- describe('componentData', () => {
- it('should return first note object for placeholder note', () => {
- const data = {
- isPlaceholderNote: true,
- notes: [{ body: 'hello world!' }],
- };
-
- const note = wrapper.vm.componentData(data);
-
- expect(note).toEqual(data.notes[0]);
- });
-
- it('should return given note for nonplaceholder notes', () => {
- const data = {
- notes: [{ id: 12 }],
- };
-
- const note = wrapper.vm.componentData(data);
-
- expect(note).toEqual(data);
- });
- });
-
describe('action text', () => {
const commitId = 'razupaltuff';
const truncatedCommitId = commitId.substr(0, 8);
diff --git a/spec/javascripts/notes/stores/actions_spec.js b/spec/javascripts/notes/stores/actions_spec.js
index 94ce6d8e222..7a9f32ddcff 100644
--- a/spec/javascripts/notes/stores/actions_spec.js
+++ b/spec/javascripts/notes/stores/actions_spec.js
@@ -3,11 +3,12 @@ import $ from 'jquery';
import _ from 'underscore';
import { TEST_HOST } from 'spec/test_constants';
import { headersInterceptor } from 'spec/helpers/vue_resource_helper';
-import * as actions from '~/notes/stores/actions';
+import actionsModule, * as actions from '~/notes/stores/actions';
import * as mutationTypes from '~/notes/stores/mutation_types';
import * as notesConstants from '~/notes/constants';
import createStore from '~/notes/stores';
import mrWidgetEventHub from '~/vue_merge_request_widget/event_hub';
+import service from '~/notes/services/notes_service';
import testAction from '../../helpers/vuex_action_helper';
import { resetStore } from '../helpers';
import {
@@ -18,11 +19,21 @@ import {
individualNote,
} from '../mock_data';
+const TEST_ERROR_MESSAGE = 'Test error message';
+
describe('Actions Notes Store', () => {
+ let commit;
+ let dispatch;
+ let state;
let store;
+ let flashSpy;
beforeEach(() => {
store = createStore();
+ commit = jasmine.createSpy('commit');
+ dispatch = jasmine.createSpy('dispatch');
+ state = {};
+ flashSpy = spyOnDependency(actionsModule, 'Flash');
});
afterEach(() => {
@@ -604,21 +615,6 @@ describe('Actions Notes Store', () => {
});
describe('updateOrCreateNotes', () => {
- let commit;
- let dispatch;
- let state;
-
- beforeEach(() => {
- commit = jasmine.createSpy('commit');
- dispatch = jasmine.createSpy('dispatch');
- state = {};
- });
-
- afterEach(() => {
- commit.calls.reset();
- dispatch.calls.reset();
- });
-
it('Updates existing note', () => {
const note = { id: 1234 };
const getters = { notesById: { 1234: note } };
@@ -751,4 +747,151 @@ describe('Actions Notes Store', () => {
);
});
});
+
+ describe('resolveDiscussion', () => {
+ let getters;
+ let discussionId;
+
+ beforeEach(() => {
+ discussionId = discussionMock.id;
+ state.discussions = [discussionMock];
+ getters = {
+ isDiscussionResolved: () => false,
+ };
+ });
+
+ it('when unresolved, dispatches action', done => {
+ testAction(
+ actions.resolveDiscussion,
+ { discussionId },
+ { ...state, ...getters },
+ [],
+ [
+ {
+ type: 'toggleResolveNote',
+ payload: {
+ endpoint: discussionMock.resolve_path,
+ isResolved: false,
+ discussion: true,
+ },
+ },
+ ],
+ done,
+ );
+ });
+
+ it('when resolved, does nothing', done => {
+ getters.isDiscussionResolved = id => id === discussionId;
+
+ testAction(
+ actions.resolveDiscussion,
+ { discussionId },
+ { ...state, ...getters },
+ [],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('saveNote', () => {
+ const payload = { endpoint: TEST_HOST, data: { 'note[note]': 'some text' } };
+
+ describe('if response contains errors', () => {
+ const res = { errors: { something: ['went wrong'] } };
+
+ it('throws an error', done => {
+ actions
+ .saveNote(
+ {
+ commit() {},
+ dispatch: () => Promise.resolve(res),
+ },
+ payload,
+ )
+ .then(() => done.fail('Expected error to be thrown!'))
+ .catch(error => {
+ expect(error.message).toBe('Failed to save comment!');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('if response contains no errors', () => {
+ const res = { valid: true };
+
+ it('returns the response', done => {
+ actions
+ .saveNote(
+ {
+ commit() {},
+ dispatch: () => Promise.resolve(res),
+ },
+ payload,
+ )
+ .then(data => {
+ expect(data).toBe(res);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+ });
+
+ describe('submitSuggestion', () => {
+ const discussionId = 'discussion-id';
+ const noteId = 'note-id';
+ const suggestionId = 'suggestion-id';
+ let flashContainer;
+
+ beforeEach(() => {
+ spyOn(service, 'applySuggestion');
+ dispatch.and.returnValue(Promise.resolve());
+ service.applySuggestion.and.returnValue(Promise.resolve());
+ flashContainer = {};
+ });
+
+ const testSubmitSuggestion = (done, expectFn) => {
+ actions
+ .submitSuggestion(
+ { commit, dispatch },
+ { discussionId, noteId, suggestionId, flashContainer },
+ )
+ .then(expectFn)
+ .then(done)
+ .catch(done.fail);
+ };
+
+ it('when service success, commits and resolves discussion', done => {
+ testSubmitSuggestion(done, () => {
+ expect(commit.calls.allArgs()).toEqual([
+ [mutationTypes.APPLY_SUGGESTION, { discussionId, noteId, suggestionId }],
+ ]);
+
+ expect(dispatch.calls.allArgs()).toEqual([['resolveDiscussion', { discussionId }]]);
+ expect(flashSpy).not.toHaveBeenCalled();
+ });
+ });
+
+ it('when service fails, flashes error message', done => {
+ const response = { response: { data: { message: TEST_ERROR_MESSAGE } } };
+
+ service.applySuggestion.and.returnValue(Promise.reject(response));
+
+ testSubmitSuggestion(done, () => {
+ expect(commit).not.toHaveBeenCalled();
+ expect(dispatch).not.toHaveBeenCalled();
+ expect(flashSpy).toHaveBeenCalledWith(`${TEST_ERROR_MESSAGE}.`, 'alert', flashContainer);
+ });
+ });
+
+ it('when resolve discussion fails, fail gracefully', done => {
+ dispatch.and.returnValue(Promise.reject());
+
+ testSubmitSuggestion(done, () => {
+ expect(flashSpy).not.toHaveBeenCalled();
+ });
+ });
+ });
});
diff --git a/spec/javascripts/notes_spec.js b/spec/javascripts/notes_spec.js
deleted file mode 100644
index 394e3343be6..00000000000
--- a/spec/javascripts/notes_spec.js
+++ /dev/null
@@ -1,1048 +0,0 @@
-/* eslint-disable no-unused-expressions, no-var, object-shorthand */
-import $ from 'jquery';
-import _ from 'underscore';
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import 'autosize';
-import '~/gl_form';
-import '~/lib/utils/text_utility';
-import '~/behaviors/markdown/render_gfm';
-import Notes from '~/notes';
-import timeoutPromise from './helpers/set_timeout_promise_helper';
-
-window.gon || (window.gon = {});
-window.gl = window.gl || {};
-gl.utils = gl.utils || {};
-
-const htmlEscape = comment => {
- const escapedString = comment.replace(/["&'<>]/g, a => {
- const escapedToken = {
- '&': '&amp;',
- '<': '&lt;',
- '>': '&gt;',
- '"': '&quot;',
- "'": '&#x27;',
- '`': '&#x60;',
- }[a];
-
- return escapedToken;
- });
-
- return escapedString;
-};
-
-describe('Notes', function() {
- const FLASH_TYPE_ALERT = 'alert';
- const NOTES_POST_PATH = /(.*)\/notes\?html=true$/;
- var fixture = 'snippets/show.html';
- preloadFixtures(fixture);
-
- beforeEach(function() {
- loadFixtures(fixture);
- gl.utils.disableButtonIfEmptyField = _.noop;
- window.project_uploads_path = 'http://test.host/uploads';
- $('body').attr('data-page', 'projects:merge_requets:show');
- });
-
- afterEach(() => {
- // Undo what we did to the shared <body>
- $('body').removeAttr('data-page');
- });
-
- describe('addBinding', () => {
- it('calls postComment when comment button is clicked', () => {
- spyOn(Notes.prototype, 'postComment');
- this.notes = new Notes('', []);
-
- $('.js-comment-button').click();
-
- expect(Notes.prototype.postComment).toHaveBeenCalled();
- });
- });
-
- describe('task lists', function() {
- let mock;
-
- beforeEach(function() {
- spyOn(axios, 'patch').and.callFake(() => new Promise(() => {}));
- mock = new MockAdapter(axios);
- mock.onAny().reply(200, {});
-
- $('.js-comment-button').on('click', function(e) {
- e.preventDefault();
- });
- this.notes = new Notes('', []);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('modifies the Markdown field', function() {
- const changeEvent = document.createEvent('HTMLEvents');
- changeEvent.initEvent('change', true, true);
- $('input[type=checkbox]')
- .attr('checked', true)[0]
- .dispatchEvent(changeEvent);
-
- expect($('.js-task-list-field.original-task-list').val()).toBe('- [x] Task List Item');
- });
-
- it('submits an ajax request on tasklist:changed', function(done) {
- const lineNumber = 8;
- const lineSource = '- [ ] item 8';
- const index = 3;
- const checked = true;
-
- $('.js-task-list-container').trigger({
- type: 'tasklist:changed',
- detail: { lineNumber, lineSource, index, checked },
- });
-
- setTimeout(() => {
- expect(axios.patch).toHaveBeenCalledWith(undefined, {
- note: {
- note: '',
- lock_version: undefined,
- update_task: { index, checked, line_number: lineNumber, line_source: lineSource },
- },
- });
-
- done();
- });
- });
- });
-
- describe('comments', function() {
- var textarea = '.js-note-text';
-
- beforeEach(function() {
- this.notes = new Notes('', []);
-
- this.autoSizeSpy = spyOnEvent($(textarea), 'autosize:update');
- spyOn(this.notes, 'renderNote').and.stub();
-
- $(textarea).data('autosave', {
- reset: function() {},
- });
-
- $('.js-comment-button').on('click', e => {
- const $form = $(this);
- e.preventDefault();
- this.notes.addNote($form);
- this.notes.reenableTargetFormSubmitButton(e);
- this.notes.resetMainTargetForm(e);
- });
- });
-
- it('autosizes after comment submission', function() {
- $(textarea).text('This is an example comment note');
-
- expect(this.autoSizeSpy).not.toHaveBeenTriggered();
-
- $('.js-comment-button').click();
-
- expect(this.autoSizeSpy).toHaveBeenTriggered();
- });
-
- it('should not place escaped text in the comment box in case of error', function() {
- const deferred = $.Deferred();
- spyOn($, 'ajax').and.returnValue(deferred.promise());
- $(textarea).text('A comment with `markup`.');
-
- deferred.reject();
- $('.js-comment-button').click();
-
- expect($(textarea).val()).toEqual('A comment with `markup`.');
- });
- });
-
- describe('updateNote', () => {
- let sampleComment;
- let noteEntity;
- let $form;
- let $notesContainer;
- let mock;
-
- beforeEach(() => {
- this.notes = new Notes('', []);
- window.gon.current_username = 'root';
- window.gon.current_user_fullname = 'Administrator';
- sampleComment = 'foo';
- noteEntity = {
- id: 1234,
- html: `<li class="note note-row-1234 timeline-entry" id="note_1234">
- <div class="note-text">${sampleComment}</div>
- </li>`,
- note: sampleComment,
- valid: true,
- };
- $form = $('form.js-main-target-form');
- $notesContainer = $('ul.main-notes-list');
- $form.find('textarea.js-note-text').val(sampleComment);
-
- mock = new MockAdapter(axios);
- mock.onPost(NOTES_POST_PATH).reply(200, noteEntity);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('updates note and resets edit form', done => {
- spyOn(this.notes, 'revertNoteEditForm');
- spyOn(this.notes, 'setupNewNote');
-
- $('.js-comment-button').click();
-
- setTimeout(() => {
- const $targetNote = $notesContainer.find(`#note_${noteEntity.id}`);
- const updatedNote = Object.assign({}, noteEntity);
- updatedNote.note = 'bar';
- this.notes.updateNote(updatedNote, $targetNote);
-
- expect(this.notes.revertNoteEditForm).toHaveBeenCalledWith($targetNote);
- expect(this.notes.setupNewNote).toHaveBeenCalled();
-
- done();
- });
- });
- });
-
- describe('updateNoteTargetSelector', () => {
- const hash = 'note_foo';
- let $note;
-
- beforeEach(() => {
- $note = $(`<div id="${hash}"></div>`);
- spyOn($note, 'filter').and.callThrough();
- spyOn($note, 'toggleClass').and.callThrough();
- });
-
- it('sets target when hash matches', () => {
- spyOnDependency(Notes, 'getLocationHash').and.returnValue(hash);
-
- Notes.updateNoteTargetSelector($note);
-
- expect($note.filter).toHaveBeenCalledWith(`#${hash}`);
- expect($note.toggleClass).toHaveBeenCalledWith('target', true);
- });
-
- it('unsets target when hash does not match', () => {
- spyOnDependency(Notes, 'getLocationHash').and.returnValue('note_doesnotexist');
-
- Notes.updateNoteTargetSelector($note);
-
- expect($note.toggleClass).toHaveBeenCalledWith('target', false);
- });
-
- it('unsets target when there is not a hash fragment anymore', () => {
- spyOnDependency(Notes, 'getLocationHash').and.returnValue(null);
-
- Notes.updateNoteTargetSelector($note);
-
- expect($note.toggleClass).toHaveBeenCalledWith('target', false);
- });
- });
-
- describe('renderNote', () => {
- let notes;
- let note;
- let $notesList;
-
- beforeEach(() => {
- note = {
- id: 1,
- valid: true,
- note: 'heya',
- html: '<div>heya</div>',
- };
- $notesList = jasmine.createSpyObj('$notesList', ['find', 'append']);
-
- notes = jasmine.createSpyObj('notes', [
- 'setupNewNote',
- 'refresh',
- 'collapseLongCommitList',
- 'updateNotesCount',
- 'putConflictEditWarningInPlace',
- ]);
- notes.taskList = jasmine.createSpyObj('tasklist', ['init']);
- notes.note_ids = [];
- notes.updatedNotesTrackingMap = {};
-
- spyOn(Notes, 'isNewNote').and.callThrough();
- spyOn(Notes, 'isUpdatedNote').and.callThrough();
- spyOn(Notes, 'animateAppendNote').and.callThrough();
- spyOn(Notes, 'animateUpdateNote').and.callThrough();
- });
-
- describe('when adding note', () => {
- it('should call .animateAppendNote', () => {
- Notes.isNewNote.and.returnValue(true);
- Notes.prototype.renderNote.call(notes, note, null, $notesList);
-
- expect(Notes.animateAppendNote).toHaveBeenCalledWith(note.html, $notesList);
- });
- });
-
- describe('when note was edited', () => {
- it('should call .animateUpdateNote', () => {
- Notes.isNewNote.and.returnValue(false);
- Notes.isUpdatedNote.and.returnValue(true);
- const $note = $('<div>');
- $notesList.find.and.returnValue($note);
- const $newNote = $(note.html);
- Notes.animateUpdateNote.and.returnValue($newNote);
-
- Notes.prototype.renderNote.call(notes, note, null, $notesList);
-
- expect(Notes.animateUpdateNote).toHaveBeenCalledWith(note.html, $note);
- expect(notes.setupNewNote).toHaveBeenCalledWith($newNote);
- });
-
- describe('while editing', () => {
- it('should update textarea if nothing has been touched', () => {
- Notes.isNewNote.and.returnValue(false);
- Notes.isUpdatedNote.and.returnValue(true);
- const $note = $(`<div class="is-editing">
- <div class="original-note-content">initial</div>
- <textarea class="js-note-text">initial</textarea>
- </div>`);
- $notesList.find.and.returnValue($note);
- Notes.prototype.renderNote.call(notes, note, null, $notesList);
-
- expect($note.find('.js-note-text').val()).toEqual(note.note);
- });
-
- it('should call .putConflictEditWarningInPlace', () => {
- Notes.isNewNote.and.returnValue(false);
- Notes.isUpdatedNote.and.returnValue(true);
- const $note = $(`<div class="is-editing">
- <div class="original-note-content">initial</div>
- <textarea class="js-note-text">different</textarea>
- </div>`);
- $notesList.find.and.returnValue($note);
- Notes.prototype.renderNote.call(notes, note, null, $notesList);
-
- expect(notes.putConflictEditWarningInPlace).toHaveBeenCalledWith(note, $note);
- });
- });
- });
- });
-
- describe('isUpdatedNote', () => {
- it('should consider same note text as the same', () => {
- const result = Notes.isUpdatedNote(
- {
- note: 'initial',
- },
- $(`<div>
- <div class="original-note-content">initial</div>
- </div>`),
- );
-
- expect(result).toEqual(false);
- });
-
- it('should consider same note with trailing newline as the same', () => {
- const result = Notes.isUpdatedNote(
- {
- note: 'initial\n',
- },
- $(`<div>
- <div class="original-note-content">initial\n</div>
- </div>`),
- );
-
- expect(result).toEqual(false);
- });
-
- it('should consider different notes as different', () => {
- const result = Notes.isUpdatedNote(
- {
- note: 'foo',
- },
- $(`<div>
- <div class="original-note-content">bar</div>
- </div>`),
- );
-
- expect(result).toEqual(true);
- });
- });
-
- describe('renderDiscussionNote', () => {
- let discussionContainer;
- let note;
- let notes;
- let $form;
- let row;
-
- beforeEach(() => {
- note = {
- html: '<li></li>',
- discussion_html: '<div></div>',
- discussion_id: 1,
- discussion_resolvable: false,
- diff_discussion_html: false,
- };
- $form = jasmine.createSpyObj('$form', ['closest', 'find']);
- $form.length = 1;
- row = jasmine.createSpyObj('row', ['prevAll', 'first', 'find']);
-
- notes = jasmine.createSpyObj('notes', ['isParallelView', 'updateNotesCount']);
- notes.note_ids = [];
-
- spyOn(Notes, 'isNewNote');
- spyOn(Notes, 'animateAppendNote');
- Notes.isNewNote.and.returnValue(true);
- notes.isParallelView.and.returnValue(false);
- row.prevAll.and.returnValue(row);
- row.first.and.returnValue(row);
- row.find.and.returnValue(row);
- });
-
- describe('Discussion root note', () => {
- let body;
-
- beforeEach(() => {
- body = jasmine.createSpyObj('body', ['attr']);
- discussionContainer = { length: 0 };
-
- $form.closest.and.returnValues(row, $form);
- $form.find.and.returnValues(discussionContainer);
- body.attr.and.returnValue('');
- });
-
- it('should call Notes.animateAppendNote', () => {
- Notes.prototype.renderDiscussionNote.call(notes, note, $form);
-
- expect(Notes.animateAppendNote).toHaveBeenCalledWith(
- note.discussion_html,
- $('.main-notes-list'),
- );
- });
-
- it('should append to row selected with line_code', () => {
- $form.length = 0;
- note.discussion_line_code = 'line_code';
- note.diff_discussion_html = '<tr></tr>';
-
- const line = document.createElement('div');
- line.id = note.discussion_line_code;
- document.body.appendChild(line);
-
- $form.closest.and.returnValues($form);
-
- Notes.prototype.renderDiscussionNote.call(notes, note, $form);
-
- expect(line.nextSibling.outerHTML).toEqual(note.diff_discussion_html);
- });
- });
-
- describe('Discussion sub note', () => {
- beforeEach(() => {
- discussionContainer = { length: 1 };
-
- $form.closest.and.returnValues(row, $form);
- $form.find.and.returnValues(discussionContainer);
-
- Notes.prototype.renderDiscussionNote.call(notes, note, $form);
- });
-
- it('should call Notes.animateAppendNote', () => {
- expect(Notes.animateAppendNote).toHaveBeenCalledWith(note.html, discussionContainer);
- });
- });
- });
-
- describe('animateAppendNote', () => {
- let noteHTML;
- let $notesList;
- let $resultantNote;
-
- beforeEach(() => {
- noteHTML = '<div></div>';
- $notesList = jasmine.createSpyObj('$notesList', ['append']);
-
- $resultantNote = Notes.animateAppendNote(noteHTML, $notesList);
- });
-
- it('should have `fade-in-full` class', () => {
- expect($resultantNote.hasClass('fade-in-full')).toEqual(true);
- });
-
- it('should append note to the notes list', () => {
- expect($notesList.append).toHaveBeenCalledWith($resultantNote);
- });
- });
-
- describe('animateUpdateNote', () => {
- let noteHTML;
- let $note;
- let $updatedNote;
-
- beforeEach(() => {
- noteHTML = '<div></div>';
- $note = jasmine.createSpyObj('$note', ['replaceWith']);
-
- $updatedNote = Notes.animateUpdateNote(noteHTML, $note);
- });
-
- it('should have `fade-in` class', () => {
- expect($updatedNote.hasClass('fade-in')).toEqual(true);
- });
-
- it('should call replaceWith on $note', () => {
- expect($note.replaceWith).toHaveBeenCalledWith($updatedNote);
- });
- });
-
- describe('putEditFormInPlace', () => {
- it('should call GLForm with GFM parameter passed through', () => {
- const notes = new Notes('', []);
- const $el = $(`
- <div>
- <form></form>
- </div>
- `);
-
- notes.putEditFormInPlace($el);
-
- expect(notes.glForm.enableGFM).toBeTruthy();
- });
- });
-
- describe('postComment & updateComment', () => {
- const sampleComment = 'foo';
- const updatedComment = 'bar';
- const note = {
- id: 1234,
- html: `<li class="note note-row-1234 timeline-entry" id="note_1234">
- <div class="note-text">${sampleComment}</div>
- </li>`,
- note: sampleComment,
- valid: true,
- };
- let $form;
- let $notesContainer;
- let mock;
-
- function mockNotesPost() {
- mock.onPost(NOTES_POST_PATH).reply(200, note);
- }
-
- function mockNotesPostError() {
- mock.onPost(NOTES_POST_PATH).networkError();
- }
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
-
- this.notes = new Notes('', []);
- window.gon.current_username = 'root';
- window.gon.current_user_fullname = 'Administrator';
- $form = $('form.js-main-target-form');
- $notesContainer = $('ul.main-notes-list');
- $form.find('textarea.js-note-text').val(sampleComment);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('should show placeholder note while new comment is being posted', () => {
- mockNotesPost();
-
- $('.js-comment-button').click();
-
- expect($notesContainer.find('.note.being-posted').length).toBeGreaterThan(0);
- });
-
- it('should remove placeholder note when new comment is done posting', done => {
- mockNotesPost();
-
- $('.js-comment-button').click();
-
- setTimeout(() => {
- expect($notesContainer.find('.note.being-posted').length).toEqual(0);
-
- done();
- });
- });
-
- describe('postComment', () => {
- it('disables the submit button', done => {
- const $submitButton = $form.find('.js-comment-submit-button');
-
- expect($submitButton).not.toBeDisabled();
- const dummyEvent = {
- preventDefault() {},
- target: $submitButton,
- };
- mock.onPost(NOTES_POST_PATH).replyOnce(() => {
- expect($submitButton).toBeDisabled();
- return [200, note];
- });
-
- this.notes
- .postComment(dummyEvent)
- .then(() => {
- expect($submitButton).not.toBeDisabled();
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- it('should show actual note element when new comment is done posting', done => {
- mockNotesPost();
-
- $('.js-comment-button').click();
-
- setTimeout(() => {
- expect($notesContainer.find(`#note_${note.id}`).length).toBeGreaterThan(0);
-
- done();
- });
- });
-
- it('should reset Form when new comment is done posting', done => {
- mockNotesPost();
-
- $('.js-comment-button').click();
-
- setTimeout(() => {
- expect($form.find('textarea.js-note-text').val()).toEqual('');
-
- done();
- });
- });
-
- it('should show flash error message when new comment failed to be posted', done => {
- mockNotesPostError();
-
- $('.js-comment-button').click();
-
- setTimeout(() => {
- expect(
- $notesContainer
- .parent()
- .find('.flash-container .flash-text')
- .is(':visible'),
- ).toEqual(true);
-
- done();
- });
- });
-
- it('should show flash error message when comment failed to be updated', done => {
- mockNotesPost();
-
- $('.js-comment-button').click();
-
- timeoutPromise()
- .then(() => {
- const $noteEl = $notesContainer.find(`#note_${note.id}`);
- $noteEl.find('.js-note-edit').click();
- $noteEl.find('textarea.js-note-text').val(updatedComment);
-
- mock.restore();
-
- mockNotesPostError();
-
- $noteEl.find('.js-comment-save-button').click();
- })
- .then(timeoutPromise)
- .then(() => {
- const $updatedNoteEl = $notesContainer.find(`#note_${note.id}`);
-
- expect($updatedNoteEl.hasClass('.being-posted')).toEqual(false); // Remove being-posted visuals
- expect(
- $updatedNoteEl
- .find('.note-text')
- .text()
- .trim(),
- ).toEqual(sampleComment); // See if comment reverted back to original
-
- expect($('.flash-container').is(':visible')).toEqual(true); // Flash error message shown
-
- done();
- })
- .catch(done.fail);
- }, 2000);
- });
-
- describe('postComment with Slash commands', () => {
- const sampleComment = '/assign @root\n/award :100:';
- const note = {
- commands_changes: {
- assignee_id: 1,
- emoji_award: '100',
- },
- errors: {
- commands_only: ['Commands applied'],
- },
- valid: false,
- };
- let $form;
- let $notesContainer;
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- mock.onPost(NOTES_POST_PATH).reply(200, note);
-
- this.notes = new Notes('', []);
- window.gon.current_username = 'root';
- window.gon.current_user_fullname = 'Administrator';
- gl.awardsHandler = {
- addAwardToEmojiBar: () => {},
- scrollToAwards: () => {},
- };
- gl.GfmAutoComplete = {
- dataSources: {
- commands: '/root/test-project/autocomplete_sources/commands',
- },
- };
- $form = $('form.js-main-target-form');
- $notesContainer = $('ul.main-notes-list');
- $form.find('textarea.js-note-text').val(sampleComment);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('should remove slash command placeholder when comment with slash commands is done posting', done => {
- spyOn(gl.awardsHandler, 'addAwardToEmojiBar').and.callThrough();
- $('.js-comment-button').click();
-
- expect($notesContainer.find('.system-note.being-posted').length).toEqual(1); // Placeholder shown
-
- setTimeout(() => {
- expect($notesContainer.find('.system-note.being-posted').length).toEqual(0); // Placeholder removed
- done();
- });
- });
- });
-
- describe('update comment with script tags', () => {
- const sampleComment = '<script></script>';
- const updatedComment = '<script></script>';
- const note = {
- id: 1234,
- html: `<li class="note note-row-1234 timeline-entry" id="note_1234">
- <div class="note-text">${sampleComment}</div>
- </li>`,
- note: sampleComment,
- valid: true,
- };
- let $form;
- let $notesContainer;
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- mock.onPost(NOTES_POST_PATH).reply(200, note);
-
- this.notes = new Notes('', []);
- window.gon.current_username = 'root';
- window.gon.current_user_fullname = 'Administrator';
- $form = $('form.js-main-target-form');
- $notesContainer = $('ul.main-notes-list');
- $form.find('textarea.js-note-text').html(sampleComment);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('should not render a script tag', done => {
- $('.js-comment-button').click();
-
- setTimeout(() => {
- const $noteEl = $notesContainer.find(`#note_${note.id}`);
- $noteEl.find('.js-note-edit').click();
- $noteEl.find('textarea.js-note-text').html(updatedComment);
- $noteEl.find('.js-comment-save-button').click();
-
- const $updatedNoteEl = $notesContainer
- .find(`#note_${note.id}`)
- .find('.js-task-list-container');
-
- expect(
- $updatedNoteEl
- .find('.note-text')
- .text()
- .trim(),
- ).toEqual('');
-
- done();
- });
- });
- });
-
- describe('getFormData', () => {
- let $form;
- let sampleComment;
-
- beforeEach(() => {
- this.notes = new Notes('', []);
-
- $form = $('form');
- sampleComment = 'foobar';
- });
-
- it('should return form metadata object from form reference', () => {
- $form.find('textarea.js-note-text').val(sampleComment);
- const { formData, formContent, formAction } = this.notes.getFormData($form);
-
- expect(formData.indexOf(sampleComment)).toBeGreaterThan(-1);
- expect(formContent).toEqual(sampleComment);
- expect(formAction).toEqual($form.attr('action'));
- });
-
- it('should return form metadata with sanitized formContent from form reference', () => {
- spyOn(_, 'escape').and.callFake(htmlEscape);
-
- sampleComment = '<script>alert("Boom!");</script>';
- $form.find('textarea.js-note-text').val(sampleComment);
-
- const { formContent } = this.notes.getFormData($form);
-
- expect(_.escape).toHaveBeenCalledWith(sampleComment);
- expect(formContent).toEqual('&lt;script&gt;alert(&quot;Boom!&quot;);&lt;/script&gt;');
- });
- });
-
- describe('hasQuickActions', () => {
- beforeEach(() => {
- this.notes = new Notes('', []);
- });
-
- it('should return true when comment begins with a quick action', () => {
- const sampleComment = '/wip\n/milestone %1.0\n/merge\n/unassign Merging this';
- const hasQuickActions = this.notes.hasQuickActions(sampleComment);
-
- expect(hasQuickActions).toBeTruthy();
- });
-
- it('should return false when comment does NOT begin with a quick action', () => {
- const sampleComment = 'Hey, /unassign Merging this';
- const hasQuickActions = this.notes.hasQuickActions(sampleComment);
-
- expect(hasQuickActions).toBeFalsy();
- });
-
- it('should return false when comment does NOT have any quick actions', () => {
- const sampleComment = 'Looking good, Awesome!';
- const hasQuickActions = this.notes.hasQuickActions(sampleComment);
-
- expect(hasQuickActions).toBeFalsy();
- });
- });
-
- describe('stripQuickActions', () => {
- it('should strip quick actions from the comment which begins with a quick action', () => {
- this.notes = new Notes();
- const sampleComment = '/wip\n/milestone %1.0\n/merge\n/unassign Merging this';
- const stripedComment = this.notes.stripQuickActions(sampleComment);
-
- expect(stripedComment).toBe('');
- });
-
- it('should strip quick actions from the comment but leaves plain comment if it is present', () => {
- this.notes = new Notes();
- const sampleComment = '/wip\n/milestone %1.0\n/merge\n/unassign\nMerging this';
- const stripedComment = this.notes.stripQuickActions(sampleComment);
-
- expect(stripedComment).toBe('Merging this');
- });
-
- it('should NOT strip string that has slashes within', () => {
- this.notes = new Notes();
- const sampleComment = 'http://127.0.0.1:3000/root/gitlab-shell/issues/1';
- const stripedComment = this.notes.stripQuickActions(sampleComment);
-
- expect(stripedComment).toBe(sampleComment);
- });
- });
-
- describe('getQuickActionDescription', () => {
- const availableQuickActions = [
- { name: 'close', description: 'Close this issue', params: [] },
- { name: 'title', description: 'Change title', params: [{}] },
- { name: 'estimate', description: 'Set time estimate', params: [{}] },
- ];
-
- beforeEach(() => {
- this.notes = new Notes();
- });
-
- it('should return executing quick action description when note has single quick action', () => {
- const sampleComment = '/close';
-
- expect(this.notes.getQuickActionDescription(sampleComment, availableQuickActions)).toBe(
- 'Applying command to close this issue',
- );
- });
-
- it('should return generic multiple quick action description when note has multiple quick actions', () => {
- const sampleComment = '/close\n/title [Duplicate] Issue foobar';
-
- expect(this.notes.getQuickActionDescription(sampleComment, availableQuickActions)).toBe(
- 'Applying multiple commands',
- );
- });
-
- it('should return generic quick action description when available quick actions list is not populated', () => {
- const sampleComment = '/close\n/title [Duplicate] Issue foobar';
-
- expect(this.notes.getQuickActionDescription(sampleComment)).toBe('Applying command');
- });
- });
-
- describe('createPlaceholderNote', () => {
- const sampleComment = 'foobar';
- const uniqueId = 'b1234-a4567';
- const currentUsername = 'root';
- const currentUserFullname = 'Administrator';
- const currentUserAvatar = 'avatar_url';
-
- beforeEach(() => {
- this.notes = new Notes('', []);
- });
-
- it('should return constructed placeholder element for regular note based on form contents', () => {
- const $tempNote = this.notes.createPlaceholderNote({
- formContent: sampleComment,
- uniqueId,
- isDiscussionNote: false,
- currentUsername,
- currentUserFullname,
- currentUserAvatar,
- });
- const $tempNoteHeader = $tempNote.find('.note-header');
-
- expect($tempNote.prop('nodeName')).toEqual('LI');
- expect($tempNote.attr('id')).toEqual(uniqueId);
- expect($tempNote.hasClass('being-posted')).toBeTruthy();
- expect($tempNote.hasClass('fade-in-half')).toBeTruthy();
- $tempNote.find('.timeline-icon > a, .note-header-info > a').each(function() {
- expect($(this).attr('href')).toEqual(`/${currentUsername}`);
- });
-
- expect($tempNote.find('.timeline-icon .avatar').attr('src')).toEqual(currentUserAvatar);
- expect($tempNote.find('.timeline-content').hasClass('discussion')).toBeFalsy();
- expect(
- $tempNoteHeader
- .find('.d-none.d-sm-inline-block')
- .text()
- .trim(),
- ).toEqual(currentUserFullname);
-
- expect(
- $tempNoteHeader
- .find('.note-headline-light')
- .text()
- .trim(),
- ).toEqual(`@${currentUsername}`);
-
- expect(
- $tempNote
- .find('.note-body .note-text p')
- .text()
- .trim(),
- ).toEqual(sampleComment);
- });
-
- it('should return constructed placeholder element for discussion note based on form contents', () => {
- const $tempNote = this.notes.createPlaceholderNote({
- formContent: sampleComment,
- uniqueId,
- isDiscussionNote: true,
- currentUsername,
- currentUserFullname,
- });
-
- expect($tempNote.prop('nodeName')).toEqual('LI');
- expect($tempNote.find('.timeline-content').hasClass('discussion')).toBeTruthy();
- });
-
- it('should return a escaped user name', () => {
- const currentUserFullnameXSS = 'Foo <script>alert("XSS")</script>';
- const $tempNote = this.notes.createPlaceholderNote({
- formContent: sampleComment,
- uniqueId,
- isDiscussionNote: false,
- currentUsername,
- currentUserFullname: currentUserFullnameXSS,
- currentUserAvatar,
- });
- const $tempNoteHeader = $tempNote.find('.note-header');
-
- expect(
- $tempNoteHeader
- .find('.d-none.d-sm-inline-block')
- .text()
- .trim(),
- ).toEqual('Foo &lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;');
- });
- });
-
- describe('createPlaceholderSystemNote', () => {
- const sampleCommandDescription = 'Applying command to close this issue';
- const uniqueId = 'b1234-a4567';
-
- beforeEach(() => {
- this.notes = new Notes('', []);
- spyOn(_, 'escape').and.callFake(htmlEscape);
- });
-
- it('should return constructed placeholder element for system note based on form contents', () => {
- const $tempNote = this.notes.createPlaceholderSystemNote({
- formContent: sampleCommandDescription,
- uniqueId,
- });
-
- expect($tempNote.prop('nodeName')).toEqual('LI');
- expect($tempNote.attr('id')).toEqual(uniqueId);
- expect($tempNote.hasClass('being-posted')).toBeTruthy();
- expect($tempNote.hasClass('fade-in-half')).toBeTruthy();
- expect(
- $tempNote
- .find('.timeline-content i')
- .text()
- .trim(),
- ).toEqual(sampleCommandDescription);
- });
- });
-
- describe('appendFlash', () => {
- beforeEach(() => {
- this.notes = new Notes();
- });
-
- it('shows a flash message', () => {
- this.notes.addFlash('Error message', FLASH_TYPE_ALERT, this.notes.parentTimeline.get(0));
-
- expect($('.flash-alert').is(':visible')).toBeTruthy();
- });
- });
-
- describe('clearFlash', () => {
- beforeEach(() => {
- $(document).off('ajax:success');
- this.notes = new Notes();
- });
-
- it('hides visible flash message', () => {
- this.notes.addFlash('Error message 1', FLASH_TYPE_ALERT, this.notes.parentTimeline.get(0));
-
- this.notes.clearFlash();
-
- expect($('.flash-alert').is(':visible')).toBeFalsy();
- });
- });
-});
diff --git a/spec/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js b/spec/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
index a89952ee435..5f4dba5ecb9 100644
--- a/spec/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
+++ b/spec/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
@@ -3,6 +3,7 @@ import GLDropdown from '~/gl_dropdown'; // eslint-disable-line no-unused-vars
import TimezoneDropdown, {
formatUtcOffset,
formatTimezone,
+ findTimezoneByIdentifier,
} from '~/pages/projects/pipeline_schedules/shared/components/timezone_dropdown';
describe('Timezone Dropdown', function() {
@@ -12,6 +13,7 @@ describe('Timezone Dropdown', function() {
let $dropdownEl = null;
let $wrapper = null;
const tzListSel = '.dropdown-content ul li a.is-active';
+ const tzDropdownToggleText = '.dropdown-toggle-text';
describe('Initialize', () => {
describe('with dropdown already loaded', () => {
@@ -94,6 +96,36 @@ describe('Timezone Dropdown', function() {
expect(onSelectTimezone).toHaveBeenCalled();
});
+
+ it('will correctly set the dropdown label if a timezone identifier is set on the inputEl', () => {
+ $inputEl.val('America/St_Johns');
+
+ // eslint-disable-next-line no-new
+ new TimezoneDropdown({
+ $inputEl,
+ $dropdownEl,
+ displayFormat: selectedItem => formatTimezone(selectedItem),
+ });
+
+ expect($wrapper.find(tzDropdownToggleText).html()).toEqual('[UTC - 2.5] Newfoundland');
+ });
+
+ it('will call a provided `displayFormat` handler to format the dropdown value', () => {
+ const displayFormat = jasmine.createSpy('displayFormat');
+ // eslint-disable-next-line no-new
+ new TimezoneDropdown({
+ $inputEl,
+ $dropdownEl,
+ displayFormat,
+ });
+
+ $wrapper
+ .find(tzListSel)
+ .first()
+ .trigger('click');
+
+ expect(displayFormat).toHaveBeenCalled();
+ });
});
});
@@ -164,4 +196,49 @@ describe('Timezone Dropdown', function() {
).toEqual('[UTC 0] Accra');
});
});
+
+ describe('findTimezoneByIdentifier', () => {
+ const tzList = [
+ {
+ identifier: 'Asia/Tokyo',
+ name: 'Sapporo',
+ offset: 32400,
+ },
+ {
+ identifier: 'Asia/Hong_Kong',
+ name: 'Hong Kong',
+ offset: 28800,
+ },
+ {
+ identifier: 'Asia/Dhaka',
+ name: 'Dhaka',
+ offset: 21600,
+ },
+ ];
+
+ const identifier = 'Asia/Dhaka';
+ it('returns the correct object if the identifier exists', () => {
+ const res = findTimezoneByIdentifier(tzList, identifier);
+
+ expect(res).toBeTruthy();
+ expect(res).toBe(tzList[2]);
+ });
+
+ it('returns null if it doesnt find the identifier', () => {
+ const res = findTimezoneByIdentifier(tzList, 'Australia/Melbourne');
+
+ expect(res).toBeNull();
+ });
+
+ it('returns null if there is no identifier given', () => {
+ expect(findTimezoneByIdentifier(tzList)).toBeNull();
+ expect(findTimezoneByIdentifier(tzList, '')).toBeNull();
+ });
+
+ it('returns null if there is an empty or invalid array given', () => {
+ expect(findTimezoneByIdentifier([], identifier)).toBeNull();
+ expect(findTimezoneByIdentifier(null, identifier)).toBeNull();
+ expect(findTimezoneByIdentifier(undefined, identifier)).toBeNull();
+ });
+ });
});
diff --git a/spec/javascripts/pdf/index_spec.js b/spec/javascripts/pdf/index_spec.js
index 6df4ded92f0..c746d5644e8 100644
--- a/spec/javascripts/pdf/index_spec.js
+++ b/spec/javascripts/pdf/index_spec.js
@@ -1,9 +1,11 @@
import Vue from 'vue';
-import { GlobalWorkerOptions } from 'vendor/pdf';
-import workerSrc from 'vendor/pdf.worker.min';
+import { GlobalWorkerOptions } from 'pdfjs-dist/build/pdf';
+import workerSrc from 'pdfjs-dist/build/pdf.worker.min';
import PDFLab from '~/pdf/index.vue';
-import pdf from '../fixtures/blob/pdf/test.pdf';
+import { FIXTURES_PATH } from 'spec/test_constants';
+
+const pdf = `${FIXTURES_PATH}/blob/pdf/test.pdf`;
GlobalWorkerOptions.workerSrc = workerSrc;
const Component = Vue.extend(PDFLab);
diff --git a/spec/javascripts/pdf/page_spec.js b/spec/javascripts/pdf/page_spec.js
index b2e9fa42a63..6dea570266b 100644
--- a/spec/javascripts/pdf/page_spec.js
+++ b/spec/javascripts/pdf/page_spec.js
@@ -1,10 +1,12 @@
import Vue from 'vue';
-import pdfjsLib from 'vendor/pdf';
-import workerSrc from 'vendor/pdf.worker.min';
+import pdfjsLib from 'pdfjs-dist/build/pdf';
+import workerSrc from 'pdfjs-dist/build/pdf.worker.min';
import PageComponent from '~/pdf/page/index.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import testPDF from 'spec/fixtures/blob/pdf/test.pdf';
+import { FIXTURES_PATH } from 'spec/test_constants';
+
+const testPDF = `${FIXTURES_PATH}/blob/pdf/test.pdf`;
describe('Page component', () => {
const Component = Vue.extend(PageComponent);
diff --git a/spec/javascripts/performance_bar/components/detailed_metric_spec.js b/spec/javascripts/performance_bar/components/detailed_metric_spec.js
index e91685e50c5..8a7aa057186 100644
--- a/spec/javascripts/performance_bar/components/detailed_metric_spec.js
+++ b/spec/javascripts/performance_bar/components/detailed_metric_spec.js
@@ -27,8 +27,8 @@ describe('detailedMetric', () => {
describe('when the current request has details', () => {
const requestDetails = [
- { duration: '100', feature: 'find_commit', request: 'abcdef' },
- { duration: '23', feature: 'rebase_in_progress', request: '' },
+ { duration: '100', feature: 'find_commit', request: 'abcdef', backtrace: ['hello', 'world'] },
+ { duration: '23', feature: 'rebase_in_progress', request: '', backtrace: ['world', 'hello'] },
];
beforeEach(() => {
@@ -54,9 +54,11 @@ describe('detailedMetric', () => {
});
it('adds a modal with a table of the details', () => {
- vm.$el.querySelectorAll('.performance-bar-modal td strong').forEach((duration, index) => {
- expect(duration.innerText).toContain(requestDetails[index].duration);
- });
+ vm.$el
+ .querySelectorAll('.performance-bar-modal td:nth-child(1)')
+ .forEach((duration, index) => {
+ expect(duration.innerText).toContain(requestDetails[index].duration);
+ });
vm.$el
.querySelectorAll('.performance-bar-modal td:nth-child(2)')
@@ -65,10 +67,16 @@ describe('detailedMetric', () => {
});
vm.$el
- .querySelectorAll('.performance-bar-modal td:nth-child(3)')
+ .querySelectorAll('.performance-bar-modal td:nth-child(2)')
.forEach((request, index) => {
- expect(request.innerText).toEqual(requestDetails[index].request);
+ expect(request.innerText).toContain(requestDetails[index].request);
});
+
+ expect(vm.$el.querySelector('.text-expander.js-toggle-button')).not.toBeNull();
+
+ vm.$el.querySelectorAll('.performance-bar-modal td:nth-child(2)').forEach(request => {
+ expect(request.innerText).toContain('world');
+ });
});
it('displays the metric name', () => {
diff --git a/spec/javascripts/pipelines/graph/action_component_spec.js b/spec/javascripts/pipelines/graph/action_component_spec.js
index 95717d659b8..321497b35b5 100644
--- a/spec/javascripts/pipelines/graph/action_component_spec.js
+++ b/spec/javascripts/pipelines/graph/action_component_spec.js
@@ -66,5 +66,16 @@ describe('pipeline graph action component', () => {
done();
}, 0);
});
+
+ it('renders a loading icon while waiting for request', done => {
+ component.$el.click();
+
+ component.$nextTick(() => {
+ expect(component.$el.querySelector('.js-action-icon-loading')).not.toBeNull();
+ setTimeout(() => {
+ done();
+ });
+ });
+ });
});
});
diff --git a/spec/javascripts/pipelines/graph/stage_column_component_spec.js b/spec/javascripts/pipelines/graph/stage_column_component_spec.js
index 3240e8e4c1b..5183f8dd2d6 100644
--- a/spec/javascripts/pipelines/graph/stage_column_component_spec.js
+++ b/spec/javascripts/pipelines/graph/stage_column_component_spec.js
@@ -70,4 +70,53 @@ describe('stage column component', () => {
);
});
});
+
+ describe('with action', () => {
+ it('renders action button', () => {
+ component = mountComponent(StageColumnComponent, {
+ groups: [
+ {
+ id: 4259,
+ name: '<img src=x onerror=alert(document.domain)>',
+ status: {
+ icon: 'status_success',
+ label: 'success',
+ tooltip: '<img src=x onerror=alert(document.domain)>',
+ },
+ },
+ ],
+ title: 'test',
+ hasTriggeredBy: false,
+ action: {
+ icon: 'play',
+ title: 'Play all',
+ path: 'action',
+ },
+ });
+
+ expect(component.$el.querySelector('.js-stage-action')).not.toBeNull();
+ });
+ });
+
+ describe('without action', () => {
+ it('does not render action button', () => {
+ component = mountComponent(StageColumnComponent, {
+ groups: [
+ {
+ id: 4259,
+ name: '<img src=x onerror=alert(document.domain)>',
+ status: {
+ icon: 'status_success',
+ label: 'success',
+ tooltip: '<img src=x onerror=alert(document.domain)>',
+ },
+ },
+ ],
+ title: 'test',
+ hasTriggeredBy: false,
+ });
+
+ expect(component.$el.querySelector('.js-stage-action')).toBeNull();
+ });
+ });
});
diff --git a/spec/javascripts/pipelines/mock_data.js b/spec/javascripts/pipelines/mock_data.js
index 03ead6cd8ba..8eef9166b8d 100644
--- a/spec/javascripts/pipelines/mock_data.js
+++ b/spec/javascripts/pipelines/mock_data.js
@@ -1,5 +1,6 @@
export const pipelineWithStages = {
id: 20333396,
+ iid: 304399,
user: {
id: 128633,
name: 'Rémy Coutable',
diff --git a/spec/javascripts/pipelines/pipeline_triggerer_spec.js b/spec/javascripts/pipelines/pipeline_triggerer_spec.js
new file mode 100644
index 00000000000..8cf290f2663
--- /dev/null
+++ b/spec/javascripts/pipelines/pipeline_triggerer_spec.js
@@ -0,0 +1,54 @@
+import { mount } from '@vue/test-utils';
+import pipelineTriggerer from '~/pipelines/components/pipeline_triggerer.vue';
+
+describe('Pipelines Triggerer', () => {
+ let wrapper;
+
+ const mockData = {
+ pipeline: {
+ user: {
+ name: 'foo',
+ avatar_url: '/avatar',
+ path: '/path',
+ },
+ },
+ };
+
+ const createComponent = () => {
+ wrapper = mount(pipelineTriggerer, {
+ propsData: mockData,
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('should render a table cell', () => {
+ expect(wrapper.contains('.table-section')).toBe(true);
+ });
+
+ it('should render triggerer information when triggerer is provided', () => {
+ const link = wrapper.find('.js-pipeline-url-user');
+
+ expect(link.attributes('href')).toEqual(mockData.pipeline.user.path);
+ expect(link.find('.js-user-avatar-image-toolip').text()).toEqual(mockData.pipeline.user.name);
+ expect(link.find('img.avatar').attributes('src')).toEqual(
+ `${mockData.pipeline.user.avatar_url}?width=26`,
+ );
+ });
+
+ it('should render "API" when no triggerer is provided', () => {
+ wrapper.setProps({
+ pipeline: {
+ user: null,
+ },
+ });
+
+ expect(wrapper.find('.js-pipeline-url-api').text()).toEqual('API');
+ });
+});
diff --git a/spec/javascripts/pipelines/pipeline_url_spec.js b/spec/javascripts/pipelines/pipeline_url_spec.js
index faad49a78b0..88c0137dc58 100644
--- a/spec/javascripts/pipelines/pipeline_url_spec.js
+++ b/spec/javascripts/pipelines/pipeline_url_spec.js
@@ -13,6 +13,7 @@ describe('Pipeline Url Component', () => {
propsData: {
pipeline: {
id: 1,
+ iid: 1,
path: 'foo',
flags: {},
},
@@ -28,6 +29,7 @@ describe('Pipeline Url Component', () => {
propsData: {
pipeline: {
id: 1,
+ iid: 1,
path: 'foo',
flags: {},
},
@@ -42,59 +44,12 @@ describe('Pipeline Url Component', () => {
expect(component.$el.querySelector('.js-pipeline-url-link span').textContent).toEqual('#1');
});
- it('should render user information when a user is provided', () => {
- const mockData = {
- pipeline: {
- id: 1,
- path: 'foo',
- flags: {},
- user: {
- web_url: '/',
- name: 'foo',
- avatar_url: '/',
- path: '/',
- },
- },
- autoDevopsHelpPath: 'foo',
- };
-
- const component = new PipelineUrlComponent({
- propsData: mockData,
- }).$mount();
-
- const image = component.$el.querySelector('.js-pipeline-url-user img');
- const tooltip = component.$el.querySelector(
- '.js-pipeline-url-user .js-user-avatar-image-toolip',
- );
-
- expect(component.$el.querySelector('.js-pipeline-url-user').getAttribute('href')).toEqual(
- mockData.pipeline.user.web_url,
- );
-
- expect(tooltip.textContent.trim()).toEqual(mockData.pipeline.user.name);
- expect(image.getAttribute('src')).toEqual(`${mockData.pipeline.user.avatar_url}?width=20`);
- });
-
- it('should render "API" when no user is provided', () => {
- const component = new PipelineUrlComponent({
- propsData: {
- pipeline: {
- id: 1,
- path: 'foo',
- flags: {},
- },
- autoDevopsHelpPath: 'foo',
- },
- }).$mount();
-
- expect(component.$el.querySelector('.js-pipeline-url-api').textContent).toContain('API');
- });
-
it('should render latest, yaml invalid, merge request, and stuck flags when provided', () => {
const component = new PipelineUrlComponent({
propsData: {
pipeline: {
id: 1,
+ iid: 1,
path: 'foo',
flags: {
latest: true,
@@ -126,6 +81,7 @@ describe('Pipeline Url Component', () => {
propsData: {
pipeline: {
id: 1,
+ iid: 1,
path: 'foo',
flags: {
latest: true,
@@ -148,6 +104,7 @@ describe('Pipeline Url Component', () => {
propsData: {
pipeline: {
id: 1,
+ iid: 1,
path: 'foo',
flags: {
failure_reason: true,
diff --git a/spec/javascripts/pipelines/pipelines_table_row_spec.js b/spec/javascripts/pipelines/pipelines_table_row_spec.js
index 234fc705a81..d47504d2f54 100644
--- a/spec/javascripts/pipelines/pipelines_table_row_spec.js
+++ b/spec/javascripts/pipelines/pipelines_table_row_spec.js
@@ -80,13 +80,13 @@ describe('Pipelines Table Row', () => {
it('should render user information', () => {
expect(
component.$el
- .querySelector('.table-section:nth-child(2) a:nth-child(3)')
+ .querySelector('.table-section:nth-child(3) .js-pipeline-url-user')
.getAttribute('href'),
).toEqual(pipeline.user.path);
expect(
component.$el
- .querySelector('.table-section:nth-child(2) .js-user-avatar-image-toolip')
+ .querySelector('.table-section:nth-child(3) .js-user-avatar-image-toolip')
.textContent.trim(),
).toEqual(pipeline.user.name);
});
diff --git a/spec/javascripts/projects/project_new_spec.js b/spec/javascripts/projects/project_new_spec.js
index b61e0ac872f..106a3ba94e4 100644
--- a/spec/javascripts/projects/project_new_spec.js
+++ b/spec/javascripts/projects/project_new_spec.js
@@ -10,7 +10,17 @@ describe('New Project', () => {
setFixtures(`
<div class='toggle-import-form'>
<div class='import-url-data'>
- <input id="project_import_url" />
+ <div class="form-group">
+ <input id="project_import_url" />
+ </div>
+ <div id="import-url-auth-method">
+ <div class="form-group">
+ <input id="project-import-url-user" />
+ </div>
+ <div class="form-group">
+ <input id="project_import_url_password" />
+ </div>
+ </div>
<input id="project_name" />
<input id="project_path" />
</div>
@@ -119,7 +129,7 @@ describe('New Project', () => {
});
it('changes project path for HTTPS URL in $projectImportUrl', () => {
- $projectImportUrl.val('https://username:password@gitlab.company.com/group/project.git');
+ $projectImportUrl.val('https://gitlab.company.com/group/project.git');
projectNew.deriveProjectPathFromUrl($projectImportUrl);
diff --git a/spec/javascripts/raven/index_spec.js b/spec/javascripts/raven/index_spec.js
index a503a54029f..6b9fe923624 100644
--- a/spec/javascripts/raven/index_spec.js
+++ b/spec/javascripts/raven/index_spec.js
@@ -5,19 +5,19 @@ describe('RavenConfig options', () => {
const sentryDsn = 'sentryDsn';
const currentUserId = 'currentUserId';
const gitlabUrl = 'gitlabUrl';
- const isProduction = 'isProduction';
+ const environment = 'test';
const revision = 'revision';
let indexReturnValue;
beforeEach(() => {
window.gon = {
sentry_dsn: sentryDsn,
+ sentry_environment: environment,
current_user_id: currentUserId,
gitlab_url: gitlabUrl,
revision,
};
- process.env.NODE_ENV = isProduction;
process.env.HEAD_COMMIT_SHA = revision;
spyOn(RavenConfig, 'init');
@@ -25,12 +25,12 @@ describe('RavenConfig options', () => {
indexReturnValue = index();
});
- it('should init with .sentryDsn, .currentUserId, .whitelistUrls and .isProduction', () => {
+ it('should init with .sentryDsn, .currentUserId, .whitelistUrls and environment', () => {
expect(RavenConfig.init).toHaveBeenCalledWith({
sentryDsn,
currentUserId,
- whitelistUrls: [gitlabUrl],
- isProduction,
+ whitelistUrls: [gitlabUrl, 'webpack-internal://'],
+ environment,
release: revision,
tags: {
revision,
diff --git a/spec/javascripts/raven/raven_config_spec.js b/spec/javascripts/raven/raven_config_spec.js
index 5cc59cc28d3..af634a0c196 100644
--- a/spec/javascripts/raven/raven_config_spec.js
+++ b/spec/javascripts/raven/raven_config_spec.js
@@ -69,8 +69,8 @@ describe('RavenConfig', () => {
let ravenConfig;
const options = {
sentryDsn: '//sentryDsn',
- whitelistUrls: ['//gitlabUrl'],
- isProduction: true,
+ whitelistUrls: ['//gitlabUrl', 'webpack-internal://'],
+ environment: 'test',
release: 'revision',
tags: {
revision: 'revision',
@@ -95,7 +95,7 @@ describe('RavenConfig', () => {
release: options.release,
tags: options.tags,
whitelistUrls: options.whitelistUrls,
- environment: 'production',
+ environment: 'test',
ignoreErrors: ravenConfig.IGNORE_ERRORS,
ignoreUrls: ravenConfig.IGNORE_URLS,
shouldSendCallback: jasmine.any(Function),
@@ -106,8 +106,8 @@ describe('RavenConfig', () => {
expect(raven.install).toHaveBeenCalled();
});
- it('should set .environment to development if isProduction is false', () => {
- ravenConfig.options.isProduction = false;
+ it('should set environment from options', () => {
+ ravenConfig.options.environment = 'development';
RavenConfig.configure.call(ravenConfig);
diff --git a/spec/javascripts/reports/components/modal_spec.js b/spec/javascripts/reports/components/modal_spec.js
index 6b8471381de..d42c509e5b5 100644
--- a/spec/javascripts/reports/components/modal_spec.js
+++ b/spec/javascripts/reports/components/modal_spec.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import component from '~/reports/components/modal.vue';
import state from '~/reports/store/state';
import mountComponent from '../../helpers/vue_mount_component_helper';
-import { trimText } from '../../helpers/vue_component_helper';
+import { trimText } from '../../helpers/text_helper';
describe('Grouped Test Reports Modal', () => {
const Component = Vue.extend(component);
diff --git a/spec/javascripts/reports/components/test_issue_body_spec.js b/spec/javascripts/reports/components/test_issue_body_spec.js
index 32baf904ad7..9c1cec4c9bc 100644
--- a/spec/javascripts/reports/components/test_issue_body_spec.js
+++ b/spec/javascripts/reports/components/test_issue_body_spec.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import component from '~/reports/components/test_issue_body.vue';
import createStore from '~/reports/store';
import { mountComponentWithStore } from '../../helpers/vue_mount_component_helper';
-import { trimText } from '../../helpers/vue_component_helper';
+import { trimText } from '../../helpers/text_helper';
import { issue } from '../mock_data/mock_data';
describe('Test Issue body', () => {
diff --git a/spec/javascripts/sidebar/assignees_spec.js b/spec/javascripts/sidebar/assignees_spec.js
index 47fee5d2b21..4ae2141d5f0 100644
--- a/spec/javascripts/sidebar/assignees_spec.js
+++ b/spec/javascripts/sidebar/assignees_spec.js
@@ -24,12 +24,12 @@ describe('Assignee component', () => {
const collapsed = component.$el.querySelector('.sidebar-collapsed-icon');
expect(collapsed.childElementCount).toEqual(1);
- expect(collapsed.children[0].getAttribute('aria-label')).toEqual('No Assignee');
+ expect(collapsed.children[0].getAttribute('aria-label')).toEqual('None');
expect(collapsed.children[0].classList.contains('fa')).toEqual(true);
expect(collapsed.children[0].classList.contains('fa-user')).toEqual(true);
});
- it('displays only "No assignee" when no users are assigned and the issue is read-only', () => {
+ it('displays only "None" when no users are assigned and the issue is read-only', () => {
component = new AssigneeComponent({
propsData: {
rootPath: 'http://localhost:3000',
@@ -39,11 +39,11 @@ describe('Assignee component', () => {
}).$mount();
const componentTextNoUsers = component.$el.querySelector('.assign-yourself').innerText.trim();
- expect(componentTextNoUsers).toBe('No assignee');
+ expect(componentTextNoUsers).toBe('None');
expect(componentTextNoUsers.indexOf('assign yourself')).toEqual(-1);
});
- it('displays only "No assignee" when no users are assigned and the issue can be edited', () => {
+ it('displays only "None" when no users are assigned and the issue can be edited', () => {
component = new AssigneeComponent({
propsData: {
rootPath: 'http://localhost:3000',
@@ -53,7 +53,7 @@ describe('Assignee component', () => {
}).$mount();
const componentTextNoUsers = component.$el.querySelector('.assign-yourself').innerText.trim();
- expect(componentTextNoUsers.indexOf('No assignee')).toEqual(0);
+ expect(componentTextNoUsers.indexOf('None')).toEqual(0);
expect(componentTextNoUsers.indexOf('assign yourself')).toBeGreaterThan(0);
});
diff --git a/spec/javascripts/test_bundle.js b/spec/javascripts/test_bundle.js
index 87ef0885d8c..8c80a425581 100644
--- a/spec/javascripts/test_bundle.js
+++ b/spec/javascripts/test_bundle.js
@@ -111,7 +111,7 @@ let longRunningTestTimeoutHandle;
beforeEach(done => {
longRunningTestTimeoutHandle = setTimeout(() => {
done.fail('Test is running too long!');
- }, 2000);
+ }, 4000);
done();
});
diff --git a/spec/javascripts/test_constants.js b/spec/javascripts/test_constants.js
index a820dd2d09c..77c206585fe 100644
--- a/spec/javascripts/test_constants.js
+++ b/spec/javascripts/test_constants.js
@@ -1,7 +1,9 @@
-export const FIXTURES_PATH = '/base/spec/javascripts/fixtures';
+export const FIXTURES_PATH = `/base/${
+ process.env.IS_GITLAB_EE ? 'ee/' : ''
+}spec/javascripts/fixtures`;
export const TEST_HOST = 'http://test.host';
-export const DUMMY_IMAGE_URL = `${FIXTURES_PATH}/one_white_pixel.png`;
+export const DUMMY_IMAGE_URL = `${FIXTURES_PATH}/static/images/one_white_pixel.png`;
-export const GREEN_BOX_IMAGE_URL = `${FIXTURES_PATH}/images/green_box.png`;
-export const RED_BOX_IMAGE_URL = `${FIXTURES_PATH}/images/red_box.png`;
+export const GREEN_BOX_IMAGE_URL = `${FIXTURES_PATH}/static/images/green_box.png`;
+export const RED_BOX_IMAGE_URL = `${FIXTURES_PATH}/static/images/red_box.png`;
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_alert_message_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_alert_message_spec.js
index f115cb457e5..8ec17efffb9 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_alert_message_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_alert_message_spec.js
@@ -11,6 +11,7 @@ describe('MrWidgetAlertMessage', () => {
wrapper = shallowMount(localVue.extend(MrWidgetAlertMessage), {
propsData: {},
localVue,
+ sync: false,
});
});
@@ -19,45 +20,58 @@ describe('MrWidgetAlertMessage', () => {
});
describe('when type is not provided', () => {
- it('should render a red message', () => {
- expect(wrapper.classes()).toContain('danger_message');
- expect(wrapper.classes()).not.toContain('warning_message');
+ it('should render a red message', done => {
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.classes()).toContain('danger_message');
+ expect(wrapper.classes()).not.toContain('warning_message');
+ done();
+ });
});
});
describe('when type === "danger"', () => {
- it('should render a red message', () => {
+ it('should render a red message', done => {
wrapper.setProps({ type: 'danger' });
-
- expect(wrapper.classes()).toContain('danger_message');
- expect(wrapper.classes()).not.toContain('warning_message');
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.classes()).toContain('danger_message');
+ expect(wrapper.classes()).not.toContain('warning_message');
+ done();
+ });
});
});
describe('when type === "warning"', () => {
- it('should render a red message', () => {
+ it('should render a red message', done => {
wrapper.setProps({ type: 'warning' });
-
- expect(wrapper.classes()).toContain('warning_message');
- expect(wrapper.classes()).not.toContain('danger_message');
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.classes()).toContain('warning_message');
+ expect(wrapper.classes()).not.toContain('danger_message');
+ done();
+ });
});
});
describe('when helpPath is not provided', () => {
- it('should not render a help icon/link', () => {
- const link = wrapper.find(GlLink);
+ it('should not render a help icon/link', done => {
+ wrapper.vm.$nextTick(() => {
+ const link = wrapper.find(GlLink);
- expect(link.exists()).toBe(false);
+ expect(link.exists()).toBe(false);
+ done();
+ });
});
});
describe('when helpPath is provided', () => {
- it('should render a help icon/link', () => {
+ it('should render a help icon/link', done => {
wrapper.setProps({ helpPath: '/path/to/help/docs' });
- const link = wrapper.find(GlLink);
+ wrapper.vm.$nextTick(() => {
+ const link = wrapper.find(GlLink);
- expect(link.exists()).toBe(true);
- expect(link.attributes().href).toBe('/path/to/help/docs');
+ expect(link.exists()).toBe(true);
+ expect(link.attributes().href).toBe('/path/to/help/docs');
+ done();
+ });
});
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js
index e5155573f6f..dfbc68c48b9 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js
@@ -1,4 +1,4 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { mount, createLocalVue } from '@vue/test-utils';
import MrWidgetPipelineContainer from '~/vue_merge_request_widget/components/mr_widget_pipeline_container.vue';
import MrWidgetPipeline from '~/vue_merge_request_widget/components/mr_widget_pipeline.vue';
import { mockStore } from '../mock_data';
@@ -9,7 +9,7 @@ describe('MrWidgetPipelineContainer', () => {
const factory = (props = {}) => {
const localVue = createLocalVue();
- wrapper = shallowMount(localVue.extend(MrWidgetPipelineContainer), {
+ wrapper = mount(localVue.extend(MrWidgetPipelineContainer), {
propsData: {
mr: Object.assign({}, mockStore),
...props,
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
index de213210cfc..a2308b0dfdb 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import pipelineComponent from '~/vue_merge_request_widget/components/mr_widget_pipeline.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import { trimText } from 'spec/helpers/vue_component_helper';
+import { trimText } from 'spec/helpers/text_helper';
import mockData from '../mock_data';
describe('MRWidgetPipeline', () => {
@@ -78,6 +78,19 @@ describe('MRWidgetPipeline', () => {
);
});
+ it('should render CI error when no pipeline is provided', () => {
+ vm = mountComponent(Component, {
+ pipeline: {},
+ hasCi: true,
+ ciStatus: 'success',
+ troubleshootingDocsPath: 'help',
+ });
+
+ expect(vm.$el.querySelector('.media-body').textContent.trim()).toContain(
+ 'Could not retrieve the pipeline status. For troubleshooting steps, read the documentation.',
+ );
+ });
+
describe('with a pipeline', () => {
beforeEach(() => {
vm = mountComponent(Component, {
@@ -90,7 +103,7 @@ describe('MRWidgetPipeline', () => {
it('should render pipeline ID', () => {
expect(vm.$el.querySelector('.pipeline-id').textContent.trim()).toEqual(
- `#${mockData.pipeline.id}`,
+ `#${mockData.pipeline.id} (#${mockData.pipeline.iid})`,
);
});
@@ -137,7 +150,7 @@ describe('MRWidgetPipeline', () => {
it('should render pipeline ID', () => {
expect(vm.$el.querySelector('.pipeline-id').textContent.trim()).toEqual(
- `#${mockData.pipeline.id}`,
+ `#${mockData.pipeline.id} (#${mockData.pipeline.iid})`,
);
});
@@ -209,9 +222,9 @@ describe('MRWidgetPipeline', () => {
sourceBranchLink: mockCopy.source_branch_link,
});
- const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${
- pipeline.commit.short_id
- } on ${mockCopy.source_branch_link}`;
+ const expected = `Pipeline #${pipeline.id} (#${pipeline.iid}) ${
+ pipeline.details.status.label
+ } for ${pipeline.commit.short_id} on ${mockCopy.source_branch_link}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info-container').innerText);
@@ -234,11 +247,11 @@ describe('MRWidgetPipeline', () => {
sourceBranchLink: mockCopy.source_branch_link,
});
- const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${
- pipeline.commit.short_id
- } on !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch} into ${
- pipeline.merge_request.target_branch
- }`;
+ const expected = `Pipeline #${pipeline.id} (#${pipeline.iid}) ${
+ pipeline.details.status.label
+ } for ${pipeline.commit.short_id} on !${pipeline.merge_request.iid} with ${
+ pipeline.merge_request.source_branch
+ } into ${pipeline.merge_request.target_branch}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info-container').innerText);
@@ -261,9 +274,11 @@ describe('MRWidgetPipeline', () => {
sourceBranchLink: mockCopy.source_branch_link,
});
- const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${
- pipeline.commit.short_id
- } on !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch}`;
+ const expected = `Pipeline #${pipeline.id} (#${pipeline.iid}) ${
+ pipeline.details.status.label
+ } for ${pipeline.commit.short_id} on !${pipeline.merge_request.iid} with ${
+ pipeline.merge_request.source_branch
+ }`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info-container').innerText);
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js
new file mode 100644
index 00000000000..2ea8c169add
--- /dev/null
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js
@@ -0,0 +1,230 @@
+import Vue from 'vue';
+import autoMergeEnabledComponent from '~/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue';
+import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
+import eventHub from '~/vue_merge_request_widget/event_hub';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import { trimText } from 'spec/helpers/text_helper';
+import { MWPS_MERGE_STRATEGY } from '~/vue_merge_request_widget/constants';
+
+describe('MRWidgetAutoMergeEnabled', () => {
+ let vm;
+ const targetBranchPath = '/foo/bar';
+ const targetBranch = 'foo';
+ const sha = '1EA2EZ34';
+
+ beforeEach(() => {
+ const Component = Vue.extend(autoMergeEnabledComponent);
+ spyOn(eventHub, '$emit');
+
+ vm = mountComponent(Component, {
+ mr: {
+ shouldRemoveSourceBranch: false,
+ canRemoveSourceBranch: true,
+ canCancelAutomaticMerge: true,
+ mergeUserId: 1,
+ currentUserId: 1,
+ setToAutoMergeBy: {},
+ sha,
+ targetBranchPath,
+ targetBranch,
+ autoMergeStrategy: MWPS_MERGE_STRATEGY,
+ },
+ service: new MRWidgetService({}),
+ });
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('computed', () => {
+ describe('canRemoveSourceBranch', () => {
+ it('should return true when user is able to remove source branch', () => {
+ expect(vm.canRemoveSourceBranch).toBeTruthy();
+ });
+
+ it('should return false when user id is not the same with who set the MWPS', () => {
+ vm.mr.mergeUserId = 2;
+
+ expect(vm.canRemoveSourceBranch).toBeFalsy();
+
+ vm.mr.currentUserId = 2;
+
+ expect(vm.canRemoveSourceBranch).toBeTruthy();
+
+ vm.mr.currentUserId = 3;
+
+ expect(vm.canRemoveSourceBranch).toBeFalsy();
+ });
+
+ it('should return false when shouldRemoveSourceBranch set to false', () => {
+ vm.mr.shouldRemoveSourceBranch = true;
+
+ expect(vm.canRemoveSourceBranch).toBeFalsy();
+ });
+
+ it('should return false if user is not able to remove the source branch', () => {
+ vm.mr.canRemoveSourceBranch = false;
+
+ expect(vm.canRemoveSourceBranch).toBeFalsy();
+ });
+ });
+
+ describe('statusTextBeforeAuthor', () => {
+ it('should return "Set by" if the MWPS is selected', () => {
+ Vue.set(vm.mr, 'autoMergeStrategy', MWPS_MERGE_STRATEGY);
+
+ expect(vm.statusTextBeforeAuthor).toBe('Set by');
+ });
+ });
+
+ describe('statusTextAfterAuthor', () => {
+ it('should return "to be merged automatically..." if MWPS is selected', () => {
+ Vue.set(vm.mr, 'autoMergeStrategy', MWPS_MERGE_STRATEGY);
+
+ expect(vm.statusTextAfterAuthor).toBe(
+ 'to be merged automatically when the pipeline succeeds',
+ );
+ });
+ });
+
+ describe('cancelButtonText', () => {
+ it('should return "Cancel automatic merge" if MWPS is selected', () => {
+ Vue.set(vm.mr, 'autoMergeStrategy', MWPS_MERGE_STRATEGY);
+
+ expect(vm.cancelButtonText).toBe('Cancel automatic merge');
+ });
+ });
+ });
+
+ describe('methods', () => {
+ describe('cancelAutomaticMerge', () => {
+ it('should set flag and call service then tell main component to update the widget with data', done => {
+ const mrObj = {
+ is_new_mr_data: true,
+ };
+ spyOn(vm.service, 'cancelAutomaticMerge').and.returnValue(
+ new Promise(resolve => {
+ resolve({
+ data: mrObj,
+ });
+ }),
+ );
+
+ vm.cancelAutomaticMerge();
+ setTimeout(() => {
+ expect(vm.isCancellingAutoMerge).toBeTruthy();
+ expect(eventHub.$emit).toHaveBeenCalledWith('UpdateWidgetData', mrObj);
+ done();
+ }, 333);
+ });
+ });
+
+ describe('removeSourceBranch', () => {
+ it('should set flag and call service then request main component to update the widget', done => {
+ spyOn(vm.service, 'merge').and.returnValue(
+ Promise.resolve({
+ data: {
+ status: MWPS_MERGE_STRATEGY,
+ },
+ }),
+ );
+
+ vm.removeSourceBranch();
+ setTimeout(() => {
+ expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
+ expect(vm.service.merge).toHaveBeenCalledWith({
+ sha,
+ auto_merge_strategy: MWPS_MERGE_STRATEGY,
+ should_remove_source_branch: true,
+ });
+ done();
+ }, 333);
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('should have correct elements', () => {
+ expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
+ expect(vm.$el.innerText).toContain('to be merged automatically when the pipeline succeeds');
+
+ expect(vm.$el.innerText).toContain('The changes will be merged into');
+ expect(vm.$el.innerText).toContain(targetBranch);
+ expect(vm.$el.innerText).toContain('The source branch will not be deleted');
+ expect(vm.$el.querySelector('.js-cancel-auto-merge').innerText).toContain(
+ 'Cancel automatic merge',
+ );
+
+ expect(vm.$el.querySelector('.js-cancel-auto-merge').getAttribute('disabled')).toBeFalsy();
+ expect(vm.$el.querySelector('.js-remove-source-branch').innerText).toContain(
+ 'Delete source branch',
+ );
+
+ expect(vm.$el.querySelector('.js-remove-source-branch').getAttribute('disabled')).toBeFalsy();
+ });
+
+ it('should disable cancel auto merge button when the action is in progress', done => {
+ vm.isCancellingAutoMerge = true;
+
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelector('.js-cancel-auto-merge').getAttribute('disabled')).toBeTruthy();
+ done();
+ });
+ });
+
+ it('should show source branch will be deleted text when it source branch set to remove', done => {
+ vm.mr.shouldRemoveSourceBranch = true;
+
+ Vue.nextTick(() => {
+ const normalizedText = vm.$el.innerText.replace(/\s+/g, ' ');
+
+ expect(normalizedText).toContain('The source branch will be deleted');
+ expect(normalizedText).not.toContain('The source branch will not be deleted');
+ done();
+ });
+ });
+
+ it('should not show delete source branch button when user not able to delete source branch', done => {
+ vm.mr.currentUserId = 4;
+
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelector('.js-remove-source-branch')).toEqual(null);
+ done();
+ });
+ });
+
+ it('should disable delete source branch button when the action is in progress', done => {
+ vm.isRemovingSourceBranch = true;
+
+ Vue.nextTick(() => {
+ expect(
+ vm.$el.querySelector('.js-remove-source-branch').getAttribute('disabled'),
+ ).toBeTruthy();
+ done();
+ });
+ });
+
+ it('should render the status text as "...to merged automatically" if MWPS is selected', done => {
+ Vue.set(vm.mr, 'autoMergeStrategy', MWPS_MERGE_STRATEGY);
+
+ Vue.nextTick(() => {
+ const statusText = trimText(vm.$el.querySelector('.js-status-text-after-author').innerText);
+
+ expect(statusText).toBe('to be merged automatically when the pipeline succeeds');
+ done();
+ });
+ });
+
+ it('should render the cancel button as "Cancel automatic merge" if MWPS is selected', done => {
+ Vue.set(vm.mr, 'autoMergeStrategy', MWPS_MERGE_STRATEGY);
+
+ Vue.nextTick(() => {
+ const cancelButtonText = trimText(vm.$el.querySelector('.js-cancel-auto-merge').innerText);
+
+ expect(cancelButtonText).toBe('Cancel automatic merge');
+ done();
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
index 0ddbdf67d8b..55073f5537c 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import ConflictsComponent from '~/vue_merge_request_widget/components/states/mr_widget_conflicts.vue';
-import { removeBreakLine } from 'spec/helpers/vue_component_helper';
+import { removeBreakLine } from 'spec/helpers/text_helper';
describe('MRWidgetConflicts', () => {
let vm;
@@ -23,11 +23,78 @@ describe('MRWidgetConflicts', () => {
vm.destroy();
});
- describe('when allowed to merge', () => {
+ // There are two permissions we need to consider:
+ //
+ // 1. Is the user allowed to merge to the target branch?
+ // 2. Is the user allowed to push to the source branch?
+ //
+ // This yields 4 possible permutations that we need to test, and
+ // we test them below. A user who can push to the source
+ // branch should be allowed to resolve conflicts. This is
+ // consistent with what the backend does.
+ describe('when allowed to merge but not allowed to push to source branch', () => {
beforeEach(() => {
createComponent({
mr: {
canMerge: true,
+ canPushToSourceBranch: false,
+ conflictResolutionPath: path,
+ conflictsDocsPath: '',
+ },
+ });
+ });
+
+ it('should tell you about conflicts without bothering other people', () => {
+ expect(vm.text()).toContain('There are merge conflicts');
+ expect(vm.text()).not.toContain('ask someone with write access');
+ });
+
+ it('should not allow you to resolve the conflicts', () => {
+ expect(vm.text()).not.toContain('Resolve conflicts');
+ });
+
+ it('should have merge buttons', () => {
+ const mergeLocallyButton = vm.find('.js-merge-locally-button');
+
+ expect(mergeLocallyButton.text()).toContain('Merge locally');
+ });
+ });
+
+ describe('when not allowed to merge but allowed to push to source branch', () => {
+ beforeEach(() => {
+ createComponent({
+ mr: {
+ canMerge: false,
+ canPushToSourceBranch: true,
+ conflictResolutionPath: path,
+ conflictsDocsPath: '',
+ },
+ });
+ });
+
+ it('should tell you about conflicts', () => {
+ expect(vm.text()).toContain('There are merge conflicts');
+ expect(vm.text()).toContain('ask someone with write access');
+ });
+
+ it('should allow you to resolve the conflicts', () => {
+ const resolveButton = vm.find('.js-resolve-conflicts-button');
+
+ expect(resolveButton.text()).toContain('Resolve conflicts');
+ expect(resolveButton.attributes('href')).toEqual(path);
+ });
+
+ it('should not have merge buttons', () => {
+ expect(vm.text()).not.toContain('Merge locally');
+ });
+ });
+
+ describe('when allowed to merge and push to source branch', () => {
+ beforeEach(() => {
+ createComponent({
+ mr: {
+ canMerge: true,
+ canPushToSourceBranch: true,
conflictResolutionPath: path,
conflictsDocsPath: '',
},
@@ -53,11 +120,12 @@ describe('MRWidgetConflicts', () => {
});
});
- describe('when user does not have permission to merge', () => {
+ describe('when user does not have permission to push to source branch', () => {
it('should show proper message', () => {
createComponent({
mr: {
canMerge: false,
+ canPushToSourceBranch: false,
conflictsDocsPath: '',
},
});
@@ -74,6 +142,7 @@ describe('MRWidgetConflicts', () => {
createComponent({
mr: {
canMerge: false,
+ canPushToSourceBranch: false,
conflictsDocsPath: '',
},
});
@@ -115,6 +184,7 @@ describe('MRWidgetConflicts', () => {
createComponent({
mr: {
canMerge: true,
+ canPushToSourceBranch: true,
conflictResolutionPath: gl.TEST_HOST,
sourceBranchProtected: true,
conflictsDocsPath: '',
@@ -136,6 +206,7 @@ describe('MRWidgetConflicts', () => {
createComponent({
mr: {
canMerge: true,
+ canPushToSourceBranch: true,
conflictResolutionPath: gl.TEST_HOST,
sourceBranchProtected: false,
conflictsDocsPath: '',
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js
deleted file mode 100644
index b9718a78fa4..00000000000
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js
+++ /dev/null
@@ -1,178 +0,0 @@
-import Vue from 'vue';
-import mwpsComponent from '~/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue';
-import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
-import eventHub from '~/vue_merge_request_widget/event_hub';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-describe('MRWidgetMergeWhenPipelineSucceeds', () => {
- let vm;
- const targetBranchPath = '/foo/bar';
- const targetBranch = 'foo';
- const sha = '1EA2EZ34';
-
- beforeEach(() => {
- const Component = Vue.extend(mwpsComponent);
- spyOn(eventHub, '$emit');
-
- vm = mountComponent(Component, {
- mr: {
- shouldRemoveSourceBranch: false,
- canRemoveSourceBranch: true,
- canCancelAutomaticMerge: true,
- mergeUserId: 1,
- currentUserId: 1,
- setToMWPSBy: {},
- sha,
- targetBranchPath,
- targetBranch,
- },
- service: new MRWidgetService({}),
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('computed', () => {
- describe('canRemoveSourceBranch', () => {
- it('should return true when user is able to remove source branch', () => {
- expect(vm.canRemoveSourceBranch).toBeTruthy();
- });
-
- it('should return false when user id is not the same with who set the MWPS', () => {
- vm.mr.mergeUserId = 2;
-
- expect(vm.canRemoveSourceBranch).toBeFalsy();
-
- vm.mr.currentUserId = 2;
-
- expect(vm.canRemoveSourceBranch).toBeTruthy();
-
- vm.mr.currentUserId = 3;
-
- expect(vm.canRemoveSourceBranch).toBeFalsy();
- });
-
- it('should return false when shouldRemoveSourceBranch set to false', () => {
- vm.mr.shouldRemoveSourceBranch = true;
-
- expect(vm.canRemoveSourceBranch).toBeFalsy();
- });
-
- it('should return false if user is not able to remove the source branch', () => {
- vm.mr.canRemoveSourceBranch = false;
-
- expect(vm.canRemoveSourceBranch).toBeFalsy();
- });
- });
- });
-
- describe('methods', () => {
- describe('cancelAutomaticMerge', () => {
- it('should set flag and call service then tell main component to update the widget with data', done => {
- const mrObj = {
- is_new_mr_data: true,
- };
- spyOn(vm.service, 'cancelAutomaticMerge').and.returnValue(
- new Promise(resolve => {
- resolve({
- data: mrObj,
- });
- }),
- );
-
- vm.cancelAutomaticMerge();
- setTimeout(() => {
- expect(vm.isCancellingAutoMerge).toBeTruthy();
- expect(eventHub.$emit).toHaveBeenCalledWith('UpdateWidgetData', mrObj);
- done();
- }, 333);
- });
- });
-
- describe('removeSourceBranch', () => {
- it('should set flag and call service then request main component to update the widget', done => {
- spyOn(vm.service, 'merge').and.returnValue(
- Promise.resolve({
- data: {
- status: 'merge_when_pipeline_succeeds',
- },
- }),
- );
-
- vm.removeSourceBranch();
- setTimeout(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
- expect(vm.service.merge).toHaveBeenCalledWith({
- sha,
- merge_when_pipeline_succeeds: true,
- should_remove_source_branch: true,
- });
- done();
- }, 333);
- });
- });
- });
-
- describe('template', () => {
- it('should have correct elements', () => {
- expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
- expect(vm.$el.innerText).toContain('to be merged automatically when the pipeline succeeds');
- expect(vm.$el.innerText).toContain('The changes will be merged into');
- expect(vm.$el.innerText).toContain(targetBranch);
- expect(vm.$el.innerText).toContain('The source branch will not be deleted');
- expect(vm.$el.querySelector('.js-cancel-auto-merge').innerText).toContain(
- 'Cancel automatic merge',
- );
-
- expect(vm.$el.querySelector('.js-cancel-auto-merge').getAttribute('disabled')).toBeFalsy();
- expect(vm.$el.querySelector('.js-remove-source-branch').innerText).toContain(
- 'Delete source branch',
- );
-
- expect(vm.$el.querySelector('.js-remove-source-branch').getAttribute('disabled')).toBeFalsy();
- });
-
- it('should disable cancel auto merge button when the action is in progress', done => {
- vm.isCancellingAutoMerge = true;
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.js-cancel-auto-merge').getAttribute('disabled')).toBeTruthy();
- done();
- });
- });
-
- it('should show source branch will be deleted text when it source branch set to remove', done => {
- vm.mr.shouldRemoveSourceBranch = true;
-
- Vue.nextTick(() => {
- const normalizedText = vm.$el.innerText.replace(/\s+/g, ' ');
-
- expect(normalizedText).toContain('The source branch will be deleted');
- expect(normalizedText).not.toContain('The source branch will not be deleted');
- done();
- });
- });
-
- it('should not show delete source branch button when user not able to delete source branch', done => {
- vm.mr.currentUserId = 4;
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.js-remove-source-branch')).toEqual(null);
- done();
- });
- });
-
- it('should disable delete source branch button when the action is in progress', done => {
- vm.isRemovingSourceBranch = true;
-
- Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.js-remove-source-branch').getAttribute('disabled'),
- ).toBeTruthy();
- done();
- });
- });
- });
-});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js
index 477041fa383..1d2f3e41509 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import pipelineBlockedComponent from '~/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import { removeBreakLine } from 'spec/helpers/vue_component_helper';
+import { removeBreakLine } from 'spec/helpers/text_helper';
describe('MRWidgetPipelineBlocked', () => {
let vm;
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js
index f7523a01963..3e4ce2c3696 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
import PipelineFailed from '~/vue_merge_request_widget/components/states/pipeline_failed.vue';
-import { removeBreakLine } from 'spec/helpers/vue_component_helper';
+import { removeBreakLine } from 'spec/helpers/text_helper';
describe('PipelineFailed', () => {
describe('template', () => {
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
index 368c997d318..bb76616be56 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
@@ -6,6 +6,7 @@ import CommitEdit from '~/vue_merge_request_widget/components/states/commit_edit
import CommitMessageDropdown from '~/vue_merge_request_widget/components/states/commit_message_dropdown.vue';
import eventHub from '~/vue_merge_request_widget/event_hub';
import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { MWPS_MERGE_STRATEGY, ATMTWPS_MERGE_STRATEGY } from '~/vue_merge_request_widget/constants';
const commitMessage = 'This is the commit message';
const squashCommitMessage = 'This is the squash commit message';
@@ -29,6 +30,8 @@ const createTestMr = customConfig => {
shouldRemoveSourceBranch: true,
canRemoveSourceBranch: false,
targetBranch: 'master',
+ preferredAutoMergeStrategy: MWPS_MERGE_STRATEGY,
+ availableAutoMergeStrategies: [MWPS_MERGE_STRATEGY],
};
Object.assign(mr, customConfig.mr);
@@ -80,7 +83,6 @@ describe('ReadyToMerge', () => {
it('should have default data', () => {
expect(vm.mergeWhenBuildSucceeds).toBeFalsy();
expect(vm.useCommitMessageWithDescription).toBeFalsy();
- expect(vm.setToMergeWhenPipelineSucceeds).toBeFalsy();
expect(vm.showCommitMessageEditor).toBeFalsy();
expect(vm.isMakingRequest).toBeFalsy();
expect(vm.isMergingImmediately).toBeFalsy();
@@ -91,47 +93,51 @@ describe('ReadyToMerge', () => {
});
describe('computed', () => {
- describe('shouldShowMergeWhenPipelineSucceedsText', () => {
- it('should return true with active pipeline', () => {
- vm.mr.isPipelineActive = true;
+ describe('isAutoMergeAvailable', () => {
+ it('should return true when at least one merge strategy is available', () => {
+ vm.mr.availableAutoMergeStrategies = [MWPS_MERGE_STRATEGY];
- expect(vm.shouldShowMergeWhenPipelineSucceedsText).toBeTruthy();
+ expect(vm.isAutoMergeAvailable).toBe(true);
});
- it('should return false with inactive pipeline', () => {
- vm.mr.isPipelineActive = false;
+ it('should return false when no merge strategies are available', () => {
+ vm.mr.availableAutoMergeStrategies = [];
- expect(vm.shouldShowMergeWhenPipelineSucceedsText).toBeFalsy();
+ expect(vm.isAutoMergeAvailable).toBe(false);
});
});
describe('status', () => {
it('defaults to success', () => {
- vm.mr.pipeline = true;
+ Vue.set(vm.mr, 'pipeline', true);
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
expect(vm.status).toEqual('success');
});
it('returns failed when MR has CI but also has an unknown status', () => {
- vm.mr.hasCI = true;
+ Vue.set(vm.mr, 'hasCI', true);
expect(vm.status).toEqual('failed');
});
it('returns default when MR has no pipeline', () => {
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
+
expect(vm.status).toEqual('success');
});
it('returns pending when pipeline is active', () => {
- vm.mr.pipeline = {};
- vm.mr.isPipelineActive = true;
+ Vue.set(vm.mr, 'pipeline', {});
+ Vue.set(vm.mr, 'isPipelineActive', true);
expect(vm.status).toEqual('pending');
});
it('returns failed when pipeline is failed', () => {
- vm.mr.pipeline = {};
- vm.mr.isPipelineFailed = true;
+ Vue.set(vm.mr, 'pipeline', {});
+ Vue.set(vm.mr, 'isPipelineFailed', true);
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
expect(vm.status).toEqual('failed');
});
@@ -143,18 +149,20 @@ describe('ReadyToMerge', () => {
const inActionClass = `${defaultClass} btn-info`;
it('defaults to success class', () => {
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
+
expect(vm.mergeButtonClass).toEqual(defaultClass);
});
it('returns success class for success status', () => {
- vm.mr.pipeline = true;
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
+ Vue.set(vm.mr, 'pipeline', true);
expect(vm.mergeButtonClass).toEqual(defaultClass);
});
it('returns info class for pending status', () => {
- vm.mr.pipeline = {};
- vm.mr.isPipelineActive = true;
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', [ATMTWPS_MERGE_STRATEGY]);
expect(vm.mergeButtonClass).toEqual(inActionClass);
});
@@ -198,69 +206,82 @@ describe('ReadyToMerge', () => {
});
describe('mergeButtonText', () => {
- it('should return Merge', () => {
+ it('should return "Merge" when no auto merge strategies are available', () => {
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
+
expect(vm.mergeButtonText).toEqual('Merge');
});
- it('should return Merge in progress', () => {
- vm.isMergingImmediately = true;
+ it('should return "Merge in progress"', () => {
+ Vue.set(vm, 'isMergingImmediately', true);
expect(vm.mergeButtonText).toEqual('Merge in progress');
});
- it('should return Merge when pipeline succeeds', () => {
- vm.isMergingImmediately = false;
- vm.mr.isPipelineActive = true;
+ it('should return "Merge when pipeline succeeds" when the MWPS auto merge strategy is available', () => {
+ Vue.set(vm, 'isMergingImmediately', false);
+ Vue.set(vm.mr, 'preferredAutoMergeStrategy', MWPS_MERGE_STRATEGY);
expect(vm.mergeButtonText).toEqual('Merge when pipeline succeeds');
});
});
+ describe('autoMergeText', () => {
+ it('should return Merge when pipeline succeeds', () => {
+ Vue.set(vm.mr, 'preferredAutoMergeStrategy', MWPS_MERGE_STRATEGY);
+
+ expect(vm.autoMergeText).toEqual('Merge when pipeline succeeds');
+ });
+ });
+
describe('shouldShowMergeOptionsDropdown', () => {
- it('should return false with initial data', () => {
- expect(vm.shouldShowMergeOptionsDropdown).toBeFalsy();
+ it('should return false when no auto merge strategies are available', () => {
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
+
+ expect(vm.shouldShowMergeOptionsDropdown).toBe(false);
});
- it('should return true when pipeline active', () => {
- vm.mr.isPipelineActive = true;
+ it('should return true when at least one auto merge strategy is available', () => {
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', [ATMTWPS_MERGE_STRATEGY]);
- expect(vm.shouldShowMergeOptionsDropdown).toBeTruthy();
+ expect(vm.shouldShowMergeOptionsDropdown).toBe(true);
});
it('should return false when pipeline active but only merge when pipeline succeeds set in project options', () => {
- vm.mr.isPipelineActive = true;
- vm.mr.onlyAllowMergeIfPipelineSucceeds = true;
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', [ATMTWPS_MERGE_STRATEGY]);
+ Vue.set(vm.mr, 'onlyAllowMergeIfPipelineSucceeds', true);
- expect(vm.shouldShowMergeOptionsDropdown).toBeFalsy();
+ expect(vm.shouldShowMergeOptionsDropdown).toBe(false);
});
});
describe('isMergeButtonDisabled', () => {
it('should return false with initial data', () => {
- vm.mr.isMergeAllowed = true;
+ Vue.set(vm.mr, 'isMergeAllowed', true);
- expect(vm.isMergeButtonDisabled).toBeFalsy();
+ expect(vm.isMergeButtonDisabled).toBe(false);
});
it('should return true when there is no commit message', () => {
- vm.mr.isMergeAllowed = true;
- vm.commitMessage = '';
+ Vue.set(vm.mr, 'isMergeAllowed', true);
+ Vue.set(vm, 'commitMessage', '');
- expect(vm.isMergeButtonDisabled).toBeTruthy();
+ expect(vm.isMergeButtonDisabled).toBe(true);
});
it('should return true if merge is not allowed', () => {
- vm.mr.isMergeAllowed = false;
- vm.mr.onlyAllowMergeIfPipelineSucceeds = true;
+ Vue.set(vm.mr, 'isMergeAllowed', false);
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
+ Vue.set(vm.mr, 'onlyAllowMergeIfPipelineSucceeds', true);
- expect(vm.isMergeButtonDisabled).toBeTruthy();
+ expect(vm.isMergeButtonDisabled).toBe(true);
});
it('should return true when the vm instance is making request', () => {
- vm.mr.isMergeAllowed = true;
- vm.isMakingRequest = true;
+ Vue.set(vm.mr, 'isMergeAllowed', true);
+ Vue.set(vm, 'isMakingRequest', true);
- expect(vm.isMergeButtonDisabled).toBeTruthy();
+ expect(vm.isMergeButtonDisabled).toBe(true);
});
});
});
@@ -268,31 +289,31 @@ describe('ReadyToMerge', () => {
describe('methods', () => {
describe('shouldShowMergeControls', () => {
it('should return false when an external pipeline is running and required to succeed', () => {
- vm.mr.isMergeAllowed = false;
- vm.mr.isPipelineActive = false;
+ Vue.set(vm.mr, 'isMergeAllowed', false);
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
- expect(vm.shouldShowMergeControls).toBeFalsy();
+ expect(vm.shouldShowMergeControls).toBe(false);
});
it('should return true when the build succeeded or build not required to succeed', () => {
- vm.mr.isMergeAllowed = true;
- vm.mr.isPipelineActive = false;
+ Vue.set(vm.mr, 'isMergeAllowed', true);
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', []);
- expect(vm.shouldShowMergeControls).toBeTruthy();
+ expect(vm.shouldShowMergeControls).toBe(true);
});
it('should return true when showing the MWPS button and a pipeline is running that needs to be successful', () => {
- vm.mr.isMergeAllowed = false;
- vm.mr.isPipelineActive = true;
+ Vue.set(vm.mr, 'isMergeAllowed', false);
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', [MWPS_MERGE_STRATEGY]);
- expect(vm.shouldShowMergeControls).toBeTruthy();
+ expect(vm.shouldShowMergeControls).toBe(true);
});
it('should return true when showing the MWPS button but not required for the pipeline to succeed', () => {
- vm.mr.isMergeAllowed = true;
- vm.mr.isPipelineActive = true;
+ Vue.set(vm.mr, 'isMergeAllowed', true);
+ Vue.set(vm.mr, 'availableAutoMergeStrategies', [MWPS_MERGE_STRATEGY]);
- expect(vm.shouldShowMergeControls).toBeTruthy();
+ expect(vm.shouldShowMergeControls).toBe(true);
});
});
@@ -325,16 +346,19 @@ describe('ReadyToMerge', () => {
vm.handleMergeButtonClick(true);
setTimeout(() => {
- expect(vm.setToMergeWhenPipelineSucceeds).toBeTruthy();
expect(vm.isMakingRequest).toBeTruthy();
expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
const params = vm.service.merge.calls.argsFor(0)[0];
- expect(params.sha).toEqual(vm.mr.sha);
- expect(params.commit_message).toEqual(vm.mr.commitMessage);
- expect(params.should_remove_source_branch).toBeFalsy();
- expect(params.merge_when_pipeline_succeeds).toBeTruthy();
+ expect(params).toEqual(
+ jasmine.objectContaining({
+ sha: vm.mr.sha,
+ commit_message: vm.mr.commitMessage,
+ should_remove_source_branch: false,
+ auto_merge_strategy: 'merge_when_pipeline_succeeds',
+ }),
+ );
done();
}, 333);
});
@@ -345,14 +369,13 @@ describe('ReadyToMerge', () => {
vm.handleMergeButtonClick(false, true);
setTimeout(() => {
- expect(vm.setToMergeWhenPipelineSucceeds).toBeFalsy();
expect(vm.isMakingRequest).toBeTruthy();
expect(eventHub.$emit).toHaveBeenCalledWith('FailedToMerge', undefined);
const params = vm.service.merge.calls.argsFor(0)[0];
expect(params.should_remove_source_branch).toBeTruthy();
- expect(params.merge_when_pipeline_succeeds).toBeFalsy();
+ expect(params.auto_merge_strategy).toBeUndefined();
done();
}, 333);
});
@@ -363,14 +386,13 @@ describe('ReadyToMerge', () => {
vm.handleMergeButtonClick();
setTimeout(() => {
- expect(vm.setToMergeWhenPipelineSucceeds).toBeFalsy();
expect(vm.isMakingRequest).toBeTruthy();
expect(vm.initiateMergePolling).toHaveBeenCalled();
const params = vm.service.merge.calls.argsFor(0)[0];
expect(params.should_remove_source_branch).toBeTruthy();
- expect(params.merge_when_pipeline_succeeds).toBeFalsy();
+ expect(params.auto_merge_strategy).toBeUndefined();
done();
}, 333);
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js
index 36f8c7a9683..9324c83bf4b 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import ShaMismatch from '~/vue_merge_request_widget/components/states/sha_mismatch.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import { removeBreakLine } from 'spec/helpers/vue_component_helper';
+import { removeBreakLine } from 'spec/helpers/text_helper';
describe('ShaMismatch', () => {
let vm;
diff --git a/spec/javascripts/vue_mr_widget/mock_data.js b/spec/javascripts/vue_mr_widget/mock_data.js
index dda16375103..3c9a5cece90 100644
--- a/spec/javascripts/vue_mr_widget/mock_data.js
+++ b/spec/javascripts/vue_mr_widget/mock_data.js
@@ -25,7 +25,6 @@ export default {
},
merge_status: 'can_be_merged',
merge_user_id: null,
- merge_when_pipeline_succeeds: false,
source_branch: 'daaaa',
source_branch_link: 'daaaa',
source_project_id: 19,
@@ -62,6 +61,7 @@ export default {
"Merge branch 'daaaa' into 'master'\n\nUpdate README.md\n\nSee merge request !22",
pipeline: {
id: 172,
+ iid: 32,
user: {
name: 'Administrator',
username: 'root',
@@ -209,8 +209,7 @@ export default {
source_branch_path: '/root/acets-app/branches/daaaa',
conflict_resolution_ui_path: '/root/acets-app/merge_requests/22/conflicts',
remove_wip_path: '/root/acets-app/merge_requests/22/remove_wip',
- cancel_merge_when_pipeline_succeeds_path:
- '/root/acets-app/merge_requests/22/cancel_merge_when_pipeline_succeeds',
+ cancel_auto_merge_path: '/root/acets-app/merge_requests/22/cancel_auto_merge',
create_issue_to_resolve_discussions_path:
'/root/acets-app/issues/new?merge_request_to_resolve_discussions_of=22',
merge_path: '/root/acets-app/merge_requests/22/merge',
@@ -235,11 +234,51 @@ export default {
troubleshooting_docs_path: 'help',
merge_request_pipelines_docs_path: '/help/ci/merge_request_pipelines/index.md',
squash: true,
+ visual_review_app_available: true,
+ merge_trains_enabled: true,
+ merge_trains_count: 3,
+ merge_train_index: 1,
};
export const mockStore = {
- pipeline: { id: 0 },
- mergePipeline: { id: 1 },
+ pipeline: {
+ id: 0,
+ iid: 0,
+ path: '/root/acets-app/pipelines/0',
+ details: {
+ status: {
+ details_path: '/root/review-app-tester/pipelines/66',
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2. png',
+ group: 'success-with-warnings',
+ has_details: true,
+ icon: 'status_warning',
+ illustration: null,
+ label: 'passed with warnings',
+ text: 'passed',
+ tooltip: 'passed',
+ },
+ },
+ },
+ mergePipeline: {
+ id: 1,
+ iid: 1,
+ path: '/root/acets-app/pipelines/0',
+ details: {
+ status: {
+ details_path: '/root/review-app-tester/pipelines/66',
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2. png',
+ group: 'success-with-warnings',
+ has_details: true,
+ icon: 'status_warning',
+ illustration: null,
+ label: 'passed with warnings',
+ text: 'passed',
+ tooltip: 'passed',
+ },
+ },
+ },
targetBranch: 'target-branch',
sourceBranch: 'source-branch',
sourceBranchLink: 'source-branch-link',
diff --git a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
index 690fcd3e224..08f7a17515e 100644
--- a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
@@ -21,7 +21,6 @@ describe('mrWidgetOptions', () => {
const COLLABORATION_MESSAGE = 'Allows commits from members who can merge to the target branch';
beforeEach(() => {
- gon.features = { approvalRules: false };
// Prevent component mounting
delete mrWidgetOptions.el;
@@ -32,7 +31,6 @@ describe('mrWidgetOptions', () => {
});
afterEach(() => {
- gon.features = null;
vm.$destroy();
});
@@ -224,44 +222,6 @@ describe('mrWidgetOptions', () => {
});
});
});
-
- describe('showTargetBranchAdvancedError', () => {
- describe(`when the pipeline's target_sha property doesn't exist`, () => {
- beforeEach(done => {
- Vue.set(vm.mr.pipeline, 'target_sha', undefined);
- Vue.set(vm.mr, 'targetBranchSha', 'abcd');
- vm.$nextTick(done);
- });
-
- it('should be false', () => {
- expect(vm.showTargetBranchAdvancedError).toEqual(false);
- });
- });
-
- describe(`when the pipeline's target_sha matches the target branch's sha`, () => {
- beforeEach(done => {
- Vue.set(vm.mr.pipeline, 'target_sha', 'abcd');
- Vue.set(vm.mr, 'targetBranchSha', 'abcd');
- vm.$nextTick(done);
- });
-
- it('should be false', () => {
- expect(vm.showTargetBranchAdvancedError).toEqual(false);
- });
- });
-
- describe(`when the pipeline's target_sha does not match the target branch's sha`, () => {
- beforeEach(done => {
- Vue.set(vm.mr.pipeline, 'target_sha', 'abcd');
- Vue.set(vm.mr, 'targetBranchSha', 'bcde');
- vm.$nextTick(done);
- });
-
- it('should be true', () => {
- expect(vm.showTargetBranchAdvancedError).toEqual(true);
- });
- });
- });
});
describe('methods', () => {
@@ -584,6 +544,7 @@ describe('mrWidgetOptions', () => {
];
const deploymentMockData = {
id: 15,
+ iid: 7,
name: 'review/diplo',
url: '/root/acets-review-apps/environments/15',
stop_url: '/root/acets-review-apps/environments/15/stop',
@@ -630,6 +591,7 @@ describe('mrWidgetOptions', () => {
vm.mr.state = 'merged';
vm.mr.mergePipeline = {
id: 127,
+ iid: 35,
user: {
id: 1,
name: 'Administrator',
diff --git a/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js b/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js
index e2cd0f084fd..e27a506f426 100644
--- a/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js
+++ b/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js
@@ -82,5 +82,47 @@ describe('MergeRequestStore', () => {
expect(store.isNothingToMergeState).toEqual(false);
});
});
+
+ describe('mergePipelinesEnabled', () => {
+ it('should set mergePipelinesEnabled = true when merge_pipelines_enabled is true', () => {
+ store.setData({ ...mockData, merge_pipelines_enabled: true });
+
+ expect(store.mergePipelinesEnabled).toBe(true);
+ });
+
+ it('should set mergePipelinesEnabled = false when merge_pipelines_enabled is not provided', () => {
+ store.setData({ ...mockData, merge_pipelines_enabled: undefined });
+
+ expect(store.mergePipelinesEnabled).toBe(false);
+ });
+ });
+
+ describe('mergeTrainsCount', () => {
+ it('should set mergeTrainsCount when merge_trains_count is provided', () => {
+ store.setData({ ...mockData, merge_trains_count: 3 });
+
+ expect(store.mergeTrainsCount).toBe(3);
+ });
+
+ it('should set mergeTrainsCount = 0 when merge_trains_count is not provided', () => {
+ store.setData({ ...mockData, merge_trains_count: undefined });
+
+ expect(store.mergeTrainsCount).toBe(0);
+ });
+ });
+
+ describe('mergeTrainIndex', () => {
+ it('should set mergeTrainIndex when merge_train_index is provided', () => {
+ store.setData({ ...mockData, merge_train_index: 3 });
+
+ expect(store.mergeTrainIndex).toBe(3);
+ });
+
+ it('should not set mergeTrainIndex when merge_train_index is not provided', () => {
+ store.setData({ ...mockData, merge_train_index: undefined });
+
+ expect(store.mergeTrainIndex).toBeUndefined();
+ });
+ });
});
});
diff --git a/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js b/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js
index 4da8c6196b1..bdf802052b9 100644
--- a/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js
+++ b/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js
@@ -4,6 +4,7 @@ import axios from '~/lib/utils/axios_utils';
import contentViewer from '~/vue_shared/components/content_viewer/content_viewer.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { GREEN_BOX_IMAGE_URL } from 'spec/test_constants';
+import '~/behaviors/markdown/render_gfm';
describe('ContentViewer', () => {
let vm;
@@ -29,6 +30,7 @@ describe('ContentViewer', () => {
path: 'test.md',
content: '* Test',
projectPath: 'testproject',
+ type: 'markdown',
});
const previewContainer = vm.$el.querySelector('.md-previewer');
@@ -44,6 +46,7 @@ describe('ContentViewer', () => {
createComponent({
path: GREEN_BOX_IMAGE_URL,
fileSize: 1024,
+ type: 'image',
});
setTimeout(() => {
diff --git a/spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js b/spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js
index 7f2e246d656..97c870f27d9 100644
--- a/spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js
+++ b/spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js
@@ -138,22 +138,6 @@ describe('ImageDiffViewer', () => {
done();
});
});
-
- it('drag handler is working', done => {
- vm.$el.querySelector('.view-modes-menu li:nth-child(2)').click();
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.swipe-bar').style.left).toBe('1px');
- expect(vm.$el.querySelector('.top-handle')).not.toBeNull();
-
- dragSlider(vm.$el.querySelector('.swipe-bar'), 40);
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.swipe-bar').style.left).toBe('-20px');
- done();
- });
- });
- });
});
describe('onionSkin', () => {
diff --git a/spec/javascripts/vue_shared/components/issue/issue_assignees_spec.js b/spec/javascripts/vue_shared/components/issue/issue_assignees_spec.js
deleted file mode 100644
index 9eac75fac96..00000000000
--- a/spec/javascripts/vue_shared/components/issue/issue_assignees_spec.js
+++ /dev/null
@@ -1,114 +0,0 @@
-import Vue from 'vue';
-
-import IssueAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import { mockAssigneesList } from 'spec/boards/mock_data';
-
-const createComponent = (assignees = mockAssigneesList, cssClass = '') => {
- const Component = Vue.extend(IssueAssignees);
-
- return mountComponent(Component, {
- assignees,
- cssClass,
- });
-};
-
-describe('IssueAssigneesComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('data', () => {
- it('returns default data props', () => {
- expect(vm.maxVisibleAssignees).toBe(2);
- expect(vm.maxAssigneeAvatars).toBe(3);
- expect(vm.maxAssignees).toBe(99);
- });
- });
-
- describe('computed', () => {
- describe('countOverLimit', () => {
- it('should return difference between assignees count and maxVisibleAssignees', () => {
- expect(vm.countOverLimit).toBe(mockAssigneesList.length - vm.maxVisibleAssignees);
- });
- });
-
- describe('assigneesToShow', () => {
- it('should return assignees containing only 2 items when count more than maxAssigneeAvatars', () => {
- expect(vm.assigneesToShow.length).toBe(2);
- });
-
- it('should return all assignees as it is when count less than maxAssigneeAvatars', () => {
- vm.assignees = mockAssigneesList.slice(0, 3); // Set 3 Assignees
-
- expect(vm.assigneesToShow.length).toBe(3);
- });
- });
-
- describe('assigneesCounterTooltip', () => {
- it('should return string containing count of remaining assignees when count more than maxAssigneeAvatars', () => {
- expect(vm.assigneesCounterTooltip).toBe('3 more assignees');
- });
- });
-
- describe('shouldRenderAssigneesCounter', () => {
- it('should return `false` when assignees count less than maxAssigneeAvatars', () => {
- vm.assignees = mockAssigneesList.slice(0, 3); // Set 3 Assignees
-
- expect(vm.shouldRenderAssigneesCounter).toBe(false);
- });
-
- it('should return `true` when assignees count more than maxAssigneeAvatars', () => {
- expect(vm.shouldRenderAssigneesCounter).toBe(true);
- });
- });
-
- describe('assigneeCounterLabel', () => {
- it('should return count of additional assignees total assignees count more than maxAssigneeAvatars', () => {
- expect(vm.assigneeCounterLabel).toBe('+3');
- });
- });
- });
-
- describe('methods', () => {
- describe('avatarUrlTitle', () => {
- it('returns string containing alt text for assignee avatar', () => {
- expect(vm.avatarUrlTitle(mockAssigneesList[0])).toBe('Avatar for Terrell Graham');
- });
- });
- });
-
- describe('template', () => {
- it('renders component root element with class `issue-assignees`', () => {
- expect(vm.$el.classList.contains('issue-assignees')).toBe(true);
- });
-
- it('renders assignee avatars', () => {
- expect(vm.$el.querySelectorAll('.user-avatar-link').length).toBe(2);
- });
-
- it('renders assignee tooltips', () => {
- const tooltipText = vm.$el
- .querySelectorAll('.user-avatar-link')[0]
- .querySelector('.js-assignee-tooltip').innerText;
-
- expect(tooltipText).toContain('Assignee');
- expect(tooltipText).toContain('Terrell Graham');
- expect(tooltipText).toContain('@monserrate.gleichner');
- });
-
- it('renders additional assignees count', () => {
- const avatarCounterEl = vm.$el.querySelector('.avatar-counter');
-
- expect(avatarCounterEl.innerText.trim()).toBe('+3');
- expect(avatarCounterEl.getAttribute('data-original-title')).toBe('3 more assignees');
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/issue/issue_milestone_spec.js b/spec/javascripts/vue_shared/components/issue/issue_milestone_spec.js
deleted file mode 100644
index 8fca2637326..00000000000
--- a/spec/javascripts/vue_shared/components/issue/issue_milestone_spec.js
+++ /dev/null
@@ -1,234 +0,0 @@
-import Vue from 'vue';
-
-import IssueMilestone from '~/vue_shared/components/issue/issue_milestone.vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import { mockMilestone } from 'spec/boards/mock_data';
-
-const createComponent = (milestone = mockMilestone) => {
- const Component = Vue.extend(IssueMilestone);
-
- return mountComponent(Component, {
- milestone,
- });
-};
-
-describe('IssueMilestoneComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('computed', () => {
- describe('isMilestoneStarted', () => {
- it('should return `false` when milestoneStart prop is not defined', done => {
- const vmStartUndefined = createComponent(
- Object.assign({}, mockMilestone, {
- start_date: '',
- }),
- );
-
- Vue.nextTick()
- .then(() => {
- expect(vmStartUndefined.isMilestoneStarted).toBe(false);
- })
- .then(done)
- .catch(done.fail);
-
- vmStartUndefined.$destroy();
- });
-
- it('should return `true` when milestone start date is past current date', done => {
- const vmStarted = createComponent(
- Object.assign({}, mockMilestone, {
- start_date: '1990-07-22',
- }),
- );
-
- Vue.nextTick()
- .then(() => {
- expect(vmStarted.isMilestoneStarted).toBe(true);
- })
- .then(done)
- .catch(done.fail);
-
- vmStarted.$destroy();
- });
- });
-
- describe('isMilestonePastDue', () => {
- it('should return `false` when milestoneDue prop is not defined', done => {
- const vmDueUndefined = createComponent(
- Object.assign({}, mockMilestone, {
- due_date: '',
- }),
- );
-
- Vue.nextTick()
- .then(() => {
- expect(vmDueUndefined.isMilestonePastDue).toBe(false);
- })
- .then(done)
- .catch(done.fail);
-
- vmDueUndefined.$destroy();
- });
-
- it('should return `true` when milestone due is past current date', done => {
- const vmPastDue = createComponent(
- Object.assign({}, mockMilestone, {
- due_date: '1990-07-22',
- }),
- );
-
- Vue.nextTick()
- .then(() => {
- expect(vmPastDue.isMilestonePastDue).toBe(true);
- })
- .then(done)
- .catch(done.fail);
-
- vmPastDue.$destroy();
- });
- });
-
- describe('milestoneDatesAbsolute', () => {
- it('returns string containing absolute milestone due date', () => {
- expect(vm.milestoneDatesAbsolute).toBe('(December 31, 2019)');
- });
-
- it('returns string containing absolute milestone start date when due date is not present', done => {
- const vmDueUndefined = createComponent(
- Object.assign({}, mockMilestone, {
- due_date: '',
- }),
- );
-
- Vue.nextTick()
- .then(() => {
- expect(vmDueUndefined.milestoneDatesAbsolute).toBe('(January 1, 2018)');
- })
- .then(done)
- .catch(done.fail);
-
- vmDueUndefined.$destroy();
- });
-
- it('returns empty string when both milestone start and due dates are not present', done => {
- const vmDatesUndefined = createComponent(
- Object.assign({}, mockMilestone, {
- start_date: '',
- due_date: '',
- }),
- );
-
- Vue.nextTick()
- .then(() => {
- expect(vmDatesUndefined.milestoneDatesAbsolute).toBe('');
- })
- .then(done)
- .catch(done.fail);
-
- vmDatesUndefined.$destroy();
- });
- });
-
- describe('milestoneDatesHuman', () => {
- it('returns string containing milestone due date when date is yet to be due', done => {
- const vmFuture = createComponent(
- Object.assign({}, mockMilestone, {
- due_date: `${new Date().getFullYear() + 10}-01-01`,
- }),
- );
-
- Vue.nextTick()
- .then(() => {
- expect(vmFuture.milestoneDatesHuman).toContain('years remaining');
- })
- .then(done)
- .catch(done.fail);
-
- vmFuture.$destroy();
- });
-
- it('returns string containing milestone start date when date has already started and due date is not present', done => {
- const vmStarted = createComponent(
- Object.assign({}, mockMilestone, {
- start_date: '1990-07-22',
- due_date: '',
- }),
- );
-
- Vue.nextTick()
- .then(() => {
- expect(vmStarted.milestoneDatesHuman).toContain('Started');
- })
- .then(done)
- .catch(done.fail);
-
- vmStarted.$destroy();
- });
-
- it('returns string containing milestone start date when date is yet to start and due date is not present', done => {
- const vmStarts = createComponent(
- Object.assign({}, mockMilestone, {
- start_date: `${new Date().getFullYear() + 10}-01-01`,
- due_date: '',
- }),
- );
-
- Vue.nextTick()
- .then(() => {
- expect(vmStarts.milestoneDatesHuman).toContain('Starts');
- })
- .then(done)
- .catch(done.fail);
-
- vmStarts.$destroy();
- });
-
- it('returns empty string when milestone start and due dates are not present', done => {
- const vmDatesUndefined = createComponent(
- Object.assign({}, mockMilestone, {
- start_date: '',
- due_date: '',
- }),
- );
-
- Vue.nextTick()
- .then(() => {
- expect(vmDatesUndefined.milestoneDatesHuman).toBe('');
- })
- .then(done)
- .catch(done.fail);
-
- vmDatesUndefined.$destroy();
- });
- });
- });
-
- describe('template', () => {
- it('renders component root element with class `issue-milestone-details`', () => {
- expect(vm.$el.classList.contains('issue-milestone-details')).toBe(true);
- });
-
- it('renders milestone icon', () => {
- expect(vm.$el.querySelector('svg use').getAttribute('xlink:href')).toContain('clock');
- });
-
- it('renders milestone title', () => {
- expect(vm.$el.querySelector('.milestone-title').innerText.trim()).toBe(mockMilestone.title);
- });
-
- it('renders milestone tooltip', () => {
- expect(vm.$el.querySelector('.js-item-milestone').innerText.trim()).toContain(
- mockMilestone.title,
- );
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/issue/issue_warning_spec.js b/spec/javascripts/vue_shared/components/issue/issue_warning_spec.js
deleted file mode 100644
index aa7d6ea2e34..00000000000
--- a/spec/javascripts/vue_shared/components/issue/issue_warning_spec.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import Vue from 'vue';
-import issueWarning from '~/vue_shared/components/issue/issue_warning.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-const IssueWarning = Vue.extend(issueWarning);
-
-function formatWarning(string) {
- // Replace newlines with a space then replace multiple spaces with one space
- return string
- .trim()
- .replace(/\n/g, ' ')
- .replace(/\s\s+/g, ' ');
-}
-
-describe('Issue Warning Component', () => {
- describe('isLocked', () => {
- it('should render locked issue warning information', () => {
- const vm = mountComponent(IssueWarning, {
- isLocked: true,
- });
-
- expect(vm.$el.querySelector('.icon use').href.baseVal).toMatch(/lock$/);
- expect(formatWarning(vm.$el.querySelector('span').textContent)).toEqual(
- 'This issue is locked. Only project members can comment.',
- );
- });
- });
-
- describe('isConfidential', () => {
- it('should render confidential issue warning information', () => {
- const vm = mountComponent(IssueWarning, {
- isConfidential: true,
- });
-
- expect(vm.$el.querySelector('.icon use').href.baseVal).toMatch(/eye-slash$/);
- expect(formatWarning(vm.$el.querySelector('span').textContent)).toEqual(
- 'This is a confidential issue. Your comment will not be visible to the public.',
- );
- });
- });
-
- describe('isLocked and isConfidential', () => {
- it('should render locked and confidential issue warning information', () => {
- const vm = mountComponent(IssueWarning, {
- isLocked: true,
- isConfidential: true,
- });
-
- expect(vm.$el.querySelector('.icon')).toBeFalsy();
- expect(formatWarning(vm.$el.querySelector('span').textContent)).toEqual(
- "This issue is confidential and locked. People without permission will never get a notification and won't be able to comment.",
- );
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/issue/related_issuable_item_spec.js b/spec/javascripts/vue_shared/components/issue/related_issuable_item_spec.js
deleted file mode 100644
index 42198e92eea..00000000000
--- a/spec/javascripts/vue_shared/components/issue/related_issuable_item_spec.js
+++ /dev/null
@@ -1,194 +0,0 @@
-import Vue from 'vue';
-import { mount, createLocalVue } from '@vue/test-utils';
-import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
-import { defaultMilestone, defaultAssignees } from './related_issuable_mock_data';
-
-describe('RelatedIssuableItem', () => {
- let wrapper;
- const props = {
- idKey: 1,
- displayReference: 'gitlab-org/gitlab-test#1',
- pathIdSeparator: '#',
- path: `${gl.TEST_HOST}/path`,
- title: 'title',
- confidential: true,
- dueDate: '1990-12-31',
- weight: 10,
- createdAt: '2018-12-01T00:00:00.00Z',
- milestone: defaultMilestone,
- assignees: defaultAssignees,
- eventNamespace: 'relatedIssue',
- };
- const slots = {
- dueDate: '<div class="js-due-date-slot"></div>',
- weight: '<div class="js-weight-slot"></div>',
- };
-
- beforeEach(() => {
- const localVue = createLocalVue();
-
- wrapper = mount(localVue.extend(RelatedIssuableItem), {
- localVue,
- slots,
- sync: false,
- propsData: props,
- });
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('contains issuable-info-container class when canReorder is false', () => {
- expect(wrapper.props('canReorder')).toBe(false);
- expect(wrapper.find('.issuable-info-container').exists()).toBe(true);
- });
-
- it('does not render token state', () => {
- expect(wrapper.find('.text-secondary svg').exists()).toBe(false);
- });
-
- it('does not render remove button', () => {
- expect(wrapper.find({ ref: 'removeButton' }).exists()).toBe(false);
- });
-
- describe('token title', () => {
- it('links to computedPath', () => {
- expect(wrapper.find('.item-title a').attributes('href')).toEqual(wrapper.props('path'));
- });
-
- it('renders confidential icon', () => {
- expect(wrapper.find('.confidential-icon').exists()).toBe(true);
- });
-
- it('renders title', () => {
- expect(wrapper.find('.item-title a').text()).toEqual(props.title);
- });
- });
-
- describe('token state', () => {
- let tokenState;
-
- beforeEach(done => {
- wrapper.setProps({ state: 'opened' });
-
- Vue.nextTick(() => {
- tokenState = wrapper.find('.issue-token-state-icon-open');
-
- done();
- });
- });
-
- it('renders if hasState', () => {
- expect(tokenState.exists()).toBe(true);
- });
-
- it('renders state title', () => {
- const stateTitle = tokenState.attributes('data-original-title');
-
- expect(stateTitle).toContain('<span class="bold">Opened</span>');
- expect(stateTitle).toContain(
- '<span class="text-tertiary">Dec 1, 2018 12:00am GMT+0000</span>',
- );
- });
-
- it('renders aria label', () => {
- expect(tokenState.attributes('aria-label')).toEqual('opened');
- });
-
- it('renders open icon when open state', () => {
- expect(tokenState.classes('issue-token-state-icon-open')).toBe(true);
- });
-
- it('renders close icon when close state', done => {
- wrapper.setProps({
- state: 'closed',
- closedAt: '2018-12-01T00:00:00.00Z',
- });
-
- Vue.nextTick(() => {
- expect(tokenState.classes('issue-token-state-icon-closed')).toBe(true);
-
- done();
- });
- });
- });
-
- describe('token metadata', () => {
- let tokenMetadata;
-
- beforeEach(done => {
- Vue.nextTick(() => {
- tokenMetadata = wrapper.find('.item-meta');
-
- done();
- });
- });
-
- it('renders item path and ID', () => {
- const pathAndID = tokenMetadata.find('.item-path-id').text();
-
- expect(pathAndID).toContain('gitlab-org/gitlab-test');
- expect(pathAndID).toContain('#1');
- });
-
- it('renders milestone icon and name', () => {
- const milestoneIcon = tokenMetadata.find('.item-milestone svg use');
- const milestoneTitle = tokenMetadata.find('.item-milestone .milestone-title');
-
- expect(milestoneIcon.attributes('href')).toContain('clock');
- expect(milestoneTitle.text()).toContain('Milestone title');
- });
-
- it('renders due date component', () => {
- expect(tokenMetadata.find('.js-due-date-slot').exists()).toBe(true);
- });
-
- it('renders weight component', () => {
- expect(tokenMetadata.find('.js-weight-slot').exists()).toBe(true);
- });
- });
-
- describe('token assignees', () => {
- it('renders assignees avatars', () => {
- expect(wrapper.findAll('.item-assignees .user-avatar-link').length).toBe(2);
- expect(wrapper.find('.item-assignees .avatar-counter').text()).toContain('+2');
- });
- });
-
- describe('remove button', () => {
- let removeBtn;
-
- beforeEach(done => {
- wrapper.setProps({ canRemove: true });
- Vue.nextTick(() => {
- removeBtn = wrapper.find({ ref: 'removeButton' });
-
- done();
- });
- });
-
- it('renders if canRemove', () => {
- expect(removeBtn.exists()).toBe(true);
- });
-
- it('renders disabled button when removeDisabled', done => {
- wrapper.vm.removeDisabled = true;
-
- Vue.nextTick(() => {
- expect(removeBtn.attributes('disabled')).toEqual('disabled');
-
- done();
- });
- });
-
- it('triggers onRemoveRequest when clicked', () => {
- removeBtn.trigger('click');
-
- const { relatedIssueRemoveRequest } = wrapper.emitted();
-
- expect(relatedIssueRemoveRequest.length).toBe(1);
- expect(relatedIssueRemoveRequest[0]).toEqual([props.idKey]);
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/markdown/suggestion_diff_header_spec.js b/spec/javascripts/vue_shared/components/markdown/suggestion_diff_header_spec.js
deleted file mode 100644
index 12ee804f668..00000000000
--- a/spec/javascripts/vue_shared/components/markdown/suggestion_diff_header_spec.js
+++ /dev/null
@@ -1,75 +0,0 @@
-import Vue from 'vue';
-import SuggestionDiffHeaderComponent from '~/vue_shared/components/markdown/suggestion_diff_header.vue';
-
-const MOCK_DATA = {
- canApply: true,
- isApplied: false,
- helpPagePath: 'path_to_docs',
-};
-
-describe('Suggestion Diff component', () => {
- let vm;
-
- function createComponent(propsData) {
- const Component = Vue.extend(SuggestionDiffHeaderComponent);
-
- return new Component({
- propsData,
- }).$mount();
- }
-
- beforeEach(done => {
- vm = createComponent(MOCK_DATA);
- Vue.nextTick(done);
- });
-
- describe('init', () => {
- it('renders a suggestion header', () => {
- const header = vm.$el.querySelector('.qa-suggestion-diff-header');
-
- expect(header).not.toBeNull();
- expect(header.innerHTML.includes('Suggested change')).toBe(true);
- });
-
- it('renders a help button', () => {
- const helpBtn = vm.$el.querySelector('.js-help-btn');
-
- expect(helpBtn).not.toBeNull();
- });
-
- it('renders an apply button', () => {
- const applyBtn = vm.$el.querySelector('.qa-apply-btn');
-
- expect(applyBtn).not.toBeNull();
- expect(applyBtn.innerHTML.includes('Apply suggestion')).toBe(true);
- });
-
- it('does not render an apply button if `canApply` is set to false', () => {
- const props = Object.assign(MOCK_DATA, { canApply: false });
-
- vm = createComponent(props);
-
- expect(vm.$el.querySelector('.qa-apply-btn')).toBeNull();
- });
- });
-
- describe('applySuggestion', () => {
- it('emits when the apply button is clicked', () => {
- const props = Object.assign(MOCK_DATA, { canApply: true });
-
- vm = createComponent(props);
- spyOn(vm, '$emit');
- vm.applySuggestion();
-
- expect(vm.$emit).toHaveBeenCalled();
- });
-
- it('does not emit when the canApply is set to false', () => {
- spyOn(vm, '$emit');
- vm.canApply = false;
- vm.applySuggestion();
-
- expect(vm.$emit).not.toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/notes/placeholder_note_spec.js b/spec/javascripts/vue_shared/components/notes/placeholder_note_spec.js
deleted file mode 100644
index 45f131194ca..00000000000
--- a/spec/javascripts/vue_shared/components/notes/placeholder_note_spec.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import Vue from 'vue';
-import issuePlaceholderNote from '~/vue_shared/components/notes/placeholder_note.vue';
-import createStore from '~/notes/stores';
-import { userDataMock } from '../../../notes/mock_data';
-
-describe('issue placeholder system note component', () => {
- let store;
- let vm;
-
- beforeEach(() => {
- const Component = Vue.extend(issuePlaceholderNote);
- store = createStore();
- store.dispatch('setUserData', userDataMock);
- vm = new Component({
- store,
- propsData: { note: { body: 'Foo' } },
- }).$mount();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('user information', () => {
- it('should render user avatar with link', () => {
- expect(vm.$el.querySelector('.user-avatar-link').getAttribute('href')).toEqual(
- userDataMock.path,
- );
-
- expect(vm.$el.querySelector('.user-avatar-link img').getAttribute('src')).toEqual(
- `${userDataMock.avatar_url}?width=40`,
- );
- });
- });
-
- describe('note content', () => {
- it('should render note header information', () => {
- expect(vm.$el.querySelector('.note-header-info a').getAttribute('href')).toEqual(
- userDataMock.path,
- );
-
- expect(
- vm.$el.querySelector('.note-header-info .note-headline-light').textContent.trim(),
- ).toEqual(`@${userDataMock.username}`);
- });
-
- it('should render note body', () => {
- expect(vm.$el.querySelector('.note-text p').textContent.trim()).toEqual('Foo');
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/notes/placeholder_system_note_spec.js b/spec/javascripts/vue_shared/components/notes/placeholder_system_note_spec.js
deleted file mode 100644
index 6013e85811a..00000000000
--- a/spec/javascripts/vue_shared/components/notes/placeholder_system_note_spec.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import Vue from 'vue';
-import placeholderSystemNote from '~/vue_shared/components/notes/placeholder_system_note.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-describe('placeholder system note component', () => {
- let PlaceholderSystemNote;
- let vm;
-
- beforeEach(() => {
- PlaceholderSystemNote = Vue.extend(placeholderSystemNote);
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('should render system note placeholder with plain text', () => {
- vm = mountComponent(PlaceholderSystemNote, {
- note: { body: 'This is a placeholder' },
- });
-
- expect(vm.$el.tagName).toEqual('LI');
- expect(vm.$el.querySelector('.timeline-content em').textContent.trim()).toEqual(
- 'This is a placeholder',
- );
- });
-});
diff --git a/spec/javascripts/vue_shared/components/notes/system_note_spec.js b/spec/javascripts/vue_shared/components/notes/system_note_spec.js
deleted file mode 100644
index adcb1c858aa..00000000000
--- a/spec/javascripts/vue_shared/components/notes/system_note_spec.js
+++ /dev/null
@@ -1,59 +0,0 @@
-import Vue from 'vue';
-import issueSystemNote from '~/vue_shared/components/notes/system_note.vue';
-import createStore from '~/notes/stores';
-
-describe('system note component', () => {
- let vm;
- let props;
-
- beforeEach(() => {
- props = {
- note: {
- id: '1424',
- author: {
- id: 1,
- name: 'Root',
- username: 'root',
- state: 'active',
- avatar_url: 'path',
- path: '/root',
- },
- note_html: '<p dir="auto">closed</p>',
- system_note_icon_name: 'status_closed',
- created_at: '2017-08-02T10:51:58.559Z',
- },
- };
-
- const store = createStore();
- store.dispatch('setTargetNoteHash', `note_${props.note.id}`);
-
- const Component = Vue.extend(issueSystemNote);
- vm = new Component({
- store,
- propsData: props,
- }).$mount();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('should render a list item with correct id', () => {
- expect(vm.$el.getAttribute('id')).toEqual(`note_${props.note.id}`);
- });
-
- it('should render target class is note is target note', () => {
- expect(vm.$el.classList).toContain('target');
- });
-
- it('should render svg icon', () => {
- expect(vm.$el.querySelector('.timeline-icon svg')).toBeDefined();
- });
-
- // Redcarpet Markdown renderer wraps text in `<p>` tags
- // we need to strip them because they break layout of commit lists in system notes:
- // https://gitlab.com/gitlab-org/gitlab-ce/uploads/b07a10670919254f0220d3ff5c1aa110/jqzI.png
- it('removes wrapping paragraph from note HTML', () => {
- expect(vm.$el.querySelector('.system-note-message').innerHTML).toEqual('<span>closed</span>');
- });
-});
diff --git a/spec/javascripts/vue_shared/components/pagination/graphql_pagination_spec.js b/spec/javascripts/vue_shared/components/pagination/graphql_pagination_spec.js
new file mode 100644
index 00000000000..7445da6cdee
--- /dev/null
+++ b/spec/javascripts/vue_shared/components/pagination/graphql_pagination_spec.js
@@ -0,0 +1,70 @@
+import { shallowMount } from '@vue/test-utils';
+import GraphqlPagination from '~/vue_shared/components/pagination/graphql_pagination.vue';
+
+describe('Graphql Pagination component', () => {
+ let wrapper;
+ function factory({ hasNextPage = true, hasPreviousPage = true }) {
+ wrapper = shallowMount(GraphqlPagination, {
+ propsData: {
+ hasNextPage,
+ hasPreviousPage,
+ },
+ });
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('without previous page', () => {
+ beforeEach(() => {
+ factory({ hasPreviousPage: false });
+ });
+
+ it('renders disabled previous button', () => {
+ expect(wrapper.find('.js-prev-btn').attributes().disabled).toEqual('true');
+ });
+ });
+
+ describe('with previous page', () => {
+ beforeEach(() => {
+ factory({ hasPreviousPage: true });
+ });
+
+ it('renders enabled previous button', () => {
+ expect(wrapper.find('.js-prev-btn').attributes().disabled).toEqual(undefined);
+ });
+
+ it('emits previousClicked on click', () => {
+ wrapper.find('.js-prev-btn').vm.$emit('click');
+
+ expect(wrapper.emitted().previousClicked.length).toBe(1);
+ });
+ });
+
+ describe('without next page', () => {
+ beforeEach(() => {
+ factory({ hasNextPage: false });
+ });
+
+ it('renders disabled next button', () => {
+ expect(wrapper.find('.js-next-btn').attributes().disabled).toEqual('true');
+ });
+ });
+
+ describe('with next page', () => {
+ beforeEach(() => {
+ factory({ hasNextPage: true });
+ });
+
+ it('renders enabled next button', () => {
+ expect(wrapper.find('.js-next-btn').attributes().disabled).toEqual(undefined);
+ });
+
+ it('emits nextClicked on click', () => {
+ wrapper.find('.js-next-btn').vm.$emit('click');
+
+ expect(wrapper.emitted().nextClicked.length).toBe(1);
+ });
+ });
+});
diff --git a/spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js b/spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js
index b95183747bb..47964a1702a 100644
--- a/spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js
+++ b/spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js
@@ -1,6 +1,6 @@
import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { trimText } from 'spec/helpers/vue_component_helper';
+import { trimText } from 'spec/helpers/text_helper';
const localVue = createLocalVue();
@@ -9,8 +9,8 @@ describe('ProjectListItem component', () => {
let wrapper;
let vm;
let options;
- loadJSONFixtures('projects.json');
- const project = getJSONFixture('projects.json')[0];
+ loadJSONFixtures('static/projects.json');
+ const project = getJSONFixture('static/projects.json')[0];
beforeEach(() => {
options = {
diff --git a/spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js b/spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js
index ba9ec8f2f19..7f5f1a778d7 100644
--- a/spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js
+++ b/spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js
@@ -3,13 +3,13 @@ import _ from 'underscore';
import ProjectSelector from '~/vue_shared/components/project_selector/project_selector.vue';
import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
import { shallowMount } from '@vue/test-utils';
-import { trimText } from 'spec/helpers/vue_component_helper';
+import { trimText } from 'spec/helpers/text_helper';
describe('ProjectSelector component', () => {
let wrapper;
let vm;
- loadJSONFixtures('projects.json');
- const allProjects = getJSONFixture('projects.json');
+ loadJSONFixtures('static/projects.json');
+ const allProjects = getJSONFixture('static/projects.json');
const searchResults = allProjects.slice(0, 5);
let selected = [];
selected = selected.concat(allProjects.slice(0, 3)).concat(allProjects.slice(5, 8));
@@ -99,7 +99,7 @@ describe('ProjectSelector component', () => {
expect(trimText(noResultsEl.text())).toEqual('Sorry, no projects matched your search');
});
- it(`shows a "minimum seach query" message if showMinimumSearchQueryMessage === true`, () => {
+ it(`shows a "minimum search query" message if showMinimumSearchQueryMessage === true`, () => {
wrapper.setProps({ showMinimumSearchQueryMessage: true });
expect(wrapper.contains('.js-minimum-search-query-message')).toBe(true);
diff --git a/spec/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js b/spec/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js
deleted file mode 100644
index 6bff1521695..00000000000
--- a/spec/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import Vue from 'vue';
-import collapsedCalendarIcon from '~/vue_shared/components/sidebar/collapsed_calendar_icon.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-describe('collapsedCalendarIcon', () => {
- let vm;
- beforeEach(() => {
- const CollapsedCalendarIcon = Vue.extend(collapsedCalendarIcon);
- vm = mountComponent(CollapsedCalendarIcon, {
- containerClass: 'test-class',
- text: 'text',
- showIcon: false,
- });
- });
-
- it('should add class to container', () => {
- expect(vm.$el.classList.contains('test-class')).toEqual(true);
- });
-
- it('should hide calendar icon if showIcon', () => {
- expect(vm.$el.querySelector('.fa-calendar')).toBeNull();
- });
-
- it('should render text', () => {
- expect(vm.$el.querySelector('span').innerText.trim()).toEqual('text');
- });
-
- it('should emit click event when container is clicked', () => {
- const click = jasmine.createSpy();
- vm.$on('click', click);
-
- vm.$el.click();
-
- expect(click).toHaveBeenCalled();
- });
-});
diff --git a/spec/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js b/spec/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
deleted file mode 100644
index c507a97d37e..00000000000
--- a/spec/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
+++ /dev/null
@@ -1,86 +0,0 @@
-import Vue from 'vue';
-import collapsedGroupedDatePicker from '~/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-describe('collapsedGroupedDatePicker', () => {
- let vm;
- beforeEach(() => {
- const CollapsedGroupedDatePicker = Vue.extend(collapsedGroupedDatePicker);
- vm = mountComponent(CollapsedGroupedDatePicker, {
- showToggleSidebar: true,
- });
- });
-
- describe('toggleCollapse events', () => {
- beforeEach(done => {
- spyOn(vm, 'toggleSidebar');
- vm.minDate = new Date('07/17/2016');
- Vue.nextTick(done);
- });
-
- it('should emit when collapsed-calendar-icon is clicked', () => {
- vm.$el.querySelector('.sidebar-collapsed-icon').click();
-
- expect(vm.toggleSidebar).toHaveBeenCalled();
- });
- });
-
- describe('minDate and maxDate', () => {
- beforeEach(done => {
- vm.minDate = new Date('07/17/2016');
- vm.maxDate = new Date('07/17/2017');
- Vue.nextTick(done);
- });
-
- it('should render both collapsed-calendar-icon', () => {
- const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
-
- expect(icons.length).toEqual(2);
- expect(icons[0].innerText.trim()).toEqual('Jul 17 2016');
- expect(icons[1].innerText.trim()).toEqual('Jul 17 2017');
- });
- });
-
- describe('minDate', () => {
- beforeEach(done => {
- vm.minDate = new Date('07/17/2016');
- Vue.nextTick(done);
- });
-
- it('should render minDate in collapsed-calendar-icon', () => {
- const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
-
- expect(icons.length).toEqual(1);
- expect(icons[0].innerText.trim()).toEqual('From Jul 17 2016');
- });
- });
-
- describe('maxDate', () => {
- beforeEach(done => {
- vm.maxDate = new Date('07/17/2017');
- Vue.nextTick(done);
- });
-
- it('should render maxDate in collapsed-calendar-icon', () => {
- const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
-
- expect(icons.length).toEqual(1);
- expect(icons[0].innerText.trim()).toEqual('Until Jul 17 2017');
- });
- });
-
- describe('no dates', () => {
- it('should render None', () => {
- const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
-
- expect(icons.length).toEqual(1);
- expect(icons[0].innerText.trim()).toEqual('None');
- });
-
- it('should have tooltip as `Start and due date`', () => {
- const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
-
- expect(icons[0].dataset.originalTitle).toBe('Start and due date');
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/sidebar/date_picker_spec.js b/spec/javascripts/vue_shared/components/sidebar/date_picker_spec.js
deleted file mode 100644
index 805ba7b9947..00000000000
--- a/spec/javascripts/vue_shared/components/sidebar/date_picker_spec.js
+++ /dev/null
@@ -1,121 +0,0 @@
-import Vue from 'vue';
-import sidebarDatePicker from '~/vue_shared/components/sidebar/date_picker.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-describe('sidebarDatePicker', () => {
- let vm;
- beforeEach(() => {
- const SidebarDatePicker = Vue.extend(sidebarDatePicker);
- vm = mountComponent(SidebarDatePicker, {
- label: 'label',
- isLoading: true,
- });
- });
-
- it('should emit toggleCollapse when collapsed toggle sidebar is clicked', () => {
- const toggleCollapse = jasmine.createSpy();
- vm.$on('toggleCollapse', toggleCollapse);
-
- vm.$el.querySelector('.issuable-sidebar-header .gutter-toggle').click();
-
- expect(toggleCollapse).toHaveBeenCalled();
- });
-
- it('should render collapsed-calendar-icon', () => {
- expect(vm.$el.querySelector('.sidebar-collapsed-icon')).toBeDefined();
- });
-
- it('should render label', () => {
- expect(vm.$el.querySelector('.title').innerText.trim()).toEqual('label');
- });
-
- it('should render loading-icon when isLoading', () => {
- expect(vm.$el.querySelector('.fa-spin')).toBeDefined();
- });
-
- it('should render value when not editing', () => {
- expect(vm.$el.querySelector('.value-content')).toBeDefined();
- });
-
- it('should render None if there is no selectedDate', () => {
- expect(vm.$el.querySelector('.value-content span').innerText.trim()).toEqual('None');
- });
-
- it('should render date-picker when editing', done => {
- vm.editing = true;
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.pika-label')).toBeDefined();
- done();
- });
- });
-
- describe('editable', () => {
- beforeEach(done => {
- vm.editable = true;
- Vue.nextTick(done);
- });
-
- it('should render edit button', () => {
- expect(vm.$el.querySelector('.title .btn-blank').innerText.trim()).toEqual('Edit');
- });
-
- it('should enable editing when edit button is clicked', done => {
- vm.isLoading = false;
- Vue.nextTick(() => {
- vm.$el.querySelector('.title .btn-blank').click();
-
- expect(vm.editing).toEqual(true);
- done();
- });
- });
- });
-
- it('should render date if selectedDate', done => {
- vm.selectedDate = new Date('07/07/2017');
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.value-content strong').innerText.trim()).toEqual('Jul 7, 2017');
- done();
- });
- });
-
- describe('selectedDate and editable', () => {
- beforeEach(done => {
- vm.selectedDate = new Date('07/07/2017');
- vm.editable = true;
- Vue.nextTick(done);
- });
-
- it('should render remove button if selectedDate and editable', () => {
- expect(vm.$el.querySelector('.value-content .btn-blank').innerText.trim()).toEqual('remove');
- });
-
- it('should emit saveDate when remove button is clicked', () => {
- const saveDate = jasmine.createSpy();
- vm.$on('saveDate', saveDate);
-
- vm.$el.querySelector('.value-content .btn-blank').click();
-
- expect(saveDate).toHaveBeenCalled();
- });
- });
-
- describe('showToggleSidebar', () => {
- beforeEach(done => {
- vm.showToggleSidebar = true;
- Vue.nextTick(done);
- });
-
- it('should render toggle-sidebar when showToggleSidebar', () => {
- expect(vm.$el.querySelector('.title .gutter-toggle')).toBeDefined();
- });
-
- it('should emit toggleCollapse when toggle sidebar is clicked', () => {
- const toggleCollapse = jasmine.createSpy();
- vm.$on('toggleCollapse', toggleCollapse);
-
- vm.$el.querySelector('.title .gutter-toggle').click();
-
- expect(toggleCollapse).toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/base_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/base_spec.js
deleted file mode 100644
index c44b04009ca..00000000000
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/base_spec.js
+++ /dev/null
@@ -1,130 +0,0 @@
-import Vue from 'vue';
-
-import LabelsSelect from '~/labels_select';
-import baseComponent from '~/vue_shared/components/sidebar/labels_select/base.vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-import { mockConfig, mockLabels } from './mock_data';
-
-const createComponent = (config = mockConfig) => {
- const Component = Vue.extend(baseComponent);
-
- return mountComponent(Component, config);
-};
-
-describe('BaseComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('computed', () => {
- describe('hiddenInputName', () => {
- it('returns correct string when showCreate prop is `true`', () => {
- expect(vm.hiddenInputName).toBe('issue[label_names][]');
- });
-
- it('returns correct string when showCreate prop is `false`', () => {
- const mockConfigNonEditable = Object.assign({}, mockConfig, { showCreate: false });
- const vmNonEditable = createComponent(mockConfigNonEditable);
-
- expect(vmNonEditable.hiddenInputName).toBe('label_id[]');
- vmNonEditable.$destroy();
- });
- });
-
- describe('createLabelTitle', () => {
- it('returns `Create project label` when `isProject` prop is true', () => {
- expect(vm.createLabelTitle).toBe('Create project label');
- });
-
- it('return `Create group label` when `isProject` prop is false', () => {
- const mockConfigGroup = Object.assign({}, mockConfig, { isProject: false });
- const vmGroup = createComponent(mockConfigGroup);
-
- expect(vmGroup.createLabelTitle).toBe('Create group label');
- vmGroup.$destroy();
- });
- });
-
- describe('manageLabelsTitle', () => {
- it('returns `Manage project labels` when `isProject` prop is true', () => {
- expect(vm.manageLabelsTitle).toBe('Manage project labels');
- });
-
- it('return `Manage group labels` when `isProject` prop is false', () => {
- const mockConfigGroup = Object.assign({}, mockConfig, { isProject: false });
- const vmGroup = createComponent(mockConfigGroup);
-
- expect(vmGroup.manageLabelsTitle).toBe('Manage group labels');
- vmGroup.$destroy();
- });
- });
- });
-
- describe('methods', () => {
- describe('handleClick', () => {
- it('emits onLabelClick event with label and list of labels as params', () => {
- spyOn(vm, '$emit');
- vm.handleClick(mockLabels[0]);
-
- expect(vm.$emit).toHaveBeenCalledWith('onLabelClick', mockLabels[0]);
- });
- });
-
- describe('handleCollapsedValueClick', () => {
- it('emits toggleCollapse event on component', () => {
- spyOn(vm, '$emit');
- vm.handleCollapsedValueClick();
-
- expect(vm.$emit).toHaveBeenCalledWith('toggleCollapse');
- });
- });
-
- describe('handleDropdownHidden', () => {
- it('emits onDropdownClose event on component', () => {
- spyOn(vm, '$emit');
- vm.handleDropdownHidden();
-
- expect(vm.$emit).toHaveBeenCalledWith('onDropdownClose');
- });
- });
- });
-
- describe('mounted', () => {
- it('creates LabelsSelect object and assigns it to `labelsDropdon` as prop', () => {
- expect(vm.labelsDropdown instanceof LabelsSelect).toBe(true);
- });
- });
-
- describe('template', () => {
- it('renders component container element with classes `block labels`', () => {
- expect(vm.$el.classList.contains('block')).toBe(true);
- expect(vm.$el.classList.contains('labels')).toBe(true);
- });
-
- it('renders `.selectbox` element', () => {
- expect(vm.$el.querySelector('.selectbox')).not.toBeNull();
- expect(vm.$el.querySelector('.selectbox').getAttribute('style')).toBe('display: none;');
- });
-
- it('renders `.dropdown` element', () => {
- expect(vm.$el.querySelector('.dropdown')).not.toBeNull();
- });
-
- it('renders `.dropdown-menu` element', () => {
- const dropdownMenuEl = vm.$el.querySelector('.dropdown-menu');
-
- expect(dropdownMenuEl).not.toBeNull();
- expect(dropdownMenuEl.querySelector('.dropdown-page-one')).not.toBeNull();
- expect(dropdownMenuEl.querySelector('.dropdown-content')).not.toBeNull();
- expect(dropdownMenuEl.querySelector('.dropdown-loading')).not.toBeNull();
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js
deleted file mode 100644
index 0689fc1cf1f..00000000000
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js
+++ /dev/null
@@ -1,95 +0,0 @@
-import Vue from 'vue';
-
-import dropdownButtonComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_button.vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-import { mockConfig, mockLabels } from './mock_data';
-
-const componentConfig = Object.assign({}, mockConfig, {
- fieldName: 'label_id[]',
- labels: mockLabels,
- showExtraOptions: false,
-});
-
-const createComponent = (config = componentConfig) => {
- const Component = Vue.extend(dropdownButtonComponent);
-
- return mountComponent(Component, config);
-};
-
-describe('DropdownButtonComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('computed', () => {
- describe('dropdownToggleText', () => {
- it('returns text as `Label` when `labels` prop is empty array', () => {
- const mockEmptyLabels = Object.assign({}, componentConfig, { labels: [] });
- const vmEmptyLabels = createComponent(mockEmptyLabels);
-
- expect(vmEmptyLabels.dropdownToggleText).toBe('Label');
- vmEmptyLabels.$destroy();
- });
-
- it('returns first label name with remaining label count when `labels` prop has more than one item', () => {
- const mockMoreLabels = Object.assign({}, componentConfig, {
- labels: mockLabels.concat(mockLabels),
- });
- const vmMoreLabels = createComponent(mockMoreLabels);
-
- expect(vmMoreLabels.dropdownToggleText).toBe(
- `Foo Label +${mockMoreLabels.labels.length - 1} more`,
- );
- vmMoreLabels.$destroy();
- });
-
- it('returns first label name when `labels` prop has only one item present', () => {
- const singleLabel = Object.assign({}, componentConfig, {
- labels: [mockLabels[0]],
- });
- const vmSingleLabel = createComponent(singleLabel);
-
- expect(vmSingleLabel.dropdownToggleText).toBe(mockLabels[0].title);
-
- vmSingleLabel.$destroy();
- });
- });
- });
-
- describe('template', () => {
- it('renders component container element of type `button`', () => {
- expect(vm.$el.nodeName).toBe('BUTTON');
- });
-
- it('renders component container element with required data attributes', () => {
- expect(vm.$el.dataset.abilityName).toBe(vm.abilityName);
- expect(vm.$el.dataset.fieldName).toBe(vm.fieldName);
- expect(vm.$el.dataset.issueUpdate).toBe(vm.updatePath);
- expect(vm.$el.dataset.labels).toBe(vm.labelsPath);
- expect(vm.$el.dataset.namespacePath).toBe(vm.namespace);
- expect(vm.$el.dataset.showAny).not.toBeDefined();
- });
-
- it('renders dropdown toggle text element', () => {
- const dropdownToggleTextEl = vm.$el.querySelector('.dropdown-toggle-text');
-
- expect(dropdownToggleTextEl).not.toBeNull();
- expect(dropdownToggleTextEl.innerText.trim()).toBe('Foo Label +1 more');
- });
-
- it('renders dropdown button icon', () => {
- const dropdownIconEl = vm.$el.querySelector('i.fa');
-
- expect(dropdownIconEl).not.toBeNull();
- expect(dropdownIconEl.classList.contains('fa-chevron-down')).toBe(true);
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js
deleted file mode 100644
index b8f32f96332..00000000000
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js
+++ /dev/null
@@ -1,108 +0,0 @@
-import Vue from 'vue';
-
-import dropdownCreateLabelComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-import { mockSuggestedColors } from './mock_data';
-
-const createComponent = headerTitle => {
- const Component = Vue.extend(dropdownCreateLabelComponent);
-
- return mountComponent(Component, {
- headerTitle,
- });
-};
-
-describe('DropdownCreateLabelComponent', () => {
- let vm;
-
- beforeEach(() => {
- gon.suggested_label_colors = mockSuggestedColors;
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('created', () => {
- it('initializes `suggestedColors` prop on component from `gon.suggested_color_labels` object', () => {
- expect(vm.suggestedColors.length).toBe(mockSuggestedColors.length);
- });
- });
-
- describe('template', () => {
- it('renders component container element with classes `dropdown-page-two dropdown-new-label`', () => {
- expect(vm.$el.classList.contains('dropdown-page-two', 'dropdown-new-label')).toBe(true);
- });
-
- it('renders `Go back` button on component header', () => {
- const backButtonEl = vm.$el.querySelector(
- '.dropdown-title button.dropdown-title-button.dropdown-menu-back',
- );
-
- expect(backButtonEl).not.toBe(null);
- expect(backButtonEl.querySelector('.fa-arrow-left')).not.toBe(null);
- });
-
- it('renders component header element as `Create new label` when `headerTitle` prop is not provided', () => {
- const headerEl = vm.$el.querySelector('.dropdown-title');
-
- expect(headerEl.innerText.trim()).toContain('Create new label');
- });
-
- it('renders component header element with value of `headerTitle` prop', () => {
- const headerTitle = 'Create project label';
- const vmWithHeaderTitle = createComponent(headerTitle);
- const headerEl = vmWithHeaderTitle.$el.querySelector('.dropdown-title');
-
- expect(headerEl.innerText.trim()).toContain(headerTitle);
- vmWithHeaderTitle.$destroy();
- });
-
- it('renders `Close` button on component header', () => {
- const closeButtonEl = vm.$el.querySelector(
- '.dropdown-title button.dropdown-title-button.dropdown-menu-close',
- );
-
- expect(closeButtonEl).not.toBe(null);
- expect(closeButtonEl.querySelector('.fa-times.dropdown-menu-close-icon')).not.toBe(null);
- });
-
- it('renders `Name new label` input element', () => {
- expect(vm.$el.querySelector('.dropdown-labels-error.js-label-error')).not.toBe(null);
- expect(vm.$el.querySelector('input#new_label_name.default-dropdown-input')).not.toBe(null);
- });
-
- it('renders suggested colors list elements', () => {
- const colorsListContainerEl = vm.$el.querySelector('.suggest-colors.suggest-colors-dropdown');
-
- expect(colorsListContainerEl).not.toBe(null);
- expect(colorsListContainerEl.querySelectorAll('a').length).toBe(mockSuggestedColors.length);
-
- const colorItemEl = colorsListContainerEl.querySelectorAll('a')[0];
-
- expect(colorItemEl.dataset.color).toBe(vm.suggestedColors[0]);
- expect(colorItemEl.getAttribute('style')).toBe('background-color: rgb(0, 51, 204);');
- });
-
- it('renders color input element', () => {
- expect(vm.$el.querySelector('.dropdown-label-color-input')).not.toBe(null);
- expect(
- vm.$el.querySelector('.dropdown-label-color-preview.js-dropdown-label-color-preview'),
- ).not.toBe(null);
-
- expect(vm.$el.querySelector('input#new_label_color.default-dropdown-input')).not.toBe(null);
- });
-
- it('renders component action buttons', () => {
- const createBtnEl = vm.$el.querySelector('button.js-new-label-btn');
- const cancelBtnEl = vm.$el.querySelector('button.js-cancel-label-btn');
-
- expect(createBtnEl).not.toBe(null);
- expect(createBtnEl.innerText.trim()).toBe('Create');
- expect(cancelBtnEl.innerText.trim()).toBe('Cancel');
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js
deleted file mode 100644
index 3711e9dac8c..00000000000
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import Vue from 'vue';
-
-import dropdownFooterComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_footer.vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-import { mockConfig } from './mock_data';
-
-const createComponent = (
- labelsWebUrl = mockConfig.labelsWebUrl,
- createLabelTitle,
- manageLabelsTitle,
-) => {
- const Component = Vue.extend(dropdownFooterComponent);
-
- return mountComponent(Component, {
- labelsWebUrl,
- createLabelTitle,
- manageLabelsTitle,
- });
-};
-
-describe('DropdownFooterComponent', () => {
- const createLabelTitle = 'Create project label';
- const manageLabelsTitle = 'Manage project labels';
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('template', () => {
- it('renders link element with `Create new label` when `createLabelTitle` prop is not provided', () => {
- const createLabelEl = vm.$el.querySelector('.dropdown-footer-list .dropdown-toggle-page');
-
- expect(createLabelEl).not.toBeNull();
- expect(createLabelEl.innerText.trim()).toBe('Create new label');
- });
-
- it('renders link element with value of `createLabelTitle` prop', () => {
- const vmWithCreateLabelTitle = createComponent(mockConfig.labelsWebUrl, createLabelTitle);
- const createLabelEl = vmWithCreateLabelTitle.$el.querySelector(
- '.dropdown-footer-list .dropdown-toggle-page',
- );
-
- expect(createLabelEl.innerText.trim()).toBe(createLabelTitle);
- vmWithCreateLabelTitle.$destroy();
- });
-
- it('renders link element with `Manage labels` when `manageLabelsTitle` prop is not provided', () => {
- const manageLabelsEl = vm.$el.querySelector('.dropdown-footer-list .dropdown-external-link');
-
- expect(manageLabelsEl).not.toBeNull();
- expect(manageLabelsEl.getAttribute('href')).toBe(vm.labelsWebUrl);
- expect(manageLabelsEl.innerText.trim()).toBe('Manage labels');
- });
-
- it('renders link element with value of `manageLabelsTitle` prop', () => {
- const vmWithManageLabelsTitle = createComponent(
- mockConfig.labelsWebUrl,
- createLabelTitle,
- manageLabelsTitle,
- );
- const manageLabelsEl = vmWithManageLabelsTitle.$el.querySelector(
- '.dropdown-footer-list .dropdown-external-link',
- );
-
- expect(manageLabelsEl.innerText.trim()).toBe(manageLabelsTitle);
- vmWithManageLabelsTitle.$destroy();
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js
deleted file mode 100644
index 115e21e4f9f..00000000000
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import Vue from 'vue';
-
-import dropdownHeaderComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_header.vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-const createComponent = () => {
- const Component = Vue.extend(dropdownHeaderComponent);
-
- return mountComponent(Component);
-};
-
-describe('DropdownHeaderComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('template', () => {
- it('renders header text element', () => {
- const headerEl = vm.$el.querySelector('.dropdown-title span');
-
- expect(headerEl.innerText.trim()).toBe('Assign labels');
- });
-
- it('renders `Close` button element', () => {
- const closeBtnEl = vm.$el.querySelector(
- '.dropdown-title button.dropdown-title-button.dropdown-menu-close',
- );
-
- expect(closeBtnEl).not.toBeNull();
- expect(closeBtnEl.querySelector('.fa-times.dropdown-menu-close-icon')).not.toBeNull();
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js
deleted file mode 100644
index c30e619e76b..00000000000
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import Vue from 'vue';
-
-import dropdownSearchInputComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_search_input.vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-const createComponent = () => {
- const Component = Vue.extend(dropdownSearchInputComponent);
-
- return mountComponent(Component);
-};
-
-describe('DropdownSearchInputComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('template', () => {
- it('renders input element with type `search`', () => {
- const inputEl = vm.$el.querySelector('input.dropdown-input-field');
-
- expect(inputEl).not.toBeNull();
- expect(inputEl.getAttribute('type')).toBe('search');
- });
-
- it('renders search icon element', () => {
- expect(vm.$el.querySelector('.fa-search.dropdown-input-search')).not.toBeNull();
- });
-
- it('renders clear search icon element', () => {
- expect(
- vm.$el.querySelector('.fa-times.dropdown-input-clear.js-dropdown-input-clear'),
- ).not.toBeNull();
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js
deleted file mode 100644
index 6c84d2e167c..00000000000
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import Vue from 'vue';
-
-import dropdownTitleComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_title.vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-const createComponent = (canEdit = true) => {
- const Component = Vue.extend(dropdownTitleComponent);
-
- return mountComponent(Component, {
- canEdit,
- });
-};
-
-describe('DropdownTitleComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('template', () => {
- it('renders title text', () => {
- expect(vm.$el.classList.contains('title', 'hide-collapsed')).toBe(true);
- expect(vm.$el.innerText.trim()).toContain('Labels');
- });
-
- it('renders spinner icon element', () => {
- expect(vm.$el.querySelector('.fa-spinner.fa-spin.block-loading')).not.toBeNull();
- });
-
- it('renders `Edit` button element', () => {
- const editBtnEl = vm.$el.querySelector('button.edit-link.js-sidebar-dropdown-toggle');
-
- expect(editBtnEl).not.toBeNull();
- expect(editBtnEl.innerText.trim()).toBe('Edit');
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
deleted file mode 100644
index cb49fa31d20..00000000000
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
+++ /dev/null
@@ -1,98 +0,0 @@
-import Vue from 'vue';
-
-import dropdownValueCollapsedComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-import { mockLabels } from './mock_data';
-
-const createComponent = (labels = mockLabels) => {
- const Component = Vue.extend(dropdownValueCollapsedComponent);
-
- return mountComponent(Component, {
- labels,
- });
-};
-
-describe('DropdownValueCollapsedComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('computed', () => {
- describe('labelsList', () => {
- it('returns empty text when `labels` prop is empty array', () => {
- const vmEmptyLabels = createComponent([]);
-
- expect(vmEmptyLabels.labelsList).toBe('');
- vmEmptyLabels.$destroy();
- });
-
- it('returns labels names separated by coma when `labels` prop has more than one item', () => {
- const labels = mockLabels.concat(mockLabels);
- const vmMoreLabels = createComponent(labels);
-
- const expectedText = labels.map(label => label.title).join(', ');
-
- expect(vmMoreLabels.labelsList).toBe(expectedText);
- vmMoreLabels.$destroy();
- });
-
- it('returns labels names separated by coma with remaining labels count and `and more` phrase when `labels` prop has more than five items', () => {
- const mockMoreLabels = Object.assign([], mockLabels);
- for (let i = 0; i < 6; i += 1) {
- mockMoreLabels.unshift(mockLabels[0]);
- }
-
- const vmMoreLabels = createComponent(mockMoreLabels);
-
- const expectedText = `${mockMoreLabels
- .slice(0, 5)
- .map(label => label.title)
- .join(', ')}, and ${mockMoreLabels.length - 5} more`;
-
- expect(vmMoreLabels.labelsList).toBe(expectedText);
- vmMoreLabels.$destroy();
- });
-
- it('returns first label name when `labels` prop has only one item present', () => {
- const text = mockLabels.map(label => label.title).join(', ');
-
- expect(vm.labelsList).toBe(text);
- });
- });
- });
-
- describe('methods', () => {
- describe('handleClick', () => {
- it('emits onValueClick event on component', () => {
- spyOn(vm, '$emit');
- vm.handleClick();
-
- expect(vm.$emit).toHaveBeenCalledWith('onValueClick');
- });
- });
- });
-
- describe('template', () => {
- it('renders component container element with tooltip`', () => {
- expect(vm.$el.dataset.placement).toBe('left');
- expect(vm.$el.dataset.container).toBe('body');
- expect(vm.$el.dataset.originalTitle).toBe(vm.labelsList);
- });
-
- it('renders tags icon element', () => {
- expect(vm.$el.querySelector('.fa-tags')).not.toBeNull();
- });
-
- it('renders labels count', () => {
- expect(vm.$el.querySelector('span').innerText.trim()).toBe(`${vm.labels.length}`);
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js
deleted file mode 100644
index 35a9c300953..00000000000
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js
+++ /dev/null
@@ -1,137 +0,0 @@
-import Vue from 'vue';
-import $ from 'jquery';
-
-import dropdownValueComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_value.vue';
-
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-import { mockConfig, mockLabels } from './mock_data';
-
-const createComponent = (
- labels = mockLabels,
- labelFilterBasePath = mockConfig.labelFilterBasePath,
-) => {
- const Component = Vue.extend(dropdownValueComponent);
-
- return mountComponent(Component, {
- labels,
- labelFilterBasePath,
- enableScopedLabels: true,
- });
-};
-
-describe('DropdownValueComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('computed', () => {
- describe('isEmpty', () => {
- it('returns true if `labels` prop is empty', () => {
- const vmEmptyLabels = createComponent([]);
-
- expect(vmEmptyLabels.isEmpty).toBe(true);
- vmEmptyLabels.$destroy();
- });
-
- it('returns false if `labels` prop is empty', () => {
- expect(vm.isEmpty).toBe(false);
- });
- });
- });
-
- describe('methods', () => {
- describe('labelFilterUrl', () => {
- it('returns URL string starting with labelFilterBasePath and encoded label.title', () => {
- expect(
- vm.labelFilterUrl({
- title: 'Foo bar',
- }),
- ).toBe('/gitlab-org/my-project/issues?label_name[]=Foo%20bar');
- });
- });
-
- describe('labelStyle', () => {
- it('returns object with `color` & `backgroundColor` properties from label.textColor & label.color', () => {
- const label = {
- textColor: '#FFFFFF',
- color: '#BADA55',
- };
- const styleObj = vm.labelStyle(label);
-
- expect(styleObj.color).toBe(label.textColor);
- expect(styleObj.backgroundColor).toBe(label.color);
- });
- });
-
- describe('scopedLabelsDescription', () => {
- it('returns html for tooltip', () => {
- const html = vm.scopedLabelsDescription(mockLabels[1]);
- const $el = $.parseHTML(html);
-
- expect($el[0]).toHaveClass('scoped-label-tooltip-title');
- expect($el[2].textContent).toEqual(mockLabels[1].description);
- });
- });
-
- describe('showScopedLabels', () => {
- it('returns true if the label is scoped label', () => {
- expect(vm.showScopedLabels(mockLabels[1])).toBe(true);
- });
-
- it('returns false when label is a regular label', () => {
- expect(vm.showScopedLabels(mockLabels[0])).toBe(false);
- });
- });
- });
-
- describe('template', () => {
- it('renders component container element with classes `hide-collapsed value issuable-show-labels`', () => {
- expect(vm.$el.classList.contains('hide-collapsed', 'value', 'issuable-show-labels')).toBe(
- true,
- );
- });
-
- it('render slot content inside component when `labels` prop is empty', () => {
- const vmEmptyLabels = createComponent([]);
-
- expect(vmEmptyLabels.$el.querySelector('.text-secondary').innerText.trim()).toBe(
- mockConfig.emptyValueText,
- );
- vmEmptyLabels.$destroy();
- });
-
- it('renders label element with filter URL', () => {
- expect(vm.$el.querySelector('a').getAttribute('href')).toBe(
- '/gitlab-org/my-project/issues?label_name[]=Foo%20Label',
- );
- });
-
- it('renders label element and styles based on label details', () => {
- const labelEl = vm.$el.querySelector('a span.badge.color-label');
-
- expect(labelEl).not.toBeNull();
- expect(labelEl.getAttribute('style')).toBe('background-color: rgb(186, 218, 85);');
- expect(labelEl.innerText.trim()).toBe(mockLabels[0].title);
- });
-
- describe('label is of scoped-label type', () => {
- it('renders a scoped-label-wrapper span to incorporate 2 anchors', () => {
- expect(vm.$el.querySelector('span.scoped-label-wrapper')).not.toBeNull();
- });
-
- it('renders anchor tag containing question icon', () => {
- const anchor = vm.$el.querySelector('.scoped-label-wrapper a.scoped-label');
-
- expect(anchor).not.toBeNull();
- expect(anchor.querySelector('i.fa-question-circle')).not.toBeNull();
- });
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/mock_data.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/mock_data.js
index 70025f041a7..6564c012e67 100644
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/mock_data.js
+++ b/spec/javascripts/vue_shared/components/sidebar/labels_select/mock_data.js
@@ -48,8 +48,8 @@ export const mockConfig = {
},
namespace: 'gitlab-org',
updatePath: '/gitlab-org/my-project/issue/1',
- labelsPath: '/gitlab-org/my-project/labels.json',
- labelsWebUrl: '/gitlab-org/my-project/labels',
+ labelsPath: '/gitlab-org/my-project/-/labels.json',
+ labelsWebUrl: '/gitlab-org/my-project/-/labels',
labelFilterBasePath: '/gitlab-org/my-project/issues',
canEdit: true,
suggestedColors: mockSuggestedColors,
diff --git a/spec/javascripts/vue_shared/components/sidebar/toggle_sidebar_spec.js b/spec/javascripts/vue_shared/components/sidebar/toggle_sidebar_spec.js
deleted file mode 100644
index c911a129173..00000000000
--- a/spec/javascripts/vue_shared/components/sidebar/toggle_sidebar_spec.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import Vue from 'vue';
-import toggleSidebar from '~/vue_shared/components/sidebar/toggle_sidebar.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-describe('toggleSidebar', () => {
- let vm;
- beforeEach(() => {
- const ToggleSidebar = Vue.extend(toggleSidebar);
- vm = mountComponent(ToggleSidebar, {
- collapsed: true,
- });
- });
-
- it('should render << when collapsed', () => {
- expect(vm.$el.querySelector('.fa').classList.contains('fa-angle-double-left')).toEqual(true);
- });
-
- it('should render >> when collapsed', () => {
- vm.collapsed = false;
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.fa').classList.contains('fa-angle-double-right')).toEqual(true);
- });
- });
-
- it('should emit toggle event when button clicked', () => {
- const toggle = jasmine.createSpy();
- vm.$on('toggle', toggle);
- vm.$el.click();
-
- expect(toggle).toHaveBeenCalled();
- });
-});
diff --git a/spec/javascripts/vue_shared/components/table_pagination_spec.js b/spec/javascripts/vue_shared/components/table_pagination_spec.js
index 42cd41381dc..42abb4d83f0 100644
--- a/spec/javascripts/vue_shared/components/table_pagination_spec.js
+++ b/spec/javascripts/vue_shared/components/table_pagination_spec.js
@@ -1,5 +1,5 @@
import Vue from 'vue';
-import paginationComp from '~/vue_shared/components/table_pagination.vue';
+import paginationComp from '~/vue_shared/components/pagination/table_pagination.vue';
describe('Pagination component', () => {
let component;
diff --git a/spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js b/spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js
index 852558a83bc..c7e0d806d80 100644
--- a/spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js
+++ b/spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js
@@ -61,6 +61,12 @@ describe('User Popover Component', () => {
expect(vm.$el.textContent).toContain(DEFAULT_PROPS.user.username);
expect(vm.$el.textContent).toContain(DEFAULT_PROPS.user.location);
});
+
+ it('shows icon for location', () => {
+ const iconEl = vm.$el.querySelector('.js-location svg');
+
+ expect(iconEl.querySelector('use').getAttribute('xlink:href')).toContain('location');
+ });
});
describe('job data', () => {
@@ -117,6 +123,18 @@ describe('User Popover Component', () => {
'Me & my <funky> Company',
);
});
+
+ it('shows icon for bio', () => {
+ const iconEl = vm.$el.querySelector('.js-bio svg');
+
+ expect(iconEl.querySelector('use').getAttribute('xlink:href')).toContain('profile');
+ });
+
+ it('shows icon for organization', () => {
+ const iconEl = vm.$el.querySelector('.js-organization svg');
+
+ expect(iconEl.querySelector('use').getAttribute('xlink:href')).toContain('work');
+ });
});
describe('status data', () => {
diff --git a/spec/javascripts/vue_shared/translate_spec.js b/spec/javascripts/vue_shared/translate_spec.js
index adb5ff682f0..0aaa4050cba 100644
--- a/spec/javascripts/vue_shared/translate_spec.js
+++ b/spec/javascripts/vue_shared/translate_spec.js
@@ -3,7 +3,7 @@ import Jed from 'jed';
import locale from '~/locale';
import Translate from '~/vue_shared/translate';
-import { trimText } from 'spec/helpers/vue_component_helper';
+import { trimText } from 'spec/helpers/text_helper';
describe('Vue translate filter', () => {
let el;
diff --git a/spec/lib/api/helpers/pagination_spec.rb b/spec/lib/api/helpers/pagination_spec.rb
index 6e215ea1561..c788da55cd2 100644
--- a/spec/lib/api/helpers/pagination_spec.rb
+++ b/spec/lib/api/helpers/pagination_spec.rb
@@ -2,8 +2,12 @@ require 'spec_helper'
describe API::Helpers::Pagination do
let(:resource) { Project.all }
- let(:incoming_api_projects_url) { "#{Gitlab.config.gitlab.url}:8080/api/v4/projects" }
- let(:canonical_api_projects_url) { "#{Gitlab.config.gitlab.url}/api/v4/projects" }
+ let(:custom_port) { 8080 }
+ let(:incoming_api_projects_url) { "#{Gitlab.config.gitlab.url}:#{custom_port}/api/v4/projects" }
+
+ before do
+ stub_config_setting(port: custom_port)
+ end
subject do
Class.new.include(described_class).new
@@ -48,7 +52,7 @@ describe API::Helpers::Pagination do
it 'adds appropriate headers' do
expect_header('X-Per-Page', '2')
- expect_header('X-Next-Page', "#{canonical_api_projects_url}?#{query.merge(ks_prev_id: projects[1].id).to_query}")
+ expect_header('X-Next-Page', "#{incoming_api_projects_url}?#{query.merge(ks_prev_id: projects[1].id).to_query}")
expect_header('Link', anything) do |_key, val|
expect(val).to include('rel="next"')
@@ -71,7 +75,7 @@ describe API::Helpers::Pagination do
it 'adds appropriate headers' do
expect_header('X-Per-Page', '2')
- expect_header('X-Next-Page', "#{canonical_api_projects_url}?#{query.merge(ks_prev_id: projects[2].id).to_query}")
+ expect_header('X-Next-Page', "#{incoming_api_projects_url}?#{query.merge(ks_prev_id: projects[2].id).to_query}")
expect_header('Link', anything) do |_key, val|
expect(val).to include('rel="next"')
@@ -171,7 +175,7 @@ describe API::Helpers::Pagination do
it 'returns the right link to the next page' do
expect_header('X-Per-Page', '2')
- expect_header('X-Next-Page', "#{canonical_api_projects_url}?#{query.merge(ks_prev_id: projects[6].id, ks_prev_name: projects[6].name).to_query}")
+ expect_header('X-Next-Page', "#{incoming_api_projects_url}?#{query.merge(ks_prev_id: projects[6].id, ks_prev_name: projects[6].name).to_query}")
expect_header('Link', anything) do |_key, val|
expect(val).to include('rel="next"')
end
@@ -224,9 +228,9 @@ describe API::Helpers::Pagination do
expect_header('X-Prev-Page', '')
expect_header('Link', anything) do |_key, val|
- expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first"))
- expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="last"))
- expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="next"))
+ expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first"))
+ expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="last"))
+ expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="next"))
expect(val).not_to include('rel="prev"')
end
@@ -290,8 +294,8 @@ describe API::Helpers::Pagination do
expect_header('X-Prev-Page', '')
expect_header('Link', anything) do |_key, val|
- expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first"))
- expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="next"))
+ expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first"))
+ expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="next"))
expect(val).not_to include('rel="last"')
expect(val).not_to include('rel="prev"')
end
@@ -318,9 +322,9 @@ describe API::Helpers::Pagination do
expect_header('X-Prev-Page', '1')
expect_header('Link', anything) do |_key, val|
- expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first"))
- expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="last"))
- expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="prev"))
+ expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first"))
+ expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="last"))
+ expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="prev"))
expect(val).not_to include('rel="next"')
end
@@ -367,8 +371,8 @@ describe API::Helpers::Pagination do
expect_header('X-Prev-Page', '')
expect_header('Link', anything) do |_key, val|
- expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first"))
- expect(val).to include(%Q(<#{canonical_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="last"))
+ expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first"))
+ expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="last"))
expect(val).not_to include('rel="prev"')
expect(val).not_to include('rel="next"')
expect(val).not_to include('page=0')
diff --git a/spec/lib/api/helpers/related_resources_helpers_spec.rb b/spec/lib/api/helpers/related_resources_helpers_spec.rb
index 66af7f81535..99fe8795d91 100644
--- a/spec/lib/api/helpers/related_resources_helpers_spec.rb
+++ b/spec/lib/api/helpers/related_resources_helpers_spec.rb
@@ -5,6 +5,40 @@ describe API::Helpers::RelatedResourcesHelpers do
Class.new.include(described_class).new
end
+ describe '#expose_path' do
+ let(:path) { '/api/v4/awesome_endpoint' }
+
+ context 'empty relative URL root' do
+ before do
+ stub_config_setting(relative_url_root: '')
+ end
+
+ it 'returns the existing path' do
+ expect(helpers.expose_path(path)).to eq(path)
+ end
+ end
+
+ context 'slash relative URL root' do
+ before do
+ stub_config_setting(relative_url_root: '/')
+ end
+
+ it 'returns the existing path' do
+ expect(helpers.expose_path(path)).to eq(path)
+ end
+ end
+
+ context 'with relative URL root' do
+ before do
+ stub_config_setting(relative_url_root: '/gitlab/root')
+ end
+
+ it 'returns the existing path' do
+ expect(helpers.expose_path(path)).to eq("/gitlab/root" + path)
+ end
+ end
+ end
+
describe '#expose_url' do
let(:path) { '/api/v4/awesome_endpoint' }
subject(:url) { helpers.expose_url(path) }
diff --git a/spec/lib/api/helpers_spec.rb b/spec/lib/api/helpers_spec.rb
index 08165f147bb..00916f80784 100644
--- a/spec/lib/api/helpers_spec.rb
+++ b/spec/lib/api/helpers_spec.rb
@@ -137,18 +137,6 @@ describe API::Helpers do
it_behaves_like 'user namespace finder'
end
- describe '#user_namespace' do
- let(:namespace_finder) do
- subject.user_namespace
- end
-
- before do
- allow(subject).to receive(:params).and_return({ id: namespace.id })
- end
-
- it_behaves_like 'user namespace finder'
- end
-
describe '#send_git_blob' do
let(:repository) { double }
let(:blob) { double(name: 'foobar') }
diff --git a/spec/lib/banzai/commit_renderer_spec.rb b/spec/lib/banzai/commit_renderer_spec.rb
index 1f53657c59c..316dbf052c3 100644
--- a/spec/lib/banzai/commit_renderer_spec.rb
+++ b/spec/lib/banzai/commit_renderer_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Banzai::CommitRenderer do
- describe '.render' do
+ describe '.render', :clean_gitlab_redis_cache do
it 'renders a commit description and title' do
user = build(:user)
project = create(:project, :repository)
@@ -13,7 +13,7 @@ describe Banzai::CommitRenderer do
described_class::ATTRIBUTES.each do |attr|
expect_any_instance_of(Banzai::ObjectRenderer).to receive(:render).with([project.commit], attr).once.and_call_original
- expect(Banzai::Renderer).to receive(:cacheless_render_field).with(project.commit, attr, {})
+ expect(Banzai::Renderer).to receive(:cacheless_render_field).with(project.commit, attr, { skip_project_check: false }).and_call_original
end
described_class.render([project.commit], project, user)
diff --git a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
index 43222ddb5e2..7c94cf37e32 100644
--- a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
@@ -155,6 +155,13 @@ describe Banzai::Filter::ExternalIssueReferenceFilter do
it_behaves_like "external issue tracker"
end
+
+ context "with a lowercase prefix" do
+ let(:issue) { ExternalIssue.new("gl-030", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
end
context "jira project" do
diff --git a/spec/lib/banzai/filter/milestone_reference_filter_spec.rb b/spec/lib/banzai/filter/milestone_reference_filter_spec.rb
index 4c94e4fdae0..f0a5dc8d0d7 100644
--- a/spec/lib/banzai/filter/milestone_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/milestone_reference_filter_spec.rb
@@ -295,6 +295,25 @@ describe Banzai::Filter::MilestoneReferenceFilter do
end
end
+ shared_examples 'references with HTML entities' do
+ before do
+ milestone.update!(title: '&lt;html&gt;')
+ end
+
+ it 'links to a valid reference' do
+ doc = reference_filter('See %"&lt;html&gt;"')
+
+ expect(doc.css('a').first.attr('href')).to eq urls.milestone_url(milestone)
+ expect(doc.text).to eq 'See %<html>'
+ end
+
+ it 'ignores invalid milestone names and escapes entities' do
+ act = %(Milestone %"&lt;non valid&gt;")
+
+ expect(reference_filter(act).to_html).to eq act
+ end
+ end
+
shared_context 'project milestones' do
let(:reference) { milestone.to_reference(format: :iid) }
@@ -307,6 +326,7 @@ describe Banzai::Filter::MilestoneReferenceFilter do
it_behaves_like 'cross-project / cross-namespace complete reference'
it_behaves_like 'cross-project / same-namespace complete reference'
it_behaves_like 'cross project shorthand reference'
+ it_behaves_like 'references with HTML entities'
end
shared_context 'group milestones' do
@@ -317,6 +337,7 @@ describe Banzai::Filter::MilestoneReferenceFilter do
it_behaves_like 'String-based single-word references'
it_behaves_like 'String-based multi-word references in quotes'
it_behaves_like 'referencing a milestone in a link href'
+ it_behaves_like 'references with HTML entities'
it 'does not support references by IID' do
doc = reference_filter("See #{Milestone.reference_prefix}#{milestone.iid}")
diff --git a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
index 05057789cc1..80ca7a63435 100644
--- a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
+++ b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
@@ -80,7 +80,7 @@ describe Banzai::Filter::SyntaxHighlightFilter do
let(:lang) { 'suggestion' }
let(:lang_params) { '-1+10' }
- it "delimits on the first appearence" do
+ it "delimits on the first appearance" do
result = filter(%{<pre><code lang="#{lang}#{delimiter}#{lang_params}#{delimiter}more-things">This is a test</code></pre>})
expect(result.to_html).to eq(%{<pre class="code highlight js-syntax-highlight #{lang}" lang="#{lang}" #{data_attr}="#{lang_params}#{delimiter}more-things" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre>})
diff --git a/spec/lib/banzai/filter/table_of_contents_filter_spec.rb b/spec/lib/banzai/filter/table_of_contents_filter_spec.rb
index 7213cd58ea7..4a9880ac85a 100644
--- a/spec/lib/banzai/filter/table_of_contents_filter_spec.rb
+++ b/spec/lib/banzai/filter/table_of_contents_filter_spec.rb
@@ -58,6 +58,11 @@ describe Banzai::Filter::TableOfContentsFilter do
expect(doc.css('h1 a').first.attr('href')).to eq '#this-header-is-filled-with-punctuation'
end
+ it 'removes any leading or trailing spaces' do
+ doc = filter(header(1, " \r\n\tTitle with spaces\r\n\t "))
+ expect(doc.css('h1 a').first.attr('href')).to eq '#title-with-spaces'
+ end
+
it 'appends a unique number to duplicates' do
doc = filter(header(1, 'One') + header(2, 'One'))
diff --git a/spec/lib/banzai/filter/wiki_link_filter_spec.rb b/spec/lib/banzai/filter/wiki_link_filter_spec.rb
index b9059b85fdc..cce1cd0b284 100644
--- a/spec/lib/banzai/filter/wiki_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/wiki_link_filter_spec.rb
@@ -70,5 +70,47 @@ describe Banzai::Filter::WikiLinkFilter do
expect(filtered_link.attribute('href').value).to eq(invalid_link)
end
end
+
+ context "when the slug is deemed unsafe or invalid" do
+ let(:link) { "alert(1);" }
+
+ invalid_slugs = [
+ "javascript:",
+ "JaVaScRiPt:",
+ "\u0001java\u0003script:",
+ "javascript :",
+ "javascript: ",
+ "javascript : ",
+ ":javascript:",
+ "javascript&#58;",
+ "javascript&#0058;",
+ "javascript&#x3A;",
+ "javascript&#x003A;",
+ "java\0script:",
+ " &#14; javascript:"
+ ]
+
+ invalid_slugs.each do |slug|
+ context "with the slug #{slug}" do
+ it "doesn't rewrite a (.) relative link" do
+ filtered_link = filter(
+ "<a href='.#{link}'>Link</a>",
+ project_wiki: wiki,
+ page_slug: slug).children[0]
+
+ expect(filtered_link.attribute('href').value).not_to include(slug)
+ end
+
+ it "doesn't rewrite a (..) relative link" do
+ filtered_link = filter(
+ "<a href='..#{link}'>Link</a>",
+ project_wiki: wiki,
+ page_slug: slug).children[0]
+
+ expect(filtered_link.attribute('href').value).not_to include(slug)
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/lib/banzai/object_renderer_spec.rb b/spec/lib/banzai/object_renderer_spec.rb
index 3b52f6666d0..7b855251a74 100644
--- a/spec/lib/banzai/object_renderer_spec.rb
+++ b/spec/lib/banzai/object_renderer_spec.rb
@@ -11,7 +11,7 @@ describe Banzai::ObjectRenderer do
)
end
- let(:object) { Note.new(note: 'hello', note_html: '<p dir="auto">hello</p>', cached_markdown_version: CacheMarkdownField::CACHE_COMMONMARK_VERSION << 16) }
+ let(:object) { Note.new(note: 'hello', note_html: '<p dir="auto">hello</p>', cached_markdown_version: Gitlab::MarkdownCache::CACHE_COMMONMARK_VERSION << 16) }
describe '#render' do
context 'with cache' do
@@ -60,24 +60,38 @@ describe Banzai::ObjectRenderer do
end
context 'without cache' do
- let(:commit) { project.commit }
+ let(:cacheless_class) do
+ Class.new do
+ attr_accessor :title, :redacted_title_html, :project
+
+ def banzai_render_context(field)
+ { project: project, pipeline: :single_line }
+ end
+ end
+ end
+ let(:cacheless_thing) do
+ cacheless_class.new.tap do |thing|
+ thing.title = "Merge branch 'branch-merged' into 'master'"
+ thing.project = project
+ end
+ end
it 'renders and redacts an Array of objects' do
- renderer.render([commit], :title)
+ renderer.render([cacheless_thing], :title)
- expect(commit.redacted_title_html).to eq("Merge branch 'branch-merged' into 'master'")
+ expect(cacheless_thing.redacted_title_html).to eq("Merge branch 'branch-merged' into 'master'")
end
it 'calls Banzai::Redactor to perform redaction' do
expect_any_instance_of(Banzai::Redactor).to receive(:redact).and_call_original
- renderer.render([commit], :title)
+ renderer.render([cacheless_thing], :title)
end
it 'retrieves field content using Banzai::Renderer.cacheless_render_field' do
- expect(Banzai::Renderer).to receive(:cacheless_render_field).with(commit, :title, {}).and_call_original
+ expect(Banzai::Renderer).to receive(:cacheless_render_field).with(cacheless_thing, :title, {}).and_call_original
- renderer.render([commit], :title)
+ renderer.render([cacheless_thing], :title)
end
end
end
diff --git a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
index 91b0499375d..7119c826bca 100644
--- a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
@@ -117,4 +117,27 @@ describe Banzai::Pipeline::GfmPipeline do
expect(output).not_to include("javascript")
end
end
+
+ describe 'emoji in references' do
+ set(:project) { create(:project, :public) }
+ let(:emoji) { '💯' }
+
+ it 'renders a label reference with emoji inside' do
+ create(:label, project: project, name: emoji)
+
+ output = described_class.to_html("#{Label.reference_prefix}\"#{emoji}\"", project: project)
+
+ expect(output).to include(emoji)
+ expect(output).to include(Gitlab::Routing.url_helpers.project_issues_path(project, label_name: emoji))
+ end
+
+ it 'renders a milestone reference with emoji inside' do
+ milestone = create(:milestone, project: project, title: emoji)
+
+ output = described_class.to_html("#{Milestone.reference_prefix}\"#{emoji}\"", project: project)
+
+ expect(output).to include(emoji)
+ expect(output).to include(Gitlab::Routing.url_helpers.milestone_path(milestone))
+ end
+ end
end
diff --git a/spec/lib/banzai/redactor_spec.rb b/spec/lib/banzai/redactor_spec.rb
index aaeec953e4b..718649e0e10 100644
--- a/spec/lib/banzai/redactor_spec.rb
+++ b/spec/lib/banzai/redactor_spec.rb
@@ -13,10 +13,10 @@ describe Banzai::Redactor do
it 'redacts an array of documents' do
doc1 = Nokogiri::HTML
- .fragment('<a class="gfm" data-reference-type="issue">foo</a>')
+ .fragment('<a class="gfm" href="https://www.gitlab.com" data-reference-type="issue">foo</a>')
doc2 = Nokogiri::HTML
- .fragment('<a class="gfm" data-reference-type="issue">bar</a>')
+ .fragment('<a class="gfm" href="https://www.gitlab.com" data-reference-type="issue">bar</a>')
redacted_data = redactor.redact([doc1, doc2])
@@ -27,7 +27,7 @@ describe Banzai::Redactor do
end
it 'replaces redacted reference with inner HTML' do
- doc = Nokogiri::HTML.fragment("<a class='gfm' data-reference-type='issue'>foo</a>")
+ doc = Nokogiri::HTML.fragment("<a class='gfm' href='https://www.gitlab.com' data-reference-type='issue'>foo</a>")
redactor.redact([doc])
expect(doc.to_html).to eq('foo')
end
@@ -35,20 +35,24 @@ describe Banzai::Redactor do
context 'when data-original attribute provided' do
let(:original_content) { '<code>foo</code>' }
it 'replaces redacted reference with original content' do
- doc = Nokogiri::HTML.fragment("<a class='gfm' data-reference-type='issue' data-original='#{original_content}'>bar</a>")
+ doc = Nokogiri::HTML.fragment("<a class='gfm' href='https://www.gitlab.com' data-reference-type='issue' data-original='#{original_content}'>bar</a>")
redactor.redact([doc])
expect(doc.to_html).to eq(original_content)
end
- end
-
- it 'returns <a> tag with original href if it is originally a link reference' do
- href = 'http://localhost:3000'
- doc = Nokogiri::HTML
- .fragment("<a class='gfm' data-reference-type='issue' data-original=#{href} data-link-reference='true'>#{href}</a>")
- redactor.redact([doc])
+ it 'does not replace redacted reference with original content if href is given' do
+ html = "<a href='https://www.gitlab.com' data-link-reference='true' class='gfm' data-reference-type='issue' data-reference-type='issue' data-original='Marge'>Marge</a>"
+ doc = Nokogiri::HTML.fragment(html)
+ redactor.redact([doc])
+ expect(doc.to_html).to eq('<a href="https://www.gitlab.com">Marge</a>')
+ end
- expect(doc.to_html).to eq('<a href="http://localhost:3000">http://localhost:3000</a>')
+ it 'uses the original content as the link content if given' do
+ html = "<a href='https://www.gitlab.com' data-link-reference='true' class='gfm' data-reference-type='issue' data-reference-type='issue' data-original='Homer'>Marge</a>"
+ doc = Nokogiri::HTML.fragment(html)
+ redactor.redact([doc])
+ expect(doc.to_html).to eq('<a href="https://www.gitlab.com">Homer</a>')
+ end
end
end
@@ -61,7 +65,7 @@ describe Banzai::Redactor do
end
it 'redacts an issue attached' do
- doc = Nokogiri::HTML.fragment("<a class='gfm' data-reference-type='issue' data-issue='#{issue.id}'>foo</a>")
+ doc = Nokogiri::HTML.fragment("<a class='gfm' href='https://www.gitlab.com' data-reference-type='issue' data-issue='#{issue.id}'>foo</a>")
redactor.redact([doc])
@@ -69,7 +73,7 @@ describe Banzai::Redactor do
end
it 'redacts an external issue' do
- doc = Nokogiri::HTML.fragment("<a class='gfm' data-reference-type='issue' data-external-issue='#{issue.id}' data-project='#{project.id}'>foo</a>")
+ doc = Nokogiri::HTML.fragment("<a class='gfm' href='https://www.gitlab.com' data-reference-type='issue' data-external-issue='#{issue.id}' data-project='#{project.id}'>foo</a>")
redactor.redact([doc])
diff --git a/spec/lib/banzai/renderer_spec.rb b/spec/lib/banzai/renderer_spec.rb
index 650cecfc778..aa828e2f0e9 100644
--- a/spec/lib/banzai/renderer_spec.rb
+++ b/spec/lib/banzai/renderer_spec.rb
@@ -11,16 +11,24 @@ describe Banzai::Renderer do
object
end
+ def fake_cacheless_object
+ object = double('cacheless object')
+
+ allow(object).to receive(:respond_to?).with(:cached_markdown_fields).and_return(false)
+
+ object
+ end
+
describe '#render_field' do
let(:renderer) { described_class }
context 'without cache' do
- let(:commit) { create(:project, :repository).commit }
+ let(:commit) { fake_cacheless_object }
it 'returns cacheless render field' do
- expect(renderer).to receive(:cacheless_render_field).with(commit, :title, {})
+ expect(renderer).to receive(:cacheless_render_field).with(commit, :field, {})
- renderer.render_field(commit, :title)
+ renderer.render_field(commit, :field)
end
end
diff --git a/spec/lib/gitlab/asciidoc_spec.rb b/spec/lib/gitlab/asciidoc_spec.rb
index e1782cff81a..0f933ac5464 100644
--- a/spec/lib/gitlab/asciidoc_spec.rb
+++ b/spec/lib/gitlab/asciidoc_spec.rb
@@ -3,20 +3,23 @@ require 'nokogiri'
module Gitlab
describe Asciidoc do
- let(:input) { '<b>ascii</b>' }
- let(:context) { {} }
- let(:html) { 'H<sub>2</sub>O' }
+ include FakeBlobHelpers
+
+ before do
+ allow_any_instance_of(ApplicationSetting).to receive(:current).and_return(::ApplicationSetting.create_from_defaults)
+ end
context "without project" do
- before do
- allow_any_instance_of(ApplicationSetting).to receive(:current).and_return(::ApplicationSetting.create_from_defaults)
- end
+ let(:input) { '<b>ascii</b>' }
+ let(:context) { {} }
+ let(:html) { 'H<sub>2</sub>O' }
it "converts the input using Asciidoctor and default options" do
expected_asciidoc_opts = {
safe: :secure,
backend: :gitlab_html5,
- attributes: described_class::DEFAULT_ADOC_ATTRS
+ attributes: described_class::DEFAULT_ADOC_ATTRS,
+ extensions: be_a(Proc)
}
expect(Asciidoctor).to receive(:convert)
@@ -30,7 +33,8 @@ module Gitlab
expected_asciidoc_opts = {
safe: :secure,
backend: :gitlab_html5,
- attributes: described_class::DEFAULT_ADOC_ATTRS
+ attributes: described_class::DEFAULT_ADOC_ATTRS,
+ extensions: be_a(Proc)
}
expect(Asciidoctor).to receive(:convert)
@@ -105,6 +109,174 @@ module Gitlab
end
end
+ context 'with project' do
+ let(:context) do
+ {
+ commit: commit,
+ project: project,
+ ref: ref,
+ requested_path: requested_path
+ }
+ end
+ let(:commit) { project.commit(ref) }
+ let(:project) { create(:project, :repository) }
+ let(:ref) { 'asciidoc' }
+ let(:requested_path) { '/' }
+
+ context 'include directive' do
+ subject(:output) { render(input, context) }
+
+ let(:input) { "Include this:\n\ninclude::#{include_path}[]" }
+
+ before do
+ current_file = requested_path
+ current_file += 'README.adoc' if requested_path.end_with? '/'
+
+ create_file(current_file, "= AsciiDoc\n")
+ end
+
+ context 'with path to non-existing file' do
+ let(:include_path) { 'not-exists.adoc' }
+
+ it 'renders Unresolved directive placeholder' do
+ is_expected.to include("<strong>[ERROR: include::#{include_path}[] - unresolved directive]</strong>")
+ end
+ end
+
+ shared_examples :invalid_include do
+ let(:include_path) { 'dk.png' }
+
+ before do
+ allow(project.repository).to receive(:blob_at).and_return(blob)
+ end
+
+ it 'does not read the blob' do
+ expect(blob).not_to receive(:data)
+ end
+
+ it 'renders Unresolved directive placeholder' do
+ is_expected.to include("<strong>[ERROR: include::#{include_path}[] - unresolved directive]</strong>")
+ end
+ end
+
+ context 'with path to a binary file' do
+ let(:blob) { fake_blob(path: 'dk.png', binary: true) }
+ include_examples :invalid_include
+ end
+
+ context 'with path to file in external storage' do
+ let(:blob) { fake_blob(path: 'dk.png', lfs: true) }
+
+ before do
+ allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
+ project.update_attribute(:lfs_enabled, true)
+ end
+
+ include_examples :invalid_include
+ end
+
+ context 'with path to a textual file' do
+ let(:include_path) { 'sample.adoc' }
+
+ before do
+ create_file(file_path, "Content from #{include_path}")
+ end
+
+ shared_examples :valid_include do
+ [
+ ['/doc/sample.adoc', 'doc/sample.adoc', 'absolute path'],
+ ['sample.adoc', 'doc/api/sample.adoc', 'relative path'],
+ ['./sample.adoc', 'doc/api/sample.adoc', 'relative path with leading ./'],
+ ['../sample.adoc', 'doc/sample.adoc', 'relative path to a file up one directory'],
+ ['../../sample.adoc', 'sample.adoc', 'relative path for a file up multiple directories']
+ ].each do |include_path_, file_path_, desc|
+
+ context "the file is specified by #{desc}" do
+ let(:include_path) { include_path_ }
+ let(:file_path) { file_path_ }
+
+ it 'includes content of the file' do
+ is_expected.to include('<p>Include this:</p>')
+ is_expected.to include("<p>Content from #{include_path}</p>")
+ end
+ end
+ end
+ end
+
+ context 'when requested path is a file in the repo' do
+ let(:requested_path) { 'doc/api/README.adoc' }
+
+ include_examples :valid_include
+
+ context 'without a commit (only ref)' do
+ let(:commit) { nil }
+ include_examples :valid_include
+ end
+ end
+
+ context 'when requested path is a directory in the repo' do
+ let(:requested_path) { 'doc/api/' }
+
+ include_examples :valid_include
+
+ context 'without a commit (only ref)' do
+ let(:commit) { nil }
+ include_examples :valid_include
+ end
+ end
+ end
+
+ context 'recursive includes with relative paths' do
+ let(:input) do
+ <<~ADOC
+ Source: requested file
+
+ include::doc/README.adoc[]
+
+ include::license.adoc[]
+ ADOC
+ end
+
+ before do
+ create_file 'doc/README.adoc', <<~ADOC
+ Source: doc/README.adoc
+
+ include::../license.adoc[]
+
+ include::api/hello.adoc[]
+ ADOC
+ create_file 'license.adoc', <<~ADOC
+ Source: license.adoc
+ ADOC
+ create_file 'doc/api/hello.adoc', <<~ADOC
+ Source: doc/api/hello.adoc
+
+ include::./common.adoc[]
+ ADOC
+ create_file 'doc/api/common.adoc', <<~ADOC
+ Source: doc/api/common.adoc
+ ADOC
+ end
+
+ it 'includes content of the included files recursively' do
+ expect(output.gsub(/<[^>]+>/, '').gsub(/\n\s*/, "\n").strip).to eq <<~ADOC.strip
+ Source: requested file
+ Source: doc/README.adoc
+ Source: license.adoc
+ Source: doc/api/hello.adoc
+ Source: doc/api/common.adoc
+ Source: license.adoc
+ ADOC
+ end
+ end
+
+ def create_file(path, content)
+ project.repository.create_file(project.creator, path, content,
+ message: "Add #{path}", branch_name: 'asciidoc')
+ end
+ end
+ end
+
def render(*args)
described_class.render(*args)
end
diff --git a/spec/lib/gitlab/background_migration/delete_diff_files_spec.rb b/spec/lib/gitlab/background_migration/delete_diff_files_spec.rb
index 27281333348..0a5b99d27e7 100644
--- a/spec/lib/gitlab/background_migration/delete_diff_files_spec.rb
+++ b/spec/lib/gitlab/background_migration/delete_diff_files_spec.rb
@@ -3,6 +3,12 @@ require 'spec_helper'
# rubocop:disable RSpec/FactoriesInMigrationSpecs
describe Gitlab::BackgroundMigration::DeleteDiffFiles, :migration, :sidekiq, schema: 20180619121030 do
describe '#perform' do
+ before do
+ # This migration was created before we introduced ProjectCiCdSetting#default_git_depth
+ allow_any_instance_of(ProjectCiCdSetting).to receive(:default_git_depth=).and_return(0)
+ allow_any_instance_of(ProjectCiCdSetting).to receive(:default_git_depth).and_return(nil)
+ end
+
context 'when diff files can be deleted' do
let(:merge_request) { create(:merge_request, :merged) }
let!(:merge_request_diff) do
diff --git a/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb b/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb
index e7ff9169f1b..d3f7f1ded16 100644
--- a/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb
+++ b/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb
@@ -177,7 +177,7 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :m
end
before do
- allow_any_instance_of(described_class::MergeRequestDiff::ActiveRecord_Relation)
+ allow_any_instance_of(ActiveRecord::Relation)
.to receive(:update_all).and_raise(exception)
end
diff --git a/spec/lib/gitlab/background_migration/migrate_build_stage_spec.rb b/spec/lib/gitlab/background_migration/migrate_build_stage_spec.rb
index 7c7e58d6bb7..582396275ed 100644
--- a/spec/lib/gitlab/background_migration/migrate_build_stage_spec.rb
+++ b/spec/lib/gitlab/background_migration/migrate_build_stage_spec.rb
@@ -51,7 +51,7 @@ describe Gitlab::BackgroundMigration::MigrateBuildStage, :migration, schema: 201
statuses[:pending]]
end
- it 'recovers from unique constraint violation only twice' do
+ it 'recovers from unique constraint violation only twice', :quarantine do
allow(described_class::Migratable::Stage)
.to receive(:find_by).and_return(nil)
diff --git a/spec/lib/gitlab/background_migration/populate_external_pipeline_source_spec.rb b/spec/lib/gitlab/background_migration/populate_external_pipeline_source_spec.rb
index 3e009fed0f1..c6bc3db88a3 100644
--- a/spec/lib/gitlab/background_migration/populate_external_pipeline_source_spec.rb
+++ b/spec/lib/gitlab/background_migration/populate_external_pipeline_source_spec.rb
@@ -9,6 +9,9 @@ describe Gitlab::BackgroundMigration::PopulateExternalPipelineSource, :migration
before do
# This migration was created before we introduced metadata configs
stub_feature_flags(ci_build_metadata_config: false)
+ # This migration was created before we introduced ProjectCiCdSetting#default_git_depth
+ allow_any_instance_of(ProjectCiCdSetting).to receive(:default_git_depth).and_return(nil)
+ allow_any_instance_of(ProjectCiCdSetting).to receive(:default_git_depth=).and_return(0)
end
let!(:internal_pipeline) { create(:ci_pipeline, source: :web) }
diff --git a/spec/lib/gitlab/background_migration/reset_merge_status_spec.rb b/spec/lib/gitlab/background_migration/reset_merge_status_spec.rb
new file mode 100644
index 00000000000..740781f1aa5
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/reset_merge_status_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Gitlab::BackgroundMigration::ResetMergeStatus, :migration, schema: 20190528180441 do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:namespace) { namespaces.create(name: 'gitlab', path: 'gitlab-org') }
+ let(:project) { projects.create(namespace_id: namespace.id, name: 'foo') }
+ let(:merge_requests) { table(:merge_requests) }
+
+ def create_merge_request(id, extra_params = {})
+ params = {
+ id: id,
+ target_project_id: project.id,
+ target_branch: 'master',
+ source_project_id: project.id,
+ source_branch: 'mr name',
+ title: "mr name#{id}"
+ }.merge(extra_params)
+
+ merge_requests.create!(params)
+ end
+
+ it 'correctly updates opened mergeable MRs to unchecked' do
+ create_merge_request(1, state: 'opened', merge_status: 'can_be_merged')
+ create_merge_request(2, state: 'opened', merge_status: 'can_be_merged')
+ create_merge_request(3, state: 'opened', merge_status: 'can_be_merged')
+ create_merge_request(4, state: 'merged', merge_status: 'can_be_merged')
+ create_merge_request(5, state: 'opened', merge_status: 'cannot_be_merged')
+
+ subject.perform(1, 5)
+
+ expected_rows = [
+ { id: 1, state: 'opened', merge_status: 'unchecked' },
+ { id: 2, state: 'opened', merge_status: 'unchecked' },
+ { id: 3, state: 'opened', merge_status: 'unchecked' },
+ { id: 4, state: 'merged', merge_status: 'can_be_merged' },
+ { id: 5, state: 'opened', merge_status: 'cannot_be_merged' }
+ ]
+
+ rows = merge_requests.order(:id).map do |row|
+ row.attributes.slice('id', 'state', 'merge_status').symbolize_keys
+ end
+
+ expect(rows).to eq(expected_rows)
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/schedule_calculate_wiki_sizes_spec.rb b/spec/lib/gitlab/background_migration/schedule_calculate_wiki_sizes_spec.rb
new file mode 100644
index 00000000000..d494ce68c5b
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/schedule_calculate_wiki_sizes_spec.rb
@@ -0,0 +1,62 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20190527194900_schedule_calculate_wiki_sizes.rb')
+
+describe ScheduleCalculateWikiSizes, :migration, :sidekiq do
+ let(:migration_class) { Gitlab::BackgroundMigration::CalculateWikiSizes }
+ let(:migration_name) { migration_class.to_s.demodulize }
+
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:project_statistics) { table(:project_statistics) }
+
+ context 'when missing wiki sizes exist' do
+ before do
+ namespaces.create!(id: 1, name: 'wiki-migration', path: 'wiki-migration')
+ projects.create!(id: 1, name: 'wiki-project-1', path: 'wiki-project-1', namespace_id: 1)
+ projects.create!(id: 2, name: 'wiki-project-2', path: 'wiki-project-2', namespace_id: 1)
+ projects.create!(id: 3, name: 'wiki-project-3', path: 'wiki-project-3', namespace_id: 1)
+ project_statistics.create!(id: 1, project_id: 1, namespace_id: 1, wiki_size: 1000)
+ project_statistics.create!(id: 2, project_id: 2, namespace_id: 1, wiki_size: nil)
+ project_statistics.create!(id: 3, project_id: 3, namespace_id: 1, wiki_size: nil)
+ end
+
+ it 'schedules a background migration' do
+ Sidekiq::Testing.fake! do
+ Timecop.freeze do
+ migrate!
+
+ expect(migration_name).to be_scheduled_delayed_migration(5.minutes, 2, 3)
+ expect(BackgroundMigrationWorker.jobs.size).to eq 1
+ end
+ end
+ end
+
+ it 'calculates missing wiki sizes' do
+ expect(project_statistics.find_by(id: 2).wiki_size).to be_nil
+ expect(project_statistics.find_by(id: 3).wiki_size).to be_nil
+
+ migrate!
+
+ expect(project_statistics.find_by(id: 2).wiki_size).not_to be_nil
+ expect(project_statistics.find_by(id: 3).wiki_size).not_to be_nil
+ end
+ end
+
+ context 'when missing wiki sizes do not exist' do
+ before do
+ namespaces.create!(id: 1, name: 'wiki-migration', path: 'wiki-migration')
+ projects.create!(id: 1, name: 'wiki-project-1', path: 'wiki-project-1', namespace_id: 1)
+ project_statistics.create!(id: 1, project_id: 1, namespace_id: 1, wiki_size: 1000)
+ end
+
+ it 'does not schedule a background migration' do
+ Sidekiq::Testing.fake! do
+ Timecop.freeze do
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq 0
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/bitbucket_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importer_spec.rb
index e1a2bae5fe8..2e90f6c7f71 100644
--- a/spec/lib/gitlab/bitbucket_import/importer_spec.rb
+++ b/spec/lib/gitlab/bitbucket_import/importer_spec.rb
@@ -5,6 +5,7 @@ describe Gitlab::BitbucketImport::Importer do
before do
stub_omniauth_provider('bitbucket')
+ stub_feature_flags(stricter_mr_branch_name: false)
end
let(:statuses) do
@@ -222,6 +223,46 @@ describe Gitlab::BitbucketImport::Importer do
body: {}.to_json)
end
+ context 'creating labels on project' do
+ before do
+ allow(importer).to receive(:import_wiki)
+ end
+
+ it 'creates labels as expected' do
+ expect { importer.execute }.to change { Label.count }.from(0).to(Gitlab::BitbucketImport::Importer::LABELS.size)
+ end
+
+ it 'does not fail if label is already existing' do
+ label = Gitlab::BitbucketImport::Importer::LABELS.first
+ ::Labels::CreateService.new(label).execute(project: project)
+
+ expect { importer.execute }.not_to raise_error
+ end
+
+ it 'does not create new labels' do
+ Gitlab::BitbucketImport::Importer::LABELS.each do |label|
+ create(:label, project: project, title: label[:title])
+ end
+
+ expect { importer.execute }.not_to change { Label.count }
+ end
+
+ it 'does not update existing ones' do
+ label_title = Gitlab::BitbucketImport::Importer::LABELS.first[:title]
+ existing_label = create(:label, project: project, title: label_title)
+ # Reload label from database so we avoid timestamp comparison issues related to time precision when comparing
+ # attributes later.
+ existing_label.reload
+
+ Timecop.freeze(Time.now + 1.minute) do
+ importer.execute
+
+ label_after_import = project.labels.find(existing_label.id)
+ expect(label_after_import.attributes).to eq(existing_label.attributes)
+ end
+ end
+ end
+
it 'maps statuses to open or closed' do
allow(importer).to receive(:import_wiki)
diff --git a/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
index 1e90a2ef27f..cc09804fd53 100644
--- a/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
+++ b/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
@@ -105,6 +105,7 @@ describe Gitlab::BitbucketServerImport::Importer do
expect(merge_request.metrics.merged_by).to eq(project.owner)
expect(merge_request.metrics.merged_at).to eq(@merge_event.merge_timestamp)
expect(merge_request.merge_commit_sha).to eq('12345678')
+ expect(merge_request.state_id).to eq(3)
end
it 'imports comments' do
diff --git a/spec/lib/gitlab/checks/branch_check_spec.rb b/spec/lib/gitlab/checks/branch_check_spec.rb
index 8d5ab27a17c..71b64a3b9df 100644
--- a/spec/lib/gitlab/checks/branch_check_spec.rb
+++ b/spec/lib/gitlab/checks/branch_check_spec.rb
@@ -77,117 +77,85 @@ describe Gitlab::Checks::BranchCheck do
let(:oldrev) { '0000000000000000000000000000000000000000' }
let(:ref) { 'refs/heads/feature' }
- context 'protected branch creation feature is disabled' do
+ context 'user can push to branch' do
before do
- stub_feature_flags(protected_branch_creation: false)
+ allow(user_access)
+ .to receive(:can_push_to_branch?)
+ .with('feature')
+ .and_return(true)
end
- context 'user is not allowed to push to protected branch' do
- before do
- allow(user_access)
- .to receive(:can_push_to_branch?)
- .and_return(false)
- end
-
- it 'raises an error' do
- expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to push code to protected branches on this project.')
- end
+ it 'does not raise an error' do
+ expect { subject.validate! }.not_to raise_error
end
+ end
- context 'user is allowed to push to protected branch' do
- before do
- allow(user_access)
- .to receive(:can_push_to_branch?)
- .and_return(true)
- end
-
- it 'does not raise an error' do
- expect { subject.validate! }.not_to raise_error
- end
+ context 'user cannot push to branch' do
+ before do
+ allow(user_access)
+ .to receive(:can_push_to_branch?)
+ .with('feature')
+ .and_return(false)
end
- end
- context 'protected branch creation feature is enabled' do
- context 'user can push to branch' do
+ context 'user cannot merge to branch' do
before do
allow(user_access)
- .to receive(:can_push_to_branch?)
+ .to receive(:can_merge_to_branch?)
.with('feature')
- .and_return(true)
+ .and_return(false)
end
- it 'does not raise an error' do
- expect { subject.validate! }.not_to raise_error
+ it 'raises an error' do
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to create protected branches on this project.')
end
end
- context 'user cannot push to branch' do
+ context 'user can merge to branch' do
before do
allow(user_access)
- .to receive(:can_push_to_branch?)
+ .to receive(:can_merge_to_branch?)
.with('feature')
- .and_return(false)
+ .and_return(true)
+
+ allow(project.repository)
+ .to receive(:branch_names_contains_sha)
+ .with(newrev)
+ .and_return(['branch'])
end
- context 'user cannot merge to branch' do
+ context "newrev isn't in any protected branches" do
before do
- allow(user_access)
- .to receive(:can_merge_to_branch?)
- .with('feature')
+ allow(ProtectedBranch)
+ .to receive(:any_protected?)
+ .with(project, ['branch'])
.and_return(false)
end
it 'raises an error' do
- expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to create protected branches on this project.')
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You can only use an existing protected branch ref as the basis of a new protected branch.')
end
end
- context 'user can merge to branch' do
+ context 'newrev is included in a protected branch' do
before do
- allow(user_access)
- .to receive(:can_merge_to_branch?)
- .with('feature')
+ allow(ProtectedBranch)
+ .to receive(:any_protected?)
+ .with(project, ['branch'])
.and_return(true)
-
- allow(project.repository)
- .to receive(:branch_names_contains_sha)
- .with(newrev)
- .and_return(['branch'])
end
- context "newrev isn't in any protected branches" do
- before do
- allow(ProtectedBranch)
- .to receive(:any_protected?)
- .with(project, ['branch'])
- .and_return(false)
- end
+ context 'via web interface' do
+ let(:protocol) { 'web' }
- it 'raises an error' do
- expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You can only use an existing protected branch ref as the basis of a new protected branch.')
+ it 'allows branch creation' do
+ expect { subject.validate! }.not_to raise_error
end
end
- context 'newrev is included in a protected branch' do
- before do
- allow(ProtectedBranch)
- .to receive(:any_protected?)
- .with(project, ['branch'])
- .and_return(true)
- end
-
- context 'via web interface' do
- let(:protocol) { 'web' }
-
- it 'allows branch creation' do
- expect { subject.validate! }.not_to raise_error
- end
- end
-
- context 'via SSH' do
- it 'raises an error' do
- expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You can only create protected branches using the web interface and API.')
- end
+ context 'via SSH' do
+ it 'raises an error' do
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You can only create protected branches using the web interface and API.')
end
end
end
diff --git a/spec/lib/gitlab/checks/lfs_check_spec.rb b/spec/lib/gitlab/checks/lfs_check_spec.rb
index 35f8069c8a4..dad14e100a7 100644
--- a/spec/lib/gitlab/checks/lfs_check_spec.rb
+++ b/spec/lib/gitlab/checks/lfs_check_spec.rb
@@ -27,6 +27,18 @@ describe Gitlab::Checks::LfsCheck do
allow(project).to receive(:lfs_enabled?).and_return(true)
end
+ context 'with lfs_check feature disabled' do
+ before do
+ stub_feature_flags(lfs_check: false)
+ end
+
+ it 'skips integrity check' do
+ expect_any_instance_of(Gitlab::Git::LfsChanges).not_to receive(:new_pointers)
+
+ subject.validate!
+ end
+ end
+
context 'deletion' do
let(:changes) { { oldrev: oldrev, ref: ref } }
diff --git a/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb b/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
index 62dcd80fad7..5387863bd07 100644
--- a/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
+++ b/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
@@ -20,7 +20,7 @@ describe Gitlab::Ci::Build::Prerequisite::KubernetesNamespace do
let!(:deployment) { create(:deployment, deployable: build) }
context 'and a cluster to deploy to' do
- let(:cluster) { create(:cluster, projects: [build.project]) }
+ let(:cluster) { create(:cluster, :group) }
before do
allow(build.deployment).to receive(:cluster).and_return(cluster)
@@ -28,11 +28,23 @@ describe Gitlab::Ci::Build::Prerequisite::KubernetesNamespace do
it { is_expected.to be_truthy }
+ context 'and the cluster is not managed' do
+ let(:cluster) { create(:cluster, :not_managed, projects: [build.project]) }
+
+ it { is_expected.to be_falsey }
+ end
+
context 'and a namespace is already created for this project' do
let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, cluster: cluster, project: build.project) }
it { is_expected.to be_falsey }
end
+
+ context 'and cluster is project type' do
+ let(:cluster) { create(:cluster, :project) }
+
+ it { is_expected.to be_falsey }
+ end
end
context 'and no cluster to deploy to' do
@@ -52,7 +64,7 @@ describe Gitlab::Ci::Build::Prerequisite::KubernetesNamespace do
subject { described_class.new(build).complete! }
context 'completion is required' do
- let(:cluster) { create(:cluster, projects: [build.project]) }
+ let(:cluster) { create(:cluster, :group) }
before do
allow(build.deployment).to receive(:cluster).and_return(cluster)
diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb
index 0560eb42e4d..e0552ae8c57 100644
--- a/spec/lib/gitlab/ci/config/entry/job_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb
@@ -94,7 +94,7 @@ describe Gitlab::Ci::Config::Entry::Job do
it 'returns error about wrong value type' do
expect(entry).not_to be_valid
- expect(entry.errors).to include "job extends should be a string"
+ expect(entry.errors).to include "job extends should be an array of strings or a string"
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/service_spec.rb b/spec/lib/gitlab/ci/config/entry/service_spec.rb
index d5bd139b5f1..d31866a1987 100644
--- a/spec/lib/gitlab/ci/config/entry/service_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/service_spec.rb
@@ -112,6 +112,16 @@ describe Gitlab::Ci::Config::Entry::Service do
it 'is valid' do
expect(entry).to be_valid
end
+
+ context 'when unknown port keys detected' do
+ let(:ports) { [{ number: 80, invalid_key: 'foo' }] }
+
+ it 'is not valid' do
+ expect(entry).not_to be_valid
+ expect(entry.errors.first)
+ .to match /port config contains unknown keys: invalid_key/
+ end
+ end
end
describe '#ports' do
diff --git a/spec/lib/gitlab/ci/config/extendable/entry_spec.rb b/spec/lib/gitlab/ci/config/extendable/entry_spec.rb
index 0a148375d11..d63612053b6 100644
--- a/spec/lib/gitlab/ci/config/extendable/entry_spec.rb
+++ b/spec/lib/gitlab/ci/config/extendable/entry_spec.rb
@@ -44,12 +44,12 @@ describe Gitlab::Ci::Config::Extendable::Entry do
end
end
- describe '#extends_key' do
+ describe '#extends_keys' do
context 'when entry is extensible' do
it 'returns symbolized extends key value' do
entry = described_class.new(:test, test: { extends: 'something' })
- expect(entry.extends_key).to eq :something
+ expect(entry.extends_keys).to eq [:something]
end
end
@@ -57,7 +57,7 @@ describe Gitlab::Ci::Config::Extendable::Entry do
it 'returns nil' do
entry = described_class.new(:test, test: 'something')
- expect(entry.extends_key).to be_nil
+ expect(entry.extends_keys).to be_nil
end
end
end
@@ -76,7 +76,7 @@ describe Gitlab::Ci::Config::Extendable::Entry do
end
end
- describe '#base_hash!' do
+ describe '#base_hashes!' do
subject { described_class.new(:test, hash) }
context 'when base hash is not extensible' do
@@ -87,8 +87,8 @@ describe Gitlab::Ci::Config::Extendable::Entry do
}
end
- it 'returns unchanged base hash' do
- expect(subject.base_hash!).to eq(script: 'rspec')
+ it 'returns unchanged base hashes' do
+ expect(subject.base_hashes!).to eq([{ script: 'rspec' }])
end
end
@@ -101,12 +101,12 @@ describe Gitlab::Ci::Config::Extendable::Entry do
}
end
- it 'extends the base hash first' do
- expect(subject.base_hash!).to eq(extends: 'first', script: 'rspec')
+ it 'extends the base hashes first' do
+ expect(subject.base_hashes!).to eq([{ extends: 'first', script: 'rspec' }])
end
it 'mutates original context' do
- subject.base_hash!
+ subject.base_hashes!
expect(hash.fetch(:second)).to eq(extends: 'first', script: 'rspec')
end
@@ -171,6 +171,34 @@ describe Gitlab::Ci::Config::Extendable::Entry do
end
end
+ context 'when extending multiple hashes correctly' do
+ let(:hash) do
+ {
+ first: { script: 'my value', image: 'ubuntu' },
+ second: { image: 'alpine' },
+ test: { extends: %w(first second) }
+ }
+ end
+
+ let(:result) do
+ {
+ first: { script: 'my value', image: 'ubuntu' },
+ second: { image: 'alpine' },
+ test: { extends: %w(first second), script: 'my value', image: 'alpine' }
+ }
+ end
+
+ it 'returns extended part of the hash' do
+ expect(subject.extend!).to eq result[:test]
+ end
+
+ it 'mutates original context' do
+ subject.extend!
+
+ expect(hash).to eq result
+ end
+ end
+
context 'when hash is not extensible' do
let(:hash) do
{
diff --git a/spec/lib/gitlab/ci/config/external/file/remote_spec.rb b/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
index d8a61618e77..46d68097fff 100644
--- a/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe Gitlab::Ci::Config::External::File::Remote do
+ include StubRequests
+
let(:context) { described_class::Context.new(nil, '12345', nil, Set.new) }
let(:params) { { remote: location } }
let(:remote_file) { described_class.new(params, context) }
@@ -46,7 +48,7 @@ describe Gitlab::Ci::Config::External::File::Remote do
describe "#valid?" do
context 'when is a valid remote url' do
before do
- WebMock.stub_request(:get, location).to_return(body: remote_file_content)
+ stub_full_request(location).to_return(body: remote_file_content)
end
it 'returns true' do
@@ -92,7 +94,7 @@ describe Gitlab::Ci::Config::External::File::Remote do
describe "#content" do
context 'with a valid remote file' do
before do
- WebMock.stub_request(:get, location).to_return(body: remote_file_content)
+ stub_full_request(location).to_return(body: remote_file_content)
end
it 'returns the content of the file' do
@@ -114,7 +116,7 @@ describe Gitlab::Ci::Config::External::File::Remote do
let(:location) { 'https://asdasdasdaj48ggerexample.com' }
before do
- WebMock.stub_request(:get, location).to_raise(SocketError.new('Some HTTP error'))
+ stub_full_request(location).to_raise(SocketError.new('Some HTTP error'))
end
it 'is nil' do
@@ -144,7 +146,7 @@ describe Gitlab::Ci::Config::External::File::Remote do
context 'when timeout error has been raised' do
before do
- WebMock.stub_request(:get, location).to_timeout
+ stub_full_request(location).to_timeout
end
it 'returns error message about a timeout' do
@@ -154,7 +156,7 @@ describe Gitlab::Ci::Config::External::File::Remote do
context 'when HTTP error has been raised' do
before do
- WebMock.stub_request(:get, location).to_raise(Gitlab::HTTP::Error)
+ stub_full_request(location).to_raise(Gitlab::HTTP::Error)
end
it 'returns error message about a HTTP error' do
@@ -164,7 +166,7 @@ describe Gitlab::Ci::Config::External::File::Remote do
context 'when response has 404 status' do
before do
- WebMock.stub_request(:get, location).to_return(body: remote_file_content, status: 404)
+ stub_full_request(location).to_return(body: remote_file_content, status: 404)
end
it 'returns error message about a timeout' do
diff --git a/spec/lib/gitlab/ci/config/external/mapper_spec.rb b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
index 136974569de..e068b786b02 100644
--- a/spec/lib/gitlab/ci/config/external/mapper_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe Gitlab::Ci::Config::External::Mapper do
+ include StubRequests
+
set(:project) { create(:project, :repository) }
set(:user) { create(:user) }
@@ -18,7 +20,7 @@ describe Gitlab::Ci::Config::External::Mapper do
end
before do
- WebMock.stub_request(:get, remote_url).to_return(body: file_content)
+ stub_full_request(remote_url).to_return(body: file_content)
end
describe '#process' do
diff --git a/spec/lib/gitlab/ci/config/external/processor_spec.rb b/spec/lib/gitlab/ci/config/external/processor_spec.rb
index 0f58a4f1d44..856187371e1 100644
--- a/spec/lib/gitlab/ci/config/external/processor_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/processor_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe Gitlab::Ci::Config::External::Processor do
+ include StubRequests
+
set(:project) { create(:project, :repository) }
set(:another_project) { create(:project, :repository) }
set(:user) { create(:user) }
@@ -42,7 +44,7 @@ describe Gitlab::Ci::Config::External::Processor do
let(:values) { { include: remote_file, image: 'ruby:2.2' } }
before do
- WebMock.stub_request(:get, remote_file).to_raise(SocketError.new('Some HTTP error'))
+ stub_full_request(remote_file).and_raise(SocketError.new('Some HTTP error'))
end
it 'raises an error' do
@@ -75,7 +77,7 @@ describe Gitlab::Ci::Config::External::Processor do
end
before do
- WebMock.stub_request(:get, remote_file).to_return(body: external_file_content)
+ stub_full_request(remote_file).to_return(body: external_file_content)
end
it 'appends the file to the values' do
@@ -145,7 +147,7 @@ describe Gitlab::Ci::Config::External::Processor do
allow_any_instance_of(Gitlab::Ci::Config::External::File::Local)
.to receive(:fetch_local_content).and_return(local_file_content)
- WebMock.stub_request(:get, remote_file).to_return(body: remote_file_content)
+ stub_full_request(remote_file).to_return(body: remote_file_content)
end
it 'appends the files to the values' do
@@ -191,7 +193,8 @@ describe Gitlab::Ci::Config::External::Processor do
end
it 'takes precedence' do
- WebMock.stub_request(:get, remote_file).to_return(body: remote_file_content)
+ stub_full_request(remote_file).to_return(body: remote_file_content)
+
expect(processor.perform[:image]).to eq('ruby:2.2')
end
end
@@ -231,7 +234,8 @@ describe Gitlab::Ci::Config::External::Processor do
HEREDOC
end
- WebMock.stub_request(:get, 'http://my.domain.com/config.yml').to_return(body: 'remote_build: { script: echo Hello World }')
+ stub_full_request('http://my.domain.com/config.yml')
+ .to_return(body: 'remote_build: { script: echo Hello World }')
end
context 'when project is public' do
@@ -273,8 +277,10 @@ describe Gitlab::Ci::Config::External::Processor do
context 'when config includes an external configuration file via SSL web request' do
before do
- stub_request(:get, 'https://sha256.badssl.com/fake.yml').to_return(body: 'image: ruby:2.6', status: 200)
- stub_request(:get, 'https://self-signed.badssl.com/fake.yml')
+ stub_full_request('https://sha256.badssl.com/fake.yml', ip_address: '8.8.8.8')
+ .to_return(body: 'image: ruby:2.6', status: 200)
+
+ stub_full_request('https://self-signed.badssl.com/fake.yml', ip_address: '8.8.8.9')
.to_raise(OpenSSL::SSL::SSLError.new('SSL_connect returned=1 errno=0 state=error: certificate verify failed (self signed certificate)'))
end
diff --git a/spec/lib/gitlab/ci/config_spec.rb b/spec/lib/gitlab/ci/config_spec.rb
index fd2a29e4ddb..7f336ee853e 100644
--- a/spec/lib/gitlab/ci/config_spec.rb
+++ b/spec/lib/gitlab/ci/config_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe Gitlab::Ci::Config do
+ include StubRequests
+
set(:user) { create(:user) }
let(:config) do
@@ -190,7 +192,6 @@ describe Gitlab::Ci::Config do
let(:remote_file_content) do
<<~HEREDOC
variables:
- AUTO_DEVOPS_DOMAIN: domain.example.com
POSTGRES_USER: user
POSTGRES_PASSWORD: testing-password
POSTGRES_ENABLED: "true"
@@ -217,8 +218,7 @@ describe Gitlab::Ci::Config do
end
before do
- WebMock.stub_request(:get, remote_location)
- .to_return(body: remote_file_content)
+ stub_full_request(remote_location).to_return(body: remote_file_content)
allow(project.repository)
.to receive(:blob_data_at).and_return(local_file_content)
@@ -232,7 +232,6 @@ describe Gitlab::Ci::Config do
"bundle install --jobs $(nproc) \"${FLAGS[@]}\""
]
variables = {
- AUTO_DEVOPS_DOMAIN: "domain.example.com",
POSTGRES_USER: "user",
POSTGRES_PASSWORD: "testing-password",
POSTGRES_ENABLED: "true",
diff --git a/spec/lib/gitlab/ci/cron_parser_spec.rb b/spec/lib/gitlab/ci/cron_parser_spec.rb
index 2a3f7807fdb..491e3fba9d9 100644
--- a/spec/lib/gitlab/ci/cron_parser_spec.rb
+++ b/spec/lib/gitlab/ci/cron_parser_spec.rb
@@ -174,6 +174,13 @@ describe Gitlab::Ci::CronParser do
it { expect(subject).to be_nil }
end
+
+ context 'when cron is scheduled to a non existent day' do
+ let(:cron) { '0 12 31 2 *' }
+ let(:cron_timezone) { 'UTC' }
+
+ it { expect(subject).to be_nil }
+ end
end
describe '#cron_valid?' do
diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexeme/and_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexeme/and_spec.rb
new file mode 100644
index 00000000000..006ce4d8078
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/expression/lexeme/and_spec.rb
@@ -0,0 +1,77 @@
+require 'fast_spec_helper'
+require 'rspec-parameterized'
+
+describe Gitlab::Ci::Pipeline::Expression::Lexeme::And do
+ let(:left) { double('left', evaluate: nil) }
+ let(:right) { double('right', evaluate: nil) }
+
+ describe '.build' do
+ it 'creates a new instance of the token' do
+ expect(described_class.build('&&', left, right)).to be_a(described_class)
+ end
+
+ context 'with non-evaluable operands' do
+ let(:left) { double('left') }
+ let(:right) { double('right') }
+
+ it 'raises an operator error' do
+ expect { described_class.build('&&', left, right) }.to raise_error Gitlab::Ci::Pipeline::Expression::Lexeme::Operator::OperatorError
+ end
+ end
+ end
+
+ describe '.type' do
+ it 'is an operator' do
+ expect(described_class.type).to eq :operator
+ end
+ end
+
+ describe '.precedence' do
+ it 'has a precedence' do
+ expect(described_class.precedence).to be_an Integer
+ end
+ end
+
+ describe '#evaluate' do
+ let(:operator) { described_class.new(left, right) }
+
+ subject { operator.evaluate }
+
+ before do
+ allow(left).to receive(:evaluate).and_return(left_value)
+ allow(right).to receive(:evaluate).and_return(right_value)
+ end
+
+ context 'when left and right are truthy' do
+ where(:left_value, :right_value) do
+ [true, 1, 'a'].permutation(2).to_a
+ end
+
+ with_them do
+ it { is_expected.to be_truthy }
+ it { is_expected.to eq(right_value) }
+ end
+ end
+
+ context 'when left or right is falsey' do
+ where(:left_value, :right_value) do
+ [true, false, nil].permutation(2).to_a
+ end
+
+ with_them do
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ context 'when left and right are falsey' do
+ where(:left_value, :right_value) do
+ [false, nil].permutation(2).to_a
+ end
+
+ with_them do
+ it { is_expected.to be_falsey }
+ it { is_expected.to eq(left_value) }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexeme/equals_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexeme/equals_spec.rb
index 019a2ed184d..fcbd2863289 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/lexeme/equals_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/lexeme/equals_spec.rb
@@ -5,9 +5,21 @@ describe Gitlab::Ci::Pipeline::Expression::Lexeme::Equals do
let(:right) { double('right') }
describe '.build' do
- it 'creates a new instance of the token' do
- expect(described_class.build('==', left, right))
- .to be_a(described_class)
+ context 'with non-evaluable operands' do
+ it 'creates a new instance of the token' do
+ expect { described_class.build('==', left, right) }
+ .to raise_error Gitlab::Ci::Pipeline::Expression::Lexeme::Operator::OperatorError
+ end
+ end
+
+ context 'with evaluable operands' do
+ it 'creates a new instance of the token' do
+ allow(left).to receive(:evaluate).and_return('my-string')
+ allow(right).to receive(:evaluate).and_return('my-string')
+
+ expect(described_class.build('==', left, right))
+ .to be_a(described_class)
+ end
end
end
@@ -17,23 +29,40 @@ describe Gitlab::Ci::Pipeline::Expression::Lexeme::Equals do
end
end
+ describe '.precedence' do
+ it 'has a precedence' do
+ expect(described_class.precedence).to be_an Integer
+ end
+ end
+
describe '#evaluate' do
- it 'returns false when left and right are not equal' do
- allow(left).to receive(:evaluate).and_return(1)
- allow(right).to receive(:evaluate).and_return(2)
+ let(:operator) { described_class.new(left, right) }
- operator = described_class.new(left, right)
+ subject { operator.evaluate }
- expect(operator.evaluate(VARIABLE: 3)).to eq false
+ before do
+ allow(left).to receive(:evaluate).and_return(left_value)
+ allow(right).to receive(:evaluate).and_return(right_value)
end
- it 'returns true when left and right are equal' do
- allow(left).to receive(:evaluate).and_return(1)
- allow(right).to receive(:evaluate).and_return(1)
+ context 'when left and right are equal' do
+ where(:left_value, :right_value) do
+ [%w(string string)]
+ end
+
+ with_them do
+ it { is_expected.to eq(true) }
+ end
+ end
- operator = described_class.new(left, right)
+ context 'when left and right are not equal' do
+ where(:left_value, :right_value) do
+ ['one string', 'two string'].permutation(2).to_a
+ end
- expect(operator.evaluate(VARIABLE: 3)).to eq true
+ with_them do
+ it { is_expected.to eq(false) }
+ end
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexeme/matches_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexeme/matches_spec.rb
index 49e5af52f4d..97da66d2bcc 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/lexeme/matches_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/lexeme/matches_spec.rb
@@ -6,9 +6,21 @@ describe Gitlab::Ci::Pipeline::Expression::Lexeme::Matches do
let(:right) { double('right') }
describe '.build' do
- it 'creates a new instance of the token' do
- expect(described_class.build('=~', left, right))
- .to be_a(described_class)
+ context 'with non-evaluable operands' do
+ it 'creates a new instance of the token' do
+ expect { described_class.build('=~', left, right) }
+ .to raise_error Gitlab::Ci::Pipeline::Expression::Lexeme::Operator::OperatorError
+ end
+ end
+
+ context 'with evaluable operands' do
+ it 'creates a new instance of the token' do
+ allow(left).to receive(:evaluate).and_return('my-string')
+ allow(right).to receive(:evaluate).and_return('/my-string/')
+
+ expect(described_class.build('=~', left, right))
+ .to be_a(described_class)
+ end
end
end
@@ -18,63 +30,93 @@ describe Gitlab::Ci::Pipeline::Expression::Lexeme::Matches do
end
end
+ describe '.precedence' do
+ it 'has a precedence' do
+ expect(described_class.precedence).to be_an Integer
+ end
+ end
+
describe '#evaluate' do
- it 'returns false when left and right do not match' do
- allow(left).to receive(:evaluate).and_return('my-string')
- allow(right).to receive(:evaluate)
- .and_return(Gitlab::UntrustedRegexp.new('something'))
+ let(:operator) { described_class.new(left, right) }
- operator = described_class.new(left, right)
+ subject { operator.evaluate }
- expect(operator.evaluate).to eq false
+ before do
+ allow(left).to receive(:evaluate).and_return(left_value)
+ allow(right).to receive(:evaluate).and_return(right_value)
end
- it 'returns true when left and right match' do
- allow(left).to receive(:evaluate).and_return('my-awesome-string')
- allow(right).to receive(:evaluate)
- .and_return(Gitlab::UntrustedRegexp.new('awesome.string$'))
+ context 'when left and right do not match' do
+ let(:left_value) { 'my-string' }
+ let(:right_value) { Gitlab::UntrustedRegexp.new('something') }
- operator = described_class.new(left, right)
-
- expect(operator.evaluate).to eq true
+ it { is_expected.to eq(nil) }
end
- it 'supports matching against a nil value' do
- allow(left).to receive(:evaluate).and_return(nil)
- allow(right).to receive(:evaluate)
- .and_return(Gitlab::UntrustedRegexp.new('pattern'))
+ context 'when left and right match' do
+ let(:left_value) { 'my-awesome-string' }
+ let(:right_value) { Gitlab::UntrustedRegexp.new('awesome.string$') }
+
+ it { is_expected.to eq(3) }
+ end
- operator = described_class.new(left, right)
+ context 'when left is nil' do
+ let(:left_value) { nil }
+ let(:right_value) { Gitlab::UntrustedRegexp.new('pattern') }
- expect(operator.evaluate).to eq false
+ it { is_expected.to eq(nil) }
end
- it 'supports multiline strings' do
- allow(left).to receive(:evaluate).and_return <<~TEXT
- My awesome contents
+ context 'when left is a multiline string and matches right' do
+ let(:left_value) do
+ <<~TEXT
+ My awesome contents
+
+ My-text-string!
+ TEXT
+ end
+
+ let(:right_value) { Gitlab::UntrustedRegexp.new('text-string') }
+
+ it { is_expected.to eq(24) }
+ end
- My-text-string!
- TEXT
+ context 'when left is a multiline string and does not match right' do
+ let(:left_value) do
+ <<~TEXT
+ My awesome contents
- allow(right).to receive(:evaluate)
- .and_return(Gitlab::UntrustedRegexp.new('text-string'))
+ My-terrible-string!
+ TEXT
+ end
- operator = described_class.new(left, right)
+ let(:right_value) { Gitlab::UntrustedRegexp.new('text-string') }
- expect(operator.evaluate).to eq true
+ it { is_expected.to eq(nil) }
end
- it 'supports regexp flags' do
- allow(left).to receive(:evaluate).and_return <<~TEXT
- My AWESOME content
- TEXT
+ context 'when a matching pattern uses regex flags' do
+ let(:left_value) do
+ <<~TEXT
+ My AWESOME content
+ TEXT
+ end
+
+ let(:right_value) { Gitlab::UntrustedRegexp.new('(?i)awesome') }
+
+ it { is_expected.to eq(3) }
+ end
- allow(right).to receive(:evaluate)
- .and_return(Gitlab::UntrustedRegexp.new('(?i)awesome'))
+ context 'when a non-matching pattern uses regex flags' do
+ let(:left_value) do
+ <<~TEXT
+ My AWESOME content
+ TEXT
+ end
- operator = described_class.new(left, right)
+ let(:right_value) { Gitlab::UntrustedRegexp.new('(?i)terrible') }
- expect(operator.evaluate).to eq true
+ it { is_expected.to eq(nil) }
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexeme/not_equals_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexeme/not_equals_spec.rb
new file mode 100644
index 00000000000..38d30c9035a
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/expression/lexeme/not_equals_spec.rb
@@ -0,0 +1,73 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Pipeline::Expression::Lexeme::NotEquals do
+ let(:left) { double('left') }
+ let(:right) { double('right') }
+
+ describe '.build' do
+ context 'with non-evaluable operands' do
+ it 'creates a new instance of the token' do
+ expect { described_class.build('!=', left, right) }
+ .to raise_error Gitlab::Ci::Pipeline::Expression::Lexeme::Operator::OperatorError
+ end
+ end
+
+ context 'with evaluable operands' do
+ it 'creates a new instance of the token' do
+ allow(left).to receive(:evaluate).and_return('my-string')
+ allow(right).to receive(:evaluate).and_return('my-string')
+
+ expect(described_class.build('!=', left, right))
+ .to be_a(described_class)
+ end
+ end
+ end
+
+ describe '.type' do
+ it 'is an operator' do
+ expect(described_class.type).to eq :operator
+ end
+ end
+
+ describe '.precedence' do
+ it 'has a precedence' do
+ expect(described_class.precedence).to be_an Integer
+ end
+ end
+
+ describe '#evaluate' do
+ let(:operator) { described_class.new(left, right) }
+
+ subject { operator.evaluate }
+
+ before do
+ allow(left).to receive(:evaluate).and_return(left_value)
+ allow(right).to receive(:evaluate).and_return(right_value)
+ end
+
+ context 'when left and right are equal' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:left_value, :right_value) do
+ 'string' | 'string'
+ 1 | 1
+ '' | ''
+ nil | nil
+ end
+
+ with_them do
+ it { is_expected.to eq(false) }
+ end
+ end
+
+ context 'when left and right are not equal' do
+ where(:left_value, :right_value) do
+ ['one string', 'two string', 1, 2, '', nil, false, true].permutation(2).to_a
+ end
+
+ with_them do
+ it { is_expected.to eq(true) }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexeme/not_matches_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexeme/not_matches_spec.rb
new file mode 100644
index 00000000000..99110ff8d88
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/expression/lexeme/not_matches_spec.rb
@@ -0,0 +1,122 @@
+require 'fast_spec_helper'
+require_dependency 're2'
+
+describe Gitlab::Ci::Pipeline::Expression::Lexeme::NotMatches do
+ let(:left) { double('left') }
+ let(:right) { double('right') }
+
+ describe '.build' do
+ context 'with non-evaluable operands' do
+ it 'creates a new instance of the token' do
+ expect { described_class.build('!~', left, right) }
+ .to raise_error Gitlab::Ci::Pipeline::Expression::Lexeme::Operator::OperatorError
+ end
+ end
+
+ context 'with evaluable operands' do
+ it 'creates a new instance of the token' do
+ allow(left).to receive(:evaluate).and_return('my-string')
+ allow(right).to receive(:evaluate).and_return('my-string')
+
+ expect(described_class.build('!~', left, right))
+ .to be_a(described_class)
+ end
+ end
+ end
+
+ describe '.type' do
+ it 'is an operator' do
+ expect(described_class.type).to eq :operator
+ end
+ end
+
+ describe '.precedence' do
+ it 'has a precedence' do
+ expect(described_class.precedence).to be_an Integer
+ end
+ end
+
+ describe '#evaluate' do
+ let(:operator) { described_class.new(left, right) }
+
+ subject { operator.evaluate }
+
+ before do
+ allow(left).to receive(:evaluate).and_return(left_value)
+ allow(right).to receive(:evaluate).and_return(right_value)
+ end
+
+ context 'when left and right do not match' do
+ let(:left_value) { 'my-string' }
+ let(:right_value) { Gitlab::UntrustedRegexp.new('something') }
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when left and right match' do
+ let(:left_value) { 'my-awesome-string' }
+ let(:right_value) { Gitlab::UntrustedRegexp.new('awesome.string$') }
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when left is nil' do
+ let(:left_value) { nil }
+ let(:right_value) { Gitlab::UntrustedRegexp.new('pattern') }
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when left is a multiline string and matches right' do
+ let(:left_value) do
+ <<~TEXT
+ My awesome contents
+
+ My-text-string!
+ TEXT
+ end
+
+ let(:right_value) { Gitlab::UntrustedRegexp.new('text-string') }
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when left is a multiline string and does not match right' do
+ let(:left_value) do
+ <<~TEXT
+ My awesome contents
+
+ My-terrible-string!
+ TEXT
+ end
+
+ let(:right_value) { Gitlab::UntrustedRegexp.new('text-string') }
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when a matching pattern uses regex flags' do
+ let(:left_value) do
+ <<~TEXT
+ My AWESOME content
+ TEXT
+ end
+
+ let(:right_value) { Gitlab::UntrustedRegexp.new('(?i)awesome') }
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when a non-matching pattern uses regex flags' do
+ let(:left_value) do
+ <<~TEXT
+ My AWESOME content
+ TEXT
+ end
+
+ let(:right_value) { Gitlab::UntrustedRegexp.new('(?i)terrible') }
+
+ it { is_expected.to eq(true) }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexeme/or_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexeme/or_spec.rb
new file mode 100644
index 00000000000..d542eebc613
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/expression/lexeme/or_spec.rb
@@ -0,0 +1,77 @@
+require 'fast_spec_helper'
+require 'rspec-parameterized'
+
+describe Gitlab::Ci::Pipeline::Expression::Lexeme::Or do
+ let(:left) { double('left', evaluate: nil) }
+ let(:right) { double('right', evaluate: nil) }
+
+ describe '.build' do
+ it 'creates a new instance of the token' do
+ expect(described_class.build('||', left, right)).to be_a(described_class)
+ end
+
+ context 'with non-evaluable operands' do
+ let(:left) { double('left') }
+ let(:right) { double('right') }
+
+ it 'raises an operator error' do
+ expect { described_class.build('||', left, right) }.to raise_error Gitlab::Ci::Pipeline::Expression::Lexeme::Operator::OperatorError
+ end
+ end
+ end
+
+ describe '.type' do
+ it 'is an operator' do
+ expect(described_class.type).to eq :operator
+ end
+ end
+
+ describe '.precedence' do
+ it 'has a precedence' do
+ expect(described_class.precedence).to be_an Integer
+ end
+ end
+
+ describe '#evaluate' do
+ let(:operator) { described_class.new(left, right) }
+
+ subject { operator.evaluate }
+
+ before do
+ allow(left).to receive(:evaluate).and_return(left_value)
+ allow(right).to receive(:evaluate).and_return(right_value)
+ end
+
+ context 'when left and right are truthy' do
+ where(:left_value, :right_value) do
+ [true, 1, 'a'].permutation(2).to_a
+ end
+
+ with_them do
+ it { is_expected.to be_truthy }
+ it { is_expected.to eq(left_value) }
+ end
+ end
+
+ context 'when left or right is truthy' do
+ where(:left_value, :right_value) do
+ [true, false, 'a'].permutation(2).to_a
+ end
+
+ with_them do
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ context 'when left and right are falsey' do
+ where(:left_value, :right_value) do
+ [false, nil].permutation(2).to_a
+ end
+
+ with_them do
+ it { is_expected.to be_falsey }
+ it { is_expected.to eq(right_value) }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexeme/pattern_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexeme/pattern_spec.rb
index cff7f57ceff..30ea3f3e28e 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/lexeme/pattern_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/lexeme/pattern_spec.rb
@@ -1,4 +1,4 @@
-require 'fast_spec_helper'
+require 'spec_helper'
describe Gitlab::Ci::Pipeline::Expression::Lexeme::Pattern do
describe '.build' do
@@ -30,16 +30,6 @@ describe Gitlab::Ci::Pipeline::Expression::Lexeme::Pattern do
.to eq Gitlab::UntrustedRegexp.new('pattern')
end
- it 'is a greedy scanner for regexp boundaries' do
- scanner = StringScanner.new('/some .* / pattern/')
-
- token = described_class.scan(scanner)
-
- expect(token).not_to be_nil
- expect(token.build.evaluate)
- .to eq Gitlab::UntrustedRegexp.new('some .* / pattern')
- end
-
it 'does not allow to use an empty pattern' do
scanner = StringScanner.new(%(//))
@@ -68,12 +58,90 @@ describe Gitlab::Ci::Pipeline::Expression::Lexeme::Pattern do
.to eq Gitlab::UntrustedRegexp.new('(?im)pattern')
end
- it 'does not support arbitrary flags' do
+ it 'ignores unsupported flags' do
scanner = StringScanner.new('/pattern/x')
token = described_class.scan(scanner)
- expect(token).to be_nil
+ expect(token).not_to be_nil
+ expect(token.build.evaluate)
+ .to eq Gitlab::UntrustedRegexp.new('pattern')
+ end
+
+ it 'is a eager scanner for regexp boundaries' do
+ scanner = StringScanner.new('/some .* / pattern/')
+
+ token = described_class.scan(scanner)
+
+ expect(token).not_to be_nil
+ expect(token.build.evaluate)
+ .to eq Gitlab::UntrustedRegexp.new('some .* ')
+ end
+
+ it 'does not match on escaped regexp boundaries' do
+ scanner = StringScanner.new('/some .* \/ pattern/')
+
+ token = described_class.scan(scanner)
+
+ expect(token).not_to be_nil
+ expect(token.build.evaluate)
+ .to eq Gitlab::UntrustedRegexp.new('some .* / pattern')
+ end
+
+ it 'recognizes \ as an escape character for /' do
+ scanner = StringScanner.new('/some numeric \/$ pattern/')
+
+ token = described_class.scan(scanner)
+
+ expect(token).not_to be_nil
+ expect(token.build.evaluate)
+ .to eq Gitlab::UntrustedRegexp.new('some numeric /$ pattern')
+ end
+
+ it 'does not recognize \ as an escape character for $' do
+ scanner = StringScanner.new('/some numeric \$ pattern/')
+
+ token = described_class.scan(scanner)
+
+ expect(token).not_to be_nil
+ expect(token.build.evaluate)
+ .to eq Gitlab::UntrustedRegexp.new('some numeric \$ pattern')
+ end
+
+ context 'with the ci_variables_complex_expressions feature flag disabled' do
+ before do
+ stub_feature_flags(ci_variables_complex_expressions: false)
+ end
+
+ it 'is a greedy scanner for regexp boundaries' do
+ scanner = StringScanner.new('/some .* / pattern/')
+
+ token = described_class.scan(scanner)
+
+ expect(token).not_to be_nil
+ expect(token.build.evaluate)
+ .to eq Gitlab::UntrustedRegexp.new('some .* / pattern')
+ end
+
+ it 'does not recognize the \ escape character for /' do
+ scanner = StringScanner.new('/some .* \/ pattern/')
+
+ token = described_class.scan(scanner)
+
+ expect(token).not_to be_nil
+ expect(token.build.evaluate)
+ .to eq Gitlab::UntrustedRegexp.new('some .* \/ pattern')
+ end
+
+ it 'does not recognize the \ escape character for $' do
+ scanner = StringScanner.new('/some numeric \$ pattern/')
+
+ token = described_class.scan(scanner)
+
+ expect(token).not_to be_nil
+ expect(token.build.evaluate)
+ .to eq Gitlab::UntrustedRegexp.new('some numeric \$ pattern')
+ end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexer_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexer_spec.rb
index 3f11b3f7673..d8db9c262a1 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/lexer_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/lexer_spec.rb
@@ -58,6 +58,56 @@ describe Gitlab::Ci::Pipeline::Expression::Lexer do
expect { lexer.tokens }
.to raise_error described_class::SyntaxError
end
+
+ context 'with complex expressions' do
+ using RSpec::Parameterized::TableSyntax
+
+ subject { described_class.new(expression).tokens.map(&:value) }
+
+ where(:expression, :tokens) do
+ '$PRESENT_VARIABLE =~ /my var/ && $EMPTY_VARIABLE =~ /nope/' | ['$PRESENT_VARIABLE', '=~', '/my var/', '&&', '$EMPTY_VARIABLE', '=~', '/nope/']
+ '$EMPTY_VARIABLE == "" && $PRESENT_VARIABLE' | ['$EMPTY_VARIABLE', '==', '""', '&&', '$PRESENT_VARIABLE']
+ '$EMPTY_VARIABLE == "" && $PRESENT_VARIABLE != "nope"' | ['$EMPTY_VARIABLE', '==', '""', '&&', '$PRESENT_VARIABLE', '!=', '"nope"']
+ '$PRESENT_VARIABLE && $EMPTY_VARIABLE' | ['$PRESENT_VARIABLE', '&&', '$EMPTY_VARIABLE']
+ '$PRESENT_VARIABLE =~ /my var/ || $EMPTY_VARIABLE =~ /nope/' | ['$PRESENT_VARIABLE', '=~', '/my var/', '||', '$EMPTY_VARIABLE', '=~', '/nope/']
+ '$EMPTY_VARIABLE == "" || $PRESENT_VARIABLE' | ['$EMPTY_VARIABLE', '==', '""', '||', '$PRESENT_VARIABLE']
+ '$EMPTY_VARIABLE == "" || $PRESENT_VARIABLE != "nope"' | ['$EMPTY_VARIABLE', '==', '""', '||', '$PRESENT_VARIABLE', '!=', '"nope"']
+ '$PRESENT_VARIABLE || $EMPTY_VARIABLE' | ['$PRESENT_VARIABLE', '||', '$EMPTY_VARIABLE']
+ '$PRESENT_VARIABLE && null || $EMPTY_VARIABLE == ""' | ['$PRESENT_VARIABLE', '&&', 'null', '||', '$EMPTY_VARIABLE', '==', '""']
+ end
+
+ with_them do
+ it { is_expected.to eq(tokens) }
+ end
+ end
+
+ context 'with the ci_variables_complex_expressions feature flag turned off' do
+ before do
+ stub_feature_flags(ci_variables_complex_expressions: false)
+ end
+
+ it 'incorrectly tokenizes conjunctive match statements as one match statement' do
+ tokens = described_class.new('$PRESENT_VARIABLE =~ /my var/ && $EMPTY_VARIABLE =~ /nope/').tokens
+
+ expect(tokens.map(&:value)).to eq(['$PRESENT_VARIABLE', '=~', '/my var/ && $EMPTY_VARIABLE =~ /nope/'])
+ end
+
+ it 'incorrectly tokenizes disjunctive match statements as one statement' do
+ tokens = described_class.new('$PRESENT_VARIABLE =~ /my var/ || $EMPTY_VARIABLE =~ /nope/').tokens
+
+ expect(tokens.map(&:value)).to eq(['$PRESENT_VARIABLE', '=~', '/my var/ || $EMPTY_VARIABLE =~ /nope/'])
+ end
+
+ it 'raises an error about && operators' do
+ expect { described_class.new('$EMPTY_VARIABLE == "" && $PRESENT_VARIABLE').tokens }
+ .to raise_error(Gitlab::Ci::Pipeline::Expression::Lexer::SyntaxError).with_message('Unknown lexeme found!')
+ end
+
+ it 'raises an error about || operators' do
+ expect { described_class.new('$EMPTY_VARIABLE == "" || $PRESENT_VARIABLE').tokens }
+ .to raise_error(Gitlab::Ci::Pipeline::Expression::Lexer::SyntaxError).with_message('Unknown lexeme found!')
+ end
+ end
end
describe '#lexemes' do
diff --git a/spec/lib/gitlab/ci/pipeline/expression/parser_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/parser_spec.rb
index 2b78b1dd4a7..e88ec5561b6 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/parser_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/parser_spec.rb
@@ -2,25 +2,67 @@ require 'fast_spec_helper'
describe Gitlab::Ci::Pipeline::Expression::Parser do
describe '#tree' do
- context 'when using operators' do
+ context 'when using two operators' do
+ it 'returns a reverse descent parse tree' do
+ expect(described_class.seed('$VAR1 == "123"').tree)
+ .to be_a Gitlab::Ci::Pipeline::Expression::Lexeme::Equals
+ end
+ end
+
+ context 'when using three operators' do
it 'returns a reverse descent parse tree' do
expect(described_class.seed('$VAR1 == "123" == $VAR2').tree)
.to be_a Gitlab::Ci::Pipeline::Expression::Lexeme::Equals
end
end
- context 'when using a single token' do
+ context 'when using a single variable token' do
it 'returns a single token instance' do
expect(described_class.seed('$VAR').tree)
.to be_a Gitlab::Ci::Pipeline::Expression::Lexeme::Variable
end
end
+ context 'when using a single string token' do
+ it 'returns a single token instance' do
+ expect(described_class.seed('"some value"').tree)
+ .to be_a Gitlab::Ci::Pipeline::Expression::Lexeme::String
+ end
+ end
+
context 'when expression is empty' do
it 'returns a null token' do
- expect(described_class.seed('').tree)
+ expect { described_class.seed('').tree }
+ .to raise_error Gitlab::Ci::Pipeline::Expression::Parser::ParseError
+ end
+ end
+
+ context 'when expression is null' do
+ it 'returns a null token' do
+ expect(described_class.seed('null').tree)
.to be_a Gitlab::Ci::Pipeline::Expression::Lexeme::Null
end
end
+
+ context 'when two value tokens have no operator' do
+ it 'raises a parsing error' do
+ expect { described_class.seed('$VAR "text"').tree }
+ .to raise_error Gitlab::Ci::Pipeline::Expression::Parser::ParseError
+ end
+ end
+
+ context 'when an operator has no left side' do
+ it 'raises an OperatorError' do
+ expect { described_class.seed('== "123"').tree }
+ .to raise_error Gitlab::Ci::Pipeline::Expression::Lexeme::Operator::OperatorError
+ end
+ end
+
+ context 'when an operator has no right side' do
+ it 'raises an OperatorError' do
+ expect { described_class.seed('$VAR ==').tree }
+ .to raise_error Gitlab::Ci::Pipeline::Expression::Lexeme::Operator::OperatorError
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb
index 11e73294f18..057e2f3fbe8 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb
@@ -1,4 +1,6 @@
-require 'fast_spec_helper'
+# TODO switch this back after the "ci_variables_complex_expressions" feature flag is removed
+# require 'fast_spec_helper'
+require 'spec_helper'
require 'rspec-parameterized'
describe Gitlab::Ci::Pipeline::Expression::Statement do
@@ -7,8 +9,12 @@ describe Gitlab::Ci::Pipeline::Expression::Statement do
end
let(:variables) do
- { 'PRESENT_VARIABLE' => 'my variable',
- EMPTY_VARIABLE: '' }
+ {
+ 'PRESENT_VARIABLE' => 'my variable',
+ 'PATH_VARIABLE' => 'a/path/variable/value',
+ 'FULL_PATH_VARIABLE' => '/a/full/path/variable/value',
+ 'EMPTY_VARIABLE' => ''
+ }
end
describe '.new' do
@@ -21,93 +27,158 @@ describe Gitlab::Ci::Pipeline::Expression::Statement do
end
end
- describe '#parse_tree' do
- context 'when expression is empty' do
- let(:text) { '' }
-
- it 'raises an error' do
- expect { subject.parse_tree }
- .to raise_error described_class::StatementError
- end
- end
+ describe '#evaluate' do
+ using RSpec::Parameterized::TableSyntax
- context 'when expression grammar is incorrect' do
- table = [
- '$VAR "text"', # missing operator
- '== "123"', # invalid left side
- '"some string"', # only string provided
- '$VAR ==', # invalid right side
- 'null', # missing lexemes
- '' # empty statement
- ]
-
- table.each do |syntax|
- context "when expression grammar is #{syntax.inspect}" do
- let(:text) { syntax }
-
- it 'raises a statement error exception' do
- expect { subject.parse_tree }
- .to raise_error described_class::StatementError
- end
-
- it 'is an invalid statement' do
- expect(subject).not_to be_valid
- end
- end
- end
+ where(:expression, :value) do
+ '$PRESENT_VARIABLE == "my variable"' | true
+ '"my variable" == $PRESENT_VARIABLE' | true
+ '$PRESENT_VARIABLE == null' | false
+ '$EMPTY_VARIABLE == null' | false
+ '"" == $EMPTY_VARIABLE' | true
+ '$EMPTY_VARIABLE' | ''
+ '$UNDEFINED_VARIABLE == null' | true
+ 'null == $UNDEFINED_VARIABLE' | true
+ '$PRESENT_VARIABLE' | 'my variable'
+ '$UNDEFINED_VARIABLE' | nil
+ "$PRESENT_VARIABLE =~ /var.*e$/" | 3
+ '$PRESENT_VARIABLE =~ /va\r.*e$/' | nil
+ '$PRESENT_VARIABLE =~ /va\/r.*e$/' | nil
+ "$PRESENT_VARIABLE =~ /var.*e$/" | 3
+ "$PRESENT_VARIABLE =~ /^var.*/" | nil
+ "$EMPTY_VARIABLE =~ /var.*/" | nil
+ "$UNDEFINED_VARIABLE =~ /var.*/" | nil
+ "$PRESENT_VARIABLE =~ /VAR.*/i" | 3
+ '$PATH_VARIABLE =~ /path\/variable/' | 2
+ '$FULL_PATH_VARIABLE =~ /^\/a\/full\/path\/variable\/value$/' | 0
+ '$FULL_PATH_VARIABLE =~ /\\/path\\/variable\\/value$/' | 7
+ '$PRESENT_VARIABLE != "my variable"' | false
+ '"my variable" != $PRESENT_VARIABLE' | false
+ '$PRESENT_VARIABLE != null' | true
+ '$EMPTY_VARIABLE != null' | true
+ '"" != $EMPTY_VARIABLE' | false
+ '$UNDEFINED_VARIABLE != null' | false
+ 'null != $UNDEFINED_VARIABLE' | false
+ "$PRESENT_VARIABLE !~ /var.*e$/" | false
+ "$PRESENT_VARIABLE !~ /^var.*/" | true
+ '$PRESENT_VARIABLE !~ /^v\ar.*/' | true
+ '$PRESENT_VARIABLE !~ /^v\/ar.*/' | true
+ "$EMPTY_VARIABLE !~ /var.*/" | true
+ "$UNDEFINED_VARIABLE !~ /var.*/" | true
+ "$PRESENT_VARIABLE !~ /VAR.*/i" | false
+
+ '$PRESENT_VARIABLE && "string"' | 'string'
+ '$PRESENT_VARIABLE && $PRESENT_VARIABLE' | 'my variable'
+ '$PRESENT_VARIABLE && $EMPTY_VARIABLE' | ''
+ '$PRESENT_VARIABLE && null' | nil
+ '"string" && $PRESENT_VARIABLE' | 'my variable'
+ '$EMPTY_VARIABLE && $PRESENT_VARIABLE' | 'my variable'
+ 'null && $PRESENT_VARIABLE' | nil
+ '$EMPTY_VARIABLE && "string"' | 'string'
+ '$EMPTY_VARIABLE && $EMPTY_VARIABLE' | ''
+ '"string" && $EMPTY_VARIABLE' | ''
+ '"string" && null' | nil
+ 'null && "string"' | nil
+ '"string" && "string"' | 'string'
+ 'null && null' | nil
+
+ '$PRESENT_VARIABLE =~ /my var/ && $EMPTY_VARIABLE =~ /nope/' | nil
+ '$EMPTY_VARIABLE == "" && $PRESENT_VARIABLE' | 'my variable'
+ '$EMPTY_VARIABLE == "" && $PRESENT_VARIABLE != "nope"' | true
+ '$PRESENT_VARIABLE && $EMPTY_VARIABLE' | ''
+ '$PRESENT_VARIABLE && $UNDEFINED_VARIABLE' | nil
+ '$UNDEFINED_VARIABLE && $EMPTY_VARIABLE' | nil
+ '$UNDEFINED_VARIABLE && $PRESENT_VARIABLE' | nil
+
+ '$FULL_PATH_VARIABLE =~ /^\/a\/full\/path\/variable\/value$/ && $PATH_VARIABLE =~ /path\/variable/' | 2
+ '$FULL_PATH_VARIABLE =~ /^\/a\/bad\/path\/variable\/value$/ && $PATH_VARIABLE =~ /path\/variable/' | nil
+ '$FULL_PATH_VARIABLE =~ /^\/a\/full\/path\/variable\/value$/ && $PATH_VARIABLE =~ /bad\/path\/variable/' | nil
+ '$FULL_PATH_VARIABLE =~ /^\/a\/bad\/path\/variable\/value$/ && $PATH_VARIABLE =~ /bad\/path\/variable/' | nil
+
+ '$FULL_PATH_VARIABLE =~ /^\/a\/full\/path\/variable\/value$/ || $PATH_VARIABLE =~ /path\/variable/' | 0
+ '$FULL_PATH_VARIABLE =~ /^\/a\/bad\/path\/variable\/value$/ || $PATH_VARIABLE =~ /path\/variable/' | 2
+ '$FULL_PATH_VARIABLE =~ /^\/a\/full\/path\/variable\/value$/ || $PATH_VARIABLE =~ /bad\/path\/variable/' | 0
+ '$FULL_PATH_VARIABLE =~ /^\/a\/bad\/path\/variable\/value$/ || $PATH_VARIABLE =~ /bad\/path\/variable/' | nil
+
+ '$PRESENT_VARIABLE =~ /my var/ || $EMPTY_VARIABLE =~ /nope/' | 0
+ '$EMPTY_VARIABLE == "" || $PRESENT_VARIABLE' | true
+ '$PRESENT_VARIABLE != "nope" || $EMPTY_VARIABLE == ""' | true
+
+ '$PRESENT_VARIABLE && null || $EMPTY_VARIABLE == ""' | true
+ '$PRESENT_VARIABLE || $UNDEFINED_VARIABLE' | 'my variable'
+ '$UNDEFINED_VARIABLE || $PRESENT_VARIABLE' | 'my variable'
+ '$UNDEFINED_VARIABLE == null || $PRESENT_VARIABLE' | true
+ '$PRESENT_VARIABLE || $UNDEFINED_VARIABLE == null' | 'my variable'
end
- context 'when expression grammar is correct' do
- context 'when using an operator' do
- let(:text) { '$VAR == "value"' }
-
- it 'returns a reverse descent parse tree' do
- expect(subject.parse_tree)
- .to be_a Gitlab::Ci::Pipeline::Expression::Lexeme::Equals
- end
+ with_them do
+ let(:text) { expression }
- it 'is a valid statement' do
- expect(subject).to be_valid
- end
+ it "evaluates to `#{params[:value].inspect}`" do
+ expect(subject.evaluate).to eq(value)
end
- context 'when using a single token' do
- let(:text) { '$PRESENT_VARIABLE' }
+ # This test is used to ensure that our parser
+ # returns exactly the same results as if we
+ # were evaluating using ruby's `eval`
+ context 'when using Ruby eval' do
+ let(:expression_ruby) do
+ expression
+ .gsub(/null/, 'nil')
+ .gsub(/\$([a-zA-Z_][a-zA-Z0-9_]*)/) { "variables['#{Regexp.last_match(1)}']" }
+ end
- it 'returns a single token instance' do
- expect(subject.parse_tree)
- .to be_a Gitlab::Ci::Pipeline::Expression::Lexeme::Variable
+ it 'behaves exactly the same' do
+ expect(instance_eval(expression_ruby)).to eq(subject.evaluate)
end
end
end
- end
- describe '#evaluate' do
- using RSpec::Parameterized::TableSyntax
+ context 'with the ci_variables_complex_expressions feature flag disabled' do
+ before do
+ stub_feature_flags(ci_variables_complex_expressions: false)
+ end
- where(:expression, :value) do
- '$PRESENT_VARIABLE == "my variable"' | true
- '"my variable" == $PRESENT_VARIABLE' | true
- '$PRESENT_VARIABLE == null' | false
- '$EMPTY_VARIABLE == null' | false
- '"" == $EMPTY_VARIABLE' | true
- '$EMPTY_VARIABLE' | ''
- '$UNDEFINED_VARIABLE == null' | true
- 'null == $UNDEFINED_VARIABLE' | true
- '$PRESENT_VARIABLE' | 'my variable'
- '$UNDEFINED_VARIABLE' | nil
- "$PRESENT_VARIABLE =~ /var.*e$/" | true
- "$PRESENT_VARIABLE =~ /^var.*/" | false
- "$EMPTY_VARIABLE =~ /var.*/" | false
- "$UNDEFINED_VARIABLE =~ /var.*/" | false
- "$PRESENT_VARIABLE =~ /VAR.*/i" | true
- end
+ where(:expression, :value) do
+ '$PRESENT_VARIABLE == "my variable"' | true
+ '"my variable" == $PRESENT_VARIABLE' | true
+ '$PRESENT_VARIABLE == null' | false
+ '$EMPTY_VARIABLE == null' | false
+ '"" == $EMPTY_VARIABLE' | true
+ '$EMPTY_VARIABLE' | ''
+ '$UNDEFINED_VARIABLE == null' | true
+ 'null == $UNDEFINED_VARIABLE' | true
+ '$PRESENT_VARIABLE' | 'my variable'
+ '$UNDEFINED_VARIABLE' | nil
+ "$PRESENT_VARIABLE =~ /var.*e$/" | true
+ "$PRESENT_VARIABLE =~ /^var.*/" | false
+ "$EMPTY_VARIABLE =~ /var.*/" | false
+ "$UNDEFINED_VARIABLE =~ /var.*/" | false
+ "$PRESENT_VARIABLE =~ /VAR.*/i" | true
+ '$PATH_VARIABLE =~ /path/variable/' | true
+ '$PATH_VARIABLE =~ /path\/variable/' | true
+ '$FULL_PATH_VARIABLE =~ /^/a/full/path/variable/value$/' | true
+ '$FULL_PATH_VARIABLE =~ /^\/a\/full\/path\/variable\/value$/' | true
+ '$PRESENT_VARIABLE != "my variable"' | false
+ '"my variable" != $PRESENT_VARIABLE' | false
+ '$PRESENT_VARIABLE != null' | true
+ '$EMPTY_VARIABLE != null' | true
+ '"" != $EMPTY_VARIABLE' | false
+ '$UNDEFINED_VARIABLE != null' | false
+ 'null != $UNDEFINED_VARIABLE' | false
+ "$PRESENT_VARIABLE !~ /var.*e$/" | false
+ "$PRESENT_VARIABLE !~ /^var.*/" | true
+ "$EMPTY_VARIABLE !~ /var.*/" | true
+ "$UNDEFINED_VARIABLE !~ /var.*/" | true
+ "$PRESENT_VARIABLE !~ /VAR.*/i" | false
+ end
- with_them do
- let(:text) { expression }
+ with_them do
+ let(:text) { expression }
- it "evaluates to `#{params[:value].inspect}`" do
- expect(subject.evaluate).to eq value
+ it "evaluates to `#{params[:value].inspect}`" do
+ expect(subject.evaluate).to eq value
+ end
end
end
end
@@ -125,6 +196,8 @@ describe Gitlab::Ci::Pipeline::Expression::Statement do
'$INVALID = 1' | false
"$PRESENT_VARIABLE =~ /var.*/" | true
"$UNDEFINED_VARIABLE =~ /var.*/" | false
+ "$PRESENT_VARIABLE !~ /var.*/" | false
+ "$UNDEFINED_VARIABLE !~ /var.*/" | true
end
with_them do
diff --git a/spec/lib/gitlab/ci/status/stage/factory_spec.rb b/spec/lib/gitlab/ci/status/stage/factory_spec.rb
index dee4f4efd1b..4b299170c87 100644
--- a/spec/lib/gitlab/ci/status/stage/factory_spec.rb
+++ b/spec/lib/gitlab/ci/status/stage/factory_spec.rb
@@ -22,7 +22,7 @@ describe Gitlab::Ci::Status::Stage::Factory do
end
context 'when stage has a core status' do
- HasStatus::AVAILABLE_STATUSES.each do |core_status|
+ (HasStatus::AVAILABLE_STATUSES - %w(manual skipped scheduled)).each do |core_status|
context "when core status is #{core_status}" do
before do
create(:ci_build, pipeline: pipeline, stage: 'test', status: core_status)
@@ -64,4 +64,20 @@ describe Gitlab::Ci::Status::Stage::Factory do
expect(status.details_path).to include "pipelines/#{pipeline.id}##{stage.name}"
end
end
+
+ context 'when stage has manual builds' do
+ (HasStatus::BLOCKED_STATUS + ['skipped']).each do |core_status|
+ context "when status is #{core_status}" do
+ before do
+ create(:ci_build, pipeline: pipeline, stage: 'test', status: core_status)
+ create(:commit_status, pipeline: pipeline, stage: 'test', status: core_status)
+ create(:ci_build, pipeline: pipeline, stage: 'build', status: :manual)
+ end
+
+ it 'fabricates a play manual status' do
+ expect(status).to be_a(Gitlab::Ci::Status::Stage::PlayManual)
+ end
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/status/stage/play_manual_spec.rb b/spec/lib/gitlab/ci/status/stage/play_manual_spec.rb
new file mode 100644
index 00000000000..b0113b00ef0
--- /dev/null
+++ b/spec/lib/gitlab/ci/status/stage/play_manual_spec.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Ci::Status::Stage::PlayManual do
+ let(:stage) { double('stage') }
+ let(:play_manual) { described_class.new(stage) }
+
+ describe '#action_icon' do
+ subject { play_manual.action_icon }
+
+ it { is_expected.to eq('play') }
+ end
+
+ describe '#action_button_title' do
+ subject { play_manual.action_button_title }
+
+ it { is_expected.to eq('Play all manual') }
+ end
+
+ describe '#action_title' do
+ subject { play_manual.action_title }
+
+ it { is_expected.to eq('Play all manual') }
+ end
+
+ describe '#action_path' do
+ let(:stage) { create(:ci_stage_entity, status: 'manual') }
+ let(:pipeline) { stage.pipeline }
+ let(:play_manual) { stage.detailed_status(create(:user)) }
+
+ subject { play_manual.action_path }
+
+ it { is_expected.to eq("/#{pipeline.project.full_path}/pipelines/#{pipeline.id}/stages/#{stage.name}/play_manual") }
+ end
+
+ describe '#action_method' do
+ subject { play_manual.action_method }
+
+ it { is_expected.to eq(:post) }
+ end
+
+ describe '.matches?' do
+ let(:user) { double('user') }
+
+ subject { described_class.matches?(stage, user) }
+
+ context 'when stage is skipped' do
+ let(:stage) { create(:ci_stage_entity, status: :skipped) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when stage is manual' do
+ let(:stage) { create(:ci_stage_entity, status: :manual) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when stage is scheduled' do
+ let(:stage) { create(:ci_stage_entity, status: :scheduled) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when stage is success' do
+ let(:stage) { create(:ci_stage_entity, status: :success) }
+
+ context 'and does not have manual builds' do
+ it { is_expected.to be_falsy }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/variables/collection/item_spec.rb b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
index 3ff2fe18c15..613814df23f 100644
--- a/spec/lib/gitlab/ci/variables/collection/item_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
@@ -137,19 +137,5 @@ describe Gitlab::Ci::Variables::Collection::Item do
.to eq(key: 'VAR', value: 'value', public: true, file: true, masked: false)
end
end
-
- context 'when variable masking is disabled' do
- before do
- stub_feature_flags(variable_masking: false)
- end
-
- it 'does not expose the masked field to the runner' do
- runner_variable = described_class
- .new(key: 'VAR', value: 'value', masked: true)
- .to_runner_variable
-
- expect(runner_variable).to eq(key: 'VAR', value: 'value', public: true)
- end
- end
end
end
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index 0d998d89d73..635b4e556e8 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -3,6 +3,8 @@ require 'spec_helper'
module Gitlab
module Ci
describe YamlProcessor do
+ include StubRequests
+
subject { described_class.new(config, user: nil) }
describe '#build_attributes' do
@@ -648,7 +650,7 @@ module Gitlab
end
before do
- WebMock.stub_request(:get, 'https://gitlab.com/awesome-project/raw/master/.before-script-template.yml')
+ stub_full_request('https://gitlab.com/awesome-project/raw/master/.before-script-template.yml')
.to_return(
status: 200,
headers: { 'Content-Type' => 'application/json' },
@@ -1468,7 +1470,7 @@ module Gitlab
expect { Gitlab::Ci::YamlProcessor.new(config) }
.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError,
- 'rspec: unknown key in `extends`')
+ 'rspec: unknown keys in `extends` (something)')
end
end
diff --git a/spec/lib/gitlab/cluster/puma_worker_killer_observer_spec.rb b/spec/lib/gitlab/cluster/puma_worker_killer_observer_spec.rb
new file mode 100644
index 00000000000..180520b27e7
--- /dev/null
+++ b/spec/lib/gitlab/cluster/puma_worker_killer_observer_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Cluster::PumaWorkerKillerObserver do
+ let(:counter) { Gitlab::Metrics::NullMetric.instance }
+
+ before do
+ allow(Gitlab::Metrics).to receive(:counter)
+ .with(any_args)
+ .and_return(counter)
+ end
+
+ describe '#callback' do
+ subject { described_class.new }
+
+ it 'increments timeout counter' do
+ worker = double(index: 0)
+
+ expect(counter)
+ .to receive(:increment)
+ .with({ worker: 'worker_0' })
+
+ subject.callback.call(worker)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/cluster/rack_timeout_observer_spec.rb b/spec/lib/gitlab/cluster/rack_timeout_observer_spec.rb
new file mode 100644
index 00000000000..68e5435450c
--- /dev/null
+++ b/spec/lib/gitlab/cluster/rack_timeout_observer_spec.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Cluster::RackTimeoutObserver do
+ let(:counter) { Gitlab::Metrics::NullMetric.instance }
+
+ before do
+ allow(Gitlab::Metrics).to receive(:counter)
+ .with(any_args)
+ .and_return(counter)
+ end
+
+ describe '#callback' do
+ context 'when request times out' do
+ let(:env) do
+ {
+ ::Rack::Timeout::ENV_INFO_KEY => double(state: :timed_out),
+ 'action_dispatch.request.parameters' => {
+ 'controller' => 'foo',
+ 'action' => 'bar'
+ }
+ }
+ end
+
+ subject { described_class.new }
+
+ it 'increments counter' do
+ expect(counter)
+ .to receive(:increment)
+ .with({ controller: 'foo', action: 'bar', route: nil, state: :timed_out })
+
+ subject.callback.call(env)
+ end
+ end
+
+ context 'when request expires' do
+ let(:endpoint) { double }
+ let(:env) do
+ {
+ ::Rack::Timeout::ENV_INFO_KEY => double(state: :expired),
+ Grape::Env::API_ENDPOINT => endpoint
+ }
+ end
+
+ subject { described_class.new }
+
+ it 'increments counter' do
+ allow(endpoint).to receive_message_chain('route.pattern.origin') { 'foobar' }
+ expect(counter)
+ .to receive(:increment)
+ .with({ controller: nil, action: nil, route: 'foobar', state: :expired })
+
+ subject.callback.call(env)
+ end
+ end
+
+ context 'when request is being processed' do
+ let(:endpoint) { double }
+ let(:env) do
+ {
+ ::Rack::Timeout::ENV_INFO_KEY => double(state: :active),
+ Grape::Env::API_ENDPOINT => endpoint
+ }
+ end
+
+ subject { described_class.new }
+
+ it 'does not increment counter' do
+ allow(endpoint).to receive_message_chain('route.pattern.origin') { 'foobar' }
+ expect(counter).not_to receive(:increment)
+
+ subject.callback.call(env)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/correlation_id_spec.rb b/spec/lib/gitlab/correlation_id_spec.rb
deleted file mode 100644
index 584d1f48386..00000000000
--- a/spec/lib/gitlab/correlation_id_spec.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-
-describe Gitlab::CorrelationId do
- describe '.use_id' do
- it 'yields when executed' do
- expect { |blk| described_class.use_id('id', &blk) }.to yield_control
- end
-
- it 'stacks correlation ids' do
- described_class.use_id('id1') do
- described_class.use_id('id2') do |current_id|
- expect(current_id).to eq('id2')
- end
- end
- end
-
- it 'for missing correlation id it generates random one' do
- described_class.use_id('id1') do
- described_class.use_id(nil) do |current_id|
- expect(current_id).not_to be_empty
- expect(current_id).not_to eq('id1')
- end
- end
- end
- end
-
- describe '.current_id' do
- subject { described_class.current_id }
-
- it 'returns last correlation id' do
- described_class.use_id('id1') do
- described_class.use_id('id2') do
- is_expected.to eq('id2')
- end
- end
- end
- end
-
- describe '.current_or_new_id' do
- subject { described_class.current_or_new_id }
-
- context 'when correlation id is set' do
- it 'returns last correlation id' do
- described_class.use_id('id1') do
- is_expected.to eq('id1')
- end
- end
- end
-
- context 'when correlation id is missing' do
- it 'returns a new correlation id' do
- expect(described_class).to receive(:new_id)
- .and_call_original
-
- is_expected.not_to be_empty
- end
- end
- end
-
- describe '.ids' do
- subject { described_class.send(:ids) }
-
- it 'returns empty list if not correlation is used' do
- is_expected.to be_empty
- end
-
- it 'returns list if correlation ids are used' do
- described_class.use_id('id1') do
- described_class.use_id('id2') do
- is_expected.to eq(%w(id1 id2))
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/danger/helper_spec.rb b/spec/lib/gitlab/danger/helper_spec.rb
index 66cd8171c12..22e52901758 100644
--- a/spec/lib/gitlab/danger/helper_spec.rb
+++ b/spec/lib/gitlab/danger/helper_spec.rb
@@ -2,7 +2,6 @@
require 'fast_spec_helper'
require 'rspec-parameterized'
-require 'webmock/rspec'
require 'gitlab/danger/helper'
@@ -19,39 +18,6 @@ describe Gitlab::Danger::Helper do
end
end
- let(:teammate_json) do
- <<~JSON
- [
- {
- "username": "in-gitlab-ce",
- "name": "CE maintainer",
- "projects":{ "gitlab-ce": "maintainer backend" }
- },
- {
- "username": "in-gitlab-ee",
- "name": "EE reviewer",
- "projects":{ "gitlab-ee": "reviewer frontend" }
- }
- ]
- JSON
- end
-
- let(:ce_teammate_matcher) do
- satisfy do |teammate|
- teammate.username == 'in-gitlab-ce' &&
- teammate.name == 'CE maintainer' &&
- teammate.projects == { 'gitlab-ce' => 'maintainer backend' }
- end
- end
-
- let(:ee_teammate_matcher) do
- satisfy do |teammate|
- teammate.username == 'in-gitlab-ee' &&
- teammate.name == 'EE reviewer' &&
- teammate.projects == { 'gitlab-ee' => 'reviewer frontend' }
- end
- end
-
let(:fake_git) { double('fake-git') }
subject(:helper) { FakeDanger.new(git: fake_git) }
@@ -119,69 +85,6 @@ describe Gitlab::Danger::Helper do
end
end
- describe '#team' do
- subject(:team) { helper.team }
-
- context 'HTTP failure' do
- before do
- WebMock
- .stub_request(:get, 'https://about.gitlab.com/roulette.json')
- .to_return(status: 404)
- end
-
- it 'raises a pretty error' do
- expect { team }.to raise_error(/Failed to read/)
- end
- end
-
- context 'JSON failure' do
- before do
- WebMock
- .stub_request(:get, 'https://about.gitlab.com/roulette.json')
- .to_return(body: 'INVALID JSON')
- end
-
- it 'raises a pretty error' do
- expect { team }.to raise_error(/Failed to parse/)
- end
- end
-
- context 'success' do
- before do
- WebMock
- .stub_request(:get, 'https://about.gitlab.com/roulette.json')
- .to_return(body: teammate_json)
- end
-
- it 'returns an array of teammates' do
- is_expected.to contain_exactly(ce_teammate_matcher, ee_teammate_matcher)
- end
-
- it 'memoizes the result' do
- expect(team.object_id).to eq(helper.team.object_id)
- end
- end
- end
-
- describe '#project_team' do
- subject { helper.project_team }
-
- before do
- WebMock
- .stub_request(:get, 'https://about.gitlab.com/roulette.json')
- .to_return(body: teammate_json)
- end
-
- it 'filters team by project_name' do
- expect(helper)
- .to receive(:project_name)
- .at_least(:once)
- .and_return('gitlab-ce')
-
- is_expected.to contain_exactly(ce_teammate_matcher)
- end
- end
-
describe '#changes_by_category' do
it 'categorizes changed files' do
expect(fake_git).to receive(:added_files) { %w[foo foo.md foo.rb foo.js db/foo qa/foo ee/changelogs/foo.yml] }
@@ -191,9 +94,8 @@ describe Gitlab::Danger::Helper do
expect(helper.changes_by_category).to eq(
backend: %w[foo.rb],
database: %w[db/foo],
- docs: %w[foo.md],
frontend: %w[foo.js],
- none: %w[ee/changelogs/foo.yml],
+ none: %w[ee/changelogs/foo.yml foo.md],
qa: %w[qa/foo],
unknown: %w[foo]
)
@@ -202,13 +104,13 @@ describe Gitlab::Danger::Helper do
describe '#category_for_file' do
where(:path, :expected_category) do
- 'doc/foo' | :docs
- 'CONTRIBUTING.md' | :docs
- 'LICENSE' | :docs
- 'MAINTENANCE.md' | :docs
- 'PHILOSOPHY.md' | :docs
- 'PROCESS.md' | :docs
- 'README.md' | :docs
+ 'doc/foo' | :none
+ 'CONTRIBUTING.md' | :none
+ 'LICENSE' | :none
+ 'MAINTENANCE.md' | :none
+ 'PHILOSOPHY.md' | :none
+ 'PROCESS.md' | :none
+ 'README.md' | :none
'ee/doc/foo' | :unknown
'ee/README' | :unknown
@@ -272,8 +174,8 @@ describe Gitlab::Danger::Helper do
'foo/bar.rb' | :backend
'foo/bar.js' | :frontend
- 'foo/bar.txt' | :docs
- 'foo/bar.md' | :docs
+ 'foo/bar.txt' | :none
+ 'foo/bar.md' | :none
end
with_them do
@@ -300,4 +202,14 @@ describe Gitlab::Danger::Helper do
it { is_expected.to eq(expected_label) }
end
end
+
+ describe '#new_teammates' do
+ it 'returns an array of Teammate' do
+ usernames = %w[filipa iamphil]
+
+ teammates = helper.new_teammates(usernames)
+
+ expect(teammates.map(&:username)).to eq(usernames)
+ end
+ end
end
diff --git a/spec/lib/gitlab/danger/roulette_spec.rb b/spec/lib/gitlab/danger/roulette_spec.rb
new file mode 100644
index 00000000000..121c5d8ecd9
--- /dev/null
+++ b/spec/lib/gitlab/danger/roulette_spec.rb
@@ -0,0 +1,144 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'webmock/rspec'
+
+require 'gitlab/danger/roulette'
+
+describe Gitlab::Danger::Roulette do
+ let(:teammate_json) do
+ <<~JSON
+ [
+ {
+ "username": "in-gitlab-ce",
+ "name": "CE maintainer",
+ "projects":{ "gitlab-ce": "maintainer backend" }
+ },
+ {
+ "username": "in-gitlab-ee",
+ "name": "EE reviewer",
+ "projects":{ "gitlab-ee": "reviewer frontend" }
+ }
+ ]
+ JSON
+ end
+
+ let(:ce_teammate_matcher) do
+ satisfy do |teammate|
+ teammate.username == 'in-gitlab-ce' &&
+ teammate.name == 'CE maintainer' &&
+ teammate.projects == { 'gitlab-ce' => 'maintainer backend' }
+ end
+ end
+
+ let(:ee_teammate_matcher) do
+ satisfy do |teammate|
+ teammate.username == 'in-gitlab-ee' &&
+ teammate.name == 'EE reviewer' &&
+ teammate.projects == { 'gitlab-ee' => 'reviewer frontend' }
+ end
+ end
+
+ subject(:roulette) { Object.new.extend(described_class) }
+
+ describe '#team' do
+ subject(:team) { roulette.team }
+
+ context 'HTTP failure' do
+ before do
+ WebMock
+ .stub_request(:get, described_class::ROULETTE_DATA_URL)
+ .to_return(status: 404)
+ end
+
+ it 'raises a pretty error' do
+ expect { team }.to raise_error(/Failed to read/)
+ end
+ end
+
+ context 'JSON failure' do
+ before do
+ WebMock
+ .stub_request(:get, described_class::ROULETTE_DATA_URL)
+ .to_return(body: 'INVALID JSON')
+ end
+
+ it 'raises a pretty error' do
+ expect { team }.to raise_error(/Failed to parse/)
+ end
+ end
+
+ context 'success' do
+ before do
+ WebMock
+ .stub_request(:get, described_class::ROULETTE_DATA_URL)
+ .to_return(body: teammate_json)
+ end
+
+ it 'returns an array of teammates' do
+ is_expected.to contain_exactly(ce_teammate_matcher, ee_teammate_matcher)
+ end
+
+ it 'memoizes the result' do
+ expect(team.object_id).to eq(roulette.team.object_id)
+ end
+ end
+ end
+
+ describe '#project_team' do
+ subject { roulette.project_team('gitlab-ce') }
+
+ before do
+ WebMock
+ .stub_request(:get, described_class::ROULETTE_DATA_URL)
+ .to_return(body: teammate_json)
+ end
+
+ it 'filters team by project_name' do
+ is_expected.to contain_exactly(ce_teammate_matcher)
+ end
+ end
+
+ describe '#spin_for_person' do
+ let(:person1) { Gitlab::Danger::Teammate.new('username' => 'rymai') }
+ let(:person2) { Gitlab::Danger::Teammate.new('username' => 'godfat') }
+ let(:author) { Gitlab::Danger::Teammate.new('username' => 'filipa') }
+ let(:ooo) { Gitlab::Danger::Teammate.new('username' => 'jacopo-beschi') }
+
+ before do
+ stub_person_message(person1, 'making GitLab magic')
+ stub_person_message(person2, 'making GitLab magic')
+ stub_person_message(ooo, 'OOO till 15th')
+ # we don't stub Filipa, as she is the author and
+ # we should not fire request checking for her
+
+ allow(subject).to receive_message_chain(:gitlab, :mr_author).and_return(author.username)
+ end
+
+ it 'returns a random person' do
+ persons = [person1, person2]
+
+ selected = subject.spin_for_person(persons, random: Random.new)
+
+ expect(selected.username).to be_in(persons.map(&:username))
+ end
+
+ it 'excludes OOO persons' do
+ expect(subject.spin_for_person([ooo], random: Random.new)).to be_nil
+ end
+
+ it 'excludes mr.author' do
+ expect(subject.spin_for_person([author], random: Random.new)).to be_nil
+ end
+
+ private
+
+ def stub_person_message(person, message)
+ body = { message: message }.to_json
+
+ WebMock
+ .stub_request(:get, "https://gitlab.com/api/v4/users/#{person.username}/status")
+ .to_return(body: body)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/danger/teammate_spec.rb b/spec/lib/gitlab/danger/teammate_spec.rb
index 4bc0a4c1398..6a6cf1429c8 100644
--- a/spec/lib/gitlab/danger/teammate_spec.rb
+++ b/spec/lib/gitlab/danger/teammate_spec.rb
@@ -1,39 +1,70 @@
# frozen_string_literal: true
+require 'fast_spec_helper'
+
+require 'gitlab/danger/teammate'
+
describe Gitlab::Danger::Teammate do
- subject { described_class.new({ 'projects' => projects }) }
+ subject { described_class.new(options) }
+ let(:options) { { 'projects' => projects, 'role' => role } }
let(:projects) { { project => capabilities } }
+ let(:role) { 'Engineer, Manage' }
+ let(:labels) { [] }
let(:project) { double }
- describe 'multiple roles project project' do
- let(:capabilities) { ['reviewer backend', 'maintainer frontend', 'trainee_maintainer database'] }
+ context 'when having multiple capabilities' do
+ let(:capabilities) { ['reviewer backend', 'maintainer frontend', 'trainee_maintainer qa'] }
it '#reviewer? supports multiple roles per project' do
- expect(subject.reviewer?(project, 'backend')).to be_truthy
+ expect(subject.reviewer?(project, :backend, labels)).to be_truthy
end
it '#traintainer? supports multiple roles per project' do
- expect(subject.traintainer?(project, 'database')).to be_truthy
+ expect(subject.traintainer?(project, :qa, labels)).to be_truthy
end
it '#maintainer? supports multiple roles per project' do
- expect(subject.maintainer?(project, 'frontend')).to be_truthy
+ expect(subject.maintainer?(project, :frontend, labels)).to be_truthy
+ end
+
+ context 'when labels contain Create and the category is test' do
+ let(:labels) { ['Create'] }
+
+ context 'when role is Test Automation Engineer, Create' do
+ let(:role) { 'Test Automation Engineer, Create' }
+
+ it '#reviewer? returns true' do
+ expect(subject.reviewer?(project, :test, labels)).to be_truthy
+ end
+
+ it '#maintainer? returns false' do
+ expect(subject.maintainer?(project, :test, labels)).to be_falsey
+ end
+ end
+
+ context 'when role is Test Automation Engineer, Manage' do
+ let(:role) { 'Test Automation Engineer, Manage' }
+
+ it '#reviewer? returns false' do
+ expect(subject.reviewer?(project, :test, labels)).to be_falsey
+ end
+ end
end
end
- describe 'one role project project' do
+ context 'when having single capability' do
let(:capabilities) { 'reviewer backend' }
it '#reviewer? supports one role per project' do
- expect(subject.reviewer?(project, 'backend')).to be_truthy
+ expect(subject.reviewer?(project, :backend, labels)).to be_truthy
end
it '#traintainer? supports one role per project' do
- expect(subject.traintainer?(project, 'database')).to be_falsey
+ expect(subject.traintainer?(project, :database, labels)).to be_falsey
end
it '#maintainer? supports one role per project' do
- expect(subject.maintainer?(project, 'frontend')).to be_falsey
+ expect(subject.maintainer?(project, :frontend, labels)).to be_falsey
end
end
end
diff --git a/spec/lib/gitlab/data_builder/deployment_spec.rb b/spec/lib/gitlab/data_builder/deployment_spec.rb
new file mode 100644
index 00000000000..0a6e2302b09
--- /dev/null
+++ b/spec/lib/gitlab/data_builder/deployment_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::DataBuilder::Deployment do
+ describe '.build' do
+ it 'returns the object kind for a deployment' do
+ deployment = build(:deployment)
+
+ data = described_class.build(deployment)
+
+ expect(data[:object_kind]).to eq('deployment')
+ end
+
+ it 'returns data for the given build' do
+ environment = create(:environment, name: "somewhere")
+ project = create(:project, :repository, name: 'myproj')
+ commit = project.commit('HEAD')
+ deployment = create(:deployment, status: :failed, environment: environment, sha: commit.sha, project: project)
+ deployable = deployment.deployable
+ expected_deployable_url = Gitlab::Routing.url_helpers.project_job_url(deployable.project, deployable)
+ expected_user_url = Gitlab::Routing.url_helpers.user_url(deployment.user)
+ expected_commit_url = Gitlab::UrlBuilder.build(commit)
+
+ data = described_class.build(deployment)
+
+ expect(data[:status]).to eq('failed')
+ expect(data[:deployable_id]).to eq(deployable.id)
+ expect(data[:deployable_url]).to eq(expected_deployable_url)
+ expect(data[:environment]).to eq("somewhere")
+ expect(data[:project]).to eq(project.hook_attrs)
+ expect(data[:short_sha]).to eq(deployment.short_sha)
+ expect(data[:user]).to eq(deployment.user.hook_attrs)
+ expect(data[:user_url]).to eq(expected_user_url)
+ expect(data[:commit_url]).to eq(expected_commit_url)
+ expect(data[:commit_title]).to eq(commit.title)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/data_builder/note_spec.rb b/spec/lib/gitlab/data_builder/note_spec.rb
index b236c1a9c49..ed9a1e23529 100644
--- a/spec/lib/gitlab/data_builder/note_spec.rb
+++ b/spec/lib/gitlab/data_builder/note_spec.rb
@@ -53,6 +53,8 @@ describe Gitlab::DataBuilder::Note do
.to eq(issue.reload.hook_attrs.except('updated_at'))
expect(data[:issue]['updated_at'])
.to be >= issue.hook_attrs['updated_at']
+ expect(data[:issue]['labels'])
+ .to eq(issue.hook_attrs['labels'])
end
context 'with confidential issue' do
diff --git a/spec/lib/gitlab/data_builder/pipeline_spec.rb b/spec/lib/gitlab/data_builder/pipeline_spec.rb
index 9ef987a0826..1f36fd5c6ef 100644
--- a/spec/lib/gitlab/data_builder/pipeline_spec.rb
+++ b/spec/lib/gitlab/data_builder/pipeline_spec.rb
@@ -50,5 +50,14 @@ describe Gitlab::DataBuilder::Pipeline do
it { expect(attributes[:variables]).to be_a(Array) }
it { expect(attributes[:variables]).to contain_exactly({ key: 'TRIGGER_KEY_1', value: 'TRIGGER_VALUE_1' }) }
end
+
+ context 'when pipeline is a detached merge request pipeline' do
+ let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) }
+ let(:pipeline) { merge_request.all_pipelines.first }
+
+ it 'returns a source ref' do
+ expect(attributes[:ref]).to eq(merge_request.source_branch)
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/data_builder/push_spec.rb b/spec/lib/gitlab/data_builder/push_spec.rb
index 0c4decc6518..46ad674a1eb 100644
--- a/spec/lib/gitlab/data_builder/push_spec.rb
+++ b/spec/lib/gitlab/data_builder/push_spec.rb
@@ -23,9 +23,12 @@ describe Gitlab::DataBuilder::Push do
describe '.build' do
let(:data) do
- described_class.build(project, user, Gitlab::Git::BLANK_SHA,
- '8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b',
- 'refs/tags/v1.1.0')
+ described_class.build(
+ project: project,
+ user: user,
+ oldrev: Gitlab::Git::BLANK_SHA,
+ newrev: '8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b',
+ ref: 'refs/tags/v1.1.0')
end
it { expect(data).to be_a(Hash) }
@@ -47,7 +50,7 @@ describe Gitlab::DataBuilder::Push do
include_examples 'deprecated repository hook data'
it 'does not raise an error when given nil commits' do
- expect { described_class.build(spy, spy, spy, spy, 'refs/tags/v1.1.0', nil) }
+ expect { described_class.build(project: spy, user: spy, ref: 'refs/tags/v1.1.0', commits: nil) }
.not_to raise_error
end
end
diff --git a/spec/lib/gitlab/discussions_diff/highlight_cache_spec.rb b/spec/lib/gitlab/discussions_diff/highlight_cache_spec.rb
index fe26ebb8796..15ee8c40b55 100644
--- a/spec/lib/gitlab/discussions_diff/highlight_cache_spec.rb
+++ b/spec/lib/gitlab/discussions_diff/highlight_cache_spec.rb
@@ -3,31 +3,32 @@
require 'spec_helper'
describe Gitlab::DiscussionsDiff::HighlightCache, :clean_gitlab_redis_cache do
+ def fake_file(offset)
+ {
+ text: 'foo',
+ type: 'new',
+ index: 2 + offset,
+ old_pos: 10 + offset,
+ new_pos: 11 + offset,
+ line_code: 'xpto',
+ rich_text: '<blips>blops</blips>'
+ }
+ end
+
+ let(:mapping) do
+ {
+ 3 => [
+ fake_file(0),
+ fake_file(1)
+ ],
+ 4 => [
+ fake_file(2)
+ ]
+ }
+ end
+
describe '#write_multiple' do
it 'sets multiple keys serializing content as JSON' do
- mapping = {
- 3 => [
- {
- text: 'foo',
- type: 'new',
- index: 2,
- old_pos: 10,
- new_pos: 11,
- line_code: 'xpto',
- rich_text: '<blips>blops</blips>'
- },
- {
- text: 'foo',
- type: 'new',
- index: 3,
- old_pos: 11,
- new_pos: 12,
- line_code: 'xpto',
- rich_text: '<blops>blips</blops>'
- }
- ]
- }
-
described_class.write_multiple(mapping)
mapping.each do |key, value|
@@ -41,53 +42,16 @@ describe Gitlab::DiscussionsDiff::HighlightCache, :clean_gitlab_redis_cache do
describe '#read_multiple' do
it 'reads multiple keys and serializes content into Gitlab::Diff::Line objects' do
- mapping = {
- 3 => [
- {
- text: 'foo',
- type: 'new',
- index: 2,
- old_pos: 11,
- new_pos: 12,
- line_code: 'xpto',
- rich_text: '<blips>blops</blips>'
- },
- {
- text: 'foo',
- type: 'new',
- index: 3,
- old_pos: 10,
- new_pos: 11,
- line_code: 'xpto',
- rich_text: '<blips>blops</blips>'
- }
- ]
- }
-
described_class.write_multiple(mapping)
found = described_class.read_multiple(mapping.keys)
- expect(found.size).to eq(1)
+ expect(found.size).to eq(2)
expect(found.first.size).to eq(2)
expect(found.first).to all(be_a(Gitlab::Diff::Line))
end
it 'returns nil when cached key is not found' do
- mapping = {
- 3 => [
- {
- text: 'foo',
- type: 'new',
- index: 2,
- old_pos: 11,
- new_pos: 12,
- line_code: 'xpto',
- rich_text: '<blips>blops</blips>'
- }
- ]
- }
-
described_class.write_multiple(mapping)
found = described_class.read_multiple([2, 3])
@@ -95,8 +59,30 @@ describe Gitlab::DiscussionsDiff::HighlightCache, :clean_gitlab_redis_cache do
expect(found.size).to eq(2)
expect(found.first).to eq(nil)
- expect(found.second.size).to eq(1)
+ expect(found.second.size).to eq(2)
expect(found.second).to all(be_a(Gitlab::Diff::Line))
end
end
+
+ describe '#clear_multiple' do
+ it 'removes all named keys' do
+ described_class.write_multiple(mapping)
+
+ described_class.clear_multiple(mapping.keys)
+
+ expect(described_class.read_multiple(mapping.keys)).to all(be_nil)
+ end
+
+ it 'only removed named keys' do
+ to_clear, to_leave = mapping.keys
+
+ described_class.write_multiple(mapping)
+ described_class.clear_multiple([to_clear])
+
+ cleared, left = described_class.read_multiple([to_clear, to_leave])
+
+ expect(cleared).to be_nil
+ expect(left).to all(be_a(Gitlab::Diff::Line))
+ end
+ end
end
diff --git a/spec/lib/gitlab/favicon_spec.rb b/spec/lib/gitlab/favicon_spec.rb
index 49a423191bb..dce56bbd2c4 100644
--- a/spec/lib/gitlab/favicon_spec.rb
+++ b/spec/lib/gitlab/favicon_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Gitlab::Favicon, :request_store do
expect(described_class.main).to match_asset_path '/assets/favicon.png'
end
- it 'has blue favicon for development' do
+ it 'has blue favicon for development', unless: Gitlab.ee? do
allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('development'))
expect(described_class.main).to match_asset_path '/assets/favicon-blue.png'
end
diff --git a/spec/lib/gitlab/git/blob_spec.rb b/spec/lib/gitlab/git/blob_spec.rb
index 10bc82e24d1..1c24244c3a6 100644
--- a/spec/lib/gitlab/git/blob_spec.rb
+++ b/spec/lib/gitlab/git/blob_spec.rb
@@ -341,7 +341,7 @@ describe Gitlab::Git::Blob, :seed_helper do
it { expect(blob.mode).to eq("100755") }
end
- context 'file with Chinese text' do
+ context 'file with Japanese text' do
let(:blob) { Gitlab::Git::Blob.find(repository, SeedRepo::Commit::ID, "encoding/テスト.txt") }
it { expect(blob.name).to eq("テスト.txt") }
diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb
index 507bf222810..25052a79916 100644
--- a/spec/lib/gitlab/git/commit_spec.rb
+++ b/spec/lib/gitlab/git/commit_spec.rb
@@ -380,7 +380,32 @@ describe Gitlab::Git::Commit, :seed_helper do
end
end
- describe '#batch_by_oid' do
+ shared_examples '.batch_by_oid' do
+ context 'with multiple OIDs' do
+ let(:oids) { [SeedRepo::Commit::ID, SeedRepo::FirstCommit::ID] }
+
+ it 'returns multiple commits' do
+ commits = described_class.batch_by_oid(repository, oids)
+
+ expect(commits.count).to eq(2)
+ expect(commits).to all( be_a(Gitlab::Git::Commit) )
+ expect(commits.first.sha).to eq(SeedRepo::Commit::ID)
+ expect(commits.second.sha).to eq(SeedRepo::FirstCommit::ID)
+ end
+ end
+
+ context 'when oids is empty' do
+ it 'returns empty commits' do
+ commits = described_class.batch_by_oid(repository, [])
+
+ expect(commits.count).to eq(0)
+ end
+ end
+ end
+
+ describe '.batch_by_oid with Gitaly enabled' do
+ it_should_behave_like '.batch_by_oid'
+
context 'when oids is empty' do
it 'makes no Gitaly request' do
expect(Gitlab::GitalyClient).not_to receive(:call)
@@ -390,6 +415,16 @@ describe Gitlab::Git::Commit, :seed_helper do
end
end
+ describe '.batch_by_oid with Rugged enabled', :enable_rugged do
+ it_should_behave_like '.batch_by_oid'
+
+ it 'calls out to the Rugged implementation' do
+ allow_any_instance_of(Rugged).to receive(:rev_parse).with(SeedRepo::Commit::ID).and_call_original
+
+ described_class.batch_by_oid(repository, [SeedRepo::Commit::ID])
+ end
+ end
+
shared_examples 'extracting commit signature' do
context 'when the commit is signed' do
let(:commit_id) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' }
diff --git a/spec/lib/gitlab/git/object_pool_spec.rb b/spec/lib/gitlab/git/object_pool_spec.rb
index 0d5069568e1..ebeb7b7b633 100644
--- a/spec/lib/gitlab/git/object_pool_spec.rb
+++ b/spec/lib/gitlab/git/object_pool_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe Gitlab::Git::ObjectPool do
+ include RepoHelpers
+
let(:pool_repository) { create(:pool_repository) }
let(:source_repository) { pool_repository.source_project.repository }
@@ -76,4 +78,43 @@ describe Gitlab::Git::ObjectPool do
end
end
end
+
+ describe '#fetch' do
+ let(:source_repository_path) { File.join(TestEnv.repos_path, source_repository.relative_path) }
+ let(:source_repository_rugged) { Rugged::Repository.new(source_repository_path) }
+ let(:commit_count) { source_repository.commit_count }
+
+ context "when the object's pool repository exists" do
+ it 'does not raise an error' do
+ expect { subject.fetch }.not_to raise_error
+ end
+ end
+
+ context "when the object's pool repository does not exist" do
+ before do
+ subject.delete
+ end
+
+ it "re-creates the object pool's repository" do
+ subject.fetch
+
+ expect(subject.repository.exists?).to be true
+ end
+
+ it 'does not raise an error' do
+ expect { subject.fetch }.not_to raise_error
+ end
+
+ it 'fetches objects from the source repository' do
+ new_commit_id = new_commit_edit_old_file(source_repository_rugged).oid
+
+ expect(subject.repository.exists?).to be false
+
+ subject.fetch
+
+ expect(subject.repository.commit_count('refs/remotes/origin/master')).to eq(commit_count)
+ expect(subject.repository.commit(new_commit_id).id).to eq(new_commit_id)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/git/repository_cleaner_spec.rb b/spec/lib/gitlab/git/repository_cleaner_spec.rb
index 6602f22843f..7bba0107e58 100644
--- a/spec/lib/gitlab/git/repository_cleaner_spec.rb
+++ b/spec/lib/gitlab/git/repository_cleaner_spec.rb
@@ -6,55 +6,62 @@ describe Gitlab::Git::RepositoryCleaner do
let(:project) { create(:project, :repository) }
let(:repository) { project.repository }
let(:head_sha) { repository.head_commit.id }
- let(:object_map_data) { "#{head_sha} #{'0' * 40}" }
+ let(:object_map_data) { "#{head_sha} #{Gitlab::Git::BLANK_SHA}" }
- subject(:cleaner) { described_class.new(repository.raw) }
+ let(:clean_refs) { %W[refs/environments/1 refs/merge-requests/1 refs/keep-around/#{head_sha}] }
+ let(:keep_refs) { %w[refs/heads/_keep refs/tags/_keep] }
- describe '#apply_bfg_object_map' do
- let(:clean_refs) { %W[refs/environments/1 refs/merge-requests/1 refs/keep-around/#{head_sha}] }
- let(:keep_refs) { %w[refs/heads/_keep refs/tags/_keep] }
+ subject(:cleaner) { described_class.new(repository.raw) }
+ shared_examples_for '#apply_bfg_object_map_stream' do
before do
(clean_refs + keep_refs).each { |ref| repository.create_ref(head_sha, ref) }
end
- context 'from StringIO' do
- let(:object_map) { StringIO.new(object_map_data) }
+ it 'removes internal references' do
+ entries = []
- it 'removes internal references' do
- cleaner.apply_bfg_object_map(object_map)
+ cleaner.apply_bfg_object_map_stream(object_map) do |rsp|
+ entries.concat(rsp.entries)
+ end
- aggregate_failures do
- clean_refs.each { |ref| expect(repository.ref_exists?(ref)).to be_falsy }
- keep_refs.each { |ref| expect(repository.ref_exists?(ref)).to be_truthy }
- end
+ aggregate_failures do
+ clean_refs.each { |ref| expect(repository.ref_exists?(ref)).to be(false) }
+ keep_refs.each { |ref| expect(repository.ref_exists?(ref)).to be(true) }
+
+ expect(entries).to contain_exactly(
+ Gitaly::ApplyBfgObjectMapStreamResponse::Entry.new(
+ type: :COMMIT,
+ old_oid: head_sha,
+ new_oid: Gitlab::Git::BLANK_SHA
+ )
+ )
end
end
+ end
- context 'from Gitlab::HttpIO' do
- let(:url) { 'http://example.com/bfg_object_map.txt' }
- let(:tempfile) { Tempfile.new }
- let(:object_map) { Gitlab::HttpIO.new(url, object_map_data.size) }
+ describe '#apply_bfg_object_map_stream (from StringIO)' do
+ let(:object_map) { StringIO.new(object_map_data) }
- around do |example|
- tempfile.write(object_map_data)
- tempfile.close
+ include_examples '#apply_bfg_object_map_stream'
+ end
- example.run
- ensure
- tempfile.unlink
- end
+ describe '#apply_bfg_object_map_stream (from Gitlab::HttpIO)' do
+ let(:url) { 'http://example.com/bfg_object_map.txt' }
+ let(:tempfile) { Tempfile.new }
+ let(:object_map) { Gitlab::HttpIO.new(url, object_map_data.size) }
- it 'removes internal references' do
- stub_remote_url_200(url, tempfile.path)
+ around do |example|
+ tempfile.write(object_map_data)
+ tempfile.close
- cleaner.apply_bfg_object_map(object_map)
+ stub_remote_url_200(url, tempfile.path)
- aggregate_failures do
- clean_refs.each { |ref| expect(repository.ref_exists?(ref)).to be_falsy }
- keep_refs.each { |ref| expect(repository.ref_exists?(ref)).to be_truthy }
- end
- end
+ example.run
+ ensure
+ tempfile.unlink
end
+
+ include_examples '#apply_bfg_object_map_stream'
end
end
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index 088f8acf554..e72fb9c6fbc 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -3,6 +3,7 @@ require "spec_helper"
describe Gitlab::Git::Repository, :seed_helper do
include Gitlab::EncodingHelper
+ include RepoHelpers
using RSpec::Parameterized::TableSyntax
shared_examples 'wrapping gRPC errors' do |gitaly_client_class, gitaly_client_method|
@@ -28,51 +29,6 @@ describe Gitlab::Git::Repository, :seed_helper do
let(:storage_path) { TestEnv.repos_path }
let(:user) { build(:user) }
- describe '.create_hooks' do
- let(:repo_path) { File.join(storage_path, 'hook-test.git') }
- let(:hooks_dir) { File.join(repo_path, 'hooks') }
- let(:target_hooks_dir) { Gitlab::Shell.new.hooks_path }
- let(:existing_target) { File.join(repo_path, 'foobar') }
-
- before do
- FileUtils.rm_rf(repo_path)
- FileUtils.mkdir_p(repo_path)
- end
-
- context 'hooks is a directory' do
- let(:existing_file) { File.join(hooks_dir, 'my-file') }
-
- before do
- FileUtils.mkdir_p(hooks_dir)
- FileUtils.touch(existing_file)
- described_class.create_hooks(repo_path, target_hooks_dir)
- end
-
- it { expect(File.readlink(hooks_dir)).to eq(target_hooks_dir) }
- it { expect(Dir[File.join(repo_path, "hooks.old.*/my-file")].count).to eq(1) }
- end
-
- context 'hooks is a valid symlink' do
- before do
- FileUtils.mkdir_p existing_target
- File.symlink(existing_target, hooks_dir)
- described_class.create_hooks(repo_path, target_hooks_dir)
- end
-
- it { expect(File.readlink(hooks_dir)).to eq(target_hooks_dir) }
- end
-
- context 'hooks is a broken symlink' do
- before do
- FileUtils.rm_f(existing_target)
- File.symlink(existing_target, hooks_dir)
- described_class.create_hooks(repo_path, target_hooks_dir)
- end
-
- it { expect(File.readlink(hooks_dir)).to eq(target_hooks_dir) }
- end
- end
-
describe "Respond to" do
subject { repository }
@@ -95,6 +51,12 @@ describe Gitlab::Git::Repository, :seed_helper do
end
end
+ describe '#create_repository' do
+ it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::RepositoryService, :create_repository do
+ subject { repository.create_repository }
+ end
+ end
+
describe '#branch_names' do
subject { repository.branch_names }
@@ -152,13 +114,14 @@ describe Gitlab::Git::Repository, :seed_helper do
let(:append_sha) { true }
let(:ref) { 'master' }
let(:format) { nil }
+ let(:path) { nil }
let(:expected_extension) { 'tar.gz' }
let(:expected_filename) { "#{expected_prefix}.#{expected_extension}" }
let(:expected_path) { File.join(storage_path, cache_key, expected_filename) }
let(:expected_prefix) { "gitlab-git-test-#{ref}-#{SeedRepo::LastCommit::ID}" }
- subject(:metadata) { repository.archive_metadata(ref, storage_path, 'gitlab-git-test', format, append_sha: append_sha) }
+ subject(:metadata) { repository.archive_metadata(ref, storage_path, 'gitlab-git-test', format, append_sha: append_sha, path: path) }
it 'sets CommitId to the commit SHA' do
expect(metadata['CommitId']).to eq(SeedRepo::LastCommit::ID)
@@ -176,6 +139,14 @@ describe Gitlab::Git::Repository, :seed_helper do
expect(metadata['ArchivePath']).to eq(expected_path)
end
+ context 'path is set' do
+ let(:path) { 'foo/bar' }
+
+ it 'appends the path to the prefix' do
+ expect(metadata['ArchivePrefix']).to eq("#{expected_prefix}-foo-bar")
+ end
+ end
+
context 'append_sha varies archive path and filename' do
where(:append_sha, :ref, :expected_prefix) do
sha = SeedRepo::LastCommit::ID
@@ -215,6 +186,18 @@ describe Gitlab::Git::Repository, :seed_helper do
it { is_expected.to be < 2 }
end
+ describe '#object_directory_size' do
+ before do
+ allow(repository.gitaly_repository_client)
+ .to receive(:get_object_directory_size)
+ .and_return(2)
+ end
+
+ subject { repository.object_directory_size }
+
+ it { is_expected.to eq 2048 }
+ end
+
describe '#empty?' do
it { expect(repository).not_to be_empty }
end
@@ -1943,13 +1926,6 @@ describe Gitlab::Git::Repository, :seed_helper do
expect { imported_repo.fsck }.not_to raise_exception
end
- it 'creates a symlink to the global hooks dir' do
- imported_repo.create_from_bundle(valid_bundle_path)
- hooks_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access { File.join(imported_repo.path, 'hooks') }
-
- expect(File.readlink(hooks_path)).to eq(Gitlab::Shell.new.hooks_path)
- end
-
it 'raises an error if the bundle is an attempted malicious payload' do
expect do
imported_repo.create_from_bundle(malicious_bundle_path)
@@ -1957,6 +1933,70 @@ describe Gitlab::Git::Repository, :seed_helper do
end
end
+ describe '#compare_source_branch' do
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_GITATTRIBUTES_REPO_PATH, '', 'group/project') }
+
+ context 'within same repository' do
+ it 'does not create a temp ref' do
+ expect(repository).not_to receive(:fetch_source_branch!)
+ expect(repository).not_to receive(:delete_refs)
+
+ compare = repository.compare_source_branch('master', repository, 'feature', straight: false)
+ expect(compare).to be_a(Gitlab::Git::Compare)
+ expect(compare.commits.count).to be > 0
+ end
+
+ it 'returns empty commits when source ref does not exist' do
+ compare = repository.compare_source_branch('master', repository, 'non-existent-branch', straight: false)
+
+ expect(compare.commits).to be_empty
+ end
+ end
+
+ context 'with different repositories' do
+ context 'when ref is known by source repo, but not by target' do
+ before do
+ mutable_repository.write_ref('another-branch', 'feature')
+ end
+
+ it 'creates temp ref' do
+ expect(repository).not_to receive(:fetch_source_branch!)
+ expect(repository).not_to receive(:delete_refs)
+
+ compare = repository.compare_source_branch('master', mutable_repository, 'another-branch', straight: false)
+ expect(compare).to be_a(Gitlab::Git::Compare)
+ expect(compare.commits.count).to be > 0
+ end
+ end
+
+ context 'when ref is known by source and target repos' do
+ before do
+ mutable_repository.write_ref('another-branch', 'feature')
+ repository.write_ref('another-branch', 'feature')
+ end
+
+ it 'does not create a temp ref' do
+ expect(repository).not_to receive(:fetch_source_branch!)
+ expect(repository).not_to receive(:delete_refs)
+
+ compare = repository.compare_source_branch('master', mutable_repository, 'another-branch', straight: false)
+ expect(compare).to be_a(Gitlab::Git::Compare)
+ expect(compare.commits.count).to be > 0
+ end
+ end
+
+ context 'when ref is unknown by source repo' do
+ it 'returns nil when source ref does not exist' do
+ expect(repository).to receive(:fetch_source_branch!).and_call_original
+ expect(repository).to receive(:delete_refs).and_call_original
+
+ compare = repository.compare_source_branch('master', mutable_repository, 'non-existent-branch', straight: false)
+ expect(compare).to be_nil
+ end
+ end
+ end
+ end
+
describe '#checksum' do
it 'calculates the checksum for non-empty repo' do
expect(repository.checksum).to eq '51d0a9662681f93e1fee547a6b7ba2bcaf716059'
@@ -2130,86 +2170,48 @@ describe Gitlab::Git::Repository, :seed_helper do
repository_rugged.references.create("refs/remotes/#{remote_name}/#{branch_name}", source_branch.dereferenced_target.sha)
end
- # Build the options hash that's passed to Rugged::Commit#create
- def commit_options(repo, index, target, ref, message)
- options = {}
- options[:tree] = index.write_tree(repo)
- options[:author] = {
- email: "test@example.com",
- name: "Test Author",
- time: Time.gm(2014, "mar", 3, 20, 15, 1)
- }
- options[:committer] = {
- email: "test@example.com",
- name: "Test Author",
- time: Time.gm(2014, "mar", 3, 20, 15, 1)
- }
- options[:message] ||= message
- options[:parents] = repo.empty? ? [] : [target].compact
- options[:update_ref] = ref
-
- options
- end
-
- # Writes a new commit to the repo and returns a Rugged::Commit. Replaces the
- # contents of CHANGELOG with a single new line of text.
- def new_commit_edit_old_file(repo)
- oid = repo.write("I replaced the changelog with this text", :blob)
- index = repo.index
- index.read_tree(repo.head.target.tree)
- index.add(path: "CHANGELOG", oid: oid, mode: 0100644)
-
- options = commit_options(
- repo,
- index,
- repo.head.target,
- "HEAD",
- "Edit CHANGELOG in its original location"
- )
-
- sha = Rugged::Commit.create(repo, options)
- repo.lookup(sha)
- end
-
- # Writes a new commit to the repo and returns a Rugged::Commit. Replaces the
- # contents of the specified file_path with new text.
- def new_commit_edit_new_file(repo, file_path, commit_message, text, branch = repo.head)
- oid = repo.write(text, :blob)
- index = repo.index
- index.read_tree(branch.target.tree)
- index.add(path: file_path, oid: oid, mode: 0100644)
- options = commit_options(repo, index, branch.target, branch.canonical_name, commit_message)
- sha = Rugged::Commit.create(repo, options)
- repo.lookup(sha)
- end
-
- # Writes a new commit to the repo and returns a Rugged::Commit. Replaces the
- # contents of encoding/CHANGELOG with new text.
- def new_commit_edit_new_file_on_branch(repo, file_path, branch_name, commit_message, text)
- branch = repo.branches[branch_name]
- new_commit_edit_new_file(repo, file_path, commit_message, text, branch)
- end
-
- # Writes a new commit to the repo and returns a Rugged::Commit. Moves the
- # CHANGELOG file to the encoding/ directory.
- def new_commit_move_file(repo)
- blob_oid = repo.head.target.tree.detect { |i| i[:name] == "CHANGELOG" }[:oid]
- file_content = repo.lookup(blob_oid).content
- oid = repo.write(file_content, :blob)
- index = repo.index
- index.read_tree(repo.head.target.tree)
- index.add(path: "encoding/CHANGELOG", oid: oid, mode: 0100644)
- index.remove("CHANGELOG")
-
- options = commit_options(repo, index, repo.head.target, "HEAD", "Move CHANGELOG to encoding/")
-
- sha = Rugged::Commit.create(repo, options)
- repo.lookup(sha)
- end
-
def refs(dir)
IO.popen(%W[git -C #{dir} for-each-ref], &:read).split("\n").map do |line|
line.split("\t").last
end
end
+
+ describe '#disconnect_alternates' do
+ let(:project) { create(:project, :repository) }
+ let(:pool_repository) { create(:pool_repository) }
+ let(:repository) { project.repository }
+ let(:repository_path) { File.join(TestEnv.repos_path, repository.relative_path) }
+ let(:object_pool) { pool_repository.object_pool }
+ let(:object_pool_path) { File.join(TestEnv.repos_path, object_pool.repository.relative_path) }
+ let(:object_pool_rugged) { Rugged::Repository.new(object_pool_path) }
+
+ before do
+ object_pool.create
+ end
+
+ it 'does not raise an error when disconnecting a non-linked repository' do
+ expect { repository.disconnect_alternates }.not_to raise_error
+ end
+
+ it 'removes the alternates file' do
+ object_pool.link(repository)
+
+ alternates_file = File.join(repository_path, "objects", "info", "alternates")
+ expect(File.exist?(alternates_file)).to be_truthy
+
+ repository.disconnect_alternates
+
+ expect(File.exist?(alternates_file)).to be_falsey
+ end
+
+ it 'can still access objects in the object pool' do
+ object_pool.link(repository)
+ new_commit = new_commit_edit_old_file(object_pool_rugged)
+ expect(repository.commit(new_commit.oid).id).to eq(new_commit.oid)
+
+ repository.disconnect_alternates
+
+ expect(repository.commit(new_commit.oid).id).to eq(new_commit.oid)
+ end
+ end
end
diff --git a/spec/lib/gitlab/git/tree_spec.rb b/spec/lib/gitlab/git/tree_spec.rb
index 7ad3cde97f8..7e169cfe270 100644
--- a/spec/lib/gitlab/git/tree_spec.rb
+++ b/spec/lib/gitlab/git/tree_spec.rb
@@ -19,7 +19,9 @@ describe Gitlab::Git::Tree, :seed_helper do
it 'returns a list of tree objects' do
entries = described_class.where(repository, SeedRepo::Commit::ID, 'files', true)
- expect(entries.count).to be >= 5
+ expect(entries.map(&:path)).to include('files/html',
+ 'files/markdown/ruby-style-guide.md')
+ expect(entries.count).to be >= 10
expect(entries).to all(be_a(Gitlab::Git::Tree))
end
diff --git a/spec/lib/gitlab/git/wiki_spec.rb b/spec/lib/gitlab/git/wiki_spec.rb
index ded5d7576df..1e577392949 100644
--- a/spec/lib/gitlab/git/wiki_spec.rb
+++ b/spec/lib/gitlab/git/wiki_spec.rb
@@ -21,13 +21,13 @@ describe Gitlab::Git::Wiki do
end
it 'returns all the pages' do
- expect(subject.pages.count).to eq(2)
- expect(subject.pages.first.title).to eq 'page1'
- expect(subject.pages.last.title).to eq 'page2'
+ expect(subject.list_pages.count).to eq(2)
+ expect(subject.list_pages.first.title).to eq 'page1'
+ expect(subject.list_pages.last.title).to eq 'page2'
end
it 'returns only one page' do
- pages = subject.pages(limit: 1)
+ pages = subject.list_pages(limit: 1)
expect(pages.count).to eq(1)
expect(pages.first.title).to eq 'page1'
@@ -62,8 +62,8 @@ describe Gitlab::Git::Wiki do
subject.delete_page('*', commit_details('whatever'))
- expect(subject.pages.count).to eq 1
- expect(subject.pages.first.title).to eq 'page1'
+ expect(subject.list_pages.count).to eq 1
+ expect(subject.list_pages.first.title).to eq 'page1'
end
end
@@ -87,7 +87,7 @@ describe Gitlab::Git::Wiki do
with_them do
subject { wiki.preview_slug(title, format) }
- let(:gitaly_slug) { wiki.pages.first }
+ let(:gitaly_slug) { wiki.list_pages.first }
it { is_expected.to eq(expected_slug) }
@@ -96,7 +96,7 @@ describe Gitlab::Git::Wiki do
create_page(title, 'content', format: format)
- gitaly_slug = wiki.pages.first.url_path
+ gitaly_slug = wiki.list_pages.first.url_path
is_expected.to eq(gitaly_slug)
end
diff --git a/spec/lib/gitlab/git_ref_validator_spec.rb b/spec/lib/gitlab/git_ref_validator_spec.rb
index 3ab04a1c46d..b63389af29f 100644
--- a/spec/lib/gitlab/git_ref_validator_spec.rb
+++ b/spec/lib/gitlab/git_ref_validator_spec.rb
@@ -1,31 +1,69 @@
require 'spec_helper'
describe Gitlab::GitRefValidator do
- it { expect(described_class.validate('feature/new')).to be_truthy }
- it { expect(described_class.validate('implement_@all')).to be_truthy }
- it { expect(described_class.validate('my_new_feature')).to be_truthy }
- it { expect(described_class.validate('my-branch')).to be_truthy }
- it { expect(described_class.validate('#1')).to be_truthy }
- it { expect(described_class.validate('feature/refs/heads/foo')).to be_truthy }
- it { expect(described_class.validate('feature/~new/')).to be_falsey }
- it { expect(described_class.validate('feature/^new/')).to be_falsey }
- it { expect(described_class.validate('feature/:new/')).to be_falsey }
- it { expect(described_class.validate('feature/?new/')).to be_falsey }
- it { expect(described_class.validate('feature/*new/')).to be_falsey }
- it { expect(described_class.validate('feature/[new/')).to be_falsey }
- it { expect(described_class.validate('feature/new/')).to be_falsey }
- it { expect(described_class.validate('feature/new.')).to be_falsey }
- it { expect(described_class.validate('feature\@{')).to be_falsey }
- it { expect(described_class.validate('feature\new')).to be_falsey }
- it { expect(described_class.validate('feature//new')).to be_falsey }
- it { expect(described_class.validate('feature new')).to be_falsey }
- it { expect(described_class.validate('refs/heads/')).to be_falsey }
- it { expect(described_class.validate('refs/remotes/')).to be_falsey }
- it { expect(described_class.validate('refs/heads/feature')).to be_falsey }
- it { expect(described_class.validate('refs/remotes/origin')).to be_falsey }
- it { expect(described_class.validate('-')).to be_falsey }
- it { expect(described_class.validate('-branch')).to be_falsey }
- it { expect(described_class.validate('.tag')).to be_falsey }
- it { expect(described_class.validate('my branch')).to be_falsey }
- it { expect(described_class.validate("\xA0\u0000\xB0")).to be_falsey }
+ using RSpec::Parameterized::TableSyntax
+
+ context '.validate' do
+ it { expect(described_class.validate('feature/new')).to be true }
+ it { expect(described_class.validate('implement_@all')).to be true }
+ it { expect(described_class.validate('my_new_feature')).to be true }
+ it { expect(described_class.validate('my-branch')).to be true }
+ it { expect(described_class.validate('#1')).to be true }
+ it { expect(described_class.validate('feature/refs/heads/foo')).to be true }
+ it { expect(described_class.validate('feature/~new/')).to be false }
+ it { expect(described_class.validate('feature/^new/')).to be false }
+ it { expect(described_class.validate('feature/:new/')).to be false }
+ it { expect(described_class.validate('feature/?new/')).to be false }
+ it { expect(described_class.validate('feature/*new/')).to be false }
+ it { expect(described_class.validate('feature/[new/')).to be false }
+ it { expect(described_class.validate('feature/new/')).to be false }
+ it { expect(described_class.validate('feature/new.')).to be false }
+ it { expect(described_class.validate('feature\@{')).to be false }
+ it { expect(described_class.validate('feature\new')).to be false }
+ it { expect(described_class.validate('feature//new')).to be false }
+ it { expect(described_class.validate('feature new')).to be false }
+ it { expect(described_class.validate('refs/heads/')).to be false }
+ it { expect(described_class.validate('refs/remotes/')).to be false }
+ it { expect(described_class.validate('refs/heads/feature')).to be false }
+ it { expect(described_class.validate('refs/remotes/origin')).to be false }
+ it { expect(described_class.validate('-')).to be false }
+ it { expect(described_class.validate('-branch')).to be false }
+ it { expect(described_class.validate('+foo:bar')).to be false }
+ it { expect(described_class.validate('foo:bar')).to be false }
+ it { expect(described_class.validate('.tag')).to be false }
+ it { expect(described_class.validate('my branch')).to be false }
+ it { expect(described_class.validate("\xA0\u0000\xB0")).to be false }
+ end
+
+ context '.validate_merge_request_branch' do
+ it { expect(described_class.validate_merge_request_branch('HEAD')).to be true }
+ it { expect(described_class.validate_merge_request_branch('feature/new')).to be true }
+ it { expect(described_class.validate_merge_request_branch('implement_@all')).to be true }
+ it { expect(described_class.validate_merge_request_branch('my_new_feature')).to be true }
+ it { expect(described_class.validate_merge_request_branch('my-branch')).to be true }
+ it { expect(described_class.validate_merge_request_branch('#1')).to be true }
+ it { expect(described_class.validate_merge_request_branch('feature/refs/heads/foo')).to be true }
+ it { expect(described_class.validate_merge_request_branch('feature/~new/')).to be false }
+ it { expect(described_class.validate_merge_request_branch('feature/^new/')).to be false }
+ it { expect(described_class.validate_merge_request_branch('feature/:new/')).to be false }
+ it { expect(described_class.validate_merge_request_branch('feature/?new/')).to be false }
+ it { expect(described_class.validate_merge_request_branch('feature/*new/')).to be false }
+ it { expect(described_class.validate_merge_request_branch('feature/[new/')).to be false }
+ it { expect(described_class.validate_merge_request_branch('feature/new/')).to be false }
+ it { expect(described_class.validate_merge_request_branch('feature/new.')).to be false }
+ it { expect(described_class.validate_merge_request_branch('feature\@{')).to be false }
+ it { expect(described_class.validate_merge_request_branch('feature\new')).to be false }
+ it { expect(described_class.validate_merge_request_branch('feature//new')).to be false }
+ it { expect(described_class.validate_merge_request_branch('feature new')).to be false }
+ it { expect(described_class.validate_merge_request_branch('refs/heads/master')).to be true }
+ it { expect(described_class.validate_merge_request_branch('refs/heads/')).to be false }
+ it { expect(described_class.validate_merge_request_branch('refs/remotes/')).to be false }
+ it { expect(described_class.validate_merge_request_branch('-')).to be false }
+ it { expect(described_class.validate_merge_request_branch('-branch')).to be false }
+ it { expect(described_class.validate_merge_request_branch('+foo:bar')).to be false }
+ it { expect(described_class.validate_merge_request_branch('foo:bar')).to be false }
+ it { expect(described_class.validate_merge_request_branch('.tag')).to be false }
+ it { expect(described_class.validate_merge_request_branch('my branch')).to be false }
+ it { expect(described_class.validate_merge_request_branch("\xA0\u0000\xB0")).to be false }
+ end
end
diff --git a/spec/lib/gitlab/gitaly_client/cleanup_service_spec.rb b/spec/lib/gitlab/gitaly_client/cleanup_service_spec.rb
index 369deff732a..c42332dc27b 100644
--- a/spec/lib/gitlab/gitaly_client/cleanup_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/cleanup_service_spec.rb
@@ -6,14 +6,14 @@ describe Gitlab::GitalyClient::CleanupService do
let(:relative_path) { project.disk_path + '.git' }
let(:client) { described_class.new(project.repository) }
- describe '#apply_bfg_object_map' do
- it 'sends an apply_bfg_object_map message' do
+ describe '#apply_bfg_object_map_stream' do
+ it 'sends an apply_bfg_object_map_stream message' do
expect_any_instance_of(Gitaly::CleanupService::Stub)
- .to receive(:apply_bfg_object_map)
+ .to receive(:apply_bfg_object_map_stream)
.with(kind_of(Enumerator), kind_of(Hash))
- .and_return(double)
+ .and_return([])
- client.apply_bfg_object_map(StringIO.new)
+ client.apply_bfg_object_map_stream(StringIO.new)
end
end
end
diff --git a/spec/lib/gitlab/gitaly_client/conflicts_service_spec.rb b/spec/lib/gitlab/gitaly_client/conflicts_service_spec.rb
index e4fe01a671f..52630ba0223 100644
--- a/spec/lib/gitlab/gitaly_client/conflicts_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/conflicts_service_spec.rb
@@ -35,7 +35,7 @@ describe Gitlab::GitalyClient::ConflictsService do
end
let(:source_branch) { 'master' }
let(:target_branch) { 'feature' }
- let(:commit_message) { 'Solving conflicts' }
+ let(:commit_message) { 'Solving conflicts\n\nTést' }
let(:resolution) do
Gitlab::Git::Conflict::Resolution.new(user, files, commit_message)
end
@@ -51,6 +51,25 @@ describe Gitlab::GitalyClient::ConflictsService do
subject
end
+ context 'with branches with UTF-8 characters' do
+ let(:source_branch) { 'testòbranch' }
+ let(:target_branch) { 'ábranch' }
+
+ it 'handles commit messages with UTF-8 characters' do
+ allow(::Gitlab::GitalyClient).to receive(:call).and_call_original
+ expect(::Gitlab::GitalyClient).to receive(:call).with(anything, :conflicts_service, :resolve_conflicts, any_args) do |*args|
+ # Force the generation of request messages by iterating through the enumerator
+ message = args[3].to_a.first
+ params = [message.header.commit_message, message.header.source_branch, message.header.target_branch]
+ expect(params.map(&:encoding).uniq).to eq([Encoding::ASCII_8BIT])
+
+ double(resolution_error: nil)
+ end
+
+ subject
+ end
+ end
+
it 'raises a relevant exception if resolution_error is present' do
expect_any_instance_of(Gitaly::ConflictsService::Stub).to receive(:resolve_conflicts)
.with(kind_of(Enumerator), kind_of(Hash)).and_return(double(resolution_error: "something happened"))
diff --git a/spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb b/spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb
index 149b7ec5bb0..0e0c3d329b5 100644
--- a/spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb
@@ -43,4 +43,24 @@ describe Gitlab::GitalyClient::ObjectPoolService do
end
end
end
+
+ describe '#fetch' do
+ before do
+ subject.delete
+ end
+
+ it 'restores the pool repository objects' do
+ subject.fetch(project.repository)
+
+ expect(object_pool.repository.exists?).to be(true)
+ end
+
+ context 'when called twice' do
+ it "doesn't raise an error" do
+ subject.delete
+
+ expect { subject.fetch(project.repository) }.not_to raise_error
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
index 7579a6577b9..18663a72fcd 100644
--- a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
@@ -78,6 +78,24 @@ describe Gitlab::GitalyClient::OperationService do
subject
end
+ describe '#user_merge_to_ref' do
+ let(:branch) { 'my-branch' }
+ let(:source_sha) { 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660' }
+ let(:ref) { 'refs/merge-requests/x/merge' }
+ let(:message) { 'validación' }
+ let(:response) { Gitaly::UserMergeToRefResponse.new(commit_id: 'new-commit-id') }
+
+ subject { client.user_merge_to_ref(user, source_sha, branch, ref, message) }
+
+ it 'sends a user_merge_to_ref message' do
+ expect_any_instance_of(Gitaly::OperationService::Stub)
+ .to receive(:user_merge_to_ref).with(kind_of(Gitaly::UserMergeToRefRequest), kind_of(Hash))
+ .and_return(response)
+
+ subject
+ end
+ end
+
context "when pre_receive_error is present" do
let(:response) do
Gitaly::UserUpdateBranchResponse.new(pre_receive_error: "GitLab: something failed")
diff --git a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
index 0dab39575b9..0bb6e582159 100644
--- a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
@@ -165,4 +165,15 @@ describe Gitlab::GitalyClient::RefService do
client.delete_refs(except_with_prefixes: prefixes)
end
end
+
+ describe '#pack_refs' do
+ it 'sends a pack_refs message' do
+ expect_any_instance_of(Gitaly::RefService::Stub)
+ .to receive(:pack_refs)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
+ .and_return(double(:pack_refs_response))
+
+ client.pack_refs
+ end
+ end
end
diff --git a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
index 46ca2340389..a3808adb376 100644
--- a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
@@ -73,6 +73,17 @@ describe Gitlab::GitalyClient::RepositoryService do
end
end
+ describe '#get_object_directory_size' do
+ it 'sends a get_object_directory_size message' do
+ expect_any_instance_of(Gitaly::RepositoryService::Stub)
+ .to receive(:get_object_directory_size)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
+ .and_return(size: 0)
+
+ client.get_object_directory_size
+ end
+ end
+
describe '#apply_gitattributes' do
let(:revision) { 'master' }
@@ -231,4 +242,34 @@ describe Gitlab::GitalyClient::RepositoryService do
client.raw_changes_between('deadbeef', 'deadpork')
end
end
+
+ describe '#disconnect_alternates' do
+ let(:project) { create(:project, :repository) }
+ let(:repository) { project.repository }
+ let(:repository_path) { File.join(TestEnv.repos_path, repository.relative_path) }
+ let(:pool_repository) { create(:pool_repository) }
+ let(:object_pool) { pool_repository.object_pool }
+ let(:object_pool_service) { Gitlab::GitalyClient::ObjectPoolService.new(object_pool) }
+
+ before do
+ object_pool_service.create(repository)
+ object_pool_service.link_repository(repository)
+ end
+
+ it 'deletes the alternates file' do
+ repository.disconnect_alternates
+
+ alternates_file = File.join(repository_path, "objects", "info", "alternates")
+
+ expect(File.exist?(alternates_file)).to be_falsey
+ end
+
+ context 'when called twice' do
+ it "doesn't raise an error" do
+ repository.disconnect_alternates
+
+ expect { repository.disconnect_alternates }.not_to raise_error
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/gitaly_client/wiki_service_spec.rb b/spec/lib/gitlab/gitaly_client/wiki_service_spec.rb
index d82c9c28da0..4fa8e97aca0 100644
--- a/spec/lib/gitlab/gitaly_client/wiki_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/wiki_service_spec.rb
@@ -46,7 +46,7 @@ describe Gitlab::GitalyClient::WikiService do
end
end
- describe '#get_all_pages' do
+ describe '#load_all_pages' do
let(:page_2_info) { { title: 'My Page 2', raw_data: 'c', version: page_version } }
let(:response) do
[
@@ -63,7 +63,7 @@ describe Gitlab::GitalyClient::WikiService do
let(:wiki_page_2) { subject[1].first }
let(:wiki_page_2_version) { subject[1].last }
- subject { client.get_all_pages }
+ subject { client.load_all_pages }
it 'sends a wiki_get_all_pages message' do
expect_any_instance_of(Gitaly::WikiService::Stub)
@@ -99,7 +99,7 @@ describe Gitlab::GitalyClient::WikiService do
end
context 'with limits' do
- subject { client.get_all_pages(limit: 1) }
+ subject { client.load_all_pages(limit: 1) }
it 'sends a request with the limit' do
expect_any_instance_of(Gitaly::WikiService::Stub)
diff --git a/spec/lib/gitlab/gitaly_client_spec.rb b/spec/lib/gitlab/gitaly_client_spec.rb
index f1acb1d9bc4..da1eb0c2618 100644
--- a/spec/lib/gitlab/gitaly_client_spec.rb
+++ b/spec/lib/gitlab/gitaly_client_spec.rb
@@ -142,6 +142,48 @@ describe Gitlab::GitalyClient do
end
end
+ describe '.request_kwargs' do
+ context 'when catfile-cache feature is enabled' do
+ before do
+ stub_feature_flags('gitaly_catfile-cache': true)
+ end
+
+ it 'sets the gitaly-session-id in the metadata' do
+ results = described_class.request_kwargs('default', nil)
+ expect(results[:metadata]).to include('gitaly-session-id')
+ end
+
+ context 'when RequestStore is not enabled' do
+ it 'sets a different gitaly-session-id per request' do
+ gitaly_session_id = described_class.request_kwargs('default', nil)[:metadata]['gitaly-session-id']
+
+ expect(described_class.request_kwargs('default', nil)[:metadata]['gitaly-session-id']).not_to eq(gitaly_session_id)
+ end
+ end
+
+ context 'when RequestStore is enabled', :request_store do
+ it 'sets the same gitaly-session-id on every outgoing request metadata' do
+ gitaly_session_id = described_class.request_kwargs('default', nil)[:metadata]['gitaly-session-id']
+
+ 3.times do
+ expect(described_class.request_kwargs('default', nil)[:metadata]['gitaly-session-id']).to eq(gitaly_session_id)
+ end
+ end
+ end
+ end
+
+ context 'when catfile-cache feature is disabled' do
+ before do
+ stub_feature_flags({ 'gitaly_catfile-cache': false })
+ end
+
+ it 'does not set the gitaly-session-id in the metadata' do
+ results = described_class.request_kwargs('default', nil)
+ expect(results[:metadata]).not_to include('gitaly-session-id')
+ end
+ end
+ end
+
describe 'enforce_gitaly_request_limits?' do
def call_gitaly(count = 1)
(1..count).each do
diff --git a/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb b/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb
index 7901ae005d9..dab5767ece1 100644
--- a/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb
@@ -98,6 +98,7 @@ describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_cach
description: 'This is my issue',
milestone_id: milestone.id,
state: :opened,
+ state_id: 1,
created_at: created_at,
updated_at: updated_at
},
@@ -127,6 +128,7 @@ describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_cach
description: "*Created by: alice*\n\nThis is my issue",
milestone_id: milestone.id,
state: :opened,
+ state_id: 1,
created_at: created_at,
updated_at: updated_at
},
diff --git a/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb
index 2e4a7c36fb8..6d614c6527a 100644
--- a/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb
@@ -93,6 +93,7 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi
source_branch: 'github/fork/alice/feature',
target_branch: 'master',
state: :merged,
+ state_id: 3,
milestone_id: milestone.id,
author_id: user.id,
assignee_id: user.id,
@@ -138,6 +139,7 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi
source_branch: 'github/fork/alice/feature',
target_branch: 'master',
state: :merged,
+ state_id: 3,
milestone_id: milestone.id,
author_id: project.creator_id,
assignee_id: user.id,
@@ -184,6 +186,7 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi
source_branch: 'master-42',
target_branch: 'master',
state: :merged,
+ state_id: 3,
milestone_id: milestone.id,
author_id: user.id,
assignee_id: user.id,
diff --git a/spec/lib/gitlab/github_import/parallel_importer_spec.rb b/spec/lib/gitlab/github_import/parallel_importer_spec.rb
index f5df38c9aaf..ecab64a372a 100644
--- a/spec/lib/gitlab/github_import/parallel_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/parallel_importer_spec.rb
@@ -25,18 +25,9 @@ describe Gitlab::GithubImport::ParallelImporter do
end
it 'sets the JID in Redis' do
- expect(Gitlab::SidekiqStatus)
- .to receive(:set)
- .with("github-importer/#{project.id}", StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION)
- .and_call_original
+ expect(Gitlab::Import::SetAsyncJid).to receive(:set_jid).with(project).and_call_original
importer.execute
end
-
- it 'updates the import JID of the project' do
- importer.execute
-
- expect(project.import_state.reload.jid).to eq("github-importer/#{project.id}")
- end
end
end
diff --git a/spec/lib/gitlab/graphql/authorize/authorize_field_service_spec.rb b/spec/lib/gitlab/graphql/authorize/authorize_field_service_spec.rb
index 6114aca0616..aec9c4baf0a 100644
--- a/spec/lib/gitlab/graphql/authorize/authorize_field_service_spec.rb
+++ b/spec/lib/gitlab/graphql/authorize/authorize_field_service_spec.rb
@@ -5,92 +5,118 @@ require 'spec_helper'
# Also see spec/graphql/features/authorization_spec.rb for
# integration tests of AuthorizeFieldService
describe Gitlab::Graphql::Authorize::AuthorizeFieldService do
- describe '#build_checker' do
- let(:current_user) { double(:current_user) }
- let(:abilities) { [double(:first_ability), double(:last_ability)] }
-
- context 'when authorizing against the object' do
- let(:checker) do
- service = described_class.new(double(resolve_proc: proc {}))
- allow(service).to receive(:authorizations).and_return(abilities)
- service.__send__(:build_checker, current_user, nil)
- end
+ def type(type_authorizations = [])
+ Class.new(Types::BaseObject) do
+ graphql_name "TestType"
- it 'returns a checker which checks for a single object' do
- object = double(:object)
+ authorize type_authorizations
+ end
+ end
- abilities.each do |ability|
- spy_ability_check_for(ability, object, passed: true)
- end
+ def type_with_field(field_type, field_authorizations = [], resolved_value = "Resolved value")
+ Class.new(Types::BaseObject) do
+ graphql_name "TestTypeWithField"
+ field :test_field, field_type, null: true, authorize: field_authorizations, resolve: -> (_, _, _) { resolved_value}
+ end
+ end
- expect(checker.call(object)).to eq(object)
- end
+ let(:current_user) { double(:current_user) }
+ subject(:service) { described_class.new(field) }
- it 'returns a checker which checks for all objects' do
- objects = [double(:first), double(:last)]
+ describe "#authorized_resolve" do
+ let(:presented_object) { double("presented object") }
+ let(:presented_type) { double("parent type", object: presented_object) }
+ subject(:resolved) { service.authorized_resolve.call(presented_type, {}, { current_user: current_user }) }
- abilities.each do |ability|
- objects.each do |object|
- spy_ability_check_for(ability, object, passed: true)
+ context "scalar types" do
+ shared_examples "checking permissions on the presented object" do
+ it "checks the abilities on the object being presented and returns the value" do
+ expected_permissions.each do |permission|
+ spy_ability_check_for(permission, presented_object, passed: true)
end
+
+ expect(resolved).to eq("Resolved value")
end
- expect(checker.call(objects)).to eq(objects)
+ it "returns nil if the value wasn't authorized" do
+ allow(Ability).to receive(:allowed?).and_return false
+
+ expect(resolved).to be_nil
+ end
end
- context 'when some objects would not pass the check' do
- it 'returns nil when it is single object' do
- disallowed = double(:object)
+ context "when the field is a built-in scalar type" do
+ let(:field) { type_with_field(GraphQL::STRING_TYPE, :read_field).fields["testField"].to_graphql }
+ let(:expected_permissions) { [:read_field] }
- spy_ability_check_for(abilities.first, disallowed, passed: false)
+ it_behaves_like "checking permissions on the presented object"
+ end
- expect(checker.call(disallowed)).to be_nil
- end
+ context "when the field is a list of scalar types" do
+ let(:field) { type_with_field([GraphQL::STRING_TYPE], :read_field).fields["testField"].to_graphql }
+ let(:expected_permissions) { [:read_field] }
+
+ it_behaves_like "checking permissions on the presented object"
+ end
- it 'returns only objects which passed when there are more than one' do
- allowed = double(:allowed)
- disallowed = double(:disallowed)
+ context "when the field is sub-classed scalar type" do
+ let(:field) { type_with_field(Types::TimeType, :read_field).fields["testField"].to_graphql }
+ let(:expected_permissions) { [:read_field] }
- spy_ability_check_for(abilities.first, disallowed, passed: false)
+ it_behaves_like "checking permissions on the presented object"
+ end
- abilities.each do |ability|
- spy_ability_check_for(ability, allowed, passed: true)
- end
+ context "when the field is a list of sub-classed scalar types" do
+ let(:field) { type_with_field([Types::TimeType], :read_field).fields["testField"].to_graphql }
+ let(:expected_permissions) { [:read_field] }
- expect(checker.call([disallowed, allowed])).to contain_exactly(allowed)
- end
+ it_behaves_like "checking permissions on the presented object"
end
end
- context 'when authorizing against another object' do
- let(:authorizing_obj) { double(:object) }
+ context "when the field is a specific type" do
+ let(:custom_type) { type(:read_type) }
+ let(:object_in_field) { double("presented in field") }
+ let(:field) { type_with_field(custom_type, :read_field, object_in_field).fields["testField"].to_graphql }
- let(:checker) do
- service = described_class.new(double(resolve_proc: proc {}))
- allow(service).to receive(:authorizations).and_return(abilities)
- service.__send__(:build_checker, current_user, authorizing_obj)
- end
+ it "checks both field & type permissions" do
+ spy_ability_check_for(:read_field, object_in_field, passed: true)
+ spy_ability_check_for(:read_type, object_in_field, passed: true)
- it 'returns a checker which checks for a single object' do
- object = double(:object)
+ expect(resolved).to eq(object_in_field)
+ end
- abilities.each do |ability|
- spy_ability_check_for(ability, authorizing_obj, passed: true)
- end
+ it "returns nil if viewing was not allowed" do
+ spy_ability_check_for(:read_field, object_in_field, passed: false)
+ spy_ability_check_for(:read_type, object_in_field, passed: true)
- expect(checker.call(object)).to eq(object)
+ expect(resolved).to be_nil
end
- it 'returns a checker which checks for all objects' do
- objects = [double(:first), double(:last)]
+ context "when the field is a list" do
+ let(:object_1) { double("presented in field 1") }
+ let(:object_2) { double("presented in field 2") }
+ let(:presented_types) { [double(object: object_1), double(object: object_2)] }
+ let(:field) { type_with_field([custom_type], :read_field, presented_types).fields["testField"].to_graphql }
- abilities.each do |ability|
- objects.each do |object|
- spy_ability_check_for(ability, authorizing_obj, passed: true)
- end
+ it "checks all permissions" do
+ allow(Ability).to receive(:allowed?) { true }
+
+ spy_ability_check_for(:read_field, object_1, passed: true)
+ spy_ability_check_for(:read_type, object_1, passed: true)
+ spy_ability_check_for(:read_field, object_2, passed: true)
+ spy_ability_check_for(:read_type, object_2, passed: true)
+
+ expect(resolved).to eq(presented_types)
end
- expect(checker.call(objects)).to eq(objects)
+ it "filters out objects that the user cannot see" do
+ allow(Ability).to receive(:allowed?) { true }
+
+ spy_ability_check_for(:read_type, object_1, passed: false)
+
+ expect(resolved.map(&:object)).to contain_exactly(object_2)
+ end
end
end
end
diff --git a/spec/lib/gitlab/graphql/connections/keyset_connection_spec.rb b/spec/lib/gitlab/graphql/connections/keyset_connection_spec.rb
index 9bcc1e78a78..fefa2881b18 100644
--- a/spec/lib/gitlab/graphql/connections/keyset_connection_spec.rb
+++ b/spec/lib/gitlab/graphql/connections/keyset_connection_spec.rb
@@ -85,6 +85,11 @@ describe Gitlab::Graphql::Connections::KeysetConnection do
expect(subject.paged_nodes.size).to eq(3)
end
+ it 'is a loaded memoized array' do
+ expect(subject.paged_nodes).to be_an(Array)
+ expect(subject.paged_nodes.object_id).to eq(subject.paged_nodes.object_id)
+ end
+
context 'when `first` is passed' do
let(:arguments) { { first: 2 } }
diff --git a/spec/lib/gitlab/graphql/generic_tracing_spec.rb b/spec/lib/gitlab/graphql/generic_tracing_spec.rb
new file mode 100644
index 00000000000..ae92dcc40af
--- /dev/null
+++ b/spec/lib/gitlab/graphql/generic_tracing_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Graphql::GenericTracing do
+ let(:graphql_duration_seconds_histogram) { double('Gitlab::Metrics::NullMetric') }
+
+ it 'updates graphql histogram with expected labels' do
+ query = 'query { users { id } }'
+ tracer = described_class.new
+
+ allow(tracer)
+ .to receive(:graphql_duration_seconds)
+ .and_return(graphql_duration_seconds_histogram)
+
+ expect_metric('graphql.lex', 'lex')
+ expect_metric('graphql.parse', 'parse')
+ expect_metric('graphql.validate', 'validate')
+ expect_metric('graphql.analyze', 'analyze_multiplex')
+ expect_metric('graphql.execute', 'execute_query_lazy')
+ expect_metric('graphql.execute', 'execute_multiplex')
+
+ GitlabSchema.execute(query, context: { tracers: [tracer] })
+ end
+
+ context "when labkit tracing is enabled" do
+ before do
+ expect(Labkit::Tracing).to receive(:enabled?).and_return(true)
+ end
+
+ it 'yields with labkit tracing' do
+ expected_tags = {
+ 'component' => 'web',
+ 'span.kind' => 'server',
+ 'platform_key' => 'pkey',
+ 'key' => 'key'
+ }
+
+ expect(Labkit::Tracing)
+ .to receive(:with_tracing)
+ .with(operation_name: "pkey.key", tags: expected_tags)
+ .and_yield
+
+ expect { |b| described_class.new.platform_trace('pkey', 'key', nil, &b) }.to yield_control
+ end
+ end
+
+ context "when labkit tracing is disabled" do
+ before do
+ expect(Labkit::Tracing).to receive(:enabled?).and_return(false)
+ end
+
+ it 'yields without measurement' do
+ expect(Labkit::Tracing).not_to receive(:with_tracing)
+
+ expect { |b| described_class.new.platform_trace('pkey', 'key', nil, &b) }.to yield_control
+ end
+ end
+
+ private
+
+ def expect_metric(platform_key, key)
+ expect(graphql_duration_seconds_histogram)
+ .to receive(:observe)
+ .with({ platform_key: platform_key, key: key }, be > 0.0)
+ end
+end
diff --git a/spec/lib/gitlab/graphql/loaders/batch_lfs_oid_loader_spec.rb b/spec/lib/gitlab/graphql/loaders/batch_lfs_oid_loader_spec.rb
new file mode 100644
index 00000000000..46dd1777285
--- /dev/null
+++ b/spec/lib/gitlab/graphql/loaders/batch_lfs_oid_loader_spec.rb
@@ -0,0 +1,23 @@
+require 'spec_helper'
+
+describe Gitlab::Graphql::Loaders::BatchLfsOidLoader do
+ include GraphqlHelpers
+
+ set(:project) { create(:project, :repository) }
+ let(:repository) { project.repository }
+ let(:blob) { Gitlab::Graphql::Representation::TreeEntry.new(repository.blob_at('master', 'files/lfs/lfs_object.iso'), repository) }
+ let(:otherblob) { Gitlab::Graphql::Representation::TreeEntry.new(repository.blob_at('master', 'README'), repository) }
+
+ describe '#find' do
+ it 'batch-resolves LFS blob IDs' do
+ expect(Gitlab::Git::Blob).to receive(:batch_lfs_pointers).once.and_call_original
+
+ result = batch do
+ [blob, otherblob].map { |b| described_class.new(repository, b.id).find }
+ end
+
+ expect(result.first).to eq(blob.lfs_oid)
+ expect(result.last).to eq(nil)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/loaders/batch_project_statistics_loader_spec.rb b/spec/lib/gitlab/graphql/loaders/batch_project_statistics_loader_spec.rb
new file mode 100644
index 00000000000..ec2fcad31e5
--- /dev/null
+++ b/spec/lib/gitlab/graphql/loaders/batch_project_statistics_loader_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Graphql::Loaders::BatchProjectStatisticsLoader do
+ describe '#find' do
+ it 'only queries once for project statistics' do
+ stats = create_list(:project_statistics, 2)
+ project1 = stats.first.project
+ project2 = stats.last.project
+
+ expect do
+ described_class.new(project1.id).find
+ described_class.new(project2.id).find
+ end.not_to exceed_query_limit(1)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/query_analyzers/logger_analyzer_spec.rb b/spec/lib/gitlab/graphql/query_analyzers/logger_analyzer_spec.rb
new file mode 100644
index 00000000000..66033736e01
--- /dev/null
+++ b/spec/lib/gitlab/graphql/query_analyzers/logger_analyzer_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Graphql::QueryAnalyzers::LoggerAnalyzer do
+ subject { described_class.new }
+
+ describe '#analyze?' do
+ context 'feature flag disabled' do
+ before do
+ stub_feature_flags(graphql_logging: false)
+ end
+
+ it 'disables the analyzer' do
+ expect(subject.analyze?(anything)).to be_falsey
+ end
+ end
+
+ context 'feature flag enabled by default' do
+ it 'enables the analyzer' do
+ expect(subject.analyze?(anything)).to be_truthy
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/representation/tree_entry_spec.rb b/spec/lib/gitlab/graphql/representation/tree_entry_spec.rb
new file mode 100644
index 00000000000..d45e690160c
--- /dev/null
+++ b/spec/lib/gitlab/graphql/representation/tree_entry_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Graphql::Representation::TreeEntry do
+ let(:project) { create(:project, :repository) }
+ let(:repository) { project.repository }
+
+ describe '.decorate' do
+ it 'returns NilClass when given nil' do
+ expect(described_class.decorate(nil, repository)).to be_nil
+ end
+
+ it 'returns array of TreeEntry' do
+ entries = described_class.decorate(repository.tree.blobs, repository)
+
+ expect(entries.first).to be_a(described_class)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/tracing_spec.rb b/spec/lib/gitlab/graphql/tracing_spec.rb
deleted file mode 100644
index 7300a9a572e..00000000000
--- a/spec/lib/gitlab/graphql/tracing_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe Gitlab::Graphql::Tracing do
- let(:graphql_duration_seconds_histogram) { double('Gitlab::Metrics::NullMetric') }
-
- it 'updates graphql histogram with expected labels' do
- query = 'query { users { id } }'
- tracer = described_class.new
-
- allow(tracer)
- .to receive(:graphql_duration_seconds)
- .and_return(graphql_duration_seconds_histogram)
-
- expect_metric('graphql.lex', 'lex')
- expect_metric('graphql.parse', 'parse')
- expect_metric('graphql.validate', 'validate')
- expect_metric('graphql.analyze', 'analyze_multiplex')
- expect_metric('graphql.execute', 'execute_query_lazy')
- expect_metric('graphql.execute', 'execute_multiplex')
-
- GitlabSchema.execute(query, context: { tracers: [tracer] })
- end
-
- private
-
- def expect_metric(platform_key, key)
- expect(graphql_duration_seconds_histogram)
- .to receive(:observe)
- .with({ platform_key: platform_key, key: key }, be > 0.0)
- end
-end
diff --git a/spec/lib/gitlab/graphql_logger_spec.rb b/spec/lib/gitlab/graphql_logger_spec.rb
new file mode 100644
index 00000000000..4977f98b83e
--- /dev/null
+++ b/spec/lib/gitlab/graphql_logger_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::GraphqlLogger do
+ subject { described_class.new('/dev/null') }
+
+ let(:now) { Time.now }
+
+ it 'builds a logger once' do
+ expect(::Logger).to receive(:new).and_call_original
+
+ subject.info('hello world')
+ subject.error('hello again')
+ end
+
+ context 'logging a GraphQL query' do
+ let(:query) { File.read(Rails.root.join('spec/fixtures/api/graphql/introspection.graphql')) }
+
+ it 'logs a query from JSON' do
+ analyzer_memo = {
+ query_string: query,
+ variables: {},
+ complexity: 181,
+ depth: 0,
+ duration: 7
+ }
+
+ output = subject.format_message('INFO', now, 'test', analyzer_memo)
+
+ data = JSON.parse(output)
+ expect(data['severity']).to eq('INFO')
+ expect(data['time']).to eq(now.utc.iso8601(3))
+ expect(data['complexity']).to eq(181)
+ expect(data['variables']).to eq({})
+ expect(data['depth']).to eq(0)
+ expect(data['duration']).to eq(7)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/http_connection_adapter_spec.rb b/spec/lib/gitlab/http_connection_adapter_spec.rb
new file mode 100644
index 00000000000..930d1f62272
--- /dev/null
+++ b/spec/lib/gitlab/http_connection_adapter_spec.rb
@@ -0,0 +1,120 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::HTTPConnectionAdapter do
+ describe '#connection' do
+ context 'when local requests are not allowed' do
+ it 'sets up the connection' do
+ uri = URI('https://example.org')
+
+ connection = described_class.new(uri).connection
+
+ expect(connection).to be_a(Net::HTTP)
+ expect(connection.address).to eq('93.184.216.34')
+ expect(connection.hostname_override).to eq('example.org')
+ expect(connection.addr_port).to eq('example.org')
+ expect(connection.port).to eq(443)
+ end
+
+ it 'raises error when it is a request to local address' do
+ uri = URI('http://172.16.0.0/12')
+
+ expect { described_class.new(uri).connection }
+ .to raise_error(Gitlab::HTTP::BlockedUrlError,
+ "URL 'http://172.16.0.0/12' is blocked: Requests to the local network are not allowed")
+ end
+
+ it 'raises error when it is a request to localhost address' do
+ uri = URI('http://127.0.0.1')
+
+ expect { described_class.new(uri).connection }
+ .to raise_error(Gitlab::HTTP::BlockedUrlError,
+ "URL 'http://127.0.0.1' is blocked: Requests to localhost are not allowed")
+ end
+
+ context 'when port different from URL scheme is used' do
+ it 'sets up the addr_port accordingly' do
+ uri = URI('https://example.org:8080')
+
+ connection = described_class.new(uri).connection
+
+ expect(connection.address).to eq('93.184.216.34')
+ expect(connection.hostname_override).to eq('example.org')
+ expect(connection.addr_port).to eq('example.org:8080')
+ expect(connection.port).to eq(8080)
+ end
+ end
+ end
+
+ context 'when DNS rebinding protection is disabled' do
+ it 'sets up the connection' do
+ stub_application_setting(dns_rebinding_protection_enabled: false)
+
+ uri = URI('https://example.org')
+
+ connection = described_class.new(uri).connection
+
+ expect(connection).to be_a(Net::HTTP)
+ expect(connection.address).to eq('example.org')
+ expect(connection.hostname_override).to eq(nil)
+ expect(connection.addr_port).to eq('example.org')
+ expect(connection.port).to eq(443)
+ end
+ end
+
+ context 'when http(s) environment variable is set' do
+ it 'sets up the connection' do
+ stub_env('https_proxy' => 'https://my.proxy')
+
+ uri = URI('https://example.org')
+
+ connection = described_class.new(uri).connection
+
+ expect(connection).to be_a(Net::HTTP)
+ expect(connection.address).to eq('example.org')
+ expect(connection.hostname_override).to eq(nil)
+ expect(connection.addr_port).to eq('example.org')
+ expect(connection.port).to eq(443)
+ end
+ end
+
+ context 'when local requests are allowed' do
+ it 'sets up the connection' do
+ uri = URI('https://example.org')
+
+ connection = described_class.new(uri, allow_local_requests: true).connection
+
+ expect(connection).to be_a(Net::HTTP)
+ expect(connection.address).to eq('93.184.216.34')
+ expect(connection.hostname_override).to eq('example.org')
+ expect(connection.addr_port).to eq('example.org')
+ expect(connection.port).to eq(443)
+ end
+
+ it 'sets up the connection when it is a local network' do
+ uri = URI('http://172.16.0.0/12')
+
+ connection = described_class.new(uri, allow_local_requests: true).connection
+
+ expect(connection).to be_a(Net::HTTP)
+ expect(connection.address).to eq('172.16.0.0')
+ expect(connection.hostname_override).to be(nil)
+ expect(connection.addr_port).to eq('172.16.0.0')
+ expect(connection.port).to eq(80)
+ end
+
+ it 'sets up the connection when it is localhost' do
+ uri = URI('http://127.0.0.1')
+
+ connection = described_class.new(uri, allow_local_requests: true).connection
+
+ expect(connection).to be_a(Net::HTTP)
+ expect(connection.address).to eq('127.0.0.1')
+ expect(connection.hostname_override).to be(nil)
+ expect(connection.addr_port).to eq('127.0.0.1')
+ expect(connection.port).to eq(80)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/http_spec.rb b/spec/lib/gitlab/http_spec.rb
index 6c37c157f5d..158f77cab2c 100644
--- a/spec/lib/gitlab/http_spec.rb
+++ b/spec/lib/gitlab/http_spec.rb
@@ -1,6 +1,28 @@
require 'spec_helper'
describe Gitlab::HTTP do
+ include StubRequests
+
+ context 'when allow_local_requests' do
+ it 'sends the request to the correct URI' do
+ stub_full_request('https://example.org:8080', ip_address: '8.8.8.8').to_return(status: 200)
+
+ described_class.get('https://example.org:8080', allow_local_requests: false)
+
+ expect(WebMock).to have_requested(:get, 'https://8.8.8.8:8080').once
+ end
+ end
+
+ context 'when not allow_local_requests' do
+ it 'sends the request to the correct URI' do
+ stub_full_request('https://example.org:8080')
+
+ described_class.get('https://example.org:8080', allow_local_requests: true)
+
+ expect(WebMock).to have_requested(:get, 'https://8.8.8.9:8080').once
+ end
+ end
+
describe 'allow_local_requests_from_hooks_and_services is' do
before do
WebMock.stub_request(:get, /.*/).to_return(status: 200, body: 'Success')
@@ -21,6 +43,8 @@ describe Gitlab::HTTP do
context 'if allow_local_requests set to true' do
it 'override the global value and allow requests to localhost or private network' do
+ stub_full_request('http://localhost:3003')
+
expect { described_class.get('http://localhost:3003', allow_local_requests: true) }.not_to raise_error
end
end
@@ -32,6 +56,8 @@ describe Gitlab::HTTP do
end
it 'allow requests to localhost' do
+ stub_full_request('http://localhost:3003')
+
expect { described_class.get('http://localhost:3003') }.not_to raise_error
end
@@ -49,7 +75,7 @@ describe Gitlab::HTTP do
describe 'handle redirect loops' do
before do
- WebMock.stub_request(:any, "http://example.org").to_raise(HTTParty::RedirectionTooDeep.new("Redirection Too Deep"))
+ stub_full_request("http://example.org", method: :any).to_raise(HTTParty::RedirectionTooDeep.new("Redirection Too Deep"))
end
it 'handles GET requests' do
diff --git a/spec/lib/gitlab/import/set_async_jid_spec.rb b/spec/lib/gitlab/import/set_async_jid_spec.rb
new file mode 100644
index 00000000000..51397280138
--- /dev/null
+++ b/spec/lib/gitlab/import/set_async_jid_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Gitlab::Import::SetAsyncJid do
+ describe '.set_jid', :clean_gitlab_redis_shared_state do
+ let(:project) { create(:project, :import_scheduled) }
+
+ it 'sets the JID in Redis' do
+ expect(Gitlab::SidekiqStatus)
+ .to receive(:set)
+ .with("async-import/#{project.id}", StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION)
+ .and_call_original
+
+ described_class.set_jid(project)
+ end
+
+ it 'updates the import JID of the project' do
+ described_class.set_jid(project)
+
+ expect(project.import_state.reload.jid).to eq("async-import/#{project.id}")
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb b/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb
index ec17ad8541f..21a227335cd 100644
--- a/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb
+++ b/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe Gitlab::ImportExport::AfterExportStrategies::WebUploadStrategy do
+ include StubRequests
+
let(:example_url) { 'http://www.example.com' }
let(:strategy) { subject.new(url: example_url, http_method: 'post') }
let!(:project) { create(:project, :with_export) }
@@ -32,5 +34,17 @@ describe Gitlab::ImportExport::AfterExportStrategies::WebUploadStrategy do
strategy.execute(user, project)
end
+
+ context 'when upload fails' do
+ it 'stores the export error' do
+ stub_full_request(example_url, method: :post).to_return(status: [404, 'Page not found'])
+
+ strategy.execute(user, project)
+
+ errors = project.import_export_shared.errors
+ expect(errors).not_to be_empty
+ expect(errors.first).to eq "Error uploading the project. Code 404: Page not found"
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 54369ff75f4..2242543daad 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -99,7 +99,7 @@ merge_requests:
- timelogs
- head_pipeline
- latest_merge_request_diff
-- merge_request_pipelines
+- pipelines_for_merge_request
- merge_request_assignees
- suggestions
- assignees
@@ -322,6 +322,7 @@ project:
- pool_repository
- kubernetes_namespaces
- error_tracking_setting
+- metrics_setting
award_emoji:
- awardable
- user
@@ -360,3 +361,5 @@ error_tracking_setting:
- project
suggestions:
- note
+metrics_setting:
+- project
diff --git a/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb b/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb
index 536cc359d39..99669285d5b 100644
--- a/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb
+++ b/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb
@@ -18,7 +18,11 @@ describe Gitlab::ImportExport::AttributeCleaner do
'notid' => 99,
'import_source' => 'whatever',
'import_type' => 'whatever',
- 'non_existent_attr' => 'whatever'
+ 'non_existent_attr' => 'whatever',
+ 'some_html' => '<p>dodgy html</p>',
+ 'legit_html' => '<p>legit html</p>',
+ '_html' => '<p>perfectly ordinary html</p>',
+ 'cached_markdown_version' => 12345
}
end
diff --git a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb
index 87ab81d8169..ddfbb020a55 100644
--- a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb
+++ b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb
@@ -29,7 +29,7 @@ describe 'Import/Export attribute configuration' do
it 'has no new columns' do
relation_names.each do |relation_name|
relation_class = relation_class_for_name(relation_name)
- relation_attributes = relation_class.new.attributes.keys
+ relation_attributes = relation_class.new.attributes.keys - relation_class.encrypted_attributes.keys.map(&:to_s)
current_attributes = parsed_attributes(relation_name, relation_attributes)
safe_attributes = safe_model_attributes[relation_class.to_s].dup || []
diff --git a/spec/lib/gitlab/import_export/members_mapper_spec.rb b/spec/lib/gitlab/import_export/members_mapper_spec.rb
index 67e4c289906..b95b5dfe791 100644
--- a/spec/lib/gitlab/import_export/members_mapper_spec.rb
+++ b/spec/lib/gitlab/import_export/members_mapper_spec.rb
@@ -12,7 +12,6 @@ describe Gitlab::ImportExport::MembersMapper do
"access_level" => 40,
"source_id" => 14,
"source_type" => "Project",
- "user_id" => 19,
"notification_level" => 3,
"created_at" => "2016-03-11T10:21:44.822Z",
"updated_at" => "2016-03-11T10:21:44.822Z",
@@ -25,7 +24,8 @@ describe Gitlab::ImportExport::MembersMapper do
"id" => exported_user_id,
"email" => user2.email,
"username" => 'test'
- }
+ },
+ "user_id" => 19
},
{
"id" => 3,
@@ -73,6 +73,22 @@ describe Gitlab::ImportExport::MembersMapper do
expect(user2.authorized_project?(project)).to be true
end
+ it 'maps an owner as a maintainer' do
+ exported_members.first['access_level'] = ProjectMember::OWNER
+
+ expect(members_mapper.map[exported_user_id]).to eq(user2.id)
+ expect(ProjectMember.find_by_user_id(user2.id).access_level).to eq(ProjectMember::MAINTAINER)
+ end
+
+ it 'removes old user_id from member_hash to avoid conflict with user key' do
+ expect(ProjectMember).to receive(:create)
+ .twice
+ .with(hash_excluding('user_id'))
+ .and_call_original
+
+ members_mapper.map
+ end
+
context 'user is not an admin' do
let(:user) { create(:user) }
diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json
index 4a7accc4c52..6512fe80a3b 100644
--- a/spec/lib/gitlab/import_export/project.json
+++ b/spec/lib/gitlab/import_export/project.json
@@ -158,6 +158,8 @@
{
"id": 351,
"note": "Quo reprehenderit aliquam qui dicta impedit cupiditate eligendi.",
+ "note_html": "<p>something else entirely</p>",
+ "cached_markdown_version": 917504,
"noteable_type": "Issue",
"author_id": 26,
"created_at": "2016-06-14T15:02:47.770Z",
@@ -2363,6 +2365,8 @@
{
"id": 671,
"note": "Sit voluptatibus eveniet architecto quidem.",
+ "note_html": "<p>something else entirely</p>",
+ "cached_markdown_version": 917504,
"noteable_type": "MergeRequest",
"author_id": 26,
"created_at": "2016-06-14T15:02:56.632Z",
@@ -6219,7 +6223,10 @@
"erased_by_id": null,
"erased_at": null,
"type": "Ci::Build",
- "token": "abcd"
+ "token": "abcd",
+ "artifacts_file_store": 1,
+ "artifacts_metadata_store": 1,
+ "artifacts_size": 10
},
{
"id": 72,
diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
index 6084dc96410..ca46006ea58 100644
--- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
@@ -58,6 +58,26 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
expect(Milestone.find_by_description('test milestone').issues.count).to eq(2)
end
+ context 'when importing a project with cached_markdown_version and note_html' do
+ context 'for an Issue' do
+ it 'does not import note_html' do
+ note_content = 'Quo reprehenderit aliquam qui dicta impedit cupiditate eligendi'
+ issue_note = Issue.find_by(description: 'Aliquam enim illo et possimus.').notes.select { |n| n.note.match(/#{note_content}/)}.first
+
+ expect(issue_note.note_html).to match(/#{note_content}/)
+ end
+ end
+
+ context 'for a Merge Request' do
+ it 'does not import note_html' do
+ note_content = 'Sit voluptatibus eveniet architecto quidem'
+ merge_request_note = MergeRequest.find_by(title: 'MR1').notes.select { |n| n.note.match(/#{note_content}/)}.first
+
+ expect(merge_request_note.note_html).to match(/#{note_content}/)
+ end
+ end
+ end
+
it 'creates a valid pipeline note' do
expect(Ci::Pipeline.find_by_sha('sha-notes').notes).not_to be_empty
end
@@ -328,6 +348,19 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
end
context 'when the project has overridden params in import data' do
+ it 'handles string versions of visibility_level' do
+ # Project needs to be in a group for visibility level comparison
+ # to happen
+ group = create(:group)
+ project.group = group
+
+ project.create_import_data(data: { override_params: { visibility_level: Gitlab::VisibilityLevel::INTERNAL.to_s } })
+
+ restored_project_json
+
+ expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::INTERNAL)
+ end
+
it 'overwrites the params stored in the JSON' do
project.create_import_data(data: { override_params: { description: "Overridden" } })
diff --git a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
index cfc3e0ce926..bc4f867e891 100644
--- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
@@ -91,7 +91,10 @@ describe Gitlab::ImportExport::ProjectTreeSaver do
end
it 'has issue comments' do
- expect(saved_project_json['issues'].first['notes']).not_to be_empty
+ notes = saved_project_json['issues'].first['notes']
+
+ expect(notes).not_to be_empty
+ expect(notes.first['type']).to eq('DiscussionNote')
end
it 'has issue assignees' do
@@ -299,7 +302,7 @@ describe Gitlab::ImportExport::ProjectTreeSaver do
create(:commit_status, project: project, pipeline: ci_build.pipeline)
create(:milestone, project: project)
- create(:note, noteable: issue, project: project)
+ create(:discussion_note, noteable: issue, project: project)
create(:note, noteable: merge_request, project: project)
create(:note, noteable: snippet, project: project)
create(:note_on_commit,
diff --git a/spec/lib/gitlab/import_export/repo_restorer_spec.rb b/spec/lib/gitlab/import_export/repo_restorer_spec.rb
index 8a699eb1461..e2ffb2adb9b 100644
--- a/spec/lib/gitlab/import_export/repo_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/repo_restorer_spec.rb
@@ -34,11 +34,5 @@ describe Gitlab::ImportExport::RepoRestorer do
it 'restores the repo successfully' do
expect(restorer.restore).to be_truthy
end
-
- it 'has the webhooks' do
- restorer.restore
-
- expect(project_hook_exists?(project)).to be true
- end
end
end
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index ebb62124cb1..9093d21647a 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -423,6 +423,7 @@ Service:
- wiki_page_events
- confidential_issues_events
- confidential_note_events
+- deployment_events
ProjectHook:
- id
- url
@@ -606,7 +607,6 @@ ResourceLabelEvent:
- user_id
- created_at
ErrorTracking::ProjectErrorTrackingSetting:
-- id
- api_url
- project_id
- project_name
@@ -626,3 +626,8 @@ MergeRequestAssignee:
- id
- user_id
- merge_request_id
+ProjectMetricsSetting:
+- project_id
+- external_dashboard_url
+- created_at
+- updated_at
diff --git a/spec/lib/gitlab/import_sources_spec.rb b/spec/lib/gitlab/import_sources_spec.rb
index 94abf9679c4..8060b5d4448 100644
--- a/spec/lib/gitlab/import_sources_spec.rb
+++ b/spec/lib/gitlab/import_sources_spec.rb
@@ -14,7 +14,8 @@ describe Gitlab::ImportSources do
'Repo by URL' => 'git',
'GitLab export' => 'gitlab_project',
'Gitea' => 'gitea',
- 'Manifest file' => 'manifest'
+ 'Manifest file' => 'manifest',
+ 'Phabricator' => 'phabricator'
}
expect(described_class.options).to eq(expected)
@@ -35,6 +36,7 @@ describe Gitlab::ImportSources do
gitlab_project
gitea
manifest
+ phabricator
)
expect(described_class.values).to eq(expected)
@@ -53,6 +55,7 @@ describe Gitlab::ImportSources do
fogbugz
gitlab_project
gitea
+ phabricator
)
expect(described_class.importer_names).to eq(expected)
@@ -70,7 +73,8 @@ describe Gitlab::ImportSources do
'git' => nil,
'gitlab_project' => Gitlab::ImportExport::Importer,
'gitea' => Gitlab::LegacyGithubImport::Importer,
- 'manifest' => nil
+ 'manifest' => nil,
+ 'phabricator' => Gitlab::PhabricatorImport::Importer
}
import_sources.each do |name, klass|
@@ -91,7 +95,8 @@ describe Gitlab::ImportSources do
'git' => 'Repo by URL',
'gitlab_project' => 'GitLab export',
'gitea' => 'Gitea',
- 'manifest' => 'Manifest file'
+ 'manifest' => 'Manifest file',
+ 'phabricator' => 'Phabricator'
}
import_sources.each do |name, title|
@@ -102,7 +107,7 @@ describe Gitlab::ImportSources do
end
describe 'imports_repository? checker' do
- let(:allowed_importers) { %w[github gitlab_project bitbucket_server] }
+ let(:allowed_importers) { %w[github gitlab_project bitbucket_server phabricator] }
it 'fails if any importer other than the allowed ones implements this method' do
current_importers = described_class.values.select { |kind| described_class.importer(kind).try(:imports_repository?) }
diff --git a/spec/lib/gitlab/json_logger_spec.rb b/spec/lib/gitlab/json_logger_spec.rb
index cff7dd58c8c..d3d9fe9948a 100644
--- a/spec/lib/gitlab/json_logger_spec.rb
+++ b/spec/lib/gitlab/json_logger_spec.rb
@@ -8,7 +8,7 @@ describe Gitlab::JsonLogger do
describe '#format_message' do
before do
- allow(Gitlab::CorrelationId).to receive(:current_id).and_return('new-correlation-id')
+ allow(Labkit::Correlation::CorrelationId).to receive(:current_id).and_return('new-correlation-id')
end
it 'formats strings' do
diff --git a/spec/lib/gitlab/kubernetes/helm/api_spec.rb b/spec/lib/gitlab/kubernetes/helm/api_spec.rb
index 8433d40b2ea..0de809833e6 100644
--- a/spec/lib/gitlab/kubernetes/helm/api_spec.rb
+++ b/spec/lib/gitlab/kubernetes/helm/api_spec.rb
@@ -33,6 +33,52 @@ describe Gitlab::Kubernetes::Helm::Api do
end
end
+ describe '#uninstall' do
+ before do
+ allow(client).to receive(:create_pod).and_return(nil)
+ allow(client).to receive(:get_config_map).and_return(nil)
+ allow(client).to receive(:create_config_map).and_return(nil)
+ allow(client).to receive(:delete_pod).and_return(nil)
+ allow(namespace).to receive(:ensure_exists!).once
+ end
+
+ it 'ensures the namespace exists before creating the POD' do
+ expect(namespace).to receive(:ensure_exists!).once.ordered
+ expect(client).to receive(:create_pod).once.ordered
+
+ subject.uninstall(command)
+ end
+
+ it 'removes an existing pod before installing' do
+ expect(client).to receive(:delete_pod).with('install-app-name', 'gitlab-managed-apps').once.ordered
+ expect(client).to receive(:create_pod).once.ordered
+
+ subject.uninstall(command)
+ end
+
+ context 'with a ConfigMap' do
+ let(:resource) { Gitlab::Kubernetes::ConfigMap.new(application_name, files).generate }
+
+ it 'creates a ConfigMap on kubeclient' do
+ expect(client).to receive(:create_config_map).with(resource).once
+
+ subject.install(command)
+ end
+
+ context 'config map already exists' do
+ before do
+ expect(client).to receive(:get_config_map).with("values-content-configuration-#{application_name}", gitlab_namespace).and_return(resource)
+ end
+
+ it 'updates the config map' do
+ expect(client).to receive(:update_config_map).with(resource).once
+
+ subject.install(command)
+ end
+ end
+ end
+ end
+
describe '#install' do
before do
allow(client).to receive(:create_pod).and_return(nil)
diff --git a/spec/lib/gitlab/legacy_github_import/importer_spec.rb b/spec/lib/gitlab/legacy_github_import/importer_spec.rb
index 6bc3792eb22..a0c664da185 100644
--- a/spec/lib/gitlab/legacy_github_import/importer_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/importer_spec.rb
@@ -13,21 +13,22 @@ describe Gitlab::LegacyGithubImport::Importer do
expected_called = [
:import_labels, :import_milestones, :import_pull_requests, :import_issues,
- :import_wiki, :import_releases, :handle_errors
+ :import_wiki, :import_releases, :handle_errors,
+ [:import_comments, :issues],
+ [:import_comments, :pull_requests]
]
expected_called -= expected_not_called
aggregate_failures do
- expected_called.each do |method_name|
- expect(importer).to receive(method_name)
+ expected_called.each do |method_name, arg|
+ base_expectation = proc { expect(importer).to receive(method_name) }
+ arg ? base_expectation.call.with(arg) : base_expectation.call
end
- expect(importer).to receive(:import_comments).with(:issues)
- expect(importer).to receive(:import_comments).with(:pull_requests)
-
- expected_not_called.each do |method_name|
- expect(importer).not_to receive(method_name)
+ expected_not_called.each do |method_name, arg|
+ base_expectation = proc { expect(importer).not_to receive(method_name) }
+ arg ? base_expectation.call.with(arg) : base_expectation.call
end
end
@@ -289,7 +290,7 @@ describe Gitlab::LegacyGithubImport::Importer do
end
it_behaves_like 'Gitlab::LegacyGithubImport::Importer#execute' do
- let(:expected_not_called) { [:import_releases] }
+ let(:expected_not_called) { [:import_releases, [:import_comments, :pull_requests]] }
end
it_behaves_like 'Gitlab::LegacyGithubImport::Importer#execute an error occurs'
it_behaves_like 'Gitlab::LegacyGithubImport unit-testing'
diff --git a/spec/lib/gitlab/lets_encrypt/challenge_spec.rb b/spec/lib/gitlab/lets_encrypt/challenge_spec.rb
new file mode 100644
index 00000000000..fcd92586362
--- /dev/null
+++ b/spec/lib/gitlab/lets_encrypt/challenge_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ::Gitlab::LetsEncrypt::Challenge do
+ include LetsEncryptHelpers
+
+ let(:challenge) { described_class.new(acme_challenge_double) }
+
+ LetsEncryptHelpers::ACME_CHALLENGE_METHODS.each do |method, value|
+ describe "##{method}" do
+ it 'delegates to Acme::Client::Resources::Challenge' do
+ expect(challenge.public_send(method)).to eq(value)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/lets_encrypt/client_spec.rb b/spec/lib/gitlab/lets_encrypt/client_spec.rb
new file mode 100644
index 00000000000..5454d9c1af4
--- /dev/null
+++ b/spec/lib/gitlab/lets_encrypt/client_spec.rb
@@ -0,0 +1,162 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ::Gitlab::LetsEncrypt::Client do
+ include LetsEncryptHelpers
+
+ let(:client) { described_class.new }
+
+ before do
+ stub_application_setting(
+ lets_encrypt_notification_email: 'myemail@test.example.com',
+ lets_encrypt_terms_of_service_accepted: true
+ )
+ end
+
+ let!(:stub_client) { stub_lets_encrypt_client }
+
+ shared_examples 'ensures account registration' do
+ it 'ensures account registration' do
+ subject
+
+ expect(stub_client).to have_received(:new_account).with(
+ contact: 'mailto:myemail@test.example.com',
+ terms_of_service_agreed: true
+ )
+ end
+
+ it 'generates and stores private key and initialize acme client with it' do
+ expect(Gitlab::CurrentSettings.lets_encrypt_private_key).to eq(nil)
+
+ subject
+
+ saved_private_key = Gitlab::CurrentSettings.lets_encrypt_private_key
+
+ expect(saved_private_key).to be
+ expect(Acme::Client).to have_received(:new).with(
+ hash_including(private_key: eq_pem(saved_private_key))
+ )
+ end
+
+ context 'when private key is saved in settings' do
+ let!(:saved_private_key) do
+ key = OpenSSL::PKey::RSA.new(4096).to_pem
+ Gitlab::CurrentSettings.current_application_settings.update(lets_encrypt_private_key: key)
+ key
+ end
+
+ it 'uses current value of private key' do
+ subject
+
+ expect(Acme::Client).to have_received(:new).with(
+ hash_including(private_key: eq_pem(saved_private_key))
+ )
+ expect(Gitlab::CurrentSettings.lets_encrypt_private_key).to eq(saved_private_key)
+ end
+ end
+
+ context 'when acme integration is disabled' do
+ before do
+ stub_application_setting(lets_encrypt_terms_of_service_accepted: false)
+ end
+
+ it 'raises error' do
+ expect do
+ subject
+ end.to raise_error('Acme integration is disabled')
+ end
+ end
+ end
+
+ describe '#new_order' do
+ subject(:new_order) { client.new_order('example.com') }
+
+ before do
+ order_double = instance_double('Acme::Order')
+ allow(stub_client).to receive(:new_order).and_return(order_double)
+ end
+
+ include_examples 'ensures account registration'
+
+ it 'returns order' do
+ is_expected.to be_a(::Gitlab::LetsEncrypt::Order)
+ end
+ end
+
+ describe '#load_order' do
+ let(:url) { 'https://example.com/order' }
+ subject { client.load_order(url) }
+
+ before do
+ acme_order = instance_double('Acme::Client::Resources::Order')
+ allow(stub_client).to receive(:order).with(url: url).and_return(acme_order)
+ end
+
+ include_examples 'ensures account registration'
+
+ it 'loads order' do
+ is_expected.to be_a(::Gitlab::LetsEncrypt::Order)
+ end
+ end
+
+ describe '#load_challenge' do
+ let(:url) { 'https://example.com/challenge' }
+ subject { client.load_challenge(url) }
+
+ before do
+ acme_challenge = instance_double('Acme::Client::Resources::Challenge')
+ allow(stub_client).to receive(:challenge).with(url: url).and_return(acme_challenge)
+ end
+
+ include_examples 'ensures account registration'
+
+ it 'loads challenge' do
+ is_expected.to be_a(::Gitlab::LetsEncrypt::Challenge)
+ end
+ end
+
+ describe '#enabled?' do
+ subject { client.enabled? }
+
+ context 'when terms of service are accepted' do
+ it { is_expected.to eq(true) }
+
+ context "when private_key isn't present and database is read only" do
+ before do
+ allow(::Gitlab::Database).to receive(:read_only?).and_return(true)
+ end
+
+ it 'returns false' do
+ expect(::Gitlab::CurrentSettings.lets_encrypt_private_key).to eq(nil)
+
+ is_expected.to eq(false)
+ end
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(pages_auto_ssl: false)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
+
+ context 'when terms of service are not accepted' do
+ before do
+ stub_application_setting(lets_encrypt_terms_of_service_accepted: false)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
+
+ describe '#terms_of_service_url' do
+ subject { client.terms_of_service_url }
+
+ it 'returns valid url' do
+ is_expected.to eq("https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf")
+ end
+ end
+end
diff --git a/spec/lib/gitlab/lets_encrypt/order_spec.rb b/spec/lib/gitlab/lets_encrypt/order_spec.rb
new file mode 100644
index 00000000000..1a759103c44
--- /dev/null
+++ b/spec/lib/gitlab/lets_encrypt/order_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ::Gitlab::LetsEncrypt::Order do
+ include LetsEncryptHelpers
+
+ let(:acme_order) { acme_order_double }
+
+ let(:order) { described_class.new(acme_order) }
+
+ LetsEncryptHelpers::ACME_ORDER_METHODS.each do |method, value|
+ describe "##{method}" do
+ it 'delegates to Acme::Client::Resources::Order' do
+ expect(order.public_send(method)).to eq(value)
+ end
+ end
+ end
+
+ describe '#new_challenge' do
+ it 'returns challenge' do
+ expect(order.new_challenge).to be_a(::Gitlab::LetsEncrypt::Challenge)
+ end
+ end
+
+ describe '#request_certificate' do
+ let(:private_key) do
+ OpenSSL::PKey::RSA.new(4096).to_pem
+ end
+
+ it 'generates csr and finalizes order' do
+ expect(acme_order).to receive(:finalize) do |csr:|
+ expect do
+ csr.csr # it's being evaluated lazily
+ end.not_to raise_error
+ end
+
+ order.request_certificate(domain: 'example.com', private_key: private_key)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/lfs_token_spec.rb b/spec/lib/gitlab/lfs_token_spec.rb
index 8961ecc4be0..701ed1f3a1b 100644
--- a/spec/lib/gitlab/lfs_token_spec.rb
+++ b/spec/lib/gitlab/lfs_token_spec.rb
@@ -77,96 +77,42 @@ describe Gitlab::LfsToken, :clean_gitlab_redis_shared_state do
let(:actor) { create(:user, username: 'test_user_lfs_1') }
let(:lfs_token) { described_class.new(actor) }
- context 'for an HMAC token' do
- before do
- # We're not interested in testing LegacyRedisDeviseToken here
- allow(Gitlab::LfsToken::LegacyRedisDeviseToken).to receive_message_chain(:new, :token_valid?).and_return(false)
- end
-
- context 'where the token is invalid' do
- context "because it's junk" do
- it 'returns false' do
- expect(lfs_token.token_valid?('junk')).to be_falsey
- end
- end
-
- context "because it's been fiddled with" do
- it 'returns false' do
- fiddled_token = lfs_token.token.tap { |token| token[0] = 'E' }
- expect(lfs_token.token_valid?(fiddled_token)).to be_falsey
- end
- end
-
- context "because it was generated with a different secret" do
- it 'returns false' do
- different_actor = create(:user, username: 'test_user_lfs_2')
- different_secret_token = described_class.new(different_actor).token
- expect(lfs_token.token_valid?(different_secret_token)).to be_falsey
- end
- end
-
- context "because it's expired" do
- it 'returns false' do
- expired_token = lfs_token.token
- # Needs to be at least 1860 seconds, because the default expiry is
- # 1800 seconds with an additional 60 second leeway.
- Timecop.freeze(Time.now + 1865) do
- expect(lfs_token.token_valid?(expired_token)).to be_falsey
- end
- end
+ context 'where the token is invalid' do
+ context "because it's junk" do
+ it 'returns false' do
+ expect(lfs_token.token_valid?('junk')).to be_falsey
end
end
- context 'where the token is valid' do
- it 'returns true' do
- expect(lfs_token.token_valid?(lfs_token.token)).to be_truthy
+ context "because it's been fiddled with" do
+ it 'returns false' do
+ fiddled_token = lfs_token.token.tap { |token| token[0] = 'E' }
+ expect(lfs_token.token_valid?(fiddled_token)).to be_falsey
end
end
- end
-
- context 'for a LegacyRedisDevise token' do
- before do
- # We're not interested in testing HMACToken here
- allow_any_instance_of(Gitlab::LfsToken::HMACToken).to receive(:token_valid?).and_return(false)
- end
-
- context 'where the token is invalid' do
- context "because it's junk" do
- it 'returns false' do
- expect(lfs_token.token_valid?('junk')).to be_falsey
- end
- end
- context "because it's been fiddled with" do
- it 'returns false' do
- generated_token = Gitlab::LfsToken::LegacyRedisDeviseToken.new(actor).store_new_token
- fiddled_token = generated_token.tap { |token| token[0] = 'E' }
- expect(lfs_token.token_valid?(fiddled_token)).to be_falsey
- end
- end
-
- context "because it was generated with a different secret" do
- it 'returns false' do
- different_actor = create(:user, username: 'test_user_lfs_2')
- different_secret_token = described_class.new(different_actor).token
- expect(lfs_token.token_valid?(different_secret_token)).to be_falsey
- end
+ context "because it was generated with a different secret" do
+ it 'returns false' do
+ different_actor = create(:user, username: 'test_user_lfs_2')
+ different_secret_token = described_class.new(different_actor).token
+ expect(lfs_token.token_valid?(different_secret_token)).to be_falsey
end
+ end
- context "because it's expired" do
- it 'returns false' do
- generated_token = Gitlab::LfsToken::LegacyRedisDeviseToken.new(actor).store_new_token(1)
- # We need a real sleep here because we need to wait for redis to expire the key.
- sleep(0.01)
- expect(lfs_token.token_valid?(generated_token)).to be_falsey
+ context "because it's expired" do
+ it 'returns false' do
+ expired_token = lfs_token.token
+ # Needs to be at least 1860 seconds, because the default expiry is
+ # 1800 seconds with an additional 60 second leeway.
+ Timecop.freeze(Time.now + 1865) do
+ expect(lfs_token.token_valid?(expired_token)).to be_falsey
end
end
end
context 'where the token is valid' do
it 'returns true' do
- generated_token = Gitlab::LfsToken::LegacyRedisDeviseToken.new(actor).store_new_token
- expect(lfs_token.token_valid?(generated_token)).to be_truthy
+ expect(lfs_token.token_valid?(lfs_token.token)).to be_truthy
end
end
end
diff --git a/spec/lib/gitlab/markdown_cache/active_record/extension_spec.rb b/spec/lib/gitlab/markdown_cache/active_record/extension_spec.rb
new file mode 100644
index 00000000000..18052b1991c
--- /dev/null
+++ b/spec/lib/gitlab/markdown_cache/active_record/extension_spec.rb
@@ -0,0 +1,179 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Gitlab::MarkdownCache::ActiveRecord::Extension do
+ let(:klass) do
+ Class.new(ActiveRecord::Base) do
+ self.table_name = 'issues'
+ include CacheMarkdownField
+ cache_markdown_field :title, whitelisted: true
+ cache_markdown_field :description, pipeline: :single_line
+
+ attr_accessor :author, :project
+ end
+ end
+
+ let(:cache_version) { Gitlab::MarkdownCache::CACHE_COMMONMARK_VERSION << 16 }
+ let(:thing) { klass.new(title: markdown, title_html: html, cached_markdown_version: cache_version) }
+
+ let(:markdown) { '`Foo`' }
+ let(:html) { '<p data-sourcepos="1:1-1:5" dir="auto"><code>Foo</code></p>' }
+
+ let(:updated_markdown) { '`Bar`' }
+ let(:updated_html) { '<p data-sourcepos="1:1-1:5" dir="auto"><code>Bar</code></p>' }
+
+ context 'an unchanged markdown field' do
+ let(:thing) { klass.new(title: markdown) }
+
+ before do
+ thing.title = thing.title
+ thing.save
+ end
+
+ it { expect(thing.title).to eq(markdown) }
+ it { expect(thing.title_html).to eq(html) }
+ it { expect(thing.title_html_changed?).not_to be_truthy }
+ it { expect(thing.cached_markdown_version).to eq(cache_version) }
+ end
+
+ context 'a changed markdown field' do
+ let(:thing) { klass.new(title: markdown, title_html: html, cached_markdown_version: cache_version) }
+
+ before do
+ thing.title = updated_markdown
+ thing.save
+ end
+
+ it { expect(thing.title_html).to eq(updated_html) }
+ it { expect(thing.cached_markdown_version).to eq(cache_version) }
+ end
+
+ context 'when a markdown field is set repeatedly to an empty string' do
+ it do
+ expect(thing).to receive(:refresh_markdown_cache).once
+ thing.title = ''
+ thing.save
+ thing.title = ''
+ thing.save
+ end
+ end
+
+ context 'when a markdown field is set repeatedly to a string which renders as empty html' do
+ it do
+ expect(thing).to receive(:refresh_markdown_cache).once
+ thing.title = '[//]: # (This is also a comment.)'
+ thing.save
+ thing.title = '[//]: # (This is also a comment.)'
+ thing.save
+ end
+ end
+
+ context 'a non-markdown field changed' do
+ let(:thing) { klass.new(title: markdown, title_html: html, cached_markdown_version: cache_version) }
+
+ before do
+ thing.state = 'closed'
+ thing.save
+ end
+
+ it { expect(thing.state).to eq('closed') }
+ it { expect(thing.title).to eq(markdown) }
+ it { expect(thing.title_html).to eq(html) }
+ it { expect(thing.cached_markdown_version).to eq(cache_version) }
+ end
+
+ context 'version is out of date' do
+ let(:thing) { klass.new(title: updated_markdown, title_html: html, cached_markdown_version: nil) }
+
+ before do
+ thing.save
+ end
+
+ it { expect(thing.title_html).to eq(updated_html) }
+ it { expect(thing.cached_markdown_version).to eq(cache_version) }
+ end
+
+ context 'when an invalidating field is changed' do
+ it 'invalidates the cache when project changes' do
+ thing.project = :new_project
+ allow(Banzai::Renderer).to receive(:cacheless_render_field).and_return(updated_html)
+
+ thing.save
+
+ expect(thing.title_html).to eq(updated_html)
+ expect(thing.description_html).to eq(updated_html)
+ expect(thing.cached_markdown_version).to eq(cache_version)
+ end
+
+ it 'invalidates the cache when author changes' do
+ thing.author = :new_author
+ allow(Banzai::Renderer).to receive(:cacheless_render_field).and_return(updated_html)
+
+ thing.save
+
+ expect(thing.title_html).to eq(updated_html)
+ expect(thing.description_html).to eq(updated_html)
+ expect(thing.cached_markdown_version).to eq(cache_version)
+ end
+ end
+
+ describe '.attributes' do
+ it 'excludes cache attributes that is blacklisted by default' do
+ expect(thing.attributes.keys.sort).not_to include(%w[description_html])
+ end
+ end
+
+ describe '#cached_html_up_to_date?' do
+ let(:thing) { klass.create(title: updated_markdown, title_html: html, cached_markdown_version: nil) }
+ subject { thing.cached_html_up_to_date?(:title) }
+
+ it 'returns false if markdown has been changed but html has not' do
+ thing.title = "changed!"
+
+ is_expected.to be_falsy
+ end
+
+ it 'returns true if markdown has not been changed but html has' do
+ thing.title_html = updated_html
+
+ is_expected.to be_truthy
+ end
+
+ it 'returns true if markdown and html have both been changed' do
+ thing.title = updated_markdown
+ thing.title_html = updated_html
+
+ is_expected.to be_truthy
+ end
+
+ it 'returns false if the markdown field is set but the html is not' do
+ thing.title_html = nil
+
+ is_expected.to be_falsy
+ end
+ end
+
+ describe '#refresh_markdown_cache!' do
+ before do
+ thing.title = updated_markdown
+ end
+
+ it 'skips saving if not persisted' do
+ expect(thing).to receive(:persisted?).and_return(false)
+ expect(thing).not_to receive(:update_columns)
+
+ thing.refresh_markdown_cache!
+ end
+
+ it 'saves the changes' do
+ expect(thing).to receive(:persisted?).and_return(true)
+
+ expect(thing).to receive(:update_columns)
+ .with("title_html" => updated_html,
+ "description_html" => "",
+ "cached_markdown_version" => cache_version)
+
+ thing.refresh_markdown_cache!
+ end
+ end
+end
diff --git a/spec/lib/gitlab/markdown_cache/field_data_spec.rb b/spec/lib/gitlab/markdown_cache/field_data_spec.rb
new file mode 100644
index 00000000000..393bf85aa43
--- /dev/null
+++ b/spec/lib/gitlab/markdown_cache/field_data_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+describe Gitlab::MarkdownCache::FieldData do
+ subject(:field_data) { described_class.new }
+
+ before do
+ field_data[:description] = { project: double('project in context') }
+ end
+
+ it 'translates a markdown field name into a html field name' do
+ expect(field_data.html_field(:description)).to eq("description_html")
+ end
+end
diff --git a/spec/lib/gitlab/markdown_cache/redis/extension_spec.rb b/spec/lib/gitlab/markdown_cache/redis/extension_spec.rb
new file mode 100644
index 00000000000..b6a781de426
--- /dev/null
+++ b/spec/lib/gitlab/markdown_cache/redis/extension_spec.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Gitlab::MarkdownCache::Redis::Extension, :clean_gitlab_redis_cache do
+ let(:klass) do
+ Class.new do
+ include CacheMarkdownField
+
+ def initialize(title: nil, description: nil)
+ @title, @description = title, description
+ end
+
+ attr_reader :title, :description
+
+ cache_markdown_field :title, pipeline: :single_line
+ cache_markdown_field :description
+
+ def cache_key
+ "cache-key"
+ end
+ end
+ end
+
+ let(:cache_version) { Gitlab::MarkdownCache::CACHE_COMMONMARK_VERSION << 16 }
+ let(:thing) { klass.new(title: "`Hello`", description: "`World`") }
+ let(:expected_cache_key) { "markdown_cache:cache-key" }
+
+ it 'defines the html attributes' do
+ expect(thing).to respond_to(:title_html, :description_html, :cached_markdown_version)
+ end
+
+ it 'loads the markdown from the cache only once' do
+ expect(thing).to receive(:load_cached_markdown).once.and_call_original
+
+ thing.title_html
+ thing.description_html
+ end
+
+ it 'correctly loads the markdown if it was stored in redis' do
+ Gitlab::Redis::Cache.with do |r|
+ r.mapped_hmset(expected_cache_key,
+ title_html: 'hello',
+ description_html: 'world',
+ cached_markdown_version: cache_version)
+ end
+
+ expect(thing.title_html).to eq('hello')
+ expect(thing.description_html).to eq('world')
+ expect(thing.cached_markdown_version).to eq(cache_version)
+ end
+
+ describe "#refresh_markdown_cache!" do
+ it "stores the value in redis" do
+ expected_results = { "title_html" => "`Hello`",
+ "description_html" => "<p data-sourcepos=\"1:1-1:7\" dir=\"auto\"><code>World</code></p>",
+ "cached_markdown_version" => cache_version.to_s }
+
+ thing.refresh_markdown_cache!
+
+ results = Gitlab::Redis::Cache.with do |r|
+ r.mapped_hmget(expected_cache_key,
+ "title_html", "description_html", "cached_markdown_version")
+ end
+
+ expect(results).to eq(expected_results)
+ end
+
+ it "assigns the values" do
+ thing.refresh_markdown_cache!
+
+ expect(thing.title_html).to eq('`Hello`')
+ expect(thing.description_html).to eq("<p data-sourcepos=\"1:1-1:7\" dir=\"auto\"><code>World</code></p>")
+ expect(thing.cached_markdown_version).to eq(cache_version)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/markdown_cache/redis/store_spec.rb b/spec/lib/gitlab/markdown_cache/redis/store_spec.rb
new file mode 100644
index 00000000000..95c68e7d491
--- /dev/null
+++ b/spec/lib/gitlab/markdown_cache/redis/store_spec.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Gitlab::MarkdownCache::Redis::Store, :clean_gitlab_redis_cache do
+ let(:storable_class) do
+ Class.new do
+ cattr_reader :cached_markdown_fields do
+ Gitlab::MarkdownCache::FieldData.new.tap do |field_data|
+ field_data[:field_1] = {}
+ field_data[:field_2] = {}
+ end
+ end
+
+ attr_accessor :field_1, :field_2, :field_1_html, :field_2_html, :cached_markdown_version
+
+ def cache_key
+ "cache-key"
+ end
+ end
+ end
+ let(:storable) { storable_class.new }
+ let(:cache_key) { "markdown_cache:#{storable.cache_key}" }
+
+ subject(:store) { described_class.new(storable) }
+
+ def read_values
+ Gitlab::Redis::Cache.with do |r|
+ r.mapped_hmget(cache_key,
+ :field_1_html, :field_2_html, :cached_markdown_version)
+ end
+ end
+
+ def store_values(values)
+ Gitlab::Redis::Cache.with do |r|
+ r.mapped_hmset(cache_key,
+ values)
+ end
+ end
+
+ describe '#save' do
+ it 'stores updates to html fields and version' do
+ values_to_store = { field_1_html: "hello", field_2_html: "world", cached_markdown_version: 1 }
+
+ store.save(values_to_store)
+
+ expect(read_values)
+ .to eq({ field_1_html: "hello", field_2_html: "world", cached_markdown_version: "1" })
+ end
+ end
+
+ describe '#read' do
+ it 'reads the html fields and version from redis if they were stored' do
+ stored_values = { field_1_html: "hello", field_2_html: "world", cached_markdown_version: 1 }
+
+ store_values(stored_values)
+
+ expect(store.read.symbolize_keys).to eq(stored_values)
+ end
+
+ it 'is mared loaded after reading' do
+ expect(store).not_to be_loaded
+
+ store.read
+
+ expect(store).to be_loaded
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/dashboard/finder_spec.rb b/spec/lib/gitlab/metrics/dashboard/finder_spec.rb
new file mode 100644
index 00000000000..bdcb5914575
--- /dev/null
+++ b/spec/lib/gitlab/metrics/dashboard/finder_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store_caching do
+ include MetricsDashboardHelpers
+
+ set(:project) { build(:project) }
+ set(:environment) { create(:environment, project: project) }
+ let(:system_dashboard_path) { Gitlab::Metrics::Dashboard::SystemDashboardService::SYSTEM_DASHBOARD_PATH}
+
+ describe '.find' do
+ let(:dashboard_path) { '.gitlab/dashboards/test.yml' }
+ let(:service_call) { described_class.find(project, nil, environment, dashboard_path) }
+
+ it_behaves_like 'misconfigured dashboard service response', :not_found
+
+ context 'when the dashboard exists' do
+ let(:project) { project_with_dashboard(dashboard_path) }
+
+ it_behaves_like 'valid dashboard service response'
+ end
+
+ context 'when the dashboard is configured incorrectly' do
+ let(:project) { project_with_dashboard(dashboard_path, {}) }
+
+ it_behaves_like 'misconfigured dashboard service response', :unprocessable_entity
+ end
+
+ context 'when the dashboard contains a metric without a query' do
+ let(:dashboard) { { 'panel_groups' => [{ 'panels' => [{ 'metrics' => [{ 'id' => 'mock' }] }] }] } }
+ let(:project) { project_with_dashboard(dashboard_path, dashboard.to_yaml) }
+
+ it_behaves_like 'misconfigured dashboard service response', :unprocessable_entity
+ end
+
+ context 'when the system dashboard is specified' do
+ let(:dashboard_path) { system_dashboard_path }
+
+ it_behaves_like 'valid dashboard service response'
+ end
+
+ context 'when no dashboard is specified' do
+ let(:service_call) { described_class.find(project, nil, environment) }
+
+ it_behaves_like 'valid dashboard service response'
+ end
+ end
+
+ describe '.find_all_paths' do
+ let(:all_dashboard_paths) { described_class.find_all_paths(project) }
+ let(:system_dashboard) { { path: system_dashboard_path, default: true } }
+
+ it 'includes only the system dashboard by default' do
+ expect(all_dashboard_paths).to eq([system_dashboard])
+ end
+
+ context 'when the project contains dashboards' do
+ let(:dashboard_path) { '.gitlab/dashboards/test.yml' }
+ let(:project) { project_with_dashboard(dashboard_path) }
+
+ it 'includes system and project dashboards' do
+ project_dashboard = { path: dashboard_path, default: false }
+
+ expect(all_dashboard_paths).to contain_exactly(system_dashboard, project_dashboard)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/dashboard/processor_spec.rb b/spec/lib/gitlab/metrics/dashboard/processor_spec.rb
new file mode 100644
index 00000000000..797d4daabe3
--- /dev/null
+++ b/spec/lib/gitlab/metrics/dashboard/processor_spec.rb
@@ -0,0 +1,127 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Metrics::Dashboard::Processor do
+ let(:project) { build(:project) }
+ let(:environment) { create(:environment, project: project) }
+ let(:dashboard_yml) { YAML.load_file('spec/fixtures/lib/gitlab/metrics/dashboard/sample_dashboard.yml') }
+
+ describe 'process' do
+ let(:process_params) { [project, environment, dashboard_yml] }
+ let(:dashboard) { described_class.new(*process_params).process(insert_project_metrics: true) }
+
+ it 'includes a path for the prometheus endpoint with each metric' do
+ expect(all_metrics).to satisfy_all do |metric|
+ metric[:prometheus_endpoint_path] == prometheus_path(metric[:query_range])
+ end
+ end
+
+ context 'when dashboard config corresponds to common metrics' do
+ let!(:common_metric) { create(:prometheus_metric, :common, identifier: 'metric_a1') }
+
+ it 'inserts metric ids into the config' do
+ target_metric = all_metrics.find { |metric| metric[:id] == 'metric_a1' }
+
+ expect(target_metric).to include(:metric_id)
+ expect(target_metric[:metric_id]).to eq(common_metric.id)
+ end
+ end
+
+ context 'when the project has associated metrics' do
+ let!(:project_response_metric) { create(:prometheus_metric, project: project, group: :response) }
+ let!(:project_system_metric) { create(:prometheus_metric, project: project, group: :system) }
+ let!(:project_business_metric) { create(:prometheus_metric, project: project, group: :business) }
+
+ it 'includes project-specific metrics' do
+ expect(all_metrics).to include get_metric_details(project_system_metric)
+ expect(all_metrics).to include get_metric_details(project_response_metric)
+ expect(all_metrics).to include get_metric_details(project_business_metric)
+ end
+
+ it 'orders groups by priority and panels by weight' do
+ expected_metrics_order = [
+ 'metric_b', # group priority 10, panel weight 1
+ 'metric_a2', # group priority 1, panel weight 2
+ 'metric_a1', # group priority 1, panel weight 1
+ project_business_metric.id, # group priority 0, panel weight nil (0)
+ project_response_metric.id, # group priority -5, panel weight nil (0)
+ project_system_metric.id, # group priority -10, panel weight nil (0)
+ ]
+ actual_metrics_order = all_metrics.map { |m| m[:id] || m[:metric_id] }
+
+ expect(actual_metrics_order).to eq expected_metrics_order
+ end
+
+ context 'when the dashboard should not include project metrics' do
+ let(:dashboard) { described_class.new(*process_params).process(insert_project_metrics: false) }
+
+ it 'includes only dashboard metrics' do
+ metrics = all_metrics.map { |m| m[:id] }
+
+ expect(metrics.length).to be(3)
+ expect(metrics).to eq %w(metric_b metric_a2 metric_a1)
+ end
+ end
+ end
+
+ shared_examples_for 'errors with message' do |expected_message|
+ it 'raises a DashboardLayoutError' do
+ error_class = Gitlab::Metrics::Dashboard::Stages::BaseStage::DashboardProcessingError
+
+ expect { dashboard }.to raise_error(error_class, expected_message)
+ end
+ end
+
+ context 'when the dashboard is missing panel_groups' do
+ let(:dashboard_yml) { {} }
+
+ it_behaves_like 'errors with message', 'Top-level key :panel_groups must be an array'
+ end
+
+ context 'when the dashboard contains a panel_group which is missing panels' do
+ let(:dashboard_yml) { { panel_groups: [{}] } }
+
+ it_behaves_like 'errors with message', 'Each "panel_group" must define an array :panels'
+ end
+
+ context 'when the dashboard contains a panel which is missing metrics' do
+ let(:dashboard_yml) { { panel_groups: [{ panels: [{}] }] } }
+
+ it_behaves_like 'errors with message', 'Each "panel" must define an array :metrics'
+ end
+
+ context 'when the dashboard contains a metric which is missing a query' do
+ let(:dashboard_yml) { { panel_groups: [{ panels: [{ metrics: [{}] }] }] } }
+
+ it_behaves_like 'errors with message', 'Each "metric" must define one of :query or :query_range'
+ end
+ end
+
+ private
+
+ def all_metrics
+ dashboard[:panel_groups].map do |group|
+ group[:panels].map { |panel| panel[:metrics] }
+ end.flatten
+ end
+
+ def get_metric_details(metric)
+ {
+ query_range: metric.query,
+ unit: metric.unit,
+ label: metric.legend,
+ metric_id: metric.id,
+ prometheus_endpoint_path: prometheus_path(metric.query)
+ }
+ end
+
+ def prometheus_path(query)
+ Gitlab::Routing.url_helpers.prometheus_api_project_environment_path(
+ project,
+ environment,
+ proxy_path: :query_range,
+ query: query
+ )
+ end
+end
diff --git a/spec/lib/gitlab/metrics/dashboard/project_dashboard_service_spec.rb b/spec/lib/gitlab/metrics/dashboard/project_dashboard_service_spec.rb
new file mode 100644
index 00000000000..794ac5f109b
--- /dev/null
+++ b/spec/lib/gitlab/metrics/dashboard/project_dashboard_service_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Gitlab::Metrics::Dashboard::ProjectDashboardService, :use_clean_rails_memory_store_caching do
+ include MetricsDashboardHelpers
+
+ set(:user) { build(:user) }
+ set(:project) { build(:project) }
+ set(:environment) { create(:environment, project: project) }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ describe 'get_dashboard' do
+ let(:dashboard_path) { '.gitlab/dashboards/test.yml' }
+ let(:service_params) { [project, user, { environment: environment, dashboard_path: dashboard_path }] }
+ let(:service_call) { described_class.new(*service_params).get_dashboard }
+
+ context 'when the dashboard does not exist' do
+ it_behaves_like 'misconfigured dashboard service response', :not_found
+ end
+
+ context 'when the dashboard exists' do
+ let(:project) { project_with_dashboard(dashboard_path) }
+
+ it_behaves_like 'valid dashboard service response'
+
+ it 'caches the unprocessed dashboard for subsequent calls' do
+ expect_any_instance_of(described_class)
+ .to receive(:get_raw_dashboard)
+ .once
+ .and_call_original
+
+ described_class.new(*service_params).get_dashboard
+ described_class.new(*service_params).get_dashboard
+ end
+
+ context 'and the dashboard is then deleted' do
+ it 'does not return the previously cached dashboard' do
+ described_class.new(*service_params).get_dashboard
+
+ delete_project_dashboard(project, user, dashboard_path)
+
+ expect_any_instance_of(described_class)
+ .to receive(:get_raw_dashboard)
+ .once
+ .and_call_original
+
+ described_class.new(*service_params).get_dashboard
+ end
+ end
+ end
+
+ context 'when the dashboard is configured incorrectly' do
+ let(:project) { project_with_dashboard(dashboard_path, {}) }
+
+ it_behaves_like 'misconfigured dashboard service response', :unprocessable_entity
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/dashboard/system_dashboard_service_spec.rb b/spec/lib/gitlab/metrics/dashboard/system_dashboard_service_spec.rb
new file mode 100644
index 00000000000..2648fe990de
--- /dev/null
+++ b/spec/lib/gitlab/metrics/dashboard/system_dashboard_service_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Metrics::Dashboard::SystemDashboardService, :use_clean_rails_memory_store_caching do
+ include MetricsDashboardHelpers
+
+ set(:project) { build(:project) }
+ set(:environment) { create(:environment, project: project) }
+
+ describe 'get_dashboard' do
+ let(:dashboard_path) { described_class::SYSTEM_DASHBOARD_PATH }
+ let(:service_params) { [project, nil, { environment: environment, dashboard_path: dashboard_path }] }
+ let(:service_call) { described_class.new(*service_params).get_dashboard }
+
+ it_behaves_like 'valid dashboard service response'
+
+ it 'caches the unprocessed dashboard for subsequent calls' do
+ expect(YAML).to receive(:safe_load).once.and_call_original
+
+ described_class.new(*service_params).get_dashboard
+ described_class.new(*service_params).get_dashboard
+ end
+
+ context 'when called with a non-system dashboard' do
+ let(:dashboard_path) { 'garbage/dashboard/path' }
+
+ # We want to alwaus return the system dashboard.
+ it_behaves_like 'valid dashboard service response'
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/samplers/puma_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/puma_sampler_spec.rb
new file mode 100644
index 00000000000..f4a6e1fc7d9
--- /dev/null
+++ b/spec/lib/gitlab/metrics/samplers/puma_sampler_spec.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Metrics::Samplers::PumaSampler do
+ subject { described_class.new(5) }
+ let(:null_metric) { double('null_metric', set: nil, observe: nil) }
+
+ before do
+ allow(Gitlab::Metrics::NullMetric).to receive(:instance).and_return(null_metric)
+ end
+
+ describe '#sample' do
+ before do
+ expect(subject).to receive(:puma_stats).and_return(puma_stats)
+ end
+
+ context 'in cluster mode' do
+ let(:puma_stats) do
+ <<~EOS
+ {
+ "workers": 2,
+ "phase": 2,
+ "booted_workers": 2,
+ "old_workers": 0,
+ "worker_status": [{
+ "pid": 32534,
+ "index": 0,
+ "phase": 1,
+ "booted": true,
+ "last_checkin": "2019-05-15T07:57:55Z",
+ "last_status": {
+ "backlog":0,
+ "running":1,
+ "pool_capacity":4,
+ "max_threads": 4
+ }
+ }]
+ }
+ EOS
+ end
+
+ it 'samples master statistics' do
+ labels = { worker: 'master' }
+
+ expect(subject.metrics[:puma_workers]).to receive(:set).with(labels, 2)
+ expect(subject.metrics[:puma_running_workers]).to receive(:set).with(labels, 2)
+ expect(subject.metrics[:puma_stale_workers]).to receive(:set).with(labels, 0)
+ expect(subject.metrics[:puma_phase]).to receive(:set).once.with(labels, 2)
+ expect(subject.metrics[:puma_phase]).to receive(:set).once.with({ worker: 'worker_0' }, 1)
+
+ subject.sample
+ end
+
+ it 'samples worker statistics' do
+ labels = { worker: 'worker_0' }
+
+ expect_worker_stats(labels)
+
+ subject.sample
+ end
+ end
+
+ context 'with empty worker stats' do
+ let(:puma_stats) do
+ <<~EOS
+ {
+ "workers": 2,
+ "phase": 2,
+ "booted_workers": 2,
+ "old_workers": 0,
+ "worker_status": [{
+ "pid": 32534,
+ "index": 0,
+ "phase": 1,
+ "booted": true,
+ "last_checkin": "2019-05-15T07:57:55Z",
+ "last_status": {}
+ }]
+ }
+ EOS
+ end
+
+ it 'does not log worker stats' do
+ expect(subject).not_to receive(:set_worker_metrics)
+
+ subject.sample
+ end
+ end
+
+ context 'in single mode' do
+ let(:puma_stats) do
+ <<~EOS
+ {
+ "backlog":0,
+ "running":1,
+ "pool_capacity":4,
+ "max_threads": 4
+ }
+ EOS
+ end
+
+ it 'samples worker statistics' do
+ labels = {}
+
+ expect(subject.metrics[:puma_workers]).to receive(:set).with(labels, 1)
+ expect(subject.metrics[:puma_running_workers]).to receive(:set).with(labels, 1)
+ expect_worker_stats(labels)
+
+ subject.sample
+ end
+ end
+ end
+
+ def expect_worker_stats(labels)
+ expect(subject.metrics[:puma_queued_connections]).to receive(:set).with(labels, 0)
+ expect(subject.metrics[:puma_active_connections]).to receive(:set).with(labels, 0)
+ expect(subject.metrics[:puma_running]).to receive(:set).with(labels, 1)
+ expect(subject.metrics[:puma_pool_capacity]).to receive(:set).with(labels, 4)
+ expect(subject.metrics[:puma_max_threads]).to receive(:set).with(labels, 4)
+ expect(subject.metrics[:puma_idle_threads]).to receive(:set).with(labels, 1)
+ end
+end
diff --git a/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb
index 7972ff253fe..aaf8c9fa2a0 100644
--- a/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb
+++ b/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb
@@ -10,17 +10,20 @@ describe Gitlab::Metrics::Samplers::RubySampler do
describe '#sample' do
it 'samples various statistics' do
- expect(Gitlab::Metrics::System).to receive(:memory_usage)
+ expect(Gitlab::Metrics::System).to receive(:cpu_time)
expect(Gitlab::Metrics::System).to receive(:file_descriptor_count)
+ expect(Gitlab::Metrics::System).to receive(:memory_usage)
+ expect(Gitlab::Metrics::System).to receive(:process_start_time)
+ expect(Gitlab::Metrics::System).to receive(:max_open_file_descriptors)
expect(sampler).to receive(:sample_gc)
sampler.sample
end
- it 'adds a metric containing the memory usage' do
+ it 'adds a metric containing the process resident memory bytes' do
expect(Gitlab::Metrics::System).to receive(:memory_usage).and_return(9000)
- expect(sampler.metrics[:memory_usage]).to receive(:set).with({}, 9000)
+ expect(sampler.metrics[:process_resident_memory_bytes]).to receive(:set).with({}, 9000)
sampler.sample
end
@@ -34,6 +37,27 @@ describe Gitlab::Metrics::Samplers::RubySampler do
sampler.sample
end
+ it 'adds a metric containing the process total cpu time' do
+ expect(Gitlab::Metrics::System).to receive(:cpu_time).and_return(0.51)
+ expect(sampler.metrics[:process_cpu_seconds_total]).to receive(:set).with({}, 0.51)
+
+ sampler.sample
+ end
+
+ it 'adds a metric containing the process start time' do
+ expect(Gitlab::Metrics::System).to receive(:process_start_time).and_return(12345)
+ expect(sampler.metrics[:process_start_time_seconds]).to receive(:set).with({}, 12345)
+
+ sampler.sample
+ end
+
+ it 'adds a metric containing the process max file descriptors' do
+ expect(Gitlab::Metrics::System).to receive(:max_open_file_descriptors).and_return(1024)
+ expect(sampler.metrics[:process_max_fds]).to receive(:set).with({}, 1024)
+
+ sampler.sample
+ end
+
it 'clears any GC profiles' do
expect(GC::Profiler).to receive(:clear)
diff --git a/spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb
index 4b03f3c2532..090e456644f 100644
--- a/spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb
+++ b/spec/lib/gitlab/metrics/samplers/unicorn_sampler_spec.rb
@@ -39,8 +39,8 @@ describe Gitlab::Metrics::Samplers::UnicornSampler do
it 'updates metrics type unix and with addr' do
labels = { socket_type: 'unix', socket_address: socket_address }
- expect(subject).to receive_message_chain(:unicorn_active_connections, :set).with(labels, 'active')
- expect(subject).to receive_message_chain(:unicorn_queued_connections, :set).with(labels, 'queued')
+ expect(subject.metrics[:unicorn_active_connections]).to receive(:set).with(labels, 'active')
+ expect(subject.metrics[:unicorn_queued_connections]).to receive(:set).with(labels, 'queued')
subject.sample
end
@@ -50,7 +50,6 @@ describe Gitlab::Metrics::Samplers::UnicornSampler do
context 'unicorn listens on tcp sockets' do
let(:tcp_socket_address) { '0.0.0.0:8080' }
let(:tcp_sockets) { [tcp_socket_address] }
-
before do
allow(unicorn).to receive(:listener_names).and_return(tcp_sockets)
end
@@ -71,13 +70,29 @@ describe Gitlab::Metrics::Samplers::UnicornSampler do
it 'updates metrics type unix and with addr' do
labels = { socket_type: 'tcp', socket_address: tcp_socket_address }
- expect(subject).to receive_message_chain(:unicorn_active_connections, :set).with(labels, 'active')
- expect(subject).to receive_message_chain(:unicorn_queued_connections, :set).with(labels, 'queued')
+ expect(subject.metrics[:unicorn_active_connections]).to receive(:set).with(labels, 'active')
+ expect(subject.metrics[:unicorn_queued_connections]).to receive(:set).with(labels, 'queued')
subject.sample
end
end
end
+
+ context 'additional metrics' do
+ let(:unicorn_workers) { 2 }
+
+ before do
+ allow(unicorn).to receive(:listener_names).and_return([""])
+ allow(::Gitlab::Metrics::System).to receive(:cpu_time).and_return(3.14)
+ allow(subject).to receive(:unicorn_workers_count).and_return(unicorn_workers)
+ end
+
+ it "sets additional metrics" do
+ expect(subject.metrics[:unicorn_workers]).to receive(:set).with({}, unicorn_workers)
+
+ subject.sample
+ end
+ end
end
describe '#start' do
diff --git a/spec/lib/gitlab/metrics/system_spec.rb b/spec/lib/gitlab/metrics/system_spec.rb
index 14afcdf5daa..b0603d96eb2 100644
--- a/spec/lib/gitlab/metrics/system_spec.rb
+++ b/spec/lib/gitlab/metrics/system_spec.rb
@@ -13,6 +13,18 @@ describe Gitlab::Metrics::System do
expect(described_class.file_descriptor_count).to be > 0
end
end
+
+ describe '.max_open_file_descriptors' do
+ it 'returns the max allowed open file descriptors' do
+ expect(described_class.max_open_file_descriptors).to be > 0
+ end
+ end
+
+ describe '.process_start_time' do
+ it 'returns the process start time' do
+ expect(described_class.process_start_time).to be > 0
+ end
+ end
else
describe '.memory_usage' do
it 'returns 0.0' do
@@ -25,6 +37,18 @@ describe Gitlab::Metrics::System do
expect(described_class.file_descriptor_count).to eq(0)
end
end
+
+ describe '.max_open_file_descriptors' do
+ it 'returns 0' do
+ expect(described_class.max_open_file_descriptors).to eq(0)
+ end
+ end
+
+ describe 'process_start_time' do
+ it 'returns 0' do
+ expect(described_class.process_start_time).to eq(0)
+ end
+ end
end
describe '.cpu_time' do
diff --git a/spec/lib/gitlab/namespaced_session_store_spec.rb b/spec/lib/gitlab/namespaced_session_store_spec.rb
new file mode 100644
index 00000000000..c0af2ede32a
--- /dev/null
+++ b/spec/lib/gitlab/namespaced_session_store_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::NamespacedSessionStore do
+ let(:key) { :some_key }
+ subject { described_class.new(key) }
+
+ it 'stores data under the specified key' do
+ Gitlab::Session.with_session({}) do
+ subject[:new_data] = 123
+
+ expect(Thread.current[:session_storage][key]).to eq(new_data: 123)
+ end
+ end
+
+ it 'retrieves data from the given key' do
+ Thread.current[:session_storage] = { key => { existing_data: 123 } }
+
+ expect(subject[:existing_data]).to eq 123
+ end
+end
diff --git a/spec/lib/gitlab/omniauth_initializer_spec.rb b/spec/lib/gitlab/omniauth_initializer_spec.rb
index d808b4d49e0..f9c0daf1ef1 100644
--- a/spec/lib/gitlab/omniauth_initializer_spec.rb
+++ b/spec/lib/gitlab/omniauth_initializer_spec.rb
@@ -38,6 +38,28 @@ describe Gitlab::OmniauthInitializer do
subject.execute([hash_config])
end
+ it 'normalizes a String strategy_class' do
+ hash_config = { 'name' => 'hash', 'args' => { strategy_class: 'OmniAuth::Strategies::OAuth2Generic' } }
+
+ expect(devise_config).to receive(:omniauth).with(:hash, strategy_class: OmniAuth::Strategies::OAuth2Generic)
+
+ subject.execute([hash_config])
+ end
+
+ it 'allows a class to be specified in strategy_class' do
+ hash_config = { 'name' => 'hash', 'args' => { strategy_class: OmniAuth::Strategies::OAuth2Generic } }
+
+ expect(devise_config).to receive(:omniauth).with(:hash, strategy_class: OmniAuth::Strategies::OAuth2Generic)
+
+ subject.execute([hash_config])
+ end
+
+ it 'throws an error for an invalid strategy_class' do
+ hash_config = { 'name' => 'hash', 'args' => { strategy_class: 'OmniAuth::Strategies::Bogus' } }
+
+ expect { subject.execute([hash_config]) }.to raise_error(NameError)
+ end
+
it 'configures fail_with_empty_uid for shibboleth' do
shibboleth_config = { 'name' => 'shibboleth', 'args' => {} }
diff --git a/spec/lib/gitlab/path_regex_spec.rb b/spec/lib/gitlab/path_regex_spec.rb
index 857862a2abd..84b2e2dc823 100644
--- a/spec/lib/gitlab/path_regex_spec.rb
+++ b/spec/lib/gitlab/path_regex_spec.rb
@@ -120,10 +120,10 @@ describe Gitlab::PathRegex do
# - Followed by one or more path-parts not starting with `:` or `*`
# - Followed by a path-part that includes a wildcard parameter `*`
# At the time of writing these routes match: http://rubular.com/r/Rv2pDE5Dvw
- STARTING_WITH_NAMESPACE = %r{^/\*namespace_id/:(project_)?id}
- NON_PARAM_PARTS = %r{[^:*][a-z\-_/]*}
- ANY_OTHER_PATH_PART = %r{[a-z\-_/:]*}
- WILDCARD_SEGMENT = /\*/
+ STARTING_WITH_NAMESPACE = %r{^/\*namespace_id/:(project_)?id}.freeze
+ NON_PARAM_PARTS = %r{[^:*][a-z\-_/]*}.freeze
+ ANY_OTHER_PATH_PART = %r{[a-z\-_/:]*}.freeze
+ WILDCARD_SEGMENT = /\*/.freeze
let(:namespaced_wildcard_routes) do
routes_without_format.select do |p|
p =~ %r{#{STARTING_WITH_NAMESPACE}/#{NON_PARAM_PARTS}/#{ANY_OTHER_PATH_PART}#{WILDCARD_SEGMENT}}
@@ -144,7 +144,7 @@ describe Gitlab::PathRegex do
end.uniq
end
- STARTING_WITH_GROUP = %r{^/groups/\*(group_)?id/}
+ STARTING_WITH_GROUP = %r{^/groups/\*(group_)?id/}.freeze
let(:group_routes) do
routes_without_format.select do |path|
path =~ STARTING_WITH_GROUP
diff --git a/spec/lib/gitlab/phabricator_import/base_worker_spec.rb b/spec/lib/gitlab/phabricator_import/base_worker_spec.rb
new file mode 100644
index 00000000000..d46d908a3e3
--- /dev/null
+++ b/spec/lib/gitlab/phabricator_import/base_worker_spec.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Gitlab::PhabricatorImport::BaseWorker do
+ let(:subclass) do
+ # Creating an anonymous class for a worker is complicated, as we generate the
+ # queue name from the class name.
+ Gitlab::PhabricatorImport::ImportTasksWorker
+ end
+
+ describe '.schedule' do
+ let(:arguments) { %w[project_id the_next_page] }
+
+ it 'schedules the job' do
+ expect(subclass).to receive(:perform_async).with(*arguments)
+
+ subclass.schedule(*arguments)
+ end
+
+ it 'counts the scheduled job', :clean_gitlab_redis_shared_state do
+ state = Gitlab::PhabricatorImport::WorkerState.new('project_id')
+
+ allow(subclass).to receive(:remove_job) # otherwise the job is removed before we saw it
+
+ expect { subclass.schedule(*arguments) }.to change { state.running_count }.by(1)
+ end
+ end
+
+ describe '#perform' do
+ let(:project) { create(:project, :import_started, import_url: "https://a.phab.instance") }
+ let(:worker) { subclass.new }
+ let(:state) { Gitlab::PhabricatorImport::WorkerState.new(project.id) }
+
+ before do
+ allow(worker).to receive(:import)
+ end
+
+ it 'does not break for a non-existing project' do
+ expect { worker.perform('not a thing') }.not_to raise_error
+ end
+
+ it 'does not do anything when the import is not in progress' do
+ project = create(:project, :import_failed)
+
+ expect(worker).not_to receive(:import)
+
+ worker.perform(project.id)
+ end
+
+ it 'calls import for the project' do
+ expect(worker).to receive(:import).with(project, 'other_arg')
+
+ worker.perform(project.id, 'other_arg')
+ end
+
+ it 'marks the project as imported if there was only one job running' do
+ worker.perform(project.id)
+
+ expect(project.import_state.reload).to be_finished
+ end
+
+ it 'does not mark the job as finished when there are more scheduled jobs' do
+ 2.times { state.add_job }
+
+ worker.perform(project.id)
+
+ expect(project.import_state.reload).to be_in_progress
+ end
+
+ it 'decrements the job counter' do
+ expect { worker.perform(project.id) }.to change { state.running_count }.by(-1)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/phabricator_import/cache/map_spec.rb b/spec/lib/gitlab/phabricator_import/cache/map_spec.rb
new file mode 100644
index 00000000000..52c7a02219f
--- /dev/null
+++ b/spec/lib/gitlab/phabricator_import/cache/map_spec.rb
@@ -0,0 +1,66 @@
+require 'spec_helper'
+
+describe Gitlab::PhabricatorImport::Cache::Map, :clean_gitlab_redis_cache do
+ set(:project) { create(:project) }
+ let(:redis) { Gitlab::Redis::Cache }
+ subject(:map) { described_class.new(project) }
+
+ describe '#get_gitlab_model' do
+ it 'returns nil if there was nothing cached for the phabricator id' do
+ expect(map.get_gitlab_model('does not exist')).to be_nil
+ end
+
+ it 'returns the object if it was set in redis' do
+ issue = create(:issue, project: project)
+ set_in_redis('exists', issue)
+
+ expect(map.get_gitlab_model('exists')).to eq(issue)
+ end
+
+ it 'extends the TTL for the cache key' do
+ set_in_redis('extend', create(:issue, project: project)) do |redis|
+ redis.expire(cache_key('extend'), 10.seconds.to_i)
+ end
+
+ map.get_gitlab_model('extend')
+
+ ttl = redis.with { |redis| redis.ttl(cache_key('extend')) }
+
+ expect(ttl).to be > 10.seconds
+ end
+ end
+
+ describe '#set_gitlab_model' do
+ around do |example|
+ Timecop.freeze { example.run }
+ end
+
+ it 'sets the class and id in redis with a ttl' do
+ issue = create(:issue, project: project)
+
+ map.set_gitlab_model(issue, 'it is set')
+
+ set_data, ttl = redis.with do |redis|
+ redis.pipelined do |p|
+ p.mapped_hmget(cache_key('it is set'), :classname, :database_id)
+ p.ttl(cache_key('it is set'))
+ end
+ end
+
+ expect(set_data).to eq({ classname: 'Issue', database_id: issue.id.to_s })
+ expect(ttl).to be_within(1.second).of(StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION)
+ end
+ end
+
+ def set_in_redis(key, object)
+ redis.with do |redis|
+ redis.mapped_hmset(cache_key(key),
+ { classname: object.class, database_id: object.id })
+ yield(redis) if block_given?
+ end
+ end
+
+ def cache_key(phabricator_id)
+ subject.__send__(:cache_key_for_phabricator_id, phabricator_id)
+ end
+end
diff --git a/spec/lib/gitlab/phabricator_import/conduit/client_spec.rb b/spec/lib/gitlab/phabricator_import/conduit/client_spec.rb
new file mode 100644
index 00000000000..542b3cd060f
--- /dev/null
+++ b/spec/lib/gitlab/phabricator_import/conduit/client_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Gitlab::PhabricatorImport::Conduit::Client do
+ let(:client) do
+ described_class.new('https://see-ya-later.phabricator', 'api-token')
+ end
+
+ describe '#get' do
+ it 'performs and parses a request' do
+ params = { some: 'extra', values: %w[are passed] }
+ stub_valid_request(params)
+
+ response = client.get('test', params: params)
+
+ expect(response).to be_a(Gitlab::PhabricatorImport::Conduit::Response)
+ expect(response).to be_success
+ end
+
+ it 'wraps request errors in an `ApiError`' do
+ stub_timeout
+
+ expect { client.get('test') }.to raise_error(Gitlab::PhabricatorImport::Conduit::ApiError)
+ end
+
+ it 'raises response error' do
+ stub_error_response
+
+ expect { client.get('test') }
+ .to raise_error(Gitlab::PhabricatorImport::Conduit::ResponseError, /has the wrong length/)
+ end
+ end
+
+ def stub_valid_request(params = {})
+ WebMock.stub_request(
+ :get, 'https://see-ya-later.phabricator/api/test'
+ ).with(
+ body: CGI.unescape(params.reverse_merge('api.token' => 'api-token').to_query)
+ ).and_return(
+ status: 200,
+ body: fixture_file('phabricator_responses/maniphest.search.json')
+ )
+ end
+
+ def stub_timeout
+ WebMock.stub_request(
+ :get, 'https://see-ya-later.phabricator/api/test'
+ ).to_timeout
+ end
+
+ def stub_error_response
+ WebMock.stub_request(
+ :get, 'https://see-ya-later.phabricator/api/test'
+ ).and_return(
+ status: 200,
+ body: fixture_file('phabricator_responses/auth_failed.json')
+ )
+ end
+end
diff --git a/spec/lib/gitlab/phabricator_import/conduit/maniphest_spec.rb b/spec/lib/gitlab/phabricator_import/conduit/maniphest_spec.rb
new file mode 100644
index 00000000000..0d7714649b9
--- /dev/null
+++ b/spec/lib/gitlab/phabricator_import/conduit/maniphest_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Gitlab::PhabricatorImport::Conduit::Maniphest do
+ let(:maniphest) do
+ described_class.new(phabricator_url: 'https://see-ya-later.phabricator', api_token: 'api-token')
+ end
+
+ describe '#tasks' do
+ let(:fake_client) { double('Phabricator client') }
+
+ before do
+ allow(maniphest).to receive(:client).and_return(fake_client)
+ end
+
+ it 'calls the api with the correct params' do
+ expected_params = {
+ after: '123',
+ attachments: {
+ projects: 1, subscribers: 1, columns: 1
+ }
+ }
+
+ expect(fake_client).to receive(:get).with('maniphest.search',
+ params: expected_params)
+
+ maniphest.tasks(after: '123')
+ end
+
+ it 'returns a parsed response' do
+ response = Gitlab::PhabricatorImport::Conduit::Response
+ .new(fixture_file('phabricator_responses/maniphest.search.json'))
+
+ allow(fake_client).to receive(:get).and_return(response)
+
+ expect(maniphest.tasks).to be_a(Gitlab::PhabricatorImport::Conduit::TasksResponse)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/phabricator_import/conduit/response_spec.rb b/spec/lib/gitlab/phabricator_import/conduit/response_spec.rb
new file mode 100644
index 00000000000..a8596968f14
--- /dev/null
+++ b/spec/lib/gitlab/phabricator_import/conduit/response_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Gitlab::PhabricatorImport::Conduit::Response do
+ let(:response) { described_class.new(JSON.parse(fixture_file('phabricator_responses/maniphest.search.json')))}
+ let(:error_response) { described_class.new(JSON.parse(fixture_file('phabricator_responses/auth_failed.json'))) }
+
+ describe '.parse!' do
+ it 'raises a ResponseError if the http response was not successfull' do
+ fake_response = double(:http_response, success?: false, status: 401)
+
+ expect { described_class.parse!(fake_response) }
+ .to raise_error(Gitlab::PhabricatorImport::Conduit::ResponseError, /responded with 401/)
+ end
+
+ it 'raises a ResponseError if the response contained a Phabricator error' do
+ fake_response = double(:http_response,
+ success?: true,
+ status: 200,
+ body: fixture_file('phabricator_responses/auth_failed.json'))
+
+ expect { described_class.parse!(fake_response) }
+ .to raise_error(Gitlab::PhabricatorImport::Conduit::ResponseError, /ERR-INVALID-AUTH: API token/)
+ end
+
+ it 'raises a ResponseError if JSON parsing failed' do
+ fake_response = double(:http_response,
+ success?: true,
+ status: 200,
+ body: 'This is no JSON')
+
+ expect { described_class.parse!(fake_response) }
+ .to raise_error(Gitlab::PhabricatorImport::Conduit::ResponseError, /unexpected token at/)
+ end
+
+ it 'returns a parsed response for valid input' do
+ fake_response = double(:http_response,
+ success?: true,
+ status: 200,
+ body: fixture_file('phabricator_responses/maniphest.search.json'))
+
+ expect(described_class.parse!(fake_response)).to be_a(described_class)
+ end
+ end
+
+ describe '#success?' do
+ it { expect(response).to be_success }
+ it { expect(error_response).not_to be_success }
+ end
+
+ describe '#error_code' do
+ it { expect(error_response.error_code).to eq('ERR-INVALID-AUTH') }
+ it { expect(response.error_code).to be_nil }
+ end
+
+ describe '#error_info' do
+ it 'returns the correct error info' do
+ expected_message = 'API token "api-token" has the wrong length. API tokens should be 32 characters long.'
+
+ expect(error_response.error_info).to eq(expected_message)
+ end
+
+ it { expect(response.error_info).to be_nil }
+ end
+
+ describe '#data' do
+ it { expect(error_response.data).to be_nil }
+ it { expect(response.data).to be_an(Array) }
+ end
+
+ describe '#pagination' do
+ it { expect(error_response.pagination).to be_nil }
+
+ it 'builds the pagination correctly' do
+ expect(response.pagination).to be_a(Gitlab::PhabricatorImport::Conduit::Pagination)
+ expect(response.pagination.next_page).to eq('284')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/phabricator_import/conduit/tasks_response_spec.rb b/spec/lib/gitlab/phabricator_import/conduit/tasks_response_spec.rb
new file mode 100644
index 00000000000..4b4c2a6276e
--- /dev/null
+++ b/spec/lib/gitlab/phabricator_import/conduit/tasks_response_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Gitlab::PhabricatorImport::Conduit::TasksResponse do
+ let(:conduit_response) do
+ Gitlab::PhabricatorImport::Conduit::Response
+ .new(JSON.parse(fixture_file('phabricator_responses/maniphest.search.json')))
+ end
+
+ subject(:response) { described_class.new(conduit_response) }
+
+ describe '#pagination' do
+ it 'delegates to the conduit reponse' do
+ expect(response.pagination).to eq(conduit_response.pagination)
+ end
+ end
+
+ describe '#tasks' do
+ it 'builds the correct tasks representation' do
+ tasks = response.tasks
+
+ titles = tasks.map(&:issue_attributes).map { |attrs| attrs[:title] }
+
+ expect(titles).to contain_exactly('Things are slow', 'Things are broken')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/phabricator_import/import_tasks_worker_spec.rb b/spec/lib/gitlab/phabricator_import/import_tasks_worker_spec.rb
new file mode 100644
index 00000000000..1e38ef8aaa5
--- /dev/null
+++ b/spec/lib/gitlab/phabricator_import/import_tasks_worker_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Gitlab::PhabricatorImport::ImportTasksWorker do
+ describe '#perform' do
+ it 'calls the correct importer' do
+ project = create(:project, :import_started, import_url: "https://the.phab.ulr")
+ fake_importer = instance_double(Gitlab::PhabricatorImport::Issues::Importer)
+
+ expect(Gitlab::PhabricatorImport::Issues::Importer).to receive(:new).with(project).and_return(fake_importer)
+ expect(fake_importer).to receive(:execute)
+
+ described_class.new.perform(project.id)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/phabricator_import/importer_spec.rb b/spec/lib/gitlab/phabricator_import/importer_spec.rb
new file mode 100644
index 00000000000..bf14010a187
--- /dev/null
+++ b/spec/lib/gitlab/phabricator_import/importer_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe Gitlab::PhabricatorImport::Importer do
+ it { expect(described_class).to be_async }
+
+ it "acts like it's importing repositories" do
+ expect(described_class).to be_imports_repository
+ end
+
+ describe '#execute' do
+ let(:project) { create(:project, :import_scheduled) }
+ subject(:importer) { described_class.new(project) }
+
+ it 'sets a custom jid that will be kept up to date' do
+ expect { importer.execute }.to change { project.import_state.reload.jid }
+ end
+
+ it 'starts importing tasks' do
+ expect(Gitlab::PhabricatorImport::ImportTasksWorker).to receive(:schedule).with(project.id)
+
+ importer.execute
+ end
+
+ it 'marks the import as failed when something goes wrong' do
+ allow(importer).to receive(:schedule_first_tasks_page).and_raise('Stuff is broken')
+
+ importer.execute
+
+ expect(project.import_state).to be_failed
+ end
+ end
+end
diff --git a/spec/lib/gitlab/phabricator_import/issues/importer_spec.rb b/spec/lib/gitlab/phabricator_import/issues/importer_spec.rb
new file mode 100644
index 00000000000..2412cf76f79
--- /dev/null
+++ b/spec/lib/gitlab/phabricator_import/issues/importer_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Gitlab::PhabricatorImport::Issues::Importer do
+ set(:project) { create(:project) }
+
+ let(:response) do
+ Gitlab::PhabricatorImport::Conduit::TasksResponse.new(
+ Gitlab::PhabricatorImport::Conduit::Response
+ .new(JSON.parse(fixture_file('phabricator_responses/maniphest.search.json')))
+ )
+ end
+
+ subject(:importer) { described_class.new(project, nil) }
+
+ before do
+ client = instance_double(Gitlab::PhabricatorImport::Conduit::Maniphest)
+
+ allow(client).to receive(:tasks).and_return(response)
+ allow(importer).to receive(:client).and_return(client)
+ end
+
+ describe '#execute' do
+ it 'imports each task in the response' do
+ response.tasks.each do |task|
+ task_importer = instance_double(Gitlab::PhabricatorImport::Issues::TaskImporter)
+
+ expect(task_importer).to receive(:execute)
+ expect(Gitlab::PhabricatorImport::Issues::TaskImporter)
+ .to receive(:new).with(project, task)
+ .and_return(task_importer)
+ end
+
+ importer.execute
+ end
+
+ it 'schedules the next batch if there is one' do
+ expect(Gitlab::PhabricatorImport::ImportTasksWorker)
+ .to receive(:schedule).with(project.id, response.pagination.next_page)
+
+ importer.execute
+ end
+
+ it 'does not reschedule when there is no next page' do
+ allow(response.pagination).to receive(:has_next_page?).and_return(false)
+
+ expect(Gitlab::PhabricatorImport::ImportTasksWorker)
+ .not_to receive(:schedule)
+
+ importer.execute
+ end
+ end
+end
diff --git a/spec/lib/gitlab/phabricator_import/issues/task_importer_spec.rb b/spec/lib/gitlab/phabricator_import/issues/task_importer_spec.rb
new file mode 100644
index 00000000000..1625604e754
--- /dev/null
+++ b/spec/lib/gitlab/phabricator_import/issues/task_importer_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Gitlab::PhabricatorImport::Issues::TaskImporter do
+ set(:project) { create(:project) }
+ let(:task) do
+ Gitlab::PhabricatorImport::Representation::Task.new(
+ {
+ 'phid' => 'the-phid',
+ 'fields' => {
+ 'name' => 'Title',
+ 'description' => {
+ 'raw' => '# This is markdown\n it can contain more text.'
+ },
+ 'dateCreated' => '1518688921',
+ 'dateClosed' => '1518789995'
+ }
+ }
+ )
+ end
+
+ describe '#execute' do
+ it 'creates the issue with the expected attributes' do
+ issue = described_class.new(project, task).execute
+
+ expect(issue.project).to eq(project)
+ expect(issue).to be_persisted
+ expect(issue.author).to eq(User.ghost)
+ expect(issue.title).to eq('Title')
+ expect(issue.description).to eq('# This is markdown\n it can contain more text.')
+ expect(issue).to be_closed
+ expect(issue.created_at).to eq(Time.at(1518688921))
+ expect(issue.closed_at).to eq(Time.at(1518789995))
+ end
+
+ it 'does not recreate the issue when called multiple times' do
+ expect { described_class.new(project, task).execute }
+ .to change { project.issues.reload.size }.from(0).to(1)
+ expect { described_class.new(project, task).execute }
+ .not_to change { project.issues.reload.size }
+ end
+
+ it 'does not trigger a save when the object did not change' do
+ existing_issue = create(:issue,
+ task.issue_attributes.merge(author: User.ghost))
+ importer = described_class.new(project, task)
+ allow(importer).to receive(:issue).and_return(existing_issue)
+
+ expect(existing_issue).not_to receive(:save!)
+
+ importer.execute
+ end
+ end
+end
diff --git a/spec/lib/gitlab/phabricator_import/project_creator_spec.rb b/spec/lib/gitlab/phabricator_import/project_creator_spec.rb
new file mode 100644
index 00000000000..e9455b866ac
--- /dev/null
+++ b/spec/lib/gitlab/phabricator_import/project_creator_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Gitlab::PhabricatorImport::ProjectCreator do
+ let(:user) { create(:user) }
+ let(:params) do
+ { path: 'new-phab-import',
+ phabricator_server_url: 'http://phab.example.com',
+ api_token: 'the-token' }
+ end
+ subject(:creator) { described_class.new(user, params) }
+
+ describe '#execute' do
+ it 'creates a project correctly and schedule an import' do
+ expect_next_instance_of(Gitlab::PhabricatorImport::Importer) do |importer|
+ expect(importer).to receive(:execute)
+ end
+
+ project = creator.execute
+
+ expect(project).to be_persisted
+ expect(project).to be_import
+ expect(project.import_type).to eq('phabricator')
+ expect(project.import_data.credentials).to match(a_hash_including(api_token: 'the-token'))
+ expect(project.import_data.data).to match(a_hash_including('phabricator_url' => 'http://phab.example.com'))
+ expect(project.import_url).to eq(Project::UNKNOWN_IMPORT_URL)
+ expect(project.namespace).to eq(user.namespace)
+ end
+
+ context 'when import params are missing' do
+ let(:params) do
+ { path: 'new-phab-import',
+ phabricator_server_url: 'http://phab.example.com',
+ api_token: '' }
+ end
+
+ it 'returns nil' do
+ expect(creator.execute).to be_nil
+ end
+ end
+
+ context 'when import params are invalid' do
+ let(:params) do
+ { path: 'new-phab-import',
+ namespace_id: '-1',
+ phabricator_server_url: 'http://phab.example.com',
+ api_token: 'the-token' }
+ end
+
+ it 'returns an unpersisted project' do
+ project = creator.execute
+
+ expect(project).not_to be_persisted
+ expect(project).not_to be_valid
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/phabricator_import/representation/task_spec.rb b/spec/lib/gitlab/phabricator_import/representation/task_spec.rb
new file mode 100644
index 00000000000..dfbd8c546eb
--- /dev/null
+++ b/spec/lib/gitlab/phabricator_import/representation/task_spec.rb
@@ -0,0 +1,33 @@
+require 'spec_helper'
+
+describe Gitlab::PhabricatorImport::Representation::Task do
+ subject(:task) do
+ described_class.new(
+ {
+ 'phid' => 'the-phid',
+ 'fields' => {
+ 'name' => 'Title'.ljust(257, '.'), # A string padded to 257 chars
+ 'description' => {
+ 'raw' => '# This is markdown\n it can contain more text.'
+ },
+ 'dateCreated' => '1518688921',
+ 'dateClosed' => '1518789995'
+ }
+ }
+ )
+ end
+
+ describe '#issue_attributes' do
+ it 'contains the expected values' do
+ expected_attributes = {
+ title: 'Title'.ljust(255, '.'),
+ description: '# This is markdown\n it can contain more text.',
+ state: :closed,
+ created_at: Time.at(1518688921),
+ closed_at: Time.at(1518789995)
+ }
+
+ expect(task.issue_attributes).to eq(expected_attributes)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/phabricator_import/worker_state_spec.rb b/spec/lib/gitlab/phabricator_import/worker_state_spec.rb
new file mode 100644
index 00000000000..a44947445c9
--- /dev/null
+++ b/spec/lib/gitlab/phabricator_import/worker_state_spec.rb
@@ -0,0 +1,46 @@
+require 'spec_helper'
+
+describe Gitlab::PhabricatorImport::WorkerState, :clean_gitlab_redis_shared_state do
+ subject(:state) { described_class.new('weird-project-id') }
+ let(:key) { 'phabricator-import/jobs/project-weird-project-id/job-count' }
+
+ describe '#add_job' do
+ it 'increments the counter for jobs' do
+ set_value(3)
+
+ expect { state.add_job }.to change { get_value }.from('3').to('4')
+ end
+ end
+
+ describe '#remove_job' do
+ it 'decrements the counter for jobs' do
+ set_value(3)
+
+ expect { state.remove_job }.to change { get_value }.from('3').to('2')
+ end
+ end
+
+ describe '#running_count' do
+ it 'reads the value' do
+ set_value(9)
+
+ expect(state.running_count).to eq(9)
+ end
+
+ it 'returns 0 when nothing was set' do
+ expect(state.running_count).to eq(0)
+ end
+ end
+
+ def set_value(value)
+ redis.with { |r| r.set(key, value) }
+ end
+
+ def get_value
+ redis.with { |r| r.get(key) }
+ end
+
+ def redis
+ Gitlab::Redis::SharedState
+ end
+end
diff --git a/spec/lib/gitlab/profiler_spec.rb b/spec/lib/gitlab/profiler_spec.rb
index 9f2214f7ce7..5af52db7a1f 100644
--- a/spec/lib/gitlab/profiler_spec.rb
+++ b/spec/lib/gitlab/profiler_spec.rb
@@ -27,13 +27,13 @@ describe Gitlab::Profiler do
it 'sends a POST request when data is passed' do
post_data = '{"a":1}'
- expect(app).to receive(:post).with(anything, post_data, anything)
+ expect(app).to receive(:post).with(anything, params: post_data, headers: anything)
described_class.profile('/', post_data: post_data)
end
it 'uses the private_token for auth if given' do
- expect(app).to receive(:get).with('/', nil, 'Private-Token' => private_token)
+ expect(app).to receive(:get).with('/', params: nil, headers: { 'Private-Token' => private_token })
expect(app).to receive(:get).with('/api/v4/users')
described_class.profile('/', private_token: private_token)
@@ -51,7 +51,7 @@ describe Gitlab::Profiler do
user = double(:user)
expect(described_class).to receive(:with_user).with(nil).and_call_original
- expect(app).to receive(:get).with('/', nil, 'Private-Token' => private_token)
+ expect(app).to receive(:get).with('/', params: nil, headers: { 'Private-Token' => private_token })
expect(app).to receive(:get).with('/api/v4/users')
described_class.profile('/', user: user, private_token: private_token)
diff --git a/spec/lib/gitlab/prometheus/query_variables_spec.rb b/spec/lib/gitlab/prometheus/query_variables_spec.rb
index 78c74266c61..6dc99ef26ec 100644
--- a/spec/lib/gitlab/prometheus/query_variables_spec.rb
+++ b/spec/lib/gitlab/prometheus/query_variables_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
describe Gitlab::Prometheus::QueryVariables do
describe '.call' do
+ let(:project) { environment.project }
let(:environment) { create(:environment) }
let(:slug) { environment.slug }
@@ -21,13 +22,32 @@ describe Gitlab::Prometheus::QueryVariables do
end
context 'with deployment platform' do
- let(:kube_namespace) { environment.deployment_platform.actual_namespace }
+ context 'with project cluster' do
+ let(:kube_namespace) { environment.deployment_platform.cluster.kubernetes_namespace_for(project) }
- before do
- create(:cluster, :provided_by_user, projects: [environment.project])
+ before do
+ create(:cluster, :project, :provided_by_user, projects: [project])
+ end
+
+ it { is_expected.to include(kube_namespace: kube_namespace) }
end
- it { is_expected.to include(kube_namespace: kube_namespace) }
+ context 'with group cluster' do
+ let(:cluster) { create(:cluster, :group, :provided_by_user, groups: [group]) }
+ let(:group) { create(:group) }
+ let(:project2) { create(:project) }
+ let(:kube_namespace) { k8s_ns.namespace }
+
+ let!(:k8s_ns) { create(:cluster_kubernetes_namespace, cluster: cluster, project: project) }
+ let!(:k8s_ns2) { create(:cluster_kubernetes_namespace, cluster: cluster, project: project2) }
+
+ before do
+ group.projects << project
+ group.projects << project2
+ end
+
+ it { is_expected.to include(kube_namespace: kube_namespace) }
+ end
end
end
end
diff --git a/spec/lib/gitlab/search_results_spec.rb b/spec/lib/gitlab/search_results_spec.rb
index 312aa3be490..3d27156b356 100644
--- a/spec/lib/gitlab/search_results_spec.rb
+++ b/spec/lib/gitlab/search_results_spec.rb
@@ -256,4 +256,28 @@ describe Gitlab::SearchResults do
expect(results.objects('merge_requests')).not_to include merge_request
end
+
+ context 'milestones' do
+ it 'returns correct set of milestones' do
+ private_project_1 = create(:project, :private)
+ private_project_2 = create(:project, :private)
+ internal_project = create(:project, :internal)
+ public_project_1 = create(:project, :public)
+ public_project_2 = create(:project, :public, :issues_disabled, :merge_requests_disabled)
+ private_project_1.add_developer(user)
+ # milestones that should not be visible
+ create(:milestone, project: private_project_2, title: 'Private project without access milestone')
+ create(:milestone, project: public_project_2, title: 'Public project with milestones disabled milestone')
+ # milestones that should be visible
+ milestone_1 = create(:milestone, project: private_project_1, title: 'Private project with access milestone', state: 'closed')
+ milestone_2 = create(:milestone, project: internal_project, title: 'Internal project milestone')
+ milestone_3 = create(:milestone, project: public_project_1, title: 'Public project with milestones enabled milestone')
+ # Global search scope takes user authorized projects, internal projects and public projects.
+ limit_projects = ProjectsFinder.new(current_user: user).execute
+
+ milestones = described_class.new(user, limit_projects, 'milestone').objects('milestones')
+
+ expect(milestones).to match_array([milestone_1, milestone_2, milestone_3])
+ end
+ end
end
diff --git a/spec/lib/gitlab/sentry_spec.rb b/spec/lib/gitlab/sentry_spec.rb
index 1128eaf8560..af8b059b984 100644
--- a/spec/lib/gitlab/sentry_spec.rb
+++ b/spec/lib/gitlab/sentry_spec.rb
@@ -2,12 +2,15 @@ require 'spec_helper'
describe Gitlab::Sentry do
describe '.context' do
- it 'adds the locale to the tags' do
+ it 'adds the expected tags' do
expect(described_class).to receive(:enabled?).and_return(true)
+ allow(Labkit::Correlation::CorrelationId).to receive(:current_id).and_return('cid')
described_class.context(nil)
expect(Raven.tags_context[:locale].to_s).to eq(I18n.locale.to_s)
+ expect(Raven.tags_context[Labkit::Correlation::CorrelationId::LOG_KEY.to_sym].to_s)
+ .to eq('cid')
end
end
@@ -27,7 +30,7 @@ describe Gitlab::Sentry do
context 'when exceptions should not be raised' do
before do
allow(described_class).to receive(:should_raise_for_dev?).and_return(false)
- allow(Gitlab::CorrelationId).to receive(:current_id).and_return('cid')
+ allow(Labkit::Correlation::CorrelationId).to receive(:current_id).and_return('cid')
end
it 'logs the exception with all attributes passed' do
@@ -65,7 +68,7 @@ describe Gitlab::Sentry do
before do
allow(described_class).to receive(:enabled?).and_return(true)
- allow(Gitlab::CorrelationId).to receive(:current_id).and_return('cid')
+ allow(Labkit::Correlation::CorrelationId).to receive(:current_id).and_return('cid')
end
it 'calls Raven.capture_exception' do
diff --git a/spec/lib/gitlab/session_spec.rb b/spec/lib/gitlab/session_spec.rb
new file mode 100644
index 00000000000..8db73f0ec7b
--- /dev/null
+++ b/spec/lib/gitlab/session_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Session do
+ it 'uses the current thread as a data store' do
+ Thread.current[:session_storage] = { a: :b }
+
+ expect(described_class.current).to eq(a: :b)
+ ensure
+ Thread.current[:session_storage] = nil
+ end
+
+ describe '#with_session' do
+ it 'sets session hash' do
+ described_class.with_session(one: 1) do
+ expect(described_class.current).to eq(one: 1)
+ end
+ end
+
+ it 'restores current store after' do
+ described_class.with_session(two: 2) { }
+
+ expect(described_class.current).to eq nil
+ end
+ end
+end
diff --git a/spec/lib/gitlab/shell_spec.rb b/spec/lib/gitlab/shell_spec.rb
index e2f09de2808..bce2e754176 100644
--- a/spec/lib/gitlab/shell_spec.rb
+++ b/spec/lib/gitlab/shell_spec.rb
@@ -612,16 +612,6 @@ describe Gitlab::Shell do
FileUtils.rm_rf(created_path)
end
- it 'creates a repository' do
- expect(gitlab_shell.create_repository(repository_storage, repo_name, repo_name)).to be_truthy
-
- expect(File.stat(created_path).mode & 0o777).to eq(0o770)
-
- hooks_path = File.join(created_path, 'hooks')
- expect(File.lstat(hooks_path)).to be_symlink
- expect(File.realpath(hooks_path)).to eq(gitlab_shell_hooks_path)
- end
-
it 'returns false when the command fails' do
FileUtils.mkdir_p(File.dirname(created_path))
# This file will block the creation of the repo's .git directory. That
diff --git a/spec/lib/gitlab/sidekiq_middleware/correlation_injector_spec.rb b/spec/lib/gitlab/sidekiq_middleware/correlation_injector_spec.rb
index a138ad7c910..0ff694d409b 100644
--- a/spec/lib/gitlab/sidekiq_middleware/correlation_injector_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/correlation_injector_spec.rb
@@ -30,7 +30,7 @@ describe Gitlab::SidekiqMiddleware::CorrelationInjector do
it 'injects into payload the correlation id' do
expect_any_instance_of(described_class).to receive(:call).and_call_original
- Gitlab::CorrelationId.use_id('new-correlation-id') do
+ Labkit::Correlation::CorrelationId.use_id('new-correlation-id') do
TestWorker.perform_async(1234)
end
diff --git a/spec/lib/gitlab/sidekiq_middleware/correlation_logger_spec.rb b/spec/lib/gitlab/sidekiq_middleware/correlation_logger_spec.rb
index 94ae4ffa184..8410467ef1f 100644
--- a/spec/lib/gitlab/sidekiq_middleware/correlation_logger_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/correlation_logger_spec.rb
@@ -23,7 +23,7 @@ describe Gitlab::SidekiqMiddleware::CorrelationLogger do
expect_any_instance_of(described_class).to receive(:call).and_call_original
expect_any_instance_of(TestWorker).to receive(:perform).with(1234) do
- expect(Gitlab::CorrelationId.current_id).to eq('new-correlation-id')
+ expect(Labkit::Correlation::CorrelationId.current_id).to eq('new-correlation-id')
end
Sidekiq::Client.push(
diff --git a/spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb b/spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb
index fe46c67a920..5f0a7e925ca 100644
--- a/spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb
+++ b/spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb
@@ -15,6 +15,13 @@ describe Gitlab::Template::GitlabCiYmlTemplate do
expect(all).to include('Docker')
expect(all).to include('Ruby')
end
+
+ it 'ensure that the template name is used exactly once' do
+ all = subject.all.group_by(&:name)
+ duplicates = all.select { |_, templates| templates.length > 1 }
+
+ expect(duplicates).to be_empty
+ end
end
describe '.find' do
diff --git a/spec/lib/gitlab/tracing/factory_spec.rb b/spec/lib/gitlab/tracing/factory_spec.rb
deleted file mode 100644
index 945490f0988..00000000000
--- a/spec/lib/gitlab/tracing/factory_spec.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-
-describe Gitlab::Tracing::Factory do
- describe '.create_tracer' do
- let(:service_name) { 'rspec' }
-
- context "when tracing is not configured" do
- it 'ignores null connection strings' do
- expect(described_class.create_tracer(service_name, nil)).to be_nil
- end
-
- it 'ignores empty connection strings' do
- expect(described_class.create_tracer(service_name, '')).to be_nil
- end
-
- it 'ignores unknown implementations' do
- expect(described_class.create_tracer(service_name, 'opentracing://invalid_driver')).to be_nil
- end
-
- it 'ignores invalid connection strings' do
- expect(described_class.create_tracer(service_name, 'open?tracing')).to be_nil
- end
- end
-
- context "when tracing is configured with jaeger" do
- let(:mock_tracer) { double('tracer') }
-
- it 'processes default connections' do
- expect(Gitlab::Tracing::JaegerFactory).to receive(:create_tracer).with(service_name, {}).and_return(mock_tracer)
-
- expect(described_class.create_tracer(service_name, 'opentracing://jaeger')).to be(mock_tracer)
- end
-
- it 'processes connections with parameters' do
- expect(Gitlab::Tracing::JaegerFactory).to receive(:create_tracer).with(service_name, { a: '1', b: '2', c: '3' }).and_return(mock_tracer)
-
- expect(described_class.create_tracer(service_name, 'opentracing://jaeger?a=1&b=2&c=3')).to be(mock_tracer)
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/tracing/grpc_interceptor_spec.rb b/spec/lib/gitlab/tracing/grpc_interceptor_spec.rb
deleted file mode 100644
index 7f5aecb7baa..00000000000
--- a/spec/lib/gitlab/tracing/grpc_interceptor_spec.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-
-describe Gitlab::Tracing::GRPCInterceptor do
- subject { described_class.instance }
-
- shared_examples_for "a grpc interceptor method" do
- let(:custom_error) { Class.new(StandardError) }
-
- it 'yields' do
- expect { |b| method.call(kwargs, &b) }.to yield_control
- end
-
- it 'propagates exceptions' do
- expect { method.call(kwargs) { raise custom_error } }.to raise_error(custom_error)
- end
- end
-
- describe '#request_response' do
- let(:method) { subject.method(:request_response) }
- let(:kwargs) { { request: {}, call: {}, method: 'grc_method', metadata: {} } }
-
- it_behaves_like 'a grpc interceptor method'
- end
-
- describe '#client_streamer' do
- let(:method) { subject.method(:client_streamer) }
- let(:kwargs) { { requests: [], call: {}, method: 'grc_method', metadata: {} } }
-
- it_behaves_like 'a grpc interceptor method'
- end
-
- describe '#server_streamer' do
- let(:method) { subject.method(:server_streamer) }
- let(:kwargs) { { request: {}, call: {}, method: 'grc_method', metadata: {} } }
-
- it_behaves_like 'a grpc interceptor method'
- end
-
- describe '#bidi_streamer' do
- let(:method) { subject.method(:bidi_streamer) }
- let(:kwargs) { { requests: [], call: {}, method: 'grc_method', metadata: {} } }
-
- it_behaves_like 'a grpc interceptor method'
- end
-end
diff --git a/spec/lib/gitlab/tracing/jaeger_factory_spec.rb b/spec/lib/gitlab/tracing/jaeger_factory_spec.rb
deleted file mode 100644
index 3d6a007cfd9..00000000000
--- a/spec/lib/gitlab/tracing/jaeger_factory_spec.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-
-describe Gitlab::Tracing::JaegerFactory do
- describe '.create_tracer' do
- let(:service_name) { 'rspec' }
-
- shared_examples_for 'a jaeger tracer' do
- it 'responds to active_span methods' do
- expect(tracer).to respond_to(:active_span)
- end
-
- it 'yields control' do
- expect { |b| tracer.start_active_span('operation_name', &b) }.to yield_control
- end
- end
-
- context 'processes default connections' do
- it_behaves_like 'a jaeger tracer' do
- let(:tracer) { described_class.create_tracer(service_name, {}) }
- end
- end
-
- context 'handles debug options' do
- it_behaves_like 'a jaeger tracer' do
- let(:tracer) { described_class.create_tracer(service_name, { debug: "1" }) }
- end
- end
-
- context 'handles const sampler' do
- it_behaves_like 'a jaeger tracer' do
- let(:tracer) { described_class.create_tracer(service_name, { sampler: "const", sampler_param: "1" }) }
- end
- end
-
- context 'handles probabilistic sampler' do
- it_behaves_like 'a jaeger tracer' do
- let(:tracer) { described_class.create_tracer(service_name, { sampler: "probabilistic", sampler_param: "0.5" }) }
- end
- end
-
- context 'handles http_endpoint configurations' do
- it_behaves_like 'a jaeger tracer' do
- let(:tracer) { described_class.create_tracer(service_name, { http_endpoint: "http://localhost:1234" }) }
- end
- end
-
- context 'handles udp_endpoint configurations' do
- it_behaves_like 'a jaeger tracer' do
- let(:tracer) { described_class.create_tracer(service_name, { udp_endpoint: "localhost:4321" }) }
- end
- end
-
- context 'ignores invalid parameters' do
- it_behaves_like 'a jaeger tracer' do
- let(:tracer) { described_class.create_tracer(service_name, { invalid: "true" }) }
- end
- end
-
- context 'accepts the debug parameter when strict_parser is set' do
- it_behaves_like 'a jaeger tracer' do
- let(:tracer) { described_class.create_tracer(service_name, { debug: "1", strict_parsing: "1" }) }
- end
- end
-
- it 'rejects invalid parameters when strict_parser is set' do
- expect { described_class.create_tracer(service_name, { invalid: "true", strict_parsing: "1" }) }.to raise_error(StandardError)
- end
- end
-end
diff --git a/spec/lib/gitlab/tracing/rack_middleware_spec.rb b/spec/lib/gitlab/tracing/rack_middleware_spec.rb
deleted file mode 100644
index 13d4d8a89f7..00000000000
--- a/spec/lib/gitlab/tracing/rack_middleware_spec.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe Gitlab::Tracing::RackMiddleware do
- using RSpec::Parameterized::TableSyntax
-
- describe '#call' do
- context 'for normal middleware flow' do
- let(:fake_app) { -> (env) { fake_app_response } }
- subject { described_class.new(fake_app) }
- let(:request) { }
-
- context 'for 200 responses' do
- let(:fake_app_response) { [200, { 'Content-Type': 'text/plain' }, ['OK']] }
-
- it 'delegates correctly' do
- expect(subject.call(Rack::MockRequest.env_for("/"))).to eq(fake_app_response)
- end
- end
-
- context 'for 500 responses' do
- let(:fake_app_response) { [500, { 'Content-Type': 'text/plain' }, ['Error']] }
-
- it 'delegates correctly' do
- expect(subject.call(Rack::MockRequest.env_for("/"))).to eq(fake_app_response)
- end
- end
- end
-
- context 'when an application is raising an exception' do
- let(:custom_error) { Class.new(StandardError) }
- let(:fake_app) { ->(env) { raise custom_error } }
-
- subject { described_class.new(fake_app) }
-
- it 'delegates propagates exceptions correctly' do
- expect { subject.call(Rack::MockRequest.env_for("/")) }.to raise_error(custom_error)
- end
- end
- end
-
- describe '.build_sanitized_url_from_env' do
- def env_for_url(url)
- env = Rack::MockRequest.env_for(input_url)
- env['action_dispatch.parameter_filter'] = [/token/]
-
- env
- end
-
- where(:input_url, :output_url) do
- '/gitlab-org/gitlab-ce' | 'http://example.org/gitlab-org/gitlab-ce'
- '/gitlab-org/gitlab-ce?safe=1' | 'http://example.org/gitlab-org/gitlab-ce?safe=1'
- '/gitlab-org/gitlab-ce?private_token=secret' | 'http://example.org/gitlab-org/gitlab-ce?private_token=%5BFILTERED%5D'
- '/gitlab-org/gitlab-ce?mixed=1&private_token=secret' | 'http://example.org/gitlab-org/gitlab-ce?mixed=1&private_token=%5BFILTERED%5D'
- end
-
- with_them do
- it { expect(described_class.build_sanitized_url_from_env(env_for_url(input_url))).to eq(output_url) }
- end
- end
-end
diff --git a/spec/lib/gitlab/tracing/rails/action_view_subscriber_spec.rb b/spec/lib/gitlab/tracing/rails/action_view_subscriber_spec.rb
deleted file mode 100644
index 0bbaf5968ed..00000000000
--- a/spec/lib/gitlab/tracing/rails/action_view_subscriber_spec.rb
+++ /dev/null
@@ -1,147 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-require 'rspec-parameterized'
-
-describe Gitlab::Tracing::Rails::ActionViewSubscriber do
- using RSpec::Parameterized::TableSyntax
-
- shared_examples 'an actionview notification' do
- it 'notifies the tracer when the hash contains null values' do
- expect(subject).to receive(:postnotify_span).with(notification_name, start, finish, tags: expected_tags, exception: exception)
-
- subject.public_send(notify_method, start, finish, payload)
- end
-
- it 'notifies the tracer when the payload is missing values' do
- expect(subject).to receive(:postnotify_span).with(notification_name, start, finish, tags: expected_tags, exception: exception)
-
- subject.public_send(notify_method, start, finish, payload.compact)
- end
-
- it 'does not throw exceptions when with the default tracer' do
- expect { subject.public_send(notify_method, start, finish, payload) }.not_to raise_error
- end
- end
-
- describe '.instrument' do
- it 'is unsubscribeable' do
- unsubscribe = described_class.instrument
-
- expect(unsubscribe).not_to be_nil
- expect { unsubscribe.call }.not_to raise_error
- end
- end
-
- describe '#notify_render_template' do
- subject { described_class.new }
- let(:start) { Time.now }
- let(:finish) { Time.now }
- let(:notification_name) { 'render_template' }
- let(:notify_method) { :notify_render_template }
-
- where(:identifier, :layout, :exception) do
- nil | nil | nil
- "" | nil | nil
- "show.haml" | nil | nil
- nil | "" | nil
- nil | "layout.haml" | nil
- nil | nil | StandardError.new
- end
-
- with_them do
- let(:payload) do
- {
- exception: exception,
- identifier: identifier,
- layout: layout
- }
- end
-
- let(:expected_tags) do
- {
- 'component' => 'ActionView',
- 'template.id' => identifier,
- 'template.layout' => layout
- }
- end
-
- it_behaves_like 'an actionview notification'
- end
- end
-
- describe '#notify_render_collection' do
- subject { described_class.new }
- let(:start) { Time.now }
- let(:finish) { Time.now }
- let(:notification_name) { 'render_collection' }
- let(:notify_method) { :notify_render_collection }
-
- where(
- :identifier, :count, :expected_count, :cache_hits, :expected_cache_hits, :exception) do
- nil | nil | 0 | nil | 0 | nil
- "" | nil | 0 | nil | 0 | nil
- "show.haml" | nil | 0 | nil | 0 | nil
- nil | 0 | 0 | nil | 0 | nil
- nil | 1 | 1 | nil | 0 | nil
- nil | nil | 0 | 0 | 0 | nil
- nil | nil | 0 | 1 | 1 | nil
- nil | nil | 0 | nil | 0 | StandardError.new
- end
-
- with_them do
- let(:payload) do
- {
- exception: exception,
- identifier: identifier,
- count: count,
- cache_hits: cache_hits
- }
- end
-
- let(:expected_tags) do
- {
- 'component' => 'ActionView',
- 'template.id' => identifier,
- 'template.count' => expected_count,
- 'template.cache.hits' => expected_cache_hits
- }
- end
-
- it_behaves_like 'an actionview notification'
- end
- end
-
- describe '#notify_render_partial' do
- subject { described_class.new }
- let(:start) { Time.now }
- let(:finish) { Time.now }
- let(:notification_name) { 'render_partial' }
- let(:notify_method) { :notify_render_partial }
-
- where(:identifier, :exception) do
- nil | nil
- "" | nil
- "show.haml" | nil
- nil | StandardError.new
- end
-
- with_them do
- let(:payload) do
- {
- exception: exception,
- identifier: identifier
- }
- end
-
- let(:expected_tags) do
- {
- 'component' => 'ActionView',
- 'template.id' => identifier
- }
- end
-
- it_behaves_like 'an actionview notification'
- end
- end
-end
diff --git a/spec/lib/gitlab/tracing/rails/active_record_subscriber_spec.rb b/spec/lib/gitlab/tracing/rails/active_record_subscriber_spec.rb
deleted file mode 100644
index 7bd0875fa68..00000000000
--- a/spec/lib/gitlab/tracing/rails/active_record_subscriber_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-require 'rspec-parameterized'
-
-describe Gitlab::Tracing::Rails::ActiveRecordSubscriber do
- using RSpec::Parameterized::TableSyntax
-
- describe '.instrument' do
- it 'is unsubscribeable' do
- unsubscribe = described_class.instrument
-
- expect(unsubscribe).not_to be_nil
- expect { unsubscribe.call }.not_to raise_error
- end
- end
-
- describe '#notify' do
- subject { described_class.new }
- let(:start) { Time.now }
- let(:finish) { Time.now }
-
- where(:name, :operation_name, :exception, :connection_id, :cached, :cached_response, :sql) do
- nil | "active_record:sqlquery" | nil | nil | nil | false | nil
- "" | "active_record:sqlquery" | nil | nil | nil | false | nil
- "User Load" | "active_record:User Load" | nil | nil | nil | false | nil
- "Repo Load" | "active_record:Repo Load" | StandardError.new | nil | nil | false | nil
- nil | "active_record:sqlquery" | nil | 123 | nil | false | nil
- nil | "active_record:sqlquery" | nil | nil | false | false | nil
- nil | "active_record:sqlquery" | nil | nil | true | true | nil
- nil | "active_record:sqlquery" | nil | nil | true | true | "SELECT * FROM users"
- end
-
- with_them do
- def payload
- {
- name: name,
- exception: exception,
- connection_id: connection_id,
- cached: cached,
- sql: sql
- }
- end
-
- def expected_tags
- {
- "component" => "ActiveRecord",
- "span.kind" => "client",
- "db.type" => "sql",
- "db.connection_id" => connection_id,
- "db.cached" => cached_response,
- "db.statement" => sql
- }
- end
-
- it 'notifies the tracer when the hash contains null values' do
- expect(subject).to receive(:postnotify_span).with(operation_name, start, finish, tags: expected_tags, exception: exception)
-
- subject.notify(start, finish, payload)
- end
-
- it 'notifies the tracer when the payload is missing values' do
- expect(subject).to receive(:postnotify_span).with(operation_name, start, finish, tags: expected_tags, exception: exception)
-
- subject.notify(start, finish, payload.compact)
- end
-
- it 'does not throw exceptions when with the default tracer' do
- expect { subject.notify(start, finish, payload) }.not_to raise_error
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/tracing/sidekiq/client_middleware_spec.rb b/spec/lib/gitlab/tracing/sidekiq/client_middleware_spec.rb
deleted file mode 100644
index 3755860b5ba..00000000000
--- a/spec/lib/gitlab/tracing/sidekiq/client_middleware_spec.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-
-describe Gitlab::Tracing::Sidekiq::ClientMiddleware do
- describe '#call' do
- let(:worker_class) { 'test_worker_class' }
- let(:job) do
- {
- 'class' => "jobclass",
- 'queue' => "jobqueue",
- 'retry' => 0,
- 'args' => %w{1 2 3}
- }
- end
- let(:queue) { 'test_queue' }
- let(:redis_pool) { double("redis_pool") }
- let(:custom_error) { Class.new(StandardError) }
- let(:span) { OpenTracing.start_span('test', ignore_active_scope: true) }
-
- subject { described_class.new }
-
- it 'yields' do
- expect(subject).to receive(:in_tracing_span).with(
- operation_name: "sidekiq:jobclass",
- tags: {
- "component" => "sidekiq",
- "span.kind" => "client",
- "sidekiq.queue" => "jobqueue",
- "sidekiq.jid" => nil,
- "sidekiq.retry" => "0",
- "sidekiq.args" => "1, 2, 3"
- }
- ).and_yield(span)
-
- expect { |b| subject.call(worker_class, job, queue, redis_pool, &b) }.to yield_control
- end
-
- it 'propagates exceptions' do
- expect { subject.call(worker_class, job, queue, redis_pool) { raise custom_error } }.to raise_error(custom_error)
- end
- end
-end
diff --git a/spec/lib/gitlab/tracing/sidekiq/server_middleware_spec.rb b/spec/lib/gitlab/tracing/sidekiq/server_middleware_spec.rb
deleted file mode 100644
index c3087de785a..00000000000
--- a/spec/lib/gitlab/tracing/sidekiq/server_middleware_spec.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-
-describe Gitlab::Tracing::Sidekiq::ServerMiddleware do
- describe '#call' do
- let(:worker_class) { 'test_worker_class' }
- let(:job) do
- {
- 'class' => "jobclass",
- 'queue' => "jobqueue",
- 'retry' => 0,
- 'args' => %w{1 2 3}
- }
- end
- let(:queue) { 'test_queue' }
- let(:custom_error) { Class.new(StandardError) }
- let(:span) { OpenTracing.start_span('test', ignore_active_scope: true) }
- subject { described_class.new }
-
- it 'yields' do
- expect(subject).to receive(:in_tracing_span).with(
- hash_including(
- operation_name: "sidekiq:jobclass",
- tags: {
- "component" => "sidekiq",
- "span.kind" => "server",
- "sidekiq.queue" => "jobqueue",
- "sidekiq.jid" => nil,
- "sidekiq.retry" => "0",
- "sidekiq.args" => "1, 2, 3"
- }
- )
- ).and_yield(span)
-
- expect { |b| subject.call(worker_class, job, queue, &b) }.to yield_control
- end
-
- it 'propagates exceptions' do
- expect { subject.call(worker_class, job, queue) { raise custom_error } }.to raise_error(custom_error)
- end
- end
-end
diff --git a/spec/lib/gitlab/url_blocker_spec.rb b/spec/lib/gitlab/url_blocker_spec.rb
index 445a56ab0d8..253366e0789 100644
--- a/spec/lib/gitlab/url_blocker_spec.rb
+++ b/spec/lib/gitlab/url_blocker_spec.rb
@@ -2,6 +2,87 @@
require 'spec_helper'
describe Gitlab::UrlBlocker do
+ describe '#validate!' do
+ context 'when URI is nil' do
+ let(:import_url) { nil }
+
+ it 'returns no URI and hostname' do
+ uri, hostname = described_class.validate!(import_url)
+
+ expect(uri).to be(nil)
+ expect(hostname).to be(nil)
+ end
+ end
+
+ context 'when URI is internal' do
+ let(:import_url) { 'http://localhost' }
+
+ it 'returns URI and no hostname' do
+ uri, hostname = described_class.validate!(import_url)
+
+ expect(uri).to eq(Addressable::URI.parse('http://[::1]'))
+ expect(hostname).to eq('localhost')
+ end
+ end
+
+ context 'when the URL hostname is a domain' do
+ let(:import_url) { 'https://example.org' }
+
+ it 'returns URI and hostname' do
+ uri, hostname = described_class.validate!(import_url)
+
+ expect(uri).to eq(Addressable::URI.parse('https://93.184.216.34'))
+ expect(hostname).to eq('example.org')
+ end
+ end
+
+ context 'when the URL hostname is an IP address' do
+ let(:import_url) { 'https://93.184.216.34' }
+
+ it 'returns URI and no hostname' do
+ uri, hostname = described_class.validate!(import_url)
+
+ expect(uri).to eq(Addressable::URI.parse('https://93.184.216.34'))
+ expect(hostname).to be(nil)
+ end
+ end
+
+ context 'disabled DNS rebinding protection' do
+ context 'when URI is internal' do
+ let(:import_url) { 'http://localhost' }
+
+ it 'returns URI and no hostname' do
+ uri, hostname = described_class.validate!(import_url, dns_rebind_protection: false)
+
+ expect(uri).to eq(Addressable::URI.parse('http://localhost'))
+ expect(hostname).to be(nil)
+ end
+ end
+
+ context 'when the URL hostname is a domain' do
+ let(:import_url) { 'https://example.org' }
+
+ it 'returns URI and no hostname' do
+ uri, hostname = described_class.validate!(import_url, dns_rebind_protection: false)
+
+ expect(uri).to eq(Addressable::URI.parse('https://example.org'))
+ expect(hostname).to eq(nil)
+ end
+ end
+
+ context 'when the URL hostname is an IP address' do
+ let(:import_url) { 'https://93.184.216.34' }
+
+ it 'returns URI and no hostname' do
+ uri, hostname = described_class.validate!(import_url, dns_rebind_protection: false)
+
+ expect(uri).to eq(Addressable::URI.parse('https://93.184.216.34'))
+ expect(hostname).to be(nil)
+ end
+ end
+ end
+ end
+
describe '#blocked_url?' do
let(:ports) { Project::VALID_IMPORT_PORTS }
@@ -208,7 +289,7 @@ describe Gitlab::UrlBlocker do
end
def stub_domain_resolv(domain, ip)
- address = double(ip_address: ip, ipv4_private?: true, ipv6_link_local?: false, ipv4_loopback?: false, ipv6_loopback?: false)
+ address = double(ip_address: ip, ipv4_private?: true, ipv6_link_local?: false, ipv4_loopback?: false, ipv6_loopback?: false, ipv4?: false)
allow(Addrinfo).to receive(:getaddrinfo).with(domain, any_args).and_return([address])
allow(address).to receive(:ipv6_v4mapped?).and_return(false)
end
diff --git a/spec/lib/gitlab/url_builder_spec.rb b/spec/lib/gitlab/url_builder_spec.rb
index 9f495a5d50b..bbcb92608d8 100644
--- a/spec/lib/gitlab/url_builder_spec.rb
+++ b/spec/lib/gitlab/url_builder_spec.rb
@@ -32,7 +32,7 @@ describe Gitlab::UrlBuilder do
url = described_class.build(milestone)
- expect(url).to eq "#{Settings.gitlab['url']}/#{milestone.project.full_path}/milestones/#{milestone.iid}"
+ expect(url).to eq "#{Settings.gitlab['url']}/#{milestone.project.full_path}/-/milestones/#{milestone.iid}"
end
end
diff --git a/spec/lib/gitlab/url_sanitizer_spec.rb b/spec/lib/gitlab/url_sanitizer_spec.rb
index 5861e6955a6..7242255d535 100644
--- a/spec/lib/gitlab/url_sanitizer_spec.rb
+++ b/spec/lib/gitlab/url_sanitizer_spec.rb
@@ -115,6 +115,40 @@ describe Gitlab::UrlSanitizer do
end
end
+ describe '#user' do
+ context 'credentials in hash' do
+ it 'overrides URL-provided user' do
+ sanitizer = described_class.new('http://a:b@example.com', credentials: { user: 'c', password: 'd' })
+
+ expect(sanitizer.user).to eq('c')
+ end
+ end
+
+ context 'credentials in URL' do
+ where(:url, :user) do
+ 'http://foo:bar@example.com' | 'foo'
+ 'http://foo:bar:baz@example.com' | 'foo'
+ 'http://:bar@example.com' | nil
+ 'http://foo:@example.com' | 'foo'
+ 'http://foo@example.com' | 'foo'
+ 'http://:@example.com' | nil
+ 'http://@example.com' | nil
+ 'http://example.com' | nil
+
+ # Other invalid URLs
+ nil | nil
+ '' | nil
+ 'no' | nil
+ end
+
+ with_them do
+ subject { described_class.new(url).user }
+
+ it { is_expected.to eq(user) }
+ end
+ end
+ end
+
describe '#full_url' do
context 'credentials in hash' do
where(:credentials, :userinfo) do
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 4e910e67ac2..e44463dd767 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -35,7 +35,7 @@ describe Gitlab::UsageData do
subject { described_class.data }
it "gathers usage data" do
- expect(subject.keys).to match_array(%i(
+ expect(subject.keys).to include(*%i(
active_user_count
counts
recorded_at
@@ -63,12 +63,7 @@ describe Gitlab::UsageData do
end
it "gathers usage counts" do
- count_data = subject[:counts]
-
- expect(count_data[:boards]).to eq(1)
- expect(count_data[:projects]).to eq(3)
-
- expect(count_data.keys).to match_array(%i(
+ expected_keys = %i(
assignee_lists
boards
ci_builds
@@ -112,6 +107,7 @@ describe Gitlab::UsageData do
milestone_lists
milestones
notes
+ pool_repositories
projects
projects_imported_from_github
projects_jira_active
@@ -132,7 +128,14 @@ describe Gitlab::UsageData do
uploads
web_hooks
user_preferences
- ))
+ )
+
+ count_data = subject[:counts]
+
+ expect(count_data[:boards]).to eq(1)
+ expect(count_data[:projects]).to eq(3)
+ expect(count_data.keys).to include(*expected_keys)
+ expect(expected_keys - count_data.keys).to be_empty
end
it 'does not gather user preferences usage data when the feature is disabled' do
@@ -211,7 +214,7 @@ describe Gitlab::UsageData do
it "gathers license data" do
expect(subject[:uuid]).to eq(Gitlab::CurrentSettings.uuid)
expect(subject[:version]).to eq(Gitlab::VERSION)
- expect(subject[:installation_type]).to eq(Gitlab::INSTALLATION_TYPE)
+ expect(subject[:installation_type]).to eq('gitlab-development-kit')
expect(subject[:active_user_count]).to eq(User.active.count)
expect(subject[:recorded_at]).to be_a(Time)
end
diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb
index d02d9be5c5c..f8332757fcd 100644
--- a/spec/lib/gitlab/workhorse_spec.rb
+++ b/spec/lib/gitlab/workhorse_spec.rb
@@ -16,40 +16,80 @@ describe Gitlab::Workhorse do
let(:ref) { 'master' }
let(:format) { 'zip' }
let(:storage_path) { Gitlab.config.gitlab.repository_downloads_path }
- let(:base_params) { repository.archive_metadata(ref, storage_path, format, append_sha: nil) }
- let(:gitaly_params) do
- base_params.merge(
- 'GitalyServer' => {
- 'address' => Gitlab::GitalyClient.address(project.repository_storage),
- 'token' => Gitlab::GitalyClient.token(project.repository_storage)
- },
- 'GitalyRepository' => repository.gitaly_repository.to_h.deep_stringify_keys
- )
- end
+ let(:path) { 'some/path' if Feature.enabled?(:git_archive_path, default_enabled: true) }
+ let(:metadata) { repository.archive_metadata(ref, storage_path, format, append_sha: nil, path: path) }
let(:cache_disabled) { false }
subject do
- described_class.send_git_archive(repository, ref: ref, format: format, append_sha: nil)
+ described_class.send_git_archive(repository, ref: ref, format: format, append_sha: nil, path: path)
end
before do
allow(described_class).to receive(:git_archive_cache_disabled?).and_return(cache_disabled)
end
- it 'sets the header correctly' do
- key, command, params = decode_workhorse_header(subject)
+ context 'feature flag disabled' do
+ before do
+ stub_feature_flags(git_archive_path: false)
+ end
- expect(key).to eq('Gitlab-Workhorse-Send-Data')
- expect(command).to eq('git-archive')
- expect(params).to include(gitaly_params)
+ it 'sets the header correctly' do
+ key, command, params = decode_workhorse_header(subject)
+
+ expected_params = metadata.merge(
+ 'GitalyRepository' => repository.gitaly_repository.to_h,
+ 'GitalyServer' => {
+ address: Gitlab::GitalyClient.address(project.repository_storage),
+ token: Gitlab::GitalyClient.token(project.repository_storage)
+ }
+ )
+
+ expect(key).to eq('Gitlab-Workhorse-Send-Data')
+ expect(command).to eq('git-archive')
+ expect(params).to eq(expected_params.deep_stringify_keys)
+ end
+
+ context 'when archive caching is disabled' do
+ let(:cache_disabled) { true }
+
+ it 'tells workhorse not to use the cache' do
+ _, _, params = decode_workhorse_header(subject)
+ expect(params).to include({ 'DisableCache' => true })
+ end
+ end
end
- context 'when archive caching is disabled' do
- let(:cache_disabled) { true }
+ context 'feature flag enabled' do
+ it 'sets the header correctly' do
+ key, command, params = decode_workhorse_header(subject)
+
+ expect(key).to eq('Gitlab-Workhorse-Send-Data')
+ expect(command).to eq('git-archive')
+ expect(params).to eq({
+ 'GitalyServer' => {
+ address: Gitlab::GitalyClient.address(project.repository_storage),
+ token: Gitlab::GitalyClient.token(project.repository_storage)
+ },
+ 'ArchivePath' => metadata['ArchivePath'],
+ 'GetArchiveRequest' => Base64.encode64(
+ Gitaly::GetArchiveRequest.new(
+ repository: repository.gitaly_repository,
+ commit_id: metadata['CommitId'],
+ prefix: metadata['ArchivePrefix'],
+ format: Gitaly::GetArchiveRequest::Format::ZIP,
+ path: path
+ ).to_proto
+ )
+ }.deep_stringify_keys)
+ end
- it 'tells workhorse not to use the cache' do
- _, _, params = decode_workhorse_header(subject)
- expect(params).to include({ 'DisableCache' => true })
+ context 'when archive caching is disabled' do
+ let(:cache_disabled) { true }
+
+ it 'tells workhorse not to use the cache' do
+ _, _, params = decode_workhorse_header(subject)
+ expect(params).to include({ 'DisableCache' => true })
+ end
end
end
diff --git a/spec/lib/gitlab_spec.rb b/spec/lib/gitlab_spec.rb
index 767b5779a79..e075904b0cc 100644
--- a/spec/lib/gitlab_spec.rb
+++ b/spec/lib/gitlab_spec.rb
@@ -109,4 +109,34 @@ describe Gitlab do
expect(described_class.ee?).to eq(false)
end
end
+
+ describe '.http_proxy_env?' do
+ it 'returns true when lower case https' do
+ stub_env('https_proxy', 'https://my.proxy')
+
+ expect(described_class.http_proxy_env?).to eq(true)
+ end
+
+ it 'returns true when upper case https' do
+ stub_env('HTTPS_PROXY', 'https://my.proxy')
+
+ expect(described_class.http_proxy_env?).to eq(true)
+ end
+
+ it 'returns true when lower case http' do
+ stub_env('http_proxy', 'http://my.proxy')
+
+ expect(described_class.http_proxy_env?).to eq(true)
+ end
+
+ it 'returns true when upper case http' do
+ stub_env('HTTP_PROXY', 'http://my.proxy')
+
+ expect(described_class.http_proxy_env?).to eq(true)
+ end
+
+ it 'returns false when not set' do
+ expect(described_class.http_proxy_env?).to eq(false)
+ end
+ end
end
diff --git a/spec/lib/mattermost/session_spec.rb b/spec/lib/mattermost/session_spec.rb
index 77fea5b2d24..346455067a7 100644
--- a/spec/lib/mattermost/session_spec.rb
+++ b/spec/lib/mattermost/session_spec.rb
@@ -2,6 +2,7 @@ require 'spec_helper'
describe Mattermost::Session, type: :request do
include ExclusiveLeaseHelpers
+ include StubRequests
let(:user) { create(:user) }
@@ -24,7 +25,7 @@ describe Mattermost::Session, type: :request do
let(:location) { 'http://location.tld' }
let(:cookie_header) {'MMOAUTH=taskik8az7rq8k6rkpuas7htia; Path=/;'}
let!(:stub) do
- WebMock.stub_request(:get, "#{mattermost_url}/oauth/gitlab/login")
+ stub_full_request("#{mattermost_url}/oauth/gitlab/login")
.to_return(headers: { 'location' => location, 'Set-Cookie' => cookie_header }, status: 302)
end
@@ -63,7 +64,7 @@ describe Mattermost::Session, type: :request do
end
before do
- WebMock.stub_request(:get, "#{mattermost_url}/signup/gitlab/complete")
+ stub_full_request("#{mattermost_url}/signup/gitlab/complete")
.with(query: hash_including({ 'state' => state }))
.to_return do |request|
post "/oauth/token",
@@ -80,7 +81,7 @@ describe Mattermost::Session, type: :request do
end
end
- WebMock.stub_request(:post, "#{mattermost_url}/api/v4/users/logout")
+ stub_full_request("#{mattermost_url}/api/v4/users/logout", method: :post)
.to_return(headers: { Authorization: 'token thisworksnow' }, status: 200)
end
diff --git a/spec/lib/quality/kubernetes_client_spec.rb b/spec/lib/quality/kubernetes_client_spec.rb
index f35d9464d48..4e77dcc97e6 100644
--- a/spec/lib/quality/kubernetes_client_spec.rb
+++ b/spec/lib/quality/kubernetes_client_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Quality::KubernetesClient do
expect(Gitlab::Popen).to receive(:popen_with_detail)
.with([%(kubectl --namespace "#{namespace}" delete ) \
'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa ' \
- "--now -l release=\"#{release_name}\""])
+ "--now --ignore-not-found --include-uninitialized -l release=\"#{release_name}\""])
.and_return(Gitlab::Popen::Result.new([], '', '', double(success?: false)))
expect { subject.cleanup(release_name: release_name) }.to raise_error(described_class::CommandFailedError)
@@ -23,7 +23,7 @@ RSpec.describe Quality::KubernetesClient do
expect(Gitlab::Popen).to receive(:popen_with_detail)
.with([%(kubectl --namespace "#{namespace}" delete ) \
'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa ' \
- "--now -l release=\"#{release_name}\""])
+ "--now --ignore-not-found --include-uninitialized -l release=\"#{release_name}\""])
.and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
# We're not verifying the output here, just silencing it
diff --git a/spec/lib/quality/seeders/issues_spec.rb b/spec/lib/quality/seeders/issues_spec.rb
new file mode 100644
index 00000000000..e17414a541a
--- /dev/null
+++ b/spec/lib/quality/seeders/issues_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Quality::Seeders::Issues do
+ let(:project) { create(:project) }
+
+ subject { described_class.new(project: project) }
+
+ describe '#seed' do
+ it 'seeds issues' do
+ issues_created = subject.seed(backfill_weeks: 1, average_issues_per_week: 1)
+
+ expect(issues_created).to be_between(0, 2)
+ expect(project.issues.count).to eq(issues_created)
+ end
+ end
+end
diff --git a/spec/lib/quality/test_level_spec.rb b/spec/lib/quality/test_level_spec.rb
new file mode 100644
index 00000000000..3465c3a050b
--- /dev/null
+++ b/spec/lib/quality/test_level_spec.rb
@@ -0,0 +1,105 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Quality::TestLevel do
+ describe '#pattern' do
+ context 'when level is unit' do
+ it 'returns a pattern' do
+ expect(subject.pattern(:unit))
+ .to eq("spec/{bin,config,db,dependencies,factories,finders,frontend,graphql,helpers,initializers,javascripts,lib,migrations,models,policies,presenters,rack_servers,routing,rubocop,serializers,services,sidekiq,tasks,uploaders,validators,views,workers,elastic_integration}{,/**/}*_spec.rb")
+ end
+ end
+
+ context 'when level is integration' do
+ it 'returns a pattern' do
+ expect(subject.pattern(:integration))
+ .to eq("spec/{controllers,mailers,requests}{,/**/}*_spec.rb")
+ end
+ end
+
+ context 'when level is system' do
+ it 'returns a pattern' do
+ expect(subject.pattern(:system))
+ .to eq("spec/{features}{,/**/}*_spec.rb")
+ end
+ end
+
+ context 'with a prefix' do
+ it 'returns a pattern' do
+ expect(described_class.new('ee/').pattern(:system))
+ .to eq("ee/spec/{features}{,/**/}*_spec.rb")
+ end
+ end
+
+ describe 'performance' do
+ it 'memoizes the pattern for a given level' do
+ expect(subject.pattern(:system).object_id).to eq(subject.pattern(:system).object_id)
+ end
+
+ it 'freezes the pattern for a given level' do
+ expect(subject.pattern(:system)).to be_frozen
+ end
+ end
+ end
+
+ describe '#regexp' do
+ context 'when level is unit' do
+ it 'returns a regexp' do
+ expect(subject.regexp(:unit))
+ .to eq(%r{spec/(bin|config|db|dependencies|factories|finders|frontend|graphql|helpers|initializers|javascripts|lib|migrations|models|policies|presenters|rack_servers|routing|rubocop|serializers|services|sidekiq|tasks|uploaders|validators|views|workers|elastic_integration)})
+ end
+ end
+
+ context 'when level is integration' do
+ it 'returns a regexp' do
+ expect(subject.regexp(:integration))
+ .to eq(%r{spec/(controllers|mailers|requests)})
+ end
+ end
+
+ context 'when level is system' do
+ it 'returns a regexp' do
+ expect(subject.regexp(:system))
+ .to eq(%r{spec/(features)})
+ end
+ end
+
+ context 'with a prefix' do
+ it 'returns a regexp' do
+ expect(described_class.new('ee/').regexp(:system))
+ .to eq(%r{ee/spec/(features)})
+ end
+ end
+
+ describe 'performance' do
+ it 'memoizes the regexp for a given level' do
+ expect(subject.regexp(:system).object_id).to eq(subject.regexp(:system).object_id)
+ end
+
+ it 'freezes the regexp for a given level' do
+ expect(subject.regexp(:system)).to be_frozen
+ end
+ end
+ end
+
+ describe '#level_for' do
+ it 'returns the correct level for a unit test' do
+ expect(subject.level_for('spec/models/abuse_report_spec.rb')).to eq(:unit)
+ end
+
+ it 'returns the correct level for an integration test' do
+ expect(subject.level_for('spec/mailers/abuse_report_mailer_spec.rb')).to eq(:integration)
+ end
+
+ it 'returns the correct level for a system test' do
+ expect(subject.level_for('spec/features/abuse_report_spec.rb')).to eq(:system)
+ end
+
+ it 'raises an error for an unknown level' do
+ expect { subject.level_for('spec/unknown/foo_spec.rb') }
+ .to raise_error(described_class::UnknownTestLevelError,
+ %r{Test level for spec/unknown/foo_spec.rb couldn't be set. Please rename the file properly or change the test level detection regexes in .+/lib/quality/test_level.rb.})
+ end
+ end
+end
diff --git a/spec/mailers/emails/pages_domains_spec.rb b/spec/mailers/emails/pages_domains_spec.rb
index 050af587061..2f594dbf9d1 100644
--- a/spec/mailers/emails/pages_domains_spec.rb
+++ b/spec/mailers/emails/pages_domains_spec.rb
@@ -5,11 +5,13 @@ describe Emails::PagesDomains do
include EmailSpec::Matchers
include_context 'gitlab email notification'
- set(:project) { create(:project) }
set(:domain) { create(:pages_domain, project: project) }
- set(:user) { project.owner }
+ set(:user) { project.creator }
shared_examples 'a pages domain email' do
+ let(:test_recipient) { user }
+
+ it_behaves_like 'an email sent to a user'
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like 'a user cannot unsubscribe through footer link'
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index fee1d701e3a..cbbb22ad78c 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -45,6 +45,10 @@ describe Notify do
context 'for a project' do
shared_examples 'an assignee email' do
+ let(:test_recipient) { assignee }
+
+ it_behaves_like 'an email sent to a user'
+
it 'is sent to the assignee as the author' do
sender = subject.header[:from].addrs.first
@@ -618,8 +622,10 @@ describe Notify do
end
describe 'project was moved' do
+ let(:test_recipient) { user }
subject { described_class.project_was_moved_email(project.id, user.id, "gitlab/gitlab") }
+ it_behaves_like 'an email sent to a user'
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like "a user cannot unsubscribe through footer link"
@@ -701,6 +707,8 @@ describe Notify do
is_expected.to have_body_text project.full_name
is_expected.to have_body_text project.web_url
is_expected.to have_body_text project_member.human_access
+ is_expected.to have_body_text 'leave the project'
+ is_expected.to have_body_text project_url(project, leave: 1)
end
end
@@ -771,7 +779,7 @@ describe Notify do
invitee
end
- subject { described_class.member_invite_declined_email('project', project.id, project_member.invite_email, maintainer.id) }
+ subject { described_class.member_invite_declined_email('Project', project.id, project_member.invite_email, maintainer.id) }
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
@@ -1081,8 +1089,6 @@ describe Notify do
end
context 'for a group' do
- set(:group) { create(:group) }
-
describe 'group access requested' do
let(:group) { create(:group, :public, :access_requestable) }
let(:group_member) do
@@ -1144,6 +1150,8 @@ describe Notify do
is_expected.to have_body_text group.name
is_expected.to have_body_text group.web_url
is_expected.to have_body_text group_member.human_access
+ is_expected.to have_body_text 'leave the group'
+ is_expected.to have_body_text group_url(group, leave: 1)
end
end
diff --git a/spec/mailers/repository_check_mailer_spec.rb b/spec/mailers/repository_check_mailer_spec.rb
index 384660f7221..3dce89f5be2 100644
--- a/spec/mailers/repository_check_mailer_spec.rb
+++ b/spec/mailers/repository_check_mailer_spec.rb
@@ -12,6 +12,16 @@ describe RepositoryCheckMailer do
expect(mail).to deliver_to admins.map(&:email)
end
+ it 'omits blocked admins' do
+ blocked = create(:admin, :blocked)
+ admins = create_list(:admin, 3)
+
+ mail = described_class.notify(1)
+
+ expect(mail.to).not_to include(blocked.email)
+ expect(mail).to deliver_to admins.map(&:email)
+ end
+
it 'mentions the number of failed checks' do
mail = described_class.notify(3)
diff --git a/spec/migrations/change_packages_size_defaults_in_project_statistics_spec.rb b/spec/migrations/change_packages_size_defaults_in_project_statistics_spec.rb
new file mode 100644
index 00000000000..93e7e9304b1
--- /dev/null
+++ b/spec/migrations/change_packages_size_defaults_in_project_statistics_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'migrate', '20190516155724_change_packages_size_defaults_in_project_statistics.rb')
+
+describe ChangePackagesSizeDefaultsInProjectStatistics, :migration do
+ let(:project_statistics) { table(:project_statistics) }
+ let(:projects) { table(:projects) }
+
+ it 'removes null packages_size' do
+ stats_to_migrate = 10
+
+ stats_to_migrate.times do |i|
+ p = projects.create!(name: "project #{i}", namespace_id: 1)
+ project_statistics.create!(project_id: p.id, namespace_id: p.namespace_id)
+ end
+
+ expect { migrate! }
+ .to change { ProjectStatistics.where(packages_size: nil).count }
+ .from(stats_to_migrate)
+ .to(0)
+ end
+
+ it 'defaults packages_size to 0' do
+ project = projects.create!(name: 'a new project', namespace_id: 2)
+ stat = project_statistics.create!(project_id: project.id, namespace_id: project.namespace_id)
+
+ expect(stat.packages_size).to be_nil
+
+ migrate!
+
+ stat.reload
+ expect(stat.packages_size).to eq(0)
+ end
+end
diff --git a/spec/migrations/enqueue_reset_merge_status_spec.rb b/spec/migrations/enqueue_reset_merge_status_spec.rb
new file mode 100644
index 00000000000..a6dd2e08079
--- /dev/null
+++ b/spec/migrations/enqueue_reset_merge_status_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20190528180441_enqueue_reset_merge_status.rb')
+
+describe EnqueueResetMergeStatus, :migration, :sidekiq do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:namespace) { namespaces.create(name: 'gitlab', path: 'gitlab-org') }
+ let(:project) { projects.create(namespace_id: namespace.id, name: 'foo') }
+ let(:merge_requests) { table(:merge_requests) }
+
+ def create_merge_request(id, extra_params = {})
+ params = {
+ id: id,
+ target_project_id: project.id,
+ target_branch: 'master',
+ source_project_id: project.id,
+ source_branch: 'mr name',
+ title: "mr name#{id}"
+ }.merge(extra_params)
+
+ merge_requests.create!(params)
+ end
+
+ it 'correctly schedules background migrations' do
+ create_merge_request(1, state: 'opened', merge_status: 'can_be_merged')
+ create_merge_request(2, state: 'opened', merge_status: 'can_be_merged')
+ create_merge_request(3, state: 'opened', merge_status: 'can_be_merged')
+ create_merge_request(4, state: 'merged', merge_status: 'can_be_merged')
+ create_merge_request(5, state: 'opened', merge_status: 'unchecked')
+
+ stub_const("#{described_class.name}::BATCH_SIZE", 2)
+
+ Sidekiq::Testing.fake! do
+ Timecop.freeze do
+ migrate!
+
+ expect(described_class::MIGRATION)
+ .to be_scheduled_delayed_migration(5.minutes, 1, 2)
+
+ expect(described_class::MIGRATION)
+ .to be_scheduled_delayed_migration(10.minutes, 3, 4)
+
+ expect(described_class::MIGRATION)
+ .to be_scheduled_delayed_migration(15.minutes, 5, 5)
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(3)
+ end
+ end
+ end
+end
diff --git a/spec/migrations/enqueue_verify_pages_domain_workers_spec.rb b/spec/migrations/enqueue_verify_pages_domain_workers_spec.rb
index afcaefa0591..abf39317188 100644
--- a/spec/migrations/enqueue_verify_pages_domain_workers_spec.rb
+++ b/spec/migrations/enqueue_verify_pages_domain_workers_spec.rb
@@ -8,9 +8,13 @@ describe EnqueueVerifyPagesDomainWorkers, :sidekiq, :migration do
end
end
+ let(:domains_table) { table(:pages_domains) }
+
describe '#up' do
it 'enqueues a verification worker for every domain' do
- domains = 1.upto(3).map { |i| PagesDomain.create!(domain: "my#{i}.domain.com") }
+ domains = Array.new(3) do |i|
+ domains_table.create!(domain: "my#{i}.domain.com", verification_code: "123#{i}")
+ end
expect { migrate! }.to change(PagesDomainVerificationWorker.jobs, :size).by(3)
diff --git a/spec/migrations/fix_pool_repository_source_project_id_spec.rb b/spec/migrations/fix_pool_repository_source_project_id_spec.rb
new file mode 100644
index 00000000000..8ddee9bb575
--- /dev/null
+++ b/spec/migrations/fix_pool_repository_source_project_id_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'migrate', '20190604184643_fix_pool_repository_source_project_id.rb')
+
+describe FixPoolRepositorySourceProjectId, :migration do
+ let(:projects) { table(:projects) }
+ let(:pool_repositories) { table(:pool_repositories) }
+ let(:shards) { table(:shards) }
+
+ it 'fills in source_project_ids' do
+ shard = shards.create!(name: 'default')
+
+ # gitaly is a project with a pool repository that has a source_project_id
+ gitaly = projects.create!(name: 'gitaly', path: 'gitlab-org/gitaly', namespace_id: 1)
+ pool_repository = pool_repositories.create(shard_id: shard.id, source_project_id: gitaly.id)
+ gitaly.update_column(:pool_repository_id, pool_repository.id)
+
+ # gitlab is a project with a pool repository that's missing a source_project_id
+ pool_repository_without_source_project = pool_repositories.create(shard_id: shard.id, source_project_id: nil)
+ gitlab = projects.create!(name: 'gitlab', path: 'gitlab-org/gitlab-ce', namespace_id: 1, pool_repository_id: pool_repository_without_source_project.id)
+ projects.create!(name: 'gitlab-fork-1', path: 'my-org-1/gitlab-ce', namespace_id: 1, pool_repository_id: pool_repository_without_source_project.id)
+
+ migrate!
+
+ expect(pool_repositories.find(pool_repository_without_source_project.id).source_project_id).to eq(gitlab.id)
+ expect(pool_repositories.find(pool_repository.id).source_project_id).to eq(gitaly.id)
+ end
+end
diff --git a/spec/migrations/generate_lets_encrypt_private_key_spec.rb b/spec/migrations/generate_lets_encrypt_private_key_spec.rb
new file mode 100644
index 00000000000..773bf5222f0
--- /dev/null
+++ b/spec/migrations/generate_lets_encrypt_private_key_spec.rb
@@ -0,0 +1,12 @@
+require 'spec_helper'
+require Rails.root.join('db', 'migrate', '20190524062810_generate_lets_encrypt_private_key.rb')
+
+describe GenerateLetsEncryptPrivateKey, :migration do
+ describe '#up' do
+ it 'does not fail' do
+ expect do
+ described_class.new.up
+ end.not_to raise_error
+ end
+ end
+end
diff --git a/spec/migrations/generate_missing_routes_spec.rb b/spec/migrations/generate_missing_routes_spec.rb
index 32515d353b0..30ad135d4df 100644
--- a/spec/migrations/generate_missing_routes_spec.rb
+++ b/spec/migrations/generate_missing_routes_spec.rb
@@ -8,7 +8,7 @@ describe GenerateMissingRoutes, :migration do
let(:routes) { table(:routes) }
it 'creates routes for projects without a route' do
- namespace = namespaces.create!(name: 'GitLab', path: 'gitlab')
+ namespace = namespaces.create!(name: 'GitLab', path: 'gitlab', type: 'Group')
routes.create!(
path: 'gitlab',
diff --git a/spec/migrations/migrate_old_artifacts_spec.rb b/spec/migrations/migrate_old_artifacts_spec.rb
index 79e21514506..bc826d91471 100644
--- a/spec/migrations/migrate_old_artifacts_spec.rb
+++ b/spec/migrations/migrate_old_artifacts_spec.rb
@@ -45,10 +45,6 @@ describe MigrateOldArtifacts, :migration, schema: 20170918072948 do
expect(build_with_legacy_artifacts.artifacts?).to be_falsey
end
- it "legacy artifacts are set" do
- expect(build_with_legacy_artifacts.legacy_artifacts_file_identifier).not_to be_nil
- end
-
describe '#min_id' do
subject { migration.send(:min_id) }
diff --git a/spec/migrations/remove_orphaned_label_links_spec.rb b/spec/migrations/remove_orphaned_label_links_spec.rb
index 13b8919343e..e8c44c141c3 100644
--- a/spec/migrations/remove_orphaned_label_links_spec.rb
+++ b/spec/migrations/remove_orphaned_label_links_spec.rb
@@ -10,6 +10,12 @@ describe RemoveOrphanedLabelLinks, :migration do
let(:project) { create(:project) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
let(:label) { create_label }
+ before do
+ # This migration was created before we introduced ProjectCiCdSetting#default_git_depth
+ allow_any_instance_of(ProjectCiCdSetting).to receive(:default_git_depth).and_return(nil)
+ allow_any_instance_of(ProjectCiCdSetting).to receive(:default_git_depth=).and_return(0)
+ end
+
context 'add foreign key on label_id' do
let!(:label_link_with_label) { create_label_link(label_id: label.id) }
let!(:label_link_without_label) { create_label_link(label_id: nil) }
diff --git a/spec/migrations/schedule_fill_valid_time_for_pages_domain_certificates_spec.rb b/spec/migrations/schedule_fill_valid_time_for_pages_domain_certificates_spec.rb
new file mode 100644
index 00000000000..54f3e264df0
--- /dev/null
+++ b/spec/migrations/schedule_fill_valid_time_for_pages_domain_certificates_spec.rb
@@ -0,0 +1,46 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20190524073827_schedule_fill_valid_time_for_pages_domain_certificates.rb')
+
+describe ScheduleFillValidTimeForPagesDomainCertificates, :migration, :sidekiq do
+ let(:migration_class) { described_class::MIGRATION }
+ let(:migration_name) { migration_class.to_s.demodulize }
+
+ let(:domains_table) { table(:pages_domains) }
+
+ let(:certificate) do
+ File.read('spec/fixtures/passphrase_x509_certificate.crt')
+ end
+
+ before do
+ domains_table.create!(domain: "domain1.example.com", verification_code: "123")
+ domains_table.create!(domain: "domain2.example.com", verification_code: "123", certificate: '')
+ domains_table.create!(domain: "domain3.example.com", verification_code: "123", certificate: certificate)
+ domains_table.create!(domain: "domain4.example.com", verification_code: "123", certificate: certificate)
+ end
+
+ it 'correctly schedules background migrations' do
+ Sidekiq::Testing.fake! do
+ Timecop.freeze do
+ migrate!
+
+ first_id = domains_table.find_by_domain("domain3.example.com").id
+ last_id = domains_table.find_by_domain("domain4.example.com").id
+
+ expect(migration_name).to be_scheduled_delayed_migration(5.minutes, first_id, last_id)
+ expect(BackgroundMigrationWorker.jobs.size).to eq(1)
+ end
+ end
+ end
+
+ it 'sets certificate valid_not_before/not_after' do
+ perform_enqueued_jobs do
+ migrate!
+
+ domain = domains_table.find_by_domain("domain3.example.com")
+ expect(domain.certificate_valid_not_before)
+ .to eq(Time.parse("2018-03-23 14:02:08 UTC"))
+ expect(domain.certificate_valid_not_after)
+ .to eq(Time.parse("2019-03-23 14:02:08 UTC"))
+ end
+ end
+end
diff --git a/spec/migrations/schedule_sync_issuables_state_id_where_nil_spec.rb b/spec/migrations/schedule_sync_issuables_state_id_where_nil_spec.rb
new file mode 100644
index 00000000000..105c05bb7ca
--- /dev/null
+++ b/spec/migrations/schedule_sync_issuables_state_id_where_nil_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20190506135400_schedule_sync_issuables_state_id_where_nil')
+
+describe ScheduleSyncIssuablesStateIdWhereNil, :migration, :sidekiq do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:merge_requests) { table(:merge_requests) }
+ let(:issues) { table(:issues) }
+ let(:migration) { described_class.new }
+ let(:group) { namespaces.create!(name: 'gitlab', path: 'gitlab') }
+ let(:project) { projects.create!(namespace_id: group.id) }
+
+ shared_examples 'scheduling migrations' do
+ before do
+ Sidekiq::Worker.clear_all
+ stub_const("#{described_class.name}::BATCH_SIZE", 2)
+ end
+
+ it 'correctly schedules issuable sync background migration' do
+ Sidekiq::Testing.fake! do
+ Timecop.freeze do
+ migrate!
+
+ expect(migration).to be_scheduled_delayed_migration(120.seconds, resource_1.id, resource_3.id)
+ expect(migration).to be_scheduled_delayed_migration(240.seconds, resource_5.id, resource_5.id)
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ end
+ end
+ end
+ end
+
+ describe '#up' do
+ context 'issues' do
+ it_behaves_like 'scheduling migrations' do
+ let(:migration) { described_class::ISSUES_MIGRATION }
+ let!(:resource_1) { issues.create!(description: 'first', state: 'opened', state_id: nil) }
+ let!(:resource_2) { issues.create!(description: 'second', state: 'closed', state_id: 2) }
+ let!(:resource_3) { issues.create!(description: 'third', state: 'closed', state_id: nil) }
+ let!(:resource_4) { issues.create!(description: 'fourth', state: 'closed', state_id: 2) }
+ let!(:resource_5) { issues.create!(description: 'fifth', state: 'closed', state_id: nil) }
+ end
+ end
+
+ context 'merge requests' do
+ it_behaves_like 'scheduling migrations' do
+ let(:migration) { described_class::MERGE_REQUESTS_MIGRATION }
+ let!(:resource_1) { merge_requests.create!(state: 'opened', state_id: nil, target_project_id: project.id, target_branch: 'feature1', source_branch: 'master') }
+ let!(:resource_2) { merge_requests.create!(state: 'closed', state_id: 2, target_project_id: project.id, target_branch: 'feature2', source_branch: 'master') }
+ let!(:resource_3) { merge_requests.create!(state: 'merged', state_id: nil, target_project_id: project.id, target_branch: 'feature3', source_branch: 'master') }
+ let!(:resource_4) { merge_requests.create!(state: 'locked', state_id: 3, target_project_id: project.id, target_branch: 'feature4', source_branch: 'master') }
+ let!(:resource_5) { merge_requests.create!(state: 'locked', state_id: nil, target_project_id: project.id, target_branch: 'feature4', source_branch: 'master') }
+ end
+ end
+ end
+end
diff --git a/spec/models/active_session_spec.rb b/spec/models/active_session_spec.rb
index b523f393ece..2762eaeccd3 100644
--- a/spec/models/active_session_spec.rb
+++ b/spec/models/active_session_spec.rb
@@ -88,6 +88,52 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do
end
end
+ describe '.list_sessions' do
+ it 'uses the ActiveSession lookup to return original sessions' do
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.set("session:gitlab:6919a6f1bb119dd7396fadc38fd18d0d", Marshal.dump({ _csrf_token: 'abcd' }))
+
+ redis.sadd(
+ "session:lookup:user:gitlab:#{user.id}",
+ %w[
+ 6919a6f1bb119dd7396fadc38fd18d0d
+ 59822c7d9fcdfa03725eff41782ad97d
+ ]
+ )
+ end
+
+ expect(ActiveSession.list_sessions(user)).to eq [{ _csrf_token: 'abcd' }]
+ end
+ end
+
+ describe '.session_ids_for_user' do
+ it 'uses the user lookup table to return session ids' do
+ session_ids = ['59822c7d9fcdfa03725eff41782ad97d']
+
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.sadd("session:lookup:user:gitlab:#{user.id}", session_ids)
+ end
+
+ expect(ActiveSession.session_ids_for_user(user)).to eq(session_ids)
+ end
+ end
+
+ describe '.sessions_from_ids' do
+ it 'uses the ActiveSession lookup to return original sessions' do
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.set("session:gitlab:6919a6f1bb119dd7396fadc38fd18d0d", Marshal.dump({ _csrf_token: 'abcd' }))
+ end
+
+ expect(ActiveSession.sessions_from_ids(['6919a6f1bb119dd7396fadc38fd18d0d'])).to eq [{ _csrf_token: 'abcd' }]
+ end
+
+ it 'avoids a redis lookup for an empty array' do
+ expect(Gitlab::Redis::SharedState).not_to receive(:with)
+
+ expect(ActiveSession.sessions_from_ids([])).to eq([])
+ end
+ end
+
describe '.set' do
it 'sets a new redis entry for the user session and a lookup entry' do
ActiveSession.set(user, request)
diff --git a/spec/models/application_record_spec.rb b/spec/models/application_record_spec.rb
index fd25132ed3a..74573d0941c 100644
--- a/spec/models/application_record_spec.rb
+++ b/spec/models/application_record_spec.rb
@@ -11,6 +11,25 @@ describe ApplicationRecord do
end
end
+ describe '.safe_ensure_unique' do
+ let(:model) { build(:suggestion) }
+ let(:klass) { model.class }
+
+ before do
+ allow(model).to receive(:save).and_raise(ActiveRecord::RecordNotUnique)
+ end
+
+ it 'returns false when ActiveRecord::RecordNotUnique is raised' do
+ expect(model).to receive(:save).once
+ expect(klass.safe_ensure_unique { model.save }).to be_falsey
+ end
+
+ it 'retries based on retry count specified' do
+ expect(model).to receive(:save).exactly(3).times
+ expect(klass.safe_ensure_unique(retries: 2) { model.save }).to be_falsey
+ end
+ end
+
describe '.safe_find_or_create_by' do
it 'creates the user avoiding race conditions' do
expect(Suggestion).to receive(:find_or_create_by).and_raise(ActiveRecord::RecordNotUnique)
@@ -33,4 +52,10 @@ describe ApplicationRecord do
expect { Suggestion.find_or_create_by!(note: nil) }.to raise_error(ActiveRecord::RecordInvalid)
end
end
+
+ describe '.underscore' do
+ it 'returns the underscored value of the class as a string' do
+ expect(MergeRequest.underscore).to eq('merge_request')
+ end
+ end
end
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index c7d7dbac736..f8dc1541dd3 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -31,6 +31,20 @@ describe ApplicationSetting do
it { is_expected.to allow_value("dev.gitlab.com").for(:commit_email_hostname) }
it { is_expected.not_to allow_value("@dev.gitlab").for(:commit_email_hostname) }
+ it { is_expected.to allow_value("myemail@gitlab.com").for(:lets_encrypt_notification_email) }
+ it { is_expected.to allow_value(nil).for(:lets_encrypt_notification_email) }
+ it { is_expected.not_to allow_value("notanemail").for(:lets_encrypt_notification_email) }
+ it { is_expected.not_to allow_value("myemail@example.com").for(:lets_encrypt_notification_email) }
+ it { is_expected.to allow_value("myemail@test.example.com").for(:lets_encrypt_notification_email) }
+
+ context "when user accepted let's encrypt terms of service" do
+ before do
+ setting.update(lets_encrypt_terms_of_service_accepted: true)
+ end
+
+ it { is_expected.not_to allow_value(nil).for(:lets_encrypt_notification_email) }
+ end
+
describe 'default_artifacts_expire_in' do
it 'sets an error if it cannot parse' do
setting.update(default_artifacts_expire_in: 'a')
diff --git a/spec/models/blob_spec.rb b/spec/models/blob_spec.rb
index d0e1688cce3..8364293b908 100644
--- a/spec/models/blob_spec.rb
+++ b/spec/models/blob_spec.rb
@@ -43,6 +43,21 @@ describe Blob do
changelog.id
contributing.id
end
+
+ it 'does not include blobs from previous requests in later requests' do
+ changelog = described_class.lazy(project, commit_id, 'CHANGELOG')
+ contributing = described_class.lazy(same_project, commit_id, 'CONTRIBUTING.md')
+
+ # Access property so the values are loaded
+ changelog.id
+ contributing.id
+
+ readme = described_class.lazy(project, commit_id, 'README.md')
+
+ expect(project.repository).to receive(:blobs_at).with([[commit_id, 'README.md']]).once.and_call_original
+
+ readme.id
+ end
end
describe '#data' do
diff --git a/spec/models/broadcast_message_spec.rb b/spec/models/broadcast_message_spec.rb
index 3ab013ddc0e..4d53e4aad8a 100644
--- a/spec/models/broadcast_message_spec.rb
+++ b/spec/models/broadcast_message_spec.rb
@@ -88,13 +88,6 @@ describe BroadcastMessage do
expect(Rails.cache).not_to receive(:delete).with(described_class::CACHE_KEY)
expect(described_class.current.length).to eq(0)
end
-
- it 'clears the legacy cache key' do
- create(:broadcast_message, :future)
-
- expect(Rails.cache).to receive(:delete).with(described_class::LEGACY_CACHE_KEY)
- expect(described_class.current.length).to eq(0)
- end
end
describe '#attributes' do
@@ -164,7 +157,6 @@ describe BroadcastMessage do
message = create(:broadcast_message)
expect(Rails.cache).to receive(:delete).with(described_class::CACHE_KEY)
- expect(Rails.cache).to receive(:delete).with(described_class::LEGACY_CACHE_KEY)
message.flush_redis_cache
end
diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb
index aacfbe3f180..eb32198265b 100644
--- a/spec/models/ci/bridge_spec.rb
+++ b/spec/models/ci/bridge_spec.rb
@@ -10,6 +10,8 @@ describe Ci::Bridge do
create(:ci_bridge, pipeline: pipeline)
end
+ it { is_expected.to include_module(Ci::PipelineDelegator) }
+
describe '#tags' do
it 'only has a bridge tag' do
expect(bridge.tags).to eq [:bridge]
@@ -33,7 +35,7 @@ describe Ci::Bridge do
CI_PROJECT_ID CI_PROJECT_NAME CI_PROJECT_PATH
CI_PROJECT_PATH_SLUG CI_PROJECT_NAMESPACE CI_PIPELINE_IID
CI_CONFIG_PATH CI_PIPELINE_SOURCE CI_COMMIT_MESSAGE
- CI_COMMIT_TITLE CI_COMMIT_DESCRIPTION
+ CI_COMMIT_TITLE CI_COMMIT_DESCRIPTION CI_COMMIT_REF_PROTECTED
]
expect(bridge.scoped_variables_hash.keys).to include(*variables)
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 66be192ab21..d98db024f73 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -28,8 +28,7 @@ describe Ci::Build do
it { is_expected.to delegate_method(:merge_request_event?).to(:pipeline) }
it { is_expected.to delegate_method(:merge_request_ref?).to(:pipeline) }
it { is_expected.to delegate_method(:legacy_detached_merge_request_pipeline?).to(:pipeline) }
-
- it { is_expected.to be_a(ArtifactMigratable) }
+ it { is_expected.to include_module(Ci::PipelineDelegator) }
describe 'associations' do
it 'has a bidirectional relationship with projects' do
@@ -111,24 +110,6 @@ describe Ci::Build do
end
end
- context 'when job has a legacy archive' do
- let!(:job) { create(:ci_build, :legacy_artifacts) }
-
- it 'returns the job' do
- is_expected.to include(job)
- end
-
- context 'when ci_enable_legacy_artifacts feature flag is disabled' do
- before do
- stub_feature_flags(ci_enable_legacy_artifacts: false)
- end
-
- it 'does not return the job' do
- is_expected.not_to include(job)
- end
- end
- end
-
context 'when job has a job artifact archive' do
let!(:job) { create(:ci_build, :artifacts) }
@@ -459,51 +440,11 @@ describe Ci::Build do
end
end
end
-
- context 'when legacy artifacts are used' do
- let(:build) { create(:ci_build, :legacy_artifacts) }
-
- subject { build.artifacts? }
-
- context 'is expired' do
- let(:build) { create(:ci_build, :legacy_artifacts, :expired) }
-
- it { is_expected.to be_falsy }
- end
-
- context 'artifacts archive does not exist' do
- let(:build) { create(:ci_build) }
-
- it { is_expected.to be_falsy }
- end
-
- context 'artifacts archive exists' do
- let(:build) { create(:ci_build, :legacy_artifacts) }
-
- it { is_expected.to be_truthy }
-
- context 'when ci_enable_legacy_artifacts feature flag is disabled' do
- before do
- stub_feature_flags(ci_enable_legacy_artifacts: false)
- end
-
- it { is_expected.to be_falsy }
- end
- end
- end
end
describe '#browsable_artifacts?' do
subject { build.browsable_artifacts? }
- context 'artifacts metadata does not exist' do
- before do
- build.update(legacy_artifacts_metadata: nil)
- end
-
- it { is_expected.to be_falsy }
- end
-
context 'artifacts metadata does exists' do
let(:build) { create(:ci_build, :artifacts) }
@@ -759,12 +700,6 @@ describe Ci::Build do
it { is_expected.to be_truthy }
end
-
- context 'when build does not have job artifacts' do
- let(:build) { create(:ci_build, :legacy_artifacts) }
-
- it { is_expected.to be_falsy }
- end
end
describe '#has_old_trace?' do
@@ -852,6 +787,10 @@ describe Ci::Build do
let(:deployment) { build.deployment }
let(:environment) { deployment.environment }
+ before do
+ allow(Deployments::FinishedWorker).to receive(:perform_async)
+ end
+
it 'has deployments record with created status' do
expect(deployment).to be_created
expect(environment.name).to eq('review/master')
@@ -1087,11 +1026,11 @@ describe Ci::Build do
describe 'erasable build' do
shared_examples 'erasable' do
it 'removes artifact file' do
- expect(build.artifacts_file.exists?).to be_falsy
+ expect(build.artifacts_file.present?).to be_falsy
end
it 'removes artifact metadata file' do
- expect(build.artifacts_metadata.exists?).to be_falsy
+ expect(build.artifacts_metadata.present?).to be_falsy
end
it 'removes all job_artifacts' do
@@ -1183,7 +1122,7 @@ describe Ci::Build do
let!(:build) { create(:ci_build, :success, :artifacts) }
before do
- build.remove_artifacts_metadata!
+ build.erase_erasable_artifacts!
end
describe '#erase' do
@@ -1194,76 +1133,6 @@ describe Ci::Build do
end
end
end
-
- context 'old artifacts' do
- context 'build is erasable' do
- context 'new artifacts' do
- let!(:build) { create(:ci_build, :trace_artifact, :success, :legacy_artifacts) }
-
- describe '#erase' do
- before do
- build.erase(erased_by: erased_by)
- end
-
- context 'erased by user' do
- let!(:erased_by) { create(:user, username: 'eraser') }
-
- include_examples 'erasable'
-
- it 'records user who erased a build' do
- expect(build.erased_by).to eq erased_by
- end
- end
-
- context 'erased by system' do
- let(:erased_by) { nil }
-
- include_examples 'erasable'
-
- it 'does not set user who erased a build' do
- expect(build.erased_by).to be_nil
- end
- end
- end
-
- describe '#erasable?' do
- subject { build.erasable? }
- it { is_expected.to be_truthy }
- end
-
- describe '#erased?' do
- let!(:build) { create(:ci_build, :trace_artifact, :success, :legacy_artifacts) }
- subject { build.erased? }
-
- context 'job has not been erased' do
- it { is_expected.to be_falsey }
- end
-
- context 'job has been erased' do
- before do
- build.erase
- end
-
- it { is_expected.to be_truthy }
- end
- end
-
- context 'metadata and build trace are not available' do
- let!(:build) { create(:ci_build, :success, :legacy_artifacts) }
-
- before do
- build.remove_artifacts_metadata!
- end
-
- describe '#erase' do
- it 'does not raise error' do
- expect { build.erase }.not_to raise_error
- end
- end
- end
- end
- end
- end
end
describe '#erase_erasable_artifacts!' do
@@ -2119,54 +1988,6 @@ describe Ci::Build do
end
end
- context 'when updating the build' do
- let(:build) { create(:ci_build, artifacts_size: 23) }
-
- it 'updates project statistics' do
- build.artifacts_size = 42
-
- expect(build).to receive(:update_project_statistics_after_save).and_call_original
-
- expect { build.save! }
- .to change { build.project.statistics.reload.build_artifacts_size }
- .by(19)
- end
-
- context 'when the artifact size stays the same' do
- it 'does not update project statistics' do
- build.name = 'changed'
-
- expect(build).not_to receive(:update_project_statistics_after_save)
-
- build.save!
- end
- end
- end
-
- context 'when destroying the build' do
- let!(:build) { create(:ci_build, artifacts_size: 23) }
-
- it 'updates project statistics' do
- expect(ProjectStatistics)
- .to receive(:increment_statistic)
- .and_call_original
-
- expect { build.destroy! }
- .to change { build.project.statistics.reload.build_artifacts_size }
- .by(-23)
- end
-
- context 'when the build is destroyed due to the project being destroyed' do
- it 'does not update the project statistics' do
- expect(ProjectStatistics)
- .not_to receive(:increment_statistic)
-
- build.project.update(pending_delete: true)
- build.project.destroy!
- end
- end
- end
-
describe '#variables' do
let(:container_registry_enabled) { false }
@@ -2227,7 +2048,8 @@ describe Ci::Build do
{ key: 'CI_PIPELINE_SOURCE', value: pipeline.source, public: true, masked: false },
{ key: 'CI_COMMIT_MESSAGE', value: pipeline.git_commit_message, public: true, masked: false },
{ key: 'CI_COMMIT_TITLE', value: pipeline.git_commit_title, public: true, masked: false },
- { key: 'CI_COMMIT_DESCRIPTION', value: pipeline.git_commit_description, public: true, masked: false }
+ { key: 'CI_COMMIT_DESCRIPTION', value: pipeline.git_commit_description, public: true, masked: false },
+ { key: 'CI_COMMIT_REF_PROTECTED', value: (!!pipeline.protected_ref?).to_s, public: true, masked: false }
]
end
@@ -2312,6 +2134,19 @@ describe Ci::Build do
it { user_variables.each { |v| is_expected.to include(v) } }
end
+ context 'when build belongs to a pipeline for merge request' do
+ let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline, source_branch: 'improve/awesome') }
+ let(:pipeline) { merge_request.all_pipelines.first }
+ let(:build) { create(:ci_build, ref: pipeline.ref, pipeline: pipeline) }
+
+ it 'returns values based on source ref' do
+ is_expected.to include(
+ { key: 'CI_COMMIT_REF_NAME', value: 'improve/awesome', public: true, masked: false },
+ { key: 'CI_COMMIT_REF_SLUG', value: 'improve-awesome', public: true, masked: false }
+ )
+ end
+ end
+
context 'when build has an environment' do
let(:environment_variables) do
[
@@ -2629,30 +2464,6 @@ describe Ci::Build do
it { is_expected.to include(ci_config_path) }
end
- context 'when using auto devops' do
- context 'and is enabled' do
- before do
- project.create_auto_devops!(enabled: true, domain: 'example.com')
- end
-
- it "includes AUTO_DEVOPS_DOMAIN" do
- is_expected.to include(
- { key: 'AUTO_DEVOPS_DOMAIN', value: 'example.com', public: true, masked: false })
- end
- end
-
- context 'and is disabled' do
- before do
- project.create_auto_devops!(enabled: false, domain: 'example.com')
- end
-
- it "includes AUTO_DEVOPS_DOMAIN" do
- is_expected.not_to include(
- { key: 'AUTO_DEVOPS_DOMAIN', value: 'example.com', public: true, masked: false })
- end
- end
- end
-
context 'when pipeline variable overrides build variable' do
before do
build.yaml_variables = [{ key: 'MYVAR', value: 'myvar', public: true }]
@@ -2703,6 +2514,8 @@ describe Ci::Build do
)
end
+ let(:pipeline) { create(:ci_pipeline, project: project, ref: 'feature') }
+
it 'returns static predefined variables' do
expect(build.variables.size).to be >= 28
expect(build.variables)
@@ -2752,6 +2565,8 @@ describe Ci::Build do
)
end
+ let(:pipeline) { create(:ci_pipeline, project: project, ref: 'feature') }
+
it 'does not persist the build' do
expect(build).to be_valid
expect(build).not_to be_persisted
@@ -2838,7 +2653,7 @@ describe Ci::Build do
context 'when ref is merge request' do
let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) }
- let(:pipeline) { merge_request.merge_request_pipelines.first }
+ let(:pipeline) { merge_request.pipelines_for_merge_request.first }
let(:build) { create(:ci_build, ref: merge_request.source_branch, tag: false, pipeline: pipeline, project: project) }
context 'when ref is protected' do
@@ -2896,7 +2711,7 @@ describe Ci::Build do
context 'when ref is merge request' do
let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) }
- let(:pipeline) { merge_request.merge_request_pipelines.first }
+ let(:pipeline) { merge_request.pipelines_for_merge_request.first }
let(:build) { create(:ci_build, ref: merge_request.source_branch, tag: false, pipeline: pipeline, project: project) }
context 'when ref is protected' do
@@ -2946,26 +2761,18 @@ describe Ci::Build do
subject { build.any_unmet_prerequisites? }
+ before do
+ allow(build).to receive(:prerequisites).and_return(prerequisites)
+ end
+
context 'build has prerequisites' do
- before do
- allow(build).to receive(:prerequisites).and_return([double])
- end
+ let(:prerequisites) { [double] }
it { is_expected.to be_truthy }
-
- context 'and the ci_preparing_state feature is disabled' do
- before do
- stub_feature_flags(ci_preparing_state: false)
- end
-
- it { is_expected.to be_falsey }
- end
end
context 'build does not have prerequisites' do
- before do
- allow(build).to receive(:prerequisites).and_return([])
- end
+ let(:prerequisites) { [] }
it { is_expected.to be_falsey }
end
@@ -3543,6 +3350,18 @@ describe Ci::Build do
end
end
+ describe '#report_artifacts' do
+ subject { build.report_artifacts }
+
+ context 'when the build has reports' do
+ let!(:report) { create(:ci_job_artifact, :codequality, job: build) }
+
+ it 'returns the artifacts with reports' do
+ expect(subject).to contain_exactly(report)
+ end
+ end
+ end
+
describe '#artifacts_metadata_entry' do
set(:build) { create(:ci_build, project: project) }
let(:path) { 'other_artifacts_0.1.2/another-subdirectory/banana_sample.gif' }
diff --git a/spec/models/ci/group_variable_spec.rb b/spec/models/ci/group_variable_spec.rb
index b3999765e5f..406a69f3bbc 100644
--- a/spec/models/ci/group_variable_spec.rb
+++ b/spec/models/ci/group_variable_spec.rb
@@ -5,7 +5,8 @@ require 'spec_helper'
describe Ci::GroupVariable do
subject { build(:ci_group_variable) }
- it { is_expected.to include_module(HasVariable) }
+ it_behaves_like "CI variable"
+
it { is_expected.to include_module(Presentable) }
it { is_expected.to include_module(Maskable) }
it { is_expected.to validate_uniqueness_of(:key).scoped_to(:group_id).with_message(/\(\w+\) has already been taken/) }
diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb
index d7abd54eec1..1ba66565e03 100644
--- a/spec/models/ci/job_artifact_spec.rb
+++ b/spec/models/ci/job_artifact_spec.rb
@@ -19,6 +19,25 @@ describe Ci::JobArtifact do
it_behaves_like 'having unique enum values'
+ it_behaves_like 'UpdateProjectStatistics' do
+ subject { build(:ci_job_artifact, :archive, size: 106365) }
+ end
+
+ describe '.with_reports' do
+ let!(:artifact) { create(:ci_job_artifact, :archive) }
+
+ subject { described_class.with_reports }
+
+ it { is_expected.to be_empty }
+
+ context 'when there are reports' do
+ let!(:metrics_report) { create(:ci_job_artifact, :junit) }
+ let!(:codequality_report) { create(:ci_job_artifact, :codequality) }
+
+ it { is_expected.to eq([metrics_report, codequality_report]) }
+ end
+ end
+
describe '.test_reports' do
subject { described_class.test_reports }
@@ -102,12 +121,6 @@ describe Ci::JobArtifact do
it 'sets the size from the file size' do
expect(artifact.size).to eq(106365)
end
-
- it 'updates the project statistics' do
- expect { artifact }
- .to change { project.statistics.reload.build_artifacts_size }
- .by(106365)
- end
end
context 'updating the artifact file' do
@@ -115,12 +128,6 @@ describe Ci::JobArtifact do
artifact.update!(file: fixture_file_upload('spec/fixtures/dk.png'))
expect(artifact.size).to eq(1062)
end
-
- it 'updates the project statistics' do
- expect { artifact.update!(file: fixture_file_upload('spec/fixtures/dk.png')) }
- .to change { artifact.project.statistics.reload.build_artifacts_size }
- .by(1062 - 106365)
- end
end
describe 'validates file format' do
@@ -259,34 +266,6 @@ describe Ci::JobArtifact do
end
end
- context 'when destroying the artifact' do
- let(:project) { create(:project, :repository) }
- let(:pipeline) { create(:ci_pipeline, project: project) }
- let!(:build) { create(:ci_build, :artifacts, pipeline: pipeline) }
-
- it 'updates the project statistics' do
- artifact = build.job_artifacts.first
-
- expect(ProjectStatistics)
- .to receive(:increment_statistic)
- .and_call_original
-
- expect { artifact.destroy }
- .to change { project.statistics.reload.build_artifacts_size }
- .by(-106365)
- end
-
- context 'when it is destroyed from the project level' do
- it 'does not update the project statistics' do
- expect(ProjectStatistics)
- .not_to receive(:increment_statistic)
-
- project.update(pending_delete: true)
- project.destroy!
- end
- end
- end
-
describe 'file is being stored' do
subject { create(:ci_job_artifact, :archive) }
diff --git a/spec/models/ci/legacy_stage_spec.rb b/spec/models/ci/legacy_stage_spec.rb
index be0307518eb..bb812cc0533 100644
--- a/spec/models/ci/legacy_stage_spec.rb
+++ b/spec/models/ci/legacy_stage_spec.rb
@@ -272,4 +272,6 @@ describe Ci::LegacyStage do
def create_job(type, status: 'success', stage: stage_name, **opts)
create(type, pipeline: pipeline, stage: stage, status: status, **opts)
end
+
+ it_behaves_like 'manual playable stage', :ci_stage
end
diff --git a/spec/models/ci/pipeline_schedule_spec.rb b/spec/models/ci/pipeline_schedule_spec.rb
index 81913f4a3b6..227870eb27f 100644
--- a/spec/models/ci/pipeline_schedule_spec.rb
+++ b/spec/models/ci/pipeline_schedule_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe Ci::PipelineSchedule do
+ subject { build(:ci_pipeline_schedule) }
+
it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:owner) }
@@ -35,34 +37,127 @@ describe Ci::PipelineSchedule do
expect(pipeline_schedule).not_to be_valid
end
end
+
+ context 'when cron contains trailing whitespaces' do
+ it 'strips the attribute' do
+ pipeline_schedule = build(:ci_pipeline_schedule, cron: ' 0 0 * * * ')
+
+ expect(pipeline_schedule).to be_valid
+ expect(pipeline_schedule.cron).to eq('0 0 * * *')
+ end
+ end
+ end
+
+ describe '.runnable_schedules' do
+ subject { described_class.runnable_schedules }
+
+ let!(:pipeline_schedule) do
+ Timecop.freeze(1.day.ago) do
+ create(:ci_pipeline_schedule, :hourly)
+ end
+ end
+
+ it 'returns the runnable schedule' do
+ is_expected.to eq([pipeline_schedule])
+ end
+
+ context 'when there are no runnable schedules' do
+ let!(:pipeline_schedule) { }
+
+ it 'returns an empty array' do
+ is_expected.to be_empty
+ end
+ end
+ end
+
+ describe '.preloaded' do
+ subject { described_class.preloaded }
+
+ before do
+ create_list(:ci_pipeline_schedule, 3)
+ end
+
+ it 'preloads the associations' do
+ subject
+
+ query = ActiveRecord::QueryRecorder.new { subject.each(&:project) }
+
+ expect(query.count).to eq(2)
+ end
end
describe '#set_next_run_at' do
- let!(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly) }
+ let(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly) }
+ let(:ideal_next_run_at) { pipeline_schedule.send(:ideal_next_run_at) }
+
+ let(:expected_next_run_at) do
+ Gitlab::Ci::CronParser.new(Settings.cron_jobs['pipeline_schedule_worker']['cron'], Time.zone.name)
+ .next_time_from(ideal_next_run_at)
+ end
+
+ let(:cron_worker_next_run_at) do
+ Gitlab::Ci::CronParser.new(Settings.cron_jobs['pipeline_schedule_worker']['cron'], Time.zone.name)
+ .next_time_from(Time.zone.now)
+ end
context 'when creates new pipeline schedule' do
- let(:expected_next_run_at) do
- Gitlab::Ci::CronParser.new(pipeline_schedule.cron, pipeline_schedule.cron_timezone)
- .next_time_from(Time.now)
+ it 'updates next_run_at automatically' do
+ expect(pipeline_schedule.next_run_at).to eq(expected_next_run_at)
end
+ end
- it 'updates next_run_at automatically' do
- expect(described_class.last.next_run_at).to eq(expected_next_run_at)
+ context 'when PipelineScheduleWorker runs at a specific interval' do
+ before do
+ allow(Settings).to receive(:cron_jobs) do
+ {
+ 'pipeline_schedule_worker' => {
+ 'cron' => '0 1 2 3 *'
+ }
+ }
+ end
+ end
+
+ it "updates next_run_at to the sidekiq worker's execution time" do
+ expect(pipeline_schedule.next_run_at.min).to eq(0)
+ expect(pipeline_schedule.next_run_at.hour).to eq(1)
+ expect(pipeline_schedule.next_run_at.day).to eq(2)
+ expect(pipeline_schedule.next_run_at.month).to eq(3)
end
end
- context 'when updates cron of exsisted pipeline schedule' do
- let(:new_cron) { '0 0 1 1 *' }
+ context 'when pipeline schedule runs every minute' do
+ let(:pipeline_schedule) { create(:ci_pipeline_schedule, :every_minute) }
- let(:expected_next_run_at) do
- Gitlab::Ci::CronParser.new(new_cron, pipeline_schedule.cron_timezone)
- .next_time_from(Time.now)
+ it "updates next_run_at to the sidekiq worker's execution time", :quarantine do
+ expect(pipeline_schedule.next_run_at).to eq(cron_worker_next_run_at)
end
+ end
+
+ context 'when there are two different pipeline schedules in different time zones' do
+ let(:pipeline_schedule_1) { create(:ci_pipeline_schedule, :weekly, cron_timezone: 'Eastern Time (US & Canada)') }
+ let(:pipeline_schedule_2) { create(:ci_pipeline_schedule, :weekly, cron_timezone: 'UTC') }
+
+ it 'sets different next_run_at' do
+ expect(pipeline_schedule_1.next_run_at).not_to eq(pipeline_schedule_2.next_run_at)
+ end
+ end
+
+ context 'when there are two different pipeline schedules in the same time zones' do
+ let(:pipeline_schedule_1) { create(:ci_pipeline_schedule, :weekly, cron_timezone: 'UTC') }
+ let(:pipeline_schedule_2) { create(:ci_pipeline_schedule, :weekly, cron_timezone: 'UTC') }
+
+ it 'sets the sames next_run_at' do
+ expect(pipeline_schedule_1.next_run_at).to eq(pipeline_schedule_2.next_run_at)
+ end
+ end
+
+ context 'when updates cron of exsisted pipeline schedule' do
+ let(:new_cron) { '0 0 1 1 *' }
it 'updates next_run_at automatically' do
pipeline_schedule.update!(cron: new_cron)
- expect(described_class.last.next_run_at).to eq(expected_next_run_at)
+ expect(pipeline_schedule.next_run_at).to eq(expected_next_run_at)
end
end
end
@@ -72,10 +167,11 @@ describe Ci::PipelineSchedule do
context 'when reschedules after 10 days from now' do
let(:future_time) { 10.days.from_now }
+ let(:ideal_next_run_at) { pipeline_schedule.send(:ideal_next_run_at) }
let(:expected_next_run_at) do
- Gitlab::Ci::CronParser.new(pipeline_schedule.cron, pipeline_schedule.cron_timezone)
- .next_time_from(future_time)
+ Gitlab::Ci::CronParser.new(Settings.cron_jobs['pipeline_schedule_worker']['cron'], Time.zone.name)
+ .next_time_from(ideal_next_run_at)
end
it 'points to proper next_run_at' do
@@ -88,38 +184,6 @@ describe Ci::PipelineSchedule do
end
end
- describe '#real_next_run' do
- subject do
- described_class.last.real_next_run(worker_cron: worker_cron,
- worker_time_zone: worker_time_zone)
- end
-
- context 'when GitLab time_zone is UTC' do
- before do
- allow(Time).to receive(:zone)
- .and_return(ActiveSupport::TimeZone[worker_time_zone])
- end
-
- let(:worker_time_zone) { 'UTC' }
-
- context 'when cron_timezone is Eastern Time (US & Canada)' do
- before do
- create(:ci_pipeline_schedule, :nightly,
- cron_timezone: 'Eastern Time (US & Canada)')
- end
-
- let(:worker_cron) { '0 1 2 3 *' }
-
- it 'returns the next time worker executes' do
- expect(subject.min).to eq(0)
- expect(subject.hour).to eq(1)
- expect(subject.day).to eq(2)
- expect(subject.month).to eq(3)
- end
- end
- end
- end
-
describe '#job_variables' do
let!(:pipeline_schedule) { create(:ci_pipeline_schedule) }
diff --git a/spec/models/ci/pipeline_schedule_variable_spec.rb b/spec/models/ci/pipeline_schedule_variable_spec.rb
index 3c9379ecb0d..c96a24d5042 100644
--- a/spec/models/ci/pipeline_schedule_variable_spec.rb
+++ b/spec/models/ci/pipeline_schedule_variable_spec.rb
@@ -5,5 +5,5 @@ require 'spec_helper'
describe Ci::PipelineScheduleVariable do
subject { build(:ci_pipeline_schedule_variable) }
- it { is_expected.to include_module(HasVariable) }
+ it_behaves_like "CI variable"
end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index fd66e344d63..a8701f0efa4 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -382,6 +382,54 @@ describe Ci::Pipeline, :mailer do
end
end
+ describe '#source_ref' do
+ subject { pipeline.source_ref }
+
+ let(:pipeline) { create(:ci_pipeline, ref: 'feature') }
+
+ it 'returns source ref' do
+ is_expected.to eq('feature')
+ end
+
+ context 'when the pipeline is a detached merge request pipeline' do
+ let(:merge_request) { create(:merge_request) }
+
+ let(:pipeline) do
+ create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, ref: merge_request.ref_path)
+ end
+
+ it 'returns source ref' do
+ is_expected.to eq(merge_request.source_branch)
+ end
+ end
+ end
+
+ describe '#source_ref_slug' do
+ subject { pipeline.source_ref_slug }
+
+ let(:pipeline) { create(:ci_pipeline, ref: 'feature') }
+
+ it 'slugifies with the source ref' do
+ expect(Gitlab::Utils).to receive(:slugify).with('feature')
+
+ subject
+ end
+
+ context 'when the pipeline is a detached merge request pipeline' do
+ let(:merge_request) { create(:merge_request) }
+
+ let(:pipeline) do
+ create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, ref: merge_request.ref_path)
+ end
+
+ it 'slugifies with the source ref of the merge request' do
+ expect(Gitlab::Utils).to receive(:slugify).with(merge_request.source_branch)
+
+ subject
+ end
+ end
+ end
+
describe '.triggered_for_branch' do
subject { described_class.triggered_for_branch(ref) }
@@ -418,7 +466,7 @@ describe Ci::Pipeline, :mailer do
target_branch: 'master')
end
- let(:pipeline) { merge_request.merge_request_pipelines.first }
+ let(:pipeline) { merge_request.pipelines_for_merge_request.first }
it 'does not return the pipeline' do
is_expected.to be_empty
@@ -690,7 +738,8 @@ describe Ci::Pipeline, :mailer do
CI_PIPELINE_SOURCE
CI_COMMIT_MESSAGE
CI_COMMIT_TITLE
- CI_COMMIT_DESCRIPTION]
+ CI_COMMIT_DESCRIPTION
+ CI_COMMIT_REF_PROTECTED]
end
context 'when source is merge request' do
@@ -1332,6 +1381,40 @@ describe Ci::Pipeline, :mailer do
end
end
+ describe 'auto merge' do
+ let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
+
+ let(:pipeline) do
+ create(:ci_pipeline, :running, project: merge_request.source_project,
+ ref: merge_request.source_branch,
+ sha: merge_request.diff_head_sha)
+ end
+
+ before do
+ merge_request.update_head_pipeline
+ end
+
+ %w[succeed! drop! cancel! skip!].each do |action|
+ context "when the pipeline recieved #{action} event" do
+ it 'performs AutoMergeProcessWorker' do
+ expect(AutoMergeProcessWorker).to receive(:perform_async).with(merge_request.id)
+
+ pipeline.public_send(action)
+ end
+ end
+ end
+
+ context 'when auto merge is not enabled in the merge request' do
+ let(:merge_request) { create(:merge_request) }
+
+ it 'performs AutoMergeProcessWorker' do
+ expect(AutoMergeProcessWorker).not_to receive(:perform_async)
+
+ pipeline.succeed!
+ end
+ end
+ end
+
def create_build(name, *traits, queued_at: current, started_from: 0, **opts)
create(:ci_build, *traits,
name: name,
@@ -2893,4 +2976,36 @@ describe Ci::Pipeline, :mailer do
end
end
end
+
+ describe '#find_stage_by_name' do
+ let(:pipeline) { create(:ci_pipeline) }
+ let(:stage_name) { 'test' }
+
+ let(:stage) do
+ create(:ci_stage_entity,
+ pipeline: pipeline,
+ project: pipeline.project,
+ name: 'test')
+ end
+
+ before do
+ create_list(:ci_build, 2, pipeline: pipeline, stage: stage.name)
+ end
+
+ subject { pipeline.find_stage_by_name!(stage_name) }
+
+ context 'when stage exists' do
+ it { is_expected.to eq(stage) }
+ end
+
+ context 'when stage does not exist' do
+ let(:stage_name) { 'build' }
+
+ it 'raises an ActiveRecord exception' do
+ expect do
+ subject
+ end.to raise_exception(ActiveRecord::RecordNotFound)
+ end
+ end
+ end
end
diff --git a/spec/models/ci/pipeline_variable_spec.rb b/spec/models/ci/pipeline_variable_spec.rb
index 2ecb688299a..e8c7ce088e2 100644
--- a/spec/models/ci/pipeline_variable_spec.rb
+++ b/spec/models/ci/pipeline_variable_spec.rb
@@ -5,7 +5,8 @@ require 'spec_helper'
describe Ci::PipelineVariable do
subject { build(:ci_pipeline_variable) }
- it { is_expected.to include_module(HasVariable) }
+ it_behaves_like "CI variable"
+
it { is_expected.to validate_uniqueness_of(:key).scoped_to(:pipeline_id) }
describe '#hook_attrs' do
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index 2cb581696a0..f735a89f69f 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -73,9 +73,8 @@ describe Ci::Runner do
end
it 'fails to save a group assigned to a project runner even if the runner is already saved' do
- group_runner
-
- expect { create(:group, runners: [project_runner]) }
+ group.runners << project_runner
+ expect { group.save! }
.to raise_error(ActiveRecord::RecordInvalid)
end
end
diff --git a/spec/models/ci/stage_spec.rb b/spec/models/ci/stage_spec.rb
index 661958390e2..85cd32fb03a 100644
--- a/spec/models/ci/stage_spec.rb
+++ b/spec/models/ci/stage_spec.rb
@@ -285,4 +285,6 @@ describe Ci::Stage, :models do
end
end
end
+
+ it_behaves_like 'manual playable stage', :ci_stage_entity
end
diff --git a/spec/models/ci/variable_spec.rb b/spec/models/ci/variable_spec.rb
index d2df6b3344e..a231c7eaed8 100644
--- a/spec/models/ci/variable_spec.rb
+++ b/spec/models/ci/variable_spec.rb
@@ -5,8 +5,9 @@ require 'spec_helper'
describe Ci::Variable do
subject { build(:ci_variable) }
+ it_behaves_like "CI variable"
+
describe 'validations' do
- it { is_expected.to include_module(HasVariable) }
it { is_expected.to include_module(Presentable) }
it { is_expected.to include_module(Maskable) }
it { is_expected.to validate_uniqueness_of(:key).scoped_to(:project_id, :environment_scope).with_message(/\(\w+\) has already been taken/) }
diff --git a/spec/models/clusters/applications/cert_manager_spec.rb b/spec/models/clusters/applications/cert_manager_spec.rb
index 5cd80edb3a1..8d853a04e33 100644
--- a/spec/models/clusters/applications/cert_manager_spec.rb
+++ b/spec/models/clusters/applications/cert_manager_spec.rb
@@ -10,6 +10,12 @@ describe Clusters::Applications::CertManager do
include_examples 'cluster application version specs', :clusters_applications_cert_managers
include_examples 'cluster application initial status specs'
+ describe '#can_uninstall?' do
+ subject { cert_manager.can_uninstall? }
+
+ it { is_expected.to be_falsey }
+ end
+
describe '#install_command' do
let(:cert_email) { 'admin@example.com' }
diff --git a/spec/models/clusters/applications/helm_spec.rb b/spec/models/clusters/applications/helm_spec.rb
index f177d493a2e..6ea6c110d62 100644
--- a/spec/models/clusters/applications/helm_spec.rb
+++ b/spec/models/clusters/applications/helm_spec.rb
@@ -18,6 +18,14 @@ describe Clusters::Applications::Helm do
it { is_expected.to contain_exactly(installed_cluster, updated_cluster) }
end
+ describe '#can_uninstall?' do
+ let(:helm) { create(:clusters_applications_helm) }
+
+ subject { helm.can_uninstall? }
+
+ it { is_expected.to be_falsey }
+ end
+
describe '#issue_client_cert' do
let(:application) { create(:clusters_applications_helm) }
subject { application.issue_client_cert }
diff --git a/spec/models/clusters/applications/ingress_spec.rb b/spec/models/clusters/applications/ingress_spec.rb
index 113d29b5551..292ddabd2d8 100644
--- a/spec/models/clusters/applications/ingress_spec.rb
+++ b/spec/models/clusters/applications/ingress_spec.rb
@@ -18,6 +18,12 @@ describe Clusters::Applications::Ingress do
allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_async)
end
+ describe '#can_uninstall?' do
+ subject { ingress.can_uninstall? }
+
+ it { is_expected.to be_falsey }
+ end
+
describe '#make_installed!' do
before do
application.make_installed!
diff --git a/spec/models/clusters/applications/jupyter_spec.rb b/spec/models/clusters/applications/jupyter_spec.rb
index 1a7363b64f9..43fa1010b2b 100644
--- a/spec/models/clusters/applications/jupyter_spec.rb
+++ b/spec/models/clusters/applications/jupyter_spec.rb
@@ -10,6 +10,15 @@ describe Clusters::Applications::Jupyter do
it { is_expected.to belong_to(:oauth_application) }
+ describe '#can_uninstall?' do
+ let(:ingress) { create(:clusters_applications_ingress, :installed, external_hostname: 'localhost.localdomain') }
+ let(:jupyter) { create(:clusters_applications_jupyter, cluster: ingress.cluster) }
+
+ subject { jupyter.can_uninstall? }
+
+ it { is_expected.to be_falsey }
+ end
+
describe '#set_initial_status' do
before do
jupyter.set_initial_status
@@ -87,6 +96,8 @@ describe Clusters::Applications::Jupyter do
expect(values).to match(/clientId: '?#{application.oauth_application.uid}/)
expect(values).to match(/callbackUrl: '?#{application.callback_url}/)
expect(values).to include("gitlabProjectIdWhitelist:\n - #{application.cluster.project.id}")
+ expect(values).to include("c.GitLabOAuthenticator.scope = ['api read_repository write_repository']")
+ expect(values).to match(/GITLAB_HOST: '?#{Gitlab.config.gitlab.host}/)
end
context 'when cluster belongs to a project' do
diff --git a/spec/models/clusters/applications/knative_spec.rb b/spec/models/clusters/applications/knative_spec.rb
index 5e68f2634da..b38cf96de7e 100644
--- a/spec/models/clusters/applications/knative_spec.rb
+++ b/spec/models/clusters/applications/knative_spec.rb
@@ -3,9 +3,6 @@
require 'rails_helper'
describe Clusters::Applications::Knative do
- include KubernetesHelpers
- include ReactiveCachingHelpers
-
let(:knative) { create(:clusters_applications_knative) }
include_examples 'cluster application core specs', :clusters_applications_knative
@@ -39,6 +36,12 @@ describe Clusters::Applications::Knative do
end
end
+ describe '#can_uninstall?' do
+ subject { knative.can_uninstall? }
+
+ it { is_expected.to be_falsey }
+ end
+
describe '#schedule_status_update with external_ip' do
let(:application) { create(:clusters_applications_knative, :installed) }
@@ -109,7 +112,7 @@ describe Clusters::Applications::Knative do
subject { knative.install_command }
it 'is initialized with latest version' do
- expect(subject.version).to eq('0.3.0')
+ expect(subject.version).to eq('0.5.0')
end
it_behaves_like 'a command'
@@ -140,77 +143,4 @@ describe Clusters::Applications::Knative do
describe 'validations' do
it { is_expected.to validate_presence_of(:hostname) }
end
-
- describe '#service_pod_details' do
- let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:service) { cluster.platform_kubernetes }
- let(:knative) { create(:clusters_applications_knative, cluster: cluster) }
-
- let(:namespace) do
- create(:cluster_kubernetes_namespace,
- cluster: cluster,
- cluster_project: cluster.cluster_project,
- project: cluster.cluster_project.project)
- end
-
- before do
- stub_kubeclient_discover(service.api_url)
- stub_kubeclient_knative_services
- stub_kubeclient_service_pods
- stub_reactive_cache(knative,
- {
- services: kube_response(kube_knative_services_body),
- pods: kube_response(kube_knative_pods_body(cluster.cluster_project.project.name, namespace.namespace))
- })
- synchronous_reactive_cache(knative)
- end
-
- it 'is able k8s core for pod details' do
- expect(knative.service_pod_details(namespace.namespace, cluster.cluster_project.project.name)).not_to be_nil
- end
- end
-
- describe '#services' do
- let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:service) { cluster.platform_kubernetes }
- let(:knative) { create(:clusters_applications_knative, cluster: cluster) }
-
- let(:namespace) do
- create(:cluster_kubernetes_namespace,
- cluster: cluster,
- cluster_project: cluster.cluster_project,
- project: cluster.cluster_project.project)
- end
-
- subject { knative.services }
-
- before do
- stub_kubeclient_discover(service.api_url)
- stub_kubeclient_knative_services
- stub_kubeclient_service_pods
- end
-
- it 'has an unintialized cache' do
- is_expected.to be_nil
- end
-
- context 'when using synchronous reactive cache' do
- before do
- stub_reactive_cache(knative,
- {
- services: kube_response(kube_knative_services_body),
- pods: kube_response(kube_knative_pods_body(cluster.cluster_project.project.name, namespace.namespace))
- })
- synchronous_reactive_cache(knative)
- end
-
- it 'has cached services' do
- is_expected.not_to be_nil
- end
-
- it 'matches our namespace' do
- expect(knative.services_for(ns: namespace)).not_to be_nil
- end
- end
- end
end
diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb
index e8ba9737c23..26267c64112 100644
--- a/spec/models/clusters/applications/prometheus_spec.rb
+++ b/spec/models/clusters/applications/prometheus_spec.rb
@@ -11,6 +11,21 @@ describe Clusters::Applications::Prometheus do
include_examples 'cluster application helm specs', :clusters_applications_prometheus
include_examples 'cluster application initial status specs'
+ describe 'after_destroy' do
+ let(:project) { create(:project) }
+ let(:cluster) { create(:cluster, :with_installed_helm, projects: [project]) }
+ let!(:application) { create(:clusters_applications_prometheus, :installed, cluster: cluster) }
+ let!(:prometheus_service) { project.create_prometheus_service(active: true) }
+
+ it 'deactivates prometheus_service after destroy' do
+ expect do
+ application.destroy!
+
+ prometheus_service.reload
+ end.to change(prometheus_service, :active).from(true).to(false)
+ end
+ end
+
describe 'transition to installed' do
let(:project) { create(:project) }
let(:cluster) { create(:cluster, :with_installed_helm, projects: [project]) }
@@ -23,12 +38,20 @@ describe Clusters::Applications::Prometheus do
end
it 'ensures Prometheus service is activated' do
- expect(prometheus_service).to receive(:update).with(active: true)
+ expect(prometheus_service).to receive(:update!).with(active: true)
subject.make_installed
end
end
+ describe '#can_uninstall?' do
+ let(:prometheus) { create(:clusters_applications_prometheus) }
+
+ subject { prometheus.can_uninstall? }
+
+ it { is_expected.to be_truthy }
+ end
+
describe '#prometheus_client' do
context 'cluster is nil' do
it 'returns nil' do
@@ -134,6 +157,34 @@ describe Clusters::Applications::Prometheus do
end
end
+ describe '#uninstall_command' do
+ let(:prometheus) { create(:clusters_applications_prometheus) }
+
+ subject { prometheus.uninstall_command }
+
+ it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::DeleteCommand) }
+
+ it 'has the application name' do
+ expect(subject.name).to eq('prometheus')
+ end
+
+ it 'has files' do
+ expect(subject.files).to eq(prometheus.files)
+ end
+
+ it 'is rbac' do
+ expect(subject).to be_rbac
+ end
+
+ context 'on a non rbac enabled cluster' do
+ before do
+ prometheus.cluster.platform_kubernetes.abac!
+ end
+
+ it { is_expected.not_to be_rbac }
+ end
+ end
+
describe '#upgrade_command' do
let(:prometheus) { build(:clusters_applications_prometheus) }
let(:values) { prometheus.values }
diff --git a/spec/models/clusters/applications/runner_spec.rb b/spec/models/clusters/applications/runner_spec.rb
index 399a13f82cb..4f0cd0efe9c 100644
--- a/spec/models/clusters/applications/runner_spec.rb
+++ b/spec/models/clusters/applications/runner_spec.rb
@@ -13,6 +13,14 @@ describe Clusters::Applications::Runner do
it { is_expected.to belong_to(:runner) }
+ describe '#can_uninstall?' do
+ let(:gitlab_runner) { create(:clusters_applications_runner, runner: ci_runner) }
+
+ subject { gitlab_runner.can_uninstall? }
+
+ it { is_expected.to be_falsey }
+ end
+
describe '#install_command' do
let(:kubeclient) { double('kubernetes client') }
let(:gitlab_runner) { create(:clusters_applications_runner, runner: ci_runner) }
@@ -24,7 +32,7 @@ describe Clusters::Applications::Runner do
it 'is initialized with 4 arguments' do
expect(subject.name).to eq('runner')
expect(subject.chart).to eq('runner/gitlab-runner')
- expect(subject.version).to eq('0.3.0')
+ expect(subject.version).to eq(Clusters::Applications::Runner::VERSION)
expect(subject).to be_rbac
expect(subject.repository).to eq('https://charts.gitlab.io')
expect(subject.files).to eq(gitlab_runner.files)
@@ -42,7 +50,7 @@ describe Clusters::Applications::Runner do
let(:gitlab_runner) { create(:clusters_applications_runner, :errored, runner: ci_runner, version: '0.1.13') }
it 'is initialized with the locked version' do
- expect(subject.version).to eq('0.3.0')
+ expect(subject.version).to eq(Clusters::Applications::Runner::VERSION)
end
end
end
@@ -61,8 +69,8 @@ describe Clusters::Applications::Runner do
expect(values).to include('privileged: true')
expect(values).to include('image: ubuntu:16.04')
expect(values).to include('resources')
- expect(values).to match(/runnerToken: '?#{ci_runner.token}/)
- expect(values).to match(/gitlabUrl: '?#{Gitlab::Routing.url_helpers.root_url}/)
+ expect(values).to match(/runnerToken: '?#{Regexp.escape(ci_runner.token)}/)
+ expect(values).to match(/gitlabUrl: '?#{Regexp.escape(Gitlab::Routing.url_helpers.root_url)}/)
end
context 'without a runner' do
@@ -75,7 +83,7 @@ describe Clusters::Applications::Runner do
end
it 'uses the new runner token' do
- expect(values).to match(/runnerToken: '?#{runner.token}/)
+ expect(values).to match(/runnerToken: '?#{Regexp.escape(runner.token)}/)
end
end
@@ -106,6 +114,18 @@ describe Clusters::Applications::Runner do
expect(runner.groups).to eq [group]
end
end
+
+ context 'instance cluster' do
+ let(:cluster) { create(:cluster, :with_installed_helm, :instance) }
+
+ include_examples 'runner creation'
+
+ it 'creates an instance runner' do
+ subject
+
+ expect(runner).to be_instance_type
+ end
+ end
end
context 'with duplicated values on vendor/runner/values.yaml' do
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index 894ef3fb956..f206bb41f45 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -2,9 +2,14 @@
require 'spec_helper'
-describe Clusters::Cluster do
+describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
+ include ReactiveCachingHelpers
+ include KubernetesHelpers
+
it_behaves_like 'having unique enum values'
+ subject { build(:cluster) }
+
it { is_expected.to belong_to(:user) }
it { is_expected.to have_many(:cluster_projects) }
it { is_expected.to have_many(:projects) }
@@ -17,12 +22,10 @@ describe Clusters::Cluster do
it { is_expected.to have_one(:application_prometheus) }
it { is_expected.to have_one(:application_runner) }
it { is_expected.to have_many(:kubernetes_namespaces) }
- it { is_expected.to have_one(:kubernetes_namespace) }
it { is_expected.to have_one(:cluster_project) }
it { is_expected.to delegate_method(:status).to(:provider) }
it { is_expected.to delegate_method(:status_reason).to(:provider) }
- it { is_expected.to delegate_method(:status_name).to(:provider) }
it { is_expected.to delegate_method(:on_creation?).to(:provider) }
it { is_expected.to delegate_method(:active?).to(:platform_kubernetes).with_prefix }
it { is_expected.to delegate_method(:rbac?).to(:platform_kubernetes).with_prefix }
@@ -35,6 +38,11 @@ describe Clusters::Cluster do
it { is_expected.to respond_to :project }
+ it do
+ expect(subject.knative_services_finder(subject.project))
+ .to be_instance_of(Clusters::KnativeServicesFinder)
+ end
+
describe '.enabled' do
subject { described_class.enabled }
@@ -95,6 +103,24 @@ describe Clusters::Cluster do
it { is_expected.to contain_exactly(cluster) }
end
+ describe '.managed' do
+ subject do
+ described_class.managed
+ end
+
+ context 'cluster is not managed' do
+ let!(:cluster) { create(:cluster, :not_managed) }
+
+ it { is_expected.not_to include(cluster) }
+ end
+
+ context 'cluster is managed' do
+ let!(:cluster) { create(:cluster) }
+
+ it { is_expected.to include(cluster) }
+ end
+ end
+
describe '.missing_kubernetes_namespace' do
let!(:cluster) { create(:cluster, :provided_by_gcp, :project) }
let(:project) { cluster.project }
@@ -307,6 +333,15 @@ describe Clusters::Cluster do
end
end
+ context 'when group and instance have configured kubernetes clusters' do
+ let(:project) { create(:project, group: group) }
+ let!(:instance_cluster) { create(:cluster, :provided_by_gcp, :instance) }
+
+ it 'returns clusters in order, descending the hierachy' do
+ is_expected.to eq([group_cluster, instance_cluster])
+ end
+ end
+
context 'when sub-group has configured kubernetes cluster', :nested_groups do
let(:sub_group_cluster) { create(:cluster, :provided_by_gcp, :group) }
let(:sub_group) { sub_group_cluster.group }
@@ -473,28 +508,6 @@ describe Clusters::Cluster do
end
end
- describe '#created?' do
- let(:cluster) { create(:cluster, :provided_by_gcp) }
-
- subject { cluster.created? }
-
- context 'when status_name is :created' do
- before do
- allow(cluster).to receive_message_chain(:provider, :status_name).and_return(:created)
- end
-
- it { is_expected.to eq(true) }
- end
-
- context 'when status_name is not :created' do
- before do
- allow(cluster).to receive_message_chain(:provider, :status_name).and_return(:creating)
- end
-
- it { is_expected.to eq(false) }
- end
- end
-
describe '#allow_user_defined_namespace?' do
let(:cluster) { create(:cluster, :provided_by_gcp) }
@@ -529,62 +542,15 @@ describe Clusters::Cluster do
end
context 'with no domain on cluster' do
- context 'with a project cluster' do
- let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:project) { cluster.project }
-
- context 'with domain set at instance level' do
- before do
- stub_application_setting(auto_devops_domain: 'global_domain.com')
-
- it { is_expected.to eq('global_domain.com') }
- end
- end
-
- context 'with domain set on ProjectAutoDevops' do
- before do
- auto_devops = project.build_auto_devops(domain: 'legacy-ado-domain.com')
- auto_devops.save
- end
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.project }
- it { is_expected.to eq('legacy-ado-domain.com') }
+ context 'with domain set at instance level' do
+ before do
+ stub_application_setting(auto_devops_domain: 'global_domain.com')
end
- context 'with domain set as environment variable on project' do
- before do
- variable = project.variables.build(key: 'AUTO_DEVOPS_DOMAIN', value: 'project-ado-domain.com')
- variable.save
- end
-
- it { is_expected.to eq('project-ado-domain.com') }
- end
-
- context 'with domain set as environment variable on the group project' do
- let(:group) { create(:group) }
-
- before do
- project.update(parent_id: group.id)
- variable = group.variables.build(key: 'AUTO_DEVOPS_DOMAIN', value: 'group-ado-domain.com')
- variable.save
- end
-
- it { is_expected.to eq('group-ado-domain.com') }
- end
- end
-
- context 'with a group cluster' do
- let(:cluster) { create(:cluster, :group, :provided_by_gcp) }
-
- context 'with domain set as environment variable for the group' do
- let(:group) { cluster.group }
-
- before do
- variable = group.variables.build(key: 'AUTO_DEVOPS_DOMAIN', value: 'group-ado-domain.com')
- variable.save
- end
-
- it { is_expected.to eq('group-ado-domain.com') }
- end
+ it { is_expected.to eq('global_domain.com') }
end
end
end
@@ -636,4 +602,139 @@ describe Clusters::Cluster do
it { is_expected.to be_truthy }
end
end
+
+ describe '#status_name' do
+ subject { cluster.status_name }
+
+ context 'the cluster has a provider' do
+ let(:cluster) { create(:cluster, :provided_by_gcp) }
+
+ before do
+ cluster.provider.make_errored!
+ end
+
+ it { is_expected.to eq :errored }
+ end
+
+ context 'there is a cached connection status' do
+ let(:cluster) { create(:cluster, :provided_by_user) }
+
+ before do
+ allow(cluster).to receive(:connection_status).and_return(:connected)
+ end
+
+ it { is_expected.to eq :connected }
+ end
+
+ context 'there is no connection status in the cache' do
+ let(:cluster) { create(:cluster, :provided_by_user) }
+
+ before do
+ allow(cluster).to receive(:connection_status).and_return(nil)
+ end
+
+ it { is_expected.to eq :created }
+ end
+ end
+
+ describe '#connection_status' do
+ let(:cluster) { create(:cluster) }
+ let(:status) { :connected }
+
+ subject { cluster.connection_status }
+
+ it { is_expected.to be_nil }
+
+ context 'with a cached status' do
+ before do
+ stub_reactive_cache(cluster, connection_status: status)
+ end
+
+ it { is_expected.to eq(status) }
+ end
+ end
+
+ describe '#calculate_reactive_cache' do
+ subject { cluster.calculate_reactive_cache }
+
+ context 'cluster is disabled' do
+ let(:cluster) { create(:cluster, :disabled) }
+
+ it 'does not populate the cache' do
+ expect(cluster).not_to receive(:retrieve_connection_status)
+
+ is_expected.to be_nil
+ end
+ end
+
+ context 'cluster is enabled' do
+ let(:cluster) { create(:cluster, :provided_by_user, :group) }
+
+ context 'connection to the cluster is successful' do
+ before do
+ stub_kubeclient_discover(cluster.platform.api_url)
+ end
+
+ it { is_expected.to eq(connection_status: :connected) }
+ end
+
+ context 'cluster cannot be reached' do
+ before do
+ allow(cluster.kubeclient.core_client).to receive(:discover)
+ .and_raise(SocketError)
+ end
+
+ it { is_expected.to eq(connection_status: :unreachable) }
+ end
+
+ context 'cluster cannot be authenticated to' do
+ before do
+ allow(cluster.kubeclient.core_client).to receive(:discover)
+ .and_raise(OpenSSL::X509::CertificateError.new("Certificate error"))
+ end
+
+ it { is_expected.to eq(connection_status: :authentication_failure) }
+ end
+
+ describe 'Kubeclient::HttpError' do
+ let(:error_code) { 403 }
+ let(:error_message) { "Forbidden" }
+
+ before do
+ allow(cluster.kubeclient.core_client).to receive(:discover)
+ .and_raise(Kubeclient::HttpError.new(error_code, error_message, nil))
+ end
+
+ it { is_expected.to eq(connection_status: :authentication_failure) }
+
+ context 'generic timeout' do
+ let(:error_message) { 'Timed out connecting to server'}
+
+ it { is_expected.to eq(connection_status: :unreachable) }
+ end
+
+ context 'gateway timeout' do
+ let(:error_message) { '504 Gateway Timeout for GET https://kubernetes.example.com/api/v1'}
+
+ it { is_expected.to eq(connection_status: :unreachable) }
+ end
+ end
+
+ context 'an uncategorised error is raised' do
+ before do
+ allow(cluster.kubeclient.core_client).to receive(:discover)
+ .and_raise(StandardError)
+ end
+
+ it { is_expected.to eq(connection_status: :unknown_failure) }
+
+ it 'notifies Sentry' do
+ expect(Gitlab::Sentry).to receive(:track_acceptable_exception)
+ .with(instance_of(StandardError), hash_including(extra: { cluster_id: cluster.id }))
+
+ subject
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb
index 0281dd2c303..c485850c16e 100644
--- a/spec/models/clusters/platforms/kubernetes_spec.rb
+++ b/spec/models/clusters/platforms/kubernetes_spec.rb
@@ -15,10 +15,8 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
it { is_expected.to validate_presence_of(:api_url) }
it { is_expected.to validate_presence_of(:token) }
- it { is_expected.to delegate_method(:project).to(:cluster) }
it { is_expected.to delegate_method(:enabled?).to(:cluster) }
it { is_expected.to delegate_method(:provided_by_user?).to(:cluster) }
- it { is_expected.to delegate_method(:kubernetes_namespace).to(:cluster) }
it_behaves_like 'having unique enum values'
@@ -209,7 +207,7 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
it { is_expected.to be_truthy }
end
- describe '#actual_namespace' do
+ describe '#kubernetes_namespace_for' do
let(:cluster) { create(:cluster, :project) }
let(:project) { cluster.project }
@@ -219,7 +217,7 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
namespace: namespace)
end
- subject { platform.actual_namespace }
+ subject { platform.kubernetes_namespace_for(project) }
context 'with a namespace assigned' do
let(:namespace) { 'namespace-123' }
@@ -305,8 +303,6 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
end
context 'no namespace provided' do
- let(:namespace) { kubernetes.actual_namespace }
-
it_behaves_like 'setting variables'
it 'sets KUBE_TOKEN' do
@@ -331,6 +327,18 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
{ key: 'KUBE_TOKEN', value: kubernetes.token, public: false }
)
end
+
+ context 'the cluster is not managed' do
+ let!(:cluster) { create(:cluster, :group, :not_managed, platform_kubernetes: kubernetes) }
+
+ it_behaves_like 'setting variables'
+
+ it 'sets KUBE_TOKEN' do
+ expect(subject).to include(
+ { key: 'KUBE_TOKEN', value: kubernetes.token, public: false, masked: true }
+ )
+ end
+ end
end
context 'kubernetes namespace exists for the project' do
@@ -377,7 +385,7 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
end
context 'with valid pods' do
- let(:pod) { kube_pod(environment_slug: environment.slug, project_slug: project.full_path_slug) }
+ let(:pod) { kube_pod(environment_slug: environment.slug, namespace: cluster.kubernetes_namespace_for(project), project_slug: project.full_path_slug) }
let(:pod_with_no_terminal) { kube_pod(environment_slug: environment.slug, project_slug: project.full_path_slug, status: "Pending") }
let(:terminals) { kube_terminals(service, pod) }
@@ -407,6 +415,7 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
let!(:cluster) { create(:cluster, :project, enabled: enabled, platform_kubernetes: service) }
let(:service) { create(:cluster_platform_kubernetes, :configured) }
let(:enabled) { true }
+ let(:namespace) { cluster.kubernetes_namespace_for(cluster.project) }
context 'when cluster is disabled' do
let(:enabled) { false }
@@ -416,8 +425,8 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
context 'when kubernetes responds with valid pods and deployments' do
before do
- stub_kubeclient_pods
- stub_kubeclient_deployments
+ stub_kubeclient_pods(namespace)
+ stub_kubeclient_deployments(namespace)
end
it { is_expected.to include(pods: [kube_pod]) }
@@ -425,8 +434,8 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
context 'when kubernetes responds with 500s' do
before do
- stub_kubeclient_pods(status: 500)
- stub_kubeclient_deployments(status: 500)
+ stub_kubeclient_pods(namespace, status: 500)
+ stub_kubeclient_deployments(namespace, status: 500)
end
it { expect { subject }.to raise_error(Kubeclient::HttpError) }
@@ -434,12 +443,18 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
context 'when kubernetes responds with 404s' do
before do
- stub_kubeclient_pods(status: 404)
- stub_kubeclient_deployments(status: 404)
+ stub_kubeclient_pods(namespace, status: 404)
+ stub_kubeclient_deployments(namespace, status: 404)
end
it { is_expected.to include(pods: []) }
end
+
+ context 'when the cluster is not project level' do
+ let(:cluster) { create(:cluster, :group, platform_kubernetes: service) }
+
+ it { is_expected.to include(pods: []) }
+ end
end
describe '#update_kubernetes_namespace' do
diff --git a/spec/models/clusters/project_spec.rb b/spec/models/clusters/project_spec.rb
index 2f017e69251..671af085d10 100644
--- a/spec/models/clusters/project_spec.rb
+++ b/spec/models/clusters/project_spec.rb
@@ -6,5 +6,4 @@ describe Clusters::Project do
it { is_expected.to belong_to(:cluster) }
it { is_expected.to belong_to(:project) }
it { is_expected.to have_many(:kubernetes_namespaces) }
- it { is_expected.to have_one(:kubernetes_namespace) }
end
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index 14f4b4d692f..e76186fb280 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -44,6 +44,14 @@ describe Commit do
expect(commit.id).to eq(oids[i])
end
end
+
+ it 'does not attempt to replace methods via BatchLoader' do
+ subject.each do |commit|
+ expect(commit).to receive(:method_missing).and_call_original
+
+ commit.id
+ end
+ end
end
context 'when not found' do
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index ca2f9e36c98..017cca0541e 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -449,7 +449,7 @@ describe CommitStatus do
end
it "lock" do
- is_expected.to be true
+ is_expected.to be_truthy
end
it "raise exception when trying to update" do
@@ -463,7 +463,7 @@ describe CommitStatus do
end
it "do not lock" do
- is_expected.to be false
+ is_expected.to be_falsey
end
it "save correctly" do
diff --git a/spec/models/concerns/cache_markdown_field_spec.rb b/spec/models/concerns/cache_markdown_field_spec.rb
index 78637ff10c6..0e5fb2b5153 100644
--- a/spec/models/concerns/cache_markdown_field_spec.rb
+++ b/spec/models/concerns/cache_markdown_field_spec.rb
@@ -2,383 +2,213 @@
require 'spec_helper'
-describe CacheMarkdownField do
- # The minimum necessary ActiveModel to test this concern
- class ThingWithMarkdownFields
- include ActiveModel::Model
- include ActiveModel::Dirty
-
- include ActiveModel::Serialization
-
- class_attribute :attribute_names
- self.attribute_names = []
-
- def attributes
- attribute_names.each_with_object({}) do |name, hsh|
- hsh[name.to_s] = send(name)
- end
+describe CacheMarkdownField, :clean_gitlab_redis_cache do
+ let(:ar_class) do
+ Class.new(ActiveRecord::Base) do
+ self.table_name = 'issues'
+ include CacheMarkdownField
+ cache_markdown_field :title, pipeline: :single_line
+ cache_markdown_field :description
end
+ end
- extend ActiveModel::Callbacks
- define_model_callbacks :create, :update
-
- include CacheMarkdownField
- cache_markdown_field :foo
- cache_markdown_field :baz, pipeline: :single_line
- cache_markdown_field :zoo, whitelisted: true
+ let(:other_class) do
+ Class.new do
+ include CacheMarkdownField
- def self.add_attr(name)
- self.attribute_names += [name]
- define_attribute_methods(name)
- attr_reader(name)
- define_method("#{name}=") do |value|
- write_attribute(name, value)
+ def initialize(args = {})
+ @title, @description, @cached_markdown_version = args[:title], args[:description], args[:cached_markdown_version]
+ @title_html, @description_html = args[:title_html], args[:description_html]
+ @author, @project = args[:author], args[:project]
end
- end
- add_attr :cached_markdown_version
+ attr_accessor :title, :description, :cached_markdown_version
- [:foo, :foo_html, :bar, :baz, :baz_html, :zoo, :zoo_html].each do |name|
- add_attr(name)
- end
-
- def initialize(*)
- super
-
- # Pretend new is load
- clear_changes_information
- end
-
- def read_attribute(name)
- instance_variable_get("@#{name}")
- end
-
- def write_attribute(name, value)
- send("#{name}_will_change!") unless value == read_attribute(name)
- instance_variable_set("@#{name}", value)
- end
+ cache_markdown_field :title, pipeline: :single_line
+ cache_markdown_field :description
- def save
- run_callbacks :update do
- changes_applied
+ def cache_key
+ "cache-key"
end
end
-
- def has_attribute?(attr_name)
- attribute_names.include?(attr_name)
- end
- end
-
- def thing_subclass(new_attr)
- Class.new(ThingWithMarkdownFields) { add_attr(new_attr) }
end
let(:markdown) { '`Foo`' }
- let(:html) { '<p dir="auto"><code>Foo</code></p>' }
+ let(:html) { '<p data-sourcepos="1:1-1:5" dir="auto"><code>Foo</code></p>' }
let(:updated_markdown) { '`Bar`' }
- let(:updated_html) { '<p dir="auto"><code>Bar</code></p>' }
-
- let(:thing) { ThingWithMarkdownFields.new(foo: markdown, foo_html: html, cached_markdown_version: cache_version) }
- let(:cache_version) { CacheMarkdownField::CACHE_COMMONMARK_VERSION << 16 }
-
- before do
- stub_commonmark_sourcepos_disabled
- end
+ let(:updated_html) { '<p data-sourcepos="1:1-1:5" dir="auto"><code>Bar</code></p>' }
- describe '.attributes' do
- it 'excludes cache attributes that is blacklisted by default' do
- expect(thing.attributes.keys.sort).to eq(%w[bar baz cached_markdown_version foo zoo zoo_html])
- end
- end
-
- context 'an unchanged markdown field' do
- before do
- thing.foo = thing.foo
- thing.save
- end
+ let(:cache_version) { Gitlab::MarkdownCache::CACHE_COMMONMARK_VERSION << 16 }
- it { expect(thing.foo).to eq(markdown) }
- it { expect(thing.foo_html).to eq(html) }
- it { expect(thing.foo_html_changed?).not_to be_truthy }
- it { expect(thing.cached_markdown_version).to eq(cache_version) }
+ def thing_subclass(klass, extra_attribute)
+ Class.new(klass) { attr_accessor(extra_attribute) }
end
- context 'a changed markdown field' do
- let(:thing) { ThingWithMarkdownFields.new(foo: markdown, foo_html: html, cached_markdown_version: cache_version - 1) }
+ shared_examples 'a class with cached markdown fields' do
+ describe '#cached_html_up_to_date?' do
+ let(:thing) { klass.new(title: markdown, title_html: html, cached_markdown_version: cache_version) }
- before do
- thing.foo = updated_markdown
- thing.save
- end
+ subject { thing.cached_html_up_to_date?(:title) }
- it { expect(thing.foo_html).to eq(updated_html) }
- it { expect(thing.cached_markdown_version).to eq(cache_version) }
- end
+ it 'returns false when the version is absent' do
+ thing.cached_markdown_version = nil
- context 'when a markdown field is set repeatedly to an empty string' do
- it do
- expect(thing).to receive(:refresh_markdown_cache).once
- thing.foo = ''
- thing.save
- thing.foo = ''
- thing.save
- end
- end
-
- context 'when a markdown field is set repeatedly to a string which renders as empty html' do
- it do
- expect(thing).to receive(:refresh_markdown_cache).once
- thing.foo = '[//]: # (This is also a comment.)'
- thing.save
- thing.foo = '[//]: # (This is also a comment.)'
- thing.save
- end
- end
-
- context 'when a markdown field and html field are both changed' do
- it do
- expect(thing).not_to receive(:refresh_markdown_cache)
- thing.foo = '_look over there!_'
- thing.foo_html = '<em>look over there!</em>'
- thing.save
- end
- end
-
- context 'a non-markdown field changed' do
- let(:thing) { ThingWithMarkdownFields.new(foo: markdown, foo_html: html, cached_markdown_version: cache_version - 1) }
-
- before do
- thing.bar = 'OK'
- thing.save
- end
-
- it { expect(thing.bar).to eq('OK') }
- it { expect(thing.foo).to eq(markdown) }
- it { expect(thing.foo_html).to eq(html) }
- it { expect(thing.cached_markdown_version).to eq(cache_version) }
- end
-
- context 'version is out of date' do
- let(:thing) { ThingWithMarkdownFields.new(foo: updated_markdown, foo_html: html, cached_markdown_version: nil) }
-
- before do
- thing.save
- end
-
- it { expect(thing.foo_html).to eq(updated_html) }
- it { expect(thing.cached_markdown_version).to eq(cache_version) }
- end
-
- describe '#cached_html_up_to_date?' do
- let(:thing) { ThingWithMarkdownFields.new(foo: markdown, foo_html: html, cached_markdown_version: cache_version) }
-
- subject { thing.cached_html_up_to_date?(:foo) }
-
- it 'returns false when the version is absent' do
- thing.cached_markdown_version = nil
-
- is_expected.to be_falsy
- end
-
- it 'returns false when the cached version is too old' do
- thing.cached_markdown_version = cache_version - 1
-
- is_expected.to be_falsy
- end
-
- it 'returns false when the cached version is in future' do
- thing.cached_markdown_version = cache_version + 1
-
- is_expected.to be_falsy
- end
-
- it 'returns false when the local version was bumped' do
- allow(Gitlab::CurrentSettings.current_application_settings).to receive(:local_markdown_version).and_return(2)
- thing.cached_markdown_version = cache_version
-
- is_expected.to be_falsy
- end
+ is_expected.to be_falsy
+ end
- it 'returns true when the local version is default' do
- thing.cached_markdown_version = cache_version
+ it 'returns false when the version is too early' do
+ thing.cached_markdown_version -= 1
- is_expected.to be_truthy
- end
+ is_expected.to be_falsy
+ end
- it 'returns true when the cached version is just right' do
- allow(Gitlab::CurrentSettings.current_application_settings).to receive(:local_markdown_version).and_return(2)
- thing.cached_markdown_version = cache_version + 2
+ it 'returns false when the version is too late' do
+ thing.cached_markdown_version += 1
- is_expected.to be_truthy
- end
+ is_expected.to be_falsy
+ end
- it 'returns false if markdown has been changed but html has not' do
- thing.foo = updated_html
+ it 'returns false when the local version was bumped' do
+ allow(Gitlab::CurrentSettings.current_application_settings).to receive(:local_markdown_version).and_return(2)
+ thing.cached_markdown_version = cache_version
- is_expected.to be_falsy
- end
+ is_expected.to be_falsy
+ end
- it 'returns true if markdown has not been changed but html has' do
- thing.foo_html = updated_html
+ it 'returns true when the local version is default' do
+ thing.cached_markdown_version = cache_version
- is_expected.to be_truthy
- end
+ is_expected.to be_truthy
+ end
- it 'returns true if markdown and html have both been changed' do
- thing.foo = updated_markdown
- thing.foo_html = updated_html
+ it 'returns true when the cached version is just right' do
+ allow(Gitlab::CurrentSettings.current_application_settings).to receive(:local_markdown_version).and_return(2)
+ thing.cached_markdown_version = cache_version + 2
- is_expected.to be_truthy
+ is_expected.to be_truthy
+ end
end
- it 'returns false if the markdown field is set but the html is not' do
- thing.foo_html = nil
+ describe '#latest_cached_markdown_version' do
+ let(:thing) { klass.new }
+ subject { thing.latest_cached_markdown_version }
- is_expected.to be_falsy
+ it 'returns default version' do
+ thing.cached_markdown_version = nil
+ is_expected.to eq(cache_version)
+ end
end
- end
-
- describe '#latest_cached_markdown_version' do
- subject { thing.latest_cached_markdown_version }
- it 'returns default version' do
- thing.cached_markdown_version = nil
- is_expected.to eq(cache_version)
- end
- end
+ describe '#refresh_markdown_cache' do
+ let(:thing) { klass.new(description: markdown, description_html: html, cached_markdown_version: cache_version) }
- describe '#refresh_markdown_cache' do
- before do
- thing.foo = updated_markdown
- end
+ before do
+ thing.description = updated_markdown
+ end
- it 'fills all html fields' do
- thing.refresh_markdown_cache
+ it 'fills all html fields' do
+ thing.refresh_markdown_cache
- expect(thing.foo_html).to eq(updated_html)
- expect(thing.foo_html_changed?).to be_truthy
- expect(thing.baz_html_changed?).to be_truthy
- end
+ expect(thing.description_html).to eq(updated_html)
+ end
- it 'does not save the result' do
- expect(thing).not_to receive(:update_columns)
+ it 'does not save the result' do
+ expect(thing).not_to receive(:save_markdown)
- thing.refresh_markdown_cache
- end
+ thing.refresh_markdown_cache
+ end
- it 'updates the markdown cache version' do
- thing.cached_markdown_version = nil
- thing.refresh_markdown_cache
+ it 'updates the markdown cache version' do
+ thing.cached_markdown_version = nil
+ thing.refresh_markdown_cache
- expect(thing.cached_markdown_version).to eq(cache_version)
+ expect(thing.cached_markdown_version).to eq(cache_version)
+ end
end
- end
-
- describe '#refresh_markdown_cache!' do
- let(:thing) { ThingWithMarkdownFields.new(foo: markdown, foo_html: html, cached_markdown_version: cache_version) }
- before do
- thing.foo = updated_markdown
- end
+ describe '#refresh_markdown_cache!' do
+ let(:thing) { klass.new(description: markdown, description_html: html, cached_markdown_version: cache_version) }
- it 'fills all html fields' do
- thing.refresh_markdown_cache!
+ before do
+ thing.description = updated_markdown
+ end
- expect(thing.foo_html).to eq(updated_html)
- expect(thing.foo_html_changed?).to be_truthy
- expect(thing.baz_html_changed?).to be_truthy
- end
+ it 'fills all html fields' do
+ thing.refresh_markdown_cache!
- it 'skips saving if not persisted' do
- expect(thing).to receive(:persisted?).and_return(false)
- expect(thing).not_to receive(:update_columns)
+ expect(thing.description_html).to eq(updated_html)
+ end
- thing.refresh_markdown_cache!
- end
+ it 'saves the changes' do
+ expect(thing)
+ .to receive(:save_markdown)
+ .with("description_html" => updated_html, "title_html" => "", "cached_markdown_version" => cache_version)
- it 'saves the changes using #update_columns' do
- expect(thing).to receive(:persisted?).and_return(true)
- expect(thing).to receive(:update_columns)
- .with(
- "foo_html" => updated_html,
- "baz_html" => "",
- "zoo_html" => "",
- "cached_markdown_version" => cache_version
- )
-
- thing.refresh_markdown_cache!
+ thing.refresh_markdown_cache!
+ end
end
- end
- describe '#banzai_render_context' do
- subject(:context) { thing.banzai_render_context(:foo) }
+ describe '#banzai_render_context' do
+ let(:thing) { klass.new(title: markdown, title_html: html, cached_markdown_version: cache_version) }
+ subject(:context) { thing.banzai_render_context(:title) }
- it 'sets project to nil if the object lacks a project' do
- is_expected.to have_key(:project)
- expect(context[:project]).to be_nil
- end
+ it 'sets project to nil if the object lacks a project' do
+ is_expected.to have_key(:project)
+ expect(context[:project]).to be_nil
+ end
- it 'excludes author if the object lacks an author' do
- is_expected.not_to have_key(:author)
- end
+ it 'excludes author if the object lacks an author' do
+ is_expected.not_to have_key(:author)
+ end
- it 'raises if the context for an unrecognised field is requested' do
- expect { thing.banzai_render_context(:not_found) }.to raise_error(ArgumentError)
- end
+ it 'raises if the context for an unrecognised field is requested' do
+ expect { thing.banzai_render_context(:not_found) }.to raise_error(ArgumentError)
+ end
- it 'includes the pipeline' do
- baz = thing.banzai_render_context(:baz)
+ it 'includes the pipeline' do
+ title_context = thing.banzai_render_context(:title)
- expect(baz[:pipeline]).to eq(:single_line)
- end
+ expect(title_context[:pipeline]).to eq(:single_line)
+ end
- it 'returns copies of the context template' do
- template = thing.cached_markdown_fields[:baz]
- copy = thing.banzai_render_context(:baz)
+ it 'returns copies of the context template' do
+ template = thing.cached_markdown_fields[:description]
+ copy = thing.banzai_render_context(:description)
- expect(copy).not_to be(template)
- end
+ expect(copy).not_to be(template)
+ end
- context 'with a project' do
- let(:project) { create(:project, group: create(:group)) }
- let(:thing) { thing_subclass(:project).new(foo: markdown, foo_html: html, project: project) }
+ context 'with a project' do
+ let(:project) { build(:project, group: create(:group)) }
+ let(:thing) { thing_subclass(klass, :project).new(title: markdown, title_html: html, project: project) }
- it 'sets the project in the context' do
- is_expected.to have_key(:project)
- expect(context[:project]).to eq(project)
+ it 'sets the project in the context' do
+ is_expected.to have_key(:project)
+ expect(context[:project]).to eq(project)
+ end
end
- it 'invalidates the cache when project changes' do
- thing.project = :new_project
- allow(Banzai::Renderer).to receive(:cacheless_render_field).and_return(updated_html)
-
- thing.save
+ context 'with an author' do
+ let(:thing) { thing_subclass(klass, :author).new(title: markdown, title_html: html, author: :author_value) }
- expect(thing.foo_html).to eq(updated_html)
- expect(thing.baz_html).to eq(updated_html)
- expect(thing.cached_markdown_version).to eq(cache_version)
+ it 'sets the author in the context' do
+ is_expected.to have_key(:author)
+ expect(context[:author]).to eq(:author_value)
+ end
end
end
+ end
- context 'with an author' do
- let(:thing) { thing_subclass(:author).new(foo: markdown, foo_html: html, author: :author_value) }
-
- it 'sets the author in the context' do
- is_expected.to have_key(:author)
- expect(context[:author]).to eq(:author_value)
- end
+ context 'for Active record classes' do
+ let(:klass) { ar_class }
- it 'invalidates the cache when author changes' do
- thing.author = :new_author
- allow(Banzai::Renderer).to receive(:cacheless_render_field).and_return(updated_html)
+ it_behaves_like 'a class with cached markdown fields'
+ end
- thing.save
+ context 'for other classes' do
+ let(:klass) { other_class }
- expect(thing.foo_html).to eq(updated_html)
- expect(thing.baz_html).to eq(updated_html)
- expect(thing.cached_markdown_version).to eq(cache_version)
- end
- end
+ it_behaves_like 'a class with cached markdown fields'
end
end
diff --git a/spec/models/concerns/has_ref_spec.rb b/spec/models/concerns/has_ref_spec.rb
index 6805731fed3..66b25c77430 100644
--- a/spec/models/concerns/has_ref_spec.rb
+++ b/spec/models/concerns/has_ref_spec.rb
@@ -19,7 +19,7 @@ describe HasRef do
context 'when it was triggered by merge request' do
let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) }
- let(:pipeline) { merge_request.merge_request_pipelines.first }
+ let(:pipeline) { merge_request.pipelines_for_merge_request.first }
let(:build) { create(:ci_build, pipeline: pipeline) }
it 'returns false' do
@@ -68,7 +68,7 @@ describe HasRef do
context 'when it is triggered by a merge request' do
let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) }
- let(:pipeline) { merge_request.merge_request_pipelines.first }
+ let(:pipeline) { merge_request.pipelines_for_merge_request.first }
let(:build) { create(:ci_build, tag: false, pipeline: pipeline) }
it 'returns nil' do
diff --git a/spec/models/concerns/milestoneish_spec.rb b/spec/models/concerns/milestoneish_spec.rb
index 22d4b2cc517..7e9a8306612 100644
--- a/spec/models/concerns/milestoneish_spec.rb
+++ b/spec/models/concerns/milestoneish_spec.rb
@@ -194,58 +194,6 @@ describe Milestone, 'Milestoneish' do
end
end
- describe '#closed_items_count' do
- it 'does not count confidential issues for non project members' do
- expect(milestone.closed_items_count(non_member)).to eq 2
- end
-
- it 'does not count confidential issues for project members with guest role' do
- expect(milestone.closed_items_count(guest)).to eq 2
- end
-
- it 'counts confidential issues for author' do
- expect(milestone.closed_items_count(author)).to eq 4
- end
-
- it 'counts confidential issues for assignee' do
- expect(milestone.closed_items_count(assignee)).to eq 4
- end
-
- it 'counts confidential issues for project members' do
- expect(milestone.closed_items_count(member)).to eq 6
- end
-
- it 'counts all issues for admin' do
- expect(milestone.closed_items_count(admin)).to eq 6
- end
- end
-
- describe '#total_items_count' do
- it 'does not count confidential issues for non project members' do
- expect(milestone.total_items_count(non_member)).to eq 4
- end
-
- it 'does not count confidential issues for project members with guest role' do
- expect(milestone.total_items_count(guest)).to eq 4
- end
-
- it 'counts confidential issues for author' do
- expect(milestone.total_items_count(author)).to eq 7
- end
-
- it 'counts confidential issues for assignee' do
- expect(milestone.total_items_count(assignee)).to eq 7
- end
-
- it 'counts confidential issues for project members' do
- expect(milestone.total_items_count(member)).to eq 10
- end
-
- it 'counts all issues for admin' do
- expect(milestone.total_items_count(admin)).to eq 10
- end
- end
-
describe '#complete?' do
it 'returns false when has items opened' do
expect(milestone.complete?(non_member)).to eq false
@@ -260,28 +208,42 @@ describe Milestone, 'Milestoneish' do
end
describe '#percent_complete' do
+ context 'division by zero' do
+ let(:new_milestone) { build_stubbed(:milestone) }
+
+ it { expect(new_milestone.percent_complete(admin)).to eq(0) }
+ end
+ end
+
+ describe '#count_issues_by_state' do
it 'does not count confidential issues for non project members' do
- expect(milestone.percent_complete(non_member)).to eq 50
+ expect(milestone.closed_issues_count(non_member)).to eq 2
+ expect(milestone.total_issues_count(non_member)).to eq 3
end
it 'does not count confidential issues for project members with guest role' do
- expect(milestone.percent_complete(guest)).to eq 50
+ expect(milestone.closed_issues_count(guest)).to eq 2
+ expect(milestone.total_issues_count(guest)).to eq 3
end
it 'counts confidential issues for author' do
- expect(milestone.percent_complete(author)).to eq 57
+ expect(milestone.closed_issues_count(author)).to eq 4
+ expect(milestone.total_issues_count(author)).to eq 6
end
it 'counts confidential issues for assignee' do
- expect(milestone.percent_complete(assignee)).to eq 57
+ expect(milestone.closed_issues_count(assignee)).to eq 4
+ expect(milestone.total_issues_count(assignee)).to eq 6
end
it 'counts confidential issues for project members' do
- expect(milestone.percent_complete(member)).to eq 60
+ expect(milestone.closed_issues_count(member)).to eq 6
+ expect(milestone.total_issues_count(member)).to eq 9
end
it 'counts confidential issues for admin' do
- expect(milestone.percent_complete(admin)).to eq 60
+ expect(milestone.closed_issues_count(admin)).to eq 6
+ expect(milestone.total_issues_count(admin)).to eq 9
end
end
diff --git a/spec/models/concerns/noteable_spec.rb b/spec/models/concerns/noteable_spec.rb
index ee613b199ad..e17b98536fa 100644
--- a/spec/models/concerns/noteable_spec.rb
+++ b/spec/models/concerns/noteable_spec.rb
@@ -260,4 +260,16 @@ describe Noteable do
end
end
end
+
+ describe '.replyable_types' do
+ it 'exposes the replyable types' do
+ expect(described_class.replyable_types).to include('Issue', 'MergeRequest')
+ end
+ end
+
+ describe '.resolvable_types' do
+ it 'exposes the replyable types' do
+ expect(described_class.resolvable_types).to include('MergeRequest')
+ end
+ end
end
diff --git a/spec/models/concerns/reactive_caching_spec.rb b/spec/models/concerns/reactive_caching_spec.rb
index 53df9e0bc05..7faa196623f 100644
--- a/spec/models/concerns/reactive_caching_spec.rb
+++ b/spec/models/concerns/reactive_caching_spec.rb
@@ -232,4 +232,17 @@ describe ReactiveCaching, :use_clean_rails_memory_store_caching do
end
end
end
+
+ describe 'default options' do
+ let(:cached_class) { Class.new { include ReactiveCaching } }
+
+ subject { cached_class.new }
+
+ it { expect(subject.reactive_cache_lease_timeout).to be_a(ActiveSupport::Duration) }
+ it { expect(subject.reactive_cache_refresh_interval).to be_a(ActiveSupport::Duration) }
+ it { expect(subject.reactive_cache_lifetime).to be_a(ActiveSupport::Duration) }
+
+ it { expect(subject.reactive_cache_key).to respond_to(:call) }
+ it { expect(subject.reactive_cache_worker_finder).to respond_to(:call) }
+ end
end
diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb
index d9170d5fa07..1dceef3fc00 100644
--- a/spec/models/deployment_spec.rb
+++ b/spec/models/deployment_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
describe Deployment do
subject { build(:deployment) }
- it { is_expected.to belong_to(:project) }
- it { is_expected.to belong_to(:environment) }
+ it { is_expected.to belong_to(:project).required }
+ it { is_expected.to belong_to(:environment).required }
it { is_expected.to belong_to(:user) }
it { is_expected.to belong_to(:deployable) }
@@ -102,6 +102,13 @@ describe Deployment do
deployment.succeed!
end
+
+ it 'executes Deployments::FinishedWorker asynchronously' do
+ expect(Deployments::FinishedWorker)
+ .to receive(:perform_async).with(deployment.id)
+
+ deployment.succeed!
+ end
end
context 'when deployment failed' do
@@ -115,6 +122,13 @@ describe Deployment do
expect(deployment.finished_at).to be_like_time(Time.now)
end
end
+
+ it 'executes Deployments::FinishedWorker asynchronously' do
+ expect(Deployments::FinishedWorker)
+ .to receive(:perform_async).with(deployment.id)
+
+ deployment.drop!
+ end
end
context 'when deployment was canceled' do
@@ -128,6 +142,13 @@ describe Deployment do
expect(deployment.finished_at).to be_like_time(Time.now)
end
end
+
+ it 'executes Deployments::FinishedWorker asynchronously' do
+ expect(Deployments::FinishedWorker)
+ .to receive(:perform_async).with(deployment.id)
+
+ deployment.cancel!
+ end
end
end
@@ -379,6 +400,12 @@ describe Deployment do
it { is_expected.to be_nil }
end
+ context 'project uses the kubernetes service for deployments' do
+ let!(:service) { create(:kubernetes_service, project: project) }
+
+ it { is_expected.to be_nil }
+ end
+
context 'project has a deployment platform' do
let!(:cluster) { create(:cluster, projects: [project]) }
let!(:platform) { create(:cluster_platform_kubernetes, cluster: cluster) }
diff --git a/spec/models/diff_note_spec.rb b/spec/models/diff_note_spec.rb
index fa19cb47a0d..d9e1fe4b165 100644
--- a/spec/models/diff_note_spec.rb
+++ b/spec/models/diff_note_spec.rb
@@ -321,6 +321,14 @@ describe DiffNote do
end
describe '#supports_suggestion?' do
+ context 'when noteable does not exist' do
+ it 'returns false' do
+ allow(subject).to receive(:noteable) { nil }
+
+ expect(subject.supports_suggestion?).to be(false)
+ end
+ end
+
context 'when noteable does not support suggestions' do
it 'returns false' do
allow(subject.noteable).to receive(:supports_suggestion?) { false }
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index cfe7c7ef0b0..7233d2454c6 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -6,7 +6,7 @@ describe Environment do
let(:project) { create(:project, :stubbed_repository) }
subject(:environment) { create(:environment, project: project) }
- it { is_expected.to belong_to(:project) }
+ it { is_expected.to belong_to(:project).required }
it { is_expected.to have_many(:deployments) }
it { is_expected.to delegate_method(:stop_action).to(:last_deployment) }
@@ -592,9 +592,7 @@ describe Environment do
shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
it 'returns the terminals from the deployment service' do
- deployment_platform_target = Gitlab.ee? ? environment : project
-
- expect(deployment_platform_target.deployment_platform)
+ expect(environment.deployment_platform)
.to receive(:terminals).with(environment)
.and_return(:fake_terminals)
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index e91b5c4c86f..62663c247d1 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -88,7 +88,7 @@ describe Event do
let(:event) { create_push_event(project, user) }
it do
- expect(event.push?).to be_truthy
+ expect(event.push_action?).to be_truthy
expect(event.visible_to_user?(user)).to be_truthy
expect(event.visible_to_user?(nil)).to be_falsey
expect(event.tag?).to be_falsey
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index e6e7298a043..d7accbef6bd 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -603,40 +603,96 @@ describe Group do
describe '#update_two_factor_requirement' do
let(:user) { create(:user) }
- before do
- group.add_user(user, GroupMember::OWNER)
- end
+ context 'group membership' do
+ before do
+ group.add_user(user, GroupMember::OWNER)
+ end
- it 'is called when require_two_factor_authentication is changed' do
- expect_any_instance_of(User).to receive(:update_two_factor_requirement)
+ it 'is called when require_two_factor_authentication is changed' do
+ expect_any_instance_of(User).to receive(:update_two_factor_requirement)
- group.update!(require_two_factor_authentication: true)
- end
+ group.update!(require_two_factor_authentication: true)
+ end
- it 'is called when two_factor_grace_period is changed' do
- expect_any_instance_of(User).to receive(:update_two_factor_requirement)
+ it 'is called when two_factor_grace_period is changed' do
+ expect_any_instance_of(User).to receive(:update_two_factor_requirement)
- group.update!(two_factor_grace_period: 23)
- end
+ group.update!(two_factor_grace_period: 23)
+ end
- it 'is not called when other attributes are changed' do
- expect_any_instance_of(User).not_to receive(:update_two_factor_requirement)
+ it 'is not called when other attributes are changed' do
+ expect_any_instance_of(User).not_to receive(:update_two_factor_requirement)
- group.update!(description: 'foobar')
+ group.update!(description: 'foobar')
+ end
+
+ it 'calls #update_two_factor_requirement on each group member' do
+ other_user = create(:user)
+ group.add_user(other_user, GroupMember::OWNER)
+
+ calls = 0
+ allow_any_instance_of(User).to receive(:update_two_factor_requirement) do
+ calls += 1
+ end
+
+ group.update!(require_two_factor_authentication: true, two_factor_grace_period: 23)
+
+ expect(calls).to eq 2
+ end
end
- it 'calls #update_two_factor_requirement on each group member' do
- other_user = create(:user)
- group.add_user(other_user, GroupMember::OWNER)
+ context 'sub groups and projects', :nested_groups do
+ it 'enables two_factor_requirement for group member' do
+ group.add_user(user, GroupMember::OWNER)
- calls = 0
- allow_any_instance_of(User).to receive(:update_two_factor_requirement) do
- calls += 1
+ group.update!(require_two_factor_authentication: true)
+
+ expect(user.reload.require_two_factor_authentication_from_group).to be_truthy
end
- group.update!(require_two_factor_authentication: true, two_factor_grace_period: 23)
+ context 'expanded group members', :nested_groups do
+ let(:indirect_user) { create(:user) }
+
+ it 'enables two_factor_requirement for subgroup member' do
+ subgroup = create(:group, :nested, parent: group)
+ subgroup.add_user(indirect_user, GroupMember::OWNER)
- expect(calls).to eq 2
+ group.update!(require_two_factor_authentication: true)
+
+ expect(indirect_user.reload.require_two_factor_authentication_from_group).to be_truthy
+ end
+
+ it 'does not enable two_factor_requirement for ancestor group member' do
+ ancestor_group = create(:group)
+ ancestor_group.add_user(indirect_user, GroupMember::OWNER)
+ group.update!(parent: ancestor_group)
+
+ group.update!(require_two_factor_authentication: true)
+
+ expect(indirect_user.reload.require_two_factor_authentication_from_group).to be_falsey
+ end
+ end
+
+ context 'project members' do
+ it 'does not enable two_factor_requirement for child project member' do
+ project = create(:project, group: group)
+ project.add_maintainer(user)
+
+ group.update!(require_two_factor_authentication: true)
+
+ expect(user.reload.require_two_factor_authentication_from_group).to be_falsey
+ end
+
+ it 'does not enable two_factor_requirement for subgroup child project member', :nested_groups do
+ subgroup = create(:group, :nested, parent: group)
+ project = create(:project, group: subgroup)
+ project.add_maintainer(user)
+
+ group.update!(require_two_factor_authentication: true)
+
+ expect(user.reload.require_two_factor_authentication_from_group).to be_falsey
+ end
+ end
end
end
diff --git a/spec/models/internal_id_spec.rb b/spec/models/internal_id_spec.rb
index 0ed4e146caa..806b4f61bd8 100644
--- a/spec/models/internal_id_spec.rb
+++ b/spec/models/internal_id_spec.rb
@@ -93,7 +93,7 @@ describe InternalId do
before do
described_class.reset_column_information
# Project factory will also call the current_version
- expect(ActiveRecord::Migrator).to receive(:current_version).twice.and_return(InternalId::REQUIRED_SCHEMA_VERSION - 1)
+ expect(ActiveRecord::Migrator).to receive(:current_version).at_least(:once).and_return(InternalId::REQUIRED_SCHEMA_VERSION - 1)
end
let(:init) { double('block') }
@@ -104,6 +104,15 @@ describe InternalId do
expect(init).to receive(:call).with(issue).and_return(val)
expect(subject).to eq(val + 1)
end
+
+ it 'always attempts to generate internal IDs in production mode' do
+ allow(Rails.env).to receive(:test?).and_return(false)
+ val = rand(1..100)
+ generator = double(generate: val)
+ expect(InternalId::InternalIdGenerator).to receive(:new).and_return(generator)
+
+ expect(subject).to eq(val)
+ end
end
end
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 0cd69cb4817..a5c7e9db2a1 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -55,6 +55,29 @@ describe Issue do
end
end
+ describe 'locking' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:lock_version) do
+ [
+ [0],
+ ["0"]
+ ]
+ end
+
+ with_them do
+ it 'works when an issue has a NULL lock_version' do
+ issue = create(:issue)
+
+ described_class.where(id: issue.id).update_all('lock_version = NULL')
+
+ issue.update!(lock_version: lock_version, title: 'locking test')
+
+ expect(issue.reload.title).to eq('locking test')
+ end
+ end
+ end
+
describe '#order_by_position_and_priority' do
let(:project) { create :project }
let(:p1) { create(:label, title: 'P1', project: project, priority: 1) }
@@ -70,6 +93,21 @@ describe Issue do
end
end
+ describe '#sort' do
+ let(:project) { create(:project) }
+
+ context "by relative_position" do
+ let!(:issue) { create(:issue, project: project) }
+ let!(:issue2) { create(:issue, project: project, relative_position: 2) }
+ let!(:issue3) { create(:issue, project: project, relative_position: 1) }
+
+ it "sorts asc with nulls at the end" do
+ issues = project.issues.sort_by_attribute('relative_position')
+ expect(issues).to eq([issue3, issue2, issue])
+ end
+ end
+ end
+
describe '#card_attributes' do
it 'includes the author name' do
allow(subject).to receive(:author).and_return(double(name: 'Robert'))
diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb
index c68c3ce2abe..782a84f922b 100644
--- a/spec/models/member_spec.rb
+++ b/spec/models/member_spec.rb
@@ -70,6 +70,16 @@ describe Member do
expect(child_member).not_to be_valid
end
+ # Membership in a subgroup confers certain access rights, such as being
+ # able to merge or push code to protected branches.
+ it "is valid with an equal level" do
+ child_member.access_level = GroupMember::DEVELOPER
+
+ child_member.validate
+
+ expect(child_member).to be_valid
+ end
+
it "is valid with a higher level" do
child_member.access_level = GroupMember::MAINTAINER
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index f61857ea5ff..c6251326c22 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -31,6 +31,29 @@ describe MergeRequest do
end
end
+ describe 'locking' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:lock_version) do
+ [
+ [0],
+ ["0"]
+ ]
+ end
+
+ with_them do
+ it 'works when a merge request has a NULL lock_version' do
+ merge_request = create(:merge_request)
+
+ described_class.where(id: merge_request.id).update_all('lock_version = NULL')
+
+ merge_request.update!(lock_version: lock_version, title: 'locking test')
+
+ expect(merge_request.reload.title).to eq('locking test')
+ end
+ end
+ end
+
describe '#squash_in_progress?' do
let(:repo_path) do
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
@@ -150,6 +173,42 @@ describe MergeRequest do
end
end
+ context 'for branch' do
+ before do
+ stub_feature_flags(stricter_mr_branch_name: false)
+ end
+
+ using RSpec::Parameterized::TableSyntax
+
+ where(:branch_name, :valid) do
+ 'foo' | true
+ 'foo:bar' | false
+ '+foo:bar' | false
+ 'foo bar' | false
+ '-foo' | false
+ 'HEAD' | true
+ 'refs/heads/master' | true
+ end
+
+ with_them do
+ it "validates source_branch" do
+ subject = build(:merge_request, source_branch: branch_name, target_branch: 'master')
+
+ subject.valid?
+
+ expect(subject.errors.added?(:source_branch)).to eq(!valid)
+ end
+
+ it "validates target_branch" do
+ subject = build(:merge_request, source_branch: 'master', target_branch: branch_name)
+
+ subject.valid?
+
+ expect(subject.errors.added?(:target_branch)).to eq(!valid)
+ end
+ end
+ end
+
context 'for forks' do
let(:project) { create(:project) }
let(:fork1) { fork_project(project) }
@@ -1015,19 +1074,17 @@ describe MergeRequest do
end
end
- describe "#reset_merge_when_pipeline_succeeds" do
- let(:merge_if_green) do
- create :merge_request, merge_when_pipeline_succeeds: true, merge_user: create(:user),
- merge_params: { "should_remove_source_branch" => "1", "commit_message" => "msg" }
- end
+ describe "#auto_merge_strategy" do
+ subject { merge_request.auto_merge_strategy }
- it "sets the item to false" do
- merge_if_green.reset_merge_when_pipeline_succeeds
- merge_if_green.reload
+ let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
- expect(merge_if_green.merge_when_pipeline_succeeds).to be_falsey
- expect(merge_if_green.merge_params["should_remove_source_branch"]).to be_nil
- expect(merge_if_green.merge_params["commit_message"]).to be_nil
+ it { is_expected.to eq('merge_when_pipeline_succeeds') }
+
+ context 'when auto merge is disabled' do
+ let(:merge_request) { create(:merge_request) }
+
+ it { is_expected.to be_nil }
end
end
@@ -2123,7 +2180,7 @@ describe MergeRequest do
end
context 'when merges are not restricted to green builds' do
- subject { build(:merge_request, target_project: build(:project, only_allow_merge_if_pipeline_succeeds: false)) }
+ subject { build(:merge_request, target_project: create(:project, only_allow_merge_if_pipeline_succeeds: false)) }
context 'and a failed pipeline is associated' do
before do
@@ -2262,6 +2319,50 @@ describe MergeRequest do
end
end
+ describe "#environments" do
+ subject { merge_request.environments }
+
+ let(:merge_request) { create(:merge_request, source_branch: 'feature', target_branch: 'master') }
+ let(:project) { merge_request.project }
+
+ let(:pipeline) do
+ create(:ci_pipeline,
+ source: :merge_request_event,
+ merge_request: merge_request, project: project,
+ sha: merge_request.diff_head_sha,
+ merge_requests_as_head_pipeline: [merge_request])
+ end
+
+ let!(:job) { create(:ci_build, :start_review_app, pipeline: pipeline, project: project) }
+
+ it 'returns environments' do
+ is_expected.to eq(pipeline.environments)
+ expect(subject.count).to be(1)
+ end
+
+ context 'when pipeline is not associated with environments' do
+ let!(:job) { create(:ci_build, pipeline: pipeline, project: project) }
+
+ it 'returns empty array' do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'when pipeline is not a pipeline for merge request' do
+ let(:pipeline) do
+ create(:ci_pipeline,
+ project: project,
+ ref: 'feature',
+ sha: merge_request.diff_head_sha,
+ merge_requests_as_head_pipeline: [merge_request])
+ end
+
+ it 'returns empty relation' do
+ is_expected.to be_empty
+ end
+ end
+ end
+
describe "#reload_diff" do
it 'calls MergeRequests::ReloadDiffsService#execute with correct params' do
user = create(:user)
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index b82368318f2..3704a2d468d 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -31,12 +31,28 @@ describe Milestone do
end
describe 'start_date' do
- it 'adds an error when start_date is greated then due_date' do
+ it 'adds an error when start_date is greater then due_date' do
milestone = build(:milestone, start_date: Date.tomorrow, due_date: Date.yesterday)
expect(milestone).not_to be_valid
expect(milestone.errors[:due_date]).to include("must be greater than start date")
end
+
+ it 'adds an error when start_date is greater than 9999-12-31' do
+ milestone = build(:milestone, start_date: Date.new(10000, 1, 1))
+
+ expect(milestone).not_to be_valid
+ expect(milestone.errors[:start_date]).to include("date must not be after 9999-12-31")
+ end
+ end
+
+ describe 'due_date' do
+ it 'adds an error when due_date is greater than 9999-12-31' do
+ milestone = build(:milestone, due_date: Date.new(10000, 1, 1))
+
+ expect(milestone).not_to be_valid
+ expect(milestone.errors[:due_date]).to include("date must not be after 9999-12-31")
+ end
end
end
@@ -166,32 +182,10 @@ describe Milestone do
end
end
- describe '#percent_complete' do
- before do
- allow(milestone).to receive_messages(
- closed_items_count: 3,
- total_items_count: 4
- )
- end
-
- it { expect(milestone.percent_complete(user)).to eq(75) }
- end
-
describe '#can_be_closed?' do
it { expect(milestone.can_be_closed?).to be_truthy }
end
- describe '#total_items_count' do
- before do
- create :closed_issue, milestone: milestone, project: project
- create :merge_request, milestone: milestone, source_project: project
- end
-
- it 'returns total count of issues and merge requests assigned to milestone' do
- expect(milestone.total_items_count(user)).to eq 2
- end
- end
-
describe '#can_be_closed?' do
before do
milestone = create :milestone, project: project
@@ -381,21 +375,6 @@ describe Milestone do
expect(milestone_ids).to be_empty
end
end
-
- context 'when there is a milestone with a date after 294276 AD', :postgresql do
- before do
- past_milestone_project_1.update!(due_date: Date.new(294277, 1, 1))
- end
-
- it 'returns the next upcoming open milestone ID for each project and group' do
- expect(milestone_ids).to contain_exactly(
- current_milestone_project_1.id,
- current_milestone_project_2.id,
- current_milestone_group_1.id,
- current_milestone_group_2.id
- )
- end
- end
end
describe '#to_reference' do
@@ -519,4 +498,20 @@ describe Milestone do
end
end
end
+
+ describe '.reference_pattern' do
+ subject { described_class.reference_pattern }
+
+ it { is_expected.to match('gitlab-org/gitlab-ce%123') }
+ it { is_expected.to match('gitlab-org/gitlab-ce%"my-milestone"') }
+ end
+
+ describe '.link_reference_pattern' do
+ subject { described_class.link_reference_pattern }
+
+ it { is_expected.to match("#{Gitlab.config.gitlab.url}/gitlab-org/gitlab-ce/milestones/123") }
+ it { is_expected.to match("#{Gitlab.config.gitlab.url}/gitlab-org/gitlab-ce/-/milestones/123") }
+ it { is_expected.not_to match("#{Gitlab.config.gitlab.url}/gitlab-org/gitlab-ce/issues/123") }
+ it { is_expected.not_to match("gitlab-org/gitlab-ce/milestones/123") }
+ end
end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 387d1221c76..d80183af33e 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -63,6 +63,11 @@ describe Namespace do
end
end
+ describe 'delegate' do
+ it { is_expected.to delegate_method(:name).to(:owner).with_prefix.with_arguments(allow_nil: true) }
+ it { is_expected.to delegate_method(:avatar_url).to(:owner).with_arguments(allow_nil: true) }
+ end
+
describe "Respond to" do
it { is_expected.to respond_to(:human_name) }
it { is_expected.to respond_to(:to_param) }
@@ -141,20 +146,22 @@ describe Namespace do
create(:project,
namespace: namespace,
statistics: build(:project_statistics,
- storage_size: 606,
repository_size: 101,
+ wiki_size: 505,
lfs_objects_size: 202,
- build_artifacts_size: 303))
+ build_artifacts_size: 303,
+ packages_size: 404))
end
let(:project2) do
create(:project,
namespace: namespace,
statistics: build(:project_statistics,
- storage_size: 60,
repository_size: 10,
+ wiki_size: 50,
lfs_objects_size: 20,
- build_artifacts_size: 30))
+ build_artifacts_size: 30,
+ packages_size: 40))
end
it "sums all project storage counters in the namespace" do
@@ -162,10 +169,12 @@ describe Namespace do
project2
statistics = described_class.with_statistics.find(namespace.id)
- expect(statistics.storage_size).to eq 666
+ expect(statistics.storage_size).to eq 1665
expect(statistics.repository_size).to eq 111
+ expect(statistics.wiki_size).to eq 555
expect(statistics.lfs_objects_size).to eq 222
expect(statistics.build_artifacts_size).to eq 333
+ expect(statistics.packages_size).to eq 444
end
it "correctly handles namespaces without projects" do
@@ -173,8 +182,10 @@ describe Namespace do
expect(statistics.storage_size).to eq 0
expect(statistics.repository_size).to eq 0
+ expect(statistics.wiki_size).to eq 0
expect(statistics.lfs_objects_size).to eq 0
expect(statistics.build_artifacts_size).to eq 0
+ expect(statistics.packages_size).to eq 0
end
end
@@ -738,22 +749,25 @@ describe Namespace do
end
end
- describe '#full_path_was' do
+ describe '#full_path_before_last_save' do
context 'when the group has no parent' do
- it 'returns the path was' do
- group = create(:group, parent: nil)
- expect(group.full_path_was).to eq(group.path_was)
+ it 'returns the path before last save' do
+ group = create(:group)
+
+ group.update(parent: nil)
+
+ expect(group.full_path_before_last_save).to eq(group.path_before_last_save)
end
end
context 'when a parent is assigned to a group with no previous parent' do
- it 'returns the path was' do
+ it 'returns the path before last save' do
group = create(:group, parent: nil)
-
parent = create(:group)
- group.parent = parent
- expect(group.full_path_was).to eq("#{group.path_was}")
+ group.update(parent: parent)
+
+ expect(group.full_path_before_last_save).to eq("#{group.path_before_last_save}")
end
end
@@ -761,9 +775,10 @@ describe Namespace do
it 'returns the parent full path' do
parent = create(:group)
group = create(:group, parent: parent)
- group.parent = nil
- expect(group.full_path_was).to eq("#{parent.full_path}/#{group.path}")
+ group.update(parent: nil)
+
+ expect(group.full_path_before_last_save).to eq("#{parent.full_path}/#{group.path}")
end
end
@@ -772,8 +787,10 @@ describe Namespace do
parent = create(:group)
group = create(:group, parent: parent)
new_parent = create(:group)
- group.parent = new_parent
- expect(group.full_path_was).to eq("#{parent.full_path}/#{group.path}")
+
+ group.update(parent: new_parent)
+
+ expect(group.full_path_before_last_save).to eq("#{parent.full_path}/#{group.path}")
end
end
end
@@ -801,4 +818,21 @@ describe Namespace do
end
end
end
+
+ describe '#user?' do
+ subject { namespace.user? }
+
+ context 'when type is a user' do
+ let(:user) { create(:user) }
+ let(:namespace) { user.namespace }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when type is a group' do
+ let(:namespace) { create(:group) }
+
+ it { is_expected.to be_falsy }
+ end
+ end
end
diff --git a/spec/models/note_diff_file_spec.rb b/spec/models/note_diff_file_spec.rb
index 99eeac8d778..b15bedd257e 100644
--- a/spec/models/note_diff_file_spec.rb
+++ b/spec/models/note_diff_file_spec.rb
@@ -10,4 +10,31 @@ describe NoteDiffFile do
describe 'validations' do
it { is_expected.to validate_presence_of(:diff_note) }
end
+
+ describe '.referencing_sha' do
+ let!(:diff_note) { create(:diff_note_on_commit) }
+
+ let(:note_diff_file) { diff_note.note_diff_file }
+ let(:project) { diff_note.project }
+
+ it 'finds note diff files by project and sha' do
+ found = described_class.referencing_sha(diff_note.commit_id, project_id: project.id)
+
+ expect(found).to contain_exactly(note_diff_file)
+ end
+
+ it 'excludes note diff files with the wrong project' do
+ other_project = create(:project)
+
+ found = described_class.referencing_sha(diff_note.commit_id, project_id: other_project.id)
+
+ expect(found).to be_empty
+ end
+
+ it 'excludes note diff files with the wrong sha' do
+ found = described_class.referencing_sha(Gitlab::Git::BLANK_SHA, project_id: project.id)
+
+ expect(found).to be_empty
+ end
+ end
end
diff --git a/spec/models/notification_recipient_spec.rb b/spec/models/notification_recipient_spec.rb
index 3710f2be287..20278d81f6d 100644
--- a/spec/models/notification_recipient_spec.rb
+++ b/spec/models/notification_recipient_spec.rb
@@ -9,11 +9,43 @@ describe NotificationRecipient do
subject(:recipient) { described_class.new(user, :watch, target: target, project: project) }
- it 'denies access to a target when cross project access is denied' do
- allow(Ability).to receive(:allowed?).and_call_original
- expect(Ability).to receive(:allowed?).with(user, :read_cross_project, :global).and_return(false)
+ describe '#has_access?' do
+ before do
+ allow(user).to receive(:can?).and_call_original
+ end
+
+ context 'user cannot read cross project' do
+ it 'returns false' do
+ expect(user).to receive(:can?).with(:read_cross_project).and_return(false)
+ expect(recipient.has_access?).to eq false
+ end
+ end
+
+ context 'user cannot read build' do
+ let(:target) { build(:ci_pipeline) }
+
+ it 'returns false' do
+ expect(user).to receive(:can?).with(:read_build, target).and_return(false)
+ expect(recipient.has_access?).to eq false
+ end
+ end
+
+ context 'user cannot read commit' do
+ let(:target) { build(:commit) }
+
+ it 'returns false' do
+ expect(user).to receive(:can?).with(:read_commit, target).and_return(false)
+ expect(recipient.has_access?).to eq false
+ end
+ end
- expect(recipient.has_access?).to be_falsy
+ context 'target has no policy' do
+ let(:target) { double.as_null_object }
+
+ it 'returns true' do
+ expect(recipient.has_access?).to eq true
+ end
+ end
end
context '#notification_setting' do
@@ -59,4 +91,237 @@ describe NotificationRecipient do
end
end
end
+
+ describe '#suitable_notification_level?' do
+ context 'when notification level is mention' do
+ before do
+ user.notification_settings_for(project).mention!
+ end
+
+ context 'when type is mention' do
+ let(:recipient) { described_class.new(user, :mention, target: target, project: project) }
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+
+ context 'when type is not mention' do
+ it 'returns false' do
+ expect(recipient.suitable_notification_level?).to eq false
+ end
+ end
+ end
+
+ context 'when notification level is participating' do
+ let(:notification_setting) { user.notification_settings_for(project) }
+
+ context 'when type is participating' do
+ let(:recipient) { described_class.new(user, :participating, target: target, project: project) }
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+
+ context 'when type is mention' do
+ let(:recipient) { described_class.new(user, :mention, target: target, project: project) }
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+
+ context 'with custom action' do
+ context "when action is failed_pipeline" do
+ let(:recipient) do
+ described_class.new(
+ user,
+ :watch,
+ custom_action: :failed_pipeline,
+ target: target,
+ project: project
+ )
+ end
+
+ before do
+ notification_setting.update!(failed_pipeline: true)
+ end
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+
+ context "when action is not failed_pipeline" do
+ let(:recipient) do
+ described_class.new(
+ user,
+ :watch,
+ custom_action: :success_pipeline,
+ target: target,
+ project: project
+ )
+ end
+
+ before do
+ notification_setting.update!(success_pipeline: true)
+ end
+
+ it 'returns false' do
+ expect(recipient.suitable_notification_level?).to eq false
+ end
+ end
+ end
+ end
+
+ context 'when notification level is custom' do
+ before do
+ user.notification_settings_for(project).custom!
+ end
+
+ context 'when type is participating' do
+ let(:notification_setting) { user.notification_settings_for(project) }
+ let(:recipient) do
+ described_class.new(
+ user,
+ :participating,
+ custom_action: :new_note,
+ target: target,
+ project: project
+ )
+ end
+
+ context 'with custom event enabled' do
+ before do
+ notification_setting.update!(new_note: true)
+ end
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+
+ context 'without custom event enabled' do
+ before do
+ notification_setting.update!(new_note: false)
+ end
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+ end
+
+ context 'when type is mention' do
+ let(:notification_setting) { user.notification_settings_for(project) }
+ let(:recipient) do
+ described_class.new(
+ user,
+ :mention,
+ custom_action: :new_issue,
+ target: target,
+ project: project
+ )
+ end
+
+ context 'with custom event enabled' do
+ before do
+ notification_setting.update!(new_issue: true)
+ end
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+
+ context 'without custom event enabled' do
+ before do
+ notification_setting.update!(new_issue: false)
+ end
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+ end
+
+ context 'when type is watch' do
+ let(:notification_setting) { user.notification_settings_for(project) }
+ let(:recipient) do
+ described_class.new(
+ user,
+ :watch,
+ custom_action: :failed_pipeline,
+ target: target,
+ project: project
+ )
+ end
+
+ context 'with custom event enabled' do
+ before do
+ notification_setting.update!(failed_pipeline: true)
+ end
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+
+ context 'without custom event enabled' do
+ before do
+ notification_setting.update!(failed_pipeline: false)
+ end
+
+ it 'returns false' do
+ expect(recipient.suitable_notification_level?).to eq false
+ end
+ end
+ end
+ end
+
+ context 'when notification level is watch' do
+ before do
+ user.notification_settings_for(project).watch!
+ end
+
+ context 'when type is watch' do
+ context 'without excluded watcher events' do
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+
+ context 'with excluded watcher events' do
+ let(:recipient) do
+ described_class.new(user, :watch, custom_action: :issue_due, target: target, project: project)
+ end
+
+ it 'returns false' do
+ expect(recipient.suitable_notification_level?).to eq false
+ end
+ end
+ end
+
+ context 'when type is not watch' do
+ context 'without excluded watcher events' do
+ let(:recipient) { described_class.new(user, :participating, target: target, project: project) }
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+
+ context 'with excluded watcher events' do
+ let(:recipient) do
+ described_class.new(user, :participating, custom_action: :issue_due, target: target, project: project)
+ end
+
+ it 'returns true' do
+ expect(recipient.suitable_notification_level?).to eq true
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/pages_domain_acme_order_spec.rb b/spec/models/pages_domain_acme_order_spec.rb
new file mode 100644
index 00000000000..4ffb4fc7389
--- /dev/null
+++ b/spec/models/pages_domain_acme_order_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe PagesDomainAcmeOrder do
+ using RSpec::Parameterized::TableSyntax
+
+ describe '.expired' do
+ let!(:not_expired_order) { create(:pages_domain_acme_order) }
+ let!(:expired_order) { create(:pages_domain_acme_order, :expired) }
+
+ it 'returns only expired orders' do
+ expect(described_class.count).to eq(2)
+ expect(described_class.expired).to eq([expired_order])
+ end
+ end
+
+ describe '.find_by_domain_and_token' do
+ let!(:domain) { create(:pages_domain, domain: 'test.com') }
+ let!(:acme_order) { create(:pages_domain_acme_order, challenge_token: 'righttoken', pages_domain: domain) }
+
+ where(:domain_name, :challenge_token, :present) do
+ 'test.com' | 'righttoken' | true
+ 'test.com' | 'wrongtoken' | false
+ 'test.org' | 'righttoken' | false
+ end
+
+ with_them do
+ subject { described_class.find_by_domain_and_token(domain_name, challenge_token).present? }
+
+ it { is_expected.to eq(present) }
+ end
+ end
+
+ subject { create(:pages_domain_acme_order) }
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:pages_domain) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:pages_domain) }
+ it { is_expected.to validate_presence_of(:expires_at) }
+ it { is_expected.to validate_presence_of(:url) }
+ it { is_expected.to validate_presence_of(:challenge_token) }
+ it { is_expected.to validate_presence_of(:challenge_file_content) }
+ it { is_expected.to validate_presence_of(:private_key) }
+ end
+end
diff --git a/spec/models/pages_domain_spec.rb b/spec/models/pages_domain_spec.rb
index 142ddebbbf8..fdc81359d34 100644
--- a/spec/models/pages_domain_spec.rb
+++ b/spec/models/pages_domain_spec.rb
@@ -81,6 +81,17 @@ describe PagesDomain do
end
end
+ describe 'when certificate is specified' do
+ let(:domain) { build(:pages_domain) }
+
+ it 'saves validity time' do
+ domain.save
+
+ expect(domain.certificate_valid_not_before).to be_like_time(Time.parse("2016-02-12 14:32:00 UTC"))
+ expect(domain.certificate_valid_not_after).to be_like_time(Time.parse("2020-04-12 14:32:00 UTC"))
+ end
+ end
+
describe 'validate certificate' do
subject { domain }
@@ -344,4 +355,32 @@ describe PagesDomain do
end
end
end
+
+ describe '.for_removal' do
+ subject { described_class.for_removal }
+
+ context 'when domain is not schedule for removal' do
+ let!(:domain) { create :pages_domain }
+
+ it 'does not return domain' do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'when domain is scheduled for removal yesterday' do
+ let!(:domain) { create :pages_domain, remove_at: 1.day.ago }
+
+ it 'returns domain' do
+ is_expected.to eq([domain])
+ end
+ end
+
+ context 'when domain is scheduled for removal tomorrow' do
+ let!(:domain) { create :pages_domain, remove_at: 1.day.from_now }
+
+ it 'does not return domain' do
+ is_expected.to be_empty
+ end
+ end
+ end
end
diff --git a/spec/models/pool_repository_spec.rb b/spec/models/pool_repository_spec.rb
index e5a3a3ad66e..ae00f9df89e 100644
--- a/spec/models/pool_repository_spec.rb
+++ b/spec/models/pool_repository_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
describe PoolRepository do
describe 'associations' do
it { is_expected.to belong_to(:shard) }
- it { is_expected.to have_one(:source_project) }
+ it { is_expected.to belong_to(:source_project) }
it { is_expected.to have_many(:member_projects) }
end
diff --git a/spec/models/project_auto_devops_spec.rb b/spec/models/project_auto_devops_spec.rb
index b81e5610e2c..7bdd2367a68 100644
--- a/spec/models/project_auto_devops_spec.rb
+++ b/spec/models/project_auto_devops_spec.rb
@@ -14,65 +14,9 @@ describe ProjectAutoDevops do
it { is_expected.to respond_to(:created_at) }
it { is_expected.to respond_to(:updated_at) }
- describe '#has_domain?' do
- context 'when domain is defined' do
- let(:auto_devops) { build_stubbed(:project_auto_devops, project: project, domain: 'domain.com') }
-
- it { expect(auto_devops).to have_domain }
- end
-
- context 'when domain is empty' do
- let(:auto_devops) { build_stubbed(:project_auto_devops, project: project, domain: '') }
-
- context 'when there is an instance domain specified' do
- before do
- allow(Gitlab::CurrentSettings).to receive(:auto_devops_domain).and_return('example.com')
- end
-
- it { expect(auto_devops).to have_domain }
- end
-
- context 'when there is no instance domain specified' do
- before do
- allow(Gitlab::CurrentSettings).to receive(:auto_devops_domain).and_return(nil)
- end
-
- it { expect(auto_devops).not_to have_domain }
- end
- end
- end
-
describe '#predefined_variables' do
let(:auto_devops) { build_stubbed(:project_auto_devops, project: project, domain: domain) }
- context 'when domain is defined' do
- let(:domain) { 'example.com' }
-
- it 'returns AUTO_DEVOPS_DOMAIN' do
- expect(auto_devops.predefined_variables).to include(domain_variable)
- end
- end
-
- context 'when domain is not defined' do
- let(:domain) { nil }
-
- context 'when there is an instance domain specified' do
- before do
- allow(Gitlab::CurrentSettings).to receive(:auto_devops_domain).and_return('example.com')
- end
-
- it { expect(auto_devops.predefined_variables).to include(domain_variable) }
- end
-
- context 'when there is no instance domain specified' do
- before do
- allow(Gitlab::CurrentSettings).to receive(:auto_devops_domain).and_return(nil)
- end
-
- it { expect(auto_devops.predefined_variables).not_to include(domain_variable) }
- end
- end
-
context 'when deploy_strategy is manual' do
let(:auto_devops) { build_stubbed(:project_auto_devops, :manual_deployment, project: project) }
let(:expected_variables) do
@@ -105,10 +49,6 @@ describe ProjectAutoDevops do
.not_to include("STAGING_ENABLED", "INCREMENTAL_ROLLOUT_ENABLED")
end
end
-
- def domain_variable
- { key: 'AUTO_DEVOPS_DOMAIN', value: 'example.com', public: true }
- end
end
describe '#create_gitlab_deploy_token' do
diff --git a/spec/models/project_ci_cd_setting_spec.rb b/spec/models/project_ci_cd_setting_spec.rb
index 4aa62028169..eb3a7e527c9 100644
--- a/spec/models/project_ci_cd_setting_spec.rb
+++ b/spec/models/project_ci_cd_setting_spec.rb
@@ -21,4 +21,44 @@ describe ProjectCiCdSetting do
2.times { described_class.available? }
end
end
+
+ describe 'validations' do
+ it 'validates default_git_depth is between 0 and 1000 or nil' do
+ expect(subject).to validate_numericality_of(:default_git_depth)
+ .only_integer
+ .is_greater_than_or_equal_to(0)
+ .is_less_than_or_equal_to(1000)
+ .allow_nil
+ end
+ end
+
+ describe '#default_git_depth' do
+ let(:default_value) { described_class::DEFAULT_GIT_DEPTH }
+
+ it 'sets default value for new records' do
+ project = create(:project)
+
+ expect(project.ci_cd_settings.default_git_depth).to eq(default_value)
+ end
+
+ it 'does not set default value if present' do
+ project = build(:project)
+ project.build_ci_cd_settings(default_git_depth: 0)
+ project.save!
+
+ expect(project.reload.ci_cd_settings.default_git_depth).to eq(0)
+ end
+
+ context 'when feature flag :ci_set_project_default_git_depth is disabled' do
+ let(:project) { create(:project) }
+
+ before do
+ stub_feature_flags(ci_set_project_default_git_depth: { enabled: false } )
+ end
+
+ it 'does not set default value for new records' do
+ expect(project.ci_cd_settings.default_git_depth).to eq(nil)
+ end
+ end
+ end
end
diff --git a/spec/models/project_metrics_setting_spec.rb b/spec/models/project_metrics_setting_spec.rb
new file mode 100644
index 00000000000..7df01625ba1
--- /dev/null
+++ b/spec/models/project_metrics_setting_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ProjectMetricsSetting do
+ describe 'Associations' do
+ it { is_expected.to belong_to(:project) }
+ end
+
+ describe 'Validations' do
+ context 'when external_dashboard_url is over 255 chars' do
+ before do
+ subject.external_dashboard_url = 'https://' + 'a' * 250
+ end
+
+ it 'fails validation' do
+ expect(subject).not_to be_valid
+ expect(subject.errors.messages[:external_dashboard_url])
+ .to include('is too long (maximum is 255 characters)')
+ end
+ end
+
+ context 'with unsafe url' do
+ before do
+ subject.external_dashboard_url = %{https://replaceme.com/'><script>alert(document.cookie)</script>}
+ end
+
+ it { is_expected.to be_invalid }
+ end
+
+ context 'non ascii chars in external_dashboard_url' do
+ before do
+ subject.external_dashboard_url = 'http://gitlab.com/api/0/projects/project1/something€'
+ end
+
+ it { is_expected.to be_invalid }
+ end
+
+ context 'internal url in external_dashboard_url' do
+ before do
+ subject.external_dashboard_url = 'http://192.168.1.1'
+ end
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'external_dashboard_url is blank' do
+ before do
+ subject.external_dashboard_url = ''
+ end
+
+ it { is_expected.to be_invalid }
+ end
+ end
+end
diff --git a/spec/models/project_services/assembla_service_spec.rb b/spec/models/project_services/assembla_service_spec.rb
index 7742e33e901..2c86c0ec7be 100644
--- a/spec/models/project_services/assembla_service_spec.rb
+++ b/spec/models/project_services/assembla_service_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe AssemblaService do
+ include StubRequests
+
describe "Associations" do
it { is_expected.to belong_to :project }
it { is_expected.to have_one :service_hook }
@@ -23,12 +25,12 @@ describe AssemblaService do
)
@sample_data = Gitlab::DataBuilder::Push.build_sample(project, user)
@api_url = 'https://atlas.assembla.com/spaces/project_name/github_tool?secret_key=verySecret'
- WebMock.stub_request(:post, @api_url)
+ stub_full_request(@api_url, method: :post)
end
it "calls Assembla API" do
@assembla_service.execute(@sample_data)
- expect(WebMock).to have_requested(:post, @api_url).with(
+ expect(WebMock).to have_requested(:post, stubbed_hostname(@api_url)).with(
body: /#{@sample_data[:before]}.*#{@sample_data[:after]}.*#{project.path}/
).once
end
diff --git a/spec/models/project_services/bamboo_service_spec.rb b/spec/models/project_services/bamboo_service_spec.rb
index 08c510f09df..65d227a17f9 100644
--- a/spec/models/project_services/bamboo_service_spec.rb
+++ b/spec/models/project_services/bamboo_service_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
describe BambooService, :use_clean_rails_memory_store_caching do
include ReactiveCachingHelpers
+ include StubRequests
let(:bamboo_url) { 'http://gitlab.com/bamboo' }
@@ -257,7 +258,7 @@ describe BambooService, :use_clean_rails_memory_store_caching do
end
def stub_bamboo_request(url, status, body)
- WebMock.stub_request(:get, url).to_return(
+ stub_full_request(url).to_return(
status: status,
headers: { 'Content-Type' => 'application/json' },
body: body
diff --git a/spec/models/project_services/buildkite_service_spec.rb b/spec/models/project_services/buildkite_service_spec.rb
index 091d4d8f695..ca196069055 100644
--- a/spec/models/project_services/buildkite_service_spec.rb
+++ b/spec/models/project_services/buildkite_service_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
describe BuildkiteService, :use_clean_rails_memory_store_caching do
include ReactiveCachingHelpers
+ include StubRequests
let(:project) { create(:project) }
@@ -110,10 +111,9 @@ describe BuildkiteService, :use_clean_rails_memory_store_caching do
body ||= %q({"status":"success"})
buildkite_full_url = 'https://gitlab.buildkite.com/status/secret-sauce-status-token.json?commit=123'
- WebMock.stub_request(:get, buildkite_full_url).to_return(
- status: status,
- headers: { 'Content-Type' => 'application/json' },
- body: body
- )
+ stub_full_request(buildkite_full_url)
+ .to_return(status: status,
+ headers: { 'Content-Type' => 'application/json' },
+ body: body)
end
end
diff --git a/spec/models/project_services/campfire_service_spec.rb b/spec/models/project_services/campfire_service_spec.rb
index bf4c52fc7ab..0d3dd89e93b 100644
--- a/spec/models/project_services/campfire_service_spec.rb
+++ b/spec/models/project_services/campfire_service_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe CampfireService do
+ include StubRequests
+
describe 'Associations' do
it { is_expected.to belong_to :project }
it { is_expected.to have_one :service_hook }
@@ -49,39 +51,37 @@ describe CampfireService do
it "calls Campfire API to get a list of rooms and speak in a room" do
# make sure a valid list of rooms is returned
body = File.read(Rails.root + 'spec/fixtures/project_services/campfire/rooms.json')
- WebMock.stub_request(:get, @rooms_url).with(basic_auth: @auth).to_return(
+
+ stub_full_request(@rooms_url).with(basic_auth: @auth).to_return(
body: body,
status: 200,
headers: @headers
)
+
# stub the speak request with the room id found in the previous request's response
speak_url = 'https://project-name.campfirenow.com/room/123/speak.json'
- WebMock.stub_request(:post, speak_url).with(basic_auth: @auth)
+ stub_full_request(speak_url, method: :post).with(basic_auth: @auth)
@campfire_service.execute(@sample_data)
- expect(WebMock).to have_requested(:get, @rooms_url).once
- expect(WebMock).to have_requested(:post, speak_url).with(
- body: /#{project.path}.*#{@sample_data[:before]}.*#{@sample_data[:after]}/
- ).once
+ expect(WebMock).to have_requested(:get, stubbed_hostname(@rooms_url)).once
+ expect(WebMock).to have_requested(:post, stubbed_hostname(speak_url))
+ .with(body: /#{project.path}.*#{@sample_data[:before]}.*#{@sample_data[:after]}/).once
end
it "calls Campfire API to get a list of rooms but shouldn't speak in a room" do
# return a list of rooms that do not contain a room named 'test-room'
body = File.read(Rails.root + 'spec/fixtures/project_services/campfire/rooms2.json')
- WebMock.stub_request(:get, @rooms_url).with(basic_auth: @auth).to_return(
+ stub_full_request(@rooms_url).with(basic_auth: @auth).to_return(
body: body,
status: 200,
headers: @headers
)
- # we want to make sure no request is sent to the /speak endpoint, here is a basic
- # regexp that matches this endpoint
- speak_url = 'https://verySecret:X@project-name.campfirenow.com/room/.*/speak.json'
@campfire_service.execute(@sample_data)
- expect(WebMock).to have_requested(:get, @rooms_url).once
- expect(WebMock).not_to have_requested(:post, /#{speak_url}/)
+ expect(WebMock).to have_requested(:get, 'https://8.8.8.9/rooms.json').once
+ expect(WebMock).not_to have_requested(:post, '*/room/.*/speak.json')
end
end
end
diff --git a/spec/models/project_services/chat_message/deployment_message_spec.rb b/spec/models/project_services/chat_message/deployment_message_spec.rb
new file mode 100644
index 00000000000..42c1689db3d
--- /dev/null
+++ b/spec/models/project_services/chat_message/deployment_message_spec.rb
@@ -0,0 +1,153 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ChatMessage::DeploymentMessage do
+ describe '#pretext' do
+ it 'returns a message with the data returned by the deployment data builder' do
+ environment = create(:environment, name: "myenvironment")
+ project = create(:project, :repository)
+ commit = project.commit('HEAD')
+ deployment = create(:deployment, status: :success, environment: environment, project: project, sha: commit.sha)
+ data = Gitlab::DataBuilder::Deployment.build(deployment)
+
+ message = described_class.new(data)
+
+ expect(message.pretext).to eq("Deploy to myenvironment succeeded")
+ end
+
+ it 'returns a message for a successful deployment' do
+ data = {
+ status: 'success',
+ environment: 'production'
+ }
+
+ message = described_class.new(data)
+
+ expect(message.pretext).to eq('Deploy to production succeeded')
+ end
+
+ it 'returns a message for a failed deployment' do
+ data = {
+ status: 'failed',
+ environment: 'production'
+ }
+
+ message = described_class.new(data)
+
+ expect(message.pretext).to eq('Deploy to production failed')
+ end
+
+ it 'returns a message for a canceled deployment' do
+ data = {
+ status: 'canceled',
+ environment: 'production'
+ }
+
+ message = described_class.new(data)
+
+ expect(message.pretext).to eq('Deploy to production canceled')
+ end
+
+ it 'returns a message for a deployment to another environment' do
+ data = {
+ status: 'success',
+ environment: 'staging'
+ }
+
+ message = described_class.new(data)
+
+ expect(message.pretext).to eq('Deploy to staging succeeded')
+ end
+
+ it 'returns a message for a deployment with any other status' do
+ data = {
+ status: 'unknown',
+ environment: 'staging'
+ }
+
+ message = described_class.new(data)
+
+ expect(message.pretext).to eq('Deploy to staging unknown')
+ end
+ end
+
+ describe '#attachments' do
+ def deployment_data(params)
+ {
+ object_kind: "deployment",
+ status: "success",
+ deployable_id: 3,
+ deployable_url: "deployable_url",
+ environment: "sandbox",
+ project: {
+ name: "greatproject",
+ web_url: "project_web_url",
+ path_with_namespace: "project_path_with_namespace"
+ },
+ user: {
+ name: "Jane Person",
+ username: "jane"
+ },
+ user_url: "user_url",
+ short_sha: "12345678",
+ commit_url: "commit_url",
+ commit_title: "commit title text"
+ }.merge(params)
+ end
+
+ it 'returns attachments with the data returned by the deployment data builder' do
+ user = create(:user, name: "John Smith", username: "smith")
+ namespace = create(:namespace, name: "myspace")
+ project = create(:project, :repository, namespace: namespace, name: "myproject")
+ commit = project.commit('HEAD')
+ environment = create(:environment, name: "myenvironment", project: project)
+ ci_build = create(:ci_build, project: project)
+ deployment = create(:deployment, :success, deployable: ci_build, environment: environment, project: project, user: user, sha: commit.sha)
+ job_url = Gitlab::Routing.url_helpers.project_job_url(project, ci_build)
+ commit_url = Gitlab::UrlBuilder.build(deployment.commit)
+ user_url = Gitlab::Routing.url_helpers.user_url(user)
+ data = Gitlab::DataBuilder::Deployment.build(deployment)
+
+ message = described_class.new(data)
+
+ expect(message.attachments).to eq([{
+ text: "[myspace/myproject](#{project.web_url}) with job [##{ci_build.id}](#{job_url}) by [John Smith (smith)](#{user_url})\n[#{deployment.short_sha}](#{commit_url}): #{commit.title}",
+ color: "good"
+ }])
+ end
+
+ it 'returns attachments for a failed deployment' do
+ data = deployment_data(status: 'failed')
+
+ message = described_class.new(data)
+
+ expect(message.attachments).to eq([{
+ text: "[project_path_with_namespace](project_web_url) with job [#3](deployable_url) by [Jane Person (jane)](user_url)\n[12345678](commit_url): commit title text",
+ color: "danger"
+ }])
+ end
+
+ it 'returns attachments for a canceled deployment' do
+ data = deployment_data(status: 'canceled')
+
+ message = described_class.new(data)
+
+ expect(message.attachments).to eq([{
+ text: "[project_path_with_namespace](project_web_url) with job [#3](deployable_url) by [Jane Person (jane)](user_url)\n[12345678](commit_url): commit title text",
+ color: "warning"
+ }])
+ end
+
+ it 'uses a neutral color for a deployment with any other status' do
+ data = deployment_data(status: 'some-new-status-we-make-in-the-future')
+
+ message = described_class.new(data)
+
+ expect(message.attachments).to eq([{
+ text: "[project_path_with_namespace](project_web_url) with job [#3](deployable_url) by [Jane Person (jane)](user_url)\n[12345678](commit_url): commit title text",
+ color: "#334455"
+ }])
+ end
+ end
+end
diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb
index fd9e33c1781..a04b984c1f6 100644
--- a/spec/models/project_services/hipchat_service_spec.rb
+++ b/spec/models/project_services/hipchat_service_spec.rb
@@ -98,12 +98,11 @@ describe HipchatService do
context 'tag_push events' do
let(:push_sample_data) do
Gitlab::DataBuilder::Push.build(
- project,
- user,
- Gitlab::Git::BLANK_SHA,
- '1' * 40,
- 'refs/tags/test',
- [])
+ project: project,
+ user: user,
+ oldrev: Gitlab::Git::BLANK_SHA,
+ newrev: '1' * 40,
+ ref: 'refs/tags/test')
end
it "calls Hipchat API for tag push events" do
diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
index 4a7eee1fbf3..04ae9390436 100644
--- a/spec/models/project_services/jira_service_spec.rb
+++ b/spec/models/project_services/jira_service_spec.rb
@@ -166,6 +166,13 @@ describe JiraService do
).once
end
+ it 'does not fail if remote_link.all on issue returns nil' do
+ allow(JIRA::Resource::Remotelink).to receive(:all).and_return(nil)
+
+ expect { @jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project)) }
+ .not_to raise_error(NoMethodError)
+ end
+
# Check https://developer.atlassian.com/jiradev/jira-platform/guides/other/guide-jira-remote-issue-links/fields-in-remote-issue-links
# for more information
it 'creates Remote Link reference in JIRA for comment' do
diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb
index 3a381cb405d..2fce120381b 100644
--- a/spec/models/project_services/kubernetes_service_spec.rb
+++ b/spec/models/project_services/kubernetes_service_spec.rb
@@ -161,8 +161,8 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
end
end
- describe '#actual_namespace' do
- subject { service.actual_namespace }
+ describe '#kubernetes_namespace_for' do
+ subject { service.kubernetes_namespace_for(project) }
shared_examples 'a correctly formatted namespace' do
it 'returns a valid Kubernetes namespace name' do
@@ -298,7 +298,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
end
context 'no namespace provided' do
- let(:namespace) { subject.actual_namespace }
+ let(:namespace) { subject.kubernetes_namespace_for(project) }
it_behaves_like 'setting variables'
@@ -325,7 +325,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
end
context 'with valid pods' do
- let(:pod) { kube_pod(environment_slug: environment.slug, project_slug: project.full_path_slug) }
+ let(:pod) { kube_pod(environment_slug: environment.slug, namespace: service.kubernetes_namespace_for(project), project_slug: project.full_path_slug) }
let(:pod_with_no_terminal) { kube_pod(environment_slug: environment.slug, project_slug: project.full_path_slug, status: "Pending") }
let(:terminals) { kube_terminals(service, pod) }
@@ -352,6 +352,8 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
describe '#calculate_reactive_cache' do
subject { service.calculate_reactive_cache }
+ let(:namespace) { service.kubernetes_namespace_for(project) }
+
context 'when service is inactive' do
before do
service.active = false
@@ -362,8 +364,8 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
context 'when kubernetes responds with valid pods' do
before do
- stub_kubeclient_pods
- stub_kubeclient_deployments # Used by EE
+ stub_kubeclient_pods(namespace)
+ stub_kubeclient_deployments(namespace) # Used by EE
end
it { is_expected.to include(pods: [kube_pod]) }
@@ -371,8 +373,8 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
context 'when kubernetes responds with 500s' do
before do
- stub_kubeclient_pods(status: 500)
- stub_kubeclient_deployments(status: 500) # Used by EE
+ stub_kubeclient_pods(namespace, status: 500)
+ stub_kubeclient_deployments(namespace, status: 500) # Used by EE
end
it { expect { subject }.to raise_error(Kubeclient::HttpError) }
@@ -380,8 +382,8 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
context 'when kubernetes responds with 404s' do
before do
- stub_kubeclient_pods(status: 404)
- stub_kubeclient_deployments(status: 404) # Used by EE
+ stub_kubeclient_pods(namespace, status: 404)
+ stub_kubeclient_deployments(namespace, status: 404) # Used by EE
end
it { is_expected.to include(pods: []) }
diff --git a/spec/models/project_services/microsoft_teams_service_spec.rb b/spec/models/project_services/microsoft_teams_service_spec.rb
index 521d5265753..c025d7c882e 100644
--- a/spec/models/project_services/microsoft_teams_service_spec.rb
+++ b/spec/models/project_services/microsoft_teams_service_spec.rb
@@ -30,6 +30,12 @@ describe MicrosoftTeamsService do
end
end
+ describe '.supported_events' do
+ it 'does not support deployment_events' do
+ expect(described_class.supported_events).not_to include('deployment')
+ end
+ end
+
describe "#execute" do
let(:user) { create(:user) }
set(:project) { create(:project, :repository, :wiki_repo) }
diff --git a/spec/models/project_services/pipelines_email_service_spec.rb b/spec/models/project_services/pipelines_email_service_spec.rb
index ca17e7453b8..b85565e0c25 100644
--- a/spec/models/project_services/pipelines_email_service_spec.rb
+++ b/spec/models/project_services/pipelines_email_service_spec.rb
@@ -4,7 +4,11 @@ require 'spec_helper'
describe PipelinesEmailService, :mailer do
let(:pipeline) do
- create(:ci_pipeline, project: project, sha: project.commit('master').sha)
+ create(:ci_pipeline, :failed,
+ project: project,
+ sha: project.commit('master').sha,
+ ref: project.default_branch
+ )
end
let(:project) { create(:project, :repository) }
@@ -84,12 +88,7 @@ describe PipelinesEmailService, :mailer do
subject.test(data)
end
- context 'when pipeline is failed' do
- before do
- data[:object_attributes][:status] = 'failed'
- pipeline.update(status: 'failed')
- end
-
+ context 'when pipeline is failed and on default branch' do
it_behaves_like 'sending email'
end
@@ -101,6 +100,25 @@ describe PipelinesEmailService, :mailer do
it_behaves_like 'sending email'
end
+
+ context 'when pipeline is failed and on a non-default branch' do
+ before do
+ data[:object_attributes][:ref] = 'not-the-default-branch'
+ pipeline.update(ref: 'not-the-default-branch')
+ end
+
+ context 'with notify_only_default branch on' do
+ before do
+ subject.notify_only_default_branch = true
+ end
+
+ it_behaves_like 'sending email'
+ end
+
+ context 'with notify_only_default_branch off' do
+ it_behaves_like 'sending email'
+ end
+ end
end
describe '#execute' do
@@ -110,11 +128,6 @@ describe PipelinesEmailService, :mailer do
context 'with recipients' do
context 'with failed pipeline' do
- before do
- data[:object_attributes][:status] = 'failed'
- pipeline.update(status: 'failed')
- end
-
it_behaves_like 'sending email'
end
@@ -133,11 +146,6 @@ describe PipelinesEmailService, :mailer do
end
context 'with failed pipeline' do
- before do
- data[:object_attributes][:status] = 'failed'
- pipeline.update(status: 'failed')
- end
-
it_behaves_like 'sending email'
end
@@ -150,6 +158,40 @@ describe PipelinesEmailService, :mailer do
it_behaves_like 'not sending email'
end
end
+
+ context 'with notify_only_default_branch off' do
+ context 'with default branch' do
+ it_behaves_like 'sending email'
+ end
+
+ context 'with non default branch' do
+ before do
+ data[:object_attributes][:ref] = 'not-the-default-branch'
+ pipeline.update(ref: 'not-the-default-branch')
+ end
+
+ it_behaves_like 'sending email'
+ end
+ end
+
+ context 'with notify_only_default_branch on' do
+ before do
+ subject.notify_only_default_branch = true
+ end
+
+ context 'with default branch' do
+ it_behaves_like 'sending email'
+ end
+
+ context 'with non default branch' do
+ before do
+ data[:object_attributes][:ref] = 'not-the-default-branch'
+ pipeline.update(ref: 'not-the-default-branch')
+ end
+
+ it_behaves_like 'not sending email'
+ end
+ end
end
context 'with empty recipients list' do
diff --git a/spec/models/project_services/pivotaltracker_service_spec.rb b/spec/models/project_services/pivotaltracker_service_spec.rb
index 773b8b7890f..dde46c82df6 100644
--- a/spec/models/project_services/pivotaltracker_service_spec.rb
+++ b/spec/models/project_services/pivotaltracker_service_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe PivotaltrackerService do
+ include StubRequests
+
describe 'Associations' do
it { is_expected.to belong_to :project }
it { is_expected.to have_one :service_hook }
@@ -53,12 +55,12 @@ describe PivotaltrackerService do
end
before do
- WebMock.stub_request(:post, url)
+ stub_full_request(url, method: :post)
end
it 'posts correct message' do
service.execute(push_data)
- expect(WebMock).to have_requested(:post, url).with(
+ expect(WebMock).to have_requested(:post, stubbed_hostname(url)).with(
body: {
'source_commit' => {
'commit_id' => '21c12ea',
@@ -85,14 +87,14 @@ describe PivotaltrackerService do
service.execute(push_data(branch: 'master'))
service.execute(push_data(branch: 'v10'))
- expect(WebMock).to have_requested(:post, url).twice
+ expect(WebMock).to have_requested(:post, stubbed_hostname(url)).twice
end
it 'does not post message if branch is not in the list' do
service.execute(push_data(branch: 'mas'))
service.execute(push_data(branch: 'v11'))
- expect(WebMock).not_to have_requested(:post, url)
+ expect(WebMock).not_to have_requested(:post, stubbed_hostname(url))
end
end
end
diff --git a/spec/models/project_services/pushover_service_spec.rb b/spec/models/project_services/pushover_service_spec.rb
index d2a45f48705..380f02739bc 100644
--- a/spec/models/project_services/pushover_service_spec.rb
+++ b/spec/models/project_services/pushover_service_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe PushoverService do
+ include StubRequests
+
describe 'Associations' do
it { is_expected.to belong_to :project }
it { is_expected.to have_one :service_hook }
@@ -57,13 +59,13 @@ describe PushoverService do
sound: sound
)
- WebMock.stub_request(:post, api_url)
+ stub_full_request(api_url, method: :post, ip_address: '8.8.8.8')
end
it 'calls Pushover API' do
pushover.execute(sample_data)
- expect(WebMock).to have_requested(:post, api_url).once
+ expect(WebMock).to have_requested(:post, 'https://8.8.8.8/1/messages.json').once
end
end
end
diff --git a/spec/models/project_services/teamcity_service_spec.rb b/spec/models/project_services/teamcity_service_spec.rb
index 96dccae733b..1c434b25205 100644
--- a/spec/models/project_services/teamcity_service_spec.rb
+++ b/spec/models/project_services/teamcity_service_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
describe TeamcityService, :use_clean_rails_memory_store_caching do
include ReactiveCachingHelpers
+ include StubRequests
let(:teamcity_url) { 'http://gitlab.com/teamcity' }
@@ -212,7 +213,7 @@ describe TeamcityService, :use_clean_rails_memory_store_caching do
body ||= %Q({"build":{"status":"#{build_status}","id":"666"}})
- WebMock.stub_request(:get, teamcity_full_url).with(basic_auth: auth).to_return(
+ stub_full_request(teamcity_full_url).with(basic_auth: auth).to_return(
status: status,
headers: { 'Content-Type' => 'application/json' },
body: body
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 9f6a0b53281..aad08b9d4aa 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -214,6 +214,13 @@ describe Project do
expect(project2).not_to be_valid
end
+ it 'validates the visibility' do
+ expect_any_instance_of(described_class).to receive(:visibility_level_allowed_as_fork).and_call_original
+ expect_any_instance_of(described_class).to receive(:visibility_level_allowed_by_group).and_call_original
+
+ create(:project)
+ end
+
describe 'wiki path conflict' do
context "when the new path has been used by the wiki of other Project" do
it 'has an error on the name attribute' do
@@ -1140,7 +1147,7 @@ describe Project do
allow(project).to receive(:avatar_in_git) { true }
end
- let(:avatar_path) { "/#{project.full_path}/avatar" }
+ let(:avatar_path) { "/#{project.full_path}/-/avatar" }
it { is_expected.to eq "http://#{Gitlab.config.gitlab.host}#{avatar_path}" }
end
@@ -3163,62 +3170,123 @@ describe Project do
end
end
- describe '.with_feature_available_for_user' do
+ describe '.ids_with_milestone_available_for' do
let!(:user) { create(:user) }
- let!(:feature) { MergeRequest }
- let!(:project) { create(:project, :public, :merge_requests_enabled) }
+
+ it 'returns project ids with milestones available for user' do
+ project_1 = create(:project, :public, :merge_requests_disabled, :issues_disabled)
+ project_2 = create(:project, :public, :merge_requests_disabled)
+ project_3 = create(:project, :public, :issues_disabled)
+ project_4 = create(:project, :public)
+ project_4.project_feature.update(issues_access_level: ProjectFeature::PRIVATE, merge_requests_access_level: ProjectFeature::PRIVATE )
+
+ project_ids = described_class.ids_with_milestone_available_for(user).pluck(:id)
+
+ expect(project_ids).to include(project_2.id, project_3.id)
+ expect(project_ids).not_to include(project_1.id, project_4.id)
+ end
+ end
+
+ describe '.with_feature_available_for_user' do
+ let(:user) { create(:user) }
+ let(:feature) { MergeRequest }
subject { described_class.with_feature_available_for_user(feature, user) }
- context 'when user has access to project' do
- subject { described_class.with_feature_available_for_user(feature, user) }
+ shared_examples 'feature disabled' do
+ let(:project) { create(:project, :public, :merge_requests_disabled) }
+
+ it 'does not return projects with the project feature disabled' do
+ is_expected.not_to include(project)
+ end
+ end
+
+ shared_examples 'feature public' do
+ let(:project) { create(:project, :public, :merge_requests_public) }
+
+ it 'returns projects with the project feature public' do
+ is_expected.to include(project)
+ end
+ end
+
+ shared_examples 'feature enabled' do
+ let(:project) { create(:project, :public, :merge_requests_enabled) }
+
+ it 'returns projects with the project feature enabled' do
+ is_expected.to include(project)
+ end
+ end
+
+ shared_examples 'feature access level is nil' do
+ let(:project) { create(:project, :public) }
+
+ it 'returns projects with the project feature access level nil' do
+ project.project_feature.update(merge_requests_access_level: nil)
+ is_expected.to include(project)
+ end
+ end
+
+ context 'with user' do
before do
project.add_guest(user)
end
- context 'when public project' do
- context 'when feature is public' do
- it 'returns project' do
- is_expected.to include(project)
+ it_behaves_like 'feature disabled'
+ it_behaves_like 'feature public'
+ it_behaves_like 'feature enabled'
+ it_behaves_like 'feature access level is nil'
+
+ context 'when feature is private' do
+ let(:project) { create(:project, :public, :merge_requests_private) }
+
+ context 'when user does not has access to the feature' do
+ it 'does not return projects with the project feature private' do
+ is_expected.not_to include(project)
end
end
- context 'when feature is private' do
- let!(:project) { create(:project, :public, :merge_requests_private) }
-
- it 'returns project when user has access to the feature' do
- project.add_maintainer(user)
+ context 'when user has access to the feature' do
+ it 'returns projects with the project feature private' do
+ project.add_reporter(user)
is_expected.to include(project)
end
-
- it 'does not return project when user does not have the minimum access level required' do
- is_expected.not_to include(project)
- end
end
end
+ end
- context 'when private project' do
- let!(:project) { create(:project) }
+ context 'user is an admin' do
+ let(:user) { create(:user, :admin) }
- it 'returns project when user has access to the feature' do
- project.add_maintainer(user)
+ it_behaves_like 'feature disabled'
+ it_behaves_like 'feature public'
+ it_behaves_like 'feature enabled'
+ it_behaves_like 'feature access level is nil'
- is_expected.to include(project)
- end
+ context 'when feature is private' do
+ let(:project) { create(:project, :public, :merge_requests_private) }
- it 'does not return project when user does not have the minimum access level required' do
- is_expected.not_to include(project)
+ it 'returns projects with the project feature private' do
+ is_expected.to include(project)
end
end
end
- context 'when user does not have access to project' do
- let!(:project) { create(:project) }
+ context 'without user' do
+ let(:user) { nil }
- it 'does not return project when user cant access project' do
- is_expected.not_to include(project)
+ it_behaves_like 'feature disabled'
+ it_behaves_like 'feature public'
+ it_behaves_like 'feature enabled'
+ it_behaves_like 'feature access level is nil'
+
+ context 'when feature is private' do
+ let(:project) { create(:project, :public, :merge_requests_private) }
+
+ it 'does not return projects with the project feature private' do
+ is_expected.not_to include(project)
+ end
end
end
end
@@ -3924,64 +3992,6 @@ describe Project do
end
end
- describe '#auto_devops_variables' do
- set(:project) { create(:project) }
-
- subject { project.auto_devops_variables }
-
- context 'when enabled in instance settings' do
- before do
- stub_application_setting(auto_devops_enabled: true)
- end
-
- context 'when domain is empty' do
- before do
- stub_application_setting(auto_devops_domain: nil)
- end
-
- it 'variables does not include AUTO_DEVOPS_DOMAIN' do
- is_expected.not_to include(domain_variable)
- end
- end
-
- context 'when domain is configured' do
- before do
- stub_application_setting(auto_devops_domain: 'example.com')
- end
-
- it 'variables includes AUTO_DEVOPS_DOMAIN' do
- is_expected.to include(domain_variable)
- end
- end
- end
-
- context 'when explicitly enabled' do
- context 'when domain is empty' do
- before do
- create(:project_auto_devops, project: project, domain: nil)
- end
-
- it 'variables does not include AUTO_DEVOPS_DOMAIN' do
- is_expected.not_to include(domain_variable)
- end
- end
-
- context 'when domain is configured' do
- before do
- create(:project_auto_devops, project: project, domain: 'example.com')
- end
-
- it 'variables includes AUTO_DEVOPS_DOMAIN' do
- is_expected.to include(domain_variable)
- end
- end
- end
-
- def domain_variable
- { key: 'AUTO_DEVOPS_DOMAIN', value: 'example.com', public: true }
- end
- end
-
describe '#latest_successful_builds_for' do
let(:project) { build(:project) }
@@ -4702,6 +4712,8 @@ describe Project do
it 'returns that pool repository' do
expect(subject).not_to be_empty
expect(subject[:pool_repository]).to be_persisted
+
+ expect(project.reload.pool_repository).to eq(subject[:pool_repository])
end
end
end
diff --git a/spec/models/project_statistics_spec.rb b/spec/models/project_statistics_spec.rb
index c670b6aac56..1cb49d83ffa 100644
--- a/spec/models/project_statistics_spec.rb
+++ b/spec/models/project_statistics_spec.rb
@@ -11,21 +11,37 @@ describe ProjectStatistics do
it { is_expected.to belong_to(:namespace) }
end
+ describe 'scopes' do
+ describe '.for_project_ids' do
+ it 'returns only requested projects' do
+ stats = create_list(:project_statistics, 3)
+ project_ids = stats[0..1].map { |s| s.project_id }
+ expected_ids = stats[0..1].map { |s| s.id }
+
+ requested_stats = described_class.for_project_ids(project_ids).pluck(:id)
+
+ expect(requested_stats).to eq(expected_ids)
+ end
+ end
+ end
+
describe 'statistics columns' do
it "support values up to 8 exabytes" do
statistics.update!(
commit_count: 8.exabytes - 1,
repository_size: 2.exabytes,
+ wiki_size: 1.exabytes,
lfs_objects_size: 2.exabytes,
- build_artifacts_size: 4.exabytes - 1
+ build_artifacts_size: 3.exabytes - 1
)
statistics.reload
expect(statistics.commit_count).to eq(8.exabytes - 1)
expect(statistics.repository_size).to eq(2.exabytes)
+ expect(statistics.wiki_size).to eq(1.exabytes)
expect(statistics.lfs_objects_size).to eq(2.exabytes)
- expect(statistics.build_artifacts_size).to eq(4.exabytes - 1)
+ expect(statistics.build_artifacts_size).to eq(3.exabytes - 1)
expect(statistics.storage_size).to eq(8.exabytes - 1)
end
end
@@ -33,6 +49,7 @@ describe ProjectStatistics do
describe '#total_repository_size' do
it "sums repository and LFS object size" do
statistics.repository_size = 2
+ statistics.wiki_size = 6
statistics.lfs_objects_size = 3
statistics.build_artifacts_size = 4
@@ -40,10 +57,17 @@ describe ProjectStatistics do
end
end
+ describe '#wiki_size' do
+ it "is initialized with not null value" do
+ expect(statistics.wiki_size).to eq 0
+ end
+ end
+
describe '#refresh!' do
before do
allow(statistics).to receive(:update_commit_count)
allow(statistics).to receive(:update_repository_size)
+ allow(statistics).to receive(:update_wiki_size)
allow(statistics).to receive(:update_lfs_objects_size)
allow(statistics).to receive(:update_storage_size)
end
@@ -56,6 +80,7 @@ describe ProjectStatistics do
it "sums all counters" do
expect(statistics).to have_received(:update_commit_count)
expect(statistics).to have_received(:update_repository_size)
+ expect(statistics).to have_received(:update_wiki_size)
expect(statistics).to have_received(:update_lfs_objects_size)
end
end
@@ -69,6 +94,45 @@ describe ProjectStatistics do
expect(statistics).to have_received(:update_lfs_objects_size)
expect(statistics).not_to have_received(:update_commit_count)
expect(statistics).not_to have_received(:update_repository_size)
+ expect(statistics).not_to have_received(:update_wiki_size)
+ end
+ end
+
+ context 'without repositories' do
+ it 'does not crash' do
+ expect(project.repository.exists?).to be_falsey
+ expect(project.wiki.repository.exists?).to be_falsey
+
+ statistics.refresh!
+
+ expect(statistics).to have_received(:update_commit_count)
+ expect(statistics).to have_received(:update_repository_size)
+ expect(statistics).to have_received(:update_wiki_size)
+ expect(statistics.repository_size).to eq(0)
+ expect(statistics.commit_count).to eq(0)
+ expect(statistics.wiki_size).to eq(0)
+ end
+ end
+
+ context 'with deleted repositories' do
+ let(:project) { create(:project, :repository, :wiki_repo) }
+
+ before do
+ Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ FileUtils.rm_rf(project.repository.path)
+ FileUtils.rm_rf(project.wiki.repository.path)
+ end
+ end
+
+ it 'does not crash' do
+ statistics.refresh!
+
+ expect(statistics).to have_received(:update_commit_count)
+ expect(statistics).to have_received(:update_repository_size)
+ expect(statistics).to have_received(:update_wiki_size)
+ expect(statistics.repository_size).to eq(0)
+ expect(statistics.commit_count).to eq(0)
+ expect(statistics.wiki_size).to eq(0)
end
end
end
@@ -95,6 +159,17 @@ describe ProjectStatistics do
end
end
+ describe '#update_wiki_size' do
+ before do
+ allow(project.wiki.repository).to receive(:size).and_return(34)
+ statistics.update_wiki_size
+ end
+
+ it "stores the size of the wiki" do
+ expect(statistics.wiki_size).to eq 34.megabytes
+ end
+ end
+
describe '#update_lfs_objects_size' do
let!(:lfs_object1) { create(:lfs_object, size: 23.megabytes) }
let!(:lfs_object2) { create(:lfs_object, size: 34.megabytes) }
@@ -114,6 +189,19 @@ describe ProjectStatistics do
it "sums all storage counters" do
statistics.update!(
repository_size: 2,
+ wiki_size: 4,
+ lfs_objects_size: 3
+ )
+
+ statistics.reload
+
+ expect(statistics.storage_size).to eq 9
+ end
+
+ it 'works during wiki_size backfill' do
+ statistics.update!(
+ repository_size: 2,
+ wiki_size: nil,
lfs_objects_size: 3
)
@@ -124,16 +212,30 @@ describe ProjectStatistics do
end
describe '.increment_statistic' do
- it 'increases the statistic by that amount' do
- expect { described_class.increment_statistic(project.id, :build_artifacts_size, 13) }
- .to change { statistics.reload.build_artifacts_size }
- .by(13)
+ shared_examples 'a statistic that increases storage_size' do
+ it 'increases the statistic by that amount' do
+ expect { described_class.increment_statistic(project.id, stat, 13) }
+ .to change { statistics.reload.send(stat) || 0 }
+ .by(13)
+ end
+
+ it 'increases also storage size by that amount' do
+ expect { described_class.increment_statistic(project.id, stat, 20) }
+ .to change { statistics.reload.storage_size }
+ .by(20)
+ end
+ end
+
+ context 'when adjusting :build_artifacts_size' do
+ let(:stat) { :build_artifacts_size }
+
+ it_behaves_like 'a statistic that increases storage_size'
end
- it 'increases also storage size by that amount' do
- expect { described_class.increment_statistic(project.id, :build_artifacts_size, 20) }
- .to change { statistics.reload.storage_size }
- .by(20)
+ context 'when adjusting :packages_size' do
+ let(:stat) { :packages_size }
+
+ it_behaves_like 'a statistic that increases storage_size'
end
context 'when the amount is 0' do
diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb
index 2525a6aebe0..d12dd97bb9e 100644
--- a/spec/models/project_wiki_spec.rb
+++ b/spec/models/project_wiki_spec.rb
@@ -109,8 +109,7 @@ describe ProjectWiki do
subject { super().empty? }
it { is_expected.to be_falsey }
- # Re-enable this when https://gitlab.com/gitlab-org/gitaly/issues/1204 is fixed
- xit 'only instantiates a Wiki page once' do
+ it 'only instantiates a Wiki page once' do
expect(WikiPage).to receive(:new).once.and_call_original
subject
@@ -119,22 +118,65 @@ describe ProjectWiki do
end
end
- describe "#pages" do
+ describe "#list_pages" do
+ let(:wiki_pages) { subject.list_pages }
+
before do
- create_page("index", "This is an awesome new Gollum Wiki")
- @pages = subject.pages
+ create_page("index", "This is an index")
+ create_page("index2", "This is an index2")
+ create_page("an index3", "This is an index3")
end
after do
- destroy_page(@pages.first.page)
+ wiki_pages.each do |wiki_page|
+ destroy_page(wiki_page.page)
+ end
end
it "returns an array of WikiPage instances" do
- expect(@pages.first).to be_a WikiPage
+ expect(wiki_pages.first).to be_a WikiPage
+ end
+
+ it 'does not load WikiPage content by default' do
+ wiki_pages.each do |page|
+ expect(page.content).to be_empty
+ end
+ end
+
+ it 'returns all pages by default' do
+ expect(wiki_pages.count).to eq(3)
+ end
+
+ context "with limit option" do
+ it 'returns limited set of pages' do
+ expect(subject.list_pages(limit: 1).count).to eq(1)
+ end
end
- it "returns the correct number of pages" do
- expect(@pages.count).to eq(1)
+ context "with sorting options" do
+ it 'returns pages sorted by title by default' do
+ pages = ['an index3', 'index', 'index2']
+
+ expect(subject.list_pages.map(&:title)).to eq(pages)
+ expect(subject.list_pages(direction: "desc").map(&:title)).to eq(pages.reverse)
+ end
+
+ it 'returns pages sorted by created_at' do
+ pages = ['index', 'index2', 'an index3']
+
+ expect(subject.list_pages(sort: 'created_at').map(&:title)).to eq(pages)
+ expect(subject.list_pages(sort: 'created_at', direction: "desc").map(&:title)).to eq(pages.reverse)
+ end
+ end
+
+ context "with load_content option" do
+ let(:pages) { subject.list_pages(load_content: true) }
+
+ it 'loads WikiPage content' do
+ expect(pages.first.content).to eq("This is an index3")
+ expect(pages.second.content).to eq("This is an index")
+ expect(pages.third.content).to eq("This is an index2")
+ end
end
end
@@ -144,7 +186,7 @@ describe ProjectWiki do
end
after do
- subject.pages.each { |page| destroy_page(page.page) }
+ subject.list_pages.each { |page| destroy_page(page.page) }
end
it "returns the latest version of the page if it exists" do
@@ -195,7 +237,7 @@ describe ProjectWiki do
end
after do
- subject.pages.each { |page| destroy_page(page.page) }
+ subject.list_pages.each { |page| destroy_page(page.page) }
end
it 'finds the page defined as _sidebar' do
@@ -242,12 +284,12 @@ describe ProjectWiki do
describe "#create_page" do
after do
- destroy_page(subject.pages.first.page)
+ destroy_page(subject.list_pages.first.page)
end
it "creates a new wiki page" do
expect(subject.create_page("test page", "this is content")).not_to eq(false)
- expect(subject.pages.count).to eq(1)
+ expect(subject.list_pages.count).to eq(1)
end
it "returns false when a duplicate page exists" do
@@ -262,7 +304,7 @@ describe ProjectWiki do
it "sets the correct commit message" do
subject.create_page("test page", "some content", :markdown, "commit message")
- expect(subject.pages.first.page.version.message).to eq("commit message")
+ expect(subject.list_pages.first.page.version.message).to eq("commit message")
end
it 'sets the correct commit email' do
@@ -293,7 +335,7 @@ describe ProjectWiki do
format: :markdown,
message: "updated page"
)
- @page = subject.pages.first.page
+ @page = subject.list_pages(load_content: true).first.page
end
after do
@@ -337,7 +379,7 @@ describe ProjectWiki do
it "deletes the page" do
subject.delete_page(@page)
- expect(subject.pages.count).to eq(0)
+ expect(subject.list_pages.count).to eq(0)
end
it 'sets the correct commit email' do
diff --git a/spec/models/push_event_spec.rb b/spec/models/push_event_spec.rb
index f86500f91cd..5509ed87308 100644
--- a/spec/models/push_event_spec.rb
+++ b/spec/models/push_event_spec.rb
@@ -123,9 +123,9 @@ describe PushEvent do
end
end
- describe '#push?' do
+ describe '#push_action?' do
it 'returns true' do
- expect(event).to be_push
+ expect(event).to be_push_action
end
end
diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb
index 0b19a4f8efc..7c106ce6b85 100644
--- a/spec/models/release_spec.rb
+++ b/spec/models/release_spec.rb
@@ -49,6 +49,11 @@ RSpec.describe Release do
it 'counts the link as an asset' do
is_expected.to eq(1 + Releases::Source::FORMATS.count)
end
+
+ it "excludes sources count when asked" do
+ assets_count = release.assets_count(except: [:sources])
+ expect(assets_count).to eq(1)
+ end
end
end
diff --git a/spec/models/remote_mirror_spec.rb b/spec/models/remote_mirror_spec.rb
index f743dfed31f..e14b19db915 100644
--- a/spec/models/remote_mirror_spec.rb
+++ b/spec/models/remote_mirror_spec.rb
@@ -373,6 +373,22 @@ describe RemoteMirror, :mailer do
end
end
+ describe '#disabled?' do
+ subject { remote_mirror.disabled? }
+
+ context 'when disabled' do
+ let(:remote_mirror) { build(:remote_mirror, enabled: false) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when enabled' do
+ let(:remote_mirror) { build(:remote_mirror, enabled: true) }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+
def create_mirror(params)
project = FactoryBot.create(:project, :repository)
project.remote_mirrors.create!(params)
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 3f5d285bc2c..c5ab7e57272 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -217,6 +217,25 @@ describe Repository do
expect(result.size).to eq(0)
end
+
+ context 'with a commit with invalid UTF-8 path' do
+ def create_commit_with_invalid_utf8_path
+ rugged = rugged_repo(repository)
+ blob_id = Rugged::Blob.from_buffer(rugged, "some contents")
+ tree_builder = Rugged::Tree::Builder.new(rugged)
+ tree_builder.insert({ oid: blob_id, name: "hello\x80world", filemode: 0100644 })
+ tree_id = tree_builder.write
+ user = { email: "jcai@gitlab.com", time: Time.now, name: "John Cai" }
+
+ Rugged::Commit.create(rugged, message: 'some commit message', parents: [rugged.head.target.oid], tree: tree_id, committer: user, author: user)
+ end
+
+ it 'does not raise an error' do
+ commit = create_commit_with_invalid_utf8_path
+
+ expect { repository.list_last_commits_for_tree(commit, '.', offset: 0) }.not_to raise_error
+ end
+ end
end
describe '#last_commit_for_path' do
@@ -1432,6 +1451,91 @@ describe Repository do
end
end
+ describe '#rebase' do
+ let(:merge_request) { create(:merge_request, source_branch: 'feature', target_branch: 'master', source_project: project) }
+
+ shared_examples_for 'a method that can rebase successfully' do
+ it 'returns the rebase commit sha' do
+ rebase_commit_sha = repository.rebase(user, merge_request)
+ head_sha = merge_request.source_project.repository.commit(merge_request.source_branch).sha
+
+ expect(rebase_commit_sha).to eq(head_sha)
+ end
+
+ it 'sets the `rebase_commit_sha` for the given merge request' do
+ rebase_commit_sha = repository.rebase(user, merge_request)
+
+ expect(rebase_commit_sha).not_to be_nil
+ expect(merge_request.rebase_commit_sha).to eq(rebase_commit_sha)
+ end
+ end
+
+ context 'when two_step_rebase feature is enabled' do
+ before do
+ stub_feature_flags(two_step_rebase: true)
+ end
+
+ it_behaves_like 'a method that can rebase successfully'
+
+ it 'executes the new Gitaly RPC' do
+ expect_any_instance_of(Gitlab::GitalyClient::OperationService).to receive(:rebase)
+ expect_any_instance_of(Gitlab::GitalyClient::OperationService).not_to receive(:user_rebase)
+
+ repository.rebase(user, merge_request)
+ end
+
+ describe 'rolling back the `rebase_commit_sha`' do
+ let(:new_sha) { Digest::SHA1.hexdigest('foo') }
+
+ it 'does not rollback when there are no errors' do
+ second_response = double(pre_receive_error: nil, git_error: nil)
+ mock_gitaly(second_response)
+
+ repository.rebase(user, merge_request)
+
+ expect(merge_request.reload.rebase_commit_sha).to eq(new_sha)
+ end
+
+ it 'does rollback when an error is encountered in the second step' do
+ second_response = double(pre_receive_error: 'my_error', git_error: nil)
+ mock_gitaly(second_response)
+
+ expect do
+ repository.rebase(user, merge_request)
+ end.to raise_error(Gitlab::Git::PreReceiveError)
+
+ expect(merge_request.reload.rebase_commit_sha).to be_nil
+ end
+
+ def mock_gitaly(second_response)
+ responses = [
+ double(rebase_sha: new_sha).as_null_object,
+ second_response
+ ]
+
+ expect_any_instance_of(
+ Gitaly::OperationService::Stub
+ ).to receive(:user_rebase_confirmable).and_return(responses.each)
+ end
+ end
+ end
+
+ context 'when two_step_rebase feature is disabled' do
+ before do
+ stub_feature_flags(two_step_rebase: false)
+ end
+
+ it_behaves_like 'a method that can rebase successfully'
+
+ it 'executes the deprecated Gitaly RPC' do
+ expect_any_instance_of(Gitlab::GitalyClient::OperationService).to receive(:user_rebase)
+ expect_any_instance_of(Gitlab::GitalyClient::OperationService).not_to receive(:rebase)
+
+ repository.rebase(user, merge_request)
+ end
+ end
+ end
+
describe '#revert' do
let(:new_image_commit) { repository.commit('33f3729a45c02fc67d00adb1b8bca394b0e761d9') }
let(:update_image_commit) { repository.commit('2f63565e7aac07bcdadb654e253078b727143ec4') }
@@ -1618,6 +1722,7 @@ describe Repository do
:has_visible_content?,
:issue_template_names,
:merge_request_template_names,
+ :metrics_dashboard_paths,
:xcode_project?
])
@@ -2181,12 +2286,45 @@ describe Repository do
end
describe '#diverging_commit_counts' do
+ let(:diverged_branch) { repository.find_branch('fix') }
+ let(:root_ref_sha) { repository.raw_repository.commit(repository.root_ref).id }
+ let(:diverged_branch_sha) { diverged_branch.dereferenced_target.sha }
+
it 'returns the commit counts behind and ahead of default branch' do
- result = repository.diverging_commit_counts(
- repository.find_branch('fix'))
+ result = repository.diverging_commit_counts(diverged_branch)
expect(result).to eq(behind: 29, ahead: 2)
end
+
+ context 'when gitaly_count_diverging_commits_no_max is enabled' do
+ before do
+ stub_feature_flags(gitaly_count_diverging_commits_no_max: true)
+ end
+
+ it 'calls diverging_commit_count without max count' do
+ expect(repository.raw_repository)
+ .to receive(:diverging_commit_count)
+ .with(root_ref_sha, diverged_branch_sha)
+ .and_return([29, 2])
+
+ repository.diverging_commit_counts(diverged_branch)
+ end
+ end
+
+ context 'when gitaly_count_diverging_commits_no_max is disabled' do
+ before do
+ stub_feature_flags(gitaly_count_diverging_commits_no_max: false)
+ end
+
+ it 'calls diverging_commit_count with max count' do
+ expect(repository.raw_repository)
+ .to receive(:diverging_commit_count)
+ .with(root_ref_sha, diverged_branch_sha, max_count: Repository::MAX_DIVERGING_COUNT)
+ .and_return([29, 2])
+
+ repository.diverging_commit_counts(diverged_branch)
+ end
+ end
end
describe '#refresh_method_caches' do
@@ -2468,4 +2606,69 @@ describe Repository do
repository.merge_base('master', 'fix')
end
end
+
+ describe '#create_if_not_exists' do
+ let(:project) { create(:project) }
+ let(:repository) { project.repository }
+
+ it 'creates the repository if it did not exist' do
+ expect { repository.create_if_not_exists }.to change { repository.exists? }.from(false).to(true)
+ end
+
+ it 'calls out to the repository client to create a repo' do
+ expect(repository.raw.gitaly_repository_client).to receive(:create_repository)
+
+ repository.create_if_not_exists
+ end
+
+ context 'it does nothing if the repository already existed' do
+ let(:project) { create(:project, :repository) }
+
+ it 'does nothing if the repository already existed' do
+ expect(repository.raw.gitaly_repository_client).not_to receive(:create_repository)
+
+ repository.create_if_not_exists
+ end
+ end
+
+ context 'when the repository exists but the cache is not up to date' do
+ let(:project) { create(:project, :repository) }
+
+ it 'does not raise errors' do
+ allow(repository).to receive(:exists?).and_return(false)
+ expect(repository.raw).to receive(:create_repository).and_call_original
+
+ expect { repository.create_if_not_exists }.not_to raise_error
+ end
+ end
+ end
+
+ describe "#blobs_metadata" do
+ set(:project) { create(:project, :repository) }
+ let(:repository) { project.repository }
+
+ def expect_metadata_blob(thing)
+ expect(thing).to be_a(Blob)
+ expect(thing.data).to be_empty
+ end
+
+ it "returns blob metadata in batch for HEAD" do
+ result = repository.blobs_metadata(["bar/branch-test.txt", "README.md", "does/not/exist"])
+
+ expect_metadata_blob(result.first)
+ expect_metadata_blob(result.second)
+ expect(result.size).to eq(2)
+ end
+
+ it "returns blob metadata for a specified ref" do
+ result = repository.blobs_metadata(["files/ruby/feature.rb"], "feature")
+
+ expect_metadata_blob(result.first)
+ end
+
+ it "performs a single gitaly call", :request_store do
+ expect { repository.blobs_metadata(["bar/branch-test.txt", "readme.txt", "does/not/exist"]) }
+ .to change { Gitlab::GitalyClient.get_request_count }.by(1)
+ end
+ end
end
diff --git a/spec/models/resource_label_event_spec.rb b/spec/models/resource_label_event_spec.rb
index 7eeb2fae57d..cb52f154299 100644
--- a/spec/models/resource_label_event_spec.rb
+++ b/spec/models/resource_label_event_spec.rb
@@ -82,13 +82,13 @@ RSpec.describe ResourceLabelEvent, type: :model do
end
it 'returns true if markdown is outdated' do
- subject.attributes = { cached_markdown_version: ((CacheMarkdownField::CACHE_COMMONMARK_VERSION - 1) << 16) | 0 }
+ subject.attributes = { cached_markdown_version: ((Gitlab::MarkdownCache::CACHE_COMMONMARK_VERSION - 1) << 16) | 0 }
expect(subject.outdated_markdown?).to be true
end
it 'returns false if label and reference are set' do
- subject.attributes = { reference: 'whatever', cached_markdown_version: CacheMarkdownField::CACHE_COMMONMARK_VERSION << 16 }
+ subject.attributes = { reference: 'whatever', cached_markdown_version: Gitlab::MarkdownCache::CACHE_COMMONMARK_VERSION << 16 }
expect(subject.outdated_markdown?).to be false
end
diff --git a/spec/models/user_preference_spec.rb b/spec/models/user_preference_spec.rb
index b2ef17a81d4..e09c91e874a 100644
--- a/spec/models/user_preference_spec.rb
+++ b/spec/models/user_preference_spec.rb
@@ -73,4 +73,10 @@ describe UserPreference do
it_behaves_like 'a sort_by preference'
end
end
+
+ describe '#timezone' do
+ it 'returns server time as default' do
+ expect(user_preference.timezone).to eq(Time.zone.tzinfo.name)
+ end
+ end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index d1338e34bb8..c95bbb0b3f5 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -2655,9 +2655,9 @@ describe User do
end
end
- context 'with 2FA requirement on nested parent group', :nested_groups do
+ context 'with 2FA requirement from expanded groups', :nested_groups do
let!(:group1) { create :group, require_two_factor_authentication: true }
- let!(:group1a) { create :group, require_two_factor_authentication: false, parent: group1 }
+ let!(:group1a) { create :group, parent: group1 }
before do
group1a.add_user(user, GroupMember::OWNER)
@@ -2685,6 +2685,27 @@ describe User do
end
end
+ context "with 2FA requirement from shared project's group" do
+ let!(:group1) { create :group, require_two_factor_authentication: true }
+ let!(:group2) { create :group }
+ let(:shared_project) { create(:project, namespace: group1) }
+
+ before do
+ shared_project.project_group_links.create!(
+ group: group2,
+ group_access: ProjectGroupLink.default_access
+ )
+
+ group2.add_user(user, GroupMember::OWNER)
+ end
+
+ it 'does not require 2FA' do
+ user.update_two_factor_requirement
+
+ expect(user.require_two_factor_authentication_from_group).to be false
+ end
+ end
+
context 'without 2FA requirement on groups' do
let(:group) { create :group }
diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb
index d5c85c11195..520a06e138e 100644
--- a/spec/models/wiki_page_spec.rb
+++ b/spec/models/wiki_page_spec.rb
@@ -44,47 +44,49 @@ describe WikiPage do
WikiDirectory.new('dir_2', pages)
end
- context 'sort by title' do
- let(:grouped_entries) { described_class.group_by_directory(wiki.pages) }
- let(:expected_grouped_entries) { [dir_1_1, dir_1, page_dir_2, dir_2, page_1, page_6] }
-
- it 'returns an array with pages and directories' do
- grouped_entries.each_with_index do |page_or_dir, i|
- expected_page_or_dir = expected_grouped_entries[i]
- expected_slugs = get_slugs(expected_page_or_dir)
- slugs = get_slugs(page_or_dir)
-
- expect(slugs).to match_array(expected_slugs)
+ context "#list_pages" do
+ context 'sort by title' do
+ let(:grouped_entries) { described_class.group_by_directory(wiki.list_pages) }
+ let(:expected_grouped_entries) { [dir_1_1, dir_1, page_dir_2, dir_2, page_1, page_6] }
+
+ it 'returns an array with pages and directories' do
+ grouped_entries.each_with_index do |page_or_dir, i|
+ expected_page_or_dir = expected_grouped_entries[i]
+ expected_slugs = get_slugs(expected_page_or_dir)
+ slugs = get_slugs(page_or_dir)
+
+ expect(slugs).to match_array(expected_slugs)
+ end
end
end
- end
- context 'sort by created_at' do
- let(:grouped_entries) { described_class.group_by_directory(wiki.pages(sort: 'created_at')) }
- let(:expected_grouped_entries) { [dir_1_1, page_1, dir_1, page_dir_2, dir_2, page_6] }
+ context 'sort by created_at' do
+ let(:grouped_entries) { described_class.group_by_directory(wiki.list_pages(sort: 'created_at')) }
+ let(:expected_grouped_entries) { [dir_1_1, page_1, dir_1, page_dir_2, dir_2, page_6] }
- it 'returns an array with pages and directories' do
- grouped_entries.each_with_index do |page_or_dir, i|
- expected_page_or_dir = expected_grouped_entries[i]
- expected_slugs = get_slugs(expected_page_or_dir)
- slugs = get_slugs(page_or_dir)
+ it 'returns an array with pages and directories' do
+ grouped_entries.each_with_index do |page_or_dir, i|
+ expected_page_or_dir = expected_grouped_entries[i]
+ expected_slugs = get_slugs(expected_page_or_dir)
+ slugs = get_slugs(page_or_dir)
- expect(slugs).to match_array(expected_slugs)
+ expect(slugs).to match_array(expected_slugs)
+ end
end
end
- end
- it 'returns an array with retained order with directories at the top' do
- expected_order = ['dir_1/dir_1_1/page_3', 'dir_1/page_2', 'dir_2', 'dir_2/page_4', 'dir_2/page_5', 'page_1', 'page_6']
+ it 'returns an array with retained order with directories at the top' do
+ expected_order = ['dir_1/dir_1_1/page_3', 'dir_1/page_2', 'dir_2', 'dir_2/page_4', 'dir_2/page_5', 'page_1', 'page_6']
- grouped_entries = described_class.group_by_directory(wiki.pages)
+ grouped_entries = described_class.group_by_directory(wiki.list_pages)
- actual_order =
- grouped_entries.map do |page_or_dir|
- get_slugs(page_or_dir)
- end
- .flatten
- expect(actual_order).to eq(expected_order)
+ actual_order =
+ grouped_entries.map do |page_or_dir|
+ get_slugs(page_or_dir)
+ end
+ .flatten
+ expect(actual_order).to eq(expected_order)
+ end
end
end
end
@@ -386,7 +388,7 @@ describe WikiPage do
it "deletes the page" do
@page.delete
- expect(wiki.pages).to be_empty
+ expect(wiki.list_pages).to be_empty
end
it "returns true" do
diff --git a/spec/policies/clusters/cluster_policy_spec.rb b/spec/policies/clusters/cluster_policy_spec.rb
index b2f0ca1bc30..cc3dde154dc 100644
--- a/spec/policies/clusters/cluster_policy_spec.rb
+++ b/spec/policies/clusters/cluster_policy_spec.rb
@@ -66,5 +66,21 @@ describe Clusters::ClusterPolicy, :models do
it { expect(policy).to be_disallowed :admin_cluster }
end
end
+
+ context 'instance cluster' do
+ let(:cluster) { create(:cluster, :instance) }
+
+ context 'when user' do
+ it { expect(policy).to be_disallowed :update_cluster }
+ it { expect(policy).to be_disallowed :admin_cluster }
+ end
+
+ context 'when admin' do
+ let(:user) { create(:admin) }
+
+ it { expect(policy).to be_allowed :update_cluster }
+ it { expect(policy).to be_allowed :admin_cluster }
+ end
+ end
end
end
diff --git a/spec/policies/clusters/instance_policy_spec.rb b/spec/policies/clusters/instance_policy_spec.rb
new file mode 100644
index 00000000000..9d755c6d29d
--- /dev/null
+++ b/spec/policies/clusters/instance_policy_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Clusters::InstancePolicy do
+ let(:user) { create(:user) }
+ let(:policy) { described_class.new(user, Clusters::Instance.new) }
+
+ describe 'rules' do
+ context 'when user' do
+ it { expect(policy).to be_disallowed :read_cluster }
+ it { expect(policy).to be_disallowed :update_cluster }
+ it { expect(policy).to be_disallowed :admin_cluster }
+ end
+
+ context 'when admin' do
+ let(:user) { create(:admin) }
+
+ context 'with instance_level_clusters enabled' do
+ it { expect(policy).to be_allowed :read_cluster }
+ it { expect(policy).to be_allowed :update_cluster }
+ it { expect(policy).to be_allowed :admin_cluster }
+ end
+
+ context 'with instance_level_clusters disabled' do
+ before do
+ stub_feature_flags(instance_clusters: false)
+ end
+
+ it { expect(policy).to be_disallowed :read_cluster }
+ it { expect(policy).to be_disallowed :update_cluster }
+ it { expect(policy).to be_disallowed :admin_cluster }
+ end
+ end
+ end
+end
diff --git a/spec/policies/personal_snippet_policy_spec.rb b/spec/policies/personal_snippet_policy_spec.rb
index a38e0dbd797..097000ceb6a 100644
--- a/spec/policies/personal_snippet_policy_spec.rb
+++ b/spec/policies/personal_snippet_policy_spec.rb
@@ -14,13 +14,6 @@ describe PersonalSnippetPolicy do
]
end
- let(:comment_permissions) do
- [
- :comment_personal_snippet,
- :create_note
- ]
- end
-
def permissions(user)
described_class.new(user, snippet)
end
@@ -33,7 +26,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_allowed(:read_personal_snippet)
- is_expected.to be_disallowed(*comment_permissions)
+ is_expected.to be_disallowed(:create_note)
is_expected.to be_disallowed(:award_emoji)
is_expected.to be_disallowed(*author_permissions)
end
@@ -44,7 +37,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_allowed(:read_personal_snippet)
- is_expected.to be_allowed(*comment_permissions)
+ is_expected.to be_allowed(:create_note)
is_expected.to be_allowed(:award_emoji)
is_expected.to be_disallowed(*author_permissions)
end
@@ -55,7 +48,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_allowed(:read_personal_snippet)
- is_expected.to be_allowed(*comment_permissions)
+ is_expected.to be_allowed(:create_note)
is_expected.to be_allowed(:award_emoji)
is_expected.to be_allowed(*author_permissions)
end
@@ -70,7 +63,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_disallowed(:read_personal_snippet)
- is_expected.to be_disallowed(*comment_permissions)
+ is_expected.to be_disallowed(:create_note)
is_expected.to be_disallowed(:award_emoji)
is_expected.to be_disallowed(*author_permissions)
end
@@ -81,7 +74,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_allowed(:read_personal_snippet)
- is_expected.to be_allowed(*comment_permissions)
+ is_expected.to be_allowed(:create_note)
is_expected.to be_allowed(:award_emoji)
is_expected.to be_disallowed(*author_permissions)
end
@@ -92,7 +85,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_disallowed(:read_personal_snippet)
- is_expected.to be_disallowed(*comment_permissions)
+ is_expected.to be_disallowed(:create_note)
is_expected.to be_disallowed(:award_emoji)
is_expected.to be_disallowed(*author_permissions)
end
@@ -103,7 +96,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_allowed(:read_personal_snippet)
- is_expected.to be_allowed(*comment_permissions)
+ is_expected.to be_allowed(:create_note)
is_expected.to be_allowed(:award_emoji)
is_expected.to be_allowed(*author_permissions)
end
@@ -118,7 +111,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_disallowed(:read_personal_snippet)
- is_expected.to be_disallowed(*comment_permissions)
+ is_expected.to be_disallowed(:create_note)
is_expected.to be_disallowed(:award_emoji)
is_expected.to be_disallowed(*author_permissions)
end
@@ -129,7 +122,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_disallowed(:read_personal_snippet)
- is_expected.to be_disallowed(*comment_permissions)
+ is_expected.to be_disallowed(:create_note)
is_expected.to be_disallowed(:award_emoji)
is_expected.to be_disallowed(*author_permissions)
end
@@ -140,7 +133,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_allowed(:read_personal_snippet)
- is_expected.to be_disallowed(:comment_personal_snippet)
+ is_expected.to be_disallowed(:create_note)
is_expected.to be_disallowed(:award_emoji)
is_expected.to be_disallowed(*author_permissions)
end
@@ -151,7 +144,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_disallowed(:read_personal_snippet)
- is_expected.to be_disallowed(*comment_permissions)
+ is_expected.to be_disallowed(:create_note)
is_expected.to be_disallowed(:award_emoji)
is_expected.to be_disallowed(*author_permissions)
end
@@ -162,7 +155,7 @@ describe PersonalSnippetPolicy do
it do
is_expected.to be_allowed(:read_personal_snippet)
- is_expected.to be_allowed(*comment_permissions)
+ is_expected.to be_allowed(:create_note)
is_expected.to be_allowed(:award_emoji)
is_expected.to be_allowed(*author_permissions)
end
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index 42f8bf3137b..ed0e82ef179 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -17,7 +17,7 @@ describe ProjectPolicy do
read_project_for_iids read_issue_iid read_label
read_milestone read_project_snippet read_project_member read_note
create_project create_issue create_note upload_file create_merge_request_in
- award_emoji
+ award_emoji read_release
]
end
@@ -26,7 +26,7 @@ describe ProjectPolicy do
download_code fork_project create_project_snippet update_issue
admin_issue admin_label admin_list read_commit_status read_build
read_container_image read_pipeline read_environment read_deployment
- read_merge_request download_wiki_code read_sentry_issue read_release
+ read_merge_request download_wiki_code read_sentry_issue
]
end
@@ -66,7 +66,7 @@ describe ProjectPolicy do
%i[
change_namespace change_visibility_level rename_project remove_project
archive_project remove_fork_project destroy_merge_request destroy_issue
- set_issue_iid set_issue_created_at set_note_created_at
+ set_issue_iid set_issue_created_at set_issue_updated_at set_note_created_at
]
end
diff --git a/spec/presenters/blob_presenter_spec.rb b/spec/presenters/blob_presenter_spec.rb
index bb1db9a3d51..eacf383be7d 100644
--- a/spec/presenters/blob_presenter_spec.rb
+++ b/spec/presenters/blob_presenter_spec.rb
@@ -14,6 +14,16 @@ describe BlobPresenter, :seed_helper do
end
let(:blob) { Blob.new(git_blob) }
+ describe '.web_url' do
+ let(:project) { create(:project, :repository) }
+ let(:repository) { project.repository }
+ let(:blob) { Gitlab::Graphql::Representation::TreeEntry.new(repository.tree.blobs.first, repository) }
+
+ subject { described_class.new(blob) }
+
+ it { expect(subject.web_url).to eq("http://localhost/#{project.full_path}/blob/#{blob.commit_id}/#{blob.path}") }
+ end
+
describe '#highlight' do
subject { described_class.new(blob) }
diff --git a/spec/presenters/ci/build_runner_presenter_spec.rb b/spec/presenters/ci/build_runner_presenter_spec.rb
index ad6cb012d0b..a4234d14255 100644
--- a/spec/presenters/ci/build_runner_presenter_spec.rb
+++ b/spec/presenters/ci/build_runner_presenter_spec.rb
@@ -119,39 +119,31 @@ describe Ci::BuildRunnerPresenter do
end
describe '#git_depth' do
- subject { presenter.git_depth }
-
let(:build) { create(:ci_build) }
- it 'returns the correct git depth' do
- is_expected.to eq(0)
- end
+ subject(:git_depth) { presenter.git_depth }
context 'when GIT_DEPTH variable is specified' do
before do
create(:ci_pipeline_variable, key: 'GIT_DEPTH', value: 1, pipeline: build.pipeline)
end
- it 'returns the correct git depth' do
- is_expected.to eq(1)
+ it 'returns its value' do
+ expect(git_depth).to eq(1)
end
end
- context 'when pipeline is detached merge request pipeline' do
- let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) }
- let(:pipeline) { merge_request.all_pipelines.first }
- let(:build) { create(:ci_build, ref: pipeline.ref, pipeline: pipeline) }
+ it 'defaults to git depth setting for the project' do
+ expect(git_depth).to eq(build.project.ci_default_git_depth)
+ end
- it 'returns the default git depth for pipelines for merge requests' do
- is_expected.to eq(described_class::DEFAULT_GIT_DEPTH_MERGE_REQUEST)
+ context 'when feature flag :ci_project_git_depth is disabled' do
+ before do
+ stub_feature_flags(ci_project_git_depth: { enabled: false })
end
- context 'when pipeline is legacy detached merge request pipeline' do
- let(:merge_request) { create(:merge_request, :with_legacy_detached_merge_request_pipeline) }
-
- it 'behaves as branch pipeline' do
- is_expected.to eq(0)
- end
+ it 'defaults to 0' do
+ expect(git_depth).to eq(0)
end
end
end
@@ -162,24 +154,24 @@ describe Ci::BuildRunnerPresenter do
let(:build) { create(:ci_build) }
it 'returns the correct refspecs' do
- is_expected.to contain_exactly('+refs/tags/*:refs/tags/*',
- '+refs/heads/*:refs/remotes/origin/*')
+ is_expected.to contain_exactly("+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}")
end
- context 'when GIT_DEPTH variable is specified' do
- before do
- create(:ci_pipeline_variable, key: 'GIT_DEPTH', value: 1, pipeline: build.pipeline)
- end
+ context 'when ref is tag' do
+ let(:build) { create(:ci_build, :tag) }
it 'returns the correct refspecs' do
- is_expected.to contain_exactly("+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}")
+ is_expected.to contain_exactly("+refs/tags/#{build.ref}:refs/tags/#{build.ref}")
end
- context 'when ref is tag' do
- let(:build) { create(:ci_build, :tag) }
+ context 'when GIT_DEPTH is zero' do
+ before do
+ create(:ci_pipeline_variable, key: 'GIT_DEPTH', value: 0, pipeline: build.pipeline)
+ end
it 'returns the correct refspecs' do
- is_expected.to contain_exactly("+refs/tags/#{build.ref}:refs/tags/#{build.ref}")
+ is_expected.to contain_exactly('+refs/tags/*:refs/tags/*',
+ '+refs/heads/*:refs/remotes/origin/*')
end
end
end
@@ -194,12 +186,24 @@ describe Ci::BuildRunnerPresenter do
.to contain_exactly('+refs/merge-requests/1/head:refs/merge-requests/1/head')
end
+ context 'when GIT_DEPTH is zero' do
+ before do
+ create(:ci_pipeline_variable, key: 'GIT_DEPTH', value: 0, pipeline: build.pipeline)
+ end
+
+ it 'returns the correct refspecs' do
+ is_expected
+ .to contain_exactly('+refs/merge-requests/1/head:refs/merge-requests/1/head',
+ '+refs/heads/*:refs/remotes/origin/*',
+ '+refs/tags/*:refs/tags/*')
+ end
+ end
+
context 'when pipeline is legacy detached merge request pipeline' do
let(:merge_request) { create(:merge_request, :with_legacy_detached_merge_request_pipeline) }
it 'returns the correct refspecs' do
- is_expected.to contain_exactly('+refs/tags/*:refs/tags/*',
- '+refs/heads/*:refs/remotes/origin/*')
+ is_expected.to contain_exactly("+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}")
end
end
end
diff --git a/spec/presenters/clusters/cluster_presenter_spec.rb b/spec/presenters/clusters/cluster_presenter_spec.rb
index a9d786bc872..7054a70e2ed 100644
--- a/spec/presenters/clusters/cluster_presenter_spec.rb
+++ b/spec/presenters/clusters/cluster_presenter_spec.rb
@@ -158,46 +158,6 @@ describe Clusters::ClusterPresenter do
it { is_expected.to include(cluster.name) }
end
- describe '#can_toggle_cluster' do
- let(:user) { create(:user) }
-
- before do
- allow(cluster).to receive(:current_user).and_return(user)
- end
-
- subject { described_class.new(cluster).can_toggle_cluster? }
-
- context 'when user can update' do
- before do
- allow_any_instance_of(described_class).to receive(:can?).with(user, :update_cluster, cluster).and_return(true)
- end
-
- context 'when cluster is created' do
- before do
- allow(cluster).to receive(:created?).and_return(true)
- end
-
- it { is_expected.to eq(true) }
- end
-
- context 'when cluster is not created' do
- before do
- allow(cluster).to receive(:created?).and_return(false)
- end
-
- it { is_expected.to eq(false) }
- end
- end
-
- context 'when user can not update' do
- before do
- allow_any_instance_of(described_class).to receive(:can?).with(user, :update_cluster, cluster).and_return(false)
- end
-
- it { is_expected.to eq(false) }
- end
- end
-
describe '#cluster_type_description' do
subject { described_class.new(cluster).cluster_type_description }
@@ -210,6 +170,12 @@ describe Clusters::ClusterPresenter do
it { is_expected.to eq('Group cluster') }
end
+
+ context 'instance_type cluster' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :instance) }
+
+ it { is_expected.to eq('Instance cluster') }
+ end
end
describe '#show_path' do
@@ -227,6 +193,12 @@ describe Clusters::ClusterPresenter do
it { is_expected.to eq(group_cluster_path(group, cluster)) }
end
+
+ context 'instance_type cluster' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :instance) }
+
+ it { is_expected.to eq(admin_cluster_path(cluster)) }
+ end
end
describe '#read_only_kubernetes_platform_fields?' do
diff --git a/spec/presenters/issue_presenter_spec.rb b/spec/presenters/issue_presenter_spec.rb
new file mode 100644
index 00000000000..8e24559341b
--- /dev/null
+++ b/spec/presenters/issue_presenter_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe IssuePresenter do
+ include Gitlab::Routing.url_helpers
+
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let(:project) { create(:project, group: group) }
+ let(:issue) { create(:issue, project: project) }
+ let(:presenter) { described_class.new(issue, current_user: user) }
+
+ before do
+ group.add_developer(user)
+ end
+
+ describe '#web_url' do
+ it 'returns correct path' do
+ expect(presenter.web_url).to eq "http://localhost/#{group.name}/#{project.name}/issues/#{issue.iid}"
+ end
+ end
+
+ describe '#issue_path' do
+ it 'returns correct path' do
+ expect(presenter.issue_path).to eq "/#{group.name}/#{project.name}/issues/#{issue.iid}"
+ end
+ end
+end
diff --git a/spec/presenters/label_presenter_spec.rb b/spec/presenters/label_presenter_spec.rb
new file mode 100644
index 00000000000..d566da7c872
--- /dev/null
+++ b/spec/presenters/label_presenter_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe LabelPresenter do
+ include Gitlab::Routing.url_helpers
+
+ set(:group) { create(:group) }
+ set(:project) { create(:project, group: group) }
+ let(:label) { build_stubbed(:label, project: project).present(issuable_subject: project) }
+ let(:group_label) { build_stubbed(:group_label, group: group).present(issuable_subject: project) }
+
+ describe '#edit_path' do
+ context 'with group label' do
+ subject { group_label.edit_path }
+
+ it { is_expected.to eq(edit_group_label_path(group, group_label)) }
+ end
+
+ context 'with project label' do
+ subject { label.edit_path }
+
+ it { is_expected.to eq(edit_project_label_path(project, label)) }
+ end
+ end
+
+ describe '#destroy_path' do
+ context 'with group label' do
+ subject { group_label.destroy_path }
+
+ it { is_expected.to eq(group_label_path(group, group_label)) }
+ end
+
+ context 'with project label' do
+ subject { label.destroy_path }
+
+ it { is_expected.to eq(project_label_path(project, label)) }
+ end
+ end
+
+ describe '#filter_path' do
+ context 'with group as context subject' do
+ let(:label_in_group) { build_stubbed(:label, project: project).present(issuable_subject: group) }
+ subject { label_in_group.filter_path }
+
+ it { is_expected.to eq(issues_group_path(group, label_name: [label_in_group.title])) }
+ end
+
+ context 'with project as context subject' do
+ subject { label.filter_path }
+
+ it { is_expected.to eq(namespace_project_issues_path(group, project, label_name: [label.title])) }
+ end
+ end
+
+ describe '#can_subscribe_to_label_in_different_levels?' do
+ it 'returns true for group labels in project context' do
+ expect(group_label.can_subscribe_to_label_in_different_levels?).to be_truthy
+ end
+
+ it 'returns false for project labels in project context' do
+ expect(label.can_subscribe_to_label_in_different_levels?).to be_falsey
+ end
+ end
+
+ describe '#project_label?' do
+ context 'with group label' do
+ subject { group_label.project_label? }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'with project label' do
+ subject { label.project_label? }
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ describe '#subject_name' do
+ context 'with group label' do
+ subject { group_label.subject_name }
+
+ it { is_expected.to eq(group_label.group.name) }
+ end
+
+ context 'with project label' do
+ subject { label.subject_name }
+
+ it { is_expected.to eq(label.project.name) }
+ end
+ end
+end
diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb
index e5f08aeb1fa..6408b0bd748 100644
--- a/spec/presenters/merge_request_presenter_spec.rb
+++ b/spec/presenters/merge_request_presenter_spec.rb
@@ -207,25 +207,25 @@ describe MergeRequestPresenter do
end
end
- describe '#cancel_merge_when_pipeline_succeeds_path' do
+ describe '#cancel_auto_merge_path' do
subject do
described_class.new(resource, current_user: user)
- .cancel_merge_when_pipeline_succeeds_path
+ .cancel_auto_merge_path
end
context 'when can cancel mwps' do
it 'returns path' do
- allow(resource).to receive(:can_cancel_merge_when_pipeline_succeeds?)
+ allow(resource).to receive(:can_cancel_auto_merge?)
.with(user)
.and_return(true)
- is_expected.to eq("/#{resource.project.full_path}/merge_requests/#{resource.iid}/cancel_merge_when_pipeline_succeeds")
+ is_expected.to eq("/#{resource.project.full_path}/merge_requests/#{resource.iid}/cancel_auto_merge")
end
end
context 'when cannot cancel mwps' do
it 'returns nil' do
- allow(resource).to receive(:can_cancel_merge_when_pipeline_succeeds?)
+ allow(resource).to receive(:can_cancel_auto_merge?)
.with(user)
.and_return(false)
@@ -403,7 +403,7 @@ describe MergeRequestPresenter do
allow(resource).to receive(:source_branch_exists?) { true }
is_expected
- .to eq("/#{resource.source_project.full_path}/branches/#{resource.source_branch}")
+ .to eq("/#{resource.source_project.full_path}/-/branches/#{resource.source_branch}")
end
end
@@ -426,7 +426,7 @@ describe MergeRequestPresenter do
allow(resource).to receive(:target_branch_exists?) { true }
is_expected
- .to eq("/#{resource.source_project.full_path}/branches/#{resource.target_branch}")
+ .to eq("/#{resource.source_project.full_path}/-/branches/#{resource.target_branch}")
end
end
@@ -439,6 +439,52 @@ describe MergeRequestPresenter do
end
end
+ describe '#source_branch_link' do
+ subject { presenter.source_branch_link }
+
+ let(:presenter) { described_class.new(resource, current_user: user) }
+
+ context 'when source branch exists' do
+ it 'returns link' do
+ allow(resource).to receive(:source_branch_exists?) { true }
+
+ is_expected
+ .to eq("<a class=\"ref-name\" href=\"#{presenter.source_branch_commits_path}\">#{presenter.source_branch}</a>")
+ end
+ end
+
+ context 'when source branch does not exist' do
+ it 'returns text' do
+ allow(resource).to receive(:source_branch_exists?) { false }
+
+ is_expected.to eq("<span class=\"ref-name\">#{presenter.source_branch}</span>")
+ end
+ end
+ end
+
+ describe '#target_branch_link' do
+ subject { presenter.target_branch_link }
+
+ let(:presenter) { described_class.new(resource, current_user: user) }
+
+ context 'when target branch exists' do
+ it 'returns link' do
+ allow(resource).to receive(:target_branch_exists?) { true }
+
+ is_expected
+ .to eq("<a class=\"ref-name\" href=\"#{presenter.target_branch_commits_path}\">#{presenter.target_branch}</a>")
+ end
+ end
+
+ context 'when target branch does not exist' do
+ it 'returns text' do
+ allow(resource).to receive(:target_branch_exists?) { false }
+
+ is_expected.to eq("<span class=\"ref-name\">#{presenter.target_branch}</span>")
+ end
+ end
+ end
+
describe '#source_branch_with_namespace_link' do
subject do
described_class.new(resource, current_user: user).source_branch_with_namespace_link
diff --git a/spec/presenters/project_presenter_spec.rb b/spec/presenters/project_presenter_spec.rb
index 456de5f1b9a..5bf80f6e318 100644
--- a/spec/presenters/project_presenter_spec.rb
+++ b/spec/presenters/project_presenter_spec.rb
@@ -411,4 +411,23 @@ describe ProjectPresenter do
end
end
end
+
+ describe '#statistics_buttons' do
+ let(:project) { build(:project) }
+ let(:presenter) { described_class.new(project, current_user: user) }
+
+ it 'orders the items correctly' do
+ allow(project.repository).to receive(:readme).and_return(double(name: 'readme'))
+ allow(project.repository).to receive(:changelog).and_return(nil)
+ allow(project.repository).to receive(:contribution_guide).and_return(double(name: 'foo'))
+ allow(presenter).to receive(:filename_path).and_return('fake/path')
+ allow(presenter).to receive(:contribution_guide_path).and_return('fake_path')
+
+ buttons = presenter.statistics_buttons(show_auto_devops_callout: false)
+ expect(buttons.map(&:label)).to start_with(
+ a_string_including('README'),
+ a_string_including('CONTRIBUTING')
+ )
+ end
+ end
end
diff --git a/spec/presenters/tree_entry_presenter_spec.rb b/spec/presenters/tree_entry_presenter_spec.rb
new file mode 100644
index 00000000000..d74ee5dc28f
--- /dev/null
+++ b/spec/presenters/tree_entry_presenter_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe TreeEntryPresenter do
+ include Gitlab::Routing.url_helpers
+
+ let(:project) { create(:project, :repository) }
+ let(:repository) { project.repository }
+ let(:tree) { Gitlab::Graphql::Representation::TreeEntry.new(repository.tree.trees.first, repository) }
+ let(:presenter) { described_class.new(tree) }
+
+ describe '.web_url' do
+ it { expect(presenter.web_url).to eq("http://localhost/#{project.full_path}/tree/#{tree.commit_id}/#{tree.path}") }
+ end
+end
diff --git a/spec/rack_servers/configs/puma.rb b/spec/rack_servers/configs/puma.rb
deleted file mode 100644
index d6b6d83d648..00000000000
--- a/spec/rack_servers/configs/puma.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-# Note: this file is used for testing puma in `spec/rack_servers/puma_spec.rb` only
-# Note: as per the convention in `config/puma.example.development.rb`,
-# this file will replace `/home/git` with the actual working directory
-
-directory '/home/git'
-threads 1, 10
-queue_requests false
-pidfile '/home/git/gitlab/tmp/pids/puma.pid'
-bind 'unix:///home/git/gitlab/tmp/tests/puma.socket'
-workers 1
-preload_app!
-worker_timeout 60
-
-require_relative "/home/git/gitlab/lib/gitlab/cluster/lifecycle_events"
-require_relative "/home/git/gitlab/lib/gitlab/cluster/puma_worker_killer_initializer"
-
-before_fork do
- Gitlab::Cluster::PumaWorkerKillerInitializer.start @config.options
- Gitlab::Cluster::LifecycleEvents.do_before_fork
-end
-
-Gitlab::Cluster::LifecycleEvents.set_puma_options @config.options
-on_worker_boot do
- Gitlab::Cluster::LifecycleEvents.do_worker_start
- File.write('/home/git/gitlab/tmp/tests/puma-worker-ready', Process.pid)
-end
-
-on_restart do
- Gitlab::Cluster::LifecycleEvents.do_master_restart
-end
diff --git a/spec/rack_servers/puma_spec.rb b/spec/rack_servers/puma_spec.rb
index 891df4f1a66..a4b37905af3 100644
--- a/spec/rack_servers/puma_spec.rb
+++ b/spec/rack_servers/puma_spec.rb
@@ -1,26 +1,26 @@
# frozen_string_literal: true
-require 'fileutils'
+require 'spec_helper'
+require 'fileutils'
require 'excon'
-require 'spec_helper'
-
describe 'Puma' do
before(:all) do
- project_root = File.expand_path('../..', __dir__)
-
- config_lines = File.read('spec/rack_servers/configs/puma.rb')
- .gsub('/home/git/gitlab', project_root)
- .gsub('/home/git', project_root)
-
- config_path = File.join(project_root, "tmp/tests/puma.rb")
+ project_root = Rails.root.to_s
+ config_lines = File.read(Rails.root.join('config/puma.example.development.rb'))
+ .gsub('config.ru', File.join(__dir__, 'configs/config.ru'))
+ .gsub('workers 2', 'workers 1')
+ .gsub('/home/git/gitlab.socket', File.join(project_root, 'tmp/tests/puma.socket'))
+ .gsub('on_worker_boot do', "on_worker_boot do\nFile.write('#{File.join(project_root, 'tmp/tests/puma-worker-ready')}', Process.pid)")
+ .gsub(%r{/home/git(/gitlab)?}, project_root)
+ config_path = File.join(project_root, 'tmp/tests/puma.rb')
@socket_path = File.join(project_root, 'tmp/tests/puma.socket')
File.write(config_path, config_lines)
cmd = %W[puma -e test -C #{config_path} #{File.join(__dir__, 'configs/config.ru')}]
- @puma_master_pid = spawn(*cmd)
+ @puma_master_pid = spawn({ 'DISABLE_PUMA_WORKER_KILLER' => '1' }, *cmd)
wait_puma_boot!(@puma_master_pid, File.join(project_root, 'tmp/tests/puma-worker-ready'))
WebMock.allow_net_connect!
end
diff --git a/spec/requests/api/badges_spec.rb b/spec/requests/api/badges_spec.rb
index 1271324a2ba..1dd0cb4817c 100644
--- a/spec/requests/api/badges_spec.rb
+++ b/spec/requests/api/badges_spec.rb
@@ -73,7 +73,7 @@ describe API::Badges do
let(:badge) { source.badges.first }
context "as a #{type}" do
- it 'returns 200' do
+ it 'returns 200', :quarantine do
user = public_send(type)
get api("/#{source_type.pluralize}/#{source.id}/badges/#{badge.id}", user)
@@ -193,7 +193,7 @@ describe API::Badges do
end
context 'when authenticated as a maintainer/owner' do
- it 'updates the member' do
+ it 'updates the member', :quarantine do
put api("/#{source_type.pluralize}/#{source.id}/badges/#{badge.id}", maintainer),
params: { link_url: example_url, image_url: example_url2 }
@@ -239,7 +239,7 @@ describe API::Badges do
end
end
- context 'when authenticated as a maintainer/owner' do
+ context 'when authenticated as a maintainer/owner', :quarantine do
it 'deletes the badge' do
expect do
delete api("/#{source_type.pluralize}/#{source.id}/badges/#{badge.id}", maintainer)
diff --git a/spec/requests/api/circuit_breakers_spec.rb b/spec/requests/api/circuit_breakers_spec.rb
deleted file mode 100644
index 6c7cb151c74..00000000000
--- a/spec/requests/api/circuit_breakers_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-require 'spec_helper'
-
-describe API::CircuitBreakers do
- set(:user) { create(:user) }
- set(:admin) { create(:admin) }
-
- describe 'GET circuit_breakers/repository_storage' do
- it 'returns a 401 for anonymous users' do
- get api('/circuit_breakers/repository_storage')
-
- expect(response).to have_gitlab_http_status(401)
- end
-
- it 'returns a 403 for users' do
- get api('/circuit_breakers/repository_storage', user)
-
- expect(response).to have_gitlab_http_status(403)
- end
-
- it 'returns an Array of storages' do
- get api('/circuit_breakers/repository_storage', admin)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_kind_of(Array)
- expect(json_response).to be_empty
- end
-
- describe 'GET circuit_breakers/repository_storage/failing' do
- it 'returns an array of failing storages' do
- get api('/circuit_breakers/repository_storage/failing', admin)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to be_kind_of(Array)
- expect(json_response).to be_empty
- end
- end
- end
-
- describe 'DELETE circuit_breakers/repository_storage' do
- it 'clears all circuit_breakers' do
- delete api('/circuit_breakers/repository_storage', admin)
-
- expect(response).to have_gitlab_http_status(204)
- end
- end
-end
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index a132b85b878..f104da6ebba 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -2,6 +2,8 @@ require 'spec_helper'
require 'mime/types'
describe API::Commits do
+ include ProjectForksHelper
+
let(:user) { create(:user) }
let(:guest) { create(:user).tap { |u| project.add_guest(u) } }
let(:project) { create(:project, :repository, creator: user, path: 'my.project') }
@@ -317,6 +319,96 @@ describe API::Commits do
expect(response).to have_gitlab_http_status(201)
end
end
+
+ context 'when the API user is a guest' do
+ def last_commit_id(project, branch_name)
+ project.repository.find_branch(branch_name)&.dereferenced_target&.id
+ end
+
+ let(:public_project) { create(:project, :public, :repository) }
+ let!(:url) { "/projects/#{public_project.id}/repository/commits" }
+ let(:guest) { create(:user).tap { |u| public_project.add_guest(u) } }
+
+ it 'returns a 403' do
+ post api(url, guest), params: valid_c_params
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+
+ context 'when start_project is provided' do
+ context 'when posting to a forked project the user owns' do
+ let!(:forked_project) { fork_project(public_project, guest, namespace: guest.namespace, repository: true) }
+ let!(:url) { "/projects/#{forked_project.id}/repository/commits" }
+
+ before do
+ valid_c_params[:start_branch] = "master"
+ valid_c_params[:branch] = "patch"
+ end
+
+ context 'identified by Integer (id)' do
+ before do
+ valid_c_params[:start_project] = public_project.id
+ end
+
+ it 'adds a new commit to forked_project and returns a 201' do
+ expect { post api(url, guest), params: valid_c_params }
+ .to change { last_commit_id(forked_project, valid_c_params[:branch]) }
+ .and not_change { last_commit_id(public_project, valid_c_params[:start_branch]) }
+
+ expect(response).to have_gitlab_http_status(201)
+ end
+ end
+
+ context 'identified by String (full_path)' do
+ before do
+ valid_c_params[:start_project] = public_project.full_path
+ end
+
+ it 'adds a new commit to forked_project and returns a 201' do
+ expect { post api(url, guest), params: valid_c_params }
+ .to change { last_commit_id(forked_project, valid_c_params[:branch]) }
+ .and not_change { last_commit_id(public_project, valid_c_params[:start_branch]) }
+
+ expect(response).to have_gitlab_http_status(201)
+ end
+ end
+ end
+
+ context 'when the target project is not part of the fork network of start_project' do
+ let(:unrelated_project) { create(:project, :public, :repository, creator: guest) }
+ let!(:url) { "/projects/#{unrelated_project.id}/repository/commits" }
+
+ before do
+ valid_c_params[:start_branch] = "master"
+ valid_c_params[:branch] = "patch"
+ valid_c_params[:start_project] = public_project.id
+ end
+
+ it 'returns a 403' do
+ post api(url, guest), params: valid_c_params
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+ end
+ end
+
+ context 'when posting to a forked project the user does not have write access' do
+ let!(:forked_project) { fork_project(public_project, user, namespace: user.namespace, repository: true) }
+ let!(:url) { "/projects/#{forked_project.id}/repository/commits" }
+
+ before do
+ valid_c_params[:start_branch] = "master"
+ valid_c_params[:branch] = "patch"
+ valid_c_params[:start_project] = public_project.id
+ end
+
+ it 'returns a 403' do
+ post api(url, guest), params: valid_c_params
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+ end
+ end
end
describe 'delete' do
diff --git a/spec/requests/api/discussions_spec.rb b/spec/requests/api/discussions_spec.rb
index 35c448d187d..ca1ffe3c524 100644
--- a/spec/requests/api/discussions_spec.rb
+++ b/spec/requests/api/discussions_spec.rb
@@ -13,7 +13,7 @@ describe API::Discussions do
let!(:issue) { create(:issue, project: project, author: user) }
let!(:issue_note) { create(:discussion_note_on_issue, noteable: issue, project: project, author: user) }
- it_behaves_like 'discussions API', 'projects', 'issues', 'iid' do
+ it_behaves_like 'discussions API', 'projects', 'issues', 'iid', can_reply_to_individual_notes: true do
let(:parent) { project }
let(:noteable) { issue }
let(:note) { issue_note }
@@ -37,7 +37,7 @@ describe API::Discussions do
let!(:diff_note) { create(:diff_note_on_merge_request, noteable: noteable, project: project, author: user) }
let(:parent) { project }
- it_behaves_like 'discussions API', 'projects', 'merge_requests', 'iid'
+ it_behaves_like 'discussions API', 'projects', 'merge_requests', 'iid', can_reply_to_individual_notes: true
it_behaves_like 'diff discussions API', 'projects', 'merge_requests', 'iid'
it_behaves_like 'resolvable discussions API', 'projects', 'merge_requests', 'iid'
end
diff --git a/spec/requests/api/events_spec.rb b/spec/requests/api/events_spec.rb
index 065b16c6221..018691e8099 100644
--- a/spec/requests/api/events_spec.rb
+++ b/spec/requests/api/events_spec.rb
@@ -164,139 +164,4 @@ describe API::Events do
expect(json_response['message']).to eq('404 User Not Found')
end
end
-
- describe 'GET /projects/:id/events' do
- context 'when unauthenticated ' do
- it 'returns 404 for private project' do
- get api("/projects/#{private_project.id}/events")
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns 200 status for a public project' do
- public_project = create(:project, :public)
-
- get api("/projects/#{public_project.id}/events")
-
- expect(response).to have_gitlab_http_status(200)
- end
- end
-
- context 'with inaccessible events' do
- let(:public_project) { create(:project, :public, creator_id: user.id, namespace: user.namespace) }
- let(:confidential_issue) { create(:closed_issue, confidential: true, project: public_project, author: user) }
- let!(:confidential_event) { create(:event, project: public_project, author: user, target: confidential_issue, action: Event::CLOSED) }
- let(:public_issue) { create(:closed_issue, project: public_project, author: user) }
- let!(:public_event) { create(:event, project: public_project, author: user, target: public_issue, action: Event::CLOSED) }
-
- it 'returns only accessible events' do
- get api("/projects/#{public_project.id}/events", non_member)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response.size).to eq(1)
- end
-
- it 'returns all events when the user has access' do
- get api("/projects/#{public_project.id}/events", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response.size).to eq(2)
- end
- end
-
- context 'pagination' do
- let(:public_project) { create(:project, :public) }
-
- before do
- create(:event,
- project: public_project,
- target: create(:issue, project: public_project, title: 'Issue 1'),
- action: Event::CLOSED,
- created_at: Date.parse('2018-12-10'))
- create(:event,
- project: public_project,
- target: create(:issue, confidential: true, project: public_project, title: 'Confidential event'),
- action: Event::CLOSED,
- created_at: Date.parse('2018-12-11'))
- create(:event,
- project: public_project,
- target: create(:issue, project: public_project, title: 'Issue 2'),
- action: Event::CLOSED,
- created_at: Date.parse('2018-12-12'))
- end
-
- it 'correctly returns the second page without inaccessible events' do
- get api("/projects/#{public_project.id}/events", user), params: { per_page: 2, page: 2 }
-
- titles = json_response.map { |event| event['target_title'] }
-
- expect(titles.first).to eq('Issue 1')
- expect(titles).not_to include('Confidential event')
- end
-
- it 'correctly returns the first page without inaccessible events' do
- get api("/projects/#{public_project.id}/events", user), params: { per_page: 2, page: 1 }
-
- titles = json_response.map { |event| event['target_title'] }
-
- expect(titles.first).to eq('Issue 2')
- expect(titles).not_to include('Confidential event')
- end
- end
-
- context 'when not permitted to read' do
- it 'returns 404' do
- get api("/projects/#{private_project.id}/events", non_member)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'when authenticated' do
- it 'returns project events' do
- get api("/projects/#{private_project.id}/events?action=closed&target_type=issue&after=2016-12-1&before=2016-12-31", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.size).to eq(1)
- end
-
- it 'returns 404 if project does not exist' do
- get api("/projects/1234/events", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- context 'when exists some events' do
- let(:merge_request1) { create(:merge_request, :closed, author: user, assignees: [user], source_project: private_project, title: 'Test') }
- let(:merge_request2) { create(:merge_request, :closed, author: user, assignees: [user], source_project: private_project, title: 'Test') }
-
- before do
- create_event(merge_request1)
- end
-
- it 'avoids N+1 queries' do
- control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
- get api("/projects/#{private_project.id}/events", user), params: { target_type: :merge_request }
- end.count
-
- create_event(merge_request2)
-
- expect do
- get api("/projects/#{private_project.id}/events", user), params: { target_type: :merge_request }
- end.not_to exceed_all_query_limit(control_count)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response.size).to eq(2)
- expect(json_response.map { |r| r['target_id'] }).to match_array([merge_request1.id, merge_request2.id])
- end
-
- def create_event(target)
- create(:event, project: private_project, author: user, target: target)
- end
- end
- end
end
diff --git a/spec/requests/api/graphql/gitlab_schema_spec.rb b/spec/requests/api/graphql/gitlab_schema_spec.rb
index b63b4fb34df..28676bb02f4 100644
--- a/spec/requests/api/graphql/gitlab_schema_spec.rb
+++ b/spec/requests/api/graphql/gitlab_schema_spec.rb
@@ -3,15 +3,103 @@ require 'spec_helper'
describe 'GitlabSchema configurations' do
include GraphqlHelpers
- it 'shows an error if complexity is too high' do
- project = create(:project, :repository)
- query = graphql_query_for('project', { 'fullPath' => project.full_path }, %w(id name description))
+ set(:project) { create(:project) }
- allow(GitlabSchema).to receive(:max_query_complexity).and_return 1
+ shared_examples 'imposing query limits' do
+ describe '#max_complexity' do
+ context 'when complexity is too high' do
+ it 'shows an error' do
+ allow(GitlabSchema).to receive(:max_query_complexity).and_return 1
- post_graphql(query, current_user: nil)
+ subject
- expect(graphql_errors.first['message']).to include('which exceeds max complexity of 1')
+ expect(graphql_errors.flatten.first['message']).to include('which exceeds max complexity of 1')
+ end
+ end
+ end
+
+ describe '#max_depth' do
+ context 'when query depth is too high' do
+ it 'shows error' do
+ errors = { "message" => "Query has depth of 2, which exceeds max depth of 1" }
+ allow(GitlabSchema).to receive(:max_query_depth).and_return 1
+
+ subject
+
+ expect(graphql_errors.flatten).to include(errors)
+ end
+ end
+
+ context 'when query depth is within range' do
+ it 'has no error' do
+ allow(GitlabSchema).to receive(:max_query_depth).and_return 5
+
+ subject
+
+ expect(Array.wrap(graphql_errors).compact).to be_empty
+ end
+ end
+ end
+ end
+
+ context 'regular queries' do
+ subject do
+ query = graphql_query_for('project', { 'fullPath' => project.full_path }, %w(id name description))
+ post_graphql(query)
+ end
+
+ it_behaves_like 'imposing query limits'
+ end
+
+ context 'multiplexed queries' do
+ let(:current_user) { nil }
+
+ subject do
+ queries = [
+ { query: graphql_query_for('project', { 'fullPath' => '$fullPath' }, %w(id name description)) },
+ { query: graphql_query_for('echo', { 'text' => "$test" }, []), variables: { "test" => "Hello world" } },
+ { query: graphql_query_for('project', { 'fullPath' => project.full_path }, "userPermissions { createIssue }") }
+ ]
+
+ post_multiplex(queries, current_user: current_user)
+ end
+
+ it 'does not authenticate all queries' do
+ subject
+
+ expect(json_response.last['data']['project']).to be_nil
+ end
+
+ it_behaves_like 'imposing query limits' do
+ it "fails all queries when only one of the queries is too complex" do
+ # The `project` query above has a complexity of 5
+ allow(GitlabSchema).to receive(:max_query_complexity).and_return 4
+
+ subject
+
+ # Expect a response for each query, even though it will be empty
+ expect(json_response.size).to eq(3)
+ json_response.each do |single_query_response|
+ expect(single_query_response).not_to have_key('data')
+ end
+
+ # Expect errors for each query
+ expect(graphql_errors.size).to eq(3)
+ graphql_errors.each do |single_query_errors|
+ expect(single_query_errors.first['message']).to include('which exceeds max complexity of 4')
+ end
+ end
+ end
+
+ context 'authentication' do
+ let(:current_user) { project.owner }
+
+ it 'authenticates all queries' do
+ subject
+
+ expect(json_response.last['data']['project']['userPermissions']['createIssue']).to be(true)
+ end
+ end
end
context 'when IntrospectionQuery' do
@@ -23,4 +111,40 @@ describe 'GitlabSchema configurations' do
expect(graphql_errors).to be_nil
end
end
+
+ context 'logging' do
+ let(:query) { File.read(Rails.root.join('spec/fixtures/api/graphql/introspection.graphql')) }
+
+ it 'logs the query complexity and depth' do
+ analyzer_memo = {
+ query_string: query,
+ variables: {}.to_s,
+ complexity: 181,
+ depth: 0,
+ duration: 7
+ }
+
+ expect_any_instance_of(Gitlab::Graphql::QueryAnalyzers::LoggerAnalyzer).to receive(:duration).and_return(7)
+ expect(Gitlab::GraphqlLogger).to receive(:info).with(analyzer_memo)
+
+ post_graphql(query, current_user: nil)
+ end
+
+ it 'logs using `format_message`' do
+ expect_any_instance_of(Gitlab::GraphqlLogger).to receive(:format_message)
+
+ post_graphql(query, current_user: nil)
+ end
+ end
+
+ context "global id's" do
+ it 'uses GlobalID to expose ids' do
+ post_graphql(graphql_query_for('project', { 'fullPath' => project.full_path }, %w(id)),
+ current_user: project.owner)
+
+ parsed_id = GlobalID.parse(graphql_data['project']['id'])
+
+ expect(parsed_id).to eq(project.to_global_id)
+ end
+ end
end
diff --git a/spec/requests/api/graphql/group_query_spec.rb b/spec/requests/api/graphql/group_query_spec.rb
new file mode 100644
index 00000000000..e0f1e4dbe9e
--- /dev/null
+++ b/spec/requests/api/graphql/group_query_spec.rb
@@ -0,0 +1,119 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+# Based on spec/requests/api/groups_spec.rb
+# Should follow closely in order to ensure all situations are covered
+describe 'getting group information' do
+ include GraphqlHelpers
+ include UploadHelpers
+
+ let(:user1) { create(:user, can_create_group: false) }
+ let(:user2) { create(:user) }
+ let(:admin) { create(:admin) }
+ let(:public_group) { create(:group, :public) }
+ let(:private_group) { create(:group, :private) }
+
+ # similar to the API "GET /groups/:id"
+ describe "Query group(fullPath)" do
+ def group_query(group)
+ graphql_query_for('group', 'fullPath' => group.full_path)
+ end
+
+ it_behaves_like 'a working graphql query' do
+ before do
+ post_graphql(group_query(public_group))
+ end
+ end
+
+ context 'when unauthenticated' do
+ it 'returns nil for a private group' do
+ post_graphql(group_query(private_group))
+
+ expect(graphql_data['group']).to be_nil
+ end
+
+ it 'returns a public group' do
+ post_graphql(group_query(public_group))
+
+ expect(graphql_data['group']).not_to be_nil
+ end
+ end
+
+ context "when authenticated as user" do
+ let!(:group1) { create(:group, avatar: File.open(uploaded_image_temp_path)) }
+ let!(:group2) { create(:group, :private) }
+
+ before do
+ group1.add_owner(user1)
+ group2.add_owner(user2)
+ end
+
+ it "returns one of user1's groups" do
+ project = create(:project, namespace: group2, path: 'Foo')
+ create(:project_group_link, project: project, group: group1)
+
+ post_graphql(group_query(group1), current_user: user1)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(graphql_data['group']['id']).to eq(group1.to_global_id.to_s)
+ expect(graphql_data['group']['name']).to eq(group1.name)
+ expect(graphql_data['group']['path']).to eq(group1.path)
+ expect(graphql_data['group']['description']).to eq(group1.description)
+ expect(graphql_data['group']['visibility']).to eq(Gitlab::VisibilityLevel.string_level(group1.visibility_level))
+ expect(graphql_data['group']['avatarUrl']).to eq(group1.avatar_url(only_path: false))
+ expect(graphql_data['group']['webUrl']).to eq(group1.web_url)
+ expect(graphql_data['group']['requestAccessEnabled']).to eq(group1.request_access_enabled)
+ expect(graphql_data['group']['fullName']).to eq(group1.full_name)
+ expect(graphql_data['group']['fullPath']).to eq(group1.full_path)
+ expect(graphql_data['group']['parentId']).to eq(group1.parent_id)
+ end
+
+ it "does not return a non existing group" do
+ query = graphql_query_for('group', 'fullPath' => '1328')
+
+ post_graphql(query, current_user: user1)
+
+ expect(graphql_data['group']).to be_nil
+ end
+
+ it "does not return a group not attached to user1" do
+ private_group.add_owner(user2)
+
+ post_graphql(group_query(private_group), current_user: user1)
+
+ expect(graphql_data['group']).to be_nil
+ end
+
+ it 'avoids N+1 queries' do
+ control_count = ActiveRecord::QueryRecorder.new do
+ post_graphql(group_query(group1), current_user: admin)
+ end.count
+
+ queries = [{ query: group_query(group1) },
+ { query: group_query(group2) }]
+
+ expect do
+ post_multiplex(queries, current_user: admin)
+ end.not_to exceed_query_limit(control_count)
+
+ expect(graphql_errors).to contain_exactly(nil, nil)
+ end
+ end
+
+ context "when authenticated as admin" do
+ it "returns any existing group" do
+ post_graphql(group_query(private_group), current_user: admin)
+
+ expect(graphql_data['group']['name']).to eq(private_group.name)
+ end
+
+ it "does not return a non existing group" do
+ query = graphql_query_for('group', 'fullPath' => '1328')
+ post_graphql(query, current_user: admin)
+
+ expect(graphql_data['group']).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/multiplexed_queries_spec.rb b/spec/requests/api/graphql/multiplexed_queries_spec.rb
new file mode 100644
index 00000000000..844fd979285
--- /dev/null
+++ b/spec/requests/api/graphql/multiplexed_queries_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe 'Multiplexed queries' do
+ include GraphqlHelpers
+
+ it 'returns responses for multiple queries' do
+ queries = [
+ { query: 'query($text: String) { echo(text: $text) }',
+ variables: { 'text' => 'Hello' } },
+ { query: 'query($text: String) { echo(text: $text) }',
+ variables: { 'text' => 'World' } }
+ ]
+
+ post_multiplex(queries)
+
+ first_response = json_response.first['data']['echo']
+ second_response = json_response.last['data']['echo']
+
+ expect(first_response).to eq('nil says: Hello')
+ expect(second_response).to eq('nil says: World')
+ end
+
+ it 'returns error and data combinations' do
+ queries = [
+ { query: 'query($text: String) { broken query }' },
+ { query: 'query working($text: String) { echo(text: $text) }',
+ variables: { 'text' => 'World' } }
+ ]
+
+ post_multiplex(queries)
+
+ first_response = json_response.first['errors']
+ second_response = json_response.last['data']['echo']
+
+ expect(first_response).not_to be_empty
+ expect(second_response).to eq('nil says: World')
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_wip_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_wip_spec.rb
index 8f427d71a32..d75f0df9fd3 100644
--- a/spec/requests/api/graphql/mutations/merge_requests/set_wip_spec.rb
+++ b/spec/requests/api/graphql/mutations/merge_requests/set_wip_spec.rb
@@ -11,7 +11,7 @@ describe 'Setting WIP status of a merge request' do
let(:mutation) do
variables = {
project_path: project.full_path,
- iid: merge_request.iid
+ iid: merge_request.iid.to_s
}
graphql_mutation(:merge_request_set_wip, variables.merge(input))
end
diff --git a/spec/requests/api/graphql/namespace/projects_spec.rb b/spec/requests/api/graphql/namespace/projects_spec.rb
new file mode 100644
index 00000000000..de1cd9586b6
--- /dev/null
+++ b/spec/requests/api/graphql/namespace/projects_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'getting projects', :nested_groups do
+ include GraphqlHelpers
+
+ let(:group) { create(:group) }
+ let!(:project) { create(:project, namespace: subject) }
+ let(:nested_group) { create(:group, parent: group) }
+ let!(:nested_project) { create(:project, group: nested_group) }
+ let!(:public_project) { create(:project, :public, namespace: subject) }
+ let(:user) { create(:user) }
+ let(:include_subgroups) { true }
+
+ subject { group }
+
+ let(:query) do
+ graphql_query_for(
+ 'namespace',
+ { 'fullPath' => subject.full_path },
+ <<~QUERY
+ projects(includeSubgroups: #{include_subgroups}) {
+ edges {
+ node {
+ #{all_graphql_fields_for('Project')}
+ }
+ }
+ }
+ QUERY
+ )
+ end
+
+ before do
+ group.add_owner(user)
+ end
+
+ shared_examples 'a graphql namespace' do
+ it_behaves_like 'a working graphql query' do
+ before do
+ post_graphql(query, current_user: user)
+ end
+ end
+
+ it "includes the packages size if the user can read the statistics" do
+ post_graphql(query, current_user: user)
+
+ count = if include_subgroups
+ subject.all_projects.count
+ else
+ subject.projects.count
+ end
+
+ expect(graphql_data['namespace']['projects']['edges'].size).to eq(count)
+ end
+
+ context 'with no user' do
+ it 'finds only public projects' do
+ post_graphql(query, current_user: nil)
+
+ expect(graphql_data['namespace']['projects']['edges'].size).to eq(1)
+ project = graphql_data['namespace']['projects']['edges'][0]['node']
+ expect(project['id']).to eq(public_project.to_global_id.to_s)
+ end
+ end
+ end
+
+ it_behaves_like 'a graphql namespace'
+
+ context 'when the namespace is a user' do
+ subject { user.namespace }
+ let(:include_subgroups) { false }
+
+ it_behaves_like 'a graphql namespace'
+ end
+
+ context 'when not including subgroups' do
+ let(:include_subgroups) { false }
+
+ it_behaves_like 'a graphql namespace'
+ end
+end
diff --git a/spec/requests/api/graphql/project/issues_spec.rb b/spec/requests/api/graphql/project/issues_spec.rb
index c2934430821..4f9f916f22e 100644
--- a/spec/requests/api/graphql/project/issues_spec.rb
+++ b/spec/requests/api/graphql/project/issues_spec.rb
@@ -7,8 +7,8 @@ describe 'getting an issue list for a project' do
let(:current_user) { create(:user) }
let(:issues_data) { graphql_data['project']['issues']['edges'] }
let!(:issues) do
- create(:issue, project: project, discussion_locked: true)
- create(:issue, project: project)
+ [create(:issue, project: project, discussion_locked: true),
+ create(:issue, project: project)]
end
let(:fields) do
<<~QUERY
@@ -47,6 +47,30 @@ describe 'getting an issue list for a project' do
expect(issues_data[1]['node']['discussionLocked']).to eq true
end
+ context 'when limiting the number of results' do
+ let(:query) do
+ graphql_query_for(
+ 'project',
+ { 'fullPath' => project.full_path },
+ "issues(first: 1) { #{fields} }"
+ )
+ end
+
+ it_behaves_like 'a working graphql query' do
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+ end
+
+ it "is expected to check permissions on the first issue only" do
+ allow(Ability).to receive(:allowed?).and_call_original
+ # Newest first, we only want to see the newest checked
+ expect(Ability).not_to receive(:allowed?).with(current_user, :read_issue, issues.first)
+
+ post_graphql(query, current_user: current_user)
+ end
+ end
+
context 'when the user does not have access to the issue' do
it 'returns nil' do
project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
diff --git a/spec/requests/api/graphql/project/project_statistics_spec.rb b/spec/requests/api/graphql/project/project_statistics_spec.rb
new file mode 100644
index 00000000000..8683fa1f390
--- /dev/null
+++ b/spec/requests/api/graphql/project/project_statistics_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'rendering namespace statistics' do
+ include GraphqlHelpers
+
+ let(:project) { create(:project) }
+ let!(:project_statistics) { create(:project_statistics, project: project, packages_size: 5.megabytes) }
+ let(:user) { create(:user) }
+
+ let(:query) do
+ graphql_query_for('project',
+ { 'fullPath' => project.full_path },
+ "statistics { #{all_graphql_fields_for('ProjectStatistics')} }")
+ end
+
+ before do
+ project.add_reporter(user)
+ end
+
+ it_behaves_like 'a working graphql query' do
+ before do
+ post_graphql(query, current_user: user)
+ end
+ end
+
+ it "includes the packages size if the user can read the statistics" do
+ post_graphql(query, current_user: user)
+
+ expect(graphql_data['project']['statistics']['packagesSize']).to eq(5.megabytes)
+ end
+
+ context 'when the project is public' do
+ let(:project) { create(:project, :public) }
+
+ it 'includes the statistics regardless of the user' do
+ post_graphql(query, current_user: nil)
+
+ expect(graphql_data['project']['statistics']).to be_present
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/project/repository_spec.rb b/spec/requests/api/graphql/project/repository_spec.rb
new file mode 100644
index 00000000000..67af612a4a0
--- /dev/null
+++ b/spec/requests/api/graphql/project/repository_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe 'getting a repository in a project' do
+ include GraphqlHelpers
+
+ let(:project) { create(:project, :repository) }
+ let(:current_user) { project.owner }
+ let(:fields) do
+ <<~QUERY
+ #{all_graphql_fields_for('repository'.classify)}
+ QUERY
+ end
+ let(:query) do
+ graphql_query_for(
+ 'project',
+ { 'fullPath' => project.full_path },
+ query_graphql_field('repository', {}, fields)
+ )
+ end
+
+ it 'returns repository' do
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data['project']['repository']).to be_present
+ end
+
+ context 'as a non-authorized user' do
+ let(:current_user) { create(:user) }
+
+ it 'returns nil' do
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data['project']).to be(nil)
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/project/tree/tree_spec.rb b/spec/requests/api/graphql/project/tree/tree_spec.rb
new file mode 100644
index 00000000000..b07aa1e12d3
--- /dev/null
+++ b/spec/requests/api/graphql/project/tree/tree_spec.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe 'getting a tree in a project' do
+ include GraphqlHelpers
+
+ let(:project) { create(:project, :repository) }
+ let(:current_user) { project.owner }
+ let(:path) { "" }
+ let(:ref) { "master" }
+ let(:fields) do
+ <<~QUERY
+ tree(path:"#{path}", ref:"#{ref}") {
+ #{all_graphql_fields_for('tree'.classify)}
+ }
+ QUERY
+ end
+ let(:query) do
+ graphql_query_for(
+ 'project',
+ { 'fullPath' => project.full_path },
+ query_graphql_field('repository', {}, fields)
+ )
+ end
+
+ context 'when path does not exist' do
+ let(:path) { "testing123" }
+
+ it 'returns empty tree' do
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data['project']['repository']['tree']['trees']['edges']).to eq([])
+ expect(graphql_data['project']['repository']['tree']['submodules']['edges']).to eq([])
+ expect(graphql_data['project']['repository']['tree']['blobs']['edges']).to eq([])
+ end
+ end
+
+ context 'when ref does not exist' do
+ let(:ref) { "testing123" }
+
+ it 'returns empty tree' do
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data['project']['repository']['tree']['trees']['edges']).to eq([])
+ expect(graphql_data['project']['repository']['tree']['submodules']['edges']).to eq([])
+ expect(graphql_data['project']['repository']['tree']['blobs']['edges']).to eq([])
+ end
+ end
+
+ context 'when ref and path exist' do
+ it 'returns tree' do
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data['project']['repository']['tree']).to be_present
+ end
+
+ it 'returns blobs, subtrees and submodules inside tree' do
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data['project']['repository']['tree']['trees']['edges'].size).to be > 0
+ expect(graphql_data['project']['repository']['tree']['blobs']['edges'].size).to be > 0
+ expect(graphql_data['project']['repository']['tree']['submodules']['edges'].size).to be > 0
+ end
+ end
+
+ context 'when current user is nil' do
+ it 'returns empty project' do
+ post_graphql(query, current_user: nil)
+
+ expect(graphql_data['project']).to be(nil)
+ end
+ end
+end
diff --git a/spec/requests/api/graphql_spec.rb b/spec/requests/api/graphql_spec.rb
index cca87c16f27..656d6f8b50b 100644
--- a/spec/requests/api/graphql_spec.rb
+++ b/spec/requests/api/graphql_spec.rb
@@ -16,6 +16,54 @@ describe 'GraphQL' do
end
end
+ context 'logging' do
+ shared_examples 'logging a graphql query' do
+ let(:expected_params) do
+ { query_string: query, variables: variables.to_s, duration: anything, depth: 1, complexity: 1 }
+ end
+
+ it 'logs a query with the expected params' do
+ expect(Gitlab::GraphqlLogger).to receive(:info).with(expected_params).once
+
+ post_graphql(query, variables: variables)
+ end
+
+ it 'does not instantiate any query analyzers' do # they are static and re-used
+ expect(GraphQL::Analysis::QueryComplexity).not_to receive(:new)
+ expect(GraphQL::Analysis::QueryDepth).not_to receive(:new)
+
+ 2.times { post_graphql(query, variables: variables) }
+ end
+ end
+
+ context 'with no variables' do
+ let(:variables) { {} }
+
+ it_behaves_like 'logging a graphql query'
+ end
+
+ context 'with variables' do
+ let(:variables) do
+ { "foo" => "bar" }
+ end
+
+ it_behaves_like 'logging a graphql query'
+ end
+
+ context 'when there is an error in the logger' do
+ before do
+ allow_any_instance_of(Gitlab::Graphql::QueryAnalyzers::LoggerAnalyzer).to receive(:process_variables).and_raise(StandardError.new("oh noes!"))
+ end
+
+ it 'logs the exception in Sentry and continues with the request' do
+ expect(Gitlab::Sentry).to receive(:track_exception).at_least(1).times
+ expect(Gitlab::GraphqlLogger).to receive(:info)
+
+ post_graphql(query, variables: {})
+ end
+ end
+ end
+
context 'invalid variables' do
it 'returns an error' do
post_graphql(query, variables: "This is not JSON")
diff --git a/spec/requests/api/group_variables_spec.rb b/spec/requests/api/group_variables_spec.rb
index 66b9aae4b58..d50bae3dc47 100644
--- a/spec/requests/api/group_variables_spec.rb
+++ b/spec/requests/api/group_variables_spec.rb
@@ -51,6 +51,7 @@ describe API::GroupVariables do
expect(response).to have_gitlab_http_status(200)
expect(json_response['value']).to eq(variable.value)
expect(json_response['protected']).to eq(variable.protected?)
+ expect(json_response['variable_type']).to eq(variable.variable_type)
end
it 'responds with 404 Not Found if requesting non-existing variable' do
@@ -94,17 +95,19 @@ describe API::GroupVariables do
expect(json_response['key']).to eq('TEST_VARIABLE_2')
expect(json_response['value']).to eq('PROTECTED_VALUE_2')
expect(json_response['protected']).to be_truthy
+ expect(json_response['variable_type']).to eq('env_var')
end
it 'creates variable with optional attributes' do
expect do
- post api("/groups/#{group.id}/variables", user), params: { key: 'TEST_VARIABLE_2', value: 'VALUE_2' }
+ post api("/groups/#{group.id}/variables", user), params: { variable_type: 'file', key: 'TEST_VARIABLE_2', value: 'VALUE_2' }
end.to change {group.variables.count}.by(1)
expect(response).to have_gitlab_http_status(201)
expect(json_response['key']).to eq('TEST_VARIABLE_2')
expect(json_response['value']).to eq('VALUE_2')
expect(json_response['protected']).to be_falsey
+ expect(json_response['variable_type']).to eq('file')
end
it 'does not allow to duplicate variable key' do
@@ -145,7 +148,7 @@ describe API::GroupVariables do
initial_variable = group.variables.reload.first
value_before = initial_variable.value
- put api("/groups/#{group.id}/variables/#{variable.key}", user), params: { value: 'VALUE_1_UP', protected: true }
+ put api("/groups/#{group.id}/variables/#{variable.key}", user), params: { variable_type: 'file', value: 'VALUE_1_UP', protected: true }
updated_variable = group.variables.reload.first
@@ -153,6 +156,7 @@ describe API::GroupVariables do
expect(value_before).to eq(variable.value)
expect(updated_variable.value).to eq('VALUE_1_UP')
expect(updated_variable).to be_protected
+ expect(json_response['variable_type']).to eq('file')
end
it 'responds with 404 Not Found if requesting non-existing variable' do
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 7176bc23e34..c41408fba65 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -90,8 +90,9 @@ describe API::Groups do
it "includes statistics if requested" do
attributes = {
- storage_size: 702,
+ storage_size: 1158,
repository_size: 123,
+ wiki_size: 456,
lfs_objects_size: 234,
build_artifacts_size: 345
}.stringify_keys
diff --git a/spec/requests/api/helpers_spec.rb b/spec/requests/api/helpers_spec.rb
index a0c64d295c0..ed907841bd8 100644
--- a/spec/requests/api/helpers_spec.rb
+++ b/spec/requests/api/helpers_spec.rb
@@ -247,11 +247,10 @@ describe API::Helpers do
exception = RuntimeError.new('test error')
allow(exception).to receive(:backtrace).and_return(caller)
- expect(Raven).to receive(:capture_exception).with(exception, tags: {
- correlation_id: 'new-correlation-id'
- }, extra: {})
+ expect(Raven).to receive(:capture_exception).with(exception, tags:
+ a_hash_including(correlation_id: 'new-correlation-id'), extra: {})
- Gitlab::CorrelationId.use_id('new-correlation-id') do
+ Labkit::Correlation::CorrelationId.use_id('new-correlation-id') do
handle_api_exception(exception)
end
end
diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb
index 1ce8f520962..fcbff19bd61 100644
--- a/spec/requests/api/internal_spec.rb
+++ b/spec/requests/api/internal_spec.rb
@@ -959,7 +959,9 @@ describe API::Internal do
it 'creates a new merge request' do
expect do
- post api('/internal/post_receive'), params: valid_params
+ Sidekiq::Testing.fake! do
+ post api('/internal/post_receive'), params: valid_params
+ end
end.to change { MergeRequest.count }.by(1)
end
@@ -995,20 +997,6 @@ describe API::Internal do
expect(json_response['warnings']).to eq('Error encountered with push options \'merge_request.create\': my error')
end
-
- context 'when the feature is disabled' do
- it 'does not invoke MergeRequests::PushOptionsHandlerService' do
- Feature.disable(:mr_push_options)
-
- expect(MergeRequests::PushOptionsHandlerService).to receive(:new)
-
- expect do
- post api('/internal/post_receive'), params: valid_params
- end.not_to change { MergeRequest.count }
-
- Feature.enable(:mr_push_options)
- end
- end
end
context 'broadcast message exists' do
diff --git a/spec/requests/api/issues/get_group_issues_spec.rb b/spec/requests/api/issues/get_group_issues_spec.rb
new file mode 100644
index 00000000000..8b02cf56e9f
--- /dev/null
+++ b/spec/requests/api/issues/get_group_issues_spec.rb
@@ -0,0 +1,652 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe API::Issues do
+ set(:user) { create(:user) }
+ let(:user2) { create(:user) }
+ let(:non_member) { create(:user) }
+ set(:guest) { create(:user) }
+ set(:author) { create(:author) }
+ set(:assignee) { create(:assignee) }
+ let(:admin) { create(:user, :admin) }
+
+ let(:issue_title) { 'foo' }
+ let(:issue_description) { 'closed' }
+
+ let(:no_milestone_title) { 'None' }
+ let(:any_milestone_title) { 'Any' }
+
+ before do
+ stub_licensed_features(multiple_issue_assignees: false, issue_weights: false)
+ end
+
+ describe 'GET /groups/:id/issues' do
+ let!(:group) { create(:group) }
+ let!(:group_project) { create(:project, :public, creator_id: user.id, namespace: group) }
+ let!(:group_closed_issue) do
+ create :closed_issue,
+ author: user,
+ assignees: [user],
+ project: group_project,
+ state: :closed,
+ milestone: group_milestone,
+ updated_at: 3.hours.ago,
+ created_at: 1.day.ago
+ end
+ let!(:group_confidential_issue) do
+ create :issue,
+ :confidential,
+ project: group_project,
+ author: author,
+ assignees: [assignee],
+ updated_at: 2.hours.ago,
+ created_at: 2.days.ago
+ end
+ let!(:group_issue) do
+ create :issue,
+ author: user,
+ assignees: [user],
+ project: group_project,
+ milestone: group_milestone,
+ updated_at: 1.hour.ago,
+ title: issue_title,
+ description: issue_description,
+ created_at: 5.days.ago
+ end
+ let!(:group_label) do
+ create(:label, title: 'group_lbl', color: '#FFAABB', project: group_project)
+ end
+ let!(:group_label_link) { create(:label_link, label: group_label, target: group_issue) }
+ let!(:group_milestone) { create(:milestone, title: '3.0.0', project: group_project) }
+ let!(:group_empty_milestone) do
+ create(:milestone, title: '4.0.0', project: group_project)
+ end
+ let!(:group_note) { create(:note_on_issue, author: user, project: group_project, noteable: group_issue) }
+
+ let(:base_url) { "/groups/#{group.id}/issues" }
+
+ shared_examples 'group issues statistics' do
+ it 'returns issues statistics' do
+ get api("/groups/#{group.id}/issues_statistics", user), params: params
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['statistics']).not_to be_nil
+ expect(json_response['statistics']['counts']['all']).to eq counts[:all]
+ expect(json_response['statistics']['counts']['closed']).to eq counts[:closed]
+ expect(json_response['statistics']['counts']['opened']).to eq counts[:opened]
+ end
+ end
+
+ context 'when group has subgroups', :nested_groups do
+ let(:subgroup_1) { create(:group, parent: group) }
+ let(:subgroup_2) { create(:group, parent: subgroup_1) }
+
+ let(:subgroup_1_project) { create(:project, :public, namespace: subgroup_1) }
+ let(:subgroup_2_project) { create(:project, namespace: subgroup_2) }
+
+ let!(:issue_1) { create(:issue, project: subgroup_1_project) }
+ let!(:issue_2) { create(:issue, project: subgroup_2_project) }
+
+ context 'when user is unauthenticated' do
+ it 'also returns subgroups public projects issues' do
+ get api(base_url)
+
+ expect_paginated_array_response([issue_1.id, group_closed_issue.id, group_issue.id])
+ end
+
+ it 'also returns subgroups public projects issues filtered by milestone' do
+ get api(base_url), params: { milestone: group_milestone.title }
+
+ expect_paginated_array_response([group_closed_issue.id, group_issue.id])
+ end
+
+ context 'issues_statistics' do
+ context 'no state is treated as all state' do
+ let(:params) { {} }
+ let(:counts) { { all: 3, closed: 1, opened: 2 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'statistics when all state is passed' do
+ let(:params) { { state: :all } }
+ let(:counts) { { all: 3, closed: 1, opened: 2 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'closed state is treated as all state' do
+ let(:params) { { state: :closed } }
+ let(:counts) { { all: 3, closed: 1, opened: 2 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'opened state is treated as all state' do
+ let(:params) { { state: :opened } }
+ let(:counts) { { all: 3, closed: 1, opened: 2 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'when filtering by milestone and no state treated as all state' do
+ let(:params) { { milestone: group_milestone.title } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'when filtering by milestone and all state' do
+ let(:params) { { milestone: group_milestone.title, state: :all } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'when filtering by milestone and closed state treated as all state' do
+ let(:params) { { milestone: group_milestone.title, state: :closed } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'when filtering by milestone and opened state treated as all state' do
+ let(:params) { { milestone: group_milestone.title, state: :opened } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+ end
+ end
+
+ context 'when user is a group member' do
+ before do
+ group.add_developer(user)
+ end
+
+ it 'also returns subgroups projects issues' do
+ get api(base_url, user)
+
+ expect_paginated_array_response([issue_2.id, issue_1.id, group_closed_issue.id, group_confidential_issue.id, group_issue.id])
+ end
+
+ it 'also returns subgroups public projects issues filtered by milestone' do
+ get api(base_url, user), params: { milestone: group_milestone.title }
+
+ expect_paginated_array_response([group_closed_issue.id, group_issue.id])
+ end
+
+ context 'issues_statistics' do
+ context 'no state is treated as all state' do
+ let(:params) { {} }
+ let(:counts) { { all: 5, closed: 1, opened: 4 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'statistics when all state is passed' do
+ let(:params) { { state: :all } }
+ let(:counts) { { all: 5, closed: 1, opened: 4 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'closed state is treated as all state' do
+ let(:params) { { state: :closed } }
+ let(:counts) { { all: 5, closed: 1, opened: 4 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'opened state is treated as all state' do
+ let(:params) { { state: :opened } }
+ let(:counts) { { all: 5, closed: 1, opened: 4 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'when filtering by milestone and no state treated as all state' do
+ let(:params) { { milestone: group_milestone.title } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'when filtering by milestone and all state' do
+ let(:params) { { milestone: group_milestone.title, state: :all } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'when filtering by milestone and closed state treated as all state' do
+ let(:params) { { milestone: group_milestone.title, state: :closed } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'when filtering by milestone and opened state treated as all state' do
+ let(:params) { { milestone: group_milestone.title, state: :opened } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+ end
+ end
+ end
+
+ context 'when user is unauthenticated' do
+ it 'lists all issues in public projects' do
+ get api(base_url)
+
+ expect_paginated_array_response([group_closed_issue.id, group_issue.id])
+ end
+
+ it 'also returns subgroups public projects issues filtered by milestone' do
+ get api(base_url), params: { milestone: group_milestone.title }
+
+ expect_paginated_array_response([group_closed_issue.id, group_issue.id])
+ end
+
+ context 'issues_statistics' do
+ context 'no state is treated as all state' do
+ let(:params) { {} }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'statistics when all state is passed' do
+ let(:params) { { state: :all } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'closed state is treated as all state' do
+ let(:params) { { state: :closed } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'opened state is treated as all state' do
+ let(:params) { { state: :opened } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'when filtering by milestone and no state treated as all state' do
+ let(:params) { { milestone: group_milestone.title } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'when filtering by milestone and all state' do
+ let(:params) { { milestone: group_milestone.title, state: :all } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'when filtering by milestone and closed state treated as all state' do
+ let(:params) { { milestone: group_milestone.title, state: :closed } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'when filtering by milestone and opened state treated as all state' do
+ let(:params) { { milestone: group_milestone.title, state: :opened } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+ end
+ end
+
+ context 'when user is a group member' do
+ before do
+ group_project.add_reporter(user)
+ end
+
+ it 'returns all group issues (including opened and closed)' do
+ get api(base_url, admin)
+
+ expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id, group_issue.id])
+ end
+
+ it 'returns group issues without confidential issues for non project members' do
+ get api(base_url, non_member), params: { state: :opened }
+
+ expect_paginated_array_response(group_issue.id)
+ end
+
+ it 'returns group confidential issues for author' do
+ get api(base_url, author), params: { state: :opened }
+
+ expect_paginated_array_response([group_confidential_issue.id, group_issue.id])
+ end
+
+ it 'returns group confidential issues for assignee' do
+ get api(base_url, assignee), params: { state: :opened }
+
+ expect_paginated_array_response([group_confidential_issue.id, group_issue.id])
+ end
+
+ it 'returns group issues with confidential issues for project members' do
+ get api(base_url, user), params: { state: :opened }
+
+ expect_paginated_array_response([group_confidential_issue.id, group_issue.id])
+ end
+
+ it 'returns group confidential issues for admin' do
+ get api(base_url, admin), params: { state: :opened }
+
+ expect_paginated_array_response([group_confidential_issue.id, group_issue.id])
+ end
+
+ it 'returns only confidential issues' do
+ get api(base_url, user), params: { confidential: true }
+
+ expect_paginated_array_response(group_confidential_issue.id)
+ end
+
+ it 'returns only public issues' do
+ get api(base_url, user), params: { confidential: false }
+
+ expect_paginated_array_response([group_closed_issue.id, group_issue.id])
+ end
+
+ it 'returns an array of labeled group issues' do
+ get api(base_url, user), params: { labels: group_label.title }
+
+ expect_paginated_array_response(group_issue.id)
+ expect(json_response.first['labels']).to eq([group_label.title])
+ end
+
+ it 'returns an array of labeled group issues with labels param as array' do
+ get api(base_url, user), params: { labels: [group_label.title] }
+
+ expect_paginated_array_response(group_issue.id)
+ expect(json_response.first['labels']).to eq([group_label.title])
+ end
+
+ it 'returns an array of labeled group issues where all labels match' do
+ get api(base_url, user), params: { labels: "#{group_label.title},foo,bar" }
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an array of labeled group issues where all labels match with labels param as array' do
+ get api(base_url, user), params: { labels: [group_label.title, 'foo', 'bar'] }
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns issues matching given search string for title' do
+ get api(base_url, user), params: { search: group_issue.title }
+
+ expect_paginated_array_response(group_issue.id)
+ end
+
+ it 'returns issues matching given search string for description' do
+ get api(base_url, user), params: { search: group_issue.description }
+
+ expect_paginated_array_response(group_issue.id)
+ end
+
+ context 'with labeled issues' do
+ let(:label_b) { create(:label, title: 'foo', project: group_project) }
+ let(:label_c) { create(:label, title: 'bar', project: group_project) }
+
+ before do
+ create(:label_link, label: label_b, target: group_issue)
+ create(:label_link, label: label_c, target: group_issue)
+
+ get api(base_url, user), params: params
+ end
+
+ let(:issue) { group_issue }
+ let(:label) { group_label }
+
+ it_behaves_like 'labeled issues with labels and label_name params'
+ end
+
+ it 'returns an array of issues found by iids' do
+ get api(base_url, user), params: { iids: [group_issue.iid] }
+
+ expect_paginated_array_response(group_issue.id)
+ expect(json_response.first['id']).to eq(group_issue.id)
+ end
+
+ it 'returns an empty array if iid does not exist' do
+ get api(base_url, user), params: { iids: [0] }
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an empty array if no group issue matches labels' do
+ get api(base_url, user), params: { labels: 'foo,bar' }
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an array of group issues with any label' do
+ get api(base_url, user), params: { labels: IssuesFinder::FILTER_ANY }
+
+ expect_paginated_array_response(group_issue.id)
+ expect(json_response.first['id']).to eq(group_issue.id)
+ end
+
+ it 'returns an array of group issues with any label with labels param as array' do
+ get api(base_url, user), params: { labels: [IssuesFinder::FILTER_ANY] }
+
+ expect_paginated_array_response(group_issue.id)
+ expect(json_response.first['id']).to eq(group_issue.id)
+ end
+
+ it 'returns an array of group issues with no label' do
+ get api(base_url, user), params: { labels: IssuesFinder::FILTER_NONE }
+
+ expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id])
+ end
+
+ it 'returns an array of group issues with no label with labels param as array' do
+ get api(base_url, user), params: { labels: [IssuesFinder::FILTER_NONE] }
+
+ expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id])
+ end
+
+ it 'returns an empty array if no issue matches milestone' do
+ get api(base_url, user), params: { milestone: group_empty_milestone.title }
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an empty array if milestone does not exist' do
+ get api(base_url, user), params: { milestone: 'foo' }
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an array of issues in given milestone' do
+ get api(base_url, user), params: { state: :opened, milestone: group_milestone.title }
+
+ expect_paginated_array_response(group_issue.id)
+ end
+
+ it 'returns an array of issues matching state in milestone' do
+ get api(base_url, user), params: { milestone: group_milestone.title, state: :closed }
+
+ expect_paginated_array_response(group_closed_issue.id)
+ end
+
+ it 'returns an array of issues with no milestone' do
+ get api(base_url, user), params: { milestone: no_milestone_title }
+
+ expect(response).to have_gitlab_http_status(200)
+
+ expect_paginated_array_response(group_confidential_issue.id)
+ end
+
+ context 'without sort params' do
+ it 'sorts by created_at descending by default' do
+ get api(base_url, user)
+
+ expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id, group_issue.id])
+ end
+
+ context 'with 2 issues with same created_at' do
+ let!(:group_issue2) do
+ create :issue,
+ author: user,
+ assignees: [user],
+ project: group_project,
+ milestone: group_milestone,
+ updated_at: 1.hour.ago,
+ title: issue_title,
+ description: issue_description,
+ created_at: group_issue.created_at
+ end
+
+ it 'page breaks first page correctly' do
+ get api("#{base_url}?per_page=3", user)
+
+ expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id, group_issue2.id])
+ end
+
+ it 'page breaks second page correctly' do
+ get api("#{base_url}?per_page=3&page=2", user)
+
+ expect_paginated_array_response([group_issue.id])
+ end
+ end
+ end
+
+ it 'sorts ascending when requested' do
+ get api("#{base_url}?sort=asc", user)
+
+ expect_paginated_array_response([group_issue.id, group_confidential_issue.id, group_closed_issue.id])
+ end
+
+ it 'sorts by updated_at descending when requested' do
+ get api("#{base_url}?order_by=updated_at", user)
+
+ group_issue.touch(:updated_at)
+
+ expect_paginated_array_response([group_issue.id, group_confidential_issue.id, group_closed_issue.id])
+ end
+
+ it 'sorts by updated_at ascending when requested' do
+ get api(base_url, user), params: { order_by: :updated_at, sort: :asc }
+
+ expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id, group_issue.id])
+ end
+
+ context 'issues_statistics' do
+ context 'no state is treated as all state' do
+ let(:params) { {} }
+ let(:counts) { { all: 3, closed: 1, opened: 2 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'statistics when all state is passed' do
+ let(:params) { { state: :all } }
+ let(:counts) { { all: 3, closed: 1, opened: 2 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'closed state is treated as all state' do
+ let(:params) { { state: :closed } }
+ let(:counts) { { all: 3, closed: 1, opened: 2 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'opened state is treated as all state' do
+ let(:params) { { state: :opened } }
+ let(:counts) { { all: 3, closed: 1, opened: 2 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'when filtering by milestone and no state treated as all state' do
+ let(:params) { { milestone: group_milestone.title } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'when filtering by milestone and all state' do
+ let(:params) { { milestone: group_milestone.title, state: :all } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'when filtering by milestone and closed state treated as all state' do
+ let(:params) { { milestone: group_milestone.title, state: :closed } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'when filtering by milestone and opened state treated as all state' do
+ let(:params) { { milestone: group_milestone.title, state: :opened } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+
+ context 'sort does not affect statistics ' do
+ let(:params) { { state: :opened, order_by: 'updated_at' } }
+ let(:counts) { { all: 3, closed: 1, opened: 2 } }
+
+ it_behaves_like 'group issues statistics'
+ end
+ end
+
+ context 'filtering by assignee_username' do
+ let(:another_assignee) { create(:assignee) }
+ let!(:issue1) { create(:issue, author: user2, project: group_project, created_at: 3.days.ago) }
+ let!(:issue2) { create(:issue, author: user2, project: group_project, created_at: 2.days.ago) }
+ let!(:issue3) { create(:issue, author: user2, assignees: [assignee, another_assignee], project: group_project, created_at: 1.day.ago) }
+
+ it 'returns issues with by assignee_username' do
+ get api(base_url, user), params: { assignee_username: [assignee.username], scope: 'all' }
+
+ expect(issue3.reload.assignees.pluck(:id)).to match_array([assignee.id, another_assignee.id])
+ expect_paginated_array_response([issue3.id, group_confidential_issue.id])
+ end
+
+ it 'returns issues by assignee_username as string' do
+ get api(base_url, user), params: { assignee_username: assignee.username, scope: 'all' }
+
+ expect(issue3.reload.assignees.pluck(:id)).to match_array([assignee.id, another_assignee.id])
+ expect_paginated_array_response([issue3.id, group_confidential_issue.id])
+ end
+
+ it 'returns error when multiple assignees are passed' do
+ get api(base_url, user), params: { assignee_username: [assignee.username, another_assignee.username], scope: 'all' }
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response["error"]).to include("allows one value, but found 2")
+ end
+
+ it 'returns error when assignee_username and assignee_id are passed together' do
+ get api(base_url, user), params: { assignee_username: [assignee.username], assignee_id: another_assignee.id, scope: 'all' }
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response["error"]).to include("mutually exclusive")
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/issues/get_project_issues_spec.rb b/spec/requests/api/issues/get_project_issues_spec.rb
new file mode 100644
index 00000000000..0b0f754ab57
--- /dev/null
+++ b/spec/requests/api/issues/get_project_issues_spec.rb
@@ -0,0 +1,807 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe API::Issues do
+ set(:user) { create(:user) }
+ set(:project) do
+ create(:project, :public, creator_id: user.id, namespace: user.namespace)
+ end
+
+ let(:user2) { create(:user) }
+ let(:non_member) { create(:user) }
+ set(:guest) { create(:user) }
+ set(:author) { create(:author) }
+ set(:assignee) { create(:assignee) }
+ let(:admin) { create(:user, :admin) }
+ let(:issue_title) { 'foo' }
+ let(:issue_description) { 'closed' }
+ let!(:closed_issue) do
+ create :closed_issue,
+ author: user,
+ assignees: [user],
+ project: project,
+ state: :closed,
+ milestone: milestone,
+ created_at: generate(:past_time),
+ updated_at: 3.hours.ago,
+ closed_at: 1.hour.ago
+ end
+ let!(:confidential_issue) do
+ create :issue,
+ :confidential,
+ project: project,
+ author: author,
+ assignees: [assignee],
+ created_at: generate(:past_time),
+ updated_at: 2.hours.ago
+ end
+ let!(:issue) do
+ create :issue,
+ author: user,
+ assignees: [user],
+ project: project,
+ milestone: milestone,
+ created_at: generate(:past_time),
+ updated_at: 1.hour.ago,
+ title: issue_title,
+ description: issue_description
+ end
+ set(:label) do
+ create(:label, title: 'label', color: '#FFAABB', project: project)
+ end
+ let!(:label_link) { create(:label_link, label: label, target: issue) }
+ let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
+ set(:empty_milestone) do
+ create(:milestone, title: '2.0.0', project: project)
+ end
+ let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) }
+
+ let(:no_milestone_title) { 'None' }
+ let(:any_milestone_title) { 'Any' }
+
+ before(:all) do
+ project.add_reporter(user)
+ project.add_guest(guest)
+ end
+
+ before do
+ stub_licensed_features(multiple_issue_assignees: false, issue_weights: false)
+ end
+
+ shared_examples 'project issues statistics' do
+ it 'returns project issues statistics' do
+ get api("/issues_statistics", user), params: params
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['statistics']).not_to be_nil
+ expect(json_response['statistics']['counts']['all']).to eq counts[:all]
+ expect(json_response['statistics']['counts']['closed']).to eq counts[:closed]
+ expect(json_response['statistics']['counts']['opened']).to eq counts[:opened]
+ end
+ end
+
+ describe "GET /projects/:id/issues" do
+ let(:base_url) { "/projects/#{project.id}" }
+
+ context 'when unauthenticated' do
+ it 'returns public project issues' do
+ get api("/projects/#{project.id}/issues")
+
+ expect_paginated_array_response([issue.id, closed_issue.id])
+ end
+
+ context 'issues_statistics' do
+ context 'no state is treated as all state' do
+ let(:params) { {} }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'project issues statistics'
+ end
+
+ context 'statistics when all state is passed' do
+ let(:params) { { state: :all } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'project issues statistics'
+ end
+
+ context 'closed state is treated as all state' do
+ let(:params) { { state: :closed } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'project issues statistics'
+ end
+
+ context 'opened state is treated as all state' do
+ let(:params) { { state: :opened } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'project issues statistics'
+ end
+
+ context 'when filtering by milestone and no state treated as all state' do
+ let(:params) { { milestone: milestone.title } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'project issues statistics'
+ end
+
+ context 'when filtering by milestone and all state' do
+ let(:params) { { milestone: milestone.title, state: :all } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'project issues statistics'
+ end
+
+ context 'when filtering by milestone and closed state treated as all state' do
+ let(:params) { { milestone: milestone.title, state: :closed } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'project issues statistics'
+ end
+
+ context 'when filtering by milestone and opened state treated as all state' do
+ let(:params) { { milestone: milestone.title, state: :opened } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'project issues statistics'
+ end
+
+ context 'sort does not affect statistics ' do
+ let(:params) { { state: :opened, order_by: 'updated_at' } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'project issues statistics'
+ end
+ end
+ end
+
+ it 'avoids N+1 queries' do
+ get api("/projects/#{project.id}/issues", user)
+
+ create_list(:issue, 3, project: project)
+
+ control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ get api("/projects/#{project.id}/issues", user)
+ end.count
+
+ expect do
+ get api("/projects/#{project.id}/issues", user)
+ end.not_to exceed_all_query_limit(control_count)
+ end
+
+ it 'returns 404 when project does not exist' do
+ max_project_id = Project.maximum(:id).to_i
+
+ get api("/projects/#{max_project_id + 1}/issues", non_member)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'returns 404 on private projects for other users' do
+ private_project = create(:project, :private)
+ create(:issue, project: private_project)
+
+ get api("/projects/#{private_project.id}/issues", non_member)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'returns no issues when user has access to project but not issues' do
+ restricted_project = create(:project, :public, :issues_private)
+ create(:issue, project: restricted_project)
+
+ get api("/projects/#{restricted_project.id}/issues", non_member)
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns project issues without confidential issues for non project members' do
+ get api("#{base_url}/issues", non_member)
+
+ expect_paginated_array_response([issue.id, closed_issue.id])
+ end
+
+ it 'returns project issues without confidential issues for project members with guest role' do
+ get api("#{base_url}/issues", guest)
+
+ expect_paginated_array_response([issue.id, closed_issue.id])
+ end
+
+ it 'returns project confidential issues for author' do
+ get api("#{base_url}/issues", author)
+
+ expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
+ end
+
+ it 'returns only confidential issues' do
+ get api("#{base_url}/issues", author), params: { confidential: true }
+
+ expect_paginated_array_response(confidential_issue.id)
+ end
+
+ it 'returns only public issues' do
+ get api("#{base_url}/issues", author), params: { confidential: false }
+
+ expect_paginated_array_response([issue.id, closed_issue.id])
+ end
+
+ it 'returns project confidential issues for assignee' do
+ get api("#{base_url}/issues", assignee)
+
+ expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
+ end
+
+ it 'returns project issues with confidential issues for project members' do
+ get api("#{base_url}/issues", user)
+
+ expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
+ end
+
+ it 'returns project confidential issues for admin' do
+ get api("#{base_url}/issues", admin)
+
+ expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
+ end
+
+ it 'returns an array of labeled project issues' do
+ get api("#{base_url}/issues", user), params: { labels: label.title }
+
+ expect_paginated_array_response(issue.id)
+ end
+
+ it 'returns an array of labeled project issues with labels param as array' do
+ get api("#{base_url}/issues", user), params: { labels: [label.title] }
+
+ expect_paginated_array_response(issue.id)
+ end
+
+ context 'with labeled issues' do
+ let(:label_b) { create(:label, title: 'foo', project: project) }
+ let(:label_c) { create(:label, title: 'bar', project: project) }
+
+ before do
+ create(:label_link, label: label_b, target: issue)
+ create(:label_link, label: label_c, target: issue)
+
+ get api('/issues', user), params: params
+ end
+
+ it_behaves_like 'labeled issues with labels and label_name params'
+ end
+
+ it 'returns issues matching given search string for title' do
+ get api("#{base_url}/issues?search=#{issue.title}", user)
+
+ expect_paginated_array_response(issue.id)
+ end
+
+ it 'returns issues matching given search string for description' do
+ get api("#{base_url}/issues?search=#{issue.description}", user)
+
+ expect_paginated_array_response(issue.id)
+ end
+
+ it 'returns an array of issues found by iids' do
+ get api("#{base_url}/issues", user), params: { iids: [issue.iid] }
+
+ expect_paginated_array_response(issue.id)
+ end
+
+ it 'returns an empty array if iid does not exist' do
+ get api("#{base_url}/issues", user), params: { iids: [0] }
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an empty array if not all labels matches' do
+ get api("#{base_url}/issues?labels=#{label.title},foo", user)
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an array of project issues with any label' do
+ get api("#{base_url}/issues", user), params: { labels: IssuesFinder::FILTER_ANY }
+
+ expect_paginated_array_response(issue.id)
+ end
+
+ it 'returns an array of project issues with any label with labels param as array' do
+ get api("#{base_url}/issues", user), params: { labels: [IssuesFinder::FILTER_ANY] }
+
+ expect_paginated_array_response(issue.id)
+ end
+
+ it 'returns an array of project issues with no label' do
+ get api("#{base_url}/issues", user), params: { labels: IssuesFinder::FILTER_NONE }
+
+ expect_paginated_array_response([confidential_issue.id, closed_issue.id])
+ end
+
+ it 'returns an array of project issues with no label with labels param as array' do
+ get api("#{base_url}/issues", user), params: { labels: [IssuesFinder::FILTER_NONE] }
+
+ expect_paginated_array_response([confidential_issue.id, closed_issue.id])
+ end
+
+ it 'returns an empty array if no project issue matches labels' do
+ get api("#{base_url}/issues", user), params: { labels: 'foo,bar' }
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an empty array if no issue matches milestone' do
+ get api("#{base_url}/issues", user), params: { milestone: empty_milestone.title }
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an empty array if milestone does not exist' do
+ get api("#{base_url}/issues", user), params: { milestone: :foo }
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an array of issues in given milestone' do
+ get api("#{base_url}/issues", user), params: { milestone: milestone.title }
+
+ expect_paginated_array_response([issue.id, closed_issue.id])
+ end
+
+ it 'returns an array of issues matching state in milestone' do
+ get api("#{base_url}/issues", user), params: { milestone: milestone.title, state: :closed }
+
+ expect_paginated_array_response(closed_issue.id)
+ end
+
+ it 'returns an array of issues with no milestone' do
+ get api("#{base_url}/issues", user), params: { milestone: no_milestone_title }
+
+ expect_paginated_array_response(confidential_issue.id)
+ end
+
+ it 'returns an array of issues with any milestone' do
+ get api("#{base_url}/issues", user), params: { milestone: any_milestone_title }
+
+ expect_paginated_array_response([issue.id, closed_issue.id])
+ end
+
+ context 'without sort params' do
+ it 'sorts by created_at descending by default' do
+ get api("#{base_url}/issues", user)
+
+ expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
+ end
+
+ context 'with 2 issues with same created_at' do
+ let!(:closed_issue2) do
+ create :closed_issue,
+ author: user,
+ assignees: [user],
+ project: project,
+ milestone: milestone,
+ created_at: closed_issue.created_at,
+ updated_at: 1.hour.ago,
+ title: issue_title,
+ description: issue_description
+ end
+
+ it 'page breaks first page correctly' do
+ get api("#{base_url}/issues?per_page=3", user)
+
+ expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue2.id])
+ end
+
+ it 'page breaks second page correctly' do
+ get api("#{base_url}/issues?per_page=3&page=2", user)
+
+ expect_paginated_array_response([closed_issue.id])
+ end
+ end
+ end
+
+ it 'sorts ascending when requested' do
+ get api("#{base_url}/issues", user), params: { sort: :asc }
+
+ expect_paginated_array_response([closed_issue.id, confidential_issue.id, issue.id])
+ end
+
+ it 'sorts by updated_at descending when requested' do
+ get api("#{base_url}/issues", user), params: { order_by: :updated_at }
+
+ issue.touch(:updated_at)
+
+ expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
+ end
+
+ it 'sorts by updated_at ascending when requested' do
+ get api("#{base_url}/issues", user), params: { order_by: :updated_at, sort: :asc }
+
+ expect_paginated_array_response([closed_issue.id, confidential_issue.id, issue.id])
+ end
+
+ context 'issues_statistics' do
+ context 'no state is treated as all state' do
+ let(:params) { {} }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'project issues statistics'
+ end
+
+ context 'statistics when all state is passed' do
+ let(:params) { { state: :all } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'project issues statistics'
+ end
+
+ context 'closed state is treated as all state' do
+ let(:params) { { state: :closed } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'project issues statistics'
+ end
+
+ context 'opened state is treated as all state' do
+ let(:params) { { state: :opened } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'project issues statistics'
+ end
+
+ context 'when filtering by milestone and no state treated as all state' do
+ let(:params) { { milestone: milestone.title } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'project issues statistics'
+ end
+
+ context 'when filtering by milestone and all state' do
+ let(:params) { { milestone: milestone.title, state: :all } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'project issues statistics'
+ end
+
+ context 'when filtering by milestone and closed state treated as all state' do
+ let(:params) { { milestone: milestone.title, state: :closed } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'project issues statistics'
+ end
+
+ context 'when filtering by milestone and opened state treated as all state' do
+ let(:params) { { milestone: milestone.title, state: :opened } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'project issues statistics'
+ end
+
+ context 'sort does not affect statistics ' do
+ let(:params) { { state: :opened, order_by: 'updated_at' } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'project issues statistics'
+ end
+ end
+
+ context 'filtering by assignee_username' do
+ let(:another_assignee) { create(:assignee) }
+ let!(:issue1) { create(:issue, author: user2, project: project, created_at: 3.days.ago) }
+ let!(:issue2) { create(:issue, author: user2, project: project, created_at: 2.days.ago) }
+ let!(:issue3) { create(:issue, author: user2, assignees: [assignee, another_assignee], project: project, created_at: 1.day.ago) }
+
+ it 'returns issues by assignee_username' do
+ get api("/issues", user), params: { assignee_username: [assignee.username], scope: 'all' }
+
+ expect(issue3.reload.assignees.pluck(:id)).to match_array([assignee.id, another_assignee.id])
+ expect_paginated_array_response([confidential_issue.id, issue3.id])
+ end
+
+ it 'returns issues by assignee_username as string' do
+ get api("/issues", user), params: { assignee_username: assignee.username, scope: 'all' }
+
+ expect(issue3.reload.assignees.pluck(:id)).to match_array([assignee.id, another_assignee.id])
+ expect_paginated_array_response([confidential_issue.id, issue3.id])
+ end
+
+ it 'returns error when multiple assignees are passed' do
+ get api("/issues", user), params: { assignee_username: [assignee.username, another_assignee.username], scope: 'all' }
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response["error"]).to include("allows one value, but found 2")
+ end
+
+ it 'returns error when assignee_username and assignee_id are passed together' do
+ get api("/issues", user), params: { assignee_username: [assignee.username], assignee_id: another_assignee.id, scope: 'all' }
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response["error"]).to include("mutually exclusive")
+ end
+ end
+ end
+
+ describe 'GET /projects/:id/issues/:issue_iid' do
+ context 'when unauthenticated' do
+ it 'returns public issues' do
+ get api("/projects/#{project.id}/issues/#{issue.iid}")
+
+ expect(response).to have_gitlab_http_status(200)
+ end
+ end
+
+ it 'exposes known attributes' do
+ get api("/projects/#{project.id}/issues/#{issue.iid}", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['id']).to eq(issue.id)
+ expect(json_response['iid']).to eq(issue.iid)
+ expect(json_response['project_id']).to eq(issue.project.id)
+ expect(json_response['title']).to eq(issue.title)
+ expect(json_response['description']).to eq(issue.description)
+ expect(json_response['state']).to eq(issue.state)
+ expect(json_response['closed_at']).to be_falsy
+ expect(json_response['created_at']).to be_present
+ expect(json_response['updated_at']).to be_present
+ expect(json_response['labels']).to eq(issue.label_names)
+ expect(json_response['milestone']).to be_a Hash
+ expect(json_response['assignees']).to be_a Array
+ expect(json_response['assignee']).to be_a Hash
+ expect(json_response['author']).to be_a Hash
+ expect(json_response['confidential']).to be_falsy
+ end
+
+ it 'exposes the closed_at attribute' do
+ get api("/projects/#{project.id}/issues/#{closed_issue.iid}", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['closed_at']).to be_present
+ end
+
+ context 'links exposure' do
+ it 'exposes related resources full URIs' do
+ get api("/projects/#{project.id}/issues/#{issue.iid}", user)
+
+ links = json_response['_links']
+
+ expect(links['self']).to end_with("/api/v4/projects/#{project.id}/issues/#{issue.iid}")
+ expect(links['notes']).to end_with("/api/v4/projects/#{project.id}/issues/#{issue.iid}/notes")
+ expect(links['award_emoji']).to end_with("/api/v4/projects/#{project.id}/issues/#{issue.iid}/award_emoji")
+ expect(links['project']).to end_with("/api/v4/projects/#{project.id}")
+ end
+ end
+
+ it 'returns a project issue by internal id' do
+ get api("/projects/#{project.id}/issues/#{issue.iid}", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['title']).to eq(issue.title)
+ expect(json_response['iid']).to eq(issue.iid)
+ end
+
+ it 'returns 404 if issue id not found' do
+ get api("/projects/#{project.id}/issues/54321", user)
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'returns 404 if the issue ID is used' do
+ get api("/projects/#{project.id}/issues/#{issue.id}", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ context 'confidential issues' do
+ it 'returns 404 for non project members' do
+ get api("/projects/#{project.id}/issues/#{confidential_issue.iid}", non_member)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'returns 404 for project members with guest role' do
+ get api("/projects/#{project.id}/issues/#{confidential_issue.iid}", guest)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'returns confidential issue for project members' do
+ get api("/projects/#{project.id}/issues/#{confidential_issue.iid}", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['title']).to eq(confidential_issue.title)
+ expect(json_response['iid']).to eq(confidential_issue.iid)
+ end
+
+ it 'returns confidential issue for author' do
+ get api("/projects/#{project.id}/issues/#{confidential_issue.iid}", author)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['title']).to eq(confidential_issue.title)
+ expect(json_response['iid']).to eq(confidential_issue.iid)
+ end
+
+ it 'returns confidential issue for assignee' do
+ get api("/projects/#{project.id}/issues/#{confidential_issue.iid}", assignee)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['title']).to eq(confidential_issue.title)
+ expect(json_response['iid']).to eq(confidential_issue.iid)
+ end
+
+ it 'returns confidential issue for admin' do
+ get api("/projects/#{project.id}/issues/#{confidential_issue.iid}", admin)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['title']).to eq(confidential_issue.title)
+ expect(json_response['iid']).to eq(confidential_issue.iid)
+ end
+ end
+ end
+
+ describe 'GET :id/issues/:issue_iid/closed_by' do
+ let(:merge_request) do
+ create(:merge_request,
+ :simple,
+ author: user,
+ source_project: project,
+ target_project: project,
+ description: "closes #{issue.to_reference}")
+ end
+
+ before do
+ create(:merge_requests_closing_issues, issue: issue, merge_request: merge_request)
+ end
+
+ context 'when unauthenticated' do
+ it 'return public project issues' do
+ get api("/projects/#{project.id}/issues/#{issue.iid}/closed_by")
+
+ expect_paginated_array_response(merge_request.id)
+ end
+ end
+
+ it 'returns merge requests that will close issue on merge' do
+ get api("/projects/#{project.id}/issues/#{issue.iid}/closed_by", user)
+
+ expect_paginated_array_response(merge_request.id)
+ end
+
+ context 'when no merge requests will close issue' do
+ it 'returns empty array' do
+ get api("/projects/#{project.id}/issues/#{closed_issue.iid}/closed_by", user)
+
+ expect_paginated_array_response([])
+ end
+ end
+
+ it "returns 404 when issue doesn't exists" do
+ get api("/projects/#{project.id}/issues/0/closed_by", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ describe 'GET :id/issues/:issue_iid/related_merge_requests' do
+ def get_related_merge_requests(project_id, issue_iid, user = nil)
+ get api("/projects/#{project_id}/issues/#{issue_iid}/related_merge_requests", user)
+ end
+
+ def create_referencing_mr(user, project, issue)
+ attributes = {
+ author: user,
+ source_project: project,
+ target_project: project,
+ source_branch: 'master',
+ target_branch: 'test',
+ description: "See #{issue.to_reference}"
+ }
+ create(:merge_request, attributes).tap do |merge_request|
+ create(:note, :system, project: issue.project, noteable: issue, author: user, note: merge_request.to_reference(full: true))
+ end
+ end
+
+ let!(:related_mr) { create_referencing_mr(user, project, issue) }
+
+ context 'when unauthenticated' do
+ it 'return list of referenced merge requests from issue' do
+ get_related_merge_requests(project.id, issue.iid)
+
+ expect_paginated_array_response(related_mr.id)
+ end
+
+ it 'renders 404 if project is not visible' do
+ private_project = create(:project, :private)
+ private_issue = create(:issue, project: private_project)
+ create_referencing_mr(user, private_project, private_issue)
+
+ get_related_merge_requests(private_project.id, private_issue.iid)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ it 'returns merge requests that mentioned a issue' do
+ create(:merge_request,
+ :simple,
+ author: user,
+ source_project: project,
+ target_project: project,
+ description: 'Some description')
+
+ get_related_merge_requests(project.id, issue.iid, user)
+
+ expect_paginated_array_response(related_mr.id)
+ end
+
+ it 'returns merge requests cross-project wide' do
+ project2 = create(:project, :public, creator_id: user.id, namespace: user.namespace)
+ merge_request = create_referencing_mr(user, project2, issue)
+
+ get_related_merge_requests(project.id, issue.iid, user)
+
+ expect_paginated_array_response([related_mr.id, merge_request.id])
+ end
+
+ it 'does not generate references to projects with no access' do
+ private_project = create(:project, :private)
+ create_referencing_mr(private_project.creator, private_project, issue)
+
+ get_related_merge_requests(project.id, issue.iid, user)
+
+ expect_paginated_array_response(related_mr.id)
+ end
+
+ context 'no merge request mentioned a issue' do
+ it 'returns empty array' do
+ get_related_merge_requests(project.id, closed_issue.iid, user)
+
+ expect_paginated_array_response([])
+ end
+ end
+
+ it "returns 404 when issue doesn't exists" do
+ get_related_merge_requests(project.id, 0, user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ describe 'GET /projects/:id/issues/:issue_iid/user_agent_detail' do
+ let!(:user_agent_detail) { create(:user_agent_detail, subject: issue) }
+
+ context 'when unauthenticated' do
+ it 'returns unauthorized' do
+ get api("/projects/#{project.id}/issues/#{issue.iid}/user_agent_detail")
+
+ expect(response).to have_gitlab_http_status(401)
+ end
+ end
+
+ it 'exposes known attributes' do
+ get api("/projects/#{project.id}/issues/#{issue.iid}/user_agent_detail", admin)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['user_agent']).to eq(user_agent_detail.user_agent)
+ expect(json_response['ip_address']).to eq(user_agent_detail.ip_address)
+ expect(json_response['akismet_submitted']).to eq(user_agent_detail.submitted)
+ end
+
+ it 'returns unauthorized for non-admin users' do
+ get api("/projects/#{project.id}/issues/#{issue.iid}/user_agent_detail", user)
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+ end
+
+ describe 'GET projects/:id/issues/:issue_iid/participants' do
+ it_behaves_like 'issuable participants endpoint' do
+ let(:entity) { issue }
+ end
+
+ it 'returns 404 if the issue is confidential' do
+ post api("/projects/#{project.id}/issues/#{confidential_issue.iid}/participants", non_member)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+end
diff --git a/spec/requests/api/issues/issues_spec.rb b/spec/requests/api/issues/issues_spec.rb
new file mode 100644
index 00000000000..f32ffd1c77b
--- /dev/null
+++ b/spec/requests/api/issues/issues_spec.rb
@@ -0,0 +1,776 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe API::Issues do
+ set(:user) { create(:user) }
+ set(:project) do
+ create(:project, :public, creator_id: user.id, namespace: user.namespace)
+ end
+
+ let(:user2) { create(:user) }
+ let(:non_member) { create(:user) }
+ set(:guest) { create(:user) }
+ set(:author) { create(:author) }
+ set(:assignee) { create(:assignee) }
+ let(:admin) { create(:user, :admin) }
+ let(:issue_title) { 'foo' }
+ let(:issue_description) { 'closed' }
+ let!(:closed_issue) do
+ create :closed_issue,
+ author: user,
+ assignees: [user],
+ project: project,
+ state: :closed,
+ milestone: milestone,
+ created_at: generate(:past_time),
+ updated_at: 3.hours.ago,
+ closed_at: 1.hour.ago
+ end
+ let!(:confidential_issue) do
+ create :issue,
+ :confidential,
+ project: project,
+ author: author,
+ assignees: [assignee],
+ created_at: generate(:past_time),
+ updated_at: 2.hours.ago
+ end
+ let!(:issue) do
+ create :issue,
+ author: user,
+ assignees: [user],
+ project: project,
+ milestone: milestone,
+ created_at: generate(:past_time),
+ updated_at: 1.hour.ago,
+ title: issue_title,
+ description: issue_description
+ end
+ set(:label) do
+ create(:label, title: 'label', color: '#FFAABB', project: project)
+ end
+ let!(:label_link) { create(:label_link, label: label, target: issue) }
+ let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
+ set(:empty_milestone) do
+ create(:milestone, title: '2.0.0', project: project)
+ end
+ let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) }
+
+ let(:no_milestone_title) { 'None' }
+ let(:any_milestone_title) { 'Any' }
+
+ before(:all) do
+ project.add_reporter(user)
+ project.add_guest(guest)
+ end
+
+ before do
+ stub_licensed_features(multiple_issue_assignees: false, issue_weights: false)
+ end
+
+ shared_examples 'issues statistics' do
+ it 'returns issues statistics' do
+ get api("/issues_statistics", user), params: params
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['statistics']).not_to be_nil
+ expect(json_response['statistics']['counts']['all']).to eq counts[:all]
+ expect(json_response['statistics']['counts']['closed']).to eq counts[:closed]
+ expect(json_response['statistics']['counts']['opened']).to eq counts[:opened]
+ end
+ end
+
+ describe 'GET /issues' do
+ context 'when unauthenticated' do
+ it 'returns an array of all issues' do
+ get api('/issues'), params: { scope: 'all' }
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_an Array
+ end
+
+ it 'returns authentication error without any scope' do
+ get api('/issues')
+
+ expect(response).to have_http_status(401)
+ end
+
+ it 'returns authentication error when scope is assigned-to-me' do
+ get api('/issues'), params: { scope: 'assigned-to-me' }
+
+ expect(response).to have_http_status(401)
+ end
+
+ it 'returns authentication error when scope is created-by-me' do
+ get api('/issues'), params: { scope: 'created-by-me' }
+
+ expect(response).to have_http_status(401)
+ end
+
+ it 'returns an array of issues matching state in milestone' do
+ get api('/issues'), params: { milestone: 'foo', scope: 'all' }
+
+ expect(response).to have_http_status(200)
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an array of issues matching state in milestone' do
+ get api('/issues'), params: { milestone: milestone.title, scope: 'all' }
+
+ expect(response).to have_http_status(200)
+ expect_paginated_array_response([issue.id, closed_issue.id])
+ end
+
+ context 'issues_statistics' do
+ it 'returns authentication error without any scope' do
+ get api('/issues_statistics')
+
+ expect(response).to have_http_status(401)
+ end
+
+ it 'returns authentication error when scope is assigned_to_me' do
+ get api('/issues_statistics'), params: { scope: 'assigned_to_me' }
+
+ expect(response).to have_http_status(401)
+ end
+
+ it 'returns authentication error when scope is created_by_me' do
+ get api('/issues_statistics'), params: { scope: 'created_by_me' }
+
+ expect(response).to have_http_status(401)
+ end
+
+ context 'no state is treated as all state' do
+ let(:params) { {} }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'issues statistics'
+ end
+
+ context 'statistics when all state is passed' do
+ let(:params) { { state: :all } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'issues statistics'
+ end
+
+ context 'closed state is treated as all state' do
+ let(:params) { { state: :closed } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'issues statistics'
+ end
+
+ context 'opened state is treated as all state' do
+ let(:params) { { state: :opened } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'issues statistics'
+ end
+
+ context 'when filtering by milestone and no state treated as all state' do
+ let(:params) { { milestone: milestone.title } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'issues statistics'
+ end
+
+ context 'when filtering by milestone and all state' do
+ let(:params) { { milestone: milestone.title, state: :all } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'issues statistics'
+ end
+
+ context 'when filtering by milestone and closed state treated as all state' do
+ let(:params) { { milestone: milestone.title, state: :closed } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'issues statistics'
+ end
+
+ context 'when filtering by milestone and opened state treated as all state' do
+ let(:params) { { milestone: milestone.title, state: :opened } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'issues statistics'
+ end
+
+ context 'sort does not affect statistics ' do
+ let(:params) { { state: :opened, order_by: 'updated_at' } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'issues statistics'
+ end
+ end
+ end
+
+ context 'when authenticated' do
+ it 'returns an array of issues' do
+ get api('/issues', user)
+
+ expect_paginated_array_response([issue.id, closed_issue.id])
+ expect(json_response.first['title']).to eq(issue.title)
+ expect(json_response.last).to have_key('web_url')
+ end
+
+ it 'returns an array of closed issues' do
+ get api('/issues', user), params: { state: :closed }
+
+ expect_paginated_array_response(closed_issue.id)
+ end
+
+ it 'returns an array of opened issues' do
+ get api('/issues', user), params: { state: :opened }
+
+ expect_paginated_array_response(issue.id)
+ end
+
+ it 'returns an array of all issues' do
+ get api('/issues', user), params: { state: :all }
+
+ expect_paginated_array_response([issue.id, closed_issue.id])
+ end
+
+ it 'returns issues assigned to me' do
+ issue2 = create(:issue, assignees: [user2], project: project)
+
+ get api('/issues', user2), params: { scope: 'assigned_to_me' }
+
+ expect_paginated_array_response(issue2.id)
+ end
+
+ it 'returns issues assigned to me (kebab-case)' do
+ issue2 = create(:issue, assignees: [user2], project: project)
+
+ get api('/issues', user2), params: { scope: 'assigned-to-me' }
+
+ expect_paginated_array_response(issue2.id)
+ end
+
+ it 'returns issues authored by the given author id' do
+ issue2 = create(:issue, author: user2, project: project)
+
+ get api('/issues', user), params: { author_id: user2.id, scope: 'all' }
+
+ expect_paginated_array_response(issue2.id)
+ end
+
+ it 'returns issues assigned to the given assignee id' do
+ issue2 = create(:issue, assignees: [user2], project: project)
+
+ get api('/issues', user), params: { assignee_id: user2.id, scope: 'all' }
+
+ expect_paginated_array_response(issue2.id)
+ end
+
+ it 'returns issues authored by the given author id and assigned to the given assignee id' do
+ issue2 = create(:issue, author: user2, assignees: [user2], project: project)
+
+ get api('/issues', user), params: { author_id: user2.id, assignee_id: user2.id, scope: 'all' }
+
+ expect_paginated_array_response(issue2.id)
+ end
+
+ it 'returns issues with no assignee' do
+ issue2 = create(:issue, author: user2, project: project)
+
+ get api('/issues', user), params: { assignee_id: 'None', scope: 'all' }
+
+ expect_paginated_array_response(issue2.id)
+ end
+
+ it 'returns issues with any assignee' do
+ # This issue without assignee should not be returned
+ create(:issue, author: user2, project: project)
+
+ get api('/issues', user), params: { assignee_id: 'Any', scope: 'all' }
+
+ expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
+ end
+
+ it 'returns only confidential issues' do
+ get api('/issues', user), params: { confidential: true, scope: 'all' }
+
+ expect_paginated_array_response(confidential_issue.id)
+ end
+
+ it 'returns only public issues' do
+ get api('/issues', user), params: { confidential: false }
+
+ expect_paginated_array_response([issue.id, closed_issue.id])
+ end
+
+ it 'returns issues reacted by the authenticated user' do
+ issue2 = create(:issue, project: project, author: user, assignees: [user])
+ create(:award_emoji, awardable: issue2, user: user2, name: 'star')
+ create(:award_emoji, awardable: issue, user: user2, name: 'thumbsup')
+
+ get api('/issues', user2), params: { my_reaction_emoji: 'Any', scope: 'all' }
+
+ expect_paginated_array_response([issue2.id, issue.id])
+ end
+
+ it 'returns issues not reacted by the authenticated user' do
+ issue2 = create(:issue, project: project, author: user, assignees: [user])
+ create(:award_emoji, awardable: issue2, user: user2, name: 'star')
+
+ get api('/issues', user2), params: { my_reaction_emoji: 'None', scope: 'all' }
+
+ expect_paginated_array_response([issue.id, closed_issue.id])
+ end
+
+ it 'returns issues matching given search string for title' do
+ get api('/issues', user), params: { search: issue.title }
+
+ expect_paginated_array_response(issue.id)
+ end
+
+ it 'returns issues matching given search string for title and scoped in title' do
+ get api('/issues', user), params: { search: issue.title, in: 'title' }
+
+ expect_paginated_array_response(issue.id)
+ end
+
+ it 'returns an empty array if no issue matches given search string for title and scoped in description' do
+ get api('/issues', user), params: { search: issue.title, in: 'description' }
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns issues matching given search string for description' do
+ get api('/issues', user), params: { search: issue.description }
+
+ expect_paginated_array_response(issue.id)
+ end
+
+ context 'filtering before a specific date' do
+ let!(:issue2) { create(:issue, project: project, author: user, created_at: Date.new(2000, 1, 1), updated_at: Date.new(2000, 1, 1)) }
+
+ it 'returns issues created before a specific date' do
+ get api('/issues?created_before=2000-01-02T00:00:00.060Z', user)
+
+ expect_paginated_array_response(issue2.id)
+ end
+
+ it 'returns issues updated before a specific date' do
+ get api('/issues?updated_before=2000-01-02T00:00:00.060Z', user)
+
+ expect_paginated_array_response(issue2.id)
+ end
+ end
+
+ context 'filtering after a specific date' do
+ let!(:issue2) { create(:issue, project: project, author: user, created_at: 1.week.from_now, updated_at: 1.week.from_now) }
+
+ it 'returns issues created after a specific date' do
+ get api("/issues?created_after=#{issue2.created_at}", user)
+
+ expect_paginated_array_response(issue2.id)
+ end
+
+ it 'returns issues updated after a specific date' do
+ get api("/issues?updated_after=#{issue2.updated_at}", user)
+
+ expect_paginated_array_response(issue2.id)
+ end
+ end
+
+ context 'filter by labels or label_name param' do
+ context 'N+1' do
+ let(:label_b) { create(:label, title: 'foo', project: project) }
+ let(:label_c) { create(:label, title: 'bar', project: project) }
+
+ before do
+ create(:label_link, label: label_b, target: issue)
+ create(:label_link, label: label_c, target: issue)
+ end
+ it 'tests N+1' do
+ control = ActiveRecord::QueryRecorder.new do
+ get api('/issues', user), params: { labels: [label.title, label_b.title, label_c.title] }
+ end
+
+ label_d = create(:label, title: 'dar', project: project)
+ label_e = create(:label, title: 'ear', project: project)
+ create(:label_link, label: label_d, target: issue)
+ create(:label_link, label: label_e, target: issue)
+
+ expect do
+ get api('/issues', user), params: { labels: [label.title, label_b.title, label_c.title] }
+ end.not_to exceed_query_limit(control)
+ expect(issue.labels.count).to eq(5)
+ end
+ end
+
+ it 'returns an array of labeled issues' do
+ get api('/issues', user), params: { labels: label.title }
+
+ expect_paginated_array_response(issue.id)
+ expect(json_response.first['labels']).to eq([label.title])
+ end
+
+ it 'returns an array of labeled issues with labels param as array' do
+ get api('/issues', user), params: { labels: [label.title] }
+
+ expect_paginated_array_response(issue.id)
+ expect(json_response.first['labels']).to eq([label.title])
+ end
+
+ context 'with labeled issues' do
+ let(:label_b) { create(:label, title: 'foo', project: project) }
+ let(:label_c) { create(:label, title: 'bar', project: project) }
+
+ before do
+ create(:label_link, label: label_b, target: issue)
+ create(:label_link, label: label_c, target: issue)
+
+ get api('/issues', user), params: params
+ end
+
+ it_behaves_like 'labeled issues with labels and label_name params'
+ end
+
+ it 'returns an empty array if no issue matches labels' do
+ get api('/issues', user), params: { labels: 'foo,bar' }
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an empty array if no issue matches labels with labels param as array' do
+ get api('/issues', user), params: { labels: %w(foo bar) }
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an array of labeled issues matching given state' do
+ get api('/issues', user), params: { labels: label.title, state: :opened }
+
+ expect_paginated_array_response(issue.id)
+ expect(json_response.first['labels']).to eq([label.title])
+ expect(json_response.first['state']).to eq('opened')
+ end
+
+ it 'returns an array of labeled issues matching given state with labels param as array' do
+ get api('/issues', user), params: { labels: [label.title], state: :opened }
+
+ expect_paginated_array_response(issue.id)
+ expect(json_response.first['labels']).to eq([label.title])
+ expect(json_response.first['state']).to eq('opened')
+ end
+
+ it 'returns an empty array if no issue matches labels and state filters' do
+ get api('/issues', user), params: { labels: label.title, state: :closed }
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an array of issues with any label' do
+ get api('/issues', user), params: { labels: IssuesFinder::FILTER_ANY }
+
+ expect_paginated_array_response(issue.id)
+ end
+
+ it 'returns an array of issues with any label with labels param as array' do
+ get api('/issues', user), params: { labels: [IssuesFinder::FILTER_ANY] }
+
+ expect_paginated_array_response(issue.id)
+ end
+
+ it 'returns an array of issues with no label' do
+ get api('/issues', user), params: { labels: IssuesFinder::FILTER_NONE }
+
+ expect_paginated_array_response(closed_issue.id)
+ end
+
+ it 'returns an array of issues with no label with labels param as array' do
+ get api('/issues', user), params: { labels: [IssuesFinder::FILTER_NONE] }
+
+ expect_paginated_array_response(closed_issue.id)
+ end
+ end
+
+ it 'returns an empty array if no issue matches milestone' do
+ get api("/issues?milestone=#{empty_milestone.title}", user)
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an empty array if milestone does not exist' do
+ get api('/issues?milestone=foo', user)
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an array of issues in given milestone' do
+ get api("/issues?milestone=#{milestone.title}", user)
+
+ expect_paginated_array_response([issue.id, closed_issue.id])
+ end
+
+ it 'returns an array of issues in given milestone_title param' do
+ get api("/issues?milestone_title=#{milestone.title}", user)
+
+ expect_paginated_array_response([issue.id, closed_issue.id])
+ end
+
+ it 'returns an array of issues matching state in milestone' do
+ get api("/issues?milestone=#{milestone.title}&state=closed", user)
+
+ expect_paginated_array_response(closed_issue.id)
+ end
+
+ it 'returns an array of issues with no milestone' do
+ get api("/issues?milestone=#{no_milestone_title}", author)
+
+ expect_paginated_array_response(confidential_issue.id)
+ end
+
+ it 'returns an array of issues with no milestone using milestone_title param' do
+ get api("/issues?milestone_title=#{no_milestone_title}", author)
+
+ expect_paginated_array_response(confidential_issue.id)
+ end
+
+ it 'returns an array of issues found by iids' do
+ get api('/issues', user), params: { iids: [closed_issue.iid] }
+
+ expect_paginated_array_response(closed_issue.id)
+ end
+
+ it 'returns an empty array if iid does not exist' do
+ get api('/issues', user), params: { iids: [0] }
+
+ expect_paginated_array_response([])
+ end
+
+ context 'without sort params' do
+ it 'sorts by created_at descending by default' do
+ get api('/issues', user)
+
+ expect_paginated_array_response([issue.id, closed_issue.id])
+ end
+
+ context 'with 2 issues with same created_at' do
+ let!(:closed_issue2) do
+ create :closed_issue,
+ author: user,
+ assignees: [user],
+ project: project,
+ milestone: milestone,
+ created_at: closed_issue.created_at,
+ updated_at: 1.hour.ago,
+ title: issue_title,
+ description: issue_description
+ end
+
+ it 'page breaks first page correctly' do
+ get api('/issues?per_page=2', user)
+
+ expect_paginated_array_response([issue.id, closed_issue2.id])
+ end
+
+ it 'page breaks second page correctly' do
+ get api('/issues?per_page=2&page=2', user)
+
+ expect_paginated_array_response([closed_issue.id])
+ end
+ end
+ end
+
+ it 'sorts ascending when requested' do
+ get api('/issues?sort=asc', user)
+
+ expect_paginated_array_response([closed_issue.id, issue.id])
+ end
+
+ it 'sorts by updated_at descending when requested' do
+ get api('/issues?order_by=updated_at', user)
+
+ issue.touch(:updated_at)
+
+ expect_paginated_array_response([issue.id, closed_issue.id])
+ end
+
+ it 'sorts by updated_at ascending when requested' do
+ get api('/issues?order_by=updated_at&sort=asc', user)
+
+ issue.touch(:updated_at)
+
+ expect_paginated_array_response([closed_issue.id, issue.id])
+ end
+
+ it 'matches V4 response schema' do
+ get api('/issues', user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/issues')
+ end
+
+ it 'returns a related merge request count of 0 if there are no related merge requests' do
+ get api('/issues', user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/issues')
+ expect(json_response.first).to include('merge_requests_count' => 0)
+ end
+
+ it 'returns a related merge request count > 0 if there are related merge requests' do
+ create(:merge_requests_closing_issues, issue: issue)
+
+ get api('/issues', user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/issues')
+ expect(json_response.first).to include('merge_requests_count' => 1)
+ end
+
+ context 'issues_statistics' do
+ context 'no state is treated as all state' do
+ let(:params) { {} }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'issues statistics'
+ end
+
+ context 'statistics when all state is passed' do
+ let(:params) { { state: :all } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'issues statistics'
+ end
+
+ context 'closed state is treated as all state' do
+ let(:params) { { state: :closed } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'issues statistics'
+ end
+
+ context 'opened state is treated as all state' do
+ let(:params) { { state: :opened } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'issues statistics'
+ end
+
+ context 'when filtering by milestone and no state treated as all state' do
+ let(:params) { { milestone: milestone.title } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'issues statistics'
+ end
+
+ context 'when filtering by milestone and all state' do
+ let(:params) { { milestone: milestone.title, state: :all } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'issues statistics'
+ end
+
+ context 'when filtering by milestone and closed state treated as all state' do
+ let(:params) { { milestone: milestone.title, state: :closed } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'issues statistics'
+ end
+
+ context 'when filtering by milestone and opened state treated as all state' do
+ let(:params) { { milestone: milestone.title, state: :opened } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'issues statistics'
+ end
+
+ context 'sort does not affect statistics ' do
+ let(:params) { { state: :opened, order_by: 'updated_at' } }
+ let(:counts) { { all: 2, closed: 1, opened: 1 } }
+
+ it_behaves_like 'issues statistics'
+ end
+ end
+
+ context 'filtering by assignee_username' do
+ let(:another_assignee) { create(:assignee) }
+ let!(:issue1) { create(:issue, author: user2, project: project, created_at: 3.days.ago) }
+ let!(:issue2) { create(:issue, author: user2, project: project, created_at: 2.days.ago) }
+ let!(:issue3) { create(:issue, author: user2, assignees: [assignee, another_assignee], project: project, created_at: 1.day.ago) }
+
+ it 'returns issues with by assignee_username' do
+ get api("/issues", user), params: { assignee_username: [assignee.username], scope: 'all' }
+
+ expect(issue3.reload.assignees.pluck(:id)).to match_array([assignee.id, another_assignee.id])
+ expect_paginated_array_response([confidential_issue.id, issue3.id])
+ end
+
+ it 'returns issues by assignee_username as string' do
+ get api("/issues", user), params: { assignee_username: assignee.username, scope: 'all' }
+
+ expect(issue3.reload.assignees.pluck(:id)).to match_array([assignee.id, another_assignee.id])
+ expect_paginated_array_response([confidential_issue.id, issue3.id])
+ end
+
+ it 'returns error when multiple assignees are passed' do
+ get api("/issues", user), params: { assignee_username: [assignee.username, another_assignee.username], scope: 'all' }
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response["error"]).to include("allows one value, but found 2")
+ end
+
+ it 'returns error when assignee_username and assignee_id are passed together' do
+ get api("/issues", user), params: { assignee_username: [assignee.username], assignee_id: another_assignee.id, scope: 'all' }
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response["error"]).to include("mutually exclusive")
+ end
+ end
+ end
+ end
+
+ describe 'DELETE /projects/:id/issues/:issue_iid' do
+ it 'rejects a non member from deleting an issue' do
+ delete api("/projects/#{project.id}/issues/#{issue.iid}", non_member)
+ expect(response).to have_gitlab_http_status(403)
+ end
+
+ it 'rejects a developer from deleting an issue' do
+ delete api("/projects/#{project.id}/issues/#{issue.iid}", author)
+ expect(response).to have_gitlab_http_status(403)
+ end
+
+ context 'when the user is project owner' do
+ let(:owner) { create(:user) }
+ let(:project) { create(:project, namespace: owner.namespace) }
+
+ it 'deletes the issue if an admin requests it' do
+ delete api("/projects/#{project.id}/issues/#{issue.iid}", owner)
+
+ expect(response).to have_gitlab_http_status(204)
+ end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/issues/#{issue.iid}", owner) }
+ end
+ end
+
+ context 'when issue does not exist' do
+ it 'returns 404 when trying to move an issue' do
+ delete api("/projects/#{project.id}/issues/123", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ it 'returns 404 when using the issue ID instead of IID' do
+ delete api("/projects/#{project.id}/issues/#{issue.id}", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ describe 'time tracking endpoints' do
+ let(:issuable) { issue }
+
+ include_examples 'time tracking endpoints', 'issue'
+ end
+end
diff --git a/spec/requests/api/issues/post_projects_issues_spec.rb b/spec/requests/api/issues/post_projects_issues_spec.rb
new file mode 100644
index 00000000000..b74e8867310
--- /dev/null
+++ b/spec/requests/api/issues/post_projects_issues_spec.rb
@@ -0,0 +1,549 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe API::Issues do
+ set(:user) { create(:user) }
+ set(:project) do
+ create(:project, :public, creator_id: user.id, namespace: user.namespace)
+ end
+
+ let(:user2) { create(:user) }
+ let(:non_member) { create(:user) }
+ set(:guest) { create(:user) }
+ set(:author) { create(:author) }
+ set(:assignee) { create(:assignee) }
+ let(:admin) { create(:user, :admin) }
+ let(:issue_title) { 'foo' }
+ let(:issue_description) { 'closed' }
+ let!(:closed_issue) do
+ create :closed_issue,
+ author: user,
+ assignees: [user],
+ project: project,
+ state: :closed,
+ milestone: milestone,
+ created_at: generate(:past_time),
+ updated_at: 3.hours.ago,
+ closed_at: 1.hour.ago
+ end
+ let!(:confidential_issue) do
+ create :issue,
+ :confidential,
+ project: project,
+ author: author,
+ assignees: [assignee],
+ created_at: generate(:past_time),
+ updated_at: 2.hours.ago
+ end
+ let!(:issue) do
+ create :issue,
+ author: user,
+ assignees: [user],
+ project: project,
+ milestone: milestone,
+ created_at: generate(:past_time),
+ updated_at: 1.hour.ago,
+ title: issue_title,
+ description: issue_description
+ end
+ set(:label) do
+ create(:label, title: 'label', color: '#FFAABB', project: project)
+ end
+ let!(:label_link) { create(:label_link, label: label, target: issue) }
+ let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
+ set(:empty_milestone) do
+ create(:milestone, title: '2.0.0', project: project)
+ end
+ let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) }
+
+ let(:no_milestone_title) { 'None' }
+ let(:any_milestone_title) { 'Any' }
+
+ before(:all) do
+ project.add_reporter(user)
+ project.add_guest(guest)
+ end
+
+ before do
+ stub_licensed_features(multiple_issue_assignees: false, issue_weights: false)
+ end
+
+ describe 'POST /projects/:id/issues' do
+ context 'support for deprecated assignee_id' do
+ it 'creates a new project issue' do
+ post api("/projects/#{project.id}/issues", user),
+ params: { title: 'new issue', assignee_id: user2.id }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['title']).to eq('new issue')
+ expect(json_response['assignee']['name']).to eq(user2.name)
+ expect(json_response['assignees'].first['name']).to eq(user2.name)
+ end
+
+ it 'creates a new project issue when assignee_id is empty' do
+ post api("/projects/#{project.id}/issues", user),
+ params: { title: 'new issue', assignee_id: '' }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['title']).to eq('new issue')
+ expect(json_response['assignee']).to be_nil
+ end
+ end
+
+ context 'single assignee restrictions' do
+ it 'creates a new project issue with no more than one assignee' do
+ post api("/projects/#{project.id}/issues", user),
+ params: { title: 'new issue', assignee_ids: [user2.id, guest.id] }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['title']).to eq('new issue')
+ expect(json_response['assignees'].count).to eq(1)
+ end
+ end
+
+ context 'user does not have permissions to create issue' do
+ let(:not_member) { create(:user) }
+
+ before do
+ project.project_feature.update(issues_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'renders 403' do
+ post api("/projects/#{project.id}/issues", not_member), params: { title: 'new issue' }
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+ end
+
+ context 'an internal ID is provided' do
+ context 'by an admin' do
+ it 'sets the internal ID on the new issue' do
+ post api("/projects/#{project.id}/issues", admin),
+ params: { title: 'new issue', iid: 9001 }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['iid']).to eq 9001
+ end
+ end
+
+ context 'by an owner' do
+ it 'sets the internal ID on the new issue' do
+ post api("/projects/#{project.id}/issues", user),
+ params: { title: 'new issue', iid: 9001 }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['iid']).to eq 9001
+ end
+ end
+
+ context 'by a group owner' do
+ let(:group) { create(:group) }
+ let(:group_project) { create(:project, :public, namespace: group) }
+
+ it 'sets the internal ID on the new issue' do
+ group.add_owner(user2)
+ post api("/projects/#{group_project.id}/issues", user2),
+ params: { title: 'new issue', iid: 9001 }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['iid']).to eq 9001
+ end
+ end
+
+ context 'by another user' do
+ it 'ignores the given internal ID' do
+ post api("/projects/#{project.id}/issues", user2),
+ params: { title: 'new issue', iid: 9001 }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['iid']).not_to eq 9001
+ end
+ end
+ end
+
+ it 'creates a new project issue' do
+ post api("/projects/#{project.id}/issues", user),
+ params: { title: 'new issue', labels: 'label, label2', weight: 3, assignee_ids: [user2.id] }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['title']).to eq('new issue')
+ expect(json_response['description']).to be_nil
+ expect(json_response['labels']).to eq(%w(label label2))
+ expect(json_response['confidential']).to be_falsy
+ expect(json_response['assignee']['name']).to eq(user2.name)
+ expect(json_response['assignees'].first['name']).to eq(user2.name)
+ end
+
+ it 'creates a new project issue with labels param as array' do
+ post api("/projects/#{project.id}/issues", user),
+ params: { title: 'new issue', labels: %w(label label2), weight: 3, assignee_ids: [user2.id] }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['title']).to eq('new issue')
+ expect(json_response['description']).to be_nil
+ expect(json_response['labels']).to eq(%w(label label2))
+ expect(json_response['confidential']).to be_falsy
+ expect(json_response['assignee']['name']).to eq(user2.name)
+ expect(json_response['assignees'].first['name']).to eq(user2.name)
+ end
+
+ it 'creates a new confidential project issue' do
+ post api("/projects/#{project.id}/issues", user),
+ params: { title: 'new issue', confidential: true }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['title']).to eq('new issue')
+ expect(json_response['confidential']).to be_truthy
+ end
+
+ it 'creates a new confidential project issue with a different param' do
+ post api("/projects/#{project.id}/issues", user),
+ params: { title: 'new issue', confidential: 'y' }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['title']).to eq('new issue')
+ expect(json_response['confidential']).to be_truthy
+ end
+
+ it 'creates a public issue when confidential param is false' do
+ post api("/projects/#{project.id}/issues", user),
+ params: { title: 'new issue', confidential: false }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['title']).to eq('new issue')
+ expect(json_response['confidential']).to be_falsy
+ end
+
+ it 'creates a public issue when confidential param is invalid' do
+ post api("/projects/#{project.id}/issues", user),
+ params: { title: 'new issue', confidential: 'foo' }
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['error']).to eq('confidential is invalid')
+ end
+
+ it 'returns a 400 bad request if title not given' do
+ post api("/projects/#{project.id}/issues", user), params: { labels: 'label, label2' }
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'allows special label names' do
+ post api("/projects/#{project.id}/issues", user),
+ params: {
+ title: 'new issue',
+ labels: 'label, label?, label&foo, ?, &'
+ }
+ expect(response.status).to eq(201)
+ expect(json_response['labels']).to include 'label'
+ expect(json_response['labels']).to include 'label?'
+ expect(json_response['labels']).to include 'label&foo'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
+ end
+
+ it 'allows special label names with labels param as array' do
+ post api("/projects/#{project.id}/issues", user),
+ params: {
+ title: 'new issue',
+ labels: ['label', 'label?', 'label&foo, ?, &']
+ }
+ expect(response.status).to eq(201)
+ expect(json_response['labels']).to include 'label'
+ expect(json_response['labels']).to include 'label?'
+ expect(json_response['labels']).to include 'label&foo'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
+ end
+
+ it 'returns 400 if title is too long' do
+ post api("/projects/#{project.id}/issues", user),
+ params: { title: 'g' * 256 }
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['message']['title']).to eq([
+ 'is too long (maximum is 255 characters)'
+ ])
+ end
+
+ context 'resolving discussions' do
+ let(:discussion) { create(:diff_note_on_merge_request).to_discussion }
+ let(:merge_request) { discussion.noteable }
+ let(:project) { merge_request.source_project }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ context 'resolving all discussions in a merge request' do
+ before do
+ post api("/projects/#{project.id}/issues", user),
+ params: {
+ title: 'New Issue',
+ merge_request_to_resolve_discussions_of: merge_request.iid
+ }
+ end
+
+ it_behaves_like 'creating an issue resolving discussions through the API'
+ end
+
+ context 'resolving a single discussion' do
+ before do
+ post api("/projects/#{project.id}/issues", user),
+ params: {
+ title: 'New Issue',
+ merge_request_to_resolve_discussions_of: merge_request.iid,
+ discussion_to_resolve: discussion.id
+ }
+ end
+
+ it_behaves_like 'creating an issue resolving discussions through the API'
+ end
+ end
+
+ context 'with due date' do
+ it 'creates a new project issue' do
+ due_date = 2.weeks.from_now.strftime('%Y-%m-%d')
+
+ post api("/projects/#{project.id}/issues", user),
+ params: { title: 'new issue', due_date: due_date }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['title']).to eq('new issue')
+ expect(json_response['description']).to be_nil
+ expect(json_response['due_date']).to eq(due_date)
+ end
+ end
+
+ context 'setting created_at' do
+ let(:creation_time) { 2.weeks.ago }
+ let(:params) { { title: 'new issue', labels: 'label, label2', created_at: creation_time } }
+
+ context 'by an admin' do
+ it 'sets the creation time on the new issue' do
+ post api("/projects/#{project.id}/issues", admin), params: params
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(Time.parse(json_response['created_at'])).to be_like_time(creation_time)
+ end
+ end
+
+ context 'by a project owner' do
+ it 'sets the creation time on the new issue' do
+ post api("/projects/#{project.id}/issues", user), params: params
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(Time.parse(json_response['created_at'])).to be_like_time(creation_time)
+ end
+ end
+
+ context 'by a group owner' do
+ it 'sets the creation time on the new issue' do
+ group = create(:group)
+ group_project = create(:project, :public, namespace: group)
+ group.add_owner(user2)
+ post api("/projects/#{group_project.id}/issues", user2), params: params
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(Time.parse(json_response['created_at'])).to be_like_time(creation_time)
+ end
+ end
+
+ context 'by another user' do
+ it 'ignores the given creation time' do
+ post api("/projects/#{project.id}/issues", user2), params: params
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(Time.parse(json_response['created_at'])).not_to be_like_time(creation_time)
+ end
+ end
+ end
+
+ context 'the user can only read the issue' do
+ it 'cannot create new labels' do
+ expect do
+ post api("/projects/#{project.id}/issues", non_member), params: { title: 'new issue', labels: 'label, label2' }
+ end.not_to change { project.labels.count }
+ end
+
+ it 'cannot create new labels with labels param as array' do
+ expect do
+ post api("/projects/#{project.id}/issues", non_member), params: { title: 'new issue', labels: %w(label label2) }
+ end.not_to change { project.labels.count }
+ end
+ end
+ end
+
+ describe 'POST /projects/:id/issues with spam filtering' do
+ before do
+ allow_any_instance_of(SpamService).to receive(:check_for_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive_messages(spam?: true)
+ end
+
+ let(:params) do
+ {
+ title: 'new issue',
+ description: 'content here',
+ labels: 'label, label2'
+ }
+ end
+
+ it 'does not create a new project issue' do
+ expect { post api("/projects/#{project.id}/issues", user), params: params }.not_to change(Issue, :count)
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['message']).to eq({ 'error' => 'Spam detected' })
+
+ spam_logs = SpamLog.all
+ expect(spam_logs.count).to eq(1)
+ expect(spam_logs[0].title).to eq('new issue')
+ expect(spam_logs[0].description).to eq('content here')
+ expect(spam_logs[0].user).to eq(user)
+ expect(spam_logs[0].noteable_type).to eq('Issue')
+ end
+ end
+
+ describe '/projects/:id/issues/:issue_iid/move' do
+ let!(:target_project) { create(:project, creator_id: user.id, namespace: user.namespace ) }
+ let!(:target_project2) { create(:project, creator_id: non_member.id, namespace: non_member.namespace ) }
+
+ it 'moves an issue' do
+ post api("/projects/#{project.id}/issues/#{issue.iid}/move", user),
+ params: { to_project_id: target_project.id }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['project_id']).to eq(target_project.id)
+ end
+
+ context 'when source and target projects are the same' do
+ it 'returns 400 when trying to move an issue' do
+ post api("/projects/#{project.id}/issues/#{issue.iid}/move", user),
+ params: { to_project_id: project.id }
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['message']).to eq('Cannot move issue to project it originates from!')
+ end
+ end
+
+ context 'when the user does not have the permission to move issues' do
+ it 'returns 400 when trying to move an issue' do
+ post api("/projects/#{project.id}/issues/#{issue.iid}/move", user),
+ params: { to_project_id: target_project2.id }
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['message']).to eq('Cannot move issue due to insufficient permissions!')
+ end
+ end
+
+ it 'moves the issue to another namespace if I am admin' do
+ post api("/projects/#{project.id}/issues/#{issue.iid}/move", admin),
+ params: { to_project_id: target_project2.id }
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['project_id']).to eq(target_project2.id)
+ end
+
+ context 'when using the issue ID instead of iid' do
+ it 'returns 404 when trying to move an issue' do
+ post api("/projects/#{project.id}/issues/#{issue.id}/move", user),
+ params: { to_project_id: target_project.id }
+
+ expect(response).to have_gitlab_http_status(404)
+ expect(json_response['message']).to eq('404 Issue Not Found')
+ end
+ end
+
+ context 'when issue does not exist' do
+ it 'returns 404 when trying to move an issue' do
+ post api("/projects/#{project.id}/issues/123/move", user),
+ params: { to_project_id: target_project.id }
+
+ expect(response).to have_gitlab_http_status(404)
+ expect(json_response['message']).to eq('404 Issue Not Found')
+ end
+ end
+
+ context 'when source project does not exist' do
+ it 'returns 404 when trying to move an issue' do
+ post api("/projects/0/issues/#{issue.iid}/move", user),
+ params: { to_project_id: target_project.id }
+
+ expect(response).to have_gitlab_http_status(404)
+ expect(json_response['message']).to eq('404 Project Not Found')
+ end
+ end
+
+ context 'when target project does not exist' do
+ it 'returns 404 when trying to move an issue' do
+ post api("/projects/#{project.id}/issues/#{issue.iid}/move", user),
+ params: { to_project_id: 0 }
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+
+ describe 'POST :id/issues/:issue_iid/subscribe' do
+ it 'subscribes to an issue' do
+ post api("/projects/#{project.id}/issues/#{issue.iid}/subscribe", user2)
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['subscribed']).to eq(true)
+ end
+
+ it 'returns 304 if already subscribed' do
+ post api("/projects/#{project.id}/issues/#{issue.iid}/subscribe", user)
+
+ expect(response).to have_gitlab_http_status(304)
+ end
+
+ it 'returns 404 if the issue is not found' do
+ post api("/projects/#{project.id}/issues/123/subscribe", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'returns 404 if the issue ID is used instead of the iid' do
+ post api("/projects/#{project.id}/issues/#{issue.id}/subscribe", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'returns 404 if the issue is confidential' do
+ post api("/projects/#{project.id}/issues/#{confidential_issue.iid}/subscribe", non_member)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ describe 'POST :id/issues/:issue_id/unsubscribe' do
+ it 'unsubscribes from an issue' do
+ post api("/projects/#{project.id}/issues/#{issue.iid}/unsubscribe", user)
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['subscribed']).to eq(false)
+ end
+
+ it 'returns 304 if not subscribed' do
+ post api("/projects/#{project.id}/issues/#{issue.iid}/unsubscribe", user2)
+
+ expect(response).to have_gitlab_http_status(304)
+ end
+
+ it 'returns 404 if the issue is not found' do
+ post api("/projects/#{project.id}/issues/123/unsubscribe", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'returns 404 if using the issue ID instead of iid' do
+ post api("/projects/#{project.id}/issues/#{issue.id}/unsubscribe", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'returns 404 if the issue is confidential' do
+ post api("/projects/#{project.id}/issues/#{confidential_issue.iid}/unsubscribe", non_member)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+end
diff --git a/spec/requests/api/issues/put_projects_issues_spec.rb b/spec/requests/api/issues/put_projects_issues_spec.rb
new file mode 100644
index 00000000000..267cba93713
--- /dev/null
+++ b/spec/requests/api/issues/put_projects_issues_spec.rb
@@ -0,0 +1,392 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe API::Issues do
+ set(:user) { create(:user) }
+ set(:project) do
+ create(:project, :public, creator_id: user.id, namespace: user.namespace)
+ end
+
+ let(:user2) { create(:user) }
+ let(:non_member) { create(:user) }
+ set(:guest) { create(:user) }
+ set(:author) { create(:author) }
+ set(:assignee) { create(:assignee) }
+ let(:admin) { create(:user, :admin) }
+ let(:issue_title) { 'foo' }
+ let(:issue_description) { 'closed' }
+ let!(:closed_issue) do
+ create :closed_issue,
+ author: user,
+ assignees: [user],
+ project: project,
+ state: :closed,
+ milestone: milestone,
+ created_at: generate(:past_time),
+ updated_at: 3.hours.ago,
+ closed_at: 1.hour.ago
+ end
+ let!(:confidential_issue) do
+ create :issue,
+ :confidential,
+ project: project,
+ author: author,
+ assignees: [assignee],
+ created_at: generate(:past_time),
+ updated_at: 2.hours.ago
+ end
+ let!(:issue) do
+ create :issue,
+ author: user,
+ assignees: [user],
+ project: project,
+ milestone: milestone,
+ created_at: generate(:past_time),
+ updated_at: 1.hour.ago,
+ title: issue_title,
+ description: issue_description
+ end
+ set(:label) do
+ create(:label, title: 'label', color: '#FFAABB', project: project)
+ end
+ let!(:label_link) { create(:label_link, label: label, target: issue) }
+ let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
+ set(:empty_milestone) do
+ create(:milestone, title: '2.0.0', project: project)
+ end
+ let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) }
+
+ let(:no_milestone_title) { 'None' }
+ let(:any_milestone_title) { 'Any' }
+
+ before(:all) do
+ project.add_reporter(user)
+ project.add_guest(guest)
+ end
+
+ before do
+ stub_licensed_features(multiple_issue_assignees: false, issue_weights: false)
+ end
+
+ describe 'PUT /projects/:id/issues/:issue_iid to update only title' do
+ it 'updates a project issue' do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: { title: 'updated title' }
+ expect(response).to have_gitlab_http_status(200)
+
+ expect(json_response['title']).to eq('updated title')
+ end
+
+ it 'returns 404 error if issue iid not found' do
+ put api("/projects/#{project.id}/issues/44444", user),
+ params: { title: 'updated title' }
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'returns 404 error if issue id is used instead of the iid' do
+ put api("/projects/#{project.id}/issues/#{issue.id}", user),
+ params: { title: 'updated title' }
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'allows special label names' do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: {
+ title: 'updated title',
+ labels: 'label, label?, label&foo, ?, &'
+ }
+
+ expect(response.status).to eq(200)
+ expect(json_response['labels']).to include 'label'
+ expect(json_response['labels']).to include 'label?'
+ expect(json_response['labels']).to include 'label&foo'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
+ end
+
+ it 'allows special label names with labels param as array' do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: {
+ title: 'updated title',
+ labels: ['label', 'label?', 'label&foo, ?, &']
+ }
+
+ expect(response.status).to eq(200)
+ expect(json_response['labels']).to include 'label'
+ expect(json_response['labels']).to include 'label?'
+ expect(json_response['labels']).to include 'label&foo'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
+ end
+
+ context 'confidential issues' do
+ it 'returns 403 for non project members' do
+ put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", non_member),
+ params: { title: 'updated title' }
+ expect(response).to have_gitlab_http_status(403)
+ end
+
+ it 'returns 403 for project members with guest role' do
+ put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", guest),
+ params: { title: 'updated title' }
+ expect(response).to have_gitlab_http_status(403)
+ end
+
+ it 'updates a confidential issue for project members' do
+ put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", user),
+ params: { title: 'updated title' }
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['title']).to eq('updated title')
+ end
+
+ it 'updates a confidential issue for author' do
+ put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", author),
+ params: { title: 'updated title' }
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['title']).to eq('updated title')
+ end
+
+ it 'updates a confidential issue for admin' do
+ put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", admin),
+ params: { title: 'updated title' }
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['title']).to eq('updated title')
+ end
+
+ it 'sets an issue to confidential' do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: { confidential: true }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['confidential']).to be_truthy
+ end
+
+ it 'makes a confidential issue public' do
+ put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", user),
+ params: { confidential: false }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['confidential']).to be_falsy
+ end
+
+ it 'does not update a confidential issue with wrong confidential flag' do
+ put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", user),
+ params: { confidential: 'foo' }
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['error']).to eq('confidential is invalid')
+ end
+ end
+ end
+
+ describe 'PUT /projects/:id/issues/:issue_iid with spam filtering' do
+ let(:params) do
+ {
+ title: 'updated title',
+ description: 'content here',
+ labels: 'label, label2'
+ }
+ end
+
+ it 'does not create a new project issue' do
+ allow_any_instance_of(SpamService).to receive_messages(check_for_spam?: true)
+ allow_any_instance_of(AkismetService).to receive_messages(spam?: true)
+
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user), params: params
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['message']).to eq({ 'error' => 'Spam detected' })
+
+ spam_logs = SpamLog.all
+ expect(spam_logs.count).to eq(1)
+ expect(spam_logs[0].title).to eq('updated title')
+ expect(spam_logs[0].description).to eq('content here')
+ expect(spam_logs[0].user).to eq(user)
+ expect(spam_logs[0].noteable_type).to eq('Issue')
+ end
+ end
+
+ describe 'PUT /projects/:id/issues/:issue_iid to update assignee' do
+ context 'support for deprecated assignee_id' do
+ it 'removes assignee' do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: { assignee_id: 0 }
+
+ expect(response).to have_gitlab_http_status(200)
+
+ expect(json_response['assignee']).to be_nil
+ end
+
+ it 'updates an issue with new assignee' do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: { assignee_id: user2.id }
+
+ expect(response).to have_gitlab_http_status(200)
+
+ expect(json_response['assignee']['name']).to eq(user2.name)
+ end
+ end
+
+ it 'removes assignee' do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: { assignee_ids: [0] }
+
+ expect(response).to have_gitlab_http_status(200)
+
+ expect(json_response['assignees']).to be_empty
+ end
+
+ it 'updates an issue with new assignee' do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: { assignee_ids: [user2.id] }
+
+ expect(response).to have_gitlab_http_status(200)
+
+ expect(json_response['assignees'].first['name']).to eq(user2.name)
+ end
+
+ context 'single assignee restrictions' do
+ it 'updates an issue with several assignees but only one has been applied' do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: { assignee_ids: [user2.id, guest.id] }
+
+ expect(response).to have_gitlab_http_status(200)
+
+ expect(json_response['assignees'].size).to eq(1)
+ end
+ end
+ end
+
+ describe 'PUT /projects/:id/issues/:issue_iid to update labels' do
+ let!(:label) { create(:label, title: 'dummy', project: project) }
+ let!(:label_link) { create(:label_link, label: label, target: issue) }
+
+ it 'does not update labels if not present' do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: { title: 'updated title' }
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['labels']).to eq([label.title])
+ end
+
+ it 'removes all labels and touches the record' do
+ Timecop.travel(1.minute.from_now) do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user), params: { labels: '' }
+ end
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['labels']).to eq([])
+ expect(json_response['updated_at']).to be > Time.now
+ end
+
+ it 'removes all labels and touches the record with labels param as array' do
+ Timecop.travel(1.minute.from_now) do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user), params: { labels: [''] }
+ end
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['labels']).to eq([])
+ expect(json_response['updated_at']).to be > Time.now
+ end
+
+ it 'updates labels and touches the record' do
+ Timecop.travel(1.minute.from_now) do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: { labels: 'foo,bar' }
+ end
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['labels']).to include 'foo'
+ expect(json_response['labels']).to include 'bar'
+ expect(json_response['updated_at']).to be > Time.now
+ end
+
+ it 'updates labels and touches the record with labels param as array' do
+ Timecop.travel(1.minute.from_now) do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: { labels: %w(foo bar) }
+ end
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['labels']).to include 'foo'
+ expect(json_response['labels']).to include 'bar'
+ expect(json_response['updated_at']).to be > Time.now
+ end
+
+ it 'allows special label names' do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: { labels: 'label:foo, label-bar,label_bar,label/bar,label?bar,label&bar,?,&' }
+ expect(response.status).to eq(200)
+ expect(json_response['labels']).to include 'label:foo'
+ expect(json_response['labels']).to include 'label-bar'
+ expect(json_response['labels']).to include 'label_bar'
+ expect(json_response['labels']).to include 'label/bar'
+ expect(json_response['labels']).to include 'label?bar'
+ expect(json_response['labels']).to include 'label&bar'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
+ end
+
+ it 'allows special label names with labels param as array' do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: { labels: ['label:foo', 'label-bar', 'label_bar', 'label/bar,label?bar,label&bar,?,&'] }
+ expect(response.status).to eq(200)
+ expect(json_response['labels']).to include 'label:foo'
+ expect(json_response['labels']).to include 'label-bar'
+ expect(json_response['labels']).to include 'label_bar'
+ expect(json_response['labels']).to include 'label/bar'
+ expect(json_response['labels']).to include 'label?bar'
+ expect(json_response['labels']).to include 'label&bar'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
+ end
+
+ it 'returns 400 if title is too long' do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: { title: 'g' * 256 }
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['message']['title']).to eq([
+ 'is too long (maximum is 255 characters)'
+ ])
+ end
+ end
+
+ describe 'PUT /projects/:id/issues/:issue_iid to update state and label' do
+ it 'updates a project issue' do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: { labels: 'label2', state_event: 'close' }
+ expect(response).to have_gitlab_http_status(200)
+
+ expect(json_response['labels']).to include 'label2'
+ expect(json_response['state']).to eq 'closed'
+ end
+
+ it 'reopens a project isssue' do
+ put api("/projects/#{project.id}/issues/#{closed_issue.iid}", user), params: { state_event: 'reopen' }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['state']).to eq 'opened'
+ end
+
+ context 'when an admin or owner makes the request' do
+ it 'accepts the update date to be set' do
+ update_time = 2.weeks.ago
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user),
+ params: { labels: 'label3', state_event: 'close', updated_at: update_time }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['labels']).to include 'label3'
+ expect(Time.parse(json_response['updated_at'])).to be_like_time(update_time)
+ end
+ end
+ end
+
+ describe 'PUT /projects/:id/issues/:issue_iid to update due date' do
+ it 'creates a new project issue' do
+ due_date = 2.weeks.from_now.strftime('%Y-%m-%d')
+
+ put api("/projects/#{project.id}/issues/#{issue.iid}", user), params: { due_date: due_date }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['due_date']).to eq(due_date)
+ end
+ end
+end
diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
deleted file mode 100644
index 86484ce62f8..00000000000
--- a/spec/requests/api/issues_spec.rb
+++ /dev/null
@@ -1,2257 +0,0 @@
-require 'spec_helper'
-
-describe API::Issues do
- set(:user) { create(:user) }
- set(:project) do
- create(:project, :public, creator_id: user.id, namespace: user.namespace)
- end
-
- let(:user2) { create(:user) }
- let(:non_member) { create(:user) }
- set(:guest) { create(:user) }
- set(:author) { create(:author) }
- set(:assignee) { create(:assignee) }
- let(:admin) { create(:user, :admin) }
- let(:issue_title) { 'foo' }
- let(:issue_description) { 'closed' }
- let!(:closed_issue) do
- create :closed_issue,
- author: user,
- assignees: [user],
- project: project,
- state: :closed,
- milestone: milestone,
- created_at: generate(:past_time),
- updated_at: 3.hours.ago,
- closed_at: 1.hour.ago
- end
- let!(:confidential_issue) do
- create :issue,
- :confidential,
- project: project,
- author: author,
- assignees: [assignee],
- created_at: generate(:past_time),
- updated_at: 2.hours.ago
- end
- let!(:issue) do
- create :issue,
- author: user,
- assignees: [user],
- project: project,
- milestone: milestone,
- created_at: generate(:past_time),
- updated_at: 1.hour.ago,
- title: issue_title,
- description: issue_description
- end
- set(:label) do
- create(:label, title: 'label', color: '#FFAABB', project: project)
- end
- let!(:label_link) { create(:label_link, label: label, target: issue) }
- let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
- set(:empty_milestone) do
- create(:milestone, title: '2.0.0', project: project)
- end
- let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) }
-
- let(:no_milestone_title) { "None" }
- let(:any_milestone_title) { "Any" }
-
- before(:all) do
- project.add_reporter(user)
- project.add_guest(guest)
- end
-
- describe "GET /issues" do
- context "when unauthenticated" do
- it "returns an array of all issues" do
- get api("/issues"), params: { scope: 'all' }
-
- expect(response).to have_http_status(200)
- expect(json_response).to be_an Array
- end
-
- it "returns authentication error without any scope" do
- get api("/issues")
-
- expect(response).to have_http_status(401)
- end
-
- it "returns authentication error when scope is assigned-to-me" do
- get api("/issues"), params: { scope: 'assigned-to-me' }
-
- expect(response).to have_http_status(401)
- end
-
- it "returns authentication error when scope is created-by-me" do
- get api("/issues"), params: { scope: 'created-by-me' }
-
- expect(response).to have_http_status(401)
- end
- end
-
- context "when authenticated" do
- it "returns an array of issues" do
- get api("/issues", user)
-
- expect_paginated_array_response([issue.id, closed_issue.id])
- expect(json_response.first['title']).to eq(issue.title)
- expect(json_response.last).to have_key('web_url')
- end
-
- it 'returns an array of closed issues' do
- get api('/issues', user), params: { state: :closed }
-
- expect_paginated_array_response(closed_issue.id)
- end
-
- it 'returns an array of opened issues' do
- get api('/issues', user), params: { state: :opened }
-
- expect_paginated_array_response(issue.id)
- end
-
- it 'returns an array of all issues' do
- get api('/issues', user), params: { state: :all }
-
- expect_paginated_array_response([issue.id, closed_issue.id])
- end
-
- it 'returns issues assigned to me' do
- issue2 = create(:issue, assignees: [user2], project: project)
-
- get api('/issues', user2), params: { scope: 'assigned_to_me' }
-
- expect_paginated_array_response(issue2.id)
- end
-
- it 'returns issues assigned to me (kebab-case)' do
- issue2 = create(:issue, assignees: [user2], project: project)
-
- get api('/issues', user2), params: { scope: 'assigned-to-me' }
-
- expect_paginated_array_response(issue2.id)
- end
-
- it 'returns issues authored by the given author id' do
- issue2 = create(:issue, author: user2, project: project)
-
- get api('/issues', user), params: { author_id: user2.id, scope: 'all' }
-
- expect_paginated_array_response(issue2.id)
- end
-
- it 'returns issues assigned to the given assignee id' do
- issue2 = create(:issue, assignees: [user2], project: project)
-
- get api('/issues', user), params: { assignee_id: user2.id, scope: 'all' }
-
- expect_paginated_array_response(issue2.id)
- end
-
- it 'returns issues authored by the given author id and assigned to the given assignee id' do
- issue2 = create(:issue, author: user2, assignees: [user2], project: project)
-
- get api('/issues', user), params: { author_id: user2.id, assignee_id: user2.id, scope: 'all' }
-
- expect_paginated_array_response(issue2.id)
- end
-
- it 'returns issues with no assignee' do
- issue2 = create(:issue, author: user2, project: project)
-
- get api('/issues', user), params: { assignee_id: 0, scope: 'all' }
-
- expect_paginated_array_response(issue2.id)
- end
-
- it 'returns issues with no assignee' do
- issue2 = create(:issue, author: user2, project: project)
-
- get api('/issues', user), params: { assignee_id: 'None', scope: 'all' }
-
- expect_paginated_array_response(issue2.id)
- end
-
- it 'returns issues with any assignee' do
- # This issue without assignee should not be returned
- create(:issue, author: user2, project: project)
-
- get api('/issues', user), params: { assignee_id: 'Any', scope: 'all' }
-
- expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
- end
-
- it 'returns only confidential issues' do
- get api('/issues', user), params: { confidential: true, scope: 'all' }
-
- expect_paginated_array_response(confidential_issue.id)
- end
-
- it 'returns only public issues' do
- get api('/issues', user), params: { confidential: false }
-
- expect_paginated_array_response([issue.id, closed_issue.id])
- end
-
- it 'returns issues reacted by the authenticated user' do
- issue2 = create(:issue, project: project, author: user, assignees: [user])
- create(:award_emoji, awardable: issue2, user: user2, name: 'star')
- create(:award_emoji, awardable: issue, user: user2, name: 'thumbsup')
-
- get api('/issues', user2), params: { my_reaction_emoji: 'Any', scope: 'all' }
-
- expect_paginated_array_response([issue2.id, issue.id])
- end
-
- it 'returns issues not reacted by the authenticated user' do
- issue2 = create(:issue, project: project, author: user, assignees: [user])
- create(:award_emoji, awardable: issue2, user: user2, name: 'star')
-
- get api('/issues', user2), params: { my_reaction_emoji: 'None', scope: 'all' }
-
- expect_paginated_array_response([issue.id, closed_issue.id])
- end
-
- it 'returns issues matching given search string for title' do
- get api("/issues", user), params: { search: issue.title }
-
- expect_paginated_array_response(issue.id)
- end
-
- it 'returns issues matching given search string for title and scoped in title' do
- get api("/issues", user), params: { search: issue.title, in: 'title' }
-
- expect_paginated_array_response(issue.id)
- end
-
- it 'returns an empty array if no issue matches given search string for title and scoped in description' do
- get api("/issues", user), params: { search: issue.title, in: 'description' }
-
- expect_paginated_array_response([])
- end
-
- it 'returns issues matching given search string for description' do
- get api("/issues", user), params: { search: issue.description }
-
- expect_paginated_array_response(issue.id)
- end
-
- context 'filtering before a specific date' do
- let!(:issue2) { create(:issue, project: project, author: user, created_at: Date.new(2000, 1, 1), updated_at: Date.new(2000, 1, 1)) }
-
- it 'returns issues created before a specific date' do
- get api('/issues?created_before=2000-01-02T00:00:00.060Z', user)
-
- expect_paginated_array_response(issue2.id)
- end
-
- it 'returns issues updated before a specific date' do
- get api('/issues?updated_before=2000-01-02T00:00:00.060Z', user)
-
- expect_paginated_array_response(issue2.id)
- end
- end
-
- context 'filtering after a specific date' do
- let!(:issue2) { create(:issue, project: project, author: user, created_at: 1.week.from_now, updated_at: 1.week.from_now) }
-
- it 'returns issues created after a specific date' do
- get api("/issues?created_after=#{issue2.created_at}", user)
-
- expect_paginated_array_response(issue2.id)
- end
-
- it 'returns issues updated after a specific date' do
- get api("/issues?updated_after=#{issue2.updated_at}", user)
-
- expect_paginated_array_response(issue2.id)
- end
- end
-
- it 'returns an array of labeled issues' do
- get api('/issues', user), params: { labels: label.title }
-
- expect_paginated_array_response(issue.id)
- expect(json_response.first['labels']).to eq([label.title])
- end
-
- it 'returns an array of labeled issues with labels param as array' do
- get api('/issues', user), params: { labels: [label.title] }
-
- expect_paginated_array_response(issue.id)
- expect(json_response.first['labels']).to eq([label.title])
- end
-
- it 'returns an array of labeled issues when all labels matches' do
- label_b = create(:label, title: 'foo', project: project)
- label_c = create(:label, title: 'bar', project: project)
-
- create(:label_link, label: label_b, target: issue)
- create(:label_link, label: label_c, target: issue)
-
- get api('/issues', user), params: { labels: "#{label.title},#{label_b.title},#{label_c.title}" }
-
- expect_paginated_array_response(issue.id)
- expect(json_response.first['labels']).to eq([label_c.title, label_b.title, label.title])
- end
-
- it 'returns an array of labeled issues when all labels matches with labels param as array' do
- label_b = create(:label, title: 'foo', project: project)
- label_c = create(:label, title: 'bar', project: project)
-
- create(:label_link, label: label_b, target: issue)
- create(:label_link, label: label_c, target: issue)
-
- get api('/issues', user), params: { labels: [label.title, label_b.title, label_c.title] }
-
- expect_paginated_array_response(issue.id)
- expect(json_response.first['labels']).to eq([label_c.title, label_b.title, label.title])
- end
-
- it 'returns an empty array if no issue matches labels' do
- get api('/issues', user), params: { labels: 'foo,bar' }
-
- expect_paginated_array_response([])
- end
-
- it 'returns an empty array if no issue matches labels with labels param as array' do
- get api('/issues', user), params: { labels: %w(foo bar) }
-
- expect_paginated_array_response([])
- end
-
- it 'returns an array of labeled issues matching given state' do
- get api('/issues', user), params: { labels: label.title, state: :opened }
-
- expect_paginated_array_response(issue.id)
- expect(json_response.first['labels']).to eq([label.title])
- expect(json_response.first['state']).to eq('opened')
- end
-
- it 'returns an array of labeled issues matching given state with labels param as array' do
- get api('/issues', user), params: { labels: [label.title], state: :opened }
-
- expect_paginated_array_response(issue.id)
- expect(json_response.first['labels']).to eq([label.title])
- expect(json_response.first['state']).to eq('opened')
- end
-
- it 'returns an empty array if no issue matches labels and state filters' do
- get api('/issues', user), params: { labels: label.title, state: :closed }
-
- expect_paginated_array_response([])
- end
-
- it 'returns an array of issues with any label' do
- get api('/issues', user), params: { labels: IssuesFinder::FILTER_ANY }
-
- expect_paginated_array_response(issue.id)
- end
-
- it 'returns an array of issues with any label with labels param as array' do
- get api('/issues', user), params: { labels: [IssuesFinder::FILTER_ANY] }
-
- expect_paginated_array_response(issue.id)
- end
-
- it 'returns an array of issues with no label' do
- get api('/issues', user), params: { labels: IssuesFinder::FILTER_NONE }
-
- expect_paginated_array_response(closed_issue.id)
- end
-
- it 'returns an array of issues with no label with labels param as array' do
- get api('/issues', user), params: { labels: [IssuesFinder::FILTER_NONE] }
-
- expect_paginated_array_response(closed_issue.id)
- end
-
- it 'returns an array of issues with no label when using the legacy No+Label filter' do
- get api('/issues', user), params: { labels: 'No Label' }
-
- expect_paginated_array_response(closed_issue.id)
- end
-
- it 'returns an array of issues with no label when using the legacy No+Label filter with labels param as array' do
- get api('/issues', user), params: { labels: ['No Label'] }
-
- expect_paginated_array_response(closed_issue.id)
- end
-
- it 'returns an empty array if no issue matches milestone' do
- get api("/issues?milestone=#{empty_milestone.title}", user)
-
- expect_paginated_array_response([])
- end
-
- it 'returns an empty array if milestone does not exist' do
- get api("/issues?milestone=foo", user)
-
- expect_paginated_array_response([])
- end
-
- it 'returns an array of issues in given milestone' do
- get api("/issues?milestone=#{milestone.title}", user)
-
- expect_paginated_array_response([issue.id, closed_issue.id])
- end
-
- it 'returns an array of issues matching state in milestone' do
- get api("/issues?milestone=#{milestone.title}"\
- '&state=closed', user)
-
- expect_paginated_array_response(closed_issue.id)
- end
-
- it 'returns an array of issues with no milestone' do
- get api("/issues?milestone=#{no_milestone_title}", author)
-
- expect_paginated_array_response(confidential_issue.id)
- end
-
- it 'returns an array of issues found by iids' do
- get api('/issues', user), params: { iids: [closed_issue.iid] }
-
- expect_paginated_array_response(closed_issue.id)
- end
-
- it 'returns an empty array if iid does not exist' do
- get api("/issues", user), params: { iids: [0] }
-
- expect_paginated_array_response([])
- end
-
- context 'without sort params' do
- it 'sorts by created_at descending by default' do
- get api('/issues', user)
-
- expect_paginated_array_response([issue.id, closed_issue.id])
- end
-
- context 'with 2 issues with same created_at' do
- let!(:closed_issue2) do
- create :closed_issue,
- author: user,
- assignees: [user],
- project: project,
- milestone: milestone,
- created_at: closed_issue.created_at,
- updated_at: 1.hour.ago,
- title: issue_title,
- description: issue_description
- end
-
- it 'page breaks first page correctly' do
- get api('/issues?per_page=2', user)
-
- expect_paginated_array_response([issue.id, closed_issue2.id])
- end
-
- it 'page breaks second page correctly' do
- get api('/issues?per_page=2&page=2', user)
-
- expect_paginated_array_response([closed_issue.id])
- end
- end
- end
-
- it 'sorts ascending when requested' do
- get api('/issues?sort=asc', user)
-
- expect_paginated_array_response([closed_issue.id, issue.id])
- end
-
- it 'sorts by updated_at descending when requested' do
- get api('/issues?order_by=updated_at', user)
-
- issue.touch(:updated_at)
-
- expect_paginated_array_response([issue.id, closed_issue.id])
- end
-
- it 'sorts by updated_at ascending when requested' do
- get api('/issues?order_by=updated_at&sort=asc', user)
-
- issue.touch(:updated_at)
-
- expect_paginated_array_response([closed_issue.id, issue.id])
- end
-
- it 'matches V4 response schema' do
- get api('/issues', user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to match_response_schema('public_api/v4/issues')
- end
-
- it 'returns a related merge request count of 0 if there are no related merge requests' do
- get api('/issues', user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to match_response_schema('public_api/v4/issues')
- expect(json_response.first).to include('merge_requests_count' => 0)
- end
-
- it 'returns a related merge request count > 0 if there are related merge requests' do
- create(:merge_requests_closing_issues, issue: issue)
-
- get api('/issues', user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to match_response_schema('public_api/v4/issues')
- expect(json_response.first).to include('merge_requests_count' => 1)
- end
- end
- end
-
- describe "GET /groups/:id/issues" do
- let!(:group) { create(:group) }
- let!(:group_project) { create(:project, :public, creator_id: user.id, namespace: group) }
- let!(:group_closed_issue) do
- create :closed_issue,
- author: user,
- assignees: [user],
- project: group_project,
- state: :closed,
- milestone: group_milestone,
- updated_at: 3.hours.ago,
- created_at: 1.day.ago
- end
- let!(:group_confidential_issue) do
- create :issue,
- :confidential,
- project: group_project,
- author: author,
- assignees: [assignee],
- updated_at: 2.hours.ago,
- created_at: 2.days.ago
- end
- let!(:group_issue) do
- create :issue,
- author: user,
- assignees: [user],
- project: group_project,
- milestone: group_milestone,
- updated_at: 1.hour.ago,
- title: issue_title,
- description: issue_description,
- created_at: 5.days.ago
- end
- let!(:group_label) do
- create(:label, title: 'group_lbl', color: '#FFAABB', project: group_project)
- end
- let!(:group_label_link) { create(:label_link, label: group_label, target: group_issue) }
- let!(:group_milestone) { create(:milestone, title: '3.0.0', project: group_project) }
- let!(:group_empty_milestone) do
- create(:milestone, title: '4.0.0', project: group_project)
- end
- let!(:group_note) { create(:note_on_issue, author: user, project: group_project, noteable: group_issue) }
-
- let(:base_url) { "/groups/#{group.id}/issues" }
-
- context 'when group has subgroups', :nested_groups do
- let(:subgroup_1) { create(:group, parent: group) }
- let(:subgroup_2) { create(:group, parent: subgroup_1) }
-
- let(:subgroup_1_project) { create(:project, namespace: subgroup_1) }
- let(:subgroup_2_project) { create(:project, namespace: subgroup_2) }
-
- let!(:issue_1) { create(:issue, project: subgroup_1_project) }
- let!(:issue_2) { create(:issue, project: subgroup_2_project) }
-
- before do
- group.add_developer(user)
- end
-
- it 'also returns subgroups projects issues' do
- get api(base_url, user)
-
- expect_paginated_array_response([issue_2.id, issue_1.id, group_closed_issue.id, group_confidential_issue.id, group_issue.id])
- end
- end
-
- context 'when user is unauthenticated' do
- it 'lists all issues in public projects' do
- get api(base_url)
-
- expect_paginated_array_response([group_closed_issue.id, group_issue.id])
- end
- end
-
- context 'when user is a group member' do
- before do
- group_project.add_reporter(user)
- end
-
- it 'returns all group issues (including opened and closed)' do
- get api(base_url, admin)
-
- expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id, group_issue.id])
- end
-
- it 'returns group issues without confidential issues for non project members' do
- get api(base_url, non_member), params: { state: :opened }
-
- expect_paginated_array_response(group_issue.id)
- end
-
- it 'returns group confidential issues for author' do
- get api(base_url, author), params: { state: :opened }
-
- expect_paginated_array_response([group_confidential_issue.id, group_issue.id])
- end
-
- it 'returns group confidential issues for assignee' do
- get api(base_url, assignee), params: { state: :opened }
-
- expect_paginated_array_response([group_confidential_issue.id, group_issue.id])
- end
-
- it 'returns group issues with confidential issues for project members' do
- get api(base_url, user), params: { state: :opened }
-
- expect_paginated_array_response([group_confidential_issue.id, group_issue.id])
- end
-
- it 'returns group confidential issues for admin' do
- get api(base_url, admin), params: { state: :opened }
-
- expect_paginated_array_response([group_confidential_issue.id, group_issue.id])
- end
-
- it 'returns only confidential issues' do
- get api(base_url, user), params: { confidential: true }
-
- expect_paginated_array_response(group_confidential_issue.id)
- end
-
- it 'returns only public issues' do
- get api(base_url, user), params: { confidential: false }
-
- expect_paginated_array_response([group_closed_issue.id, group_issue.id])
- end
-
- it 'returns an array of labeled group issues' do
- get api(base_url, user), params: { labels: group_label.title }
-
- expect_paginated_array_response(group_issue.id)
- expect(json_response.first['labels']).to eq([group_label.title])
- end
-
- it 'returns an array of labeled group issues with labels param as array' do
- get api(base_url, user), params: { labels: [group_label.title] }
-
- expect_paginated_array_response(group_issue.id)
- expect(json_response.first['labels']).to eq([group_label.title])
- end
-
- it 'returns an array of labeled group issues where all labels match' do
- get api(base_url, user), params: { labels: "#{group_label.title},foo,bar" }
-
- expect_paginated_array_response([])
- end
-
- it 'returns an array of labeled group issues where all labels match with labels param as array' do
- get api(base_url, user), params: { labels: [group_label.title, 'foo', 'bar'] }
-
- expect_paginated_array_response([])
- end
-
- it 'returns issues matching given search string for title' do
- get api(base_url, user), params: { search: group_issue.title }
-
- expect_paginated_array_response(group_issue.id)
- end
-
- it 'returns issues matching given search string for description' do
- get api(base_url, user), params: { search: group_issue.description }
-
- expect_paginated_array_response(group_issue.id)
- end
-
- it 'returns an array of labeled issues when all labels matches' do
- label_b = create(:label, title: 'foo', project: group_project)
- label_c = create(:label, title: 'bar', project: group_project)
-
- create(:label_link, label: label_b, target: group_issue)
- create(:label_link, label: label_c, target: group_issue)
-
- get api(base_url, user), params: { labels: "#{group_label.title},#{label_b.title},#{label_c.title}" }
-
- expect_paginated_array_response(group_issue.id)
- expect(json_response.first['labels']).to eq([label_c.title, label_b.title, group_label.title])
- end
-
- it 'returns an array of labeled issues when all labels matches with labels param as array' do
- label_b = create(:label, title: 'foo', project: group_project)
- label_c = create(:label, title: 'bar', project: group_project)
-
- create(:label_link, label: label_b, target: group_issue)
- create(:label_link, label: label_c, target: group_issue)
-
- get api(base_url, user), params: { labels: [group_label.title, label_b.title, label_c.title] }
-
- expect_paginated_array_response(group_issue.id)
- expect(json_response.first['labels']).to eq([label_c.title, label_b.title, group_label.title])
- end
-
- it 'returns an array of issues found by iids' do
- get api(base_url, user), params: { iids: [group_issue.iid] }
-
- expect_paginated_array_response(group_issue.id)
- expect(json_response.first['id']).to eq(group_issue.id)
- end
-
- it 'returns an empty array if iid does not exist' do
- get api(base_url, user), params: { iids: [0] }
-
- expect_paginated_array_response([])
- end
-
- it 'returns an empty array if no group issue matches labels' do
- get api(base_url, user), params: { labels: 'foo,bar' }
-
- expect_paginated_array_response([])
- end
-
- it 'returns an array of group issues with any label' do
- get api(base_url, user), params: { labels: IssuesFinder::FILTER_ANY }
-
- expect_paginated_array_response(group_issue.id)
- expect(json_response.first['id']).to eq(group_issue.id)
- end
-
- it 'returns an array of group issues with any label with labels param as array' do
- get api(base_url, user), params: { labels: [IssuesFinder::FILTER_ANY] }
-
- expect_paginated_array_response(group_issue.id)
- expect(json_response.first['id']).to eq(group_issue.id)
- end
-
- it 'returns an array of group issues with no label' do
- get api(base_url, user), params: { labels: IssuesFinder::FILTER_NONE }
-
- expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id])
- end
-
- it 'returns an array of group issues with no label with labels param as array' do
- get api(base_url, user), params: { labels: [IssuesFinder::FILTER_NONE] }
-
- expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id])
- end
-
- it 'returns an empty array if no issue matches milestone' do
- get api(base_url, user), params: { milestone: group_empty_milestone.title }
-
- expect_paginated_array_response([])
- end
-
- it 'returns an empty array if milestone does not exist' do
- get api(base_url, user), params: { milestone: 'foo' }
-
- expect_paginated_array_response([])
- end
-
- it 'returns an array of issues in given milestone' do
- get api(base_url, user), params: { state: :opened, milestone: group_milestone.title }
-
- expect_paginated_array_response(group_issue.id)
- end
-
- it 'returns an array of issues matching state in milestone' do
- get api(base_url, user), params: { milestone: group_milestone.title, state: :closed }
-
- expect_paginated_array_response(group_closed_issue.id)
- end
-
- it 'returns an array of issues with no milestone' do
- get api(base_url, user), params: { milestone: no_milestone_title }
-
- expect(response).to have_gitlab_http_status(200)
-
- expect_paginated_array_response(group_confidential_issue.id)
- end
-
- context 'without sort params' do
- it 'sorts by created_at descending by default' do
- get api(base_url, user)
-
- expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id, group_issue.id])
- end
-
- context 'with 2 issues with same created_at' do
- let!(:group_issue2) do
- create :issue,
- author: user,
- assignees: [user],
- project: group_project,
- milestone: group_milestone,
- updated_at: 1.hour.ago,
- title: issue_title,
- description: issue_description,
- created_at: group_issue.created_at
- end
-
- it 'page breaks first page correctly' do
- get api("#{base_url}?per_page=3", user)
-
- expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id, group_issue2.id])
- end
-
- it 'page breaks second page correctly' do
- get api("#{base_url}?per_page=3&page=2", user)
-
- expect_paginated_array_response([group_issue.id])
- end
- end
- end
-
- it 'sorts ascending when requested' do
- get api("#{base_url}?sort=asc", user)
-
- expect_paginated_array_response([group_issue.id, group_confidential_issue.id, group_closed_issue.id])
- end
-
- it 'sorts by updated_at descending when requested' do
- get api("#{base_url}?order_by=updated_at", user)
-
- group_issue.touch(:updated_at)
-
- expect_paginated_array_response([group_issue.id, group_confidential_issue.id, group_closed_issue.id])
- end
-
- it 'sorts by updated_at ascending when requested' do
- get api(base_url, user), params: { order_by: :updated_at, sort: :asc }
-
- expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id, group_issue.id])
- end
- end
- end
-
- describe "GET /projects/:id/issues" do
- let(:base_url) { "/projects/#{project.id}" }
-
- context 'when unauthenticated' do
- it 'returns public project issues' do
- get api("/projects/#{project.id}/issues")
-
- expect_paginated_array_response([issue.id, closed_issue.id])
- end
- end
-
- it 'avoids N+1 queries' do
- get api("/projects/#{project.id}/issues", user)
-
- control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
- get api("/projects/#{project.id}/issues", user)
- end.count
-
- create_list(:issue, 3, project: project)
-
- expect do
- get api("/projects/#{project.id}/issues", user)
- end.not_to exceed_all_query_limit(control_count)
- end
-
- it 'returns 404 when project does not exist' do
- get api('/projects/1000/issues', non_member)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it "returns 404 on private projects for other users" do
- private_project = create(:project, :private)
- create(:issue, project: private_project)
-
- get api("/projects/#{private_project.id}/issues", non_member)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns no issues when user has access to project but not issues' do
- restricted_project = create(:project, :public, :issues_private)
- create(:issue, project: restricted_project)
-
- get api("/projects/#{restricted_project.id}/issues", non_member)
-
- expect_paginated_array_response([])
- end
-
- it 'returns project issues without confidential issues for non project members' do
- get api("#{base_url}/issues", non_member)
-
- expect_paginated_array_response([issue.id, closed_issue.id])
- end
-
- it 'returns project issues without confidential issues for project members with guest role' do
- get api("#{base_url}/issues", guest)
-
- expect_paginated_array_response([issue.id, closed_issue.id])
- end
-
- it 'returns project confidential issues for author' do
- get api("#{base_url}/issues", author)
-
- expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
- end
-
- it 'returns only confidential issues' do
- get api("#{base_url}/issues", author), params: { confidential: true }
-
- expect_paginated_array_response(confidential_issue.id)
- end
-
- it 'returns only public issues' do
- get api("#{base_url}/issues", author), params: { confidential: false }
-
- expect_paginated_array_response([issue.id, closed_issue.id])
- end
-
- it 'returns project confidential issues for assignee' do
- get api("#{base_url}/issues", assignee)
-
- expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
- end
-
- it 'returns project issues with confidential issues for project members' do
- get api("#{base_url}/issues", user)
-
- expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
- end
-
- it 'returns project confidential issues for admin' do
- get api("#{base_url}/issues", admin)
-
- expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
- end
-
- it 'returns an array of labeled project issues' do
- get api("#{base_url}/issues", user), params: { labels: label.title }
-
- expect_paginated_array_response(issue.id)
- end
-
- it 'returns an array of labeled project issues with labels param as array' do
- get api("#{base_url}/issues", user), params: { labels: [label.title] }
-
- expect_paginated_array_response(issue.id)
- end
-
- it 'returns an array of labeled issues when all labels matches' do
- label_b = create(:label, title: 'foo', project: project)
- label_c = create(:label, title: 'bar', project: project)
-
- create(:label_link, label: label_b, target: issue)
- create(:label_link, label: label_c, target: issue)
-
- get api("#{base_url}/issues", user), params: { labels: "#{label.title},#{label_b.title},#{label_c.title}" }
-
- expect_paginated_array_response(issue.id)
- end
-
- it 'returns an array of labeled issues when all labels matches with labels param as array' do
- label_b = create(:label, title: 'foo', project: project)
- label_c = create(:label, title: 'bar', project: project)
-
- create(:label_link, label: label_b, target: issue)
- create(:label_link, label: label_c, target: issue)
-
- get api("#{base_url}/issues", user), params: { labels: [label.title, label_b.title, label_c.title] }
-
- expect_paginated_array_response(issue.id)
- end
-
- it 'returns issues matching given search string for title' do
- get api("#{base_url}/issues?search=#{issue.title}", user)
-
- expect_paginated_array_response(issue.id)
- end
-
- it 'returns issues matching given search string for description' do
- get api("#{base_url}/issues?search=#{issue.description}", user)
-
- expect_paginated_array_response(issue.id)
- end
-
- it 'returns an array of issues found by iids' do
- get api("#{base_url}/issues", user), params: { iids: [issue.iid] }
-
- expect_paginated_array_response(issue.id)
- end
-
- it 'returns an empty array if iid does not exist' do
- get api("#{base_url}/issues", user), params: { iids: [0] }
-
- expect_paginated_array_response([])
- end
-
- it 'returns an empty array if not all labels matches' do
- get api("#{base_url}/issues?labels=#{label.title},foo", user)
-
- expect_paginated_array_response([])
- end
-
- it 'returns an array of project issues with any label' do
- get api("#{base_url}/issues", user), params: { labels: IssuesFinder::FILTER_ANY }
-
- expect_paginated_array_response(issue.id)
- end
-
- it 'returns an array of project issues with any label with labels param as array' do
- get api("#{base_url}/issues", user), params: { labels: [IssuesFinder::FILTER_ANY] }
-
- expect_paginated_array_response(issue.id)
- end
-
- it 'returns an array of project issues with no label' do
- get api("#{base_url}/issues", user), params: { labels: IssuesFinder::FILTER_NONE }
-
- expect_paginated_array_response([confidential_issue.id, closed_issue.id])
- end
-
- it 'returns an array of project issues with no label with labels param as array' do
- get api("#{base_url}/issues", user), params: { labels: [IssuesFinder::FILTER_NONE] }
-
- expect_paginated_array_response([confidential_issue.id, closed_issue.id])
- end
-
- it 'returns an empty array if no project issue matches labels' do
- get api("#{base_url}/issues", user), params: { labels: 'foo,bar' }
-
- expect_paginated_array_response([])
- end
-
- it 'returns an empty array if no issue matches milestone' do
- get api("#{base_url}/issues", user), params: { milestone: empty_milestone.title }
-
- expect_paginated_array_response([])
- end
-
- it 'returns an empty array if milestone does not exist' do
- get api("#{base_url}/issues", user), params: { milestone: :foo }
-
- expect_paginated_array_response([])
- end
-
- it 'returns an array of issues in given milestone' do
- get api("#{base_url}/issues", user), params: { milestone: milestone.title }
-
- expect_paginated_array_response([issue.id, closed_issue.id])
- end
-
- it 'returns an array of issues matching state in milestone' do
- get api("#{base_url}/issues", user), params: { milestone: milestone.title, state: :closed }
-
- expect_paginated_array_response(closed_issue.id)
- end
-
- it 'returns an array of issues with no milestone' do
- get api("#{base_url}/issues", user), params: { milestone: no_milestone_title }
-
- expect_paginated_array_response(confidential_issue.id)
- end
-
- it 'returns an array of issues with any milestone' do
- get api("#{base_url}/issues", user), params: { milestone: any_milestone_title }
-
- expect_paginated_array_response([issue.id, closed_issue.id])
- end
-
- context 'without sort params' do
- it 'sorts by created_at descending by default' do
- get api("#{base_url}/issues", user)
-
- expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
- end
-
- context 'with 2 issues with same created_at' do
- let!(:closed_issue2) do
- create :closed_issue,
- author: user,
- assignees: [user],
- project: project,
- milestone: milestone,
- created_at: closed_issue.created_at,
- updated_at: 1.hour.ago,
- title: issue_title,
- description: issue_description
- end
-
- it 'page breaks first page correctly' do
- get api("#{base_url}/issues?per_page=3", user)
-
- expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue2.id])
- end
-
- it 'page breaks second page correctly' do
- get api("#{base_url}/issues?per_page=3&page=2", user)
-
- expect_paginated_array_response([closed_issue.id])
- end
- end
- end
-
- it 'sorts ascending when requested' do
- get api("#{base_url}/issues", user), params: { sort: :asc }
-
- expect_paginated_array_response([closed_issue.id, confidential_issue.id, issue.id])
- end
-
- it 'sorts by updated_at descending when requested' do
- get api("#{base_url}/issues", user), params: { order_by: :updated_at }
-
- issue.touch(:updated_at)
-
- expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
- end
-
- it 'sorts by updated_at ascending when requested' do
- get api("#{base_url}/issues", user), params: { order_by: :updated_at, sort: :asc }
-
- expect_paginated_array_response([closed_issue.id, confidential_issue.id, issue.id])
- end
- end
-
- describe "GET /projects/:id/issues/:issue_iid" do
- context 'when unauthenticated' do
- it 'returns public issues' do
- get api("/projects/#{project.id}/issues/#{issue.iid}")
-
- expect(response).to have_gitlab_http_status(200)
- end
- end
-
- it 'exposes known attributes' do
- get api("/projects/#{project.id}/issues/#{issue.iid}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['id']).to eq(issue.id)
- expect(json_response['iid']).to eq(issue.iid)
- expect(json_response['project_id']).to eq(issue.project.id)
- expect(json_response['title']).to eq(issue.title)
- expect(json_response['description']).to eq(issue.description)
- expect(json_response['state']).to eq(issue.state)
- expect(json_response['closed_at']).to be_falsy
- expect(json_response['created_at']).to be_present
- expect(json_response['updated_at']).to be_present
- expect(json_response['labels']).to eq(issue.label_names)
- expect(json_response['milestone']).to be_a Hash
- expect(json_response['assignees']).to be_a Array
- expect(json_response['assignee']).to be_a Hash
- expect(json_response['author']).to be_a Hash
- expect(json_response['confidential']).to be_falsy
- end
-
- it "exposes the 'closed_at' attribute" do
- get api("/projects/#{project.id}/issues/#{closed_issue.iid}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['closed_at']).to be_present
- end
-
- context 'links exposure' do
- it 'exposes related resources full URIs' do
- get api("/projects/#{project.id}/issues/#{issue.iid}", user)
-
- links = json_response['_links']
-
- expect(links['self']).to end_with("/api/v4/projects/#{project.id}/issues/#{issue.iid}")
- expect(links['notes']).to end_with("/api/v4/projects/#{project.id}/issues/#{issue.iid}/notes")
- expect(links['award_emoji']).to end_with("/api/v4/projects/#{project.id}/issues/#{issue.iid}/award_emoji")
- expect(links['project']).to end_with("/api/v4/projects/#{project.id}")
- end
- end
-
- it "returns a project issue by internal id" do
- get api("/projects/#{project.id}/issues/#{issue.iid}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq(issue.title)
- expect(json_response['iid']).to eq(issue.iid)
- end
-
- it "returns 404 if issue id not found" do
- get api("/projects/#{project.id}/issues/54321", user)
- expect(response).to have_gitlab_http_status(404)
- end
-
- it "returns 404 if the issue ID is used" do
- get api("/projects/#{project.id}/issues/#{issue.id}", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- context 'confidential issues' do
- it "returns 404 for non project members" do
- get api("/projects/#{project.id}/issues/#{confidential_issue.iid}", non_member)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it "returns 404 for project members with guest role" do
- get api("/projects/#{project.id}/issues/#{confidential_issue.iid}", guest)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it "returns confidential issue for project members" do
- get api("/projects/#{project.id}/issues/#{confidential_issue.iid}", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq(confidential_issue.title)
- expect(json_response['iid']).to eq(confidential_issue.iid)
- end
-
- it "returns confidential issue for author" do
- get api("/projects/#{project.id}/issues/#{confidential_issue.iid}", author)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq(confidential_issue.title)
- expect(json_response['iid']).to eq(confidential_issue.iid)
- end
-
- it "returns confidential issue for assignee" do
- get api("/projects/#{project.id}/issues/#{confidential_issue.iid}", assignee)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq(confidential_issue.title)
- expect(json_response['iid']).to eq(confidential_issue.iid)
- end
-
- it "returns confidential issue for admin" do
- get api("/projects/#{project.id}/issues/#{confidential_issue.iid}", admin)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq(confidential_issue.title)
- expect(json_response['iid']).to eq(confidential_issue.iid)
- end
- end
- end
-
- describe "POST /projects/:id/issues" do
- context 'support for deprecated assignee_id' do
- it 'creates a new project issue' do
- post api("/projects/#{project.id}/issues", user),
- params: { title: 'new issue', assignee_id: user2.id }
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('new issue')
- expect(json_response['assignee']['name']).to eq(user2.name)
- expect(json_response['assignees'].first['name']).to eq(user2.name)
- end
-
- it 'creates a new project issue when assignee_id is empty' do
- post api("/projects/#{project.id}/issues", user),
- params: { title: 'new issue', assignee_id: '' }
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('new issue')
- expect(json_response['assignee']).to be_nil
- end
- end
-
- context 'single assignee restrictions' do
- it 'creates a new project issue with no more than one assignee' do
- post api("/projects/#{project.id}/issues", user),
- params: { title: 'new issue', assignee_ids: [user2.id, guest.id] }
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('new issue')
- expect(json_response['assignees'].count).to eq(1)
- end
- end
-
- context 'user does not have permissions to create issue' do
- let(:not_member) { create(:user) }
-
- before do
- project.project_feature.update(issues_access_level: ProjectFeature::PRIVATE)
- end
-
- it 'renders 403' do
- post api("/projects/#{project.id}/issues", not_member), params: { title: 'new issue' }
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- context 'an internal ID is provided' do
- context 'by an admin' do
- it 'sets the internal ID on the new issue' do
- post api("/projects/#{project.id}/issues", admin),
- params: { title: 'new issue', iid: 9001 }
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['iid']).to eq 9001
- end
- end
-
- context 'by an owner' do
- it 'sets the internal ID on the new issue' do
- post api("/projects/#{project.id}/issues", user),
- params: { title: 'new issue', iid: 9001 }
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['iid']).to eq 9001
- end
- end
-
- context 'by a group owner' do
- let(:group) { create(:group) }
- let(:group_project) { create(:project, :public, namespace: group) }
-
- it 'sets the internal ID on the new issue' do
- group.add_owner(user2)
- post api("/projects/#{group_project.id}/issues", user2),
- params: { title: 'new issue', iid: 9001 }
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['iid']).to eq 9001
- end
- end
-
- context 'by another user' do
- it 'ignores the given internal ID' do
- post api("/projects/#{project.id}/issues", user2),
- params: { title: 'new issue', iid: 9001 }
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['iid']).not_to eq 9001
- end
- end
- end
-
- it 'creates a new project issue' do
- post api("/projects/#{project.id}/issues", user),
- params: { title: 'new issue', labels: 'label, label2', weight: 3, assignee_ids: [user2.id] }
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('new issue')
- expect(json_response['description']).to be_nil
- expect(json_response['labels']).to eq(%w(label label2))
- expect(json_response['confidential']).to be_falsy
- expect(json_response['assignee']['name']).to eq(user2.name)
- expect(json_response['assignees'].first['name']).to eq(user2.name)
- end
-
- it 'creates a new project issue with labels param as array' do
- post api("/projects/#{project.id}/issues", user),
- params: { title: 'new issue', labels: %w(label label2), weight: 3, assignee_ids: [user2.id] }
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('new issue')
- expect(json_response['description']).to be_nil
- expect(json_response['labels']).to eq(%w(label label2))
- expect(json_response['confidential']).to be_falsy
- expect(json_response['assignee']['name']).to eq(user2.name)
- expect(json_response['assignees'].first['name']).to eq(user2.name)
- end
-
- it 'creates a new confidential project issue' do
- post api("/projects/#{project.id}/issues", user),
- params: { title: 'new issue', confidential: true }
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('new issue')
- expect(json_response['confidential']).to be_truthy
- end
-
- it 'creates a new confidential project issue with a different param' do
- post api("/projects/#{project.id}/issues", user),
- params: { title: 'new issue', confidential: 'y' }
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('new issue')
- expect(json_response['confidential']).to be_truthy
- end
-
- it 'creates a public issue when confidential param is false' do
- post api("/projects/#{project.id}/issues", user),
- params: { title: 'new issue', confidential: false }
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('new issue')
- expect(json_response['confidential']).to be_falsy
- end
-
- it 'creates a public issue when confidential param is invalid' do
- post api("/projects/#{project.id}/issues", user),
- params: { title: 'new issue', confidential: 'foo' }
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['error']).to eq('confidential is invalid')
- end
-
- it "returns a 400 bad request if title not given" do
- post api("/projects/#{project.id}/issues", user), params: { labels: 'label, label2' }
- expect(response).to have_gitlab_http_status(400)
- end
-
- it 'allows special label names' do
- post api("/projects/#{project.id}/issues", user),
- params: {
- title: 'new issue',
- labels: 'label, label?, label&foo, ?, &'
- }
- expect(response.status).to eq(201)
- expect(json_response['labels']).to include 'label'
- expect(json_response['labels']).to include 'label?'
- expect(json_response['labels']).to include 'label&foo'
- expect(json_response['labels']).to include '?'
- expect(json_response['labels']).to include '&'
- end
-
- it 'allows special label names with labels param as array' do
- post api("/projects/#{project.id}/issues", user),
- params: {
- title: 'new issue',
- labels: ['label', 'label?', 'label&foo, ?, &']
- }
- expect(response.status).to eq(201)
- expect(json_response['labels']).to include 'label'
- expect(json_response['labels']).to include 'label?'
- expect(json_response['labels']).to include 'label&foo'
- expect(json_response['labels']).to include '?'
- expect(json_response['labels']).to include '&'
- end
-
- it 'returns 400 if title is too long' do
- post api("/projects/#{project.id}/issues", user),
- params: { title: 'g' * 256 }
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']['title']).to eq([
- 'is too long (maximum is 255 characters)'
- ])
- end
-
- context 'resolving discussions' do
- let(:discussion) { create(:diff_note_on_merge_request).to_discussion }
- let(:merge_request) { discussion.noteable }
- let(:project) { merge_request.source_project }
-
- before do
- project.add_maintainer(user)
- end
-
- context 'resolving all discussions in a merge request' do
- before do
- post api("/projects/#{project.id}/issues", user),
- params: {
- title: 'New Issue',
- merge_request_to_resolve_discussions_of: merge_request.iid
- }
- end
-
- it_behaves_like 'creating an issue resolving discussions through the API'
- end
-
- context 'resolving a single discussion' do
- before do
- post api("/projects/#{project.id}/issues", user),
- params: {
- title: 'New Issue',
- merge_request_to_resolve_discussions_of: merge_request.iid,
- discussion_to_resolve: discussion.id
- }
- end
-
- it_behaves_like 'creating an issue resolving discussions through the API'
- end
- end
-
- context 'with due date' do
- it 'creates a new project issue' do
- due_date = 2.weeks.from_now.strftime('%Y-%m-%d')
-
- post api("/projects/#{project.id}/issues", user),
- params: { title: 'new issue', due_date: due_date }
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['title']).to eq('new issue')
- expect(json_response['description']).to be_nil
- expect(json_response['due_date']).to eq(due_date)
- end
- end
-
- context 'setting created_at' do
- let(:creation_time) { 2.weeks.ago }
- let(:params) { { title: 'new issue', labels: 'label, label2', created_at: creation_time } }
-
- context 'by an admin' do
- it 'sets the creation time on the new issue' do
- post api("/projects/#{project.id}/issues", admin), params: params
-
- expect(response).to have_gitlab_http_status(201)
- expect(Time.parse(json_response['created_at'])).to be_like_time(creation_time)
- end
- end
-
- context 'by a project owner' do
- it 'sets the creation time on the new issue' do
- post api("/projects/#{project.id}/issues", user), params: params
-
- expect(response).to have_gitlab_http_status(201)
- expect(Time.parse(json_response['created_at'])).to be_like_time(creation_time)
- end
- end
-
- context 'by a group owner' do
- it 'sets the creation time on the new issue' do
- group = create(:group)
- group_project = create(:project, :public, namespace: group)
- group.add_owner(user2)
- post api("/projects/#{group_project.id}/issues", user2), params: params
-
- expect(response).to have_gitlab_http_status(201)
- expect(Time.parse(json_response['created_at'])).to be_like_time(creation_time)
- end
- end
-
- context 'by another user' do
- it 'ignores the given creation time' do
- post api("/projects/#{project.id}/issues", user2), params: params
-
- expect(response).to have_gitlab_http_status(201)
- expect(Time.parse(json_response['created_at'])).not_to be_like_time(creation_time)
- end
- end
- end
-
- context 'the user can only read the issue' do
- it 'cannot create new labels' do
- expect do
- post api("/projects/#{project.id}/issues", non_member), params: { title: 'new issue', labels: 'label, label2' }
- end.not_to change { project.labels.count }
- end
-
- it 'cannot create new labels with labels param as array' do
- expect do
- post api("/projects/#{project.id}/issues", non_member), params: { title: 'new issue', labels: %w(label label2) }
- end.not_to change { project.labels.count }
- end
- end
- end
-
- describe 'POST /projects/:id/issues with spam filtering' do
- before do
- allow_any_instance_of(SpamService).to receive(:check_for_spam?).and_return(true)
- allow_any_instance_of(AkismetService).to receive_messages(spam?: true)
- end
-
- let(:params) do
- {
- title: 'new issue',
- description: 'content here',
- labels: 'label, label2'
- }
- end
-
- it "does not create a new project issue" do
- expect { post api("/projects/#{project.id}/issues", user), params: params }.not_to change(Issue, :count)
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']).to eq({ "error" => "Spam detected" })
-
- spam_logs = SpamLog.all
- expect(spam_logs.count).to eq(1)
- expect(spam_logs[0].title).to eq('new issue')
- expect(spam_logs[0].description).to eq('content here')
- expect(spam_logs[0].user).to eq(user)
- expect(spam_logs[0].noteable_type).to eq('Issue')
- end
- end
-
- describe "PUT /projects/:id/issues/:issue_iid to update only title" do
- it "updates a project issue" do
- put api("/projects/#{project.id}/issues/#{issue.iid}", user),
- params: { title: 'updated title' }
- expect(response).to have_gitlab_http_status(200)
-
- expect(json_response['title']).to eq('updated title')
- end
-
- it "returns 404 error if issue iid not found" do
- put api("/projects/#{project.id}/issues/44444", user),
- params: { title: 'updated title' }
- expect(response).to have_gitlab_http_status(404)
- end
-
- it "returns 404 error if issue id is used instead of the iid" do
- put api("/projects/#{project.id}/issues/#{issue.id}", user),
- params: { title: 'updated title' }
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'allows special label names' do
- put api("/projects/#{project.id}/issues/#{issue.iid}", user),
- params: {
- title: 'updated title',
- labels: 'label, label?, label&foo, ?, &'
- }
-
- expect(response.status).to eq(200)
- expect(json_response['labels']).to include 'label'
- expect(json_response['labels']).to include 'label?'
- expect(json_response['labels']).to include 'label&foo'
- expect(json_response['labels']).to include '?'
- expect(json_response['labels']).to include '&'
- end
-
- it 'allows special label names with labels param as array' do
- put api("/projects/#{project.id}/issues/#{issue.iid}", user),
- params: {
- title: 'updated title',
- labels: ['label', 'label?', 'label&foo, ?, &']
- }
-
- expect(response.status).to eq(200)
- expect(json_response['labels']).to include 'label'
- expect(json_response['labels']).to include 'label?'
- expect(json_response['labels']).to include 'label&foo'
- expect(json_response['labels']).to include '?'
- expect(json_response['labels']).to include '&'
- end
-
- context 'confidential issues' do
- it "returns 403 for non project members" do
- put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", non_member),
- params: { title: 'updated title' }
- expect(response).to have_gitlab_http_status(403)
- end
-
- it "returns 403 for project members with guest role" do
- put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", guest),
- params: { title: 'updated title' }
- expect(response).to have_gitlab_http_status(403)
- end
-
- it "updates a confidential issue for project members" do
- put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", user),
- params: { title: 'updated title' }
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq('updated title')
- end
-
- it "updates a confidential issue for author" do
- put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", author),
- params: { title: 'updated title' }
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq('updated title')
- end
-
- it "updates a confidential issue for admin" do
- put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", admin),
- params: { title: 'updated title' }
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['title']).to eq('updated title')
- end
-
- it 'sets an issue to confidential' do
- put api("/projects/#{project.id}/issues/#{issue.iid}", user),
- params: { confidential: true }
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['confidential']).to be_truthy
- end
-
- it 'makes a confidential issue public' do
- put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", user),
- params: { confidential: false }
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['confidential']).to be_falsy
- end
-
- it 'does not update a confidential issue with wrong confidential flag' do
- put api("/projects/#{project.id}/issues/#{confidential_issue.iid}", user),
- params: { confidential: 'foo' }
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['error']).to eq('confidential is invalid')
- end
- end
- end
-
- describe 'PUT /projects/:id/issues/:issue_iid with spam filtering' do
- let(:params) do
- {
- title: 'updated title',
- description: 'content here',
- labels: 'label, label2'
- }
- end
-
- it "does not create a new project issue" do
- allow_any_instance_of(SpamService).to receive_messages(check_for_spam?: true)
- allow_any_instance_of(AkismetService).to receive_messages(spam?: true)
-
- put api("/projects/#{project.id}/issues/#{issue.iid}", user), params: params
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']).to eq({ "error" => "Spam detected" })
-
- spam_logs = SpamLog.all
- expect(spam_logs.count).to eq(1)
- expect(spam_logs[0].title).to eq('updated title')
- expect(spam_logs[0].description).to eq('content here')
- expect(spam_logs[0].user).to eq(user)
- expect(spam_logs[0].noteable_type).to eq('Issue')
- end
- end
-
- describe 'PUT /projects/:id/issues/:issue_iid to update assignee' do
- context 'support for deprecated assignee_id' do
- it 'removes assignee' do
- put api("/projects/#{project.id}/issues/#{issue.iid}", user),
- params: { assignee_id: 0 }
-
- expect(response).to have_gitlab_http_status(200)
-
- expect(json_response['assignee']).to be_nil
- end
-
- it 'updates an issue with new assignee' do
- put api("/projects/#{project.id}/issues/#{issue.iid}", user),
- params: { assignee_id: user2.id }
-
- expect(response).to have_gitlab_http_status(200)
-
- expect(json_response['assignee']['name']).to eq(user2.name)
- end
- end
-
- it 'removes assignee' do
- put api("/projects/#{project.id}/issues/#{issue.iid}", user),
- params: { assignee_ids: [0] }
-
- expect(response).to have_gitlab_http_status(200)
-
- expect(json_response['assignees']).to be_empty
- end
-
- it 'updates an issue with new assignee' do
- put api("/projects/#{project.id}/issues/#{issue.iid}", user),
- params: { assignee_ids: [user2.id] }
-
- expect(response).to have_gitlab_http_status(200)
-
- expect(json_response['assignees'].first['name']).to eq(user2.name)
- end
-
- context 'single assignee restrictions' do
- it 'updates an issue with several assignees but only one has been applied' do
- put api("/projects/#{project.id}/issues/#{issue.iid}", user),
- params: { assignee_ids: [user2.id, guest.id] }
-
- expect(response).to have_gitlab_http_status(200)
-
- expect(json_response['assignees'].size).to eq(1)
- end
- end
- end
-
- describe 'PUT /projects/:id/issues/:issue_iid to update labels' do
- let!(:label) { create(:label, title: 'dummy', project: project) }
- let!(:label_link) { create(:label_link, label: label, target: issue) }
-
- it 'does not update labels if not present' do
- put api("/projects/#{project.id}/issues/#{issue.iid}", user),
- params: { title: 'updated title' }
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['labels']).to eq([label.title])
- end
-
- it 'removes all labels and touches the record' do
- Timecop.travel(1.minute.from_now) do
- put api("/projects/#{project.id}/issues/#{issue.iid}", user), params: { labels: '' }
- end
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['labels']).to eq([])
- expect(json_response['updated_at']).to be > Time.now
- end
-
- it 'removes all labels and touches the record with labels param as array' do
- Timecop.travel(1.minute.from_now) do
- put api("/projects/#{project.id}/issues/#{issue.iid}", user), params: { labels: [''] }
- end
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['labels']).to eq([])
- expect(json_response['updated_at']).to be > Time.now
- end
-
- it 'updates labels and touches the record' do
- Timecop.travel(1.minute.from_now) do
- put api("/projects/#{project.id}/issues/#{issue.iid}", user),
- params: { labels: 'foo,bar' }
- end
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['labels']).to include 'foo'
- expect(json_response['labels']).to include 'bar'
- expect(json_response['updated_at']).to be > Time.now
- end
-
- it 'updates labels and touches the record with labels param as array' do
- Timecop.travel(1.minute.from_now) do
- put api("/projects/#{project.id}/issues/#{issue.iid}", user),
- params: { labels: %w(foo bar) }
- end
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['labels']).to include 'foo'
- expect(json_response['labels']).to include 'bar'
- expect(json_response['updated_at']).to be > Time.now
- end
-
- it 'allows special label names' do
- put api("/projects/#{project.id}/issues/#{issue.iid}", user),
- params: { labels: 'label:foo, label-bar,label_bar,label/bar,label?bar,label&bar,?,&' }
- expect(response.status).to eq(200)
- expect(json_response['labels']).to include 'label:foo'
- expect(json_response['labels']).to include 'label-bar'
- expect(json_response['labels']).to include 'label_bar'
- expect(json_response['labels']).to include 'label/bar'
- expect(json_response['labels']).to include 'label?bar'
- expect(json_response['labels']).to include 'label&bar'
- expect(json_response['labels']).to include '?'
- expect(json_response['labels']).to include '&'
- end
-
- it 'allows special label names with labels param as array' do
- put api("/projects/#{project.id}/issues/#{issue.iid}", user),
- params: { labels: ['label:foo', 'label-bar', 'label_bar', 'label/bar,label?bar,label&bar,?,&'] }
- expect(response.status).to eq(200)
- expect(json_response['labels']).to include 'label:foo'
- expect(json_response['labels']).to include 'label-bar'
- expect(json_response['labels']).to include 'label_bar'
- expect(json_response['labels']).to include 'label/bar'
- expect(json_response['labels']).to include 'label?bar'
- expect(json_response['labels']).to include 'label&bar'
- expect(json_response['labels']).to include '?'
- expect(json_response['labels']).to include '&'
- end
-
- it 'returns 400 if title is too long' do
- put api("/projects/#{project.id}/issues/#{issue.iid}", user),
- params: { title: 'g' * 256 }
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']['title']).to eq([
- 'is too long (maximum is 255 characters)'
- ])
- end
- end
-
- describe "PUT /projects/:id/issues/:issue_iid to update state and label" do
- it "updates a project issue" do
- put api("/projects/#{project.id}/issues/#{issue.iid}", user),
- params: { labels: 'label2', state_event: "close" }
- expect(response).to have_gitlab_http_status(200)
-
- expect(json_response['labels']).to include 'label2'
- expect(json_response['state']).to eq "closed"
- end
-
- it 'reopens a project isssue' do
- put api("/projects/#{project.id}/issues/#{closed_issue.iid}", user), params: { state_event: 'reopen' }
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['state']).to eq 'opened'
- end
-
- context 'when an admin or owner makes the request' do
- it 'accepts the update date to be set' do
- update_time = 2.weeks.ago
- put api("/projects/#{project.id}/issues/#{issue.iid}", user),
- params: { labels: 'label3', state_event: 'close', updated_at: update_time }
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['labels']).to include 'label3'
- expect(Time.parse(json_response['updated_at'])).to be_like_time(update_time)
- end
- end
- end
-
- describe 'PUT /projects/:id/issues/:issue_iid to update due date' do
- it 'creates a new project issue' do
- due_date = 2.weeks.from_now.strftime('%Y-%m-%d')
-
- put api("/projects/#{project.id}/issues/#{issue.iid}", user), params: { due_date: due_date }
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['due_date']).to eq(due_date)
- end
- end
-
- describe "DELETE /projects/:id/issues/:issue_iid" do
- it "rejects a non member from deleting an issue" do
- delete api("/projects/#{project.id}/issues/#{issue.iid}", non_member)
- expect(response).to have_gitlab_http_status(403)
- end
-
- it "rejects a developer from deleting an issue" do
- delete api("/projects/#{project.id}/issues/#{issue.iid}", author)
- expect(response).to have_gitlab_http_status(403)
- end
-
- context "when the user is project owner" do
- let(:owner) { create(:user) }
- let(:project) { create(:project, namespace: owner.namespace) }
-
- it "deletes the issue if an admin requests it" do
- delete api("/projects/#{project.id}/issues/#{issue.iid}", owner)
-
- expect(response).to have_gitlab_http_status(204)
- end
-
- it_behaves_like '412 response' do
- let(:request) { api("/projects/#{project.id}/issues/#{issue.iid}", owner) }
- end
- end
-
- context 'when issue does not exist' do
- it 'returns 404 when trying to move an issue' do
- delete api("/projects/#{project.id}/issues/123", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- it 'returns 404 when using the issue ID instead of IID' do
- delete api("/projects/#{project.id}/issues/#{issue.id}", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe '/projects/:id/issues/:issue_iid/move' do
- let!(:target_project) { create(:project, creator_id: user.id, namespace: user.namespace ) }
- let!(:target_project2) { create(:project, creator_id: non_member.id, namespace: non_member.namespace ) }
-
- it 'moves an issue' do
- post api("/projects/#{project.id}/issues/#{issue.iid}/move", user),
- params: { to_project_id: target_project.id }
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['project_id']).to eq(target_project.id)
- end
-
- context 'when source and target projects are the same' do
- it 'returns 400 when trying to move an issue' do
- post api("/projects/#{project.id}/issues/#{issue.iid}/move", user),
- params: { to_project_id: project.id }
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']).to eq('Cannot move issue to project it originates from!')
- end
- end
-
- context 'when the user does not have the permission to move issues' do
- it 'returns 400 when trying to move an issue' do
- post api("/projects/#{project.id}/issues/#{issue.iid}/move", user),
- params: { to_project_id: target_project2.id }
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']).to eq('Cannot move issue due to insufficient permissions!')
- end
- end
-
- it 'moves the issue to another namespace if I am admin' do
- post api("/projects/#{project.id}/issues/#{issue.iid}/move", admin),
- params: { to_project_id: target_project2.id }
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['project_id']).to eq(target_project2.id)
- end
-
- context 'when using the issue ID instead of iid' do
- it 'returns 404 when trying to move an issue' do
- post api("/projects/#{project.id}/issues/#{issue.id}/move", user),
- params: { to_project_id: target_project.id }
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 Issue Not Found')
- end
- end
-
- context 'when issue does not exist' do
- it 'returns 404 when trying to move an issue' do
- post api("/projects/#{project.id}/issues/123/move", user),
- params: { to_project_id: target_project.id }
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 Issue Not Found')
- end
- end
-
- context 'when source project does not exist' do
- it 'returns 404 when trying to move an issue' do
- post api("/projects/0/issues/#{issue.iid}/move", user),
- params: { to_project_id: target_project.id }
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 Project Not Found')
- end
- end
-
- context 'when target project does not exist' do
- it 'returns 404 when trying to move an issue' do
- post api("/projects/#{project.id}/issues/#{issue.iid}/move", user),
- params: { to_project_id: 0 }
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
- end
-
- describe 'POST :id/issues/:issue_iid/subscribe' do
- it 'subscribes to an issue' do
- post api("/projects/#{project.id}/issues/#{issue.iid}/subscribe", user2)
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['subscribed']).to eq(true)
- end
-
- it 'returns 304 if already subscribed' do
- post api("/projects/#{project.id}/issues/#{issue.iid}/subscribe", user)
-
- expect(response).to have_gitlab_http_status(304)
- end
-
- it 'returns 404 if the issue is not found' do
- post api("/projects/#{project.id}/issues/123/subscribe", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns 404 if the issue ID is used instead of the iid' do
- post api("/projects/#{project.id}/issues/#{issue.id}/subscribe", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns 404 if the issue is confidential' do
- post api("/projects/#{project.id}/issues/#{confidential_issue.iid}/subscribe", non_member)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe 'POST :id/issues/:issue_id/unsubscribe' do
- it 'unsubscribes from an issue' do
- post api("/projects/#{project.id}/issues/#{issue.iid}/unsubscribe", user)
-
- expect(response).to have_gitlab_http_status(201)
- expect(json_response['subscribed']).to eq(false)
- end
-
- it 'returns 304 if not subscribed' do
- post api("/projects/#{project.id}/issues/#{issue.iid}/unsubscribe", user2)
-
- expect(response).to have_gitlab_http_status(304)
- end
-
- it 'returns 404 if the issue is not found' do
- post api("/projects/#{project.id}/issues/123/unsubscribe", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns 404 if using the issue ID instead of iid' do
- post api("/projects/#{project.id}/issues/#{issue.id}/unsubscribe", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'returns 404 if the issue is confidential' do
- post api("/projects/#{project.id}/issues/#{confidential_issue.iid}/unsubscribe", non_member)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe 'time tracking endpoints' do
- let(:issuable) { issue }
-
- include_examples 'time tracking endpoints', 'issue'
- end
-
- describe 'GET :id/issues/:issue_iid/closed_by' do
- let(:merge_request) do
- create(:merge_request,
- :simple,
- author: user,
- source_project: project,
- target_project: project,
- description: "closes #{issue.to_reference}")
- end
-
- before do
- create(:merge_requests_closing_issues, issue: issue, merge_request: merge_request)
- end
-
- context 'when unauthenticated' do
- it 'return public project issues' do
- get api("/projects/#{project.id}/issues/#{issue.iid}/closed_by")
-
- expect_paginated_array_response(merge_request.id)
- end
- end
-
- it 'returns merge requests that will close issue on merge' do
- get api("/projects/#{project.id}/issues/#{issue.iid}/closed_by", user)
-
- expect_paginated_array_response(merge_request.id)
- end
-
- context 'when no merge requests will close issue' do
- it 'returns empty array' do
- get api("/projects/#{project.id}/issues/#{closed_issue.iid}/closed_by", user)
-
- expect_paginated_array_response([])
- end
- end
-
- it "returns 404 when issue doesn't exists" do
- get api("/projects/#{project.id}/issues/0/closed_by", user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe 'GET :id/issues/:issue_iid/related_merge_requests' do
- def get_related_merge_requests(project_id, issue_iid, user = nil)
- get api("/projects/#{project_id}/issues/#{issue_iid}/related_merge_requests", user)
- end
-
- def create_referencing_mr(user, project, issue)
- attributes = {
- author: user,
- source_project: project,
- target_project: project,
- source_branch: "master",
- target_branch: "test",
- description: "See #{issue.to_reference}"
- }
- create(:merge_request, attributes).tap do |merge_request|
- create(:note, :system, project: issue.project, noteable: issue, author: user, note: merge_request.to_reference(full: true))
- end
- end
-
- let!(:related_mr) { create_referencing_mr(user, project, issue) }
-
- context 'when unauthenticated' do
- it 'return list of referenced merge requests from issue' do
- get_related_merge_requests(project.id, issue.iid)
-
- expect_paginated_array_response(related_mr.id)
- end
-
- it 'renders 404 if project is not visible' do
- private_project = create(:project, :private)
- private_issue = create(:issue, project: private_project)
- create_referencing_mr(user, private_project, private_issue)
-
- get_related_merge_requests(private_project.id, private_issue.iid)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- it 'returns merge requests that mentioned a issue' do
- create(:merge_request,
- :simple,
- author: user,
- source_project: project,
- target_project: project,
- description: "Some description")
-
- get_related_merge_requests(project.id, issue.iid, user)
-
- expect_paginated_array_response(related_mr.id)
- end
-
- it 'returns merge requests cross-project wide' do
- project2 = create(:project, :public, creator_id: user.id, namespace: user.namespace)
- merge_request = create_referencing_mr(user, project2, issue)
-
- get_related_merge_requests(project.id, issue.iid, user)
-
- expect_paginated_array_response([related_mr.id, merge_request.id])
- end
-
- it 'does not generate references to projects with no access' do
- private_project = create(:project, :private)
- create_referencing_mr(private_project.creator, private_project, issue)
-
- get_related_merge_requests(project.id, issue.iid, user)
-
- expect_paginated_array_response(related_mr.id)
- end
-
- context 'merge request closes an issue' do
- let!(:closing_issue_mr_rel) do
- create(:merge_requests_closing_issues, issue: issue, merge_request: related_mr)
- end
-
- it 'returns closing MR only once' do
- get_related_merge_requests(project.id, issue.iid, user)
-
- expect_paginated_array_response([related_mr.id])
- end
- end
-
- context 'no merge request mentioned a issue' do
- it 'returns empty array' do
- get_related_merge_requests(project.id, closed_issue.iid, user)
-
- expect_paginated_array_response([])
- end
- end
-
- it "returns 404 when issue doesn't exists" do
- get_related_merge_requests(project.id, 0, user)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-
- describe "GET /projects/:id/issues/:issue_iid/user_agent_detail" do
- let!(:user_agent_detail) { create(:user_agent_detail, subject: issue) }
-
- context 'when unauthenticated' do
- it "returns unauthorized" do
- get api("/projects/#{project.id}/issues/#{issue.iid}/user_agent_detail")
-
- expect(response).to have_gitlab_http_status(401)
- end
- end
-
- it 'exposes known attributes' do
- get api("/projects/#{project.id}/issues/#{issue.iid}/user_agent_detail", admin)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response['user_agent']).to eq(user_agent_detail.user_agent)
- expect(json_response['ip_address']).to eq(user_agent_detail.ip_address)
- expect(json_response['akismet_submitted']).to eq(user_agent_detail.submitted)
- end
-
- it "returns unauthorized for non-admin users" do
- get api("/projects/#{project.id}/issues/#{issue.iid}/user_agent_detail", user)
-
- expect(response).to have_gitlab_http_status(403)
- end
- end
-
- describe 'GET projects/:id/issues/:issue_iid/participants' do
- it_behaves_like 'issuable participants endpoint' do
- let(:entity) { issue }
- end
-
- it 'returns 404 if the issue is confidential' do
- post api("/projects/#{project.id}/issues/#{confidential_issue.iid}/participants", non_member)
-
- expect(response).to have_gitlab_http_status(404)
- end
- end
-end
diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb
index ed2ef4c730b..89ee6f896f9 100644
--- a/spec/requests/api/jobs_spec.rb
+++ b/spec/requests/api/jobs_spec.rb
@@ -286,6 +286,7 @@ describe API::Jobs do
expect(json_response['ref']).to eq(job.ref)
expect(json_response['tag']).to eq(job.tag)
expect(json_response['coverage']).to eq(job.coverage)
+ expect(json_response['allow_failure']).to eq(job.allow_failure)
expect(Time.parse(json_response['created_at'])).to be_like_time(job.created_at)
expect(Time.parse(json_response['started_at'])).to be_like_time(job.started_at)
expect(Time.parse(json_response['finished_at'])).to be_like_time(job.finished_at)
@@ -912,8 +913,8 @@ describe API::Jobs do
expect(response).to have_gitlab_http_status(201)
expect(job.job_artifacts.count).to eq(0)
expect(job.trace.exist?).to be_falsy
- expect(job.artifacts_file.exists?).to be_falsy
- expect(job.artifacts_metadata.exists?).to be_falsy
+ expect(job.artifacts_file.present?).to be_falsy
+ expect(job.artifacts_metadata.present?).to be_falsy
expect(job.has_job_artifacts?).to be_falsy
end
diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb
index 79edbb301f2..55f38079b1f 100644
--- a/spec/requests/api/members_spec.rb
+++ b/spec/requests/api/members_spec.rb
@@ -132,6 +132,19 @@ describe API::Members do
expect(json_response.map { |u| u['id'] }).to match_array [maintainer.id, developer.id, nested_user.id, project_user.id, linked_group_user.id]
end
+ it 'returns only one member for each user without returning duplicated members' do
+ linked_group.add_developer(developer)
+
+ get api("/projects/#{project.id}/members/all", developer)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.map { |u| u['id'] }).to eq [developer.id, maintainer.id, nested_user.id, project_user.id, linked_group_user.id]
+ expect(json_response.map { |u| u['access_level'] }).to eq [Gitlab::Access::DEVELOPER, Gitlab::Access::OWNER, Gitlab::Access::DEVELOPER,
+ Gitlab::Access::DEVELOPER, Gitlab::Access::DEVELOPER]
+ end
+
it 'finds all group members including inherited members' do
get api("/groups/#{nested_group.id}/members/all", developer)
@@ -236,7 +249,7 @@ describe API::Members do
params: { user_id: stranger.id, access_level: Member::REPORTER }
expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']['access_level']).to eq(["should be higher than Developer inherited membership from group #{parent.name}"])
+ expect(json_response['message']['access_level']).to eq(["should be greater than or equal to Developer inherited membership from group #{parent.name}"])
end
it 'creates the member if group level is lower', :nested_groups do
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 5c94a87529b..9f9180bc8c9 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -1473,7 +1473,7 @@ describe API::MergeRequests do
end
it "enables merge when pipeline succeeds if the pipeline is active" do
- allow_any_instance_of(MergeRequest).to receive(:head_pipeline).and_return(pipeline)
+ allow_any_instance_of(MergeRequest).to receive_messages(head_pipeline: pipeline, actual_head_pipeline: pipeline)
allow(pipeline).to receive(:active?).and_return(true)
put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user), params: { merge_when_pipeline_succeeds: true }
@@ -1484,7 +1484,7 @@ describe API::MergeRequests do
end
it "enables merge when pipeline succeeds if the pipeline is active and only_allow_merge_if_pipeline_succeeds is true" do
- allow_any_instance_of(MergeRequest).to receive(:head_pipeline).and_return(pipeline)
+ allow_any_instance_of(MergeRequest).to receive_messages(head_pipeline: pipeline, actual_head_pipeline: pipeline)
allow(pipeline).to receive(:active?).and_return(true)
project.update_attribute(:only_allow_merge_if_pipeline_succeeds, true)
@@ -1950,7 +1950,7 @@ describe API::MergeRequests do
describe 'POST :id/merge_requests/:merge_request_iid/cancel_merge_when_pipeline_succeeds' do
before do
- ::MergeRequests::MergeWhenPipelineSucceedsService.new(merge_request.target_project, user).execute(merge_request)
+ ::AutoMergeService.new(merge_request.target_project, user).execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
end
it 'removes the merge_when_pipeline_succeeds status' do
diff --git a/spec/requests/api/pipeline_schedules_spec.rb b/spec/requests/api/pipeline_schedules_spec.rb
index 870ef34437f..072bd02f2ac 100644
--- a/spec/requests/api/pipeline_schedules_spec.rb
+++ b/spec/requests/api/pipeline_schedules_spec.rb
@@ -91,6 +91,7 @@ describe API::PipelineSchedules do
let(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: developer) }
before do
+ pipeline_schedule.variables << build(:ci_pipeline_schedule_variable)
pipeline_schedule.pipelines << build(:ci_pipeline, project: project)
end
@@ -331,13 +332,14 @@ describe API::PipelineSchedules do
it 'creates pipeline_schedule_variable' do
expect do
post api("/projects/#{project.id}/pipeline_schedules/#{pipeline_schedule.id}/variables", developer),
- params: params
+ params: params.merge(variable_type: 'file')
end.to change { pipeline_schedule.variables.count }.by(1)
expect(response).to have_gitlab_http_status(:created)
expect(response).to match_response_schema('pipeline_schedule_variable')
expect(json_response['key']).to eq(params[:key])
expect(json_response['value']).to eq(params[:value])
+ expect(json_response['variable_type']).to eq('file')
end
end
@@ -389,11 +391,12 @@ describe API::PipelineSchedules do
context 'authenticated user with valid permissions' do
it 'updates pipeline_schedule_variable' do
put api("/projects/#{project.id}/pipeline_schedules/#{pipeline_schedule.id}/variables/#{pipeline_schedule_variable.key}", developer),
- params: { value: 'updated_value' }
+ params: { value: 'updated_value', variable_type: 'file' }
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('pipeline_schedule_variable')
expect(json_response['value']).to eq('updated_value')
+ expect(json_response['variable_type']).to eq('file')
end
end
diff --git a/spec/requests/api/pipelines_spec.rb b/spec/requests/api/pipelines_spec.rb
index 26158231444..35b3dd219f7 100644
--- a/spec/requests/api/pipelines_spec.rb
+++ b/spec/requests/api/pipelines_spec.rb
@@ -294,6 +294,7 @@ describe API::Pipelines do
expect(variable.key).to eq(expected_variable['key'])
expect(variable.value).to eq(expected_variable['value'])
+ expect(variable.variable_type).to eq(expected_variable['variable_type'])
end
end
@@ -314,7 +315,7 @@ describe API::Pipelines do
end
context 'variables given' do
- let(:variables) { [{ 'key' => 'UPLOAD_TO_S3', 'value' => 'true' }] }
+ let(:variables) { [{ 'variable_type' => 'file', 'key' => 'UPLOAD_TO_S3', 'value' => 'true' }] }
it 'creates and returns a new pipeline using the given variables' do
expect do
@@ -330,7 +331,7 @@ describe API::Pipelines do
end
describe 'using variables conditions' do
- let(:variables) { [{ 'key' => 'STAGING', 'value' => 'true' }] }
+ let(:variables) { [{ 'variable_type' => 'env_var', 'key' => 'STAGING', 'value' => 'true' }] }
before do
config = YAML.dump(test: { script: 'test', only: { variables: ['$STAGING'] } })
@@ -467,7 +468,7 @@ describe API::Pipelines do
subject
expect(response).to have_gitlab_http_status(200)
- expect(json_response).to contain_exactly({ "key" => "foo", "value" => "bar" })
+ expect(json_response).to contain_exactly({ "variable_type" => "env_var", "key" => "foo", "value" => "bar" })
end
end
end
@@ -488,7 +489,7 @@ describe API::Pipelines do
subject
expect(response).to have_gitlab_http_status(200)
- expect(json_response).to contain_exactly({ "key" => "foo", "value" => "bar" })
+ expect(json_response).to contain_exactly({ "variable_type" => "env_var", "key" => "foo", "value" => "bar" })
end
end
diff --git a/spec/requests/api/project_clusters_spec.rb b/spec/requests/api/project_clusters_spec.rb
index 94e6ca2c07c..fc0381159dd 100644
--- a/spec/requests/api/project_clusters_spec.rb
+++ b/spec/requests/api/project_clusters_spec.rb
@@ -189,6 +189,7 @@ describe API::ProjectClusters do
{
name: 'test-cluster',
domain: 'domain.example.com',
+ managed: false,
platform_kubernetes_attributes: platform_kubernetes_attributes
}
end
@@ -220,6 +221,7 @@ describe API::ProjectClusters do
expect(cluster_result.project).to eq(project)
expect(cluster_result.name).to eq('test-cluster')
expect(cluster_result.domain).to eq('domain.example.com')
+ expect(cluster_result.managed).to be_falsy
expect(platform_kubernetes.rbac?).to be_truthy
expect(platform_kubernetes.api_url).to eq(api_url)
expect(platform_kubernetes.namespace).to eq(namespace)
@@ -349,7 +351,7 @@ describe API::ProjectClusters do
it 'does not update cluster attributes' do
expect(cluster.domain).not_to eq('new_domain.com')
expect(cluster.platform_kubernetes.namespace).not_to eq('invalid_namespace')
- expect(cluster.kubernetes_namespace.namespace).not_to eq('invalid_namespace')
+ expect(cluster.kubernetes_namespace_for(project)).not_to eq('invalid_namespace')
end
it 'returns validation errors' do
diff --git a/spec/requests/api/project_events_spec.rb b/spec/requests/api/project_events_spec.rb
new file mode 100644
index 00000000000..43df9993eb9
--- /dev/null
+++ b/spec/requests/api/project_events_spec.rb
@@ -0,0 +1,156 @@
+require 'spec_helper'
+
+describe API::ProjectEvents do
+ include ApiHelpers
+
+ let(:user) { create(:user) }
+ let(:non_member) { create(:user) }
+ let(:private_project) { create(:project, :private, creator_id: user.id, namespace: user.namespace) }
+ let(:closed_issue) { create(:closed_issue, project: private_project, author: user) }
+ let!(:closed_issue_event) { create(:event, project: private_project, author: user, target: closed_issue, action: Event::CLOSED, created_at: Date.new(2016, 12, 30)) }
+
+ describe 'GET /projects/:id/events' do
+ context 'when unauthenticated ' do
+ it 'returns 404 for private project' do
+ get api("/projects/#{private_project.id}/events")
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'returns 200 status for a public project' do
+ public_project = create(:project, :public)
+
+ get api("/projects/#{public_project.id}/events")
+
+ expect(response).to have_gitlab_http_status(200)
+ end
+ end
+
+ context 'with inaccessible events' do
+ let(:public_project) { create(:project, :public, creator_id: user.id, namespace: user.namespace) }
+ let(:confidential_issue) { create(:closed_issue, confidential: true, project: public_project, author: user) }
+ let!(:confidential_event) { create(:event, project: public_project, author: user, target: confidential_issue, action: Event::CLOSED) }
+ let(:public_issue) { create(:closed_issue, project: public_project, author: user) }
+ let!(:public_event) { create(:event, project: public_project, author: user, target: public_issue, action: Event::CLOSED) }
+
+ it 'returns only accessible events' do
+ get api("/projects/#{public_project.id}/events", non_member)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response.size).to eq(1)
+ end
+
+ it 'returns all events when the user has access' do
+ get api("/projects/#{public_project.id}/events", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response.size).to eq(2)
+ end
+ end
+
+ context 'pagination' do
+ let(:public_project) { create(:project, :public) }
+
+ before do
+ create(:event,
+ project: public_project,
+ target: create(:issue, project: public_project, title: 'Issue 1'),
+ action: Event::CLOSED,
+ created_at: Date.parse('2018-12-10'))
+ create(:event,
+ project: public_project,
+ target: create(:issue, confidential: true, project: public_project, title: 'Confidential event'),
+ action: Event::CLOSED,
+ created_at: Date.parse('2018-12-11'))
+ create(:event,
+ project: public_project,
+ target: create(:issue, project: public_project, title: 'Issue 2'),
+ action: Event::CLOSED,
+ created_at: Date.parse('2018-12-12'))
+ end
+
+ it 'correctly returns the second page without inaccessible events' do
+ get api("/projects/#{public_project.id}/events", user), params: { per_page: 2, page: 2 }
+
+ titles = json_response.map { |event| event['target_title'] }
+
+ expect(titles.first).to eq('Issue 1')
+ expect(titles).not_to include('Confidential event')
+ end
+
+ it 'correctly returns the first page without inaccessible events' do
+ get api("/projects/#{public_project.id}/events", user), params: { per_page: 2, page: 1 }
+
+ titles = json_response.map { |event| event['target_title'] }
+
+ expect(titles.first).to eq('Issue 2')
+ expect(titles).not_to include('Confidential event')
+ end
+ end
+
+ context 'when not permitted to read' do
+ it 'returns 404' do
+ get api("/projects/#{private_project.id}/events", non_member)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'when authenticated' do
+ it 'returns project events' do
+ get api("/projects/#{private_project.id}/events?action=closed&target_type=issue&after=2016-12-1&before=2016-12-31", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.size).to eq(1)
+ end
+
+ it 'returns 404 if project does not exist' do
+ get api("/projects/1234/events", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ context 'when the requesting token does not have "api" scope' do
+ let(:token) { create(:personal_access_token, scopes: ['read_user'], user: user) }
+
+ it 'returns a "403" response' do
+ get api("/projects/#{private_project.id}/events", personal_access_token: token)
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+ end
+ end
+
+ context 'when exists some events' do
+ let(:merge_request1) { create(:merge_request, :closed, author: user, assignees: [user], source_project: private_project, title: 'Test') }
+ let(:merge_request2) { create(:merge_request, :closed, author: user, assignees: [user], source_project: private_project, title: 'Test') }
+
+ before do
+ create_event(merge_request1)
+ end
+
+ it 'avoids N+1 queries' do
+ control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ get api("/projects/#{private_project.id}/events", user), params: { target_type: :merge_request }
+ end.count
+
+ create_event(merge_request2)
+
+ expect do
+ get api("/projects/#{private_project.id}/events", user), params: { target_type: :merge_request }
+ end.not_to exceed_all_query_limit(control_count)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response.size).to eq(2)
+ expect(json_response.map { |r| r['target_id'] }).to match_array([merge_request1.id, merge_request2.id])
+ end
+
+ def create_event(target)
+ create(:event, project: private_project, author: user, target: target)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 352ea448c00..5f7d2fa6d9c 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -504,8 +504,9 @@ describe API::Projects do
project4.add_reporter(user2)
end
- it 'returns an array of groups the user has at least developer access' do
+ it 'returns an array of projects the user has at least developer access' do
get api('/projects', user2), params: { min_access_level: 30 }
+
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
@@ -1024,7 +1025,54 @@ describe API::Projects do
end
end
- context 'when authenticated' do
+ context 'when authenticated as an admin' do
+ it 'returns a project by id' do
+ project
+ project_member
+ group = create(:group)
+ link = create(:project_group_link, project: project, group: group)
+
+ get api("/projects/#{project.id}", admin)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['id']).to eq(project.id)
+ expect(json_response['description']).to eq(project.description)
+ expect(json_response['default_branch']).to eq(project.default_branch)
+ expect(json_response['tag_list']).to be_an Array
+ expect(json_response['archived']).to be_falsey
+ expect(json_response['visibility']).to be_present
+ expect(json_response['ssh_url_to_repo']).to be_present
+ expect(json_response['http_url_to_repo']).to be_present
+ expect(json_response['web_url']).to be_present
+ expect(json_response['owner']).to be_a Hash
+ expect(json_response['name']).to eq(project.name)
+ expect(json_response['path']).to be_present
+ expect(json_response['issues_enabled']).to be_present
+ expect(json_response['merge_requests_enabled']).to be_present
+ expect(json_response['wiki_enabled']).to be_present
+ expect(json_response['jobs_enabled']).to be_present
+ expect(json_response['snippets_enabled']).to be_present
+ expect(json_response['container_registry_enabled']).to be_present
+ expect(json_response['created_at']).to be_present
+ expect(json_response['last_activity_at']).to be_present
+ expect(json_response['shared_runners_enabled']).to be_present
+ expect(json_response['creator_id']).to be_present
+ expect(json_response['namespace']).to be_present
+ expect(json_response['avatar_url']).to be_nil
+ expect(json_response['star_count']).to be_present
+ expect(json_response['forks_count']).to be_present
+ expect(json_response['public_jobs']).to be_present
+ expect(json_response['shared_with_groups']).to be_an Array
+ expect(json_response['shared_with_groups'].length).to eq(1)
+ expect(json_response['shared_with_groups'][0]['group_id']).to eq(group.id)
+ expect(json_response['shared_with_groups'][0]['group_name']).to eq(group.name)
+ expect(json_response['shared_with_groups'][0]['group_access_level']).to eq(link.group_access)
+ expect(json_response['only_allow_merge_if_pipeline_succeeds']).to eq(project.only_allow_merge_if_pipeline_succeeds)
+ expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to eq(project.only_allow_merge_if_all_discussions_are_resolved)
+ end
+ end
+
+ context 'when authenticated as a regular user' do
before do
project
project_member
@@ -1047,7 +1095,6 @@ describe API::Projects do
expect(json_response['http_url_to_repo']).to be_present
expect(json_response['web_url']).to be_present
expect(json_response['owner']).to be_a Hash
- expect(json_response['owner']).to be_a Hash
expect(json_response['name']).to eq(project.name)
expect(json_response['path']).to be_present
expect(json_response['issues_enabled']).to be_present
@@ -1078,6 +1125,7 @@ describe API::Projects do
expect(json_response['shared_with_groups'][0]['expires_at']).to be_nil
expect(json_response['only_allow_merge_if_pipeline_succeeds']).to eq(project.only_allow_merge_if_pipeline_succeeds)
expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to eq(project.only_allow_merge_if_all_discussions_are_resolved)
+ expect(json_response['ci_default_git_depth']).to eq(project.ci_default_git_depth)
expect(json_response['merge_method']).to eq(project.merge_method.to_s)
expect(json_response['readme_url']).to eq(project.readme_url)
end
@@ -1135,7 +1183,9 @@ describe API::Projects do
'path' => user.namespace.path,
'kind' => user.namespace.kind,
'full_path' => user.namespace.full_path,
- 'parent_id' => nil
+ 'parent_id' => nil,
+ 'avatar_url' => user.avatar_url,
+ 'web_url' => Gitlab::Routing.url_helpers.user_url(user)
})
end
@@ -1337,6 +1387,37 @@ describe API::Projects do
end
end
end
+
+ context 'when project belongs to a group namespace' do
+ let(:group) { create(:group, :with_avatar) }
+ let(:project) { create(:project, namespace: group) }
+ let!(:project_member) { create(:project_member, :developer, user: user, project: project) }
+
+ it 'returns group web_url and avatar_url' do
+ get api("/projects/#{project.id}", user)
+
+ expect(response).to have_gitlab_http_status(200)
+
+ group_data = json_response['namespace']
+ expect(group_data['web_url']).to eq(group.web_url)
+ expect(group_data['avatar_url']).to eq(group.avatar_url)
+ end
+ end
+
+ context 'when project belongs to a user namespace' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, namespace: user.namespace) }
+
+ it 'returns user web_url and avatar_url' do
+ get api("/projects/#{project.id}", user)
+
+ expect(response).to have_gitlab_http_status(200)
+
+ user_data = json_response['namespace']
+ expect(user_data['web_url']).to eq("http://localhost/#{user.username}")
+ expect(user_data['avatar_url']).to eq(user.avatar_url)
+ end
+ end
end
context 'with external authorization' do
@@ -1883,6 +1964,7 @@ describe API::Projects do
snippets_enabled: true,
merge_requests_enabled: true,
merge_method: 'ff',
+ ci_default_git_depth: 20,
description: 'new description' }
put api("/projects/#{project3.id}", user4), params: project_param
diff --git a/spec/requests/api/releases_spec.rb b/spec/requests/api/releases_spec.rb
index 71ec091c42c..8603fa2a73d 100644
--- a/spec/requests/api/releases_spec.rb
+++ b/spec/requests/api/releases_spec.rb
@@ -52,7 +52,7 @@ describe API::Releases do
it 'matches response schema' do
get api("/projects/#{project.id}/releases", maintainer)
- expect(response).to match_response_schema('releases')
+ expect(response).to match_response_schema('public_api/v4/releases')
end
end
@@ -69,10 +69,25 @@ describe API::Releases do
end
context 'when user is a guest' do
- it 'responds 403 Forbidden' do
+ let!(:release) do
+ create(:release,
+ project: project,
+ tag: 'v0.1',
+ author: maintainer,
+ created_at: 2.days.ago)
+ end
+
+ it 'responds 200 OK' do
get api("/projects/#{project.id}/releases", guest)
- expect(response).to have_gitlab_http_status(:forbidden)
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it "does not expose tag, commit and source code" do
+ get api("/projects/#{project.id}/releases", guest)
+
+ expect(response).to match_response_schema('public_api/v4/release/releases_for_guest')
+ expect(json_response[0]['assets']['count']).to eq(release.links.count)
end
context 'when project is public' do
@@ -83,6 +98,13 @@ describe API::Releases do
expect(response).to have_gitlab_http_status(:ok)
end
+
+ it "exposes tag, commit and source code" do
+ get api("/projects/#{project.id}/releases", guest)
+
+ expect(response).to match_response_schema('public_api/v4/releases')
+ expect(json_response[0]['assets']['count']).to eq(release.links.count + release.sources.count)
+ end
end
end
@@ -135,7 +157,7 @@ describe API::Releases do
it 'matches response schema' do
get api("/projects/#{project.id}/releases/v0.1", maintainer)
- expect(response).to match_response_schema('release')
+ expect(response).to match_response_schema('public_api/v4/release')
end
it 'contains source information as assets' do
@@ -225,6 +247,17 @@ describe API::Releases do
expect(response).to have_gitlab_http_status(:ok)
end
+
+ it "exposes tag and commit" do
+ create(:release,
+ project: project,
+ tag: 'v0.1',
+ author: maintainer,
+ created_at: 2.days.ago)
+ get api("/projects/#{project.id}/releases/v0.1", guest)
+
+ expect(response).to match_response_schema('public_api/v4/release')
+ end
end
end
end
@@ -306,7 +339,7 @@ describe API::Releases do
it 'matches response schema' do
post api("/projects/#{project.id}/releases", maintainer), params: params
- expect(response).to match_response_schema('release')
+ expect(response).to match_response_schema('public_api/v4/release')
end
it 'does not create a new tag' do
@@ -378,7 +411,7 @@ describe API::Releases do
it 'matches response schema' do
post api("/projects/#{project.id}/releases", maintainer), params: params
- expect(response).to match_response_schema('release')
+ expect(response).to match_response_schema('public_api/v4/release')
end
end
@@ -532,7 +565,7 @@ describe API::Releases do
it 'matches response schema' do
put api("/projects/#{project.id}/releases/v0.1", maintainer), params: params
- expect(response).to match_response_schema('release')
+ expect(response).to match_response_schema('public_api/v4/release')
end
context 'when user tries to update sha' do
@@ -624,7 +657,7 @@ describe API::Releases do
it 'matches response schema' do
delete api("/projects/#{project.id}/releases/v0.1", maintainer)
- expect(response).to match_response_schema('release')
+ expect(response).to match_response_schema('public_api/v4/release')
end
context 'when there are no corresponding releases' do
diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb
index 3585a827838..d9ef5edb848 100644
--- a/spec/requests/api/runner_spec.rb
+++ b/spec/requests/api/runner_spec.rb
@@ -68,7 +68,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
post api('/runners'), params: { token: group.runners_token }
expect(response).to have_http_status 201
- expect(group.runners.size).to eq(1)
+ expect(group.runners.reload.size).to eq(1)
runner = Ci::Runner.first
expect(runner.token).not_to eq(registration_token)
expect(runner.token).not_to eq(group.runners_token)
@@ -168,6 +168,32 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
end
end
+ context 'when access_level is provided for Runner' do
+ context 'when access_level is set to ref_protected' do
+ it 'creates runner' do
+ post api('/runners'), params: {
+ token: registration_token,
+ access_level: 'ref_protected'
+ }
+
+ expect(response).to have_gitlab_http_status 201
+ expect(Ci::Runner.first.ref_protected?).to be true
+ end
+ end
+
+ context 'when access_level is set to not_protected' do
+ it 'creates runner' do
+ post api('/runners'), params: {
+ token: registration_token,
+ access_level: 'not_protected'
+ }
+
+ expect(response).to have_gitlab_http_status 201
+ expect(Ci::Runner.first.ref_protected?).to be false
+ end
+ end
+ end
+
context 'when maximum job timeout is specified' do
it 'creates runner' do
post api('/runners'), params: {
@@ -418,8 +444,8 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
'sha' => job.sha,
'before_sha' => job.before_sha,
'ref_type' => 'branch',
- 'refspecs' => %w[+refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*],
- 'depth' => 0 }
+ 'refspecs' => ["+refs/heads/#{job.ref}:refs/remotes/origin/#{job.ref}"],
+ 'depth' => project.ci_default_git_depth }
end
let(:expected_steps) do
@@ -505,7 +531,11 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
end
end
- context 'when GIT_DEPTH is not specified' do
+ context 'when GIT_DEPTH is not specified and there is no default git depth for the project' do
+ before do
+ project.update!(ci_default_git_depth: nil)
+ end
+
it 'specifies refspecs' do
request_job
@@ -516,6 +546,30 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
end
end
+ context 'when job filtered by job_age' do
+ let!(:job) { create(:ci_build, :tag, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0, queued_at: 60.seconds.ago) }
+
+ context 'job is queued less than job_age parameter' do
+ let(:job_age) { 120 }
+
+ it 'gives 204' do
+ request_job(job_age: job_age)
+
+ expect(response).to have_gitlab_http_status(204)
+ end
+ end
+
+ context 'job is queued more than job_age parameter' do
+ let(:job_age) { 30 }
+
+ it 'picks a job' do
+ request_job(job_age: job_age)
+
+ expect(response).to have_gitlab_http_status(201)
+ end
+ end
+ end
+
context 'when job is made for branch' do
it 'sets tag as ref_type' do
request_job
@@ -537,7 +591,11 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
end
end
- context 'when GIT_DEPTH is not specified' do
+ context 'when GIT_DEPTH is not specified and there is no default git depth for the project' do
+ before do
+ project.update!(ci_default_git_depth: nil)
+ end
+
it 'specifies refspecs' do
request_job
@@ -1582,8 +1640,8 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
let!(:metadata) { file_upload2 }
let!(:metadata_sha256) { Digest::SHA256.file(metadata.path).hexdigest }
- let(:stored_artifacts_file) { job.reload.artifacts_file.file }
- let(:stored_metadata_file) { job.reload.artifacts_metadata.file }
+ let(:stored_artifacts_file) { job.reload.artifacts_file }
+ let(:stored_metadata_file) { job.reload.artifacts_metadata }
let(:stored_artifacts_size) { job.reload.artifacts_size }
let(:stored_artifacts_sha256) { job.reload.job_artifacts_archive.file_sha256 }
let(:stored_metadata_sha256) { job.reload.job_artifacts_metadata.file_sha256 }
@@ -1604,9 +1662,9 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
it 'stores artifacts and artifacts metadata' do
expect(response).to have_gitlab_http_status(201)
- expect(stored_artifacts_file.original_filename).to eq(artifacts.original_filename)
- expect(stored_metadata_file.original_filename).to eq(metadata.original_filename)
- expect(stored_artifacts_size).to eq(72821)
+ expect(stored_artifacts_file.filename).to eq(artifacts.original_filename)
+ expect(stored_metadata_file.filename).to eq(metadata.original_filename)
+ expect(stored_artifacts_size).to eq(artifacts.size)
expect(stored_artifacts_sha256).to eq(artifacts_sha256)
expect(stored_metadata_sha256).to eq(metadata_sha256)
end
diff --git a/spec/requests/api/search_spec.rb b/spec/requests/api/search_spec.rb
index 49672591b3b..3e0b478abb3 100644
--- a/spec/requests/api/search_spec.rb
+++ b/spec/requests/api/search_spec.rb
@@ -70,11 +70,30 @@ describe API::Search do
context 'for milestones scope' do
before do
create(:milestone, project: project, title: 'awesome milestone')
+ end
+
+ context 'when user can read project milestones' do
+ before do
+ get api('/search', user), params: { scope: 'milestones', search: 'awesome' }
+ end
- get api('/search', user), params: { scope: 'milestones', search: 'awesome' }
+ it_behaves_like 'response is correct', schema: 'public_api/v4/milestones'
end
- it_behaves_like 'response is correct', schema: 'public_api/v4/milestones'
+ context 'when user cannot read project milestones' do
+ before do
+ project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
+ project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'returns empty array' do
+ get api('/search', user), params: { scope: 'milestones', search: 'awesome' }
+
+ milestones = JSON.parse(response.body)
+
+ expect(milestones).to be_empty
+ end
+ end
end
context 'for users scope' do
@@ -318,11 +337,30 @@ describe API::Search do
context 'for milestones scope' do
before do
create(:milestone, project: project, title: 'awesome milestone')
+ end
+
+ context 'when user can read milestones' do
+ before do
+ get api("/projects/#{project.id}/search", user), params: { scope: 'milestones', search: 'awesome' }
+ end
- get api("/projects/#{project.id}/search", user), params: { scope: 'milestones', search: 'awesome' }
+ it_behaves_like 'response is correct', schema: 'public_api/v4/milestones'
end
- it_behaves_like 'response is correct', schema: 'public_api/v4/milestones'
+ context 'when user cannot read project milestones' do
+ before do
+ project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
+ project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'returns empty array' do
+ get api("/projects/#{project.id}/search", user), params: { scope: 'milestones', search: 'awesome' }
+
+ milestones = JSON.parse(response.body)
+
+ expect(milestones).to be_empty
+ end
+ end
end
context 'for users scope' do
@@ -414,6 +452,13 @@ describe API::Search do
expect(response).to have_gitlab_http_status(200)
expect(json_response.size).to eq(11)
end
+
+ it 'by ref' do
+ get api("/projects/#{repo_project.id}/search", user), params: { scope: 'blobs', search: 'This file is used in tests for ci_environments_status', ref: 'pages-deploy' }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response.size).to eq(1)
+ end
end
end
end
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 527ab1cfb66..8a60980fe80 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -13,6 +13,7 @@ describe API::Settings, 'Settings' do
expect(json_response['default_projects_limit']).to eq(42)
expect(json_response['password_authentication_enabled_for_web']).to be_truthy
expect(json_response['repository_storages']).to eq(['default'])
+ expect(json_response['password_authentication_enabled']).to be_truthy
expect(json_response['plantuml_enabled']).to be_falsey
expect(json_response['plantuml_url']).to be_nil
expect(json_response['default_project_visibility']).to be_a String
diff --git a/spec/requests/api/system_hooks_spec.rb b/spec/requests/api/system_hooks_spec.rb
index b6e8d74c2e9..0e2f3face71 100644
--- a/spec/requests/api/system_hooks_spec.rb
+++ b/spec/requests/api/system_hooks_spec.rb
@@ -1,12 +1,14 @@
require 'spec_helper'
describe API::SystemHooks do
+ include StubRequests
+
let(:user) { create(:user) }
let(:admin) { create(:admin) }
let!(:hook) { create(:system_hook, url: "http://example.com") }
before do
- stub_request(:post, hook.url)
+ stub_full_request(hook.url, method: :post)
end
describe "GET /hooks" do
@@ -68,6 +70,8 @@ describe API::SystemHooks do
end
it 'sets default values for events' do
+ stub_full_request('http://mep.mep', method: :post)
+
post api('/hooks', admin), params: { url: 'http://mep.mep' }
expect(response).to have_gitlab_http_status(201)
@@ -78,6 +82,8 @@ describe API::SystemHooks do
end
it 'sets explicit values for events' do
+ stub_full_request('http://mep.mep', method: :post)
+
post api('/hooks', admin),
params: {
url: 'http://mep.mep',
diff --git a/spec/requests/api/tags_spec.rb b/spec/requests/api/tags_spec.rb
index fffe878ddbd..d898319e709 100644
--- a/spec/requests/api/tags_spec.rb
+++ b/spec/requests/api/tags_spec.rb
@@ -378,7 +378,7 @@ describe API::Tags do
post api(route, user), params: { description: description }
expect(response).to have_gitlab_http_status(201)
- expect(response).to match_response_schema('public_api/v4/release')
+ expect(response).to match_response_schema('public_api/v4/release/tag_release')
expect(json_response['tag_name']).to eq(tag_name)
expect(json_response['description']).to eq(description)
end
diff --git a/spec/requests/api/task_completion_status_spec.rb b/spec/requests/api/task_completion_status_spec.rb
new file mode 100644
index 00000000000..ee2531197b1
--- /dev/null
+++ b/spec/requests/api/task_completion_status_spec.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'task completion status response' do
+ set(:user) { create(:user) }
+ set(:project) do
+ create(:project, :public, creator_id: user.id, namespace: user.namespace)
+ end
+
+ shared_examples 'taskable completion status provider' do |path|
+ samples = [
+ {
+ description: '',
+ expected_count: 0,
+ expected_completed_count: 0
+ },
+ {
+ description: 'Lorem ipsum',
+ expected_count: 0,
+ expected_completed_count: 0
+ },
+ {
+ description: %{- [ ] task 1
+ - [x] task 2 },
+ expected_count: 2,
+ expected_completed_count: 1
+ },
+ {
+ description: %{- [ ] task 1
+ - [ ] task 2 },
+ expected_count: 2,
+ expected_completed_count: 0
+ },
+ {
+ description: %{- [x] task 1
+ - [x] task 2 },
+ expected_count: 2,
+ expected_completed_count: 2
+ },
+ {
+ description: %{- [ ] task 1},
+ expected_count: 1,
+ expected_completed_count: 0
+ },
+ {
+ description: %{- [x] task 1},
+ expected_count: 1,
+ expected_completed_count: 1
+ }
+ ]
+ samples.each do |sample_data|
+ context "with a description of #{sample_data[:description].inspect}" do
+ before do
+ taskable.update!(description: sample_data[:description])
+
+ get api("#{path}?iids[]=#{taskable.iid}", user)
+ end
+
+ it { expect(response).to have_gitlab_http_status(200) }
+
+ it 'returns the expected results' do
+ expect(json_response).to be_an Array
+ expect(json_response).not_to be_empty
+
+ task_completion_status = json_response.first['task_completion_status']
+ expect(task_completion_status['count']).to eq(sample_data[:expected_count])
+ expect(task_completion_status['completed_count']).to eq(sample_data[:expected_completed_count])
+ end
+ end
+ end
+ end
+
+ context 'task list completion status for issues' do
+ it_behaves_like 'taskable completion status provider', '/issues' do
+ let(:taskable) { create(:issue, project: project, author: user) }
+ end
+ end
+
+ context 'task list completion status for merge_requests' do
+ it_behaves_like 'taskable completion status provider', '/merge_requests' do
+ let(:taskable) { create(:merge_request, source_project: project, target_project: project, author: user) }
+ end
+ end
+end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index b84202364e1..bab1520b960 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -276,6 +276,18 @@ describe API::Users do
expect(response).to have_gitlab_http_status(400)
end
end
+
+ context "when authenticated and ldap is enabled" do
+ it "returns non-ldap user" do
+ create :omniauth_user, provider: "ldapserver1"
+
+ get api("/users", user), params: { skip_ldap: "true" }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.first["username"]).to eq user.username
+ end
+ end
end
describe "GET /users/:id" do
diff --git a/spec/requests/api/variables_spec.rb b/spec/requests/api/variables_spec.rb
index 5df6baf0ddf..55b1419a004 100644
--- a/spec/requests/api/variables_spec.rb
+++ b/spec/requests/api/variables_spec.rb
@@ -43,6 +43,8 @@ describe API::Variables do
expect(response).to have_gitlab_http_status(200)
expect(json_response['value']).to eq(variable.value)
expect(json_response['protected']).to eq(variable.protected?)
+ expect(json_response['masked']).to eq(variable.masked?)
+ expect(json_response['variable_type']).to eq('env_var')
end
it 'responds with 404 Not Found if requesting non-existing variable' do
@@ -73,24 +75,28 @@ describe API::Variables do
context 'authorized user with proper permissions' do
it 'creates variable' do
expect do
- post api("/projects/#{project.id}/variables", user), params: { key: 'TEST_VARIABLE_2', value: 'PROTECTED_VALUE_2', protected: true }
+ post api("/projects/#{project.id}/variables", user), params: { key: 'TEST_VARIABLE_2', value: 'PROTECTED_VALUE_2', protected: true, masked: true }
end.to change {project.variables.count}.by(1)
expect(response).to have_gitlab_http_status(201)
expect(json_response['key']).to eq('TEST_VARIABLE_2')
expect(json_response['value']).to eq('PROTECTED_VALUE_2')
expect(json_response['protected']).to be_truthy
+ expect(json_response['masked']).to be_truthy
+ expect(json_response['variable_type']).to eq('env_var')
end
it 'creates variable with optional attributes' do
expect do
- post api("/projects/#{project.id}/variables", user), params: { key: 'TEST_VARIABLE_2', value: 'VALUE_2' }
+ post api("/projects/#{project.id}/variables", user), params: { variable_type: 'file', key: 'TEST_VARIABLE_2', value: 'VALUE_2' }
end.to change {project.variables.count}.by(1)
expect(response).to have_gitlab_http_status(201)
expect(json_response['key']).to eq('TEST_VARIABLE_2')
expect(json_response['value']).to eq('VALUE_2')
expect(json_response['protected']).to be_falsey
+ expect(json_response['masked']).to be_falsey
+ expect(json_response['variable_type']).to eq('file')
end
it 'does not allow to duplicate variable key' do
@@ -125,7 +131,7 @@ describe API::Variables do
initial_variable = project.variables.reload.first
value_before = initial_variable.value
- put api("/projects/#{project.id}/variables/#{variable.key}", user), params: { value: 'VALUE_1_UP', protected: true }
+ put api("/projects/#{project.id}/variables/#{variable.key}", user), params: { variable_type: 'file', value: 'VALUE_1_UP', protected: true }
updated_variable = project.variables.reload.first
@@ -133,6 +139,7 @@ describe API::Variables do
expect(value_before).to eq(variable.value)
expect(updated_variable.value).to eq('VALUE_1_UP')
expect(updated_variable).to be_protected
+ expect(updated_variable.variable_type).to eq('file')
end
it 'responds with 404 Not Found if requesting non-existing variable' do
diff --git a/spec/requests/rack_attack_global_spec.rb b/spec/requests/rack_attack_global_spec.rb
index 49021f5d1b7..89adbc77a7f 100644
--- a/spec/requests/rack_attack_global_spec.rb
+++ b/spec/requests/rack_attack_global_spec.rb
@@ -182,6 +182,17 @@ describe 'Rack Attack global throttles' do
end
end
end
+
+ it 'logs RackAttack info into structured logs' do
+ requests_per_period.times do
+ get url_that_does_not_require_authentication
+ expect(response).to have_http_status 200
+ end
+
+ expect(Gitlab::AuthLogger).to receive(:error).once
+
+ get url_that_does_not_require_authentication
+ end
end
context 'when the throttle is disabled' do
@@ -251,8 +262,8 @@ describe 'Rack Attack global throttles' do
let(:throttle_setting_prefix) { 'throttle_authenticated_web' }
context 'with the token in the query string' do
- let(:get_args) { [rss_url(user), nil] }
- let(:other_user_get_args) { [rss_url(other_user), nil] }
+ let(:get_args) { [rss_url(user), params: nil] }
+ let(:other_user_get_args) { [rss_url(other_user), params: nil] }
it_behaves_like 'rate-limited token-authenticated requests'
end
@@ -327,6 +338,17 @@ describe 'Rack Attack global throttles' do
expect_rejection { get url_that_requires_authentication }
end
+
+ it 'logs RackAttack info into structured logs' do
+ requests_per_period.times do
+ get url_that_requires_authentication
+ expect(response).to have_http_status 200
+ end
+
+ expect(Gitlab::AuthLogger).to receive(:error).once
+
+ get url_that_requires_authentication
+ end
end
context 'when the throttle is disabled' do
diff --git a/spec/routing/group_routing_spec.rb b/spec/routing/group_routing_spec.rb
index 53271550e8b..00ca394a50b 100644
--- a/spec/routing/group_routing_spec.rb
+++ b/spec/routing/group_routing_spec.rb
@@ -133,5 +133,19 @@ describe "Groups", "routing" do
let(:resource) { create(:group, parent: parent, path: 'activity') }
end
end
+
+ describe 'subgroup "boards"' do
+ it 'shows group show page' do
+ allow(Group).to receive(:find_by_full_path).with('gitlabhq/boards', any_args).and_return(true)
+
+ expect(get('/groups/gitlabhq/boards')).to route_to('groups#show', id: 'gitlabhq/boards')
+ end
+
+ it 'shows boards index page' do
+ allow(Group).to receive(:find_by_full_path).with('gitlabhq', any_args).and_return(true)
+
+ expect(get('/groups/gitlabhq/-/boards')).to route_to('groups/boards#index', group_id: 'gitlabhq')
+ end
+ end
end
end
diff --git a/spec/routing/import_routing_spec.rb b/spec/routing/import_routing_spec.rb
index 106f92082e4..3fdede7914d 100644
--- a/spec/routing/import_routing_spec.rb
+++ b/spec/routing/import_routing_spec.rb
@@ -174,3 +174,15 @@ describe Import::GitlabProjectsController, 'routing' do
expect(get('/import/gitlab_project/new')).to route_to('import/gitlab_projects#new')
end
end
+
+# new_import_phabricator GET /import/phabricator/new(.:format) import/phabricator#new
+# import_phabricator POST /import/phabricator(.:format) import/phabricator#create
+describe Import::PhabricatorController, 'routing' do
+ it 'to #create' do
+ expect(post("/import/phabricator")).to route_to("import/phabricator#create")
+ end
+
+ it 'to #new' do
+ expect(get("/import/phabricator/new")).to route_to("import/phabricator#new")
+ end
+end
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index a0d01fc8263..83775b1040e 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -138,9 +138,11 @@ describe 'project routing' do
describe Projects::AutocompleteSourcesController, 'routing' do
[:members, :issues, :merge_requests, :labels, :milestones, :commands, :snippets].each do |action|
it "to ##{action}" do
- expect(get("/gitlab/gitlabhq/autocomplete_sources/#{action}")).to route_to("projects/autocomplete_sources##{action}", namespace_id: 'gitlab', project_id: 'gitlabhq')
+ expect(get("/gitlab/gitlabhq/-/autocomplete_sources/#{action}")).to route_to("projects/autocomplete_sources##{action}", namespace_id: 'gitlab', project_id: 'gitlabhq')
end
end
+
+ it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/autocomplete_sources/labels", "/gitlab/gitlabhq/-/autocomplete_sources/labels"
end
# pages_project_wikis GET /:project_id/wikis/pages(.:format) projects/wikis#pages
@@ -204,25 +206,27 @@ describe 'project routing' do
describe Projects::BranchesController, 'routing' do
it 'to #branches' do
- expect(get('/gitlab/gitlabhq/branches')).to route_to('projects/branches#index', namespace_id: 'gitlab', project_id: 'gitlabhq')
- expect(delete('/gitlab/gitlabhq/branches/feature%2345')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45')
- expect(delete('/gitlab/gitlabhq/branches/feature%2B45')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45')
- expect(delete('/gitlab/gitlabhq/branches/feature@45')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45')
- expect(delete('/gitlab/gitlabhq/branches/feature%2345/foo/bar/baz')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45/foo/bar/baz')
- expect(delete('/gitlab/gitlabhq/branches/feature%2B45/foo/bar/baz')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45/foo/bar/baz')
- expect(delete('/gitlab/gitlabhq/branches/feature@45/foo/bar/baz')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45/foo/bar/baz')
+ expect(get('/gitlab/gitlabhq/-/branches')).to route_to('projects/branches#index', namespace_id: 'gitlab', project_id: 'gitlabhq')
+ expect(delete('/gitlab/gitlabhq/-/branches/feature%2345')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45')
+ expect(delete('/gitlab/gitlabhq/-/branches/feature%2B45')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45')
+ expect(delete('/gitlab/gitlabhq/-/branches/feature@45')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45')
+ expect(delete('/gitlab/gitlabhq/-/branches/feature%2345/foo/bar/baz')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45/foo/bar/baz')
+ expect(delete('/gitlab/gitlabhq/-/branches/feature%2B45/foo/bar/baz')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45/foo/bar/baz')
+ expect(delete('/gitlab/gitlabhq/-/branches/feature@45/foo/bar/baz')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45/foo/bar/baz')
end
+
+ it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/branches", "/gitlab/gitlabhq/-/branches"
end
describe Projects::TagsController, 'routing' do
it 'to #tags' do
- expect(get('/gitlab/gitlabhq/tags')).to route_to('projects/tags#index', namespace_id: 'gitlab', project_id: 'gitlabhq')
- expect(delete('/gitlab/gitlabhq/tags/feature%2345')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45')
- expect(delete('/gitlab/gitlabhq/tags/feature%2B45')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45')
- expect(delete('/gitlab/gitlabhq/tags/feature@45')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45')
- expect(delete('/gitlab/gitlabhq/tags/feature%2345/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45/foo/bar/baz')
- expect(delete('/gitlab/gitlabhq/tags/feature%2B45/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45/foo/bar/baz')
- expect(delete('/gitlab/gitlabhq/tags/feature@45/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45/foo/bar/baz')
+ expect(get('/gitlab/gitlabhq/-/tags')).to route_to('projects/tags#index', namespace_id: 'gitlab', project_id: 'gitlabhq')
+ expect(delete('/gitlab/gitlabhq/-/tags/feature%2345')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45')
+ expect(delete('/gitlab/gitlabhq/-/tags/feature%2B45')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45')
+ expect(delete('/gitlab/gitlabhq/-/tags/feature@45')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45')
+ expect(delete('/gitlab/gitlabhq/-/tags/feature%2345/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45/foo/bar/baz')
+ expect(delete('/gitlab/gitlabhq/-/tags/feature%2B45/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45/foo/bar/baz')
+ expect(delete('/gitlab/gitlabhq/-/tags/feature@45/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45/foo/bar/baz')
end
end
@@ -237,7 +241,10 @@ describe 'project routing' do
it_behaves_like 'RESTful project resources' do
let(:actions) { [:index, :new, :create, :edit, :update] }
let(:controller) { 'deploy_keys' }
+ let(:controller_path) { '/-/deploy_keys' }
end
+
+ it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/deploy_keys", "/gitlab/gitlabhq/-/deploy_keys"
end
# project_protected_branches GET /:project_id/protected_branches(.:format) protected_branches#index
@@ -247,6 +254,7 @@ describe 'project routing' do
it_behaves_like 'RESTful project resources' do
let(:actions) { [:index, :create, :destroy] }
let(:controller) { 'protected_branches' }
+ let(:controller_path) { '/-/protected_branches' }
end
end
@@ -444,7 +452,10 @@ describe 'project routing' do
it_behaves_like 'RESTful project resources' do
let(:actions) { [:index, :create, :update, :destroy] }
let(:controller) { 'project_members' }
+ let(:controller_path) { '/-/project_members' }
end
+
+ it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/project_members", "/gitlab/gitlabhq/-/project_members"
end
# project_milestones GET /:project_id/milestones(.:format) milestones#index
@@ -459,18 +470,23 @@ describe 'project routing' do
it_behaves_like 'RESTful project resources' do
let(:controller) { 'milestones' }
let(:actions) { [:index, :create, :new, :edit, :show, :update] }
+ let(:controller_path) { '/-/milestones' }
end
it 'to #promote' do
- expect(post('/gitlab/gitlabhq/milestones/1/promote')).to route_to('projects/milestones#promote', namespace_id: 'gitlab', project_id: 'gitlabhq', id: "1")
+ expect(post('/gitlab/gitlabhq/-/milestones/1/promote')).to route_to('projects/milestones#promote', namespace_id: 'gitlab', project_id: 'gitlabhq', id: "1")
end
+
+ it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/milestones", "/gitlab/gitlabhq/-/milestones"
end
# project_labels GET /:project_id/labels(.:format) labels#index
describe Projects::LabelsController, 'routing' do
it 'to #index' do
- expect(get('/gitlab/gitlabhq/labels')).to route_to('projects/labels#index', namespace_id: 'gitlab', project_id: 'gitlabhq')
+ expect(get('/gitlab/gitlabhq/-/labels')).to route_to('projects/labels#index', namespace_id: 'gitlab', project_id: 'gitlabhq')
end
+
+ it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/labels", "/gitlab/gitlabhq/-/labels"
end
# sort_project_issues POST /:project_id/issues/sort(.:format) issues#sort
@@ -592,36 +608,44 @@ describe 'project routing' do
describe Projects::NetworkController, 'routing' do
it 'to #show' do
- expect(get('/gitlab/gitlabhq/network/master')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master')
- expect(get('/gitlab/gitlabhq/network/ends-with.json')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'ends-with.json')
- expect(get('/gitlab/gitlabhq/network/master?format=json')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', format: 'json')
+ expect(get('/gitlab/gitlabhq/-/network/master')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master')
+ expect(get('/gitlab/gitlabhq/-/network/ends-with.json')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'ends-with.json')
+ expect(get('/gitlab/gitlabhq/-/network/master?format=json')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', format: 'json')
end
+
+ it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/network/master", "/gitlab/gitlabhq/-/network/master"
end
describe Projects::GraphsController, 'routing' do
it 'to #show' do
- expect(get('/gitlab/gitlabhq/graphs/master')).to route_to('projects/graphs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master')
- expect(get('/gitlab/gitlabhq/graphs/ends-with.json')).to route_to('projects/graphs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'ends-with.json')
- expect(get('/gitlab/gitlabhq/graphs/master?format=json')).to route_to('projects/graphs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', format: 'json')
+ expect(get('/gitlab/gitlabhq/-/graphs/master')).to route_to('projects/graphs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master')
+ expect(get('/gitlab/gitlabhq/-/graphs/ends-with.json')).to route_to('projects/graphs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'ends-with.json')
+ expect(get('/gitlab/gitlabhq/-/graphs/master?format=json')).to route_to('projects/graphs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', format: 'json')
end
+
+ it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/graphs/master", "/gitlab/gitlabhq/-/graphs/master"
end
describe Projects::ForksController, 'routing' do
it 'to #new' do
- expect(get('/gitlab/gitlabhq/forks/new')).to route_to('projects/forks#new', namespace_id: 'gitlab', project_id: 'gitlabhq')
+ expect(get('/gitlab/gitlabhq/-/forks/new')).to route_to('projects/forks#new', namespace_id: 'gitlab', project_id: 'gitlabhq')
end
it 'to #create' do
- expect(post('/gitlab/gitlabhq/forks')).to route_to('projects/forks#create', namespace_id: 'gitlab', project_id: 'gitlabhq')
+ expect(post('/gitlab/gitlabhq/-/forks')).to route_to('projects/forks#create', namespace_id: 'gitlab', project_id: 'gitlabhq')
end
+
+ it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/forks", "/gitlab/gitlabhq/-/forks"
end
# project_avatar DELETE /project/avatar(.:format) projects/avatars#destroy
describe Projects::AvatarsController, 'routing' do
it 'to #destroy' do
- expect(delete('/gitlab/gitlabhq/avatar')).to route_to(
+ expect(delete('/gitlab/gitlabhq/-/avatar')).to route_to(
'projects/avatars#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq')
end
+
+ it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/avatar", "/gitlab/gitlabhq/-/avatar"
end
describe Projects::PagesDomainsController, 'routing' do
@@ -661,4 +685,12 @@ describe 'project routing' do
end
end
end
+
+ describe Projects::Settings::RepositoryController, 'routing' do
+ it 'to #show' do
+ expect(get('/gitlab/gitlabhq/-/settings/repository')).to route_to('projects/settings/repository#show', namespace_id: 'gitlab', project_id: 'gitlabhq')
+ end
+
+ it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/settings/repository", "/gitlab/gitlabhq/-/settings/repository"
+ end
end
diff --git a/spec/routing/uploads_routing_spec.rb b/spec/routing/uploads_routing_spec.rb
new file mode 100644
index 00000000000..6a041ffdd6c
--- /dev/null
+++ b/spec/routing/uploads_routing_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Uploads', 'routing' do
+ it 'allows creating uploads for personal snippets' do
+ expect(post('/uploads/personal_snippet?id=1')).to route_to(
+ controller: 'uploads',
+ action: 'create',
+ model: 'personal_snippet',
+ id: '1'
+ )
+ end
+
+ it 'does not allow creating uploads for other models' do
+ UploadsController::MODEL_CLASSES.keys.compact.each do |model|
+ next if model == 'personal_snippet'
+
+ expect(post("/uploads/#{model}?id=1")).not_to be_routable
+ end
+ end
+end
diff --git a/spec/rubocop/cop/code_reuse/active_record_spec.rb b/spec/rubocop/cop/code_reuse/active_record_spec.rb
index a30fc52d26f..8f3a3690d88 100644
--- a/spec/rubocop/cop/code_reuse/active_record_spec.rb
+++ b/spec/rubocop/cop/code_reuse/active_record_spec.rb
@@ -14,7 +14,7 @@ describe RuboCop::Cop::CodeReuse::ActiveRecord do
expect_offense(<<~SOURCE)
def foo
User.where
- ^^^^^ This method can only be used inside an ActiveRecord model
+ ^^^^^ This method can only be used inside an ActiveRecord model: https://gitlab.com/gitlab-org/gitlab-ce/issues/49653
end
SOURCE
end
@@ -23,7 +23,7 @@ describe RuboCop::Cop::CodeReuse::ActiveRecord do
expect_offense(<<~SOURCE)
def foo
User.where(id: 10)
- ^^^^^ This method can only be used inside an ActiveRecord model
+ ^^^^^ This method can only be used inside an ActiveRecord model: https://gitlab.com/gitlab-org/gitlab-ce/issues/49653
end
SOURCE
end
@@ -40,7 +40,7 @@ describe RuboCop::Cop::CodeReuse::ActiveRecord do
expect_offense(<<~SOURCE)
def foo
project.group(:name)
- ^^^^^ This method can only be used inside an ActiveRecord model
+ ^^^^^ This method can only be used inside an ActiveRecord model: https://gitlab.com/gitlab-org/gitlab-ce/issues/49653
end
SOURCE
end
diff --git a/spec/rubocop/cop/include_action_view_context_spec.rb b/spec/rubocop/cop/include_action_view_context_spec.rb
new file mode 100644
index 00000000000..c888555b54f
--- /dev/null
+++ b/spec/rubocop/cop/include_action_view_context_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require 'rubocop'
+require 'rubocop/rspec/support'
+
+require_relative '../../../rubocop/cop/include_action_view_context'
+
+describe RuboCop::Cop::IncludeActionViewContext do
+ include CopHelper
+
+ subject(:cop) { described_class.new }
+
+ context 'when `ActionView::Context` is included' do
+ let(:source) { 'include ActionView::Context' }
+ let(:correct_source) { 'include ::Gitlab::ActionViewOutput::Context' }
+
+ it 'registers an offense' do
+ inspect_source(source)
+
+ aggregate_failures do
+ expect(cop.offenses.size).to eq(1)
+ expect(cop.offenses.map(&:line)).to eq([1])
+ expect(cop.highlights).to eq(['ActionView::Context'])
+ end
+ end
+
+ it 'autocorrects to the right version' do
+ autocorrected = autocorrect_source(source)
+
+ expect(autocorrected).to eq(correct_source)
+ end
+ end
+
+ context 'when `ActionView::Context` is not included' do
+ it 'registers no offense' do
+ inspect_source('include Context')
+
+ aggregate_failures do
+ expect(cop.offenses.size).to eq(0)
+ end
+ end
+ end
+end
diff --git a/spec/rubocop/cop/qa/element_with_pattern_spec.rb b/spec/rubocop/cop/qa/element_with_pattern_spec.rb
index c5beb40f9fd..ef20d9a1f26 100644
--- a/spec/rubocop/cop/qa/element_with_pattern_spec.rb
+++ b/spec/rubocop/cop/qa/element_with_pattern_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
@@ -23,7 +25,7 @@ describe RuboCop::Cop::QA::ElementWithPattern do
element :groups_filter, 'search_field_tag :filter'
^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't use a pattern for element, create a corresponding `qa-groups-filter` instead.
element :groups_filter_placeholder, /Search by name/
- ^^^^^^^^^^^^^^^^ Don't use a pattern for element, create a corresponding `qa-groups-filter-placeholder` instead.
+ ^^^^^^^^^^^^^^ Don't use a pattern for element, create a corresponding `qa-groups-filter-placeholder` instead.
end
RUBY
end
@@ -35,6 +37,13 @@ describe RuboCop::Cop::QA::ElementWithPattern do
element :groups_filter_placeholder
end
RUBY
+
+ expect_no_offenses(<<-RUBY)
+ view 'app/views/shared/groups/_search_form.html.haml' do
+ element :groups_filter, required: true
+ element :groups_filter_placeholder, required: false
+ end
+ RUBY
end
end
diff --git a/spec/serializers/analytics_stage_serializer_spec.rb b/spec/serializers/analytics_stage_serializer_spec.rb
index dbfb3eace83..5b05c2f2ef3 100644
--- a/spec/serializers/analytics_stage_serializer_spec.rb
+++ b/spec/serializers/analytics_stage_serializer_spec.rb
@@ -21,4 +21,34 @@ describe AnalyticsStageSerializer do
it 'contains important elements of AnalyticsStage' do
expect(subject).to include(:title, :description, :value)
end
+
+ context 'when median is equal 0' do
+ before do
+ allow_any_instance_of(Gitlab::CycleAnalytics::BaseStage).to receive(:median).and_return(0)
+ end
+
+ it 'sets the value to nil' do
+ expect(subject.fetch(:value)).to be_nil
+ end
+ end
+
+ context 'when median is below 1' do
+ before do
+ allow_any_instance_of(Gitlab::CycleAnalytics::BaseStage).to receive(:median).and_return(0.12)
+ end
+
+ it 'sets the value to equal to median' do
+ expect(subject.fetch(:value)).to eq('less than a minute')
+ end
+ end
+
+ context 'when median is above 1' do
+ before do
+ allow_any_instance_of(Gitlab::CycleAnalytics::BaseStage).to receive(:median).and_return(60.12)
+ end
+
+ it 'sets the value to equal to median' do
+ expect(subject.fetch(:value)).to eq('1 minute')
+ end
+ end
end
diff --git a/spec/serializers/board_serializer_spec.rb b/spec/serializers/board_serializer_spec.rb
new file mode 100644
index 00000000000..8a633e46316
--- /dev/null
+++ b/spec/serializers/board_serializer_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe BoardSerializer do
+ let(:resource) { create(:board) }
+ let(:json_entity) do
+ described_class.new
+ .represent(resource, serializer: serializer)
+ .with_indifferent_access
+ end
+
+ context 'serialization' do
+ let(:serializer) { 'board' }
+
+ it 'matches issue_sidebar json schema' do
+ expect(json_entity).to match_schema('board')
+ end
+ end
+end
diff --git a/spec/serializers/build_details_entity_spec.rb b/spec/serializers/build_details_entity_spec.rb
index 1edf69dc290..d922e8246c7 100644
--- a/spec/serializers/build_details_entity_spec.rb
+++ b/spec/serializers/build_details_entity_spec.rb
@@ -122,5 +122,38 @@ describe BuildDetailsEntity do
it { is_expected.to include(failure_reason: 'unmet_prerequisites') }
end
+
+ context 'when a build has environment with latest deployment' do
+ let(:build) do
+ create(:ci_build, :running, environment: environment.name, pipeline: pipeline)
+ end
+
+ let(:environment) do
+ create(:environment, project: project, name: 'staging', state: :available)
+ end
+
+ before do
+ create(:deployment, :success, environment: environment, project: project)
+
+ allow(request).to receive(:project).and_return(project)
+ end
+
+ it 'does not serialize latest deployment commit and associated builds' do
+ response = subject.with_indifferent_access
+
+ response.dig(:deployment_status, :environment, :last_deployment).tap do |deployment|
+ expect(deployment).not_to include(:commit, :manual_actions, :scheduled_actions)
+ end
+ end
+ end
+
+ context 'when the build has reports' do
+ let!(:report) { create(:ci_job_artifact, :codequality, job: build) }
+
+ it 'exposes the report artifacts' do
+ expect(subject[:reports].count).to eq(1)
+ expect(subject[:reports].first[:file_type]).to eq('codequality')
+ end
+ end
end
end
diff --git a/spec/serializers/cluster_application_entity_spec.rb b/spec/serializers/cluster_application_entity_spec.rb
index 7e151c3744e..f38a18fcf59 100644
--- a/spec/serializers/cluster_application_entity_spec.rb
+++ b/spec/serializers/cluster_application_entity_spec.rb
@@ -21,6 +21,10 @@ describe ClusterApplicationEntity do
expect(subject[:status_reason]).to be_nil
end
+ it 'has can_uninstall' do
+ expect(subject[:can_uninstall]).to be_falsey
+ end
+
context 'non-helm application' do
let(:application) { build(:clusters_applications_runner, version: '0.0.0') }
diff --git a/spec/serializers/deployment_entity_spec.rb b/spec/serializers/deployment_entity_spec.rb
index 894fd7a0a12..76ad2aee5c5 100644
--- a/spec/serializers/deployment_entity_spec.rb
+++ b/spec/serializers/deployment_entity_spec.rb
@@ -10,6 +10,7 @@ describe DeploymentEntity do
let(:build) { create(:ci_build, :manual, pipeline: pipeline) }
let(:pipeline) { create(:ci_pipeline, project: project, user: user) }
let(:entity) { described_class.new(deployment, request: request) }
+
subject { entity.as_json }
before do
@@ -47,6 +48,16 @@ describe DeploymentEntity do
expect(subject[:manual_actions]).not_to be_present
end
end
+
+ context 'when deployment details serialization was disabled' do
+ let(:entity) do
+ described_class.new(deployment, request: request, deployment_details: false)
+ end
+
+ it 'does not serialize manual actions details' do
+ expect(subject.with_indifferent_access).not_to include(:manual_actions)
+ end
+ end
end
describe 'scheduled_actions' do
@@ -69,5 +80,35 @@ describe DeploymentEntity do
expect(subject[:scheduled_actions]).to be_empty
end
end
+
+ context 'when deployment details serialization was disabled' do
+ let(:entity) do
+ described_class.new(deployment, request: request, deployment_details: false)
+ end
+
+ it 'does not serialize scheduled actions details' do
+ expect(subject.with_indifferent_access).not_to include(:scheduled_actions)
+ end
+ end
+ end
+
+ context 'when deployment details serialization was disabled' do
+ include Gitlab::Routing
+
+ let(:entity) do
+ described_class.new(deployment, request: request, deployment_details: false)
+ end
+
+ it 'does not serialize deployment details' do
+ expect(subject.with_indifferent_access)
+ .not_to include(:commit, :manual_actions, :scheduled_actions)
+ end
+
+ it 'only exposes deployable name and path' do
+ project_job_path(project, deployment.deployable).tap do |path|
+ expect(subject.fetch(:deployable))
+ .to eq(name: 'test', build_path: path)
+ end
+ end
end
end
diff --git a/spec/serializers/job_artifact_report_entity_spec.rb b/spec/serializers/job_artifact_report_entity_spec.rb
new file mode 100644
index 00000000000..eef5c16d0fb
--- /dev/null
+++ b/spec/serializers/job_artifact_report_entity_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe JobArtifactReportEntity do
+ let(:report) { create(:ci_job_artifact, :codequality) }
+ let(:entity) { described_class.new(report, request: double) }
+
+ describe '#as_json' do
+ subject { entity.as_json }
+
+ it 'exposes file_type' do
+ expect(subject[:file_type]).to eq(report.file_type)
+ end
+
+ it 'exposes file_format' do
+ expect(subject[:file_format]).to eq(report.file_format)
+ end
+
+ it 'exposes size' do
+ expect(subject[:size]).to eq(report.size)
+ end
+
+ it 'exposes download path' do
+ expect(subject[:download_path]).to include("jobs/#{report.job.id}/artifacts/download")
+ end
+ end
+end
diff --git a/spec/serializers/merge_request_widget_entity_spec.rb b/spec/serializers/merge_request_widget_entity_spec.rb
index b89898f26f7..a27c22191f4 100644
--- a/spec/serializers/merge_request_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_widget_entity_spec.rb
@@ -297,4 +297,50 @@ describe MergeRequestWidgetEntity do
end
end
end
+
+ describe 'auto merge' do
+ context 'when auto merge is enabled' do
+ let(:resource) { create(:merge_request, :merge_when_pipeline_succeeds) }
+
+ it 'returns auto merge related information' do
+ expect(subject[:auto_merge_enabled]).to be_truthy
+ expect(subject[:auto_merge_strategy]).to eq('merge_when_pipeline_succeeds')
+ end
+ end
+
+ context 'when auto merge is not enabled' do
+ let(:resource) { create(:merge_request) }
+
+ it 'returns auto merge related information' do
+ expect(subject[:auto_merge_enabled]).to be_falsy
+ expect(subject[:auto_merge_strategy]).to be_nil
+ end
+ end
+
+ context 'when head pipeline is running' do
+ before do
+ create(:ci_pipeline, :running, project: project,
+ ref: resource.source_branch,
+ sha: resource.diff_head_sha)
+ resource.update_head_pipeline
+ end
+
+ it 'returns available auto merge strategies' do
+ expect(subject[:available_auto_merge_strategies]).to eq(%w[merge_when_pipeline_succeeds])
+ end
+ end
+
+ context 'when head pipeline is finished' do
+ before do
+ create(:ci_pipeline, :success, project: project,
+ ref: resource.source_branch,
+ sha: resource.diff_head_sha)
+ resource.update_head_pipeline
+ end
+
+ it 'returns available auto merge strategies' do
+ expect(subject[:available_auto_merge_strategies]).to be_empty
+ end
+ end
+ end
end
diff --git a/spec/serializers/pipeline_entity_spec.rb b/spec/serializers/pipeline_entity_spec.rb
index dba7fd91747..6be612ec226 100644
--- a/spec/serializers/pipeline_entity_spec.rb
+++ b/spec/serializers/pipeline_entity_spec.rb
@@ -48,8 +48,8 @@ describe PipelineEntity do
it 'contains flags' do
expect(subject).to include :flags
expect(subject[:flags])
- .to include :latest, :stuck, :auto_devops,
- :yaml_errors, :retryable, :cancelable, :merge_request
+ .to include :stuck, :auto_devops, :yaml_errors,
+ :retryable, :cancelable, :merge_request
end
end
@@ -64,6 +64,12 @@ describe PipelineEntity do
create(:ci_build, :failed, pipeline: pipeline)
end
+ it 'does not serialize stage builds' do
+ subject.with_indifferent_access.dig(:details, :stages, 0).tap do |stage|
+ expect(stage).not_to include(:groups, :latest_statuses, :retries)
+ end
+ end
+
context 'user has ability to retry pipeline' do
before do
project.add_developer(user)
@@ -92,6 +98,12 @@ describe PipelineEntity do
create(:ci_build, :pending, pipeline: pipeline)
end
+ it 'does not serialize stage builds' do
+ subject.with_indifferent_access.dig(:details, :stages, 0).tap do |stage|
+ expect(stage).not_to include(:groups, :latest_statuses, :retries)
+ end
+ end
+
context 'user has ability to cancel pipeline' do
before do
project.add_developer(user)
@@ -137,7 +149,7 @@ describe PipelineEntity do
context 'when pipeline is detached merge request pipeline' do
let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) }
let(:project) { merge_request.target_project }
- let(:pipeline) { merge_request.merge_request_pipelines.first }
+ let(:pipeline) { merge_request.pipelines_for_merge_request.first }
it 'makes detached flag true' do
expect(subject[:flags][:detached_merge_request_pipeline]).to be_truthy
@@ -185,7 +197,7 @@ describe PipelineEntity do
context 'when pipeline is merge request pipeline' do
let(:merge_request) { create(:merge_request, :with_merge_request_pipeline, merge_sha: 'abc') }
let(:project) { merge_request.target_project }
- let(:pipeline) { merge_request.merge_request_pipelines.first }
+ let(:pipeline) { merge_request.pipelines_for_merge_request.first }
it 'makes detached flag false' do
expect(subject[:flags][:detached_merge_request_pipeline]).to be_falsy
diff --git a/spec/serializers/pipeline_serializer_spec.rb b/spec/serializers/pipeline_serializer_spec.rb
index d9023036534..54e6abc2d3a 100644
--- a/spec/serializers/pipeline_serializer_spec.rb
+++ b/spec/serializers/pipeline_serializer_spec.rb
@@ -156,8 +156,8 @@ describe PipelineSerializer do
it 'verifies number of queries', :request_store do
recorded = ActiveRecord::QueryRecorder.new { subject }
-
expected_queries = Gitlab.ee? ? 38 : 31
+
expect(recorded.count).to be_within(2).of(expected_queries)
expect(recorded.cached_count).to eq(0)
end
diff --git a/spec/serializers/stage_entity_spec.rb b/spec/serializers/stage_entity_spec.rb
index 2034c7891ef..6b1185d1283 100644
--- a/spec/serializers/stage_entity_spec.rb
+++ b/spec/serializers/stage_entity_spec.rb
@@ -48,6 +48,10 @@ describe StageEntity do
expect(subject[:title]).to eq 'test: passed'
end
+ it 'does not contain play_details info' do
+ expect(subject[:status][:action]).not_to be_present
+ end
+
context 'when the jobs should be grouped' do
let(:entity) { described_class.new(stage, request: request, grouped: true) }
@@ -66,5 +70,29 @@ describe StageEntity do
end
end
end
+
+ context 'with a skipped stage ' do
+ let(:stage) { create(:ci_stage_entity, status: 'skipped') }
+
+ it 'contains play_all_manual' do
+ expect(subject[:status][:action]).to be_present
+ end
+ end
+
+ context 'with a scheduled stage ' do
+ let(:stage) { create(:ci_stage_entity, status: 'scheduled') }
+
+ it 'contains play_all_manual' do
+ expect(subject[:status][:action]).to be_present
+ end
+ end
+
+ context 'with a manual stage ' do
+ let(:stage) { create(:ci_stage_entity, status: 'manual') }
+
+ it 'contains play_all_manual' do
+ expect(subject[:status][:action]).to be_present
+ end
+ end
end
end
diff --git a/spec/serializers/stage_serializer_spec.rb b/spec/serializers/stage_serializer_spec.rb
new file mode 100644
index 00000000000..aae17cfbcb9
--- /dev/null
+++ b/spec/serializers/stage_serializer_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe StageSerializer do
+ let(:project) { create(:project, :repository) }
+ let(:user) { create(:user) }
+ let(:resource) { create(:ci_stage_entity) }
+
+ let(:serializer) do
+ described_class.new(current_user: user, project: project)
+ end
+
+ subject { serializer.represent(resource) }
+
+ describe '#represent' do
+ context 'with a single entity' do
+ it 'serializes the stage object' do
+ expect(subject[:name]).to eq(resource.name)
+ end
+ end
+
+ context 'with an array of entities' do
+ let(:resource) { create_list(:ci_stage_entity, 2) }
+
+ it 'serializes the array of pipelines' do
+ expect(subject).not_to be_empty
+ end
+ end
+ end
+end
diff --git a/spec/serializers/test_case_entity_spec.rb b/spec/serializers/test_case_entity_spec.rb
index a55910f98bb..986c9feb07b 100644
--- a/spec/serializers/test_case_entity_spec.rb
+++ b/spec/serializers/test_case_entity_spec.rb
@@ -14,6 +14,7 @@ describe TestCaseEntity do
it 'contains correct test case details' do
expect(subject[:status]).to eq('success')
expect(subject[:name]).to eq('Test#sum when a is 1 and b is 3 returns summary')
+ expect(subject[:classname]).to eq('spec.test_spec')
expect(subject[:execution_time]).to eq(1.11)
end
end
@@ -24,6 +25,7 @@ describe TestCaseEntity do
it 'contains correct test case details' do
expect(subject[:status]).to eq('failed')
expect(subject[:name]).to eq('Test#sum when a is 2 and b is 2 returns summary')
+ expect(subject[:classname]).to eq('spec.test_spec')
expect(subject[:execution_time]).to eq(2.22)
end
end
diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb
index e24fe60f059..4f4776bbb27 100644
--- a/spec/services/auth/container_registry_authentication_service_spec.rb
+++ b/spec/services/auth/container_registry_authentication_service_spec.rb
@@ -285,7 +285,7 @@ describe Auth::ContainerRegistryAuthenticationService do
it_behaves_like 'not a container repository factory'
end
- context 'disallow guest to delete images since regsitry 2.7' do
+ context 'disallow guest to delete images since registry 2.7' do
before do
project.add_guest(current_user)
end
diff --git a/spec/services/auto_merge/base_service_spec.rb b/spec/services/auto_merge/base_service_spec.rb
new file mode 100644
index 00000000000..cd08e0b6f32
--- /dev/null
+++ b/spec/services/auto_merge/base_service_spec.rb
@@ -0,0 +1,178 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe AutoMerge::BaseService do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:service) { described_class.new(project, user, params) }
+ let(:merge_request) { create(:merge_request) }
+ let(:params) { {} }
+
+ describe '#execute' do
+ subject { service.execute(merge_request) }
+
+ before do
+ allow(AutoMergeProcessWorker).to receive(:perform_async) {}
+ end
+
+ it 'sets properies to the merge request' do
+ subject
+
+ merge_request.reload
+ expect(merge_request).to be_auto_merge_enabled
+ expect(merge_request.merge_user).to eq(user)
+ expect(merge_request.auto_merge_strategy).to eq('base')
+ end
+
+ it 'yields block' do
+ expect { |b| service.execute(merge_request, &b) }.to yield_control.once
+ end
+
+ it 'returns activated strategy name' do
+ is_expected.to eq(:base)
+ end
+
+ context 'when merge parameters are given' do
+ let(:params) do
+ {
+ 'commit_message' => "Merge branch 'patch-12' into 'master'",
+ 'sha' => "200fcc9c260f7219eaf0daba87d818f0922c5b18",
+ 'should_remove_source_branch' => false,
+ 'squash' => false,
+ 'squash_commit_message' => "Update README.md"
+ }
+ end
+
+ it 'sets merge parameters' do
+ subject
+
+ merge_request.reload
+ expect(merge_request.merge_params['commit_message']).to eq("Merge branch 'patch-12' into 'master'")
+ expect(merge_request.merge_params['sha']).to eq('200fcc9c260f7219eaf0daba87d818f0922c5b18')
+ expect(merge_request.merge_params['should_remove_source_branch']).to eq(false)
+ expect(merge_request.merge_params['squash']).to eq(false)
+ expect(merge_request.merge_params['squash_commit_message']).to eq('Update README.md')
+ end
+ end
+
+ context 'when strategy is merge when pipeline succeeds' do
+ let(:service) { AutoMerge::MergeWhenPipelineSucceedsService.new(project, user) }
+
+ it 'sets the auto merge strategy' do
+ subject
+
+ merge_request.reload
+ expect(merge_request.auto_merge_strategy).to eq(AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
+ end
+
+ it 'returns activated strategy name' do
+ is_expected.to eq(AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS.to_sym)
+ end
+
+ it 'calls AutoMergeProcessWorker' do
+ expect(AutoMergeProcessWorker).to receive(:perform_async).with(merge_request.id).once
+
+ subject
+ end
+ end
+
+ context 'when failed to save' do
+ before do
+ allow(merge_request).to receive(:save) { false }
+ end
+
+ it 'does not yield block' do
+ expect { |b| service.execute(merge_request, &b) }.not_to yield_control
+ end
+
+ it 'returns failed' do
+ is_expected.to eq(:failed)
+ end
+ end
+ end
+
+ describe '#update' do
+ subject { service.update(merge_request) }
+
+ let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
+
+ context 'when merge params are specified' do
+ let(:params) do
+ {
+ 'commit_message' => "Merge branch 'patch-12' into 'master'",
+ 'sha' => "200fcc9c260f7219eaf0daba87d818f0922c5b18",
+ 'should_remove_source_branch' => false,
+ 'squash' => false,
+ 'squash_commit_message' => "Update README.md"
+ }
+ end
+
+ it 'updates merge params' do
+ expect { subject }.to change {
+ merge_request.reload.merge_params.slice(*params.keys)
+ }.from({}).to(params)
+ end
+ end
+ end
+
+ describe '#cancel' do
+ subject { service.cancel(merge_request) }
+
+ let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
+
+ it 'removes properies from the merge request' do
+ subject
+
+ merge_request.reload
+ expect(merge_request).not_to be_auto_merge_enabled
+ expect(merge_request.merge_user).to be_nil
+ expect(merge_request.auto_merge_strategy).to be_nil
+ end
+
+ it 'yields block' do
+ expect { |b| service.cancel(merge_request, &b) }.to yield_control.once
+ end
+
+ it 'returns success status' do
+ expect(subject[:status]).to eq(:success)
+ end
+
+ context 'when merge params are set' do
+ before do
+ merge_request.update!(merge_params:
+ {
+ 'should_remove_source_branch' => false,
+ 'commit_message' => "Merge branch 'patch-12' into 'master'",
+ 'squash_commit_message' => "Update README.md",
+ 'auto_merge_strategy' => 'merge_when_pipeline_succeeds'
+ })
+ end
+
+ it 'removes merge parameters' do
+ subject
+
+ merge_request.reload
+ expect(merge_request.merge_params['should_remove_source_branch']).to be_nil
+ expect(merge_request.merge_params['commit_message']).to be_nil
+ expect(merge_request.merge_params['squash_commit_message']).to be_nil
+ expect(merge_request.merge_params['auto_merge_strategy']).to be_nil
+ end
+ end
+
+ context 'when failed to save' do
+ before do
+ allow(merge_request).to receive(:save) { false }
+ end
+
+ it 'does not yield block' do
+ expect { |b| service.execute(merge_request, &b) }.not_to yield_control
+ end
+
+ it 'returns error status' do
+ expect(subject[:status]).to eq(:error)
+ expect(subject[:message]).to eq("Can't cancel the automatic merge")
+ end
+ end
+ end
+end
diff --git a/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb b/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb
new file mode 100644
index 00000000000..a20bf8e17e4
--- /dev/null
+++ b/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb
@@ -0,0 +1,223 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe AutoMerge::MergeWhenPipelineSucceedsService do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+
+ let(:mr_merge_if_green_enabled) do
+ create(:merge_request, merge_when_pipeline_succeeds: true, merge_user: user,
+ source_branch: "master", target_branch: 'feature',
+ source_project: project, target_project: project, state: "opened")
+ end
+
+ let(:pipeline) do
+ create(:ci_pipeline_with_one_job, ref: mr_merge_if_green_enabled.source_branch,
+ project: project)
+ end
+
+ let(:service) do
+ described_class.new(project, user, commit_message: 'Awesome message')
+ end
+
+ describe "#available_for?" do
+ subject { service.available_for?(mr_merge_if_green_enabled) }
+
+ let(:pipeline_status) { :running }
+
+ before do
+ create(:ci_pipeline, pipeline_status, ref: mr_merge_if_green_enabled.source_branch,
+ sha: mr_merge_if_green_enabled.diff_head_sha,
+ project: mr_merge_if_green_enabled.source_project)
+ mr_merge_if_green_enabled.update_head_pipeline
+ end
+
+ it { is_expected.to be_truthy }
+
+ context 'when the head piipeline succeeded' do
+ let(:pipeline_status) { :success }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+
+ describe "#execute" do
+ let(:merge_request) do
+ create(:merge_request, target_project: project, source_project: project,
+ source_branch: "feature", target_branch: 'master')
+ end
+
+ context 'first time enabling' do
+ before do
+ allow(merge_request)
+ .to receive_messages(head_pipeline: pipeline, actual_head_pipeline: pipeline)
+
+ service.execute(merge_request)
+ end
+
+ it 'sets the params, merge_user, and flag' do
+ expect(merge_request).to be_valid
+ expect(merge_request.merge_when_pipeline_succeeds).to be_truthy
+ expect(merge_request.merge_params).to include commit_message: 'Awesome message'
+ expect(merge_request.merge_user).to be user
+ end
+
+ it 'creates a system note' do
+ note = merge_request.notes.last
+ expect(note.note).to match %r{enabled an automatic merge when the pipeline for (\w+/\w+@)?\h{8}}
+ end
+ end
+
+ context 'already approved' do
+ let(:service) { described_class.new(project, user, new_key: true) }
+ let(:build) { create(:ci_build, ref: mr_merge_if_green_enabled.source_branch) }
+
+ before do
+ allow(mr_merge_if_green_enabled)
+ .to receive_messages(head_pipeline: pipeline, actual_head_pipeline: pipeline)
+
+ allow(mr_merge_if_green_enabled).to receive(:mergeable?)
+ .and_return(true)
+
+ allow(pipeline).to receive(:success?).and_return(true)
+ end
+
+ it 'updates the merge params' do
+ expect(SystemNoteService).not_to receive(:merge_when_pipeline_succeeds)
+
+ service.execute(mr_merge_if_green_enabled)
+ expect(mr_merge_if_green_enabled.merge_params).to have_key(:new_key)
+ end
+ end
+ end
+
+ describe "#process" do
+ let(:merge_request_ref) { mr_merge_if_green_enabled.source_branch }
+ let(:merge_request_head) do
+ project.commit(mr_merge_if_green_enabled.source_branch).id
+ end
+
+ context 'when triggered by pipeline with valid ref and sha' do
+ let(:triggering_pipeline) do
+ create(:ci_pipeline, project: project, ref: merge_request_ref,
+ sha: merge_request_head, status: 'success',
+ head_pipeline_of: mr_merge_if_green_enabled)
+ end
+
+ it "merges all merge requests with merge when the pipeline succeeds enabled" do
+ allow(mr_merge_if_green_enabled)
+ .to receive_messages(head_pipeline: triggering_pipeline, actual_head_pipeline: triggering_pipeline)
+
+ expect(MergeWorker).to receive(:perform_async)
+ service.process(mr_merge_if_green_enabled)
+ end
+ end
+
+ context 'when triggered by an old pipeline' do
+ let(:old_pipeline) do
+ create(:ci_pipeline, project: project, ref: merge_request_ref,
+ sha: '1234abcdef', status: 'success')
+ end
+
+ it 'does not merge request' do
+ expect(MergeWorker).not_to receive(:perform_async)
+ service.process(mr_merge_if_green_enabled)
+ end
+ end
+
+ context 'when triggered by pipeline from a different branch' do
+ let(:unrelated_pipeline) do
+ create(:ci_pipeline, project: project, ref: 'feature',
+ sha: merge_request_head, status: 'success')
+ end
+
+ it 'does not merge request' do
+ expect(MergeWorker).not_to receive(:perform_async)
+ service.process(mr_merge_if_green_enabled)
+ end
+ end
+
+ context 'when pipeline is merge request pipeline' do
+ let(:pipeline) do
+ create(:ci_pipeline, :success,
+ source: :merge_request_event,
+ ref: mr_merge_if_green_enabled.merge_ref_path,
+ merge_request: mr_merge_if_green_enabled,
+ merge_requests_as_head_pipeline: [mr_merge_if_green_enabled])
+ end
+
+ it 'merges the associated merge request' do
+ allow(mr_merge_if_green_enabled)
+ .to receive_messages(head_pipeline: pipeline, actual_head_pipeline: pipeline)
+
+ expect(MergeWorker).to receive(:perform_async)
+ service.process(mr_merge_if_green_enabled)
+ end
+ end
+ end
+
+ describe "#cancel" do
+ before do
+ service.cancel(mr_merge_if_green_enabled)
+ end
+
+ it "resets all the pipeline succeeds params" do
+ expect(mr_merge_if_green_enabled.merge_when_pipeline_succeeds).to be_falsey
+ expect(mr_merge_if_green_enabled.merge_params).to eq({})
+ expect(mr_merge_if_green_enabled.merge_user).to be nil
+ end
+
+ it 'Posts a system note' do
+ note = mr_merge_if_green_enabled.notes.last
+ expect(note.note).to include 'canceled the automatic merge'
+ end
+ end
+
+ describe 'pipeline integration' do
+ context 'when there are multiple stages in the pipeline' do
+ let(:ref) { mr_merge_if_green_enabled.source_branch }
+ let(:sha) { project.commit(ref).id }
+
+ let(:pipeline) do
+ create(:ci_empty_pipeline, ref: ref, sha: sha, project: project)
+ end
+
+ let!(:build) do
+ create(:ci_build, :created, pipeline: pipeline, ref: ref,
+ name: 'build', stage: 'build')
+ end
+
+ let!(:test) do
+ create(:ci_build, :created, pipeline: pipeline, ref: ref,
+ name: 'test', stage: 'test')
+ end
+
+ before do
+ # This behavior of MergeRequest: we instantiate a new object
+ #
+ allow_any_instance_of(MergeRequest)
+ .to receive(:head_pipeline)
+ .and_wrap_original do
+ Ci::Pipeline.find(pipeline.id)
+ end
+ end
+
+ it "doesn't merge if any of stages failed" do
+ expect(MergeWorker).not_to receive(:perform_async)
+
+ build.success
+ test.reload
+ test.drop
+ end
+
+ it 'merges when all stages succeeded' do
+ expect(MergeWorker).to receive(:perform_async)
+
+ build.success
+ test.reload
+ test.success
+ end
+ end
+ end
+end
diff --git a/spec/services/auto_merge_service_spec.rb b/spec/services/auto_merge_service_spec.rb
new file mode 100644
index 00000000000..93a22e60498
--- /dev/null
+++ b/spec/services/auto_merge_service_spec.rb
@@ -0,0 +1,164 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe AutoMergeService do
+ set(:project) { create(:project) }
+ set(:user) { create(:user) }
+ let(:service) { described_class.new(project, user) }
+
+ describe '.all_strategies' do
+ subject { described_class.all_strategies }
+
+ it 'includes merge when pipeline succeeds' do
+ is_expected.to include(AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
+ end
+ end
+
+ describe '#available_strategies' do
+ subject { service.available_strategies(merge_request) }
+
+ let(:merge_request) { create(:merge_request) }
+ let(:pipeline_status) { :running }
+
+ before do
+ create(:ci_pipeline, pipeline_status, ref: merge_request.source_branch,
+ sha: merge_request.diff_head_sha,
+ project: merge_request.source_project)
+
+ merge_request.update_head_pipeline
+ end
+
+ it 'returns available strategies' do
+ is_expected.to include('merge_when_pipeline_succeeds')
+ end
+
+ context 'when the head piipeline succeeded' do
+ let(:pipeline_status) { :success }
+
+ it 'returns available strategies' do
+ is_expected.to be_empty
+ end
+ end
+ end
+
+ describe '.get_service_class' do
+ subject { described_class.get_service_class(strategy) }
+
+ let(:strategy) { AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS }
+
+ it 'returns service instance' do
+ is_expected.to eq(AutoMerge::MergeWhenPipelineSucceedsService)
+ end
+
+ context 'when strategy is not present' do
+ let(:strategy) { }
+
+ it 'returns nil' do
+ is_expected.to be_nil
+ end
+ end
+ end
+
+ describe '#execute' do
+ subject { service.execute(merge_request, strategy) }
+
+ let(:merge_request) { create(:merge_request) }
+ let(:pipeline_status) { :running }
+ let(:strategy) { AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS }
+
+ before do
+ create(:ci_pipeline, pipeline_status, ref: merge_request.source_branch,
+ sha: merge_request.diff_head_sha,
+ project: merge_request.source_project)
+
+ merge_request.update_head_pipeline
+ end
+
+ it 'delegates to a relevant service instance' do
+ expect_next_instance_of(AutoMerge::MergeWhenPipelineSucceedsService) do |service|
+ expect(service).to receive(:execute).with(merge_request)
+ end
+
+ subject
+ end
+
+ context 'when the head piipeline succeeded' do
+ let(:pipeline_status) { :success }
+
+ it 'returns failed' do
+ is_expected.to eq(:failed)
+ end
+ end
+ end
+
+ describe '#update' do
+ subject { service.update(merge_request) }
+
+ context 'when auto merge is enabled' do
+ let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
+
+ it 'delegates to a relevant service instance' do
+ expect_next_instance_of(AutoMerge::MergeWhenPipelineSucceedsService) do |service|
+ expect(service).to receive(:update).with(merge_request)
+ end
+
+ subject
+ end
+ end
+
+ context 'when auto merge is not enabled' do
+ let(:merge_request) { create(:merge_request) }
+
+ it 'returns failed' do
+ is_expected.to eq(:failed)
+ end
+ end
+ end
+
+ describe '#process' do
+ subject { service.process(merge_request) }
+
+ let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
+
+ it 'delegates to a relevant service instance' do
+ expect_next_instance_of(AutoMerge::MergeWhenPipelineSucceedsService) do |service|
+ expect(service).to receive(:process).with(merge_request)
+ end
+
+ subject
+ end
+
+ context 'when auto merge is not enabled' do
+ let(:merge_request) { create(:merge_request) }
+
+ it 'returns nil' do
+ is_expected.to be_nil
+ end
+ end
+ end
+
+ describe '#cancel' do
+ subject { service.cancel(merge_request) }
+
+ let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
+
+ it 'delegates to a relevant service instance' do
+ expect_next_instance_of(AutoMerge::MergeWhenPipelineSucceedsService) do |service|
+ expect(service).to receive(:cancel).with(merge_request)
+ end
+
+ subject
+ end
+
+ context 'when auto merge is not enabled' do
+ let(:merge_request) { create(:merge_request) }
+
+ it 'returns error' do
+ expect(subject[:message]).to eq("Can't cancel the automatic merge")
+ expect(subject[:status]).to eq(:error)
+ expect(subject[:http_status]).to eq(406)
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index 8a80652b3d8..867692d4d64 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -773,7 +773,7 @@ describe Ci::CreatePipelineService do
end
end
- describe 'Merge request pipelines' do
+ describe 'Pipelines for merge requests' do
let(:pipeline) do
execute_service(source: source,
merge_request: merge_request,
@@ -817,12 +817,14 @@ describe Ci::CreatePipelineService do
let(:merge_request) do
create(:merge_request,
source_project: project,
- source_branch: Gitlab::Git.ref_name(ref_name),
+ source_branch: 'feature',
target_project: project,
target_branch: 'master')
end
- it 'creates a merge request pipeline' do
+ let(:ref_name) { merge_request.ref_path }
+
+ it 'creates a detached merge request pipeline' do
expect(pipeline).to be_persisted
expect(pipeline).to be_merge_request_event
expect(pipeline.merge_request).to eq(merge_request)
@@ -837,6 +839,13 @@ describe Ci::CreatePipelineService do
expect(pipeline.target_sha).to be_nil
end
+ it 'schedules update for the head pipeline of the merge request' do
+ expect(UpdateHeadPipelineForMergeRequestWorker)
+ .to receive(:perform_async).with(merge_request.id)
+
+ pipeline
+ end
+
context 'when target sha is specified' do
let(:target_sha) { merge_request.target_branch_sha }
@@ -858,15 +867,16 @@ describe Ci::CreatePipelineService do
let(:merge_request) do
create(:merge_request,
source_project: project,
- source_branch: Gitlab::Git.ref_name(ref_name),
+ source_branch: 'feature',
target_project: target_project,
target_branch: 'master')
end
+ let(:ref_name) { 'refs/heads/feature' }
let!(:project) { fork_project(target_project, nil, repository: true) }
let!(:target_project) { create(:project, :repository) }
- it 'creates a merge request pipeline in the forked project' do
+ it 'creates a legacy detached merge request pipeline in the forked project' do
expect(pipeline).to be_persisted
expect(project.ci_pipelines).to eq([pipeline])
expect(target_project.ci_pipelines).to be_empty
@@ -884,7 +894,7 @@ describe Ci::CreatePipelineService do
}
end
- it 'does not create a merge request pipeline' do
+ it 'does not create a detached merge request pipeline' do
expect(pipeline).not_to be_persisted
expect(pipeline.errors[:base]).to eq(["No stages / jobs for this pipeline."])
end
@@ -894,7 +904,7 @@ describe Ci::CreatePipelineService do
context 'when merge request is not specified' do
let(:merge_request) { nil }
- it 'does not create a merge request pipeline' do
+ it 'does not create a detached merge request pipeline' do
expect(pipeline).not_to be_persisted
expect(pipeline.errors[:merge_request]).to eq(["can't be blank"])
end
@@ -928,7 +938,7 @@ describe Ci::CreatePipelineService do
target_branch: 'master')
end
- it 'does not create a merge request pipeline' do
+ it 'does not create a detached merge request pipeline' do
expect(pipeline).not_to be_persisted
expect(pipeline.errors[:base])
@@ -939,7 +949,7 @@ describe Ci::CreatePipelineService do
context 'when merge request is not specified' do
let(:merge_request) { nil }
- it 'does not create a merge request pipeline' do
+ it 'does not create a detached merge request pipeline' do
expect(pipeline).not_to be_persisted
expect(pipeline.errors[:base])
@@ -963,12 +973,12 @@ describe Ci::CreatePipelineService do
let(:merge_request) do
create(:merge_request,
source_project: project,
- source_branch: ref_name,
+ source_branch: Gitlab::Git.ref_name(ref_name),
target_project: project,
target_branch: 'master')
end
- it 'does not create a merge request pipeline' do
+ it 'does not create a detached merge request pipeline' do
expect(pipeline).not_to be_persisted
expect(pipeline.errors[:base])
@@ -994,12 +1004,12 @@ describe Ci::CreatePipelineService do
let(:merge_request) do
create(:merge_request,
source_project: project,
- source_branch: ref_name,
+ source_branch: Gitlab::Git.ref_name(ref_name),
target_project: project,
target_branch: 'master')
end
- it 'does not create a merge request pipeline' do
+ it 'does not create a detached merge request pipeline' do
expect(pipeline).not_to be_persisted
expect(pipeline.errors[:base])
@@ -1023,12 +1033,12 @@ describe Ci::CreatePipelineService do
let(:merge_request) do
create(:merge_request,
source_project: project,
- source_branch: ref_name,
+ source_branch: Gitlab::Git.ref_name(ref_name),
target_project: project,
target_branch: 'master')
end
- it 'does not create a merge request pipeline' do
+ it 'does not create a detached merge request pipeline' do
expect(pipeline).not_to be_persisted
expect(pipeline.errors[:base])
diff --git a/spec/services/ci/pipeline_schedule_service_spec.rb b/spec/services/ci/pipeline_schedule_service_spec.rb
new file mode 100644
index 00000000000..867ed0acc0d
--- /dev/null
+++ b/spec/services/ci/pipeline_schedule_service_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Ci::PipelineScheduleService do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:service) { described_class.new(project, user) }
+
+ describe '#execute' do
+ subject { service.execute(schedule) }
+
+ let(:schedule) { create(:ci_pipeline_schedule, project: project, owner: user) }
+
+ it 'schedules next run' do
+ expect(schedule).to receive(:schedule_next_run!)
+
+ subject
+ end
+
+ it 'runs RunPipelineScheduleWorker' do
+ expect(RunPipelineScheduleWorker)
+ .to receive(:perform_async).with(schedule.id, schedule.owner.id)
+
+ subject
+ end
+
+ context 'when owner is nil' do
+ let(:schedule) { create(:ci_pipeline_schedule, project: project, owner: nil) }
+
+ it 'does not raise an error' do
+ expect { subject }.not_to raise_error
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/play_manual_stage_service_spec.rb b/spec/services/ci/play_manual_stage_service_spec.rb
new file mode 100644
index 00000000000..5d812745c7f
--- /dev/null
+++ b/spec/services/ci/play_manual_stage_service_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Ci::PlayManualStageService, '#execute' do
+ let(:current_user) { create(:user) }
+ let(:pipeline) { create(:ci_pipeline, user: current_user) }
+ let(:project) { pipeline.project }
+ let(:service) { described_class.new(project, current_user, pipeline: pipeline) }
+ let(:stage_status) { 'manual' }
+
+ let(:stage) do
+ create(:ci_stage_entity,
+ pipeline: pipeline,
+ project: project,
+ name: 'test')
+ end
+
+ before do
+ project.add_maintainer(current_user)
+ create_builds_for_stage(status: stage_status)
+ end
+
+ context 'when pipeline has manual builds' do
+ before do
+ service.execute(stage)
+ end
+
+ it 'starts manual builds from pipeline' do
+ expect(pipeline.builds.manual.count).to eq(0)
+ end
+
+ it 'updates manual builds' do
+ pipeline.builds.each do |build|
+ expect(build.user).to eq(current_user)
+ end
+ end
+ end
+
+ context 'when pipeline has no manual builds' do
+ let(:stage_status) { 'failed' }
+
+ before do
+ service.execute(stage)
+ end
+
+ it 'does not update the builds' do
+ expect(pipeline.builds.failed.count).to eq(3)
+ end
+ end
+
+ context 'when user does not have permission on a specific build' do
+ before do
+ allow_any_instance_of(Ci::Build).to receive(:play)
+ .and_raise(Gitlab::Access::AccessDeniedError)
+
+ service.execute(stage)
+ end
+
+ it 'logs the error' do
+ expect(Gitlab::AppLogger).to receive(:error)
+ .exactly(stage.builds.manual.count)
+
+ service.execute(stage)
+ end
+ end
+
+ def create_builds_for_stage(options)
+ options.merge!({
+ when: 'manual',
+ pipeline: pipeline,
+ stage: stage.name,
+ stage_id: stage.id,
+ user: pipeline.user
+ })
+
+ create_list(:ci_build, 3, options)
+ end
+end
diff --git a/spec/services/ci/retry_build_service_spec.rb b/spec/services/ci/retry_build_service_spec.rb
index df2376384ca..e9a26400723 100644
--- a/spec/services/ci/retry_build_service_spec.rb
+++ b/spec/services/ci/retry_build_service_spec.rb
@@ -23,7 +23,7 @@ describe Ci::RetryBuildService do
REJECT_ACCESSORS =
%i[id status user token token_encrypted coverage trace runner
- artifacts_expire_at artifacts_file artifacts_metadata artifacts_size
+ artifacts_expire_at
created_at updated_at started_at finished_at queued_at erased_by
erased_at auto_canceled_by job_artifacts job_artifacts_archive
job_artifacts_metadata job_artifacts_trace job_artifacts_junit
@@ -38,7 +38,8 @@ describe Ci::RetryBuildService do
runner_id tag_taggings taggings tags trigger_request_id
user_id auto_canceled_by_id retried failure_reason
sourced_pipelines artifacts_file_store artifacts_metadata_store
- metadata runner_session trace_chunks].freeze
+ metadata runner_session trace_chunks
+ artifacts_file artifacts_metadata artifacts_size].freeze
shared_examples 'build duplication' do
let(:another_pipeline) { create(:ci_empty_pipeline, project: project) }
diff --git a/spec/services/ci/stop_environments_service_spec.rb b/spec/services/ci/stop_environments_service_spec.rb
index 31b8d540356..890fa5bc009 100644
--- a/spec/services/ci/stop_environments_service_spec.rb
+++ b/spec/services/ci/stop_environments_service_spec.rb
@@ -105,6 +105,82 @@ describe Ci::StopEnvironmentsService do
end
end
+ describe '#execute_for_merge_request' do
+ subject { service.execute_for_merge_request(merge_request) }
+
+ let(:merge_request) { create(:merge_request, source_branch: 'feature', target_branch: 'master') }
+ let(:project) { merge_request.project }
+ let(:user) { create(:user) }
+
+ let(:pipeline) do
+ create(:ci_pipeline,
+ source: :merge_request_event,
+ merge_request: merge_request,
+ project: project,
+ sha: merge_request.diff_head_sha,
+ merge_requests_as_head_pipeline: [merge_request])
+ end
+
+ let!(:review_job) { create(:ci_build, :start_review_app, pipeline: pipeline, project: project) }
+ let!(:stop_review_job) { create(:ci_build, :stop_review_app, :manual, pipeline: pipeline, project: project) }
+
+ before do
+ review_job.deployment.success!
+ end
+
+ it 'has active environment at first' do
+ expect(pipeline.environments.first).to be_available
+ end
+
+ context 'when user is a developer' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'stops the active environment' do
+ subject
+
+ expect(pipeline.environments.first).to be_stopped
+ end
+ end
+
+ context 'when user is a reporter' do
+ before do
+ project.add_reporter(user)
+ end
+
+ it 'does not stop the active environment' do
+ subject
+
+ expect(pipeline.environments.first).to be_available
+ end
+ end
+
+ context 'when pipeline is not associated with environments' do
+ let!(:job) { create(:ci_build, pipeline: pipeline, project: project) }
+
+ it 'does not raise exception' do
+ expect { subject }.not_to raise_exception
+ end
+ end
+
+ context 'when pipeline is not a pipeline for merge request' do
+ let(:pipeline) do
+ create(:ci_pipeline,
+ project: project,
+ ref: 'feature',
+ sha: merge_request.diff_head_sha,
+ merge_requests_as_head_pipeline: [merge_request])
+ end
+
+ it 'does not stop the active environment' do
+ subject
+
+ expect(pipeline.environments.first).to be_available
+ end
+ end
+ end
+
def expect_environment_stopped_on(branch)
expect_any_instance_of(Environment)
.to receive(:stop!)
diff --git a/spec/services/clusters/applications/check_installation_progress_service_spec.rb b/spec/services/clusters/applications/check_installation_progress_service_spec.rb
index 8ad90aaf720..a54bd85a11a 100644
--- a/spec/services/clusters/applications/check_installation_progress_service_spec.rb
+++ b/spec/services/clusters/applications/check_installation_progress_service_spec.rb
@@ -18,7 +18,7 @@ describe Clusters::Applications::CheckInstallationProgressService, '#execute' do
end
context "when phase is #{a_phase}" do
- context 'when not timeouted' do
+ context 'when not timed_out' do
it 'reschedule a new check' do
expect(ClusterWaitForAppInstallationWorker).to receive(:perform_in).once
expect(service).not_to receive(:remove_installation_pod)
@@ -113,7 +113,7 @@ describe Clusters::Applications::CheckInstallationProgressService, '#execute' do
end
context 'when timed out' do
- let(:application) { create(:clusters_applications_helm, :timeouted, :updating) }
+ let(:application) { create(:clusters_applications_helm, :timed_out, :updating) }
before do
expect(service).to receive(:installation_phase).once.and_return(phase)
@@ -174,7 +174,7 @@ describe Clusters::Applications::CheckInstallationProgressService, '#execute' do
end
context 'when timed out' do
- let(:application) { create(:clusters_applications_helm, :timeouted) }
+ let(:application) { create(:clusters_applications_helm, :timed_out) }
before do
expect(service).to receive(:installation_phase).once.and_return(phase)
diff --git a/spec/services/clusters/applications/check_uninstall_progress_service_spec.rb b/spec/services/clusters/applications/check_uninstall_progress_service_spec.rb
new file mode 100644
index 00000000000..9ab83d913f5
--- /dev/null
+++ b/spec/services/clusters/applications/check_uninstall_progress_service_spec.rb
@@ -0,0 +1,145 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Clusters::Applications::CheckUninstallProgressService do
+ RESCHEDULE_PHASES = Gitlab::Kubernetes::Pod::PHASES - [Gitlab::Kubernetes::Pod::SUCCEEDED, Gitlab::Kubernetes::Pod::FAILED].freeze
+
+ let(:application) { create(:clusters_applications_prometheus, :uninstalling) }
+ let(:service) { described_class.new(application) }
+ let(:phase) { Gitlab::Kubernetes::Pod::UNKNOWN }
+ let(:errors) { nil }
+ let(:worker_class) { Clusters::Applications::WaitForUninstallAppWorker }
+
+ before do
+ allow(service).to receive(:installation_errors).and_return(errors)
+ allow(service).to receive(:remove_installation_pod)
+ end
+
+ shared_examples 'a not yet terminated installation' do |a_phase|
+ let(:phase) { a_phase }
+
+ before do
+ expect(service).to receive(:installation_phase).once.and_return(phase)
+ end
+
+ context "when phase is #{a_phase}" do
+ context 'when not timed_out' do
+ it 'reschedule a new check' do
+ expect(worker_class).to receive(:perform_in).once
+ expect(service).not_to receive(:remove_installation_pod)
+
+ expect do
+ service.execute
+
+ application.reload
+ end.not_to change(application, :status)
+
+ expect(application.status_reason).to be_nil
+ end
+ end
+ end
+ end
+
+ context 'when application is installing' do
+ RESCHEDULE_PHASES.each { |phase| it_behaves_like 'a not yet terminated installation', phase }
+
+ context 'when installation POD succeeded' do
+ let(:phase) { Gitlab::Kubernetes::Pod::SUCCEEDED }
+ before do
+ expect(service).to receive(:installation_phase).once.and_return(phase)
+ end
+
+ it 'removes the installation POD' do
+ expect(service).to receive(:remove_installation_pod).once
+
+ service.execute
+ end
+
+ it 'destroys the application' do
+ expect(worker_class).not_to receive(:perform_in)
+
+ service.execute
+
+ expect(application).to be_destroyed
+ end
+
+ context 'an error occurs while destroying' do
+ before do
+ expect(application).to receive(:destroy!).once.and_raise("destroy failed")
+ end
+
+ it 'still removes the installation POD' do
+ expect(service).to receive(:remove_installation_pod).once
+
+ service.execute
+ end
+
+ it 'makes the application uninstall_errored' do
+ service.execute
+
+ expect(application).to be_uninstall_errored
+ expect(application.status_reason).to eq('Application uninstalled but failed to destroy: destroy failed')
+ end
+ end
+ end
+
+ context 'when installation POD failed' do
+ let(:phase) { Gitlab::Kubernetes::Pod::FAILED }
+ let(:errors) { 'test installation failed' }
+
+ before do
+ expect(service).to receive(:installation_phase).once.and_return(phase)
+ end
+
+ it 'make the application errored' do
+ service.execute
+
+ expect(application).to be_uninstall_errored
+ expect(application.status_reason).to eq('Operation failed. Check pod logs for uninstall-prometheus for more details.')
+ end
+ end
+
+ context 'when timed out' do
+ let(:application) { create(:clusters_applications_prometheus, :timed_out, :uninstalling) }
+
+ before do
+ expect(service).to receive(:installation_phase).once.and_return(phase)
+ end
+
+ it 'make the application errored' do
+ expect(worker_class).not_to receive(:perform_in)
+
+ service.execute
+
+ expect(application).to be_uninstall_errored
+ expect(application.status_reason).to eq('Operation timed out. Check pod logs for uninstall-prometheus for more details.')
+ end
+ end
+
+ context 'when installation raises a Kubeclient::HttpError' do
+ let(:cluster) { create(:cluster, :provided_by_user, :project) }
+ let(:logger) { service.send(:logger) }
+ let(:error) { Kubeclient::HttpError.new(401, 'Unauthorized', nil) }
+
+ before do
+ application.update!(cluster: cluster)
+
+ expect(service).to receive(:installation_phase).and_raise(error)
+ end
+
+ include_examples 'logs kubernetes errors' do
+ let(:error_name) { 'Kubeclient::HttpError' }
+ let(:error_message) { 'Unauthorized' }
+ let(:error_code) { 401 }
+ end
+
+ it 'shows the response code from the error' do
+ service.execute
+
+ expect(application).to be_uninstall_errored
+ expect(application.status_reason).to eq('Kubernetes error: 401')
+ end
+ end
+ end
+end
diff --git a/spec/services/clusters/applications/create_service_spec.rb b/spec/services/clusters/applications/create_service_spec.rb
index 20555873503..bb86a742f0e 100644
--- a/spec/services/clusters/applications/create_service_spec.rb
+++ b/spec/services/clusters/applications/create_service_spec.rb
@@ -151,8 +151,8 @@ describe Clusters::Applications::CreateService do
'helm' | :application_helm | true | false
'ingress' | :application_ingress | true | true
'runner' | :application_runner | true | true
+ 'prometheus' | :application_prometheus | true | true
'jupyter' | :application_jupyter | false | true
- 'prometheus' | :application_prometheus | false | true
end
with_them do
diff --git a/spec/services/clusters/applications/destroy_service_spec.rb b/spec/services/clusters/applications/destroy_service_spec.rb
new file mode 100644
index 00000000000..8d9dc6a0f11
--- /dev/null
+++ b/spec/services/clusters/applications/destroy_service_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Clusters::Applications::DestroyService, '#execute' do
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:user) { create(:user) }
+ let(:params) { { application: 'prometheus' } }
+ let(:service) { described_class.new(cluster, user, params) }
+ let(:test_request) { double }
+ let(:worker_class) { Clusters::Applications::UninstallWorker }
+
+ subject { service.execute(test_request) }
+
+ before do
+ allow(worker_class).to receive(:perform_async)
+ end
+
+ context 'application is not installed' do
+ it 'raises Clusters::Applications::BaseService::InvalidApplicationError' do
+ expect(worker_class).not_to receive(:perform_async)
+
+ expect { subject }
+ .to raise_exception { Clusters::Applications::BaseService::InvalidApplicationError }
+ .and not_change { Clusters::Applications::Prometheus.count }
+ .and not_change { Clusters::Applications::Prometheus.with_status(:scheduled).count }
+ end
+ end
+
+ context 'application is installed' do
+ context 'application is schedulable' do
+ let!(:application) do
+ create(:clusters_applications_prometheus, :installed, cluster: cluster)
+ end
+
+ it 'makes application scheduled!' do
+ subject
+
+ expect(application.reload).to be_scheduled
+ end
+
+ it 'schedules UninstallWorker' do
+ expect(worker_class).to receive(:perform_async).with(application.name, application.id)
+
+ subject
+ end
+ end
+
+ context 'application is not schedulable' do
+ let!(:application) do
+ create(:clusters_applications_prometheus, :updating, cluster: cluster)
+ end
+
+ it 'raises StateMachines::InvalidTransition' do
+ expect(worker_class).not_to receive(:perform_async)
+
+ expect { subject }
+ .to raise_exception { StateMachines::InvalidTransition }
+ .and not_change { Clusters::Applications::Prometheus.with_status(:scheduled).count }
+ end
+ end
+ end
+end
diff --git a/spec/services/clusters/applications/uninstall_service_spec.rb b/spec/services/clusters/applications/uninstall_service_spec.rb
new file mode 100644
index 00000000000..16497d752b2
--- /dev/null
+++ b/spec/services/clusters/applications/uninstall_service_spec.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Clusters::Applications::UninstallService, '#execute' do
+ let(:application) { create(:clusters_applications_prometheus, :scheduled) }
+ let(:service) { described_class.new(application) }
+ let(:helm_client) { instance_double(Gitlab::Kubernetes::Helm::Api) }
+ let(:worker_class) { Clusters::Applications::WaitForUninstallAppWorker }
+
+ before do
+ allow(service).to receive(:helm_api).and_return(helm_client)
+ end
+
+ context 'when there are no errors' do
+ before do
+ expect(helm_client).to receive(:uninstall).with(kind_of(Gitlab::Kubernetes::Helm::DeleteCommand))
+ allow(worker_class).to receive(:perform_in).and_return(nil)
+ end
+
+ it 'make the application to be uninstalling' do
+ expect(application.cluster).not_to be_nil
+ service.execute
+
+ expect(application).to be_uninstalling
+ end
+
+ it 'schedule async installation status check' do
+ expect(worker_class).to receive(:perform_in).once
+
+ service.execute
+ end
+ end
+
+ context 'when k8s cluster communication fails' do
+ let(:error) { Kubeclient::HttpError.new(500, 'system failure', nil) }
+
+ before do
+ expect(helm_client).to receive(:uninstall).with(kind_of(Gitlab::Kubernetes::Helm::DeleteCommand)).and_raise(error)
+ end
+
+ include_examples 'logs kubernetes errors' do
+ let(:error_name) { 'Kubeclient::HttpError' }
+ let(:error_message) { 'system failure' }
+ let(:error_code) { 500 }
+ end
+
+ it 'make the application errored' do
+ service.execute
+
+ expect(application).to be_uninstall_errored
+ expect(application.status_reason).to match('Kubernetes error: 500')
+ end
+ end
+
+ context 'a non kubernetes error happens' do
+ let(:application) { create(:clusters_applications_prometheus, :scheduled) }
+ let(:error) { StandardError.new('something bad happened') }
+
+ before do
+ expect(helm_client).to receive(:uninstall).with(kind_of(Gitlab::Kubernetes::Helm::DeleteCommand)).and_raise(error)
+ end
+
+ include_examples 'logs kubernetes errors' do
+ let(:error_name) { 'StandardError' }
+ let(:error_message) { 'something bad happened' }
+ let(:error_code) { nil }
+ end
+
+ it 'make the application errored' do
+ service.execute
+
+ expect(application).to be_uninstall_errored
+ expect(application.status_reason).to eq('Failed to uninstall.')
+ end
+ end
+end
diff --git a/spec/services/clusters/build_service_spec.rb b/spec/services/clusters/build_service_spec.rb
index da0cb42b3a1..f3e852726f4 100644
--- a/spec/services/clusters/build_service_spec.rb
+++ b/spec/services/clusters/build_service_spec.rb
@@ -21,5 +21,13 @@ describe Clusters::BuildService do
is_expected.to be_group_type
end
end
+
+ describe 'when cluster subject is an instance' do
+ let(:cluster_subject) { Clusters::Instance.new }
+
+ it 'sets the cluster_type to instance_type' do
+ is_expected.to be_instance_type
+ end
+ end
end
end
diff --git a/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb b/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb
index 18f218fc236..be052a07da7 100644
--- a/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb
+++ b/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb
@@ -113,7 +113,7 @@ describe Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService, '#execute' d
it 'does not create any Clusters::KubernetesNamespace' do
subject
- expect(cluster.kubernetes_namespace).to eq(kubernetes_namespace)
+ expect(cluster.kubernetes_namespaces).to eq([kubernetes_namespace])
end
it 'creates project service account' do
diff --git a/spec/services/clusters/refresh_service_spec.rb b/spec/services/clusters/refresh_service_spec.rb
index 58ab3c3cf73..5bc8a709941 100644
--- a/spec/services/clusters/refresh_service_spec.rb
+++ b/spec/services/clusters/refresh_service_spec.rb
@@ -93,7 +93,7 @@ describe Clusters::RefreshService do
let(:group) { cluster.group }
let(:project) { create(:project, group: group) }
- include_examples 'creates a kubernetes namespace'
+ include_examples 'does not create a kubernetes namespace'
context 'when project already has kubernetes namespace' do
before do
@@ -103,5 +103,11 @@ describe Clusters::RefreshService do
include_examples 'does not create a kubernetes namespace'
end
end
+
+ context 'cluster is not managed' do
+ let!(:cluster) { create(:cluster, :project, :not_managed, projects: [project]) }
+
+ include_examples 'does not create a kubernetes namespace'
+ end
end
end
diff --git a/spec/services/compare_service_spec.rb b/spec/services/compare_service_spec.rb
index 0e4ef69ec19..fadd43635a6 100644
--- a/spec/services/compare_service_spec.rb
+++ b/spec/services/compare_service_spec.rb
@@ -19,5 +19,18 @@ describe CompareService do
it { expect(subject.diffs.size).to eq(3) }
end
+
+ context 'compare with target branch that does not exist' do
+ subject { service.execute(project, 'non-existent-ref') }
+
+ it { expect(subject).to be_nil }
+ end
+
+ context 'compare with source branch that does not exist' do
+ let(:service) { described_class.new(project, 'non-existent-branch') }
+ subject { service.execute(project, 'non-existent-ref') }
+
+ it { expect(subject).to be_nil }
+ end
end
end
diff --git a/spec/services/delete_branch_service_spec.rb b/spec/services/delete_branch_service_spec.rb
index 43a70d33d2d..b8064c2cbc1 100644
--- a/spec/services/delete_branch_service_spec.rb
+++ b/spec/services/delete_branch_service_spec.rb
@@ -8,20 +8,24 @@ describe DeleteBranchService do
let(:user) { create(:user) }
let(:service) { described_class.new(project, user) }
+ shared_examples 'a deleted branch' do |branch_name|
+ it 'removes the branch' do
+ expect(branch_exists?(branch_name)).to be true
+
+ result = service.execute(branch_name)
+
+ expect(result.status).to eq :success
+ expect(branch_exists?(branch_name)).to be false
+ end
+ end
+
describe '#execute' do
context 'when user has access to push to repository' do
before do
project.add_developer(user)
end
- it 'removes the branch' do
- expect(branch_exists?('feature')).to be true
-
- result = service.execute('feature')
-
- expect(result[:status]).to eq :success
- expect(branch_exists?('feature')).to be false
- end
+ it_behaves_like 'a deleted branch', 'feature'
end
context 'when user does not have access to push to repository' do
@@ -30,8 +34,8 @@ describe DeleteBranchService do
result = service.execute('feature')
- expect(result[:status]).to eq :error
- expect(result[:message]).to eq 'You dont have push access to repo'
+ expect(result.status).to eq :error
+ expect(result.message).to eq 'You dont have push access to repo'
expect(branch_exists?('feature')).to be true
end
end
diff --git a/spec/services/git/base_hooks_service_spec.rb b/spec/services/git/base_hooks_service_spec.rb
new file mode 100644
index 00000000000..4a2ec769116
--- /dev/null
+++ b/spec/services/git/base_hooks_service_spec.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Git::BaseHooksService do
+ include RepoHelpers
+ include GitHelpers
+
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:service) { described_class.new(project, user, oldrev: oldrev, newrev: newrev, ref: ref) }
+
+ let(:oldrev) { Gitlab::Git::BLANK_SHA }
+ let(:newrev) { "8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b" } # gitlab-test: git rev-parse refs/tags/v1.1.0
+ let(:ref) { 'refs/tags/v1.1.0' }
+
+ describe 'with remote mirrors' do
+ class TestService < described_class
+ def commits
+ []
+ end
+ end
+
+ let(:project) { create(:project, :repository, :remote_mirror) }
+
+ subject { TestService.new(project, user, oldrev: oldrev, newrev: newrev, ref: ref) }
+
+ before do
+ expect(subject).to receive(:execute_project_hooks)
+ end
+
+ context 'when remote mirror feature is enabled' do
+ it 'fails stuck remote mirrors' do
+ allow(project).to receive(:update_remote_mirrors).and_return(project.remote_mirrors)
+ expect(project).to receive(:mark_stuck_remote_mirrors_as_failed!)
+
+ subject.execute
+ end
+
+ it 'updates remote mirrors' do
+ expect(project).to receive(:update_remote_mirrors)
+
+ subject.execute
+ end
+ end
+
+ context 'when remote mirror feature is disabled' do
+ before do
+ stub_application_setting(mirror_available: false)
+ end
+
+ context 'with remote mirrors global setting overridden' do
+ before do
+ project.remote_mirror_available_overridden = true
+ end
+
+ it 'fails stuck remote mirrors' do
+ allow(project).to receive(:update_remote_mirrors).and_return(project.remote_mirrors)
+ expect(project).to receive(:mark_stuck_remote_mirrors_as_failed!)
+
+ subject.execute
+ end
+
+ it 'updates remote mirrors' do
+ expect(project).to receive(:update_remote_mirrors)
+
+ subject.execute
+ end
+ end
+
+ context 'without remote mirrors global setting overridden' do
+ before do
+ project.remote_mirror_available_overridden = false
+ end
+
+ it 'does not fails stuck remote mirrors' do
+ expect(project).not_to receive(:mark_stuck_remote_mirrors_as_failed!)
+
+ subject.execute
+ end
+
+ it 'does not updates remote mirrors' do
+ expect(project).not_to receive(:update_remote_mirrors)
+
+ subject.execute
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/git/branch_hooks_service_spec.rb b/spec/services/git/branch_hooks_service_spec.rb
index 4895e762602..b5694628269 100644
--- a/spec/services/git/branch_hooks_service_spec.rb
+++ b/spec/services/git/branch_hooks_service_spec.rb
@@ -18,6 +18,12 @@ describe Git::BranchHooksService do
described_class.new(project, user, oldrev: oldrev, newrev: newrev, ref: ref)
end
+ it 'update remote mirrors' do
+ expect(service).to receive(:update_remote_mirrors).and_call_original
+
+ service.execute
+ end
+
describe "Git Push Data" do
subject(:push_data) { service.execute }
@@ -281,8 +287,8 @@ describe Git::BranchHooksService do
context 'creating the default branch' do
let(:oldrev) { Gitlab::Git::BLANK_SHA }
- it 'does not process commit messages' do
- expect(ProcessCommitWorker).not_to receive(:perform_async)
+ it 'processes a limited number of commit messages' do
+ expect(ProcessCommitWorker).to receive(:perform_async).once
service.execute
end
diff --git a/spec/services/git/branch_push_service_spec.rb b/spec/services/git/branch_push_service_spec.rb
index ad21f710833..6e39fa6b3c0 100644
--- a/spec/services/git/branch_push_service_spec.rb
+++ b/spec/services/git/branch_push_service_spec.rb
@@ -17,72 +17,6 @@ describe Git::BranchPushService, services: true do
project.add_maintainer(user)
end
- describe 'with remote mirrors' do
- let(:project) { create(:project, :repository, :remote_mirror) }
-
- subject do
- described_class.new(project, user, oldrev: oldrev, newrev: newrev, ref: ref)
- end
-
- context 'when remote mirror feature is enabled' do
- it 'fails stuck remote mirrors' do
- allow(project).to receive(:update_remote_mirrors).and_return(project.remote_mirrors)
- expect(project).to receive(:mark_stuck_remote_mirrors_as_failed!)
-
- subject.execute
- end
-
- it 'updates remote mirrors' do
- expect(project).to receive(:update_remote_mirrors)
-
- subject.execute
- end
- end
-
- context 'when remote mirror feature is disabled' do
- before do
- stub_application_setting(mirror_available: false)
- end
-
- context 'with remote mirrors global setting overridden' do
- before do
- project.remote_mirror_available_overridden = true
- end
-
- it 'fails stuck remote mirrors' do
- allow(project).to receive(:update_remote_mirrors).and_return(project.remote_mirrors)
- expect(project).to receive(:mark_stuck_remote_mirrors_as_failed!)
-
- subject.execute
- end
-
- it 'updates remote mirrors' do
- expect(project).to receive(:update_remote_mirrors)
-
- subject.execute
- end
- end
-
- context 'without remote mirrors global setting overridden' do
- before do
- project.remote_mirror_available_overridden = false
- end
-
- it 'does not fails stuck remote mirrors' do
- expect(project).not_to receive(:mark_stuck_remote_mirrors_as_failed!)
-
- subject.execute
- end
-
- it 'does not updates remote mirrors' do
- expect(project).not_to receive(:update_remote_mirrors)
-
- subject.execute
- end
- end
- end
- end
-
describe 'Push branches' do
subject do
execute_service(project, user, oldrev, newrev, ref)
diff --git a/spec/services/git/tag_hooks_service_spec.rb b/spec/services/git/tag_hooks_service_spec.rb
index f4c02932f98..f5938a5c708 100644
--- a/spec/services/git/tag_hooks_service_spec.rb
+++ b/spec/services/git/tag_hooks_service_spec.rb
@@ -18,6 +18,12 @@ describe Git::TagHooksService, :service do
described_class.new(project, user, oldrev: oldrev, newrev: newrev, ref: ref)
end
+ it 'update remote mirrors' do
+ expect(service).to receive(:update_remote_mirrors).and_call_original
+
+ service.execute
+ end
+
describe 'System hooks' do
it 'Executes system hooks' do
push_data = service.execute
diff --git a/spec/services/issuable/clone/content_rewriter_spec.rb b/spec/services/issuable/clone/content_rewriter_spec.rb
index 4d3cb0bd254..230e1123280 100644
--- a/spec/services/issuable/clone/content_rewriter_spec.rb
+++ b/spec/services/issuable/clone/content_rewriter_spec.rb
@@ -149,5 +149,21 @@ describe Issuable::Clone::ContentRewriter do
expect(new_note.author).to eq(note.author)
end
end
+
+ context 'notes with upload' do
+ let(:uploader) { build(:file_uploader, project: project1) }
+ let(:text) { "Simple text with image: #{uploader.markdown_link} "}
+ let!(:note) { create(:note, noteable: original_issue, note: text, project: project1) }
+
+ it 'rewrites note content correctly' do
+ subject.execute
+ new_note = new_issue.notes.first
+
+ expect(note.note).to match(/Simple text with image: #{FileUploader::MARKDOWN_PATTERN}/)
+ expect(new_note.note).to match(/Simple text with image: #{FileUploader::MARKDOWN_PATTERN}/)
+ expect(note.note).not_to eq(new_note.note)
+ expect(note.note_html).not_to eq(new_note.note_html)
+ end
+ end
end
end
diff --git a/spec/services/issues/close_service_spec.rb b/spec/services/issues/close_service_spec.rb
index fce9eed8b08..6874a8a0929 100644
--- a/spec/services/issues/close_service_spec.rb
+++ b/spec/services/issues/close_service_spec.rb
@@ -3,11 +3,13 @@
require 'spec_helper'
describe Issues::CloseService do
- let(:user) { create(:user) }
- let(:user2) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:user) { create(:user, email: "user@example.com") }
+ let(:user2) { create(:user, email: "user2@example.com") }
let(:guest) { create(:user) }
- let(:issue) { create(:issue, assignees: [user2], author: create(:user)) }
- let(:project) { issue.project }
+ let(:issue) { create(:issue, title: "My issue", project: project, assignees: [user2], author: create(:user)) }
+ let(:closing_merge_request) { create(:merge_request, source_project: project) }
+ let(:closing_commit) { create(:commit, project: project) }
let!(:todo) { create(:todo, :assigned, user: user, project: project, target: issue, author: user2) }
before do
@@ -39,7 +41,7 @@ describe Issues::CloseService do
.and_return(true)
expect(service).to receive(:close_issue)
- .with(issue, commit: nil, notifications: true, system_note: true)
+ .with(issue, closed_via: nil, notifications: true, system_note: true)
service.execute(issue)
end
@@ -57,6 +59,38 @@ describe Issues::CloseService do
end
describe '#close_issue' do
+ context "closed by a merge request" do
+ before do
+ perform_enqueued_jobs do
+ described_class.new(project, user).close_issue(issue, closed_via: closing_merge_request)
+ end
+ end
+
+ it 'mentions closure via a merge request' do
+ email = ActionMailer::Base.deliveries.last
+
+ expect(email.to.first).to eq(user2.email)
+ expect(email.subject).to include(issue.title)
+ expect(email.body.parts.map(&:body)).to all(include(closing_merge_request.to_reference))
+ end
+ end
+
+ context "closed by a commit" do
+ before do
+ perform_enqueued_jobs do
+ described_class.new(project, user).close_issue(issue, closed_via: closing_commit)
+ end
+ end
+
+ it 'mentions closure via a commit' do
+ email = ActionMailer::Base.deliveries.last
+
+ expect(email.to.first).to eq(user2.email)
+ expect(email.subject).to include(issue.title)
+ expect(email.body.parts.map(&:body)).to all(include(closing_commit.id))
+ end
+ end
+
context "valid params" do
before do
perform_enqueued_jobs do
diff --git a/spec/services/lfs/file_transformer_spec.rb b/spec/services/lfs/file_transformer_spec.rb
index 2c6e86069f3..888eea6e91e 100644
--- a/spec/services/lfs/file_transformer_spec.rb
+++ b/spec/services/lfs/file_transformer_spec.rb
@@ -64,6 +64,25 @@ describe Lfs::FileTransformer do
expect(result.encoding).to eq('text')
end
+ context 'when an actual file is passed' do
+ let(:file) { Tempfile.new(file_path) }
+
+ before do
+ file.write(file_content)
+ file.rewind
+ end
+
+ after do
+ file.unlink
+ end
+
+ it "creates an LfsObject with the file's content" do
+ subject.new_file(file_path, file)
+
+ expect(LfsObject.last.file.read).to eq file_content
+ end
+ end
+
context "when doesn't use LFS" do
let(:file_path) { 'other.filetype' }
diff --git a/spec/services/members/create_service_spec.rb b/spec/services/members/create_service_spec.rb
index 2c4fb131ed9..674fe0f666e 100644
--- a/spec/services/members/create_service_spec.rb
+++ b/spec/services/members/create_service_spec.rb
@@ -44,7 +44,18 @@ describe Members::CreateService do
result = described_class.new(user, params).execute(project)
expect(result[:status]).to eq(:error)
- expect(result[:message]).to include(project_user.username)
+ expect(result[:message]).to include("#{project_user.username}: Access level is not included in the list")
expect(project.users).not_to include project_user
end
+
+ it 'does not add a member with an existing invite' do
+ invited_member = create(:project_member, :invited, project: project)
+
+ params = { user_ids: invited_member.invite_email,
+ access_level: Gitlab::Access::GUEST }
+ result = described_class.new(user, params).execute(project)
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('Invite email has already been taken')
+ end
end
diff --git a/spec/services/merge_requests/close_service_spec.rb b/spec/services/merge_requests/close_service_spec.rb
index aa7dfda4950..29b7e0f17e2 100644
--- a/spec/services/merge_requests/close_service_spec.rb
+++ b/spec/services/merge_requests/close_service_spec.rb
@@ -52,6 +52,14 @@ describe MergeRequests::CloseService do
it 'marks todos as done' do
expect(todo.reload).to be_done
end
+
+ context 'when auto merge is enabled' do
+ let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
+
+ it 'cancels the auto merge' do
+ expect(@merge_request).not_to be_auto_merge_enabled
+ end
+ end
end
it 'updates metrics' do
@@ -74,6 +82,14 @@ describe MergeRequests::CloseService do
.to change { project.open_merge_requests_count }.from(1).to(0)
end
+ it 'clean up environments for the merge request' do
+ expect_next_instance_of(Ci::StopEnvironmentsService) do |service|
+ expect(service).to receive(:execute_for_merge_request).with(merge_request)
+ end
+
+ described_class.new(project, user).execute(merge_request)
+ end
+
context 'current user is not authorized to close merge request' do
before do
perform_enqueued_jobs do
diff --git a/spec/services/merge_requests/create_pipeline_service_spec.rb b/spec/services/merge_requests/create_pipeline_service_spec.rb
new file mode 100644
index 00000000000..9479439bde8
--- /dev/null
+++ b/spec/services/merge_requests/create_pipeline_service_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe MergeRequests::CreatePipelineService do
+ set(:project) { create(:project, :repository) }
+ set(:user) { create(:user) }
+ let(:service) { described_class.new(project, user, params) }
+ let(:params) { {} }
+
+ before do
+ project.add_developer(user)
+ end
+
+ describe '#execute' do
+ subject { service.execute(merge_request) }
+
+ before do
+ stub_ci_pipeline_yaml_file(YAML.dump(config))
+ end
+
+ let(:config) do
+ { rspec: { script: 'echo', only: ['merge_requests'] } }
+ end
+
+ let(:merge_request) do
+ create(:merge_request,
+ source_branch: 'feature',
+ source_project: project,
+ target_branch: 'master',
+ target_project: project)
+ end
+
+ it 'creates a detached merge request pipeline' do
+ expect { subject }.to change { Ci::Pipeline.count }.by(1)
+
+ expect(subject).to be_persisted
+ expect(subject).to be_detached_merge_request_pipeline
+ end
+
+ context 'when service is called multiple times' do
+ it 'creates a pipeline once' do
+ expect do
+ service.execute(merge_request)
+ service.execute(merge_request)
+ end.to change { Ci::Pipeline.count }.by(1)
+ end
+
+ context 'when allow_duplicate option is true' do
+ let(:params) { { allow_duplicate: true } }
+
+ it 'creates pipelines multiple times' do
+ expect do
+ service.execute(merge_request)
+ service.execute(merge_request)
+ end.to change { Ci::Pipeline.count }.by(2)
+ end
+ end
+ end
+
+ context 'when .gitlab-ci.yml does not have only: [merge_requests] keyword' do
+ let(:config) do
+ { rspec: { script: 'echo' } }
+ end
+
+ it 'does not create a pipeline' do
+ expect { subject }.not_to change { Ci::Pipeline.count }
+ end
+ end
+ end
+end
diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb
index c795176a1e4..ed48f4b1e44 100644
--- a/spec/services/merge_requests/create_service_spec.rb
+++ b/spec/services/merge_requests/create_service_spec.rb
@@ -195,7 +195,7 @@ describe MergeRequests::CreateService do
expect(merge_request).to be_persisted
merge_request.reload
- expect(merge_request.merge_request_pipelines.count).to eq(1)
+ expect(merge_request.pipelines_for_merge_request.count).to eq(1)
expect(merge_request.actual_head_pipeline).to be_detached_merge_request_pipeline
end
@@ -247,7 +247,7 @@ describe MergeRequests::CreateService do
expect(merge_request).to be_persisted
merge_request.reload
- expect(merge_request.merge_request_pipelines.count).to eq(0)
+ expect(merge_request.pipelines_for_merge_request.count).to eq(0)
end
end
@@ -281,7 +281,7 @@ describe MergeRequests::CreateService do
expect(merge_request).to be_persisted
merge_request.reload
- expect(merge_request.merge_request_pipelines.count).to eq(0)
+ expect(merge_request.pipelines_for_merge_request.count).to eq(0)
end
end
end
diff --git a/spec/services/merge_requests/merge_to_ref_service_spec.rb b/spec/services/merge_requests/merge_to_ref_service_spec.rb
index 24d09c1fd00..0ac23050caf 100644
--- a/spec/services/merge_requests/merge_to_ref_service_spec.rb
+++ b/spec/services/merge_requests/merge_to_ref_service_spec.rb
@@ -104,7 +104,7 @@ describe MergeRequests::MergeToRefService do
it_behaves_like 'MergeService for target ref'
end
- context 'when merge commit with squash' do
+ context 'when merge commit with squash', :quarantine do
before do
merge_request.update!(squash: true, source_branch: 'master', target_branch: 'feature')
end
diff --git a/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb b/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb
deleted file mode 100644
index 96f61f3f103..00000000000
--- a/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb
+++ /dev/null
@@ -1,197 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe MergeRequests::MergeWhenPipelineSucceedsService do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
-
- let(:mr_merge_if_green_enabled) do
- create(:merge_request, merge_when_pipeline_succeeds: true, merge_user: user,
- source_branch: "master", target_branch: 'feature',
- source_project: project, target_project: project, state: "opened")
- end
-
- let(:pipeline) do
- create(:ci_pipeline_with_one_job, ref: mr_merge_if_green_enabled.source_branch,
- project: project)
- end
-
- let(:service) do
- described_class.new(project, user, commit_message: 'Awesome message')
- end
-
- describe "#execute" do
- let(:merge_request) do
- create(:merge_request, target_project: project, source_project: project,
- source_branch: "feature", target_branch: 'master')
- end
-
- context 'first time enabling' do
- before do
- allow(merge_request)
- .to receive(:head_pipeline)
- .and_return(pipeline)
-
- service.execute(merge_request)
- end
-
- it 'sets the params, merge_user, and flag' do
- expect(merge_request).to be_valid
- expect(merge_request.merge_when_pipeline_succeeds).to be_truthy
- expect(merge_request.merge_params).to eq commit_message: 'Awesome message'
- expect(merge_request.merge_user).to be user
- end
-
- it 'creates a system note' do
- note = merge_request.notes.last
- expect(note.note).to match %r{enabled an automatic merge when the pipeline for (\w+/\w+@)?\h{8}}
- end
- end
-
- context 'already approved' do
- let(:service) { described_class.new(project, user, new_key: true) }
- let(:build) { create(:ci_build, ref: mr_merge_if_green_enabled.source_branch) }
-
- before do
- allow(mr_merge_if_green_enabled).to receive(:head_pipeline)
- .and_return(pipeline)
-
- allow(mr_merge_if_green_enabled).to receive(:mergeable?)
- .and_return(true)
-
- allow(pipeline).to receive(:success?).and_return(true)
- end
-
- it 'updates the merge params' do
- expect(SystemNoteService).not_to receive(:merge_when_pipeline_succeeds)
-
- service.execute(mr_merge_if_green_enabled)
- expect(mr_merge_if_green_enabled.merge_params).to have_key(:new_key)
- end
- end
- end
-
- describe "#trigger" do
- let(:merge_request_ref) { mr_merge_if_green_enabled.source_branch }
- let(:merge_request_head) do
- project.commit(mr_merge_if_green_enabled.source_branch).id
- end
-
- context 'when triggered by pipeline with valid ref and sha' do
- let(:triggering_pipeline) do
- create(:ci_pipeline, project: project, ref: merge_request_ref,
- sha: merge_request_head, status: 'success',
- head_pipeline_of: mr_merge_if_green_enabled)
- end
-
- it "merges all merge requests with merge when the pipeline succeeds enabled" do
- expect(MergeWorker).to receive(:perform_async)
- service.trigger(triggering_pipeline)
- end
- end
-
- context 'when triggered by an old pipeline' do
- let(:old_pipeline) do
- create(:ci_pipeline, project: project, ref: merge_request_ref,
- sha: '1234abcdef', status: 'success')
- end
-
- it 'does not merge request' do
- expect(MergeWorker).not_to receive(:perform_async)
- service.trigger(old_pipeline)
- end
- end
-
- context 'when triggered by pipeline from a different branch' do
- let(:unrelated_pipeline) do
- create(:ci_pipeline, project: project, ref: 'feature',
- sha: merge_request_head, status: 'success')
- end
-
- it 'does not merge request' do
- expect(MergeWorker).not_to receive(:perform_async)
- service.trigger(unrelated_pipeline)
- end
- end
-
- context 'when pipeline is merge request pipeline' do
- let(:pipeline) do
- create(:ci_pipeline, :success,
- source: :merge_request_event,
- ref: mr_merge_if_green_enabled.merge_ref_path,
- merge_request: mr_merge_if_green_enabled,
- merge_requests_as_head_pipeline: [mr_merge_if_green_enabled])
- end
-
- it 'merges the associated merge request' do
- expect(MergeWorker).to receive(:perform_async)
- service.trigger(pipeline)
- end
- end
- end
-
- describe "#cancel" do
- before do
- service.cancel(mr_merge_if_green_enabled)
- end
-
- it "resets all the pipeline succeeds params" do
- expect(mr_merge_if_green_enabled.merge_when_pipeline_succeeds).to be_falsey
- expect(mr_merge_if_green_enabled.merge_params).to eq({})
- expect(mr_merge_if_green_enabled.merge_user).to be nil
- end
-
- it 'Posts a system note' do
- note = mr_merge_if_green_enabled.notes.last
- expect(note.note).to include 'canceled the automatic merge'
- end
- end
-
- describe 'pipeline integration' do
- context 'when there are multiple stages in the pipeline' do
- let(:ref) { mr_merge_if_green_enabled.source_branch }
- let(:sha) { project.commit(ref).id }
-
- let(:pipeline) do
- create(:ci_empty_pipeline, ref: ref, sha: sha, project: project)
- end
-
- let!(:build) do
- create(:ci_build, :created, pipeline: pipeline, ref: ref,
- name: 'build', stage: 'build')
- end
-
- let!(:test) do
- create(:ci_build, :created, pipeline: pipeline, ref: ref,
- name: 'test', stage: 'test')
- end
-
- before do
- # This behavior of MergeRequest: we instantiate a new object
- #
- allow_any_instance_of(MergeRequest)
- .to receive(:head_pipeline)
- .and_wrap_original do
- Ci::Pipeline.find(pipeline.id)
- end
- end
-
- it "doesn't merge if any of stages failed" do
- expect(MergeWorker).not_to receive(:perform_async)
-
- build.success
- test.reload
- test.drop
- end
-
- it 'merges when all stages succeeded' do
- expect(MergeWorker).to receive(:perform_async)
-
- build.success
- test.reload
- test.success
- end
- end
- end
-end
diff --git a/spec/services/merge_requests/post_merge_service_spec.rb b/spec/services/merge_requests/post_merge_service_spec.rb
index 7b87913ab8b..ffc86f68469 100644
--- a/spec/services/merge_requests/post_merge_service_spec.rb
+++ b/spec/services/merge_requests/post_merge_service_spec.rb
@@ -62,5 +62,13 @@ describe MergeRequests::PostMergeService do
expect(merge_request.reload).to be_merged
end
+
+ it 'clean up environments for the merge request' do
+ expect_next_instance_of(Ci::StopEnvironmentsService) do |service|
+ expect(service).to receive(:execute_for_merge_request).with(merge_request)
+ end
+
+ described_class.new(project, user).execute(merge_request)
+ end
end
end
diff --git a/spec/services/merge_requests/push_options_handler_service_spec.rb b/spec/services/merge_requests/push_options_handler_service_spec.rb
index f7a39bb42d5..54b9c6dae38 100644
--- a/spec/services/merge_requests/push_options_handler_service_spec.rb
+++ b/spec/services/merge_requests/push_options_handler_service_spec.rb
@@ -76,10 +76,11 @@ describe MergeRequests::PushOptionsHandlerService do
shared_examples_for 'a service that can set the merge request to merge when pipeline succeeds' do
subject(:last_mr) { MergeRequest.last }
- it 'sets merge_when_pipeline_succeeds' do
+ it 'sets auto_merge_enabled' do
service.execute
- expect(last_mr.merge_when_pipeline_succeeds).to eq(true)
+ expect(last_mr.auto_merge_enabled).to eq(true)
+ expect(last_mr.auto_merge_strategy).to eq(AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
end
it 'sets merge_user to the user' do
diff --git a/spec/services/merge_requests/rebase_service_spec.rb b/spec/services/merge_requests/rebase_service_spec.rb
index 0d9523a4c2c..7e2f03d1097 100644
--- a/spec/services/merge_requests/rebase_service_spec.rb
+++ b/spec/services/merge_requests/rebase_service_spec.rb
@@ -38,6 +38,32 @@ describe MergeRequests::RebaseService do
end
end
+ shared_examples 'sequence of failure and success' do
+ it 'properly clears the error message' do
+ allow(repository).to receive(:gitaly_operation_client).and_raise('Something went wrong')
+
+ service.execute(merge_request)
+
+ expect(merge_request.reload.merge_error).to eq described_class::REBASE_ERROR
+
+ allow(repository).to receive(:gitaly_operation_client).and_call_original
+
+ service.execute(merge_request)
+
+ expect(merge_request.reload.merge_error).to eq nil
+ end
+ end
+
+ it_behaves_like 'sequence of failure and success'
+
+ context 'with deprecated step rebase feature' do
+ before do
+ stub_feature_flags(two_step_rebase: false)
+ end
+
+ it_behaves_like 'sequence of failure and success'
+ end
+
context 'when unexpected error occurs' do
before do
allow(repository).to receive(:gitaly_operation_client).and_raise('Something went wrong')
@@ -73,7 +99,7 @@ describe MergeRequests::RebaseService do
end
context 'valid params' do
- describe 'successful rebase' do
+ shared_examples_for 'a service that can execute a successful rebase' do
before do
service.execute(merge_request)
end
@@ -99,6 +125,22 @@ describe MergeRequests::RebaseService do
end
end
+ context 'when the two_step_rebase feature is enabled' do
+ before do
+ stub_feature_flags(two_step_rebase: true)
+ end
+
+ it_behaves_like 'a service that can execute a successful rebase'
+ end
+
+ context 'when the two_step_rebase feature is disabled' do
+ before do
+ stub_feature_flags(two_step_rebase: false)
+ end
+
+ it_behaves_like 'a service that can execute a successful rebase'
+ end
+
context 'fork' do
describe 'successful fork rebase' do
let(:forked_project) do
diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb
index d20b2d81763..6ba67c7165c 100644
--- a/spec/services/merge_requests/refresh_service_spec.rb
+++ b/spec/services/merge_requests/refresh_service_spec.rb
@@ -23,7 +23,8 @@ describe MergeRequests::RefreshService do
source_branch: 'master',
target_branch: 'feature',
target_project: @project,
- merge_when_pipeline_succeeds: true,
+ auto_merge_enabled: true,
+ auto_merge_strategy: AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS,
merge_user: @user)
@another_merge_request = create(:merge_request,
@@ -31,7 +32,8 @@ describe MergeRequests::RefreshService do
source_branch: 'master',
target_branch: 'test',
target_project: @project,
- merge_when_pipeline_succeeds: true,
+ auto_merge_enabled: true,
+ auto_merge_strategy: AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS,
merge_user: @user)
@fork_merge_request = create(:merge_request,
@@ -83,7 +85,7 @@ describe MergeRequests::RefreshService do
expect(@merge_request.notes).not_to be_empty
expect(@merge_request).to be_open
- expect(@merge_request.merge_when_pipeline_succeeds).to be_falsey
+ expect(@merge_request.auto_merge_enabled).to be_falsey
expect(@merge_request.diff_head_sha).to eq(@newrev)
expect(@fork_merge_request).to be_open
expect(@fork_merge_request.notes).to be_empty
@@ -166,8 +168,8 @@ describe MergeRequests::RefreshService do
it 'create detached merge request pipeline with commits' do
expect { subject }
- .to change { @merge_request.merge_request_pipelines.count }.by(1)
- .and change { @another_merge_request.merge_request_pipelines.count }.by(0)
+ .to change { @merge_request.pipelines_for_merge_request.count }.by(1)
+ .and change { @another_merge_request.pipelines_for_merge_request.count }.by(0)
expect(@merge_request.has_commits?).to be_truthy
expect(@another_merge_request.has_commits?).to be_falsy
@@ -175,13 +177,13 @@ describe MergeRequests::RefreshService do
it 'does not create detached merge request pipeline for forked project' do
expect { subject }
- .not_to change { @fork_merge_request.merge_request_pipelines.count }
+ .not_to change { @fork_merge_request.pipelines_for_merge_request.count }
end
it 'create detached merge request pipeline for non-fork merge request' do
subject
- expect(@merge_request.merge_request_pipelines.first)
+ expect(@merge_request.pipelines_for_merge_request.first)
.to be_detached_merge_request_pipeline
end
@@ -190,7 +192,7 @@ describe MergeRequests::RefreshService do
it 'does not create detached merge request pipeline' do
expect { subject }
- .not_to change { @merge_request.merge_request_pipelines.count }
+ .not_to change { @merge_request.pipelines_for_merge_request.count }
end
end
@@ -199,9 +201,9 @@ describe MergeRequests::RefreshService do
it 'creates legacy detached merge request pipeline for fork merge request' do
expect { subject }
- .to change { @fork_merge_request.merge_request_pipelines.count }.by(1)
+ .to change { @fork_merge_request.pipelines_for_merge_request.count }.by(1)
- expect(@fork_merge_request.merge_request_pipelines.first)
+ expect(@fork_merge_request.pipelines_for_merge_request.first)
.to be_legacy_detached_merge_request_pipeline
end
end
@@ -214,7 +216,7 @@ describe MergeRequests::RefreshService do
it 'create legacy detached merge request pipeline for non-fork merge request' do
subject
- expect(@merge_request.merge_request_pipelines.first)
+ expect(@merge_request.pipelines_for_merge_request.first)
.to be_legacy_detached_merge_request_pipeline
end
end
@@ -245,11 +247,11 @@ describe MergeRequests::RefreshService do
it 'does not re-create a duplicate detached merge request pipeline' do
expect do
service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/master')
- end.to change { @merge_request.merge_request_pipelines.count }.by(1)
+ end.to change { @merge_request.pipelines_for_merge_request.count }.by(1)
expect do
service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/master')
- end.not_to change { @merge_request.merge_request_pipelines.count }
+ end.not_to change { @merge_request.pipelines_for_merge_request.count }
end
end
end
@@ -266,7 +268,7 @@ describe MergeRequests::RefreshService do
it 'does not create a detached merge request pipeline' do
expect { subject }
- .not_to change { @merge_request.merge_request_pipelines.count }
+ .not_to change { @merge_request.pipelines_for_merge_request.count }
end
end
end
@@ -292,7 +294,7 @@ describe MergeRequests::RefreshService do
expect(@merge_request.notes).not_to be_empty
expect(@merge_request).to be_open
- expect(@merge_request.merge_when_pipeline_succeeds).to be_falsey
+ expect(@merge_request.auto_merge_enabled).to be_falsey
expect(@merge_request.diff_head_sha).to eq(@newrev)
expect(@fork_merge_request).to be_open
expect(@fork_merge_request.notes).to be_empty
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index ba4c9ce60f3..f566d235787 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -217,8 +217,9 @@ describe MergeRequests::UpdateService, :mailer do
head_pipeline_of: merge_request
)
- expect(MergeRequests::MergeWhenPipelineSucceedsService).to receive(:new).with(project, user)
+ expect(AutoMerge::MergeWhenPipelineSucceedsService).to receive(:new).with(project, user, {})
.and_return(service_mock)
+ allow(service_mock).to receive(:available_for?) { true }
expect(service_mock).to receive(:execute).with(merge_request)
end
@@ -405,6 +406,18 @@ describe MergeRequests::UpdateService, :mailer do
expect(pending_todo.reload).to be_done
end
end
+
+ context 'when auto merge is enabled and target branch changed' do
+ before do
+ AutoMergeService.new(project, user).execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
+
+ update_merge_request({ target_branch: 'target' })
+ end
+
+ it 'marks pending todos as done' do
+ expect(pending_todo.reload).to be_done
+ end
+ end
end
context 'when the merge request is relabeled' do
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 8e34406133a..4b40c86574f 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -643,6 +643,64 @@ describe NotificationService, :mailer do
end
end
+ describe 'Participating project notification settings have priority over group and global settings if available' do
+ let!(:group) { create(:group) }
+ let!(:maintainer) { group.add_owner(create(:user, username: 'maintainer')).user }
+ let!(:user1) { group.add_developer(create(:user, username: 'user_with_project_and_custom_setting')).user }
+
+ let(:project) { create(:project, :public, namespace: group) }
+ let(:issue) { create :issue, project: project, assignees: [assignee], description: '' }
+
+ before do
+ reset_delivered_emails!
+
+ create_notification_setting(user1, project, :participating)
+ end
+
+ context 'custom on group' do
+ [nil, true].each do |new_issue_value|
+ value_caption = new_issue_value || 'nil'
+ it "does not send an email to user1 when a new issue is created and new_issue is set to #{value_caption}" do
+ update_custom_notification(:new_issue, user1, resource: group, value: new_issue_value)
+
+ notification.new_issue(issue, maintainer)
+ should_not_email(user1)
+ end
+ end
+ end
+
+ context 'watch on group' do
+ it 'does not send an email' do
+ user1.notification_settings_for(group).update!(level: :watch)
+
+ notification.new_issue(issue, maintainer)
+ should_not_email(user1)
+ end
+ end
+
+ context 'custom on global, global on group' do
+ it 'does not send an email' do
+ user1.notification_settings_for(nil).update!(level: :custom)
+
+ user1.notification_settings_for(group).update!(level: :global)
+
+ notification.new_issue(issue, maintainer)
+ should_not_email(user1)
+ end
+ end
+
+ context 'watch on global, global on group' do
+ it 'does not send an email' do
+ user1.notification_settings_for(nil).update!(level: :watch)
+
+ user1.notification_settings_for(group).update!(level: :global)
+
+ notification.new_issue(issue, maintainer)
+ should_not_email(user1)
+ end
+ end
+ end
+
describe 'Issues' do
let(:group) { create(:group) }
let(:project) { create(:project, :public, namespace: group) }
@@ -660,7 +718,7 @@ describe NotificationService, :mailer do
end
describe '#new_issue' do
- it do
+ it 'notifies the expected users' do
notification.new_issue(issue, @u_disabled)
should_email(assignee)
@@ -1639,7 +1697,7 @@ describe NotificationService, :mailer do
end
describe '#project_was_moved' do
- it do
+ it 'notifies the expected users' do
notification.project_was_moved(project, "gitlab/gitlab")
should_email(@u_watcher)
diff --git a/spec/services/pages_domains/create_acme_order_service_spec.rb b/spec/services/pages_domains/create_acme_order_service_spec.rb
new file mode 100644
index 00000000000..d59aa9b979e
--- /dev/null
+++ b/spec/services/pages_domains/create_acme_order_service_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe PagesDomains::CreateAcmeOrderService do
+ include LetsEncryptHelpers
+
+ let(:pages_domain) { create(:pages_domain) }
+
+ let(:challenge) { ::Gitlab::LetsEncrypt::Challenge.new(acme_challenge_double) }
+
+ let(:order_double) do
+ Gitlab::LetsEncrypt::Order.new(acme_order_double).tap do |order|
+ allow(order).to receive(:new_challenge).and_return(challenge)
+ end
+ end
+
+ let(:lets_encrypt_client) do
+ instance_double('Gitlab::LetsEncrypt::Client').tap do |client|
+ allow(client).to receive(:new_order).with(pages_domain.domain)
+ .and_return(order_double)
+ end
+ end
+
+ let(:service) { described_class.new(pages_domain) }
+
+ before do
+ allow(::Gitlab::LetsEncrypt::Client).to receive(:new).and_return(lets_encrypt_client)
+ end
+
+ it 'saves order to database before requesting validation' do
+ allow(pages_domain.acme_orders).to receive(:create!).and_call_original
+ allow(challenge).to receive(:request_validation).and_call_original
+
+ service.execute
+
+ expect(pages_domain.acme_orders).to have_received(:create!).ordered
+ expect(challenge).to have_received(:request_validation).ordered
+ end
+
+ it 'generates and saves private key' do
+ service.execute
+
+ saved_order = PagesDomainAcmeOrder.last
+ expect { OpenSSL::PKey::RSA.new(saved_order.private_key) }.not_to raise_error
+ end
+
+ it 'properly saves order attributes' do
+ service.execute
+
+ saved_order = PagesDomainAcmeOrder.last
+ expect(saved_order.url).to eq(order_double.url)
+ expect(saved_order.expires_at).to be_like_time(order_double.expires)
+ end
+
+ it 'properly saves challenge attributes' do
+ service.execute
+
+ saved_order = PagesDomainAcmeOrder.last
+ expect(saved_order.challenge_token).to eq(challenge.token)
+ expect(saved_order.challenge_file_content).to eq(challenge.file_content)
+ end
+end
diff --git a/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb b/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb
new file mode 100644
index 00000000000..6d7be27939c
--- /dev/null
+++ b/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb
@@ -0,0 +1,146 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe PagesDomains::ObtainLetsEncryptCertificateService do
+ include LetsEncryptHelpers
+
+ let(:pages_domain) { create(:pages_domain, :without_certificate, :without_key) }
+ let(:service) { described_class.new(pages_domain) }
+
+ before do
+ stub_lets_encrypt_settings
+ end
+
+ def expect_to_create_acme_challenge
+ expect(::PagesDomains::CreateAcmeOrderService).to receive(:new).with(pages_domain)
+ .and_wrap_original do |m, *args|
+ create_service = m.call(*args)
+
+ expect(create_service).to receive(:execute)
+
+ create_service
+ end
+ end
+
+ def stub_lets_encrypt_order(url, status)
+ order = ::Gitlab::LetsEncrypt::Order.new(acme_order_double(status: status))
+
+ allow_any_instance_of(::Gitlab::LetsEncrypt::Client).to(
+ receive(:load_order).with(url).and_return(order)
+ )
+
+ order
+ end
+
+ context 'when there is no acme order' do
+ it 'creates acme order' do
+ expect_to_create_acme_challenge
+
+ service.execute
+ end
+ end
+
+ context 'when there is expired acme order' do
+ let!(:existing_order) do
+ create(:pages_domain_acme_order, :expired, pages_domain: pages_domain)
+ end
+
+ it 'removes acme order and creates new one' do
+ expect_to_create_acme_challenge
+
+ service.execute
+
+ expect(PagesDomainAcmeOrder.find_by_id(existing_order.id)).to be_nil
+ end
+ end
+
+ %w(pending processing).each do |status|
+ context "there is an order in '#{status}' status" do
+ let(:existing_order) do
+ create(:pages_domain_acme_order, pages_domain: pages_domain)
+ end
+
+ before do
+ stub_lets_encrypt_order(existing_order.url, status)
+ end
+
+ it 'does not raise errors' do
+ expect do
+ service.execute
+ end.not_to raise_error
+ end
+ end
+ end
+
+ context 'when order is ready' do
+ let(:existing_order) do
+ create(:pages_domain_acme_order, pages_domain: pages_domain)
+ end
+
+ let!(:api_order) do
+ stub_lets_encrypt_order(existing_order.url, 'ready')
+ end
+
+ it 'request certificate' do
+ expect(api_order).to receive(:request_certificate).and_call_original
+
+ service.execute
+ end
+ end
+
+ context 'when order is valid' do
+ let(:existing_order) do
+ create(:pages_domain_acme_order, pages_domain: pages_domain)
+ end
+
+ let!(:api_order) do
+ stub_lets_encrypt_order(existing_order.url, 'valid')
+ end
+
+ let(:certificate) do
+ key = OpenSSL::PKey.read(existing_order.private_key)
+
+ subject = "/C=BE/O=Test/OU=Test/CN=#{pages_domain.domain}"
+
+ cert = OpenSSL::X509::Certificate.new
+ cert.subject = cert.issuer = OpenSSL::X509::Name.parse(subject)
+ cert.not_before = Time.now
+ cert.not_after = 1.year.from_now
+ cert.public_key = key.public_key
+ cert.serial = 0x0
+ cert.version = 2
+
+ ef = OpenSSL::X509::ExtensionFactory.new
+ ef.subject_certificate = cert
+ ef.issuer_certificate = cert
+ cert.extensions = [
+ ef.create_extension("basicConstraints", "CA:TRUE", true),
+ ef.create_extension("subjectKeyIdentifier", "hash")
+ ]
+ cert.add_extension ef.create_extension("authorityKeyIdentifier",
+ "keyid:always,issuer:always")
+
+ cert.sign key, OpenSSL::Digest::SHA1.new
+
+ cert.to_pem
+ end
+
+ before do
+ expect(api_order).to receive(:certificate) { certificate }
+ end
+
+ it 'saves private_key and certificate for domain' do
+ service.execute
+
+ expect(pages_domain.key).to be_present
+ expect(pages_domain.certificate).to eq(certificate)
+ end
+
+ it 'removes order from database' do
+ service.execute
+
+ expect(PagesDomainAcmeOrder.find_by_id(existing_order.id)).to be_nil
+ end
+ end
+end
diff --git a/spec/services/preview_markdown_service_spec.rb b/spec/services/preview_markdown_service_spec.rb
index f7261cd7125..d25e9958831 100644
--- a/spec/services/preview_markdown_service_spec.rb
+++ b/spec/services/preview_markdown_service_spec.rb
@@ -56,7 +56,9 @@ describe PreviewMarkdownService do
expect(Gitlab::Diff::SuggestionsParser)
.to receive(:parse)
- .with(text, position: position, project: merge_request.project)
+ .with(text, position: position,
+ project: merge_request.project,
+ supports_suggestion: true)
.and_call_original
result = service.execute
diff --git a/spec/services/projects/after_import_service_spec.rb b/spec/services/projects/after_import_service_spec.rb
index 95c11f71c5e..51d3fd18881 100644
--- a/spec/services/projects/after_import_service_spec.rb
+++ b/spec/services/projects/after_import_service_spec.rb
@@ -15,7 +15,7 @@ describe Projects::AfterImportService do
describe '#execute' do
before do
allow(Projects::HousekeepingService)
- .to receive(:new).with(project, :gc).and_return(housekeeping_service)
+ .to receive(:new).with(project).and_return(housekeeping_service)
allow(housekeeping_service)
.to receive(:execute).and_yield
diff --git a/spec/services/projects/cleanup_service_spec.rb b/spec/services/projects/cleanup_service_spec.rb
index 29eabc86327..5c246854eb7 100644
--- a/spec/services/projects/cleanup_service_spec.rb
+++ b/spec/services/projects/cleanup_service_spec.rb
@@ -6,13 +6,13 @@ describe Projects::CleanupService do
let(:project) { create(:project, :repository, bfg_object_map: fixture_file_upload('spec/fixtures/bfg_object_map.txt')) }
let(:object_map) { project.bfg_object_map }
+ let(:cleaner) { service.__send__(:repository_cleaner) }
+
subject(:service) { described_class.new(project) }
describe '#execute' do
- it 'runs the apply_bfg_object_map gitaly RPC' do
- expect_next_instance_of(Gitlab::Git::RepositoryCleaner) do |cleaner|
- expect(cleaner).to receive(:apply_bfg_object_map).with(kind_of(IO))
- end
+ it 'runs the apply_bfg_object_map_stream gitaly RPC' do
+ expect(cleaner).to receive(:apply_bfg_object_map_stream).with(kind_of(IO))
service.execute
end
@@ -37,10 +37,91 @@ describe Projects::CleanupService do
expect(object_map.exists?).to be_falsy
end
+ context 'with a tainted merge request diff' do
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+ let(:diff) { merge_request.merge_request_diff }
+ let(:entry) { build_entry(diff.commits.first.id) }
+
+ before do
+ allow(cleaner)
+ .to receive(:apply_bfg_object_map_stream)
+ .and_yield(Gitaly::ApplyBfgObjectMapStreamResponse.new(entries: [entry]))
+ end
+
+ it 'removes the tainted commit from the database' do
+ service.execute
+
+ expect(MergeRequestDiff.exists?(diff.id)).to be_falsy
+ end
+
+ it 'ignores non-commit responses from Gitaly' do
+ entry.type = :UNKNOWN
+
+ service.execute
+
+ expect(MergeRequestDiff.exists?(diff.id)).to be_truthy
+ end
+ end
+
+ context 'with a tainted diff note' do
+ let(:diff_note) { create(:diff_note_on_commit, project: project) }
+ let(:note_diff_file) { diff_note.note_diff_file }
+ let(:entry) { build_entry(diff_note.commit_id) }
+
+ let(:highlight_cache) { Gitlab::DiscussionsDiff::HighlightCache }
+ let(:cache_id) { note_diff_file.id }
+
+ before do
+ allow(cleaner)
+ .to receive(:apply_bfg_object_map_stream)
+ .and_yield(Gitaly::ApplyBfgObjectMapStreamResponse.new(entries: [entry]))
+ end
+
+ it 'removes the tainted commit from the database' do
+ service.execute
+
+ expect(NoteDiffFile.exists?(note_diff_file.id)).to be_falsy
+ end
+
+ it 'removes the highlight cache from redis' do
+ write_cache(highlight_cache, cache_id, [{}])
+
+ expect(read_cache(highlight_cache, cache_id)).not_to be_nil
+
+ service.execute
+
+ expect(read_cache(highlight_cache, cache_id)).to be_nil
+ end
+
+ it 'ignores non-commit responses from Gitaly' do
+ entry.type = :UNKNOWN
+
+ service.execute
+
+ expect(NoteDiffFile.exists?(note_diff_file.id)).to be_truthy
+ end
+ end
+
it 'raises an error if no object map can be found' do
object_map.remove!
expect { service.execute }.to raise_error(described_class::NoUploadError)
end
end
+
+ def build_entry(old_oid)
+ Gitaly::ApplyBfgObjectMapStreamResponse::Entry.new(
+ type: :COMMIT,
+ old_oid: old_oid,
+ new_oid: Gitlab::Git::BLANK_SHA
+ )
+ end
+
+ def read_cache(cache, key)
+ cache.read_multiple([key]).first
+ end
+
+ def write_cache(cache, key, value)
+ cache.write_multiple(key => value)
+ end
end
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index bd7a0c68766..f54f9200661 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -268,33 +268,6 @@ describe Projects::CreateService, '#execute' do
end
end
- context 'when group has kubernetes cluster' do
- let(:group_cluster) { create(:cluster, :group, :provided_by_gcp) }
- let(:group) { group_cluster.group }
-
- let(:token) { 'aaaa' }
- let(:service_account_creator) { double(Clusters::Gcp::Kubernetes::CreateOrUpdateServiceAccountService, execute: true) }
- let(:secrets_fetcher) { double(Clusters::Gcp::Kubernetes::FetchKubernetesTokenService, execute: token) }
-
- before do
- group.add_owner(user)
-
- stub_feature_flags(ci_preparing_state: false)
- expect(Clusters::Gcp::Kubernetes::CreateOrUpdateServiceAccountService).to receive(:namespace_creator).and_return(service_account_creator)
- expect(Clusters::Gcp::Kubernetes::FetchKubernetesTokenService).to receive(:new).and_return(secrets_fetcher)
- end
-
- it 'creates kubernetes namespace for the project' do
- project = create_project(user, opts.merge!(namespace_id: group.id))
-
- expect(project).to be_valid
-
- kubernetes_namespace = group_cluster.kubernetes_namespaces.first
- expect(kubernetes_namespace).to be_present
- expect(kubernetes_namespace.project).to eq(project)
- end
- end
-
context 'when there is an active service template' do
before do
create(:service, project: nil, template: true, active: true)
diff --git a/spec/services/projects/detect_repository_languages_service_spec.rb b/spec/services/projects/detect_repository_languages_service_spec.rb
index e3e561c971c..df5eed18ac0 100644
--- a/spec/services/projects/detect_repository_languages_service_spec.rb
+++ b/spec/services/projects/detect_repository_languages_service_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
describe Projects::DetectRepositoryLanguagesService, :clean_gitlab_redis_shared_state do
set(:project) { create(:project, :repository) }
- subject { described_class.new(project, project.owner) }
+ subject { described_class.new(project) }
describe '#execute' do
context 'without previous detection' do
diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb
index ec3f1782e8f..6afc91d5e95 100644
--- a/spec/services/projects/fork_service_spec.rb
+++ b/spec/services/projects/fork_service_spec.rb
@@ -145,6 +145,30 @@ describe Projects::ForkService do
end
end
+ context "CI/CD settings" do
+ let(:to_project) { fork_project(@from_project, @to_user) }
+
+ context "when origin has git depth specified" do
+ before do
+ @from_project.update(ci_default_git_depth: 42)
+ end
+
+ it "inherits default_git_depth from the origin project" do
+ expect(to_project.ci_default_git_depth).to eq(42)
+ end
+ end
+
+ context "when origin does not define git depth" do
+ before do
+ @from_project.update!(ci_default_git_depth: nil)
+ end
+
+ it "the fork has git depth set to 0" do
+ expect(to_project.ci_default_git_depth).to eq(0)
+ end
+ end
+ end
+
context "when project has restricted visibility level" do
context "and only one visibility level is restricted" do
before do
diff --git a/spec/services/projects/git_deduplication_service_spec.rb b/spec/services/projects/git_deduplication_service_spec.rb
new file mode 100644
index 00000000000..3acbc46b473
--- /dev/null
+++ b/spec/services/projects/git_deduplication_service_spec.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Projects::GitDeduplicationService do
+ include ExclusiveLeaseHelpers
+
+ let(:pool) { create(:pool_repository, :ready) }
+ let(:project) { create(:project, :repository) }
+ let(:lease_key) { "git_deduplication:#{project.id}" }
+ let(:lease_timeout) { Projects::GitDeduplicationService::LEASE_TIMEOUT }
+
+ subject(:service) { described_class.new(project) }
+
+ describe '#execute' do
+ context 'when there is not already a lease' do
+ context 'when the project does not have a pool repository' do
+ it 'calls disconnect_git_alternates' do
+ stub_exclusive_lease(lease_key, timeout: lease_timeout)
+
+ expect(project.repository).to receive(:disconnect_alternates)
+
+ service.execute
+ end
+ end
+
+ context 'when the project has a pool repository' do
+ let(:project) { create(:project, :repository, pool_repository: pool) }
+
+ context 'when the project is a source project' do
+ let(:lease_key) { "git_deduplication:#{pool.source_project.id}" }
+
+ subject(:service) { described_class.new(pool.source_project) }
+
+ it 'calls fetch' do
+ stub_exclusive_lease(lease_key, timeout: lease_timeout)
+ allow(pool.source_project).to receive(:git_objects_poolable?).and_return(true)
+
+ expect(pool.object_pool).to receive(:fetch)
+
+ service.execute
+ end
+
+ it 'does not call fetch if git objects are not poolable' do
+ stub_exclusive_lease(lease_key, timeout: lease_timeout)
+ allow(pool.source_project).to receive(:git_objects_poolable?).and_return(false)
+
+ expect(pool.object_pool).not_to receive(:fetch)
+
+ service.execute
+ end
+
+ it 'does not call fetch if pool and project are not on the same storage' do
+ stub_exclusive_lease(lease_key, timeout: lease_timeout)
+ allow(pool.source_project.repository).to receive(:storage).and_return('special_storage_001')
+
+ expect(pool.object_pool).not_to receive(:fetch)
+
+ service.execute
+ end
+ end
+
+ it 'links the repository to the object pool' do
+ expect(project).to receive(:link_pool_repository)
+
+ service.execute
+ end
+
+ it 'does not link the repository to the object pool if they are not on the same storage' do
+ allow(project.repository).to receive(:storage).and_return('special_storage_001')
+ expect(project).not_to receive(:link_pool_repository)
+
+ service.execute
+ end
+ end
+
+ context 'when a lease is already out' do
+ before do
+ stub_exclusive_lease_taken(lease_key, timeout: lease_timeout)
+ end
+
+ it 'fails when a lease is already out' do
+ expect(service).to receive(:log_error).with('Cannot obtain an exclusive lease. There must be another instance already in execution.')
+
+ service.execute
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/projects/housekeeping_service_spec.rb b/spec/services/projects/housekeeping_service_spec.rb
index 368cf123c3e..f651db70cbd 100644
--- a/spec/services/projects/housekeeping_service_spec.rb
+++ b/spec/services/projects/housekeeping_service_spec.rb
@@ -81,6 +81,9 @@ describe Projects::HousekeepingService do
# At push 10, 20, ... (except those above)
expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id, :incremental_repack, :the_lease_key, :the_uuid)
.exactly(16).times
+ # At push 6, 12, 18, ... (except those above)
+ expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id, :pack_refs, :the_lease_key, :the_uuid)
+ .exactly(27).times
201.times do
subject.increment!
diff --git a/spec/services/projects/import_service_spec.rb b/spec/services/projects/import_service_spec.rb
index 7f233a52f50..d9f9ede8ecd 100644
--- a/spec/services/projects/import_service_spec.rb
+++ b/spec/services/projects/import_service_spec.rb
@@ -5,15 +5,11 @@ require 'spec_helper'
describe Projects::ImportService do
let!(:project) { create(:project) }
let(:user) { project.creator }
- let(:import_url) { 'http://www.gitlab.com/demo/repo.git' }
- let(:oid_download_links) { { 'oid1' => "#{import_url}/gitlab-lfs/objects/oid1", 'oid2' => "#{import_url}/gitlab-lfs/objects/oid2" } }
subject { described_class.new(project, user) }
before do
allow(project).to receive(:lfs_enabled?).and_return(true)
- allow_any_instance_of(Projects::LfsPointers::LfsDownloadService).to receive(:execute)
- allow_any_instance_of(Projects::LfsPointers::LfsImportService).to receive(:execute).and_return(oid_download_links)
end
describe '#async?' do
@@ -77,7 +73,6 @@ describe Projects::ImportService do
context 'when repository creation succeeds' do
it 'does not download lfs files' do
expect_any_instance_of(Projects::LfsPointers::LfsImportService).not_to receive(:execute)
- expect_any_instance_of(Projects::LfsPointers::LfsDownloadService).not_to receive(:execute)
subject.execute
end
@@ -114,7 +109,6 @@ describe Projects::ImportService do
context 'when repository import scheduled' do
it 'does not download lfs objects' do
expect_any_instance_of(Projects::LfsPointers::LfsImportService).not_to receive(:execute)
- expect_any_instance_of(Projects::LfsPointers::LfsDownloadService).not_to receive(:execute)
subject.execute
end
@@ -130,7 +124,7 @@ describe Projects::ImportService do
it 'succeeds if repository import is successful' do
expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).and_return(true)
expect_any_instance_of(Gitlab::BitbucketImport::Importer).to receive(:execute).and_return(true)
- expect_any_instance_of(Projects::LfsPointers::LfsImportService).to receive(:execute).and_return({})
+ expect_any_instance_of(Projects::LfsPointers::LfsImportService).to receive(:execute).and_return(status: :success)
result = subject.execute
@@ -146,6 +140,19 @@ describe Projects::ImportService do
expect(result[:message]).to eq "Error importing repository #{project.safe_import_url} into #{project.full_path} - Failed to import the repository [FILTERED]"
end
+ context 'when lfs import fails' do
+ it 'logs the error' do
+ error_message = 'error message'
+
+ expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).and_return(true)
+ expect_any_instance_of(Gitlab::BitbucketImport::Importer).to receive(:execute).and_return(true)
+ expect_any_instance_of(Projects::LfsPointers::LfsImportService).to receive(:execute).and_return(status: :error, message: error_message)
+ expect(Gitlab::AppLogger).to receive(:error).with("The Lfs import process failed. #{error_message}")
+
+ subject.execute
+ end
+ end
+
context 'when repository import scheduled' do
before do
allow_any_instance_of(Gitlab::Shell).to receive(:import_repository).and_return(true)
@@ -155,10 +162,7 @@ describe Projects::ImportService do
it 'downloads lfs objects if lfs_enabled is enabled for project' do
allow(project).to receive(:lfs_enabled?).and_return(true)
- service = double
- expect_any_instance_of(Projects::LfsPointers::LfsImportService).to receive(:execute).and_return(oid_download_links)
- expect(Projects::LfsPointers::LfsDownloadService).to receive(:new).and_return(service).twice
- expect(service).to receive(:execute).twice
+ expect_any_instance_of(Projects::LfsPointers::LfsImportService).to receive(:execute)
subject.execute
end
@@ -166,7 +170,6 @@ describe Projects::ImportService do
it 'does not download lfs objects if lfs_enabled is not enabled for project' do
allow(project).to receive(:lfs_enabled?).and_return(false)
expect_any_instance_of(Projects::LfsPointers::LfsImportService).not_to receive(:execute)
- expect_any_instance_of(Projects::LfsPointers::LfsDownloadService).not_to receive(:execute)
subject.execute
end
@@ -208,7 +211,6 @@ describe Projects::ImportService do
allow(Gitlab::GithubImport::ParallelImporter).to receive(:imports_repository?).and_return(true)
expect_any_instance_of(Projects::LfsPointers::LfsImportService).not_to receive(:execute)
- expect_any_instance_of(Projects::LfsPointers::LfsDownloadService).not_to receive(:execute)
subject.execute
end
@@ -216,13 +218,22 @@ describe Projects::ImportService do
it 'does not have a custom repository importer downloads lfs objects' do
allow(Gitlab::GithubImport::ParallelImporter).to receive(:imports_repository?).and_return(false)
- service = double
- expect_any_instance_of(Projects::LfsPointers::LfsImportService).to receive(:execute).and_return(oid_download_links)
- expect(Projects::LfsPointers::LfsDownloadService).to receive(:new).and_return(service).twice
- expect(service).to receive(:execute).twice
+ expect_any_instance_of(Projects::LfsPointers::LfsImportService).to receive(:execute)
subject.execute
end
+
+ context 'when lfs import fails' do
+ it 'logs the error' do
+ error_message = 'error message'
+
+ allow(Gitlab::GithubImport::ParallelImporter).to receive(:imports_repository?).and_return(false)
+ expect_any_instance_of(Projects::LfsPointers::LfsImportService).to receive(:execute).and_return(status: :error, message: error_message)
+ expect(Gitlab::AppLogger).to receive(:error).with("The Lfs import process failed. #{error_message}")
+
+ subject.execute
+ end
+ end
end
end
diff --git a/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb
index f1c0f5b9576..80debcd3a7a 100644
--- a/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb
+++ b/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb
@@ -1,5 +1,4 @@
# frozen_string_literal: true
-
require 'spec_helper'
describe Projects::LfsPointers::LfsDownloadLinkListService do
@@ -34,7 +33,10 @@ describe Projects::LfsPointers::LfsDownloadLinkListService do
before do
allow(project).to receive(:lfs_enabled?).and_return(true)
- allow(Gitlab::HTTP).to receive(:post).and_return(objects_response)
+ response = instance_double(HTTParty::Response)
+ allow(response).to receive(:body).and_return(objects_response.to_json)
+ allow(response).to receive(:success?).and_return(true)
+ allow(Gitlab::HTTP).to receive(:post).and_return(response)
end
describe '#execute' do
@@ -85,11 +87,26 @@ describe Projects::LfsPointers::LfsDownloadLinkListService do
end
describe '#get_download_links' do
- it 'raise errorif request fails' do
+ it 'raise error if request fails' do
allow(Gitlab::HTTP).to receive(:post).and_return(Struct.new(:success?, :message).new(false, 'Failed request'))
expect { subject.send(:get_download_links, new_oids) }.to raise_error(described_class::DownloadLinksError)
end
+
+ shared_examples 'JSON parse errors' do |body|
+ it 'raises error' do
+ response = instance_double(HTTParty::Response)
+ allow(response).to receive(:body).and_return(body)
+ allow(response).to receive(:success?).and_return(true)
+ allow(Gitlab::HTTP).to receive(:post).and_return(response)
+
+ expect { subject.send(:get_download_links, new_oids) }.to raise_error(described_class::DownloadLinksError)
+ end
+ end
+
+ it_behaves_like 'JSON parse errors', '{'
+ it_behaves_like 'JSON parse errors', '{}'
+ it_behaves_like 'JSON parse errors', '{ foo: 123 }'
end
describe '#parse_response_links' do
diff --git a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
index cde3f2d6155..75d534c59bf 100644
--- a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
+++ b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
@@ -1,8 +1,9 @@
# frozen_string_literal: true
-
require 'spec_helper'
describe Projects::LfsPointers::LfsDownloadService do
+ include StubRequests
+
let(:project) { create(:project) }
let(:lfs_content) { SecureRandom.random_bytes(10) }
let(:oid) { Digest::SHA256.hexdigest(lfs_content) }
@@ -63,7 +64,7 @@ describe Projects::LfsPointers::LfsDownloadService do
describe '#execute' do
context 'when file download succeeds' do
before do
- WebMock.stub_request(:get, download_link).to_return(body: lfs_content)
+ stub_full_request(download_link).to_return(body: lfs_content)
end
it_behaves_like 'lfs object is created'
@@ -105,7 +106,7 @@ describe Projects::LfsPointers::LfsDownloadService do
let(:size) { 1 }
before do
- WebMock.stub_request(:get, download_link).to_return(body: lfs_content)
+ stub_full_request(download_link).to_return(body: lfs_content)
end
it_behaves_like 'no lfs object is created'
@@ -119,7 +120,7 @@ describe Projects::LfsPointers::LfsDownloadService do
context 'when downloaded lfs file has a different oid' do
before do
- WebMock.stub_request(:get, download_link).to_return(body: lfs_content)
+ stub_full_request(download_link).to_return(body: lfs_content)
allow_any_instance_of(Digest::SHA256).to receive(:hexdigest).and_return('foobar')
end
@@ -137,7 +138,7 @@ describe Projects::LfsPointers::LfsDownloadService do
let(:lfs_object) { LfsDownloadObject.new(oid: oid, size: size, link: download_link_with_credentials) }
before do
- WebMock.stub_request(:get, download_link).with(headers: { 'Authorization' => 'Basic dXNlcjpwYXNzd29yZA==' }).to_return(body: lfs_content)
+ stub_full_request(download_link).with(headers: { 'Authorization' => 'Basic dXNlcjpwYXNzd29yZA==' }).to_return(body: lfs_content)
end
it 'the request adds authorization headers' do
@@ -150,7 +151,7 @@ describe Projects::LfsPointers::LfsDownloadService do
let(:local_request_setting) { true }
before do
- WebMock.stub_request(:get, download_link).to_return(body: lfs_content)
+ stub_full_request(download_link, ip_address: '192.168.2.120').to_return(body: lfs_content)
end
it_behaves_like 'lfs object is created'
@@ -174,7 +175,8 @@ describe Projects::LfsPointers::LfsDownloadService do
with_them do
before do
- WebMock.stub_request(:get, download_link).to_return(status: 301, headers: { 'Location' => redirect_link })
+ stub_full_request(download_link, ip_address: '192.168.2.120')
+ .to_return(status: 301, headers: { 'Location' => redirect_link })
end
it_behaves_like 'no lfs object is created'
@@ -185,8 +187,8 @@ describe Projects::LfsPointers::LfsDownloadService do
let(:redirect_link) { "http://example.com/"}
before do
- WebMock.stub_request(:get, download_link).to_return(status: 301, headers: { 'Location' => redirect_link })
- WebMock.stub_request(:get, redirect_link).to_return(body: lfs_content)
+ stub_full_request(download_link).to_return(status: 301, headers: { 'Location' => redirect_link })
+ stub_full_request(redirect_link).to_return(body: lfs_content)
end
it_behaves_like 'lfs object is created'
diff --git a/spec/services/projects/lfs_pointers/lfs_import_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_import_service_spec.rb
index 5c9ca99df7c..7ca20a6d751 100644
--- a/spec/services/projects/lfs_pointers/lfs_import_service_spec.rb
+++ b/spec/services/projects/lfs_pointers/lfs_import_service_spec.rb
@@ -1,148 +1,63 @@
# frozen_string_literal: true
-
require 'spec_helper'
describe Projects::LfsPointers::LfsImportService do
+ let(:project) { create(:project) }
+ let(:user) { project.creator }
let(:import_url) { 'http://www.gitlab.com/demo/repo.git' }
- let(:default_endpoint) { "#{import_url}/info/lfs/objects/batch"}
- let(:group) { create(:group, lfs_enabled: true)}
- let!(:project) { create(:project, namespace: group, import_url: import_url, lfs_enabled: true) }
- let!(:lfs_objects_project) { create_list(:lfs_objects_project, 2, project: project) }
- let!(:existing_lfs_objects) { LfsObject.pluck(:oid, :size).to_h }
- let(:oids) { { 'oid1' => 123, 'oid2' => 125 } }
let(:oid_download_links) { { 'oid1' => "#{import_url}/gitlab-lfs/objects/oid1", 'oid2' => "#{import_url}/gitlab-lfs/objects/oid2" } }
- let(:all_oids) { existing_lfs_objects.merge(oids) }
- let(:remote_uri) { URI.parse(lfs_endpoint) }
-
- subject { described_class.new(project) }
-
- before do
- allow(project.repository).to receive(:lfsconfig_for).and_return(nil)
- allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
- allow_any_instance_of(Projects::LfsPointers::LfsListService).to receive(:execute).and_return(all_oids)
- end
-
- describe '#execute' do
- context 'when no lfs pointer is linked' do
- before do
- allow_any_instance_of(Projects::LfsPointers::LfsLinkService).to receive(:execute).and_return([])
- allow_any_instance_of(Projects::LfsPointers::LfsDownloadLinkListService).to receive(:execute).and_return(oid_download_links)
- expect(Projects::LfsPointers::LfsDownloadLinkListService).to receive(:new).with(project, remote_uri: URI.parse(default_endpoint)).and_call_original
- end
-
- it 'retrieves all lfs pointers in the project repository' do
- expect_any_instance_of(Projects::LfsPointers::LfsListService).to receive(:execute)
-
- subject.execute
- end
-
- it 'links existent lfs objects to the project' do
- expect_any_instance_of(Projects::LfsPointers::LfsLinkService).to receive(:execute)
-
- subject.execute
- end
- it 'retrieves the download links of non existent objects' do
- expect_any_instance_of(Projects::LfsPointers::LfsDownloadLinkListService).to receive(:execute).with(all_oids)
+ subject { described_class.new(project, user) }
- subject.execute
- end
+ context 'when lfs is enabled for the project' do
+ before do
+ allow(project).to receive(:lfs_enabled?).and_return(true)
end
- context 'when some lfs objects are linked' do
- before do
- allow_any_instance_of(Projects::LfsPointers::LfsLinkService).to receive(:execute).and_return(existing_lfs_objects.keys)
- allow_any_instance_of(Projects::LfsPointers::LfsDownloadLinkListService).to receive(:execute).and_return(oid_download_links)
- end
+ it 'downloads lfs objects' do
+ service = double
+ expect_any_instance_of(Projects::LfsPointers::LfsObjectDownloadListService).to receive(:execute).and_return(oid_download_links)
+ expect(Projects::LfsPointers::LfsDownloadService).to receive(:new).and_return(service).twice
+ expect(service).to receive(:execute).twice
- it 'retrieves the download links of non existent objects' do
- expect_any_instance_of(Projects::LfsPointers::LfsDownloadLinkListService).to receive(:execute).with(oids)
+ result = subject.execute
- subject.execute
- end
+ expect(result[:status]).to eq :success
end
- context 'when all lfs objects are linked' do
- before do
- allow_any_instance_of(Projects::LfsPointers::LfsLinkService).to receive(:execute).and_return(all_oids.keys)
- allow_any_instance_of(Projects::LfsPointers::LfsDownloadLinkListService).to receive(:execute)
- end
+ context 'when no downloadable lfs object links' do
+ it 'does not call LfsDownloadService' do
+ expect_any_instance_of(Projects::LfsPointers::LfsObjectDownloadListService).to receive(:execute).and_return({})
+ expect(Projects::LfsPointers::LfsDownloadService).not_to receive(:new)
- it 'retrieves no download links' do
- expect_any_instance_of(Projects::LfsPointers::LfsDownloadLinkListService).to receive(:execute).with({}).and_call_original
+ result = subject.execute
- expect(subject.execute).to be_empty
+ expect(result[:status]).to eq :success
end
end
- context 'when lfsconfig file exists' do
- before do
- allow(project.repository).to receive(:lfsconfig_for).and_return("[lfs]\n\turl = #{lfs_endpoint}\n")
- end
-
- context 'when url points to the same import url host' do
- let(:lfs_endpoint) { "#{import_url}/different_endpoint" }
- let(:service) { double }
-
- before do
- allow(service).to receive(:execute)
- end
- it 'downloads lfs object using the new endpoint' do
- expect(Projects::LfsPointers::LfsDownloadLinkListService).to receive(:new).with(project, remote_uri: remote_uri).and_return(service)
-
- subject.execute
- end
-
- context 'when import url has credentials' do
- let(:import_url) { 'http://user:password@www.gitlab.com/demo/repo.git'}
-
- it 'adds the credentials to the new endpoint' do
- expect(Projects::LfsPointers::LfsDownloadLinkListService)
- .to receive(:new).with(project, remote_uri: URI.parse("http://user:password@www.gitlab.com/demo/repo.git/different_endpoint"))
- .and_return(service)
-
- subject.execute
- end
-
- context 'when url has its own credentials' do
- let(:lfs_endpoint) { "http://user1:password1@www.gitlab.com/demo/repo.git/different_endpoint" }
+ context 'when an exception is raised' do
+ it 'returns error' do
+ error_message = "error message"
+ expect_any_instance_of(Projects::LfsPointers::LfsObjectDownloadListService).to receive(:execute).and_raise(StandardError, error_message)
- it 'does not add the import url credentials' do
- expect(Projects::LfsPointers::LfsDownloadLinkListService)
- .to receive(:new).with(project, remote_uri: remote_uri)
- .and_return(service)
+ result = subject.execute
- subject.execute
- end
- end
- end
- end
-
- context 'when url points to a third party service' do
- let(:lfs_endpoint) { 'http://third_party_service.com/info/lfs/objects/' }
-
- it 'disables lfs from the project' do
- expect(project.lfs_enabled?).to be_truthy
-
- subject.execute
-
- expect(project.lfs_enabled?).to be_falsey
- end
-
- it 'does not download anything' do
- expect_any_instance_of(Projects::LfsPointers::LfsListService).not_to receive(:execute)
-
- subject.execute
- end
+ expect(result[:status]).to eq :error
+ expect(result[:message]).to eq error_message
end
end
end
- describe '#default_endpoint_uri' do
- let(:import_url) { 'http://www.gitlab.com/demo/repo' }
+ context 'when lfs is not enabled for the project' do
+ it 'does not download lfs objects' do
+ allow(project).to receive(:lfs_enabled?).and_return(false)
+ expect(Projects::LfsPointers::LfsObjectDownloadListService).not_to receive(:new)
+ expect(Projects::LfsPointers::LfsDownloadService).not_to receive(:new)
+
+ result = subject.execute
- it 'adds suffix .git if the url does not have it' do
- expect(subject.send(:default_endpoint_uri).path).to match(/repo.git/)
+ expect(result[:status]).to eq :success
end
end
end
diff --git a/spec/services/projects/lfs_pointers/lfs_link_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_link_service_spec.rb
index 5caa9de732e..849601c4a63 100644
--- a/spec/services/projects/lfs_pointers/lfs_link_service_spec.rb
+++ b/spec/services/projects/lfs_pointers/lfs_link_service_spec.rb
@@ -1,5 +1,4 @@
# frozen_string_literal: true
-
require 'spec_helper'
describe Projects::LfsPointers::LfsLinkService do
diff --git a/spec/services/projects/lfs_pointers/lfs_object_download_list_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_object_download_list_service_spec.rb
new file mode 100644
index 00000000000..9dac29765a2
--- /dev/null
+++ b/spec/services/projects/lfs_pointers/lfs_object_download_list_service_spec.rb
@@ -0,0 +1,148 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Projects::LfsPointers::LfsObjectDownloadListService do
+ let(:import_url) { 'http://www.gitlab.com/demo/repo.git' }
+ let(:default_endpoint) { "#{import_url}/info/lfs/objects/batch"}
+ let(:group) { create(:group, lfs_enabled: true)}
+ let!(:project) { create(:project, namespace: group, import_url: import_url, lfs_enabled: true) }
+ let!(:lfs_objects_project) { create_list(:lfs_objects_project, 2, project: project) }
+ let!(:existing_lfs_objects) { LfsObject.pluck(:oid, :size).to_h }
+ let(:oids) { { 'oid1' => 123, 'oid2' => 125 } }
+ let(:oid_download_links) { { 'oid1' => "#{import_url}/gitlab-lfs/objects/oid1", 'oid2' => "#{import_url}/gitlab-lfs/objects/oid2" } }
+ let(:all_oids) { existing_lfs_objects.merge(oids) }
+ let(:remote_uri) { URI.parse(lfs_endpoint) }
+
+ subject { described_class.new(project) }
+
+ before do
+ allow(project.repository).to receive(:lfsconfig_for).and_return(nil)
+ allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
+ allow_any_instance_of(Projects::LfsPointers::LfsListService).to receive(:execute).and_return(all_oids)
+ end
+
+ describe '#execute' do
+ context 'when no lfs pointer is linked' do
+ before do
+ allow_any_instance_of(Projects::LfsPointers::LfsLinkService).to receive(:execute).and_return([])
+ allow_any_instance_of(Projects::LfsPointers::LfsDownloadLinkListService).to receive(:execute).and_return(oid_download_links)
+ expect(Projects::LfsPointers::LfsDownloadLinkListService).to receive(:new).with(project, remote_uri: URI.parse(default_endpoint)).and_call_original
+ end
+
+ it 'retrieves all lfs pointers in the project repository' do
+ expect_any_instance_of(Projects::LfsPointers::LfsListService).to receive(:execute)
+
+ subject.execute
+ end
+
+ it 'links existent lfs objects to the project' do
+ expect_any_instance_of(Projects::LfsPointers::LfsLinkService).to receive(:execute)
+
+ subject.execute
+ end
+
+ it 'retrieves the download links of non existent objects' do
+ expect_any_instance_of(Projects::LfsPointers::LfsDownloadLinkListService).to receive(:execute).with(all_oids)
+
+ subject.execute
+ end
+ end
+
+ context 'when some lfs objects are linked' do
+ before do
+ allow_any_instance_of(Projects::LfsPointers::LfsLinkService).to receive(:execute).and_return(existing_lfs_objects.keys)
+ allow_any_instance_of(Projects::LfsPointers::LfsDownloadLinkListService).to receive(:execute).and_return(oid_download_links)
+ end
+
+ it 'retrieves the download links of non existent objects' do
+ expect_any_instance_of(Projects::LfsPointers::LfsDownloadLinkListService).to receive(:execute).with(oids)
+
+ subject.execute
+ end
+ end
+
+ context 'when all lfs objects are linked' do
+ before do
+ allow_any_instance_of(Projects::LfsPointers::LfsLinkService).to receive(:execute).and_return(all_oids.keys)
+ allow_any_instance_of(Projects::LfsPointers::LfsDownloadLinkListService).to receive(:execute)
+ end
+
+ it 'retrieves no download links' do
+ expect_any_instance_of(Projects::LfsPointers::LfsDownloadLinkListService).to receive(:execute).with({}).and_call_original
+
+ expect(subject.execute).to be_empty
+ end
+ end
+
+ context 'when lfsconfig file exists' do
+ before do
+ allow(project.repository).to receive(:lfsconfig_for).and_return("[lfs]\n\turl = #{lfs_endpoint}\n")
+ end
+
+ context 'when url points to the same import url host' do
+ let(:lfs_endpoint) { "#{import_url}/different_endpoint" }
+ let(:service) { double }
+
+ before do
+ allow(service).to receive(:execute)
+ end
+
+ it 'downloads lfs object using the new endpoint' do
+ expect(Projects::LfsPointers::LfsDownloadLinkListService).to receive(:new).with(project, remote_uri: remote_uri).and_return(service)
+
+ subject.execute
+ end
+
+ context 'when import url has credentials' do
+ let(:import_url) { 'http://user:password@www.gitlab.com/demo/repo.git'}
+
+ it 'adds the credentials to the new endpoint' do
+ expect(Projects::LfsPointers::LfsDownloadLinkListService)
+ .to receive(:new).with(project, remote_uri: URI.parse("http://user:password@www.gitlab.com/demo/repo.git/different_endpoint"))
+ .and_return(service)
+
+ subject.execute
+ end
+
+ context 'when url has its own credentials' do
+ let(:lfs_endpoint) { "http://user1:password1@www.gitlab.com/demo/repo.git/different_endpoint" }
+
+ it 'does not add the import url credentials' do
+ expect(Projects::LfsPointers::LfsDownloadLinkListService)
+ .to receive(:new).with(project, remote_uri: remote_uri)
+ .and_return(service)
+
+ subject.execute
+ end
+ end
+ end
+ end
+
+ context 'when url points to a third party service' do
+ let(:lfs_endpoint) { 'http://third_party_service.com/info/lfs/objects/' }
+
+ it 'disables lfs from the project' do
+ expect(project.lfs_enabled?).to be_truthy
+
+ subject.execute
+
+ expect(project.lfs_enabled?).to be_falsey
+ end
+
+ it 'does not download anything' do
+ expect_any_instance_of(Projects::LfsPointers::LfsListService).not_to receive(:execute)
+
+ subject.execute
+ end
+ end
+ end
+ end
+
+ describe '#default_endpoint_uri' do
+ let(:import_url) { 'http://www.gitlab.com/demo/repo' }
+
+ it 'adds suffix .git if the url does not have it' do
+ expect(subject.send(:default_endpoint_uri).path).to match(/repo.git/)
+ end
+ end
+end
diff --git a/spec/services/projects/operations/update_service_spec.rb b/spec/services/projects/operations/update_service_spec.rb
index 86b1ec83f50..7e765659b9d 100644
--- a/spec/services/projects/operations/update_service_spec.rb
+++ b/spec/services/projects/operations/update_service_spec.rb
@@ -11,6 +11,56 @@ describe Projects::Operations::UpdateService do
subject { described_class.new(project, user, params) }
describe '#execute' do
+ context 'metrics dashboard setting' do
+ let(:params) do
+ {
+ metrics_setting_attributes: {
+ external_dashboard_url: 'http://gitlab.com'
+ }
+ }
+ end
+
+ context 'without existing metrics dashboard setting' do
+ it 'creates a setting' do
+ expect(result[:status]).to eq(:success)
+
+ expect(project.reload.metrics_setting.external_dashboard_url).to eq(
+ 'http://gitlab.com'
+ )
+ end
+ end
+
+ context 'with existing metrics dashboard setting' do
+ before do
+ create(:project_metrics_setting, project: project)
+ end
+
+ it 'updates the settings' do
+ expect(result[:status]).to eq(:success)
+
+ expect(project.reload.metrics_setting.external_dashboard_url).to eq(
+ 'http://gitlab.com'
+ )
+ end
+
+ context 'with blank external_dashboard_url in params' do
+ let(:params) do
+ {
+ metrics_setting_attributes: {
+ external_dashboard_url: ''
+ }
+ }
+ end
+
+ it 'destroys the metrics_setting entry in DB' do
+ expect(result[:status]).to eq(:success)
+
+ expect(project.reload.metrics_setting).to be_nil
+ end
+ end
+ end
+ end
+
context 'error tracking' do
context 'with existing error tracking setting' do
let(:params) do
diff --git a/spec/services/projects/repository_languages_service_spec.rb b/spec/services/projects/repository_languages_service_spec.rb
index 09c61363ad2..46c5095327d 100644
--- a/spec/services/projects/repository_languages_service_spec.rb
+++ b/spec/services/projects/repository_languages_service_spec.rb
@@ -10,7 +10,7 @@ describe Projects::RepositoryLanguagesService do
context 'when a project is without detected programming languages' do
it 'schedules a worker and returns the empty result' do
- expect(::DetectRepositoryLanguagesWorker).to receive(:perform_async).with(project.id, project.owner.id)
+ expect(::DetectRepositoryLanguagesWorker).to receive(:perform_async).with(project.id)
expect(service.execute).to eq([])
end
end
@@ -19,7 +19,7 @@ describe Projects::RepositoryLanguagesService do
let!(:repository_language) { create(:repository_language, project: project) }
it 'does not schedule a worker and returns the detected languages' do
- expect(::DetectRepositoryLanguagesWorker).not_to receive(:perform_async).with(project.id, project.owner.id)
+ expect(::DetectRepositoryLanguagesWorker).not_to receive(:perform_async).with(project.id)
languages = service.execute
diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb
index 9acc3657fa9..a47c10d991a 100644
--- a/spec/services/projects/transfer_service_spec.rb
+++ b/spec/services/projects/transfer_service_spec.rb
@@ -73,33 +73,6 @@ describe Projects::TransferService do
shard_name: project.repository_storage
)
end
-
- context 'new group has a kubernetes cluster' do
- let(:group_cluster) { create(:cluster, :group, :provided_by_gcp) }
- let(:group) { group_cluster.group }
-
- let(:token) { 'aaaa' }
- let(:service_account_creator) { double(Clusters::Gcp::Kubernetes::CreateOrUpdateServiceAccountService, execute: true) }
- let(:secrets_fetcher) { double(Clusters::Gcp::Kubernetes::FetchKubernetesTokenService, execute: token) }
-
- subject { transfer_project(project, user, group) }
-
- before do
- stub_feature_flags(ci_preparing_state: false)
- expect(Clusters::Gcp::Kubernetes::CreateOrUpdateServiceAccountService).to receive(:namespace_creator).and_return(service_account_creator)
- expect(Clusters::Gcp::Kubernetes::FetchKubernetesTokenService).to receive(:new).and_return(secrets_fetcher)
- end
-
- it 'creates kubernetes namespace for the project' do
- subject
-
- expect(project.kubernetes_namespaces.count).to eq(1)
-
- kubernetes_namespace = group_cluster.kubernetes_namespaces.first
- expect(kubernetes_namespace).to be_present
- expect(kubernetes_namespace.project).to eq(project)
- end
- end
end
context 'when transfer fails' do
diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb
index 7c91f0bbe6e..b597717c347 100644
--- a/spec/services/projects/update_pages_service_spec.rb
+++ b/spec/services/projects/update_pages_service_spec.rb
@@ -27,59 +27,6 @@ describe Projects::UpdatePagesService do
it { is_expected.not_to match(Gitlab::PathRegex.namespace_format_regex) }
end
- context 'legacy artifacts' do
- before do
- build.update(legacy_artifacts_file: file)
- build.update(legacy_artifacts_metadata: metadata)
- end
-
- describe 'pages artifacts' do
- it "doesn't delete artifacts after deploying" do
- expect(execute).to eq(:success)
-
- expect(build.reload.artifacts?).to eq(true)
- end
- end
-
- it 'succeeds' do
- expect(project.pages_deployed?).to be_falsey
- expect(execute).to eq(:success)
- expect(project.pages_deployed?).to be_truthy
-
- # Check that all expected files are extracted
- %w[index.html zero .hidden/file].each do |filename|
- expect(File.exist?(File.join(project.public_pages_path, filename))).to be_truthy
- end
- end
-
- it 'limits pages size' do
- stub_application_setting(max_pages_size: 1)
- expect(execute).not_to eq(:success)
- end
-
- it 'removes pages after destroy' do
- expect(PagesWorker).to receive(:perform_in)
- expect(project.pages_deployed?).to be_falsey
- expect(execute).to eq(:success)
- expect(project.pages_deployed?).to be_truthy
- project.destroy
- expect(project.pages_deployed?).to be_falsey
- end
-
- it 'fails if sha on branch is not latest' do
- build.update(ref: 'feature')
-
- expect(execute).not_to eq(:success)
- end
-
- it 'fails for empty file fails' do
- build.update(legacy_artifacts_file: empty_file)
-
- expect { execute }
- .to raise_error(Projects::UpdatePagesService::FailedToExtractError)
- end
- end
-
context 'for new artifacts' do
context "for a valid job" do
before do
@@ -207,7 +154,7 @@ describe Projects::UpdatePagesService do
end
it 'fails for invalid archive' do
- build.update(legacy_artifacts_file: invalid_file)
+ create(:ci_job_artifact, :archive, file: invalid_file, job: build)
expect(execute).not_to eq(:success)
end
@@ -218,8 +165,8 @@ describe Projects::UpdatePagesService do
file = fixture_file_upload('spec/fixtures/pages.zip')
metafile = fixture_file_upload('spec/fixtures/pages.zip.meta')
- build.update(legacy_artifacts_file: file)
- build.update(legacy_artifacts_metadata: metafile)
+ create(:ci_job_artifact, :archive, file: file, job: build)
+ create(:ci_job_artifact, :metadata, file: metafile, job: build)
allow(build).to receive(:artifacts_metadata_entry)
.and_return(metadata)
diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb
index c37147e7d3b..1dcfb739eb6 100644
--- a/spec/services/projects/update_service_spec.rb
+++ b/spec/services/projects/update_service_spec.rb
@@ -45,6 +45,7 @@ describe Projects::UpdateService do
it 'updates the project to private' do
expect(TodosDestroyer::ProjectPrivateWorker).to receive(:perform_in).with(Todo::WAIT_FOR_DELETE, project.id)
+ expect(TodosDestroyer::ConfidentialIssueWorker).to receive(:perform_in).with(Todo::WAIT_FOR_DELETE, nil, project.id)
result = update_project(project, user, visibility_level: Gitlab::VisibilityLevel::PRIVATE)
@@ -440,6 +441,8 @@ describe Projects::UpdateService do
context 'when auto devops is set to instance setting' do
before do
project.create_auto_devops!(enabled: nil)
+ project.reload
+
allow(project.auto_devops).to receive(:previous_changes).and_return('enabled' => true)
end
diff --git a/spec/services/projects/update_statistics_service_spec.rb b/spec/services/projects/update_statistics_service_spec.rb
index 5000ea58e5f..8534853fbc7 100644
--- a/spec/services/projects/update_statistics_service_spec.rb
+++ b/spec/services/projects/update_statistics_service_spec.rb
@@ -17,19 +17,9 @@ describe Projects::UpdateStatisticsService do
end
end
- context 'with an existing project without a repository' do
+ context 'with an existing project' do
let(:project) { create(:project) }
- it 'does nothing' do
- expect_any_instance_of(ProjectStatistics).not_to receive(:refresh!)
-
- service.execute
- end
- end
-
- context 'with an existing project with a repository' do
- let(:project) { create(:project, :repository) }
-
it 'refreshes the project statistics' do
expect_any_instance_of(ProjectStatistics).to receive(:refresh!)
.with(only: statistics.map(&:to_sym))
diff --git a/spec/services/service_response_spec.rb b/spec/services/service_response_spec.rb
new file mode 100644
index 00000000000..30bd4d6820b
--- /dev/null
+++ b/spec/services/service_response_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+ActiveSupport::Dependencies.autoload_paths << 'app/services'
+
+describe ServiceResponse do
+ describe '.success' do
+ it 'creates a successful response without a message' do
+ expect(described_class.success).to be_success
+ end
+
+ it 'creates a successful response with a message' do
+ response = described_class.success(message: 'Good orange')
+
+ expect(response).to be_success
+ expect(response.message).to eq('Good orange')
+ end
+ end
+
+ describe '.error' do
+ it 'creates a failed response without HTTP status' do
+ response = described_class.error(message: 'Bad apple')
+
+ expect(response).to be_error
+ expect(response.message).to eq('Bad apple')
+ end
+
+ it 'creates a failed response with HTTP status' do
+ response = described_class.error(message: 'Bad apple', http_status: 400)
+
+ expect(response).to be_error
+ expect(response.message).to eq('Bad apple')
+ expect(response.http_status).to eq(400)
+ end
+ end
+
+ describe '#success?' do
+ it 'returns true for a successful response' do
+ expect(described_class.success.success?).to eq(true)
+ end
+
+ it 'returns false for a failed response' do
+ expect(described_class.error(message: 'Bad apple').success?).to eq(false)
+ end
+ end
+
+ describe '#error?' do
+ it 'returns false for a successful response' do
+ expect(described_class.success.error?).to eq(false)
+ end
+
+ it 'returns true for a failed response' do
+ expect(described_class.error(message: 'Bad apple').error?).to eq(true)
+ end
+ end
+end
diff --git a/spec/services/submit_usage_ping_service_spec.rb b/spec/services/submit_usage_ping_service_spec.rb
index 78df9bf96bf..653f17a4324 100644
--- a/spec/services/submit_usage_ping_service_spec.rb
+++ b/spec/services/submit_usage_ping_service_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe SubmitUsagePingService do
+ include StubRequests
+
context 'when usage ping is disabled' do
before do
stub_application_setting(usage_ping_enabled: false)
@@ -99,7 +101,7 @@ describe SubmitUsagePingService do
end
def stub_response(body)
- stub_request(:post, 'https://version.gitlab.com/usage_data')
+ stub_full_request('https://version.gitlab.com/usage_data', method: :post)
.to_return(
headers: { 'Content-Type' => 'application/json' },
body: body.to_json
diff --git a/spec/services/suggestions/apply_service_spec.rb b/spec/services/suggestions/apply_service_spec.rb
index 7732767137c..bdbcb0fdb07 100644
--- a/spec/services/suggestions/apply_service_spec.rb
+++ b/spec/services/suggestions/apply_service_spec.rb
@@ -5,6 +5,16 @@ require 'spec_helper'
describe Suggestions::ApplyService do
include ProjectForksHelper
+ def build_position(args = {})
+ default_args = { old_path: "files/ruby/popen.rb",
+ new_path: "files/ruby/popen.rb",
+ old_line: nil,
+ new_line: 9,
+ diff_refs: merge_request.diff_refs }
+
+ Gitlab::Diff::Position.new(default_args.merge(args))
+ end
+
shared_examples 'successfully creates commit and updates suggestion' do
def apply(suggestion)
result = subject.execute(suggestion)
@@ -43,13 +53,7 @@ describe Suggestions::ApplyService do
let(:project) { create(:project, :repository) }
let(:user) { create(:user, :commit_email) }
- let(:position) do
- Gitlab::Diff::Position.new(old_path: "files/ruby/popen.rb",
- new_path: "files/ruby/popen.rb",
- old_line: nil,
- new_line: 9,
- diff_refs: merge_request.diff_refs)
- end
+ let(:position) { build_position }
let(:diff_note) do
create(:diff_note_on_merge_request, noteable: merge_request, position: position, project: project)
@@ -333,6 +337,56 @@ describe Suggestions::ApplyService do
it_behaves_like 'successfully creates commit and updates suggestion'
end
+
+ context 'remove an empty line suggestion' do
+ let(:expected_content) do
+ <<~CONTENT
+ require 'fileutils'
+ require 'open3'
+
+ module Popen
+ extend self
+
+ def popen(cmd, path=nil)
+ unless cmd.is_a?(Array)
+ raise RuntimeError, "System commands must be given as an array of strings"
+ end
+
+ path ||= Dir.pwd
+ vars = {
+ "PWD" => path
+ }
+
+ options = {
+ chdir: path
+ }
+
+ unless File.directory?(path)
+ FileUtils.mkdir_p(path)
+ end
+
+ @cmd_output = ""
+ @cmd_status = 0
+
+ Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|
+ @cmd_output << stdout.read
+ @cmd_output << stderr.read
+ @cmd_status = wait_thr.value.exitstatus
+ end
+
+ return @cmd_output, @cmd_status
+ end
+ end
+ CONTENT
+ end
+
+ let(:position) { build_position(new_line: 13) }
+ let(:suggestion) do
+ create(:suggestion, :content_from_repo, note: diff_note, to_content: "")
+ end
+
+ it_behaves_like 'successfully creates commit and updates suggestion'
+ end
end
context 'fork-project' do
diff --git a/spec/services/suggestions/create_service_spec.rb b/spec/services/suggestions/create_service_spec.rb
index ce4990a34a4..d95f9e3349b 100644
--- a/spec/services/suggestions/create_service_spec.rb
+++ b/spec/services/suggestions/create_service_spec.rb
@@ -96,7 +96,7 @@ describe Suggestions::CreateService do
it 'creates no suggestion when diff file is not found' do
expect_next_instance_of(DiffNote) do |diff_note|
- expect(diff_note).to receive(:latest_diff_file).twice { nil }
+ expect(diff_note).to receive(:latest_diff_file).once { nil }
end
expect { subject.execute }.not_to change(Suggestion, :count)
@@ -151,6 +151,26 @@ describe Suggestions::CreateService do
subject.execute
end
end
+
+ context 'when a patch removes an empty line' do
+ let(:markdown) do
+ <<-MARKDOWN.strip_heredoc
+ ```suggestion
+ ```
+ MARKDOWN
+ end
+ let(:position) { build_position(new_line: 13) }
+
+ it 'creates an appliable suggestion' do
+ subject.execute
+
+ suggestion = note.suggestions.last
+
+ expect(suggestion).to be_appliable
+ expect(suggestion.from_content).to eq("\n")
+ expect(suggestion.to_content).to eq("")
+ end
+ end
end
end
end
diff --git a/spec/services/system_hooks_service_spec.rb b/spec/services/system_hooks_service_spec.rb
index 5dc7394b84f..f5c6e972953 100644
--- a/spec/services/system_hooks_service_spec.rb
+++ b/spec/services/system_hooks_service_spec.rb
@@ -86,20 +86,20 @@ describe SystemHooksService do
context 'group_rename' do
it 'contains old and new path' do
- allow(group).to receive(:path_was).and_return('old-path')
+ allow(group).to receive(:path_before_last_save).and_return('old-path')
data = event_data(group, :rename)
expect(data).to include(:event_name, :name, :created_at, :updated_at, :full_path, :path, :group_id, :old_path, :old_full_path)
expect(data[:path]).to eq(group.path)
expect(data[:full_path]).to eq(group.path)
- expect(data[:old_path]).to eq(group.path_was)
- expect(data[:old_full_path]).to eq(group.path_was)
+ expect(data[:old_path]).to eq(group.path_before_last_save)
+ expect(data[:old_full_path]).to eq(group.path_before_last_save)
end
it 'contains old and new full_path for subgroup' do
subgroup = create(:group, parent: group)
- allow(subgroup).to receive(:path_was).and_return('old-path')
+ allow(subgroup).to receive(:path_before_last_save).and_return('old-path')
data = event_data(subgroup, :rename)
@@ -110,13 +110,13 @@ describe SystemHooksService do
context 'user_rename' do
it 'contains old and new username' do
- allow(user).to receive(:username_was).and_return('old-username')
+ allow(user).to receive(:username_before_last_save).and_return('old-username')
data = event_data(user, :rename)
expect(data).to include(:event_name, :name, :created_at, :updated_at, :email, :user_id, :username, :old_username)
expect(data[:username]).to eq(user.username)
- expect(data[:old_username]).to eq(user.username_was)
+ expect(data[:old_username]).to eq(user.username_before_last_save)
end
end
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 51c5a803dbd..2420817e1f7 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -132,7 +132,7 @@ describe SystemNoteService do
end
it 'sets the note text' do
- link = "http://localhost/#{project.full_path}/tags/#{tag_name}"
+ link = "/#{project.full_path}/-/tags/#{tag_name}"
expect(subject.note).to eq "tagged commit #{noteable.sha} to [`#{tag_name}`](#{link})"
end
@@ -1139,7 +1139,7 @@ describe SystemNoteService do
diff_id = merge_request.merge_request_diff.id
line_code = change_position.line_code(project.repository)
- expect(subject.note).to include(diffs_project_merge_request_url(project, merge_request, diff_id: diff_id, anchor: line_code))
+ expect(subject.note).to include(diffs_project_merge_request_path(project, merge_request, diff_id: diff_id, anchor: line_code))
end
end
diff --git a/spec/services/todos/destroy/confidential_issue_service_spec.rb b/spec/services/todos/destroy/confidential_issue_service_spec.rb
index 78b6744b426..9f7e656f7d3 100644
--- a/spec/services/todos/destroy/confidential_issue_service_spec.rb
+++ b/spec/services/todos/destroy/confidential_issue_service_spec.rb
@@ -9,36 +9,60 @@ describe Todos::Destroy::ConfidentialIssueService do
let(:assignee) { create(:user) }
let(:guest) { create(:user) }
let(:project_member) { create(:user) }
- let(:issue) { create(:issue, project: project, author: author, assignees: [assignee]) }
-
- let!(:todo_issue_non_member) { create(:todo, user: user, target: issue, project: project) }
- let!(:todo_issue_member) { create(:todo, user: project_member, target: issue, project: project) }
- let!(:todo_issue_author) { create(:todo, user: author, target: issue, project: project) }
- let!(:todo_issue_asignee) { create(:todo, user: assignee, target: issue, project: project) }
- let!(:todo_issue_guest) { create(:todo, user: guest, target: issue, project: project) }
- let!(:todo_another_non_member) { create(:todo, user: user, project: project) }
+ let(:issue_1) { create(:issue, :confidential, project: project, author: author, assignees: [assignee]) }
describe '#execute' do
before do
project.add_developer(project_member)
project.add_guest(guest)
+
+ # todos not to be deleted
+ create(:todo, user: project_member, target: issue_1, project: project)
+ create(:todo, user: author, target: issue_1, project: project)
+ create(:todo, user: assignee, target: issue_1, project: project)
+ create(:todo, user: user, project: project)
+ # Todos to be deleted
+ create(:todo, user: guest, target: issue_1, project: project)
+ create(:todo, user: user, target: issue_1, project: project)
end
- subject { described_class.new(issue.id).execute }
+ subject { described_class.new(issue_id: issue_1.id).execute }
- context 'when provided issue is confidential' do
- before do
- issue.update!(confidential: true)
+ context 'when issue_id parameter is present' do
+ context 'when provided issue is confidential' do
+ it 'removes issue todos for users who can not access the confidential issue' do
+ expect { subject }.to change { Todo.count }.from(6).to(4)
+ end
end
- it 'removes issue todos for users who can not access the confidential issue' do
- expect { subject }.to change { Todo.count }.from(6).to(4)
+ context 'when provided issue is not confidential' do
+ it 'does not remove any todos' do
+ issue_1.update(confidential: false)
+
+ expect { subject }.not_to change { Todo.count }
+ end
end
end
- context 'when provided issue is not confidential' do
- it 'does not remove any todos' do
- expect { subject }.not_to change { Todo.count }
+ context 'when project_id parameter is present' do
+ subject { described_class.new(issue_id: nil, project_id: project.id).execute }
+
+ it 'removes issues todos for users that cannot access confidential issues' do
+ issue_2 = create(:issue, :confidential, project: project)
+ issue_3 = create(:issue, :confidential, project: project, author: author, assignees: [assignee])
+ issue_4 = create(:issue, project: project)
+ # Todos not to be deleted
+ create(:todo, user: guest, target: issue_1, project: project)
+ create(:todo, user: assignee, target: issue_1, project: project)
+ create(:todo, user: project_member, target: issue_2, project: project)
+ create(:todo, user: author, target: issue_3, project: project)
+ create(:todo, user: user, target: issue_4, project: project)
+ create(:todo, user: user, project: project)
+ # Todos to be deleted
+ create(:todo, user: user, target: issue_1, project: project)
+ create(:todo, user: guest, target: issue_2, project: project)
+
+ expect { subject }.to change { Todo.count }.from(14).to(10)
end
end
end
diff --git a/spec/services/todos/destroy/entity_leave_service_spec.rb b/spec/services/todos/destroy/entity_leave_service_spec.rb
index 1447b9d4126..2a553e18807 100644
--- a/spec/services/todos/destroy/entity_leave_service_spec.rb
+++ b/spec/services/todos/destroy/entity_leave_service_spec.rb
@@ -75,6 +75,13 @@ describe Todos::Destroy::EntityLeaveService do
project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
end
+ it 'enqueues the PrivateFeaturesWorker' do
+ expect(TodosDestroyer::PrivateFeaturesWorker)
+ .to receive(:perform_async).with(project.id, user.id)
+
+ subject
+ end
+
context 'confidential issues' do
context 'when a user is not an author of confidential issue' do
it 'removes only confidential issues todos' do
@@ -246,6 +253,13 @@ describe Todos::Destroy::EntityLeaveService do
project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
end
+ it 'enqueues the PrivateFeaturesWorker' do
+ expect(TodosDestroyer::PrivateFeaturesWorker)
+ .to receive(:perform_async).with(project.id, user.id)
+
+ subject
+ end
+
context 'when user is not member' do
it 'removes only confidential issues todos' do
expect { subject }.to change { Todo.count }.from(5).to(4)
diff --git a/spec/services/update_deployment_service_spec.rb b/spec/services/update_deployment_service_spec.rb
index c664bac39fc..7dc52f6816a 100644
--- a/spec/services/update_deployment_service_spec.rb
+++ b/spec/services/update_deployment_service_spec.rb
@@ -22,6 +22,7 @@ describe UpdateDeploymentService do
subject(:service) { described_class.new(deployment) }
before do
+ allow(Deployments::FinishedWorker).to receive(:perform_async)
job.success! # Create/Succeed deployment
end
diff --git a/spec/services/users/destroy_service_spec.rb b/spec/services/users/destroy_service_spec.rb
index 1c79af34538..4a5f4509a7b 100644
--- a/spec/services/users/destroy_service_spec.rb
+++ b/spec/services/users/destroy_service_spec.rb
@@ -210,6 +210,8 @@ describe Users::DestroyService do
describe "calls the before/after callbacks" do
it 'of project_members' do
+ expect_any_instance_of(ProjectMember).to receive(:run_callbacks).with(:find).once
+ expect_any_instance_of(ProjectMember).to receive(:run_callbacks).with(:initialize).once
expect_any_instance_of(ProjectMember).to receive(:run_callbacks).with(:destroy).once
service.execute(user)
@@ -219,6 +221,8 @@ describe Users::DestroyService do
group_member = create(:group_member)
group_member.group.group_members.create(user: user, access_level: 40)
+ expect_any_instance_of(GroupMember).to receive(:run_callbacks).with(:find).once
+ expect_any_instance_of(GroupMember).to receive(:run_callbacks).with(:initialize).once
expect_any_instance_of(GroupMember).to receive(:run_callbacks).with(:destroy).once
service.execute(user)
diff --git a/spec/services/users/migrate_to_ghost_user_service_spec.rb b/spec/services/users/migrate_to_ghost_user_service_spec.rb
index b808fa6d91a..40206775aed 100644
--- a/spec/services/users/migrate_to_ghost_user_service_spec.rb
+++ b/spec/services/users/migrate_to_ghost_user_service_spec.rb
@@ -80,7 +80,7 @@ describe Users::MigrateToGhostUserService do
context "when record migration fails with a rollback exception" do
before do
- expect_any_instance_of(MergeRequest::ActiveRecord_Associations_CollectionProxy)
+ expect_any_instance_of(ActiveRecord::Associations::CollectionProxy)
.to receive(:update_all).and_raise(ActiveRecord::Rollback)
end
diff --git a/spec/services/users/update_service_spec.rb b/spec/services/users/update_service_spec.rb
index e04c05418b0..9384287f98a 100644
--- a/spec/services/users/update_service_spec.rb
+++ b/spec/services/users/update_service_spec.rb
@@ -13,6 +13,15 @@ describe Users::UpdateService do
expect(user.name).to eq('New Name')
end
+ it 'updates time preferences' do
+ result = update_user(user, timezone: 'Europe/Warsaw', time_display_relative: true, time_format_in_24h: false)
+
+ expect(result).to eq(status: :success)
+ expect(user.reload.timezone).to eq('Europe/Warsaw')
+ expect(user.time_display_relative).to eq(true)
+ expect(user.time_format_in_24h).to eq(false)
+ end
+
it 'returns an error result when record cannot be updated' do
result = {}
expect do
diff --git a/spec/services/verify_pages_domain_service_spec.rb b/spec/services/verify_pages_domain_service_spec.rb
index e5c7b5bb9a7..f2b3b44d223 100644
--- a/spec/services/verify_pages_domain_service_spec.rb
+++ b/spec/services/verify_pages_domain_service_spec.rb
@@ -57,12 +57,12 @@ describe VerifyPagesDomainService do
expect(domain).not_to be_verified
end
- it 'disables domain and shedules it for removal' do
- Timecop.freeze do
- service.execute
- expect(domain).not_to be_enabled
- expect(domain.remove_at).to be_within(1.second).of(1.week.from_now)
- end
+ it 'disables domain and shedules it for removal in 1 week' do
+ service.execute
+
+ expect(domain).not_to be_enabled
+
+ expect(domain.remove_at).to be_like_time(7.days.from_now)
end
end
diff --git a/spec/services/web_hook_service_spec.rb b/spec/services/web_hook_service_spec.rb
index 75ba2479b63..37bafc0c002 100644
--- a/spec/services/web_hook_service_spec.rb
+++ b/spec/services/web_hook_service_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe WebHookService do
+ include StubRequests
+
let(:project) { create(:project) }
let(:project_hook) { create(:project_hook) }
let(:headers) do
@@ -67,11 +69,11 @@ describe WebHookService do
let(:project_hook) { create(:project_hook, url: 'https://demo:demo@example.org/') }
it 'uses the credentials' do
- WebMock.stub_request(:post, url)
+ stub_full_request(url, method: :post)
service_instance.execute
- expect(WebMock).to have_requested(:post, url).with(
+ expect(WebMock).to have_requested(:post, stubbed_hostname(url)).with(
headers: headers.merge('Authorization' => 'Basic ZGVtbzpkZW1v')
).once
end
@@ -82,11 +84,11 @@ describe WebHookService do
let(:project_hook) { create(:project_hook, url: 'https://demo@example.org/') }
it 'uses the credentials anyways' do
- WebMock.stub_request(:post, url)
+ stub_full_request(url, method: :post)
service_instance.execute
- expect(WebMock).to have_requested(:post, url).with(
+ expect(WebMock).to have_requested(:post, stubbed_hostname(url)).with(
headers: headers.merge('Authorization' => 'Basic ZGVtbzo=')
).once
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 60db3e1bc46..390a869d93f 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -44,6 +44,8 @@ Dir[Rails.root.join("spec/support/shared_contexts/*.rb")].each { |f| require f }
Dir[Rails.root.join("spec/support/shared_examples/*.rb")].each { |f| require f }
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
+quality_level = Quality::TestLevel.new
+
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.use_instantiated_fixtures = false
@@ -53,10 +55,12 @@ RSpec.configure do |config|
config.display_try_failure_messages = true
config.infer_spec_type_from_file_location!
+ config.full_backtrace = !!ENV['CI']
- config.define_derived_metadata(file_path: %r{/spec/}) do |metadata|
+ config.define_derived_metadata(file_path: %r{(ee)?/spec/.+_spec\.rb\z}) do |metadata|
location = metadata[:location]
+ metadata[:level] = quality_level.level_for(location)
metadata[:api] = true if location =~ %r{/spec/requests/api/}
# do not overwrite type if it's already set
@@ -83,6 +87,7 @@ RSpec.configure do |config|
config.include Devise::Test::IntegrationHelpers, type: :feature
config.include LoginHelpers, type: :feature
config.include SearchHelpers, type: :feature
+ config.include WaitHelpers, type: :feature
config.include EmailHelpers, :mailer, type: :mailer
config.include Warden::Test::Helpers, type: :request
config.include Gitlab::Routing, type: :routing
@@ -136,7 +141,7 @@ RSpec.configure do |config|
.and_return(false)
end
- config.before(:example, :quarantine) do
+ config.around(:example, :quarantine) do
# Skip tests in quarantine unless we explicitly focus on them.
skip('In quarantine') unless config.inclusion_filter[:quarantine]
end
diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb
index 18a7a392c12..56ac208a025 100644
--- a/spec/support/capybara.rb
+++ b/spec/support/capybara.rb
@@ -17,6 +17,8 @@ JS_CONSOLE_FILTER = Regexp.union([
"Download the Vue Devtools extension"
])
+CAPYBARA_WINDOW_SIZE = [1366, 768].freeze
+
Capybara.register_driver :chrome do |app|
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
# This enables access to logs with `page.driver.manage.get_log(:browser)`
@@ -29,7 +31,7 @@ Capybara.register_driver :chrome do |app|
)
options = Selenium::WebDriver::Chrome::Options.new
- options.add_argument("window-size=1240,1400")
+ options.add_argument("window-size=#{CAPYBARA_WINDOW_SIZE.join(',')}")
# Chrome won't work properly in a Docker container in sandbox mode
options.add_argument("no-sandbox")
@@ -40,6 +42,9 @@ Capybara.register_driver :chrome do |app|
# Disable /dev/shm use in CI. See https://gitlab.com/gitlab-org/gitlab-ee/issues/4252
options.add_argument("disable-dev-shm-usage") if ENV['CI'] || ENV['CI_SERVER']
+ # Explicitly set user-data-dir to prevent crashes. See https://gitlab.com/gitlab-org/gitlab-ce/issues/58882#note_179811508
+ options.add_argument("user-data-dir=/tmp/chrome") if ENV['CI'] || ENV['CI_SERVER']
+
Capybara::Selenium::Driver.new(
app,
browser: :chrome,
@@ -48,9 +53,11 @@ Capybara.register_driver :chrome do |app|
)
end
+Capybara.server = :webrick
Capybara.javascript_driver = :chrome
Capybara.default_max_wait_time = timeout
Capybara.ignore_hidden_elements = true
+Capybara.default_normalize_ws = true
# Keep only the screenshots generated from the last failing test suite
Capybara::Screenshot.prune_strategy = :keep_last_run
@@ -78,8 +85,11 @@ RSpec.configure do |config|
protocol: 'http')
# reset window size between tests
- unless session.current_window.size == [1240, 1400]
- session.current_window.resize_to(1240, 1400) rescue nil
+ unless session.current_window.size == CAPYBARA_WINDOW_SIZE
+ begin
+ session.current_window.resize_to(*CAPYBARA_WINDOW_SIZE)
+ rescue # ?
+ end
end
end
diff --git a/spec/support/controllers/ldap_omniauth_callbacks_controller_shared_context.rb b/spec/support/controllers/ldap_omniauth_callbacks_controller_shared_context.rb
index 72912ffb89d..a0c77eecb61 100644
--- a/spec/support/controllers/ldap_omniauth_callbacks_controller_shared_context.rb
+++ b/spec/support/controllers/ldap_omniauth_callbacks_controller_shared_context.rb
@@ -25,9 +25,13 @@ shared_context 'Ldap::OmniauthCallbacksController' do
described_class.define_providers!
Rails.application.reload_routes!
- mock_auth_hash(provider.to_s, uid, user.email)
+ @original_env_config_omniauth_auth = mock_auth_hash(provider.to_s, uid, user.email)
stub_omniauth_provider(provider, context: request)
allow(Gitlab::Auth::LDAP::Access).to receive(:allowed?).and_return(valid_login?)
end
+
+ after do
+ Rails.application.env_config['omniauth.auth'] = @original_env_config_omniauth_auth
+ end
end
diff --git a/spec/support/features/discussion_comments_shared_example.rb b/spec/support/features/discussion_comments_shared_example.rb
index 542f533d590..0f8af2c5d6d 100644
--- a/spec/support/features/discussion_comments_shared_example.rb
+++ b/spec/support/features/discussion_comments_shared_example.rb
@@ -84,7 +84,7 @@ shared_examples 'discussion comments' do |resource_name|
#
# if dropdown menu is not toggled (and also not present),
# it's "issue-type" dropdown
- if first(menu_selector).nil?
+ if first(menu_selector, minimum: 0).nil?
expect(find(dropdown_selector)).to have_content 'Comment'
find(toggle_selector).click
diff --git a/spec/support/features/reportable_note_shared_examples.rb b/spec/support/features/reportable_note_shared_examples.rb
index 89dfbf931d2..5d5a0a7b5d2 100644
--- a/spec/support/features/reportable_note_shared_examples.rb
+++ b/spec/support/features/reportable_note_shared_examples.rb
@@ -20,7 +20,7 @@ shared_examples 'reportable note' do |type|
dropdown = comment.find(more_actions_selector)
open_dropdown(dropdown)
- expect(dropdown).to have_link('Report abuse to GitLab', href: abuse_report_path)
+ expect(dropdown).to have_link('Report abuse to admin', href: abuse_report_path)
if type == 'issue' || type == 'merge_request'
expect(dropdown).to have_button('Delete comment')
@@ -33,7 +33,7 @@ shared_examples 'reportable note' do |type|
dropdown = comment.find(more_actions_selector)
open_dropdown(dropdown)
- dropdown.click_link('Report abuse to GitLab')
+ dropdown.click_link('Report abuse to admin')
expect(find('#user_name')['value']).to match(note.author.username)
expect(find('#abuse_report_message')['value']).to match(noteable_note_url(note))
diff --git a/spec/support/features/variable_list_shared_examples.rb b/spec/support/features/variable_list_shared_examples.rb
index 693b796fbdc..01531864c1f 100644
--- a/spec/support/features/variable_list_shared_examples.rb
+++ b/spec/support/features/variable_list_shared_examples.rb
@@ -17,7 +17,7 @@ shared_examples 'variable list' do
visit page_path
# We check the first row because it re-sorts to alphabetical order on refresh
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
expect(find('.js-ci-variable-input-key').value).to eq('key')
expect(find('.js-ci-variable-input-value', visible: false).value).to eq('key_value')
end
@@ -38,19 +38,19 @@ shared_examples 'variable list' do
visit page_path
# We check the first row because it re-sorts to alphabetical order on refresh
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
expect(find('.js-ci-variable-input-key').value).to eq('key')
expect(find('.js-ci-variable-input-value', visible: false).value).to eq('key_value')
expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('true')
end
end
- it 'defaults to masked' do
+ it 'defaults to unmasked' do
page.within('.js-ci-variable-list-section .js-row:last-child') do
find('.js-ci-variable-input-key').set('key')
find('.js-ci-variable-input-value').set('key_value')
- expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('true')
+ expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('false')
end
click_button('Save variables')
@@ -59,10 +59,10 @@ shared_examples 'variable list' do
visit page_path
# We check the first row because it re-sorts to alphabetical order on refresh
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
expect(find('.js-ci-variable-input-key').value).to eq('key')
expect(find('.js-ci-variable-input-value', visible: false).value).to eq('key_value')
- expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('true')
+ expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('false')
end
end
@@ -116,19 +116,19 @@ shared_examples 'variable list' do
page.within('.js-ci-variable-list-section') do
expect(first('.js-ci-variable-input-key').value).to eq(variable.key)
expect(first('.js-ci-variable-input-value', visible: false).value).to eq(variable.value)
- expect(page).to have_content('*' * 20)
+ expect(page).to have_content('*' * 17)
click_button('Reveal value')
expect(first('.js-ci-variable-input-key').value).to eq(variable.key)
expect(first('.js-ci-variable-input-value').value).to eq(variable.value)
- expect(page).not_to have_content('*' * 20)
+ expect(page).not_to have_content('*' * 17)
click_button('Hide value')
expect(first('.js-ci-variable-input-key').value).to eq(variable.key)
expect(first('.js-ci-variable-input-value', visible: false).value).to eq(variable.value)
- expect(page).to have_content('*' * 20)
+ expect(page).to have_content('*' * 17)
end
end
@@ -149,7 +149,7 @@ shared_examples 'variable list' do
page.within('.js-ci-variable-list-section') do
click_button('Reveal value')
- page.within('.js-row:nth-child(1)') do
+ page.within('.js-row:nth-child(2)') do
find('.js-ci-variable-input-key').set('new_key')
find('.js-ci-variable-input-value').set('new_value')
end
@@ -159,7 +159,7 @@ shared_examples 'variable list' do
visit page_path
- page.within('.js-row:nth-child(1)') do
+ page.within('.js-row:nth-child(2)') do
expect(find('.js-ci-variable-input-key').value).to eq('new_key')
expect(find('.js-ci-variable-input-value', visible: false).value).to eq('new_value')
end
@@ -181,7 +181,7 @@ shared_examples 'variable list' do
visit page_path
# We check the first row because it re-sorts to alphabetical order on refresh
- page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(3)') do
find('.ci-variable-protected-item .js-project-feature-toggle').click
expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('true')
@@ -193,7 +193,7 @@ shared_examples 'variable list' do
visit page_path
# We check the first row because it re-sorts to alphabetical order on refresh
- page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(3)') do
expect(find('.js-ci-variable-input-key').value).to eq('unprotected_key')
expect(find('.js-ci-variable-input-value', visible: false).value).to eq('unprotected_value')
expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('true')
@@ -215,7 +215,7 @@ shared_examples 'variable list' do
visit page_path
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
find('.ci-variable-protected-item .js-project-feature-toggle').click
expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('false')
@@ -226,7 +226,7 @@ shared_examples 'variable list' do
visit page_path
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
expect(find('.js-ci-variable-input-key').value).to eq('protected_key')
expect(find('.js-ci-variable-input-value', visible: false).value).to eq('protected_value')
expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('false')
@@ -234,12 +234,14 @@ shared_examples 'variable list' do
end
it 'edits variable to be unmasked' do
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
- expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('true')
+ page.within('.js-ci-variable-list-section .js-row:last-child') do
+ find('.js-ci-variable-input-key').set('unmasked_key')
+ find('.js-ci-variable-input-value').set('unmasked_value')
+ expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('false')
find('.ci-variable-masked-item .js-project-feature-toggle').click
- expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('false')
+ expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('true')
end
click_button('Save variables')
@@ -247,13 +249,7 @@ shared_examples 'variable list' do
visit page_path
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
- expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('false')
- end
- end
-
- it 'edits variable to be masked' do
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('true')
find('.ci-variable-masked-item .js-project-feature-toggle').click
@@ -266,7 +262,15 @@ shared_examples 'variable list' do
visit page_path
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
+ expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('false')
+ end
+ end
+
+ it 'edits variable to be masked' do
+ page.within('.js-ci-variable-list-section .js-row:last-child') do
+ find('.js-ci-variable-input-key').set('masked_key')
+ find('.js-ci-variable-input-value').set('masked_value')
expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('false')
find('.ci-variable-masked-item .js-project-feature-toggle').click
@@ -279,7 +283,7 @@ shared_examples 'variable list' do
visit page_path
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('true')
end
end
@@ -302,7 +306,7 @@ shared_examples 'variable list' do
expect(page).to have_selector('.js-row', count: 4)
# Remove the `akey` variable
- page.within('.js-row:nth-child(2)') do
+ page.within('.js-row:nth-child(3)') do
first('.js-row-remove-button').click
end
@@ -348,10 +352,11 @@ shared_examples 'variable list' do
end
end
- it 'shows validation error box about empty values' do
+ it 'shows validation error box about masking empty values' do
page.within('.js-ci-variable-list-section .js-row:last-child') do
find('.js-ci-variable-input-key').set('empty_value')
find('.js-ci-variable-input-value').set('')
+ find('.ci-variable-masked-item .js-project-feature-toggle').click
end
click_button('Save variables')
@@ -367,6 +372,7 @@ shared_examples 'variable list' do
page.within('.js-ci-variable-list-section .js-row:last-child') do
find('.js-ci-variable-input-key').set('unmaskable_value')
find('.js-ci-variable-input-value').set('???')
+ find('.ci-variable-masked-item .js-project-feature-toggle').click
end
click_button('Save variables')
diff --git a/spec/support/helpers/email_helpers.rb b/spec/support/helpers/email_helpers.rb
index ad6e1064499..ed049daba80 100644
--- a/spec/support/helpers/email_helpers.rb
+++ b/spec/support/helpers/email_helpers.rb
@@ -16,7 +16,9 @@ module EmailHelpers
end
def should_email(user, times: 1, recipients: email_recipients)
- expect(sent_to_user(user, recipients: recipients)).to eq(times)
+ amount = sent_to_user(user, recipients: recipients)
+ failed_message = lambda { "User #{user.username} (#{user.id}): email test failed (expected #{times}, got #{amount})" }
+ expect(amount).to eq(times), failed_message
end
def should_not_email(user, recipients: email_recipients)
diff --git a/spec/support/helpers/features/notes_helpers.rb b/spec/support/helpers/features/notes_helpers.rb
index 89517fde6e2..8a139fafac2 100644
--- a/spec/support/helpers/features/notes_helpers.rb
+++ b/spec/support/helpers/features/notes_helpers.rb
@@ -23,8 +23,16 @@ module Spec
def preview_note(text)
page.within('.js-main-target-form') do
- fill_in('note[note]', with: text)
+ filled_text = fill_in('note[note]', with: text)
+
+ # Wait for quick action prompt to load and then dismiss it with ESC
+ # because it may block the Preview button
+ wait_for_requests
+ filled_text.send_keys(:escape)
+
click_on('Preview')
+
+ yield if block_given?
end
end
end
diff --git a/spec/support/helpers/filtered_search_helpers.rb b/spec/support/helpers/filtered_search_helpers.rb
index 03057a102c5..34ef185ea27 100644
--- a/spec/support/helpers/filtered_search_helpers.rb
+++ b/spec/support/helpers/filtered_search_helpers.rb
@@ -78,20 +78,17 @@ module FilteredSearchHelpers
# .tokens-container to make sure the correct names and values are rendered
def expect_tokens(tokens)
page.within '.filtered-search-box .tokens-container' do
- page.all(:css, '.tokens-container li .selectable').each_with_index do |el, index|
- token_name = tokens[index][:name]
- token_value = tokens[index][:value]
- token_emoji = tokens[index][:emoji_name]
+ token_elements = page.all(:css, 'li.filtered-search-token')
- expect(el.find('.name')).to have_content(token_name)
+ tokens.each_with_index do |token, index|
+ el = token_elements[index]
- if token_value
- expect(el.find('.value')).to have_content(token_value)
- end
+ expect(el.find('.name')).to have_content(token[:name])
+ expect(el.find('.value')).to have_content(token[:value]) if token[:value].present?
# gl-emoji content is blank when the emoji unicode is not supported
- if token_emoji
- selector = %(gl-emoji[data-name="#{token_emoji}"])
+ if token[:emoji_name].present?
+ selector = %(gl-emoji[data-name="#{token[:emoji_name]}"])
expect(el.find('.value')).to have_css(selector)
end
end
diff --git a/spec/support/helpers/git_helpers.rb b/spec/support/helpers/git_helpers.rb
index 99a7c39852e..99c5871ba54 100644
--- a/spec/support/helpers/git_helpers.rb
+++ b/spec/support/helpers/git_helpers.rb
@@ -6,12 +6,4 @@ module GitHelpers
Rugged::Repository.new(path)
end
-
- def project_hook_exists?(project)
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project_path = project.repository.raw_repository.path
-
- File.exist?(File.join(project_path, 'hooks', 'post-receive'))
- end
- end
end
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index 2f4e6e4c934..e95c7f2a6d6 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -61,7 +61,14 @@ module GraphqlHelpers
def variables_for_mutation(name, input)
graphql_input = input.map { |name, value| [GraphqlHelpers.fieldnamerize(name), value] }.to_h
- { input_variable_name_for_mutation(name) => graphql_input }.to_json
+ result = { input_variable_name_for_mutation(name) => graphql_input }
+
+ # Avoid trying to serialize multipart data into JSON
+ if graphql_input.values.none? { |value| io_value?(value) }
+ result.to_json
+ else
+ result
+ end
end
def input_variable_name_for_mutation(mutation_name)
@@ -95,6 +102,7 @@ module GraphqlHelpers
def all_graphql_fields_for(class_name, parent_types = Set.new)
allow_unlimited_graphql_complexity
+ allow_unlimited_graphql_depth
type = GitlabSchema.types[class_name.to_s]
return "" unless type
@@ -126,6 +134,10 @@ module GraphqlHelpers
end.join(", ")
end
+ def post_multiplex(queries, current_user: nil, headers: {})
+ post api('/', current_user, version: 'graphql'), params: { _json: queries }, headers: headers
+ end
+
def post_graphql(query, current_user: nil, variables: nil, headers: {})
post api('/', current_user, version: 'graphql'), params: { query: query, variables: variables }, headers: headers
end
@@ -139,7 +151,14 @@ module GraphqlHelpers
end
def graphql_errors
- json_response['errors']
+ case json_response
+ when Hash # regular query
+ json_response['errors']
+ when Array # multiplexed queries
+ json_response.map { |response| response['errors'] }
+ else
+ raise "Unkown GraphQL response type #{json_response.class}"
+ end
end
def graphql_mutation_response(mutation_name)
@@ -162,6 +181,10 @@ module GraphqlHelpers
field.arguments.values.any? { |argument| argument.type.non_null? }
end
+ def io_value?(value)
+ Array.wrap(value).any? { |v| v.respond_to?(:to_io) }
+ end
+
def field_type(field)
field_type = field.type
@@ -179,4 +202,13 @@ module GraphqlHelpers
allow_any_instance_of(GitlabSchema).to receive(:max_complexity).and_return nil
allow(GitlabSchema).to receive(:max_query_complexity).with(any_args).and_return nil
end
+
+ def allow_unlimited_graphql_depth
+ allow_any_instance_of(GitlabSchema).to receive(:max_depth).and_return nil
+ allow(GitlabSchema).to receive(:max_query_depth).with(any_args).and_return nil
+ end
end
+
+# This warms our schema, doing this as part of loading the helpers to avoid
+# duplicate loading error when Rails tries autoload the types.
+GitlabSchema.graphql_definition
diff --git a/spec/support/helpers/javascript_fixtures_helpers.rb b/spec/support/helpers/javascript_fixtures_helpers.rb
index 9cae8f934db..cdd7724cc13 100644
--- a/spec/support/helpers/javascript_fixtures_helpers.rb
+++ b/spec/support/helpers/javascript_fixtures_helpers.rb
@@ -11,11 +11,15 @@ module JavaScriptFixturesHelpers
base.around do |example|
# pick an arbitrary date from the past, so tests are not time dependent
Timecop.freeze(Time.utc(2015, 7, 3, 10)) { example.run }
+
+ raise NoMethodError.new('You need to set `response` for the fixture generator! This will automatically happen with `type: :controller` or `type: :request`.', 'response') unless respond_to?(:response)
+
+ store_frontend_fixture(response, example.description)
end
end
def fixture_root_path
- 'spec/javascripts/fixtures'
+ (Gitlab.ee? ? 'ee/' : '') + 'spec/javascripts/fixtures'
end
# Public: Removes all fixture files from given directory
@@ -29,7 +33,13 @@ module JavaScriptFixturesHelpers
end
end
- # Public: Store a response object as fixture file
+ def remove_repository(project)
+ Gitlab::Shell.new.remove_repository(project.repository_storage, project.disk_path)
+ end
+
+ private
+
+ # Private: Store a response object as fixture file
#
# response - string or response object to store
# fixture_file_name - file name to store the fixture in (relative to .fixture_root_path)
@@ -42,12 +52,6 @@ module JavaScriptFixturesHelpers
File.write(full_fixture_path, fixture)
end
- def remove_repository(project)
- Gitlab::Shell.new.remove_repository(project.repository_storage, project.disk_path)
- end
-
- private
-
# Private: Prepare a response object for use as a frontend fixture
#
# response - response object to prepare
diff --git a/spec/support/helpers/kubernetes_helpers.rb b/spec/support/helpers/kubernetes_helpers.rb
index ac52acb6570..011c4df0fe5 100644
--- a/spec/support/helpers/kubernetes_helpers.rb
+++ b/spec/support/helpers/kubernetes_helpers.rb
@@ -17,50 +17,78 @@ module KubernetesHelpers
kube_response(kube_deployments_body)
end
- def stub_kubeclient_discover(api_url)
+ def stub_kubeclient_discover_base(api_url)
WebMock.stub_request(:get, api_url + '/api/v1').to_return(kube_response(kube_v1_discovery_body))
- WebMock.stub_request(:get, api_url + '/apis/extensions/v1beta1').to_return(kube_response(kube_v1beta1_discovery_body))
- WebMock.stub_request(:get, api_url + '/apis/rbac.authorization.k8s.io/v1').to_return(kube_response(kube_v1_rbac_authorization_discovery_body))
- WebMock.stub_request(:get, api_url + '/apis/serving.knative.dev/v1alpha1').to_return(kube_response(kube_v1alpha1_serving_knative_discovery_body))
+ WebMock
+ .stub_request(:get, api_url + '/apis/extensions/v1beta1')
+ .to_return(kube_response(kube_v1beta1_discovery_body))
+ WebMock
+ .stub_request(:get, api_url + '/apis/rbac.authorization.k8s.io/v1')
+ .to_return(kube_response(kube_v1_rbac_authorization_discovery_body))
+ end
+
+ def stub_kubeclient_discover(api_url)
+ stub_kubeclient_discover_base(api_url)
+
+ WebMock
+ .stub_request(:get, api_url + '/apis/serving.knative.dev/v1alpha1')
+ .to_return(kube_response(kube_v1alpha1_serving_knative_discovery_body))
+ end
+
+ def stub_kubeclient_discover_knative_not_found(api_url)
+ stub_kubeclient_discover_base(api_url)
+
+ WebMock
+ .stub_request(:get, api_url + '/apis/serving.knative.dev/v1alpha1')
+ .to_return(status: [404, "Resource Not Found"])
end
- def stub_kubeclient_service_pods(response = nil)
+ def stub_kubeclient_service_pods(response = nil, options = {})
stub_kubeclient_discover(service.api_url)
- pods_url = service.api_url + "/api/v1/pods"
+
+ namespace_path = options[:namespace].present? ? "namespaces/#{options[:namespace]}/" : ""
+
+ pods_url = service.api_url + "/api/v1/#{namespace_path}pods"
WebMock.stub_request(:get, pods_url).to_return(response || kube_pods_response)
end
- def stub_kubeclient_pods(response = nil)
+ def stub_kubeclient_pods(namespace, status: nil)
stub_kubeclient_discover(service.api_url)
- pods_url = service.api_url + "/api/v1/namespaces/#{service.actual_namespace}/pods"
+ pods_url = service.api_url + "/api/v1/namespaces/#{namespace}/pods"
+ response = { status: status } if status
WebMock.stub_request(:get, pods_url).to_return(response || kube_pods_response)
end
- def stub_kubeclient_logs(pod_name, response = nil)
+ def stub_kubeclient_logs(pod_name, namespace, status: nil)
stub_kubeclient_discover(service.api_url)
- logs_url = service.api_url + "/api/v1/namespaces/#{service.actual_namespace}/pods/#{pod_name}/log?tailLines=#{Clusters::Platforms::Kubernetes::LOGS_LIMIT}"
+ logs_url = service.api_url + "/api/v1/namespaces/#{namespace}/pods/#{pod_name}/log?tailLines=#{Clusters::Platforms::Kubernetes::LOGS_LIMIT}"
+ response = { status: status } if status
WebMock.stub_request(:get, logs_url).to_return(response || kube_logs_response)
end
- def stub_kubeclient_deployments(response = nil)
+ def stub_kubeclient_deployments(namespace, status: nil)
stub_kubeclient_discover(service.api_url)
- deployments_url = service.api_url + "/apis/extensions/v1beta1/namespaces/#{service.actual_namespace}/deployments"
+ deployments_url = service.api_url + "/apis/extensions/v1beta1/namespaces/#{namespace}/deployments"
+ response = { status: status } if status
WebMock.stub_request(:get, deployments_url).to_return(response || kube_deployments_response)
end
- def stub_kubeclient_knative_services(**options)
+ def stub_kubeclient_knative_services(options = {})
+ namespace_path = options[:namespace].present? ? "namespaces/#{options[:namespace]}/" : ""
+
options[:name] ||= "kubetest"
- options[:namespace] ||= "default"
options[:domain] ||= "example.com"
+ options[:response] ||= kube_response(kube_knative_services_body(options))
stub_kubeclient_discover(service.api_url)
- knative_url = service.api_url + "/apis/serving.knative.dev/v1alpha1/services"
- WebMock.stub_request(:get, knative_url).to_return(kube_response(kube_knative_services_body(options)))
+ knative_url = service.api_url + "/apis/serving.knative.dev/v1alpha1/#{namespace_path}services"
+
+ WebMock.stub_request(:get, knative_url).to_return(options[:response])
end
def stub_kubeclient_get_secret(api_url, **options)
@@ -250,10 +278,11 @@ module KubernetesHelpers
# This is a partial response, it will have many more elements in reality but
# these are the ones we care about at the moment
- def kube_pod(name: "kube-pod", environment_slug: "production", project_slug: "project-path-slug", status: "Running", track: nil)
+ def kube_pod(name: "kube-pod", environment_slug: "production", namespace: "project-namespace", project_slug: "project-path-slug", status: "Running", track: nil)
{
"metadata" => {
"name" => name,
+ "namespace" => namespace,
"generate_name" => "generated-name-with-suffix",
"creationTimestamp" => "2016-11-25T19:55:19Z",
"annotations" => {
@@ -369,12 +398,13 @@ module KubernetesHelpers
def kube_terminals(service, pod)
pod_name = pod['metadata']['name']
+ pod_namespace = pod['metadata']['namespace']
containers = pod['spec']['containers']
containers.map do |container|
terminal = {
selectors: { pod: pod_name, container: container['name'] },
- url: container_exec_url(service.api_url, service.actual_namespace, pod_name, container['name']),
+ url: container_exec_url(service.api_url, pod_namespace, pod_name, container['name']),
subprotocols: ['channel.k8s.io'],
headers: { 'Authorization' => ["Bearer #{service.token}"] },
created_at: DateTime.parse(pod['metadata']['creationTimestamp']),
diff --git a/spec/support/helpers/lets_encrypt_helpers.rb b/spec/support/helpers/lets_encrypt_helpers.rb
new file mode 100644
index 00000000000..2857416ad95
--- /dev/null
+++ b/spec/support/helpers/lets_encrypt_helpers.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+module LetsEncryptHelpers
+ ACME_ORDER_METHODS = {
+ url: 'https://example.com/',
+ status: 'valid',
+ expires: 2.days.from_now
+ }.freeze
+
+ ACME_CHALLENGE_METHODS = {
+ status: 'pending',
+ token: 'tokenvalue',
+ file_content: 'hereisfilecontent',
+ request_validation: true
+ }.freeze
+
+ def stub_lets_encrypt_settings
+ stub_application_setting(
+ lets_encrypt_notification_email: 'myemail@test.example.com',
+ lets_encrypt_terms_of_service_accepted: true
+ )
+ end
+
+ def stub_lets_encrypt_client
+ client = instance_double('Acme::Client')
+
+ allow(client).to receive(:new_account)
+ allow(client).to receive(:terms_of_service).and_return(
+ "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf"
+ )
+
+ allow(Acme::Client).to receive(:new).with(
+ private_key: kind_of(OpenSSL::PKey::RSA),
+ directory: ::Gitlab::LetsEncrypt::Client::STAGING_DIRECTORY_URL
+ ).and_return(client)
+
+ client
+ end
+
+ def acme_challenge_double
+ challenge = instance_double('Acme::Client::Resources::Challenges::HTTP01')
+ allow(challenge).to receive_messages(ACME_CHALLENGE_METHODS)
+ challenge
+ end
+
+ def acme_authorization_double
+ authorization = instance_double('Acme::Client::Resources::Authorization')
+ allow(authorization).to receive(:http).and_return(acme_challenge_double)
+ authorization
+ end
+
+ def acme_order_double(attributes = {})
+ acme_order = instance_double('Acme::Client::Resources::Order')
+ allow(acme_order).to receive_messages(ACME_ORDER_METHODS.merge(attributes))
+ allow(acme_order).to receive(:authorizations).and_return([acme_authorization_double])
+ allow(acme_order).to receive(:finalize)
+ acme_order
+ end
+end
diff --git a/spec/support/helpers/login_helpers.rb b/spec/support/helpers/login_helpers.rb
index 4a0cf62a661..0bb2d2510c2 100644
--- a/spec/support/helpers/login_helpers.rb
+++ b/spec/support/helpers/login_helpers.rb
@@ -118,7 +118,10 @@ module LoginHelpers
response_object: response_object
}
})
+ original_env_config_omniauth_auth = Rails.application.env_config['omniauth.auth']
Rails.application.env_config['omniauth.auth'] = OmniAuth.config.mock_auth[provider.to_sym]
+
+ original_env_config_omniauth_auth
end
def saml_xml(raw_saml_response)
diff --git a/spec/support/helpers/metrics_dashboard_helpers.rb b/spec/support/helpers/metrics_dashboard_helpers.rb
new file mode 100644
index 00000000000..1f36b0e217c
--- /dev/null
+++ b/spec/support/helpers/metrics_dashboard_helpers.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module MetricsDashboardHelpers
+ def project_with_dashboard(dashboard_path, dashboard_yml = nil)
+ dashboard_yml ||= fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml')
+
+ create(:project, :custom_repo, files: { dashboard_path => dashboard_yml })
+ end
+
+ def delete_project_dashboard(project, user, dashboard_path)
+ project.repository.delete_file(
+ user,
+ dashboard_path,
+ branch_name: 'master',
+ message: 'Delete dashboard'
+ )
+
+ project.repository.refresh_method_caches([:metrics_dashboard])
+ end
+
+ shared_examples_for 'misconfigured dashboard service response' do |status_code|
+ it 'returns an appropriate message and status code' do
+ result = service_call
+
+ expect(result.keys).to contain_exactly(:message, :http_status, :status)
+ expect(result[:status]).to eq(:error)
+ expect(result[:http_status]).to eq(status_code)
+ end
+ end
+
+ shared_examples_for 'valid dashboard service response' do
+ let(:dashboard_schema) { JSON.parse(fixture_file('lib/gitlab/metrics/dashboard/schemas/dashboard.json')) }
+
+ it 'returns a json representation of the dashboard' do
+ result = service_call
+
+ expect(result.keys).to contain_exactly(:dashboard, :status)
+ expect(result[:status]).to eq(:success)
+
+ expect(JSON::Validator.fully_validate(dashboard_schema, result[:dashboard])).to be_empty
+ end
+ end
+end
diff --git a/spec/support/helpers/mobile_helpers.rb b/spec/support/helpers/mobile_helpers.rb
index 9dc1f1de436..4230d315d9b 100644
--- a/spec/support/helpers/mobile_helpers.rb
+++ b/spec/support/helpers/mobile_helpers.rb
@@ -8,7 +8,7 @@ module MobileHelpers
end
def restore_window_size
- resize_window(1366, 768)
+ resize_window(*CAPYBARA_WINDOW_SIZE)
end
def resize_window(width, height)
diff --git a/spec/support/helpers/notification_helpers.rb b/spec/support/helpers/notification_helpers.rb
index 8d84510fb73..44c2051598c 100644
--- a/spec/support/helpers/notification_helpers.rb
+++ b/spec/support/helpers/notification_helpers.rb
@@ -17,11 +17,15 @@ module NotificationHelpers
def create_user_with_notification(level, username, resource = project)
user = create(:user, username: username)
+ create_notification_setting(user, resource, level)
+
+ user
+ end
+
+ def create_notification_setting(user, resource, level)
setting = user.notification_settings_for(resource)
setting.level = level
setting.save
-
- user
end
# Create custom notifications
diff --git a/spec/support/helpers/project_forks_helper.rb b/spec/support/helpers/project_forks_helper.rb
index 9a86560da2a..bcb11a09b36 100644
--- a/spec/support/helpers/project_forks_helper.rb
+++ b/spec/support/helpers/project_forks_helper.rb
@@ -1,5 +1,11 @@
module ProjectForksHelper
def fork_project(project, user = nil, params = {})
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ fork_project_direct(project, user, params)
+ end
+ end
+
+ def fork_project_direct(project, user = nil, params = {})
# Load the `fork_network` for the project to fork as there might be one that
# wasn't loaded yet.
project.reload unless project.fork_network
@@ -44,11 +50,16 @@ module ProjectForksHelper
end
def fork_project_with_submodules(project, user = nil, params = {})
- forked_project = fork_project(project, user, params)
- TestEnv.copy_repo(forked_project,
- bare_repo: TestEnv.forked_repo_path_bare,
- refs: TestEnv::FORKED_BRANCH_SHA)
- forked_project.repository.after_import
- forked_project
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ forked_project = fork_project_direct(project, user, params)
+ TestEnv.copy_repo(
+ forked_project,
+ bare_repo: TestEnv.forked_repo_path_bare,
+ refs: TestEnv::FORKED_BRANCH_SHA
+ )
+ forked_project.repository.after_import
+
+ forked_project
+ end
end
end
diff --git a/spec/support/helpers/query_recorder.rb b/spec/support/helpers/query_recorder.rb
index 7ce63375d34..c4ae62b25e4 100644
--- a/spec/support/helpers/query_recorder.rb
+++ b/spec/support/helpers/query_recorder.rb
@@ -17,7 +17,7 @@ module ActiveRecord
def callback(name, start, finish, message_id, values)
show_backtrace(values) if ENV['QUERY_RECORDER_DEBUG']
- if values[:name]&.include?("CACHE") && skip_cached
+ if values[:cached] && skip_cached
@cached << values[:sql]
elsif !values[:name]&.include?("SCHEMA")
@log << values[:sql]
diff --git a/spec/support/helpers/repo_helpers.rb b/spec/support/helpers/repo_helpers.rb
index 4af90f4af79..44d95a029af 100644
--- a/spec/support/helpers/repo_helpers.rb
+++ b/spec/support/helpers/repo_helpers.rb
@@ -11,6 +11,8 @@ module RepoHelpers
# blob.path # => 'files/js/commit.js.coffee'
# blob.data # => 'class Commit...'
#
+ # Build the options hash that's passed to Rugged::Commit#create
+
def sample_blob
OpenStruct.new(
oid: '5f53439ca4b009096571d3c8bc3d09d30e7431b3',
@@ -129,4 +131,80 @@ eos
file_content: content
).execute
end
+
+ def commit_options(repo, index, target, ref, message)
+ options = {}
+ options[:tree] = index.write_tree(repo)
+ options[:author] = {
+ email: "test@example.com",
+ name: "Test Author",
+ time: Time.gm(2014, "mar", 3, 20, 15, 1)
+ }
+ options[:committer] = {
+ email: "test@example.com",
+ name: "Test Author",
+ time: Time.gm(2014, "mar", 3, 20, 15, 1)
+ }
+ options[:message] ||= message
+ options[:parents] = repo.empty? ? [] : [target].compact
+ options[:update_ref] = ref
+
+ options
+ end
+
+ # Writes a new commit to the repo and returns a Rugged::Commit. Replaces the
+ # contents of CHANGELOG with a single new line of text.
+ def new_commit_edit_old_file(repo)
+ oid = repo.write("I replaced the changelog with this text", :blob)
+ index = repo.index
+ index.read_tree(repo.head.target.tree)
+ index.add(path: "CHANGELOG", oid: oid, mode: 0100644)
+
+ options = commit_options(
+ repo,
+ index,
+ repo.head.target,
+ "HEAD",
+ "Edit CHANGELOG in its original location"
+ )
+
+ sha = Rugged::Commit.create(repo, options)
+ repo.lookup(sha)
+ end
+
+ # Writes a new commit to the repo and returns a Rugged::Commit. Replaces the
+ # contents of the specified file_path with new text.
+ def new_commit_edit_new_file(repo, file_path, commit_message, text, branch = repo.head)
+ oid = repo.write(text, :blob)
+ index = repo.index
+ index.read_tree(branch.target.tree)
+ index.add(path: file_path, oid: oid, mode: 0100644)
+ options = commit_options(repo, index, branch.target, branch.canonical_name, commit_message)
+ sha = Rugged::Commit.create(repo, options)
+ repo.lookup(sha)
+ end
+
+ # Writes a new commit to the repo and returns a Rugged::Commit. Replaces the
+ # contents of encoding/CHANGELOG with new text.
+ def new_commit_edit_new_file_on_branch(repo, file_path, branch_name, commit_message, text)
+ branch = repo.branches[branch_name]
+ new_commit_edit_new_file(repo, file_path, commit_message, text, branch)
+ end
+
+ # Writes a new commit to the repo and returns a Rugged::Commit. Moves the
+ # CHANGELOG file to the encoding/ directory.
+ def new_commit_move_file(repo)
+ blob_oid = repo.head.target.tree.detect { |i| i[:name] == "CHANGELOG" }[:oid]
+ file_content = repo.lookup(blob_oid).content
+ oid = repo.write(file_content, :blob)
+ index = repo.index
+ index.read_tree(repo.head.target.tree)
+ index.add(path: "encoding/CHANGELOG", oid: oid, mode: 0100644)
+ index.remove("CHANGELOG")
+
+ options = commit_options(repo, index, repo.head.target, "HEAD", "Move CHANGELOG to encoding/")
+
+ sha = Rugged::Commit.create(repo, options)
+ repo.lookup(sha)
+ end
end
diff --git a/spec/support/helpers/select2_helper.rb b/spec/support/helpers/select2_helper.rb
index f4f0415985c..87672c8896d 100644
--- a/spec/support/helpers/select2_helper.rb
+++ b/spec/support/helpers/select2_helper.rb
@@ -35,6 +35,10 @@ module Select2Helper
execute_script("$('#{selector}').select2('open');")
end
+ def close_select2(selector)
+ execute_script("$('#{selector}').select2('close');")
+ end
+
def scroll_select2_to_bottom(selector)
evaluate_script "$('#{selector}').scrollTop($('#{selector}')[0].scrollHeight); $('#{selector}');"
end
diff --git a/spec/support/helpers/stub_configuration.rb b/spec/support/helpers/stub_configuration.rb
index 3e507fb133e..f6c613ad5aa 100644
--- a/spec/support/helpers/stub_configuration.rb
+++ b/spec/support/helpers/stub_configuration.rb
@@ -2,7 +2,8 @@ require 'active_support/core_ext/hash/transform_values'
require 'active_support/hash_with_indifferent_access'
require 'active_support/dependencies'
-require_dependency 'gitlab'
+# check gets rid of already initialized constant warnings when using spring
+require_dependency 'gitlab' unless defined?(Gitlab)
module StubConfiguration
def stub_application_setting(messages)
diff --git a/spec/support/helpers/stub_requests.rb b/spec/support/helpers/stub_requests.rb
new file mode 100644
index 00000000000..5cad35282c0
--- /dev/null
+++ b/spec/support/helpers/stub_requests.rb
@@ -0,0 +1,40 @@
+module StubRequests
+ IP_ADDRESS_STUB = '8.8.8.9'.freeze
+
+ # Fully stubs a request using WebMock class. This class also
+ # stubs the IP address the URL is translated to (DNS lookup).
+ #
+ # It expects the final request to go to the `ip_address` instead the given url.
+ # That's primarily a DNS rebind attack prevention of Gitlab::HTTP
+ # (see: Gitlab::UrlBlocker).
+ #
+ def stub_full_request(url, ip_address: IP_ADDRESS_STUB, port: 80, method: :get)
+ stub_dns(url, ip_address: ip_address, port: port)
+
+ url = stubbed_hostname(url, hostname: ip_address)
+ WebMock.stub_request(method, url)
+ end
+
+ def stub_dns(url, ip_address:, port: 80)
+ url = parse_url(url)
+ socket = Socket.sockaddr_in(port, ip_address)
+ addr = Addrinfo.new(socket)
+
+ # See Gitlab::UrlBlocker
+ allow(Addrinfo).to receive(:getaddrinfo)
+ .with(url.hostname, url.port, nil, :STREAM)
+ .and_return([addr])
+ end
+
+ def stubbed_hostname(url, hostname: IP_ADDRESS_STUB)
+ url = parse_url(url)
+ url.hostname = hostname
+ url.to_s
+ end
+
+ private
+
+ def parse_url(url)
+ url.is_a?(URI) ? url : URI(url)
+ end
+end
diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb
index dc902d373b8..06b5ecdf150 100644
--- a/spec/support/helpers/test_env.rb
+++ b/spec/support/helpers/test_env.rb
@@ -135,7 +135,7 @@ module TestEnv
def clean_gitlab_test_path
Dir[TMP_TEST_PATH].each do |entry|
- if File.basename(entry) =~ /\A(gitlab-(test|test_bare|test-fork|test-fork_bare))\z/
+ unless test_dirs.include?(File.basename(entry))
FileUtils.rm_rf(entry)
end
end
@@ -312,6 +312,18 @@ module TestEnv
private
+ # These are directories that should be preserved at cleanup time
+ def test_dirs
+ @test_dirs ||= %w[
+ gitaly
+ gitlab-shell
+ gitlab-test
+ gitlab-test_bare
+ gitlab-test-fork
+ gitlab-test-fork_bare
+ ]
+ end
+
def factory_repo_path
@factory_repo_path ||= Rails.root.join('tmp', 'tests', factory_repo_name)
end
diff --git a/spec/support/helpers/test_request_helpers.rb b/spec/support/helpers/test_request_helpers.rb
index 5a84d67bdfc..39e5dafb059 100644
--- a/spec/support/helpers/test_request_helpers.rb
+++ b/spec/support/helpers/test_request_helpers.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module TestRequestHelpers
- def test_request(remote_ip: '127.0.0.1')
- ActionController::TestRequest.new({ remote_ip: remote_ip }, ActionController::TestSession.new)
+ def test_request(remote_ip: '127.0.0.1', controller: nil)
+ ActionController::TestRequest.new({ remote_ip: remote_ip }, ActionController::TestSession.new, controller)
end
end
diff --git a/spec/support/helpers/wait_for_requests.rb b/spec/support/helpers/wait_for_requests.rb
index c7f878b7371..45b9faa0fea 100644
--- a/spec/support/helpers/wait_for_requests.rb
+++ b/spec/support/helpers/wait_for_requests.rb
@@ -50,20 +50,6 @@ module WaitForRequests
finished_all_vue_resource_requests?
end
- # Waits until the passed block returns true
- def wait_for(condition_name, max_wait_time: Capybara.default_max_wait_time, polling_interval: 0.01)
- wait_until = Time.now + max_wait_time.seconds
- loop do
- break if yield
-
- if Time.now > wait_until
- raise "Condition not met: #{condition_name}"
- else
- sleep(polling_interval)
- end
- end
- end
-
def finished_all_vue_resource_requests?
Capybara.page.evaluate_script('window.activeVueResources || 0').zero?
end
diff --git a/spec/support/helpers/wait_helpers.rb b/spec/support/helpers/wait_helpers.rb
new file mode 100644
index 00000000000..7e8e25798e8
--- /dev/null
+++ b/spec/support/helpers/wait_helpers.rb
@@ -0,0 +1,20 @@
+module WaitHelpers
+ extend self
+
+ # Waits until the passed block returns true
+ def wait_for(condition_name, max_wait_time: Capybara.default_max_wait_time, polling_interval: 0.01, reload: false)
+ wait_until = Time.now + max_wait_time.seconds
+ loop do
+ result = yield
+ break if result
+
+ page.refresh if reload
+
+ if Time.now > wait_until
+ raise "Condition not met: #{condition_name}"
+ else
+ sleep(polling_interval)
+ end
+ end
+ end
+end
diff --git a/spec/support/matchers/eq_pem.rb b/spec/support/matchers/eq_pem.rb
new file mode 100644
index 00000000000..158281e4a19
--- /dev/null
+++ b/spec/support/matchers/eq_pem.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+RSpec::Matchers.define :eq_pem do |expected_pem_string|
+ match do |actual|
+ actual.to_pem == expected_pem_string
+ end
+
+ description do
+ "contain pem #{expected_pem_string}"
+ end
+end
diff --git a/spec/support/prometheus/additional_metrics_shared_examples.rb b/spec/support/prometheus/additional_metrics_shared_examples.rb
index 0fd67531c3b..8044b061ca5 100644
--- a/spec/support/prometheus/additional_metrics_shared_examples.rb
+++ b/spec/support/prometheus/additional_metrics_shared_examples.rb
@@ -46,7 +46,7 @@ RSpec.shared_examples 'additional metrics query' do
describe 'project has Kubernetes service' do
shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
let(:environment) { create(:environment, slug: 'environment-slug', project: project) }
- let(:kube_namespace) { project.deployment_platform.actual_namespace }
+ let(:kube_namespace) { project.deployment_platform.kubernetes_namespace_for(project) }
it_behaves_like 'query context containing environment slug and filter'
diff --git a/spec/support/protected_branch_helpers.rb b/spec/support/protected_branch_helpers.rb
new file mode 100644
index 00000000000..ede16d1c1e2
--- /dev/null
+++ b/spec/support/protected_branch_helpers.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module ProtectedBranchHelpers
+ def set_allowed_to(operation, option = 'Maintainers', form: '.js-new-protected-branch')
+ within form do
+ select_elem = find(".js-allowed-to-#{operation}")
+ select_elem.click
+
+ wait_for_requests
+
+ within('.dropdown-content') do
+ Array(option).each { |opt| click_on(opt) }
+ end
+
+ # Enhanced select is used in EE, therefore an extra click is needed.
+ select_elem.click if select_elem['aria-expanded'] == 'true'
+ end
+ end
+
+ def set_protected_branch_name(branch_name)
+ find('.js-protected-branch-select').click
+ find('.dropdown-input-field').set(branch_name)
+ click_on("Create wildcard #{branch_name}")
+ end
+
+ def set_defaults
+ set_allowed_to('merge')
+ set_allowed_to('push')
+ end
+end
diff --git a/spec/support/protected_tag_helpers.rb b/spec/support/protected_tag_helpers.rb
new file mode 100644
index 00000000000..fe9be856286
--- /dev/null
+++ b/spec/support/protected_tag_helpers.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require_relative 'protected_branch_helpers'
+
+module ProtectedTagHelpers
+ include ::ProtectedBranchHelpers
+
+ def set_allowed_to(operation, option = 'Maintainers', form: '.new-protected-tag')
+ super
+ end
+
+ def set_protected_tag_name(tag_name)
+ find('.js-protected-tag-select').click
+ find('.dropdown-input-field').set(tag_name)
+ click_on("Create wildcard #{tag_name}")
+ find('.protected-tags-dropdown .dropdown-menu', visible: false)
+ end
+end
diff --git a/spec/support/services/migrate_to_ghost_user_service_shared_examples.rb b/spec/support/services/migrate_to_ghost_user_service_shared_examples.rb
index 62ae95df8c0..1284415da1f 100644
--- a/spec/support/services/migrate_to_ghost_user_service_shared_examples.rb
+++ b/spec/support/services/migrate_to_ghost_user_service_shared_examples.rb
@@ -45,7 +45,7 @@ shared_examples "migrating a deleted user's associated records to the ghost user
context "race conditions" do
context "when #{record_class_name} migration fails and is rolled back" do
before do
- expect_any_instance_of(record_class::ActiveRecord_Associations_CollectionProxy)
+ expect_any_instance_of(ActiveRecord::Associations::CollectionProxy)
.to receive(:update_all).and_raise(ActiveRecord::Rollback)
end
@@ -66,7 +66,7 @@ shared_examples "migrating a deleted user's associated records to the ghost user
context "when #{record_class_name} migration fails with a non-rollback exception" do
before do
- expect_any_instance_of(record_class::ActiveRecord_Associations_CollectionProxy)
+ expect_any_instance_of(ActiveRecord::Associations::CollectionProxy)
.to receive(:update_all).and_raise(ArgumentError)
end
diff --git a/spec/support/shared_context/policies/project_policy_shared_context.rb b/spec/support/shared_context/policies/project_policy_shared_context.rb
deleted file mode 100644
index ee5cfcd850d..00000000000
--- a/spec/support/shared_context/policies/project_policy_shared_context.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_context 'ProjectPolicy context' do
- set(:guest) { create(:user) }
- set(:reporter) { create(:user) }
- set(:developer) { create(:user) }
- set(:maintainer) { create(:user) }
- set(:owner) { create(:user) }
- set(:admin) { create(:admin) }
- let(:project) { create(:project, :public, namespace: owner.namespace) }
-
- let(:base_guest_permissions) do
- %i[
- read_project read_board read_list read_wiki read_issue
- read_project_for_iids read_issue_iid read_label
- read_milestone read_project_snippet read_project_member read_note
- create_project create_issue create_note upload_file create_merge_request_in
- award_emoji
- ]
- end
-
- let(:base_reporter_permissions) do
- %i[
- download_code fork_project create_project_snippet update_issue
- admin_issue admin_label admin_list read_commit_status read_build
- read_container_image read_pipeline read_environment read_deployment
- read_merge_request download_wiki_code read_sentry_issue read_release
- read_prometheus
- ]
- end
-
- let(:team_member_reporter_permissions) do
- %i[build_download_code build_read_container_image]
- end
-
- let(:developer_permissions) do
- %i[
- admin_milestone admin_merge_request update_merge_request create_commit_status
- update_commit_status create_build update_build create_pipeline
- update_pipeline create_merge_request_from create_wiki push_code
- resolve_note create_container_image update_container_image
- create_environment create_deployment create_release update_release
- ]
- end
-
- let(:base_maintainer_permissions) do
- %i[
- push_to_delete_protected_branch update_project_snippet update_environment
- update_deployment admin_project_snippet admin_project_member admin_note admin_wiki admin_project
- admin_commit_status admin_build admin_container_image
- admin_pipeline admin_environment admin_deployment destroy_release add_cluster
- daily_statistics
- ]
- end
-
- let(:public_permissions) do
- %i[
- download_code fork_project read_commit_status read_pipeline
- read_container_image build_download_code build_read_container_image
- download_wiki_code read_release
- ]
- end
-
- let(:base_owner_permissions) do
- %i[
- change_namespace change_visibility_level rename_project remove_project
- archive_project remove_fork_project destroy_merge_request destroy_issue
- set_issue_iid set_issue_created_at set_note_created_at
- ]
- end
-
- # Used in EE specs
- let(:additional_guest_permissions) { [] }
- let(:additional_reporter_permissions) { [] }
- let(:additional_maintainer_permissions) { [] }
- let(:additional_owner_permissions) { [] }
-
- let(:guest_permissions) { base_guest_permissions + additional_guest_permissions }
- let(:reporter_permissions) { base_reporter_permissions + additional_reporter_permissions }
- let(:maintainer_permissions) { base_maintainer_permissions + additional_maintainer_permissions }
- let(:owner_permissions) { base_owner_permissions + additional_owner_permissions }
-
- before do
- project.add_guest(guest)
- project.add_maintainer(maintainer)
- project.add_developer(developer)
- project.add_reporter(reporter)
- end
-end
diff --git a/spec/support/shared_contexts/policies/project_policy_shared_context.rb b/spec/support/shared_contexts/policies/project_policy_shared_context.rb
new file mode 100644
index 00000000000..1aa40dcde3d
--- /dev/null
+++ b/spec/support/shared_contexts/policies/project_policy_shared_context.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'ProjectPolicy context' do
+ set(:guest) { create(:user) }
+ set(:reporter) { create(:user) }
+ set(:developer) { create(:user) }
+ set(:maintainer) { create(:user) }
+ set(:owner) { create(:user) }
+ set(:admin) { create(:admin) }
+ let(:project) { create(:project, :public, namespace: owner.namespace) }
+
+ let(:base_guest_permissions) do
+ %i[
+ read_project read_board read_list read_wiki read_issue
+ read_project_for_iids read_issue_iid read_label
+ read_milestone read_project_snippet read_project_member read_note
+ create_project create_issue create_note upload_file create_merge_request_in
+ award_emoji
+ ]
+ end
+
+ let(:base_reporter_permissions) do
+ %i[
+ download_code fork_project create_project_snippet update_issue
+ admin_issue admin_label admin_list read_commit_status read_build
+ read_container_image read_pipeline read_environment read_deployment
+ read_merge_request download_wiki_code read_sentry_issue read_prometheus
+ ]
+ end
+
+ let(:team_member_reporter_permissions) do
+ %i[build_download_code build_read_container_image]
+ end
+
+ let(:developer_permissions) do
+ %i[
+ admin_milestone admin_merge_request update_merge_request create_commit_status
+ update_commit_status create_build update_build create_pipeline
+ update_pipeline create_merge_request_from create_wiki push_code
+ resolve_note create_container_image update_container_image
+ create_environment create_deployment create_release update_release
+ ]
+ end
+
+ let(:base_maintainer_permissions) do
+ %i[
+ push_to_delete_protected_branch update_project_snippet update_environment
+ update_deployment admin_project_snippet admin_project_member admin_note admin_wiki admin_project
+ admin_commit_status admin_build admin_container_image
+ admin_pipeline admin_environment admin_deployment destroy_release add_cluster
+ daily_statistics
+ ]
+ end
+
+ let(:public_permissions) do
+ %i[
+ download_code fork_project read_commit_status read_pipeline
+ read_container_image build_download_code build_read_container_image
+ download_wiki_code read_release
+ ]
+ end
+
+ let(:base_owner_permissions) do
+ %i[
+ change_namespace change_visibility_level rename_project remove_project
+ archive_project remove_fork_project destroy_merge_request destroy_issue
+ set_issue_iid set_issue_created_at set_issue_updated_at set_note_created_at
+ ]
+ end
+
+ # Used in EE specs
+ let(:additional_guest_permissions) { [] }
+ let(:additional_reporter_permissions) { [] }
+ let(:additional_maintainer_permissions) { [] }
+ let(:additional_owner_permissions) { [] }
+
+ let(:guest_permissions) { base_guest_permissions + additional_guest_permissions }
+ let(:reporter_permissions) { base_reporter_permissions + additional_reporter_permissions }
+ let(:maintainer_permissions) { base_maintainer_permissions + additional_maintainer_permissions }
+ let(:owner_permissions) { base_owner_permissions + additional_owner_permissions }
+
+ before do
+ project.add_guest(guest)
+ project.add_maintainer(maintainer)
+ project.add_developer(developer)
+ project.add_reporter(reporter)
+ end
+end
diff --git a/spec/support/shared_examples/application_setting_examples.rb b/spec/support/shared_examples/application_setting_examples.rb
index e7ec24c5b7e..421303c97be 100644
--- a/spec/support/shared_examples/application_setting_examples.rb
+++ b/spec/support/shared_examples/application_setting_examples.rb
@@ -249,4 +249,43 @@ RSpec.shared_examples 'application settings examples' do
expect(setting.password_authentication_enabled_for_web?).to be_falsey
end
+
+ describe 'sentry settings' do
+ context 'when the sentry settings are not set in gitlab.yml' do
+ it 'fallbacks to the settings in the database' do
+ setting.sentry_enabled = true
+ setting.sentry_dsn = 'https://b44a0828b72421a6d8e99efd68d44fa8@example.com/40'
+ setting.clientside_sentry_enabled = true
+ setting.clientside_sentry_dsn = 'https://b44a0828b72421a6d8e99efd68d44fa8@example.com/41'
+
+ allow(Gitlab.config.sentry).to receive(:enabled).and_return(false)
+ allow(Gitlab.config.sentry).to receive(:dsn).and_return(nil)
+ allow(Gitlab.config.sentry).to receive(:clientside_dsn).and_return(nil)
+
+ expect(setting.sentry_enabled).to eq true
+ expect(setting.sentry_dsn).to eq 'https://b44a0828b72421a6d8e99efd68d44fa8@example.com/40'
+ expect(setting.clientside_sentry_enabled).to eq true
+ expect(setting.clientside_sentry_dsn). to eq 'https://b44a0828b72421a6d8e99efd68d44fa8@example.com/41'
+ end
+ end
+
+ context 'when the sentry settings are set in gitlab.yml' do
+ it 'does not fallback to the settings in the database' do
+ setting.sentry_enabled = false
+ setting.sentry_dsn = 'https://b44a0828b72421a6d8e99efd68d44fa8@example.com/40'
+ setting.clientside_sentry_enabled = false
+ setting.clientside_sentry_dsn = 'https://b44a0828b72421a6d8e99efd68d44fa8@example.com/41'
+
+ allow(Gitlab.config.sentry).to receive(:enabled).and_return(true)
+ allow(Gitlab.config.sentry).to receive(:dsn).and_return('https://b44a0828b72421a6d8e99efd68d44fa8@example.com/42')
+ allow(Gitlab.config.sentry).to receive(:clientside_dsn).and_return('https://b44a0828b72421a6d8e99efd68d44fa8@example.com/43')
+
+ expect(setting).not_to receive(:read_attribute)
+ expect(setting.sentry_enabled).to eq true
+ expect(setting.sentry_dsn).to eq 'https://b44a0828b72421a6d8e99efd68d44fa8@example.com/42'
+ expect(setting.clientside_sentry_enabled).to eq true
+ expect(setting.clientside_sentry_dsn). to eq 'https://b44a0828b72421a6d8e99efd68d44fa8@example.com/43'
+ end
+ end
+ end
end
diff --git a/spec/support/shared_examples/ci/stage_shared_examples.rb b/spec/support/shared_examples/ci/stage_shared_examples.rb
new file mode 100644
index 00000000000..925974ed11e
--- /dev/null
+++ b/spec/support/shared_examples/ci/stage_shared_examples.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+shared_examples 'manual playable stage' do |stage_type|
+ let(:stage) { build(stage_type, status: status) }
+
+ describe '#manual_playable?' do
+ subject { stage.manual_playable? }
+
+ context 'when is manual' do
+ let(:status) { 'manual' }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when is scheduled' do
+ let(:status) { 'scheduled' }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when is skipped' do
+ let(:status) { 'skipped' }
+
+ it { is_expected.to be_truthy }
+ end
+ end
+end
diff --git a/spec/support/shared_examples/ci_trace_shared_examples.rb b/spec/support/shared_examples/ci_trace_shared_examples.rb
index c603421d748..db935bcb388 100644
--- a/spec/support/shared_examples/ci_trace_shared_examples.rb
+++ b/spec/support/shared_examples/ci_trace_shared_examples.rb
@@ -329,14 +329,6 @@ shared_examples_for 'trace with disabled live trace feature' do
it_behaves_like 'read successfully with IO'
end
- context 'when current_path (with project_ci_id) exists' do
- before do
- expect(trace).to receive(:deprecated_path) { expand_fixture_path('trace/sample_trace') }
- end
-
- it_behaves_like 'read successfully with IO'
- end
-
context 'when db trace exists' do
before do
build.send(:write_attribute, :trace, "data")
@@ -396,37 +388,6 @@ shared_examples_for 'trace with disabled live trace feature' do
end
end
- context 'deprecated path' do
- let(:path) { trace.send(:deprecated_path) }
-
- context 'with valid ci_id' do
- before do
- build.project.update(ci_id: 1000)
-
- FileUtils.mkdir_p(File.dirname(path))
-
- File.open(path, "w") do |file|
- file.write("data")
- end
- end
-
- it "trace exist" do
- expect(trace.exist?).to be(true)
- end
-
- it "can be erased" do
- trace.erase!
- expect(trace.exist?).to be(false)
- end
- end
-
- context 'without valid ci_id' do
- it "does not return deprecated path" do
- expect(path).to be_nil
- end
- end
- end
-
context 'stored in database' do
before do
build.send(:write_attribute, :trace, "data")
diff --git a/spec/support/shared_examples/controllers/repository_lfs_file_load_examples.rb b/spec/support/shared_examples/controllers/repository_lfs_file_load_examples.rb
index 982e0317f7f..b7080c68270 100644
--- a/spec/support/shared_examples/controllers/repository_lfs_file_load_examples.rb
+++ b/spec/support/shared_examples/controllers/repository_lfs_file_load_examples.rb
@@ -9,87 +9,87 @@
# - `filepath`: path of the file (contains filename)
# - `subject`: the request to be made to the controller. Example:
# subject { get :show, namespace_id: project.namespace, project_id: project }
-shared_examples 'repository lfs file load' do
- context 'when file is stored in lfs' do
- let(:lfs_oid) { '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897' }
- let(:lfs_size) { '1575078' }
- let!(:lfs_object) { create(:lfs_object, oid: lfs_oid, size: lfs_size) }
+shared_examples 'a controller that can serve LFS files' do
+ let(:lfs_oid) { '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897' }
+ let(:lfs_size) { '1575078' }
+ let!(:lfs_object) { create(:lfs_object, oid: lfs_oid, size: lfs_size) }
+
+ context 'when lfs is enabled' do
+ before do
+ allow_any_instance_of(Project).to receive(:lfs_enabled?).and_return(true)
+ end
- context 'when lfs is enabled' do
+ context 'when project has access' do
before do
- allow_any_instance_of(Project).to receive(:lfs_enabled?).and_return(true)
+ project.lfs_objects << lfs_object
+ allow_any_instance_of(LfsObjectUploader).to receive(:exists?).and_return(true)
+ allow(controller).to receive(:send_file) { controller.head :ok }
end
- context 'when project has access' do
- before do
- project.lfs_objects << lfs_object
- allow_any_instance_of(LfsObjectUploader).to receive(:exists?).and_return(true)
- allow(controller).to receive(:send_file) { controller.head :ok }
- end
+ it 'serves the file' do
+ lfs_uploader = LfsObjectUploader.new(lfs_object)
- it 'serves the file' do
- # Notice the filename= is omitted from the disposition; this is because
- # Rails 5 will append this header in send_file
- expect(controller).to receive(:send_file)
- .with(
- "#{LfsObjectUploader.root}/91/ef/f75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897",
- filename: filename,
- disposition: %Q(attachment; filename*=UTF-8''#{filename}))
+ # Notice the filename= is omitted from the disposition; this is because
+ # Rails 5 will append this header in send_file
+ expect(controller).to receive(:send_file)
+ .with(
+ File.join(lfs_uploader.root, lfs_uploader.store_dir, lfs_uploader.filename),
+ filename: filename,
+ disposition: %Q(attachment; filename*=UTF-8''#{filename}))
- subject
+ subject
- expect(response).to have_gitlab_http_status(200)
- end
+ expect(response).to have_gitlab_http_status(200)
+ end
- context 'and lfs uses object storage' do
- let(:lfs_object) { create(:lfs_object, :with_file, oid: lfs_oid, size: lfs_size) }
+ context 'and lfs uses object storage' do
+ let(:lfs_object) { create(:lfs_object, :with_file, oid: lfs_oid, size: lfs_size) }
- before do
- stub_lfs_object_storage
- lfs_object.file.migrate!(LfsObjectUploader::Store::REMOTE)
- end
+ before do
+ stub_lfs_object_storage
+ lfs_object.file.migrate!(LfsObjectUploader::Store::REMOTE)
+ end
- it 'responds with redirect to file' do
- subject
+ it 'responds with redirect to file' do
+ subject
- expect(response).to have_gitlab_http_status(302)
- expect(response.location).to include(lfs_object.reload.file.path)
- end
+ expect(response).to have_gitlab_http_status(302)
+ expect(response.location).to include(lfs_object.reload.file.path)
+ end
- it 'sets content disposition' do
- subject
+ it 'sets content disposition' do
+ subject
- file_uri = URI.parse(response.location)
- params = CGI.parse(file_uri.query)
+ file_uri = URI.parse(response.location)
+ params = CGI.parse(file_uri.query)
- expect(params["response-content-disposition"].first).to eq(%q(attachment; filename="lfs_object.iso"; filename*=UTF-8''lfs_object.iso))
- end
+ expect(params["response-content-disposition"].first).to eq(%Q(attachment; filename="#{filename}"; filename*=UTF-8''#{filename}))
end
end
+ end
- context 'when project does not have access' do
- it 'does not serve the file' do
- subject
+ context 'when project does not have access' do
+ it 'does not serve the file' do
+ subject
- expect(response).to have_gitlab_http_status(404)
- end
+ expect(response).to have_gitlab_http_status(404)
end
end
+ end
- context 'when lfs is not enabled' do
- before do
- allow_any_instance_of(Project).to receive(:lfs_enabled?).and_return(false)
- end
+ context 'when lfs is not enabled' do
+ before do
+ allow_any_instance_of(Project).to receive(:lfs_enabled?).and_return(false)
+ end
- it 'delivers ASCII file' do
- subject
+ it 'delivers ASCII file' do
+ subject
- expect(response).to have_gitlab_http_status(200)
- expect(response.header['Content-Type']).to eq('text/plain; charset=utf-8')
- expect(response.header['Content-Disposition'])
- .to eq('inline')
- expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with('git-blob:')
- end
+ expect(response).to have_gitlab_http_status(200)
+ expect(response.header['Content-Type']).to eq('text/plain; charset=utf-8')
+ expect(response.header['Content-Disposition'])
+ .to eq('inline')
+ expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with('git-blob:')
end
end
end
diff --git a/spec/support/shared_examples/controllers/variables_shared_examples.rb b/spec/support/shared_examples/controllers/variables_shared_examples.rb
index b615a8f54cf..e80722857ec 100644
--- a/spec/support/shared_examples/controllers/variables_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/variables_shared_examples.rb
@@ -120,4 +120,16 @@ shared_examples 'PATCH #update updates variables' do
expect(response).to match_response_schema('variables')
end
end
+
+ context 'for variables of type file' do
+ let(:variables_attributes) do
+ [
+ new_variable_attributes.merge(variable_type: 'file')
+ ]
+ end
+
+ it 'creates new variable of type file' do
+ expect { subject }.to change { owner.variables.file.count }.by(1)
+ end
+ end
end
diff --git a/spec/support/shared_examples/finders/assignees_filter_shared_examples.rb b/spec/support/shared_examples/finders/assignees_filter_shared_examples.rb
new file mode 100644
index 00000000000..a931c4df99f
--- /dev/null
+++ b/spec/support/shared_examples/finders/assignees_filter_shared_examples.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+shared_examples 'assignee ID filter' do
+ it 'returns issuables assigned to that user' do
+ expect(issuables).to contain_exactly(*expected_issuables)
+ end
+end
+
+shared_examples 'assignee username filter' do
+ it 'returns issuables assigned to those users' do
+ expect(issuables).to contain_exactly(*expected_issuables)
+ end
+end
+
+shared_examples 'no assignee filter' do
+ let(:params) { { assignee_id: 'None' } }
+
+ it 'returns issuables not assigned to any assignee' do
+ expect(issuables).to contain_exactly(*expected_issuables)
+ end
+
+ it 'returns issuables not assigned to any assignee' do
+ params[:assignee_id] = 'none'
+
+ expect(issuables).to contain_exactly(*expected_issuables)
+ end
+end
+
+shared_examples 'any assignee filter' do
+ context '' do
+ let(:params) { { assignee_id: 'Any' } }
+
+ it 'returns issuables assigned to any assignee' do
+ expect(issuables).to contain_exactly(*expected_issuables)
+ end
+
+ it 'returns issuables assigned to any assignee' do
+ params[:assignee_id] = 'any'
+
+ expect(issuables).to contain_exactly(*expected_issuables)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/finders/assignees_filter_spec.rb b/spec/support/shared_examples/finders/assignees_filter_spec.rb
deleted file mode 100644
index 782a2d97746..00000000000
--- a/spec/support/shared_examples/finders/assignees_filter_spec.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-shared_examples 'assignee ID filter' do
- it 'returns issuables assigned to that user' do
- expect(issuables).to contain_exactly(*expected_issuables)
- end
-end
-
-shared_examples 'assignee username filter' do
- it 'returns issuables assigned to those users' do
- expect(issuables).to contain_exactly(*expected_issuables)
- end
-end
-
-shared_examples 'no assignee filter' do
- let(:params) { { assignee_id: 'None' } }
-
- it 'returns issuables not assigned to any assignee' do
- expect(issuables).to contain_exactly(*expected_issuables)
- end
-
- it 'returns issuables not assigned to any assignee' do
- params[:assignee_id] = 0
-
- expect(issuables).to contain_exactly(*expected_issuables)
- end
-
- it 'returns issuables not assigned to any assignee' do
- params[:assignee_id] = 'none'
-
- expect(issuables).to contain_exactly(*expected_issuables)
- end
-end
-
-shared_examples 'any assignee filter' do
- context '' do
- let(:params) { { assignee_id: 'Any' } }
-
- it 'returns issuables assigned to any assignee' do
- expect(issuables).to contain_exactly(*expected_issuables)
- end
-
- it 'returns issuables assigned to any assignee' do
- params[:assignee_id] = 'any'
-
- expect(issuables).to contain_exactly(*expected_issuables)
- end
- end
-end
diff --git a/spec/support/shared_examples/legacy_path_redirect_shared_examples.rb b/spec/support/shared_examples/legacy_path_redirect_shared_examples.rb
index f300bdd48b1..f326e502092 100644
--- a/spec/support/shared_examples/legacy_path_redirect_shared_examples.rb
+++ b/spec/support/shared_examples/legacy_path_redirect_shared_examples.rb
@@ -11,3 +11,11 @@ shared_examples 'redirecting a legacy path' do |source, target|
expect(get(source)).not_to redirect_to(target)
end
end
+
+shared_examples 'redirecting a legacy project path' do |source, target|
+ include RSpec::Rails::RequestExampleGroup
+
+ it "redirects #{source} to #{target}" do
+ expect(get(source)).to redirect_to(target)
+ end
+end
diff --git a/spec/support/shared_examples/models/atomic_internal_id_spec.rb b/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb
index a248f60d23e..a248f60d23e 100644
--- a/spec/support/shared_examples/models/atomic_internal_id_spec.rb
+++ b/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb
diff --git a/spec/support/shared_examples/models/chat_service_shared_examples.rb b/spec/support/shared_examples/models/chat_service_shared_examples.rb
new file mode 100644
index 00000000000..0a302e7d030
--- /dev/null
+++ b/spec/support/shared_examples/models/chat_service_shared_examples.rb
@@ -0,0 +1,248 @@
+require "spec_helper"
+
+shared_examples_for "chat service" do |service_name|
+ describe "Associations" do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe "Validations" do
+ context "when service is active" do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:webhook) }
+ it_behaves_like "issue tracker service URL attribute", :webhook
+ end
+
+ context "when service is inactive" do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:webhook) }
+ end
+ end
+
+ describe '.supported_events' do
+ it 'does not support deployment_events' do
+ expect(described_class.supported_events).not_to include('deployment')
+ end
+ end
+
+ describe "#execute" do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:webhook_url) { "https://example.gitlab.com/" }
+
+ before do
+ allow(subject).to receive_messages(
+ project: project,
+ project_id: project.id,
+ service_hook: true,
+ webhook: webhook_url
+ )
+
+ WebMock.stub_request(:post, webhook_url)
+ end
+
+ shared_examples "#{service_name} service" do
+ it "calls #{service_name} API" do
+ subject.execute(sample_data)
+
+ expect(WebMock).to have_requested(:post, webhook_url).with { |req| req.body =~ /\A{"#{content_key}":.+}\Z/ }.once
+ end
+ end
+
+ context "with push events" do
+ let(:sample_data) do
+ Gitlab::DataBuilder::Push.build_sample(project, user)
+ end
+
+ it_behaves_like "#{service_name} service"
+
+ it "specifies the webhook when it is configured" do
+ expect(client).to receive(:new).with(client_arguments).and_return(double(:chat_service).as_null_object)
+
+ subject.execute(sample_data)
+ end
+
+ context "with not default branch" do
+ let(:sample_data) do
+ Gitlab::DataBuilder::Push.build(project: project, user: user, ref: "not-the-default-branch")
+ end
+
+ context "when notify_only_default_branch enabled" do
+ before do
+ subject.notify_only_default_branch = true
+ end
+
+ it "does not call the Discord Webhooks API" do
+ result = subject.execute(sample_data)
+
+ expect(result).to be_falsy
+ end
+ end
+
+ context "when notify_only_default_branch disabled" do
+ before do
+ subject.notify_only_default_branch = false
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+ end
+ end
+
+ context "with issue events" do
+ let(:opts) { { title: "Awesome issue", description: "please fix" } }
+ let(:sample_data) do
+ service = Issues::CreateService.new(project, user, opts)
+ issue = service.execute
+ service.hook_data(issue, "open")
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with merge events" do
+ let(:opts) do
+ {
+ title: "Awesome merge_request",
+ description: "please fix",
+ source_branch: "feature",
+ target_branch: "master"
+ }
+ end
+
+ let(:sample_data) do
+ service = MergeRequests::CreateService.new(project, user, opts)
+ merge_request = service.execute
+ service.hook_data(merge_request, "open")
+ end
+
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with wiki page events" do
+ let(:opts) do
+ {
+ title: "Awesome wiki_page",
+ content: "Some text describing some thing or another",
+ format: "md",
+ message: "user created page: Awesome wiki_page"
+ }
+ end
+ let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: opts) }
+ let(:sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, "create") }
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with note events" do
+ let(:sample_data) { Gitlab::DataBuilder::Note.build(note, user) }
+
+ context "with commit comment" do
+ let(:note) do
+ create(:note_on_commit,
+ author: user,
+ project: project,
+ commit_id: project.repository.commit.id,
+ note: "a comment on a commit")
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with merge request comment" do
+ let(:note) do
+ create(:note_on_merge_request, project: project, note: "merge request note")
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with issue comment" do
+ let(:note) do
+ create(:note_on_issue, project: project, note: "issue note")
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with snippet comment" do
+ let(:note) do
+ create(:note_on_project_snippet, project: project, note: "snippet note")
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+ end
+
+ context "with pipeline events" do
+ let(:pipeline) do
+ create(:ci_pipeline,
+ project: project, status: status,
+ sha: project.commit.sha, ref: project.default_branch)
+ end
+ let(:sample_data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
+
+ context "with failed pipeline" do
+ let(:status) { "failed" }
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with succeeded pipeline" do
+ let(:status) { "success" }
+
+ context "with default notify_only_broken_pipelines" do
+ it "does not call Discord Webhooks API" do
+ result = subject.execute(sample_data)
+
+ expect(result).to be_falsy
+ end
+ end
+
+ context "when notify_only_broken_pipelines is false" do
+ before do
+ subject.notify_only_broken_pipelines = false
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+ end
+
+ context "with not default branch" do
+ let(:pipeline) do
+ create(:ci_pipeline, project: project, status: "failed", ref: "not-the-default-branch")
+ end
+
+ context "when notify_only_default_branch enabled" do
+ before do
+ subject.notify_only_default_branch = true
+ end
+
+ it "does not call the Discord Webhooks API" do
+ result = subject.execute(sample_data)
+
+ expect(result).to be_falsy
+ end
+ end
+
+ context "when notify_only_default_branch disabled" do
+ before do
+ subject.notify_only_default_branch = false
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/chat_service_spec.rb b/spec/support/shared_examples/models/chat_service_spec.rb
deleted file mode 100644
index cf1d52a9616..00000000000
--- a/spec/support/shared_examples/models/chat_service_spec.rb
+++ /dev/null
@@ -1,242 +0,0 @@
-require "spec_helper"
-
-shared_examples_for "chat service" do |service_name|
- describe "Associations" do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe "Validations" do
- context "when service is active" do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:webhook) }
- it_behaves_like "issue tracker service URL attribute", :webhook
- end
-
- context "when service is inactive" do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:webhook) }
- end
- end
-
- describe "#execute" do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
- let(:webhook_url) { "https://example.gitlab.com/" }
-
- before do
- allow(subject).to receive_messages(
- project: project,
- project_id: project.id,
- service_hook: true,
- webhook: webhook_url
- )
-
- WebMock.stub_request(:post, webhook_url)
- end
-
- shared_examples "#{service_name} service" do
- it "calls #{service_name} API" do
- subject.execute(sample_data)
-
- expect(WebMock).to have_requested(:post, webhook_url).with { |req| req.body =~ /\A{"#{content_key}":.+}\Z/ }.once
- end
- end
-
- context "with push events" do
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build_sample(project, user)
- end
-
- it_behaves_like "#{service_name} service"
-
- it "specifies the webhook when it is configured" do
- expect(client).to receive(:new).with(client_arguments).and_return(double(:chat_service).as_null_object)
-
- subject.execute(sample_data)
- end
-
- context "with not default branch" do
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build(project, user, nil, nil, "not-the-default-branch")
- end
-
- context "when notify_only_default_branch enabled" do
- before do
- subject.notify_only_default_branch = true
- end
-
- it "does not call the Discord Webhooks API" do
- result = subject.execute(sample_data)
-
- expect(result).to be_falsy
- end
- end
-
- context "when notify_only_default_branch disabled" do
- before do
- subject.notify_only_default_branch = false
- end
-
- it_behaves_like "#{service_name} service"
- end
- end
- end
-
- context "with issue events" do
- let(:opts) { { title: "Awesome issue", description: "please fix" } }
- let(:sample_data) do
- service = Issues::CreateService.new(project, user, opts)
- issue = service.execute
- service.hook_data(issue, "open")
- end
-
- it_behaves_like "#{service_name} service"
- end
-
- context "with merge events" do
- let(:opts) do
- {
- title: "Awesome merge_request",
- description: "please fix",
- source_branch: "feature",
- target_branch: "master"
- }
- end
-
- let(:sample_data) do
- service = MergeRequests::CreateService.new(project, user, opts)
- merge_request = service.execute
- service.hook_data(merge_request, "open")
- end
-
- before do
- project.add_developer(user)
- end
-
- it_behaves_like "#{service_name} service"
- end
-
- context "with wiki page events" do
- let(:opts) do
- {
- title: "Awesome wiki_page",
- content: "Some text describing some thing or another",
- format: "md",
- message: "user created page: Awesome wiki_page"
- }
- end
- let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: opts) }
- let(:sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, "create") }
-
- it_behaves_like "#{service_name} service"
- end
-
- context "with note events" do
- let(:sample_data) { Gitlab::DataBuilder::Note.build(note, user) }
-
- context "with commit comment" do
- let(:note) do
- create(:note_on_commit,
- author: user,
- project: project,
- commit_id: project.repository.commit.id,
- note: "a comment on a commit")
- end
-
- it_behaves_like "#{service_name} service"
- end
-
- context "with merge request comment" do
- let(:note) do
- create(:note_on_merge_request, project: project, note: "merge request note")
- end
-
- it_behaves_like "#{service_name} service"
- end
-
- context "with issue comment" do
- let(:note) do
- create(:note_on_issue, project: project, note: "issue note")
- end
-
- it_behaves_like "#{service_name} service"
- end
-
- context "with snippet comment" do
- let(:note) do
- create(:note_on_project_snippet, project: project, note: "snippet note")
- end
-
- it_behaves_like "#{service_name} service"
- end
- end
-
- context "with pipeline events" do
- let(:pipeline) do
- create(:ci_pipeline,
- project: project, status: status,
- sha: project.commit.sha, ref: project.default_branch)
- end
- let(:sample_data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
-
- context "with failed pipeline" do
- let(:status) { "failed" }
-
- it_behaves_like "#{service_name} service"
- end
-
- context "with succeeded pipeline" do
- let(:status) { "success" }
-
- context "with default notify_only_broken_pipelines" do
- it "does not call Discord Webhooks API" do
- result = subject.execute(sample_data)
-
- expect(result).to be_falsy
- end
- end
-
- context "when notify_only_broken_pipelines is false" do
- before do
- subject.notify_only_broken_pipelines = false
- end
-
- it_behaves_like "#{service_name} service"
- end
- end
-
- context "with not default branch" do
- let(:pipeline) do
- create(:ci_pipeline, project: project, status: "failed", ref: "not-the-default-branch")
- end
-
- context "when notify_only_default_branch enabled" do
- before do
- subject.notify_only_default_branch = true
- end
-
- it "does not call the Discord Webhooks API" do
- result = subject.execute(sample_data)
-
- expect(result).to be_falsy
- end
- end
-
- context "when notify_only_default_branch disabled" do
- before do
- subject.notify_only_default_branch = false
- end
-
- it_behaves_like "#{service_name} service"
- end
- end
- end
- end
-end
diff --git a/spec/support/shared_examples/models/ci_variable_shared_examples.rb b/spec/support/shared_examples/models/ci_variable_shared_examples.rb
new file mode 100644
index 00000000000..f93de8b6ff1
--- /dev/null
+++ b/spec/support/shared_examples/models/ci_variable_shared_examples.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+shared_examples_for 'CI variable' do
+ it { is_expected.to include_module(HasVariable) }
+
+ describe "variable type" do
+ it 'defines variable types' do
+ expect(described_class.variable_types).to eq({ "env_var" => 1, "file" => 2 })
+ end
+
+ it "defaults variable type to env_var" do
+ expect(subject.variable_type).to eq("env_var")
+ end
+
+ it "supports variable type file" do
+ variable = described_class.new(variable_type: :file)
+ expect(variable).to be_file
+ end
+ end
+
+ it 'strips whitespaces when assigning key' do
+ subject.key = " SECRET "
+ expect(subject.key).to eq("SECRET")
+ end
+
+ it 'can convert to runner variable' do
+ expect(subject.to_runner_variable.keys).to include(:key, :value, :public, :file)
+ end
+end
diff --git a/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb b/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb
index 1f76b981292..d6490a808ce 100644
--- a/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb
+++ b/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb
@@ -2,6 +2,14 @@ shared_examples 'cluster application core specs' do |application_name|
it { is_expected.to belong_to(:cluster) }
it { is_expected.to validate_presence_of(:cluster) }
+ describe '#can_uninstall?' do
+ it 'calls allowed_to_uninstall?' do
+ expect(subject).to receive(:allowed_to_uninstall?).and_return(true)
+
+ expect(subject.can_uninstall?).to be_truthy
+ end
+ end
+
describe '#name' do
it 'is .application_name' do
expect(subject.name).to eq(described_class.application_name)
diff --git a/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb b/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb
index b8c19cab0c4..4525c03837f 100644
--- a/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb
+++ b/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb
@@ -114,6 +114,17 @@ shared_examples 'cluster application status specs' do |application_name|
expect(subject.status_reason).to eq(reason)
end
end
+
+ context 'application is uninstalling' do
+ subject { create(application_name, :uninstalling) }
+
+ it 'is uninstall_errored' do
+ subject.make_errored(reason)
+
+ expect(subject).to be_uninstall_errored
+ expect(subject.status_reason).to eq(reason)
+ end
+ end
end
describe '#make_scheduled' do
@@ -125,6 +136,16 @@ shared_examples 'cluster application status specs' do |application_name|
expect(subject).to be_scheduled
end
+ describe 'when installed' do
+ subject { create(application_name, :installed) }
+
+ it 'is scheduled' do
+ subject.make_scheduled
+
+ expect(subject).to be_scheduled
+ end
+ end
+
describe 'when was errored' do
subject { create(application_name, :errored) }
@@ -148,6 +169,28 @@ shared_examples 'cluster application status specs' do |application_name|
expect(subject.status_reason).to be_nil
end
end
+
+ describe 'when was uninstall_errored' do
+ subject { create(application_name, :uninstall_errored) }
+
+ it 'clears #status_reason' do
+ expect(subject.status_reason).not_to be_nil
+
+ subject.make_scheduled!
+
+ expect(subject.status_reason).to be_nil
+ end
+ end
+ end
+
+ describe '#make_uninstalling' do
+ subject { create(application_name, :scheduled) }
+
+ it 'is uninstalling' do
+ subject.make_uninstalling!
+
+ expect(subject).to be_uninstalling
+ end
end
end
@@ -155,16 +198,18 @@ shared_examples 'cluster application status specs' do |application_name|
using RSpec::Parameterized::TableSyntax
where(:trait, :available) do
- :not_installable | false
- :installable | false
- :scheduled | false
- :installing | false
- :installed | true
- :updating | false
- :updated | true
- :errored | false
- :update_errored | false
- :timeouted | false
+ :not_installable | false
+ :installable | false
+ :scheduled | false
+ :installing | false
+ :installed | true
+ :updating | false
+ :updated | true
+ :errored | false
+ :update_errored | false
+ :uninstalling | false
+ :uninstall_errored | false
+ :timed_out | false
end
with_them do
diff --git a/spec/support/shared_examples/models/member_shared_examples.rb b/spec/support/shared_examples/models/member_shared_examples.rb
index 77376496854..e5375bc8280 100644
--- a/spec/support/shared_examples/models/member_shared_examples.rb
+++ b/spec/support/shared_examples/models/member_shared_examples.rb
@@ -41,7 +41,7 @@ shared_examples_for 'inherited access level as a member of entity' do
member.update(access_level: Gitlab::Access::REPORTER)
- expect(member.errors.full_messages).to eq(["Access level should be higher than Developer inherited membership from group #{parent_entity.name}"])
+ expect(member.errors.full_messages).to eq(["Access level should be greater than or equal to Developer inherited membership from group #{parent_entity.name}"])
end
it 'allows changing the level from a non existing member' do
diff --git a/spec/support/shared_examples/models/update_project_statistics_shared_examples.rb b/spec/support/shared_examples/models/update_project_statistics_shared_examples.rb
new file mode 100644
index 00000000000..1b09c3dd636
--- /dev/null
+++ b/spec/support/shared_examples/models/update_project_statistics_shared_examples.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+shared_examples_for 'UpdateProjectStatistics' do
+ let(:project) { subject.project }
+ let(:project_statistics_name) { described_class.project_statistics_name }
+ let(:statistic_attribute) { described_class.statistic_attribute }
+
+ def reload_stat
+ project.statistics.reload.send(project_statistics_name).to_i
+ end
+
+ def read_attribute
+ subject.read_attribute(statistic_attribute).to_i
+ end
+
+ it { is_expected.to be_new_record }
+
+ context 'when creating' do
+ it 'updates the project statistics' do
+ delta = read_attribute
+
+ expect { subject.save! }
+ .to change { reload_stat }
+ .by(delta)
+ end
+ end
+
+ context 'when updating' do
+ before do
+ subject.save!
+ end
+
+ it 'updates project statistics' do
+ delta = 42
+
+ expect(ProjectStatistics)
+ .to receive(:increment_statistic)
+ .and_call_original
+
+ subject.write_attribute(statistic_attribute, read_attribute + delta)
+
+ expect { subject.save! }
+ .to change { reload_stat }
+ .by(delta)
+ end
+ end
+
+ context 'when destroying' do
+ before do
+ subject.save!
+ end
+
+ it 'updates the project statistics' do
+ delta = -read_attribute
+
+ expect(ProjectStatistics)
+ .to receive(:increment_statistic)
+ .and_call_original
+
+ expect { subject.destroy }
+ .to change { reload_stat }
+ .by(delta)
+ end
+
+ context 'when it is destroyed from the project level' do
+ it 'does not update the project statistics' do
+ expect(ProjectStatistics)
+ .not_to receive(:increment_statistic)
+
+ project.update(pending_delete: true)
+ project.destroy!
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/notify_shared_examples.rb b/spec/support/shared_examples/notify_shared_examples.rb
index 4fff1c4e228..897c9106d77 100644
--- a/spec/support/shared_examples/notify_shared_examples.rb
+++ b/spec/support/shared_examples/notify_shared_examples.rb
@@ -1,5 +1,7 @@
shared_context 'gitlab email notification' do
- set(:project) { create(:project, :repository, name: 'a-known-name') }
+ set(:group) { create(:group) }
+ set(:subgroup) { create(:group, parent: group) }
+ set(:project) { create(:project, :repository, name: 'a-known-name', group: group) }
set(:recipient) { create(:user, email: 'recipient@example.com') }
let(:gitlab_sender_display_name) { Gitlab.config.gitlab.email_display_name }
@@ -39,6 +41,47 @@ shared_examples 'an email sent from GitLab' do
end
end
+shared_examples 'an email sent to a user' do
+ let(:group_notification_email) { 'user+group@example.com' }
+
+ it 'is sent to user\'s global notification email address' do
+ expect(subject).to deliver_to(test_recipient.notification_email)
+ end
+
+ context 'that is part of a project\'s group' do
+ it 'is sent to user\'s group notification email address when set' do
+ create(:notification_setting, user: test_recipient, source: project.group, notification_email: group_notification_email)
+ expect(subject).to deliver_to(group_notification_email)
+ end
+
+ it 'is sent to user\'s global notification email address when no group email set' do
+ create(:notification_setting, user: test_recipient, source: project.group, notification_email: '')
+ expect(subject).to deliver_to(test_recipient.notification_email)
+ end
+ end
+
+ context 'when project is in a sub-group', :nested_groups do
+ before do
+ project.update!(group: subgroup)
+ end
+
+ it 'is sent to user\'s subgroup notification email address when set' do
+ # Set top-level group notification email address to make sure it doesn't get selected
+ create(:notification_setting, user: test_recipient, source: group, notification_email: group_notification_email)
+
+ subgroup_notification_email = 'user+subgroup@example.com'
+ create(:notification_setting, user: test_recipient, source: subgroup, notification_email: subgroup_notification_email)
+
+ expect(subject).to deliver_to(subgroup_notification_email)
+ end
+
+ it 'is sent to user\'s group notification email address when set and subgroup email address not set' do
+ create(:notification_setting, user: test_recipient, source: subgroup, notification_email: '')
+ expect(subject).to deliver_to(test_recipient.notification_email)
+ end
+ end
+end
+
shared_examples 'an email that contains a header with author username' do
it 'has X-GitLab-Author header containing author\'s username' do
is_expected.to have_header 'X-GitLab-Author', user.username
diff --git a/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb
index e0d0b790a0e..a79a61bc708 100644
--- a/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb
+++ b/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
shared_examples 'close quick action' do |issuable_type|
+ include Spec::Support::Helpers::Features::NotesHelpers
+
before do
project.add_maintainer(maintainer)
gitlab_sign_in(maintainer)
@@ -76,10 +78,7 @@ shared_examples 'close quick action' do |issuable_type|
it 'explains close quick action' do
visit public_send("project_#{issuable_type}_path", project, issuable)
- page.within('.js-main-target-form') do
- fill_in 'note[note]', with: "this is done, close\n/close"
- click_on 'Preview'
-
+ preview_note("this is done, close\n/close") do
expect(page).not_to have_content '/close'
expect(page).to have_content 'this is done, close'
expect(page).to have_content "Closes this #{issuable_type.to_s.humanize.downcase}."
diff --git a/spec/support/shared_examples/quick_actions/issuable/shrug_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/shrug_quick_action_shared_examples.rb
index 0a526808585..b592cf16f67 100644
--- a/spec/support/shared_examples/quick_actions/issuable/shrug_quick_action_shared_examples.rb
+++ b/spec/support/shared_examples/quick_actions/issuable/shrug_quick_action_shared_examples.rb
@@ -27,7 +27,7 @@ shared_examples 'shrug quick action' do |issuable_type|
expect(issuable.description).to eq "bug description\noops ¯\\_(ツ)_/¯"
expect(page).to have_content 'bug 345'
- expect(page).to have_content "bug description\noops ¯\\_(ツ)_/¯"
+ expect(page).to have_content "bug description oops ¯\\_(ツ)_/¯"
end
end
diff --git a/spec/support/shared_examples/quick_actions/issuable/tableflip_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/tableflip_quick_action_shared_examples.rb
index ef831e39872..c174127c4ff 100644
--- a/spec/support/shared_examples/quick_actions/issuable/tableflip_quick_action_shared_examples.rb
+++ b/spec/support/shared_examples/quick_actions/issuable/tableflip_quick_action_shared_examples.rb
@@ -27,7 +27,7 @@ shared_examples 'tableflip quick action' do |issuable_type|
expect(issuable.description).to eq "bug description\noops (╯°□°)╯︵ â”»â”â”»"
expect(page).to have_content 'bug 345'
- expect(page).to have_content "bug description\noops (╯°□°)╯︵ â”»â”â”»"
+ expect(page).to have_content "bug description oops (╯°□°)╯︵ â”»â”â”»"
end
end
diff --git a/spec/support/shared_examples/quick_actions/issue/remove_due_date_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/remove_due_date_quick_action_shared_examples.rb
index dd1676a08e2..657c2a60d24 100644
--- a/spec/support/shared_examples/quick_actions/issue/remove_due_date_quick_action_shared_examples.rb
+++ b/spec/support/shared_examples/quick_actions/issue/remove_due_date_quick_action_shared_examples.rb
@@ -11,7 +11,7 @@ shared_examples 'remove_due_date quick action' do
visit project_issue_path(project, issue)
page.within '.due_date' do
- expect(page).to have_content 'No due date'
+ expect(page).to have_content 'None'
end
end
end
diff --git a/spec/support/shared_examples/requests/api/discussions.rb b/spec/support/shared_examples/requests/api/discussions.rb
index eff8e401bad..c3132c41f5b 100644
--- a/spec/support/shared_examples/requests/api/discussions.rb
+++ b/spec/support/shared_examples/requests/api/discussions.rb
@@ -1,4 +1,4 @@
-shared_examples 'discussions API' do |parent_type, noteable_type, id_name|
+shared_examples 'discussions API' do |parent_type, noteable_type, id_name, can_reply_to_individual_notes: false|
describe "GET /#{parent_type}/:id/#{noteable_type}/:noteable_id/discussions" do
it "returns an array of discussions" do
get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions", user)
@@ -136,13 +136,25 @@ shared_examples 'discussions API' do |parent_type, noteable_type, id_name|
expect(response).to have_gitlab_http_status(400)
end
- it "returns a 400 bad request error if discussion is individual note" do
- note.update_attribute(:type, nil)
+ context 'when the discussion is an individual note' do
+ before do
+ note.update!(type: nil)
- post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
- "discussions/#{note.discussion_id}/notes", user), params: { body: 'hi!' }
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
+ "discussions/#{note.discussion_id}/notes", user), params: { body: 'hi!' }
+ end
- expect(response).to have_gitlab_http_status(400)
+ if can_reply_to_individual_notes
+ it 'creates a new discussion' do
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['body']).to eq('hi!')
+ expect(json_response['type']).to eq('DiscussionNote')
+ end
+ else
+ it 'returns 400 bad request' do
+ expect(response).to have_gitlab_http_status(400)
+ end
+ end
end
end
diff --git a/spec/support/shared_examples/requests/api/issues_shared_examples.rb b/spec/support/shared_examples/requests/api/issues_shared_examples.rb
new file mode 100644
index 00000000000..1133e95e44e
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/issues_shared_examples.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+shared_examples 'labeled issues with labels and label_name params' do
+ shared_examples 'returns label names' do
+ it 'returns label names' do
+ expect_paginated_array_response(issue.id)
+ expect(json_response.first['labels']).to eq([label_c.title, label_b.title, label.title])
+ end
+ end
+
+ shared_examples 'returns basic label entity' do
+ it 'returns basic label entity' do
+ expect_paginated_array_response(issue.id)
+ expect(json_response.first['labels'].pluck('name')).to eq([label_c.title, label_b.title, label.title])
+ expect(json_response.first['labels'].first).to match_schema('/public_api/v4/label_basic')
+ end
+ end
+
+ context 'array of labeled issues when all labels match' do
+ let(:params) { { labels: "#{label.title},#{label_b.title},#{label_c.title}" } }
+
+ it_behaves_like 'returns label names'
+ end
+
+ context 'array of labeled issues when all labels match with labels param as array' do
+ let(:params) { { labels: [label.title, label_b.title, label_c.title] } }
+
+ it_behaves_like 'returns label names'
+ end
+
+ context 'when with_labels_details provided' do
+ context 'array of labeled issues when all labels match' do
+ let(:params) { { labels: "#{label.title},#{label_b.title},#{label_c.title}", with_labels_details: true } }
+
+ it_behaves_like 'returns basic label entity'
+ end
+
+ context 'array of labeled issues when all labels match with labels param as array' do
+ let(:params) { { labels: [label.title, label_b.title, label_c.title], with_labels_details: true } }
+
+ it_behaves_like 'returns basic label entity'
+ end
+ end
+end
diff --git a/spec/support/shared_examples/slack_mattermost_notifications_shared_examples.rb b/spec/support/shared_examples/slack_mattermost_notifications_shared_examples.rb
index 940c24c8d67..36c486dbdd6 100644
--- a/spec/support/shared_examples/slack_mattermost_notifications_shared_examples.rb
+++ b/spec/support/shared_examples/slack_mattermost_notifications_shared_examples.rb
@@ -106,6 +106,14 @@ RSpec.shared_examples 'slack or mattermost notifications' do
expect(WebMock).to have_requested(:post, webhook_url).once
end
+ it "calls Slack/Mattermost API for deployment events" do
+ deployment_event_data = { object_kind: 'deployment' }
+
+ chat_service.execute(deployment_event_data)
+
+ expect(WebMock).to have_requested(:post, webhook_url).once
+ end
+
it 'uses the username as an option for slack when configured' do
allow(chat_service).to receive(:username).and_return(username)
@@ -267,7 +275,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do
it 'does not notify push events if they are not for the default branch' do
ref = "#{Gitlab::Git::BRANCH_REF_PREFIX}test"
- push_sample_data = Gitlab::DataBuilder::Push.build(project, user, nil, nil, ref, [])
+ push_sample_data = Gitlab::DataBuilder::Push.build(project: project, user: user, ref: ref)
chat_service.execute(push_sample_data)
@@ -284,7 +292,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do
it 'still notifies about pushed tags' do
ref = "#{Gitlab::Git::TAG_REF_PREFIX}test"
- push_sample_data = Gitlab::DataBuilder::Push.build(project, user, nil, nil, ref, [])
+ push_sample_data = Gitlab::DataBuilder::Push.build(project: project, user: user, ref: ref)
chat_service.execute(push_sample_data)
@@ -299,7 +307,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do
it 'notifies about all push events' do
ref = "#{Gitlab::Git::BRANCH_REF_PREFIX}test"
- push_sample_data = Gitlab::DataBuilder::Push.build(project, user, nil, nil, ref, [])
+ push_sample_data = Gitlab::DataBuilder::Push.build(project: project, user: user, ref: ref)
chat_service.execute(push_sample_data)
diff --git a/spec/support/shoulda/matchers/rails_shim.rb b/spec/support/shoulda/matchers/rails_shim.rb
deleted file mode 100644
index 8d70598beb5..00000000000
--- a/spec/support/shoulda/matchers/rails_shim.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# monkey patch which fixes serialization matcher in Rails 5
-# https://github.com/thoughtbot/shoulda-matchers/issues/913
-# This can be removed when a new version of shoulda-matchers
-# is released
-module Shoulda
- module Matchers
- class RailsShim
- def self.serialized_attributes_for(model)
- if defined?(::ActiveRecord::Type::Serialized)
- # Rails 5+
- serialized_columns = model.columns.select do |column|
- model.type_for_attribute(column.name).is_a?(
- ::ActiveRecord::Type::Serialized
- )
- end
-
- serialized_columns.inject({}) do |hash, column| # rubocop:disable Style/EachWithObject
- hash[column.name.to_s] = model.type_for_attribute(column.name).coder
- hash
- end
- else
- model.serialized_attributes
- end
- end
- end
- end
-end
diff --git a/spec/tasks/gitlab/artifacts/migrate_rake_spec.rb b/spec/tasks/gitlab/artifacts/migrate_rake_spec.rb
index 8544fb62b5a..be69c10d7c8 100644
--- a/spec/tasks/gitlab/artifacts/migrate_rake_spec.rb
+++ b/spec/tasks/gitlab/artifacts/migrate_rake_spec.rb
@@ -13,61 +13,6 @@ describe 'gitlab:artifacts namespace rake task' do
subject { run_rake_task('gitlab:artifacts:migrate') }
- context 'legacy artifacts' do
- describe 'migrate' do
- let!(:build) { create(:ci_build, :legacy_artifacts, artifacts_file_store: store, artifacts_metadata_store: store) }
-
- context 'when local storage is used' do
- let(:store) { ObjectStorage::Store::LOCAL }
-
- context 'and job does not have file store defined' do
- let(:object_storage_enabled) { true }
- let(:store) { nil }
-
- it "migrates file to remote storage" do
- subject
-
- expect(build.reload.artifacts_file_store).to eq(ObjectStorage::Store::REMOTE)
- expect(build.reload.artifacts_metadata_store).to eq(ObjectStorage::Store::REMOTE)
- end
- end
-
- context 'and remote storage is defined' do
- let(:object_storage_enabled) { true }
-
- it "migrates file to remote storage" do
- subject
-
- expect(build.reload.artifacts_file_store).to eq(ObjectStorage::Store::REMOTE)
- expect(build.reload.artifacts_metadata_store).to eq(ObjectStorage::Store::REMOTE)
- end
- end
-
- context 'and remote storage is not defined' do
- it "fails to migrate to remote storage" do
- subject
-
- expect(build.reload.artifacts_file_store).to eq(ObjectStorage::Store::LOCAL)
- expect(build.reload.artifacts_metadata_store).to eq(ObjectStorage::Store::LOCAL)
- end
- end
- end
-
- context 'when remote storage is used' do
- let(:object_storage_enabled) { true }
-
- let(:store) { ObjectStorage::Store::REMOTE }
-
- it "file stays on remote storage" do
- subject
-
- expect(build.reload.artifacts_file_store).to eq(ObjectStorage::Store::REMOTE)
- expect(build.reload.artifacts_metadata_store).to eq(ObjectStorage::Store::REMOTE)
- end
- end
- end
- end
-
context 'job artifacts' do
let!(:artifact) { create(:ci_job_artifact, :archive, file_store: store) }
diff --git a/spec/tasks/gitlab/shell_rake_spec.rb b/spec/tasks/gitlab/shell_rake_spec.rb
index a9d14070177..c3e912b02c5 100644
--- a/spec/tasks/gitlab/shell_rake_spec.rb
+++ b/spec/tasks/gitlab/shell_rake_spec.rb
@@ -7,14 +7,8 @@ describe 'gitlab:shell rake tasks' do
stub_warn_user_is_not_gitlab
end
- after do
- TestEnv.sabotage_gitlab_shell_hooks
- end
-
describe 'install task' do
- it 'invokes create_hooks task' do
- expect(Rake::Task['gitlab:shell:create_hooks']).to receive(:invoke)
-
+ it 'installs and compiles gitlab-shell' do
storages = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
Gitlab.config.repositories.storages.values.map(&:legacy_disk_path)
end
@@ -24,14 +18,4 @@ describe 'gitlab:shell rake tasks' do
run_rake_task('gitlab:shell:install')
end
end
-
- describe 'create_hooks task' do
- it 'calls gitlab-shell bin/create_hooks' do
- expect_any_instance_of(Object).to receive(:system)
- .with("#{Gitlab.config.gitlab_shell.path}/bin/create-hooks",
- *Gitlab::TaskHelpers.repository_storage_paths_args)
-
- run_rake_task('gitlab:shell:create_hooks')
- end
- end
end
diff --git a/spec/tasks/tokens_spec.rb b/spec/tasks/tokens_spec.rb
index 555a58e9aa1..4188e7caccb 100644
--- a/spec/tasks/tokens_spec.rb
+++ b/spec/tasks/tokens_spec.rb
@@ -8,13 +8,13 @@ describe 'tokens rake tasks' do
end
describe 'reset_all_email task' do
- it 'invokes create_hooks task' do
+ it 'changes the incoming email token' do
expect { run_rake_task('tokens:reset_all_email') }.to change { user.reload.incoming_email_token }
end
end
describe 'reset_all_feed task' do
- it 'invokes create_hooks task' do
+ it 'changes the feed token for the user' do
expect { run_rake_task('tokens:reset_all_feed') }.to change { user.reload.feed_token }
end
end
diff --git a/spec/uploaders/import_export_uploader_spec.rb b/spec/uploaders/import_export_uploader_spec.rb
index 825c1cabc14..2dea48e3a88 100644
--- a/spec/uploaders/import_export_uploader_spec.rb
+++ b/spec/uploaders/import_export_uploader_spec.rb
@@ -3,9 +3,18 @@ require 'spec_helper'
describe ImportExportUploader do
let(:model) { build_stubbed(:import_export_upload) }
let(:upload) { create(:upload, model: model) }
+ let(:import_export_upload) { ImportExportUpload.new }
subject { described_class.new(model, :import_file) }
+ context 'local store' do
+ describe '#move_to_store' do
+ it 'returns true' do
+ expect(subject.move_to_store).to be true
+ end
+ end
+ end
+
context "object_store is REMOTE" do
before do
stub_uploads_object_storage
@@ -16,5 +25,28 @@ describe ImportExportUploader do
it_behaves_like 'builds correct paths',
store_dir: %r[import_export_upload/import_file/],
upload_path: %r[import_export_upload/import_file/]
+
+ describe '#move_to_store' do
+ it 'returns false' do
+ expect(subject.move_to_store).to be false
+ end
+ end
+
+ describe 'with an export file directly uploaded' do
+ let(:tempfile) { Tempfile.new(['test', '.gz']) }
+
+ before do
+ stub_uploads_object_storage(described_class, direct_upload: true)
+ import_export_upload.export_file = tempfile
+ end
+
+ it 'cleans up cached file' do
+ cache_dir = File.join(import_export_upload.export_file.cache_path(nil), '*')
+
+ import_export_upload.save!
+
+ expect(Dir[cache_dir]).to be_empty
+ end
+ end
end
end
diff --git a/spec/uploaders/legacy_artifact_uploader_spec.rb b/spec/uploaders/legacy_artifact_uploader_spec.rb
deleted file mode 100644
index 0589563b502..00000000000
--- a/spec/uploaders/legacy_artifact_uploader_spec.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-require 'rails_helper'
-
-describe LegacyArtifactUploader do
- let(:store) { described_class::Store::LOCAL }
- let(:job) { create(:ci_build, artifacts_file_store: store) }
- let(:uploader) { described_class.new(job, :legacy_artifacts_file) }
- let(:local_path) { described_class.root }
-
- subject { uploader }
-
- # TODO: move to Workhorse::UploadPath
- describe '.workhorse_upload_path' do
- subject { described_class.workhorse_upload_path }
-
- it { is_expected.to start_with(local_path) }
- it { is_expected.to end_with('tmp/uploads') }
- end
-
- it_behaves_like "builds correct paths",
- store_dir: %r[\d{4}_\d{1,2}/\d+/\d+\z],
- cache_dir: %r[artifacts/tmp/cache],
- work_dir: %r[artifacts/tmp/work]
-
- context 'object store is remote' do
- before do
- stub_artifacts_object_storage
- end
-
- include_context 'with storage', described_class::Store::REMOTE
-
- it_behaves_like "builds correct paths",
- store_dir: %r[\d{4}_\d{1,2}/\d+/\d+\z]
- end
-
- describe '#filename' do
- # we need to use uploader, as this makes to use mounter
- # which initialises uploader.file object
- let(:uploader) { job.artifacts_file }
-
- subject { uploader.filename }
-
- it { is_expected.to be_nil }
- end
-
- context 'file is stored in valid path' do
- let(:file) do
- fixture_file_upload('spec/fixtures/ci_build_artifacts.zip', 'application/zip')
- end
-
- before do
- uploader.store!(file)
- end
-
- subject { uploader.file.path }
-
- it { is_expected.to start_with("#{uploader.root}") }
- it { is_expected.to include("/#{job.created_at.utc.strftime('%Y_%m')}/") }
- it { is_expected.to include("/#{job.project_id}/") }
- it { is_expected.to end_with("ci_build_artifacts.zip") }
- end
-end
diff --git a/spec/uploaders/object_storage_spec.rb b/spec/uploaders/object_storage_spec.rb
index 9ce9a353913..6bad5d49b1c 100644
--- a/spec/uploaders/object_storage_spec.rb
+++ b/spec/uploaders/object_storage_spec.rb
@@ -12,7 +12,7 @@ class Implementation < GitlabUploader
# user/:id
def dynamic_segment
- File.join(model.class.to_s.underscore, model.id.to_s)
+ File.join(model.class.underscore, model.id.to_s)
end
end
@@ -771,6 +771,14 @@ describe ObjectStorage do
expect { avatars }.not_to exceed_query_limit(1)
end
+ it 'does not attempt to replace methods' do
+ models.each do |model|
+ expect(model.avatar.upload).to receive(:method_missing).and_call_original
+
+ model.avatar.upload.path
+ end
+ end
+
it 'fetches a unique upload for each model' do
expect(avatars.map(&:url).uniq).to eq(avatars.map(&:url))
expect(avatars.map(&:upload).uniq).to eq(avatars.map(&:upload))
diff --git a/spec/uploaders/personal_file_uploader_spec.rb b/spec/uploaders/personal_file_uploader_spec.rb
index 97758f0243e..d9f0e2f3cb7 100644
--- a/spec/uploaders/personal_file_uploader_spec.rb
+++ b/spec/uploaders/personal_file_uploader_spec.rb
@@ -7,33 +7,19 @@ describe PersonalFileUploader do
subject { uploader }
- it_behaves_like 'builds correct paths',
- store_dir: %r[uploads/-/system/personal_snippet/\d+],
- upload_path: %r[\h+/\S+],
- absolute_path: %r[#{CarrierWave.root}/uploads/-/system/personal_snippet\/\d+\/\h+\/\S+$]
-
- context "object_store is REMOTE" do
+ shared_examples '#base_dir' do
before do
- stub_uploads_object_storage
+ subject.instance_variable_set(:@secret, 'secret')
end
- include_context 'with storage', described_class::Store::REMOTE
-
- it_behaves_like 'builds correct paths',
- store_dir: %r[\d+/\h+],
- upload_path: %r[^personal_snippet\/\d+\/\h+\/<filename>]
- end
-
- describe '#upload_paths' do
- it 'builds correct paths for both local and remote storage' do
- paths = uploader.upload_paths('test.jpg')
+ it 'is prefixed with uploads/-/system' do
+ allow(uploader).to receive(:file).and_return(double(extension: 'txt', filename: 'file_name'))
- expect(paths.first).to match(%r[\h+\/test.jpg])
- expect(paths.second).to match(%r[^personal_snippet\/\d+\/\h+\/test.jpg])
+ expect(described_class.base_dir(model)).to eq("uploads/-/system/personal_snippet/#{model.id}")
end
end
- describe '#to_h' do
+ shared_examples '#to_h' do
before do
subject.instance_variable_set(:@secret, 'secret')
end
@@ -50,6 +36,40 @@ describe PersonalFileUploader do
end
end
+ describe '#upload_paths' do
+ it 'builds correct paths for both local and remote storage' do
+ paths = uploader.upload_paths('test.jpg')
+
+ expect(paths.first).to match(%r[\h+\/test.jpg])
+ expect(paths.second).to match(%r[^personal_snippet\/\d+\/\h+\/test.jpg])
+ end
+ end
+
+ context 'object_store is LOCAL' do
+ it_behaves_like 'builds correct paths',
+ store_dir: %r[uploads/-/system/personal_snippet/\d+/\h+],
+ upload_path: %r[\h+/\S+],
+ absolute_path: %r[#{CarrierWave.root}/uploads/-/system/personal_snippet\/\d+\/\h+\/\S+$]
+
+ it_behaves_like '#base_dir'
+ it_behaves_like '#to_h'
+ end
+
+ context "object_store is REMOTE" do
+ before do
+ stub_uploads_object_storage
+ end
+
+ include_context 'with storage', described_class::Store::REMOTE
+
+ it_behaves_like 'builds correct paths',
+ store_dir: %r[\d+/\h+],
+ upload_path: %r[^personal_snippet\/\d+\/\h+\/<filename>]
+
+ it_behaves_like '#base_dir'
+ it_behaves_like '#to_h'
+ end
+
describe "#migrate!" do
before do
uploader.store!(fixture_file_upload('spec/fixtures/doc_sample.txt'))
diff --git a/spec/uploaders/workers/object_storage/background_move_worker_spec.rb b/spec/uploaders/workers/object_storage/background_move_worker_spec.rb
index 95813d15e52..cc8970d2ba0 100644
--- a/spec/uploaders/workers/object_storage/background_move_worker_spec.rb
+++ b/spec/uploaders/workers/object_storage/background_move_worker_spec.rb
@@ -48,40 +48,6 @@ describe ObjectStorage::BackgroundMoveWorker do
end
end
- context 'for legacy artifacts' do
- let(:build) { create(:ci_build, :legacy_artifacts) }
- let(:uploader_class) { LegacyArtifactUploader }
- let(:subject_class) { Ci::Build }
- let(:file_field) { :artifacts_file }
- let(:subject_id) { build.id }
-
- context 'when local storage is used' do
- let(:store) { local }
-
- context 'and remote storage is defined' do
- before do
- stub_artifacts_object_storage(background_upload: true)
- end
-
- it "migrates file to remote storage" do
- perform
-
- expect(build.reload.artifacts_file_store).to eq(remote)
- end
-
- context 'for artifacts_metadata' do
- let(:file_field) { :artifacts_metadata }
-
- it 'migrates metadata to remote storage' do
- perform
-
- expect(build.reload.artifacts_metadata_store).to eq(remote)
- end
- end
- end
- end
- end
-
context 'for job artifacts' do
let(:artifact) { create(:ci_job_artifact, :archive) }
let(:uploader_class) { JobArtifactUploader }
diff --git a/spec/views/help/index.html.haml_spec.rb b/spec/views/help/index.html.haml_spec.rb
index 34e93d929a7..257991549a9 100644
--- a/spec/views/help/index.html.haml_spec.rb
+++ b/spec/views/help/index.html.haml_spec.rb
@@ -31,7 +31,7 @@ describe 'help/index' do
render
expect(rendered).to match '8.0.2'
- expect(rendered).to have_link('8.0.2', href: %r{https://gitlab.com/gitlab-org/gitlab-(ce|ee)/tags/v8.0.2})
+ expect(rendered).to have_link('8.0.2', href: %r{https://gitlab.com/gitlab-org/gitlab-(ce|ee)/-/tags/v8.0.2})
end
it 'shows a link to the commit for pre-releases' do
diff --git a/spec/views/notify/pipeline_failed_email.html.haml_spec.rb b/spec/views/notify/pipeline_failed_email.html.haml_spec.rb
index d9d73f789c5..d04affc7df1 100644
--- a/spec/views/notify/pipeline_failed_email.html.haml_spec.rb
+++ b/spec/views/notify/pipeline_failed_email.html.haml_spec.rb
@@ -28,7 +28,7 @@ describe 'notify/pipeline_failed_email.html.haml' do
expect(rendered).to have_content "Your pipeline has failed"
expect(rendered).to have_content pipeline.project.name
- expect(rendered).to have_content pipeline.git_commit_message.truncate(50)
+ expect(rendered).to have_content pipeline.git_commit_message.truncate(50).gsub!(/\s+/, ' ')
expect(rendered).to have_content pipeline.commit.author_name
expect(rendered).to have_content "##{pipeline.id}"
expect(rendered).to have_content pipeline.user.name
@@ -45,7 +45,7 @@ describe 'notify/pipeline_failed_email.html.haml' do
expect(rendered).to have_content "Your pipeline has failed"
expect(rendered).to have_content pipeline.project.name
- expect(rendered).to have_content pipeline.git_commit_message.truncate(50)
+ expect(rendered).to have_content pipeline.git_commit_message.truncate(50).gsub!(/\s+/, ' ')
expect(rendered).to have_content pipeline.commit.author_name
expect(rendered).to have_content "##{pipeline.id}"
expect(rendered).to have_content "by API"
diff --git a/spec/views/notify/pipeline_failed_email.text.erb_spec.rb b/spec/views/notify/pipeline_failed_email.text.erb_spec.rb
new file mode 100644
index 00000000000..079fb865d7b
--- /dev/null
+++ b/spec/views/notify/pipeline_failed_email.text.erb_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe 'notify/pipeline_failed_email.text.erb' do
+ include Devise::Test::ControllerHelpers
+
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:merge_request) { create(:merge_request, :simple, source_project: project) }
+
+ let(:pipeline) do
+ create(:ci_pipeline,
+ :failed,
+ project: project,
+ user: user,
+ ref: project.default_branch,
+ sha: project.commit.sha)
+ end
+
+ before do
+ assign(:project, project)
+ assign(:pipeline, pipeline)
+ assign(:merge_request, merge_request)
+ end
+
+ it 'renders the email correctly' do
+ job = create(:ci_build, :failed, pipeline: pipeline, project: pipeline.project)
+
+ render
+
+ expect(rendered).to have_content('Your pipeline has failed')
+ expect(rendered).to have_content(pipeline.project.name)
+ expect(rendered).to have_content(pipeline.git_commit_message.truncate(50).gsub!(/\s+/, ' '))
+ expect(rendered).to have_content(pipeline.commit.author_name)
+ expect(rendered).to have_content("##{pipeline.id}")
+ expect(rendered).to have_content(pipeline.user.name)
+ expect(rendered).to have_content("/-/jobs/#{job.id}/raw")
+ end
+end
diff --git a/spec/views/notify/pipeline_success_email.html.haml_spec.rb b/spec/views/notify/pipeline_success_email.html.haml_spec.rb
index a793b37e412..8ee7f954d70 100644
--- a/spec/views/notify/pipeline_success_email.html.haml_spec.rb
+++ b/spec/views/notify/pipeline_success_email.html.haml_spec.rb
@@ -28,7 +28,7 @@ describe 'notify/pipeline_success_email.html.haml' do
expect(rendered).to have_content "Your pipeline has passed"
expect(rendered).to have_content pipeline.project.name
- expect(rendered).to have_content pipeline.git_commit_message.truncate(50)
+ expect(rendered).to have_content pipeline.git_commit_message.truncate(50).gsub!(/\s+/, ' ')
expect(rendered).to have_content pipeline.commit.author_name
expect(rendered).to have_content "##{pipeline.id}"
expect(rendered).to have_content pipeline.user.name
@@ -45,7 +45,7 @@ describe 'notify/pipeline_success_email.html.haml' do
expect(rendered).to have_content "Your pipeline has passed"
expect(rendered).to have_content pipeline.project.name
- expect(rendered).to have_content pipeline.git_commit_message.truncate(50)
+ expect(rendered).to have_content pipeline.git_commit_message.truncate(50).gsub!(/\s+/, ' ')
expect(rendered).to have_content pipeline.commit.author_name
expect(rendered).to have_content "##{pipeline.id}"
expect(rendered).to have_content "by API"
diff --git a/spec/views/profiles/show.html.haml_spec.rb b/spec/views/profiles/show.html.haml_spec.rb
index e89a8cb9626..9e7ac0b84fa 100644
--- a/spec/views/profiles/show.html.haml_spec.rb
+++ b/spec/views/profiles/show.html.haml_spec.rb
@@ -12,8 +12,8 @@ describe 'profiles/show' do
it 'displays the correct elements' do
render
- expect(rendered).to have_field('user_name', user.name)
- expect(rendered).to have_field('user_id', user.id)
+ expect(rendered).to have_field('user_name', with: user.name)
+ expect(rendered).to have_field('user_id', with: user.id)
end
end
end
diff --git a/spec/views/projects/commit/_commit_box.html.haml_spec.rb b/spec/views/projects/commit/_commit_box.html.haml_spec.rb
index 1086546c10d..457dd2e940f 100644
--- a/spec/views/projects/commit/_commit_box.html.haml_spec.rb
+++ b/spec/views/projects/commit/_commit_box.html.haml_spec.rb
@@ -27,7 +27,7 @@ describe 'projects/commit/_commit_box.html.haml' do
render
- expect(rendered).to have_text("Pipeline ##{third_pipeline.id} failed")
+ expect(rendered).to have_text("Pipeline ##{third_pipeline.id} (##{third_pipeline.iid}) failed")
end
end
@@ -40,7 +40,7 @@ describe 'projects/commit/_commit_box.html.haml' do
it 'shows correct pipeline description' do
render
- expect(rendered).to have_text "Pipeline ##{pipeline.id} " \
+ expect(rendered).to have_text "Pipeline ##{pipeline.id} (##{pipeline.iid}) " \
'waiting for manual action'
end
end
diff --git a/spec/views/projects/issues/_merge_requests_status.html.haml_spec.rb b/spec/views/projects/issues/_merge_requests_status.html.haml_spec.rb
deleted file mode 100644
index 9424795749d..00000000000
--- a/spec/views/projects/issues/_merge_requests_status.html.haml_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-require 'spec_helper'
-
-describe 'projects/issues/_merge_requests_status.html.haml' do
- around do |ex|
- Timecop.freeze(Date.new(2018, 7, 22)) do
- ex.run
- end
- end
-
- it 'shows date of status change in tooltip' do
- merge_request = create(:merge_request, created_at: 1.month.ago)
-
- render partial: 'projects/issues/merge_requests_status',
- locals: { merge_request: merge_request, css_class: '' }
-
- expect(rendered).to match("Opened.*about 1 month ago")
- end
-
- it 'shows only status in tooltip if date is not set' do
- merge_request = create(:merge_request, state: :closed)
-
- render partial: 'projects/issues/merge_requests_status',
- locals: { merge_request: merge_request, css_class: '' }
-
- expect(rendered).to match("Closed")
- end
-end
diff --git a/spec/views/projects/issues/show.html.haml_spec.rb b/spec/views/projects/issues/show.html.haml_spec.rb
index 1d9c6d36ad7..1ca9eaf8fdb 100644
--- a/spec/views/projects/issues/show.html.haml_spec.rb
+++ b/spec/views/projects/issues/show.html.haml_spec.rb
@@ -19,6 +19,7 @@ describe 'projects/issues/show' do
context 'when the issue is closed' do
before do
allow(issue).to receive(:closed?).and_return(true)
+ allow(view).to receive(:current_user).and_return(user)
end
context 'when the issue was moved' do
@@ -28,16 +29,30 @@ describe 'projects/issues/show' do
issue.moved_to = new_issue
end
- it 'shows "Closed (moved)" if an issue has been moved' do
- render
+ context 'when user can see the moved issue' do
+ before do
+ project.add_developer(user)
+ end
- expect(rendered).to have_selector('.status-box-issue-closed:not(.hidden)', text: 'Closed (moved)')
+ it 'shows "Closed (moved)" if an issue has been moved' do
+ render
+
+ expect(rendered).to have_selector('.status-box-issue-closed:not(.hidden)', text: 'Closed (moved)')
+ end
+
+ it 'links "moved" to the new issue the original issue was moved to' do
+ render
+
+ expect(rendered).to have_selector("a[href=\"#{issue_path(new_issue)}\"]", text: 'moved')
+ end
end
- it 'links "moved" to the new issue the original issue was moved to' do
- render
+ context 'when user cannot see moved issue' do
+ it 'does not show moved issue link' do
+ render
- expect(rendered).to have_selector("a[href=\"#{issue_path(new_issue)}\"]", text: 'moved')
+ expect(rendered).not_to have_selector("a[href=\"#{issue_path(new_issue)}\"]", text: 'moved')
+ end
end
end
diff --git a/spec/views/projects/jobs/_build.html.haml_spec.rb b/spec/views/projects/jobs/_build.html.haml_spec.rb
index 1d58891036e..97b25a6976f 100644
--- a/spec/views/projects/jobs/_build.html.haml_spec.rb
+++ b/spec/views/projects/jobs/_build.html.haml_spec.rb
@@ -4,7 +4,7 @@ describe 'projects/ci/jobs/_build' do
include Devise::Test::ControllerHelpers
let(:project) { create(:project, :repository) }
- let(:pipeline) { create(:ci_empty_pipeline, id: 1337, project: project, sha: project.commit.id) }
+ let(:pipeline) { create(:ci_empty_pipeline, id: 1337, iid: 57, project: project, sha: project.commit.id) }
let(:build) { create(:ci_build, pipeline: pipeline, stage: 'test', stage_idx: 1, name: 'rspec 0:2', status: :pending) }
before do
@@ -15,14 +15,14 @@ describe 'projects/ci/jobs/_build' do
it 'won\'t include a column with a link to its pipeline by default' do
render partial: 'projects/ci/builds/build', locals: { build: build }
- expect(rendered).not_to have_link('#1337')
- expect(rendered).not_to have_text('#1337 by API')
+ expect(rendered).not_to have_link('#1337 (#57)')
+ expect(rendered).not_to have_text('#1337 (#57) by API')
end
it 'can include a column with a link to its pipeline' do
render partial: 'projects/ci/builds/build', locals: { build: build, pipeline_link: true }
- expect(rendered).to have_link('#1337')
- expect(rendered).to have_text('#1337 by API')
+ expect(rendered).to have_link('#1337 (#57)')
+ expect(rendered).to have_text('#1337 (#57) by API')
end
end
diff --git a/spec/views/projects/notes/_more_actions_dropdown.html.haml_spec.rb b/spec/views/projects/notes/_more_actions_dropdown.html.haml_spec.rb
index 8a9ab02eaca..ae47f364296 100644
--- a/spec/views/projects/notes/_more_actions_dropdown.html.haml_spec.rb
+++ b/spec/views/projects/notes/_more_actions_dropdown.html.haml_spec.rb
@@ -12,10 +12,10 @@ describe 'projects/notes/_more_actions_dropdown' do
assign(:project, project)
end
- it 'shows Report abuse to GitLab button if not editable and not current users comment' do
+ it 'shows Report abuse to admin button if not editable and not current users comment' do
render 'projects/notes/more_actions_dropdown', current_user: not_author_user, note_editable: false, note: note
- expect(rendered).to have_link('Report abuse to GitLab')
+ expect(rendered).to have_link('Report abuse to admin')
end
it 'does not show the More actions button if not editable and current users comment' do
@@ -24,10 +24,10 @@ describe 'projects/notes/_more_actions_dropdown' do
expect(rendered).not_to have_selector('.dropdown.more-actions')
end
- it 'shows Report abuse to GitLab and Delete buttons if editable and not current users comment' do
+ it 'shows Report abuse to admin and Delete buttons if editable and not current users comment' do
render 'projects/notes/more_actions_dropdown', current_user: not_author_user, note_editable: true, note: note
- expect(rendered).to have_link('Report abuse to GitLab')
+ expect(rendered).to have_link('Report abuse to admin')
expect(rendered).to have_link('Delete comment')
end
diff --git a/spec/views/projects/tree/show.html.haml_spec.rb b/spec/views/projects/tree/show.html.haml_spec.rb
index 3b098320ad7..5bb0173ab89 100644
--- a/spec/views/projects/tree/show.html.haml_spec.rb
+++ b/spec/views/projects/tree/show.html.haml_spec.rb
@@ -7,6 +7,8 @@ describe 'projects/tree/show' do
let(:repository) { project.repository }
before do
+ stub_feature_flags(vue_file_list: false)
+
assign(:project, project)
assign(:repository, repository)
assign(:lfs_blob_ids, [])
diff --git a/spec/views/shared/_label_row.html.haml.rb b/spec/views/shared/_label_row.html.haml.rb
new file mode 100644
index 00000000000..a58d5efc1e3
--- /dev/null
+++ b/spec/views/shared/_label_row.html.haml.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe 'shared/_label_row.html.haml' do
+ label_types = {
+ 'project label': :label,
+ 'group label': :group_label
+ }
+
+ label_types.each do |label_type, label_factory|
+ let!(:label) { create(label_factory) }
+
+ context "for a #{label_type}" do
+ it 'has a non-linked label title' do
+ render 'shared/label_row', label: label
+
+ expect(rendered).not_to have_css('a', text: label.title)
+ end
+
+ it "has Issues link for #{label_type}" do
+ render 'shared/label_row', label: label
+
+ expect(rendered).to have_css('a', text: 'Issues')
+ end
+
+ it "has Merge request link for #{label_type}" do
+ render 'shared/label_row', label: label
+
+ expect(rendered).to have_css('a', text: 'Merge requests')
+ end
+ end
+ end
+end
diff --git a/spec/workers/auto_merge_process_worker_spec.rb b/spec/workers/auto_merge_process_worker_spec.rb
new file mode 100644
index 00000000000..616727ce5ca
--- /dev/null
+++ b/spec/workers/auto_merge_process_worker_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe AutoMergeProcessWorker do
+ describe '#perform' do
+ subject { described_class.new.perform(merge_request&.id) }
+
+ context 'when merge request is found' do
+ let(:merge_request) { create(:merge_request) }
+
+ it 'executes AutoMergeService' do
+ expect_next_instance_of(AutoMergeService) do |auto_merge|
+ expect(auto_merge).to receive(:process)
+ end
+
+ subject
+ end
+ end
+
+ context 'when merge request is not found' do
+ let(:merge_request) { nil }
+
+ it 'does not execute AutoMergeService' do
+ expect(AutoMergeService).not_to receive(:new)
+
+ subject
+ end
+ end
+ end
+end
diff --git a/spec/workers/build_finished_worker_spec.rb b/spec/workers/build_finished_worker_spec.rb
index 33f327d4a0c..4adb795b1d6 100644
--- a/spec/workers/build_finished_worker_spec.rb
+++ b/spec/workers/build_finished_worker_spec.rb
@@ -17,6 +17,7 @@ describe BuildFinishedWorker do
expect_any_instance_of(BuildCoverageWorker).to receive(:perform)
expect(BuildHooksWorker).to receive(:perform_async)
expect(ArchiveTraceWorker).to receive(:perform_async)
+ expect(ExpirePipelineCacheWorker).to receive(:perform_async)
described_class.new.perform(build.id)
end
diff --git a/spec/workers/build_success_worker_spec.rb b/spec/workers/build_success_worker_spec.rb
index 065aeaf2b65..ffe8796ded9 100644
--- a/spec/workers/build_success_worker_spec.rb
+++ b/spec/workers/build_success_worker_spec.rb
@@ -15,6 +15,7 @@ describe BuildSuccessWorker do
let!(:build) { create(:ci_build, :deploy_to_production) }
before do
+ allow(Deployments::FinishedWorker).to receive(:perform_async)
Deployment.delete_all
build.reload
end
diff --git a/spec/workers/cluster_configure_worker_spec.rb b/spec/workers/cluster_configure_worker_spec.rb
index 83f76809435..975088f3ee6 100644
--- a/spec/workers/cluster_configure_worker_spec.rb
+++ b/spec/workers/cluster_configure_worker_spec.rb
@@ -4,61 +4,58 @@ require 'spec_helper'
describe ClusterConfigureWorker, '#perform' do
let(:worker) { described_class.new }
- let(:ci_preparing_state_enabled) { false }
- before do
- stub_feature_flags(ci_preparing_state: ci_preparing_state_enabled)
- end
+ shared_examples 'configured cluster' do
+ it 'creates a namespace' do
+ expect(Clusters::RefreshService).to receive(:create_or_update_namespaces_for_cluster).with(cluster).once
- context 'when group cluster' do
- let(:cluster) { create(:cluster, :group, :provided_by_gcp) }
- let(:group) { cluster.group }
+ worker.perform(cluster.id)
+ end
+ end
- context 'when group has no projects' do
- it 'does not create a namespace' do
- expect_any_instance_of(Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService).not_to receive(:execute)
+ shared_examples 'unconfigured cluster' do
+ it 'does not create a namespace' do
+ expect(Clusters::RefreshService).not_to receive(:create_or_update_namespaces_for_cluster)
- worker.perform(cluster.id)
- end
+ worker.perform(cluster.id)
end
+ end
+
+ context 'group cluster' do
+ let(:cluster) { create(:cluster, :group, :provided_by_gcp) }
+ let(:group) { cluster.group }
context 'when group has a project' do
let!(:project) { create(:project, group: group) }
- it 'creates a namespace for the project' do
- expect_any_instance_of(Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService).to receive(:execute).once
-
- worker.perform(cluster.id)
- end
+ it_behaves_like 'unconfigured cluster'
end
context 'when group has project in a sub-group' do
let!(:subgroup) { create(:group, parent: group) }
let!(:project) { create(:project, group: subgroup) }
- it 'creates a namespace for the project' do
- expect_any_instance_of(Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService).to receive(:execute).once
-
- worker.perform(cluster.id)
- end
+ it_behaves_like 'unconfigured cluster'
end
end
context 'when provider type is gcp' do
- let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
-
- it 'configures kubernetes platform' do
- expect_any_instance_of(Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService).to receive(:execute)
+ let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- described_class.new.perform(cluster.id)
- end
+ it_behaves_like 'configured cluster'
end
context 'when provider type is user' do
- let(:cluster) { create(:cluster, :project, :provided_by_user) }
+ let!(:cluster) { create(:cluster, :project, :provided_by_user) }
+
+ it_behaves_like 'configured cluster'
+ end
- it 'configures kubernetes platform' do
- expect_any_instance_of(Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService).to receive(:execute)
+ context 'when cluster is not managed' do
+ let(:cluster) { create(:cluster, :not_managed) }
+
+ it 'does not configure the cluster' do
+ expect(Clusters::RefreshService).not_to receive(:create_or_update_namespaces_for_cluster)
described_class.new.perform(cluster.id)
end
@@ -71,15 +68,4 @@ describe ClusterConfigureWorker, '#perform' do
described_class.new.perform(123)
end
end
-
- context 'ci_preparing_state feature is enabled' do
- let(:cluster) { create(:cluster) }
- let(:ci_preparing_state_enabled) { true }
-
- it 'does not configure the cluster' do
- expect(Clusters::RefreshService).not_to receive(:create_or_update_namespaces_for_cluster)
-
- described_class.new.perform(cluster.id)
- end
- end
end
diff --git a/spec/workers/cluster_project_configure_worker_spec.rb b/spec/workers/cluster_project_configure_worker_spec.rb
index afdea55adf4..2ac9d0f61b4 100644
--- a/spec/workers/cluster_project_configure_worker_spec.rb
+++ b/spec/workers/cluster_project_configure_worker_spec.rb
@@ -4,18 +4,11 @@ require 'spec_helper'
describe ClusterProjectConfigureWorker, '#perform' do
let(:worker) { described_class.new }
+ let(:cluster) { create(:cluster, :project) }
- context 'ci_preparing_state feature is enabled' do
- let(:cluster) { create(:cluster) }
+ it 'configures the cluster' do
+ expect(Clusters::RefreshService).to receive(:create_or_update_namespaces_for_project)
- before do
- stub_feature_flags(ci_preparing_state: true)
- end
-
- it 'does not configure the cluster' do
- expect(Clusters::RefreshService).not_to receive(:create_or_update_namespaces_for_project)
-
- described_class.new.perform(cluster.id)
- end
+ described_class.new.perform(cluster.projects.first.id)
end
end
diff --git a/spec/workers/clusters/applications/wait_for_uninstall_app_worker_spec.rb b/spec/workers/clusters/applications/wait_for_uninstall_app_worker_spec.rb
new file mode 100644
index 00000000000..aaf5c9defc4
--- /dev/null
+++ b/spec/workers/clusters/applications/wait_for_uninstall_app_worker_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Clusters::Applications::WaitForUninstallAppWorker, '#perform' do
+ let(:app) { create(:clusters_applications_helm) }
+ let(:app_name) { app.name }
+ let(:app_id) { app.id }
+
+ subject { described_class.new.perform(app_name, app_id) }
+
+ context 'app exists' do
+ let(:service) { instance_double(Clusters::Applications::CheckUninstallProgressService) }
+
+ it 'calls the check service' do
+ expect(Clusters::Applications::CheckUninstallProgressService).to receive(:new).with(app).and_return(service)
+ expect(service).to receive(:execute).once
+
+ subject
+ end
+ end
+
+ context 'app does not exist' do
+ let(:app_id) { 0 }
+
+ it 'does not call the check service' do
+ expect(Clusters::Applications::CheckUninstallProgressService).not_to receive(:new)
+
+ expect { subject }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+end
diff --git a/spec/workers/deployments/finished_worker_spec.rb b/spec/workers/deployments/finished_worker_spec.rb
new file mode 100644
index 00000000000..df62821e2cd
--- /dev/null
+++ b/spec/workers/deployments/finished_worker_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Deployments::FinishedWorker do
+ let(:worker) { described_class.new }
+
+ describe '#perform' do
+ before do
+ allow(ProjectServiceWorker).to receive(:perform_async)
+ end
+
+ it 'executes project services for deployment_hooks' do
+ deployment = create(:deployment)
+ project = deployment.project
+ service = create(:service, type: 'SlackService', project: project, deployment_events: true, active: true)
+
+ worker.perform(deployment.id)
+
+ expect(ProjectServiceWorker).to have_received(:perform_async).with(service.id, an_instance_of(Hash))
+ end
+
+ it 'does not execute an inactive service' do
+ deployment = create(:deployment)
+ project = deployment.project
+ create(:service, type: 'SlackService', project: project, deployment_events: true, active: false)
+
+ worker.perform(deployment.id)
+
+ expect(ProjectServiceWorker).not_to have_received(:perform_async)
+ end
+
+ it 'does nothing if a deployment with the given id does not exist' do
+ worker.perform(0)
+
+ expect(ProjectServiceWorker).not_to have_received(:perform_async)
+ end
+ end
+end
diff --git a/spec/workers/detect_repository_languages_worker_spec.rb b/spec/workers/detect_repository_languages_worker_spec.rb
index dbf32555985..755eb8dbf6b 100644
--- a/spec/workers/detect_repository_languages_worker_spec.rb
+++ b/spec/workers/detect_repository_languages_worker_spec.rb
@@ -4,7 +4,6 @@ require 'spec_helper'
describe DetectRepositoryLanguagesWorker do
set(:project) { create(:project) }
- let(:user) { project.owner }
subject { described_class.new }
@@ -14,19 +13,13 @@ describe DetectRepositoryLanguagesWorker do
allow(::Projects::DetectRepositoryLanguagesService).to receive(:new).and_return(service)
expect(service).to receive(:execute)
- subject.perform(project.id, user.id)
+ subject.perform(project.id)
end
context 'when invalid ids are used' do
it 'does not raise when the project could not be found' do
expect do
- subject.perform(-1, user.id)
- end.not_to raise_error
- end
-
- it 'does not raise when the user could not be found' do
- expect do
- subject.perform(project.id, -1)
+ subject.perform(-1)
end.not_to raise_error
end
end
diff --git a/spec/workers/expire_build_instance_artifacts_worker_spec.rb b/spec/workers/expire_build_instance_artifacts_worker_spec.rb
index bdb5a3801d9..39f676f1057 100644
--- a/spec/workers/expire_build_instance_artifacts_worker_spec.rb
+++ b/spec/workers/expire_build_instance_artifacts_worker_spec.rb
@@ -21,7 +21,7 @@ describe ExpireBuildInstanceArtifactsWorker do
end
it 'does remove files' do
- expect(build.reload.artifacts_file.exists?).to be_falsey
+ expect(build.reload.artifacts_file.present?).to be_falsey
end
it 'does remove the job artifact record' do
@@ -40,7 +40,7 @@ describe ExpireBuildInstanceArtifactsWorker do
end
it 'does not remove files' do
- expect(build.reload.artifacts_file.exists?).to be_truthy
+ expect(build.reload.artifacts_file.present?).to be_truthy
end
it 'does not remove the job artifact record' do
@@ -56,7 +56,7 @@ describe ExpireBuildInstanceArtifactsWorker do
end
it 'does not remove files' do
- expect(build.reload.artifacts_file.exists?).to be_truthy
+ expect(build.reload.artifacts_file.present?).to be_truthy
end
it 'does not remove the job artifact record' do
diff --git a/spec/workers/git_garbage_collect_worker_spec.rb b/spec/workers/git_garbage_collect_worker_spec.rb
index 2459638c3e6..cc1c23bb9e7 100644
--- a/spec/workers/git_garbage_collect_worker_spec.rb
+++ b/spec/workers/git_garbage_collect_worker_spec.rb
@@ -115,6 +115,19 @@ describe GitGarbageCollectWorker do
end
end
+ context "pack_refs" do
+ before do
+ expect(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
+ end
+
+ it "calls Gitaly" do
+ expect_any_instance_of(Gitlab::GitalyClient::RefService).to receive(:pack_refs)
+ .and_return(nil)
+
+ subject.perform(project.id, :pack_refs, lease_key, lease_uuid)
+ end
+ end
+
context "repack_incremental" do
before do
expect(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
diff --git a/spec/workers/pages_domain_removal_cron_worker_spec.rb b/spec/workers/pages_domain_removal_cron_worker_spec.rb
new file mode 100644
index 00000000000..2408ad54189
--- /dev/null
+++ b/spec/workers/pages_domain_removal_cron_worker_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe PagesDomainRemovalCronWorker do
+ subject(:worker) { described_class.new }
+
+ describe '#perform' do
+ context 'when there is domain which should be removed' do
+ let!(:domain_for_removal) { create(:pages_domain, :should_be_removed) }
+
+ it 'removes domain' do
+ expect { worker.perform }.to change { PagesDomain.count }.by(-1)
+ expect(PagesDomain.exists?).to eq(false)
+ end
+ end
+
+ context 'where there is a domain which scheduled for removal in the future' do
+ let!(:domain_for_removal) { create(:pages_domain, :scheduled_for_removal) }
+
+ it 'does not remove pages domain' do
+ expect { worker.perform }.not_to change { PagesDomain.count }
+ expect(PagesDomain.find_by(domain: domain_for_removal.domain)).to be_present
+ end
+ end
+ end
+end
diff --git a/spec/workers/pages_domain_verification_cron_worker_spec.rb b/spec/workers/pages_domain_verification_cron_worker_spec.rb
index 9b479da1cb6..3fb86adee11 100644
--- a/spec/workers/pages_domain_verification_cron_worker_spec.rb
+++ b/spec/workers/pages_domain_verification_cron_worker_spec.rb
@@ -6,11 +6,18 @@ describe PagesDomainVerificationCronWorker do
subject(:worker) { described_class.new }
describe '#perform' do
- it 'enqueues a PagesDomainVerificationWorker for domains needing verification' do
- verified = create(:pages_domain)
- reverify = create(:pages_domain, :reverify)
- disabled = create(:pages_domain, :disabled)
+ let!(:verified) { create(:pages_domain) }
+ let!(:reverify) { create(:pages_domain, :reverify) }
+ let!(:disabled) { create(:pages_domain, :disabled) }
+
+ it 'does nothing if the database is read-only' do
+ allow(Gitlab::Database).to receive(:read_only?).and_return(true)
+ expect(PagesDomainVerificationWorker).not_to receive(:perform_async).with(reverify.id)
+
+ worker.perform
+ end
+ it 'enqueues a PagesDomainVerificationWorker for domains needing verification' do
[reverify, disabled].each do |domain|
expect(PagesDomainVerificationWorker).to receive(:perform_async).with(domain.id)
end
diff --git a/spec/workers/pages_domain_verification_worker_spec.rb b/spec/workers/pages_domain_verification_worker_spec.rb
index 2f23dcb487f..f51ac1f4323 100644
--- a/spec/workers/pages_domain_verification_worker_spec.rb
+++ b/spec/workers/pages_domain_verification_worker_spec.rb
@@ -8,6 +8,13 @@ describe PagesDomainVerificationWorker do
let(:domain) { create(:pages_domain) }
describe '#perform' do
+ it 'does nothing if the database is read-only' do
+ allow(Gitlab::Database).to receive(:read_only?).and_return(true)
+ expect(PagesDomain).not_to receive(:find_by).with(id: domain.id)
+
+ worker.perform(domain.id)
+ end
+
it 'does nothing for a non-existent domain' do
domain.destroy
diff --git a/spec/workers/pipeline_schedule_worker_spec.rb b/spec/workers/pipeline_schedule_worker_spec.rb
index f23910d23be..9326db34209 100644
--- a/spec/workers/pipeline_schedule_worker_spec.rb
+++ b/spec/workers/pipeline_schedule_worker_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe PipelineScheduleWorker do
+ include ExclusiveLeaseHelpers
+
subject { described_class.new.perform }
set(:project) { create(:project, :repository) }
@@ -65,47 +67,19 @@ describe PipelineScheduleWorker do
stub_ci_pipeline_yaml_file(YAML.dump(rspec: { variables: 'rspec' } ))
end
- it 'creates a failed pipeline with the reason' do
- expect { subject }.to change { project.ci_pipelines.count }.by(1)
- expect(Ci::Pipeline.last).to be_config_error
- expect(Ci::Pipeline.last.yaml_errors).not_to be_nil
+ it 'does not creates a new pipeline' do
+ expect { subject }.not_to change { project.ci_pipelines.count }
end
end
end
context 'when the schedule is not runnable by the user' do
- before do
- expect(Gitlab::Sentry)
- .to receive(:track_exception)
- .with(Ci::CreatePipelineService::CreateError,
- issue_url: 'https://gitlab.com/gitlab-org/gitlab-ce/issues/41231',
- extra: { schedule_id: pipeline_schedule.id } ).once
- end
-
it 'does not deactivate the schedule' do
subject
expect(pipeline_schedule.reload.active).to be_truthy
end
- it 'increments Prometheus counter' do
- expect(Gitlab::Metrics)
- .to receive(:counter)
- .with(:pipeline_schedule_creation_failed_total, "Counter of failed attempts of pipeline schedule creation")
- .and_call_original
-
- subject
- end
-
- it 'logging a pipeline error' do
- expect(Rails.logger)
- .to receive(:error)
- .with(a_string_matching("Insufficient permissions to create a new pipeline"))
- .and_call_original
-
- subject
- end
-
it 'does not create a pipeline' do
expect { subject }.not_to change { project.ci_pipelines.count }
end
@@ -119,21 +93,6 @@ describe PipelineScheduleWorker do
before do
stub_ci_pipeline_yaml_file(nil)
project.add_maintainer(user)
-
- expect(Gitlab::Sentry)
- .to receive(:track_exception)
- .with(Ci::CreatePipelineService::CreateError,
- issue_url: 'https://gitlab.com/gitlab-org/gitlab-ce/issues/41231',
- extra: { schedule_id: pipeline_schedule.id } ).once
- end
-
- it 'logging a pipeline error' do
- expect(Rails.logger)
- .to receive(:error)
- .with(a_string_matching("Missing .gitlab-ci.yml file"))
- .and_call_original
-
- subject
end
it 'does not create a pipeline' do
diff --git a/spec/workers/pipeline_success_worker_spec.rb b/spec/workers/pipeline_success_worker_spec.rb
deleted file mode 100644
index 4cbe384b47a..00000000000
--- a/spec/workers/pipeline_success_worker_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe PipelineSuccessWorker do
- describe '#perform' do
- context 'when pipeline exists' do
- let(:pipeline) { create(:ci_pipeline, status: 'success') }
-
- it 'performs "merge when pipeline succeeds"' do
- expect_any_instance_of(
- MergeRequests::MergeWhenPipelineSucceedsService
- ).to receive(:trigger)
-
- described_class.new.perform(pipeline.id)
- end
- end
-
- context 'when pipeline does not exist' do
- it 'does not raise exception' do
- expect { described_class.new.perform(123) }
- .not_to raise_error
- end
- end
- end
-end
diff --git a/spec/workers/project_cache_worker_spec.rb b/spec/workers/project_cache_worker_spec.rb
index 3c40269adc7..51afb076da1 100644
--- a/spec/workers/project_cache_worker_spec.rb
+++ b/spec/workers/project_cache_worker_spec.rb
@@ -25,10 +25,11 @@ describe ProjectCacheWorker do
end
context 'with an existing project without a repository' do
- it 'does nothing' do
+ it 'updates statistics but does not refresh the method cashes' do
allow_any_instance_of(Repository).to receive(:exists?).and_return(false)
- expect(worker).not_to receive(:update_statistics)
+ expect(worker).to receive(:update_statistics)
+ expect_any_instance_of(Repository).not_to receive(:refresh_method_caches)
worker.perform(project.id)
end
diff --git a/spec/workers/run_pipeline_schedule_worker_spec.rb b/spec/workers/run_pipeline_schedule_worker_spec.rb
index 690af22f4dc..7414470f8e7 100644
--- a/spec/workers/run_pipeline_schedule_worker_spec.rb
+++ b/spec/workers/run_pipeline_schedule_worker_spec.rb
@@ -32,7 +32,37 @@ describe RunPipelineScheduleWorker do
it 'calls the Service' do
expect(Ci::CreatePipelineService).to receive(:new).with(project, user, ref: pipeline_schedule.ref).and_return(create_pipeline_service)
- expect(create_pipeline_service).to receive(:execute).with(:schedule, ignore_skip_ci: true, save_on_errors: false, schedule: pipeline_schedule)
+ expect(create_pipeline_service).to receive(:execute!).with(:schedule, ignore_skip_ci: true, save_on_errors: false, schedule: pipeline_schedule)
+
+ worker.perform(pipeline_schedule.id, user.id)
+ end
+ end
+
+ context 'when database statement timeout happens' do
+ before do
+ allow(Ci::CreatePipelineService).to receive(:new) { raise ActiveRecord::StatementInvalid }
+
+ expect(Gitlab::Sentry)
+ .to receive(:track_exception)
+ .with(ActiveRecord::StatementInvalid,
+ issue_url: 'https://gitlab.com/gitlab-org/gitlab-ce/issues/41231',
+ extra: { schedule_id: pipeline_schedule.id } ).once
+ end
+
+ it 'increments Prometheus counter' do
+ expect(Gitlab::Metrics)
+ .to receive(:counter)
+ .with(:pipeline_schedule_creation_failed_total, "Counter of failed attempts of pipeline schedule creation")
+ .and_call_original
+
+ worker.perform(pipeline_schedule.id, user.id)
+ end
+
+ it 'logging a pipeline error' do
+ expect(Rails.logger)
+ .to receive(:error)
+ .with(a_string_matching('ActiveRecord::StatementInvalid'))
+ .and_call_original
worker.perform(pipeline_schedule.id, user.id)
end
diff --git a/spec/workers/todos_destroyer/confidential_issue_worker_spec.rb b/spec/workers/todos_destroyer/confidential_issue_worker_spec.rb
index 18876b71615..0907e2768ba 100644
--- a/spec/workers/todos_destroyer/confidential_issue_worker_spec.rb
+++ b/spec/workers/todos_destroyer/confidential_issue_worker_spec.rb
@@ -3,12 +3,19 @@
require 'spec_helper'
describe TodosDestroyer::ConfidentialIssueWorker do
- it "calls the Todos::Destroy::ConfidentialIssueService with the params it was given" do
- service = double
+ let(:service) { double }
- expect(::Todos::Destroy::ConfidentialIssueService).to receive(:new).with(100).and_return(service)
+ it "calls the Todos::Destroy::ConfidentialIssueService with issue_id parameter" do
+ expect(::Todos::Destroy::ConfidentialIssueService).to receive(:new).with(issue_id: 100, project_id: nil).and_return(service)
expect(service).to receive(:execute)
described_class.new.perform(100)
end
+
+ it "calls the Todos::Destroy::ConfidentialIssueService with project_id parameter" do
+ expect(::Todos::Destroy::ConfidentialIssueService).to receive(:new).with(issue_id: nil, project_id: 100).and_return(service)
+ expect(service).to receive(:execute)
+
+ described_class.new.perform(nil, 100)
+ end
end
diff --git a/vendor/assets/javascripts/pdf.js b/vendor/assets/javascripts/pdf.js
deleted file mode 100644
index 4d8adb0f2c9..00000000000
--- a/vendor/assets/javascripts/pdf.js
+++ /dev/null
@@ -1,19365 +0,0 @@
-/**
- * @licstart The following is the entire license notice for the
- * Javascript code in this page
- *
- * Copyright 2018 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @licend The above is the entire license notice for the
- * Javascript code in this page
- */
-
-(function webpackUniversalModuleDefinition(root, factory) {
- if(typeof exports === 'object' && typeof module === 'object')
- module.exports = factory();
- else if(typeof define === 'function' && define.amd)
- define("pdfjs-dist/build/pdf", [], factory);
- else if(typeof exports === 'object')
- exports["pdfjs-dist/build/pdf"] = factory();
- else
- root["pdfjs-dist/build/pdf"] = root.pdfjsLib = factory();
-})(this, function() {
-return /******/ (function(modules) { // webpackBootstrap
-/******/ // The module cache
-/******/ var installedModules = {};
-/******/
-/******/ // The require function
-/******/ function __w_pdfjs_require__(moduleId) {
-/******/
-/******/ // Check if module is in cache
-/******/ if(installedModules[moduleId]) {
-/******/ return installedModules[moduleId].exports;
-/******/ }
-/******/ // Create a new module (and put it into the cache)
-/******/ var module = installedModules[moduleId] = {
-/******/ i: moduleId,
-/******/ l: false,
-/******/ exports: {}
-/******/ };
-/******/
-/******/ // Execute the module function
-/******/ modules[moduleId].call(module.exports, module, module.exports, __w_pdfjs_require__);
-/******/
-/******/ // Flag the module as loaded
-/******/ module.l = true;
-/******/
-/******/ // Return the exports of the module
-/******/ return module.exports;
-/******/ }
-/******/
-/******/
-/******/ // expose the modules object (__webpack_modules__)
-/******/ __w_pdfjs_require__.m = modules;
-/******/
-/******/ // expose the module cache
-/******/ __w_pdfjs_require__.c = installedModules;
-/******/
-/******/ // define getter function for harmony exports
-/******/ __w_pdfjs_require__.d = function(exports, name, getter) {
-/******/ if(!__w_pdfjs_require__.o(exports, name)) {
-/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
-/******/ }
-/******/ };
-/******/
-/******/ // define __esModule on exports
-/******/ __w_pdfjs_require__.r = function(exports) {
-/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
-/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
-/******/ }
-/******/ Object.defineProperty(exports, '__esModule', { value: true });
-/******/ };
-/******/
-/******/ // create a fake namespace object
-/******/ // mode & 1: value is a module id, require it
-/******/ // mode & 2: merge all properties of value into the ns
-/******/ // mode & 4: return value when already ns object
-/******/ // mode & 8|1: behave like require
-/******/ __w_pdfjs_require__.t = function(value, mode) {
-/******/ if(mode & 1) value = __w_pdfjs_require__(value);
-/******/ if(mode & 8) return value;
-/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
-/******/ var ns = Object.create(null);
-/******/ __w_pdfjs_require__.r(ns);
-/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
-/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __w_pdfjs_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
-/******/ return ns;
-/******/ };
-/******/
-/******/ // getDefaultExport function for compatibility with non-harmony modules
-/******/ __w_pdfjs_require__.n = function(module) {
-/******/ var getter = module && module.__esModule ?
-/******/ function getDefault() { return module['default']; } :
-/******/ function getModuleExports() { return module; };
-/******/ __w_pdfjs_require__.d(getter, 'a', getter);
-/******/ return getter;
-/******/ };
-/******/
-/******/ // Object.prototype.hasOwnProperty.call
-/******/ __w_pdfjs_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
-/******/
-/******/ // __webpack_public_path__
-/******/ __w_pdfjs_require__.p = "";
-/******/
-/******/
-/******/ // Load entry module and return exports
-/******/ return __w_pdfjs_require__(__w_pdfjs_require__.s = 0);
-/******/ })
-/************************************************************************/
-/******/ ([
-/* 0 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var pdfjsVersion = '2.0.943';
-var pdfjsBuild = 'dc98bf76';
-var pdfjsSharedUtil = __w_pdfjs_require__(1);
-var pdfjsDisplayAPI = __w_pdfjs_require__(129);
-var pdfjsDisplayTextLayer = __w_pdfjs_require__(145);
-var pdfjsDisplayAnnotationLayer = __w_pdfjs_require__(146);
-var pdfjsDisplayDOMUtils = __w_pdfjs_require__(130);
-var pdfjsDisplaySVG = __w_pdfjs_require__(147);
-var pdfjsDisplayWorkerOptions = __w_pdfjs_require__(135);
-var pdfjsDisplayAPICompatibility = __w_pdfjs_require__(132);
-{
- var isNodeJS = __w_pdfjs_require__(4);
- if (isNodeJS()) {
- var PDFNodeStream = __w_pdfjs_require__(148).PDFNodeStream;
- pdfjsDisplayAPI.setPDFNetworkStreamFactory(function (params) {
- return new PDFNodeStream(params);
- });
- } else if (typeof Response !== 'undefined' && 'body' in Response.prototype && typeof ReadableStream !== 'undefined') {
- var PDFFetchStream = __w_pdfjs_require__(151).PDFFetchStream;
- pdfjsDisplayAPI.setPDFNetworkStreamFactory(function (params) {
- return new PDFFetchStream(params);
- });
- } else {
- var PDFNetworkStream = __w_pdfjs_require__(152).PDFNetworkStream;
- pdfjsDisplayAPI.setPDFNetworkStreamFactory(function (params) {
- return new PDFNetworkStream(params);
- });
- }
-}
-exports.build = pdfjsDisplayAPI.build;
-exports.version = pdfjsDisplayAPI.version;
-exports.getDocument = pdfjsDisplayAPI.getDocument;
-exports.LoopbackPort = pdfjsDisplayAPI.LoopbackPort;
-exports.PDFDataRangeTransport = pdfjsDisplayAPI.PDFDataRangeTransport;
-exports.PDFWorker = pdfjsDisplayAPI.PDFWorker;
-exports.renderTextLayer = pdfjsDisplayTextLayer.renderTextLayer;
-exports.AnnotationLayer = pdfjsDisplayAnnotationLayer.AnnotationLayer;
-exports.createPromiseCapability = pdfjsSharedUtil.createPromiseCapability;
-exports.PasswordResponses = pdfjsSharedUtil.PasswordResponses;
-exports.InvalidPDFException = pdfjsSharedUtil.InvalidPDFException;
-exports.MissingPDFException = pdfjsSharedUtil.MissingPDFException;
-exports.SVGGraphics = pdfjsDisplaySVG.SVGGraphics;
-exports.NativeImageDecoding = pdfjsSharedUtil.NativeImageDecoding;
-exports.CMapCompressionType = pdfjsSharedUtil.CMapCompressionType;
-exports.PermissionFlag = pdfjsSharedUtil.PermissionFlag;
-exports.UnexpectedResponseException = pdfjsSharedUtil.UnexpectedResponseException;
-exports.OPS = pdfjsSharedUtil.OPS;
-exports.VerbosityLevel = pdfjsSharedUtil.VerbosityLevel;
-exports.UNSUPPORTED_FEATURES = pdfjsSharedUtil.UNSUPPORTED_FEATURES;
-exports.createValidAbsoluteUrl = pdfjsSharedUtil.createValidAbsoluteUrl;
-exports.createObjectURL = pdfjsSharedUtil.createObjectURL;
-exports.removeNullCharacters = pdfjsSharedUtil.removeNullCharacters;
-exports.shadow = pdfjsSharedUtil.shadow;
-exports.Util = pdfjsSharedUtil.Util;
-exports.ReadableStream = pdfjsSharedUtil.ReadableStream;
-exports.URL = pdfjsSharedUtil.URL;
-exports.RenderingCancelledException = pdfjsDisplayDOMUtils.RenderingCancelledException;
-exports.getFilenameFromUrl = pdfjsDisplayDOMUtils.getFilenameFromUrl;
-exports.LinkTarget = pdfjsDisplayDOMUtils.LinkTarget;
-exports.addLinkAttributes = pdfjsDisplayDOMUtils.addLinkAttributes;
-exports.loadScript = pdfjsDisplayDOMUtils.loadScript;
-exports.GlobalWorkerOptions = pdfjsDisplayWorkerOptions.GlobalWorkerOptions;
-exports.apiCompatibilityParams = pdfjsDisplayAPICompatibility.apiCompatibilityParams;
-
-/***/ }),
-/* 1 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.unreachable = exports.warn = exports.utf8StringToString = exports.stringToUTF8String = exports.stringToPDFString = exports.stringToBytes = exports.string32 = exports.shadow = exports.setVerbosityLevel = exports.URL = exports.ReadableStream = exports.removeNullCharacters = exports.readUint32 = exports.readUint16 = exports.readInt8 = exports.log2 = exports.isEvalSupported = exports.isLittleEndian = exports.createValidAbsoluteUrl = exports.isSameOrigin = exports.isSpace = exports.isString = exports.isNum = exports.isEmptyObj = exports.isBool = exports.isArrayBuffer = exports.info = exports.getVerbosityLevel = exports.getLookupTableFactory = exports.getInheritableProperty = exports.deprecated = exports.createObjectURL = exports.createPromiseCapability = exports.bytesToString = exports.assert = exports.arraysToBytes = exports.arrayByteLength = exports.FormatError = exports.XRefParseException = exports.toRomanNumerals = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.PermissionFlag = exports.PasswordResponses = exports.PasswordException = exports.NativeImageDecoding = exports.MissingPDFException = exports.MissingDataException = exports.InvalidPDFException = exports.AbortException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VerbosityLevel = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = undefined;
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-__w_pdfjs_require__(2);
-
-var _streams_polyfill = __w_pdfjs_require__(125);
-
-var _url_polyfill = __w_pdfjs_require__(127);
-
-var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
-var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
-var NativeImageDecoding = {
- NONE: 'none',
- DECODE: 'decode',
- DISPLAY: 'display'
-};
-var PermissionFlag = {
- PRINT: 0x04,
- MODIFY_CONTENTS: 0x08,
- COPY: 0x10,
- MODIFY_ANNOTATIONS: 0x20,
- FILL_INTERACTIVE_FORMS: 0x100,
- COPY_FOR_ACCESSIBILITY: 0x200,
- ASSEMBLE: 0x400,
- PRINT_HIGH_QUALITY: 0x800
-};
-var TextRenderingMode = {
- FILL: 0,
- STROKE: 1,
- FILL_STROKE: 2,
- INVISIBLE: 3,
- FILL_ADD_TO_PATH: 4,
- STROKE_ADD_TO_PATH: 5,
- FILL_STROKE_ADD_TO_PATH: 6,
- ADD_TO_PATH: 7,
- FILL_STROKE_MASK: 3,
- ADD_TO_PATH_FLAG: 4
-};
-var ImageKind = {
- GRAYSCALE_1BPP: 1,
- RGB_24BPP: 2,
- RGBA_32BPP: 3
-};
-var AnnotationType = {
- TEXT: 1,
- LINK: 2,
- FREETEXT: 3,
- LINE: 4,
- SQUARE: 5,
- CIRCLE: 6,
- POLYGON: 7,
- POLYLINE: 8,
- HIGHLIGHT: 9,
- UNDERLINE: 10,
- SQUIGGLY: 11,
- STRIKEOUT: 12,
- STAMP: 13,
- CARET: 14,
- INK: 15,
- POPUP: 16,
- FILEATTACHMENT: 17,
- SOUND: 18,
- MOVIE: 19,
- WIDGET: 20,
- SCREEN: 21,
- PRINTERMARK: 22,
- TRAPNET: 23,
- WATERMARK: 24,
- THREED: 25,
- REDACT: 26
-};
-var AnnotationFlag = {
- INVISIBLE: 0x01,
- HIDDEN: 0x02,
- PRINT: 0x04,
- NOZOOM: 0x08,
- NOROTATE: 0x10,
- NOVIEW: 0x20,
- READONLY: 0x40,
- LOCKED: 0x80,
- TOGGLENOVIEW: 0x100,
- LOCKEDCONTENTS: 0x200
-};
-var AnnotationFieldFlag = {
- READONLY: 0x0000001,
- REQUIRED: 0x0000002,
- NOEXPORT: 0x0000004,
- MULTILINE: 0x0001000,
- PASSWORD: 0x0002000,
- NOTOGGLETOOFF: 0x0004000,
- RADIO: 0x0008000,
- PUSHBUTTON: 0x0010000,
- COMBO: 0x0020000,
- EDIT: 0x0040000,
- SORT: 0x0080000,
- FILESELECT: 0x0100000,
- MULTISELECT: 0x0200000,
- DONOTSPELLCHECK: 0x0400000,
- DONOTSCROLL: 0x0800000,
- COMB: 0x1000000,
- RICHTEXT: 0x2000000,
- RADIOSINUNISON: 0x2000000,
- COMMITONSELCHANGE: 0x4000000
-};
-var AnnotationBorderStyleType = {
- SOLID: 1,
- DASHED: 2,
- BEVELED: 3,
- INSET: 4,
- UNDERLINE: 5
-};
-var StreamType = {
- UNKNOWN: 0,
- FLATE: 1,
- LZW: 2,
- DCT: 3,
- JPX: 4,
- JBIG: 5,
- A85: 6,
- AHX: 7,
- CCF: 8,
- RL: 9
-};
-var FontType = {
- UNKNOWN: 0,
- TYPE1: 1,
- TYPE1C: 2,
- CIDFONTTYPE0: 3,
- CIDFONTTYPE0C: 4,
- TRUETYPE: 5,
- CIDFONTTYPE2: 6,
- TYPE3: 7,
- OPENTYPE: 8,
- TYPE0: 9,
- MMTYPE1: 10
-};
-var VerbosityLevel = {
- ERRORS: 0,
- WARNINGS: 1,
- INFOS: 5
-};
-var CMapCompressionType = {
- NONE: 0,
- BINARY: 1,
- STREAM: 2
-};
-var OPS = {
- dependency: 1,
- setLineWidth: 2,
- setLineCap: 3,
- setLineJoin: 4,
- setMiterLimit: 5,
- setDash: 6,
- setRenderingIntent: 7,
- setFlatness: 8,
- setGState: 9,
- save: 10,
- restore: 11,
- transform: 12,
- moveTo: 13,
- lineTo: 14,
- curveTo: 15,
- curveTo2: 16,
- curveTo3: 17,
- closePath: 18,
- rectangle: 19,
- stroke: 20,
- closeStroke: 21,
- fill: 22,
- eoFill: 23,
- fillStroke: 24,
- eoFillStroke: 25,
- closeFillStroke: 26,
- closeEOFillStroke: 27,
- endPath: 28,
- clip: 29,
- eoClip: 30,
- beginText: 31,
- endText: 32,
- setCharSpacing: 33,
- setWordSpacing: 34,
- setHScale: 35,
- setLeading: 36,
- setFont: 37,
- setTextRenderingMode: 38,
- setTextRise: 39,
- moveText: 40,
- setLeadingMoveText: 41,
- setTextMatrix: 42,
- nextLine: 43,
- showText: 44,
- showSpacedText: 45,
- nextLineShowText: 46,
- nextLineSetSpacingShowText: 47,
- setCharWidth: 48,
- setCharWidthAndBounds: 49,
- setStrokeColorSpace: 50,
- setFillColorSpace: 51,
- setStrokeColor: 52,
- setStrokeColorN: 53,
- setFillColor: 54,
- setFillColorN: 55,
- setStrokeGray: 56,
- setFillGray: 57,
- setStrokeRGBColor: 58,
- setFillRGBColor: 59,
- setStrokeCMYKColor: 60,
- setFillCMYKColor: 61,
- shadingFill: 62,
- beginInlineImage: 63,
- beginImageData: 64,
- endInlineImage: 65,
- paintXObject: 66,
- markPoint: 67,
- markPointProps: 68,
- beginMarkedContent: 69,
- beginMarkedContentProps: 70,
- endMarkedContent: 71,
- beginCompat: 72,
- endCompat: 73,
- paintFormXObjectBegin: 74,
- paintFormXObjectEnd: 75,
- beginGroup: 76,
- endGroup: 77,
- beginAnnotations: 78,
- endAnnotations: 79,
- beginAnnotation: 80,
- endAnnotation: 81,
- paintJpegXObject: 82,
- paintImageMaskXObject: 83,
- paintImageMaskXObjectGroup: 84,
- paintImageXObject: 85,
- paintInlineImageXObject: 86,
- paintInlineImageXObjectGroup: 87,
- paintImageXObjectRepeat: 88,
- paintImageMaskXObjectRepeat: 89,
- paintSolidColorImageMask: 90,
- constructPath: 91
-};
-var UNSUPPORTED_FEATURES = {
- unknown: 'unknown',
- forms: 'forms',
- javaScript: 'javaScript',
- smask: 'smask',
- shadingPattern: 'shadingPattern',
- font: 'font'
-};
-var PasswordResponses = {
- NEED_PASSWORD: 1,
- INCORRECT_PASSWORD: 2
-};
-var verbosity = VerbosityLevel.WARNINGS;
-function setVerbosityLevel(level) {
- if (Number.isInteger(level)) {
- verbosity = level;
- }
-}
-function getVerbosityLevel() {
- return verbosity;
-}
-function info(msg) {
- if (verbosity >= VerbosityLevel.INFOS) {
- console.log('Info: ' + msg);
- }
-}
-function warn(msg) {
- if (verbosity >= VerbosityLevel.WARNINGS) {
- console.log('Warning: ' + msg);
- }
-}
-function deprecated(details) {
- console.log('Deprecated API usage: ' + details);
-}
-function unreachable(msg) {
- throw new Error(msg);
-}
-function assert(cond, msg) {
- if (!cond) {
- unreachable(msg);
- }
-}
-function isSameOrigin(baseUrl, otherUrl) {
- try {
- var base = new _url_polyfill.URL(baseUrl);
- if (!base.origin || base.origin === 'null') {
- return false;
- }
- } catch (e) {
- return false;
- }
- var other = new _url_polyfill.URL(otherUrl, base);
- return base.origin === other.origin;
-}
-function _isValidProtocol(url) {
- if (!url) {
- return false;
- }
- switch (url.protocol) {
- case 'http:':
- case 'https:':
- case 'ftp:':
- case 'mailto:':
- case 'tel:':
- return true;
- default:
- return false;
- }
-}
-function createValidAbsoluteUrl(url, baseUrl) {
- if (!url) {
- return null;
- }
- try {
- var absoluteUrl = baseUrl ? new _url_polyfill.URL(url, baseUrl) : new _url_polyfill.URL(url);
- if (_isValidProtocol(absoluteUrl)) {
- return absoluteUrl;
- }
- } catch (ex) {}
- return null;
-}
-function shadow(obj, prop, value) {
- Object.defineProperty(obj, prop, {
- value: value,
- enumerable: true,
- configurable: true,
- writable: false
- });
- return value;
-}
-function getLookupTableFactory(initializer) {
- var lookup;
- return function () {
- if (initializer) {
- lookup = Object.create(null);
- initializer(lookup);
- initializer = null;
- }
- return lookup;
- };
-}
-var PasswordException = function PasswordExceptionClosure() {
- function PasswordException(msg, code) {
- this.name = 'PasswordException';
- this.message = msg;
- this.code = code;
- }
- PasswordException.prototype = new Error();
- PasswordException.constructor = PasswordException;
- return PasswordException;
-}();
-var UnknownErrorException = function UnknownErrorExceptionClosure() {
- function UnknownErrorException(msg, details) {
- this.name = 'UnknownErrorException';
- this.message = msg;
- this.details = details;
- }
- UnknownErrorException.prototype = new Error();
- UnknownErrorException.constructor = UnknownErrorException;
- return UnknownErrorException;
-}();
-var InvalidPDFException = function InvalidPDFExceptionClosure() {
- function InvalidPDFException(msg) {
- this.name = 'InvalidPDFException';
- this.message = msg;
- }
- InvalidPDFException.prototype = new Error();
- InvalidPDFException.constructor = InvalidPDFException;
- return InvalidPDFException;
-}();
-var MissingPDFException = function MissingPDFExceptionClosure() {
- function MissingPDFException(msg) {
- this.name = 'MissingPDFException';
- this.message = msg;
- }
- MissingPDFException.prototype = new Error();
- MissingPDFException.constructor = MissingPDFException;
- return MissingPDFException;
-}();
-var UnexpectedResponseException = function UnexpectedResponseExceptionClosure() {
- function UnexpectedResponseException(msg, status) {
- this.name = 'UnexpectedResponseException';
- this.message = msg;
- this.status = status;
- }
- UnexpectedResponseException.prototype = new Error();
- UnexpectedResponseException.constructor = UnexpectedResponseException;
- return UnexpectedResponseException;
-}();
-var MissingDataException = function MissingDataExceptionClosure() {
- function MissingDataException(begin, end) {
- this.begin = begin;
- this.end = end;
- this.message = 'Missing data [' + begin + ', ' + end + ')';
- }
- MissingDataException.prototype = new Error();
- MissingDataException.prototype.name = 'MissingDataException';
- MissingDataException.constructor = MissingDataException;
- return MissingDataException;
-}();
-var XRefParseException = function XRefParseExceptionClosure() {
- function XRefParseException(msg) {
- this.message = msg;
- }
- XRefParseException.prototype = new Error();
- XRefParseException.prototype.name = 'XRefParseException';
- XRefParseException.constructor = XRefParseException;
- return XRefParseException;
-}();
-var FormatError = function FormatErrorClosure() {
- function FormatError(msg) {
- this.message = msg;
- }
- FormatError.prototype = new Error();
- FormatError.prototype.name = 'FormatError';
- FormatError.constructor = FormatError;
- return FormatError;
-}();
-var AbortException = function AbortExceptionClosure() {
- function AbortException(msg) {
- this.name = 'AbortException';
- this.message = msg;
- }
- AbortException.prototype = new Error();
- AbortException.constructor = AbortException;
- return AbortException;
-}();
-var NullCharactersRegExp = /\x00/g;
-function removeNullCharacters(str) {
- if (typeof str !== 'string') {
- warn('The argument for removeNullCharacters must be a string.');
- return str;
- }
- return str.replace(NullCharactersRegExp, '');
-}
-function bytesToString(bytes) {
- assert(bytes !== null && (typeof bytes === 'undefined' ? 'undefined' : _typeof(bytes)) === 'object' && bytes.length !== undefined, 'Invalid argument for bytesToString');
- var length = bytes.length;
- var MAX_ARGUMENT_COUNT = 8192;
- if (length < MAX_ARGUMENT_COUNT) {
- return String.fromCharCode.apply(null, bytes);
- }
- var strBuf = [];
- for (var i = 0; i < length; i += MAX_ARGUMENT_COUNT) {
- var chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);
- var chunk = bytes.subarray(i, chunkEnd);
- strBuf.push(String.fromCharCode.apply(null, chunk));
- }
- return strBuf.join('');
-}
-function stringToBytes(str) {
- assert(typeof str === 'string', 'Invalid argument for stringToBytes');
- var length = str.length;
- var bytes = new Uint8Array(length);
- for (var i = 0; i < length; ++i) {
- bytes[i] = str.charCodeAt(i) & 0xFF;
- }
- return bytes;
-}
-function arrayByteLength(arr) {
- if (arr.length !== undefined) {
- return arr.length;
- }
- assert(arr.byteLength !== undefined);
- return arr.byteLength;
-}
-function arraysToBytes(arr) {
- if (arr.length === 1 && arr[0] instanceof Uint8Array) {
- return arr[0];
- }
- var resultLength = 0;
- var i,
- ii = arr.length;
- var item, itemLength;
- for (i = 0; i < ii; i++) {
- item = arr[i];
- itemLength = arrayByteLength(item);
- resultLength += itemLength;
- }
- var pos = 0;
- var data = new Uint8Array(resultLength);
- for (i = 0; i < ii; i++) {
- item = arr[i];
- if (!(item instanceof Uint8Array)) {
- if (typeof item === 'string') {
- item = stringToBytes(item);
- } else {
- item = new Uint8Array(item);
- }
- }
- itemLength = item.byteLength;
- data.set(item, pos);
- pos += itemLength;
- }
- return data;
-}
-function string32(value) {
- return String.fromCharCode(value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff);
-}
-function log2(x) {
- if (x <= 0) {
- return 0;
- }
- return Math.ceil(Math.log2(x));
-}
-function readInt8(data, start) {
- return data[start] << 24 >> 24;
-}
-function readUint16(data, offset) {
- return data[offset] << 8 | data[offset + 1];
-}
-function readUint32(data, offset) {
- return (data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]) >>> 0;
-}
-function isLittleEndian() {
- var buffer8 = new Uint8Array(4);
- buffer8[0] = 1;
- var view32 = new Uint32Array(buffer8.buffer, 0, 1);
- return view32[0] === 1;
-}
-function isEvalSupported() {
- try {
- new Function('');
- return true;
- } catch (e) {
- return false;
- }
-}
-function getInheritableProperty(_ref) {
- var dict = _ref.dict,
- key = _ref.key,
- _ref$getArray = _ref.getArray,
- getArray = _ref$getArray === undefined ? false : _ref$getArray,
- _ref$stopWhenFound = _ref.stopWhenFound,
- stopWhenFound = _ref$stopWhenFound === undefined ? true : _ref$stopWhenFound;
-
- var LOOP_LIMIT = 100;
- var loopCount = 0;
- var values = void 0;
- while (dict) {
- var value = getArray ? dict.getArray(key) : dict.get(key);
- if (value !== undefined) {
- if (stopWhenFound) {
- return value;
- }
- if (!values) {
- values = [];
- }
- values.push(value);
- }
- if (++loopCount > LOOP_LIMIT) {
- warn('getInheritableProperty: maximum loop count exceeded for "' + key + '"');
- break;
- }
- dict = dict.get('Parent');
- }
- return values;
-}
-var Util = function UtilClosure() {
- function Util() {}
- var rgbBuf = ['rgb(', 0, ',', 0, ',', 0, ')'];
- Util.makeCssRgb = function Util_makeCssRgb(r, g, b) {
- rgbBuf[1] = r;
- rgbBuf[3] = g;
- rgbBuf[5] = b;
- return rgbBuf.join('');
- };
- Util.transform = function Util_transform(m1, m2) {
- return [m1[0] * m2[0] + m1[2] * m2[1], m1[1] * m2[0] + m1[3] * m2[1], m1[0] * m2[2] + m1[2] * m2[3], m1[1] * m2[2] + m1[3] * m2[3], m1[0] * m2[4] + m1[2] * m2[5] + m1[4], m1[1] * m2[4] + m1[3] * m2[5] + m1[5]];
- };
- Util.applyTransform = function Util_applyTransform(p, m) {
- var xt = p[0] * m[0] + p[1] * m[2] + m[4];
- var yt = p[0] * m[1] + p[1] * m[3] + m[5];
- return [xt, yt];
- };
- Util.applyInverseTransform = function Util_applyInverseTransform(p, m) {
- var d = m[0] * m[3] - m[1] * m[2];
- var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
- var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
- return [xt, yt];
- };
- Util.getAxialAlignedBoundingBox = function Util_getAxialAlignedBoundingBox(r, m) {
- var p1 = Util.applyTransform(r, m);
- var p2 = Util.applyTransform(r.slice(2, 4), m);
- var p3 = Util.applyTransform([r[0], r[3]], m);
- var p4 = Util.applyTransform([r[2], r[1]], m);
- return [Math.min(p1[0], p2[0], p3[0], p4[0]), Math.min(p1[1], p2[1], p3[1], p4[1]), Math.max(p1[0], p2[0], p3[0], p4[0]), Math.max(p1[1], p2[1], p3[1], p4[1])];
- };
- Util.inverseTransform = function Util_inverseTransform(m) {
- var d = m[0] * m[3] - m[1] * m[2];
- return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d];
- };
- Util.apply3dTransform = function Util_apply3dTransform(m, v) {
- return [m[0] * v[0] + m[1] * v[1] + m[2] * v[2], m[3] * v[0] + m[4] * v[1] + m[5] * v[2], m[6] * v[0] + m[7] * v[1] + m[8] * v[2]];
- };
- Util.singularValueDecompose2dScale = function Util_singularValueDecompose2dScale(m) {
- var transpose = [m[0], m[2], m[1], m[3]];
- var a = m[0] * transpose[0] + m[1] * transpose[2];
- var b = m[0] * transpose[1] + m[1] * transpose[3];
- var c = m[2] * transpose[0] + m[3] * transpose[2];
- var d = m[2] * transpose[1] + m[3] * transpose[3];
- var first = (a + d) / 2;
- var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2;
- var sx = first + second || 1;
- var sy = first - second || 1;
- return [Math.sqrt(sx), Math.sqrt(sy)];
- };
- Util.normalizeRect = function Util_normalizeRect(rect) {
- var r = rect.slice(0);
- if (rect[0] > rect[2]) {
- r[0] = rect[2];
- r[2] = rect[0];
- }
- if (rect[1] > rect[3]) {
- r[1] = rect[3];
- r[3] = rect[1];
- }
- return r;
- };
- Util.intersect = function Util_intersect(rect1, rect2) {
- function compare(a, b) {
- return a - b;
- }
- var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare),
- orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare),
- result = [];
- rect1 = Util.normalizeRect(rect1);
- rect2 = Util.normalizeRect(rect2);
- if (orderedX[0] === rect1[0] && orderedX[1] === rect2[0] || orderedX[0] === rect2[0] && orderedX[1] === rect1[0]) {
- result[0] = orderedX[1];
- result[2] = orderedX[2];
- } else {
- return false;
- }
- if (orderedY[0] === rect1[1] && orderedY[1] === rect2[1] || orderedY[0] === rect2[1] && orderedY[1] === rect1[1]) {
- result[1] = orderedY[1];
- result[3] = orderedY[2];
- } else {
- return false;
- }
- return result;
- };
- return Util;
-}();
-var ROMAN_NUMBER_MAP = ['', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM', '', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC', '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'];
-function toRomanNumerals(number) {
- var lowerCase = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
-
- assert(Number.isInteger(number) && number > 0, 'The number should be a positive integer.');
- var pos = void 0,
- romanBuf = [];
- while (number >= 1000) {
- number -= 1000;
- romanBuf.push('M');
- }
- pos = number / 100 | 0;
- number %= 100;
- romanBuf.push(ROMAN_NUMBER_MAP[pos]);
- pos = number / 10 | 0;
- number %= 10;
- romanBuf.push(ROMAN_NUMBER_MAP[10 + pos]);
- romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);
- var romanStr = romanBuf.join('');
- return lowerCase ? romanStr.toLowerCase() : romanStr;
-}
-var PDFStringTranslateTable = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160, 0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC];
-function stringToPDFString(str) {
- var i,
- n = str.length,
- strBuf = [];
- if (str[0] === '\xFE' && str[1] === '\xFF') {
- for (i = 2; i < n; i += 2) {
- strBuf.push(String.fromCharCode(str.charCodeAt(i) << 8 | str.charCodeAt(i + 1)));
- }
- } else {
- for (i = 0; i < n; ++i) {
- var code = PDFStringTranslateTable[str.charCodeAt(i)];
- strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
- }
- }
- return strBuf.join('');
-}
-function stringToUTF8String(str) {
- return decodeURIComponent(escape(str));
-}
-function utf8StringToString(str) {
- return unescape(encodeURIComponent(str));
-}
-function isEmptyObj(obj) {
- for (var key in obj) {
- return false;
- }
- return true;
-}
-function isBool(v) {
- return typeof v === 'boolean';
-}
-function isNum(v) {
- return typeof v === 'number';
-}
-function isString(v) {
- return typeof v === 'string';
-}
-function isArrayBuffer(v) {
- return (typeof v === 'undefined' ? 'undefined' : _typeof(v)) === 'object' && v !== null && v.byteLength !== undefined;
-}
-function isSpace(ch) {
- return ch === 0x20 || ch === 0x09 || ch === 0x0D || ch === 0x0A;
-}
-function createPromiseCapability() {
- var capability = {};
- capability.promise = new Promise(function (resolve, reject) {
- capability.resolve = resolve;
- capability.reject = reject;
- });
- return capability;
-}
-var createObjectURL = function createObjectURLClosure() {
- var digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
- return function createObjectURL(data, contentType) {
- var forceDataSchema = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
-
- if (!forceDataSchema && _url_polyfill.URL.createObjectURL) {
- var blob = new Blob([data], { type: contentType });
- return _url_polyfill.URL.createObjectURL(blob);
- }
- var buffer = 'data:' + contentType + ';base64,';
- for (var i = 0, ii = data.length; i < ii; i += 3) {
- var b1 = data[i] & 0xFF;
- var b2 = data[i + 1] & 0xFF;
- var b3 = data[i + 2] & 0xFF;
- var d1 = b1 >> 2,
- d2 = (b1 & 3) << 4 | b2 >> 4;
- var d3 = i + 1 < ii ? (b2 & 0xF) << 2 | b3 >> 6 : 64;
- var d4 = i + 2 < ii ? b3 & 0x3F : 64;
- buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
- }
- return buffer;
- };
-}();
-exports.FONT_IDENTITY_MATRIX = FONT_IDENTITY_MATRIX;
-exports.IDENTITY_MATRIX = IDENTITY_MATRIX;
-exports.OPS = OPS;
-exports.VerbosityLevel = VerbosityLevel;
-exports.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES;
-exports.AnnotationBorderStyleType = AnnotationBorderStyleType;
-exports.AnnotationFieldFlag = AnnotationFieldFlag;
-exports.AnnotationFlag = AnnotationFlag;
-exports.AnnotationType = AnnotationType;
-exports.FontType = FontType;
-exports.ImageKind = ImageKind;
-exports.CMapCompressionType = CMapCompressionType;
-exports.AbortException = AbortException;
-exports.InvalidPDFException = InvalidPDFException;
-exports.MissingDataException = MissingDataException;
-exports.MissingPDFException = MissingPDFException;
-exports.NativeImageDecoding = NativeImageDecoding;
-exports.PasswordException = PasswordException;
-exports.PasswordResponses = PasswordResponses;
-exports.PermissionFlag = PermissionFlag;
-exports.StreamType = StreamType;
-exports.TextRenderingMode = TextRenderingMode;
-exports.UnexpectedResponseException = UnexpectedResponseException;
-exports.UnknownErrorException = UnknownErrorException;
-exports.Util = Util;
-exports.toRomanNumerals = toRomanNumerals;
-exports.XRefParseException = XRefParseException;
-exports.FormatError = FormatError;
-exports.arrayByteLength = arrayByteLength;
-exports.arraysToBytes = arraysToBytes;
-exports.assert = assert;
-exports.bytesToString = bytesToString;
-exports.createPromiseCapability = createPromiseCapability;
-exports.createObjectURL = createObjectURL;
-exports.deprecated = deprecated;
-exports.getInheritableProperty = getInheritableProperty;
-exports.getLookupTableFactory = getLookupTableFactory;
-exports.getVerbosityLevel = getVerbosityLevel;
-exports.info = info;
-exports.isArrayBuffer = isArrayBuffer;
-exports.isBool = isBool;
-exports.isEmptyObj = isEmptyObj;
-exports.isNum = isNum;
-exports.isString = isString;
-exports.isSpace = isSpace;
-exports.isSameOrigin = isSameOrigin;
-exports.createValidAbsoluteUrl = createValidAbsoluteUrl;
-exports.isLittleEndian = isLittleEndian;
-exports.isEvalSupported = isEvalSupported;
-exports.log2 = log2;
-exports.readInt8 = readInt8;
-exports.readUint16 = readUint16;
-exports.readUint32 = readUint32;
-exports.removeNullCharacters = removeNullCharacters;
-exports.ReadableStream = _streams_polyfill.ReadableStream;
-exports.URL = _url_polyfill.URL;
-exports.setVerbosityLevel = setVerbosityLevel;
-exports.shadow = shadow;
-exports.string32 = string32;
-exports.stringToBytes = stringToBytes;
-exports.stringToPDFString = stringToPDFString;
-exports.stringToUTF8String = stringToUTF8String;
-exports.utf8StringToString = utf8StringToString;
-exports.warn = warn;
-exports.unreachable = unreachable;
-
-/***/ }),
-/* 2 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-var globalScope = __w_pdfjs_require__(3);
-if (!globalScope._pdfjsCompatibilityChecked) {
- globalScope._pdfjsCompatibilityChecked = true;
- var isNodeJS = __w_pdfjs_require__(4);
- var hasDOM = (typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && (typeof document === 'undefined' ? 'undefined' : _typeof(document)) === 'object';
- (function checkNodeBtoa() {
- if (globalScope.btoa || !isNodeJS()) {
- return;
- }
- globalScope.btoa = function (chars) {
- return Buffer.from(chars, 'binary').toString('base64');
- };
- })();
- (function checkNodeAtob() {
- if (globalScope.atob || !isNodeJS()) {
- return;
- }
- globalScope.atob = function (input) {
- return Buffer.from(input, 'base64').toString('binary');
- };
- })();
- (function checkCurrentScript() {
- if (!hasDOM) {
- return;
- }
- if ('currentScript' in document) {
- return;
- }
- Object.defineProperty(document, 'currentScript', {
- get: function get() {
- var scripts = document.getElementsByTagName('script');
- return scripts[scripts.length - 1];
- },
-
- enumerable: true,
- configurable: true
- });
- })();
- (function checkChildNodeRemove() {
- if (!hasDOM) {
- return;
- }
- if (typeof Element.prototype.remove !== 'undefined') {
- return;
- }
- Element.prototype.remove = function () {
- if (this.parentNode) {
- this.parentNode.removeChild(this);
- }
- };
- })();
- (function checkDOMTokenListToggle() {
- if (!hasDOM || isNodeJS()) {
- return;
- }
- var div = document.createElement('div');
- if (div.classList.toggle('test', 0) === false) {
- return;
- }
- var originalDOMTokenListToggle = DOMTokenList.prototype.toggle;
- DOMTokenList.prototype.toggle = function (token) {
- if (arguments.length > 1) {
- var force = !!arguments[1];
- return this[force ? 'add' : 'remove'](token), force;
- }
- return originalDOMTokenListToggle(token);
- };
- })();
- (function checkStringIncludes() {
- if (String.prototype.includes) {
- return;
- }
- __w_pdfjs_require__(5);
- })();
- (function checkArrayIncludes() {
- if (Array.prototype.includes) {
- return;
- }
- __w_pdfjs_require__(33);
- })();
- (function checkObjectAssign() {
- if (Object.assign) {
- return;
- }
- __w_pdfjs_require__(42);
- })();
- (function checkMathLog2() {
- if (Math.log2) {
- return;
- }
- Math.log2 = __w_pdfjs_require__(52);
- })();
- (function checkNumberIsNaN() {
- if (Number.isNaN) {
- return;
- }
- Number.isNaN = __w_pdfjs_require__(54);
- })();
- (function checkNumberIsInteger() {
- if (Number.isInteger) {
- return;
- }
- Number.isInteger = __w_pdfjs_require__(56);
- })();
- (function checkPromise() {
- if (globalScope.Promise) {
- return;
- }
- globalScope.Promise = __w_pdfjs_require__(59);
- })();
- (function checkWeakMap() {
- if (globalScope.WeakMap) {
- return;
- }
- globalScope.WeakMap = __w_pdfjs_require__(94);
- })();
- (function checkStringCodePointAt() {
- if (String.codePointAt) {
- return;
- }
- String.codePointAt = __w_pdfjs_require__(111);
- })();
- (function checkStringFromCodePoint() {
- if (String.fromCodePoint) {
- return;
- }
- String.fromCodePoint = __w_pdfjs_require__(113);
- })();
- (function checkSymbol() {
- if (globalScope.Symbol) {
- return;
- }
- __w_pdfjs_require__(115);
- })();
- (function checkObjectValues() {
- if (Object.values) {
- return;
- }
- Object.values = __w_pdfjs_require__(122);
- })();
-}
-
-/***/ }),
-/* 3 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = typeof window !== 'undefined' && window.Math === Math ? window : typeof global !== 'undefined' && global.Math === Math ? global : typeof self !== 'undefined' && self.Math === Math ? self : {};
-
-/***/ }),
-/* 4 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-module.exports = function isNodeJS() {
- return (typeof process === 'undefined' ? 'undefined' : _typeof(process)) === 'object' && process + '' === '[object process]';
-};
-
-/***/ }),
-/* 5 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(6);
-module.exports = __w_pdfjs_require__(9).String.includes;
-
-/***/ }),
-/* 6 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(7);
-var context = __w_pdfjs_require__(25);
-var INCLUDES = 'includes';
-$export($export.P + $export.F * __w_pdfjs_require__(32)(INCLUDES), 'String', {
- includes: function includes(searchString) {
- return !!~context(this, searchString, INCLUDES).indexOf(searchString, arguments.length > 1 ? arguments[1] : undefined);
- }
-});
-
-/***/ }),
-/* 7 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var global = __w_pdfjs_require__(8);
-var core = __w_pdfjs_require__(9);
-var hide = __w_pdfjs_require__(10);
-var redefine = __w_pdfjs_require__(20);
-var ctx = __w_pdfjs_require__(23);
-var PROTOTYPE = 'prototype';
-var $export = function $export(type, name, source) {
- var IS_FORCED = type & $export.F;
- var IS_GLOBAL = type & $export.G;
- var IS_STATIC = type & $export.S;
- var IS_PROTO = type & $export.P;
- var IS_BIND = type & $export.B;
- var target = IS_GLOBAL ? global : IS_STATIC ? global[name] || (global[name] = {}) : (global[name] || {})[PROTOTYPE];
- var exports = IS_GLOBAL ? core : core[name] || (core[name] = {});
- var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {});
- var key, own, out, exp;
- if (IS_GLOBAL) source = name;
- for (key in source) {
- own = !IS_FORCED && target && target[key] !== undefined;
- out = (own ? target : source)[key];
- exp = IS_BIND && own ? ctx(out, global) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;
- if (target) redefine(target, key, out, type & $export.U);
- if (exports[key] != out) hide(exports, key, exp);
- if (IS_PROTO && expProto[key] != out) expProto[key] = out;
- }
-};
-global.core = core;
-$export.F = 1;
-$export.G = 2;
-$export.S = 4;
-$export.P = 8;
-$export.B = 16;
-$export.W = 32;
-$export.U = 64;
-$export.R = 128;
-module.exports = $export;
-
-/***/ }),
-/* 8 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var global = module.exports = typeof window != 'undefined' && window.Math == Math ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')();
-if (typeof __g == 'number') __g = global;
-
-/***/ }),
-/* 9 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var core = module.exports = { version: '2.5.7' };
-if (typeof __e == 'number') __e = core;
-
-/***/ }),
-/* 10 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var dP = __w_pdfjs_require__(11);
-var createDesc = __w_pdfjs_require__(19);
-module.exports = __w_pdfjs_require__(15) ? function (object, key, value) {
- return dP.f(object, key, createDesc(1, value));
-} : function (object, key, value) {
- object[key] = value;
- return object;
-};
-
-/***/ }),
-/* 11 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var anObject = __w_pdfjs_require__(12);
-var IE8_DOM_DEFINE = __w_pdfjs_require__(14);
-var toPrimitive = __w_pdfjs_require__(18);
-var dP = Object.defineProperty;
-exports.f = __w_pdfjs_require__(15) ? Object.defineProperty : function defineProperty(O, P, Attributes) {
- anObject(O);
- P = toPrimitive(P, true);
- anObject(Attributes);
- if (IE8_DOM_DEFINE) try {
- return dP(O, P, Attributes);
- } catch (e) {}
- if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!');
- if ('value' in Attributes) O[P] = Attributes.value;
- return O;
-};
-
-/***/ }),
-/* 12 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isObject = __w_pdfjs_require__(13);
-module.exports = function (it) {
- if (!isObject(it)) throw TypeError(it + ' is not an object!');
- return it;
-};
-
-/***/ }),
-/* 13 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-module.exports = function (it) {
- return (typeof it === 'undefined' ? 'undefined' : _typeof(it)) === 'object' ? it !== null : typeof it === 'function';
-};
-
-/***/ }),
-/* 14 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = !__w_pdfjs_require__(15) && !__w_pdfjs_require__(16)(function () {
- return Object.defineProperty(__w_pdfjs_require__(17)('div'), 'a', {
- get: function get() {
- return 7;
- }
- }).a != 7;
-});
-
-/***/ }),
-/* 15 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = !__w_pdfjs_require__(16)(function () {
- return Object.defineProperty({}, 'a', {
- get: function get() {
- return 7;
- }
- }).a != 7;
-});
-
-/***/ }),
-/* 16 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = function (exec) {
- try {
- return !!exec();
- } catch (e) {
- return true;
- }
-};
-
-/***/ }),
-/* 17 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isObject = __w_pdfjs_require__(13);
-var document = __w_pdfjs_require__(8).document;
-var is = isObject(document) && isObject(document.createElement);
-module.exports = function (it) {
- return is ? document.createElement(it) : {};
-};
-
-/***/ }),
-/* 18 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isObject = __w_pdfjs_require__(13);
-module.exports = function (it, S) {
- if (!isObject(it)) return it;
- var fn, val;
- if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;
- if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val;
- if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;
- throw TypeError("Can't convert object to primitive value");
-};
-
-/***/ }),
-/* 19 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = function (bitmap, value) {
- return {
- enumerable: !(bitmap & 1),
- configurable: !(bitmap & 2),
- writable: !(bitmap & 4),
- value: value
- };
-};
-
-/***/ }),
-/* 20 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var global = __w_pdfjs_require__(8);
-var hide = __w_pdfjs_require__(10);
-var has = __w_pdfjs_require__(21);
-var SRC = __w_pdfjs_require__(22)('src');
-var TO_STRING = 'toString';
-var $toString = Function[TO_STRING];
-var TPL = ('' + $toString).split(TO_STRING);
-__w_pdfjs_require__(9).inspectSource = function (it) {
- return $toString.call(it);
-};
-(module.exports = function (O, key, val, safe) {
- var isFunction = typeof val == 'function';
- if (isFunction) has(val, 'name') || hide(val, 'name', key);
- if (O[key] === val) return;
- if (isFunction) has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key)));
- if (O === global) {
- O[key] = val;
- } else if (!safe) {
- delete O[key];
- hide(O, key, val);
- } else if (O[key]) {
- O[key] = val;
- } else {
- hide(O, key, val);
- }
-})(Function.prototype, TO_STRING, function toString() {
- return typeof this == 'function' && this[SRC] || $toString.call(this);
-});
-
-/***/ }),
-/* 21 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var hasOwnProperty = {}.hasOwnProperty;
-module.exports = function (it, key) {
- return hasOwnProperty.call(it, key);
-};
-
-/***/ }),
-/* 22 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var id = 0;
-var px = Math.random();
-module.exports = function (key) {
- return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));
-};
-
-/***/ }),
-/* 23 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var aFunction = __w_pdfjs_require__(24);
-module.exports = function (fn, that, length) {
- aFunction(fn);
- if (that === undefined) return fn;
- switch (length) {
- case 1:
- return function (a) {
- return fn.call(that, a);
- };
- case 2:
- return function (a, b) {
- return fn.call(that, a, b);
- };
- case 3:
- return function (a, b, c) {
- return fn.call(that, a, b, c);
- };
- }
- return function () {
- return fn.apply(that, arguments);
- };
-};
-
-/***/ }),
-/* 24 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = function (it) {
- if (typeof it != 'function') throw TypeError(it + ' is not a function!');
- return it;
-};
-
-/***/ }),
-/* 25 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isRegExp = __w_pdfjs_require__(26);
-var defined = __w_pdfjs_require__(31);
-module.exports = function (that, searchString, NAME) {
- if (isRegExp(searchString)) throw TypeError('String#' + NAME + " doesn't accept regex!");
- return String(defined(that));
-};
-
-/***/ }),
-/* 26 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isObject = __w_pdfjs_require__(13);
-var cof = __w_pdfjs_require__(27);
-var MATCH = __w_pdfjs_require__(28)('match');
-module.exports = function (it) {
- var isRegExp;
- return isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : cof(it) == 'RegExp');
-};
-
-/***/ }),
-/* 27 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var toString = {}.toString;
-module.exports = function (it) {
- return toString.call(it).slice(8, -1);
-};
-
-/***/ }),
-/* 28 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var store = __w_pdfjs_require__(29)('wks');
-var uid = __w_pdfjs_require__(22);
-var _Symbol = __w_pdfjs_require__(8).Symbol;
-var USE_SYMBOL = typeof _Symbol == 'function';
-var $exports = module.exports = function (name) {
- return store[name] || (store[name] = USE_SYMBOL && _Symbol[name] || (USE_SYMBOL ? _Symbol : uid)('Symbol.' + name));
-};
-$exports.store = store;
-
-/***/ }),
-/* 29 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var core = __w_pdfjs_require__(9);
-var global = __w_pdfjs_require__(8);
-var SHARED = '__core-js_shared__';
-var store = global[SHARED] || (global[SHARED] = {});
-(module.exports = function (key, value) {
- return store[key] || (store[key] = value !== undefined ? value : {});
-})('versions', []).push({
- version: core.version,
- mode: __w_pdfjs_require__(30) ? 'pure' : 'global',
- copyright: '© 2018 Denis Pushkarev (zloirock.ru)'
-});
-
-/***/ }),
-/* 30 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = false;
-
-/***/ }),
-/* 31 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = function (it) {
- if (it == undefined) throw TypeError("Can't call method on " + it);
- return it;
-};
-
-/***/ }),
-/* 32 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var MATCH = __w_pdfjs_require__(28)('match');
-module.exports = function (KEY) {
- var re = /./;
- try {
- '/./'[KEY](re);
- } catch (e) {
- try {
- re[MATCH] = false;
- return !'/./'[KEY](re);
- } catch (f) {}
- }
- return true;
-};
-
-/***/ }),
-/* 33 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(34);
-module.exports = __w_pdfjs_require__(9).Array.includes;
-
-/***/ }),
-/* 34 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(7);
-var $includes = __w_pdfjs_require__(35)(true);
-$export($export.P, 'Array', {
- includes: function includes(el) {
- return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined);
- }
-});
-__w_pdfjs_require__(41)('includes');
-
-/***/ }),
-/* 35 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var toIObject = __w_pdfjs_require__(36);
-var toLength = __w_pdfjs_require__(38);
-var toAbsoluteIndex = __w_pdfjs_require__(40);
-module.exports = function (IS_INCLUDES) {
- return function ($this, el, fromIndex) {
- var O = toIObject($this);
- var length = toLength(O.length);
- var index = toAbsoluteIndex(fromIndex, length);
- var value;
- if (IS_INCLUDES && el != el) while (length > index) {
- value = O[index++];
- if (value != value) return true;
- } else for (; length > index; index++) {
- if (IS_INCLUDES || index in O) {
- if (O[index] === el) return IS_INCLUDES || index || 0;
- }
- }return !IS_INCLUDES && -1;
- };
-};
-
-/***/ }),
-/* 36 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var IObject = __w_pdfjs_require__(37);
-var defined = __w_pdfjs_require__(31);
-module.exports = function (it) {
- return IObject(defined(it));
-};
-
-/***/ }),
-/* 37 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var cof = __w_pdfjs_require__(27);
-module.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) {
- return cof(it) == 'String' ? it.split('') : Object(it);
-};
-
-/***/ }),
-/* 38 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var toInteger = __w_pdfjs_require__(39);
-var min = Math.min;
-module.exports = function (it) {
- return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0;
-};
-
-/***/ }),
-/* 39 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var ceil = Math.ceil;
-var floor = Math.floor;
-module.exports = function (it) {
- return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);
-};
-
-/***/ }),
-/* 40 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var toInteger = __w_pdfjs_require__(39);
-var max = Math.max;
-var min = Math.min;
-module.exports = function (index, length) {
- index = toInteger(index);
- return index < 0 ? max(index + length, 0) : min(index, length);
-};
-
-/***/ }),
-/* 41 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var UNSCOPABLES = __w_pdfjs_require__(28)('unscopables');
-var ArrayProto = Array.prototype;
-if (ArrayProto[UNSCOPABLES] == undefined) __w_pdfjs_require__(10)(ArrayProto, UNSCOPABLES, {});
-module.exports = function (key) {
- ArrayProto[UNSCOPABLES][key] = true;
-};
-
-/***/ }),
-/* 42 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(43);
-module.exports = __w_pdfjs_require__(9).Object.assign;
-
-/***/ }),
-/* 43 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(7);
-$export($export.S + $export.F, 'Object', { assign: __w_pdfjs_require__(44) });
-
-/***/ }),
-/* 44 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var getKeys = __w_pdfjs_require__(45);
-var gOPS = __w_pdfjs_require__(49);
-var pIE = __w_pdfjs_require__(50);
-var toObject = __w_pdfjs_require__(51);
-var IObject = __w_pdfjs_require__(37);
-var $assign = Object.assign;
-module.exports = !$assign || __w_pdfjs_require__(16)(function () {
- var A = {};
- var B = {};
- var S = Symbol();
- var K = 'abcdefghijklmnopqrst';
- A[S] = 7;
- K.split('').forEach(function (k) {
- B[k] = k;
- });
- return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K;
-}) ? function assign(target, source) {
- var T = toObject(target);
- var aLen = arguments.length;
- var index = 1;
- var getSymbols = gOPS.f;
- var isEnum = pIE.f;
- while (aLen > index) {
- var S = IObject(arguments[index++]);
- var keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S);
- var length = keys.length;
- var j = 0;
- var key;
- while (length > j) {
- if (isEnum.call(S, key = keys[j++])) T[key] = S[key];
- }
- }
- return T;
-} : $assign;
-
-/***/ }),
-/* 45 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $keys = __w_pdfjs_require__(46);
-var enumBugKeys = __w_pdfjs_require__(48);
-module.exports = Object.keys || function keys(O) {
- return $keys(O, enumBugKeys);
-};
-
-/***/ }),
-/* 46 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var has = __w_pdfjs_require__(21);
-var toIObject = __w_pdfjs_require__(36);
-var arrayIndexOf = __w_pdfjs_require__(35)(false);
-var IE_PROTO = __w_pdfjs_require__(47)('IE_PROTO');
-module.exports = function (object, names) {
- var O = toIObject(object);
- var i = 0;
- var result = [];
- var key;
- for (key in O) {
- if (key != IE_PROTO) has(O, key) && result.push(key);
- }while (names.length > i) {
- if (has(O, key = names[i++])) {
- ~arrayIndexOf(result, key) || result.push(key);
- }
- }return result;
-};
-
-/***/ }),
-/* 47 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var shared = __w_pdfjs_require__(29)('keys');
-var uid = __w_pdfjs_require__(22);
-module.exports = function (key) {
- return shared[key] || (shared[key] = uid(key));
-};
-
-/***/ }),
-/* 48 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'.split(',');
-
-/***/ }),
-/* 49 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-exports.f = Object.getOwnPropertySymbols;
-
-/***/ }),
-/* 50 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-exports.f = {}.propertyIsEnumerable;
-
-/***/ }),
-/* 51 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var defined = __w_pdfjs_require__(31);
-module.exports = function (it) {
- return Object(defined(it));
-};
-
-/***/ }),
-/* 52 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(53);
-module.exports = __w_pdfjs_require__(9).Math.log2;
-
-/***/ }),
-/* 53 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(7);
-$export($export.S, 'Math', {
- log2: function log2(x) {
- return Math.log(x) / Math.LN2;
- }
-});
-
-/***/ }),
-/* 54 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(55);
-module.exports = __w_pdfjs_require__(9).Number.isNaN;
-
-/***/ }),
-/* 55 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(7);
-$export($export.S, 'Number', {
- isNaN: function isNaN(number) {
- return number != number;
- }
-});
-
-/***/ }),
-/* 56 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(57);
-module.exports = __w_pdfjs_require__(9).Number.isInteger;
-
-/***/ }),
-/* 57 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(7);
-$export($export.S, 'Number', { isInteger: __w_pdfjs_require__(58) });
-
-/***/ }),
-/* 58 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isObject = __w_pdfjs_require__(13);
-var floor = Math.floor;
-module.exports = function isInteger(it) {
- return !isObject(it) && isFinite(it) && floor(it) === it;
-};
-
-/***/ }),
-/* 59 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(60);
-__w_pdfjs_require__(62);
-__w_pdfjs_require__(72);
-__w_pdfjs_require__(75);
-__w_pdfjs_require__(92);
-__w_pdfjs_require__(93);
-module.exports = __w_pdfjs_require__(9).Promise;
-
-/***/ }),
-/* 60 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var classof = __w_pdfjs_require__(61);
-var test = {};
-test[__w_pdfjs_require__(28)('toStringTag')] = 'z';
-if (test + '' != '[object z]') {
- __w_pdfjs_require__(20)(Object.prototype, 'toString', function toString() {
- return '[object ' + classof(this) + ']';
- }, true);
-}
-
-/***/ }),
-/* 61 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var cof = __w_pdfjs_require__(27);
-var TAG = __w_pdfjs_require__(28)('toStringTag');
-var ARG = cof(function () {
- return arguments;
-}()) == 'Arguments';
-var tryGet = function tryGet(it, key) {
- try {
- return it[key];
- } catch (e) {}
-};
-module.exports = function (it) {
- var O, T, B;
- return it === undefined ? 'Undefined' : it === null ? 'Null' : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T : ARG ? cof(O) : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B;
-};
-
-/***/ }),
-/* 62 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $at = __w_pdfjs_require__(63)(true);
-__w_pdfjs_require__(64)(String, 'String', function (iterated) {
- this._t = String(iterated);
- this._i = 0;
-}, function () {
- var O = this._t;
- var index = this._i;
- var point;
- if (index >= O.length) return {
- value: undefined,
- done: true
- };
- point = $at(O, index);
- this._i += point.length;
- return {
- value: point,
- done: false
- };
-});
-
-/***/ }),
-/* 63 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var toInteger = __w_pdfjs_require__(39);
-var defined = __w_pdfjs_require__(31);
-module.exports = function (TO_STRING) {
- return function (that, pos) {
- var s = String(defined(that));
- var i = toInteger(pos);
- var l = s.length;
- var a, b;
- if (i < 0 || i >= l) return TO_STRING ? '' : undefined;
- a = s.charCodeAt(i);
- return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff ? TO_STRING ? s.charAt(i) : a : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000;
- };
-};
-
-/***/ }),
-/* 64 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var LIBRARY = __w_pdfjs_require__(30);
-var $export = __w_pdfjs_require__(7);
-var redefine = __w_pdfjs_require__(20);
-var hide = __w_pdfjs_require__(10);
-var Iterators = __w_pdfjs_require__(65);
-var $iterCreate = __w_pdfjs_require__(66);
-var setToStringTag = __w_pdfjs_require__(70);
-var getPrototypeOf = __w_pdfjs_require__(71);
-var ITERATOR = __w_pdfjs_require__(28)('iterator');
-var BUGGY = !([].keys && 'next' in [].keys());
-var FF_ITERATOR = '@@iterator';
-var KEYS = 'keys';
-var VALUES = 'values';
-var returnThis = function returnThis() {
- return this;
-};
-module.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) {
- $iterCreate(Constructor, NAME, next);
- var getMethod = function getMethod(kind) {
- if (!BUGGY && kind in proto) return proto[kind];
- switch (kind) {
- case KEYS:
- return function keys() {
- return new Constructor(this, kind);
- };
- case VALUES:
- return function values() {
- return new Constructor(this, kind);
- };
- }
- return function entries() {
- return new Constructor(this, kind);
- };
- };
- var TAG = NAME + ' Iterator';
- var DEF_VALUES = DEFAULT == VALUES;
- var VALUES_BUG = false;
- var proto = Base.prototype;
- var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT];
- var $default = $native || getMethod(DEFAULT);
- var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined;
- var $anyNative = NAME == 'Array' ? proto.entries || $native : $native;
- var methods, key, IteratorPrototype;
- if ($anyNative) {
- IteratorPrototype = getPrototypeOf($anyNative.call(new Base()));
- if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) {
- setToStringTag(IteratorPrototype, TAG, true);
- if (!LIBRARY && typeof IteratorPrototype[ITERATOR] != 'function') hide(IteratorPrototype, ITERATOR, returnThis);
- }
- }
- if (DEF_VALUES && $native && $native.name !== VALUES) {
- VALUES_BUG = true;
- $default = function values() {
- return $native.call(this);
- };
- }
- if ((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) {
- hide(proto, ITERATOR, $default);
- }
- Iterators[NAME] = $default;
- Iterators[TAG] = returnThis;
- if (DEFAULT) {
- methods = {
- values: DEF_VALUES ? $default : getMethod(VALUES),
- keys: IS_SET ? $default : getMethod(KEYS),
- entries: $entries
- };
- if (FORCED) for (key in methods) {
- if (!(key in proto)) redefine(proto, key, methods[key]);
- } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods);
- }
- return methods;
-};
-
-/***/ }),
-/* 65 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = {};
-
-/***/ }),
-/* 66 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var create = __w_pdfjs_require__(67);
-var descriptor = __w_pdfjs_require__(19);
-var setToStringTag = __w_pdfjs_require__(70);
-var IteratorPrototype = {};
-__w_pdfjs_require__(10)(IteratorPrototype, __w_pdfjs_require__(28)('iterator'), function () {
- return this;
-});
-module.exports = function (Constructor, NAME, next) {
- Constructor.prototype = create(IteratorPrototype, { next: descriptor(1, next) });
- setToStringTag(Constructor, NAME + ' Iterator');
-};
-
-/***/ }),
-/* 67 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var anObject = __w_pdfjs_require__(12);
-var dPs = __w_pdfjs_require__(68);
-var enumBugKeys = __w_pdfjs_require__(48);
-var IE_PROTO = __w_pdfjs_require__(47)('IE_PROTO');
-var Empty = function Empty() {};
-var PROTOTYPE = 'prototype';
-var _createDict = function createDict() {
- var iframe = __w_pdfjs_require__(17)('iframe');
- var i = enumBugKeys.length;
- var lt = '<';
- var gt = '>';
- var iframeDocument;
- iframe.style.display = 'none';
- __w_pdfjs_require__(69).appendChild(iframe);
- iframe.src = 'javascript:';
- iframeDocument = iframe.contentWindow.document;
- iframeDocument.open();
- iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt);
- iframeDocument.close();
- _createDict = iframeDocument.F;
- while (i--) {
- delete _createDict[PROTOTYPE][enumBugKeys[i]];
- }return _createDict();
-};
-module.exports = Object.create || function create(O, Properties) {
- var result;
- if (O !== null) {
- Empty[PROTOTYPE] = anObject(O);
- result = new Empty();
- Empty[PROTOTYPE] = null;
- result[IE_PROTO] = O;
- } else result = _createDict();
- return Properties === undefined ? result : dPs(result, Properties);
-};
-
-/***/ }),
-/* 68 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var dP = __w_pdfjs_require__(11);
-var anObject = __w_pdfjs_require__(12);
-var getKeys = __w_pdfjs_require__(45);
-module.exports = __w_pdfjs_require__(15) ? Object.defineProperties : function defineProperties(O, Properties) {
- anObject(O);
- var keys = getKeys(Properties);
- var length = keys.length;
- var i = 0;
- var P;
- while (length > i) {
- dP.f(O, P = keys[i++], Properties[P]);
- }return O;
-};
-
-/***/ }),
-/* 69 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var document = __w_pdfjs_require__(8).document;
-module.exports = document && document.documentElement;
-
-/***/ }),
-/* 70 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var def = __w_pdfjs_require__(11).f;
-var has = __w_pdfjs_require__(21);
-var TAG = __w_pdfjs_require__(28)('toStringTag');
-module.exports = function (it, tag, stat) {
- if (it && !has(it = stat ? it : it.prototype, TAG)) def(it, TAG, {
- configurable: true,
- value: tag
- });
-};
-
-/***/ }),
-/* 71 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var has = __w_pdfjs_require__(21);
-var toObject = __w_pdfjs_require__(51);
-var IE_PROTO = __w_pdfjs_require__(47)('IE_PROTO');
-var ObjectProto = Object.prototype;
-module.exports = Object.getPrototypeOf || function (O) {
- O = toObject(O);
- if (has(O, IE_PROTO)) return O[IE_PROTO];
- if (typeof O.constructor == 'function' && O instanceof O.constructor) {
- return O.constructor.prototype;
- }
- return O instanceof Object ? ObjectProto : null;
-};
-
-/***/ }),
-/* 72 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $iterators = __w_pdfjs_require__(73);
-var getKeys = __w_pdfjs_require__(45);
-var redefine = __w_pdfjs_require__(20);
-var global = __w_pdfjs_require__(8);
-var hide = __w_pdfjs_require__(10);
-var Iterators = __w_pdfjs_require__(65);
-var wks = __w_pdfjs_require__(28);
-var ITERATOR = wks('iterator');
-var TO_STRING_TAG = wks('toStringTag');
-var ArrayValues = Iterators.Array;
-var DOMIterables = {
- CSSRuleList: true,
- CSSStyleDeclaration: false,
- CSSValueList: false,
- ClientRectList: false,
- DOMRectList: false,
- DOMStringList: false,
- DOMTokenList: true,
- DataTransferItemList: false,
- FileList: false,
- HTMLAllCollection: false,
- HTMLCollection: false,
- HTMLFormElement: false,
- HTMLSelectElement: false,
- MediaList: true,
- MimeTypeArray: false,
- NamedNodeMap: false,
- NodeList: true,
- PaintRequestList: false,
- Plugin: false,
- PluginArray: false,
- SVGLengthList: false,
- SVGNumberList: false,
- SVGPathSegList: false,
- SVGPointList: false,
- SVGStringList: false,
- SVGTransformList: false,
- SourceBufferList: false,
- StyleSheetList: true,
- TextTrackCueList: false,
- TextTrackList: false,
- TouchList: false
-};
-for (var collections = getKeys(DOMIterables), i = 0; i < collections.length; i++) {
- var NAME = collections[i];
- var explicit = DOMIterables[NAME];
- var Collection = global[NAME];
- var proto = Collection && Collection.prototype;
- var key;
- if (proto) {
- if (!proto[ITERATOR]) hide(proto, ITERATOR, ArrayValues);
- if (!proto[TO_STRING_TAG]) hide(proto, TO_STRING_TAG, NAME);
- Iterators[NAME] = ArrayValues;
- if (explicit) for (key in $iterators) {
- if (!proto[key]) redefine(proto, key, $iterators[key], true);
- }
- }
-}
-
-/***/ }),
-/* 73 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var addToUnscopables = __w_pdfjs_require__(41);
-var step = __w_pdfjs_require__(74);
-var Iterators = __w_pdfjs_require__(65);
-var toIObject = __w_pdfjs_require__(36);
-module.exports = __w_pdfjs_require__(64)(Array, 'Array', function (iterated, kind) {
- this._t = toIObject(iterated);
- this._i = 0;
- this._k = kind;
-}, function () {
- var O = this._t;
- var kind = this._k;
- var index = this._i++;
- if (!O || index >= O.length) {
- this._t = undefined;
- return step(1);
- }
- if (kind == 'keys') return step(0, index);
- if (kind == 'values') return step(0, O[index]);
- return step(0, [index, O[index]]);
-}, 'values');
-Iterators.Arguments = Iterators.Array;
-addToUnscopables('keys');
-addToUnscopables('values');
-addToUnscopables('entries');
-
-/***/ }),
-/* 74 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = function (done, value) {
- return {
- value: value,
- done: !!done
- };
-};
-
-/***/ }),
-/* 75 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var LIBRARY = __w_pdfjs_require__(30);
-var global = __w_pdfjs_require__(8);
-var ctx = __w_pdfjs_require__(23);
-var classof = __w_pdfjs_require__(61);
-var $export = __w_pdfjs_require__(7);
-var isObject = __w_pdfjs_require__(13);
-var aFunction = __w_pdfjs_require__(24);
-var anInstance = __w_pdfjs_require__(76);
-var forOf = __w_pdfjs_require__(77);
-var speciesConstructor = __w_pdfjs_require__(81);
-var task = __w_pdfjs_require__(82).set;
-var microtask = __w_pdfjs_require__(84)();
-var newPromiseCapabilityModule = __w_pdfjs_require__(85);
-var perform = __w_pdfjs_require__(86);
-var userAgent = __w_pdfjs_require__(87);
-var promiseResolve = __w_pdfjs_require__(88);
-var PROMISE = 'Promise';
-var TypeError = global.TypeError;
-var process = global.process;
-var versions = process && process.versions;
-var v8 = versions && versions.v8 || '';
-var $Promise = global[PROMISE];
-var isNode = classof(process) == 'process';
-var empty = function empty() {};
-var Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper;
-var newPromiseCapability = newGenericPromiseCapability = newPromiseCapabilityModule.f;
-var USE_NATIVE = !!function () {
- try {
- var promise = $Promise.resolve(1);
- var FakePromise = (promise.constructor = {})[__w_pdfjs_require__(28)('species')] = function (exec) {
- exec(empty, empty);
- };
- return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise && v8.indexOf('6.6') !== 0 && userAgent.indexOf('Chrome/66') === -1;
- } catch (e) {}
-}();
-var isThenable = function isThenable(it) {
- var then;
- return isObject(it) && typeof (then = it.then) == 'function' ? then : false;
-};
-var notify = function notify(promise, isReject) {
- if (promise._n) return;
- promise._n = true;
- var chain = promise._c;
- microtask(function () {
- var value = promise._v;
- var ok = promise._s == 1;
- var i = 0;
- var run = function run(reaction) {
- var handler = ok ? reaction.ok : reaction.fail;
- var resolve = reaction.resolve;
- var reject = reaction.reject;
- var domain = reaction.domain;
- var result, then, exited;
- try {
- if (handler) {
- if (!ok) {
- if (promise._h == 2) onHandleUnhandled(promise);
- promise._h = 1;
- }
- if (handler === true) result = value;else {
- if (domain) domain.enter();
- result = handler(value);
- if (domain) {
- domain.exit();
- exited = true;
- }
- }
- if (result === reaction.promise) {
- reject(TypeError('Promise-chain cycle'));
- } else if (then = isThenable(result)) {
- then.call(result, resolve, reject);
- } else resolve(result);
- } else reject(value);
- } catch (e) {
- if (domain && !exited) domain.exit();
- reject(e);
- }
- };
- while (chain.length > i) {
- run(chain[i++]);
- }promise._c = [];
- promise._n = false;
- if (isReject && !promise._h) onUnhandled(promise);
- });
-};
-var onUnhandled = function onUnhandled(promise) {
- task.call(global, function () {
- var value = promise._v;
- var unhandled = isUnhandled(promise);
- var result, handler, console;
- if (unhandled) {
- result = perform(function () {
- if (isNode) {
- process.emit('unhandledRejection', value, promise);
- } else if (handler = global.onunhandledrejection) {
- handler({
- promise: promise,
- reason: value
- });
- } else if ((console = global.console) && console.error) {
- console.error('Unhandled promise rejection', value);
- }
- });
- promise._h = isNode || isUnhandled(promise) ? 2 : 1;
- }
- promise._a = undefined;
- if (unhandled && result.e) throw result.v;
- });
-};
-var isUnhandled = function isUnhandled(promise) {
- return promise._h !== 1 && (promise._a || promise._c).length === 0;
-};
-var onHandleUnhandled = function onHandleUnhandled(promise) {
- task.call(global, function () {
- var handler;
- if (isNode) {
- process.emit('rejectionHandled', promise);
- } else if (handler = global.onrejectionhandled) {
- handler({
- promise: promise,
- reason: promise._v
- });
- }
- });
-};
-var $reject = function $reject(value) {
- var promise = this;
- if (promise._d) return;
- promise._d = true;
- promise = promise._w || promise;
- promise._v = value;
- promise._s = 2;
- if (!promise._a) promise._a = promise._c.slice();
- notify(promise, true);
-};
-var $resolve = function $resolve(value) {
- var promise = this;
- var then;
- if (promise._d) return;
- promise._d = true;
- promise = promise._w || promise;
- try {
- if (promise === value) throw TypeError("Promise can't be resolved itself");
- if (then = isThenable(value)) {
- microtask(function () {
- var wrapper = {
- _w: promise,
- _d: false
- };
- try {
- then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1));
- } catch (e) {
- $reject.call(wrapper, e);
- }
- });
- } else {
- promise._v = value;
- promise._s = 1;
- notify(promise, false);
- }
- } catch (e) {
- $reject.call({
- _w: promise,
- _d: false
- }, e);
- }
-};
-if (!USE_NATIVE) {
- $Promise = function Promise(executor) {
- anInstance(this, $Promise, PROMISE, '_h');
- aFunction(executor);
- Internal.call(this);
- try {
- executor(ctx($resolve, this, 1), ctx($reject, this, 1));
- } catch (err) {
- $reject.call(this, err);
- }
- };
- Internal = function Promise(executor) {
- this._c = [];
- this._a = undefined;
- this._s = 0;
- this._d = false;
- this._v = undefined;
- this._h = 0;
- this._n = false;
- };
- Internal.prototype = __w_pdfjs_require__(89)($Promise.prototype, {
- then: function then(onFulfilled, onRejected) {
- var reaction = newPromiseCapability(speciesConstructor(this, $Promise));
- reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;
- reaction.fail = typeof onRejected == 'function' && onRejected;
- reaction.domain = isNode ? process.domain : undefined;
- this._c.push(reaction);
- if (this._a) this._a.push(reaction);
- if (this._s) notify(this, false);
- return reaction.promise;
- },
- 'catch': function _catch(onRejected) {
- return this.then(undefined, onRejected);
- }
- });
- OwnPromiseCapability = function OwnPromiseCapability() {
- var promise = new Internal();
- this.promise = promise;
- this.resolve = ctx($resolve, promise, 1);
- this.reject = ctx($reject, promise, 1);
- };
- newPromiseCapabilityModule.f = newPromiseCapability = function newPromiseCapability(C) {
- return C === $Promise || C === Wrapper ? new OwnPromiseCapability(C) : newGenericPromiseCapability(C);
- };
-}
-$export($export.G + $export.W + $export.F * !USE_NATIVE, { Promise: $Promise });
-__w_pdfjs_require__(70)($Promise, PROMISE);
-__w_pdfjs_require__(90)(PROMISE);
-Wrapper = __w_pdfjs_require__(9)[PROMISE];
-$export($export.S + $export.F * !USE_NATIVE, PROMISE, {
- reject: function reject(r) {
- var capability = newPromiseCapability(this);
- var $$reject = capability.reject;
- $$reject(r);
- return capability.promise;
- }
-});
-$export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, {
- resolve: function resolve(x) {
- return promiseResolve(LIBRARY && this === Wrapper ? $Promise : this, x);
- }
-});
-$export($export.S + $export.F * !(USE_NATIVE && __w_pdfjs_require__(91)(function (iter) {
- $Promise.all(iter)['catch'](empty);
-})), PROMISE, {
- all: function all(iterable) {
- var C = this;
- var capability = newPromiseCapability(C);
- var resolve = capability.resolve;
- var reject = capability.reject;
- var result = perform(function () {
- var values = [];
- var index = 0;
- var remaining = 1;
- forOf(iterable, false, function (promise) {
- var $index = index++;
- var alreadyCalled = false;
- values.push(undefined);
- remaining++;
- C.resolve(promise).then(function (value) {
- if (alreadyCalled) return;
- alreadyCalled = true;
- values[$index] = value;
- --remaining || resolve(values);
- }, reject);
- });
- --remaining || resolve(values);
- });
- if (result.e) reject(result.v);
- return capability.promise;
- },
- race: function race(iterable) {
- var C = this;
- var capability = newPromiseCapability(C);
- var reject = capability.reject;
- var result = perform(function () {
- forOf(iterable, false, function (promise) {
- C.resolve(promise).then(capability.resolve, reject);
- });
- });
- if (result.e) reject(result.v);
- return capability.promise;
- }
-});
-
-/***/ }),
-/* 76 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = function (it, Constructor, name, forbiddenField) {
- if (!(it instanceof Constructor) || forbiddenField !== undefined && forbiddenField in it) {
- throw TypeError(name + ': incorrect invocation!');
- }
- return it;
-};
-
-/***/ }),
-/* 77 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var ctx = __w_pdfjs_require__(23);
-var call = __w_pdfjs_require__(78);
-var isArrayIter = __w_pdfjs_require__(79);
-var anObject = __w_pdfjs_require__(12);
-var toLength = __w_pdfjs_require__(38);
-var getIterFn = __w_pdfjs_require__(80);
-var BREAK = {};
-var RETURN = {};
-var _exports = module.exports = function (iterable, entries, fn, that, ITERATOR) {
- var iterFn = ITERATOR ? function () {
- return iterable;
- } : getIterFn(iterable);
- var f = ctx(fn, that, entries ? 2 : 1);
- var index = 0;
- var length, step, iterator, result;
- if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!');
- if (isArrayIter(iterFn)) for (length = toLength(iterable.length); length > index; index++) {
- result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]);
- if (result === BREAK || result === RETURN) return result;
- } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) {
- result = call(iterator, f, step.value, entries);
- if (result === BREAK || result === RETURN) return result;
- }
-};
-_exports.BREAK = BREAK;
-_exports.RETURN = RETURN;
-
-/***/ }),
-/* 78 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var anObject = __w_pdfjs_require__(12);
-module.exports = function (iterator, fn, value, entries) {
- try {
- return entries ? fn(anObject(value)[0], value[1]) : fn(value);
- } catch (e) {
- var ret = iterator['return'];
- if (ret !== undefined) anObject(ret.call(iterator));
- throw e;
- }
-};
-
-/***/ }),
-/* 79 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var Iterators = __w_pdfjs_require__(65);
-var ITERATOR = __w_pdfjs_require__(28)('iterator');
-var ArrayProto = Array.prototype;
-module.exports = function (it) {
- return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it);
-};
-
-/***/ }),
-/* 80 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var classof = __w_pdfjs_require__(61);
-var ITERATOR = __w_pdfjs_require__(28)('iterator');
-var Iterators = __w_pdfjs_require__(65);
-module.exports = __w_pdfjs_require__(9).getIteratorMethod = function (it) {
- if (it != undefined) return it[ITERATOR] || it['@@iterator'] || Iterators[classof(it)];
-};
-
-/***/ }),
-/* 81 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var anObject = __w_pdfjs_require__(12);
-var aFunction = __w_pdfjs_require__(24);
-var SPECIES = __w_pdfjs_require__(28)('species');
-module.exports = function (O, D) {
- var C = anObject(O).constructor;
- var S;
- return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S);
-};
-
-/***/ }),
-/* 82 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var ctx = __w_pdfjs_require__(23);
-var invoke = __w_pdfjs_require__(83);
-var html = __w_pdfjs_require__(69);
-var cel = __w_pdfjs_require__(17);
-var global = __w_pdfjs_require__(8);
-var process = global.process;
-var setTask = global.setImmediate;
-var clearTask = global.clearImmediate;
-var MessageChannel = global.MessageChannel;
-var Dispatch = global.Dispatch;
-var counter = 0;
-var queue = {};
-var ONREADYSTATECHANGE = 'onreadystatechange';
-var defer, channel, port;
-var run = function run() {
- var id = +this;
- if (queue.hasOwnProperty(id)) {
- var fn = queue[id];
- delete queue[id];
- fn();
- }
-};
-var listener = function listener(event) {
- run.call(event.data);
-};
-if (!setTask || !clearTask) {
- setTask = function setImmediate(fn) {
- var args = [];
- var i = 1;
- while (arguments.length > i) {
- args.push(arguments[i++]);
- }queue[++counter] = function () {
- invoke(typeof fn == 'function' ? fn : Function(fn), args);
- };
- defer(counter);
- return counter;
- };
- clearTask = function clearImmediate(id) {
- delete queue[id];
- };
- if (__w_pdfjs_require__(27)(process) == 'process') {
- defer = function defer(id) {
- process.nextTick(ctx(run, id, 1));
- };
- } else if (Dispatch && Dispatch.now) {
- defer = function defer(id) {
- Dispatch.now(ctx(run, id, 1));
- };
- } else if (MessageChannel) {
- channel = new MessageChannel();
- port = channel.port2;
- channel.port1.onmessage = listener;
- defer = ctx(port.postMessage, port, 1);
- } else if (global.addEventListener && typeof postMessage == 'function' && !global.importScripts) {
- defer = function defer(id) {
- global.postMessage(id + '', '*');
- };
- global.addEventListener('message', listener, false);
- } else if (ONREADYSTATECHANGE in cel('script')) {
- defer = function defer(id) {
- html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function () {
- html.removeChild(this);
- run.call(id);
- };
- };
- } else {
- defer = function defer(id) {
- setTimeout(ctx(run, id, 1), 0);
- };
- }
-}
-module.exports = {
- set: setTask,
- clear: clearTask
-};
-
-/***/ }),
-/* 83 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = function (fn, args, that) {
- var un = that === undefined;
- switch (args.length) {
- case 0:
- return un ? fn() : fn.call(that);
- case 1:
- return un ? fn(args[0]) : fn.call(that, args[0]);
- case 2:
- return un ? fn(args[0], args[1]) : fn.call(that, args[0], args[1]);
- case 3:
- return un ? fn(args[0], args[1], args[2]) : fn.call(that, args[0], args[1], args[2]);
- case 4:
- return un ? fn(args[0], args[1], args[2], args[3]) : fn.call(that, args[0], args[1], args[2], args[3]);
- }
- return fn.apply(that, args);
-};
-
-/***/ }),
-/* 84 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var global = __w_pdfjs_require__(8);
-var macrotask = __w_pdfjs_require__(82).set;
-var Observer = global.MutationObserver || global.WebKitMutationObserver;
-var process = global.process;
-var Promise = global.Promise;
-var isNode = __w_pdfjs_require__(27)(process) == 'process';
-module.exports = function () {
- var head, last, notify;
- var flush = function flush() {
- var parent, fn;
- if (isNode && (parent = process.domain)) parent.exit();
- while (head) {
- fn = head.fn;
- head = head.next;
- try {
- fn();
- } catch (e) {
- if (head) notify();else last = undefined;
- throw e;
- }
- }
- last = undefined;
- if (parent) parent.enter();
- };
- if (isNode) {
- notify = function notify() {
- process.nextTick(flush);
- };
- } else if (Observer && !(global.navigator && global.navigator.standalone)) {
- var toggle = true;
- var node = document.createTextNode('');
- new Observer(flush).observe(node, { characterData: true });
- notify = function notify() {
- node.data = toggle = !toggle;
- };
- } else if (Promise && Promise.resolve) {
- var promise = Promise.resolve(undefined);
- notify = function notify() {
- promise.then(flush);
- };
- } else {
- notify = function notify() {
- macrotask.call(global, flush);
- };
- }
- return function (fn) {
- var task = {
- fn: fn,
- next: undefined
- };
- if (last) last.next = task;
- if (!head) {
- head = task;
- notify();
- }
- last = task;
- };
-};
-
-/***/ }),
-/* 85 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var aFunction = __w_pdfjs_require__(24);
-function PromiseCapability(C) {
- var resolve, reject;
- this.promise = new C(function ($$resolve, $$reject) {
- if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor');
- resolve = $$resolve;
- reject = $$reject;
- });
- this.resolve = aFunction(resolve);
- this.reject = aFunction(reject);
-}
-module.exports.f = function (C) {
- return new PromiseCapability(C);
-};
-
-/***/ }),
-/* 86 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = function (exec) {
- try {
- return {
- e: false,
- v: exec()
- };
- } catch (e) {
- return {
- e: true,
- v: e
- };
- }
-};
-
-/***/ }),
-/* 87 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var global = __w_pdfjs_require__(8);
-var navigator = global.navigator;
-module.exports = navigator && navigator.userAgent || '';
-
-/***/ }),
-/* 88 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var anObject = __w_pdfjs_require__(12);
-var isObject = __w_pdfjs_require__(13);
-var newPromiseCapability = __w_pdfjs_require__(85);
-module.exports = function (C, x) {
- anObject(C);
- if (isObject(x) && x.constructor === C) return x;
- var promiseCapability = newPromiseCapability.f(C);
- var resolve = promiseCapability.resolve;
- resolve(x);
- return promiseCapability.promise;
-};
-
-/***/ }),
-/* 89 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var redefine = __w_pdfjs_require__(20);
-module.exports = function (target, src, safe) {
- for (var key in src) {
- redefine(target, key, src[key], safe);
- }return target;
-};
-
-/***/ }),
-/* 90 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var global = __w_pdfjs_require__(8);
-var dP = __w_pdfjs_require__(11);
-var DESCRIPTORS = __w_pdfjs_require__(15);
-var SPECIES = __w_pdfjs_require__(28)('species');
-module.exports = function (KEY) {
- var C = global[KEY];
- if (DESCRIPTORS && C && !C[SPECIES]) dP.f(C, SPECIES, {
- configurable: true,
- get: function get() {
- return this;
- }
- });
-};
-
-/***/ }),
-/* 91 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var ITERATOR = __w_pdfjs_require__(28)('iterator');
-var SAFE_CLOSING = false;
-try {
- var riter = [7][ITERATOR]();
- riter['return'] = function () {
- SAFE_CLOSING = true;
- };
- Array.from(riter, function () {
- throw 2;
- });
-} catch (e) {}
-module.exports = function (exec, skipClosing) {
- if (!skipClosing && !SAFE_CLOSING) return false;
- var safe = false;
- try {
- var arr = [7];
- var iter = arr[ITERATOR]();
- iter.next = function () {
- return { done: safe = true };
- };
- arr[ITERATOR] = function () {
- return iter;
- };
- exec(arr);
- } catch (e) {}
- return safe;
-};
-
-/***/ }),
-/* 92 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(7);
-var core = __w_pdfjs_require__(9);
-var global = __w_pdfjs_require__(8);
-var speciesConstructor = __w_pdfjs_require__(81);
-var promiseResolve = __w_pdfjs_require__(88);
-$export($export.P + $export.R, 'Promise', {
- 'finally': function _finally(onFinally) {
- var C = speciesConstructor(this, core.Promise || global.Promise);
- var isFunction = typeof onFinally == 'function';
- return this.then(isFunction ? function (x) {
- return promiseResolve(C, onFinally()).then(function () {
- return x;
- });
- } : onFinally, isFunction ? function (e) {
- return promiseResolve(C, onFinally()).then(function () {
- throw e;
- });
- } : onFinally);
- }
-});
-
-/***/ }),
-/* 93 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(7);
-var newPromiseCapability = __w_pdfjs_require__(85);
-var perform = __w_pdfjs_require__(86);
-$export($export.S, 'Promise', {
- 'try': function _try(callbackfn) {
- var promiseCapability = newPromiseCapability.f(this);
- var result = perform(callbackfn);
- (result.e ? promiseCapability.reject : promiseCapability.resolve)(result.v);
- return promiseCapability.promise;
- }
-});
-
-/***/ }),
-/* 94 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(60);
-__w_pdfjs_require__(72);
-__w_pdfjs_require__(95);
-__w_pdfjs_require__(107);
-__w_pdfjs_require__(109);
-module.exports = __w_pdfjs_require__(9).WeakMap;
-
-/***/ }),
-/* 95 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var each = __w_pdfjs_require__(96)(0);
-var redefine = __w_pdfjs_require__(20);
-var meta = __w_pdfjs_require__(100);
-var assign = __w_pdfjs_require__(44);
-var weak = __w_pdfjs_require__(101);
-var isObject = __w_pdfjs_require__(13);
-var fails = __w_pdfjs_require__(16);
-var validate = __w_pdfjs_require__(102);
-var WEAK_MAP = 'WeakMap';
-var getWeak = meta.getWeak;
-var isExtensible = Object.isExtensible;
-var uncaughtFrozenStore = weak.ufstore;
-var tmp = {};
-var InternalMap;
-var wrapper = function wrapper(get) {
- return function WeakMap() {
- return get(this, arguments.length > 0 ? arguments[0] : undefined);
- };
-};
-var methods = {
- get: function get(key) {
- if (isObject(key)) {
- var data = getWeak(key);
- if (data === true) return uncaughtFrozenStore(validate(this, WEAK_MAP)).get(key);
- return data ? data[this._i] : undefined;
- }
- },
- set: function set(key, value) {
- return weak.def(validate(this, WEAK_MAP), key, value);
- }
-};
-var $WeakMap = module.exports = __w_pdfjs_require__(103)(WEAK_MAP, wrapper, methods, weak, true, true);
-if (fails(function () {
- return new $WeakMap().set((Object.freeze || Object)(tmp), 7).get(tmp) != 7;
-})) {
- InternalMap = weak.getConstructor(wrapper, WEAK_MAP);
- assign(InternalMap.prototype, methods);
- meta.NEED = true;
- each(['delete', 'has', 'get', 'set'], function (key) {
- var proto = $WeakMap.prototype;
- var method = proto[key];
- redefine(proto, key, function (a, b) {
- if (isObject(a) && !isExtensible(a)) {
- if (!this._f) this._f = new InternalMap();
- var result = this._f[key](a, b);
- return key == 'set' ? this : result;
- }
- return method.call(this, a, b);
- });
- });
-}
-
-/***/ }),
-/* 96 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var ctx = __w_pdfjs_require__(23);
-var IObject = __w_pdfjs_require__(37);
-var toObject = __w_pdfjs_require__(51);
-var toLength = __w_pdfjs_require__(38);
-var asc = __w_pdfjs_require__(97);
-module.exports = function (TYPE, $create) {
- var IS_MAP = TYPE == 1;
- var IS_FILTER = TYPE == 2;
- var IS_SOME = TYPE == 3;
- var IS_EVERY = TYPE == 4;
- var IS_FIND_INDEX = TYPE == 6;
- var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;
- var create = $create || asc;
- return function ($this, callbackfn, that) {
- var O = toObject($this);
- var self = IObject(O);
- var f = ctx(callbackfn, that, 3);
- var length = toLength(self.length);
- var index = 0;
- var result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined;
- var val, res;
- for (; length > index; index++) {
- if (NO_HOLES || index in self) {
- val = self[index];
- res = f(val, index, O);
- if (TYPE) {
- if (IS_MAP) result[index] = res;else if (res) switch (TYPE) {
- case 3:
- return true;
- case 5:
- return val;
- case 6:
- return index;
- case 2:
- result.push(val);
- } else if (IS_EVERY) return false;
- }
- }
- }return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result;
- };
-};
-
-/***/ }),
-/* 97 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var speciesConstructor = __w_pdfjs_require__(98);
-module.exports = function (original, length) {
- return new (speciesConstructor(original))(length);
-};
-
-/***/ }),
-/* 98 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isObject = __w_pdfjs_require__(13);
-var isArray = __w_pdfjs_require__(99);
-var SPECIES = __w_pdfjs_require__(28)('species');
-module.exports = function (original) {
- var C;
- if (isArray(original)) {
- C = original.constructor;
- if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined;
- if (isObject(C)) {
- C = C[SPECIES];
- if (C === null) C = undefined;
- }
- }
- return C === undefined ? Array : C;
-};
-
-/***/ }),
-/* 99 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var cof = __w_pdfjs_require__(27);
-module.exports = Array.isArray || function isArray(arg) {
- return cof(arg) == 'Array';
-};
-
-/***/ }),
-/* 100 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-var META = __w_pdfjs_require__(22)('meta');
-var isObject = __w_pdfjs_require__(13);
-var has = __w_pdfjs_require__(21);
-var setDesc = __w_pdfjs_require__(11).f;
-var id = 0;
-var isExtensible = Object.isExtensible || function () {
- return true;
-};
-var FREEZE = !__w_pdfjs_require__(16)(function () {
- return isExtensible(Object.preventExtensions({}));
-});
-var setMeta = function setMeta(it) {
- setDesc(it, META, {
- value: {
- i: 'O' + ++id,
- w: {}
- }
- });
-};
-var fastKey = function fastKey(it, create) {
- if (!isObject(it)) return (typeof it === 'undefined' ? 'undefined' : _typeof(it)) == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;
- if (!has(it, META)) {
- if (!isExtensible(it)) return 'F';
- if (!create) return 'E';
- setMeta(it);
- }
- return it[META].i;
-};
-var getWeak = function getWeak(it, create) {
- if (!has(it, META)) {
- if (!isExtensible(it)) return true;
- if (!create) return false;
- setMeta(it);
- }
- return it[META].w;
-};
-var onFreeze = function onFreeze(it) {
- if (FREEZE && meta.NEED && isExtensible(it) && !has(it, META)) setMeta(it);
- return it;
-};
-var meta = module.exports = {
- KEY: META,
- NEED: false,
- fastKey: fastKey,
- getWeak: getWeak,
- onFreeze: onFreeze
-};
-
-/***/ }),
-/* 101 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var redefineAll = __w_pdfjs_require__(89);
-var getWeak = __w_pdfjs_require__(100).getWeak;
-var anObject = __w_pdfjs_require__(12);
-var isObject = __w_pdfjs_require__(13);
-var anInstance = __w_pdfjs_require__(76);
-var forOf = __w_pdfjs_require__(77);
-var createArrayMethod = __w_pdfjs_require__(96);
-var $has = __w_pdfjs_require__(21);
-var validate = __w_pdfjs_require__(102);
-var arrayFind = createArrayMethod(5);
-var arrayFindIndex = createArrayMethod(6);
-var id = 0;
-var uncaughtFrozenStore = function uncaughtFrozenStore(that) {
- return that._l || (that._l = new UncaughtFrozenStore());
-};
-var UncaughtFrozenStore = function UncaughtFrozenStore() {
- this.a = [];
-};
-var findUncaughtFrozen = function findUncaughtFrozen(store, key) {
- return arrayFind(store.a, function (it) {
- return it[0] === key;
- });
-};
-UncaughtFrozenStore.prototype = {
- get: function get(key) {
- var entry = findUncaughtFrozen(this, key);
- if (entry) return entry[1];
- },
- has: function has(key) {
- return !!findUncaughtFrozen(this, key);
- },
- set: function set(key, value) {
- var entry = findUncaughtFrozen(this, key);
- if (entry) entry[1] = value;else this.a.push([key, value]);
- },
- 'delete': function _delete(key) {
- var index = arrayFindIndex(this.a, function (it) {
- return it[0] === key;
- });
- if (~index) this.a.splice(index, 1);
- return !!~index;
- }
-};
-module.exports = {
- getConstructor: function getConstructor(wrapper, NAME, IS_MAP, ADDER) {
- var C = wrapper(function (that, iterable) {
- anInstance(that, C, NAME, '_i');
- that._t = NAME;
- that._i = id++;
- that._l = undefined;
- if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);
- });
- redefineAll(C.prototype, {
- 'delete': function _delete(key) {
- if (!isObject(key)) return false;
- var data = getWeak(key);
- if (data === true) return uncaughtFrozenStore(validate(this, NAME))['delete'](key);
- return data && $has(data, this._i) && delete data[this._i];
- },
- has: function has(key) {
- if (!isObject(key)) return false;
- var data = getWeak(key);
- if (data === true) return uncaughtFrozenStore(validate(this, NAME)).has(key);
- return data && $has(data, this._i);
- }
- });
- return C;
- },
- def: function def(that, key, value) {
- var data = getWeak(anObject(key), true);
- if (data === true) uncaughtFrozenStore(that).set(key, value);else data[that._i] = value;
- return that;
- },
- ufstore: uncaughtFrozenStore
-};
-
-/***/ }),
-/* 102 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isObject = __w_pdfjs_require__(13);
-module.exports = function (it, TYPE) {
- if (!isObject(it) || it._t !== TYPE) throw TypeError('Incompatible receiver, ' + TYPE + ' required!');
- return it;
-};
-
-/***/ }),
-/* 103 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var global = __w_pdfjs_require__(8);
-var $export = __w_pdfjs_require__(7);
-var redefine = __w_pdfjs_require__(20);
-var redefineAll = __w_pdfjs_require__(89);
-var meta = __w_pdfjs_require__(100);
-var forOf = __w_pdfjs_require__(77);
-var anInstance = __w_pdfjs_require__(76);
-var isObject = __w_pdfjs_require__(13);
-var fails = __w_pdfjs_require__(16);
-var $iterDetect = __w_pdfjs_require__(91);
-var setToStringTag = __w_pdfjs_require__(70);
-var inheritIfRequired = __w_pdfjs_require__(104);
-module.exports = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) {
- var Base = global[NAME];
- var C = Base;
- var ADDER = IS_MAP ? 'set' : 'add';
- var proto = C && C.prototype;
- var O = {};
- var fixMethod = function fixMethod(KEY) {
- var fn = proto[KEY];
- redefine(proto, KEY, KEY == 'delete' ? function (a) {
- return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);
- } : KEY == 'has' ? function has(a) {
- return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);
- } : KEY == 'get' ? function get(a) {
- return IS_WEAK && !isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a);
- } : KEY == 'add' ? function add(a) {
- fn.call(this, a === 0 ? 0 : a);
- return this;
- } : function set(a, b) {
- fn.call(this, a === 0 ? 0 : a, b);
- return this;
- });
- };
- if (typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function () {
- new C().entries().next();
- }))) {
- C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER);
- redefineAll(C.prototype, methods);
- meta.NEED = true;
- } else {
- var instance = new C();
- var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance;
- var THROWS_ON_PRIMITIVES = fails(function () {
- instance.has(1);
- });
- var ACCEPT_ITERABLES = $iterDetect(function (iter) {
- new C(iter);
- });
- var BUGGY_ZERO = !IS_WEAK && fails(function () {
- var $instance = new C();
- var index = 5;
- while (index--) {
- $instance[ADDER](index, index);
- }return !$instance.has(-0);
- });
- if (!ACCEPT_ITERABLES) {
- C = wrapper(function (target, iterable) {
- anInstance(target, C, NAME);
- var that = inheritIfRequired(new Base(), target, C);
- if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);
- return that;
- });
- C.prototype = proto;
- proto.constructor = C;
- }
- if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {
- fixMethod('delete');
- fixMethod('has');
- IS_MAP && fixMethod('get');
- }
- if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);
- if (IS_WEAK && proto.clear) delete proto.clear;
- }
- setToStringTag(C, NAME);
- O[NAME] = C;
- $export($export.G + $export.W + $export.F * (C != Base), O);
- if (!IS_WEAK) common.setStrong(C, NAME, IS_MAP);
- return C;
-};
-
-/***/ }),
-/* 104 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isObject = __w_pdfjs_require__(13);
-var setPrototypeOf = __w_pdfjs_require__(105).set;
-module.exports = function (that, target, C) {
- var S = target.constructor;
- var P;
- if (S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && isObject(P) && setPrototypeOf) {
- setPrototypeOf(that, P);
- }
- return that;
-};
-
-/***/ }),
-/* 105 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isObject = __w_pdfjs_require__(13);
-var anObject = __w_pdfjs_require__(12);
-var check = function check(O, proto) {
- anObject(O);
- if (!isObject(proto) && proto !== null) throw TypeError(proto + ": can't set as prototype!");
-};
-module.exports = {
- set: Object.setPrototypeOf || ('__proto__' in {} ? function (test, buggy, set) {
- try {
- set = __w_pdfjs_require__(23)(Function.call, __w_pdfjs_require__(106).f(Object.prototype, '__proto__').set, 2);
- set(test, []);
- buggy = !(test instanceof Array);
- } catch (e) {
- buggy = true;
- }
- return function setPrototypeOf(O, proto) {
- check(O, proto);
- if (buggy) O.__proto__ = proto;else set(O, proto);
- return O;
- };
- }({}, false) : undefined),
- check: check
-};
-
-/***/ }),
-/* 106 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var pIE = __w_pdfjs_require__(50);
-var createDesc = __w_pdfjs_require__(19);
-var toIObject = __w_pdfjs_require__(36);
-var toPrimitive = __w_pdfjs_require__(18);
-var has = __w_pdfjs_require__(21);
-var IE8_DOM_DEFINE = __w_pdfjs_require__(14);
-var gOPD = Object.getOwnPropertyDescriptor;
-exports.f = __w_pdfjs_require__(15) ? gOPD : function getOwnPropertyDescriptor(O, P) {
- O = toIObject(O);
- P = toPrimitive(P, true);
- if (IE8_DOM_DEFINE) try {
- return gOPD(O, P);
- } catch (e) {}
- if (has(O, P)) return createDesc(!pIE.f.call(O, P), O[P]);
-};
-
-/***/ }),
-/* 107 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(108)('WeakMap');
-
-/***/ }),
-/* 108 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(7);
-module.exports = function (COLLECTION) {
- $export($export.S, COLLECTION, {
- of: function of() {
- var length = arguments.length;
- var A = new Array(length);
- while (length--) {
- A[length] = arguments[length];
- }return new this(A);
- }
- });
-};
-
-/***/ }),
-/* 109 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(110)('WeakMap');
-
-/***/ }),
-/* 110 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(7);
-var aFunction = __w_pdfjs_require__(24);
-var ctx = __w_pdfjs_require__(23);
-var forOf = __w_pdfjs_require__(77);
-module.exports = function (COLLECTION) {
- $export($export.S, COLLECTION, {
- from: function from(source) {
- var mapFn = arguments[1];
- var mapping, A, n, cb;
- aFunction(this);
- mapping = mapFn !== undefined;
- if (mapping) aFunction(mapFn);
- if (source == undefined) return new this();
- A = [];
- if (mapping) {
- n = 0;
- cb = ctx(mapFn, arguments[2], 2);
- forOf(source, false, function (nextItem) {
- A.push(cb(nextItem, n++));
- });
- } else {
- forOf(source, false, A.push, A);
- }
- return new this(A);
- }
- });
-};
-
-/***/ }),
-/* 111 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(112);
-module.exports = __w_pdfjs_require__(9).String.codePointAt;
-
-/***/ }),
-/* 112 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(7);
-var $at = __w_pdfjs_require__(63)(false);
-$export($export.P, 'String', {
- codePointAt: function codePointAt(pos) {
- return $at(this, pos);
- }
-});
-
-/***/ }),
-/* 113 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(114);
-module.exports = __w_pdfjs_require__(9).String.fromCodePoint;
-
-/***/ }),
-/* 114 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(7);
-var toAbsoluteIndex = __w_pdfjs_require__(40);
-var fromCharCode = String.fromCharCode;
-var $fromCodePoint = String.fromCodePoint;
-$export($export.S + $export.F * (!!$fromCodePoint && $fromCodePoint.length != 1), 'String', {
- fromCodePoint: function fromCodePoint(x) {
- var res = [];
- var aLen = arguments.length;
- var i = 0;
- var code;
- while (aLen > i) {
- code = +arguments[i++];
- if (toAbsoluteIndex(code, 0x10ffff) !== code) throw RangeError(code + ' is not a valid code point');
- res.push(code < 0x10000 ? fromCharCode(code) : fromCharCode(((code -= 0x10000) >> 10) + 0xd800, code % 0x400 + 0xdc00));
- }
- return res.join('');
- }
-});
-
-/***/ }),
-/* 115 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(116);
-__w_pdfjs_require__(60);
-module.exports = __w_pdfjs_require__(9).Symbol;
-
-/***/ }),
-/* 116 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-var global = __w_pdfjs_require__(8);
-var has = __w_pdfjs_require__(21);
-var DESCRIPTORS = __w_pdfjs_require__(15);
-var $export = __w_pdfjs_require__(7);
-var redefine = __w_pdfjs_require__(20);
-var META = __w_pdfjs_require__(100).KEY;
-var $fails = __w_pdfjs_require__(16);
-var shared = __w_pdfjs_require__(29);
-var setToStringTag = __w_pdfjs_require__(70);
-var uid = __w_pdfjs_require__(22);
-var wks = __w_pdfjs_require__(28);
-var wksExt = __w_pdfjs_require__(117);
-var wksDefine = __w_pdfjs_require__(118);
-var enumKeys = __w_pdfjs_require__(119);
-var isArray = __w_pdfjs_require__(99);
-var anObject = __w_pdfjs_require__(12);
-var isObject = __w_pdfjs_require__(13);
-var toIObject = __w_pdfjs_require__(36);
-var toPrimitive = __w_pdfjs_require__(18);
-var createDesc = __w_pdfjs_require__(19);
-var _create = __w_pdfjs_require__(67);
-var gOPNExt = __w_pdfjs_require__(120);
-var $GOPD = __w_pdfjs_require__(106);
-var $DP = __w_pdfjs_require__(11);
-var $keys = __w_pdfjs_require__(45);
-var gOPD = $GOPD.f;
-var dP = $DP.f;
-var gOPN = gOPNExt.f;
-var $Symbol = global.Symbol;
-var $JSON = global.JSON;
-var _stringify = $JSON && $JSON.stringify;
-var PROTOTYPE = 'prototype';
-var HIDDEN = wks('_hidden');
-var TO_PRIMITIVE = wks('toPrimitive');
-var isEnum = {}.propertyIsEnumerable;
-var SymbolRegistry = shared('symbol-registry');
-var AllSymbols = shared('symbols');
-var OPSymbols = shared('op-symbols');
-var ObjectProto = Object[PROTOTYPE];
-var USE_NATIVE = typeof $Symbol == 'function';
-var QObject = global.QObject;
-var setter = !QObject || !QObject[PROTOTYPE] || !QObject[PROTOTYPE].findChild;
-var setSymbolDesc = DESCRIPTORS && $fails(function () {
- return _create(dP({}, 'a', {
- get: function get() {
- return dP(this, 'a', { value: 7 }).a;
- }
- })).a != 7;
-}) ? function (it, key, D) {
- var protoDesc = gOPD(ObjectProto, key);
- if (protoDesc) delete ObjectProto[key];
- dP(it, key, D);
- if (protoDesc && it !== ObjectProto) dP(ObjectProto, key, protoDesc);
-} : dP;
-var wrap = function wrap(tag) {
- var sym = AllSymbols[tag] = _create($Symbol[PROTOTYPE]);
- sym._k = tag;
- return sym;
-};
-var isSymbol = USE_NATIVE && _typeof($Symbol.iterator) == 'symbol' ? function (it) {
- return (typeof it === 'undefined' ? 'undefined' : _typeof(it)) == 'symbol';
-} : function (it) {
- return it instanceof $Symbol;
-};
-var $defineProperty = function defineProperty(it, key, D) {
- if (it === ObjectProto) $defineProperty(OPSymbols, key, D);
- anObject(it);
- key = toPrimitive(key, true);
- anObject(D);
- if (has(AllSymbols, key)) {
- if (!D.enumerable) {
- if (!has(it, HIDDEN)) dP(it, HIDDEN, createDesc(1, {}));
- it[HIDDEN][key] = true;
- } else {
- if (has(it, HIDDEN) && it[HIDDEN][key]) it[HIDDEN][key] = false;
- D = _create(D, { enumerable: createDesc(0, false) });
- }
- return setSymbolDesc(it, key, D);
- }
- return dP(it, key, D);
-};
-var $defineProperties = function defineProperties(it, P) {
- anObject(it);
- var keys = enumKeys(P = toIObject(P));
- var i = 0;
- var l = keys.length;
- var key;
- while (l > i) {
- $defineProperty(it, key = keys[i++], P[key]);
- }return it;
-};
-var $create = function create(it, P) {
- return P === undefined ? _create(it) : $defineProperties(_create(it), P);
-};
-var $propertyIsEnumerable = function propertyIsEnumerable(key) {
- var E = isEnum.call(this, key = toPrimitive(key, true));
- if (this === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key)) return false;
- return E || !has(this, key) || !has(AllSymbols, key) || has(this, HIDDEN) && this[HIDDEN][key] ? E : true;
-};
-var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(it, key) {
- it = toIObject(it);
- key = toPrimitive(key, true);
- if (it === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key)) return;
- var D = gOPD(it, key);
- if (D && has(AllSymbols, key) && !(has(it, HIDDEN) && it[HIDDEN][key])) D.enumerable = true;
- return D;
-};
-var $getOwnPropertyNames = function getOwnPropertyNames(it) {
- var names = gOPN(toIObject(it));
- var result = [];
- var i = 0;
- var key;
- while (names.length > i) {
- if (!has(AllSymbols, key = names[i++]) && key != HIDDEN && key != META) result.push(key);
- }
- return result;
-};
-var $getOwnPropertySymbols = function getOwnPropertySymbols(it) {
- var IS_OP = it === ObjectProto;
- var names = gOPN(IS_OP ? OPSymbols : toIObject(it));
- var result = [];
- var i = 0;
- var key;
- while (names.length > i) {
- if (has(AllSymbols, key = names[i++]) && (IS_OP ? has(ObjectProto, key) : true)) result.push(AllSymbols[key]);
- }
- return result;
-};
-if (!USE_NATIVE) {
- $Symbol = function _Symbol() {
- if (this instanceof $Symbol) throw TypeError('Symbol is not a constructor!');
- var tag = uid(arguments.length > 0 ? arguments[0] : undefined);
- var $set = function $set(value) {
- if (this === ObjectProto) $set.call(OPSymbols, value);
- if (has(this, HIDDEN) && has(this[HIDDEN], tag)) this[HIDDEN][tag] = false;
- setSymbolDesc(this, tag, createDesc(1, value));
- };
- if (DESCRIPTORS && setter) setSymbolDesc(ObjectProto, tag, {
- configurable: true,
- set: $set
- });
- return wrap(tag);
- };
- redefine($Symbol[PROTOTYPE], 'toString', function toString() {
- return this._k;
- });
- $GOPD.f = $getOwnPropertyDescriptor;
- $DP.f = $defineProperty;
- __w_pdfjs_require__(121).f = gOPNExt.f = $getOwnPropertyNames;
- __w_pdfjs_require__(50).f = $propertyIsEnumerable;
- __w_pdfjs_require__(49).f = $getOwnPropertySymbols;
- if (DESCRIPTORS && !__w_pdfjs_require__(30)) {
- redefine(ObjectProto, 'propertyIsEnumerable', $propertyIsEnumerable, true);
- }
- wksExt.f = function (name) {
- return wrap(wks(name));
- };
-}
-$export($export.G + $export.W + $export.F * !USE_NATIVE, { Symbol: $Symbol });
-for (var es6Symbols = 'hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables'.split(','), j = 0; es6Symbols.length > j;) {
- wks(es6Symbols[j++]);
-}for (var wellKnownSymbols = $keys(wks.store), k = 0; wellKnownSymbols.length > k;) {
- wksDefine(wellKnownSymbols[k++]);
-}$export($export.S + $export.F * !USE_NATIVE, 'Symbol', {
- 'for': function _for(key) {
- return has(SymbolRegistry, key += '') ? SymbolRegistry[key] : SymbolRegistry[key] = $Symbol(key);
- },
- keyFor: function keyFor(sym) {
- if (!isSymbol(sym)) throw TypeError(sym + ' is not a symbol!');
- for (var key in SymbolRegistry) {
- if (SymbolRegistry[key] === sym) return key;
- }
- },
- useSetter: function useSetter() {
- setter = true;
- },
- useSimple: function useSimple() {
- setter = false;
- }
-});
-$export($export.S + $export.F * !USE_NATIVE, 'Object', {
- create: $create,
- defineProperty: $defineProperty,
- defineProperties: $defineProperties,
- getOwnPropertyDescriptor: $getOwnPropertyDescriptor,
- getOwnPropertyNames: $getOwnPropertyNames,
- getOwnPropertySymbols: $getOwnPropertySymbols
-});
-$JSON && $export($export.S + $export.F * (!USE_NATIVE || $fails(function () {
- var S = $Symbol();
- return _stringify([S]) != '[null]' || _stringify({ a: S }) != '{}' || _stringify(Object(S)) != '{}';
-})), 'JSON', {
- stringify: function stringify(it) {
- var args = [it];
- var i = 1;
- var replacer, $replacer;
- while (arguments.length > i) {
- args.push(arguments[i++]);
- }$replacer = replacer = args[1];
- if (!isObject(replacer) && it === undefined || isSymbol(it)) return;
- if (!isArray(replacer)) replacer = function replacer(key, value) {
- if (typeof $replacer == 'function') value = $replacer.call(this, key, value);
- if (!isSymbol(value)) return value;
- };
- args[1] = replacer;
- return _stringify.apply($JSON, args);
- }
-});
-$Symbol[PROTOTYPE][TO_PRIMITIVE] || __w_pdfjs_require__(10)($Symbol[PROTOTYPE], TO_PRIMITIVE, $Symbol[PROTOTYPE].valueOf);
-setToStringTag($Symbol, 'Symbol');
-setToStringTag(Math, 'Math', true);
-setToStringTag(global.JSON, 'JSON', true);
-
-/***/ }),
-/* 117 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-exports.f = __w_pdfjs_require__(28);
-
-/***/ }),
-/* 118 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var global = __w_pdfjs_require__(8);
-var core = __w_pdfjs_require__(9);
-var LIBRARY = __w_pdfjs_require__(30);
-var wksExt = __w_pdfjs_require__(117);
-var defineProperty = __w_pdfjs_require__(11).f;
-module.exports = function (name) {
- var $Symbol = core.Symbol || (core.Symbol = LIBRARY ? {} : global.Symbol || {});
- if (name.charAt(0) != '_' && !(name in $Symbol)) defineProperty($Symbol, name, { value: wksExt.f(name) });
-};
-
-/***/ }),
-/* 119 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var getKeys = __w_pdfjs_require__(45);
-var gOPS = __w_pdfjs_require__(49);
-var pIE = __w_pdfjs_require__(50);
-module.exports = function (it) {
- var result = getKeys(it);
- var getSymbols = gOPS.f;
- if (getSymbols) {
- var symbols = getSymbols(it);
- var isEnum = pIE.f;
- var i = 0;
- var key;
- while (symbols.length > i) {
- if (isEnum.call(it, key = symbols[i++])) result.push(key);
- }
- }
- return result;
-};
-
-/***/ }),
-/* 120 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-var toIObject = __w_pdfjs_require__(36);
-var gOPN = __w_pdfjs_require__(121).f;
-var toString = {}.toString;
-var windowNames = (typeof window === 'undefined' ? 'undefined' : _typeof(window)) == 'object' && window && Object.getOwnPropertyNames ? Object.getOwnPropertyNames(window) : [];
-var getWindowNames = function getWindowNames(it) {
- try {
- return gOPN(it);
- } catch (e) {
- return windowNames.slice();
- }
-};
-module.exports.f = function getOwnPropertyNames(it) {
- return windowNames && toString.call(it) == '[object Window]' ? getWindowNames(it) : gOPN(toIObject(it));
-};
-
-/***/ }),
-/* 121 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $keys = __w_pdfjs_require__(46);
-var hiddenKeys = __w_pdfjs_require__(48).concat('length', 'prototype');
-exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
- return $keys(O, hiddenKeys);
-};
-
-/***/ }),
-/* 122 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(123);
-module.exports = __w_pdfjs_require__(9).Object.values;
-
-/***/ }),
-/* 123 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(7);
-var $values = __w_pdfjs_require__(124)(false);
-$export($export.S, 'Object', {
- values: function values(it) {
- return $values(it);
- }
-});
-
-/***/ }),
-/* 124 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var getKeys = __w_pdfjs_require__(45);
-var toIObject = __w_pdfjs_require__(36);
-var isEnum = __w_pdfjs_require__(50).f;
-module.exports = function (isEntries) {
- return function (it) {
- var O = toIObject(it);
- var keys = getKeys(O);
- var length = keys.length;
- var i = 0;
- var result = [];
- var key;
- while (length > i) {
- if (isEnum.call(O, key = keys[i++])) {
- result.push(isEntries ? [key, O[key]] : O[key]);
- }
- }return result;
- };
-};
-
-/***/ }),
-/* 125 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isReadableStreamSupported = false;
-if (typeof ReadableStream !== 'undefined') {
- try {
- new ReadableStream({
- start: function start(controller) {
- controller.close();
- }
- });
- isReadableStreamSupported = true;
- } catch (e) {}
-}
-if (isReadableStreamSupported) {
- exports.ReadableStream = ReadableStream;
-} else {
- exports.ReadableStream = __w_pdfjs_require__(126).ReadableStream;
-}
-
-/***/ }),
-/* 126 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var _typeof2 = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-(function (e, a) {
- for (var i in a) {
- e[i] = a[i];
- }
-})(exports, function (modules) {
- var installedModules = {};
- function __w_pdfjs_require__(moduleId) {
- if (installedModules[moduleId]) return installedModules[moduleId].exports;
- var module = installedModules[moduleId] = {
- i: moduleId,
- l: false,
- exports: {}
- };
- modules[moduleId].call(module.exports, module, module.exports, __w_pdfjs_require__);
- module.l = true;
- return module.exports;
- }
- __w_pdfjs_require__.m = modules;
- __w_pdfjs_require__.c = installedModules;
- __w_pdfjs_require__.i = function (value) {
- return value;
- };
- __w_pdfjs_require__.d = function (exports, name, getter) {
- if (!__w_pdfjs_require__.o(exports, name)) {
- Object.defineProperty(exports, name, {
- configurable: false,
- enumerable: true,
- get: getter
- });
- }
- };
- __w_pdfjs_require__.n = function (module) {
- var getter = module && module.__esModule ? function getDefault() {
- return module['default'];
- } : function getModuleExports() {
- return module;
- };
- __w_pdfjs_require__.d(getter, 'a', getter);
- return getter;
- };
- __w_pdfjs_require__.o = function (object, property) {
- return Object.prototype.hasOwnProperty.call(object, property);
- };
- __w_pdfjs_require__.p = "";
- return __w_pdfjs_require__(__w_pdfjs_require__.s = 7);
-}([function (module, exports, __w_pdfjs_require__) {
- "use strict";
-
- var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) {
- return typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
- } : function (obj) {
- return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
- };
- var _require = __w_pdfjs_require__(1),
- assert = _require.assert;
- function IsPropertyKey(argument) {
- return typeof argument === 'string' || (typeof argument === 'undefined' ? 'undefined' : _typeof(argument)) === 'symbol';
- }
- exports.typeIsObject = function (x) {
- return (typeof x === 'undefined' ? 'undefined' : _typeof(x)) === 'object' && x !== null || typeof x === 'function';
- };
- exports.createDataProperty = function (o, p, v) {
- assert(exports.typeIsObject(o));
- Object.defineProperty(o, p, {
- value: v,
- writable: true,
- enumerable: true,
- configurable: true
- });
- };
- exports.createArrayFromList = function (elements) {
- return elements.slice();
- };
- exports.ArrayBufferCopy = function (dest, destOffset, src, srcOffset, n) {
- new Uint8Array(dest).set(new Uint8Array(src, srcOffset, n), destOffset);
- };
- exports.CreateIterResultObject = function (value, done) {
- assert(typeof done === 'boolean');
- var obj = {};
- Object.defineProperty(obj, 'value', {
- value: value,
- enumerable: true,
- writable: true,
- configurable: true
- });
- Object.defineProperty(obj, 'done', {
- value: done,
- enumerable: true,
- writable: true,
- configurable: true
- });
- return obj;
- };
- exports.IsFiniteNonNegativeNumber = function (v) {
- if (Number.isNaN(v)) {
- return false;
- }
- if (v === Infinity) {
- return false;
- }
- if (v < 0) {
- return false;
- }
- return true;
- };
- function Call(F, V, args) {
- if (typeof F !== 'function') {
- throw new TypeError('Argument is not a function');
- }
- return Function.prototype.apply.call(F, V, args);
- }
- exports.InvokeOrNoop = function (O, P, args) {
- assert(O !== undefined);
- assert(IsPropertyKey(P));
- assert(Array.isArray(args));
- var method = O[P];
- if (method === undefined) {
- return undefined;
- }
- return Call(method, O, args);
- };
- exports.PromiseInvokeOrNoop = function (O, P, args) {
- assert(O !== undefined);
- assert(IsPropertyKey(P));
- assert(Array.isArray(args));
- try {
- return Promise.resolve(exports.InvokeOrNoop(O, P, args));
- } catch (returnValueE) {
- return Promise.reject(returnValueE);
- }
- };
- exports.PromiseInvokeOrPerformFallback = function (O, P, args, F, argsF) {
- assert(O !== undefined);
- assert(IsPropertyKey(P));
- assert(Array.isArray(args));
- assert(Array.isArray(argsF));
- var method = void 0;
- try {
- method = O[P];
- } catch (methodE) {
- return Promise.reject(methodE);
- }
- if (method === undefined) {
- return F.apply(null, argsF);
- }
- try {
- return Promise.resolve(Call(method, O, args));
- } catch (e) {
- return Promise.reject(e);
- }
- };
- exports.TransferArrayBuffer = function (O) {
- return O.slice();
- };
- exports.ValidateAndNormalizeHighWaterMark = function (highWaterMark) {
- highWaterMark = Number(highWaterMark);
- if (Number.isNaN(highWaterMark) || highWaterMark < 0) {
- throw new RangeError('highWaterMark property of a queuing strategy must be non-negative and non-NaN');
- }
- return highWaterMark;
- };
- exports.ValidateAndNormalizeQueuingStrategy = function (size, highWaterMark) {
- if (size !== undefined && typeof size !== 'function') {
- throw new TypeError('size property of a queuing strategy must be a function');
- }
- highWaterMark = exports.ValidateAndNormalizeHighWaterMark(highWaterMark);
- return {
- size: size,
- highWaterMark: highWaterMark
- };
- };
-}, function (module, exports, __w_pdfjs_require__) {
- "use strict";
-
- function rethrowAssertionErrorRejection(e) {
- if (e && e.constructor === AssertionError) {
- setTimeout(function () {
- throw e;
- }, 0);
- }
- }
- function AssertionError(message) {
- this.name = 'AssertionError';
- this.message = message || '';
- this.stack = new Error().stack;
- }
- AssertionError.prototype = Object.create(Error.prototype);
- AssertionError.prototype.constructor = AssertionError;
- function assert(value, message) {
- if (!value) {
- throw new AssertionError(message);
- }
- }
- module.exports = {
- rethrowAssertionErrorRejection: rethrowAssertionErrorRejection,
- AssertionError: AssertionError,
- assert: assert
- };
-}, function (module, exports, __w_pdfjs_require__) {
- "use strict";
-
- var _createClass = function () {
- function defineProperties(target, props) {
- for (var i = 0; i < props.length; i++) {
- var descriptor = props[i];
- descriptor.enumerable = descriptor.enumerable || false;
- descriptor.configurable = true;
- if ("value" in descriptor) descriptor.writable = true;
- Object.defineProperty(target, descriptor.key, descriptor);
- }
- }
- return function (Constructor, protoProps, staticProps) {
- if (protoProps) defineProperties(Constructor.prototype, protoProps);
- if (staticProps) defineProperties(Constructor, staticProps);
- return Constructor;
- };
- }();
- function _classCallCheck(instance, Constructor) {
- if (!(instance instanceof Constructor)) {
- throw new TypeError("Cannot call a class as a function");
- }
- }
- var _require = __w_pdfjs_require__(0),
- InvokeOrNoop = _require.InvokeOrNoop,
- PromiseInvokeOrNoop = _require.PromiseInvokeOrNoop,
- ValidateAndNormalizeQueuingStrategy = _require.ValidateAndNormalizeQueuingStrategy,
- typeIsObject = _require.typeIsObject;
- var _require2 = __w_pdfjs_require__(1),
- assert = _require2.assert,
- rethrowAssertionErrorRejection = _require2.rethrowAssertionErrorRejection;
- var _require3 = __w_pdfjs_require__(3),
- DequeueValue = _require3.DequeueValue,
- EnqueueValueWithSize = _require3.EnqueueValueWithSize,
- PeekQueueValue = _require3.PeekQueueValue,
- ResetQueue = _require3.ResetQueue;
- var WritableStream = function () {
- function WritableStream() {
- var underlyingSink = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
- size = _ref.size,
- _ref$highWaterMark = _ref.highWaterMark,
- highWaterMark = _ref$highWaterMark === undefined ? 1 : _ref$highWaterMark;
- _classCallCheck(this, WritableStream);
- this._state = 'writable';
- this._storedError = undefined;
- this._writer = undefined;
- this._writableStreamController = undefined;
- this._writeRequests = [];
- this._inFlightWriteRequest = undefined;
- this._closeRequest = undefined;
- this._inFlightCloseRequest = undefined;
- this._pendingAbortRequest = undefined;
- this._backpressure = false;
- var type = underlyingSink.type;
- if (type !== undefined) {
- throw new RangeError('Invalid type is specified');
- }
- this._writableStreamController = new WritableStreamDefaultController(this, underlyingSink, size, highWaterMark);
- this._writableStreamController.__startSteps();
- }
- _createClass(WritableStream, [{
- key: 'abort',
- value: function abort(reason) {
- if (IsWritableStream(this) === false) {
- return Promise.reject(streamBrandCheckException('abort'));
- }
- if (IsWritableStreamLocked(this) === true) {
- return Promise.reject(new TypeError('Cannot abort a stream that already has a writer'));
- }
- return WritableStreamAbort(this, reason);
- }
- }, {
- key: 'getWriter',
- value: function getWriter() {
- if (IsWritableStream(this) === false) {
- throw streamBrandCheckException('getWriter');
- }
- return AcquireWritableStreamDefaultWriter(this);
- }
- }, {
- key: 'locked',
- get: function get() {
- if (IsWritableStream(this) === false) {
- throw streamBrandCheckException('locked');
- }
- return IsWritableStreamLocked(this);
- }
- }]);
- return WritableStream;
- }();
- module.exports = {
- AcquireWritableStreamDefaultWriter: AcquireWritableStreamDefaultWriter,
- IsWritableStream: IsWritableStream,
- IsWritableStreamLocked: IsWritableStreamLocked,
- WritableStream: WritableStream,
- WritableStreamAbort: WritableStreamAbort,
- WritableStreamDefaultControllerError: WritableStreamDefaultControllerError,
- WritableStreamDefaultWriterCloseWithErrorPropagation: WritableStreamDefaultWriterCloseWithErrorPropagation,
- WritableStreamDefaultWriterRelease: WritableStreamDefaultWriterRelease,
- WritableStreamDefaultWriterWrite: WritableStreamDefaultWriterWrite,
- WritableStreamCloseQueuedOrInFlight: WritableStreamCloseQueuedOrInFlight
- };
- function AcquireWritableStreamDefaultWriter(stream) {
- return new WritableStreamDefaultWriter(stream);
- }
- function IsWritableStream(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_writableStreamController')) {
- return false;
- }
- return true;
- }
- function IsWritableStreamLocked(stream) {
- assert(IsWritableStream(stream) === true, 'IsWritableStreamLocked should only be used on known writable streams');
- if (stream._writer === undefined) {
- return false;
- }
- return true;
- }
- function WritableStreamAbort(stream, reason) {
- var state = stream._state;
- if (state === 'closed') {
- return Promise.resolve(undefined);
- }
- if (state === 'errored') {
- return Promise.reject(stream._storedError);
- }
- var error = new TypeError('Requested to abort');
- if (stream._pendingAbortRequest !== undefined) {
- return Promise.reject(error);
- }
- assert(state === 'writable' || state === 'erroring', 'state must be writable or erroring');
- var wasAlreadyErroring = false;
- if (state === 'erroring') {
- wasAlreadyErroring = true;
- reason = undefined;
- }
- var promise = new Promise(function (resolve, reject) {
- stream._pendingAbortRequest = {
- _resolve: resolve,
- _reject: reject,
- _reason: reason,
- _wasAlreadyErroring: wasAlreadyErroring
- };
- });
- if (wasAlreadyErroring === false) {
- WritableStreamStartErroring(stream, error);
- }
- return promise;
- }
- function WritableStreamAddWriteRequest(stream) {
- assert(IsWritableStreamLocked(stream) === true);
- assert(stream._state === 'writable');
- var promise = new Promise(function (resolve, reject) {
- var writeRequest = {
- _resolve: resolve,
- _reject: reject
- };
- stream._writeRequests.push(writeRequest);
- });
- return promise;
- }
- function WritableStreamDealWithRejection(stream, error) {
- var state = stream._state;
- if (state === 'writable') {
- WritableStreamStartErroring(stream, error);
- return;
- }
- assert(state === 'erroring');
- WritableStreamFinishErroring(stream);
- }
- function WritableStreamStartErroring(stream, reason) {
- assert(stream._storedError === undefined, 'stream._storedError === undefined');
- assert(stream._state === 'writable', 'state must be writable');
- var controller = stream._writableStreamController;
- assert(controller !== undefined, 'controller must not be undefined');
- stream._state = 'erroring';
- stream._storedError = reason;
- var writer = stream._writer;
- if (writer !== undefined) {
- WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason);
- }
- if (WritableStreamHasOperationMarkedInFlight(stream) === false && controller._started === true) {
- WritableStreamFinishErroring(stream);
- }
- }
- function WritableStreamFinishErroring(stream) {
- assert(stream._state === 'erroring', 'stream._state === erroring');
- assert(WritableStreamHasOperationMarkedInFlight(stream) === false, 'WritableStreamHasOperationMarkedInFlight(stream) === false');
- stream._state = 'errored';
- stream._writableStreamController.__errorSteps();
- var storedError = stream._storedError;
- for (var i = 0; i < stream._writeRequests.length; i++) {
- var writeRequest = stream._writeRequests[i];
- writeRequest._reject(storedError);
- }
- stream._writeRequests = [];
- if (stream._pendingAbortRequest === undefined) {
- WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
- return;
- }
- var abortRequest = stream._pendingAbortRequest;
- stream._pendingAbortRequest = undefined;
- if (abortRequest._wasAlreadyErroring === true) {
- abortRequest._reject(storedError);
- WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
- return;
- }
- var promise = stream._writableStreamController.__abortSteps(abortRequest._reason);
- promise.then(function () {
- abortRequest._resolve();
- WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
- }, function (reason) {
- abortRequest._reject(reason);
- WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
- });
- }
- function WritableStreamFinishInFlightWrite(stream) {
- assert(stream._inFlightWriteRequest !== undefined);
- stream._inFlightWriteRequest._resolve(undefined);
- stream._inFlightWriteRequest = undefined;
- }
- function WritableStreamFinishInFlightWriteWithError(stream, error) {
- assert(stream._inFlightWriteRequest !== undefined);
- stream._inFlightWriteRequest._reject(error);
- stream._inFlightWriteRequest = undefined;
- assert(stream._state === 'writable' || stream._state === 'erroring');
- WritableStreamDealWithRejection(stream, error);
- }
- function WritableStreamFinishInFlightClose(stream) {
- assert(stream._inFlightCloseRequest !== undefined);
- stream._inFlightCloseRequest._resolve(undefined);
- stream._inFlightCloseRequest = undefined;
- var state = stream._state;
- assert(state === 'writable' || state === 'erroring');
- if (state === 'erroring') {
- stream._storedError = undefined;
- if (stream._pendingAbortRequest !== undefined) {
- stream._pendingAbortRequest._resolve();
- stream._pendingAbortRequest = undefined;
- }
- }
- stream._state = 'closed';
- var writer = stream._writer;
- if (writer !== undefined) {
- defaultWriterClosedPromiseResolve(writer);
- }
- assert(stream._pendingAbortRequest === undefined, 'stream._pendingAbortRequest === undefined');
- assert(stream._storedError === undefined, 'stream._storedError === undefined');
- }
- function WritableStreamFinishInFlightCloseWithError(stream, error) {
- assert(stream._inFlightCloseRequest !== undefined);
- stream._inFlightCloseRequest._reject(error);
- stream._inFlightCloseRequest = undefined;
- assert(stream._state === 'writable' || stream._state === 'erroring');
- if (stream._pendingAbortRequest !== undefined) {
- stream._pendingAbortRequest._reject(error);
- stream._pendingAbortRequest = undefined;
- }
- WritableStreamDealWithRejection(stream, error);
- }
- function WritableStreamCloseQueuedOrInFlight(stream) {
- if (stream._closeRequest === undefined && stream._inFlightCloseRequest === undefined) {
- return false;
- }
- return true;
- }
- function WritableStreamHasOperationMarkedInFlight(stream) {
- if (stream._inFlightWriteRequest === undefined && stream._inFlightCloseRequest === undefined) {
- return false;
- }
- return true;
- }
- function WritableStreamMarkCloseRequestInFlight(stream) {
- assert(stream._inFlightCloseRequest === undefined);
- assert(stream._closeRequest !== undefined);
- stream._inFlightCloseRequest = stream._closeRequest;
- stream._closeRequest = undefined;
- }
- function WritableStreamMarkFirstWriteRequestInFlight(stream) {
- assert(stream._inFlightWriteRequest === undefined, 'there must be no pending write request');
- assert(stream._writeRequests.length !== 0, 'writeRequests must not be empty');
- stream._inFlightWriteRequest = stream._writeRequests.shift();
- }
- function WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream) {
- assert(stream._state === 'errored', '_stream_.[[state]] is `"errored"`');
- if (stream._closeRequest !== undefined) {
- assert(stream._inFlightCloseRequest === undefined);
- stream._closeRequest._reject(stream._storedError);
- stream._closeRequest = undefined;
- }
- var writer = stream._writer;
- if (writer !== undefined) {
- defaultWriterClosedPromiseReject(writer, stream._storedError);
- writer._closedPromise.catch(function () {});
- }
- }
- function WritableStreamUpdateBackpressure(stream, backpressure) {
- assert(stream._state === 'writable');
- assert(WritableStreamCloseQueuedOrInFlight(stream) === false);
- var writer = stream._writer;
- if (writer !== undefined && backpressure !== stream._backpressure) {
- if (backpressure === true) {
- defaultWriterReadyPromiseReset(writer);
- } else {
- assert(backpressure === false);
- defaultWriterReadyPromiseResolve(writer);
- }
- }
- stream._backpressure = backpressure;
- }
- var WritableStreamDefaultWriter = function () {
- function WritableStreamDefaultWriter(stream) {
- _classCallCheck(this, WritableStreamDefaultWriter);
- if (IsWritableStream(stream) === false) {
- throw new TypeError('WritableStreamDefaultWriter can only be constructed with a WritableStream instance');
- }
- if (IsWritableStreamLocked(stream) === true) {
- throw new TypeError('This stream has already been locked for exclusive writing by another writer');
- }
- this._ownerWritableStream = stream;
- stream._writer = this;
- var state = stream._state;
- if (state === 'writable') {
- if (WritableStreamCloseQueuedOrInFlight(stream) === false && stream._backpressure === true) {
- defaultWriterReadyPromiseInitialize(this);
- } else {
- defaultWriterReadyPromiseInitializeAsResolved(this);
- }
- defaultWriterClosedPromiseInitialize(this);
- } else if (state === 'erroring') {
- defaultWriterReadyPromiseInitializeAsRejected(this, stream._storedError);
- this._readyPromise.catch(function () {});
- defaultWriterClosedPromiseInitialize(this);
- } else if (state === 'closed') {
- defaultWriterReadyPromiseInitializeAsResolved(this);
- defaultWriterClosedPromiseInitializeAsResolved(this);
- } else {
- assert(state === 'errored', 'state must be errored');
- var storedError = stream._storedError;
- defaultWriterReadyPromiseInitializeAsRejected(this, storedError);
- this._readyPromise.catch(function () {});
- defaultWriterClosedPromiseInitializeAsRejected(this, storedError);
- this._closedPromise.catch(function () {});
- }
- }
- _createClass(WritableStreamDefaultWriter, [{
- key: 'abort',
- value: function abort(reason) {
- if (IsWritableStreamDefaultWriter(this) === false) {
- return Promise.reject(defaultWriterBrandCheckException('abort'));
- }
- if (this._ownerWritableStream === undefined) {
- return Promise.reject(defaultWriterLockException('abort'));
- }
- return WritableStreamDefaultWriterAbort(this, reason);
- }
- }, {
- key: 'close',
- value: function close() {
- if (IsWritableStreamDefaultWriter(this) === false) {
- return Promise.reject(defaultWriterBrandCheckException('close'));
- }
- var stream = this._ownerWritableStream;
- if (stream === undefined) {
- return Promise.reject(defaultWriterLockException('close'));
- }
- if (WritableStreamCloseQueuedOrInFlight(stream) === true) {
- return Promise.reject(new TypeError('cannot close an already-closing stream'));
- }
- return WritableStreamDefaultWriterClose(this);
- }
- }, {
- key: 'releaseLock',
- value: function releaseLock() {
- if (IsWritableStreamDefaultWriter(this) === false) {
- throw defaultWriterBrandCheckException('releaseLock');
- }
- var stream = this._ownerWritableStream;
- if (stream === undefined) {
- return;
- }
- assert(stream._writer !== undefined);
- WritableStreamDefaultWriterRelease(this);
- }
- }, {
- key: 'write',
- value: function write(chunk) {
- if (IsWritableStreamDefaultWriter(this) === false) {
- return Promise.reject(defaultWriterBrandCheckException('write'));
- }
- if (this._ownerWritableStream === undefined) {
- return Promise.reject(defaultWriterLockException('write to'));
- }
- return WritableStreamDefaultWriterWrite(this, chunk);
- }
- }, {
- key: 'closed',
- get: function get() {
- if (IsWritableStreamDefaultWriter(this) === false) {
- return Promise.reject(defaultWriterBrandCheckException('closed'));
- }
- return this._closedPromise;
- }
- }, {
- key: 'desiredSize',
- get: function get() {
- if (IsWritableStreamDefaultWriter(this) === false) {
- throw defaultWriterBrandCheckException('desiredSize');
- }
- if (this._ownerWritableStream === undefined) {
- throw defaultWriterLockException('desiredSize');
- }
- return WritableStreamDefaultWriterGetDesiredSize(this);
- }
- }, {
- key: 'ready',
- get: function get() {
- if (IsWritableStreamDefaultWriter(this) === false) {
- return Promise.reject(defaultWriterBrandCheckException('ready'));
- }
- return this._readyPromise;
- }
- }]);
- return WritableStreamDefaultWriter;
- }();
- function IsWritableStreamDefaultWriter(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_ownerWritableStream')) {
- return false;
- }
- return true;
- }
- function WritableStreamDefaultWriterAbort(writer, reason) {
- var stream = writer._ownerWritableStream;
- assert(stream !== undefined);
- return WritableStreamAbort(stream, reason);
- }
- function WritableStreamDefaultWriterClose(writer) {
- var stream = writer._ownerWritableStream;
- assert(stream !== undefined);
- var state = stream._state;
- if (state === 'closed' || state === 'errored') {
- return Promise.reject(new TypeError('The stream (in ' + state + ' state) is not in the writable state and cannot be closed'));
- }
- assert(state === 'writable' || state === 'erroring');
- assert(WritableStreamCloseQueuedOrInFlight(stream) === false);
- var promise = new Promise(function (resolve, reject) {
- var closeRequest = {
- _resolve: resolve,
- _reject: reject
- };
- stream._closeRequest = closeRequest;
- });
- if (stream._backpressure === true && state === 'writable') {
- defaultWriterReadyPromiseResolve(writer);
- }
- WritableStreamDefaultControllerClose(stream._writableStreamController);
- return promise;
- }
- function WritableStreamDefaultWriterCloseWithErrorPropagation(writer) {
- var stream = writer._ownerWritableStream;
- assert(stream !== undefined);
- var state = stream._state;
- if (WritableStreamCloseQueuedOrInFlight(stream) === true || state === 'closed') {
- return Promise.resolve();
- }
- if (state === 'errored') {
- return Promise.reject(stream._storedError);
- }
- assert(state === 'writable' || state === 'erroring');
- return WritableStreamDefaultWriterClose(writer);
- }
- function WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, error) {
- if (writer._closedPromiseState === 'pending') {
- defaultWriterClosedPromiseReject(writer, error);
- } else {
- defaultWriterClosedPromiseResetToRejected(writer, error);
- }
- writer._closedPromise.catch(function () {});
- }
- function WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, error) {
- if (writer._readyPromiseState === 'pending') {
- defaultWriterReadyPromiseReject(writer, error);
- } else {
- defaultWriterReadyPromiseResetToRejected(writer, error);
- }
- writer._readyPromise.catch(function () {});
- }
- function WritableStreamDefaultWriterGetDesiredSize(writer) {
- var stream = writer._ownerWritableStream;
- var state = stream._state;
- if (state === 'errored' || state === 'erroring') {
- return null;
- }
- if (state === 'closed') {
- return 0;
- }
- return WritableStreamDefaultControllerGetDesiredSize(stream._writableStreamController);
- }
- function WritableStreamDefaultWriterRelease(writer) {
- var stream = writer._ownerWritableStream;
- assert(stream !== undefined);
- assert(stream._writer === writer);
- var releasedError = new TypeError('Writer was released and can no longer be used to monitor the stream\'s closedness');
- WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError);
- WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedError);
- stream._writer = undefined;
- writer._ownerWritableStream = undefined;
- }
- function WritableStreamDefaultWriterWrite(writer, chunk) {
- var stream = writer._ownerWritableStream;
- assert(stream !== undefined);
- var controller = stream._writableStreamController;
- var chunkSize = WritableStreamDefaultControllerGetChunkSize(controller, chunk);
- if (stream !== writer._ownerWritableStream) {
- return Promise.reject(defaultWriterLockException('write to'));
- }
- var state = stream._state;
- if (state === 'errored') {
- return Promise.reject(stream._storedError);
- }
- if (WritableStreamCloseQueuedOrInFlight(stream) === true || state === 'closed') {
- return Promise.reject(new TypeError('The stream is closing or closed and cannot be written to'));
- }
- if (state === 'erroring') {
- return Promise.reject(stream._storedError);
- }
- assert(state === 'writable');
- var promise = WritableStreamAddWriteRequest(stream);
- WritableStreamDefaultControllerWrite(controller, chunk, chunkSize);
- return promise;
- }
- var WritableStreamDefaultController = function () {
- function WritableStreamDefaultController(stream, underlyingSink, size, highWaterMark) {
- _classCallCheck(this, WritableStreamDefaultController);
- if (IsWritableStream(stream) === false) {
- throw new TypeError('WritableStreamDefaultController can only be constructed with a WritableStream instance');
- }
- if (stream._writableStreamController !== undefined) {
- throw new TypeError('WritableStreamDefaultController instances can only be created by the WritableStream constructor');
- }
- this._controlledWritableStream = stream;
- this._underlyingSink = underlyingSink;
- this._queue = undefined;
- this._queueTotalSize = undefined;
- ResetQueue(this);
- this._started = false;
- var normalizedStrategy = ValidateAndNormalizeQueuingStrategy(size, highWaterMark);
- this._strategySize = normalizedStrategy.size;
- this._strategyHWM = normalizedStrategy.highWaterMark;
- var backpressure = WritableStreamDefaultControllerGetBackpressure(this);
- WritableStreamUpdateBackpressure(stream, backpressure);
- }
- _createClass(WritableStreamDefaultController, [{
- key: 'error',
- value: function error(e) {
- if (IsWritableStreamDefaultController(this) === false) {
- throw new TypeError('WritableStreamDefaultController.prototype.error can only be used on a WritableStreamDefaultController');
- }
- var state = this._controlledWritableStream._state;
- if (state !== 'writable') {
- return;
- }
- WritableStreamDefaultControllerError(this, e);
- }
- }, {
- key: '__abortSteps',
- value: function __abortSteps(reason) {
- return PromiseInvokeOrNoop(this._underlyingSink, 'abort', [reason]);
- }
- }, {
- key: '__errorSteps',
- value: function __errorSteps() {
- ResetQueue(this);
- }
- }, {
- key: '__startSteps',
- value: function __startSteps() {
- var _this = this;
- var startResult = InvokeOrNoop(this._underlyingSink, 'start', [this]);
- var stream = this._controlledWritableStream;
- Promise.resolve(startResult).then(function () {
- assert(stream._state === 'writable' || stream._state === 'erroring');
- _this._started = true;
- WritableStreamDefaultControllerAdvanceQueueIfNeeded(_this);
- }, function (r) {
- assert(stream._state === 'writable' || stream._state === 'erroring');
- _this._started = true;
- WritableStreamDealWithRejection(stream, r);
- }).catch(rethrowAssertionErrorRejection);
- }
- }]);
- return WritableStreamDefaultController;
- }();
- function WritableStreamDefaultControllerClose(controller) {
- EnqueueValueWithSize(controller, 'close', 0);
- WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
- }
- function WritableStreamDefaultControllerGetChunkSize(controller, chunk) {
- var strategySize = controller._strategySize;
- if (strategySize === undefined) {
- return 1;
- }
- try {
- return strategySize(chunk);
- } catch (chunkSizeE) {
- WritableStreamDefaultControllerErrorIfNeeded(controller, chunkSizeE);
- return 1;
- }
- }
- function WritableStreamDefaultControllerGetDesiredSize(controller) {
- return controller._strategyHWM - controller._queueTotalSize;
- }
- function WritableStreamDefaultControllerWrite(controller, chunk, chunkSize) {
- var writeRecord = { chunk: chunk };
- try {
- EnqueueValueWithSize(controller, writeRecord, chunkSize);
- } catch (enqueueE) {
- WritableStreamDefaultControllerErrorIfNeeded(controller, enqueueE);
- return;
- }
- var stream = controller._controlledWritableStream;
- if (WritableStreamCloseQueuedOrInFlight(stream) === false && stream._state === 'writable') {
- var backpressure = WritableStreamDefaultControllerGetBackpressure(controller);
- WritableStreamUpdateBackpressure(stream, backpressure);
- }
- WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
- }
- function IsWritableStreamDefaultController(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_underlyingSink')) {
- return false;
- }
- return true;
- }
- function WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller) {
- var stream = controller._controlledWritableStream;
- if (controller._started === false) {
- return;
- }
- if (stream._inFlightWriteRequest !== undefined) {
- return;
- }
- var state = stream._state;
- if (state === 'closed' || state === 'errored') {
- return;
- }
- if (state === 'erroring') {
- WritableStreamFinishErroring(stream);
- return;
- }
- if (controller._queue.length === 0) {
- return;
- }
- var writeRecord = PeekQueueValue(controller);
- if (writeRecord === 'close') {
- WritableStreamDefaultControllerProcessClose(controller);
- } else {
- WritableStreamDefaultControllerProcessWrite(controller, writeRecord.chunk);
- }
- }
- function WritableStreamDefaultControllerErrorIfNeeded(controller, error) {
- if (controller._controlledWritableStream._state === 'writable') {
- WritableStreamDefaultControllerError(controller, error);
- }
- }
- function WritableStreamDefaultControllerProcessClose(controller) {
- var stream = controller._controlledWritableStream;
- WritableStreamMarkCloseRequestInFlight(stream);
- DequeueValue(controller);
- assert(controller._queue.length === 0, 'queue must be empty once the final write record is dequeued');
- var sinkClosePromise = PromiseInvokeOrNoop(controller._underlyingSink, 'close', []);
- sinkClosePromise.then(function () {
- WritableStreamFinishInFlightClose(stream);
- }, function (reason) {
- WritableStreamFinishInFlightCloseWithError(stream, reason);
- }).catch(rethrowAssertionErrorRejection);
- }
- function WritableStreamDefaultControllerProcessWrite(controller, chunk) {
- var stream = controller._controlledWritableStream;
- WritableStreamMarkFirstWriteRequestInFlight(stream);
- var sinkWritePromise = PromiseInvokeOrNoop(controller._underlyingSink, 'write', [chunk, controller]);
- sinkWritePromise.then(function () {
- WritableStreamFinishInFlightWrite(stream);
- var state = stream._state;
- assert(state === 'writable' || state === 'erroring');
- DequeueValue(controller);
- if (WritableStreamCloseQueuedOrInFlight(stream) === false && state === 'writable') {
- var backpressure = WritableStreamDefaultControllerGetBackpressure(controller);
- WritableStreamUpdateBackpressure(stream, backpressure);
- }
- WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
- }, function (reason) {
- WritableStreamFinishInFlightWriteWithError(stream, reason);
- }).catch(rethrowAssertionErrorRejection);
- }
- function WritableStreamDefaultControllerGetBackpressure(controller) {
- var desiredSize = WritableStreamDefaultControllerGetDesiredSize(controller);
- return desiredSize <= 0;
- }
- function WritableStreamDefaultControllerError(controller, error) {
- var stream = controller._controlledWritableStream;
- assert(stream._state === 'writable');
- WritableStreamStartErroring(stream, error);
- }
- function streamBrandCheckException(name) {
- return new TypeError('WritableStream.prototype.' + name + ' can only be used on a WritableStream');
- }
- function defaultWriterBrandCheckException(name) {
- return new TypeError('WritableStreamDefaultWriter.prototype.' + name + ' can only be used on a WritableStreamDefaultWriter');
- }
- function defaultWriterLockException(name) {
- return new TypeError('Cannot ' + name + ' a stream using a released writer');
- }
- function defaultWriterClosedPromiseInitialize(writer) {
- writer._closedPromise = new Promise(function (resolve, reject) {
- writer._closedPromise_resolve = resolve;
- writer._closedPromise_reject = reject;
- writer._closedPromiseState = 'pending';
- });
- }
- function defaultWriterClosedPromiseInitializeAsRejected(writer, reason) {
- writer._closedPromise = Promise.reject(reason);
- writer._closedPromise_resolve = undefined;
- writer._closedPromise_reject = undefined;
- writer._closedPromiseState = 'rejected';
- }
- function defaultWriterClosedPromiseInitializeAsResolved(writer) {
- writer._closedPromise = Promise.resolve(undefined);
- writer._closedPromise_resolve = undefined;
- writer._closedPromise_reject = undefined;
- writer._closedPromiseState = 'resolved';
- }
- function defaultWriterClosedPromiseReject(writer, reason) {
- assert(writer._closedPromise_resolve !== undefined, 'writer._closedPromise_resolve !== undefined');
- assert(writer._closedPromise_reject !== undefined, 'writer._closedPromise_reject !== undefined');
- assert(writer._closedPromiseState === 'pending', 'writer._closedPromiseState is pending');
- writer._closedPromise_reject(reason);
- writer._closedPromise_resolve = undefined;
- writer._closedPromise_reject = undefined;
- writer._closedPromiseState = 'rejected';
- }
- function defaultWriterClosedPromiseResetToRejected(writer, reason) {
- assert(writer._closedPromise_resolve === undefined, 'writer._closedPromise_resolve === undefined');
- assert(writer._closedPromise_reject === undefined, 'writer._closedPromise_reject === undefined');
- assert(writer._closedPromiseState !== 'pending', 'writer._closedPromiseState is not pending');
- writer._closedPromise = Promise.reject(reason);
- writer._closedPromiseState = 'rejected';
- }
- function defaultWriterClosedPromiseResolve(writer) {
- assert(writer._closedPromise_resolve !== undefined, 'writer._closedPromise_resolve !== undefined');
- assert(writer._closedPromise_reject !== undefined, 'writer._closedPromise_reject !== undefined');
- assert(writer._closedPromiseState === 'pending', 'writer._closedPromiseState is pending');
- writer._closedPromise_resolve(undefined);
- writer._closedPromise_resolve = undefined;
- writer._closedPromise_reject = undefined;
- writer._closedPromiseState = 'resolved';
- }
- function defaultWriterReadyPromiseInitialize(writer) {
- writer._readyPromise = new Promise(function (resolve, reject) {
- writer._readyPromise_resolve = resolve;
- writer._readyPromise_reject = reject;
- });
- writer._readyPromiseState = 'pending';
- }
- function defaultWriterReadyPromiseInitializeAsRejected(writer, reason) {
- writer._readyPromise = Promise.reject(reason);
- writer._readyPromise_resolve = undefined;
- writer._readyPromise_reject = undefined;
- writer._readyPromiseState = 'rejected';
- }
- function defaultWriterReadyPromiseInitializeAsResolved(writer) {
- writer._readyPromise = Promise.resolve(undefined);
- writer._readyPromise_resolve = undefined;
- writer._readyPromise_reject = undefined;
- writer._readyPromiseState = 'fulfilled';
- }
- function defaultWriterReadyPromiseReject(writer, reason) {
- assert(writer._readyPromise_resolve !== undefined, 'writer._readyPromise_resolve !== undefined');
- assert(writer._readyPromise_reject !== undefined, 'writer._readyPromise_reject !== undefined');
- writer._readyPromise_reject(reason);
- writer._readyPromise_resolve = undefined;
- writer._readyPromise_reject = undefined;
- writer._readyPromiseState = 'rejected';
- }
- function defaultWriterReadyPromiseReset(writer) {
- assert(writer._readyPromise_resolve === undefined, 'writer._readyPromise_resolve === undefined');
- assert(writer._readyPromise_reject === undefined, 'writer._readyPromise_reject === undefined');
- writer._readyPromise = new Promise(function (resolve, reject) {
- writer._readyPromise_resolve = resolve;
- writer._readyPromise_reject = reject;
- });
- writer._readyPromiseState = 'pending';
- }
- function defaultWriterReadyPromiseResetToRejected(writer, reason) {
- assert(writer._readyPromise_resolve === undefined, 'writer._readyPromise_resolve === undefined');
- assert(writer._readyPromise_reject === undefined, 'writer._readyPromise_reject === undefined');
- writer._readyPromise = Promise.reject(reason);
- writer._readyPromiseState = 'rejected';
- }
- function defaultWriterReadyPromiseResolve(writer) {
- assert(writer._readyPromise_resolve !== undefined, 'writer._readyPromise_resolve !== undefined');
- assert(writer._readyPromise_reject !== undefined, 'writer._readyPromise_reject !== undefined');
- writer._readyPromise_resolve(undefined);
- writer._readyPromise_resolve = undefined;
- writer._readyPromise_reject = undefined;
- writer._readyPromiseState = 'fulfilled';
- }
-}, function (module, exports, __w_pdfjs_require__) {
- "use strict";
-
- var _require = __w_pdfjs_require__(0),
- IsFiniteNonNegativeNumber = _require.IsFiniteNonNegativeNumber;
- var _require2 = __w_pdfjs_require__(1),
- assert = _require2.assert;
- exports.DequeueValue = function (container) {
- assert('_queue' in container && '_queueTotalSize' in container, 'Spec-level failure: DequeueValue should only be used on containers with [[queue]] and [[queueTotalSize]].');
- assert(container._queue.length > 0, 'Spec-level failure: should never dequeue from an empty queue.');
- var pair = container._queue.shift();
- container._queueTotalSize -= pair.size;
- if (container._queueTotalSize < 0) {
- container._queueTotalSize = 0;
- }
- return pair.value;
- };
- exports.EnqueueValueWithSize = function (container, value, size) {
- assert('_queue' in container && '_queueTotalSize' in container, 'Spec-level failure: EnqueueValueWithSize should only be used on containers with [[queue]] and ' + '[[queueTotalSize]].');
- size = Number(size);
- if (!IsFiniteNonNegativeNumber(size)) {
- throw new RangeError('Size must be a finite, non-NaN, non-negative number.');
- }
- container._queue.push({
- value: value,
- size: size
- });
- container._queueTotalSize += size;
- };
- exports.PeekQueueValue = function (container) {
- assert('_queue' in container && '_queueTotalSize' in container, 'Spec-level failure: PeekQueueValue should only be used on containers with [[queue]] and [[queueTotalSize]].');
- assert(container._queue.length > 0, 'Spec-level failure: should never peek at an empty queue.');
- var pair = container._queue[0];
- return pair.value;
- };
- exports.ResetQueue = function (container) {
- assert('_queue' in container && '_queueTotalSize' in container, 'Spec-level failure: ResetQueue should only be used on containers with [[queue]] and [[queueTotalSize]].');
- container._queue = [];
- container._queueTotalSize = 0;
- };
-}, function (module, exports, __w_pdfjs_require__) {
- "use strict";
-
- var _createClass = function () {
- function defineProperties(target, props) {
- for (var i = 0; i < props.length; i++) {
- var descriptor = props[i];
- descriptor.enumerable = descriptor.enumerable || false;
- descriptor.configurable = true;
- if ("value" in descriptor) descriptor.writable = true;
- Object.defineProperty(target, descriptor.key, descriptor);
- }
- }
- return function (Constructor, protoProps, staticProps) {
- if (protoProps) defineProperties(Constructor.prototype, protoProps);
- if (staticProps) defineProperties(Constructor, staticProps);
- return Constructor;
- };
- }();
- function _classCallCheck(instance, Constructor) {
- if (!(instance instanceof Constructor)) {
- throw new TypeError("Cannot call a class as a function");
- }
- }
- var _require = __w_pdfjs_require__(0),
- ArrayBufferCopy = _require.ArrayBufferCopy,
- CreateIterResultObject = _require.CreateIterResultObject,
- IsFiniteNonNegativeNumber = _require.IsFiniteNonNegativeNumber,
- InvokeOrNoop = _require.InvokeOrNoop,
- PromiseInvokeOrNoop = _require.PromiseInvokeOrNoop,
- TransferArrayBuffer = _require.TransferArrayBuffer,
- ValidateAndNormalizeQueuingStrategy = _require.ValidateAndNormalizeQueuingStrategy,
- ValidateAndNormalizeHighWaterMark = _require.ValidateAndNormalizeHighWaterMark;
- var _require2 = __w_pdfjs_require__(0),
- createArrayFromList = _require2.createArrayFromList,
- createDataProperty = _require2.createDataProperty,
- typeIsObject = _require2.typeIsObject;
- var _require3 = __w_pdfjs_require__(1),
- assert = _require3.assert,
- rethrowAssertionErrorRejection = _require3.rethrowAssertionErrorRejection;
- var _require4 = __w_pdfjs_require__(3),
- DequeueValue = _require4.DequeueValue,
- EnqueueValueWithSize = _require4.EnqueueValueWithSize,
- ResetQueue = _require4.ResetQueue;
- var _require5 = __w_pdfjs_require__(2),
- AcquireWritableStreamDefaultWriter = _require5.AcquireWritableStreamDefaultWriter,
- IsWritableStream = _require5.IsWritableStream,
- IsWritableStreamLocked = _require5.IsWritableStreamLocked,
- WritableStreamAbort = _require5.WritableStreamAbort,
- WritableStreamDefaultWriterCloseWithErrorPropagation = _require5.WritableStreamDefaultWriterCloseWithErrorPropagation,
- WritableStreamDefaultWriterRelease = _require5.WritableStreamDefaultWriterRelease,
- WritableStreamDefaultWriterWrite = _require5.WritableStreamDefaultWriterWrite,
- WritableStreamCloseQueuedOrInFlight = _require5.WritableStreamCloseQueuedOrInFlight;
- var ReadableStream = function () {
- function ReadableStream() {
- var underlyingSource = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
- size = _ref.size,
- highWaterMark = _ref.highWaterMark;
- _classCallCheck(this, ReadableStream);
- this._state = 'readable';
- this._reader = undefined;
- this._storedError = undefined;
- this._disturbed = false;
- this._readableStreamController = undefined;
- var type = underlyingSource.type;
- var typeString = String(type);
- if (typeString === 'bytes') {
- if (highWaterMark === undefined) {
- highWaterMark = 0;
- }
- this._readableStreamController = new ReadableByteStreamController(this, underlyingSource, highWaterMark);
- } else if (type === undefined) {
- if (highWaterMark === undefined) {
- highWaterMark = 1;
- }
- this._readableStreamController = new ReadableStreamDefaultController(this, underlyingSource, size, highWaterMark);
- } else {
- throw new RangeError('Invalid type is specified');
- }
- }
- _createClass(ReadableStream, [{
- key: 'cancel',
- value: function cancel(reason) {
- if (IsReadableStream(this) === false) {
- return Promise.reject(streamBrandCheckException('cancel'));
- }
- if (IsReadableStreamLocked(this) === true) {
- return Promise.reject(new TypeError('Cannot cancel a stream that already has a reader'));
- }
- return ReadableStreamCancel(this, reason);
- }
- }, {
- key: 'getReader',
- value: function getReader() {
- var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- mode = _ref2.mode;
- if (IsReadableStream(this) === false) {
- throw streamBrandCheckException('getReader');
- }
- if (mode === undefined) {
- return AcquireReadableStreamDefaultReader(this);
- }
- mode = String(mode);
- if (mode === 'byob') {
- return AcquireReadableStreamBYOBReader(this);
- }
- throw new RangeError('Invalid mode is specified');
- }
- }, {
- key: 'pipeThrough',
- value: function pipeThrough(_ref3, options) {
- var writable = _ref3.writable,
- readable = _ref3.readable;
- var promise = this.pipeTo(writable, options);
- ifIsObjectAndHasAPromiseIsHandledInternalSlotSetPromiseIsHandledToTrue(promise);
- return readable;
- }
- }, {
- key: 'pipeTo',
- value: function pipeTo(dest) {
- var _this = this;
- var _ref4 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
- preventClose = _ref4.preventClose,
- preventAbort = _ref4.preventAbort,
- preventCancel = _ref4.preventCancel;
- if (IsReadableStream(this) === false) {
- return Promise.reject(streamBrandCheckException('pipeTo'));
- }
- if (IsWritableStream(dest) === false) {
- return Promise.reject(new TypeError('ReadableStream.prototype.pipeTo\'s first argument must be a WritableStream'));
- }
- preventClose = Boolean(preventClose);
- preventAbort = Boolean(preventAbort);
- preventCancel = Boolean(preventCancel);
- if (IsReadableStreamLocked(this) === true) {
- return Promise.reject(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream'));
- }
- if (IsWritableStreamLocked(dest) === true) {
- return Promise.reject(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream'));
- }
- var reader = AcquireReadableStreamDefaultReader(this);
- var writer = AcquireWritableStreamDefaultWriter(dest);
- var shuttingDown = false;
- var currentWrite = Promise.resolve();
- return new Promise(function (resolve, reject) {
- function pipeLoop() {
- currentWrite = Promise.resolve();
- if (shuttingDown === true) {
- return Promise.resolve();
- }
- return writer._readyPromise.then(function () {
- return ReadableStreamDefaultReaderRead(reader).then(function (_ref5) {
- var value = _ref5.value,
- done = _ref5.done;
- if (done === true) {
- return;
- }
- currentWrite = WritableStreamDefaultWriterWrite(writer, value).catch(function () {});
- });
- }).then(pipeLoop);
- }
- isOrBecomesErrored(_this, reader._closedPromise, function (storedError) {
- if (preventAbort === false) {
- shutdownWithAction(function () {
- return WritableStreamAbort(dest, storedError);
- }, true, storedError);
- } else {
- shutdown(true, storedError);
- }
- });
- isOrBecomesErrored(dest, writer._closedPromise, function (storedError) {
- if (preventCancel === false) {
- shutdownWithAction(function () {
- return ReadableStreamCancel(_this, storedError);
- }, true, storedError);
- } else {
- shutdown(true, storedError);
- }
- });
- isOrBecomesClosed(_this, reader._closedPromise, function () {
- if (preventClose === false) {
- shutdownWithAction(function () {
- return WritableStreamDefaultWriterCloseWithErrorPropagation(writer);
- });
- } else {
- shutdown();
- }
- });
- if (WritableStreamCloseQueuedOrInFlight(dest) === true || dest._state === 'closed') {
- var destClosed = new TypeError('the destination writable stream closed before all data could be piped to it');
- if (preventCancel === false) {
- shutdownWithAction(function () {
- return ReadableStreamCancel(_this, destClosed);
- }, true, destClosed);
- } else {
- shutdown(true, destClosed);
- }
- }
- pipeLoop().catch(function (err) {
- currentWrite = Promise.resolve();
- rethrowAssertionErrorRejection(err);
- });
- function waitForWritesToFinish() {
- var oldCurrentWrite = currentWrite;
- return currentWrite.then(function () {
- return oldCurrentWrite !== currentWrite ? waitForWritesToFinish() : undefined;
- });
- }
- function isOrBecomesErrored(stream, promise, action) {
- if (stream._state === 'errored') {
- action(stream._storedError);
- } else {
- promise.catch(action).catch(rethrowAssertionErrorRejection);
- }
- }
- function isOrBecomesClosed(stream, promise, action) {
- if (stream._state === 'closed') {
- action();
- } else {
- promise.then(action).catch(rethrowAssertionErrorRejection);
- }
- }
- function shutdownWithAction(action, originalIsError, originalError) {
- if (shuttingDown === true) {
- return;
- }
- shuttingDown = true;
- if (dest._state === 'writable' && WritableStreamCloseQueuedOrInFlight(dest) === false) {
- waitForWritesToFinish().then(doTheRest);
- } else {
- doTheRest();
- }
- function doTheRest() {
- action().then(function () {
- return finalize(originalIsError, originalError);
- }, function (newError) {
- return finalize(true, newError);
- }).catch(rethrowAssertionErrorRejection);
- }
- }
- function shutdown(isError, error) {
- if (shuttingDown === true) {
- return;
- }
- shuttingDown = true;
- if (dest._state === 'writable' && WritableStreamCloseQueuedOrInFlight(dest) === false) {
- waitForWritesToFinish().then(function () {
- return finalize(isError, error);
- }).catch(rethrowAssertionErrorRejection);
- } else {
- finalize(isError, error);
- }
- }
- function finalize(isError, error) {
- WritableStreamDefaultWriterRelease(writer);
- ReadableStreamReaderGenericRelease(reader);
- if (isError) {
- reject(error);
- } else {
- resolve(undefined);
- }
- }
- });
- }
- }, {
- key: 'tee',
- value: function tee() {
- if (IsReadableStream(this) === false) {
- throw streamBrandCheckException('tee');
- }
- var branches = ReadableStreamTee(this, false);
- return createArrayFromList(branches);
- }
- }, {
- key: 'locked',
- get: function get() {
- if (IsReadableStream(this) === false) {
- throw streamBrandCheckException('locked');
- }
- return IsReadableStreamLocked(this);
- }
- }]);
- return ReadableStream;
- }();
- module.exports = {
- ReadableStream: ReadableStream,
- IsReadableStreamDisturbed: IsReadableStreamDisturbed,
- ReadableStreamDefaultControllerClose: ReadableStreamDefaultControllerClose,
- ReadableStreamDefaultControllerEnqueue: ReadableStreamDefaultControllerEnqueue,
- ReadableStreamDefaultControllerError: ReadableStreamDefaultControllerError,
- ReadableStreamDefaultControllerGetDesiredSize: ReadableStreamDefaultControllerGetDesiredSize
- };
- function AcquireReadableStreamBYOBReader(stream) {
- return new ReadableStreamBYOBReader(stream);
- }
- function AcquireReadableStreamDefaultReader(stream) {
- return new ReadableStreamDefaultReader(stream);
- }
- function IsReadableStream(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_readableStreamController')) {
- return false;
- }
- return true;
- }
- function IsReadableStreamDisturbed(stream) {
- assert(IsReadableStream(stream) === true, 'IsReadableStreamDisturbed should only be used on known readable streams');
- return stream._disturbed;
- }
- function IsReadableStreamLocked(stream) {
- assert(IsReadableStream(stream) === true, 'IsReadableStreamLocked should only be used on known readable streams');
- if (stream._reader === undefined) {
- return false;
- }
- return true;
- }
- function ReadableStreamTee(stream, cloneForBranch2) {
- assert(IsReadableStream(stream) === true);
- assert(typeof cloneForBranch2 === 'boolean');
- var reader = AcquireReadableStreamDefaultReader(stream);
- var teeState = {
- closedOrErrored: false,
- canceled1: false,
- canceled2: false,
- reason1: undefined,
- reason2: undefined
- };
- teeState.promise = new Promise(function (resolve) {
- teeState._resolve = resolve;
- });
- var pull = create_ReadableStreamTeePullFunction();
- pull._reader = reader;
- pull._teeState = teeState;
- pull._cloneForBranch2 = cloneForBranch2;
- var cancel1 = create_ReadableStreamTeeBranch1CancelFunction();
- cancel1._stream = stream;
- cancel1._teeState = teeState;
- var cancel2 = create_ReadableStreamTeeBranch2CancelFunction();
- cancel2._stream = stream;
- cancel2._teeState = teeState;
- var underlyingSource1 = Object.create(Object.prototype);
- createDataProperty(underlyingSource1, 'pull', pull);
- createDataProperty(underlyingSource1, 'cancel', cancel1);
- var branch1Stream = new ReadableStream(underlyingSource1);
- var underlyingSource2 = Object.create(Object.prototype);
- createDataProperty(underlyingSource2, 'pull', pull);
- createDataProperty(underlyingSource2, 'cancel', cancel2);
- var branch2Stream = new ReadableStream(underlyingSource2);
- pull._branch1 = branch1Stream._readableStreamController;
- pull._branch2 = branch2Stream._readableStreamController;
- reader._closedPromise.catch(function (r) {
- if (teeState.closedOrErrored === true) {
- return;
- }
- ReadableStreamDefaultControllerError(pull._branch1, r);
- ReadableStreamDefaultControllerError(pull._branch2, r);
- teeState.closedOrErrored = true;
- });
- return [branch1Stream, branch2Stream];
- }
- function create_ReadableStreamTeePullFunction() {
- function f() {
- var reader = f._reader,
- branch1 = f._branch1,
- branch2 = f._branch2,
- teeState = f._teeState;
- return ReadableStreamDefaultReaderRead(reader).then(function (result) {
- assert(typeIsObject(result));
- var value = result.value;
- var done = result.done;
- assert(typeof done === 'boolean');
- if (done === true && teeState.closedOrErrored === false) {
- if (teeState.canceled1 === false) {
- ReadableStreamDefaultControllerClose(branch1);
- }
- if (teeState.canceled2 === false) {
- ReadableStreamDefaultControllerClose(branch2);
- }
- teeState.closedOrErrored = true;
- }
- if (teeState.closedOrErrored === true) {
- return;
- }
- var value1 = value;
- var value2 = value;
- if (teeState.canceled1 === false) {
- ReadableStreamDefaultControllerEnqueue(branch1, value1);
- }
- if (teeState.canceled2 === false) {
- ReadableStreamDefaultControllerEnqueue(branch2, value2);
- }
- });
- }
- return f;
- }
- function create_ReadableStreamTeeBranch1CancelFunction() {
- function f(reason) {
- var stream = f._stream,
- teeState = f._teeState;
- teeState.canceled1 = true;
- teeState.reason1 = reason;
- if (teeState.canceled2 === true) {
- var compositeReason = createArrayFromList([teeState.reason1, teeState.reason2]);
- var cancelResult = ReadableStreamCancel(stream, compositeReason);
- teeState._resolve(cancelResult);
- }
- return teeState.promise;
- }
- return f;
- }
- function create_ReadableStreamTeeBranch2CancelFunction() {
- function f(reason) {
- var stream = f._stream,
- teeState = f._teeState;
- teeState.canceled2 = true;
- teeState.reason2 = reason;
- if (teeState.canceled1 === true) {
- var compositeReason = createArrayFromList([teeState.reason1, teeState.reason2]);
- var cancelResult = ReadableStreamCancel(stream, compositeReason);
- teeState._resolve(cancelResult);
- }
- return teeState.promise;
- }
- return f;
- }
- function ReadableStreamAddReadIntoRequest(stream) {
- assert(IsReadableStreamBYOBReader(stream._reader) === true);
- assert(stream._state === 'readable' || stream._state === 'closed');
- var promise = new Promise(function (resolve, reject) {
- var readIntoRequest = {
- _resolve: resolve,
- _reject: reject
- };
- stream._reader._readIntoRequests.push(readIntoRequest);
- });
- return promise;
- }
- function ReadableStreamAddReadRequest(stream) {
- assert(IsReadableStreamDefaultReader(stream._reader) === true);
- assert(stream._state === 'readable');
- var promise = new Promise(function (resolve, reject) {
- var readRequest = {
- _resolve: resolve,
- _reject: reject
- };
- stream._reader._readRequests.push(readRequest);
- });
- return promise;
- }
- function ReadableStreamCancel(stream, reason) {
- stream._disturbed = true;
- if (stream._state === 'closed') {
- return Promise.resolve(undefined);
- }
- if (stream._state === 'errored') {
- return Promise.reject(stream._storedError);
- }
- ReadableStreamClose(stream);
- var sourceCancelPromise = stream._readableStreamController.__cancelSteps(reason);
- return sourceCancelPromise.then(function () {
- return undefined;
- });
- }
- function ReadableStreamClose(stream) {
- assert(stream._state === 'readable');
- stream._state = 'closed';
- var reader = stream._reader;
- if (reader === undefined) {
- return undefined;
- }
- if (IsReadableStreamDefaultReader(reader) === true) {
- for (var i = 0; i < reader._readRequests.length; i++) {
- var _resolve = reader._readRequests[i]._resolve;
- _resolve(CreateIterResultObject(undefined, true));
- }
- reader._readRequests = [];
- }
- defaultReaderClosedPromiseResolve(reader);
- return undefined;
- }
- function ReadableStreamError(stream, e) {
- assert(IsReadableStream(stream) === true, 'stream must be ReadableStream');
- assert(stream._state === 'readable', 'state must be readable');
- stream._state = 'errored';
- stream._storedError = e;
- var reader = stream._reader;
- if (reader === undefined) {
- return undefined;
- }
- if (IsReadableStreamDefaultReader(reader) === true) {
- for (var i = 0; i < reader._readRequests.length; i++) {
- var readRequest = reader._readRequests[i];
- readRequest._reject(e);
- }
- reader._readRequests = [];
- } else {
- assert(IsReadableStreamBYOBReader(reader), 'reader must be ReadableStreamBYOBReader');
- for (var _i = 0; _i < reader._readIntoRequests.length; _i++) {
- var readIntoRequest = reader._readIntoRequests[_i];
- readIntoRequest._reject(e);
- }
- reader._readIntoRequests = [];
- }
- defaultReaderClosedPromiseReject(reader, e);
- reader._closedPromise.catch(function () {});
- }
- function ReadableStreamFulfillReadIntoRequest(stream, chunk, done) {
- var reader = stream._reader;
- assert(reader._readIntoRequests.length > 0);
- var readIntoRequest = reader._readIntoRequests.shift();
- readIntoRequest._resolve(CreateIterResultObject(chunk, done));
- }
- function ReadableStreamFulfillReadRequest(stream, chunk, done) {
- var reader = stream._reader;
- assert(reader._readRequests.length > 0);
- var readRequest = reader._readRequests.shift();
- readRequest._resolve(CreateIterResultObject(chunk, done));
- }
- function ReadableStreamGetNumReadIntoRequests(stream) {
- return stream._reader._readIntoRequests.length;
- }
- function ReadableStreamGetNumReadRequests(stream) {
- return stream._reader._readRequests.length;
- }
- function ReadableStreamHasBYOBReader(stream) {
- var reader = stream._reader;
- if (reader === undefined) {
- return false;
- }
- if (IsReadableStreamBYOBReader(reader) === false) {
- return false;
- }
- return true;
- }
- function ReadableStreamHasDefaultReader(stream) {
- var reader = stream._reader;
- if (reader === undefined) {
- return false;
- }
- if (IsReadableStreamDefaultReader(reader) === false) {
- return false;
- }
- return true;
- }
- var ReadableStreamDefaultReader = function () {
- function ReadableStreamDefaultReader(stream) {
- _classCallCheck(this, ReadableStreamDefaultReader);
- if (IsReadableStream(stream) === false) {
- throw new TypeError('ReadableStreamDefaultReader can only be constructed with a ReadableStream instance');
- }
- if (IsReadableStreamLocked(stream) === true) {
- throw new TypeError('This stream has already been locked for exclusive reading by another reader');
- }
- ReadableStreamReaderGenericInitialize(this, stream);
- this._readRequests = [];
- }
- _createClass(ReadableStreamDefaultReader, [{
- key: 'cancel',
- value: function cancel(reason) {
- if (IsReadableStreamDefaultReader(this) === false) {
- return Promise.reject(defaultReaderBrandCheckException('cancel'));
- }
- if (this._ownerReadableStream === undefined) {
- return Promise.reject(readerLockException('cancel'));
- }
- return ReadableStreamReaderGenericCancel(this, reason);
- }
- }, {
- key: 'read',
- value: function read() {
- if (IsReadableStreamDefaultReader(this) === false) {
- return Promise.reject(defaultReaderBrandCheckException('read'));
- }
- if (this._ownerReadableStream === undefined) {
- return Promise.reject(readerLockException('read from'));
- }
- return ReadableStreamDefaultReaderRead(this);
- }
- }, {
- key: 'releaseLock',
- value: function releaseLock() {
- if (IsReadableStreamDefaultReader(this) === false) {
- throw defaultReaderBrandCheckException('releaseLock');
- }
- if (this._ownerReadableStream === undefined) {
- return;
- }
- if (this._readRequests.length > 0) {
- throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled');
- }
- ReadableStreamReaderGenericRelease(this);
- }
- }, {
- key: 'closed',
- get: function get() {
- if (IsReadableStreamDefaultReader(this) === false) {
- return Promise.reject(defaultReaderBrandCheckException('closed'));
- }
- return this._closedPromise;
- }
- }]);
- return ReadableStreamDefaultReader;
- }();
- var ReadableStreamBYOBReader = function () {
- function ReadableStreamBYOBReader(stream) {
- _classCallCheck(this, ReadableStreamBYOBReader);
- if (!IsReadableStream(stream)) {
- throw new TypeError('ReadableStreamBYOBReader can only be constructed with a ReadableStream instance given a ' + 'byte source');
- }
- if (IsReadableByteStreamController(stream._readableStreamController) === false) {
- throw new TypeError('Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte ' + 'source');
- }
- if (IsReadableStreamLocked(stream)) {
- throw new TypeError('This stream has already been locked for exclusive reading by another reader');
- }
- ReadableStreamReaderGenericInitialize(this, stream);
- this._readIntoRequests = [];
- }
- _createClass(ReadableStreamBYOBReader, [{
- key: 'cancel',
- value: function cancel(reason) {
- if (!IsReadableStreamBYOBReader(this)) {
- return Promise.reject(byobReaderBrandCheckException('cancel'));
- }
- if (this._ownerReadableStream === undefined) {
- return Promise.reject(readerLockException('cancel'));
- }
- return ReadableStreamReaderGenericCancel(this, reason);
- }
- }, {
- key: 'read',
- value: function read(view) {
- if (!IsReadableStreamBYOBReader(this)) {
- return Promise.reject(byobReaderBrandCheckException('read'));
- }
- if (this._ownerReadableStream === undefined) {
- return Promise.reject(readerLockException('read from'));
- }
- if (!ArrayBuffer.isView(view)) {
- return Promise.reject(new TypeError('view must be an array buffer view'));
- }
- if (view.byteLength === 0) {
- return Promise.reject(new TypeError('view must have non-zero byteLength'));
- }
- return ReadableStreamBYOBReaderRead(this, view);
- }
- }, {
- key: 'releaseLock',
- value: function releaseLock() {
- if (!IsReadableStreamBYOBReader(this)) {
- throw byobReaderBrandCheckException('releaseLock');
- }
- if (this._ownerReadableStream === undefined) {
- return;
- }
- if (this._readIntoRequests.length > 0) {
- throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled');
- }
- ReadableStreamReaderGenericRelease(this);
- }
- }, {
- key: 'closed',
- get: function get() {
- if (!IsReadableStreamBYOBReader(this)) {
- return Promise.reject(byobReaderBrandCheckException('closed'));
- }
- return this._closedPromise;
- }
- }]);
- return ReadableStreamBYOBReader;
- }();
- function IsReadableStreamBYOBReader(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_readIntoRequests')) {
- return false;
- }
- return true;
- }
- function IsReadableStreamDefaultReader(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_readRequests')) {
- return false;
- }
- return true;
- }
- function ReadableStreamReaderGenericInitialize(reader, stream) {
- reader._ownerReadableStream = stream;
- stream._reader = reader;
- if (stream._state === 'readable') {
- defaultReaderClosedPromiseInitialize(reader);
- } else if (stream._state === 'closed') {
- defaultReaderClosedPromiseInitializeAsResolved(reader);
- } else {
- assert(stream._state === 'errored', 'state must be errored');
- defaultReaderClosedPromiseInitializeAsRejected(reader, stream._storedError);
- reader._closedPromise.catch(function () {});
- }
- }
- function ReadableStreamReaderGenericCancel(reader, reason) {
- var stream = reader._ownerReadableStream;
- assert(stream !== undefined);
- return ReadableStreamCancel(stream, reason);
- }
- function ReadableStreamReaderGenericRelease(reader) {
- assert(reader._ownerReadableStream !== undefined);
- assert(reader._ownerReadableStream._reader === reader);
- if (reader._ownerReadableStream._state === 'readable') {
- defaultReaderClosedPromiseReject(reader, new TypeError('Reader was released and can no longer be used to monitor the stream\'s closedness'));
- } else {
- defaultReaderClosedPromiseResetToRejected(reader, new TypeError('Reader was released and can no longer be used to monitor the stream\'s closedness'));
- }
- reader._closedPromise.catch(function () {});
- reader._ownerReadableStream._reader = undefined;
- reader._ownerReadableStream = undefined;
- }
- function ReadableStreamBYOBReaderRead(reader, view) {
- var stream = reader._ownerReadableStream;
- assert(stream !== undefined);
- stream._disturbed = true;
- if (stream._state === 'errored') {
- return Promise.reject(stream._storedError);
- }
- return ReadableByteStreamControllerPullInto(stream._readableStreamController, view);
- }
- function ReadableStreamDefaultReaderRead(reader) {
- var stream = reader._ownerReadableStream;
- assert(stream !== undefined);
- stream._disturbed = true;
- if (stream._state === 'closed') {
- return Promise.resolve(CreateIterResultObject(undefined, true));
- }
- if (stream._state === 'errored') {
- return Promise.reject(stream._storedError);
- }
- assert(stream._state === 'readable');
- return stream._readableStreamController.__pullSteps();
- }
- var ReadableStreamDefaultController = function () {
- function ReadableStreamDefaultController(stream, underlyingSource, size, highWaterMark) {
- _classCallCheck(this, ReadableStreamDefaultController);
- if (IsReadableStream(stream) === false) {
- throw new TypeError('ReadableStreamDefaultController can only be constructed with a ReadableStream instance');
- }
- if (stream._readableStreamController !== undefined) {
- throw new TypeError('ReadableStreamDefaultController instances can only be created by the ReadableStream constructor');
- }
- this._controlledReadableStream = stream;
- this._underlyingSource = underlyingSource;
- this._queue = undefined;
- this._queueTotalSize = undefined;
- ResetQueue(this);
- this._started = false;
- this._closeRequested = false;
- this._pullAgain = false;
- this._pulling = false;
- var normalizedStrategy = ValidateAndNormalizeQueuingStrategy(size, highWaterMark);
- this._strategySize = normalizedStrategy.size;
- this._strategyHWM = normalizedStrategy.highWaterMark;
- var controller = this;
- var startResult = InvokeOrNoop(underlyingSource, 'start', [this]);
- Promise.resolve(startResult).then(function () {
- controller._started = true;
- assert(controller._pulling === false);
- assert(controller._pullAgain === false);
- ReadableStreamDefaultControllerCallPullIfNeeded(controller);
- }, function (r) {
- ReadableStreamDefaultControllerErrorIfNeeded(controller, r);
- }).catch(rethrowAssertionErrorRejection);
- }
- _createClass(ReadableStreamDefaultController, [{
- key: 'close',
- value: function close() {
- if (IsReadableStreamDefaultController(this) === false) {
- throw defaultControllerBrandCheckException('close');
- }
- if (this._closeRequested === true) {
- throw new TypeError('The stream has already been closed; do not close it again!');
- }
- var state = this._controlledReadableStream._state;
- if (state !== 'readable') {
- throw new TypeError('The stream (in ' + state + ' state) is not in the readable state and cannot be closed');
- }
- ReadableStreamDefaultControllerClose(this);
- }
- }, {
- key: 'enqueue',
- value: function enqueue(chunk) {
- if (IsReadableStreamDefaultController(this) === false) {
- throw defaultControllerBrandCheckException('enqueue');
- }
- if (this._closeRequested === true) {
- throw new TypeError('stream is closed or draining');
- }
- var state = this._controlledReadableStream._state;
- if (state !== 'readable') {
- throw new TypeError('The stream (in ' + state + ' state) is not in the readable state and cannot be enqueued to');
- }
- return ReadableStreamDefaultControllerEnqueue(this, chunk);
- }
- }, {
- key: 'error',
- value: function error(e) {
- if (IsReadableStreamDefaultController(this) === false) {
- throw defaultControllerBrandCheckException('error');
- }
- var stream = this._controlledReadableStream;
- if (stream._state !== 'readable') {
- throw new TypeError('The stream is ' + stream._state + ' and so cannot be errored');
- }
- ReadableStreamDefaultControllerError(this, e);
- }
- }, {
- key: '__cancelSteps',
- value: function __cancelSteps(reason) {
- ResetQueue(this);
- return PromiseInvokeOrNoop(this._underlyingSource, 'cancel', [reason]);
- }
- }, {
- key: '__pullSteps',
- value: function __pullSteps() {
- var stream = this._controlledReadableStream;
- if (this._queue.length > 0) {
- var chunk = DequeueValue(this);
- if (this._closeRequested === true && this._queue.length === 0) {
- ReadableStreamClose(stream);
- } else {
- ReadableStreamDefaultControllerCallPullIfNeeded(this);
- }
- return Promise.resolve(CreateIterResultObject(chunk, false));
- }
- var pendingPromise = ReadableStreamAddReadRequest(stream);
- ReadableStreamDefaultControllerCallPullIfNeeded(this);
- return pendingPromise;
- }
- }, {
- key: 'desiredSize',
- get: function get() {
- if (IsReadableStreamDefaultController(this) === false) {
- throw defaultControllerBrandCheckException('desiredSize');
- }
- return ReadableStreamDefaultControllerGetDesiredSize(this);
- }
- }]);
- return ReadableStreamDefaultController;
- }();
- function IsReadableStreamDefaultController(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_underlyingSource')) {
- return false;
- }
- return true;
- }
- function ReadableStreamDefaultControllerCallPullIfNeeded(controller) {
- var shouldPull = ReadableStreamDefaultControllerShouldCallPull(controller);
- if (shouldPull === false) {
- return undefined;
- }
- if (controller._pulling === true) {
- controller._pullAgain = true;
- return undefined;
- }
- assert(controller._pullAgain === false);
- controller._pulling = true;
- var pullPromise = PromiseInvokeOrNoop(controller._underlyingSource, 'pull', [controller]);
- pullPromise.then(function () {
- controller._pulling = false;
- if (controller._pullAgain === true) {
- controller._pullAgain = false;
- return ReadableStreamDefaultControllerCallPullIfNeeded(controller);
- }
- return undefined;
- }, function (e) {
- ReadableStreamDefaultControllerErrorIfNeeded(controller, e);
- }).catch(rethrowAssertionErrorRejection);
- return undefined;
- }
- function ReadableStreamDefaultControllerShouldCallPull(controller) {
- var stream = controller._controlledReadableStream;
- if (stream._state === 'closed' || stream._state === 'errored') {
- return false;
- }
- if (controller._closeRequested === true) {
- return false;
- }
- if (controller._started === false) {
- return false;
- }
- if (IsReadableStreamLocked(stream) === true && ReadableStreamGetNumReadRequests(stream) > 0) {
- return true;
- }
- var desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller);
- if (desiredSize > 0) {
- return true;
- }
- return false;
- }
- function ReadableStreamDefaultControllerClose(controller) {
- var stream = controller._controlledReadableStream;
- assert(controller._closeRequested === false);
- assert(stream._state === 'readable');
- controller._closeRequested = true;
- if (controller._queue.length === 0) {
- ReadableStreamClose(stream);
- }
- }
- function ReadableStreamDefaultControllerEnqueue(controller, chunk) {
- var stream = controller._controlledReadableStream;
- assert(controller._closeRequested === false);
- assert(stream._state === 'readable');
- if (IsReadableStreamLocked(stream) === true && ReadableStreamGetNumReadRequests(stream) > 0) {
- ReadableStreamFulfillReadRequest(stream, chunk, false);
- } else {
- var chunkSize = 1;
- if (controller._strategySize !== undefined) {
- var strategySize = controller._strategySize;
- try {
- chunkSize = strategySize(chunk);
- } catch (chunkSizeE) {
- ReadableStreamDefaultControllerErrorIfNeeded(controller, chunkSizeE);
- throw chunkSizeE;
- }
- }
- try {
- EnqueueValueWithSize(controller, chunk, chunkSize);
- } catch (enqueueE) {
- ReadableStreamDefaultControllerErrorIfNeeded(controller, enqueueE);
- throw enqueueE;
- }
- }
- ReadableStreamDefaultControllerCallPullIfNeeded(controller);
- return undefined;
- }
- function ReadableStreamDefaultControllerError(controller, e) {
- var stream = controller._controlledReadableStream;
- assert(stream._state === 'readable');
- ResetQueue(controller);
- ReadableStreamError(stream, e);
- }
- function ReadableStreamDefaultControllerErrorIfNeeded(controller, e) {
- if (controller._controlledReadableStream._state === 'readable') {
- ReadableStreamDefaultControllerError(controller, e);
- }
- }
- function ReadableStreamDefaultControllerGetDesiredSize(controller) {
- var stream = controller._controlledReadableStream;
- var state = stream._state;
- if (state === 'errored') {
- return null;
- }
- if (state === 'closed') {
- return 0;
- }
- return controller._strategyHWM - controller._queueTotalSize;
- }
- var ReadableStreamBYOBRequest = function () {
- function ReadableStreamBYOBRequest(controller, view) {
- _classCallCheck(this, ReadableStreamBYOBRequest);
- this._associatedReadableByteStreamController = controller;
- this._view = view;
- }
- _createClass(ReadableStreamBYOBRequest, [{
- key: 'respond',
- value: function respond(bytesWritten) {
- if (IsReadableStreamBYOBRequest(this) === false) {
- throw byobRequestBrandCheckException('respond');
- }
- if (this._associatedReadableByteStreamController === undefined) {
- throw new TypeError('This BYOB request has been invalidated');
- }
- ReadableByteStreamControllerRespond(this._associatedReadableByteStreamController, bytesWritten);
- }
- }, {
- key: 'respondWithNewView',
- value: function respondWithNewView(view) {
- if (IsReadableStreamBYOBRequest(this) === false) {
- throw byobRequestBrandCheckException('respond');
- }
- if (this._associatedReadableByteStreamController === undefined) {
- throw new TypeError('This BYOB request has been invalidated');
- }
- if (!ArrayBuffer.isView(view)) {
- throw new TypeError('You can only respond with array buffer views');
- }
- ReadableByteStreamControllerRespondWithNewView(this._associatedReadableByteStreamController, view);
- }
- }, {
- key: 'view',
- get: function get() {
- return this._view;
- }
- }]);
- return ReadableStreamBYOBRequest;
- }();
- var ReadableByteStreamController = function () {
- function ReadableByteStreamController(stream, underlyingByteSource, highWaterMark) {
- _classCallCheck(this, ReadableByteStreamController);
- if (IsReadableStream(stream) === false) {
- throw new TypeError('ReadableByteStreamController can only be constructed with a ReadableStream instance given ' + 'a byte source');
- }
- if (stream._readableStreamController !== undefined) {
- throw new TypeError('ReadableByteStreamController instances can only be created by the ReadableStream constructor given a byte ' + 'source');
- }
- this._controlledReadableStream = stream;
- this._underlyingByteSource = underlyingByteSource;
- this._pullAgain = false;
- this._pulling = false;
- ReadableByteStreamControllerClearPendingPullIntos(this);
- this._queue = this._queueTotalSize = undefined;
- ResetQueue(this);
- this._closeRequested = false;
- this._started = false;
- this._strategyHWM = ValidateAndNormalizeHighWaterMark(highWaterMark);
- var autoAllocateChunkSize = underlyingByteSource.autoAllocateChunkSize;
- if (autoAllocateChunkSize !== undefined) {
- if (Number.isInteger(autoAllocateChunkSize) === false || autoAllocateChunkSize <= 0) {
- throw new RangeError('autoAllocateChunkSize must be a positive integer');
- }
- }
- this._autoAllocateChunkSize = autoAllocateChunkSize;
- this._pendingPullIntos = [];
- var controller = this;
- var startResult = InvokeOrNoop(underlyingByteSource, 'start', [this]);
- Promise.resolve(startResult).then(function () {
- controller._started = true;
- assert(controller._pulling === false);
- assert(controller._pullAgain === false);
- ReadableByteStreamControllerCallPullIfNeeded(controller);
- }, function (r) {
- if (stream._state === 'readable') {
- ReadableByteStreamControllerError(controller, r);
- }
- }).catch(rethrowAssertionErrorRejection);
- }
- _createClass(ReadableByteStreamController, [{
- key: 'close',
- value: function close() {
- if (IsReadableByteStreamController(this) === false) {
- throw byteStreamControllerBrandCheckException('close');
- }
- if (this._closeRequested === true) {
- throw new TypeError('The stream has already been closed; do not close it again!');
- }
- var state = this._controlledReadableStream._state;
- if (state !== 'readable') {
- throw new TypeError('The stream (in ' + state + ' state) is not in the readable state and cannot be closed');
- }
- ReadableByteStreamControllerClose(this);
- }
- }, {
- key: 'enqueue',
- value: function enqueue(chunk) {
- if (IsReadableByteStreamController(this) === false) {
- throw byteStreamControllerBrandCheckException('enqueue');
- }
- if (this._closeRequested === true) {
- throw new TypeError('stream is closed or draining');
- }
- var state = this._controlledReadableStream._state;
- if (state !== 'readable') {
- throw new TypeError('The stream (in ' + state + ' state) is not in the readable state and cannot be enqueued to');
- }
- if (!ArrayBuffer.isView(chunk)) {
- throw new TypeError('You can only enqueue array buffer views when using a ReadableByteStreamController');
- }
- ReadableByteStreamControllerEnqueue(this, chunk);
- }
- }, {
- key: 'error',
- value: function error(e) {
- if (IsReadableByteStreamController(this) === false) {
- throw byteStreamControllerBrandCheckException('error');
- }
- var stream = this._controlledReadableStream;
- if (stream._state !== 'readable') {
- throw new TypeError('The stream is ' + stream._state + ' and so cannot be errored');
- }
- ReadableByteStreamControllerError(this, e);
- }
- }, {
- key: '__cancelSteps',
- value: function __cancelSteps(reason) {
- if (this._pendingPullIntos.length > 0) {
- var firstDescriptor = this._pendingPullIntos[0];
- firstDescriptor.bytesFilled = 0;
- }
- ResetQueue(this);
- return PromiseInvokeOrNoop(this._underlyingByteSource, 'cancel', [reason]);
- }
- }, {
- key: '__pullSteps',
- value: function __pullSteps() {
- var stream = this._controlledReadableStream;
- assert(ReadableStreamHasDefaultReader(stream) === true);
- if (this._queueTotalSize > 0) {
- assert(ReadableStreamGetNumReadRequests(stream) === 0);
- var entry = this._queue.shift();
- this._queueTotalSize -= entry.byteLength;
- ReadableByteStreamControllerHandleQueueDrain(this);
- var view = void 0;
- try {
- view = new Uint8Array(entry.buffer, entry.byteOffset, entry.byteLength);
- } catch (viewE) {
- return Promise.reject(viewE);
- }
- return Promise.resolve(CreateIterResultObject(view, false));
- }
- var autoAllocateChunkSize = this._autoAllocateChunkSize;
- if (autoAllocateChunkSize !== undefined) {
- var buffer = void 0;
- try {
- buffer = new ArrayBuffer(autoAllocateChunkSize);
- } catch (bufferE) {
- return Promise.reject(bufferE);
- }
- var pullIntoDescriptor = {
- buffer: buffer,
- byteOffset: 0,
- byteLength: autoAllocateChunkSize,
- bytesFilled: 0,
- elementSize: 1,
- ctor: Uint8Array,
- readerType: 'default'
- };
- this._pendingPullIntos.push(pullIntoDescriptor);
- }
- var promise = ReadableStreamAddReadRequest(stream);
- ReadableByteStreamControllerCallPullIfNeeded(this);
- return promise;
- }
- }, {
- key: 'byobRequest',
- get: function get() {
- if (IsReadableByteStreamController(this) === false) {
- throw byteStreamControllerBrandCheckException('byobRequest');
- }
- if (this._byobRequest === undefined && this._pendingPullIntos.length > 0) {
- var firstDescriptor = this._pendingPullIntos[0];
- var view = new Uint8Array(firstDescriptor.buffer, firstDescriptor.byteOffset + firstDescriptor.bytesFilled, firstDescriptor.byteLength - firstDescriptor.bytesFilled);
- this._byobRequest = new ReadableStreamBYOBRequest(this, view);
- }
- return this._byobRequest;
- }
- }, {
- key: 'desiredSize',
- get: function get() {
- if (IsReadableByteStreamController(this) === false) {
- throw byteStreamControllerBrandCheckException('desiredSize');
- }
- return ReadableByteStreamControllerGetDesiredSize(this);
- }
- }]);
- return ReadableByteStreamController;
- }();
- function IsReadableByteStreamController(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_underlyingByteSource')) {
- return false;
- }
- return true;
- }
- function IsReadableStreamBYOBRequest(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_associatedReadableByteStreamController')) {
- return false;
- }
- return true;
- }
- function ReadableByteStreamControllerCallPullIfNeeded(controller) {
- var shouldPull = ReadableByteStreamControllerShouldCallPull(controller);
- if (shouldPull === false) {
- return undefined;
- }
- if (controller._pulling === true) {
- controller._pullAgain = true;
- return undefined;
- }
- assert(controller._pullAgain === false);
- controller._pulling = true;
- var pullPromise = PromiseInvokeOrNoop(controller._underlyingByteSource, 'pull', [controller]);
- pullPromise.then(function () {
- controller._pulling = false;
- if (controller._pullAgain === true) {
- controller._pullAgain = false;
- ReadableByteStreamControllerCallPullIfNeeded(controller);
- }
- }, function (e) {
- if (controller._controlledReadableStream._state === 'readable') {
- ReadableByteStreamControllerError(controller, e);
- }
- }).catch(rethrowAssertionErrorRejection);
- return undefined;
- }
- function ReadableByteStreamControllerClearPendingPullIntos(controller) {
- ReadableByteStreamControllerInvalidateBYOBRequest(controller);
- controller._pendingPullIntos = [];
- }
- function ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor) {
- assert(stream._state !== 'errored', 'state must not be errored');
- var done = false;
- if (stream._state === 'closed') {
- assert(pullIntoDescriptor.bytesFilled === 0);
- done = true;
- }
- var filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor);
- if (pullIntoDescriptor.readerType === 'default') {
- ReadableStreamFulfillReadRequest(stream, filledView, done);
- } else {
- assert(pullIntoDescriptor.readerType === 'byob');
- ReadableStreamFulfillReadIntoRequest(stream, filledView, done);
- }
- }
- function ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor) {
- var bytesFilled = pullIntoDescriptor.bytesFilled;
- var elementSize = pullIntoDescriptor.elementSize;
- assert(bytesFilled <= pullIntoDescriptor.byteLength);
- assert(bytesFilled % elementSize === 0);
- return new pullIntoDescriptor.ctor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, bytesFilled / elementSize);
- }
- function ReadableByteStreamControllerEnqueueChunkToQueue(controller, buffer, byteOffset, byteLength) {
- controller._queue.push({
- buffer: buffer,
- byteOffset: byteOffset,
- byteLength: byteLength
- });
- controller._queueTotalSize += byteLength;
- }
- function ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) {
- var elementSize = pullIntoDescriptor.elementSize;
- var currentAlignedBytes = pullIntoDescriptor.bytesFilled - pullIntoDescriptor.bytesFilled % elementSize;
- var maxBytesToCopy = Math.min(controller._queueTotalSize, pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled);
- var maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy;
- var maxAlignedBytes = maxBytesFilled - maxBytesFilled % elementSize;
- var totalBytesToCopyRemaining = maxBytesToCopy;
- var ready = false;
- if (maxAlignedBytes > currentAlignedBytes) {
- totalBytesToCopyRemaining = maxAlignedBytes - pullIntoDescriptor.bytesFilled;
- ready = true;
- }
- var queue = controller._queue;
- while (totalBytesToCopyRemaining > 0) {
- var headOfQueue = queue[0];
- var bytesToCopy = Math.min(totalBytesToCopyRemaining, headOfQueue.byteLength);
- var destStart = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled;
- ArrayBufferCopy(pullIntoDescriptor.buffer, destStart, headOfQueue.buffer, headOfQueue.byteOffset, bytesToCopy);
- if (headOfQueue.byteLength === bytesToCopy) {
- queue.shift();
- } else {
- headOfQueue.byteOffset += bytesToCopy;
- headOfQueue.byteLength -= bytesToCopy;
- }
- controller._queueTotalSize -= bytesToCopy;
- ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesToCopy, pullIntoDescriptor);
- totalBytesToCopyRemaining -= bytesToCopy;
- }
- if (ready === false) {
- assert(controller._queueTotalSize === 0, 'queue must be empty');
- assert(pullIntoDescriptor.bytesFilled > 0);
- assert(pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize);
- }
- return ready;
- }
- function ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, size, pullIntoDescriptor) {
- assert(controller._pendingPullIntos.length === 0 || controller._pendingPullIntos[0] === pullIntoDescriptor);
- ReadableByteStreamControllerInvalidateBYOBRequest(controller);
- pullIntoDescriptor.bytesFilled += size;
- }
- function ReadableByteStreamControllerHandleQueueDrain(controller) {
- assert(controller._controlledReadableStream._state === 'readable');
- if (controller._queueTotalSize === 0 && controller._closeRequested === true) {
- ReadableStreamClose(controller._controlledReadableStream);
- } else {
- ReadableByteStreamControllerCallPullIfNeeded(controller);
- }
- }
- function ReadableByteStreamControllerInvalidateBYOBRequest(controller) {
- if (controller._byobRequest === undefined) {
- return;
- }
- controller._byobRequest._associatedReadableByteStreamController = undefined;
- controller._byobRequest._view = undefined;
- controller._byobRequest = undefined;
- }
- function ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller) {
- assert(controller._closeRequested === false);
- while (controller._pendingPullIntos.length > 0) {
- if (controller._queueTotalSize === 0) {
- return;
- }
- var pullIntoDescriptor = controller._pendingPullIntos[0];
- if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) === true) {
- ReadableByteStreamControllerShiftPendingPullInto(controller);
- ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableStream, pullIntoDescriptor);
- }
- }
- }
- function ReadableByteStreamControllerPullInto(controller, view) {
- var stream = controller._controlledReadableStream;
- var elementSize = 1;
- if (view.constructor !== DataView) {
- elementSize = view.constructor.BYTES_PER_ELEMENT;
- }
- var ctor = view.constructor;
- var pullIntoDescriptor = {
- buffer: view.buffer,
- byteOffset: view.byteOffset,
- byteLength: view.byteLength,
- bytesFilled: 0,
- elementSize: elementSize,
- ctor: ctor,
- readerType: 'byob'
- };
- if (controller._pendingPullIntos.length > 0) {
- pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer);
- controller._pendingPullIntos.push(pullIntoDescriptor);
- return ReadableStreamAddReadIntoRequest(stream);
- }
- if (stream._state === 'closed') {
- var emptyView = new view.constructor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, 0);
- return Promise.resolve(CreateIterResultObject(emptyView, true));
- }
- if (controller._queueTotalSize > 0) {
- if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) === true) {
- var filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor);
- ReadableByteStreamControllerHandleQueueDrain(controller);
- return Promise.resolve(CreateIterResultObject(filledView, false));
- }
- if (controller._closeRequested === true) {
- var e = new TypeError('Insufficient bytes to fill elements in the given buffer');
- ReadableByteStreamControllerError(controller, e);
- return Promise.reject(e);
- }
- }
- pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer);
- controller._pendingPullIntos.push(pullIntoDescriptor);
- var promise = ReadableStreamAddReadIntoRequest(stream);
- ReadableByteStreamControllerCallPullIfNeeded(controller);
- return promise;
- }
- function ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor) {
- firstDescriptor.buffer = TransferArrayBuffer(firstDescriptor.buffer);
- assert(firstDescriptor.bytesFilled === 0, 'bytesFilled must be 0');
- var stream = controller._controlledReadableStream;
- if (ReadableStreamHasBYOBReader(stream) === true) {
- while (ReadableStreamGetNumReadIntoRequests(stream) > 0) {
- var pullIntoDescriptor = ReadableByteStreamControllerShiftPendingPullInto(controller);
- ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor);
- }
- }
- }
- function ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, pullIntoDescriptor) {
- if (pullIntoDescriptor.bytesFilled + bytesWritten > pullIntoDescriptor.byteLength) {
- throw new RangeError('bytesWritten out of range');
- }
- ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesWritten, pullIntoDescriptor);
- if (pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize) {
- return;
- }
- ReadableByteStreamControllerShiftPendingPullInto(controller);
- var remainderSize = pullIntoDescriptor.bytesFilled % pullIntoDescriptor.elementSize;
- if (remainderSize > 0) {
- var end = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled;
- var remainder = pullIntoDescriptor.buffer.slice(end - remainderSize, end);
- ReadableByteStreamControllerEnqueueChunkToQueue(controller, remainder, 0, remainder.byteLength);
- }
- pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer);
- pullIntoDescriptor.bytesFilled -= remainderSize;
- ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableStream, pullIntoDescriptor);
- ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller);
- }
- function ReadableByteStreamControllerRespondInternal(controller, bytesWritten) {
- var firstDescriptor = controller._pendingPullIntos[0];
- var stream = controller._controlledReadableStream;
- if (stream._state === 'closed') {
- if (bytesWritten !== 0) {
- throw new TypeError('bytesWritten must be 0 when calling respond() on a closed stream');
- }
- ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor);
- } else {
- assert(stream._state === 'readable');
- ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, firstDescriptor);
- }
- }
- function ReadableByteStreamControllerShiftPendingPullInto(controller) {
- var descriptor = controller._pendingPullIntos.shift();
- ReadableByteStreamControllerInvalidateBYOBRequest(controller);
- return descriptor;
- }
- function ReadableByteStreamControllerShouldCallPull(controller) {
- var stream = controller._controlledReadableStream;
- if (stream._state !== 'readable') {
- return false;
- }
- if (controller._closeRequested === true) {
- return false;
- }
- if (controller._started === false) {
- return false;
- }
- if (ReadableStreamHasDefaultReader(stream) === true && ReadableStreamGetNumReadRequests(stream) > 0) {
- return true;
- }
- if (ReadableStreamHasBYOBReader(stream) === true && ReadableStreamGetNumReadIntoRequests(stream) > 0) {
- return true;
- }
- if (ReadableByteStreamControllerGetDesiredSize(controller) > 0) {
- return true;
- }
- return false;
- }
- function ReadableByteStreamControllerClose(controller) {
- var stream = controller._controlledReadableStream;
- assert(controller._closeRequested === false);
- assert(stream._state === 'readable');
- if (controller._queueTotalSize > 0) {
- controller._closeRequested = true;
- return;
- }
- if (controller._pendingPullIntos.length > 0) {
- var firstPendingPullInto = controller._pendingPullIntos[0];
- if (firstPendingPullInto.bytesFilled > 0) {
- var e = new TypeError('Insufficient bytes to fill elements in the given buffer');
- ReadableByteStreamControllerError(controller, e);
- throw e;
- }
- }
- ReadableStreamClose(stream);
- }
- function ReadableByteStreamControllerEnqueue(controller, chunk) {
- var stream = controller._controlledReadableStream;
- assert(controller._closeRequested === false);
- assert(stream._state === 'readable');
- var buffer = chunk.buffer;
- var byteOffset = chunk.byteOffset;
- var byteLength = chunk.byteLength;
- var transferredBuffer = TransferArrayBuffer(buffer);
- if (ReadableStreamHasDefaultReader(stream) === true) {
- if (ReadableStreamGetNumReadRequests(stream) === 0) {
- ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength);
- } else {
- assert(controller._queue.length === 0);
- var transferredView = new Uint8Array(transferredBuffer, byteOffset, byteLength);
- ReadableStreamFulfillReadRequest(stream, transferredView, false);
- }
- } else if (ReadableStreamHasBYOBReader(stream) === true) {
- ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength);
- ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller);
- } else {
- assert(IsReadableStreamLocked(stream) === false, 'stream must not be locked');
- ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength);
- }
- }
- function ReadableByteStreamControllerError(controller, e) {
- var stream = controller._controlledReadableStream;
- assert(stream._state === 'readable');
- ReadableByteStreamControllerClearPendingPullIntos(controller);
- ResetQueue(controller);
- ReadableStreamError(stream, e);
- }
- function ReadableByteStreamControllerGetDesiredSize(controller) {
- var stream = controller._controlledReadableStream;
- var state = stream._state;
- if (state === 'errored') {
- return null;
- }
- if (state === 'closed') {
- return 0;
- }
- return controller._strategyHWM - controller._queueTotalSize;
- }
- function ReadableByteStreamControllerRespond(controller, bytesWritten) {
- bytesWritten = Number(bytesWritten);
- if (IsFiniteNonNegativeNumber(bytesWritten) === false) {
- throw new RangeError('bytesWritten must be a finite');
- }
- assert(controller._pendingPullIntos.length > 0);
- ReadableByteStreamControllerRespondInternal(controller, bytesWritten);
- }
- function ReadableByteStreamControllerRespondWithNewView(controller, view) {
- assert(controller._pendingPullIntos.length > 0);
- var firstDescriptor = controller._pendingPullIntos[0];
- if (firstDescriptor.byteOffset + firstDescriptor.bytesFilled !== view.byteOffset) {
- throw new RangeError('The region specified by view does not match byobRequest');
- }
- if (firstDescriptor.byteLength !== view.byteLength) {
- throw new RangeError('The buffer of view has different capacity than byobRequest');
- }
- firstDescriptor.buffer = view.buffer;
- ReadableByteStreamControllerRespondInternal(controller, view.byteLength);
- }
- function streamBrandCheckException(name) {
- return new TypeError('ReadableStream.prototype.' + name + ' can only be used on a ReadableStream');
- }
- function readerLockException(name) {
- return new TypeError('Cannot ' + name + ' a stream using a released reader');
- }
- function defaultReaderBrandCheckException(name) {
- return new TypeError('ReadableStreamDefaultReader.prototype.' + name + ' can only be used on a ReadableStreamDefaultReader');
- }
- function defaultReaderClosedPromiseInitialize(reader) {
- reader._closedPromise = new Promise(function (resolve, reject) {
- reader._closedPromise_resolve = resolve;
- reader._closedPromise_reject = reject;
- });
- }
- function defaultReaderClosedPromiseInitializeAsRejected(reader, reason) {
- reader._closedPromise = Promise.reject(reason);
- reader._closedPromise_resolve = undefined;
- reader._closedPromise_reject = undefined;
- }
- function defaultReaderClosedPromiseInitializeAsResolved(reader) {
- reader._closedPromise = Promise.resolve(undefined);
- reader._closedPromise_resolve = undefined;
- reader._closedPromise_reject = undefined;
- }
- function defaultReaderClosedPromiseReject(reader, reason) {
- assert(reader._closedPromise_resolve !== undefined);
- assert(reader._closedPromise_reject !== undefined);
- reader._closedPromise_reject(reason);
- reader._closedPromise_resolve = undefined;
- reader._closedPromise_reject = undefined;
- }
- function defaultReaderClosedPromiseResetToRejected(reader, reason) {
- assert(reader._closedPromise_resolve === undefined);
- assert(reader._closedPromise_reject === undefined);
- reader._closedPromise = Promise.reject(reason);
- }
- function defaultReaderClosedPromiseResolve(reader) {
- assert(reader._closedPromise_resolve !== undefined);
- assert(reader._closedPromise_reject !== undefined);
- reader._closedPromise_resolve(undefined);
- reader._closedPromise_resolve = undefined;
- reader._closedPromise_reject = undefined;
- }
- function byobReaderBrandCheckException(name) {
- return new TypeError('ReadableStreamBYOBReader.prototype.' + name + ' can only be used on a ReadableStreamBYOBReader');
- }
- function defaultControllerBrandCheckException(name) {
- return new TypeError('ReadableStreamDefaultController.prototype.' + name + ' can only be used on a ReadableStreamDefaultController');
- }
- function byobRequestBrandCheckException(name) {
- return new TypeError('ReadableStreamBYOBRequest.prototype.' + name + ' can only be used on a ReadableStreamBYOBRequest');
- }
- function byteStreamControllerBrandCheckException(name) {
- return new TypeError('ReadableByteStreamController.prototype.' + name + ' can only be used on a ReadableByteStreamController');
- }
- function ifIsObjectAndHasAPromiseIsHandledInternalSlotSetPromiseIsHandledToTrue(promise) {
- try {
- Promise.prototype.then.call(promise, undefined, function () {});
- } catch (e) {}
- }
-}, function (module, exports, __w_pdfjs_require__) {
- "use strict";
-
- var transformStream = __w_pdfjs_require__(6);
- var readableStream = __w_pdfjs_require__(4);
- var writableStream = __w_pdfjs_require__(2);
- exports.TransformStream = transformStream.TransformStream;
- exports.ReadableStream = readableStream.ReadableStream;
- exports.IsReadableStreamDisturbed = readableStream.IsReadableStreamDisturbed;
- exports.ReadableStreamDefaultControllerClose = readableStream.ReadableStreamDefaultControllerClose;
- exports.ReadableStreamDefaultControllerEnqueue = readableStream.ReadableStreamDefaultControllerEnqueue;
- exports.ReadableStreamDefaultControllerError = readableStream.ReadableStreamDefaultControllerError;
- exports.ReadableStreamDefaultControllerGetDesiredSize = readableStream.ReadableStreamDefaultControllerGetDesiredSize;
- exports.AcquireWritableStreamDefaultWriter = writableStream.AcquireWritableStreamDefaultWriter;
- exports.IsWritableStream = writableStream.IsWritableStream;
- exports.IsWritableStreamLocked = writableStream.IsWritableStreamLocked;
- exports.WritableStream = writableStream.WritableStream;
- exports.WritableStreamAbort = writableStream.WritableStreamAbort;
- exports.WritableStreamDefaultControllerError = writableStream.WritableStreamDefaultControllerError;
- exports.WritableStreamDefaultWriterCloseWithErrorPropagation = writableStream.WritableStreamDefaultWriterCloseWithErrorPropagation;
- exports.WritableStreamDefaultWriterRelease = writableStream.WritableStreamDefaultWriterRelease;
- exports.WritableStreamDefaultWriterWrite = writableStream.WritableStreamDefaultWriterWrite;
-}, function (module, exports, __w_pdfjs_require__) {
- "use strict";
-
- var _createClass = function () {
- function defineProperties(target, props) {
- for (var i = 0; i < props.length; i++) {
- var descriptor = props[i];
- descriptor.enumerable = descriptor.enumerable || false;
- descriptor.configurable = true;
- if ("value" in descriptor) descriptor.writable = true;
- Object.defineProperty(target, descriptor.key, descriptor);
- }
- }
- return function (Constructor, protoProps, staticProps) {
- if (protoProps) defineProperties(Constructor.prototype, protoProps);
- if (staticProps) defineProperties(Constructor, staticProps);
- return Constructor;
- };
- }();
- function _classCallCheck(instance, Constructor) {
- if (!(instance instanceof Constructor)) {
- throw new TypeError("Cannot call a class as a function");
- }
- }
- var _require = __w_pdfjs_require__(1),
- assert = _require.assert;
- var _require2 = __w_pdfjs_require__(0),
- InvokeOrNoop = _require2.InvokeOrNoop,
- PromiseInvokeOrPerformFallback = _require2.PromiseInvokeOrPerformFallback,
- PromiseInvokeOrNoop = _require2.PromiseInvokeOrNoop,
- typeIsObject = _require2.typeIsObject;
- var _require3 = __w_pdfjs_require__(4),
- ReadableStream = _require3.ReadableStream,
- ReadableStreamDefaultControllerClose = _require3.ReadableStreamDefaultControllerClose,
- ReadableStreamDefaultControllerEnqueue = _require3.ReadableStreamDefaultControllerEnqueue,
- ReadableStreamDefaultControllerError = _require3.ReadableStreamDefaultControllerError,
- ReadableStreamDefaultControllerGetDesiredSize = _require3.ReadableStreamDefaultControllerGetDesiredSize;
- var _require4 = __w_pdfjs_require__(2),
- WritableStream = _require4.WritableStream,
- WritableStreamDefaultControllerError = _require4.WritableStreamDefaultControllerError;
- function TransformStreamCloseReadable(transformStream) {
- if (transformStream._errored === true) {
- throw new TypeError('TransformStream is already errored');
- }
- if (transformStream._readableClosed === true) {
- throw new TypeError('Readable side is already closed');
- }
- TransformStreamCloseReadableInternal(transformStream);
- }
- function TransformStreamEnqueueToReadable(transformStream, chunk) {
- if (transformStream._errored === true) {
- throw new TypeError('TransformStream is already errored');
- }
- if (transformStream._readableClosed === true) {
- throw new TypeError('Readable side is already closed');
- }
- var controller = transformStream._readableController;
- try {
- ReadableStreamDefaultControllerEnqueue(controller, chunk);
- } catch (e) {
- transformStream._readableClosed = true;
- TransformStreamErrorIfNeeded(transformStream, e);
- throw transformStream._storedError;
- }
- var desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller);
- var maybeBackpressure = desiredSize <= 0;
- if (maybeBackpressure === true && transformStream._backpressure === false) {
- TransformStreamSetBackpressure(transformStream, true);
- }
- }
- function TransformStreamError(transformStream, e) {
- if (transformStream._errored === true) {
- throw new TypeError('TransformStream is already errored');
- }
- TransformStreamErrorInternal(transformStream, e);
- }
- function TransformStreamCloseReadableInternal(transformStream) {
- assert(transformStream._errored === false);
- assert(transformStream._readableClosed === false);
- try {
- ReadableStreamDefaultControllerClose(transformStream._readableController);
- } catch (e) {
- assert(false);
- }
- transformStream._readableClosed = true;
- }
- function TransformStreamErrorIfNeeded(transformStream, e) {
- if (transformStream._errored === false) {
- TransformStreamErrorInternal(transformStream, e);
- }
- }
- function TransformStreamErrorInternal(transformStream, e) {
- assert(transformStream._errored === false);
- transformStream._errored = true;
- transformStream._storedError = e;
- if (transformStream._writableDone === false) {
- WritableStreamDefaultControllerError(transformStream._writableController, e);
- }
- if (transformStream._readableClosed === false) {
- ReadableStreamDefaultControllerError(transformStream._readableController, e);
- }
- }
- function TransformStreamReadableReadyPromise(transformStream) {
- assert(transformStream._backpressureChangePromise !== undefined, '_backpressureChangePromise should have been initialized');
- if (transformStream._backpressure === false) {
- return Promise.resolve();
- }
- assert(transformStream._backpressure === true, '_backpressure should have been initialized');
- return transformStream._backpressureChangePromise;
- }
- function TransformStreamSetBackpressure(transformStream, backpressure) {
- assert(transformStream._backpressure !== backpressure, 'TransformStreamSetBackpressure() should be called only when backpressure is changed');
- if (transformStream._backpressureChangePromise !== undefined) {
- transformStream._backpressureChangePromise_resolve(backpressure);
- }
- transformStream._backpressureChangePromise = new Promise(function (resolve) {
- transformStream._backpressureChangePromise_resolve = resolve;
- });
- transformStream._backpressureChangePromise.then(function (resolution) {
- assert(resolution !== backpressure, '_backpressureChangePromise should be fulfilled only when backpressure is changed');
- });
- transformStream._backpressure = backpressure;
- }
- function TransformStreamDefaultTransform(chunk, transformStreamController) {
- var transformStream = transformStreamController._controlledTransformStream;
- TransformStreamEnqueueToReadable(transformStream, chunk);
- return Promise.resolve();
- }
- function TransformStreamTransform(transformStream, chunk) {
- assert(transformStream._errored === false);
- assert(transformStream._transforming === false);
- assert(transformStream._backpressure === false);
- transformStream._transforming = true;
- var transformer = transformStream._transformer;
- var controller = transformStream._transformStreamController;
- var transformPromise = PromiseInvokeOrPerformFallback(transformer, 'transform', [chunk, controller], TransformStreamDefaultTransform, [chunk, controller]);
- return transformPromise.then(function () {
- transformStream._transforming = false;
- return TransformStreamReadableReadyPromise(transformStream);
- }, function (e) {
- TransformStreamErrorIfNeeded(transformStream, e);
- return Promise.reject(e);
- });
- }
- function IsTransformStreamDefaultController(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_controlledTransformStream')) {
- return false;
- }
- return true;
- }
- function IsTransformStream(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_transformStreamController')) {
- return false;
- }
- return true;
- }
- var TransformStreamSink = function () {
- function TransformStreamSink(transformStream, startPromise) {
- _classCallCheck(this, TransformStreamSink);
- this._transformStream = transformStream;
- this._startPromise = startPromise;
- }
- _createClass(TransformStreamSink, [{
- key: 'start',
- value: function start(c) {
- var transformStream = this._transformStream;
- transformStream._writableController = c;
- return this._startPromise.then(function () {
- return TransformStreamReadableReadyPromise(transformStream);
- });
- }
- }, {
- key: 'write',
- value: function write(chunk) {
- var transformStream = this._transformStream;
- return TransformStreamTransform(transformStream, chunk);
- }
- }, {
- key: 'abort',
- value: function abort() {
- var transformStream = this._transformStream;
- transformStream._writableDone = true;
- TransformStreamErrorInternal(transformStream, new TypeError('Writable side aborted'));
- }
- }, {
- key: 'close',
- value: function close() {
- var transformStream = this._transformStream;
- assert(transformStream._transforming === false);
- transformStream._writableDone = true;
- var flushPromise = PromiseInvokeOrNoop(transformStream._transformer, 'flush', [transformStream._transformStreamController]);
- return flushPromise.then(function () {
- if (transformStream._errored === true) {
- return Promise.reject(transformStream._storedError);
- }
- if (transformStream._readableClosed === false) {
- TransformStreamCloseReadableInternal(transformStream);
- }
- return Promise.resolve();
- }).catch(function (r) {
- TransformStreamErrorIfNeeded(transformStream, r);
- return Promise.reject(transformStream._storedError);
- });
- }
- }]);
- return TransformStreamSink;
- }();
- var TransformStreamSource = function () {
- function TransformStreamSource(transformStream, startPromise) {
- _classCallCheck(this, TransformStreamSource);
- this._transformStream = transformStream;
- this._startPromise = startPromise;
- }
- _createClass(TransformStreamSource, [{
- key: 'start',
- value: function start(c) {
- var transformStream = this._transformStream;
- transformStream._readableController = c;
- return this._startPromise.then(function () {
- assert(transformStream._backpressureChangePromise !== undefined, '_backpressureChangePromise should have been initialized');
- if (transformStream._backpressure === true) {
- return Promise.resolve();
- }
- assert(transformStream._backpressure === false, '_backpressure should have been initialized');
- return transformStream._backpressureChangePromise;
- });
- }
- }, {
- key: 'pull',
- value: function pull() {
- var transformStream = this._transformStream;
- assert(transformStream._backpressure === true, 'pull() should be never called while _backpressure is false');
- assert(transformStream._backpressureChangePromise !== undefined, '_backpressureChangePromise should have been initialized');
- TransformStreamSetBackpressure(transformStream, false);
- return transformStream._backpressureChangePromise;
- }
- }, {
- key: 'cancel',
- value: function cancel() {
- var transformStream = this._transformStream;
- transformStream._readableClosed = true;
- TransformStreamErrorInternal(transformStream, new TypeError('Readable side canceled'));
- }
- }]);
- return TransformStreamSource;
- }();
- var TransformStreamDefaultController = function () {
- function TransformStreamDefaultController(transformStream) {
- _classCallCheck(this, TransformStreamDefaultController);
- if (IsTransformStream(transformStream) === false) {
- throw new TypeError('TransformStreamDefaultController can only be ' + 'constructed with a TransformStream instance');
- }
- if (transformStream._transformStreamController !== undefined) {
- throw new TypeError('TransformStreamDefaultController instances can ' + 'only be created by the TransformStream constructor');
- }
- this._controlledTransformStream = transformStream;
- }
- _createClass(TransformStreamDefaultController, [{
- key: 'enqueue',
- value: function enqueue(chunk) {
- if (IsTransformStreamDefaultController(this) === false) {
- throw defaultControllerBrandCheckException('enqueue');
- }
- TransformStreamEnqueueToReadable(this._controlledTransformStream, chunk);
- }
- }, {
- key: 'close',
- value: function close() {
- if (IsTransformStreamDefaultController(this) === false) {
- throw defaultControllerBrandCheckException('close');
- }
- TransformStreamCloseReadable(this._controlledTransformStream);
- }
- }, {
- key: 'error',
- value: function error(reason) {
- if (IsTransformStreamDefaultController(this) === false) {
- throw defaultControllerBrandCheckException('error');
- }
- TransformStreamError(this._controlledTransformStream, reason);
- }
- }, {
- key: 'desiredSize',
- get: function get() {
- if (IsTransformStreamDefaultController(this) === false) {
- throw defaultControllerBrandCheckException('desiredSize');
- }
- var transformStream = this._controlledTransformStream;
- var readableController = transformStream._readableController;
- return ReadableStreamDefaultControllerGetDesiredSize(readableController);
- }
- }]);
- return TransformStreamDefaultController;
- }();
- var TransformStream = function () {
- function TransformStream() {
- var transformer = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- _classCallCheck(this, TransformStream);
- this._transformer = transformer;
- var readableStrategy = transformer.readableStrategy,
- writableStrategy = transformer.writableStrategy;
- this._transforming = false;
- this._errored = false;
- this._storedError = undefined;
- this._writableController = undefined;
- this._readableController = undefined;
- this._transformStreamController = undefined;
- this._writableDone = false;
- this._readableClosed = false;
- this._backpressure = undefined;
- this._backpressureChangePromise = undefined;
- this._backpressureChangePromise_resolve = undefined;
- this._transformStreamController = new TransformStreamDefaultController(this);
- var startPromise_resolve = void 0;
- var startPromise = new Promise(function (resolve) {
- startPromise_resolve = resolve;
- });
- var source = new TransformStreamSource(this, startPromise);
- this._readable = new ReadableStream(source, readableStrategy);
- var sink = new TransformStreamSink(this, startPromise);
- this._writable = new WritableStream(sink, writableStrategy);
- assert(this._writableController !== undefined);
- assert(this._readableController !== undefined);
- var desiredSize = ReadableStreamDefaultControllerGetDesiredSize(this._readableController);
- TransformStreamSetBackpressure(this, desiredSize <= 0);
- var transformStream = this;
- var startResult = InvokeOrNoop(transformer, 'start', [transformStream._transformStreamController]);
- startPromise_resolve(startResult);
- startPromise.catch(function (e) {
- if (transformStream._errored === false) {
- transformStream._errored = true;
- transformStream._storedError = e;
- }
- });
- }
- _createClass(TransformStream, [{
- key: 'readable',
- get: function get() {
- if (IsTransformStream(this) === false) {
- throw streamBrandCheckException('readable');
- }
- return this._readable;
- }
- }, {
- key: 'writable',
- get: function get() {
- if (IsTransformStream(this) === false) {
- throw streamBrandCheckException('writable');
- }
- return this._writable;
- }
- }]);
- return TransformStream;
- }();
- module.exports = { TransformStream: TransformStream };
- function defaultControllerBrandCheckException(name) {
- return new TypeError('TransformStreamDefaultController.prototype.' + name + ' can only be used on a TransformStreamDefaultController');
- }
- function streamBrandCheckException(name) {
- return new TypeError('TransformStream.prototype.' + name + ' can only be used on a TransformStream');
- }
-}, function (module, exports, __w_pdfjs_require__) {
- module.exports = __w_pdfjs_require__(5);
-}]));
-
-/***/ }),
-/* 127 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-{
- var isURLSupported = false;
- try {
- if (typeof URL === 'function' && _typeof(URL.prototype) === 'object' && 'origin' in URL.prototype) {
- var u = new URL('b', 'http://a');
- u.pathname = 'c%20d';
- isURLSupported = u.href === 'http://a/c%20d';
- }
- } catch (ex) {}
- if (isURLSupported) {
- exports.URL = URL;
- } else {
- var PolyfillURL = __w_pdfjs_require__(128).URL;
- var OriginalURL = __w_pdfjs_require__(3).URL;
- if (OriginalURL) {
- PolyfillURL.createObjectURL = function (blob) {
- return OriginalURL.createObjectURL.apply(OriginalURL, arguments);
- };
- PolyfillURL.revokeObjectURL = function (url) {
- OriginalURL.revokeObjectURL(url);
- };
- }
- exports.URL = PolyfillURL;
- }
-}
-
-/***/ }),
-/* 128 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-(function URLConstructorClosure() {
- 'use strict';
-
- var relative = Object.create(null);
- relative['ftp'] = 21;
- relative['file'] = 0;
- relative['gopher'] = 70;
- relative['http'] = 80;
- relative['https'] = 443;
- relative['ws'] = 80;
- relative['wss'] = 443;
- var relativePathDotMapping = Object.create(null);
- relativePathDotMapping['%2e'] = '.';
- relativePathDotMapping['.%2e'] = '..';
- relativePathDotMapping['%2e.'] = '..';
- relativePathDotMapping['%2e%2e'] = '..';
- function isRelativeScheme(scheme) {
- return relative[scheme] !== undefined;
- }
- function invalid() {
- clear.call(this);
- this._isInvalid = true;
- }
- function IDNAToASCII(h) {
- if (h === '') {
- invalid.call(this);
- }
- return h.toLowerCase();
- }
- function percentEscape(c) {
- var unicode = c.charCodeAt(0);
- if (unicode > 0x20 && unicode < 0x7F && [0x22, 0x23, 0x3C, 0x3E, 0x3F, 0x60].indexOf(unicode) === -1) {
- return c;
- }
- return encodeURIComponent(c);
- }
- function percentEscapeQuery(c) {
- var unicode = c.charCodeAt(0);
- if (unicode > 0x20 && unicode < 0x7F && [0x22, 0x23, 0x3C, 0x3E, 0x60].indexOf(unicode) === -1) {
- return c;
- }
- return encodeURIComponent(c);
- }
- var EOF,
- ALPHA = /[a-zA-Z]/,
- ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
- function parse(input, stateOverride, base) {
- function err(message) {
- errors.push(message);
- }
- var state = stateOverride || 'scheme start',
- cursor = 0,
- buffer = '',
- seenAt = false,
- seenBracket = false,
- errors = [];
- loop: while ((input[cursor - 1] !== EOF || cursor === 0) && !this._isInvalid) {
- var c = input[cursor];
- switch (state) {
- case 'scheme start':
- if (c && ALPHA.test(c)) {
- buffer += c.toLowerCase();
- state = 'scheme';
- } else if (!stateOverride) {
- buffer = '';
- state = 'no scheme';
- continue;
- } else {
- err('Invalid scheme.');
- break loop;
- }
- break;
- case 'scheme':
- if (c && ALPHANUMERIC.test(c)) {
- buffer += c.toLowerCase();
- } else if (c === ':') {
- this._scheme = buffer;
- buffer = '';
- if (stateOverride) {
- break loop;
- }
- if (isRelativeScheme(this._scheme)) {
- this._isRelative = true;
- }
- if (this._scheme === 'file') {
- state = 'relative';
- } else if (this._isRelative && base && base._scheme === this._scheme) {
- state = 'relative or authority';
- } else if (this._isRelative) {
- state = 'authority first slash';
- } else {
- state = 'scheme data';
- }
- } else if (!stateOverride) {
- buffer = '';
- cursor = 0;
- state = 'no scheme';
- continue;
- } else if (c === EOF) {
- break loop;
- } else {
- err('Code point not allowed in scheme: ' + c);
- break loop;
- }
- break;
- case 'scheme data':
- if (c === '?') {
- this._query = '?';
- state = 'query';
- } else if (c === '#') {
- this._fragment = '#';
- state = 'fragment';
- } else {
- if (c !== EOF && c !== '\t' && c !== '\n' && c !== '\r') {
- this._schemeData += percentEscape(c);
- }
- }
- break;
- case 'no scheme':
- if (!base || !isRelativeScheme(base._scheme)) {
- err('Missing scheme.');
- invalid.call(this);
- } else {
- state = 'relative';
- continue;
- }
- break;
- case 'relative or authority':
- if (c === '/' && input[cursor + 1] === '/') {
- state = 'authority ignore slashes';
- } else {
- err('Expected /, got: ' + c);
- state = 'relative';
- continue;
- }
- break;
- case 'relative':
- this._isRelative = true;
- if (this._scheme !== 'file') {
- this._scheme = base._scheme;
- }
- if (c === EOF) {
- this._host = base._host;
- this._port = base._port;
- this._path = base._path.slice();
- this._query = base._query;
- this._username = base._username;
- this._password = base._password;
- break loop;
- } else if (c === '/' || c === '\\') {
- if (c === '\\') {
- err('\\ is an invalid code point.');
- }
- state = 'relative slash';
- } else if (c === '?') {
- this._host = base._host;
- this._port = base._port;
- this._path = base._path.slice();
- this._query = '?';
- this._username = base._username;
- this._password = base._password;
- state = 'query';
- } else if (c === '#') {
- this._host = base._host;
- this._port = base._port;
- this._path = base._path.slice();
- this._query = base._query;
- this._fragment = '#';
- this._username = base._username;
- this._password = base._password;
- state = 'fragment';
- } else {
- var nextC = input[cursor + 1];
- var nextNextC = input[cursor + 2];
- if (this._scheme !== 'file' || !ALPHA.test(c) || nextC !== ':' && nextC !== '|' || nextNextC !== EOF && nextNextC !== '/' && nextNextC !== '\\' && nextNextC !== '?' && nextNextC !== '#') {
- this._host = base._host;
- this._port = base._port;
- this._username = base._username;
- this._password = base._password;
- this._path = base._path.slice();
- this._path.pop();
- }
- state = 'relative path';
- continue;
- }
- break;
- case 'relative slash':
- if (c === '/' || c === '\\') {
- if (c === '\\') {
- err('\\ is an invalid code point.');
- }
- if (this._scheme === 'file') {
- state = 'file host';
- } else {
- state = 'authority ignore slashes';
- }
- } else {
- if (this._scheme !== 'file') {
- this._host = base._host;
- this._port = base._port;
- this._username = base._username;
- this._password = base._password;
- }
- state = 'relative path';
- continue;
- }
- break;
- case 'authority first slash':
- if (c === '/') {
- state = 'authority second slash';
- } else {
- err('Expected \'/\', got: ' + c);
- state = 'authority ignore slashes';
- continue;
- }
- break;
- case 'authority second slash':
- state = 'authority ignore slashes';
- if (c !== '/') {
- err('Expected \'/\', got: ' + c);
- continue;
- }
- break;
- case 'authority ignore slashes':
- if (c !== '/' && c !== '\\') {
- state = 'authority';
- continue;
- } else {
- err('Expected authority, got: ' + c);
- }
- break;
- case 'authority':
- if (c === '@') {
- if (seenAt) {
- err('@ already seen.');
- buffer += '%40';
- }
- seenAt = true;
- for (var i = 0; i < buffer.length; i++) {
- var cp = buffer[i];
- if (cp === '\t' || cp === '\n' || cp === '\r') {
- err('Invalid whitespace in authority.');
- continue;
- }
- if (cp === ':' && this._password === null) {
- this._password = '';
- continue;
- }
- var tempC = percentEscape(cp);
- if (this._password !== null) {
- this._password += tempC;
- } else {
- this._username += tempC;
- }
- }
- buffer = '';
- } else if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#') {
- cursor -= buffer.length;
- buffer = '';
- state = 'host';
- continue;
- } else {
- buffer += c;
- }
- break;
- case 'file host':
- if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#') {
- if (buffer.length === 2 && ALPHA.test(buffer[0]) && (buffer[1] === ':' || buffer[1] === '|')) {
- state = 'relative path';
- } else if (buffer.length === 0) {
- state = 'relative path start';
- } else {
- this._host = IDNAToASCII.call(this, buffer);
- buffer = '';
- state = 'relative path start';
- }
- continue;
- } else if (c === '\t' || c === '\n' || c === '\r') {
- err('Invalid whitespace in file host.');
- } else {
- buffer += c;
- }
- break;
- case 'host':
- case 'hostname':
- if (c === ':' && !seenBracket) {
- this._host = IDNAToASCII.call(this, buffer);
- buffer = '';
- state = 'port';
- if (stateOverride === 'hostname') {
- break loop;
- }
- } else if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#') {
- this._host = IDNAToASCII.call(this, buffer);
- buffer = '';
- state = 'relative path start';
- if (stateOverride) {
- break loop;
- }
- continue;
- } else if (c !== '\t' && c !== '\n' && c !== '\r') {
- if (c === '[') {
- seenBracket = true;
- } else if (c === ']') {
- seenBracket = false;
- }
- buffer += c;
- } else {
- err('Invalid code point in host/hostname: ' + c);
- }
- break;
- case 'port':
- if (/[0-9]/.test(c)) {
- buffer += c;
- } else if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#' || stateOverride) {
- if (buffer !== '') {
- var temp = parseInt(buffer, 10);
- if (temp !== relative[this._scheme]) {
- this._port = temp + '';
- }
- buffer = '';
- }
- if (stateOverride) {
- break loop;
- }
- state = 'relative path start';
- continue;
- } else if (c === '\t' || c === '\n' || c === '\r') {
- err('Invalid code point in port: ' + c);
- } else {
- invalid.call(this);
- }
- break;
- case 'relative path start':
- if (c === '\\') {
- err('\'\\\' not allowed in path.');
- }
- state = 'relative path';
- if (c !== '/' && c !== '\\') {
- continue;
- }
- break;
- case 'relative path':
- if (c === EOF || c === '/' || c === '\\' || !stateOverride && (c === '?' || c === '#')) {
- if (c === '\\') {
- err('\\ not allowed in relative path.');
- }
- var tmp;
- if (tmp = relativePathDotMapping[buffer.toLowerCase()]) {
- buffer = tmp;
- }
- if (buffer === '..') {
- this._path.pop();
- if (c !== '/' && c !== '\\') {
- this._path.push('');
- }
- } else if (buffer === '.' && c !== '/' && c !== '\\') {
- this._path.push('');
- } else if (buffer !== '.') {
- if (this._scheme === 'file' && this._path.length === 0 && buffer.length === 2 && ALPHA.test(buffer[0]) && buffer[1] === '|') {
- buffer = buffer[0] + ':';
- }
- this._path.push(buffer);
- }
- buffer = '';
- if (c === '?') {
- this._query = '?';
- state = 'query';
- } else if (c === '#') {
- this._fragment = '#';
- state = 'fragment';
- }
- } else if (c !== '\t' && c !== '\n' && c !== '\r') {
- buffer += percentEscape(c);
- }
- break;
- case 'query':
- if (!stateOverride && c === '#') {
- this._fragment = '#';
- state = 'fragment';
- } else if (c !== EOF && c !== '\t' && c !== '\n' && c !== '\r') {
- this._query += percentEscapeQuery(c);
- }
- break;
- case 'fragment':
- if (c !== EOF && c !== '\t' && c !== '\n' && c !== '\r') {
- this._fragment += c;
- }
- break;
- }
- cursor++;
- }
- }
- function clear() {
- this._scheme = '';
- this._schemeData = '';
- this._username = '';
- this._password = null;
- this._host = '';
- this._port = '';
- this._path = [];
- this._query = '';
- this._fragment = '';
- this._isInvalid = false;
- this._isRelative = false;
- }
- function JURL(url, base) {
- if (base !== undefined && !(base instanceof JURL)) {
- base = new JURL(String(base));
- }
- this._url = url;
- clear.call(this);
- var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, '');
- parse.call(this, input, null, base);
- }
- JURL.prototype = {
- toString: function toString() {
- return this.href;
- },
-
- get href() {
- if (this._isInvalid) {
- return this._url;
- }
- var authority = '';
- if (this._username !== '' || this._password !== null) {
- authority = this._username + (this._password !== null ? ':' + this._password : '') + '@';
- }
- return this.protocol + (this._isRelative ? '//' + authority + this.host : '') + this.pathname + this._query + this._fragment;
- },
- set href(value) {
- clear.call(this);
- parse.call(this, value);
- },
- get protocol() {
- return this._scheme + ':';
- },
- set protocol(value) {
- if (this._isInvalid) {
- return;
- }
- parse.call(this, value + ':', 'scheme start');
- },
- get host() {
- return this._isInvalid ? '' : this._port ? this._host + ':' + this._port : this._host;
- },
- set host(value) {
- if (this._isInvalid || !this._isRelative) {
- return;
- }
- parse.call(this, value, 'host');
- },
- get hostname() {
- return this._host;
- },
- set hostname(value) {
- if (this._isInvalid || !this._isRelative) {
- return;
- }
- parse.call(this, value, 'hostname');
- },
- get port() {
- return this._port;
- },
- set port(value) {
- if (this._isInvalid || !this._isRelative) {
- return;
- }
- parse.call(this, value, 'port');
- },
- get pathname() {
- return this._isInvalid ? '' : this._isRelative ? '/' + this._path.join('/') : this._schemeData;
- },
- set pathname(value) {
- if (this._isInvalid || !this._isRelative) {
- return;
- }
- this._path = [];
- parse.call(this, value, 'relative path start');
- },
- get search() {
- return this._isInvalid || !this._query || this._query === '?' ? '' : this._query;
- },
- set search(value) {
- if (this._isInvalid || !this._isRelative) {
- return;
- }
- this._query = '?';
- if (value[0] === '?') {
- value = value.slice(1);
- }
- parse.call(this, value, 'query');
- },
- get hash() {
- return this._isInvalid || !this._fragment || this._fragment === '#' ? '' : this._fragment;
- },
- set hash(value) {
- if (this._isInvalid) {
- return;
- }
- this._fragment = '#';
- if (value[0] === '#') {
- value = value.slice(1);
- }
- parse.call(this, value, 'fragment');
- },
- get origin() {
- var host;
- if (this._isInvalid || !this._scheme) {
- return '';
- }
- switch (this._scheme) {
- case 'data':
- case 'file':
- case 'javascript':
- case 'mailto':
- return 'null';
- case 'blob':
- try {
- return new JURL(this._schemeData).origin || 'null';
- } catch (_) {}
- return 'null';
- }
- host = this.host;
- if (!host) {
- return '';
- }
- return this._scheme + '://' + host;
- }
- };
- exports.URL = JURL;
-})();
-
-/***/ }),
-/* 129 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.build = exports.version = exports.setPDFNetworkStreamFactory = exports.PDFPageProxy = exports.PDFDocumentProxy = exports.PDFWorker = exports.PDFDataRangeTransport = exports.LoopbackPort = exports.getDocument = undefined;
-
-var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-var _util = __w_pdfjs_require__(1);
-
-var _dom_utils = __w_pdfjs_require__(130);
-
-var _font_loader = __w_pdfjs_require__(131);
-
-var _api_compatibility = __w_pdfjs_require__(132);
-
-var _canvas = __w_pdfjs_require__(133);
-
-var _global_scope = __w_pdfjs_require__(3);
-
-var _global_scope2 = _interopRequireDefault(_global_scope);
-
-var _worker_options = __w_pdfjs_require__(135);
-
-var _message_handler = __w_pdfjs_require__(136);
-
-var _metadata = __w_pdfjs_require__(141);
-
-var _transport_stream = __w_pdfjs_require__(143);
-
-var _webgl = __w_pdfjs_require__(144);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-var DEFAULT_RANGE_CHUNK_SIZE = 65536;
-var isWorkerDisabled = false;
-var fallbackWorkerSrc = void 0;
-var fakeWorkerFilesLoader = null;
-{
- var useRequireEnsure = false;
- if (typeof window === 'undefined') {
- isWorkerDisabled = true;
- if (typeof require.ensure === 'undefined') {
- require.ensure = require('node-ensure');
- }
- useRequireEnsure = true;
- } else if (typeof require !== 'undefined' && typeof require.ensure === 'function') {
- useRequireEnsure = true;
- }
- if (typeof requirejs !== 'undefined' && requirejs.toUrl) {
- fallbackWorkerSrc = requirejs.toUrl('pdfjs-dist/build/pdf.worker.js');
- }
- var dynamicLoaderSupported = typeof requirejs !== 'undefined' && requirejs.load;
- fakeWorkerFilesLoader = useRequireEnsure ? function () {
- return new Promise(function (resolve, reject) {
- require.ensure([], function () {
- try {
- var worker = void 0;
- worker = require('./pdf.worker.js');
- resolve(worker.WorkerMessageHandler);
- } catch (ex) {
- reject(ex);
- }
- }, reject, 'pdfjsWorker');
- });
- } : dynamicLoaderSupported ? function () {
- return new Promise(function (resolve, reject) {
- requirejs(['pdfjs-dist/build/pdf.worker'], function (worker) {
- try {
- resolve(worker.WorkerMessageHandler);
- } catch (ex) {
- reject(ex);
- }
- }, reject);
- });
- } : null;
- if (!fallbackWorkerSrc && typeof document !== 'undefined') {
- var pdfjsFilePath = document.currentScript && document.currentScript.src;
- if (pdfjsFilePath) {
- fallbackWorkerSrc = pdfjsFilePath.replace(/(\.(?:min\.)?js)(\?.*)?$/i, '.worker$1$2');
- }
- }
-}
-var createPDFNetworkStream;
-function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) {
- createPDFNetworkStream = pdfNetworkStreamFactory;
-}
-function getDocument(src) {
- var task = new PDFDocumentLoadingTask();
- var source;
- if (typeof src === 'string') {
- source = { url: src };
- } else if ((0, _util.isArrayBuffer)(src)) {
- source = { data: src };
- } else if (src instanceof PDFDataRangeTransport) {
- source = { range: src };
- } else {
- if ((typeof src === 'undefined' ? 'undefined' : _typeof(src)) !== 'object') {
- throw new Error('Invalid parameter in getDocument, ' + 'need either Uint8Array, string or a parameter object');
- }
- if (!src.url && !src.data && !src.range) {
- throw new Error('Invalid parameter object: need either .data, .range or .url');
- }
- source = src;
- }
- var params = Object.create(null);
- var rangeTransport = null;
- var worker = null;
- for (var key in source) {
- if (key === 'url' && typeof window !== 'undefined') {
- params[key] = new _util.URL(source[key], window.location).href;
- continue;
- } else if (key === 'range') {
- rangeTransport = source[key];
- continue;
- } else if (key === 'worker') {
- worker = source[key];
- continue;
- } else if (key === 'data' && !(source[key] instanceof Uint8Array)) {
- var pdfBytes = source[key];
- if (typeof pdfBytes === 'string') {
- params[key] = (0, _util.stringToBytes)(pdfBytes);
- } else if ((typeof pdfBytes === 'undefined' ? 'undefined' : _typeof(pdfBytes)) === 'object' && pdfBytes !== null && !isNaN(pdfBytes.length)) {
- params[key] = new Uint8Array(pdfBytes);
- } else if ((0, _util.isArrayBuffer)(pdfBytes)) {
- params[key] = new Uint8Array(pdfBytes);
- } else {
- throw new Error('Invalid PDF binary data: either typed array, ' + 'string or array-like object is expected in the ' + 'data property.');
- }
- continue;
- }
- params[key] = source[key];
- }
- params.rangeChunkSize = params.rangeChunkSize || DEFAULT_RANGE_CHUNK_SIZE;
- params.CMapReaderFactory = params.CMapReaderFactory || _dom_utils.DOMCMapReaderFactory;
- params.ignoreErrors = params.stopAtErrors !== true;
- params.pdfBug = params.pdfBug === true;
- var NativeImageDecoderValues = Object.values(_util.NativeImageDecoding);
- if (params.nativeImageDecoderSupport === undefined || !NativeImageDecoderValues.includes(params.nativeImageDecoderSupport)) {
- params.nativeImageDecoderSupport = _api_compatibility.apiCompatibilityParams.nativeImageDecoderSupport || _util.NativeImageDecoding.DECODE;
- }
- if (!Number.isInteger(params.maxImageSize)) {
- params.maxImageSize = -1;
- }
- if (typeof params.isEvalSupported !== 'boolean') {
- params.isEvalSupported = true;
- }
- if (typeof params.disableFontFace !== 'boolean') {
- params.disableFontFace = _api_compatibility.apiCompatibilityParams.disableFontFace || false;
- }
- if (typeof params.disableRange !== 'boolean') {
- params.disableRange = false;
- }
- if (typeof params.disableStream !== 'boolean') {
- params.disableStream = false;
- }
- if (typeof params.disableAutoFetch !== 'boolean') {
- params.disableAutoFetch = false;
- }
- if (typeof params.disableCreateObjectURL !== 'boolean') {
- params.disableCreateObjectURL = _api_compatibility.apiCompatibilityParams.disableCreateObjectURL || false;
- }
- (0, _util.setVerbosityLevel)(params.verbosity);
- if (!worker) {
- var workerParams = {
- postMessageTransfers: params.postMessageTransfers,
- verbosity: params.verbosity
- };
- var workerPort = _worker_options.GlobalWorkerOptions.workerPort;
- if (workerPort) {
- workerParams.port = workerPort;
- worker = PDFWorker.fromPort(workerParams);
- } else {
- worker = new PDFWorker(workerParams);
- }
- task._worker = worker;
- }
- var docId = task.docId;
- worker.promise.then(function () {
- if (task.destroyed) {
- throw new Error('Loading aborted');
- }
- return _fetchDocument(worker, params, rangeTransport, docId).then(function (workerId) {
- if (task.destroyed) {
- throw new Error('Loading aborted');
- }
- var networkStream = void 0;
- if (rangeTransport) {
- networkStream = new _transport_stream.PDFDataTransportStream({
- length: params.length,
- initialData: params.initialData,
- disableRange: params.disableRange,
- disableStream: params.disableStream
- }, rangeTransport);
- } else if (!params.data) {
- networkStream = createPDFNetworkStream({
- url: params.url,
- length: params.length,
- httpHeaders: params.httpHeaders,
- withCredentials: params.withCredentials,
- rangeChunkSize: params.rangeChunkSize,
- disableRange: params.disableRange,
- disableStream: params.disableStream
- });
- }
- var messageHandler = new _message_handler.MessageHandler(docId, workerId, worker.port);
- messageHandler.postMessageTransfers = worker.postMessageTransfers;
- var transport = new WorkerTransport(messageHandler, task, networkStream, params);
- task._transport = transport;
- messageHandler.send('Ready', null);
- });
- }).catch(task._capability.reject);
- return task;
-}
-function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
- if (worker.destroyed) {
- return Promise.reject(new Error('Worker was destroyed'));
- }
- if (pdfDataRangeTransport) {
- source.length = pdfDataRangeTransport.length;
- source.initialData = pdfDataRangeTransport.initialData;
- }
- return worker.messageHandler.sendWithPromise('GetDocRequest', {
- docId: docId,
- apiVersion: '2.0.943',
- source: {
- data: source.data,
- url: source.url,
- password: source.password,
- disableAutoFetch: source.disableAutoFetch,
- rangeChunkSize: source.rangeChunkSize,
- length: source.length
- },
- maxImageSize: source.maxImageSize,
- disableFontFace: source.disableFontFace,
- disableCreateObjectURL: source.disableCreateObjectURL,
- postMessageTransfers: worker.postMessageTransfers,
- docBaseUrl: source.docBaseUrl,
- nativeImageDecoderSupport: source.nativeImageDecoderSupport,
- ignoreErrors: source.ignoreErrors,
- isEvalSupported: source.isEvalSupported
- }).then(function (workerId) {
- if (worker.destroyed) {
- throw new Error('Worker was destroyed');
- }
- return workerId;
- });
-}
-var PDFDocumentLoadingTask = function PDFDocumentLoadingTaskClosure() {
- var nextDocumentId = 0;
- function PDFDocumentLoadingTask() {
- this._capability = (0, _util.createPromiseCapability)();
- this._transport = null;
- this._worker = null;
- this.docId = 'd' + nextDocumentId++;
- this.destroyed = false;
- this.onPassword = null;
- this.onProgress = null;
- this.onUnsupportedFeature = null;
- }
- PDFDocumentLoadingTask.prototype = {
- get promise() {
- return this._capability.promise;
- },
- destroy: function destroy() {
- var _this = this;
-
- this.destroyed = true;
- var transportDestroyed = !this._transport ? Promise.resolve() : this._transport.destroy();
- return transportDestroyed.then(function () {
- _this._transport = null;
- if (_this._worker) {
- _this._worker.destroy();
- _this._worker = null;
- }
- });
- },
-
- then: function PDFDocumentLoadingTask_then(onFulfilled, onRejected) {
- return this.promise.then.apply(this.promise, arguments);
- }
- };
- return PDFDocumentLoadingTask;
-}();
-
-var PDFDataRangeTransport = function () {
- function PDFDataRangeTransport(length, initialData) {
- _classCallCheck(this, PDFDataRangeTransport);
-
- this.length = length;
- this.initialData = initialData;
- this._rangeListeners = [];
- this._progressListeners = [];
- this._progressiveReadListeners = [];
- this._readyCapability = (0, _util.createPromiseCapability)();
- }
-
- _createClass(PDFDataRangeTransport, [{
- key: 'addRangeListener',
- value: function addRangeListener(listener) {
- this._rangeListeners.push(listener);
- }
- }, {
- key: 'addProgressListener',
- value: function addProgressListener(listener) {
- this._progressListeners.push(listener);
- }
- }, {
- key: 'addProgressiveReadListener',
- value: function addProgressiveReadListener(listener) {
- this._progressiveReadListeners.push(listener);
- }
- }, {
- key: 'onDataRange',
- value: function onDataRange(begin, chunk) {
- var _iteratorNormalCompletion = true;
- var _didIteratorError = false;
- var _iteratorError = undefined;
-
- try {
- for (var _iterator = this._rangeListeners[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
- var listener = _step.value;
-
- listener(begin, chunk);
- }
- } catch (err) {
- _didIteratorError = true;
- _iteratorError = err;
- } finally {
- try {
- if (!_iteratorNormalCompletion && _iterator.return) {
- _iterator.return();
- }
- } finally {
- if (_didIteratorError) {
- throw _iteratorError;
- }
- }
- }
- }
- }, {
- key: 'onDataProgress',
- value: function onDataProgress(loaded) {
- var _this2 = this;
-
- this._readyCapability.promise.then(function () {
- var _iteratorNormalCompletion2 = true;
- var _didIteratorError2 = false;
- var _iteratorError2 = undefined;
-
- try {
- for (var _iterator2 = _this2._progressListeners[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
- var listener = _step2.value;
-
- listener(loaded);
- }
- } catch (err) {
- _didIteratorError2 = true;
- _iteratorError2 = err;
- } finally {
- try {
- if (!_iteratorNormalCompletion2 && _iterator2.return) {
- _iterator2.return();
- }
- } finally {
- if (_didIteratorError2) {
- throw _iteratorError2;
- }
- }
- }
- });
- }
- }, {
- key: 'onDataProgressiveRead',
- value: function onDataProgressiveRead(chunk) {
- var _this3 = this;
-
- this._readyCapability.promise.then(function () {
- var _iteratorNormalCompletion3 = true;
- var _didIteratorError3 = false;
- var _iteratorError3 = undefined;
-
- try {
- for (var _iterator3 = _this3._progressiveReadListeners[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
- var listener = _step3.value;
-
- listener(chunk);
- }
- } catch (err) {
- _didIteratorError3 = true;
- _iteratorError3 = err;
- } finally {
- try {
- if (!_iteratorNormalCompletion3 && _iterator3.return) {
- _iterator3.return();
- }
- } finally {
- if (_didIteratorError3) {
- throw _iteratorError3;
- }
- }
- }
- });
- }
- }, {
- key: 'transportReady',
- value: function transportReady() {
- this._readyCapability.resolve();
- }
- }, {
- key: 'requestDataRange',
- value: function requestDataRange(begin, end) {
- (0, _util.unreachable)('Abstract method PDFDataRangeTransport.requestDataRange');
- }
- }, {
- key: 'abort',
- value: function abort() {}
- }]);
-
- return PDFDataRangeTransport;
-}();
-
-var PDFDocumentProxy = function () {
- function PDFDocumentProxy(pdfInfo, transport, loadingTask) {
- _classCallCheck(this, PDFDocumentProxy);
-
- this.loadingTask = loadingTask;
- this._pdfInfo = pdfInfo;
- this._transport = transport;
- }
-
- _createClass(PDFDocumentProxy, [{
- key: 'getPage',
- value: function getPage(pageNumber) {
- return this._transport.getPage(pageNumber);
- }
- }, {
- key: 'getPageIndex',
- value: function getPageIndex(ref) {
- return this._transport.getPageIndex(ref);
- }
- }, {
- key: 'getDestinations',
- value: function getDestinations() {
- return this._transport.getDestinations();
- }
- }, {
- key: 'getDestination',
- value: function getDestination(id) {
- return this._transport.getDestination(id);
- }
- }, {
- key: 'getPageLabels',
- value: function getPageLabels() {
- return this._transport.getPageLabels();
- }
- }, {
- key: 'getPageMode',
- value: function getPageMode() {
- return this._transport.getPageMode();
- }
- }, {
- key: 'getAttachments',
- value: function getAttachments() {
- return this._transport.getAttachments();
- }
- }, {
- key: 'getJavaScript',
- value: function getJavaScript() {
- return this._transport.getJavaScript();
- }
- }, {
- key: 'getOutline',
- value: function getOutline() {
- return this._transport.getOutline();
- }
- }, {
- key: 'getPermissions',
- value: function getPermissions() {
- return this._transport.getPermissions();
- }
- }, {
- key: 'getMetadata',
- value: function getMetadata() {
- return this._transport.getMetadata();
- }
- }, {
- key: 'getData',
- value: function getData() {
- return this._transport.getData();
- }
- }, {
- key: 'getDownloadInfo',
- value: function getDownloadInfo() {
- return this._transport.downloadInfoCapability.promise;
- }
- }, {
- key: 'getStats',
- value: function getStats() {
- return this._transport.getStats();
- }
- }, {
- key: 'cleanup',
- value: function cleanup() {
- this._transport.startCleanup();
- }
- }, {
- key: 'destroy',
- value: function destroy() {
- return this.loadingTask.destroy();
- }
- }, {
- key: 'numPages',
- get: function get() {
- return this._pdfInfo.numPages;
- }
- }, {
- key: 'fingerprint',
- get: function get() {
- return this._pdfInfo.fingerprint;
- }
- }, {
- key: 'loadingParams',
- get: function get() {
- return this._transport.loadingParams;
- }
- }]);
-
- return PDFDocumentProxy;
-}();
-
-var PDFPageProxy = function PDFPageProxyClosure() {
- function PDFPageProxy(pageIndex, pageInfo, transport) {
- var pdfBug = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
-
- this.pageIndex = pageIndex;
- this._pageInfo = pageInfo;
- this.transport = transport;
- this._stats = pdfBug ? new _dom_utils.StatTimer() : _dom_utils.DummyStatTimer;
- this._pdfBug = pdfBug;
- this.commonObjs = transport.commonObjs;
- this.objs = new PDFObjects();
- this.cleanupAfterRender = false;
- this.pendingCleanup = false;
- this.intentStates = Object.create(null);
- this.destroyed = false;
- }
- PDFPageProxy.prototype = {
- get pageNumber() {
- return this.pageIndex + 1;
- },
- get rotate() {
- return this._pageInfo.rotate;
- },
- get ref() {
- return this._pageInfo.ref;
- },
- get userUnit() {
- return this._pageInfo.userUnit;
- },
- get view() {
- return this._pageInfo.view;
- },
- getViewport: function getViewport(scale) {
- var rotate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.rotate;
- var dontFlip = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
-
- return new _dom_utils.PageViewport({
- viewBox: this.view,
- scale: scale,
- rotation: rotate,
- dontFlip: dontFlip
- });
- },
-
- getAnnotations: function PDFPageProxy_getAnnotations(params) {
- var intent = params && params.intent || null;
- if (!this.annotationsPromise || this.annotationsIntent !== intent) {
- this.annotationsPromise = this.transport.getAnnotations(this.pageIndex, intent);
- this.annotationsIntent = intent;
- }
- return this.annotationsPromise;
- },
- render: function PDFPageProxy_render(params) {
- var _this4 = this;
-
- var stats = this._stats;
- stats.time('Overall');
- this.pendingCleanup = false;
- var renderingIntent = params.intent === 'print' ? 'print' : 'display';
- var canvasFactory = params.canvasFactory || new _dom_utils.DOMCanvasFactory();
- var webGLContext = new _webgl.WebGLContext({ enable: params.enableWebGL });
- if (!this.intentStates[renderingIntent]) {
- this.intentStates[renderingIntent] = Object.create(null);
- }
- var intentState = this.intentStates[renderingIntent];
- if (!intentState.displayReadyCapability) {
- intentState.receivingOperatorList = true;
- intentState.displayReadyCapability = (0, _util.createPromiseCapability)();
- intentState.operatorList = {
- fnArray: [],
- argsArray: [],
- lastChunk: false
- };
- stats.time('Page Request');
- this.transport.messageHandler.send('RenderPageRequest', {
- pageIndex: this.pageNumber - 1,
- intent: renderingIntent,
- renderInteractiveForms: params.renderInteractiveForms === true
- });
- }
- var complete = function complete(error) {
- var i = intentState.renderTasks.indexOf(internalRenderTask);
- if (i >= 0) {
- intentState.renderTasks.splice(i, 1);
- }
- if (_this4.cleanupAfterRender) {
- _this4.pendingCleanup = true;
- }
- _this4._tryCleanup();
- if (error) {
- internalRenderTask.capability.reject(error);
- } else {
- internalRenderTask.capability.resolve();
- }
- stats.timeEnd('Rendering');
- stats.timeEnd('Overall');
- };
- var internalRenderTask = new InternalRenderTask(complete, params, this.objs, this.commonObjs, intentState.operatorList, this.pageNumber, canvasFactory, webGLContext, this._pdfBug);
- internalRenderTask.useRequestAnimationFrame = renderingIntent !== 'print';
- if (!intentState.renderTasks) {
- intentState.renderTasks = [];
- }
- intentState.renderTasks.push(internalRenderTask);
- var renderTask = internalRenderTask.task;
- intentState.displayReadyCapability.promise.then(function (transparency) {
- if (_this4.pendingCleanup) {
- complete();
- return;
- }
- stats.time('Rendering');
- internalRenderTask.initializeGraphics(transparency);
- internalRenderTask.operatorListChanged();
- }).catch(complete);
- return renderTask;
- },
- getOperatorList: function PDFPageProxy_getOperatorList() {
- function operatorListChanged() {
- if (intentState.operatorList.lastChunk) {
- intentState.opListReadCapability.resolve(intentState.operatorList);
- var i = intentState.renderTasks.indexOf(opListTask);
- if (i >= 0) {
- intentState.renderTasks.splice(i, 1);
- }
- }
- }
- var renderingIntent = 'oplist';
- if (!this.intentStates[renderingIntent]) {
- this.intentStates[renderingIntent] = Object.create(null);
- }
- var intentState = this.intentStates[renderingIntent];
- var opListTask;
- if (!intentState.opListReadCapability) {
- opListTask = {};
- opListTask.operatorListChanged = operatorListChanged;
- intentState.receivingOperatorList = true;
- intentState.opListReadCapability = (0, _util.createPromiseCapability)();
- intentState.renderTasks = [];
- intentState.renderTasks.push(opListTask);
- intentState.operatorList = {
- fnArray: [],
- argsArray: [],
- lastChunk: false
- };
- this._stats.time('Page Request');
- this.transport.messageHandler.send('RenderPageRequest', {
- pageIndex: this.pageIndex,
- intent: renderingIntent
- });
- }
- return intentState.opListReadCapability.promise;
- },
- streamTextContent: function streamTextContent() {
- var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
-
- var TEXT_CONTENT_CHUNK_SIZE = 100;
- return this.transport.messageHandler.sendWithStream('GetTextContent', {
- pageIndex: this.pageNumber - 1,
- normalizeWhitespace: params.normalizeWhitespace === true,
- combineTextItems: params.disableCombineTextItems !== true
- }, {
- highWaterMark: TEXT_CONTENT_CHUNK_SIZE,
- size: function size(textContent) {
- return textContent.items.length;
- }
- });
- },
-
- getTextContent: function PDFPageProxy_getTextContent(params) {
- params = params || {};
- var readableStream = this.streamTextContent(params);
- return new Promise(function (resolve, reject) {
- function pump() {
- reader.read().then(function (_ref) {
- var _textContent$items;
-
- var value = _ref.value,
- done = _ref.done;
-
- if (done) {
- resolve(textContent);
- return;
- }
- Object.assign(textContent.styles, value.styles);
- (_textContent$items = textContent.items).push.apply(_textContent$items, _toConsumableArray(value.items));
- pump();
- }, reject);
- }
- var reader = readableStream.getReader();
- var textContent = {
- items: [],
- styles: Object.create(null)
- };
- pump();
- });
- },
- _destroy: function PDFPageProxy_destroy() {
- this.destroyed = true;
- this.transport.pageCache[this.pageIndex] = null;
- var waitOn = [];
- Object.keys(this.intentStates).forEach(function (intent) {
- if (intent === 'oplist') {
- return;
- }
- var intentState = this.intentStates[intent];
- intentState.renderTasks.forEach(function (renderTask) {
- var renderCompleted = renderTask.capability.promise.catch(function () {});
- waitOn.push(renderCompleted);
- renderTask.cancel();
- });
- }, this);
- this.objs.clear();
- this.annotationsPromise = null;
- this.pendingCleanup = false;
- return Promise.all(waitOn);
- },
- cleanup: function cleanup() {
- var resetStats = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
-
- this.pendingCleanup = true;
- this._tryCleanup(resetStats);
- },
- _tryCleanup: function _tryCleanup() {
- var resetStats = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
-
- if (!this.pendingCleanup || Object.keys(this.intentStates).some(function (intent) {
- var intentState = this.intentStates[intent];
- return intentState.renderTasks.length !== 0 || intentState.receivingOperatorList;
- }, this)) {
- return;
- }
- Object.keys(this.intentStates).forEach(function (intent) {
- delete this.intentStates[intent];
- }, this);
- this.objs.clear();
- this.annotationsPromise = null;
- if (resetStats && this._stats instanceof _dom_utils.StatTimer) {
- this._stats = new _dom_utils.StatTimer();
- }
- this.pendingCleanup = false;
- },
-
- _startRenderPage: function PDFPageProxy_startRenderPage(transparency, intent) {
- var intentState = this.intentStates[intent];
- if (intentState.displayReadyCapability) {
- intentState.displayReadyCapability.resolve(transparency);
- }
- },
- _renderPageChunk: function PDFPageProxy_renderPageChunk(operatorListChunk, intent) {
- var intentState = this.intentStates[intent];
- var i, ii;
- for (i = 0, ii = operatorListChunk.length; i < ii; i++) {
- intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]);
- intentState.operatorList.argsArray.push(operatorListChunk.argsArray[i]);
- }
- intentState.operatorList.lastChunk = operatorListChunk.lastChunk;
- for (i = 0; i < intentState.renderTasks.length; i++) {
- intentState.renderTasks[i].operatorListChanged();
- }
- if (operatorListChunk.lastChunk) {
- intentState.receivingOperatorList = false;
- this._tryCleanup();
- }
- },
- get stats() {
- return this._stats instanceof _dom_utils.StatTimer ? this._stats : null;
- }
- };
- return PDFPageProxy;
-}();
-
-var LoopbackPort = function () {
- function LoopbackPort() {
- var defer = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
-
- _classCallCheck(this, LoopbackPort);
-
- this._listeners = [];
- this._defer = defer;
- this._deferred = Promise.resolve(undefined);
- }
-
- _createClass(LoopbackPort, [{
- key: 'postMessage',
- value: function postMessage(obj, transfers) {
- var _this5 = this;
-
- function cloneValue(value) {
- if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) !== 'object' || value === null) {
- return value;
- }
- if (cloned.has(value)) {
- return cloned.get(value);
- }
- var result;
- var buffer;
- if ((buffer = value.buffer) && (0, _util.isArrayBuffer)(buffer)) {
- var transferable = transfers && transfers.includes(buffer);
- if (value === buffer) {
- result = value;
- } else if (transferable) {
- result = new value.constructor(buffer, value.byteOffset, value.byteLength);
- } else {
- result = new value.constructor(value);
- }
- cloned.set(value, result);
- return result;
- }
- result = Array.isArray(value) ? [] : {};
- cloned.set(value, result);
- for (var i in value) {
- var desc,
- p = value;
- while (!(desc = Object.getOwnPropertyDescriptor(p, i))) {
- p = Object.getPrototypeOf(p);
- }
- if (typeof desc.value === 'undefined' || typeof desc.value === 'function') {
- continue;
- }
- result[i] = cloneValue(desc.value);
- }
- return result;
- }
- if (!this._defer) {
- this._listeners.forEach(function (listener) {
- listener.call(this, { data: obj });
- }, this);
- return;
- }
- var cloned = new WeakMap();
- var e = { data: cloneValue(obj) };
- this._deferred.then(function () {
- _this5._listeners.forEach(function (listener) {
- listener.call(this, e);
- }, _this5);
- });
- }
- }, {
- key: 'addEventListener',
- value: function addEventListener(name, listener) {
- this._listeners.push(listener);
- }
- }, {
- key: 'removeEventListener',
- value: function removeEventListener(name, listener) {
- var i = this._listeners.indexOf(listener);
- this._listeners.splice(i, 1);
- }
- }, {
- key: 'terminate',
- value: function terminate() {
- this._listeners = [];
- }
- }]);
-
- return LoopbackPort;
-}();
-
-var PDFWorker = function PDFWorkerClosure() {
- var nextFakeWorkerId = 0;
- function getWorkerSrc() {
- if (_worker_options.GlobalWorkerOptions.workerSrc) {
- return _worker_options.GlobalWorkerOptions.workerSrc;
- }
- if (typeof fallbackWorkerSrc !== 'undefined') {
- return fallbackWorkerSrc;
- }
- throw new Error('No "GlobalWorkerOptions.workerSrc" specified.');
- }
- function getMainThreadWorkerMessageHandler() {
- try {
- if (typeof window !== 'undefined') {
- return window.pdfjsWorker && window.pdfjsWorker.WorkerMessageHandler;
- }
- } catch (ex) {}
- return null;
- }
- var fakeWorkerFilesLoadedCapability = void 0;
- function setupFakeWorkerGlobal() {
- if (fakeWorkerFilesLoadedCapability) {
- return fakeWorkerFilesLoadedCapability.promise;
- }
- fakeWorkerFilesLoadedCapability = (0, _util.createPromiseCapability)();
- var mainWorkerMessageHandler = getMainThreadWorkerMessageHandler();
- if (mainWorkerMessageHandler) {
- fakeWorkerFilesLoadedCapability.resolve(mainWorkerMessageHandler);
- return fakeWorkerFilesLoadedCapability.promise;
- }
- var loader = fakeWorkerFilesLoader || function () {
- return (0, _dom_utils.loadScript)(getWorkerSrc()).then(function () {
- return window.pdfjsWorker.WorkerMessageHandler;
- });
- };
- loader().then(fakeWorkerFilesLoadedCapability.resolve, fakeWorkerFilesLoadedCapability.reject);
- return fakeWorkerFilesLoadedCapability.promise;
- }
- function createCDNWrapper(url) {
- var wrapper = 'importScripts(\'' + url + '\');';
- return _util.URL.createObjectURL(new Blob([wrapper]));
- }
- var pdfWorkerPorts = new WeakMap();
- function PDFWorker() {
- var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref2$name = _ref2.name,
- name = _ref2$name === undefined ? null : _ref2$name,
- _ref2$port = _ref2.port,
- port = _ref2$port === undefined ? null : _ref2$port,
- _ref2$postMessageTran = _ref2.postMessageTransfers,
- postMessageTransfers = _ref2$postMessageTran === undefined ? true : _ref2$postMessageTran,
- _ref2$verbosity = _ref2.verbosity,
- verbosity = _ref2$verbosity === undefined ? (0, _util.getVerbosityLevel)() : _ref2$verbosity;
-
- if (port && pdfWorkerPorts.has(port)) {
- throw new Error('Cannot use more than one PDFWorker per port');
- }
- this.name = name;
- this.destroyed = false;
- this.postMessageTransfers = postMessageTransfers !== false;
- this.verbosity = verbosity;
- this._readyCapability = (0, _util.createPromiseCapability)();
- this._port = null;
- this._webWorker = null;
- this._messageHandler = null;
- if (port) {
- pdfWorkerPorts.set(port, this);
- this._initializeFromPort(port);
- return;
- }
- this._initialize();
- }
- PDFWorker.prototype = {
- get promise() {
- return this._readyCapability.promise;
- },
- get port() {
- return this._port;
- },
- get messageHandler() {
- return this._messageHandler;
- },
- _initializeFromPort: function PDFWorker_initializeFromPort(port) {
- this._port = port;
- this._messageHandler = new _message_handler.MessageHandler('main', 'worker', port);
- this._messageHandler.on('ready', function () {});
- this._readyCapability.resolve();
- },
- _initialize: function PDFWorker_initialize() {
- var _this6 = this;
-
- if (typeof Worker !== 'undefined' && !isWorkerDisabled && !getMainThreadWorkerMessageHandler()) {
- var workerSrc = getWorkerSrc();
- try {
- if (!(0, _util.isSameOrigin)(window.location.href, workerSrc)) {
- workerSrc = createCDNWrapper(new _util.URL(workerSrc, window.location).href);
- }
- var worker = new Worker(workerSrc);
- var messageHandler = new _message_handler.MessageHandler('main', 'worker', worker);
- var terminateEarly = function terminateEarly() {
- worker.removeEventListener('error', onWorkerError);
- messageHandler.destroy();
- worker.terminate();
- if (_this6.destroyed) {
- _this6._readyCapability.reject(new Error('Worker was destroyed'));
- } else {
- _this6._setupFakeWorker();
- }
- };
- var onWorkerError = function onWorkerError() {
- if (!_this6._webWorker) {
- terminateEarly();
- }
- };
- worker.addEventListener('error', onWorkerError);
- messageHandler.on('test', function (data) {
- worker.removeEventListener('error', onWorkerError);
- if (_this6.destroyed) {
- terminateEarly();
- return;
- }
- if (data && data.supportTypedArray) {
- _this6._messageHandler = messageHandler;
- _this6._port = worker;
- _this6._webWorker = worker;
- if (!data.supportTransfers) {
- _this6.postMessageTransfers = false;
- }
- _this6._readyCapability.resolve();
- messageHandler.send('configure', { verbosity: _this6.verbosity });
- } else {
- _this6._setupFakeWorker();
- messageHandler.destroy();
- worker.terminate();
- }
- });
- messageHandler.on('ready', function (data) {
- worker.removeEventListener('error', onWorkerError);
- if (_this6.destroyed) {
- terminateEarly();
- return;
- }
- try {
- sendTest();
- } catch (e) {
- _this6._setupFakeWorker();
- }
- });
- var sendTest = function sendTest() {
- var testObj = new Uint8Array([_this6.postMessageTransfers ? 255 : 0]);
- try {
- messageHandler.send('test', testObj, [testObj.buffer]);
- } catch (ex) {
- (0, _util.info)('Cannot use postMessage transfers');
- testObj[0] = 0;
- messageHandler.send('test', testObj);
- }
- };
- sendTest();
- return;
- } catch (e) {
- (0, _util.info)('The worker has been disabled.');
- }
- }
- this._setupFakeWorker();
- },
- _setupFakeWorker: function PDFWorker_setupFakeWorker() {
- var _this7 = this;
-
- if (!isWorkerDisabled) {
- (0, _util.warn)('Setting up fake worker.');
- isWorkerDisabled = true;
- }
- setupFakeWorkerGlobal().then(function (WorkerMessageHandler) {
- if (_this7.destroyed) {
- _this7._readyCapability.reject(new Error('Worker was destroyed'));
- return;
- }
- var port = new LoopbackPort();
- _this7._port = port;
- var id = 'fake' + nextFakeWorkerId++;
- var workerHandler = new _message_handler.MessageHandler(id + '_worker', id, port);
- WorkerMessageHandler.setup(workerHandler, port);
- var messageHandler = new _message_handler.MessageHandler(id, id + '_worker', port);
- _this7._messageHandler = messageHandler;
- _this7._readyCapability.resolve();
- }).catch(function (reason) {
- _this7._readyCapability.reject(new Error('Setting up fake worker failed: "' + reason.message + '".'));
- });
- },
- destroy: function PDFWorker_destroy() {
- this.destroyed = true;
- if (this._webWorker) {
- this._webWorker.terminate();
- this._webWorker = null;
- }
- pdfWorkerPorts.delete(this._port);
- this._port = null;
- if (this._messageHandler) {
- this._messageHandler.destroy();
- this._messageHandler = null;
- }
- }
- };
- PDFWorker.fromPort = function (params) {
- if (!params || !params.port) {
- throw new Error('PDFWorker.fromPort - invalid method signature.');
- }
- if (pdfWorkerPorts.has(params.port)) {
- return pdfWorkerPorts.get(params.port);
- }
- return new PDFWorker(params);
- };
- PDFWorker.getWorkerSrc = function () {
- return getWorkerSrc();
- };
- return PDFWorker;
-}();
-
-var WorkerTransport = function () {
- function WorkerTransport(messageHandler, loadingTask, networkStream, params) {
- _classCallCheck(this, WorkerTransport);
-
- this.messageHandler = messageHandler;
- this.loadingTask = loadingTask;
- this.commonObjs = new PDFObjects();
- this.fontLoader = new _font_loader.FontLoader(loadingTask.docId);
- this._params = params;
- this.CMapReaderFactory = new params.CMapReaderFactory({
- baseUrl: params.cMapUrl,
- isCompressed: params.cMapPacked
- });
- this.destroyed = false;
- this.destroyCapability = null;
- this._passwordCapability = null;
- this._networkStream = networkStream;
- this._fullReader = null;
- this._lastProgress = null;
- this.pageCache = [];
- this.pagePromises = [];
- this.downloadInfoCapability = (0, _util.createPromiseCapability)();
- this.setupMessageHandler();
- }
-
- _createClass(WorkerTransport, [{
- key: 'destroy',
- value: function destroy() {
- var _this8 = this;
-
- if (this.destroyCapability) {
- return this.destroyCapability.promise;
- }
- this.destroyed = true;
- this.destroyCapability = (0, _util.createPromiseCapability)();
- if (this._passwordCapability) {
- this._passwordCapability.reject(new Error('Worker was destroyed during onPassword callback'));
- }
- var waitOn = [];
- this.pageCache.forEach(function (page) {
- if (page) {
- waitOn.push(page._destroy());
- }
- });
- this.pageCache = [];
- this.pagePromises = [];
- var terminated = this.messageHandler.sendWithPromise('Terminate', null);
- waitOn.push(terminated);
- Promise.all(waitOn).then(function () {
- _this8.fontLoader.clear();
- if (_this8._networkStream) {
- _this8._networkStream.cancelAllRequests();
- }
- if (_this8.messageHandler) {
- _this8.messageHandler.destroy();
- _this8.messageHandler = null;
- }
- _this8.destroyCapability.resolve();
- }, this.destroyCapability.reject);
- return this.destroyCapability.promise;
- }
- }, {
- key: 'setupMessageHandler',
- value: function setupMessageHandler() {
- var messageHandler = this.messageHandler,
- loadingTask = this.loadingTask;
-
- messageHandler.on('GetReader', function (data, sink) {
- var _this9 = this;
-
- (0, _util.assert)(this._networkStream);
- this._fullReader = this._networkStream.getFullReader();
- this._fullReader.onProgress = function (evt) {
- _this9._lastProgress = {
- loaded: evt.loaded,
- total: evt.total
- };
- };
- sink.onPull = function () {
- _this9._fullReader.read().then(function (_ref3) {
- var value = _ref3.value,
- done = _ref3.done;
-
- if (done) {
- sink.close();
- return;
- }
- (0, _util.assert)((0, _util.isArrayBuffer)(value));
- sink.enqueue(new Uint8Array(value), 1, [value]);
- }).catch(function (reason) {
- sink.error(reason);
- });
- };
- sink.onCancel = function (reason) {
- _this9._fullReader.cancel(reason);
- };
- }, this);
- messageHandler.on('ReaderHeadersReady', function (data) {
- var _this10 = this;
-
- var headersCapability = (0, _util.createPromiseCapability)();
- var fullReader = this._fullReader;
- fullReader.headersReady.then(function () {
- if (!fullReader.isStreamingSupported || !fullReader.isRangeSupported) {
- if (_this10._lastProgress && loadingTask.onProgress) {
- loadingTask.onProgress(_this10._lastProgress);
- }
- fullReader.onProgress = function (evt) {
- if (loadingTask.onProgress) {
- loadingTask.onProgress({
- loaded: evt.loaded,
- total: evt.total
- });
- }
- };
- }
- headersCapability.resolve({
- isStreamingSupported: fullReader.isStreamingSupported,
- isRangeSupported: fullReader.isRangeSupported,
- contentLength: fullReader.contentLength
- });
- }, headersCapability.reject);
- return headersCapability.promise;
- }, this);
- messageHandler.on('GetRangeReader', function (data, sink) {
- (0, _util.assert)(this._networkStream);
- var rangeReader = this._networkStream.getRangeReader(data.begin, data.end);
- sink.onPull = function () {
- rangeReader.read().then(function (_ref4) {
- var value = _ref4.value,
- done = _ref4.done;
-
- if (done) {
- sink.close();
- return;
- }
- (0, _util.assert)((0, _util.isArrayBuffer)(value));
- sink.enqueue(new Uint8Array(value), 1, [value]);
- }).catch(function (reason) {
- sink.error(reason);
- });
- };
- sink.onCancel = function (reason) {
- rangeReader.cancel(reason);
- };
- }, this);
- messageHandler.on('GetDoc', function (_ref5) {
- var pdfInfo = _ref5.pdfInfo;
-
- this.numPages = pdfInfo.numPages;
- this.pdfDocument = new PDFDocumentProxy(pdfInfo, this, loadingTask);
- loadingTask._capability.resolve(this.pdfDocument);
- }, this);
- messageHandler.on('PasswordRequest', function (exception) {
- var _this11 = this;
-
- this._passwordCapability = (0, _util.createPromiseCapability)();
- if (loadingTask.onPassword) {
- var updatePassword = function updatePassword(password) {
- _this11._passwordCapability.resolve({ password: password });
- };
- try {
- loadingTask.onPassword(updatePassword, exception.code);
- } catch (ex) {
- this._passwordCapability.reject(ex);
- }
- } else {
- this._passwordCapability.reject(new _util.PasswordException(exception.message, exception.code));
- }
- return this._passwordCapability.promise;
- }, this);
- messageHandler.on('PasswordException', function (exception) {
- loadingTask._capability.reject(new _util.PasswordException(exception.message, exception.code));
- }, this);
- messageHandler.on('InvalidPDF', function (exception) {
- loadingTask._capability.reject(new _util.InvalidPDFException(exception.message));
- }, this);
- messageHandler.on('MissingPDF', function (exception) {
- loadingTask._capability.reject(new _util.MissingPDFException(exception.message));
- }, this);
- messageHandler.on('UnexpectedResponse', function (exception) {
- loadingTask._capability.reject(new _util.UnexpectedResponseException(exception.message, exception.status));
- }, this);
- messageHandler.on('UnknownError', function (exception) {
- loadingTask._capability.reject(new _util.UnknownErrorException(exception.message, exception.details));
- }, this);
- messageHandler.on('DataLoaded', function (data) {
- if (loadingTask.onProgress) {
- loadingTask.onProgress({
- loaded: data.length,
- total: data.length
- });
- }
- this.downloadInfoCapability.resolve(data);
- }, this);
- messageHandler.on('StartRenderPage', function (data) {
- if (this.destroyed) {
- return;
- }
- var page = this.pageCache[data.pageIndex];
- page._stats.timeEnd('Page Request');
- page._startRenderPage(data.transparency, data.intent);
- }, this);
- messageHandler.on('RenderPageChunk', function (data) {
- if (this.destroyed) {
- return;
- }
- var page = this.pageCache[data.pageIndex];
- page._renderPageChunk(data.operatorList, data.intent);
- }, this);
- messageHandler.on('commonobj', function (data) {
- var _this12 = this;
-
- if (this.destroyed) {
- return;
- }
-
- var _data = _slicedToArray(data, 3),
- id = _data[0],
- type = _data[1],
- exportedData = _data[2];
-
- if (this.commonObjs.hasData(id)) {
- return;
- }
- switch (type) {
- case 'Font':
- var params = this._params;
- if ('error' in exportedData) {
- var exportedError = exportedData.error;
- (0, _util.warn)('Error during font loading: ' + exportedError);
- this.commonObjs.resolve(id, exportedError);
- break;
- }
- var fontRegistry = null;
- if (params.pdfBug && _global_scope2.default.FontInspector && _global_scope2.default.FontInspector.enabled) {
- fontRegistry = {
- registerFont: function registerFont(font, url) {
- _global_scope2.default['FontInspector'].fontAdded(font, url);
- }
- };
- }
- var font = new _font_loader.FontFaceObject(exportedData, {
- isEvalSupported: params.isEvalSupported,
- disableFontFace: params.disableFontFace,
- ignoreErrors: params.ignoreErrors,
- onUnsupportedFeature: this._onUnsupportedFeature.bind(this),
- fontRegistry: fontRegistry
- });
- var fontReady = function fontReady(fontObjs) {
- _this12.commonObjs.resolve(id, font);
- };
- this.fontLoader.bind([font], fontReady);
- break;
- case 'FontPath':
- this.commonObjs.resolve(id, exportedData);
- break;
- default:
- throw new Error('Got unknown common object type ' + type);
- }
- }, this);
- messageHandler.on('obj', function (data) {
- if (this.destroyed) {
- return;
- }
-
- var _data2 = _slicedToArray(data, 4),
- id = _data2[0],
- pageIndex = _data2[1],
- type = _data2[2],
- imageData = _data2[3];
-
- var pageProxy = this.pageCache[pageIndex];
- if (pageProxy.objs.hasData(id)) {
- return;
- }
- switch (type) {
- case 'JpegStream':
- return new Promise(function (resolve, reject) {
- var img = new Image();
- img.onload = function () {
- resolve(img);
- };
- img.onerror = function () {
- reject(new Error('Error during JPEG image loading'));
- };
- img.src = imageData;
- }).then(function (img) {
- pageProxy.objs.resolve(id, img);
- });
- case 'Image':
- pageProxy.objs.resolve(id, imageData);
- var MAX_IMAGE_SIZE_TO_STORE = 8000000;
- if (imageData && 'data' in imageData && imageData.data.length > MAX_IMAGE_SIZE_TO_STORE) {
- pageProxy.cleanupAfterRender = true;
- }
- break;
- default:
- throw new Error('Got unknown object type ' + type);
- }
- }, this);
- messageHandler.on('DocProgress', function (data) {
- if (this.destroyed) {
- return;
- }
- if (loadingTask.onProgress) {
- loadingTask.onProgress({
- loaded: data.loaded,
- total: data.total
- });
- }
- }, this);
- messageHandler.on('PageError', function (data) {
- if (this.destroyed) {
- return;
- }
- var page = this.pageCache[data.pageNum - 1];
- var intentState = page.intentStates[data.intent];
- if (intentState.displayReadyCapability) {
- intentState.displayReadyCapability.reject(data.error);
- } else {
- throw new Error(data.error);
- }
- if (intentState.operatorList) {
- intentState.operatorList.lastChunk = true;
- for (var i = 0; i < intentState.renderTasks.length; i++) {
- intentState.renderTasks[i].operatorListChanged();
- }
- }
- }, this);
- messageHandler.on('UnsupportedFeature', this._onUnsupportedFeature, this);
- messageHandler.on('JpegDecode', function (data) {
- if (this.destroyed) {
- return Promise.reject(new Error('Worker was destroyed'));
- }
- if (typeof document === 'undefined') {
- return Promise.reject(new Error('"document" is not defined.'));
- }
-
- var _data3 = _slicedToArray(data, 2),
- imageUrl = _data3[0],
- components = _data3[1];
-
- if (components !== 3 && components !== 1) {
- return Promise.reject(new Error('Only 3 components or 1 component can be returned'));
- }
- return new Promise(function (resolve, reject) {
- var img = new Image();
- img.onload = function () {
- var width = img.width;
- var height = img.height;
- var size = width * height;
- var rgbaLength = size * 4;
- var buf = new Uint8ClampedArray(size * components);
- var tmpCanvas = document.createElement('canvas');
- tmpCanvas.width = width;
- tmpCanvas.height = height;
- var tmpCtx = tmpCanvas.getContext('2d');
- tmpCtx.drawImage(img, 0, 0);
- var data = tmpCtx.getImageData(0, 0, width, height).data;
- if (components === 3) {
- for (var i = 0, j = 0; i < rgbaLength; i += 4, j += 3) {
- buf[j] = data[i];
- buf[j + 1] = data[i + 1];
- buf[j + 2] = data[i + 2];
- }
- } else if (components === 1) {
- for (var _i = 0, _j = 0; _i < rgbaLength; _i += 4, _j++) {
- buf[_j] = data[_i];
- }
- }
- resolve({
- data: buf,
- width: width,
- height: height
- });
- };
- img.onerror = function () {
- reject(new Error('JpegDecode failed to load image'));
- };
- img.src = imageUrl;
- });
- }, this);
- messageHandler.on('FetchBuiltInCMap', function (data) {
- if (this.destroyed) {
- return Promise.reject(new Error('Worker was destroyed'));
- }
- return this.CMapReaderFactory.fetch({ name: data.name });
- }, this);
- }
- }, {
- key: '_onUnsupportedFeature',
- value: function _onUnsupportedFeature(_ref6) {
- var featureId = _ref6.featureId;
-
- if (this.destroyed) {
- return;
- }
- if (this.loadingTask.onUnsupportedFeature) {
- this.loadingTask.onUnsupportedFeature(featureId);
- }
- }
- }, {
- key: 'getData',
- value: function getData() {
- return this.messageHandler.sendWithPromise('GetData', null);
- }
- }, {
- key: 'getPage',
- value: function getPage(pageNumber) {
- var _this13 = this;
-
- if (!Number.isInteger(pageNumber) || pageNumber <= 0 || pageNumber > this.numPages) {
- return Promise.reject(new Error('Invalid page request'));
- }
- var pageIndex = pageNumber - 1;
- if (pageIndex in this.pagePromises) {
- return this.pagePromises[pageIndex];
- }
- var promise = this.messageHandler.sendWithPromise('GetPage', { pageIndex: pageIndex }).then(function (pageInfo) {
- if (_this13.destroyed) {
- throw new Error('Transport destroyed');
- }
- var page = new PDFPageProxy(pageIndex, pageInfo, _this13, _this13._params.pdfBug);
- _this13.pageCache[pageIndex] = page;
- return page;
- });
- this.pagePromises[pageIndex] = promise;
- return promise;
- }
- }, {
- key: 'getPageIndex',
- value: function getPageIndex(ref) {
- return this.messageHandler.sendWithPromise('GetPageIndex', { ref: ref }).catch(function (reason) {
- return Promise.reject(new Error(reason));
- });
- }
- }, {
- key: 'getAnnotations',
- value: function getAnnotations(pageIndex, intent) {
- return this.messageHandler.sendWithPromise('GetAnnotations', {
- pageIndex: pageIndex,
- intent: intent
- });
- }
- }, {
- key: 'getDestinations',
- value: function getDestinations() {
- return this.messageHandler.sendWithPromise('GetDestinations', null);
- }
- }, {
- key: 'getDestination',
- value: function getDestination(id) {
- if (typeof id !== 'string') {
- return Promise.reject(new Error('Invalid destination request.'));
- }
- return this.messageHandler.sendWithPromise('GetDestination', { id: id });
- }
- }, {
- key: 'getPageLabels',
- value: function getPageLabels() {
- return this.messageHandler.sendWithPromise('GetPageLabels', null);
- }
- }, {
- key: 'getPageMode',
- value: function getPageMode() {
- return this.messageHandler.sendWithPromise('GetPageMode', null);
- }
- }, {
- key: 'getAttachments',
- value: function getAttachments() {
- return this.messageHandler.sendWithPromise('GetAttachments', null);
- }
- }, {
- key: 'getJavaScript',
- value: function getJavaScript() {
- return this.messageHandler.sendWithPromise('GetJavaScript', null);
- }
- }, {
- key: 'getOutline',
- value: function getOutline() {
- return this.messageHandler.sendWithPromise('GetOutline', null);
- }
- }, {
- key: 'getPermissions',
- value: function getPermissions() {
- return this.messageHandler.sendWithPromise('GetPermissions', null);
- }
- }, {
- key: 'getMetadata',
- value: function getMetadata() {
- var _this14 = this;
-
- return this.messageHandler.sendWithPromise('GetMetadata', null).then(function (results) {
- return {
- info: results[0],
- metadata: results[1] ? new _metadata.Metadata(results[1]) : null,
- contentDispositionFilename: _this14._fullReader ? _this14._fullReader.filename : null
- };
- });
- }
- }, {
- key: 'getStats',
- value: function getStats() {
- return this.messageHandler.sendWithPromise('GetStats', null);
- }
- }, {
- key: 'startCleanup',
- value: function startCleanup() {
- var _this15 = this;
-
- this.messageHandler.sendWithPromise('Cleanup', null).then(function () {
- for (var i = 0, ii = _this15.pageCache.length; i < ii; i++) {
- var page = _this15.pageCache[i];
- if (page) {
- page.cleanup();
- }
- }
- _this15.commonObjs.clear();
- _this15.fontLoader.clear();
- });
- }
- }, {
- key: 'loadingParams',
- get: function get() {
- var params = this._params;
- return (0, _util.shadow)(this, 'loadingParams', {
- disableAutoFetch: params.disableAutoFetch,
- disableCreateObjectURL: params.disableCreateObjectURL,
- disableFontFace: params.disableFontFace,
- nativeImageDecoderSupport: params.nativeImageDecoderSupport
- });
- }
- }]);
-
- return WorkerTransport;
-}();
-
-var PDFObjects = function PDFObjectsClosure() {
- function PDFObjects() {
- this.objs = Object.create(null);
- }
- PDFObjects.prototype = {
- ensureObj: function PDFObjects_ensureObj(objId) {
- if (this.objs[objId]) {
- return this.objs[objId];
- }
- var obj = {
- capability: (0, _util.createPromiseCapability)(),
- data: null,
- resolved: false
- };
- this.objs[objId] = obj;
- return obj;
- },
- get: function PDFObjects_get(objId, callback) {
- if (callback) {
- this.ensureObj(objId).capability.promise.then(callback);
- return null;
- }
- var obj = this.objs[objId];
- if (!obj || !obj.resolved) {
- throw new Error('Requesting object that isn\'t resolved yet ' + objId);
- }
- return obj.data;
- },
- resolve: function PDFObjects_resolve(objId, data) {
- var obj = this.ensureObj(objId);
- obj.resolved = true;
- obj.data = data;
- obj.capability.resolve(data);
- },
- isResolved: function PDFObjects_isResolved(objId) {
- var objs = this.objs;
- if (!objs[objId]) {
- return false;
- }
- return objs[objId].resolved;
- },
- hasData: function PDFObjects_hasData(objId) {
- return this.isResolved(objId);
- },
- getData: function PDFObjects_getData(objId) {
- var objs = this.objs;
- if (!objs[objId] || !objs[objId].resolved) {
- return null;
- }
- return objs[objId].data;
- },
- clear: function PDFObjects_clear() {
- this.objs = Object.create(null);
- }
- };
- return PDFObjects;
-}();
-var RenderTask = function RenderTaskClosure() {
- function RenderTask(internalRenderTask) {
- this._internalRenderTask = internalRenderTask;
- this.onContinue = null;
- }
- RenderTask.prototype = {
- get promise() {
- return this._internalRenderTask.capability.promise;
- },
- cancel: function RenderTask_cancel() {
- this._internalRenderTask.cancel();
- },
- then: function RenderTask_then(onFulfilled, onRejected) {
- return this.promise.then.apply(this.promise, arguments);
- }
- };
- return RenderTask;
-}();
-var InternalRenderTask = function InternalRenderTaskClosure() {
- var canvasInRendering = new WeakMap();
- function InternalRenderTask(callback, params, objs, commonObjs, operatorList, pageNumber, canvasFactory, webGLContext) {
- var pdfBug = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : false;
-
- this.callback = callback;
- this.params = params;
- this.objs = objs;
- this.commonObjs = commonObjs;
- this.operatorListIdx = null;
- this.operatorList = operatorList;
- this.pageNumber = pageNumber;
- this.canvasFactory = canvasFactory;
- this.webGLContext = webGLContext;
- this._pdfBug = pdfBug;
- this.running = false;
- this.graphicsReadyCallback = null;
- this.graphicsReady = false;
- this.useRequestAnimationFrame = false;
- this.cancelled = false;
- this.capability = (0, _util.createPromiseCapability)();
- this.task = new RenderTask(this);
- this._continueBound = this._continue.bind(this);
- this._scheduleNextBound = this._scheduleNext.bind(this);
- this._nextBound = this._next.bind(this);
- this._canvas = params.canvasContext.canvas;
- }
- InternalRenderTask.prototype = {
- initializeGraphics: function initializeGraphics(transparency) {
- if (this.cancelled) {
- return;
- }
- if (this._canvas) {
- if (canvasInRendering.has(this._canvas)) {
- throw new Error('Cannot use the same canvas during multiple render() operations. ' + 'Use different canvas or ensure previous operations were ' + 'cancelled or completed.');
- }
- canvasInRendering.set(this._canvas, this);
- }
- if (this._pdfBug && _global_scope2.default.StepperManager && _global_scope2.default.StepperManager.enabled) {
- this.stepper = _global_scope2.default.StepperManager.create(this.pageNumber - 1);
- this.stepper.init(this.operatorList);
- this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint();
- }
- var params = this.params;
- this.gfx = new _canvas.CanvasGraphics(params.canvasContext, this.commonObjs, this.objs, this.canvasFactory, this.webGLContext, params.imageLayer);
- this.gfx.beginDrawing({
- transform: params.transform,
- viewport: params.viewport,
- transparency: transparency,
- background: params.background
- });
- this.operatorListIdx = 0;
- this.graphicsReady = true;
- if (this.graphicsReadyCallback) {
- this.graphicsReadyCallback();
- }
- },
-
- cancel: function InternalRenderTask_cancel() {
- this.running = false;
- this.cancelled = true;
- if (this._canvas) {
- canvasInRendering.delete(this._canvas);
- }
- this.callback(new _dom_utils.RenderingCancelledException('Rendering cancelled, page ' + this.pageNumber, 'canvas'));
- },
- operatorListChanged: function InternalRenderTask_operatorListChanged() {
- if (!this.graphicsReady) {
- if (!this.graphicsReadyCallback) {
- this.graphicsReadyCallback = this._continueBound;
- }
- return;
- }
- if (this.stepper) {
- this.stepper.updateOperatorList(this.operatorList);
- }
- if (this.running) {
- return;
- }
- this._continue();
- },
- _continue: function InternalRenderTask__continue() {
- this.running = true;
- if (this.cancelled) {
- return;
- }
- if (this.task.onContinue) {
- this.task.onContinue(this._scheduleNextBound);
- } else {
- this._scheduleNext();
- }
- },
- _scheduleNext: function InternalRenderTask__scheduleNext() {
- var _this16 = this;
-
- if (this.useRequestAnimationFrame && typeof window !== 'undefined') {
- window.requestAnimationFrame(function () {
- _this16._nextBound().catch(_this16.callback);
- });
- } else {
- Promise.resolve().then(this._nextBound).catch(this.callback);
- }
- },
- _next: function InternalRenderTask__next() {
- var _this17 = this;
-
- return new Promise(function () {
- if (_this17.cancelled) {
- return;
- }
- _this17.operatorListIdx = _this17.gfx.executeOperatorList(_this17.operatorList, _this17.operatorListIdx, _this17._continueBound, _this17.stepper);
- if (_this17.operatorListIdx === _this17.operatorList.argsArray.length) {
- _this17.running = false;
- if (_this17.operatorList.lastChunk) {
- _this17.gfx.endDrawing();
- if (_this17._canvas) {
- canvasInRendering.delete(_this17._canvas);
- }
- _this17.callback();
- }
- }
- });
- }
- };
- return InternalRenderTask;
-}();
-var version, build;
-{
- exports.version = version = '2.0.943';
- exports.build = build = 'dc98bf76';
-}
-exports.getDocument = getDocument;
-exports.LoopbackPort = LoopbackPort;
-exports.PDFDataRangeTransport = PDFDataRangeTransport;
-exports.PDFWorker = PDFWorker;
-exports.PDFDocumentProxy = PDFDocumentProxy;
-exports.PDFPageProxy = PDFPageProxy;
-exports.setPDFNetworkStreamFactory = setPDFNetworkStreamFactory;
-exports.version = version;
-exports.build = build;
-
-/***/ }),
-/* 130 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.loadScript = exports.DummyStatTimer = exports.StatTimer = exports.DOMSVGFactory = exports.DOMCMapReaderFactory = exports.DOMCanvasFactory = exports.DEFAULT_LINK_REL = exports.LinkTarget = exports.getFilenameFromUrl = exports.addLinkAttributes = exports.RenderingCancelledException = exports.PageViewport = undefined;
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-var _util = __w_pdfjs_require__(1);
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-var DEFAULT_LINK_REL = 'noopener noreferrer nofollow';
-var SVG_NS = 'http://www.w3.org/2000/svg';
-
-var DOMCanvasFactory = function () {
- function DOMCanvasFactory() {
- _classCallCheck(this, DOMCanvasFactory);
- }
-
- _createClass(DOMCanvasFactory, [{
- key: 'create',
- value: function create(width, height) {
- if (width <= 0 || height <= 0) {
- throw new Error('invalid canvas size');
- }
- var canvas = document.createElement('canvas');
- var context = canvas.getContext('2d');
- canvas.width = width;
- canvas.height = height;
- return {
- canvas: canvas,
- context: context
- };
- }
- }, {
- key: 'reset',
- value: function reset(canvasAndContext, width, height) {
- if (!canvasAndContext.canvas) {
- throw new Error('canvas is not specified');
- }
- if (width <= 0 || height <= 0) {
- throw new Error('invalid canvas size');
- }
- canvasAndContext.canvas.width = width;
- canvasAndContext.canvas.height = height;
- }
- }, {
- key: 'destroy',
- value: function destroy(canvasAndContext) {
- if (!canvasAndContext.canvas) {
- throw new Error('canvas is not specified');
- }
- canvasAndContext.canvas.width = 0;
- canvasAndContext.canvas.height = 0;
- canvasAndContext.canvas = null;
- canvasAndContext.context = null;
- }
- }]);
-
- return DOMCanvasFactory;
-}();
-
-var DOMCMapReaderFactory = function () {
- function DOMCMapReaderFactory(_ref) {
- var _ref$baseUrl = _ref.baseUrl,
- baseUrl = _ref$baseUrl === undefined ? null : _ref$baseUrl,
- _ref$isCompressed = _ref.isCompressed,
- isCompressed = _ref$isCompressed === undefined ? false : _ref$isCompressed;
-
- _classCallCheck(this, DOMCMapReaderFactory);
-
- this.baseUrl = baseUrl;
- this.isCompressed = isCompressed;
- }
-
- _createClass(DOMCMapReaderFactory, [{
- key: 'fetch',
- value: function fetch(_ref2) {
- var _this = this;
-
- var name = _ref2.name;
-
- if (!this.baseUrl) {
- return Promise.reject(new Error('The CMap "baseUrl" parameter must be specified, ensure that ' + 'the "cMapUrl" and "cMapPacked" API parameters are provided.'));
- }
- if (!name) {
- return Promise.reject(new Error('CMap name must be specified.'));
- }
- return new Promise(function (resolve, reject) {
- var url = _this.baseUrl + name + (_this.isCompressed ? '.bcmap' : '');
- var request = new XMLHttpRequest();
- request.open('GET', url, true);
- if (_this.isCompressed) {
- request.responseType = 'arraybuffer';
- }
- request.onreadystatechange = function () {
- if (request.readyState !== XMLHttpRequest.DONE) {
- return;
- }
- if (request.status === 200 || request.status === 0) {
- var data = void 0;
- if (_this.isCompressed && request.response) {
- data = new Uint8Array(request.response);
- } else if (!_this.isCompressed && request.responseText) {
- data = (0, _util.stringToBytes)(request.responseText);
- }
- if (data) {
- resolve({
- cMapData: data,
- compressionType: _this.isCompressed ? _util.CMapCompressionType.BINARY : _util.CMapCompressionType.NONE
- });
- return;
- }
- }
- reject(new Error('Unable to load ' + (_this.isCompressed ? 'binary ' : '') + 'CMap at: ' + url));
- };
- request.send(null);
- });
- }
- }]);
-
- return DOMCMapReaderFactory;
-}();
-
-var DOMSVGFactory = function () {
- function DOMSVGFactory() {
- _classCallCheck(this, DOMSVGFactory);
- }
-
- _createClass(DOMSVGFactory, [{
- key: 'create',
- value: function create(width, height) {
- (0, _util.assert)(width > 0 && height > 0, 'Invalid SVG dimensions');
- var svg = document.createElementNS(SVG_NS, 'svg:svg');
- svg.setAttribute('version', '1.1');
- svg.setAttribute('width', width + 'px');
- svg.setAttribute('height', height + 'px');
- svg.setAttribute('preserveAspectRatio', 'none');
- svg.setAttribute('viewBox', '0 0 ' + width + ' ' + height);
- return svg;
- }
- }, {
- key: 'createElement',
- value: function createElement(type) {
- (0, _util.assert)(typeof type === 'string', 'Invalid SVG element type');
- return document.createElementNS(SVG_NS, type);
- }
- }]);
-
- return DOMSVGFactory;
-}();
-
-var PageViewport = function () {
- function PageViewport(_ref3) {
- var viewBox = _ref3.viewBox,
- scale = _ref3.scale,
- rotation = _ref3.rotation,
- _ref3$offsetX = _ref3.offsetX,
- offsetX = _ref3$offsetX === undefined ? 0 : _ref3$offsetX,
- _ref3$offsetY = _ref3.offsetY,
- offsetY = _ref3$offsetY === undefined ? 0 : _ref3$offsetY,
- _ref3$dontFlip = _ref3.dontFlip,
- dontFlip = _ref3$dontFlip === undefined ? false : _ref3$dontFlip;
-
- _classCallCheck(this, PageViewport);
-
- this.viewBox = viewBox;
- this.scale = scale;
- this.rotation = rotation;
- this.offsetX = offsetX;
- this.offsetY = offsetY;
- var centerX = (viewBox[2] + viewBox[0]) / 2;
- var centerY = (viewBox[3] + viewBox[1]) / 2;
- var rotateA = void 0,
- rotateB = void 0,
- rotateC = void 0,
- rotateD = void 0;
- rotation = rotation % 360;
- rotation = rotation < 0 ? rotation + 360 : rotation;
- switch (rotation) {
- case 180:
- rotateA = -1;
- rotateB = 0;
- rotateC = 0;
- rotateD = 1;
- break;
- case 90:
- rotateA = 0;
- rotateB = 1;
- rotateC = 1;
- rotateD = 0;
- break;
- case 270:
- rotateA = 0;
- rotateB = -1;
- rotateC = -1;
- rotateD = 0;
- break;
- default:
- rotateA = 1;
- rotateB = 0;
- rotateC = 0;
- rotateD = -1;
- break;
- }
- if (dontFlip) {
- rotateC = -rotateC;
- rotateD = -rotateD;
- }
- var offsetCanvasX = void 0,
- offsetCanvasY = void 0;
- var width = void 0,
- height = void 0;
- if (rotateA === 0) {
- offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
- offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
- width = Math.abs(viewBox[3] - viewBox[1]) * scale;
- height = Math.abs(viewBox[2] - viewBox[0]) * scale;
- } else {
- offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
- offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
- width = Math.abs(viewBox[2] - viewBox[0]) * scale;
- height = Math.abs(viewBox[3] - viewBox[1]) * scale;
- }
- this.transform = [rotateA * scale, rotateB * scale, rotateC * scale, rotateD * scale, offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY];
- this.width = width;
- this.height = height;
- }
-
- _createClass(PageViewport, [{
- key: 'clone',
- value: function clone() {
- var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref4$scale = _ref4.scale,
- scale = _ref4$scale === undefined ? this.scale : _ref4$scale,
- _ref4$rotation = _ref4.rotation,
- rotation = _ref4$rotation === undefined ? this.rotation : _ref4$rotation,
- _ref4$dontFlip = _ref4.dontFlip,
- dontFlip = _ref4$dontFlip === undefined ? false : _ref4$dontFlip;
-
- return new PageViewport({
- viewBox: this.viewBox.slice(),
- scale: scale,
- rotation: rotation,
- offsetX: this.offsetX,
- offsetY: this.offsetY,
- dontFlip: dontFlip
- });
- }
- }, {
- key: 'convertToViewportPoint',
- value: function convertToViewportPoint(x, y) {
- return _util.Util.applyTransform([x, y], this.transform);
- }
- }, {
- key: 'convertToViewportRectangle',
- value: function convertToViewportRectangle(rect) {
- var tl = _util.Util.applyTransform([rect[0], rect[1]], this.transform);
- var br = _util.Util.applyTransform([rect[2], rect[3]], this.transform);
- return [tl[0], tl[1], br[0], br[1]];
- }
- }, {
- key: 'convertToPdfPoint',
- value: function convertToPdfPoint(x, y) {
- return _util.Util.applyInverseTransform([x, y], this.transform);
- }
- }]);
-
- return PageViewport;
-}();
-
-var RenderingCancelledException = function RenderingCancelledException() {
- function RenderingCancelledException(msg, type) {
- this.message = msg;
- this.type = type;
- }
- RenderingCancelledException.prototype = new Error();
- RenderingCancelledException.prototype.name = 'RenderingCancelledException';
- RenderingCancelledException.constructor = RenderingCancelledException;
- return RenderingCancelledException;
-}();
-var LinkTarget = {
- NONE: 0,
- SELF: 1,
- BLANK: 2,
- PARENT: 3,
- TOP: 4
-};
-var LinkTargetStringMap = ['', '_self', '_blank', '_parent', '_top'];
-function addLinkAttributes(link) {
- var _ref5 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
- url = _ref5.url,
- target = _ref5.target,
- rel = _ref5.rel;
-
- link.href = link.title = url ? (0, _util.removeNullCharacters)(url) : '';
- if (url) {
- var LinkTargetValues = Object.values(LinkTarget);
- var targetIndex = LinkTargetValues.includes(target) ? target : LinkTarget.NONE;
- link.target = LinkTargetStringMap[targetIndex];
- link.rel = typeof rel === 'string' ? rel : DEFAULT_LINK_REL;
- }
-}
-function getFilenameFromUrl(url) {
- var anchor = url.indexOf('#');
- var query = url.indexOf('?');
- var end = Math.min(anchor > 0 ? anchor : url.length, query > 0 ? query : url.length);
- return url.substring(url.lastIndexOf('/', end) + 1, end);
-}
-
-var StatTimer = function () {
- function StatTimer() {
- var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
-
- _classCallCheck(this, StatTimer);
-
- this.enabled = !!enable;
- this.started = Object.create(null);
- this.times = [];
- }
-
- _createClass(StatTimer, [{
- key: 'time',
- value: function time(name) {
- if (!this.enabled) {
- return;
- }
- if (name in this.started) {
- (0, _util.warn)('Timer is already running for ' + name);
- }
- this.started[name] = Date.now();
- }
- }, {
- key: 'timeEnd',
- value: function timeEnd(name) {
- if (!this.enabled) {
- return;
- }
- if (!(name in this.started)) {
- (0, _util.warn)('Timer has not been started for ' + name);
- }
- this.times.push({
- 'name': name,
- 'start': this.started[name],
- 'end': Date.now()
- });
- delete this.started[name];
- }
- }, {
- key: 'toString',
- value: function toString() {
- var times = this.times;
- var out = '',
- longest = 0;
- for (var i = 0, ii = times.length; i < ii; ++i) {
- var name = times[i]['name'];
- if (name.length > longest) {
- longest = name.length;
- }
- }
- for (var _i = 0, _ii = times.length; _i < _ii; ++_i) {
- var span = times[_i];
- var duration = span.end - span.start;
- out += span['name'].padEnd(longest) + ' ' + duration + 'ms\n';
- }
- return out;
- }
- }]);
-
- return StatTimer;
-}();
-
-var DummyStatTimer = function () {
- function DummyStatTimer() {
- _classCallCheck(this, DummyStatTimer);
-
- (0, _util.unreachable)('Cannot initialize DummyStatTimer.');
- }
-
- _createClass(DummyStatTimer, null, [{
- key: 'time',
- value: function time(name) {}
- }, {
- key: 'timeEnd',
- value: function timeEnd(name) {}
- }, {
- key: 'toString',
- value: function toString() {
- return '';
- }
- }]);
-
- return DummyStatTimer;
-}();
-
-function loadScript(src) {
- return new Promise(function (resolve, reject) {
- var script = document.createElement('script');
- script.src = src;
- script.onload = resolve;
- script.onerror = function () {
- reject(new Error('Cannot load script at: ' + script.src));
- };
- (document.head || document.documentElement).appendChild(script);
- });
-}
-exports.PageViewport = PageViewport;
-exports.RenderingCancelledException = RenderingCancelledException;
-exports.addLinkAttributes = addLinkAttributes;
-exports.getFilenameFromUrl = getFilenameFromUrl;
-exports.LinkTarget = LinkTarget;
-exports.DEFAULT_LINK_REL = DEFAULT_LINK_REL;
-exports.DOMCanvasFactory = DOMCanvasFactory;
-exports.DOMCMapReaderFactory = DOMCMapReaderFactory;
-exports.DOMSVGFactory = DOMSVGFactory;
-exports.StatTimer = StatTimer;
-exports.DummyStatTimer = DummyStatTimer;
-exports.loadScript = loadScript;
-
-/***/ }),
-/* 131 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.FontLoader = exports.FontFaceObject = undefined;
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-var _util = __w_pdfjs_require__(1);
-
-function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
-
-function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-var BaseFontLoader = function () {
- function BaseFontLoader(docId) {
- _classCallCheck(this, BaseFontLoader);
-
- if (this.constructor === BaseFontLoader) {
- (0, _util.unreachable)('Cannot initialize BaseFontLoader.');
- }
- this.docId = docId;
- this.nativeFontFaces = [];
- this.styleElement = null;
- this.loadingContext = {
- requests: [],
- nextRequestId: 0
- };
- }
-
- _createClass(BaseFontLoader, [{
- key: 'addNativeFontFace',
- value: function addNativeFontFace(nativeFontFace) {
- this.nativeFontFaces.push(nativeFontFace);
- document.fonts.add(nativeFontFace);
- }
- }, {
- key: 'insertRule',
- value: function insertRule(rule) {
- var styleElement = this.styleElement;
- if (!styleElement) {
- styleElement = this.styleElement = document.createElement('style');
- styleElement.id = 'PDFJS_FONT_STYLE_TAG_' + this.docId;
- document.documentElement.getElementsByTagName('head')[0].appendChild(styleElement);
- }
- var styleSheet = styleElement.sheet;
- styleSheet.insertRule(rule, styleSheet.cssRules.length);
- }
- }, {
- key: 'clear',
- value: function clear() {
- this.nativeFontFaces.forEach(function (nativeFontFace) {
- document.fonts.delete(nativeFontFace);
- });
- this.nativeFontFaces.length = 0;
- if (this.styleElement) {
- this.styleElement.remove();
- this.styleElement = null;
- }
- }
- }, {
- key: 'bind',
- value: function bind(fonts, callback) {
- var rules = [];
- var fontsToLoad = [];
- var fontLoadPromises = [];
- var getNativeFontPromise = function getNativeFontPromise(nativeFontFace) {
- return nativeFontFace.loaded.catch(function (reason) {
- (0, _util.warn)('Failed to load font "' + nativeFontFace.family + '": ' + reason);
- });
- };
- var _iteratorNormalCompletion = true;
- var _didIteratorError = false;
- var _iteratorError = undefined;
-
- try {
- for (var _iterator = fonts[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
- var font = _step.value;
-
- if (font.attached || font.missingFile) {
- continue;
- }
- font.attached = true;
- if (this.isFontLoadingAPISupported) {
- var nativeFontFace = font.createNativeFontFace();
- if (nativeFontFace) {
- this.addNativeFontFace(nativeFontFace);
- fontLoadPromises.push(getNativeFontPromise(nativeFontFace));
- }
- } else {
- var rule = font.createFontFaceRule();
- if (rule) {
- this.insertRule(rule);
- rules.push(rule);
- fontsToLoad.push(font);
- }
- }
- }
- } catch (err) {
- _didIteratorError = true;
- _iteratorError = err;
- } finally {
- try {
- if (!_iteratorNormalCompletion && _iterator.return) {
- _iterator.return();
- }
- } finally {
- if (_didIteratorError) {
- throw _iteratorError;
- }
- }
- }
-
- var request = this._queueLoadingCallback(callback);
- if (this.isFontLoadingAPISupported) {
- Promise.all(fontLoadPromises).then(request.complete);
- } else if (rules.length > 0 && !this.isSyncFontLoadingSupported) {
- this._prepareFontLoadEvent(rules, fontsToLoad, request);
- } else {
- request.complete();
- }
- }
- }, {
- key: '_queueLoadingCallback',
- value: function _queueLoadingCallback(callback) {
- function completeRequest() {
- (0, _util.assert)(!request.done, 'completeRequest() cannot be called twice.');
- request.done = true;
- while (context.requests.length > 0 && context.requests[0].done) {
- var otherRequest = context.requests.shift();
- setTimeout(otherRequest.callback, 0);
- }
- }
- var context = this.loadingContext;
- var request = {
- id: 'pdfjs-font-loading-' + context.nextRequestId++,
- done: false,
- complete: completeRequest,
- callback: callback
- };
- context.requests.push(request);
- return request;
- }
- }, {
- key: '_prepareFontLoadEvent',
- value: function _prepareFontLoadEvent(rules, fontsToLoad, request) {
- (0, _util.unreachable)('Abstract method `_prepareFontLoadEvent`.');
- }
- }, {
- key: 'isFontLoadingAPISupported',
- get: function get() {
- (0, _util.unreachable)('Abstract method `isFontLoadingAPISupported`.');
- }
- }, {
- key: 'isSyncFontLoadingSupported',
- get: function get() {
- (0, _util.unreachable)('Abstract method `isSyncFontLoadingSupported`.');
- }
- }, {
- key: '_loadTestFont',
- get: function get() {
- (0, _util.unreachable)('Abstract method `_loadTestFont`.');
- }
- }]);
-
- return BaseFontLoader;
-}();
-
-var FontLoader = void 0;
-{
- exports.FontLoader = FontLoader = function (_BaseFontLoader) {
- _inherits(GenericFontLoader, _BaseFontLoader);
-
- function GenericFontLoader(docId) {
- _classCallCheck(this, GenericFontLoader);
-
- var _this = _possibleConstructorReturn(this, (GenericFontLoader.__proto__ || Object.getPrototypeOf(GenericFontLoader)).call(this, docId));
-
- _this.loadTestFontId = 0;
- return _this;
- }
-
- _createClass(GenericFontLoader, [{
- key: '_prepareFontLoadEvent',
- value: function _prepareFontLoadEvent(rules, fonts, request) {
- function int32(data, offset) {
- return data.charCodeAt(offset) << 24 | data.charCodeAt(offset + 1) << 16 | data.charCodeAt(offset + 2) << 8 | data.charCodeAt(offset + 3) & 0xff;
- }
- function spliceString(s, offset, remove, insert) {
- var chunk1 = s.substring(0, offset);
- var chunk2 = s.substring(offset + remove);
- return chunk1 + insert + chunk2;
- }
- var i = void 0,
- ii = void 0;
- var canvas = document.createElement('canvas');
- canvas.width = 1;
- canvas.height = 1;
- var ctx = canvas.getContext('2d');
- var called = 0;
- function isFontReady(name, callback) {
- called++;
- if (called > 30) {
- (0, _util.warn)('Load test font never loaded.');
- callback();
- return;
- }
- ctx.font = '30px ' + name;
- ctx.fillText('.', 0, 20);
- var imageData = ctx.getImageData(0, 0, 1, 1);
- if (imageData.data[3] > 0) {
- callback();
- return;
- }
- setTimeout(isFontReady.bind(null, name, callback));
- }
- var loadTestFontId = 'lt' + Date.now() + this.loadTestFontId++;
- var data = this._loadTestFont;
- var COMMENT_OFFSET = 976;
- data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length, loadTestFontId);
- var CFF_CHECKSUM_OFFSET = 16;
- var XXXX_VALUE = 0x58585858;
- var checksum = int32(data, CFF_CHECKSUM_OFFSET);
- for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) {
- checksum = checksum - XXXX_VALUE + int32(loadTestFontId, i) | 0;
- }
- if (i < loadTestFontId.length) {
- checksum = checksum - XXXX_VALUE + int32(loadTestFontId + 'XXX', i) | 0;
- }
- data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, (0, _util.string32)(checksum));
- var url = 'url(data:font/opentype;base64,' + btoa(data) + ');';
- var rule = '@font-face {font-family:"' + loadTestFontId + '";src:' + url + '}';
- this.insertRule(rule);
- var names = [];
- for (i = 0, ii = fonts.length; i < ii; i++) {
- names.push(fonts[i].loadedName);
- }
- names.push(loadTestFontId);
- var div = document.createElement('div');
- div.setAttribute('style', 'visibility: hidden;' + 'width: 10px; height: 10px;' + 'position: absolute; top: 0px; left: 0px;');
- for (i = 0, ii = names.length; i < ii; ++i) {
- var span = document.createElement('span');
- span.textContent = 'Hi';
- span.style.fontFamily = names[i];
- div.appendChild(span);
- }
- document.body.appendChild(div);
- isFontReady(loadTestFontId, function () {
- document.body.removeChild(div);
- request.complete();
- });
- }
- }, {
- key: 'isFontLoadingAPISupported',
- get: function get() {
- var supported = typeof document !== 'undefined' && !!document.fonts;
- if (supported && typeof navigator !== 'undefined') {
- var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(navigator.userAgent);
- if (m && m[1] < 63) {
- supported = false;
- }
- }
- return (0, _util.shadow)(this, 'isFontLoadingAPISupported', supported);
- }
- }, {
- key: 'isSyncFontLoadingSupported',
- get: function get() {
- var supported = false;
- if (typeof navigator === 'undefined') {
- supported = true;
- } else {
- var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(navigator.userAgent);
- if (m && m[1] >= 14) {
- supported = true;
- }
- }
- return (0, _util.shadow)(this, 'isSyncFontLoadingSupported', supported);
- }
- }, {
- key: '_loadTestFont',
- get: function get() {
- var getLoadTestFont = function getLoadTestFont() {
- return atob('T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQA' + 'FQAABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAA' + 'ALwAAAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgA' + 'AAAGbmFtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1' + 'AAsD6AAAAADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD' + '6AAAAAAD6AABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACM' + 'AooCvAAAAeAAMQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4D' + 'IP84AFoDIQAAAAAAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAA' + 'AAEAAQAAAAEAAAAAAAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUA' + 'AQAAAAEAAAAAAAYAAQAAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgAB' + 'AAMAAQQJAAMAAgABAAMAAQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABY' + 'AAAAAAAAAwAAAAMAAAAcAAEAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAA' + 'AC7////TAAEAAAAAAAABBgAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + 'AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAA' + 'AAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgcA/gXBIwMAYuL+nz5tQXkD5j3CBLnEQAC' + 'AQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYAAABAQAADwACAQEEE/t3' + 'Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQAAAAAAAABAAAAAMmJbzEAAAAAzgTj' + 'FQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAgABAAAAAAAAAAAD6AAAAAAAAA==');
- };
- return (0, _util.shadow)(this, '_loadTestFont', getLoadTestFont());
- }
- }]);
-
- return GenericFontLoader;
- }(BaseFontLoader);
-}
-var IsEvalSupportedCached = {
- get value() {
- return (0, _util.shadow)(this, 'value', (0, _util.isEvalSupported)());
- }
-};
-
-var FontFaceObject = function () {
- function FontFaceObject(translatedData, _ref) {
- var _ref$isEvalSupported = _ref.isEvalSupported,
- isEvalSupported = _ref$isEvalSupported === undefined ? true : _ref$isEvalSupported,
- _ref$disableFontFace = _ref.disableFontFace,
- disableFontFace = _ref$disableFontFace === undefined ? false : _ref$disableFontFace,
- _ref$ignoreErrors = _ref.ignoreErrors,
- ignoreErrors = _ref$ignoreErrors === undefined ? false : _ref$ignoreErrors,
- _ref$onUnsupportedFea = _ref.onUnsupportedFeature,
- onUnsupportedFeature = _ref$onUnsupportedFea === undefined ? null : _ref$onUnsupportedFea,
- _ref$fontRegistry = _ref.fontRegistry,
- fontRegistry = _ref$fontRegistry === undefined ? null : _ref$fontRegistry;
-
- _classCallCheck(this, FontFaceObject);
-
- this.compiledGlyphs = Object.create(null);
- for (var i in translatedData) {
- this[i] = translatedData[i];
- }
- this.isEvalSupported = isEvalSupported !== false;
- this.disableFontFace = disableFontFace === true;
- this.ignoreErrors = ignoreErrors === true;
- this._onUnsupportedFeature = onUnsupportedFeature;
- this.fontRegistry = fontRegistry;
- }
-
- _createClass(FontFaceObject, [{
- key: 'createNativeFontFace',
- value: function createNativeFontFace() {
- if (!this.data || this.disableFontFace) {
- return null;
- }
- var nativeFontFace = new FontFace(this.loadedName, this.data, {});
- if (this.fontRegistry) {
- this.fontRegistry.registerFont(this);
- }
- return nativeFontFace;
- }
- }, {
- key: 'createFontFaceRule',
- value: function createFontFaceRule() {
- if (!this.data || this.disableFontFace) {
- return null;
- }
- var data = (0, _util.bytesToString)(new Uint8Array(this.data));
- var url = 'url(data:' + this.mimetype + ';base64,' + btoa(data) + ');';
- var rule = '@font-face {font-family:"' + this.loadedName + '";src:' + url + '}';
- if (this.fontRegistry) {
- this.fontRegistry.registerFont(this, url);
- }
- return rule;
- }
- }, {
- key: 'getPathGenerator',
- value: function getPathGenerator(objs, character) {
- if (this.compiledGlyphs[character] !== undefined) {
- return this.compiledGlyphs[character];
- }
- var cmds = void 0,
- current = void 0;
- try {
- cmds = objs.get(this.loadedName + '_path_' + character);
- } catch (ex) {
- if (!this.ignoreErrors) {
- throw ex;
- }
- if (this._onUnsupportedFeature) {
- this._onUnsupportedFeature({ featureId: _util.UNSUPPORTED_FEATURES.font });
- }
- (0, _util.warn)('getPathGenerator - ignoring character: "' + ex + '".');
- return this.compiledGlyphs[character] = function (c, size) {};
- }
- if (this.isEvalSupported && IsEvalSupportedCached.value) {
- var args = void 0,
- js = '';
- for (var i = 0, ii = cmds.length; i < ii; i++) {
- current = cmds[i];
- if (current.args !== undefined) {
- args = current.args.join(',');
- } else {
- args = '';
- }
- js += 'c.' + current.cmd + '(' + args + ');\n';
- }
- return this.compiledGlyphs[character] = new Function('c', 'size', js);
- }
- return this.compiledGlyphs[character] = function (c, size) {
- for (var _i = 0, _ii = cmds.length; _i < _ii; _i++) {
- current = cmds[_i];
- if (current.cmd === 'scale') {
- current.args = [size, -size];
- }
- c[current.cmd].apply(c, current.args);
- }
- };
- }
- }]);
-
- return FontFaceObject;
-}();
-
-exports.FontFaceObject = FontFaceObject;
-exports.FontLoader = FontLoader;
-
-/***/ }),
-/* 132 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var compatibilityParams = Object.create(null);
-{
- var isNodeJS = __w_pdfjs_require__(4);
- var userAgent = typeof navigator !== 'undefined' && navigator.userAgent || '';
- var isIE = /Trident/.test(userAgent);
- var isIOSChrome = /CriOS/.test(userAgent);
- (function checkOnBlobSupport() {
- if (isIE || isIOSChrome) {
- compatibilityParams.disableCreateObjectURL = true;
- }
- })();
- (function checkFontFaceAndImage() {
- if (isNodeJS()) {
- compatibilityParams.disableFontFace = true;
- compatibilityParams.nativeImageDecoderSupport = 'none';
- }
- })();
-}
-exports.apiCompatibilityParams = Object.freeze(compatibilityParams);
-
-/***/ }),
-/* 133 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.CanvasGraphics = undefined;
-
-var _util = __w_pdfjs_require__(1);
-
-var _pattern_helper = __w_pdfjs_require__(134);
-
-var MIN_FONT_SIZE = 16;
-var MAX_FONT_SIZE = 100;
-var MAX_GROUP_SIZE = 4096;
-var MIN_WIDTH_FACTOR = 0.65;
-var COMPILE_TYPE3_GLYPHS = true;
-var MAX_SIZE_TO_COMPILE = 1000;
-var FULL_CHUNK_HEIGHT = 16;
-var IsLittleEndianCached = {
- get value() {
- return (0, _util.shadow)(IsLittleEndianCached, 'value', (0, _util.isLittleEndian)());
- }
-};
-function addContextCurrentTransform(ctx) {
- if (!ctx.mozCurrentTransform) {
- ctx._originalSave = ctx.save;
- ctx._originalRestore = ctx.restore;
- ctx._originalRotate = ctx.rotate;
- ctx._originalScale = ctx.scale;
- ctx._originalTranslate = ctx.translate;
- ctx._originalTransform = ctx.transform;
- ctx._originalSetTransform = ctx.setTransform;
- ctx._transformMatrix = ctx._transformMatrix || [1, 0, 0, 1, 0, 0];
- ctx._transformStack = [];
- Object.defineProperty(ctx, 'mozCurrentTransform', {
- get: function getCurrentTransform() {
- return this._transformMatrix;
- }
- });
- Object.defineProperty(ctx, 'mozCurrentTransformInverse', {
- get: function getCurrentTransformInverse() {
- var m = this._transformMatrix;
- var a = m[0],
- b = m[1],
- c = m[2],
- d = m[3],
- e = m[4],
- f = m[5];
- var ad_bc = a * d - b * c;
- var bc_ad = b * c - a * d;
- return [d / ad_bc, b / bc_ad, c / bc_ad, a / ad_bc, (d * e - c * f) / bc_ad, (b * e - a * f) / ad_bc];
- }
- });
- ctx.save = function ctxSave() {
- var old = this._transformMatrix;
- this._transformStack.push(old);
- this._transformMatrix = old.slice(0, 6);
- this._originalSave();
- };
- ctx.restore = function ctxRestore() {
- var prev = this._transformStack.pop();
- if (prev) {
- this._transformMatrix = prev;
- this._originalRestore();
- }
- };
- ctx.translate = function ctxTranslate(x, y) {
- var m = this._transformMatrix;
- m[4] = m[0] * x + m[2] * y + m[4];
- m[5] = m[1] * x + m[3] * y + m[5];
- this._originalTranslate(x, y);
- };
- ctx.scale = function ctxScale(x, y) {
- var m = this._transformMatrix;
- m[0] = m[0] * x;
- m[1] = m[1] * x;
- m[2] = m[2] * y;
- m[3] = m[3] * y;
- this._originalScale(x, y);
- };
- ctx.transform = function ctxTransform(a, b, c, d, e, f) {
- var m = this._transformMatrix;
- this._transformMatrix = [m[0] * a + m[2] * b, m[1] * a + m[3] * b, m[0] * c + m[2] * d, m[1] * c + m[3] * d, m[0] * e + m[2] * f + m[4], m[1] * e + m[3] * f + m[5]];
- ctx._originalTransform(a, b, c, d, e, f);
- };
- ctx.setTransform = function ctxSetTransform(a, b, c, d, e, f) {
- this._transformMatrix = [a, b, c, d, e, f];
- ctx._originalSetTransform(a, b, c, d, e, f);
- };
- ctx.rotate = function ctxRotate(angle) {
- var cosValue = Math.cos(angle);
- var sinValue = Math.sin(angle);
- var m = this._transformMatrix;
- this._transformMatrix = [m[0] * cosValue + m[2] * sinValue, m[1] * cosValue + m[3] * sinValue, m[0] * -sinValue + m[2] * cosValue, m[1] * -sinValue + m[3] * cosValue, m[4], m[5]];
- this._originalRotate(angle);
- };
- }
-}
-var CachedCanvases = function CachedCanvasesClosure() {
- function CachedCanvases(canvasFactory) {
- this.canvasFactory = canvasFactory;
- this.cache = Object.create(null);
- }
- CachedCanvases.prototype = {
- getCanvas: function CachedCanvases_getCanvas(id, width, height, trackTransform) {
- var canvasEntry;
- if (this.cache[id] !== undefined) {
- canvasEntry = this.cache[id];
- this.canvasFactory.reset(canvasEntry, width, height);
- canvasEntry.context.setTransform(1, 0, 0, 1, 0, 0);
- } else {
- canvasEntry = this.canvasFactory.create(width, height);
- this.cache[id] = canvasEntry;
- }
- if (trackTransform) {
- addContextCurrentTransform(canvasEntry.context);
- }
- return canvasEntry;
- },
- clear: function clear() {
- for (var id in this.cache) {
- var canvasEntry = this.cache[id];
- this.canvasFactory.destroy(canvasEntry);
- delete this.cache[id];
- }
- }
- };
- return CachedCanvases;
-}();
-function compileType3Glyph(imgData) {
- var POINT_TO_PROCESS_LIMIT = 1000;
- var width = imgData.width,
- height = imgData.height;
- var i,
- j,
- j0,
- width1 = width + 1;
- var points = new Uint8Array(width1 * (height + 1));
- var POINT_TYPES = new Uint8Array([0, 2, 4, 0, 1, 0, 5, 4, 8, 10, 0, 8, 0, 2, 1, 0]);
- var lineSize = width + 7 & ~7,
- data0 = imgData.data;
- var data = new Uint8Array(lineSize * height),
- pos = 0,
- ii;
- for (i = 0, ii = data0.length; i < ii; i++) {
- var mask = 128,
- elem = data0[i];
- while (mask > 0) {
- data[pos++] = elem & mask ? 0 : 255;
- mask >>= 1;
- }
- }
- var count = 0;
- pos = 0;
- if (data[pos] !== 0) {
- points[0] = 1;
- ++count;
- }
- for (j = 1; j < width; j++) {
- if (data[pos] !== data[pos + 1]) {
- points[j] = data[pos] ? 2 : 1;
- ++count;
- }
- pos++;
- }
- if (data[pos] !== 0) {
- points[j] = 2;
- ++count;
- }
- for (i = 1; i < height; i++) {
- pos = i * lineSize;
- j0 = i * width1;
- if (data[pos - lineSize] !== data[pos]) {
- points[j0] = data[pos] ? 1 : 8;
- ++count;
- }
- var sum = (data[pos] ? 4 : 0) + (data[pos - lineSize] ? 8 : 0);
- for (j = 1; j < width; j++) {
- sum = (sum >> 2) + (data[pos + 1] ? 4 : 0) + (data[pos - lineSize + 1] ? 8 : 0);
- if (POINT_TYPES[sum]) {
- points[j0 + j] = POINT_TYPES[sum];
- ++count;
- }
- pos++;
- }
- if (data[pos - lineSize] !== data[pos]) {
- points[j0 + j] = data[pos] ? 2 : 4;
- ++count;
- }
- if (count > POINT_TO_PROCESS_LIMIT) {
- return null;
- }
- }
- pos = lineSize * (height - 1);
- j0 = i * width1;
- if (data[pos] !== 0) {
- points[j0] = 8;
- ++count;
- }
- for (j = 1; j < width; j++) {
- if (data[pos] !== data[pos + 1]) {
- points[j0 + j] = data[pos] ? 4 : 8;
- ++count;
- }
- pos++;
- }
- if (data[pos] !== 0) {
- points[j0 + j] = 4;
- ++count;
- }
- if (count > POINT_TO_PROCESS_LIMIT) {
- return null;
- }
- var steps = new Int32Array([0, width1, -1, 0, -width1, 0, 0, 0, 1]);
- var outlines = [];
- for (i = 0; count && i <= height; i++) {
- var p = i * width1;
- var end = p + width;
- while (p < end && !points[p]) {
- p++;
- }
- if (p === end) {
- continue;
- }
- var coords = [p % width1, i];
- var type = points[p],
- p0 = p,
- pp;
- do {
- var step = steps[type];
- do {
- p += step;
- } while (!points[p]);
- pp = points[p];
- if (pp !== 5 && pp !== 10) {
- type = pp;
- points[p] = 0;
- } else {
- type = pp & 0x33 * type >> 4;
- points[p] &= type >> 2 | type << 2;
- }
- coords.push(p % width1);
- coords.push(p / width1 | 0);
- --count;
- } while (p0 !== p);
- outlines.push(coords);
- --i;
- }
- var drawOutline = function drawOutline(c) {
- c.save();
- c.scale(1 / width, -1 / height);
- c.translate(0, -height);
- c.beginPath();
- for (var i = 0, ii = outlines.length; i < ii; i++) {
- var o = outlines[i];
- c.moveTo(o[0], o[1]);
- for (var j = 2, jj = o.length; j < jj; j += 2) {
- c.lineTo(o[j], o[j + 1]);
- }
- }
- c.fill();
- c.beginPath();
- c.restore();
- };
- return drawOutline;
-}
-var CanvasExtraState = function CanvasExtraStateClosure() {
- function CanvasExtraState() {
- this.alphaIsShape = false;
- this.fontSize = 0;
- this.fontSizeScale = 1;
- this.textMatrix = _util.IDENTITY_MATRIX;
- this.textMatrixScale = 1;
- this.fontMatrix = _util.FONT_IDENTITY_MATRIX;
- this.leading = 0;
- this.x = 0;
- this.y = 0;
- this.lineX = 0;
- this.lineY = 0;
- this.charSpacing = 0;
- this.wordSpacing = 0;
- this.textHScale = 1;
- this.textRenderingMode = _util.TextRenderingMode.FILL;
- this.textRise = 0;
- this.fillColor = '#000000';
- this.strokeColor = '#000000';
- this.patternFill = false;
- this.fillAlpha = 1;
- this.strokeAlpha = 1;
- this.lineWidth = 1;
- this.activeSMask = null;
- this.resumeSMaskCtx = null;
- }
- CanvasExtraState.prototype = {
- clone: function CanvasExtraState_clone() {
- return Object.create(this);
- },
- setCurrentPoint: function CanvasExtraState_setCurrentPoint(x, y) {
- this.x = x;
- this.y = y;
- }
- };
- return CanvasExtraState;
-}();
-var CanvasGraphics = function CanvasGraphicsClosure() {
- var EXECUTION_TIME = 15;
- var EXECUTION_STEPS = 10;
- function CanvasGraphics(canvasCtx, commonObjs, objs, canvasFactory, webGLContext, imageLayer) {
- this.ctx = canvasCtx;
- this.current = new CanvasExtraState();
- this.stateStack = [];
- this.pendingClip = null;
- this.pendingEOFill = false;
- this.res = null;
- this.xobjs = null;
- this.commonObjs = commonObjs;
- this.objs = objs;
- this.canvasFactory = canvasFactory;
- this.webGLContext = webGLContext;
- this.imageLayer = imageLayer;
- this.groupStack = [];
- this.processingType3 = null;
- this.baseTransform = null;
- this.baseTransformStack = [];
- this.groupLevel = 0;
- this.smaskStack = [];
- this.smaskCounter = 0;
- this.tempSMask = null;
- this.cachedCanvases = new CachedCanvases(this.canvasFactory);
- if (canvasCtx) {
- addContextCurrentTransform(canvasCtx);
- }
- this._cachedGetSinglePixelWidth = null;
- }
- function putBinaryImageData(ctx, imgData) {
- if (typeof ImageData !== 'undefined' && imgData instanceof ImageData) {
- ctx.putImageData(imgData, 0, 0);
- return;
- }
- var height = imgData.height,
- width = imgData.width;
- var partialChunkHeight = height % FULL_CHUNK_HEIGHT;
- var fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
- var totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
- var chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);
- var srcPos = 0,
- destPos;
- var src = imgData.data;
- var dest = chunkImgData.data;
- var i, j, thisChunkHeight, elemsInThisChunk;
- if (imgData.kind === _util.ImageKind.GRAYSCALE_1BPP) {
- var srcLength = src.byteLength;
- var dest32 = new Uint32Array(dest.buffer, 0, dest.byteLength >> 2);
- var dest32DataLength = dest32.length;
- var fullSrcDiff = width + 7 >> 3;
- var white = 0xFFFFFFFF;
- var black = IsLittleEndianCached.value ? 0xFF000000 : 0x000000FF;
- for (i = 0; i < totalChunks; i++) {
- thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight;
- destPos = 0;
- for (j = 0; j < thisChunkHeight; j++) {
- var srcDiff = srcLength - srcPos;
- var k = 0;
- var kEnd = srcDiff > fullSrcDiff ? width : srcDiff * 8 - 7;
- var kEndUnrolled = kEnd & ~7;
- var mask = 0;
- var srcByte = 0;
- for (; k < kEndUnrolled; k += 8) {
- srcByte = src[srcPos++];
- dest32[destPos++] = srcByte & 128 ? white : black;
- dest32[destPos++] = srcByte & 64 ? white : black;
- dest32[destPos++] = srcByte & 32 ? white : black;
- dest32[destPos++] = srcByte & 16 ? white : black;
- dest32[destPos++] = srcByte & 8 ? white : black;
- dest32[destPos++] = srcByte & 4 ? white : black;
- dest32[destPos++] = srcByte & 2 ? white : black;
- dest32[destPos++] = srcByte & 1 ? white : black;
- }
- for (; k < kEnd; k++) {
- if (mask === 0) {
- srcByte = src[srcPos++];
- mask = 128;
- }
- dest32[destPos++] = srcByte & mask ? white : black;
- mask >>= 1;
- }
- }
- while (destPos < dest32DataLength) {
- dest32[destPos++] = 0;
- }
- ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
- }
- } else if (imgData.kind === _util.ImageKind.RGBA_32BPP) {
- j = 0;
- elemsInThisChunk = width * FULL_CHUNK_HEIGHT * 4;
- for (i = 0; i < fullChunks; i++) {
- dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
- srcPos += elemsInThisChunk;
- ctx.putImageData(chunkImgData, 0, j);
- j += FULL_CHUNK_HEIGHT;
- }
- if (i < totalChunks) {
- elemsInThisChunk = width * partialChunkHeight * 4;
- dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
- ctx.putImageData(chunkImgData, 0, j);
- }
- } else if (imgData.kind === _util.ImageKind.RGB_24BPP) {
- thisChunkHeight = FULL_CHUNK_HEIGHT;
- elemsInThisChunk = width * thisChunkHeight;
- for (i = 0; i < totalChunks; i++) {
- if (i >= fullChunks) {
- thisChunkHeight = partialChunkHeight;
- elemsInThisChunk = width * thisChunkHeight;
- }
- destPos = 0;
- for (j = elemsInThisChunk; j--;) {
- dest[destPos++] = src[srcPos++];
- dest[destPos++] = src[srcPos++];
- dest[destPos++] = src[srcPos++];
- dest[destPos++] = 255;
- }
- ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
- }
- } else {
- throw new Error('bad image kind: ' + imgData.kind);
- }
- }
- function putBinaryImageMask(ctx, imgData) {
- var height = imgData.height,
- width = imgData.width;
- var partialChunkHeight = height % FULL_CHUNK_HEIGHT;
- var fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
- var totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
- var chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);
- var srcPos = 0;
- var src = imgData.data;
- var dest = chunkImgData.data;
- for (var i = 0; i < totalChunks; i++) {
- var thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight;
- var destPos = 3;
- for (var j = 0; j < thisChunkHeight; j++) {
- var mask = 0;
- for (var k = 0; k < width; k++) {
- if (!mask) {
- var elem = src[srcPos++];
- mask = 128;
- }
- dest[destPos] = elem & mask ? 0 : 255;
- destPos += 4;
- mask >>= 1;
- }
- }
- ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
- }
- }
- function copyCtxState(sourceCtx, destCtx) {
- var properties = ['strokeStyle', 'fillStyle', 'fillRule', 'globalAlpha', 'lineWidth', 'lineCap', 'lineJoin', 'miterLimit', 'globalCompositeOperation', 'font'];
- for (var i = 0, ii = properties.length; i < ii; i++) {
- var property = properties[i];
- if (sourceCtx[property] !== undefined) {
- destCtx[property] = sourceCtx[property];
- }
- }
- if (sourceCtx.setLineDash !== undefined) {
- destCtx.setLineDash(sourceCtx.getLineDash());
- destCtx.lineDashOffset = sourceCtx.lineDashOffset;
- }
- }
- function resetCtxToDefault(ctx) {
- ctx.strokeStyle = '#000000';
- ctx.fillStyle = '#000000';
- ctx.fillRule = 'nonzero';
- ctx.globalAlpha = 1;
- ctx.lineWidth = 1;
- ctx.lineCap = 'butt';
- ctx.lineJoin = 'miter';
- ctx.miterLimit = 10;
- ctx.globalCompositeOperation = 'source-over';
- ctx.font = '10px sans-serif';
- if (ctx.setLineDash !== undefined) {
- ctx.setLineDash([]);
- ctx.lineDashOffset = 0;
- }
- }
- function composeSMaskBackdrop(bytes, r0, g0, b0) {
- var length = bytes.length;
- for (var i = 3; i < length; i += 4) {
- var alpha = bytes[i];
- if (alpha === 0) {
- bytes[i - 3] = r0;
- bytes[i - 2] = g0;
- bytes[i - 1] = b0;
- } else if (alpha < 255) {
- var alpha_ = 255 - alpha;
- bytes[i - 3] = bytes[i - 3] * alpha + r0 * alpha_ >> 8;
- bytes[i - 2] = bytes[i - 2] * alpha + g0 * alpha_ >> 8;
- bytes[i - 1] = bytes[i - 1] * alpha + b0 * alpha_ >> 8;
- }
- }
- }
- function composeSMaskAlpha(maskData, layerData, transferMap) {
- var length = maskData.length;
- var scale = 1 / 255;
- for (var i = 3; i < length; i += 4) {
- var alpha = transferMap ? transferMap[maskData[i]] : maskData[i];
- layerData[i] = layerData[i] * alpha * scale | 0;
- }
- }
- function composeSMaskLuminosity(maskData, layerData, transferMap) {
- var length = maskData.length;
- for (var i = 3; i < length; i += 4) {
- var y = maskData[i - 3] * 77 + maskData[i - 2] * 152 + maskData[i - 1] * 28;
- layerData[i] = transferMap ? layerData[i] * transferMap[y >> 8] >> 8 : layerData[i] * y >> 16;
- }
- }
- function genericComposeSMask(maskCtx, layerCtx, width, height, subtype, backdrop, transferMap) {
- var hasBackdrop = !!backdrop;
- var r0 = hasBackdrop ? backdrop[0] : 0;
- var g0 = hasBackdrop ? backdrop[1] : 0;
- var b0 = hasBackdrop ? backdrop[2] : 0;
- var composeFn;
- if (subtype === 'Luminosity') {
- composeFn = composeSMaskLuminosity;
- } else {
- composeFn = composeSMaskAlpha;
- }
- var PIXELS_TO_PROCESS = 1048576;
- var chunkSize = Math.min(height, Math.ceil(PIXELS_TO_PROCESS / width));
- for (var row = 0; row < height; row += chunkSize) {
- var chunkHeight = Math.min(chunkSize, height - row);
- var maskData = maskCtx.getImageData(0, row, width, chunkHeight);
- var layerData = layerCtx.getImageData(0, row, width, chunkHeight);
- if (hasBackdrop) {
- composeSMaskBackdrop(maskData.data, r0, g0, b0);
- }
- composeFn(maskData.data, layerData.data, transferMap);
- maskCtx.putImageData(layerData, 0, row);
- }
- }
- function composeSMask(ctx, smask, layerCtx, webGLContext) {
- var mask = smask.canvas;
- var maskCtx = smask.context;
- ctx.setTransform(smask.scaleX, 0, 0, smask.scaleY, smask.offsetX, smask.offsetY);
- var backdrop = smask.backdrop || null;
- if (!smask.transferMap && webGLContext.isEnabled) {
- var composed = webGLContext.composeSMask({
- layer: layerCtx.canvas,
- mask: mask,
- properties: {
- subtype: smask.subtype,
- backdrop: backdrop
- }
- });
- ctx.setTransform(1, 0, 0, 1, 0, 0);
- ctx.drawImage(composed, smask.offsetX, smask.offsetY);
- return;
- }
- genericComposeSMask(maskCtx, layerCtx, mask.width, mask.height, smask.subtype, backdrop, smask.transferMap);
- ctx.drawImage(mask, 0, 0);
- }
- var LINE_CAP_STYLES = ['butt', 'round', 'square'];
- var LINE_JOIN_STYLES = ['miter', 'round', 'bevel'];
- var NORMAL_CLIP = {};
- var EO_CLIP = {};
- CanvasGraphics.prototype = {
- beginDrawing: function beginDrawing(_ref) {
- var transform = _ref.transform,
- viewport = _ref.viewport,
- transparency = _ref.transparency,
- _ref$background = _ref.background,
- background = _ref$background === undefined ? null : _ref$background;
-
- var width = this.ctx.canvas.width;
- var height = this.ctx.canvas.height;
- this.ctx.save();
- this.ctx.fillStyle = background || 'rgb(255, 255, 255)';
- this.ctx.fillRect(0, 0, width, height);
- this.ctx.restore();
- if (transparency) {
- var transparentCanvas = this.cachedCanvases.getCanvas('transparent', width, height, true);
- this.compositeCtx = this.ctx;
- this.transparentCanvas = transparentCanvas.canvas;
- this.ctx = transparentCanvas.context;
- this.ctx.save();
- this.ctx.transform.apply(this.ctx, this.compositeCtx.mozCurrentTransform);
- }
- this.ctx.save();
- resetCtxToDefault(this.ctx);
- if (transform) {
- this.ctx.transform.apply(this.ctx, transform);
- }
- this.ctx.transform.apply(this.ctx, viewport.transform);
- this.baseTransform = this.ctx.mozCurrentTransform.slice();
- if (this.imageLayer) {
- this.imageLayer.beginLayout();
- }
- },
-
- executeOperatorList: function CanvasGraphics_executeOperatorList(operatorList, executionStartIdx, continueCallback, stepper) {
- var argsArray = operatorList.argsArray;
- var fnArray = operatorList.fnArray;
- var i = executionStartIdx || 0;
- var argsArrayLen = argsArray.length;
- if (argsArrayLen === i) {
- return i;
- }
- var chunkOperations = argsArrayLen - i > EXECUTION_STEPS && typeof continueCallback === 'function';
- var endTime = chunkOperations ? Date.now() + EXECUTION_TIME : 0;
- var steps = 0;
- var commonObjs = this.commonObjs;
- var objs = this.objs;
- var fnId;
- while (true) {
- if (stepper !== undefined && i === stepper.nextBreakPoint) {
- stepper.breakIt(i, continueCallback);
- return i;
- }
- fnId = fnArray[i];
- if (fnId !== _util.OPS.dependency) {
- this[fnId].apply(this, argsArray[i]);
- } else {
- var deps = argsArray[i];
- for (var n = 0, nn = deps.length; n < nn; n++) {
- var depObjId = deps[n];
- var common = depObjId[0] === 'g' && depObjId[1] === '_';
- var objsPool = common ? commonObjs : objs;
- if (!objsPool.isResolved(depObjId)) {
- objsPool.get(depObjId, continueCallback);
- return i;
- }
- }
- }
- i++;
- if (i === argsArrayLen) {
- return i;
- }
- if (chunkOperations && ++steps > EXECUTION_STEPS) {
- if (Date.now() > endTime) {
- continueCallback();
- return i;
- }
- steps = 0;
- }
- }
- },
- endDrawing: function CanvasGraphics_endDrawing() {
- if (this.current.activeSMask !== null) {
- this.endSMaskGroup();
- }
- this.ctx.restore();
- if (this.transparentCanvas) {
- this.ctx = this.compositeCtx;
- this.ctx.save();
- this.ctx.setTransform(1, 0, 0, 1, 0, 0);
- this.ctx.drawImage(this.transparentCanvas, 0, 0);
- this.ctx.restore();
- this.transparentCanvas = null;
- }
- this.cachedCanvases.clear();
- this.webGLContext.clear();
- if (this.imageLayer) {
- this.imageLayer.endLayout();
- }
- },
- setLineWidth: function CanvasGraphics_setLineWidth(width) {
- this.current.lineWidth = width;
- this.ctx.lineWidth = width;
- },
- setLineCap: function CanvasGraphics_setLineCap(style) {
- this.ctx.lineCap = LINE_CAP_STYLES[style];
- },
- setLineJoin: function CanvasGraphics_setLineJoin(style) {
- this.ctx.lineJoin = LINE_JOIN_STYLES[style];
- },
- setMiterLimit: function CanvasGraphics_setMiterLimit(limit) {
- this.ctx.miterLimit = limit;
- },
- setDash: function CanvasGraphics_setDash(dashArray, dashPhase) {
- var ctx = this.ctx;
- if (ctx.setLineDash !== undefined) {
- ctx.setLineDash(dashArray);
- ctx.lineDashOffset = dashPhase;
- }
- },
- setRenderingIntent: function CanvasGraphics_setRenderingIntent(intent) {},
- setFlatness: function CanvasGraphics_setFlatness(flatness) {},
- setGState: function CanvasGraphics_setGState(states) {
- for (var i = 0, ii = states.length; i < ii; i++) {
- var state = states[i];
- var key = state[0];
- var value = state[1];
- switch (key) {
- case 'LW':
- this.setLineWidth(value);
- break;
- case 'LC':
- this.setLineCap(value);
- break;
- case 'LJ':
- this.setLineJoin(value);
- break;
- case 'ML':
- this.setMiterLimit(value);
- break;
- case 'D':
- this.setDash(value[0], value[1]);
- break;
- case 'RI':
- this.setRenderingIntent(value);
- break;
- case 'FL':
- this.setFlatness(value);
- break;
- case 'Font':
- this.setFont(value[0], value[1]);
- break;
- case 'CA':
- this.current.strokeAlpha = state[1];
- break;
- case 'ca':
- this.current.fillAlpha = state[1];
- this.ctx.globalAlpha = state[1];
- break;
- case 'BM':
- this.ctx.globalCompositeOperation = value;
- break;
- case 'SMask':
- if (this.current.activeSMask) {
- if (this.stateStack.length > 0 && this.stateStack[this.stateStack.length - 1].activeSMask === this.current.activeSMask) {
- this.suspendSMaskGroup();
- } else {
- this.endSMaskGroup();
- }
- }
- this.current.activeSMask = value ? this.tempSMask : null;
- if (this.current.activeSMask) {
- this.beginSMaskGroup();
- }
- this.tempSMask = null;
- break;
- }
- }
- },
- beginSMaskGroup: function CanvasGraphics_beginSMaskGroup() {
- var activeSMask = this.current.activeSMask;
- var drawnWidth = activeSMask.canvas.width;
- var drawnHeight = activeSMask.canvas.height;
- var cacheId = 'smaskGroupAt' + this.groupLevel;
- var scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight, true);
- var currentCtx = this.ctx;
- var currentTransform = currentCtx.mozCurrentTransform;
- this.ctx.save();
- var groupCtx = scratchCanvas.context;
- groupCtx.scale(1 / activeSMask.scaleX, 1 / activeSMask.scaleY);
- groupCtx.translate(-activeSMask.offsetX, -activeSMask.offsetY);
- groupCtx.transform.apply(groupCtx, currentTransform);
- activeSMask.startTransformInverse = groupCtx.mozCurrentTransformInverse;
- copyCtxState(currentCtx, groupCtx);
- this.ctx = groupCtx;
- this.setGState([['BM', 'source-over'], ['ca', 1], ['CA', 1]]);
- this.groupStack.push(currentCtx);
- this.groupLevel++;
- },
- suspendSMaskGroup: function CanvasGraphics_endSMaskGroup() {
- var groupCtx = this.ctx;
- this.groupLevel--;
- this.ctx = this.groupStack.pop();
- composeSMask(this.ctx, this.current.activeSMask, groupCtx, this.webGLContext);
- this.ctx.restore();
- this.ctx.save();
- copyCtxState(groupCtx, this.ctx);
- this.current.resumeSMaskCtx = groupCtx;
- var deltaTransform = _util.Util.transform(this.current.activeSMask.startTransformInverse, groupCtx.mozCurrentTransform);
- this.ctx.transform.apply(this.ctx, deltaTransform);
- groupCtx.save();
- groupCtx.setTransform(1, 0, 0, 1, 0, 0);
- groupCtx.clearRect(0, 0, groupCtx.canvas.width, groupCtx.canvas.height);
- groupCtx.restore();
- },
- resumeSMaskGroup: function CanvasGraphics_endSMaskGroup() {
- var groupCtx = this.current.resumeSMaskCtx;
- var currentCtx = this.ctx;
- this.ctx = groupCtx;
- this.groupStack.push(currentCtx);
- this.groupLevel++;
- },
- endSMaskGroup: function CanvasGraphics_endSMaskGroup() {
- var groupCtx = this.ctx;
- this.groupLevel--;
- this.ctx = this.groupStack.pop();
- composeSMask(this.ctx, this.current.activeSMask, groupCtx, this.webGLContext);
- this.ctx.restore();
- copyCtxState(groupCtx, this.ctx);
- var deltaTransform = _util.Util.transform(this.current.activeSMask.startTransformInverse, groupCtx.mozCurrentTransform);
- this.ctx.transform.apply(this.ctx, deltaTransform);
- },
- save: function CanvasGraphics_save() {
- this.ctx.save();
- var old = this.current;
- this.stateStack.push(old);
- this.current = old.clone();
- this.current.resumeSMaskCtx = null;
- },
- restore: function CanvasGraphics_restore() {
- if (this.current.resumeSMaskCtx) {
- this.resumeSMaskGroup();
- }
- if (this.current.activeSMask !== null && (this.stateStack.length === 0 || this.stateStack[this.stateStack.length - 1].activeSMask !== this.current.activeSMask)) {
- this.endSMaskGroup();
- }
- if (this.stateStack.length !== 0) {
- this.current = this.stateStack.pop();
- this.ctx.restore();
- this.pendingClip = null;
- this._cachedGetSinglePixelWidth = null;
- }
- },
- transform: function CanvasGraphics_transform(a, b, c, d, e, f) {
- this.ctx.transform(a, b, c, d, e, f);
- this._cachedGetSinglePixelWidth = null;
- },
- constructPath: function CanvasGraphics_constructPath(ops, args) {
- var ctx = this.ctx;
- var current = this.current;
- var x = current.x,
- y = current.y;
- for (var i = 0, j = 0, ii = ops.length; i < ii; i++) {
- switch (ops[i] | 0) {
- case _util.OPS.rectangle:
- x = args[j++];
- y = args[j++];
- var width = args[j++];
- var height = args[j++];
- if (width === 0) {
- width = this.getSinglePixelWidth();
- }
- if (height === 0) {
- height = this.getSinglePixelWidth();
- }
- var xw = x + width;
- var yh = y + height;
- this.ctx.moveTo(x, y);
- this.ctx.lineTo(xw, y);
- this.ctx.lineTo(xw, yh);
- this.ctx.lineTo(x, yh);
- this.ctx.lineTo(x, y);
- this.ctx.closePath();
- break;
- case _util.OPS.moveTo:
- x = args[j++];
- y = args[j++];
- ctx.moveTo(x, y);
- break;
- case _util.OPS.lineTo:
- x = args[j++];
- y = args[j++];
- ctx.lineTo(x, y);
- break;
- case _util.OPS.curveTo:
- x = args[j + 4];
- y = args[j + 5];
- ctx.bezierCurveTo(args[j], args[j + 1], args[j + 2], args[j + 3], x, y);
- j += 6;
- break;
- case _util.OPS.curveTo2:
- ctx.bezierCurveTo(x, y, args[j], args[j + 1], args[j + 2], args[j + 3]);
- x = args[j + 2];
- y = args[j + 3];
- j += 4;
- break;
- case _util.OPS.curveTo3:
- x = args[j + 2];
- y = args[j + 3];
- ctx.bezierCurveTo(args[j], args[j + 1], x, y, x, y);
- j += 4;
- break;
- case _util.OPS.closePath:
- ctx.closePath();
- break;
- }
- }
- current.setCurrentPoint(x, y);
- },
- closePath: function CanvasGraphics_closePath() {
- this.ctx.closePath();
- },
- stroke: function CanvasGraphics_stroke(consumePath) {
- consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
- var ctx = this.ctx;
- var strokeColor = this.current.strokeColor;
- ctx.lineWidth = Math.max(this.getSinglePixelWidth() * MIN_WIDTH_FACTOR, this.current.lineWidth);
- ctx.globalAlpha = this.current.strokeAlpha;
- if (strokeColor && strokeColor.hasOwnProperty('type') && strokeColor.type === 'Pattern') {
- ctx.save();
- ctx.strokeStyle = strokeColor.getPattern(ctx, this);
- ctx.stroke();
- ctx.restore();
- } else {
- ctx.stroke();
- }
- if (consumePath) {
- this.consumePath();
- }
- ctx.globalAlpha = this.current.fillAlpha;
- },
- closeStroke: function CanvasGraphics_closeStroke() {
- this.closePath();
- this.stroke();
- },
- fill: function CanvasGraphics_fill(consumePath) {
- consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
- var ctx = this.ctx;
- var fillColor = this.current.fillColor;
- var isPatternFill = this.current.patternFill;
- var needRestore = false;
- if (isPatternFill) {
- ctx.save();
- if (this.baseTransform) {
- ctx.setTransform.apply(ctx, this.baseTransform);
- }
- ctx.fillStyle = fillColor.getPattern(ctx, this);
- needRestore = true;
- }
- if (this.pendingEOFill) {
- ctx.fill('evenodd');
- this.pendingEOFill = false;
- } else {
- ctx.fill();
- }
- if (needRestore) {
- ctx.restore();
- }
- if (consumePath) {
- this.consumePath();
- }
- },
- eoFill: function CanvasGraphics_eoFill() {
- this.pendingEOFill = true;
- this.fill();
- },
- fillStroke: function CanvasGraphics_fillStroke() {
- this.fill(false);
- this.stroke(false);
- this.consumePath();
- },
- eoFillStroke: function CanvasGraphics_eoFillStroke() {
- this.pendingEOFill = true;
- this.fillStroke();
- },
- closeFillStroke: function CanvasGraphics_closeFillStroke() {
- this.closePath();
- this.fillStroke();
- },
- closeEOFillStroke: function CanvasGraphics_closeEOFillStroke() {
- this.pendingEOFill = true;
- this.closePath();
- this.fillStroke();
- },
- endPath: function CanvasGraphics_endPath() {
- this.consumePath();
- },
- clip: function CanvasGraphics_clip() {
- this.pendingClip = NORMAL_CLIP;
- },
- eoClip: function CanvasGraphics_eoClip() {
- this.pendingClip = EO_CLIP;
- },
- beginText: function CanvasGraphics_beginText() {
- this.current.textMatrix = _util.IDENTITY_MATRIX;
- this.current.textMatrixScale = 1;
- this.current.x = this.current.lineX = 0;
- this.current.y = this.current.lineY = 0;
- },
- endText: function CanvasGraphics_endText() {
- var paths = this.pendingTextPaths;
- var ctx = this.ctx;
- if (paths === undefined) {
- ctx.beginPath();
- return;
- }
- ctx.save();
- ctx.beginPath();
- for (var i = 0; i < paths.length; i++) {
- var path = paths[i];
- ctx.setTransform.apply(ctx, path.transform);
- ctx.translate(path.x, path.y);
- path.addToPath(ctx, path.fontSize);
- }
- ctx.restore();
- ctx.clip();
- ctx.beginPath();
- delete this.pendingTextPaths;
- },
- setCharSpacing: function CanvasGraphics_setCharSpacing(spacing) {
- this.current.charSpacing = spacing;
- },
- setWordSpacing: function CanvasGraphics_setWordSpacing(spacing) {
- this.current.wordSpacing = spacing;
- },
- setHScale: function CanvasGraphics_setHScale(scale) {
- this.current.textHScale = scale / 100;
- },
- setLeading: function CanvasGraphics_setLeading(leading) {
- this.current.leading = -leading;
- },
- setFont: function CanvasGraphics_setFont(fontRefName, size) {
- var fontObj = this.commonObjs.get(fontRefName);
- var current = this.current;
- if (!fontObj) {
- throw new Error('Can\'t find font for ' + fontRefName);
- }
- current.fontMatrix = fontObj.fontMatrix ? fontObj.fontMatrix : _util.FONT_IDENTITY_MATRIX;
- if (current.fontMatrix[0] === 0 || current.fontMatrix[3] === 0) {
- (0, _util.warn)('Invalid font matrix for font ' + fontRefName);
- }
- if (size < 0) {
- size = -size;
- current.fontDirection = -1;
- } else {
- current.fontDirection = 1;
- }
- this.current.font = fontObj;
- this.current.fontSize = size;
- if (fontObj.isType3Font) {
- return;
- }
- var name = fontObj.loadedName || 'sans-serif';
- var bold = fontObj.black ? '900' : fontObj.bold ? 'bold' : 'normal';
- var italic = fontObj.italic ? 'italic' : 'normal';
- var typeface = '"' + name + '", ' + fontObj.fallbackName;
- var browserFontSize = size < MIN_FONT_SIZE ? MIN_FONT_SIZE : size > MAX_FONT_SIZE ? MAX_FONT_SIZE : size;
- this.current.fontSizeScale = size / browserFontSize;
- var rule = italic + ' ' + bold + ' ' + browserFontSize + 'px ' + typeface;
- this.ctx.font = rule;
- },
- setTextRenderingMode: function CanvasGraphics_setTextRenderingMode(mode) {
- this.current.textRenderingMode = mode;
- },
- setTextRise: function CanvasGraphics_setTextRise(rise) {
- this.current.textRise = rise;
- },
- moveText: function CanvasGraphics_moveText(x, y) {
- this.current.x = this.current.lineX += x;
- this.current.y = this.current.lineY += y;
- },
- setLeadingMoveText: function CanvasGraphics_setLeadingMoveText(x, y) {
- this.setLeading(-y);
- this.moveText(x, y);
- },
- setTextMatrix: function CanvasGraphics_setTextMatrix(a, b, c, d, e, f) {
- this.current.textMatrix = [a, b, c, d, e, f];
- this.current.textMatrixScale = Math.sqrt(a * a + b * b);
- this.current.x = this.current.lineX = 0;
- this.current.y = this.current.lineY = 0;
- },
- nextLine: function CanvasGraphics_nextLine() {
- this.moveText(0, this.current.leading);
- },
- paintChar: function paintChar(character, x, y, patternTransform) {
- var ctx = this.ctx;
- var current = this.current;
- var font = current.font;
- var textRenderingMode = current.textRenderingMode;
- var fontSize = current.fontSize / current.fontSizeScale;
- var fillStrokeMode = textRenderingMode & _util.TextRenderingMode.FILL_STROKE_MASK;
- var isAddToPathSet = !!(textRenderingMode & _util.TextRenderingMode.ADD_TO_PATH_FLAG);
- var patternFill = current.patternFill && font.data;
- var addToPath;
- if (font.disableFontFace || isAddToPathSet || patternFill) {
- addToPath = font.getPathGenerator(this.commonObjs, character);
- }
- if (font.disableFontFace || patternFill) {
- ctx.save();
- ctx.translate(x, y);
- ctx.beginPath();
- addToPath(ctx, fontSize);
- if (patternTransform) {
- ctx.setTransform.apply(ctx, patternTransform);
- }
- if (fillStrokeMode === _util.TextRenderingMode.FILL || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
- ctx.fill();
- }
- if (fillStrokeMode === _util.TextRenderingMode.STROKE || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
- ctx.stroke();
- }
- ctx.restore();
- } else {
- if (fillStrokeMode === _util.TextRenderingMode.FILL || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
- ctx.fillText(character, x, y);
- }
- if (fillStrokeMode === _util.TextRenderingMode.STROKE || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
- ctx.strokeText(character, x, y);
- }
- }
- if (isAddToPathSet) {
- var paths = this.pendingTextPaths || (this.pendingTextPaths = []);
- paths.push({
- transform: ctx.mozCurrentTransform,
- x: x,
- y: y,
- fontSize: fontSize,
- addToPath: addToPath
- });
- }
- },
-
- get isFontSubpixelAAEnabled() {
- var ctx = this.canvasFactory.create(10, 10).context;
- ctx.scale(1.5, 1);
- ctx.fillText('I', 0, 10);
- var data = ctx.getImageData(0, 0, 10, 10).data;
- var enabled = false;
- for (var i = 3; i < data.length; i += 4) {
- if (data[i] > 0 && data[i] < 255) {
- enabled = true;
- break;
- }
- }
- return (0, _util.shadow)(this, 'isFontSubpixelAAEnabled', enabled);
- },
- showText: function CanvasGraphics_showText(glyphs) {
- var current = this.current;
- var font = current.font;
- if (font.isType3Font) {
- return this.showType3Text(glyphs);
- }
- var fontSize = current.fontSize;
- if (fontSize === 0) {
- return;
- }
- var ctx = this.ctx;
- var fontSizeScale = current.fontSizeScale;
- var charSpacing = current.charSpacing;
- var wordSpacing = current.wordSpacing;
- var fontDirection = current.fontDirection;
- var textHScale = current.textHScale * fontDirection;
- var glyphsLength = glyphs.length;
- var vertical = font.vertical;
- var spacingDir = vertical ? 1 : -1;
- var defaultVMetrics = font.defaultVMetrics;
- var widthAdvanceScale = fontSize * current.fontMatrix[0];
- var simpleFillText = current.textRenderingMode === _util.TextRenderingMode.FILL && !font.disableFontFace && !current.patternFill;
- ctx.save();
- var patternTransform = void 0;
- if (current.patternFill) {
- ctx.save();
- var pattern = current.fillColor.getPattern(ctx, this);
- patternTransform = ctx.mozCurrentTransform;
- ctx.restore();
- ctx.fillStyle = pattern;
- }
- ctx.transform.apply(ctx, current.textMatrix);
- ctx.translate(current.x, current.y + current.textRise);
- if (fontDirection > 0) {
- ctx.scale(textHScale, -1);
- } else {
- ctx.scale(textHScale, 1);
- }
- var lineWidth = current.lineWidth;
- var scale = current.textMatrixScale;
- if (scale === 0 || lineWidth === 0) {
- var fillStrokeMode = current.textRenderingMode & _util.TextRenderingMode.FILL_STROKE_MASK;
- if (fillStrokeMode === _util.TextRenderingMode.STROKE || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
- this._cachedGetSinglePixelWidth = null;
- lineWidth = this.getSinglePixelWidth() * MIN_WIDTH_FACTOR;
- }
- } else {
- lineWidth /= scale;
- }
- if (fontSizeScale !== 1.0) {
- ctx.scale(fontSizeScale, fontSizeScale);
- lineWidth /= fontSizeScale;
- }
- ctx.lineWidth = lineWidth;
- var x = 0,
- i;
- for (i = 0; i < glyphsLength; ++i) {
- var glyph = glyphs[i];
- if ((0, _util.isNum)(glyph)) {
- x += spacingDir * glyph * fontSize / 1000;
- continue;
- }
- var restoreNeeded = false;
- var spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
- var character = glyph.fontChar;
- var accent = glyph.accent;
- var scaledX, scaledY, scaledAccentX, scaledAccentY;
- var width = glyph.width;
- if (vertical) {
- var vmetric, vx, vy;
- vmetric = glyph.vmetric || defaultVMetrics;
- vx = glyph.vmetric ? vmetric[1] : width * 0.5;
- vx = -vx * widthAdvanceScale;
- vy = vmetric[2] * widthAdvanceScale;
- width = vmetric ? -vmetric[0] : width;
- scaledX = vx / fontSizeScale;
- scaledY = (x + vy) / fontSizeScale;
- } else {
- scaledX = x / fontSizeScale;
- scaledY = 0;
- }
- if (font.remeasure && width > 0) {
- var measuredWidth = ctx.measureText(character).width * 1000 / fontSize * fontSizeScale;
- if (width < measuredWidth && this.isFontSubpixelAAEnabled) {
- var characterScaleX = width / measuredWidth;
- restoreNeeded = true;
- ctx.save();
- ctx.scale(characterScaleX, 1);
- scaledX /= characterScaleX;
- } else if (width !== measuredWidth) {
- scaledX += (width - measuredWidth) / 2000 * fontSize / fontSizeScale;
- }
- }
- if (glyph.isInFont || font.missingFile) {
- if (simpleFillText && !accent) {
- ctx.fillText(character, scaledX, scaledY);
- } else {
- this.paintChar(character, scaledX, scaledY, patternTransform);
- if (accent) {
- scaledAccentX = scaledX + accent.offset.x / fontSizeScale;
- scaledAccentY = scaledY - accent.offset.y / fontSizeScale;
- this.paintChar(accent.fontChar, scaledAccentX, scaledAccentY, patternTransform);
- }
- }
- }
- var charWidth = width * widthAdvanceScale + spacing * fontDirection;
- x += charWidth;
- if (restoreNeeded) {
- ctx.restore();
- }
- }
- if (vertical) {
- current.y -= x * textHScale;
- } else {
- current.x += x * textHScale;
- }
- ctx.restore();
- },
- showType3Text: function CanvasGraphics_showType3Text(glyphs) {
- var ctx = this.ctx;
- var current = this.current;
- var font = current.font;
- var fontSize = current.fontSize;
- var fontDirection = current.fontDirection;
- var spacingDir = font.vertical ? 1 : -1;
- var charSpacing = current.charSpacing;
- var wordSpacing = current.wordSpacing;
- var textHScale = current.textHScale * fontDirection;
- var fontMatrix = current.fontMatrix || _util.FONT_IDENTITY_MATRIX;
- var glyphsLength = glyphs.length;
- var isTextInvisible = current.textRenderingMode === _util.TextRenderingMode.INVISIBLE;
- var i, glyph, width, spacingLength;
- if (isTextInvisible || fontSize === 0) {
- return;
- }
- this._cachedGetSinglePixelWidth = null;
- ctx.save();
- ctx.transform.apply(ctx, current.textMatrix);
- ctx.translate(current.x, current.y);
- ctx.scale(textHScale, fontDirection);
- for (i = 0; i < glyphsLength; ++i) {
- glyph = glyphs[i];
- if ((0, _util.isNum)(glyph)) {
- spacingLength = spacingDir * glyph * fontSize / 1000;
- this.ctx.translate(spacingLength, 0);
- current.x += spacingLength * textHScale;
- continue;
- }
- var spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
- var operatorList = font.charProcOperatorList[glyph.operatorListId];
- if (!operatorList) {
- (0, _util.warn)('Type3 character "' + glyph.operatorListId + '" is not available.');
- continue;
- }
- this.processingType3 = glyph;
- this.save();
- ctx.scale(fontSize, fontSize);
- ctx.transform.apply(ctx, fontMatrix);
- this.executeOperatorList(operatorList);
- this.restore();
- var transformed = _util.Util.applyTransform([glyph.width, 0], fontMatrix);
- width = transformed[0] * fontSize + spacing;
- ctx.translate(width, 0);
- current.x += width * textHScale;
- }
- ctx.restore();
- this.processingType3 = null;
- },
- setCharWidth: function CanvasGraphics_setCharWidth(xWidth, yWidth) {},
- setCharWidthAndBounds: function CanvasGraphics_setCharWidthAndBounds(xWidth, yWidth, llx, lly, urx, ury) {
- this.ctx.rect(llx, lly, urx - llx, ury - lly);
- this.clip();
- this.endPath();
- },
- getColorN_Pattern: function CanvasGraphics_getColorN_Pattern(IR) {
- var _this = this;
-
- var pattern;
- if (IR[0] === 'TilingPattern') {
- var color = IR[1];
- var baseTransform = this.baseTransform || this.ctx.mozCurrentTransform.slice();
- var canvasGraphicsFactory = {
- createCanvasGraphics: function createCanvasGraphics(ctx) {
- return new CanvasGraphics(ctx, _this.commonObjs, _this.objs, _this.canvasFactory, _this.webGLContext);
- }
- };
- pattern = new _pattern_helper.TilingPattern(IR, color, this.ctx, canvasGraphicsFactory, baseTransform);
- } else {
- pattern = (0, _pattern_helper.getShadingPatternFromIR)(IR);
- }
- return pattern;
- },
- setStrokeColorN: function CanvasGraphics_setStrokeColorN() {
- this.current.strokeColor = this.getColorN_Pattern(arguments);
- },
- setFillColorN: function CanvasGraphics_setFillColorN() {
- this.current.fillColor = this.getColorN_Pattern(arguments);
- this.current.patternFill = true;
- },
- setStrokeRGBColor: function CanvasGraphics_setStrokeRGBColor(r, g, b) {
- var color = _util.Util.makeCssRgb(r, g, b);
- this.ctx.strokeStyle = color;
- this.current.strokeColor = color;
- },
- setFillRGBColor: function CanvasGraphics_setFillRGBColor(r, g, b) {
- var color = _util.Util.makeCssRgb(r, g, b);
- this.ctx.fillStyle = color;
- this.current.fillColor = color;
- this.current.patternFill = false;
- },
- shadingFill: function CanvasGraphics_shadingFill(patternIR) {
- var ctx = this.ctx;
- this.save();
- var pattern = (0, _pattern_helper.getShadingPatternFromIR)(patternIR);
- ctx.fillStyle = pattern.getPattern(ctx, this, true);
- var inv = ctx.mozCurrentTransformInverse;
- if (inv) {
- var canvas = ctx.canvas;
- var width = canvas.width;
- var height = canvas.height;
- var bl = _util.Util.applyTransform([0, 0], inv);
- var br = _util.Util.applyTransform([0, height], inv);
- var ul = _util.Util.applyTransform([width, 0], inv);
- var ur = _util.Util.applyTransform([width, height], inv);
- var x0 = Math.min(bl[0], br[0], ul[0], ur[0]);
- var y0 = Math.min(bl[1], br[1], ul[1], ur[1]);
- var x1 = Math.max(bl[0], br[0], ul[0], ur[0]);
- var y1 = Math.max(bl[1], br[1], ul[1], ur[1]);
- this.ctx.fillRect(x0, y0, x1 - x0, y1 - y0);
- } else {
- this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10);
- }
- this.restore();
- },
- beginInlineImage: function CanvasGraphics_beginInlineImage() {
- (0, _util.unreachable)('Should not call beginInlineImage');
- },
- beginImageData: function CanvasGraphics_beginImageData() {
- (0, _util.unreachable)('Should not call beginImageData');
- },
- paintFormXObjectBegin: function CanvasGraphics_paintFormXObjectBegin(matrix, bbox) {
- this.save();
- this.baseTransformStack.push(this.baseTransform);
- if (Array.isArray(matrix) && matrix.length === 6) {
- this.transform.apply(this, matrix);
- }
- this.baseTransform = this.ctx.mozCurrentTransform;
- if (Array.isArray(bbox) && bbox.length === 4) {
- var width = bbox[2] - bbox[0];
- var height = bbox[3] - bbox[1];
- this.ctx.rect(bbox[0], bbox[1], width, height);
- this.clip();
- this.endPath();
- }
- },
- paintFormXObjectEnd: function CanvasGraphics_paintFormXObjectEnd() {
- this.restore();
- this.baseTransform = this.baseTransformStack.pop();
- },
- beginGroup: function CanvasGraphics_beginGroup(group) {
- this.save();
- var currentCtx = this.ctx;
- if (!group.isolated) {
- (0, _util.info)('TODO: Support non-isolated groups.');
- }
- if (group.knockout) {
- (0, _util.warn)('Knockout groups not supported.');
- }
- var currentTransform = currentCtx.mozCurrentTransform;
- if (group.matrix) {
- currentCtx.transform.apply(currentCtx, group.matrix);
- }
- if (!group.bbox) {
- throw new Error('Bounding box is required.');
- }
- var bounds = _util.Util.getAxialAlignedBoundingBox(group.bbox, currentCtx.mozCurrentTransform);
- var canvasBounds = [0, 0, currentCtx.canvas.width, currentCtx.canvas.height];
- bounds = _util.Util.intersect(bounds, canvasBounds) || [0, 0, 0, 0];
- var offsetX = Math.floor(bounds[0]);
- var offsetY = Math.floor(bounds[1]);
- var drawnWidth = Math.max(Math.ceil(bounds[2]) - offsetX, 1);
- var drawnHeight = Math.max(Math.ceil(bounds[3]) - offsetY, 1);
- var scaleX = 1,
- scaleY = 1;
- if (drawnWidth > MAX_GROUP_SIZE) {
- scaleX = drawnWidth / MAX_GROUP_SIZE;
- drawnWidth = MAX_GROUP_SIZE;
- }
- if (drawnHeight > MAX_GROUP_SIZE) {
- scaleY = drawnHeight / MAX_GROUP_SIZE;
- drawnHeight = MAX_GROUP_SIZE;
- }
- var cacheId = 'groupAt' + this.groupLevel;
- if (group.smask) {
- cacheId += '_smask_' + this.smaskCounter++ % 2;
- }
- var scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight, true);
- var groupCtx = scratchCanvas.context;
- groupCtx.scale(1 / scaleX, 1 / scaleY);
- groupCtx.translate(-offsetX, -offsetY);
- groupCtx.transform.apply(groupCtx, currentTransform);
- if (group.smask) {
- this.smaskStack.push({
- canvas: scratchCanvas.canvas,
- context: groupCtx,
- offsetX: offsetX,
- offsetY: offsetY,
- scaleX: scaleX,
- scaleY: scaleY,
- subtype: group.smask.subtype,
- backdrop: group.smask.backdrop,
- transferMap: group.smask.transferMap || null,
- startTransformInverse: null
- });
- } else {
- currentCtx.setTransform(1, 0, 0, 1, 0, 0);
- currentCtx.translate(offsetX, offsetY);
- currentCtx.scale(scaleX, scaleY);
- }
- copyCtxState(currentCtx, groupCtx);
- this.ctx = groupCtx;
- this.setGState([['BM', 'source-over'], ['ca', 1], ['CA', 1]]);
- this.groupStack.push(currentCtx);
- this.groupLevel++;
- this.current.activeSMask = null;
- },
- endGroup: function CanvasGraphics_endGroup(group) {
- this.groupLevel--;
- var groupCtx = this.ctx;
- this.ctx = this.groupStack.pop();
- if (this.ctx.imageSmoothingEnabled !== undefined) {
- this.ctx.imageSmoothingEnabled = false;
- } else {
- this.ctx.mozImageSmoothingEnabled = false;
- }
- if (group.smask) {
- this.tempSMask = this.smaskStack.pop();
- } else {
- this.ctx.drawImage(groupCtx.canvas, 0, 0);
- }
- this.restore();
- },
- beginAnnotations: function CanvasGraphics_beginAnnotations() {
- this.save();
- if (this.baseTransform) {
- this.ctx.setTransform.apply(this.ctx, this.baseTransform);
- }
- },
- endAnnotations: function CanvasGraphics_endAnnotations() {
- this.restore();
- },
- beginAnnotation: function CanvasGraphics_beginAnnotation(rect, transform, matrix) {
- this.save();
- resetCtxToDefault(this.ctx);
- this.current = new CanvasExtraState();
- if (Array.isArray(rect) && rect.length === 4) {
- var width = rect[2] - rect[0];
- var height = rect[3] - rect[1];
- this.ctx.rect(rect[0], rect[1], width, height);
- this.clip();
- this.endPath();
- }
- this.transform.apply(this, transform);
- this.transform.apply(this, matrix);
- },
- endAnnotation: function CanvasGraphics_endAnnotation() {
- this.restore();
- },
- paintJpegXObject: function CanvasGraphics_paintJpegXObject(objId, w, h) {
- var domImage = this.objs.get(objId);
- if (!domImage) {
- (0, _util.warn)('Dependent image isn\'t ready yet');
- return;
- }
- this.save();
- var ctx = this.ctx;
- ctx.scale(1 / w, -1 / h);
- ctx.drawImage(domImage, 0, 0, domImage.width, domImage.height, 0, -h, w, h);
- if (this.imageLayer) {
- var currentTransform = ctx.mozCurrentTransformInverse;
- var position = this.getCanvasPosition(0, 0);
- this.imageLayer.appendImage({
- objId: objId,
- left: position[0],
- top: position[1],
- width: w / currentTransform[0],
- height: h / currentTransform[3]
- });
- }
- this.restore();
- },
- paintImageMaskXObject: function CanvasGraphics_paintImageMaskXObject(img) {
- var ctx = this.ctx;
- var width = img.width,
- height = img.height;
- var fillColor = this.current.fillColor;
- var isPatternFill = this.current.patternFill;
- var glyph = this.processingType3;
- if (COMPILE_TYPE3_GLYPHS && glyph && glyph.compiled === undefined) {
- if (width <= MAX_SIZE_TO_COMPILE && height <= MAX_SIZE_TO_COMPILE) {
- glyph.compiled = compileType3Glyph({
- data: img.data,
- width: width,
- height: height
- });
- } else {
- glyph.compiled = null;
- }
- }
- if (glyph && glyph.compiled) {
- glyph.compiled(ctx);
- return;
- }
- var maskCanvas = this.cachedCanvases.getCanvas('maskCanvas', width, height);
- var maskCtx = maskCanvas.context;
- maskCtx.save();
- putBinaryImageMask(maskCtx, img);
- maskCtx.globalCompositeOperation = 'source-in';
- maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this) : fillColor;
- maskCtx.fillRect(0, 0, width, height);
- maskCtx.restore();
- this.paintInlineImageXObject(maskCanvas.canvas);
- },
- paintImageMaskXObjectRepeat: function CanvasGraphics_paintImageMaskXObjectRepeat(imgData, scaleX, scaleY, positions) {
- var width = imgData.width;
- var height = imgData.height;
- var fillColor = this.current.fillColor;
- var isPatternFill = this.current.patternFill;
- var maskCanvas = this.cachedCanvases.getCanvas('maskCanvas', width, height);
- var maskCtx = maskCanvas.context;
- maskCtx.save();
- putBinaryImageMask(maskCtx, imgData);
- maskCtx.globalCompositeOperation = 'source-in';
- maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this) : fillColor;
- maskCtx.fillRect(0, 0, width, height);
- maskCtx.restore();
- var ctx = this.ctx;
- for (var i = 0, ii = positions.length; i < ii; i += 2) {
- ctx.save();
- ctx.transform(scaleX, 0, 0, scaleY, positions[i], positions[i + 1]);
- ctx.scale(1, -1);
- ctx.drawImage(maskCanvas.canvas, 0, 0, width, height, 0, -1, 1, 1);
- ctx.restore();
- }
- },
- paintImageMaskXObjectGroup: function CanvasGraphics_paintImageMaskXObjectGroup(images) {
- var ctx = this.ctx;
- var fillColor = this.current.fillColor;
- var isPatternFill = this.current.patternFill;
- for (var i = 0, ii = images.length; i < ii; i++) {
- var image = images[i];
- var width = image.width,
- height = image.height;
- var maskCanvas = this.cachedCanvases.getCanvas('maskCanvas', width, height);
- var maskCtx = maskCanvas.context;
- maskCtx.save();
- putBinaryImageMask(maskCtx, image);
- maskCtx.globalCompositeOperation = 'source-in';
- maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this) : fillColor;
- maskCtx.fillRect(0, 0, width, height);
- maskCtx.restore();
- ctx.save();
- ctx.transform.apply(ctx, image.transform);
- ctx.scale(1, -1);
- ctx.drawImage(maskCanvas.canvas, 0, 0, width, height, 0, -1, 1, 1);
- ctx.restore();
- }
- },
- paintImageXObject: function CanvasGraphics_paintImageXObject(objId) {
- var imgData = this.objs.get(objId);
- if (!imgData) {
- (0, _util.warn)('Dependent image isn\'t ready yet');
- return;
- }
- this.paintInlineImageXObject(imgData);
- },
- paintImageXObjectRepeat: function CanvasGraphics_paintImageXObjectRepeat(objId, scaleX, scaleY, positions) {
- var imgData = this.objs.get(objId);
- if (!imgData) {
- (0, _util.warn)('Dependent image isn\'t ready yet');
- return;
- }
- var width = imgData.width;
- var height = imgData.height;
- var map = [];
- for (var i = 0, ii = positions.length; i < ii; i += 2) {
- map.push({
- transform: [scaleX, 0, 0, scaleY, positions[i], positions[i + 1]],
- x: 0,
- y: 0,
- w: width,
- h: height
- });
- }
- this.paintInlineImageXObjectGroup(imgData, map);
- },
- paintInlineImageXObject: function CanvasGraphics_paintInlineImageXObject(imgData) {
- var width = imgData.width;
- var height = imgData.height;
- var ctx = this.ctx;
- this.save();
- ctx.scale(1 / width, -1 / height);
- var currentTransform = ctx.mozCurrentTransformInverse;
- var a = currentTransform[0],
- b = currentTransform[1];
- var widthScale = Math.max(Math.sqrt(a * a + b * b), 1);
- var c = currentTransform[2],
- d = currentTransform[3];
- var heightScale = Math.max(Math.sqrt(c * c + d * d), 1);
- var imgToPaint, tmpCanvas;
- if (typeof HTMLElement === 'function' && imgData instanceof HTMLElement || !imgData.data) {
- imgToPaint = imgData;
- } else {
- tmpCanvas = this.cachedCanvases.getCanvas('inlineImage', width, height);
- var tmpCtx = tmpCanvas.context;
- putBinaryImageData(tmpCtx, imgData);
- imgToPaint = tmpCanvas.canvas;
- }
- var paintWidth = width,
- paintHeight = height;
- var tmpCanvasId = 'prescale1';
- while (widthScale > 2 && paintWidth > 1 || heightScale > 2 && paintHeight > 1) {
- var newWidth = paintWidth,
- newHeight = paintHeight;
- if (widthScale > 2 && paintWidth > 1) {
- newWidth = Math.ceil(paintWidth / 2);
- widthScale /= paintWidth / newWidth;
- }
- if (heightScale > 2 && paintHeight > 1) {
- newHeight = Math.ceil(paintHeight / 2);
- heightScale /= paintHeight / newHeight;
- }
- tmpCanvas = this.cachedCanvases.getCanvas(tmpCanvasId, newWidth, newHeight);
- tmpCtx = tmpCanvas.context;
- tmpCtx.clearRect(0, 0, newWidth, newHeight);
- tmpCtx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight, 0, 0, newWidth, newHeight);
- imgToPaint = tmpCanvas.canvas;
- paintWidth = newWidth;
- paintHeight = newHeight;
- tmpCanvasId = tmpCanvasId === 'prescale1' ? 'prescale2' : 'prescale1';
- }
- ctx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight, 0, -height, width, height);
- if (this.imageLayer) {
- var position = this.getCanvasPosition(0, -height);
- this.imageLayer.appendImage({
- imgData: imgData,
- left: position[0],
- top: position[1],
- width: width / currentTransform[0],
- height: height / currentTransform[3]
- });
- }
- this.restore();
- },
- paintInlineImageXObjectGroup: function CanvasGraphics_paintInlineImageXObjectGroup(imgData, map) {
- var ctx = this.ctx;
- var w = imgData.width;
- var h = imgData.height;
- var tmpCanvas = this.cachedCanvases.getCanvas('inlineImage', w, h);
- var tmpCtx = tmpCanvas.context;
- putBinaryImageData(tmpCtx, imgData);
- for (var i = 0, ii = map.length; i < ii; i++) {
- var entry = map[i];
- ctx.save();
- ctx.transform.apply(ctx, entry.transform);
- ctx.scale(1, -1);
- ctx.drawImage(tmpCanvas.canvas, entry.x, entry.y, entry.w, entry.h, 0, -1, 1, 1);
- if (this.imageLayer) {
- var position = this.getCanvasPosition(entry.x, entry.y);
- this.imageLayer.appendImage({
- imgData: imgData,
- left: position[0],
- top: position[1],
- width: w,
- height: h
- });
- }
- ctx.restore();
- }
- },
- paintSolidColorImageMask: function CanvasGraphics_paintSolidColorImageMask() {
- this.ctx.fillRect(0, 0, 1, 1);
- },
- paintXObject: function CanvasGraphics_paintXObject() {
- (0, _util.warn)('Unsupported \'paintXObject\' command.');
- },
- markPoint: function CanvasGraphics_markPoint(tag) {},
- markPointProps: function CanvasGraphics_markPointProps(tag, properties) {},
- beginMarkedContent: function CanvasGraphics_beginMarkedContent(tag) {},
- beginMarkedContentProps: function CanvasGraphics_beginMarkedContentProps(tag, properties) {},
- endMarkedContent: function CanvasGraphics_endMarkedContent() {},
- beginCompat: function CanvasGraphics_beginCompat() {},
- endCompat: function CanvasGraphics_endCompat() {},
- consumePath: function CanvasGraphics_consumePath() {
- var ctx = this.ctx;
- if (this.pendingClip) {
- if (this.pendingClip === EO_CLIP) {
- ctx.clip('evenodd');
- } else {
- ctx.clip();
- }
- this.pendingClip = null;
- }
- ctx.beginPath();
- },
- getSinglePixelWidth: function getSinglePixelWidth(scale) {
- if (this._cachedGetSinglePixelWidth === null) {
- var inverse = this.ctx.mozCurrentTransformInverse;
- this._cachedGetSinglePixelWidth = Math.sqrt(Math.max(inverse[0] * inverse[0] + inverse[1] * inverse[1], inverse[2] * inverse[2] + inverse[3] * inverse[3]));
- }
- return this._cachedGetSinglePixelWidth;
- },
-
- getCanvasPosition: function CanvasGraphics_getCanvasPosition(x, y) {
- var transform = this.ctx.mozCurrentTransform;
- return [transform[0] * x + transform[2] * y + transform[4], transform[1] * x + transform[3] * y + transform[5]];
- }
- };
- for (var op in _util.OPS) {
- CanvasGraphics.prototype[_util.OPS[op]] = CanvasGraphics.prototype[op];
- }
- return CanvasGraphics;
-}();
-exports.CanvasGraphics = CanvasGraphics;
-
-/***/ }),
-/* 134 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.TilingPattern = exports.getShadingPatternFromIR = undefined;
-
-var _util = __w_pdfjs_require__(1);
-
-var ShadingIRs = {};
-ShadingIRs.RadialAxial = {
- fromIR: function RadialAxial_fromIR(raw) {
- var type = raw[1];
- var colorStops = raw[2];
- var p0 = raw[3];
- var p1 = raw[4];
- var r0 = raw[5];
- var r1 = raw[6];
- return {
- type: 'Pattern',
- getPattern: function RadialAxial_getPattern(ctx) {
- var grad;
- if (type === 'axial') {
- grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]);
- } else if (type === 'radial') {
- grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1);
- }
- for (var i = 0, ii = colorStops.length; i < ii; ++i) {
- var c = colorStops[i];
- grad.addColorStop(c[0], c[1]);
- }
- return grad;
- }
- };
- }
-};
-var createMeshCanvas = function createMeshCanvasClosure() {
- function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) {
- var coords = context.coords,
- colors = context.colors;
- var bytes = data.data,
- rowSize = data.width * 4;
- var tmp;
- if (coords[p1 + 1] > coords[p2 + 1]) {
- tmp = p1;
- p1 = p2;
- p2 = tmp;
- tmp = c1;
- c1 = c2;
- c2 = tmp;
- }
- if (coords[p2 + 1] > coords[p3 + 1]) {
- tmp = p2;
- p2 = p3;
- p3 = tmp;
- tmp = c2;
- c2 = c3;
- c3 = tmp;
- }
- if (coords[p1 + 1] > coords[p2 + 1]) {
- tmp = p1;
- p1 = p2;
- p2 = tmp;
- tmp = c1;
- c1 = c2;
- c2 = tmp;
- }
- var x1 = (coords[p1] + context.offsetX) * context.scaleX;
- var y1 = (coords[p1 + 1] + context.offsetY) * context.scaleY;
- var x2 = (coords[p2] + context.offsetX) * context.scaleX;
- var y2 = (coords[p2 + 1] + context.offsetY) * context.scaleY;
- var x3 = (coords[p3] + context.offsetX) * context.scaleX;
- var y3 = (coords[p3 + 1] + context.offsetY) * context.scaleY;
- if (y1 >= y3) {
- return;
- }
- var c1r = colors[c1],
- c1g = colors[c1 + 1],
- c1b = colors[c1 + 2];
- var c2r = colors[c2],
- c2g = colors[c2 + 1],
- c2b = colors[c2 + 2];
- var c3r = colors[c3],
- c3g = colors[c3 + 1],
- c3b = colors[c3 + 2];
- var minY = Math.round(y1),
- maxY = Math.round(y3);
- var xa, car, cag, cab;
- var xb, cbr, cbg, cbb;
- var k;
- for (var y = minY; y <= maxY; y++) {
- if (y < y2) {
- k = y < y1 ? 0 : y1 === y2 ? 1 : (y1 - y) / (y1 - y2);
- xa = x1 - (x1 - x2) * k;
- car = c1r - (c1r - c2r) * k;
- cag = c1g - (c1g - c2g) * k;
- cab = c1b - (c1b - c2b) * k;
- } else {
- k = y > y3 ? 1 : y2 === y3 ? 0 : (y2 - y) / (y2 - y3);
- xa = x2 - (x2 - x3) * k;
- car = c2r - (c2r - c3r) * k;
- cag = c2g - (c2g - c3g) * k;
- cab = c2b - (c2b - c3b) * k;
- }
- k = y < y1 ? 0 : y > y3 ? 1 : (y1 - y) / (y1 - y3);
- xb = x1 - (x1 - x3) * k;
- cbr = c1r - (c1r - c3r) * k;
- cbg = c1g - (c1g - c3g) * k;
- cbb = c1b - (c1b - c3b) * k;
- var x1_ = Math.round(Math.min(xa, xb));
- var x2_ = Math.round(Math.max(xa, xb));
- var j = rowSize * y + x1_ * 4;
- for (var x = x1_; x <= x2_; x++) {
- k = (xa - x) / (xa - xb);
- k = k < 0 ? 0 : k > 1 ? 1 : k;
- bytes[j++] = car - (car - cbr) * k | 0;
- bytes[j++] = cag - (cag - cbg) * k | 0;
- bytes[j++] = cab - (cab - cbb) * k | 0;
- bytes[j++] = 255;
- }
- }
- }
- function drawFigure(data, figure, context) {
- var ps = figure.coords;
- var cs = figure.colors;
- var i, ii;
- switch (figure.type) {
- case 'lattice':
- var verticesPerRow = figure.verticesPerRow;
- var rows = Math.floor(ps.length / verticesPerRow) - 1;
- var cols = verticesPerRow - 1;
- for (i = 0; i < rows; i++) {
- var q = i * verticesPerRow;
- for (var j = 0; j < cols; j++, q++) {
- drawTriangle(data, context, ps[q], ps[q + 1], ps[q + verticesPerRow], cs[q], cs[q + 1], cs[q + verticesPerRow]);
- drawTriangle(data, context, ps[q + verticesPerRow + 1], ps[q + 1], ps[q + verticesPerRow], cs[q + verticesPerRow + 1], cs[q + 1], cs[q + verticesPerRow]);
- }
- }
- break;
- case 'triangles':
- for (i = 0, ii = ps.length; i < ii; i += 3) {
- drawTriangle(data, context, ps[i], ps[i + 1], ps[i + 2], cs[i], cs[i + 1], cs[i + 2]);
- }
- break;
- default:
- throw new Error('illegal figure');
- }
- }
- function createMeshCanvas(bounds, combinesScale, coords, colors, figures, backgroundColor, cachedCanvases, webGLContext) {
- var EXPECTED_SCALE = 1.1;
- var MAX_PATTERN_SIZE = 3000;
- var BORDER_SIZE = 2;
- var offsetX = Math.floor(bounds[0]);
- var offsetY = Math.floor(bounds[1]);
- var boundsWidth = Math.ceil(bounds[2]) - offsetX;
- var boundsHeight = Math.ceil(bounds[3]) - offsetY;
- var width = Math.min(Math.ceil(Math.abs(boundsWidth * combinesScale[0] * EXPECTED_SCALE)), MAX_PATTERN_SIZE);
- var height = Math.min(Math.ceil(Math.abs(boundsHeight * combinesScale[1] * EXPECTED_SCALE)), MAX_PATTERN_SIZE);
- var scaleX = boundsWidth / width;
- var scaleY = boundsHeight / height;
- var context = {
- coords: coords,
- colors: colors,
- offsetX: -offsetX,
- offsetY: -offsetY,
- scaleX: 1 / scaleX,
- scaleY: 1 / scaleY
- };
- var paddedWidth = width + BORDER_SIZE * 2;
- var paddedHeight = height + BORDER_SIZE * 2;
- var canvas, tmpCanvas, i, ii;
- if (webGLContext.isEnabled) {
- canvas = webGLContext.drawFigures({
- width: width,
- height: height,
- backgroundColor: backgroundColor,
- figures: figures,
- context: context
- });
- tmpCanvas = cachedCanvases.getCanvas('mesh', paddedWidth, paddedHeight, false);
- tmpCanvas.context.drawImage(canvas, BORDER_SIZE, BORDER_SIZE);
- canvas = tmpCanvas.canvas;
- } else {
- tmpCanvas = cachedCanvases.getCanvas('mesh', paddedWidth, paddedHeight, false);
- var tmpCtx = tmpCanvas.context;
- var data = tmpCtx.createImageData(width, height);
- if (backgroundColor) {
- var bytes = data.data;
- for (i = 0, ii = bytes.length; i < ii; i += 4) {
- bytes[i] = backgroundColor[0];
- bytes[i + 1] = backgroundColor[1];
- bytes[i + 2] = backgroundColor[2];
- bytes[i + 3] = 255;
- }
- }
- for (i = 0; i < figures.length; i++) {
- drawFigure(data, figures[i], context);
- }
- tmpCtx.putImageData(data, BORDER_SIZE, BORDER_SIZE);
- canvas = tmpCanvas.canvas;
- }
- return {
- canvas: canvas,
- offsetX: offsetX - BORDER_SIZE * scaleX,
- offsetY: offsetY - BORDER_SIZE * scaleY,
- scaleX: scaleX,
- scaleY: scaleY
- };
- }
- return createMeshCanvas;
-}();
-ShadingIRs.Mesh = {
- fromIR: function Mesh_fromIR(raw) {
- var coords = raw[2];
- var colors = raw[3];
- var figures = raw[4];
- var bounds = raw[5];
- var matrix = raw[6];
- var background = raw[8];
- return {
- type: 'Pattern',
- getPattern: function Mesh_getPattern(ctx, owner, shadingFill) {
- var scale;
- if (shadingFill) {
- scale = _util.Util.singularValueDecompose2dScale(ctx.mozCurrentTransform);
- } else {
- scale = _util.Util.singularValueDecompose2dScale(owner.baseTransform);
- if (matrix) {
- var matrixScale = _util.Util.singularValueDecompose2dScale(matrix);
- scale = [scale[0] * matrixScale[0], scale[1] * matrixScale[1]];
- }
- }
- var temporaryPatternCanvas = createMeshCanvas(bounds, scale, coords, colors, figures, shadingFill ? null : background, owner.cachedCanvases, owner.webGLContext);
- if (!shadingFill) {
- ctx.setTransform.apply(ctx, owner.baseTransform);
- if (matrix) {
- ctx.transform.apply(ctx, matrix);
- }
- }
- ctx.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY);
- ctx.scale(temporaryPatternCanvas.scaleX, temporaryPatternCanvas.scaleY);
- return ctx.createPattern(temporaryPatternCanvas.canvas, 'no-repeat');
- }
- };
- }
-};
-ShadingIRs.Dummy = {
- fromIR: function Dummy_fromIR() {
- return {
- type: 'Pattern',
- getPattern: function Dummy_fromIR_getPattern() {
- return 'hotpink';
- }
- };
- }
-};
-function getShadingPatternFromIR(raw) {
- var shadingIR = ShadingIRs[raw[0]];
- if (!shadingIR) {
- throw new Error('Unknown IR type: ' + raw[0]);
- }
- return shadingIR.fromIR(raw);
-}
-var TilingPattern = function TilingPatternClosure() {
- var PaintType = {
- COLORED: 1,
- UNCOLORED: 2
- };
- var MAX_PATTERN_SIZE = 3000;
- function TilingPattern(IR, color, ctx, canvasGraphicsFactory, baseTransform) {
- this.operatorList = IR[2];
- this.matrix = IR[3] || [1, 0, 0, 1, 0, 0];
- this.bbox = IR[4];
- this.xstep = IR[5];
- this.ystep = IR[6];
- this.paintType = IR[7];
- this.tilingType = IR[8];
- this.color = color;
- this.canvasGraphicsFactory = canvasGraphicsFactory;
- this.baseTransform = baseTransform;
- this.type = 'Pattern';
- this.ctx = ctx;
- }
- TilingPattern.prototype = {
- createPatternCanvas: function TilinPattern_createPatternCanvas(owner) {
- var operatorList = this.operatorList;
- var bbox = this.bbox;
- var xstep = this.xstep;
- var ystep = this.ystep;
- var paintType = this.paintType;
- var tilingType = this.tilingType;
- var color = this.color;
- var canvasGraphicsFactory = this.canvasGraphicsFactory;
- (0, _util.info)('TilingType: ' + tilingType);
- var x0 = bbox[0],
- y0 = bbox[1],
- x1 = bbox[2],
- y1 = bbox[3];
- var topLeft = [x0, y0];
- var botRight = [x0 + xstep, y0 + ystep];
- var width = botRight[0] - topLeft[0];
- var height = botRight[1] - topLeft[1];
- var matrixScale = _util.Util.singularValueDecompose2dScale(this.matrix);
- var curMatrixScale = _util.Util.singularValueDecompose2dScale(this.baseTransform);
- var combinedScale = [matrixScale[0] * curMatrixScale[0], matrixScale[1] * curMatrixScale[1]];
- width = Math.min(Math.ceil(Math.abs(width * combinedScale[0])), MAX_PATTERN_SIZE);
- height = Math.min(Math.ceil(Math.abs(height * combinedScale[1])), MAX_PATTERN_SIZE);
- var tmpCanvas = owner.cachedCanvases.getCanvas('pattern', width, height, true);
- var tmpCtx = tmpCanvas.context;
- var graphics = canvasGraphicsFactory.createCanvasGraphics(tmpCtx);
- graphics.groupLevel = owner.groupLevel;
- this.setFillAndStrokeStyleToContext(graphics, paintType, color);
- this.setScale(width, height, xstep, ystep);
- this.transformToScale(graphics);
- var tmpTranslate = [1, 0, 0, 1, -topLeft[0], -topLeft[1]];
- graphics.transform.apply(graphics, tmpTranslate);
- this.clipBbox(graphics, bbox, x0, y0, x1, y1);
- graphics.executeOperatorList(operatorList);
- return tmpCanvas.canvas;
- },
- setScale: function TilingPattern_setScale(width, height, xstep, ystep) {
- this.scale = [width / xstep, height / ystep];
- },
- transformToScale: function TilingPattern_transformToScale(graphics) {
- var scale = this.scale;
- var tmpScale = [scale[0], 0, 0, scale[1], 0, 0];
- graphics.transform.apply(graphics, tmpScale);
- },
- scaleToContext: function TilingPattern_scaleToContext() {
- var scale = this.scale;
- this.ctx.scale(1 / scale[0], 1 / scale[1]);
- },
- clipBbox: function clipBbox(graphics, bbox, x0, y0, x1, y1) {
- if (Array.isArray(bbox) && bbox.length === 4) {
- var bboxWidth = x1 - x0;
- var bboxHeight = y1 - y0;
- graphics.ctx.rect(x0, y0, bboxWidth, bboxHeight);
- graphics.clip();
- graphics.endPath();
- }
- },
- setFillAndStrokeStyleToContext: function setFillAndStrokeStyleToContext(graphics, paintType, color) {
- var context = graphics.ctx,
- current = graphics.current;
- switch (paintType) {
- case PaintType.COLORED:
- var ctx = this.ctx;
- context.fillStyle = ctx.fillStyle;
- context.strokeStyle = ctx.strokeStyle;
- current.fillColor = ctx.fillStyle;
- current.strokeColor = ctx.strokeStyle;
- break;
- case PaintType.UNCOLORED:
- var cssColor = _util.Util.makeCssRgb(color[0], color[1], color[2]);
- context.fillStyle = cssColor;
- context.strokeStyle = cssColor;
- current.fillColor = cssColor;
- current.strokeColor = cssColor;
- break;
- default:
- throw new _util.FormatError('Unsupported paint type: ' + paintType);
- }
- },
- getPattern: function TilingPattern_getPattern(ctx, owner) {
- var temporaryPatternCanvas = this.createPatternCanvas(owner);
- ctx = this.ctx;
- ctx.setTransform.apply(ctx, this.baseTransform);
- ctx.transform.apply(ctx, this.matrix);
- this.scaleToContext();
- return ctx.createPattern(temporaryPatternCanvas, 'repeat');
- }
- };
- return TilingPattern;
-}();
-exports.getShadingPatternFromIR = getShadingPatternFromIR;
-exports.TilingPattern = TilingPattern;
-
-/***/ }),
-/* 135 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-var GlobalWorkerOptions = Object.create(null);
-GlobalWorkerOptions.workerPort = GlobalWorkerOptions.workerPort === undefined ? null : GlobalWorkerOptions.workerPort;
-GlobalWorkerOptions.workerSrc = GlobalWorkerOptions.workerSrc === undefined ? '' : GlobalWorkerOptions.workerSrc;
-exports.GlobalWorkerOptions = GlobalWorkerOptions;
-
-/***/ }),
-/* 136 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.MessageHandler = undefined;
-
-var _regenerator = __w_pdfjs_require__(137);
-
-var _regenerator2 = _interopRequireDefault(_regenerator);
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-var resolveCall = function () {
- var _ref = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee(fn, args) {
- var thisArg = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
- return _regenerator2.default.wrap(function _callee$(_context) {
- while (1) {
- switch (_context.prev = _context.next) {
- case 0:
- if (fn) {
- _context.next = 2;
- break;
- }
-
- return _context.abrupt('return');
-
- case 2:
- return _context.abrupt('return', fn.apply(thisArg, args));
-
- case 3:
- case 'end':
- return _context.stop();
- }
- }
- }, _callee, this);
- }));
-
- return function resolveCall(_x2, _x3) {
- return _ref.apply(this, arguments);
- };
-}();
-
-var _util = __w_pdfjs_require__(1);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
-
-function wrapReason(reason) {
- if ((typeof reason === 'undefined' ? 'undefined' : _typeof(reason)) !== 'object') {
- return reason;
- }
- switch (reason.name) {
- case 'AbortException':
- return new _util.AbortException(reason.message);
- case 'MissingPDFException':
- return new _util.MissingPDFException(reason.message);
- case 'UnexpectedResponseException':
- return new _util.UnexpectedResponseException(reason.message, reason.status);
- default:
- return new _util.UnknownErrorException(reason.message, reason.details);
- }
-}
-function makeReasonSerializable(reason) {
- if (!(reason instanceof Error) || reason instanceof _util.AbortException || reason instanceof _util.MissingPDFException || reason instanceof _util.UnexpectedResponseException || reason instanceof _util.UnknownErrorException) {
- return reason;
- }
- return new _util.UnknownErrorException(reason.message, reason.toString());
-}
-function resolveOrReject(capability, success, reason) {
- if (success) {
- capability.resolve();
- } else {
- capability.reject(reason);
- }
-}
-function finalize(promise) {
- return Promise.resolve(promise).catch(function () {});
-}
-function MessageHandler(sourceName, targetName, comObj) {
- var _this = this;
-
- this.sourceName = sourceName;
- this.targetName = targetName;
- this.comObj = comObj;
- this.callbackId = 1;
- this.streamId = 1;
- this.postMessageTransfers = true;
- this.streamSinks = Object.create(null);
- this.streamControllers = Object.create(null);
- var callbacksCapabilities = this.callbacksCapabilities = Object.create(null);
- var ah = this.actionHandler = Object.create(null);
- this._onComObjOnMessage = function (event) {
- var data = event.data;
- if (data.targetName !== _this.sourceName) {
- return;
- }
- if (data.stream) {
- _this._processStreamMessage(data);
- } else if (data.isReply) {
- var callbackId = data.callbackId;
- if (data.callbackId in callbacksCapabilities) {
- var callback = callbacksCapabilities[callbackId];
- delete callbacksCapabilities[callbackId];
- if ('error' in data) {
- callback.reject(wrapReason(data.error));
- } else {
- callback.resolve(data.data);
- }
- } else {
- throw new Error('Cannot resolve callback ' + callbackId);
- }
- } else if (data.action in ah) {
- var action = ah[data.action];
- if (data.callbackId) {
- var _sourceName = _this.sourceName;
- var _targetName = data.sourceName;
- Promise.resolve().then(function () {
- return action[0].call(action[1], data.data);
- }).then(function (result) {
- comObj.postMessage({
- sourceName: _sourceName,
- targetName: _targetName,
- isReply: true,
- callbackId: data.callbackId,
- data: result
- });
- }, function (reason) {
- comObj.postMessage({
- sourceName: _sourceName,
- targetName: _targetName,
- isReply: true,
- callbackId: data.callbackId,
- error: makeReasonSerializable(reason)
- });
- });
- } else if (data.streamId) {
- _this._createStreamSink(data);
- } else {
- action[0].call(action[1], data.data);
- }
- } else {
- throw new Error('Unknown action from worker: ' + data.action);
- }
- };
- comObj.addEventListener('message', this._onComObjOnMessage);
-}
-MessageHandler.prototype = {
- on: function on(actionName, handler, scope) {
- var ah = this.actionHandler;
- if (ah[actionName]) {
- throw new Error('There is already an actionName called "' + actionName + '"');
- }
- ah[actionName] = [handler, scope];
- },
- send: function send(actionName, data, transfers) {
- var message = {
- sourceName: this.sourceName,
- targetName: this.targetName,
- action: actionName,
- data: data
- };
- this.postMessage(message, transfers);
- },
- sendWithPromise: function sendWithPromise(actionName, data, transfers) {
- var callbackId = this.callbackId++;
- var message = {
- sourceName: this.sourceName,
- targetName: this.targetName,
- action: actionName,
- data: data,
- callbackId: callbackId
- };
- var capability = (0, _util.createPromiseCapability)();
- this.callbacksCapabilities[callbackId] = capability;
- try {
- this.postMessage(message, transfers);
- } catch (e) {
- capability.reject(e);
- }
- return capability.promise;
- },
- sendWithStream: function sendWithStream(actionName, data, queueingStrategy, transfers) {
- var _this2 = this;
-
- var streamId = this.streamId++;
- var sourceName = this.sourceName;
- var targetName = this.targetName;
- return new _util.ReadableStream({
- start: function start(controller) {
- var startCapability = (0, _util.createPromiseCapability)();
- _this2.streamControllers[streamId] = {
- controller: controller,
- startCall: startCapability,
- isClosed: false
- };
- _this2.postMessage({
- sourceName: sourceName,
- targetName: targetName,
- action: actionName,
- streamId: streamId,
- data: data,
- desiredSize: controller.desiredSize
- });
- return startCapability.promise;
- },
- pull: function pull(controller) {
- var pullCapability = (0, _util.createPromiseCapability)();
- _this2.streamControllers[streamId].pullCall = pullCapability;
- _this2.postMessage({
- sourceName: sourceName,
- targetName: targetName,
- stream: 'pull',
- streamId: streamId,
- desiredSize: controller.desiredSize
- });
- return pullCapability.promise;
- },
- cancel: function cancel(reason) {
- var cancelCapability = (0, _util.createPromiseCapability)();
- _this2.streamControllers[streamId].cancelCall = cancelCapability;
- _this2.streamControllers[streamId].isClosed = true;
- _this2.postMessage({
- sourceName: sourceName,
- targetName: targetName,
- stream: 'cancel',
- reason: reason,
- streamId: streamId
- });
- return cancelCapability.promise;
- }
- }, queueingStrategy);
- },
- _createStreamSink: function _createStreamSink(data) {
- var _this3 = this;
-
- var self = this;
- var action = this.actionHandler[data.action];
- var streamId = data.streamId;
- var desiredSize = data.desiredSize;
- var sourceName = this.sourceName;
- var targetName = data.sourceName;
- var capability = (0, _util.createPromiseCapability)();
- var sendStreamRequest = function sendStreamRequest(_ref2) {
- var stream = _ref2.stream,
- chunk = _ref2.chunk,
- transfers = _ref2.transfers,
- success = _ref2.success,
- reason = _ref2.reason;
-
- _this3.postMessage({
- sourceName: sourceName,
- targetName: targetName,
- stream: stream,
- streamId: streamId,
- chunk: chunk,
- success: success,
- reason: reason
- }, transfers);
- };
- var streamSink = {
- enqueue: function enqueue(chunk) {
- var size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
- var transfers = arguments[2];
-
- if (this.isCancelled) {
- return;
- }
- var lastDesiredSize = this.desiredSize;
- this.desiredSize -= size;
- if (lastDesiredSize > 0 && this.desiredSize <= 0) {
- this.sinkCapability = (0, _util.createPromiseCapability)();
- this.ready = this.sinkCapability.promise;
- }
- sendStreamRequest({
- stream: 'enqueue',
- chunk: chunk,
- transfers: transfers
- });
- },
- close: function close() {
- if (this.isCancelled) {
- return;
- }
- this.isCancelled = true;
- sendStreamRequest({ stream: 'close' });
- delete self.streamSinks[streamId];
- },
- error: function error(reason) {
- if (this.isCancelled) {
- return;
- }
- this.isCancelled = true;
- sendStreamRequest({
- stream: 'error',
- reason: reason
- });
- },
-
- sinkCapability: capability,
- onPull: null,
- onCancel: null,
- isCancelled: false,
- desiredSize: desiredSize,
- ready: null
- };
- streamSink.sinkCapability.resolve();
- streamSink.ready = streamSink.sinkCapability.promise;
- this.streamSinks[streamId] = streamSink;
- resolveCall(action[0], [data.data, streamSink], action[1]).then(function () {
- sendStreamRequest({
- stream: 'start_complete',
- success: true
- });
- }, function (reason) {
- sendStreamRequest({
- stream: 'start_complete',
- success: false,
- reason: reason
- });
- });
- },
- _processStreamMessage: function _processStreamMessage(data) {
- var _this4 = this;
-
- var sourceName = this.sourceName;
- var targetName = data.sourceName;
- var streamId = data.streamId;
- var sendStreamResponse = function sendStreamResponse(_ref3) {
- var stream = _ref3.stream,
- success = _ref3.success,
- reason = _ref3.reason;
-
- _this4.comObj.postMessage({
- sourceName: sourceName,
- targetName: targetName,
- stream: stream,
- success: success,
- streamId: streamId,
- reason: reason
- });
- };
- var deleteStreamController = function deleteStreamController() {
- Promise.all([_this4.streamControllers[data.streamId].startCall, _this4.streamControllers[data.streamId].pullCall, _this4.streamControllers[data.streamId].cancelCall].map(function (capability) {
- return capability && finalize(capability.promise);
- })).then(function () {
- delete _this4.streamControllers[data.streamId];
- });
- };
- switch (data.stream) {
- case 'start_complete':
- resolveOrReject(this.streamControllers[data.streamId].startCall, data.success, wrapReason(data.reason));
- break;
- case 'pull_complete':
- resolveOrReject(this.streamControllers[data.streamId].pullCall, data.success, wrapReason(data.reason));
- break;
- case 'pull':
- if (!this.streamSinks[data.streamId]) {
- sendStreamResponse({
- stream: 'pull_complete',
- success: true
- });
- break;
- }
- if (this.streamSinks[data.streamId].desiredSize <= 0 && data.desiredSize > 0) {
- this.streamSinks[data.streamId].sinkCapability.resolve();
- }
- this.streamSinks[data.streamId].desiredSize = data.desiredSize;
- resolveCall(this.streamSinks[data.streamId].onPull).then(function () {
- sendStreamResponse({
- stream: 'pull_complete',
- success: true
- });
- }, function (reason) {
- sendStreamResponse({
- stream: 'pull_complete',
- success: false,
- reason: reason
- });
- });
- break;
- case 'enqueue':
- (0, _util.assert)(this.streamControllers[data.streamId], 'enqueue should have stream controller');
- if (!this.streamControllers[data.streamId].isClosed) {
- this.streamControllers[data.streamId].controller.enqueue(data.chunk);
- }
- break;
- case 'close':
- (0, _util.assert)(this.streamControllers[data.streamId], 'close should have stream controller');
- if (this.streamControllers[data.streamId].isClosed) {
- break;
- }
- this.streamControllers[data.streamId].isClosed = true;
- this.streamControllers[data.streamId].controller.close();
- deleteStreamController();
- break;
- case 'error':
- (0, _util.assert)(this.streamControllers[data.streamId], 'error should have stream controller');
- this.streamControllers[data.streamId].controller.error(wrapReason(data.reason));
- deleteStreamController();
- break;
- case 'cancel_complete':
- resolveOrReject(this.streamControllers[data.streamId].cancelCall, data.success, wrapReason(data.reason));
- deleteStreamController();
- break;
- case 'cancel':
- if (!this.streamSinks[data.streamId]) {
- break;
- }
- resolveCall(this.streamSinks[data.streamId].onCancel, [wrapReason(data.reason)]).then(function () {
- sendStreamResponse({
- stream: 'cancel_complete',
- success: true
- });
- }, function (reason) {
- sendStreamResponse({
- stream: 'cancel_complete',
- success: false,
- reason: reason
- });
- });
- this.streamSinks[data.streamId].sinkCapability.reject(wrapReason(data.reason));
- this.streamSinks[data.streamId].isCancelled = true;
- delete this.streamSinks[data.streamId];
- break;
- default:
- throw new Error('Unexpected stream case');
- }
- },
- postMessage: function postMessage(message, transfers) {
- if (transfers && this.postMessageTransfers) {
- this.comObj.postMessage(message, transfers);
- } else {
- this.comObj.postMessage(message);
- }
- },
- destroy: function destroy() {
- this.comObj.removeEventListener('message', this._onComObjOnMessage);
- }
-};
-exports.MessageHandler = MessageHandler;
-
-/***/ }),
-/* 137 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = __w_pdfjs_require__(138);
-
-/***/ }),
-/* 138 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var g = function () {
- return this;
-}() || Function("return this")();
-var hadRuntime = g.regeneratorRuntime && Object.getOwnPropertyNames(g).indexOf("regeneratorRuntime") >= 0;
-var oldRuntime = hadRuntime && g.regeneratorRuntime;
-g.regeneratorRuntime = undefined;
-module.exports = __w_pdfjs_require__(139);
-if (hadRuntime) {
- g.regeneratorRuntime = oldRuntime;
-} else {
- try {
- delete g.regeneratorRuntime;
- } catch (e) {
- g.regeneratorRuntime = undefined;
- }
-}
-
-/***/ }),
-/* 139 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-/* WEBPACK VAR INJECTION */(function(module) {
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-!function (global) {
- "use strict";
-
- var Op = Object.prototype;
- var hasOwn = Op.hasOwnProperty;
- var undefined;
- var $Symbol = typeof Symbol === "function" ? Symbol : {};
- var iteratorSymbol = $Symbol.iterator || "@@iterator";
- var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator";
- var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
- var inModule = ( false ? undefined : _typeof(module)) === "object";
- var runtime = global.regeneratorRuntime;
- if (runtime) {
- if (inModule) {
- module.exports = runtime;
- }
- return;
- }
- runtime = global.regeneratorRuntime = inModule ? module.exports : {};
- function wrap(innerFn, outerFn, self, tryLocsList) {
- var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;
- var generator = Object.create(protoGenerator.prototype);
- var context = new Context(tryLocsList || []);
- generator._invoke = makeInvokeMethod(innerFn, self, context);
- return generator;
- }
- runtime.wrap = wrap;
- function tryCatch(fn, obj, arg) {
- try {
- return {
- type: "normal",
- arg: fn.call(obj, arg)
- };
- } catch (err) {
- return {
- type: "throw",
- arg: err
- };
- }
- }
- var GenStateSuspendedStart = "suspendedStart";
- var GenStateSuspendedYield = "suspendedYield";
- var GenStateExecuting = "executing";
- var GenStateCompleted = "completed";
- var ContinueSentinel = {};
- function Generator() {}
- function GeneratorFunction() {}
- function GeneratorFunctionPrototype() {}
- var IteratorPrototype = {};
- IteratorPrototype[iteratorSymbol] = function () {
- return this;
- };
- var getProto = Object.getPrototypeOf;
- var NativeIteratorPrototype = getProto && getProto(getProto(values([])));
- if (NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {
- IteratorPrototype = NativeIteratorPrototype;
- }
- var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
- GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;
- GeneratorFunctionPrototype.constructor = GeneratorFunction;
- GeneratorFunctionPrototype[toStringTagSymbol] = GeneratorFunction.displayName = "GeneratorFunction";
- function defineIteratorMethods(prototype) {
- ["next", "throw", "return"].forEach(function (method) {
- prototype[method] = function (arg) {
- return this._invoke(method, arg);
- };
- });
- }
- runtime.isGeneratorFunction = function (genFun) {
- var ctor = typeof genFun === "function" && genFun.constructor;
- return ctor ? ctor === GeneratorFunction || (ctor.displayName || ctor.name) === "GeneratorFunction" : false;
- };
- runtime.mark = function (genFun) {
- if (Object.setPrototypeOf) {
- Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
- } else {
- genFun.__proto__ = GeneratorFunctionPrototype;
- if (!(toStringTagSymbol in genFun)) {
- genFun[toStringTagSymbol] = "GeneratorFunction";
- }
- }
- genFun.prototype = Object.create(Gp);
- return genFun;
- };
- runtime.awrap = function (arg) {
- return { __await: arg };
- };
- function AsyncIterator(generator) {
- function invoke(method, arg, resolve, reject) {
- var record = tryCatch(generator[method], generator, arg);
- if (record.type === "throw") {
- reject(record.arg);
- } else {
- var result = record.arg;
- var value = result.value;
- if (value && (typeof value === "undefined" ? "undefined" : _typeof(value)) === "object" && hasOwn.call(value, "__await")) {
- return Promise.resolve(value.__await).then(function (value) {
- invoke("next", value, resolve, reject);
- }, function (err) {
- invoke("throw", err, resolve, reject);
- });
- }
- return Promise.resolve(value).then(function (unwrapped) {
- result.value = unwrapped;
- resolve(result);
- }, reject);
- }
- }
- var previousPromise;
- function enqueue(method, arg) {
- function callInvokeWithMethodAndArg() {
- return new Promise(function (resolve, reject) {
- invoke(method, arg, resolve, reject);
- });
- }
- return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
- }
- this._invoke = enqueue;
- }
- defineIteratorMethods(AsyncIterator.prototype);
- AsyncIterator.prototype[asyncIteratorSymbol] = function () {
- return this;
- };
- runtime.AsyncIterator = AsyncIterator;
- runtime.async = function (innerFn, outerFn, self, tryLocsList) {
- var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList));
- return runtime.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) {
- return result.done ? result.value : iter.next();
- });
- };
- function makeInvokeMethod(innerFn, self, context) {
- var state = GenStateSuspendedStart;
- return function invoke(method, arg) {
- if (state === GenStateExecuting) {
- throw new Error("Generator is already running");
- }
- if (state === GenStateCompleted) {
- if (method === "throw") {
- throw arg;
- }
- return doneResult();
- }
- context.method = method;
- context.arg = arg;
- while (true) {
- var delegate = context.delegate;
- if (delegate) {
- var delegateResult = maybeInvokeDelegate(delegate, context);
- if (delegateResult) {
- if (delegateResult === ContinueSentinel) continue;
- return delegateResult;
- }
- }
- if (context.method === "next") {
- context.sent = context._sent = context.arg;
- } else if (context.method === "throw") {
- if (state === GenStateSuspendedStart) {
- state = GenStateCompleted;
- throw context.arg;
- }
- context.dispatchException(context.arg);
- } else if (context.method === "return") {
- context.abrupt("return", context.arg);
- }
- state = GenStateExecuting;
- var record = tryCatch(innerFn, self, context);
- if (record.type === "normal") {
- state = context.done ? GenStateCompleted : GenStateSuspendedYield;
- if (record.arg === ContinueSentinel) {
- continue;
- }
- return {
- value: record.arg,
- done: context.done
- };
- } else if (record.type === "throw") {
- state = GenStateCompleted;
- context.method = "throw";
- context.arg = record.arg;
- }
- }
- };
- }
- function maybeInvokeDelegate(delegate, context) {
- var method = delegate.iterator[context.method];
- if (method === undefined) {
- context.delegate = null;
- if (context.method === "throw") {
- if (delegate.iterator.return) {
- context.method = "return";
- context.arg = undefined;
- maybeInvokeDelegate(delegate, context);
- if (context.method === "throw") {
- return ContinueSentinel;
- }
- }
- context.method = "throw";
- context.arg = new TypeError("The iterator does not provide a 'throw' method");
- }
- return ContinueSentinel;
- }
- var record = tryCatch(method, delegate.iterator, context.arg);
- if (record.type === "throw") {
- context.method = "throw";
- context.arg = record.arg;
- context.delegate = null;
- return ContinueSentinel;
- }
- var info = record.arg;
- if (!info) {
- context.method = "throw";
- context.arg = new TypeError("iterator result is not an object");
- context.delegate = null;
- return ContinueSentinel;
- }
- if (info.done) {
- context[delegate.resultName] = info.value;
- context.next = delegate.nextLoc;
- if (context.method !== "return") {
- context.method = "next";
- context.arg = undefined;
- }
- } else {
- return info;
- }
- context.delegate = null;
- return ContinueSentinel;
- }
- defineIteratorMethods(Gp);
- Gp[toStringTagSymbol] = "Generator";
- Gp[iteratorSymbol] = function () {
- return this;
- };
- Gp.toString = function () {
- return "[object Generator]";
- };
- function pushTryEntry(locs) {
- var entry = { tryLoc: locs[0] };
- if (1 in locs) {
- entry.catchLoc = locs[1];
- }
- if (2 in locs) {
- entry.finallyLoc = locs[2];
- entry.afterLoc = locs[3];
- }
- this.tryEntries.push(entry);
- }
- function resetTryEntry(entry) {
- var record = entry.completion || {};
- record.type = "normal";
- delete record.arg;
- entry.completion = record;
- }
- function Context(tryLocsList) {
- this.tryEntries = [{ tryLoc: "root" }];
- tryLocsList.forEach(pushTryEntry, this);
- this.reset(true);
- }
- runtime.keys = function (object) {
- var keys = [];
- for (var key in object) {
- keys.push(key);
- }
- keys.reverse();
- return function next() {
- while (keys.length) {
- var key = keys.pop();
- if (key in object) {
- next.value = key;
- next.done = false;
- return next;
- }
- }
- next.done = true;
- return next;
- };
- };
- function values(iterable) {
- if (iterable) {
- var iteratorMethod = iterable[iteratorSymbol];
- if (iteratorMethod) {
- return iteratorMethod.call(iterable);
- }
- if (typeof iterable.next === "function") {
- return iterable;
- }
- if (!isNaN(iterable.length)) {
- var i = -1,
- next = function next() {
- while (++i < iterable.length) {
- if (hasOwn.call(iterable, i)) {
- next.value = iterable[i];
- next.done = false;
- return next;
- }
- }
- next.value = undefined;
- next.done = true;
- return next;
- };
- return next.next = next;
- }
- }
- return { next: doneResult };
- }
- runtime.values = values;
- function doneResult() {
- return {
- value: undefined,
- done: true
- };
- }
- Context.prototype = {
- constructor: Context,
- reset: function reset(skipTempReset) {
- this.prev = 0;
- this.next = 0;
- this.sent = this._sent = undefined;
- this.done = false;
- this.delegate = null;
- this.method = "next";
- this.arg = undefined;
- this.tryEntries.forEach(resetTryEntry);
- if (!skipTempReset) {
- for (var name in this) {
- if (name.charAt(0) === "t" && hasOwn.call(this, name) && !isNaN(+name.slice(1))) {
- this[name] = undefined;
- }
- }
- }
- },
- stop: function stop() {
- this.done = true;
- var rootEntry = this.tryEntries[0];
- var rootRecord = rootEntry.completion;
- if (rootRecord.type === "throw") {
- throw rootRecord.arg;
- }
- return this.rval;
- },
- dispatchException: function dispatchException(exception) {
- if (this.done) {
- throw exception;
- }
- var context = this;
- function handle(loc, caught) {
- record.type = "throw";
- record.arg = exception;
- context.next = loc;
- if (caught) {
- context.method = "next";
- context.arg = undefined;
- }
- return !!caught;
- }
- for (var i = this.tryEntries.length - 1; i >= 0; --i) {
- var entry = this.tryEntries[i];
- var record = entry.completion;
- if (entry.tryLoc === "root") {
- return handle("end");
- }
- if (entry.tryLoc <= this.prev) {
- var hasCatch = hasOwn.call(entry, "catchLoc");
- var hasFinally = hasOwn.call(entry, "finallyLoc");
- if (hasCatch && hasFinally) {
- if (this.prev < entry.catchLoc) {
- return handle(entry.catchLoc, true);
- } else if (this.prev < entry.finallyLoc) {
- return handle(entry.finallyLoc);
- }
- } else if (hasCatch) {
- if (this.prev < entry.catchLoc) {
- return handle(entry.catchLoc, true);
- }
- } else if (hasFinally) {
- if (this.prev < entry.finallyLoc) {
- return handle(entry.finallyLoc);
- }
- } else {
- throw new Error("try statement without catch or finally");
- }
- }
- }
- },
- abrupt: function abrupt(type, arg) {
- for (var i = this.tryEntries.length - 1; i >= 0; --i) {
- var entry = this.tryEntries[i];
- if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
- var finallyEntry = entry;
- break;
- }
- }
- if (finallyEntry && (type === "break" || type === "continue") && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc) {
- finallyEntry = null;
- }
- var record = finallyEntry ? finallyEntry.completion : {};
- record.type = type;
- record.arg = arg;
- if (finallyEntry) {
- this.method = "next";
- this.next = finallyEntry.finallyLoc;
- return ContinueSentinel;
- }
- return this.complete(record);
- },
- complete: function complete(record, afterLoc) {
- if (record.type === "throw") {
- throw record.arg;
- }
- if (record.type === "break" || record.type === "continue") {
- this.next = record.arg;
- } else if (record.type === "return") {
- this.rval = this.arg = record.arg;
- this.method = "return";
- this.next = "end";
- } else if (record.type === "normal" && afterLoc) {
- this.next = afterLoc;
- }
- return ContinueSentinel;
- },
- finish: function finish(finallyLoc) {
- for (var i = this.tryEntries.length - 1; i >= 0; --i) {
- var entry = this.tryEntries[i];
- if (entry.finallyLoc === finallyLoc) {
- this.complete(entry.completion, entry.afterLoc);
- resetTryEntry(entry);
- return ContinueSentinel;
- }
- }
- },
- "catch": function _catch(tryLoc) {
- for (var i = this.tryEntries.length - 1; i >= 0; --i) {
- var entry = this.tryEntries[i];
- if (entry.tryLoc === tryLoc) {
- var record = entry.completion;
- if (record.type === "throw") {
- var thrown = record.arg;
- resetTryEntry(entry);
- }
- return thrown;
- }
- }
- throw new Error("illegal catch attempt");
- },
- delegateYield: function delegateYield(iterable, resultName, nextLoc) {
- this.delegate = {
- iterator: values(iterable),
- resultName: resultName,
- nextLoc: nextLoc
- };
- if (this.method === "next") {
- this.arg = undefined;
- }
- return ContinueSentinel;
- }
- };
-}(function () {
- return this;
-}() || Function("return this")());
-/* WEBPACK VAR INJECTION */}.call(this, __w_pdfjs_require__(140)(module)))
-
-/***/ }),
-/* 140 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = function (module) {
- if (!module.webpackPolyfill) {
- module.deprecate = function () {};
- module.paths = [];
- if (!module.children) module.children = [];
- Object.defineProperty(module, "loaded", {
- enumerable: true,
- get: function get() {
- return module.l;
- }
- });
- Object.defineProperty(module, "id", {
- enumerable: true,
- get: function get() {
- return module.i;
- }
- });
- module.webpackPolyfill = 1;
- }
- return module;
-};
-
-/***/ }),
-/* 141 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.Metadata = undefined;
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-var _util = __w_pdfjs_require__(1);
-
-var _xml_parser = __w_pdfjs_require__(142);
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-var Metadata = function () {
- function Metadata(data) {
- _classCallCheck(this, Metadata);
-
- (0, _util.assert)(typeof data === 'string', 'Metadata: input is not a string');
- data = this._repair(data);
- var parser = new _xml_parser.SimpleXMLParser();
- var xmlDocument = parser.parseFromString(data);
- this._metadata = Object.create(null);
- if (xmlDocument) {
- this._parse(xmlDocument);
- }
- }
-
- _createClass(Metadata, [{
- key: '_repair',
- value: function _repair(data) {
- return data.replace(/>\\376\\377([^<]+)/g, function (all, codes) {
- var bytes = codes.replace(/\\([0-3])([0-7])([0-7])/g, function (code, d1, d2, d3) {
- return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1);
- }).replace(/&(amp|apos|gt|lt|quot);/g, function (str, name) {
- switch (name) {
- case 'amp':
- return '&';
- case 'apos':
- return '\'';
- case 'gt':
- return '>';
- case 'lt':
- return '<';
- case 'quot':
- return '\"';
- }
- throw new Error('_repair: ' + name + ' isn\'t defined.');
- });
- var chars = '';
- for (var i = 0, ii = bytes.length; i < ii; i += 2) {
- var code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1);
- if (code >= 32 && code < 127 && code !== 60 && code !== 62 && code !== 38) {
- chars += String.fromCharCode(code);
- } else {
- chars += '&#x' + (0x10000 + code).toString(16).substring(1) + ';';
- }
- }
- return '>' + chars;
- });
- }
- }, {
- key: '_parse',
- value: function _parse(xmlDocument) {
- var rdf = xmlDocument.documentElement;
- if (rdf.nodeName.toLowerCase() !== 'rdf:rdf') {
- rdf = rdf.firstChild;
- while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf') {
- rdf = rdf.nextSibling;
- }
- }
- var nodeName = rdf ? rdf.nodeName.toLowerCase() : null;
- if (!rdf || nodeName !== 'rdf:rdf' || !rdf.hasChildNodes()) {
- return;
- }
- var children = rdf.childNodes;
- for (var i = 0, ii = children.length; i < ii; i++) {
- var desc = children[i];
- if (desc.nodeName.toLowerCase() !== 'rdf:description') {
- continue;
- }
- for (var j = 0, jj = desc.childNodes.length; j < jj; j++) {
- if (desc.childNodes[j].nodeName.toLowerCase() !== '#text') {
- var entry = desc.childNodes[j];
- var name = entry.nodeName.toLowerCase();
- this._metadata[name] = entry.textContent.trim();
- }
- }
- }
- }
- }, {
- key: 'get',
- value: function get(name) {
- return this._metadata[name] || null;
- }
- }, {
- key: 'getAll',
- value: function getAll() {
- return this._metadata;
- }
- }, {
- key: 'has',
- value: function has(name) {
- return typeof this._metadata[name] !== 'undefined';
- }
- }]);
-
- return Metadata;
-}();
-
-exports.Metadata = Metadata;
-
-/***/ }),
-/* 142 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-
-var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
-
-var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
-
-function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-var XMLParserErrorCode = {
- NoError: 0,
- EndOfDocument: -1,
- UnterminatedCdat: -2,
- UnterminatedXmlDeclaration: -3,
- UnterminatedDoctypeDeclaration: -4,
- UnterminatedComment: -5,
- MalformedElement: -6,
- OutOfMemory: -7,
- UnterminatedAttributeValue: -8,
- UnterminatedElement: -9,
- ElementNeverBegun: -10
-};
-function isWhitespace(s, index) {
- var ch = s[index];
- return ch === ' ' || ch === '\n' || ch === '\r' || ch === '\t';
-}
-function isWhitespaceString(s) {
- for (var i = 0, ii = s.length; i < ii; i++) {
- if (!isWhitespace(s, i)) {
- return false;
- }
- }
- return true;
-}
-
-var XMLParserBase = function () {
- function XMLParserBase() {
- _classCallCheck(this, XMLParserBase);
- }
-
- _createClass(XMLParserBase, [{
- key: '_resolveEntities',
- value: function _resolveEntities(s) {
- return s.replace(/&([^;]+);/g, function (all, entity) {
- if (entity.substring(0, 2) === '#x') {
- return String.fromCharCode(parseInt(entity.substring(2), 16));
- } else if (entity.substring(0, 1) === '#') {
- return String.fromCharCode(parseInt(entity.substring(1), 10));
- }
- switch (entity) {
- case 'lt':
- return '<';
- case 'gt':
- return '>';
- case 'amp':
- return '&';
- case 'quot':
- return '\"';
- }
- return this.onResolveEntity(entity);
- });
- }
- }, {
- key: '_parseContent',
- value: function _parseContent(s, start) {
- var pos = start,
- name = void 0,
- attributes = [];
- function skipWs() {
- while (pos < s.length && isWhitespace(s, pos)) {
- ++pos;
- }
- }
- while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== '>' && s[pos] !== '/') {
- ++pos;
- }
- name = s.substring(start, pos);
- skipWs();
- while (pos < s.length && s[pos] !== '>' && s[pos] !== '/' && s[pos] !== '?') {
- skipWs();
- var attrName = '',
- attrValue = '';
- while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== '=') {
- attrName += s[pos];
- ++pos;
- }
- skipWs();
- if (s[pos] !== '=') {
- return null;
- }
- ++pos;
- skipWs();
- var attrEndChar = s[pos];
- if (attrEndChar !== '\"' && attrEndChar !== '\'') {
- return null;
- }
- var attrEndIndex = s.indexOf(attrEndChar, ++pos);
- if (attrEndIndex < 0) {
- return null;
- }
- attrValue = s.substring(pos, attrEndIndex);
- attributes.push({
- name: attrName,
- value: this._resolveEntities(attrValue)
- });
- pos = attrEndIndex + 1;
- skipWs();
- }
- return {
- name: name,
- attributes: attributes,
- parsed: pos - start
- };
- }
- }, {
- key: '_parseProcessingInstruction',
- value: function _parseProcessingInstruction(s, start) {
- var pos = start,
- name = void 0,
- value = void 0;
- function skipWs() {
- while (pos < s.length && isWhitespace(s, pos)) {
- ++pos;
- }
- }
- while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== '>' && s[pos] !== '/') {
- ++pos;
- }
- name = s.substring(start, pos);
- skipWs();
- var attrStart = pos;
- while (pos < s.length && (s[pos] !== '?' || s[pos + 1] !== '>')) {
- ++pos;
- }
- value = s.substring(attrStart, pos);
- return {
- name: name,
- value: value,
- parsed: pos - start
- };
- }
- }, {
- key: 'parseXml',
- value: function parseXml(s) {
- var i = 0;
- while (i < s.length) {
- var ch = s[i];
- var j = i;
- if (ch === '<') {
- ++j;
- var ch2 = s[j];
- var q = void 0;
- switch (ch2) {
- case '/':
- ++j;
- q = s.indexOf('>', j);
- if (q < 0) {
- this.onError(XMLParserErrorCode.UnterminatedElement);
- return;
- }
- this.onEndElement(s.substring(j, q));
- j = q + 1;
- break;
- case '?':
- ++j;
- var pi = this._parseProcessingInstruction(s, j);
- if (s.substring(j + pi.parsed, j + pi.parsed + 2) !== '?>') {
- this.onError(XMLParserErrorCode.UnterminatedXmlDeclaration);
- return;
- }
- this.onPi(pi.name, pi.value);
- j += pi.parsed + 2;
- break;
- case '!':
- if (s.substring(j + 1, j + 3) === '--') {
- q = s.indexOf('-->', j + 3);
- if (q < 0) {
- this.onError(XMLParserErrorCode.UnterminatedComment);
- return;
- }
- this.onComment(s.substring(j + 3, q));
- j = q + 3;
- } else if (s.substring(j + 1, j + 8) === '[CDATA[') {
- q = s.indexOf(']]>', j + 8);
- if (q < 0) {
- this.onError(XMLParserErrorCode.UnterminatedCdat);
- return;
- }
- this.onCdata(s.substring(j + 8, q));
- j = q + 3;
- } else if (s.substring(j + 1, j + 8) === 'DOCTYPE') {
- var q2 = s.indexOf('[', j + 8);
- var complexDoctype = false;
- q = s.indexOf('>', j + 8);
- if (q < 0) {
- this.onError(XMLParserErrorCode.UnterminatedDoctypeDeclaration);
- return;
- }
- if (q2 > 0 && q > q2) {
- q = s.indexOf(']>', j + 8);
- if (q < 0) {
- this.onError(XMLParserErrorCode.UnterminatedDoctypeDeclaration);
- return;
- }
- complexDoctype = true;
- }
- var doctypeContent = s.substring(j + 8, q + (complexDoctype ? 1 : 0));
- this.onDoctype(doctypeContent);
- j = q + (complexDoctype ? 2 : 1);
- } else {
- this.onError(XMLParserErrorCode.MalformedElement);
- return;
- }
- break;
- default:
- var content = this._parseContent(s, j);
- if (content === null) {
- this.onError(XMLParserErrorCode.MalformedElement);
- return;
- }
- var isClosed = false;
- if (s.substring(j + content.parsed, j + content.parsed + 2) === '/>') {
- isClosed = true;
- } else if (s.substring(j + content.parsed, j + content.parsed + 1) !== '>') {
- this.onError(XMLParserErrorCode.UnterminatedElement);
- return;
- }
- this.onBeginElement(content.name, content.attributes, isClosed);
- j += content.parsed + (isClosed ? 2 : 1);
- break;
- }
- } else {
- while (j < s.length && s[j] !== '<') {
- j++;
- }
- var text = s.substring(i, j);
- this.onText(this._resolveEntities(text));
- }
- i = j;
- }
- }
- }, {
- key: 'onResolveEntity',
- value: function onResolveEntity(name) {
- return '&' + name + ';';
- }
- }, {
- key: 'onPi',
- value: function onPi(name, value) {}
- }, {
- key: 'onComment',
- value: function onComment(text) {}
- }, {
- key: 'onCdata',
- value: function onCdata(text) {}
- }, {
- key: 'onDoctype',
- value: function onDoctype(doctypeContent) {}
- }, {
- key: 'onText',
- value: function onText(text) {}
- }, {
- key: 'onBeginElement',
- value: function onBeginElement(name, attributes, isEmpty) {}
- }, {
- key: 'onEndElement',
- value: function onEndElement(name) {}
- }, {
- key: 'onError',
- value: function onError(code) {}
- }]);
-
- return XMLParserBase;
-}();
-
-var SimpleDOMNode = function () {
- function SimpleDOMNode(nodeName, nodeValue) {
- _classCallCheck(this, SimpleDOMNode);
-
- this.nodeName = nodeName;
- this.nodeValue = nodeValue;
- Object.defineProperty(this, 'parentNode', {
- value: null,
- writable: true
- });
- }
-
- _createClass(SimpleDOMNode, [{
- key: 'hasChildNodes',
- value: function hasChildNodes() {
- return this.childNodes && this.childNodes.length > 0;
- }
- }, {
- key: 'firstChild',
- get: function get() {
- return this.childNodes[0];
- }
- }, {
- key: 'nextSibling',
- get: function get() {
- var index = this.parentNode.childNodes.indexOf(this);
- return this.parentNode.childNodes[index + 1];
- }
- }, {
- key: 'textContent',
- get: function get() {
- if (!this.childNodes) {
- return this.nodeValue || '';
- }
- return this.childNodes.map(function (child) {
- return child.textContent;
- }).join('');
- }
- }]);
-
- return SimpleDOMNode;
-}();
-
-var SimpleXMLParser = function (_XMLParserBase) {
- _inherits(SimpleXMLParser, _XMLParserBase);
-
- function SimpleXMLParser() {
- _classCallCheck(this, SimpleXMLParser);
-
- var _this = _possibleConstructorReturn(this, (SimpleXMLParser.__proto__ || Object.getPrototypeOf(SimpleXMLParser)).call(this));
-
- _this._currentFragment = null;
- _this._stack = null;
- _this._errorCode = XMLParserErrorCode.NoError;
- return _this;
- }
-
- _createClass(SimpleXMLParser, [{
- key: 'parseFromString',
- value: function parseFromString(data) {
- this._currentFragment = [];
- this._stack = [];
- this._errorCode = XMLParserErrorCode.NoError;
- this.parseXml(data);
- if (this._errorCode !== XMLParserErrorCode.NoError) {
- return undefined;
- }
-
- var _currentFragment = _slicedToArray(this._currentFragment, 1),
- documentElement = _currentFragment[0];
-
- if (!documentElement) {
- return undefined;
- }
- return { documentElement: documentElement };
- }
- }, {
- key: 'onResolveEntity',
- value: function onResolveEntity(name) {
- switch (name) {
- case 'apos':
- return '\'';
- }
- return _get(SimpleXMLParser.prototype.__proto__ || Object.getPrototypeOf(SimpleXMLParser.prototype), 'onResolveEntity', this).call(this, name);
- }
- }, {
- key: 'onText',
- value: function onText(text) {
- if (isWhitespaceString(text)) {
- return;
- }
- var node = new SimpleDOMNode('#text', text);
- this._currentFragment.push(node);
- }
- }, {
- key: 'onCdata',
- value: function onCdata(text) {
- var node = new SimpleDOMNode('#text', text);
- this._currentFragment.push(node);
- }
- }, {
- key: 'onBeginElement',
- value: function onBeginElement(name, attributes, isEmpty) {
- var node = new SimpleDOMNode(name);
- node.childNodes = [];
- this._currentFragment.push(node);
- if (isEmpty) {
- return;
- }
- this._stack.push(this._currentFragment);
- this._currentFragment = node.childNodes;
- }
- }, {
- key: 'onEndElement',
- value: function onEndElement(name) {
- this._currentFragment = this._stack.pop();
- var lastElement = this._currentFragment[this._currentFragment.length - 1];
- for (var i = 0, ii = lastElement.childNodes.length; i < ii; i++) {
- lastElement.childNodes[i].parentNode = lastElement;
- }
- }
- }, {
- key: 'onError',
- value: function onError(code) {
- this._errorCode = code;
- }
- }]);
-
- return SimpleXMLParser;
-}(XMLParserBase);
-
-exports.SimpleXMLParser = SimpleXMLParser;
-
-/***/ }),
-/* 143 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.PDFDataTransportStream = undefined;
-
-var _regenerator = __w_pdfjs_require__(137);
-
-var _regenerator2 = _interopRequireDefault(_regenerator);
-
-var _util = __w_pdfjs_require__(1);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
-
-var PDFDataTransportStream = function PDFDataTransportStreamClosure() {
- function PDFDataTransportStream(params, pdfDataRangeTransport) {
- var _this = this;
-
- (0, _util.assert)(pdfDataRangeTransport);
- this._queuedChunks = [];
- var initialData = params.initialData;
- if (initialData && initialData.length > 0) {
- var buffer = new Uint8Array(initialData).buffer;
- this._queuedChunks.push(buffer);
- }
- this._pdfDataRangeTransport = pdfDataRangeTransport;
- this._isStreamingSupported = !params.disableStream;
- this._isRangeSupported = !params.disableRange;
- this._contentLength = params.length;
- this._fullRequestReader = null;
- this._rangeReaders = [];
- this._pdfDataRangeTransport.addRangeListener(function (begin, chunk) {
- _this._onReceiveData({
- begin: begin,
- chunk: chunk
- });
- });
- this._pdfDataRangeTransport.addProgressListener(function (loaded) {
- _this._onProgress({ loaded: loaded });
- });
- this._pdfDataRangeTransport.addProgressiveReadListener(function (chunk) {
- _this._onReceiveData({ chunk: chunk });
- });
- this._pdfDataRangeTransport.transportReady();
- }
- PDFDataTransportStream.prototype = {
- _onReceiveData: function PDFDataTransportStream_onReceiveData(args) {
- var buffer = new Uint8Array(args.chunk).buffer;
- if (args.begin === undefined) {
- if (this._fullRequestReader) {
- this._fullRequestReader._enqueue(buffer);
- } else {
- this._queuedChunks.push(buffer);
- }
- } else {
- var found = this._rangeReaders.some(function (rangeReader) {
- if (rangeReader._begin !== args.begin) {
- return false;
- }
- rangeReader._enqueue(buffer);
- return true;
- });
- (0, _util.assert)(found);
- }
- },
- _onProgress: function PDFDataTransportStream_onDataProgress(evt) {
- if (this._rangeReaders.length > 0) {
- var firstReader = this._rangeReaders[0];
- if (firstReader.onProgress) {
- firstReader.onProgress({ loaded: evt.loaded });
- }
- }
- },
- _removeRangeReader: function PDFDataTransportStream_removeRangeReader(reader) {
- var i = this._rangeReaders.indexOf(reader);
- if (i >= 0) {
- this._rangeReaders.splice(i, 1);
- }
- },
- getFullReader: function PDFDataTransportStream_getFullReader() {
- (0, _util.assert)(!this._fullRequestReader);
- var queuedChunks = this._queuedChunks;
- this._queuedChunks = null;
- return new PDFDataTransportStreamReader(this, queuedChunks);
- },
- getRangeReader: function PDFDataTransportStream_getRangeReader(begin, end) {
- var reader = new PDFDataTransportStreamRangeReader(this, begin, end);
- this._pdfDataRangeTransport.requestDataRange(begin, end);
- this._rangeReaders.push(reader);
- return reader;
- },
- cancelAllRequests: function PDFDataTransportStream_cancelAllRequests(reason) {
- if (this._fullRequestReader) {
- this._fullRequestReader.cancel(reason);
- }
- var readers = this._rangeReaders.slice(0);
- readers.forEach(function (rangeReader) {
- rangeReader.cancel(reason);
- });
- this._pdfDataRangeTransport.abort();
- }
- };
- function PDFDataTransportStreamReader(stream, queuedChunks) {
- this._stream = stream;
- this._done = false;
- this._filename = null;
- this._queuedChunks = queuedChunks || [];
- this._requests = [];
- this._headersReady = Promise.resolve();
- stream._fullRequestReader = this;
- this.onProgress = null;
- }
- PDFDataTransportStreamReader.prototype = {
- _enqueue: function PDFDataTransportStreamReader_enqueue(chunk) {
- if (this._done) {
- return;
- }
- if (this._requests.length > 0) {
- var requestCapability = this._requests.shift();
- requestCapability.resolve({
- value: chunk,
- done: false
- });
- return;
- }
- this._queuedChunks.push(chunk);
- },
- get headersReady() {
- return this._headersReady;
- },
- get filename() {
- return this._filename;
- },
- get isRangeSupported() {
- return this._stream._isRangeSupported;
- },
- get isStreamingSupported() {
- return this._stream._isStreamingSupported;
- },
- get contentLength() {
- return this._stream._contentLength;
- },
- read: function () {
- var _ref = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee() {
- var chunk, requestCapability;
- return _regenerator2.default.wrap(function _callee$(_context) {
- while (1) {
- switch (_context.prev = _context.next) {
- case 0:
- if (!(this._queuedChunks.length > 0)) {
- _context.next = 3;
- break;
- }
-
- chunk = this._queuedChunks.shift();
- return _context.abrupt('return', {
- value: chunk,
- done: false
- });
-
- case 3:
- if (!this._done) {
- _context.next = 5;
- break;
- }
-
- return _context.abrupt('return', {
- value: undefined,
- done: true
- });
-
- case 5:
- requestCapability = (0, _util.createPromiseCapability)();
-
- this._requests.push(requestCapability);
- return _context.abrupt('return', requestCapability.promise);
-
- case 8:
- case 'end':
- return _context.stop();
- }
- }
- }, _callee, this);
- }));
-
- function read() {
- return _ref.apply(this, arguments);
- }
-
- return read;
- }(),
-
- cancel: function PDFDataTransportStreamReader_cancel(reason) {
- this._done = true;
- this._requests.forEach(function (requestCapability) {
- requestCapability.resolve({
- value: undefined,
- done: true
- });
- });
- this._requests = [];
- }
- };
- function PDFDataTransportStreamRangeReader(stream, begin, end) {
- this._stream = stream;
- this._begin = begin;
- this._end = end;
- this._queuedChunk = null;
- this._requests = [];
- this._done = false;
- this.onProgress = null;
- }
- PDFDataTransportStreamRangeReader.prototype = {
- _enqueue: function PDFDataTransportStreamRangeReader_enqueue(chunk) {
- if (this._done) {
- return;
- }
- if (this._requests.length === 0) {
- this._queuedChunk = chunk;
- } else {
- var requestsCapability = this._requests.shift();
- requestsCapability.resolve({
- value: chunk,
- done: false
- });
- this._requests.forEach(function (requestCapability) {
- requestCapability.resolve({
- value: undefined,
- done: true
- });
- });
- this._requests = [];
- }
- this._done = true;
- this._stream._removeRangeReader(this);
- },
- get isStreamingSupported() {
- return false;
- },
- read: function () {
- var _ref2 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee2() {
- var chunk, requestCapability;
- return _regenerator2.default.wrap(function _callee2$(_context2) {
- while (1) {
- switch (_context2.prev = _context2.next) {
- case 0:
- if (!this._queuedChunk) {
- _context2.next = 4;
- break;
- }
-
- chunk = this._queuedChunk;
-
- this._queuedChunk = null;
- return _context2.abrupt('return', {
- value: chunk,
- done: false
- });
-
- case 4:
- if (!this._done) {
- _context2.next = 6;
- break;
- }
-
- return _context2.abrupt('return', {
- value: undefined,
- done: true
- });
-
- case 6:
- requestCapability = (0, _util.createPromiseCapability)();
-
- this._requests.push(requestCapability);
- return _context2.abrupt('return', requestCapability.promise);
-
- case 9:
- case 'end':
- return _context2.stop();
- }
- }
- }, _callee2, this);
- }));
-
- function read() {
- return _ref2.apply(this, arguments);
- }
-
- return read;
- }(),
-
- cancel: function PDFDataTransportStreamRangeReader_cancel(reason) {
- this._done = true;
- this._requests.forEach(function (requestCapability) {
- requestCapability.resolve({
- value: undefined,
- done: true
- });
- });
- this._requests = [];
- this._stream._removeRangeReader(this);
- }
- };
- return PDFDataTransportStream;
-}();
-exports.PDFDataTransportStream = PDFDataTransportStream;
-
-/***/ }),
-/* 144 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.WebGLContext = undefined;
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-var _util = __w_pdfjs_require__(1);
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-var WebGLContext = function () {
- function WebGLContext(_ref) {
- var _ref$enable = _ref.enable,
- enable = _ref$enable === undefined ? false : _ref$enable;
-
- _classCallCheck(this, WebGLContext);
-
- this._enabled = enable === true;
- }
-
- _createClass(WebGLContext, [{
- key: 'composeSMask',
- value: function composeSMask(_ref2) {
- var layer = _ref2.layer,
- mask = _ref2.mask,
- properties = _ref2.properties;
-
- return WebGLUtils.composeSMask(layer, mask, properties);
- }
- }, {
- key: 'drawFigures',
- value: function drawFigures(_ref3) {
- var width = _ref3.width,
- height = _ref3.height,
- backgroundColor = _ref3.backgroundColor,
- figures = _ref3.figures,
- context = _ref3.context;
-
- return WebGLUtils.drawFigures(width, height, backgroundColor, figures, context);
- }
- }, {
- key: 'clear',
- value: function clear() {
- WebGLUtils.cleanup();
- }
- }, {
- key: 'isEnabled',
- get: function get() {
- var enabled = this._enabled;
- if (enabled) {
- enabled = WebGLUtils.tryInitGL();
- }
- return (0, _util.shadow)(this, 'isEnabled', enabled);
- }
- }]);
-
- return WebGLContext;
-}();
-
-var WebGLUtils = function WebGLUtilsClosure() {
- function loadShader(gl, code, shaderType) {
- var shader = gl.createShader(shaderType);
- gl.shaderSource(shader, code);
- gl.compileShader(shader);
- var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
- if (!compiled) {
- var errorMsg = gl.getShaderInfoLog(shader);
- throw new Error('Error during shader compilation: ' + errorMsg);
- }
- return shader;
- }
- function createVertexShader(gl, code) {
- return loadShader(gl, code, gl.VERTEX_SHADER);
- }
- function createFragmentShader(gl, code) {
- return loadShader(gl, code, gl.FRAGMENT_SHADER);
- }
- function createProgram(gl, shaders) {
- var program = gl.createProgram();
- for (var i = 0, ii = shaders.length; i < ii; ++i) {
- gl.attachShader(program, shaders[i]);
- }
- gl.linkProgram(program);
- var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
- if (!linked) {
- var errorMsg = gl.getProgramInfoLog(program);
- throw new Error('Error during program linking: ' + errorMsg);
- }
- return program;
- }
- function createTexture(gl, image, textureId) {
- gl.activeTexture(textureId);
- var texture = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, texture);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
- return texture;
- }
- var currentGL, currentCanvas;
- function generateGL() {
- if (currentGL) {
- return;
- }
- currentCanvas = document.createElement('canvas');
- currentGL = currentCanvas.getContext('webgl', { premultipliedalpha: false });
- }
- var smaskVertexShaderCode = '\
- attribute vec2 a_position; \
- attribute vec2 a_texCoord; \
- \
- uniform vec2 u_resolution; \
- \
- varying vec2 v_texCoord; \
- \
- void main() { \
- vec2 clipSpace = (a_position / u_resolution) * 2.0 - 1.0; \
- gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); \
- \
- v_texCoord = a_texCoord; \
- } ';
- var smaskFragmentShaderCode = '\
- precision mediump float; \
- \
- uniform vec4 u_backdrop; \
- uniform int u_subtype; \
- uniform sampler2D u_image; \
- uniform sampler2D u_mask; \
- \
- varying vec2 v_texCoord; \
- \
- void main() { \
- vec4 imageColor = texture2D(u_image, v_texCoord); \
- vec4 maskColor = texture2D(u_mask, v_texCoord); \
- if (u_backdrop.a > 0.0) { \
- maskColor.rgb = maskColor.rgb * maskColor.a + \
- u_backdrop.rgb * (1.0 - maskColor.a); \
- } \
- float lum; \
- if (u_subtype == 0) { \
- lum = maskColor.a; \
- } else { \
- lum = maskColor.r * 0.3 + maskColor.g * 0.59 + \
- maskColor.b * 0.11; \
- } \
- imageColor.a *= lum; \
- imageColor.rgb *= imageColor.a; \
- gl_FragColor = imageColor; \
- } ';
- var smaskCache = null;
- function initSmaskGL() {
- var canvas, gl;
- generateGL();
- canvas = currentCanvas;
- currentCanvas = null;
- gl = currentGL;
- currentGL = null;
- var vertexShader = createVertexShader(gl, smaskVertexShaderCode);
- var fragmentShader = createFragmentShader(gl, smaskFragmentShaderCode);
- var program = createProgram(gl, [vertexShader, fragmentShader]);
- gl.useProgram(program);
- var cache = {};
- cache.gl = gl;
- cache.canvas = canvas;
- cache.resolutionLocation = gl.getUniformLocation(program, 'u_resolution');
- cache.positionLocation = gl.getAttribLocation(program, 'a_position');
- cache.backdropLocation = gl.getUniformLocation(program, 'u_backdrop');
- cache.subtypeLocation = gl.getUniformLocation(program, 'u_subtype');
- var texCoordLocation = gl.getAttribLocation(program, 'a_texCoord');
- var texLayerLocation = gl.getUniformLocation(program, 'u_image');
- var texMaskLocation = gl.getUniformLocation(program, 'u_mask');
- var texCoordBuffer = gl.createBuffer();
- gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0]), gl.STATIC_DRAW);
- gl.enableVertexAttribArray(texCoordLocation);
- gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);
- gl.uniform1i(texLayerLocation, 0);
- gl.uniform1i(texMaskLocation, 1);
- smaskCache = cache;
- }
- function composeSMask(layer, mask, properties) {
- var width = layer.width,
- height = layer.height;
- if (!smaskCache) {
- initSmaskGL();
- }
- var cache = smaskCache,
- canvas = cache.canvas,
- gl = cache.gl;
- canvas.width = width;
- canvas.height = height;
- gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
- gl.uniform2f(cache.resolutionLocation, width, height);
- if (properties.backdrop) {
- gl.uniform4f(cache.resolutionLocation, properties.backdrop[0], properties.backdrop[1], properties.backdrop[2], 1);
- } else {
- gl.uniform4f(cache.resolutionLocation, 0, 0, 0, 0);
- }
- gl.uniform1i(cache.subtypeLocation, properties.subtype === 'Luminosity' ? 1 : 0);
- var texture = createTexture(gl, layer, gl.TEXTURE0);
- var maskTexture = createTexture(gl, mask, gl.TEXTURE1);
- var buffer = gl.createBuffer();
- gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0, width, 0, 0, height, 0, height, width, 0, width, height]), gl.STATIC_DRAW);
- gl.enableVertexAttribArray(cache.positionLocation);
- gl.vertexAttribPointer(cache.positionLocation, 2, gl.FLOAT, false, 0, 0);
- gl.clearColor(0, 0, 0, 0);
- gl.enable(gl.BLEND);
- gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
- gl.clear(gl.COLOR_BUFFER_BIT);
- gl.drawArrays(gl.TRIANGLES, 0, 6);
- gl.flush();
- gl.deleteTexture(texture);
- gl.deleteTexture(maskTexture);
- gl.deleteBuffer(buffer);
- return canvas;
- }
- var figuresVertexShaderCode = '\
- attribute vec2 a_position; \
- attribute vec3 a_color; \
- \
- uniform vec2 u_resolution; \
- uniform vec2 u_scale; \
- uniform vec2 u_offset; \
- \
- varying vec4 v_color; \
- \
- void main() { \
- vec2 position = (a_position + u_offset) * u_scale; \
- vec2 clipSpace = (position / u_resolution) * 2.0 - 1.0; \
- gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); \
- \
- v_color = vec4(a_color / 255.0, 1.0); \
- } ';
- var figuresFragmentShaderCode = '\
- precision mediump float; \
- \
- varying vec4 v_color; \
- \
- void main() { \
- gl_FragColor = v_color; \
- } ';
- var figuresCache = null;
- function initFiguresGL() {
- var canvas, gl;
- generateGL();
- canvas = currentCanvas;
- currentCanvas = null;
- gl = currentGL;
- currentGL = null;
- var vertexShader = createVertexShader(gl, figuresVertexShaderCode);
- var fragmentShader = createFragmentShader(gl, figuresFragmentShaderCode);
- var program = createProgram(gl, [vertexShader, fragmentShader]);
- gl.useProgram(program);
- var cache = {};
- cache.gl = gl;
- cache.canvas = canvas;
- cache.resolutionLocation = gl.getUniformLocation(program, 'u_resolution');
- cache.scaleLocation = gl.getUniformLocation(program, 'u_scale');
- cache.offsetLocation = gl.getUniformLocation(program, 'u_offset');
- cache.positionLocation = gl.getAttribLocation(program, 'a_position');
- cache.colorLocation = gl.getAttribLocation(program, 'a_color');
- figuresCache = cache;
- }
- function drawFigures(width, height, backgroundColor, figures, context) {
- if (!figuresCache) {
- initFiguresGL();
- }
- var cache = figuresCache,
- canvas = cache.canvas,
- gl = cache.gl;
- canvas.width = width;
- canvas.height = height;
- gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
- gl.uniform2f(cache.resolutionLocation, width, height);
- var count = 0;
- var i, ii, rows;
- for (i = 0, ii = figures.length; i < ii; i++) {
- switch (figures[i].type) {
- case 'lattice':
- rows = figures[i].coords.length / figures[i].verticesPerRow | 0;
- count += (rows - 1) * (figures[i].verticesPerRow - 1) * 6;
- break;
- case 'triangles':
- count += figures[i].coords.length;
- break;
- }
- }
- var coords = new Float32Array(count * 2);
- var colors = new Uint8Array(count * 3);
- var coordsMap = context.coords,
- colorsMap = context.colors;
- var pIndex = 0,
- cIndex = 0;
- for (i = 0, ii = figures.length; i < ii; i++) {
- var figure = figures[i],
- ps = figure.coords,
- cs = figure.colors;
- switch (figure.type) {
- case 'lattice':
- var cols = figure.verticesPerRow;
- rows = ps.length / cols | 0;
- for (var row = 1; row < rows; row++) {
- var offset = row * cols + 1;
- for (var col = 1; col < cols; col++, offset++) {
- coords[pIndex] = coordsMap[ps[offset - cols - 1]];
- coords[pIndex + 1] = coordsMap[ps[offset - cols - 1] + 1];
- coords[pIndex + 2] = coordsMap[ps[offset - cols]];
- coords[pIndex + 3] = coordsMap[ps[offset - cols] + 1];
- coords[pIndex + 4] = coordsMap[ps[offset - 1]];
- coords[pIndex + 5] = coordsMap[ps[offset - 1] + 1];
- colors[cIndex] = colorsMap[cs[offset - cols - 1]];
- colors[cIndex + 1] = colorsMap[cs[offset - cols - 1] + 1];
- colors[cIndex + 2] = colorsMap[cs[offset - cols - 1] + 2];
- colors[cIndex + 3] = colorsMap[cs[offset - cols]];
- colors[cIndex + 4] = colorsMap[cs[offset - cols] + 1];
- colors[cIndex + 5] = colorsMap[cs[offset - cols] + 2];
- colors[cIndex + 6] = colorsMap[cs[offset - 1]];
- colors[cIndex + 7] = colorsMap[cs[offset - 1] + 1];
- colors[cIndex + 8] = colorsMap[cs[offset - 1] + 2];
- coords[pIndex + 6] = coords[pIndex + 2];
- coords[pIndex + 7] = coords[pIndex + 3];
- coords[pIndex + 8] = coords[pIndex + 4];
- coords[pIndex + 9] = coords[pIndex + 5];
- coords[pIndex + 10] = coordsMap[ps[offset]];
- coords[pIndex + 11] = coordsMap[ps[offset] + 1];
- colors[cIndex + 9] = colors[cIndex + 3];
- colors[cIndex + 10] = colors[cIndex + 4];
- colors[cIndex + 11] = colors[cIndex + 5];
- colors[cIndex + 12] = colors[cIndex + 6];
- colors[cIndex + 13] = colors[cIndex + 7];
- colors[cIndex + 14] = colors[cIndex + 8];
- colors[cIndex + 15] = colorsMap[cs[offset]];
- colors[cIndex + 16] = colorsMap[cs[offset] + 1];
- colors[cIndex + 17] = colorsMap[cs[offset] + 2];
- pIndex += 12;
- cIndex += 18;
- }
- }
- break;
- case 'triangles':
- for (var j = 0, jj = ps.length; j < jj; j++) {
- coords[pIndex] = coordsMap[ps[j]];
- coords[pIndex + 1] = coordsMap[ps[j] + 1];
- colors[cIndex] = colorsMap[cs[j]];
- colors[cIndex + 1] = colorsMap[cs[j] + 1];
- colors[cIndex + 2] = colorsMap[cs[j] + 2];
- pIndex += 2;
- cIndex += 3;
- }
- break;
- }
- }
- if (backgroundColor) {
- gl.clearColor(backgroundColor[0] / 255, backgroundColor[1] / 255, backgroundColor[2] / 255, 1.0);
- } else {
- gl.clearColor(0, 0, 0, 0);
- }
- gl.clear(gl.COLOR_BUFFER_BIT);
- var coordsBuffer = gl.createBuffer();
- gl.bindBuffer(gl.ARRAY_BUFFER, coordsBuffer);
- gl.bufferData(gl.ARRAY_BUFFER, coords, gl.STATIC_DRAW);
- gl.enableVertexAttribArray(cache.positionLocation);
- gl.vertexAttribPointer(cache.positionLocation, 2, gl.FLOAT, false, 0, 0);
- var colorsBuffer = gl.createBuffer();
- gl.bindBuffer(gl.ARRAY_BUFFER, colorsBuffer);
- gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
- gl.enableVertexAttribArray(cache.colorLocation);
- gl.vertexAttribPointer(cache.colorLocation, 3, gl.UNSIGNED_BYTE, false, 0, 0);
- gl.uniform2f(cache.scaleLocation, context.scaleX, context.scaleY);
- gl.uniform2f(cache.offsetLocation, context.offsetX, context.offsetY);
- gl.drawArrays(gl.TRIANGLES, 0, count);
- gl.flush();
- gl.deleteBuffer(coordsBuffer);
- gl.deleteBuffer(colorsBuffer);
- return canvas;
- }
- return {
- tryInitGL: function tryInitGL() {
- try {
- generateGL();
- return !!currentGL;
- } catch (ex) {}
- return false;
- },
-
- composeSMask: composeSMask,
- drawFigures: drawFigures,
- cleanup: function cleanup() {
- if (smaskCache && smaskCache.canvas) {
- smaskCache.canvas.width = 0;
- smaskCache.canvas.height = 0;
- }
- if (figuresCache && figuresCache.canvas) {
- figuresCache.canvas.width = 0;
- figuresCache.canvas.height = 0;
- }
- smaskCache = null;
- figuresCache = null;
- }
- };
-}();
-exports.WebGLContext = WebGLContext;
-
-/***/ }),
-/* 145 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.renderTextLayer = undefined;
-
-var _util = __w_pdfjs_require__(1);
-
-var _global_scope = __w_pdfjs_require__(3);
-
-var _global_scope2 = _interopRequireDefault(_global_scope);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-var renderTextLayer = function renderTextLayerClosure() {
- var MAX_TEXT_DIVS_TO_RENDER = 100000;
- var NonWhitespaceRegexp = /\S/;
- function isAllWhitespace(str) {
- return !NonWhitespaceRegexp.test(str);
- }
- var styleBuf = ['left: ', 0, 'px; top: ', 0, 'px; font-size: ', 0, 'px; font-family: ', '', ';'];
- function appendText(task, geom, styles) {
- var textDiv = document.createElement('div');
- var textDivProperties = {
- style: null,
- angle: 0,
- canvasWidth: 0,
- isWhitespace: false,
- originalTransform: null,
- paddingBottom: 0,
- paddingLeft: 0,
- paddingRight: 0,
- paddingTop: 0,
- scale: 1
- };
- task._textDivs.push(textDiv);
- if (isAllWhitespace(geom.str)) {
- textDivProperties.isWhitespace = true;
- task._textDivProperties.set(textDiv, textDivProperties);
- return;
- }
- var tx = _util.Util.transform(task._viewport.transform, geom.transform);
- var angle = Math.atan2(tx[1], tx[0]);
- var style = styles[geom.fontName];
- if (style.vertical) {
- angle += Math.PI / 2;
- }
- var fontHeight = Math.sqrt(tx[2] * tx[2] + tx[3] * tx[3]);
- var fontAscent = fontHeight;
- if (style.ascent) {
- fontAscent = style.ascent * fontAscent;
- } else if (style.descent) {
- fontAscent = (1 + style.descent) * fontAscent;
- }
- var left;
- var top;
- if (angle === 0) {
- left = tx[4];
- top = tx[5] - fontAscent;
- } else {
- left = tx[4] + fontAscent * Math.sin(angle);
- top = tx[5] - fontAscent * Math.cos(angle);
- }
- styleBuf[1] = left;
- styleBuf[3] = top;
- styleBuf[5] = fontHeight;
- styleBuf[7] = style.fontFamily;
- textDivProperties.style = styleBuf.join('');
- textDiv.setAttribute('style', textDivProperties.style);
- textDiv.textContent = geom.str;
- if (task._fontInspectorEnabled) {
- textDiv.dataset.fontName = geom.fontName;
- }
- if (angle !== 0) {
- textDivProperties.angle = angle * (180 / Math.PI);
- }
- if (geom.str.length > 1) {
- if (style.vertical) {
- textDivProperties.canvasWidth = geom.height * task._viewport.scale;
- } else {
- textDivProperties.canvasWidth = geom.width * task._viewport.scale;
- }
- }
- task._textDivProperties.set(textDiv, textDivProperties);
- if (task._textContentStream) {
- task._layoutText(textDiv);
- }
- if (task._enhanceTextSelection) {
- var angleCos = 1,
- angleSin = 0;
- if (angle !== 0) {
- angleCos = Math.cos(angle);
- angleSin = Math.sin(angle);
- }
- var divWidth = (style.vertical ? geom.height : geom.width) * task._viewport.scale;
- var divHeight = fontHeight;
- var m, b;
- if (angle !== 0) {
- m = [angleCos, angleSin, -angleSin, angleCos, left, top];
- b = _util.Util.getAxialAlignedBoundingBox([0, 0, divWidth, divHeight], m);
- } else {
- b = [left, top, left + divWidth, top + divHeight];
- }
- task._bounds.push({
- left: b[0],
- top: b[1],
- right: b[2],
- bottom: b[3],
- div: textDiv,
- size: [divWidth, divHeight],
- m: m
- });
- }
- }
- function render(task) {
- if (task._canceled) {
- return;
- }
- var textDivs = task._textDivs;
- var capability = task._capability;
- var textDivsLength = textDivs.length;
- if (textDivsLength > MAX_TEXT_DIVS_TO_RENDER) {
- task._renderingDone = true;
- capability.resolve();
- return;
- }
- if (!task._textContentStream) {
- for (var i = 0; i < textDivsLength; i++) {
- task._layoutText(textDivs[i]);
- }
- }
- task._renderingDone = true;
- capability.resolve();
- }
- function expand(task) {
- var bounds = task._bounds;
- var viewport = task._viewport;
- var expanded = expandBounds(viewport.width, viewport.height, bounds);
- for (var i = 0; i < expanded.length; i++) {
- var div = bounds[i].div;
- var divProperties = task._textDivProperties.get(div);
- if (divProperties.angle === 0) {
- divProperties.paddingLeft = bounds[i].left - expanded[i].left;
- divProperties.paddingTop = bounds[i].top - expanded[i].top;
- divProperties.paddingRight = expanded[i].right - bounds[i].right;
- divProperties.paddingBottom = expanded[i].bottom - bounds[i].bottom;
- task._textDivProperties.set(div, divProperties);
- continue;
- }
- var e = expanded[i],
- b = bounds[i];
- var m = b.m,
- c = m[0],
- s = m[1];
- var points = [[0, 0], [0, b.size[1]], [b.size[0], 0], b.size];
- var ts = new Float64Array(64);
- points.forEach(function (p, i) {
- var t = _util.Util.applyTransform(p, m);
- ts[i + 0] = c && (e.left - t[0]) / c;
- ts[i + 4] = s && (e.top - t[1]) / s;
- ts[i + 8] = c && (e.right - t[0]) / c;
- ts[i + 12] = s && (e.bottom - t[1]) / s;
- ts[i + 16] = s && (e.left - t[0]) / -s;
- ts[i + 20] = c && (e.top - t[1]) / c;
- ts[i + 24] = s && (e.right - t[0]) / -s;
- ts[i + 28] = c && (e.bottom - t[1]) / c;
- ts[i + 32] = c && (e.left - t[0]) / -c;
- ts[i + 36] = s && (e.top - t[1]) / -s;
- ts[i + 40] = c && (e.right - t[0]) / -c;
- ts[i + 44] = s && (e.bottom - t[1]) / -s;
- ts[i + 48] = s && (e.left - t[0]) / s;
- ts[i + 52] = c && (e.top - t[1]) / -c;
- ts[i + 56] = s && (e.right - t[0]) / s;
- ts[i + 60] = c && (e.bottom - t[1]) / -c;
- });
- var findPositiveMin = function findPositiveMin(ts, offset, count) {
- var result = 0;
- for (var i = 0; i < count; i++) {
- var t = ts[offset++];
- if (t > 0) {
- result = result ? Math.min(t, result) : t;
- }
- }
- return result;
- };
- var boxScale = 1 + Math.min(Math.abs(c), Math.abs(s));
- divProperties.paddingLeft = findPositiveMin(ts, 32, 16) / boxScale;
- divProperties.paddingTop = findPositiveMin(ts, 48, 16) / boxScale;
- divProperties.paddingRight = findPositiveMin(ts, 0, 16) / boxScale;
- divProperties.paddingBottom = findPositiveMin(ts, 16, 16) / boxScale;
- task._textDivProperties.set(div, divProperties);
- }
- }
- function expandBounds(width, height, boxes) {
- var bounds = boxes.map(function (box, i) {
- return {
- x1: box.left,
- y1: box.top,
- x2: box.right,
- y2: box.bottom,
- index: i,
- x1New: undefined,
- x2New: undefined
- };
- });
- expandBoundsLTR(width, bounds);
- var expanded = new Array(boxes.length);
- bounds.forEach(function (b) {
- var i = b.index;
- expanded[i] = {
- left: b.x1New,
- top: 0,
- right: b.x2New,
- bottom: 0
- };
- });
- boxes.map(function (box, i) {
- var e = expanded[i],
- b = bounds[i];
- b.x1 = box.top;
- b.y1 = width - e.right;
- b.x2 = box.bottom;
- b.y2 = width - e.left;
- b.index = i;
- b.x1New = undefined;
- b.x2New = undefined;
- });
- expandBoundsLTR(height, bounds);
- bounds.forEach(function (b) {
- var i = b.index;
- expanded[i].top = b.x1New;
- expanded[i].bottom = b.x2New;
- });
- return expanded;
- }
- function expandBoundsLTR(width, bounds) {
- bounds.sort(function (a, b) {
- return a.x1 - b.x1 || a.index - b.index;
- });
- var fakeBoundary = {
- x1: -Infinity,
- y1: -Infinity,
- x2: 0,
- y2: Infinity,
- index: -1,
- x1New: 0,
- x2New: 0
- };
- var horizon = [{
- start: -Infinity,
- end: Infinity,
- boundary: fakeBoundary
- }];
- bounds.forEach(function (boundary) {
- var i = 0;
- while (i < horizon.length && horizon[i].end <= boundary.y1) {
- i++;
- }
- var j = horizon.length - 1;
- while (j >= 0 && horizon[j].start >= boundary.y2) {
- j--;
- }
- var horizonPart, affectedBoundary;
- var q,
- k,
- maxXNew = -Infinity;
- for (q = i; q <= j; q++) {
- horizonPart = horizon[q];
- affectedBoundary = horizonPart.boundary;
- var xNew;
- if (affectedBoundary.x2 > boundary.x1) {
- xNew = affectedBoundary.index > boundary.index ? affectedBoundary.x1New : boundary.x1;
- } else if (affectedBoundary.x2New === undefined) {
- xNew = (affectedBoundary.x2 + boundary.x1) / 2;
- } else {
- xNew = affectedBoundary.x2New;
- }
- if (xNew > maxXNew) {
- maxXNew = xNew;
- }
- }
- boundary.x1New = maxXNew;
- for (q = i; q <= j; q++) {
- horizonPart = horizon[q];
- affectedBoundary = horizonPart.boundary;
- if (affectedBoundary.x2New === undefined) {
- if (affectedBoundary.x2 > boundary.x1) {
- if (affectedBoundary.index > boundary.index) {
- affectedBoundary.x2New = affectedBoundary.x2;
- }
- } else {
- affectedBoundary.x2New = maxXNew;
- }
- } else if (affectedBoundary.x2New > maxXNew) {
- affectedBoundary.x2New = Math.max(maxXNew, affectedBoundary.x2);
- }
- }
- var changedHorizon = [],
- lastBoundary = null;
- for (q = i; q <= j; q++) {
- horizonPart = horizon[q];
- affectedBoundary = horizonPart.boundary;
- var useBoundary = affectedBoundary.x2 > boundary.x2 ? affectedBoundary : boundary;
- if (lastBoundary === useBoundary) {
- changedHorizon[changedHorizon.length - 1].end = horizonPart.end;
- } else {
- changedHorizon.push({
- start: horizonPart.start,
- end: horizonPart.end,
- boundary: useBoundary
- });
- lastBoundary = useBoundary;
- }
- }
- if (horizon[i].start < boundary.y1) {
- changedHorizon[0].start = boundary.y1;
- changedHorizon.unshift({
- start: horizon[i].start,
- end: boundary.y1,
- boundary: horizon[i].boundary
- });
- }
- if (boundary.y2 < horizon[j].end) {
- changedHorizon[changedHorizon.length - 1].end = boundary.y2;
- changedHorizon.push({
- start: boundary.y2,
- end: horizon[j].end,
- boundary: horizon[j].boundary
- });
- }
- for (q = i; q <= j; q++) {
- horizonPart = horizon[q];
- affectedBoundary = horizonPart.boundary;
- if (affectedBoundary.x2New !== undefined) {
- continue;
- }
- var used = false;
- for (k = i - 1; !used && k >= 0 && horizon[k].start >= affectedBoundary.y1; k--) {
- used = horizon[k].boundary === affectedBoundary;
- }
- for (k = j + 1; !used && k < horizon.length && horizon[k].end <= affectedBoundary.y2; k++) {
- used = horizon[k].boundary === affectedBoundary;
- }
- for (k = 0; !used && k < changedHorizon.length; k++) {
- used = changedHorizon[k].boundary === affectedBoundary;
- }
- if (!used) {
- affectedBoundary.x2New = maxXNew;
- }
- }
- Array.prototype.splice.apply(horizon, [i, j - i + 1].concat(changedHorizon));
- });
- horizon.forEach(function (horizonPart) {
- var affectedBoundary = horizonPart.boundary;
- if (affectedBoundary.x2New === undefined) {
- affectedBoundary.x2New = Math.max(width, affectedBoundary.x2);
- }
- });
- }
- function TextLayerRenderTask(_ref) {
- var textContent = _ref.textContent,
- textContentStream = _ref.textContentStream,
- container = _ref.container,
- viewport = _ref.viewport,
- textDivs = _ref.textDivs,
- textContentItemsStr = _ref.textContentItemsStr,
- enhanceTextSelection = _ref.enhanceTextSelection;
-
- this._textContent = textContent;
- this._textContentStream = textContentStream;
- this._container = container;
- this._viewport = viewport;
- this._textDivs = textDivs || [];
- this._textContentItemsStr = textContentItemsStr || [];
- this._enhanceTextSelection = !!enhanceTextSelection;
- this._fontInspectorEnabled = !!(_global_scope2.default.FontInspector && _global_scope2.default.FontInspector.enabled);
- this._reader = null;
- this._layoutTextLastFontSize = null;
- this._layoutTextLastFontFamily = null;
- this._layoutTextCtx = null;
- this._textDivProperties = new WeakMap();
- this._renderingDone = false;
- this._canceled = false;
- this._capability = (0, _util.createPromiseCapability)();
- this._renderTimer = null;
- this._bounds = [];
- }
- TextLayerRenderTask.prototype = {
- get promise() {
- return this._capability.promise;
- },
- cancel: function TextLayer_cancel() {
- if (this._reader) {
- this._reader.cancel(new _util.AbortException('text layer task cancelled'));
- this._reader = null;
- }
- this._canceled = true;
- if (this._renderTimer !== null) {
- clearTimeout(this._renderTimer);
- this._renderTimer = null;
- }
- this._capability.reject('canceled');
- },
- _processItems: function _processItems(items, styleCache) {
- for (var i = 0, len = items.length; i < len; i++) {
- this._textContentItemsStr.push(items[i].str);
- appendText(this, items[i], styleCache);
- }
- },
- _layoutText: function _layoutText(textDiv) {
- var textLayerFrag = this._container;
- var textDivProperties = this._textDivProperties.get(textDiv);
- if (textDivProperties.isWhitespace) {
- return;
- }
- var fontSize = textDiv.style.fontSize;
- var fontFamily = textDiv.style.fontFamily;
- if (fontSize !== this._layoutTextLastFontSize || fontFamily !== this._layoutTextLastFontFamily) {
- this._layoutTextCtx.font = fontSize + ' ' + fontFamily;
- this._layoutTextLastFontSize = fontSize;
- this._layoutTextLastFontFamily = fontFamily;
- }
- var width = this._layoutTextCtx.measureText(textDiv.textContent).width;
- var transform = '';
- if (textDivProperties.canvasWidth !== 0 && width > 0) {
- textDivProperties.scale = textDivProperties.canvasWidth / width;
- transform = 'scaleX(' + textDivProperties.scale + ')';
- }
- if (textDivProperties.angle !== 0) {
- transform = 'rotate(' + textDivProperties.angle + 'deg) ' + transform;
- }
- if (transform !== '') {
- textDivProperties.originalTransform = transform;
- textDiv.style.transform = transform;
- }
- this._textDivProperties.set(textDiv, textDivProperties);
- textLayerFrag.appendChild(textDiv);
- },
-
- _render: function TextLayer_render(timeout) {
- var _this = this;
-
- var capability = (0, _util.createPromiseCapability)();
- var styleCache = Object.create(null);
- var canvas = document.createElement('canvas');
- canvas.mozOpaque = true;
- this._layoutTextCtx = canvas.getContext('2d', { alpha: false });
- if (this._textContent) {
- var textItems = this._textContent.items;
- var textStyles = this._textContent.styles;
- this._processItems(textItems, textStyles);
- capability.resolve();
- } else if (this._textContentStream) {
- var pump = function pump() {
- _this._reader.read().then(function (_ref2) {
- var value = _ref2.value,
- done = _ref2.done;
-
- if (done) {
- capability.resolve();
- return;
- }
- Object.assign(styleCache, value.styles);
- _this._processItems(value.items, styleCache);
- pump();
- }, capability.reject);
- };
- this._reader = this._textContentStream.getReader();
- pump();
- } else {
- throw new Error('Neither "textContent" nor "textContentStream"' + ' parameters specified.');
- }
- capability.promise.then(function () {
- styleCache = null;
- if (!timeout) {
- render(_this);
- } else {
- _this._renderTimer = setTimeout(function () {
- render(_this);
- _this._renderTimer = null;
- }, timeout);
- }
- }, this._capability.reject);
- },
- expandTextDivs: function TextLayer_expandTextDivs(expandDivs) {
- if (!this._enhanceTextSelection || !this._renderingDone) {
- return;
- }
- if (this._bounds !== null) {
- expand(this);
- this._bounds = null;
- }
- for (var i = 0, ii = this._textDivs.length; i < ii; i++) {
- var div = this._textDivs[i];
- var divProperties = this._textDivProperties.get(div);
- if (divProperties.isWhitespace) {
- continue;
- }
- if (expandDivs) {
- var transform = '',
- padding = '';
- if (divProperties.scale !== 1) {
- transform = 'scaleX(' + divProperties.scale + ')';
- }
- if (divProperties.angle !== 0) {
- transform = 'rotate(' + divProperties.angle + 'deg) ' + transform;
- }
- if (divProperties.paddingLeft !== 0) {
- padding += ' padding-left: ' + divProperties.paddingLeft / divProperties.scale + 'px;';
- transform += ' translateX(' + -divProperties.paddingLeft / divProperties.scale + 'px)';
- }
- if (divProperties.paddingTop !== 0) {
- padding += ' padding-top: ' + divProperties.paddingTop + 'px;';
- transform += ' translateY(' + -divProperties.paddingTop + 'px)';
- }
- if (divProperties.paddingRight !== 0) {
- padding += ' padding-right: ' + divProperties.paddingRight / divProperties.scale + 'px;';
- }
- if (divProperties.paddingBottom !== 0) {
- padding += ' padding-bottom: ' + divProperties.paddingBottom + 'px;';
- }
- if (padding !== '') {
- div.setAttribute('style', divProperties.style + padding);
- }
- if (transform !== '') {
- div.style.transform = transform;
- }
- } else {
- div.style.padding = 0;
- div.style.transform = divProperties.originalTransform || '';
- }
- }
- }
- };
- function renderTextLayer(renderParameters) {
- var task = new TextLayerRenderTask({
- textContent: renderParameters.textContent,
- textContentStream: renderParameters.textContentStream,
- container: renderParameters.container,
- viewport: renderParameters.viewport,
- textDivs: renderParameters.textDivs,
- textContentItemsStr: renderParameters.textContentItemsStr,
- enhanceTextSelection: renderParameters.enhanceTextSelection
- });
- task._render(renderParameters.timeout);
- return task;
- }
- return renderTextLayer;
-}();
-exports.renderTextLayer = renderTextLayer;
-
-/***/ }),
-/* 146 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.AnnotationLayer = undefined;
-
-var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-var _dom_utils = __w_pdfjs_require__(130);
-
-var _util = __w_pdfjs_require__(1);
-
-function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
-
-function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-var AnnotationElementFactory = function () {
- function AnnotationElementFactory() {
- _classCallCheck(this, AnnotationElementFactory);
- }
-
- _createClass(AnnotationElementFactory, null, [{
- key: 'create',
- value: function create(parameters) {
- var subtype = parameters.data.annotationType;
- switch (subtype) {
- case _util.AnnotationType.LINK:
- return new LinkAnnotationElement(parameters);
- case _util.AnnotationType.TEXT:
- return new TextAnnotationElement(parameters);
- case _util.AnnotationType.WIDGET:
- var fieldType = parameters.data.fieldType;
- switch (fieldType) {
- case 'Tx':
- return new TextWidgetAnnotationElement(parameters);
- case 'Btn':
- if (parameters.data.radioButton) {
- return new RadioButtonWidgetAnnotationElement(parameters);
- } else if (parameters.data.checkBox) {
- return new CheckboxWidgetAnnotationElement(parameters);
- }
- return new PushButtonWidgetAnnotationElement(parameters);
- case 'Ch':
- return new ChoiceWidgetAnnotationElement(parameters);
- }
- return new WidgetAnnotationElement(parameters);
- case _util.AnnotationType.POPUP:
- return new PopupAnnotationElement(parameters);
- case _util.AnnotationType.LINE:
- return new LineAnnotationElement(parameters);
- case _util.AnnotationType.SQUARE:
- return new SquareAnnotationElement(parameters);
- case _util.AnnotationType.CIRCLE:
- return new CircleAnnotationElement(parameters);
- case _util.AnnotationType.POLYLINE:
- return new PolylineAnnotationElement(parameters);
- case _util.AnnotationType.INK:
- return new InkAnnotationElement(parameters);
- case _util.AnnotationType.POLYGON:
- return new PolygonAnnotationElement(parameters);
- case _util.AnnotationType.HIGHLIGHT:
- return new HighlightAnnotationElement(parameters);
- case _util.AnnotationType.UNDERLINE:
- return new UnderlineAnnotationElement(parameters);
- case _util.AnnotationType.SQUIGGLY:
- return new SquigglyAnnotationElement(parameters);
- case _util.AnnotationType.STRIKEOUT:
- return new StrikeOutAnnotationElement(parameters);
- case _util.AnnotationType.STAMP:
- return new StampAnnotationElement(parameters);
- case _util.AnnotationType.FILEATTACHMENT:
- return new FileAttachmentAnnotationElement(parameters);
- default:
- return new AnnotationElement(parameters);
- }
- }
- }]);
-
- return AnnotationElementFactory;
-}();
-
-var AnnotationElement = function () {
- function AnnotationElement(parameters) {
- var isRenderable = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
- var ignoreBorder = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
-
- _classCallCheck(this, AnnotationElement);
-
- this.isRenderable = isRenderable;
- this.data = parameters.data;
- this.layer = parameters.layer;
- this.page = parameters.page;
- this.viewport = parameters.viewport;
- this.linkService = parameters.linkService;
- this.downloadManager = parameters.downloadManager;
- this.imageResourcesPath = parameters.imageResourcesPath;
- this.renderInteractiveForms = parameters.renderInteractiveForms;
- this.svgFactory = parameters.svgFactory;
- if (isRenderable) {
- this.container = this._createContainer(ignoreBorder);
- }
- }
-
- _createClass(AnnotationElement, [{
- key: '_createContainer',
- value: function _createContainer() {
- var ignoreBorder = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
-
- var data = this.data,
- page = this.page,
- viewport = this.viewport;
- var container = document.createElement('section');
- var width = data.rect[2] - data.rect[0];
- var height = data.rect[3] - data.rect[1];
- container.setAttribute('data-annotation-id', data.id);
- var rect = _util.Util.normalizeRect([data.rect[0], page.view[3] - data.rect[1] + page.view[1], data.rect[2], page.view[3] - data.rect[3] + page.view[1]]);
- container.style.transform = 'matrix(' + viewport.transform.join(',') + ')';
- container.style.transformOrigin = -rect[0] + 'px ' + -rect[1] + 'px';
- if (!ignoreBorder && data.borderStyle.width > 0) {
- container.style.borderWidth = data.borderStyle.width + 'px';
- if (data.borderStyle.style !== _util.AnnotationBorderStyleType.UNDERLINE) {
- width = width - 2 * data.borderStyle.width;
- height = height - 2 * data.borderStyle.width;
- }
- var horizontalRadius = data.borderStyle.horizontalCornerRadius;
- var verticalRadius = data.borderStyle.verticalCornerRadius;
- if (horizontalRadius > 0 || verticalRadius > 0) {
- var radius = horizontalRadius + 'px / ' + verticalRadius + 'px';
- container.style.borderRadius = radius;
- }
- switch (data.borderStyle.style) {
- case _util.AnnotationBorderStyleType.SOLID:
- container.style.borderStyle = 'solid';
- break;
- case _util.AnnotationBorderStyleType.DASHED:
- container.style.borderStyle = 'dashed';
- break;
- case _util.AnnotationBorderStyleType.BEVELED:
- (0, _util.warn)('Unimplemented border style: beveled');
- break;
- case _util.AnnotationBorderStyleType.INSET:
- (0, _util.warn)('Unimplemented border style: inset');
- break;
- case _util.AnnotationBorderStyleType.UNDERLINE:
- container.style.borderBottomStyle = 'solid';
- break;
- default:
- break;
- }
- if (data.color) {
- container.style.borderColor = _util.Util.makeCssRgb(data.color[0] | 0, data.color[1] | 0, data.color[2] | 0);
- } else {
- container.style.borderWidth = 0;
- }
- }
- container.style.left = rect[0] + 'px';
- container.style.top = rect[1] + 'px';
- container.style.width = width + 'px';
- container.style.height = height + 'px';
- return container;
- }
- }, {
- key: '_createPopup',
- value: function _createPopup(container, trigger, data) {
- if (!trigger) {
- trigger = document.createElement('div');
- trigger.style.height = container.style.height;
- trigger.style.width = container.style.width;
- container.appendChild(trigger);
- }
- var popupElement = new PopupElement({
- container: container,
- trigger: trigger,
- color: data.color,
- title: data.title,
- contents: data.contents,
- hideWrapper: true
- });
- var popup = popupElement.render();
- popup.style.left = container.style.width;
- container.appendChild(popup);
- }
- }, {
- key: 'render',
- value: function render() {
- (0, _util.unreachable)('Abstract method `AnnotationElement.render` called');
- }
- }]);
-
- return AnnotationElement;
-}();
-
-var LinkAnnotationElement = function (_AnnotationElement) {
- _inherits(LinkAnnotationElement, _AnnotationElement);
-
- function LinkAnnotationElement(parameters) {
- _classCallCheck(this, LinkAnnotationElement);
-
- var isRenderable = !!(parameters.data.url || parameters.data.dest || parameters.data.action);
- return _possibleConstructorReturn(this, (LinkAnnotationElement.__proto__ || Object.getPrototypeOf(LinkAnnotationElement)).call(this, parameters, isRenderable));
- }
-
- _createClass(LinkAnnotationElement, [{
- key: 'render',
- value: function render() {
- this.container.className = 'linkAnnotation';
- var data = this.data,
- linkService = this.linkService;
-
- var link = document.createElement('a');
- (0, _dom_utils.addLinkAttributes)(link, {
- url: data.url,
- target: data.newWindow ? _dom_utils.LinkTarget.BLANK : linkService.externalLinkTarget,
- rel: linkService.externalLinkRel
- });
- if (!data.url) {
- if (data.action) {
- this._bindNamedAction(link, data.action);
- } else {
- this._bindLink(link, data.dest);
- }
- }
- this.container.appendChild(link);
- return this.container;
- }
- }, {
- key: '_bindLink',
- value: function _bindLink(link, destination) {
- var _this2 = this;
-
- link.href = this.linkService.getDestinationHash(destination);
- link.onclick = function () {
- if (destination) {
- _this2.linkService.navigateTo(destination);
- }
- return false;
- };
- if (destination) {
- link.className = 'internalLink';
- }
- }
- }, {
- key: '_bindNamedAction',
- value: function _bindNamedAction(link, action) {
- var _this3 = this;
-
- link.href = this.linkService.getAnchorUrl('');
- link.onclick = function () {
- _this3.linkService.executeNamedAction(action);
- return false;
- };
- link.className = 'internalLink';
- }
- }]);
-
- return LinkAnnotationElement;
-}(AnnotationElement);
-
-var TextAnnotationElement = function (_AnnotationElement2) {
- _inherits(TextAnnotationElement, _AnnotationElement2);
-
- function TextAnnotationElement(parameters) {
- _classCallCheck(this, TextAnnotationElement);
-
- var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
- return _possibleConstructorReturn(this, (TextAnnotationElement.__proto__ || Object.getPrototypeOf(TextAnnotationElement)).call(this, parameters, isRenderable));
- }
-
- _createClass(TextAnnotationElement, [{
- key: 'render',
- value: function render() {
- this.container.className = 'textAnnotation';
- var image = document.createElement('img');
- image.style.height = this.container.style.height;
- image.style.width = this.container.style.width;
- image.src = this.imageResourcesPath + 'annotation-' + this.data.name.toLowerCase() + '.svg';
- image.alt = '[{{type}} Annotation]';
- image.dataset.l10nId = 'text_annotation_type';
- image.dataset.l10nArgs = JSON.stringify({ type: this.data.name });
- if (!this.data.hasPopup) {
- this._createPopup(this.container, image, this.data);
- }
- this.container.appendChild(image);
- return this.container;
- }
- }]);
-
- return TextAnnotationElement;
-}(AnnotationElement);
-
-var WidgetAnnotationElement = function (_AnnotationElement3) {
- _inherits(WidgetAnnotationElement, _AnnotationElement3);
-
- function WidgetAnnotationElement() {
- _classCallCheck(this, WidgetAnnotationElement);
-
- return _possibleConstructorReturn(this, (WidgetAnnotationElement.__proto__ || Object.getPrototypeOf(WidgetAnnotationElement)).apply(this, arguments));
- }
-
- _createClass(WidgetAnnotationElement, [{
- key: 'render',
- value: function render() {
- return this.container;
- }
- }]);
-
- return WidgetAnnotationElement;
-}(AnnotationElement);
-
-var TextWidgetAnnotationElement = function (_WidgetAnnotationElem) {
- _inherits(TextWidgetAnnotationElement, _WidgetAnnotationElem);
-
- function TextWidgetAnnotationElement(parameters) {
- _classCallCheck(this, TextWidgetAnnotationElement);
-
- var isRenderable = parameters.renderInteractiveForms || !parameters.data.hasAppearance && !!parameters.data.fieldValue;
- return _possibleConstructorReturn(this, (TextWidgetAnnotationElement.__proto__ || Object.getPrototypeOf(TextWidgetAnnotationElement)).call(this, parameters, isRenderable));
- }
-
- _createClass(TextWidgetAnnotationElement, [{
- key: 'render',
- value: function render() {
- var TEXT_ALIGNMENT = ['left', 'center', 'right'];
- this.container.className = 'textWidgetAnnotation';
- var element = null;
- if (this.renderInteractiveForms) {
- if (this.data.multiLine) {
- element = document.createElement('textarea');
- element.textContent = this.data.fieldValue;
- } else {
- element = document.createElement('input');
- element.type = 'text';
- element.setAttribute('value', this.data.fieldValue);
- }
- element.disabled = this.data.readOnly;
- if (this.data.maxLen !== null) {
- element.maxLength = this.data.maxLen;
- }
- if (this.data.comb) {
- var fieldWidth = this.data.rect[2] - this.data.rect[0];
- var combWidth = fieldWidth / this.data.maxLen;
- element.classList.add('comb');
- element.style.letterSpacing = 'calc(' + combWidth + 'px - 1ch)';
- }
- } else {
- element = document.createElement('div');
- element.textContent = this.data.fieldValue;
- element.style.verticalAlign = 'middle';
- element.style.display = 'table-cell';
- var font = null;
- if (this.data.fontRefName) {
- font = this.page.commonObjs.getData(this.data.fontRefName);
- }
- this._setTextStyle(element, font);
- }
- if (this.data.textAlignment !== null) {
- element.style.textAlign = TEXT_ALIGNMENT[this.data.textAlignment];
- }
- this.container.appendChild(element);
- return this.container;
- }
- }, {
- key: '_setTextStyle',
- value: function _setTextStyle(element, font) {
- var style = element.style;
- style.fontSize = this.data.fontSize + 'px';
- style.direction = this.data.fontDirection < 0 ? 'rtl' : 'ltr';
- if (!font) {
- return;
- }
- style.fontWeight = font.black ? font.bold ? '900' : 'bold' : font.bold ? 'bold' : 'normal';
- style.fontStyle = font.italic ? 'italic' : 'normal';
- var fontFamily = font.loadedName ? '"' + font.loadedName + '", ' : '';
- var fallbackName = font.fallbackName || 'Helvetica, sans-serif';
- style.fontFamily = fontFamily + fallbackName;
- }
- }]);
-
- return TextWidgetAnnotationElement;
-}(WidgetAnnotationElement);
-
-var CheckboxWidgetAnnotationElement = function (_WidgetAnnotationElem2) {
- _inherits(CheckboxWidgetAnnotationElement, _WidgetAnnotationElem2);
-
- function CheckboxWidgetAnnotationElement(parameters) {
- _classCallCheck(this, CheckboxWidgetAnnotationElement);
-
- return _possibleConstructorReturn(this, (CheckboxWidgetAnnotationElement.__proto__ || Object.getPrototypeOf(CheckboxWidgetAnnotationElement)).call(this, parameters, parameters.renderInteractiveForms));
- }
-
- _createClass(CheckboxWidgetAnnotationElement, [{
- key: 'render',
- value: function render() {
- this.container.className = 'buttonWidgetAnnotation checkBox';
- var element = document.createElement('input');
- element.disabled = this.data.readOnly;
- element.type = 'checkbox';
- if (this.data.fieldValue && this.data.fieldValue !== 'Off') {
- element.setAttribute('checked', true);
- }
- this.container.appendChild(element);
- return this.container;
- }
- }]);
-
- return CheckboxWidgetAnnotationElement;
-}(WidgetAnnotationElement);
-
-var RadioButtonWidgetAnnotationElement = function (_WidgetAnnotationElem3) {
- _inherits(RadioButtonWidgetAnnotationElement, _WidgetAnnotationElem3);
-
- function RadioButtonWidgetAnnotationElement(parameters) {
- _classCallCheck(this, RadioButtonWidgetAnnotationElement);
-
- return _possibleConstructorReturn(this, (RadioButtonWidgetAnnotationElement.__proto__ || Object.getPrototypeOf(RadioButtonWidgetAnnotationElement)).call(this, parameters, parameters.renderInteractiveForms));
- }
-
- _createClass(RadioButtonWidgetAnnotationElement, [{
- key: 'render',
- value: function render() {
- this.container.className = 'buttonWidgetAnnotation radioButton';
- var element = document.createElement('input');
- element.disabled = this.data.readOnly;
- element.type = 'radio';
- element.name = this.data.fieldName;
- if (this.data.fieldValue === this.data.buttonValue) {
- element.setAttribute('checked', true);
- }
- this.container.appendChild(element);
- return this.container;
- }
- }]);
-
- return RadioButtonWidgetAnnotationElement;
-}(WidgetAnnotationElement);
-
-var PushButtonWidgetAnnotationElement = function (_LinkAnnotationElemen) {
- _inherits(PushButtonWidgetAnnotationElement, _LinkAnnotationElemen);
-
- function PushButtonWidgetAnnotationElement() {
- _classCallCheck(this, PushButtonWidgetAnnotationElement);
-
- return _possibleConstructorReturn(this, (PushButtonWidgetAnnotationElement.__proto__ || Object.getPrototypeOf(PushButtonWidgetAnnotationElement)).apply(this, arguments));
- }
-
- _createClass(PushButtonWidgetAnnotationElement, [{
- key: 'render',
- value: function render() {
- var container = _get(PushButtonWidgetAnnotationElement.prototype.__proto__ || Object.getPrototypeOf(PushButtonWidgetAnnotationElement.prototype), 'render', this).call(this);
- container.className = 'buttonWidgetAnnotation pushButton';
- return container;
- }
- }]);
-
- return PushButtonWidgetAnnotationElement;
-}(LinkAnnotationElement);
-
-var ChoiceWidgetAnnotationElement = function (_WidgetAnnotationElem4) {
- _inherits(ChoiceWidgetAnnotationElement, _WidgetAnnotationElem4);
-
- function ChoiceWidgetAnnotationElement(parameters) {
- _classCallCheck(this, ChoiceWidgetAnnotationElement);
-
- return _possibleConstructorReturn(this, (ChoiceWidgetAnnotationElement.__proto__ || Object.getPrototypeOf(ChoiceWidgetAnnotationElement)).call(this, parameters, parameters.renderInteractiveForms));
- }
-
- _createClass(ChoiceWidgetAnnotationElement, [{
- key: 'render',
- value: function render() {
- this.container.className = 'choiceWidgetAnnotation';
- var selectElement = document.createElement('select');
- selectElement.disabled = this.data.readOnly;
- if (!this.data.combo) {
- selectElement.size = this.data.options.length;
- if (this.data.multiSelect) {
- selectElement.multiple = true;
- }
- }
- for (var i = 0, ii = this.data.options.length; i < ii; i++) {
- var option = this.data.options[i];
- var optionElement = document.createElement('option');
- optionElement.textContent = option.displayValue;
- optionElement.value = option.exportValue;
- if (this.data.fieldValue.includes(option.displayValue)) {
- optionElement.setAttribute('selected', true);
- }
- selectElement.appendChild(optionElement);
- }
- this.container.appendChild(selectElement);
- return this.container;
- }
- }]);
-
- return ChoiceWidgetAnnotationElement;
-}(WidgetAnnotationElement);
-
-var PopupAnnotationElement = function (_AnnotationElement4) {
- _inherits(PopupAnnotationElement, _AnnotationElement4);
-
- function PopupAnnotationElement(parameters) {
- _classCallCheck(this, PopupAnnotationElement);
-
- var isRenderable = !!(parameters.data.title || parameters.data.contents);
- return _possibleConstructorReturn(this, (PopupAnnotationElement.__proto__ || Object.getPrototypeOf(PopupAnnotationElement)).call(this, parameters, isRenderable));
- }
-
- _createClass(PopupAnnotationElement, [{
- key: 'render',
- value: function render() {
- var IGNORE_TYPES = ['Line', 'Square', 'Circle', 'PolyLine', 'Polygon', 'Ink'];
- this.container.className = 'popupAnnotation';
- if (IGNORE_TYPES.includes(this.data.parentType)) {
- return this.container;
- }
- var selector = '[data-annotation-id="' + this.data.parentId + '"]';
- var parentElement = this.layer.querySelector(selector);
- if (!parentElement) {
- return this.container;
- }
- var popup = new PopupElement({
- container: this.container,
- trigger: parentElement,
- color: this.data.color,
- title: this.data.title,
- contents: this.data.contents
- });
- var parentLeft = parseFloat(parentElement.style.left);
- var parentWidth = parseFloat(parentElement.style.width);
- this.container.style.transformOrigin = -(parentLeft + parentWidth) + 'px -' + parentElement.style.top;
- this.container.style.left = parentLeft + parentWidth + 'px';
- this.container.appendChild(popup.render());
- return this.container;
- }
- }]);
-
- return PopupAnnotationElement;
-}(AnnotationElement);
-
-var PopupElement = function () {
- function PopupElement(parameters) {
- _classCallCheck(this, PopupElement);
-
- this.container = parameters.container;
- this.trigger = parameters.trigger;
- this.color = parameters.color;
- this.title = parameters.title;
- this.contents = parameters.contents;
- this.hideWrapper = parameters.hideWrapper || false;
- this.pinned = false;
- }
-
- _createClass(PopupElement, [{
- key: 'render',
- value: function render() {
- var BACKGROUND_ENLIGHT = 0.7;
- var wrapper = document.createElement('div');
- wrapper.className = 'popupWrapper';
- this.hideElement = this.hideWrapper ? wrapper : this.container;
- this.hideElement.setAttribute('hidden', true);
- var popup = document.createElement('div');
- popup.className = 'popup';
- var color = this.color;
- if (color) {
- var r = BACKGROUND_ENLIGHT * (255 - color[0]) + color[0];
- var g = BACKGROUND_ENLIGHT * (255 - color[1]) + color[1];
- var b = BACKGROUND_ENLIGHT * (255 - color[2]) + color[2];
- popup.style.backgroundColor = _util.Util.makeCssRgb(r | 0, g | 0, b | 0);
- }
- var contents = this._formatContents(this.contents);
- var title = document.createElement('h1');
- title.textContent = this.title;
- this.trigger.addEventListener('click', this._toggle.bind(this));
- this.trigger.addEventListener('mouseover', this._show.bind(this, false));
- this.trigger.addEventListener('mouseout', this._hide.bind(this, false));
- popup.addEventListener('click', this._hide.bind(this, true));
- popup.appendChild(title);
- popup.appendChild(contents);
- wrapper.appendChild(popup);
- return wrapper;
- }
- }, {
- key: '_formatContents',
- value: function _formatContents(contents) {
- var p = document.createElement('p');
- var lines = contents.split(/(?:\r\n?|\n)/);
- for (var i = 0, ii = lines.length; i < ii; ++i) {
- var line = lines[i];
- p.appendChild(document.createTextNode(line));
- if (i < ii - 1) {
- p.appendChild(document.createElement('br'));
- }
- }
- return p;
- }
- }, {
- key: '_toggle',
- value: function _toggle() {
- if (this.pinned) {
- this._hide(true);
- } else {
- this._show(true);
- }
- }
- }, {
- key: '_show',
- value: function _show() {
- var pin = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
-
- if (pin) {
- this.pinned = true;
- }
- if (this.hideElement.hasAttribute('hidden')) {
- this.hideElement.removeAttribute('hidden');
- this.container.style.zIndex += 1;
- }
- }
- }, {
- key: '_hide',
- value: function _hide() {
- var unpin = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
-
- if (unpin) {
- this.pinned = false;
- }
- if (!this.hideElement.hasAttribute('hidden') && !this.pinned) {
- this.hideElement.setAttribute('hidden', true);
- this.container.style.zIndex -= 1;
- }
- }
- }]);
-
- return PopupElement;
-}();
-
-var LineAnnotationElement = function (_AnnotationElement5) {
- _inherits(LineAnnotationElement, _AnnotationElement5);
-
- function LineAnnotationElement(parameters) {
- _classCallCheck(this, LineAnnotationElement);
-
- var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
- return _possibleConstructorReturn(this, (LineAnnotationElement.__proto__ || Object.getPrototypeOf(LineAnnotationElement)).call(this, parameters, isRenderable, true));
- }
-
- _createClass(LineAnnotationElement, [{
- key: 'render',
- value: function render() {
- this.container.className = 'lineAnnotation';
- var data = this.data;
- var width = data.rect[2] - data.rect[0];
- var height = data.rect[3] - data.rect[1];
- var svg = this.svgFactory.create(width, height);
- var line = this.svgFactory.createElement('svg:line');
- line.setAttribute('x1', data.rect[2] - data.lineCoordinates[0]);
- line.setAttribute('y1', data.rect[3] - data.lineCoordinates[1]);
- line.setAttribute('x2', data.rect[2] - data.lineCoordinates[2]);
- line.setAttribute('y2', data.rect[3] - data.lineCoordinates[3]);
- line.setAttribute('stroke-width', data.borderStyle.width);
- line.setAttribute('stroke', 'transparent');
- svg.appendChild(line);
- this.container.append(svg);
- this._createPopup(this.container, line, data);
- return this.container;
- }
- }]);
-
- return LineAnnotationElement;
-}(AnnotationElement);
-
-var SquareAnnotationElement = function (_AnnotationElement6) {
- _inherits(SquareAnnotationElement, _AnnotationElement6);
-
- function SquareAnnotationElement(parameters) {
- _classCallCheck(this, SquareAnnotationElement);
-
- var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
- return _possibleConstructorReturn(this, (SquareAnnotationElement.__proto__ || Object.getPrototypeOf(SquareAnnotationElement)).call(this, parameters, isRenderable, true));
- }
-
- _createClass(SquareAnnotationElement, [{
- key: 'render',
- value: function render() {
- this.container.className = 'squareAnnotation';
- var data = this.data;
- var width = data.rect[2] - data.rect[0];
- var height = data.rect[3] - data.rect[1];
- var svg = this.svgFactory.create(width, height);
- var borderWidth = data.borderStyle.width;
- var square = this.svgFactory.createElement('svg:rect');
- square.setAttribute('x', borderWidth / 2);
- square.setAttribute('y', borderWidth / 2);
- square.setAttribute('width', width - borderWidth);
- square.setAttribute('height', height - borderWidth);
- square.setAttribute('stroke-width', borderWidth);
- square.setAttribute('stroke', 'transparent');
- square.setAttribute('fill', 'none');
- svg.appendChild(square);
- this.container.append(svg);
- this._createPopup(this.container, square, data);
- return this.container;
- }
- }]);
-
- return SquareAnnotationElement;
-}(AnnotationElement);
-
-var CircleAnnotationElement = function (_AnnotationElement7) {
- _inherits(CircleAnnotationElement, _AnnotationElement7);
-
- function CircleAnnotationElement(parameters) {
- _classCallCheck(this, CircleAnnotationElement);
-
- var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
- return _possibleConstructorReturn(this, (CircleAnnotationElement.__proto__ || Object.getPrototypeOf(CircleAnnotationElement)).call(this, parameters, isRenderable, true));
- }
-
- _createClass(CircleAnnotationElement, [{
- key: 'render',
- value: function render() {
- this.container.className = 'circleAnnotation';
- var data = this.data;
- var width = data.rect[2] - data.rect[0];
- var height = data.rect[3] - data.rect[1];
- var svg = this.svgFactory.create(width, height);
- var borderWidth = data.borderStyle.width;
- var circle = this.svgFactory.createElement('svg:ellipse');
- circle.setAttribute('cx', width / 2);
- circle.setAttribute('cy', height / 2);
- circle.setAttribute('rx', width / 2 - borderWidth / 2);
- circle.setAttribute('ry', height / 2 - borderWidth / 2);
- circle.setAttribute('stroke-width', borderWidth);
- circle.setAttribute('stroke', 'transparent');
- circle.setAttribute('fill', 'none');
- svg.appendChild(circle);
- this.container.append(svg);
- this._createPopup(this.container, circle, data);
- return this.container;
- }
- }]);
-
- return CircleAnnotationElement;
-}(AnnotationElement);
-
-var PolylineAnnotationElement = function (_AnnotationElement8) {
- _inherits(PolylineAnnotationElement, _AnnotationElement8);
-
- function PolylineAnnotationElement(parameters) {
- _classCallCheck(this, PolylineAnnotationElement);
-
- var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
-
- var _this15 = _possibleConstructorReturn(this, (PolylineAnnotationElement.__proto__ || Object.getPrototypeOf(PolylineAnnotationElement)).call(this, parameters, isRenderable, true));
-
- _this15.containerClassName = 'polylineAnnotation';
- _this15.svgElementName = 'svg:polyline';
- return _this15;
- }
-
- _createClass(PolylineAnnotationElement, [{
- key: 'render',
- value: function render() {
- this.container.className = this.containerClassName;
- var data = this.data;
- var width = data.rect[2] - data.rect[0];
- var height = data.rect[3] - data.rect[1];
- var svg = this.svgFactory.create(width, height);
- var vertices = data.vertices;
- var points = [];
- for (var i = 0, ii = vertices.length; i < ii; i++) {
- var x = vertices[i].x - data.rect[0];
- var y = data.rect[3] - vertices[i].y;
- points.push(x + ',' + y);
- }
- points = points.join(' ');
- var borderWidth = data.borderStyle.width;
- var polyline = this.svgFactory.createElement(this.svgElementName);
- polyline.setAttribute('points', points);
- polyline.setAttribute('stroke-width', borderWidth);
- polyline.setAttribute('stroke', 'transparent');
- polyline.setAttribute('fill', 'none');
- svg.appendChild(polyline);
- this.container.append(svg);
- this._createPopup(this.container, polyline, data);
- return this.container;
- }
- }]);
-
- return PolylineAnnotationElement;
-}(AnnotationElement);
-
-var PolygonAnnotationElement = function (_PolylineAnnotationEl) {
- _inherits(PolygonAnnotationElement, _PolylineAnnotationEl);
-
- function PolygonAnnotationElement(parameters) {
- _classCallCheck(this, PolygonAnnotationElement);
-
- var _this16 = _possibleConstructorReturn(this, (PolygonAnnotationElement.__proto__ || Object.getPrototypeOf(PolygonAnnotationElement)).call(this, parameters));
-
- _this16.containerClassName = 'polygonAnnotation';
- _this16.svgElementName = 'svg:polygon';
- return _this16;
- }
-
- return PolygonAnnotationElement;
-}(PolylineAnnotationElement);
-
-var InkAnnotationElement = function (_AnnotationElement9) {
- _inherits(InkAnnotationElement, _AnnotationElement9);
-
- function InkAnnotationElement(parameters) {
- _classCallCheck(this, InkAnnotationElement);
-
- var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
-
- var _this17 = _possibleConstructorReturn(this, (InkAnnotationElement.__proto__ || Object.getPrototypeOf(InkAnnotationElement)).call(this, parameters, isRenderable, true));
-
- _this17.containerClassName = 'inkAnnotation';
- _this17.svgElementName = 'svg:polyline';
- return _this17;
- }
-
- _createClass(InkAnnotationElement, [{
- key: 'render',
- value: function render() {
- this.container.className = this.containerClassName;
- var data = this.data;
- var width = data.rect[2] - data.rect[0];
- var height = data.rect[3] - data.rect[1];
- var svg = this.svgFactory.create(width, height);
- var inkLists = data.inkLists;
- for (var i = 0, ii = inkLists.length; i < ii; i++) {
- var inkList = inkLists[i];
- var points = [];
- for (var j = 0, jj = inkList.length; j < jj; j++) {
- var x = inkList[j].x - data.rect[0];
- var y = data.rect[3] - inkList[j].y;
- points.push(x + ',' + y);
- }
- points = points.join(' ');
- var borderWidth = data.borderStyle.width;
- var polyline = this.svgFactory.createElement(this.svgElementName);
- polyline.setAttribute('points', points);
- polyline.setAttribute('stroke-width', borderWidth);
- polyline.setAttribute('stroke', 'transparent');
- polyline.setAttribute('fill', 'none');
- this._createPopup(this.container, polyline, data);
- svg.appendChild(polyline);
- }
- this.container.append(svg);
- return this.container;
- }
- }]);
-
- return InkAnnotationElement;
-}(AnnotationElement);
-
-var HighlightAnnotationElement = function (_AnnotationElement10) {
- _inherits(HighlightAnnotationElement, _AnnotationElement10);
-
- function HighlightAnnotationElement(parameters) {
- _classCallCheck(this, HighlightAnnotationElement);
-
- var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
- return _possibleConstructorReturn(this, (HighlightAnnotationElement.__proto__ || Object.getPrototypeOf(HighlightAnnotationElement)).call(this, parameters, isRenderable, true));
- }
-
- _createClass(HighlightAnnotationElement, [{
- key: 'render',
- value: function render() {
- this.container.className = 'highlightAnnotation';
- if (!this.data.hasPopup) {
- this._createPopup(this.container, null, this.data);
- }
- return this.container;
- }
- }]);
-
- return HighlightAnnotationElement;
-}(AnnotationElement);
-
-var UnderlineAnnotationElement = function (_AnnotationElement11) {
- _inherits(UnderlineAnnotationElement, _AnnotationElement11);
-
- function UnderlineAnnotationElement(parameters) {
- _classCallCheck(this, UnderlineAnnotationElement);
-
- var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
- return _possibleConstructorReturn(this, (UnderlineAnnotationElement.__proto__ || Object.getPrototypeOf(UnderlineAnnotationElement)).call(this, parameters, isRenderable, true));
- }
-
- _createClass(UnderlineAnnotationElement, [{
- key: 'render',
- value: function render() {
- this.container.className = 'underlineAnnotation';
- if (!this.data.hasPopup) {
- this._createPopup(this.container, null, this.data);
- }
- return this.container;
- }
- }]);
-
- return UnderlineAnnotationElement;
-}(AnnotationElement);
-
-var SquigglyAnnotationElement = function (_AnnotationElement12) {
- _inherits(SquigglyAnnotationElement, _AnnotationElement12);
-
- function SquigglyAnnotationElement(parameters) {
- _classCallCheck(this, SquigglyAnnotationElement);
-
- var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
- return _possibleConstructorReturn(this, (SquigglyAnnotationElement.__proto__ || Object.getPrototypeOf(SquigglyAnnotationElement)).call(this, parameters, isRenderable, true));
- }
-
- _createClass(SquigglyAnnotationElement, [{
- key: 'render',
- value: function render() {
- this.container.className = 'squigglyAnnotation';
- if (!this.data.hasPopup) {
- this._createPopup(this.container, null, this.data);
- }
- return this.container;
- }
- }]);
-
- return SquigglyAnnotationElement;
-}(AnnotationElement);
-
-var StrikeOutAnnotationElement = function (_AnnotationElement13) {
- _inherits(StrikeOutAnnotationElement, _AnnotationElement13);
-
- function StrikeOutAnnotationElement(parameters) {
- _classCallCheck(this, StrikeOutAnnotationElement);
-
- var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
- return _possibleConstructorReturn(this, (StrikeOutAnnotationElement.__proto__ || Object.getPrototypeOf(StrikeOutAnnotationElement)).call(this, parameters, isRenderable, true));
- }
-
- _createClass(StrikeOutAnnotationElement, [{
- key: 'render',
- value: function render() {
- this.container.className = 'strikeoutAnnotation';
- if (!this.data.hasPopup) {
- this._createPopup(this.container, null, this.data);
- }
- return this.container;
- }
- }]);
-
- return StrikeOutAnnotationElement;
-}(AnnotationElement);
-
-var StampAnnotationElement = function (_AnnotationElement14) {
- _inherits(StampAnnotationElement, _AnnotationElement14);
-
- function StampAnnotationElement(parameters) {
- _classCallCheck(this, StampAnnotationElement);
-
- var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
- return _possibleConstructorReturn(this, (StampAnnotationElement.__proto__ || Object.getPrototypeOf(StampAnnotationElement)).call(this, parameters, isRenderable, true));
- }
-
- _createClass(StampAnnotationElement, [{
- key: 'render',
- value: function render() {
- this.container.className = 'stampAnnotation';
- if (!this.data.hasPopup) {
- this._createPopup(this.container, null, this.data);
- }
- return this.container;
- }
- }]);
-
- return StampAnnotationElement;
-}(AnnotationElement);
-
-var FileAttachmentAnnotationElement = function (_AnnotationElement15) {
- _inherits(FileAttachmentAnnotationElement, _AnnotationElement15);
-
- function FileAttachmentAnnotationElement(parameters) {
- _classCallCheck(this, FileAttachmentAnnotationElement);
-
- var _this23 = _possibleConstructorReturn(this, (FileAttachmentAnnotationElement.__proto__ || Object.getPrototypeOf(FileAttachmentAnnotationElement)).call(this, parameters, true));
-
- var _this23$data$file = _this23.data.file,
- filename = _this23$data$file.filename,
- content = _this23$data$file.content;
-
- _this23.filename = (0, _dom_utils.getFilenameFromUrl)(filename);
- _this23.content = content;
- if (_this23.linkService.eventBus) {
- _this23.linkService.eventBus.dispatch('fileattachmentannotation', {
- source: _this23,
- id: (0, _util.stringToPDFString)(filename),
- filename: filename,
- content: content
- });
- }
- return _this23;
- }
-
- _createClass(FileAttachmentAnnotationElement, [{
- key: 'render',
- value: function render() {
- this.container.className = 'fileAttachmentAnnotation';
- var trigger = document.createElement('div');
- trigger.style.height = this.container.style.height;
- trigger.style.width = this.container.style.width;
- trigger.addEventListener('dblclick', this._download.bind(this));
- if (!this.data.hasPopup && (this.data.title || this.data.contents)) {
- this._createPopup(this.container, trigger, this.data);
- }
- this.container.appendChild(trigger);
- return this.container;
- }
- }, {
- key: '_download',
- value: function _download() {
- if (!this.downloadManager) {
- (0, _util.warn)('Download cannot be started due to unavailable download manager');
- return;
- }
- this.downloadManager.downloadData(this.content, this.filename, '');
- }
- }]);
-
- return FileAttachmentAnnotationElement;
-}(AnnotationElement);
-
-var AnnotationLayer = function () {
- function AnnotationLayer() {
- _classCallCheck(this, AnnotationLayer);
- }
-
- _createClass(AnnotationLayer, null, [{
- key: 'render',
- value: function render(parameters) {
- for (var i = 0, ii = parameters.annotations.length; i < ii; i++) {
- var data = parameters.annotations[i];
- if (!data) {
- continue;
- }
- var element = AnnotationElementFactory.create({
- data: data,
- layer: parameters.div,
- page: parameters.page,
- viewport: parameters.viewport,
- linkService: parameters.linkService,
- downloadManager: parameters.downloadManager,
- imageResourcesPath: parameters.imageResourcesPath || '',
- renderInteractiveForms: parameters.renderInteractiveForms || false,
- svgFactory: new _dom_utils.DOMSVGFactory()
- });
- if (element.isRenderable) {
- parameters.div.appendChild(element.render());
- }
- }
- }
- }, {
- key: 'update',
- value: function update(parameters) {
- for (var i = 0, ii = parameters.annotations.length; i < ii; i++) {
- var data = parameters.annotations[i];
- var element = parameters.div.querySelector('[data-annotation-id="' + data.id + '"]');
- if (element) {
- element.style.transform = 'matrix(' + parameters.viewport.transform.join(',') + ')';
- }
- }
- parameters.div.removeAttribute('hidden');
- }
- }]);
-
- return AnnotationLayer;
-}();
-
-exports.AnnotationLayer = AnnotationLayer;
-
-/***/ }),
-/* 147 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.SVGGraphics = undefined;
-
-var _util = __w_pdfjs_require__(1);
-
-var _dom_utils = __w_pdfjs_require__(130);
-
-var _is_node = __w_pdfjs_require__(4);
-
-var _is_node2 = _interopRequireDefault(_is_node);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-var SVGGraphics = function SVGGraphics() {
- throw new Error('Not implemented: SVGGraphics');
-};
-{
- var SVG_DEFAULTS = {
- fontStyle: 'normal',
- fontWeight: 'normal',
- fillColor: '#000000'
- };
- var convertImgDataToPng = function convertImgDataToPngClosure() {
- var PNG_HEADER = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
- var CHUNK_WRAPPER_SIZE = 12;
- var crcTable = new Int32Array(256);
- for (var i = 0; i < 256; i++) {
- var c = i;
- for (var h = 0; h < 8; h++) {
- if (c & 1) {
- c = 0xedB88320 ^ c >> 1 & 0x7fffffff;
- } else {
- c = c >> 1 & 0x7fffffff;
- }
- }
- crcTable[i] = c;
- }
- function crc32(data, start, end) {
- var crc = -1;
- for (var i = start; i < end; i++) {
- var a = (crc ^ data[i]) & 0xff;
- var b = crcTable[a];
- crc = crc >>> 8 ^ b;
- }
- return crc ^ -1;
- }
- function writePngChunk(type, body, data, offset) {
- var p = offset;
- var len = body.length;
- data[p] = len >> 24 & 0xff;
- data[p + 1] = len >> 16 & 0xff;
- data[p + 2] = len >> 8 & 0xff;
- data[p + 3] = len & 0xff;
- p += 4;
- data[p] = type.charCodeAt(0) & 0xff;
- data[p + 1] = type.charCodeAt(1) & 0xff;
- data[p + 2] = type.charCodeAt(2) & 0xff;
- data[p + 3] = type.charCodeAt(3) & 0xff;
- p += 4;
- data.set(body, p);
- p += body.length;
- var crc = crc32(data, offset + 4, p);
- data[p] = crc >> 24 & 0xff;
- data[p + 1] = crc >> 16 & 0xff;
- data[p + 2] = crc >> 8 & 0xff;
- data[p + 3] = crc & 0xff;
- }
- function adler32(data, start, end) {
- var a = 1;
- var b = 0;
- for (var i = start; i < end; ++i) {
- a = (a + (data[i] & 0xff)) % 65521;
- b = (b + a) % 65521;
- }
- return b << 16 | a;
- }
- function deflateSync(literals) {
- if (!(0, _is_node2.default)()) {
- return deflateSyncUncompressed(literals);
- }
- try {
- var input;
- if (parseInt(process.versions.node) >= 8) {
- input = literals;
- } else {
- input = new Buffer(literals);
- }
- var output = require('zlib').deflateSync(input, { level: 9 });
- return output instanceof Uint8Array ? output : new Uint8Array(output);
- } catch (e) {
- (0, _util.warn)('Not compressing PNG because zlib.deflateSync is unavailable: ' + e);
- }
- return deflateSyncUncompressed(literals);
- }
- function deflateSyncUncompressed(literals) {
- var len = literals.length;
- var maxBlockLength = 0xFFFF;
- var deflateBlocks = Math.ceil(len / maxBlockLength);
- var idat = new Uint8Array(2 + len + deflateBlocks * 5 + 4);
- var pi = 0;
- idat[pi++] = 0x78;
- idat[pi++] = 0x9c;
- var pos = 0;
- while (len > maxBlockLength) {
- idat[pi++] = 0x00;
- idat[pi++] = 0xff;
- idat[pi++] = 0xff;
- idat[pi++] = 0x00;
- idat[pi++] = 0x00;
- idat.set(literals.subarray(pos, pos + maxBlockLength), pi);
- pi += maxBlockLength;
- pos += maxBlockLength;
- len -= maxBlockLength;
- }
- idat[pi++] = 0x01;
- idat[pi++] = len & 0xff;
- idat[pi++] = len >> 8 & 0xff;
- idat[pi++] = ~len & 0xffff & 0xff;
- idat[pi++] = (~len & 0xffff) >> 8 & 0xff;
- idat.set(literals.subarray(pos), pi);
- pi += literals.length - pos;
- var adler = adler32(literals, 0, literals.length);
- idat[pi++] = adler >> 24 & 0xff;
- idat[pi++] = adler >> 16 & 0xff;
- idat[pi++] = adler >> 8 & 0xff;
- idat[pi++] = adler & 0xff;
- return idat;
- }
- function encode(imgData, kind, forceDataSchema, isMask) {
- var width = imgData.width;
- var height = imgData.height;
- var bitDepth, colorType, lineSize;
- var bytes = imgData.data;
- switch (kind) {
- case _util.ImageKind.GRAYSCALE_1BPP:
- colorType = 0;
- bitDepth = 1;
- lineSize = width + 7 >> 3;
- break;
- case _util.ImageKind.RGB_24BPP:
- colorType = 2;
- bitDepth = 8;
- lineSize = width * 3;
- break;
- case _util.ImageKind.RGBA_32BPP:
- colorType = 6;
- bitDepth = 8;
- lineSize = width * 4;
- break;
- default:
- throw new Error('invalid format');
- }
- var literals = new Uint8Array((1 + lineSize) * height);
- var offsetLiterals = 0,
- offsetBytes = 0;
- var y, i;
- for (y = 0; y < height; ++y) {
- literals[offsetLiterals++] = 0;
- literals.set(bytes.subarray(offsetBytes, offsetBytes + lineSize), offsetLiterals);
- offsetBytes += lineSize;
- offsetLiterals += lineSize;
- }
- if (kind === _util.ImageKind.GRAYSCALE_1BPP && isMask) {
- offsetLiterals = 0;
- for (y = 0; y < height; y++) {
- offsetLiterals++;
- for (i = 0; i < lineSize; i++) {
- literals[offsetLiterals++] ^= 0xFF;
- }
- }
- }
- var ihdr = new Uint8Array([width >> 24 & 0xff, width >> 16 & 0xff, width >> 8 & 0xff, width & 0xff, height >> 24 & 0xff, height >> 16 & 0xff, height >> 8 & 0xff, height & 0xff, bitDepth, colorType, 0x00, 0x00, 0x00]);
- var idat = deflateSync(literals);
- var pngLength = PNG_HEADER.length + CHUNK_WRAPPER_SIZE * 3 + ihdr.length + idat.length;
- var data = new Uint8Array(pngLength);
- var offset = 0;
- data.set(PNG_HEADER, offset);
- offset += PNG_HEADER.length;
- writePngChunk('IHDR', ihdr, data, offset);
- offset += CHUNK_WRAPPER_SIZE + ihdr.length;
- writePngChunk('IDATA', idat, data, offset);
- offset += CHUNK_WRAPPER_SIZE + idat.length;
- writePngChunk('IEND', new Uint8Array(0), data, offset);
- return (0, _util.createObjectURL)(data, 'image/png', forceDataSchema);
- }
- return function convertImgDataToPng(imgData, forceDataSchema, isMask) {
- var kind = imgData.kind === undefined ? _util.ImageKind.GRAYSCALE_1BPP : imgData.kind;
- return encode(imgData, kind, forceDataSchema, isMask);
- };
- }();
- var SVGExtraState = function SVGExtraStateClosure() {
- function SVGExtraState() {
- this.fontSizeScale = 1;
- this.fontWeight = SVG_DEFAULTS.fontWeight;
- this.fontSize = 0;
- this.textMatrix = _util.IDENTITY_MATRIX;
- this.fontMatrix = _util.FONT_IDENTITY_MATRIX;
- this.leading = 0;
- this.textRenderingMode = _util.TextRenderingMode.FILL;
- this.x = 0;
- this.y = 0;
- this.lineX = 0;
- this.lineY = 0;
- this.charSpacing = 0;
- this.wordSpacing = 0;
- this.textHScale = 1;
- this.textRise = 0;
- this.fillColor = SVG_DEFAULTS.fillColor;
- this.strokeColor = '#000000';
- this.fillAlpha = 1;
- this.strokeAlpha = 1;
- this.lineWidth = 1;
- this.lineJoin = '';
- this.lineCap = '';
- this.miterLimit = 0;
- this.dashArray = [];
- this.dashPhase = 0;
- this.dependencies = [];
- this.activeClipUrl = null;
- this.clipGroup = null;
- this.maskId = '';
- }
- SVGExtraState.prototype = {
- clone: function SVGExtraState_clone() {
- return Object.create(this);
- },
- setCurrentPoint: function SVGExtraState_setCurrentPoint(x, y) {
- this.x = x;
- this.y = y;
- }
- };
- return SVGExtraState;
- }();
- exports.SVGGraphics = SVGGraphics = function SVGGraphicsClosure() {
- function opListToTree(opList) {
- var opTree = [];
- var tmp = [];
- var opListLen = opList.length;
- for (var x = 0; x < opListLen; x++) {
- if (opList[x].fn === 'save') {
- opTree.push({
- 'fnId': 92,
- 'fn': 'group',
- 'items': []
- });
- tmp.push(opTree);
- opTree = opTree[opTree.length - 1].items;
- continue;
- }
- if (opList[x].fn === 'restore') {
- opTree = tmp.pop();
- } else {
- opTree.push(opList[x]);
- }
- }
- return opTree;
- }
- function pf(value) {
- if (Number.isInteger(value)) {
- return value.toString();
- }
- var s = value.toFixed(10);
- var i = s.length - 1;
- if (s[i] !== '0') {
- return s;
- }
- do {
- i--;
- } while (s[i] === '0');
- return s.substring(0, s[i] === '.' ? i : i + 1);
- }
- function pm(m) {
- if (m[4] === 0 && m[5] === 0) {
- if (m[1] === 0 && m[2] === 0) {
- if (m[0] === 1 && m[3] === 1) {
- return '';
- }
- return 'scale(' + pf(m[0]) + ' ' + pf(m[3]) + ')';
- }
- if (m[0] === m[3] && m[1] === -m[2]) {
- var a = Math.acos(m[0]) * 180 / Math.PI;
- return 'rotate(' + pf(a) + ')';
- }
- } else {
- if (m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 1) {
- return 'translate(' + pf(m[4]) + ' ' + pf(m[5]) + ')';
- }
- }
- return 'matrix(' + pf(m[0]) + ' ' + pf(m[1]) + ' ' + pf(m[2]) + ' ' + pf(m[3]) + ' ' + pf(m[4]) + ' ' + pf(m[5]) + ')';
- }
- function SVGGraphics(commonObjs, objs, forceDataSchema) {
- this.svgFactory = new _dom_utils.DOMSVGFactory();
- this.current = new SVGExtraState();
- this.transformMatrix = _util.IDENTITY_MATRIX;
- this.transformStack = [];
- this.extraStack = [];
- this.commonObjs = commonObjs;
- this.objs = objs;
- this.pendingClip = null;
- this.pendingEOFill = false;
- this.embedFonts = false;
- this.embeddedFonts = Object.create(null);
- this.cssStyle = null;
- this.forceDataSchema = !!forceDataSchema;
- }
- var XML_NS = 'http://www.w3.org/XML/1998/namespace';
- var XLINK_NS = 'http://www.w3.org/1999/xlink';
- var LINE_CAP_STYLES = ['butt', 'round', 'square'];
- var LINE_JOIN_STYLES = ['miter', 'round', 'bevel'];
- var clipCount = 0;
- var maskCount = 0;
- SVGGraphics.prototype = {
- save: function SVGGraphics_save() {
- this.transformStack.push(this.transformMatrix);
- var old = this.current;
- this.extraStack.push(old);
- this.current = old.clone();
- },
- restore: function SVGGraphics_restore() {
- this.transformMatrix = this.transformStack.pop();
- this.current = this.extraStack.pop();
- this.pendingClip = null;
- this.tgrp = null;
- },
- group: function SVGGraphics_group(items) {
- this.save();
- this.executeOpTree(items);
- this.restore();
- },
- loadDependencies: function SVGGraphics_loadDependencies(operatorList) {
- var _this = this;
-
- var fnArray = operatorList.fnArray;
- var fnArrayLen = fnArray.length;
- var argsArray = operatorList.argsArray;
- for (var i = 0; i < fnArrayLen; i++) {
- if (_util.OPS.dependency === fnArray[i]) {
- var deps = argsArray[i];
- for (var n = 0, nn = deps.length; n < nn; n++) {
- var obj = deps[n];
- var common = obj.substring(0, 2) === 'g_';
- var promise;
- if (common) {
- promise = new Promise(function (resolve) {
- _this.commonObjs.get(obj, resolve);
- });
- } else {
- promise = new Promise(function (resolve) {
- _this.objs.get(obj, resolve);
- });
- }
- this.current.dependencies.push(promise);
- }
- }
- }
- return Promise.all(this.current.dependencies);
- },
- transform: function SVGGraphics_transform(a, b, c, d, e, f) {
- var transformMatrix = [a, b, c, d, e, f];
- this.transformMatrix = _util.Util.transform(this.transformMatrix, transformMatrix);
- this.tgrp = null;
- },
- getSVG: function SVGGraphics_getSVG(operatorList, viewport) {
- var _this2 = this;
-
- this.viewport = viewport;
- var svgElement = this._initialize(viewport);
- return this.loadDependencies(operatorList).then(function () {
- _this2.transformMatrix = _util.IDENTITY_MATRIX;
- var opTree = _this2.convertOpList(operatorList);
- _this2.executeOpTree(opTree);
- return svgElement;
- });
- },
- convertOpList: function SVGGraphics_convertOpList(operatorList) {
- var argsArray = operatorList.argsArray;
- var fnArray = operatorList.fnArray;
- var fnArrayLen = fnArray.length;
- var REVOPS = [];
- var opList = [];
- for (var op in _util.OPS) {
- REVOPS[_util.OPS[op]] = op;
- }
- for (var x = 0; x < fnArrayLen; x++) {
- var fnId = fnArray[x];
- opList.push({
- 'fnId': fnId,
- 'fn': REVOPS[fnId],
- 'args': argsArray[x]
- });
- }
- return opListToTree(opList);
- },
- executeOpTree: function SVGGraphics_executeOpTree(opTree) {
- var opTreeLen = opTree.length;
- for (var x = 0; x < opTreeLen; x++) {
- var fn = opTree[x].fn;
- var fnId = opTree[x].fnId;
- var args = opTree[x].args;
- switch (fnId | 0) {
- case _util.OPS.beginText:
- this.beginText();
- break;
- case _util.OPS.dependency:
- break;
- case _util.OPS.setLeading:
- this.setLeading(args);
- break;
- case _util.OPS.setLeadingMoveText:
- this.setLeadingMoveText(args[0], args[1]);
- break;
- case _util.OPS.setFont:
- this.setFont(args);
- break;
- case _util.OPS.showText:
- this.showText(args[0]);
- break;
- case _util.OPS.showSpacedText:
- this.showText(args[0]);
- break;
- case _util.OPS.endText:
- this.endText();
- break;
- case _util.OPS.moveText:
- this.moveText(args[0], args[1]);
- break;
- case _util.OPS.setCharSpacing:
- this.setCharSpacing(args[0]);
- break;
- case _util.OPS.setWordSpacing:
- this.setWordSpacing(args[0]);
- break;
- case _util.OPS.setHScale:
- this.setHScale(args[0]);
- break;
- case _util.OPS.setTextMatrix:
- this.setTextMatrix(args[0], args[1], args[2], args[3], args[4], args[5]);
- break;
- case _util.OPS.setTextRise:
- this.setTextRise(args[0]);
- break;
- case _util.OPS.setTextRenderingMode:
- this.setTextRenderingMode(args[0]);
- break;
- case _util.OPS.setLineWidth:
- this.setLineWidth(args[0]);
- break;
- case _util.OPS.setLineJoin:
- this.setLineJoin(args[0]);
- break;
- case _util.OPS.setLineCap:
- this.setLineCap(args[0]);
- break;
- case _util.OPS.setMiterLimit:
- this.setMiterLimit(args[0]);
- break;
- case _util.OPS.setFillRGBColor:
- this.setFillRGBColor(args[0], args[1], args[2]);
- break;
- case _util.OPS.setStrokeRGBColor:
- this.setStrokeRGBColor(args[0], args[1], args[2]);
- break;
- case _util.OPS.setDash:
- this.setDash(args[0], args[1]);
- break;
- case _util.OPS.setGState:
- this.setGState(args[0]);
- break;
- case _util.OPS.fill:
- this.fill();
- break;
- case _util.OPS.eoFill:
- this.eoFill();
- break;
- case _util.OPS.stroke:
- this.stroke();
- break;
- case _util.OPS.fillStroke:
- this.fillStroke();
- break;
- case _util.OPS.eoFillStroke:
- this.eoFillStroke();
- break;
- case _util.OPS.clip:
- this.clip('nonzero');
- break;
- case _util.OPS.eoClip:
- this.clip('evenodd');
- break;
- case _util.OPS.paintSolidColorImageMask:
- this.paintSolidColorImageMask();
- break;
- case _util.OPS.paintJpegXObject:
- this.paintJpegXObject(args[0], args[1], args[2]);
- break;
- case _util.OPS.paintImageXObject:
- this.paintImageXObject(args[0]);
- break;
- case _util.OPS.paintInlineImageXObject:
- this.paintInlineImageXObject(args[0]);
- break;
- case _util.OPS.paintImageMaskXObject:
- this.paintImageMaskXObject(args[0]);
- break;
- case _util.OPS.paintFormXObjectBegin:
- this.paintFormXObjectBegin(args[0], args[1]);
- break;
- case _util.OPS.paintFormXObjectEnd:
- this.paintFormXObjectEnd();
- break;
- case _util.OPS.closePath:
- this.closePath();
- break;
- case _util.OPS.closeStroke:
- this.closeStroke();
- break;
- case _util.OPS.closeFillStroke:
- this.closeFillStroke();
- break;
- case _util.OPS.closeEOFillStroke:
- this.closeEOFillStroke();
- break;
- case _util.OPS.nextLine:
- this.nextLine();
- break;
- case _util.OPS.transform:
- this.transform(args[0], args[1], args[2], args[3], args[4], args[5]);
- break;
- case _util.OPS.constructPath:
- this.constructPath(args[0], args[1]);
- break;
- case _util.OPS.endPath:
- this.endPath();
- break;
- case 92:
- this.group(opTree[x].items);
- break;
- default:
- (0, _util.warn)('Unimplemented operator ' + fn);
- break;
- }
- }
- },
- setWordSpacing: function SVGGraphics_setWordSpacing(wordSpacing) {
- this.current.wordSpacing = wordSpacing;
- },
- setCharSpacing: function SVGGraphics_setCharSpacing(charSpacing) {
- this.current.charSpacing = charSpacing;
- },
- nextLine: function SVGGraphics_nextLine() {
- this.moveText(0, this.current.leading);
- },
- setTextMatrix: function SVGGraphics_setTextMatrix(a, b, c, d, e, f) {
- var current = this.current;
- this.current.textMatrix = this.current.lineMatrix = [a, b, c, d, e, f];
- this.current.x = this.current.lineX = 0;
- this.current.y = this.current.lineY = 0;
- current.xcoords = [];
- current.tspan = this.svgFactory.createElement('svg:tspan');
- current.tspan.setAttributeNS(null, 'font-family', current.fontFamily);
- current.tspan.setAttributeNS(null, 'font-size', pf(current.fontSize) + 'px');
- current.tspan.setAttributeNS(null, 'y', pf(-current.y));
- current.txtElement = this.svgFactory.createElement('svg:text');
- current.txtElement.appendChild(current.tspan);
- },
- beginText: function SVGGraphics_beginText() {
- this.current.x = this.current.lineX = 0;
- this.current.y = this.current.lineY = 0;
- this.current.textMatrix = _util.IDENTITY_MATRIX;
- this.current.lineMatrix = _util.IDENTITY_MATRIX;
- this.current.tspan = this.svgFactory.createElement('svg:tspan');
- this.current.txtElement = this.svgFactory.createElement('svg:text');
- this.current.txtgrp = this.svgFactory.createElement('svg:g');
- this.current.xcoords = [];
- },
- moveText: function SVGGraphics_moveText(x, y) {
- var current = this.current;
- this.current.x = this.current.lineX += x;
- this.current.y = this.current.lineY += y;
- current.xcoords = [];
- current.tspan = this.svgFactory.createElement('svg:tspan');
- current.tspan.setAttributeNS(null, 'font-family', current.fontFamily);
- current.tspan.setAttributeNS(null, 'font-size', pf(current.fontSize) + 'px');
- current.tspan.setAttributeNS(null, 'y', pf(-current.y));
- },
- showText: function SVGGraphics_showText(glyphs) {
- var current = this.current;
- var font = current.font;
- var fontSize = current.fontSize;
- if (fontSize === 0) {
- return;
- }
- var charSpacing = current.charSpacing;
- var wordSpacing = current.wordSpacing;
- var fontDirection = current.fontDirection;
- var textHScale = current.textHScale * fontDirection;
- var glyphsLength = glyphs.length;
- var vertical = font.vertical;
- var widthAdvanceScale = fontSize * current.fontMatrix[0];
- var x = 0,
- i;
- for (i = 0; i < glyphsLength; ++i) {
- var glyph = glyphs[i];
- if (glyph === null) {
- x += fontDirection * wordSpacing;
- continue;
- } else if ((0, _util.isNum)(glyph)) {
- x += -glyph * fontSize * 0.001;
- continue;
- }
- var width = glyph.width;
- var character = glyph.fontChar;
- var spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
- var charWidth = width * widthAdvanceScale + spacing * fontDirection;
- if (!glyph.isInFont && !font.missingFile) {
- x += charWidth;
- continue;
- }
- current.xcoords.push(current.x + x * textHScale);
- current.tspan.textContent += character;
- x += charWidth;
- }
- if (vertical) {
- current.y -= x * textHScale;
- } else {
- current.x += x * textHScale;
- }
- current.tspan.setAttributeNS(null, 'x', current.xcoords.map(pf).join(' '));
- current.tspan.setAttributeNS(null, 'y', pf(-current.y));
- current.tspan.setAttributeNS(null, 'font-family', current.fontFamily);
- current.tspan.setAttributeNS(null, 'font-size', pf(current.fontSize) + 'px');
- if (current.fontStyle !== SVG_DEFAULTS.fontStyle) {
- current.tspan.setAttributeNS(null, 'font-style', current.fontStyle);
- }
- if (current.fontWeight !== SVG_DEFAULTS.fontWeight) {
- current.tspan.setAttributeNS(null, 'font-weight', current.fontWeight);
- }
- var fillStrokeMode = current.textRenderingMode & _util.TextRenderingMode.FILL_STROKE_MASK;
- if (fillStrokeMode === _util.TextRenderingMode.FILL || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
- if (current.fillColor !== SVG_DEFAULTS.fillColor) {
- current.tspan.setAttributeNS(null, 'fill', current.fillColor);
- }
- if (current.fillAlpha < 1) {
- current.tspan.setAttributeNS(null, 'fill-opacity', current.fillAlpha);
- }
- } else if (current.textRenderingMode === _util.TextRenderingMode.ADD_TO_PATH) {
- current.tspan.setAttributeNS(null, 'fill', 'transparent');
- } else {
- current.tspan.setAttributeNS(null, 'fill', 'none');
- }
- if (fillStrokeMode === _util.TextRenderingMode.STROKE || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
- this._setStrokeAttributes(current.tspan);
- }
- var textMatrix = current.textMatrix;
- if (current.textRise !== 0) {
- textMatrix = textMatrix.slice();
- textMatrix[5] += current.textRise;
- }
- current.txtElement.setAttributeNS(null, 'transform', pm(textMatrix) + ' scale(1, -1)');
- current.txtElement.setAttributeNS(XML_NS, 'xml:space', 'preserve');
- current.txtElement.appendChild(current.tspan);
- current.txtgrp.appendChild(current.txtElement);
- this._ensureTransformGroup().appendChild(current.txtElement);
- },
- setLeadingMoveText: function SVGGraphics_setLeadingMoveText(x, y) {
- this.setLeading(-y);
- this.moveText(x, y);
- },
- addFontStyle: function SVGGraphics_addFontStyle(fontObj) {
- if (!this.cssStyle) {
- this.cssStyle = this.svgFactory.createElement('svg:style');
- this.cssStyle.setAttributeNS(null, 'type', 'text/css');
- this.defs.appendChild(this.cssStyle);
- }
- var url = (0, _util.createObjectURL)(fontObj.data, fontObj.mimetype, this.forceDataSchema);
- this.cssStyle.textContent += '@font-face { font-family: "' + fontObj.loadedName + '";' + ' src: url(' + url + '); }\n';
- },
- setFont: function SVGGraphics_setFont(details) {
- var current = this.current;
- var fontObj = this.commonObjs.get(details[0]);
- var size = details[1];
- this.current.font = fontObj;
- if (this.embedFonts && fontObj.data && !this.embeddedFonts[fontObj.loadedName]) {
- this.addFontStyle(fontObj);
- this.embeddedFonts[fontObj.loadedName] = fontObj;
- }
- current.fontMatrix = fontObj.fontMatrix ? fontObj.fontMatrix : _util.FONT_IDENTITY_MATRIX;
- var bold = fontObj.black ? fontObj.bold ? 'bolder' : 'bold' : fontObj.bold ? 'bold' : 'normal';
- var italic = fontObj.italic ? 'italic' : 'normal';
- if (size < 0) {
- size = -size;
- current.fontDirection = -1;
- } else {
- current.fontDirection = 1;
- }
- current.fontSize = size;
- current.fontFamily = fontObj.loadedName;
- current.fontWeight = bold;
- current.fontStyle = italic;
- current.tspan = this.svgFactory.createElement('svg:tspan');
- current.tspan.setAttributeNS(null, 'y', pf(-current.y));
- current.xcoords = [];
- },
- endText: function endText() {
- var current = this.current;
- if (current.textRenderingMode & _util.TextRenderingMode.ADD_TO_PATH_FLAG && current.txtElement && current.txtElement.hasChildNodes()) {
- current.element = current.txtElement;
- this.clip('nonzero');
- this.endPath();
- }
- },
-
- setLineWidth: function SVGGraphics_setLineWidth(width) {
- this.current.lineWidth = width;
- },
- setLineCap: function SVGGraphics_setLineCap(style) {
- this.current.lineCap = LINE_CAP_STYLES[style];
- },
- setLineJoin: function SVGGraphics_setLineJoin(style) {
- this.current.lineJoin = LINE_JOIN_STYLES[style];
- },
- setMiterLimit: function SVGGraphics_setMiterLimit(limit) {
- this.current.miterLimit = limit;
- },
- setStrokeAlpha: function SVGGraphics_setStrokeAlpha(strokeAlpha) {
- this.current.strokeAlpha = strokeAlpha;
- },
- setStrokeRGBColor: function SVGGraphics_setStrokeRGBColor(r, g, b) {
- var color = _util.Util.makeCssRgb(r, g, b);
- this.current.strokeColor = color;
- },
- setFillAlpha: function SVGGraphics_setFillAlpha(fillAlpha) {
- this.current.fillAlpha = fillAlpha;
- },
- setFillRGBColor: function SVGGraphics_setFillRGBColor(r, g, b) {
- var color = _util.Util.makeCssRgb(r, g, b);
- this.current.fillColor = color;
- this.current.tspan = this.svgFactory.createElement('svg:tspan');
- this.current.xcoords = [];
- },
- setDash: function SVGGraphics_setDash(dashArray, dashPhase) {
- this.current.dashArray = dashArray;
- this.current.dashPhase = dashPhase;
- },
- constructPath: function SVGGraphics_constructPath(ops, args) {
- var current = this.current;
- var x = current.x,
- y = current.y;
- current.path = this.svgFactory.createElement('svg:path');
- var d = [];
- var opLength = ops.length;
- for (var i = 0, j = 0; i < opLength; i++) {
- switch (ops[i] | 0) {
- case _util.OPS.rectangle:
- x = args[j++];
- y = args[j++];
- var width = args[j++];
- var height = args[j++];
- var xw = x + width;
- var yh = y + height;
- d.push('M', pf(x), pf(y), 'L', pf(xw), pf(y), 'L', pf(xw), pf(yh), 'L', pf(x), pf(yh), 'Z');
- break;
- case _util.OPS.moveTo:
- x = args[j++];
- y = args[j++];
- d.push('M', pf(x), pf(y));
- break;
- case _util.OPS.lineTo:
- x = args[j++];
- y = args[j++];
- d.push('L', pf(x), pf(y));
- break;
- case _util.OPS.curveTo:
- x = args[j + 4];
- y = args[j + 5];
- d.push('C', pf(args[j]), pf(args[j + 1]), pf(args[j + 2]), pf(args[j + 3]), pf(x), pf(y));
- j += 6;
- break;
- case _util.OPS.curveTo2:
- x = args[j + 2];
- y = args[j + 3];
- d.push('C', pf(x), pf(y), pf(args[j]), pf(args[j + 1]), pf(args[j + 2]), pf(args[j + 3]));
- j += 4;
- break;
- case _util.OPS.curveTo3:
- x = args[j + 2];
- y = args[j + 3];
- d.push('C', pf(args[j]), pf(args[j + 1]), pf(x), pf(y), pf(x), pf(y));
- j += 4;
- break;
- case _util.OPS.closePath:
- d.push('Z');
- break;
- }
- }
- current.path.setAttributeNS(null, 'd', d.join(' '));
- current.path.setAttributeNS(null, 'fill', 'none');
- this._ensureTransformGroup().appendChild(current.path);
- current.element = current.path;
- current.setCurrentPoint(x, y);
- },
- endPath: function SVGGraphics_endPath() {
- if (!this.pendingClip) {
- return;
- }
- var current = this.current;
- var clipId = 'clippath' + clipCount;
- clipCount++;
- var clipPath = this.svgFactory.createElement('svg:clipPath');
- clipPath.setAttributeNS(null, 'id', clipId);
- clipPath.setAttributeNS(null, 'transform', pm(this.transformMatrix));
- var clipElement = current.element.cloneNode(true);
- if (this.pendingClip === 'evenodd') {
- clipElement.setAttributeNS(null, 'clip-rule', 'evenodd');
- } else {
- clipElement.setAttributeNS(null, 'clip-rule', 'nonzero');
- }
- this.pendingClip = null;
- clipPath.appendChild(clipElement);
- this.defs.appendChild(clipPath);
- if (current.activeClipUrl) {
- current.clipGroup = null;
- this.extraStack.forEach(function (prev) {
- prev.clipGroup = null;
- });
- clipPath.setAttributeNS(null, 'clip-path', current.activeClipUrl);
- }
- current.activeClipUrl = 'url(#' + clipId + ')';
- this.tgrp = null;
- },
- clip: function SVGGraphics_clip(type) {
- this.pendingClip = type;
- },
- closePath: function SVGGraphics_closePath() {
- var current = this.current;
- if (current.path) {
- var d = current.path.getAttributeNS(null, 'd');
- d += 'Z';
- current.path.setAttributeNS(null, 'd', d);
- }
- },
- setLeading: function SVGGraphics_setLeading(leading) {
- this.current.leading = -leading;
- },
- setTextRise: function SVGGraphics_setTextRise(textRise) {
- this.current.textRise = textRise;
- },
- setTextRenderingMode: function setTextRenderingMode(textRenderingMode) {
- this.current.textRenderingMode = textRenderingMode;
- },
-
- setHScale: function SVGGraphics_setHScale(scale) {
- this.current.textHScale = scale / 100;
- },
- setGState: function SVGGraphics_setGState(states) {
- for (var i = 0, ii = states.length; i < ii; i++) {
- var state = states[i];
- var key = state[0];
- var value = state[1];
- switch (key) {
- case 'LW':
- this.setLineWidth(value);
- break;
- case 'LC':
- this.setLineCap(value);
- break;
- case 'LJ':
- this.setLineJoin(value);
- break;
- case 'ML':
- this.setMiterLimit(value);
- break;
- case 'D':
- this.setDash(value[0], value[1]);
- break;
- case 'Font':
- this.setFont(value);
- break;
- case 'CA':
- this.setStrokeAlpha(value);
- break;
- case 'ca':
- this.setFillAlpha(value);
- break;
- default:
- (0, _util.warn)('Unimplemented graphic state ' + key);
- break;
- }
- }
- },
- fill: function SVGGraphics_fill() {
- var current = this.current;
- if (current.element) {
- current.element.setAttributeNS(null, 'fill', current.fillColor);
- current.element.setAttributeNS(null, 'fill-opacity', current.fillAlpha);
- this.endPath();
- }
- },
- stroke: function SVGGraphics_stroke() {
- var current = this.current;
- if (current.element) {
- this._setStrokeAttributes(current.element);
- current.element.setAttributeNS(null, 'fill', 'none');
- this.endPath();
- }
- },
- _setStrokeAttributes: function _setStrokeAttributes(element) {
- var current = this.current;
- element.setAttributeNS(null, 'stroke', current.strokeColor);
- element.setAttributeNS(null, 'stroke-opacity', current.strokeAlpha);
- element.setAttributeNS(null, 'stroke-miterlimit', pf(current.miterLimit));
- element.setAttributeNS(null, 'stroke-linecap', current.lineCap);
- element.setAttributeNS(null, 'stroke-linejoin', current.lineJoin);
- element.setAttributeNS(null, 'stroke-width', pf(current.lineWidth) + 'px');
- element.setAttributeNS(null, 'stroke-dasharray', current.dashArray.map(pf).join(' '));
- element.setAttributeNS(null, 'stroke-dashoffset', pf(current.dashPhase) + 'px');
- },
-
- eoFill: function SVGGraphics_eoFill() {
- if (this.current.element) {
- this.current.element.setAttributeNS(null, 'fill-rule', 'evenodd');
- }
- this.fill();
- },
- fillStroke: function SVGGraphics_fillStroke() {
- this.stroke();
- this.fill();
- },
- eoFillStroke: function SVGGraphics_eoFillStroke() {
- if (this.current.element) {
- this.current.element.setAttributeNS(null, 'fill-rule', 'evenodd');
- }
- this.fillStroke();
- },
- closeStroke: function SVGGraphics_closeStroke() {
- this.closePath();
- this.stroke();
- },
- closeFillStroke: function SVGGraphics_closeFillStroke() {
- this.closePath();
- this.fillStroke();
- },
- closeEOFillStroke: function closeEOFillStroke() {
- this.closePath();
- this.eoFillStroke();
- },
-
- paintSolidColorImageMask: function SVGGraphics_paintSolidColorImageMask() {
- var current = this.current;
- var rect = this.svgFactory.createElement('svg:rect');
- rect.setAttributeNS(null, 'x', '0');
- rect.setAttributeNS(null, 'y', '0');
- rect.setAttributeNS(null, 'width', '1px');
- rect.setAttributeNS(null, 'height', '1px');
- rect.setAttributeNS(null, 'fill', current.fillColor);
- this._ensureTransformGroup().appendChild(rect);
- },
- paintJpegXObject: function SVGGraphics_paintJpegXObject(objId, w, h) {
- var imgObj = this.objs.get(objId);
- var imgEl = this.svgFactory.createElement('svg:image');
- imgEl.setAttributeNS(XLINK_NS, 'xlink:href', imgObj.src);
- imgEl.setAttributeNS(null, 'width', pf(w));
- imgEl.setAttributeNS(null, 'height', pf(h));
- imgEl.setAttributeNS(null, 'x', '0');
- imgEl.setAttributeNS(null, 'y', pf(-h));
- imgEl.setAttributeNS(null, 'transform', 'scale(' + pf(1 / w) + ' ' + pf(-1 / h) + ')');
- this._ensureTransformGroup().appendChild(imgEl);
- },
- paintImageXObject: function SVGGraphics_paintImageXObject(objId) {
- var imgData = this.objs.get(objId);
- if (!imgData) {
- (0, _util.warn)('Dependent image isn\'t ready yet');
- return;
- }
- this.paintInlineImageXObject(imgData);
- },
- paintInlineImageXObject: function SVGGraphics_paintInlineImageXObject(imgData, mask) {
- var width = imgData.width;
- var height = imgData.height;
- var imgSrc = convertImgDataToPng(imgData, this.forceDataSchema, !!mask);
- var cliprect = this.svgFactory.createElement('svg:rect');
- cliprect.setAttributeNS(null, 'x', '0');
- cliprect.setAttributeNS(null, 'y', '0');
- cliprect.setAttributeNS(null, 'width', pf(width));
- cliprect.setAttributeNS(null, 'height', pf(height));
- this.current.element = cliprect;
- this.clip('nonzero');
- var imgEl = this.svgFactory.createElement('svg:image');
- imgEl.setAttributeNS(XLINK_NS, 'xlink:href', imgSrc);
- imgEl.setAttributeNS(null, 'x', '0');
- imgEl.setAttributeNS(null, 'y', pf(-height));
- imgEl.setAttributeNS(null, 'width', pf(width) + 'px');
- imgEl.setAttributeNS(null, 'height', pf(height) + 'px');
- imgEl.setAttributeNS(null, 'transform', 'scale(' + pf(1 / width) + ' ' + pf(-1 / height) + ')');
- if (mask) {
- mask.appendChild(imgEl);
- } else {
- this._ensureTransformGroup().appendChild(imgEl);
- }
- },
- paintImageMaskXObject: function SVGGraphics_paintImageMaskXObject(imgData) {
- var current = this.current;
- var width = imgData.width;
- var height = imgData.height;
- var fillColor = current.fillColor;
- current.maskId = 'mask' + maskCount++;
- var mask = this.svgFactory.createElement('svg:mask');
- mask.setAttributeNS(null, 'id', current.maskId);
- var rect = this.svgFactory.createElement('svg:rect');
- rect.setAttributeNS(null, 'x', '0');
- rect.setAttributeNS(null, 'y', '0');
- rect.setAttributeNS(null, 'width', pf(width));
- rect.setAttributeNS(null, 'height', pf(height));
- rect.setAttributeNS(null, 'fill', fillColor);
- rect.setAttributeNS(null, 'mask', 'url(#' + current.maskId + ')');
- this.defs.appendChild(mask);
- this._ensureTransformGroup().appendChild(rect);
- this.paintInlineImageXObject(imgData, mask);
- },
- paintFormXObjectBegin: function SVGGraphics_paintFormXObjectBegin(matrix, bbox) {
- if (Array.isArray(matrix) && matrix.length === 6) {
- this.transform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
- }
- if (Array.isArray(bbox) && bbox.length === 4) {
- var width = bbox[2] - bbox[0];
- var height = bbox[3] - bbox[1];
- var cliprect = this.svgFactory.createElement('svg:rect');
- cliprect.setAttributeNS(null, 'x', bbox[0]);
- cliprect.setAttributeNS(null, 'y', bbox[1]);
- cliprect.setAttributeNS(null, 'width', pf(width));
- cliprect.setAttributeNS(null, 'height', pf(height));
- this.current.element = cliprect;
- this.clip('nonzero');
- this.endPath();
- }
- },
- paintFormXObjectEnd: function SVGGraphics_paintFormXObjectEnd() {},
- _initialize: function _initialize(viewport) {
- var svg = this.svgFactory.create(viewport.width, viewport.height);
- var definitions = this.svgFactory.createElement('svg:defs');
- svg.appendChild(definitions);
- this.defs = definitions;
- var rootGroup = this.svgFactory.createElement('svg:g');
- rootGroup.setAttributeNS(null, 'transform', pm(viewport.transform));
- svg.appendChild(rootGroup);
- this.svg = rootGroup;
- return svg;
- },
-
- _ensureClipGroup: function SVGGraphics_ensureClipGroup() {
- if (!this.current.clipGroup) {
- var clipGroup = this.svgFactory.createElement('svg:g');
- clipGroup.setAttributeNS(null, 'clip-path', this.current.activeClipUrl);
- this.svg.appendChild(clipGroup);
- this.current.clipGroup = clipGroup;
- }
- return this.current.clipGroup;
- },
- _ensureTransformGroup: function SVGGraphics_ensureTransformGroup() {
- if (!this.tgrp) {
- this.tgrp = this.svgFactory.createElement('svg:g');
- this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix));
- if (this.current.activeClipUrl) {
- this._ensureClipGroup().appendChild(this.tgrp);
- } else {
- this.svg.appendChild(this.tgrp);
- }
- }
- return this.tgrp;
- }
- };
- return SVGGraphics;
- }();
-}
-exports.SVGGraphics = SVGGraphics;
-
-/***/ }),
-/* 148 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.PDFNodeStream = undefined;
-
-var _regenerator = __w_pdfjs_require__(137);
-
-var _regenerator2 = _interopRequireDefault(_regenerator);
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-var _util = __w_pdfjs_require__(1);
-
-var _network_utils = __w_pdfjs_require__(149);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
-
-function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
-
-function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-var fs = require('fs');
-var http = require('http');
-var https = require('https');
-var url = require('url');
-
-var fileUriRegex = /^file:\/\/\/[a-zA-Z]:\//;
-function parseUrl(sourceUrl) {
- var parsedUrl = url.parse(sourceUrl);
- if (parsedUrl.protocol === 'file:' || parsedUrl.host) {
- return parsedUrl;
- }
- if (/^[a-z]:[/\\]/i.test(sourceUrl)) {
- return url.parse('file:///' + sourceUrl);
- }
- if (!parsedUrl.host) {
- parsedUrl.protocol = 'file:';
- }
- return parsedUrl;
-}
-
-var PDFNodeStream = function () {
- function PDFNodeStream(source) {
- _classCallCheck(this, PDFNodeStream);
-
- this.source = source;
- this.url = parseUrl(source.url);
- this.isHttp = this.url.protocol === 'http:' || this.url.protocol === 'https:';
- this.isFsUrl = this.url.protocol === 'file:';
- this.httpHeaders = this.isHttp && source.httpHeaders || {};
- this._fullRequest = null;
- this._rangeRequestReaders = [];
- }
-
- _createClass(PDFNodeStream, [{
- key: 'getFullReader',
- value: function getFullReader() {
- (0, _util.assert)(!this._fullRequest);
- this._fullRequest = this.isFsUrl ? new PDFNodeStreamFsFullReader(this) : new PDFNodeStreamFullReader(this);
- return this._fullRequest;
- }
- }, {
- key: 'getRangeReader',
- value: function getRangeReader(start, end) {
- var rangeReader = this.isFsUrl ? new PDFNodeStreamFsRangeReader(this, start, end) : new PDFNodeStreamRangeReader(this, start, end);
- this._rangeRequestReaders.push(rangeReader);
- return rangeReader;
- }
- }, {
- key: 'cancelAllRequests',
- value: function cancelAllRequests(reason) {
- if (this._fullRequest) {
- this._fullRequest.cancel(reason);
- }
- var readers = this._rangeRequestReaders.slice(0);
- readers.forEach(function (reader) {
- reader.cancel(reason);
- });
- }
- }]);
-
- return PDFNodeStream;
-}();
-
-var BaseFullReader = function () {
- function BaseFullReader(stream) {
- _classCallCheck(this, BaseFullReader);
-
- this._url = stream.url;
- this._done = false;
- this._storedError = null;
- this.onProgress = null;
- var source = stream.source;
- this._contentLength = source.length;
- this._loaded = 0;
- this._filename = null;
- this._disableRange = source.disableRange || false;
- this._rangeChunkSize = source.rangeChunkSize;
- if (!this._rangeChunkSize && !this._disableRange) {
- this._disableRange = true;
- }
- this._isStreamingSupported = !source.disableStream;
- this._isRangeSupported = !source.disableRange;
- this._readableStream = null;
- this._readCapability = (0, _util.createPromiseCapability)();
- this._headersCapability = (0, _util.createPromiseCapability)();
- }
-
- _createClass(BaseFullReader, [{
- key: 'read',
- value: function () {
- var _ref = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee() {
- var chunk, buffer;
- return _regenerator2.default.wrap(function _callee$(_context) {
- while (1) {
- switch (_context.prev = _context.next) {
- case 0:
- _context.next = 2;
- return this._readCapability.promise;
-
- case 2:
- if (!this._done) {
- _context.next = 4;
- break;
- }
-
- return _context.abrupt('return', {
- value: undefined,
- done: true
- });
-
- case 4:
- if (!this._storedError) {
- _context.next = 6;
- break;
- }
-
- throw this._storedError;
-
- case 6:
- chunk = this._readableStream.read();
-
- if (!(chunk === null)) {
- _context.next = 10;
- break;
- }
-
- this._readCapability = (0, _util.createPromiseCapability)();
- return _context.abrupt('return', this.read());
-
- case 10:
- this._loaded += chunk.length;
- if (this.onProgress) {
- this.onProgress({
- loaded: this._loaded,
- total: this._contentLength
- });
- }
- buffer = new Uint8Array(chunk).buffer;
- return _context.abrupt('return', {
- value: buffer,
- done: false
- });
-
- case 14:
- case 'end':
- return _context.stop();
- }
- }
- }, _callee, this);
- }));
-
- function read() {
- return _ref.apply(this, arguments);
- }
-
- return read;
- }()
- }, {
- key: 'cancel',
- value: function cancel(reason) {
- if (!this._readableStream) {
- this._error(reason);
- return;
- }
- this._readableStream.destroy(reason);
- }
- }, {
- key: '_error',
- value: function _error(reason) {
- this._storedError = reason;
- this._readCapability.resolve();
- }
- }, {
- key: '_setReadableStream',
- value: function _setReadableStream(readableStream) {
- var _this = this;
-
- this._readableStream = readableStream;
- readableStream.on('readable', function () {
- _this._readCapability.resolve();
- });
- readableStream.on('end', function () {
- readableStream.destroy();
- _this._done = true;
- _this._readCapability.resolve();
- });
- readableStream.on('error', function (reason) {
- _this._error(reason);
- });
- if (!this._isStreamingSupported && this._isRangeSupported) {
- this._error(new _util.AbortException('streaming is disabled'));
- }
- if (this._storedError) {
- this._readableStream.destroy(this._storedError);
- }
- }
- }, {
- key: 'headersReady',
- get: function get() {
- return this._headersCapability.promise;
- }
- }, {
- key: 'filename',
- get: function get() {
- return this._filename;
- }
- }, {
- key: 'contentLength',
- get: function get() {
- return this._contentLength;
- }
- }, {
- key: 'isRangeSupported',
- get: function get() {
- return this._isRangeSupported;
- }
- }, {
- key: 'isStreamingSupported',
- get: function get() {
- return this._isStreamingSupported;
- }
- }]);
-
- return BaseFullReader;
-}();
-
-var BaseRangeReader = function () {
- function BaseRangeReader(stream) {
- _classCallCheck(this, BaseRangeReader);
-
- this._url = stream.url;
- this._done = false;
- this._storedError = null;
- this.onProgress = null;
- this._loaded = 0;
- this._readableStream = null;
- this._readCapability = (0, _util.createPromiseCapability)();
- var source = stream.source;
- this._isStreamingSupported = !source.disableStream;
- }
-
- _createClass(BaseRangeReader, [{
- key: 'read',
- value: function () {
- var _ref2 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee2() {
- var chunk, buffer;
- return _regenerator2.default.wrap(function _callee2$(_context2) {
- while (1) {
- switch (_context2.prev = _context2.next) {
- case 0:
- _context2.next = 2;
- return this._readCapability.promise;
-
- case 2:
- if (!this._done) {
- _context2.next = 4;
- break;
- }
-
- return _context2.abrupt('return', {
- value: undefined,
- done: true
- });
-
- case 4:
- if (!this._storedError) {
- _context2.next = 6;
- break;
- }
-
- throw this._storedError;
-
- case 6:
- chunk = this._readableStream.read();
-
- if (!(chunk === null)) {
- _context2.next = 10;
- break;
- }
-
- this._readCapability = (0, _util.createPromiseCapability)();
- return _context2.abrupt('return', this.read());
-
- case 10:
- this._loaded += chunk.length;
- if (this.onProgress) {
- this.onProgress({ loaded: this._loaded });
- }
- buffer = new Uint8Array(chunk).buffer;
- return _context2.abrupt('return', {
- value: buffer,
- done: false
- });
-
- case 14:
- case 'end':
- return _context2.stop();
- }
- }
- }, _callee2, this);
- }));
-
- function read() {
- return _ref2.apply(this, arguments);
- }
-
- return read;
- }()
- }, {
- key: 'cancel',
- value: function cancel(reason) {
- if (!this._readableStream) {
- this._error(reason);
- return;
- }
- this._readableStream.destroy(reason);
- }
- }, {
- key: '_error',
- value: function _error(reason) {
- this._storedError = reason;
- this._readCapability.resolve();
- }
- }, {
- key: '_setReadableStream',
- value: function _setReadableStream(readableStream) {
- var _this2 = this;
-
- this._readableStream = readableStream;
- readableStream.on('readable', function () {
- _this2._readCapability.resolve();
- });
- readableStream.on('end', function () {
- readableStream.destroy();
- _this2._done = true;
- _this2._readCapability.resolve();
- });
- readableStream.on('error', function (reason) {
- _this2._error(reason);
- });
- if (this._storedError) {
- this._readableStream.destroy(this._storedError);
- }
- }
- }, {
- key: 'isStreamingSupported',
- get: function get() {
- return this._isStreamingSupported;
- }
- }]);
-
- return BaseRangeReader;
-}();
-
-function createRequestOptions(url, headers) {
- return {
- protocol: url.protocol,
- auth: url.auth,
- host: url.hostname,
- port: url.port,
- path: url.path,
- method: 'GET',
- headers: headers
- };
-}
-
-var PDFNodeStreamFullReader = function (_BaseFullReader) {
- _inherits(PDFNodeStreamFullReader, _BaseFullReader);
-
- function PDFNodeStreamFullReader(stream) {
- _classCallCheck(this, PDFNodeStreamFullReader);
-
- var _this3 = _possibleConstructorReturn(this, (PDFNodeStreamFullReader.__proto__ || Object.getPrototypeOf(PDFNodeStreamFullReader)).call(this, stream));
-
- var handleResponse = function handleResponse(response) {
- if (response.statusCode === 404) {
- var error = new _util.MissingPDFException('Missing PDF "' + _this3._url + '".');
- _this3._storedError = error;
- _this3._headersCapability.reject(error);
- return;
- }
- _this3._headersCapability.resolve();
- _this3._setReadableStream(response);
- var getResponseHeader = function getResponseHeader(name) {
- return _this3._readableStream.headers[name.toLowerCase()];
- };
-
- var _validateRangeRequest = (0, _network_utils.validateRangeRequestCapabilities)({
- getResponseHeader: getResponseHeader,
- isHttp: stream.isHttp,
- rangeChunkSize: _this3._rangeChunkSize,
- disableRange: _this3._disableRange
- }),
- allowRangeRequests = _validateRangeRequest.allowRangeRequests,
- suggestedLength = _validateRangeRequest.suggestedLength;
-
- _this3._isRangeSupported = allowRangeRequests;
- _this3._contentLength = suggestedLength || _this3._contentLength;
- _this3._filename = (0, _network_utils.extractFilenameFromHeader)(getResponseHeader);
- };
- _this3._request = null;
- if (_this3._url.protocol === 'http:') {
- _this3._request = http.request(createRequestOptions(_this3._url, stream.httpHeaders), handleResponse);
- } else {
- _this3._request = https.request(createRequestOptions(_this3._url, stream.httpHeaders), handleResponse);
- }
- _this3._request.on('error', function (reason) {
- _this3._storedError = reason;
- _this3._headersCapability.reject(reason);
- });
- _this3._request.end();
- return _this3;
- }
-
- return PDFNodeStreamFullReader;
-}(BaseFullReader);
-
-var PDFNodeStreamRangeReader = function (_BaseRangeReader) {
- _inherits(PDFNodeStreamRangeReader, _BaseRangeReader);
-
- function PDFNodeStreamRangeReader(stream, start, end) {
- _classCallCheck(this, PDFNodeStreamRangeReader);
-
- var _this4 = _possibleConstructorReturn(this, (PDFNodeStreamRangeReader.__proto__ || Object.getPrototypeOf(PDFNodeStreamRangeReader)).call(this, stream));
-
- _this4._httpHeaders = {};
- for (var property in stream.httpHeaders) {
- var value = stream.httpHeaders[property];
- if (typeof value === 'undefined') {
- continue;
- }
- _this4._httpHeaders[property] = value;
- }
- _this4._httpHeaders['Range'] = 'bytes=' + start + '-' + (end - 1);
- var handleResponse = function handleResponse(response) {
- if (response.statusCode === 404) {
- var error = new _util.MissingPDFException('Missing PDF "' + _this4._url + '".');
- _this4._storedError = error;
- return;
- }
- _this4._setReadableStream(response);
- };
- _this4._request = null;
- if (_this4._url.protocol === 'http:') {
- _this4._request = http.request(createRequestOptions(_this4._url, _this4._httpHeaders), handleResponse);
- } else {
- _this4._request = https.request(createRequestOptions(_this4._url, _this4._httpHeaders), handleResponse);
- }
- _this4._request.on('error', function (reason) {
- _this4._storedError = reason;
- });
- _this4._request.end();
- return _this4;
- }
-
- return PDFNodeStreamRangeReader;
-}(BaseRangeReader);
-
-var PDFNodeStreamFsFullReader = function (_BaseFullReader2) {
- _inherits(PDFNodeStreamFsFullReader, _BaseFullReader2);
-
- function PDFNodeStreamFsFullReader(stream) {
- _classCallCheck(this, PDFNodeStreamFsFullReader);
-
- var _this5 = _possibleConstructorReturn(this, (PDFNodeStreamFsFullReader.__proto__ || Object.getPrototypeOf(PDFNodeStreamFsFullReader)).call(this, stream));
-
- var path = decodeURIComponent(_this5._url.path);
- if (fileUriRegex.test(_this5._url.href)) {
- path = path.replace(/^\//, '');
- }
- fs.lstat(path, function (error, stat) {
- if (error) {
- if (error.code === 'ENOENT') {
- error = new _util.MissingPDFException('Missing PDF "' + path + '".');
- }
- _this5._storedError = error;
- _this5._headersCapability.reject(error);
- return;
- }
- _this5._contentLength = stat.size;
- _this5._setReadableStream(fs.createReadStream(path));
- _this5._headersCapability.resolve();
- });
- return _this5;
- }
-
- return PDFNodeStreamFsFullReader;
-}(BaseFullReader);
-
-var PDFNodeStreamFsRangeReader = function (_BaseRangeReader2) {
- _inherits(PDFNodeStreamFsRangeReader, _BaseRangeReader2);
-
- function PDFNodeStreamFsRangeReader(stream, start, end) {
- _classCallCheck(this, PDFNodeStreamFsRangeReader);
-
- var _this6 = _possibleConstructorReturn(this, (PDFNodeStreamFsRangeReader.__proto__ || Object.getPrototypeOf(PDFNodeStreamFsRangeReader)).call(this, stream));
-
- var path = decodeURIComponent(_this6._url.path);
- if (fileUriRegex.test(_this6._url.href)) {
- path = path.replace(/^\//, '');
- }
- _this6._setReadableStream(fs.createReadStream(path, {
- start: start,
- end: end - 1
- }));
- return _this6;
- }
-
- return PDFNodeStreamFsRangeReader;
-}(BaseRangeReader);
-
-exports.PDFNodeStream = PDFNodeStream;
-
-/***/ }),
-/* 149 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.validateResponseStatus = exports.validateRangeRequestCapabilities = exports.extractFilenameFromHeader = exports.createResponseStatusError = undefined;
-
-var _util = __w_pdfjs_require__(1);
-
-var _content_disposition = __w_pdfjs_require__(150);
-
-function validateRangeRequestCapabilities(_ref) {
- var getResponseHeader = _ref.getResponseHeader,
- isHttp = _ref.isHttp,
- rangeChunkSize = _ref.rangeChunkSize,
- disableRange = _ref.disableRange;
-
- (0, _util.assert)(rangeChunkSize > 0, 'Range chunk size must be larger than zero');
- var returnValues = {
- allowRangeRequests: false,
- suggestedLength: undefined
- };
- var length = parseInt(getResponseHeader('Content-Length'), 10);
- if (!Number.isInteger(length)) {
- return returnValues;
- }
- returnValues.suggestedLength = length;
- if (length <= 2 * rangeChunkSize) {
- return returnValues;
- }
- if (disableRange || !isHttp) {
- return returnValues;
- }
- if (getResponseHeader('Accept-Ranges') !== 'bytes') {
- return returnValues;
- }
- var contentEncoding = getResponseHeader('Content-Encoding') || 'identity';
- if (contentEncoding !== 'identity') {
- return returnValues;
- }
- returnValues.allowRangeRequests = true;
- return returnValues;
-}
-function extractFilenameFromHeader(getResponseHeader) {
- var contentDisposition = getResponseHeader('Content-Disposition');
- if (contentDisposition) {
- var filename = (0, _content_disposition.getFilenameFromContentDispositionHeader)(contentDisposition);
- if (/\.pdf$/i.test(filename)) {
- return filename;
- }
- }
- return null;
-}
-function createResponseStatusError(status, url) {
- if (status === 404 || status === 0 && /^file:/.test(url)) {
- return new _util.MissingPDFException('Missing PDF "' + url + '".');
- }
- return new _util.UnexpectedResponseException('Unexpected server response (' + status + ') while retrieving PDF "' + url + '".', status);
-}
-function validateResponseStatus(status) {
- return status === 200 || status === 206;
-}
-exports.createResponseStatusError = createResponseStatusError;
-exports.extractFilenameFromHeader = extractFilenameFromHeader;
-exports.validateRangeRequestCapabilities = validateRangeRequestCapabilities;
-exports.validateResponseStatus = validateResponseStatus;
-
-/***/ }),
-/* 150 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-
-var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
-
-function getFilenameFromContentDispositionHeader(contentDisposition) {
- var needsEncodingFixup = true;
- var tmp = toParamRegExp('filename\\*', 'i').exec(contentDisposition);
- if (tmp) {
- tmp = tmp[1];
- var filename = rfc2616unquote(tmp);
- filename = unescape(filename);
- filename = rfc5987decode(filename);
- filename = rfc2047decode(filename);
- return fixupEncoding(filename);
- }
- tmp = rfc2231getparam(contentDisposition);
- if (tmp) {
- var _filename = rfc2047decode(tmp);
- return fixupEncoding(_filename);
- }
- tmp = toParamRegExp('filename', 'i').exec(contentDisposition);
- if (tmp) {
- tmp = tmp[1];
- var _filename2 = rfc2616unquote(tmp);
- _filename2 = rfc2047decode(_filename2);
- return fixupEncoding(_filename2);
- }
- function toParamRegExp(attributePattern, flags) {
- return new RegExp('(?:^|;)\\s*' + attributePattern + '\\s*=\\s*' + '(' + '[^";\\s][^;\\s]*' + '|' + '"(?:[^"\\\\]|\\\\"?)+"?' + ')', flags);
- }
- function textdecode(encoding, value) {
- if (encoding) {
- if (!/^[\x00-\xFF]+$/.test(value)) {
- return value;
- }
- try {
- var decoder = new TextDecoder(encoding, { fatal: true });
- var bytes = new Array(value.length);
- for (var i = 0; i < value.length; ++i) {
- bytes[i] = value.charCodeAt(i);
- }
- value = decoder.decode(new Uint8Array(bytes));
- needsEncodingFixup = false;
- } catch (e) {
- if (/^utf-?8$/i.test(encoding)) {
- try {
- value = decodeURIComponent(escape(value));
- needsEncodingFixup = false;
- } catch (err) {}
- }
- }
- }
- return value;
- }
- function fixupEncoding(value) {
- if (needsEncodingFixup && /[\x80-\xff]/.test(value)) {
- value = textdecode('utf-8', value);
- if (needsEncodingFixup) {
- value = textdecode('iso-8859-1', value);
- }
- }
- return value;
- }
- function rfc2231getparam(contentDisposition) {
- var matches = [],
- match = void 0;
- var iter = toParamRegExp('filename\\*((?!0\\d)\\d+)(\\*?)', 'ig');
- while ((match = iter.exec(contentDisposition)) !== null) {
- var _match = match,
- _match2 = _slicedToArray(_match, 4),
- n = _match2[1],
- quot = _match2[2],
- part = _match2[3];
-
- n = parseInt(n, 10);
- if (n in matches) {
- if (n === 0) {
- break;
- }
- continue;
- }
- matches[n] = [quot, part];
- }
- var parts = [];
- for (var _n = 0; _n < matches.length; ++_n) {
- if (!(_n in matches)) {
- break;
- }
-
- var _matches$_n = _slicedToArray(matches[_n], 2),
- _quot = _matches$_n[0],
- _part = _matches$_n[1];
-
- _part = rfc2616unquote(_part);
- if (_quot) {
- _part = unescape(_part);
- if (_n === 0) {
- _part = rfc5987decode(_part);
- }
- }
- parts.push(_part);
- }
- return parts.join('');
- }
- function rfc2616unquote(value) {
- if (value.charAt(0) === '"') {
- var parts = value.slice(1).split('\\"');
- for (var i = 0; i < parts.length; ++i) {
- var quotindex = parts[i].indexOf('"');
- if (quotindex !== -1) {
- parts[i] = parts[i].slice(0, quotindex);
- parts.length = i + 1;
- }
- parts[i] = parts[i].replace(/\\(.)/g, '$1');
- }
- value = parts.join('"');
- }
- return value;
- }
- function rfc5987decode(extvalue) {
- var encodingend = extvalue.indexOf('\'');
- if (encodingend === -1) {
- return extvalue;
- }
- var encoding = extvalue.slice(0, encodingend);
- var langvalue = extvalue.slice(encodingend + 1);
- var value = langvalue.replace(/^[^']*'/, '');
- return textdecode(encoding, value);
- }
- function rfc2047decode(value) {
- if (value.slice(0, 2) !== '=?' || /[\x00-\x19\x80-\xff]/.test(value)) {
- return value;
- }
- return value.replace(/=\?([\w-]*)\?([QqBb])\?((?:[^?]|\?(?!=))*)\?=/g, function (_, charset, encoding, text) {
- if (encoding === 'q' || encoding === 'Q') {
- text = text.replace(/_/g, ' ');
- text = text.replace(/=([0-9a-fA-F]{2})/g, function (_, hex) {
- return String.fromCharCode(parseInt(hex, 16));
- });
- return textdecode(charset, text);
- }
- try {
- text = atob(text);
- } catch (e) {}
- return textdecode(charset, text);
- });
- }
- return '';
-}
-exports.getFilenameFromContentDispositionHeader = getFilenameFromContentDispositionHeader;
-
-/***/ }),
-/* 151 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.PDFFetchStream = undefined;
-
-var _regenerator = __w_pdfjs_require__(137);
-
-var _regenerator2 = _interopRequireDefault(_regenerator);
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-var _util = __w_pdfjs_require__(1);
-
-var _network_utils = __w_pdfjs_require__(149);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-function createFetchOptions(headers, withCredentials, abortController) {
- return {
- method: 'GET',
- headers: headers,
- signal: abortController && abortController.signal,
- mode: 'cors',
- credentials: withCredentials ? 'include' : 'same-origin',
- redirect: 'follow'
- };
-}
-
-var PDFFetchStream = function () {
- function PDFFetchStream(source) {
- _classCallCheck(this, PDFFetchStream);
-
- this.source = source;
- this.isHttp = /^https?:/i.test(source.url);
- this.httpHeaders = this.isHttp && source.httpHeaders || {};
- this._fullRequestReader = null;
- this._rangeRequestReaders = [];
- }
-
- _createClass(PDFFetchStream, [{
- key: 'getFullReader',
- value: function getFullReader() {
- (0, _util.assert)(!this._fullRequestReader);
- this._fullRequestReader = new PDFFetchStreamReader(this);
- return this._fullRequestReader;
- }
- }, {
- key: 'getRangeReader',
- value: function getRangeReader(begin, end) {
- var reader = new PDFFetchStreamRangeReader(this, begin, end);
- this._rangeRequestReaders.push(reader);
- return reader;
- }
- }, {
- key: 'cancelAllRequests',
- value: function cancelAllRequests(reason) {
- if (this._fullRequestReader) {
- this._fullRequestReader.cancel(reason);
- }
- var readers = this._rangeRequestReaders.slice(0);
- readers.forEach(function (reader) {
- reader.cancel(reason);
- });
- }
- }]);
-
- return PDFFetchStream;
-}();
-
-var PDFFetchStreamReader = function () {
- function PDFFetchStreamReader(stream) {
- var _this = this;
-
- _classCallCheck(this, PDFFetchStreamReader);
-
- this._stream = stream;
- this._reader = null;
- this._loaded = 0;
- this._filename = null;
- var source = stream.source;
- this._withCredentials = source.withCredentials;
- this._contentLength = source.length;
- this._headersCapability = (0, _util.createPromiseCapability)();
- this._disableRange = source.disableRange || false;
- this._rangeChunkSize = source.rangeChunkSize;
- if (!this._rangeChunkSize && !this._disableRange) {
- this._disableRange = true;
- }
- if (typeof AbortController !== 'undefined') {
- this._abortController = new AbortController();
- }
- this._isStreamingSupported = !source.disableStream;
- this._isRangeSupported = !source.disableRange;
- this._headers = new Headers();
- for (var property in this._stream.httpHeaders) {
- var value = this._stream.httpHeaders[property];
- if (typeof value === 'undefined') {
- continue;
- }
- this._headers.append(property, value);
- }
- var url = source.url;
- fetch(url, createFetchOptions(this._headers, this._withCredentials, this._abortController)).then(function (response) {
- if (!(0, _network_utils.validateResponseStatus)(response.status)) {
- throw (0, _network_utils.createResponseStatusError)(response.status, url);
- }
- _this._reader = response.body.getReader();
- _this._headersCapability.resolve();
- var getResponseHeader = function getResponseHeader(name) {
- return response.headers.get(name);
- };
-
- var _validateRangeRequest = (0, _network_utils.validateRangeRequestCapabilities)({
- getResponseHeader: getResponseHeader,
- isHttp: _this._stream.isHttp,
- rangeChunkSize: _this._rangeChunkSize,
- disableRange: _this._disableRange
- }),
- allowRangeRequests = _validateRangeRequest.allowRangeRequests,
- suggestedLength = _validateRangeRequest.suggestedLength;
-
- _this._isRangeSupported = allowRangeRequests;
- _this._contentLength = suggestedLength || _this._contentLength;
- _this._filename = (0, _network_utils.extractFilenameFromHeader)(getResponseHeader);
- if (!_this._isStreamingSupported && _this._isRangeSupported) {
- _this.cancel(new _util.AbortException('streaming is disabled'));
- }
- }).catch(this._headersCapability.reject);
- this.onProgress = null;
- }
-
- _createClass(PDFFetchStreamReader, [{
- key: 'read',
- value: function () {
- var _ref = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee() {
- var _ref2, value, done, buffer;
-
- return _regenerator2.default.wrap(function _callee$(_context) {
- while (1) {
- switch (_context.prev = _context.next) {
- case 0:
- _context.next = 2;
- return this._headersCapability.promise;
-
- case 2:
- _context.next = 4;
- return this._reader.read();
-
- case 4:
- _ref2 = _context.sent;
- value = _ref2.value;
- done = _ref2.done;
-
- if (!done) {
- _context.next = 9;
- break;
- }
-
- return _context.abrupt('return', {
- value: value,
- done: done
- });
-
- case 9:
- this._loaded += value.byteLength;
- if (this.onProgress) {
- this.onProgress({
- loaded: this._loaded,
- total: this._contentLength
- });
- }
- buffer = new Uint8Array(value).buffer;
- return _context.abrupt('return', {
- value: buffer,
- done: false
- });
-
- case 13:
- case 'end':
- return _context.stop();
- }
- }
- }, _callee, this);
- }));
-
- function read() {
- return _ref.apply(this, arguments);
- }
-
- return read;
- }()
- }, {
- key: 'cancel',
- value: function cancel(reason) {
- if (this._reader) {
- this._reader.cancel(reason);
- }
- if (this._abortController) {
- this._abortController.abort();
- }
- }
- }, {
- key: 'headersReady',
- get: function get() {
- return this._headersCapability.promise;
- }
- }, {
- key: 'filename',
- get: function get() {
- return this._filename;
- }
- }, {
- key: 'contentLength',
- get: function get() {
- return this._contentLength;
- }
- }, {
- key: 'isRangeSupported',
- get: function get() {
- return this._isRangeSupported;
- }
- }, {
- key: 'isStreamingSupported',
- get: function get() {
- return this._isStreamingSupported;
- }
- }]);
-
- return PDFFetchStreamReader;
-}();
-
-var PDFFetchStreamRangeReader = function () {
- function PDFFetchStreamRangeReader(stream, begin, end) {
- var _this2 = this;
-
- _classCallCheck(this, PDFFetchStreamRangeReader);
-
- this._stream = stream;
- this._reader = null;
- this._loaded = 0;
- var source = stream.source;
- this._withCredentials = source.withCredentials;
- this._readCapability = (0, _util.createPromiseCapability)();
- this._isStreamingSupported = !source.disableStream;
- if (typeof AbortController !== 'undefined') {
- this._abortController = new AbortController();
- }
- this._headers = new Headers();
- for (var property in this._stream.httpHeaders) {
- var value = this._stream.httpHeaders[property];
- if (typeof value === 'undefined') {
- continue;
- }
- this._headers.append(property, value);
- }
- var rangeStr = begin + '-' + (end - 1);
- this._headers.append('Range', 'bytes=' + rangeStr);
- var url = source.url;
- fetch(url, createFetchOptions(this._headers, this._withCredentials, this._abortController)).then(function (response) {
- if (!(0, _network_utils.validateResponseStatus)(response.status)) {
- throw (0, _network_utils.createResponseStatusError)(response.status, url);
- }
- _this2._readCapability.resolve();
- _this2._reader = response.body.getReader();
- });
- this.onProgress = null;
- }
-
- _createClass(PDFFetchStreamRangeReader, [{
- key: 'read',
- value: function () {
- var _ref3 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee2() {
- var _ref4, value, done, buffer;
-
- return _regenerator2.default.wrap(function _callee2$(_context2) {
- while (1) {
- switch (_context2.prev = _context2.next) {
- case 0:
- _context2.next = 2;
- return this._readCapability.promise;
-
- case 2:
- _context2.next = 4;
- return this._reader.read();
-
- case 4:
- _ref4 = _context2.sent;
- value = _ref4.value;
- done = _ref4.done;
-
- if (!done) {
- _context2.next = 9;
- break;
- }
-
- return _context2.abrupt('return', {
- value: value,
- done: done
- });
-
- case 9:
- this._loaded += value.byteLength;
- if (this.onProgress) {
- this.onProgress({ loaded: this._loaded });
- }
- buffer = new Uint8Array(value).buffer;
- return _context2.abrupt('return', {
- value: buffer,
- done: false
- });
-
- case 13:
- case 'end':
- return _context2.stop();
- }
- }
- }, _callee2, this);
- }));
-
- function read() {
- return _ref3.apply(this, arguments);
- }
-
- return read;
- }()
- }, {
- key: 'cancel',
- value: function cancel(reason) {
- if (this._reader) {
- this._reader.cancel(reason);
- }
- if (this._abortController) {
- this._abortController.abort();
- }
- }
- }, {
- key: 'isStreamingSupported',
- get: function get() {
- return this._isStreamingSupported;
- }
- }]);
-
- return PDFFetchStreamRangeReader;
-}();
-
-exports.PDFFetchStream = PDFFetchStream;
-
-/***/ }),
-/* 152 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.NetworkManager = exports.PDFNetworkStream = undefined;
-
-var _regenerator = __w_pdfjs_require__(137);
-
-var _regenerator2 = _interopRequireDefault(_regenerator);
-
-var _util = __w_pdfjs_require__(1);
-
-var _network_utils = __w_pdfjs_require__(149);
-
-var _global_scope = __w_pdfjs_require__(3);
-
-var _global_scope2 = _interopRequireDefault(_global_scope);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
-
-;
-var OK_RESPONSE = 200;
-var PARTIAL_CONTENT_RESPONSE = 206;
-function NetworkManager(url, args) {
- this.url = url;
- args = args || {};
- this.isHttp = /^https?:/i.test(url);
- this.httpHeaders = this.isHttp && args.httpHeaders || {};
- this.withCredentials = args.withCredentials || false;
- this.getXhr = args.getXhr || function NetworkManager_getXhr() {
- return new XMLHttpRequest();
- };
- this.currXhrId = 0;
- this.pendingRequests = Object.create(null);
- this.loadedRequests = Object.create(null);
-}
-function getArrayBuffer(xhr) {
- var data = xhr.response;
- if (typeof data !== 'string') {
- return data;
- }
- var array = (0, _util.stringToBytes)(data);
- return array.buffer;
-}
-var supportsMozChunked = function supportsMozChunkedClosure() {
- try {
- var x = new XMLHttpRequest();
- x.open('GET', _global_scope2.default.location.href);
- x.responseType = 'moz-chunked-arraybuffer';
- return x.responseType === 'moz-chunked-arraybuffer';
- } catch (e) {
- return false;
- }
-}();
-NetworkManager.prototype = {
- requestRange: function NetworkManager_requestRange(begin, end, listeners) {
- var args = {
- begin: begin,
- end: end
- };
- for (var prop in listeners) {
- args[prop] = listeners[prop];
- }
- return this.request(args);
- },
- requestFull: function NetworkManager_requestFull(listeners) {
- return this.request(listeners);
- },
- request: function NetworkManager_request(args) {
- var xhr = this.getXhr();
- var xhrId = this.currXhrId++;
- var pendingRequest = this.pendingRequests[xhrId] = { xhr: xhr };
- xhr.open('GET', this.url);
- xhr.withCredentials = this.withCredentials;
- for (var property in this.httpHeaders) {
- var value = this.httpHeaders[property];
- if (typeof value === 'undefined') {
- continue;
- }
- xhr.setRequestHeader(property, value);
- }
- if (this.isHttp && 'begin' in args && 'end' in args) {
- var rangeStr = args.begin + '-' + (args.end - 1);
- xhr.setRequestHeader('Range', 'bytes=' + rangeStr);
- pendingRequest.expectedStatus = 206;
- } else {
- pendingRequest.expectedStatus = 200;
- }
- var useMozChunkedLoading = supportsMozChunked && !!args.onProgressiveData;
- if (useMozChunkedLoading) {
- xhr.responseType = 'moz-chunked-arraybuffer';
- pendingRequest.onProgressiveData = args.onProgressiveData;
- pendingRequest.mozChunked = true;
- } else {
- xhr.responseType = 'arraybuffer';
- }
- if (args.onError) {
- xhr.onerror = function (evt) {
- args.onError(xhr.status);
- };
- }
- xhr.onreadystatechange = this.onStateChange.bind(this, xhrId);
- xhr.onprogress = this.onProgress.bind(this, xhrId);
- pendingRequest.onHeadersReceived = args.onHeadersReceived;
- pendingRequest.onDone = args.onDone;
- pendingRequest.onError = args.onError;
- pendingRequest.onProgress = args.onProgress;
- xhr.send(null);
- return xhrId;
- },
- onProgress: function NetworkManager_onProgress(xhrId, evt) {
- var pendingRequest = this.pendingRequests[xhrId];
- if (!pendingRequest) {
- return;
- }
- if (pendingRequest.mozChunked) {
- var chunk = getArrayBuffer(pendingRequest.xhr);
- pendingRequest.onProgressiveData(chunk);
- }
- var onProgress = pendingRequest.onProgress;
- if (onProgress) {
- onProgress(evt);
- }
- },
- onStateChange: function NetworkManager_onStateChange(xhrId, evt) {
- var pendingRequest = this.pendingRequests[xhrId];
- if (!pendingRequest) {
- return;
- }
- var xhr = pendingRequest.xhr;
- if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) {
- pendingRequest.onHeadersReceived();
- delete pendingRequest.onHeadersReceived;
- }
- if (xhr.readyState !== 4) {
- return;
- }
- if (!(xhrId in this.pendingRequests)) {
- return;
- }
- delete this.pendingRequests[xhrId];
- if (xhr.status === 0 && this.isHttp) {
- if (pendingRequest.onError) {
- pendingRequest.onError(xhr.status);
- }
- return;
- }
- var xhrStatus = xhr.status || OK_RESPONSE;
- var ok_response_on_range_request = xhrStatus === OK_RESPONSE && pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE;
- if (!ok_response_on_range_request && xhrStatus !== pendingRequest.expectedStatus) {
- if (pendingRequest.onError) {
- pendingRequest.onError(xhr.status);
- }
- return;
- }
- this.loadedRequests[xhrId] = true;
- var chunk = getArrayBuffer(xhr);
- if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {
- var rangeHeader = xhr.getResponseHeader('Content-Range');
- var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
- var begin = parseInt(matches[1], 10);
- pendingRequest.onDone({
- begin: begin,
- chunk: chunk
- });
- } else if (pendingRequest.onProgressiveData) {
- pendingRequest.onDone(null);
- } else if (chunk) {
- pendingRequest.onDone({
- begin: 0,
- chunk: chunk
- });
- } else if (pendingRequest.onError) {
- pendingRequest.onError(xhr.status);
- }
- },
- hasPendingRequests: function NetworkManager_hasPendingRequests() {
- for (var xhrId in this.pendingRequests) {
- return true;
- }
- return false;
- },
- getRequestXhr: function NetworkManager_getXhr(xhrId) {
- return this.pendingRequests[xhrId].xhr;
- },
- isStreamingRequest: function NetworkManager_isStreamingRequest(xhrId) {
- return !!this.pendingRequests[xhrId].onProgressiveData;
- },
- isPendingRequest: function NetworkManager_isPendingRequest(xhrId) {
- return xhrId in this.pendingRequests;
- },
- isLoadedRequest: function NetworkManager_isLoadedRequest(xhrId) {
- return xhrId in this.loadedRequests;
- },
- abortAllRequests: function NetworkManager_abortAllRequests() {
- for (var xhrId in this.pendingRequests) {
- this.abortRequest(xhrId | 0);
- }
- },
- abortRequest: function NetworkManager_abortRequest(xhrId) {
- var xhr = this.pendingRequests[xhrId].xhr;
- delete this.pendingRequests[xhrId];
- xhr.abort();
- }
-};
-function PDFNetworkStream(source) {
- this._source = source;
- this._manager = new NetworkManager(source.url, {
- httpHeaders: source.httpHeaders,
- withCredentials: source.withCredentials
- });
- this._rangeChunkSize = source.rangeChunkSize;
- this._fullRequestReader = null;
- this._rangeRequestReaders = [];
-}
-PDFNetworkStream.prototype = {
- _onRangeRequestReaderClosed: function PDFNetworkStream_onRangeRequestReaderClosed(reader) {
- var i = this._rangeRequestReaders.indexOf(reader);
- if (i >= 0) {
- this._rangeRequestReaders.splice(i, 1);
- }
- },
- getFullReader: function PDFNetworkStream_getFullReader() {
- (0, _util.assert)(!this._fullRequestReader);
- this._fullRequestReader = new PDFNetworkStreamFullRequestReader(this._manager, this._source);
- return this._fullRequestReader;
- },
- getRangeReader: function PDFNetworkStream_getRangeReader(begin, end) {
- var reader = new PDFNetworkStreamRangeRequestReader(this._manager, begin, end);
- reader.onClosed = this._onRangeRequestReaderClosed.bind(this);
- this._rangeRequestReaders.push(reader);
- return reader;
- },
- cancelAllRequests: function PDFNetworkStream_cancelAllRequests(reason) {
- if (this._fullRequestReader) {
- this._fullRequestReader.cancel(reason);
- }
- var readers = this._rangeRequestReaders.slice(0);
- readers.forEach(function (reader) {
- reader.cancel(reason);
- });
- }
-};
-function PDFNetworkStreamFullRequestReader(manager, source) {
- this._manager = manager;
- var args = {
- onHeadersReceived: this._onHeadersReceived.bind(this),
- onProgressiveData: source.disableStream ? null : this._onProgressiveData.bind(this),
- onDone: this._onDone.bind(this),
- onError: this._onError.bind(this),
- onProgress: this._onProgress.bind(this)
- };
- this._url = source.url;
- this._fullRequestId = manager.requestFull(args);
- this._headersReceivedCapability = (0, _util.createPromiseCapability)();
- this._disableRange = source.disableRange || false;
- this._contentLength = source.length;
- this._rangeChunkSize = source.rangeChunkSize;
- if (!this._rangeChunkSize && !this._disableRange) {
- this._disableRange = true;
- }
- this._isStreamingSupported = false;
- this._isRangeSupported = false;
- this._cachedChunks = [];
- this._requests = [];
- this._done = false;
- this._storedError = undefined;
- this._filename = null;
- this.onProgress = null;
-}
-PDFNetworkStreamFullRequestReader.prototype = {
- _onHeadersReceived: function PDFNetworkStreamFullRequestReader_onHeadersReceived() {
- var fullRequestXhrId = this._fullRequestId;
- var fullRequestXhr = this._manager.getRequestXhr(fullRequestXhrId);
- var getResponseHeader = function getResponseHeader(name) {
- return fullRequestXhr.getResponseHeader(name);
- };
-
- var _validateRangeRequest = (0, _network_utils.validateRangeRequestCapabilities)({
- getResponseHeader: getResponseHeader,
- isHttp: this._manager.isHttp,
- rangeChunkSize: this._rangeChunkSize,
- disableRange: this._disableRange
- }),
- allowRangeRequests = _validateRangeRequest.allowRangeRequests,
- suggestedLength = _validateRangeRequest.suggestedLength;
-
- if (allowRangeRequests) {
- this._isRangeSupported = true;
- }
- this._contentLength = suggestedLength || this._contentLength;
- this._filename = (0, _network_utils.extractFilenameFromHeader)(getResponseHeader);
- var networkManager = this._manager;
- if (networkManager.isStreamingRequest(fullRequestXhrId)) {
- this._isStreamingSupported = true;
- } else if (this._isRangeSupported) {
- networkManager.abortRequest(fullRequestXhrId);
- }
- this._headersReceivedCapability.resolve();
- },
- _onProgressiveData: function PDFNetworkStreamFullRequestReader_onProgressiveData(chunk) {
- if (this._requests.length > 0) {
- var requestCapability = this._requests.shift();
- requestCapability.resolve({
- value: chunk,
- done: false
- });
- } else {
- this._cachedChunks.push(chunk);
- }
- },
- _onDone: function PDFNetworkStreamFullRequestReader_onDone(args) {
- if (args) {
- this._onProgressiveData(args.chunk);
- }
- this._done = true;
- if (this._cachedChunks.length > 0) {
- return;
- }
- this._requests.forEach(function (requestCapability) {
- requestCapability.resolve({
- value: undefined,
- done: true
- });
- });
- this._requests = [];
- },
- _onError: function PDFNetworkStreamFullRequestReader_onError(status) {
- var url = this._url;
- var exception = (0, _network_utils.createResponseStatusError)(status, url);
- this._storedError = exception;
- this._headersReceivedCapability.reject(exception);
- this._requests.forEach(function (requestCapability) {
- requestCapability.reject(exception);
- });
- this._requests = [];
- this._cachedChunks = [];
- },
- _onProgress: function PDFNetworkStreamFullRequestReader_onProgress(data) {
- if (this.onProgress) {
- this.onProgress({
- loaded: data.loaded,
- total: data.lengthComputable ? data.total : this._contentLength
- });
- }
- },
- get filename() {
- return this._filename;
- },
- get isRangeSupported() {
- return this._isRangeSupported;
- },
- get isStreamingSupported() {
- return this._isStreamingSupported;
- },
- get contentLength() {
- return this._contentLength;
- },
- get headersReady() {
- return this._headersReceivedCapability.promise;
- },
- read: function () {
- var _ref = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee() {
- var chunk, requestCapability;
- return _regenerator2.default.wrap(function _callee$(_context) {
- while (1) {
- switch (_context.prev = _context.next) {
- case 0:
- if (!this._storedError) {
- _context.next = 2;
- break;
- }
-
- throw this._storedError;
-
- case 2:
- if (!(this._cachedChunks.length > 0)) {
- _context.next = 5;
- break;
- }
-
- chunk = this._cachedChunks.shift();
- return _context.abrupt('return', {
- value: chunk,
- done: false
- });
-
- case 5:
- if (!this._done) {
- _context.next = 7;
- break;
- }
-
- return _context.abrupt('return', {
- value: undefined,
- done: true
- });
-
- case 7:
- requestCapability = (0, _util.createPromiseCapability)();
-
- this._requests.push(requestCapability);
- return _context.abrupt('return', requestCapability.promise);
-
- case 10:
- case 'end':
- return _context.stop();
- }
- }
- }, _callee, this);
- }));
-
- function read() {
- return _ref.apply(this, arguments);
- }
-
- return read;
- }(),
-
- cancel: function PDFNetworkStreamFullRequestReader_cancel(reason) {
- this._done = true;
- this._headersReceivedCapability.reject(reason);
- this._requests.forEach(function (requestCapability) {
- requestCapability.resolve({
- value: undefined,
- done: true
- });
- });
- this._requests = [];
- if (this._manager.isPendingRequest(this._fullRequestId)) {
- this._manager.abortRequest(this._fullRequestId);
- }
- this._fullRequestReader = null;
- }
-};
-function PDFNetworkStreamRangeRequestReader(manager, begin, end) {
- this._manager = manager;
- var args = {
- onDone: this._onDone.bind(this),
- onProgress: this._onProgress.bind(this)
- };
- this._requestId = manager.requestRange(begin, end, args);
- this._requests = [];
- this._queuedChunk = null;
- this._done = false;
- this.onProgress = null;
- this.onClosed = null;
-}
-PDFNetworkStreamRangeRequestReader.prototype = {
- _close: function PDFNetworkStreamRangeRequestReader_close() {
- if (this.onClosed) {
- this.onClosed(this);
- }
- },
- _onDone: function PDFNetworkStreamRangeRequestReader_onDone(data) {
- var chunk = data.chunk;
- if (this._requests.length > 0) {
- var requestCapability = this._requests.shift();
- requestCapability.resolve({
- value: chunk,
- done: false
- });
- } else {
- this._queuedChunk = chunk;
- }
- this._done = true;
- this._requests.forEach(function (requestCapability) {
- requestCapability.resolve({
- value: undefined,
- done: true
- });
- });
- this._requests = [];
- this._close();
- },
- _onProgress: function PDFNetworkStreamRangeRequestReader_onProgress(evt) {
- if (!this.isStreamingSupported && this.onProgress) {
- this.onProgress({ loaded: evt.loaded });
- }
- },
- get isStreamingSupported() {
- return false;
- },
- read: function () {
- var _ref2 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee2() {
- var chunk, requestCapability;
- return _regenerator2.default.wrap(function _callee2$(_context2) {
- while (1) {
- switch (_context2.prev = _context2.next) {
- case 0:
- if (!(this._queuedChunk !== null)) {
- _context2.next = 4;
- break;
- }
-
- chunk = this._queuedChunk;
-
- this._queuedChunk = null;
- return _context2.abrupt('return', {
- value: chunk,
- done: false
- });
-
- case 4:
- if (!this._done) {
- _context2.next = 6;
- break;
- }
-
- return _context2.abrupt('return', {
- value: undefined,
- done: true
- });
-
- case 6:
- requestCapability = (0, _util.createPromiseCapability)();
-
- this._requests.push(requestCapability);
- return _context2.abrupt('return', requestCapability.promise);
-
- case 9:
- case 'end':
- return _context2.stop();
- }
- }
- }, _callee2, this);
- }));
-
- function read() {
- return _ref2.apply(this, arguments);
- }
-
- return read;
- }(),
-
- cancel: function PDFNetworkStreamRangeRequestReader_cancel(reason) {
- this._done = true;
- this._requests.forEach(function (requestCapability) {
- requestCapability.resolve({
- value: undefined,
- done: true
- });
- });
- this._requests = [];
- if (this._manager.isPendingRequest(this._requestId)) {
- this._manager.abortRequest(this._requestId);
- }
- this._close();
- }
-};
-exports.PDFNetworkStream = PDFNetworkStream;
-exports.NetworkManager = NetworkManager;
-
-/***/ })
-/******/ ]);
-});
-//# sourceMappingURL=pdf.js.map \ No newline at end of file
diff --git a/vendor/assets/javascripts/pdf.min.js b/vendor/assets/javascripts/pdf.min.js
deleted file mode 100644
index 43ab356bfec..00000000000
--- a/vendor/assets/javascripts/pdf.min.js
+++ /dev/null
@@ -1 +0,0 @@
-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("pdfjs-dist/build/pdf",[],t):"object"==typeof exports?exports["pdfjs-dist/build/pdf"]=t():e["pdfjs-dist/build/pdf"]=e.pdfjsLib=t()}(this,function(){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)r.d(n,i,function(t){return e[t]}.bind(null,i));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=0)}([function(e,t,r){"use strict";var n=r(1),i=r(129),a=r(145),o=r(146),s=r(130),u=r(147),l=r(135),c=r(132);if(r(4)()){var h=r(148).PDFNodeStream;i.setPDFNetworkStreamFactory(function(e){return new h(e)})}else if("undefined"!=typeof Response&&"body"in Response.prototype&&"undefined"!=typeof ReadableStream){var d=r(151).PDFFetchStream;i.setPDFNetworkStreamFactory(function(e){return new d(e)})}else{var f=r(152).PDFNetworkStream;i.setPDFNetworkStreamFactory(function(e){return new f(e)})}t.build=i.build,t.version=i.version,t.getDocument=i.getDocument,t.LoopbackPort=i.LoopbackPort,t.PDFDataRangeTransport=i.PDFDataRangeTransport,t.PDFWorker=i.PDFWorker,t.renderTextLayer=a.renderTextLayer,t.AnnotationLayer=o.AnnotationLayer,t.createPromiseCapability=n.createPromiseCapability,t.PasswordResponses=n.PasswordResponses,t.InvalidPDFException=n.InvalidPDFException,t.MissingPDFException=n.MissingPDFException,t.SVGGraphics=u.SVGGraphics,t.NativeImageDecoding=n.NativeImageDecoding,t.CMapCompressionType=n.CMapCompressionType,t.PermissionFlag=n.PermissionFlag,t.UnexpectedResponseException=n.UnexpectedResponseException,t.OPS=n.OPS,t.VerbosityLevel=n.VerbosityLevel,t.UNSUPPORTED_FEATURES=n.UNSUPPORTED_FEATURES,t.createValidAbsoluteUrl=n.createValidAbsoluteUrl,t.createObjectURL=n.createObjectURL,t.removeNullCharacters=n.removeNullCharacters,t.shadow=n.shadow,t.Util=n.Util,t.ReadableStream=n.ReadableStream,t.URL=n.URL,t.RenderingCancelledException=s.RenderingCancelledException,t.getFilenameFromUrl=s.getFilenameFromUrl,t.LinkTarget=s.LinkTarget,t.addLinkAttributes=s.addLinkAttributes,t.loadScript=s.loadScript,t.GlobalWorkerOptions=l.GlobalWorkerOptions,t.apiCompatibilityParams=c.apiCompatibilityParams},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.unreachable=t.warn=t.utf8StringToString=t.stringToUTF8String=t.stringToPDFString=t.stringToBytes=t.string32=t.shadow=t.setVerbosityLevel=t.URL=t.ReadableStream=t.removeNullCharacters=t.readUint32=t.readUint16=t.readInt8=t.log2=t.isEvalSupported=t.isLittleEndian=t.createValidAbsoluteUrl=t.isSameOrigin=t.isSpace=t.isString=t.isNum=t.isEmptyObj=t.isBool=t.isArrayBuffer=t.info=t.getVerbosityLevel=t.getLookupTableFactory=t.getInheritableProperty=t.deprecated=t.createObjectURL=t.createPromiseCapability=t.bytesToString=t.assert=t.arraysToBytes=t.arrayByteLength=t.FormatError=t.XRefParseException=t.toRomanNumerals=t.Util=t.UnknownErrorException=t.UnexpectedResponseException=t.TextRenderingMode=t.StreamType=t.PermissionFlag=t.PasswordResponses=t.PasswordException=t.NativeImageDecoding=t.MissingPDFException=t.MissingDataException=t.InvalidPDFException=t.AbortException=t.CMapCompressionType=t.ImageKind=t.FontType=t.AnnotationType=t.AnnotationFlag=t.AnnotationFieldFlag=t.AnnotationBorderStyleType=t.UNSUPPORTED_FEATURES=t.VerbosityLevel=t.OPS=t.IDENTITY_MATRIX=t.FONT_IDENTITY_MATRIX=void 0;var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};r(2);var i=r(125),a=r(127),o={ERRORS:0,WARNINGS:1,INFOS:5},s=o.WARNINGS;function u(e){s>=o.WARNINGS&&console.log("Warning: "+e)}function l(e){throw new Error(e)}function c(e,t){e||l(t)}var h=function(){function e(e,t){this.name="PasswordException",this.message=e,this.code=t}return e.prototype=new Error,e.constructor=e,e}(),d=function(){function e(e,t){this.name="UnknownErrorException",this.message=e,this.details=t}return e.prototype=new Error,e.constructor=e,e}(),f=function(){function e(e){this.name="InvalidPDFException",this.message=e}return e.prototype=new Error,e.constructor=e,e}(),p=function(){function e(e){this.name="MissingPDFException",this.message=e}return e.prototype=new Error,e.constructor=e,e}(),v=function(){function e(e,t){this.name="UnexpectedResponseException",this.message=e,this.status=t}return e.prototype=new Error,e.constructor=e,e}(),m=function(){function e(e,t){this.begin=e,this.end=t,this.message="Missing data ["+e+", "+t+")"}return e.prototype=new Error,e.prototype.name="MissingDataException",e.constructor=e,e}(),g=function(){function e(e){this.message=e}return e.prototype=new Error,e.prototype.name="XRefParseException",e.constructor=e,e}(),y=function(){function e(e){this.message=e}return e.prototype=new Error,e.prototype.name="FormatError",e.constructor=e,e}(),b=function(){function e(e){this.name="AbortException",this.message=e}return e.prototype=new Error,e.constructor=e,e}(),_=/\x00/g;function A(e){c("string"==typeof e,"Invalid argument for stringToBytes");for(var t=e.length,r=new Uint8Array(t),n=0;n<t;++n)r[n]=255&e.charCodeAt(n);return r}function S(e){return void 0!==e.length?e.length:(c(void 0!==e.byteLength),e.byteLength)}var w=function(){function e(){}var t=["rgb(",0,",",0,",",0,")"];return e.makeCssRgb=function(e,r,n){return t[1]=e,t[3]=r,t[5]=n,t.join("")},e.transform=function(e,t){return[e[0]*t[0]+e[2]*t[1],e[1]*t[0]+e[3]*t[1],e[0]*t[2]+e[2]*t[3],e[1]*t[2]+e[3]*t[3],e[0]*t[4]+e[2]*t[5]+e[4],e[1]*t[4]+e[3]*t[5]+e[5]]},e.applyTransform=function(e,t){return[e[0]*t[0]+e[1]*t[2]+t[4],e[0]*t[1]+e[1]*t[3]+t[5]]},e.applyInverseTransform=function(e,t){var r=t[0]*t[3]-t[1]*t[2];return[(e[0]*t[3]-e[1]*t[2]+t[2]*t[5]-t[4]*t[3])/r,(-e[0]*t[1]+e[1]*t[0]+t[4]*t[1]-t[5]*t[0])/r]},e.getAxialAlignedBoundingBox=function(t,r){var n=e.applyTransform(t,r),i=e.applyTransform(t.slice(2,4),r),a=e.applyTransform([t[0],t[3]],r),o=e.applyTransform([t[2],t[1]],r);return[Math.min(n[0],i[0],a[0],o[0]),Math.min(n[1],i[1],a[1],o[1]),Math.max(n[0],i[0],a[0],o[0]),Math.max(n[1],i[1],a[1],o[1])]},e.inverseTransform=function(e){var t=e[0]*e[3]-e[1]*e[2];return[e[3]/t,-e[1]/t,-e[2]/t,e[0]/t,(e[2]*e[5]-e[4]*e[3])/t,(e[4]*e[1]-e[5]*e[0])/t]},e.apply3dTransform=function(e,t){return[e[0]*t[0]+e[1]*t[1]+e[2]*t[2],e[3]*t[0]+e[4]*t[1]+e[5]*t[2],e[6]*t[0]+e[7]*t[1]+e[8]*t[2]]},e.singularValueDecompose2dScale=function(e){var t=[e[0],e[2],e[1],e[3]],r=e[0]*t[0]+e[1]*t[2],n=e[0]*t[1]+e[1]*t[3],i=e[2]*t[0]+e[3]*t[2],a=e[2]*t[1]+e[3]*t[3],o=(r+a)/2,s=Math.sqrt((r+a)*(r+a)-4*(r*a-i*n))/2,u=o+s||1,l=o-s||1;return[Math.sqrt(u),Math.sqrt(l)]},e.normalizeRect=function(e){var t=e.slice(0);return e[0]>e[2]&&(t[0]=e[2],t[2]=e[0]),e[1]>e[3]&&(t[1]=e[3],t[3]=e[1]),t},e.intersect=function(t,r){function n(e,t){return e-t}var i=[t[0],t[2],r[0],r[2]].sort(n),a=[t[1],t[3],r[1],r[3]].sort(n),o=[];return t=e.normalizeRect(t),r=e.normalizeRect(r),(i[0]===t[0]&&i[1]===r[0]||i[0]===r[0]&&i[1]===t[0])&&(o[0]=i[1],o[2]=i[2],(a[0]===t[1]&&a[1]===r[1]||a[0]===r[1]&&a[1]===t[1])&&(o[1]=a[1],o[3]=a[2],o))},e}(),k=["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM","","X","XX","XXX","XL","L","LX","LXX","LXXX","XC","","I","II","III","IV","V","VI","VII","VIII","IX"];var P=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,728,711,710,729,733,731,730,732,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8226,8224,8225,8230,8212,8211,402,8260,8249,8250,8722,8240,8222,8220,8221,8216,8217,8218,8482,64257,64258,321,338,352,376,381,305,322,339,353,382,0,8364];var x,C=(x="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",function(e,t){if(!(arguments.length>2&&void 0!==arguments[2]&&arguments[2])&&a.URL.createObjectURL){var r=new Blob([e],{type:t});return a.URL.createObjectURL(r)}for(var n="data:"+t+";base64,",i=0,o=e.length;i<o;i+=3){var s=255&e[i],u=255&e[i+1],l=255&e[i+2];n+=x[s>>2]+x[(3&s)<<4|u>>4]+x[i+1<o?(15&u)<<2|l>>6:64]+x[i+2<o?63&l:64]}return n});t.FONT_IDENTITY_MATRIX=[.001,0,0,.001,0,0],t.IDENTITY_MATRIX=[1,0,0,1,0,0],t.OPS={dependency:1,setLineWidth:2,setLineCap:3,setLineJoin:4,setMiterLimit:5,setDash:6,setRenderingIntent:7,setFlatness:8,setGState:9,save:10,restore:11,transform:12,moveTo:13,lineTo:14,curveTo:15,curveTo2:16,curveTo3:17,closePath:18,rectangle:19,stroke:20,closeStroke:21,fill:22,eoFill:23,fillStroke:24,eoFillStroke:25,closeFillStroke:26,closeEOFillStroke:27,endPath:28,clip:29,eoClip:30,beginText:31,endText:32,setCharSpacing:33,setWordSpacing:34,setHScale:35,setLeading:36,setFont:37,setTextRenderingMode:38,setTextRise:39,moveText:40,setLeadingMoveText:41,setTextMatrix:42,nextLine:43,showText:44,showSpacedText:45,nextLineShowText:46,nextLineSetSpacingShowText:47,setCharWidth:48,setCharWidthAndBounds:49,setStrokeColorSpace:50,setFillColorSpace:51,setStrokeColor:52,setStrokeColorN:53,setFillColor:54,setFillColorN:55,setStrokeGray:56,setFillGray:57,setStrokeRGBColor:58,setFillRGBColor:59,setStrokeCMYKColor:60,setFillCMYKColor:61,shadingFill:62,beginInlineImage:63,beginImageData:64,endInlineImage:65,paintXObject:66,markPoint:67,markPointProps:68,beginMarkedContent:69,beginMarkedContentProps:70,endMarkedContent:71,beginCompat:72,endCompat:73,paintFormXObjectBegin:74,paintFormXObjectEnd:75,beginGroup:76,endGroup:77,beginAnnotations:78,endAnnotations:79,beginAnnotation:80,endAnnotation:81,paintJpegXObject:82,paintImageMaskXObject:83,paintImageMaskXObjectGroup:84,paintImageXObject:85,paintInlineImageXObject:86,paintInlineImageXObjectGroup:87,paintImageXObjectRepeat:88,paintImageMaskXObjectRepeat:89,paintSolidColorImageMask:90,constructPath:91},t.VerbosityLevel=o,t.UNSUPPORTED_FEATURES={unknown:"unknown",forms:"forms",javaScript:"javaScript",smask:"smask",shadingPattern:"shadingPattern",font:"font"},t.AnnotationBorderStyleType={SOLID:1,DASHED:2,BEVELED:3,INSET:4,UNDERLINE:5},t.AnnotationFieldFlag={READONLY:1,REQUIRED:2,NOEXPORT:4,MULTILINE:4096,PASSWORD:8192,NOTOGGLETOOFF:16384,RADIO:32768,PUSHBUTTON:65536,COMBO:131072,EDIT:262144,SORT:524288,FILESELECT:1048576,MULTISELECT:2097152,DONOTSPELLCHECK:4194304,DONOTSCROLL:8388608,COMB:16777216,RICHTEXT:33554432,RADIOSINUNISON:33554432,COMMITONSELCHANGE:67108864},t.AnnotationFlag={INVISIBLE:1,HIDDEN:2,PRINT:4,NOZOOM:8,NOROTATE:16,NOVIEW:32,READONLY:64,LOCKED:128,TOGGLENOVIEW:256,LOCKEDCONTENTS:512},t.AnnotationType={TEXT:1,LINK:2,FREETEXT:3,LINE:4,SQUARE:5,CIRCLE:6,POLYGON:7,POLYLINE:8,HIGHLIGHT:9,UNDERLINE:10,SQUIGGLY:11,STRIKEOUT:12,STAMP:13,CARET:14,INK:15,POPUP:16,FILEATTACHMENT:17,SOUND:18,MOVIE:19,WIDGET:20,SCREEN:21,PRINTERMARK:22,TRAPNET:23,WATERMARK:24,THREED:25,REDACT:26},t.FontType={UNKNOWN:0,TYPE1:1,TYPE1C:2,CIDFONTTYPE0:3,CIDFONTTYPE0C:4,TRUETYPE:5,CIDFONTTYPE2:6,TYPE3:7,OPENTYPE:8,TYPE0:9,MMTYPE1:10},t.ImageKind={GRAYSCALE_1BPP:1,RGB_24BPP:2,RGBA_32BPP:3},t.CMapCompressionType={NONE:0,BINARY:1,STREAM:2},t.AbortException=b,t.InvalidPDFException=f,t.MissingDataException=m,t.MissingPDFException=p,t.NativeImageDecoding={NONE:"none",DECODE:"decode",DISPLAY:"display"},t.PasswordException=h,t.PasswordResponses={NEED_PASSWORD:1,INCORRECT_PASSWORD:2},t.PermissionFlag={PRINT:4,MODIFY_CONTENTS:8,COPY:16,MODIFY_ANNOTATIONS:32,FILL_INTERACTIVE_FORMS:256,COPY_FOR_ACCESSIBILITY:512,ASSEMBLE:1024,PRINT_HIGH_QUALITY:2048},t.StreamType={UNKNOWN:0,FLATE:1,LZW:2,DCT:3,JPX:4,JBIG:5,A85:6,AHX:7,CCF:8,RL:9},t.TextRenderingMode={FILL:0,STROKE:1,FILL_STROKE:2,INVISIBLE:3,FILL_ADD_TO_PATH:4,STROKE_ADD_TO_PATH:5,FILL_STROKE_ADD_TO_PATH:6,ADD_TO_PATH:7,FILL_STROKE_MASK:3,ADD_TO_PATH_FLAG:4},t.UnexpectedResponseException=v,t.UnknownErrorException=d,t.Util=w,t.toRomanNumerals=function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];c(Number.isInteger(e)&&e>0,"The number should be a positive integer.");for(var r=void 0,n=[];e>=1e3;)e-=1e3,n.push("M");r=e/100|0,e%=100,n.push(k[r]),r=e/10|0,e%=10,n.push(k[10+r]),n.push(k[20+e]);var i=n.join("");return t?i.toLowerCase():i},t.XRefParseException=g,t.FormatError=y,t.arrayByteLength=S,t.arraysToBytes=function(e){if(1===e.length&&e[0]instanceof Uint8Array)return e[0];var t,r,n,i=0,a=e.length;for(t=0;t<a;t++)i+=n=S(r=e[t]);var o=0,s=new Uint8Array(i);for(t=0;t<a;t++)(r=e[t])instanceof Uint8Array||(r="string"==typeof r?A(r):new Uint8Array(r)),n=r.byteLength,s.set(r,o),o+=n;return s},t.assert=c,t.bytesToString=function(e){c(null!==e&&"object"===(void 0===e?"undefined":n(e))&&void 0!==e.length,"Invalid argument for bytesToString");var t=e.length;if(t<8192)return String.fromCharCode.apply(null,e);for(var r=[],i=0;i<t;i+=8192){var a=Math.min(i+8192,t),o=e.subarray(i,a);r.push(String.fromCharCode.apply(null,o))}return r.join("")},t.createPromiseCapability=function(){var e={};return e.promise=new Promise(function(t,r){e.resolve=t,e.reject=r}),e},t.createObjectURL=C,t.deprecated=function(e){console.log("Deprecated API usage: "+e)},t.getInheritableProperty=function(e){for(var t=e.dict,r=e.key,n=e.getArray,i=void 0!==n&&n,a=e.stopWhenFound,o=void 0===a||a,s=0,l=void 0;t;){var c=i?t.getArray(r):t.get(r);if(void 0!==c){if(o)return c;l||(l=[]),l.push(c)}if(++s>100){u('getInheritableProperty: maximum loop count exceeded for "'+r+'"');break}t=t.get("Parent")}return l},t.getLookupTableFactory=function(e){var t;return function(){return e&&(t=Object.create(null),e(t),e=null),t}},t.getVerbosityLevel=function(){return s},t.info=function(e){s>=o.INFOS&&console.log("Info: "+e)},t.isArrayBuffer=function(e){return"object"===(void 0===e?"undefined":n(e))&&null!==e&&void 0!==e.byteLength},t.isBool=function(e){return"boolean"==typeof e},t.isEmptyObj=function(e){for(var t in e)return!1;return!0},t.isNum=function(e){return"number"==typeof e},t.isString=function(e){return"string"==typeof e},t.isSpace=function(e){return 32===e||9===e||13===e||10===e},t.isSameOrigin=function(e,t){try{var r=new a.URL(e);if(!r.origin||"null"===r.origin)return!1}catch(e){return!1}var n=new a.URL(t,r);return r.origin===n.origin},t.createValidAbsoluteUrl=function(e,t){if(!e)return null;try{var r=t?new a.URL(e,t):new a.URL(e);if(function(e){if(!e)return!1;switch(e.protocol){case"http:":case"https:":case"ftp:":case"mailto:":case"tel:":return!0;default:return!1}}(r))return r}catch(e){}return null},t.isLittleEndian=function(){var e=new Uint8Array(4);return e[0]=1,1===new Uint32Array(e.buffer,0,1)[0]},t.isEvalSupported=function(){try{return new Function(""),!0}catch(e){return!1}},t.log2=function(e){return e<=0?0:Math.ceil(Math.log2(e))},t.readInt8=function(e,t){return e[t]<<24>>24},t.readUint16=function(e,t){return e[t]<<8|e[t+1]},t.readUint32=function(e,t){return(e[t]<<24|e[t+1]<<16|e[t+2]<<8|e[t+3])>>>0},t.removeNullCharacters=function(e){return"string"!=typeof e?(u("The argument for removeNullCharacters must be a string."),e):e.replace(_,"")},t.ReadableStream=i.ReadableStream,t.URL=a.URL,t.setVerbosityLevel=function(e){Number.isInteger(e)&&(s=e)},t.shadow=function(e,t,r){return Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!1}),r},t.string32=function(e){return String.fromCharCode(e>>24&255,e>>16&255,e>>8&255,255&e)},t.stringToBytes=A,t.stringToPDFString=function(e){var t,r=e.length,n=[];if("þ"===e[0]&&"ÿ"===e[1])for(t=2;t<r;t+=2)n.push(String.fromCharCode(e.charCodeAt(t)<<8|e.charCodeAt(t+1)));else for(t=0;t<r;++t){var i=P[e.charCodeAt(t)];n.push(i?String.fromCharCode(i):e.charAt(t))}return n.join("")},t.stringToUTF8String=function(e){return decodeURIComponent(escape(e))},t.utf8StringToString=function(e){return unescape(encodeURIComponent(e))},t.warn=u,t.unreachable=l},function(e,t,r){"use strict";var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i=r(3);if(!i._pdfjsCompatibilityChecked){i._pdfjsCompatibilityChecked=!0;var a=r(4),o="object"===("undefined"==typeof window?"undefined":n(window))&&"object"===("undefined"==typeof document?"undefined":n(document));!i.btoa&&a()&&(i.btoa=function(e){return Buffer.from(e,"binary").toString("base64")}),!i.atob&&a()&&(i.atob=function(e){return Buffer.from(e,"base64").toString("binary")}),o&&("currentScript"in document||Object.defineProperty(document,"currentScript",{get:function(){var e=document.getElementsByTagName("script");return e[e.length-1]},enumerable:!0,configurable:!0})),o&&void 0===Element.prototype.remove&&(Element.prototype.remove=function(){this.parentNode&&this.parentNode.removeChild(this)}),function(){if(o&&!a()&&!1!==document.createElement("div").classList.toggle("test",0)){var e=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(t){if(arguments.length>1){var r=!!arguments[1];return this[r?"add":"remove"](t),r}return e(t)}}}(),String.prototype.includes||r(5),Array.prototype.includes||r(33),Object.assign||r(42),Math.log2||(Math.log2=r(52)),Number.isNaN||(Number.isNaN=r(54)),Number.isInteger||(Number.isInteger=r(56)),i.Promise||(i.Promise=r(59)),i.WeakMap||(i.WeakMap=r(94)),String.codePointAt||(String.codePointAt=r(111)),String.fromCodePoint||(String.fromCodePoint=r(113)),i.Symbol||r(115),Object.values||(Object.values=r(122))}},function(e,t,r){"use strict";e.exports="undefined"!=typeof window&&window.Math===Math?window:"undefined"!=typeof global&&global.Math===Math?global:"undefined"!=typeof self&&self.Math===Math?self:{}},function(e,t,r){"use strict";var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};e.exports=function(){return"object"===("undefined"==typeof process?"undefined":n(process))&&process+""=="[object process]"}},function(e,t,r){"use strict";r(6),e.exports=r(9).String.includes},function(e,t,r){"use strict";var n=r(7),i=r(25);n(n.P+n.F*r(32)("includes"),"String",{includes:function(e){return!!~i(this,e,"includes").indexOf(e,arguments.length>1?arguments[1]:void 0)}})},function(e,t,r){"use strict";var n=r(8),i=r(9),a=r(10),o=r(20),s=r(23),u=function e(t,r,u){var l,c,h,d,f=t&e.F,p=t&e.G,v=t&e.P,m=t&e.B,g=p?n:t&e.S?n[r]||(n[r]={}):(n[r]||{}).prototype,y=p?i:i[r]||(i[r]={}),b=y.prototype||(y.prototype={});for(l in p&&(u=r),u)h=((c=!f&&g&&void 0!==g[l])?g:u)[l],d=m&&c?s(h,n):v&&"function"==typeof h?s(Function.call,h):h,g&&o(g,l,h,t&e.U),y[l]!=h&&a(y,l,d),v&&b[l]!=h&&(b[l]=h)};n.core=i,u.F=1,u.G=2,u.S=4,u.P=8,u.B=16,u.W=32,u.U=64,u.R=128,e.exports=u},function(e,t,r){"use strict";var n=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},function(e,t,r){"use strict";var n=e.exports={version:"2.5.7"};"number"==typeof __e&&(__e=n)},function(e,t,r){"use strict";var n=r(11),i=r(19);e.exports=r(15)?function(e,t,r){return n.f(e,t,i(1,r))}:function(e,t,r){return e[t]=r,e}},function(e,t,r){"use strict";var n=r(12),i=r(14),a=r(18),o=Object.defineProperty;t.f=r(15)?Object.defineProperty:function(e,t,r){if(n(e),t=a(t,!0),n(r),i)try{return o(e,t,r)}catch(e){}if("get"in r||"set"in r)throw TypeError("Accessors not supported!");return"value"in r&&(e[t]=r.value),e}},function(e,t,r){"use strict";var n=r(13);e.exports=function(e){if(!n(e))throw TypeError(e+" is not an object!");return e}},function(e,t,r){"use strict";var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};e.exports=function(e){return"object"===(void 0===e?"undefined":n(e))?null!==e:"function"==typeof e}},function(e,t,r){"use strict";e.exports=!r(15)&&!r(16)(function(){return 7!=Object.defineProperty(r(17)("div"),"a",{get:function(){return 7}}).a})},function(e,t,r){"use strict";e.exports=!r(16)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(e,t,r){"use strict";e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,t,r){"use strict";var n=r(13),i=r(8).document,a=n(i)&&n(i.createElement);e.exports=function(e){return a?i.createElement(e):{}}},function(e,t,r){"use strict";var n=r(13);e.exports=function(e,t){if(!n(e))return e;var r,i;if(t&&"function"==typeof(r=e.toString)&&!n(i=r.call(e)))return i;if("function"==typeof(r=e.valueOf)&&!n(i=r.call(e)))return i;if(!t&&"function"==typeof(r=e.toString)&&!n(i=r.call(e)))return i;throw TypeError("Can't convert object to primitive value")}},function(e,t,r){"use strict";e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t,r){"use strict";var n=r(8),i=r(10),a=r(21),o=r(22)("src"),s=Function.toString,u=(""+s).split("toString");r(9).inspectSource=function(e){return s.call(e)},(e.exports=function(e,t,r,s){var l="function"==typeof r;l&&(a(r,"name")||i(r,"name",t)),e[t]!==r&&(l&&(a(r,o)||i(r,o,e[t]?""+e[t]:u.join(String(t)))),e===n?e[t]=r:s?e[t]?e[t]=r:i(e,t,r):(delete e[t],i(e,t,r)))})(Function.prototype,"toString",function(){return"function"==typeof this&&this[o]||s.call(this)})},function(e,t,r){"use strict";var n={}.hasOwnProperty;e.exports=function(e,t){return n.call(e,t)}},function(e,t,r){"use strict";var n=0,i=Math.random();e.exports=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++n+i).toString(36))}},function(e,t,r){"use strict";var n=r(24);e.exports=function(e,t,r){if(n(e),void 0===t)return e;switch(r){case 1:return function(r){return e.call(t,r)};case 2:return function(r,n){return e.call(t,r,n)};case 3:return function(r,n,i){return e.call(t,r,n,i)}}return function(){return e.apply(t,arguments)}}},function(e,t,r){"use strict";e.exports=function(e){if("function"!=typeof e)throw TypeError(e+" is not a function!");return e}},function(e,t,r){"use strict";var n=r(26),i=r(31);e.exports=function(e,t,r){if(n(t))throw TypeError("String#"+r+" doesn't accept regex!");return String(i(e))}},function(e,t,r){"use strict";var n=r(13),i=r(27),a=r(28)("match");e.exports=function(e){var t;return n(e)&&(void 0!==(t=e[a])?!!t:"RegExp"==i(e))}},function(e,t,r){"use strict";var n={}.toString;e.exports=function(e){return n.call(e).slice(8,-1)}},function(e,t,r){"use strict";var n=r(29)("wks"),i=r(22),a=r(8).Symbol,o="function"==typeof a;(e.exports=function(e){return n[e]||(n[e]=o&&a[e]||(o?a:i)("Symbol."+e))}).store=n},function(e,t,r){"use strict";var n=r(9),i=r(8),a=i["__core-js_shared__"]||(i["__core-js_shared__"]={});(e.exports=function(e,t){return a[e]||(a[e]=void 0!==t?t:{})})("versions",[]).push({version:n.version,mode:r(30)?"pure":"global",copyright:"© 2018 Denis Pushkarev (zloirock.ru)"})},function(e,t,r){"use strict";e.exports=!1},function(e,t,r){"use strict";e.exports=function(e){if(void 0==e)throw TypeError("Can't call method on "+e);return e}},function(e,t,r){"use strict";var n=r(28)("match");e.exports=function(e){var t=/./;try{"/./"[e](t)}catch(r){try{return t[n]=!1,!"/./"[e](t)}catch(e){}}return!0}},function(e,t,r){"use strict";r(34),e.exports=r(9).Array.includes},function(e,t,r){"use strict";var n=r(7),i=r(35)(!0);n(n.P,"Array",{includes:function(e){return i(this,e,arguments.length>1?arguments[1]:void 0)}}),r(41)("includes")},function(e,t,r){"use strict";var n=r(36),i=r(38),a=r(40);e.exports=function(e){return function(t,r,o){var s,u=n(t),l=i(u.length),c=a(o,l);if(e&&r!=r){for(;l>c;)if((s=u[c++])!=s)return!0}else for(;l>c;c++)if((e||c in u)&&u[c]===r)return e||c||0;return!e&&-1}}},function(e,t,r){"use strict";var n=r(37),i=r(31);e.exports=function(e){return n(i(e))}},function(e,t,r){"use strict";var n=r(27);e.exports=Object("z").propertyIsEnumerable(0)?Object:function(e){return"String"==n(e)?e.split(""):Object(e)}},function(e,t,r){"use strict";var n=r(39),i=Math.min;e.exports=function(e){return e>0?i(n(e),9007199254740991):0}},function(e,t,r){"use strict";var n=Math.ceil,i=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?i:n)(e)}},function(e,t,r){"use strict";var n=r(39),i=Math.max,a=Math.min;e.exports=function(e,t){return(e=n(e))<0?i(e+t,0):a(e,t)}},function(e,t,r){"use strict";var n=r(28)("unscopables"),i=Array.prototype;void 0==i[n]&&r(10)(i,n,{}),e.exports=function(e){i[n][e]=!0}},function(e,t,r){"use strict";r(43),e.exports=r(9).Object.assign},function(e,t,r){"use strict";var n=r(7);n(n.S+n.F,"Object",{assign:r(44)})},function(e,t,r){"use strict";var n=r(45),i=r(49),a=r(50),o=r(51),s=r(37),u=Object.assign;e.exports=!u||r(16)(function(){var e={},t={},r=Symbol(),n="abcdefghijklmnopqrst";return e[r]=7,n.split("").forEach(function(e){t[e]=e}),7!=u({},e)[r]||Object.keys(u({},t)).join("")!=n})?function(e,t){for(var r=o(e),u=arguments.length,l=1,c=i.f,h=a.f;u>l;)for(var d,f=s(arguments[l++]),p=c?n(f).concat(c(f)):n(f),v=p.length,m=0;v>m;)h.call(f,d=p[m++])&&(r[d]=f[d]);return r}:u},function(e,t,r){"use strict";var n=r(46),i=r(48);e.exports=Object.keys||function(e){return n(e,i)}},function(e,t,r){"use strict";var n=r(21),i=r(36),a=r(35)(!1),o=r(47)("IE_PROTO");e.exports=function(e,t){var r,s=i(e),u=0,l=[];for(r in s)r!=o&&n(s,r)&&l.push(r);for(;t.length>u;)n(s,r=t[u++])&&(~a(l,r)||l.push(r));return l}},function(e,t,r){"use strict";var n=r(29)("keys"),i=r(22);e.exports=function(e){return n[e]||(n[e]=i(e))}},function(e,t,r){"use strict";e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(e,t,r){"use strict";t.f=Object.getOwnPropertySymbols},function(e,t,r){"use strict";t.f={}.propertyIsEnumerable},function(e,t,r){"use strict";var n=r(31);e.exports=function(e){return Object(n(e))}},function(e,t,r){"use strict";r(53),e.exports=r(9).Math.log2},function(e,t,r){"use strict";var n=r(7);n(n.S,"Math",{log2:function(e){return Math.log(e)/Math.LN2}})},function(e,t,r){"use strict";r(55),e.exports=r(9).Number.isNaN},function(e,t,r){"use strict";var n=r(7);n(n.S,"Number",{isNaN:function(e){return e!=e}})},function(e,t,r){"use strict";r(57),e.exports=r(9).Number.isInteger},function(e,t,r){"use strict";var n=r(7);n(n.S,"Number",{isInteger:r(58)})},function(e,t,r){"use strict";var n=r(13),i=Math.floor;e.exports=function(e){return!n(e)&&isFinite(e)&&i(e)===e}},function(e,t,r){"use strict";r(60),r(62),r(72),r(75),r(92),r(93),e.exports=r(9).Promise},function(e,t,r){"use strict";var n=r(61),i={};i[r(28)("toStringTag")]="z",i+""!="[object z]"&&r(20)(Object.prototype,"toString",function(){return"[object "+n(this)+"]"},!0)},function(e,t,r){"use strict";var n=r(27),i=r(28)("toStringTag"),a="Arguments"==n(function(){return arguments}());e.exports=function(e){var t,r,o;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(r=function(e,t){try{return e[t]}catch(e){}}(t=Object(e),i))?r:a?n(t):"Object"==(o=n(t))&&"function"==typeof t.callee?"Arguments":o}},function(e,t,r){"use strict";var n=r(63)(!0);r(64)(String,"String",function(e){this._t=String(e),this._i=0},function(){var e,t=this._t,r=this._i;return r>=t.length?{value:void 0,done:!0}:(e=n(t,r),this._i+=e.length,{value:e,done:!1})})},function(e,t,r){"use strict";var n=r(39),i=r(31);e.exports=function(e){return function(t,r){var a,o,s=String(i(t)),u=n(r),l=s.length;return u<0||u>=l?e?"":void 0:(a=s.charCodeAt(u))<55296||a>56319||u+1===l||(o=s.charCodeAt(u+1))<56320||o>57343?e?s.charAt(u):a:e?s.slice(u,u+2):o-56320+(a-55296<<10)+65536}}},function(e,t,r){"use strict";var n=r(30),i=r(7),a=r(20),o=r(10),s=r(65),u=r(66),l=r(70),c=r(71),h=r(28)("iterator"),d=!([].keys&&"next"in[].keys()),f=function(){return this};e.exports=function(e,t,r,p,v,m,g){u(r,t,p);var y,b,_,A=function(e){if(!d&&e in P)return P[e];switch(e){case"keys":case"values":return function(){return new r(this,e)}}return function(){return new r(this,e)}},S=t+" Iterator",w="values"==v,k=!1,P=e.prototype,x=P[h]||P["@@iterator"]||v&&P[v],C=x||A(v),R=v?w?A("entries"):C:void 0,E="Array"==t&&P.entries||x;if(E&&(_=c(E.call(new e)))!==Object.prototype&&_.next&&(l(_,S,!0),n||"function"==typeof _[h]||o(_,h,f)),w&&x&&"values"!==x.name&&(k=!0,C=function(){return x.call(this)}),n&&!g||!d&&!k&&P[h]||o(P,h,C),s[t]=C,s[S]=f,v)if(y={values:w?C:A("values"),keys:m?C:A("keys"),entries:R},g)for(b in y)b in P||a(P,b,y[b]);else i(i.P+i.F*(d||k),t,y);return y}},function(e,t,r){"use strict";e.exports={}},function(e,t,r){"use strict";var n=r(67),i=r(19),a=r(70),o={};r(10)(o,r(28)("iterator"),function(){return this}),e.exports=function(e,t,r){e.prototype=n(o,{next:i(1,r)}),a(e,t+" Iterator")}},function(e,t,r){"use strict";var n=r(12),i=r(68),a=r(48),o=r(47)("IE_PROTO"),s=function(){},u=function(){var e,t=r(17)("iframe"),n=a.length;for(t.style.display="none",r(69).appendChild(t),t.src="javascript:",(e=t.contentWindow.document).open(),e.write("<script>document.F=Object<\/script>"),e.close(),u=e.F;n--;)delete u.prototype[a[n]];return u()};e.exports=Object.create||function(e,t){var r;return null!==e?(s.prototype=n(e),r=new s,s.prototype=null,r[o]=e):r=u(),void 0===t?r:i(r,t)}},function(e,t,r){"use strict";var n=r(11),i=r(12),a=r(45);e.exports=r(15)?Object.defineProperties:function(e,t){i(e);for(var r,o=a(t),s=o.length,u=0;s>u;)n.f(e,r=o[u++],t[r]);return e}},function(e,t,r){"use strict";var n=r(8).document;e.exports=n&&n.documentElement},function(e,t,r){"use strict";var n=r(11).f,i=r(21),a=r(28)("toStringTag");e.exports=function(e,t,r){e&&!i(e=r?e:e.prototype,a)&&n(e,a,{configurable:!0,value:t})}},function(e,t,r){"use strict";var n=r(21),i=r(51),a=r(47)("IE_PROTO"),o=Object.prototype;e.exports=Object.getPrototypeOf||function(e){return e=i(e),n(e,a)?e[a]:"function"==typeof e.constructor&&e instanceof e.constructor?e.constructor.prototype:e instanceof Object?o:null}},function(e,t,r){"use strict";for(var n=r(73),i=r(45),a=r(20),o=r(8),s=r(10),u=r(65),l=r(28),c=l("iterator"),h=l("toStringTag"),d=u.Array,f={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},p=i(f),v=0;v<p.length;v++){var m,g=p[v],y=f[g],b=o[g],_=b&&b.prototype;if(_&&(_[c]||s(_,c,d),_[h]||s(_,h,g),u[g]=d,y))for(m in n)_[m]||a(_,m,n[m],!0)}},function(e,t,r){"use strict";var n=r(41),i=r(74),a=r(65),o=r(36);e.exports=r(64)(Array,"Array",function(e,t){this._t=o(e),this._i=0,this._k=t},function(){var e=this._t,t=this._k,r=this._i++;return!e||r>=e.length?(this._t=void 0,i(1)):i(0,"keys"==t?r:"values"==t?e[r]:[r,e[r]])},"values"),a.Arguments=a.Array,n("keys"),n("values"),n("entries")},function(e,t,r){"use strict";e.exports=function(e,t){return{value:t,done:!!e}}},function(e,t,r){"use strict";var n,i,a,o,s=r(30),u=r(8),l=r(23),c=r(61),h=r(7),d=r(13),f=r(24),p=r(76),v=r(77),m=r(81),g=r(82).set,y=r(84)(),b=r(85),_=r(86),A=r(87),S=r(88),w=u.TypeError,k=u.process,P=k&&k.versions,x=P&&P.v8||"",C=u.Promise,R="process"==c(k),E=function(){},T=i=b.f,O=!!function(){try{var e=C.resolve(1),t=(e.constructor={})[r(28)("species")]=function(e){e(E,E)};return(R||"function"==typeof PromiseRejectionEvent)&&e.then(E)instanceof t&&0!==x.indexOf("6.6")&&-1===A.indexOf("Chrome/66")}catch(e){}}(),I=function(e){var t;return!(!d(e)||"function"!=typeof(t=e.then))&&t},F=function(e,t){if(!e._n){e._n=!0;var r=e._c;y(function(){for(var n=e._v,i=1==e._s,a=0,o=function(t){var r,a,o,s=i?t.ok:t.fail,u=t.resolve,l=t.reject,c=t.domain;try{s?(i||(2==e._h&&M(e),e._h=1),!0===s?r=n:(c&&c.enter(),r=s(n),c&&(c.exit(),o=!0)),r===t.promise?l(w("Promise-chain cycle")):(a=I(r))?a.call(r,u,l):u(r)):l(n)}catch(e){c&&!o&&c.exit(),l(e)}};r.length>a;)o(r[a++]);e._c=[],e._n=!1,t&&!e._h&&L(e)})}},L=function(e){g.call(u,function(){var t,r,n,i=e._v,a=j(e);if(a&&(t=_(function(){R?k.emit("unhandledRejection",i,e):(r=u.onunhandledrejection)?r({promise:e,reason:i}):(n=u.console)&&n.error&&n.error("Unhandled promise rejection",i)}),e._h=R||j(e)?2:1),e._a=void 0,a&&t.e)throw t.v})},j=function(e){return 1!==e._h&&0===(e._a||e._c).length},M=function(e){g.call(u,function(){var t;R?k.emit("rejectionHandled",e):(t=u.onrejectionhandled)&&t({promise:e,reason:e._v})})},D=function(e){var t=this;t._d||(t._d=!0,(t=t._w||t)._v=e,t._s=2,t._a||(t._a=t._c.slice()),F(t,!0))},N=function e(t){var r,n=this;if(!n._d){n._d=!0,n=n._w||n;try{if(n===t)throw w("Promise can't be resolved itself");(r=I(t))?y(function(){var i={_w:n,_d:!1};try{r.call(t,l(e,i,1),l(D,i,1))}catch(e){D.call(i,e)}}):(n._v=t,n._s=1,F(n,!1))}catch(e){D.call({_w:n,_d:!1},e)}}};O||(C=function(e){p(this,C,"Promise","_h"),f(e),n.call(this);try{e(l(N,this,1),l(D,this,1))}catch(e){D.call(this,e)}},(n=function(e){this._c=[],this._a=void 0,this._s=0,this._d=!1,this._v=void 0,this._h=0,this._n=!1}).prototype=r(89)(C.prototype,{then:function(e,t){var r=T(m(this,C));return r.ok="function"!=typeof e||e,r.fail="function"==typeof t&&t,r.domain=R?k.domain:void 0,this._c.push(r),this._a&&this._a.push(r),this._s&&F(this,!1),r.promise},catch:function(e){return this.then(void 0,e)}}),a=function(){var e=new n;this.promise=e,this.resolve=l(N,e,1),this.reject=l(D,e,1)},b.f=T=function(e){return e===C||e===o?new a(e):i(e)}),h(h.G+h.W+h.F*!O,{Promise:C}),r(70)(C,"Promise"),r(90)("Promise"),o=r(9).Promise,h(h.S+h.F*!O,"Promise",{reject:function(e){var t=T(this);return(0,t.reject)(e),t.promise}}),h(h.S+h.F*(s||!O),"Promise",{resolve:function(e){return S(s&&this===o?C:this,e)}}),h(h.S+h.F*!(O&&r(91)(function(e){C.all(e).catch(E)})),"Promise",{all:function(e){var t=this,r=T(t),n=r.resolve,i=r.reject,a=_(function(){var r=[],a=0,o=1;v(e,!1,function(e){var s=a++,u=!1;r.push(void 0),o++,t.resolve(e).then(function(e){u||(u=!0,r[s]=e,--o||n(r))},i)}),--o||n(r)});return a.e&&i(a.v),r.promise},race:function(e){var t=this,r=T(t),n=r.reject,i=_(function(){v(e,!1,function(e){t.resolve(e).then(r.resolve,n)})});return i.e&&n(i.v),r.promise}})},function(e,t,r){"use strict";e.exports=function(e,t,r,n){if(!(e instanceof t)||void 0!==n&&n in e)throw TypeError(r+": incorrect invocation!");return e}},function(e,t,r){"use strict";var n=r(23),i=r(78),a=r(79),o=r(12),s=r(38),u=r(80),l={},c={},h=e.exports=function(e,t,r,h,d){var f,p,v,m,g=d?function(){return e}:u(e),y=n(r,h,t?2:1),b=0;if("function"!=typeof g)throw TypeError(e+" is not iterable!");if(a(g)){for(f=s(e.length);f>b;b++)if((m=t?y(o(p=e[b])[0],p[1]):y(e[b]))===l||m===c)return m}else for(v=g.call(e);!(p=v.next()).done;)if((m=i(v,y,p.value,t))===l||m===c)return m};h.BREAK=l,h.RETURN=c},function(e,t,r){"use strict";var n=r(12);e.exports=function(e,t,r,i){try{return i?t(n(r)[0],r[1]):t(r)}catch(t){var a=e.return;throw void 0!==a&&n(a.call(e)),t}}},function(e,t,r){"use strict";var n=r(65),i=r(28)("iterator"),a=Array.prototype;e.exports=function(e){return void 0!==e&&(n.Array===e||a[i]===e)}},function(e,t,r){"use strict";var n=r(61),i=r(28)("iterator"),a=r(65);e.exports=r(9).getIteratorMethod=function(e){if(void 0!=e)return e[i]||e["@@iterator"]||a[n(e)]}},function(e,t,r){"use strict";var n=r(12),i=r(24),a=r(28)("species");e.exports=function(e,t){var r,o=n(e).constructor;return void 0===o||void 0==(r=n(o)[a])?t:i(r)}},function(e,t,r){"use strict";var n,i,a,o=r(23),s=r(83),u=r(69),l=r(17),c=r(8),h=c.process,d=c.setImmediate,f=c.clearImmediate,p=c.MessageChannel,v=c.Dispatch,m=0,g={},y=function(){var e=+this;if(g.hasOwnProperty(e)){var t=g[e];delete g[e],t()}},b=function(e){y.call(e.data)};d&&f||(d=function(e){for(var t=[],r=1;arguments.length>r;)t.push(arguments[r++]);return g[++m]=function(){s("function"==typeof e?e:Function(e),t)},n(m),m},f=function(e){delete g[e]},"process"==r(27)(h)?n=function(e){h.nextTick(o(y,e,1))}:v&&v.now?n=function(e){v.now(o(y,e,1))}:p?(a=(i=new p).port2,i.port1.onmessage=b,n=o(a.postMessage,a,1)):c.addEventListener&&"function"==typeof postMessage&&!c.importScripts?(n=function(e){c.postMessage(e+"","*")},c.addEventListener("message",b,!1)):n="onreadystatechange"in l("script")?function(e){u.appendChild(l("script")).onreadystatechange=function(){u.removeChild(this),y.call(e)}}:function(e){setTimeout(o(y,e,1),0)}),e.exports={set:d,clear:f}},function(e,t,r){"use strict";e.exports=function(e,t,r){var n=void 0===r;switch(t.length){case 0:return n?e():e.call(r);case 1:return n?e(t[0]):e.call(r,t[0]);case 2:return n?e(t[0],t[1]):e.call(r,t[0],t[1]);case 3:return n?e(t[0],t[1],t[2]):e.call(r,t[0],t[1],t[2]);case 4:return n?e(t[0],t[1],t[2],t[3]):e.call(r,t[0],t[1],t[2],t[3])}return e.apply(r,t)}},function(e,t,r){"use strict";var n=r(8),i=r(82).set,a=n.MutationObserver||n.WebKitMutationObserver,o=n.process,s=n.Promise,u="process"==r(27)(o);e.exports=function(){var e,t,r,l=function(){var n,i;for(u&&(n=o.domain)&&n.exit();e;){i=e.fn,e=e.next;try{i()}catch(n){throw e?r():t=void 0,n}}t=void 0,n&&n.enter()};if(u)r=function(){o.nextTick(l)};else if(!a||n.navigator&&n.navigator.standalone)if(s&&s.resolve){var c=s.resolve(void 0);r=function(){c.then(l)}}else r=function(){i.call(n,l)};else{var h=!0,d=document.createTextNode("");new a(l).observe(d,{characterData:!0}),r=function(){d.data=h=!h}}return function(n){var i={fn:n,next:void 0};t&&(t.next=i),e||(e=i,r()),t=i}}},function(e,t,r){"use strict";var n=r(24);e.exports.f=function(e){return new function(e){var t,r;this.promise=new e(function(e,n){if(void 0!==t||void 0!==r)throw TypeError("Bad Promise constructor");t=e,r=n}),this.resolve=n(t),this.reject=n(r)}(e)}},function(e,t,r){"use strict";e.exports=function(e){try{return{e:!1,v:e()}}catch(e){return{e:!0,v:e}}}},function(e,t,r){"use strict";var n=r(8).navigator;e.exports=n&&n.userAgent||""},function(e,t,r){"use strict";var n=r(12),i=r(13),a=r(85);e.exports=function(e,t){if(n(e),i(t)&&t.constructor===e)return t;var r=a.f(e);return(0,r.resolve)(t),r.promise}},function(e,t,r){"use strict";var n=r(20);e.exports=function(e,t,r){for(var i in t)n(e,i,t[i],r);return e}},function(e,t,r){"use strict";var n=r(8),i=r(11),a=r(15),o=r(28)("species");e.exports=function(e){var t=n[e];a&&t&&!t[o]&&i.f(t,o,{configurable:!0,get:function(){return this}})}},function(e,t,r){"use strict";var n=r(28)("iterator"),i=!1;try{var a=[7][n]();a.return=function(){i=!0},Array.from(a,function(){throw 2})}catch(e){}e.exports=function(e,t){if(!t&&!i)return!1;var r=!1;try{var a=[7],o=a[n]();o.next=function(){return{done:r=!0}},a[n]=function(){return o},e(a)}catch(e){}return r}},function(e,t,r){"use strict";var n=r(7),i=r(9),a=r(8),o=r(81),s=r(88);n(n.P+n.R,"Promise",{finally:function(e){var t=o(this,i.Promise||a.Promise),r="function"==typeof e;return this.then(r?function(r){return s(t,e()).then(function(){return r})}:e,r?function(r){return s(t,e()).then(function(){throw r})}:e)}})},function(e,t,r){"use strict";var n=r(7),i=r(85),a=r(86);n(n.S,"Promise",{try:function(e){var t=i.f(this),r=a(e);return(r.e?t.reject:t.resolve)(r.v),t.promise}})},function(e,t,r){"use strict";r(60),r(72),r(95),r(107),r(109),e.exports=r(9).WeakMap},function(e,t,r){"use strict";var n,i=r(96)(0),a=r(20),o=r(100),s=r(44),u=r(101),l=r(13),c=r(16),h=r(102),d=o.getWeak,f=Object.isExtensible,p=u.ufstore,v={},m=function(e){return function(){return e(this,arguments.length>0?arguments[0]:void 0)}},g={get:function(e){if(l(e)){var t=d(e);return!0===t?p(h(this,"WeakMap")).get(e):t?t[this._i]:void 0}},set:function(e,t){return u.def(h(this,"WeakMap"),e,t)}},y=e.exports=r(103)("WeakMap",m,g,u,!0,!0);c(function(){return 7!=(new y).set((Object.freeze||Object)(v),7).get(v)})&&(s((n=u.getConstructor(m,"WeakMap")).prototype,g),o.NEED=!0,i(["delete","has","get","set"],function(e){var t=y.prototype,r=t[e];a(t,e,function(t,i){if(l(t)&&!f(t)){this._f||(this._f=new n);var a=this._f[e](t,i);return"set"==e?this:a}return r.call(this,t,i)})}))},function(e,t,r){"use strict";var n=r(23),i=r(37),a=r(51),o=r(38),s=r(97);e.exports=function(e,t){var r=1==e,u=2==e,l=3==e,c=4==e,h=6==e,d=5==e||h,f=t||s;return function(t,s,p){for(var v,m,g=a(t),y=i(g),b=n(s,p,3),_=o(y.length),A=0,S=r?f(t,_):u?f(t,0):void 0;_>A;A++)if((d||A in y)&&(m=b(v=y[A],A,g),e))if(r)S[A]=m;else if(m)switch(e){case 3:return!0;case 5:return v;case 6:return A;case 2:S.push(v)}else if(c)return!1;return h?-1:l||c?c:S}}},function(e,t,r){"use strict";var n=r(98);e.exports=function(e,t){return new(n(e))(t)}},function(e,t,r){"use strict";var n=r(13),i=r(99),a=r(28)("species");e.exports=function(e){var t;return i(e)&&("function"!=typeof(t=e.constructor)||t!==Array&&!i(t.prototype)||(t=void 0),n(t)&&null===(t=t[a])&&(t=void 0)),void 0===t?Array:t}},function(e,t,r){"use strict";var n=r(27);e.exports=Array.isArray||function(e){return"Array"==n(e)}},function(e,t,r){"use strict";var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i=r(22)("meta"),a=r(13),o=r(21),s=r(11).f,u=0,l=Object.isExtensible||function(){return!0},c=!r(16)(function(){return l(Object.preventExtensions({}))}),h=function(e){s(e,i,{value:{i:"O"+ ++u,w:{}}})},d=e.exports={KEY:i,NEED:!1,fastKey:function(e,t){if(!a(e))return"symbol"==(void 0===e?"undefined":n(e))?e:("string"==typeof e?"S":"P")+e;if(!o(e,i)){if(!l(e))return"F";if(!t)return"E";h(e)}return e[i].i},getWeak:function(e,t){if(!o(e,i)){if(!l(e))return!0;if(!t)return!1;h(e)}return e[i].w},onFreeze:function(e){return c&&d.NEED&&l(e)&&!o(e,i)&&h(e),e}}},function(e,t,r){"use strict";var n=r(89),i=r(100).getWeak,a=r(12),o=r(13),s=r(76),u=r(77),l=r(96),c=r(21),h=r(102),d=l(5),f=l(6),p=0,v=function(e){return e._l||(e._l=new m)},m=function(){this.a=[]},g=function(e,t){return d(e.a,function(e){return e[0]===t})};m.prototype={get:function(e){var t=g(this,e);if(t)return t[1]},has:function(e){return!!g(this,e)},set:function(e,t){var r=g(this,e);r?r[1]=t:this.a.push([e,t])},delete:function(e){var t=f(this.a,function(t){return t[0]===e});return~t&&this.a.splice(t,1),!!~t}},e.exports={getConstructor:function(e,t,r,a){var l=e(function(e,n){s(e,l,t,"_i"),e._t=t,e._i=p++,e._l=void 0,void 0!=n&&u(n,r,e[a],e)});return n(l.prototype,{delete:function(e){if(!o(e))return!1;var r=i(e);return!0===r?v(h(this,t)).delete(e):r&&c(r,this._i)&&delete r[this._i]},has:function(e){if(!o(e))return!1;var r=i(e);return!0===r?v(h(this,t)).has(e):r&&c(r,this._i)}}),l},def:function(e,t,r){var n=i(a(t),!0);return!0===n?v(e).set(t,r):n[e._i]=r,e},ufstore:v}},function(e,t,r){"use strict";var n=r(13);e.exports=function(e,t){if(!n(e)||e._t!==t)throw TypeError("Incompatible receiver, "+t+" required!");return e}},function(e,t,r){"use strict";var n=r(8),i=r(7),a=r(20),o=r(89),s=r(100),u=r(77),l=r(76),c=r(13),h=r(16),d=r(91),f=r(70),p=r(104);e.exports=function(e,t,r,v,m,g){var y=n[e],b=y,_=m?"set":"add",A=b&&b.prototype,S={},w=function(e){var t=A[e];a(A,e,"delete"==e?function(e){return!(g&&!c(e))&&t.call(this,0===e?0:e)}:"has"==e?function(e){return!(g&&!c(e))&&t.call(this,0===e?0:e)}:"get"==e?function(e){return g&&!c(e)?void 0:t.call(this,0===e?0:e)}:"add"==e?function(e){return t.call(this,0===e?0:e),this}:function(e,r){return t.call(this,0===e?0:e,r),this})};if("function"==typeof b&&(g||A.forEach&&!h(function(){(new b).entries().next()}))){var k=new b,P=k[_](g?{}:-0,1)!=k,x=h(function(){k.has(1)}),C=d(function(e){new b(e)}),R=!g&&h(function(){for(var e=new b,t=5;t--;)e[_](t,t);return!e.has(-0)});C||((b=t(function(t,r){l(t,b,e);var n=p(new y,t,b);return void 0!=r&&u(r,m,n[_],n),n})).prototype=A,A.constructor=b),(x||R)&&(w("delete"),w("has"),m&&w("get")),(R||P)&&w(_),g&&A.clear&&delete A.clear}else b=v.getConstructor(t,e,m,_),o(b.prototype,r),s.NEED=!0;return f(b,e),S[e]=b,i(i.G+i.W+i.F*(b!=y),S),g||v.setStrong(b,e,m),b}},function(e,t,r){"use strict";var n=r(13),i=r(105).set;e.exports=function(e,t,r){var a,o=t.constructor;return o!==r&&"function"==typeof o&&(a=o.prototype)!==r.prototype&&n(a)&&i&&i(e,a),e}},function(e,t,r){"use strict";var n=r(13),i=r(12),a=function(e,t){if(i(e),!n(t)&&null!==t)throw TypeError(t+": can't set as prototype!")};e.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(e,t,n){try{(n=r(23)(Function.call,r(106).f(Object.prototype,"__proto__").set,2))(e,[]),t=!(e instanceof Array)}catch(e){t=!0}return function(e,r){return a(e,r),t?e.__proto__=r:n(e,r),e}}({},!1):void 0),check:a}},function(e,t,r){"use strict";var n=r(50),i=r(19),a=r(36),o=r(18),s=r(21),u=r(14),l=Object.getOwnPropertyDescriptor;t.f=r(15)?l:function(e,t){if(e=a(e),t=o(t,!0),u)try{return l(e,t)}catch(e){}if(s(e,t))return i(!n.f.call(e,t),e[t])}},function(e,t,r){"use strict";r(108)("WeakMap")},function(e,t,r){"use strict";var n=r(7);e.exports=function(e){n(n.S,e,{of:function(){for(var e=arguments.length,t=new Array(e);e--;)t[e]=arguments[e];return new this(t)}})}},function(e,t,r){"use strict";r(110)("WeakMap")},function(e,t,r){"use strict";var n=r(7),i=r(24),a=r(23),o=r(77);e.exports=function(e){n(n.S,e,{from:function(e){var t,r,n,s,u=arguments[1];return i(this),(t=void 0!==u)&&i(u),void 0==e?new this:(r=[],t?(n=0,s=a(u,arguments[2],2),o(e,!1,function(e){r.push(s(e,n++))})):o(e,!1,r.push,r),new this(r))}})}},function(e,t,r){"use strict";r(112),e.exports=r(9).String.codePointAt},function(e,t,r){"use strict";var n=r(7),i=r(63)(!1);n(n.P,"String",{codePointAt:function(e){return i(this,e)}})},function(e,t,r){"use strict";r(114),e.exports=r(9).String.fromCodePoint},function(e,t,r){"use strict";var n=r(7),i=r(40),a=String.fromCharCode,o=String.fromCodePoint;n(n.S+n.F*(!!o&&1!=o.length),"String",{fromCodePoint:function(e){for(var t,r=[],n=arguments.length,o=0;n>o;){if(t=+arguments[o++],i(t,1114111)!==t)throw RangeError(t+" is not a valid code point");r.push(t<65536?a(t):a(55296+((t-=65536)>>10),t%1024+56320))}return r.join("")}})},function(e,t,r){"use strict";r(116),r(60),e.exports=r(9).Symbol},function(e,t,r){"use strict";var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i=r(8),a=r(21),o=r(15),s=r(7),u=r(20),l=r(100).KEY,c=r(16),h=r(29),d=r(70),f=r(22),p=r(28),v=r(117),m=r(118),g=r(119),y=r(99),b=r(12),_=r(13),A=r(36),S=r(18),w=r(19),k=r(67),P=r(120),x=r(106),C=r(11),R=r(45),E=x.f,T=C.f,O=P.f,I=i.Symbol,F=i.JSON,L=F&&F.stringify,j=p("_hidden"),M=p("toPrimitive"),D={}.propertyIsEnumerable,N=h("symbol-registry"),q=h("symbols"),W=h("op-symbols"),U=Object.prototype,B="function"==typeof I,z=i.QObject,G=!z||!z.prototype||!z.prototype.findChild,H=o&&c(function(){return 7!=k(T({},"a",{get:function(){return T(this,"a",{value:7}).a}})).a})?function(e,t,r){var n=E(U,t);n&&delete U[t],T(e,t,r),n&&e!==U&&T(U,t,n)}:T,X=function(e){var t=q[e]=k(I.prototype);return t._k=e,t},Y=B&&"symbol"==n(I.iterator)?function(e){return"symbol"==(void 0===e?"undefined":n(e))}:function(e){return e instanceof I},V=function(e,t,r){return e===U&&V(W,t,r),b(e),t=S(t,!0),b(r),a(q,t)?(r.enumerable?(a(e,j)&&e[j][t]&&(e[j][t]=!1),r=k(r,{enumerable:w(0,!1)})):(a(e,j)||T(e,j,w(1,{})),e[j][t]=!0),H(e,t,r)):T(e,t,r)},Q=function(e,t){b(e);for(var r,n=g(t=A(t)),i=0,a=n.length;a>i;)V(e,r=n[i++],t[r]);return e},K=function(e){var t=D.call(this,e=S(e,!0));return!(this===U&&a(q,e)&&!a(W,e))&&(!(t||!a(this,e)||!a(q,e)||a(this,j)&&this[j][e])||t)},J=function(e,t){if(e=A(e),t=S(t,!0),e!==U||!a(q,t)||a(W,t)){var r=E(e,t);return!r||!a(q,t)||a(e,j)&&e[j][t]||(r.enumerable=!0),r}},Z=function(e){for(var t,r=O(A(e)),n=[],i=0;r.length>i;)a(q,t=r[i++])||t==j||t==l||n.push(t);return n},$=function(e){for(var t,r=e===U,n=O(r?W:A(e)),i=[],o=0;n.length>o;)!a(q,t=n[o++])||r&&!a(U,t)||i.push(q[t]);return i};B||(u((I=function(){if(this instanceof I)throw TypeError("Symbol is not a constructor!");var e=f(arguments.length>0?arguments[0]:void 0);return o&&G&&H(U,e,{configurable:!0,set:function t(r){this===U&&t.call(W,r),a(this,j)&&a(this[j],e)&&(this[j][e]=!1),H(this,e,w(1,r))}}),X(e)}).prototype,"toString",function(){return this._k}),x.f=J,C.f=V,r(121).f=P.f=Z,r(50).f=K,r(49).f=$,o&&!r(30)&&u(U,"propertyIsEnumerable",K,!0),v.f=function(e){return X(p(e))}),s(s.G+s.W+s.F*!B,{Symbol:I});for(var ee="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),te=0;ee.length>te;)p(ee[te++]);for(var re=R(p.store),ne=0;re.length>ne;)m(re[ne++]);s(s.S+s.F*!B,"Symbol",{for:function(e){return a(N,e+="")?N[e]:N[e]=I(e)},keyFor:function(e){if(!Y(e))throw TypeError(e+" is not a symbol!");for(var t in N)if(N[t]===e)return t},useSetter:function(){G=!0},useSimple:function(){G=!1}}),s(s.S+s.F*!B,"Object",{create:function(e,t){return void 0===t?k(e):Q(k(e),t)},defineProperty:V,defineProperties:Q,getOwnPropertyDescriptor:J,getOwnPropertyNames:Z,getOwnPropertySymbols:$}),F&&s(s.S+s.F*(!B||c(function(){var e=I();return"[null]"!=L([e])||"{}"!=L({a:e})||"{}"!=L(Object(e))})),"JSON",{stringify:function(e){for(var t,r,n=[e],i=1;arguments.length>i;)n.push(arguments[i++]);if(r=t=n[1],(_(t)||void 0!==e)&&!Y(e))return y(t)||(t=function(e,t){if("function"==typeof r&&(t=r.call(this,e,t)),!Y(t))return t}),n[1]=t,L.apply(F,n)}}),I.prototype[M]||r(10)(I.prototype,M,I.prototype.valueOf),d(I,"Symbol"),d(Math,"Math",!0),d(i.JSON,"JSON",!0)},function(e,t,r){"use strict";t.f=r(28)},function(e,t,r){"use strict";var n=r(8),i=r(9),a=r(30),o=r(117),s=r(11).f;e.exports=function(e){var t=i.Symbol||(i.Symbol=a?{}:n.Symbol||{});"_"==e.charAt(0)||e in t||s(t,e,{value:o.f(e)})}},function(e,t,r){"use strict";var n=r(45),i=r(49),a=r(50);e.exports=function(e){var t=n(e),r=i.f;if(r)for(var o,s=r(e),u=a.f,l=0;s.length>l;)u.call(e,o=s[l++])&&t.push(o);return t}},function(e,t,r){"use strict";var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i=r(36),a=r(121).f,o={}.toString,s="object"==("undefined"==typeof window?"undefined":n(window))&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[];e.exports.f=function(e){return s&&"[object Window]"==o.call(e)?function(e){try{return a(e)}catch(e){return s.slice()}}(e):a(i(e))}},function(e,t,r){"use strict";var n=r(46),i=r(48).concat("length","prototype");t.f=Object.getOwnPropertyNames||function(e){return n(e,i)}},function(e,t,r){"use strict";r(123),e.exports=r(9).Object.values},function(e,t,r){"use strict";var n=r(7),i=r(124)(!1);n(n.S,"Object",{values:function(e){return i(e)}})},function(e,t,r){"use strict";var n=r(45),i=r(36),a=r(50).f;e.exports=function(e){return function(t){for(var r,o=i(t),s=n(o),u=s.length,l=0,c=[];u>l;)a.call(o,r=s[l++])&&c.push(e?[r,o[r]]:o[r]);return c}}},function(e,t,r){"use strict";var n=!1;if("undefined"!=typeof ReadableStream)try{new ReadableStream({start:function(e){e.close()}}),n=!0}catch(e){}t.ReadableStream=n?ReadableStream:r(126).ReadableStream},function(e,t,r){"use strict";var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};!function(e,t){for(var r in t)e[r]=t[r]}(t,function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=e,r.c=t,r.i=function(e){return e},r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:n})},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=7)}([function(e,t,r){var i="function"==typeof Symbol&&"symbol"===n(Symbol.iterator)?function(e){return void 0===e?"undefined":n(e)}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":void 0===e?"undefined":n(e)},a=r(1).assert;function o(e){return"string"==typeof e||"symbol"===(void 0===e?"undefined":i(e))}function s(e,t,r){if("function"!=typeof e)throw new TypeError("Argument is not a function");return Function.prototype.apply.call(e,t,r)}t.typeIsObject=function(e){return"object"===(void 0===e?"undefined":i(e))&&null!==e||"function"==typeof e},t.createDataProperty=function(e,r,n){a(t.typeIsObject(e)),Object.defineProperty(e,r,{value:n,writable:!0,enumerable:!0,configurable:!0})},t.createArrayFromList=function(e){return e.slice()},t.ArrayBufferCopy=function(e,t,r,n,i){new Uint8Array(e).set(new Uint8Array(r,n,i),t)},t.CreateIterResultObject=function(e,t){a("boolean"==typeof t);var r={};return Object.defineProperty(r,"value",{value:e,enumerable:!0,writable:!0,configurable:!0}),Object.defineProperty(r,"done",{value:t,enumerable:!0,writable:!0,configurable:!0}),r},t.IsFiniteNonNegativeNumber=function(e){return!Number.isNaN(e)&&(e!==1/0&&!(e<0))},t.InvokeOrNoop=function(e,t,r){a(void 0!==e),a(o(t)),a(Array.isArray(r));var n=e[t];if(void 0!==n)return s(n,e,r)},t.PromiseInvokeOrNoop=function(e,r,n){a(void 0!==e),a(o(r)),a(Array.isArray(n));try{return Promise.resolve(t.InvokeOrNoop(e,r,n))}catch(e){return Promise.reject(e)}},t.PromiseInvokeOrPerformFallback=function(e,t,r,n,i){a(void 0!==e),a(o(t)),a(Array.isArray(r)),a(Array.isArray(i));var u=void 0;try{u=e[t]}catch(e){return Promise.reject(e)}if(void 0===u)return n.apply(null,i);try{return Promise.resolve(s(u,e,r))}catch(e){return Promise.reject(e)}},t.TransferArrayBuffer=function(e){return e.slice()},t.ValidateAndNormalizeHighWaterMark=function(e){if(e=Number(e),Number.isNaN(e)||e<0)throw new RangeError("highWaterMark property of a queuing strategy must be non-negative and non-NaN");return e},t.ValidateAndNormalizeQueuingStrategy=function(e,r){if(void 0!==e&&"function"!=typeof e)throw new TypeError("size property of a queuing strategy must be a function");return{size:e,highWaterMark:r=t.ValidateAndNormalizeHighWaterMark(r)}}},function(e,t,r){function n(e){this.name="AssertionError",this.message=e||"",this.stack=(new Error).stack}n.prototype=Object.create(Error.prototype),n.prototype.constructor=n,e.exports={rethrowAssertionErrorRejection:function(e){e&&e.constructor===n&&setTimeout(function(){throw e},0)},AssertionError:n,assert:function(e,t){if(!e)throw new n(t)}}},function(e,t,r){var n=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}();function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var a=r(0),o=a.InvokeOrNoop,s=a.PromiseInvokeOrNoop,u=a.ValidateAndNormalizeQueuingStrategy,l=a.typeIsObject,c=r(1),h=c.assert,d=c.rethrowAssertionErrorRejection,f=r(3),p=f.DequeueValue,v=f.EnqueueValueWithSize,m=f.PeekQueueValue,g=f.ResetQueue,y=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=r.size,a=r.highWaterMark,o=void 0===a?1:a;if(i(this,e),this._state="writable",this._storedError=void 0,this._writer=void 0,this._writableStreamController=void 0,this._writeRequests=[],this._inFlightWriteRequest=void 0,this._closeRequest=void 0,this._inFlightCloseRequest=void 0,this._pendingAbortRequest=void 0,this._backpressure=!1,void 0!==t.type)throw new RangeError("Invalid type is specified");this._writableStreamController=new N(this,t,n,o),this._writableStreamController.__startSteps()}return n(e,[{key:"abort",value:function(e){return!1===_(this)?Promise.reject(G("abort")):!0===A(this)?Promise.reject(new TypeError("Cannot abort a stream that already has a writer")):S(this,e)}},{key:"getWriter",value:function(){if(!1===_(this))throw G("getWriter");return b(this)}},{key:"locked",get:function(){if(!1===_(this))throw G("locked");return A(this)}}]),e}();function b(e){return new O(e)}function _(e){return!!l(e)&&!!Object.prototype.hasOwnProperty.call(e,"_writableStreamController")}function A(e){return h(!0===_(e),"IsWritableStreamLocked should only be used on known writable streams"),void 0!==e._writer}function S(e,t){var r=e._state;if("closed"===r)return Promise.resolve(void 0);if("errored"===r)return Promise.reject(e._storedError);var n=new TypeError("Requested to abort");if(void 0!==e._pendingAbortRequest)return Promise.reject(n);h("writable"===r||"erroring"===r,"state must be writable or erroring");var i=!1;"erroring"===r&&(i=!0,t=void 0);var a=new Promise(function(r,n){e._pendingAbortRequest={_resolve:r,_reject:n,_reason:t,_wasAlreadyErroring:i}});return!1===i&&k(e,n),a}function w(e,t){var r=e._state;"writable"!==r?(h("erroring"===r),P(e)):k(e,t)}function k(e,t){h(void 0===e._storedError,"stream._storedError === undefined"),h("writable"===e._state,"state must be writable");var r=e._writableStreamController;h(void 0!==r,"controller must not be undefined"),e._state="erroring",e._storedError=t;var n=e._writer;void 0!==n&&j(n,t),!1===R(e)&&!0===r._started&&P(e)}function P(e){h("erroring"===e._state,"stream._state === erroring"),h(!1===R(e),"WritableStreamHasOperationMarkedInFlight(stream) === false"),e._state="errored",e._writableStreamController.__errorSteps();for(var t=e._storedError,r=0;r<e._writeRequests.length;r++){e._writeRequests[r]._reject(t)}if(e._writeRequests=[],void 0!==e._pendingAbortRequest){var n=e._pendingAbortRequest;if(e._pendingAbortRequest=void 0,!0===n._wasAlreadyErroring)return n._reject(t),void E(e);e._writableStreamController.__abortSteps(n._reason).then(function(){n._resolve(),E(e)},function(t){n._reject(t),E(e)})}else E(e)}function x(e){h(void 0!==e._inFlightCloseRequest),e._inFlightCloseRequest._resolve(void 0),e._inFlightCloseRequest=void 0;var t=e._state;h("writable"===t||"erroring"===t),"erroring"===t&&(e._storedError=void 0,void 0!==e._pendingAbortRequest&&(e._pendingAbortRequest._resolve(),e._pendingAbortRequest=void 0)),e._state="closed";var r=e._writer;void 0!==r&&function(e){h(void 0!==e._closedPromise_resolve,"writer._closedPromise_resolve !== undefined"),h(void 0!==e._closedPromise_reject,"writer._closedPromise_reject !== undefined"),h("pending"===e._closedPromiseState,"writer._closedPromiseState is pending"),e._closedPromise_resolve(void 0),e._closedPromise_resolve=void 0,e._closedPromise_reject=void 0,e._closedPromiseState="resolved"}(r),h(void 0===e._pendingAbortRequest,"stream._pendingAbortRequest === undefined"),h(void 0===e._storedError,"stream._storedError === undefined")}function C(e){return void 0!==e._closeRequest||void 0!==e._inFlightCloseRequest}function R(e){return void 0!==e._inFlightWriteRequest||void 0!==e._inFlightCloseRequest}function E(e){h("errored"===e._state,'_stream_.[[state]] is `"errored"`'),void 0!==e._closeRequest&&(h(void 0===e._inFlightCloseRequest),e._closeRequest._reject(e._storedError),e._closeRequest=void 0);var t=e._writer;void 0!==t&&(V(t,e._storedError),t._closedPromise.catch(function(){}))}function T(e,t){h("writable"===e._state),h(!1===C(e));var r=e._writer;void 0!==r&&t!==e._backpressure&&(!0===t?function(e){h(void 0===e._readyPromise_resolve,"writer._readyPromise_resolve === undefined"),h(void 0===e._readyPromise_reject,"writer._readyPromise_reject === undefined"),e._readyPromise=new Promise(function(t,r){e._readyPromise_resolve=t,e._readyPromise_reject=r}),e._readyPromiseState="pending"}(r):(h(!1===t),J(r))),e._backpressure=t}e.exports={AcquireWritableStreamDefaultWriter:b,IsWritableStream:_,IsWritableStreamLocked:A,WritableStream:y,WritableStreamAbort:S,WritableStreamDefaultControllerError:z,WritableStreamDefaultWriterCloseWithErrorPropagation:function(e){var t=e._ownerWritableStream;h(void 0!==t);var r=t._state;if(!0===C(t)||"closed"===r)return Promise.resolve();if("errored"===r)return Promise.reject(t._storedError);return h("writable"===r||"erroring"===r),F(e)},WritableStreamDefaultWriterRelease:M,WritableStreamDefaultWriterWrite:D,WritableStreamCloseQueuedOrInFlight:C};var O=function(){function e(t){if(i(this,e),!1===_(t))throw new TypeError("WritableStreamDefaultWriter can only be constructed with a WritableStream instance");if(!0===A(t))throw new TypeError("This stream has already been locked for exclusive writing by another writer");this._ownerWritableStream=t,t._writer=this;var r,n=t._state;if("writable"===n)!1===C(t)&&!0===t._backpressure?((r=this)._readyPromise=new Promise(function(e,t){r._readyPromise_resolve=e,r._readyPromise_reject=t}),r._readyPromiseState="pending"):K(this),Y(this);else if("erroring"===n)Q(this,t._storedError),this._readyPromise.catch(function(){}),Y(this);else if("closed"===n)K(this),function(e){e._closedPromise=Promise.resolve(void 0),e._closedPromise_resolve=void 0,e._closedPromise_reject=void 0,e._closedPromiseState="resolved"}(this);else{h("errored"===n,"state must be errored");var a=t._storedError;Q(this,a),this._readyPromise.catch(function(){}),function(e,t){e._closedPromise=Promise.reject(t),e._closedPromise_resolve=void 0,e._closedPromise_reject=void 0,e._closedPromiseState="rejected"}(this,a),this._closedPromise.catch(function(){})}}return n(e,[{key:"abort",value:function(e){return!1===I(this)?Promise.reject(H("abort")):void 0===this._ownerWritableStream?Promise.reject(X("abort")):function(e,t){var r=e._ownerWritableStream;return h(void 0!==r),S(r,t)}(this,e)}},{key:"close",value:function(){if(!1===I(this))return Promise.reject(H("close"));var e=this._ownerWritableStream;return void 0===e?Promise.reject(X("close")):!0===C(e)?Promise.reject(new TypeError("cannot close an already-closing stream")):F(this)}},{key:"releaseLock",value:function(){if(!1===I(this))throw H("releaseLock");var e=this._ownerWritableStream;void 0!==e&&(h(void 0!==e._writer),M(this))}},{key:"write",value:function(e){return!1===I(this)?Promise.reject(H("write")):void 0===this._ownerWritableStream?Promise.reject(X("write to")):D(this,e)}},{key:"closed",get:function(){return!1===I(this)?Promise.reject(H("closed")):this._closedPromise}},{key:"desiredSize",get:function(){if(!1===I(this))throw H("desiredSize");if(void 0===this._ownerWritableStream)throw X("desiredSize");return function(e){var t=e._ownerWritableStream,r=t._state;if("errored"===r||"erroring"===r)return null;if("closed"===r)return 0;return q(t._writableStreamController)}(this)}},{key:"ready",get:function(){return!1===I(this)?Promise.reject(H("ready")):this._readyPromise}}]),e}();function I(e){return!!l(e)&&!!Object.prototype.hasOwnProperty.call(e,"_ownerWritableStream")}function F(e){var t=e._ownerWritableStream;h(void 0!==t);var r=t._state;if("closed"===r||"errored"===r)return Promise.reject(new TypeError("The stream (in "+r+" state) is not in the writable state and cannot be closed"));h("writable"===r||"erroring"===r),h(!1===C(t));var n,i=new Promise(function(e,r){var n={_resolve:e,_reject:r};t._closeRequest=n});return!0===t._backpressure&&"writable"===r&&J(e),n=t._writableStreamController,v(n,"close",0),W(n),i}function L(e,t){"pending"===e._closedPromiseState?V(e,t):function(e,t){h(void 0===e._closedPromise_resolve,"writer._closedPromise_resolve === undefined"),h(void 0===e._closedPromise_reject,"writer._closedPromise_reject === undefined"),h("pending"!==e._closedPromiseState,"writer._closedPromiseState is not pending"),e._closedPromise=Promise.reject(t),e._closedPromiseState="rejected"}(e,t),e._closedPromise.catch(function(){})}function j(e,t){"pending"===e._readyPromiseState?function(e,t){h(void 0!==e._readyPromise_resolve,"writer._readyPromise_resolve !== undefined"),h(void 0!==e._readyPromise_reject,"writer._readyPromise_reject !== undefined"),e._readyPromise_reject(t),e._readyPromise_resolve=void 0,e._readyPromise_reject=void 0,e._readyPromiseState="rejected"}(e,t):function(e,t){h(void 0===e._readyPromise_resolve,"writer._readyPromise_resolve === undefined"),h(void 0===e._readyPromise_reject,"writer._readyPromise_reject === undefined"),e._readyPromise=Promise.reject(t),e._readyPromiseState="rejected"}(e,t),e._readyPromise.catch(function(){})}function M(e){var t=e._ownerWritableStream;h(void 0!==t),h(t._writer===e);var r=new TypeError("Writer was released and can no longer be used to monitor the stream's closedness");j(e,r),L(e,r),t._writer=void 0,e._ownerWritableStream=void 0}function D(e,t){var r=e._ownerWritableStream;h(void 0!==r);var n=r._writableStreamController,i=function(e,t){var r=e._strategySize;if(void 0===r)return 1;try{return r(t)}catch(t){return U(e,t),1}}(n,t);if(r!==e._ownerWritableStream)return Promise.reject(X("write to"));var a=r._state;if("errored"===a)return Promise.reject(r._storedError);if(!0===C(r)||"closed"===a)return Promise.reject(new TypeError("The stream is closing or closed and cannot be written to"));if("erroring"===a)return Promise.reject(r._storedError);h("writable"===a);var o=function(e){return h(!0===A(e)),h("writable"===e._state),new Promise(function(t,r){var n={_resolve:t,_reject:r};e._writeRequests.push(n)})}(r);return function(e,t,r){var n={chunk:t};try{v(e,n,r)}catch(t){return void U(e,t)}var i=e._controlledWritableStream;if(!1===C(i)&&"writable"===i._state){var a=B(e);T(i,a)}W(e)}(n,t,i),o}var N=function(){function e(t,r,n,a){if(i(this,e),!1===_(t))throw new TypeError("WritableStreamDefaultController can only be constructed with a WritableStream instance");if(void 0!==t._writableStreamController)throw new TypeError("WritableStreamDefaultController instances can only be created by the WritableStream constructor");this._controlledWritableStream=t,this._underlyingSink=r,this._queue=void 0,this._queueTotalSize=void 0,g(this),this._started=!1;var o=u(n,a);this._strategySize=o.size,this._strategyHWM=o.highWaterMark,T(t,B(this))}return n(e,[{key:"error",value:function(e){if(!1===function(e){if(!l(e))return!1;if(!Object.prototype.hasOwnProperty.call(e,"_underlyingSink"))return!1;return!0}(this))throw new TypeError("WritableStreamDefaultController.prototype.error can only be used on a WritableStreamDefaultController");"writable"===this._controlledWritableStream._state&&z(this,e)}},{key:"__abortSteps",value:function(e){return s(this._underlyingSink,"abort",[e])}},{key:"__errorSteps",value:function(){g(this)}},{key:"__startSteps",value:function(){var e=this,t=o(this._underlyingSink,"start",[this]),r=this._controlledWritableStream;Promise.resolve(t).then(function(){h("writable"===r._state||"erroring"===r._state),e._started=!0,W(e)},function(t){h("writable"===r._state||"erroring"===r._state),e._started=!0,w(r,t)}).catch(d)}}]),e}();function q(e){return e._strategyHWM-e._queueTotalSize}function W(e){var t=e._controlledWritableStream;if(!1!==e._started&&void 0===t._inFlightWriteRequest){var r=t._state;if("closed"!==r&&"errored"!==r)if("erroring"!==r){if(0!==e._queue.length){var n=m(e);"close"===n?function(e){var t=e._controlledWritableStream;(function(e){h(void 0===e._inFlightCloseRequest),h(void 0!==e._closeRequest),e._inFlightCloseRequest=e._closeRequest,e._closeRequest=void 0})(t),p(e),h(0===e._queue.length,"queue must be empty once the final write record is dequeued"),s(e._underlyingSink,"close",[]).then(function(){x(t)},function(e){!function(e,t){h(void 0!==e._inFlightCloseRequest),e._inFlightCloseRequest._reject(t),e._inFlightCloseRequest=void 0,h("writable"===e._state||"erroring"===e._state),void 0!==e._pendingAbortRequest&&(e._pendingAbortRequest._reject(t),e._pendingAbortRequest=void 0),w(e,t)}(t,e)}).catch(d)}(e):function(e,t){var r=e._controlledWritableStream;(function(e){h(void 0===e._inFlightWriteRequest,"there must be no pending write request"),h(0!==e._writeRequests.length,"writeRequests must not be empty"),e._inFlightWriteRequest=e._writeRequests.shift()})(r),s(e._underlyingSink,"write",[t,e]).then(function(){!function(e){h(void 0!==e._inFlightWriteRequest),e._inFlightWriteRequest._resolve(void 0),e._inFlightWriteRequest=void 0}(r);var t=r._state;if(h("writable"===t||"erroring"===t),p(e),!1===C(r)&&"writable"===t){var n=B(e);T(r,n)}W(e)},function(e){!function(e,t){h(void 0!==e._inFlightWriteRequest),e._inFlightWriteRequest._reject(t),e._inFlightWriteRequest=void 0,h("writable"===e._state||"erroring"===e._state),w(e,t)}(r,e)}).catch(d)}(e,n.chunk)}}else P(t)}}function U(e,t){"writable"===e._controlledWritableStream._state&&z(e,t)}function B(e){return q(e)<=0}function z(e,t){var r=e._controlledWritableStream;h("writable"===r._state),k(r,t)}function G(e){return new TypeError("WritableStream.prototype."+e+" can only be used on a WritableStream")}function H(e){return new TypeError("WritableStreamDefaultWriter.prototype."+e+" can only be used on a WritableStreamDefaultWriter")}function X(e){return new TypeError("Cannot "+e+" a stream using a released writer")}function Y(e){e._closedPromise=new Promise(function(t,r){e._closedPromise_resolve=t,e._closedPromise_reject=r,e._closedPromiseState="pending"})}function V(e,t){h(void 0!==e._closedPromise_resolve,"writer._closedPromise_resolve !== undefined"),h(void 0!==e._closedPromise_reject,"writer._closedPromise_reject !== undefined"),h("pending"===e._closedPromiseState,"writer._closedPromiseState is pending"),e._closedPromise_reject(t),e._closedPromise_resolve=void 0,e._closedPromise_reject=void 0,e._closedPromiseState="rejected"}function Q(e,t){e._readyPromise=Promise.reject(t),e._readyPromise_resolve=void 0,e._readyPromise_reject=void 0,e._readyPromiseState="rejected"}function K(e){e._readyPromise=Promise.resolve(void 0),e._readyPromise_resolve=void 0,e._readyPromise_reject=void 0,e._readyPromiseState="fulfilled"}function J(e){h(void 0!==e._readyPromise_resolve,"writer._readyPromise_resolve !== undefined"),h(void 0!==e._readyPromise_reject,"writer._readyPromise_reject !== undefined"),e._readyPromise_resolve(void 0),e._readyPromise_resolve=void 0,e._readyPromise_reject=void 0,e._readyPromiseState="fulfilled"}},function(e,t,r){var n=r(0).IsFiniteNonNegativeNumber,i=r(1).assert;t.DequeueValue=function(e){i("_queue"in e&&"_queueTotalSize"in e,"Spec-level failure: DequeueValue should only be used on containers with [[queue]] and [[queueTotalSize]]."),i(e._queue.length>0,"Spec-level failure: should never dequeue from an empty queue.");var t=e._queue.shift();return e._queueTotalSize-=t.size,e._queueTotalSize<0&&(e._queueTotalSize=0),t.value},t.EnqueueValueWithSize=function(e,t,r){if(i("_queue"in e&&"_queueTotalSize"in e,"Spec-level failure: EnqueueValueWithSize should only be used on containers with [[queue]] and [[queueTotalSize]]."),r=Number(r),!n(r))throw new RangeError("Size must be a finite, non-NaN, non-negative number.");e._queue.push({value:t,size:r}),e._queueTotalSize+=r},t.PeekQueueValue=function(e){return i("_queue"in e&&"_queueTotalSize"in e,"Spec-level failure: PeekQueueValue should only be used on containers with [[queue]] and [[queueTotalSize]]."),i(e._queue.length>0,"Spec-level failure: should never peek at an empty queue."),e._queue[0].value},t.ResetQueue=function(e){i("_queue"in e&&"_queueTotalSize"in e,"Spec-level failure: ResetQueue should only be used on containers with [[queue]] and [[queueTotalSize]]."),e._queue=[],e._queueTotalSize=0}},function(e,t,r){var n=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}();function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var a=r(0),o=a.ArrayBufferCopy,s=a.CreateIterResultObject,u=a.IsFiniteNonNegativeNumber,l=a.InvokeOrNoop,c=a.PromiseInvokeOrNoop,h=a.TransferArrayBuffer,d=a.ValidateAndNormalizeQueuingStrategy,f=a.ValidateAndNormalizeHighWaterMark,p=r(0),v=p.createArrayFromList,m=p.createDataProperty,g=p.typeIsObject,y=r(1),b=y.assert,_=y.rethrowAssertionErrorRejection,A=r(3),S=A.DequeueValue,w=A.EnqueueValueWithSize,k=A.ResetQueue,P=r(2),x=P.AcquireWritableStreamDefaultWriter,C=P.IsWritableStream,R=P.IsWritableStreamLocked,E=P.WritableStreamAbort,T=P.WritableStreamDefaultWriterCloseWithErrorPropagation,O=P.WritableStreamDefaultWriterRelease,I=P.WritableStreamDefaultWriterWrite,F=P.WritableStreamCloseQueuedOrInFlight,L=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=r.size,a=r.highWaterMark;i(this,e),this._state="readable",this._reader=void 0,this._storedError=void 0,this._disturbed=!1,this._readableStreamController=void 0;var o=t.type;if("bytes"===String(o))void 0===a&&(a=0),this._readableStreamController=new de(this,t,a);else{if(void 0!==o)throw new RangeError("Invalid type is specified");void 0===a&&(a=1),this._readableStreamController=new ne(this,t,n,a)}}return n(e,[{key:"cancel",value:function(e){return!1===M(this)?Promise.reject(Ee("cancel")):!0===D(this)?Promise.reject(new TypeError("Cannot cancel a stream that already has a reader")):U(this,e)}},{key:"getReader",value:function(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}).mode;if(!1===M(this))throw Ee("getReader");if(void 0===e)return j(this);if("byob"===(e=String(e)))return new K(this);throw new RangeError("Invalid mode is specified")}},{key:"pipeThrough",value:function(e,t){var r=e.writable,n=e.readable;return function(e){try{Promise.prototype.then.call(e,void 0,function(){})}catch(e){}}(this.pipeTo(r,t)),n}},{key:"pipeTo",value:function(e){var t=this,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=r.preventClose,i=r.preventAbort,a=r.preventCancel;if(!1===M(this))return Promise.reject(Ee("pipeTo"));if(!1===C(e))return Promise.reject(new TypeError("ReadableStream.prototype.pipeTo's first argument must be a WritableStream"));if(n=Boolean(n),i=Boolean(i),a=Boolean(a),!0===D(this))return Promise.reject(new TypeError("ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream"));if(!0===R(e))return Promise.reject(new TypeError("ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream"));var o=j(this),s=x(e),u=!1,l=Promise.resolve();return new Promise(function(r,c){var h,d,f;if(m(t,o._closedPromise,function(t){!1===i?g(function(){return E(e,t)},!0,t):y(!0,t)}),m(e,s._closedPromise,function(e){!1===a?g(function(){return U(t,e)},!0,e):y(!0,e)}),h=t,d=o._closedPromise,f=function(){!1===n?g(function(){return T(s)}):y()},"closed"===h._state?f():d.then(f).catch(_),!0===F(e)||"closed"===e._state){var p=new TypeError("the destination writable stream closed before all data could be piped to it");!1===a?g(function(){return U(t,p)},!0,p):y(!0,p)}function v(){var e=l;return l.then(function(){return e!==l?v():void 0})}function m(e,t,r){"errored"===e._state?r(e._storedError):t.catch(r).catch(_)}function g(t,r,n){function i(){t().then(function(){return b(r,n)},function(e){return b(!0,e)}).catch(_)}!0!==u&&(u=!0,"writable"===e._state&&!1===F(e)?v().then(i):i())}function y(t,r){!0!==u&&(u=!0,"writable"===e._state&&!1===F(e)?v().then(function(){return b(t,r)}).catch(_):b(t,r))}function b(e,t){O(s),te(o),e?c(t):r(void 0)}(function e(){return l=Promise.resolve(),!0===u?Promise.resolve():s._readyPromise.then(function(){return re(o).then(function(e){var t=e.value;!0!==e.done&&(l=I(s,t).catch(function(){}))})}).then(e)})().catch(function(e){l=Promise.resolve(),_(e)})})}},{key:"tee",value:function(){if(!1===M(this))throw Ee("tee");var e=N(this,!1);return v(e)}},{key:"locked",get:function(){if(!1===M(this))throw Ee("locked");return D(this)}}]),e}();function j(e){return new Q(e)}function M(e){return!!g(e)&&!!Object.prototype.hasOwnProperty.call(e,"_readableStreamController")}function D(e){return b(!0===M(e),"IsReadableStreamLocked should only be used on known readable streams"),void 0!==e._reader}function N(e,t){b(!0===M(e)),b("boolean"==typeof t);var r=j(e),n={closedOrErrored:!1,canceled1:!1,canceled2:!1,reason1:void 0,reason2:void 0};n.promise=new Promise(function(e){n._resolve=e});var i=function(){return function e(){var t=e._reader,r=e._branch1,n=e._branch2,i=e._teeState;return re(t).then(function(e){b(g(e));var t=e.value,a=e.done;if(b("boolean"==typeof a),!0===a&&!1===i.closedOrErrored&&(!1===i.canceled1&&oe(r),!1===i.canceled2&&oe(n),i.closedOrErrored=!0),!0!==i.closedOrErrored){var o=t,s=t;!1===i.canceled1&&se(r,o),!1===i.canceled2&&se(n,s)}})}}();i._reader=r,i._teeState=n,i._cloneForBranch2=t;var a=function(){return function e(t){var r=e._stream,n=e._teeState;n.canceled1=!0;n.reason1=t;if(!0===n.canceled2){var i=v([n.reason1,n.reason2]),a=U(r,i);n._resolve(a)}return n.promise}}();a._stream=e,a._teeState=n;var o=function(){return function e(t){var r=e._stream,n=e._teeState;n.canceled2=!0;n.reason2=t;if(!0===n.canceled1){var i=v([n.reason1,n.reason2]),a=U(r,i);n._resolve(a)}return n.promise}}();o._stream=e,o._teeState=n;var s=Object.create(Object.prototype);m(s,"pull",i),m(s,"cancel",a);var u=new L(s),l=Object.create(Object.prototype);m(l,"pull",i),m(l,"cancel",o);var c=new L(l);return i._branch1=u._readableStreamController,i._branch2=c._readableStreamController,r._closedPromise.catch(function(e){!0!==n.closedOrErrored&&(ue(i._branch1,e),ue(i._branch2,e),n.closedOrErrored=!0)}),[u,c]}function q(e){return b(!0===J(e._reader)),b("readable"===e._state||"closed"===e._state),new Promise(function(t,r){var n={_resolve:t,_reject:r};e._reader._readIntoRequests.push(n)})}function W(e){return b(!0===Z(e._reader)),b("readable"===e._state),new Promise(function(t,r){var n={_resolve:t,_reject:r};e._reader._readRequests.push(n)})}function U(e,t){return e._disturbed=!0,"closed"===e._state?Promise.resolve(void 0):"errored"===e._state?Promise.reject(e._storedError):(B(e),e._readableStreamController.__cancelSteps(t).then(function(){}))}function B(e){b("readable"===e._state),e._state="closed";var t=e._reader;if(void 0!==t){if(!0===Z(t)){for(var r=0;r<t._readRequests.length;r++){(0,t._readRequests[r]._resolve)(s(void 0,!0))}t._readRequests=[]}!function(e){b(void 0!==e._closedPromise_resolve),b(void 0!==e._closedPromise_reject),e._closedPromise_resolve(void 0),e._closedPromise_resolve=void 0,e._closedPromise_reject=void 0}(t)}}function z(e,t){b(!0===M(e),"stream must be ReadableStream"),b("readable"===e._state,"state must be readable"),e._state="errored",e._storedError=t;var r=e._reader;if(void 0!==r){if(!0===Z(r)){for(var n=0;n<r._readRequests.length;n++){r._readRequests[n]._reject(t)}r._readRequests=[]}else{b(J(r),"reader must be ReadableStreamBYOBReader");for(var i=0;i<r._readIntoRequests.length;i++){r._readIntoRequests[i]._reject(t)}r._readIntoRequests=[]}Ie(r,t),r._closedPromise.catch(function(){})}}function G(e,t,r){var n=e._reader;b(n._readRequests.length>0),n._readRequests.shift()._resolve(s(t,r))}function H(e){return e._reader._readIntoRequests.length}function X(e){return e._reader._readRequests.length}function Y(e){var t=e._reader;return void 0!==t&&!1!==J(t)}function V(e){var t=e._reader;return void 0!==t&&!1!==Z(t)}e.exports={ReadableStream:L,IsReadableStreamDisturbed:function(e){return b(!0===M(e),"IsReadableStreamDisturbed should only be used on known readable streams"),e._disturbed},ReadableStreamDefaultControllerClose:oe,ReadableStreamDefaultControllerEnqueue:se,ReadableStreamDefaultControllerError:ue,ReadableStreamDefaultControllerGetDesiredSize:ce};var Q=function(){function e(t){if(i(this,e),!1===M(t))throw new TypeError("ReadableStreamDefaultReader can only be constructed with a ReadableStream instance");if(!0===D(t))throw new TypeError("This stream has already been locked for exclusive reading by another reader");$(this,t),this._readRequests=[]}return n(e,[{key:"cancel",value:function(e){return!1===Z(this)?Promise.reject(Oe("cancel")):void 0===this._ownerReadableStream?Promise.reject(Te("cancel")):ee(this,e)}},{key:"read",value:function(){return!1===Z(this)?Promise.reject(Oe("read")):void 0===this._ownerReadableStream?Promise.reject(Te("read from")):re(this)}},{key:"releaseLock",value:function(){if(!1===Z(this))throw Oe("releaseLock");if(void 0!==this._ownerReadableStream){if(this._readRequests.length>0)throw new TypeError("Tried to release a reader lock when that reader has pending read() calls un-settled");te(this)}}},{key:"closed",get:function(){return!1===Z(this)?Promise.reject(Oe("closed")):this._closedPromise}}]),e}(),K=function(){function e(t){if(i(this,e),!M(t))throw new TypeError("ReadableStreamBYOBReader can only be constructed with a ReadableStream instance given a byte source");if(!1===fe(t._readableStreamController))throw new TypeError("Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte source");if(D(t))throw new TypeError("This stream has already been locked for exclusive reading by another reader");$(this,t),this._readIntoRequests=[]}return n(e,[{key:"cancel",value:function(e){return J(this)?void 0===this._ownerReadableStream?Promise.reject(Te("cancel")):ee(this,e):Promise.reject(Fe("cancel"))}},{key:"read",value:function(e){return J(this)?void 0===this._ownerReadableStream?Promise.reject(Te("read from")):ArrayBuffer.isView(e)?0===e.byteLength?Promise.reject(new TypeError("view must have non-zero byteLength")):function(e,t){var r=e._ownerReadableStream;if(b(void 0!==r),r._disturbed=!0,"errored"===r._state)return Promise.reject(r._storedError);return function(e,t){var r=e._controlledReadableStream,n=1;t.constructor!==DataView&&(n=t.constructor.BYTES_PER_ELEMENT);var i=t.constructor,a={buffer:t.buffer,byteOffset:t.byteOffset,byteLength:t.byteLength,bytesFilled:0,elementSize:n,ctor:i,readerType:"byob"};if(e._pendingPullIntos.length>0)return a.buffer=h(a.buffer),e._pendingPullIntos.push(a),q(r);if("closed"===r._state){var o=new t.constructor(a.buffer,a.byteOffset,0);return Promise.resolve(s(o,!0))}if(e._queueTotalSize>0){if(!0===_e(e,a)){var u=ye(a);return Se(e),Promise.resolve(s(u,!1))}if(!0===e._closeRequested){var l=new TypeError("Insufficient bytes to fill elements in the given buffer");return Ce(e,l),Promise.reject(l)}}a.buffer=h(a.buffer),e._pendingPullIntos.push(a);var c=q(r);return ve(e),c}(r._readableStreamController,t)}(this,e):Promise.reject(new TypeError("view must be an array buffer view")):Promise.reject(Fe("read"))}},{key:"releaseLock",value:function(){if(!J(this))throw Fe("releaseLock");if(void 0!==this._ownerReadableStream){if(this._readIntoRequests.length>0)throw new TypeError("Tried to release a reader lock when that reader has pending read() calls un-settled");te(this)}}},{key:"closed",get:function(){return J(this)?this._closedPromise:Promise.reject(Fe("closed"))}}]),e}();function J(e){return!!g(e)&&!!Object.prototype.hasOwnProperty.call(e,"_readIntoRequests")}function Z(e){return!!g(e)&&!!Object.prototype.hasOwnProperty.call(e,"_readRequests")}function $(e,t){e._ownerReadableStream=t,t._reader=e,"readable"===t._state?function(e){e._closedPromise=new Promise(function(t,r){e._closedPromise_resolve=t,e._closedPromise_reject=r})}(e):"closed"===t._state?function(e){e._closedPromise=Promise.resolve(void 0),e._closedPromise_resolve=void 0,e._closedPromise_reject=void 0}(e):(b("errored"===t._state,"state must be errored"),function(e,t){e._closedPromise=Promise.reject(t),e._closedPromise_resolve=void 0,e._closedPromise_reject=void 0}(e,t._storedError),e._closedPromise.catch(function(){}))}function ee(e,t){var r=e._ownerReadableStream;return b(void 0!==r),U(r,t)}function te(e){b(void 0!==e._ownerReadableStream),b(e._ownerReadableStream._reader===e),"readable"===e._ownerReadableStream._state?Ie(e,new TypeError("Reader was released and can no longer be used to monitor the stream's closedness")):function(e,t){b(void 0===e._closedPromise_resolve),b(void 0===e._closedPromise_reject),e._closedPromise=Promise.reject(t)}(e,new TypeError("Reader was released and can no longer be used to monitor the stream's closedness")),e._closedPromise.catch(function(){}),e._ownerReadableStream._reader=void 0,e._ownerReadableStream=void 0}function re(e){var t=e._ownerReadableStream;return b(void 0!==t),t._disturbed=!0,"closed"===t._state?Promise.resolve(s(void 0,!0)):"errored"===t._state?Promise.reject(t._storedError):(b("readable"===t._state),t._readableStreamController.__pullSteps())}var ne=function(){function e(t,r,n,a){if(i(this,e),!1===M(t))throw new TypeError("ReadableStreamDefaultController can only be constructed with a ReadableStream instance");if(void 0!==t._readableStreamController)throw new TypeError("ReadableStreamDefaultController instances can only be created by the ReadableStream constructor");this._controlledReadableStream=t,this._underlyingSource=r,this._queue=void 0,this._queueTotalSize=void 0,k(this),this._started=!1,this._closeRequested=!1,this._pullAgain=!1,this._pulling=!1;var o=d(n,a);this._strategySize=o.size,this._strategyHWM=o.highWaterMark;var s=this,u=l(r,"start",[this]);Promise.resolve(u).then(function(){s._started=!0,b(!1===s._pulling),b(!1===s._pullAgain),ae(s)},function(e){le(s,e)}).catch(_)}return n(e,[{key:"close",value:function(){if(!1===ie(this))throw Le("close");if(!0===this._closeRequested)throw new TypeError("The stream has already been closed; do not close it again!");var e=this._controlledReadableStream._state;if("readable"!==e)throw new TypeError("The stream (in "+e+" state) is not in the readable state and cannot be closed");oe(this)}},{key:"enqueue",value:function(e){if(!1===ie(this))throw Le("enqueue");if(!0===this._closeRequested)throw new TypeError("stream is closed or draining");var t=this._controlledReadableStream._state;if("readable"!==t)throw new TypeError("The stream (in "+t+" state) is not in the readable state and cannot be enqueued to");return se(this,e)}},{key:"error",value:function(e){if(!1===ie(this))throw Le("error");var t=this._controlledReadableStream;if("readable"!==t._state)throw new TypeError("The stream is "+t._state+" and so cannot be errored");ue(this,e)}},{key:"__cancelSteps",value:function(e){return k(this),c(this._underlyingSource,"cancel",[e])}},{key:"__pullSteps",value:function(){var e=this._controlledReadableStream;if(this._queue.length>0){var t=S(this);return!0===this._closeRequested&&0===this._queue.length?B(e):ae(this),Promise.resolve(s(t,!1))}var r=W(e);return ae(this),r}},{key:"desiredSize",get:function(){if(!1===ie(this))throw Le("desiredSize");return ce(this)}}]),e}();function ie(e){return!!g(e)&&!!Object.prototype.hasOwnProperty.call(e,"_underlyingSource")}function ae(e){!1!==function(e){var t=e._controlledReadableStream;if("closed"===t._state||"errored"===t._state)return!1;if(!0===e._closeRequested)return!1;if(!1===e._started)return!1;if(!0===D(t)&&X(t)>0)return!0;if(ce(e)>0)return!0;return!1}(e)&&(!0!==e._pulling?(b(!1===e._pullAgain),e._pulling=!0,c(e._underlyingSource,"pull",[e]).then(function(){if(e._pulling=!1,!0===e._pullAgain)return e._pullAgain=!1,ae(e)},function(t){le(e,t)}).catch(_)):e._pullAgain=!0)}function oe(e){var t=e._controlledReadableStream;b(!1===e._closeRequested),b("readable"===t._state),e._closeRequested=!0,0===e._queue.length&&B(t)}function se(e,t){var r=e._controlledReadableStream;if(b(!1===e._closeRequested),b("readable"===r._state),!0===D(r)&&X(r)>0)G(r,t,!1);else{var n=1;if(void 0!==e._strategySize){var i=e._strategySize;try{n=i(t)}catch(t){throw le(e,t),t}}try{w(e,t,n)}catch(t){throw le(e,t),t}}ae(e)}function ue(e,t){var r=e._controlledReadableStream;b("readable"===r._state),k(e),z(r,t)}function le(e,t){"readable"===e._controlledReadableStream._state&&ue(e,t)}function ce(e){var t=e._controlledReadableStream._state;return"errored"===t?null:"closed"===t?0:e._strategyHWM-e._queueTotalSize}var he=function(){function e(t,r){i(this,e),this._associatedReadableByteStreamController=t,this._view=r}return n(e,[{key:"respond",value:function(e){if(!1===pe(this))throw je("respond");if(void 0===this._associatedReadableByteStreamController)throw new TypeError("This BYOB request has been invalidated");!function(e,t){if(t=Number(t),!1===u(t))throw new RangeError("bytesWritten must be a finite");b(e._pendingPullIntos.length>0),Pe(e,t)}(this._associatedReadableByteStreamController,e)}},{key:"respondWithNewView",value:function(e){if(!1===pe(this))throw je("respond");if(void 0===this._associatedReadableByteStreamController)throw new TypeError("This BYOB request has been invalidated");if(!ArrayBuffer.isView(e))throw new TypeError("You can only respond with array buffer views");!function(e,t){b(e._pendingPullIntos.length>0);var r=e._pendingPullIntos[0];if(r.byteOffset+r.bytesFilled!==t.byteOffset)throw new RangeError("The region specified by view does not match byobRequest");if(r.byteLength!==t.byteLength)throw new RangeError("The buffer of view has different capacity than byobRequest");r.buffer=t.buffer,Pe(e,t.byteLength)}(this._associatedReadableByteStreamController,e)}},{key:"view",get:function(){return this._view}}]),e}(),de=function(){function e(t,r,n){if(i(this,e),!1===M(t))throw new TypeError("ReadableByteStreamController can only be constructed with a ReadableStream instance given a byte source");if(void 0!==t._readableStreamController)throw new TypeError("ReadableByteStreamController instances can only be created by the ReadableStream constructor given a byte source");this._controlledReadableStream=t,this._underlyingByteSource=r,this._pullAgain=!1,this._pulling=!1,me(this),this._queue=this._queueTotalSize=void 0,k(this),this._closeRequested=!1,this._started=!1,this._strategyHWM=f(n);var a=r.autoAllocateChunkSize;if(void 0!==a&&(!1===Number.isInteger(a)||a<=0))throw new RangeError("autoAllocateChunkSize must be a positive integer");this._autoAllocateChunkSize=a,this._pendingPullIntos=[];var o=this,s=l(r,"start",[this]);Promise.resolve(s).then(function(){o._started=!0,b(!1===o._pulling),b(!1===o._pullAgain),ve(o)},function(e){"readable"===t._state&&Ce(o,e)}).catch(_)}return n(e,[{key:"close",value:function(){if(!1===fe(this))throw Me("close");if(!0===this._closeRequested)throw new TypeError("The stream has already been closed; do not close it again!");var e=this._controlledReadableStream._state;if("readable"!==e)throw new TypeError("The stream (in "+e+" state) is not in the readable state and cannot be closed");!function(e){var t=e._controlledReadableStream;if(b(!1===e._closeRequested),b("readable"===t._state),e._queueTotalSize>0)return void(e._closeRequested=!0);if(e._pendingPullIntos.length>0){var r=e._pendingPullIntos[0];if(r.bytesFilled>0){var n=new TypeError("Insufficient bytes to fill elements in the given buffer");throw Ce(e,n),n}}B(t)}(this)}},{key:"enqueue",value:function(e){if(!1===fe(this))throw Me("enqueue");if(!0===this._closeRequested)throw new TypeError("stream is closed or draining");var t=this._controlledReadableStream._state;if("readable"!==t)throw new TypeError("The stream (in "+t+" state) is not in the readable state and cannot be enqueued to");if(!ArrayBuffer.isView(e))throw new TypeError("You can only enqueue array buffer views when using a ReadableByteStreamController");!function(e,t){var r=e._controlledReadableStream;b(!1===e._closeRequested),b("readable"===r._state);var n=t.buffer,i=t.byteOffset,a=t.byteLength,o=h(n);if(!0===V(r))if(0===X(r))be(e,o,i,a);else{b(0===e._queue.length);var s=new Uint8Array(o,i,a);G(r,s,!1)}else!0===Y(r)?(be(e,o,i,a),ke(e)):(b(!1===D(r),"stream must not be locked"),be(e,o,i,a))}(this,e)}},{key:"error",value:function(e){if(!1===fe(this))throw Me("error");var t=this._controlledReadableStream;if("readable"!==t._state)throw new TypeError("The stream is "+t._state+" and so cannot be errored");Ce(this,e)}},{key:"__cancelSteps",value:function(e){this._pendingPullIntos.length>0&&(this._pendingPullIntos[0].bytesFilled=0);return k(this),c(this._underlyingByteSource,"cancel",[e])}},{key:"__pullSteps",value:function(){var e=this._controlledReadableStream;if(b(!0===V(e)),this._queueTotalSize>0){b(0===X(e));var t=this._queue.shift();this._queueTotalSize-=t.byteLength,Se(this);var r=void 0;try{r=new Uint8Array(t.buffer,t.byteOffset,t.byteLength)}catch(e){return Promise.reject(e)}return Promise.resolve(s(r,!1))}var n=this._autoAllocateChunkSize;if(void 0!==n){var i=void 0;try{i=new ArrayBuffer(n)}catch(e){return Promise.reject(e)}var a={buffer:i,byteOffset:0,byteLength:n,bytesFilled:0,elementSize:1,ctor:Uint8Array,readerType:"default"};this._pendingPullIntos.push(a)}var o=W(e);return ve(this),o}},{key:"byobRequest",get:function(){if(!1===fe(this))throw Me("byobRequest");if(void 0===this._byobRequest&&this._pendingPullIntos.length>0){var e=this._pendingPullIntos[0],t=new Uint8Array(e.buffer,e.byteOffset+e.bytesFilled,e.byteLength-e.bytesFilled);this._byobRequest=new he(this,t)}return this._byobRequest}},{key:"desiredSize",get:function(){if(!1===fe(this))throw Me("desiredSize");return Re(this)}}]),e}();function fe(e){return!!g(e)&&!!Object.prototype.hasOwnProperty.call(e,"_underlyingByteSource")}function pe(e){return!!g(e)&&!!Object.prototype.hasOwnProperty.call(e,"_associatedReadableByteStreamController")}function ve(e){!1!==function(e){var t=e._controlledReadableStream;if("readable"!==t._state)return!1;if(!0===e._closeRequested)return!1;if(!1===e._started)return!1;if(!0===V(t)&&X(t)>0)return!0;if(!0===Y(t)&&H(t)>0)return!0;if(Re(e)>0)return!0;return!1}(e)&&(!0!==e._pulling?(b(!1===e._pullAgain),e._pulling=!0,c(e._underlyingByteSource,"pull",[e]).then(function(){e._pulling=!1,!0===e._pullAgain&&(e._pullAgain=!1,ve(e))},function(t){"readable"===e._controlledReadableStream._state&&Ce(e,t)}).catch(_)):e._pullAgain=!0)}function me(e){we(e),e._pendingPullIntos=[]}function ge(e,t){b("errored"!==e._state,"state must not be errored");var r=!1;"closed"===e._state&&(b(0===t.bytesFilled),r=!0);var n=ye(t);"default"===t.readerType?G(e,n,r):(b("byob"===t.readerType),function(e,t,r){var n=e._reader;b(n._readIntoRequests.length>0),n._readIntoRequests.shift()._resolve(s(t,r))}(e,n,r))}function ye(e){var t=e.bytesFilled,r=e.elementSize;return b(t<=e.byteLength),b(t%r==0),new e.ctor(e.buffer,e.byteOffset,t/r)}function be(e,t,r,n){e._queue.push({buffer:t,byteOffset:r,byteLength:n}),e._queueTotalSize+=n}function _e(e,t){var r=t.elementSize,n=t.bytesFilled-t.bytesFilled%r,i=Math.min(e._queueTotalSize,t.byteLength-t.bytesFilled),a=t.bytesFilled+i,s=a-a%r,u=i,l=!1;s>n&&(u=s-t.bytesFilled,l=!0);for(var c=e._queue;u>0;){var h=c[0],d=Math.min(u,h.byteLength),f=t.byteOffset+t.bytesFilled;o(t.buffer,f,h.buffer,h.byteOffset,d),h.byteLength===d?c.shift():(h.byteOffset+=d,h.byteLength-=d),e._queueTotalSize-=d,Ae(e,d,t),u-=d}return!1===l&&(b(0===e._queueTotalSize,"queue must be empty"),b(t.bytesFilled>0),b(t.bytesFilled<t.elementSize)),l}function Ae(e,t,r){b(0===e._pendingPullIntos.length||e._pendingPullIntos[0]===r),we(e),r.bytesFilled+=t}function Se(e){b("readable"===e._controlledReadableStream._state),0===e._queueTotalSize&&!0===e._closeRequested?B(e._controlledReadableStream):ve(e)}function we(e){void 0!==e._byobRequest&&(e._byobRequest._associatedReadableByteStreamController=void 0,e._byobRequest._view=void 0,e._byobRequest=void 0)}function ke(e){for(b(!1===e._closeRequested);e._pendingPullIntos.length>0;){if(0===e._queueTotalSize)return;var t=e._pendingPullIntos[0];!0===_e(e,t)&&(xe(e),ge(e._controlledReadableStream,t))}}function Pe(e,t){var r=e._pendingPullIntos[0],n=e._controlledReadableStream;if("closed"===n._state){if(0!==t)throw new TypeError("bytesWritten must be 0 when calling respond() on a closed stream");!function(e,t){t.buffer=h(t.buffer),b(0===t.bytesFilled,"bytesFilled must be 0");var r=e._controlledReadableStream;if(!0===Y(r))for(;H(r)>0;)ge(r,xe(e))}(e,r)}else b("readable"===n._state),function(e,t,r){if(r.bytesFilled+t>r.byteLength)throw new RangeError("bytesWritten out of range");if(Ae(e,t,r),!(r.bytesFilled<r.elementSize)){xe(e);var n=r.bytesFilled%r.elementSize;if(n>0){var i=r.byteOffset+r.bytesFilled,a=r.buffer.slice(i-n,i);be(e,a,0,a.byteLength)}r.buffer=h(r.buffer),r.bytesFilled-=n,ge(e._controlledReadableStream,r),ke(e)}}(e,t,r)}function xe(e){var t=e._pendingPullIntos.shift();return we(e),t}function Ce(e,t){var r=e._controlledReadableStream;b("readable"===r._state),me(e),k(e),z(r,t)}function Re(e){var t=e._controlledReadableStream._state;return"errored"===t?null:"closed"===t?0:e._strategyHWM-e._queueTotalSize}function Ee(e){return new TypeError("ReadableStream.prototype."+e+" can only be used on a ReadableStream")}function Te(e){return new TypeError("Cannot "+e+" a stream using a released reader")}function Oe(e){return new TypeError("ReadableStreamDefaultReader.prototype."+e+" can only be used on a ReadableStreamDefaultReader")}function Ie(e,t){b(void 0!==e._closedPromise_resolve),b(void 0!==e._closedPromise_reject),e._closedPromise_reject(t),e._closedPromise_resolve=void 0,e._closedPromise_reject=void 0}function Fe(e){return new TypeError("ReadableStreamBYOBReader.prototype."+e+" can only be used on a ReadableStreamBYOBReader")}function Le(e){return new TypeError("ReadableStreamDefaultController.prototype."+e+" can only be used on a ReadableStreamDefaultController")}function je(e){return new TypeError("ReadableStreamBYOBRequest.prototype."+e+" can only be used on a ReadableStreamBYOBRequest")}function Me(e){return new TypeError("ReadableByteStreamController.prototype."+e+" can only be used on a ReadableByteStreamController")}},function(e,t,r){var n=r(6),i=r(4),a=r(2);t.TransformStream=n.TransformStream,t.ReadableStream=i.ReadableStream,t.IsReadableStreamDisturbed=i.IsReadableStreamDisturbed,t.ReadableStreamDefaultControllerClose=i.ReadableStreamDefaultControllerClose,t.ReadableStreamDefaultControllerEnqueue=i.ReadableStreamDefaultControllerEnqueue,t.ReadableStreamDefaultControllerError=i.ReadableStreamDefaultControllerError,t.ReadableStreamDefaultControllerGetDesiredSize=i.ReadableStreamDefaultControllerGetDesiredSize,t.AcquireWritableStreamDefaultWriter=a.AcquireWritableStreamDefaultWriter,t.IsWritableStream=a.IsWritableStream,t.IsWritableStreamLocked=a.IsWritableStreamLocked,t.WritableStream=a.WritableStream,t.WritableStreamAbort=a.WritableStreamAbort,t.WritableStreamDefaultControllerError=a.WritableStreamDefaultControllerError,t.WritableStreamDefaultWriterCloseWithErrorPropagation=a.WritableStreamDefaultWriterCloseWithErrorPropagation,t.WritableStreamDefaultWriterRelease=a.WritableStreamDefaultWriterRelease,t.WritableStreamDefaultWriterWrite=a.WritableStreamDefaultWriterWrite},function(e,t,r){var n=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}();function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var a=r(1).assert,o=r(0),s=o.InvokeOrNoop,u=o.PromiseInvokeOrPerformFallback,l=o.PromiseInvokeOrNoop,c=o.typeIsObject,h=r(4),d=h.ReadableStream,f=h.ReadableStreamDefaultControllerClose,p=h.ReadableStreamDefaultControllerEnqueue,v=h.ReadableStreamDefaultControllerError,m=h.ReadableStreamDefaultControllerGetDesiredSize,g=r(2),y=g.WritableStream,b=g.WritableStreamDefaultControllerError;function _(e,t){if(!0===e._errored)throw new TypeError("TransformStream is already errored");if(!0===e._readableClosed)throw new TypeError("Readable side is already closed");var r=e._readableController;try{p(r,t)}catch(t){throw e._readableClosed=!0,S(e,t),e._storedError}!0===m(r)<=0&&!1===e._backpressure&&P(e,!0)}function A(e){a(!1===e._errored),a(!1===e._readableClosed);try{f(e._readableController)}catch(e){a(!1)}e._readableClosed=!0}function S(e,t){!1===e._errored&&w(e,t)}function w(e,t){a(!1===e._errored),e._errored=!0,e._storedError=t,!1===e._writableDone&&b(e._writableController,t),!1===e._readableClosed&&v(e._readableController,t)}function k(e){return a(void 0!==e._backpressureChangePromise,"_backpressureChangePromise should have been initialized"),!1===e._backpressure?Promise.resolve():(a(!0===e._backpressure,"_backpressure should have been initialized"),e._backpressureChangePromise)}function P(e,t){a(e._backpressure!==t,"TransformStreamSetBackpressure() should be called only when backpressure is changed"),void 0!==e._backpressureChangePromise&&e._backpressureChangePromise_resolve(t),e._backpressureChangePromise=new Promise(function(t){e._backpressureChangePromise_resolve=t}),e._backpressureChangePromise.then(function(e){a(e!==t,"_backpressureChangePromise should be fulfilled only when backpressure is changed")}),e._backpressure=t}function x(e,t){return _(t._controlledTransformStream,e),Promise.resolve()}function C(e){return!!c(e)&&!!Object.prototype.hasOwnProperty.call(e,"_controlledTransformStream")}function R(e){return!!c(e)&&!!Object.prototype.hasOwnProperty.call(e,"_transformStreamController")}var E=function(){function e(t,r){i(this,e),this._transformStream=t,this._startPromise=r}return n(e,[{key:"start",value:function(e){var t=this._transformStream;return t._writableController=e,this._startPromise.then(function(){return k(t)})}},{key:"write",value:function(e){return function(e,t){a(!1===e._errored),a(!1===e._transforming),a(!1===e._backpressure),e._transforming=!0;var r=e._transformer,n=e._transformStreamController;return u(r,"transform",[t,n],x,[t,n]).then(function(){return e._transforming=!1,k(e)},function(t){return S(e,t),Promise.reject(t)})}(this._transformStream,e)}},{key:"abort",value:function(){var e=this._transformStream;e._writableDone=!0,w(e,new TypeError("Writable side aborted"))}},{key:"close",value:function(){var e=this._transformStream;return a(!1===e._transforming),e._writableDone=!0,l(e._transformer,"flush",[e._transformStreamController]).then(function(){return!0===e._errored?Promise.reject(e._storedError):(!1===e._readableClosed&&A(e),Promise.resolve())}).catch(function(t){return S(e,t),Promise.reject(e._storedError)})}}]),e}(),T=function(){function e(t,r){i(this,e),this._transformStream=t,this._startPromise=r}return n(e,[{key:"start",value:function(e){var t=this._transformStream;return t._readableController=e,this._startPromise.then(function(){return a(void 0!==t._backpressureChangePromise,"_backpressureChangePromise should have been initialized"),!0===t._backpressure?Promise.resolve():(a(!1===t._backpressure,"_backpressure should have been initialized"),t._backpressureChangePromise)})}},{key:"pull",value:function(){var e=this._transformStream;return a(!0===e._backpressure,"pull() should be never called while _backpressure is false"),a(void 0!==e._backpressureChangePromise,"_backpressureChangePromise should have been initialized"),P(e,!1),e._backpressureChangePromise}},{key:"cancel",value:function(){var e=this._transformStream;e._readableClosed=!0,w(e,new TypeError("Readable side canceled"))}}]),e}(),O=function(){function e(t){if(i(this,e),!1===R(t))throw new TypeError("TransformStreamDefaultController can only be constructed with a TransformStream instance");if(void 0!==t._transformStreamController)throw new TypeError("TransformStreamDefaultController instances can only be created by the TransformStream constructor");this._controlledTransformStream=t}return n(e,[{key:"enqueue",value:function(e){if(!1===C(this))throw F("enqueue");_(this._controlledTransformStream,e)}},{key:"close",value:function(){if(!1===C(this))throw F("close");!function(e){if(!0===e._errored)throw new TypeError("TransformStream is already errored");if(!0===e._readableClosed)throw new TypeError("Readable side is already closed");A(e)}(this._controlledTransformStream)}},{key:"error",value:function(e){if(!1===C(this))throw F("error");!function(e,t){if(!0===e._errored)throw new TypeError("TransformStream is already errored");w(e,t)}(this._controlledTransformStream,e)}},{key:"desiredSize",get:function(){if(!1===C(this))throw F("desiredSize");var e=this._controlledTransformStream._readableController;return m(e)}}]),e}(),I=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};i(this,e),this._transformer=t;var r=t.readableStrategy,n=t.writableStrategy;this._transforming=!1,this._errored=!1,this._storedError=void 0,this._writableController=void 0,this._readableController=void 0,this._transformStreamController=void 0,this._writableDone=!1,this._readableClosed=!1,this._backpressure=void 0,this._backpressureChangePromise=void 0,this._backpressureChangePromise_resolve=void 0,this._transformStreamController=new O(this);var o=void 0,u=new Promise(function(e){o=e}),l=new T(this,u);this._readable=new d(l,r);var c=new E(this,u);this._writable=new y(c,n),a(void 0!==this._writableController),a(void 0!==this._readableController),P(this,m(this._readableController)<=0);var h=this,f=s(t,"start",[h._transformStreamController]);o(f),u.catch(function(e){!1===h._errored&&(h._errored=!0,h._storedError=e)})}return n(e,[{key:"readable",get:function(){if(!1===R(this))throw L("readable");return this._readable}},{key:"writable",get:function(){if(!1===R(this))throw L("writable");return this._writable}}]),e}();function F(e){return new TypeError("TransformStreamDefaultController.prototype."+e+" can only be used on a TransformStreamDefaultController")}function L(e){return new TypeError("TransformStream.prototype."+e+" can only be used on a TransformStream")}e.exports={TransformStream:I}},function(e,t,r){e.exports=r(5)}]))},function(e,t,r){"use strict";var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i=!1;try{if("function"==typeof URL&&"object"===n(URL.prototype)&&"origin"in URL.prototype){var a=new URL("b","http://a");a.pathname="c%20d",i="http://a/c%20d"===a.href}}catch(e){}if(i)t.URL=URL;else{var o=r(128).URL,s=r(3).URL;s&&(o.createObjectURL=function(e){return s.createObjectURL.apply(s,arguments)},o.revokeObjectURL=function(e){s.revokeObjectURL(e)}),t.URL=o}},function(e,t,r){"use strict";!function(){var e=Object.create(null);e.ftp=21,e.file=0,e.gopher=70,e.http=80,e.https=443,e.ws=80,e.wss=443;var r=Object.create(null);function n(t){return void 0!==e[t]}function i(){d.call(this),this._isInvalid=!0}function a(e){return""===e&&i.call(this),e.toLowerCase()}function o(e){var t=e.charCodeAt(0);return t>32&&t<127&&-1===[34,35,60,62,63,96].indexOf(t)?e:encodeURIComponent(e)}function s(e){var t=e.charCodeAt(0);return t>32&&t<127&&-1===[34,35,60,62,96].indexOf(t)?e:encodeURIComponent(e)}r["%2e"]=".",r[".%2e"]="..",r["%2e."]="..",r["%2e%2e"]="..";var u,l=/[a-zA-Z]/,c=/[a-zA-Z0-9\+\-\.]/;function h(t,h,d){function f(e){b.push(e)}var p=h||"scheme start",v=0,m="",g=!1,y=!1,b=[];e:for(;(t[v-1]!==u||0===v)&&!this._isInvalid;){var _=t[v];switch(p){case"scheme start":if(!_||!l.test(_)){if(h){f("Invalid scheme.");break e}m="",p="no scheme";continue}m+=_.toLowerCase(),p="scheme";break;case"scheme":if(_&&c.test(_))m+=_.toLowerCase();else{if(":"!==_){if(h){if(_===u)break e;f("Code point not allowed in scheme: "+_);break e}m="",v=0,p="no scheme";continue}if(this._scheme=m,m="",h)break e;n(this._scheme)&&(this._isRelative=!0),p="file"===this._scheme?"relative":this._isRelative&&d&&d._scheme===this._scheme?"relative or authority":this._isRelative?"authority first slash":"scheme data"}break;case"scheme data":"?"===_?(this._query="?",p="query"):"#"===_?(this._fragment="#",p="fragment"):_!==u&&"\t"!==_&&"\n"!==_&&"\r"!==_&&(this._schemeData+=o(_));break;case"no scheme":if(d&&n(d._scheme)){p="relative";continue}f("Missing scheme."),i.call(this);break;case"relative or authority":if("/"!==_||"/"!==t[v+1]){f("Expected /, got: "+_),p="relative";continue}p="authority ignore slashes";break;case"relative":if(this._isRelative=!0,"file"!==this._scheme&&(this._scheme=d._scheme),_===u){this._host=d._host,this._port=d._port,this._path=d._path.slice(),this._query=d._query,this._username=d._username,this._password=d._password;break e}if("/"===_||"\\"===_)"\\"===_&&f("\\ is an invalid code point."),p="relative slash";else if("?"===_)this._host=d._host,this._port=d._port,this._path=d._path.slice(),this._query="?",this._username=d._username,this._password=d._password,p="query";else{if("#"!==_){var A=t[v+1],S=t[v+2];("file"!==this._scheme||!l.test(_)||":"!==A&&"|"!==A||S!==u&&"/"!==S&&"\\"!==S&&"?"!==S&&"#"!==S)&&(this._host=d._host,this._port=d._port,this._username=d._username,this._password=d._password,this._path=d._path.slice(),this._path.pop()),p="relative path";continue}this._host=d._host,this._port=d._port,this._path=d._path.slice(),this._query=d._query,this._fragment="#",this._username=d._username,this._password=d._password,p="fragment"}break;case"relative slash":if("/"!==_&&"\\"!==_){"file"!==this._scheme&&(this._host=d._host,this._port=d._port,this._username=d._username,this._password=d._password),p="relative path";continue}"\\"===_&&f("\\ is an invalid code point."),p="file"===this._scheme?"file host":"authority ignore slashes";break;case"authority first slash":if("/"!==_){f("Expected '/', got: "+_),p="authority ignore slashes";continue}p="authority second slash";break;case"authority second slash":if(p="authority ignore slashes","/"!==_){f("Expected '/', got: "+_);continue}break;case"authority ignore slashes":if("/"!==_&&"\\"!==_){p="authority";continue}f("Expected authority, got: "+_);break;case"authority":if("@"===_){g&&(f("@ already seen."),m+="%40"),g=!0;for(var w=0;w<m.length;w++){var k=m[w];if("\t"!==k&&"\n"!==k&&"\r"!==k)if(":"!==k||null!==this._password){var P=o(k);null!==this._password?this._password+=P:this._username+=P}else this._password="";else f("Invalid whitespace in authority.")}m=""}else{if(_===u||"/"===_||"\\"===_||"?"===_||"#"===_){v-=m.length,m="",p="host";continue}m+=_}break;case"file host":if(_===u||"/"===_||"\\"===_||"?"===_||"#"===_){2!==m.length||!l.test(m[0])||":"!==m[1]&&"|"!==m[1]?0===m.length?p="relative path start":(this._host=a.call(this,m),m="",p="relative path start"):p="relative path";continue}"\t"===_||"\n"===_||"\r"===_?f("Invalid whitespace in file host."):m+=_;break;case"host":case"hostname":if(":"!==_||y){if(_===u||"/"===_||"\\"===_||"?"===_||"#"===_){if(this._host=a.call(this,m),m="",p="relative path start",h)break e;continue}"\t"!==_&&"\n"!==_&&"\r"!==_?("["===_?y=!0:"]"===_&&(y=!1),m+=_):f("Invalid code point in host/hostname: "+_)}else if(this._host=a.call(this,m),m="",p="port","hostname"===h)break e;break;case"port":if(/[0-9]/.test(_))m+=_;else{if(_===u||"/"===_||"\\"===_||"?"===_||"#"===_||h){if(""!==m){var x=parseInt(m,10);x!==e[this._scheme]&&(this._port=x+""),m=""}if(h)break e;p="relative path start";continue}"\t"===_||"\n"===_||"\r"===_?f("Invalid code point in port: "+_):i.call(this)}break;case"relative path start":if("\\"===_&&f("'\\' not allowed in path."),p="relative path","/"!==_&&"\\"!==_)continue;break;case"relative path":var C;if(_!==u&&"/"!==_&&"\\"!==_&&(h||"?"!==_&&"#"!==_))"\t"!==_&&"\n"!==_&&"\r"!==_&&(m+=o(_));else"\\"===_&&f("\\ not allowed in relative path."),(C=r[m.toLowerCase()])&&(m=C),".."===m?(this._path.pop(),"/"!==_&&"\\"!==_&&this._path.push("")):"."===m&&"/"!==_&&"\\"!==_?this._path.push(""):"."!==m&&("file"===this._scheme&&0===this._path.length&&2===m.length&&l.test(m[0])&&"|"===m[1]&&(m=m[0]+":"),this._path.push(m)),m="","?"===_?(this._query="?",p="query"):"#"===_&&(this._fragment="#",p="fragment");break;case"query":h||"#"!==_?_!==u&&"\t"!==_&&"\n"!==_&&"\r"!==_&&(this._query+=s(_)):(this._fragment="#",p="fragment");break;case"fragment":_!==u&&"\t"!==_&&"\n"!==_&&"\r"!==_&&(this._fragment+=_)}v++}}function d(){this._scheme="",this._schemeData="",this._username="",this._password=null,this._host="",this._port="",this._path=[],this._query="",this._fragment="",this._isInvalid=!1,this._isRelative=!1}function f(e,t){void 0===t||t instanceof f||(t=new f(String(t))),this._url=e,d.call(this);var r=e.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g,"");h.call(this,r,null,t)}f.prototype={toString:function(){return this.href},get href(){if(this._isInvalid)return this._url;var e="";return""===this._username&&null===this._password||(e=this._username+(null!==this._password?":"+this._password:"")+"@"),this.protocol+(this._isRelative?"//"+e+this.host:"")+this.pathname+this._query+this._fragment},set href(e){d.call(this),h.call(this,e)},get protocol(){return this._scheme+":"},set protocol(e){this._isInvalid||h.call(this,e+":","scheme start")},get host(){return this._isInvalid?"":this._port?this._host+":"+this._port:this._host},set host(e){!this._isInvalid&&this._isRelative&&h.call(this,e,"host")},get hostname(){return this._host},set hostname(e){!this._isInvalid&&this._isRelative&&h.call(this,e,"hostname")},get port(){return this._port},set port(e){!this._isInvalid&&this._isRelative&&h.call(this,e,"port")},get pathname(){return this._isInvalid?"":this._isRelative?"/"+this._path.join("/"):this._schemeData},set pathname(e){!this._isInvalid&&this._isRelative&&(this._path=[],h.call(this,e,"relative path start"))},get search(){return this._isInvalid||!this._query||"?"===this._query?"":this._query},set search(e){!this._isInvalid&&this._isRelative&&(this._query="?","?"===e[0]&&(e=e.slice(1)),h.call(this,e,"query"))},get hash(){return this._isInvalid||!this._fragment||"#"===this._fragment?"":this._fragment},set hash(e){this._isInvalid||(this._fragment="#","#"===e[0]&&(e=e.slice(1)),h.call(this,e,"fragment"))},get origin(){var e;if(this._isInvalid||!this._scheme)return"";switch(this._scheme){case"data":case"file":case"javascript":case"mailto":return"null";case"blob":try{return new f(this._schemeData).origin||"null"}catch(e){}return"null"}return(e=this.host)?this._scheme+"://"+e:""}},t.URL=f}()},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.build=t.version=t.setPDFNetworkStreamFactory=t.PDFPageProxy=t.PDFDocumentProxy=t.PDFWorker=t.PDFDataRangeTransport=t.LoopbackPort=t.getDocument=void 0;var n,i=function(){return function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var r=[],n=!0,i=!1,a=void 0;try{for(var o,s=e[Symbol.iterator]();!(n=(o=s.next()).done)&&(r.push(o.value),!t||r.length!==t);n=!0);}catch(e){i=!0,a=e}finally{try{!n&&s.return&&s.return()}finally{if(i)throw a}}return r}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),a=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},s=r(1),u=r(130),l=r(131),c=r(132),h=r(133),d=r(3),f=(n=d)&&n.__esModule?n:{default:n},p=r(135),v=r(136),m=r(141),g=r(143),y=r(144);function b(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var _=65536,A=!1,S=void 0,w=null,k=!1;"undefined"==typeof window?(A=!0,void 0===require.ensure&&(require.ensure=require("node-ensure")),k=!0):"undefined"!=typeof require&&"function"==typeof require.ensure&&(k=!0),"undefined"!=typeof requirejs&&requirejs.toUrl&&(S=requirejs.toUrl("pdfjs-dist/build/pdf.worker.js"));var P,x="undefined"!=typeof requirejs&&requirejs.load;if(w=k?function(){return new Promise(function(e,t){require.ensure([],function(){try{var r;r=require("./pdf.worker.js"),e(r.WorkerMessageHandler)}catch(e){t(e)}},t,"pdfjsWorker")})}:x?function(){return new Promise(function(e,t){requirejs(["pdfjs-dist/build/pdf.worker"],function(r){try{e(r.WorkerMessageHandler)}catch(e){t(e)}},t)})}:null,!S&&"undefined"!=typeof document){var C=document.currentScript&&document.currentScript.src;C&&(S=C.replace(/(\.(?:min\.)?js)(\?.*)?$/i,".worker$1$2"))}var R=function(){var e=0;function t(){this._capability=(0,s.createPromiseCapability)(),this._transport=null,this._worker=null,this.docId="d"+e++,this.destroyed=!1,this.onPassword=null,this.onProgress=null,this.onUnsupportedFeature=null}return t.prototype={get promise(){return this._capability.promise},destroy:function(){var e=this;return this.destroyed=!0,(this._transport?this._transport.destroy():Promise.resolve()).then(function(){e._transport=null,e._worker&&(e._worker.destroy(),e._worker=null)})},then:function(e,t){return this.promise.then.apply(this.promise,arguments)}},t}(),E=function(){function e(t,r){b(this,e),this.length=t,this.initialData=r,this._rangeListeners=[],this._progressListeners=[],this._progressiveReadListeners=[],this._readyCapability=(0,s.createPromiseCapability)()}return a(e,[{key:"addRangeListener",value:function(e){this._rangeListeners.push(e)}},{key:"addProgressListener",value:function(e){this._progressListeners.push(e)}},{key:"addProgressiveReadListener",value:function(e){this._progressiveReadListeners.push(e)}},{key:"onDataRange",value:function(e,t){var r=!0,n=!1,i=void 0;try{for(var a,o=this._rangeListeners[Symbol.iterator]();!(r=(a=o.next()).done);r=!0){(0,a.value)(e,t)}}catch(e){n=!0,i=e}finally{try{!r&&o.return&&o.return()}finally{if(n)throw i}}}},{key:"onDataProgress",value:function(e){var t=this;this._readyCapability.promise.then(function(){var r=!0,n=!1,i=void 0;try{for(var a,o=t._progressListeners[Symbol.iterator]();!(r=(a=o.next()).done);r=!0){(0,a.value)(e)}}catch(e){n=!0,i=e}finally{try{!r&&o.return&&o.return()}finally{if(n)throw i}}})}},{key:"onDataProgressiveRead",value:function(e){var t=this;this._readyCapability.promise.then(function(){var r=!0,n=!1,i=void 0;try{for(var a,o=t._progressiveReadListeners[Symbol.iterator]();!(r=(a=o.next()).done);r=!0){(0,a.value)(e)}}catch(e){n=!0,i=e}finally{try{!r&&o.return&&o.return()}finally{if(n)throw i}}})}},{key:"transportReady",value:function(){this._readyCapability.resolve()}},{key:"requestDataRange",value:function(e,t){(0,s.unreachable)("Abstract method PDFDataRangeTransport.requestDataRange")}},{key:"abort",value:function(){}}]),e}(),T=function(){function e(t,r,n){b(this,e),this.loadingTask=n,this._pdfInfo=t,this._transport=r}return a(e,[{key:"getPage",value:function(e){return this._transport.getPage(e)}},{key:"getPageIndex",value:function(e){return this._transport.getPageIndex(e)}},{key:"getDestinations",value:function(){return this._transport.getDestinations()}},{key:"getDestination",value:function(e){return this._transport.getDestination(e)}},{key:"getPageLabels",value:function(){return this._transport.getPageLabels()}},{key:"getPageMode",value:function(){return this._transport.getPageMode()}},{key:"getAttachments",value:function(){return this._transport.getAttachments()}},{key:"getJavaScript",value:function(){return this._transport.getJavaScript()}},{key:"getOutline",value:function(){return this._transport.getOutline()}},{key:"getPermissions",value:function(){return this._transport.getPermissions()}},{key:"getMetadata",value:function(){return this._transport.getMetadata()}},{key:"getData",value:function(){return this._transport.getData()}},{key:"getDownloadInfo",value:function(){return this._transport.downloadInfoCapability.promise}},{key:"getStats",value:function(){return this._transport.getStats()}},{key:"cleanup",value:function(){this._transport.startCleanup()}},{key:"destroy",value:function(){return this.loadingTask.destroy()}},{key:"numPages",get:function(){return this._pdfInfo.numPages}},{key:"fingerprint",get:function(){return this._pdfInfo.fingerprint}},{key:"loadingParams",get:function(){return this._transport.loadingParams}}]),e}(),O=function(){function e(e,t,r){var n=arguments.length>3&&void 0!==arguments[3]&&arguments[3];this.pageIndex=e,this._pageInfo=t,this.transport=r,this._stats=n?new u.StatTimer:u.DummyStatTimer,this._pdfBug=n,this.commonObjs=r.commonObjs,this.objs=new j,this.cleanupAfterRender=!1,this.pendingCleanup=!1,this.intentStates=Object.create(null),this.destroyed=!1}return e.prototype={get pageNumber(){return this.pageIndex+1},get rotate(){return this._pageInfo.rotate},get ref(){return this._pageInfo.ref},get userUnit(){return this._pageInfo.userUnit},get view(){return this._pageInfo.view},getViewport:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.rotate,r=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return new u.PageViewport({viewBox:this.view,scale:e,rotation:t,dontFlip:r})},getAnnotations:function(e){var t=e&&e.intent||null;return this.annotationsPromise&&this.annotationsIntent===t||(this.annotationsPromise=this.transport.getAnnotations(this.pageIndex,t),this.annotationsIntent=t),this.annotationsPromise},render:function(e){var t=this,r=this._stats;r.time("Overall"),this.pendingCleanup=!1;var n="print"===e.intent?"print":"display",i=e.canvasFactory||new u.DOMCanvasFactory,a=new y.WebGLContext({enable:e.enableWebGL});this.intentStates[n]||(this.intentStates[n]=Object.create(null));var o=this.intentStates[n];o.displayReadyCapability||(o.receivingOperatorList=!0,o.displayReadyCapability=(0,s.createPromiseCapability)(),o.operatorList={fnArray:[],argsArray:[],lastChunk:!1},r.time("Page Request"),this.transport.messageHandler.send("RenderPageRequest",{pageIndex:this.pageNumber-1,intent:n,renderInteractiveForms:!0===e.renderInteractiveForms}));var l=function(e){var n=o.renderTasks.indexOf(c);n>=0&&o.renderTasks.splice(n,1),t.cleanupAfterRender&&(t.pendingCleanup=!0),t._tryCleanup(),e?c.capability.reject(e):c.capability.resolve(),r.timeEnd("Rendering"),r.timeEnd("Overall")},c=new D(l,e,this.objs,this.commonObjs,o.operatorList,this.pageNumber,i,a,this._pdfBug);c.useRequestAnimationFrame="print"!==n,o.renderTasks||(o.renderTasks=[]),o.renderTasks.push(c);var h=c.task;return o.displayReadyCapability.promise.then(function(e){t.pendingCleanup?l():(r.time("Rendering"),c.initializeGraphics(e),c.operatorListChanged())}).catch(l),h},getOperatorList:function(){this.intentStates.oplist||(this.intentStates.oplist=Object.create(null));var e,t=this.intentStates.oplist;return t.opListReadCapability||((e={}).operatorListChanged=function(){if(t.operatorList.lastChunk){t.opListReadCapability.resolve(t.operatorList);var r=t.renderTasks.indexOf(e);r>=0&&t.renderTasks.splice(r,1)}},t.receivingOperatorList=!0,t.opListReadCapability=(0,s.createPromiseCapability)(),t.renderTasks=[],t.renderTasks.push(e),t.operatorList={fnArray:[],argsArray:[],lastChunk:!1},this._stats.time("Page Request"),this.transport.messageHandler.send("RenderPageRequest",{pageIndex:this.pageIndex,intent:"oplist"})),t.opListReadCapability.promise},streamTextContent:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return this.transport.messageHandler.sendWithStream("GetTextContent",{pageIndex:this.pageNumber-1,normalizeWhitespace:!0===e.normalizeWhitespace,combineTextItems:!0!==e.disableCombineTextItems},{highWaterMark:100,size:function(e){return e.items.length}})},getTextContent:function(e){e=e||{};var t=this.streamTextContent(e);return new Promise(function(e,r){var n=t.getReader(),i={items:[],styles:Object.create(null)};!function t(){n.read().then(function(r){var n,a=r.value;r.done?e(i):(Object.assign(i.styles,a.styles),(n=i.items).push.apply(n,function(e){if(Array.isArray(e)){for(var t=0,r=Array(e.length);t<e.length;t++)r[t]=e[t];return r}return Array.from(e)}(a.items)),t())},r)}()})},_destroy:function(){this.destroyed=!0,this.transport.pageCache[this.pageIndex]=null;var e=[];return Object.keys(this.intentStates).forEach(function(t){"oplist"!==t&&this.intentStates[t].renderTasks.forEach(function(t){var r=t.capability.promise.catch(function(){});e.push(r),t.cancel()})},this),this.objs.clear(),this.annotationsPromise=null,this.pendingCleanup=!1,Promise.all(e)},cleanup:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.pendingCleanup=!0,this._tryCleanup(e)},_tryCleanup:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.pendingCleanup&&!Object.keys(this.intentStates).some(function(e){var t=this.intentStates[e];return 0!==t.renderTasks.length||t.receivingOperatorList},this)&&(Object.keys(this.intentStates).forEach(function(e){delete this.intentStates[e]},this),this.objs.clear(),this.annotationsPromise=null,e&&this._stats instanceof u.StatTimer&&(this._stats=new u.StatTimer),this.pendingCleanup=!1)},_startRenderPage:function(e,t){var r=this.intentStates[t];r.displayReadyCapability&&r.displayReadyCapability.resolve(e)},_renderPageChunk:function(e,t){var r,n,i=this.intentStates[t];for(r=0,n=e.length;r<n;r++)i.operatorList.fnArray.push(e.fnArray[r]),i.operatorList.argsArray.push(e.argsArray[r]);for(i.operatorList.lastChunk=e.lastChunk,r=0;r<i.renderTasks.length;r++)i.renderTasks[r].operatorListChanged();e.lastChunk&&(i.receivingOperatorList=!1,this._tryCleanup())},get stats(){return this._stats instanceof u.StatTimer?this._stats:null}},e}(),I=function(){function e(){var t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];b(this,e),this._listeners=[],this._defer=t,this._deferred=Promise.resolve(void 0)}return a(e,[{key:"postMessage",value:function(e,t){var r=this;if(this._defer){var n=new WeakMap,i={data:function e(r){if("object"!==(void 0===r?"undefined":o(r))||null===r)return r;if(n.has(r))return n.get(r);var i,a;if((a=r.buffer)&&(0,s.isArrayBuffer)(a)){var u=t&&t.includes(a);return i=r===a?r:u?new r.constructor(a,r.byteOffset,r.byteLength):new r.constructor(r),n.set(r,i),i}for(var l in i=Array.isArray(r)?[]:{},n.set(r,i),r){for(var c,h=r;!(c=Object.getOwnPropertyDescriptor(h,l));)h=Object.getPrototypeOf(h);void 0!==c.value&&"function"!=typeof c.value&&(i[l]=e(c.value))}return i}(e)};this._deferred.then(function(){r._listeners.forEach(function(e){e.call(this,i)},r)})}else this._listeners.forEach(function(t){t.call(this,{data:e})},this)}},{key:"addEventListener",value:function(e,t){this._listeners.push(t)}},{key:"removeEventListener",value:function(e,t){var r=this._listeners.indexOf(t);this._listeners.splice(r,1)}},{key:"terminate",value:function(){this._listeners=[]}}]),e}(),F=function(){var e=0;function t(){if(p.GlobalWorkerOptions.workerSrc)return p.GlobalWorkerOptions.workerSrc;if(void 0!==S)return S;throw new Error('No "GlobalWorkerOptions.workerSrc" specified.')}function r(){try{if("undefined"!=typeof window)return window.pdfjsWorker&&window.pdfjsWorker.WorkerMessageHandler}catch(e){}return null}var n=void 0;var i=new WeakMap;function a(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.name,r=void 0===t?null:t,n=e.port,a=void 0===n?null:n,o=e.postMessageTransfers,u=void 0===o||o,l=e.verbosity,c=void 0===l?(0,s.getVerbosityLevel)():l;if(a&&i.has(a))throw new Error("Cannot use more than one PDFWorker per port");if(this.name=r,this.destroyed=!1,this.postMessageTransfers=!1!==u,this.verbosity=c,this._readyCapability=(0,s.createPromiseCapability)(),this._port=null,this._webWorker=null,this._messageHandler=null,a)return i.set(a,this),void this._initializeFromPort(a);this._initialize()}return a.prototype={get promise(){return this._readyCapability.promise},get port(){return this._port},get messageHandler(){return this._messageHandler},_initializeFromPort:function(e){this._port=e,this._messageHandler=new v.MessageHandler("main","worker",e),this._messageHandler.on("ready",function(){}),this._readyCapability.resolve()},_initialize:function(){var e,n,i=this;if("undefined"!=typeof Worker&&!A&&!r()){var a=t();try{(0,s.isSameOrigin)(window.location.href,a)||(e=new s.URL(a,window.location).href,n="importScripts('"+e+"');",a=s.URL.createObjectURL(new Blob([n])));var o=new Worker(a),u=new v.MessageHandler("main","worker",o),l=function(){o.removeEventListener("error",c),u.destroy(),o.terminate(),i.destroyed?i._readyCapability.reject(new Error("Worker was destroyed")):i._setupFakeWorker()},c=function(){i._webWorker||l()};o.addEventListener("error",c),u.on("test",function(e){o.removeEventListener("error",c),i.destroyed?l():e&&e.supportTypedArray?(i._messageHandler=u,i._port=o,i._webWorker=o,e.supportTransfers||(i.postMessageTransfers=!1),i._readyCapability.resolve(),u.send("configure",{verbosity:i.verbosity})):(i._setupFakeWorker(),u.destroy(),o.terminate())}),u.on("ready",function(e){if(o.removeEventListener("error",c),i.destroyed)l();else try{h()}catch(e){i._setupFakeWorker()}});var h=function(){var e=new Uint8Array([i.postMessageTransfers?255:0]);try{u.send("test",e,[e.buffer])}catch(t){(0,s.info)("Cannot use postMessage transfers"),e[0]=0,u.send("test",e)}};return void h()}catch(e){(0,s.info)("The worker has been disabled.")}}this._setupFakeWorker()},_setupFakeWorker:function(){var i=this;A||((0,s.warn)("Setting up fake worker."),A=!0),function(){if(n)return n.promise;n=(0,s.createPromiseCapability)();var e=r();return e?(n.resolve(e),n.promise):((w||function(){return(0,u.loadScript)(t()).then(function(){return window.pdfjsWorker.WorkerMessageHandler})})().then(n.resolve,n.reject),n.promise)}().then(function(t){if(i.destroyed)i._readyCapability.reject(new Error("Worker was destroyed"));else{var r=new I;i._port=r;var n="fake"+e++,a=new v.MessageHandler(n+"_worker",n,r);t.setup(a,r);var o=new v.MessageHandler(n,n+"_worker",r);i._messageHandler=o,i._readyCapability.resolve()}}).catch(function(e){i._readyCapability.reject(new Error('Setting up fake worker failed: "'+e.message+'".'))})},destroy:function(){this.destroyed=!0,this._webWorker&&(this._webWorker.terminate(),this._webWorker=null),i.delete(this._port),this._port=null,this._messageHandler&&(this._messageHandler.destroy(),this._messageHandler=null)}},a.fromPort=function(e){if(!e||!e.port)throw new Error("PDFWorker.fromPort - invalid method signature.");return i.has(e.port)?i.get(e.port):new a(e)},a.getWorkerSrc=function(){return t()},a}(),L=function(){function e(t,r,n,i){b(this,e),this.messageHandler=t,this.loadingTask=r,this.commonObjs=new j,this.fontLoader=new l.FontLoader(r.docId),this._params=i,this.CMapReaderFactory=new i.CMapReaderFactory({baseUrl:i.cMapUrl,isCompressed:i.cMapPacked}),this.destroyed=!1,this.destroyCapability=null,this._passwordCapability=null,this._networkStream=n,this._fullReader=null,this._lastProgress=null,this.pageCache=[],this.pagePromises=[],this.downloadInfoCapability=(0,s.createPromiseCapability)(),this.setupMessageHandler()}return a(e,[{key:"destroy",value:function(){var e=this;if(this.destroyCapability)return this.destroyCapability.promise;this.destroyed=!0,this.destroyCapability=(0,s.createPromiseCapability)(),this._passwordCapability&&this._passwordCapability.reject(new Error("Worker was destroyed during onPassword callback"));var t=[];this.pageCache.forEach(function(e){e&&t.push(e._destroy())}),this.pageCache=[],this.pagePromises=[];var r=this.messageHandler.sendWithPromise("Terminate",null);return t.push(r),Promise.all(t).then(function(){e.fontLoader.clear(),e._networkStream&&e._networkStream.cancelAllRequests(),e.messageHandler&&(e.messageHandler.destroy(),e.messageHandler=null),e.destroyCapability.resolve()},this.destroyCapability.reject),this.destroyCapability.promise}},{key:"setupMessageHandler",value:function(){var e=this.messageHandler,t=this.loadingTask;e.on("GetReader",function(e,t){var r=this;(0,s.assert)(this._networkStream),this._fullReader=this._networkStream.getFullReader(),this._fullReader.onProgress=function(e){r._lastProgress={loaded:e.loaded,total:e.total}},t.onPull=function(){r._fullReader.read().then(function(e){var r=e.value;e.done?t.close():((0,s.assert)((0,s.isArrayBuffer)(r)),t.enqueue(new Uint8Array(r),1,[r]))}).catch(function(e){t.error(e)})},t.onCancel=function(e){r._fullReader.cancel(e)}},this),e.on("ReaderHeadersReady",function(e){var r=this,n=(0,s.createPromiseCapability)(),i=this._fullReader;return i.headersReady.then(function(){i.isStreamingSupported&&i.isRangeSupported||(r._lastProgress&&t.onProgress&&t.onProgress(r._lastProgress),i.onProgress=function(e){t.onProgress&&t.onProgress({loaded:e.loaded,total:e.total})}),n.resolve({isStreamingSupported:i.isStreamingSupported,isRangeSupported:i.isRangeSupported,contentLength:i.contentLength})},n.reject),n.promise},this),e.on("GetRangeReader",function(e,t){(0,s.assert)(this._networkStream);var r=this._networkStream.getRangeReader(e.begin,e.end);t.onPull=function(){r.read().then(function(e){var r=e.value;e.done?t.close():((0,s.assert)((0,s.isArrayBuffer)(r)),t.enqueue(new Uint8Array(r),1,[r]))}).catch(function(e){t.error(e)})},t.onCancel=function(e){r.cancel(e)}},this),e.on("GetDoc",function(e){var r=e.pdfInfo;this.numPages=r.numPages,this.pdfDocument=new T(r,this,t),t._capability.resolve(this.pdfDocument)},this),e.on("PasswordRequest",function(e){var r=this;if(this._passwordCapability=(0,s.createPromiseCapability)(),t.onPassword){try{t.onPassword(function(e){r._passwordCapability.resolve({password:e})},e.code)}catch(e){this._passwordCapability.reject(e)}}else this._passwordCapability.reject(new s.PasswordException(e.message,e.code));return this._passwordCapability.promise},this),e.on("PasswordException",function(e){t._capability.reject(new s.PasswordException(e.message,e.code))},this),e.on("InvalidPDF",function(e){t._capability.reject(new s.InvalidPDFException(e.message))},this),e.on("MissingPDF",function(e){t._capability.reject(new s.MissingPDFException(e.message))},this),e.on("UnexpectedResponse",function(e){t._capability.reject(new s.UnexpectedResponseException(e.message,e.status))},this),e.on("UnknownError",function(e){t._capability.reject(new s.UnknownErrorException(e.message,e.details))},this),e.on("DataLoaded",function(e){t.onProgress&&t.onProgress({loaded:e.length,total:e.length}),this.downloadInfoCapability.resolve(e)},this),e.on("StartRenderPage",function(e){if(!this.destroyed){var t=this.pageCache[e.pageIndex];t._stats.timeEnd("Page Request"),t._startRenderPage(e.transparency,e.intent)}},this),e.on("RenderPageChunk",function(e){this.destroyed||this.pageCache[e.pageIndex]._renderPageChunk(e.operatorList,e.intent)},this),e.on("commonobj",function(e){var t=this;if(!this.destroyed){var r=i(e,3),n=r[0],a=r[1],o=r[2];if(!this.commonObjs.hasData(n))switch(a){case"Font":var u=this._params;if("error"in o){var c=o.error;(0,s.warn)("Error during font loading: "+c),this.commonObjs.resolve(n,c);break}var h=null;u.pdfBug&&f.default.FontInspector&&f.default.FontInspector.enabled&&(h={registerFont:function(e,t){f.default.FontInspector.fontAdded(e,t)}});var d=new l.FontFaceObject(o,{isEvalSupported:u.isEvalSupported,disableFontFace:u.disableFontFace,ignoreErrors:u.ignoreErrors,onUnsupportedFeature:this._onUnsupportedFeature.bind(this),fontRegistry:h});this.fontLoader.bind([d],function(e){t.commonObjs.resolve(n,d)});break;case"FontPath":this.commonObjs.resolve(n,o);break;default:throw new Error("Got unknown common object type "+a)}}},this),e.on("obj",function(e){if(!this.destroyed){var t=i(e,4),r=t[0],n=t[1],a=t[2],o=t[3],s=this.pageCache[n];if(!s.objs.hasData(r))switch(a){case"JpegStream":return new Promise(function(e,t){var r=new Image;r.onload=function(){e(r)},r.onerror=function(){t(new Error("Error during JPEG image loading"))},r.src=o}).then(function(e){s.objs.resolve(r,e)});case"Image":s.objs.resolve(r,o);o&&"data"in o&&o.data.length>8e6&&(s.cleanupAfterRender=!0);break;default:throw new Error("Got unknown object type "+a)}}},this),e.on("DocProgress",function(e){this.destroyed||t.onProgress&&t.onProgress({loaded:e.loaded,total:e.total})},this),e.on("PageError",function(e){if(!this.destroyed){var t=this.pageCache[e.pageNum-1].intentStates[e.intent];if(!t.displayReadyCapability)throw new Error(e.error);if(t.displayReadyCapability.reject(e.error),t.operatorList){t.operatorList.lastChunk=!0;for(var r=0;r<t.renderTasks.length;r++)t.renderTasks[r].operatorListChanged()}}},this),e.on("UnsupportedFeature",this._onUnsupportedFeature,this),e.on("JpegDecode",function(e){if(this.destroyed)return Promise.reject(new Error("Worker was destroyed"));if("undefined"==typeof document)return Promise.reject(new Error('"document" is not defined.'));var t=i(e,2),r=t[0],n=t[1];return 3!==n&&1!==n?Promise.reject(new Error("Only 3 components or 1 component can be returned")):new Promise(function(e,t){var i=new Image;i.onload=function(){var t=i.width,r=i.height,a=t*r,o=4*a,s=new Uint8ClampedArray(a*n),u=document.createElement("canvas");u.width=t,u.height=r;var l=u.getContext("2d");l.drawImage(i,0,0);var c=l.getImageData(0,0,t,r).data;if(3===n)for(var h=0,d=0;h<o;h+=4,d+=3)s[d]=c[h],s[d+1]=c[h+1],s[d+2]=c[h+2];else if(1===n)for(var f=0,p=0;f<o;f+=4,p++)s[p]=c[f];e({data:s,width:t,height:r})},i.onerror=function(){t(new Error("JpegDecode failed to load image"))},i.src=r})},this),e.on("FetchBuiltInCMap",function(e){return this.destroyed?Promise.reject(new Error("Worker was destroyed")):this.CMapReaderFactory.fetch({name:e.name})},this)}},{key:"_onUnsupportedFeature",value:function(e){var t=e.featureId;this.destroyed||this.loadingTask.onUnsupportedFeature&&this.loadingTask.onUnsupportedFeature(t)}},{key:"getData",value:function(){return this.messageHandler.sendWithPromise("GetData",null)}},{key:"getPage",value:function(e){var t=this;if(!Number.isInteger(e)||e<=0||e>this.numPages)return Promise.reject(new Error("Invalid page request"));var r=e-1;if(r in this.pagePromises)return this.pagePromises[r];var n=this.messageHandler.sendWithPromise("GetPage",{pageIndex:r}).then(function(e){if(t.destroyed)throw new Error("Transport destroyed");var n=new O(r,e,t,t._params.pdfBug);return t.pageCache[r]=n,n});return this.pagePromises[r]=n,n}},{key:"getPageIndex",value:function(e){return this.messageHandler.sendWithPromise("GetPageIndex",{ref:e}).catch(function(e){return Promise.reject(new Error(e))})}},{key:"getAnnotations",value:function(e,t){return this.messageHandler.sendWithPromise("GetAnnotations",{pageIndex:e,intent:t})}},{key:"getDestinations",value:function(){return this.messageHandler.sendWithPromise("GetDestinations",null)}},{key:"getDestination",value:function(e){return"string"!=typeof e?Promise.reject(new Error("Invalid destination request.")):this.messageHandler.sendWithPromise("GetDestination",{id:e})}},{key:"getPageLabels",value:function(){return this.messageHandler.sendWithPromise("GetPageLabels",null)}},{key:"getPageMode",value:function(){return this.messageHandler.sendWithPromise("GetPageMode",null)}},{key:"getAttachments",value:function(){return this.messageHandler.sendWithPromise("GetAttachments",null)}},{key:"getJavaScript",value:function(){return this.messageHandler.sendWithPromise("GetJavaScript",null)}},{key:"getOutline",value:function(){return this.messageHandler.sendWithPromise("GetOutline",null)}},{key:"getPermissions",value:function(){return this.messageHandler.sendWithPromise("GetPermissions",null)}},{key:"getMetadata",value:function(){var e=this;return this.messageHandler.sendWithPromise("GetMetadata",null).then(function(t){return{info:t[0],metadata:t[1]?new m.Metadata(t[1]):null,contentDispositionFilename:e._fullReader?e._fullReader.filename:null}})}},{key:"getStats",value:function(){return this.messageHandler.sendWithPromise("GetStats",null)}},{key:"startCleanup",value:function(){var e=this;this.messageHandler.sendWithPromise("Cleanup",null).then(function(){for(var t=0,r=e.pageCache.length;t<r;t++){var n=e.pageCache[t];n&&n.cleanup()}e.commonObjs.clear(),e.fontLoader.clear()})}},{key:"loadingParams",get:function(){var e=this._params;return(0,s.shadow)(this,"loadingParams",{disableAutoFetch:e.disableAutoFetch,disableCreateObjectURL:e.disableCreateObjectURL,disableFontFace:e.disableFontFace,nativeImageDecoderSupport:e.nativeImageDecoderSupport})}}]),e}(),j=function(){function e(){this.objs=Object.create(null)}return e.prototype={ensureObj:function(e){if(this.objs[e])return this.objs[e];var t={capability:(0,s.createPromiseCapability)(),data:null,resolved:!1};return this.objs[e]=t,t},get:function(e,t){if(t)return this.ensureObj(e).capability.promise.then(t),null;var r=this.objs[e];if(!r||!r.resolved)throw new Error("Requesting object that isn't resolved yet "+e);return r.data},resolve:function(e,t){var r=this.ensureObj(e);r.resolved=!0,r.data=t,r.capability.resolve(t)},isResolved:function(e){var t=this.objs;return!!t[e]&&t[e].resolved},hasData:function(e){return this.isResolved(e)},getData:function(e){var t=this.objs;return t[e]&&t[e].resolved?t[e].data:null},clear:function(){this.objs=Object.create(null)}},e}(),M=function(){function e(e){this._internalRenderTask=e,this.onContinue=null}return e.prototype={get promise(){return this._internalRenderTask.capability.promise},cancel:function(){this._internalRenderTask.cancel()},then:function(e,t){return this.promise.then.apply(this.promise,arguments)}},e}(),D=function(){var e=new WeakMap;function t(e,t,r,n,i,a,o,u){var l=arguments.length>8&&void 0!==arguments[8]&&arguments[8];this.callback=e,this.params=t,this.objs=r,this.commonObjs=n,this.operatorListIdx=null,this.operatorList=i,this.pageNumber=a,this.canvasFactory=o,this.webGLContext=u,this._pdfBug=l,this.running=!1,this.graphicsReadyCallback=null,this.graphicsReady=!1,this.useRequestAnimationFrame=!1,this.cancelled=!1,this.capability=(0,s.createPromiseCapability)(),this.task=new M(this),this._continueBound=this._continue.bind(this),this._scheduleNextBound=this._scheduleNext.bind(this),this._nextBound=this._next.bind(this),this._canvas=t.canvasContext.canvas}return t.prototype={initializeGraphics:function(t){if(!this.cancelled){if(this._canvas){if(e.has(this._canvas))throw new Error("Cannot use the same canvas during multiple render() operations. Use different canvas or ensure previous operations were cancelled or completed.");e.set(this._canvas,this)}this._pdfBug&&f.default.StepperManager&&f.default.StepperManager.enabled&&(this.stepper=f.default.StepperManager.create(this.pageNumber-1),this.stepper.init(this.operatorList),this.stepper.nextBreakPoint=this.stepper.getNextBreakPoint());var r=this.params;this.gfx=new h.CanvasGraphics(r.canvasContext,this.commonObjs,this.objs,this.canvasFactory,this.webGLContext,r.imageLayer),this.gfx.beginDrawing({transform:r.transform,viewport:r.viewport,transparency:t,background:r.background}),this.operatorListIdx=0,this.graphicsReady=!0,this.graphicsReadyCallback&&this.graphicsReadyCallback()}},cancel:function(){this.running=!1,this.cancelled=!0,this._canvas&&e.delete(this._canvas),this.callback(new u.RenderingCancelledException("Rendering cancelled, page "+this.pageNumber,"canvas"))},operatorListChanged:function(){this.graphicsReady?(this.stepper&&this.stepper.updateOperatorList(this.operatorList),this.running||this._continue()):this.graphicsReadyCallback||(this.graphicsReadyCallback=this._continueBound)},_continue:function(){this.running=!0,this.cancelled||(this.task.onContinue?this.task.onContinue(this._scheduleNextBound):this._scheduleNext())},_scheduleNext:function(){var e=this;this.useRequestAnimationFrame&&"undefined"!=typeof window?window.requestAnimationFrame(function(){e._nextBound().catch(e.callback)}):Promise.resolve().then(this._nextBound).catch(this.callback)},_next:function(){var t=this;return new Promise(function(){t.cancelled||(t.operatorListIdx=t.gfx.executeOperatorList(t.operatorList,t.operatorListIdx,t._continueBound,t.stepper),t.operatorListIdx===t.operatorList.argsArray.length&&(t.running=!1,t.operatorList.lastChunk&&(t.gfx.endDrawing(),t._canvas&&e.delete(t._canvas),t.callback())))})}},t}();t.version="2.0.943",t.build="dc98bf76",t.getDocument=function(e){var t,r=new R;if("string"==typeof e)t={url:e};else if((0,s.isArrayBuffer)(e))t={data:e};else if(e instanceof E)t={range:e};else{if("object"!==(void 0===e?"undefined":o(e)))throw new Error("Invalid parameter in getDocument, need either Uint8Array, string or a parameter object");if(!e.url&&!e.data&&!e.range)throw new Error("Invalid parameter object: need either .data, .range or .url");t=e}var n=Object.create(null),i=null,a=null;for(var l in t)if("url"!==l||"undefined"==typeof window)if("range"!==l)if("worker"!==l)if("data"!==l||t[l]instanceof Uint8Array)n[l]=t[l];else{var h=t[l];if("string"==typeof h)n[l]=(0,s.stringToBytes)(h);else if("object"!==(void 0===h?"undefined":o(h))||null===h||isNaN(h.length)){if(!(0,s.isArrayBuffer)(h))throw new Error("Invalid PDF binary data: either typed array, string or array-like object is expected in the data property.");n[l]=new Uint8Array(h)}else n[l]=new Uint8Array(h)}else a=t[l];else i=t[l];else n[l]=new s.URL(t[l],window.location).href;n.rangeChunkSize=n.rangeChunkSize||_,n.CMapReaderFactory=n.CMapReaderFactory||u.DOMCMapReaderFactory,n.ignoreErrors=!0!==n.stopAtErrors,n.pdfBug=!0===n.pdfBug;var d=Object.values(s.NativeImageDecoding);if(void 0!==n.nativeImageDecoderSupport&&d.includes(n.nativeImageDecoderSupport)||(n.nativeImageDecoderSupport=c.apiCompatibilityParams.nativeImageDecoderSupport||s.NativeImageDecoding.DECODE),Number.isInteger(n.maxImageSize)||(n.maxImageSize=-1),"boolean"!=typeof n.isEvalSupported&&(n.isEvalSupported=!0),"boolean"!=typeof n.disableFontFace&&(n.disableFontFace=c.apiCompatibilityParams.disableFontFace||!1),"boolean"!=typeof n.disableRange&&(n.disableRange=!1),"boolean"!=typeof n.disableStream&&(n.disableStream=!1),"boolean"!=typeof n.disableAutoFetch&&(n.disableAutoFetch=!1),"boolean"!=typeof n.disableCreateObjectURL&&(n.disableCreateObjectURL=c.apiCompatibilityParams.disableCreateObjectURL||!1),(0,s.setVerbosityLevel)(n.verbosity),!a){var f={postMessageTransfers:n.postMessageTransfers,verbosity:n.verbosity},m=p.GlobalWorkerOptions.workerPort;m?(f.port=m,a=F.fromPort(f)):a=new F(f),r._worker=a}var y=r.docId;return a.promise.then(function(){if(r.destroyed)throw new Error("Loading aborted");return function(e,t,r,n){return e.destroyed?Promise.reject(new Error("Worker was destroyed")):(r&&(t.length=r.length,t.initialData=r.initialData),e.messageHandler.sendWithPromise("GetDocRequest",{docId:n,apiVersion:"2.0.943",source:{data:t.data,url:t.url,password:t.password,disableAutoFetch:t.disableAutoFetch,rangeChunkSize:t.rangeChunkSize,length:t.length},maxImageSize:t.maxImageSize,disableFontFace:t.disableFontFace,disableCreateObjectURL:t.disableCreateObjectURL,postMessageTransfers:e.postMessageTransfers,docBaseUrl:t.docBaseUrl,nativeImageDecoderSupport:t.nativeImageDecoderSupport,ignoreErrors:t.ignoreErrors,isEvalSupported:t.isEvalSupported}).then(function(t){if(e.destroyed)throw new Error("Worker was destroyed");return t}))}(a,n,i,y).then(function(e){if(r.destroyed)throw new Error("Loading aborted");var t=void 0;i?t=new g.PDFDataTransportStream({length:n.length,initialData:n.initialData,disableRange:n.disableRange,disableStream:n.disableStream},i):n.data||(t=P({url:n.url,length:n.length,httpHeaders:n.httpHeaders,withCredentials:n.withCredentials,rangeChunkSize:n.rangeChunkSize,disableRange:n.disableRange,disableStream:n.disableStream}));var o=new v.MessageHandler(y,e,a.port);o.postMessageTransfers=a.postMessageTransfers;var s=new L(o,r,t,n);r._transport=s,o.send("Ready",null)})}).catch(r._capability.reject),r},t.LoopbackPort=I,t.PDFDataRangeTransport=E,t.PDFWorker=F,t.PDFDocumentProxy=T,t.PDFPageProxy=O,t.setPDFNetworkStreamFactory=function(e){P=e},t.version="2.0.943",t.build="dc98bf76"},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.loadScript=t.DummyStatTimer=t.StatTimer=t.DOMSVGFactory=t.DOMCMapReaderFactory=t.DOMCanvasFactory=t.DEFAULT_LINK_REL=t.LinkTarget=t.getFilenameFromUrl=t.addLinkAttributes=t.RenderingCancelledException=t.PageViewport=void 0;var n=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),i=r(1);function a(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var o="noopener noreferrer nofollow",s="http://www.w3.org/2000/svg",u=function(){function e(){a(this,e)}return n(e,[{key:"create",value:function(e,t){if(e<=0||t<=0)throw new Error("invalid canvas size");var r=document.createElement("canvas"),n=r.getContext("2d");return r.width=e,r.height=t,{canvas:r,context:n}}},{key:"reset",value:function(e,t,r){if(!e.canvas)throw new Error("canvas is not specified");if(t<=0||r<=0)throw new Error("invalid canvas size");e.canvas.width=t,e.canvas.height=r}},{key:"destroy",value:function(e){if(!e.canvas)throw new Error("canvas is not specified");e.canvas.width=0,e.canvas.height=0,e.canvas=null,e.context=null}}]),e}(),l=function(){function e(t){var r=t.baseUrl,n=void 0===r?null:r,i=t.isCompressed,o=void 0!==i&&i;a(this,e),this.baseUrl=n,this.isCompressed=o}return n(e,[{key:"fetch",value:function(e){var t=this,r=e.name;return this.baseUrl?r?new Promise(function(e,n){var a=t.baseUrl+r+(t.isCompressed?".bcmap":""),o=new XMLHttpRequest;o.open("GET",a,!0),t.isCompressed&&(o.responseType="arraybuffer"),o.onreadystatechange=function(){if(o.readyState===XMLHttpRequest.DONE){if(200===o.status||0===o.status){var r=void 0;if(t.isCompressed&&o.response?r=new Uint8Array(o.response):!t.isCompressed&&o.responseText&&(r=(0,i.stringToBytes)(o.responseText)),r)return void e({cMapData:r,compressionType:t.isCompressed?i.CMapCompressionType.BINARY:i.CMapCompressionType.NONE})}n(new Error("Unable to load "+(t.isCompressed?"binary ":"")+"CMap at: "+a))}},o.send(null)}):Promise.reject(new Error("CMap name must be specified.")):Promise.reject(new Error('The CMap "baseUrl" parameter must be specified, ensure that the "cMapUrl" and "cMapPacked" API parameters are provided.'))}}]),e}(),c=function(){function e(){a(this,e)}return n(e,[{key:"create",value:function(e,t){(0,i.assert)(e>0&&t>0,"Invalid SVG dimensions");var r=document.createElementNS(s,"svg:svg");return r.setAttribute("version","1.1"),r.setAttribute("width",e+"px"),r.setAttribute("height",t+"px"),r.setAttribute("preserveAspectRatio","none"),r.setAttribute("viewBox","0 0 "+e+" "+t),r}},{key:"createElement",value:function(e){return(0,i.assert)("string"==typeof e,"Invalid SVG element type"),document.createElementNS(s,e)}}]),e}(),h=function(){function e(t){var r=t.viewBox,n=t.scale,i=t.rotation,o=t.offsetX,s=void 0===o?0:o,u=t.offsetY,l=void 0===u?0:u,c=t.dontFlip,h=void 0!==c&&c;a(this,e),this.viewBox=r,this.scale=n,this.rotation=i,this.offsetX=s,this.offsetY=l;var d=(r[2]+r[0])/2,f=(r[3]+r[1])/2,p=void 0,v=void 0,m=void 0,g=void 0;switch(i=(i%=360)<0?i+360:i){case 180:p=-1,v=0,m=0,g=1;break;case 90:p=0,v=1,m=1,g=0;break;case 270:p=0,v=-1,m=-1,g=0;break;default:p=1,v=0,m=0,g=-1}h&&(m=-m,g=-g);var y=void 0,b=void 0,_=void 0,A=void 0;0===p?(y=Math.abs(f-r[1])*n+s,b=Math.abs(d-r[0])*n+l,_=Math.abs(r[3]-r[1])*n,A=Math.abs(r[2]-r[0])*n):(y=Math.abs(d-r[0])*n+s,b=Math.abs(f-r[1])*n+l,_=Math.abs(r[2]-r[0])*n,A=Math.abs(r[3]-r[1])*n),this.transform=[p*n,v*n,m*n,g*n,y-p*n*d-m*n*f,b-v*n*d-g*n*f],this.width=_,this.height=A}return n(e,[{key:"clone",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=t.scale,n=void 0===r?this.scale:r,i=t.rotation,a=void 0===i?this.rotation:i,o=t.dontFlip,s=void 0!==o&&o;return new e({viewBox:this.viewBox.slice(),scale:n,rotation:a,offsetX:this.offsetX,offsetY:this.offsetY,dontFlip:s})}},{key:"convertToViewportPoint",value:function(e,t){return i.Util.applyTransform([e,t],this.transform)}},{key:"convertToViewportRectangle",value:function(e){var t=i.Util.applyTransform([e[0],e[1]],this.transform),r=i.Util.applyTransform([e[2],e[3]],this.transform);return[t[0],t[1],r[0],r[1]]}},{key:"convertToPdfPoint",value:function(e,t){return i.Util.applyInverseTransform([e,t],this.transform)}}]),e}(),d=function(){function e(e,t){this.message=e,this.type=t}return e.prototype=new Error,e.prototype.name="RenderingCancelledException",e.constructor=e,e}(),f={NONE:0,SELF:1,BLANK:2,PARENT:3,TOP:4},p=["","_self","_blank","_parent","_top"];var v=function(){function e(){var t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];a(this,e),this.enabled=!!t,this.started=Object.create(null),this.times=[]}return n(e,[{key:"time",value:function(e){this.enabled&&(e in this.started&&(0,i.warn)("Timer is already running for "+e),this.started[e]=Date.now())}},{key:"timeEnd",value:function(e){this.enabled&&(e in this.started||(0,i.warn)("Timer has not been started for "+e),this.times.push({name:e,start:this.started[e],end:Date.now()}),delete this.started[e])}},{key:"toString",value:function(){for(var e=this.times,t="",r=0,n=0,i=e.length;n<i;++n){var a=e[n].name;a.length>r&&(r=a.length)}for(var o=0,s=e.length;o<s;++o){var u=e[o],l=u.end-u.start;t+=u.name.padEnd(r)+" "+l+"ms\n"}return t}}]),e}(),m=function(){function e(){a(this,e),(0,i.unreachable)("Cannot initialize DummyStatTimer.")}return n(e,null,[{key:"time",value:function(e){}},{key:"timeEnd",value:function(e){}},{key:"toString",value:function(){return""}}]),e}();t.PageViewport=h,t.RenderingCancelledException=d,t.addLinkAttributes=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=t.url,n=t.target,a=t.rel;if(e.href=e.title=r?(0,i.removeNullCharacters)(r):"",r){var s=Object.values(f).includes(n)?n:f.NONE;e.target=p[s],e.rel="string"==typeof a?a:o}},t.getFilenameFromUrl=function(e){var t=e.indexOf("#"),r=e.indexOf("?"),n=Math.min(t>0?t:e.length,r>0?r:e.length);return e.substring(e.lastIndexOf("/",n)+1,n)},t.LinkTarget=f,t.DEFAULT_LINK_REL=o,t.DOMCanvasFactory=u,t.DOMCMapReaderFactory=l,t.DOMSVGFactory=c,t.StatTimer=v,t.DummyStatTimer=m,t.loadScript=function(e){return new Promise(function(t,r){var n=document.createElement("script");n.src=e,n.onload=t,n.onerror=function(){r(new Error("Cannot load script at: "+n.src))},(document.head||document.documentElement).appendChild(n)})}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.FontLoader=t.FontFaceObject=void 0;var n=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),i=r(1);function a(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var o,s=function(){function e(t){a(this,e),this.constructor===e&&(0,i.unreachable)("Cannot initialize BaseFontLoader."),this.docId=t,this.nativeFontFaces=[],this.styleElement=null,this.loadingContext={requests:[],nextRequestId:0}}return n(e,[{key:"addNativeFontFace",value:function(e){this.nativeFontFaces.push(e),document.fonts.add(e)}},{key:"insertRule",value:function(e){var t=this.styleElement;t||((t=this.styleElement=document.createElement("style")).id="PDFJS_FONT_STYLE_TAG_"+this.docId,document.documentElement.getElementsByTagName("head")[0].appendChild(t));var r=t.sheet;r.insertRule(e,r.cssRules.length)}},{key:"clear",value:function(){this.nativeFontFaces.forEach(function(e){document.fonts.delete(e)}),this.nativeFontFaces.length=0,this.styleElement&&(this.styleElement.remove(),this.styleElement=null)}},{key:"bind",value:function(e,t){var r=[],n=[],a=[],o=function(e){return e.loaded.catch(function(t){(0,i.warn)('Failed to load font "'+e.family+'": '+t)})},s=!0,u=!1,l=void 0;try{for(var c,h=e[Symbol.iterator]();!(s=(c=h.next()).done);s=!0){var d=c.value;if(!d.attached&&!d.missingFile)if(d.attached=!0,this.isFontLoadingAPISupported){var f=d.createNativeFontFace();f&&(this.addNativeFontFace(f),a.push(o(f)))}else{var p=d.createFontFaceRule();p&&(this.insertRule(p),r.push(p),n.push(d))}}}catch(e){u=!0,l=e}finally{try{!s&&h.return&&h.return()}finally{if(u)throw l}}var v=this._queueLoadingCallback(t);this.isFontLoadingAPISupported?Promise.all(a).then(v.complete):r.length>0&&!this.isSyncFontLoadingSupported?this._prepareFontLoadEvent(r,n,v):v.complete()}},{key:"_queueLoadingCallback",value:function(e){var t=this.loadingContext,r={id:"pdfjs-font-loading-"+t.nextRequestId++,done:!1,complete:function(){for((0,i.assert)(!r.done,"completeRequest() cannot be called twice."),r.done=!0;t.requests.length>0&&t.requests[0].done;){var e=t.requests.shift();setTimeout(e.callback,0)}},callback:e};return t.requests.push(r),r}},{key:"_prepareFontLoadEvent",value:function(e,t,r){(0,i.unreachable)("Abstract method `_prepareFontLoadEvent`.")}},{key:"isFontLoadingAPISupported",get:function(){(0,i.unreachable)("Abstract method `isFontLoadingAPISupported`.")}},{key:"isSyncFontLoadingSupported",get:function(){(0,i.unreachable)("Abstract method `isSyncFontLoadingSupported`.")}},{key:"_loadTestFont",get:function(){(0,i.unreachable)("Abstract method `_loadTestFont`.")}}]),e}();t.FontLoader=o=function(e){function t(e){a(this,t);var r=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return r.loadTestFontId=0,r}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,s),n(t,[{key:"_prepareFontLoadEvent",value:function(e,t,r){function n(e,t){return e.charCodeAt(t)<<24|e.charCodeAt(t+1)<<16|e.charCodeAt(t+2)<<8|255&e.charCodeAt(t+3)}function a(e,t,r,n){return e.substring(0,t)+n+e.substring(t+r)}var o=void 0,s=void 0,u=document.createElement("canvas");u.width=1,u.height=1;var l=u.getContext("2d"),c=0;var h="lt"+Date.now()+this.loadTestFontId++,d=this._loadTestFont,f=n(d=a(d,976,h.length,h),16);for(o=0,s=h.length-3;o<s;o+=4)f=f-1482184792+n(h,o)|0;o<h.length&&(f=f-1482184792+n(h+"XXX",o)|0),d=a(d,16,4,(0,i.string32)(f));var p='@font-face {font-family:"'+h+'";src:'+("url(data:font/opentype;base64,"+btoa(d)+");")+"}";this.insertRule(p);var v=[];for(o=0,s=t.length;o<s;o++)v.push(t[o].loadedName);v.push(h);var m=document.createElement("div");for(m.setAttribute("style","visibility: hidden;width: 10px; height: 10px;position: absolute; top: 0px; left: 0px;"),o=0,s=v.length;o<s;++o){var g=document.createElement("span");g.textContent="Hi",g.style.fontFamily=v[o],m.appendChild(g)}document.body.appendChild(m),function e(t,r){if(++c>30)return(0,i.warn)("Load test font never loaded."),void r();l.font="30px "+t,l.fillText(".",0,20),l.getImageData(0,0,1,1).data[3]>0?r():setTimeout(e.bind(null,t,r))}(h,function(){document.body.removeChild(m),r.complete()})}},{key:"isFontLoadingAPISupported",get:function(){var e="undefined"!=typeof document&&!!document.fonts;if(e&&"undefined"!=typeof navigator){var t=/Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(navigator.userAgent);t&&t[1]<63&&(e=!1)}return(0,i.shadow)(this,"isFontLoadingAPISupported",e)}},{key:"isSyncFontLoadingSupported",get:function(){var e=!1;if("undefined"==typeof navigator)e=!0;else{var t=/Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(navigator.userAgent);t&&t[1]>=14&&(e=!0)}return(0,i.shadow)(this,"isSyncFontLoadingSupported",e)}},{key:"_loadTestFont",get:function(){return(0,i.shadow)(this,"_loadTestFont",atob("T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQAFQAABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAAALwAAAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgAAAAGbmFtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1AAsD6AAAAADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD6AAAAAAD6AABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACMAooCvAAAAeAAMQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4DIP84AFoDIQAAAAAAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAAAAEAAQAAAAEAAAAAAAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUAAQAAAAEAAAAAAAYAAQAAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgABAAMAAQQJAAMAAgABAAMAAQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABYAAAAAAAAAwAAAAMAAAAcAAEAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAAAC7////TAAEAAAAAAAABBgAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAAAAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgcA/gXBIwMAYuL+nz5tQXkD5j3CBLnEQACAQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYAAABAQAADwACAQEEE/t3Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQAAAAAAAABAAAAAMmJbzEAAAAAzgTjFQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAgABAAAAAAAAAAAD6AAAAAAAAA=="))}}]),t}();var u={get value(){return(0,i.shadow)(this,"value",(0,i.isEvalSupported)())}},l=function(){function e(t,r){var n=r.isEvalSupported,i=void 0===n||n,o=r.disableFontFace,s=void 0!==o&&o,u=r.ignoreErrors,l=void 0!==u&&u,c=r.onUnsupportedFeature,h=void 0===c?null:c,d=r.fontRegistry,f=void 0===d?null:d;for(var p in a(this,e),this.compiledGlyphs=Object.create(null),t)this[p]=t[p];this.isEvalSupported=!1!==i,this.disableFontFace=!0===s,this.ignoreErrors=!0===l,this._onUnsupportedFeature=h,this.fontRegistry=f}return n(e,[{key:"createNativeFontFace",value:function(){if(!this.data||this.disableFontFace)return null;var e=new FontFace(this.loadedName,this.data,{});return this.fontRegistry&&this.fontRegistry.registerFont(this),e}},{key:"createFontFaceRule",value:function(){if(!this.data||this.disableFontFace)return null;var e=(0,i.bytesToString)(new Uint8Array(this.data)),t="url(data:"+this.mimetype+";base64,"+btoa(e)+");",r='@font-face {font-family:"'+this.loadedName+'";src:'+t+"}";return this.fontRegistry&&this.fontRegistry.registerFont(this,t),r}},{key:"getPathGenerator",value:function(e,t){if(void 0!==this.compiledGlyphs[t])return this.compiledGlyphs[t];var r=void 0,n=void 0;try{r=e.get(this.loadedName+"_path_"+t)}catch(e){if(!this.ignoreErrors)throw e;return this._onUnsupportedFeature&&this._onUnsupportedFeature({featureId:i.UNSUPPORTED_FEATURES.font}),(0,i.warn)('getPathGenerator - ignoring character: "'+e+'".'),this.compiledGlyphs[t]=function(e,t){}}if(this.isEvalSupported&&u.value){for(var a=void 0,o="",s=0,l=r.length;s<l;s++)a=void 0!==(n=r[s]).args?n.args.join(","):"",o+="c."+n.cmd+"("+a+");\n";return this.compiledGlyphs[t]=new Function("c","size",o)}return this.compiledGlyphs[t]=function(e,t){for(var i=0,a=r.length;i<a;i++)"scale"===(n=r[i]).cmd&&(n.args=[t,-t]),e[n.cmd].apply(e,n.args)}}}]),e}();t.FontFaceObject=l,t.FontLoader=o},function(e,t,r){"use strict";var n=Object.create(null),i=r(4),a="undefined"!=typeof navigator&&navigator.userAgent||"",o=/Trident/.test(a),s=/CriOS/.test(a);(o||s)&&(n.disableCreateObjectURL=!0),i()&&(n.disableFontFace=!0,n.nativeImageDecoderSupport="none"),t.apiCompatibilityParams=Object.freeze(n)},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.CanvasGraphics=void 0;var n=r(1),i=r(134),a=16,o={get value(){return(0,n.shadow)(o,"value",(0,n.isLittleEndian)())}};function s(e){e.mozCurrentTransform||(e._originalSave=e.save,e._originalRestore=e.restore,e._originalRotate=e.rotate,e._originalScale=e.scale,e._originalTranslate=e.translate,e._originalTransform=e.transform,e._originalSetTransform=e.setTransform,e._transformMatrix=e._transformMatrix||[1,0,0,1,0,0],e._transformStack=[],Object.defineProperty(e,"mozCurrentTransform",{get:function(){return this._transformMatrix}}),Object.defineProperty(e,"mozCurrentTransformInverse",{get:function(){var e=this._transformMatrix,t=e[0],r=e[1],n=e[2],i=e[3],a=e[4],o=e[5],s=t*i-r*n,u=r*n-t*i;return[i/s,r/u,n/u,t/s,(i*a-n*o)/u,(r*a-t*o)/s]}}),e.save=function(){var e=this._transformMatrix;this._transformStack.push(e),this._transformMatrix=e.slice(0,6),this._originalSave()},e.restore=function(){var e=this._transformStack.pop();e&&(this._transformMatrix=e,this._originalRestore())},e.translate=function(e,t){var r=this._transformMatrix;r[4]=r[0]*e+r[2]*t+r[4],r[5]=r[1]*e+r[3]*t+r[5],this._originalTranslate(e,t)},e.scale=function(e,t){var r=this._transformMatrix;r[0]=r[0]*e,r[1]=r[1]*e,r[2]=r[2]*t,r[3]=r[3]*t,this._originalScale(e,t)},e.transform=function(t,r,n,i,a,o){var s=this._transformMatrix;this._transformMatrix=[s[0]*t+s[2]*r,s[1]*t+s[3]*r,s[0]*n+s[2]*i,s[1]*n+s[3]*i,s[0]*a+s[2]*o+s[4],s[1]*a+s[3]*o+s[5]],e._originalTransform(t,r,n,i,a,o)},e.setTransform=function(t,r,n,i,a,o){this._transformMatrix=[t,r,n,i,a,o],e._originalSetTransform(t,r,n,i,a,o)},e.rotate=function(e){var t=Math.cos(e),r=Math.sin(e),n=this._transformMatrix;this._transformMatrix=[n[0]*t+n[2]*r,n[1]*t+n[3]*r,n[0]*-r+n[2]*t,n[1]*-r+n[3]*t,n[4],n[5]],this._originalRotate(e)})}var u=function(){function e(e){this.canvasFactory=e,this.cache=Object.create(null)}return e.prototype={getCanvas:function(e,t,r,n){var i;return void 0!==this.cache[e]?(i=this.cache[e],this.canvasFactory.reset(i,t,r),i.context.setTransform(1,0,0,1,0,0)):(i=this.canvasFactory.create(t,r),this.cache[e]=i),n&&s(i.context),i},clear:function(){for(var e in this.cache){var t=this.cache[e];this.canvasFactory.destroy(t),delete this.cache[e]}}},e}();var l=function(){function e(){this.alphaIsShape=!1,this.fontSize=0,this.fontSizeScale=1,this.textMatrix=n.IDENTITY_MATRIX,this.textMatrixScale=1,this.fontMatrix=n.FONT_IDENTITY_MATRIX,this.leading=0,this.x=0,this.y=0,this.lineX=0,this.lineY=0,this.charSpacing=0,this.wordSpacing=0,this.textHScale=1,this.textRenderingMode=n.TextRenderingMode.FILL,this.textRise=0,this.fillColor="#000000",this.strokeColor="#000000",this.patternFill=!1,this.fillAlpha=1,this.strokeAlpha=1,this.lineWidth=1,this.activeSMask=null,this.resumeSMaskCtx=null}return e.prototype={clone:function(){return Object.create(this)},setCurrentPoint:function(e,t){this.x=e,this.y=t}},e}(),c=function(){function e(e,t,r,n,i,a){this.ctx=e,this.current=new l,this.stateStack=[],this.pendingClip=null,this.pendingEOFill=!1,this.res=null,this.xobjs=null,this.commonObjs=t,this.objs=r,this.canvasFactory=n,this.webGLContext=i,this.imageLayer=a,this.groupStack=[],this.processingType3=null,this.baseTransform=null,this.baseTransformStack=[],this.groupLevel=0,this.smaskStack=[],this.smaskCounter=0,this.tempSMask=null,this.cachedCanvases=new u(this.canvasFactory),e&&s(e),this._cachedGetSinglePixelWidth=null}function t(e,t){if("undefined"!=typeof ImageData&&t instanceof ImageData)e.putImageData(t,0,0);else{var r,i,s,u,l,c=t.height,h=t.width,d=c%a,f=(c-d)/a,p=0===d?f:f+1,v=e.createImageData(h,a),m=0,g=t.data,y=v.data;if(t.kind===n.ImageKind.GRAYSCALE_1BPP){var b=g.byteLength,_=new Uint32Array(y.buffer,0,y.byteLength>>2),A=_.length,S=h+7>>3,w=4294967295,k=o.value?4278190080:255;for(i=0;i<p;i++){for(u=i<f?a:d,r=0,s=0;s<u;s++){for(var P=b-m,x=0,C=P>S?h:8*P-7,R=-8&C,E=0,T=0;x<R;x+=8)T=g[m++],_[r++]=128&T?w:k,_[r++]=64&T?w:k,_[r++]=32&T?w:k,_[r++]=16&T?w:k,_[r++]=8&T?w:k,_[r++]=4&T?w:k,_[r++]=2&T?w:k,_[r++]=1&T?w:k;for(;x<C;x++)0===E&&(T=g[m++],E=128),_[r++]=T&E?w:k,E>>=1}for(;r<A;)_[r++]=0;e.putImageData(v,0,i*a)}}else if(t.kind===n.ImageKind.RGBA_32BPP){for(s=0,l=h*a*4,i=0;i<f;i++)y.set(g.subarray(m,m+l)),m+=l,e.putImageData(v,0,s),s+=a;i<p&&(l=h*d*4,y.set(g.subarray(m,m+l)),e.putImageData(v,0,s))}else{if(t.kind!==n.ImageKind.RGB_24BPP)throw new Error("bad image kind: "+t.kind);for(l=h*(u=a),i=0;i<p;i++){for(i>=f&&(l=h*(u=d)),r=0,s=l;s--;)y[r++]=g[m++],y[r++]=g[m++],y[r++]=g[m++],y[r++]=255;e.putImageData(v,0,i*a)}}}}function r(e,t){for(var r=t.height,n=t.width,i=r%a,o=(r-i)/a,s=0===i?o:o+1,u=e.createImageData(n,a),l=0,c=t.data,h=u.data,d=0;d<s;d++){for(var f=d<o?a:i,p=3,v=0;v<f;v++)for(var m=0,g=0;g<n;g++){if(!m){var y=c[l++];m=128}h[p]=y&m?0:255,p+=4,m>>=1}e.putImageData(u,0,d*a)}}function c(e,t){for(var r=["strokeStyle","fillStyle","fillRule","globalAlpha","lineWidth","lineCap","lineJoin","miterLimit","globalCompositeOperation","font"],n=0,i=r.length;n<i;n++){var a=r[n];void 0!==e[a]&&(t[a]=e[a])}void 0!==e.setLineDash&&(t.setLineDash(e.getLineDash()),t.lineDashOffset=e.lineDashOffset)}function h(e){e.strokeStyle="#000000",e.fillStyle="#000000",e.fillRule="nonzero",e.globalAlpha=1,e.lineWidth=1,e.lineCap="butt",e.lineJoin="miter",e.miterLimit=10,e.globalCompositeOperation="source-over",e.font="10px sans-serif",void 0!==e.setLineDash&&(e.setLineDash([]),e.lineDashOffset=0)}function d(e,t,r,n){for(var i=e.length,a=3;a<i;a+=4){var o=e[a];if(0===o)e[a-3]=t,e[a-2]=r,e[a-1]=n;else if(o<255){var s=255-o;e[a-3]=e[a-3]*o+t*s>>8,e[a-2]=e[a-2]*o+r*s>>8,e[a-1]=e[a-1]*o+n*s>>8}}}function f(e,t,r){for(var n=e.length,i=3;i<n;i+=4){var a=r?r[e[i]]:e[i];t[i]=t[i]*a*(1/255)|0}}function p(e,t,r){for(var n=e.length,i=3;i<n;i+=4){var a=77*e[i-3]+152*e[i-2]+28*e[i-1];t[i]=r?t[i]*r[a>>8]>>8:t[i]*a>>16}}function v(e,t,r,n){var i=t.canvas,a=t.context;e.setTransform(t.scaleX,0,0,t.scaleY,t.offsetX,t.offsetY);var o=t.backdrop||null;if(!t.transferMap&&n.isEnabled){var s=n.composeSMask({layer:r.canvas,mask:i,properties:{subtype:t.subtype,backdrop:o}});return e.setTransform(1,0,0,1,0,0),void e.drawImage(s,t.offsetX,t.offsetY)}!function(e,t,r,n,i,a,o){var s,u=!!a,l=u?a[0]:0,c=u?a[1]:0,h=u?a[2]:0;s="Luminosity"===i?p:f;for(var v=Math.min(n,Math.ceil(1048576/r)),m=0;m<n;m+=v){var g=Math.min(v,n-m),y=e.getImageData(0,m,r,g),b=t.getImageData(0,m,r,g);u&&d(y.data,l,c,h),s(y.data,b.data,o),e.putImageData(b,0,m)}}(a,r,i.width,i.height,t.subtype,o,t.transferMap),e.drawImage(i,0,0)}var m=["butt","round","square"],g=["miter","round","bevel"],y={},b={};for(var _ in e.prototype={beginDrawing:function(e){var t=e.transform,r=e.viewport,n=e.transparency,i=e.background,a=void 0===i?null:i,o=this.ctx.canvas.width,s=this.ctx.canvas.height;if(this.ctx.save(),this.ctx.fillStyle=a||"rgb(255, 255, 255)",this.ctx.fillRect(0,0,o,s),this.ctx.restore(),n){var u=this.cachedCanvases.getCanvas("transparent",o,s,!0);this.compositeCtx=this.ctx,this.transparentCanvas=u.canvas,this.ctx=u.context,this.ctx.save(),this.ctx.transform.apply(this.ctx,this.compositeCtx.mozCurrentTransform)}this.ctx.save(),h(this.ctx),t&&this.ctx.transform.apply(this.ctx,t),this.ctx.transform.apply(this.ctx,r.transform),this.baseTransform=this.ctx.mozCurrentTransform.slice(),this.imageLayer&&this.imageLayer.beginLayout()},executeOperatorList:function(e,t,r,i){var a=e.argsArray,o=e.fnArray,s=t||0,u=a.length;if(u===s)return s;for(var l,c=u-s>10&&"function"==typeof r,h=c?Date.now()+15:0,d=0,f=this.commonObjs,p=this.objs;;){if(void 0!==i&&s===i.nextBreakPoint)return i.breakIt(s,r),s;if((l=o[s])!==n.OPS.dependency)this[l].apply(this,a[s]);else for(var v=a[s],m=0,g=v.length;m<g;m++){var y=v[m],b="g"===y[0]&&"_"===y[1]?f:p;if(!b.isResolved(y))return b.get(y,r),s}if(++s===u)return s;if(c&&++d>10){if(Date.now()>h)return r(),s;d=0}}},endDrawing:function(){null!==this.current.activeSMask&&this.endSMaskGroup(),this.ctx.restore(),this.transparentCanvas&&(this.ctx=this.compositeCtx,this.ctx.save(),this.ctx.setTransform(1,0,0,1,0,0),this.ctx.drawImage(this.transparentCanvas,0,0),this.ctx.restore(),this.transparentCanvas=null),this.cachedCanvases.clear(),this.webGLContext.clear(),this.imageLayer&&this.imageLayer.endLayout()},setLineWidth:function(e){this.current.lineWidth=e,this.ctx.lineWidth=e},setLineCap:function(e){this.ctx.lineCap=m[e]},setLineJoin:function(e){this.ctx.lineJoin=g[e]},setMiterLimit:function(e){this.ctx.miterLimit=e},setDash:function(e,t){var r=this.ctx;void 0!==r.setLineDash&&(r.setLineDash(e),r.lineDashOffset=t)},setRenderingIntent:function(e){},setFlatness:function(e){},setGState:function(e){for(var t=0,r=e.length;t<r;t++){var n=e[t],i=n[0],a=n[1];switch(i){case"LW":this.setLineWidth(a);break;case"LC":this.setLineCap(a);break;case"LJ":this.setLineJoin(a);break;case"ML":this.setMiterLimit(a);break;case"D":this.setDash(a[0],a[1]);break;case"RI":this.setRenderingIntent(a);break;case"FL":this.setFlatness(a);break;case"Font":this.setFont(a[0],a[1]);break;case"CA":this.current.strokeAlpha=n[1];break;case"ca":this.current.fillAlpha=n[1],this.ctx.globalAlpha=n[1];break;case"BM":this.ctx.globalCompositeOperation=a;break;case"SMask":this.current.activeSMask&&(this.stateStack.length>0&&this.stateStack[this.stateStack.length-1].activeSMask===this.current.activeSMask?this.suspendSMaskGroup():this.endSMaskGroup()),this.current.activeSMask=a?this.tempSMask:null,this.current.activeSMask&&this.beginSMaskGroup(),this.tempSMask=null}}},beginSMaskGroup:function(){var e=this.current.activeSMask,t=e.canvas.width,r=e.canvas.height,n="smaskGroupAt"+this.groupLevel,i=this.cachedCanvases.getCanvas(n,t,r,!0),a=this.ctx,o=a.mozCurrentTransform;this.ctx.save();var s=i.context;s.scale(1/e.scaleX,1/e.scaleY),s.translate(-e.offsetX,-e.offsetY),s.transform.apply(s,o),e.startTransformInverse=s.mozCurrentTransformInverse,c(a,s),this.ctx=s,this.setGState([["BM","source-over"],["ca",1],["CA",1]]),this.groupStack.push(a),this.groupLevel++},suspendSMaskGroup:function(){var e=this.ctx;this.groupLevel--,this.ctx=this.groupStack.pop(),v(this.ctx,this.current.activeSMask,e,this.webGLContext),this.ctx.restore(),this.ctx.save(),c(e,this.ctx),this.current.resumeSMaskCtx=e;var t=n.Util.transform(this.current.activeSMask.startTransformInverse,e.mozCurrentTransform);this.ctx.transform.apply(this.ctx,t),e.save(),e.setTransform(1,0,0,1,0,0),e.clearRect(0,0,e.canvas.width,e.canvas.height),e.restore()},resumeSMaskGroup:function(){var e=this.current.resumeSMaskCtx,t=this.ctx;this.ctx=e,this.groupStack.push(t),this.groupLevel++},endSMaskGroup:function(){var e=this.ctx;this.groupLevel--,this.ctx=this.groupStack.pop(),v(this.ctx,this.current.activeSMask,e,this.webGLContext),this.ctx.restore(),c(e,this.ctx);var t=n.Util.transform(this.current.activeSMask.startTransformInverse,e.mozCurrentTransform);this.ctx.transform.apply(this.ctx,t)},save:function(){this.ctx.save();var e=this.current;this.stateStack.push(e),this.current=e.clone(),this.current.resumeSMaskCtx=null},restore:function(){this.current.resumeSMaskCtx&&this.resumeSMaskGroup(),null===this.current.activeSMask||0!==this.stateStack.length&&this.stateStack[this.stateStack.length-1].activeSMask===this.current.activeSMask||this.endSMaskGroup(),0!==this.stateStack.length&&(this.current=this.stateStack.pop(),this.ctx.restore(),this.pendingClip=null,this._cachedGetSinglePixelWidth=null)},transform:function(e,t,r,n,i,a){this.ctx.transform(e,t,r,n,i,a),this._cachedGetSinglePixelWidth=null},constructPath:function(e,t){for(var r=this.ctx,i=this.current,a=i.x,o=i.y,s=0,u=0,l=e.length;s<l;s++)switch(0|e[s]){case n.OPS.rectangle:a=t[u++],o=t[u++];var c=t[u++],h=t[u++];0===c&&(c=this.getSinglePixelWidth()),0===h&&(h=this.getSinglePixelWidth());var d=a+c,f=o+h;this.ctx.moveTo(a,o),this.ctx.lineTo(d,o),this.ctx.lineTo(d,f),this.ctx.lineTo(a,f),this.ctx.lineTo(a,o),this.ctx.closePath();break;case n.OPS.moveTo:a=t[u++],o=t[u++],r.moveTo(a,o);break;case n.OPS.lineTo:a=t[u++],o=t[u++],r.lineTo(a,o);break;case n.OPS.curveTo:a=t[u+4],o=t[u+5],r.bezierCurveTo(t[u],t[u+1],t[u+2],t[u+3],a,o),u+=6;break;case n.OPS.curveTo2:r.bezierCurveTo(a,o,t[u],t[u+1],t[u+2],t[u+3]),a=t[u+2],o=t[u+3],u+=4;break;case n.OPS.curveTo3:a=t[u+2],o=t[u+3],r.bezierCurveTo(t[u],t[u+1],a,o,a,o),u+=4;break;case n.OPS.closePath:r.closePath()}i.setCurrentPoint(a,o)},closePath:function(){this.ctx.closePath()},stroke:function(e){e=void 0===e||e;var t=this.ctx,r=this.current.strokeColor;t.lineWidth=Math.max(.65*this.getSinglePixelWidth(),this.current.lineWidth),t.globalAlpha=this.current.strokeAlpha,r&&r.hasOwnProperty("type")&&"Pattern"===r.type?(t.save(),t.strokeStyle=r.getPattern(t,this),t.stroke(),t.restore()):t.stroke(),e&&this.consumePath(),t.globalAlpha=this.current.fillAlpha},closeStroke:function(){this.closePath(),this.stroke()},fill:function(e){e=void 0===e||e;var t=this.ctx,r=this.current.fillColor,n=!1;this.current.patternFill&&(t.save(),this.baseTransform&&t.setTransform.apply(t,this.baseTransform),t.fillStyle=r.getPattern(t,this),n=!0),this.pendingEOFill?(t.fill("evenodd"),this.pendingEOFill=!1):t.fill(),n&&t.restore(),e&&this.consumePath()},eoFill:function(){this.pendingEOFill=!0,this.fill()},fillStroke:function(){this.fill(!1),this.stroke(!1),this.consumePath()},eoFillStroke:function(){this.pendingEOFill=!0,this.fillStroke()},closeFillStroke:function(){this.closePath(),this.fillStroke()},closeEOFillStroke:function(){this.pendingEOFill=!0,this.closePath(),this.fillStroke()},endPath:function(){this.consumePath()},clip:function(){this.pendingClip=y},eoClip:function(){this.pendingClip=b},beginText:function(){this.current.textMatrix=n.IDENTITY_MATRIX,this.current.textMatrixScale=1,this.current.x=this.current.lineX=0,this.current.y=this.current.lineY=0},endText:function(){var e=this.pendingTextPaths,t=this.ctx;if(void 0!==e){t.save(),t.beginPath();for(var r=0;r<e.length;r++){var n=e[r];t.setTransform.apply(t,n.transform),t.translate(n.x,n.y),n.addToPath(t,n.fontSize)}t.restore(),t.clip(),t.beginPath(),delete this.pendingTextPaths}else t.beginPath()},setCharSpacing:function(e){this.current.charSpacing=e},setWordSpacing:function(e){this.current.wordSpacing=e},setHScale:function(e){this.current.textHScale=e/100},setLeading:function(e){this.current.leading=-e},setFont:function(e,t){var r=this.commonObjs.get(e),i=this.current;if(!r)throw new Error("Can't find font for "+e);if(i.fontMatrix=r.fontMatrix?r.fontMatrix:n.FONT_IDENTITY_MATRIX,0!==i.fontMatrix[0]&&0!==i.fontMatrix[3]||(0,n.warn)("Invalid font matrix for font "+e),t<0?(t=-t,i.fontDirection=-1):i.fontDirection=1,this.current.font=r,this.current.fontSize=t,!r.isType3Font){var a=r.loadedName||"sans-serif",o=r.black?"900":r.bold?"bold":"normal",s=r.italic?"italic":"normal",u='"'+a+'", '+r.fallbackName,l=t<16?16:t>100?100:t;this.current.fontSizeScale=t/l;var c=s+" "+o+" "+l+"px "+u;this.ctx.font=c}},setTextRenderingMode:function(e){this.current.textRenderingMode=e},setTextRise:function(e){this.current.textRise=e},moveText:function(e,t){this.current.x=this.current.lineX+=e,this.current.y=this.current.lineY+=t},setLeadingMoveText:function(e,t){this.setLeading(-t),this.moveText(e,t)},setTextMatrix:function(e,t,r,n,i,a){this.current.textMatrix=[e,t,r,n,i,a],this.current.textMatrixScale=Math.sqrt(e*e+t*t),this.current.x=this.current.lineX=0,this.current.y=this.current.lineY=0},nextLine:function(){this.moveText(0,this.current.leading)},paintChar:function(e,t,r,i){var a,o=this.ctx,s=this.current,u=s.font,l=s.textRenderingMode,c=s.fontSize/s.fontSizeScale,h=l&n.TextRenderingMode.FILL_STROKE_MASK,d=!!(l&n.TextRenderingMode.ADD_TO_PATH_FLAG),f=s.patternFill&&u.data;((u.disableFontFace||d||f)&&(a=u.getPathGenerator(this.commonObjs,e)),u.disableFontFace||f?(o.save(),o.translate(t,r),o.beginPath(),a(o,c),i&&o.setTransform.apply(o,i),h!==n.TextRenderingMode.FILL&&h!==n.TextRenderingMode.FILL_STROKE||o.fill(),h!==n.TextRenderingMode.STROKE&&h!==n.TextRenderingMode.FILL_STROKE||o.stroke(),o.restore()):(h!==n.TextRenderingMode.FILL&&h!==n.TextRenderingMode.FILL_STROKE||o.fillText(e,t,r),h!==n.TextRenderingMode.STROKE&&h!==n.TextRenderingMode.FILL_STROKE||o.strokeText(e,t,r)),d)&&(this.pendingTextPaths||(this.pendingTextPaths=[])).push({transform:o.mozCurrentTransform,x:t,y:r,fontSize:c,addToPath:a})},get isFontSubpixelAAEnabled(){var e=this.canvasFactory.create(10,10).context;e.scale(1.5,1),e.fillText("I",0,10);for(var t=e.getImageData(0,0,10,10).data,r=!1,i=3;i<t.length;i+=4)if(t[i]>0&&t[i]<255){r=!0;break}return(0,n.shadow)(this,"isFontSubpixelAAEnabled",r)},showText:function(e){var t=this.current,r=t.font;if(r.isType3Font)return this.showType3Text(e);var i=t.fontSize;if(0!==i){var a=this.ctx,o=t.fontSizeScale,s=t.charSpacing,u=t.wordSpacing,l=t.fontDirection,c=t.textHScale*l,h=e.length,d=r.vertical,f=d?1:-1,p=r.defaultVMetrics,v=i*t.fontMatrix[0],m=t.textRenderingMode===n.TextRenderingMode.FILL&&!r.disableFontFace&&!t.patternFill;a.save();var g=void 0;if(t.patternFill){a.save();var y=t.fillColor.getPattern(a,this);g=a.mozCurrentTransform,a.restore(),a.fillStyle=y}a.transform.apply(a,t.textMatrix),a.translate(t.x,t.y+t.textRise),l>0?a.scale(c,-1):a.scale(c,1);var b=t.lineWidth,_=t.textMatrixScale;if(0===_||0===b){var A=t.textRenderingMode&n.TextRenderingMode.FILL_STROKE_MASK;A!==n.TextRenderingMode.STROKE&&A!==n.TextRenderingMode.FILL_STROKE||(this._cachedGetSinglePixelWidth=null,b=.65*this.getSinglePixelWidth())}else b/=_;1!==o&&(a.scale(o,o),b/=o),a.lineWidth=b;var S,w=0;for(S=0;S<h;++S){var k=e[S];if((0,n.isNum)(k))w+=f*k*i/1e3;else{var P,x,C,R,E,T,O,I=!1,F=(k.isSpace?u:0)+s,L=k.fontChar,j=k.accent,M=k.width;if(d)E=k.vmetric||p,T=-(T=k.vmetric?E[1]:.5*M)*v,O=E[2]*v,M=E?-E[0]:M,P=T/o,x=(w+O)/o;else P=w/o,x=0;if(r.remeasure&&M>0){var D=1e3*a.measureText(L).width/i*o;if(M<D&&this.isFontSubpixelAAEnabled){var N=M/D;I=!0,a.save(),a.scale(N,1),P/=N}else M!==D&&(P+=(M-D)/2e3*i/o)}(k.isInFont||r.missingFile)&&(m&&!j?a.fillText(L,P,x):(this.paintChar(L,P,x,g),j&&(C=P+j.offset.x/o,R=x-j.offset.y/o,this.paintChar(j.fontChar,C,R,g)))),w+=M*v+F*l,I&&a.restore()}}d?t.y-=w*c:t.x+=w*c,a.restore()}},showType3Text:function(e){var t,r,i,a,o=this.ctx,s=this.current,u=s.font,l=s.fontSize,c=s.fontDirection,h=u.vertical?1:-1,d=s.charSpacing,f=s.wordSpacing,p=s.textHScale*c,v=s.fontMatrix||n.FONT_IDENTITY_MATRIX,m=e.length;if(!(s.textRenderingMode===n.TextRenderingMode.INVISIBLE)&&0!==l){for(this._cachedGetSinglePixelWidth=null,o.save(),o.transform.apply(o,s.textMatrix),o.translate(s.x,s.y),o.scale(p,c),t=0;t<m;++t)if(r=e[t],(0,n.isNum)(r))a=h*r*l/1e3,this.ctx.translate(a,0),s.x+=a*p;else{var g=(r.isSpace?f:0)+d,y=u.charProcOperatorList[r.operatorListId];if(y)this.processingType3=r,this.save(),o.scale(l,l),o.transform.apply(o,v),this.executeOperatorList(y),this.restore(),i=n.Util.applyTransform([r.width,0],v)[0]*l+g,o.translate(i,0),s.x+=i*p;else(0,n.warn)('Type3 character "'+r.operatorListId+'" is not available.')}o.restore(),this.processingType3=null}},setCharWidth:function(e,t){},setCharWidthAndBounds:function(e,t,r,n,i,a){this.ctx.rect(r,n,i-r,a-n),this.clip(),this.endPath()},getColorN_Pattern:function(t){var r,n=this;if("TilingPattern"===t[0]){var a=t[1],o=this.baseTransform||this.ctx.mozCurrentTransform.slice(),s={createCanvasGraphics:function(t){return new e(t,n.commonObjs,n.objs,n.canvasFactory,n.webGLContext)}};r=new i.TilingPattern(t,a,this.ctx,s,o)}else r=(0,i.getShadingPatternFromIR)(t);return r},setStrokeColorN:function(){this.current.strokeColor=this.getColorN_Pattern(arguments)},setFillColorN:function(){this.current.fillColor=this.getColorN_Pattern(arguments),this.current.patternFill=!0},setStrokeRGBColor:function(e,t,r){var i=n.Util.makeCssRgb(e,t,r);this.ctx.strokeStyle=i,this.current.strokeColor=i},setFillRGBColor:function(e,t,r){var i=n.Util.makeCssRgb(e,t,r);this.ctx.fillStyle=i,this.current.fillColor=i,this.current.patternFill=!1},shadingFill:function(e){var t=this.ctx;this.save();var r=(0,i.getShadingPatternFromIR)(e);t.fillStyle=r.getPattern(t,this,!0);var a=t.mozCurrentTransformInverse;if(a){var o=t.canvas,s=o.width,u=o.height,l=n.Util.applyTransform([0,0],a),c=n.Util.applyTransform([0,u],a),h=n.Util.applyTransform([s,0],a),d=n.Util.applyTransform([s,u],a),f=Math.min(l[0],c[0],h[0],d[0]),p=Math.min(l[1],c[1],h[1],d[1]),v=Math.max(l[0],c[0],h[0],d[0]),m=Math.max(l[1],c[1],h[1],d[1]);this.ctx.fillRect(f,p,v-f,m-p)}else this.ctx.fillRect(-1e10,-1e10,2e10,2e10);this.restore()},beginInlineImage:function(){(0,n.unreachable)("Should not call beginInlineImage")},beginImageData:function(){(0,n.unreachable)("Should not call beginImageData")},paintFormXObjectBegin:function(e,t){if(this.save(),this.baseTransformStack.push(this.baseTransform),Array.isArray(e)&&6===e.length&&this.transform.apply(this,e),this.baseTransform=this.ctx.mozCurrentTransform,Array.isArray(t)&&4===t.length){var r=t[2]-t[0],n=t[3]-t[1];this.ctx.rect(t[0],t[1],r,n),this.clip(),this.endPath()}},paintFormXObjectEnd:function(){this.restore(),this.baseTransform=this.baseTransformStack.pop()},beginGroup:function(e){this.save();var t=this.ctx;e.isolated||(0,n.info)("TODO: Support non-isolated groups."),e.knockout&&(0,n.warn)("Knockout groups not supported.");var r=t.mozCurrentTransform;if(e.matrix&&t.transform.apply(t,e.matrix),!e.bbox)throw new Error("Bounding box is required.");var i=n.Util.getAxialAlignedBoundingBox(e.bbox,t.mozCurrentTransform),a=[0,0,t.canvas.width,t.canvas.height];i=n.Util.intersect(i,a)||[0,0,0,0];var o=Math.floor(i[0]),s=Math.floor(i[1]),u=Math.max(Math.ceil(i[2])-o,1),l=Math.max(Math.ceil(i[3])-s,1),h=1,d=1;u>4096&&(h=u/4096,u=4096),l>4096&&(d=l/4096,l=4096);var f="groupAt"+this.groupLevel;e.smask&&(f+="_smask_"+this.smaskCounter++%2);var p=this.cachedCanvases.getCanvas(f,u,l,!0),v=p.context;v.scale(1/h,1/d),v.translate(-o,-s),v.transform.apply(v,r),e.smask?this.smaskStack.push({canvas:p.canvas,context:v,offsetX:o,offsetY:s,scaleX:h,scaleY:d,subtype:e.smask.subtype,backdrop:e.smask.backdrop,transferMap:e.smask.transferMap||null,startTransformInverse:null}):(t.setTransform(1,0,0,1,0,0),t.translate(o,s),t.scale(h,d)),c(t,v),this.ctx=v,this.setGState([["BM","source-over"],["ca",1],["CA",1]]),this.groupStack.push(t),this.groupLevel++,this.current.activeSMask=null},endGroup:function(e){this.groupLevel--;var t=this.ctx;this.ctx=this.groupStack.pop(),void 0!==this.ctx.imageSmoothingEnabled?this.ctx.imageSmoothingEnabled=!1:this.ctx.mozImageSmoothingEnabled=!1,e.smask?this.tempSMask=this.smaskStack.pop():this.ctx.drawImage(t.canvas,0,0),this.restore()},beginAnnotations:function(){this.save(),this.baseTransform&&this.ctx.setTransform.apply(this.ctx,this.baseTransform)},endAnnotations:function(){this.restore()},beginAnnotation:function(e,t,r){if(this.save(),h(this.ctx),this.current=new l,Array.isArray(e)&&4===e.length){var n=e[2]-e[0],i=e[3]-e[1];this.ctx.rect(e[0],e[1],n,i),this.clip(),this.endPath()}this.transform.apply(this,t),this.transform.apply(this,r)},endAnnotation:function(){this.restore()},paintJpegXObject:function(e,t,r){var i=this.objs.get(e);if(i){this.save();var a=this.ctx;if(a.scale(1/t,-1/r),a.drawImage(i,0,0,i.width,i.height,0,-r,t,r),this.imageLayer){var o=a.mozCurrentTransformInverse,s=this.getCanvasPosition(0,0);this.imageLayer.appendImage({objId:e,left:s[0],top:s[1],width:t/o[0],height:r/o[3]})}this.restore()}else(0,n.warn)("Dependent image isn't ready yet")},paintImageMaskXObject:function(e){var t=this.ctx,n=e.width,i=e.height,a=this.current.fillColor,o=this.current.patternFill,s=this.processingType3;if(s&&void 0===s.compiled&&(s.compiled=n<=1e3&&i<=1e3?function(e){var t,r,n,i,a=e.width,o=e.height,s=a+1,u=new Uint8Array(s*(o+1)),l=new Uint8Array([0,2,4,0,1,0,5,4,8,10,0,8,0,2,1,0]),c=a+7&-8,h=e.data,d=new Uint8Array(c*o),f=0;for(t=0,i=h.length;t<i;t++)for(var p=128,v=h[t];p>0;)d[f++]=v&p?0:255,p>>=1;var m=0;for(0!==d[f=0]&&(u[0]=1,++m),r=1;r<a;r++)d[f]!==d[f+1]&&(u[r]=d[f]?2:1,++m),f++;for(0!==d[f]&&(u[r]=2,++m),t=1;t<o;t++){n=t*s,d[(f=t*c)-c]!==d[f]&&(u[n]=d[f]?1:8,++m);var g=(d[f]?4:0)+(d[f-c]?8:0);for(r=1;r<a;r++)l[g=(g>>2)+(d[f+1]?4:0)+(d[f-c+1]?8:0)]&&(u[n+r]=l[g],++m),f++;if(d[f-c]!==d[f]&&(u[n+r]=d[f]?2:4,++m),m>1e3)return null}for(n=t*s,0!==d[f=c*(o-1)]&&(u[n]=8,++m),r=1;r<a;r++)d[f]!==d[f+1]&&(u[n+r]=d[f]?4:8,++m),f++;if(0!==d[f]&&(u[n+r]=4,++m),m>1e3)return null;var y=new Int32Array([0,s,-1,0,-s,0,0,0,1]),b=[];for(t=0;m&&t<=o;t++){for(var _=t*s,A=_+a;_<A&&!u[_];)_++;if(_!==A){var S,w=[_%s,t],k=u[_],P=_;do{var x=y[k];do{_+=x}while(!u[_]);5!==(S=u[_])&&10!==S?(k=S,u[_]=0):(k=S&51*k>>4,u[_]&=k>>2|k<<2),w.push(_%s),w.push(_/s|0),--m}while(P!==_);b.push(w),--t}}return function(e){e.save(),e.scale(1/a,-1/o),e.translate(0,-o),e.beginPath();for(var t=0,r=b.length;t<r;t++){var n=b[t];e.moveTo(n[0],n[1]);for(var i=2,s=n.length;i<s;i+=2)e.lineTo(n[i],n[i+1])}e.fill(),e.beginPath(),e.restore()}}({data:e.data,width:n,height:i}):null),s&&s.compiled)s.compiled(t);else{var u=this.cachedCanvases.getCanvas("maskCanvas",n,i),l=u.context;l.save(),r(l,e),l.globalCompositeOperation="source-in",l.fillStyle=o?a.getPattern(l,this):a,l.fillRect(0,0,n,i),l.restore(),this.paintInlineImageXObject(u.canvas)}},paintImageMaskXObjectRepeat:function(e,t,n,i){var a=e.width,o=e.height,s=this.current.fillColor,u=this.current.patternFill,l=this.cachedCanvases.getCanvas("maskCanvas",a,o),c=l.context;c.save(),r(c,e),c.globalCompositeOperation="source-in",c.fillStyle=u?s.getPattern(c,this):s,c.fillRect(0,0,a,o),c.restore();for(var h=this.ctx,d=0,f=i.length;d<f;d+=2)h.save(),h.transform(t,0,0,n,i[d],i[d+1]),h.scale(1,-1),h.drawImage(l.canvas,0,0,a,o,0,-1,1,1),h.restore()},paintImageMaskXObjectGroup:function(e){for(var t=this.ctx,n=this.current.fillColor,i=this.current.patternFill,a=0,o=e.length;a<o;a++){var s=e[a],u=s.width,l=s.height,c=this.cachedCanvases.getCanvas("maskCanvas",u,l),h=c.context;h.save(),r(h,s),h.globalCompositeOperation="source-in",h.fillStyle=i?n.getPattern(h,this):n,h.fillRect(0,0,u,l),h.restore(),t.save(),t.transform.apply(t,s.transform),t.scale(1,-1),t.drawImage(c.canvas,0,0,u,l,0,-1,1,1),t.restore()}},paintImageXObject:function(e){var t=this.objs.get(e);t?this.paintInlineImageXObject(t):(0,n.warn)("Dependent image isn't ready yet")},paintImageXObjectRepeat:function(e,t,r,i){var a=this.objs.get(e);if(a){for(var o=a.width,s=a.height,u=[],l=0,c=i.length;l<c;l+=2)u.push({transform:[t,0,0,r,i[l],i[l+1]],x:0,y:0,w:o,h:s});this.paintInlineImageXObjectGroup(a,u)}else(0,n.warn)("Dependent image isn't ready yet")},paintInlineImageXObject:function(e){var r=e.width,n=e.height,i=this.ctx;this.save(),i.scale(1/r,-1/n);var a,o,s=i.mozCurrentTransformInverse,u=s[0],l=s[1],c=Math.max(Math.sqrt(u*u+l*l),1),h=s[2],d=s[3],f=Math.max(Math.sqrt(h*h+d*d),1);if("function"==typeof HTMLElement&&e instanceof HTMLElement||!e.data)a=e;else{var p=(o=this.cachedCanvases.getCanvas("inlineImage",r,n)).context;t(p,e),a=o.canvas}for(var v=r,m=n,g="prescale1";c>2&&v>1||f>2&&m>1;){var y=v,b=m;c>2&&v>1&&(c/=v/(y=Math.ceil(v/2))),f>2&&m>1&&(f/=m/(b=Math.ceil(m/2))),(p=(o=this.cachedCanvases.getCanvas(g,y,b)).context).clearRect(0,0,y,b),p.drawImage(a,0,0,v,m,0,0,y,b),a=o.canvas,v=y,m=b,g="prescale1"===g?"prescale2":"prescale1"}if(i.drawImage(a,0,0,v,m,0,-n,r,n),this.imageLayer){var _=this.getCanvasPosition(0,-n);this.imageLayer.appendImage({imgData:e,left:_[0],top:_[1],width:r/s[0],height:n/s[3]})}this.restore()},paintInlineImageXObjectGroup:function(e,r){var n=this.ctx,i=e.width,a=e.height,o=this.cachedCanvases.getCanvas("inlineImage",i,a);t(o.context,e);for(var s=0,u=r.length;s<u;s++){var l=r[s];if(n.save(),n.transform.apply(n,l.transform),n.scale(1,-1),n.drawImage(o.canvas,l.x,l.y,l.w,l.h,0,-1,1,1),this.imageLayer){var c=this.getCanvasPosition(l.x,l.y);this.imageLayer.appendImage({imgData:e,left:c[0],top:c[1],width:i,height:a})}n.restore()}},paintSolidColorImageMask:function(){this.ctx.fillRect(0,0,1,1)},paintXObject:function(){(0,n.warn)("Unsupported 'paintXObject' command.")},markPoint:function(e){},markPointProps:function(e,t){},beginMarkedContent:function(e){},beginMarkedContentProps:function(e,t){},endMarkedContent:function(){},beginCompat:function(){},endCompat:function(){},consumePath:function(){var e=this.ctx;this.pendingClip&&(this.pendingClip===b?e.clip("evenodd"):e.clip(),this.pendingClip=null),e.beginPath()},getSinglePixelWidth:function(e){if(null===this._cachedGetSinglePixelWidth){var t=this.ctx.mozCurrentTransformInverse;this._cachedGetSinglePixelWidth=Math.sqrt(Math.max(t[0]*t[0]+t[1]*t[1],t[2]*t[2]+t[3]*t[3]))}return this._cachedGetSinglePixelWidth},getCanvasPosition:function(e,t){var r=this.ctx.mozCurrentTransform;return[r[0]*e+r[2]*t+r[4],r[1]*e+r[3]*t+r[5]]}},n.OPS)e.prototype[n.OPS[_]]=e.prototype[_];return e}();t.CanvasGraphics=c},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.TilingPattern=t.getShadingPatternFromIR=void 0;var n=r(1),i={RadialAxial:{fromIR:function(e){var t=e[1],r=e[2],n=e[3],i=e[4],a=e[5],o=e[6];return{type:"Pattern",getPattern:function(e){var s;"axial"===t?s=e.createLinearGradient(n[0],n[1],i[0],i[1]):"radial"===t&&(s=e.createRadialGradient(n[0],n[1],a,i[0],i[1],o));for(var u=0,l=r.length;u<l;++u){var c=r[u];s.addColorStop(c[0],c[1])}return s}}}}},a=function(){function e(e,t,r,n,i,a,o,s){var u,l=t.coords,c=t.colors,h=e.data,d=4*e.width;l[r+1]>l[n+1]&&(u=r,r=n,n=u,u=a,a=o,o=u),l[n+1]>l[i+1]&&(u=n,n=i,i=u,u=o,o=s,s=u),l[r+1]>l[n+1]&&(u=r,r=n,n=u,u=a,a=o,o=u);var f=(l[r]+t.offsetX)*t.scaleX,p=(l[r+1]+t.offsetY)*t.scaleY,v=(l[n]+t.offsetX)*t.scaleX,m=(l[n+1]+t.offsetY)*t.scaleY,g=(l[i]+t.offsetX)*t.scaleX,y=(l[i+1]+t.offsetY)*t.scaleY;if(!(p>=y))for(var b,_,A,S,w,k,P,x,C,R=c[a],E=c[a+1],T=c[a+2],O=c[o],I=c[o+1],F=c[o+2],L=c[s],j=c[s+1],M=c[s+2],D=Math.round(p),N=Math.round(y),q=D;q<=N;q++){q<m?(b=f-(f-v)*(C=q<p?0:p===m?1:(p-q)/(p-m)),_=R-(R-O)*C,A=E-(E-I)*C,S=T-(T-F)*C):(b=v-(v-g)*(C=q>y?1:m===y?0:(m-q)/(m-y)),_=O-(O-L)*C,A=I-(I-j)*C,S=F-(F-M)*C),w=f-(f-g)*(C=q<p?0:q>y?1:(p-q)/(p-y)),k=R-(R-L)*C,P=E-(E-j)*C,x=T-(T-M)*C;for(var W=Math.round(Math.min(b,w)),U=Math.round(Math.max(b,w)),B=d*q+4*W,z=W;z<=U;z++)C=(C=(b-z)/(b-w))<0?0:C>1?1:C,h[B++]=_-(_-k)*C|0,h[B++]=A-(A-P)*C|0,h[B++]=S-(S-x)*C|0,h[B++]=255}}function t(t,r,n){var i,a,o=r.coords,s=r.colors;switch(r.type){case"lattice":var u=r.verticesPerRow,l=Math.floor(o.length/u)-1,c=u-1;for(i=0;i<l;i++)for(var h=i*u,d=0;d<c;d++,h++)e(t,n,o[h],o[h+1],o[h+u],s[h],s[h+1],s[h+u]),e(t,n,o[h+u+1],o[h+1],o[h+u],s[h+u+1],s[h+1],s[h+u]);break;case"triangles":for(i=0,a=o.length;i<a;i+=3)e(t,n,o[i],o[i+1],o[i+2],s[i],s[i+1],s[i+2]);break;default:throw new Error("illegal figure")}}return function(e,r,n,i,a,o,s,u){var l,c,h,d,f=Math.floor(e[0]),p=Math.floor(e[1]),v=Math.ceil(e[2])-f,m=Math.ceil(e[3])-p,g=Math.min(Math.ceil(Math.abs(v*r[0]*1.1)),3e3),y=Math.min(Math.ceil(Math.abs(m*r[1]*1.1)),3e3),b=v/g,_=m/y,A={coords:n,colors:i,offsetX:-f,offsetY:-p,scaleX:1/b,scaleY:1/_},S=g+4,w=y+4;if(u.isEnabled)l=u.drawFigures({width:g,height:y,backgroundColor:o,figures:a,context:A}),(c=s.getCanvas("mesh",S,w,!1)).context.drawImage(l,2,2),l=c.canvas;else{var k=(c=s.getCanvas("mesh",S,w,!1)).context,P=k.createImageData(g,y);if(o){var x=P.data;for(h=0,d=x.length;h<d;h+=4)x[h]=o[0],x[h+1]=o[1],x[h+2]=o[2],x[h+3]=255}for(h=0;h<a.length;h++)t(P,a[h],A);k.putImageData(P,2,2),l=c.canvas}return{canvas:l,offsetX:f-2*b,offsetY:p-2*_,scaleX:b,scaleY:_}}}();i.Mesh={fromIR:function(e){var t=e[2],r=e[3],i=e[4],o=e[5],s=e[6],u=e[8];return{type:"Pattern",getPattern:function(e,l,c){var h;if(c)h=n.Util.singularValueDecompose2dScale(e.mozCurrentTransform);else if(h=n.Util.singularValueDecompose2dScale(l.baseTransform),s){var d=n.Util.singularValueDecompose2dScale(s);h=[h[0]*d[0],h[1]*d[1]]}var f=a(o,h,t,r,i,c?null:u,l.cachedCanvases,l.webGLContext);return c||(e.setTransform.apply(e,l.baseTransform),s&&e.transform.apply(e,s)),e.translate(f.offsetX,f.offsetY),e.scale(f.scaleX,f.scaleY),e.createPattern(f.canvas,"no-repeat")}}}},i.Dummy={fromIR:function(){return{type:"Pattern",getPattern:function(){return"hotpink"}}}};var o=function(){var e=1,t=2;function r(e,t,r,n,i){this.operatorList=e[2],this.matrix=e[3]||[1,0,0,1,0,0],this.bbox=e[4],this.xstep=e[5],this.ystep=e[6],this.paintType=e[7],this.tilingType=e[8],this.color=t,this.canvasGraphicsFactory=n,this.baseTransform=i,this.type="Pattern",this.ctx=r}return r.prototype={createPatternCanvas:function(e){var t=this.operatorList,r=this.bbox,i=this.xstep,a=this.ystep,o=this.paintType,s=this.tilingType,u=this.color,l=this.canvasGraphicsFactory;(0,n.info)("TilingType: "+s);var c=r[0],h=r[1],d=r[2],f=r[3],p=[c,h],v=[c+i,h+a],m=v[0]-p[0],g=v[1]-p[1],y=n.Util.singularValueDecompose2dScale(this.matrix),b=n.Util.singularValueDecompose2dScale(this.baseTransform),_=[y[0]*b[0],y[1]*b[1]];m=Math.min(Math.ceil(Math.abs(m*_[0])),3e3),g=Math.min(Math.ceil(Math.abs(g*_[1])),3e3);var A=e.cachedCanvases.getCanvas("pattern",m,g,!0),S=A.context,w=l.createCanvasGraphics(S);w.groupLevel=e.groupLevel,this.setFillAndStrokeStyleToContext(w,o,u),this.setScale(m,g,i,a),this.transformToScale(w);var k=[1,0,0,1,-p[0],-p[1]];return w.transform.apply(w,k),this.clipBbox(w,r,c,h,d,f),w.executeOperatorList(t),A.canvas},setScale:function(e,t,r,n){this.scale=[e/r,t/n]},transformToScale:function(e){var t=this.scale,r=[t[0],0,0,t[1],0,0];e.transform.apply(e,r)},scaleToContext:function(){var e=this.scale;this.ctx.scale(1/e[0],1/e[1])},clipBbox:function(e,t,r,n,i,a){if(Array.isArray(t)&&4===t.length){var o=i-r,s=a-n;e.ctx.rect(r,n,o,s),e.clip(),e.endPath()}},setFillAndStrokeStyleToContext:function(r,i,a){var o=r.ctx,s=r.current;switch(i){case e:var u=this.ctx;o.fillStyle=u.fillStyle,o.strokeStyle=u.strokeStyle,s.fillColor=u.fillStyle,s.strokeColor=u.strokeStyle;break;case t:var l=n.Util.makeCssRgb(a[0],a[1],a[2]);o.fillStyle=l,o.strokeStyle=l,s.fillColor=l,s.strokeColor=l;break;default:throw new n.FormatError("Unsupported paint type: "+i)}},getPattern:function(e,t){var r=this.createPatternCanvas(t);return(e=this.ctx).setTransform.apply(e,this.baseTransform),e.transform.apply(e,this.matrix),this.scaleToContext(),e.createPattern(r,"repeat")}},r}();t.getShadingPatternFromIR=function(e){var t=i[e[0]];if(!t)throw new Error("Unknown IR type: "+e[0]);return t.fromIR(e)},t.TilingPattern=o},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=Object.create(null);n.workerPort=void 0===n.workerPort?null:n.workerPort,n.workerSrc=void 0===n.workerSrc?"":n.workerSrc,t.GlobalWorkerOptions=n},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.MessageHandler=void 0;var n,i,a,o=r(137),s=(n=o)&&n.__esModule?n:{default:n},u="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},l=(i=s.default.mark(function e(t,r){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return s.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(t){e.next=2;break}return e.abrupt("return");case 2:return e.abrupt("return",t.apply(n,r));case 3:case"end":return e.stop()}},e,this)}),a=function(){var e=i.apply(this,arguments);return new Promise(function(t,r){return function n(i,a){try{var o=e[i](a),s=o.value}catch(e){return void r(e)}if(!o.done)return Promise.resolve(s).then(function(e){n("next",e)},function(e){n("throw",e)});t(s)}("next")})},function(e,t){return a.apply(this,arguments)}),c=r(1);function h(e){if("object"!==(void 0===e?"undefined":u(e)))return e;switch(e.name){case"AbortException":return new c.AbortException(e.message);case"MissingPDFException":return new c.MissingPDFException(e.message);case"UnexpectedResponseException":return new c.UnexpectedResponseException(e.message,e.status);default:return new c.UnknownErrorException(e.message,e.details)}}function d(e,t,r){t?e.resolve():e.reject(r)}function f(e,t,r){var n=this;this.sourceName=e,this.targetName=t,this.comObj=r,this.callbackId=1,this.streamId=1,this.postMessageTransfers=!0,this.streamSinks=Object.create(null),this.streamControllers=Object.create(null);var i=this.callbacksCapabilities=Object.create(null),a=this.actionHandler=Object.create(null);this._onComObjOnMessage=function(e){var t=e.data;if(t.targetName===n.sourceName)if(t.stream)n._processStreamMessage(t);else if(t.isReply){var o=t.callbackId;if(!(t.callbackId in i))throw new Error("Cannot resolve callback "+o);var s=i[o];delete i[o],"error"in t?s.reject(h(t.error)):s.resolve(t.data)}else{if(!(t.action in a))throw new Error("Unknown action from worker: "+t.action);var u=a[t.action];if(t.callbackId){var l=n.sourceName,d=t.sourceName;Promise.resolve().then(function(){return u[0].call(u[1],t.data)}).then(function(e){r.postMessage({sourceName:l,targetName:d,isReply:!0,callbackId:t.callbackId,data:e})},function(e){r.postMessage({sourceName:l,targetName:d,isReply:!0,callbackId:t.callbackId,error:function(e){return!(e instanceof Error)||e instanceof c.AbortException||e instanceof c.MissingPDFException||e instanceof c.UnexpectedResponseException||e instanceof c.UnknownErrorException?e:new c.UnknownErrorException(e.message,e.toString())}(e)})})}else t.streamId?n._createStreamSink(t):u[0].call(u[1],t.data)}},r.addEventListener("message",this._onComObjOnMessage)}f.prototype={on:function(e,t,r){var n=this.actionHandler;if(n[e])throw new Error('There is already an actionName called "'+e+'"');n[e]=[t,r]},send:function(e,t,r){var n={sourceName:this.sourceName,targetName:this.targetName,action:e,data:t};this.postMessage(n,r)},sendWithPromise:function(e,t,r){var n=this.callbackId++,i={sourceName:this.sourceName,targetName:this.targetName,action:e,data:t,callbackId:n},a=(0,c.createPromiseCapability)();this.callbacksCapabilities[n]=a;try{this.postMessage(i,r)}catch(e){a.reject(e)}return a.promise},sendWithStream:function(e,t,r,n){var i=this,a=this.streamId++,o=this.sourceName,s=this.targetName;return new c.ReadableStream({start:function(r){var n=(0,c.createPromiseCapability)();return i.streamControllers[a]={controller:r,startCall:n,isClosed:!1},i.postMessage({sourceName:o,targetName:s,action:e,streamId:a,data:t,desiredSize:r.desiredSize}),n.promise},pull:function(e){var t=(0,c.createPromiseCapability)();return i.streamControllers[a].pullCall=t,i.postMessage({sourceName:o,targetName:s,stream:"pull",streamId:a,desiredSize:e.desiredSize}),t.promise},cancel:function(e){var t=(0,c.createPromiseCapability)();return i.streamControllers[a].cancelCall=t,i.streamControllers[a].isClosed=!0,i.postMessage({sourceName:o,targetName:s,stream:"cancel",reason:e,streamId:a}),t.promise}},r)},_createStreamSink:function(e){var t=this,r=this,n=this.actionHandler[e.action],i=e.streamId,a=e.desiredSize,o=this.sourceName,s=e.sourceName,u=function(e){var r=e.stream,n=e.chunk,a=e.transfers,u=e.success,l=e.reason;t.postMessage({sourceName:o,targetName:s,stream:r,streamId:i,chunk:n,success:u,reason:l},a)},h={enqueue:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,r=arguments[2];if(!this.isCancelled){var n=this.desiredSize;this.desiredSize-=t,n>0&&this.desiredSize<=0&&(this.sinkCapability=(0,c.createPromiseCapability)(),this.ready=this.sinkCapability.promise),u({stream:"enqueue",chunk:e,transfers:r})}},close:function(){this.isCancelled||(this.isCancelled=!0,u({stream:"close"}),delete r.streamSinks[i])},error:function(e){this.isCancelled||(this.isCancelled=!0,u({stream:"error",reason:e}))},sinkCapability:(0,c.createPromiseCapability)(),onPull:null,onCancel:null,isCancelled:!1,desiredSize:a,ready:null};h.sinkCapability.resolve(),h.ready=h.sinkCapability.promise,this.streamSinks[i]=h,l(n[0],[e.data,h],n[1]).then(function(){u({stream:"start_complete",success:!0})},function(e){u({stream:"start_complete",success:!1,reason:e})})},_processStreamMessage:function(e){var t=this,r=this.sourceName,n=e.sourceName,i=e.streamId,a=function(e){var a=e.stream,o=e.success,s=e.reason;t.comObj.postMessage({sourceName:r,targetName:n,stream:a,success:o,streamId:i,reason:s})},o=function(){Promise.all([t.streamControllers[e.streamId].startCall,t.streamControllers[e.streamId].pullCall,t.streamControllers[e.streamId].cancelCall].map(function(e){return e&&(t=e.promise,Promise.resolve(t).catch(function(){}));var t})).then(function(){delete t.streamControllers[e.streamId]})};switch(e.stream){case"start_complete":d(this.streamControllers[e.streamId].startCall,e.success,h(e.reason));break;case"pull_complete":d(this.streamControllers[e.streamId].pullCall,e.success,h(e.reason));break;case"pull":if(!this.streamSinks[e.streamId]){a({stream:"pull_complete",success:!0});break}this.streamSinks[e.streamId].desiredSize<=0&&e.desiredSize>0&&this.streamSinks[e.streamId].sinkCapability.resolve(),this.streamSinks[e.streamId].desiredSize=e.desiredSize,l(this.streamSinks[e.streamId].onPull).then(function(){a({stream:"pull_complete",success:!0})},function(e){a({stream:"pull_complete",success:!1,reason:e})});break;case"enqueue":(0,c.assert)(this.streamControllers[e.streamId],"enqueue should have stream controller"),this.streamControllers[e.streamId].isClosed||this.streamControllers[e.streamId].controller.enqueue(e.chunk);break;case"close":if((0,c.assert)(this.streamControllers[e.streamId],"close should have stream controller"),this.streamControllers[e.streamId].isClosed)break;this.streamControllers[e.streamId].isClosed=!0,this.streamControllers[e.streamId].controller.close(),o();break;case"error":(0,c.assert)(this.streamControllers[e.streamId],"error should have stream controller"),this.streamControllers[e.streamId].controller.error(h(e.reason)),o();break;case"cancel_complete":d(this.streamControllers[e.streamId].cancelCall,e.success,h(e.reason)),o();break;case"cancel":if(!this.streamSinks[e.streamId])break;l(this.streamSinks[e.streamId].onCancel,[h(e.reason)]).then(function(){a({stream:"cancel_complete",success:!0})},function(e){a({stream:"cancel_complete",success:!1,reason:e})}),this.streamSinks[e.streamId].sinkCapability.reject(h(e.reason)),this.streamSinks[e.streamId].isCancelled=!0,delete this.streamSinks[e.streamId];break;default:throw new Error("Unexpected stream case")}},postMessage:function(e,t){t&&this.postMessageTransfers?this.comObj.postMessage(e,t):this.comObj.postMessage(e)},destroy:function(){this.comObj.removeEventListener("message",this._onComObjOnMessage)}},t.MessageHandler=f},function(e,t,r){"use strict";e.exports=r(138)},function(e,t,r){"use strict";var n=function(){return this}()||Function("return this")(),i=n.regeneratorRuntime&&Object.getOwnPropertyNames(n).indexOf("regeneratorRuntime")>=0,a=i&&n.regeneratorRuntime;if(n.regeneratorRuntime=void 0,e.exports=r(139),i)n.regeneratorRuntime=a;else try{delete n.regeneratorRuntime}catch(e){n.regeneratorRuntime=void 0}},function(e,t,r){"use strict";(function(e){var t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};!function(r){var n,i=Object.prototype,a=i.hasOwnProperty,o="function"==typeof Symbol?Symbol:{},s=o.iterator||"@@iterator",u=o.asyncIterator||"@@asyncIterator",l=o.toStringTag||"@@toStringTag",c="object"===t(e),h=r.regeneratorRuntime;if(h)c&&(e.exports=h);else{(h=r.regeneratorRuntime=c?e.exports:{}).wrap=A;var d="suspendedStart",f="suspendedYield",p="executing",v="completed",m={},g={};g[s]=function(){return this};var y=Object.getPrototypeOf,b=y&&y(y(I([])));b&&b!==i&&a.call(b,s)&&(g=b);var _=P.prototype=w.prototype=Object.create(g);k.prototype=_.constructor=P,P.constructor=k,P[l]=k.displayName="GeneratorFunction",h.isGeneratorFunction=function(e){var t="function"==typeof e&&e.constructor;return!!t&&(t===k||"GeneratorFunction"===(t.displayName||t.name))},h.mark=function(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,P):(e.__proto__=P,l in e||(e[l]="GeneratorFunction")),e.prototype=Object.create(_),e},h.awrap=function(e){return{__await:e}},x(C.prototype),C.prototype[u]=function(){return this},h.AsyncIterator=C,h.async=function(e,t,r,n){var i=new C(A(e,t,r,n));return h.isGeneratorFunction(t)?i:i.next().then(function(e){return e.done?e.value:i.next()})},x(_),_[l]="Generator",_[s]=function(){return this},_.toString=function(){return"[object Generator]"},h.keys=function(e){var t=[];for(var r in e)t.push(r);return t.reverse(),function r(){for(;t.length;){var n=t.pop();if(n in e)return r.value=n,r.done=!1,r}return r.done=!0,r}},h.values=I,O.prototype={constructor:O,reset:function(e){if(this.prev=0,this.next=0,this.sent=this._sent=n,this.done=!1,this.delegate=null,this.method="next",this.arg=n,this.tryEntries.forEach(T),!e)for(var t in this)"t"===t.charAt(0)&&a.call(this,t)&&!isNaN(+t.slice(1))&&(this[t]=n)},stop:function(){this.done=!0;var e=this.tryEntries[0].completion;if("throw"===e.type)throw e.arg;return this.rval},dispatchException:function(e){if(this.done)throw e;var t=this;function r(r,i){return s.type="throw",s.arg=e,t.next=r,i&&(t.method="next",t.arg=n),!!i}for(var i=this.tryEntries.length-1;i>=0;--i){var o=this.tryEntries[i],s=o.completion;if("root"===o.tryLoc)return r("end");if(o.tryLoc<=this.prev){var u=a.call(o,"catchLoc"),l=a.call(o,"finallyLoc");if(u&&l){if(this.prev<o.catchLoc)return r(o.catchLoc,!0);if(this.prev<o.finallyLoc)return r(o.finallyLoc)}else if(u){if(this.prev<o.catchLoc)return r(o.catchLoc,!0)}else{if(!l)throw new Error("try statement without catch or finally");if(this.prev<o.finallyLoc)return r(o.finallyLoc)}}}},abrupt:function(e,t){for(var r=this.tryEntries.length-1;r>=0;--r){var n=this.tryEntries[r];if(n.tryLoc<=this.prev&&a.call(n,"finallyLoc")&&this.prev<n.finallyLoc){var i=n;break}}i&&("break"===e||"continue"===e)&&i.tryLoc<=t&&t<=i.finallyLoc&&(i=null);var o=i?i.completion:{};return o.type=e,o.arg=t,i?(this.method="next",this.next=i.finallyLoc,m):this.complete(o)},complete:function(e,t){if("throw"===e.type)throw e.arg;return"break"===e.type||"continue"===e.type?this.next=e.arg:"return"===e.type?(this.rval=this.arg=e.arg,this.method="return",this.next="end"):"normal"===e.type&&t&&(this.next=t),m},finish:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var r=this.tryEntries[t];if(r.finallyLoc===e)return this.complete(r.completion,r.afterLoc),T(r),m}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var r=this.tryEntries[t];if(r.tryLoc===e){var n=r.completion;if("throw"===n.type){var i=n.arg;T(r)}return i}}throw new Error("illegal catch attempt")},delegateYield:function(e,t,r){return this.delegate={iterator:I(e),resultName:t,nextLoc:r},"next"===this.method&&(this.arg=n),m}}}function A(e,t,r,n){var i=t&&t.prototype instanceof w?t:w,a=Object.create(i.prototype),o=new O(n||[]);return a._invoke=function(e,t,r){var n=d;return function(i,a){if(n===p)throw new Error("Generator is already running");if(n===v){if("throw"===i)throw a;return F()}for(r.method=i,r.arg=a;;){var o=r.delegate;if(o){var s=R(o,r);if(s){if(s===m)continue;return s}}if("next"===r.method)r.sent=r._sent=r.arg;else if("throw"===r.method){if(n===d)throw n=v,r.arg;r.dispatchException(r.arg)}else"return"===r.method&&r.abrupt("return",r.arg);n=p;var u=S(e,t,r);if("normal"===u.type){if(n=r.done?v:f,u.arg===m)continue;return{value:u.arg,done:r.done}}"throw"===u.type&&(n=v,r.method="throw",r.arg=u.arg)}}}(e,r,o),a}function S(e,t,r){try{return{type:"normal",arg:e.call(t,r)}}catch(e){return{type:"throw",arg:e}}}function w(){}function k(){}function P(){}function x(e){["next","throw","return"].forEach(function(t){e[t]=function(e){return this._invoke(t,e)}})}function C(e){var r;this._invoke=function(n,i){function o(){return new Promise(function(r,o){!function r(n,i,o,s){var u=S(e[n],e,i);if("throw"!==u.type){var l=u.arg,c=l.value;return c&&"object"===(void 0===c?"undefined":t(c))&&a.call(c,"__await")?Promise.resolve(c.__await).then(function(e){r("next",e,o,s)},function(e){r("throw",e,o,s)}):Promise.resolve(c).then(function(e){l.value=e,o(l)},s)}s(u.arg)}(n,i,r,o)})}return r=r?r.then(o,o):o()}}function R(e,t){var r=e.iterator[t.method];if(r===n){if(t.delegate=null,"throw"===t.method){if(e.iterator.return&&(t.method="return",t.arg=n,R(e,t),"throw"===t.method))return m;t.method="throw",t.arg=new TypeError("The iterator does not provide a 'throw' method")}return m}var i=S(r,e.iterator,t.arg);if("throw"===i.type)return t.method="throw",t.arg=i.arg,t.delegate=null,m;var a=i.arg;return a?a.done?(t[e.resultName]=a.value,t.next=e.nextLoc,"return"!==t.method&&(t.method="next",t.arg=n),t.delegate=null,m):a:(t.method="throw",t.arg=new TypeError("iterator result is not an object"),t.delegate=null,m)}function E(e){var t={tryLoc:e[0]};1 in e&&(t.catchLoc=e[1]),2 in e&&(t.finallyLoc=e[2],t.afterLoc=e[3]),this.tryEntries.push(t)}function T(e){var t=e.completion||{};t.type="normal",delete t.arg,e.completion=t}function O(e){this.tryEntries=[{tryLoc:"root"}],e.forEach(E,this),this.reset(!0)}function I(e){if(e){var t=e[s];if(t)return t.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var r=-1,i=function t(){for(;++r<e.length;)if(a.call(e,r))return t.value=e[r],t.done=!1,t;return t.value=n,t.done=!0,t};return i.next=i}}return{next:F}}function F(){return{value:n,done:!0}}}(function(){return this}()||Function("return this")())}).call(this,r(140)(e))},function(e,t,r){"use strict";e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Metadata=void 0;var n=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),i=r(1),a=r(142);var o=function(){function e(t){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),(0,i.assert)("string"==typeof t,"Metadata: input is not a string"),t=this._repair(t);var r=(new a.SimpleXMLParser).parseFromString(t);this._metadata=Object.create(null),r&&this._parse(r)}return n(e,[{key:"_repair",value:function(e){return e.replace(/>\\376\\377([^<]+)/g,function(e,t){for(var r=t.replace(/\\([0-3])([0-7])([0-7])/g,function(e,t,r,n){return String.fromCharCode(64*t+8*r+1*n)}).replace(/&(amp|apos|gt|lt|quot);/g,function(e,t){switch(t){case"amp":return"&";case"apos":return"'";case"gt":return">";case"lt":return"<";case"quot":return'"'}throw new Error("_repair: "+t+" isn't defined.")}),n="",i=0,a=r.length;i<a;i+=2){var o=256*r.charCodeAt(i)+r.charCodeAt(i+1);n+=o>=32&&o<127&&60!==o&&62!==o&&38!==o?String.fromCharCode(o):"&#x"+(65536+o).toString(16).substring(1)+";"}return">"+n})}},{key:"_parse",value:function(e){var t=e.documentElement;if("rdf:rdf"!==t.nodeName.toLowerCase())for(t=t.firstChild;t&&"rdf:rdf"!==t.nodeName.toLowerCase();)t=t.nextSibling;var r=t?t.nodeName.toLowerCase():null;if(t&&"rdf:rdf"===r&&t.hasChildNodes())for(var n=t.childNodes,i=0,a=n.length;i<a;i++){var o=n[i];if("rdf:description"===o.nodeName.toLowerCase())for(var s=0,u=o.childNodes.length;s<u;s++)if("#text"!==o.childNodes[s].nodeName.toLowerCase()){var l=o.childNodes[s],c=l.nodeName.toLowerCase();this._metadata[c]=l.textContent.trim()}}}},{key:"get",value:function(e){return this._metadata[e]||null}},{key:"getAll",value:function(){return this._metadata}},{key:"has",value:function(e){return void 0!==this._metadata[e]}}]),e}();t.Metadata=o},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=function(){return function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var r=[],n=!0,i=!1,a=void 0;try{for(var o,s=e[Symbol.iterator]();!(n=(o=s.next()).done)&&(r.push(o.value),!t||r.length!==t);n=!0);}catch(e){i=!0,a=e}finally{try{!n&&s.return&&s.return()}finally{if(i)throw a}}return r}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),i=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}();function a(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var o={NoError:0,EndOfDocument:-1,UnterminatedCdat:-2,UnterminatedXmlDeclaration:-3,UnterminatedDoctypeDeclaration:-4,UnterminatedComment:-5,MalformedElement:-6,OutOfMemory:-7,UnterminatedAttributeValue:-8,UnterminatedElement:-9,ElementNeverBegun:-10};function s(e,t){var r=e[t];return" "===r||"\n"===r||"\r"===r||"\t"===r}var u=function(){function e(){a(this,e)}return i(e,[{key:"_resolveEntities",value:function(e){return e.replace(/&([^;]+);/g,function(e,t){if("#x"===t.substring(0,2))return String.fromCharCode(parseInt(t.substring(2),16));if("#"===t.substring(0,1))return String.fromCharCode(parseInt(t.substring(1),10));switch(t){case"lt":return"<";case"gt":return">";case"amp":return"&";case"quot":return'"'}return this.onResolveEntity(t)})}},{key:"_parseContent",value:function(e,t){var r,n=t,i=[];function a(){for(;n<e.length&&s(e,n);)++n}for(;n<e.length&&!s(e,n)&&">"!==e[n]&&"/"!==e[n];)++n;for(r=e.substring(t,n),a();n<e.length&&">"!==e[n]&&"/"!==e[n]&&"?"!==e[n];){a();for(var o,u="";n<e.length&&!s(e,n)&&"="!==e[n];)u+=e[n],++n;if(a(),"="!==e[n])return null;++n,a();var l=e[n];if('"'!==l&&"'"!==l)return null;var c=e.indexOf(l,++n);if(c<0)return null;o=e.substring(n,c),i.push({name:u,value:this._resolveEntities(o)}),n=c+1,a()}return{name:r,attributes:i,parsed:n-t}}},{key:"_parseProcessingInstruction",value:function(e,t){var r,n=t;for(;n<e.length&&!s(e,n)&&">"!==e[n]&&"/"!==e[n];)++n;r=e.substring(t,n),function(){for(;n<e.length&&s(e,n);)++n}();for(var i=n;n<e.length&&("?"!==e[n]||">"!==e[n+1]);)++n;return{name:r,value:e.substring(i,n),parsed:n-t}}},{key:"parseXml",value:function(e){for(var t=0;t<e.length;){var r=t;if("<"===e[t]){var n=void 0;switch(e[++r]){case"/":if(++r,(n=e.indexOf(">",r))<0)return void this.onError(o.UnterminatedElement);this.onEndElement(e.substring(r,n)),r=n+1;break;case"?":++r;var i=this._parseProcessingInstruction(e,r);if("?>"!==e.substring(r+i.parsed,r+i.parsed+2))return void this.onError(o.UnterminatedXmlDeclaration);this.onPi(i.name,i.value),r+=i.parsed+2;break;case"!":if("--"===e.substring(r+1,r+3)){if((n=e.indexOf("--\x3e",r+3))<0)return void this.onError(o.UnterminatedComment);this.onComment(e.substring(r+3,n)),r=n+3}else if("[CDATA["===e.substring(r+1,r+8)){if((n=e.indexOf("]]>",r+8))<0)return void this.onError(o.UnterminatedCdat);this.onCdata(e.substring(r+8,n)),r=n+3}else{if("DOCTYPE"!==e.substring(r+1,r+8))return void this.onError(o.MalformedElement);var a=e.indexOf("[",r+8),s=!1;if((n=e.indexOf(">",r+8))<0)return void this.onError(o.UnterminatedDoctypeDeclaration);if(a>0&&n>a){if((n=e.indexOf("]>",r+8))<0)return void this.onError(o.UnterminatedDoctypeDeclaration);s=!0}var u=e.substring(r+8,n+(s?1:0));this.onDoctype(u),r=n+(s?2:1)}break;default:var l=this._parseContent(e,r);if(null===l)return void this.onError(o.MalformedElement);var c=!1;if("/>"===e.substring(r+l.parsed,r+l.parsed+2))c=!0;else if(">"!==e.substring(r+l.parsed,r+l.parsed+1))return void this.onError(o.UnterminatedElement);this.onBeginElement(l.name,l.attributes,c),r+=l.parsed+(c?2:1)}}else{for(;r<e.length&&"<"!==e[r];)r++;var h=e.substring(t,r);this.onText(this._resolveEntities(h))}t=r}}},{key:"onResolveEntity",value:function(e){return"&"+e+";"}},{key:"onPi",value:function(e,t){}},{key:"onComment",value:function(e){}},{key:"onCdata",value:function(e){}},{key:"onDoctype",value:function(e){}},{key:"onText",value:function(e){}},{key:"onBeginElement",value:function(e,t,r){}},{key:"onEndElement",value:function(e){}},{key:"onError",value:function(e){}}]),e}(),l=function(){function e(t,r){a(this,e),this.nodeName=t,this.nodeValue=r,Object.defineProperty(this,"parentNode",{value:null,writable:!0})}return i(e,[{key:"hasChildNodes",value:function(){return this.childNodes&&this.childNodes.length>0}},{key:"firstChild",get:function(){return this.childNodes[0]}},{key:"nextSibling",get:function(){var e=this.parentNode.childNodes.indexOf(this);return this.parentNode.childNodes[e+1]}},{key:"textContent",get:function(){return this.childNodes?this.childNodes.map(function(e){return e.textContent}).join(""):this.nodeValue||""}}]),e}(),c=function(e){function t(){a(this,t);var e=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return e._currentFragment=null,e._stack=null,e._errorCode=o.NoError,e}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,u),i(t,[{key:"parseFromString",value:function(e){if(this._currentFragment=[],this._stack=[],this._errorCode=o.NoError,this.parseXml(e),this._errorCode===o.NoError){var t=n(this._currentFragment,1)[0];if(t)return{documentElement:t}}}},{key:"onResolveEntity",value:function(e){switch(e){case"apos":return"'"}return function e(t,r,n){null===t&&(t=Function.prototype);var i=Object.getOwnPropertyDescriptor(t,r);if(void 0===i){var a=Object.getPrototypeOf(t);return null===a?void 0:e(a,r,n)}if("value"in i)return i.value;var o=i.get;return void 0!==o?o.call(n):void 0}(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"onResolveEntity",this).call(this,e)}},{key:"onText",value:function(e){if(!function(e){for(var t=0,r=e.length;t<r;t++)if(!s(e,t))return!1;return!0}(e)){var t=new l("#text",e);this._currentFragment.push(t)}}},{key:"onCdata",value:function(e){var t=new l("#text",e);this._currentFragment.push(t)}},{key:"onBeginElement",value:function(e,t,r){var n=new l(e);n.childNodes=[],this._currentFragment.push(n),r||(this._stack.push(this._currentFragment),this._currentFragment=n.childNodes)}},{key:"onEndElement",value:function(e){this._currentFragment=this._stack.pop();for(var t=this._currentFragment[this._currentFragment.length-1],r=0,n=t.childNodes.length;r<n;r++)t.childNodes[r].parentNode=t}},{key:"onError",value:function(e){this._errorCode=e}}]),t}();t.SimpleXMLParser=c},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.PDFDataTransportStream=void 0;var n,i=r(137),a=(n=i)&&n.__esModule?n:{default:n},o=r(1);function s(e){return function(){var t=e.apply(this,arguments);return new Promise(function(e,r){return function n(i,a){try{var o=t[i](a),s=o.value}catch(e){return void r(e)}if(!o.done)return Promise.resolve(s).then(function(e){n("next",e)},function(e){n("throw",e)});e(s)}("next")})}}var u=function(){function e(e,t){var r=this;(0,o.assert)(t),this._queuedChunks=[];var n=e.initialData;if(n&&n.length>0){var i=new Uint8Array(n).buffer;this._queuedChunks.push(i)}this._pdfDataRangeTransport=t,this._isStreamingSupported=!e.disableStream,this._isRangeSupported=!e.disableRange,this._contentLength=e.length,this._fullRequestReader=null,this._rangeReaders=[],this._pdfDataRangeTransport.addRangeListener(function(e,t){r._onReceiveData({begin:e,chunk:t})}),this._pdfDataRangeTransport.addProgressListener(function(e){r._onProgress({loaded:e})}),this._pdfDataRangeTransport.addProgressiveReadListener(function(e){r._onReceiveData({chunk:e})}),this._pdfDataRangeTransport.transportReady()}function t(e,t){this._stream=e,this._done=!1,this._filename=null,this._queuedChunks=t||[],this._requests=[],this._headersReady=Promise.resolve(),e._fullRequestReader=this,this.onProgress=null}function r(e,t,r){this._stream=e,this._begin=t,this._end=r,this._queuedChunk=null,this._requests=[],this._done=!1,this.onProgress=null}return e.prototype={_onReceiveData:function(e){var t=new Uint8Array(e.chunk).buffer;if(void 0===e.begin)this._fullRequestReader?this._fullRequestReader._enqueue(t):this._queuedChunks.push(t);else{var r=this._rangeReaders.some(function(r){return r._begin===e.begin&&(r._enqueue(t),!0)});(0,o.assert)(r)}},_onProgress:function(e){if(this._rangeReaders.length>0){var t=this._rangeReaders[0];t.onProgress&&t.onProgress({loaded:e.loaded})}},_removeRangeReader:function(e){var t=this._rangeReaders.indexOf(e);t>=0&&this._rangeReaders.splice(t,1)},getFullReader:function(){(0,o.assert)(!this._fullRequestReader);var e=this._queuedChunks;return this._queuedChunks=null,new t(this,e)},getRangeReader:function(e,t){var n=new r(this,e,t);return this._pdfDataRangeTransport.requestDataRange(e,t),this._rangeReaders.push(n),n},cancelAllRequests:function(e){this._fullRequestReader&&this._fullRequestReader.cancel(e),this._rangeReaders.slice(0).forEach(function(t){t.cancel(e)}),this._pdfDataRangeTransport.abort()}},t.prototype={_enqueue:function(e){this._done||(this._requests.length>0?this._requests.shift().resolve({value:e,done:!1}):this._queuedChunks.push(e))},get headersReady(){return this._headersReady},get filename(){return this._filename},get isRangeSupported(){return this._stream._isRangeSupported},get isStreamingSupported(){return this._stream._isStreamingSupported},get contentLength(){return this._stream._contentLength},read:function(){var e=s(a.default.mark(function e(){var t,r;return a.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(!(this._queuedChunks.length>0)){e.next=3;break}return t=this._queuedChunks.shift(),e.abrupt("return",{value:t,done:!1});case 3:if(!this._done){e.next=5;break}return e.abrupt("return",{value:void 0,done:!0});case 5:return r=(0,o.createPromiseCapability)(),this._requests.push(r),e.abrupt("return",r.promise);case 8:case"end":return e.stop()}},e,this)}));return function(){return e.apply(this,arguments)}}(),cancel:function(e){this._done=!0,this._requests.forEach(function(e){e.resolve({value:void 0,done:!0})}),this._requests=[]}},r.prototype={_enqueue:function(e){if(!this._done){if(0===this._requests.length)this._queuedChunk=e;else this._requests.shift().resolve({value:e,done:!1}),this._requests.forEach(function(e){e.resolve({value:void 0,done:!0})}),this._requests=[];this._done=!0,this._stream._removeRangeReader(this)}},get isStreamingSupported(){return!1},read:function(){var e=s(a.default.mark(function e(){var t,r;return a.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(!this._queuedChunk){e.next=4;break}return t=this._queuedChunk,this._queuedChunk=null,e.abrupt("return",{value:t,done:!1});case 4:if(!this._done){e.next=6;break}return e.abrupt("return",{value:void 0,done:!0});case 6:return r=(0,o.createPromiseCapability)(),this._requests.push(r),e.abrupt("return",r.promise);case 9:case"end":return e.stop()}},e,this)}));return function(){return e.apply(this,arguments)}}(),cancel:function(e){this._done=!0,this._requests.forEach(function(e){e.resolve({value:void 0,done:!0})}),this._requests=[],this._stream._removeRangeReader(this)}},e}();t.PDFDataTransportStream=u},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.WebGLContext=void 0;var n=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),i=r(1);var a=function(){function e(t){var r=t.enable,n=void 0!==r&&r;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this._enabled=!0===n}return n(e,[{key:"composeSMask",value:function(e){var t=e.layer,r=e.mask,n=e.properties;return o.composeSMask(t,r,n)}},{key:"drawFigures",value:function(e){var t=e.width,r=e.height,n=e.backgroundColor,i=e.figures,a=e.context;return o.drawFigures(t,r,n,i,a)}},{key:"clear",value:function(){o.cleanup()}},{key:"isEnabled",get:function(){var e=this._enabled;return e&&(e=o.tryInitGL()),(0,i.shadow)(this,"isEnabled",e)}}]),e}(),o=function(){function e(e,t,r){var n=e.createShader(r);if(e.shaderSource(n,t),e.compileShader(n),!e.getShaderParameter(n,e.COMPILE_STATUS)){var i=e.getShaderInfoLog(n);throw new Error("Error during shader compilation: "+i)}return n}function t(t,r){return e(t,r,t.VERTEX_SHADER)}function r(t,r){return e(t,r,t.FRAGMENT_SHADER)}function n(e,t){for(var r=e.createProgram(),n=0,i=t.length;n<i;++n)e.attachShader(r,t[n]);if(e.linkProgram(r),!e.getProgramParameter(r,e.LINK_STATUS)){var a=e.getProgramInfoLog(r);throw new Error("Error during program linking: "+a)}return r}function i(e,t,r){e.activeTexture(r);var n=e.createTexture();return e.bindTexture(e.TEXTURE_2D,n),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,t),n}var a,o;function s(){a||(o=document.createElement("canvas"),a=o.getContext("webgl",{premultipliedalpha:!1}))}var u=" attribute vec2 a_position; attribute vec2 a_texCoord; uniform vec2 u_resolution; varying vec2 v_texCoord; void main() { vec2 clipSpace = (a_position / u_resolution) * 2.0 - 1.0; gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); v_texCoord = a_texCoord; } ",l=" precision mediump float; uniform vec4 u_backdrop; uniform int u_subtype; uniform sampler2D u_image; uniform sampler2D u_mask; varying vec2 v_texCoord; void main() { vec4 imageColor = texture2D(u_image, v_texCoord); vec4 maskColor = texture2D(u_mask, v_texCoord); if (u_backdrop.a > 0.0) { maskColor.rgb = maskColor.rgb * maskColor.a + u_backdrop.rgb * (1.0 - maskColor.a); } float lum; if (u_subtype == 0) { lum = maskColor.a; } else { lum = maskColor.r * 0.3 + maskColor.g * 0.59 + maskColor.b * 0.11; } imageColor.a *= lum; imageColor.rgb *= imageColor.a; gl_FragColor = imageColor; } ",c=null;var h=" attribute vec2 a_position; attribute vec3 a_color; uniform vec2 u_resolution; uniform vec2 u_scale; uniform vec2 u_offset; varying vec4 v_color; void main() { vec2 position = (a_position + u_offset) * u_scale; vec2 clipSpace = (position / u_resolution) * 2.0 - 1.0; gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); v_color = vec4(a_color / 255.0, 1.0); } ",d=" precision mediump float; varying vec4 v_color; void main() { gl_FragColor = v_color; } ",f=null;return{tryInitGL:function(){try{return s(),!!a}catch(e){}return!1},composeSMask:function(e,h,d){var f=e.width,p=e.height;c||function(){var e,i;s(),e=o,o=null,i=a,a=null;var h=n(i,[t(i,u),r(i,l)]);i.useProgram(h);var d={};d.gl=i,d.canvas=e,d.resolutionLocation=i.getUniformLocation(h,"u_resolution"),d.positionLocation=i.getAttribLocation(h,"a_position"),d.backdropLocation=i.getUniformLocation(h,"u_backdrop"),d.subtypeLocation=i.getUniformLocation(h,"u_subtype");var f=i.getAttribLocation(h,"a_texCoord"),p=i.getUniformLocation(h,"u_image"),v=i.getUniformLocation(h,"u_mask"),m=i.createBuffer();i.bindBuffer(i.ARRAY_BUFFER,m),i.bufferData(i.ARRAY_BUFFER,new Float32Array([0,0,1,0,0,1,0,1,1,0,1,1]),i.STATIC_DRAW),i.enableVertexAttribArray(f),i.vertexAttribPointer(f,2,i.FLOAT,!1,0,0),i.uniform1i(p,0),i.uniform1i(v,1),c=d}();var v=c,m=v.canvas,g=v.gl;m.width=f,m.height=p,g.viewport(0,0,g.drawingBufferWidth,g.drawingBufferHeight),g.uniform2f(v.resolutionLocation,f,p),d.backdrop?g.uniform4f(v.resolutionLocation,d.backdrop[0],d.backdrop[1],d.backdrop[2],1):g.uniform4f(v.resolutionLocation,0,0,0,0),g.uniform1i(v.subtypeLocation,"Luminosity"===d.subtype?1:0);var y=i(g,e,g.TEXTURE0),b=i(g,h,g.TEXTURE1),_=g.createBuffer();return g.bindBuffer(g.ARRAY_BUFFER,_),g.bufferData(g.ARRAY_BUFFER,new Float32Array([0,0,f,0,0,p,0,p,f,0,f,p]),g.STATIC_DRAW),g.enableVertexAttribArray(v.positionLocation),g.vertexAttribPointer(v.positionLocation,2,g.FLOAT,!1,0,0),g.clearColor(0,0,0,0),g.enable(g.BLEND),g.blendFunc(g.ONE,g.ONE_MINUS_SRC_ALPHA),g.clear(g.COLOR_BUFFER_BIT),g.drawArrays(g.TRIANGLES,0,6),g.flush(),g.deleteTexture(y),g.deleteTexture(b),g.deleteBuffer(_),m},drawFigures:function(e,i,u,l,c){f||function(){var e,i;s(),e=o,o=null,i=a,a=null;var u=n(i,[t(i,h),r(i,d)]);i.useProgram(u);var l={};l.gl=i,l.canvas=e,l.resolutionLocation=i.getUniformLocation(u,"u_resolution"),l.scaleLocation=i.getUniformLocation(u,"u_scale"),l.offsetLocation=i.getUniformLocation(u,"u_offset"),l.positionLocation=i.getAttribLocation(u,"a_position"),l.colorLocation=i.getAttribLocation(u,"a_color"),f=l}();var p=f,v=p.canvas,m=p.gl;v.width=e,v.height=i,m.viewport(0,0,m.drawingBufferWidth,m.drawingBufferHeight),m.uniform2f(p.resolutionLocation,e,i);var g,y,b,_=0;for(g=0,y=l.length;g<y;g++)switch(l[g].type){case"lattice":_+=((b=l[g].coords.length/l[g].verticesPerRow|0)-1)*(l[g].verticesPerRow-1)*6;break;case"triangles":_+=l[g].coords.length}var A=new Float32Array(2*_),S=new Uint8Array(3*_),w=c.coords,k=c.colors,P=0,x=0;for(g=0,y=l.length;g<y;g++){var C=l[g],R=C.coords,E=C.colors;switch(C.type){case"lattice":var T=C.verticesPerRow;b=R.length/T|0;for(var O=1;O<b;O++)for(var I=O*T+1,F=1;F<T;F++,I++)A[P]=w[R[I-T-1]],A[P+1]=w[R[I-T-1]+1],A[P+2]=w[R[I-T]],A[P+3]=w[R[I-T]+1],A[P+4]=w[R[I-1]],A[P+5]=w[R[I-1]+1],S[x]=k[E[I-T-1]],S[x+1]=k[E[I-T-1]+1],S[x+2]=k[E[I-T-1]+2],S[x+3]=k[E[I-T]],S[x+4]=k[E[I-T]+1],S[x+5]=k[E[I-T]+2],S[x+6]=k[E[I-1]],S[x+7]=k[E[I-1]+1],S[x+8]=k[E[I-1]+2],A[P+6]=A[P+2],A[P+7]=A[P+3],A[P+8]=A[P+4],A[P+9]=A[P+5],A[P+10]=w[R[I]],A[P+11]=w[R[I]+1],S[x+9]=S[x+3],S[x+10]=S[x+4],S[x+11]=S[x+5],S[x+12]=S[x+6],S[x+13]=S[x+7],S[x+14]=S[x+8],S[x+15]=k[E[I]],S[x+16]=k[E[I]+1],S[x+17]=k[E[I]+2],P+=12,x+=18;break;case"triangles":for(var L=0,j=R.length;L<j;L++)A[P]=w[R[L]],A[P+1]=w[R[L]+1],S[x]=k[E[L]],S[x+1]=k[E[L]+1],S[x+2]=k[E[L]+2],P+=2,x+=3}}u?m.clearColor(u[0]/255,u[1]/255,u[2]/255,1):m.clearColor(0,0,0,0),m.clear(m.COLOR_BUFFER_BIT);var M=m.createBuffer();m.bindBuffer(m.ARRAY_BUFFER,M),m.bufferData(m.ARRAY_BUFFER,A,m.STATIC_DRAW),m.enableVertexAttribArray(p.positionLocation),m.vertexAttribPointer(p.positionLocation,2,m.FLOAT,!1,0,0);var D=m.createBuffer();return m.bindBuffer(m.ARRAY_BUFFER,D),m.bufferData(m.ARRAY_BUFFER,S,m.STATIC_DRAW),m.enableVertexAttribArray(p.colorLocation),m.vertexAttribPointer(p.colorLocation,3,m.UNSIGNED_BYTE,!1,0,0),m.uniform2f(p.scaleLocation,c.scaleX,c.scaleY),m.uniform2f(p.offsetLocation,c.offsetX,c.offsetY),m.drawArrays(m.TRIANGLES,0,_),m.flush(),m.deleteBuffer(M),m.deleteBuffer(D),v},cleanup:function(){c&&c.canvas&&(c.canvas.width=0,c.canvas.height=0),f&&f.canvas&&(f.canvas.width=0,f.canvas.height=0),c=null,f=null}}}();t.WebGLContext=a},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.renderTextLayer=void 0;var n,i=r(1),a=r(3),o=(n=a)&&n.__esModule?n:{default:n};var s=function(){var e=1e5,t=/\S/;var r=["left: ",0,"px; top: ",0,"px; font-size: ",0,"px; font-family: ","",";"];function n(e,n,a){var o,s=document.createElement("div"),u={style:null,angle:0,canvasWidth:0,isWhitespace:!1,originalTransform:null,paddingBottom:0,paddingLeft:0,paddingRight:0,paddingTop:0,scale:1};if(e._textDivs.push(s),o=n.str,!t.test(o))return u.isWhitespace=!0,void e._textDivProperties.set(s,u);var l=i.Util.transform(e._viewport.transform,n.transform),c=Math.atan2(l[1],l[0]),h=a[n.fontName];h.vertical&&(c+=Math.PI/2);var d,f,p=Math.sqrt(l[2]*l[2]+l[3]*l[3]),v=p;if(h.ascent?v=h.ascent*v:h.descent&&(v=(1+h.descent)*v),0===c?(d=l[4],f=l[5]-v):(d=l[4]+v*Math.sin(c),f=l[5]-v*Math.cos(c)),r[1]=d,r[3]=f,r[5]=p,r[7]=h.fontFamily,u.style=r.join(""),s.setAttribute("style",u.style),s.textContent=n.str,e._fontInspectorEnabled&&(s.dataset.fontName=n.fontName),0!==c&&(u.angle=c*(180/Math.PI)),n.str.length>1&&(h.vertical?u.canvasWidth=n.height*e._viewport.scale:u.canvasWidth=n.width*e._viewport.scale),e._textDivProperties.set(s,u),e._textContentStream&&e._layoutText(s),e._enhanceTextSelection){var m=1,g=0;0!==c&&(m=Math.cos(c),g=Math.sin(c));var y,b,_=(h.vertical?n.height:n.width)*e._viewport.scale,A=p;0!==c?(y=[m,g,-g,m,d,f],b=i.Util.getAxialAlignedBoundingBox([0,0,_,A],y)):b=[d,f,d+_,f+A],e._bounds.push({left:b[0],top:b[1],right:b[2],bottom:b[3],div:s,size:[_,A],m:y})}}function a(t){if(!t._canceled){var r=t._textDivs,n=t._capability,i=r.length;if(i>e)return t._renderingDone=!0,void n.resolve();if(!t._textContentStream)for(var a=0;a<i;a++)t._layoutText(r[a]);t._renderingDone=!0,n.resolve()}}function s(e){for(var t=e._bounds,r=e._viewport,n=function(e,t,r){var n=r.map(function(e,t){return{x1:e.left,y1:e.top,x2:e.right,y2:e.bottom,index:t,x1New:void 0,x2New:void 0}});u(e,n);var i=new Array(r.length);return n.forEach(function(e){var t=e.index;i[t]={left:e.x1New,top:0,right:e.x2New,bottom:0}}),r.map(function(t,r){var a=i[r],o=n[r];o.x1=t.top,o.y1=e-a.right,o.x2=t.bottom,o.y2=e-a.left,o.index=r,o.x1New=void 0,o.x2New=void 0}),u(t,n),n.forEach(function(e){var t=e.index;i[t].top=e.x1New,i[t].bottom=e.x2New}),i}(r.width,r.height,t),a=0;a<n.length;a++){var o=t[a].div,s=e._textDivProperties.get(o);if(0!==s.angle){var l=n[a],c=t[a],h=c.m,d=h[0],f=h[1],p=[[0,0],[0,c.size[1]],[c.size[0],0],c.size],v=new Float64Array(64);p.forEach(function(e,t){var r=i.Util.applyTransform(e,h);v[t+0]=d&&(l.left-r[0])/d,v[t+4]=f&&(l.top-r[1])/f,v[t+8]=d&&(l.right-r[0])/d,v[t+12]=f&&(l.bottom-r[1])/f,v[t+16]=f&&(l.left-r[0])/-f,v[t+20]=d&&(l.top-r[1])/d,v[t+24]=f&&(l.right-r[0])/-f,v[t+28]=d&&(l.bottom-r[1])/d,v[t+32]=d&&(l.left-r[0])/-d,v[t+36]=f&&(l.top-r[1])/-f,v[t+40]=d&&(l.right-r[0])/-d,v[t+44]=f&&(l.bottom-r[1])/-f,v[t+48]=f&&(l.left-r[0])/f,v[t+52]=d&&(l.top-r[1])/-d,v[t+56]=f&&(l.right-r[0])/f,v[t+60]=d&&(l.bottom-r[1])/-d});var m=function(e,t,r){for(var n=0,i=0;i<r;i++){var a=e[t++];a>0&&(n=n?Math.min(a,n):a)}return n},g=1+Math.min(Math.abs(d),Math.abs(f));s.paddingLeft=m(v,32,16)/g,s.paddingTop=m(v,48,16)/g,s.paddingRight=m(v,0,16)/g,s.paddingBottom=m(v,16,16)/g,e._textDivProperties.set(o,s)}else s.paddingLeft=t[a].left-n[a].left,s.paddingTop=t[a].top-n[a].top,s.paddingRight=n[a].right-t[a].right,s.paddingBottom=n[a].bottom-t[a].bottom,e._textDivProperties.set(o,s)}}function u(e,t){t.sort(function(e,t){return e.x1-t.x1||e.index-t.index});var r=[{start:-1/0,end:1/0,boundary:{x1:-1/0,y1:-1/0,x2:0,y2:1/0,index:-1,x1New:0,x2New:0}}];t.forEach(function(e){for(var t=0;t<r.length&&r[t].end<=e.y1;)t++;for(var n,i,a=r.length-1;a>=0&&r[a].start>=e.y2;)a--;var o,s,u=-1/0;for(o=t;o<=a;o++){var l;(l=(i=(n=r[o]).boundary).x2>e.x1?i.index>e.index?i.x1New:e.x1:void 0===i.x2New?(i.x2+e.x1)/2:i.x2New)>u&&(u=l)}for(e.x1New=u,o=t;o<=a;o++)void 0===(i=(n=r[o]).boundary).x2New?i.x2>e.x1?i.index>e.index&&(i.x2New=i.x2):i.x2New=u:i.x2New>u&&(i.x2New=Math.max(u,i.x2));var c=[],h=null;for(o=t;o<=a;o++){var d=(i=(n=r[o]).boundary).x2>e.x2?i:e;h===d?c[c.length-1].end=n.end:(c.push({start:n.start,end:n.end,boundary:d}),h=d)}for(r[t].start<e.y1&&(c[0].start=e.y1,c.unshift({start:r[t].start,end:e.y1,boundary:r[t].boundary})),e.y2<r[a].end&&(c[c.length-1].end=e.y2,c.push({start:e.y2,end:r[a].end,boundary:r[a].boundary})),o=t;o<=a;o++)if(void 0===(i=(n=r[o]).boundary).x2New){var f=!1;for(s=t-1;!f&&s>=0&&r[s].start>=i.y1;s--)f=r[s].boundary===i;for(s=a+1;!f&&s<r.length&&r[s].end<=i.y2;s++)f=r[s].boundary===i;for(s=0;!f&&s<c.length;s++)f=c[s].boundary===i;f||(i.x2New=u)}Array.prototype.splice.apply(r,[t,a-t+1].concat(c))}),r.forEach(function(t){var r=t.boundary;void 0===r.x2New&&(r.x2New=Math.max(e,r.x2))})}function l(e){var t=e.textContent,r=e.textContentStream,n=e.container,a=e.viewport,s=e.textDivs,u=e.textContentItemsStr,l=e.enhanceTextSelection;this._textContent=t,this._textContentStream=r,this._container=n,this._viewport=a,this._textDivs=s||[],this._textContentItemsStr=u||[],this._enhanceTextSelection=!!l,this._fontInspectorEnabled=!(!o.default.FontInspector||!o.default.FontInspector.enabled),this._reader=null,this._layoutTextLastFontSize=null,this._layoutTextLastFontFamily=null,this._layoutTextCtx=null,this._textDivProperties=new WeakMap,this._renderingDone=!1,this._canceled=!1,this._capability=(0,i.createPromiseCapability)(),this._renderTimer=null,this._bounds=[]}return l.prototype={get promise(){return this._capability.promise},cancel:function(){this._reader&&(this._reader.cancel(new i.AbortException("text layer task cancelled")),this._reader=null),this._canceled=!0,null!==this._renderTimer&&(clearTimeout(this._renderTimer),this._renderTimer=null),this._capability.reject("canceled")},_processItems:function(e,t){for(var r=0,i=e.length;r<i;r++)this._textContentItemsStr.push(e[r].str),n(this,e[r],t)},_layoutText:function(e){var t=this._container,r=this._textDivProperties.get(e);if(!r.isWhitespace){var n=e.style.fontSize,i=e.style.fontFamily;n===this._layoutTextLastFontSize&&i===this._layoutTextLastFontFamily||(this._layoutTextCtx.font=n+" "+i,this._layoutTextLastFontSize=n,this._layoutTextLastFontFamily=i);var a=this._layoutTextCtx.measureText(e.textContent).width,o="";0!==r.canvasWidth&&a>0&&(r.scale=r.canvasWidth/a,o="scaleX("+r.scale+")"),0!==r.angle&&(o="rotate("+r.angle+"deg) "+o),""!==o&&(r.originalTransform=o,e.style.transform=o),this._textDivProperties.set(e,r),t.appendChild(e)}},_render:function(e){var t=this,r=(0,i.createPromiseCapability)(),n=Object.create(null),o=document.createElement("canvas");if(o.mozOpaque=!0,this._layoutTextCtx=o.getContext("2d",{alpha:!1}),this._textContent){var s=this._textContent.items,u=this._textContent.styles;this._processItems(s,u),r.resolve()}else{if(!this._textContentStream)throw new Error('Neither "textContent" nor "textContentStream" parameters specified.');this._reader=this._textContentStream.getReader(),function e(){t._reader.read().then(function(i){var a=i.value;i.done?r.resolve():(Object.assign(n,a.styles),t._processItems(a.items,n),e())},r.reject)}()}r.promise.then(function(){n=null,e?t._renderTimer=setTimeout(function(){a(t),t._renderTimer=null},e):a(t)},this._capability.reject)},expandTextDivs:function(e){if(this._enhanceTextSelection&&this._renderingDone){null!==this._bounds&&(s(this),this._bounds=null);for(var t=0,r=this._textDivs.length;t<r;t++){var n=this._textDivs[t],i=this._textDivProperties.get(n);if(!i.isWhitespace)if(e){var a="",o="";1!==i.scale&&(a="scaleX("+i.scale+")"),0!==i.angle&&(a="rotate("+i.angle+"deg) "+a),0!==i.paddingLeft&&(o+=" padding-left: "+i.paddingLeft/i.scale+"px;",a+=" translateX("+-i.paddingLeft/i.scale+"px)"),0!==i.paddingTop&&(o+=" padding-top: "+i.paddingTop+"px;",a+=" translateY("+-i.paddingTop+"px)"),0!==i.paddingRight&&(o+=" padding-right: "+i.paddingRight/i.scale+"px;"),0!==i.paddingBottom&&(o+=" padding-bottom: "+i.paddingBottom+"px;"),""!==o&&n.setAttribute("style",i.style+o),""!==a&&(n.style.transform=a)}else n.style.padding=0,n.style.transform=i.originalTransform||""}}}},function(e){var t=new l({textContent:e.textContent,textContentStream:e.textContentStream,container:e.container,viewport:e.viewport,textDivs:e.textDivs,textContentItemsStr:e.textContentItemsStr,enhanceTextSelection:e.enhanceTextSelection});return t._render(e.timeout),t}}();t.renderTextLayer=s},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.AnnotationLayer=void 0;var n=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),i=r(130),a=r(1);function o(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function u(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var l=function(){function e(){u(this,e)}return n(e,null,[{key:"create",value:function(e){switch(e.data.annotationType){case a.AnnotationType.LINK:return new h(e);case a.AnnotationType.TEXT:return new d(e);case a.AnnotationType.WIDGET:switch(e.data.fieldType){case"Tx":return new p(e);case"Btn":return e.data.radioButton?new m(e):e.data.checkBox?new v(e):new g(e);case"Ch":return new y(e)}return new f(e);case a.AnnotationType.POPUP:return new b(e);case a.AnnotationType.LINE:return new A(e);case a.AnnotationType.SQUARE:return new S(e);case a.AnnotationType.CIRCLE:return new w(e);case a.AnnotationType.POLYLINE:return new k(e);case a.AnnotationType.INK:return new x(e);case a.AnnotationType.POLYGON:return new P(e);case a.AnnotationType.HIGHLIGHT:return new C(e);case a.AnnotationType.UNDERLINE:return new R(e);case a.AnnotationType.SQUIGGLY:return new E(e);case a.AnnotationType.STRIKEOUT:return new T(e);case a.AnnotationType.STAMP:return new O(e);case a.AnnotationType.FILEATTACHMENT:return new I(e);default:return new c(e)}}}]),e}(),c=function(){function e(t){var r=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];u(this,e),this.isRenderable=r,this.data=t.data,this.layer=t.layer,this.page=t.page,this.viewport=t.viewport,this.linkService=t.linkService,this.downloadManager=t.downloadManager,this.imageResourcesPath=t.imageResourcesPath,this.renderInteractiveForms=t.renderInteractiveForms,this.svgFactory=t.svgFactory,r&&(this.container=this._createContainer(n))}return n(e,[{key:"_createContainer",value:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=this.data,r=this.page,n=this.viewport,i=document.createElement("section"),o=t.rect[2]-t.rect[0],s=t.rect[3]-t.rect[1];i.setAttribute("data-annotation-id",t.id);var u=a.Util.normalizeRect([t.rect[0],r.view[3]-t.rect[1]+r.view[1],t.rect[2],r.view[3]-t.rect[3]+r.view[1]]);if(i.style.transform="matrix("+n.transform.join(",")+")",i.style.transformOrigin=-u[0]+"px "+-u[1]+"px",!e&&t.borderStyle.width>0){i.style.borderWidth=t.borderStyle.width+"px",t.borderStyle.style!==a.AnnotationBorderStyleType.UNDERLINE&&(o-=2*t.borderStyle.width,s-=2*t.borderStyle.width);var l=t.borderStyle.horizontalCornerRadius,c=t.borderStyle.verticalCornerRadius;if(l>0||c>0){var h=l+"px / "+c+"px";i.style.borderRadius=h}switch(t.borderStyle.style){case a.AnnotationBorderStyleType.SOLID:i.style.borderStyle="solid";break;case a.AnnotationBorderStyleType.DASHED:i.style.borderStyle="dashed";break;case a.AnnotationBorderStyleType.BEVELED:(0,a.warn)("Unimplemented border style: beveled");break;case a.AnnotationBorderStyleType.INSET:(0,a.warn)("Unimplemented border style: inset");break;case a.AnnotationBorderStyleType.UNDERLINE:i.style.borderBottomStyle="solid"}t.color?i.style.borderColor=a.Util.makeCssRgb(0|t.color[0],0|t.color[1],0|t.color[2]):i.style.borderWidth=0}return i.style.left=u[0]+"px",i.style.top=u[1]+"px",i.style.width=o+"px",i.style.height=s+"px",i}},{key:"_createPopup",value:function(e,t,r){t||((t=document.createElement("div")).style.height=e.style.height,t.style.width=e.style.width,e.appendChild(t));var n=new _({container:e,trigger:t,color:r.color,title:r.title,contents:r.contents,hideWrapper:!0}).render();n.style.left=e.style.width,e.appendChild(n)}},{key:"render",value:function(){(0,a.unreachable)("Abstract method `AnnotationElement.render` called")}}]),e}(),h=function(e){function t(e){u(this,t);var r=!!(e.data.url||e.data.dest||e.data.action);return o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r))}return s(t,c),n(t,[{key:"render",value:function(){this.container.className="linkAnnotation";var e=this.data,t=this.linkService,r=document.createElement("a");return(0,i.addLinkAttributes)(r,{url:e.url,target:e.newWindow?i.LinkTarget.BLANK:t.externalLinkTarget,rel:t.externalLinkRel}),e.url||(e.action?this._bindNamedAction(r,e.action):this._bindLink(r,e.dest)),this.container.appendChild(r),this.container}},{key:"_bindLink",value:function(e,t){var r=this;e.href=this.linkService.getDestinationHash(t),e.onclick=function(){return t&&r.linkService.navigateTo(t),!1},t&&(e.className="internalLink")}},{key:"_bindNamedAction",value:function(e,t){var r=this;e.href=this.linkService.getAnchorUrl(""),e.onclick=function(){return r.linkService.executeNamedAction(t),!1},e.className="internalLink"}}]),t}(),d=function(e){function t(e){u(this,t);var r=!!(e.data.hasPopup||e.data.title||e.data.contents);return o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r))}return s(t,c),n(t,[{key:"render",value:function(){this.container.className="textAnnotation";var e=document.createElement("img");return e.style.height=this.container.style.height,e.style.width=this.container.style.width,e.src=this.imageResourcesPath+"annotation-"+this.data.name.toLowerCase()+".svg",e.alt="[{{type}} Annotation]",e.dataset.l10nId="text_annotation_type",e.dataset.l10nArgs=JSON.stringify({type:this.data.name}),this.data.hasPopup||this._createPopup(this.container,e,this.data),this.container.appendChild(e),this.container}}]),t}(),f=function(e){function t(){return u(this,t),o(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments))}return s(t,c),n(t,[{key:"render",value:function(){return this.container}}]),t}(),p=function(e){function t(e){u(this,t);var r=e.renderInteractiveForms||!e.data.hasAppearance&&!!e.data.fieldValue;return o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r))}return s(t,f),n(t,[{key:"render",value:function(){this.container.className="textWidgetAnnotation";var e=null;if(this.renderInteractiveForms){if(this.data.multiLine?(e=document.createElement("textarea")).textContent=this.data.fieldValue:((e=document.createElement("input")).type="text",e.setAttribute("value",this.data.fieldValue)),e.disabled=this.data.readOnly,null!==this.data.maxLen&&(e.maxLength=this.data.maxLen),this.data.comb){var t=(this.data.rect[2]-this.data.rect[0])/this.data.maxLen;e.classList.add("comb"),e.style.letterSpacing="calc("+t+"px - 1ch)"}}else{(e=document.createElement("div")).textContent=this.data.fieldValue,e.style.verticalAlign="middle",e.style.display="table-cell";var r=null;this.data.fontRefName&&(r=this.page.commonObjs.getData(this.data.fontRefName)),this._setTextStyle(e,r)}return null!==this.data.textAlignment&&(e.style.textAlign=["left","center","right"][this.data.textAlignment]),this.container.appendChild(e),this.container}},{key:"_setTextStyle",value:function(e,t){var r=e.style;if(r.fontSize=this.data.fontSize+"px",r.direction=this.data.fontDirection<0?"rtl":"ltr",t){r.fontWeight=t.black?t.bold?"900":"bold":t.bold?"bold":"normal",r.fontStyle=t.italic?"italic":"normal";var n=t.loadedName?'"'+t.loadedName+'", ':"",i=t.fallbackName||"Helvetica, sans-serif";r.fontFamily=n+i}}}]),t}(),v=function(e){function t(e){return u(this,t),o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,e.renderInteractiveForms))}return s(t,f),n(t,[{key:"render",value:function(){this.container.className="buttonWidgetAnnotation checkBox";var e=document.createElement("input");return e.disabled=this.data.readOnly,e.type="checkbox",this.data.fieldValue&&"Off"!==this.data.fieldValue&&e.setAttribute("checked",!0),this.container.appendChild(e),this.container}}]),t}(),m=function(e){function t(e){return u(this,t),o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,e.renderInteractiveForms))}return s(t,f),n(t,[{key:"render",value:function(){this.container.className="buttonWidgetAnnotation radioButton";var e=document.createElement("input");return e.disabled=this.data.readOnly,e.type="radio",e.name=this.data.fieldName,this.data.fieldValue===this.data.buttonValue&&e.setAttribute("checked",!0),this.container.appendChild(e),this.container}}]),t}(),g=function(e){function t(){return u(this,t),o(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments))}return s(t,h),n(t,[{key:"render",value:function(){var e=function e(t,r,n){null===t&&(t=Function.prototype);var i=Object.getOwnPropertyDescriptor(t,r);if(void 0===i){var a=Object.getPrototypeOf(t);return null===a?void 0:e(a,r,n)}if("value"in i)return i.value;var o=i.get;return void 0!==o?o.call(n):void 0}(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"render",this).call(this);return e.className="buttonWidgetAnnotation pushButton",e}}]),t}(),y=function(e){function t(e){return u(this,t),o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,e.renderInteractiveForms))}return s(t,f),n(t,[{key:"render",value:function(){this.container.className="choiceWidgetAnnotation";var e=document.createElement("select");e.disabled=this.data.readOnly,this.data.combo||(e.size=this.data.options.length,this.data.multiSelect&&(e.multiple=!0));for(var t=0,r=this.data.options.length;t<r;t++){var n=this.data.options[t],i=document.createElement("option");i.textContent=n.displayValue,i.value=n.exportValue,this.data.fieldValue.includes(n.displayValue)&&i.setAttribute("selected",!0),e.appendChild(i)}return this.container.appendChild(e),this.container}}]),t}(),b=function(e){function t(e){u(this,t);var r=!(!e.data.title&&!e.data.contents);return o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r))}return s(t,c),n(t,[{key:"render",value:function(){if(this.container.className="popupAnnotation",["Line","Square","Circle","PolyLine","Polygon","Ink"].includes(this.data.parentType))return this.container;var e='[data-annotation-id="'+this.data.parentId+'"]',t=this.layer.querySelector(e);if(!t)return this.container;var r=new _({container:this.container,trigger:t,color:this.data.color,title:this.data.title,contents:this.data.contents}),n=parseFloat(t.style.left),i=parseFloat(t.style.width);return this.container.style.transformOrigin=-(n+i)+"px -"+t.style.top,this.container.style.left=n+i+"px",this.container.appendChild(r.render()),this.container}}]),t}(),_=function(){function e(t){u(this,e),this.container=t.container,this.trigger=t.trigger,this.color=t.color,this.title=t.title,this.contents=t.contents,this.hideWrapper=t.hideWrapper||!1,this.pinned=!1}return n(e,[{key:"render",value:function(){var e=document.createElement("div");e.className="popupWrapper",this.hideElement=this.hideWrapper?e:this.container,this.hideElement.setAttribute("hidden",!0);var t=document.createElement("div");t.className="popup";var r=this.color;if(r){var n=.7*(255-r[0])+r[0],i=.7*(255-r[1])+r[1],o=.7*(255-r[2])+r[2];t.style.backgroundColor=a.Util.makeCssRgb(0|n,0|i,0|o)}var s=this._formatContents(this.contents),u=document.createElement("h1");return u.textContent=this.title,this.trigger.addEventListener("click",this._toggle.bind(this)),this.trigger.addEventListener("mouseover",this._show.bind(this,!1)),this.trigger.addEventListener("mouseout",this._hide.bind(this,!1)),t.addEventListener("click",this._hide.bind(this,!0)),t.appendChild(u),t.appendChild(s),e.appendChild(t),e}},{key:"_formatContents",value:function(e){for(var t=document.createElement("p"),r=e.split(/(?:\r\n?|\n)/),n=0,i=r.length;n<i;++n){var a=r[n];t.appendChild(document.createTextNode(a)),n<i-1&&t.appendChild(document.createElement("br"))}return t}},{key:"_toggle",value:function(){this.pinned?this._hide(!0):this._show(!0)}},{key:"_show",value:function(){arguments.length>0&&void 0!==arguments[0]&&arguments[0]&&(this.pinned=!0),this.hideElement.hasAttribute("hidden")&&(this.hideElement.removeAttribute("hidden"),this.container.style.zIndex+=1)}},{key:"_hide",value:function(){(!(arguments.length>0&&void 0!==arguments[0])||arguments[0])&&(this.pinned=!1),this.hideElement.hasAttribute("hidden")||this.pinned||(this.hideElement.setAttribute("hidden",!0),this.container.style.zIndex-=1)}}]),e}(),A=function(e){function t(e){u(this,t);var r=!!(e.data.hasPopup||e.data.title||e.data.contents);return o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r,!0))}return s(t,c),n(t,[{key:"render",value:function(){this.container.className="lineAnnotation";var e=this.data,t=e.rect[2]-e.rect[0],r=e.rect[3]-e.rect[1],n=this.svgFactory.create(t,r),i=this.svgFactory.createElement("svg:line");return i.setAttribute("x1",e.rect[2]-e.lineCoordinates[0]),i.setAttribute("y1",e.rect[3]-e.lineCoordinates[1]),i.setAttribute("x2",e.rect[2]-e.lineCoordinates[2]),i.setAttribute("y2",e.rect[3]-e.lineCoordinates[3]),i.setAttribute("stroke-width",e.borderStyle.width),i.setAttribute("stroke","transparent"),n.appendChild(i),this.container.append(n),this._createPopup(this.container,i,e),this.container}}]),t}(),S=function(e){function t(e){u(this,t);var r=!!(e.data.hasPopup||e.data.title||e.data.contents);return o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r,!0))}return s(t,c),n(t,[{key:"render",value:function(){this.container.className="squareAnnotation";var e=this.data,t=e.rect[2]-e.rect[0],r=e.rect[3]-e.rect[1],n=this.svgFactory.create(t,r),i=e.borderStyle.width,a=this.svgFactory.createElement("svg:rect");return a.setAttribute("x",i/2),a.setAttribute("y",i/2),a.setAttribute("width",t-i),a.setAttribute("height",r-i),a.setAttribute("stroke-width",i),a.setAttribute("stroke","transparent"),a.setAttribute("fill","none"),n.appendChild(a),this.container.append(n),this._createPopup(this.container,a,e),this.container}}]),t}(),w=function(e){function t(e){u(this,t);var r=!!(e.data.hasPopup||e.data.title||e.data.contents);return o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r,!0))}return s(t,c),n(t,[{key:"render",value:function(){this.container.className="circleAnnotation";var e=this.data,t=e.rect[2]-e.rect[0],r=e.rect[3]-e.rect[1],n=this.svgFactory.create(t,r),i=e.borderStyle.width,a=this.svgFactory.createElement("svg:ellipse");return a.setAttribute("cx",t/2),a.setAttribute("cy",r/2),a.setAttribute("rx",t/2-i/2),a.setAttribute("ry",r/2-i/2),a.setAttribute("stroke-width",i),a.setAttribute("stroke","transparent"),a.setAttribute("fill","none"),n.appendChild(a),this.container.append(n),this._createPopup(this.container,a,e),this.container}}]),t}(),k=function(e){function t(e){u(this,t);var r=!!(e.data.hasPopup||e.data.title||e.data.contents),n=o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r,!0));return n.containerClassName="polylineAnnotation",n.svgElementName="svg:polyline",n}return s(t,c),n(t,[{key:"render",value:function(){this.container.className=this.containerClassName;for(var e=this.data,t=e.rect[2]-e.rect[0],r=e.rect[3]-e.rect[1],n=this.svgFactory.create(t,r),i=e.vertices,a=[],o=0,s=i.length;o<s;o++){var u=i[o].x-e.rect[0],l=e.rect[3]-i[o].y;a.push(u+","+l)}a=a.join(" ");var c=e.borderStyle.width,h=this.svgFactory.createElement(this.svgElementName);return h.setAttribute("points",a),h.setAttribute("stroke-width",c),h.setAttribute("stroke","transparent"),h.setAttribute("fill","none"),n.appendChild(h),this.container.append(n),this._createPopup(this.container,h,e),this.container}}]),t}(),P=function(e){function t(e){u(this,t);var r=o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return r.containerClassName="polygonAnnotation",r.svgElementName="svg:polygon",r}return s(t,k),t}(),x=function(e){function t(e){u(this,t);var r=!!(e.data.hasPopup||e.data.title||e.data.contents),n=o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r,!0));return n.containerClassName="inkAnnotation",n.svgElementName="svg:polyline",n}return s(t,c),n(t,[{key:"render",value:function(){this.container.className=this.containerClassName;for(var e=this.data,t=e.rect[2]-e.rect[0],r=e.rect[3]-e.rect[1],n=this.svgFactory.create(t,r),i=e.inkLists,a=0,o=i.length;a<o;a++){for(var s=i[a],u=[],l=0,c=s.length;l<c;l++){var h=s[l].x-e.rect[0],d=e.rect[3]-s[l].y;u.push(h+","+d)}u=u.join(" ");var f=e.borderStyle.width,p=this.svgFactory.createElement(this.svgElementName);p.setAttribute("points",u),p.setAttribute("stroke-width",f),p.setAttribute("stroke","transparent"),p.setAttribute("fill","none"),this._createPopup(this.container,p,e),n.appendChild(p)}return this.container.append(n),this.container}}]),t}(),C=function(e){function t(e){u(this,t);var r=!!(e.data.hasPopup||e.data.title||e.data.contents);return o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r,!0))}return s(t,c),n(t,[{key:"render",value:function(){return this.container.className="highlightAnnotation",this.data.hasPopup||this._createPopup(this.container,null,this.data),this.container}}]),t}(),R=function(e){function t(e){u(this,t);var r=!!(e.data.hasPopup||e.data.title||e.data.contents);return o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r,!0))}return s(t,c),n(t,[{key:"render",value:function(){return this.container.className="underlineAnnotation",this.data.hasPopup||this._createPopup(this.container,null,this.data),this.container}}]),t}(),E=function(e){function t(e){u(this,t);var r=!!(e.data.hasPopup||e.data.title||e.data.contents);return o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r,!0))}return s(t,c),n(t,[{key:"render",value:function(){return this.container.className="squigglyAnnotation",this.data.hasPopup||this._createPopup(this.container,null,this.data),this.container}}]),t}(),T=function(e){function t(e){u(this,t);var r=!!(e.data.hasPopup||e.data.title||e.data.contents);return o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r,!0))}return s(t,c),n(t,[{key:"render",value:function(){return this.container.className="strikeoutAnnotation",this.data.hasPopup||this._createPopup(this.container,null,this.data),this.container}}]),t}(),O=function(e){function t(e){u(this,t);var r=!!(e.data.hasPopup||e.data.title||e.data.contents);return o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r,!0))}return s(t,c),n(t,[{key:"render",value:function(){return this.container.className="stampAnnotation",this.data.hasPopup||this._createPopup(this.container,null,this.data),this.container}}]),t}(),I=function(e){function t(e){u(this,t);var r=o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,!0)),n=r.data.file,s=n.filename,l=n.content;return r.filename=(0,i.getFilenameFromUrl)(s),r.content=l,r.linkService.eventBus&&r.linkService.eventBus.dispatch("fileattachmentannotation",{source:r,id:(0,a.stringToPDFString)(s),filename:s,content:l}),r}return s(t,c),n(t,[{key:"render",value:function(){this.container.className="fileAttachmentAnnotation";var e=document.createElement("div");return e.style.height=this.container.style.height,e.style.width=this.container.style.width,e.addEventListener("dblclick",this._download.bind(this)),this.data.hasPopup||!this.data.title&&!this.data.contents||this._createPopup(this.container,e,this.data),this.container.appendChild(e),this.container}},{key:"_download",value:function(){this.downloadManager?this.downloadManager.downloadData(this.content,this.filename,""):(0,a.warn)("Download cannot be started due to unavailable download manager")}}]),t}(),F=function(){function e(){u(this,e)}return n(e,null,[{key:"render",value:function(e){for(var t=0,r=e.annotations.length;t<r;t++){var n=e.annotations[t];if(n){var a=l.create({data:n,layer:e.div,page:e.page,viewport:e.viewport,linkService:e.linkService,downloadManager:e.downloadManager,imageResourcesPath:e.imageResourcesPath||"",renderInteractiveForms:e.renderInteractiveForms||!1,svgFactory:new i.DOMSVGFactory});a.isRenderable&&e.div.appendChild(a.render())}}}},{key:"update",value:function(e){for(var t=0,r=e.annotations.length;t<r;t++){var n=e.annotations[t],i=e.div.querySelector('[data-annotation-id="'+n.id+'"]');i&&(i.style.transform="matrix("+e.viewport.transform.join(",")+")")}e.div.removeAttribute("hidden")}}]),e}();t.AnnotationLayer=F},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.SVGGraphics=void 0;var n,i=r(1),a=r(130),o=r(4),s=(n=o)&&n.__esModule?n:{default:n};var u,l={fontStyle:"normal",fontWeight:"normal",fillColor:"#000000"},c=function(){for(var e=new Uint8Array([137,80,78,71,13,10,26,10]),t=12,r=new Int32Array(256),n=0;n<256;n++){for(var a=n,o=0;o<8;o++)a=1&a?3988292384^a>>1&2147483647:a>>1&2147483647;r[n]=a}function u(e,t,n,i){var a=i,o=t.length;n[a]=o>>24&255,n[a+1]=o>>16&255,n[a+2]=o>>8&255,n[a+3]=255&o,n[a+=4]=255&e.charCodeAt(0),n[a+1]=255&e.charCodeAt(1),n[a+2]=255&e.charCodeAt(2),n[a+3]=255&e.charCodeAt(3),a+=4,n.set(t,a);var s=function(e,t,n){for(var i=-1,a=t;a<n;a++){var o=255&(i^e[a]);i=i>>>8^r[o]}return-1^i}(n,i+4,a+=t.length);n[a]=s>>24&255,n[a+1]=s>>16&255,n[a+2]=s>>8&255,n[a+3]=255&s}function l(e){var t=e.length,r=Math.ceil(t/65535),n=new Uint8Array(2+t+5*r+4),i=0;n[i++]=120,n[i++]=156;for(var a=0;t>65535;)n[i++]=0,n[i++]=255,n[i++]=255,n[i++]=0,n[i++]=0,n.set(e.subarray(a,a+65535),i),i+=65535,a+=65535,t-=65535;n[i++]=1,n[i++]=255&t,n[i++]=t>>8&255,n[i++]=255&~t,n[i++]=(65535&~t)>>8&255,n.set(e.subarray(a),i),i+=e.length-a;var o=function(e,t,r){for(var n=1,i=0,a=t;a<r;++a)i=(i+(n=(n+(255&e[a]))%65521))%65521;return i<<16|n}(e,0,e.length);return n[i++]=o>>24&255,n[i++]=o>>16&255,n[i++]=o>>8&255,n[i++]=255&o,n}function c(r,n,a,o){var c,h,d,f=r.width,p=r.height,v=r.data;switch(n){case i.ImageKind.GRAYSCALE_1BPP:h=0,c=1,d=f+7>>3;break;case i.ImageKind.RGB_24BPP:h=2,c=8,d=3*f;break;case i.ImageKind.RGBA_32BPP:h=6,c=8,d=4*f;break;default:throw new Error("invalid format")}var m,g,y=new Uint8Array((1+d)*p),b=0,_=0;for(m=0;m<p;++m)y[b++]=0,y.set(v.subarray(_,_+d),b),_+=d,b+=d;if(n===i.ImageKind.GRAYSCALE_1BPP&&o)for(b=0,m=0;m<p;m++)for(b++,g=0;g<d;g++)y[b++]^=255;var A=new Uint8Array([f>>24&255,f>>16&255,f>>8&255,255&f,p>>24&255,p>>16&255,p>>8&255,255&p,c,h,0,0,0]),S=function(e){if(!(0,s.default)())return l(e);try{var t;t=parseInt(process.versions.node)>=8?e:new Buffer(e);var r=require("zlib").deflateSync(t,{level:9});return r instanceof Uint8Array?r:new Uint8Array(r)}catch(e){(0,i.warn)("Not compressing PNG because zlib.deflateSync is unavailable: "+e)}return l(e)}(y),w=e.length+3*t+A.length+S.length,k=new Uint8Array(w),P=0;return k.set(e,P),u("IHDR",A,k,P+=e.length),u("IDATA",S,k,P+=t+A.length),P+=t+S.length,u("IEND",new Uint8Array(0),k,P),(0,i.createObjectURL)(k,"image/png",a)}return function(e,t,r){return c(e,void 0===e.kind?i.ImageKind.GRAYSCALE_1BPP:e.kind,t,r)}}(),h=function(){function e(){this.fontSizeScale=1,this.fontWeight=l.fontWeight,this.fontSize=0,this.textMatrix=i.IDENTITY_MATRIX,this.fontMatrix=i.FONT_IDENTITY_MATRIX,this.leading=0,this.textRenderingMode=i.TextRenderingMode.FILL,this.x=0,this.y=0,this.lineX=0,this.lineY=0,this.charSpacing=0,this.wordSpacing=0,this.textHScale=1,this.textRise=0,this.fillColor=l.fillColor,this.strokeColor="#000000",this.fillAlpha=1,this.strokeAlpha=1,this.lineWidth=1,this.lineJoin="",this.lineCap="",this.miterLimit=0,this.dashArray=[],this.dashPhase=0,this.dependencies=[],this.activeClipUrl=null,this.clipGroup=null,this.maskId=""}return e.prototype={clone:function(){return Object.create(this)},setCurrentPoint:function(e,t){this.x=e,this.y=t}},e}();t.SVGGraphics=u=function(){function e(e){if(Number.isInteger(e))return e.toString();var t=e.toFixed(10),r=t.length-1;if("0"!==t[r])return t;do{r--}while("0"===t[r]);return t.substring(0,"."===t[r]?r:r+1)}function t(t){if(0===t[4]&&0===t[5]){if(0===t[1]&&0===t[2])return 1===t[0]&&1===t[3]?"":"scale("+e(t[0])+" "+e(t[3])+")";if(t[0]===t[3]&&t[1]===-t[2])return"rotate("+e(180*Math.acos(t[0])/Math.PI)+")"}else if(1===t[0]&&0===t[1]&&0===t[2]&&1===t[3])return"translate("+e(t[4])+" "+e(t[5])+")";return"matrix("+e(t[0])+" "+e(t[1])+" "+e(t[2])+" "+e(t[3])+" "+e(t[4])+" "+e(t[5])+")"}function r(e,t,r){this.svgFactory=new a.DOMSVGFactory,this.current=new h,this.transformMatrix=i.IDENTITY_MATRIX,this.transformStack=[],this.extraStack=[],this.commonObjs=e,this.objs=t,this.pendingClip=null,this.pendingEOFill=!1,this.embedFonts=!1,this.embeddedFonts=Object.create(null),this.cssStyle=null,this.forceDataSchema=!!r}var n="http://www.w3.org/1999/xlink",o=["butt","round","square"],s=["miter","round","bevel"],u=0,d=0;return r.prototype={save:function(){this.transformStack.push(this.transformMatrix);var e=this.current;this.extraStack.push(e),this.current=e.clone()},restore:function(){this.transformMatrix=this.transformStack.pop(),this.current=this.extraStack.pop(),this.pendingClip=null,this.tgrp=null},group:function(e){this.save(),this.executeOpTree(e),this.restore()},loadDependencies:function(e){for(var t=this,r=e.fnArray,n=r.length,a=e.argsArray,o=0;o<n;o++)if(i.OPS.dependency===r[o])for(var s=a[o],u=0,l=s.length;u<l;u++){var c,h=s[u];c="g_"===h.substring(0,2)?new Promise(function(e){t.commonObjs.get(h,e)}):new Promise(function(e){t.objs.get(h,e)}),this.current.dependencies.push(c)}return Promise.all(this.current.dependencies)},transform:function(e,t,r,n,a,o){var s=[e,t,r,n,a,o];this.transformMatrix=i.Util.transform(this.transformMatrix,s),this.tgrp=null},getSVG:function(e,t){var r=this;this.viewport=t;var n=this._initialize(t);return this.loadDependencies(e).then(function(){r.transformMatrix=i.IDENTITY_MATRIX;var t=r.convertOpList(e);return r.executeOpTree(t),n})},convertOpList:function(e){var t=e.argsArray,r=e.fnArray,n=r.length,a=[],o=[];for(var s in i.OPS)a[i.OPS[s]]=s;for(var u=0;u<n;u++){var l=r[u];o.push({fnId:l,fn:a[l],args:t[u]})}return function(e){for(var t=[],r=[],n=e.length,i=0;i<n;i++)"save"!==e[i].fn?"restore"===e[i].fn?t=r.pop():t.push(e[i]):(t.push({fnId:92,fn:"group",items:[]}),r.push(t),t=t[t.length-1].items);return t}(o)},executeOpTree:function(e){for(var t=e.length,r=0;r<t;r++){var n=e[r].fn,a=e[r].fnId,o=e[r].args;switch(0|a){case i.OPS.beginText:this.beginText();break;case i.OPS.dependency:break;case i.OPS.setLeading:this.setLeading(o);break;case i.OPS.setLeadingMoveText:this.setLeadingMoveText(o[0],o[1]);break;case i.OPS.setFont:this.setFont(o);break;case i.OPS.showText:case i.OPS.showSpacedText:this.showText(o[0]);break;case i.OPS.endText:this.endText();break;case i.OPS.moveText:this.moveText(o[0],o[1]);break;case i.OPS.setCharSpacing:this.setCharSpacing(o[0]);break;case i.OPS.setWordSpacing:this.setWordSpacing(o[0]);break;case i.OPS.setHScale:this.setHScale(o[0]);break;case i.OPS.setTextMatrix:this.setTextMatrix(o[0],o[1],o[2],o[3],o[4],o[5]);break;case i.OPS.setTextRise:this.setTextRise(o[0]);break;case i.OPS.setTextRenderingMode:this.setTextRenderingMode(o[0]);break;case i.OPS.setLineWidth:this.setLineWidth(o[0]);break;case i.OPS.setLineJoin:this.setLineJoin(o[0]);break;case i.OPS.setLineCap:this.setLineCap(o[0]);break;case i.OPS.setMiterLimit:this.setMiterLimit(o[0]);break;case i.OPS.setFillRGBColor:this.setFillRGBColor(o[0],o[1],o[2]);break;case i.OPS.setStrokeRGBColor:this.setStrokeRGBColor(o[0],o[1],o[2]);break;case i.OPS.setDash:this.setDash(o[0],o[1]);break;case i.OPS.setGState:this.setGState(o[0]);break;case i.OPS.fill:this.fill();break;case i.OPS.eoFill:this.eoFill();break;case i.OPS.stroke:this.stroke();break;case i.OPS.fillStroke:this.fillStroke();break;case i.OPS.eoFillStroke:this.eoFillStroke();break;case i.OPS.clip:this.clip("nonzero");break;case i.OPS.eoClip:this.clip("evenodd");break;case i.OPS.paintSolidColorImageMask:this.paintSolidColorImageMask();break;case i.OPS.paintJpegXObject:this.paintJpegXObject(o[0],o[1],o[2]);break;case i.OPS.paintImageXObject:this.paintImageXObject(o[0]);break;case i.OPS.paintInlineImageXObject:this.paintInlineImageXObject(o[0]);break;case i.OPS.paintImageMaskXObject:this.paintImageMaskXObject(o[0]);break;case i.OPS.paintFormXObjectBegin:this.paintFormXObjectBegin(o[0],o[1]);break;case i.OPS.paintFormXObjectEnd:this.paintFormXObjectEnd();break;case i.OPS.closePath:this.closePath();break;case i.OPS.closeStroke:this.closeStroke();break;case i.OPS.closeFillStroke:this.closeFillStroke();break;case i.OPS.closeEOFillStroke:this.closeEOFillStroke();break;case i.OPS.nextLine:this.nextLine();break;case i.OPS.transform:this.transform(o[0],o[1],o[2],o[3],o[4],o[5]);break;case i.OPS.constructPath:this.constructPath(o[0],o[1]);break;case i.OPS.endPath:this.endPath();break;case 92:this.group(e[r].items);break;default:(0,i.warn)("Unimplemented operator "+n)}}},setWordSpacing:function(e){this.current.wordSpacing=e},setCharSpacing:function(e){this.current.charSpacing=e},nextLine:function(){this.moveText(0,this.current.leading)},setTextMatrix:function(t,r,n,i,a,o){var s=this.current;this.current.textMatrix=this.current.lineMatrix=[t,r,n,i,a,o],this.current.x=this.current.lineX=0,this.current.y=this.current.lineY=0,s.xcoords=[],s.tspan=this.svgFactory.createElement("svg:tspan"),s.tspan.setAttributeNS(null,"font-family",s.fontFamily),s.tspan.setAttributeNS(null,"font-size",e(s.fontSize)+"px"),s.tspan.setAttributeNS(null,"y",e(-s.y)),s.txtElement=this.svgFactory.createElement("svg:text"),s.txtElement.appendChild(s.tspan)},beginText:function(){this.current.x=this.current.lineX=0,this.current.y=this.current.lineY=0,this.current.textMatrix=i.IDENTITY_MATRIX,this.current.lineMatrix=i.IDENTITY_MATRIX,this.current.tspan=this.svgFactory.createElement("svg:tspan"),this.current.txtElement=this.svgFactory.createElement("svg:text"),this.current.txtgrp=this.svgFactory.createElement("svg:g"),this.current.xcoords=[]},moveText:function(t,r){var n=this.current;this.current.x=this.current.lineX+=t,this.current.y=this.current.lineY+=r,n.xcoords=[],n.tspan=this.svgFactory.createElement("svg:tspan"),n.tspan.setAttributeNS(null,"font-family",n.fontFamily),n.tspan.setAttributeNS(null,"font-size",e(n.fontSize)+"px"),n.tspan.setAttributeNS(null,"y",e(-n.y))},showText:function(r){var n=this.current,a=n.font,o=n.fontSize;if(0!==o){var s,u=n.charSpacing,c=n.wordSpacing,h=n.fontDirection,d=n.textHScale*h,f=r.length,p=a.vertical,v=o*n.fontMatrix[0],m=0;for(s=0;s<f;++s){var g=r[s];if(null!==g)if((0,i.isNum)(g))m+=-g*o*.001;else{var y=g.width,b=g.fontChar,_=y*v+((g.isSpace?c:0)+u)*h;g.isInFont||a.missingFile?(n.xcoords.push(n.x+m*d),n.tspan.textContent+=b,m+=_):m+=_}else m+=h*c}p?n.y-=m*d:n.x+=m*d,n.tspan.setAttributeNS(null,"x",n.xcoords.map(e).join(" ")),n.tspan.setAttributeNS(null,"y",e(-n.y)),n.tspan.setAttributeNS(null,"font-family",n.fontFamily),n.tspan.setAttributeNS(null,"font-size",e(n.fontSize)+"px"),n.fontStyle!==l.fontStyle&&n.tspan.setAttributeNS(null,"font-style",n.fontStyle),n.fontWeight!==l.fontWeight&&n.tspan.setAttributeNS(null,"font-weight",n.fontWeight);var A=n.textRenderingMode&i.TextRenderingMode.FILL_STROKE_MASK;A===i.TextRenderingMode.FILL||A===i.TextRenderingMode.FILL_STROKE?(n.fillColor!==l.fillColor&&n.tspan.setAttributeNS(null,"fill",n.fillColor),n.fillAlpha<1&&n.tspan.setAttributeNS(null,"fill-opacity",n.fillAlpha)):n.textRenderingMode===i.TextRenderingMode.ADD_TO_PATH?n.tspan.setAttributeNS(null,"fill","transparent"):n.tspan.setAttributeNS(null,"fill","none"),A!==i.TextRenderingMode.STROKE&&A!==i.TextRenderingMode.FILL_STROKE||this._setStrokeAttributes(n.tspan);var S=n.textMatrix;0!==n.textRise&&((S=S.slice())[5]+=n.textRise),n.txtElement.setAttributeNS(null,"transform",t(S)+" scale(1, -1)"),n.txtElement.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve"),n.txtElement.appendChild(n.tspan),n.txtgrp.appendChild(n.txtElement),this._ensureTransformGroup().appendChild(n.txtElement)}},setLeadingMoveText:function(e,t){this.setLeading(-t),this.moveText(e,t)},addFontStyle:function(e){this.cssStyle||(this.cssStyle=this.svgFactory.createElement("svg:style"),this.cssStyle.setAttributeNS(null,"type","text/css"),this.defs.appendChild(this.cssStyle));var t=(0,i.createObjectURL)(e.data,e.mimetype,this.forceDataSchema);this.cssStyle.textContent+='@font-face { font-family: "'+e.loadedName+'"; src: url('+t+"); }\n"},setFont:function(t){var r=this.current,n=this.commonObjs.get(t[0]),a=t[1];this.current.font=n,this.embedFonts&&n.data&&!this.embeddedFonts[n.loadedName]&&(this.addFontStyle(n),this.embeddedFonts[n.loadedName]=n),r.fontMatrix=n.fontMatrix?n.fontMatrix:i.FONT_IDENTITY_MATRIX;var o=n.black?n.bold?"bolder":"bold":n.bold?"bold":"normal",s=n.italic?"italic":"normal";a<0?(a=-a,r.fontDirection=-1):r.fontDirection=1,r.fontSize=a,r.fontFamily=n.loadedName,r.fontWeight=o,r.fontStyle=s,r.tspan=this.svgFactory.createElement("svg:tspan"),r.tspan.setAttributeNS(null,"y",e(-r.y)),r.xcoords=[]},endText:function(){var e=this.current;e.textRenderingMode&i.TextRenderingMode.ADD_TO_PATH_FLAG&&e.txtElement&&e.txtElement.hasChildNodes()&&(e.element=e.txtElement,this.clip("nonzero"),this.endPath())},setLineWidth:function(e){this.current.lineWidth=e},setLineCap:function(e){this.current.lineCap=o[e]},setLineJoin:function(e){this.current.lineJoin=s[e]},setMiterLimit:function(e){this.current.miterLimit=e},setStrokeAlpha:function(e){this.current.strokeAlpha=e},setStrokeRGBColor:function(e,t,r){var n=i.Util.makeCssRgb(e,t,r);this.current.strokeColor=n},setFillAlpha:function(e){this.current.fillAlpha=e},setFillRGBColor:function(e,t,r){var n=i.Util.makeCssRgb(e,t,r);this.current.fillColor=n,this.current.tspan=this.svgFactory.createElement("svg:tspan"),this.current.xcoords=[]},setDash:function(e,t){this.current.dashArray=e,this.current.dashPhase=t},constructPath:function(t,r){var n=this.current,a=n.x,o=n.y;n.path=this.svgFactory.createElement("svg:path");for(var s=[],u=t.length,l=0,c=0;l<u;l++)switch(0|t[l]){case i.OPS.rectangle:a=r[c++],o=r[c++];var h=a+r[c++],d=o+r[c++];s.push("M",e(a),e(o),"L",e(h),e(o),"L",e(h),e(d),"L",e(a),e(d),"Z");break;case i.OPS.moveTo:a=r[c++],o=r[c++],s.push("M",e(a),e(o));break;case i.OPS.lineTo:a=r[c++],o=r[c++],s.push("L",e(a),e(o));break;case i.OPS.curveTo:a=r[c+4],o=r[c+5],s.push("C",e(r[c]),e(r[c+1]),e(r[c+2]),e(r[c+3]),e(a),e(o)),c+=6;break;case i.OPS.curveTo2:a=r[c+2],o=r[c+3],s.push("C",e(a),e(o),e(r[c]),e(r[c+1]),e(r[c+2]),e(r[c+3])),c+=4;break;case i.OPS.curveTo3:a=r[c+2],o=r[c+3],s.push("C",e(r[c]),e(r[c+1]),e(a),e(o),e(a),e(o)),c+=4;break;case i.OPS.closePath:s.push("Z")}n.path.setAttributeNS(null,"d",s.join(" ")),n.path.setAttributeNS(null,"fill","none"),this._ensureTransformGroup().appendChild(n.path),n.element=n.path,n.setCurrentPoint(a,o)},endPath:function(){if(this.pendingClip){var e=this.current,r="clippath"+u;u++;var n=this.svgFactory.createElement("svg:clipPath");n.setAttributeNS(null,"id",r),n.setAttributeNS(null,"transform",t(this.transformMatrix));var i=e.element.cloneNode(!0);"evenodd"===this.pendingClip?i.setAttributeNS(null,"clip-rule","evenodd"):i.setAttributeNS(null,"clip-rule","nonzero"),this.pendingClip=null,n.appendChild(i),this.defs.appendChild(n),e.activeClipUrl&&(e.clipGroup=null,this.extraStack.forEach(function(e){e.clipGroup=null}),n.setAttributeNS(null,"clip-path",e.activeClipUrl)),e.activeClipUrl="url(#"+r+")",this.tgrp=null}},clip:function(e){this.pendingClip=e},closePath:function(){var e=this.current;if(e.path){var t=e.path.getAttributeNS(null,"d");t+="Z",e.path.setAttributeNS(null,"d",t)}},setLeading:function(e){this.current.leading=-e},setTextRise:function(e){this.current.textRise=e},setTextRenderingMode:function(e){this.current.textRenderingMode=e},setHScale:function(e){this.current.textHScale=e/100},setGState:function(e){for(var t=0,r=e.length;t<r;t++){var n=e[t],a=n[0],o=n[1];switch(a){case"LW":this.setLineWidth(o);break;case"LC":this.setLineCap(o);break;case"LJ":this.setLineJoin(o);break;case"ML":this.setMiterLimit(o);break;case"D":this.setDash(o[0],o[1]);break;case"Font":this.setFont(o);break;case"CA":this.setStrokeAlpha(o);break;case"ca":this.setFillAlpha(o);break;default:(0,i.warn)("Unimplemented graphic state "+a)}}},fill:function(){var e=this.current;e.element&&(e.element.setAttributeNS(null,"fill",e.fillColor),e.element.setAttributeNS(null,"fill-opacity",e.fillAlpha),this.endPath())},stroke:function(){var e=this.current;e.element&&(this._setStrokeAttributes(e.element),e.element.setAttributeNS(null,"fill","none"),this.endPath())},_setStrokeAttributes:function(t){var r=this.current;t.setAttributeNS(null,"stroke",r.strokeColor),t.setAttributeNS(null,"stroke-opacity",r.strokeAlpha),t.setAttributeNS(null,"stroke-miterlimit",e(r.miterLimit)),t.setAttributeNS(null,"stroke-linecap",r.lineCap),t.setAttributeNS(null,"stroke-linejoin",r.lineJoin),t.setAttributeNS(null,"stroke-width",e(r.lineWidth)+"px"),t.setAttributeNS(null,"stroke-dasharray",r.dashArray.map(e).join(" ")),t.setAttributeNS(null,"stroke-dashoffset",e(r.dashPhase)+"px")},eoFill:function(){this.current.element&&this.current.element.setAttributeNS(null,"fill-rule","evenodd"),this.fill()},fillStroke:function(){this.stroke(),this.fill()},eoFillStroke:function(){this.current.element&&this.current.element.setAttributeNS(null,"fill-rule","evenodd"),this.fillStroke()},closeStroke:function(){this.closePath(),this.stroke()},closeFillStroke:function(){this.closePath(),this.fillStroke()},closeEOFillStroke:function(){this.closePath(),this.eoFillStroke()},paintSolidColorImageMask:function(){var e=this.current,t=this.svgFactory.createElement("svg:rect");t.setAttributeNS(null,"x","0"),t.setAttributeNS(null,"y","0"),t.setAttributeNS(null,"width","1px"),t.setAttributeNS(null,"height","1px"),t.setAttributeNS(null,"fill",e.fillColor),this._ensureTransformGroup().appendChild(t)},paintJpegXObject:function(t,r,i){var a=this.objs.get(t),o=this.svgFactory.createElement("svg:image");o.setAttributeNS(n,"xlink:href",a.src),o.setAttributeNS(null,"width",e(r)),o.setAttributeNS(null,"height",e(i)),o.setAttributeNS(null,"x","0"),o.setAttributeNS(null,"y",e(-i)),o.setAttributeNS(null,"transform","scale("+e(1/r)+" "+e(-1/i)+")"),this._ensureTransformGroup().appendChild(o)},paintImageXObject:function(e){var t=this.objs.get(e);t?this.paintInlineImageXObject(t):(0,i.warn)("Dependent image isn't ready yet")},paintInlineImageXObject:function(t,r){var i=t.width,a=t.height,o=c(t,this.forceDataSchema,!!r),s=this.svgFactory.createElement("svg:rect");s.setAttributeNS(null,"x","0"),s.setAttributeNS(null,"y","0"),s.setAttributeNS(null,"width",e(i)),s.setAttributeNS(null,"height",e(a)),this.current.element=s,this.clip("nonzero");var u=this.svgFactory.createElement("svg:image");u.setAttributeNS(n,"xlink:href",o),u.setAttributeNS(null,"x","0"),u.setAttributeNS(null,"y",e(-a)),u.setAttributeNS(null,"width",e(i)+"px"),u.setAttributeNS(null,"height",e(a)+"px"),u.setAttributeNS(null,"transform","scale("+e(1/i)+" "+e(-1/a)+")"),r?r.appendChild(u):this._ensureTransformGroup().appendChild(u)},paintImageMaskXObject:function(t){var r=this.current,n=t.width,i=t.height,a=r.fillColor;r.maskId="mask"+d++;var o=this.svgFactory.createElement("svg:mask");o.setAttributeNS(null,"id",r.maskId);var s=this.svgFactory.createElement("svg:rect");s.setAttributeNS(null,"x","0"),s.setAttributeNS(null,"y","0"),s.setAttributeNS(null,"width",e(n)),s.setAttributeNS(null,"height",e(i)),s.setAttributeNS(null,"fill",a),s.setAttributeNS(null,"mask","url(#"+r.maskId+")"),this.defs.appendChild(o),this._ensureTransformGroup().appendChild(s),this.paintInlineImageXObject(t,o)},paintFormXObjectBegin:function(t,r){if(Array.isArray(t)&&6===t.length&&this.transform(t[0],t[1],t[2],t[3],t[4],t[5]),Array.isArray(r)&&4===r.length){var n=r[2]-r[0],i=r[3]-r[1],a=this.svgFactory.createElement("svg:rect");a.setAttributeNS(null,"x",r[0]),a.setAttributeNS(null,"y",r[1]),a.setAttributeNS(null,"width",e(n)),a.setAttributeNS(null,"height",e(i)),this.current.element=a,this.clip("nonzero"),this.endPath()}},paintFormXObjectEnd:function(){},_initialize:function(e){var r=this.svgFactory.create(e.width,e.height),n=this.svgFactory.createElement("svg:defs");r.appendChild(n),this.defs=n;var i=this.svgFactory.createElement("svg:g");return i.setAttributeNS(null,"transform",t(e.transform)),r.appendChild(i),this.svg=i,r},_ensureClipGroup:function(){if(!this.current.clipGroup){var e=this.svgFactory.createElement("svg:g");e.setAttributeNS(null,"clip-path",this.current.activeClipUrl),this.svg.appendChild(e),this.current.clipGroup=e}return this.current.clipGroup},_ensureTransformGroup:function(){return this.tgrp||(this.tgrp=this.svgFactory.createElement("svg:g"),this.tgrp.setAttributeNS(null,"transform",t(this.transformMatrix)),this.current.activeClipUrl?this._ensureClipGroup().appendChild(this.tgrp):this.svg.appendChild(this.tgrp)),this.tgrp}},r}(),t.SVGGraphics=u},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.PDFNodeStream=void 0;var n,i=r(137),a=(n=i)&&n.__esModule?n:{default:n},o=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),s=r(1),u=r(149);function l(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function c(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function h(e){return function(){var t=e.apply(this,arguments);return new Promise(function(e,r){return function n(i,a){try{var o=t[i](a),s=o.value}catch(e){return void r(e)}if(!o.done)return Promise.resolve(s).then(function(e){n("next",e)},function(e){n("throw",e)});e(s)}("next")})}}function d(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var f=require("fs"),p=require("http"),v=require("https"),m=require("url"),g=/^file:\/\/\/[a-zA-Z]:\//;var y=function(){function e(t){var r,n;d(this,e),this.source=t,this.url=(r=t.url,"file:"===(n=m.parse(r)).protocol||n.host?n:/^[a-z]:[/\\]/i.test(r)?m.parse("file:///"+r):(n.host||(n.protocol="file:"),n)),this.isHttp="http:"===this.url.protocol||"https:"===this.url.protocol,this.isFsUrl="file:"===this.url.protocol,this.httpHeaders=this.isHttp&&t.httpHeaders||{},this._fullRequest=null,this._rangeRequestReaders=[]}return o(e,[{key:"getFullReader",value:function(){return(0,s.assert)(!this._fullRequest),this._fullRequest=this.isFsUrl?new k(this):new S(this),this._fullRequest}},{key:"getRangeReader",value:function(e,t){var r=this.isFsUrl?new P(this,e,t):new w(this,e,t);return this._rangeRequestReaders.push(r),r}},{key:"cancelAllRequests",value:function(e){this._fullRequest&&this._fullRequest.cancel(e),this._rangeRequestReaders.slice(0).forEach(function(t){t.cancel(e)})}}]),e}(),b=function(){function e(t){d(this,e),this._url=t.url,this._done=!1,this._storedError=null,this.onProgress=null;var r=t.source;this._contentLength=r.length,this._loaded=0,this._filename=null,this._disableRange=r.disableRange||!1,this._rangeChunkSize=r.rangeChunkSize,this._rangeChunkSize||this._disableRange||(this._disableRange=!0),this._isStreamingSupported=!r.disableStream,this._isRangeSupported=!r.disableRange,this._readableStream=null,this._readCapability=(0,s.createPromiseCapability)(),this._headersCapability=(0,s.createPromiseCapability)()}return o(e,[{key:"read",value:function(){var e=h(a.default.mark(function e(){var t,r;return a.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,this._readCapability.promise;case 2:if(!this._done){e.next=4;break}return e.abrupt("return",{value:void 0,done:!0});case 4:if(!this._storedError){e.next=6;break}throw this._storedError;case 6:if(null!==(t=this._readableStream.read())){e.next=10;break}return this._readCapability=(0,s.createPromiseCapability)(),e.abrupt("return",this.read());case 10:return this._loaded+=t.length,this.onProgress&&this.onProgress({loaded:this._loaded,total:this._contentLength}),r=new Uint8Array(t).buffer,e.abrupt("return",{value:r,done:!1});case 14:case"end":return e.stop()}},e,this)}));return function(){return e.apply(this,arguments)}}()},{key:"cancel",value:function(e){this._readableStream?this._readableStream.destroy(e):this._error(e)}},{key:"_error",value:function(e){this._storedError=e,this._readCapability.resolve()}},{key:"_setReadableStream",value:function(e){var t=this;this._readableStream=e,e.on("readable",function(){t._readCapability.resolve()}),e.on("end",function(){e.destroy(),t._done=!0,t._readCapability.resolve()}),e.on("error",function(e){t._error(e)}),!this._isStreamingSupported&&this._isRangeSupported&&this._error(new s.AbortException("streaming is disabled")),this._storedError&&this._readableStream.destroy(this._storedError)}},{key:"headersReady",get:function(){return this._headersCapability.promise}},{key:"filename",get:function(){return this._filename}},{key:"contentLength",get:function(){return this._contentLength}},{key:"isRangeSupported",get:function(){return this._isRangeSupported}},{key:"isStreamingSupported",get:function(){return this._isStreamingSupported}}]),e}(),_=function(){function e(t){d(this,e),this._url=t.url,this._done=!1,this._storedError=null,this.onProgress=null,this._loaded=0,this._readableStream=null,this._readCapability=(0,s.createPromiseCapability)();var r=t.source;this._isStreamingSupported=!r.disableStream}return o(e,[{key:"read",value:function(){var e=h(a.default.mark(function e(){var t,r;return a.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,this._readCapability.promise;case 2:if(!this._done){e.next=4;break}return e.abrupt("return",{value:void 0,done:!0});case 4:if(!this._storedError){e.next=6;break}throw this._storedError;case 6:if(null!==(t=this._readableStream.read())){e.next=10;break}return this._readCapability=(0,s.createPromiseCapability)(),e.abrupt("return",this.read());case 10:return this._loaded+=t.length,this.onProgress&&this.onProgress({loaded:this._loaded}),r=new Uint8Array(t).buffer,e.abrupt("return",{value:r,done:!1});case 14:case"end":return e.stop()}},e,this)}));return function(){return e.apply(this,arguments)}}()},{key:"cancel",value:function(e){this._readableStream?this._readableStream.destroy(e):this._error(e)}},{key:"_error",value:function(e){this._storedError=e,this._readCapability.resolve()}},{key:"_setReadableStream",value:function(e){var t=this;this._readableStream=e,e.on("readable",function(){t._readCapability.resolve()}),e.on("end",function(){e.destroy(),t._done=!0,t._readCapability.resolve()}),e.on("error",function(e){t._error(e)}),this._storedError&&this._readableStream.destroy(this._storedError)}},{key:"isStreamingSupported",get:function(){return this._isStreamingSupported}}]),e}();function A(e,t){return{protocol:e.protocol,auth:e.auth,host:e.hostname,port:e.port,path:e.path,method:"GET",headers:t}}var S=function(e){function t(e){d(this,t);var r=l(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e)),n=function(t){if(404===t.statusCode){var n=new s.MissingPDFException('Missing PDF "'+r._url+'".');return r._storedError=n,void r._headersCapability.reject(n)}r._headersCapability.resolve(),r._setReadableStream(t);var i=function(e){return r._readableStream.headers[e.toLowerCase()]},a=(0,u.validateRangeRequestCapabilities)({getResponseHeader:i,isHttp:e.isHttp,rangeChunkSize:r._rangeChunkSize,disableRange:r._disableRange}),o=a.allowRangeRequests,l=a.suggestedLength;r._isRangeSupported=o,r._contentLength=l||r._contentLength,r._filename=(0,u.extractFilenameFromHeader)(i)};return r._request=null,"http:"===r._url.protocol?r._request=p.request(A(r._url,e.httpHeaders),n):r._request=v.request(A(r._url,e.httpHeaders),n),r._request.on("error",function(e){r._storedError=e,r._headersCapability.reject(e)}),r._request.end(),r}return c(t,b),t}(),w=function(e){function t(e,r,n){d(this,t);var i=l(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));for(var a in i._httpHeaders={},e.httpHeaders){var o=e.httpHeaders[a];void 0!==o&&(i._httpHeaders[a]=o)}i._httpHeaders.Range="bytes="+r+"-"+(n-1);var u=function(e){if(404!==e.statusCode)i._setReadableStream(e);else{var t=new s.MissingPDFException('Missing PDF "'+i._url+'".');i._storedError=t}};return i._request=null,"http:"===i._url.protocol?i._request=p.request(A(i._url,i._httpHeaders),u):i._request=v.request(A(i._url,i._httpHeaders),u),i._request.on("error",function(e){i._storedError=e}),i._request.end(),i}return c(t,_),t}(),k=function(e){function t(e){d(this,t);var r=l(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e)),n=decodeURIComponent(r._url.path);return g.test(r._url.href)&&(n=n.replace(/^\//,"")),f.lstat(n,function(e,t){if(e)return"ENOENT"===e.code&&(e=new s.MissingPDFException('Missing PDF "'+n+'".')),r._storedError=e,void r._headersCapability.reject(e);r._contentLength=t.size,r._setReadableStream(f.createReadStream(n)),r._headersCapability.resolve()}),r}return c(t,b),t}(),P=function(e){function t(e,r,n){d(this,t);var i=l(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e)),a=decodeURIComponent(i._url.path);return g.test(i._url.href)&&(a=a.replace(/^\//,"")),i._setReadableStream(f.createReadStream(a,{start:r,end:n-1})),i}return c(t,_),t}();t.PDFNodeStream=y},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.validateResponseStatus=t.validateRangeRequestCapabilities=t.extractFilenameFromHeader=t.createResponseStatusError=void 0;var n=r(1),i=r(150);t.createResponseStatusError=function(e,t){return 404===e||0===e&&/^file:/.test(t)?new n.MissingPDFException('Missing PDF "'+t+'".'):new n.UnexpectedResponseException("Unexpected server response ("+e+') while retrieving PDF "'+t+'".',e)},t.extractFilenameFromHeader=function(e){var t=e("Content-Disposition");if(t){var r=(0,i.getFilenameFromContentDispositionHeader)(t);if(/\.pdf$/i.test(r))return r}return null},t.validateRangeRequestCapabilities=function(e){var t=e.getResponseHeader,r=e.isHttp,i=e.rangeChunkSize,a=e.disableRange;(0,n.assert)(i>0,"Range chunk size must be larger than zero");var o={allowRangeRequests:!1,suggestedLength:void 0},s=parseInt(t("Content-Length"),10);return Number.isInteger(s)?(o.suggestedLength=s,s<=2*i?o:a||!r?o:"bytes"!==t("Accept-Ranges")?o:"identity"!==(t("Content-Encoding")||"identity")?o:(o.allowRangeRequests=!0,o)):o},t.validateResponseStatus=function(e){return 200===e||206===e}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=function(){return function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var r=[],n=!0,i=!1,a=void 0;try{for(var o,s=e[Symbol.iterator]();!(n=(o=s.next()).done)&&(r.push(o.value),!t||r.length!==t);n=!0);}catch(e){i=!0,a=e}finally{try{!n&&s.return&&s.return()}finally{if(i)throw a}}return r}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();t.getFilenameFromContentDispositionHeader=function(e){var t=!0,r=o("filename\\*","i").exec(e);if(r){var i=l(r=r[1]);return u(i=h(i=c(i=unescape(i))))}if(r=function(e){for(var t=[],r=void 0,i=o("filename\\*((?!0\\d)\\d+)(\\*?)","ig");null!==(r=i.exec(e));){var a=r,s=n(a,4),u=s[1],h=s[2],d=s[3];if((u=parseInt(u,10))in t){if(0===u)break}else t[u]=[h,d]}for(var f=[],p=0;p<t.length&&p in t;++p){var v=n(t[p],2),m=v[0],g=v[1];g=l(g),m&&(g=unescape(g),0===p&&(g=c(g))),f.push(g)}return f.join("")}(e))return u(h(r));if(r=o("filename","i").exec(e)){var a=l(r=r[1]);return u(a=h(a))}function o(e,t){return new RegExp("(?:^|;)\\s*"+e+'\\s*=\\s*([^";\\s][^;\\s]*|"(?:[^"\\\\]|\\\\"?)+"?)',t)}function s(e,r){if(e){if(!/^[\x00-\xFF]+$/.test(r))return r;try{for(var n=new TextDecoder(e,{fatal:!0}),i=new Array(r.length),a=0;a<r.length;++a)i[a]=r.charCodeAt(a);r=n.decode(new Uint8Array(i)),t=!1}catch(n){if(/^utf-?8$/i.test(e))try{r=decodeURIComponent(escape(r)),t=!1}catch(e){}}}return r}function u(e){return t&&/[\x80-\xff]/.test(e)&&(e=s("utf-8",e),t&&(e=s("iso-8859-1",e))),e}function l(e){if('"'===e.charAt(0)){for(var t=e.slice(1).split('\\"'),r=0;r<t.length;++r){var n=t[r].indexOf('"');-1!==n&&(t[r]=t[r].slice(0,n),t.length=r+1),t[r]=t[r].replace(/\\(.)/g,"$1")}e=t.join('"')}return e}function c(e){var t=e.indexOf("'");return-1===t?e:s(e.slice(0,t),e.slice(t+1).replace(/^[^']*'/,""))}function h(e){return"=?"!==e.slice(0,2)||/[\x00-\x19\x80-\xff]/.test(e)?e:e.replace(/=\?([\w-]*)\?([QqBb])\?((?:[^?]|\?(?!=))*)\?=/g,function(e,t,r,n){if("q"===r||"Q"===r)return s(t,n=(n=n.replace(/_/g," ")).replace(/=([0-9a-fA-F]{2})/g,function(e,t){return String.fromCharCode(parseInt(t,16))}));try{n=atob(n)}catch(e){}return s(t,n)})}return""}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.PDFFetchStream=void 0;var n,i=r(137),a=(n=i)&&n.__esModule?n:{default:n},o=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),s=r(1),u=r(149);function l(e){return function(){var t=e.apply(this,arguments);return new Promise(function(e,r){return function n(i,a){try{var o=t[i](a),s=o.value}catch(e){return void r(e)}if(!o.done)return Promise.resolve(s).then(function(e){n("next",e)},function(e){n("throw",e)});e(s)}("next")})}}function c(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function h(e,t,r){return{method:"GET",headers:e,signal:r&&r.signal,mode:"cors",credentials:t?"include":"same-origin",redirect:"follow"}}var d=function(){function e(t){c(this,e),this.source=t,this.isHttp=/^https?:/i.test(t.url),this.httpHeaders=this.isHttp&&t.httpHeaders||{},this._fullRequestReader=null,this._rangeRequestReaders=[]}return o(e,[{key:"getFullReader",value:function(){return(0,s.assert)(!this._fullRequestReader),this._fullRequestReader=new f(this),this._fullRequestReader}},{key:"getRangeReader",value:function(e,t){var r=new p(this,e,t);return this._rangeRequestReaders.push(r),r}},{key:"cancelAllRequests",value:function(e){this._fullRequestReader&&this._fullRequestReader.cancel(e),this._rangeRequestReaders.slice(0).forEach(function(t){t.cancel(e)})}}]),e}(),f=function(){function e(t){var r=this;c(this,e),this._stream=t,this._reader=null,this._loaded=0,this._filename=null;var n=t.source;for(var i in this._withCredentials=n.withCredentials,this._contentLength=n.length,this._headersCapability=(0,s.createPromiseCapability)(),this._disableRange=n.disableRange||!1,this._rangeChunkSize=n.rangeChunkSize,this._rangeChunkSize||this._disableRange||(this._disableRange=!0),"undefined"!=typeof AbortController&&(this._abortController=new AbortController),this._isStreamingSupported=!n.disableStream,this._isRangeSupported=!n.disableRange,this._headers=new Headers,this._stream.httpHeaders){var a=this._stream.httpHeaders[i];void 0!==a&&this._headers.append(i,a)}var o=n.url;fetch(o,h(this._headers,this._withCredentials,this._abortController)).then(function(e){if(!(0,u.validateResponseStatus)(e.status))throw(0,u.createResponseStatusError)(e.status,o);r._reader=e.body.getReader(),r._headersCapability.resolve();var t=function(t){return e.headers.get(t)},n=(0,u.validateRangeRequestCapabilities)({getResponseHeader:t,isHttp:r._stream.isHttp,rangeChunkSize:r._rangeChunkSize,disableRange:r._disableRange}),i=n.allowRangeRequests,a=n.suggestedLength;r._isRangeSupported=i,r._contentLength=a||r._contentLength,r._filename=(0,u.extractFilenameFromHeader)(t),!r._isStreamingSupported&&r._isRangeSupported&&r.cancel(new s.AbortException("streaming is disabled"))}).catch(this._headersCapability.reject),this.onProgress=null}return o(e,[{key:"read",value:function(){var e=l(a.default.mark(function e(){var t,r,n,i;return a.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,this._headersCapability.promise;case 2:return e.next=4,this._reader.read();case 4:if(t=e.sent,r=t.value,!(n=t.done)){e.next=9;break}return e.abrupt("return",{value:r,done:n});case 9:return this._loaded+=r.byteLength,this.onProgress&&this.onProgress({loaded:this._loaded,total:this._contentLength}),i=new Uint8Array(r).buffer,e.abrupt("return",{value:i,done:!1});case 13:case"end":return e.stop()}},e,this)}));return function(){return e.apply(this,arguments)}}()},{key:"cancel",value:function(e){this._reader&&this._reader.cancel(e),this._abortController&&this._abortController.abort()}},{key:"headersReady",get:function(){return this._headersCapability.promise}},{key:"filename",get:function(){return this._filename}},{key:"contentLength",get:function(){return this._contentLength}},{key:"isRangeSupported",get:function(){return this._isRangeSupported}},{key:"isStreamingSupported",get:function(){return this._isStreamingSupported}}]),e}(),p=function(){function e(t,r,n){var i=this;c(this,e),this._stream=t,this._reader=null,this._loaded=0;var a=t.source;for(var o in this._withCredentials=a.withCredentials,this._readCapability=(0,s.createPromiseCapability)(),this._isStreamingSupported=!a.disableStream,"undefined"!=typeof AbortController&&(this._abortController=new AbortController),this._headers=new Headers,this._stream.httpHeaders){var l=this._stream.httpHeaders[o];void 0!==l&&this._headers.append(o,l)}var d=r+"-"+(n-1);this._headers.append("Range","bytes="+d);var f=a.url;fetch(f,h(this._headers,this._withCredentials,this._abortController)).then(function(e){if(!(0,u.validateResponseStatus)(e.status))throw(0,u.createResponseStatusError)(e.status,f);i._readCapability.resolve(),i._reader=e.body.getReader()}),this.onProgress=null}return o(e,[{key:"read",value:function(){var e=l(a.default.mark(function e(){var t,r,n,i;return a.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,this._readCapability.promise;case 2:return e.next=4,this._reader.read();case 4:if(t=e.sent,r=t.value,!(n=t.done)){e.next=9;break}return e.abrupt("return",{value:r,done:n});case 9:return this._loaded+=r.byteLength,this.onProgress&&this.onProgress({loaded:this._loaded}),i=new Uint8Array(r).buffer,e.abrupt("return",{value:i,done:!1});case 13:case"end":return e.stop()}},e,this)}));return function(){return e.apply(this,arguments)}}()},{key:"cancel",value:function(e){this._reader&&this._reader.cancel(e),this._abortController&&this._abortController.abort()}},{key:"isStreamingSupported",get:function(){return this._isStreamingSupported}}]),e}();t.PDFFetchStream=d},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.NetworkManager=t.PDFNetworkStream=void 0;var n=s(r(137)),i=r(1),a=r(149),o=s(r(3));function s(e){return e&&e.__esModule?e:{default:e}}function u(e){return function(){var t=e.apply(this,arguments);return new Promise(function(e,r){return function n(i,a){try{var o=t[i](a),s=o.value}catch(e){return void r(e)}if(!o.done)return Promise.resolve(s).then(function(e){n("next",e)},function(e){n("throw",e)});e(s)}("next")})}}function l(e,t){this.url=e,t=t||{},this.isHttp=/^https?:/i.test(e),this.httpHeaders=this.isHttp&&t.httpHeaders||{},this.withCredentials=t.withCredentials||!1,this.getXhr=t.getXhr||function(){return new XMLHttpRequest},this.currXhrId=0,this.pendingRequests=Object.create(null),this.loadedRequests=Object.create(null)}function c(e){var t=e.response;return"string"!=typeof t?t:(0,i.stringToBytes)(t).buffer}var h=function(){try{var e=new XMLHttpRequest;return e.open("GET",o.default.location.href),e.responseType="moz-chunked-arraybuffer","moz-chunked-arraybuffer"===e.responseType}catch(e){return!1}}();function d(e){this._source=e,this._manager=new l(e.url,{httpHeaders:e.httpHeaders,withCredentials:e.withCredentials}),this._rangeChunkSize=e.rangeChunkSize,this._fullRequestReader=null,this._rangeRequestReaders=[]}function f(e,t){this._manager=e;var r={onHeadersReceived:this._onHeadersReceived.bind(this),onProgressiveData:t.disableStream?null:this._onProgressiveData.bind(this),onDone:this._onDone.bind(this),onError:this._onError.bind(this),onProgress:this._onProgress.bind(this)};this._url=t.url,this._fullRequestId=e.requestFull(r),this._headersReceivedCapability=(0,i.createPromiseCapability)(),this._disableRange=t.disableRange||!1,this._contentLength=t.length,this._rangeChunkSize=t.rangeChunkSize,this._rangeChunkSize||this._disableRange||(this._disableRange=!0),this._isStreamingSupported=!1,this._isRangeSupported=!1,this._cachedChunks=[],this._requests=[],this._done=!1,this._storedError=void 0,this._filename=null,this.onProgress=null}function p(e,t,r){this._manager=e;var n={onDone:this._onDone.bind(this),onProgress:this._onProgress.bind(this)};this._requestId=e.requestRange(t,r,n),this._requests=[],this._queuedChunk=null,this._done=!1,this.onProgress=null,this.onClosed=null}l.prototype={requestRange:function(e,t,r){var n={begin:e,end:t};for(var i in r)n[i]=r[i];return this.request(n)},requestFull:function(e){return this.request(e)},request:function(e){var t=this.getXhr(),r=this.currXhrId++,n=this.pendingRequests[r]={xhr:t};for(var i in t.open("GET",this.url),t.withCredentials=this.withCredentials,this.httpHeaders){var a=this.httpHeaders[i];void 0!==a&&t.setRequestHeader(i,a)}if(this.isHttp&&"begin"in e&&"end"in e){var o=e.begin+"-"+(e.end-1);t.setRequestHeader("Range","bytes="+o),n.expectedStatus=206}else n.expectedStatus=200;return h&&!!e.onProgressiveData?(t.responseType="moz-chunked-arraybuffer",n.onProgressiveData=e.onProgressiveData,n.mozChunked=!0):t.responseType="arraybuffer",e.onError&&(t.onerror=function(r){e.onError(t.status)}),t.onreadystatechange=this.onStateChange.bind(this,r),t.onprogress=this.onProgress.bind(this,r),n.onHeadersReceived=e.onHeadersReceived,n.onDone=e.onDone,n.onError=e.onError,n.onProgress=e.onProgress,t.send(null),r},onProgress:function(e,t){var r=this.pendingRequests[e];if(r){if(r.mozChunked){var n=c(r.xhr);r.onProgressiveData(n)}var i=r.onProgress;i&&i(t)}},onStateChange:function(e,t){var r=this.pendingRequests[e];if(r){var n=r.xhr;if(n.readyState>=2&&r.onHeadersReceived&&(r.onHeadersReceived(),delete r.onHeadersReceived),4===n.readyState&&e in this.pendingRequests)if(delete this.pendingRequests[e],0===n.status&&this.isHttp)r.onError&&r.onError(n.status);else{var i=n.status||200;if(200===i&&206===r.expectedStatus||i===r.expectedStatus){this.loadedRequests[e]=!0;var a=c(n);if(206===i){var o=n.getResponseHeader("Content-Range"),s=/bytes (\d+)-(\d+)\/(\d+)/.exec(o),u=parseInt(s[1],10);r.onDone({begin:u,chunk:a})}else r.onProgressiveData?r.onDone(null):a?r.onDone({begin:0,chunk:a}):r.onError&&r.onError(n.status)}else r.onError&&r.onError(n.status)}}},hasPendingRequests:function(){for(var e in this.pendingRequests)return!0;return!1},getRequestXhr:function(e){return this.pendingRequests[e].xhr},isStreamingRequest:function(e){return!!this.pendingRequests[e].onProgressiveData},isPendingRequest:function(e){return e in this.pendingRequests},isLoadedRequest:function(e){return e in this.loadedRequests},abortAllRequests:function(){for(var e in this.pendingRequests)this.abortRequest(0|e)},abortRequest:function(e){var t=this.pendingRequests[e].xhr;delete this.pendingRequests[e],t.abort()}},d.prototype={_onRangeRequestReaderClosed:function(e){var t=this._rangeRequestReaders.indexOf(e);t>=0&&this._rangeRequestReaders.splice(t,1)},getFullReader:function(){return(0,i.assert)(!this._fullRequestReader),this._fullRequestReader=new f(this._manager,this._source),this._fullRequestReader},getRangeReader:function(e,t){var r=new p(this._manager,e,t);return r.onClosed=this._onRangeRequestReaderClosed.bind(this),this._rangeRequestReaders.push(r),r},cancelAllRequests:function(e){this._fullRequestReader&&this._fullRequestReader.cancel(e),this._rangeRequestReaders.slice(0).forEach(function(t){t.cancel(e)})}},f.prototype={_onHeadersReceived:function(){var e=this._fullRequestId,t=this._manager.getRequestXhr(e),r=function(e){return t.getResponseHeader(e)},n=(0,a.validateRangeRequestCapabilities)({getResponseHeader:r,isHttp:this._manager.isHttp,rangeChunkSize:this._rangeChunkSize,disableRange:this._disableRange}),i=n.allowRangeRequests,o=n.suggestedLength;i&&(this._isRangeSupported=!0),this._contentLength=o||this._contentLength,this._filename=(0,a.extractFilenameFromHeader)(r);var s=this._manager;s.isStreamingRequest(e)?this._isStreamingSupported=!0:this._isRangeSupported&&s.abortRequest(e),this._headersReceivedCapability.resolve()},_onProgressiveData:function(e){this._requests.length>0?this._requests.shift().resolve({value:e,done:!1}):this._cachedChunks.push(e)},_onDone:function(e){e&&this._onProgressiveData(e.chunk),this._done=!0,this._cachedChunks.length>0||(this._requests.forEach(function(e){e.resolve({value:void 0,done:!0})}),this._requests=[])},_onError:function(e){var t=this._url,r=(0,a.createResponseStatusError)(e,t);this._storedError=r,this._headersReceivedCapability.reject(r),this._requests.forEach(function(e){e.reject(r)}),this._requests=[],this._cachedChunks=[]},_onProgress:function(e){this.onProgress&&this.onProgress({loaded:e.loaded,total:e.lengthComputable?e.total:this._contentLength})},get filename(){return this._filename},get isRangeSupported(){return this._isRangeSupported},get isStreamingSupported(){return this._isStreamingSupported},get contentLength(){return this._contentLength},get headersReady(){return this._headersReceivedCapability.promise},read:function(){var e=u(n.default.mark(function e(){var t,r;return n.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(!this._storedError){e.next=2;break}throw this._storedError;case 2:if(!(this._cachedChunks.length>0)){e.next=5;break}return t=this._cachedChunks.shift(),e.abrupt("return",{value:t,done:!1});case 5:if(!this._done){e.next=7;break}return e.abrupt("return",{value:void 0,done:!0});case 7:return r=(0,i.createPromiseCapability)(),this._requests.push(r),e.abrupt("return",r.promise);case 10:case"end":return e.stop()}},e,this)}));return function(){return e.apply(this,arguments)}}(),cancel:function(e){this._done=!0,this._headersReceivedCapability.reject(e),this._requests.forEach(function(e){e.resolve({value:void 0,done:!0})}),this._requests=[],this._manager.isPendingRequest(this._fullRequestId)&&this._manager.abortRequest(this._fullRequestId),this._fullRequestReader=null}},p.prototype={_close:function(){this.onClosed&&this.onClosed(this)},_onDone:function(e){var t=e.chunk;this._requests.length>0?this._requests.shift().resolve({value:t,done:!1}):this._queuedChunk=t;this._done=!0,this._requests.forEach(function(e){e.resolve({value:void 0,done:!0})}),this._requests=[],this._close()},_onProgress:function(e){!this.isStreamingSupported&&this.onProgress&&this.onProgress({loaded:e.loaded})},get isStreamingSupported(){return!1},read:function(){var e=u(n.default.mark(function e(){var t,r;return n.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(null===this._queuedChunk){e.next=4;break}return t=this._queuedChunk,this._queuedChunk=null,e.abrupt("return",{value:t,done:!1});case 4:if(!this._done){e.next=6;break}return e.abrupt("return",{value:void 0,done:!0});case 6:return r=(0,i.createPromiseCapability)(),this._requests.push(r),e.abrupt("return",r.promise);case 9:case"end":return e.stop()}},e,this)}));return function(){return e.apply(this,arguments)}}(),cancel:function(e){this._done=!0,this._requests.forEach(function(e){e.resolve({value:void 0,done:!0})}),this._requests=[],this._manager.isPendingRequest(this._requestId)&&this._manager.abortRequest(this._requestId),this._close()}},t.PDFNetworkStream=d,t.NetworkManager=l}])}); \ No newline at end of file
diff --git a/vendor/assets/javascripts/pdf.worker.js b/vendor/assets/javascripts/pdf.worker.js
deleted file mode 100644
index 57ff1ff8e57..00000000000
--- a/vendor/assets/javascripts/pdf.worker.js
+++ /dev/null
@@ -1,47057 +0,0 @@
-/**
- * @licstart The following is the entire license notice for the
- * Javascript code in this page
- *
- * Copyright 2018 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * @licend The above is the entire license notice for the
- * Javascript code in this page
- */
-
-(function webpackUniversalModuleDefinition(root, factory) {
- if(typeof exports === 'object' && typeof module === 'object')
- module.exports = factory();
- else if(typeof define === 'function' && define.amd)
- define("pdfjs-dist/build/pdf.worker", [], factory);
- else if(typeof exports === 'object')
- exports["pdfjs-dist/build/pdf.worker"] = factory();
- else
- root["pdfjs-dist/build/pdf.worker"] = root.pdfjsWorker = factory();
-})(this, function() {
-return /******/ (function(modules) { // webpackBootstrap
-/******/ // The module cache
-/******/ var installedModules = {};
-/******/
-/******/ // The require function
-/******/ function __w_pdfjs_require__(moduleId) {
-/******/
-/******/ // Check if module is in cache
-/******/ if(installedModules[moduleId]) {
-/******/ return installedModules[moduleId].exports;
-/******/ }
-/******/ // Create a new module (and put it into the cache)
-/******/ var module = installedModules[moduleId] = {
-/******/ i: moduleId,
-/******/ l: false,
-/******/ exports: {}
-/******/ };
-/******/
-/******/ // Execute the module function
-/******/ modules[moduleId].call(module.exports, module, module.exports, __w_pdfjs_require__);
-/******/
-/******/ // Flag the module as loaded
-/******/ module.l = true;
-/******/
-/******/ // Return the exports of the module
-/******/ return module.exports;
-/******/ }
-/******/
-/******/
-/******/ // expose the modules object (__webpack_modules__)
-/******/ __w_pdfjs_require__.m = modules;
-/******/
-/******/ // expose the module cache
-/******/ __w_pdfjs_require__.c = installedModules;
-/******/
-/******/ // define getter function for harmony exports
-/******/ __w_pdfjs_require__.d = function(exports, name, getter) {
-/******/ if(!__w_pdfjs_require__.o(exports, name)) {
-/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
-/******/ }
-/******/ };
-/******/
-/******/ // define __esModule on exports
-/******/ __w_pdfjs_require__.r = function(exports) {
-/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
-/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
-/******/ }
-/******/ Object.defineProperty(exports, '__esModule', { value: true });
-/******/ };
-/******/
-/******/ // create a fake namespace object
-/******/ // mode & 1: value is a module id, require it
-/******/ // mode & 2: merge all properties of value into the ns
-/******/ // mode & 4: return value when already ns object
-/******/ // mode & 8|1: behave like require
-/******/ __w_pdfjs_require__.t = function(value, mode) {
-/******/ if(mode & 1) value = __w_pdfjs_require__(value);
-/******/ if(mode & 8) return value;
-/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
-/******/ var ns = Object.create(null);
-/******/ __w_pdfjs_require__.r(ns);
-/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
-/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __w_pdfjs_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
-/******/ return ns;
-/******/ };
-/******/
-/******/ // getDefaultExport function for compatibility with non-harmony modules
-/******/ __w_pdfjs_require__.n = function(module) {
-/******/ var getter = module && module.__esModule ?
-/******/ function getDefault() { return module['default']; } :
-/******/ function getModuleExports() { return module; };
-/******/ __w_pdfjs_require__.d(getter, 'a', getter);
-/******/ return getter;
-/******/ };
-/******/
-/******/ // Object.prototype.hasOwnProperty.call
-/******/ __w_pdfjs_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
-/******/
-/******/ // __webpack_public_path__
-/******/ __w_pdfjs_require__.p = "";
-/******/
-/******/
-/******/ // Load entry module and return exports
-/******/ return __w_pdfjs_require__(__w_pdfjs_require__.s = 0);
-/******/ })
-/************************************************************************/
-/******/ ([
-/* 0 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var pdfjsVersion = '2.0.943';
-var pdfjsBuild = 'dc98bf76';
-var pdfjsCoreWorker = __w_pdfjs_require__(1);
-exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
-
-/***/ }),
-/* 1 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.WorkerMessageHandler = exports.WorkerTask = undefined;
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
-
-var _util = __w_pdfjs_require__(2);
-
-var _pdf_manager = __w_pdfjs_require__(130);
-
-var _is_node = __w_pdfjs_require__(5);
-
-var _is_node2 = _interopRequireDefault(_is_node);
-
-var _message_handler = __w_pdfjs_require__(172);
-
-var _primitives = __w_pdfjs_require__(138);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-var WorkerTask = function WorkerTaskClosure() {
- function WorkerTask(name) {
- this.name = name;
- this.terminated = false;
- this._capability = (0, _util.createPromiseCapability)();
- }
- WorkerTask.prototype = {
- get finished() {
- return this._capability.promise;
- },
- finish: function finish() {
- this._capability.resolve();
- },
- terminate: function terminate() {
- this.terminated = true;
- },
- ensureNotTerminated: function ensureNotTerminated() {
- if (this.terminated) {
- throw new Error('Worker task was terminated');
- }
- }
- };
- return WorkerTask;
-}();
-;
-var PDFWorkerStream = function PDFWorkerStreamClosure() {
- function PDFWorkerStream(msgHandler) {
- this._msgHandler = msgHandler;
- this._contentLength = null;
- this._fullRequestReader = null;
- this._rangeRequestReaders = [];
- }
- PDFWorkerStream.prototype = {
- getFullReader: function getFullReader() {
- (0, _util.assert)(!this._fullRequestReader);
- this._fullRequestReader = new PDFWorkerStreamReader(this._msgHandler);
- return this._fullRequestReader;
- },
- getRangeReader: function getRangeReader(begin, end) {
- var reader = new PDFWorkerStreamRangeReader(begin, end, this._msgHandler);
- this._rangeRequestReaders.push(reader);
- return reader;
- },
- cancelAllRequests: function cancelAllRequests(reason) {
- if (this._fullRequestReader) {
- this._fullRequestReader.cancel(reason);
- }
- var readers = this._rangeRequestReaders.slice(0);
- readers.forEach(function (reader) {
- reader.cancel(reason);
- });
- }
- };
- function PDFWorkerStreamReader(msgHandler) {
- var _this = this;
-
- this._msgHandler = msgHandler;
- this._contentLength = null;
- this._isRangeSupported = false;
- this._isStreamingSupported = false;
- var readableStream = this._msgHandler.sendWithStream('GetReader');
- this._reader = readableStream.getReader();
- this._headersReady = this._msgHandler.sendWithPromise('ReaderHeadersReady').then(function (data) {
- _this._isStreamingSupported = data.isStreamingSupported;
- _this._isRangeSupported = data.isRangeSupported;
- _this._contentLength = data.contentLength;
- });
- }
- PDFWorkerStreamReader.prototype = {
- get headersReady() {
- return this._headersReady;
- },
- get contentLength() {
- return this._contentLength;
- },
- get isStreamingSupported() {
- return this._isStreamingSupported;
- },
- get isRangeSupported() {
- return this._isRangeSupported;
- },
- read: function read() {
- return this._reader.read().then(function (_ref) {
- var value = _ref.value,
- done = _ref.done;
-
- if (done) {
- return {
- value: undefined,
- done: true
- };
- }
- return {
- value: value.buffer,
- done: false
- };
- });
- },
- cancel: function cancel(reason) {
- this._reader.cancel(reason);
- }
- };
- function PDFWorkerStreamRangeReader(begin, end, msgHandler) {
- this._msgHandler = msgHandler;
- this.onProgress = null;
- var readableStream = this._msgHandler.sendWithStream('GetRangeReader', {
- begin: begin,
- end: end
- });
- this._reader = readableStream.getReader();
- }
- PDFWorkerStreamRangeReader.prototype = {
- get isStreamingSupported() {
- return false;
- },
- read: function read() {
- return this._reader.read().then(function (_ref2) {
- var value = _ref2.value,
- done = _ref2.done;
-
- if (done) {
- return {
- value: undefined,
- done: true
- };
- }
- return {
- value: value.buffer,
- done: false
- };
- });
- },
- cancel: function cancel(reason) {
- this._reader.cancel(reason);
- }
- };
- return PDFWorkerStream;
-}();
-var WorkerMessageHandler = {
- setup: function setup(handler, port) {
- var testMessageProcessed = false;
- handler.on('test', function wphSetupTest(data) {
- if (testMessageProcessed) {
- return;
- }
- testMessageProcessed = true;
- if (!(data instanceof Uint8Array)) {
- handler.send('test', false);
- return;
- }
- var supportTransfers = data[0] === 255;
- handler.postMessageTransfers = supportTransfers;
- var xhr = new XMLHttpRequest();
- var responseExists = 'response' in xhr;
- try {
- xhr.responseType;
- } catch (e) {
- responseExists = false;
- }
- if (!responseExists) {
- handler.send('test', false);
- return;
- }
- handler.send('test', {
- supportTypedArray: true,
- supportTransfers: supportTransfers
- });
- });
- handler.on('configure', function wphConfigure(data) {
- (0, _util.setVerbosityLevel)(data.verbosity);
- });
- handler.on('GetDocRequest', function wphSetupDoc(data) {
- return WorkerMessageHandler.createDocumentHandler(data, port);
- });
- },
- createDocumentHandler: function createDocumentHandler(docParams, port) {
- var pdfManager;
- var terminated = false;
- var cancelXHRs = null;
- var WorkerTasks = [];
- var apiVersion = docParams.apiVersion;
- var workerVersion = '2.0.943';
- if (apiVersion !== workerVersion) {
- throw new Error('The API version "' + apiVersion + '" does not match ' + ('the Worker version "' + workerVersion + '".'));
- }
- var docId = docParams.docId;
- var docBaseUrl = docParams.docBaseUrl;
- var workerHandlerName = docParams.docId + '_worker';
- var handler = new _message_handler.MessageHandler(workerHandlerName, docId, port);
- handler.postMessageTransfers = docParams.postMessageTransfers;
- function ensureNotTerminated() {
- if (terminated) {
- throw new Error('Worker was terminated');
- }
- }
- function startWorkerTask(task) {
- WorkerTasks.push(task);
- }
- function finishWorkerTask(task) {
- task.finish();
- var i = WorkerTasks.indexOf(task);
- WorkerTasks.splice(i, 1);
- }
- function loadDocument(recoveryMode) {
- var loadDocumentCapability = (0, _util.createPromiseCapability)();
- var parseSuccess = function parseSuccess() {
- Promise.all([pdfManager.ensureDoc('numPages'), pdfManager.ensureDoc('fingerprint')]).then(function (_ref3) {
- var _ref4 = _slicedToArray(_ref3, 2),
- numPages = _ref4[0],
- fingerprint = _ref4[1];
-
- loadDocumentCapability.resolve({
- numPages: numPages,
- fingerprint: fingerprint
- });
- }, parseFailure);
- };
- var parseFailure = function parseFailure(e) {
- loadDocumentCapability.reject(e);
- };
- pdfManager.ensureDoc('checkHeader', []).then(function () {
- pdfManager.ensureDoc('parseStartXRef', []).then(function () {
- pdfManager.ensureDoc('parse', [recoveryMode]).then(parseSuccess, parseFailure);
- }, parseFailure);
- }, parseFailure);
- return loadDocumentCapability.promise;
- }
- function getPdfManager(data, evaluatorOptions) {
- var pdfManagerCapability = (0, _util.createPromiseCapability)();
- var pdfManager;
- var source = data.source;
- if (source.data) {
- try {
- pdfManager = new _pdf_manager.LocalPdfManager(docId, source.data, source.password, evaluatorOptions, docBaseUrl);
- pdfManagerCapability.resolve(pdfManager);
- } catch (ex) {
- pdfManagerCapability.reject(ex);
- }
- return pdfManagerCapability.promise;
- }
- var pdfStream,
- cachedChunks = [];
- try {
- pdfStream = new PDFWorkerStream(handler);
- } catch (ex) {
- pdfManagerCapability.reject(ex);
- return pdfManagerCapability.promise;
- }
- var fullRequest = pdfStream.getFullReader();
- fullRequest.headersReady.then(function () {
- if (!fullRequest.isRangeSupported) {
- return;
- }
- var disableAutoFetch = source.disableAutoFetch || fullRequest.isStreamingSupported;
- pdfManager = new _pdf_manager.NetworkPdfManager(docId, pdfStream, {
- msgHandler: handler,
- url: source.url,
- password: source.password,
- length: fullRequest.contentLength,
- disableAutoFetch: disableAutoFetch,
- rangeChunkSize: source.rangeChunkSize
- }, evaluatorOptions, docBaseUrl);
- for (var i = 0; i < cachedChunks.length; i++) {
- pdfManager.sendProgressiveData(cachedChunks[i]);
- }
- cachedChunks = [];
- pdfManagerCapability.resolve(pdfManager);
- cancelXHRs = null;
- }).catch(function (reason) {
- pdfManagerCapability.reject(reason);
- cancelXHRs = null;
- });
- var loaded = 0;
- var flushChunks = function flushChunks() {
- var pdfFile = (0, _util.arraysToBytes)(cachedChunks);
- if (source.length && pdfFile.length !== source.length) {
- (0, _util.warn)('reported HTTP length is different from actual');
- }
- try {
- pdfManager = new _pdf_manager.LocalPdfManager(docId, pdfFile, source.password, evaluatorOptions, docBaseUrl);
- pdfManagerCapability.resolve(pdfManager);
- } catch (ex) {
- pdfManagerCapability.reject(ex);
- }
- cachedChunks = [];
- };
- var readPromise = new Promise(function (resolve, reject) {
- var readChunk = function readChunk(chunk) {
- try {
- ensureNotTerminated();
- if (chunk.done) {
- if (!pdfManager) {
- flushChunks();
- }
- cancelXHRs = null;
- return;
- }
- var data = chunk.value;
- loaded += (0, _util.arrayByteLength)(data);
- if (!fullRequest.isStreamingSupported) {
- handler.send('DocProgress', {
- loaded: loaded,
- total: Math.max(loaded, fullRequest.contentLength || 0)
- });
- }
- if (pdfManager) {
- pdfManager.sendProgressiveData(data);
- } else {
- cachedChunks.push(data);
- }
- fullRequest.read().then(readChunk, reject);
- } catch (e) {
- reject(e);
- }
- };
- fullRequest.read().then(readChunk, reject);
- });
- readPromise.catch(function (e) {
- pdfManagerCapability.reject(e);
- cancelXHRs = null;
- });
- cancelXHRs = function cancelXHRs() {
- pdfStream.cancelAllRequests('abort');
- };
- return pdfManagerCapability.promise;
- }
- function setupDoc(data) {
- function onSuccess(doc) {
- ensureNotTerminated();
- handler.send('GetDoc', { pdfInfo: doc });
- }
- function onFailure(e) {
- ensureNotTerminated();
- if (e instanceof _util.PasswordException) {
- var task = new WorkerTask('PasswordException: response ' + e.code);
- startWorkerTask(task);
- handler.sendWithPromise('PasswordRequest', e).then(function (data) {
- finishWorkerTask(task);
- pdfManager.updatePassword(data.password);
- pdfManagerReady();
- }).catch(function (boundException) {
- finishWorkerTask(task);
- handler.send('PasswordException', boundException);
- }.bind(null, e));
- } else if (e instanceof _util.InvalidPDFException) {
- handler.send('InvalidPDF', e);
- } else if (e instanceof _util.MissingPDFException) {
- handler.send('MissingPDF', e);
- } else if (e instanceof _util.UnexpectedResponseException) {
- handler.send('UnexpectedResponse', e);
- } else {
- handler.send('UnknownError', new _util.UnknownErrorException(e.message, e.toString()));
- }
- }
- function pdfManagerReady() {
- ensureNotTerminated();
- loadDocument(false).then(onSuccess, function loadFailure(ex) {
- ensureNotTerminated();
- if (!(ex instanceof _util.XRefParseException)) {
- onFailure(ex);
- return;
- }
- pdfManager.requestLoadedStream();
- pdfManager.onLoadedStream().then(function () {
- ensureNotTerminated();
- loadDocument(true).then(onSuccess, onFailure);
- });
- }, onFailure);
- }
- ensureNotTerminated();
- var evaluatorOptions = {
- forceDataSchema: data.disableCreateObjectURL,
- maxImageSize: data.maxImageSize,
- disableFontFace: data.disableFontFace,
- nativeImageDecoderSupport: data.nativeImageDecoderSupport,
- ignoreErrors: data.ignoreErrors,
- isEvalSupported: data.isEvalSupported
- };
- getPdfManager(data, evaluatorOptions).then(function (newPdfManager) {
- if (terminated) {
- newPdfManager.terminate();
- throw new Error('Worker was terminated');
- }
- pdfManager = newPdfManager;
- pdfManager.onLoadedStream().then(function (stream) {
- handler.send('DataLoaded', { length: stream.bytes.byteLength });
- });
- }).then(pdfManagerReady, onFailure);
- }
- handler.on('GetPage', function wphSetupGetPage(data) {
- return pdfManager.getPage(data.pageIndex).then(function (page) {
- return Promise.all([pdfManager.ensure(page, 'rotate'), pdfManager.ensure(page, 'ref'), pdfManager.ensure(page, 'userUnit'), pdfManager.ensure(page, 'view')]).then(function (_ref5) {
- var _ref6 = _slicedToArray(_ref5, 4),
- rotate = _ref6[0],
- ref = _ref6[1],
- userUnit = _ref6[2],
- view = _ref6[3];
-
- return {
- rotate: rotate,
- ref: ref,
- userUnit: userUnit,
- view: view
- };
- });
- });
- });
- handler.on('GetPageIndex', function wphSetupGetPageIndex(data) {
- var ref = new _primitives.Ref(data.ref.num, data.ref.gen);
- var catalog = pdfManager.pdfDocument.catalog;
- return catalog.getPageIndex(ref);
- });
- handler.on('GetDestinations', function wphSetupGetDestinations(data) {
- return pdfManager.ensureCatalog('destinations');
- });
- handler.on('GetDestination', function wphSetupGetDestination(data) {
- return pdfManager.ensureCatalog('getDestination', [data.id]);
- });
- handler.on('GetPageLabels', function wphSetupGetPageLabels(data) {
- return pdfManager.ensureCatalog('pageLabels');
- });
- handler.on('GetPageMode', function wphSetupGetPageMode(data) {
- return pdfManager.ensureCatalog('pageMode');
- });
- handler.on('GetAttachments', function wphSetupGetAttachments(data) {
- return pdfManager.ensureCatalog('attachments');
- });
- handler.on('GetJavaScript', function wphSetupGetJavaScript(data) {
- return pdfManager.ensureCatalog('javaScript');
- });
- handler.on('GetOutline', function wphSetupGetOutline(data) {
- return pdfManager.ensureCatalog('documentOutline');
- });
- handler.on('GetPermissions', function (data) {
- return pdfManager.ensureCatalog('permissions');
- });
- handler.on('GetMetadata', function wphSetupGetMetadata(data) {
- return Promise.all([pdfManager.ensureDoc('documentInfo'), pdfManager.ensureCatalog('metadata')]);
- });
- handler.on('GetData', function wphSetupGetData(data) {
- pdfManager.requestLoadedStream();
- return pdfManager.onLoadedStream().then(function (stream) {
- return stream.bytes;
- });
- });
- handler.on('GetStats', function wphSetupGetStats(data) {
- return pdfManager.pdfDocument.xref.stats;
- });
- handler.on('GetAnnotations', function (_ref7) {
- var pageIndex = _ref7.pageIndex,
- intent = _ref7.intent;
-
- return pdfManager.getPage(pageIndex).then(function (page) {
- return page.getAnnotationsData(intent);
- });
- });
- handler.on('RenderPageRequest', function wphSetupRenderPage(data) {
- var pageIndex = data.pageIndex;
- pdfManager.getPage(pageIndex).then(function (page) {
- var task = new WorkerTask('RenderPageRequest: page ' + pageIndex);
- startWorkerTask(task);
- var pageNum = pageIndex + 1;
- var start = Date.now();
- page.getOperatorList({
- handler: handler,
- task: task,
- intent: data.intent,
- renderInteractiveForms: data.renderInteractiveForms
- }).then(function (operatorList) {
- finishWorkerTask(task);
- (0, _util.info)('page=' + pageNum + ' - getOperatorList: time=' + (Date.now() - start) + 'ms, len=' + operatorList.totalLength);
- }, function (e) {
- finishWorkerTask(task);
- if (task.terminated) {
- return;
- }
- handler.send('UnsupportedFeature', { featureId: _util.UNSUPPORTED_FEATURES.unknown });
- var minimumStackMessage = 'worker.js: while trying to getPage() and getOperatorList()';
- var wrappedException;
- if (typeof e === 'string') {
- wrappedException = {
- message: e,
- stack: minimumStackMessage
- };
- } else if ((typeof e === 'undefined' ? 'undefined' : _typeof(e)) === 'object') {
- wrappedException = {
- message: e.message || e.toString(),
- stack: e.stack || minimumStackMessage
- };
- } else {
- wrappedException = {
- message: 'Unknown exception type: ' + (typeof e === 'undefined' ? 'undefined' : _typeof(e)),
- stack: minimumStackMessage
- };
- }
- handler.send('PageError', {
- pageNum: pageNum,
- error: wrappedException,
- intent: data.intent
- });
- });
- });
- }, this);
- handler.on('GetTextContent', function wphExtractText(data, sink) {
- var pageIndex = data.pageIndex;
- sink.onPull = function (desiredSize) {};
- sink.onCancel = function (reason) {};
- pdfManager.getPage(pageIndex).then(function (page) {
- var task = new WorkerTask('GetTextContent: page ' + pageIndex);
- startWorkerTask(task);
- var pageNum = pageIndex + 1;
- var start = Date.now();
- page.extractTextContent({
- handler: handler,
- task: task,
- sink: sink,
- normalizeWhitespace: data.normalizeWhitespace,
- combineTextItems: data.combineTextItems
- }).then(function () {
- finishWorkerTask(task);
- (0, _util.info)('text indexing: page=' + pageNum + ' - time=' + (Date.now() - start) + 'ms');
- sink.close();
- }, function (reason) {
- finishWorkerTask(task);
- if (task.terminated) {
- return;
- }
- sink.error(reason);
- throw reason;
- });
- });
- });
- handler.on('Cleanup', function wphCleanup(data) {
- return pdfManager.cleanup();
- });
- handler.on('Terminate', function wphTerminate(data) {
- terminated = true;
- if (pdfManager) {
- pdfManager.terminate();
- pdfManager = null;
- }
- if (cancelXHRs) {
- cancelXHRs();
- }
- var waitOn = [];
- WorkerTasks.forEach(function (task) {
- waitOn.push(task.finished);
- task.terminate();
- });
- return Promise.all(waitOn).then(function () {
- handler.destroy();
- handler = null;
- });
- });
- handler.on('Ready', function wphReady(data) {
- setupDoc(docParams);
- docParams = null;
- });
- return workerHandlerName;
- },
- initializeFromPort: function initializeFromPort(port) {
- var handler = new _message_handler.MessageHandler('worker', 'main', port);
- WorkerMessageHandler.setup(handler, port);
- handler.send('ready', null);
- }
-};
-function isMessagePort(maybePort) {
- return typeof maybePort.postMessage === 'function' && 'onmessage' in maybePort;
-}
-if (typeof window === 'undefined' && !(0, _is_node2.default)() && typeof self !== 'undefined' && isMessagePort(self)) {
- WorkerMessageHandler.initializeFromPort(self);
-}
-exports.WorkerTask = WorkerTask;
-exports.WorkerMessageHandler = WorkerMessageHandler;
-
-/***/ }),
-/* 2 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.unreachable = exports.warn = exports.utf8StringToString = exports.stringToUTF8String = exports.stringToPDFString = exports.stringToBytes = exports.string32 = exports.shadow = exports.setVerbosityLevel = exports.URL = exports.ReadableStream = exports.removeNullCharacters = exports.readUint32 = exports.readUint16 = exports.readInt8 = exports.log2 = exports.isEvalSupported = exports.isLittleEndian = exports.createValidAbsoluteUrl = exports.isSameOrigin = exports.isSpace = exports.isString = exports.isNum = exports.isEmptyObj = exports.isBool = exports.isArrayBuffer = exports.info = exports.getVerbosityLevel = exports.getLookupTableFactory = exports.getInheritableProperty = exports.deprecated = exports.createObjectURL = exports.createPromiseCapability = exports.bytesToString = exports.assert = exports.arraysToBytes = exports.arrayByteLength = exports.FormatError = exports.XRefParseException = exports.toRomanNumerals = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.PermissionFlag = exports.PasswordResponses = exports.PasswordException = exports.NativeImageDecoding = exports.MissingPDFException = exports.MissingDataException = exports.InvalidPDFException = exports.AbortException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VerbosityLevel = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = undefined;
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-__w_pdfjs_require__(3);
-
-var _streams_polyfill = __w_pdfjs_require__(126);
-
-var _url_polyfill = __w_pdfjs_require__(128);
-
-var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
-var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
-var NativeImageDecoding = {
- NONE: 'none',
- DECODE: 'decode',
- DISPLAY: 'display'
-};
-var PermissionFlag = {
- PRINT: 0x04,
- MODIFY_CONTENTS: 0x08,
- COPY: 0x10,
- MODIFY_ANNOTATIONS: 0x20,
- FILL_INTERACTIVE_FORMS: 0x100,
- COPY_FOR_ACCESSIBILITY: 0x200,
- ASSEMBLE: 0x400,
- PRINT_HIGH_QUALITY: 0x800
-};
-var TextRenderingMode = {
- FILL: 0,
- STROKE: 1,
- FILL_STROKE: 2,
- INVISIBLE: 3,
- FILL_ADD_TO_PATH: 4,
- STROKE_ADD_TO_PATH: 5,
- FILL_STROKE_ADD_TO_PATH: 6,
- ADD_TO_PATH: 7,
- FILL_STROKE_MASK: 3,
- ADD_TO_PATH_FLAG: 4
-};
-var ImageKind = {
- GRAYSCALE_1BPP: 1,
- RGB_24BPP: 2,
- RGBA_32BPP: 3
-};
-var AnnotationType = {
- TEXT: 1,
- LINK: 2,
- FREETEXT: 3,
- LINE: 4,
- SQUARE: 5,
- CIRCLE: 6,
- POLYGON: 7,
- POLYLINE: 8,
- HIGHLIGHT: 9,
- UNDERLINE: 10,
- SQUIGGLY: 11,
- STRIKEOUT: 12,
- STAMP: 13,
- CARET: 14,
- INK: 15,
- POPUP: 16,
- FILEATTACHMENT: 17,
- SOUND: 18,
- MOVIE: 19,
- WIDGET: 20,
- SCREEN: 21,
- PRINTERMARK: 22,
- TRAPNET: 23,
- WATERMARK: 24,
- THREED: 25,
- REDACT: 26
-};
-var AnnotationFlag = {
- INVISIBLE: 0x01,
- HIDDEN: 0x02,
- PRINT: 0x04,
- NOZOOM: 0x08,
- NOROTATE: 0x10,
- NOVIEW: 0x20,
- READONLY: 0x40,
- LOCKED: 0x80,
- TOGGLENOVIEW: 0x100,
- LOCKEDCONTENTS: 0x200
-};
-var AnnotationFieldFlag = {
- READONLY: 0x0000001,
- REQUIRED: 0x0000002,
- NOEXPORT: 0x0000004,
- MULTILINE: 0x0001000,
- PASSWORD: 0x0002000,
- NOTOGGLETOOFF: 0x0004000,
- RADIO: 0x0008000,
- PUSHBUTTON: 0x0010000,
- COMBO: 0x0020000,
- EDIT: 0x0040000,
- SORT: 0x0080000,
- FILESELECT: 0x0100000,
- MULTISELECT: 0x0200000,
- DONOTSPELLCHECK: 0x0400000,
- DONOTSCROLL: 0x0800000,
- COMB: 0x1000000,
- RICHTEXT: 0x2000000,
- RADIOSINUNISON: 0x2000000,
- COMMITONSELCHANGE: 0x4000000
-};
-var AnnotationBorderStyleType = {
- SOLID: 1,
- DASHED: 2,
- BEVELED: 3,
- INSET: 4,
- UNDERLINE: 5
-};
-var StreamType = {
- UNKNOWN: 0,
- FLATE: 1,
- LZW: 2,
- DCT: 3,
- JPX: 4,
- JBIG: 5,
- A85: 6,
- AHX: 7,
- CCF: 8,
- RL: 9
-};
-var FontType = {
- UNKNOWN: 0,
- TYPE1: 1,
- TYPE1C: 2,
- CIDFONTTYPE0: 3,
- CIDFONTTYPE0C: 4,
- TRUETYPE: 5,
- CIDFONTTYPE2: 6,
- TYPE3: 7,
- OPENTYPE: 8,
- TYPE0: 9,
- MMTYPE1: 10
-};
-var VerbosityLevel = {
- ERRORS: 0,
- WARNINGS: 1,
- INFOS: 5
-};
-var CMapCompressionType = {
- NONE: 0,
- BINARY: 1,
- STREAM: 2
-};
-var OPS = {
- dependency: 1,
- setLineWidth: 2,
- setLineCap: 3,
- setLineJoin: 4,
- setMiterLimit: 5,
- setDash: 6,
- setRenderingIntent: 7,
- setFlatness: 8,
- setGState: 9,
- save: 10,
- restore: 11,
- transform: 12,
- moveTo: 13,
- lineTo: 14,
- curveTo: 15,
- curveTo2: 16,
- curveTo3: 17,
- closePath: 18,
- rectangle: 19,
- stroke: 20,
- closeStroke: 21,
- fill: 22,
- eoFill: 23,
- fillStroke: 24,
- eoFillStroke: 25,
- closeFillStroke: 26,
- closeEOFillStroke: 27,
- endPath: 28,
- clip: 29,
- eoClip: 30,
- beginText: 31,
- endText: 32,
- setCharSpacing: 33,
- setWordSpacing: 34,
- setHScale: 35,
- setLeading: 36,
- setFont: 37,
- setTextRenderingMode: 38,
- setTextRise: 39,
- moveText: 40,
- setLeadingMoveText: 41,
- setTextMatrix: 42,
- nextLine: 43,
- showText: 44,
- showSpacedText: 45,
- nextLineShowText: 46,
- nextLineSetSpacingShowText: 47,
- setCharWidth: 48,
- setCharWidthAndBounds: 49,
- setStrokeColorSpace: 50,
- setFillColorSpace: 51,
- setStrokeColor: 52,
- setStrokeColorN: 53,
- setFillColor: 54,
- setFillColorN: 55,
- setStrokeGray: 56,
- setFillGray: 57,
- setStrokeRGBColor: 58,
- setFillRGBColor: 59,
- setStrokeCMYKColor: 60,
- setFillCMYKColor: 61,
- shadingFill: 62,
- beginInlineImage: 63,
- beginImageData: 64,
- endInlineImage: 65,
- paintXObject: 66,
- markPoint: 67,
- markPointProps: 68,
- beginMarkedContent: 69,
- beginMarkedContentProps: 70,
- endMarkedContent: 71,
- beginCompat: 72,
- endCompat: 73,
- paintFormXObjectBegin: 74,
- paintFormXObjectEnd: 75,
- beginGroup: 76,
- endGroup: 77,
- beginAnnotations: 78,
- endAnnotations: 79,
- beginAnnotation: 80,
- endAnnotation: 81,
- paintJpegXObject: 82,
- paintImageMaskXObject: 83,
- paintImageMaskXObjectGroup: 84,
- paintImageXObject: 85,
- paintInlineImageXObject: 86,
- paintInlineImageXObjectGroup: 87,
- paintImageXObjectRepeat: 88,
- paintImageMaskXObjectRepeat: 89,
- paintSolidColorImageMask: 90,
- constructPath: 91
-};
-var UNSUPPORTED_FEATURES = {
- unknown: 'unknown',
- forms: 'forms',
- javaScript: 'javaScript',
- smask: 'smask',
- shadingPattern: 'shadingPattern',
- font: 'font'
-};
-var PasswordResponses = {
- NEED_PASSWORD: 1,
- INCORRECT_PASSWORD: 2
-};
-var verbosity = VerbosityLevel.WARNINGS;
-function setVerbosityLevel(level) {
- if (Number.isInteger(level)) {
- verbosity = level;
- }
-}
-function getVerbosityLevel() {
- return verbosity;
-}
-function info(msg) {
- if (verbosity >= VerbosityLevel.INFOS) {
- console.log('Info: ' + msg);
- }
-}
-function warn(msg) {
- if (verbosity >= VerbosityLevel.WARNINGS) {
- console.log('Warning: ' + msg);
- }
-}
-function deprecated(details) {
- console.log('Deprecated API usage: ' + details);
-}
-function unreachable(msg) {
- throw new Error(msg);
-}
-function assert(cond, msg) {
- if (!cond) {
- unreachable(msg);
- }
-}
-function isSameOrigin(baseUrl, otherUrl) {
- try {
- var base = new _url_polyfill.URL(baseUrl);
- if (!base.origin || base.origin === 'null') {
- return false;
- }
- } catch (e) {
- return false;
- }
- var other = new _url_polyfill.URL(otherUrl, base);
- return base.origin === other.origin;
-}
-function _isValidProtocol(url) {
- if (!url) {
- return false;
- }
- switch (url.protocol) {
- case 'http:':
- case 'https:':
- case 'ftp:':
- case 'mailto:':
- case 'tel:':
- return true;
- default:
- return false;
- }
-}
-function createValidAbsoluteUrl(url, baseUrl) {
- if (!url) {
- return null;
- }
- try {
- var absoluteUrl = baseUrl ? new _url_polyfill.URL(url, baseUrl) : new _url_polyfill.URL(url);
- if (_isValidProtocol(absoluteUrl)) {
- return absoluteUrl;
- }
- } catch (ex) {}
- return null;
-}
-function shadow(obj, prop, value) {
- Object.defineProperty(obj, prop, {
- value: value,
- enumerable: true,
- configurable: true,
- writable: false
- });
- return value;
-}
-function getLookupTableFactory(initializer) {
- var lookup;
- return function () {
- if (initializer) {
- lookup = Object.create(null);
- initializer(lookup);
- initializer = null;
- }
- return lookup;
- };
-}
-var PasswordException = function PasswordExceptionClosure() {
- function PasswordException(msg, code) {
- this.name = 'PasswordException';
- this.message = msg;
- this.code = code;
- }
- PasswordException.prototype = new Error();
- PasswordException.constructor = PasswordException;
- return PasswordException;
-}();
-var UnknownErrorException = function UnknownErrorExceptionClosure() {
- function UnknownErrorException(msg, details) {
- this.name = 'UnknownErrorException';
- this.message = msg;
- this.details = details;
- }
- UnknownErrorException.prototype = new Error();
- UnknownErrorException.constructor = UnknownErrorException;
- return UnknownErrorException;
-}();
-var InvalidPDFException = function InvalidPDFExceptionClosure() {
- function InvalidPDFException(msg) {
- this.name = 'InvalidPDFException';
- this.message = msg;
- }
- InvalidPDFException.prototype = new Error();
- InvalidPDFException.constructor = InvalidPDFException;
- return InvalidPDFException;
-}();
-var MissingPDFException = function MissingPDFExceptionClosure() {
- function MissingPDFException(msg) {
- this.name = 'MissingPDFException';
- this.message = msg;
- }
- MissingPDFException.prototype = new Error();
- MissingPDFException.constructor = MissingPDFException;
- return MissingPDFException;
-}();
-var UnexpectedResponseException = function UnexpectedResponseExceptionClosure() {
- function UnexpectedResponseException(msg, status) {
- this.name = 'UnexpectedResponseException';
- this.message = msg;
- this.status = status;
- }
- UnexpectedResponseException.prototype = new Error();
- UnexpectedResponseException.constructor = UnexpectedResponseException;
- return UnexpectedResponseException;
-}();
-var MissingDataException = function MissingDataExceptionClosure() {
- function MissingDataException(begin, end) {
- this.begin = begin;
- this.end = end;
- this.message = 'Missing data [' + begin + ', ' + end + ')';
- }
- MissingDataException.prototype = new Error();
- MissingDataException.prototype.name = 'MissingDataException';
- MissingDataException.constructor = MissingDataException;
- return MissingDataException;
-}();
-var XRefParseException = function XRefParseExceptionClosure() {
- function XRefParseException(msg) {
- this.message = msg;
- }
- XRefParseException.prototype = new Error();
- XRefParseException.prototype.name = 'XRefParseException';
- XRefParseException.constructor = XRefParseException;
- return XRefParseException;
-}();
-var FormatError = function FormatErrorClosure() {
- function FormatError(msg) {
- this.message = msg;
- }
- FormatError.prototype = new Error();
- FormatError.prototype.name = 'FormatError';
- FormatError.constructor = FormatError;
- return FormatError;
-}();
-var AbortException = function AbortExceptionClosure() {
- function AbortException(msg) {
- this.name = 'AbortException';
- this.message = msg;
- }
- AbortException.prototype = new Error();
- AbortException.constructor = AbortException;
- return AbortException;
-}();
-var NullCharactersRegExp = /\x00/g;
-function removeNullCharacters(str) {
- if (typeof str !== 'string') {
- warn('The argument for removeNullCharacters must be a string.');
- return str;
- }
- return str.replace(NullCharactersRegExp, '');
-}
-function bytesToString(bytes) {
- assert(bytes !== null && (typeof bytes === 'undefined' ? 'undefined' : _typeof(bytes)) === 'object' && bytes.length !== undefined, 'Invalid argument for bytesToString');
- var length = bytes.length;
- var MAX_ARGUMENT_COUNT = 8192;
- if (length < MAX_ARGUMENT_COUNT) {
- return String.fromCharCode.apply(null, bytes);
- }
- var strBuf = [];
- for (var i = 0; i < length; i += MAX_ARGUMENT_COUNT) {
- var chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);
- var chunk = bytes.subarray(i, chunkEnd);
- strBuf.push(String.fromCharCode.apply(null, chunk));
- }
- return strBuf.join('');
-}
-function stringToBytes(str) {
- assert(typeof str === 'string', 'Invalid argument for stringToBytes');
- var length = str.length;
- var bytes = new Uint8Array(length);
- for (var i = 0; i < length; ++i) {
- bytes[i] = str.charCodeAt(i) & 0xFF;
- }
- return bytes;
-}
-function arrayByteLength(arr) {
- if (arr.length !== undefined) {
- return arr.length;
- }
- assert(arr.byteLength !== undefined);
- return arr.byteLength;
-}
-function arraysToBytes(arr) {
- if (arr.length === 1 && arr[0] instanceof Uint8Array) {
- return arr[0];
- }
- var resultLength = 0;
- var i,
- ii = arr.length;
- var item, itemLength;
- for (i = 0; i < ii; i++) {
- item = arr[i];
- itemLength = arrayByteLength(item);
- resultLength += itemLength;
- }
- var pos = 0;
- var data = new Uint8Array(resultLength);
- for (i = 0; i < ii; i++) {
- item = arr[i];
- if (!(item instanceof Uint8Array)) {
- if (typeof item === 'string') {
- item = stringToBytes(item);
- } else {
- item = new Uint8Array(item);
- }
- }
- itemLength = item.byteLength;
- data.set(item, pos);
- pos += itemLength;
- }
- return data;
-}
-function string32(value) {
- return String.fromCharCode(value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff);
-}
-function log2(x) {
- if (x <= 0) {
- return 0;
- }
- return Math.ceil(Math.log2(x));
-}
-function readInt8(data, start) {
- return data[start] << 24 >> 24;
-}
-function readUint16(data, offset) {
- return data[offset] << 8 | data[offset + 1];
-}
-function readUint32(data, offset) {
- return (data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]) >>> 0;
-}
-function isLittleEndian() {
- var buffer8 = new Uint8Array(4);
- buffer8[0] = 1;
- var view32 = new Uint32Array(buffer8.buffer, 0, 1);
- return view32[0] === 1;
-}
-function isEvalSupported() {
- try {
- new Function('');
- return true;
- } catch (e) {
- return false;
- }
-}
-function getInheritableProperty(_ref) {
- var dict = _ref.dict,
- key = _ref.key,
- _ref$getArray = _ref.getArray,
- getArray = _ref$getArray === undefined ? false : _ref$getArray,
- _ref$stopWhenFound = _ref.stopWhenFound,
- stopWhenFound = _ref$stopWhenFound === undefined ? true : _ref$stopWhenFound;
-
- var LOOP_LIMIT = 100;
- var loopCount = 0;
- var values = void 0;
- while (dict) {
- var value = getArray ? dict.getArray(key) : dict.get(key);
- if (value !== undefined) {
- if (stopWhenFound) {
- return value;
- }
- if (!values) {
- values = [];
- }
- values.push(value);
- }
- if (++loopCount > LOOP_LIMIT) {
- warn('getInheritableProperty: maximum loop count exceeded for "' + key + '"');
- break;
- }
- dict = dict.get('Parent');
- }
- return values;
-}
-var Util = function UtilClosure() {
- function Util() {}
- var rgbBuf = ['rgb(', 0, ',', 0, ',', 0, ')'];
- Util.makeCssRgb = function Util_makeCssRgb(r, g, b) {
- rgbBuf[1] = r;
- rgbBuf[3] = g;
- rgbBuf[5] = b;
- return rgbBuf.join('');
- };
- Util.transform = function Util_transform(m1, m2) {
- return [m1[0] * m2[0] + m1[2] * m2[1], m1[1] * m2[0] + m1[3] * m2[1], m1[0] * m2[2] + m1[2] * m2[3], m1[1] * m2[2] + m1[3] * m2[3], m1[0] * m2[4] + m1[2] * m2[5] + m1[4], m1[1] * m2[4] + m1[3] * m2[5] + m1[5]];
- };
- Util.applyTransform = function Util_applyTransform(p, m) {
- var xt = p[0] * m[0] + p[1] * m[2] + m[4];
- var yt = p[0] * m[1] + p[1] * m[3] + m[5];
- return [xt, yt];
- };
- Util.applyInverseTransform = function Util_applyInverseTransform(p, m) {
- var d = m[0] * m[3] - m[1] * m[2];
- var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
- var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
- return [xt, yt];
- };
- Util.getAxialAlignedBoundingBox = function Util_getAxialAlignedBoundingBox(r, m) {
- var p1 = Util.applyTransform(r, m);
- var p2 = Util.applyTransform(r.slice(2, 4), m);
- var p3 = Util.applyTransform([r[0], r[3]], m);
- var p4 = Util.applyTransform([r[2], r[1]], m);
- return [Math.min(p1[0], p2[0], p3[0], p4[0]), Math.min(p1[1], p2[1], p3[1], p4[1]), Math.max(p1[0], p2[0], p3[0], p4[0]), Math.max(p1[1], p2[1], p3[1], p4[1])];
- };
- Util.inverseTransform = function Util_inverseTransform(m) {
- var d = m[0] * m[3] - m[1] * m[2];
- return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d];
- };
- Util.apply3dTransform = function Util_apply3dTransform(m, v) {
- return [m[0] * v[0] + m[1] * v[1] + m[2] * v[2], m[3] * v[0] + m[4] * v[1] + m[5] * v[2], m[6] * v[0] + m[7] * v[1] + m[8] * v[2]];
- };
- Util.singularValueDecompose2dScale = function Util_singularValueDecompose2dScale(m) {
- var transpose = [m[0], m[2], m[1], m[3]];
- var a = m[0] * transpose[0] + m[1] * transpose[2];
- var b = m[0] * transpose[1] + m[1] * transpose[3];
- var c = m[2] * transpose[0] + m[3] * transpose[2];
- var d = m[2] * transpose[1] + m[3] * transpose[3];
- var first = (a + d) / 2;
- var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2;
- var sx = first + second || 1;
- var sy = first - second || 1;
- return [Math.sqrt(sx), Math.sqrt(sy)];
- };
- Util.normalizeRect = function Util_normalizeRect(rect) {
- var r = rect.slice(0);
- if (rect[0] > rect[2]) {
- r[0] = rect[2];
- r[2] = rect[0];
- }
- if (rect[1] > rect[3]) {
- r[1] = rect[3];
- r[3] = rect[1];
- }
- return r;
- };
- Util.intersect = function Util_intersect(rect1, rect2) {
- function compare(a, b) {
- return a - b;
- }
- var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare),
- orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare),
- result = [];
- rect1 = Util.normalizeRect(rect1);
- rect2 = Util.normalizeRect(rect2);
- if (orderedX[0] === rect1[0] && orderedX[1] === rect2[0] || orderedX[0] === rect2[0] && orderedX[1] === rect1[0]) {
- result[0] = orderedX[1];
- result[2] = orderedX[2];
- } else {
- return false;
- }
- if (orderedY[0] === rect1[1] && orderedY[1] === rect2[1] || orderedY[0] === rect2[1] && orderedY[1] === rect1[1]) {
- result[1] = orderedY[1];
- result[3] = orderedY[2];
- } else {
- return false;
- }
- return result;
- };
- return Util;
-}();
-var ROMAN_NUMBER_MAP = ['', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM', '', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC', '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'];
-function toRomanNumerals(number) {
- var lowerCase = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
-
- assert(Number.isInteger(number) && number > 0, 'The number should be a positive integer.');
- var pos = void 0,
- romanBuf = [];
- while (number >= 1000) {
- number -= 1000;
- romanBuf.push('M');
- }
- pos = number / 100 | 0;
- number %= 100;
- romanBuf.push(ROMAN_NUMBER_MAP[pos]);
- pos = number / 10 | 0;
- number %= 10;
- romanBuf.push(ROMAN_NUMBER_MAP[10 + pos]);
- romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);
- var romanStr = romanBuf.join('');
- return lowerCase ? romanStr.toLowerCase() : romanStr;
-}
-var PDFStringTranslateTable = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160, 0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC];
-function stringToPDFString(str) {
- var i,
- n = str.length,
- strBuf = [];
- if (str[0] === '\xFE' && str[1] === '\xFF') {
- for (i = 2; i < n; i += 2) {
- strBuf.push(String.fromCharCode(str.charCodeAt(i) << 8 | str.charCodeAt(i + 1)));
- }
- } else {
- for (i = 0; i < n; ++i) {
- var code = PDFStringTranslateTable[str.charCodeAt(i)];
- strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
- }
- }
- return strBuf.join('');
-}
-function stringToUTF8String(str) {
- return decodeURIComponent(escape(str));
-}
-function utf8StringToString(str) {
- return unescape(encodeURIComponent(str));
-}
-function isEmptyObj(obj) {
- for (var key in obj) {
- return false;
- }
- return true;
-}
-function isBool(v) {
- return typeof v === 'boolean';
-}
-function isNum(v) {
- return typeof v === 'number';
-}
-function isString(v) {
- return typeof v === 'string';
-}
-function isArrayBuffer(v) {
- return (typeof v === 'undefined' ? 'undefined' : _typeof(v)) === 'object' && v !== null && v.byteLength !== undefined;
-}
-function isSpace(ch) {
- return ch === 0x20 || ch === 0x09 || ch === 0x0D || ch === 0x0A;
-}
-function createPromiseCapability() {
- var capability = {};
- capability.promise = new Promise(function (resolve, reject) {
- capability.resolve = resolve;
- capability.reject = reject;
- });
- return capability;
-}
-var createObjectURL = function createObjectURLClosure() {
- var digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
- return function createObjectURL(data, contentType) {
- var forceDataSchema = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
-
- if (!forceDataSchema && _url_polyfill.URL.createObjectURL) {
- var blob = new Blob([data], { type: contentType });
- return _url_polyfill.URL.createObjectURL(blob);
- }
- var buffer = 'data:' + contentType + ';base64,';
- for (var i = 0, ii = data.length; i < ii; i += 3) {
- var b1 = data[i] & 0xFF;
- var b2 = data[i + 1] & 0xFF;
- var b3 = data[i + 2] & 0xFF;
- var d1 = b1 >> 2,
- d2 = (b1 & 3) << 4 | b2 >> 4;
- var d3 = i + 1 < ii ? (b2 & 0xF) << 2 | b3 >> 6 : 64;
- var d4 = i + 2 < ii ? b3 & 0x3F : 64;
- buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
- }
- return buffer;
- };
-}();
-exports.FONT_IDENTITY_MATRIX = FONT_IDENTITY_MATRIX;
-exports.IDENTITY_MATRIX = IDENTITY_MATRIX;
-exports.OPS = OPS;
-exports.VerbosityLevel = VerbosityLevel;
-exports.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES;
-exports.AnnotationBorderStyleType = AnnotationBorderStyleType;
-exports.AnnotationFieldFlag = AnnotationFieldFlag;
-exports.AnnotationFlag = AnnotationFlag;
-exports.AnnotationType = AnnotationType;
-exports.FontType = FontType;
-exports.ImageKind = ImageKind;
-exports.CMapCompressionType = CMapCompressionType;
-exports.AbortException = AbortException;
-exports.InvalidPDFException = InvalidPDFException;
-exports.MissingDataException = MissingDataException;
-exports.MissingPDFException = MissingPDFException;
-exports.NativeImageDecoding = NativeImageDecoding;
-exports.PasswordException = PasswordException;
-exports.PasswordResponses = PasswordResponses;
-exports.PermissionFlag = PermissionFlag;
-exports.StreamType = StreamType;
-exports.TextRenderingMode = TextRenderingMode;
-exports.UnexpectedResponseException = UnexpectedResponseException;
-exports.UnknownErrorException = UnknownErrorException;
-exports.Util = Util;
-exports.toRomanNumerals = toRomanNumerals;
-exports.XRefParseException = XRefParseException;
-exports.FormatError = FormatError;
-exports.arrayByteLength = arrayByteLength;
-exports.arraysToBytes = arraysToBytes;
-exports.assert = assert;
-exports.bytesToString = bytesToString;
-exports.createPromiseCapability = createPromiseCapability;
-exports.createObjectURL = createObjectURL;
-exports.deprecated = deprecated;
-exports.getInheritableProperty = getInheritableProperty;
-exports.getLookupTableFactory = getLookupTableFactory;
-exports.getVerbosityLevel = getVerbosityLevel;
-exports.info = info;
-exports.isArrayBuffer = isArrayBuffer;
-exports.isBool = isBool;
-exports.isEmptyObj = isEmptyObj;
-exports.isNum = isNum;
-exports.isString = isString;
-exports.isSpace = isSpace;
-exports.isSameOrigin = isSameOrigin;
-exports.createValidAbsoluteUrl = createValidAbsoluteUrl;
-exports.isLittleEndian = isLittleEndian;
-exports.isEvalSupported = isEvalSupported;
-exports.log2 = log2;
-exports.readInt8 = readInt8;
-exports.readUint16 = readUint16;
-exports.readUint32 = readUint32;
-exports.removeNullCharacters = removeNullCharacters;
-exports.ReadableStream = _streams_polyfill.ReadableStream;
-exports.URL = _url_polyfill.URL;
-exports.setVerbosityLevel = setVerbosityLevel;
-exports.shadow = shadow;
-exports.string32 = string32;
-exports.stringToBytes = stringToBytes;
-exports.stringToPDFString = stringToPDFString;
-exports.stringToUTF8String = stringToUTF8String;
-exports.utf8StringToString = utf8StringToString;
-exports.warn = warn;
-exports.unreachable = unreachable;
-
-/***/ }),
-/* 3 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-var globalScope = __w_pdfjs_require__(4);
-if (!globalScope._pdfjsCompatibilityChecked) {
- globalScope._pdfjsCompatibilityChecked = true;
- var isNodeJS = __w_pdfjs_require__(5);
- var hasDOM = (typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && (typeof document === 'undefined' ? 'undefined' : _typeof(document)) === 'object';
- (function checkNodeBtoa() {
- if (globalScope.btoa || !isNodeJS()) {
- return;
- }
- globalScope.btoa = function (chars) {
- return Buffer.from(chars, 'binary').toString('base64');
- };
- })();
- (function checkNodeAtob() {
- if (globalScope.atob || !isNodeJS()) {
- return;
- }
- globalScope.atob = function (input) {
- return Buffer.from(input, 'base64').toString('binary');
- };
- })();
- (function checkCurrentScript() {
- if (!hasDOM) {
- return;
- }
- if ('currentScript' in document) {
- return;
- }
- Object.defineProperty(document, 'currentScript', {
- get: function get() {
- var scripts = document.getElementsByTagName('script');
- return scripts[scripts.length - 1];
- },
-
- enumerable: true,
- configurable: true
- });
- })();
- (function checkChildNodeRemove() {
- if (!hasDOM) {
- return;
- }
- if (typeof Element.prototype.remove !== 'undefined') {
- return;
- }
- Element.prototype.remove = function () {
- if (this.parentNode) {
- this.parentNode.removeChild(this);
- }
- };
- })();
- (function checkDOMTokenListToggle() {
- if (!hasDOM || isNodeJS()) {
- return;
- }
- var div = document.createElement('div');
- if (div.classList.toggle('test', 0) === false) {
- return;
- }
- var originalDOMTokenListToggle = DOMTokenList.prototype.toggle;
- DOMTokenList.prototype.toggle = function (token) {
- if (arguments.length > 1) {
- var force = !!arguments[1];
- return this[force ? 'add' : 'remove'](token), force;
- }
- return originalDOMTokenListToggle(token);
- };
- })();
- (function checkStringIncludes() {
- if (String.prototype.includes) {
- return;
- }
- __w_pdfjs_require__(6);
- })();
- (function checkArrayIncludes() {
- if (Array.prototype.includes) {
- return;
- }
- __w_pdfjs_require__(34);
- })();
- (function checkObjectAssign() {
- if (Object.assign) {
- return;
- }
- __w_pdfjs_require__(43);
- })();
- (function checkMathLog2() {
- if (Math.log2) {
- return;
- }
- Math.log2 = __w_pdfjs_require__(53);
- })();
- (function checkNumberIsNaN() {
- if (Number.isNaN) {
- return;
- }
- Number.isNaN = __w_pdfjs_require__(55);
- })();
- (function checkNumberIsInteger() {
- if (Number.isInteger) {
- return;
- }
- Number.isInteger = __w_pdfjs_require__(57);
- })();
- (function checkPromise() {
- if (globalScope.Promise) {
- return;
- }
- globalScope.Promise = __w_pdfjs_require__(60);
- })();
- (function checkWeakMap() {
- if (globalScope.WeakMap) {
- return;
- }
- globalScope.WeakMap = __w_pdfjs_require__(95);
- })();
- (function checkStringCodePointAt() {
- if (String.codePointAt) {
- return;
- }
- String.codePointAt = __w_pdfjs_require__(112);
- })();
- (function checkStringFromCodePoint() {
- if (String.fromCodePoint) {
- return;
- }
- String.fromCodePoint = __w_pdfjs_require__(114);
- })();
- (function checkSymbol() {
- if (globalScope.Symbol) {
- return;
- }
- __w_pdfjs_require__(116);
- })();
- (function checkObjectValues() {
- if (Object.values) {
- return;
- }
- Object.values = __w_pdfjs_require__(123);
- })();
-}
-
-/***/ }),
-/* 4 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = typeof window !== 'undefined' && window.Math === Math ? window : typeof global !== 'undefined' && global.Math === Math ? global : typeof self !== 'undefined' && self.Math === Math ? self : {};
-
-/***/ }),
-/* 5 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-module.exports = function isNodeJS() {
- return (typeof process === 'undefined' ? 'undefined' : _typeof(process)) === 'object' && process + '' === '[object process]';
-};
-
-/***/ }),
-/* 6 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(7);
-module.exports = __w_pdfjs_require__(10).String.includes;
-
-/***/ }),
-/* 7 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(8);
-var context = __w_pdfjs_require__(26);
-var INCLUDES = 'includes';
-$export($export.P + $export.F * __w_pdfjs_require__(33)(INCLUDES), 'String', {
- includes: function includes(searchString) {
- return !!~context(this, searchString, INCLUDES).indexOf(searchString, arguments.length > 1 ? arguments[1] : undefined);
- }
-});
-
-/***/ }),
-/* 8 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var global = __w_pdfjs_require__(9);
-var core = __w_pdfjs_require__(10);
-var hide = __w_pdfjs_require__(11);
-var redefine = __w_pdfjs_require__(21);
-var ctx = __w_pdfjs_require__(24);
-var PROTOTYPE = 'prototype';
-var $export = function $export(type, name, source) {
- var IS_FORCED = type & $export.F;
- var IS_GLOBAL = type & $export.G;
- var IS_STATIC = type & $export.S;
- var IS_PROTO = type & $export.P;
- var IS_BIND = type & $export.B;
- var target = IS_GLOBAL ? global : IS_STATIC ? global[name] || (global[name] = {}) : (global[name] || {})[PROTOTYPE];
- var exports = IS_GLOBAL ? core : core[name] || (core[name] = {});
- var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {});
- var key, own, out, exp;
- if (IS_GLOBAL) source = name;
- for (key in source) {
- own = !IS_FORCED && target && target[key] !== undefined;
- out = (own ? target : source)[key];
- exp = IS_BIND && own ? ctx(out, global) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;
- if (target) redefine(target, key, out, type & $export.U);
- if (exports[key] != out) hide(exports, key, exp);
- if (IS_PROTO && expProto[key] != out) expProto[key] = out;
- }
-};
-global.core = core;
-$export.F = 1;
-$export.G = 2;
-$export.S = 4;
-$export.P = 8;
-$export.B = 16;
-$export.W = 32;
-$export.U = 64;
-$export.R = 128;
-module.exports = $export;
-
-/***/ }),
-/* 9 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var global = module.exports = typeof window != 'undefined' && window.Math == Math ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')();
-if (typeof __g == 'number') __g = global;
-
-/***/ }),
-/* 10 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var core = module.exports = { version: '2.5.7' };
-if (typeof __e == 'number') __e = core;
-
-/***/ }),
-/* 11 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var dP = __w_pdfjs_require__(12);
-var createDesc = __w_pdfjs_require__(20);
-module.exports = __w_pdfjs_require__(16) ? function (object, key, value) {
- return dP.f(object, key, createDesc(1, value));
-} : function (object, key, value) {
- object[key] = value;
- return object;
-};
-
-/***/ }),
-/* 12 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var anObject = __w_pdfjs_require__(13);
-var IE8_DOM_DEFINE = __w_pdfjs_require__(15);
-var toPrimitive = __w_pdfjs_require__(19);
-var dP = Object.defineProperty;
-exports.f = __w_pdfjs_require__(16) ? Object.defineProperty : function defineProperty(O, P, Attributes) {
- anObject(O);
- P = toPrimitive(P, true);
- anObject(Attributes);
- if (IE8_DOM_DEFINE) try {
- return dP(O, P, Attributes);
- } catch (e) {}
- if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!');
- if ('value' in Attributes) O[P] = Attributes.value;
- return O;
-};
-
-/***/ }),
-/* 13 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isObject = __w_pdfjs_require__(14);
-module.exports = function (it) {
- if (!isObject(it)) throw TypeError(it + ' is not an object!');
- return it;
-};
-
-/***/ }),
-/* 14 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-module.exports = function (it) {
- return (typeof it === 'undefined' ? 'undefined' : _typeof(it)) === 'object' ? it !== null : typeof it === 'function';
-};
-
-/***/ }),
-/* 15 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = !__w_pdfjs_require__(16) && !__w_pdfjs_require__(17)(function () {
- return Object.defineProperty(__w_pdfjs_require__(18)('div'), 'a', {
- get: function get() {
- return 7;
- }
- }).a != 7;
-});
-
-/***/ }),
-/* 16 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = !__w_pdfjs_require__(17)(function () {
- return Object.defineProperty({}, 'a', {
- get: function get() {
- return 7;
- }
- }).a != 7;
-});
-
-/***/ }),
-/* 17 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = function (exec) {
- try {
- return !!exec();
- } catch (e) {
- return true;
- }
-};
-
-/***/ }),
-/* 18 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isObject = __w_pdfjs_require__(14);
-var document = __w_pdfjs_require__(9).document;
-var is = isObject(document) && isObject(document.createElement);
-module.exports = function (it) {
- return is ? document.createElement(it) : {};
-};
-
-/***/ }),
-/* 19 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isObject = __w_pdfjs_require__(14);
-module.exports = function (it, S) {
- if (!isObject(it)) return it;
- var fn, val;
- if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;
- if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val;
- if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;
- throw TypeError("Can't convert object to primitive value");
-};
-
-/***/ }),
-/* 20 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = function (bitmap, value) {
- return {
- enumerable: !(bitmap & 1),
- configurable: !(bitmap & 2),
- writable: !(bitmap & 4),
- value: value
- };
-};
-
-/***/ }),
-/* 21 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var global = __w_pdfjs_require__(9);
-var hide = __w_pdfjs_require__(11);
-var has = __w_pdfjs_require__(22);
-var SRC = __w_pdfjs_require__(23)('src');
-var TO_STRING = 'toString';
-var $toString = Function[TO_STRING];
-var TPL = ('' + $toString).split(TO_STRING);
-__w_pdfjs_require__(10).inspectSource = function (it) {
- return $toString.call(it);
-};
-(module.exports = function (O, key, val, safe) {
- var isFunction = typeof val == 'function';
- if (isFunction) has(val, 'name') || hide(val, 'name', key);
- if (O[key] === val) return;
- if (isFunction) has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key)));
- if (O === global) {
- O[key] = val;
- } else if (!safe) {
- delete O[key];
- hide(O, key, val);
- } else if (O[key]) {
- O[key] = val;
- } else {
- hide(O, key, val);
- }
-})(Function.prototype, TO_STRING, function toString() {
- return typeof this == 'function' && this[SRC] || $toString.call(this);
-});
-
-/***/ }),
-/* 22 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var hasOwnProperty = {}.hasOwnProperty;
-module.exports = function (it, key) {
- return hasOwnProperty.call(it, key);
-};
-
-/***/ }),
-/* 23 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var id = 0;
-var px = Math.random();
-module.exports = function (key) {
- return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));
-};
-
-/***/ }),
-/* 24 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var aFunction = __w_pdfjs_require__(25);
-module.exports = function (fn, that, length) {
- aFunction(fn);
- if (that === undefined) return fn;
- switch (length) {
- case 1:
- return function (a) {
- return fn.call(that, a);
- };
- case 2:
- return function (a, b) {
- return fn.call(that, a, b);
- };
- case 3:
- return function (a, b, c) {
- return fn.call(that, a, b, c);
- };
- }
- return function () {
- return fn.apply(that, arguments);
- };
-};
-
-/***/ }),
-/* 25 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = function (it) {
- if (typeof it != 'function') throw TypeError(it + ' is not a function!');
- return it;
-};
-
-/***/ }),
-/* 26 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isRegExp = __w_pdfjs_require__(27);
-var defined = __w_pdfjs_require__(32);
-module.exports = function (that, searchString, NAME) {
- if (isRegExp(searchString)) throw TypeError('String#' + NAME + " doesn't accept regex!");
- return String(defined(that));
-};
-
-/***/ }),
-/* 27 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isObject = __w_pdfjs_require__(14);
-var cof = __w_pdfjs_require__(28);
-var MATCH = __w_pdfjs_require__(29)('match');
-module.exports = function (it) {
- var isRegExp;
- return isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : cof(it) == 'RegExp');
-};
-
-/***/ }),
-/* 28 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var toString = {}.toString;
-module.exports = function (it) {
- return toString.call(it).slice(8, -1);
-};
-
-/***/ }),
-/* 29 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var store = __w_pdfjs_require__(30)('wks');
-var uid = __w_pdfjs_require__(23);
-var _Symbol = __w_pdfjs_require__(9).Symbol;
-var USE_SYMBOL = typeof _Symbol == 'function';
-var $exports = module.exports = function (name) {
- return store[name] || (store[name] = USE_SYMBOL && _Symbol[name] || (USE_SYMBOL ? _Symbol : uid)('Symbol.' + name));
-};
-$exports.store = store;
-
-/***/ }),
-/* 30 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var core = __w_pdfjs_require__(10);
-var global = __w_pdfjs_require__(9);
-var SHARED = '__core-js_shared__';
-var store = global[SHARED] || (global[SHARED] = {});
-(module.exports = function (key, value) {
- return store[key] || (store[key] = value !== undefined ? value : {});
-})('versions', []).push({
- version: core.version,
- mode: __w_pdfjs_require__(31) ? 'pure' : 'global',
- copyright: '© 2018 Denis Pushkarev (zloirock.ru)'
-});
-
-/***/ }),
-/* 31 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = false;
-
-/***/ }),
-/* 32 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = function (it) {
- if (it == undefined) throw TypeError("Can't call method on " + it);
- return it;
-};
-
-/***/ }),
-/* 33 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var MATCH = __w_pdfjs_require__(29)('match');
-module.exports = function (KEY) {
- var re = /./;
- try {
- '/./'[KEY](re);
- } catch (e) {
- try {
- re[MATCH] = false;
- return !'/./'[KEY](re);
- } catch (f) {}
- }
- return true;
-};
-
-/***/ }),
-/* 34 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(35);
-module.exports = __w_pdfjs_require__(10).Array.includes;
-
-/***/ }),
-/* 35 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(8);
-var $includes = __w_pdfjs_require__(36)(true);
-$export($export.P, 'Array', {
- includes: function includes(el) {
- return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined);
- }
-});
-__w_pdfjs_require__(42)('includes');
-
-/***/ }),
-/* 36 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var toIObject = __w_pdfjs_require__(37);
-var toLength = __w_pdfjs_require__(39);
-var toAbsoluteIndex = __w_pdfjs_require__(41);
-module.exports = function (IS_INCLUDES) {
- return function ($this, el, fromIndex) {
- var O = toIObject($this);
- var length = toLength(O.length);
- var index = toAbsoluteIndex(fromIndex, length);
- var value;
- if (IS_INCLUDES && el != el) while (length > index) {
- value = O[index++];
- if (value != value) return true;
- } else for (; length > index; index++) {
- if (IS_INCLUDES || index in O) {
- if (O[index] === el) return IS_INCLUDES || index || 0;
- }
- }return !IS_INCLUDES && -1;
- };
-};
-
-/***/ }),
-/* 37 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var IObject = __w_pdfjs_require__(38);
-var defined = __w_pdfjs_require__(32);
-module.exports = function (it) {
- return IObject(defined(it));
-};
-
-/***/ }),
-/* 38 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var cof = __w_pdfjs_require__(28);
-module.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) {
- return cof(it) == 'String' ? it.split('') : Object(it);
-};
-
-/***/ }),
-/* 39 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var toInteger = __w_pdfjs_require__(40);
-var min = Math.min;
-module.exports = function (it) {
- return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0;
-};
-
-/***/ }),
-/* 40 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var ceil = Math.ceil;
-var floor = Math.floor;
-module.exports = function (it) {
- return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);
-};
-
-/***/ }),
-/* 41 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var toInteger = __w_pdfjs_require__(40);
-var max = Math.max;
-var min = Math.min;
-module.exports = function (index, length) {
- index = toInteger(index);
- return index < 0 ? max(index + length, 0) : min(index, length);
-};
-
-/***/ }),
-/* 42 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var UNSCOPABLES = __w_pdfjs_require__(29)('unscopables');
-var ArrayProto = Array.prototype;
-if (ArrayProto[UNSCOPABLES] == undefined) __w_pdfjs_require__(11)(ArrayProto, UNSCOPABLES, {});
-module.exports = function (key) {
- ArrayProto[UNSCOPABLES][key] = true;
-};
-
-/***/ }),
-/* 43 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(44);
-module.exports = __w_pdfjs_require__(10).Object.assign;
-
-/***/ }),
-/* 44 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(8);
-$export($export.S + $export.F, 'Object', { assign: __w_pdfjs_require__(45) });
-
-/***/ }),
-/* 45 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var getKeys = __w_pdfjs_require__(46);
-var gOPS = __w_pdfjs_require__(50);
-var pIE = __w_pdfjs_require__(51);
-var toObject = __w_pdfjs_require__(52);
-var IObject = __w_pdfjs_require__(38);
-var $assign = Object.assign;
-module.exports = !$assign || __w_pdfjs_require__(17)(function () {
- var A = {};
- var B = {};
- var S = Symbol();
- var K = 'abcdefghijklmnopqrst';
- A[S] = 7;
- K.split('').forEach(function (k) {
- B[k] = k;
- });
- return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K;
-}) ? function assign(target, source) {
- var T = toObject(target);
- var aLen = arguments.length;
- var index = 1;
- var getSymbols = gOPS.f;
- var isEnum = pIE.f;
- while (aLen > index) {
- var S = IObject(arguments[index++]);
- var keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S);
- var length = keys.length;
- var j = 0;
- var key;
- while (length > j) {
- if (isEnum.call(S, key = keys[j++])) T[key] = S[key];
- }
- }
- return T;
-} : $assign;
-
-/***/ }),
-/* 46 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $keys = __w_pdfjs_require__(47);
-var enumBugKeys = __w_pdfjs_require__(49);
-module.exports = Object.keys || function keys(O) {
- return $keys(O, enumBugKeys);
-};
-
-/***/ }),
-/* 47 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var has = __w_pdfjs_require__(22);
-var toIObject = __w_pdfjs_require__(37);
-var arrayIndexOf = __w_pdfjs_require__(36)(false);
-var IE_PROTO = __w_pdfjs_require__(48)('IE_PROTO');
-module.exports = function (object, names) {
- var O = toIObject(object);
- var i = 0;
- var result = [];
- var key;
- for (key in O) {
- if (key != IE_PROTO) has(O, key) && result.push(key);
- }while (names.length > i) {
- if (has(O, key = names[i++])) {
- ~arrayIndexOf(result, key) || result.push(key);
- }
- }return result;
-};
-
-/***/ }),
-/* 48 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var shared = __w_pdfjs_require__(30)('keys');
-var uid = __w_pdfjs_require__(23);
-module.exports = function (key) {
- return shared[key] || (shared[key] = uid(key));
-};
-
-/***/ }),
-/* 49 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'.split(',');
-
-/***/ }),
-/* 50 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-exports.f = Object.getOwnPropertySymbols;
-
-/***/ }),
-/* 51 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-exports.f = {}.propertyIsEnumerable;
-
-/***/ }),
-/* 52 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var defined = __w_pdfjs_require__(32);
-module.exports = function (it) {
- return Object(defined(it));
-};
-
-/***/ }),
-/* 53 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(54);
-module.exports = __w_pdfjs_require__(10).Math.log2;
-
-/***/ }),
-/* 54 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(8);
-$export($export.S, 'Math', {
- log2: function log2(x) {
- return Math.log(x) / Math.LN2;
- }
-});
-
-/***/ }),
-/* 55 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(56);
-module.exports = __w_pdfjs_require__(10).Number.isNaN;
-
-/***/ }),
-/* 56 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(8);
-$export($export.S, 'Number', {
- isNaN: function isNaN(number) {
- return number != number;
- }
-});
-
-/***/ }),
-/* 57 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(58);
-module.exports = __w_pdfjs_require__(10).Number.isInteger;
-
-/***/ }),
-/* 58 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(8);
-$export($export.S, 'Number', { isInteger: __w_pdfjs_require__(59) });
-
-/***/ }),
-/* 59 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isObject = __w_pdfjs_require__(14);
-var floor = Math.floor;
-module.exports = function isInteger(it) {
- return !isObject(it) && isFinite(it) && floor(it) === it;
-};
-
-/***/ }),
-/* 60 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(61);
-__w_pdfjs_require__(63);
-__w_pdfjs_require__(73);
-__w_pdfjs_require__(76);
-__w_pdfjs_require__(93);
-__w_pdfjs_require__(94);
-module.exports = __w_pdfjs_require__(10).Promise;
-
-/***/ }),
-/* 61 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var classof = __w_pdfjs_require__(62);
-var test = {};
-test[__w_pdfjs_require__(29)('toStringTag')] = 'z';
-if (test + '' != '[object z]') {
- __w_pdfjs_require__(21)(Object.prototype, 'toString', function toString() {
- return '[object ' + classof(this) + ']';
- }, true);
-}
-
-/***/ }),
-/* 62 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var cof = __w_pdfjs_require__(28);
-var TAG = __w_pdfjs_require__(29)('toStringTag');
-var ARG = cof(function () {
- return arguments;
-}()) == 'Arguments';
-var tryGet = function tryGet(it, key) {
- try {
- return it[key];
- } catch (e) {}
-};
-module.exports = function (it) {
- var O, T, B;
- return it === undefined ? 'Undefined' : it === null ? 'Null' : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T : ARG ? cof(O) : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B;
-};
-
-/***/ }),
-/* 63 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $at = __w_pdfjs_require__(64)(true);
-__w_pdfjs_require__(65)(String, 'String', function (iterated) {
- this._t = String(iterated);
- this._i = 0;
-}, function () {
- var O = this._t;
- var index = this._i;
- var point;
- if (index >= O.length) return {
- value: undefined,
- done: true
- };
- point = $at(O, index);
- this._i += point.length;
- return {
- value: point,
- done: false
- };
-});
-
-/***/ }),
-/* 64 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var toInteger = __w_pdfjs_require__(40);
-var defined = __w_pdfjs_require__(32);
-module.exports = function (TO_STRING) {
- return function (that, pos) {
- var s = String(defined(that));
- var i = toInteger(pos);
- var l = s.length;
- var a, b;
- if (i < 0 || i >= l) return TO_STRING ? '' : undefined;
- a = s.charCodeAt(i);
- return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff ? TO_STRING ? s.charAt(i) : a : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000;
- };
-};
-
-/***/ }),
-/* 65 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var LIBRARY = __w_pdfjs_require__(31);
-var $export = __w_pdfjs_require__(8);
-var redefine = __w_pdfjs_require__(21);
-var hide = __w_pdfjs_require__(11);
-var Iterators = __w_pdfjs_require__(66);
-var $iterCreate = __w_pdfjs_require__(67);
-var setToStringTag = __w_pdfjs_require__(71);
-var getPrototypeOf = __w_pdfjs_require__(72);
-var ITERATOR = __w_pdfjs_require__(29)('iterator');
-var BUGGY = !([].keys && 'next' in [].keys());
-var FF_ITERATOR = '@@iterator';
-var KEYS = 'keys';
-var VALUES = 'values';
-var returnThis = function returnThis() {
- return this;
-};
-module.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) {
- $iterCreate(Constructor, NAME, next);
- var getMethod = function getMethod(kind) {
- if (!BUGGY && kind in proto) return proto[kind];
- switch (kind) {
- case KEYS:
- return function keys() {
- return new Constructor(this, kind);
- };
- case VALUES:
- return function values() {
- return new Constructor(this, kind);
- };
- }
- return function entries() {
- return new Constructor(this, kind);
- };
- };
- var TAG = NAME + ' Iterator';
- var DEF_VALUES = DEFAULT == VALUES;
- var VALUES_BUG = false;
- var proto = Base.prototype;
- var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT];
- var $default = $native || getMethod(DEFAULT);
- var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined;
- var $anyNative = NAME == 'Array' ? proto.entries || $native : $native;
- var methods, key, IteratorPrototype;
- if ($anyNative) {
- IteratorPrototype = getPrototypeOf($anyNative.call(new Base()));
- if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) {
- setToStringTag(IteratorPrototype, TAG, true);
- if (!LIBRARY && typeof IteratorPrototype[ITERATOR] != 'function') hide(IteratorPrototype, ITERATOR, returnThis);
- }
- }
- if (DEF_VALUES && $native && $native.name !== VALUES) {
- VALUES_BUG = true;
- $default = function values() {
- return $native.call(this);
- };
- }
- if ((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) {
- hide(proto, ITERATOR, $default);
- }
- Iterators[NAME] = $default;
- Iterators[TAG] = returnThis;
- if (DEFAULT) {
- methods = {
- values: DEF_VALUES ? $default : getMethod(VALUES),
- keys: IS_SET ? $default : getMethod(KEYS),
- entries: $entries
- };
- if (FORCED) for (key in methods) {
- if (!(key in proto)) redefine(proto, key, methods[key]);
- } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods);
- }
- return methods;
-};
-
-/***/ }),
-/* 66 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = {};
-
-/***/ }),
-/* 67 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var create = __w_pdfjs_require__(68);
-var descriptor = __w_pdfjs_require__(20);
-var setToStringTag = __w_pdfjs_require__(71);
-var IteratorPrototype = {};
-__w_pdfjs_require__(11)(IteratorPrototype, __w_pdfjs_require__(29)('iterator'), function () {
- return this;
-});
-module.exports = function (Constructor, NAME, next) {
- Constructor.prototype = create(IteratorPrototype, { next: descriptor(1, next) });
- setToStringTag(Constructor, NAME + ' Iterator');
-};
-
-/***/ }),
-/* 68 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var anObject = __w_pdfjs_require__(13);
-var dPs = __w_pdfjs_require__(69);
-var enumBugKeys = __w_pdfjs_require__(49);
-var IE_PROTO = __w_pdfjs_require__(48)('IE_PROTO');
-var Empty = function Empty() {};
-var PROTOTYPE = 'prototype';
-var _createDict = function createDict() {
- var iframe = __w_pdfjs_require__(18)('iframe');
- var i = enumBugKeys.length;
- var lt = '<';
- var gt = '>';
- var iframeDocument;
- iframe.style.display = 'none';
- __w_pdfjs_require__(70).appendChild(iframe);
- iframe.src = 'javascript:';
- iframeDocument = iframe.contentWindow.document;
- iframeDocument.open();
- iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt);
- iframeDocument.close();
- _createDict = iframeDocument.F;
- while (i--) {
- delete _createDict[PROTOTYPE][enumBugKeys[i]];
- }return _createDict();
-};
-module.exports = Object.create || function create(O, Properties) {
- var result;
- if (O !== null) {
- Empty[PROTOTYPE] = anObject(O);
- result = new Empty();
- Empty[PROTOTYPE] = null;
- result[IE_PROTO] = O;
- } else result = _createDict();
- return Properties === undefined ? result : dPs(result, Properties);
-};
-
-/***/ }),
-/* 69 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var dP = __w_pdfjs_require__(12);
-var anObject = __w_pdfjs_require__(13);
-var getKeys = __w_pdfjs_require__(46);
-module.exports = __w_pdfjs_require__(16) ? Object.defineProperties : function defineProperties(O, Properties) {
- anObject(O);
- var keys = getKeys(Properties);
- var length = keys.length;
- var i = 0;
- var P;
- while (length > i) {
- dP.f(O, P = keys[i++], Properties[P]);
- }return O;
-};
-
-/***/ }),
-/* 70 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var document = __w_pdfjs_require__(9).document;
-module.exports = document && document.documentElement;
-
-/***/ }),
-/* 71 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var def = __w_pdfjs_require__(12).f;
-var has = __w_pdfjs_require__(22);
-var TAG = __w_pdfjs_require__(29)('toStringTag');
-module.exports = function (it, tag, stat) {
- if (it && !has(it = stat ? it : it.prototype, TAG)) def(it, TAG, {
- configurable: true,
- value: tag
- });
-};
-
-/***/ }),
-/* 72 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var has = __w_pdfjs_require__(22);
-var toObject = __w_pdfjs_require__(52);
-var IE_PROTO = __w_pdfjs_require__(48)('IE_PROTO');
-var ObjectProto = Object.prototype;
-module.exports = Object.getPrototypeOf || function (O) {
- O = toObject(O);
- if (has(O, IE_PROTO)) return O[IE_PROTO];
- if (typeof O.constructor == 'function' && O instanceof O.constructor) {
- return O.constructor.prototype;
- }
- return O instanceof Object ? ObjectProto : null;
-};
-
-/***/ }),
-/* 73 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $iterators = __w_pdfjs_require__(74);
-var getKeys = __w_pdfjs_require__(46);
-var redefine = __w_pdfjs_require__(21);
-var global = __w_pdfjs_require__(9);
-var hide = __w_pdfjs_require__(11);
-var Iterators = __w_pdfjs_require__(66);
-var wks = __w_pdfjs_require__(29);
-var ITERATOR = wks('iterator');
-var TO_STRING_TAG = wks('toStringTag');
-var ArrayValues = Iterators.Array;
-var DOMIterables = {
- CSSRuleList: true,
- CSSStyleDeclaration: false,
- CSSValueList: false,
- ClientRectList: false,
- DOMRectList: false,
- DOMStringList: false,
- DOMTokenList: true,
- DataTransferItemList: false,
- FileList: false,
- HTMLAllCollection: false,
- HTMLCollection: false,
- HTMLFormElement: false,
- HTMLSelectElement: false,
- MediaList: true,
- MimeTypeArray: false,
- NamedNodeMap: false,
- NodeList: true,
- PaintRequestList: false,
- Plugin: false,
- PluginArray: false,
- SVGLengthList: false,
- SVGNumberList: false,
- SVGPathSegList: false,
- SVGPointList: false,
- SVGStringList: false,
- SVGTransformList: false,
- SourceBufferList: false,
- StyleSheetList: true,
- TextTrackCueList: false,
- TextTrackList: false,
- TouchList: false
-};
-for (var collections = getKeys(DOMIterables), i = 0; i < collections.length; i++) {
- var NAME = collections[i];
- var explicit = DOMIterables[NAME];
- var Collection = global[NAME];
- var proto = Collection && Collection.prototype;
- var key;
- if (proto) {
- if (!proto[ITERATOR]) hide(proto, ITERATOR, ArrayValues);
- if (!proto[TO_STRING_TAG]) hide(proto, TO_STRING_TAG, NAME);
- Iterators[NAME] = ArrayValues;
- if (explicit) for (key in $iterators) {
- if (!proto[key]) redefine(proto, key, $iterators[key], true);
- }
- }
-}
-
-/***/ }),
-/* 74 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var addToUnscopables = __w_pdfjs_require__(42);
-var step = __w_pdfjs_require__(75);
-var Iterators = __w_pdfjs_require__(66);
-var toIObject = __w_pdfjs_require__(37);
-module.exports = __w_pdfjs_require__(65)(Array, 'Array', function (iterated, kind) {
- this._t = toIObject(iterated);
- this._i = 0;
- this._k = kind;
-}, function () {
- var O = this._t;
- var kind = this._k;
- var index = this._i++;
- if (!O || index >= O.length) {
- this._t = undefined;
- return step(1);
- }
- if (kind == 'keys') return step(0, index);
- if (kind == 'values') return step(0, O[index]);
- return step(0, [index, O[index]]);
-}, 'values');
-Iterators.Arguments = Iterators.Array;
-addToUnscopables('keys');
-addToUnscopables('values');
-addToUnscopables('entries');
-
-/***/ }),
-/* 75 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = function (done, value) {
- return {
- value: value,
- done: !!done
- };
-};
-
-/***/ }),
-/* 76 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var LIBRARY = __w_pdfjs_require__(31);
-var global = __w_pdfjs_require__(9);
-var ctx = __w_pdfjs_require__(24);
-var classof = __w_pdfjs_require__(62);
-var $export = __w_pdfjs_require__(8);
-var isObject = __w_pdfjs_require__(14);
-var aFunction = __w_pdfjs_require__(25);
-var anInstance = __w_pdfjs_require__(77);
-var forOf = __w_pdfjs_require__(78);
-var speciesConstructor = __w_pdfjs_require__(82);
-var task = __w_pdfjs_require__(83).set;
-var microtask = __w_pdfjs_require__(85)();
-var newPromiseCapabilityModule = __w_pdfjs_require__(86);
-var perform = __w_pdfjs_require__(87);
-var userAgent = __w_pdfjs_require__(88);
-var promiseResolve = __w_pdfjs_require__(89);
-var PROMISE = 'Promise';
-var TypeError = global.TypeError;
-var process = global.process;
-var versions = process && process.versions;
-var v8 = versions && versions.v8 || '';
-var $Promise = global[PROMISE];
-var isNode = classof(process) == 'process';
-var empty = function empty() {};
-var Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper;
-var newPromiseCapability = newGenericPromiseCapability = newPromiseCapabilityModule.f;
-var USE_NATIVE = !!function () {
- try {
- var promise = $Promise.resolve(1);
- var FakePromise = (promise.constructor = {})[__w_pdfjs_require__(29)('species')] = function (exec) {
- exec(empty, empty);
- };
- return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise && v8.indexOf('6.6') !== 0 && userAgent.indexOf('Chrome/66') === -1;
- } catch (e) {}
-}();
-var isThenable = function isThenable(it) {
- var then;
- return isObject(it) && typeof (then = it.then) == 'function' ? then : false;
-};
-var notify = function notify(promise, isReject) {
- if (promise._n) return;
- promise._n = true;
- var chain = promise._c;
- microtask(function () {
- var value = promise._v;
- var ok = promise._s == 1;
- var i = 0;
- var run = function run(reaction) {
- var handler = ok ? reaction.ok : reaction.fail;
- var resolve = reaction.resolve;
- var reject = reaction.reject;
- var domain = reaction.domain;
- var result, then, exited;
- try {
- if (handler) {
- if (!ok) {
- if (promise._h == 2) onHandleUnhandled(promise);
- promise._h = 1;
- }
- if (handler === true) result = value;else {
- if (domain) domain.enter();
- result = handler(value);
- if (domain) {
- domain.exit();
- exited = true;
- }
- }
- if (result === reaction.promise) {
- reject(TypeError('Promise-chain cycle'));
- } else if (then = isThenable(result)) {
- then.call(result, resolve, reject);
- } else resolve(result);
- } else reject(value);
- } catch (e) {
- if (domain && !exited) domain.exit();
- reject(e);
- }
- };
- while (chain.length > i) {
- run(chain[i++]);
- }promise._c = [];
- promise._n = false;
- if (isReject && !promise._h) onUnhandled(promise);
- });
-};
-var onUnhandled = function onUnhandled(promise) {
- task.call(global, function () {
- var value = promise._v;
- var unhandled = isUnhandled(promise);
- var result, handler, console;
- if (unhandled) {
- result = perform(function () {
- if (isNode) {
- process.emit('unhandledRejection', value, promise);
- } else if (handler = global.onunhandledrejection) {
- handler({
- promise: promise,
- reason: value
- });
- } else if ((console = global.console) && console.error) {
- console.error('Unhandled promise rejection', value);
- }
- });
- promise._h = isNode || isUnhandled(promise) ? 2 : 1;
- }
- promise._a = undefined;
- if (unhandled && result.e) throw result.v;
- });
-};
-var isUnhandled = function isUnhandled(promise) {
- return promise._h !== 1 && (promise._a || promise._c).length === 0;
-};
-var onHandleUnhandled = function onHandleUnhandled(promise) {
- task.call(global, function () {
- var handler;
- if (isNode) {
- process.emit('rejectionHandled', promise);
- } else if (handler = global.onrejectionhandled) {
- handler({
- promise: promise,
- reason: promise._v
- });
- }
- });
-};
-var $reject = function $reject(value) {
- var promise = this;
- if (promise._d) return;
- promise._d = true;
- promise = promise._w || promise;
- promise._v = value;
- promise._s = 2;
- if (!promise._a) promise._a = promise._c.slice();
- notify(promise, true);
-};
-var $resolve = function $resolve(value) {
- var promise = this;
- var then;
- if (promise._d) return;
- promise._d = true;
- promise = promise._w || promise;
- try {
- if (promise === value) throw TypeError("Promise can't be resolved itself");
- if (then = isThenable(value)) {
- microtask(function () {
- var wrapper = {
- _w: promise,
- _d: false
- };
- try {
- then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1));
- } catch (e) {
- $reject.call(wrapper, e);
- }
- });
- } else {
- promise._v = value;
- promise._s = 1;
- notify(promise, false);
- }
- } catch (e) {
- $reject.call({
- _w: promise,
- _d: false
- }, e);
- }
-};
-if (!USE_NATIVE) {
- $Promise = function Promise(executor) {
- anInstance(this, $Promise, PROMISE, '_h');
- aFunction(executor);
- Internal.call(this);
- try {
- executor(ctx($resolve, this, 1), ctx($reject, this, 1));
- } catch (err) {
- $reject.call(this, err);
- }
- };
- Internal = function Promise(executor) {
- this._c = [];
- this._a = undefined;
- this._s = 0;
- this._d = false;
- this._v = undefined;
- this._h = 0;
- this._n = false;
- };
- Internal.prototype = __w_pdfjs_require__(90)($Promise.prototype, {
- then: function then(onFulfilled, onRejected) {
- var reaction = newPromiseCapability(speciesConstructor(this, $Promise));
- reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;
- reaction.fail = typeof onRejected == 'function' && onRejected;
- reaction.domain = isNode ? process.domain : undefined;
- this._c.push(reaction);
- if (this._a) this._a.push(reaction);
- if (this._s) notify(this, false);
- return reaction.promise;
- },
- 'catch': function _catch(onRejected) {
- return this.then(undefined, onRejected);
- }
- });
- OwnPromiseCapability = function OwnPromiseCapability() {
- var promise = new Internal();
- this.promise = promise;
- this.resolve = ctx($resolve, promise, 1);
- this.reject = ctx($reject, promise, 1);
- };
- newPromiseCapabilityModule.f = newPromiseCapability = function newPromiseCapability(C) {
- return C === $Promise || C === Wrapper ? new OwnPromiseCapability(C) : newGenericPromiseCapability(C);
- };
-}
-$export($export.G + $export.W + $export.F * !USE_NATIVE, { Promise: $Promise });
-__w_pdfjs_require__(71)($Promise, PROMISE);
-__w_pdfjs_require__(91)(PROMISE);
-Wrapper = __w_pdfjs_require__(10)[PROMISE];
-$export($export.S + $export.F * !USE_NATIVE, PROMISE, {
- reject: function reject(r) {
- var capability = newPromiseCapability(this);
- var $$reject = capability.reject;
- $$reject(r);
- return capability.promise;
- }
-});
-$export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, {
- resolve: function resolve(x) {
- return promiseResolve(LIBRARY && this === Wrapper ? $Promise : this, x);
- }
-});
-$export($export.S + $export.F * !(USE_NATIVE && __w_pdfjs_require__(92)(function (iter) {
- $Promise.all(iter)['catch'](empty);
-})), PROMISE, {
- all: function all(iterable) {
- var C = this;
- var capability = newPromiseCapability(C);
- var resolve = capability.resolve;
- var reject = capability.reject;
- var result = perform(function () {
- var values = [];
- var index = 0;
- var remaining = 1;
- forOf(iterable, false, function (promise) {
- var $index = index++;
- var alreadyCalled = false;
- values.push(undefined);
- remaining++;
- C.resolve(promise).then(function (value) {
- if (alreadyCalled) return;
- alreadyCalled = true;
- values[$index] = value;
- --remaining || resolve(values);
- }, reject);
- });
- --remaining || resolve(values);
- });
- if (result.e) reject(result.v);
- return capability.promise;
- },
- race: function race(iterable) {
- var C = this;
- var capability = newPromiseCapability(C);
- var reject = capability.reject;
- var result = perform(function () {
- forOf(iterable, false, function (promise) {
- C.resolve(promise).then(capability.resolve, reject);
- });
- });
- if (result.e) reject(result.v);
- return capability.promise;
- }
-});
-
-/***/ }),
-/* 77 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = function (it, Constructor, name, forbiddenField) {
- if (!(it instanceof Constructor) || forbiddenField !== undefined && forbiddenField in it) {
- throw TypeError(name + ': incorrect invocation!');
- }
- return it;
-};
-
-/***/ }),
-/* 78 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var ctx = __w_pdfjs_require__(24);
-var call = __w_pdfjs_require__(79);
-var isArrayIter = __w_pdfjs_require__(80);
-var anObject = __w_pdfjs_require__(13);
-var toLength = __w_pdfjs_require__(39);
-var getIterFn = __w_pdfjs_require__(81);
-var BREAK = {};
-var RETURN = {};
-var _exports = module.exports = function (iterable, entries, fn, that, ITERATOR) {
- var iterFn = ITERATOR ? function () {
- return iterable;
- } : getIterFn(iterable);
- var f = ctx(fn, that, entries ? 2 : 1);
- var index = 0;
- var length, step, iterator, result;
- if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!');
- if (isArrayIter(iterFn)) for (length = toLength(iterable.length); length > index; index++) {
- result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]);
- if (result === BREAK || result === RETURN) return result;
- } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) {
- result = call(iterator, f, step.value, entries);
- if (result === BREAK || result === RETURN) return result;
- }
-};
-_exports.BREAK = BREAK;
-_exports.RETURN = RETURN;
-
-/***/ }),
-/* 79 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var anObject = __w_pdfjs_require__(13);
-module.exports = function (iterator, fn, value, entries) {
- try {
- return entries ? fn(anObject(value)[0], value[1]) : fn(value);
- } catch (e) {
- var ret = iterator['return'];
- if (ret !== undefined) anObject(ret.call(iterator));
- throw e;
- }
-};
-
-/***/ }),
-/* 80 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var Iterators = __w_pdfjs_require__(66);
-var ITERATOR = __w_pdfjs_require__(29)('iterator');
-var ArrayProto = Array.prototype;
-module.exports = function (it) {
- return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it);
-};
-
-/***/ }),
-/* 81 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var classof = __w_pdfjs_require__(62);
-var ITERATOR = __w_pdfjs_require__(29)('iterator');
-var Iterators = __w_pdfjs_require__(66);
-module.exports = __w_pdfjs_require__(10).getIteratorMethod = function (it) {
- if (it != undefined) return it[ITERATOR] || it['@@iterator'] || Iterators[classof(it)];
-};
-
-/***/ }),
-/* 82 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var anObject = __w_pdfjs_require__(13);
-var aFunction = __w_pdfjs_require__(25);
-var SPECIES = __w_pdfjs_require__(29)('species');
-module.exports = function (O, D) {
- var C = anObject(O).constructor;
- var S;
- return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S);
-};
-
-/***/ }),
-/* 83 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var ctx = __w_pdfjs_require__(24);
-var invoke = __w_pdfjs_require__(84);
-var html = __w_pdfjs_require__(70);
-var cel = __w_pdfjs_require__(18);
-var global = __w_pdfjs_require__(9);
-var process = global.process;
-var setTask = global.setImmediate;
-var clearTask = global.clearImmediate;
-var MessageChannel = global.MessageChannel;
-var Dispatch = global.Dispatch;
-var counter = 0;
-var queue = {};
-var ONREADYSTATECHANGE = 'onreadystatechange';
-var defer, channel, port;
-var run = function run() {
- var id = +this;
- if (queue.hasOwnProperty(id)) {
- var fn = queue[id];
- delete queue[id];
- fn();
- }
-};
-var listener = function listener(event) {
- run.call(event.data);
-};
-if (!setTask || !clearTask) {
- setTask = function setImmediate(fn) {
- var args = [];
- var i = 1;
- while (arguments.length > i) {
- args.push(arguments[i++]);
- }queue[++counter] = function () {
- invoke(typeof fn == 'function' ? fn : Function(fn), args);
- };
- defer(counter);
- return counter;
- };
- clearTask = function clearImmediate(id) {
- delete queue[id];
- };
- if (__w_pdfjs_require__(28)(process) == 'process') {
- defer = function defer(id) {
- process.nextTick(ctx(run, id, 1));
- };
- } else if (Dispatch && Dispatch.now) {
- defer = function defer(id) {
- Dispatch.now(ctx(run, id, 1));
- };
- } else if (MessageChannel) {
- channel = new MessageChannel();
- port = channel.port2;
- channel.port1.onmessage = listener;
- defer = ctx(port.postMessage, port, 1);
- } else if (global.addEventListener && typeof postMessage == 'function' && !global.importScripts) {
- defer = function defer(id) {
- global.postMessage(id + '', '*');
- };
- global.addEventListener('message', listener, false);
- } else if (ONREADYSTATECHANGE in cel('script')) {
- defer = function defer(id) {
- html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function () {
- html.removeChild(this);
- run.call(id);
- };
- };
- } else {
- defer = function defer(id) {
- setTimeout(ctx(run, id, 1), 0);
- };
- }
-}
-module.exports = {
- set: setTask,
- clear: clearTask
-};
-
-/***/ }),
-/* 84 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = function (fn, args, that) {
- var un = that === undefined;
- switch (args.length) {
- case 0:
- return un ? fn() : fn.call(that);
- case 1:
- return un ? fn(args[0]) : fn.call(that, args[0]);
- case 2:
- return un ? fn(args[0], args[1]) : fn.call(that, args[0], args[1]);
- case 3:
- return un ? fn(args[0], args[1], args[2]) : fn.call(that, args[0], args[1], args[2]);
- case 4:
- return un ? fn(args[0], args[1], args[2], args[3]) : fn.call(that, args[0], args[1], args[2], args[3]);
- }
- return fn.apply(that, args);
-};
-
-/***/ }),
-/* 85 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var global = __w_pdfjs_require__(9);
-var macrotask = __w_pdfjs_require__(83).set;
-var Observer = global.MutationObserver || global.WebKitMutationObserver;
-var process = global.process;
-var Promise = global.Promise;
-var isNode = __w_pdfjs_require__(28)(process) == 'process';
-module.exports = function () {
- var head, last, notify;
- var flush = function flush() {
- var parent, fn;
- if (isNode && (parent = process.domain)) parent.exit();
- while (head) {
- fn = head.fn;
- head = head.next;
- try {
- fn();
- } catch (e) {
- if (head) notify();else last = undefined;
- throw e;
- }
- }
- last = undefined;
- if (parent) parent.enter();
- };
- if (isNode) {
- notify = function notify() {
- process.nextTick(flush);
- };
- } else if (Observer && !(global.navigator && global.navigator.standalone)) {
- var toggle = true;
- var node = document.createTextNode('');
- new Observer(flush).observe(node, { characterData: true });
- notify = function notify() {
- node.data = toggle = !toggle;
- };
- } else if (Promise && Promise.resolve) {
- var promise = Promise.resolve(undefined);
- notify = function notify() {
- promise.then(flush);
- };
- } else {
- notify = function notify() {
- macrotask.call(global, flush);
- };
- }
- return function (fn) {
- var task = {
- fn: fn,
- next: undefined
- };
- if (last) last.next = task;
- if (!head) {
- head = task;
- notify();
- }
- last = task;
- };
-};
-
-/***/ }),
-/* 86 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var aFunction = __w_pdfjs_require__(25);
-function PromiseCapability(C) {
- var resolve, reject;
- this.promise = new C(function ($$resolve, $$reject) {
- if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor');
- resolve = $$resolve;
- reject = $$reject;
- });
- this.resolve = aFunction(resolve);
- this.reject = aFunction(reject);
-}
-module.exports.f = function (C) {
- return new PromiseCapability(C);
-};
-
-/***/ }),
-/* 87 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = function (exec) {
- try {
- return {
- e: false,
- v: exec()
- };
- } catch (e) {
- return {
- e: true,
- v: e
- };
- }
-};
-
-/***/ }),
-/* 88 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var global = __w_pdfjs_require__(9);
-var navigator = global.navigator;
-module.exports = navigator && navigator.userAgent || '';
-
-/***/ }),
-/* 89 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var anObject = __w_pdfjs_require__(13);
-var isObject = __w_pdfjs_require__(14);
-var newPromiseCapability = __w_pdfjs_require__(86);
-module.exports = function (C, x) {
- anObject(C);
- if (isObject(x) && x.constructor === C) return x;
- var promiseCapability = newPromiseCapability.f(C);
- var resolve = promiseCapability.resolve;
- resolve(x);
- return promiseCapability.promise;
-};
-
-/***/ }),
-/* 90 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var redefine = __w_pdfjs_require__(21);
-module.exports = function (target, src, safe) {
- for (var key in src) {
- redefine(target, key, src[key], safe);
- }return target;
-};
-
-/***/ }),
-/* 91 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var global = __w_pdfjs_require__(9);
-var dP = __w_pdfjs_require__(12);
-var DESCRIPTORS = __w_pdfjs_require__(16);
-var SPECIES = __w_pdfjs_require__(29)('species');
-module.exports = function (KEY) {
- var C = global[KEY];
- if (DESCRIPTORS && C && !C[SPECIES]) dP.f(C, SPECIES, {
- configurable: true,
- get: function get() {
- return this;
- }
- });
-};
-
-/***/ }),
-/* 92 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var ITERATOR = __w_pdfjs_require__(29)('iterator');
-var SAFE_CLOSING = false;
-try {
- var riter = [7][ITERATOR]();
- riter['return'] = function () {
- SAFE_CLOSING = true;
- };
- Array.from(riter, function () {
- throw 2;
- });
-} catch (e) {}
-module.exports = function (exec, skipClosing) {
- if (!skipClosing && !SAFE_CLOSING) return false;
- var safe = false;
- try {
- var arr = [7];
- var iter = arr[ITERATOR]();
- iter.next = function () {
- return { done: safe = true };
- };
- arr[ITERATOR] = function () {
- return iter;
- };
- exec(arr);
- } catch (e) {}
- return safe;
-};
-
-/***/ }),
-/* 93 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(8);
-var core = __w_pdfjs_require__(10);
-var global = __w_pdfjs_require__(9);
-var speciesConstructor = __w_pdfjs_require__(82);
-var promiseResolve = __w_pdfjs_require__(89);
-$export($export.P + $export.R, 'Promise', {
- 'finally': function _finally(onFinally) {
- var C = speciesConstructor(this, core.Promise || global.Promise);
- var isFunction = typeof onFinally == 'function';
- return this.then(isFunction ? function (x) {
- return promiseResolve(C, onFinally()).then(function () {
- return x;
- });
- } : onFinally, isFunction ? function (e) {
- return promiseResolve(C, onFinally()).then(function () {
- throw e;
- });
- } : onFinally);
- }
-});
-
-/***/ }),
-/* 94 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(8);
-var newPromiseCapability = __w_pdfjs_require__(86);
-var perform = __w_pdfjs_require__(87);
-$export($export.S, 'Promise', {
- 'try': function _try(callbackfn) {
- var promiseCapability = newPromiseCapability.f(this);
- var result = perform(callbackfn);
- (result.e ? promiseCapability.reject : promiseCapability.resolve)(result.v);
- return promiseCapability.promise;
- }
-});
-
-/***/ }),
-/* 95 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(61);
-__w_pdfjs_require__(73);
-__w_pdfjs_require__(96);
-__w_pdfjs_require__(108);
-__w_pdfjs_require__(110);
-module.exports = __w_pdfjs_require__(10).WeakMap;
-
-/***/ }),
-/* 96 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var each = __w_pdfjs_require__(97)(0);
-var redefine = __w_pdfjs_require__(21);
-var meta = __w_pdfjs_require__(101);
-var assign = __w_pdfjs_require__(45);
-var weak = __w_pdfjs_require__(102);
-var isObject = __w_pdfjs_require__(14);
-var fails = __w_pdfjs_require__(17);
-var validate = __w_pdfjs_require__(103);
-var WEAK_MAP = 'WeakMap';
-var getWeak = meta.getWeak;
-var isExtensible = Object.isExtensible;
-var uncaughtFrozenStore = weak.ufstore;
-var tmp = {};
-var InternalMap;
-var wrapper = function wrapper(get) {
- return function WeakMap() {
- return get(this, arguments.length > 0 ? arguments[0] : undefined);
- };
-};
-var methods = {
- get: function get(key) {
- if (isObject(key)) {
- var data = getWeak(key);
- if (data === true) return uncaughtFrozenStore(validate(this, WEAK_MAP)).get(key);
- return data ? data[this._i] : undefined;
- }
- },
- set: function set(key, value) {
- return weak.def(validate(this, WEAK_MAP), key, value);
- }
-};
-var $WeakMap = module.exports = __w_pdfjs_require__(104)(WEAK_MAP, wrapper, methods, weak, true, true);
-if (fails(function () {
- return new $WeakMap().set((Object.freeze || Object)(tmp), 7).get(tmp) != 7;
-})) {
- InternalMap = weak.getConstructor(wrapper, WEAK_MAP);
- assign(InternalMap.prototype, methods);
- meta.NEED = true;
- each(['delete', 'has', 'get', 'set'], function (key) {
- var proto = $WeakMap.prototype;
- var method = proto[key];
- redefine(proto, key, function (a, b) {
- if (isObject(a) && !isExtensible(a)) {
- if (!this._f) this._f = new InternalMap();
- var result = this._f[key](a, b);
- return key == 'set' ? this : result;
- }
- return method.call(this, a, b);
- });
- });
-}
-
-/***/ }),
-/* 97 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var ctx = __w_pdfjs_require__(24);
-var IObject = __w_pdfjs_require__(38);
-var toObject = __w_pdfjs_require__(52);
-var toLength = __w_pdfjs_require__(39);
-var asc = __w_pdfjs_require__(98);
-module.exports = function (TYPE, $create) {
- var IS_MAP = TYPE == 1;
- var IS_FILTER = TYPE == 2;
- var IS_SOME = TYPE == 3;
- var IS_EVERY = TYPE == 4;
- var IS_FIND_INDEX = TYPE == 6;
- var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;
- var create = $create || asc;
- return function ($this, callbackfn, that) {
- var O = toObject($this);
- var self = IObject(O);
- var f = ctx(callbackfn, that, 3);
- var length = toLength(self.length);
- var index = 0;
- var result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined;
- var val, res;
- for (; length > index; index++) {
- if (NO_HOLES || index in self) {
- val = self[index];
- res = f(val, index, O);
- if (TYPE) {
- if (IS_MAP) result[index] = res;else if (res) switch (TYPE) {
- case 3:
- return true;
- case 5:
- return val;
- case 6:
- return index;
- case 2:
- result.push(val);
- } else if (IS_EVERY) return false;
- }
- }
- }return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result;
- };
-};
-
-/***/ }),
-/* 98 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var speciesConstructor = __w_pdfjs_require__(99);
-module.exports = function (original, length) {
- return new (speciesConstructor(original))(length);
-};
-
-/***/ }),
-/* 99 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isObject = __w_pdfjs_require__(14);
-var isArray = __w_pdfjs_require__(100);
-var SPECIES = __w_pdfjs_require__(29)('species');
-module.exports = function (original) {
- var C;
- if (isArray(original)) {
- C = original.constructor;
- if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined;
- if (isObject(C)) {
- C = C[SPECIES];
- if (C === null) C = undefined;
- }
- }
- return C === undefined ? Array : C;
-};
-
-/***/ }),
-/* 100 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var cof = __w_pdfjs_require__(28);
-module.exports = Array.isArray || function isArray(arg) {
- return cof(arg) == 'Array';
-};
-
-/***/ }),
-/* 101 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-var META = __w_pdfjs_require__(23)('meta');
-var isObject = __w_pdfjs_require__(14);
-var has = __w_pdfjs_require__(22);
-var setDesc = __w_pdfjs_require__(12).f;
-var id = 0;
-var isExtensible = Object.isExtensible || function () {
- return true;
-};
-var FREEZE = !__w_pdfjs_require__(17)(function () {
- return isExtensible(Object.preventExtensions({}));
-});
-var setMeta = function setMeta(it) {
- setDesc(it, META, {
- value: {
- i: 'O' + ++id,
- w: {}
- }
- });
-};
-var fastKey = function fastKey(it, create) {
- if (!isObject(it)) return (typeof it === 'undefined' ? 'undefined' : _typeof(it)) == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;
- if (!has(it, META)) {
- if (!isExtensible(it)) return 'F';
- if (!create) return 'E';
- setMeta(it);
- }
- return it[META].i;
-};
-var getWeak = function getWeak(it, create) {
- if (!has(it, META)) {
- if (!isExtensible(it)) return true;
- if (!create) return false;
- setMeta(it);
- }
- return it[META].w;
-};
-var onFreeze = function onFreeze(it) {
- if (FREEZE && meta.NEED && isExtensible(it) && !has(it, META)) setMeta(it);
- return it;
-};
-var meta = module.exports = {
- KEY: META,
- NEED: false,
- fastKey: fastKey,
- getWeak: getWeak,
- onFreeze: onFreeze
-};
-
-/***/ }),
-/* 102 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var redefineAll = __w_pdfjs_require__(90);
-var getWeak = __w_pdfjs_require__(101).getWeak;
-var anObject = __w_pdfjs_require__(13);
-var isObject = __w_pdfjs_require__(14);
-var anInstance = __w_pdfjs_require__(77);
-var forOf = __w_pdfjs_require__(78);
-var createArrayMethod = __w_pdfjs_require__(97);
-var $has = __w_pdfjs_require__(22);
-var validate = __w_pdfjs_require__(103);
-var arrayFind = createArrayMethod(5);
-var arrayFindIndex = createArrayMethod(6);
-var id = 0;
-var uncaughtFrozenStore = function uncaughtFrozenStore(that) {
- return that._l || (that._l = new UncaughtFrozenStore());
-};
-var UncaughtFrozenStore = function UncaughtFrozenStore() {
- this.a = [];
-};
-var findUncaughtFrozen = function findUncaughtFrozen(store, key) {
- return arrayFind(store.a, function (it) {
- return it[0] === key;
- });
-};
-UncaughtFrozenStore.prototype = {
- get: function get(key) {
- var entry = findUncaughtFrozen(this, key);
- if (entry) return entry[1];
- },
- has: function has(key) {
- return !!findUncaughtFrozen(this, key);
- },
- set: function set(key, value) {
- var entry = findUncaughtFrozen(this, key);
- if (entry) entry[1] = value;else this.a.push([key, value]);
- },
- 'delete': function _delete(key) {
- var index = arrayFindIndex(this.a, function (it) {
- return it[0] === key;
- });
- if (~index) this.a.splice(index, 1);
- return !!~index;
- }
-};
-module.exports = {
- getConstructor: function getConstructor(wrapper, NAME, IS_MAP, ADDER) {
- var C = wrapper(function (that, iterable) {
- anInstance(that, C, NAME, '_i');
- that._t = NAME;
- that._i = id++;
- that._l = undefined;
- if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);
- });
- redefineAll(C.prototype, {
- 'delete': function _delete(key) {
- if (!isObject(key)) return false;
- var data = getWeak(key);
- if (data === true) return uncaughtFrozenStore(validate(this, NAME))['delete'](key);
- return data && $has(data, this._i) && delete data[this._i];
- },
- has: function has(key) {
- if (!isObject(key)) return false;
- var data = getWeak(key);
- if (data === true) return uncaughtFrozenStore(validate(this, NAME)).has(key);
- return data && $has(data, this._i);
- }
- });
- return C;
- },
- def: function def(that, key, value) {
- var data = getWeak(anObject(key), true);
- if (data === true) uncaughtFrozenStore(that).set(key, value);else data[that._i] = value;
- return that;
- },
- ufstore: uncaughtFrozenStore
-};
-
-/***/ }),
-/* 103 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isObject = __w_pdfjs_require__(14);
-module.exports = function (it, TYPE) {
- if (!isObject(it) || it._t !== TYPE) throw TypeError('Incompatible receiver, ' + TYPE + ' required!');
- return it;
-};
-
-/***/ }),
-/* 104 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var global = __w_pdfjs_require__(9);
-var $export = __w_pdfjs_require__(8);
-var redefine = __w_pdfjs_require__(21);
-var redefineAll = __w_pdfjs_require__(90);
-var meta = __w_pdfjs_require__(101);
-var forOf = __w_pdfjs_require__(78);
-var anInstance = __w_pdfjs_require__(77);
-var isObject = __w_pdfjs_require__(14);
-var fails = __w_pdfjs_require__(17);
-var $iterDetect = __w_pdfjs_require__(92);
-var setToStringTag = __w_pdfjs_require__(71);
-var inheritIfRequired = __w_pdfjs_require__(105);
-module.exports = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) {
- var Base = global[NAME];
- var C = Base;
- var ADDER = IS_MAP ? 'set' : 'add';
- var proto = C && C.prototype;
- var O = {};
- var fixMethod = function fixMethod(KEY) {
- var fn = proto[KEY];
- redefine(proto, KEY, KEY == 'delete' ? function (a) {
- return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);
- } : KEY == 'has' ? function has(a) {
- return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);
- } : KEY == 'get' ? function get(a) {
- return IS_WEAK && !isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a);
- } : KEY == 'add' ? function add(a) {
- fn.call(this, a === 0 ? 0 : a);
- return this;
- } : function set(a, b) {
- fn.call(this, a === 0 ? 0 : a, b);
- return this;
- });
- };
- if (typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function () {
- new C().entries().next();
- }))) {
- C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER);
- redefineAll(C.prototype, methods);
- meta.NEED = true;
- } else {
- var instance = new C();
- var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance;
- var THROWS_ON_PRIMITIVES = fails(function () {
- instance.has(1);
- });
- var ACCEPT_ITERABLES = $iterDetect(function (iter) {
- new C(iter);
- });
- var BUGGY_ZERO = !IS_WEAK && fails(function () {
- var $instance = new C();
- var index = 5;
- while (index--) {
- $instance[ADDER](index, index);
- }return !$instance.has(-0);
- });
- if (!ACCEPT_ITERABLES) {
- C = wrapper(function (target, iterable) {
- anInstance(target, C, NAME);
- var that = inheritIfRequired(new Base(), target, C);
- if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);
- return that;
- });
- C.prototype = proto;
- proto.constructor = C;
- }
- if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {
- fixMethod('delete');
- fixMethod('has');
- IS_MAP && fixMethod('get');
- }
- if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);
- if (IS_WEAK && proto.clear) delete proto.clear;
- }
- setToStringTag(C, NAME);
- O[NAME] = C;
- $export($export.G + $export.W + $export.F * (C != Base), O);
- if (!IS_WEAK) common.setStrong(C, NAME, IS_MAP);
- return C;
-};
-
-/***/ }),
-/* 105 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isObject = __w_pdfjs_require__(14);
-var setPrototypeOf = __w_pdfjs_require__(106).set;
-module.exports = function (that, target, C) {
- var S = target.constructor;
- var P;
- if (S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && isObject(P) && setPrototypeOf) {
- setPrototypeOf(that, P);
- }
- return that;
-};
-
-/***/ }),
-/* 106 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isObject = __w_pdfjs_require__(14);
-var anObject = __w_pdfjs_require__(13);
-var check = function check(O, proto) {
- anObject(O);
- if (!isObject(proto) && proto !== null) throw TypeError(proto + ": can't set as prototype!");
-};
-module.exports = {
- set: Object.setPrototypeOf || ('__proto__' in {} ? function (test, buggy, set) {
- try {
- set = __w_pdfjs_require__(24)(Function.call, __w_pdfjs_require__(107).f(Object.prototype, '__proto__').set, 2);
- set(test, []);
- buggy = !(test instanceof Array);
- } catch (e) {
- buggy = true;
- }
- return function setPrototypeOf(O, proto) {
- check(O, proto);
- if (buggy) O.__proto__ = proto;else set(O, proto);
- return O;
- };
- }({}, false) : undefined),
- check: check
-};
-
-/***/ }),
-/* 107 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var pIE = __w_pdfjs_require__(51);
-var createDesc = __w_pdfjs_require__(20);
-var toIObject = __w_pdfjs_require__(37);
-var toPrimitive = __w_pdfjs_require__(19);
-var has = __w_pdfjs_require__(22);
-var IE8_DOM_DEFINE = __w_pdfjs_require__(15);
-var gOPD = Object.getOwnPropertyDescriptor;
-exports.f = __w_pdfjs_require__(16) ? gOPD : function getOwnPropertyDescriptor(O, P) {
- O = toIObject(O);
- P = toPrimitive(P, true);
- if (IE8_DOM_DEFINE) try {
- return gOPD(O, P);
- } catch (e) {}
- if (has(O, P)) return createDesc(!pIE.f.call(O, P), O[P]);
-};
-
-/***/ }),
-/* 108 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(109)('WeakMap');
-
-/***/ }),
-/* 109 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(8);
-module.exports = function (COLLECTION) {
- $export($export.S, COLLECTION, {
- of: function of() {
- var length = arguments.length;
- var A = new Array(length);
- while (length--) {
- A[length] = arguments[length];
- }return new this(A);
- }
- });
-};
-
-/***/ }),
-/* 110 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(111)('WeakMap');
-
-/***/ }),
-/* 111 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(8);
-var aFunction = __w_pdfjs_require__(25);
-var ctx = __w_pdfjs_require__(24);
-var forOf = __w_pdfjs_require__(78);
-module.exports = function (COLLECTION) {
- $export($export.S, COLLECTION, {
- from: function from(source) {
- var mapFn = arguments[1];
- var mapping, A, n, cb;
- aFunction(this);
- mapping = mapFn !== undefined;
- if (mapping) aFunction(mapFn);
- if (source == undefined) return new this();
- A = [];
- if (mapping) {
- n = 0;
- cb = ctx(mapFn, arguments[2], 2);
- forOf(source, false, function (nextItem) {
- A.push(cb(nextItem, n++));
- });
- } else {
- forOf(source, false, A.push, A);
- }
- return new this(A);
- }
- });
-};
-
-/***/ }),
-/* 112 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(113);
-module.exports = __w_pdfjs_require__(10).String.codePointAt;
-
-/***/ }),
-/* 113 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(8);
-var $at = __w_pdfjs_require__(64)(false);
-$export($export.P, 'String', {
- codePointAt: function codePointAt(pos) {
- return $at(this, pos);
- }
-});
-
-/***/ }),
-/* 114 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(115);
-module.exports = __w_pdfjs_require__(10).String.fromCodePoint;
-
-/***/ }),
-/* 115 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(8);
-var toAbsoluteIndex = __w_pdfjs_require__(41);
-var fromCharCode = String.fromCharCode;
-var $fromCodePoint = String.fromCodePoint;
-$export($export.S + $export.F * (!!$fromCodePoint && $fromCodePoint.length != 1), 'String', {
- fromCodePoint: function fromCodePoint(x) {
- var res = [];
- var aLen = arguments.length;
- var i = 0;
- var code;
- while (aLen > i) {
- code = +arguments[i++];
- if (toAbsoluteIndex(code, 0x10ffff) !== code) throw RangeError(code + ' is not a valid code point');
- res.push(code < 0x10000 ? fromCharCode(code) : fromCharCode(((code -= 0x10000) >> 10) + 0xd800, code % 0x400 + 0xdc00));
- }
- return res.join('');
- }
-});
-
-/***/ }),
-/* 116 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(117);
-__w_pdfjs_require__(61);
-module.exports = __w_pdfjs_require__(10).Symbol;
-
-/***/ }),
-/* 117 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-var global = __w_pdfjs_require__(9);
-var has = __w_pdfjs_require__(22);
-var DESCRIPTORS = __w_pdfjs_require__(16);
-var $export = __w_pdfjs_require__(8);
-var redefine = __w_pdfjs_require__(21);
-var META = __w_pdfjs_require__(101).KEY;
-var $fails = __w_pdfjs_require__(17);
-var shared = __w_pdfjs_require__(30);
-var setToStringTag = __w_pdfjs_require__(71);
-var uid = __w_pdfjs_require__(23);
-var wks = __w_pdfjs_require__(29);
-var wksExt = __w_pdfjs_require__(118);
-var wksDefine = __w_pdfjs_require__(119);
-var enumKeys = __w_pdfjs_require__(120);
-var isArray = __w_pdfjs_require__(100);
-var anObject = __w_pdfjs_require__(13);
-var isObject = __w_pdfjs_require__(14);
-var toIObject = __w_pdfjs_require__(37);
-var toPrimitive = __w_pdfjs_require__(19);
-var createDesc = __w_pdfjs_require__(20);
-var _create = __w_pdfjs_require__(68);
-var gOPNExt = __w_pdfjs_require__(121);
-var $GOPD = __w_pdfjs_require__(107);
-var $DP = __w_pdfjs_require__(12);
-var $keys = __w_pdfjs_require__(46);
-var gOPD = $GOPD.f;
-var dP = $DP.f;
-var gOPN = gOPNExt.f;
-var $Symbol = global.Symbol;
-var $JSON = global.JSON;
-var _stringify = $JSON && $JSON.stringify;
-var PROTOTYPE = 'prototype';
-var HIDDEN = wks('_hidden');
-var TO_PRIMITIVE = wks('toPrimitive');
-var isEnum = {}.propertyIsEnumerable;
-var SymbolRegistry = shared('symbol-registry');
-var AllSymbols = shared('symbols');
-var OPSymbols = shared('op-symbols');
-var ObjectProto = Object[PROTOTYPE];
-var USE_NATIVE = typeof $Symbol == 'function';
-var QObject = global.QObject;
-var setter = !QObject || !QObject[PROTOTYPE] || !QObject[PROTOTYPE].findChild;
-var setSymbolDesc = DESCRIPTORS && $fails(function () {
- return _create(dP({}, 'a', {
- get: function get() {
- return dP(this, 'a', { value: 7 }).a;
- }
- })).a != 7;
-}) ? function (it, key, D) {
- var protoDesc = gOPD(ObjectProto, key);
- if (protoDesc) delete ObjectProto[key];
- dP(it, key, D);
- if (protoDesc && it !== ObjectProto) dP(ObjectProto, key, protoDesc);
-} : dP;
-var wrap = function wrap(tag) {
- var sym = AllSymbols[tag] = _create($Symbol[PROTOTYPE]);
- sym._k = tag;
- return sym;
-};
-var isSymbol = USE_NATIVE && _typeof($Symbol.iterator) == 'symbol' ? function (it) {
- return (typeof it === 'undefined' ? 'undefined' : _typeof(it)) == 'symbol';
-} : function (it) {
- return it instanceof $Symbol;
-};
-var $defineProperty = function defineProperty(it, key, D) {
- if (it === ObjectProto) $defineProperty(OPSymbols, key, D);
- anObject(it);
- key = toPrimitive(key, true);
- anObject(D);
- if (has(AllSymbols, key)) {
- if (!D.enumerable) {
- if (!has(it, HIDDEN)) dP(it, HIDDEN, createDesc(1, {}));
- it[HIDDEN][key] = true;
- } else {
- if (has(it, HIDDEN) && it[HIDDEN][key]) it[HIDDEN][key] = false;
- D = _create(D, { enumerable: createDesc(0, false) });
- }
- return setSymbolDesc(it, key, D);
- }
- return dP(it, key, D);
-};
-var $defineProperties = function defineProperties(it, P) {
- anObject(it);
- var keys = enumKeys(P = toIObject(P));
- var i = 0;
- var l = keys.length;
- var key;
- while (l > i) {
- $defineProperty(it, key = keys[i++], P[key]);
- }return it;
-};
-var $create = function create(it, P) {
- return P === undefined ? _create(it) : $defineProperties(_create(it), P);
-};
-var $propertyIsEnumerable = function propertyIsEnumerable(key) {
- var E = isEnum.call(this, key = toPrimitive(key, true));
- if (this === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key)) return false;
- return E || !has(this, key) || !has(AllSymbols, key) || has(this, HIDDEN) && this[HIDDEN][key] ? E : true;
-};
-var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(it, key) {
- it = toIObject(it);
- key = toPrimitive(key, true);
- if (it === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key)) return;
- var D = gOPD(it, key);
- if (D && has(AllSymbols, key) && !(has(it, HIDDEN) && it[HIDDEN][key])) D.enumerable = true;
- return D;
-};
-var $getOwnPropertyNames = function getOwnPropertyNames(it) {
- var names = gOPN(toIObject(it));
- var result = [];
- var i = 0;
- var key;
- while (names.length > i) {
- if (!has(AllSymbols, key = names[i++]) && key != HIDDEN && key != META) result.push(key);
- }
- return result;
-};
-var $getOwnPropertySymbols = function getOwnPropertySymbols(it) {
- var IS_OP = it === ObjectProto;
- var names = gOPN(IS_OP ? OPSymbols : toIObject(it));
- var result = [];
- var i = 0;
- var key;
- while (names.length > i) {
- if (has(AllSymbols, key = names[i++]) && (IS_OP ? has(ObjectProto, key) : true)) result.push(AllSymbols[key]);
- }
- return result;
-};
-if (!USE_NATIVE) {
- $Symbol = function _Symbol() {
- if (this instanceof $Symbol) throw TypeError('Symbol is not a constructor!');
- var tag = uid(arguments.length > 0 ? arguments[0] : undefined);
- var $set = function $set(value) {
- if (this === ObjectProto) $set.call(OPSymbols, value);
- if (has(this, HIDDEN) && has(this[HIDDEN], tag)) this[HIDDEN][tag] = false;
- setSymbolDesc(this, tag, createDesc(1, value));
- };
- if (DESCRIPTORS && setter) setSymbolDesc(ObjectProto, tag, {
- configurable: true,
- set: $set
- });
- return wrap(tag);
- };
- redefine($Symbol[PROTOTYPE], 'toString', function toString() {
- return this._k;
- });
- $GOPD.f = $getOwnPropertyDescriptor;
- $DP.f = $defineProperty;
- __w_pdfjs_require__(122).f = gOPNExt.f = $getOwnPropertyNames;
- __w_pdfjs_require__(51).f = $propertyIsEnumerable;
- __w_pdfjs_require__(50).f = $getOwnPropertySymbols;
- if (DESCRIPTORS && !__w_pdfjs_require__(31)) {
- redefine(ObjectProto, 'propertyIsEnumerable', $propertyIsEnumerable, true);
- }
- wksExt.f = function (name) {
- return wrap(wks(name));
- };
-}
-$export($export.G + $export.W + $export.F * !USE_NATIVE, { Symbol: $Symbol });
-for (var es6Symbols = 'hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables'.split(','), j = 0; es6Symbols.length > j;) {
- wks(es6Symbols[j++]);
-}for (var wellKnownSymbols = $keys(wks.store), k = 0; wellKnownSymbols.length > k;) {
- wksDefine(wellKnownSymbols[k++]);
-}$export($export.S + $export.F * !USE_NATIVE, 'Symbol', {
- 'for': function _for(key) {
- return has(SymbolRegistry, key += '') ? SymbolRegistry[key] : SymbolRegistry[key] = $Symbol(key);
- },
- keyFor: function keyFor(sym) {
- if (!isSymbol(sym)) throw TypeError(sym + ' is not a symbol!');
- for (var key in SymbolRegistry) {
- if (SymbolRegistry[key] === sym) return key;
- }
- },
- useSetter: function useSetter() {
- setter = true;
- },
- useSimple: function useSimple() {
- setter = false;
- }
-});
-$export($export.S + $export.F * !USE_NATIVE, 'Object', {
- create: $create,
- defineProperty: $defineProperty,
- defineProperties: $defineProperties,
- getOwnPropertyDescriptor: $getOwnPropertyDescriptor,
- getOwnPropertyNames: $getOwnPropertyNames,
- getOwnPropertySymbols: $getOwnPropertySymbols
-});
-$JSON && $export($export.S + $export.F * (!USE_NATIVE || $fails(function () {
- var S = $Symbol();
- return _stringify([S]) != '[null]' || _stringify({ a: S }) != '{}' || _stringify(Object(S)) != '{}';
-})), 'JSON', {
- stringify: function stringify(it) {
- var args = [it];
- var i = 1;
- var replacer, $replacer;
- while (arguments.length > i) {
- args.push(arguments[i++]);
- }$replacer = replacer = args[1];
- if (!isObject(replacer) && it === undefined || isSymbol(it)) return;
- if (!isArray(replacer)) replacer = function replacer(key, value) {
- if (typeof $replacer == 'function') value = $replacer.call(this, key, value);
- if (!isSymbol(value)) return value;
- };
- args[1] = replacer;
- return _stringify.apply($JSON, args);
- }
-});
-$Symbol[PROTOTYPE][TO_PRIMITIVE] || __w_pdfjs_require__(11)($Symbol[PROTOTYPE], TO_PRIMITIVE, $Symbol[PROTOTYPE].valueOf);
-setToStringTag($Symbol, 'Symbol');
-setToStringTag(Math, 'Math', true);
-setToStringTag(global.JSON, 'JSON', true);
-
-/***/ }),
-/* 118 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-exports.f = __w_pdfjs_require__(29);
-
-/***/ }),
-/* 119 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var global = __w_pdfjs_require__(9);
-var core = __w_pdfjs_require__(10);
-var LIBRARY = __w_pdfjs_require__(31);
-var wksExt = __w_pdfjs_require__(118);
-var defineProperty = __w_pdfjs_require__(12).f;
-module.exports = function (name) {
- var $Symbol = core.Symbol || (core.Symbol = LIBRARY ? {} : global.Symbol || {});
- if (name.charAt(0) != '_' && !(name in $Symbol)) defineProperty($Symbol, name, { value: wksExt.f(name) });
-};
-
-/***/ }),
-/* 120 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var getKeys = __w_pdfjs_require__(46);
-var gOPS = __w_pdfjs_require__(50);
-var pIE = __w_pdfjs_require__(51);
-module.exports = function (it) {
- var result = getKeys(it);
- var getSymbols = gOPS.f;
- if (getSymbols) {
- var symbols = getSymbols(it);
- var isEnum = pIE.f;
- var i = 0;
- var key;
- while (symbols.length > i) {
- if (isEnum.call(it, key = symbols[i++])) result.push(key);
- }
- }
- return result;
-};
-
-/***/ }),
-/* 121 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-var toIObject = __w_pdfjs_require__(37);
-var gOPN = __w_pdfjs_require__(122).f;
-var toString = {}.toString;
-var windowNames = (typeof window === 'undefined' ? 'undefined' : _typeof(window)) == 'object' && window && Object.getOwnPropertyNames ? Object.getOwnPropertyNames(window) : [];
-var getWindowNames = function getWindowNames(it) {
- try {
- return gOPN(it);
- } catch (e) {
- return windowNames.slice();
- }
-};
-module.exports.f = function getOwnPropertyNames(it) {
- return windowNames && toString.call(it) == '[object Window]' ? getWindowNames(it) : gOPN(toIObject(it));
-};
-
-/***/ }),
-/* 122 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $keys = __w_pdfjs_require__(47);
-var hiddenKeys = __w_pdfjs_require__(49).concat('length', 'prototype');
-exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
- return $keys(O, hiddenKeys);
-};
-
-/***/ }),
-/* 123 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-__w_pdfjs_require__(124);
-module.exports = __w_pdfjs_require__(10).Object.values;
-
-/***/ }),
-/* 124 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var $export = __w_pdfjs_require__(8);
-var $values = __w_pdfjs_require__(125)(false);
-$export($export.S, 'Object', {
- values: function values(it) {
- return $values(it);
- }
-});
-
-/***/ }),
-/* 125 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var getKeys = __w_pdfjs_require__(46);
-var toIObject = __w_pdfjs_require__(37);
-var isEnum = __w_pdfjs_require__(51).f;
-module.exports = function (isEntries) {
- return function (it) {
- var O = toIObject(it);
- var keys = getKeys(O);
- var length = keys.length;
- var i = 0;
- var result = [];
- var key;
- while (length > i) {
- if (isEnum.call(O, key = keys[i++])) {
- result.push(isEntries ? [key, O[key]] : O[key]);
- }
- }return result;
- };
-};
-
-/***/ }),
-/* 126 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var isReadableStreamSupported = false;
-if (typeof ReadableStream !== 'undefined') {
- try {
- new ReadableStream({
- start: function start(controller) {
- controller.close();
- }
- });
- isReadableStreamSupported = true;
- } catch (e) {}
-}
-if (isReadableStreamSupported) {
- exports.ReadableStream = ReadableStream;
-} else {
- exports.ReadableStream = __w_pdfjs_require__(127).ReadableStream;
-}
-
-/***/ }),
-/* 127 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var _typeof2 = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-(function (e, a) {
- for (var i in a) {
- e[i] = a[i];
- }
-})(exports, function (modules) {
- var installedModules = {};
- function __w_pdfjs_require__(moduleId) {
- if (installedModules[moduleId]) return installedModules[moduleId].exports;
- var module = installedModules[moduleId] = {
- i: moduleId,
- l: false,
- exports: {}
- };
- modules[moduleId].call(module.exports, module, module.exports, __w_pdfjs_require__);
- module.l = true;
- return module.exports;
- }
- __w_pdfjs_require__.m = modules;
- __w_pdfjs_require__.c = installedModules;
- __w_pdfjs_require__.i = function (value) {
- return value;
- };
- __w_pdfjs_require__.d = function (exports, name, getter) {
- if (!__w_pdfjs_require__.o(exports, name)) {
- Object.defineProperty(exports, name, {
- configurable: false,
- enumerable: true,
- get: getter
- });
- }
- };
- __w_pdfjs_require__.n = function (module) {
- var getter = module && module.__esModule ? function getDefault() {
- return module['default'];
- } : function getModuleExports() {
- return module;
- };
- __w_pdfjs_require__.d(getter, 'a', getter);
- return getter;
- };
- __w_pdfjs_require__.o = function (object, property) {
- return Object.prototype.hasOwnProperty.call(object, property);
- };
- __w_pdfjs_require__.p = "";
- return __w_pdfjs_require__(__w_pdfjs_require__.s = 7);
-}([function (module, exports, __w_pdfjs_require__) {
- "use strict";
-
- var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) {
- return typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
- } : function (obj) {
- return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
- };
- var _require = __w_pdfjs_require__(1),
- assert = _require.assert;
- function IsPropertyKey(argument) {
- return typeof argument === 'string' || (typeof argument === 'undefined' ? 'undefined' : _typeof(argument)) === 'symbol';
- }
- exports.typeIsObject = function (x) {
- return (typeof x === 'undefined' ? 'undefined' : _typeof(x)) === 'object' && x !== null || typeof x === 'function';
- };
- exports.createDataProperty = function (o, p, v) {
- assert(exports.typeIsObject(o));
- Object.defineProperty(o, p, {
- value: v,
- writable: true,
- enumerable: true,
- configurable: true
- });
- };
- exports.createArrayFromList = function (elements) {
- return elements.slice();
- };
- exports.ArrayBufferCopy = function (dest, destOffset, src, srcOffset, n) {
- new Uint8Array(dest).set(new Uint8Array(src, srcOffset, n), destOffset);
- };
- exports.CreateIterResultObject = function (value, done) {
- assert(typeof done === 'boolean');
- var obj = {};
- Object.defineProperty(obj, 'value', {
- value: value,
- enumerable: true,
- writable: true,
- configurable: true
- });
- Object.defineProperty(obj, 'done', {
- value: done,
- enumerable: true,
- writable: true,
- configurable: true
- });
- return obj;
- };
- exports.IsFiniteNonNegativeNumber = function (v) {
- if (Number.isNaN(v)) {
- return false;
- }
- if (v === Infinity) {
- return false;
- }
- if (v < 0) {
- return false;
- }
- return true;
- };
- function Call(F, V, args) {
- if (typeof F !== 'function') {
- throw new TypeError('Argument is not a function');
- }
- return Function.prototype.apply.call(F, V, args);
- }
- exports.InvokeOrNoop = function (O, P, args) {
- assert(O !== undefined);
- assert(IsPropertyKey(P));
- assert(Array.isArray(args));
- var method = O[P];
- if (method === undefined) {
- return undefined;
- }
- return Call(method, O, args);
- };
- exports.PromiseInvokeOrNoop = function (O, P, args) {
- assert(O !== undefined);
- assert(IsPropertyKey(P));
- assert(Array.isArray(args));
- try {
- return Promise.resolve(exports.InvokeOrNoop(O, P, args));
- } catch (returnValueE) {
- return Promise.reject(returnValueE);
- }
- };
- exports.PromiseInvokeOrPerformFallback = function (O, P, args, F, argsF) {
- assert(O !== undefined);
- assert(IsPropertyKey(P));
- assert(Array.isArray(args));
- assert(Array.isArray(argsF));
- var method = void 0;
- try {
- method = O[P];
- } catch (methodE) {
- return Promise.reject(methodE);
- }
- if (method === undefined) {
- return F.apply(null, argsF);
- }
- try {
- return Promise.resolve(Call(method, O, args));
- } catch (e) {
- return Promise.reject(e);
- }
- };
- exports.TransferArrayBuffer = function (O) {
- return O.slice();
- };
- exports.ValidateAndNormalizeHighWaterMark = function (highWaterMark) {
- highWaterMark = Number(highWaterMark);
- if (Number.isNaN(highWaterMark) || highWaterMark < 0) {
- throw new RangeError('highWaterMark property of a queuing strategy must be non-negative and non-NaN');
- }
- return highWaterMark;
- };
- exports.ValidateAndNormalizeQueuingStrategy = function (size, highWaterMark) {
- if (size !== undefined && typeof size !== 'function') {
- throw new TypeError('size property of a queuing strategy must be a function');
- }
- highWaterMark = exports.ValidateAndNormalizeHighWaterMark(highWaterMark);
- return {
- size: size,
- highWaterMark: highWaterMark
- };
- };
-}, function (module, exports, __w_pdfjs_require__) {
- "use strict";
-
- function rethrowAssertionErrorRejection(e) {
- if (e && e.constructor === AssertionError) {
- setTimeout(function () {
- throw e;
- }, 0);
- }
- }
- function AssertionError(message) {
- this.name = 'AssertionError';
- this.message = message || '';
- this.stack = new Error().stack;
- }
- AssertionError.prototype = Object.create(Error.prototype);
- AssertionError.prototype.constructor = AssertionError;
- function assert(value, message) {
- if (!value) {
- throw new AssertionError(message);
- }
- }
- module.exports = {
- rethrowAssertionErrorRejection: rethrowAssertionErrorRejection,
- AssertionError: AssertionError,
- assert: assert
- };
-}, function (module, exports, __w_pdfjs_require__) {
- "use strict";
-
- var _createClass = function () {
- function defineProperties(target, props) {
- for (var i = 0; i < props.length; i++) {
- var descriptor = props[i];
- descriptor.enumerable = descriptor.enumerable || false;
- descriptor.configurable = true;
- if ("value" in descriptor) descriptor.writable = true;
- Object.defineProperty(target, descriptor.key, descriptor);
- }
- }
- return function (Constructor, protoProps, staticProps) {
- if (protoProps) defineProperties(Constructor.prototype, protoProps);
- if (staticProps) defineProperties(Constructor, staticProps);
- return Constructor;
- };
- }();
- function _classCallCheck(instance, Constructor) {
- if (!(instance instanceof Constructor)) {
- throw new TypeError("Cannot call a class as a function");
- }
- }
- var _require = __w_pdfjs_require__(0),
- InvokeOrNoop = _require.InvokeOrNoop,
- PromiseInvokeOrNoop = _require.PromiseInvokeOrNoop,
- ValidateAndNormalizeQueuingStrategy = _require.ValidateAndNormalizeQueuingStrategy,
- typeIsObject = _require.typeIsObject;
- var _require2 = __w_pdfjs_require__(1),
- assert = _require2.assert,
- rethrowAssertionErrorRejection = _require2.rethrowAssertionErrorRejection;
- var _require3 = __w_pdfjs_require__(3),
- DequeueValue = _require3.DequeueValue,
- EnqueueValueWithSize = _require3.EnqueueValueWithSize,
- PeekQueueValue = _require3.PeekQueueValue,
- ResetQueue = _require3.ResetQueue;
- var WritableStream = function () {
- function WritableStream() {
- var underlyingSink = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
- size = _ref.size,
- _ref$highWaterMark = _ref.highWaterMark,
- highWaterMark = _ref$highWaterMark === undefined ? 1 : _ref$highWaterMark;
- _classCallCheck(this, WritableStream);
- this._state = 'writable';
- this._storedError = undefined;
- this._writer = undefined;
- this._writableStreamController = undefined;
- this._writeRequests = [];
- this._inFlightWriteRequest = undefined;
- this._closeRequest = undefined;
- this._inFlightCloseRequest = undefined;
- this._pendingAbortRequest = undefined;
- this._backpressure = false;
- var type = underlyingSink.type;
- if (type !== undefined) {
- throw new RangeError('Invalid type is specified');
- }
- this._writableStreamController = new WritableStreamDefaultController(this, underlyingSink, size, highWaterMark);
- this._writableStreamController.__startSteps();
- }
- _createClass(WritableStream, [{
- key: 'abort',
- value: function abort(reason) {
- if (IsWritableStream(this) === false) {
- return Promise.reject(streamBrandCheckException('abort'));
- }
- if (IsWritableStreamLocked(this) === true) {
- return Promise.reject(new TypeError('Cannot abort a stream that already has a writer'));
- }
- return WritableStreamAbort(this, reason);
- }
- }, {
- key: 'getWriter',
- value: function getWriter() {
- if (IsWritableStream(this) === false) {
- throw streamBrandCheckException('getWriter');
- }
- return AcquireWritableStreamDefaultWriter(this);
- }
- }, {
- key: 'locked',
- get: function get() {
- if (IsWritableStream(this) === false) {
- throw streamBrandCheckException('locked');
- }
- return IsWritableStreamLocked(this);
- }
- }]);
- return WritableStream;
- }();
- module.exports = {
- AcquireWritableStreamDefaultWriter: AcquireWritableStreamDefaultWriter,
- IsWritableStream: IsWritableStream,
- IsWritableStreamLocked: IsWritableStreamLocked,
- WritableStream: WritableStream,
- WritableStreamAbort: WritableStreamAbort,
- WritableStreamDefaultControllerError: WritableStreamDefaultControllerError,
- WritableStreamDefaultWriterCloseWithErrorPropagation: WritableStreamDefaultWriterCloseWithErrorPropagation,
- WritableStreamDefaultWriterRelease: WritableStreamDefaultWriterRelease,
- WritableStreamDefaultWriterWrite: WritableStreamDefaultWriterWrite,
- WritableStreamCloseQueuedOrInFlight: WritableStreamCloseQueuedOrInFlight
- };
- function AcquireWritableStreamDefaultWriter(stream) {
- return new WritableStreamDefaultWriter(stream);
- }
- function IsWritableStream(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_writableStreamController')) {
- return false;
- }
- return true;
- }
- function IsWritableStreamLocked(stream) {
- assert(IsWritableStream(stream) === true, 'IsWritableStreamLocked should only be used on known writable streams');
- if (stream._writer === undefined) {
- return false;
- }
- return true;
- }
- function WritableStreamAbort(stream, reason) {
- var state = stream._state;
- if (state === 'closed') {
- return Promise.resolve(undefined);
- }
- if (state === 'errored') {
- return Promise.reject(stream._storedError);
- }
- var error = new TypeError('Requested to abort');
- if (stream._pendingAbortRequest !== undefined) {
- return Promise.reject(error);
- }
- assert(state === 'writable' || state === 'erroring', 'state must be writable or erroring');
- var wasAlreadyErroring = false;
- if (state === 'erroring') {
- wasAlreadyErroring = true;
- reason = undefined;
- }
- var promise = new Promise(function (resolve, reject) {
- stream._pendingAbortRequest = {
- _resolve: resolve,
- _reject: reject,
- _reason: reason,
- _wasAlreadyErroring: wasAlreadyErroring
- };
- });
- if (wasAlreadyErroring === false) {
- WritableStreamStartErroring(stream, error);
- }
- return promise;
- }
- function WritableStreamAddWriteRequest(stream) {
- assert(IsWritableStreamLocked(stream) === true);
- assert(stream._state === 'writable');
- var promise = new Promise(function (resolve, reject) {
- var writeRequest = {
- _resolve: resolve,
- _reject: reject
- };
- stream._writeRequests.push(writeRequest);
- });
- return promise;
- }
- function WritableStreamDealWithRejection(stream, error) {
- var state = stream._state;
- if (state === 'writable') {
- WritableStreamStartErroring(stream, error);
- return;
- }
- assert(state === 'erroring');
- WritableStreamFinishErroring(stream);
- }
- function WritableStreamStartErroring(stream, reason) {
- assert(stream._storedError === undefined, 'stream._storedError === undefined');
- assert(stream._state === 'writable', 'state must be writable');
- var controller = stream._writableStreamController;
- assert(controller !== undefined, 'controller must not be undefined');
- stream._state = 'erroring';
- stream._storedError = reason;
- var writer = stream._writer;
- if (writer !== undefined) {
- WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason);
- }
- if (WritableStreamHasOperationMarkedInFlight(stream) === false && controller._started === true) {
- WritableStreamFinishErroring(stream);
- }
- }
- function WritableStreamFinishErroring(stream) {
- assert(stream._state === 'erroring', 'stream._state === erroring');
- assert(WritableStreamHasOperationMarkedInFlight(stream) === false, 'WritableStreamHasOperationMarkedInFlight(stream) === false');
- stream._state = 'errored';
- stream._writableStreamController.__errorSteps();
- var storedError = stream._storedError;
- for (var i = 0; i < stream._writeRequests.length; i++) {
- var writeRequest = stream._writeRequests[i];
- writeRequest._reject(storedError);
- }
- stream._writeRequests = [];
- if (stream._pendingAbortRequest === undefined) {
- WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
- return;
- }
- var abortRequest = stream._pendingAbortRequest;
- stream._pendingAbortRequest = undefined;
- if (abortRequest._wasAlreadyErroring === true) {
- abortRequest._reject(storedError);
- WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
- return;
- }
- var promise = stream._writableStreamController.__abortSteps(abortRequest._reason);
- promise.then(function () {
- abortRequest._resolve();
- WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
- }, function (reason) {
- abortRequest._reject(reason);
- WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
- });
- }
- function WritableStreamFinishInFlightWrite(stream) {
- assert(stream._inFlightWriteRequest !== undefined);
- stream._inFlightWriteRequest._resolve(undefined);
- stream._inFlightWriteRequest = undefined;
- }
- function WritableStreamFinishInFlightWriteWithError(stream, error) {
- assert(stream._inFlightWriteRequest !== undefined);
- stream._inFlightWriteRequest._reject(error);
- stream._inFlightWriteRequest = undefined;
- assert(stream._state === 'writable' || stream._state === 'erroring');
- WritableStreamDealWithRejection(stream, error);
- }
- function WritableStreamFinishInFlightClose(stream) {
- assert(stream._inFlightCloseRequest !== undefined);
- stream._inFlightCloseRequest._resolve(undefined);
- stream._inFlightCloseRequest = undefined;
- var state = stream._state;
- assert(state === 'writable' || state === 'erroring');
- if (state === 'erroring') {
- stream._storedError = undefined;
- if (stream._pendingAbortRequest !== undefined) {
- stream._pendingAbortRequest._resolve();
- stream._pendingAbortRequest = undefined;
- }
- }
- stream._state = 'closed';
- var writer = stream._writer;
- if (writer !== undefined) {
- defaultWriterClosedPromiseResolve(writer);
- }
- assert(stream._pendingAbortRequest === undefined, 'stream._pendingAbortRequest === undefined');
- assert(stream._storedError === undefined, 'stream._storedError === undefined');
- }
- function WritableStreamFinishInFlightCloseWithError(stream, error) {
- assert(stream._inFlightCloseRequest !== undefined);
- stream._inFlightCloseRequest._reject(error);
- stream._inFlightCloseRequest = undefined;
- assert(stream._state === 'writable' || stream._state === 'erroring');
- if (stream._pendingAbortRequest !== undefined) {
- stream._pendingAbortRequest._reject(error);
- stream._pendingAbortRequest = undefined;
- }
- WritableStreamDealWithRejection(stream, error);
- }
- function WritableStreamCloseQueuedOrInFlight(stream) {
- if (stream._closeRequest === undefined && stream._inFlightCloseRequest === undefined) {
- return false;
- }
- return true;
- }
- function WritableStreamHasOperationMarkedInFlight(stream) {
- if (stream._inFlightWriteRequest === undefined && stream._inFlightCloseRequest === undefined) {
- return false;
- }
- return true;
- }
- function WritableStreamMarkCloseRequestInFlight(stream) {
- assert(stream._inFlightCloseRequest === undefined);
- assert(stream._closeRequest !== undefined);
- stream._inFlightCloseRequest = stream._closeRequest;
- stream._closeRequest = undefined;
- }
- function WritableStreamMarkFirstWriteRequestInFlight(stream) {
- assert(stream._inFlightWriteRequest === undefined, 'there must be no pending write request');
- assert(stream._writeRequests.length !== 0, 'writeRequests must not be empty');
- stream._inFlightWriteRequest = stream._writeRequests.shift();
- }
- function WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream) {
- assert(stream._state === 'errored', '_stream_.[[state]] is `"errored"`');
- if (stream._closeRequest !== undefined) {
- assert(stream._inFlightCloseRequest === undefined);
- stream._closeRequest._reject(stream._storedError);
- stream._closeRequest = undefined;
- }
- var writer = stream._writer;
- if (writer !== undefined) {
- defaultWriterClosedPromiseReject(writer, stream._storedError);
- writer._closedPromise.catch(function () {});
- }
- }
- function WritableStreamUpdateBackpressure(stream, backpressure) {
- assert(stream._state === 'writable');
- assert(WritableStreamCloseQueuedOrInFlight(stream) === false);
- var writer = stream._writer;
- if (writer !== undefined && backpressure !== stream._backpressure) {
- if (backpressure === true) {
- defaultWriterReadyPromiseReset(writer);
- } else {
- assert(backpressure === false);
- defaultWriterReadyPromiseResolve(writer);
- }
- }
- stream._backpressure = backpressure;
- }
- var WritableStreamDefaultWriter = function () {
- function WritableStreamDefaultWriter(stream) {
- _classCallCheck(this, WritableStreamDefaultWriter);
- if (IsWritableStream(stream) === false) {
- throw new TypeError('WritableStreamDefaultWriter can only be constructed with a WritableStream instance');
- }
- if (IsWritableStreamLocked(stream) === true) {
- throw new TypeError('This stream has already been locked for exclusive writing by another writer');
- }
- this._ownerWritableStream = stream;
- stream._writer = this;
- var state = stream._state;
- if (state === 'writable') {
- if (WritableStreamCloseQueuedOrInFlight(stream) === false && stream._backpressure === true) {
- defaultWriterReadyPromiseInitialize(this);
- } else {
- defaultWriterReadyPromiseInitializeAsResolved(this);
- }
- defaultWriterClosedPromiseInitialize(this);
- } else if (state === 'erroring') {
- defaultWriterReadyPromiseInitializeAsRejected(this, stream._storedError);
- this._readyPromise.catch(function () {});
- defaultWriterClosedPromiseInitialize(this);
- } else if (state === 'closed') {
- defaultWriterReadyPromiseInitializeAsResolved(this);
- defaultWriterClosedPromiseInitializeAsResolved(this);
- } else {
- assert(state === 'errored', 'state must be errored');
- var storedError = stream._storedError;
- defaultWriterReadyPromiseInitializeAsRejected(this, storedError);
- this._readyPromise.catch(function () {});
- defaultWriterClosedPromiseInitializeAsRejected(this, storedError);
- this._closedPromise.catch(function () {});
- }
- }
- _createClass(WritableStreamDefaultWriter, [{
- key: 'abort',
- value: function abort(reason) {
- if (IsWritableStreamDefaultWriter(this) === false) {
- return Promise.reject(defaultWriterBrandCheckException('abort'));
- }
- if (this._ownerWritableStream === undefined) {
- return Promise.reject(defaultWriterLockException('abort'));
- }
- return WritableStreamDefaultWriterAbort(this, reason);
- }
- }, {
- key: 'close',
- value: function close() {
- if (IsWritableStreamDefaultWriter(this) === false) {
- return Promise.reject(defaultWriterBrandCheckException('close'));
- }
- var stream = this._ownerWritableStream;
- if (stream === undefined) {
- return Promise.reject(defaultWriterLockException('close'));
- }
- if (WritableStreamCloseQueuedOrInFlight(stream) === true) {
- return Promise.reject(new TypeError('cannot close an already-closing stream'));
- }
- return WritableStreamDefaultWriterClose(this);
- }
- }, {
- key: 'releaseLock',
- value: function releaseLock() {
- if (IsWritableStreamDefaultWriter(this) === false) {
- throw defaultWriterBrandCheckException('releaseLock');
- }
- var stream = this._ownerWritableStream;
- if (stream === undefined) {
- return;
- }
- assert(stream._writer !== undefined);
- WritableStreamDefaultWriterRelease(this);
- }
- }, {
- key: 'write',
- value: function write(chunk) {
- if (IsWritableStreamDefaultWriter(this) === false) {
- return Promise.reject(defaultWriterBrandCheckException('write'));
- }
- if (this._ownerWritableStream === undefined) {
- return Promise.reject(defaultWriterLockException('write to'));
- }
- return WritableStreamDefaultWriterWrite(this, chunk);
- }
- }, {
- key: 'closed',
- get: function get() {
- if (IsWritableStreamDefaultWriter(this) === false) {
- return Promise.reject(defaultWriterBrandCheckException('closed'));
- }
- return this._closedPromise;
- }
- }, {
- key: 'desiredSize',
- get: function get() {
- if (IsWritableStreamDefaultWriter(this) === false) {
- throw defaultWriterBrandCheckException('desiredSize');
- }
- if (this._ownerWritableStream === undefined) {
- throw defaultWriterLockException('desiredSize');
- }
- return WritableStreamDefaultWriterGetDesiredSize(this);
- }
- }, {
- key: 'ready',
- get: function get() {
- if (IsWritableStreamDefaultWriter(this) === false) {
- return Promise.reject(defaultWriterBrandCheckException('ready'));
- }
- return this._readyPromise;
- }
- }]);
- return WritableStreamDefaultWriter;
- }();
- function IsWritableStreamDefaultWriter(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_ownerWritableStream')) {
- return false;
- }
- return true;
- }
- function WritableStreamDefaultWriterAbort(writer, reason) {
- var stream = writer._ownerWritableStream;
- assert(stream !== undefined);
- return WritableStreamAbort(stream, reason);
- }
- function WritableStreamDefaultWriterClose(writer) {
- var stream = writer._ownerWritableStream;
- assert(stream !== undefined);
- var state = stream._state;
- if (state === 'closed' || state === 'errored') {
- return Promise.reject(new TypeError('The stream (in ' + state + ' state) is not in the writable state and cannot be closed'));
- }
- assert(state === 'writable' || state === 'erroring');
- assert(WritableStreamCloseQueuedOrInFlight(stream) === false);
- var promise = new Promise(function (resolve, reject) {
- var closeRequest = {
- _resolve: resolve,
- _reject: reject
- };
- stream._closeRequest = closeRequest;
- });
- if (stream._backpressure === true && state === 'writable') {
- defaultWriterReadyPromiseResolve(writer);
- }
- WritableStreamDefaultControllerClose(stream._writableStreamController);
- return promise;
- }
- function WritableStreamDefaultWriterCloseWithErrorPropagation(writer) {
- var stream = writer._ownerWritableStream;
- assert(stream !== undefined);
- var state = stream._state;
- if (WritableStreamCloseQueuedOrInFlight(stream) === true || state === 'closed') {
- return Promise.resolve();
- }
- if (state === 'errored') {
- return Promise.reject(stream._storedError);
- }
- assert(state === 'writable' || state === 'erroring');
- return WritableStreamDefaultWriterClose(writer);
- }
- function WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, error) {
- if (writer._closedPromiseState === 'pending') {
- defaultWriterClosedPromiseReject(writer, error);
- } else {
- defaultWriterClosedPromiseResetToRejected(writer, error);
- }
- writer._closedPromise.catch(function () {});
- }
- function WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, error) {
- if (writer._readyPromiseState === 'pending') {
- defaultWriterReadyPromiseReject(writer, error);
- } else {
- defaultWriterReadyPromiseResetToRejected(writer, error);
- }
- writer._readyPromise.catch(function () {});
- }
- function WritableStreamDefaultWriterGetDesiredSize(writer) {
- var stream = writer._ownerWritableStream;
- var state = stream._state;
- if (state === 'errored' || state === 'erroring') {
- return null;
- }
- if (state === 'closed') {
- return 0;
- }
- return WritableStreamDefaultControllerGetDesiredSize(stream._writableStreamController);
- }
- function WritableStreamDefaultWriterRelease(writer) {
- var stream = writer._ownerWritableStream;
- assert(stream !== undefined);
- assert(stream._writer === writer);
- var releasedError = new TypeError('Writer was released and can no longer be used to monitor the stream\'s closedness');
- WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError);
- WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedError);
- stream._writer = undefined;
- writer._ownerWritableStream = undefined;
- }
- function WritableStreamDefaultWriterWrite(writer, chunk) {
- var stream = writer._ownerWritableStream;
- assert(stream !== undefined);
- var controller = stream._writableStreamController;
- var chunkSize = WritableStreamDefaultControllerGetChunkSize(controller, chunk);
- if (stream !== writer._ownerWritableStream) {
- return Promise.reject(defaultWriterLockException('write to'));
- }
- var state = stream._state;
- if (state === 'errored') {
- return Promise.reject(stream._storedError);
- }
- if (WritableStreamCloseQueuedOrInFlight(stream) === true || state === 'closed') {
- return Promise.reject(new TypeError('The stream is closing or closed and cannot be written to'));
- }
- if (state === 'erroring') {
- return Promise.reject(stream._storedError);
- }
- assert(state === 'writable');
- var promise = WritableStreamAddWriteRequest(stream);
- WritableStreamDefaultControllerWrite(controller, chunk, chunkSize);
- return promise;
- }
- var WritableStreamDefaultController = function () {
- function WritableStreamDefaultController(stream, underlyingSink, size, highWaterMark) {
- _classCallCheck(this, WritableStreamDefaultController);
- if (IsWritableStream(stream) === false) {
- throw new TypeError('WritableStreamDefaultController can only be constructed with a WritableStream instance');
- }
- if (stream._writableStreamController !== undefined) {
- throw new TypeError('WritableStreamDefaultController instances can only be created by the WritableStream constructor');
- }
- this._controlledWritableStream = stream;
- this._underlyingSink = underlyingSink;
- this._queue = undefined;
- this._queueTotalSize = undefined;
- ResetQueue(this);
- this._started = false;
- var normalizedStrategy = ValidateAndNormalizeQueuingStrategy(size, highWaterMark);
- this._strategySize = normalizedStrategy.size;
- this._strategyHWM = normalizedStrategy.highWaterMark;
- var backpressure = WritableStreamDefaultControllerGetBackpressure(this);
- WritableStreamUpdateBackpressure(stream, backpressure);
- }
- _createClass(WritableStreamDefaultController, [{
- key: 'error',
- value: function error(e) {
- if (IsWritableStreamDefaultController(this) === false) {
- throw new TypeError('WritableStreamDefaultController.prototype.error can only be used on a WritableStreamDefaultController');
- }
- var state = this._controlledWritableStream._state;
- if (state !== 'writable') {
- return;
- }
- WritableStreamDefaultControllerError(this, e);
- }
- }, {
- key: '__abortSteps',
- value: function __abortSteps(reason) {
- return PromiseInvokeOrNoop(this._underlyingSink, 'abort', [reason]);
- }
- }, {
- key: '__errorSteps',
- value: function __errorSteps() {
- ResetQueue(this);
- }
- }, {
- key: '__startSteps',
- value: function __startSteps() {
- var _this = this;
- var startResult = InvokeOrNoop(this._underlyingSink, 'start', [this]);
- var stream = this._controlledWritableStream;
- Promise.resolve(startResult).then(function () {
- assert(stream._state === 'writable' || stream._state === 'erroring');
- _this._started = true;
- WritableStreamDefaultControllerAdvanceQueueIfNeeded(_this);
- }, function (r) {
- assert(stream._state === 'writable' || stream._state === 'erroring');
- _this._started = true;
- WritableStreamDealWithRejection(stream, r);
- }).catch(rethrowAssertionErrorRejection);
- }
- }]);
- return WritableStreamDefaultController;
- }();
- function WritableStreamDefaultControllerClose(controller) {
- EnqueueValueWithSize(controller, 'close', 0);
- WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
- }
- function WritableStreamDefaultControllerGetChunkSize(controller, chunk) {
- var strategySize = controller._strategySize;
- if (strategySize === undefined) {
- return 1;
- }
- try {
- return strategySize(chunk);
- } catch (chunkSizeE) {
- WritableStreamDefaultControllerErrorIfNeeded(controller, chunkSizeE);
- return 1;
- }
- }
- function WritableStreamDefaultControllerGetDesiredSize(controller) {
- return controller._strategyHWM - controller._queueTotalSize;
- }
- function WritableStreamDefaultControllerWrite(controller, chunk, chunkSize) {
- var writeRecord = { chunk: chunk };
- try {
- EnqueueValueWithSize(controller, writeRecord, chunkSize);
- } catch (enqueueE) {
- WritableStreamDefaultControllerErrorIfNeeded(controller, enqueueE);
- return;
- }
- var stream = controller._controlledWritableStream;
- if (WritableStreamCloseQueuedOrInFlight(stream) === false && stream._state === 'writable') {
- var backpressure = WritableStreamDefaultControllerGetBackpressure(controller);
- WritableStreamUpdateBackpressure(stream, backpressure);
- }
- WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
- }
- function IsWritableStreamDefaultController(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_underlyingSink')) {
- return false;
- }
- return true;
- }
- function WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller) {
- var stream = controller._controlledWritableStream;
- if (controller._started === false) {
- return;
- }
- if (stream._inFlightWriteRequest !== undefined) {
- return;
- }
- var state = stream._state;
- if (state === 'closed' || state === 'errored') {
- return;
- }
- if (state === 'erroring') {
- WritableStreamFinishErroring(stream);
- return;
- }
- if (controller._queue.length === 0) {
- return;
- }
- var writeRecord = PeekQueueValue(controller);
- if (writeRecord === 'close') {
- WritableStreamDefaultControllerProcessClose(controller);
- } else {
- WritableStreamDefaultControllerProcessWrite(controller, writeRecord.chunk);
- }
- }
- function WritableStreamDefaultControllerErrorIfNeeded(controller, error) {
- if (controller._controlledWritableStream._state === 'writable') {
- WritableStreamDefaultControllerError(controller, error);
- }
- }
- function WritableStreamDefaultControllerProcessClose(controller) {
- var stream = controller._controlledWritableStream;
- WritableStreamMarkCloseRequestInFlight(stream);
- DequeueValue(controller);
- assert(controller._queue.length === 0, 'queue must be empty once the final write record is dequeued');
- var sinkClosePromise = PromiseInvokeOrNoop(controller._underlyingSink, 'close', []);
- sinkClosePromise.then(function () {
- WritableStreamFinishInFlightClose(stream);
- }, function (reason) {
- WritableStreamFinishInFlightCloseWithError(stream, reason);
- }).catch(rethrowAssertionErrorRejection);
- }
- function WritableStreamDefaultControllerProcessWrite(controller, chunk) {
- var stream = controller._controlledWritableStream;
- WritableStreamMarkFirstWriteRequestInFlight(stream);
- var sinkWritePromise = PromiseInvokeOrNoop(controller._underlyingSink, 'write', [chunk, controller]);
- sinkWritePromise.then(function () {
- WritableStreamFinishInFlightWrite(stream);
- var state = stream._state;
- assert(state === 'writable' || state === 'erroring');
- DequeueValue(controller);
- if (WritableStreamCloseQueuedOrInFlight(stream) === false && state === 'writable') {
- var backpressure = WritableStreamDefaultControllerGetBackpressure(controller);
- WritableStreamUpdateBackpressure(stream, backpressure);
- }
- WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
- }, function (reason) {
- WritableStreamFinishInFlightWriteWithError(stream, reason);
- }).catch(rethrowAssertionErrorRejection);
- }
- function WritableStreamDefaultControllerGetBackpressure(controller) {
- var desiredSize = WritableStreamDefaultControllerGetDesiredSize(controller);
- return desiredSize <= 0;
- }
- function WritableStreamDefaultControllerError(controller, error) {
- var stream = controller._controlledWritableStream;
- assert(stream._state === 'writable');
- WritableStreamStartErroring(stream, error);
- }
- function streamBrandCheckException(name) {
- return new TypeError('WritableStream.prototype.' + name + ' can only be used on a WritableStream');
- }
- function defaultWriterBrandCheckException(name) {
- return new TypeError('WritableStreamDefaultWriter.prototype.' + name + ' can only be used on a WritableStreamDefaultWriter');
- }
- function defaultWriterLockException(name) {
- return new TypeError('Cannot ' + name + ' a stream using a released writer');
- }
- function defaultWriterClosedPromiseInitialize(writer) {
- writer._closedPromise = new Promise(function (resolve, reject) {
- writer._closedPromise_resolve = resolve;
- writer._closedPromise_reject = reject;
- writer._closedPromiseState = 'pending';
- });
- }
- function defaultWriterClosedPromiseInitializeAsRejected(writer, reason) {
- writer._closedPromise = Promise.reject(reason);
- writer._closedPromise_resolve = undefined;
- writer._closedPromise_reject = undefined;
- writer._closedPromiseState = 'rejected';
- }
- function defaultWriterClosedPromiseInitializeAsResolved(writer) {
- writer._closedPromise = Promise.resolve(undefined);
- writer._closedPromise_resolve = undefined;
- writer._closedPromise_reject = undefined;
- writer._closedPromiseState = 'resolved';
- }
- function defaultWriterClosedPromiseReject(writer, reason) {
- assert(writer._closedPromise_resolve !== undefined, 'writer._closedPromise_resolve !== undefined');
- assert(writer._closedPromise_reject !== undefined, 'writer._closedPromise_reject !== undefined');
- assert(writer._closedPromiseState === 'pending', 'writer._closedPromiseState is pending');
- writer._closedPromise_reject(reason);
- writer._closedPromise_resolve = undefined;
- writer._closedPromise_reject = undefined;
- writer._closedPromiseState = 'rejected';
- }
- function defaultWriterClosedPromiseResetToRejected(writer, reason) {
- assert(writer._closedPromise_resolve === undefined, 'writer._closedPromise_resolve === undefined');
- assert(writer._closedPromise_reject === undefined, 'writer._closedPromise_reject === undefined');
- assert(writer._closedPromiseState !== 'pending', 'writer._closedPromiseState is not pending');
- writer._closedPromise = Promise.reject(reason);
- writer._closedPromiseState = 'rejected';
- }
- function defaultWriterClosedPromiseResolve(writer) {
- assert(writer._closedPromise_resolve !== undefined, 'writer._closedPromise_resolve !== undefined');
- assert(writer._closedPromise_reject !== undefined, 'writer._closedPromise_reject !== undefined');
- assert(writer._closedPromiseState === 'pending', 'writer._closedPromiseState is pending');
- writer._closedPromise_resolve(undefined);
- writer._closedPromise_resolve = undefined;
- writer._closedPromise_reject = undefined;
- writer._closedPromiseState = 'resolved';
- }
- function defaultWriterReadyPromiseInitialize(writer) {
- writer._readyPromise = new Promise(function (resolve, reject) {
- writer._readyPromise_resolve = resolve;
- writer._readyPromise_reject = reject;
- });
- writer._readyPromiseState = 'pending';
- }
- function defaultWriterReadyPromiseInitializeAsRejected(writer, reason) {
- writer._readyPromise = Promise.reject(reason);
- writer._readyPromise_resolve = undefined;
- writer._readyPromise_reject = undefined;
- writer._readyPromiseState = 'rejected';
- }
- function defaultWriterReadyPromiseInitializeAsResolved(writer) {
- writer._readyPromise = Promise.resolve(undefined);
- writer._readyPromise_resolve = undefined;
- writer._readyPromise_reject = undefined;
- writer._readyPromiseState = 'fulfilled';
- }
- function defaultWriterReadyPromiseReject(writer, reason) {
- assert(writer._readyPromise_resolve !== undefined, 'writer._readyPromise_resolve !== undefined');
- assert(writer._readyPromise_reject !== undefined, 'writer._readyPromise_reject !== undefined');
- writer._readyPromise_reject(reason);
- writer._readyPromise_resolve = undefined;
- writer._readyPromise_reject = undefined;
- writer._readyPromiseState = 'rejected';
- }
- function defaultWriterReadyPromiseReset(writer) {
- assert(writer._readyPromise_resolve === undefined, 'writer._readyPromise_resolve === undefined');
- assert(writer._readyPromise_reject === undefined, 'writer._readyPromise_reject === undefined');
- writer._readyPromise = new Promise(function (resolve, reject) {
- writer._readyPromise_resolve = resolve;
- writer._readyPromise_reject = reject;
- });
- writer._readyPromiseState = 'pending';
- }
- function defaultWriterReadyPromiseResetToRejected(writer, reason) {
- assert(writer._readyPromise_resolve === undefined, 'writer._readyPromise_resolve === undefined');
- assert(writer._readyPromise_reject === undefined, 'writer._readyPromise_reject === undefined');
- writer._readyPromise = Promise.reject(reason);
- writer._readyPromiseState = 'rejected';
- }
- function defaultWriterReadyPromiseResolve(writer) {
- assert(writer._readyPromise_resolve !== undefined, 'writer._readyPromise_resolve !== undefined');
- assert(writer._readyPromise_reject !== undefined, 'writer._readyPromise_reject !== undefined');
- writer._readyPromise_resolve(undefined);
- writer._readyPromise_resolve = undefined;
- writer._readyPromise_reject = undefined;
- writer._readyPromiseState = 'fulfilled';
- }
-}, function (module, exports, __w_pdfjs_require__) {
- "use strict";
-
- var _require = __w_pdfjs_require__(0),
- IsFiniteNonNegativeNumber = _require.IsFiniteNonNegativeNumber;
- var _require2 = __w_pdfjs_require__(1),
- assert = _require2.assert;
- exports.DequeueValue = function (container) {
- assert('_queue' in container && '_queueTotalSize' in container, 'Spec-level failure: DequeueValue should only be used on containers with [[queue]] and [[queueTotalSize]].');
- assert(container._queue.length > 0, 'Spec-level failure: should never dequeue from an empty queue.');
- var pair = container._queue.shift();
- container._queueTotalSize -= pair.size;
- if (container._queueTotalSize < 0) {
- container._queueTotalSize = 0;
- }
- return pair.value;
- };
- exports.EnqueueValueWithSize = function (container, value, size) {
- assert('_queue' in container && '_queueTotalSize' in container, 'Spec-level failure: EnqueueValueWithSize should only be used on containers with [[queue]] and ' + '[[queueTotalSize]].');
- size = Number(size);
- if (!IsFiniteNonNegativeNumber(size)) {
- throw new RangeError('Size must be a finite, non-NaN, non-negative number.');
- }
- container._queue.push({
- value: value,
- size: size
- });
- container._queueTotalSize += size;
- };
- exports.PeekQueueValue = function (container) {
- assert('_queue' in container && '_queueTotalSize' in container, 'Spec-level failure: PeekQueueValue should only be used on containers with [[queue]] and [[queueTotalSize]].');
- assert(container._queue.length > 0, 'Spec-level failure: should never peek at an empty queue.');
- var pair = container._queue[0];
- return pair.value;
- };
- exports.ResetQueue = function (container) {
- assert('_queue' in container && '_queueTotalSize' in container, 'Spec-level failure: ResetQueue should only be used on containers with [[queue]] and [[queueTotalSize]].');
- container._queue = [];
- container._queueTotalSize = 0;
- };
-}, function (module, exports, __w_pdfjs_require__) {
- "use strict";
-
- var _createClass = function () {
- function defineProperties(target, props) {
- for (var i = 0; i < props.length; i++) {
- var descriptor = props[i];
- descriptor.enumerable = descriptor.enumerable || false;
- descriptor.configurable = true;
- if ("value" in descriptor) descriptor.writable = true;
- Object.defineProperty(target, descriptor.key, descriptor);
- }
- }
- return function (Constructor, protoProps, staticProps) {
- if (protoProps) defineProperties(Constructor.prototype, protoProps);
- if (staticProps) defineProperties(Constructor, staticProps);
- return Constructor;
- };
- }();
- function _classCallCheck(instance, Constructor) {
- if (!(instance instanceof Constructor)) {
- throw new TypeError("Cannot call a class as a function");
- }
- }
- var _require = __w_pdfjs_require__(0),
- ArrayBufferCopy = _require.ArrayBufferCopy,
- CreateIterResultObject = _require.CreateIterResultObject,
- IsFiniteNonNegativeNumber = _require.IsFiniteNonNegativeNumber,
- InvokeOrNoop = _require.InvokeOrNoop,
- PromiseInvokeOrNoop = _require.PromiseInvokeOrNoop,
- TransferArrayBuffer = _require.TransferArrayBuffer,
- ValidateAndNormalizeQueuingStrategy = _require.ValidateAndNormalizeQueuingStrategy,
- ValidateAndNormalizeHighWaterMark = _require.ValidateAndNormalizeHighWaterMark;
- var _require2 = __w_pdfjs_require__(0),
- createArrayFromList = _require2.createArrayFromList,
- createDataProperty = _require2.createDataProperty,
- typeIsObject = _require2.typeIsObject;
- var _require3 = __w_pdfjs_require__(1),
- assert = _require3.assert,
- rethrowAssertionErrorRejection = _require3.rethrowAssertionErrorRejection;
- var _require4 = __w_pdfjs_require__(3),
- DequeueValue = _require4.DequeueValue,
- EnqueueValueWithSize = _require4.EnqueueValueWithSize,
- ResetQueue = _require4.ResetQueue;
- var _require5 = __w_pdfjs_require__(2),
- AcquireWritableStreamDefaultWriter = _require5.AcquireWritableStreamDefaultWriter,
- IsWritableStream = _require5.IsWritableStream,
- IsWritableStreamLocked = _require5.IsWritableStreamLocked,
- WritableStreamAbort = _require5.WritableStreamAbort,
- WritableStreamDefaultWriterCloseWithErrorPropagation = _require5.WritableStreamDefaultWriterCloseWithErrorPropagation,
- WritableStreamDefaultWriterRelease = _require5.WritableStreamDefaultWriterRelease,
- WritableStreamDefaultWriterWrite = _require5.WritableStreamDefaultWriterWrite,
- WritableStreamCloseQueuedOrInFlight = _require5.WritableStreamCloseQueuedOrInFlight;
- var ReadableStream = function () {
- function ReadableStream() {
- var underlyingSource = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
- size = _ref.size,
- highWaterMark = _ref.highWaterMark;
- _classCallCheck(this, ReadableStream);
- this._state = 'readable';
- this._reader = undefined;
- this._storedError = undefined;
- this._disturbed = false;
- this._readableStreamController = undefined;
- var type = underlyingSource.type;
- var typeString = String(type);
- if (typeString === 'bytes') {
- if (highWaterMark === undefined) {
- highWaterMark = 0;
- }
- this._readableStreamController = new ReadableByteStreamController(this, underlyingSource, highWaterMark);
- } else if (type === undefined) {
- if (highWaterMark === undefined) {
- highWaterMark = 1;
- }
- this._readableStreamController = new ReadableStreamDefaultController(this, underlyingSource, size, highWaterMark);
- } else {
- throw new RangeError('Invalid type is specified');
- }
- }
- _createClass(ReadableStream, [{
- key: 'cancel',
- value: function cancel(reason) {
- if (IsReadableStream(this) === false) {
- return Promise.reject(streamBrandCheckException('cancel'));
- }
- if (IsReadableStreamLocked(this) === true) {
- return Promise.reject(new TypeError('Cannot cancel a stream that already has a reader'));
- }
- return ReadableStreamCancel(this, reason);
- }
- }, {
- key: 'getReader',
- value: function getReader() {
- var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- mode = _ref2.mode;
- if (IsReadableStream(this) === false) {
- throw streamBrandCheckException('getReader');
- }
- if (mode === undefined) {
- return AcquireReadableStreamDefaultReader(this);
- }
- mode = String(mode);
- if (mode === 'byob') {
- return AcquireReadableStreamBYOBReader(this);
- }
- throw new RangeError('Invalid mode is specified');
- }
- }, {
- key: 'pipeThrough',
- value: function pipeThrough(_ref3, options) {
- var writable = _ref3.writable,
- readable = _ref3.readable;
- var promise = this.pipeTo(writable, options);
- ifIsObjectAndHasAPromiseIsHandledInternalSlotSetPromiseIsHandledToTrue(promise);
- return readable;
- }
- }, {
- key: 'pipeTo',
- value: function pipeTo(dest) {
- var _this = this;
- var _ref4 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
- preventClose = _ref4.preventClose,
- preventAbort = _ref4.preventAbort,
- preventCancel = _ref4.preventCancel;
- if (IsReadableStream(this) === false) {
- return Promise.reject(streamBrandCheckException('pipeTo'));
- }
- if (IsWritableStream(dest) === false) {
- return Promise.reject(new TypeError('ReadableStream.prototype.pipeTo\'s first argument must be a WritableStream'));
- }
- preventClose = Boolean(preventClose);
- preventAbort = Boolean(preventAbort);
- preventCancel = Boolean(preventCancel);
- if (IsReadableStreamLocked(this) === true) {
- return Promise.reject(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream'));
- }
- if (IsWritableStreamLocked(dest) === true) {
- return Promise.reject(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream'));
- }
- var reader = AcquireReadableStreamDefaultReader(this);
- var writer = AcquireWritableStreamDefaultWriter(dest);
- var shuttingDown = false;
- var currentWrite = Promise.resolve();
- return new Promise(function (resolve, reject) {
- function pipeLoop() {
- currentWrite = Promise.resolve();
- if (shuttingDown === true) {
- return Promise.resolve();
- }
- return writer._readyPromise.then(function () {
- return ReadableStreamDefaultReaderRead(reader).then(function (_ref5) {
- var value = _ref5.value,
- done = _ref5.done;
- if (done === true) {
- return;
- }
- currentWrite = WritableStreamDefaultWriterWrite(writer, value).catch(function () {});
- });
- }).then(pipeLoop);
- }
- isOrBecomesErrored(_this, reader._closedPromise, function (storedError) {
- if (preventAbort === false) {
- shutdownWithAction(function () {
- return WritableStreamAbort(dest, storedError);
- }, true, storedError);
- } else {
- shutdown(true, storedError);
- }
- });
- isOrBecomesErrored(dest, writer._closedPromise, function (storedError) {
- if (preventCancel === false) {
- shutdownWithAction(function () {
- return ReadableStreamCancel(_this, storedError);
- }, true, storedError);
- } else {
- shutdown(true, storedError);
- }
- });
- isOrBecomesClosed(_this, reader._closedPromise, function () {
- if (preventClose === false) {
- shutdownWithAction(function () {
- return WritableStreamDefaultWriterCloseWithErrorPropagation(writer);
- });
- } else {
- shutdown();
- }
- });
- if (WritableStreamCloseQueuedOrInFlight(dest) === true || dest._state === 'closed') {
- var destClosed = new TypeError('the destination writable stream closed before all data could be piped to it');
- if (preventCancel === false) {
- shutdownWithAction(function () {
- return ReadableStreamCancel(_this, destClosed);
- }, true, destClosed);
- } else {
- shutdown(true, destClosed);
- }
- }
- pipeLoop().catch(function (err) {
- currentWrite = Promise.resolve();
- rethrowAssertionErrorRejection(err);
- });
- function waitForWritesToFinish() {
- var oldCurrentWrite = currentWrite;
- return currentWrite.then(function () {
- return oldCurrentWrite !== currentWrite ? waitForWritesToFinish() : undefined;
- });
- }
- function isOrBecomesErrored(stream, promise, action) {
- if (stream._state === 'errored') {
- action(stream._storedError);
- } else {
- promise.catch(action).catch(rethrowAssertionErrorRejection);
- }
- }
- function isOrBecomesClosed(stream, promise, action) {
- if (stream._state === 'closed') {
- action();
- } else {
- promise.then(action).catch(rethrowAssertionErrorRejection);
- }
- }
- function shutdownWithAction(action, originalIsError, originalError) {
- if (shuttingDown === true) {
- return;
- }
- shuttingDown = true;
- if (dest._state === 'writable' && WritableStreamCloseQueuedOrInFlight(dest) === false) {
- waitForWritesToFinish().then(doTheRest);
- } else {
- doTheRest();
- }
- function doTheRest() {
- action().then(function () {
- return finalize(originalIsError, originalError);
- }, function (newError) {
- return finalize(true, newError);
- }).catch(rethrowAssertionErrorRejection);
- }
- }
- function shutdown(isError, error) {
- if (shuttingDown === true) {
- return;
- }
- shuttingDown = true;
- if (dest._state === 'writable' && WritableStreamCloseQueuedOrInFlight(dest) === false) {
- waitForWritesToFinish().then(function () {
- return finalize(isError, error);
- }).catch(rethrowAssertionErrorRejection);
- } else {
- finalize(isError, error);
- }
- }
- function finalize(isError, error) {
- WritableStreamDefaultWriterRelease(writer);
- ReadableStreamReaderGenericRelease(reader);
- if (isError) {
- reject(error);
- } else {
- resolve(undefined);
- }
- }
- });
- }
- }, {
- key: 'tee',
- value: function tee() {
- if (IsReadableStream(this) === false) {
- throw streamBrandCheckException('tee');
- }
- var branches = ReadableStreamTee(this, false);
- return createArrayFromList(branches);
- }
- }, {
- key: 'locked',
- get: function get() {
- if (IsReadableStream(this) === false) {
- throw streamBrandCheckException('locked');
- }
- return IsReadableStreamLocked(this);
- }
- }]);
- return ReadableStream;
- }();
- module.exports = {
- ReadableStream: ReadableStream,
- IsReadableStreamDisturbed: IsReadableStreamDisturbed,
- ReadableStreamDefaultControllerClose: ReadableStreamDefaultControllerClose,
- ReadableStreamDefaultControllerEnqueue: ReadableStreamDefaultControllerEnqueue,
- ReadableStreamDefaultControllerError: ReadableStreamDefaultControllerError,
- ReadableStreamDefaultControllerGetDesiredSize: ReadableStreamDefaultControllerGetDesiredSize
- };
- function AcquireReadableStreamBYOBReader(stream) {
- return new ReadableStreamBYOBReader(stream);
- }
- function AcquireReadableStreamDefaultReader(stream) {
- return new ReadableStreamDefaultReader(stream);
- }
- function IsReadableStream(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_readableStreamController')) {
- return false;
- }
- return true;
- }
- function IsReadableStreamDisturbed(stream) {
- assert(IsReadableStream(stream) === true, 'IsReadableStreamDisturbed should only be used on known readable streams');
- return stream._disturbed;
- }
- function IsReadableStreamLocked(stream) {
- assert(IsReadableStream(stream) === true, 'IsReadableStreamLocked should only be used on known readable streams');
- if (stream._reader === undefined) {
- return false;
- }
- return true;
- }
- function ReadableStreamTee(stream, cloneForBranch2) {
- assert(IsReadableStream(stream) === true);
- assert(typeof cloneForBranch2 === 'boolean');
- var reader = AcquireReadableStreamDefaultReader(stream);
- var teeState = {
- closedOrErrored: false,
- canceled1: false,
- canceled2: false,
- reason1: undefined,
- reason2: undefined
- };
- teeState.promise = new Promise(function (resolve) {
- teeState._resolve = resolve;
- });
- var pull = create_ReadableStreamTeePullFunction();
- pull._reader = reader;
- pull._teeState = teeState;
- pull._cloneForBranch2 = cloneForBranch2;
- var cancel1 = create_ReadableStreamTeeBranch1CancelFunction();
- cancel1._stream = stream;
- cancel1._teeState = teeState;
- var cancel2 = create_ReadableStreamTeeBranch2CancelFunction();
- cancel2._stream = stream;
- cancel2._teeState = teeState;
- var underlyingSource1 = Object.create(Object.prototype);
- createDataProperty(underlyingSource1, 'pull', pull);
- createDataProperty(underlyingSource1, 'cancel', cancel1);
- var branch1Stream = new ReadableStream(underlyingSource1);
- var underlyingSource2 = Object.create(Object.prototype);
- createDataProperty(underlyingSource2, 'pull', pull);
- createDataProperty(underlyingSource2, 'cancel', cancel2);
- var branch2Stream = new ReadableStream(underlyingSource2);
- pull._branch1 = branch1Stream._readableStreamController;
- pull._branch2 = branch2Stream._readableStreamController;
- reader._closedPromise.catch(function (r) {
- if (teeState.closedOrErrored === true) {
- return;
- }
- ReadableStreamDefaultControllerError(pull._branch1, r);
- ReadableStreamDefaultControllerError(pull._branch2, r);
- teeState.closedOrErrored = true;
- });
- return [branch1Stream, branch2Stream];
- }
- function create_ReadableStreamTeePullFunction() {
- function f() {
- var reader = f._reader,
- branch1 = f._branch1,
- branch2 = f._branch2,
- teeState = f._teeState;
- return ReadableStreamDefaultReaderRead(reader).then(function (result) {
- assert(typeIsObject(result));
- var value = result.value;
- var done = result.done;
- assert(typeof done === 'boolean');
- if (done === true && teeState.closedOrErrored === false) {
- if (teeState.canceled1 === false) {
- ReadableStreamDefaultControllerClose(branch1);
- }
- if (teeState.canceled2 === false) {
- ReadableStreamDefaultControllerClose(branch2);
- }
- teeState.closedOrErrored = true;
- }
- if (teeState.closedOrErrored === true) {
- return;
- }
- var value1 = value;
- var value2 = value;
- if (teeState.canceled1 === false) {
- ReadableStreamDefaultControllerEnqueue(branch1, value1);
- }
- if (teeState.canceled2 === false) {
- ReadableStreamDefaultControllerEnqueue(branch2, value2);
- }
- });
- }
- return f;
- }
- function create_ReadableStreamTeeBranch1CancelFunction() {
- function f(reason) {
- var stream = f._stream,
- teeState = f._teeState;
- teeState.canceled1 = true;
- teeState.reason1 = reason;
- if (teeState.canceled2 === true) {
- var compositeReason = createArrayFromList([teeState.reason1, teeState.reason2]);
- var cancelResult = ReadableStreamCancel(stream, compositeReason);
- teeState._resolve(cancelResult);
- }
- return teeState.promise;
- }
- return f;
- }
- function create_ReadableStreamTeeBranch2CancelFunction() {
- function f(reason) {
- var stream = f._stream,
- teeState = f._teeState;
- teeState.canceled2 = true;
- teeState.reason2 = reason;
- if (teeState.canceled1 === true) {
- var compositeReason = createArrayFromList([teeState.reason1, teeState.reason2]);
- var cancelResult = ReadableStreamCancel(stream, compositeReason);
- teeState._resolve(cancelResult);
- }
- return teeState.promise;
- }
- return f;
- }
- function ReadableStreamAddReadIntoRequest(stream) {
- assert(IsReadableStreamBYOBReader(stream._reader) === true);
- assert(stream._state === 'readable' || stream._state === 'closed');
- var promise = new Promise(function (resolve, reject) {
- var readIntoRequest = {
- _resolve: resolve,
- _reject: reject
- };
- stream._reader._readIntoRequests.push(readIntoRequest);
- });
- return promise;
- }
- function ReadableStreamAddReadRequest(stream) {
- assert(IsReadableStreamDefaultReader(stream._reader) === true);
- assert(stream._state === 'readable');
- var promise = new Promise(function (resolve, reject) {
- var readRequest = {
- _resolve: resolve,
- _reject: reject
- };
- stream._reader._readRequests.push(readRequest);
- });
- return promise;
- }
- function ReadableStreamCancel(stream, reason) {
- stream._disturbed = true;
- if (stream._state === 'closed') {
- return Promise.resolve(undefined);
- }
- if (stream._state === 'errored') {
- return Promise.reject(stream._storedError);
- }
- ReadableStreamClose(stream);
- var sourceCancelPromise = stream._readableStreamController.__cancelSteps(reason);
- return sourceCancelPromise.then(function () {
- return undefined;
- });
- }
- function ReadableStreamClose(stream) {
- assert(stream._state === 'readable');
- stream._state = 'closed';
- var reader = stream._reader;
- if (reader === undefined) {
- return undefined;
- }
- if (IsReadableStreamDefaultReader(reader) === true) {
- for (var i = 0; i < reader._readRequests.length; i++) {
- var _resolve = reader._readRequests[i]._resolve;
- _resolve(CreateIterResultObject(undefined, true));
- }
- reader._readRequests = [];
- }
- defaultReaderClosedPromiseResolve(reader);
- return undefined;
- }
- function ReadableStreamError(stream, e) {
- assert(IsReadableStream(stream) === true, 'stream must be ReadableStream');
- assert(stream._state === 'readable', 'state must be readable');
- stream._state = 'errored';
- stream._storedError = e;
- var reader = stream._reader;
- if (reader === undefined) {
- return undefined;
- }
- if (IsReadableStreamDefaultReader(reader) === true) {
- for (var i = 0; i < reader._readRequests.length; i++) {
- var readRequest = reader._readRequests[i];
- readRequest._reject(e);
- }
- reader._readRequests = [];
- } else {
- assert(IsReadableStreamBYOBReader(reader), 'reader must be ReadableStreamBYOBReader');
- for (var _i = 0; _i < reader._readIntoRequests.length; _i++) {
- var readIntoRequest = reader._readIntoRequests[_i];
- readIntoRequest._reject(e);
- }
- reader._readIntoRequests = [];
- }
- defaultReaderClosedPromiseReject(reader, e);
- reader._closedPromise.catch(function () {});
- }
- function ReadableStreamFulfillReadIntoRequest(stream, chunk, done) {
- var reader = stream._reader;
- assert(reader._readIntoRequests.length > 0);
- var readIntoRequest = reader._readIntoRequests.shift();
- readIntoRequest._resolve(CreateIterResultObject(chunk, done));
- }
- function ReadableStreamFulfillReadRequest(stream, chunk, done) {
- var reader = stream._reader;
- assert(reader._readRequests.length > 0);
- var readRequest = reader._readRequests.shift();
- readRequest._resolve(CreateIterResultObject(chunk, done));
- }
- function ReadableStreamGetNumReadIntoRequests(stream) {
- return stream._reader._readIntoRequests.length;
- }
- function ReadableStreamGetNumReadRequests(stream) {
- return stream._reader._readRequests.length;
- }
- function ReadableStreamHasBYOBReader(stream) {
- var reader = stream._reader;
- if (reader === undefined) {
- return false;
- }
- if (IsReadableStreamBYOBReader(reader) === false) {
- return false;
- }
- return true;
- }
- function ReadableStreamHasDefaultReader(stream) {
- var reader = stream._reader;
- if (reader === undefined) {
- return false;
- }
- if (IsReadableStreamDefaultReader(reader) === false) {
- return false;
- }
- return true;
- }
- var ReadableStreamDefaultReader = function () {
- function ReadableStreamDefaultReader(stream) {
- _classCallCheck(this, ReadableStreamDefaultReader);
- if (IsReadableStream(stream) === false) {
- throw new TypeError('ReadableStreamDefaultReader can only be constructed with a ReadableStream instance');
- }
- if (IsReadableStreamLocked(stream) === true) {
- throw new TypeError('This stream has already been locked for exclusive reading by another reader');
- }
- ReadableStreamReaderGenericInitialize(this, stream);
- this._readRequests = [];
- }
- _createClass(ReadableStreamDefaultReader, [{
- key: 'cancel',
- value: function cancel(reason) {
- if (IsReadableStreamDefaultReader(this) === false) {
- return Promise.reject(defaultReaderBrandCheckException('cancel'));
- }
- if (this._ownerReadableStream === undefined) {
- return Promise.reject(readerLockException('cancel'));
- }
- return ReadableStreamReaderGenericCancel(this, reason);
- }
- }, {
- key: 'read',
- value: function read() {
- if (IsReadableStreamDefaultReader(this) === false) {
- return Promise.reject(defaultReaderBrandCheckException('read'));
- }
- if (this._ownerReadableStream === undefined) {
- return Promise.reject(readerLockException('read from'));
- }
- return ReadableStreamDefaultReaderRead(this);
- }
- }, {
- key: 'releaseLock',
- value: function releaseLock() {
- if (IsReadableStreamDefaultReader(this) === false) {
- throw defaultReaderBrandCheckException('releaseLock');
- }
- if (this._ownerReadableStream === undefined) {
- return;
- }
- if (this._readRequests.length > 0) {
- throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled');
- }
- ReadableStreamReaderGenericRelease(this);
- }
- }, {
- key: 'closed',
- get: function get() {
- if (IsReadableStreamDefaultReader(this) === false) {
- return Promise.reject(defaultReaderBrandCheckException('closed'));
- }
- return this._closedPromise;
- }
- }]);
- return ReadableStreamDefaultReader;
- }();
- var ReadableStreamBYOBReader = function () {
- function ReadableStreamBYOBReader(stream) {
- _classCallCheck(this, ReadableStreamBYOBReader);
- if (!IsReadableStream(stream)) {
- throw new TypeError('ReadableStreamBYOBReader can only be constructed with a ReadableStream instance given a ' + 'byte source');
- }
- if (IsReadableByteStreamController(stream._readableStreamController) === false) {
- throw new TypeError('Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte ' + 'source');
- }
- if (IsReadableStreamLocked(stream)) {
- throw new TypeError('This stream has already been locked for exclusive reading by another reader');
- }
- ReadableStreamReaderGenericInitialize(this, stream);
- this._readIntoRequests = [];
- }
- _createClass(ReadableStreamBYOBReader, [{
- key: 'cancel',
- value: function cancel(reason) {
- if (!IsReadableStreamBYOBReader(this)) {
- return Promise.reject(byobReaderBrandCheckException('cancel'));
- }
- if (this._ownerReadableStream === undefined) {
- return Promise.reject(readerLockException('cancel'));
- }
- return ReadableStreamReaderGenericCancel(this, reason);
- }
- }, {
- key: 'read',
- value: function read(view) {
- if (!IsReadableStreamBYOBReader(this)) {
- return Promise.reject(byobReaderBrandCheckException('read'));
- }
- if (this._ownerReadableStream === undefined) {
- return Promise.reject(readerLockException('read from'));
- }
- if (!ArrayBuffer.isView(view)) {
- return Promise.reject(new TypeError('view must be an array buffer view'));
- }
- if (view.byteLength === 0) {
- return Promise.reject(new TypeError('view must have non-zero byteLength'));
- }
- return ReadableStreamBYOBReaderRead(this, view);
- }
- }, {
- key: 'releaseLock',
- value: function releaseLock() {
- if (!IsReadableStreamBYOBReader(this)) {
- throw byobReaderBrandCheckException('releaseLock');
- }
- if (this._ownerReadableStream === undefined) {
- return;
- }
- if (this._readIntoRequests.length > 0) {
- throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled');
- }
- ReadableStreamReaderGenericRelease(this);
- }
- }, {
- key: 'closed',
- get: function get() {
- if (!IsReadableStreamBYOBReader(this)) {
- return Promise.reject(byobReaderBrandCheckException('closed'));
- }
- return this._closedPromise;
- }
- }]);
- return ReadableStreamBYOBReader;
- }();
- function IsReadableStreamBYOBReader(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_readIntoRequests')) {
- return false;
- }
- return true;
- }
- function IsReadableStreamDefaultReader(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_readRequests')) {
- return false;
- }
- return true;
- }
- function ReadableStreamReaderGenericInitialize(reader, stream) {
- reader._ownerReadableStream = stream;
- stream._reader = reader;
- if (stream._state === 'readable') {
- defaultReaderClosedPromiseInitialize(reader);
- } else if (stream._state === 'closed') {
- defaultReaderClosedPromiseInitializeAsResolved(reader);
- } else {
- assert(stream._state === 'errored', 'state must be errored');
- defaultReaderClosedPromiseInitializeAsRejected(reader, stream._storedError);
- reader._closedPromise.catch(function () {});
- }
- }
- function ReadableStreamReaderGenericCancel(reader, reason) {
- var stream = reader._ownerReadableStream;
- assert(stream !== undefined);
- return ReadableStreamCancel(stream, reason);
- }
- function ReadableStreamReaderGenericRelease(reader) {
- assert(reader._ownerReadableStream !== undefined);
- assert(reader._ownerReadableStream._reader === reader);
- if (reader._ownerReadableStream._state === 'readable') {
- defaultReaderClosedPromiseReject(reader, new TypeError('Reader was released and can no longer be used to monitor the stream\'s closedness'));
- } else {
- defaultReaderClosedPromiseResetToRejected(reader, new TypeError('Reader was released and can no longer be used to monitor the stream\'s closedness'));
- }
- reader._closedPromise.catch(function () {});
- reader._ownerReadableStream._reader = undefined;
- reader._ownerReadableStream = undefined;
- }
- function ReadableStreamBYOBReaderRead(reader, view) {
- var stream = reader._ownerReadableStream;
- assert(stream !== undefined);
- stream._disturbed = true;
- if (stream._state === 'errored') {
- return Promise.reject(stream._storedError);
- }
- return ReadableByteStreamControllerPullInto(stream._readableStreamController, view);
- }
- function ReadableStreamDefaultReaderRead(reader) {
- var stream = reader._ownerReadableStream;
- assert(stream !== undefined);
- stream._disturbed = true;
- if (stream._state === 'closed') {
- return Promise.resolve(CreateIterResultObject(undefined, true));
- }
- if (stream._state === 'errored') {
- return Promise.reject(stream._storedError);
- }
- assert(stream._state === 'readable');
- return stream._readableStreamController.__pullSteps();
- }
- var ReadableStreamDefaultController = function () {
- function ReadableStreamDefaultController(stream, underlyingSource, size, highWaterMark) {
- _classCallCheck(this, ReadableStreamDefaultController);
- if (IsReadableStream(stream) === false) {
- throw new TypeError('ReadableStreamDefaultController can only be constructed with a ReadableStream instance');
- }
- if (stream._readableStreamController !== undefined) {
- throw new TypeError('ReadableStreamDefaultController instances can only be created by the ReadableStream constructor');
- }
- this._controlledReadableStream = stream;
- this._underlyingSource = underlyingSource;
- this._queue = undefined;
- this._queueTotalSize = undefined;
- ResetQueue(this);
- this._started = false;
- this._closeRequested = false;
- this._pullAgain = false;
- this._pulling = false;
- var normalizedStrategy = ValidateAndNormalizeQueuingStrategy(size, highWaterMark);
- this._strategySize = normalizedStrategy.size;
- this._strategyHWM = normalizedStrategy.highWaterMark;
- var controller = this;
- var startResult = InvokeOrNoop(underlyingSource, 'start', [this]);
- Promise.resolve(startResult).then(function () {
- controller._started = true;
- assert(controller._pulling === false);
- assert(controller._pullAgain === false);
- ReadableStreamDefaultControllerCallPullIfNeeded(controller);
- }, function (r) {
- ReadableStreamDefaultControllerErrorIfNeeded(controller, r);
- }).catch(rethrowAssertionErrorRejection);
- }
- _createClass(ReadableStreamDefaultController, [{
- key: 'close',
- value: function close() {
- if (IsReadableStreamDefaultController(this) === false) {
- throw defaultControllerBrandCheckException('close');
- }
- if (this._closeRequested === true) {
- throw new TypeError('The stream has already been closed; do not close it again!');
- }
- var state = this._controlledReadableStream._state;
- if (state !== 'readable') {
- throw new TypeError('The stream (in ' + state + ' state) is not in the readable state and cannot be closed');
- }
- ReadableStreamDefaultControllerClose(this);
- }
- }, {
- key: 'enqueue',
- value: function enqueue(chunk) {
- if (IsReadableStreamDefaultController(this) === false) {
- throw defaultControllerBrandCheckException('enqueue');
- }
- if (this._closeRequested === true) {
- throw new TypeError('stream is closed or draining');
- }
- var state = this._controlledReadableStream._state;
- if (state !== 'readable') {
- throw new TypeError('The stream (in ' + state + ' state) is not in the readable state and cannot be enqueued to');
- }
- return ReadableStreamDefaultControllerEnqueue(this, chunk);
- }
- }, {
- key: 'error',
- value: function error(e) {
- if (IsReadableStreamDefaultController(this) === false) {
- throw defaultControllerBrandCheckException('error');
- }
- var stream = this._controlledReadableStream;
- if (stream._state !== 'readable') {
- throw new TypeError('The stream is ' + stream._state + ' and so cannot be errored');
- }
- ReadableStreamDefaultControllerError(this, e);
- }
- }, {
- key: '__cancelSteps',
- value: function __cancelSteps(reason) {
- ResetQueue(this);
- return PromiseInvokeOrNoop(this._underlyingSource, 'cancel', [reason]);
- }
- }, {
- key: '__pullSteps',
- value: function __pullSteps() {
- var stream = this._controlledReadableStream;
- if (this._queue.length > 0) {
- var chunk = DequeueValue(this);
- if (this._closeRequested === true && this._queue.length === 0) {
- ReadableStreamClose(stream);
- } else {
- ReadableStreamDefaultControllerCallPullIfNeeded(this);
- }
- return Promise.resolve(CreateIterResultObject(chunk, false));
- }
- var pendingPromise = ReadableStreamAddReadRequest(stream);
- ReadableStreamDefaultControllerCallPullIfNeeded(this);
- return pendingPromise;
- }
- }, {
- key: 'desiredSize',
- get: function get() {
- if (IsReadableStreamDefaultController(this) === false) {
- throw defaultControllerBrandCheckException('desiredSize');
- }
- return ReadableStreamDefaultControllerGetDesiredSize(this);
- }
- }]);
- return ReadableStreamDefaultController;
- }();
- function IsReadableStreamDefaultController(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_underlyingSource')) {
- return false;
- }
- return true;
- }
- function ReadableStreamDefaultControllerCallPullIfNeeded(controller) {
- var shouldPull = ReadableStreamDefaultControllerShouldCallPull(controller);
- if (shouldPull === false) {
- return undefined;
- }
- if (controller._pulling === true) {
- controller._pullAgain = true;
- return undefined;
- }
- assert(controller._pullAgain === false);
- controller._pulling = true;
- var pullPromise = PromiseInvokeOrNoop(controller._underlyingSource, 'pull', [controller]);
- pullPromise.then(function () {
- controller._pulling = false;
- if (controller._pullAgain === true) {
- controller._pullAgain = false;
- return ReadableStreamDefaultControllerCallPullIfNeeded(controller);
- }
- return undefined;
- }, function (e) {
- ReadableStreamDefaultControllerErrorIfNeeded(controller, e);
- }).catch(rethrowAssertionErrorRejection);
- return undefined;
- }
- function ReadableStreamDefaultControllerShouldCallPull(controller) {
- var stream = controller._controlledReadableStream;
- if (stream._state === 'closed' || stream._state === 'errored') {
- return false;
- }
- if (controller._closeRequested === true) {
- return false;
- }
- if (controller._started === false) {
- return false;
- }
- if (IsReadableStreamLocked(stream) === true && ReadableStreamGetNumReadRequests(stream) > 0) {
- return true;
- }
- var desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller);
- if (desiredSize > 0) {
- return true;
- }
- return false;
- }
- function ReadableStreamDefaultControllerClose(controller) {
- var stream = controller._controlledReadableStream;
- assert(controller._closeRequested === false);
- assert(stream._state === 'readable');
- controller._closeRequested = true;
- if (controller._queue.length === 0) {
- ReadableStreamClose(stream);
- }
- }
- function ReadableStreamDefaultControllerEnqueue(controller, chunk) {
- var stream = controller._controlledReadableStream;
- assert(controller._closeRequested === false);
- assert(stream._state === 'readable');
- if (IsReadableStreamLocked(stream) === true && ReadableStreamGetNumReadRequests(stream) > 0) {
- ReadableStreamFulfillReadRequest(stream, chunk, false);
- } else {
- var chunkSize = 1;
- if (controller._strategySize !== undefined) {
- var strategySize = controller._strategySize;
- try {
- chunkSize = strategySize(chunk);
- } catch (chunkSizeE) {
- ReadableStreamDefaultControllerErrorIfNeeded(controller, chunkSizeE);
- throw chunkSizeE;
- }
- }
- try {
- EnqueueValueWithSize(controller, chunk, chunkSize);
- } catch (enqueueE) {
- ReadableStreamDefaultControllerErrorIfNeeded(controller, enqueueE);
- throw enqueueE;
- }
- }
- ReadableStreamDefaultControllerCallPullIfNeeded(controller);
- return undefined;
- }
- function ReadableStreamDefaultControllerError(controller, e) {
- var stream = controller._controlledReadableStream;
- assert(stream._state === 'readable');
- ResetQueue(controller);
- ReadableStreamError(stream, e);
- }
- function ReadableStreamDefaultControllerErrorIfNeeded(controller, e) {
- if (controller._controlledReadableStream._state === 'readable') {
- ReadableStreamDefaultControllerError(controller, e);
- }
- }
- function ReadableStreamDefaultControllerGetDesiredSize(controller) {
- var stream = controller._controlledReadableStream;
- var state = stream._state;
- if (state === 'errored') {
- return null;
- }
- if (state === 'closed') {
- return 0;
- }
- return controller._strategyHWM - controller._queueTotalSize;
- }
- var ReadableStreamBYOBRequest = function () {
- function ReadableStreamBYOBRequest(controller, view) {
- _classCallCheck(this, ReadableStreamBYOBRequest);
- this._associatedReadableByteStreamController = controller;
- this._view = view;
- }
- _createClass(ReadableStreamBYOBRequest, [{
- key: 'respond',
- value: function respond(bytesWritten) {
- if (IsReadableStreamBYOBRequest(this) === false) {
- throw byobRequestBrandCheckException('respond');
- }
- if (this._associatedReadableByteStreamController === undefined) {
- throw new TypeError('This BYOB request has been invalidated');
- }
- ReadableByteStreamControllerRespond(this._associatedReadableByteStreamController, bytesWritten);
- }
- }, {
- key: 'respondWithNewView',
- value: function respondWithNewView(view) {
- if (IsReadableStreamBYOBRequest(this) === false) {
- throw byobRequestBrandCheckException('respond');
- }
- if (this._associatedReadableByteStreamController === undefined) {
- throw new TypeError('This BYOB request has been invalidated');
- }
- if (!ArrayBuffer.isView(view)) {
- throw new TypeError('You can only respond with array buffer views');
- }
- ReadableByteStreamControllerRespondWithNewView(this._associatedReadableByteStreamController, view);
- }
- }, {
- key: 'view',
- get: function get() {
- return this._view;
- }
- }]);
- return ReadableStreamBYOBRequest;
- }();
- var ReadableByteStreamController = function () {
- function ReadableByteStreamController(stream, underlyingByteSource, highWaterMark) {
- _classCallCheck(this, ReadableByteStreamController);
- if (IsReadableStream(stream) === false) {
- throw new TypeError('ReadableByteStreamController can only be constructed with a ReadableStream instance given ' + 'a byte source');
- }
- if (stream._readableStreamController !== undefined) {
- throw new TypeError('ReadableByteStreamController instances can only be created by the ReadableStream constructor given a byte ' + 'source');
- }
- this._controlledReadableStream = stream;
- this._underlyingByteSource = underlyingByteSource;
- this._pullAgain = false;
- this._pulling = false;
- ReadableByteStreamControllerClearPendingPullIntos(this);
- this._queue = this._queueTotalSize = undefined;
- ResetQueue(this);
- this._closeRequested = false;
- this._started = false;
- this._strategyHWM = ValidateAndNormalizeHighWaterMark(highWaterMark);
- var autoAllocateChunkSize = underlyingByteSource.autoAllocateChunkSize;
- if (autoAllocateChunkSize !== undefined) {
- if (Number.isInteger(autoAllocateChunkSize) === false || autoAllocateChunkSize <= 0) {
- throw new RangeError('autoAllocateChunkSize must be a positive integer');
- }
- }
- this._autoAllocateChunkSize = autoAllocateChunkSize;
- this._pendingPullIntos = [];
- var controller = this;
- var startResult = InvokeOrNoop(underlyingByteSource, 'start', [this]);
- Promise.resolve(startResult).then(function () {
- controller._started = true;
- assert(controller._pulling === false);
- assert(controller._pullAgain === false);
- ReadableByteStreamControllerCallPullIfNeeded(controller);
- }, function (r) {
- if (stream._state === 'readable') {
- ReadableByteStreamControllerError(controller, r);
- }
- }).catch(rethrowAssertionErrorRejection);
- }
- _createClass(ReadableByteStreamController, [{
- key: 'close',
- value: function close() {
- if (IsReadableByteStreamController(this) === false) {
- throw byteStreamControllerBrandCheckException('close');
- }
- if (this._closeRequested === true) {
- throw new TypeError('The stream has already been closed; do not close it again!');
- }
- var state = this._controlledReadableStream._state;
- if (state !== 'readable') {
- throw new TypeError('The stream (in ' + state + ' state) is not in the readable state and cannot be closed');
- }
- ReadableByteStreamControllerClose(this);
- }
- }, {
- key: 'enqueue',
- value: function enqueue(chunk) {
- if (IsReadableByteStreamController(this) === false) {
- throw byteStreamControllerBrandCheckException('enqueue');
- }
- if (this._closeRequested === true) {
- throw new TypeError('stream is closed or draining');
- }
- var state = this._controlledReadableStream._state;
- if (state !== 'readable') {
- throw new TypeError('The stream (in ' + state + ' state) is not in the readable state and cannot be enqueued to');
- }
- if (!ArrayBuffer.isView(chunk)) {
- throw new TypeError('You can only enqueue array buffer views when using a ReadableByteStreamController');
- }
- ReadableByteStreamControllerEnqueue(this, chunk);
- }
- }, {
- key: 'error',
- value: function error(e) {
- if (IsReadableByteStreamController(this) === false) {
- throw byteStreamControllerBrandCheckException('error');
- }
- var stream = this._controlledReadableStream;
- if (stream._state !== 'readable') {
- throw new TypeError('The stream is ' + stream._state + ' and so cannot be errored');
- }
- ReadableByteStreamControllerError(this, e);
- }
- }, {
- key: '__cancelSteps',
- value: function __cancelSteps(reason) {
- if (this._pendingPullIntos.length > 0) {
- var firstDescriptor = this._pendingPullIntos[0];
- firstDescriptor.bytesFilled = 0;
- }
- ResetQueue(this);
- return PromiseInvokeOrNoop(this._underlyingByteSource, 'cancel', [reason]);
- }
- }, {
- key: '__pullSteps',
- value: function __pullSteps() {
- var stream = this._controlledReadableStream;
- assert(ReadableStreamHasDefaultReader(stream) === true);
- if (this._queueTotalSize > 0) {
- assert(ReadableStreamGetNumReadRequests(stream) === 0);
- var entry = this._queue.shift();
- this._queueTotalSize -= entry.byteLength;
- ReadableByteStreamControllerHandleQueueDrain(this);
- var view = void 0;
- try {
- view = new Uint8Array(entry.buffer, entry.byteOffset, entry.byteLength);
- } catch (viewE) {
- return Promise.reject(viewE);
- }
- return Promise.resolve(CreateIterResultObject(view, false));
- }
- var autoAllocateChunkSize = this._autoAllocateChunkSize;
- if (autoAllocateChunkSize !== undefined) {
- var buffer = void 0;
- try {
- buffer = new ArrayBuffer(autoAllocateChunkSize);
- } catch (bufferE) {
- return Promise.reject(bufferE);
- }
- var pullIntoDescriptor = {
- buffer: buffer,
- byteOffset: 0,
- byteLength: autoAllocateChunkSize,
- bytesFilled: 0,
- elementSize: 1,
- ctor: Uint8Array,
- readerType: 'default'
- };
- this._pendingPullIntos.push(pullIntoDescriptor);
- }
- var promise = ReadableStreamAddReadRequest(stream);
- ReadableByteStreamControllerCallPullIfNeeded(this);
- return promise;
- }
- }, {
- key: 'byobRequest',
- get: function get() {
- if (IsReadableByteStreamController(this) === false) {
- throw byteStreamControllerBrandCheckException('byobRequest');
- }
- if (this._byobRequest === undefined && this._pendingPullIntos.length > 0) {
- var firstDescriptor = this._pendingPullIntos[0];
- var view = new Uint8Array(firstDescriptor.buffer, firstDescriptor.byteOffset + firstDescriptor.bytesFilled, firstDescriptor.byteLength - firstDescriptor.bytesFilled);
- this._byobRequest = new ReadableStreamBYOBRequest(this, view);
- }
- return this._byobRequest;
- }
- }, {
- key: 'desiredSize',
- get: function get() {
- if (IsReadableByteStreamController(this) === false) {
- throw byteStreamControllerBrandCheckException('desiredSize');
- }
- return ReadableByteStreamControllerGetDesiredSize(this);
- }
- }]);
- return ReadableByteStreamController;
- }();
- function IsReadableByteStreamController(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_underlyingByteSource')) {
- return false;
- }
- return true;
- }
- function IsReadableStreamBYOBRequest(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_associatedReadableByteStreamController')) {
- return false;
- }
- return true;
- }
- function ReadableByteStreamControllerCallPullIfNeeded(controller) {
- var shouldPull = ReadableByteStreamControllerShouldCallPull(controller);
- if (shouldPull === false) {
- return undefined;
- }
- if (controller._pulling === true) {
- controller._pullAgain = true;
- return undefined;
- }
- assert(controller._pullAgain === false);
- controller._pulling = true;
- var pullPromise = PromiseInvokeOrNoop(controller._underlyingByteSource, 'pull', [controller]);
- pullPromise.then(function () {
- controller._pulling = false;
- if (controller._pullAgain === true) {
- controller._pullAgain = false;
- ReadableByteStreamControllerCallPullIfNeeded(controller);
- }
- }, function (e) {
- if (controller._controlledReadableStream._state === 'readable') {
- ReadableByteStreamControllerError(controller, e);
- }
- }).catch(rethrowAssertionErrorRejection);
- return undefined;
- }
- function ReadableByteStreamControllerClearPendingPullIntos(controller) {
- ReadableByteStreamControllerInvalidateBYOBRequest(controller);
- controller._pendingPullIntos = [];
- }
- function ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor) {
- assert(stream._state !== 'errored', 'state must not be errored');
- var done = false;
- if (stream._state === 'closed') {
- assert(pullIntoDescriptor.bytesFilled === 0);
- done = true;
- }
- var filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor);
- if (pullIntoDescriptor.readerType === 'default') {
- ReadableStreamFulfillReadRequest(stream, filledView, done);
- } else {
- assert(pullIntoDescriptor.readerType === 'byob');
- ReadableStreamFulfillReadIntoRequest(stream, filledView, done);
- }
- }
- function ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor) {
- var bytesFilled = pullIntoDescriptor.bytesFilled;
- var elementSize = pullIntoDescriptor.elementSize;
- assert(bytesFilled <= pullIntoDescriptor.byteLength);
- assert(bytesFilled % elementSize === 0);
- return new pullIntoDescriptor.ctor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, bytesFilled / elementSize);
- }
- function ReadableByteStreamControllerEnqueueChunkToQueue(controller, buffer, byteOffset, byteLength) {
- controller._queue.push({
- buffer: buffer,
- byteOffset: byteOffset,
- byteLength: byteLength
- });
- controller._queueTotalSize += byteLength;
- }
- function ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) {
- var elementSize = pullIntoDescriptor.elementSize;
- var currentAlignedBytes = pullIntoDescriptor.bytesFilled - pullIntoDescriptor.bytesFilled % elementSize;
- var maxBytesToCopy = Math.min(controller._queueTotalSize, pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled);
- var maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy;
- var maxAlignedBytes = maxBytesFilled - maxBytesFilled % elementSize;
- var totalBytesToCopyRemaining = maxBytesToCopy;
- var ready = false;
- if (maxAlignedBytes > currentAlignedBytes) {
- totalBytesToCopyRemaining = maxAlignedBytes - pullIntoDescriptor.bytesFilled;
- ready = true;
- }
- var queue = controller._queue;
- while (totalBytesToCopyRemaining > 0) {
- var headOfQueue = queue[0];
- var bytesToCopy = Math.min(totalBytesToCopyRemaining, headOfQueue.byteLength);
- var destStart = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled;
- ArrayBufferCopy(pullIntoDescriptor.buffer, destStart, headOfQueue.buffer, headOfQueue.byteOffset, bytesToCopy);
- if (headOfQueue.byteLength === bytesToCopy) {
- queue.shift();
- } else {
- headOfQueue.byteOffset += bytesToCopy;
- headOfQueue.byteLength -= bytesToCopy;
- }
- controller._queueTotalSize -= bytesToCopy;
- ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesToCopy, pullIntoDescriptor);
- totalBytesToCopyRemaining -= bytesToCopy;
- }
- if (ready === false) {
- assert(controller._queueTotalSize === 0, 'queue must be empty');
- assert(pullIntoDescriptor.bytesFilled > 0);
- assert(pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize);
- }
- return ready;
- }
- function ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, size, pullIntoDescriptor) {
- assert(controller._pendingPullIntos.length === 0 || controller._pendingPullIntos[0] === pullIntoDescriptor);
- ReadableByteStreamControllerInvalidateBYOBRequest(controller);
- pullIntoDescriptor.bytesFilled += size;
- }
- function ReadableByteStreamControllerHandleQueueDrain(controller) {
- assert(controller._controlledReadableStream._state === 'readable');
- if (controller._queueTotalSize === 0 && controller._closeRequested === true) {
- ReadableStreamClose(controller._controlledReadableStream);
- } else {
- ReadableByteStreamControllerCallPullIfNeeded(controller);
- }
- }
- function ReadableByteStreamControllerInvalidateBYOBRequest(controller) {
- if (controller._byobRequest === undefined) {
- return;
- }
- controller._byobRequest._associatedReadableByteStreamController = undefined;
- controller._byobRequest._view = undefined;
- controller._byobRequest = undefined;
- }
- function ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller) {
- assert(controller._closeRequested === false);
- while (controller._pendingPullIntos.length > 0) {
- if (controller._queueTotalSize === 0) {
- return;
- }
- var pullIntoDescriptor = controller._pendingPullIntos[0];
- if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) === true) {
- ReadableByteStreamControllerShiftPendingPullInto(controller);
- ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableStream, pullIntoDescriptor);
- }
- }
- }
- function ReadableByteStreamControllerPullInto(controller, view) {
- var stream = controller._controlledReadableStream;
- var elementSize = 1;
- if (view.constructor !== DataView) {
- elementSize = view.constructor.BYTES_PER_ELEMENT;
- }
- var ctor = view.constructor;
- var pullIntoDescriptor = {
- buffer: view.buffer,
- byteOffset: view.byteOffset,
- byteLength: view.byteLength,
- bytesFilled: 0,
- elementSize: elementSize,
- ctor: ctor,
- readerType: 'byob'
- };
- if (controller._pendingPullIntos.length > 0) {
- pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer);
- controller._pendingPullIntos.push(pullIntoDescriptor);
- return ReadableStreamAddReadIntoRequest(stream);
- }
- if (stream._state === 'closed') {
- var emptyView = new view.constructor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, 0);
- return Promise.resolve(CreateIterResultObject(emptyView, true));
- }
- if (controller._queueTotalSize > 0) {
- if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) === true) {
- var filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor);
- ReadableByteStreamControllerHandleQueueDrain(controller);
- return Promise.resolve(CreateIterResultObject(filledView, false));
- }
- if (controller._closeRequested === true) {
- var e = new TypeError('Insufficient bytes to fill elements in the given buffer');
- ReadableByteStreamControllerError(controller, e);
- return Promise.reject(e);
- }
- }
- pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer);
- controller._pendingPullIntos.push(pullIntoDescriptor);
- var promise = ReadableStreamAddReadIntoRequest(stream);
- ReadableByteStreamControllerCallPullIfNeeded(controller);
- return promise;
- }
- function ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor) {
- firstDescriptor.buffer = TransferArrayBuffer(firstDescriptor.buffer);
- assert(firstDescriptor.bytesFilled === 0, 'bytesFilled must be 0');
- var stream = controller._controlledReadableStream;
- if (ReadableStreamHasBYOBReader(stream) === true) {
- while (ReadableStreamGetNumReadIntoRequests(stream) > 0) {
- var pullIntoDescriptor = ReadableByteStreamControllerShiftPendingPullInto(controller);
- ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor);
- }
- }
- }
- function ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, pullIntoDescriptor) {
- if (pullIntoDescriptor.bytesFilled + bytesWritten > pullIntoDescriptor.byteLength) {
- throw new RangeError('bytesWritten out of range');
- }
- ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesWritten, pullIntoDescriptor);
- if (pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize) {
- return;
- }
- ReadableByteStreamControllerShiftPendingPullInto(controller);
- var remainderSize = pullIntoDescriptor.bytesFilled % pullIntoDescriptor.elementSize;
- if (remainderSize > 0) {
- var end = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled;
- var remainder = pullIntoDescriptor.buffer.slice(end - remainderSize, end);
- ReadableByteStreamControllerEnqueueChunkToQueue(controller, remainder, 0, remainder.byteLength);
- }
- pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer);
- pullIntoDescriptor.bytesFilled -= remainderSize;
- ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableStream, pullIntoDescriptor);
- ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller);
- }
- function ReadableByteStreamControllerRespondInternal(controller, bytesWritten) {
- var firstDescriptor = controller._pendingPullIntos[0];
- var stream = controller._controlledReadableStream;
- if (stream._state === 'closed') {
- if (bytesWritten !== 0) {
- throw new TypeError('bytesWritten must be 0 when calling respond() on a closed stream');
- }
- ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor);
- } else {
- assert(stream._state === 'readable');
- ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, firstDescriptor);
- }
- }
- function ReadableByteStreamControllerShiftPendingPullInto(controller) {
- var descriptor = controller._pendingPullIntos.shift();
- ReadableByteStreamControllerInvalidateBYOBRequest(controller);
- return descriptor;
- }
- function ReadableByteStreamControllerShouldCallPull(controller) {
- var stream = controller._controlledReadableStream;
- if (stream._state !== 'readable') {
- return false;
- }
- if (controller._closeRequested === true) {
- return false;
- }
- if (controller._started === false) {
- return false;
- }
- if (ReadableStreamHasDefaultReader(stream) === true && ReadableStreamGetNumReadRequests(stream) > 0) {
- return true;
- }
- if (ReadableStreamHasBYOBReader(stream) === true && ReadableStreamGetNumReadIntoRequests(stream) > 0) {
- return true;
- }
- if (ReadableByteStreamControllerGetDesiredSize(controller) > 0) {
- return true;
- }
- return false;
- }
- function ReadableByteStreamControllerClose(controller) {
- var stream = controller._controlledReadableStream;
- assert(controller._closeRequested === false);
- assert(stream._state === 'readable');
- if (controller._queueTotalSize > 0) {
- controller._closeRequested = true;
- return;
- }
- if (controller._pendingPullIntos.length > 0) {
- var firstPendingPullInto = controller._pendingPullIntos[0];
- if (firstPendingPullInto.bytesFilled > 0) {
- var e = new TypeError('Insufficient bytes to fill elements in the given buffer');
- ReadableByteStreamControllerError(controller, e);
- throw e;
- }
- }
- ReadableStreamClose(stream);
- }
- function ReadableByteStreamControllerEnqueue(controller, chunk) {
- var stream = controller._controlledReadableStream;
- assert(controller._closeRequested === false);
- assert(stream._state === 'readable');
- var buffer = chunk.buffer;
- var byteOffset = chunk.byteOffset;
- var byteLength = chunk.byteLength;
- var transferredBuffer = TransferArrayBuffer(buffer);
- if (ReadableStreamHasDefaultReader(stream) === true) {
- if (ReadableStreamGetNumReadRequests(stream) === 0) {
- ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength);
- } else {
- assert(controller._queue.length === 0);
- var transferredView = new Uint8Array(transferredBuffer, byteOffset, byteLength);
- ReadableStreamFulfillReadRequest(stream, transferredView, false);
- }
- } else if (ReadableStreamHasBYOBReader(stream) === true) {
- ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength);
- ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller);
- } else {
- assert(IsReadableStreamLocked(stream) === false, 'stream must not be locked');
- ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength);
- }
- }
- function ReadableByteStreamControllerError(controller, e) {
- var stream = controller._controlledReadableStream;
- assert(stream._state === 'readable');
- ReadableByteStreamControllerClearPendingPullIntos(controller);
- ResetQueue(controller);
- ReadableStreamError(stream, e);
- }
- function ReadableByteStreamControllerGetDesiredSize(controller) {
- var stream = controller._controlledReadableStream;
- var state = stream._state;
- if (state === 'errored') {
- return null;
- }
- if (state === 'closed') {
- return 0;
- }
- return controller._strategyHWM - controller._queueTotalSize;
- }
- function ReadableByteStreamControllerRespond(controller, bytesWritten) {
- bytesWritten = Number(bytesWritten);
- if (IsFiniteNonNegativeNumber(bytesWritten) === false) {
- throw new RangeError('bytesWritten must be a finite');
- }
- assert(controller._pendingPullIntos.length > 0);
- ReadableByteStreamControllerRespondInternal(controller, bytesWritten);
- }
- function ReadableByteStreamControllerRespondWithNewView(controller, view) {
- assert(controller._pendingPullIntos.length > 0);
- var firstDescriptor = controller._pendingPullIntos[0];
- if (firstDescriptor.byteOffset + firstDescriptor.bytesFilled !== view.byteOffset) {
- throw new RangeError('The region specified by view does not match byobRequest');
- }
- if (firstDescriptor.byteLength !== view.byteLength) {
- throw new RangeError('The buffer of view has different capacity than byobRequest');
- }
- firstDescriptor.buffer = view.buffer;
- ReadableByteStreamControllerRespondInternal(controller, view.byteLength);
- }
- function streamBrandCheckException(name) {
- return new TypeError('ReadableStream.prototype.' + name + ' can only be used on a ReadableStream');
- }
- function readerLockException(name) {
- return new TypeError('Cannot ' + name + ' a stream using a released reader');
- }
- function defaultReaderBrandCheckException(name) {
- return new TypeError('ReadableStreamDefaultReader.prototype.' + name + ' can only be used on a ReadableStreamDefaultReader');
- }
- function defaultReaderClosedPromiseInitialize(reader) {
- reader._closedPromise = new Promise(function (resolve, reject) {
- reader._closedPromise_resolve = resolve;
- reader._closedPromise_reject = reject;
- });
- }
- function defaultReaderClosedPromiseInitializeAsRejected(reader, reason) {
- reader._closedPromise = Promise.reject(reason);
- reader._closedPromise_resolve = undefined;
- reader._closedPromise_reject = undefined;
- }
- function defaultReaderClosedPromiseInitializeAsResolved(reader) {
- reader._closedPromise = Promise.resolve(undefined);
- reader._closedPromise_resolve = undefined;
- reader._closedPromise_reject = undefined;
- }
- function defaultReaderClosedPromiseReject(reader, reason) {
- assert(reader._closedPromise_resolve !== undefined);
- assert(reader._closedPromise_reject !== undefined);
- reader._closedPromise_reject(reason);
- reader._closedPromise_resolve = undefined;
- reader._closedPromise_reject = undefined;
- }
- function defaultReaderClosedPromiseResetToRejected(reader, reason) {
- assert(reader._closedPromise_resolve === undefined);
- assert(reader._closedPromise_reject === undefined);
- reader._closedPromise = Promise.reject(reason);
- }
- function defaultReaderClosedPromiseResolve(reader) {
- assert(reader._closedPromise_resolve !== undefined);
- assert(reader._closedPromise_reject !== undefined);
- reader._closedPromise_resolve(undefined);
- reader._closedPromise_resolve = undefined;
- reader._closedPromise_reject = undefined;
- }
- function byobReaderBrandCheckException(name) {
- return new TypeError('ReadableStreamBYOBReader.prototype.' + name + ' can only be used on a ReadableStreamBYOBReader');
- }
- function defaultControllerBrandCheckException(name) {
- return new TypeError('ReadableStreamDefaultController.prototype.' + name + ' can only be used on a ReadableStreamDefaultController');
- }
- function byobRequestBrandCheckException(name) {
- return new TypeError('ReadableStreamBYOBRequest.prototype.' + name + ' can only be used on a ReadableStreamBYOBRequest');
- }
- function byteStreamControllerBrandCheckException(name) {
- return new TypeError('ReadableByteStreamController.prototype.' + name + ' can only be used on a ReadableByteStreamController');
- }
- function ifIsObjectAndHasAPromiseIsHandledInternalSlotSetPromiseIsHandledToTrue(promise) {
- try {
- Promise.prototype.then.call(promise, undefined, function () {});
- } catch (e) {}
- }
-}, function (module, exports, __w_pdfjs_require__) {
- "use strict";
-
- var transformStream = __w_pdfjs_require__(6);
- var readableStream = __w_pdfjs_require__(4);
- var writableStream = __w_pdfjs_require__(2);
- exports.TransformStream = transformStream.TransformStream;
- exports.ReadableStream = readableStream.ReadableStream;
- exports.IsReadableStreamDisturbed = readableStream.IsReadableStreamDisturbed;
- exports.ReadableStreamDefaultControllerClose = readableStream.ReadableStreamDefaultControllerClose;
- exports.ReadableStreamDefaultControllerEnqueue = readableStream.ReadableStreamDefaultControllerEnqueue;
- exports.ReadableStreamDefaultControllerError = readableStream.ReadableStreamDefaultControllerError;
- exports.ReadableStreamDefaultControllerGetDesiredSize = readableStream.ReadableStreamDefaultControllerGetDesiredSize;
- exports.AcquireWritableStreamDefaultWriter = writableStream.AcquireWritableStreamDefaultWriter;
- exports.IsWritableStream = writableStream.IsWritableStream;
- exports.IsWritableStreamLocked = writableStream.IsWritableStreamLocked;
- exports.WritableStream = writableStream.WritableStream;
- exports.WritableStreamAbort = writableStream.WritableStreamAbort;
- exports.WritableStreamDefaultControllerError = writableStream.WritableStreamDefaultControllerError;
- exports.WritableStreamDefaultWriterCloseWithErrorPropagation = writableStream.WritableStreamDefaultWriterCloseWithErrorPropagation;
- exports.WritableStreamDefaultWriterRelease = writableStream.WritableStreamDefaultWriterRelease;
- exports.WritableStreamDefaultWriterWrite = writableStream.WritableStreamDefaultWriterWrite;
-}, function (module, exports, __w_pdfjs_require__) {
- "use strict";
-
- var _createClass = function () {
- function defineProperties(target, props) {
- for (var i = 0; i < props.length; i++) {
- var descriptor = props[i];
- descriptor.enumerable = descriptor.enumerable || false;
- descriptor.configurable = true;
- if ("value" in descriptor) descriptor.writable = true;
- Object.defineProperty(target, descriptor.key, descriptor);
- }
- }
- return function (Constructor, protoProps, staticProps) {
- if (protoProps) defineProperties(Constructor.prototype, protoProps);
- if (staticProps) defineProperties(Constructor, staticProps);
- return Constructor;
- };
- }();
- function _classCallCheck(instance, Constructor) {
- if (!(instance instanceof Constructor)) {
- throw new TypeError("Cannot call a class as a function");
- }
- }
- var _require = __w_pdfjs_require__(1),
- assert = _require.assert;
- var _require2 = __w_pdfjs_require__(0),
- InvokeOrNoop = _require2.InvokeOrNoop,
- PromiseInvokeOrPerformFallback = _require2.PromiseInvokeOrPerformFallback,
- PromiseInvokeOrNoop = _require2.PromiseInvokeOrNoop,
- typeIsObject = _require2.typeIsObject;
- var _require3 = __w_pdfjs_require__(4),
- ReadableStream = _require3.ReadableStream,
- ReadableStreamDefaultControllerClose = _require3.ReadableStreamDefaultControllerClose,
- ReadableStreamDefaultControllerEnqueue = _require3.ReadableStreamDefaultControllerEnqueue,
- ReadableStreamDefaultControllerError = _require3.ReadableStreamDefaultControllerError,
- ReadableStreamDefaultControllerGetDesiredSize = _require3.ReadableStreamDefaultControllerGetDesiredSize;
- var _require4 = __w_pdfjs_require__(2),
- WritableStream = _require4.WritableStream,
- WritableStreamDefaultControllerError = _require4.WritableStreamDefaultControllerError;
- function TransformStreamCloseReadable(transformStream) {
- if (transformStream._errored === true) {
- throw new TypeError('TransformStream is already errored');
- }
- if (transformStream._readableClosed === true) {
- throw new TypeError('Readable side is already closed');
- }
- TransformStreamCloseReadableInternal(transformStream);
- }
- function TransformStreamEnqueueToReadable(transformStream, chunk) {
- if (transformStream._errored === true) {
- throw new TypeError('TransformStream is already errored');
- }
- if (transformStream._readableClosed === true) {
- throw new TypeError('Readable side is already closed');
- }
- var controller = transformStream._readableController;
- try {
- ReadableStreamDefaultControllerEnqueue(controller, chunk);
- } catch (e) {
- transformStream._readableClosed = true;
- TransformStreamErrorIfNeeded(transformStream, e);
- throw transformStream._storedError;
- }
- var desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller);
- var maybeBackpressure = desiredSize <= 0;
- if (maybeBackpressure === true && transformStream._backpressure === false) {
- TransformStreamSetBackpressure(transformStream, true);
- }
- }
- function TransformStreamError(transformStream, e) {
- if (transformStream._errored === true) {
- throw new TypeError('TransformStream is already errored');
- }
- TransformStreamErrorInternal(transformStream, e);
- }
- function TransformStreamCloseReadableInternal(transformStream) {
- assert(transformStream._errored === false);
- assert(transformStream._readableClosed === false);
- try {
- ReadableStreamDefaultControllerClose(transformStream._readableController);
- } catch (e) {
- assert(false);
- }
- transformStream._readableClosed = true;
- }
- function TransformStreamErrorIfNeeded(transformStream, e) {
- if (transformStream._errored === false) {
- TransformStreamErrorInternal(transformStream, e);
- }
- }
- function TransformStreamErrorInternal(transformStream, e) {
- assert(transformStream._errored === false);
- transformStream._errored = true;
- transformStream._storedError = e;
- if (transformStream._writableDone === false) {
- WritableStreamDefaultControllerError(transformStream._writableController, e);
- }
- if (transformStream._readableClosed === false) {
- ReadableStreamDefaultControllerError(transformStream._readableController, e);
- }
- }
- function TransformStreamReadableReadyPromise(transformStream) {
- assert(transformStream._backpressureChangePromise !== undefined, '_backpressureChangePromise should have been initialized');
- if (transformStream._backpressure === false) {
- return Promise.resolve();
- }
- assert(transformStream._backpressure === true, '_backpressure should have been initialized');
- return transformStream._backpressureChangePromise;
- }
- function TransformStreamSetBackpressure(transformStream, backpressure) {
- assert(transformStream._backpressure !== backpressure, 'TransformStreamSetBackpressure() should be called only when backpressure is changed');
- if (transformStream._backpressureChangePromise !== undefined) {
- transformStream._backpressureChangePromise_resolve(backpressure);
- }
- transformStream._backpressureChangePromise = new Promise(function (resolve) {
- transformStream._backpressureChangePromise_resolve = resolve;
- });
- transformStream._backpressureChangePromise.then(function (resolution) {
- assert(resolution !== backpressure, '_backpressureChangePromise should be fulfilled only when backpressure is changed');
- });
- transformStream._backpressure = backpressure;
- }
- function TransformStreamDefaultTransform(chunk, transformStreamController) {
- var transformStream = transformStreamController._controlledTransformStream;
- TransformStreamEnqueueToReadable(transformStream, chunk);
- return Promise.resolve();
- }
- function TransformStreamTransform(transformStream, chunk) {
- assert(transformStream._errored === false);
- assert(transformStream._transforming === false);
- assert(transformStream._backpressure === false);
- transformStream._transforming = true;
- var transformer = transformStream._transformer;
- var controller = transformStream._transformStreamController;
- var transformPromise = PromiseInvokeOrPerformFallback(transformer, 'transform', [chunk, controller], TransformStreamDefaultTransform, [chunk, controller]);
- return transformPromise.then(function () {
- transformStream._transforming = false;
- return TransformStreamReadableReadyPromise(transformStream);
- }, function (e) {
- TransformStreamErrorIfNeeded(transformStream, e);
- return Promise.reject(e);
- });
- }
- function IsTransformStreamDefaultController(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_controlledTransformStream')) {
- return false;
- }
- return true;
- }
- function IsTransformStream(x) {
- if (!typeIsObject(x)) {
- return false;
- }
- if (!Object.prototype.hasOwnProperty.call(x, '_transformStreamController')) {
- return false;
- }
- return true;
- }
- var TransformStreamSink = function () {
- function TransformStreamSink(transformStream, startPromise) {
- _classCallCheck(this, TransformStreamSink);
- this._transformStream = transformStream;
- this._startPromise = startPromise;
- }
- _createClass(TransformStreamSink, [{
- key: 'start',
- value: function start(c) {
- var transformStream = this._transformStream;
- transformStream._writableController = c;
- return this._startPromise.then(function () {
- return TransformStreamReadableReadyPromise(transformStream);
- });
- }
- }, {
- key: 'write',
- value: function write(chunk) {
- var transformStream = this._transformStream;
- return TransformStreamTransform(transformStream, chunk);
- }
- }, {
- key: 'abort',
- value: function abort() {
- var transformStream = this._transformStream;
- transformStream._writableDone = true;
- TransformStreamErrorInternal(transformStream, new TypeError('Writable side aborted'));
- }
- }, {
- key: 'close',
- value: function close() {
- var transformStream = this._transformStream;
- assert(transformStream._transforming === false);
- transformStream._writableDone = true;
- var flushPromise = PromiseInvokeOrNoop(transformStream._transformer, 'flush', [transformStream._transformStreamController]);
- return flushPromise.then(function () {
- if (transformStream._errored === true) {
- return Promise.reject(transformStream._storedError);
- }
- if (transformStream._readableClosed === false) {
- TransformStreamCloseReadableInternal(transformStream);
- }
- return Promise.resolve();
- }).catch(function (r) {
- TransformStreamErrorIfNeeded(transformStream, r);
- return Promise.reject(transformStream._storedError);
- });
- }
- }]);
- return TransformStreamSink;
- }();
- var TransformStreamSource = function () {
- function TransformStreamSource(transformStream, startPromise) {
- _classCallCheck(this, TransformStreamSource);
- this._transformStream = transformStream;
- this._startPromise = startPromise;
- }
- _createClass(TransformStreamSource, [{
- key: 'start',
- value: function start(c) {
- var transformStream = this._transformStream;
- transformStream._readableController = c;
- return this._startPromise.then(function () {
- assert(transformStream._backpressureChangePromise !== undefined, '_backpressureChangePromise should have been initialized');
- if (transformStream._backpressure === true) {
- return Promise.resolve();
- }
- assert(transformStream._backpressure === false, '_backpressure should have been initialized');
- return transformStream._backpressureChangePromise;
- });
- }
- }, {
- key: 'pull',
- value: function pull() {
- var transformStream = this._transformStream;
- assert(transformStream._backpressure === true, 'pull() should be never called while _backpressure is false');
- assert(transformStream._backpressureChangePromise !== undefined, '_backpressureChangePromise should have been initialized');
- TransformStreamSetBackpressure(transformStream, false);
- return transformStream._backpressureChangePromise;
- }
- }, {
- key: 'cancel',
- value: function cancel() {
- var transformStream = this._transformStream;
- transformStream._readableClosed = true;
- TransformStreamErrorInternal(transformStream, new TypeError('Readable side canceled'));
- }
- }]);
- return TransformStreamSource;
- }();
- var TransformStreamDefaultController = function () {
- function TransformStreamDefaultController(transformStream) {
- _classCallCheck(this, TransformStreamDefaultController);
- if (IsTransformStream(transformStream) === false) {
- throw new TypeError('TransformStreamDefaultController can only be ' + 'constructed with a TransformStream instance');
- }
- if (transformStream._transformStreamController !== undefined) {
- throw new TypeError('TransformStreamDefaultController instances can ' + 'only be created by the TransformStream constructor');
- }
- this._controlledTransformStream = transformStream;
- }
- _createClass(TransformStreamDefaultController, [{
- key: 'enqueue',
- value: function enqueue(chunk) {
- if (IsTransformStreamDefaultController(this) === false) {
- throw defaultControllerBrandCheckException('enqueue');
- }
- TransformStreamEnqueueToReadable(this._controlledTransformStream, chunk);
- }
- }, {
- key: 'close',
- value: function close() {
- if (IsTransformStreamDefaultController(this) === false) {
- throw defaultControllerBrandCheckException('close');
- }
- TransformStreamCloseReadable(this._controlledTransformStream);
- }
- }, {
- key: 'error',
- value: function error(reason) {
- if (IsTransformStreamDefaultController(this) === false) {
- throw defaultControllerBrandCheckException('error');
- }
- TransformStreamError(this._controlledTransformStream, reason);
- }
- }, {
- key: 'desiredSize',
- get: function get() {
- if (IsTransformStreamDefaultController(this) === false) {
- throw defaultControllerBrandCheckException('desiredSize');
- }
- var transformStream = this._controlledTransformStream;
- var readableController = transformStream._readableController;
- return ReadableStreamDefaultControllerGetDesiredSize(readableController);
- }
- }]);
- return TransformStreamDefaultController;
- }();
- var TransformStream = function () {
- function TransformStream() {
- var transformer = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- _classCallCheck(this, TransformStream);
- this._transformer = transformer;
- var readableStrategy = transformer.readableStrategy,
- writableStrategy = transformer.writableStrategy;
- this._transforming = false;
- this._errored = false;
- this._storedError = undefined;
- this._writableController = undefined;
- this._readableController = undefined;
- this._transformStreamController = undefined;
- this._writableDone = false;
- this._readableClosed = false;
- this._backpressure = undefined;
- this._backpressureChangePromise = undefined;
- this._backpressureChangePromise_resolve = undefined;
- this._transformStreamController = new TransformStreamDefaultController(this);
- var startPromise_resolve = void 0;
- var startPromise = new Promise(function (resolve) {
- startPromise_resolve = resolve;
- });
- var source = new TransformStreamSource(this, startPromise);
- this._readable = new ReadableStream(source, readableStrategy);
- var sink = new TransformStreamSink(this, startPromise);
- this._writable = new WritableStream(sink, writableStrategy);
- assert(this._writableController !== undefined);
- assert(this._readableController !== undefined);
- var desiredSize = ReadableStreamDefaultControllerGetDesiredSize(this._readableController);
- TransformStreamSetBackpressure(this, desiredSize <= 0);
- var transformStream = this;
- var startResult = InvokeOrNoop(transformer, 'start', [transformStream._transformStreamController]);
- startPromise_resolve(startResult);
- startPromise.catch(function (e) {
- if (transformStream._errored === false) {
- transformStream._errored = true;
- transformStream._storedError = e;
- }
- });
- }
- _createClass(TransformStream, [{
- key: 'readable',
- get: function get() {
- if (IsTransformStream(this) === false) {
- throw streamBrandCheckException('readable');
- }
- return this._readable;
- }
- }, {
- key: 'writable',
- get: function get() {
- if (IsTransformStream(this) === false) {
- throw streamBrandCheckException('writable');
- }
- return this._writable;
- }
- }]);
- return TransformStream;
- }();
- module.exports = { TransformStream: TransformStream };
- function defaultControllerBrandCheckException(name) {
- return new TypeError('TransformStreamDefaultController.prototype.' + name + ' can only be used on a TransformStreamDefaultController');
- }
- function streamBrandCheckException(name) {
- return new TypeError('TransformStream.prototype.' + name + ' can only be used on a TransformStream');
- }
-}, function (module, exports, __w_pdfjs_require__) {
- module.exports = __w_pdfjs_require__(5);
-}]));
-
-/***/ }),
-/* 128 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-{
- var isURLSupported = false;
- try {
- if (typeof URL === 'function' && _typeof(URL.prototype) === 'object' && 'origin' in URL.prototype) {
- var u = new URL('b', 'http://a');
- u.pathname = 'c%20d';
- isURLSupported = u.href === 'http://a/c%20d';
- }
- } catch (ex) {}
- if (isURLSupported) {
- exports.URL = URL;
- } else {
- var PolyfillURL = __w_pdfjs_require__(129).URL;
- var OriginalURL = __w_pdfjs_require__(4).URL;
- if (OriginalURL) {
- PolyfillURL.createObjectURL = function (blob) {
- return OriginalURL.createObjectURL.apply(OriginalURL, arguments);
- };
- PolyfillURL.revokeObjectURL = function (url) {
- OriginalURL.revokeObjectURL(url);
- };
- }
- exports.URL = PolyfillURL;
- }
-}
-
-/***/ }),
-/* 129 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-(function URLConstructorClosure() {
- 'use strict';
-
- var relative = Object.create(null);
- relative['ftp'] = 21;
- relative['file'] = 0;
- relative['gopher'] = 70;
- relative['http'] = 80;
- relative['https'] = 443;
- relative['ws'] = 80;
- relative['wss'] = 443;
- var relativePathDotMapping = Object.create(null);
- relativePathDotMapping['%2e'] = '.';
- relativePathDotMapping['.%2e'] = '..';
- relativePathDotMapping['%2e.'] = '..';
- relativePathDotMapping['%2e%2e'] = '..';
- function isRelativeScheme(scheme) {
- return relative[scheme] !== undefined;
- }
- function invalid() {
- clear.call(this);
- this._isInvalid = true;
- }
- function IDNAToASCII(h) {
- if (h === '') {
- invalid.call(this);
- }
- return h.toLowerCase();
- }
- function percentEscape(c) {
- var unicode = c.charCodeAt(0);
- if (unicode > 0x20 && unicode < 0x7F && [0x22, 0x23, 0x3C, 0x3E, 0x3F, 0x60].indexOf(unicode) === -1) {
- return c;
- }
- return encodeURIComponent(c);
- }
- function percentEscapeQuery(c) {
- var unicode = c.charCodeAt(0);
- if (unicode > 0x20 && unicode < 0x7F && [0x22, 0x23, 0x3C, 0x3E, 0x60].indexOf(unicode) === -1) {
- return c;
- }
- return encodeURIComponent(c);
- }
- var EOF,
- ALPHA = /[a-zA-Z]/,
- ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
- function parse(input, stateOverride, base) {
- function err(message) {
- errors.push(message);
- }
- var state = stateOverride || 'scheme start',
- cursor = 0,
- buffer = '',
- seenAt = false,
- seenBracket = false,
- errors = [];
- loop: while ((input[cursor - 1] !== EOF || cursor === 0) && !this._isInvalid) {
- var c = input[cursor];
- switch (state) {
- case 'scheme start':
- if (c && ALPHA.test(c)) {
- buffer += c.toLowerCase();
- state = 'scheme';
- } else if (!stateOverride) {
- buffer = '';
- state = 'no scheme';
- continue;
- } else {
- err('Invalid scheme.');
- break loop;
- }
- break;
- case 'scheme':
- if (c && ALPHANUMERIC.test(c)) {
- buffer += c.toLowerCase();
- } else if (c === ':') {
- this._scheme = buffer;
- buffer = '';
- if (stateOverride) {
- break loop;
- }
- if (isRelativeScheme(this._scheme)) {
- this._isRelative = true;
- }
- if (this._scheme === 'file') {
- state = 'relative';
- } else if (this._isRelative && base && base._scheme === this._scheme) {
- state = 'relative or authority';
- } else if (this._isRelative) {
- state = 'authority first slash';
- } else {
- state = 'scheme data';
- }
- } else if (!stateOverride) {
- buffer = '';
- cursor = 0;
- state = 'no scheme';
- continue;
- } else if (c === EOF) {
- break loop;
- } else {
- err('Code point not allowed in scheme: ' + c);
- break loop;
- }
- break;
- case 'scheme data':
- if (c === '?') {
- this._query = '?';
- state = 'query';
- } else if (c === '#') {
- this._fragment = '#';
- state = 'fragment';
- } else {
- if (c !== EOF && c !== '\t' && c !== '\n' && c !== '\r') {
- this._schemeData += percentEscape(c);
- }
- }
- break;
- case 'no scheme':
- if (!base || !isRelativeScheme(base._scheme)) {
- err('Missing scheme.');
- invalid.call(this);
- } else {
- state = 'relative';
- continue;
- }
- break;
- case 'relative or authority':
- if (c === '/' && input[cursor + 1] === '/') {
- state = 'authority ignore slashes';
- } else {
- err('Expected /, got: ' + c);
- state = 'relative';
- continue;
- }
- break;
- case 'relative':
- this._isRelative = true;
- if (this._scheme !== 'file') {
- this._scheme = base._scheme;
- }
- if (c === EOF) {
- this._host = base._host;
- this._port = base._port;
- this._path = base._path.slice();
- this._query = base._query;
- this._username = base._username;
- this._password = base._password;
- break loop;
- } else if (c === '/' || c === '\\') {
- if (c === '\\') {
- err('\\ is an invalid code point.');
- }
- state = 'relative slash';
- } else if (c === '?') {
- this._host = base._host;
- this._port = base._port;
- this._path = base._path.slice();
- this._query = '?';
- this._username = base._username;
- this._password = base._password;
- state = 'query';
- } else if (c === '#') {
- this._host = base._host;
- this._port = base._port;
- this._path = base._path.slice();
- this._query = base._query;
- this._fragment = '#';
- this._username = base._username;
- this._password = base._password;
- state = 'fragment';
- } else {
- var nextC = input[cursor + 1];
- var nextNextC = input[cursor + 2];
- if (this._scheme !== 'file' || !ALPHA.test(c) || nextC !== ':' && nextC !== '|' || nextNextC !== EOF && nextNextC !== '/' && nextNextC !== '\\' && nextNextC !== '?' && nextNextC !== '#') {
- this._host = base._host;
- this._port = base._port;
- this._username = base._username;
- this._password = base._password;
- this._path = base._path.slice();
- this._path.pop();
- }
- state = 'relative path';
- continue;
- }
- break;
- case 'relative slash':
- if (c === '/' || c === '\\') {
- if (c === '\\') {
- err('\\ is an invalid code point.');
- }
- if (this._scheme === 'file') {
- state = 'file host';
- } else {
- state = 'authority ignore slashes';
- }
- } else {
- if (this._scheme !== 'file') {
- this._host = base._host;
- this._port = base._port;
- this._username = base._username;
- this._password = base._password;
- }
- state = 'relative path';
- continue;
- }
- break;
- case 'authority first slash':
- if (c === '/') {
- state = 'authority second slash';
- } else {
- err('Expected \'/\', got: ' + c);
- state = 'authority ignore slashes';
- continue;
- }
- break;
- case 'authority second slash':
- state = 'authority ignore slashes';
- if (c !== '/') {
- err('Expected \'/\', got: ' + c);
- continue;
- }
- break;
- case 'authority ignore slashes':
- if (c !== '/' && c !== '\\') {
- state = 'authority';
- continue;
- } else {
- err('Expected authority, got: ' + c);
- }
- break;
- case 'authority':
- if (c === '@') {
- if (seenAt) {
- err('@ already seen.');
- buffer += '%40';
- }
- seenAt = true;
- for (var i = 0; i < buffer.length; i++) {
- var cp = buffer[i];
- if (cp === '\t' || cp === '\n' || cp === '\r') {
- err('Invalid whitespace in authority.');
- continue;
- }
- if (cp === ':' && this._password === null) {
- this._password = '';
- continue;
- }
- var tempC = percentEscape(cp);
- if (this._password !== null) {
- this._password += tempC;
- } else {
- this._username += tempC;
- }
- }
- buffer = '';
- } else if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#') {
- cursor -= buffer.length;
- buffer = '';
- state = 'host';
- continue;
- } else {
- buffer += c;
- }
- break;
- case 'file host':
- if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#') {
- if (buffer.length === 2 && ALPHA.test(buffer[0]) && (buffer[1] === ':' || buffer[1] === '|')) {
- state = 'relative path';
- } else if (buffer.length === 0) {
- state = 'relative path start';
- } else {
- this._host = IDNAToASCII.call(this, buffer);
- buffer = '';
- state = 'relative path start';
- }
- continue;
- } else if (c === '\t' || c === '\n' || c === '\r') {
- err('Invalid whitespace in file host.');
- } else {
- buffer += c;
- }
- break;
- case 'host':
- case 'hostname':
- if (c === ':' && !seenBracket) {
- this._host = IDNAToASCII.call(this, buffer);
- buffer = '';
- state = 'port';
- if (stateOverride === 'hostname') {
- break loop;
- }
- } else if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#') {
- this._host = IDNAToASCII.call(this, buffer);
- buffer = '';
- state = 'relative path start';
- if (stateOverride) {
- break loop;
- }
- continue;
- } else if (c !== '\t' && c !== '\n' && c !== '\r') {
- if (c === '[') {
- seenBracket = true;
- } else if (c === ']') {
- seenBracket = false;
- }
- buffer += c;
- } else {
- err('Invalid code point in host/hostname: ' + c);
- }
- break;
- case 'port':
- if (/[0-9]/.test(c)) {
- buffer += c;
- } else if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#' || stateOverride) {
- if (buffer !== '') {
- var temp = parseInt(buffer, 10);
- if (temp !== relative[this._scheme]) {
- this._port = temp + '';
- }
- buffer = '';
- }
- if (stateOverride) {
- break loop;
- }
- state = 'relative path start';
- continue;
- } else if (c === '\t' || c === '\n' || c === '\r') {
- err('Invalid code point in port: ' + c);
- } else {
- invalid.call(this);
- }
- break;
- case 'relative path start':
- if (c === '\\') {
- err('\'\\\' not allowed in path.');
- }
- state = 'relative path';
- if (c !== '/' && c !== '\\') {
- continue;
- }
- break;
- case 'relative path':
- if (c === EOF || c === '/' || c === '\\' || !stateOverride && (c === '?' || c === '#')) {
- if (c === '\\') {
- err('\\ not allowed in relative path.');
- }
- var tmp;
- if (tmp = relativePathDotMapping[buffer.toLowerCase()]) {
- buffer = tmp;
- }
- if (buffer === '..') {
- this._path.pop();
- if (c !== '/' && c !== '\\') {
- this._path.push('');
- }
- } else if (buffer === '.' && c !== '/' && c !== '\\') {
- this._path.push('');
- } else if (buffer !== '.') {
- if (this._scheme === 'file' && this._path.length === 0 && buffer.length === 2 && ALPHA.test(buffer[0]) && buffer[1] === '|') {
- buffer = buffer[0] + ':';
- }
- this._path.push(buffer);
- }
- buffer = '';
- if (c === '?') {
- this._query = '?';
- state = 'query';
- } else if (c === '#') {
- this._fragment = '#';
- state = 'fragment';
- }
- } else if (c !== '\t' && c !== '\n' && c !== '\r') {
- buffer += percentEscape(c);
- }
- break;
- case 'query':
- if (!stateOverride && c === '#') {
- this._fragment = '#';
- state = 'fragment';
- } else if (c !== EOF && c !== '\t' && c !== '\n' && c !== '\r') {
- this._query += percentEscapeQuery(c);
- }
- break;
- case 'fragment':
- if (c !== EOF && c !== '\t' && c !== '\n' && c !== '\r') {
- this._fragment += c;
- }
- break;
- }
- cursor++;
- }
- }
- function clear() {
- this._scheme = '';
- this._schemeData = '';
- this._username = '';
- this._password = null;
- this._host = '';
- this._port = '';
- this._path = [];
- this._query = '';
- this._fragment = '';
- this._isInvalid = false;
- this._isRelative = false;
- }
- function JURL(url, base) {
- if (base !== undefined && !(base instanceof JURL)) {
- base = new JURL(String(base));
- }
- this._url = url;
- clear.call(this);
- var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, '');
- parse.call(this, input, null, base);
- }
- JURL.prototype = {
- toString: function toString() {
- return this.href;
- },
-
- get href() {
- if (this._isInvalid) {
- return this._url;
- }
- var authority = '';
- if (this._username !== '' || this._password !== null) {
- authority = this._username + (this._password !== null ? ':' + this._password : '') + '@';
- }
- return this.protocol + (this._isRelative ? '//' + authority + this.host : '') + this.pathname + this._query + this._fragment;
- },
- set href(value) {
- clear.call(this);
- parse.call(this, value);
- },
- get protocol() {
- return this._scheme + ':';
- },
- set protocol(value) {
- if (this._isInvalid) {
- return;
- }
- parse.call(this, value + ':', 'scheme start');
- },
- get host() {
- return this._isInvalid ? '' : this._port ? this._host + ':' + this._port : this._host;
- },
- set host(value) {
- if (this._isInvalid || !this._isRelative) {
- return;
- }
- parse.call(this, value, 'host');
- },
- get hostname() {
- return this._host;
- },
- set hostname(value) {
- if (this._isInvalid || !this._isRelative) {
- return;
- }
- parse.call(this, value, 'hostname');
- },
- get port() {
- return this._port;
- },
- set port(value) {
- if (this._isInvalid || !this._isRelative) {
- return;
- }
- parse.call(this, value, 'port');
- },
- get pathname() {
- return this._isInvalid ? '' : this._isRelative ? '/' + this._path.join('/') : this._schemeData;
- },
- set pathname(value) {
- if (this._isInvalid || !this._isRelative) {
- return;
- }
- this._path = [];
- parse.call(this, value, 'relative path start');
- },
- get search() {
- return this._isInvalid || !this._query || this._query === '?' ? '' : this._query;
- },
- set search(value) {
- if (this._isInvalid || !this._isRelative) {
- return;
- }
- this._query = '?';
- if (value[0] === '?') {
- value = value.slice(1);
- }
- parse.call(this, value, 'query');
- },
- get hash() {
- return this._isInvalid || !this._fragment || this._fragment === '#' ? '' : this._fragment;
- },
- set hash(value) {
- if (this._isInvalid) {
- return;
- }
- this._fragment = '#';
- if (value[0] === '#') {
- value = value.slice(1);
- }
- parse.call(this, value, 'fragment');
- },
- get origin() {
- var host;
- if (this._isInvalid || !this._scheme) {
- return '';
- }
- switch (this._scheme) {
- case 'data':
- case 'file':
- case 'javascript':
- case 'mailto':
- return 'null';
- case 'blob':
- try {
- return new JURL(this._schemeData).origin || 'null';
- } catch (_) {}
- return 'null';
- }
- host = this.host;
- if (!host) {
- return '';
- }
- return this._scheme + '://' + host;
- }
- };
- exports.URL = JURL;
-})();
-
-/***/ }),
-/* 130 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.NetworkPdfManager = exports.LocalPdfManager = undefined;
-
-var _regenerator = __w_pdfjs_require__(131);
-
-var _regenerator2 = _interopRequireDefault(_regenerator);
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-var _util = __w_pdfjs_require__(2);
-
-var _chunked_stream = __w_pdfjs_require__(135);
-
-var _document = __w_pdfjs_require__(136);
-
-var _stream = __w_pdfjs_require__(140);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
-
-function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
-
-function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-var BasePdfManager = function () {
- function BasePdfManager() {
- _classCallCheck(this, BasePdfManager);
-
- if (this.constructor === BasePdfManager) {
- (0, _util.unreachable)('Cannot initialize BasePdfManager.');
- }
- }
-
- _createClass(BasePdfManager, [{
- key: 'onLoadedStream',
- value: function onLoadedStream() {
- (0, _util.unreachable)('Abstract method `onLoadedStream` called');
- }
- }, {
- key: 'ensureDoc',
- value: function ensureDoc(prop, args) {
- return this.ensure(this.pdfDocument, prop, args);
- }
- }, {
- key: 'ensureXRef',
- value: function ensureXRef(prop, args) {
- return this.ensure(this.pdfDocument.xref, prop, args);
- }
- }, {
- key: 'ensureCatalog',
- value: function ensureCatalog(prop, args) {
- return this.ensure(this.pdfDocument.catalog, prop, args);
- }
- }, {
- key: 'getPage',
- value: function getPage(pageIndex) {
- return this.pdfDocument.getPage(pageIndex);
- }
- }, {
- key: 'cleanup',
- value: function cleanup() {
- return this.pdfDocument.cleanup();
- }
- }, {
- key: 'ensure',
- value: function () {
- var _ref = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee(obj, prop, args) {
- return _regenerator2.default.wrap(function _callee$(_context) {
- while (1) {
- switch (_context.prev = _context.next) {
- case 0:
- (0, _util.unreachable)('Abstract method `ensure` called');
-
- case 1:
- case 'end':
- return _context.stop();
- }
- }
- }, _callee, this);
- }));
-
- function ensure(_x, _x2, _x3) {
- return _ref.apply(this, arguments);
- }
-
- return ensure;
- }()
- }, {
- key: 'requestRange',
- value: function requestRange(begin, end) {
- (0, _util.unreachable)('Abstract method `requestRange` called');
- }
- }, {
- key: 'requestLoadedStream',
- value: function requestLoadedStream() {
- (0, _util.unreachable)('Abstract method `requestLoadedStream` called');
- }
- }, {
- key: 'sendProgressiveData',
- value: function sendProgressiveData(chunk) {
- (0, _util.unreachable)('Abstract method `sendProgressiveData` called');
- }
- }, {
- key: 'updatePassword',
- value: function updatePassword(password) {
- this._password = password;
- }
- }, {
- key: 'terminate',
- value: function terminate() {
- (0, _util.unreachable)('Abstract method `terminate` called');
- }
- }, {
- key: 'docId',
- get: function get() {
- return this._docId;
- }
- }, {
- key: 'password',
- get: function get() {
- return this._password;
- }
- }, {
- key: 'docBaseUrl',
- get: function get() {
- var docBaseUrl = null;
- if (this._docBaseUrl) {
- var absoluteUrl = (0, _util.createValidAbsoluteUrl)(this._docBaseUrl);
- if (absoluteUrl) {
- docBaseUrl = absoluteUrl.href;
- } else {
- (0, _util.warn)('Invalid absolute docBaseUrl: "' + this._docBaseUrl + '".');
- }
- }
- return (0, _util.shadow)(this, 'docBaseUrl', docBaseUrl);
- }
- }]);
-
- return BasePdfManager;
-}();
-
-var LocalPdfManager = function (_BasePdfManager) {
- _inherits(LocalPdfManager, _BasePdfManager);
-
- function LocalPdfManager(docId, data, password, evaluatorOptions, docBaseUrl) {
- _classCallCheck(this, LocalPdfManager);
-
- var _this = _possibleConstructorReturn(this, (LocalPdfManager.__proto__ || Object.getPrototypeOf(LocalPdfManager)).call(this));
-
- _this._docId = docId;
- _this._password = password;
- _this._docBaseUrl = docBaseUrl;
- _this.evaluatorOptions = evaluatorOptions;
- var stream = new _stream.Stream(data);
- _this.pdfDocument = new _document.PDFDocument(_this, stream);
- _this._loadedStreamPromise = Promise.resolve(stream);
- return _this;
- }
-
- _createClass(LocalPdfManager, [{
- key: 'ensure',
- value: function () {
- var _ref2 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee2(obj, prop, args) {
- var value;
- return _regenerator2.default.wrap(function _callee2$(_context2) {
- while (1) {
- switch (_context2.prev = _context2.next) {
- case 0:
- value = obj[prop];
-
- if (!(typeof value === 'function')) {
- _context2.next = 3;
- break;
- }
-
- return _context2.abrupt('return', value.apply(obj, args));
-
- case 3:
- return _context2.abrupt('return', value);
-
- case 4:
- case 'end':
- return _context2.stop();
- }
- }
- }, _callee2, this);
- }));
-
- function ensure(_x4, _x5, _x6) {
- return _ref2.apply(this, arguments);
- }
-
- return ensure;
- }()
- }, {
- key: 'requestRange',
- value: function requestRange(begin, end) {
- return Promise.resolve();
- }
- }, {
- key: 'requestLoadedStream',
- value: function requestLoadedStream() {}
- }, {
- key: 'onLoadedStream',
- value: function onLoadedStream() {
- return this._loadedStreamPromise;
- }
- }, {
- key: 'terminate',
- value: function terminate() {}
- }]);
-
- return LocalPdfManager;
-}(BasePdfManager);
-
-var NetworkPdfManager = function (_BasePdfManager2) {
- _inherits(NetworkPdfManager, _BasePdfManager2);
-
- function NetworkPdfManager(docId, pdfNetworkStream, args, evaluatorOptions, docBaseUrl) {
- _classCallCheck(this, NetworkPdfManager);
-
- var _this2 = _possibleConstructorReturn(this, (NetworkPdfManager.__proto__ || Object.getPrototypeOf(NetworkPdfManager)).call(this));
-
- _this2._docId = docId;
- _this2._password = args.password;
- _this2._docBaseUrl = docBaseUrl;
- _this2.msgHandler = args.msgHandler;
- _this2.evaluatorOptions = evaluatorOptions;
- _this2.streamManager = new _chunked_stream.ChunkedStreamManager(pdfNetworkStream, {
- msgHandler: args.msgHandler,
- url: args.url,
- length: args.length,
- disableAutoFetch: args.disableAutoFetch,
- rangeChunkSize: args.rangeChunkSize
- });
- _this2.pdfDocument = new _document.PDFDocument(_this2, _this2.streamManager.getStream());
- return _this2;
- }
-
- _createClass(NetworkPdfManager, [{
- key: 'ensure',
- value: function () {
- var _ref3 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee3(obj, prop, args) {
- var value;
- return _regenerator2.default.wrap(function _callee3$(_context3) {
- while (1) {
- switch (_context3.prev = _context3.next) {
- case 0:
- _context3.prev = 0;
- value = obj[prop];
-
- if (!(typeof value === 'function')) {
- _context3.next = 4;
- break;
- }
-
- return _context3.abrupt('return', value.apply(obj, args));
-
- case 4:
- return _context3.abrupt('return', value);
-
- case 7:
- _context3.prev = 7;
- _context3.t0 = _context3['catch'](0);
-
- if (_context3.t0 instanceof _util.MissingDataException) {
- _context3.next = 11;
- break;
- }
-
- throw _context3.t0;
-
- case 11:
- _context3.next = 13;
- return this.requestRange(_context3.t0.begin, _context3.t0.end);
-
- case 13:
- return _context3.abrupt('return', this.ensure(obj, prop, args));
-
- case 14:
- case 'end':
- return _context3.stop();
- }
- }
- }, _callee3, this, [[0, 7]]);
- }));
-
- function ensure(_x7, _x8, _x9) {
- return _ref3.apply(this, arguments);
- }
-
- return ensure;
- }()
- }, {
- key: 'requestRange',
- value: function requestRange(begin, end) {
- return this.streamManager.requestRange(begin, end);
- }
- }, {
- key: 'requestLoadedStream',
- value: function requestLoadedStream() {
- this.streamManager.requestAllChunks();
- }
- }, {
- key: 'sendProgressiveData',
- value: function sendProgressiveData(chunk) {
- this.streamManager.onReceiveData({ chunk: chunk });
- }
- }, {
- key: 'onLoadedStream',
- value: function onLoadedStream() {
- return this.streamManager.onLoadedStream();
- }
- }, {
- key: 'terminate',
- value: function terminate() {
- this.streamManager.abort();
- }
- }]);
-
- return NetworkPdfManager;
-}(BasePdfManager);
-
-exports.LocalPdfManager = LocalPdfManager;
-exports.NetworkPdfManager = NetworkPdfManager;
-
-/***/ }),
-/* 131 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = __w_pdfjs_require__(132);
-
-/***/ }),
-/* 132 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-var g = function () {
- return this;
-}() || Function("return this")();
-var hadRuntime = g.regeneratorRuntime && Object.getOwnPropertyNames(g).indexOf("regeneratorRuntime") >= 0;
-var oldRuntime = hadRuntime && g.regeneratorRuntime;
-g.regeneratorRuntime = undefined;
-module.exports = __w_pdfjs_require__(133);
-if (hadRuntime) {
- g.regeneratorRuntime = oldRuntime;
-} else {
- try {
- delete g.regeneratorRuntime;
- } catch (e) {
- g.regeneratorRuntime = undefined;
- }
-}
-
-/***/ }),
-/* 133 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-/* WEBPACK VAR INJECTION */(function(module) {
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-!function (global) {
- "use strict";
-
- var Op = Object.prototype;
- var hasOwn = Op.hasOwnProperty;
- var undefined;
- var $Symbol = typeof Symbol === "function" ? Symbol : {};
- var iteratorSymbol = $Symbol.iterator || "@@iterator";
- var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator";
- var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
- var inModule = ( false ? undefined : _typeof(module)) === "object";
- var runtime = global.regeneratorRuntime;
- if (runtime) {
- if (inModule) {
- module.exports = runtime;
- }
- return;
- }
- runtime = global.regeneratorRuntime = inModule ? module.exports : {};
- function wrap(innerFn, outerFn, self, tryLocsList) {
- var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;
- var generator = Object.create(protoGenerator.prototype);
- var context = new Context(tryLocsList || []);
- generator._invoke = makeInvokeMethod(innerFn, self, context);
- return generator;
- }
- runtime.wrap = wrap;
- function tryCatch(fn, obj, arg) {
- try {
- return {
- type: "normal",
- arg: fn.call(obj, arg)
- };
- } catch (err) {
- return {
- type: "throw",
- arg: err
- };
- }
- }
- var GenStateSuspendedStart = "suspendedStart";
- var GenStateSuspendedYield = "suspendedYield";
- var GenStateExecuting = "executing";
- var GenStateCompleted = "completed";
- var ContinueSentinel = {};
- function Generator() {}
- function GeneratorFunction() {}
- function GeneratorFunctionPrototype() {}
- var IteratorPrototype = {};
- IteratorPrototype[iteratorSymbol] = function () {
- return this;
- };
- var getProto = Object.getPrototypeOf;
- var NativeIteratorPrototype = getProto && getProto(getProto(values([])));
- if (NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {
- IteratorPrototype = NativeIteratorPrototype;
- }
- var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
- GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;
- GeneratorFunctionPrototype.constructor = GeneratorFunction;
- GeneratorFunctionPrototype[toStringTagSymbol] = GeneratorFunction.displayName = "GeneratorFunction";
- function defineIteratorMethods(prototype) {
- ["next", "throw", "return"].forEach(function (method) {
- prototype[method] = function (arg) {
- return this._invoke(method, arg);
- };
- });
- }
- runtime.isGeneratorFunction = function (genFun) {
- var ctor = typeof genFun === "function" && genFun.constructor;
- return ctor ? ctor === GeneratorFunction || (ctor.displayName || ctor.name) === "GeneratorFunction" : false;
- };
- runtime.mark = function (genFun) {
- if (Object.setPrototypeOf) {
- Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
- } else {
- genFun.__proto__ = GeneratorFunctionPrototype;
- if (!(toStringTagSymbol in genFun)) {
- genFun[toStringTagSymbol] = "GeneratorFunction";
- }
- }
- genFun.prototype = Object.create(Gp);
- return genFun;
- };
- runtime.awrap = function (arg) {
- return { __await: arg };
- };
- function AsyncIterator(generator) {
- function invoke(method, arg, resolve, reject) {
- var record = tryCatch(generator[method], generator, arg);
- if (record.type === "throw") {
- reject(record.arg);
- } else {
- var result = record.arg;
- var value = result.value;
- if (value && (typeof value === "undefined" ? "undefined" : _typeof(value)) === "object" && hasOwn.call(value, "__await")) {
- return Promise.resolve(value.__await).then(function (value) {
- invoke("next", value, resolve, reject);
- }, function (err) {
- invoke("throw", err, resolve, reject);
- });
- }
- return Promise.resolve(value).then(function (unwrapped) {
- result.value = unwrapped;
- resolve(result);
- }, reject);
- }
- }
- var previousPromise;
- function enqueue(method, arg) {
- function callInvokeWithMethodAndArg() {
- return new Promise(function (resolve, reject) {
- invoke(method, arg, resolve, reject);
- });
- }
- return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
- }
- this._invoke = enqueue;
- }
- defineIteratorMethods(AsyncIterator.prototype);
- AsyncIterator.prototype[asyncIteratorSymbol] = function () {
- return this;
- };
- runtime.AsyncIterator = AsyncIterator;
- runtime.async = function (innerFn, outerFn, self, tryLocsList) {
- var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList));
- return runtime.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) {
- return result.done ? result.value : iter.next();
- });
- };
- function makeInvokeMethod(innerFn, self, context) {
- var state = GenStateSuspendedStart;
- return function invoke(method, arg) {
- if (state === GenStateExecuting) {
- throw new Error("Generator is already running");
- }
- if (state === GenStateCompleted) {
- if (method === "throw") {
- throw arg;
- }
- return doneResult();
- }
- context.method = method;
- context.arg = arg;
- while (true) {
- var delegate = context.delegate;
- if (delegate) {
- var delegateResult = maybeInvokeDelegate(delegate, context);
- if (delegateResult) {
- if (delegateResult === ContinueSentinel) continue;
- return delegateResult;
- }
- }
- if (context.method === "next") {
- context.sent = context._sent = context.arg;
- } else if (context.method === "throw") {
- if (state === GenStateSuspendedStart) {
- state = GenStateCompleted;
- throw context.arg;
- }
- context.dispatchException(context.arg);
- } else if (context.method === "return") {
- context.abrupt("return", context.arg);
- }
- state = GenStateExecuting;
- var record = tryCatch(innerFn, self, context);
- if (record.type === "normal") {
- state = context.done ? GenStateCompleted : GenStateSuspendedYield;
- if (record.arg === ContinueSentinel) {
- continue;
- }
- return {
- value: record.arg,
- done: context.done
- };
- } else if (record.type === "throw") {
- state = GenStateCompleted;
- context.method = "throw";
- context.arg = record.arg;
- }
- }
- };
- }
- function maybeInvokeDelegate(delegate, context) {
- var method = delegate.iterator[context.method];
- if (method === undefined) {
- context.delegate = null;
- if (context.method === "throw") {
- if (delegate.iterator.return) {
- context.method = "return";
- context.arg = undefined;
- maybeInvokeDelegate(delegate, context);
- if (context.method === "throw") {
- return ContinueSentinel;
- }
- }
- context.method = "throw";
- context.arg = new TypeError("The iterator does not provide a 'throw' method");
- }
- return ContinueSentinel;
- }
- var record = tryCatch(method, delegate.iterator, context.arg);
- if (record.type === "throw") {
- context.method = "throw";
- context.arg = record.arg;
- context.delegate = null;
- return ContinueSentinel;
- }
- var info = record.arg;
- if (!info) {
- context.method = "throw";
- context.arg = new TypeError("iterator result is not an object");
- context.delegate = null;
- return ContinueSentinel;
- }
- if (info.done) {
- context[delegate.resultName] = info.value;
- context.next = delegate.nextLoc;
- if (context.method !== "return") {
- context.method = "next";
- context.arg = undefined;
- }
- } else {
- return info;
- }
- context.delegate = null;
- return ContinueSentinel;
- }
- defineIteratorMethods(Gp);
- Gp[toStringTagSymbol] = "Generator";
- Gp[iteratorSymbol] = function () {
- return this;
- };
- Gp.toString = function () {
- return "[object Generator]";
- };
- function pushTryEntry(locs) {
- var entry = { tryLoc: locs[0] };
- if (1 in locs) {
- entry.catchLoc = locs[1];
- }
- if (2 in locs) {
- entry.finallyLoc = locs[2];
- entry.afterLoc = locs[3];
- }
- this.tryEntries.push(entry);
- }
- function resetTryEntry(entry) {
- var record = entry.completion || {};
- record.type = "normal";
- delete record.arg;
- entry.completion = record;
- }
- function Context(tryLocsList) {
- this.tryEntries = [{ tryLoc: "root" }];
- tryLocsList.forEach(pushTryEntry, this);
- this.reset(true);
- }
- runtime.keys = function (object) {
- var keys = [];
- for (var key in object) {
- keys.push(key);
- }
- keys.reverse();
- return function next() {
- while (keys.length) {
- var key = keys.pop();
- if (key in object) {
- next.value = key;
- next.done = false;
- return next;
- }
- }
- next.done = true;
- return next;
- };
- };
- function values(iterable) {
- if (iterable) {
- var iteratorMethod = iterable[iteratorSymbol];
- if (iteratorMethod) {
- return iteratorMethod.call(iterable);
- }
- if (typeof iterable.next === "function") {
- return iterable;
- }
- if (!isNaN(iterable.length)) {
- var i = -1,
- next = function next() {
- while (++i < iterable.length) {
- if (hasOwn.call(iterable, i)) {
- next.value = iterable[i];
- next.done = false;
- return next;
- }
- }
- next.value = undefined;
- next.done = true;
- return next;
- };
- return next.next = next;
- }
- }
- return { next: doneResult };
- }
- runtime.values = values;
- function doneResult() {
- return {
- value: undefined,
- done: true
- };
- }
- Context.prototype = {
- constructor: Context,
- reset: function reset(skipTempReset) {
- this.prev = 0;
- this.next = 0;
- this.sent = this._sent = undefined;
- this.done = false;
- this.delegate = null;
- this.method = "next";
- this.arg = undefined;
- this.tryEntries.forEach(resetTryEntry);
- if (!skipTempReset) {
- for (var name in this) {
- if (name.charAt(0) === "t" && hasOwn.call(this, name) && !isNaN(+name.slice(1))) {
- this[name] = undefined;
- }
- }
- }
- },
- stop: function stop() {
- this.done = true;
- var rootEntry = this.tryEntries[0];
- var rootRecord = rootEntry.completion;
- if (rootRecord.type === "throw") {
- throw rootRecord.arg;
- }
- return this.rval;
- },
- dispatchException: function dispatchException(exception) {
- if (this.done) {
- throw exception;
- }
- var context = this;
- function handle(loc, caught) {
- record.type = "throw";
- record.arg = exception;
- context.next = loc;
- if (caught) {
- context.method = "next";
- context.arg = undefined;
- }
- return !!caught;
- }
- for (var i = this.tryEntries.length - 1; i >= 0; --i) {
- var entry = this.tryEntries[i];
- var record = entry.completion;
- if (entry.tryLoc === "root") {
- return handle("end");
- }
- if (entry.tryLoc <= this.prev) {
- var hasCatch = hasOwn.call(entry, "catchLoc");
- var hasFinally = hasOwn.call(entry, "finallyLoc");
- if (hasCatch && hasFinally) {
- if (this.prev < entry.catchLoc) {
- return handle(entry.catchLoc, true);
- } else if (this.prev < entry.finallyLoc) {
- return handle(entry.finallyLoc);
- }
- } else if (hasCatch) {
- if (this.prev < entry.catchLoc) {
- return handle(entry.catchLoc, true);
- }
- } else if (hasFinally) {
- if (this.prev < entry.finallyLoc) {
- return handle(entry.finallyLoc);
- }
- } else {
- throw new Error("try statement without catch or finally");
- }
- }
- }
- },
- abrupt: function abrupt(type, arg) {
- for (var i = this.tryEntries.length - 1; i >= 0; --i) {
- var entry = this.tryEntries[i];
- if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
- var finallyEntry = entry;
- break;
- }
- }
- if (finallyEntry && (type === "break" || type === "continue") && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc) {
- finallyEntry = null;
- }
- var record = finallyEntry ? finallyEntry.completion : {};
- record.type = type;
- record.arg = arg;
- if (finallyEntry) {
- this.method = "next";
- this.next = finallyEntry.finallyLoc;
- return ContinueSentinel;
- }
- return this.complete(record);
- },
- complete: function complete(record, afterLoc) {
- if (record.type === "throw") {
- throw record.arg;
- }
- if (record.type === "break" || record.type === "continue") {
- this.next = record.arg;
- } else if (record.type === "return") {
- this.rval = this.arg = record.arg;
- this.method = "return";
- this.next = "end";
- } else if (record.type === "normal" && afterLoc) {
- this.next = afterLoc;
- }
- return ContinueSentinel;
- },
- finish: function finish(finallyLoc) {
- for (var i = this.tryEntries.length - 1; i >= 0; --i) {
- var entry = this.tryEntries[i];
- if (entry.finallyLoc === finallyLoc) {
- this.complete(entry.completion, entry.afterLoc);
- resetTryEntry(entry);
- return ContinueSentinel;
- }
- }
- },
- "catch": function _catch(tryLoc) {
- for (var i = this.tryEntries.length - 1; i >= 0; --i) {
- var entry = this.tryEntries[i];
- if (entry.tryLoc === tryLoc) {
- var record = entry.completion;
- if (record.type === "throw") {
- var thrown = record.arg;
- resetTryEntry(entry);
- }
- return thrown;
- }
- }
- throw new Error("illegal catch attempt");
- },
- delegateYield: function delegateYield(iterable, resultName, nextLoc) {
- this.delegate = {
- iterator: values(iterable),
- resultName: resultName,
- nextLoc: nextLoc
- };
- if (this.method === "next") {
- this.arg = undefined;
- }
- return ContinueSentinel;
- }
- };
-}(function () {
- return this;
-}() || Function("return this")());
-/* WEBPACK VAR INJECTION */}.call(this, __w_pdfjs_require__(134)(module)))
-
-/***/ }),
-/* 134 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-module.exports = function (module) {
- if (!module.webpackPolyfill) {
- module.deprecate = function () {};
- module.paths = [];
- if (!module.children) module.children = [];
- Object.defineProperty(module, "loaded", {
- enumerable: true,
- get: function get() {
- return module.l;
- }
- });
- Object.defineProperty(module, "id", {
- enumerable: true,
- get: function get() {
- return module.i;
- }
- });
- module.webpackPolyfill = 1;
- }
- return module;
-};
-
-/***/ }),
-/* 135 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.ChunkedStreamManager = exports.ChunkedStream = undefined;
-
-var _util = __w_pdfjs_require__(2);
-
-var ChunkedStream = function ChunkedStreamClosure() {
- function ChunkedStream(length, chunkSize, manager) {
- this.bytes = new Uint8Array(length);
- this.start = 0;
- this.pos = 0;
- this.end = length;
- this.chunkSize = chunkSize;
- this.loadedChunks = [];
- this.numChunksLoaded = 0;
- this.numChunks = Math.ceil(length / chunkSize);
- this.manager = manager;
- this.progressiveDataLength = 0;
- this.lastSuccessfulEnsureByteChunk = -1;
- }
- ChunkedStream.prototype = {
- getMissingChunks: function ChunkedStream_getMissingChunks() {
- var chunks = [];
- for (var chunk = 0, n = this.numChunks; chunk < n; ++chunk) {
- if (!this.loadedChunks[chunk]) {
- chunks.push(chunk);
- }
- }
- return chunks;
- },
- getBaseStreams: function ChunkedStream_getBaseStreams() {
- return [this];
- },
- allChunksLoaded: function ChunkedStream_allChunksLoaded() {
- return this.numChunksLoaded === this.numChunks;
- },
- onReceiveData: function ChunkedStream_onReceiveData(begin, chunk) {
- var end = begin + chunk.byteLength;
- if (begin % this.chunkSize !== 0) {
- throw new Error('Bad begin offset: ' + begin);
- }
- var length = this.bytes.length;
- if (end % this.chunkSize !== 0 && end !== length) {
- throw new Error('Bad end offset: ' + end);
- }
- this.bytes.set(new Uint8Array(chunk), begin);
- var chunkSize = this.chunkSize;
- var beginChunk = Math.floor(begin / chunkSize);
- var endChunk = Math.floor((end - 1) / chunkSize) + 1;
- var curChunk;
- for (curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
- if (!this.loadedChunks[curChunk]) {
- this.loadedChunks[curChunk] = true;
- ++this.numChunksLoaded;
- }
- }
- },
- onReceiveProgressiveData: function ChunkedStream_onReceiveProgressiveData(data) {
- var position = this.progressiveDataLength;
- var beginChunk = Math.floor(position / this.chunkSize);
- this.bytes.set(new Uint8Array(data), position);
- position += data.byteLength;
- this.progressiveDataLength = position;
- var endChunk = position >= this.end ? this.numChunks : Math.floor(position / this.chunkSize);
- var curChunk;
- for (curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
- if (!this.loadedChunks[curChunk]) {
- this.loadedChunks[curChunk] = true;
- ++this.numChunksLoaded;
- }
- }
- },
- ensureByte: function ChunkedStream_ensureByte(pos) {
- var chunk = Math.floor(pos / this.chunkSize);
- if (chunk === this.lastSuccessfulEnsureByteChunk) {
- return;
- }
- if (!this.loadedChunks[chunk]) {
- throw new _util.MissingDataException(pos, pos + 1);
- }
- this.lastSuccessfulEnsureByteChunk = chunk;
- },
- ensureRange: function ChunkedStream_ensureRange(begin, end) {
- if (begin >= end) {
- return;
- }
- if (end <= this.progressiveDataLength) {
- return;
- }
- var chunkSize = this.chunkSize;
- var beginChunk = Math.floor(begin / chunkSize);
- var endChunk = Math.floor((end - 1) / chunkSize) + 1;
- for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
- if (!this.loadedChunks[chunk]) {
- throw new _util.MissingDataException(begin, end);
- }
- }
- },
- nextEmptyChunk: function ChunkedStream_nextEmptyChunk(beginChunk) {
- var chunk,
- numChunks = this.numChunks;
- for (var i = 0; i < numChunks; ++i) {
- chunk = (beginChunk + i) % numChunks;
- if (!this.loadedChunks[chunk]) {
- return chunk;
- }
- }
- return null;
- },
- hasChunk: function ChunkedStream_hasChunk(chunk) {
- return !!this.loadedChunks[chunk];
- },
- get length() {
- return this.end - this.start;
- },
- get isEmpty() {
- return this.length === 0;
- },
- getByte: function ChunkedStream_getByte() {
- var pos = this.pos;
- if (pos >= this.end) {
- return -1;
- }
- this.ensureByte(pos);
- return this.bytes[this.pos++];
- },
- getUint16: function ChunkedStream_getUint16() {
- var b0 = this.getByte();
- var b1 = this.getByte();
- if (b0 === -1 || b1 === -1) {
- return -1;
- }
- return (b0 << 8) + b1;
- },
- getInt32: function ChunkedStream_getInt32() {
- var b0 = this.getByte();
- var b1 = this.getByte();
- var b2 = this.getByte();
- var b3 = this.getByte();
- return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
- },
- getBytes: function getBytes(length) {
- var forceClamped = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
-
- var bytes = this.bytes;
- var pos = this.pos;
- var strEnd = this.end;
- if (!length) {
- this.ensureRange(pos, strEnd);
- var _subarray = bytes.subarray(pos, strEnd);
- return forceClamped ? new Uint8ClampedArray(_subarray) : _subarray;
- }
- var end = pos + length;
- if (end > strEnd) {
- end = strEnd;
- }
- this.ensureRange(pos, end);
- this.pos = end;
- var subarray = bytes.subarray(pos, end);
- return forceClamped ? new Uint8ClampedArray(subarray) : subarray;
- },
-
- peekByte: function ChunkedStream_peekByte() {
- var peekedByte = this.getByte();
- this.pos--;
- return peekedByte;
- },
- peekBytes: function peekBytes(length) {
- var forceClamped = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
-
- var bytes = this.getBytes(length, forceClamped);
- this.pos -= bytes.length;
- return bytes;
- },
-
- getByteRange: function ChunkedStream_getBytes(begin, end) {
- this.ensureRange(begin, end);
- return this.bytes.subarray(begin, end);
- },
- skip: function ChunkedStream_skip(n) {
- if (!n) {
- n = 1;
- }
- this.pos += n;
- },
- reset: function ChunkedStream_reset() {
- this.pos = this.start;
- },
- moveStart: function ChunkedStream_moveStart() {
- this.start = this.pos;
- },
- makeSubStream: function ChunkedStream_makeSubStream(start, length, dict) {
- this.ensureRange(start, start + length);
- function ChunkedStreamSubstream() {}
- ChunkedStreamSubstream.prototype = Object.create(this);
- ChunkedStreamSubstream.prototype.getMissingChunks = function () {
- var chunkSize = this.chunkSize;
- var beginChunk = Math.floor(this.start / chunkSize);
- var endChunk = Math.floor((this.end - 1) / chunkSize) + 1;
- var missingChunks = [];
- for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
- if (!this.loadedChunks[chunk]) {
- missingChunks.push(chunk);
- }
- }
- return missingChunks;
- };
- var subStream = new ChunkedStreamSubstream();
- subStream.pos = subStream.start = start;
- subStream.end = start + length || this.end;
- subStream.dict = dict;
- return subStream;
- }
- };
- return ChunkedStream;
-}();
-var ChunkedStreamManager = function ChunkedStreamManagerClosure() {
- function ChunkedStreamManager(pdfNetworkStream, args) {
- var chunkSize = args.rangeChunkSize;
- var length = args.length;
- this.stream = new ChunkedStream(length, chunkSize, this);
- this.length = length;
- this.chunkSize = chunkSize;
- this.pdfNetworkStream = pdfNetworkStream;
- this.url = args.url;
- this.disableAutoFetch = args.disableAutoFetch;
- this.msgHandler = args.msgHandler;
- this.currRequestId = 0;
- this.chunksNeededByRequest = Object.create(null);
- this.requestsByChunk = Object.create(null);
- this.promisesByRequest = Object.create(null);
- this.progressiveDataLength = 0;
- this.aborted = false;
- this._loadedStreamCapability = (0, _util.createPromiseCapability)();
- }
- ChunkedStreamManager.prototype = {
- onLoadedStream: function ChunkedStreamManager_getLoadedStream() {
- return this._loadedStreamCapability.promise;
- },
- sendRequest: function ChunkedStreamManager_sendRequest(begin, end) {
- var _this = this;
-
- var rangeReader = this.pdfNetworkStream.getRangeReader(begin, end);
- if (!rangeReader.isStreamingSupported) {
- rangeReader.onProgress = this.onProgress.bind(this);
- }
- var chunks = [],
- loaded = 0;
- var manager = this;
- var promise = new Promise(function (resolve, reject) {
- var readChunk = function readChunk(chunk) {
- try {
- if (!chunk.done) {
- var data = chunk.value;
- chunks.push(data);
- loaded += (0, _util.arrayByteLength)(data);
- if (rangeReader.isStreamingSupported) {
- manager.onProgress({ loaded: loaded });
- }
- rangeReader.read().then(readChunk, reject);
- return;
- }
- var chunkData = (0, _util.arraysToBytes)(chunks);
- chunks = null;
- resolve(chunkData);
- } catch (e) {
- reject(e);
- }
- };
- rangeReader.read().then(readChunk, reject);
- });
- promise.then(function (data) {
- if (_this.aborted) {
- return;
- }
- _this.onReceiveData({
- chunk: data,
- begin: begin
- });
- });
- },
- requestAllChunks: function ChunkedStreamManager_requestAllChunks() {
- var missingChunks = this.stream.getMissingChunks();
- this._requestChunks(missingChunks);
- return this._loadedStreamCapability.promise;
- },
- _requestChunks: function ChunkedStreamManager_requestChunks(chunks) {
- var requestId = this.currRequestId++;
- var i, ii;
- var chunksNeeded = Object.create(null);
- this.chunksNeededByRequest[requestId] = chunksNeeded;
- for (i = 0, ii = chunks.length; i < ii; i++) {
- if (!this.stream.hasChunk(chunks[i])) {
- chunksNeeded[chunks[i]] = true;
- }
- }
- if ((0, _util.isEmptyObj)(chunksNeeded)) {
- return Promise.resolve();
- }
- var capability = (0, _util.createPromiseCapability)();
- this.promisesByRequest[requestId] = capability;
- var chunksToRequest = [];
- for (var chunk in chunksNeeded) {
- chunk = chunk | 0;
- if (!(chunk in this.requestsByChunk)) {
- this.requestsByChunk[chunk] = [];
- chunksToRequest.push(chunk);
- }
- this.requestsByChunk[chunk].push(requestId);
- }
- if (!chunksToRequest.length) {
- return capability.promise;
- }
- var groupedChunksToRequest = this.groupChunks(chunksToRequest);
- for (i = 0; i < groupedChunksToRequest.length; ++i) {
- var groupedChunk = groupedChunksToRequest[i];
- var begin = groupedChunk.beginChunk * this.chunkSize;
- var end = Math.min(groupedChunk.endChunk * this.chunkSize, this.length);
- this.sendRequest(begin, end);
- }
- return capability.promise;
- },
- getStream: function ChunkedStreamManager_getStream() {
- return this.stream;
- },
- requestRange: function ChunkedStreamManager_requestRange(begin, end) {
- end = Math.min(end, this.length);
- var beginChunk = this.getBeginChunk(begin);
- var endChunk = this.getEndChunk(end);
- var chunks = [];
- for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
- chunks.push(chunk);
- }
- return this._requestChunks(chunks);
- },
- requestRanges: function ChunkedStreamManager_requestRanges(ranges) {
- ranges = ranges || [];
- var chunksToRequest = [];
- for (var i = 0; i < ranges.length; i++) {
- var beginChunk = this.getBeginChunk(ranges[i].begin);
- var endChunk = this.getEndChunk(ranges[i].end);
- for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
- if (!chunksToRequest.includes(chunk)) {
- chunksToRequest.push(chunk);
- }
- }
- }
- chunksToRequest.sort(function (a, b) {
- return a - b;
- });
- return this._requestChunks(chunksToRequest);
- },
- groupChunks: function ChunkedStreamManager_groupChunks(chunks) {
- var groupedChunks = [];
- var beginChunk = -1;
- var prevChunk = -1;
- for (var i = 0; i < chunks.length; ++i) {
- var chunk = chunks[i];
- if (beginChunk < 0) {
- beginChunk = chunk;
- }
- if (prevChunk >= 0 && prevChunk + 1 !== chunk) {
- groupedChunks.push({
- beginChunk: beginChunk,
- endChunk: prevChunk + 1
- });
- beginChunk = chunk;
- }
- if (i + 1 === chunks.length) {
- groupedChunks.push({
- beginChunk: beginChunk,
- endChunk: chunk + 1
- });
- }
- prevChunk = chunk;
- }
- return groupedChunks;
- },
- onProgress: function ChunkedStreamManager_onProgress(args) {
- var bytesLoaded = this.stream.numChunksLoaded * this.chunkSize + args.loaded;
- this.msgHandler.send('DocProgress', {
- loaded: bytesLoaded,
- total: this.length
- });
- },
- onReceiveData: function ChunkedStreamManager_onReceiveData(args) {
- var chunk = args.chunk;
- var isProgressive = args.begin === undefined;
- var begin = isProgressive ? this.progressiveDataLength : args.begin;
- var end = begin + chunk.byteLength;
- var beginChunk = Math.floor(begin / this.chunkSize);
- var endChunk = end < this.length ? Math.floor(end / this.chunkSize) : Math.ceil(end / this.chunkSize);
- if (isProgressive) {
- this.stream.onReceiveProgressiveData(chunk);
- this.progressiveDataLength = end;
- } else {
- this.stream.onReceiveData(begin, chunk);
- }
- if (this.stream.allChunksLoaded()) {
- this._loadedStreamCapability.resolve(this.stream);
- }
- var loadedRequests = [];
- var i, requestId;
- for (chunk = beginChunk; chunk < endChunk; ++chunk) {
- var requestIds = this.requestsByChunk[chunk] || [];
- delete this.requestsByChunk[chunk];
- for (i = 0; i < requestIds.length; ++i) {
- requestId = requestIds[i];
- var chunksNeeded = this.chunksNeededByRequest[requestId];
- if (chunk in chunksNeeded) {
- delete chunksNeeded[chunk];
- }
- if (!(0, _util.isEmptyObj)(chunksNeeded)) {
- continue;
- }
- loadedRequests.push(requestId);
- }
- }
- if (!this.disableAutoFetch && (0, _util.isEmptyObj)(this.requestsByChunk)) {
- var nextEmptyChunk;
- if (this.stream.numChunksLoaded === 1) {
- var lastChunk = this.stream.numChunks - 1;
- if (!this.stream.hasChunk(lastChunk)) {
- nextEmptyChunk = lastChunk;
- }
- } else {
- nextEmptyChunk = this.stream.nextEmptyChunk(endChunk);
- }
- if (Number.isInteger(nextEmptyChunk)) {
- this._requestChunks([nextEmptyChunk]);
- }
- }
- for (i = 0; i < loadedRequests.length; ++i) {
- requestId = loadedRequests[i];
- var capability = this.promisesByRequest[requestId];
- delete this.promisesByRequest[requestId];
- capability.resolve();
- }
- this.msgHandler.send('DocProgress', {
- loaded: this.stream.numChunksLoaded * this.chunkSize,
- total: this.length
- });
- },
- onError: function ChunkedStreamManager_onError(err) {
- this._loadedStreamCapability.reject(err);
- },
- getBeginChunk: function ChunkedStreamManager_getBeginChunk(begin) {
- var chunk = Math.floor(begin / this.chunkSize);
- return chunk;
- },
- getEndChunk: function ChunkedStreamManager_getEndChunk(end) {
- var chunk = Math.floor((end - 1) / this.chunkSize) + 1;
- return chunk;
- },
- abort: function ChunkedStreamManager_abort() {
- this.aborted = true;
- if (this.pdfNetworkStream) {
- this.pdfNetworkStream.cancelAllRequests('abort');
- }
- for (var requestId in this.promisesByRequest) {
- var capability = this.promisesByRequest[requestId];
- capability.reject(new Error('Request was aborted'));
- }
- }
- };
- return ChunkedStreamManager;
-}();
-exports.ChunkedStream = ChunkedStream;
-exports.ChunkedStreamManager = ChunkedStreamManager;
-
-/***/ }),
-/* 136 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.PDFDocument = exports.Page = undefined;
-
-var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
-
-var _util = __w_pdfjs_require__(2);
-
-var _obj = __w_pdfjs_require__(137);
-
-var _primitives = __w_pdfjs_require__(138);
-
-var _stream = __w_pdfjs_require__(140);
-
-var _annotation = __w_pdfjs_require__(152);
-
-var _crypto = __w_pdfjs_require__(150);
-
-var _parser = __w_pdfjs_require__(139);
-
-var _operator_list = __w_pdfjs_require__(153);
-
-var _evaluator = __w_pdfjs_require__(154);
-
-var _function = __w_pdfjs_require__(168);
-
-var Page = function PageClosure() {
- var DEFAULT_USER_UNIT = 1.0;
- var LETTER_SIZE_MEDIABOX = [0, 0, 612, 792];
- function isAnnotationRenderable(annotation, intent) {
- return intent === 'display' && annotation.viewable || intent === 'print' && annotation.printable;
- }
- function Page(_ref) {
- var pdfManager = _ref.pdfManager,
- xref = _ref.xref,
- pageIndex = _ref.pageIndex,
- pageDict = _ref.pageDict,
- ref = _ref.ref,
- fontCache = _ref.fontCache,
- builtInCMapCache = _ref.builtInCMapCache,
- pdfFunctionFactory = _ref.pdfFunctionFactory;
-
- this.pdfManager = pdfManager;
- this.pageIndex = pageIndex;
- this.pageDict = pageDict;
- this.xref = xref;
- this.ref = ref;
- this.fontCache = fontCache;
- this.builtInCMapCache = builtInCMapCache;
- this.pdfFunctionFactory = pdfFunctionFactory;
- this.evaluatorOptions = pdfManager.evaluatorOptions;
- this.resourcesPromise = null;
- var uniquePrefix = 'p' + this.pageIndex + '_';
- var idCounters = { obj: 0 };
- this.idFactory = {
- createObjId: function createObjId() {
- return uniquePrefix + ++idCounters.obj;
- }
- };
- }
- Page.prototype = {
- _getInheritableProperty: function _getInheritableProperty(key) {
- var getArray = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
-
- var value = (0, _util.getInheritableProperty)({
- dict: this.pageDict,
- key: key,
- getArray: getArray,
- stopWhenFound: false
- });
- if (!Array.isArray(value)) {
- return value;
- }
- if (value.length === 1 || !(0, _primitives.isDict)(value[0])) {
- return value[0];
- }
- return _primitives.Dict.merge(this.xref, value);
- },
-
- get content() {
- return this.pageDict.get('Contents');
- },
- get resources() {
- return (0, _util.shadow)(this, 'resources', this._getInheritableProperty('Resources') || _primitives.Dict.empty);
- },
- get mediaBox() {
- var mediaBox = this._getInheritableProperty('MediaBox', true);
- if (!Array.isArray(mediaBox) || mediaBox.length !== 4) {
- return (0, _util.shadow)(this, 'mediaBox', LETTER_SIZE_MEDIABOX);
- }
- return (0, _util.shadow)(this, 'mediaBox', mediaBox);
- },
- get cropBox() {
- var cropBox = this._getInheritableProperty('CropBox', true);
- if (!Array.isArray(cropBox) || cropBox.length !== 4) {
- return (0, _util.shadow)(this, 'cropBox', this.mediaBox);
- }
- return (0, _util.shadow)(this, 'cropBox', cropBox);
- },
- get userUnit() {
- var obj = this.pageDict.get('UserUnit');
- if (!(0, _util.isNum)(obj) || obj <= 0) {
- obj = DEFAULT_USER_UNIT;
- }
- return (0, _util.shadow)(this, 'userUnit', obj);
- },
- get view() {
- var mediaBox = this.mediaBox,
- cropBox = this.cropBox;
- if (mediaBox === cropBox) {
- return (0, _util.shadow)(this, 'view', mediaBox);
- }
- var intersection = _util.Util.intersect(cropBox, mediaBox);
- return (0, _util.shadow)(this, 'view', intersection || mediaBox);
- },
- get rotate() {
- var rotate = this._getInheritableProperty('Rotate') || 0;
- if (rotate % 90 !== 0) {
- rotate = 0;
- } else if (rotate >= 360) {
- rotate = rotate % 360;
- } else if (rotate < 0) {
- rotate = (rotate % 360 + 360) % 360;
- }
- return (0, _util.shadow)(this, 'rotate', rotate);
- },
- getContentStream: function Page_getContentStream() {
- var content = this.content;
- var stream;
- if (Array.isArray(content)) {
- var xref = this.xref;
- var i,
- n = content.length;
- var streams = [];
- for (i = 0; i < n; ++i) {
- streams.push(xref.fetchIfRef(content[i]));
- }
- stream = new _stream.StreamsSequenceStream(streams);
- } else if ((0, _primitives.isStream)(content)) {
- stream = content;
- } else {
- stream = new _stream.NullStream();
- }
- return stream;
- },
- loadResources: function Page_loadResources(keys) {
- var _this = this;
-
- if (!this.resourcesPromise) {
- this.resourcesPromise = this.pdfManager.ensure(this, 'resources');
- }
- return this.resourcesPromise.then(function () {
- var objectLoader = new _obj.ObjectLoader(_this.resources, keys, _this.xref);
- return objectLoader.load();
- });
- },
- getOperatorList: function getOperatorList(_ref2) {
- var _this2 = this;
-
- var handler = _ref2.handler,
- task = _ref2.task,
- intent = _ref2.intent,
- renderInteractiveForms = _ref2.renderInteractiveForms;
-
- var contentStreamPromise = this.pdfManager.ensure(this, 'getContentStream');
- var resourcesPromise = this.loadResources(['ExtGState', 'ColorSpace', 'Pattern', 'Shading', 'XObject', 'Font']);
- var partialEvaluator = new _evaluator.PartialEvaluator({
- pdfManager: this.pdfManager,
- xref: this.xref,
- handler: handler,
- pageIndex: this.pageIndex,
- idFactory: this.idFactory,
- fontCache: this.fontCache,
- builtInCMapCache: this.builtInCMapCache,
- options: this.evaluatorOptions,
- pdfFunctionFactory: this.pdfFunctionFactory
- });
- var dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);
- var pageListPromise = dataPromises.then(function (_ref3) {
- var _ref4 = _slicedToArray(_ref3, 1),
- contentStream = _ref4[0];
-
- var opList = new _operator_list.OperatorList(intent, handler, _this2.pageIndex);
- handler.send('StartRenderPage', {
- transparency: partialEvaluator.hasBlendModes(_this2.resources),
- pageIndex: _this2.pageIndex,
- intent: intent
- });
- return partialEvaluator.getOperatorList({
- stream: contentStream,
- task: task,
- resources: _this2.resources,
- operatorList: opList
- }).then(function () {
- return opList;
- });
- });
- return Promise.all([pageListPromise, this._parsedAnnotations]).then(function (_ref5) {
- var _ref6 = _slicedToArray(_ref5, 2),
- pageOpList = _ref6[0],
- annotations = _ref6[1];
-
- if (annotations.length === 0) {
- pageOpList.flush(true);
- return pageOpList;
- }
- var i,
- ii,
- opListPromises = [];
- for (i = 0, ii = annotations.length; i < ii; i++) {
- if (isAnnotationRenderable(annotations[i], intent)) {
- opListPromises.push(annotations[i].getOperatorList(partialEvaluator, task, renderInteractiveForms));
- }
- }
- return Promise.all(opListPromises).then(function (opLists) {
- pageOpList.addOp(_util.OPS.beginAnnotations, []);
- for (i = 0, ii = opLists.length; i < ii; i++) {
- pageOpList.addOpList(opLists[i]);
- }
- pageOpList.addOp(_util.OPS.endAnnotations, []);
- pageOpList.flush(true);
- return pageOpList;
- });
- });
- },
- extractTextContent: function extractTextContent(_ref7) {
- var _this3 = this;
-
- var handler = _ref7.handler,
- task = _ref7.task,
- normalizeWhitespace = _ref7.normalizeWhitespace,
- sink = _ref7.sink,
- combineTextItems = _ref7.combineTextItems;
-
- var contentStreamPromise = this.pdfManager.ensure(this, 'getContentStream');
- var resourcesPromise = this.loadResources(['ExtGState', 'XObject', 'Font']);
- var dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);
- return dataPromises.then(function (_ref8) {
- var _ref9 = _slicedToArray(_ref8, 1),
- contentStream = _ref9[0];
-
- var partialEvaluator = new _evaluator.PartialEvaluator({
- pdfManager: _this3.pdfManager,
- xref: _this3.xref,
- handler: handler,
- pageIndex: _this3.pageIndex,
- idFactory: _this3.idFactory,
- fontCache: _this3.fontCache,
- builtInCMapCache: _this3.builtInCMapCache,
- options: _this3.evaluatorOptions,
- pdfFunctionFactory: _this3.pdfFunctionFactory
- });
- return partialEvaluator.getTextContent({
- stream: contentStream,
- task: task,
- resources: _this3.resources,
- normalizeWhitespace: normalizeWhitespace,
- combineTextItems: combineTextItems,
- sink: sink
- });
- });
- },
- getAnnotationsData: function getAnnotationsData(intent) {
- return this._parsedAnnotations.then(function (annotations) {
- var annotationsData = [];
- for (var i = 0, ii = annotations.length; i < ii; i++) {
- if (!intent || isAnnotationRenderable(annotations[i], intent)) {
- annotationsData.push(annotations[i].data);
- }
- }
- return annotationsData;
- });
- },
-
- get annotations() {
- return (0, _util.shadow)(this, 'annotations', this._getInheritableProperty('Annots') || []);
- },
- get _parsedAnnotations() {
- var _this4 = this;
-
- var parsedAnnotations = this.pdfManager.ensure(this, 'annotations').then(function () {
- var annotationRefs = _this4.annotations;
- var annotationPromises = [];
- for (var i = 0, ii = annotationRefs.length; i < ii; i++) {
- annotationPromises.push(_annotation.AnnotationFactory.create(_this4.xref, annotationRefs[i], _this4.pdfManager, _this4.idFactory));
- }
- return Promise.all(annotationPromises).then(function (annotations) {
- return annotations.filter(function isDefined(annotation) {
- return !!annotation;
- });
- }, function (reason) {
- (0, _util.warn)('_parsedAnnotations: "' + reason + '".');
- return [];
- });
- });
- return (0, _util.shadow)(this, '_parsedAnnotations', parsedAnnotations);
- }
- };
- return Page;
-}();
-var PDFDocument = function PDFDocumentClosure() {
- var FINGERPRINT_FIRST_BYTES = 1024;
- var EMPTY_FINGERPRINT = '\x00\x00\x00\x00\x00\x00\x00' + '\x00\x00\x00\x00\x00\x00\x00\x00\x00';
- function PDFDocument(pdfManager, arg) {
- var stream;
- if ((0, _primitives.isStream)(arg)) {
- stream = arg;
- } else if ((0, _util.isArrayBuffer)(arg)) {
- stream = new _stream.Stream(arg);
- } else {
- throw new Error('PDFDocument: Unknown argument type');
- }
- if (stream.length <= 0) {
- throw new Error('PDFDocument: stream must have data');
- }
- this.pdfManager = pdfManager;
- this.stream = stream;
- this.xref = new _obj.XRef(stream, pdfManager);
- var evaluatorOptions = pdfManager.evaluatorOptions;
- this.pdfFunctionFactory = new _function.PDFFunctionFactory({
- xref: this.xref,
- isEvalSupported: evaluatorOptions.isEvalSupported
- });
- this._pagePromises = [];
- }
- function find(stream, needle, limit, backwards) {
- var pos = stream.pos;
- var end = stream.end;
- var strBuf = [];
- if (pos + limit > end) {
- limit = end - pos;
- }
- for (var n = 0; n < limit; ++n) {
- strBuf.push(String.fromCharCode(stream.getByte()));
- }
- var str = strBuf.join('');
- stream.pos = pos;
- var index = backwards ? str.lastIndexOf(needle) : str.indexOf(needle);
- if (index === -1) {
- return false;
- }
- stream.pos += index;
- return true;
- }
- var DocumentInfoValidators = {
- Title: _util.isString,
- Author: _util.isString,
- Subject: _util.isString,
- Keywords: _util.isString,
- Creator: _util.isString,
- Producer: _util.isString,
- CreationDate: _util.isString,
- ModDate: _util.isString,
- Trapped: _primitives.isName
- };
- PDFDocument.prototype = {
- parse: function PDFDocument_parse(recoveryMode) {
- this.setup(recoveryMode);
- var version = this.catalog.catDict.get('Version');
- if ((0, _primitives.isName)(version)) {
- this.pdfFormatVersion = version.name;
- }
- try {
- this.acroForm = this.catalog.catDict.get('AcroForm');
- if (this.acroForm) {
- this.xfa = this.acroForm.get('XFA');
- var fields = this.acroForm.get('Fields');
- if ((!fields || !Array.isArray(fields) || fields.length === 0) && !this.xfa) {
- this.acroForm = null;
- }
- }
- } catch (ex) {
- if (ex instanceof _util.MissingDataException) {
- throw ex;
- }
- (0, _util.info)('Something wrong with AcroForm entry');
- this.acroForm = null;
- }
- },
- get linearization() {
- var linearization = null;
- try {
- linearization = _parser.Linearization.create(this.stream);
- } catch (err) {
- if (err instanceof _util.MissingDataException) {
- throw err;
- }
- (0, _util.info)(err);
- }
- return (0, _util.shadow)(this, 'linearization', linearization);
- },
- get startXRef() {
- var stream = this.stream;
- var startXRef = 0;
- var linearization = this.linearization;
- if (linearization) {
- stream.reset();
- if (find(stream, 'endobj', 1024)) {
- startXRef = stream.pos + 6;
- }
- } else {
- var step = 1024;
- var found = false,
- pos = stream.end;
- while (!found && pos > 0) {
- pos -= step - 'startxref'.length;
- if (pos < 0) {
- pos = 0;
- }
- stream.pos = pos;
- found = find(stream, 'startxref', step, true);
- }
- if (found) {
- stream.skip(9);
- var ch;
- do {
- ch = stream.getByte();
- } while ((0, _util.isSpace)(ch));
- var str = '';
- while (ch >= 0x20 && ch <= 0x39) {
- str += String.fromCharCode(ch);
- ch = stream.getByte();
- }
- startXRef = parseInt(str, 10);
- if (isNaN(startXRef)) {
- startXRef = 0;
- }
- }
- }
- return (0, _util.shadow)(this, 'startXRef', startXRef);
- },
- checkHeader: function PDFDocument_checkHeader() {
- var stream = this.stream;
- stream.reset();
- if (find(stream, '%PDF-', 1024)) {
- stream.moveStart();
- var MAX_VERSION_LENGTH = 12;
- var version = '',
- ch;
- while ((ch = stream.getByte()) > 0x20) {
- if (version.length >= MAX_VERSION_LENGTH) {
- break;
- }
- version += String.fromCharCode(ch);
- }
- if (!this.pdfFormatVersion) {
- this.pdfFormatVersion = version.substring(5);
- }
- return;
- }
- },
- parseStartXRef: function PDFDocument_parseStartXRef() {
- var startXRef = this.startXRef;
- this.xref.setStartXRef(startXRef);
- },
- setup: function PDFDocument_setup(recoveryMode) {
- this.xref.parse(recoveryMode);
- this.catalog = new _obj.Catalog(this.pdfManager, this.xref);
- },
- get numPages() {
- var linearization = this.linearization;
- var num = linearization ? linearization.numPages : this.catalog.numPages;
- return (0, _util.shadow)(this, 'numPages', num);
- },
- get documentInfo() {
- var docInfo = {
- PDFFormatVersion: this.pdfFormatVersion,
- IsLinearized: !!this.linearization,
- IsAcroFormPresent: !!this.acroForm,
- IsXFAPresent: !!this.xfa
- };
- var infoDict = void 0;
- try {
- infoDict = this.xref.trailer.get('Info');
- } catch (err) {
- if (err instanceof _util.MissingDataException) {
- throw err;
- }
- (0, _util.info)('The document information dictionary is invalid.');
- }
- if ((0, _primitives.isDict)(infoDict)) {
- for (var key in DocumentInfoValidators) {
- if (infoDict.has(key)) {
- var value = infoDict.get(key);
- if (DocumentInfoValidators[key](value)) {
- docInfo[key] = typeof value !== 'string' ? value : (0, _util.stringToPDFString)(value);
- } else {
- (0, _util.info)('Bad value in document info for "' + key + '"');
- }
- }
- }
- }
- return (0, _util.shadow)(this, 'documentInfo', docInfo);
- },
- get fingerprint() {
- var xref = this.xref,
- hash,
- fileID = '';
- var idArray = xref.trailer.get('ID');
- if (Array.isArray(idArray) && idArray[0] && (0, _util.isString)(idArray[0]) && idArray[0] !== EMPTY_FINGERPRINT) {
- hash = (0, _util.stringToBytes)(idArray[0]);
- } else {
- if (this.stream.ensureRange) {
- this.stream.ensureRange(0, Math.min(FINGERPRINT_FIRST_BYTES, this.stream.end));
- }
- hash = (0, _crypto.calculateMD5)(this.stream.bytes.subarray(0, FINGERPRINT_FIRST_BYTES), 0, FINGERPRINT_FIRST_BYTES);
- }
- for (var i = 0, n = hash.length; i < n; i++) {
- var hex = hash[i].toString(16);
- fileID += hex.length === 1 ? '0' + hex : hex;
- }
- return (0, _util.shadow)(this, 'fingerprint', fileID);
- },
- _getLinearizationPage: function _getLinearizationPage(pageIndex) {
- var catalog = this.catalog,
- linearization = this.linearization;
-
- (0, _util.assert)(linearization && linearization.pageFirst === pageIndex);
- var ref = new _primitives.Ref(linearization.objectNumberFirst, 0);
- return this.xref.fetchAsync(ref).then(function (obj) {
- if ((0, _primitives.isDict)(obj, 'Page') || (0, _primitives.isDict)(obj) && !obj.has('Type') && obj.has('Contents')) {
- if (ref && !catalog.pageKidsCountCache.has(ref)) {
- catalog.pageKidsCountCache.put(ref, 1);
- }
- return [obj, ref];
- }
- throw new _util.FormatError('The Linearization dictionary doesn\'t point ' + 'to a valid Page dictionary.');
- }).catch(function (reason) {
- (0, _util.info)(reason);
- return catalog.getPageDict(pageIndex);
- });
- },
- getPage: function getPage(pageIndex) {
- var _this5 = this;
-
- if (this._pagePromises[pageIndex] !== undefined) {
- return this._pagePromises[pageIndex];
- }
- var catalog = this.catalog,
- linearization = this.linearization;
-
- var promise = linearization && linearization.pageFirst === pageIndex ? this._getLinearizationPage(pageIndex) : catalog.getPageDict(pageIndex);
- return this._pagePromises[pageIndex] = promise.then(function (_ref10) {
- var _ref11 = _slicedToArray(_ref10, 2),
- pageDict = _ref11[0],
- ref = _ref11[1];
-
- return new Page({
- pdfManager: _this5.pdfManager,
- xref: _this5.xref,
- pageIndex: pageIndex,
- pageDict: pageDict,
- ref: ref,
- fontCache: catalog.fontCache,
- builtInCMapCache: catalog.builtInCMapCache,
- pdfFunctionFactory: _this5.pdfFunctionFactory
- });
- });
- },
-
- cleanup: function PDFDocument_cleanup() {
- return this.catalog.cleanup();
- }
- };
- return PDFDocument;
-}();
-exports.Page = Page;
-exports.PDFDocument = PDFDocument;
-
-/***/ }),
-/* 137 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.FileSpec = exports.XRef = exports.ObjectLoader = exports.Catalog = undefined;
-
-var _regenerator = __w_pdfjs_require__(131);
-
-var _regenerator2 = _interopRequireDefault(_regenerator);
-
-var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-var _util = __w_pdfjs_require__(2);
-
-var _primitives = __w_pdfjs_require__(138);
-
-var _parser = __w_pdfjs_require__(139);
-
-var _chunked_stream = __w_pdfjs_require__(135);
-
-var _crypto = __w_pdfjs_require__(150);
-
-var _colorspace = __w_pdfjs_require__(151);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
-
-function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
-
-function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-function fetchDestination(dest) {
- return (0, _primitives.isDict)(dest) ? dest.get('D') : dest;
-}
-
-var Catalog = function () {
- function Catalog(pdfManager, xref) {
- _classCallCheck(this, Catalog);
-
- this.pdfManager = pdfManager;
- this.xref = xref;
- this.catDict = xref.getCatalogObj();
- if (!(0, _primitives.isDict)(this.catDict)) {
- throw new _util.FormatError('Catalog object is not a dictionary.');
- }
- this.fontCache = new _primitives.RefSetCache();
- this.builtInCMapCache = new Map();
- this.pageKidsCountCache = new _primitives.RefSetCache();
- }
-
- _createClass(Catalog, [{
- key: '_readDocumentOutline',
- value: function _readDocumentOutline() {
- var obj = this.catDict.get('Outlines');
- if (!(0, _primitives.isDict)(obj)) {
- return null;
- }
- obj = obj.getRaw('First');
- if (!(0, _primitives.isRef)(obj)) {
- return null;
- }
- var root = { items: [] };
- var queue = [{
- obj: obj,
- parent: root
- }];
- var processed = new _primitives.RefSet();
- processed.put(obj);
- var xref = this.xref,
- blackColor = new Uint8ClampedArray(3);
- while (queue.length > 0) {
- var i = queue.shift();
- var outlineDict = xref.fetchIfRef(i.obj);
- if (outlineDict === null) {
- continue;
- }
- if (!outlineDict.has('Title')) {
- throw new _util.FormatError('Invalid outline item encountered.');
- }
- var data = {
- url: null,
- dest: null
- };
- Catalog.parseDestDictionary({
- destDict: outlineDict,
- resultObj: data,
- docBaseUrl: this.pdfManager.docBaseUrl
- });
- var title = outlineDict.get('Title');
- var flags = outlineDict.get('F') || 0;
- var color = outlineDict.getArray('C');
- var rgbColor = blackColor;
- if (Array.isArray(color) && color.length === 3 && (color[0] !== 0 || color[1] !== 0 || color[2] !== 0)) {
- rgbColor = _colorspace.ColorSpace.singletons.rgb.getRgb(color, 0);
- }
- var outlineItem = {
- dest: data.dest,
- url: data.url,
- unsafeUrl: data.unsafeUrl,
- newWindow: data.newWindow,
- title: (0, _util.stringToPDFString)(title),
- color: rgbColor,
- count: outlineDict.get('Count'),
- bold: !!(flags & 2),
- italic: !!(flags & 1),
- items: []
- };
- i.parent.items.push(outlineItem);
- obj = outlineDict.getRaw('First');
- if ((0, _primitives.isRef)(obj) && !processed.has(obj)) {
- queue.push({
- obj: obj,
- parent: outlineItem
- });
- processed.put(obj);
- }
- obj = outlineDict.getRaw('Next');
- if ((0, _primitives.isRef)(obj) && !processed.has(obj)) {
- queue.push({
- obj: obj,
- parent: i.parent
- });
- processed.put(obj);
- }
- }
- return root.items.length > 0 ? root.items : null;
- }
- }, {
- key: '_readPermissions',
- value: function _readPermissions() {
- var encrypt = this.xref.trailer.get('Encrypt');
- if (!(0, _primitives.isDict)(encrypt)) {
- return null;
- }
- var flags = encrypt.get('P');
- if (!(0, _util.isNum)(flags)) {
- return null;
- }
- flags += Math.pow(2, 32);
- var permissions = [];
- for (var key in _util.PermissionFlag) {
- var value = _util.PermissionFlag[key];
- if (flags & value) {
- permissions.push(value);
- }
- }
- return permissions;
- }
- }, {
- key: 'getDestination',
- value: function getDestination(destinationId) {
- var obj = this._readDests();
- if (obj instanceof NameTree || obj instanceof _primitives.Dict) {
- return fetchDestination(obj.get(destinationId) || null);
- }
- return null;
- }
- }, {
- key: '_readDests',
- value: function _readDests() {
- var obj = this.catDict.get('Names');
- if (obj && obj.has('Dests')) {
- return new NameTree(obj.getRaw('Dests'), this.xref);
- } else if (this.catDict.has('Dests')) {
- return this.catDict.get('Dests');
- }
- }
- }, {
- key: '_readPageLabels',
- value: function _readPageLabels() {
- var obj = this.catDict.getRaw('PageLabels');
- if (!obj) {
- return null;
- }
- var pageLabels = new Array(this.numPages);
- var style = null,
- prefix = '';
- var numberTree = new NumberTree(obj, this.xref);
- var nums = numberTree.getAll();
- var currentLabel = '',
- currentIndex = 1;
- for (var i = 0, ii = this.numPages; i < ii; i++) {
- if (i in nums) {
- var labelDict = nums[i];
- if (!(0, _primitives.isDict)(labelDict)) {
- throw new _util.FormatError('PageLabel is not a dictionary.');
- }
- if (labelDict.has('Type') && !(0, _primitives.isName)(labelDict.get('Type'), 'PageLabel')) {
- throw new _util.FormatError('Invalid type in PageLabel dictionary.');
- }
- if (labelDict.has('S')) {
- var s = labelDict.get('S');
- if (!(0, _primitives.isName)(s)) {
- throw new _util.FormatError('Invalid style in PageLabel dictionary.');
- }
- style = s.name;
- } else {
- style = null;
- }
- if (labelDict.has('P')) {
- var p = labelDict.get('P');
- if (!(0, _util.isString)(p)) {
- throw new _util.FormatError('Invalid prefix in PageLabel dictionary.');
- }
- prefix = (0, _util.stringToPDFString)(p);
- } else {
- prefix = '';
- }
- if (labelDict.has('St')) {
- var st = labelDict.get('St');
- if (!(Number.isInteger(st) && st >= 1)) {
- throw new _util.FormatError('Invalid start in PageLabel dictionary.');
- }
- currentIndex = st;
- } else {
- currentIndex = 1;
- }
- }
- switch (style) {
- case 'D':
- currentLabel = currentIndex;
- break;
- case 'R':
- case 'r':
- currentLabel = (0, _util.toRomanNumerals)(currentIndex, style === 'r');
- break;
- case 'A':
- case 'a':
- var LIMIT = 26;
- var A_UPPER_CASE = 0x41,
- A_LOWER_CASE = 0x61;
- var baseCharCode = style === 'a' ? A_LOWER_CASE : A_UPPER_CASE;
- var letterIndex = currentIndex - 1;
- var character = String.fromCharCode(baseCharCode + letterIndex % LIMIT);
- var charBuf = [];
- for (var j = 0, jj = letterIndex / LIMIT | 0; j <= jj; j++) {
- charBuf.push(character);
- }
- currentLabel = charBuf.join('');
- break;
- default:
- if (style) {
- throw new _util.FormatError('Invalid style "' + style + '" in PageLabel dictionary.');
- }
- currentLabel = '';
- }
- pageLabels[i] = prefix + currentLabel;
- currentIndex++;
- }
- return pageLabels;
- }
- }, {
- key: 'cleanup',
- value: function cleanup() {
- var _this = this;
-
- this.pageKidsCountCache.clear();
- var promises = [];
- this.fontCache.forEach(function (promise) {
- promises.push(promise);
- });
- return Promise.all(promises).then(function (translatedFonts) {
- for (var i = 0, ii = translatedFonts.length; i < ii; i++) {
- var font = translatedFonts[i].dict;
- delete font.translated;
- }
- _this.fontCache.clear();
- _this.builtInCMapCache.clear();
- });
- }
- }, {
- key: 'getPageDict',
- value: function getPageDict(pageIndex) {
- var capability = (0, _util.createPromiseCapability)();
- var nodesToVisit = [this.catDict.getRaw('Pages')];
- var xref = this.xref,
- pageKidsCountCache = this.pageKidsCountCache;
- var count = void 0,
- currentPageIndex = 0;
- function next() {
- var _loop = function _loop() {
- var currentNode = nodesToVisit.pop();
- if ((0, _primitives.isRef)(currentNode)) {
- count = pageKidsCountCache.get(currentNode);
- if (count > 0 && currentPageIndex + count < pageIndex) {
- currentPageIndex += count;
- return 'continue';
- }
- xref.fetchAsync(currentNode).then(function (obj) {
- if ((0, _primitives.isDict)(obj, 'Page') || (0, _primitives.isDict)(obj) && !obj.has('Kids')) {
- if (pageIndex === currentPageIndex) {
- if (currentNode && !pageKidsCountCache.has(currentNode)) {
- pageKidsCountCache.put(currentNode, 1);
- }
- capability.resolve([obj, currentNode]);
- } else {
- currentPageIndex++;
- next();
- }
- return;
- }
- nodesToVisit.push(obj);
- next();
- }, capability.reject);
- return {
- v: void 0
- };
- }
- if (!(0, _primitives.isDict)(currentNode)) {
- capability.reject(new _util.FormatError('Page dictionary kid reference points to wrong type of object.'));
- return {
- v: void 0
- };
- }
- count = currentNode.get('Count');
- if (Number.isInteger(count) && count >= 0) {
- var objId = currentNode.objId;
- if (objId && !pageKidsCountCache.has(objId)) {
- pageKidsCountCache.put(objId, count);
- }
- if (currentPageIndex + count <= pageIndex) {
- currentPageIndex += count;
- return 'continue';
- }
- }
- var kids = currentNode.get('Kids');
- if (!Array.isArray(kids)) {
- if ((0, _primitives.isName)(currentNode.get('Type'), 'Page') || !currentNode.has('Type') && currentNode.has('Contents')) {
- if (currentPageIndex === pageIndex) {
- capability.resolve([currentNode, null]);
- return {
- v: void 0
- };
- }
- currentPageIndex++;
- return 'continue';
- }
- capability.reject(new _util.FormatError('Page dictionary kids object is not an array.'));
- return {
- v: void 0
- };
- }
- for (var last = kids.length - 1; last >= 0; last--) {
- nodesToVisit.push(kids[last]);
- }
- };
-
- while (nodesToVisit.length) {
- var _ret = _loop();
-
- switch (_ret) {
- case 'continue':
- continue;
-
- default:
- if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v;
- }
- }
- capability.reject(new Error('Page index ' + pageIndex + ' not found.'));
- }
- next();
- return capability.promise;
- }
- }, {
- key: 'getPageIndex',
- value: function getPageIndex(pageRef) {
- var xref = this.xref;
- function pagesBeforeRef(kidRef) {
- var total = 0,
- parentRef = void 0;
- return xref.fetchAsync(kidRef).then(function (node) {
- if ((0, _primitives.isRefsEqual)(kidRef, pageRef) && !(0, _primitives.isDict)(node, 'Page') && !((0, _primitives.isDict)(node) && !node.has('Type') && node.has('Contents'))) {
- throw new _util.FormatError('The reference does not point to a /Page dictionary.');
- }
- if (!node) {
- return null;
- }
- if (!(0, _primitives.isDict)(node)) {
- throw new _util.FormatError('Node must be a dictionary.');
- }
- parentRef = node.getRaw('Parent');
- return node.getAsync('Parent');
- }).then(function (parent) {
- if (!parent) {
- return null;
- }
- if (!(0, _primitives.isDict)(parent)) {
- throw new _util.FormatError('Parent must be a dictionary.');
- }
- return parent.getAsync('Kids');
- }).then(function (kids) {
- if (!kids) {
- return null;
- }
- var kidPromises = [];
- var found = false;
- for (var i = 0, ii = kids.length; i < ii; i++) {
- var kid = kids[i];
- if (!(0, _primitives.isRef)(kid)) {
- throw new _util.FormatError('Kid must be a reference.');
- }
- if ((0, _primitives.isRefsEqual)(kid, kidRef)) {
- found = true;
- break;
- }
- kidPromises.push(xref.fetchAsync(kid).then(function (kid) {
- if (!(0, _primitives.isDict)(kid)) {
- throw new _util.FormatError('Kid node must be a dictionary.');
- }
- if (kid.has('Count')) {
- total += kid.get('Count');
- } else {
- total++;
- }
- }));
- }
- if (!found) {
- throw new _util.FormatError('Kid reference not found in parent\'s kids.');
- }
- return Promise.all(kidPromises).then(function () {
- return [total, parentRef];
- });
- });
- }
- var total = 0;
- function next(ref) {
- return pagesBeforeRef(ref).then(function (args) {
- if (!args) {
- return total;
- }
-
- var _args = _slicedToArray(args, 2),
- count = _args[0],
- parentRef = _args[1];
-
- total += count;
- return next(parentRef);
- });
- }
- return next(pageRef);
- }
- }, {
- key: 'metadata',
- get: function get() {
- var streamRef = this.catDict.getRaw('Metadata');
- if (!(0, _primitives.isRef)(streamRef)) {
- return (0, _util.shadow)(this, 'metadata', null);
- }
- var suppressEncryption = !(this.xref.encrypt && this.xref.encrypt.encryptMetadata);
- var stream = this.xref.fetch(streamRef, suppressEncryption);
- var metadata = void 0;
- if (stream && (0, _primitives.isDict)(stream.dict)) {
- var type = stream.dict.get('Type');
- var subtype = stream.dict.get('Subtype');
- if ((0, _primitives.isName)(type, 'Metadata') && (0, _primitives.isName)(subtype, 'XML')) {
- try {
- metadata = (0, _util.stringToUTF8String)((0, _util.bytesToString)(stream.getBytes()));
- } catch (e) {
- if (e instanceof _util.MissingDataException) {
- throw e;
- }
- (0, _util.info)('Skipping invalid metadata.');
- }
- }
- }
- return (0, _util.shadow)(this, 'metadata', metadata);
- }
- }, {
- key: 'toplevelPagesDict',
- get: function get() {
- var pagesObj = this.catDict.get('Pages');
- if (!(0, _primitives.isDict)(pagesObj)) {
- throw new _util.FormatError('Invalid top-level pages dictionary.');
- }
- return (0, _util.shadow)(this, 'toplevelPagesDict', pagesObj);
- }
- }, {
- key: 'documentOutline',
- get: function get() {
- var obj = null;
- try {
- obj = this._readDocumentOutline();
- } catch (ex) {
- if (ex instanceof _util.MissingDataException) {
- throw ex;
- }
- (0, _util.warn)('Unable to read document outline.');
- }
- return (0, _util.shadow)(this, 'documentOutline', obj);
- }
- }, {
- key: 'permissions',
- get: function get() {
- var permissions = null;
- try {
- permissions = this._readPermissions();
- } catch (ex) {
- if (ex instanceof _util.MissingDataException) {
- throw ex;
- }
- (0, _util.warn)('Unable to read permissions.');
- }
- return (0, _util.shadow)(this, 'permissions', permissions);
- }
- }, {
- key: 'numPages',
- get: function get() {
- var obj = this.toplevelPagesDict.get('Count');
- if (!Number.isInteger(obj)) {
- throw new _util.FormatError('Page count in top-level pages dictionary is not an integer.');
- }
- return (0, _util.shadow)(this, 'numPages', obj);
- }
- }, {
- key: 'destinations',
- get: function get() {
- var obj = this._readDests(),
- dests = Object.create(null);
- if (obj instanceof NameTree) {
- var names = obj.getAll();
- for (var name in names) {
- dests[name] = fetchDestination(names[name]);
- }
- } else if (obj instanceof _primitives.Dict) {
- obj.forEach(function (key, value) {
- if (value) {
- dests[key] = fetchDestination(value);
- }
- });
- }
- return (0, _util.shadow)(this, 'destinations', dests);
- }
- }, {
- key: 'pageLabels',
- get: function get() {
- var obj = null;
- try {
- obj = this._readPageLabels();
- } catch (ex) {
- if (ex instanceof _util.MissingDataException) {
- throw ex;
- }
- (0, _util.warn)('Unable to read page labels.');
- }
- return (0, _util.shadow)(this, 'pageLabels', obj);
- }
- }, {
- key: 'pageMode',
- get: function get() {
- var obj = this.catDict.get('PageMode');
- var pageMode = 'UseNone';
- if ((0, _primitives.isName)(obj)) {
- switch (obj.name) {
- case 'UseNone':
- case 'UseOutlines':
- case 'UseThumbs':
- case 'FullScreen':
- case 'UseOC':
- case 'UseAttachments':
- pageMode = obj.name;
- }
- }
- return (0, _util.shadow)(this, 'pageMode', pageMode);
- }
- }, {
- key: 'attachments',
- get: function get() {
- var obj = this.catDict.get('Names');
- var attachments = null;
- if (obj && obj.has('EmbeddedFiles')) {
- var nameTree = new NameTree(obj.getRaw('EmbeddedFiles'), this.xref);
- var names = nameTree.getAll();
- for (var name in names) {
- var fs = new FileSpec(names[name], this.xref);
- if (!attachments) {
- attachments = Object.create(null);
- }
- attachments[(0, _util.stringToPDFString)(name)] = fs.serializable;
- }
- }
- return (0, _util.shadow)(this, 'attachments', attachments);
- }
- }, {
- key: 'javaScript',
- get: function get() {
- var obj = this.catDict.get('Names');
- var javaScript = null;
- function appendIfJavaScriptDict(jsDict) {
- var type = jsDict.get('S');
- if (!(0, _primitives.isName)(type, 'JavaScript')) {
- return;
- }
- var js = jsDict.get('JS');
- if ((0, _primitives.isStream)(js)) {
- js = (0, _util.bytesToString)(js.getBytes());
- } else if (!(0, _util.isString)(js)) {
- return;
- }
- if (!javaScript) {
- javaScript = [];
- }
- javaScript.push((0, _util.stringToPDFString)(js));
- }
- if (obj && obj.has('JavaScript')) {
- var nameTree = new NameTree(obj.getRaw('JavaScript'), this.xref);
- var names = nameTree.getAll();
- for (var name in names) {
- var jsDict = names[name];
- if ((0, _primitives.isDict)(jsDict)) {
- appendIfJavaScriptDict(jsDict);
- }
- }
- }
- var openActionDict = this.catDict.get('OpenAction');
- if ((0, _primitives.isDict)(openActionDict, 'Action')) {
- var actionType = openActionDict.get('S');
- if ((0, _primitives.isName)(actionType, 'Named')) {
- var action = openActionDict.get('N');
- if ((0, _primitives.isName)(action, 'Print')) {
- if (!javaScript) {
- javaScript = [];
- }
- javaScript.push('print({});');
- }
- } else {
- appendIfJavaScriptDict(openActionDict);
- }
- }
- return (0, _util.shadow)(this, 'javaScript', javaScript);
- }
- }], [{
- key: 'parseDestDictionary',
- value: function parseDestDictionary(params) {
- function addDefaultProtocolToUrl(url) {
- if (url.indexOf('www.') === 0) {
- return 'http://' + url;
- }
- return url;
- }
- function tryConvertUrlEncoding(url) {
- try {
- return (0, _util.stringToUTF8String)(url);
- } catch (e) {
- return url;
- }
- }
- var destDict = params.destDict;
- if (!(0, _primitives.isDict)(destDict)) {
- (0, _util.warn)('parseDestDictionary: `destDict` must be a dictionary.');
- return;
- }
- var resultObj = params.resultObj;
- if ((typeof resultObj === 'undefined' ? 'undefined' : _typeof(resultObj)) !== 'object') {
- (0, _util.warn)('parseDestDictionary: `resultObj` must be an object.');
- return;
- }
- var docBaseUrl = params.docBaseUrl || null;
- var action = destDict.get('A'),
- url = void 0,
- dest = void 0;
- if (!(0, _primitives.isDict)(action) && destDict.has('Dest')) {
- action = destDict.get('Dest');
- }
- if ((0, _primitives.isDict)(action)) {
- var actionType = action.get('S');
- if (!(0, _primitives.isName)(actionType)) {
- (0, _util.warn)('parseDestDictionary: Invalid type in Action dictionary.');
- return;
- }
- var actionName = actionType.name;
- switch (actionName) {
- case 'URI':
- url = action.get('URI');
- if ((0, _primitives.isName)(url)) {
- url = '/' + url.name;
- } else if ((0, _util.isString)(url)) {
- url = addDefaultProtocolToUrl(url);
- }
- break;
- case 'GoTo':
- dest = action.get('D');
- break;
- case 'Launch':
- case 'GoToR':
- var urlDict = action.get('F');
- if ((0, _primitives.isDict)(urlDict)) {
- url = urlDict.get('F') || null;
- } else if ((0, _util.isString)(urlDict)) {
- url = urlDict;
- }
- var remoteDest = action.get('D');
- if (remoteDest) {
- if ((0, _primitives.isName)(remoteDest)) {
- remoteDest = remoteDest.name;
- }
- if ((0, _util.isString)(url)) {
- var baseUrl = url.split('#')[0];
- if ((0, _util.isString)(remoteDest)) {
- url = baseUrl + '#' + remoteDest;
- } else if (Array.isArray(remoteDest)) {
- url = baseUrl + '#' + JSON.stringify(remoteDest);
- }
- }
- }
- var newWindow = action.get('NewWindow');
- if ((0, _util.isBool)(newWindow)) {
- resultObj.newWindow = newWindow;
- }
- break;
- case 'Named':
- var namedAction = action.get('N');
- if ((0, _primitives.isName)(namedAction)) {
- resultObj.action = namedAction.name;
- }
- break;
- case 'JavaScript':
- var jsAction = action.get('JS');
- var js = void 0;
- if ((0, _primitives.isStream)(jsAction)) {
- js = (0, _util.bytesToString)(jsAction.getBytes());
- } else if ((0, _util.isString)(jsAction)) {
- js = jsAction;
- }
- if (js) {
- var URL_OPEN_METHODS = ['app.launchURL', 'window.open'];
- var regex = new RegExp('^\\s*(' + URL_OPEN_METHODS.join('|').split('.').join('\\.') + ')\\((?:\'|\")([^\'\"]*)(?:\'|\")(?:,\\s*(\\w+)\\)|\\))', 'i');
- var jsUrl = regex.exec((0, _util.stringToPDFString)(js));
- if (jsUrl && jsUrl[2]) {
- url = jsUrl[2];
- if (jsUrl[3] === 'true' && jsUrl[1] === 'app.launchURL') {
- resultObj.newWindow = true;
- }
- break;
- }
- }
- default:
- (0, _util.warn)('parseDestDictionary: unsupported action type "' + actionName + '".');
- break;
- }
- } else if (destDict.has('Dest')) {
- dest = destDict.get('Dest');
- }
- if ((0, _util.isString)(url)) {
- url = tryConvertUrlEncoding(url);
- var absoluteUrl = (0, _util.createValidAbsoluteUrl)(url, docBaseUrl);
- if (absoluteUrl) {
- resultObj.url = absoluteUrl.href;
- }
- resultObj.unsafeUrl = url;
- }
- if (dest) {
- if ((0, _primitives.isName)(dest)) {
- dest = dest.name;
- }
- if ((0, _util.isString)(dest) || Array.isArray(dest)) {
- resultObj.dest = dest;
- }
- }
- }
- }]);
-
- return Catalog;
-}();
-
-var XRef = function XRefClosure() {
- function XRef(stream, pdfManager) {
- this.stream = stream;
- this.pdfManager = pdfManager;
- this.entries = [];
- this.xrefstms = Object.create(null);
- this.cache = [];
- this.stats = {
- streamTypes: [],
- fontTypes: []
- };
- }
- XRef.prototype = {
- setStartXRef: function XRef_setStartXRef(startXRef) {
- this.startXRefQueue = [startXRef];
- },
- parse: function XRef_parse(recoveryMode) {
- var trailerDict;
- if (!recoveryMode) {
- trailerDict = this.readXRef();
- } else {
- (0, _util.warn)('Indexing all PDF objects');
- trailerDict = this.indexObjects();
- }
- trailerDict.assignXref(this);
- this.trailer = trailerDict;
- var encrypt = void 0;
- try {
- encrypt = trailerDict.get('Encrypt');
- } catch (ex) {
- if (ex instanceof _util.MissingDataException) {
- throw ex;
- }
- (0, _util.warn)('XRef.parse - Invalid "Encrypt" reference: "' + ex + '".');
- }
- if ((0, _primitives.isDict)(encrypt)) {
- var ids = trailerDict.get('ID');
- var fileId = ids && ids.length ? ids[0] : '';
- encrypt.suppressEncryption = true;
- this.encrypt = new _crypto.CipherTransformFactory(encrypt, fileId, this.pdfManager.password);
- }
- var root = void 0;
- try {
- root = trailerDict.get('Root');
- } catch (ex) {
- if (ex instanceof _util.MissingDataException) {
- throw ex;
- }
- (0, _util.warn)('XRef.parse - Invalid "Root" reference: "' + ex + '".');
- }
- if ((0, _primitives.isDict)(root) && root.has('Pages')) {
- this.root = root;
- } else {
- if (!recoveryMode) {
- throw new _util.XRefParseException();
- }
- throw new _util.FormatError('Invalid root reference');
- }
- },
- processXRefTable: function XRef_processXRefTable(parser) {
- if (!('tableState' in this)) {
- this.tableState = {
- entryNum: 0,
- streamPos: parser.lexer.stream.pos,
- parserBuf1: parser.buf1,
- parserBuf2: parser.buf2
- };
- }
- var obj = this.readXRefTable(parser);
- if (!(0, _primitives.isCmd)(obj, 'trailer')) {
- throw new _util.FormatError('Invalid XRef table: could not find trailer dictionary');
- }
- var dict = parser.getObj();
- if (!(0, _primitives.isDict)(dict) && dict.dict) {
- dict = dict.dict;
- }
- if (!(0, _primitives.isDict)(dict)) {
- throw new _util.FormatError('Invalid XRef table: could not parse trailer dictionary');
- }
- delete this.tableState;
- return dict;
- },
- readXRefTable: function XRef_readXRefTable(parser) {
- var stream = parser.lexer.stream;
- var tableState = this.tableState;
- stream.pos = tableState.streamPos;
- parser.buf1 = tableState.parserBuf1;
- parser.buf2 = tableState.parserBuf2;
- var obj;
- while (true) {
- if (!('firstEntryNum' in tableState) || !('entryCount' in tableState)) {
- if ((0, _primitives.isCmd)(obj = parser.getObj(), 'trailer')) {
- break;
- }
- tableState.firstEntryNum = obj;
- tableState.entryCount = parser.getObj();
- }
- var first = tableState.firstEntryNum;
- var count = tableState.entryCount;
- if (!Number.isInteger(first) || !Number.isInteger(count)) {
- throw new _util.FormatError('Invalid XRef table: wrong types in subsection header');
- }
- for (var i = tableState.entryNum; i < count; i++) {
- tableState.streamPos = stream.pos;
- tableState.entryNum = i;
- tableState.parserBuf1 = parser.buf1;
- tableState.parserBuf2 = parser.buf2;
- var entry = {};
- entry.offset = parser.getObj();
- entry.gen = parser.getObj();
- var type = parser.getObj();
- if ((0, _primitives.isCmd)(type, 'f')) {
- entry.free = true;
- } else if ((0, _primitives.isCmd)(type, 'n')) {
- entry.uncompressed = true;
- }
- if (!Number.isInteger(entry.offset) || !Number.isInteger(entry.gen) || !(entry.free || entry.uncompressed)) {
- throw new _util.FormatError('Invalid entry in XRef subsection: ' + first + ', ' + count);
- }
- if (i === 0 && entry.free && first === 1) {
- first = 0;
- }
- if (!this.entries[i + first]) {
- this.entries[i + first] = entry;
- }
- }
- tableState.entryNum = 0;
- tableState.streamPos = stream.pos;
- tableState.parserBuf1 = parser.buf1;
- tableState.parserBuf2 = parser.buf2;
- delete tableState.firstEntryNum;
- delete tableState.entryCount;
- }
- if (this.entries[0] && !this.entries[0].free) {
- throw new _util.FormatError('Invalid XRef table: unexpected first object');
- }
- return obj;
- },
- processXRefStream: function XRef_processXRefStream(stream) {
- if (!('streamState' in this)) {
- var streamParameters = stream.dict;
- var byteWidths = streamParameters.get('W');
- var range = streamParameters.get('Index');
- if (!range) {
- range = [0, streamParameters.get('Size')];
- }
- this.streamState = {
- entryRanges: range,
- byteWidths: byteWidths,
- entryNum: 0,
- streamPos: stream.pos
- };
- }
- this.readXRefStream(stream);
- delete this.streamState;
- return stream.dict;
- },
- readXRefStream: function XRef_readXRefStream(stream) {
- var i, j;
- var streamState = this.streamState;
- stream.pos = streamState.streamPos;
- var byteWidths = streamState.byteWidths;
- var typeFieldWidth = byteWidths[0];
- var offsetFieldWidth = byteWidths[1];
- var generationFieldWidth = byteWidths[2];
- var entryRanges = streamState.entryRanges;
- while (entryRanges.length > 0) {
- var first = entryRanges[0];
- var n = entryRanges[1];
- if (!Number.isInteger(first) || !Number.isInteger(n)) {
- throw new _util.FormatError('Invalid XRef range fields: ' + first + ', ' + n);
- }
- if (!Number.isInteger(typeFieldWidth) || !Number.isInteger(offsetFieldWidth) || !Number.isInteger(generationFieldWidth)) {
- throw new _util.FormatError('Invalid XRef entry fields length: ' + first + ', ' + n);
- }
- for (i = streamState.entryNum; i < n; ++i) {
- streamState.entryNum = i;
- streamState.streamPos = stream.pos;
- var type = 0,
- offset = 0,
- generation = 0;
- for (j = 0; j < typeFieldWidth; ++j) {
- type = type << 8 | stream.getByte();
- }
- if (typeFieldWidth === 0) {
- type = 1;
- }
- for (j = 0; j < offsetFieldWidth; ++j) {
- offset = offset << 8 | stream.getByte();
- }
- for (j = 0; j < generationFieldWidth; ++j) {
- generation = generation << 8 | stream.getByte();
- }
- var entry = {};
- entry.offset = offset;
- entry.gen = generation;
- switch (type) {
- case 0:
- entry.free = true;
- break;
- case 1:
- entry.uncompressed = true;
- break;
- case 2:
- break;
- default:
- throw new _util.FormatError('Invalid XRef entry type: ' + type);
- }
- if (!this.entries[first + i]) {
- this.entries[first + i] = entry;
- }
- }
- streamState.entryNum = 0;
- streamState.streamPos = stream.pos;
- entryRanges.splice(0, 2);
- }
- },
- indexObjects: function XRef_indexObjects() {
- var TAB = 0x9,
- LF = 0xA,
- CR = 0xD,
- SPACE = 0x20;
- var PERCENT = 0x25,
- LT = 0x3C;
- function readToken(data, offset) {
- var token = '',
- ch = data[offset];
- while (ch !== LF && ch !== CR && ch !== LT) {
- if (++offset >= data.length) {
- break;
- }
- token += String.fromCharCode(ch);
- ch = data[offset];
- }
- return token;
- }
- function skipUntil(data, offset, what) {
- var length = what.length,
- dataLength = data.length;
- var skipped = 0;
- while (offset < dataLength) {
- var i = 0;
- while (i < length && data[offset + i] === what[i]) {
- ++i;
- }
- if (i >= length) {
- break;
- }
- offset++;
- skipped++;
- }
- return skipped;
- }
- var objRegExp = /^(\d+)\s+(\d+)\s+obj\b/;
- var endobjRegExp = /\bendobj[\b\s]$/;
- var nestedObjRegExp = /\s+(\d+\s+\d+\s+obj[\b\s])$/;
- var CHECK_CONTENT_LENGTH = 25;
- var trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]);
- var startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114, 101, 102]);
- var objBytes = new Uint8Array([111, 98, 106]);
- var xrefBytes = new Uint8Array([47, 88, 82, 101, 102]);
- this.entries.length = 0;
- var stream = this.stream;
- stream.pos = 0;
- var buffer = stream.getBytes();
- var position = stream.start,
- length = buffer.length;
- var trailers = [],
- xrefStms = [];
- while (position < length) {
- var ch = buffer[position];
- if (ch === TAB || ch === LF || ch === CR || ch === SPACE) {
- ++position;
- continue;
- }
- if (ch === PERCENT) {
- do {
- ++position;
- if (position >= length) {
- break;
- }
- ch = buffer[position];
- } while (ch !== LF && ch !== CR);
- continue;
- }
- var token = readToken(buffer, position);
- var m;
- if (token.indexOf('xref') === 0 && (token.length === 4 || /\s/.test(token[4]))) {
- position += skipUntil(buffer, position, trailerBytes);
- trailers.push(position);
- position += skipUntil(buffer, position, startxrefBytes);
- } else if (m = objRegExp.exec(token)) {
- if (typeof this.entries[m[1]] === 'undefined') {
- this.entries[m[1]] = {
- offset: position - stream.start,
- gen: m[2] | 0,
- uncompressed: true
- };
- }
- var contentLength = void 0,
- startPos = position + token.length;
- while (startPos < buffer.length) {
- var endPos = startPos + skipUntil(buffer, startPos, objBytes) + 4;
- contentLength = endPos - position;
- var checkPos = Math.max(endPos - CHECK_CONTENT_LENGTH, startPos);
- var tokenStr = (0, _util.bytesToString)(buffer.subarray(checkPos, endPos));
- if (endobjRegExp.test(tokenStr)) {
- break;
- } else {
- var objToken = nestedObjRegExp.exec(tokenStr);
- if (objToken && objToken[1]) {
- (0, _util.warn)('indexObjects: Found new "obj" inside of another "obj", ' + 'caused by missing "endobj" -- trying to recover.');
- contentLength -= objToken[1].length;
- break;
- }
- }
- startPos = endPos;
- }
- var content = buffer.subarray(position, position + contentLength);
- var xrefTagOffset = skipUntil(content, 0, xrefBytes);
- if (xrefTagOffset < contentLength && content[xrefTagOffset + 5] < 64) {
- xrefStms.push(position - stream.start);
- this.xrefstms[position - stream.start] = 1;
- }
- position += contentLength;
- } else if (token.indexOf('trailer') === 0 && (token.length === 7 || /\s/.test(token[7]))) {
- trailers.push(position);
- position += skipUntil(buffer, position, startxrefBytes);
- } else {
- position += token.length + 1;
- }
- }
- var i, ii;
- for (i = 0, ii = xrefStms.length; i < ii; ++i) {
- this.startXRefQueue.push(xrefStms[i]);
- this.readXRef(true);
- }
- var trailerDict = void 0;
- for (i = 0, ii = trailers.length; i < ii; ++i) {
- stream.pos = trailers[i];
- var parser = new _parser.Parser(new _parser.Lexer(stream), true, this, true);
- var obj = parser.getObj();
- if (!(0, _primitives.isCmd)(obj, 'trailer')) {
- continue;
- }
- var dict = parser.getObj();
- if (!(0, _primitives.isDict)(dict)) {
- continue;
- }
- var rootDict = void 0;
- try {
- rootDict = dict.get('Root');
- } catch (ex) {
- if (ex instanceof _util.MissingDataException) {
- throw ex;
- }
- continue;
- }
- if (!(0, _primitives.isDict)(rootDict) || !rootDict.has('Pages')) {
- continue;
- }
- if (dict.has('ID')) {
- return dict;
- }
- trailerDict = dict;
- }
- if (trailerDict) {
- return trailerDict;
- }
- throw new _util.InvalidPDFException('Invalid PDF structure');
- },
- readXRef: function XRef_readXRef(recoveryMode) {
- var stream = this.stream;
- var startXRefParsedCache = Object.create(null);
- try {
- while (this.startXRefQueue.length) {
- var startXRef = this.startXRefQueue[0];
- if (startXRefParsedCache[startXRef]) {
- (0, _util.warn)('readXRef - skipping XRef table since it was already parsed.');
- this.startXRefQueue.shift();
- continue;
- }
- startXRefParsedCache[startXRef] = true;
- stream.pos = startXRef + stream.start;
- var parser = new _parser.Parser(new _parser.Lexer(stream), true, this);
- var obj = parser.getObj();
- var dict;
- if ((0, _primitives.isCmd)(obj, 'xref')) {
- dict = this.processXRefTable(parser);
- if (!this.topDict) {
- this.topDict = dict;
- }
- obj = dict.get('XRefStm');
- if (Number.isInteger(obj)) {
- var pos = obj;
- if (!(pos in this.xrefstms)) {
- this.xrefstms[pos] = 1;
- this.startXRefQueue.push(pos);
- }
- }
- } else if (Number.isInteger(obj)) {
- if (!Number.isInteger(parser.getObj()) || !(0, _primitives.isCmd)(parser.getObj(), 'obj') || !(0, _primitives.isStream)(obj = parser.getObj())) {
- throw new _util.FormatError('Invalid XRef stream');
- }
- dict = this.processXRefStream(obj);
- if (!this.topDict) {
- this.topDict = dict;
- }
- if (!dict) {
- throw new _util.FormatError('Failed to read XRef stream');
- }
- } else {
- throw new _util.FormatError('Invalid XRef stream header');
- }
- obj = dict.get('Prev');
- if (Number.isInteger(obj)) {
- this.startXRefQueue.push(obj);
- } else if ((0, _primitives.isRef)(obj)) {
- this.startXRefQueue.push(obj.num);
- }
- this.startXRefQueue.shift();
- }
- return this.topDict;
- } catch (e) {
- if (e instanceof _util.MissingDataException) {
- throw e;
- }
- (0, _util.info)('(while reading XRef): ' + e);
- }
- if (recoveryMode) {
- return;
- }
- throw new _util.XRefParseException();
- },
- getEntry: function XRef_getEntry(i) {
- var xrefEntry = this.entries[i];
- if (xrefEntry && !xrefEntry.free && xrefEntry.offset) {
- return xrefEntry;
- }
- return null;
- },
- fetchIfRef: function XRef_fetchIfRef(obj, suppressEncryption) {
- if (!(0, _primitives.isRef)(obj)) {
- return obj;
- }
- return this.fetch(obj, suppressEncryption);
- },
- fetch: function XRef_fetch(ref, suppressEncryption) {
- if (!(0, _primitives.isRef)(ref)) {
- throw new Error('ref object is not a reference');
- }
- var num = ref.num;
- if (num in this.cache) {
- var cacheEntry = this.cache[num];
- if (cacheEntry instanceof _primitives.Dict && !cacheEntry.objId) {
- cacheEntry.objId = ref.toString();
- }
- return cacheEntry;
- }
- var xrefEntry = this.getEntry(num);
- if (xrefEntry === null) {
- return this.cache[num] = null;
- }
- if (xrefEntry.uncompressed) {
- xrefEntry = this.fetchUncompressed(ref, xrefEntry, suppressEncryption);
- } else {
- xrefEntry = this.fetchCompressed(xrefEntry, suppressEncryption);
- }
- if ((0, _primitives.isDict)(xrefEntry)) {
- xrefEntry.objId = ref.toString();
- } else if ((0, _primitives.isStream)(xrefEntry)) {
- xrefEntry.dict.objId = ref.toString();
- }
- return xrefEntry;
- },
- fetchUncompressed: function XRef_fetchUncompressed(ref, xrefEntry, suppressEncryption) {
- var gen = ref.gen;
- var num = ref.num;
- if (xrefEntry.gen !== gen) {
- throw new _util.FormatError('inconsistent generation in XRef');
- }
- var stream = this.stream.makeSubStream(xrefEntry.offset + this.stream.start);
- var parser = new _parser.Parser(new _parser.Lexer(stream), true, this);
- var obj1 = parser.getObj();
- var obj2 = parser.getObj();
- var obj3 = parser.getObj();
- if (!Number.isInteger(obj1)) {
- obj1 = parseInt(obj1, 10);
- }
- if (!Number.isInteger(obj2)) {
- obj2 = parseInt(obj2, 10);
- }
- if (obj1 !== num || obj2 !== gen || !(0, _primitives.isCmd)(obj3)) {
- throw new _util.FormatError('bad XRef entry');
- }
- if (obj3.cmd !== 'obj') {
- if (obj3.cmd.indexOf('obj') === 0) {
- num = parseInt(obj3.cmd.substring(3), 10);
- if (!Number.isNaN(num)) {
- return num;
- }
- }
- throw new _util.FormatError('bad XRef entry');
- }
- if (this.encrypt && !suppressEncryption) {
- xrefEntry = parser.getObj(this.encrypt.createCipherTransform(num, gen));
- } else {
- xrefEntry = parser.getObj();
- }
- if (!(0, _primitives.isStream)(xrefEntry)) {
- this.cache[num] = xrefEntry;
- }
- return xrefEntry;
- },
- fetchCompressed: function XRef_fetchCompressed(xrefEntry, suppressEncryption) {
- var tableOffset = xrefEntry.offset;
- var stream = this.fetch(new _primitives.Ref(tableOffset, 0));
- if (!(0, _primitives.isStream)(stream)) {
- throw new _util.FormatError('bad ObjStm stream');
- }
- var first = stream.dict.get('First');
- var n = stream.dict.get('N');
- if (!Number.isInteger(first) || !Number.isInteger(n)) {
- throw new _util.FormatError('invalid first and n parameters for ObjStm stream');
- }
- var parser = new _parser.Parser(new _parser.Lexer(stream), false, this);
- parser.allowStreams = true;
- var i,
- entries = [],
- num,
- nums = [];
- for (i = 0; i < n; ++i) {
- num = parser.getObj();
- if (!Number.isInteger(num)) {
- throw new _util.FormatError('invalid object number in the ObjStm stream: ' + num);
- }
- nums.push(num);
- var offset = parser.getObj();
- if (!Number.isInteger(offset)) {
- throw new _util.FormatError('invalid object offset in the ObjStm stream: ' + offset);
- }
- }
- for (i = 0; i < n; ++i) {
- entries.push(parser.getObj());
- if ((0, _primitives.isCmd)(parser.buf1, 'endobj')) {
- parser.shift();
- }
- num = nums[i];
- var entry = this.entries[num];
- if (entry && entry.offset === tableOffset && entry.gen === i) {
- this.cache[num] = entries[i];
- }
- }
- xrefEntry = entries[xrefEntry.gen];
- if (xrefEntry === undefined) {
- throw new _util.FormatError('bad XRef entry for compressed object');
- }
- return xrefEntry;
- },
- fetchIfRefAsync: function () {
- var _ref = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee(obj, suppressEncryption) {
- return _regenerator2.default.wrap(function _callee$(_context) {
- while (1) {
- switch (_context.prev = _context.next) {
- case 0:
- if ((0, _primitives.isRef)(obj)) {
- _context.next = 2;
- break;
- }
-
- return _context.abrupt('return', obj);
-
- case 2:
- return _context.abrupt('return', this.fetchAsync(obj, suppressEncryption));
-
- case 3:
- case 'end':
- return _context.stop();
- }
- }
- }, _callee, this);
- }));
-
- function fetchIfRefAsync(_x, _x2) {
- return _ref.apply(this, arguments);
- }
-
- return fetchIfRefAsync;
- }(),
- fetchAsync: function () {
- var _ref2 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee2(ref, suppressEncryption) {
- return _regenerator2.default.wrap(function _callee2$(_context2) {
- while (1) {
- switch (_context2.prev = _context2.next) {
- case 0:
- _context2.prev = 0;
- return _context2.abrupt('return', this.fetch(ref, suppressEncryption));
-
- case 4:
- _context2.prev = 4;
- _context2.t0 = _context2['catch'](0);
-
- if (_context2.t0 instanceof _util.MissingDataException) {
- _context2.next = 8;
- break;
- }
-
- throw _context2.t0;
-
- case 8:
- _context2.next = 10;
- return this.pdfManager.requestRange(_context2.t0.begin, _context2.t0.end);
-
- case 10:
- return _context2.abrupt('return', this.fetchAsync(ref, suppressEncryption));
-
- case 11:
- case 'end':
- return _context2.stop();
- }
- }
- }, _callee2, this, [[0, 4]]);
- }));
-
- function fetchAsync(_x3, _x4) {
- return _ref2.apply(this, arguments);
- }
-
- return fetchAsync;
- }(),
-
- getCatalogObj: function XRef_getCatalogObj() {
- return this.root;
- }
- };
- return XRef;
-}();
-
-var NameOrNumberTree = function () {
- function NameOrNumberTree(root, xref, type) {
- _classCallCheck(this, NameOrNumberTree);
-
- if (this.constructor === NameOrNumberTree) {
- (0, _util.unreachable)('Cannot initialize NameOrNumberTree.');
- }
- this.root = root;
- this.xref = xref;
- this._type = type;
- }
-
- _createClass(NameOrNumberTree, [{
- key: 'getAll',
- value: function getAll() {
- var dict = Object.create(null);
- if (!this.root) {
- return dict;
- }
- var xref = this.xref;
- var processed = new _primitives.RefSet();
- processed.put(this.root);
- var queue = [this.root];
- while (queue.length > 0) {
- var obj = xref.fetchIfRef(queue.shift());
- if (!(0, _primitives.isDict)(obj)) {
- continue;
- }
- if (obj.has('Kids')) {
- var _kids = obj.get('Kids');
- for (var i = 0, ii = _kids.length; i < ii; i++) {
- var kid = _kids[i];
- if (processed.has(kid)) {
- throw new _util.FormatError('Duplicate entry in "' + this._type + '" tree.');
- }
- queue.push(kid);
- processed.put(kid);
- }
- continue;
- }
- var entries = obj.get(this._type);
- if (Array.isArray(entries)) {
- for (var _i2 = 0, _ii = entries.length; _i2 < _ii; _i2 += 2) {
- dict[xref.fetchIfRef(entries[_i2])] = xref.fetchIfRef(entries[_i2 + 1]);
- }
- }
- }
- return dict;
- }
- }, {
- key: 'get',
- value: function get(key) {
- if (!this.root) {
- return null;
- }
- var xref = this.xref;
- var kidsOrEntries = xref.fetchIfRef(this.root);
- var loopCount = 0;
- var MAX_LEVELS = 10;
- while (kidsOrEntries.has('Kids')) {
- if (++loopCount > MAX_LEVELS) {
- (0, _util.warn)('Search depth limit reached for "' + this._type + '" tree.');
- return null;
- }
- var _kids2 = kidsOrEntries.get('Kids');
- if (!Array.isArray(_kids2)) {
- return null;
- }
- var l = 0,
- r = _kids2.length - 1;
- while (l <= r) {
- var m = l + r >> 1;
- var kid = xref.fetchIfRef(_kids2[m]);
- var limits = kid.get('Limits');
- if (key < xref.fetchIfRef(limits[0])) {
- r = m - 1;
- } else if (key > xref.fetchIfRef(limits[1])) {
- l = m + 1;
- } else {
- kidsOrEntries = xref.fetchIfRef(_kids2[m]);
- break;
- }
- }
- if (l > r) {
- return null;
- }
- }
- var entries = kidsOrEntries.get(this._type);
- if (Array.isArray(entries)) {
- var _l = 0,
- _r = entries.length - 2;
- while (_l <= _r) {
- var _m = _l + _r & ~1;
- var currentKey = xref.fetchIfRef(entries[_m]);
- if (key < currentKey) {
- _r = _m - 2;
- } else if (key > currentKey) {
- _l = _m + 2;
- } else {
- return xref.fetchIfRef(entries[_m + 1]);
- }
- }
- }
- return null;
- }
- }]);
-
- return NameOrNumberTree;
-}();
-
-var NameTree = function (_NameOrNumberTree) {
- _inherits(NameTree, _NameOrNumberTree);
-
- function NameTree(root, xref) {
- _classCallCheck(this, NameTree);
-
- return _possibleConstructorReturn(this, (NameTree.__proto__ || Object.getPrototypeOf(NameTree)).call(this, root, xref, 'Names'));
- }
-
- return NameTree;
-}(NameOrNumberTree);
-
-var NumberTree = function (_NameOrNumberTree2) {
- _inherits(NumberTree, _NameOrNumberTree2);
-
- function NumberTree(root, xref) {
- _classCallCheck(this, NumberTree);
-
- return _possibleConstructorReturn(this, (NumberTree.__proto__ || Object.getPrototypeOf(NumberTree)).call(this, root, xref, 'Nums'));
- }
-
- return NumberTree;
-}(NameOrNumberTree);
-
-var FileSpec = function FileSpecClosure() {
- function FileSpec(root, xref) {
- if (!root || !(0, _primitives.isDict)(root)) {
- return;
- }
- this.xref = xref;
- this.root = root;
- if (root.has('FS')) {
- this.fs = root.get('FS');
- }
- this.description = root.has('Desc') ? (0, _util.stringToPDFString)(root.get('Desc')) : '';
- if (root.has('RF')) {
- (0, _util.warn)('Related file specifications are not supported');
- }
- this.contentAvailable = true;
- if (!root.has('EF')) {
- this.contentAvailable = false;
- (0, _util.warn)('Non-embedded file specifications are not supported');
- }
- }
- function pickPlatformItem(dict) {
- if (dict.has('UF')) {
- return dict.get('UF');
- } else if (dict.has('F')) {
- return dict.get('F');
- } else if (dict.has('Unix')) {
- return dict.get('Unix');
- } else if (dict.has('Mac')) {
- return dict.get('Mac');
- } else if (dict.has('DOS')) {
- return dict.get('DOS');
- }
- return null;
- }
- FileSpec.prototype = {
- get filename() {
- if (!this._filename && this.root) {
- var filename = pickPlatformItem(this.root) || 'unnamed';
- this._filename = (0, _util.stringToPDFString)(filename).replace(/\\\\/g, '\\').replace(/\\\//g, '/').replace(/\\/g, '/');
- }
- return this._filename;
- },
- get content() {
- if (!this.contentAvailable) {
- return null;
- }
- if (!this.contentRef && this.root) {
- this.contentRef = pickPlatformItem(this.root.get('EF'));
- }
- var content = null;
- if (this.contentRef) {
- var xref = this.xref;
- var fileObj = xref.fetchIfRef(this.contentRef);
- if (fileObj && (0, _primitives.isStream)(fileObj)) {
- content = fileObj.getBytes();
- } else {
- (0, _util.warn)('Embedded file specification points to non-existing/invalid ' + 'content');
- }
- } else {
- (0, _util.warn)('Embedded file specification does not have a content');
- }
- return content;
- },
- get serializable() {
- return {
- filename: this.filename,
- content: this.content
- };
- }
- };
- return FileSpec;
-}();
-var ObjectLoader = function () {
- function mayHaveChildren(value) {
- return (0, _primitives.isRef)(value) || (0, _primitives.isDict)(value) || Array.isArray(value) || (0, _primitives.isStream)(value);
- }
- function addChildren(node, nodesToVisit) {
- if ((0, _primitives.isDict)(node) || (0, _primitives.isStream)(node)) {
- var dict = (0, _primitives.isDict)(node) ? node : node.dict;
- var dictKeys = dict.getKeys();
- for (var i = 0, ii = dictKeys.length; i < ii; i++) {
- var rawValue = dict.getRaw(dictKeys[i]);
- if (mayHaveChildren(rawValue)) {
- nodesToVisit.push(rawValue);
- }
- }
- } else if (Array.isArray(node)) {
- for (var _i3 = 0, _ii2 = node.length; _i3 < _ii2; _i3++) {
- var value = node[_i3];
- if (mayHaveChildren(value)) {
- nodesToVisit.push(value);
- }
- }
- }
- }
- function ObjectLoader(dict, keys, xref) {
- this.dict = dict;
- this.keys = keys;
- this.xref = xref;
- this.refSet = null;
- this.capability = null;
- }
- ObjectLoader.prototype = {
- load: function load() {
- this.capability = (0, _util.createPromiseCapability)();
- if (!(this.xref.stream instanceof _chunked_stream.ChunkedStream) || this.xref.stream.getMissingChunks().length === 0) {
- this.capability.resolve();
- return this.capability.promise;
- }
- var keys = this.keys,
- dict = this.dict;
-
- this.refSet = new _primitives.RefSet();
- var nodesToVisit = [];
- for (var i = 0, ii = keys.length; i < ii; i++) {
- var rawValue = dict.getRaw(keys[i]);
- if (rawValue !== undefined) {
- nodesToVisit.push(rawValue);
- }
- }
- this._walk(nodesToVisit);
- return this.capability.promise;
- },
- _walk: function _walk(nodesToVisit) {
- var _this4 = this;
-
- var nodesToRevisit = [];
- var pendingRequests = [];
- while (nodesToVisit.length) {
- var _currentNode = nodesToVisit.pop();
- if ((0, _primitives.isRef)(_currentNode)) {
- if (this.refSet.has(_currentNode)) {
- continue;
- }
- try {
- this.refSet.put(_currentNode);
- _currentNode = this.xref.fetch(_currentNode);
- } catch (ex) {
- if (!(ex instanceof _util.MissingDataException)) {
- throw ex;
- }
- nodesToRevisit.push(_currentNode);
- pendingRequests.push({
- begin: ex.begin,
- end: ex.end
- });
- }
- }
- if (_currentNode && _currentNode.getBaseStreams) {
- var baseStreams = _currentNode.getBaseStreams();
- var foundMissingData = false;
- for (var i = 0, ii = baseStreams.length; i < ii; i++) {
- var stream = baseStreams[i];
- if (stream.getMissingChunks && stream.getMissingChunks().length) {
- foundMissingData = true;
- pendingRequests.push({
- begin: stream.start,
- end: stream.end
- });
- }
- }
- if (foundMissingData) {
- nodesToRevisit.push(_currentNode);
- }
- }
- addChildren(_currentNode, nodesToVisit);
- }
- if (pendingRequests.length) {
- this.xref.stream.manager.requestRanges(pendingRequests).then(function () {
- for (var _i4 = 0, _ii3 = nodesToRevisit.length; _i4 < _ii3; _i4++) {
- var node = nodesToRevisit[_i4];
- if ((0, _primitives.isRef)(node)) {
- _this4.refSet.remove(node);
- }
- }
- _this4._walk(nodesToRevisit);
- }, this.capability.reject);
- return;
- }
- this.refSet = null;
- this.capability.resolve();
- }
- };
- return ObjectLoader;
-}();
-exports.Catalog = Catalog;
-exports.ObjectLoader = ObjectLoader;
-exports.XRef = XRef;
-exports.FileSpec = FileSpec;
-
-/***/ }),
-/* 138 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-var EOF = {};
-var Name = function NameClosure() {
- function Name(name) {
- this.name = name;
- }
- Name.prototype = {};
- var nameCache = Object.create(null);
- Name.get = function Name_get(name) {
- var nameValue = nameCache[name];
- return nameValue ? nameValue : nameCache[name] = new Name(name);
- };
- return Name;
-}();
-var Cmd = function CmdClosure() {
- function Cmd(cmd) {
- this.cmd = cmd;
- }
- Cmd.prototype = {};
- var cmdCache = Object.create(null);
- Cmd.get = function Cmd_get(cmd) {
- var cmdValue = cmdCache[cmd];
- return cmdValue ? cmdValue : cmdCache[cmd] = new Cmd(cmd);
- };
- return Cmd;
-}();
-var Dict = function DictClosure() {
- var nonSerializable = function nonSerializableClosure() {
- return nonSerializable;
- };
- function Dict(xref) {
- this._map = Object.create(null);
- this.xref = xref;
- this.objId = null;
- this.suppressEncryption = false;
- this.__nonSerializable__ = nonSerializable;
- }
- Dict.prototype = {
- assignXref: function Dict_assignXref(newXref) {
- this.xref = newXref;
- },
- get: function Dict_get(key1, key2, key3) {
- var value;
- var xref = this.xref,
- suppressEncryption = this.suppressEncryption;
- if (typeof (value = this._map[key1]) !== 'undefined' || key1 in this._map || typeof key2 === 'undefined') {
- return xref ? xref.fetchIfRef(value, suppressEncryption) : value;
- }
- if (typeof (value = this._map[key2]) !== 'undefined' || key2 in this._map || typeof key3 === 'undefined') {
- return xref ? xref.fetchIfRef(value, suppressEncryption) : value;
- }
- value = this._map[key3] || null;
- return xref ? xref.fetchIfRef(value, suppressEncryption) : value;
- },
- getAsync: function Dict_getAsync(key1, key2, key3) {
- var value;
- var xref = this.xref,
- suppressEncryption = this.suppressEncryption;
- if (typeof (value = this._map[key1]) !== 'undefined' || key1 in this._map || typeof key2 === 'undefined') {
- if (xref) {
- return xref.fetchIfRefAsync(value, suppressEncryption);
- }
- return Promise.resolve(value);
- }
- if (typeof (value = this._map[key2]) !== 'undefined' || key2 in this._map || typeof key3 === 'undefined') {
- if (xref) {
- return xref.fetchIfRefAsync(value, suppressEncryption);
- }
- return Promise.resolve(value);
- }
- value = this._map[key3] || null;
- if (xref) {
- return xref.fetchIfRefAsync(value, suppressEncryption);
- }
- return Promise.resolve(value);
- },
- getArray: function Dict_getArray(key1, key2, key3) {
- var value = this.get(key1, key2, key3);
- var xref = this.xref,
- suppressEncryption = this.suppressEncryption;
- if (!Array.isArray(value) || !xref) {
- return value;
- }
- value = value.slice();
- for (var i = 0, ii = value.length; i < ii; i++) {
- if (!isRef(value[i])) {
- continue;
- }
- value[i] = xref.fetch(value[i], suppressEncryption);
- }
- return value;
- },
- getRaw: function Dict_getRaw(key) {
- return this._map[key];
- },
- getKeys: function Dict_getKeys() {
- return Object.keys(this._map);
- },
- set: function Dict_set(key, value) {
- this._map[key] = value;
- },
- has: function Dict_has(key) {
- return key in this._map;
- },
- forEach: function Dict_forEach(callback) {
- for (var key in this._map) {
- callback(key, this.get(key));
- }
- }
- };
- Dict.empty = new Dict(null);
- Dict.merge = function (xref, dictArray) {
- var mergedDict = new Dict(xref);
- for (var i = 0, ii = dictArray.length; i < ii; i++) {
- var dict = dictArray[i];
- if (!isDict(dict)) {
- continue;
- }
- for (var keyName in dict._map) {
- if (mergedDict._map[keyName] !== undefined) {
- continue;
- }
- mergedDict._map[keyName] = dict._map[keyName];
- }
- }
- return mergedDict;
- };
- return Dict;
-}();
-var Ref = function RefClosure() {
- function Ref(num, gen) {
- this.num = num;
- this.gen = gen;
- }
- Ref.prototype = {
- toString: function Ref_toString() {
- var str = this.num + 'R';
- if (this.gen !== 0) {
- str += this.gen;
- }
- return str;
- }
- };
- return Ref;
-}();
-var RefSet = function RefSetClosure() {
- function RefSet() {
- this.dict = Object.create(null);
- }
- RefSet.prototype = {
- has: function RefSet_has(ref) {
- return ref.toString() in this.dict;
- },
- put: function RefSet_put(ref) {
- this.dict[ref.toString()] = true;
- },
- remove: function RefSet_remove(ref) {
- delete this.dict[ref.toString()];
- }
- };
- return RefSet;
-}();
-var RefSetCache = function RefSetCacheClosure() {
- function RefSetCache() {
- this.dict = Object.create(null);
- }
- RefSetCache.prototype = {
- get: function RefSetCache_get(ref) {
- return this.dict[ref.toString()];
- },
- has: function RefSetCache_has(ref) {
- return ref.toString() in this.dict;
- },
- put: function RefSetCache_put(ref, obj) {
- this.dict[ref.toString()] = obj;
- },
- putAlias: function RefSetCache_putAlias(ref, aliasRef) {
- this.dict[ref.toString()] = this.get(aliasRef);
- },
- forEach: function RefSetCache_forEach(fn, thisArg) {
- for (var i in this.dict) {
- fn.call(thisArg, this.dict[i]);
- }
- },
- clear: function RefSetCache_clear() {
- this.dict = Object.create(null);
- }
- };
- return RefSetCache;
-}();
-function isEOF(v) {
- return v === EOF;
-}
-function isName(v, name) {
- return v instanceof Name && (name === undefined || v.name === name);
-}
-function isCmd(v, cmd) {
- return v instanceof Cmd && (cmd === undefined || v.cmd === cmd);
-}
-function isDict(v, type) {
- return v instanceof Dict && (type === undefined || isName(v.get('Type'), type));
-}
-function isRef(v) {
- return v instanceof Ref;
-}
-function isRefsEqual(v1, v2) {
- return v1.num === v2.num && v1.gen === v2.gen;
-}
-function isStream(v) {
- return (typeof v === 'undefined' ? 'undefined' : _typeof(v)) === 'object' && v !== null && v.getBytes !== undefined;
-}
-exports.EOF = EOF;
-exports.Cmd = Cmd;
-exports.Dict = Dict;
-exports.Name = Name;
-exports.Ref = Ref;
-exports.RefSet = RefSet;
-exports.RefSetCache = RefSetCache;
-exports.isEOF = isEOF;
-exports.isCmd = isCmd;
-exports.isDict = isDict;
-exports.isName = isName;
-exports.isRef = isRef;
-exports.isRefsEqual = isRefsEqual;
-exports.isStream = isStream;
-
-/***/ }),
-/* 139 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.Parser = exports.Linearization = exports.Lexer = undefined;
-
-var _stream = __w_pdfjs_require__(140);
-
-var _util = __w_pdfjs_require__(2);
-
-var _primitives = __w_pdfjs_require__(138);
-
-var _ccitt_stream = __w_pdfjs_require__(141);
-
-var _jbig2_stream = __w_pdfjs_require__(143);
-
-var _jpeg_stream = __w_pdfjs_require__(146);
-
-var _jpx_stream = __w_pdfjs_require__(148);
-
-var MAX_LENGTH_TO_CACHE = 1000;
-var MAX_ADLER32_LENGTH = 5552;
-function computeAdler32(bytes) {
- var bytesLength = bytes.length;
- var a = 1,
- b = 0;
- for (var i = 0; i < bytesLength; ++i) {
- a += bytes[i] & 0xFF;
- b += a;
- }
- return b % 65521 << 16 | a % 65521;
-}
-var Parser = function ParserClosure() {
- function Parser(lexer, allowStreams, xref, recoveryMode) {
- this.lexer = lexer;
- this.allowStreams = allowStreams;
- this.xref = xref;
- this.recoveryMode = recoveryMode || false;
- this.imageCache = Object.create(null);
- this.refill();
- }
- Parser.prototype = {
- refill: function Parser_refill() {
- this.buf1 = this.lexer.getObj();
- this.buf2 = this.lexer.getObj();
- },
- shift: function Parser_shift() {
- if ((0, _primitives.isCmd)(this.buf2, 'ID')) {
- this.buf1 = this.buf2;
- this.buf2 = null;
- } else {
- this.buf1 = this.buf2;
- this.buf2 = this.lexer.getObj();
- }
- },
- tryShift: function Parser_tryShift() {
- try {
- this.shift();
- return true;
- } catch (e) {
- if (e instanceof _util.MissingDataException) {
- throw e;
- }
- return false;
- }
- },
- getObj: function Parser_getObj(cipherTransform) {
- var buf1 = this.buf1;
- this.shift();
- if (buf1 instanceof _primitives.Cmd) {
- switch (buf1.cmd) {
- case 'BI':
- return this.makeInlineImage(cipherTransform);
- case '[':
- var array = [];
- while (!(0, _primitives.isCmd)(this.buf1, ']') && !(0, _primitives.isEOF)(this.buf1)) {
- array.push(this.getObj(cipherTransform));
- }
- if ((0, _primitives.isEOF)(this.buf1)) {
- if (!this.recoveryMode) {
- throw new _util.FormatError('End of file inside array');
- }
- return array;
- }
- this.shift();
- return array;
- case '<<':
- var dict = new _primitives.Dict(this.xref);
- while (!(0, _primitives.isCmd)(this.buf1, '>>') && !(0, _primitives.isEOF)(this.buf1)) {
- if (!(0, _primitives.isName)(this.buf1)) {
- (0, _util.info)('Malformed dictionary: key must be a name object');
- this.shift();
- continue;
- }
- var key = this.buf1.name;
- this.shift();
- if ((0, _primitives.isEOF)(this.buf1)) {
- break;
- }
- dict.set(key, this.getObj(cipherTransform));
- }
- if ((0, _primitives.isEOF)(this.buf1)) {
- if (!this.recoveryMode) {
- throw new _util.FormatError('End of file inside dictionary');
- }
- return dict;
- }
- if ((0, _primitives.isCmd)(this.buf2, 'stream')) {
- return this.allowStreams ? this.makeStream(dict, cipherTransform) : dict;
- }
- this.shift();
- return dict;
- default:
- return buf1;
- }
- }
- if (Number.isInteger(buf1)) {
- var num = buf1;
- if (Number.isInteger(this.buf1) && (0, _primitives.isCmd)(this.buf2, 'R')) {
- var ref = new _primitives.Ref(num, this.buf1);
- this.shift();
- this.shift();
- return ref;
- }
- return num;
- }
- if ((0, _util.isString)(buf1)) {
- var str = buf1;
- if (cipherTransform) {
- str = cipherTransform.decryptString(str);
- }
- return str;
- }
- return buf1;
- },
- findDefaultInlineStreamEnd: function findDefaultInlineStreamEnd(stream) {
- var E = 0x45,
- I = 0x49,
- SPACE = 0x20,
- LF = 0xA,
- CR = 0xD;
- var n = 10,
- NUL = 0x0;
- var startPos = stream.pos,
- state = 0,
- ch = void 0,
- maybeEIPos = void 0;
- while ((ch = stream.getByte()) !== -1) {
- if (state === 0) {
- state = ch === E ? 1 : 0;
- } else if (state === 1) {
- state = ch === I ? 2 : 0;
- } else {
- (0, _util.assert)(state === 2);
- if (ch === SPACE || ch === LF || ch === CR) {
- maybeEIPos = stream.pos;
- var followingBytes = stream.peekBytes(n);
- for (var i = 0, ii = followingBytes.length; i < ii; i++) {
- ch = followingBytes[i];
- if (ch === NUL && followingBytes[i + 1] !== NUL) {
- continue;
- }
- if (ch !== LF && ch !== CR && (ch < SPACE || ch > 0x7F)) {
- state = 0;
- break;
- }
- }
- if (state === 2) {
- break;
- }
- } else {
- state = 0;
- }
- }
- }
- if (ch === -1) {
- (0, _util.warn)('findDefaultInlineStreamEnd: ' + 'Reached the end of the stream without finding a valid EI marker');
- if (maybeEIPos) {
- (0, _util.warn)('... trying to recover by using the last "EI" occurrence.');
- stream.skip(-(stream.pos - maybeEIPos));
- }
- }
- return stream.pos - 4 - startPos;
- },
-
- findDCTDecodeInlineStreamEnd: function Parser_findDCTDecodeInlineStreamEnd(stream) {
- var startPos = stream.pos,
- foundEOI = false,
- b,
- markerLength,
- length;
- while ((b = stream.getByte()) !== -1) {
- if (b !== 0xFF) {
- continue;
- }
- switch (stream.getByte()) {
- case 0x00:
- break;
- case 0xFF:
- stream.skip(-1);
- break;
- case 0xD9:
- foundEOI = true;
- break;
- case 0xC0:
- case 0xC1:
- case 0xC2:
- case 0xC3:
- case 0xC5:
- case 0xC6:
- case 0xC7:
- case 0xC9:
- case 0xCA:
- case 0xCB:
- case 0xCD:
- case 0xCE:
- case 0xCF:
- case 0xC4:
- case 0xCC:
- case 0xDA:
- case 0xDB:
- case 0xDC:
- case 0xDD:
- case 0xDE:
- case 0xDF:
- case 0xE0:
- case 0xE1:
- case 0xE2:
- case 0xE3:
- case 0xE4:
- case 0xE5:
- case 0xE6:
- case 0xE7:
- case 0xE8:
- case 0xE9:
- case 0xEA:
- case 0xEB:
- case 0xEC:
- case 0xED:
- case 0xEE:
- case 0xEF:
- case 0xFE:
- markerLength = stream.getUint16();
- if (markerLength > 2) {
- stream.skip(markerLength - 2);
- } else {
- stream.skip(-2);
- }
- break;
- }
- if (foundEOI) {
- break;
- }
- }
- length = stream.pos - startPos;
- if (b === -1) {
- (0, _util.warn)('Inline DCTDecode image stream: ' + 'EOI marker not found, searching for /EI/ instead.');
- stream.skip(-length);
- return this.findDefaultInlineStreamEnd(stream);
- }
- this.inlineStreamSkipEI(stream);
- return length;
- },
- findASCII85DecodeInlineStreamEnd: function Parser_findASCII85DecodeInlineStreamEnd(stream) {
- var TILDE = 0x7E,
- GT = 0x3E;
- var startPos = stream.pos,
- ch,
- length;
- while ((ch = stream.getByte()) !== -1) {
- if (ch === TILDE && stream.peekByte() === GT) {
- stream.skip();
- break;
- }
- }
- length = stream.pos - startPos;
- if (ch === -1) {
- (0, _util.warn)('Inline ASCII85Decode image stream: ' + 'EOD marker not found, searching for /EI/ instead.');
- stream.skip(-length);
- return this.findDefaultInlineStreamEnd(stream);
- }
- this.inlineStreamSkipEI(stream);
- return length;
- },
- findASCIIHexDecodeInlineStreamEnd: function Parser_findASCIIHexDecodeInlineStreamEnd(stream) {
- var GT = 0x3E;
- var startPos = stream.pos,
- ch,
- length;
- while ((ch = stream.getByte()) !== -1) {
- if (ch === GT) {
- break;
- }
- }
- length = stream.pos - startPos;
- if (ch === -1) {
- (0, _util.warn)('Inline ASCIIHexDecode image stream: ' + 'EOD marker not found, searching for /EI/ instead.');
- stream.skip(-length);
- return this.findDefaultInlineStreamEnd(stream);
- }
- this.inlineStreamSkipEI(stream);
- return length;
- },
- inlineStreamSkipEI: function Parser_inlineStreamSkipEI(stream) {
- var E = 0x45,
- I = 0x49;
- var state = 0,
- ch;
- while ((ch = stream.getByte()) !== -1) {
- if (state === 0) {
- state = ch === E ? 1 : 0;
- } else if (state === 1) {
- state = ch === I ? 2 : 0;
- } else if (state === 2) {
- break;
- }
- }
- },
- makeInlineImage: function Parser_makeInlineImage(cipherTransform) {
- var lexer = this.lexer;
- var stream = lexer.stream;
- var dict = new _primitives.Dict(this.xref),
- dictLength = void 0;
- while (!(0, _primitives.isCmd)(this.buf1, 'ID') && !(0, _primitives.isEOF)(this.buf1)) {
- if (!(0, _primitives.isName)(this.buf1)) {
- throw new _util.FormatError('Dictionary key must be a name object');
- }
- var key = this.buf1.name;
- this.shift();
- if ((0, _primitives.isEOF)(this.buf1)) {
- break;
- }
- dict.set(key, this.getObj(cipherTransform));
- }
- if (lexer.beginInlineImagePos !== -1) {
- dictLength = stream.pos - lexer.beginInlineImagePos;
- }
- var filter = dict.get('Filter', 'F'),
- filterName;
- if ((0, _primitives.isName)(filter)) {
- filterName = filter.name;
- } else if (Array.isArray(filter)) {
- var filterZero = this.xref.fetchIfRef(filter[0]);
- if ((0, _primitives.isName)(filterZero)) {
- filterName = filterZero.name;
- }
- }
- var startPos = stream.pos,
- length = void 0;
- if (filterName === 'DCTDecode' || filterName === 'DCT') {
- length = this.findDCTDecodeInlineStreamEnd(stream);
- } else if (filterName === 'ASCII85Decode' || filterName === 'A85') {
- length = this.findASCII85DecodeInlineStreamEnd(stream);
- } else if (filterName === 'ASCIIHexDecode' || filterName === 'AHx') {
- length = this.findASCIIHexDecodeInlineStreamEnd(stream);
- } else {
- length = this.findDefaultInlineStreamEnd(stream);
- }
- var imageStream = stream.makeSubStream(startPos, length, dict);
- var cacheKey = void 0;
- if (length < MAX_LENGTH_TO_CACHE && dictLength < MAX_ADLER32_LENGTH) {
- var imageBytes = imageStream.getBytes();
- imageStream.reset();
- var initialStreamPos = stream.pos;
- stream.pos = lexer.beginInlineImagePos;
- var dictBytes = stream.getBytes(dictLength);
- stream.pos = initialStreamPos;
- cacheKey = computeAdler32(imageBytes) + '_' + computeAdler32(dictBytes);
- var cacheEntry = this.imageCache[cacheKey];
- if (cacheEntry !== undefined) {
- this.buf2 = _primitives.Cmd.get('EI');
- this.shift();
- cacheEntry.reset();
- return cacheEntry;
- }
- }
- if (cipherTransform) {
- imageStream = cipherTransform.createStream(imageStream, length);
- }
- imageStream = this.filter(imageStream, dict, length);
- imageStream.dict = dict;
- if (cacheKey !== undefined) {
- imageStream.cacheKey = 'inline_' + length + '_' + cacheKey;
- this.imageCache[cacheKey] = imageStream;
- }
- this.buf2 = _primitives.Cmd.get('EI');
- this.shift();
- return imageStream;
- },
- _findStreamLength: function _findStreamLength(startPos, signature) {
- var stream = this.lexer.stream;
-
- stream.pos = startPos;
- var SCAN_BLOCK_LENGTH = 2048;
- var signatureLength = signature.length;
- while (stream.pos < stream.end) {
- var scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH);
- var scanLength = scanBytes.length - signatureLength;
- if (scanLength <= 0) {
- break;
- }
- var pos = 0;
- while (pos < scanLength) {
- var j = 0;
- while (j < signatureLength && scanBytes[pos + j] === signature[j]) {
- j++;
- }
- if (j >= signatureLength) {
- stream.pos += pos;
- return stream.pos - startPos;
- }
- pos++;
- }
- stream.pos += scanLength;
- }
- return -1;
- },
-
- makeStream: function Parser_makeStream(dict, cipherTransform) {
- var lexer = this.lexer;
- var stream = lexer.stream;
- lexer.skipToNextLine();
- var startPos = stream.pos - 1;
- var length = dict.get('Length');
- if (!Number.isInteger(length)) {
- (0, _util.info)('Bad ' + length + ' attribute in stream');
- length = 0;
- }
- stream.pos = startPos + length;
- lexer.nextChar();
- if (this.tryShift() && (0, _primitives.isCmd)(this.buf2, 'endstream')) {
- this.shift();
- } else {
- var ENDSTREAM_SIGNATURE = new Uint8Array([0x65, 0x6E, 0x64, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6D]);
- var actualLength = this._findStreamLength(startPos, ENDSTREAM_SIGNATURE);
- if (actualLength < 0) {
- var MAX_TRUNCATION = 1;
- for (var i = 1; i <= MAX_TRUNCATION; i++) {
- var end = ENDSTREAM_SIGNATURE.length - i;
- var TRUNCATED_SIGNATURE = ENDSTREAM_SIGNATURE.slice(0, end);
- var maybeLength = this._findStreamLength(startPos, TRUNCATED_SIGNATURE);
- if (maybeLength >= 0) {
- var lastByte = stream.peekBytes(end + 1)[end];
- if (!(0, _util.isSpace)(lastByte)) {
- break;
- }
- (0, _util.info)('Found "' + (0, _util.bytesToString)(TRUNCATED_SIGNATURE) + '" when ' + 'searching for endstream command.');
- actualLength = maybeLength;
- break;
- }
- }
- if (actualLength < 0) {
- throw new _util.FormatError('Missing endstream command.');
- }
- }
- length = actualLength;
- lexer.nextChar();
- this.shift();
- this.shift();
- }
- this.shift();
- stream = stream.makeSubStream(startPos, length, dict);
- if (cipherTransform) {
- stream = cipherTransform.createStream(stream, length);
- }
- stream = this.filter(stream, dict, length);
- stream.dict = dict;
- return stream;
- },
- filter: function Parser_filter(stream, dict, length) {
- var filter = dict.get('Filter', 'F');
- var params = dict.get('DecodeParms', 'DP');
- if ((0, _primitives.isName)(filter)) {
- if (Array.isArray(params)) {
- (0, _util.warn)('/DecodeParms should not contain an Array, ' + 'when /Filter contains a Name.');
- }
- return this.makeFilter(stream, filter.name, length, params);
- }
- var maybeLength = length;
- if (Array.isArray(filter)) {
- var filterArray = filter;
- var paramsArray = params;
- for (var i = 0, ii = filterArray.length; i < ii; ++i) {
- filter = this.xref.fetchIfRef(filterArray[i]);
- if (!(0, _primitives.isName)(filter)) {
- throw new _util.FormatError('Bad filter name: ' + filter);
- }
- params = null;
- if (Array.isArray(paramsArray) && i in paramsArray) {
- params = this.xref.fetchIfRef(paramsArray[i]);
- }
- stream = this.makeFilter(stream, filter.name, maybeLength, params);
- maybeLength = null;
- }
- }
- return stream;
- },
- makeFilter: function Parser_makeFilter(stream, name, maybeLength, params) {
- if (maybeLength === 0) {
- (0, _util.warn)('Empty "' + name + '" stream.');
- return new _stream.NullStream();
- }
- try {
- var xrefStreamStats = this.xref.stats.streamTypes;
- if (name === 'FlateDecode' || name === 'Fl') {
- xrefStreamStats[_util.StreamType.FLATE] = true;
- if (params) {
- return new _stream.PredictorStream(new _stream.FlateStream(stream, maybeLength), maybeLength, params);
- }
- return new _stream.FlateStream(stream, maybeLength);
- }
- if (name === 'LZWDecode' || name === 'LZW') {
- xrefStreamStats[_util.StreamType.LZW] = true;
- var earlyChange = 1;
- if (params) {
- if (params.has('EarlyChange')) {
- earlyChange = params.get('EarlyChange');
- }
- return new _stream.PredictorStream(new _stream.LZWStream(stream, maybeLength, earlyChange), maybeLength, params);
- }
- return new _stream.LZWStream(stream, maybeLength, earlyChange);
- }
- if (name === 'DCTDecode' || name === 'DCT') {
- xrefStreamStats[_util.StreamType.DCT] = true;
- return new _jpeg_stream.JpegStream(stream, maybeLength, stream.dict, params);
- }
- if (name === 'JPXDecode' || name === 'JPX') {
- xrefStreamStats[_util.StreamType.JPX] = true;
- return new _jpx_stream.JpxStream(stream, maybeLength, stream.dict, params);
- }
- if (name === 'ASCII85Decode' || name === 'A85') {
- xrefStreamStats[_util.StreamType.A85] = true;
- return new _stream.Ascii85Stream(stream, maybeLength);
- }
- if (name === 'ASCIIHexDecode' || name === 'AHx') {
- xrefStreamStats[_util.StreamType.AHX] = true;
- return new _stream.AsciiHexStream(stream, maybeLength);
- }
- if (name === 'CCITTFaxDecode' || name === 'CCF') {
- xrefStreamStats[_util.StreamType.CCF] = true;
- return new _ccitt_stream.CCITTFaxStream(stream, maybeLength, params);
- }
- if (name === 'RunLengthDecode' || name === 'RL') {
- xrefStreamStats[_util.StreamType.RL] = true;
- return new _stream.RunLengthStream(stream, maybeLength);
- }
- if (name === 'JBIG2Decode') {
- xrefStreamStats[_util.StreamType.JBIG] = true;
- return new _jbig2_stream.Jbig2Stream(stream, maybeLength, stream.dict, params);
- }
- (0, _util.warn)('filter "' + name + '" not supported yet');
- return stream;
- } catch (ex) {
- if (ex instanceof _util.MissingDataException) {
- throw ex;
- }
- (0, _util.warn)('Invalid stream: \"' + ex + '\"');
- return new _stream.NullStream();
- }
- }
- };
- return Parser;
-}();
-var Lexer = function LexerClosure() {
- function Lexer(stream, knownCommands) {
- this.stream = stream;
- this.nextChar();
- this.strBuf = [];
- this.knownCommands = knownCommands;
- this.beginInlineImagePos = -1;
- }
- var specialChars = [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
- function toHexDigit(ch) {
- if (ch >= 0x30 && ch <= 0x39) {
- return ch & 0x0F;
- }
- if (ch >= 0x41 && ch <= 0x46 || ch >= 0x61 && ch <= 0x66) {
- return (ch & 0x0F) + 9;
- }
- return -1;
- }
- Lexer.prototype = {
- nextChar: function Lexer_nextChar() {
- return this.currentChar = this.stream.getByte();
- },
- peekChar: function Lexer_peekChar() {
- return this.stream.peekByte();
- },
- getNumber: function Lexer_getNumber() {
- var ch = this.currentChar;
- var eNotation = false;
- var divideBy = 0;
- var sign = 0;
- if (ch === 0x2D) {
- sign = -1;
- ch = this.nextChar();
- if (ch === 0x2D) {
- ch = this.nextChar();
- }
- } else if (ch === 0x2B) {
- sign = 1;
- ch = this.nextChar();
- }
- if (ch === 0x0A || ch === 0x0D) {
- do {
- ch = this.nextChar();
- } while (ch === 0x0A || ch === 0x0D);
- }
- if (ch === 0x2E) {
- divideBy = 10;
- ch = this.nextChar();
- }
- if (ch < 0x30 || ch > 0x39) {
- if (divideBy === 10 && sign === 0 && ((0, _util.isSpace)(ch) || ch === -1)) {
- (0, _util.warn)('Lexer.getNumber - treating a single decimal point as zero.');
- return 0;
- }
- throw new _util.FormatError('Invalid number: ' + String.fromCharCode(ch) + ' (charCode ' + ch + ')');
- }
- sign = sign || 1;
- var baseValue = ch - 0x30;
- var powerValue = 0;
- var powerValueSign = 1;
- while ((ch = this.nextChar()) >= 0) {
- if (0x30 <= ch && ch <= 0x39) {
- var currentDigit = ch - 0x30;
- if (eNotation) {
- powerValue = powerValue * 10 + currentDigit;
- } else {
- if (divideBy !== 0) {
- divideBy *= 10;
- }
- baseValue = baseValue * 10 + currentDigit;
- }
- } else if (ch === 0x2E) {
- if (divideBy === 0) {
- divideBy = 1;
- } else {
- break;
- }
- } else if (ch === 0x2D) {
- (0, _util.warn)('Badly formatted number');
- } else if (ch === 0x45 || ch === 0x65) {
- ch = this.peekChar();
- if (ch === 0x2B || ch === 0x2D) {
- powerValueSign = ch === 0x2D ? -1 : 1;
- this.nextChar();
- } else if (ch < 0x30 || ch > 0x39) {
- break;
- }
- eNotation = true;
- } else {
- break;
- }
- }
- if (divideBy !== 0) {
- baseValue /= divideBy;
- }
- if (eNotation) {
- baseValue *= Math.pow(10, powerValueSign * powerValue);
- }
- return sign * baseValue;
- },
- getString: function Lexer_getString() {
- var numParen = 1;
- var done = false;
- var strBuf = this.strBuf;
- strBuf.length = 0;
- var ch = this.nextChar();
- while (true) {
- var charBuffered = false;
- switch (ch | 0) {
- case -1:
- (0, _util.warn)('Unterminated string');
- done = true;
- break;
- case 0x28:
- ++numParen;
- strBuf.push('(');
- break;
- case 0x29:
- if (--numParen === 0) {
- this.nextChar();
- done = true;
- } else {
- strBuf.push(')');
- }
- break;
- case 0x5C:
- ch = this.nextChar();
- switch (ch) {
- case -1:
- (0, _util.warn)('Unterminated string');
- done = true;
- break;
- case 0x6E:
- strBuf.push('\n');
- break;
- case 0x72:
- strBuf.push('\r');
- break;
- case 0x74:
- strBuf.push('\t');
- break;
- case 0x62:
- strBuf.push('\b');
- break;
- case 0x66:
- strBuf.push('\f');
- break;
- case 0x5C:
- case 0x28:
- case 0x29:
- strBuf.push(String.fromCharCode(ch));
- break;
- case 0x30:
- case 0x31:
- case 0x32:
- case 0x33:
- case 0x34:
- case 0x35:
- case 0x36:
- case 0x37:
- var x = ch & 0x0F;
- ch = this.nextChar();
- charBuffered = true;
- if (ch >= 0x30 && ch <= 0x37) {
- x = (x << 3) + (ch & 0x0F);
- ch = this.nextChar();
- if (ch >= 0x30 && ch <= 0x37) {
- charBuffered = false;
- x = (x << 3) + (ch & 0x0F);
- }
- }
- strBuf.push(String.fromCharCode(x));
- break;
- case 0x0D:
- if (this.peekChar() === 0x0A) {
- this.nextChar();
- }
- break;
- case 0x0A:
- break;
- default:
- strBuf.push(String.fromCharCode(ch));
- break;
- }
- break;
- default:
- strBuf.push(String.fromCharCode(ch));
- break;
- }
- if (done) {
- break;
- }
- if (!charBuffered) {
- ch = this.nextChar();
- }
- }
- return strBuf.join('');
- },
- getName: function Lexer_getName() {
- var ch, previousCh;
- var strBuf = this.strBuf;
- strBuf.length = 0;
- while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) {
- if (ch === 0x23) {
- ch = this.nextChar();
- if (specialChars[ch]) {
- (0, _util.warn)('Lexer_getName: ' + 'NUMBER SIGN (#) should be followed by a hexadecimal number.');
- strBuf.push('#');
- break;
- }
- var x = toHexDigit(ch);
- if (x !== -1) {
- previousCh = ch;
- ch = this.nextChar();
- var x2 = toHexDigit(ch);
- if (x2 === -1) {
- (0, _util.warn)('Lexer_getName: Illegal digit (' + String.fromCharCode(ch) + ') in hexadecimal number.');
- strBuf.push('#', String.fromCharCode(previousCh));
- if (specialChars[ch]) {
- break;
- }
- strBuf.push(String.fromCharCode(ch));
- continue;
- }
- strBuf.push(String.fromCharCode(x << 4 | x2));
- } else {
- strBuf.push('#', String.fromCharCode(ch));
- }
- } else {
- strBuf.push(String.fromCharCode(ch));
- }
- }
- if (strBuf.length > 127) {
- (0, _util.warn)('name token is longer than allowed by the spec: ' + strBuf.length);
- }
- return _primitives.Name.get(strBuf.join(''));
- },
- getHexString: function Lexer_getHexString() {
- var strBuf = this.strBuf;
- strBuf.length = 0;
- var ch = this.currentChar;
- var isFirstHex = true;
- var firstDigit;
- var secondDigit;
- while (true) {
- if (ch < 0) {
- (0, _util.warn)('Unterminated hex string');
- break;
- } else if (ch === 0x3E) {
- this.nextChar();
- break;
- } else if (specialChars[ch] === 1) {
- ch = this.nextChar();
- continue;
- } else {
- if (isFirstHex) {
- firstDigit = toHexDigit(ch);
- if (firstDigit === -1) {
- (0, _util.warn)('Ignoring invalid character "' + ch + '" in hex string');
- ch = this.nextChar();
- continue;
- }
- } else {
- secondDigit = toHexDigit(ch);
- if (secondDigit === -1) {
- (0, _util.warn)('Ignoring invalid character "' + ch + '" in hex string');
- ch = this.nextChar();
- continue;
- }
- strBuf.push(String.fromCharCode(firstDigit << 4 | secondDigit));
- }
- isFirstHex = !isFirstHex;
- ch = this.nextChar();
- }
- }
- return strBuf.join('');
- },
- getObj: function Lexer_getObj() {
- var comment = false;
- var ch = this.currentChar;
- while (true) {
- if (ch < 0) {
- return _primitives.EOF;
- }
- if (comment) {
- if (ch === 0x0A || ch === 0x0D) {
- comment = false;
- }
- } else if (ch === 0x25) {
- comment = true;
- } else if (specialChars[ch] !== 1) {
- break;
- }
- ch = this.nextChar();
- }
- switch (ch | 0) {
- case 0x30:
- case 0x31:
- case 0x32:
- case 0x33:
- case 0x34:
- case 0x35:
- case 0x36:
- case 0x37:
- case 0x38:
- case 0x39:
- case 0x2B:
- case 0x2D:
- case 0x2E:
- return this.getNumber();
- case 0x28:
- return this.getString();
- case 0x2F:
- return this.getName();
- case 0x5B:
- this.nextChar();
- return _primitives.Cmd.get('[');
- case 0x5D:
- this.nextChar();
- return _primitives.Cmd.get(']');
- case 0x3C:
- ch = this.nextChar();
- if (ch === 0x3C) {
- this.nextChar();
- return _primitives.Cmd.get('<<');
- }
- return this.getHexString();
- case 0x3E:
- ch = this.nextChar();
- if (ch === 0x3E) {
- this.nextChar();
- return _primitives.Cmd.get('>>');
- }
- return _primitives.Cmd.get('>');
- case 0x7B:
- this.nextChar();
- return _primitives.Cmd.get('{');
- case 0x7D:
- this.nextChar();
- return _primitives.Cmd.get('}');
- case 0x29:
- this.nextChar();
- throw new _util.FormatError('Illegal character: ' + ch);
- }
- var str = String.fromCharCode(ch);
- var knownCommands = this.knownCommands;
- var knownCommandFound = knownCommands && knownCommands[str] !== undefined;
- while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) {
- var possibleCommand = str + String.fromCharCode(ch);
- if (knownCommandFound && knownCommands[possibleCommand] === undefined) {
- break;
- }
- if (str.length === 128) {
- throw new _util.FormatError('Command token too long: ' + str.length);
- }
- str = possibleCommand;
- knownCommandFound = knownCommands && knownCommands[str] !== undefined;
- }
- if (str === 'true') {
- return true;
- }
- if (str === 'false') {
- return false;
- }
- if (str === 'null') {
- return null;
- }
- if (str === 'BI') {
- this.beginInlineImagePos = this.stream.pos;
- }
- return _primitives.Cmd.get(str);
- },
- skipToNextLine: function Lexer_skipToNextLine() {
- var ch = this.currentChar;
- while (ch >= 0) {
- if (ch === 0x0D) {
- ch = this.nextChar();
- if (ch === 0x0A) {
- this.nextChar();
- }
- break;
- } else if (ch === 0x0A) {
- this.nextChar();
- break;
- }
- ch = this.nextChar();
- }
- }
- };
- return Lexer;
-}();
-var Linearization = {
- create: function LinearizationCreate(stream) {
- function getInt(name, allowZeroValue) {
- var obj = linDict.get(name);
- if (Number.isInteger(obj) && (allowZeroValue ? obj >= 0 : obj > 0)) {
- return obj;
- }
- throw new Error('The "' + name + '" parameter in the linearization ' + 'dictionary is invalid.');
- }
- function getHints() {
- var hints = linDict.get('H'),
- hintsLength,
- item;
- if (Array.isArray(hints) && ((hintsLength = hints.length) === 2 || hintsLength === 4)) {
- for (var index = 0; index < hintsLength; index++) {
- if (!(Number.isInteger(item = hints[index]) && item > 0)) {
- throw new Error('Hint (' + index + ') in the linearization dictionary is invalid.');
- }
- }
- return hints;
- }
- throw new Error('Hint array in the linearization dictionary is invalid.');
- }
- var parser = new Parser(new Lexer(stream), false, null);
- var obj1 = parser.getObj();
- var obj2 = parser.getObj();
- var obj3 = parser.getObj();
- var linDict = parser.getObj();
- var obj, length;
- if (!(Number.isInteger(obj1) && Number.isInteger(obj2) && (0, _primitives.isCmd)(obj3, 'obj') && (0, _primitives.isDict)(linDict) && (0, _util.isNum)(obj = linDict.get('Linearized')) && obj > 0)) {
- return null;
- } else if ((length = getInt('L')) !== stream.length) {
- throw new Error('The "L" parameter in the linearization dictionary ' + 'does not equal the stream length.');
- }
- return {
- length: length,
- hints: getHints(),
- objectNumberFirst: getInt('O'),
- endFirst: getInt('E'),
- numPages: getInt('N'),
- mainXRefEntriesOffset: getInt('T'),
- pageFirst: linDict.has('P') ? getInt('P', true) : 0
- };
- }
-};
-exports.Lexer = Lexer;
-exports.Linearization = Linearization;
-exports.Parser = Parser;
-
-/***/ }),
-/* 140 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.LZWStream = exports.StringStream = exports.StreamsSequenceStream = exports.Stream = exports.RunLengthStream = exports.PredictorStream = exports.NullStream = exports.FlateStream = exports.DecodeStream = exports.DecryptStream = exports.AsciiHexStream = exports.Ascii85Stream = undefined;
-
-var _util = __w_pdfjs_require__(2);
-
-var _primitives = __w_pdfjs_require__(138);
-
-function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
-
-var Stream = function StreamClosure() {
- function Stream(arrayBuffer, start, length, dict) {
- this.bytes = arrayBuffer instanceof Uint8Array ? arrayBuffer : new Uint8Array(arrayBuffer);
- this.start = start || 0;
- this.pos = this.start;
- this.end = start + length || this.bytes.length;
- this.dict = dict;
- }
- Stream.prototype = {
- get length() {
- return this.end - this.start;
- },
- get isEmpty() {
- return this.length === 0;
- },
- getByte: function Stream_getByte() {
- if (this.pos >= this.end) {
- return -1;
- }
- return this.bytes[this.pos++];
- },
- getUint16: function Stream_getUint16() {
- var b0 = this.getByte();
- var b1 = this.getByte();
- if (b0 === -1 || b1 === -1) {
- return -1;
- }
- return (b0 << 8) + b1;
- },
- getInt32: function Stream_getInt32() {
- var b0 = this.getByte();
- var b1 = this.getByte();
- var b2 = this.getByte();
- var b3 = this.getByte();
- return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
- },
- getBytes: function getBytes(length) {
- var forceClamped = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
-
- var bytes = this.bytes;
- var pos = this.pos;
- var strEnd = this.end;
- if (!length) {
- var _subarray = bytes.subarray(pos, strEnd);
- return forceClamped ? new Uint8ClampedArray(_subarray) : _subarray;
- }
- var end = pos + length;
- if (end > strEnd) {
- end = strEnd;
- }
- this.pos = end;
- var subarray = bytes.subarray(pos, end);
- return forceClamped ? new Uint8ClampedArray(subarray) : subarray;
- },
-
- peekByte: function Stream_peekByte() {
- var peekedByte = this.getByte();
- this.pos--;
- return peekedByte;
- },
- peekBytes: function peekBytes(length) {
- var forceClamped = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
-
- var bytes = this.getBytes(length, forceClamped);
- this.pos -= bytes.length;
- return bytes;
- },
-
- skip: function Stream_skip(n) {
- if (!n) {
- n = 1;
- }
- this.pos += n;
- },
- reset: function Stream_reset() {
- this.pos = this.start;
- },
- moveStart: function Stream_moveStart() {
- this.start = this.pos;
- },
- makeSubStream: function Stream_makeSubStream(start, length, dict) {
- return new Stream(this.bytes.buffer, start, length, dict);
- }
- };
- return Stream;
-}();
-var StringStream = function StringStreamClosure() {
- function StringStream(str) {
- var bytes = (0, _util.stringToBytes)(str);
- Stream.call(this, bytes);
- }
- StringStream.prototype = Stream.prototype;
- return StringStream;
-}();
-var DecodeStream = function DecodeStreamClosure() {
- var emptyBuffer = new Uint8Array(0);
- function DecodeStream(maybeMinBufferLength) {
- this._rawMinBufferLength = maybeMinBufferLength || 0;
- this.pos = 0;
- this.bufferLength = 0;
- this.eof = false;
- this.buffer = emptyBuffer;
- this.minBufferLength = 512;
- if (maybeMinBufferLength) {
- while (this.minBufferLength < maybeMinBufferLength) {
- this.minBufferLength *= 2;
- }
- }
- }
- DecodeStream.prototype = {
- get isEmpty() {
- while (!this.eof && this.bufferLength === 0) {
- this.readBlock();
- }
- return this.bufferLength === 0;
- },
- ensureBuffer: function DecodeStream_ensureBuffer(requested) {
- var buffer = this.buffer;
- if (requested <= buffer.byteLength) {
- return buffer;
- }
- var size = this.minBufferLength;
- while (size < requested) {
- size *= 2;
- }
- var buffer2 = new Uint8Array(size);
- buffer2.set(buffer);
- return this.buffer = buffer2;
- },
- getByte: function DecodeStream_getByte() {
- var pos = this.pos;
- while (this.bufferLength <= pos) {
- if (this.eof) {
- return -1;
- }
- this.readBlock();
- }
- return this.buffer[this.pos++];
- },
- getUint16: function DecodeStream_getUint16() {
- var b0 = this.getByte();
- var b1 = this.getByte();
- if (b0 === -1 || b1 === -1) {
- return -1;
- }
- return (b0 << 8) + b1;
- },
- getInt32: function DecodeStream_getInt32() {
- var b0 = this.getByte();
- var b1 = this.getByte();
- var b2 = this.getByte();
- var b3 = this.getByte();
- return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
- },
- getBytes: function getBytes(length) {
- var forceClamped = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
-
- var end,
- pos = this.pos;
- if (length) {
- this.ensureBuffer(pos + length);
- end = pos + length;
- while (!this.eof && this.bufferLength < end) {
- this.readBlock();
- }
- var bufEnd = this.bufferLength;
- if (end > bufEnd) {
- end = bufEnd;
- }
- } else {
- while (!this.eof) {
- this.readBlock();
- }
- end = this.bufferLength;
- }
- this.pos = end;
- var subarray = this.buffer.subarray(pos, end);
- return forceClamped && !(subarray instanceof Uint8ClampedArray) ? new Uint8ClampedArray(subarray) : subarray;
- },
-
- peekByte: function DecodeStream_peekByte() {
- var peekedByte = this.getByte();
- this.pos--;
- return peekedByte;
- },
- peekBytes: function peekBytes(length) {
- var forceClamped = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
-
- var bytes = this.getBytes(length, forceClamped);
- this.pos -= bytes.length;
- return bytes;
- },
-
- makeSubStream: function DecodeStream_makeSubStream(start, length, dict) {
- var end = start + length;
- while (this.bufferLength <= end && !this.eof) {
- this.readBlock();
- }
- return new Stream(this.buffer, start, length, dict);
- },
- skip: function DecodeStream_skip(n) {
- if (!n) {
- n = 1;
- }
- this.pos += n;
- },
- reset: function DecodeStream_reset() {
- this.pos = 0;
- },
- getBaseStreams: function DecodeStream_getBaseStreams() {
- if (this.str && this.str.getBaseStreams) {
- return this.str.getBaseStreams();
- }
- return [];
- }
- };
- return DecodeStream;
-}();
-var StreamsSequenceStream = function StreamsSequenceStreamClosure() {
- function StreamsSequenceStream(streams) {
- this.streams = streams;
- var maybeLength = 0;
- for (var i = 0, ii = streams.length; i < ii; i++) {
- var stream = streams[i];
- if (stream instanceof DecodeStream) {
- maybeLength += stream._rawMinBufferLength;
- } else {
- maybeLength += stream.length;
- }
- }
- DecodeStream.call(this, maybeLength);
- }
- StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype);
- StreamsSequenceStream.prototype.readBlock = function streamSequenceStreamReadBlock() {
- var streams = this.streams;
- if (streams.length === 0) {
- this.eof = true;
- return;
- }
- var stream = streams.shift();
- var chunk = stream.getBytes();
- var bufferLength = this.bufferLength;
- var newLength = bufferLength + chunk.length;
- var buffer = this.ensureBuffer(newLength);
- buffer.set(chunk, bufferLength);
- this.bufferLength = newLength;
- };
- StreamsSequenceStream.prototype.getBaseStreams = function StreamsSequenceStream_getBaseStreams() {
- var baseStreams = [];
- for (var i = 0, ii = this.streams.length; i < ii; i++) {
- var stream = this.streams[i];
- if (stream.getBaseStreams) {
- baseStreams.push.apply(baseStreams, _toConsumableArray(stream.getBaseStreams()));
- }
- }
- return baseStreams;
- };
- return StreamsSequenceStream;
-}();
-var FlateStream = function FlateStreamClosure() {
- var codeLenCodeMap = new Int32Array([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
- var lengthDecode = new Int32Array([0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a, 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f, 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073, 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102]);
- var distDecode = new Int32Array([0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d, 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1, 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01, 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001]);
- var fixedLitCodeTab = [new Int32Array([0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0, 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0, 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0, 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8, 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8, 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8, 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4, 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4, 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4, 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc, 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec, 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc, 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2, 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2, 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2, 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca, 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea, 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da, 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6, 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6, 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6, 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce, 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee, 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de, 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe, 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1, 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1, 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1, 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9, 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9, 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9, 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5, 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5, 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5, 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd, 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed, 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd, 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3, 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3, 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3, 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb, 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb, 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db, 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7, 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7, 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7, 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf, 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef, 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df, 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff]), 9];
- var fixedDistCodeTab = [new Int32Array([0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c, 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000, 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d, 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000]), 5];
- function FlateStream(str, maybeLength) {
- this.str = str;
- this.dict = str.dict;
- var cmf = str.getByte();
- var flg = str.getByte();
- if (cmf === -1 || flg === -1) {
- throw new _util.FormatError('Invalid header in flate stream: ' + cmf + ', ' + flg);
- }
- if ((cmf & 0x0f) !== 0x08) {
- throw new _util.FormatError('Unknown compression method in flate stream: ' + cmf + ', ' + flg);
- }
- if (((cmf << 8) + flg) % 31 !== 0) {
- throw new _util.FormatError('Bad FCHECK in flate stream: ' + cmf + ', ' + flg);
- }
- if (flg & 0x20) {
- throw new _util.FormatError('FDICT bit set in flate stream: ' + cmf + ', ' + flg);
- }
- this.codeSize = 0;
- this.codeBuf = 0;
- DecodeStream.call(this, maybeLength);
- }
- FlateStream.prototype = Object.create(DecodeStream.prototype);
- FlateStream.prototype.getBits = function FlateStream_getBits(bits) {
- var str = this.str;
- var codeSize = this.codeSize;
- var codeBuf = this.codeBuf;
- var b;
- while (codeSize < bits) {
- if ((b = str.getByte()) === -1) {
- throw new _util.FormatError('Bad encoding in flate stream');
- }
- codeBuf |= b << codeSize;
- codeSize += 8;
- }
- b = codeBuf & (1 << bits) - 1;
- this.codeBuf = codeBuf >> bits;
- this.codeSize = codeSize -= bits;
- return b;
- };
- FlateStream.prototype.getCode = function FlateStream_getCode(table) {
- var str = this.str;
- var codes = table[0];
- var maxLen = table[1];
- var codeSize = this.codeSize;
- var codeBuf = this.codeBuf;
- var b;
- while (codeSize < maxLen) {
- if ((b = str.getByte()) === -1) {
- break;
- }
- codeBuf |= b << codeSize;
- codeSize += 8;
- }
- var code = codes[codeBuf & (1 << maxLen) - 1];
- var codeLen = code >> 16;
- var codeVal = code & 0xffff;
- if (codeLen < 1 || codeSize < codeLen) {
- throw new _util.FormatError('Bad encoding in flate stream');
- }
- this.codeBuf = codeBuf >> codeLen;
- this.codeSize = codeSize - codeLen;
- return codeVal;
- };
- FlateStream.prototype.generateHuffmanTable = function flateStreamGenerateHuffmanTable(lengths) {
- var n = lengths.length;
- var maxLen = 0;
- var i;
- for (i = 0; i < n; ++i) {
- if (lengths[i] > maxLen) {
- maxLen = lengths[i];
- }
- }
- var size = 1 << maxLen;
- var codes = new Int32Array(size);
- for (var len = 1, code = 0, skip = 2; len <= maxLen; ++len, code <<= 1, skip <<= 1) {
- for (var val = 0; val < n; ++val) {
- if (lengths[val] === len) {
- var code2 = 0;
- var t = code;
- for (i = 0; i < len; ++i) {
- code2 = code2 << 1 | t & 1;
- t >>= 1;
- }
- for (i = code2; i < size; i += skip) {
- codes[i] = len << 16 | val;
- }
- ++code;
- }
- }
- }
- return [codes, maxLen];
- };
- FlateStream.prototype.readBlock = function FlateStream_readBlock() {
- var buffer, len;
- var str = this.str;
- var hdr = this.getBits(3);
- if (hdr & 1) {
- this.eof = true;
- }
- hdr >>= 1;
- if (hdr === 0) {
- var b;
- if ((b = str.getByte()) === -1) {
- throw new _util.FormatError('Bad block header in flate stream');
- }
- var blockLen = b;
- if ((b = str.getByte()) === -1) {
- throw new _util.FormatError('Bad block header in flate stream');
- }
- blockLen |= b << 8;
- if ((b = str.getByte()) === -1) {
- throw new _util.FormatError('Bad block header in flate stream');
- }
- var check = b;
- if ((b = str.getByte()) === -1) {
- throw new _util.FormatError('Bad block header in flate stream');
- }
- check |= b << 8;
- if (check !== (~blockLen & 0xffff) && (blockLen !== 0 || check !== 0)) {
- throw new _util.FormatError('Bad uncompressed block length in flate stream');
- }
- this.codeBuf = 0;
- this.codeSize = 0;
- var bufferLength = this.bufferLength;
- buffer = this.ensureBuffer(bufferLength + blockLen);
- var end = bufferLength + blockLen;
- this.bufferLength = end;
- if (blockLen === 0) {
- if (str.peekByte() === -1) {
- this.eof = true;
- }
- } else {
- for (var n = bufferLength; n < end; ++n) {
- if ((b = str.getByte()) === -1) {
- this.eof = true;
- break;
- }
- buffer[n] = b;
- }
- }
- return;
- }
- var litCodeTable;
- var distCodeTable;
- if (hdr === 1) {
- litCodeTable = fixedLitCodeTab;
- distCodeTable = fixedDistCodeTab;
- } else if (hdr === 2) {
- var numLitCodes = this.getBits(5) + 257;
- var numDistCodes = this.getBits(5) + 1;
- var numCodeLenCodes = this.getBits(4) + 4;
- var codeLenCodeLengths = new Uint8Array(codeLenCodeMap.length);
- var i;
- for (i = 0; i < numCodeLenCodes; ++i) {
- codeLenCodeLengths[codeLenCodeMap[i]] = this.getBits(3);
- }
- var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths);
- len = 0;
- i = 0;
- var codes = numLitCodes + numDistCodes;
- var codeLengths = new Uint8Array(codes);
- var bitsLength, bitsOffset, what;
- while (i < codes) {
- var code = this.getCode(codeLenCodeTab);
- if (code === 16) {
- bitsLength = 2;
- bitsOffset = 3;
- what = len;
- } else if (code === 17) {
- bitsLength = 3;
- bitsOffset = 3;
- what = len = 0;
- } else if (code === 18) {
- bitsLength = 7;
- bitsOffset = 11;
- what = len = 0;
- } else {
- codeLengths[i++] = len = code;
- continue;
- }
- var repeatLength = this.getBits(bitsLength) + bitsOffset;
- while (repeatLength-- > 0) {
- codeLengths[i++] = what;
- }
- }
- litCodeTable = this.generateHuffmanTable(codeLengths.subarray(0, numLitCodes));
- distCodeTable = this.generateHuffmanTable(codeLengths.subarray(numLitCodes, codes));
- } else {
- throw new _util.FormatError('Unknown block type in flate stream');
- }
- buffer = this.buffer;
- var limit = buffer ? buffer.length : 0;
- var pos = this.bufferLength;
- while (true) {
- var code1 = this.getCode(litCodeTable);
- if (code1 < 256) {
- if (pos + 1 >= limit) {
- buffer = this.ensureBuffer(pos + 1);
- limit = buffer.length;
- }
- buffer[pos++] = code1;
- continue;
- }
- if (code1 === 256) {
- this.bufferLength = pos;
- return;
- }
- code1 -= 257;
- code1 = lengthDecode[code1];
- var code2 = code1 >> 16;
- if (code2 > 0) {
- code2 = this.getBits(code2);
- }
- len = (code1 & 0xffff) + code2;
- code1 = this.getCode(distCodeTable);
- code1 = distDecode[code1];
- code2 = code1 >> 16;
- if (code2 > 0) {
- code2 = this.getBits(code2);
- }
- var dist = (code1 & 0xffff) + code2;
- if (pos + len >= limit) {
- buffer = this.ensureBuffer(pos + len);
- limit = buffer.length;
- }
- for (var k = 0; k < len; ++k, ++pos) {
- buffer[pos] = buffer[pos - dist];
- }
- }
- };
- return FlateStream;
-}();
-var PredictorStream = function PredictorStreamClosure() {
- function PredictorStream(str, maybeLength, params) {
- if (!(0, _primitives.isDict)(params)) {
- return str;
- }
- var predictor = this.predictor = params.get('Predictor') || 1;
- if (predictor <= 1) {
- return str;
- }
- if (predictor !== 2 && (predictor < 10 || predictor > 15)) {
- throw new _util.FormatError('Unsupported predictor: ' + predictor);
- }
- if (predictor === 2) {
- this.readBlock = this.readBlockTiff;
- } else {
- this.readBlock = this.readBlockPng;
- }
- this.str = str;
- this.dict = str.dict;
- var colors = this.colors = params.get('Colors') || 1;
- var bits = this.bits = params.get('BitsPerComponent') || 8;
- var columns = this.columns = params.get('Columns') || 1;
- this.pixBytes = colors * bits + 7 >> 3;
- this.rowBytes = columns * colors * bits + 7 >> 3;
- DecodeStream.call(this, maybeLength);
- return this;
- }
- PredictorStream.prototype = Object.create(DecodeStream.prototype);
- PredictorStream.prototype.readBlockTiff = function predictorStreamReadBlockTiff() {
- var rowBytes = this.rowBytes;
- var bufferLength = this.bufferLength;
- var buffer = this.ensureBuffer(bufferLength + rowBytes);
- var bits = this.bits;
- var colors = this.colors;
- var rawBytes = this.str.getBytes(rowBytes);
- this.eof = !rawBytes.length;
- if (this.eof) {
- return;
- }
- var inbuf = 0,
- outbuf = 0;
- var inbits = 0,
- outbits = 0;
- var pos = bufferLength;
- var i;
- if (bits === 1 && colors === 1) {
- for (i = 0; i < rowBytes; ++i) {
- var c = rawBytes[i] ^ inbuf;
- c ^= c >> 1;
- c ^= c >> 2;
- c ^= c >> 4;
- inbuf = (c & 1) << 7;
- buffer[pos++] = c;
- }
- } else if (bits === 8) {
- for (i = 0; i < colors; ++i) {
- buffer[pos++] = rawBytes[i];
- }
- for (; i < rowBytes; ++i) {
- buffer[pos] = buffer[pos - colors] + rawBytes[i];
- pos++;
- }
- } else if (bits === 16) {
- var bytesPerPixel = colors * 2;
- for (i = 0; i < bytesPerPixel; ++i) {
- buffer[pos++] = rawBytes[i];
- }
- for (; i < rowBytes; i += 2) {
- var sum = ((rawBytes[i] & 0xFF) << 8) + (rawBytes[i + 1] & 0xFF) + ((buffer[pos - bytesPerPixel] & 0xFF) << 8) + (buffer[pos - bytesPerPixel + 1] & 0xFF);
- buffer[pos++] = sum >> 8 & 0xFF;
- buffer[pos++] = sum & 0xFF;
- }
- } else {
- var compArray = new Uint8Array(colors + 1);
- var bitMask = (1 << bits) - 1;
- var j = 0,
- k = bufferLength;
- var columns = this.columns;
- for (i = 0; i < columns; ++i) {
- for (var kk = 0; kk < colors; ++kk) {
- if (inbits < bits) {
- inbuf = inbuf << 8 | rawBytes[j++] & 0xFF;
- inbits += 8;
- }
- compArray[kk] = compArray[kk] + (inbuf >> inbits - bits) & bitMask;
- inbits -= bits;
- outbuf = outbuf << bits | compArray[kk];
- outbits += bits;
- if (outbits >= 8) {
- buffer[k++] = outbuf >> outbits - 8 & 0xFF;
- outbits -= 8;
- }
- }
- }
- if (outbits > 0) {
- buffer[k++] = (outbuf << 8 - outbits) + (inbuf & (1 << 8 - outbits) - 1);
- }
- }
- this.bufferLength += rowBytes;
- };
- PredictorStream.prototype.readBlockPng = function predictorStreamReadBlockPng() {
- var rowBytes = this.rowBytes;
- var pixBytes = this.pixBytes;
- var predictor = this.str.getByte();
- var rawBytes = this.str.getBytes(rowBytes);
- this.eof = !rawBytes.length;
- if (this.eof) {
- return;
- }
- var bufferLength = this.bufferLength;
- var buffer = this.ensureBuffer(bufferLength + rowBytes);
- var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength);
- if (prevRow.length === 0) {
- prevRow = new Uint8Array(rowBytes);
- }
- var i,
- j = bufferLength,
- up,
- c;
- switch (predictor) {
- case 0:
- for (i = 0; i < rowBytes; ++i) {
- buffer[j++] = rawBytes[i];
- }
- break;
- case 1:
- for (i = 0; i < pixBytes; ++i) {
- buffer[j++] = rawBytes[i];
- }
- for (; i < rowBytes; ++i) {
- buffer[j] = buffer[j - pixBytes] + rawBytes[i] & 0xFF;
- j++;
- }
- break;
- case 2:
- for (i = 0; i < rowBytes; ++i) {
- buffer[j++] = prevRow[i] + rawBytes[i] & 0xFF;
- }
- break;
- case 3:
- for (i = 0; i < pixBytes; ++i) {
- buffer[j++] = (prevRow[i] >> 1) + rawBytes[i];
- }
- for (; i < rowBytes; ++i) {
- buffer[j] = (prevRow[i] + buffer[j - pixBytes] >> 1) + rawBytes[i] & 0xFF;
- j++;
- }
- break;
- case 4:
- for (i = 0; i < pixBytes; ++i) {
- up = prevRow[i];
- c = rawBytes[i];
- buffer[j++] = up + c;
- }
- for (; i < rowBytes; ++i) {
- up = prevRow[i];
- var upLeft = prevRow[i - pixBytes];
- var left = buffer[j - pixBytes];
- var p = left + up - upLeft;
- var pa = p - left;
- if (pa < 0) {
- pa = -pa;
- }
- var pb = p - up;
- if (pb < 0) {
- pb = -pb;
- }
- var pc = p - upLeft;
- if (pc < 0) {
- pc = -pc;
- }
- c = rawBytes[i];
- if (pa <= pb && pa <= pc) {
- buffer[j++] = left + c;
- } else if (pb <= pc) {
- buffer[j++] = up + c;
- } else {
- buffer[j++] = upLeft + c;
- }
- }
- break;
- default:
- throw new _util.FormatError('Unsupported predictor: ' + predictor);
- }
- this.bufferLength += rowBytes;
- };
- return PredictorStream;
-}();
-var DecryptStream = function DecryptStreamClosure() {
- function DecryptStream(str, maybeLength, decrypt) {
- this.str = str;
- this.dict = str.dict;
- this.decrypt = decrypt;
- this.nextChunk = null;
- this.initialized = false;
- DecodeStream.call(this, maybeLength);
- }
- var chunkSize = 512;
- DecryptStream.prototype = Object.create(DecodeStream.prototype);
- DecryptStream.prototype.readBlock = function DecryptStream_readBlock() {
- var chunk;
- if (this.initialized) {
- chunk = this.nextChunk;
- } else {
- chunk = this.str.getBytes(chunkSize);
- this.initialized = true;
- }
- if (!chunk || chunk.length === 0) {
- this.eof = true;
- return;
- }
- this.nextChunk = this.str.getBytes(chunkSize);
- var hasMoreData = this.nextChunk && this.nextChunk.length > 0;
- var decrypt = this.decrypt;
- chunk = decrypt(chunk, !hasMoreData);
- var bufferLength = this.bufferLength;
- var i,
- n = chunk.length;
- var buffer = this.ensureBuffer(bufferLength + n);
- for (i = 0; i < n; i++) {
- buffer[bufferLength++] = chunk[i];
- }
- this.bufferLength = bufferLength;
- };
- return DecryptStream;
-}();
-var Ascii85Stream = function Ascii85StreamClosure() {
- function Ascii85Stream(str, maybeLength) {
- this.str = str;
- this.dict = str.dict;
- this.input = new Uint8Array(5);
- if (maybeLength) {
- maybeLength = 0.8 * maybeLength;
- }
- DecodeStream.call(this, maybeLength);
- }
- Ascii85Stream.prototype = Object.create(DecodeStream.prototype);
- Ascii85Stream.prototype.readBlock = function Ascii85Stream_readBlock() {
- var TILDA_CHAR = 0x7E;
- var Z_LOWER_CHAR = 0x7A;
- var EOF = -1;
- var str = this.str;
- var c = str.getByte();
- while ((0, _util.isSpace)(c)) {
- c = str.getByte();
- }
- if (c === EOF || c === TILDA_CHAR) {
- this.eof = true;
- return;
- }
- var bufferLength = this.bufferLength,
- buffer;
- var i;
- if (c === Z_LOWER_CHAR) {
- buffer = this.ensureBuffer(bufferLength + 4);
- for (i = 0; i < 4; ++i) {
- buffer[bufferLength + i] = 0;
- }
- this.bufferLength += 4;
- } else {
- var input = this.input;
- input[0] = c;
- for (i = 1; i < 5; ++i) {
- c = str.getByte();
- while ((0, _util.isSpace)(c)) {
- c = str.getByte();
- }
- input[i] = c;
- if (c === EOF || c === TILDA_CHAR) {
- break;
- }
- }
- buffer = this.ensureBuffer(bufferLength + i - 1);
- this.bufferLength += i - 1;
- if (i < 5) {
- for (; i < 5; ++i) {
- input[i] = 0x21 + 84;
- }
- this.eof = true;
- }
- var t = 0;
- for (i = 0; i < 5; ++i) {
- t = t * 85 + (input[i] - 0x21);
- }
- for (i = 3; i >= 0; --i) {
- buffer[bufferLength + i] = t & 0xFF;
- t >>= 8;
- }
- }
- };
- return Ascii85Stream;
-}();
-var AsciiHexStream = function AsciiHexStreamClosure() {
- function AsciiHexStream(str, maybeLength) {
- this.str = str;
- this.dict = str.dict;
- this.firstDigit = -1;
- if (maybeLength) {
- maybeLength = 0.5 * maybeLength;
- }
- DecodeStream.call(this, maybeLength);
- }
- AsciiHexStream.prototype = Object.create(DecodeStream.prototype);
- AsciiHexStream.prototype.readBlock = function AsciiHexStream_readBlock() {
- var UPSTREAM_BLOCK_SIZE = 8000;
- var bytes = this.str.getBytes(UPSTREAM_BLOCK_SIZE);
- if (!bytes.length) {
- this.eof = true;
- return;
- }
- var maxDecodeLength = bytes.length + 1 >> 1;
- var buffer = this.ensureBuffer(this.bufferLength + maxDecodeLength);
- var bufferLength = this.bufferLength;
- var firstDigit = this.firstDigit;
- for (var i = 0, ii = bytes.length; i < ii; i++) {
- var ch = bytes[i],
- digit;
- if (ch >= 0x30 && ch <= 0x39) {
- digit = ch & 0x0F;
- } else if (ch >= 0x41 && ch <= 0x46 || ch >= 0x61 && ch <= 0x66) {
- digit = (ch & 0x0F) + 9;
- } else if (ch === 0x3E) {
- this.eof = true;
- break;
- } else {
- continue;
- }
- if (firstDigit < 0) {
- firstDigit = digit;
- } else {
- buffer[bufferLength++] = firstDigit << 4 | digit;
- firstDigit = -1;
- }
- }
- if (firstDigit >= 0 && this.eof) {
- buffer[bufferLength++] = firstDigit << 4;
- firstDigit = -1;
- }
- this.firstDigit = firstDigit;
- this.bufferLength = bufferLength;
- };
- return AsciiHexStream;
-}();
-var RunLengthStream = function RunLengthStreamClosure() {
- function RunLengthStream(str, maybeLength) {
- this.str = str;
- this.dict = str.dict;
- DecodeStream.call(this, maybeLength);
- }
- RunLengthStream.prototype = Object.create(DecodeStream.prototype);
- RunLengthStream.prototype.readBlock = function RunLengthStream_readBlock() {
- var repeatHeader = this.str.getBytes(2);
- if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] === 128) {
- this.eof = true;
- return;
- }
- var buffer;
- var bufferLength = this.bufferLength;
- var n = repeatHeader[0];
- if (n < 128) {
- buffer = this.ensureBuffer(bufferLength + n + 1);
- buffer[bufferLength++] = repeatHeader[1];
- if (n > 0) {
- var source = this.str.getBytes(n);
- buffer.set(source, bufferLength);
- bufferLength += n;
- }
- } else {
- n = 257 - n;
- var b = repeatHeader[1];
- buffer = this.ensureBuffer(bufferLength + n + 1);
- for (var i = 0; i < n; i++) {
- buffer[bufferLength++] = b;
- }
- }
- this.bufferLength = bufferLength;
- };
- return RunLengthStream;
-}();
-var LZWStream = function LZWStreamClosure() {
- function LZWStream(str, maybeLength, earlyChange) {
- this.str = str;
- this.dict = str.dict;
- this.cachedData = 0;
- this.bitsCached = 0;
- var maxLzwDictionarySize = 4096;
- var lzwState = {
- earlyChange: earlyChange,
- codeLength: 9,
- nextCode: 258,
- dictionaryValues: new Uint8Array(maxLzwDictionarySize),
- dictionaryLengths: new Uint16Array(maxLzwDictionarySize),
- dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize),
- currentSequence: new Uint8Array(maxLzwDictionarySize),
- currentSequenceLength: 0
- };
- for (var i = 0; i < 256; ++i) {
- lzwState.dictionaryValues[i] = i;
- lzwState.dictionaryLengths[i] = 1;
- }
- this.lzwState = lzwState;
- DecodeStream.call(this, maybeLength);
- }
- LZWStream.prototype = Object.create(DecodeStream.prototype);
- LZWStream.prototype.readBits = function LZWStream_readBits(n) {
- var bitsCached = this.bitsCached;
- var cachedData = this.cachedData;
- while (bitsCached < n) {
- var c = this.str.getByte();
- if (c === -1) {
- this.eof = true;
- return null;
- }
- cachedData = cachedData << 8 | c;
- bitsCached += 8;
- }
- this.bitsCached = bitsCached -= n;
- this.cachedData = cachedData;
- this.lastCode = null;
- return cachedData >>> bitsCached & (1 << n) - 1;
- };
- LZWStream.prototype.readBlock = function LZWStream_readBlock() {
- var blockSize = 512;
- var estimatedDecodedSize = blockSize * 2,
- decodedSizeDelta = blockSize;
- var i, j, q;
- var lzwState = this.lzwState;
- if (!lzwState) {
- return;
- }
- var earlyChange = lzwState.earlyChange;
- var nextCode = lzwState.nextCode;
- var dictionaryValues = lzwState.dictionaryValues;
- var dictionaryLengths = lzwState.dictionaryLengths;
- var dictionaryPrevCodes = lzwState.dictionaryPrevCodes;
- var codeLength = lzwState.codeLength;
- var prevCode = lzwState.prevCode;
- var currentSequence = lzwState.currentSequence;
- var currentSequenceLength = lzwState.currentSequenceLength;
- var decodedLength = 0;
- var currentBufferLength = this.bufferLength;
- var buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
- for (i = 0; i < blockSize; i++) {
- var code = this.readBits(codeLength);
- var hasPrev = currentSequenceLength > 0;
- if (code < 256) {
- currentSequence[0] = code;
- currentSequenceLength = 1;
- } else if (code >= 258) {
- if (code < nextCode) {
- currentSequenceLength = dictionaryLengths[code];
- for (j = currentSequenceLength - 1, q = code; j >= 0; j--) {
- currentSequence[j] = dictionaryValues[q];
- q = dictionaryPrevCodes[q];
- }
- } else {
- currentSequence[currentSequenceLength++] = currentSequence[0];
- }
- } else if (code === 256) {
- codeLength = 9;
- nextCode = 258;
- currentSequenceLength = 0;
- continue;
- } else {
- this.eof = true;
- delete this.lzwState;
- break;
- }
- if (hasPrev) {
- dictionaryPrevCodes[nextCode] = prevCode;
- dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1;
- dictionaryValues[nextCode] = currentSequence[0];
- nextCode++;
- codeLength = nextCode + earlyChange & nextCode + earlyChange - 1 ? codeLength : Math.min(Math.log(nextCode + earlyChange) / 0.6931471805599453 + 1, 12) | 0;
- }
- prevCode = code;
- decodedLength += currentSequenceLength;
- if (estimatedDecodedSize < decodedLength) {
- do {
- estimatedDecodedSize += decodedSizeDelta;
- } while (estimatedDecodedSize < decodedLength);
- buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
- }
- for (j = 0; j < currentSequenceLength; j++) {
- buffer[currentBufferLength++] = currentSequence[j];
- }
- }
- lzwState.nextCode = nextCode;
- lzwState.codeLength = codeLength;
- lzwState.prevCode = prevCode;
- lzwState.currentSequenceLength = currentSequenceLength;
- this.bufferLength = currentBufferLength;
- };
- return LZWStream;
-}();
-var NullStream = function NullStreamClosure() {
- function NullStream() {
- Stream.call(this, new Uint8Array(0));
- }
- NullStream.prototype = Stream.prototype;
- return NullStream;
-}();
-exports.Ascii85Stream = Ascii85Stream;
-exports.AsciiHexStream = AsciiHexStream;
-exports.DecryptStream = DecryptStream;
-exports.DecodeStream = DecodeStream;
-exports.FlateStream = FlateStream;
-exports.NullStream = NullStream;
-exports.PredictorStream = PredictorStream;
-exports.RunLengthStream = RunLengthStream;
-exports.Stream = Stream;
-exports.StreamsSequenceStream = StreamsSequenceStream;
-exports.StringStream = StringStream;
-exports.LZWStream = LZWStream;
-
-/***/ }),
-/* 141 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.CCITTFaxStream = undefined;
-
-var _primitives = __w_pdfjs_require__(138);
-
-var _ccitt = __w_pdfjs_require__(142);
-
-var _stream = __w_pdfjs_require__(140);
-
-var CCITTFaxStream = function CCITTFaxStreamClosure() {
- function CCITTFaxStream(str, maybeLength, params) {
- this.str = str;
- this.dict = str.dict;
- if (!(0, _primitives.isDict)(params)) {
- params = _primitives.Dict.empty;
- }
- var source = {
- next: function next() {
- return str.getByte();
- }
- };
- this.ccittFaxDecoder = new _ccitt.CCITTFaxDecoder(source, {
- K: params.get('K'),
- EndOfLine: params.get('EndOfLine'),
- EncodedByteAlign: params.get('EncodedByteAlign'),
- Columns: params.get('Columns'),
- Rows: params.get('Rows'),
- EndOfBlock: params.get('EndOfBlock'),
- BlackIs1: params.get('BlackIs1')
- });
- _stream.DecodeStream.call(this, maybeLength);
- }
- CCITTFaxStream.prototype = Object.create(_stream.DecodeStream.prototype);
- CCITTFaxStream.prototype.readBlock = function () {
- while (!this.eof) {
- var c = this.ccittFaxDecoder.readNextChar();
- if (c === -1) {
- this.eof = true;
- return;
- }
- this.ensureBuffer(this.bufferLength + 1);
- this.buffer[this.bufferLength++] = c;
- }
- };
- return CCITTFaxStream;
-}();
-exports.CCITTFaxStream = CCITTFaxStream;
-
-/***/ }),
-/* 142 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.CCITTFaxDecoder = undefined;
-
-var _util = __w_pdfjs_require__(2);
-
-var CCITTFaxDecoder = function CCITTFaxDecoder() {
- var ccittEOL = -2;
- var ccittEOF = -1;
- var twoDimPass = 0;
- var twoDimHoriz = 1;
- var twoDimVert0 = 2;
- var twoDimVertR1 = 3;
- var twoDimVertL1 = 4;
- var twoDimVertR2 = 5;
- var twoDimVertL2 = 6;
- var twoDimVertR3 = 7;
- var twoDimVertL3 = 8;
- var twoDimTable = [[-1, -1], [-1, -1], [7, twoDimVertL3], [7, twoDimVertR3], [6, twoDimVertL2], [6, twoDimVertL2], [6, twoDimVertR2], [6, twoDimVertR2], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0]];
- var whiteTable1 = [[-1, -1], [12, ccittEOL], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [11, 1792], [11, 1792], [12, 1984], [12, 2048], [12, 2112], [12, 2176], [12, 2240], [12, 2304], [11, 1856], [11, 1856], [11, 1920], [11, 1920], [12, 2368], [12, 2432], [12, 2496], [12, 2560]];
- var whiteTable2 = [[-1, -1], [-1, -1], [-1, -1], [-1, -1], [8, 29], [8, 29], [8, 30], [8, 30], [8, 45], [8, 45], [8, 46], [8, 46], [7, 22], [7, 22], [7, 22], [7, 22], [7, 23], [7, 23], [7, 23], [7, 23], [8, 47], [8, 47], [8, 48], [8, 48], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [7, 20], [7, 20], [7, 20], [7, 20], [8, 33], [8, 33], [8, 34], [8, 34], [8, 35], [8, 35], [8, 36], [8, 36], [8, 37], [8, 37], [8, 38], [8, 38], [7, 19], [7, 19], [7, 19], [7, 19], [8, 31], [8, 31], [8, 32], [8, 32], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [8, 53], [8, 53], [8, 54], [8, 54], [7, 26], [7, 26], [7, 26], [7, 26], [8, 39], [8, 39], [8, 40], [8, 40], [8, 41], [8, 41], [8, 42], [8, 42], [8, 43], [8, 43], [8, 44], [8, 44], [7, 21], [7, 21], [7, 21], [7, 21], [7, 28], [7, 28], [7, 28], [7, 28], [8, 61], [8, 61], [8, 62], [8, 62], [8, 63], [8, 63], [8, 0], [8, 0], [8, 320], [8, 320], [8, 384], [8, 384], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [7, 27], [7, 27], [7, 27], [7, 27], [8, 59], [8, 59], [8, 60], [8, 60], [9, 1472], [9, 1536], [9, 1600], [9, 1728], [7, 18], [7, 18], [7, 18], [7, 18], [7, 24], [7, 24], [7, 24], [7, 24], [8, 49], [8, 49], [8, 50], [8, 50], [8, 51], [8, 51], [8, 52], [8, 52], [7, 25], [7, 25], [7, 25], [7, 25], [8, 55], [8, 55], [8, 56], [8, 56], [8, 57], [8, 57], [8, 58], [8, 58], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [8, 448], [8, 448], [8, 512], [8, 512], [9, 704], [9, 768], [8, 640], [8, 640], [8, 576], [8, 576], [9, 832], [9, 896], [9, 960], [9, 1024], [9, 1088], [9, 1152], [9, 1216], [9, 1280], [9, 1344], [9, 1408], [7, 256], [7, 256], [7, 256], [7, 256], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7]];
- var blackTable1 = [[-1, -1], [-1, -1], [12, ccittEOL], [12, ccittEOL], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [11, 1792], [11, 1792], [11, 1792], [11, 1792], [12, 1984], [12, 1984], [12, 2048], [12, 2048], [12, 2112], [12, 2112], [12, 2176], [12, 2176], [12, 2240], [12, 2240], [12, 2304], [12, 2304], [11, 1856], [11, 1856], [11, 1856], [11, 1856], [11, 1920], [11, 1920], [11, 1920], [11, 1920], [12, 2368], [12, 2368], [12, 2432], [12, 2432], [12, 2496], [12, 2496], [12, 2560], [12, 2560], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [12, 52], [12, 52], [13, 640], [13, 704], [13, 768], [13, 832], [12, 55], [12, 55], [12, 56], [12, 56], [13, 1280], [13, 1344], [13, 1408], [13, 1472], [12, 59], [12, 59], [12, 60], [12, 60], [13, 1536], [13, 1600], [11, 24], [11, 24], [11, 24], [11, 24], [11, 25], [11, 25], [11, 25], [11, 25], [13, 1664], [13, 1728], [12, 320], [12, 320], [12, 384], [12, 384], [12, 448], [12, 448], [13, 512], [13, 576], [12, 53], [12, 53], [12, 54], [12, 54], [13, 896], [13, 960], [13, 1024], [13, 1088], [13, 1152], [13, 1216], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64]];
- var blackTable2 = [[8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [11, 23], [11, 23], [12, 50], [12, 51], [12, 44], [12, 45], [12, 46], [12, 47], [12, 57], [12, 58], [12, 61], [12, 256], [10, 16], [10, 16], [10, 16], [10, 16], [10, 17], [10, 17], [10, 17], [10, 17], [12, 48], [12, 49], [12, 62], [12, 63], [12, 30], [12, 31], [12, 32], [12, 33], [12, 40], [12, 41], [11, 22], [11, 22], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [12, 128], [12, 192], [12, 26], [12, 27], [12, 28], [12, 29], [11, 19], [11, 19], [11, 20], [11, 20], [12, 34], [12, 35], [12, 36], [12, 37], [12, 38], [12, 39], [11, 21], [11, 21], [12, 42], [12, 43], [10, 0], [10, 0], [10, 0], [10, 0], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12]];
- var blackTable3 = [[-1, -1], [-1, -1], [-1, -1], [-1, -1], [6, 9], [6, 8], [5, 7], [5, 7], [4, 6], [4, 6], [4, 6], [4, 6], [4, 5], [4, 5], [4, 5], [4, 5], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2]];
- function CCITTFaxDecoder(source) {
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
-
- if (!source || typeof source.next !== 'function') {
- throw new Error('CCITTFaxDecoder - invalid "source" parameter.');
- }
- this.source = source;
- this.eof = false;
- this.encoding = options['K'] || 0;
- this.eoline = options['EndOfLine'] || false;
- this.byteAlign = options['EncodedByteAlign'] || false;
- this.columns = options['Columns'] || 1728;
- this.rows = options['Rows'] || 0;
- var eoblock = options['EndOfBlock'];
- if (eoblock === null || eoblock === undefined) {
- eoblock = true;
- }
- this.eoblock = eoblock;
- this.black = options['BlackIs1'] || false;
- this.codingLine = new Uint32Array(this.columns + 1);
- this.refLine = new Uint32Array(this.columns + 2);
- this.codingLine[0] = this.columns;
- this.codingPos = 0;
- this.row = 0;
- this.nextLine2D = this.encoding < 0;
- this.inputBits = 0;
- this.inputBuf = 0;
- this.outputBits = 0;
- this.rowsDone = false;
- var code1 = void 0;
- while ((code1 = this._lookBits(12)) === 0) {
- this._eatBits(1);
- }
- if (code1 === 1) {
- this._eatBits(12);
- }
- if (this.encoding > 0) {
- this.nextLine2D = !this._lookBits(1);
- this._eatBits(1);
- }
- }
- CCITTFaxDecoder.prototype = {
- readNextChar: function readNextChar() {
- if (this.eof) {
- return -1;
- }
- var refLine = this.refLine;
- var codingLine = this.codingLine;
- var columns = this.columns;
- var refPos = void 0,
- blackPixels = void 0,
- bits = void 0,
- i = void 0;
- if (this.outputBits === 0) {
- if (this.rowsDone) {
- this.eof = true;
- }
- if (this.eof) {
- return -1;
- }
- this.err = false;
- var code1 = void 0,
- code2 = void 0,
- code3 = void 0;
- if (this.nextLine2D) {
- for (i = 0; codingLine[i] < columns; ++i) {
- refLine[i] = codingLine[i];
- }
- refLine[i++] = columns;
- refLine[i] = columns;
- codingLine[0] = 0;
- this.codingPos = 0;
- refPos = 0;
- blackPixels = 0;
- while (codingLine[this.codingPos] < columns) {
- code1 = this._getTwoDimCode();
- switch (code1) {
- case twoDimPass:
- this._addPixels(refLine[refPos + 1], blackPixels);
- if (refLine[refPos + 1] < columns) {
- refPos += 2;
- }
- break;
- case twoDimHoriz:
- code1 = code2 = 0;
- if (blackPixels) {
- do {
- code1 += code3 = this._getBlackCode();
- } while (code3 >= 64);
- do {
- code2 += code3 = this._getWhiteCode();
- } while (code3 >= 64);
- } else {
- do {
- code1 += code3 = this._getWhiteCode();
- } while (code3 >= 64);
- do {
- code2 += code3 = this._getBlackCode();
- } while (code3 >= 64);
- }
- this._addPixels(codingLine[this.codingPos] + code1, blackPixels);
- if (codingLine[this.codingPos] < columns) {
- this._addPixels(codingLine[this.codingPos] + code2, blackPixels ^ 1);
- }
- while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
- refPos += 2;
- }
- break;
- case twoDimVertR3:
- this._addPixels(refLine[refPos] + 3, blackPixels);
- blackPixels ^= 1;
- if (codingLine[this.codingPos] < columns) {
- ++refPos;
- while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
- refPos += 2;
- }
- }
- break;
- case twoDimVertR2:
- this._addPixels(refLine[refPos] + 2, blackPixels);
- blackPixels ^= 1;
- if (codingLine[this.codingPos] < columns) {
- ++refPos;
- while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
- refPos += 2;
- }
- }
- break;
- case twoDimVertR1:
- this._addPixels(refLine[refPos] + 1, blackPixels);
- blackPixels ^= 1;
- if (codingLine[this.codingPos] < columns) {
- ++refPos;
- while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
- refPos += 2;
- }
- }
- break;
- case twoDimVert0:
- this._addPixels(refLine[refPos], blackPixels);
- blackPixels ^= 1;
- if (codingLine[this.codingPos] < columns) {
- ++refPos;
- while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
- refPos += 2;
- }
- }
- break;
- case twoDimVertL3:
- this._addPixelsNeg(refLine[refPos] - 3, blackPixels);
- blackPixels ^= 1;
- if (codingLine[this.codingPos] < columns) {
- if (refPos > 0) {
- --refPos;
- } else {
- ++refPos;
- }
- while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
- refPos += 2;
- }
- }
- break;
- case twoDimVertL2:
- this._addPixelsNeg(refLine[refPos] - 2, blackPixels);
- blackPixels ^= 1;
- if (codingLine[this.codingPos] < columns) {
- if (refPos > 0) {
- --refPos;
- } else {
- ++refPos;
- }
- while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
- refPos += 2;
- }
- }
- break;
- case twoDimVertL1:
- this._addPixelsNeg(refLine[refPos] - 1, blackPixels);
- blackPixels ^= 1;
- if (codingLine[this.codingPos] < columns) {
- if (refPos > 0) {
- --refPos;
- } else {
- ++refPos;
- }
- while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
- refPos += 2;
- }
- }
- break;
- case ccittEOF:
- this._addPixels(columns, 0);
- this.eof = true;
- break;
- default:
- (0, _util.info)('bad 2d code');
- this._addPixels(columns, 0);
- this.err = true;
- }
- }
- } else {
- codingLine[0] = 0;
- this.codingPos = 0;
- blackPixels = 0;
- while (codingLine[this.codingPos] < columns) {
- code1 = 0;
- if (blackPixels) {
- do {
- code1 += code3 = this._getBlackCode();
- } while (code3 >= 64);
- } else {
- do {
- code1 += code3 = this._getWhiteCode();
- } while (code3 >= 64);
- }
- this._addPixels(codingLine[this.codingPos] + code1, blackPixels);
- blackPixels ^= 1;
- }
- }
- var gotEOL = false;
- if (this.byteAlign) {
- this.inputBits &= ~7;
- }
- if (!this.eoblock && this.row === this.rows - 1) {
- this.rowsDone = true;
- } else {
- code1 = this._lookBits(12);
- if (this.eoline) {
- while (code1 !== ccittEOF && code1 !== 1) {
- this._eatBits(1);
- code1 = this._lookBits(12);
- }
- } else {
- while (code1 === 0) {
- this._eatBits(1);
- code1 = this._lookBits(12);
- }
- }
- if (code1 === 1) {
- this._eatBits(12);
- gotEOL = true;
- } else if (code1 === ccittEOF) {
- this.eof = true;
- }
- }
- if (!this.eof && this.encoding > 0 && !this.rowsDone) {
- this.nextLine2D = !this._lookBits(1);
- this._eatBits(1);
- }
- if (this.eoblock && gotEOL && this.byteAlign) {
- code1 = this._lookBits(12);
- if (code1 === 1) {
- this._eatBits(12);
- if (this.encoding > 0) {
- this._lookBits(1);
- this._eatBits(1);
- }
- if (this.encoding >= 0) {
- for (i = 0; i < 4; ++i) {
- code1 = this._lookBits(12);
- if (code1 !== 1) {
- (0, _util.info)('bad rtc code: ' + code1);
- }
- this._eatBits(12);
- if (this.encoding > 0) {
- this._lookBits(1);
- this._eatBits(1);
- }
- }
- }
- this.eof = true;
- }
- } else if (this.err && this.eoline) {
- while (true) {
- code1 = this._lookBits(13);
- if (code1 === ccittEOF) {
- this.eof = true;
- return -1;
- }
- if (code1 >> 1 === 1) {
- break;
- }
- this._eatBits(1);
- }
- this._eatBits(12);
- if (this.encoding > 0) {
- this._eatBits(1);
- this.nextLine2D = !(code1 & 1);
- }
- }
- if (codingLine[0] > 0) {
- this.outputBits = codingLine[this.codingPos = 0];
- } else {
- this.outputBits = codingLine[this.codingPos = 1];
- }
- this.row++;
- }
- var c = void 0;
- if (this.outputBits >= 8) {
- c = this.codingPos & 1 ? 0 : 0xFF;
- this.outputBits -= 8;
- if (this.outputBits === 0 && codingLine[this.codingPos] < columns) {
- this.codingPos++;
- this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1];
- }
- } else {
- bits = 8;
- c = 0;
- do {
- if (this.outputBits > bits) {
- c <<= bits;
- if (!(this.codingPos & 1)) {
- c |= 0xFF >> 8 - bits;
- }
- this.outputBits -= bits;
- bits = 0;
- } else {
- c <<= this.outputBits;
- if (!(this.codingPos & 1)) {
- c |= 0xFF >> 8 - this.outputBits;
- }
- bits -= this.outputBits;
- this.outputBits = 0;
- if (codingLine[this.codingPos] < columns) {
- this.codingPos++;
- this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1];
- } else if (bits > 0) {
- c <<= bits;
- bits = 0;
- }
- }
- } while (bits);
- }
- if (this.black) {
- c ^= 0xFF;
- }
- return c;
- },
- _addPixels: function _addPixels(a1, blackPixels) {
- var codingLine = this.codingLine;
- var codingPos = this.codingPos;
- if (a1 > codingLine[codingPos]) {
- if (a1 > this.columns) {
- (0, _util.info)('row is wrong length');
- this.err = true;
- a1 = this.columns;
- }
- if (codingPos & 1 ^ blackPixels) {
- ++codingPos;
- }
- codingLine[codingPos] = a1;
- }
- this.codingPos = codingPos;
- },
- _addPixelsNeg: function _addPixelsNeg(a1, blackPixels) {
- var codingLine = this.codingLine;
- var codingPos = this.codingPos;
- if (a1 > codingLine[codingPos]) {
- if (a1 > this.columns) {
- (0, _util.info)('row is wrong length');
- this.err = true;
- a1 = this.columns;
- }
- if (codingPos & 1 ^ blackPixels) {
- ++codingPos;
- }
- codingLine[codingPos] = a1;
- } else if (a1 < codingLine[codingPos]) {
- if (a1 < 0) {
- (0, _util.info)('invalid code');
- this.err = true;
- a1 = 0;
- }
- while (codingPos > 0 && a1 < codingLine[codingPos - 1]) {
- --codingPos;
- }
- codingLine[codingPos] = a1;
- }
- this.codingPos = codingPos;
- },
- _findTableCode: function _findTableCode(start, end, table, limit) {
- var limitValue = limit || 0;
- for (var i = start; i <= end; ++i) {
- var code = this._lookBits(i);
- if (code === ccittEOF) {
- return [true, 1, false];
- }
- if (i < end) {
- code <<= end - i;
- }
- if (!limitValue || code >= limitValue) {
- var p = table[code - limitValue];
- if (p[0] === i) {
- this._eatBits(i);
- return [true, p[1], true];
- }
- }
- }
- return [false, 0, false];
- },
- _getTwoDimCode: function _getTwoDimCode() {
- var code = 0;
- var p = void 0;
- if (this.eoblock) {
- code = this._lookBits(7);
- p = twoDimTable[code];
- if (p && p[0] > 0) {
- this._eatBits(p[0]);
- return p[1];
- }
- } else {
- var result = this._findTableCode(1, 7, twoDimTable);
- if (result[0] && result[2]) {
- return result[1];
- }
- }
- (0, _util.info)('Bad two dim code');
- return ccittEOF;
- },
- _getWhiteCode: function _getWhiteCode() {
- var code = 0;
- var p = void 0;
- if (this.eoblock) {
- code = this._lookBits(12);
- if (code === ccittEOF) {
- return 1;
- }
- if (code >> 5 === 0) {
- p = whiteTable1[code];
- } else {
- p = whiteTable2[code >> 3];
- }
- if (p[0] > 0) {
- this._eatBits(p[0]);
- return p[1];
- }
- } else {
- var result = this._findTableCode(1, 9, whiteTable2);
- if (result[0]) {
- return result[1];
- }
- result = this._findTableCode(11, 12, whiteTable1);
- if (result[0]) {
- return result[1];
- }
- }
- (0, _util.info)('bad white code');
- this._eatBits(1);
- return 1;
- },
- _getBlackCode: function _getBlackCode() {
- var code = void 0,
- p = void 0;
- if (this.eoblock) {
- code = this._lookBits(13);
- if (code === ccittEOF) {
- return 1;
- }
- if (code >> 7 === 0) {
- p = blackTable1[code];
- } else if (code >> 9 === 0 && code >> 7 !== 0) {
- p = blackTable2[(code >> 1) - 64];
- } else {
- p = blackTable3[code >> 7];
- }
- if (p[0] > 0) {
- this._eatBits(p[0]);
- return p[1];
- }
- } else {
- var result = this._findTableCode(2, 6, blackTable3);
- if (result[0]) {
- return result[1];
- }
- result = this._findTableCode(7, 12, blackTable2, 64);
- if (result[0]) {
- return result[1];
- }
- result = this._findTableCode(10, 13, blackTable1);
- if (result[0]) {
- return result[1];
- }
- }
- (0, _util.info)('bad black code');
- this._eatBits(1);
- return 1;
- },
- _lookBits: function _lookBits(n) {
- var c = void 0;
- while (this.inputBits < n) {
- if ((c = this.source.next()) === -1) {
- if (this.inputBits === 0) {
- return ccittEOF;
- }
- return this.inputBuf << n - this.inputBits & 0xFFFF >> 16 - n;
- }
- this.inputBuf = this.inputBuf << 8 | c;
- this.inputBits += 8;
- }
- return this.inputBuf >> this.inputBits - n & 0xFFFF >> 16 - n;
- },
- _eatBits: function _eatBits(n) {
- if ((this.inputBits -= n) < 0) {
- this.inputBits = 0;
- }
- }
- };
- return CCITTFaxDecoder;
-}();
-exports.CCITTFaxDecoder = CCITTFaxDecoder;
-
-/***/ }),
-/* 143 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.Jbig2Stream = undefined;
-
-var _primitives = __w_pdfjs_require__(138);
-
-var _stream = __w_pdfjs_require__(140);
-
-var _jbig = __w_pdfjs_require__(144);
-
-var _util = __w_pdfjs_require__(2);
-
-var Jbig2Stream = function Jbig2StreamClosure() {
- function Jbig2Stream(stream, maybeLength, dict, params) {
- this.stream = stream;
- this.maybeLength = maybeLength;
- this.dict = dict;
- this.params = params;
- _stream.DecodeStream.call(this, maybeLength);
- }
- Jbig2Stream.prototype = Object.create(_stream.DecodeStream.prototype);
- Object.defineProperty(Jbig2Stream.prototype, 'bytes', {
- get: function get() {
- return (0, _util.shadow)(this, 'bytes', this.stream.getBytes(this.maybeLength));
- },
-
- configurable: true
- });
- Jbig2Stream.prototype.ensureBuffer = function (requested) {};
- Jbig2Stream.prototype.readBlock = function () {
- if (this.eof) {
- return;
- }
- var jbig2Image = new _jbig.Jbig2Image();
- var chunks = [];
- if ((0, _primitives.isDict)(this.params)) {
- var globalsStream = this.params.get('JBIG2Globals');
- if ((0, _primitives.isStream)(globalsStream)) {
- var globals = globalsStream.getBytes();
- chunks.push({
- data: globals,
- start: 0,
- end: globals.length
- });
- }
- }
- chunks.push({
- data: this.bytes,
- start: 0,
- end: this.bytes.length
- });
- var data = jbig2Image.parseChunks(chunks);
- var dataLength = data.length;
- for (var i = 0; i < dataLength; i++) {
- data[i] ^= 0xFF;
- }
- this.buffer = data;
- this.bufferLength = dataLength;
- this.eof = true;
- };
- return Jbig2Stream;
-}();
-exports.Jbig2Stream = Jbig2Stream;
-
-/***/ }),
-/* 144 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.Jbig2Image = undefined;
-
-var _util = __w_pdfjs_require__(2);
-
-var _arithmetic_decoder = __w_pdfjs_require__(145);
-
-var _ccitt = __w_pdfjs_require__(142);
-
-var Jbig2Error = function Jbig2ErrorClosure() {
- function Jbig2Error(msg) {
- this.message = 'JBIG2 error: ' + msg;
- }
- Jbig2Error.prototype = new Error();
- Jbig2Error.prototype.name = 'Jbig2Error';
- Jbig2Error.constructor = Jbig2Error;
- return Jbig2Error;
-}();
-var Jbig2Image = function Jbig2ImageClosure() {
- function ContextCache() {}
- ContextCache.prototype = {
- getContexts: function getContexts(id) {
- if (id in this) {
- return this[id];
- }
- return this[id] = new Int8Array(1 << 16);
- }
- };
- function DecodingContext(data, start, end) {
- this.data = data;
- this.start = start;
- this.end = end;
- }
- DecodingContext.prototype = {
- get decoder() {
- var decoder = new _arithmetic_decoder.ArithmeticDecoder(this.data, this.start, this.end);
- return (0, _util.shadow)(this, 'decoder', decoder);
- },
- get contextCache() {
- var cache = new ContextCache();
- return (0, _util.shadow)(this, 'contextCache', cache);
- }
- };
- function decodeInteger(contextCache, procedure, decoder) {
- var contexts = contextCache.getContexts(procedure);
- var prev = 1;
- function readBits(length) {
- var v = 0;
- for (var i = 0; i < length; i++) {
- var bit = decoder.readBit(contexts, prev);
- prev = prev < 256 ? prev << 1 | bit : (prev << 1 | bit) & 511 | 256;
- v = v << 1 | bit;
- }
- return v >>> 0;
- }
- var sign = readBits(1);
- var value = readBits(1) ? readBits(1) ? readBits(1) ? readBits(1) ? readBits(1) ? readBits(32) + 4436 : readBits(12) + 340 : readBits(8) + 84 : readBits(6) + 20 : readBits(4) + 4 : readBits(2);
- return sign === 0 ? value : value > 0 ? -value : null;
- }
- function decodeIAID(contextCache, decoder, codeLength) {
- var contexts = contextCache.getContexts('IAID');
- var prev = 1;
- for (var i = 0; i < codeLength; i++) {
- var bit = decoder.readBit(contexts, prev);
- prev = prev << 1 | bit;
- }
- if (codeLength < 31) {
- return prev & (1 << codeLength) - 1;
- }
- return prev & 0x7FFFFFFF;
- }
- var SegmentTypes = ['SymbolDictionary', null, null, null, 'IntermediateTextRegion', null, 'ImmediateTextRegion', 'ImmediateLosslessTextRegion', null, null, null, null, null, null, null, null, 'PatternDictionary', null, null, null, 'IntermediateHalftoneRegion', null, 'ImmediateHalftoneRegion', 'ImmediateLosslessHalftoneRegion', null, null, null, null, null, null, null, null, null, null, null, null, 'IntermediateGenericRegion', null, 'ImmediateGenericRegion', 'ImmediateLosslessGenericRegion', 'IntermediateGenericRefinementRegion', null, 'ImmediateGenericRefinementRegion', 'ImmediateLosslessGenericRefinementRegion', null, null, null, null, 'PageInformation', 'EndOfPage', 'EndOfStripe', 'EndOfFile', 'Profiles', 'Tables', null, null, null, null, null, null, null, null, 'Extension'];
- var CodingTemplates = [[{
- x: -1,
- y: -2
- }, {
- x: 0,
- y: -2
- }, {
- x: 1,
- y: -2
- }, {
- x: -2,
- y: -1
- }, {
- x: -1,
- y: -1
- }, {
- x: 0,
- y: -1
- }, {
- x: 1,
- y: -1
- }, {
- x: 2,
- y: -1
- }, {
- x: -4,
- y: 0
- }, {
- x: -3,
- y: 0
- }, {
- x: -2,
- y: 0
- }, {
- x: -1,
- y: 0
- }], [{
- x: -1,
- y: -2
- }, {
- x: 0,
- y: -2
- }, {
- x: 1,
- y: -2
- }, {
- x: 2,
- y: -2
- }, {
- x: -2,
- y: -1
- }, {
- x: -1,
- y: -1
- }, {
- x: 0,
- y: -1
- }, {
- x: 1,
- y: -1
- }, {
- x: 2,
- y: -1
- }, {
- x: -3,
- y: 0
- }, {
- x: -2,
- y: 0
- }, {
- x: -1,
- y: 0
- }], [{
- x: -1,
- y: -2
- }, {
- x: 0,
- y: -2
- }, {
- x: 1,
- y: -2
- }, {
- x: -2,
- y: -1
- }, {
- x: -1,
- y: -1
- }, {
- x: 0,
- y: -1
- }, {
- x: 1,
- y: -1
- }, {
- x: -2,
- y: 0
- }, {
- x: -1,
- y: 0
- }], [{
- x: -3,
- y: -1
- }, {
- x: -2,
- y: -1
- }, {
- x: -1,
- y: -1
- }, {
- x: 0,
- y: -1
- }, {
- x: 1,
- y: -1
- }, {
- x: -4,
- y: 0
- }, {
- x: -3,
- y: 0
- }, {
- x: -2,
- y: 0
- }, {
- x: -1,
- y: 0
- }]];
- var RefinementTemplates = [{
- coding: [{
- x: 0,
- y: -1
- }, {
- x: 1,
- y: -1
- }, {
- x: -1,
- y: 0
- }],
- reference: [{
- x: 0,
- y: -1
- }, {
- x: 1,
- y: -1
- }, {
- x: -1,
- y: 0
- }, {
- x: 0,
- y: 0
- }, {
- x: 1,
- y: 0
- }, {
- x: -1,
- y: 1
- }, {
- x: 0,
- y: 1
- }, {
- x: 1,
- y: 1
- }]
- }, {
- coding: [{
- x: -1,
- y: -1
- }, {
- x: 0,
- y: -1
- }, {
- x: 1,
- y: -1
- }, {
- x: -1,
- y: 0
- }],
- reference: [{
- x: 0,
- y: -1
- }, {
- x: -1,
- y: 0
- }, {
- x: 0,
- y: 0
- }, {
- x: 1,
- y: 0
- }, {
- x: 0,
- y: 1
- }, {
- x: 1,
- y: 1
- }]
- }];
- var ReusedContexts = [0x9B25, 0x0795, 0x00E5, 0x0195];
- var RefinementReusedContexts = [0x0020, 0x0008];
- function decodeBitmapTemplate0(width, height, decodingContext) {
- var decoder = decodingContext.decoder;
- var contexts = decodingContext.contextCache.getContexts('GB');
- var contextLabel,
- i,
- j,
- pixel,
- row,
- row1,
- row2,
- bitmap = [];
- var OLD_PIXEL_MASK = 0x7BF7;
- for (i = 0; i < height; i++) {
- row = bitmap[i] = new Uint8Array(width);
- row1 = i < 1 ? row : bitmap[i - 1];
- row2 = i < 2 ? row : bitmap[i - 2];
- contextLabel = row2[0] << 13 | row2[1] << 12 | row2[2] << 11 | row1[0] << 7 | row1[1] << 6 | row1[2] << 5 | row1[3] << 4;
- for (j = 0; j < width; j++) {
- row[j] = pixel = decoder.readBit(contexts, contextLabel);
- contextLabel = (contextLabel & OLD_PIXEL_MASK) << 1 | (j + 3 < width ? row2[j + 3] << 11 : 0) | (j + 4 < width ? row1[j + 4] << 4 : 0) | pixel;
- }
- }
- return bitmap;
- }
- function decodeBitmap(mmr, width, height, templateIndex, prediction, skip, at, decodingContext) {
- if (mmr) {
- var input = new Reader(decodingContext.data, decodingContext.start, decodingContext.end);
- return decodeMMRBitmap(input, width, height, false);
- }
- if (templateIndex === 0 && !skip && !prediction && at.length === 4 && at[0].x === 3 && at[0].y === -1 && at[1].x === -3 && at[1].y === -1 && at[2].x === 2 && at[2].y === -2 && at[3].x === -2 && at[3].y === -2) {
- return decodeBitmapTemplate0(width, height, decodingContext);
- }
- var useskip = !!skip;
- var template = CodingTemplates[templateIndex].concat(at);
- template.sort(function (a, b) {
- return a.y - b.y || a.x - b.x;
- });
- var templateLength = template.length;
- var templateX = new Int8Array(templateLength);
- var templateY = new Int8Array(templateLength);
- var changingTemplateEntries = [];
- var reuseMask = 0,
- minX = 0,
- maxX = 0,
- minY = 0;
- var c, k;
- for (k = 0; k < templateLength; k++) {
- templateX[k] = template[k].x;
- templateY[k] = template[k].y;
- minX = Math.min(minX, template[k].x);
- maxX = Math.max(maxX, template[k].x);
- minY = Math.min(minY, template[k].y);
- if (k < templateLength - 1 && template[k].y === template[k + 1].y && template[k].x === template[k + 1].x - 1) {
- reuseMask |= 1 << templateLength - 1 - k;
- } else {
- changingTemplateEntries.push(k);
- }
- }
- var changingEntriesLength = changingTemplateEntries.length;
- var changingTemplateX = new Int8Array(changingEntriesLength);
- var changingTemplateY = new Int8Array(changingEntriesLength);
- var changingTemplateBit = new Uint16Array(changingEntriesLength);
- for (c = 0; c < changingEntriesLength; c++) {
- k = changingTemplateEntries[c];
- changingTemplateX[c] = template[k].x;
- changingTemplateY[c] = template[k].y;
- changingTemplateBit[c] = 1 << templateLength - 1 - k;
- }
- var sbb_left = -minX;
- var sbb_top = -minY;
- var sbb_right = width - maxX;
- var pseudoPixelContext = ReusedContexts[templateIndex];
- var row = new Uint8Array(width);
- var bitmap = [];
- var decoder = decodingContext.decoder;
- var contexts = decodingContext.contextCache.getContexts('GB');
- var ltp = 0,
- j,
- i0,
- j0,
- contextLabel = 0,
- bit,
- shift;
- for (var i = 0; i < height; i++) {
- if (prediction) {
- var sltp = decoder.readBit(contexts, pseudoPixelContext);
- ltp ^= sltp;
- if (ltp) {
- bitmap.push(row);
- continue;
- }
- }
- row = new Uint8Array(row);
- bitmap.push(row);
- for (j = 0; j < width; j++) {
- if (useskip && skip[i][j]) {
- row[j] = 0;
- continue;
- }
- if (j >= sbb_left && j < sbb_right && i >= sbb_top) {
- contextLabel = contextLabel << 1 & reuseMask;
- for (k = 0; k < changingEntriesLength; k++) {
- i0 = i + changingTemplateY[k];
- j0 = j + changingTemplateX[k];
- bit = bitmap[i0][j0];
- if (bit) {
- bit = changingTemplateBit[k];
- contextLabel |= bit;
- }
- }
- } else {
- contextLabel = 0;
- shift = templateLength - 1;
- for (k = 0; k < templateLength; k++, shift--) {
- j0 = j + templateX[k];
- if (j0 >= 0 && j0 < width) {
- i0 = i + templateY[k];
- if (i0 >= 0) {
- bit = bitmap[i0][j0];
- if (bit) {
- contextLabel |= bit << shift;
- }
- }
- }
- }
- }
- var pixel = decoder.readBit(contexts, contextLabel);
- row[j] = pixel;
- }
- }
- return bitmap;
- }
- function decodeRefinement(width, height, templateIndex, referenceBitmap, offsetX, offsetY, prediction, at, decodingContext) {
- var codingTemplate = RefinementTemplates[templateIndex].coding;
- if (templateIndex === 0) {
- codingTemplate = codingTemplate.concat([at[0]]);
- }
- var codingTemplateLength = codingTemplate.length;
- var codingTemplateX = new Int32Array(codingTemplateLength);
- var codingTemplateY = new Int32Array(codingTemplateLength);
- var k;
- for (k = 0; k < codingTemplateLength; k++) {
- codingTemplateX[k] = codingTemplate[k].x;
- codingTemplateY[k] = codingTemplate[k].y;
- }
- var referenceTemplate = RefinementTemplates[templateIndex].reference;
- if (templateIndex === 0) {
- referenceTemplate = referenceTemplate.concat([at[1]]);
- }
- var referenceTemplateLength = referenceTemplate.length;
- var referenceTemplateX = new Int32Array(referenceTemplateLength);
- var referenceTemplateY = new Int32Array(referenceTemplateLength);
- for (k = 0; k < referenceTemplateLength; k++) {
- referenceTemplateX[k] = referenceTemplate[k].x;
- referenceTemplateY[k] = referenceTemplate[k].y;
- }
- var referenceWidth = referenceBitmap[0].length;
- var referenceHeight = referenceBitmap.length;
- var pseudoPixelContext = RefinementReusedContexts[templateIndex];
- var bitmap = [];
- var decoder = decodingContext.decoder;
- var contexts = decodingContext.contextCache.getContexts('GR');
- var ltp = 0;
- for (var i = 0; i < height; i++) {
- if (prediction) {
- var sltp = decoder.readBit(contexts, pseudoPixelContext);
- ltp ^= sltp;
- if (ltp) {
- throw new Jbig2Error('prediction is not supported');
- }
- }
- var row = new Uint8Array(width);
- bitmap.push(row);
- for (var j = 0; j < width; j++) {
- var i0, j0;
- var contextLabel = 0;
- for (k = 0; k < codingTemplateLength; k++) {
- i0 = i + codingTemplateY[k];
- j0 = j + codingTemplateX[k];
- if (i0 < 0 || j0 < 0 || j0 >= width) {
- contextLabel <<= 1;
- } else {
- contextLabel = contextLabel << 1 | bitmap[i0][j0];
- }
- }
- for (k = 0; k < referenceTemplateLength; k++) {
- i0 = i + referenceTemplateY[k] - offsetY;
- j0 = j + referenceTemplateX[k] - offsetX;
- if (i0 < 0 || i0 >= referenceHeight || j0 < 0 || j0 >= referenceWidth) {
- contextLabel <<= 1;
- } else {
- contextLabel = contextLabel << 1 | referenceBitmap[i0][j0];
- }
- }
- var pixel = decoder.readBit(contexts, contextLabel);
- row[j] = pixel;
- }
- }
- return bitmap;
- }
- function decodeSymbolDictionary(huffman, refinement, symbols, numberOfNewSymbols, numberOfExportedSymbols, huffmanTables, templateIndex, at, refinementTemplateIndex, refinementAt, decodingContext, huffmanInput) {
- if (huffman && refinement) {
- throw new Jbig2Error('symbol refinement with Huffman is not supported');
- }
- var newSymbols = [];
- var currentHeight = 0;
- var symbolCodeLength = (0, _util.log2)(symbols.length + numberOfNewSymbols);
- var decoder = decodingContext.decoder;
- var contextCache = decodingContext.contextCache;
- var tableB1 = void 0,
- symbolWidths = void 0;
- if (huffman) {
- tableB1 = getStandardTable(1);
- symbolWidths = [];
- symbolCodeLength = Math.max(symbolCodeLength, 1);
- }
- while (newSymbols.length < numberOfNewSymbols) {
- var deltaHeight = huffman ? huffmanTables.tableDeltaHeight.decode(huffmanInput) : decodeInteger(contextCache, 'IADH', decoder);
- currentHeight += deltaHeight;
- var currentWidth = 0,
- totalWidth = 0;
- var firstSymbol = huffman ? symbolWidths.length : 0;
- while (true) {
- var deltaWidth = huffman ? huffmanTables.tableDeltaWidth.decode(huffmanInput) : decodeInteger(contextCache, 'IADW', decoder);
- if (deltaWidth === null) {
- break;
- }
- currentWidth += deltaWidth;
- totalWidth += currentWidth;
- var bitmap;
- if (refinement) {
- var numberOfInstances = decodeInteger(contextCache, 'IAAI', decoder);
- if (numberOfInstances > 1) {
- bitmap = decodeTextRegion(huffman, refinement, currentWidth, currentHeight, 0, numberOfInstances, 1, symbols.concat(newSymbols), symbolCodeLength, 0, 0, 1, 0, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext, 0, huffmanInput);
- } else {
- var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength);
- var rdx = decodeInteger(contextCache, 'IARDX', decoder);
- var rdy = decodeInteger(contextCache, 'IARDY', decoder);
- var symbol = symbolId < symbols.length ? symbols[symbolId] : newSymbols[symbolId - symbols.length];
- bitmap = decodeRefinement(currentWidth, currentHeight, refinementTemplateIndex, symbol, rdx, rdy, false, refinementAt, decodingContext);
- }
- newSymbols.push(bitmap);
- } else if (huffman) {
- symbolWidths.push(currentWidth);
- } else {
- bitmap = decodeBitmap(false, currentWidth, currentHeight, templateIndex, false, null, at, decodingContext);
- newSymbols.push(bitmap);
- }
- }
- if (huffman && !refinement) {
- var bitmapSize = huffmanTables.tableBitmapSize.decode(huffmanInput);
- huffmanInput.byteAlign();
- var collectiveBitmap = void 0;
- if (bitmapSize === 0) {
- collectiveBitmap = readUncompressedBitmap(huffmanInput, totalWidth, currentHeight);
- } else {
- var originalEnd = huffmanInput.end;
- var bitmapEnd = huffmanInput.position + bitmapSize;
- huffmanInput.end = bitmapEnd;
- collectiveBitmap = decodeMMRBitmap(huffmanInput, totalWidth, currentHeight, false);
- huffmanInput.end = originalEnd;
- huffmanInput.position = bitmapEnd;
- }
- var numberOfSymbolsDecoded = symbolWidths.length;
- if (firstSymbol === numberOfSymbolsDecoded - 1) {
- newSymbols.push(collectiveBitmap);
- } else {
- var _i = void 0,
- y = void 0,
- xMin = 0,
- xMax = void 0,
- bitmapWidth = void 0,
- symbolBitmap = void 0;
- for (_i = firstSymbol; _i < numberOfSymbolsDecoded; _i++) {
- bitmapWidth = symbolWidths[_i];
- xMax = xMin + bitmapWidth;
- symbolBitmap = [];
- for (y = 0; y < currentHeight; y++) {
- symbolBitmap.push(collectiveBitmap[y].subarray(xMin, xMax));
- }
- newSymbols.push(symbolBitmap);
- xMin = xMax;
- }
- }
- }
- }
- var exportedSymbols = [];
- var flags = [],
- currentFlag = false;
- var totalSymbolsLength = symbols.length + numberOfNewSymbols;
- while (flags.length < totalSymbolsLength) {
- var runLength = huffman ? tableB1.decode(huffmanInput) : decodeInteger(contextCache, 'IAEX', decoder);
- while (runLength--) {
- flags.push(currentFlag);
- }
- currentFlag = !currentFlag;
- }
- for (var i = 0, ii = symbols.length; i < ii; i++) {
- if (flags[i]) {
- exportedSymbols.push(symbols[i]);
- }
- }
- for (var j = 0; j < numberOfNewSymbols; i++, j++) {
- if (flags[i]) {
- exportedSymbols.push(newSymbols[j]);
- }
- }
- return exportedSymbols;
- }
- function decodeTextRegion(huffman, refinement, width, height, defaultPixelValue, numberOfSymbolInstances, stripSize, inputSymbols, symbolCodeLength, transposed, dsOffset, referenceCorner, combinationOperator, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext, logStripSize, huffmanInput) {
- if (huffman && refinement) {
- throw new Jbig2Error('refinement with Huffman is not supported');
- }
- var bitmap = [];
- var i, row;
- for (i = 0; i < height; i++) {
- row = new Uint8Array(width);
- if (defaultPixelValue) {
- for (var j = 0; j < width; j++) {
- row[j] = defaultPixelValue;
- }
- }
- bitmap.push(row);
- }
- var decoder = decodingContext.decoder;
- var contextCache = decodingContext.contextCache;
- var stripT = huffman ? -huffmanTables.tableDeltaT.decode(huffmanInput) : -decodeInteger(contextCache, 'IADT', decoder);
- var firstS = 0;
- i = 0;
- while (i < numberOfSymbolInstances) {
- var deltaT = huffman ? huffmanTables.tableDeltaT.decode(huffmanInput) : decodeInteger(contextCache, 'IADT', decoder);
- stripT += deltaT;
- var deltaFirstS = huffman ? huffmanTables.tableFirstS.decode(huffmanInput) : decodeInteger(contextCache, 'IAFS', decoder);
- firstS += deltaFirstS;
- var currentS = firstS;
- do {
- var currentT = 0;
- if (stripSize > 1) {
- currentT = huffman ? huffmanInput.readBits(logStripSize) : decodeInteger(contextCache, 'IAIT', decoder);
- }
- var t = stripSize * stripT + currentT;
- var symbolId = huffman ? huffmanTables.symbolIDTable.decode(huffmanInput) : decodeIAID(contextCache, decoder, symbolCodeLength);
- var applyRefinement = refinement && (huffman ? huffmanInput.readBit() : decodeInteger(contextCache, 'IARI', decoder));
- var symbolBitmap = inputSymbols[symbolId];
- var symbolWidth = symbolBitmap[0].length;
- var symbolHeight = symbolBitmap.length;
- if (applyRefinement) {
- var rdw = decodeInteger(contextCache, 'IARDW', decoder);
- var rdh = decodeInteger(contextCache, 'IARDH', decoder);
- var rdx = decodeInteger(contextCache, 'IARDX', decoder);
- var rdy = decodeInteger(contextCache, 'IARDY', decoder);
- symbolWidth += rdw;
- symbolHeight += rdh;
- symbolBitmap = decodeRefinement(symbolWidth, symbolHeight, refinementTemplateIndex, symbolBitmap, (rdw >> 1) + rdx, (rdh >> 1) + rdy, false, refinementAt, decodingContext);
- }
- var offsetT = t - (referenceCorner & 1 ? 0 : symbolHeight - 1);
- var offsetS = currentS - (referenceCorner & 2 ? symbolWidth - 1 : 0);
- var s2, t2, symbolRow;
- if (transposed) {
- for (s2 = 0; s2 < symbolHeight; s2++) {
- row = bitmap[offsetS + s2];
- if (!row) {
- continue;
- }
- symbolRow = symbolBitmap[s2];
- var maxWidth = Math.min(width - offsetT, symbolWidth);
- switch (combinationOperator) {
- case 0:
- for (t2 = 0; t2 < maxWidth; t2++) {
- row[offsetT + t2] |= symbolRow[t2];
- }
- break;
- case 2:
- for (t2 = 0; t2 < maxWidth; t2++) {
- row[offsetT + t2] ^= symbolRow[t2];
- }
- break;
- default:
- throw new Jbig2Error('operator ' + combinationOperator + ' is not supported');
- }
- }
- currentS += symbolHeight - 1;
- } else {
- for (t2 = 0; t2 < symbolHeight; t2++) {
- row = bitmap[offsetT + t2];
- if (!row) {
- continue;
- }
- symbolRow = symbolBitmap[t2];
- switch (combinationOperator) {
- case 0:
- for (s2 = 0; s2 < symbolWidth; s2++) {
- row[offsetS + s2] |= symbolRow[s2];
- }
- break;
- case 2:
- for (s2 = 0; s2 < symbolWidth; s2++) {
- row[offsetS + s2] ^= symbolRow[s2];
- }
- break;
- default:
- throw new Jbig2Error('operator ' + combinationOperator + ' is not supported');
- }
- }
- currentS += symbolWidth - 1;
- }
- i++;
- var deltaS = huffman ? huffmanTables.tableDeltaS.decode(huffmanInput) : decodeInteger(contextCache, 'IADS', decoder);
- if (deltaS === null) {
- break;
- }
- currentS += deltaS + dsOffset;
- } while (true);
- }
- return bitmap;
- }
- function decodePatternDictionary(mmr, patternWidth, patternHeight, maxPatternIndex, template, decodingContext) {
- var at = [];
- if (!mmr) {
- at.push({
- x: -patternWidth,
- y: 0
- });
- if (template === 0) {
- at.push({
- x: -3,
- y: -1
- });
- at.push({
- x: 2,
- y: -2
- });
- at.push({
- x: -2,
- y: -2
- });
- }
- }
- var collectiveWidth = (maxPatternIndex + 1) * patternWidth;
- var collectiveBitmap = decodeBitmap(mmr, collectiveWidth, patternHeight, template, false, null, at, decodingContext);
- var patterns = [],
- i = 0,
- patternBitmap = void 0,
- xMin = void 0,
- xMax = void 0,
- y = void 0;
- while (i <= maxPatternIndex) {
- patternBitmap = [];
- xMin = patternWidth * i;
- xMax = xMin + patternWidth;
- for (y = 0; y < patternHeight; y++) {
- patternBitmap.push(collectiveBitmap[y].subarray(xMin, xMax));
- }
- patterns.push(patternBitmap);
- i++;
- }
- return patterns;
- }
- function decodeHalftoneRegion(mmr, patterns, template, regionWidth, regionHeight, defaultPixelValue, enableSkip, combinationOperator, gridWidth, gridHeight, gridOffsetX, gridOffsetY, gridVectorX, gridVectorY, decodingContext) {
- var skip = null;
- if (enableSkip) {
- throw new Jbig2Error('skip is not supported');
- }
- if (combinationOperator !== 0) {
- throw new Jbig2Error('operator ' + combinationOperator + ' is not supported in halftone region');
- }
- var regionBitmap = [];
- var i = void 0,
- j = void 0,
- row = void 0;
- for (i = 0; i < regionHeight; i++) {
- row = new Uint8Array(regionWidth);
- if (defaultPixelValue) {
- for (j = 0; j < regionWidth; j++) {
- row[j] = defaultPixelValue;
- }
- }
- regionBitmap.push(row);
- }
- var numberOfPatterns = patterns.length;
- var pattern0 = patterns[0];
- var patternWidth = pattern0[0].length,
- patternHeight = pattern0.length;
- var bitsPerValue = (0, _util.log2)(numberOfPatterns);
- var at = [];
- if (!mmr) {
- at.push({
- x: template <= 1 ? 3 : 2,
- y: -1
- });
- if (template === 0) {
- at.push({
- x: -3,
- y: -1
- });
- at.push({
- x: 2,
- y: -2
- });
- at.push({
- x: -2,
- y: -2
- });
- }
- }
- var grayScaleBitPlanes = [],
- mmrInput = void 0,
- bitmap = void 0;
- if (mmr) {
- mmrInput = new Reader(decodingContext.data, decodingContext.start, decodingContext.end);
- }
- for (i = bitsPerValue - 1; i >= 0; i--) {
- if (mmr) {
- bitmap = decodeMMRBitmap(mmrInput, gridWidth, gridHeight, true);
- } else {
- bitmap = decodeBitmap(false, gridWidth, gridHeight, template, false, skip, at, decodingContext);
- }
- grayScaleBitPlanes[i] = bitmap;
- }
- var mg = void 0,
- ng = void 0,
- bit = void 0,
- patternIndex = void 0,
- patternBitmap = void 0,
- x = void 0,
- y = void 0,
- patternRow = void 0,
- regionRow = void 0;
- for (mg = 0; mg < gridHeight; mg++) {
- for (ng = 0; ng < gridWidth; ng++) {
- bit = 0;
- patternIndex = 0;
- for (j = bitsPerValue - 1; j >= 0; j--) {
- bit = grayScaleBitPlanes[j][mg][ng] ^ bit;
- patternIndex |= bit << j;
- }
- patternBitmap = patterns[patternIndex];
- x = gridOffsetX + mg * gridVectorY + ng * gridVectorX >> 8;
- y = gridOffsetY + mg * gridVectorX - ng * gridVectorY >> 8;
- if (x >= 0 && x + patternWidth <= regionWidth && y >= 0 && y + patternHeight <= regionHeight) {
- for (i = 0; i < patternHeight; i++) {
- regionRow = regionBitmap[y + i];
- patternRow = patternBitmap[i];
- for (j = 0; j < patternWidth; j++) {
- regionRow[x + j] |= patternRow[j];
- }
- }
- } else {
- var regionX = void 0,
- regionY = void 0;
- for (i = 0; i < patternHeight; i++) {
- regionY = y + i;
- if (regionY < 0 || regionY >= regionHeight) {
- continue;
- }
- regionRow = regionBitmap[regionY];
- patternRow = patternBitmap[i];
- for (j = 0; j < patternWidth; j++) {
- regionX = x + j;
- if (regionX >= 0 && regionX < regionWidth) {
- regionRow[regionX] |= patternRow[j];
- }
- }
- }
- }
- }
- }
- return regionBitmap;
- }
- function readSegmentHeader(data, start) {
- var segmentHeader = {};
- segmentHeader.number = (0, _util.readUint32)(data, start);
- var flags = data[start + 4];
- var segmentType = flags & 0x3F;
- if (!SegmentTypes[segmentType]) {
- throw new Jbig2Error('invalid segment type: ' + segmentType);
- }
- segmentHeader.type = segmentType;
- segmentHeader.typeName = SegmentTypes[segmentType];
- segmentHeader.deferredNonRetain = !!(flags & 0x80);
- var pageAssociationFieldSize = !!(flags & 0x40);
- var referredFlags = data[start + 5];
- var referredToCount = referredFlags >> 5 & 7;
- var retainBits = [referredFlags & 31];
- var position = start + 6;
- if (referredFlags === 7) {
- referredToCount = (0, _util.readUint32)(data, position - 1) & 0x1FFFFFFF;
- position += 3;
- var bytes = referredToCount + 7 >> 3;
- retainBits[0] = data[position++];
- while (--bytes > 0) {
- retainBits.push(data[position++]);
- }
- } else if (referredFlags === 5 || referredFlags === 6) {
- throw new Jbig2Error('invalid referred-to flags');
- }
- segmentHeader.retainBits = retainBits;
- var referredToSegmentNumberSize = segmentHeader.number <= 256 ? 1 : segmentHeader.number <= 65536 ? 2 : 4;
- var referredTo = [];
- var i, ii;
- for (i = 0; i < referredToCount; i++) {
- var number = referredToSegmentNumberSize === 1 ? data[position] : referredToSegmentNumberSize === 2 ? (0, _util.readUint16)(data, position) : (0, _util.readUint32)(data, position);
- referredTo.push(number);
- position += referredToSegmentNumberSize;
- }
- segmentHeader.referredTo = referredTo;
- if (!pageAssociationFieldSize) {
- segmentHeader.pageAssociation = data[position++];
- } else {
- segmentHeader.pageAssociation = (0, _util.readUint32)(data, position);
- position += 4;
- }
- segmentHeader.length = (0, _util.readUint32)(data, position);
- position += 4;
- if (segmentHeader.length === 0xFFFFFFFF) {
- if (segmentType === 38) {
- var genericRegionInfo = readRegionSegmentInformation(data, position);
- var genericRegionSegmentFlags = data[position + RegionSegmentInformationFieldLength];
- var genericRegionMmr = !!(genericRegionSegmentFlags & 1);
- var searchPatternLength = 6;
- var searchPattern = new Uint8Array(searchPatternLength);
- if (!genericRegionMmr) {
- searchPattern[0] = 0xFF;
- searchPattern[1] = 0xAC;
- }
- searchPattern[2] = genericRegionInfo.height >>> 24 & 0xFF;
- searchPattern[3] = genericRegionInfo.height >> 16 & 0xFF;
- searchPattern[4] = genericRegionInfo.height >> 8 & 0xFF;
- searchPattern[5] = genericRegionInfo.height & 0xFF;
- for (i = position, ii = data.length; i < ii; i++) {
- var j = 0;
- while (j < searchPatternLength && searchPattern[j] === data[i + j]) {
- j++;
- }
- if (j === searchPatternLength) {
- segmentHeader.length = i + searchPatternLength;
- break;
- }
- }
- if (segmentHeader.length === 0xFFFFFFFF) {
- throw new Jbig2Error('segment end was not found');
- }
- } else {
- throw new Jbig2Error('invalid unknown segment length');
- }
- }
- segmentHeader.headerEnd = position;
- return segmentHeader;
- }
- function readSegments(header, data, start, end) {
- var segments = [];
- var position = start;
- while (position < end) {
- var segmentHeader = readSegmentHeader(data, position);
- position = segmentHeader.headerEnd;
- var segment = {
- header: segmentHeader,
- data: data
- };
- if (!header.randomAccess) {
- segment.start = position;
- position += segmentHeader.length;
- segment.end = position;
- }
- segments.push(segment);
- if (segmentHeader.type === 51) {
- break;
- }
- }
- if (header.randomAccess) {
- for (var i = 0, ii = segments.length; i < ii; i++) {
- segments[i].start = position;
- position += segments[i].header.length;
- segments[i].end = position;
- }
- }
- return segments;
- }
- function readRegionSegmentInformation(data, start) {
- return {
- width: (0, _util.readUint32)(data, start),
- height: (0, _util.readUint32)(data, start + 4),
- x: (0, _util.readUint32)(data, start + 8),
- y: (0, _util.readUint32)(data, start + 12),
- combinationOperator: data[start + 16] & 7
- };
- }
- var RegionSegmentInformationFieldLength = 17;
- function processSegment(segment, visitor) {
- var header = segment.header;
- var data = segment.data,
- position = segment.start,
- end = segment.end;
- var args, at, i, atLength;
- switch (header.type) {
- case 0:
- var dictionary = {};
- var dictionaryFlags = (0, _util.readUint16)(data, position);
- dictionary.huffman = !!(dictionaryFlags & 1);
- dictionary.refinement = !!(dictionaryFlags & 2);
- dictionary.huffmanDHSelector = dictionaryFlags >> 2 & 3;
- dictionary.huffmanDWSelector = dictionaryFlags >> 4 & 3;
- dictionary.bitmapSizeSelector = dictionaryFlags >> 6 & 1;
- dictionary.aggregationInstancesSelector = dictionaryFlags >> 7 & 1;
- dictionary.bitmapCodingContextUsed = !!(dictionaryFlags & 256);
- dictionary.bitmapCodingContextRetained = !!(dictionaryFlags & 512);
- dictionary.template = dictionaryFlags >> 10 & 3;
- dictionary.refinementTemplate = dictionaryFlags >> 12 & 1;
- position += 2;
- if (!dictionary.huffman) {
- atLength = dictionary.template === 0 ? 4 : 1;
- at = [];
- for (i = 0; i < atLength; i++) {
- at.push({
- x: (0, _util.readInt8)(data, position),
- y: (0, _util.readInt8)(data, position + 1)
- });
- position += 2;
- }
- dictionary.at = at;
- }
- if (dictionary.refinement && !dictionary.refinementTemplate) {
- at = [];
- for (i = 0; i < 2; i++) {
- at.push({
- x: (0, _util.readInt8)(data, position),
- y: (0, _util.readInt8)(data, position + 1)
- });
- position += 2;
- }
- dictionary.refinementAt = at;
- }
- dictionary.numberOfExportedSymbols = (0, _util.readUint32)(data, position);
- position += 4;
- dictionary.numberOfNewSymbols = (0, _util.readUint32)(data, position);
- position += 4;
- args = [dictionary, header.number, header.referredTo, data, position, end];
- break;
- case 6:
- case 7:
- var textRegion = {};
- textRegion.info = readRegionSegmentInformation(data, position);
- position += RegionSegmentInformationFieldLength;
- var textRegionSegmentFlags = (0, _util.readUint16)(data, position);
- position += 2;
- textRegion.huffman = !!(textRegionSegmentFlags & 1);
- textRegion.refinement = !!(textRegionSegmentFlags & 2);
- textRegion.logStripSize = textRegionSegmentFlags >> 2 & 3;
- textRegion.stripSize = 1 << textRegion.logStripSize;
- textRegion.referenceCorner = textRegionSegmentFlags >> 4 & 3;
- textRegion.transposed = !!(textRegionSegmentFlags & 64);
- textRegion.combinationOperator = textRegionSegmentFlags >> 7 & 3;
- textRegion.defaultPixelValue = textRegionSegmentFlags >> 9 & 1;
- textRegion.dsOffset = textRegionSegmentFlags << 17 >> 27;
- textRegion.refinementTemplate = textRegionSegmentFlags >> 15 & 1;
- if (textRegion.huffman) {
- var textRegionHuffmanFlags = (0, _util.readUint16)(data, position);
- position += 2;
- textRegion.huffmanFS = textRegionHuffmanFlags & 3;
- textRegion.huffmanDS = textRegionHuffmanFlags >> 2 & 3;
- textRegion.huffmanDT = textRegionHuffmanFlags >> 4 & 3;
- textRegion.huffmanRefinementDW = textRegionHuffmanFlags >> 6 & 3;
- textRegion.huffmanRefinementDH = textRegionHuffmanFlags >> 8 & 3;
- textRegion.huffmanRefinementDX = textRegionHuffmanFlags >> 10 & 3;
- textRegion.huffmanRefinementDY = textRegionHuffmanFlags >> 12 & 3;
- textRegion.huffmanRefinementSizeSelector = !!(textRegionHuffmanFlags & 0x4000);
- }
- if (textRegion.refinement && !textRegion.refinementTemplate) {
- at = [];
- for (i = 0; i < 2; i++) {
- at.push({
- x: (0, _util.readInt8)(data, position),
- y: (0, _util.readInt8)(data, position + 1)
- });
- position += 2;
- }
- textRegion.refinementAt = at;
- }
- textRegion.numberOfSymbolInstances = (0, _util.readUint32)(data, position);
- position += 4;
- args = [textRegion, header.referredTo, data, position, end];
- break;
- case 16:
- var patternDictionary = {};
- var patternDictionaryFlags = data[position++];
- patternDictionary.mmr = !!(patternDictionaryFlags & 1);
- patternDictionary.template = patternDictionaryFlags >> 1 & 3;
- patternDictionary.patternWidth = data[position++];
- patternDictionary.patternHeight = data[position++];
- patternDictionary.maxPatternIndex = (0, _util.readUint32)(data, position);
- position += 4;
- args = [patternDictionary, header.number, data, position, end];
- break;
- case 22:
- case 23:
- var halftoneRegion = {};
- halftoneRegion.info = readRegionSegmentInformation(data, position);
- position += RegionSegmentInformationFieldLength;
- var halftoneRegionFlags = data[position++];
- halftoneRegion.mmr = !!(halftoneRegionFlags & 1);
- halftoneRegion.template = halftoneRegionFlags >> 1 & 3;
- halftoneRegion.enableSkip = !!(halftoneRegionFlags & 8);
- halftoneRegion.combinationOperator = halftoneRegionFlags >> 4 & 7;
- halftoneRegion.defaultPixelValue = halftoneRegionFlags >> 7 & 1;
- halftoneRegion.gridWidth = (0, _util.readUint32)(data, position);
- position += 4;
- halftoneRegion.gridHeight = (0, _util.readUint32)(data, position);
- position += 4;
- halftoneRegion.gridOffsetX = (0, _util.readUint32)(data, position) & 0xFFFFFFFF;
- position += 4;
- halftoneRegion.gridOffsetY = (0, _util.readUint32)(data, position) & 0xFFFFFFFF;
- position += 4;
- halftoneRegion.gridVectorX = (0, _util.readUint16)(data, position);
- position += 2;
- halftoneRegion.gridVectorY = (0, _util.readUint16)(data, position);
- position += 2;
- args = [halftoneRegion, header.referredTo, data, position, end];
- break;
- case 38:
- case 39:
- var genericRegion = {};
- genericRegion.info = readRegionSegmentInformation(data, position);
- position += RegionSegmentInformationFieldLength;
- var genericRegionSegmentFlags = data[position++];
- genericRegion.mmr = !!(genericRegionSegmentFlags & 1);
- genericRegion.template = genericRegionSegmentFlags >> 1 & 3;
- genericRegion.prediction = !!(genericRegionSegmentFlags & 8);
- if (!genericRegion.mmr) {
- atLength = genericRegion.template === 0 ? 4 : 1;
- at = [];
- for (i = 0; i < atLength; i++) {
- at.push({
- x: (0, _util.readInt8)(data, position),
- y: (0, _util.readInt8)(data, position + 1)
- });
- position += 2;
- }
- genericRegion.at = at;
- }
- args = [genericRegion, data, position, end];
- break;
- case 48:
- var pageInfo = {
- width: (0, _util.readUint32)(data, position),
- height: (0, _util.readUint32)(data, position + 4),
- resolutionX: (0, _util.readUint32)(data, position + 8),
- resolutionY: (0, _util.readUint32)(data, position + 12)
- };
- if (pageInfo.height === 0xFFFFFFFF) {
- delete pageInfo.height;
- }
- var pageSegmentFlags = data[position + 16];
- (0, _util.readUint16)(data, position + 17);
- pageInfo.lossless = !!(pageSegmentFlags & 1);
- pageInfo.refinement = !!(pageSegmentFlags & 2);
- pageInfo.defaultPixelValue = pageSegmentFlags >> 2 & 1;
- pageInfo.combinationOperator = pageSegmentFlags >> 3 & 3;
- pageInfo.requiresBuffer = !!(pageSegmentFlags & 32);
- pageInfo.combinationOperatorOverride = !!(pageSegmentFlags & 64);
- args = [pageInfo];
- break;
- case 49:
- break;
- case 50:
- break;
- case 51:
- break;
- case 53:
- args = [header.number, data, position, end];
- break;
- case 62:
- break;
- default:
- throw new Jbig2Error('segment type ' + header.typeName + '(' + header.type + ')' + ' is not implemented');
- }
- var callbackName = 'on' + header.typeName;
- if (callbackName in visitor) {
- visitor[callbackName].apply(visitor, args);
- }
- }
- function processSegments(segments, visitor) {
- for (var i = 0, ii = segments.length; i < ii; i++) {
- processSegment(segments[i], visitor);
- }
- }
- function parseJbig2Chunks(chunks) {
- var visitor = new SimpleSegmentVisitor();
- for (var i = 0, ii = chunks.length; i < ii; i++) {
- var chunk = chunks[i];
- var segments = readSegments({}, chunk.data, chunk.start, chunk.end);
- processSegments(segments, visitor);
- }
- return visitor.buffer;
- }
- function parseJbig2(data) {
- var position = 0,
- end = data.length;
- if (data[position] !== 0x97 || data[position + 1] !== 0x4A || data[position + 2] !== 0x42 || data[position + 3] !== 0x32 || data[position + 4] !== 0x0D || data[position + 5] !== 0x0A || data[position + 6] !== 0x1A || data[position + 7] !== 0x0A) {
- throw new Jbig2Error('parseJbig2 - invalid header.');
- }
- var header = Object.create(null);
- position += 8;
- var flags = data[position++];
- header.randomAccess = !(flags & 1);
- if (!(flags & 2)) {
- header.numberOfPages = (0, _util.readUint32)(data, position);
- position += 4;
- }
- var segments = readSegments(header, data, position, end);
- var visitor = new SimpleSegmentVisitor();
- processSegments(segments, visitor);
- var _visitor$currentPageI = visitor.currentPageInfo,
- width = _visitor$currentPageI.width,
- height = _visitor$currentPageI.height;
-
- var bitPacked = visitor.buffer;
- var imgData = new Uint8ClampedArray(width * height);
- var q = 0,
- k = 0;
- for (var i = 0; i < height; i++) {
- var mask = 0,
- buffer = void 0;
- for (var j = 0; j < width; j++) {
- if (!mask) {
- mask = 128;
- buffer = bitPacked[k++];
- }
- imgData[q++] = buffer & mask ? 0 : 255;
- mask >>= 1;
- }
- }
- return {
- imgData: imgData,
- width: width,
- height: height
- };
- }
- function SimpleSegmentVisitor() {}
- SimpleSegmentVisitor.prototype = {
- onPageInformation: function SimpleSegmentVisitor_onPageInformation(info) {
- this.currentPageInfo = info;
- var rowSize = info.width + 7 >> 3;
- var buffer = new Uint8ClampedArray(rowSize * info.height);
- if (info.defaultPixelValue) {
- for (var i = 0, ii = buffer.length; i < ii; i++) {
- buffer[i] = 0xFF;
- }
- }
- this.buffer = buffer;
- },
- drawBitmap: function SimpleSegmentVisitor_drawBitmap(regionInfo, bitmap) {
- var pageInfo = this.currentPageInfo;
- var width = regionInfo.width,
- height = regionInfo.height;
- var rowSize = pageInfo.width + 7 >> 3;
- var combinationOperator = pageInfo.combinationOperatorOverride ? regionInfo.combinationOperator : pageInfo.combinationOperator;
- var buffer = this.buffer;
- var mask0 = 128 >> (regionInfo.x & 7);
- var offset0 = regionInfo.y * rowSize + (regionInfo.x >> 3);
- var i, j, mask, offset;
- switch (combinationOperator) {
- case 0:
- for (i = 0; i < height; i++) {
- mask = mask0;
- offset = offset0;
- for (j = 0; j < width; j++) {
- if (bitmap[i][j]) {
- buffer[offset] |= mask;
- }
- mask >>= 1;
- if (!mask) {
- mask = 128;
- offset++;
- }
- }
- offset0 += rowSize;
- }
- break;
- case 2:
- for (i = 0; i < height; i++) {
- mask = mask0;
- offset = offset0;
- for (j = 0; j < width; j++) {
- if (bitmap[i][j]) {
- buffer[offset] ^= mask;
- }
- mask >>= 1;
- if (!mask) {
- mask = 128;
- offset++;
- }
- }
- offset0 += rowSize;
- }
- break;
- default:
- throw new Jbig2Error('operator ' + combinationOperator + ' is not supported');
- }
- },
- onImmediateGenericRegion: function SimpleSegmentVisitor_onImmediateGenericRegion(region, data, start, end) {
- var regionInfo = region.info;
- var decodingContext = new DecodingContext(data, start, end);
- var bitmap = decodeBitmap(region.mmr, regionInfo.width, regionInfo.height, region.template, region.prediction, null, region.at, decodingContext);
- this.drawBitmap(regionInfo, bitmap);
- },
- onImmediateLosslessGenericRegion: function SimpleSegmentVisitor_onImmediateLosslessGenericRegion() {
- this.onImmediateGenericRegion.apply(this, arguments);
- },
- onSymbolDictionary: function SimpleSegmentVisitor_onSymbolDictionary(dictionary, currentSegment, referredSegments, data, start, end) {
- var huffmanTables = void 0,
- huffmanInput = void 0;
- if (dictionary.huffman) {
- huffmanTables = getSymbolDictionaryHuffmanTables(dictionary, referredSegments, this.customTables);
- huffmanInput = new Reader(data, start, end);
- }
- var symbols = this.symbols;
- if (!symbols) {
- this.symbols = symbols = {};
- }
- var inputSymbols = [];
- for (var i = 0, ii = referredSegments.length; i < ii; i++) {
- var referredSymbols = symbols[referredSegments[i]];
- if (referredSymbols) {
- inputSymbols = inputSymbols.concat(referredSymbols);
- }
- }
- var decodingContext = new DecodingContext(data, start, end);
- symbols[currentSegment] = decodeSymbolDictionary(dictionary.huffman, dictionary.refinement, inputSymbols, dictionary.numberOfNewSymbols, dictionary.numberOfExportedSymbols, huffmanTables, dictionary.template, dictionary.at, dictionary.refinementTemplate, dictionary.refinementAt, decodingContext, huffmanInput);
- },
- onImmediateTextRegion: function SimpleSegmentVisitor_onImmediateTextRegion(region, referredSegments, data, start, end) {
- var regionInfo = region.info;
- var huffmanTables = void 0,
- huffmanInput = void 0;
- var symbols = this.symbols;
- var inputSymbols = [];
- for (var i = 0, ii = referredSegments.length; i < ii; i++) {
- var referredSymbols = symbols[referredSegments[i]];
- if (referredSymbols) {
- inputSymbols = inputSymbols.concat(referredSymbols);
- }
- }
- var symbolCodeLength = (0, _util.log2)(inputSymbols.length);
- if (region.huffman) {
- huffmanInput = new Reader(data, start, end);
- huffmanTables = getTextRegionHuffmanTables(region, referredSegments, this.customTables, inputSymbols.length, huffmanInput);
- }
- var decodingContext = new DecodingContext(data, start, end);
- var bitmap = decodeTextRegion(region.huffman, region.refinement, regionInfo.width, regionInfo.height, region.defaultPixelValue, region.numberOfSymbolInstances, region.stripSize, inputSymbols, symbolCodeLength, region.transposed, region.dsOffset, region.referenceCorner, region.combinationOperator, huffmanTables, region.refinementTemplate, region.refinementAt, decodingContext, region.logStripSize, huffmanInput);
- this.drawBitmap(regionInfo, bitmap);
- },
- onImmediateLosslessTextRegion: function SimpleSegmentVisitor_onImmediateLosslessTextRegion() {
- this.onImmediateTextRegion.apply(this, arguments);
- },
- onPatternDictionary: function onPatternDictionary(dictionary, currentSegment, data, start, end) {
- var patterns = this.patterns;
- if (!patterns) {
- this.patterns = patterns = {};
- }
- var decodingContext = new DecodingContext(data, start, end);
- patterns[currentSegment] = decodePatternDictionary(dictionary.mmr, dictionary.patternWidth, dictionary.patternHeight, dictionary.maxPatternIndex, dictionary.template, decodingContext);
- },
- onImmediateHalftoneRegion: function onImmediateHalftoneRegion(region, referredSegments, data, start, end) {
- var patterns = this.patterns[referredSegments[0]];
- var regionInfo = region.info;
- var decodingContext = new DecodingContext(data, start, end);
- var bitmap = decodeHalftoneRegion(region.mmr, patterns, region.template, regionInfo.width, regionInfo.height, region.defaultPixelValue, region.enableSkip, region.combinationOperator, region.gridWidth, region.gridHeight, region.gridOffsetX, region.gridOffsetY, region.gridVectorX, region.gridVectorY, decodingContext);
- this.drawBitmap(regionInfo, bitmap);
- },
- onImmediateLosslessHalftoneRegion: function onImmediateLosslessHalftoneRegion() {
- this.onImmediateHalftoneRegion.apply(this, arguments);
- },
- onTables: function onTables(currentSegment, data, start, end) {
- var customTables = this.customTables;
- if (!customTables) {
- this.customTables = customTables = {};
- }
- customTables[currentSegment] = decodeTablesSegment(data, start, end);
- }
- };
- function HuffmanLine(lineData) {
- if (lineData.length === 2) {
- this.isOOB = true;
- this.rangeLow = 0;
- this.prefixLength = lineData[0];
- this.rangeLength = 0;
- this.prefixCode = lineData[1];
- this.isLowerRange = false;
- } else {
- this.isOOB = false;
- this.rangeLow = lineData[0];
- this.prefixLength = lineData[1];
- this.rangeLength = lineData[2];
- this.prefixCode = lineData[3];
- this.isLowerRange = lineData[4] === 'lower';
- }
- }
- function HuffmanTreeNode(line) {
- this.children = [];
- if (line) {
- this.isLeaf = true;
- this.rangeLength = line.rangeLength;
- this.rangeLow = line.rangeLow;
- this.isLowerRange = line.isLowerRange;
- this.isOOB = line.isOOB;
- } else {
- this.isLeaf = false;
- }
- }
- HuffmanTreeNode.prototype = {
- buildTree: function buildTree(line, shift) {
- var bit = line.prefixCode >> shift & 1;
- if (shift <= 0) {
- this.children[bit] = new HuffmanTreeNode(line);
- } else {
- var node = this.children[bit];
- if (!node) {
- this.children[bit] = node = new HuffmanTreeNode(null);
- }
- node.buildTree(line, shift - 1);
- }
- },
- decodeNode: function decodeNode(reader) {
- if (this.isLeaf) {
- if (this.isOOB) {
- return null;
- }
- var htOffset = reader.readBits(this.rangeLength);
- return this.rangeLow + (this.isLowerRange ? -htOffset : htOffset);
- }
- var node = this.children[reader.readBit()];
- if (!node) {
- throw new Jbig2Error('invalid Huffman data');
- }
- return node.decodeNode(reader);
- }
- };
- function HuffmanTable(lines, prefixCodesDone) {
- if (!prefixCodesDone) {
- this.assignPrefixCodes(lines);
- }
- this.rootNode = new HuffmanTreeNode(null);
- var i = void 0,
- ii = lines.length,
- line = void 0;
- for (i = 0; i < ii; i++) {
- line = lines[i];
- if (line.prefixLength > 0) {
- this.rootNode.buildTree(line, line.prefixLength - 1);
- }
- }
- }
- HuffmanTable.prototype = {
- decode: function decode(reader) {
- return this.rootNode.decodeNode(reader);
- },
- assignPrefixCodes: function assignPrefixCodes(lines) {
- var linesLength = lines.length,
- prefixLengthMax = 0,
- i = void 0;
- for (i = 0; i < linesLength; i++) {
- prefixLengthMax = Math.max(prefixLengthMax, lines[i].prefixLength);
- }
- var histogram = new Uint32Array(prefixLengthMax + 1);
- for (i = 0; i < linesLength; i++) {
- histogram[lines[i].prefixLength]++;
- }
- var currentLength = 1,
- firstCode = 0,
- currentCode = void 0,
- currentTemp = void 0,
- line = void 0;
- histogram[0] = 0;
- while (currentLength <= prefixLengthMax) {
- firstCode = firstCode + histogram[currentLength - 1] << 1;
- currentCode = firstCode;
- currentTemp = 0;
- while (currentTemp < linesLength) {
- line = lines[currentTemp];
- if (line.prefixLength === currentLength) {
- line.prefixCode = currentCode;
- currentCode++;
- }
- currentTemp++;
- }
- currentLength++;
- }
- }
- };
- function decodeTablesSegment(data, start, end) {
- var flags = data[start];
- var lowestValue = (0, _util.readUint32)(data, start + 1) & 0xFFFFFFFF;
- var highestValue = (0, _util.readUint32)(data, start + 5) & 0xFFFFFFFF;
- var reader = new Reader(data, start + 9, end);
- var prefixSizeBits = (flags >> 1 & 7) + 1;
- var rangeSizeBits = (flags >> 4 & 7) + 1;
- var lines = [];
- var prefixLength = void 0,
- rangeLength = void 0,
- currentRangeLow = lowestValue;
- do {
- prefixLength = reader.readBits(prefixSizeBits);
- rangeLength = reader.readBits(rangeSizeBits);
- lines.push(new HuffmanLine([currentRangeLow, prefixLength, rangeLength, 0]));
- currentRangeLow += 1 << rangeLength;
- } while (currentRangeLow < highestValue);
- prefixLength = reader.readBits(prefixSizeBits);
- lines.push(new HuffmanLine([lowestValue - 1, prefixLength, 32, 0, 'lower']));
- prefixLength = reader.readBits(prefixSizeBits);
- lines.push(new HuffmanLine([highestValue, prefixLength, 32, 0]));
- if (flags & 1) {
- prefixLength = reader.readBits(prefixSizeBits);
- lines.push(new HuffmanLine([prefixLength, 0]));
- }
- return new HuffmanTable(lines, false);
- }
- var standardTablesCache = {};
- function getStandardTable(number) {
- var table = standardTablesCache[number];
- if (table) {
- return table;
- }
- var lines = void 0;
- switch (number) {
- case 1:
- lines = [[0, 1, 4, 0x0], [16, 2, 8, 0x2], [272, 3, 16, 0x6], [65808, 3, 32, 0x7]];
- break;
- case 2:
- lines = [[0, 1, 0, 0x0], [1, 2, 0, 0x2], [2, 3, 0, 0x6], [3, 4, 3, 0xE], [11, 5, 6, 0x1E], [75, 6, 32, 0x3E], [6, 0x3F]];
- break;
- case 3:
- lines = [[-256, 8, 8, 0xFE], [0, 1, 0, 0x0], [1, 2, 0, 0x2], [2, 3, 0, 0x6], [3, 4, 3, 0xE], [11, 5, 6, 0x1E], [-257, 8, 32, 0xFF, 'lower'], [75, 7, 32, 0x7E], [6, 0x3E]];
- break;
- case 4:
- lines = [[1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 0, 0x6], [4, 4, 3, 0xE], [12, 5, 6, 0x1E], [76, 5, 32, 0x1F]];
- break;
- case 5:
- lines = [[-255, 7, 8, 0x7E], [1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 0, 0x6], [4, 4, 3, 0xE], [12, 5, 6, 0x1E], [-256, 7, 32, 0x7F, 'lower'], [76, 6, 32, 0x3E]];
- break;
- case 6:
- lines = [[-2048, 5, 10, 0x1C], [-1024, 4, 9, 0x8], [-512, 4, 8, 0x9], [-256, 4, 7, 0xA], [-128, 5, 6, 0x1D], [-64, 5, 5, 0x1E], [-32, 4, 5, 0xB], [0, 2, 7, 0x0], [128, 3, 7, 0x2], [256, 3, 8, 0x3], [512, 4, 9, 0xC], [1024, 4, 10, 0xD], [-2049, 6, 32, 0x3E, 'lower'], [2048, 6, 32, 0x3F]];
- break;
- case 7:
- lines = [[-1024, 4, 9, 0x8], [-512, 3, 8, 0x0], [-256, 4, 7, 0x9], [-128, 5, 6, 0x1A], [-64, 5, 5, 0x1B], [-32, 4, 5, 0xA], [0, 4, 5, 0xB], [32, 5, 5, 0x1C], [64, 5, 6, 0x1D], [128, 4, 7, 0xC], [256, 3, 8, 0x1], [512, 3, 9, 0x2], [1024, 3, 10, 0x3], [-1025, 5, 32, 0x1E, 'lower'], [2048, 5, 32, 0x1F]];
- break;
- case 8:
- lines = [[-15, 8, 3, 0xFC], [-7, 9, 1, 0x1FC], [-5, 8, 1, 0xFD], [-3, 9, 0, 0x1FD], [-2, 7, 0, 0x7C], [-1, 4, 0, 0xA], [0, 2, 1, 0x0], [2, 5, 0, 0x1A], [3, 6, 0, 0x3A], [4, 3, 4, 0x4], [20, 6, 1, 0x3B], [22, 4, 4, 0xB], [38, 4, 5, 0xC], [70, 5, 6, 0x1B], [134, 5, 7, 0x1C], [262, 6, 7, 0x3C], [390, 7, 8, 0x7D], [646, 6, 10, 0x3D], [-16, 9, 32, 0x1FE, 'lower'], [1670, 9, 32, 0x1FF], [2, 0x1]];
- break;
- case 9:
- lines = [[-31, 8, 4, 0xFC], [-15, 9, 2, 0x1FC], [-11, 8, 2, 0xFD], [-7, 9, 1, 0x1FD], [-5, 7, 1, 0x7C], [-3, 4, 1, 0xA], [-1, 3, 1, 0x2], [1, 3, 1, 0x3], [3, 5, 1, 0x1A], [5, 6, 1, 0x3A], [7, 3, 5, 0x4], [39, 6, 2, 0x3B], [43, 4, 5, 0xB], [75, 4, 6, 0xC], [139, 5, 7, 0x1B], [267, 5, 8, 0x1C], [523, 6, 8, 0x3C], [779, 7, 9, 0x7D], [1291, 6, 11, 0x3D], [-32, 9, 32, 0x1FE, 'lower'], [3339, 9, 32, 0x1FF], [2, 0x0]];
- break;
- case 10:
- lines = [[-21, 7, 4, 0x7A], [-5, 8, 0, 0xFC], [-4, 7, 0, 0x7B], [-3, 5, 0, 0x18], [-2, 2, 2, 0x0], [2, 5, 0, 0x19], [3, 6, 0, 0x36], [4, 7, 0, 0x7C], [5, 8, 0, 0xFD], [6, 2, 6, 0x1], [70, 5, 5, 0x1A], [102, 6, 5, 0x37], [134, 6, 6, 0x38], [198, 6, 7, 0x39], [326, 6, 8, 0x3A], [582, 6, 9, 0x3B], [1094, 6, 10, 0x3C], [2118, 7, 11, 0x7D], [-22, 8, 32, 0xFE, 'lower'], [4166, 8, 32, 0xFF], [2, 0x2]];
- break;
- case 11:
- lines = [[1, 1, 0, 0x0], [2, 2, 1, 0x2], [4, 4, 0, 0xC], [5, 4, 1, 0xD], [7, 5, 1, 0x1C], [9, 5, 2, 0x1D], [13, 6, 2, 0x3C], [17, 7, 2, 0x7A], [21, 7, 3, 0x7B], [29, 7, 4, 0x7C], [45, 7, 5, 0x7D], [77, 7, 6, 0x7E], [141, 7, 32, 0x7F]];
- break;
- case 12:
- lines = [[1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 1, 0x6], [5, 5, 0, 0x1C], [6, 5, 1, 0x1D], [8, 6, 1, 0x3C], [10, 7, 0, 0x7A], [11, 7, 1, 0x7B], [13, 7, 2, 0x7C], [17, 7, 3, 0x7D], [25, 7, 4, 0x7E], [41, 8, 5, 0xFE], [73, 8, 32, 0xFF]];
- break;
- case 13:
- lines = [[1, 1, 0, 0x0], [2, 3, 0, 0x4], [3, 4, 0, 0xC], [4, 5, 0, 0x1C], [5, 4, 1, 0xD], [7, 3, 3, 0x5], [15, 6, 1, 0x3A], [17, 6, 2, 0x3B], [21, 6, 3, 0x3C], [29, 6, 4, 0x3D], [45, 6, 5, 0x3E], [77, 7, 6, 0x7E], [141, 7, 32, 0x7F]];
- break;
- case 14:
- lines = [[-2, 3, 0, 0x4], [-1, 3, 0, 0x5], [0, 1, 0, 0x0], [1, 3, 0, 0x6], [2, 3, 0, 0x7]];
- break;
- case 15:
- lines = [[-24, 7, 4, 0x7C], [-8, 6, 2, 0x3C], [-4, 5, 1, 0x1C], [-2, 4, 0, 0xC], [-1, 3, 0, 0x4], [0, 1, 0, 0x0], [1, 3, 0, 0x5], [2, 4, 0, 0xD], [3, 5, 1, 0x1D], [5, 6, 2, 0x3D], [9, 7, 4, 0x7D], [-25, 7, 32, 0x7E, 'lower'], [25, 7, 32, 0x7F]];
- break;
- default:
- throw new Jbig2Error('standard table B.' + number + ' does not exist');
- }
- var length = lines.length,
- i = void 0;
- for (i = 0; i < length; i++) {
- lines[i] = new HuffmanLine(lines[i]);
- }
- table = new HuffmanTable(lines, true);
- standardTablesCache[number] = table;
- return table;
- }
- function Reader(data, start, end) {
- this.data = data;
- this.start = start;
- this.end = end;
- this.position = start;
- this.shift = -1;
- this.currentByte = 0;
- }
- Reader.prototype = {
- readBit: function readBit() {
- if (this.shift < 0) {
- if (this.position >= this.end) {
- throw new Jbig2Error('end of data while reading bit');
- }
- this.currentByte = this.data[this.position++];
- this.shift = 7;
- }
- var bit = this.currentByte >> this.shift & 1;
- this.shift--;
- return bit;
- },
- readBits: function readBits(numBits) {
- var result = 0,
- i = void 0;
- for (i = numBits - 1; i >= 0; i--) {
- result |= this.readBit() << i;
- }
- return result;
- },
- byteAlign: function byteAlign() {
- this.shift = -1;
- },
- next: function next() {
- if (this.position >= this.end) {
- return -1;
- }
- return this.data[this.position++];
- }
- };
- function getCustomHuffmanTable(index, referredTo, customTables) {
- var currentIndex = 0,
- i = void 0,
- ii = referredTo.length,
- table = void 0;
- for (i = 0; i < ii; i++) {
- table = customTables[referredTo[i]];
- if (table) {
- if (index === currentIndex) {
- return table;
- }
- currentIndex++;
- }
- }
- throw new Jbig2Error('can\'t find custom Huffman table');
- }
- function getTextRegionHuffmanTables(textRegion, referredTo, customTables, numberOfSymbols, reader) {
- var codes = [],
- i = void 0,
- codeLength = void 0;
- for (i = 0; i <= 34; i++) {
- codeLength = reader.readBits(4);
- codes.push(new HuffmanLine([i, codeLength, 0, 0]));
- }
- var runCodesTable = new HuffmanTable(codes, false);
- codes.length = 0;
- for (i = 0; i < numberOfSymbols;) {
- codeLength = runCodesTable.decode(reader);
- if (codeLength >= 32) {
- var repeatedLength = void 0,
- numberOfRepeats = void 0,
- j = void 0;
- switch (codeLength) {
- case 32:
- if (i === 0) {
- throw new Jbig2Error('no previous value in symbol ID table');
- }
- numberOfRepeats = reader.readBits(2) + 3;
- repeatedLength = codes[i - 1].prefixLength;
- break;
- case 33:
- numberOfRepeats = reader.readBits(3) + 3;
- repeatedLength = 0;
- break;
- case 34:
- numberOfRepeats = reader.readBits(7) + 11;
- repeatedLength = 0;
- break;
- default:
- throw new Jbig2Error('invalid code length in symbol ID table');
- }
- for (j = 0; j < numberOfRepeats; j++) {
- codes.push(new HuffmanLine([i, repeatedLength, 0, 0]));
- i++;
- }
- } else {
- codes.push(new HuffmanLine([i, codeLength, 0, 0]));
- i++;
- }
- }
- reader.byteAlign();
- var symbolIDTable = new HuffmanTable(codes, false);
- var customIndex = 0,
- tableFirstS = void 0,
- tableDeltaS = void 0,
- tableDeltaT = void 0;
- switch (textRegion.huffmanFS) {
- case 0:
- case 1:
- tableFirstS = getStandardTable(textRegion.huffmanFS + 6);
- break;
- case 3:
- tableFirstS = getCustomHuffmanTable(customIndex, referredTo, customTables);
- customIndex++;
- break;
- default:
- throw new Jbig2Error('invalid Huffman FS selector');
- }
- switch (textRegion.huffmanDS) {
- case 0:
- case 1:
- case 2:
- tableDeltaS = getStandardTable(textRegion.huffmanDS + 8);
- break;
- case 3:
- tableDeltaS = getCustomHuffmanTable(customIndex, referredTo, customTables);
- customIndex++;
- break;
- default:
- throw new Jbig2Error('invalid Huffman DS selector');
- }
- switch (textRegion.huffmanDT) {
- case 0:
- case 1:
- case 2:
- tableDeltaT = getStandardTable(textRegion.huffmanDT + 11);
- break;
- case 3:
- tableDeltaT = getCustomHuffmanTable(customIndex, referredTo, customTables);
- customIndex++;
- break;
- default:
- throw new Jbig2Error('invalid Huffman DT selector');
- }
- if (textRegion.refinement) {
- throw new Jbig2Error('refinement with Huffman is not supported');
- }
- return {
- symbolIDTable: symbolIDTable,
- tableFirstS: tableFirstS,
- tableDeltaS: tableDeltaS,
- tableDeltaT: tableDeltaT
- };
- }
- function getSymbolDictionaryHuffmanTables(dictionary, referredTo, customTables) {
- var customIndex = 0,
- tableDeltaHeight = void 0,
- tableDeltaWidth = void 0;
- switch (dictionary.huffmanDHSelector) {
- case 0:
- case 1:
- tableDeltaHeight = getStandardTable(dictionary.huffmanDHSelector + 4);
- break;
- case 3:
- tableDeltaHeight = getCustomHuffmanTable(customIndex, referredTo, customTables);
- customIndex++;
- break;
- default:
- throw new Jbig2Error('invalid Huffman DH selector');
- }
- switch (dictionary.huffmanDWSelector) {
- case 0:
- case 1:
- tableDeltaWidth = getStandardTable(dictionary.huffmanDWSelector + 2);
- break;
- case 3:
- tableDeltaWidth = getCustomHuffmanTable(customIndex, referredTo, customTables);
- customIndex++;
- break;
- default:
- throw new Jbig2Error('invalid Huffman DW selector');
- }
- var tableBitmapSize = void 0,
- tableAggregateInstances = void 0;
- if (dictionary.bitmapSizeSelector) {
- tableBitmapSize = getCustomHuffmanTable(customIndex, referredTo, customTables);
- customIndex++;
- } else {
- tableBitmapSize = getStandardTable(1);
- }
- if (dictionary.aggregationInstancesSelector) {
- tableAggregateInstances = getCustomHuffmanTable(customIndex, referredTo, customTables);
- } else {
- tableAggregateInstances = getStandardTable(1);
- }
- return {
- tableDeltaHeight: tableDeltaHeight,
- tableDeltaWidth: tableDeltaWidth,
- tableBitmapSize: tableBitmapSize,
- tableAggregateInstances: tableAggregateInstances
- };
- }
- function readUncompressedBitmap(reader, width, height) {
- var bitmap = [],
- x = void 0,
- y = void 0,
- row = void 0;
- for (y = 0; y < height; y++) {
- row = new Uint8Array(width);
- bitmap.push(row);
- for (x = 0; x < width; x++) {
- row[x] = reader.readBit();
- }
- reader.byteAlign();
- }
- return bitmap;
- }
- function decodeMMRBitmap(input, width, height, endOfBlock) {
- var params = {
- K: -1,
- Columns: width,
- Rows: height,
- BlackIs1: true,
- EndOfBlock: endOfBlock
- };
- var decoder = new _ccitt.CCITTFaxDecoder(input, params);
- var bitmap = [],
- x = void 0,
- y = void 0,
- row = void 0,
- currentByte = void 0,
- shift = void 0,
- eof = false;
- for (y = 0; y < height; y++) {
- row = new Uint8Array(width);
- bitmap.push(row);
- shift = -1;
- for (x = 0; x < width; x++) {
- if (shift < 0) {
- currentByte = decoder.readNextChar();
- if (currentByte === -1) {
- currentByte = 0;
- eof = true;
- }
- shift = 7;
- }
- row[x] = currentByte >> shift & 1;
- shift--;
- }
- }
- if (endOfBlock && !eof) {
- var lookForEOFLimit = 5;
- for (var i = 0; i < lookForEOFLimit; i++) {
- if (decoder.readNextChar() === -1) {
- break;
- }
- }
- }
- return bitmap;
- }
- function Jbig2Image() {}
- Jbig2Image.prototype = {
- parseChunks: function parseChunks(chunks) {
- return parseJbig2Chunks(chunks);
- },
- parse: function parse(data) {
- var _parseJbig = parseJbig2(data),
- imgData = _parseJbig.imgData,
- width = _parseJbig.width,
- height = _parseJbig.height;
-
- this.width = width;
- this.height = height;
- return imgData;
- }
- };
- return Jbig2Image;
-}();
-exports.Jbig2Image = Jbig2Image;
-
-/***/ }),
-/* 145 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-var ArithmeticDecoder = function ArithmeticDecoderClosure() {
- var QeTable = [{
- qe: 0x5601,
- nmps: 1,
- nlps: 1,
- switchFlag: 1
- }, {
- qe: 0x3401,
- nmps: 2,
- nlps: 6,
- switchFlag: 0
- }, {
- qe: 0x1801,
- nmps: 3,
- nlps: 9,
- switchFlag: 0
- }, {
- qe: 0x0AC1,
- nmps: 4,
- nlps: 12,
- switchFlag: 0
- }, {
- qe: 0x0521,
- nmps: 5,
- nlps: 29,
- switchFlag: 0
- }, {
- qe: 0x0221,
- nmps: 38,
- nlps: 33,
- switchFlag: 0
- }, {
- qe: 0x5601,
- nmps: 7,
- nlps: 6,
- switchFlag: 1
- }, {
- qe: 0x5401,
- nmps: 8,
- nlps: 14,
- switchFlag: 0
- }, {
- qe: 0x4801,
- nmps: 9,
- nlps: 14,
- switchFlag: 0
- }, {
- qe: 0x3801,
- nmps: 10,
- nlps: 14,
- switchFlag: 0
- }, {
- qe: 0x3001,
- nmps: 11,
- nlps: 17,
- switchFlag: 0
- }, {
- qe: 0x2401,
- nmps: 12,
- nlps: 18,
- switchFlag: 0
- }, {
- qe: 0x1C01,
- nmps: 13,
- nlps: 20,
- switchFlag: 0
- }, {
- qe: 0x1601,
- nmps: 29,
- nlps: 21,
- switchFlag: 0
- }, {
- qe: 0x5601,
- nmps: 15,
- nlps: 14,
- switchFlag: 1
- }, {
- qe: 0x5401,
- nmps: 16,
- nlps: 14,
- switchFlag: 0
- }, {
- qe: 0x5101,
- nmps: 17,
- nlps: 15,
- switchFlag: 0
- }, {
- qe: 0x4801,
- nmps: 18,
- nlps: 16,
- switchFlag: 0
- }, {
- qe: 0x3801,
- nmps: 19,
- nlps: 17,
- switchFlag: 0
- }, {
- qe: 0x3401,
- nmps: 20,
- nlps: 18,
- switchFlag: 0
- }, {
- qe: 0x3001,
- nmps: 21,
- nlps: 19,
- switchFlag: 0
- }, {
- qe: 0x2801,
- nmps: 22,
- nlps: 19,
- switchFlag: 0
- }, {
- qe: 0x2401,
- nmps: 23,
- nlps: 20,
- switchFlag: 0
- }, {
- qe: 0x2201,
- nmps: 24,
- nlps: 21,
- switchFlag: 0
- }, {
- qe: 0x1C01,
- nmps: 25,
- nlps: 22,
- switchFlag: 0
- }, {
- qe: 0x1801,
- nmps: 26,
- nlps: 23,
- switchFlag: 0
- }, {
- qe: 0x1601,
- nmps: 27,
- nlps: 24,
- switchFlag: 0
- }, {
- qe: 0x1401,
- nmps: 28,
- nlps: 25,
- switchFlag: 0
- }, {
- qe: 0x1201,
- nmps: 29,
- nlps: 26,
- switchFlag: 0
- }, {
- qe: 0x1101,
- nmps: 30,
- nlps: 27,
- switchFlag: 0
- }, {
- qe: 0x0AC1,
- nmps: 31,
- nlps: 28,
- switchFlag: 0
- }, {
- qe: 0x09C1,
- nmps: 32,
- nlps: 29,
- switchFlag: 0
- }, {
- qe: 0x08A1,
- nmps: 33,
- nlps: 30,
- switchFlag: 0
- }, {
- qe: 0x0521,
- nmps: 34,
- nlps: 31,
- switchFlag: 0
- }, {
- qe: 0x0441,
- nmps: 35,
- nlps: 32,
- switchFlag: 0
- }, {
- qe: 0x02A1,
- nmps: 36,
- nlps: 33,
- switchFlag: 0
- }, {
- qe: 0x0221,
- nmps: 37,
- nlps: 34,
- switchFlag: 0
- }, {
- qe: 0x0141,
- nmps: 38,
- nlps: 35,
- switchFlag: 0
- }, {
- qe: 0x0111,
- nmps: 39,
- nlps: 36,
- switchFlag: 0
- }, {
- qe: 0x0085,
- nmps: 40,
- nlps: 37,
- switchFlag: 0
- }, {
- qe: 0x0049,
- nmps: 41,
- nlps: 38,
- switchFlag: 0
- }, {
- qe: 0x0025,
- nmps: 42,
- nlps: 39,
- switchFlag: 0
- }, {
- qe: 0x0015,
- nmps: 43,
- nlps: 40,
- switchFlag: 0
- }, {
- qe: 0x0009,
- nmps: 44,
- nlps: 41,
- switchFlag: 0
- }, {
- qe: 0x0005,
- nmps: 45,
- nlps: 42,
- switchFlag: 0
- }, {
- qe: 0x0001,
- nmps: 45,
- nlps: 43,
- switchFlag: 0
- }, {
- qe: 0x5601,
- nmps: 46,
- nlps: 46,
- switchFlag: 0
- }];
- function ArithmeticDecoder(data, start, end) {
- this.data = data;
- this.bp = start;
- this.dataEnd = end;
- this.chigh = data[start];
- this.clow = 0;
- this.byteIn();
- this.chigh = this.chigh << 7 & 0xFFFF | this.clow >> 9 & 0x7F;
- this.clow = this.clow << 7 & 0xFFFF;
- this.ct -= 7;
- this.a = 0x8000;
- }
- ArithmeticDecoder.prototype = {
- byteIn: function ArithmeticDecoder_byteIn() {
- var data = this.data;
- var bp = this.bp;
- if (data[bp] === 0xFF) {
- var b1 = data[bp + 1];
- if (b1 > 0x8F) {
- this.clow += 0xFF00;
- this.ct = 8;
- } else {
- bp++;
- this.clow += data[bp] << 9;
- this.ct = 7;
- this.bp = bp;
- }
- } else {
- bp++;
- this.clow += bp < this.dataEnd ? data[bp] << 8 : 0xFF00;
- this.ct = 8;
- this.bp = bp;
- }
- if (this.clow > 0xFFFF) {
- this.chigh += this.clow >> 16;
- this.clow &= 0xFFFF;
- }
- },
- readBit: function ArithmeticDecoder_readBit(contexts, pos) {
- var cx_index = contexts[pos] >> 1,
- cx_mps = contexts[pos] & 1;
- var qeTableIcx = QeTable[cx_index];
- var qeIcx = qeTableIcx.qe;
- var d;
- var a = this.a - qeIcx;
- if (this.chigh < qeIcx) {
- if (a < qeIcx) {
- a = qeIcx;
- d = cx_mps;
- cx_index = qeTableIcx.nmps;
- } else {
- a = qeIcx;
- d = 1 ^ cx_mps;
- if (qeTableIcx.switchFlag === 1) {
- cx_mps = d;
- }
- cx_index = qeTableIcx.nlps;
- }
- } else {
- this.chigh -= qeIcx;
- if ((a & 0x8000) !== 0) {
- this.a = a;
- return cx_mps;
- }
- if (a < qeIcx) {
- d = 1 ^ cx_mps;
- if (qeTableIcx.switchFlag === 1) {
- cx_mps = d;
- }
- cx_index = qeTableIcx.nlps;
- } else {
- d = cx_mps;
- cx_index = qeTableIcx.nmps;
- }
- }
- do {
- if (this.ct === 0) {
- this.byteIn();
- }
- a <<= 1;
- this.chigh = this.chigh << 1 & 0xFFFF | this.clow >> 15 & 1;
- this.clow = this.clow << 1 & 0xFFFF;
- this.ct--;
- } while ((a & 0x8000) === 0);
- this.a = a;
- contexts[pos] = cx_index << 1 | cx_mps;
- return d;
- }
- };
- return ArithmeticDecoder;
-}();
-exports.ArithmeticDecoder = ArithmeticDecoder;
-
-/***/ }),
-/* 146 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.JpegStream = undefined;
-
-var _util = __w_pdfjs_require__(2);
-
-var _stream = __w_pdfjs_require__(140);
-
-var _primitives = __w_pdfjs_require__(138);
-
-var _jpg = __w_pdfjs_require__(147);
-
-var JpegStream = function JpegStreamClosure() {
- function JpegStream(stream, maybeLength, dict, params) {
- var ch = void 0;
- while ((ch = stream.getByte()) !== -1) {
- if (ch === 0xFF) {
- stream.skip(-1);
- break;
- }
- }
- this.stream = stream;
- this.maybeLength = maybeLength;
- this.dict = dict;
- this.params = params;
- _stream.DecodeStream.call(this, maybeLength);
- }
- JpegStream.prototype = Object.create(_stream.DecodeStream.prototype);
- Object.defineProperty(JpegStream.prototype, 'bytes', {
- get: function JpegStream_bytes() {
- return (0, _util.shadow)(this, 'bytes', this.stream.getBytes(this.maybeLength));
- },
- configurable: true
- });
- JpegStream.prototype.ensureBuffer = function (requested) {};
- JpegStream.prototype.readBlock = function () {
- if (this.eof) {
- return;
- }
- var jpegOptions = {
- decodeTransform: undefined,
- colorTransform: undefined
- };
- var decodeArr = this.dict.getArray('Decode', 'D');
- if (this.forceRGB && Array.isArray(decodeArr)) {
- var bitsPerComponent = this.dict.get('BitsPerComponent') || 8;
- var decodeArrLength = decodeArr.length;
- var transform = new Int32Array(decodeArrLength);
- var transformNeeded = false;
- var maxValue = (1 << bitsPerComponent) - 1;
- for (var i = 0; i < decodeArrLength; i += 2) {
- transform[i] = (decodeArr[i + 1] - decodeArr[i]) * 256 | 0;
- transform[i + 1] = decodeArr[i] * maxValue | 0;
- if (transform[i] !== 256 || transform[i + 1] !== 0) {
- transformNeeded = true;
- }
- }
- if (transformNeeded) {
- jpegOptions.decodeTransform = transform;
- }
- }
- if ((0, _primitives.isDict)(this.params)) {
- var colorTransform = this.params.get('ColorTransform');
- if (Number.isInteger(colorTransform)) {
- jpegOptions.colorTransform = colorTransform;
- }
- }
- var jpegImage = new _jpg.JpegImage(jpegOptions);
- jpegImage.parse(this.bytes);
- var data = jpegImage.getData({
- width: this.drawWidth,
- height: this.drawHeight,
- forceRGB: this.forceRGB,
- isSourcePDF: true
- });
- this.buffer = data;
- this.bufferLength = data.length;
- this.eof = true;
- };
- JpegStream.prototype.getIR = function () {
- var forceDataSchema = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
-
- return (0, _util.createObjectURL)(this.bytes, 'image/jpeg', forceDataSchema);
- };
- return JpegStream;
-}();
-exports.JpegStream = JpegStream;
-
-/***/ }),
-/* 147 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.JpegImage = undefined;
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-var _util = __w_pdfjs_require__(2);
-
-var JpegError = function JpegErrorClosure() {
- function JpegError(msg) {
- this.message = 'JPEG error: ' + msg;
- }
- JpegError.prototype = new Error();
- JpegError.prototype.name = 'JpegError';
- JpegError.constructor = JpegError;
- return JpegError;
-}();
-var DNLMarkerError = function DNLMarkerErrorClosure() {
- function DNLMarkerError(message, scanLines) {
- this.message = message;
- this.scanLines = scanLines;
- }
- DNLMarkerError.prototype = new Error();
- DNLMarkerError.prototype.name = 'DNLMarkerError';
- DNLMarkerError.constructor = DNLMarkerError;
- return DNLMarkerError;
-}();
-var EOIMarkerError = function EOIMarkerErrorClosure() {
- function EOIMarkerError(message) {
- this.message = message;
- }
- EOIMarkerError.prototype = new Error();
- EOIMarkerError.prototype.name = 'EOIMarkerError';
- EOIMarkerError.constructor = EOIMarkerError;
- return EOIMarkerError;
-}();
-var JpegImage = function JpegImageClosure() {
- var dctZigZag = new Uint8Array([0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63]);
- var dctCos1 = 4017;
- var dctSin1 = 799;
- var dctCos3 = 3406;
- var dctSin3 = 2276;
- var dctCos6 = 1567;
- var dctSin6 = 3784;
- var dctSqrt2 = 5793;
- var dctSqrt1d2 = 2896;
- function JpegImage() {
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
- _ref$decodeTransform = _ref.decodeTransform,
- decodeTransform = _ref$decodeTransform === undefined ? null : _ref$decodeTransform,
- _ref$colorTransform = _ref.colorTransform,
- colorTransform = _ref$colorTransform === undefined ? -1 : _ref$colorTransform;
-
- this._decodeTransform = decodeTransform;
- this._colorTransform = colorTransform;
- }
- function buildHuffmanTable(codeLengths, values) {
- var k = 0,
- code = [],
- i,
- j,
- length = 16;
- while (length > 0 && !codeLengths[length - 1]) {
- length--;
- }
- code.push({
- children: [],
- index: 0
- });
- var p = code[0],
- q;
- for (i = 0; i < length; i++) {
- for (j = 0; j < codeLengths[i]; j++) {
- p = code.pop();
- p.children[p.index] = values[k];
- while (p.index > 0) {
- p = code.pop();
- }
- p.index++;
- code.push(p);
- while (code.length <= i) {
- code.push(q = {
- children: [],
- index: 0
- });
- p.children[p.index] = q.children;
- p = q;
- }
- k++;
- }
- if (i + 1 < length) {
- code.push(q = {
- children: [],
- index: 0
- });
- p.children[p.index] = q.children;
- p = q;
- }
- }
- return code[0].children;
- }
- function getBlockBufferOffset(component, row, col) {
- return 64 * ((component.blocksPerLine + 1) * row + col);
- }
- function decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successivePrev, successive) {
- var parseDNLMarker = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false;
-
- var mcusPerLine = frame.mcusPerLine;
- var progressive = frame.progressive;
- var startOffset = offset,
- bitsData = 0,
- bitsCount = 0;
- function readBit() {
- if (bitsCount > 0) {
- bitsCount--;
- return bitsData >> bitsCount & 1;
- }
- bitsData = data[offset++];
- if (bitsData === 0xFF) {
- var nextByte = data[offset++];
- if (nextByte) {
- if (nextByte === 0xDC && parseDNLMarker) {
- offset += 2;
- var scanLines = data[offset++] << 8 | data[offset++];
- if (scanLines > 0 && scanLines !== frame.scanLines) {
- throw new DNLMarkerError('Found DNL marker (0xFFDC) while parsing scan data', scanLines);
- }
- } else if (nextByte === 0xD9) {
- throw new EOIMarkerError('Found EOI marker (0xFFD9) while parsing scan data');
- }
- throw new JpegError('unexpected marker ' + (bitsData << 8 | nextByte).toString(16));
- }
- }
- bitsCount = 7;
- return bitsData >>> 7;
- }
- function decodeHuffman(tree) {
- var node = tree;
- while (true) {
- node = node[readBit()];
- if (typeof node === 'number') {
- return node;
- }
- if ((typeof node === 'undefined' ? 'undefined' : _typeof(node)) !== 'object') {
- throw new JpegError('invalid huffman sequence');
- }
- }
- }
- function receive(length) {
- var n = 0;
- while (length > 0) {
- n = n << 1 | readBit();
- length--;
- }
- return n;
- }
- function receiveAndExtend(length) {
- if (length === 1) {
- return readBit() === 1 ? 1 : -1;
- }
- var n = receive(length);
- if (n >= 1 << length - 1) {
- return n;
- }
- return n + (-1 << length) + 1;
- }
- function decodeBaseline(component, offset) {
- var t = decodeHuffman(component.huffmanTableDC);
- var diff = t === 0 ? 0 : receiveAndExtend(t);
- component.blockData[offset] = component.pred += diff;
- var k = 1;
- while (k < 64) {
- var rs = decodeHuffman(component.huffmanTableAC);
- var s = rs & 15,
- r = rs >> 4;
- if (s === 0) {
- if (r < 15) {
- break;
- }
- k += 16;
- continue;
- }
- k += r;
- var z = dctZigZag[k];
- component.blockData[offset + z] = receiveAndExtend(s);
- k++;
- }
- }
- function decodeDCFirst(component, offset) {
- var t = decodeHuffman(component.huffmanTableDC);
- var diff = t === 0 ? 0 : receiveAndExtend(t) << successive;
- component.blockData[offset] = component.pred += diff;
- }
- function decodeDCSuccessive(component, offset) {
- component.blockData[offset] |= readBit() << successive;
- }
- var eobrun = 0;
- function decodeACFirst(component, offset) {
- if (eobrun > 0) {
- eobrun--;
- return;
- }
- var k = spectralStart,
- e = spectralEnd;
- while (k <= e) {
- var rs = decodeHuffman(component.huffmanTableAC);
- var s = rs & 15,
- r = rs >> 4;
- if (s === 0) {
- if (r < 15) {
- eobrun = receive(r) + (1 << r) - 1;
- break;
- }
- k += 16;
- continue;
- }
- k += r;
- var z = dctZigZag[k];
- component.blockData[offset + z] = receiveAndExtend(s) * (1 << successive);
- k++;
- }
- }
- var successiveACState = 0,
- successiveACNextValue;
- function decodeACSuccessive(component, offset) {
- var k = spectralStart;
- var e = spectralEnd;
- var r = 0;
- var s;
- var rs;
- while (k <= e) {
- var offsetZ = offset + dctZigZag[k];
- var sign = component.blockData[offsetZ] < 0 ? -1 : 1;
- switch (successiveACState) {
- case 0:
- rs = decodeHuffman(component.huffmanTableAC);
- s = rs & 15;
- r = rs >> 4;
- if (s === 0) {
- if (r < 15) {
- eobrun = receive(r) + (1 << r);
- successiveACState = 4;
- } else {
- r = 16;
- successiveACState = 1;
- }
- } else {
- if (s !== 1) {
- throw new JpegError('invalid ACn encoding');
- }
- successiveACNextValue = receiveAndExtend(s);
- successiveACState = r ? 2 : 3;
- }
- continue;
- case 1:
- case 2:
- if (component.blockData[offsetZ]) {
- component.blockData[offsetZ] += sign * (readBit() << successive);
- } else {
- r--;
- if (r === 0) {
- successiveACState = successiveACState === 2 ? 3 : 0;
- }
- }
- break;
- case 3:
- if (component.blockData[offsetZ]) {
- component.blockData[offsetZ] += sign * (readBit() << successive);
- } else {
- component.blockData[offsetZ] = successiveACNextValue << successive;
- successiveACState = 0;
- }
- break;
- case 4:
- if (component.blockData[offsetZ]) {
- component.blockData[offsetZ] += sign * (readBit() << successive);
- }
- break;
- }
- k++;
- }
- if (successiveACState === 4) {
- eobrun--;
- if (eobrun === 0) {
- successiveACState = 0;
- }
- }
- }
- function decodeMcu(component, decode, mcu, row, col) {
- var mcuRow = mcu / mcusPerLine | 0;
- var mcuCol = mcu % mcusPerLine;
- var blockRow = mcuRow * component.v + row;
- var blockCol = mcuCol * component.h + col;
- var offset = getBlockBufferOffset(component, blockRow, blockCol);
- decode(component, offset);
- }
- function decodeBlock(component, decode, mcu) {
- var blockRow = mcu / component.blocksPerLine | 0;
- var blockCol = mcu % component.blocksPerLine;
- var offset = getBlockBufferOffset(component, blockRow, blockCol);
- decode(component, offset);
- }
- var componentsLength = components.length;
- var component, i, j, k, n;
- var decodeFn;
- if (progressive) {
- if (spectralStart === 0) {
- decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive;
- } else {
- decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive;
- }
- } else {
- decodeFn = decodeBaseline;
- }
- var mcu = 0,
- fileMarker;
- var mcuExpected;
- if (componentsLength === 1) {
- mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn;
- } else {
- mcuExpected = mcusPerLine * frame.mcusPerColumn;
- }
- var h, v;
- while (mcu < mcuExpected) {
- var mcuToRead = resetInterval ? Math.min(mcuExpected - mcu, resetInterval) : mcuExpected;
- for (i = 0; i < componentsLength; i++) {
- components[i].pred = 0;
- }
- eobrun = 0;
- if (componentsLength === 1) {
- component = components[0];
- for (n = 0; n < mcuToRead; n++) {
- decodeBlock(component, decodeFn, mcu);
- mcu++;
- }
- } else {
- for (n = 0; n < mcuToRead; n++) {
- for (i = 0; i < componentsLength; i++) {
- component = components[i];
- h = component.h;
- v = component.v;
- for (j = 0; j < v; j++) {
- for (k = 0; k < h; k++) {
- decodeMcu(component, decodeFn, mcu, j, k);
- }
- }
- }
- mcu++;
- }
- }
- bitsCount = 0;
- fileMarker = findNextFileMarker(data, offset);
- if (fileMarker && fileMarker.invalid) {
- (0, _util.warn)('decodeScan - unexpected MCU data, current marker is: ' + fileMarker.invalid);
- offset = fileMarker.offset;
- }
- var marker = fileMarker && fileMarker.marker;
- if (!marker || marker <= 0xFF00) {
- throw new JpegError('marker was not found');
- }
- if (marker >= 0xFFD0 && marker <= 0xFFD7) {
- offset += 2;
- } else {
- break;
- }
- }
- fileMarker = findNextFileMarker(data, offset);
- if (fileMarker && fileMarker.invalid) {
- (0, _util.warn)('decodeScan - unexpected Scan data, current marker is: ' + fileMarker.invalid);
- offset = fileMarker.offset;
- }
- return offset - startOffset;
- }
- function quantizeAndInverse(component, blockBufferOffset, p) {
- var qt = component.quantizationTable,
- blockData = component.blockData;
- var v0, v1, v2, v3, v4, v5, v6, v7;
- var p0, p1, p2, p3, p4, p5, p6, p7;
- var t;
- if (!qt) {
- throw new JpegError('missing required Quantization Table.');
- }
- for (var row = 0; row < 64; row += 8) {
- p0 = blockData[blockBufferOffset + row];
- p1 = blockData[blockBufferOffset + row + 1];
- p2 = blockData[blockBufferOffset + row + 2];
- p3 = blockData[blockBufferOffset + row + 3];
- p4 = blockData[blockBufferOffset + row + 4];
- p5 = blockData[blockBufferOffset + row + 5];
- p6 = blockData[blockBufferOffset + row + 6];
- p7 = blockData[blockBufferOffset + row + 7];
- p0 *= qt[row];
- if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) {
- t = dctSqrt2 * p0 + 512 >> 10;
- p[row] = t;
- p[row + 1] = t;
- p[row + 2] = t;
- p[row + 3] = t;
- p[row + 4] = t;
- p[row + 5] = t;
- p[row + 6] = t;
- p[row + 7] = t;
- continue;
- }
- p1 *= qt[row + 1];
- p2 *= qt[row + 2];
- p3 *= qt[row + 3];
- p4 *= qt[row + 4];
- p5 *= qt[row + 5];
- p6 *= qt[row + 6];
- p7 *= qt[row + 7];
- v0 = dctSqrt2 * p0 + 128 >> 8;
- v1 = dctSqrt2 * p4 + 128 >> 8;
- v2 = p2;
- v3 = p6;
- v4 = dctSqrt1d2 * (p1 - p7) + 128 >> 8;
- v7 = dctSqrt1d2 * (p1 + p7) + 128 >> 8;
- v5 = p3 << 4;
- v6 = p5 << 4;
- v0 = v0 + v1 + 1 >> 1;
- v1 = v0 - v1;
- t = v2 * dctSin6 + v3 * dctCos6 + 128 >> 8;
- v2 = v2 * dctCos6 - v3 * dctSin6 + 128 >> 8;
- v3 = t;
- v4 = v4 + v6 + 1 >> 1;
- v6 = v4 - v6;
- v7 = v7 + v5 + 1 >> 1;
- v5 = v7 - v5;
- v0 = v0 + v3 + 1 >> 1;
- v3 = v0 - v3;
- v1 = v1 + v2 + 1 >> 1;
- v2 = v1 - v2;
- t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12;
- v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12;
- v7 = t;
- t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12;
- v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12;
- v6 = t;
- p[row] = v0 + v7;
- p[row + 7] = v0 - v7;
- p[row + 1] = v1 + v6;
- p[row + 6] = v1 - v6;
- p[row + 2] = v2 + v5;
- p[row + 5] = v2 - v5;
- p[row + 3] = v3 + v4;
- p[row + 4] = v3 - v4;
- }
- for (var col = 0; col < 8; ++col) {
- p0 = p[col];
- p1 = p[col + 8];
- p2 = p[col + 16];
- p3 = p[col + 24];
- p4 = p[col + 32];
- p5 = p[col + 40];
- p6 = p[col + 48];
- p7 = p[col + 56];
- if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) {
- t = dctSqrt2 * p0 + 8192 >> 14;
- t = t < -2040 ? 0 : t >= 2024 ? 255 : t + 2056 >> 4;
- blockData[blockBufferOffset + col] = t;
- blockData[blockBufferOffset + col + 8] = t;
- blockData[blockBufferOffset + col + 16] = t;
- blockData[blockBufferOffset + col + 24] = t;
- blockData[blockBufferOffset + col + 32] = t;
- blockData[blockBufferOffset + col + 40] = t;
- blockData[blockBufferOffset + col + 48] = t;
- blockData[blockBufferOffset + col + 56] = t;
- continue;
- }
- v0 = dctSqrt2 * p0 + 2048 >> 12;
- v1 = dctSqrt2 * p4 + 2048 >> 12;
- v2 = p2;
- v3 = p6;
- v4 = dctSqrt1d2 * (p1 - p7) + 2048 >> 12;
- v7 = dctSqrt1d2 * (p1 + p7) + 2048 >> 12;
- v5 = p3;
- v6 = p5;
- v0 = (v0 + v1 + 1 >> 1) + 4112;
- v1 = v0 - v1;
- t = v2 * dctSin6 + v3 * dctCos6 + 2048 >> 12;
- v2 = v2 * dctCos6 - v3 * dctSin6 + 2048 >> 12;
- v3 = t;
- v4 = v4 + v6 + 1 >> 1;
- v6 = v4 - v6;
- v7 = v7 + v5 + 1 >> 1;
- v5 = v7 - v5;
- v0 = v0 + v3 + 1 >> 1;
- v3 = v0 - v3;
- v1 = v1 + v2 + 1 >> 1;
- v2 = v1 - v2;
- t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12;
- v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12;
- v7 = t;
- t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12;
- v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12;
- v6 = t;
- p0 = v0 + v7;
- p7 = v0 - v7;
- p1 = v1 + v6;
- p6 = v1 - v6;
- p2 = v2 + v5;
- p5 = v2 - v5;
- p3 = v3 + v4;
- p4 = v3 - v4;
- p0 = p0 < 16 ? 0 : p0 >= 4080 ? 255 : p0 >> 4;
- p1 = p1 < 16 ? 0 : p1 >= 4080 ? 255 : p1 >> 4;
- p2 = p2 < 16 ? 0 : p2 >= 4080 ? 255 : p2 >> 4;
- p3 = p3 < 16 ? 0 : p3 >= 4080 ? 255 : p3 >> 4;
- p4 = p4 < 16 ? 0 : p4 >= 4080 ? 255 : p4 >> 4;
- p5 = p5 < 16 ? 0 : p5 >= 4080 ? 255 : p5 >> 4;
- p6 = p6 < 16 ? 0 : p6 >= 4080 ? 255 : p6 >> 4;
- p7 = p7 < 16 ? 0 : p7 >= 4080 ? 255 : p7 >> 4;
- blockData[blockBufferOffset + col] = p0;
- blockData[blockBufferOffset + col + 8] = p1;
- blockData[blockBufferOffset + col + 16] = p2;
- blockData[blockBufferOffset + col + 24] = p3;
- blockData[blockBufferOffset + col + 32] = p4;
- blockData[blockBufferOffset + col + 40] = p5;
- blockData[blockBufferOffset + col + 48] = p6;
- blockData[blockBufferOffset + col + 56] = p7;
- }
- }
- function buildComponentData(frame, component) {
- var blocksPerLine = component.blocksPerLine;
- var blocksPerColumn = component.blocksPerColumn;
- var computationBuffer = new Int16Array(64);
- for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
- for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) {
- var offset = getBlockBufferOffset(component, blockRow, blockCol);
- quantizeAndInverse(component, offset, computationBuffer);
- }
- }
- return component.blockData;
- }
- function findNextFileMarker(data, currentPos) {
- var startPos = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : currentPos;
-
- function peekUint16(pos) {
- return data[pos] << 8 | data[pos + 1];
- }
- var maxPos = data.length - 1;
- var newPos = startPos < currentPos ? startPos : currentPos;
- if (currentPos >= maxPos) {
- return null;
- }
- var currentMarker = peekUint16(currentPos);
- if (currentMarker >= 0xFFC0 && currentMarker <= 0xFFFE) {
- return {
- invalid: null,
- marker: currentMarker,
- offset: currentPos
- };
- }
- var newMarker = peekUint16(newPos);
- while (!(newMarker >= 0xFFC0 && newMarker <= 0xFFFE)) {
- if (++newPos >= maxPos) {
- return null;
- }
- newMarker = peekUint16(newPos);
- }
- return {
- invalid: currentMarker.toString(16),
- marker: newMarker,
- offset: newPos
- };
- }
- JpegImage.prototype = {
- parse: function parse(data) {
- var _ref2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
- _ref2$dnlScanLines = _ref2.dnlScanLines,
- dnlScanLines = _ref2$dnlScanLines === undefined ? null : _ref2$dnlScanLines;
-
- function readUint16() {
- var value = data[offset] << 8 | data[offset + 1];
- offset += 2;
- return value;
- }
- function readDataBlock() {
- var length = readUint16();
- var endOffset = offset + length - 2;
- var fileMarker = findNextFileMarker(data, endOffset, offset);
- if (fileMarker && fileMarker.invalid) {
- (0, _util.warn)('readDataBlock - incorrect length, current marker is: ' + fileMarker.invalid);
- endOffset = fileMarker.offset;
- }
- var array = data.subarray(offset, endOffset);
- offset += array.length;
- return array;
- }
- function prepareComponents(frame) {
- var mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / frame.maxH);
- var mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV);
- for (var i = 0; i < frame.components.length; i++) {
- component = frame.components[i];
- var blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / frame.maxH);
- var blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * component.v / frame.maxV);
- var blocksPerLineForMcu = mcusPerLine * component.h;
- var blocksPerColumnForMcu = mcusPerColumn * component.v;
- var blocksBufferSize = 64 * blocksPerColumnForMcu * (blocksPerLineForMcu + 1);
- component.blockData = new Int16Array(blocksBufferSize);
- component.blocksPerLine = blocksPerLine;
- component.blocksPerColumn = blocksPerColumn;
- }
- frame.mcusPerLine = mcusPerLine;
- frame.mcusPerColumn = mcusPerColumn;
- }
- var offset = 0;
- var jfif = null;
- var adobe = null;
- var frame, resetInterval;
- var numSOSMarkers = 0;
- var quantizationTables = [];
- var huffmanTablesAC = [],
- huffmanTablesDC = [];
- var fileMarker = readUint16();
- if (fileMarker !== 0xFFD8) {
- throw new JpegError('SOI not found');
- }
- fileMarker = readUint16();
- markerLoop: while (fileMarker !== 0xFFD9) {
- var i, j, l;
- switch (fileMarker) {
- case 0xFFE0:
- case 0xFFE1:
- case 0xFFE2:
- case 0xFFE3:
- case 0xFFE4:
- case 0xFFE5:
- case 0xFFE6:
- case 0xFFE7:
- case 0xFFE8:
- case 0xFFE9:
- case 0xFFEA:
- case 0xFFEB:
- case 0xFFEC:
- case 0xFFED:
- case 0xFFEE:
- case 0xFFEF:
- case 0xFFFE:
- var appData = readDataBlock();
- if (fileMarker === 0xFFE0) {
- if (appData[0] === 0x4A && appData[1] === 0x46 && appData[2] === 0x49 && appData[3] === 0x46 && appData[4] === 0) {
- jfif = {
- version: {
- major: appData[5],
- minor: appData[6]
- },
- densityUnits: appData[7],
- xDensity: appData[8] << 8 | appData[9],
- yDensity: appData[10] << 8 | appData[11],
- thumbWidth: appData[12],
- thumbHeight: appData[13],
- thumbData: appData.subarray(14, 14 + 3 * appData[12] * appData[13])
- };
- }
- }
- if (fileMarker === 0xFFEE) {
- if (appData[0] === 0x41 && appData[1] === 0x64 && appData[2] === 0x6F && appData[3] === 0x62 && appData[4] === 0x65) {
- adobe = {
- version: appData[5] << 8 | appData[6],
- flags0: appData[7] << 8 | appData[8],
- flags1: appData[9] << 8 | appData[10],
- transformCode: appData[11]
- };
- }
- }
- break;
- case 0xFFDB:
- var quantizationTablesLength = readUint16();
- var quantizationTablesEnd = quantizationTablesLength + offset - 2;
- var z;
- while (offset < quantizationTablesEnd) {
- var quantizationTableSpec = data[offset++];
- var tableData = new Uint16Array(64);
- if (quantizationTableSpec >> 4 === 0) {
- for (j = 0; j < 64; j++) {
- z = dctZigZag[j];
- tableData[z] = data[offset++];
- }
- } else if (quantizationTableSpec >> 4 === 1) {
- for (j = 0; j < 64; j++) {
- z = dctZigZag[j];
- tableData[z] = readUint16();
- }
- } else {
- throw new JpegError('DQT - invalid table spec');
- }
- quantizationTables[quantizationTableSpec & 15] = tableData;
- }
- break;
- case 0xFFC0:
- case 0xFFC1:
- case 0xFFC2:
- if (frame) {
- throw new JpegError('Only single frame JPEGs supported');
- }
- readUint16();
- frame = {};
- frame.extended = fileMarker === 0xFFC1;
- frame.progressive = fileMarker === 0xFFC2;
- frame.precision = data[offset++];
- var sofScanLines = readUint16();
- frame.scanLines = dnlScanLines || sofScanLines;
- frame.samplesPerLine = readUint16();
- frame.components = [];
- frame.componentIds = {};
- var componentsCount = data[offset++],
- componentId;
- var maxH = 0,
- maxV = 0;
- for (i = 0; i < componentsCount; i++) {
- componentId = data[offset];
- var h = data[offset + 1] >> 4;
- var v = data[offset + 1] & 15;
- if (maxH < h) {
- maxH = h;
- }
- if (maxV < v) {
- maxV = v;
- }
- var qId = data[offset + 2];
- l = frame.components.push({
- h: h,
- v: v,
- quantizationId: qId,
- quantizationTable: null
- });
- frame.componentIds[componentId] = l - 1;
- offset += 3;
- }
- frame.maxH = maxH;
- frame.maxV = maxV;
- prepareComponents(frame);
- break;
- case 0xFFC4:
- var huffmanLength = readUint16();
- for (i = 2; i < huffmanLength;) {
- var huffmanTableSpec = data[offset++];
- var codeLengths = new Uint8Array(16);
- var codeLengthSum = 0;
- for (j = 0; j < 16; j++, offset++) {
- codeLengthSum += codeLengths[j] = data[offset];
- }
- var huffmanValues = new Uint8Array(codeLengthSum);
- for (j = 0; j < codeLengthSum; j++, offset++) {
- huffmanValues[j] = data[offset];
- }
- i += 17 + codeLengthSum;
- (huffmanTableSpec >> 4 === 0 ? huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] = buildHuffmanTable(codeLengths, huffmanValues);
- }
- break;
- case 0xFFDD:
- readUint16();
- resetInterval = readUint16();
- break;
- case 0xFFDA:
- var parseDNLMarker = ++numSOSMarkers === 1 && !dnlScanLines;
- readUint16();
- var selectorsCount = data[offset++];
- var components = [],
- component;
- for (i = 0; i < selectorsCount; i++) {
- var componentIndex = frame.componentIds[data[offset++]];
- component = frame.components[componentIndex];
- var tableSpec = data[offset++];
- component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];
- component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];
- components.push(component);
- }
- var spectralStart = data[offset++];
- var spectralEnd = data[offset++];
- var successiveApproximation = data[offset++];
- try {
- var processed = decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successiveApproximation >> 4, successiveApproximation & 15, parseDNLMarker);
- offset += processed;
- } catch (ex) {
- if (ex instanceof DNLMarkerError) {
- (0, _util.warn)(ex.message + ' -- attempting to re-parse the JPEG image.');
- return this.parse(data, { dnlScanLines: ex.scanLines });
- } else if (ex instanceof EOIMarkerError) {
- (0, _util.warn)(ex.message + ' -- ignoring the rest of the image data.');
- break markerLoop;
- }
- throw ex;
- }
- break;
- case 0xFFDC:
- offset += 4;
- break;
- case 0xFFFF:
- if (data[offset] !== 0xFF) {
- offset--;
- }
- break;
- default:
- if (data[offset - 3] === 0xFF && data[offset - 2] >= 0xC0 && data[offset - 2] <= 0xFE) {
- offset -= 3;
- break;
- }
- var nextFileMarker = findNextFileMarker(data, offset - 2);
- if (nextFileMarker && nextFileMarker.invalid) {
- (0, _util.warn)('JpegImage.parse - unexpected data, current marker is: ' + nextFileMarker.invalid);
- offset = nextFileMarker.offset;
- break;
- }
- throw new JpegError('unknown marker ' + fileMarker.toString(16));
- }
- fileMarker = readUint16();
- }
- this.width = frame.samplesPerLine;
- this.height = frame.scanLines;
- this.jfif = jfif;
- this.adobe = adobe;
- this.components = [];
- for (i = 0; i < frame.components.length; i++) {
- component = frame.components[i];
- var quantizationTable = quantizationTables[component.quantizationId];
- if (quantizationTable) {
- component.quantizationTable = quantizationTable;
- }
- this.components.push({
- output: buildComponentData(frame, component),
- scaleX: component.h / frame.maxH,
- scaleY: component.v / frame.maxV,
- blocksPerLine: component.blocksPerLine,
- blocksPerColumn: component.blocksPerColumn
- });
- }
- this.numComponents = this.components.length;
- },
- _getLinearizedBlockData: function _getLinearizedBlockData(width, height) {
- var isSourcePDF = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
-
- var scaleX = this.width / width,
- scaleY = this.height / height;
- var component, componentScaleX, componentScaleY, blocksPerScanline;
- var x, y, i, j, k;
- var index;
- var offset = 0;
- var output;
- var numComponents = this.components.length;
- var dataLength = width * height * numComponents;
- var data = new Uint8ClampedArray(dataLength);
- var xScaleBlockOffset = new Uint32Array(width);
- var mask3LSB = 0xfffffff8;
- for (i = 0; i < numComponents; i++) {
- component = this.components[i];
- componentScaleX = component.scaleX * scaleX;
- componentScaleY = component.scaleY * scaleY;
- offset = i;
- output = component.output;
- blocksPerScanline = component.blocksPerLine + 1 << 3;
- for (x = 0; x < width; x++) {
- j = 0 | x * componentScaleX;
- xScaleBlockOffset[x] = (j & mask3LSB) << 3 | j & 7;
- }
- for (y = 0; y < height; y++) {
- j = 0 | y * componentScaleY;
- index = blocksPerScanline * (j & mask3LSB) | (j & 7) << 3;
- for (x = 0; x < width; x++) {
- data[offset] = output[index + xScaleBlockOffset[x]];
- offset += numComponents;
- }
- }
- }
- var transform = this._decodeTransform;
- if (!isSourcePDF && numComponents === 4 && !transform) {
- transform = new Int32Array([-256, 255, -256, 255, -256, 255, -256, 255]);
- }
- if (transform) {
- for (i = 0; i < dataLength;) {
- for (j = 0, k = 0; j < numComponents; j++, i++, k += 2) {
- data[i] = (data[i] * transform[k] >> 8) + transform[k + 1];
- }
- }
- }
- return data;
- },
-
- get _isColorConversionNeeded() {
- if (this.adobe) {
- return !!this.adobe.transformCode;
- }
- if (this.numComponents === 3) {
- if (this._colorTransform === 0) {
- return false;
- }
- return true;
- }
- if (this._colorTransform === 1) {
- return true;
- }
- return false;
- },
- _convertYccToRgb: function convertYccToRgb(data) {
- var Y, Cb, Cr;
- for (var i = 0, length = data.length; i < length; i += 3) {
- Y = data[i];
- Cb = data[i + 1];
- Cr = data[i + 2];
- data[i] = Y - 179.456 + 1.402 * Cr;
- data[i + 1] = Y + 135.459 - 0.344 * Cb - 0.714 * Cr;
- data[i + 2] = Y - 226.816 + 1.772 * Cb;
- }
- return data;
- },
- _convertYcckToRgb: function convertYcckToRgb(data) {
- var Y, Cb, Cr, k;
- var offset = 0;
- for (var i = 0, length = data.length; i < length; i += 4) {
- Y = data[i];
- Cb = data[i + 1];
- Cr = data[i + 2];
- k = data[i + 3];
- data[offset++] = -122.67195406894 + Cb * (-6.60635669420364e-5 * Cb + 0.000437130475926232 * Cr - 5.4080610064599e-5 * Y + 0.00048449797120281 * k - 0.154362151871126) + Cr * (-0.000957964378445773 * Cr + 0.000817076911346625 * Y - 0.00477271405408747 * k + 1.53380253221734) + Y * (0.000961250184130688 * Y - 0.00266257332283933 * k + 0.48357088451265) + k * (-0.000336197177618394 * k + 0.484791561490776);
- data[offset++] = 107.268039397724 + Cb * (2.19927104525741e-5 * Cb - 0.000640992018297945 * Cr + 0.000659397001245577 * Y + 0.000426105652938837 * k - 0.176491792462875) + Cr * (-0.000778269941513683 * Cr + 0.00130872261408275 * Y + 0.000770482631801132 * k - 0.151051492775562) + Y * (0.00126935368114843 * Y - 0.00265090189010898 * k + 0.25802910206845) + k * (-0.000318913117588328 * k - 0.213742400323665);
- data[offset++] = -20.810012546947 + Cb * (-0.000570115196973677 * Cb - 2.63409051004589e-5 * Cr + 0.0020741088115012 * Y - 0.00288260236853442 * k + 0.814272968359295) + Cr * (-1.53496057440975e-5 * Cr - 0.000132689043961446 * Y + 0.000560833691242812 * k - 0.195152027534049) + Y * (0.00174418132927582 * Y - 0.00255243321439347 * k + 0.116935020465145) + k * (-0.000343531996510555 * k + 0.24165260232407);
- }
- return data.subarray(0, offset);
- },
- _convertYcckToCmyk: function convertYcckToCmyk(data) {
- var Y, Cb, Cr;
- for (var i = 0, length = data.length; i < length; i += 4) {
- Y = data[i];
- Cb = data[i + 1];
- Cr = data[i + 2];
- data[i] = 434.456 - Y - 1.402 * Cr;
- data[i + 1] = 119.541 - Y + 0.344 * Cb + 0.714 * Cr;
- data[i + 2] = 481.816 - Y - 1.772 * Cb;
- }
- return data;
- },
- _convertCmykToRgb: function convertCmykToRgb(data) {
- var c, m, y, k;
- var offset = 0;
- var scale = 1 / 255;
- for (var i = 0, length = data.length; i < length; i += 4) {
- c = data[i] * scale;
- m = data[i + 1] * scale;
- y = data[i + 2] * scale;
- k = data[i + 3] * scale;
- data[offset++] = 255 + c * (-4.387332384609988 * c + 54.48615194189176 * m + 18.82290502165302 * y + 212.25662451639585 * k - 285.2331026137004) + m * (1.7149763477362134 * m - 5.6096736904047315 * y - 17.873870861415444 * k - 5.497006427196366) + y * (-2.5217340131683033 * y - 21.248923337353073 * k + 17.5119270841813) - k * (21.86122147463605 * k + 189.48180835922747);
- data[offset++] = 255 + c * (8.841041422036149 * c + 60.118027045597366 * m + 6.871425592049007 * y + 31.159100130055922 * k - 79.2970844816548) + m * (-15.310361306967817 * m + 17.575251261109482 * y + 131.35250912493976 * k - 190.9453302588951) + y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) - k * (20.737325471181034 * k + 187.80453709719578);
- data[offset++] = 255 + c * (0.8842522430003296 * c + 8.078677503112928 * m + 30.89978309703729 * y - 0.23883238689178934 * k - 14.183576799673286) + m * (10.49593273432072 * m + 63.02378494754052 * y + 50.606957656360734 * k - 112.23884253719248) + y * (0.03296041114873217 * y + 115.60384449646641 * k - 193.58209356861505) - k * (22.33816807309886 * k + 180.12613974708367);
- }
- return data.subarray(0, offset);
- },
- getData: function getData(_ref3) {
- var width = _ref3.width,
- height = _ref3.height,
- _ref3$forceRGB = _ref3.forceRGB,
- forceRGB = _ref3$forceRGB === undefined ? false : _ref3$forceRGB,
- _ref3$isSourcePDF = _ref3.isSourcePDF,
- isSourcePDF = _ref3$isSourcePDF === undefined ? false : _ref3$isSourcePDF;
-
- if (this.numComponents > 4) {
- throw new JpegError('Unsupported color mode');
- }
- var data = this._getLinearizedBlockData(width, height, isSourcePDF);
- if (this.numComponents === 1 && forceRGB) {
- var dataLength = data.length;
- var rgbData = new Uint8ClampedArray(dataLength * 3);
- var offset = 0;
- for (var i = 0; i < dataLength; i++) {
- var grayColor = data[i];
- rgbData[offset++] = grayColor;
- rgbData[offset++] = grayColor;
- rgbData[offset++] = grayColor;
- }
- return rgbData;
- } else if (this.numComponents === 3 && this._isColorConversionNeeded) {
- return this._convertYccToRgb(data);
- } else if (this.numComponents === 4) {
- if (this._isColorConversionNeeded) {
- if (forceRGB) {
- return this._convertYcckToRgb(data);
- }
- return this._convertYcckToCmyk(data);
- } else if (forceRGB) {
- return this._convertCmykToRgb(data);
- }
- }
- return data;
- }
- };
- return JpegImage;
-}();
-exports.JpegImage = JpegImage;
-
-/***/ }),
-/* 148 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.JpxStream = undefined;
-
-var _stream = __w_pdfjs_require__(140);
-
-var _jpx = __w_pdfjs_require__(149);
-
-var _util = __w_pdfjs_require__(2);
-
-var JpxStream = function JpxStreamClosure() {
- function JpxStream(stream, maybeLength, dict, params) {
- this.stream = stream;
- this.maybeLength = maybeLength;
- this.dict = dict;
- this.params = params;
- _stream.DecodeStream.call(this, maybeLength);
- }
- JpxStream.prototype = Object.create(_stream.DecodeStream.prototype);
- Object.defineProperty(JpxStream.prototype, 'bytes', {
- get: function JpxStream_bytes() {
- return (0, _util.shadow)(this, 'bytes', this.stream.getBytes(this.maybeLength));
- },
- configurable: true
- });
- JpxStream.prototype.ensureBuffer = function (requested) {};
- JpxStream.prototype.readBlock = function () {
- if (this.eof) {
- return;
- }
- var jpxImage = new _jpx.JpxImage();
- jpxImage.parse(this.bytes);
- var width = jpxImage.width;
- var height = jpxImage.height;
- var componentsCount = jpxImage.componentsCount;
- var tileCount = jpxImage.tiles.length;
- if (tileCount === 1) {
- this.buffer = jpxImage.tiles[0].items;
- } else {
- var data = new Uint8ClampedArray(width * height * componentsCount);
- for (var k = 0; k < tileCount; k++) {
- var tileComponents = jpxImage.tiles[k];
- var tileWidth = tileComponents.width;
- var tileHeight = tileComponents.height;
- var tileLeft = tileComponents.left;
- var tileTop = tileComponents.top;
- var src = tileComponents.items;
- var srcPosition = 0;
- var dataPosition = (width * tileTop + tileLeft) * componentsCount;
- var imgRowSize = width * componentsCount;
- var tileRowSize = tileWidth * componentsCount;
- for (var j = 0; j < tileHeight; j++) {
- var rowBytes = src.subarray(srcPosition, srcPosition + tileRowSize);
- data.set(rowBytes, dataPosition);
- srcPosition += tileRowSize;
- dataPosition += imgRowSize;
- }
- }
- this.buffer = data;
- }
- this.bufferLength = this.buffer.length;
- this.eof = true;
- };
- return JpxStream;
-}();
-exports.JpxStream = JpxStream;
-
-/***/ }),
-/* 149 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.JpxImage = undefined;
-
-var _util = __w_pdfjs_require__(2);
-
-var _arithmetic_decoder = __w_pdfjs_require__(145);
-
-var JpxError = function JpxErrorClosure() {
- function JpxError(msg) {
- this.message = 'JPX error: ' + msg;
- }
- JpxError.prototype = new Error();
- JpxError.prototype.name = 'JpxError';
- JpxError.constructor = JpxError;
- return JpxError;
-}();
-var JpxImage = function JpxImageClosure() {
- var SubbandsGainLog2 = {
- 'LL': 0,
- 'LH': 1,
- 'HL': 1,
- 'HH': 2
- };
- function JpxImage() {
- this.failOnCorruptedImage = false;
- }
- JpxImage.prototype = {
- parse: function JpxImage_parse(data) {
- var head = (0, _util.readUint16)(data, 0);
- if (head === 0xFF4F) {
- this.parseCodestream(data, 0, data.length);
- return;
- }
- var position = 0,
- length = data.length;
- while (position < length) {
- var headerSize = 8;
- var lbox = (0, _util.readUint32)(data, position);
- var tbox = (0, _util.readUint32)(data, position + 4);
- position += headerSize;
- if (lbox === 1) {
- lbox = (0, _util.readUint32)(data, position) * 4294967296 + (0, _util.readUint32)(data, position + 4);
- position += 8;
- headerSize += 8;
- }
- if (lbox === 0) {
- lbox = length - position + headerSize;
- }
- if (lbox < headerSize) {
- throw new JpxError('Invalid box field size');
- }
- var dataLength = lbox - headerSize;
- var jumpDataLength = true;
- switch (tbox) {
- case 0x6A703268:
- jumpDataLength = false;
- break;
- case 0x636F6C72:
- var method = data[position];
- if (method === 1) {
- var colorspace = (0, _util.readUint32)(data, position + 3);
- switch (colorspace) {
- case 16:
- case 17:
- case 18:
- break;
- default:
- (0, _util.warn)('Unknown colorspace ' + colorspace);
- break;
- }
- } else if (method === 2) {
- (0, _util.info)('ICC profile not supported');
- }
- break;
- case 0x6A703263:
- this.parseCodestream(data, position, position + dataLength);
- break;
- case 0x6A502020:
- if ((0, _util.readUint32)(data, position) !== 0x0d0a870a) {
- (0, _util.warn)('Invalid JP2 signature');
- }
- break;
- case 0x6A501A1A:
- case 0x66747970:
- case 0x72726571:
- case 0x72657320:
- case 0x69686472:
- break;
- default:
- var headerType = String.fromCharCode(tbox >> 24 & 0xFF, tbox >> 16 & 0xFF, tbox >> 8 & 0xFF, tbox & 0xFF);
- (0, _util.warn)('Unsupported header type ' + tbox + ' (' + headerType + ')');
- break;
- }
- if (jumpDataLength) {
- position += dataLength;
- }
- }
- },
- parseImageProperties: function JpxImage_parseImageProperties(stream) {
- var newByte = stream.getByte();
- while (newByte >= 0) {
- var oldByte = newByte;
- newByte = stream.getByte();
- var code = oldByte << 8 | newByte;
- if (code === 0xFF51) {
- stream.skip(4);
- var Xsiz = stream.getInt32() >>> 0;
- var Ysiz = stream.getInt32() >>> 0;
- var XOsiz = stream.getInt32() >>> 0;
- var YOsiz = stream.getInt32() >>> 0;
- stream.skip(16);
- var Csiz = stream.getUint16();
- this.width = Xsiz - XOsiz;
- this.height = Ysiz - YOsiz;
- this.componentsCount = Csiz;
- this.bitsPerComponent = 8;
- return;
- }
- }
- throw new JpxError('No size marker found in JPX stream');
- },
- parseCodestream: function JpxImage_parseCodestream(data, start, end) {
- var context = {};
- var doNotRecover = false;
- try {
- var position = start;
- while (position + 1 < end) {
- var code = (0, _util.readUint16)(data, position);
- position += 2;
- var length = 0,
- j,
- sqcd,
- spqcds,
- spqcdSize,
- scalarExpounded,
- tile;
- switch (code) {
- case 0xFF4F:
- context.mainHeader = true;
- break;
- case 0xFFD9:
- break;
- case 0xFF51:
- length = (0, _util.readUint16)(data, position);
- var siz = {};
- siz.Xsiz = (0, _util.readUint32)(data, position + 4);
- siz.Ysiz = (0, _util.readUint32)(data, position + 8);
- siz.XOsiz = (0, _util.readUint32)(data, position + 12);
- siz.YOsiz = (0, _util.readUint32)(data, position + 16);
- siz.XTsiz = (0, _util.readUint32)(data, position + 20);
- siz.YTsiz = (0, _util.readUint32)(data, position + 24);
- siz.XTOsiz = (0, _util.readUint32)(data, position + 28);
- siz.YTOsiz = (0, _util.readUint32)(data, position + 32);
- var componentsCount = (0, _util.readUint16)(data, position + 36);
- siz.Csiz = componentsCount;
- var components = [];
- j = position + 38;
- for (var i = 0; i < componentsCount; i++) {
- var component = {
- precision: (data[j] & 0x7F) + 1,
- isSigned: !!(data[j] & 0x80),
- XRsiz: data[j + 1],
- YRsiz: data[j + 2]
- };
- j += 3;
- calculateComponentDimensions(component, siz);
- components.push(component);
- }
- context.SIZ = siz;
- context.components = components;
- calculateTileGrids(context, components);
- context.QCC = [];
- context.COC = [];
- break;
- case 0xFF5C:
- length = (0, _util.readUint16)(data, position);
- var qcd = {};
- j = position + 2;
- sqcd = data[j++];
- switch (sqcd & 0x1F) {
- case 0:
- spqcdSize = 8;
- scalarExpounded = true;
- break;
- case 1:
- spqcdSize = 16;
- scalarExpounded = false;
- break;
- case 2:
- spqcdSize = 16;
- scalarExpounded = true;
- break;
- default:
- throw new Error('Invalid SQcd value ' + sqcd);
- }
- qcd.noQuantization = spqcdSize === 8;
- qcd.scalarExpounded = scalarExpounded;
- qcd.guardBits = sqcd >> 5;
- spqcds = [];
- while (j < length + position) {
- var spqcd = {};
- if (spqcdSize === 8) {
- spqcd.epsilon = data[j++] >> 3;
- spqcd.mu = 0;
- } else {
- spqcd.epsilon = data[j] >> 3;
- spqcd.mu = (data[j] & 0x7) << 8 | data[j + 1];
- j += 2;
- }
- spqcds.push(spqcd);
- }
- qcd.SPqcds = spqcds;
- if (context.mainHeader) {
- context.QCD = qcd;
- } else {
- context.currentTile.QCD = qcd;
- context.currentTile.QCC = [];
- }
- break;
- case 0xFF5D:
- length = (0, _util.readUint16)(data, position);
- var qcc = {};
- j = position + 2;
- var cqcc;
- if (context.SIZ.Csiz < 257) {
- cqcc = data[j++];
- } else {
- cqcc = (0, _util.readUint16)(data, j);
- j += 2;
- }
- sqcd = data[j++];
- switch (sqcd & 0x1F) {
- case 0:
- spqcdSize = 8;
- scalarExpounded = true;
- break;
- case 1:
- spqcdSize = 16;
- scalarExpounded = false;
- break;
- case 2:
- spqcdSize = 16;
- scalarExpounded = true;
- break;
- default:
- throw new Error('Invalid SQcd value ' + sqcd);
- }
- qcc.noQuantization = spqcdSize === 8;
- qcc.scalarExpounded = scalarExpounded;
- qcc.guardBits = sqcd >> 5;
- spqcds = [];
- while (j < length + position) {
- spqcd = {};
- if (spqcdSize === 8) {
- spqcd.epsilon = data[j++] >> 3;
- spqcd.mu = 0;
- } else {
- spqcd.epsilon = data[j] >> 3;
- spqcd.mu = (data[j] & 0x7) << 8 | data[j + 1];
- j += 2;
- }
- spqcds.push(spqcd);
- }
- qcc.SPqcds = spqcds;
- if (context.mainHeader) {
- context.QCC[cqcc] = qcc;
- } else {
- context.currentTile.QCC[cqcc] = qcc;
- }
- break;
- case 0xFF52:
- length = (0, _util.readUint16)(data, position);
- var cod = {};
- j = position + 2;
- var scod = data[j++];
- cod.entropyCoderWithCustomPrecincts = !!(scod & 1);
- cod.sopMarkerUsed = !!(scod & 2);
- cod.ephMarkerUsed = !!(scod & 4);
- cod.progressionOrder = data[j++];
- cod.layersCount = (0, _util.readUint16)(data, j);
- j += 2;
- cod.multipleComponentTransform = data[j++];
- cod.decompositionLevelsCount = data[j++];
- cod.xcb = (data[j++] & 0xF) + 2;
- cod.ycb = (data[j++] & 0xF) + 2;
- var blockStyle = data[j++];
- cod.selectiveArithmeticCodingBypass = !!(blockStyle & 1);
- cod.resetContextProbabilities = !!(blockStyle & 2);
- cod.terminationOnEachCodingPass = !!(blockStyle & 4);
- cod.verticallyStripe = !!(blockStyle & 8);
- cod.predictableTermination = !!(blockStyle & 16);
- cod.segmentationSymbolUsed = !!(blockStyle & 32);
- cod.reversibleTransformation = data[j++];
- if (cod.entropyCoderWithCustomPrecincts) {
- var precinctsSizes = [];
- while (j < length + position) {
- var precinctsSize = data[j++];
- precinctsSizes.push({
- PPx: precinctsSize & 0xF,
- PPy: precinctsSize >> 4
- });
- }
- cod.precinctsSizes = precinctsSizes;
- }
- var unsupported = [];
- if (cod.selectiveArithmeticCodingBypass) {
- unsupported.push('selectiveArithmeticCodingBypass');
- }
- if (cod.resetContextProbabilities) {
- unsupported.push('resetContextProbabilities');
- }
- if (cod.terminationOnEachCodingPass) {
- unsupported.push('terminationOnEachCodingPass');
- }
- if (cod.verticallyStripe) {
- unsupported.push('verticallyStripe');
- }
- if (cod.predictableTermination) {
- unsupported.push('predictableTermination');
- }
- if (unsupported.length > 0) {
- doNotRecover = true;
- throw new Error('Unsupported COD options (' + unsupported.join(', ') + ')');
- }
- if (context.mainHeader) {
- context.COD = cod;
- } else {
- context.currentTile.COD = cod;
- context.currentTile.COC = [];
- }
- break;
- case 0xFF90:
- length = (0, _util.readUint16)(data, position);
- tile = {};
- tile.index = (0, _util.readUint16)(data, position + 2);
- tile.length = (0, _util.readUint32)(data, position + 4);
- tile.dataEnd = tile.length + position - 2;
- tile.partIndex = data[position + 8];
- tile.partsCount = data[position + 9];
- context.mainHeader = false;
- if (tile.partIndex === 0) {
- tile.COD = context.COD;
- tile.COC = context.COC.slice(0);
- tile.QCD = context.QCD;
- tile.QCC = context.QCC.slice(0);
- }
- context.currentTile = tile;
- break;
- case 0xFF93:
- tile = context.currentTile;
- if (tile.partIndex === 0) {
- initializeTile(context, tile.index);
- buildPackets(context);
- }
- length = tile.dataEnd - position;
- parseTilePackets(context, data, position, length);
- break;
- case 0xFF55:
- case 0xFF57:
- case 0xFF58:
- case 0xFF64:
- length = (0, _util.readUint16)(data, position);
- break;
- case 0xFF53:
- throw new Error('Codestream code 0xFF53 (COC) is ' + 'not implemented');
- default:
- throw new Error('Unknown codestream code: ' + code.toString(16));
- }
- position += length;
- }
- } catch (e) {
- if (doNotRecover || this.failOnCorruptedImage) {
- throw new JpxError(e.message);
- } else {
- (0, _util.warn)('JPX: Trying to recover from: ' + e.message);
- }
- }
- this.tiles = transformComponents(context);
- this.width = context.SIZ.Xsiz - context.SIZ.XOsiz;
- this.height = context.SIZ.Ysiz - context.SIZ.YOsiz;
- this.componentsCount = context.SIZ.Csiz;
- }
- };
- function calculateComponentDimensions(component, siz) {
- component.x0 = Math.ceil(siz.XOsiz / component.XRsiz);
- component.x1 = Math.ceil(siz.Xsiz / component.XRsiz);
- component.y0 = Math.ceil(siz.YOsiz / component.YRsiz);
- component.y1 = Math.ceil(siz.Ysiz / component.YRsiz);
- component.width = component.x1 - component.x0;
- component.height = component.y1 - component.y0;
- }
- function calculateTileGrids(context, components) {
- var siz = context.SIZ;
- var tile,
- tiles = [];
- var numXtiles = Math.ceil((siz.Xsiz - siz.XTOsiz) / siz.XTsiz);
- var numYtiles = Math.ceil((siz.Ysiz - siz.YTOsiz) / siz.YTsiz);
- for (var q = 0; q < numYtiles; q++) {
- for (var p = 0; p < numXtiles; p++) {
- tile = {};
- tile.tx0 = Math.max(siz.XTOsiz + p * siz.XTsiz, siz.XOsiz);
- tile.ty0 = Math.max(siz.YTOsiz + q * siz.YTsiz, siz.YOsiz);
- tile.tx1 = Math.min(siz.XTOsiz + (p + 1) * siz.XTsiz, siz.Xsiz);
- tile.ty1 = Math.min(siz.YTOsiz + (q + 1) * siz.YTsiz, siz.Ysiz);
- tile.width = tile.tx1 - tile.tx0;
- tile.height = tile.ty1 - tile.ty0;
- tile.components = [];
- tiles.push(tile);
- }
- }
- context.tiles = tiles;
- var componentsCount = siz.Csiz;
- for (var i = 0, ii = componentsCount; i < ii; i++) {
- var component = components[i];
- for (var j = 0, jj = tiles.length; j < jj; j++) {
- var tileComponent = {};
- tile = tiles[j];
- tileComponent.tcx0 = Math.ceil(tile.tx0 / component.XRsiz);
- tileComponent.tcy0 = Math.ceil(tile.ty0 / component.YRsiz);
- tileComponent.tcx1 = Math.ceil(tile.tx1 / component.XRsiz);
- tileComponent.tcy1 = Math.ceil(tile.ty1 / component.YRsiz);
- tileComponent.width = tileComponent.tcx1 - tileComponent.tcx0;
- tileComponent.height = tileComponent.tcy1 - tileComponent.tcy0;
- tile.components[i] = tileComponent;
- }
- }
- }
- function getBlocksDimensions(context, component, r) {
- var codOrCoc = component.codingStyleParameters;
- var result = {};
- if (!codOrCoc.entropyCoderWithCustomPrecincts) {
- result.PPx = 15;
- result.PPy = 15;
- } else {
- result.PPx = codOrCoc.precinctsSizes[r].PPx;
- result.PPy = codOrCoc.precinctsSizes[r].PPy;
- }
- result.xcb_ = r > 0 ? Math.min(codOrCoc.xcb, result.PPx - 1) : Math.min(codOrCoc.xcb, result.PPx);
- result.ycb_ = r > 0 ? Math.min(codOrCoc.ycb, result.PPy - 1) : Math.min(codOrCoc.ycb, result.PPy);
- return result;
- }
- function buildPrecincts(context, resolution, dimensions) {
- var precinctWidth = 1 << dimensions.PPx;
- var precinctHeight = 1 << dimensions.PPy;
- var isZeroRes = resolution.resLevel === 0;
- var precinctWidthInSubband = 1 << dimensions.PPx + (isZeroRes ? 0 : -1);
- var precinctHeightInSubband = 1 << dimensions.PPy + (isZeroRes ? 0 : -1);
- var numprecinctswide = resolution.trx1 > resolution.trx0 ? Math.ceil(resolution.trx1 / precinctWidth) - Math.floor(resolution.trx0 / precinctWidth) : 0;
- var numprecinctshigh = resolution.try1 > resolution.try0 ? Math.ceil(resolution.try1 / precinctHeight) - Math.floor(resolution.try0 / precinctHeight) : 0;
- var numprecincts = numprecinctswide * numprecinctshigh;
- resolution.precinctParameters = {
- precinctWidth: precinctWidth,
- precinctHeight: precinctHeight,
- numprecinctswide: numprecinctswide,
- numprecinctshigh: numprecinctshigh,
- numprecincts: numprecincts,
- precinctWidthInSubband: precinctWidthInSubband,
- precinctHeightInSubband: precinctHeightInSubband
- };
- }
- function buildCodeblocks(context, subband, dimensions) {
- var xcb_ = dimensions.xcb_;
- var ycb_ = dimensions.ycb_;
- var codeblockWidth = 1 << xcb_;
- var codeblockHeight = 1 << ycb_;
- var cbx0 = subband.tbx0 >> xcb_;
- var cby0 = subband.tby0 >> ycb_;
- var cbx1 = subband.tbx1 + codeblockWidth - 1 >> xcb_;
- var cby1 = subband.tby1 + codeblockHeight - 1 >> ycb_;
- var precinctParameters = subband.resolution.precinctParameters;
- var codeblocks = [];
- var precincts = [];
- var i, j, codeblock, precinctNumber;
- for (j = cby0; j < cby1; j++) {
- for (i = cbx0; i < cbx1; i++) {
- codeblock = {
- cbx: i,
- cby: j,
- tbx0: codeblockWidth * i,
- tby0: codeblockHeight * j,
- tbx1: codeblockWidth * (i + 1),
- tby1: codeblockHeight * (j + 1)
- };
- codeblock.tbx0_ = Math.max(subband.tbx0, codeblock.tbx0);
- codeblock.tby0_ = Math.max(subband.tby0, codeblock.tby0);
- codeblock.tbx1_ = Math.min(subband.tbx1, codeblock.tbx1);
- codeblock.tby1_ = Math.min(subband.tby1, codeblock.tby1);
- var pi = Math.floor((codeblock.tbx0_ - subband.tbx0) / precinctParameters.precinctWidthInSubband);
- var pj = Math.floor((codeblock.tby0_ - subband.tby0) / precinctParameters.precinctHeightInSubband);
- precinctNumber = pi + pj * precinctParameters.numprecinctswide;
- codeblock.precinctNumber = precinctNumber;
- codeblock.subbandType = subband.type;
- codeblock.Lblock = 3;
- if (codeblock.tbx1_ <= codeblock.tbx0_ || codeblock.tby1_ <= codeblock.tby0_) {
- continue;
- }
- codeblocks.push(codeblock);
- var precinct = precincts[precinctNumber];
- if (precinct !== undefined) {
- if (i < precinct.cbxMin) {
- precinct.cbxMin = i;
- } else if (i > precinct.cbxMax) {
- precinct.cbxMax = i;
- }
- if (j < precinct.cbyMin) {
- precinct.cbxMin = j;
- } else if (j > precinct.cbyMax) {
- precinct.cbyMax = j;
- }
- } else {
- precincts[precinctNumber] = precinct = {
- cbxMin: i,
- cbyMin: j,
- cbxMax: i,
- cbyMax: j
- };
- }
- codeblock.precinct = precinct;
- }
- }
- subband.codeblockParameters = {
- codeblockWidth: xcb_,
- codeblockHeight: ycb_,
- numcodeblockwide: cbx1 - cbx0 + 1,
- numcodeblockhigh: cby1 - cby0 + 1
- };
- subband.codeblocks = codeblocks;
- subband.precincts = precincts;
- }
- function createPacket(resolution, precinctNumber, layerNumber) {
- var precinctCodeblocks = [];
- var subbands = resolution.subbands;
- for (var i = 0, ii = subbands.length; i < ii; i++) {
- var subband = subbands[i];
- var codeblocks = subband.codeblocks;
- for (var j = 0, jj = codeblocks.length; j < jj; j++) {
- var codeblock = codeblocks[j];
- if (codeblock.precinctNumber !== precinctNumber) {
- continue;
- }
- precinctCodeblocks.push(codeblock);
- }
- }
- return {
- layerNumber: layerNumber,
- codeblocks: precinctCodeblocks
- };
- }
- function LayerResolutionComponentPositionIterator(context) {
- var siz = context.SIZ;
- var tileIndex = context.currentTile.index;
- var tile = context.tiles[tileIndex];
- var layersCount = tile.codingStyleDefaultParameters.layersCount;
- var componentsCount = siz.Csiz;
- var maxDecompositionLevelsCount = 0;
- for (var q = 0; q < componentsCount; q++) {
- maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, tile.components[q].codingStyleParameters.decompositionLevelsCount);
- }
- var l = 0,
- r = 0,
- i = 0,
- k = 0;
- this.nextPacket = function JpxImage_nextPacket() {
- for (; l < layersCount; l++) {
- for (; r <= maxDecompositionLevelsCount; r++) {
- for (; i < componentsCount; i++) {
- var component = tile.components[i];
- if (r > component.codingStyleParameters.decompositionLevelsCount) {
- continue;
- }
- var resolution = component.resolutions[r];
- var numprecincts = resolution.precinctParameters.numprecincts;
- for (; k < numprecincts;) {
- var packet = createPacket(resolution, k, l);
- k++;
- return packet;
- }
- k = 0;
- }
- i = 0;
- }
- r = 0;
- }
- throw new JpxError('Out of packets');
- };
- }
- function ResolutionLayerComponentPositionIterator(context) {
- var siz = context.SIZ;
- var tileIndex = context.currentTile.index;
- var tile = context.tiles[tileIndex];
- var layersCount = tile.codingStyleDefaultParameters.layersCount;
- var componentsCount = siz.Csiz;
- var maxDecompositionLevelsCount = 0;
- for (var q = 0; q < componentsCount; q++) {
- maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, tile.components[q].codingStyleParameters.decompositionLevelsCount);
- }
- var r = 0,
- l = 0,
- i = 0,
- k = 0;
- this.nextPacket = function JpxImage_nextPacket() {
- for (; r <= maxDecompositionLevelsCount; r++) {
- for (; l < layersCount; l++) {
- for (; i < componentsCount; i++) {
- var component = tile.components[i];
- if (r > component.codingStyleParameters.decompositionLevelsCount) {
- continue;
- }
- var resolution = component.resolutions[r];
- var numprecincts = resolution.precinctParameters.numprecincts;
- for (; k < numprecincts;) {
- var packet = createPacket(resolution, k, l);
- k++;
- return packet;
- }
- k = 0;
- }
- i = 0;
- }
- l = 0;
- }
- throw new JpxError('Out of packets');
- };
- }
- function ResolutionPositionComponentLayerIterator(context) {
- var siz = context.SIZ;
- var tileIndex = context.currentTile.index;
- var tile = context.tiles[tileIndex];
- var layersCount = tile.codingStyleDefaultParameters.layersCount;
- var componentsCount = siz.Csiz;
- var l, r, c, p;
- var maxDecompositionLevelsCount = 0;
- for (c = 0; c < componentsCount; c++) {
- var component = tile.components[c];
- maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, component.codingStyleParameters.decompositionLevelsCount);
- }
- var maxNumPrecinctsInLevel = new Int32Array(maxDecompositionLevelsCount + 1);
- for (r = 0; r <= maxDecompositionLevelsCount; ++r) {
- var maxNumPrecincts = 0;
- for (c = 0; c < componentsCount; ++c) {
- var resolutions = tile.components[c].resolutions;
- if (r < resolutions.length) {
- maxNumPrecincts = Math.max(maxNumPrecincts, resolutions[r].precinctParameters.numprecincts);
- }
- }
- maxNumPrecinctsInLevel[r] = maxNumPrecincts;
- }
- l = 0;
- r = 0;
- c = 0;
- p = 0;
- this.nextPacket = function JpxImage_nextPacket() {
- for (; r <= maxDecompositionLevelsCount; r++) {
- for (; p < maxNumPrecinctsInLevel[r]; p++) {
- for (; c < componentsCount; c++) {
- var component = tile.components[c];
- if (r > component.codingStyleParameters.decompositionLevelsCount) {
- continue;
- }
- var resolution = component.resolutions[r];
- var numprecincts = resolution.precinctParameters.numprecincts;
- if (p >= numprecincts) {
- continue;
- }
- for (; l < layersCount;) {
- var packet = createPacket(resolution, p, l);
- l++;
- return packet;
- }
- l = 0;
- }
- c = 0;
- }
- p = 0;
- }
- throw new JpxError('Out of packets');
- };
- }
- function PositionComponentResolutionLayerIterator(context) {
- var siz = context.SIZ;
- var tileIndex = context.currentTile.index;
- var tile = context.tiles[tileIndex];
- var layersCount = tile.codingStyleDefaultParameters.layersCount;
- var componentsCount = siz.Csiz;
- var precinctsSizes = getPrecinctSizesInImageScale(tile);
- var precinctsIterationSizes = precinctsSizes;
- var l = 0,
- r = 0,
- c = 0,
- px = 0,
- py = 0;
- this.nextPacket = function JpxImage_nextPacket() {
- for (; py < precinctsIterationSizes.maxNumHigh; py++) {
- for (; px < precinctsIterationSizes.maxNumWide; px++) {
- for (; c < componentsCount; c++) {
- var component = tile.components[c];
- var decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount;
- for (; r <= decompositionLevelsCount; r++) {
- var resolution = component.resolutions[r];
- var sizeInImageScale = precinctsSizes.components[c].resolutions[r];
- var k = getPrecinctIndexIfExist(px, py, sizeInImageScale, precinctsIterationSizes, resolution);
- if (k === null) {
- continue;
- }
- for (; l < layersCount;) {
- var packet = createPacket(resolution, k, l);
- l++;
- return packet;
- }
- l = 0;
- }
- r = 0;
- }
- c = 0;
- }
- px = 0;
- }
- throw new JpxError('Out of packets');
- };
- }
- function ComponentPositionResolutionLayerIterator(context) {
- var siz = context.SIZ;
- var tileIndex = context.currentTile.index;
- var tile = context.tiles[tileIndex];
- var layersCount = tile.codingStyleDefaultParameters.layersCount;
- var componentsCount = siz.Csiz;
- var precinctsSizes = getPrecinctSizesInImageScale(tile);
- var l = 0,
- r = 0,
- c = 0,
- px = 0,
- py = 0;
- this.nextPacket = function JpxImage_nextPacket() {
- for (; c < componentsCount; ++c) {
- var component = tile.components[c];
- var precinctsIterationSizes = precinctsSizes.components[c];
- var decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount;
- for (; py < precinctsIterationSizes.maxNumHigh; py++) {
- for (; px < precinctsIterationSizes.maxNumWide; px++) {
- for (; r <= decompositionLevelsCount; r++) {
- var resolution = component.resolutions[r];
- var sizeInImageScale = precinctsIterationSizes.resolutions[r];
- var k = getPrecinctIndexIfExist(px, py, sizeInImageScale, precinctsIterationSizes, resolution);
- if (k === null) {
- continue;
- }
- for (; l < layersCount;) {
- var packet = createPacket(resolution, k, l);
- l++;
- return packet;
- }
- l = 0;
- }
- r = 0;
- }
- px = 0;
- }
- py = 0;
- }
- throw new JpxError('Out of packets');
- };
- }
- function getPrecinctIndexIfExist(pxIndex, pyIndex, sizeInImageScale, precinctIterationSizes, resolution) {
- var posX = pxIndex * precinctIterationSizes.minWidth;
- var posY = pyIndex * precinctIterationSizes.minHeight;
- if (posX % sizeInImageScale.width !== 0 || posY % sizeInImageScale.height !== 0) {
- return null;
- }
- var startPrecinctRowIndex = posY / sizeInImageScale.width * resolution.precinctParameters.numprecinctswide;
- return posX / sizeInImageScale.height + startPrecinctRowIndex;
- }
- function getPrecinctSizesInImageScale(tile) {
- var componentsCount = tile.components.length;
- var minWidth = Number.MAX_VALUE;
- var minHeight = Number.MAX_VALUE;
- var maxNumWide = 0;
- var maxNumHigh = 0;
- var sizePerComponent = new Array(componentsCount);
- for (var c = 0; c < componentsCount; c++) {
- var component = tile.components[c];
- var decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount;
- var sizePerResolution = new Array(decompositionLevelsCount + 1);
- var minWidthCurrentComponent = Number.MAX_VALUE;
- var minHeightCurrentComponent = Number.MAX_VALUE;
- var maxNumWideCurrentComponent = 0;
- var maxNumHighCurrentComponent = 0;
- var scale = 1;
- for (var r = decompositionLevelsCount; r >= 0; --r) {
- var resolution = component.resolutions[r];
- var widthCurrentResolution = scale * resolution.precinctParameters.precinctWidth;
- var heightCurrentResolution = scale * resolution.precinctParameters.precinctHeight;
- minWidthCurrentComponent = Math.min(minWidthCurrentComponent, widthCurrentResolution);
- minHeightCurrentComponent = Math.min(minHeightCurrentComponent, heightCurrentResolution);
- maxNumWideCurrentComponent = Math.max(maxNumWideCurrentComponent, resolution.precinctParameters.numprecinctswide);
- maxNumHighCurrentComponent = Math.max(maxNumHighCurrentComponent, resolution.precinctParameters.numprecinctshigh);
- sizePerResolution[r] = {
- width: widthCurrentResolution,
- height: heightCurrentResolution
- };
- scale <<= 1;
- }
- minWidth = Math.min(minWidth, minWidthCurrentComponent);
- minHeight = Math.min(minHeight, minHeightCurrentComponent);
- maxNumWide = Math.max(maxNumWide, maxNumWideCurrentComponent);
- maxNumHigh = Math.max(maxNumHigh, maxNumHighCurrentComponent);
- sizePerComponent[c] = {
- resolutions: sizePerResolution,
- minWidth: minWidthCurrentComponent,
- minHeight: minHeightCurrentComponent,
- maxNumWide: maxNumWideCurrentComponent,
- maxNumHigh: maxNumHighCurrentComponent
- };
- }
- return {
- components: sizePerComponent,
- minWidth: minWidth,
- minHeight: minHeight,
- maxNumWide: maxNumWide,
- maxNumHigh: maxNumHigh
- };
- }
- function buildPackets(context) {
- var siz = context.SIZ;
- var tileIndex = context.currentTile.index;
- var tile = context.tiles[tileIndex];
- var componentsCount = siz.Csiz;
- for (var c = 0; c < componentsCount; c++) {
- var component = tile.components[c];
- var decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount;
- var resolutions = [];
- var subbands = [];
- for (var r = 0; r <= decompositionLevelsCount; r++) {
- var blocksDimensions = getBlocksDimensions(context, component, r);
- var resolution = {};
- var scale = 1 << decompositionLevelsCount - r;
- resolution.trx0 = Math.ceil(component.tcx0 / scale);
- resolution.try0 = Math.ceil(component.tcy0 / scale);
- resolution.trx1 = Math.ceil(component.tcx1 / scale);
- resolution.try1 = Math.ceil(component.tcy1 / scale);
- resolution.resLevel = r;
- buildPrecincts(context, resolution, blocksDimensions);
- resolutions.push(resolution);
- var subband;
- if (r === 0) {
- subband = {};
- subband.type = 'LL';
- subband.tbx0 = Math.ceil(component.tcx0 / scale);
- subband.tby0 = Math.ceil(component.tcy0 / scale);
- subband.tbx1 = Math.ceil(component.tcx1 / scale);
- subband.tby1 = Math.ceil(component.tcy1 / scale);
- subband.resolution = resolution;
- buildCodeblocks(context, subband, blocksDimensions);
- subbands.push(subband);
- resolution.subbands = [subband];
- } else {
- var bscale = 1 << decompositionLevelsCount - r + 1;
- var resolutionSubbands = [];
- subband = {};
- subband.type = 'HL';
- subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5);
- subband.tby0 = Math.ceil(component.tcy0 / bscale);
- subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5);
- subband.tby1 = Math.ceil(component.tcy1 / bscale);
- subband.resolution = resolution;
- buildCodeblocks(context, subband, blocksDimensions);
- subbands.push(subband);
- resolutionSubbands.push(subband);
- subband = {};
- subband.type = 'LH';
- subband.tbx0 = Math.ceil(component.tcx0 / bscale);
- subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5);
- subband.tbx1 = Math.ceil(component.tcx1 / bscale);
- subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5);
- subband.resolution = resolution;
- buildCodeblocks(context, subband, blocksDimensions);
- subbands.push(subband);
- resolutionSubbands.push(subband);
- subband = {};
- subband.type = 'HH';
- subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5);
- subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5);
- subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5);
- subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5);
- subband.resolution = resolution;
- buildCodeblocks(context, subband, blocksDimensions);
- subbands.push(subband);
- resolutionSubbands.push(subband);
- resolution.subbands = resolutionSubbands;
- }
- }
- component.resolutions = resolutions;
- component.subbands = subbands;
- }
- var progressionOrder = tile.codingStyleDefaultParameters.progressionOrder;
- switch (progressionOrder) {
- case 0:
- tile.packetsIterator = new LayerResolutionComponentPositionIterator(context);
- break;
- case 1:
- tile.packetsIterator = new ResolutionLayerComponentPositionIterator(context);
- break;
- case 2:
- tile.packetsIterator = new ResolutionPositionComponentLayerIterator(context);
- break;
- case 3:
- tile.packetsIterator = new PositionComponentResolutionLayerIterator(context);
- break;
- case 4:
- tile.packetsIterator = new ComponentPositionResolutionLayerIterator(context);
- break;
- default:
- throw new JpxError('Unsupported progression order ' + progressionOrder);
- }
- }
- function parseTilePackets(context, data, offset, dataLength) {
- var position = 0;
- var buffer,
- bufferSize = 0,
- skipNextBit = false;
- function readBits(count) {
- while (bufferSize < count) {
- var b = data[offset + position];
- position++;
- if (skipNextBit) {
- buffer = buffer << 7 | b;
- bufferSize += 7;
- skipNextBit = false;
- } else {
- buffer = buffer << 8 | b;
- bufferSize += 8;
- }
- if (b === 0xFF) {
- skipNextBit = true;
- }
- }
- bufferSize -= count;
- return buffer >>> bufferSize & (1 << count) - 1;
- }
- function skipMarkerIfEqual(value) {
- if (data[offset + position - 1] === 0xFF && data[offset + position] === value) {
- skipBytes(1);
- return true;
- } else if (data[offset + position] === 0xFF && data[offset + position + 1] === value) {
- skipBytes(2);
- return true;
- }
- return false;
- }
- function skipBytes(count) {
- position += count;
- }
- function alignToByte() {
- bufferSize = 0;
- if (skipNextBit) {
- position++;
- skipNextBit = false;
- }
- }
- function readCodingpasses() {
- if (readBits(1) === 0) {
- return 1;
- }
- if (readBits(1) === 0) {
- return 2;
- }
- var value = readBits(2);
- if (value < 3) {
- return value + 3;
- }
- value = readBits(5);
- if (value < 31) {
- return value + 6;
- }
- value = readBits(7);
- return value + 37;
- }
- var tileIndex = context.currentTile.index;
- var tile = context.tiles[tileIndex];
- var sopMarkerUsed = context.COD.sopMarkerUsed;
- var ephMarkerUsed = context.COD.ephMarkerUsed;
- var packetsIterator = tile.packetsIterator;
- while (position < dataLength) {
- alignToByte();
- if (sopMarkerUsed && skipMarkerIfEqual(0x91)) {
- skipBytes(4);
- }
- var packet = packetsIterator.nextPacket();
- if (!readBits(1)) {
- continue;
- }
- var layerNumber = packet.layerNumber;
- var queue = [],
- codeblock;
- for (var i = 0, ii = packet.codeblocks.length; i < ii; i++) {
- codeblock = packet.codeblocks[i];
- var precinct = codeblock.precinct;
- var codeblockColumn = codeblock.cbx - precinct.cbxMin;
- var codeblockRow = codeblock.cby - precinct.cbyMin;
- var codeblockIncluded = false;
- var firstTimeInclusion = false;
- var valueReady;
- if (codeblock['included'] !== undefined) {
- codeblockIncluded = !!readBits(1);
- } else {
- precinct = codeblock.precinct;
- var inclusionTree, zeroBitPlanesTree;
- if (precinct['inclusionTree'] !== undefined) {
- inclusionTree = precinct.inclusionTree;
- } else {
- var width = precinct.cbxMax - precinct.cbxMin + 1;
- var height = precinct.cbyMax - precinct.cbyMin + 1;
- inclusionTree = new InclusionTree(width, height, layerNumber);
- zeroBitPlanesTree = new TagTree(width, height);
- precinct.inclusionTree = inclusionTree;
- precinct.zeroBitPlanesTree = zeroBitPlanesTree;
- }
- if (inclusionTree.reset(codeblockColumn, codeblockRow, layerNumber)) {
- while (true) {
- if (readBits(1)) {
- valueReady = !inclusionTree.nextLevel();
- if (valueReady) {
- codeblock.included = true;
- codeblockIncluded = firstTimeInclusion = true;
- break;
- }
- } else {
- inclusionTree.incrementValue(layerNumber);
- break;
- }
- }
- }
- }
- if (!codeblockIncluded) {
- continue;
- }
- if (firstTimeInclusion) {
- zeroBitPlanesTree = precinct.zeroBitPlanesTree;
- zeroBitPlanesTree.reset(codeblockColumn, codeblockRow);
- while (true) {
- if (readBits(1)) {
- valueReady = !zeroBitPlanesTree.nextLevel();
- if (valueReady) {
- break;
- }
- } else {
- zeroBitPlanesTree.incrementValue();
- }
- }
- codeblock.zeroBitPlanes = zeroBitPlanesTree.value;
- }
- var codingpasses = readCodingpasses();
- while (readBits(1)) {
- codeblock.Lblock++;
- }
- var codingpassesLog2 = (0, _util.log2)(codingpasses);
- var bits = (codingpasses < 1 << codingpassesLog2 ? codingpassesLog2 - 1 : codingpassesLog2) + codeblock.Lblock;
- var codedDataLength = readBits(bits);
- queue.push({
- codeblock: codeblock,
- codingpasses: codingpasses,
- dataLength: codedDataLength
- });
- }
- alignToByte();
- if (ephMarkerUsed) {
- skipMarkerIfEqual(0x92);
- }
- while (queue.length > 0) {
- var packetItem = queue.shift();
- codeblock = packetItem.codeblock;
- if (codeblock['data'] === undefined) {
- codeblock.data = [];
- }
- codeblock.data.push({
- data: data,
- start: offset + position,
- end: offset + position + packetItem.dataLength,
- codingpasses: packetItem.codingpasses
- });
- position += packetItem.dataLength;
- }
- }
- return position;
- }
- function copyCoefficients(coefficients, levelWidth, levelHeight, subband, delta, mb, reversible, segmentationSymbolUsed) {
- var x0 = subband.tbx0;
- var y0 = subband.tby0;
- var width = subband.tbx1 - subband.tbx0;
- var codeblocks = subband.codeblocks;
- var right = subband.type.charAt(0) === 'H' ? 1 : 0;
- var bottom = subband.type.charAt(1) === 'H' ? levelWidth : 0;
- for (var i = 0, ii = codeblocks.length; i < ii; ++i) {
- var codeblock = codeblocks[i];
- var blockWidth = codeblock.tbx1_ - codeblock.tbx0_;
- var blockHeight = codeblock.tby1_ - codeblock.tby0_;
- if (blockWidth === 0 || blockHeight === 0) {
- continue;
- }
- if (codeblock['data'] === undefined) {
- continue;
- }
- var bitModel, currentCodingpassType;
- bitModel = new BitModel(blockWidth, blockHeight, codeblock.subbandType, codeblock.zeroBitPlanes, mb);
- currentCodingpassType = 2;
- var data = codeblock.data,
- totalLength = 0,
- codingpasses = 0;
- var j, jj, dataItem;
- for (j = 0, jj = data.length; j < jj; j++) {
- dataItem = data[j];
- totalLength += dataItem.end - dataItem.start;
- codingpasses += dataItem.codingpasses;
- }
- var encodedData = new Uint8Array(totalLength);
- var position = 0;
- for (j = 0, jj = data.length; j < jj; j++) {
- dataItem = data[j];
- var chunk = dataItem.data.subarray(dataItem.start, dataItem.end);
- encodedData.set(chunk, position);
- position += chunk.length;
- }
- var decoder = new _arithmetic_decoder.ArithmeticDecoder(encodedData, 0, totalLength);
- bitModel.setDecoder(decoder);
- for (j = 0; j < codingpasses; j++) {
- switch (currentCodingpassType) {
- case 0:
- bitModel.runSignificancePropagationPass();
- break;
- case 1:
- bitModel.runMagnitudeRefinementPass();
- break;
- case 2:
- bitModel.runCleanupPass();
- if (segmentationSymbolUsed) {
- bitModel.checkSegmentationSymbol();
- }
- break;
- }
- currentCodingpassType = (currentCodingpassType + 1) % 3;
- }
- var offset = codeblock.tbx0_ - x0 + (codeblock.tby0_ - y0) * width;
- var sign = bitModel.coefficentsSign;
- var magnitude = bitModel.coefficentsMagnitude;
- var bitsDecoded = bitModel.bitsDecoded;
- var magnitudeCorrection = reversible ? 0 : 0.5;
- var k, n, nb;
- position = 0;
- var interleave = subband.type !== 'LL';
- for (j = 0; j < blockHeight; j++) {
- var row = offset / width | 0;
- var levelOffset = 2 * row * (levelWidth - width) + right + bottom;
- for (k = 0; k < blockWidth; k++) {
- n = magnitude[position];
- if (n !== 0) {
- n = (n + magnitudeCorrection) * delta;
- if (sign[position] !== 0) {
- n = -n;
- }
- nb = bitsDecoded[position];
- var pos = interleave ? levelOffset + (offset << 1) : offset;
- if (reversible && nb >= mb) {
- coefficients[pos] = n;
- } else {
- coefficients[pos] = n * (1 << mb - nb);
- }
- }
- offset++;
- position++;
- }
- offset += width - blockWidth;
- }
- }
- }
- function transformTile(context, tile, c) {
- var component = tile.components[c];
- var codingStyleParameters = component.codingStyleParameters;
- var quantizationParameters = component.quantizationParameters;
- var decompositionLevelsCount = codingStyleParameters.decompositionLevelsCount;
- var spqcds = quantizationParameters.SPqcds;
- var scalarExpounded = quantizationParameters.scalarExpounded;
- var guardBits = quantizationParameters.guardBits;
- var segmentationSymbolUsed = codingStyleParameters.segmentationSymbolUsed;
- var precision = context.components[c].precision;
- var reversible = codingStyleParameters.reversibleTransformation;
- var transform = reversible ? new ReversibleTransform() : new IrreversibleTransform();
- var subbandCoefficients = [];
- var b = 0;
- for (var i = 0; i <= decompositionLevelsCount; i++) {
- var resolution = component.resolutions[i];
- var width = resolution.trx1 - resolution.trx0;
- var height = resolution.try1 - resolution.try0;
- var coefficients = new Float32Array(width * height);
- for (var j = 0, jj = resolution.subbands.length; j < jj; j++) {
- var mu, epsilon;
- if (!scalarExpounded) {
- mu = spqcds[0].mu;
- epsilon = spqcds[0].epsilon + (i > 0 ? 1 - i : 0);
- } else {
- mu = spqcds[b].mu;
- epsilon = spqcds[b].epsilon;
- b++;
- }
- var subband = resolution.subbands[j];
- var gainLog2 = SubbandsGainLog2[subband.type];
- var delta = reversible ? 1 : Math.pow(2, precision + gainLog2 - epsilon) * (1 + mu / 2048);
- var mb = guardBits + epsilon - 1;
- copyCoefficients(coefficients, width, height, subband, delta, mb, reversible, segmentationSymbolUsed);
- }
- subbandCoefficients.push({
- width: width,
- height: height,
- items: coefficients
- });
- }
- var result = transform.calculate(subbandCoefficients, component.tcx0, component.tcy0);
- return {
- left: component.tcx0,
- top: component.tcy0,
- width: result.width,
- height: result.height,
- items: result.items
- };
- }
- function transformComponents(context) {
- var siz = context.SIZ;
- var components = context.components;
- var componentsCount = siz.Csiz;
- var resultImages = [];
- for (var i = 0, ii = context.tiles.length; i < ii; i++) {
- var tile = context.tiles[i];
- var transformedTiles = [];
- var c;
- for (c = 0; c < componentsCount; c++) {
- transformedTiles[c] = transformTile(context, tile, c);
- }
- var tile0 = transformedTiles[0];
- var out = new Uint8ClampedArray(tile0.items.length * componentsCount);
- var result = {
- left: tile0.left,
- top: tile0.top,
- width: tile0.width,
- height: tile0.height,
- items: out
- };
- var shift, offset;
- var pos = 0,
- j,
- jj,
- y0,
- y1,
- y2;
- if (tile.codingStyleDefaultParameters.multipleComponentTransform) {
- var fourComponents = componentsCount === 4;
- var y0items = transformedTiles[0].items;
- var y1items = transformedTiles[1].items;
- var y2items = transformedTiles[2].items;
- var y3items = fourComponents ? transformedTiles[3].items : null;
- shift = components[0].precision - 8;
- offset = (128 << shift) + 0.5;
- var component0 = tile.components[0];
- var alpha01 = componentsCount - 3;
- jj = y0items.length;
- if (!component0.codingStyleParameters.reversibleTransformation) {
- for (j = 0; j < jj; j++, pos += alpha01) {
- y0 = y0items[j] + offset;
- y1 = y1items[j];
- y2 = y2items[j];
- out[pos++] = y0 + 1.402 * y2 >> shift;
- out[pos++] = y0 - 0.34413 * y1 - 0.71414 * y2 >> shift;
- out[pos++] = y0 + 1.772 * y1 >> shift;
- }
- } else {
- for (j = 0; j < jj; j++, pos += alpha01) {
- y0 = y0items[j] + offset;
- y1 = y1items[j];
- y2 = y2items[j];
- var g = y0 - (y2 + y1 >> 2);
- out[pos++] = g + y2 >> shift;
- out[pos++] = g >> shift;
- out[pos++] = g + y1 >> shift;
- }
- }
- if (fourComponents) {
- for (j = 0, pos = 3; j < jj; j++, pos += 4) {
- out[pos] = y3items[j] + offset >> shift;
- }
- }
- } else {
- for (c = 0; c < componentsCount; c++) {
- var items = transformedTiles[c].items;
- shift = components[c].precision - 8;
- offset = (128 << shift) + 0.5;
- for (pos = c, j = 0, jj = items.length; j < jj; j++) {
- out[pos] = items[j] + offset >> shift;
- pos += componentsCount;
- }
- }
- }
- resultImages.push(result);
- }
- return resultImages;
- }
- function initializeTile(context, tileIndex) {
- var siz = context.SIZ;
- var componentsCount = siz.Csiz;
- var tile = context.tiles[tileIndex];
- for (var c = 0; c < componentsCount; c++) {
- var component = tile.components[c];
- var qcdOrQcc = context.currentTile.QCC[c] !== undefined ? context.currentTile.QCC[c] : context.currentTile.QCD;
- component.quantizationParameters = qcdOrQcc;
- var codOrCoc = context.currentTile.COC[c] !== undefined ? context.currentTile.COC[c] : context.currentTile.COD;
- component.codingStyleParameters = codOrCoc;
- }
- tile.codingStyleDefaultParameters = context.currentTile.COD;
- }
- var TagTree = function TagTreeClosure() {
- function TagTree(width, height) {
- var levelsLength = (0, _util.log2)(Math.max(width, height)) + 1;
- this.levels = [];
- for (var i = 0; i < levelsLength; i++) {
- var level = {
- width: width,
- height: height,
- items: []
- };
- this.levels.push(level);
- width = Math.ceil(width / 2);
- height = Math.ceil(height / 2);
- }
- }
- TagTree.prototype = {
- reset: function TagTree_reset(i, j) {
- var currentLevel = 0,
- value = 0,
- level;
- while (currentLevel < this.levels.length) {
- level = this.levels[currentLevel];
- var index = i + j * level.width;
- if (level.items[index] !== undefined) {
- value = level.items[index];
- break;
- }
- level.index = index;
- i >>= 1;
- j >>= 1;
- currentLevel++;
- }
- currentLevel--;
- level = this.levels[currentLevel];
- level.items[level.index] = value;
- this.currentLevel = currentLevel;
- delete this.value;
- },
- incrementValue: function TagTree_incrementValue() {
- var level = this.levels[this.currentLevel];
- level.items[level.index]++;
- },
- nextLevel: function TagTree_nextLevel() {
- var currentLevel = this.currentLevel;
- var level = this.levels[currentLevel];
- var value = level.items[level.index];
- currentLevel--;
- if (currentLevel < 0) {
- this.value = value;
- return false;
- }
- this.currentLevel = currentLevel;
- level = this.levels[currentLevel];
- level.items[level.index] = value;
- return true;
- }
- };
- return TagTree;
- }();
- var InclusionTree = function InclusionTreeClosure() {
- function InclusionTree(width, height, defaultValue) {
- var levelsLength = (0, _util.log2)(Math.max(width, height)) + 1;
- this.levels = [];
- for (var i = 0; i < levelsLength; i++) {
- var items = new Uint8Array(width * height);
- for (var j = 0, jj = items.length; j < jj; j++) {
- items[j] = defaultValue;
- }
- var level = {
- width: width,
- height: height,
- items: items
- };
- this.levels.push(level);
- width = Math.ceil(width / 2);
- height = Math.ceil(height / 2);
- }
- }
- InclusionTree.prototype = {
- reset: function InclusionTree_reset(i, j, stopValue) {
- var currentLevel = 0;
- while (currentLevel < this.levels.length) {
- var level = this.levels[currentLevel];
- var index = i + j * level.width;
- level.index = index;
- var value = level.items[index];
- if (value === 0xFF) {
- break;
- }
- if (value > stopValue) {
- this.currentLevel = currentLevel;
- this.propagateValues();
- return false;
- }
- i >>= 1;
- j >>= 1;
- currentLevel++;
- }
- this.currentLevel = currentLevel - 1;
- return true;
- },
- incrementValue: function InclusionTree_incrementValue(stopValue) {
- var level = this.levels[this.currentLevel];
- level.items[level.index] = stopValue + 1;
- this.propagateValues();
- },
- propagateValues: function InclusionTree_propagateValues() {
- var levelIndex = this.currentLevel;
- var level = this.levels[levelIndex];
- var currentValue = level.items[level.index];
- while (--levelIndex >= 0) {
- level = this.levels[levelIndex];
- level.items[level.index] = currentValue;
- }
- },
- nextLevel: function InclusionTree_nextLevel() {
- var currentLevel = this.currentLevel;
- var level = this.levels[currentLevel];
- var value = level.items[level.index];
- level.items[level.index] = 0xFF;
- currentLevel--;
- if (currentLevel < 0) {
- return false;
- }
- this.currentLevel = currentLevel;
- level = this.levels[currentLevel];
- level.items[level.index] = value;
- return true;
- }
- };
- return InclusionTree;
- }();
- var BitModel = function BitModelClosure() {
- var UNIFORM_CONTEXT = 17;
- var RUNLENGTH_CONTEXT = 18;
- var LLAndLHContextsLabel = new Uint8Array([0, 5, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 1, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8]);
- var HLContextLabel = new Uint8Array([0, 3, 4, 0, 5, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 1, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8]);
- var HHContextLabel = new Uint8Array([0, 1, 2, 0, 1, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 3, 4, 5, 0, 4, 5, 5, 0, 5, 5, 5, 0, 0, 0, 0, 0, 6, 7, 7, 0, 7, 7, 7, 0, 7, 7, 7, 0, 0, 0, 0, 0, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 8, 0, 0, 0, 0, 0, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 8]);
- function BitModel(width, height, subband, zeroBitPlanes, mb) {
- this.width = width;
- this.height = height;
- this.contextLabelTable = subband === 'HH' ? HHContextLabel : subband === 'HL' ? HLContextLabel : LLAndLHContextsLabel;
- var coefficientCount = width * height;
- this.neighborsSignificance = new Uint8Array(coefficientCount);
- this.coefficentsSign = new Uint8Array(coefficientCount);
- this.coefficentsMagnitude = mb > 14 ? new Uint32Array(coefficientCount) : mb > 6 ? new Uint16Array(coefficientCount) : new Uint8Array(coefficientCount);
- this.processingFlags = new Uint8Array(coefficientCount);
- var bitsDecoded = new Uint8Array(coefficientCount);
- if (zeroBitPlanes !== 0) {
- for (var i = 0; i < coefficientCount; i++) {
- bitsDecoded[i] = zeroBitPlanes;
- }
- }
- this.bitsDecoded = bitsDecoded;
- this.reset();
- }
- BitModel.prototype = {
- setDecoder: function BitModel_setDecoder(decoder) {
- this.decoder = decoder;
- },
- reset: function BitModel_reset() {
- this.contexts = new Int8Array(19);
- this.contexts[0] = 4 << 1 | 0;
- this.contexts[UNIFORM_CONTEXT] = 46 << 1 | 0;
- this.contexts[RUNLENGTH_CONTEXT] = 3 << 1 | 0;
- },
- setNeighborsSignificance: function BitModel_setNeighborsSignificance(row, column, index) {
- var neighborsSignificance = this.neighborsSignificance;
- var width = this.width,
- height = this.height;
- var left = column > 0;
- var right = column + 1 < width;
- var i;
- if (row > 0) {
- i = index - width;
- if (left) {
- neighborsSignificance[i - 1] += 0x10;
- }
- if (right) {
- neighborsSignificance[i + 1] += 0x10;
- }
- neighborsSignificance[i] += 0x04;
- }
- if (row + 1 < height) {
- i = index + width;
- if (left) {
- neighborsSignificance[i - 1] += 0x10;
- }
- if (right) {
- neighborsSignificance[i + 1] += 0x10;
- }
- neighborsSignificance[i] += 0x04;
- }
- if (left) {
- neighborsSignificance[index - 1] += 0x01;
- }
- if (right) {
- neighborsSignificance[index + 1] += 0x01;
- }
- neighborsSignificance[index] |= 0x80;
- },
- runSignificancePropagationPass: function BitModel_runSignificancePropagationPass() {
- var decoder = this.decoder;
- var width = this.width,
- height = this.height;
- var coefficentsMagnitude = this.coefficentsMagnitude;
- var coefficentsSign = this.coefficentsSign;
- var neighborsSignificance = this.neighborsSignificance;
- var processingFlags = this.processingFlags;
- var contexts = this.contexts;
- var labels = this.contextLabelTable;
- var bitsDecoded = this.bitsDecoded;
- var processedInverseMask = ~1;
- var processedMask = 1;
- var firstMagnitudeBitMask = 2;
- for (var i0 = 0; i0 < height; i0 += 4) {
- for (var j = 0; j < width; j++) {
- var index = i0 * width + j;
- for (var i1 = 0; i1 < 4; i1++, index += width) {
- var i = i0 + i1;
- if (i >= height) {
- break;
- }
- processingFlags[index] &= processedInverseMask;
- if (coefficentsMagnitude[index] || !neighborsSignificance[index]) {
- continue;
- }
- var contextLabel = labels[neighborsSignificance[index]];
- var decision = decoder.readBit(contexts, contextLabel);
- if (decision) {
- var sign = this.decodeSignBit(i, j, index);
- coefficentsSign[index] = sign;
- coefficentsMagnitude[index] = 1;
- this.setNeighborsSignificance(i, j, index);
- processingFlags[index] |= firstMagnitudeBitMask;
- }
- bitsDecoded[index]++;
- processingFlags[index] |= processedMask;
- }
- }
- }
- },
- decodeSignBit: function BitModel_decodeSignBit(row, column, index) {
- var width = this.width,
- height = this.height;
- var coefficentsMagnitude = this.coefficentsMagnitude;
- var coefficentsSign = this.coefficentsSign;
- var contribution, sign0, sign1, significance1;
- var contextLabel, decoded;
- significance1 = column > 0 && coefficentsMagnitude[index - 1] !== 0;
- if (column + 1 < width && coefficentsMagnitude[index + 1] !== 0) {
- sign1 = coefficentsSign[index + 1];
- if (significance1) {
- sign0 = coefficentsSign[index - 1];
- contribution = 1 - sign1 - sign0;
- } else {
- contribution = 1 - sign1 - sign1;
- }
- } else if (significance1) {
- sign0 = coefficentsSign[index - 1];
- contribution = 1 - sign0 - sign0;
- } else {
- contribution = 0;
- }
- var horizontalContribution = 3 * contribution;
- significance1 = row > 0 && coefficentsMagnitude[index - width] !== 0;
- if (row + 1 < height && coefficentsMagnitude[index + width] !== 0) {
- sign1 = coefficentsSign[index + width];
- if (significance1) {
- sign0 = coefficentsSign[index - width];
- contribution = 1 - sign1 - sign0 + horizontalContribution;
- } else {
- contribution = 1 - sign1 - sign1 + horizontalContribution;
- }
- } else if (significance1) {
- sign0 = coefficentsSign[index - width];
- contribution = 1 - sign0 - sign0 + horizontalContribution;
- } else {
- contribution = horizontalContribution;
- }
- if (contribution >= 0) {
- contextLabel = 9 + contribution;
- decoded = this.decoder.readBit(this.contexts, contextLabel);
- } else {
- contextLabel = 9 - contribution;
- decoded = this.decoder.readBit(this.contexts, contextLabel) ^ 1;
- }
- return decoded;
- },
- runMagnitudeRefinementPass: function BitModel_runMagnitudeRefinementPass() {
- var decoder = this.decoder;
- var width = this.width,
- height = this.height;
- var coefficentsMagnitude = this.coefficentsMagnitude;
- var neighborsSignificance = this.neighborsSignificance;
- var contexts = this.contexts;
- var bitsDecoded = this.bitsDecoded;
- var processingFlags = this.processingFlags;
- var processedMask = 1;
- var firstMagnitudeBitMask = 2;
- var length = width * height;
- var width4 = width * 4;
- for (var index0 = 0, indexNext; index0 < length; index0 = indexNext) {
- indexNext = Math.min(length, index0 + width4);
- for (var j = 0; j < width; j++) {
- for (var index = index0 + j; index < indexNext; index += width) {
- if (!coefficentsMagnitude[index] || (processingFlags[index] & processedMask) !== 0) {
- continue;
- }
- var contextLabel = 16;
- if ((processingFlags[index] & firstMagnitudeBitMask) !== 0) {
- processingFlags[index] ^= firstMagnitudeBitMask;
- var significance = neighborsSignificance[index] & 127;
- contextLabel = significance === 0 ? 15 : 14;
- }
- var bit = decoder.readBit(contexts, contextLabel);
- coefficentsMagnitude[index] = coefficentsMagnitude[index] << 1 | bit;
- bitsDecoded[index]++;
- processingFlags[index] |= processedMask;
- }
- }
- }
- },
- runCleanupPass: function BitModel_runCleanupPass() {
- var decoder = this.decoder;
- var width = this.width,
- height = this.height;
- var neighborsSignificance = this.neighborsSignificance;
- var coefficentsMagnitude = this.coefficentsMagnitude;
- var coefficentsSign = this.coefficentsSign;
- var contexts = this.contexts;
- var labels = this.contextLabelTable;
- var bitsDecoded = this.bitsDecoded;
- var processingFlags = this.processingFlags;
- var processedMask = 1;
- var firstMagnitudeBitMask = 2;
- var oneRowDown = width;
- var twoRowsDown = width * 2;
- var threeRowsDown = width * 3;
- var iNext;
- for (var i0 = 0; i0 < height; i0 = iNext) {
- iNext = Math.min(i0 + 4, height);
- var indexBase = i0 * width;
- var checkAllEmpty = i0 + 3 < height;
- for (var j = 0; j < width; j++) {
- var index0 = indexBase + j;
- var allEmpty = checkAllEmpty && processingFlags[index0] === 0 && processingFlags[index0 + oneRowDown] === 0 && processingFlags[index0 + twoRowsDown] === 0 && processingFlags[index0 + threeRowsDown] === 0 && neighborsSignificance[index0] === 0 && neighborsSignificance[index0 + oneRowDown] === 0 && neighborsSignificance[index0 + twoRowsDown] === 0 && neighborsSignificance[index0 + threeRowsDown] === 0;
- var i1 = 0,
- index = index0;
- var i = i0,
- sign;
- if (allEmpty) {
- var hasSignificantCoefficent = decoder.readBit(contexts, RUNLENGTH_CONTEXT);
- if (!hasSignificantCoefficent) {
- bitsDecoded[index0]++;
- bitsDecoded[index0 + oneRowDown]++;
- bitsDecoded[index0 + twoRowsDown]++;
- bitsDecoded[index0 + threeRowsDown]++;
- continue;
- }
- i1 = decoder.readBit(contexts, UNIFORM_CONTEXT) << 1 | decoder.readBit(contexts, UNIFORM_CONTEXT);
- if (i1 !== 0) {
- i = i0 + i1;
- index += i1 * width;
- }
- sign = this.decodeSignBit(i, j, index);
- coefficentsSign[index] = sign;
- coefficentsMagnitude[index] = 1;
- this.setNeighborsSignificance(i, j, index);
- processingFlags[index] |= firstMagnitudeBitMask;
- index = index0;
- for (var i2 = i0; i2 <= i; i2++, index += width) {
- bitsDecoded[index]++;
- }
- i1++;
- }
- for (i = i0 + i1; i < iNext; i++, index += width) {
- if (coefficentsMagnitude[index] || (processingFlags[index] & processedMask) !== 0) {
- continue;
- }
- var contextLabel = labels[neighborsSignificance[index]];
- var decision = decoder.readBit(contexts, contextLabel);
- if (decision === 1) {
- sign = this.decodeSignBit(i, j, index);
- coefficentsSign[index] = sign;
- coefficentsMagnitude[index] = 1;
- this.setNeighborsSignificance(i, j, index);
- processingFlags[index] |= firstMagnitudeBitMask;
- }
- bitsDecoded[index]++;
- }
- }
- }
- },
- checkSegmentationSymbol: function BitModel_checkSegmentationSymbol() {
- var decoder = this.decoder;
- var contexts = this.contexts;
- var symbol = decoder.readBit(contexts, UNIFORM_CONTEXT) << 3 | decoder.readBit(contexts, UNIFORM_CONTEXT) << 2 | decoder.readBit(contexts, UNIFORM_CONTEXT) << 1 | decoder.readBit(contexts, UNIFORM_CONTEXT);
- if (symbol !== 0xA) {
- throw new JpxError('Invalid segmentation symbol');
- }
- }
- };
- return BitModel;
- }();
- var Transform = function TransformClosure() {
- function Transform() {}
- Transform.prototype.calculate = function transformCalculate(subbands, u0, v0) {
- var ll = subbands[0];
- for (var i = 1, ii = subbands.length; i < ii; i++) {
- ll = this.iterate(ll, subbands[i], u0, v0);
- }
- return ll;
- };
- Transform.prototype.extend = function extend(buffer, offset, size) {
- var i1 = offset - 1,
- j1 = offset + 1;
- var i2 = offset + size - 2,
- j2 = offset + size;
- buffer[i1--] = buffer[j1++];
- buffer[j2++] = buffer[i2--];
- buffer[i1--] = buffer[j1++];
- buffer[j2++] = buffer[i2--];
- buffer[i1--] = buffer[j1++];
- buffer[j2++] = buffer[i2--];
- buffer[i1] = buffer[j1];
- buffer[j2] = buffer[i2];
- };
- Transform.prototype.iterate = function Transform_iterate(ll, hl_lh_hh, u0, v0) {
- var llWidth = ll.width,
- llHeight = ll.height,
- llItems = ll.items;
- var width = hl_lh_hh.width;
- var height = hl_lh_hh.height;
- var items = hl_lh_hh.items;
- var i, j, k, l, u, v;
- for (k = 0, i = 0; i < llHeight; i++) {
- l = i * 2 * width;
- for (j = 0; j < llWidth; j++, k++, l += 2) {
- items[l] = llItems[k];
- }
- }
- llItems = ll.items = null;
- var bufferPadding = 4;
- var rowBuffer = new Float32Array(width + 2 * bufferPadding);
- if (width === 1) {
- if ((u0 & 1) !== 0) {
- for (v = 0, k = 0; v < height; v++, k += width) {
- items[k] *= 0.5;
- }
- }
- } else {
- for (v = 0, k = 0; v < height; v++, k += width) {
- rowBuffer.set(items.subarray(k, k + width), bufferPadding);
- this.extend(rowBuffer, bufferPadding, width);
- this.filter(rowBuffer, bufferPadding, width);
- items.set(rowBuffer.subarray(bufferPadding, bufferPadding + width), k);
- }
- }
- var numBuffers = 16;
- var colBuffers = [];
- for (i = 0; i < numBuffers; i++) {
- colBuffers.push(new Float32Array(height + 2 * bufferPadding));
- }
- var b,
- currentBuffer = 0;
- ll = bufferPadding + height;
- if (height === 1) {
- if ((v0 & 1) !== 0) {
- for (u = 0; u < width; u++) {
- items[u] *= 0.5;
- }
- }
- } else {
- for (u = 0; u < width; u++) {
- if (currentBuffer === 0) {
- numBuffers = Math.min(width - u, numBuffers);
- for (k = u, l = bufferPadding; l < ll; k += width, l++) {
- for (b = 0; b < numBuffers; b++) {
- colBuffers[b][l] = items[k + b];
- }
- }
- currentBuffer = numBuffers;
- }
- currentBuffer--;
- var buffer = colBuffers[currentBuffer];
- this.extend(buffer, bufferPadding, height);
- this.filter(buffer, bufferPadding, height);
- if (currentBuffer === 0) {
- k = u - numBuffers + 1;
- for (l = bufferPadding; l < ll; k += width, l++) {
- for (b = 0; b < numBuffers; b++) {
- items[k + b] = colBuffers[b][l];
- }
- }
- }
- }
- }
- return {
- width: width,
- height: height,
- items: items
- };
- };
- return Transform;
- }();
- var IrreversibleTransform = function IrreversibleTransformClosure() {
- function IrreversibleTransform() {
- Transform.call(this);
- }
- IrreversibleTransform.prototype = Object.create(Transform.prototype);
- IrreversibleTransform.prototype.filter = function irreversibleTransformFilter(x, offset, length) {
- var len = length >> 1;
- offset = offset | 0;
- var j, n, current, next;
- var alpha = -1.586134342059924;
- var beta = -0.052980118572961;
- var gamma = 0.882911075530934;
- var delta = 0.443506852043971;
- var K = 1.230174104914001;
- var K_ = 1 / K;
- j = offset - 3;
- for (n = len + 4; n--; j += 2) {
- x[j] *= K_;
- }
- j = offset - 2;
- current = delta * x[j - 1];
- for (n = len + 3; n--; j += 2) {
- next = delta * x[j + 1];
- x[j] = K * x[j] - current - next;
- if (n--) {
- j += 2;
- current = delta * x[j + 1];
- x[j] = K * x[j] - current - next;
- } else {
- break;
- }
- }
- j = offset - 1;
- current = gamma * x[j - 1];
- for (n = len + 2; n--; j += 2) {
- next = gamma * x[j + 1];
- x[j] -= current + next;
- if (n--) {
- j += 2;
- current = gamma * x[j + 1];
- x[j] -= current + next;
- } else {
- break;
- }
- }
- j = offset;
- current = beta * x[j - 1];
- for (n = len + 1; n--; j += 2) {
- next = beta * x[j + 1];
- x[j] -= current + next;
- if (n--) {
- j += 2;
- current = beta * x[j + 1];
- x[j] -= current + next;
- } else {
- break;
- }
- }
- if (len !== 0) {
- j = offset + 1;
- current = alpha * x[j - 1];
- for (n = len; n--; j += 2) {
- next = alpha * x[j + 1];
- x[j] -= current + next;
- if (n--) {
- j += 2;
- current = alpha * x[j + 1];
- x[j] -= current + next;
- } else {
- break;
- }
- }
- }
- };
- return IrreversibleTransform;
- }();
- var ReversibleTransform = function ReversibleTransformClosure() {
- function ReversibleTransform() {
- Transform.call(this);
- }
- ReversibleTransform.prototype = Object.create(Transform.prototype);
- ReversibleTransform.prototype.filter = function reversibleTransformFilter(x, offset, length) {
- var len = length >> 1;
- offset = offset | 0;
- var j, n;
- for (j = offset, n = len + 1; n--; j += 2) {
- x[j] -= x[j - 1] + x[j + 1] + 2 >> 2;
- }
- for (j = offset + 1, n = len; n--; j += 2) {
- x[j] += x[j - 1] + x[j + 1] >> 1;
- }
- };
- return ReversibleTransform;
- }();
- return JpxImage;
-}();
-exports.JpxImage = JpxImage;
-
-/***/ }),
-/* 150 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.calculateSHA512 = exports.calculateSHA384 = exports.calculateSHA256 = exports.calculateMD5 = exports.PDF20 = exports.PDF17 = exports.CipherTransformFactory = exports.ARCFourCipher = exports.AES256Cipher = exports.AES128Cipher = undefined;
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-var _util = __w_pdfjs_require__(2);
-
-var _primitives = __w_pdfjs_require__(138);
-
-var _stream = __w_pdfjs_require__(140);
-
-function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
-
-function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-var ARCFourCipher = function ARCFourCipherClosure() {
- function ARCFourCipher(key) {
- this.a = 0;
- this.b = 0;
- var s = new Uint8Array(256);
- var i,
- j = 0,
- tmp,
- keyLength = key.length;
- for (i = 0; i < 256; ++i) {
- s[i] = i;
- }
- for (i = 0; i < 256; ++i) {
- tmp = s[i];
- j = j + tmp + key[i % keyLength] & 0xFF;
- s[i] = s[j];
- s[j] = tmp;
- }
- this.s = s;
- }
- ARCFourCipher.prototype = {
- encryptBlock: function ARCFourCipher_encryptBlock(data) {
- var i,
- n = data.length,
- tmp,
- tmp2;
- var a = this.a,
- b = this.b,
- s = this.s;
- var output = new Uint8Array(n);
- for (i = 0; i < n; ++i) {
- a = a + 1 & 0xFF;
- tmp = s[a];
- b = b + tmp & 0xFF;
- tmp2 = s[b];
- s[a] = tmp2;
- s[b] = tmp;
- output[i] = data[i] ^ s[tmp + tmp2 & 0xFF];
- }
- this.a = a;
- this.b = b;
- return output;
- }
- };
- ARCFourCipher.prototype.decryptBlock = ARCFourCipher.prototype.encryptBlock;
- return ARCFourCipher;
-}();
-var calculateMD5 = function calculateMD5Closure() {
- var r = new Uint8Array([7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]);
- var k = new Int32Array([-680876936, -389564586, 606105819, -1044525330, -176418897, 1200080426, -1473231341, -45705983, 1770035416, -1958414417, -42063, -1990404162, 1804603682, -40341101, -1502002290, 1236535329, -165796510, -1069501632, 643717713, -373897302, -701558691, 38016083, -660478335, -405537848, 568446438, -1019803690, -187363961, 1163531501, -1444681467, -51403784, 1735328473, -1926607734, -378558, -2022574463, 1839030562, -35309556, -1530992060, 1272893353, -155497632, -1094730640, 681279174, -358537222, -722521979, 76029189, -640364487, -421815835, 530742520, -995338651, -198630844, 1126891415, -1416354905, -57434055, 1700485571, -1894986606, -1051523, -2054922799, 1873313359, -30611744, -1560198380, 1309151649, -145523070, -1120210379, 718787259, -343485551]);
- function hash(data, offset, length) {
- var h0 = 1732584193,
- h1 = -271733879,
- h2 = -1732584194,
- h3 = 271733878;
- var paddedLength = length + 72 & ~63;
- var padded = new Uint8Array(paddedLength);
- var i, j, n;
- for (i = 0; i < length; ++i) {
- padded[i] = data[offset++];
- }
- padded[i++] = 0x80;
- n = paddedLength - 8;
- while (i < n) {
- padded[i++] = 0;
- }
- padded[i++] = length << 3 & 0xFF;
- padded[i++] = length >> 5 & 0xFF;
- padded[i++] = length >> 13 & 0xFF;
- padded[i++] = length >> 21 & 0xFF;
- padded[i++] = length >>> 29 & 0xFF;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- var w = new Int32Array(16);
- for (i = 0; i < paddedLength;) {
- for (j = 0; j < 16; ++j, i += 4) {
- w[j] = padded[i] | padded[i + 1] << 8 | padded[i + 2] << 16 | padded[i + 3] << 24;
- }
- var a = h0,
- b = h1,
- c = h2,
- d = h3,
- f,
- g;
- for (j = 0; j < 64; ++j) {
- if (j < 16) {
- f = b & c | ~b & d;
- g = j;
- } else if (j < 32) {
- f = d & b | ~d & c;
- g = 5 * j + 1 & 15;
- } else if (j < 48) {
- f = b ^ c ^ d;
- g = 3 * j + 5 & 15;
- } else {
- f = c ^ (b | ~d);
- g = 7 * j & 15;
- }
- var tmp = d,
- rotateArg = a + f + k[j] + w[g] | 0,
- rotate = r[j];
- d = c;
- c = b;
- b = b + (rotateArg << rotate | rotateArg >>> 32 - rotate) | 0;
- a = tmp;
- }
- h0 = h0 + a | 0;
- h1 = h1 + b | 0;
- h2 = h2 + c | 0;
- h3 = h3 + d | 0;
- }
- return new Uint8Array([h0 & 0xFF, h0 >> 8 & 0xFF, h0 >> 16 & 0xFF, h0 >>> 24 & 0xFF, h1 & 0xFF, h1 >> 8 & 0xFF, h1 >> 16 & 0xFF, h1 >>> 24 & 0xFF, h2 & 0xFF, h2 >> 8 & 0xFF, h2 >> 16 & 0xFF, h2 >>> 24 & 0xFF, h3 & 0xFF, h3 >> 8 & 0xFF, h3 >> 16 & 0xFF, h3 >>> 24 & 0xFF]);
- }
- return hash;
-}();
-var Word64 = function Word64Closure() {
- function Word64(highInteger, lowInteger) {
- this.high = highInteger | 0;
- this.low = lowInteger | 0;
- }
- Word64.prototype = {
- and: function Word64_and(word) {
- this.high &= word.high;
- this.low &= word.low;
- },
- xor: function Word64_xor(word) {
- this.high ^= word.high;
- this.low ^= word.low;
- },
- or: function Word64_or(word) {
- this.high |= word.high;
- this.low |= word.low;
- },
- shiftRight: function Word64_shiftRight(places) {
- if (places >= 32) {
- this.low = this.high >>> places - 32 | 0;
- this.high = 0;
- } else {
- this.low = this.low >>> places | this.high << 32 - places;
- this.high = this.high >>> places | 0;
- }
- },
- shiftLeft: function Word64_shiftLeft(places) {
- if (places >= 32) {
- this.high = this.low << places - 32;
- this.low = 0;
- } else {
- this.high = this.high << places | this.low >>> 32 - places;
- this.low = this.low << places;
- }
- },
- rotateRight: function Word64_rotateRight(places) {
- var low, high;
- if (places & 32) {
- high = this.low;
- low = this.high;
- } else {
- low = this.low;
- high = this.high;
- }
- places &= 31;
- this.low = low >>> places | high << 32 - places;
- this.high = high >>> places | low << 32 - places;
- },
- not: function Word64_not() {
- this.high = ~this.high;
- this.low = ~this.low;
- },
- add: function Word64_add(word) {
- var lowAdd = (this.low >>> 0) + (word.low >>> 0);
- var highAdd = (this.high >>> 0) + (word.high >>> 0);
- if (lowAdd > 0xFFFFFFFF) {
- highAdd += 1;
- }
- this.low = lowAdd | 0;
- this.high = highAdd | 0;
- },
- copyTo: function Word64_copyTo(bytes, offset) {
- bytes[offset] = this.high >>> 24 & 0xFF;
- bytes[offset + 1] = this.high >> 16 & 0xFF;
- bytes[offset + 2] = this.high >> 8 & 0xFF;
- bytes[offset + 3] = this.high & 0xFF;
- bytes[offset + 4] = this.low >>> 24 & 0xFF;
- bytes[offset + 5] = this.low >> 16 & 0xFF;
- bytes[offset + 6] = this.low >> 8 & 0xFF;
- bytes[offset + 7] = this.low & 0xFF;
- },
- assign: function Word64_assign(word) {
- this.high = word.high;
- this.low = word.low;
- }
- };
- return Word64;
-}();
-var calculateSHA256 = function calculateSHA256Closure() {
- function rotr(x, n) {
- return x >>> n | x << 32 - n;
- }
- function ch(x, y, z) {
- return x & y ^ ~x & z;
- }
- function maj(x, y, z) {
- return x & y ^ x & z ^ y & z;
- }
- function sigma(x) {
- return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22);
- }
- function sigmaPrime(x) {
- return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25);
- }
- function littleSigma(x) {
- return rotr(x, 7) ^ rotr(x, 18) ^ x >>> 3;
- }
- function littleSigmaPrime(x) {
- return rotr(x, 17) ^ rotr(x, 19) ^ x >>> 10;
- }
- var k = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];
- function hash(data, offset, length) {
- var h0 = 0x6a09e667,
- h1 = 0xbb67ae85,
- h2 = 0x3c6ef372,
- h3 = 0xa54ff53a,
- h4 = 0x510e527f,
- h5 = 0x9b05688c,
- h6 = 0x1f83d9ab,
- h7 = 0x5be0cd19;
- var paddedLength = Math.ceil((length + 9) / 64) * 64;
- var padded = new Uint8Array(paddedLength);
- var i, j, n;
- for (i = 0; i < length; ++i) {
- padded[i] = data[offset++];
- }
- padded[i++] = 0x80;
- n = paddedLength - 8;
- while (i < n) {
- padded[i++] = 0;
- }
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = length >>> 29 & 0xFF;
- padded[i++] = length >> 21 & 0xFF;
- padded[i++] = length >> 13 & 0xFF;
- padded[i++] = length >> 5 & 0xFF;
- padded[i++] = length << 3 & 0xFF;
- var w = new Uint32Array(64);
- for (i = 0; i < paddedLength;) {
- for (j = 0; j < 16; ++j) {
- w[j] = padded[i] << 24 | padded[i + 1] << 16 | padded[i + 2] << 8 | padded[i + 3];
- i += 4;
- }
- for (j = 16; j < 64; ++j) {
- w[j] = littleSigmaPrime(w[j - 2]) + w[j - 7] + littleSigma(w[j - 15]) + w[j - 16] | 0;
- }
- var a = h0,
- b = h1,
- c = h2,
- d = h3,
- e = h4,
- f = h5,
- g = h6,
- h = h7,
- t1,
- t2;
- for (j = 0; j < 64; ++j) {
- t1 = h + sigmaPrime(e) + ch(e, f, g) + k[j] + w[j];
- t2 = sigma(a) + maj(a, b, c);
- h = g;
- g = f;
- f = e;
- e = d + t1 | 0;
- d = c;
- c = b;
- b = a;
- a = t1 + t2 | 0;
- }
- h0 = h0 + a | 0;
- h1 = h1 + b | 0;
- h2 = h2 + c | 0;
- h3 = h3 + d | 0;
- h4 = h4 + e | 0;
- h5 = h5 + f | 0;
- h6 = h6 + g | 0;
- h7 = h7 + h | 0;
- }
- return new Uint8Array([h0 >> 24 & 0xFF, h0 >> 16 & 0xFF, h0 >> 8 & 0xFF, h0 & 0xFF, h1 >> 24 & 0xFF, h1 >> 16 & 0xFF, h1 >> 8 & 0xFF, h1 & 0xFF, h2 >> 24 & 0xFF, h2 >> 16 & 0xFF, h2 >> 8 & 0xFF, h2 & 0xFF, h3 >> 24 & 0xFF, h3 >> 16 & 0xFF, h3 >> 8 & 0xFF, h3 & 0xFF, h4 >> 24 & 0xFF, h4 >> 16 & 0xFF, h4 >> 8 & 0xFF, h4 & 0xFF, h5 >> 24 & 0xFF, h5 >> 16 & 0xFF, h5 >> 8 & 0xFF, h5 & 0xFF, h6 >> 24 & 0xFF, h6 >> 16 & 0xFF, h6 >> 8 & 0xFF, h6 & 0xFF, h7 >> 24 & 0xFF, h7 >> 16 & 0xFF, h7 >> 8 & 0xFF, h7 & 0xFF]);
- }
- return hash;
-}();
-var calculateSHA512 = function calculateSHA512Closure() {
- function ch(result, x, y, z, tmp) {
- result.assign(x);
- result.and(y);
- tmp.assign(x);
- tmp.not();
- tmp.and(z);
- result.xor(tmp);
- }
- function maj(result, x, y, z, tmp) {
- result.assign(x);
- result.and(y);
- tmp.assign(x);
- tmp.and(z);
- result.xor(tmp);
- tmp.assign(y);
- tmp.and(z);
- result.xor(tmp);
- }
- function sigma(result, x, tmp) {
- result.assign(x);
- result.rotateRight(28);
- tmp.assign(x);
- tmp.rotateRight(34);
- result.xor(tmp);
- tmp.assign(x);
- tmp.rotateRight(39);
- result.xor(tmp);
- }
- function sigmaPrime(result, x, tmp) {
- result.assign(x);
- result.rotateRight(14);
- tmp.assign(x);
- tmp.rotateRight(18);
- result.xor(tmp);
- tmp.assign(x);
- tmp.rotateRight(41);
- result.xor(tmp);
- }
- function littleSigma(result, x, tmp) {
- result.assign(x);
- result.rotateRight(1);
- tmp.assign(x);
- tmp.rotateRight(8);
- result.xor(tmp);
- tmp.assign(x);
- tmp.shiftRight(7);
- result.xor(tmp);
- }
- function littleSigmaPrime(result, x, tmp) {
- result.assign(x);
- result.rotateRight(19);
- tmp.assign(x);
- tmp.rotateRight(61);
- result.xor(tmp);
- tmp.assign(x);
- tmp.shiftRight(6);
- result.xor(tmp);
- }
- var k = [new Word64(0x428a2f98, 0xd728ae22), new Word64(0x71374491, 0x23ef65cd), new Word64(0xb5c0fbcf, 0xec4d3b2f), new Word64(0xe9b5dba5, 0x8189dbbc), new Word64(0x3956c25b, 0xf348b538), new Word64(0x59f111f1, 0xb605d019), new Word64(0x923f82a4, 0xaf194f9b), new Word64(0xab1c5ed5, 0xda6d8118), new Word64(0xd807aa98, 0xa3030242), new Word64(0x12835b01, 0x45706fbe), new Word64(0x243185be, 0x4ee4b28c), new Word64(0x550c7dc3, 0xd5ffb4e2), new Word64(0x72be5d74, 0xf27b896f), new Word64(0x80deb1fe, 0x3b1696b1), new Word64(0x9bdc06a7, 0x25c71235), new Word64(0xc19bf174, 0xcf692694), new Word64(0xe49b69c1, 0x9ef14ad2), new Word64(0xefbe4786, 0x384f25e3), new Word64(0x0fc19dc6, 0x8b8cd5b5), new Word64(0x240ca1cc, 0x77ac9c65), new Word64(0x2de92c6f, 0x592b0275), new Word64(0x4a7484aa, 0x6ea6e483), new Word64(0x5cb0a9dc, 0xbd41fbd4), new Word64(0x76f988da, 0x831153b5), new Word64(0x983e5152, 0xee66dfab), new Word64(0xa831c66d, 0x2db43210), new Word64(0xb00327c8, 0x98fb213f), new Word64(0xbf597fc7, 0xbeef0ee4), new Word64(0xc6e00bf3, 0x3da88fc2), new Word64(0xd5a79147, 0x930aa725), new Word64(0x06ca6351, 0xe003826f), new Word64(0x14292967, 0x0a0e6e70), new Word64(0x27b70a85, 0x46d22ffc), new Word64(0x2e1b2138, 0x5c26c926), new Word64(0x4d2c6dfc, 0x5ac42aed), new Word64(0x53380d13, 0x9d95b3df), new Word64(0x650a7354, 0x8baf63de), new Word64(0x766a0abb, 0x3c77b2a8), new Word64(0x81c2c92e, 0x47edaee6), new Word64(0x92722c85, 0x1482353b), new Word64(0xa2bfe8a1, 0x4cf10364), new Word64(0xa81a664b, 0xbc423001), new Word64(0xc24b8b70, 0xd0f89791), new Word64(0xc76c51a3, 0x0654be30), new Word64(0xd192e819, 0xd6ef5218), new Word64(0xd6990624, 0x5565a910), new Word64(0xf40e3585, 0x5771202a), new Word64(0x106aa070, 0x32bbd1b8), new Word64(0x19a4c116, 0xb8d2d0c8), new Word64(0x1e376c08, 0x5141ab53), new Word64(0x2748774c, 0xdf8eeb99), new Word64(0x34b0bcb5, 0xe19b48a8), new Word64(0x391c0cb3, 0xc5c95a63), new Word64(0x4ed8aa4a, 0xe3418acb), new Word64(0x5b9cca4f, 0x7763e373), new Word64(0x682e6ff3, 0xd6b2b8a3), new Word64(0x748f82ee, 0x5defb2fc), new Word64(0x78a5636f, 0x43172f60), new Word64(0x84c87814, 0xa1f0ab72), new Word64(0x8cc70208, 0x1a6439ec), new Word64(0x90befffa, 0x23631e28), new Word64(0xa4506ceb, 0xde82bde9), new Word64(0xbef9a3f7, 0xb2c67915), new Word64(0xc67178f2, 0xe372532b), new Word64(0xca273ece, 0xea26619c), new Word64(0xd186b8c7, 0x21c0c207), new Word64(0xeada7dd6, 0xcde0eb1e), new Word64(0xf57d4f7f, 0xee6ed178), new Word64(0x06f067aa, 0x72176fba), new Word64(0x0a637dc5, 0xa2c898a6), new Word64(0x113f9804, 0xbef90dae), new Word64(0x1b710b35, 0x131c471b), new Word64(0x28db77f5, 0x23047d84), new Word64(0x32caab7b, 0x40c72493), new Word64(0x3c9ebe0a, 0x15c9bebc), new Word64(0x431d67c4, 0x9c100d4c), new Word64(0x4cc5d4be, 0xcb3e42b6), new Word64(0x597f299c, 0xfc657e2a), new Word64(0x5fcb6fab, 0x3ad6faec), new Word64(0x6c44198c, 0x4a475817)];
- function hash(data, offset, length, mode384) {
- mode384 = !!mode384;
- var h0, h1, h2, h3, h4, h5, h6, h7;
- if (!mode384) {
- h0 = new Word64(0x6a09e667, 0xf3bcc908);
- h1 = new Word64(0xbb67ae85, 0x84caa73b);
- h2 = new Word64(0x3c6ef372, 0xfe94f82b);
- h3 = new Word64(0xa54ff53a, 0x5f1d36f1);
- h4 = new Word64(0x510e527f, 0xade682d1);
- h5 = new Word64(0x9b05688c, 0x2b3e6c1f);
- h6 = new Word64(0x1f83d9ab, 0xfb41bd6b);
- h7 = new Word64(0x5be0cd19, 0x137e2179);
- } else {
- h0 = new Word64(0xcbbb9d5d, 0xc1059ed8);
- h1 = new Word64(0x629a292a, 0x367cd507);
- h2 = new Word64(0x9159015a, 0x3070dd17);
- h3 = new Word64(0x152fecd8, 0xf70e5939);
- h4 = new Word64(0x67332667, 0xffc00b31);
- h5 = new Word64(0x8eb44a87, 0x68581511);
- h6 = new Word64(0xdb0c2e0d, 0x64f98fa7);
- h7 = new Word64(0x47b5481d, 0xbefa4fa4);
- }
- var paddedLength = Math.ceil((length + 17) / 128) * 128;
- var padded = new Uint8Array(paddedLength);
- var i, j, n;
- for (i = 0; i < length; ++i) {
- padded[i] = data[offset++];
- }
- padded[i++] = 0x80;
- n = paddedLength - 16;
- while (i < n) {
- padded[i++] = 0;
- }
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = 0;
- padded[i++] = length >>> 29 & 0xFF;
- padded[i++] = length >> 21 & 0xFF;
- padded[i++] = length >> 13 & 0xFF;
- padded[i++] = length >> 5 & 0xFF;
- padded[i++] = length << 3 & 0xFF;
- var w = new Array(80);
- for (i = 0; i < 80; i++) {
- w[i] = new Word64(0, 0);
- }
- var a = new Word64(0, 0),
- b = new Word64(0, 0),
- c = new Word64(0, 0);
- var d = new Word64(0, 0),
- e = new Word64(0, 0),
- f = new Word64(0, 0);
- var g = new Word64(0, 0),
- h = new Word64(0, 0);
- var t1 = new Word64(0, 0),
- t2 = new Word64(0, 0);
- var tmp1 = new Word64(0, 0),
- tmp2 = new Word64(0, 0),
- tmp3;
- for (i = 0; i < paddedLength;) {
- for (j = 0; j < 16; ++j) {
- w[j].high = padded[i] << 24 | padded[i + 1] << 16 | padded[i + 2] << 8 | padded[i + 3];
- w[j].low = padded[i + 4] << 24 | padded[i + 5] << 16 | padded[i + 6] << 8 | padded[i + 7];
- i += 8;
- }
- for (j = 16; j < 80; ++j) {
- tmp3 = w[j];
- littleSigmaPrime(tmp3, w[j - 2], tmp2);
- tmp3.add(w[j - 7]);
- littleSigma(tmp1, w[j - 15], tmp2);
- tmp3.add(tmp1);
- tmp3.add(w[j - 16]);
- }
- a.assign(h0);
- b.assign(h1);
- c.assign(h2);
- d.assign(h3);
- e.assign(h4);
- f.assign(h5);
- g.assign(h6);
- h.assign(h7);
- for (j = 0; j < 80; ++j) {
- t1.assign(h);
- sigmaPrime(tmp1, e, tmp2);
- t1.add(tmp1);
- ch(tmp1, e, f, g, tmp2);
- t1.add(tmp1);
- t1.add(k[j]);
- t1.add(w[j]);
- sigma(t2, a, tmp2);
- maj(tmp1, a, b, c, tmp2);
- t2.add(tmp1);
- tmp3 = h;
- h = g;
- g = f;
- f = e;
- d.add(t1);
- e = d;
- d = c;
- c = b;
- b = a;
- tmp3.assign(t1);
- tmp3.add(t2);
- a = tmp3;
- }
- h0.add(a);
- h1.add(b);
- h2.add(c);
- h3.add(d);
- h4.add(e);
- h5.add(f);
- h6.add(g);
- h7.add(h);
- }
- var result;
- if (!mode384) {
- result = new Uint8Array(64);
- h0.copyTo(result, 0);
- h1.copyTo(result, 8);
- h2.copyTo(result, 16);
- h3.copyTo(result, 24);
- h4.copyTo(result, 32);
- h5.copyTo(result, 40);
- h6.copyTo(result, 48);
- h7.copyTo(result, 56);
- } else {
- result = new Uint8Array(48);
- h0.copyTo(result, 0);
- h1.copyTo(result, 8);
- h2.copyTo(result, 16);
- h3.copyTo(result, 24);
- h4.copyTo(result, 32);
- h5.copyTo(result, 40);
- }
- return result;
- }
- return hash;
-}();
-var calculateSHA384 = function calculateSHA384Closure() {
- function hash(data, offset, length) {
- return calculateSHA512(data, offset, length, true);
- }
- return hash;
-}();
-var NullCipher = function NullCipherClosure() {
- function NullCipher() {}
- NullCipher.prototype = {
- decryptBlock: function NullCipher_decryptBlock(data) {
- return data;
- }
- };
- return NullCipher;
-}();
-
-var AESBaseCipher = function () {
- function AESBaseCipher() {
- _classCallCheck(this, AESBaseCipher);
-
- if (this.constructor === AESBaseCipher) {
- (0, _util.unreachable)('Cannot initialize AESBaseCipher.');
- }
- this._s = new Uint8Array([0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]);
- this._inv_s = new Uint8Array([0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d]);
- this._mix = new Uint32Array([0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]);
- this._mixCol = new Uint8Array(256);
- for (var i = 0; i < 256; i++) {
- if (i < 128) {
- this._mixCol[i] = i << 1;
- } else {
- this._mixCol[i] = i << 1 ^ 0x1b;
- }
- }
- this.buffer = new Uint8Array(16);
- this.bufferPosition = 0;
- }
-
- _createClass(AESBaseCipher, [{
- key: '_expandKey',
- value: function _expandKey(cipherKey) {
- (0, _util.unreachable)('Cannot call `_expandKey` on the base class');
- }
- }, {
- key: '_decrypt',
- value: function _decrypt(input, key) {
- var t = void 0,
- u = void 0,
- v = void 0;
- var state = new Uint8Array(16);
- state.set(input);
- for (var j = 0, k = this._keySize; j < 16; ++j, ++k) {
- state[j] ^= key[k];
- }
- for (var i = this._cyclesOfRepetition - 1; i >= 1; --i) {
- t = state[13];
- state[13] = state[9];
- state[9] = state[5];
- state[5] = state[1];
- state[1] = t;
- t = state[14];
- u = state[10];
- state[14] = state[6];
- state[10] = state[2];
- state[6] = t;
- state[2] = u;
- t = state[15];
- u = state[11];
- v = state[7];
- state[15] = state[3];
- state[11] = t;
- state[7] = u;
- state[3] = v;
- for (var _j = 0; _j < 16; ++_j) {
- state[_j] = this._inv_s[state[_j]];
- }
- for (var _j2 = 0, _k = i * 16; _j2 < 16; ++_j2, ++_k) {
- state[_j2] ^= key[_k];
- }
- for (var _j3 = 0; _j3 < 16; _j3 += 4) {
- var s0 = this._mix[state[_j3]];
- var s1 = this._mix[state[_j3 + 1]];
- var s2 = this._mix[state[_j3 + 2]];
- var s3 = this._mix[state[_j3 + 3]];
- t = s0 ^ s1 >>> 8 ^ s1 << 24 ^ s2 >>> 16 ^ s2 << 16 ^ s3 >>> 24 ^ s3 << 8;
- state[_j3] = t >>> 24 & 0xFF;
- state[_j3 + 1] = t >> 16 & 0xFF;
- state[_j3 + 2] = t >> 8 & 0xFF;
- state[_j3 + 3] = t & 0xFF;
- }
- }
- t = state[13];
- state[13] = state[9];
- state[9] = state[5];
- state[5] = state[1];
- state[1] = t;
- t = state[14];
- u = state[10];
- state[14] = state[6];
- state[10] = state[2];
- state[6] = t;
- state[2] = u;
- t = state[15];
- u = state[11];
- v = state[7];
- state[15] = state[3];
- state[11] = t;
- state[7] = u;
- state[3] = v;
- for (var _j4 = 0; _j4 < 16; ++_j4) {
- state[_j4] = this._inv_s[state[_j4]];
- state[_j4] ^= key[_j4];
- }
- return state;
- }
- }, {
- key: '_encrypt',
- value: function _encrypt(input, key) {
- var s = this._s;
- var t = void 0,
- u = void 0,
- v = void 0;
- var state = new Uint8Array(16);
- state.set(input);
- for (var j = 0; j < 16; ++j) {
- state[j] ^= key[j];
- }
- for (var i = 1; i < this._cyclesOfRepetition; i++) {
- for (var _j5 = 0; _j5 < 16; ++_j5) {
- state[_j5] = s[state[_j5]];
- }
- v = state[1];
- state[1] = state[5];
- state[5] = state[9];
- state[9] = state[13];
- state[13] = v;
- v = state[2];
- u = state[6];
- state[2] = state[10];
- state[6] = state[14];
- state[10] = v;
- state[14] = u;
- v = state[3];
- u = state[7];
- t = state[11];
- state[3] = state[15];
- state[7] = v;
- state[11] = u;
- state[15] = t;
- for (var _j6 = 0; _j6 < 16; _j6 += 4) {
- var s0 = state[_j6 + 0];
- var s1 = state[_j6 + 1];
- var s2 = state[_j6 + 2];
- var s3 = state[_j6 + 3];
- t = s0 ^ s1 ^ s2 ^ s3;
- state[_j6 + 0] ^= t ^ this._mixCol[s0 ^ s1];
- state[_j6 + 1] ^= t ^ this._mixCol[s1 ^ s2];
- state[_j6 + 2] ^= t ^ this._mixCol[s2 ^ s3];
- state[_j6 + 3] ^= t ^ this._mixCol[s3 ^ s0];
- }
- for (var _j7 = 0, k = i * 16; _j7 < 16; ++_j7, ++k) {
- state[_j7] ^= key[k];
- }
- }
- for (var _j8 = 0; _j8 < 16; ++_j8) {
- state[_j8] = s[state[_j8]];
- }
- v = state[1];
- state[1] = state[5];
- state[5] = state[9];
- state[9] = state[13];
- state[13] = v;
- v = state[2];
- u = state[6];
- state[2] = state[10];
- state[6] = state[14];
- state[10] = v;
- state[14] = u;
- v = state[3];
- u = state[7];
- t = state[11];
- state[3] = state[15];
- state[7] = v;
- state[11] = u;
- state[15] = t;
- for (var _j9 = 0, _k2 = this._keySize; _j9 < 16; ++_j9, ++_k2) {
- state[_j9] ^= key[_k2];
- }
- return state;
- }
- }, {
- key: '_decryptBlock2',
- value: function _decryptBlock2(data, finalize) {
- var sourceLength = data.length;
- var buffer = this.buffer,
- bufferLength = this.bufferPosition;
- var result = [],
- iv = this.iv;
- for (var i = 0; i < sourceLength; ++i) {
- buffer[bufferLength] = data[i];
- ++bufferLength;
- if (bufferLength < 16) {
- continue;
- }
- var plain = this._decrypt(buffer, this._key);
- for (var j = 0; j < 16; ++j) {
- plain[j] ^= iv[j];
- }
- iv = buffer;
- result.push(plain);
- buffer = new Uint8Array(16);
- bufferLength = 0;
- }
- this.buffer = buffer;
- this.bufferLength = bufferLength;
- this.iv = iv;
- if (result.length === 0) {
- return new Uint8Array(0);
- }
- var outputLength = 16 * result.length;
- if (finalize) {
- var lastBlock = result[result.length - 1];
- var psLen = lastBlock[15];
- if (psLen <= 16) {
- for (var _i = 15, ii = 16 - psLen; _i >= ii; --_i) {
- if (lastBlock[_i] !== psLen) {
- psLen = 0;
- break;
- }
- }
- outputLength -= psLen;
- result[result.length - 1] = lastBlock.subarray(0, 16 - psLen);
- }
- }
- var output = new Uint8Array(outputLength);
- for (var _i2 = 0, _j10 = 0, _ii = result.length; _i2 < _ii; ++_i2, _j10 += 16) {
- output.set(result[_i2], _j10);
- }
- return output;
- }
- }, {
- key: 'decryptBlock',
- value: function decryptBlock(data, finalize) {
- var iv = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
-
- var sourceLength = data.length;
- var buffer = this.buffer,
- bufferLength = this.bufferPosition;
- if (iv) {
- this.iv = iv;
- } else {
- for (var i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) {
- buffer[bufferLength] = data[i];
- }
- if (bufferLength < 16) {
- this.bufferLength = bufferLength;
- return new Uint8Array(0);
- }
- this.iv = buffer;
- data = data.subarray(16);
- }
- this.buffer = new Uint8Array(16);
- this.bufferLength = 0;
- this.decryptBlock = this._decryptBlock2;
- return this.decryptBlock(data, finalize);
- }
- }, {
- key: 'encrypt',
- value: function encrypt(data, iv) {
- var sourceLength = data.length;
- var buffer = this.buffer,
- bufferLength = this.bufferPosition;
- var result = [];
- if (!iv) {
- iv = new Uint8Array(16);
- }
- for (var i = 0; i < sourceLength; ++i) {
- buffer[bufferLength] = data[i];
- ++bufferLength;
- if (bufferLength < 16) {
- continue;
- }
- for (var j = 0; j < 16; ++j) {
- buffer[j] ^= iv[j];
- }
- var cipher = this._encrypt(buffer, this._key);
- iv = cipher;
- result.push(cipher);
- buffer = new Uint8Array(16);
- bufferLength = 0;
- }
- this.buffer = buffer;
- this.bufferLength = bufferLength;
- this.iv = iv;
- if (result.length === 0) {
- return new Uint8Array(0);
- }
- var outputLength = 16 * result.length;
- var output = new Uint8Array(outputLength);
- for (var _i3 = 0, _j11 = 0, ii = result.length; _i3 < ii; ++_i3, _j11 += 16) {
- output.set(result[_i3], _j11);
- }
- return output;
- }
- }]);
-
- return AESBaseCipher;
-}();
-
-var AES128Cipher = function (_AESBaseCipher) {
- _inherits(AES128Cipher, _AESBaseCipher);
-
- function AES128Cipher(key) {
- _classCallCheck(this, AES128Cipher);
-
- var _this = _possibleConstructorReturn(this, (AES128Cipher.__proto__ || Object.getPrototypeOf(AES128Cipher)).call(this));
-
- _this._cyclesOfRepetition = 10;
- _this._keySize = 160;
- _this._rcon = new Uint8Array([0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d]);
- _this._key = _this._expandKey(key);
- return _this;
- }
-
- _createClass(AES128Cipher, [{
- key: '_expandKey',
- value: function _expandKey(cipherKey) {
- var b = 176;
- var s = this._s;
- var rcon = this._rcon;
- var result = new Uint8Array(b);
- result.set(cipherKey);
- for (var j = 16, i = 1; j < b; ++i) {
- var t1 = result[j - 3];
- var t2 = result[j - 2];
- var t3 = result[j - 1];
- var t4 = result[j - 4];
- t1 = s[t1];
- t2 = s[t2];
- t3 = s[t3];
- t4 = s[t4];
- t1 = t1 ^ rcon[i];
- for (var n = 0; n < 4; ++n) {
- result[j] = t1 ^= result[j - 16];
- j++;
- result[j] = t2 ^= result[j - 16];
- j++;
- result[j] = t3 ^= result[j - 16];
- j++;
- result[j] = t4 ^= result[j - 16];
- j++;
- }
- }
- return result;
- }
- }]);
-
- return AES128Cipher;
-}(AESBaseCipher);
-
-var AES256Cipher = function (_AESBaseCipher2) {
- _inherits(AES256Cipher, _AESBaseCipher2);
-
- function AES256Cipher(key) {
- _classCallCheck(this, AES256Cipher);
-
- var _this2 = _possibleConstructorReturn(this, (AES256Cipher.__proto__ || Object.getPrototypeOf(AES256Cipher)).call(this));
-
- _this2._cyclesOfRepetition = 14;
- _this2._keySize = 224;
- _this2._key = _this2._expandKey(key);
- return _this2;
- }
-
- _createClass(AES256Cipher, [{
- key: '_expandKey',
- value: function _expandKey(cipherKey) {
- var b = 240;
- var s = this._s;
- var result = new Uint8Array(b);
- result.set(cipherKey);
- var r = 1;
- var t1 = void 0,
- t2 = void 0,
- t3 = void 0,
- t4 = void 0;
- for (var j = 32, i = 1; j < b; ++i) {
- if (j % 32 === 16) {
- t1 = s[t1];
- t2 = s[t2];
- t3 = s[t3];
- t4 = s[t4];
- } else if (j % 32 === 0) {
- t1 = result[j - 3];
- t2 = result[j - 2];
- t3 = result[j - 1];
- t4 = result[j - 4];
- t1 = s[t1];
- t2 = s[t2];
- t3 = s[t3];
- t4 = s[t4];
- t1 = t1 ^ r;
- if ((r <<= 1) >= 256) {
- r = (r ^ 0x1b) & 0xFF;
- }
- }
- for (var n = 0; n < 4; ++n) {
- result[j] = t1 ^= result[j - 32];
- j++;
- result[j] = t2 ^= result[j - 32];
- j++;
- result[j] = t3 ^= result[j - 32];
- j++;
- result[j] = t4 ^= result[j - 32];
- j++;
- }
- }
- return result;
- }
- }]);
-
- return AES256Cipher;
-}(AESBaseCipher);
-
-var PDF17 = function PDF17Closure() {
- function compareByteArrays(array1, array2) {
- if (array1.length !== array2.length) {
- return false;
- }
- for (var i = 0; i < array1.length; i++) {
- if (array1[i] !== array2[i]) {
- return false;
- }
- }
- return true;
- }
- function PDF17() {}
- PDF17.prototype = {
- checkOwnerPassword: function PDF17_checkOwnerPassword(password, ownerValidationSalt, userBytes, ownerPassword) {
- var hashData = new Uint8Array(password.length + 56);
- hashData.set(password, 0);
- hashData.set(ownerValidationSalt, password.length);
- hashData.set(userBytes, password.length + ownerValidationSalt.length);
- var result = calculateSHA256(hashData, 0, hashData.length);
- return compareByteArrays(result, ownerPassword);
- },
- checkUserPassword: function PDF17_checkUserPassword(password, userValidationSalt, userPassword) {
- var hashData = new Uint8Array(password.length + 8);
- hashData.set(password, 0);
- hashData.set(userValidationSalt, password.length);
- var result = calculateSHA256(hashData, 0, hashData.length);
- return compareByteArrays(result, userPassword);
- },
- getOwnerKey: function PDF17_getOwnerKey(password, ownerKeySalt, userBytes, ownerEncryption) {
- var hashData = new Uint8Array(password.length + 56);
- hashData.set(password, 0);
- hashData.set(ownerKeySalt, password.length);
- hashData.set(userBytes, password.length + ownerKeySalt.length);
- var key = calculateSHA256(hashData, 0, hashData.length);
- var cipher = new AES256Cipher(key);
- return cipher.decryptBlock(ownerEncryption, false, new Uint8Array(16));
- },
- getUserKey: function PDF17_getUserKey(password, userKeySalt, userEncryption) {
- var hashData = new Uint8Array(password.length + 8);
- hashData.set(password, 0);
- hashData.set(userKeySalt, password.length);
- var key = calculateSHA256(hashData, 0, hashData.length);
- var cipher = new AES256Cipher(key);
- return cipher.decryptBlock(userEncryption, false, new Uint8Array(16));
- }
- };
- return PDF17;
-}();
-var PDF20 = function PDF20Closure() {
- function concatArrays(array1, array2) {
- var t = new Uint8Array(array1.length + array2.length);
- t.set(array1, 0);
- t.set(array2, array1.length);
- return t;
- }
- function calculatePDF20Hash(password, input, userBytes) {
- var k = calculateSHA256(input, 0, input.length).subarray(0, 32);
- var e = [0];
- var i = 0;
- while (i < 64 || e[e.length - 1] > i - 32) {
- var arrayLength = password.length + k.length + userBytes.length;
- var k1 = new Uint8Array(arrayLength * 64);
- var array = concatArrays(password, k);
- array = concatArrays(array, userBytes);
- for (var j = 0, pos = 0; j < 64; j++, pos += arrayLength) {
- k1.set(array, pos);
- }
- var cipher = new AES128Cipher(k.subarray(0, 16));
- e = cipher.encrypt(k1, k.subarray(16, 32));
- var remainder = 0;
- for (var z = 0; z < 16; z++) {
- remainder *= 256 % 3;
- remainder %= 3;
- remainder += (e[z] >>> 0) % 3;
- remainder %= 3;
- }
- if (remainder === 0) {
- k = calculateSHA256(e, 0, e.length);
- } else if (remainder === 1) {
- k = calculateSHA384(e, 0, e.length);
- } else if (remainder === 2) {
- k = calculateSHA512(e, 0, e.length);
- }
- i++;
- }
- return k.subarray(0, 32);
- }
- function PDF20() {}
- function compareByteArrays(array1, array2) {
- if (array1.length !== array2.length) {
- return false;
- }
- for (var i = 0; i < array1.length; i++) {
- if (array1[i] !== array2[i]) {
- return false;
- }
- }
- return true;
- }
- PDF20.prototype = {
- hash: function PDF20_hash(password, concatBytes, userBytes) {
- return calculatePDF20Hash(password, concatBytes, userBytes);
- },
- checkOwnerPassword: function PDF20_checkOwnerPassword(password, ownerValidationSalt, userBytes, ownerPassword) {
- var hashData = new Uint8Array(password.length + 56);
- hashData.set(password, 0);
- hashData.set(ownerValidationSalt, password.length);
- hashData.set(userBytes, password.length + ownerValidationSalt.length);
- var result = calculatePDF20Hash(password, hashData, userBytes);
- return compareByteArrays(result, ownerPassword);
- },
- checkUserPassword: function PDF20_checkUserPassword(password, userValidationSalt, userPassword) {
- var hashData = new Uint8Array(password.length + 8);
- hashData.set(password, 0);
- hashData.set(userValidationSalt, password.length);
- var result = calculatePDF20Hash(password, hashData, []);
- return compareByteArrays(result, userPassword);
- },
- getOwnerKey: function PDF20_getOwnerKey(password, ownerKeySalt, userBytes, ownerEncryption) {
- var hashData = new Uint8Array(password.length + 56);
- hashData.set(password, 0);
- hashData.set(ownerKeySalt, password.length);
- hashData.set(userBytes, password.length + ownerKeySalt.length);
- var key = calculatePDF20Hash(password, hashData, userBytes);
- var cipher = new AES256Cipher(key);
- return cipher.decryptBlock(ownerEncryption, false, new Uint8Array(16));
- },
- getUserKey: function PDF20_getUserKey(password, userKeySalt, userEncryption) {
- var hashData = new Uint8Array(password.length + 8);
- hashData.set(password, 0);
- hashData.set(userKeySalt, password.length);
- var key = calculatePDF20Hash(password, hashData, []);
- var cipher = new AES256Cipher(key);
- return cipher.decryptBlock(userEncryption, false, new Uint8Array(16));
- }
- };
- return PDF20;
-}();
-var CipherTransform = function CipherTransformClosure() {
- function CipherTransform(stringCipherConstructor, streamCipherConstructor) {
- this.StringCipherConstructor = stringCipherConstructor;
- this.StreamCipherConstructor = streamCipherConstructor;
- }
- CipherTransform.prototype = {
- createStream: function CipherTransform_createStream(stream, length) {
- var cipher = new this.StreamCipherConstructor();
- return new _stream.DecryptStream(stream, length, function cipherTransformDecryptStream(data, finalize) {
- return cipher.decryptBlock(data, finalize);
- });
- },
- decryptString: function CipherTransform_decryptString(s) {
- var cipher = new this.StringCipherConstructor();
- var data = (0, _util.stringToBytes)(s);
- data = cipher.decryptBlock(data, true);
- return (0, _util.bytesToString)(data);
- }
- };
- return CipherTransform;
-}();
-var CipherTransformFactory = function CipherTransformFactoryClosure() {
- var defaultPasswordBytes = new Uint8Array([0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08, 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A]);
- function createEncryptionKey20(revision, password, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms) {
- if (password) {
- var passwordLength = Math.min(127, password.length);
- password = password.subarray(0, passwordLength);
- } else {
- password = [];
- }
- var pdfAlgorithm;
- if (revision === 6) {
- pdfAlgorithm = new PDF20();
- } else {
- pdfAlgorithm = new PDF17();
- }
- if (pdfAlgorithm.checkUserPassword(password, userValidationSalt, userPassword)) {
- return pdfAlgorithm.getUserKey(password, userKeySalt, userEncryption);
- } else if (password.length && pdfAlgorithm.checkOwnerPassword(password, ownerValidationSalt, uBytes, ownerPassword)) {
- return pdfAlgorithm.getOwnerKey(password, ownerKeySalt, uBytes, ownerEncryption);
- }
- return null;
- }
- function prepareKeyData(fileId, password, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata) {
- var hashDataSize = 40 + ownerPassword.length + fileId.length;
- var hashData = new Uint8Array(hashDataSize),
- i = 0,
- j,
- n;
- if (password) {
- n = Math.min(32, password.length);
- for (; i < n; ++i) {
- hashData[i] = password[i];
- }
- }
- j = 0;
- while (i < 32) {
- hashData[i++] = defaultPasswordBytes[j++];
- }
- for (j = 0, n = ownerPassword.length; j < n; ++j) {
- hashData[i++] = ownerPassword[j];
- }
- hashData[i++] = flags & 0xFF;
- hashData[i++] = flags >> 8 & 0xFF;
- hashData[i++] = flags >> 16 & 0xFF;
- hashData[i++] = flags >>> 24 & 0xFF;
- for (j = 0, n = fileId.length; j < n; ++j) {
- hashData[i++] = fileId[j];
- }
- if (revision >= 4 && !encryptMetadata) {
- hashData[i++] = 0xFF;
- hashData[i++] = 0xFF;
- hashData[i++] = 0xFF;
- hashData[i++] = 0xFF;
- }
- var hash = calculateMD5(hashData, 0, i);
- var keyLengthInBytes = keyLength >> 3;
- if (revision >= 3) {
- for (j = 0; j < 50; ++j) {
- hash = calculateMD5(hash, 0, keyLengthInBytes);
- }
- }
- var encryptionKey = hash.subarray(0, keyLengthInBytes);
- var cipher, checkData;
- if (revision >= 3) {
- for (i = 0; i < 32; ++i) {
- hashData[i] = defaultPasswordBytes[i];
- }
- for (j = 0, n = fileId.length; j < n; ++j) {
- hashData[i++] = fileId[j];
- }
- cipher = new ARCFourCipher(encryptionKey);
- checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i));
- n = encryptionKey.length;
- var derivedKey = new Uint8Array(n),
- k;
- for (j = 1; j <= 19; ++j) {
- for (k = 0; k < n; ++k) {
- derivedKey[k] = encryptionKey[k] ^ j;
- }
- cipher = new ARCFourCipher(derivedKey);
- checkData = cipher.encryptBlock(checkData);
- }
- for (j = 0, n = checkData.length; j < n; ++j) {
- if (userPassword[j] !== checkData[j]) {
- return null;
- }
- }
- } else {
- cipher = new ARCFourCipher(encryptionKey);
- checkData = cipher.encryptBlock(defaultPasswordBytes);
- for (j = 0, n = checkData.length; j < n; ++j) {
- if (userPassword[j] !== checkData[j]) {
- return null;
- }
- }
- }
- return encryptionKey;
- }
- function decodeUserPassword(password, ownerPassword, revision, keyLength) {
- var hashData = new Uint8Array(32),
- i = 0,
- j,
- n;
- n = Math.min(32, password.length);
- for (; i < n; ++i) {
- hashData[i] = password[i];
- }
- j = 0;
- while (i < 32) {
- hashData[i++] = defaultPasswordBytes[j++];
- }
- var hash = calculateMD5(hashData, 0, i);
- var keyLengthInBytes = keyLength >> 3;
- if (revision >= 3) {
- for (j = 0; j < 50; ++j) {
- hash = calculateMD5(hash, 0, hash.length);
- }
- }
- var cipher, userPassword;
- if (revision >= 3) {
- userPassword = ownerPassword;
- var derivedKey = new Uint8Array(keyLengthInBytes),
- k;
- for (j = 19; j >= 0; j--) {
- for (k = 0; k < keyLengthInBytes; ++k) {
- derivedKey[k] = hash[k] ^ j;
- }
- cipher = new ARCFourCipher(derivedKey);
- userPassword = cipher.encryptBlock(userPassword);
- }
- } else {
- cipher = new ARCFourCipher(hash.subarray(0, keyLengthInBytes));
- userPassword = cipher.encryptBlock(ownerPassword);
- }
- return userPassword;
- }
- var identityName = _primitives.Name.get('Identity');
- function CipherTransformFactory(dict, fileId, password) {
- var filter = dict.get('Filter');
- if (!(0, _primitives.isName)(filter, 'Standard')) {
- throw new _util.FormatError('unknown encryption method');
- }
- this.dict = dict;
- var algorithm = dict.get('V');
- if (!Number.isInteger(algorithm) || algorithm !== 1 && algorithm !== 2 && algorithm !== 4 && algorithm !== 5) {
- throw new _util.FormatError('unsupported encryption algorithm');
- }
- this.algorithm = algorithm;
- var keyLength = dict.get('Length');
- if (!keyLength) {
- if (algorithm <= 3) {
- keyLength = 40;
- } else {
- var cfDict = dict.get('CF');
- var streamCryptoName = dict.get('StmF');
- if ((0, _primitives.isDict)(cfDict) && (0, _primitives.isName)(streamCryptoName)) {
- cfDict.suppressEncryption = true;
- var handlerDict = cfDict.get(streamCryptoName.name);
- keyLength = handlerDict && handlerDict.get('Length') || 128;
- if (keyLength < 40) {
- keyLength <<= 3;
- }
- }
- }
- }
- if (!Number.isInteger(keyLength) || keyLength < 40 || keyLength % 8 !== 0) {
- throw new _util.FormatError('invalid key length');
- }
- var ownerPassword = (0, _util.stringToBytes)(dict.get('O')).subarray(0, 32);
- var userPassword = (0, _util.stringToBytes)(dict.get('U')).subarray(0, 32);
- var flags = dict.get('P');
- var revision = dict.get('R');
- var encryptMetadata = (algorithm === 4 || algorithm === 5) && dict.get('EncryptMetadata') !== false;
- this.encryptMetadata = encryptMetadata;
- var fileIdBytes = (0, _util.stringToBytes)(fileId);
- var passwordBytes;
- if (password) {
- if (revision === 6) {
- try {
- password = (0, _util.utf8StringToString)(password);
- } catch (ex) {
- (0, _util.warn)('CipherTransformFactory: ' + 'Unable to convert UTF8 encoded password.');
- }
- }
- passwordBytes = (0, _util.stringToBytes)(password);
- }
- var encryptionKey;
- if (algorithm !== 5) {
- encryptionKey = prepareKeyData(fileIdBytes, passwordBytes, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata);
- } else {
- var ownerValidationSalt = (0, _util.stringToBytes)(dict.get('O')).subarray(32, 40);
- var ownerKeySalt = (0, _util.stringToBytes)(dict.get('O')).subarray(40, 48);
- var uBytes = (0, _util.stringToBytes)(dict.get('U')).subarray(0, 48);
- var userValidationSalt = (0, _util.stringToBytes)(dict.get('U')).subarray(32, 40);
- var userKeySalt = (0, _util.stringToBytes)(dict.get('U')).subarray(40, 48);
- var ownerEncryption = (0, _util.stringToBytes)(dict.get('OE'));
- var userEncryption = (0, _util.stringToBytes)(dict.get('UE'));
- var perms = (0, _util.stringToBytes)(dict.get('Perms'));
- encryptionKey = createEncryptionKey20(revision, passwordBytes, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms);
- }
- if (!encryptionKey && !password) {
- throw new _util.PasswordException('No password given', _util.PasswordResponses.NEED_PASSWORD);
- } else if (!encryptionKey && password) {
- var decodedPassword = decodeUserPassword(passwordBytes, ownerPassword, revision, keyLength);
- encryptionKey = prepareKeyData(fileIdBytes, decodedPassword, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata);
- }
- if (!encryptionKey) {
- throw new _util.PasswordException('Incorrect Password', _util.PasswordResponses.INCORRECT_PASSWORD);
- }
- this.encryptionKey = encryptionKey;
- if (algorithm >= 4) {
- var cf = dict.get('CF');
- if ((0, _primitives.isDict)(cf)) {
- cf.suppressEncryption = true;
- }
- this.cf = cf;
- this.stmf = dict.get('StmF') || identityName;
- this.strf = dict.get('StrF') || identityName;
- this.eff = dict.get('EFF') || this.stmf;
- }
- }
- function buildObjectKey(num, gen, encryptionKey, isAes) {
- var key = new Uint8Array(encryptionKey.length + 9),
- i,
- n;
- for (i = 0, n = encryptionKey.length; i < n; ++i) {
- key[i] = encryptionKey[i];
- }
- key[i++] = num & 0xFF;
- key[i++] = num >> 8 & 0xFF;
- key[i++] = num >> 16 & 0xFF;
- key[i++] = gen & 0xFF;
- key[i++] = gen >> 8 & 0xFF;
- if (isAes) {
- key[i++] = 0x73;
- key[i++] = 0x41;
- key[i++] = 0x6C;
- key[i++] = 0x54;
- }
- var hash = calculateMD5(key, 0, i);
- return hash.subarray(0, Math.min(encryptionKey.length + 5, 16));
- }
- function buildCipherConstructor(cf, name, num, gen, key) {
- if (!(0, _primitives.isName)(name)) {
- throw new _util.FormatError('Invalid crypt filter name.');
- }
- var cryptFilter = cf.get(name.name);
- var cfm;
- if (cryptFilter !== null && cryptFilter !== undefined) {
- cfm = cryptFilter.get('CFM');
- }
- if (!cfm || cfm.name === 'None') {
- return function cipherTransformFactoryBuildCipherConstructorNone() {
- return new NullCipher();
- };
- }
- if (cfm.name === 'V2') {
- return function cipherTransformFactoryBuildCipherConstructorV2() {
- return new ARCFourCipher(buildObjectKey(num, gen, key, false));
- };
- }
- if (cfm.name === 'AESV2') {
- return function cipherTransformFactoryBuildCipherConstructorAESV2() {
- return new AES128Cipher(buildObjectKey(num, gen, key, true));
- };
- }
- if (cfm.name === 'AESV3') {
- return function cipherTransformFactoryBuildCipherConstructorAESV3() {
- return new AES256Cipher(key);
- };
- }
- throw new _util.FormatError('Unknown crypto method');
- }
- CipherTransformFactory.prototype = {
- createCipherTransform: function CipherTransformFactory_createCipherTransform(num, gen) {
- if (this.algorithm === 4 || this.algorithm === 5) {
- return new CipherTransform(buildCipherConstructor(this.cf, this.stmf, num, gen, this.encryptionKey), buildCipherConstructor(this.cf, this.strf, num, gen, this.encryptionKey));
- }
- var key = buildObjectKey(num, gen, this.encryptionKey, false);
- var cipherConstructor = function buildCipherCipherConstructor() {
- return new ARCFourCipher(key);
- };
- return new CipherTransform(cipherConstructor, cipherConstructor);
- }
- };
- return CipherTransformFactory;
-}();
-exports.AES128Cipher = AES128Cipher;
-exports.AES256Cipher = AES256Cipher;
-exports.ARCFourCipher = ARCFourCipher;
-exports.CipherTransformFactory = CipherTransformFactory;
-exports.PDF17 = PDF17;
-exports.PDF20 = PDF20;
-exports.calculateMD5 = calculateMD5;
-exports.calculateSHA256 = calculateSHA256;
-exports.calculateSHA384 = calculateSHA384;
-exports.calculateSHA512 = calculateSHA512;
-
-/***/ }),
-/* 151 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.ColorSpace = undefined;
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-var _util = __w_pdfjs_require__(2);
-
-var _primitives = __w_pdfjs_require__(138);
-
-function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
-
-function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
- var COMPONENTS = 3;
- alpha01 = alpha01 !== 1 ? 0 : alpha01;
- var xRatio = w1 / w2;
- var yRatio = h1 / h2;
- var newIndex = 0,
- oldIndex = void 0;
- var xScaled = new Uint16Array(w2);
- var w1Scanline = w1 * COMPONENTS;
- for (var i = 0; i < w2; i++) {
- xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
- }
- for (var _i = 0; _i < h2; _i++) {
- var py = Math.floor(_i * yRatio) * w1Scanline;
- for (var j = 0; j < w2; j++) {
- oldIndex = py + xScaled[j];
- dest[newIndex++] = src[oldIndex++];
- dest[newIndex++] = src[oldIndex++];
- dest[newIndex++] = src[oldIndex++];
- newIndex += alpha01;
- }
- }
-}
-
-var ColorSpace = function () {
- function ColorSpace(name, numComps) {
- _classCallCheck(this, ColorSpace);
-
- if (this.constructor === ColorSpace) {
- (0, _util.unreachable)('Cannot initialize ColorSpace.');
- }
- this.name = name;
- this.numComps = numComps;
- }
-
- _createClass(ColorSpace, [{
- key: 'getRgb',
- value: function getRgb(src, srcOffset) {
- var rgb = new Uint8ClampedArray(3);
- this.getRgbItem(src, srcOffset, rgb, 0);
- return rgb;
- }
- }, {
- key: 'getRgbItem',
- value: function getRgbItem(src, srcOffset, dest, destOffset) {
- (0, _util.unreachable)('Should not call ColorSpace.getRgbItem');
- }
- }, {
- key: 'getRgbBuffer',
- value: function getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
- (0, _util.unreachable)('Should not call ColorSpace.getRgbBuffer');
- }
- }, {
- key: 'getOutputLength',
- value: function getOutputLength(inputLength, alpha01) {
- (0, _util.unreachable)('Should not call ColorSpace.getOutputLength');
- }
- }, {
- key: 'isPassthrough',
- value: function isPassthrough(bits) {
- return false;
- }
- }, {
- key: 'fillRgb',
- value: function fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {
- var count = originalWidth * originalHeight;
- var rgbBuf = null;
- var numComponentColors = 1 << bpc;
- var needsResizing = originalHeight !== height || originalWidth !== width;
- if (this.isPassthrough(bpc)) {
- rgbBuf = comps;
- } else if (this.numComps === 1 && count > numComponentColors && this.name !== 'DeviceGray' && this.name !== 'DeviceRGB') {
- var allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);
- for (var i = 0; i < numComponentColors; i++) {
- allColors[i] = i;
- }
- var colorMap = new Uint8ClampedArray(numComponentColors * 3);
- this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bpc, 0);
- if (!needsResizing) {
- var destPos = 0;
- for (var _i2 = 0; _i2 < count; ++_i2) {
- var key = comps[_i2] * 3;
- dest[destPos++] = colorMap[key];
- dest[destPos++] = colorMap[key + 1];
- dest[destPos++] = colorMap[key + 2];
- destPos += alpha01;
- }
- } else {
- rgbBuf = new Uint8Array(count * 3);
- var rgbPos = 0;
- for (var _i3 = 0; _i3 < count; ++_i3) {
- var _key = comps[_i3] * 3;
- rgbBuf[rgbPos++] = colorMap[_key];
- rgbBuf[rgbPos++] = colorMap[_key + 1];
- rgbBuf[rgbPos++] = colorMap[_key + 2];
- }
- }
- } else {
- if (!needsResizing) {
- this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);
- } else {
- rgbBuf = new Uint8ClampedArray(count * 3);
- this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc, 0);
- }
- }
- if (rgbBuf) {
- if (needsResizing) {
- resizeRgbImage(rgbBuf, dest, originalWidth, originalHeight, width, height, alpha01);
- } else {
- var _destPos = 0,
- _rgbPos = 0;
- for (var _i4 = 0, ii = width * actualHeight; _i4 < ii; _i4++) {
- dest[_destPos++] = rgbBuf[_rgbPos++];
- dest[_destPos++] = rgbBuf[_rgbPos++];
- dest[_destPos++] = rgbBuf[_rgbPos++];
- _destPos += alpha01;
- }
- }
- }
- }
- }, {
- key: 'usesZeroToOneRange',
- get: function get() {
- return (0, _util.shadow)(this, 'usesZeroToOneRange', true);
- }
- }], [{
- key: 'parse',
- value: function parse(cs, xref, res, pdfFunctionFactory) {
- var IR = this.parseToIR(cs, xref, res, pdfFunctionFactory);
- return this.fromIR(IR);
- }
- }, {
- key: 'fromIR',
- value: function fromIR(IR) {
- var name = Array.isArray(IR) ? IR[0] : IR;
- var whitePoint = void 0,
- blackPoint = void 0,
- gamma = void 0;
- switch (name) {
- case 'DeviceGrayCS':
- return this.singletons.gray;
- case 'DeviceRgbCS':
- return this.singletons.rgb;
- case 'DeviceCmykCS':
- return this.singletons.cmyk;
- case 'CalGrayCS':
- whitePoint = IR[1];
- blackPoint = IR[2];
- gamma = IR[3];
- return new CalGrayCS(whitePoint, blackPoint, gamma);
- case 'CalRGBCS':
- whitePoint = IR[1];
- blackPoint = IR[2];
- gamma = IR[3];
- var matrix = IR[4];
- return new CalRGBCS(whitePoint, blackPoint, gamma, matrix);
- case 'PatternCS':
- var basePatternCS = IR[1];
- if (basePatternCS) {
- basePatternCS = this.fromIR(basePatternCS);
- }
- return new PatternCS(basePatternCS);
- case 'IndexedCS':
- var baseIndexedCS = IR[1];
- var hiVal = IR[2];
- var lookup = IR[3];
- return new IndexedCS(this.fromIR(baseIndexedCS), hiVal, lookup);
- case 'AlternateCS':
- var numComps = IR[1];
- var alt = IR[2];
- var tintFn = IR[3];
- return new AlternateCS(numComps, this.fromIR(alt), tintFn);
- case 'LabCS':
- whitePoint = IR[1];
- blackPoint = IR[2];
- var range = IR[3];
- return new LabCS(whitePoint, blackPoint, range);
- default:
- throw new _util.FormatError('Unknown colorspace name: ' + name);
- }
- }
- }, {
- key: 'parseToIR',
- value: function parseToIR(cs, xref) {
- var res = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
- var pdfFunctionFactory = arguments[3];
-
- cs = xref.fetchIfRef(cs);
- if ((0, _primitives.isName)(cs)) {
- switch (cs.name) {
- case 'DeviceGray':
- case 'G':
- return 'DeviceGrayCS';
- case 'DeviceRGB':
- case 'RGB':
- return 'DeviceRgbCS';
- case 'DeviceCMYK':
- case 'CMYK':
- return 'DeviceCmykCS';
- case 'Pattern':
- return ['PatternCS', null];
- default:
- if ((0, _primitives.isDict)(res)) {
- var colorSpaces = res.get('ColorSpace');
- if ((0, _primitives.isDict)(colorSpaces)) {
- var resCS = colorSpaces.get(cs.name);
- if (resCS) {
- if ((0, _primitives.isName)(resCS)) {
- return this.parseToIR(resCS, xref, res, pdfFunctionFactory);
- }
- cs = resCS;
- break;
- }
- }
- }
- throw new _util.FormatError('unrecognized colorspace ' + cs.name);
- }
- }
- if (Array.isArray(cs)) {
- var mode = xref.fetchIfRef(cs[0]).name;
- var numComps = void 0,
- params = void 0,
- alt = void 0,
- whitePoint = void 0,
- blackPoint = void 0,
- gamma = void 0;
- switch (mode) {
- case 'DeviceGray':
- case 'G':
- return 'DeviceGrayCS';
- case 'DeviceRGB':
- case 'RGB':
- return 'DeviceRgbCS';
- case 'DeviceCMYK':
- case 'CMYK':
- return 'DeviceCmykCS';
- case 'CalGray':
- params = xref.fetchIfRef(cs[1]);
- whitePoint = params.getArray('WhitePoint');
- blackPoint = params.getArray('BlackPoint');
- gamma = params.get('Gamma');
- return ['CalGrayCS', whitePoint, blackPoint, gamma];
- case 'CalRGB':
- params = xref.fetchIfRef(cs[1]);
- whitePoint = params.getArray('WhitePoint');
- blackPoint = params.getArray('BlackPoint');
- gamma = params.getArray('Gamma');
- var matrix = params.getArray('Matrix');
- return ['CalRGBCS', whitePoint, blackPoint, gamma, matrix];
- case 'ICCBased':
- var stream = xref.fetchIfRef(cs[1]);
- var dict = stream.dict;
- numComps = dict.get('N');
- alt = dict.get('Alternate');
- if (alt) {
- var altIR = this.parseToIR(alt, xref, res, pdfFunctionFactory);
- var altCS = this.fromIR(altIR, pdfFunctionFactory);
- if (altCS.numComps === numComps) {
- return altIR;
- }
- (0, _util.warn)('ICCBased color space: Ignoring incorrect /Alternate entry.');
- }
- if (numComps === 1) {
- return 'DeviceGrayCS';
- } else if (numComps === 3) {
- return 'DeviceRgbCS';
- } else if (numComps === 4) {
- return 'DeviceCmykCS';
- }
- break;
- case 'Pattern':
- var basePatternCS = cs[1] || null;
- if (basePatternCS) {
- basePatternCS = this.parseToIR(basePatternCS, xref, res, pdfFunctionFactory);
- }
- return ['PatternCS', basePatternCS];
- case 'Indexed':
- case 'I':
- var baseIndexedCS = this.parseToIR(cs[1], xref, res, pdfFunctionFactory);
- var hiVal = xref.fetchIfRef(cs[2]) + 1;
- var lookup = xref.fetchIfRef(cs[3]);
- if ((0, _primitives.isStream)(lookup)) {
- lookup = lookup.getBytes();
- }
- return ['IndexedCS', baseIndexedCS, hiVal, lookup];
- case 'Separation':
- case 'DeviceN':
- var name = xref.fetchIfRef(cs[1]);
- numComps = Array.isArray(name) ? name.length : 1;
- alt = this.parseToIR(cs[2], xref, res, pdfFunctionFactory);
- var tintFn = pdfFunctionFactory.create(xref.fetchIfRef(cs[3]));
- return ['AlternateCS', numComps, alt, tintFn];
- case 'Lab':
- params = xref.fetchIfRef(cs[1]);
- whitePoint = params.getArray('WhitePoint');
- blackPoint = params.getArray('BlackPoint');
- var range = params.getArray('Range');
- return ['LabCS', whitePoint, blackPoint, range];
- default:
- throw new _util.FormatError('unimplemented color space object "' + mode + '"');
- }
- }
- throw new _util.FormatError('unrecognized color space object: "' + cs + '"');
- }
- }, {
- key: 'isDefaultDecode',
- value: function isDefaultDecode(decode, n) {
- if (!Array.isArray(decode)) {
- return true;
- }
- if (n * 2 !== decode.length) {
- (0, _util.warn)('The decode map is not the correct length');
- return true;
- }
- for (var i = 0, ii = decode.length; i < ii; i += 2) {
- if (decode[i] !== 0 || decode[i + 1] !== 1) {
- return false;
- }
- }
- return true;
- }
- }, {
- key: 'singletons',
- get: function get() {
- return (0, _util.shadow)(this, 'singletons', {
- get gray() {
- return (0, _util.shadow)(this, 'gray', new DeviceGrayCS());
- },
- get rgb() {
- return (0, _util.shadow)(this, 'rgb', new DeviceRgbCS());
- },
- get cmyk() {
- return (0, _util.shadow)(this, 'cmyk', new DeviceCmykCS());
- }
- });
- }
- }]);
-
- return ColorSpace;
-}();
-
-var AlternateCS = function (_ColorSpace) {
- _inherits(AlternateCS, _ColorSpace);
-
- function AlternateCS(numComps, base, tintFn) {
- _classCallCheck(this, AlternateCS);
-
- var _this = _possibleConstructorReturn(this, (AlternateCS.__proto__ || Object.getPrototypeOf(AlternateCS)).call(this, 'Alternate', numComps));
-
- _this.base = base;
- _this.tintFn = tintFn;
- _this.tmpBuf = new Float32Array(base.numComps);
- return _this;
- }
-
- _createClass(AlternateCS, [{
- key: 'getRgbItem',
- value: function getRgbItem(src, srcOffset, dest, destOffset) {
- var tmpBuf = this.tmpBuf;
- this.tintFn(src, srcOffset, tmpBuf, 0);
- this.base.getRgbItem(tmpBuf, 0, dest, destOffset);
- }
- }, {
- key: 'getRgbBuffer',
- value: function getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
- var tintFn = this.tintFn;
- var base = this.base;
- var scale = 1 / ((1 << bits) - 1);
- var baseNumComps = base.numComps;
- var usesZeroToOneRange = base.usesZeroToOneRange;
- var isPassthrough = (base.isPassthrough(8) || !usesZeroToOneRange) && alpha01 === 0;
- var pos = isPassthrough ? destOffset : 0;
- var baseBuf = isPassthrough ? dest : new Uint8ClampedArray(baseNumComps * count);
- var numComps = this.numComps;
- var scaled = new Float32Array(numComps);
- var tinted = new Float32Array(baseNumComps);
- var i = void 0,
- j = void 0;
- for (i = 0; i < count; i++) {
- for (j = 0; j < numComps; j++) {
- scaled[j] = src[srcOffset++] * scale;
- }
- tintFn(scaled, 0, tinted, 0);
- if (usesZeroToOneRange) {
- for (j = 0; j < baseNumComps; j++) {
- baseBuf[pos++] = tinted[j] * 255;
- }
- } else {
- base.getRgbItem(tinted, 0, baseBuf, pos);
- pos += baseNumComps;
- }
- }
- if (!isPassthrough) {
- base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8, alpha01);
- }
- }
- }, {
- key: 'getOutputLength',
- value: function getOutputLength(inputLength, alpha01) {
- return this.base.getOutputLength(inputLength * this.base.numComps / this.numComps, alpha01);
- }
- }, {
- key: 'isDefaultDecode',
- value: function isDefaultDecode(decodeMap) {
- return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
- }
- }]);
-
- return AlternateCS;
-}(ColorSpace);
-
-var PatternCS = function (_ColorSpace2) {
- _inherits(PatternCS, _ColorSpace2);
-
- function PatternCS(baseCS) {
- _classCallCheck(this, PatternCS);
-
- var _this2 = _possibleConstructorReturn(this, (PatternCS.__proto__ || Object.getPrototypeOf(PatternCS)).call(this, 'Pattern', null));
-
- _this2.base = baseCS;
- return _this2;
- }
-
- return PatternCS;
-}(ColorSpace);
-
-var IndexedCS = function (_ColorSpace3) {
- _inherits(IndexedCS, _ColorSpace3);
-
- function IndexedCS(base, highVal, lookup) {
- _classCallCheck(this, IndexedCS);
-
- var _this3 = _possibleConstructorReturn(this, (IndexedCS.__proto__ || Object.getPrototypeOf(IndexedCS)).call(this, 'Indexed', 1));
-
- _this3.base = base;
- _this3.highVal = highVal;
- var baseNumComps = base.numComps;
- var length = baseNumComps * highVal;
- if ((0, _primitives.isStream)(lookup)) {
- _this3.lookup = new Uint8Array(length);
- var bytes = lookup.getBytes(length);
- _this3.lookup.set(bytes);
- } else if ((0, _util.isString)(lookup)) {
- _this3.lookup = new Uint8Array(length);
- for (var i = 0; i < length; ++i) {
- _this3.lookup[i] = lookup.charCodeAt(i);
- }
- } else if (lookup instanceof Uint8Array) {
- _this3.lookup = lookup;
- } else {
- throw new _util.FormatError('Unrecognized lookup table: ' + lookup);
- }
- return _this3;
- }
-
- _createClass(IndexedCS, [{
- key: 'getRgbItem',
- value: function getRgbItem(src, srcOffset, dest, destOffset) {
- var numComps = this.base.numComps;
- var start = src[srcOffset] * numComps;
- this.base.getRgbBuffer(this.lookup, start, 1, dest, destOffset, 8, 0);
- }
- }, {
- key: 'getRgbBuffer',
- value: function getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
- var base = this.base;
- var numComps = base.numComps;
- var outputDelta = base.getOutputLength(numComps, alpha01);
- var lookup = this.lookup;
- for (var i = 0; i < count; ++i) {
- var lookupPos = src[srcOffset++] * numComps;
- base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8, alpha01);
- destOffset += outputDelta;
- }
- }
- }, {
- key: 'getOutputLength',
- value: function getOutputLength(inputLength, alpha01) {
- return this.base.getOutputLength(inputLength * this.base.numComps, alpha01);
- }
- }, {
- key: 'isDefaultDecode',
- value: function isDefaultDecode(decodeMap) {
- return true;
- }
- }]);
-
- return IndexedCS;
-}(ColorSpace);
-
-var DeviceGrayCS = function (_ColorSpace4) {
- _inherits(DeviceGrayCS, _ColorSpace4);
-
- function DeviceGrayCS() {
- _classCallCheck(this, DeviceGrayCS);
-
- return _possibleConstructorReturn(this, (DeviceGrayCS.__proto__ || Object.getPrototypeOf(DeviceGrayCS)).call(this, 'DeviceGray', 1));
- }
-
- _createClass(DeviceGrayCS, [{
- key: 'getRgbItem',
- value: function getRgbItem(src, srcOffset, dest, destOffset) {
- var c = src[srcOffset] * 255;
- dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c;
- }
- }, {
- key: 'getRgbBuffer',
- value: function getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
- var scale = 255 / ((1 << bits) - 1);
- var j = srcOffset,
- q = destOffset;
- for (var i = 0; i < count; ++i) {
- var c = scale * src[j++];
- dest[q++] = c;
- dest[q++] = c;
- dest[q++] = c;
- q += alpha01;
- }
- }
- }, {
- key: 'getOutputLength',
- value: function getOutputLength(inputLength, alpha01) {
- return inputLength * (3 + alpha01);
- }
- }, {
- key: 'isDefaultDecode',
- value: function isDefaultDecode(decodeMap) {
- return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
- }
- }]);
-
- return DeviceGrayCS;
-}(ColorSpace);
-
-var DeviceRgbCS = function (_ColorSpace5) {
- _inherits(DeviceRgbCS, _ColorSpace5);
-
- function DeviceRgbCS() {
- _classCallCheck(this, DeviceRgbCS);
-
- return _possibleConstructorReturn(this, (DeviceRgbCS.__proto__ || Object.getPrototypeOf(DeviceRgbCS)).call(this, 'DeviceRGB', 3));
- }
-
- _createClass(DeviceRgbCS, [{
- key: 'getRgbItem',
- value: function getRgbItem(src, srcOffset, dest, destOffset) {
- dest[destOffset] = src[srcOffset] * 255;
- dest[destOffset + 1] = src[srcOffset + 1] * 255;
- dest[destOffset + 2] = src[srcOffset + 2] * 255;
- }
- }, {
- key: 'getRgbBuffer',
- value: function getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
- if (bits === 8 && alpha01 === 0) {
- dest.set(src.subarray(srcOffset, srcOffset + count * 3), destOffset);
- return;
- }
- var scale = 255 / ((1 << bits) - 1);
- var j = srcOffset,
- q = destOffset;
- for (var i = 0; i < count; ++i) {
- dest[q++] = scale * src[j++];
- dest[q++] = scale * src[j++];
- dest[q++] = scale * src[j++];
- q += alpha01;
- }
- }
- }, {
- key: 'getOutputLength',
- value: function getOutputLength(inputLength, alpha01) {
- return inputLength * (3 + alpha01) / 3 | 0;
- }
- }, {
- key: 'isPassthrough',
- value: function isPassthrough(bits) {
- return bits === 8;
- }
- }, {
- key: 'isDefaultDecode',
- value: function isDefaultDecode(decodeMap) {
- return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
- }
- }]);
-
- return DeviceRgbCS;
-}(ColorSpace);
-
-var DeviceCmykCS = function DeviceCmykCSClosure() {
- function convertToRgb(src, srcOffset, srcScale, dest, destOffset) {
- var c = src[srcOffset] * srcScale;
- var m = src[srcOffset + 1] * srcScale;
- var y = src[srcOffset + 2] * srcScale;
- var k = src[srcOffset + 3] * srcScale;
- dest[destOffset] = 255 + c * (-4.387332384609988 * c + 54.48615194189176 * m + 18.82290502165302 * y + 212.25662451639585 * k + -285.2331026137004) + m * (1.7149763477362134 * m - 5.6096736904047315 * y + -17.873870861415444 * k - 5.497006427196366) + y * (-2.5217340131683033 * y - 21.248923337353073 * k + 17.5119270841813) + k * (-21.86122147463605 * k - 189.48180835922747);
- dest[destOffset + 1] = 255 + c * (8.841041422036149 * c + 60.118027045597366 * m + 6.871425592049007 * y + 31.159100130055922 * k + -79.2970844816548) + m * (-15.310361306967817 * m + 17.575251261109482 * y + 131.35250912493976 * k - 190.9453302588951) + y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) + k * (-20.737325471181034 * k - 187.80453709719578);
- dest[destOffset + 2] = 255 + c * (0.8842522430003296 * c + 8.078677503112928 * m + 30.89978309703729 * y - 0.23883238689178934 * k + -14.183576799673286) + m * (10.49593273432072 * m + 63.02378494754052 * y + 50.606957656360734 * k - 112.23884253719248) + y * (0.03296041114873217 * y + 115.60384449646641 * k + -193.58209356861505) + k * (-22.33816807309886 * k - 180.12613974708367);
- }
-
- var DeviceCmykCS = function (_ColorSpace6) {
- _inherits(DeviceCmykCS, _ColorSpace6);
-
- function DeviceCmykCS() {
- _classCallCheck(this, DeviceCmykCS);
-
- return _possibleConstructorReturn(this, (DeviceCmykCS.__proto__ || Object.getPrototypeOf(DeviceCmykCS)).call(this, 'DeviceCMYK', 4));
- }
-
- _createClass(DeviceCmykCS, [{
- key: 'getRgbItem',
- value: function getRgbItem(src, srcOffset, dest, destOffset) {
- convertToRgb(src, srcOffset, 1, dest, destOffset);
- }
- }, {
- key: 'getRgbBuffer',
- value: function getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
- var scale = 1 / ((1 << bits) - 1);
- for (var i = 0; i < count; i++) {
- convertToRgb(src, srcOffset, scale, dest, destOffset);
- srcOffset += 4;
- destOffset += 3 + alpha01;
- }
- }
- }, {
- key: 'getOutputLength',
- value: function getOutputLength(inputLength, alpha01) {
- return inputLength / 4 * (3 + alpha01) | 0;
- }
- }, {
- key: 'isDefaultDecode',
- value: function isDefaultDecode(decodeMap) {
- return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
- }
- }]);
-
- return DeviceCmykCS;
- }(ColorSpace);
-
- return DeviceCmykCS;
-}();
-var CalGrayCS = function CalGrayCSClosure() {
- function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) {
- var A = src[srcOffset] * scale;
- var AG = Math.pow(A, cs.G);
- var L = cs.YW * AG;
- var val = Math.max(295.8 * Math.pow(L, 0.333333333333333333) - 40.8, 0);
- dest[destOffset] = val;
- dest[destOffset + 1] = val;
- dest[destOffset + 2] = val;
- }
-
- var CalGrayCS = function (_ColorSpace7) {
- _inherits(CalGrayCS, _ColorSpace7);
-
- function CalGrayCS(whitePoint, blackPoint, gamma) {
- _classCallCheck(this, CalGrayCS);
-
- var _this7 = _possibleConstructorReturn(this, (CalGrayCS.__proto__ || Object.getPrototypeOf(CalGrayCS)).call(this, 'CalGray', 1));
-
- if (!whitePoint) {
- throw new _util.FormatError('WhitePoint missing - required for color space CalGray');
- }
- blackPoint = blackPoint || [0, 0, 0];
- gamma = gamma || 1;
- _this7.XW = whitePoint[0];
- _this7.YW = whitePoint[1];
- _this7.ZW = whitePoint[2];
- _this7.XB = blackPoint[0];
- _this7.YB = blackPoint[1];
- _this7.ZB = blackPoint[2];
- _this7.G = gamma;
- if (_this7.XW < 0 || _this7.ZW < 0 || _this7.YW !== 1) {
- throw new _util.FormatError('Invalid WhitePoint components for ' + _this7.name + ', no fallback available');
- }
- if (_this7.XB < 0 || _this7.YB < 0 || _this7.ZB < 0) {
- (0, _util.info)('Invalid BlackPoint for ' + _this7.name + ', falling back to default.');
- _this7.XB = _this7.YB = _this7.ZB = 0;
- }
- if (_this7.XB !== 0 || _this7.YB !== 0 || _this7.ZB !== 0) {
- (0, _util.warn)(_this7.name + ', BlackPoint: XB: ' + _this7.XB + ', YB: ' + _this7.YB + ', ' + ('ZB: ' + _this7.ZB + ', only default values are supported.'));
- }
- if (_this7.G < 1) {
- (0, _util.info)('Invalid Gamma: ' + _this7.G + ' for ' + _this7.name + ', ' + 'falling back to default.');
- _this7.G = 1;
- }
- return _this7;
- }
-
- _createClass(CalGrayCS, [{
- key: 'getRgbItem',
- value: function getRgbItem(src, srcOffset, dest, destOffset) {
- convertToRgb(this, src, srcOffset, dest, destOffset, 1);
- }
- }, {
- key: 'getRgbBuffer',
- value: function getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
- var scale = 1 / ((1 << bits) - 1);
- for (var i = 0; i < count; ++i) {
- convertToRgb(this, src, srcOffset, dest, destOffset, scale);
- srcOffset += 1;
- destOffset += 3 + alpha01;
- }
- }
- }, {
- key: 'getOutputLength',
- value: function getOutputLength(inputLength, alpha01) {
- return inputLength * (3 + alpha01);
- }
- }, {
- key: 'isDefaultDecode',
- value: function isDefaultDecode(decodeMap) {
- return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
- }
- }]);
-
- return CalGrayCS;
- }(ColorSpace);
-
- return CalGrayCS;
-}();
-var CalRGBCS = function CalRGBCSClosure() {
- var BRADFORD_SCALE_MATRIX = new Float32Array([0.8951, 0.2664, -0.1614, -0.7502, 1.7135, 0.0367, 0.0389, -0.0685, 1.0296]);
- var BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([0.9869929, -0.1470543, 0.1599627, 0.4323053, 0.5183603, 0.0492912, -0.0085287, 0.0400428, 0.9684867]);
- var SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([3.2404542, -1.5371385, -0.4985314, -0.9692660, 1.8760108, 0.0415560, 0.0556434, -0.2040259, 1.0572252]);
- var FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);
- var tempNormalizeMatrix = new Float32Array(3);
- var tempConvertMatrix1 = new Float32Array(3);
- var tempConvertMatrix2 = new Float32Array(3);
- var DECODE_L_CONSTANT = Math.pow((8 + 16) / 116, 3) / 8.0;
- function matrixProduct(a, b, result) {
- result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
- result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
- result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
- }
- function convertToFlat(sourceWhitePoint, LMS, result) {
- result[0] = LMS[0] * 1 / sourceWhitePoint[0];
- result[1] = LMS[1] * 1 / sourceWhitePoint[1];
- result[2] = LMS[2] * 1 / sourceWhitePoint[2];
- }
- function convertToD65(sourceWhitePoint, LMS, result) {
- var D65X = 0.95047;
- var D65Y = 1;
- var D65Z = 1.08883;
- result[0] = LMS[0] * D65X / sourceWhitePoint[0];
- result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
- result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
- }
- function sRGBTransferFunction(color) {
- if (color <= 0.0031308) {
- return adjustToRange(0, 1, 12.92 * color);
- }
- return adjustToRange(0, 1, (1 + 0.055) * Math.pow(color, 1 / 2.4) - 0.055);
- }
- function adjustToRange(min, max, value) {
- return Math.max(min, Math.min(max, value));
- }
- function decodeL(L) {
- if (L < 0) {
- return -decodeL(-L);
- }
- if (L > 8.0) {
- return Math.pow((L + 16) / 116, 3);
- }
- return L * DECODE_L_CONSTANT;
- }
- function compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
- if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {
- result[0] = XYZ_Flat[0];
- result[1] = XYZ_Flat[1];
- result[2] = XYZ_Flat[2];
- return;
- }
- var zeroDecodeL = decodeL(0);
- var X_DST = zeroDecodeL;
- var X_SRC = decodeL(sourceBlackPoint[0]);
- var Y_DST = zeroDecodeL;
- var Y_SRC = decodeL(sourceBlackPoint[1]);
- var Z_DST = zeroDecodeL;
- var Z_SRC = decodeL(sourceBlackPoint[2]);
- var X_Scale = (1 - X_DST) / (1 - X_SRC);
- var X_Offset = 1 - X_Scale;
- var Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
- var Y_Offset = 1 - Y_Scale;
- var Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
- var Z_Offset = 1 - Z_Scale;
- result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
- result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
- result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
- }
- function normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
- if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
- result[0] = XYZ_In[0];
- result[1] = XYZ_In[1];
- result[2] = XYZ_In[2];
- return;
- }
- var LMS = result;
- matrixProduct(BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
- var LMS_Flat = tempNormalizeMatrix;
- convertToFlat(sourceWhitePoint, LMS, LMS_Flat);
- matrixProduct(BRADFORD_SCALE_INVERSE_MATRIX, LMS_Flat, result);
- }
- function normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
- var LMS = result;
- matrixProduct(BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
- var LMS_D65 = tempNormalizeMatrix;
- convertToD65(sourceWhitePoint, LMS, LMS_D65);
- matrixProduct(BRADFORD_SCALE_INVERSE_MATRIX, LMS_D65, result);
- }
- function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) {
- var A = adjustToRange(0, 1, src[srcOffset] * scale);
- var B = adjustToRange(0, 1, src[srcOffset + 1] * scale);
- var C = adjustToRange(0, 1, src[srcOffset + 2] * scale);
- var AGR = Math.pow(A, cs.GR);
- var BGG = Math.pow(B, cs.GG);
- var CGB = Math.pow(C, cs.GB);
- var X = cs.MXA * AGR + cs.MXB * BGG + cs.MXC * CGB;
- var Y = cs.MYA * AGR + cs.MYB * BGG + cs.MYC * CGB;
- var Z = cs.MZA * AGR + cs.MZB * BGG + cs.MZC * CGB;
- var XYZ = tempConvertMatrix1;
- XYZ[0] = X;
- XYZ[1] = Y;
- XYZ[2] = Z;
- var XYZ_Flat = tempConvertMatrix2;
- normalizeWhitePointToFlat(cs.whitePoint, XYZ, XYZ_Flat);
- var XYZ_Black = tempConvertMatrix1;
- compensateBlackPoint(cs.blackPoint, XYZ_Flat, XYZ_Black);
- var XYZ_D65 = tempConvertMatrix2;
- normalizeWhitePointToD65(FLAT_WHITEPOINT_MATRIX, XYZ_Black, XYZ_D65);
- var SRGB = tempConvertMatrix1;
- matrixProduct(SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
- dest[destOffset] = sRGBTransferFunction(SRGB[0]) * 255;
- dest[destOffset + 1] = sRGBTransferFunction(SRGB[1]) * 255;
- dest[destOffset + 2] = sRGBTransferFunction(SRGB[2]) * 255;
- }
-
- var CalRGBCS = function (_ColorSpace8) {
- _inherits(CalRGBCS, _ColorSpace8);
-
- function CalRGBCS(whitePoint, blackPoint, gamma, matrix) {
- _classCallCheck(this, CalRGBCS);
-
- var _this8 = _possibleConstructorReturn(this, (CalRGBCS.__proto__ || Object.getPrototypeOf(CalRGBCS)).call(this, 'CalRGB', 3));
-
- if (!whitePoint) {
- throw new _util.FormatError('WhitePoint missing - required for color space CalRGB');
- }
- blackPoint = blackPoint || new Float32Array(3);
- gamma = gamma || new Float32Array([1, 1, 1]);
- matrix = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
- var XW = whitePoint[0];
- var YW = whitePoint[1];
- var ZW = whitePoint[2];
- _this8.whitePoint = whitePoint;
- var XB = blackPoint[0];
- var YB = blackPoint[1];
- var ZB = blackPoint[2];
- _this8.blackPoint = blackPoint;
- _this8.GR = gamma[0];
- _this8.GG = gamma[1];
- _this8.GB = gamma[2];
- _this8.MXA = matrix[0];
- _this8.MYA = matrix[1];
- _this8.MZA = matrix[2];
- _this8.MXB = matrix[3];
- _this8.MYB = matrix[4];
- _this8.MZB = matrix[5];
- _this8.MXC = matrix[6];
- _this8.MYC = matrix[7];
- _this8.MZC = matrix[8];
- if (XW < 0 || ZW < 0 || YW !== 1) {
- throw new _util.FormatError('Invalid WhitePoint components for ' + _this8.name + ', no fallback available');
- }
- if (XB < 0 || YB < 0 || ZB < 0) {
- (0, _util.info)('Invalid BlackPoint for ' + _this8.name + ' [' + XB + ', ' + YB + ', ' + ZB + '], ' + 'falling back to default.');
- _this8.blackPoint = new Float32Array(3);
- }
- if (_this8.GR < 0 || _this8.GG < 0 || _this8.GB < 0) {
- (0, _util.info)('Invalid Gamma [' + _this8.GR + ', ' + _this8.GG + ', ' + _this8.GB + '] for ' + (_this8.name + ', falling back to default.'));
- _this8.GR = _this8.GG = _this8.GB = 1;
- }
- return _this8;
- }
-
- _createClass(CalRGBCS, [{
- key: 'getRgbItem',
- value: function getRgbItem(src, srcOffset, dest, destOffset) {
- convertToRgb(this, src, srcOffset, dest, destOffset, 1);
- }
- }, {
- key: 'getRgbBuffer',
- value: function getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
- var scale = 1 / ((1 << bits) - 1);
- for (var i = 0; i < count; ++i) {
- convertToRgb(this, src, srcOffset, dest, destOffset, scale);
- srcOffset += 3;
- destOffset += 3 + alpha01;
- }
- }
- }, {
- key: 'getOutputLength',
- value: function getOutputLength(inputLength, alpha01) {
- return inputLength * (3 + alpha01) / 3 | 0;
- }
- }, {
- key: 'isDefaultDecode',
- value: function isDefaultDecode(decodeMap) {
- return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
- }
- }]);
-
- return CalRGBCS;
- }(ColorSpace);
-
- return CalRGBCS;
-}();
-var LabCS = function LabCSClosure() {
- function fn_g(x) {
- var result = void 0;
- if (x >= 6 / 29) {
- result = x * x * x;
- } else {
- result = 108 / 841 * (x - 4 / 29);
- }
- return result;
- }
- function decode(value, high1, low2, high2) {
- return low2 + value * (high2 - low2) / high1;
- }
- function convertToRgb(cs, src, srcOffset, maxVal, dest, destOffset) {
- var Ls = src[srcOffset];
- var as = src[srcOffset + 1];
- var bs = src[srcOffset + 2];
- if (maxVal !== false) {
- Ls = decode(Ls, maxVal, 0, 100);
- as = decode(as, maxVal, cs.amin, cs.amax);
- bs = decode(bs, maxVal, cs.bmin, cs.bmax);
- }
- as = as > cs.amax ? cs.amax : as < cs.amin ? cs.amin : as;
- bs = bs > cs.bmax ? cs.bmax : bs < cs.bmin ? cs.bmin : bs;
- var M = (Ls + 16) / 116;
- var L = M + as / 500;
- var N = M - bs / 200;
- var X = cs.XW * fn_g(L);
- var Y = cs.YW * fn_g(M);
- var Z = cs.ZW * fn_g(N);
- var r = void 0,
- g = void 0,
- b = void 0;
- if (cs.ZW < 1) {
- r = X * 3.1339 + Y * -1.6170 + Z * -0.4906;
- g = X * -0.9785 + Y * 1.9160 + Z * 0.0333;
- b = X * 0.0720 + Y * -0.2290 + Z * 1.4057;
- } else {
- r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
- g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
- b = X * 0.0557 + Y * -0.2040 + Z * 1.0570;
- }
- dest[destOffset] = Math.sqrt(r) * 255;
- dest[destOffset + 1] = Math.sqrt(g) * 255;
- dest[destOffset + 2] = Math.sqrt(b) * 255;
- }
-
- var LabCS = function (_ColorSpace9) {
- _inherits(LabCS, _ColorSpace9);
-
- function LabCS(whitePoint, blackPoint, range) {
- _classCallCheck(this, LabCS);
-
- var _this9 = _possibleConstructorReturn(this, (LabCS.__proto__ || Object.getPrototypeOf(LabCS)).call(this, 'Lab', 3));
-
- if (!whitePoint) {
- throw new _util.FormatError('WhitePoint missing - required for color space Lab');
- }
- blackPoint = blackPoint || [0, 0, 0];
- range = range || [-100, 100, -100, 100];
- _this9.XW = whitePoint[0];
- _this9.YW = whitePoint[1];
- _this9.ZW = whitePoint[2];
- _this9.amin = range[0];
- _this9.amax = range[1];
- _this9.bmin = range[2];
- _this9.bmax = range[3];
- _this9.XB = blackPoint[0];
- _this9.YB = blackPoint[1];
- _this9.ZB = blackPoint[2];
- if (_this9.XW < 0 || _this9.ZW < 0 || _this9.YW !== 1) {
- throw new _util.FormatError('Invalid WhitePoint components, no fallback available');
- }
- if (_this9.XB < 0 || _this9.YB < 0 || _this9.ZB < 0) {
- (0, _util.info)('Invalid BlackPoint, falling back to default');
- _this9.XB = _this9.YB = _this9.ZB = 0;
- }
- if (_this9.amin > _this9.amax || _this9.bmin > _this9.bmax) {
- (0, _util.info)('Invalid Range, falling back to defaults');
- _this9.amin = -100;
- _this9.amax = 100;
- _this9.bmin = -100;
- _this9.bmax = 100;
- }
- return _this9;
- }
-
- _createClass(LabCS, [{
- key: 'getRgbItem',
- value: function getRgbItem(src, srcOffset, dest, destOffset) {
- convertToRgb(this, src, srcOffset, false, dest, destOffset);
- }
- }, {
- key: 'getRgbBuffer',
- value: function getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
- var maxVal = (1 << bits) - 1;
- for (var i = 0; i < count; i++) {
- convertToRgb(this, src, srcOffset, maxVal, dest, destOffset);
- srcOffset += 3;
- destOffset += 3 + alpha01;
- }
- }
- }, {
- key: 'getOutputLength',
- value: function getOutputLength(inputLength, alpha01) {
- return inputLength * (3 + alpha01) / 3 | 0;
- }
- }, {
- key: 'isDefaultDecode',
- value: function isDefaultDecode(decodeMap) {
- return true;
- }
- }, {
- key: 'usesZeroToOneRange',
- get: function get() {
- return (0, _util.shadow)(this, 'usesZeroToOneRange', false);
- }
- }]);
-
- return LabCS;
- }(ColorSpace);
-
- return LabCS;
-}();
-exports.ColorSpace = ColorSpace;
-
-/***/ }),
-/* 152 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.AnnotationFactory = exports.AnnotationBorderStyle = exports.Annotation = undefined;
-
-var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-var _util = __w_pdfjs_require__(2);
-
-var _obj = __w_pdfjs_require__(137);
-
-var _primitives = __w_pdfjs_require__(138);
-
-var _colorspace = __w_pdfjs_require__(151);
-
-var _operator_list = __w_pdfjs_require__(153);
-
-var _stream = __w_pdfjs_require__(140);
-
-function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
-
-function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-var AnnotationFactory = function () {
- function AnnotationFactory() {
- _classCallCheck(this, AnnotationFactory);
- }
-
- _createClass(AnnotationFactory, null, [{
- key: 'create',
- value: function create(xref, ref, pdfManager, idFactory) {
- return pdfManager.ensure(this, '_create', [xref, ref, pdfManager, idFactory]);
- }
- }, {
- key: '_create',
- value: function _create(xref, ref, pdfManager, idFactory) {
- var dict = xref.fetchIfRef(ref);
- if (!(0, _primitives.isDict)(dict)) {
- return;
- }
- var id = (0, _primitives.isRef)(ref) ? ref.toString() : 'annot_' + idFactory.createObjId();
- var subtype = dict.get('Subtype');
- subtype = (0, _primitives.isName)(subtype) ? subtype.name : null;
- var parameters = {
- xref: xref,
- dict: dict,
- ref: (0, _primitives.isRef)(ref) ? ref : null,
- subtype: subtype,
- id: id,
- pdfManager: pdfManager
- };
- switch (subtype) {
- case 'Link':
- return new LinkAnnotation(parameters);
- case 'Text':
- return new TextAnnotation(parameters);
- case 'Widget':
- var fieldType = (0, _util.getInheritableProperty)({
- dict: dict,
- key: 'FT'
- });
- fieldType = (0, _primitives.isName)(fieldType) ? fieldType.name : null;
- switch (fieldType) {
- case 'Tx':
- return new TextWidgetAnnotation(parameters);
- case 'Btn':
- return new ButtonWidgetAnnotation(parameters);
- case 'Ch':
- return new ChoiceWidgetAnnotation(parameters);
- }
- (0, _util.warn)('Unimplemented widget field type "' + fieldType + '", ' + 'falling back to base field type.');
- return new WidgetAnnotation(parameters);
- case 'Popup':
- return new PopupAnnotation(parameters);
- case 'Line':
- return new LineAnnotation(parameters);
- case 'Square':
- return new SquareAnnotation(parameters);
- case 'Circle':
- return new CircleAnnotation(parameters);
- case 'PolyLine':
- return new PolylineAnnotation(parameters);
- case 'Polygon':
- return new PolygonAnnotation(parameters);
- case 'Ink':
- return new InkAnnotation(parameters);
- case 'Highlight':
- return new HighlightAnnotation(parameters);
- case 'Underline':
- return new UnderlineAnnotation(parameters);
- case 'Squiggly':
- return new SquigglyAnnotation(parameters);
- case 'StrikeOut':
- return new StrikeOutAnnotation(parameters);
- case 'Stamp':
- return new StampAnnotation(parameters);
- case 'FileAttachment':
- return new FileAttachmentAnnotation(parameters);
- default:
- if (!subtype) {
- (0, _util.warn)('Annotation is missing the required /Subtype.');
- } else {
- (0, _util.warn)('Unimplemented annotation type "' + subtype + '", ' + 'falling back to base annotation.');
- }
- return new Annotation(parameters);
- }
- }
- }]);
-
- return AnnotationFactory;
-}();
-
-function getTransformMatrix(rect, bbox, matrix) {
- var bounds = _util.Util.getAxialAlignedBoundingBox(bbox, matrix);
- var minX = bounds[0];
- var minY = bounds[1];
- var maxX = bounds[2];
- var maxY = bounds[3];
- if (minX === maxX || minY === maxY) {
- return [1, 0, 0, 1, rect[0], rect[1]];
- }
- var xRatio = (rect[2] - rect[0]) / (maxX - minX);
- var yRatio = (rect[3] - rect[1]) / (maxY - minY);
- return [xRatio, 0, 0, yRatio, rect[0] - minX * xRatio, rect[1] - minY * yRatio];
-}
-
-var Annotation = function () {
- function Annotation(params) {
- _classCallCheck(this, Annotation);
-
- var dict = params.dict;
- this.setFlags(dict.get('F'));
- this.setRectangle(dict.getArray('Rect'));
- this.setColor(dict.getArray('C'));
- this.setBorderStyle(dict);
- this.setAppearance(dict);
- this.data = {
- annotationFlags: this.flags,
- borderStyle: this.borderStyle,
- color: this.color,
- hasAppearance: !!this.appearance,
- id: params.id,
- rect: this.rectangle,
- subtype: params.subtype
- };
- }
-
- _createClass(Annotation, [{
- key: '_hasFlag',
- value: function _hasFlag(flags, flag) {
- return !!(flags & flag);
- }
- }, {
- key: '_isViewable',
- value: function _isViewable(flags) {
- return !this._hasFlag(flags, _util.AnnotationFlag.INVISIBLE) && !this._hasFlag(flags, _util.AnnotationFlag.HIDDEN) && !this._hasFlag(flags, _util.AnnotationFlag.NOVIEW);
- }
- }, {
- key: '_isPrintable',
- value: function _isPrintable(flags) {
- return this._hasFlag(flags, _util.AnnotationFlag.PRINT) && !this._hasFlag(flags, _util.AnnotationFlag.INVISIBLE) && !this._hasFlag(flags, _util.AnnotationFlag.HIDDEN);
- }
- }, {
- key: 'setFlags',
- value: function setFlags(flags) {
- this.flags = Number.isInteger(flags) && flags > 0 ? flags : 0;
- }
- }, {
- key: 'hasFlag',
- value: function hasFlag(flag) {
- return this._hasFlag(this.flags, flag);
- }
- }, {
- key: 'setRectangle',
- value: function setRectangle(rectangle) {
- if (Array.isArray(rectangle) && rectangle.length === 4) {
- this.rectangle = _util.Util.normalizeRect(rectangle);
- } else {
- this.rectangle = [0, 0, 0, 0];
- }
- }
- }, {
- key: 'setColor',
- value: function setColor(color) {
- var rgbColor = new Uint8ClampedArray(3);
- if (!Array.isArray(color)) {
- this.color = rgbColor;
- return;
- }
- switch (color.length) {
- case 0:
- this.color = null;
- break;
- case 1:
- _colorspace.ColorSpace.singletons.gray.getRgbItem(color, 0, rgbColor, 0);
- this.color = rgbColor;
- break;
- case 3:
- _colorspace.ColorSpace.singletons.rgb.getRgbItem(color, 0, rgbColor, 0);
- this.color = rgbColor;
- break;
- case 4:
- _colorspace.ColorSpace.singletons.cmyk.getRgbItem(color, 0, rgbColor, 0);
- this.color = rgbColor;
- break;
- default:
- this.color = rgbColor;
- break;
- }
- }
- }, {
- key: 'setBorderStyle',
- value: function setBorderStyle(borderStyle) {
- this.borderStyle = new AnnotationBorderStyle();
- if (!(0, _primitives.isDict)(borderStyle)) {
- return;
- }
- if (borderStyle.has('BS')) {
- var dict = borderStyle.get('BS');
- var dictType = dict.get('Type');
- if (!dictType || (0, _primitives.isName)(dictType, 'Border')) {
- this.borderStyle.setWidth(dict.get('W'));
- this.borderStyle.setStyle(dict.get('S'));
- this.borderStyle.setDashArray(dict.getArray('D'));
- }
- } else if (borderStyle.has('Border')) {
- var array = borderStyle.getArray('Border');
- if (Array.isArray(array) && array.length >= 3) {
- this.borderStyle.setHorizontalCornerRadius(array[0]);
- this.borderStyle.setVerticalCornerRadius(array[1]);
- this.borderStyle.setWidth(array[2]);
- if (array.length === 4) {
- this.borderStyle.setDashArray(array[3]);
- }
- }
- } else {
- this.borderStyle.setWidth(0);
- }
- }
- }, {
- key: 'setAppearance',
- value: function setAppearance(dict) {
- this.appearance = null;
- var appearanceStates = dict.get('AP');
- if (!(0, _primitives.isDict)(appearanceStates)) {
- return;
- }
- var normalAppearanceState = appearanceStates.get('N');
- if ((0, _primitives.isStream)(normalAppearanceState)) {
- this.appearance = normalAppearanceState;
- return;
- }
- if (!(0, _primitives.isDict)(normalAppearanceState)) {
- return;
- }
- var as = dict.get('AS');
- if (!(0, _primitives.isName)(as) || !normalAppearanceState.has(as.name)) {
- return;
- }
- this.appearance = normalAppearanceState.get(as.name);
- }
- }, {
- key: '_preparePopup',
- value: function _preparePopup(dict) {
- if (!dict.has('C')) {
- this.data.color = null;
- }
- this.data.hasPopup = dict.has('Popup');
- this.data.title = (0, _util.stringToPDFString)(dict.get('T') || '');
- this.data.contents = (0, _util.stringToPDFString)(dict.get('Contents') || '');
- }
- }, {
- key: 'loadResources',
- value: function loadResources(keys) {
- return this.appearance.dict.getAsync('Resources').then(function (resources) {
- if (!resources) {
- return;
- }
- var objectLoader = new _obj.ObjectLoader(resources, keys, resources.xref);
- return objectLoader.load().then(function () {
- return resources;
- });
- });
- }
- }, {
- key: 'getOperatorList',
- value: function getOperatorList(evaluator, task, renderForms) {
- var _this = this;
-
- if (!this.appearance) {
- return Promise.resolve(new _operator_list.OperatorList());
- }
- var data = this.data;
- var appearanceDict = this.appearance.dict;
- var resourcesPromise = this.loadResources(['ExtGState', 'ColorSpace', 'Pattern', 'Shading', 'XObject', 'Font']);
- var bbox = appearanceDict.getArray('BBox') || [0, 0, 1, 1];
- var matrix = appearanceDict.getArray('Matrix') || [1, 0, 0, 1, 0, 0];
- var transform = getTransformMatrix(data.rect, bbox, matrix);
- return resourcesPromise.then(function (resources) {
- var opList = new _operator_list.OperatorList();
- opList.addOp(_util.OPS.beginAnnotation, [data.rect, transform, matrix]);
- return evaluator.getOperatorList({
- stream: _this.appearance,
- task: task,
- resources: resources,
- operatorList: opList
- }).then(function () {
- opList.addOp(_util.OPS.endAnnotation, []);
- _this.appearance.reset();
- return opList;
- });
- });
- }
- }, {
- key: 'viewable',
- get: function get() {
- if (this.flags === 0) {
- return true;
- }
- return this._isViewable(this.flags);
- }
- }, {
- key: 'printable',
- get: function get() {
- if (this.flags === 0) {
- return false;
- }
- return this._isPrintable(this.flags);
- }
- }]);
-
- return Annotation;
-}();
-
-var AnnotationBorderStyle = function () {
- function AnnotationBorderStyle() {
- _classCallCheck(this, AnnotationBorderStyle);
-
- this.width = 1;
- this.style = _util.AnnotationBorderStyleType.SOLID;
- this.dashArray = [3];
- this.horizontalCornerRadius = 0;
- this.verticalCornerRadius = 0;
- }
-
- _createClass(AnnotationBorderStyle, [{
- key: 'setWidth',
- value: function setWidth(width) {
- if (Number.isInteger(width)) {
- this.width = width;
- }
- }
- }, {
- key: 'setStyle',
- value: function setStyle(style) {
- if (!style) {
- return;
- }
- switch (style.name) {
- case 'S':
- this.style = _util.AnnotationBorderStyleType.SOLID;
- break;
- case 'D':
- this.style = _util.AnnotationBorderStyleType.DASHED;
- break;
- case 'B':
- this.style = _util.AnnotationBorderStyleType.BEVELED;
- break;
- case 'I':
- this.style = _util.AnnotationBorderStyleType.INSET;
- break;
- case 'U':
- this.style = _util.AnnotationBorderStyleType.UNDERLINE;
- break;
- default:
- break;
- }
- }
- }, {
- key: 'setDashArray',
- value: function setDashArray(dashArray) {
- if (Array.isArray(dashArray) && dashArray.length > 0) {
- var isValid = true;
- var allZeros = true;
- for (var i = 0, len = dashArray.length; i < len; i++) {
- var element = dashArray[i];
- var validNumber = +element >= 0;
- if (!validNumber) {
- isValid = false;
- break;
- } else if (element > 0) {
- allZeros = false;
- }
- }
- if (isValid && !allZeros) {
- this.dashArray = dashArray;
- } else {
- this.width = 0;
- }
- } else if (dashArray) {
- this.width = 0;
- }
- }
- }, {
- key: 'setHorizontalCornerRadius',
- value: function setHorizontalCornerRadius(radius) {
- if (Number.isInteger(radius)) {
- this.horizontalCornerRadius = radius;
- }
- }
- }, {
- key: 'setVerticalCornerRadius',
- value: function setVerticalCornerRadius(radius) {
- if (Number.isInteger(radius)) {
- this.verticalCornerRadius = radius;
- }
- }
- }]);
-
- return AnnotationBorderStyle;
-}();
-
-var WidgetAnnotation = function (_Annotation) {
- _inherits(WidgetAnnotation, _Annotation);
-
- function WidgetAnnotation(params) {
- _classCallCheck(this, WidgetAnnotation);
-
- var _this2 = _possibleConstructorReturn(this, (WidgetAnnotation.__proto__ || Object.getPrototypeOf(WidgetAnnotation)).call(this, params));
-
- var dict = params.dict;
- var data = _this2.data;
- data.annotationType = _util.AnnotationType.WIDGET;
- data.fieldName = _this2._constructFieldName(dict);
- data.fieldValue = (0, _util.getInheritableProperty)({
- dict: dict,
- key: 'V',
- getArray: true
- });
- data.alternativeText = (0, _util.stringToPDFString)(dict.get('TU') || '');
- data.defaultAppearance = (0, _util.getInheritableProperty)({
- dict: dict,
- key: 'DA'
- }) || '';
- var fieldType = (0, _util.getInheritableProperty)({
- dict: dict,
- key: 'FT'
- });
- data.fieldType = (0, _primitives.isName)(fieldType) ? fieldType.name : null;
- _this2.fieldResources = (0, _util.getInheritableProperty)({
- dict: dict,
- key: 'DR'
- }) || _primitives.Dict.empty;
- data.fieldFlags = (0, _util.getInheritableProperty)({
- dict: dict,
- key: 'Ff'
- });
- if (!Number.isInteger(data.fieldFlags) || data.fieldFlags < 0) {
- data.fieldFlags = 0;
- }
- data.readOnly = _this2.hasFieldFlag(_util.AnnotationFieldFlag.READONLY);
- if (data.fieldType === 'Sig') {
- _this2.setFlags(_util.AnnotationFlag.HIDDEN);
- }
- return _this2;
- }
-
- _createClass(WidgetAnnotation, [{
- key: '_constructFieldName',
- value: function _constructFieldName(dict) {
- if (!dict.has('T') && !dict.has('Parent')) {
- (0, _util.warn)('Unknown field name, falling back to empty field name.');
- return '';
- }
- if (!dict.has('Parent')) {
- return (0, _util.stringToPDFString)(dict.get('T'));
- }
- var fieldName = [];
- if (dict.has('T')) {
- fieldName.unshift((0, _util.stringToPDFString)(dict.get('T')));
- }
- var loopDict = dict;
- while (loopDict.has('Parent')) {
- loopDict = loopDict.get('Parent');
- if (!(0, _primitives.isDict)(loopDict)) {
- break;
- }
- if (loopDict.has('T')) {
- fieldName.unshift((0, _util.stringToPDFString)(loopDict.get('T')));
- }
- }
- return fieldName.join('.');
- }
- }, {
- key: 'hasFieldFlag',
- value: function hasFieldFlag(flag) {
- return !!(this.data.fieldFlags & flag);
- }
- }, {
- key: 'getOperatorList',
- value: function getOperatorList(evaluator, task, renderForms) {
- if (renderForms) {
- return Promise.resolve(new _operator_list.OperatorList());
- }
- return _get(WidgetAnnotation.prototype.__proto__ || Object.getPrototypeOf(WidgetAnnotation.prototype), 'getOperatorList', this).call(this, evaluator, task, renderForms);
- }
- }]);
-
- return WidgetAnnotation;
-}(Annotation);
-
-var TextWidgetAnnotation = function (_WidgetAnnotation) {
- _inherits(TextWidgetAnnotation, _WidgetAnnotation);
-
- function TextWidgetAnnotation(params) {
- _classCallCheck(this, TextWidgetAnnotation);
-
- var _this3 = _possibleConstructorReturn(this, (TextWidgetAnnotation.__proto__ || Object.getPrototypeOf(TextWidgetAnnotation)).call(this, params));
-
- var dict = params.dict;
- _this3.data.fieldValue = (0, _util.stringToPDFString)(_this3.data.fieldValue || '');
- var alignment = (0, _util.getInheritableProperty)({
- dict: dict,
- key: 'Q'
- });
- if (!Number.isInteger(alignment) || alignment < 0 || alignment > 2) {
- alignment = null;
- }
- _this3.data.textAlignment = alignment;
- var maximumLength = (0, _util.getInheritableProperty)({
- dict: dict,
- key: 'MaxLen'
- });
- if (!Number.isInteger(maximumLength) || maximumLength < 0) {
- maximumLength = null;
- }
- _this3.data.maxLen = maximumLength;
- _this3.data.multiLine = _this3.hasFieldFlag(_util.AnnotationFieldFlag.MULTILINE);
- _this3.data.comb = _this3.hasFieldFlag(_util.AnnotationFieldFlag.COMB) && !_this3.hasFieldFlag(_util.AnnotationFieldFlag.MULTILINE) && !_this3.hasFieldFlag(_util.AnnotationFieldFlag.PASSWORD) && !_this3.hasFieldFlag(_util.AnnotationFieldFlag.FILESELECT) && _this3.data.maxLen !== null;
- return _this3;
- }
-
- _createClass(TextWidgetAnnotation, [{
- key: 'getOperatorList',
- value: function getOperatorList(evaluator, task, renderForms) {
- if (renderForms || this.appearance) {
- return _get(TextWidgetAnnotation.prototype.__proto__ || Object.getPrototypeOf(TextWidgetAnnotation.prototype), 'getOperatorList', this).call(this, evaluator, task, renderForms);
- }
- var operatorList = new _operator_list.OperatorList();
- if (!this.data.defaultAppearance) {
- return Promise.resolve(operatorList);
- }
- var stream = new _stream.Stream((0, _util.stringToBytes)(this.data.defaultAppearance));
- return evaluator.getOperatorList({
- stream: stream,
- task: task,
- resources: this.fieldResources,
- operatorList: operatorList
- }).then(function () {
- return operatorList;
- });
- }
- }]);
-
- return TextWidgetAnnotation;
-}(WidgetAnnotation);
-
-var ButtonWidgetAnnotation = function (_WidgetAnnotation2) {
- _inherits(ButtonWidgetAnnotation, _WidgetAnnotation2);
-
- function ButtonWidgetAnnotation(params) {
- _classCallCheck(this, ButtonWidgetAnnotation);
-
- var _this4 = _possibleConstructorReturn(this, (ButtonWidgetAnnotation.__proto__ || Object.getPrototypeOf(ButtonWidgetAnnotation)).call(this, params));
-
- _this4.data.checkBox = !_this4.hasFieldFlag(_util.AnnotationFieldFlag.RADIO) && !_this4.hasFieldFlag(_util.AnnotationFieldFlag.PUSHBUTTON);
- _this4.data.radioButton = _this4.hasFieldFlag(_util.AnnotationFieldFlag.RADIO) && !_this4.hasFieldFlag(_util.AnnotationFieldFlag.PUSHBUTTON);
- _this4.data.pushButton = _this4.hasFieldFlag(_util.AnnotationFieldFlag.PUSHBUTTON);
- if (_this4.data.checkBox) {
- _this4._processCheckBox(params);
- } else if (_this4.data.radioButton) {
- _this4._processRadioButton(params);
- } else if (_this4.data.pushButton) {
- _this4._processPushButton(params);
- } else {
- (0, _util.warn)('Invalid field flags for button widget annotation');
- }
- return _this4;
- }
-
- _createClass(ButtonWidgetAnnotation, [{
- key: '_processCheckBox',
- value: function _processCheckBox(params) {
- if ((0, _primitives.isName)(this.data.fieldValue)) {
- this.data.fieldValue = this.data.fieldValue.name;
- }
- var customAppearance = params.dict.get('AP');
- if (!(0, _primitives.isDict)(customAppearance)) {
- return;
- }
- var exportValueOptionsDict = customAppearance.get('D');
- if (!(0, _primitives.isDict)(exportValueOptionsDict)) {
- return;
- }
- var exportValues = exportValueOptionsDict.getKeys();
- var hasCorrectOptionCount = exportValues.length === 2;
- if (!hasCorrectOptionCount) {
- return;
- }
- this.data.exportValue = exportValues[0] === 'Off' ? exportValues[1] : exportValues[0];
- }
- }, {
- key: '_processRadioButton',
- value: function _processRadioButton(params) {
- this.data.fieldValue = this.data.buttonValue = null;
- var fieldParent = params.dict.get('Parent');
- if ((0, _primitives.isDict)(fieldParent) && fieldParent.has('V')) {
- var fieldParentValue = fieldParent.get('V');
- if ((0, _primitives.isName)(fieldParentValue)) {
- this.data.fieldValue = fieldParentValue.name;
- }
- }
- var appearanceStates = params.dict.get('AP');
- if (!(0, _primitives.isDict)(appearanceStates)) {
- return;
- }
- var normalAppearanceState = appearanceStates.get('N');
- if (!(0, _primitives.isDict)(normalAppearanceState)) {
- return;
- }
- var keys = normalAppearanceState.getKeys();
- for (var i = 0, ii = keys.length; i < ii; i++) {
- if (keys[i] !== 'Off') {
- this.data.buttonValue = keys[i];
- break;
- }
- }
- }
- }, {
- key: '_processPushButton',
- value: function _processPushButton(params) {
- if (!params.dict.has('A')) {
- (0, _util.warn)('Push buttons without action dictionaries are not supported');
- return;
- }
- _obj.Catalog.parseDestDictionary({
- destDict: params.dict,
- resultObj: this.data,
- docBaseUrl: params.pdfManager.docBaseUrl
- });
- }
- }]);
-
- return ButtonWidgetAnnotation;
-}(WidgetAnnotation);
-
-var ChoiceWidgetAnnotation = function (_WidgetAnnotation3) {
- _inherits(ChoiceWidgetAnnotation, _WidgetAnnotation3);
-
- function ChoiceWidgetAnnotation(params) {
- _classCallCheck(this, ChoiceWidgetAnnotation);
-
- var _this5 = _possibleConstructorReturn(this, (ChoiceWidgetAnnotation.__proto__ || Object.getPrototypeOf(ChoiceWidgetAnnotation)).call(this, params));
-
- _this5.data.options = [];
- var options = (0, _util.getInheritableProperty)({
- dict: params.dict,
- key: 'Opt'
- });
- if (Array.isArray(options)) {
- var xref = params.xref;
- for (var i = 0, ii = options.length; i < ii; i++) {
- var option = xref.fetchIfRef(options[i]);
- var isOptionArray = Array.isArray(option);
- _this5.data.options[i] = {
- exportValue: isOptionArray ? xref.fetchIfRef(option[0]) : option,
- displayValue: (0, _util.stringToPDFString)(isOptionArray ? xref.fetchIfRef(option[1]) : option)
- };
- }
- }
- if (!Array.isArray(_this5.data.fieldValue)) {
- _this5.data.fieldValue = [_this5.data.fieldValue];
- }
- _this5.data.combo = _this5.hasFieldFlag(_util.AnnotationFieldFlag.COMBO);
- _this5.data.multiSelect = _this5.hasFieldFlag(_util.AnnotationFieldFlag.MULTISELECT);
- return _this5;
- }
-
- return ChoiceWidgetAnnotation;
-}(WidgetAnnotation);
-
-var TextAnnotation = function (_Annotation2) {
- _inherits(TextAnnotation, _Annotation2);
-
- function TextAnnotation(parameters) {
- _classCallCheck(this, TextAnnotation);
-
- var DEFAULT_ICON_SIZE = 22;
-
- var _this6 = _possibleConstructorReturn(this, (TextAnnotation.__proto__ || Object.getPrototypeOf(TextAnnotation)).call(this, parameters));
-
- _this6.data.annotationType = _util.AnnotationType.TEXT;
- if (_this6.data.hasAppearance) {
- _this6.data.name = 'NoIcon';
- } else {
- _this6.data.rect[1] = _this6.data.rect[3] - DEFAULT_ICON_SIZE;
- _this6.data.rect[2] = _this6.data.rect[0] + DEFAULT_ICON_SIZE;
- _this6.data.name = parameters.dict.has('Name') ? parameters.dict.get('Name').name : 'Note';
- }
- _this6._preparePopup(parameters.dict);
- return _this6;
- }
-
- return TextAnnotation;
-}(Annotation);
-
-var LinkAnnotation = function (_Annotation3) {
- _inherits(LinkAnnotation, _Annotation3);
-
- function LinkAnnotation(params) {
- _classCallCheck(this, LinkAnnotation);
-
- var _this7 = _possibleConstructorReturn(this, (LinkAnnotation.__proto__ || Object.getPrototypeOf(LinkAnnotation)).call(this, params));
-
- _this7.data.annotationType = _util.AnnotationType.LINK;
- _obj.Catalog.parseDestDictionary({
- destDict: params.dict,
- resultObj: _this7.data,
- docBaseUrl: params.pdfManager.docBaseUrl
- });
- return _this7;
- }
-
- return LinkAnnotation;
-}(Annotation);
-
-var PopupAnnotation = function (_Annotation4) {
- _inherits(PopupAnnotation, _Annotation4);
-
- function PopupAnnotation(parameters) {
- _classCallCheck(this, PopupAnnotation);
-
- var _this8 = _possibleConstructorReturn(this, (PopupAnnotation.__proto__ || Object.getPrototypeOf(PopupAnnotation)).call(this, parameters));
-
- _this8.data.annotationType = _util.AnnotationType.POPUP;
- var dict = parameters.dict;
- var parentItem = dict.get('Parent');
- if (!parentItem) {
- (0, _util.warn)('Popup annotation has a missing or invalid parent annotation.');
- return _possibleConstructorReturn(_this8);
- }
- var parentSubtype = parentItem.get('Subtype');
- _this8.data.parentType = (0, _primitives.isName)(parentSubtype) ? parentSubtype.name : null;
- _this8.data.parentId = dict.getRaw('Parent').toString();
- _this8.data.title = (0, _util.stringToPDFString)(parentItem.get('T') || '');
- _this8.data.contents = (0, _util.stringToPDFString)(parentItem.get('Contents') || '');
- if (!parentItem.has('C')) {
- _this8.data.color = null;
- } else {
- _this8.setColor(parentItem.getArray('C'));
- _this8.data.color = _this8.color;
- }
- if (!_this8.viewable) {
- var parentFlags = parentItem.get('F');
- if (_this8._isViewable(parentFlags)) {
- _this8.setFlags(parentFlags);
- }
- }
- return _this8;
- }
-
- return PopupAnnotation;
-}(Annotation);
-
-var LineAnnotation = function (_Annotation5) {
- _inherits(LineAnnotation, _Annotation5);
-
- function LineAnnotation(parameters) {
- _classCallCheck(this, LineAnnotation);
-
- var _this9 = _possibleConstructorReturn(this, (LineAnnotation.__proto__ || Object.getPrototypeOf(LineAnnotation)).call(this, parameters));
-
- _this9.data.annotationType = _util.AnnotationType.LINE;
- var dict = parameters.dict;
- _this9.data.lineCoordinates = _util.Util.normalizeRect(dict.getArray('L'));
- _this9._preparePopup(dict);
- return _this9;
- }
-
- return LineAnnotation;
-}(Annotation);
-
-var SquareAnnotation = function (_Annotation6) {
- _inherits(SquareAnnotation, _Annotation6);
-
- function SquareAnnotation(parameters) {
- _classCallCheck(this, SquareAnnotation);
-
- var _this10 = _possibleConstructorReturn(this, (SquareAnnotation.__proto__ || Object.getPrototypeOf(SquareAnnotation)).call(this, parameters));
-
- _this10.data.annotationType = _util.AnnotationType.SQUARE;
- _this10._preparePopup(parameters.dict);
- return _this10;
- }
-
- return SquareAnnotation;
-}(Annotation);
-
-var CircleAnnotation = function (_Annotation7) {
- _inherits(CircleAnnotation, _Annotation7);
-
- function CircleAnnotation(parameters) {
- _classCallCheck(this, CircleAnnotation);
-
- var _this11 = _possibleConstructorReturn(this, (CircleAnnotation.__proto__ || Object.getPrototypeOf(CircleAnnotation)).call(this, parameters));
-
- _this11.data.annotationType = _util.AnnotationType.CIRCLE;
- _this11._preparePopup(parameters.dict);
- return _this11;
- }
-
- return CircleAnnotation;
-}(Annotation);
-
-var PolylineAnnotation = function (_Annotation8) {
- _inherits(PolylineAnnotation, _Annotation8);
-
- function PolylineAnnotation(parameters) {
- _classCallCheck(this, PolylineAnnotation);
-
- var _this12 = _possibleConstructorReturn(this, (PolylineAnnotation.__proto__ || Object.getPrototypeOf(PolylineAnnotation)).call(this, parameters));
-
- _this12.data.annotationType = _util.AnnotationType.POLYLINE;
- var dict = parameters.dict;
- var rawVertices = dict.getArray('Vertices');
- _this12.data.vertices = [];
- for (var i = 0, ii = rawVertices.length; i < ii; i += 2) {
- _this12.data.vertices.push({
- x: rawVertices[i],
- y: rawVertices[i + 1]
- });
- }
- _this12._preparePopup(dict);
- return _this12;
- }
-
- return PolylineAnnotation;
-}(Annotation);
-
-var PolygonAnnotation = function (_PolylineAnnotation) {
- _inherits(PolygonAnnotation, _PolylineAnnotation);
-
- function PolygonAnnotation(parameters) {
- _classCallCheck(this, PolygonAnnotation);
-
- var _this13 = _possibleConstructorReturn(this, (PolygonAnnotation.__proto__ || Object.getPrototypeOf(PolygonAnnotation)).call(this, parameters));
-
- _this13.data.annotationType = _util.AnnotationType.POLYGON;
- return _this13;
- }
-
- return PolygonAnnotation;
-}(PolylineAnnotation);
-
-var InkAnnotation = function (_Annotation9) {
- _inherits(InkAnnotation, _Annotation9);
-
- function InkAnnotation(parameters) {
- _classCallCheck(this, InkAnnotation);
-
- var _this14 = _possibleConstructorReturn(this, (InkAnnotation.__proto__ || Object.getPrototypeOf(InkAnnotation)).call(this, parameters));
-
- _this14.data.annotationType = _util.AnnotationType.INK;
- var dict = parameters.dict;
- var xref = parameters.xref;
- var originalInkLists = dict.getArray('InkList');
- _this14.data.inkLists = [];
- for (var i = 0, ii = originalInkLists.length; i < ii; ++i) {
- _this14.data.inkLists.push([]);
- for (var j = 0, jj = originalInkLists[i].length; j < jj; j += 2) {
- _this14.data.inkLists[i].push({
- x: xref.fetchIfRef(originalInkLists[i][j]),
- y: xref.fetchIfRef(originalInkLists[i][j + 1])
- });
- }
- }
- _this14._preparePopup(dict);
- return _this14;
- }
-
- return InkAnnotation;
-}(Annotation);
-
-var HighlightAnnotation = function (_Annotation10) {
- _inherits(HighlightAnnotation, _Annotation10);
-
- function HighlightAnnotation(parameters) {
- _classCallCheck(this, HighlightAnnotation);
-
- var _this15 = _possibleConstructorReturn(this, (HighlightAnnotation.__proto__ || Object.getPrototypeOf(HighlightAnnotation)).call(this, parameters));
-
- _this15.data.annotationType = _util.AnnotationType.HIGHLIGHT;
- _this15._preparePopup(parameters.dict);
- return _this15;
- }
-
- return HighlightAnnotation;
-}(Annotation);
-
-var UnderlineAnnotation = function (_Annotation11) {
- _inherits(UnderlineAnnotation, _Annotation11);
-
- function UnderlineAnnotation(parameters) {
- _classCallCheck(this, UnderlineAnnotation);
-
- var _this16 = _possibleConstructorReturn(this, (UnderlineAnnotation.__proto__ || Object.getPrototypeOf(UnderlineAnnotation)).call(this, parameters));
-
- _this16.data.annotationType = _util.AnnotationType.UNDERLINE;
- _this16._preparePopup(parameters.dict);
- return _this16;
- }
-
- return UnderlineAnnotation;
-}(Annotation);
-
-var SquigglyAnnotation = function (_Annotation12) {
- _inherits(SquigglyAnnotation, _Annotation12);
-
- function SquigglyAnnotation(parameters) {
- _classCallCheck(this, SquigglyAnnotation);
-
- var _this17 = _possibleConstructorReturn(this, (SquigglyAnnotation.__proto__ || Object.getPrototypeOf(SquigglyAnnotation)).call(this, parameters));
-
- _this17.data.annotationType = _util.AnnotationType.SQUIGGLY;
- _this17._preparePopup(parameters.dict);
- return _this17;
- }
-
- return SquigglyAnnotation;
-}(Annotation);
-
-var StrikeOutAnnotation = function (_Annotation13) {
- _inherits(StrikeOutAnnotation, _Annotation13);
-
- function StrikeOutAnnotation(parameters) {
- _classCallCheck(this, StrikeOutAnnotation);
-
- var _this18 = _possibleConstructorReturn(this, (StrikeOutAnnotation.__proto__ || Object.getPrototypeOf(StrikeOutAnnotation)).call(this, parameters));
-
- _this18.data.annotationType = _util.AnnotationType.STRIKEOUT;
- _this18._preparePopup(parameters.dict);
- return _this18;
- }
-
- return StrikeOutAnnotation;
-}(Annotation);
-
-var StampAnnotation = function (_Annotation14) {
- _inherits(StampAnnotation, _Annotation14);
-
- function StampAnnotation(parameters) {
- _classCallCheck(this, StampAnnotation);
-
- var _this19 = _possibleConstructorReturn(this, (StampAnnotation.__proto__ || Object.getPrototypeOf(StampAnnotation)).call(this, parameters));
-
- _this19.data.annotationType = _util.AnnotationType.STAMP;
- _this19._preparePopup(parameters.dict);
- return _this19;
- }
-
- return StampAnnotation;
-}(Annotation);
-
-var FileAttachmentAnnotation = function (_Annotation15) {
- _inherits(FileAttachmentAnnotation, _Annotation15);
-
- function FileAttachmentAnnotation(parameters) {
- _classCallCheck(this, FileAttachmentAnnotation);
-
- var _this20 = _possibleConstructorReturn(this, (FileAttachmentAnnotation.__proto__ || Object.getPrototypeOf(FileAttachmentAnnotation)).call(this, parameters));
-
- var file = new _obj.FileSpec(parameters.dict.get('FS'), parameters.xref);
- _this20.data.annotationType = _util.AnnotationType.FILEATTACHMENT;
- _this20.data.file = file.serializable;
- _this20._preparePopup(parameters.dict);
- return _this20;
- }
-
- return FileAttachmentAnnotation;
-}(Annotation);
-
-exports.Annotation = Annotation;
-exports.AnnotationBorderStyle = AnnotationBorderStyle;
-exports.AnnotationFactory = AnnotationFactory;
-
-/***/ }),
-/* 153 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.OperatorList = undefined;
-
-var _util = __w_pdfjs_require__(2);
-
-var QueueOptimizer = function QueueOptimizerClosure() {
- function addState(parentState, pattern, checkFn, iterateFn, processFn) {
- var state = parentState;
- for (var i = 0, ii = pattern.length - 1; i < ii; i++) {
- var item = pattern[i];
- state = state[item] || (state[item] = []);
- }
- state[pattern[pattern.length - 1]] = {
- checkFn: checkFn,
- iterateFn: iterateFn,
- processFn: processFn
- };
- }
- function handlePaintSolidColorImageMask(iFirstSave, count, fnArray, argsArray) {
- var iFirstPIMXO = iFirstSave + 2;
- for (var i = 0; i < count; i++) {
- var arg = argsArray[iFirstPIMXO + 4 * i];
- var imageMask = arg.length === 1 && arg[0];
- if (imageMask && imageMask.width === 1 && imageMask.height === 1 && (!imageMask.data.length || imageMask.data.length === 1 && imageMask.data[0] === 0)) {
- fnArray[iFirstPIMXO + 4 * i] = _util.OPS.paintSolidColorImageMask;
- continue;
- }
- break;
- }
- return count - i;
- }
- var InitialState = [];
- addState(InitialState, [_util.OPS.save, _util.OPS.transform, _util.OPS.paintInlineImageXObject, _util.OPS.restore], null, function iterateInlineImageGroup(context, i) {
- var fnArray = context.fnArray;
- var iFirstSave = context.iCurr - 3;
- var pos = (i - iFirstSave) % 4;
- switch (pos) {
- case 0:
- return fnArray[i] === _util.OPS.save;
- case 1:
- return fnArray[i] === _util.OPS.transform;
- case 2:
- return fnArray[i] === _util.OPS.paintInlineImageXObject;
- case 3:
- return fnArray[i] === _util.OPS.restore;
- }
- }, function foundInlineImageGroup(context, i) {
- var MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10;
- var MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200;
- var MAX_WIDTH = 1000;
- var IMAGE_PADDING = 1;
- var fnArray = context.fnArray,
- argsArray = context.argsArray;
- var curr = context.iCurr;
- var iFirstSave = curr - 3;
- var iFirstTransform = curr - 2;
- var iFirstPIIXO = curr - 1;
- var count = Math.min(Math.floor((i - iFirstSave) / 4), MAX_IMAGES_IN_INLINE_IMAGES_BLOCK);
- if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) {
- return i - (i - iFirstSave) % 4;
- }
- var maxX = 0;
- var map = [],
- maxLineHeight = 0;
- var currentX = IMAGE_PADDING,
- currentY = IMAGE_PADDING;
- var q;
- for (q = 0; q < count; q++) {
- var transform = argsArray[iFirstTransform + (q << 2)];
- var img = argsArray[iFirstPIIXO + (q << 2)][0];
- if (currentX + img.width > MAX_WIDTH) {
- maxX = Math.max(maxX, currentX);
- currentY += maxLineHeight + 2 * IMAGE_PADDING;
- currentX = 0;
- maxLineHeight = 0;
- }
- map.push({
- transform: transform,
- x: currentX,
- y: currentY,
- w: img.width,
- h: img.height
- });
- currentX += img.width + 2 * IMAGE_PADDING;
- maxLineHeight = Math.max(maxLineHeight, img.height);
- }
- var imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING;
- var imgHeight = currentY + maxLineHeight + IMAGE_PADDING;
- var imgData = new Uint8ClampedArray(imgWidth * imgHeight * 4);
- var imgRowSize = imgWidth << 2;
- for (q = 0; q < count; q++) {
- var data = argsArray[iFirstPIIXO + (q << 2)][0].data;
- var rowSize = map[q].w << 2;
- var dataOffset = 0;
- var offset = map[q].x + map[q].y * imgWidth << 2;
- imgData.set(data.subarray(0, rowSize), offset - imgRowSize);
- for (var k = 0, kk = map[q].h; k < kk; k++) {
- imgData.set(data.subarray(dataOffset, dataOffset + rowSize), offset);
- dataOffset += rowSize;
- offset += imgRowSize;
- }
- imgData.set(data.subarray(dataOffset - rowSize, dataOffset), offset);
- while (offset >= 0) {
- data[offset - 4] = data[offset];
- data[offset - 3] = data[offset + 1];
- data[offset - 2] = data[offset + 2];
- data[offset - 1] = data[offset + 3];
- data[offset + rowSize] = data[offset + rowSize - 4];
- data[offset + rowSize + 1] = data[offset + rowSize - 3];
- data[offset + rowSize + 2] = data[offset + rowSize - 2];
- data[offset + rowSize + 3] = data[offset + rowSize - 1];
- offset -= imgRowSize;
- }
- }
- fnArray.splice(iFirstSave, count * 4, _util.OPS.paintInlineImageXObjectGroup);
- argsArray.splice(iFirstSave, count * 4, [{
- width: imgWidth,
- height: imgHeight,
- kind: _util.ImageKind.RGBA_32BPP,
- data: imgData
- }, map]);
- return iFirstSave + 1;
- });
- addState(InitialState, [_util.OPS.save, _util.OPS.transform, _util.OPS.paintImageMaskXObject, _util.OPS.restore], null, function iterateImageMaskGroup(context, i) {
- var fnArray = context.fnArray;
- var iFirstSave = context.iCurr - 3;
- var pos = (i - iFirstSave) % 4;
- switch (pos) {
- case 0:
- return fnArray[i] === _util.OPS.save;
- case 1:
- return fnArray[i] === _util.OPS.transform;
- case 2:
- return fnArray[i] === _util.OPS.paintImageMaskXObject;
- case 3:
- return fnArray[i] === _util.OPS.restore;
- }
- }, function foundImageMaskGroup(context, i) {
- var MIN_IMAGES_IN_MASKS_BLOCK = 10;
- var MAX_IMAGES_IN_MASKS_BLOCK = 100;
- var MAX_SAME_IMAGES_IN_MASKS_BLOCK = 1000;
- var fnArray = context.fnArray,
- argsArray = context.argsArray;
- var curr = context.iCurr;
- var iFirstSave = curr - 3;
- var iFirstTransform = curr - 2;
- var iFirstPIMXO = curr - 1;
- var count = Math.floor((i - iFirstSave) / 4);
- count = handlePaintSolidColorImageMask(iFirstSave, count, fnArray, argsArray);
- if (count < MIN_IMAGES_IN_MASKS_BLOCK) {
- return i - (i - iFirstSave) % 4;
- }
- var q;
- var isSameImage = false;
- var iTransform, transformArgs;
- var firstPIMXOArg0 = argsArray[iFirstPIMXO][0];
- if (argsArray[iFirstTransform][1] === 0 && argsArray[iFirstTransform][2] === 0) {
- isSameImage = true;
- var firstTransformArg0 = argsArray[iFirstTransform][0];
- var firstTransformArg3 = argsArray[iFirstTransform][3];
- iTransform = iFirstTransform + 4;
- var iPIMXO = iFirstPIMXO + 4;
- for (q = 1; q < count; q++, iTransform += 4, iPIMXO += 4) {
- transformArgs = argsArray[iTransform];
- if (argsArray[iPIMXO][0] !== firstPIMXOArg0 || transformArgs[0] !== firstTransformArg0 || transformArgs[1] !== 0 || transformArgs[2] !== 0 || transformArgs[3] !== firstTransformArg3) {
- if (q < MIN_IMAGES_IN_MASKS_BLOCK) {
- isSameImage = false;
- } else {
- count = q;
- }
- break;
- }
- }
- }
- if (isSameImage) {
- count = Math.min(count, MAX_SAME_IMAGES_IN_MASKS_BLOCK);
- var positions = new Float32Array(count * 2);
- iTransform = iFirstTransform;
- for (q = 0; q < count; q++, iTransform += 4) {
- transformArgs = argsArray[iTransform];
- positions[q << 1] = transformArgs[4];
- positions[(q << 1) + 1] = transformArgs[5];
- }
- fnArray.splice(iFirstSave, count * 4, _util.OPS.paintImageMaskXObjectRepeat);
- argsArray.splice(iFirstSave, count * 4, [firstPIMXOArg0, firstTransformArg0, firstTransformArg3, positions]);
- } else {
- count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK);
- var images = [];
- for (q = 0; q < count; q++) {
- transformArgs = argsArray[iFirstTransform + (q << 2)];
- var maskParams = argsArray[iFirstPIMXO + (q << 2)][0];
- images.push({
- data: maskParams.data,
- width: maskParams.width,
- height: maskParams.height,
- transform: transformArgs
- });
- }
- fnArray.splice(iFirstSave, count * 4, _util.OPS.paintImageMaskXObjectGroup);
- argsArray.splice(iFirstSave, count * 4, [images]);
- }
- return iFirstSave + 1;
- });
- addState(InitialState, [_util.OPS.save, _util.OPS.transform, _util.OPS.paintImageXObject, _util.OPS.restore], function (context) {
- var argsArray = context.argsArray;
- var iFirstTransform = context.iCurr - 2;
- return argsArray[iFirstTransform][1] === 0 && argsArray[iFirstTransform][2] === 0;
- }, function (context, i) {
- var fnArray = context.fnArray,
- argsArray = context.argsArray;
- var iFirstSave = context.iCurr - 3;
- var pos = (i - iFirstSave) % 4;
- switch (pos) {
- case 0:
- return fnArray[i] === _util.OPS.save;
- case 1:
- if (fnArray[i] !== _util.OPS.transform) {
- return false;
- }
- var iFirstTransform = context.iCurr - 2;
- var firstTransformArg0 = argsArray[iFirstTransform][0];
- var firstTransformArg3 = argsArray[iFirstTransform][3];
- if (argsArray[i][0] !== firstTransformArg0 || argsArray[i][1] !== 0 || argsArray[i][2] !== 0 || argsArray[i][3] !== firstTransformArg3) {
- return false;
- }
- return true;
- case 2:
- if (fnArray[i] !== _util.OPS.paintImageXObject) {
- return false;
- }
- var iFirstPIXO = context.iCurr - 1;
- var firstPIXOArg0 = argsArray[iFirstPIXO][0];
- if (argsArray[i][0] !== firstPIXOArg0) {
- return false;
- }
- return true;
- case 3:
- return fnArray[i] === _util.OPS.restore;
- }
- }, function (context, i) {
- var MIN_IMAGES_IN_BLOCK = 3;
- var MAX_IMAGES_IN_BLOCK = 1000;
- var fnArray = context.fnArray,
- argsArray = context.argsArray;
- var curr = context.iCurr;
- var iFirstSave = curr - 3;
- var iFirstTransform = curr - 2;
- var iFirstPIXO = curr - 1;
- var firstPIXOArg0 = argsArray[iFirstPIXO][0];
- var firstTransformArg0 = argsArray[iFirstTransform][0];
- var firstTransformArg3 = argsArray[iFirstTransform][3];
- var count = Math.min(Math.floor((i - iFirstSave) / 4), MAX_IMAGES_IN_BLOCK);
- if (count < MIN_IMAGES_IN_BLOCK) {
- return i - (i - iFirstSave) % 4;
- }
- var positions = new Float32Array(count * 2);
- var iTransform = iFirstTransform;
- for (var q = 0; q < count; q++, iTransform += 4) {
- var transformArgs = argsArray[iTransform];
- positions[q << 1] = transformArgs[4];
- positions[(q << 1) + 1] = transformArgs[5];
- }
- var args = [firstPIXOArg0, firstTransformArg0, firstTransformArg3, positions];
- fnArray.splice(iFirstSave, count * 4, _util.OPS.paintImageXObjectRepeat);
- argsArray.splice(iFirstSave, count * 4, args);
- return iFirstSave + 1;
- });
- addState(InitialState, [_util.OPS.beginText, _util.OPS.setFont, _util.OPS.setTextMatrix, _util.OPS.showText, _util.OPS.endText], null, function (context, i) {
- var fnArray = context.fnArray,
- argsArray = context.argsArray;
- var iFirstSave = context.iCurr - 4;
- var pos = (i - iFirstSave) % 5;
- switch (pos) {
- case 0:
- return fnArray[i] === _util.OPS.beginText;
- case 1:
- return fnArray[i] === _util.OPS.setFont;
- case 2:
- return fnArray[i] === _util.OPS.setTextMatrix;
- case 3:
- if (fnArray[i] !== _util.OPS.showText) {
- return false;
- }
- var iFirstSetFont = context.iCurr - 3;
- var firstSetFontArg0 = argsArray[iFirstSetFont][0];
- var firstSetFontArg1 = argsArray[iFirstSetFont][1];
- if (argsArray[i][0] !== firstSetFontArg0 || argsArray[i][1] !== firstSetFontArg1) {
- return false;
- }
- return true;
- case 4:
- return fnArray[i] === _util.OPS.endText;
- }
- }, function (context, i) {
- var MIN_CHARS_IN_BLOCK = 3;
- var MAX_CHARS_IN_BLOCK = 1000;
- var fnArray = context.fnArray,
- argsArray = context.argsArray;
- var curr = context.iCurr;
- var iFirstBeginText = curr - 4;
- var iFirstSetFont = curr - 3;
- var iFirstSetTextMatrix = curr - 2;
- var iFirstShowText = curr - 1;
- var iFirstEndText = curr;
- var firstSetFontArg0 = argsArray[iFirstSetFont][0];
- var firstSetFontArg1 = argsArray[iFirstSetFont][1];
- var count = Math.min(Math.floor((i - iFirstBeginText) / 5), MAX_CHARS_IN_BLOCK);
- if (count < MIN_CHARS_IN_BLOCK) {
- return i - (i - iFirstBeginText) % 5;
- }
- var iFirst = iFirstBeginText;
- if (iFirstBeginText >= 4 && fnArray[iFirstBeginText - 4] === fnArray[iFirstSetFont] && fnArray[iFirstBeginText - 3] === fnArray[iFirstSetTextMatrix] && fnArray[iFirstBeginText - 2] === fnArray[iFirstShowText] && fnArray[iFirstBeginText - 1] === fnArray[iFirstEndText] && argsArray[iFirstBeginText - 4][0] === firstSetFontArg0 && argsArray[iFirstBeginText - 4][1] === firstSetFontArg1) {
- count++;
- iFirst -= 5;
- }
- var iEndText = iFirst + 4;
- for (var q = 1; q < count; q++) {
- fnArray.splice(iEndText, 3);
- argsArray.splice(iEndText, 3);
- iEndText += 2;
- }
- return iEndText + 1;
- });
- function QueueOptimizer(queue) {
- this.queue = queue;
- this.state = null;
- this.context = {
- iCurr: 0,
- fnArray: queue.fnArray,
- argsArray: queue.argsArray
- };
- this.match = null;
- this.lastProcessed = 0;
- }
- QueueOptimizer.prototype = {
- _optimize: function _optimize() {
- var fnArray = this.queue.fnArray;
- var i = this.lastProcessed,
- ii = fnArray.length;
- var state = this.state;
- var match = this.match;
- if (!state && !match && i + 1 === ii && !InitialState[fnArray[i]]) {
- this.lastProcessed = ii;
- return;
- }
- var context = this.context;
- while (i < ii) {
- if (match) {
- var iterate = (0, match.iterateFn)(context, i);
- if (iterate) {
- i++;
- continue;
- }
- i = (0, match.processFn)(context, i + 1);
- ii = fnArray.length;
- match = null;
- state = null;
- if (i >= ii) {
- break;
- }
- }
- state = (state || InitialState)[fnArray[i]];
- if (!state || Array.isArray(state)) {
- i++;
- continue;
- }
- context.iCurr = i;
- i++;
- if (state.checkFn && !(0, state.checkFn)(context)) {
- state = null;
- continue;
- }
- match = state;
- state = null;
- }
- this.state = state;
- this.match = match;
- this.lastProcessed = i;
- },
- push: function push(fn, args) {
- this.queue.fnArray.push(fn);
- this.queue.argsArray.push(args);
- this._optimize();
- },
- flush: function flush() {
- while (this.match) {
- var length = this.queue.fnArray.length;
- this.lastProcessed = (0, this.match.processFn)(this.context, length);
- this.match = null;
- this.state = null;
- this._optimize();
- }
- },
- reset: function reset() {
- this.state = null;
- this.match = null;
- this.lastProcessed = 0;
- }
- };
- return QueueOptimizer;
-}();
-var NullOptimizer = function NullOptimizerClosure() {
- function NullOptimizer(queue) {
- this.queue = queue;
- }
- NullOptimizer.prototype = {
- push: function push(fn, args) {
- this.queue.fnArray.push(fn);
- this.queue.argsArray.push(args);
- },
- flush: function flush() {}
- };
- return NullOptimizer;
-}();
-var OperatorList = function OperatorListClosure() {
- var CHUNK_SIZE = 1000;
- var CHUNK_SIZE_ABOUT = CHUNK_SIZE - 5;
- function getTransfers(queue) {
- var transfers = [];
- var fnArray = queue.fnArray,
- argsArray = queue.argsArray;
- for (var i = 0, ii = queue.length; i < ii; i++) {
- switch (fnArray[i]) {
- case _util.OPS.paintInlineImageXObject:
- case _util.OPS.paintInlineImageXObjectGroup:
- case _util.OPS.paintImageMaskXObject:
- var arg = argsArray[i][0];
- ;
- if (!arg.cached) {
- transfers.push(arg.data.buffer);
- }
- break;
- }
- }
- return transfers;
- }
- function OperatorList(intent, messageHandler, pageIndex) {
- this.messageHandler = messageHandler;
- this.fnArray = [];
- this.argsArray = [];
- if (messageHandler && this.intent !== 'oplist') {
- this.optimizer = new QueueOptimizer(this);
- } else {
- this.optimizer = new NullOptimizer(this);
- }
- this.dependencies = Object.create(null);
- this._totalLength = 0;
- this.pageIndex = pageIndex;
- this.intent = intent;
- this.weight = 0;
- }
- OperatorList.prototype = {
- get length() {
- return this.argsArray.length;
- },
- get totalLength() {
- return this._totalLength + this.length;
- },
- addOp: function addOp(fn, args) {
- this.optimizer.push(fn, args);
- this.weight++;
- if (this.messageHandler) {
- if (this.weight >= CHUNK_SIZE) {
- this.flush();
- } else if (this.weight >= CHUNK_SIZE_ABOUT && (fn === _util.OPS.restore || fn === _util.OPS.endText)) {
- this.flush();
- }
- }
- },
- addDependency: function addDependency(dependency) {
- if (dependency in this.dependencies) {
- return;
- }
- this.dependencies[dependency] = true;
- this.addOp(_util.OPS.dependency, [dependency]);
- },
- addDependencies: function addDependencies(dependencies) {
- for (var key in dependencies) {
- this.addDependency(key);
- }
- },
- addOpList: function addOpList(opList) {
- Object.assign(this.dependencies, opList.dependencies);
- for (var i = 0, ii = opList.length; i < ii; i++) {
- this.addOp(opList.fnArray[i], opList.argsArray[i]);
- }
- },
- getIR: function getIR() {
- return {
- fnArray: this.fnArray,
- argsArray: this.argsArray,
- length: this.length
- };
- },
- flush: function flush(lastChunk) {
- this.optimizer.flush();
- var transfers = getTransfers(this);
- var length = this.length;
- this._totalLength += length;
- this.messageHandler.send('RenderPageChunk', {
- operatorList: {
- fnArray: this.fnArray,
- argsArray: this.argsArray,
- lastChunk: lastChunk,
- length: length
- },
- pageIndex: this.pageIndex,
- intent: this.intent
- }, transfers);
- this.dependencies = Object.create(null);
- this.fnArray.length = 0;
- this.argsArray.length = 0;
- this.weight = 0;
- this.optimizer.reset();
- }
- };
- return OperatorList;
-}();
-exports.OperatorList = OperatorList;
-
-/***/ }),
-/* 154 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.PartialEvaluator = undefined;
-
-var _regenerator = __w_pdfjs_require__(131);
-
-var _regenerator2 = _interopRequireDefault(_regenerator);
-
-var _util = __w_pdfjs_require__(2);
-
-var _cmap = __w_pdfjs_require__(155);
-
-var _stream = __w_pdfjs_require__(140);
-
-var _primitives = __w_pdfjs_require__(138);
-
-var _fonts = __w_pdfjs_require__(156);
-
-var _encodings = __w_pdfjs_require__(159);
-
-var _unicode = __w_pdfjs_require__(162);
-
-var _standard_fonts = __w_pdfjs_require__(161);
-
-var _pattern = __w_pdfjs_require__(165);
-
-var _parser = __w_pdfjs_require__(139);
-
-var _bidi = __w_pdfjs_require__(166);
-
-var _colorspace = __w_pdfjs_require__(151);
-
-var _glyphlist = __w_pdfjs_require__(160);
-
-var _metrics = __w_pdfjs_require__(167);
-
-var _function = __w_pdfjs_require__(168);
-
-var _jpeg_stream = __w_pdfjs_require__(146);
-
-var _murmurhash = __w_pdfjs_require__(170);
-
-var _operator_list = __w_pdfjs_require__(153);
-
-var _image = __w_pdfjs_require__(171);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
-
-var PartialEvaluator = function PartialEvaluatorClosure() {
- var DefaultPartialEvaluatorOptions = {
- forceDataSchema: false,
- maxImageSize: -1,
- disableFontFace: false,
- nativeImageDecoderSupport: _util.NativeImageDecoding.DECODE,
- ignoreErrors: false,
- isEvalSupported: true
- };
- function NativeImageDecoder(_ref) {
- var xref = _ref.xref,
- resources = _ref.resources,
- handler = _ref.handler,
- _ref$forceDataSchema = _ref.forceDataSchema,
- forceDataSchema = _ref$forceDataSchema === undefined ? false : _ref$forceDataSchema,
- pdfFunctionFactory = _ref.pdfFunctionFactory;
-
- this.xref = xref;
- this.resources = resources;
- this.handler = handler;
- this.forceDataSchema = forceDataSchema;
- this.pdfFunctionFactory = pdfFunctionFactory;
- }
- NativeImageDecoder.prototype = {
- canDecode: function canDecode(image) {
- return image instanceof _jpeg_stream.JpegStream && NativeImageDecoder.isDecodable(image, this.xref, this.resources, this.pdfFunctionFactory);
- },
- decode: function decode(image) {
- var dict = image.dict;
- var colorSpace = dict.get('ColorSpace', 'CS');
- colorSpace = _colorspace.ColorSpace.parse(colorSpace, this.xref, this.resources, this.pdfFunctionFactory);
- return this.handler.sendWithPromise('JpegDecode', [image.getIR(this.forceDataSchema), colorSpace.numComps]).then(function (_ref2) {
- var data = _ref2.data,
- width = _ref2.width,
- height = _ref2.height;
-
- return new _stream.Stream(data, 0, data.length, image.dict);
- });
- }
- };
- NativeImageDecoder.isSupported = function (image, xref, res, pdfFunctionFactory) {
- var dict = image.dict;
- if (dict.has('DecodeParms') || dict.has('DP')) {
- return false;
- }
- var cs = _colorspace.ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res, pdfFunctionFactory);
- return (cs.name === 'DeviceGray' || cs.name === 'DeviceRGB') && cs.isDefaultDecode(dict.getArray('Decode', 'D'));
- };
- NativeImageDecoder.isDecodable = function (image, xref, res, pdfFunctionFactory) {
- var dict = image.dict;
- if (dict.has('DecodeParms') || dict.has('DP')) {
- return false;
- }
- var cs = _colorspace.ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res, pdfFunctionFactory);
- return (cs.numComps === 1 || cs.numComps === 3) && cs.isDefaultDecode(dict.getArray('Decode', 'D'));
- };
- function PartialEvaluator(_ref3) {
- var _this = this;
-
- var pdfManager = _ref3.pdfManager,
- xref = _ref3.xref,
- handler = _ref3.handler,
- pageIndex = _ref3.pageIndex,
- idFactory = _ref3.idFactory,
- fontCache = _ref3.fontCache,
- builtInCMapCache = _ref3.builtInCMapCache,
- _ref3$options = _ref3.options,
- options = _ref3$options === undefined ? null : _ref3$options,
- pdfFunctionFactory = _ref3.pdfFunctionFactory;
-
- this.pdfManager = pdfManager;
- this.xref = xref;
- this.handler = handler;
- this.pageIndex = pageIndex;
- this.idFactory = idFactory;
- this.fontCache = fontCache;
- this.builtInCMapCache = builtInCMapCache;
- this.options = options || DefaultPartialEvaluatorOptions;
- this.pdfFunctionFactory = pdfFunctionFactory;
- this.fetchBuiltInCMap = function () {
- var _ref4 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee(name) {
- var data;
- return _regenerator2.default.wrap(function _callee$(_context) {
- while (1) {
- switch (_context.prev = _context.next) {
- case 0:
- if (!_this.builtInCMapCache.has(name)) {
- _context.next = 2;
- break;
- }
-
- return _context.abrupt('return', _this.builtInCMapCache.get(name));
-
- case 2:
- _context.next = 4;
- return _this.handler.sendWithPromise('FetchBuiltInCMap', { name: name });
-
- case 4:
- data = _context.sent;
-
- if (data.compressionType !== _util.CMapCompressionType.NONE) {
- _this.builtInCMapCache.set(name, data);
- }
- return _context.abrupt('return', data);
-
- case 7:
- case 'end':
- return _context.stop();
- }
- }
- }, _callee, _this);
- }));
-
- return function (_x) {
- return _ref4.apply(this, arguments);
- };
- }();
- }
- var TIME_SLOT_DURATION_MS = 20;
- var CHECK_TIME_EVERY = 100;
- function TimeSlotManager() {
- this.reset();
- }
- TimeSlotManager.prototype = {
- check: function TimeSlotManager_check() {
- if (++this.checked < CHECK_TIME_EVERY) {
- return false;
- }
- this.checked = 0;
- return this.endTime <= Date.now();
- },
- reset: function TimeSlotManager_reset() {
- this.endTime = Date.now() + TIME_SLOT_DURATION_MS;
- this.checked = 0;
- }
- };
- function normalizeBlendMode(value) {
- if (!(0, _primitives.isName)(value)) {
- return 'source-over';
- }
- switch (value.name) {
- case 'Normal':
- case 'Compatible':
- return 'source-over';
- case 'Multiply':
- return 'multiply';
- case 'Screen':
- return 'screen';
- case 'Overlay':
- return 'overlay';
- case 'Darken':
- return 'darken';
- case 'Lighten':
- return 'lighten';
- case 'ColorDodge':
- return 'color-dodge';
- case 'ColorBurn':
- return 'color-burn';
- case 'HardLight':
- return 'hard-light';
- case 'SoftLight':
- return 'soft-light';
- case 'Difference':
- return 'difference';
- case 'Exclusion':
- return 'exclusion';
- case 'Hue':
- return 'hue';
- case 'Saturation':
- return 'saturation';
- case 'Color':
- return 'color';
- case 'Luminosity':
- return 'luminosity';
- }
- (0, _util.warn)('Unsupported blend mode: ' + value.name);
- return 'source-over';
- }
- var deferred = Promise.resolve();
- var TILING_PATTERN = 1,
- SHADING_PATTERN = 2;
- PartialEvaluator.prototype = {
- clone: function clone() {
- var newOptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DefaultPartialEvaluatorOptions;
-
- var newEvaluator = Object.create(this);
- newEvaluator.options = newOptions;
- return newEvaluator;
- },
-
- hasBlendModes: function PartialEvaluator_hasBlendModes(resources) {
- if (!(0, _primitives.isDict)(resources)) {
- return false;
- }
- var processed = Object.create(null);
- if (resources.objId) {
- processed[resources.objId] = true;
- }
- var nodes = [resources],
- xref = this.xref;
- while (nodes.length) {
- var key, i, ii;
- var node = nodes.shift();
- var graphicStates = node.get('ExtGState');
- if ((0, _primitives.isDict)(graphicStates)) {
- var graphicStatesKeys = graphicStates.getKeys();
- for (i = 0, ii = graphicStatesKeys.length; i < ii; i++) {
- key = graphicStatesKeys[i];
- var graphicState = graphicStates.get(key);
- var bm = graphicState.get('BM');
- if ((0, _primitives.isName)(bm) && bm.name !== 'Normal') {
- return true;
- }
- }
- }
- var xObjects = node.get('XObject');
- if (!(0, _primitives.isDict)(xObjects)) {
- continue;
- }
- var xObjectsKeys = xObjects.getKeys();
- for (i = 0, ii = xObjectsKeys.length; i < ii; i++) {
- key = xObjectsKeys[i];
- var xObject = xObjects.getRaw(key);
- if ((0, _primitives.isRef)(xObject)) {
- if (processed[xObject.toString()]) {
- continue;
- }
- xObject = xref.fetch(xObject);
- }
- if (!(0, _primitives.isStream)(xObject)) {
- continue;
- }
- if (xObject.dict.objId) {
- if (processed[xObject.dict.objId]) {
- continue;
- }
- processed[xObject.dict.objId] = true;
- }
- var xResources = xObject.dict.get('Resources');
- if ((0, _primitives.isDict)(xResources) && (!xResources.objId || !processed[xResources.objId])) {
- nodes.push(xResources);
- if (xResources.objId) {
- processed[xResources.objId] = true;
- }
- }
- }
- }
- return false;
- },
- buildFormXObject: function PartialEvaluator_buildFormXObject(resources, xobj, smask, operatorList, task, initialState) {
- var dict = xobj.dict;
- var matrix = dict.getArray('Matrix');
- var bbox = dict.getArray('BBox');
- var group = dict.get('Group');
- if (group) {
- var groupOptions = {
- matrix: matrix,
- bbox: bbox,
- smask: smask,
- isolated: false,
- knockout: false
- };
- var groupSubtype = group.get('S');
- var colorSpace = null;
- if ((0, _primitives.isName)(groupSubtype, 'Transparency')) {
- groupOptions.isolated = group.get('I') || false;
- groupOptions.knockout = group.get('K') || false;
- if (group.has('CS')) {
- colorSpace = _colorspace.ColorSpace.parse(group.get('CS'), this.xref, resources, this.pdfFunctionFactory);
- }
- }
- if (smask && smask.backdrop) {
- colorSpace = colorSpace || _colorspace.ColorSpace.singletons.rgb;
- smask.backdrop = colorSpace.getRgb(smask.backdrop, 0);
- }
- operatorList.addOp(_util.OPS.beginGroup, [groupOptions]);
- }
- operatorList.addOp(_util.OPS.paintFormXObjectBegin, [matrix, bbox]);
- return this.getOperatorList({
- stream: xobj,
- task: task,
- resources: dict.get('Resources') || resources,
- operatorList: operatorList,
- initialState: initialState
- }).then(function () {
- operatorList.addOp(_util.OPS.paintFormXObjectEnd, []);
- if (group) {
- operatorList.addOp(_util.OPS.endGroup, [groupOptions]);
- }
- });
- },
- buildPaintImageXObject: function buildPaintImageXObject(_ref5) {
- var _this2 = this;
-
- var resources = _ref5.resources,
- image = _ref5.image,
- _ref5$isInline = _ref5.isInline,
- isInline = _ref5$isInline === undefined ? false : _ref5$isInline,
- operatorList = _ref5.operatorList,
- cacheKey = _ref5.cacheKey,
- imageCache = _ref5.imageCache,
- _ref5$forceDisableNat = _ref5.forceDisableNativeImageDecoder,
- forceDisableNativeImageDecoder = _ref5$forceDisableNat === undefined ? false : _ref5$forceDisableNat;
-
- var dict = image.dict;
- var w = dict.get('Width', 'W');
- var h = dict.get('Height', 'H');
- if (!(w && (0, _util.isNum)(w)) || !(h && (0, _util.isNum)(h))) {
- (0, _util.warn)('Image dimensions are missing, or not numbers.');
- return Promise.resolve();
- }
- var maxImageSize = this.options.maxImageSize;
- if (maxImageSize !== -1 && w * h > maxImageSize) {
- (0, _util.warn)('Image exceeded maximum allowed size and was removed.');
- return Promise.resolve();
- }
- var imageMask = dict.get('ImageMask', 'IM') || false;
- var imgData, args;
- if (imageMask) {
- var width = dict.get('Width', 'W');
- var height = dict.get('Height', 'H');
- var bitStrideLength = width + 7 >> 3;
- var imgArray = image.getBytes(bitStrideLength * height, true);
- var decode = dict.getArray('Decode', 'D');
- imgData = _image.PDFImage.createMask({
- imgArray: imgArray,
- width: width,
- height: height,
- imageIsFromDecodeStream: image instanceof _stream.DecodeStream,
- inverseDecode: !!decode && decode[0] > 0
- });
- imgData.cached = true;
- args = [imgData];
- operatorList.addOp(_util.OPS.paintImageMaskXObject, args);
- if (cacheKey) {
- imageCache[cacheKey] = {
- fn: _util.OPS.paintImageMaskXObject,
- args: args
- };
- }
- return Promise.resolve();
- }
- var softMask = dict.get('SMask', 'SM') || false;
- var mask = dict.get('Mask') || false;
- var SMALL_IMAGE_DIMENSIONS = 200;
- if (isInline && !softMask && !mask && !(image instanceof _jpeg_stream.JpegStream) && w + h < SMALL_IMAGE_DIMENSIONS) {
- var imageObj = new _image.PDFImage({
- xref: this.xref,
- res: resources,
- image: image,
- isInline: isInline,
- pdfFunctionFactory: this.pdfFunctionFactory
- });
- imgData = imageObj.createImageData(true);
- operatorList.addOp(_util.OPS.paintInlineImageXObject, [imgData]);
- return Promise.resolve();
- }
- var nativeImageDecoderSupport = forceDisableNativeImageDecoder ? _util.NativeImageDecoding.NONE : this.options.nativeImageDecoderSupport;
- var objId = 'img_' + this.idFactory.createObjId();
- if (nativeImageDecoderSupport !== _util.NativeImageDecoding.NONE && !softMask && !mask && image instanceof _jpeg_stream.JpegStream && NativeImageDecoder.isSupported(image, this.xref, resources, this.pdfFunctionFactory)) {
- return this.handler.sendWithPromise('obj', [objId, this.pageIndex, 'JpegStream', image.getIR(this.options.forceDataSchema)]).then(function () {
- operatorList.addDependency(objId);
- args = [objId, w, h];
- operatorList.addOp(_util.OPS.paintJpegXObject, args);
- if (cacheKey) {
- imageCache[cacheKey] = {
- fn: _util.OPS.paintJpegXObject,
- args: args
- };
- }
- }, function (reason) {
- (0, _util.warn)('Native JPEG decoding failed -- trying to recover: ' + (reason && reason.message));
- return _this2.buildPaintImageXObject({
- resources: resources,
- image: image,
- isInline: isInline,
- operatorList: operatorList,
- cacheKey: cacheKey,
- imageCache: imageCache,
- forceDisableNativeImageDecoder: true
- });
- });
- }
- var nativeImageDecoder = null;
- if (nativeImageDecoderSupport === _util.NativeImageDecoding.DECODE && (image instanceof _jpeg_stream.JpegStream || mask instanceof _jpeg_stream.JpegStream || softMask instanceof _jpeg_stream.JpegStream)) {
- nativeImageDecoder = new NativeImageDecoder({
- xref: this.xref,
- resources: resources,
- handler: this.handler,
- forceDataSchema: this.options.forceDataSchema,
- pdfFunctionFactory: this.pdfFunctionFactory
- });
- }
- operatorList.addDependency(objId);
- args = [objId, w, h];
- _image.PDFImage.buildImage({
- handler: this.handler,
- xref: this.xref,
- res: resources,
- image: image,
- isInline: isInline,
- nativeDecoder: nativeImageDecoder,
- pdfFunctionFactory: this.pdfFunctionFactory
- }).then(function (imageObj) {
- var imgData = imageObj.createImageData(false);
- _this2.handler.send('obj', [objId, _this2.pageIndex, 'Image', imgData], [imgData.data.buffer]);
- }).catch(function (reason) {
- (0, _util.warn)('Unable to decode image: ' + reason);
- _this2.handler.send('obj', [objId, _this2.pageIndex, 'Image', null]);
- });
- operatorList.addOp(_util.OPS.paintImageXObject, args);
- if (cacheKey) {
- imageCache[cacheKey] = {
- fn: _util.OPS.paintImageXObject,
- args: args
- };
- }
- return Promise.resolve();
- },
-
- handleSMask: function PartialEvaluator_handleSmask(smask, resources, operatorList, task, stateManager) {
- var smaskContent = smask.get('G');
- var smaskOptions = {
- subtype: smask.get('S').name,
- backdrop: smask.get('BC')
- };
- var transferObj = smask.get('TR');
- if ((0, _function.isPDFFunction)(transferObj)) {
- var transferFn = this.pdfFunctionFactory.create(transferObj);
- var transferMap = new Uint8Array(256);
- var tmp = new Float32Array(1);
- for (var i = 0; i < 256; i++) {
- tmp[0] = i / 255;
- transferFn(tmp, 0, tmp, 0);
- transferMap[i] = tmp[0] * 255 | 0;
- }
- smaskOptions.transferMap = transferMap;
- }
- return this.buildFormXObject(resources, smaskContent, smaskOptions, operatorList, task, stateManager.state.clone());
- },
- handleTilingType: function handleTilingType(fn, args, resources, pattern, patternDict, operatorList, task) {
- var _this3 = this;
-
- var tilingOpList = new _operator_list.OperatorList();
- var resourcesArray = [patternDict.get('Resources'), resources];
- var patternResources = _primitives.Dict.merge(this.xref, resourcesArray);
- return this.getOperatorList({
- stream: pattern,
- task: task,
- resources: patternResources,
- operatorList: tilingOpList
- }).then(function () {
- return (0, _pattern.getTilingPatternIR)({
- fnArray: tilingOpList.fnArray,
- argsArray: tilingOpList.argsArray
- }, patternDict, args);
- }).then(function (tilingPatternIR) {
- operatorList.addDependencies(tilingOpList.dependencies);
- operatorList.addOp(fn, tilingPatternIR);
- }, function (reason) {
- if (_this3.options.ignoreErrors) {
- _this3.handler.send('UnsupportedFeature', { featureId: _util.UNSUPPORTED_FEATURES.unknown });
- (0, _util.warn)('handleTilingType - ignoring pattern: "' + reason + '".');
- return;
- }
- throw reason;
- });
- },
-
- handleSetFont: function PartialEvaluator_handleSetFont(resources, fontArgs, fontRef, operatorList, task, state) {
- var _this4 = this;
-
- var fontName;
- if (fontArgs) {
- fontArgs = fontArgs.slice();
- fontName = fontArgs[0].name;
- }
- return this.loadFont(fontName, fontRef, resources).then(function (translated) {
- if (!translated.font.isType3Font) {
- return translated;
- }
- return translated.loadType3Data(_this4, resources, operatorList, task).then(function () {
- return translated;
- }).catch(function (reason) {
- _this4.handler.send('UnsupportedFeature', { featureId: _util.UNSUPPORTED_FEATURES.font });
- return new TranslatedFont('g_font_error', new _fonts.ErrorFont('Type3 font load error: ' + reason), translated.font);
- });
- }).then(function (translated) {
- state.font = translated.font;
- translated.send(_this4.handler);
- return translated.loadedName;
- });
- },
- handleText: function PartialEvaluator_handleText(chars, state) {
- var _this5 = this;
-
- var font = state.font;
- var glyphs = font.charsToGlyphs(chars);
- var isAddToPathSet = !!(state.textRenderingMode & _util.TextRenderingMode.ADD_TO_PATH_FLAG);
- if (font.data && (isAddToPathSet || this.options.disableFontFace || state.fillColorSpace.name === 'Pattern')) {
- var buildPath = function buildPath(fontChar) {
- if (!font.renderer.hasBuiltPath(fontChar)) {
- var path = font.renderer.getPathJs(fontChar);
- _this5.handler.send('commonobj', [font.loadedName + '_path_' + fontChar, 'FontPath', path]);
- }
- };
- for (var i = 0, ii = glyphs.length; i < ii; i++) {
- var glyph = glyphs[i];
- buildPath(glyph.fontChar);
- var accent = glyph.accent;
- if (accent && accent.fontChar) {
- buildPath(accent.fontChar);
- }
- }
- }
- return glyphs;
- },
- setGState: function PartialEvaluator_setGState(resources, gState, operatorList, task, stateManager) {
- var _this6 = this;
-
- var gStateObj = [];
- var gStateKeys = gState.getKeys();
- var promise = Promise.resolve();
-
- var _loop = function _loop() {
- var key = gStateKeys[i];
- var value = gState.get(key);
- switch (key) {
- case 'Type':
- break;
- case 'LW':
- case 'LC':
- case 'LJ':
- case 'ML':
- case 'D':
- case 'RI':
- case 'FL':
- case 'CA':
- case 'ca':
- gStateObj.push([key, value]);
- break;
- case 'Font':
- promise = promise.then(function () {
- return _this6.handleSetFont(resources, null, value[0], operatorList, task, stateManager.state).then(function (loadedName) {
- operatorList.addDependency(loadedName);
- gStateObj.push([key, [loadedName, value[1]]]);
- });
- });
- break;
- case 'BM':
- gStateObj.push([key, normalizeBlendMode(value)]);
- break;
- case 'SMask':
- if ((0, _primitives.isName)(value, 'None')) {
- gStateObj.push([key, false]);
- break;
- }
- if ((0, _primitives.isDict)(value)) {
- promise = promise.then(function () {
- return _this6.handleSMask(value, resources, operatorList, task, stateManager);
- });
- gStateObj.push([key, true]);
- } else {
- (0, _util.warn)('Unsupported SMask type');
- }
- break;
- case 'OP':
- case 'op':
- case 'OPM':
- case 'BG':
- case 'BG2':
- case 'UCR':
- case 'UCR2':
- case 'TR':
- case 'TR2':
- case 'HT':
- case 'SM':
- case 'SA':
- case 'AIS':
- case 'TK':
- (0, _util.info)('graphic state operator ' + key);
- break;
- default:
- (0, _util.info)('Unknown graphic state operator ' + key);
- break;
- }
- };
-
- for (var i = 0, ii = gStateKeys.length; i < ii; i++) {
- _loop();
- }
- return promise.then(function () {
- if (gStateObj.length > 0) {
- operatorList.addOp(_util.OPS.setGState, [gStateObj]);
- }
- });
- },
- loadFont: function PartialEvaluator_loadFont(fontName, font, resources) {
- var _this7 = this;
-
- function errorFont() {
- return Promise.resolve(new TranslatedFont('g_font_error', new _fonts.ErrorFont('Font ' + fontName + ' is not available'), font));
- }
- var fontRef,
- xref = this.xref;
- if (font) {
- if (!(0, _primitives.isRef)(font)) {
- throw new Error('The "font" object should be a reference.');
- }
- fontRef = font;
- } else {
- var fontRes = resources.get('Font');
- if (fontRes) {
- fontRef = fontRes.getRaw(fontName);
- } else {
- (0, _util.warn)('fontRes not available');
- return errorFont();
- }
- }
- if (!fontRef) {
- (0, _util.warn)('fontRef not available');
- return errorFont();
- }
- if (this.fontCache.has(fontRef)) {
- return this.fontCache.get(fontRef);
- }
- font = xref.fetchIfRef(fontRef);
- if (!(0, _primitives.isDict)(font)) {
- return errorFont();
- }
- if (font.translated) {
- return font.translated;
- }
- var fontCapability = (0, _util.createPromiseCapability)();
- var preEvaluatedFont = this.preEvaluateFont(font);
- var descriptor = preEvaluatedFont.descriptor;
- var fontRefIsRef = (0, _primitives.isRef)(fontRef),
- fontID;
- if (fontRefIsRef) {
- fontID = fontRef.toString();
- }
- if ((0, _primitives.isDict)(descriptor)) {
- if (!descriptor.fontAliases) {
- descriptor.fontAliases = Object.create(null);
- }
- var fontAliases = descriptor.fontAliases;
- var hash = preEvaluatedFont.hash;
- if (fontAliases[hash]) {
- var aliasFontRef = fontAliases[hash].aliasRef;
- if (fontRefIsRef && aliasFontRef && this.fontCache.has(aliasFontRef)) {
- this.fontCache.putAlias(fontRef, aliasFontRef);
- return this.fontCache.get(fontRef);
- }
- } else {
- fontAliases[hash] = { fontID: _fonts.Font.getFontID() };
- }
- if (fontRefIsRef) {
- fontAliases[hash].aliasRef = fontRef;
- }
- fontID = fontAliases[hash].fontID;
- }
- if (fontRefIsRef) {
- this.fontCache.put(fontRef, fontCapability.promise);
- } else {
- if (!fontID) {
- fontID = this.idFactory.createObjId();
- }
- this.fontCache.put('id_' + fontID, fontCapability.promise);
- }
- (0, _util.assert)(fontID, 'The "fontID" must be defined.');
- font.loadedName = 'g_' + this.pdfManager.docId + '_f' + fontID;
- font.translated = fontCapability.promise;
- var translatedPromise;
- try {
- translatedPromise = this.translateFont(preEvaluatedFont);
- } catch (e) {
- translatedPromise = Promise.reject(e);
- }
- translatedPromise.then(function (translatedFont) {
- if (translatedFont.fontType !== undefined) {
- var xrefFontStats = xref.stats.fontTypes;
- xrefFontStats[translatedFont.fontType] = true;
- }
- fontCapability.resolve(new TranslatedFont(font.loadedName, translatedFont, font));
- }).catch(function (reason) {
- _this7.handler.send('UnsupportedFeature', { featureId: _util.UNSUPPORTED_FEATURES.font });
- try {
- var descriptor = preEvaluatedFont.descriptor;
- var fontFile3 = descriptor && descriptor.get('FontFile3');
- var subtype = fontFile3 && fontFile3.get('Subtype');
- var fontType = (0, _fonts.getFontType)(preEvaluatedFont.type, subtype && subtype.name);
- var xrefFontStats = xref.stats.fontTypes;
- xrefFontStats[fontType] = true;
- } catch (ex) {}
- fontCapability.resolve(new TranslatedFont(font.loadedName, new _fonts.ErrorFont(reason instanceof Error ? reason.message : reason), font));
- });
- return fontCapability.promise;
- },
- buildPath: function PartialEvaluator_buildPath(operatorList, fn, args) {
- var lastIndex = operatorList.length - 1;
- if (!args) {
- args = [];
- }
- if (lastIndex < 0 || operatorList.fnArray[lastIndex] !== _util.OPS.constructPath) {
- operatorList.addOp(_util.OPS.constructPath, [[fn], args]);
- } else {
- var opArgs = operatorList.argsArray[lastIndex];
- opArgs[0].push(fn);
- Array.prototype.push.apply(opArgs[1], args);
- }
- },
- handleColorN: function PartialEvaluator_handleColorN(operatorList, fn, args, cs, patterns, resources, task) {
- var patternName = args[args.length - 1];
- var pattern;
- if ((0, _primitives.isName)(patternName) && (pattern = patterns.get(patternName.name))) {
- var dict = (0, _primitives.isStream)(pattern) ? pattern.dict : pattern;
- var typeNum = dict.get('PatternType');
- if (typeNum === TILING_PATTERN) {
- var color = cs.base ? cs.base.getRgb(args, 0) : null;
- return this.handleTilingType(fn, color, resources, pattern, dict, operatorList, task);
- } else if (typeNum === SHADING_PATTERN) {
- var shading = dict.get('Shading');
- var matrix = dict.getArray('Matrix');
- pattern = _pattern.Pattern.parseShading(shading, matrix, this.xref, resources, this.handler, this.pdfFunctionFactory);
- operatorList.addOp(fn, pattern.getIR());
- return Promise.resolve();
- }
- return Promise.reject(new Error('Unknown PatternType: ' + typeNum));
- }
- operatorList.addOp(fn, args);
- return Promise.resolve();
- },
- getOperatorList: function getOperatorList(_ref6) {
- var _this8 = this;
-
- var stream = _ref6.stream,
- task = _ref6.task,
- resources = _ref6.resources,
- operatorList = _ref6.operatorList,
- _ref6$initialState = _ref6.initialState,
- initialState = _ref6$initialState === undefined ? null : _ref6$initialState;
-
- resources = resources || _primitives.Dict.empty;
- initialState = initialState || new EvalState();
- if (!operatorList) {
- throw new Error('getOperatorList: missing "operatorList" parameter');
- }
- var self = this;
- var xref = this.xref;
- var imageCache = Object.create(null);
- var xobjs = resources.get('XObject') || _primitives.Dict.empty;
- var patterns = resources.get('Pattern') || _primitives.Dict.empty;
- var stateManager = new StateManager(initialState);
- var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager);
- var timeSlotManager = new TimeSlotManager();
- function closePendingRestoreOPS(argument) {
- for (var i = 0, ii = preprocessor.savedStatesDepth; i < ii; i++) {
- operatorList.addOp(_util.OPS.restore, []);
- }
- }
- return new Promise(function promiseBody(resolve, reject) {
- var next = function next(promise) {
- promise.then(function () {
- try {
- promiseBody(resolve, reject);
- } catch (ex) {
- reject(ex);
- }
- }, reject);
- };
- task.ensureNotTerminated();
- timeSlotManager.reset();
- var stop,
- operation = {},
- i,
- ii,
- cs;
- while (!(stop = timeSlotManager.check())) {
- operation.args = null;
- if (!preprocessor.read(operation)) {
- break;
- }
- var args = operation.args;
- var fn = operation.fn;
- switch (fn | 0) {
- case _util.OPS.paintXObject:
- var name = args[0].name;
- if (name && imageCache[name] !== undefined) {
- operatorList.addOp(imageCache[name].fn, imageCache[name].args);
- args = null;
- continue;
- }
- next(new Promise(function (resolveXObject, rejectXObject) {
- if (!name) {
- throw new _util.FormatError('XObject must be referred to by name.');
- }
- var xobj = xobjs.get(name);
- if (!xobj) {
- operatorList.addOp(fn, args);
- resolveXObject();
- return;
- }
- if (!(0, _primitives.isStream)(xobj)) {
- throw new _util.FormatError('XObject should be a stream');
- }
- var type = xobj.dict.get('Subtype');
- if (!(0, _primitives.isName)(type)) {
- throw new _util.FormatError('XObject should have a Name subtype');
- }
- if (type.name === 'Form') {
- stateManager.save();
- self.buildFormXObject(resources, xobj, null, operatorList, task, stateManager.state.clone()).then(function () {
- stateManager.restore();
- resolveXObject();
- }, rejectXObject);
- return;
- } else if (type.name === 'Image') {
- self.buildPaintImageXObject({
- resources: resources,
- image: xobj,
- operatorList: operatorList,
- cacheKey: name,
- imageCache: imageCache
- }).then(resolveXObject, rejectXObject);
- return;
- } else if (type.name === 'PS') {
- (0, _util.info)('Ignored XObject subtype PS');
- } else {
- throw new _util.FormatError('Unhandled XObject subtype ' + type.name);
- }
- resolveXObject();
- }).catch(function (reason) {
- if (self.options.ignoreErrors) {
- self.handler.send('UnsupportedFeature', { featureId: _util.UNSUPPORTED_FEATURES.unknown });
- (0, _util.warn)('getOperatorList - ignoring XObject: "' + reason + '".');
- return;
- }
- throw reason;
- }));
- return;
- case _util.OPS.setFont:
- var fontSize = args[1];
- next(self.handleSetFont(resources, args, null, operatorList, task, stateManager.state).then(function (loadedName) {
- operatorList.addDependency(loadedName);
- operatorList.addOp(_util.OPS.setFont, [loadedName, fontSize]);
- }));
- return;
- case _util.OPS.endInlineImage:
- var cacheKey = args[0].cacheKey;
- if (cacheKey) {
- var cacheEntry = imageCache[cacheKey];
- if (cacheEntry !== undefined) {
- operatorList.addOp(cacheEntry.fn, cacheEntry.args);
- args = null;
- continue;
- }
- }
- next(self.buildPaintImageXObject({
- resources: resources,
- image: args[0],
- isInline: true,
- operatorList: operatorList,
- cacheKey: cacheKey,
- imageCache: imageCache
- }));
- return;
- case _util.OPS.showText:
- args[0] = self.handleText(args[0], stateManager.state);
- break;
- case _util.OPS.showSpacedText:
- var arr = args[0];
- var combinedGlyphs = [];
- var arrLength = arr.length;
- var state = stateManager.state;
- for (i = 0; i < arrLength; ++i) {
- var arrItem = arr[i];
- if ((0, _util.isString)(arrItem)) {
- Array.prototype.push.apply(combinedGlyphs, self.handleText(arrItem, state));
- } else if ((0, _util.isNum)(arrItem)) {
- combinedGlyphs.push(arrItem);
- }
- }
- args[0] = combinedGlyphs;
- fn = _util.OPS.showText;
- break;
- case _util.OPS.nextLineShowText:
- operatorList.addOp(_util.OPS.nextLine);
- args[0] = self.handleText(args[0], stateManager.state);
- fn = _util.OPS.showText;
- break;
- case _util.OPS.nextLineSetSpacingShowText:
- operatorList.addOp(_util.OPS.nextLine);
- operatorList.addOp(_util.OPS.setWordSpacing, [args.shift()]);
- operatorList.addOp(_util.OPS.setCharSpacing, [args.shift()]);
- args[0] = self.handleText(args[0], stateManager.state);
- fn = _util.OPS.showText;
- break;
- case _util.OPS.setTextRenderingMode:
- stateManager.state.textRenderingMode = args[0];
- break;
- case _util.OPS.setFillColorSpace:
- stateManager.state.fillColorSpace = _colorspace.ColorSpace.parse(args[0], xref, resources, self.pdfFunctionFactory);
- continue;
- case _util.OPS.setStrokeColorSpace:
- stateManager.state.strokeColorSpace = _colorspace.ColorSpace.parse(args[0], xref, resources, self.pdfFunctionFactory);
- continue;
- case _util.OPS.setFillColor:
- cs = stateManager.state.fillColorSpace;
- args = cs.getRgb(args, 0);
- fn = _util.OPS.setFillRGBColor;
- break;
- case _util.OPS.setStrokeColor:
- cs = stateManager.state.strokeColorSpace;
- args = cs.getRgb(args, 0);
- fn = _util.OPS.setStrokeRGBColor;
- break;
- case _util.OPS.setFillGray:
- stateManager.state.fillColorSpace = _colorspace.ColorSpace.singletons.gray;
- args = _colorspace.ColorSpace.singletons.gray.getRgb(args, 0);
- fn = _util.OPS.setFillRGBColor;
- break;
- case _util.OPS.setStrokeGray:
- stateManager.state.strokeColorSpace = _colorspace.ColorSpace.singletons.gray;
- args = _colorspace.ColorSpace.singletons.gray.getRgb(args, 0);
- fn = _util.OPS.setStrokeRGBColor;
- break;
- case _util.OPS.setFillCMYKColor:
- stateManager.state.fillColorSpace = _colorspace.ColorSpace.singletons.cmyk;
- args = _colorspace.ColorSpace.singletons.cmyk.getRgb(args, 0);
- fn = _util.OPS.setFillRGBColor;
- break;
- case _util.OPS.setStrokeCMYKColor:
- stateManager.state.strokeColorSpace = _colorspace.ColorSpace.singletons.cmyk;
- args = _colorspace.ColorSpace.singletons.cmyk.getRgb(args, 0);
- fn = _util.OPS.setStrokeRGBColor;
- break;
- case _util.OPS.setFillRGBColor:
- stateManager.state.fillColorSpace = _colorspace.ColorSpace.singletons.rgb;
- args = _colorspace.ColorSpace.singletons.rgb.getRgb(args, 0);
- break;
- case _util.OPS.setStrokeRGBColor:
- stateManager.state.strokeColorSpace = _colorspace.ColorSpace.singletons.rgb;
- args = _colorspace.ColorSpace.singletons.rgb.getRgb(args, 0);
- break;
- case _util.OPS.setFillColorN:
- cs = stateManager.state.fillColorSpace;
- if (cs.name === 'Pattern') {
- next(self.handleColorN(operatorList, _util.OPS.setFillColorN, args, cs, patterns, resources, task));
- return;
- }
- args = cs.getRgb(args, 0);
- fn = _util.OPS.setFillRGBColor;
- break;
- case _util.OPS.setStrokeColorN:
- cs = stateManager.state.strokeColorSpace;
- if (cs.name === 'Pattern') {
- next(self.handleColorN(operatorList, _util.OPS.setStrokeColorN, args, cs, patterns, resources, task));
- return;
- }
- args = cs.getRgb(args, 0);
- fn = _util.OPS.setStrokeRGBColor;
- break;
- case _util.OPS.shadingFill:
- var shadingRes = resources.get('Shading');
- if (!shadingRes) {
- throw new _util.FormatError('No shading resource found');
- }
- var shading = shadingRes.get(args[0].name);
- if (!shading) {
- throw new _util.FormatError('No shading object found');
- }
- var shadingFill = _pattern.Pattern.parseShading(shading, null, xref, resources, self.handler, self.pdfFunctionFactory);
- var patternIR = shadingFill.getIR();
- args = [patternIR];
- fn = _util.OPS.shadingFill;
- break;
- case _util.OPS.setGState:
- var dictName = args[0];
- var extGState = resources.get('ExtGState');
- if (!(0, _primitives.isDict)(extGState) || !extGState.has(dictName.name)) {
- break;
- }
- var gState = extGState.get(dictName.name);
- next(self.setGState(resources, gState, operatorList, task, stateManager));
- return;
- case _util.OPS.moveTo:
- case _util.OPS.lineTo:
- case _util.OPS.curveTo:
- case _util.OPS.curveTo2:
- case _util.OPS.curveTo3:
- case _util.OPS.closePath:
- self.buildPath(operatorList, fn, args);
- continue;
- case _util.OPS.rectangle:
- self.buildPath(operatorList, fn, args);
- continue;
- case _util.OPS.markPoint:
- case _util.OPS.markPointProps:
- case _util.OPS.beginMarkedContent:
- case _util.OPS.beginMarkedContentProps:
- case _util.OPS.endMarkedContent:
- case _util.OPS.beginCompat:
- case _util.OPS.endCompat:
- continue;
- default:
- if (args !== null) {
- for (i = 0, ii = args.length; i < ii; i++) {
- if (args[i] instanceof _primitives.Dict) {
- break;
- }
- }
- if (i < ii) {
- (0, _util.warn)('getOperatorList - ignoring operator: ' + fn);
- continue;
- }
- }
- }
- operatorList.addOp(fn, args);
- }
- if (stop) {
- next(deferred);
- return;
- }
- closePendingRestoreOPS();
- resolve();
- }).catch(function (reason) {
- if (_this8.options.ignoreErrors) {
- _this8.handler.send('UnsupportedFeature', { featureId: _util.UNSUPPORTED_FEATURES.unknown });
- (0, _util.warn)('getOperatorList - ignoring errors during "' + task.name + '" ' + ('task: "' + reason + '".'));
- closePendingRestoreOPS();
- return;
- }
- throw reason;
- });
- },
- getTextContent: function getTextContent(_ref7) {
- var _this9 = this;
-
- var stream = _ref7.stream,
- task = _ref7.task,
- resources = _ref7.resources,
- _ref7$stateManager = _ref7.stateManager,
- stateManager = _ref7$stateManager === undefined ? null : _ref7$stateManager,
- _ref7$normalizeWhites = _ref7.normalizeWhitespace,
- normalizeWhitespace = _ref7$normalizeWhites === undefined ? false : _ref7$normalizeWhites,
- _ref7$combineTextItem = _ref7.combineTextItems,
- combineTextItems = _ref7$combineTextItem === undefined ? false : _ref7$combineTextItem,
- sink = _ref7.sink,
- _ref7$seenStyles = _ref7.seenStyles,
- seenStyles = _ref7$seenStyles === undefined ? Object.create(null) : _ref7$seenStyles;
-
- resources = resources || _primitives.Dict.empty;
- stateManager = stateManager || new StateManager(new TextState());
- var WhitespaceRegexp = /\s/g;
- var textContent = {
- items: [],
- styles: Object.create(null)
- };
- var textContentItem = {
- initialized: false,
- str: [],
- width: 0,
- height: 0,
- vertical: false,
- lastAdvanceWidth: 0,
- lastAdvanceHeight: 0,
- textAdvanceScale: 0,
- spaceWidth: 0,
- fakeSpaceMin: Infinity,
- fakeMultiSpaceMin: Infinity,
- fakeMultiSpaceMax: -0,
- textRunBreakAllowed: false,
- transform: null,
- fontName: null
- };
- var SPACE_FACTOR = 0.3;
- var MULTI_SPACE_FACTOR = 1.5;
- var MULTI_SPACE_FACTOR_MAX = 4;
- var self = this;
- var xref = this.xref;
- var xobjs = null;
- var skipEmptyXObjs = Object.create(null);
- var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager);
- var textState;
- function ensureTextContentItem() {
- if (textContentItem.initialized) {
- return textContentItem;
- }
- var font = textState.font;
- if (!(font.loadedName in seenStyles)) {
- seenStyles[font.loadedName] = true;
- textContent.styles[font.loadedName] = {
- fontFamily: font.fallbackName,
- ascent: font.ascent,
- descent: font.descent,
- vertical: font.vertical
- };
- }
- textContentItem.fontName = font.loadedName;
- var tsm = [textState.fontSize * textState.textHScale, 0, 0, textState.fontSize, 0, textState.textRise];
- if (font.isType3Font && textState.fontMatrix !== _util.FONT_IDENTITY_MATRIX && textState.fontSize === 1) {
- var glyphHeight = font.bbox[3] - font.bbox[1];
- if (glyphHeight > 0) {
- glyphHeight = glyphHeight * textState.fontMatrix[3];
- tsm[3] *= glyphHeight;
- }
- }
- var trm = _util.Util.transform(textState.ctm, _util.Util.transform(textState.textMatrix, tsm));
- textContentItem.transform = trm;
- if (!font.vertical) {
- textContentItem.width = 0;
- textContentItem.height = Math.sqrt(trm[2] * trm[2] + trm[3] * trm[3]);
- textContentItem.vertical = false;
- } else {
- textContentItem.width = Math.sqrt(trm[0] * trm[0] + trm[1] * trm[1]);
- textContentItem.height = 0;
- textContentItem.vertical = true;
- }
- var a = textState.textLineMatrix[0];
- var b = textState.textLineMatrix[1];
- var scaleLineX = Math.sqrt(a * a + b * b);
- a = textState.ctm[0];
- b = textState.ctm[1];
- var scaleCtmX = Math.sqrt(a * a + b * b);
- textContentItem.textAdvanceScale = scaleCtmX * scaleLineX;
- textContentItem.lastAdvanceWidth = 0;
- textContentItem.lastAdvanceHeight = 0;
- var spaceWidth = font.spaceWidth / 1000 * textState.fontSize;
- if (spaceWidth) {
- textContentItem.spaceWidth = spaceWidth;
- textContentItem.fakeSpaceMin = spaceWidth * SPACE_FACTOR;
- textContentItem.fakeMultiSpaceMin = spaceWidth * MULTI_SPACE_FACTOR;
- textContentItem.fakeMultiSpaceMax = spaceWidth * MULTI_SPACE_FACTOR_MAX;
- textContentItem.textRunBreakAllowed = !font.isMonospace;
- } else {
- textContentItem.spaceWidth = 0;
- textContentItem.fakeSpaceMin = Infinity;
- textContentItem.fakeMultiSpaceMin = Infinity;
- textContentItem.fakeMultiSpaceMax = 0;
- textContentItem.textRunBreakAllowed = false;
- }
- textContentItem.initialized = true;
- return textContentItem;
- }
- function replaceWhitespace(str) {
- var i = 0,
- ii = str.length,
- code;
- while (i < ii && (code = str.charCodeAt(i)) >= 0x20 && code <= 0x7F) {
- i++;
- }
- return i < ii ? str.replace(WhitespaceRegexp, ' ') : str;
- }
- function runBidiTransform(textChunk) {
- var str = textChunk.str.join('');
- var bidiResult = (0, _bidi.bidi)(str, -1, textChunk.vertical);
- return {
- str: normalizeWhitespace ? replaceWhitespace(bidiResult.str) : bidiResult.str,
- dir: bidiResult.dir,
- width: textChunk.width,
- height: textChunk.height,
- transform: textChunk.transform,
- fontName: textChunk.fontName
- };
- }
- function handleSetFont(fontName, fontRef) {
- return self.loadFont(fontName, fontRef, resources).then(function (translated) {
- textState.font = translated.font;
- textState.fontMatrix = translated.font.fontMatrix || _util.FONT_IDENTITY_MATRIX;
- });
- }
- function buildTextContentItem(chars) {
- var font = textState.font;
- var textChunk = ensureTextContentItem();
- var width = 0;
- var height = 0;
- var glyphs = font.charsToGlyphs(chars);
- for (var i = 0; i < glyphs.length; i++) {
- var glyph = glyphs[i];
- var glyphWidth = null;
- if (font.vertical && glyph.vmetric) {
- glyphWidth = glyph.vmetric[0];
- } else {
- glyphWidth = glyph.width;
- }
- var glyphUnicode = glyph.unicode;
- var NormalizedUnicodes = (0, _unicode.getNormalizedUnicodes)();
- if (NormalizedUnicodes[glyphUnicode] !== undefined) {
- glyphUnicode = NormalizedUnicodes[glyphUnicode];
- }
- glyphUnicode = (0, _unicode.reverseIfRtl)(glyphUnicode);
- var charSpacing = textState.charSpacing;
- if (glyph.isSpace) {
- var wordSpacing = textState.wordSpacing;
- charSpacing += wordSpacing;
- if (wordSpacing > 0) {
- addFakeSpaces(wordSpacing, textChunk.str);
- }
- }
- var tx = 0;
- var ty = 0;
- if (!font.vertical) {
- var w0 = glyphWidth * textState.fontMatrix[0];
- tx = (w0 * textState.fontSize + charSpacing) * textState.textHScale;
- width += tx;
- } else {
- var w1 = glyphWidth * textState.fontMatrix[0];
- ty = w1 * textState.fontSize + charSpacing;
- height += ty;
- }
- textState.translateTextMatrix(tx, ty);
- textChunk.str.push(glyphUnicode);
- }
- if (!font.vertical) {
- textChunk.lastAdvanceWidth = width;
- textChunk.width += width;
- } else {
- textChunk.lastAdvanceHeight = height;
- textChunk.height += Math.abs(height);
- }
- return textChunk;
- }
- function addFakeSpaces(width, strBuf) {
- if (width < textContentItem.fakeSpaceMin) {
- return;
- }
- if (width < textContentItem.fakeMultiSpaceMin) {
- strBuf.push(' ');
- return;
- }
- var fakeSpaces = Math.round(width / textContentItem.spaceWidth);
- while (fakeSpaces-- > 0) {
- strBuf.push(' ');
- }
- }
- function flushTextContentItem() {
- if (!textContentItem.initialized) {
- return;
- }
- textContentItem.width *= textContentItem.textAdvanceScale;
- textContentItem.height *= textContentItem.textAdvanceScale;
- textContent.items.push(runBidiTransform(textContentItem));
- textContentItem.initialized = false;
- textContentItem.str.length = 0;
- }
- function enqueueChunk() {
- var length = textContent.items.length;
- if (length > 0) {
- sink.enqueue(textContent, length);
- textContent.items = [];
- textContent.styles = Object.create(null);
- }
- }
- var timeSlotManager = new TimeSlotManager();
- return new Promise(function promiseBody(resolve, reject) {
- var next = function next(promise) {
- enqueueChunk();
- Promise.all([promise, sink.ready]).then(function () {
- try {
- promiseBody(resolve, reject);
- } catch (ex) {
- reject(ex);
- }
- }, reject);
- };
- task.ensureNotTerminated();
- timeSlotManager.reset();
- var stop,
- operation = {},
- args = [];
- while (!(stop = timeSlotManager.check())) {
- args.length = 0;
- operation.args = args;
- if (!preprocessor.read(operation)) {
- break;
- }
- textState = stateManager.state;
- var fn = operation.fn;
- args = operation.args;
- var advance, diff;
- switch (fn | 0) {
- case _util.OPS.setFont:
- var fontNameArg = args[0].name,
- fontSizeArg = args[1];
- if (textState.font && fontNameArg === textState.fontName && fontSizeArg === textState.fontSize) {
- break;
- }
- flushTextContentItem();
- textState.fontName = fontNameArg;
- textState.fontSize = fontSizeArg;
- next(handleSetFont(fontNameArg, null));
- return;
- case _util.OPS.setTextRise:
- flushTextContentItem();
- textState.textRise = args[0];
- break;
- case _util.OPS.setHScale:
- flushTextContentItem();
- textState.textHScale = args[0] / 100;
- break;
- case _util.OPS.setLeading:
- flushTextContentItem();
- textState.leading = args[0];
- break;
- case _util.OPS.moveText:
- var isSameTextLine = !textState.font ? false : (textState.font.vertical ? args[0] : args[1]) === 0;
- advance = args[0] - args[1];
- if (combineTextItems && isSameTextLine && textContentItem.initialized && advance > 0 && advance <= textContentItem.fakeMultiSpaceMax) {
- textState.translateTextLineMatrix(args[0], args[1]);
- textContentItem.width += args[0] - textContentItem.lastAdvanceWidth;
- textContentItem.height += args[1] - textContentItem.lastAdvanceHeight;
- diff = args[0] - textContentItem.lastAdvanceWidth - (args[1] - textContentItem.lastAdvanceHeight);
- addFakeSpaces(diff, textContentItem.str);
- break;
- }
- flushTextContentItem();
- textState.translateTextLineMatrix(args[0], args[1]);
- textState.textMatrix = textState.textLineMatrix.slice();
- break;
- case _util.OPS.setLeadingMoveText:
- flushTextContentItem();
- textState.leading = -args[1];
- textState.translateTextLineMatrix(args[0], args[1]);
- textState.textMatrix = textState.textLineMatrix.slice();
- break;
- case _util.OPS.nextLine:
- flushTextContentItem();
- textState.carriageReturn();
- break;
- case _util.OPS.setTextMatrix:
- advance = textState.calcTextLineMatrixAdvance(args[0], args[1], args[2], args[3], args[4], args[5]);
- if (combineTextItems && advance !== null && textContentItem.initialized && advance.value > 0 && advance.value <= textContentItem.fakeMultiSpaceMax) {
- textState.translateTextLineMatrix(advance.width, advance.height);
- textContentItem.width += advance.width - textContentItem.lastAdvanceWidth;
- textContentItem.height += advance.height - textContentItem.lastAdvanceHeight;
- diff = advance.width - textContentItem.lastAdvanceWidth - (advance.height - textContentItem.lastAdvanceHeight);
- addFakeSpaces(diff, textContentItem.str);
- break;
- }
- flushTextContentItem();
- textState.setTextMatrix(args[0], args[1], args[2], args[3], args[4], args[5]);
- textState.setTextLineMatrix(args[0], args[1], args[2], args[3], args[4], args[5]);
- break;
- case _util.OPS.setCharSpacing:
- textState.charSpacing = args[0];
- break;
- case _util.OPS.setWordSpacing:
- textState.wordSpacing = args[0];
- break;
- case _util.OPS.beginText:
- flushTextContentItem();
- textState.textMatrix = _util.IDENTITY_MATRIX.slice();
- textState.textLineMatrix = _util.IDENTITY_MATRIX.slice();
- break;
- case _util.OPS.showSpacedText:
- var items = args[0];
- var offset;
- for (var j = 0, jj = items.length; j < jj; j++) {
- if (typeof items[j] === 'string') {
- buildTextContentItem(items[j]);
- } else if ((0, _util.isNum)(items[j])) {
- ensureTextContentItem();
- advance = items[j] * textState.fontSize / 1000;
- var breakTextRun = false;
- if (textState.font.vertical) {
- offset = advance;
- textState.translateTextMatrix(0, offset);
- breakTextRun = textContentItem.textRunBreakAllowed && advance > textContentItem.fakeMultiSpaceMax;
- if (!breakTextRun) {
- textContentItem.height += offset;
- }
- } else {
- advance = -advance;
- offset = advance * textState.textHScale;
- textState.translateTextMatrix(offset, 0);
- breakTextRun = textContentItem.textRunBreakAllowed && advance > textContentItem.fakeMultiSpaceMax;
- if (!breakTextRun) {
- textContentItem.width += offset;
- }
- }
- if (breakTextRun) {
- flushTextContentItem();
- } else if (advance > 0) {
- addFakeSpaces(advance, textContentItem.str);
- }
- }
- }
- break;
- case _util.OPS.showText:
- buildTextContentItem(args[0]);
- break;
- case _util.OPS.nextLineShowText:
- flushTextContentItem();
- textState.carriageReturn();
- buildTextContentItem(args[0]);
- break;
- case _util.OPS.nextLineSetSpacingShowText:
- flushTextContentItem();
- textState.wordSpacing = args[0];
- textState.charSpacing = args[1];
- textState.carriageReturn();
- buildTextContentItem(args[2]);
- break;
- case _util.OPS.paintXObject:
- flushTextContentItem();
- if (!xobjs) {
- xobjs = resources.get('XObject') || _primitives.Dict.empty;
- }
- var name = args[0].name;
- if (name && skipEmptyXObjs[name] !== undefined) {
- break;
- }
- next(new Promise(function (resolveXObject, rejectXObject) {
- if (!name) {
- throw new _util.FormatError('XObject must be referred to by name.');
- }
- var xobj = xobjs.get(name);
- if (!xobj) {
- resolveXObject();
- return;
- }
- if (!(0, _primitives.isStream)(xobj)) {
- throw new _util.FormatError('XObject should be a stream');
- }
- var type = xobj.dict.get('Subtype');
- if (!(0, _primitives.isName)(type)) {
- throw new _util.FormatError('XObject should have a Name subtype');
- }
- if (type.name !== 'Form') {
- skipEmptyXObjs[name] = true;
- resolveXObject();
- return;
- }
- var currentState = stateManager.state.clone();
- var xObjStateManager = new StateManager(currentState);
- var matrix = xobj.dict.getArray('Matrix');
- if (Array.isArray(matrix) && matrix.length === 6) {
- xObjStateManager.transform(matrix);
- }
- enqueueChunk();
- var sinkWrapper = {
- enqueueInvoked: false,
- enqueue: function enqueue(chunk, size) {
- this.enqueueInvoked = true;
- sink.enqueue(chunk, size);
- },
-
- get desiredSize() {
- return sink.desiredSize;
- },
- get ready() {
- return sink.ready;
- }
- };
- self.getTextContent({
- stream: xobj,
- task: task,
- resources: xobj.dict.get('Resources') || resources,
- stateManager: xObjStateManager,
- normalizeWhitespace: normalizeWhitespace,
- combineTextItems: combineTextItems,
- sink: sinkWrapper,
- seenStyles: seenStyles
- }).then(function () {
- if (!sinkWrapper.enqueueInvoked) {
- skipEmptyXObjs[name] = true;
- }
- resolveXObject();
- }, rejectXObject);
- }).catch(function (reason) {
- if (reason instanceof _util.AbortException) {
- return;
- }
- if (self.options.ignoreErrors) {
- (0, _util.warn)('getTextContent - ignoring XObject: "' + reason + '".');
- return;
- }
- throw reason;
- }));
- return;
- case _util.OPS.setGState:
- flushTextContentItem();
- var dictName = args[0];
- var extGState = resources.get('ExtGState');
- if (!(0, _primitives.isDict)(extGState) || !(0, _primitives.isName)(dictName)) {
- break;
- }
- var gState = extGState.get(dictName.name);
- if (!(0, _primitives.isDict)(gState)) {
- break;
- }
- var gStateFont = gState.get('Font');
- if (gStateFont) {
- textState.fontName = null;
- textState.fontSize = gStateFont[1];
- next(handleSetFont(null, gStateFont[0]));
- return;
- }
- break;
- }
- if (textContent.items.length >= sink.desiredSize) {
- stop = true;
- break;
- }
- }
- if (stop) {
- next(deferred);
- return;
- }
- flushTextContentItem();
- enqueueChunk();
- resolve();
- }).catch(function (reason) {
- if (reason instanceof _util.AbortException) {
- return;
- }
- if (_this9.options.ignoreErrors) {
- (0, _util.warn)('getTextContent - ignoring errors during "' + task.name + '" ' + ('task: "' + reason + '".'));
- flushTextContentItem();
- enqueueChunk();
- return;
- }
- throw reason;
- });
- },
-
- extractDataStructures: function PartialEvaluator_extractDataStructures(dict, baseDict, properties) {
- var _this10 = this;
-
- var xref = this.xref;
- var toUnicode = dict.get('ToUnicode') || baseDict.get('ToUnicode');
- var toUnicodePromise = toUnicode ? this.readToUnicode(toUnicode) : Promise.resolve(undefined);
- if (properties.composite) {
- var cidSystemInfo = dict.get('CIDSystemInfo');
- if ((0, _primitives.isDict)(cidSystemInfo)) {
- properties.cidSystemInfo = {
- registry: (0, _util.stringToPDFString)(cidSystemInfo.get('Registry')),
- ordering: (0, _util.stringToPDFString)(cidSystemInfo.get('Ordering')),
- supplement: cidSystemInfo.get('Supplement')
- };
- }
- var cidToGidMap = dict.get('CIDToGIDMap');
- if ((0, _primitives.isStream)(cidToGidMap)) {
- properties.cidToGidMap = this.readCidToGidMap(cidToGidMap);
- }
- }
- var differences = [];
- var baseEncodingName = null;
- var encoding;
- if (dict.has('Encoding')) {
- encoding = dict.get('Encoding');
- if ((0, _primitives.isDict)(encoding)) {
- baseEncodingName = encoding.get('BaseEncoding');
- baseEncodingName = (0, _primitives.isName)(baseEncodingName) ? baseEncodingName.name : null;
- if (encoding.has('Differences')) {
- var diffEncoding = encoding.get('Differences');
- var index = 0;
- for (var j = 0, jj = diffEncoding.length; j < jj; j++) {
- var data = xref.fetchIfRef(diffEncoding[j]);
- if ((0, _util.isNum)(data)) {
- index = data;
- } else if ((0, _primitives.isName)(data)) {
- differences[index++] = data.name;
- } else {
- throw new _util.FormatError('Invalid entry in \'Differences\' array: ' + data);
- }
- }
- }
- } else if ((0, _primitives.isName)(encoding)) {
- baseEncodingName = encoding.name;
- } else {
- throw new _util.FormatError('Encoding is not a Name nor a Dict');
- }
- if (baseEncodingName !== 'MacRomanEncoding' && baseEncodingName !== 'MacExpertEncoding' && baseEncodingName !== 'WinAnsiEncoding') {
- baseEncodingName = null;
- }
- }
- if (baseEncodingName) {
- properties.defaultEncoding = (0, _encodings.getEncoding)(baseEncodingName).slice();
- } else {
- var isSymbolicFont = !!(properties.flags & _fonts.FontFlags.Symbolic);
- var isNonsymbolicFont = !!(properties.flags & _fonts.FontFlags.Nonsymbolic);
- encoding = _encodings.StandardEncoding;
- if (properties.type === 'TrueType' && !isNonsymbolicFont) {
- encoding = _encodings.WinAnsiEncoding;
- }
- if (isSymbolicFont) {
- encoding = _encodings.MacRomanEncoding;
- if (!properties.file) {
- if (/Symbol/i.test(properties.name)) {
- encoding = _encodings.SymbolSetEncoding;
- } else if (/Dingbats/i.test(properties.name)) {
- encoding = _encodings.ZapfDingbatsEncoding;
- }
- }
- }
- properties.defaultEncoding = encoding;
- }
- properties.differences = differences;
- properties.baseEncodingName = baseEncodingName;
- properties.hasEncoding = !!baseEncodingName || differences.length > 0;
- properties.dict = dict;
- return toUnicodePromise.then(function (toUnicode) {
- properties.toUnicode = toUnicode;
- return _this10.buildToUnicode(properties);
- }).then(function (toUnicode) {
- properties.toUnicode = toUnicode;
- return properties;
- });
- },
- _buildSimpleFontToUnicode: function _buildSimpleFontToUnicode(properties) {
- (0, _util.assert)(!properties.composite, 'Must be a simple font.');
- var toUnicode = [],
- charcode = void 0,
- glyphName = void 0;
- var encoding = properties.defaultEncoding.slice();
- var baseEncodingName = properties.baseEncodingName;
- var differences = properties.differences;
- for (charcode in differences) {
- glyphName = differences[charcode];
- if (glyphName === '.notdef') {
- continue;
- }
- encoding[charcode] = glyphName;
- }
- var glyphsUnicodeMap = (0, _glyphlist.getGlyphsUnicode)();
- for (charcode in encoding) {
- glyphName = encoding[charcode];
- if (glyphName === '') {
- continue;
- } else if (glyphsUnicodeMap[glyphName] === undefined) {
- var code = 0;
- switch (glyphName[0]) {
- case 'G':
- if (glyphName.length === 3) {
- code = parseInt(glyphName.substring(1), 16);
- }
- break;
- case 'g':
- if (glyphName.length === 5) {
- code = parseInt(glyphName.substring(1), 16);
- }
- break;
- case 'C':
- case 'c':
- if (glyphName.length >= 3) {
- code = +glyphName.substring(1);
- }
- break;
- default:
- var unicode = (0, _unicode.getUnicodeForGlyph)(glyphName, glyphsUnicodeMap);
- if (unicode !== -1) {
- code = unicode;
- }
- }
- if (code) {
- if (baseEncodingName && code === +charcode) {
- var baseEncoding = (0, _encodings.getEncoding)(baseEncodingName);
- if (baseEncoding && (glyphName = baseEncoding[charcode])) {
- toUnicode[charcode] = String.fromCharCode(glyphsUnicodeMap[glyphName]);
- continue;
- }
- }
- toUnicode[charcode] = String.fromCharCode(code);
- }
- continue;
- }
- toUnicode[charcode] = String.fromCharCode(glyphsUnicodeMap[glyphName]);
- }
- return new _fonts.ToUnicodeMap(toUnicode);
- },
- buildToUnicode: function buildToUnicode(properties) {
- properties.hasIncludedToUnicodeMap = !!properties.toUnicode && properties.toUnicode.length > 0;
- if (properties.hasIncludedToUnicodeMap) {
- if (!properties.composite && properties.hasEncoding) {
- properties.fallbackToUnicode = this._buildSimpleFontToUnicode(properties);
- }
- return Promise.resolve(properties.toUnicode);
- }
- if (!properties.composite) {
- return Promise.resolve(this._buildSimpleFontToUnicode(properties));
- }
- if (properties.composite && (properties.cMap.builtInCMap && !(properties.cMap instanceof _cmap.IdentityCMap) || properties.cidSystemInfo.registry === 'Adobe' && (properties.cidSystemInfo.ordering === 'GB1' || properties.cidSystemInfo.ordering === 'CNS1' || properties.cidSystemInfo.ordering === 'Japan1' || properties.cidSystemInfo.ordering === 'Korea1'))) {
- var registry = properties.cidSystemInfo.registry;
- var ordering = properties.cidSystemInfo.ordering;
- var ucs2CMapName = _primitives.Name.get(registry + '-' + ordering + '-UCS2');
- return _cmap.CMapFactory.create({
- encoding: ucs2CMapName,
- fetchBuiltInCMap: this.fetchBuiltInCMap,
- useCMap: null
- }).then(function (ucs2CMap) {
- var cMap = properties.cMap;
- var toUnicode = [];
- cMap.forEach(function (charcode, cid) {
- if (cid > 0xffff) {
- throw new _util.FormatError('Max size of CID is 65,535');
- }
- var ucs2 = ucs2CMap.lookup(cid);
- if (ucs2) {
- toUnicode[charcode] = String.fromCharCode((ucs2.charCodeAt(0) << 8) + ucs2.charCodeAt(1));
- }
- });
- return new _fonts.ToUnicodeMap(toUnicode);
- });
- }
- return Promise.resolve(new _fonts.IdentityToUnicodeMap(properties.firstChar, properties.lastChar));
- },
-
- readToUnicode: function PartialEvaluator_readToUnicode(toUnicode) {
- var cmapObj = toUnicode;
- if ((0, _primitives.isName)(cmapObj)) {
- return _cmap.CMapFactory.create({
- encoding: cmapObj,
- fetchBuiltInCMap: this.fetchBuiltInCMap,
- useCMap: null
- }).then(function (cmap) {
- if (cmap instanceof _cmap.IdentityCMap) {
- return new _fonts.IdentityToUnicodeMap(0, 0xFFFF);
- }
- return new _fonts.ToUnicodeMap(cmap.getMap());
- });
- } else if ((0, _primitives.isStream)(cmapObj)) {
- return _cmap.CMapFactory.create({
- encoding: cmapObj,
- fetchBuiltInCMap: this.fetchBuiltInCMap,
- useCMap: null
- }).then(function (cmap) {
- if (cmap instanceof _cmap.IdentityCMap) {
- return new _fonts.IdentityToUnicodeMap(0, 0xFFFF);
- }
- var map = new Array(cmap.length);
- cmap.forEach(function (charCode, token) {
- var str = [];
- for (var k = 0; k < token.length; k += 2) {
- var w1 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1);
- if ((w1 & 0xF800) !== 0xD800) {
- str.push(w1);
- continue;
- }
- k += 2;
- var w2 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1);
- str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000);
- }
- map[charCode] = String.fromCharCode.apply(String, str);
- });
- return new _fonts.ToUnicodeMap(map);
- });
- }
- return Promise.resolve(null);
- },
- readCidToGidMap: function PartialEvaluator_readCidToGidMap(cidToGidStream) {
- var glyphsData = cidToGidStream.getBytes();
- var result = [];
- for (var j = 0, jj = glyphsData.length; j < jj; j++) {
- var glyphID = glyphsData[j++] << 8 | glyphsData[j];
- if (glyphID === 0) {
- continue;
- }
- var code = j >> 1;
- result[code] = glyphID;
- }
- return result;
- },
- extractWidths: function PartialEvaluator_extractWidths(dict, descriptor, properties) {
- var xref = this.xref;
- var glyphsWidths = [];
- var defaultWidth = 0;
- var glyphsVMetrics = [];
- var defaultVMetrics;
- var i, ii, j, jj, start, code, widths;
- if (properties.composite) {
- defaultWidth = dict.has('DW') ? dict.get('DW') : 1000;
- widths = dict.get('W');
- if (widths) {
- for (i = 0, ii = widths.length; i < ii; i++) {
- start = xref.fetchIfRef(widths[i++]);
- code = xref.fetchIfRef(widths[i]);
- if (Array.isArray(code)) {
- for (j = 0, jj = code.length; j < jj; j++) {
- glyphsWidths[start++] = xref.fetchIfRef(code[j]);
- }
- } else {
- var width = xref.fetchIfRef(widths[++i]);
- for (j = start; j <= code; j++) {
- glyphsWidths[j] = width;
- }
- }
- }
- }
- if (properties.vertical) {
- var vmetrics = dict.getArray('DW2') || [880, -1000];
- defaultVMetrics = [vmetrics[1], defaultWidth * 0.5, vmetrics[0]];
- vmetrics = dict.get('W2');
- if (vmetrics) {
- for (i = 0, ii = vmetrics.length; i < ii; i++) {
- start = xref.fetchIfRef(vmetrics[i++]);
- code = xref.fetchIfRef(vmetrics[i]);
- if (Array.isArray(code)) {
- for (j = 0, jj = code.length; j < jj; j++) {
- glyphsVMetrics[start++] = [xref.fetchIfRef(code[j++]), xref.fetchIfRef(code[j++]), xref.fetchIfRef(code[j])];
- }
- } else {
- var vmetric = [xref.fetchIfRef(vmetrics[++i]), xref.fetchIfRef(vmetrics[++i]), xref.fetchIfRef(vmetrics[++i])];
- for (j = start; j <= code; j++) {
- glyphsVMetrics[j] = vmetric;
- }
- }
- }
- }
- }
- } else {
- var firstChar = properties.firstChar;
- widths = dict.get('Widths');
- if (widths) {
- j = firstChar;
- for (i = 0, ii = widths.length; i < ii; i++) {
- glyphsWidths[j++] = xref.fetchIfRef(widths[i]);
- }
- defaultWidth = parseFloat(descriptor.get('MissingWidth')) || 0;
- } else {
- var baseFontName = dict.get('BaseFont');
- if ((0, _primitives.isName)(baseFontName)) {
- var metrics = this.getBaseFontMetrics(baseFontName.name);
- glyphsWidths = this.buildCharCodeToWidth(metrics.widths, properties);
- defaultWidth = metrics.defaultWidth;
- }
- }
- }
- var isMonospace = true;
- var firstWidth = defaultWidth;
- for (var glyph in glyphsWidths) {
- var glyphWidth = glyphsWidths[glyph];
- if (!glyphWidth) {
- continue;
- }
- if (!firstWidth) {
- firstWidth = glyphWidth;
- continue;
- }
- if (firstWidth !== glyphWidth) {
- isMonospace = false;
- break;
- }
- }
- if (isMonospace) {
- properties.flags |= _fonts.FontFlags.FixedPitch;
- }
- properties.defaultWidth = defaultWidth;
- properties.widths = glyphsWidths;
- properties.defaultVMetrics = defaultVMetrics;
- properties.vmetrics = glyphsVMetrics;
- },
- isSerifFont: function PartialEvaluator_isSerifFont(baseFontName) {
- var fontNameWoStyle = baseFontName.split('-')[0];
- return fontNameWoStyle in (0, _standard_fonts.getSerifFonts)() || fontNameWoStyle.search(/serif/gi) !== -1;
- },
- getBaseFontMetrics: function PartialEvaluator_getBaseFontMetrics(name) {
- var defaultWidth = 0;
- var widths = [];
- var monospace = false;
- var stdFontMap = (0, _standard_fonts.getStdFontMap)();
- var lookupName = stdFontMap[name] || name;
- var Metrics = (0, _metrics.getMetrics)();
- if (!(lookupName in Metrics)) {
- if (this.isSerifFont(name)) {
- lookupName = 'Times-Roman';
- } else {
- lookupName = 'Helvetica';
- }
- }
- var glyphWidths = Metrics[lookupName];
- if ((0, _util.isNum)(glyphWidths)) {
- defaultWidth = glyphWidths;
- monospace = true;
- } else {
- widths = glyphWidths();
- }
- return {
- defaultWidth: defaultWidth,
- monospace: monospace,
- widths: widths
- };
- },
- buildCharCodeToWidth: function PartialEvaluator_bulildCharCodeToWidth(widthsByGlyphName, properties) {
- var widths = Object.create(null);
- var differences = properties.differences;
- var encoding = properties.defaultEncoding;
- for (var charCode = 0; charCode < 256; charCode++) {
- if (charCode in differences && widthsByGlyphName[differences[charCode]]) {
- widths[charCode] = widthsByGlyphName[differences[charCode]];
- continue;
- }
- if (charCode in encoding && widthsByGlyphName[encoding[charCode]]) {
- widths[charCode] = widthsByGlyphName[encoding[charCode]];
- continue;
- }
- }
- return widths;
- },
- preEvaluateFont: function PartialEvaluator_preEvaluateFont(dict) {
- var baseDict = dict;
- var type = dict.get('Subtype');
- if (!(0, _primitives.isName)(type)) {
- throw new _util.FormatError('invalid font Subtype');
- }
- var composite = false;
- var uint8array;
- if (type.name === 'Type0') {
- var df = dict.get('DescendantFonts');
- if (!df) {
- throw new _util.FormatError('Descendant fonts are not specified');
- }
- dict = Array.isArray(df) ? this.xref.fetchIfRef(df[0]) : df;
- type = dict.get('Subtype');
- if (!(0, _primitives.isName)(type)) {
- throw new _util.FormatError('invalid font Subtype');
- }
- composite = true;
- }
- var descriptor = dict.get('FontDescriptor');
- if (descriptor) {
- var hash = new _murmurhash.MurmurHash3_64();
- var encoding = baseDict.getRaw('Encoding');
- if ((0, _primitives.isName)(encoding)) {
- hash.update(encoding.name);
- } else if ((0, _primitives.isRef)(encoding)) {
- hash.update(encoding.toString());
- } else if ((0, _primitives.isDict)(encoding)) {
- var keys = encoding.getKeys();
- for (var i = 0, ii = keys.length; i < ii; i++) {
- var entry = encoding.getRaw(keys[i]);
- if ((0, _primitives.isName)(entry)) {
- hash.update(entry.name);
- } else if ((0, _primitives.isRef)(entry)) {
- hash.update(entry.toString());
- } else if (Array.isArray(entry)) {
- var diffLength = entry.length,
- diffBuf = new Array(diffLength);
- for (var j = 0; j < diffLength; j++) {
- var diffEntry = entry[j];
- if ((0, _primitives.isName)(diffEntry)) {
- diffBuf[j] = diffEntry.name;
- } else if ((0, _util.isNum)(diffEntry) || (0, _primitives.isRef)(diffEntry)) {
- diffBuf[j] = diffEntry.toString();
- }
- }
- hash.update(diffBuf.join());
- }
- }
- }
- var toUnicode = dict.get('ToUnicode') || baseDict.get('ToUnicode');
- if ((0, _primitives.isStream)(toUnicode)) {
- var stream = toUnicode.str || toUnicode;
- uint8array = stream.buffer ? new Uint8Array(stream.buffer.buffer, 0, stream.bufferLength) : new Uint8Array(stream.bytes.buffer, stream.start, stream.end - stream.start);
- hash.update(uint8array);
- } else if ((0, _primitives.isName)(toUnicode)) {
- hash.update(toUnicode.name);
- }
- var widths = dict.get('Widths') || baseDict.get('Widths');
- if (widths) {
- uint8array = new Uint8Array(new Uint32Array(widths).buffer);
- hash.update(uint8array);
- }
- }
- return {
- descriptor: descriptor,
- dict: dict,
- baseDict: baseDict,
- composite: composite,
- type: type.name,
- hash: hash ? hash.hexdigest() : ''
- };
- },
- translateFont: function PartialEvaluator_translateFont(preEvaluatedFont) {
- var _this11 = this;
-
- var baseDict = preEvaluatedFont.baseDict;
- var dict = preEvaluatedFont.dict;
- var composite = preEvaluatedFont.composite;
- var descriptor = preEvaluatedFont.descriptor;
- var type = preEvaluatedFont.type;
- var maxCharIndex = composite ? 0xFFFF : 0xFF;
- var properties;
- if (!descriptor) {
- if (type === 'Type3') {
- descriptor = new _primitives.Dict(null);
- descriptor.set('FontName', _primitives.Name.get(type));
- descriptor.set('FontBBox', dict.getArray('FontBBox'));
- } else {
- var baseFontName = dict.get('BaseFont');
- if (!(0, _primitives.isName)(baseFontName)) {
- throw new _util.FormatError('Base font is not specified');
- }
- baseFontName = baseFontName.name.replace(/[,_]/g, '-');
- var metrics = this.getBaseFontMetrics(baseFontName);
- var fontNameWoStyle = baseFontName.split('-')[0];
- var flags = (this.isSerifFont(fontNameWoStyle) ? _fonts.FontFlags.Serif : 0) | (metrics.monospace ? _fonts.FontFlags.FixedPitch : 0) | ((0, _standard_fonts.getSymbolsFonts)()[fontNameWoStyle] ? _fonts.FontFlags.Symbolic : _fonts.FontFlags.Nonsymbolic);
- properties = {
- type: type,
- name: baseFontName,
- widths: metrics.widths,
- defaultWidth: metrics.defaultWidth,
- flags: flags,
- firstChar: 0,
- lastChar: maxCharIndex
- };
- return this.extractDataStructures(dict, dict, properties).then(function (properties) {
- properties.widths = _this11.buildCharCodeToWidth(metrics.widths, properties);
- return new _fonts.Font(baseFontName, null, properties);
- });
- }
- }
- var firstChar = dict.get('FirstChar') || 0;
- var lastChar = dict.get('LastChar') || maxCharIndex;
- var fontName = descriptor.get('FontName');
- var baseFont = dict.get('BaseFont');
- if ((0, _util.isString)(fontName)) {
- fontName = _primitives.Name.get(fontName);
- }
- if ((0, _util.isString)(baseFont)) {
- baseFont = _primitives.Name.get(baseFont);
- }
- if (type !== 'Type3') {
- var fontNameStr = fontName && fontName.name;
- var baseFontStr = baseFont && baseFont.name;
- if (fontNameStr !== baseFontStr) {
- (0, _util.info)('The FontDescriptor\'s FontName is "' + fontNameStr + '" but should be the same as the Font\'s BaseFont "' + baseFontStr + '"');
- if (fontNameStr && baseFontStr && baseFontStr.indexOf(fontNameStr) === 0) {
- fontName = baseFont;
- }
- }
- }
- fontName = fontName || baseFont;
- if (!(0, _primitives.isName)(fontName)) {
- throw new _util.FormatError('invalid font name');
- }
- var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3');
- if (fontFile) {
- if (fontFile.dict) {
- var subtype = fontFile.dict.get('Subtype');
- if (subtype) {
- subtype = subtype.name;
- }
- var length1 = fontFile.dict.get('Length1');
- var length2 = fontFile.dict.get('Length2');
- var length3 = fontFile.dict.get('Length3');
- }
- }
- properties = {
- type: type,
- name: fontName.name,
- subtype: subtype,
- file: fontFile,
- length1: length1,
- length2: length2,
- length3: length3,
- loadedName: baseDict.loadedName,
- composite: composite,
- wideChars: composite,
- fixedPitch: false,
- fontMatrix: dict.getArray('FontMatrix') || _util.FONT_IDENTITY_MATRIX,
- firstChar: firstChar || 0,
- lastChar: lastChar || maxCharIndex,
- bbox: descriptor.getArray('FontBBox'),
- ascent: descriptor.get('Ascent'),
- descent: descriptor.get('Descent'),
- xHeight: descriptor.get('XHeight'),
- capHeight: descriptor.get('CapHeight'),
- flags: descriptor.get('Flags'),
- italicAngle: descriptor.get('ItalicAngle'),
- isType3Font: false
- };
- var cMapPromise;
- if (composite) {
- var cidEncoding = baseDict.get('Encoding');
- if ((0, _primitives.isName)(cidEncoding)) {
- properties.cidEncoding = cidEncoding.name;
- }
- cMapPromise = _cmap.CMapFactory.create({
- encoding: cidEncoding,
- fetchBuiltInCMap: this.fetchBuiltInCMap,
- useCMap: null
- }).then(function (cMap) {
- properties.cMap = cMap;
- properties.vertical = properties.cMap.vertical;
- });
- } else {
- cMapPromise = Promise.resolve(undefined);
- }
- return cMapPromise.then(function () {
- return _this11.extractDataStructures(dict, baseDict, properties);
- }).then(function (properties) {
- _this11.extractWidths(dict, descriptor, properties);
- if (type === 'Type3') {
- properties.isType3Font = true;
- }
- return new _fonts.Font(fontName.name, fontFile, properties);
- });
- }
- };
- return PartialEvaluator;
-}();
-var TranslatedFont = function TranslatedFontClosure() {
- function TranslatedFont(loadedName, font, dict) {
- this.loadedName = loadedName;
- this.font = font;
- this.dict = dict;
- this.type3Loaded = null;
- this.sent = false;
- }
- TranslatedFont.prototype = {
- send: function send(handler) {
- if (this.sent) {
- return;
- }
- var fontData = this.font.exportData();
- handler.send('commonobj', [this.loadedName, 'Font', fontData]);
- this.sent = true;
- },
- loadType3Data: function loadType3Data(evaluator, resources, parentOperatorList, task) {
- if (!this.font.isType3Font) {
- throw new Error('Must be a Type3 font.');
- }
- if (this.type3Loaded) {
- return this.type3Loaded;
- }
- var type3Options = Object.create(evaluator.options);
- type3Options.ignoreErrors = false;
- var type3Evaluator = evaluator.clone(type3Options);
- var translatedFont = this.font;
- var loadCharProcsPromise = Promise.resolve();
- var charProcs = this.dict.get('CharProcs');
- var fontResources = this.dict.get('Resources') || resources;
- var charProcKeys = charProcs.getKeys();
- var charProcOperatorList = Object.create(null);
-
- var _loop2 = function _loop2() {
- var key = charProcKeys[i];
- loadCharProcsPromise = loadCharProcsPromise.then(function () {
- var glyphStream = charProcs.get(key);
- var operatorList = new _operator_list.OperatorList();
- return type3Evaluator.getOperatorList({
- stream: glyphStream,
- task: task,
- resources: fontResources,
- operatorList: operatorList
- }).then(function () {
- charProcOperatorList[key] = operatorList.getIR();
- parentOperatorList.addDependencies(operatorList.dependencies);
- }).catch(function (reason) {
- (0, _util.warn)('Type3 font resource "' + key + '" is not available.');
- var operatorList = new _operator_list.OperatorList();
- charProcOperatorList[key] = operatorList.getIR();
- });
- });
- };
-
- for (var i = 0, n = charProcKeys.length; i < n; ++i) {
- _loop2();
- }
- this.type3Loaded = loadCharProcsPromise.then(function () {
- translatedFont.charProcOperatorList = charProcOperatorList;
- });
- return this.type3Loaded;
- }
- };
- return TranslatedFont;
-}();
-var StateManager = function StateManagerClosure() {
- function StateManager(initialState) {
- this.state = initialState;
- this.stateStack = [];
- }
- StateManager.prototype = {
- save: function save() {
- var old = this.state;
- this.stateStack.push(this.state);
- this.state = old.clone();
- },
- restore: function restore() {
- var prev = this.stateStack.pop();
- if (prev) {
- this.state = prev;
- }
- },
- transform: function transform(args) {
- this.state.ctm = _util.Util.transform(this.state.ctm, args);
- }
- };
- return StateManager;
-}();
-var TextState = function TextStateClosure() {
- function TextState() {
- this.ctm = new Float32Array(_util.IDENTITY_MATRIX);
- this.fontName = null;
- this.fontSize = 0;
- this.font = null;
- this.fontMatrix = _util.FONT_IDENTITY_MATRIX;
- this.textMatrix = _util.IDENTITY_MATRIX.slice();
- this.textLineMatrix = _util.IDENTITY_MATRIX.slice();
- this.charSpacing = 0;
- this.wordSpacing = 0;
- this.leading = 0;
- this.textHScale = 1;
- this.textRise = 0;
- }
- TextState.prototype = {
- setTextMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) {
- var m = this.textMatrix;
- m[0] = a;
- m[1] = b;
- m[2] = c;
- m[3] = d;
- m[4] = e;
- m[5] = f;
- },
- setTextLineMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) {
- var m = this.textLineMatrix;
- m[0] = a;
- m[1] = b;
- m[2] = c;
- m[3] = d;
- m[4] = e;
- m[5] = f;
- },
- translateTextMatrix: function TextState_translateTextMatrix(x, y) {
- var m = this.textMatrix;
- m[4] = m[0] * x + m[2] * y + m[4];
- m[5] = m[1] * x + m[3] * y + m[5];
- },
- translateTextLineMatrix: function TextState_translateTextMatrix(x, y) {
- var m = this.textLineMatrix;
- m[4] = m[0] * x + m[2] * y + m[4];
- m[5] = m[1] * x + m[3] * y + m[5];
- },
- calcTextLineMatrixAdvance: function TextState_calcTextLineMatrixAdvance(a, b, c, d, e, f) {
- var font = this.font;
- if (!font) {
- return null;
- }
- var m = this.textLineMatrix;
- if (!(a === m[0] && b === m[1] && c === m[2] && d === m[3])) {
- return null;
- }
- var txDiff = e - m[4],
- tyDiff = f - m[5];
- if (font.vertical && txDiff !== 0 || !font.vertical && tyDiff !== 0) {
- return null;
- }
- var tx,
- ty,
- denominator = a * d - b * c;
- if (font.vertical) {
- tx = -tyDiff * c / denominator;
- ty = tyDiff * a / denominator;
- } else {
- tx = txDiff * d / denominator;
- ty = -txDiff * b / denominator;
- }
- return {
- width: tx,
- height: ty,
- value: font.vertical ? ty : tx
- };
- },
- calcRenderMatrix: function TextState_calcRendeMatrix(ctm) {
- var tsm = [this.fontSize * this.textHScale, 0, 0, this.fontSize, 0, this.textRise];
- return _util.Util.transform(ctm, _util.Util.transform(this.textMatrix, tsm));
- },
- carriageReturn: function TextState_carriageReturn() {
- this.translateTextLineMatrix(0, -this.leading);
- this.textMatrix = this.textLineMatrix.slice();
- },
- clone: function TextState_clone() {
- var clone = Object.create(this);
- clone.textMatrix = this.textMatrix.slice();
- clone.textLineMatrix = this.textLineMatrix.slice();
- clone.fontMatrix = this.fontMatrix.slice();
- return clone;
- }
- };
- return TextState;
-}();
-var EvalState = function EvalStateClosure() {
- function EvalState() {
- this.ctm = new Float32Array(_util.IDENTITY_MATRIX);
- this.font = null;
- this.textRenderingMode = _util.TextRenderingMode.FILL;
- this.fillColorSpace = _colorspace.ColorSpace.singletons.gray;
- this.strokeColorSpace = _colorspace.ColorSpace.singletons.gray;
- }
- EvalState.prototype = {
- clone: function CanvasExtraState_clone() {
- return Object.create(this);
- }
- };
- return EvalState;
-}();
-var EvaluatorPreprocessor = function EvaluatorPreprocessorClosure() {
- var getOPMap = (0, _util.getLookupTableFactory)(function (t) {
- t['w'] = {
- id: _util.OPS.setLineWidth,
- numArgs: 1,
- variableArgs: false
- };
- t['J'] = {
- id: _util.OPS.setLineCap,
- numArgs: 1,
- variableArgs: false
- };
- t['j'] = {
- id: _util.OPS.setLineJoin,
- numArgs: 1,
- variableArgs: false
- };
- t['M'] = {
- id: _util.OPS.setMiterLimit,
- numArgs: 1,
- variableArgs: false
- };
- t['d'] = {
- id: _util.OPS.setDash,
- numArgs: 2,
- variableArgs: false
- };
- t['ri'] = {
- id: _util.OPS.setRenderingIntent,
- numArgs: 1,
- variableArgs: false
- };
- t['i'] = {
- id: _util.OPS.setFlatness,
- numArgs: 1,
- variableArgs: false
- };
- t['gs'] = {
- id: _util.OPS.setGState,
- numArgs: 1,
- variableArgs: false
- };
- t['q'] = {
- id: _util.OPS.save,
- numArgs: 0,
- variableArgs: false
- };
- t['Q'] = {
- id: _util.OPS.restore,
- numArgs: 0,
- variableArgs: false
- };
- t['cm'] = {
- id: _util.OPS.transform,
- numArgs: 6,
- variableArgs: false
- };
- t['m'] = {
- id: _util.OPS.moveTo,
- numArgs: 2,
- variableArgs: false
- };
- t['l'] = {
- id: _util.OPS.lineTo,
- numArgs: 2,
- variableArgs: false
- };
- t['c'] = {
- id: _util.OPS.curveTo,
- numArgs: 6,
- variableArgs: false
- };
- t['v'] = {
- id: _util.OPS.curveTo2,
- numArgs: 4,
- variableArgs: false
- };
- t['y'] = {
- id: _util.OPS.curveTo3,
- numArgs: 4,
- variableArgs: false
- };
- t['h'] = {
- id: _util.OPS.closePath,
- numArgs: 0,
- variableArgs: false
- };
- t['re'] = {
- id: _util.OPS.rectangle,
- numArgs: 4,
- variableArgs: false
- };
- t['S'] = {
- id: _util.OPS.stroke,
- numArgs: 0,
- variableArgs: false
- };
- t['s'] = {
- id: _util.OPS.closeStroke,
- numArgs: 0,
- variableArgs: false
- };
- t['f'] = {
- id: _util.OPS.fill,
- numArgs: 0,
- variableArgs: false
- };
- t['F'] = {
- id: _util.OPS.fill,
- numArgs: 0,
- variableArgs: false
- };
- t['f*'] = {
- id: _util.OPS.eoFill,
- numArgs: 0,
- variableArgs: false
- };
- t['B'] = {
- id: _util.OPS.fillStroke,
- numArgs: 0,
- variableArgs: false
- };
- t['B*'] = {
- id: _util.OPS.eoFillStroke,
- numArgs: 0,
- variableArgs: false
- };
- t['b'] = {
- id: _util.OPS.closeFillStroke,
- numArgs: 0,
- variableArgs: false
- };
- t['b*'] = {
- id: _util.OPS.closeEOFillStroke,
- numArgs: 0,
- variableArgs: false
- };
- t['n'] = {
- id: _util.OPS.endPath,
- numArgs: 0,
- variableArgs: false
- };
- t['W'] = {
- id: _util.OPS.clip,
- numArgs: 0,
- variableArgs: false
- };
- t['W*'] = {
- id: _util.OPS.eoClip,
- numArgs: 0,
- variableArgs: false
- };
- t['BT'] = {
- id: _util.OPS.beginText,
- numArgs: 0,
- variableArgs: false
- };
- t['ET'] = {
- id: _util.OPS.endText,
- numArgs: 0,
- variableArgs: false
- };
- t['Tc'] = {
- id: _util.OPS.setCharSpacing,
- numArgs: 1,
- variableArgs: false
- };
- t['Tw'] = {
- id: _util.OPS.setWordSpacing,
- numArgs: 1,
- variableArgs: false
- };
- t['Tz'] = {
- id: _util.OPS.setHScale,
- numArgs: 1,
- variableArgs: false
- };
- t['TL'] = {
- id: _util.OPS.setLeading,
- numArgs: 1,
- variableArgs: false
- };
- t['Tf'] = {
- id: _util.OPS.setFont,
- numArgs: 2,
- variableArgs: false
- };
- t['Tr'] = {
- id: _util.OPS.setTextRenderingMode,
- numArgs: 1,
- variableArgs: false
- };
- t['Ts'] = {
- id: _util.OPS.setTextRise,
- numArgs: 1,
- variableArgs: false
- };
- t['Td'] = {
- id: _util.OPS.moveText,
- numArgs: 2,
- variableArgs: false
- };
- t['TD'] = {
- id: _util.OPS.setLeadingMoveText,
- numArgs: 2,
- variableArgs: false
- };
- t['Tm'] = {
- id: _util.OPS.setTextMatrix,
- numArgs: 6,
- variableArgs: false
- };
- t['T*'] = {
- id: _util.OPS.nextLine,
- numArgs: 0,
- variableArgs: false
- };
- t['Tj'] = {
- id: _util.OPS.showText,
- numArgs: 1,
- variableArgs: false
- };
- t['TJ'] = {
- id: _util.OPS.showSpacedText,
- numArgs: 1,
- variableArgs: false
- };
- t['\''] = {
- id: _util.OPS.nextLineShowText,
- numArgs: 1,
- variableArgs: false
- };
- t['"'] = {
- id: _util.OPS.nextLineSetSpacingShowText,
- numArgs: 3,
- variableArgs: false
- };
- t['d0'] = {
- id: _util.OPS.setCharWidth,
- numArgs: 2,
- variableArgs: false
- };
- t['d1'] = {
- id: _util.OPS.setCharWidthAndBounds,
- numArgs: 6,
- variableArgs: false
- };
- t['CS'] = {
- id: _util.OPS.setStrokeColorSpace,
- numArgs: 1,
- variableArgs: false
- };
- t['cs'] = {
- id: _util.OPS.setFillColorSpace,
- numArgs: 1,
- variableArgs: false
- };
- t['SC'] = {
- id: _util.OPS.setStrokeColor,
- numArgs: 4,
- variableArgs: true
- };
- t['SCN'] = {
- id: _util.OPS.setStrokeColorN,
- numArgs: 33,
- variableArgs: true
- };
- t['sc'] = {
- id: _util.OPS.setFillColor,
- numArgs: 4,
- variableArgs: true
- };
- t['scn'] = {
- id: _util.OPS.setFillColorN,
- numArgs: 33,
- variableArgs: true
- };
- t['G'] = {
- id: _util.OPS.setStrokeGray,
- numArgs: 1,
- variableArgs: false
- };
- t['g'] = {
- id: _util.OPS.setFillGray,
- numArgs: 1,
- variableArgs: false
- };
- t['RG'] = {
- id: _util.OPS.setStrokeRGBColor,
- numArgs: 3,
- variableArgs: false
- };
- t['rg'] = {
- id: _util.OPS.setFillRGBColor,
- numArgs: 3,
- variableArgs: false
- };
- t['K'] = {
- id: _util.OPS.setStrokeCMYKColor,
- numArgs: 4,
- variableArgs: false
- };
- t['k'] = {
- id: _util.OPS.setFillCMYKColor,
- numArgs: 4,
- variableArgs: false
- };
- t['sh'] = {
- id: _util.OPS.shadingFill,
- numArgs: 1,
- variableArgs: false
- };
- t['BI'] = {
- id: _util.OPS.beginInlineImage,
- numArgs: 0,
- variableArgs: false
- };
- t['ID'] = {
- id: _util.OPS.beginImageData,
- numArgs: 0,
- variableArgs: false
- };
- t['EI'] = {
- id: _util.OPS.endInlineImage,
- numArgs: 1,
- variableArgs: false
- };
- t['Do'] = {
- id: _util.OPS.paintXObject,
- numArgs: 1,
- variableArgs: false
- };
- t['MP'] = {
- id: _util.OPS.markPoint,
- numArgs: 1,
- variableArgs: false
- };
- t['DP'] = {
- id: _util.OPS.markPointProps,
- numArgs: 2,
- variableArgs: false
- };
- t['BMC'] = {
- id: _util.OPS.beginMarkedContent,
- numArgs: 1,
- variableArgs: false
- };
- t['BDC'] = {
- id: _util.OPS.beginMarkedContentProps,
- numArgs: 2,
- variableArgs: false
- };
- t['EMC'] = {
- id: _util.OPS.endMarkedContent,
- numArgs: 0,
- variableArgs: false
- };
- t['BX'] = {
- id: _util.OPS.beginCompat,
- numArgs: 0,
- variableArgs: false
- };
- t['EX'] = {
- id: _util.OPS.endCompat,
- numArgs: 0,
- variableArgs: false
- };
- t['BM'] = null;
- t['BD'] = null;
- t['true'] = null;
- t['fa'] = null;
- t['fal'] = null;
- t['fals'] = null;
- t['false'] = null;
- t['nu'] = null;
- t['nul'] = null;
- t['null'] = null;
- });
- var MAX_INVALID_PATH_OPS = 20;
- function EvaluatorPreprocessor(stream, xref, stateManager) {
- this.opMap = getOPMap();
- this.parser = new _parser.Parser(new _parser.Lexer(stream, this.opMap), false, xref);
- this.stateManager = stateManager;
- this.nonProcessedArgs = [];
- this._numInvalidPathOPS = 0;
- }
- EvaluatorPreprocessor.prototype = {
- get savedStatesDepth() {
- return this.stateManager.stateStack.length;
- },
- read: function EvaluatorPreprocessor_read(operation) {
- var args = operation.args;
- while (true) {
- var obj = this.parser.getObj();
- if ((0, _primitives.isCmd)(obj)) {
- var cmd = obj.cmd;
- var opSpec = this.opMap[cmd];
- if (!opSpec) {
- (0, _util.warn)('Unknown command "' + cmd + '".');
- continue;
- }
- var fn = opSpec.id;
- var numArgs = opSpec.numArgs;
- var argsLength = args !== null ? args.length : 0;
- if (!opSpec.variableArgs) {
- if (argsLength !== numArgs) {
- var nonProcessedArgs = this.nonProcessedArgs;
- while (argsLength > numArgs) {
- nonProcessedArgs.push(args.shift());
- argsLength--;
- }
- while (argsLength < numArgs && nonProcessedArgs.length !== 0) {
- if (args === null) {
- args = [];
- }
- args.unshift(nonProcessedArgs.pop());
- argsLength++;
- }
- }
- if (argsLength < numArgs) {
- var partialMsg = 'command ' + cmd + ': expected ' + numArgs + ' args, ' + ('but received ' + argsLength + ' args.');
- if (fn >= _util.OPS.moveTo && fn <= _util.OPS.endPath && ++this._numInvalidPathOPS > MAX_INVALID_PATH_OPS) {
- throw new _util.FormatError('Invalid ' + partialMsg);
- }
- (0, _util.warn)('Skipping ' + partialMsg);
- if (args !== null) {
- args.length = 0;
- }
- continue;
- }
- } else if (argsLength > numArgs) {
- (0, _util.info)('Command ' + cmd + ': expected [0, ' + numArgs + '] args, ' + ('but received ' + argsLength + ' args.'));
- }
- this.preprocessCommand(fn, args);
- operation.fn = fn;
- operation.args = args;
- return true;
- }
- if ((0, _primitives.isEOF)(obj)) {
- return false;
- }
- if (obj !== null) {
- if (args === null) {
- args = [];
- }
- args.push(obj);
- if (args.length > 33) {
- throw new _util.FormatError('Too many arguments');
- }
- }
- }
- },
- preprocessCommand: function EvaluatorPreprocessor_preprocessCommand(fn, args) {
- switch (fn | 0) {
- case _util.OPS.save:
- this.stateManager.save();
- break;
- case _util.OPS.restore:
- this.stateManager.restore();
- break;
- case _util.OPS.transform:
- this.stateManager.transform(args);
- break;
- }
- }
- };
- return EvaluatorPreprocessor;
-}();
-exports.PartialEvaluator = PartialEvaluator;
-
-/***/ }),
-/* 155 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.CMapFactory = exports.IdentityCMap = exports.CMap = undefined;
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-var _util = __w_pdfjs_require__(2);
-
-var _primitives = __w_pdfjs_require__(138);
-
-var _parser = __w_pdfjs_require__(139);
-
-var _stream = __w_pdfjs_require__(140);
-
-function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
-
-function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-var BUILT_IN_CMAPS = ['Adobe-GB1-UCS2', 'Adobe-CNS1-UCS2', 'Adobe-Japan1-UCS2', 'Adobe-Korea1-UCS2', '78-EUC-H', '78-EUC-V', '78-H', '78-RKSJ-H', '78-RKSJ-V', '78-V', '78ms-RKSJ-H', '78ms-RKSJ-V', '83pv-RKSJ-H', '90ms-RKSJ-H', '90ms-RKSJ-V', '90msp-RKSJ-H', '90msp-RKSJ-V', '90pv-RKSJ-H', '90pv-RKSJ-V', 'Add-H', 'Add-RKSJ-H', 'Add-RKSJ-V', 'Add-V', 'Adobe-CNS1-0', 'Adobe-CNS1-1', 'Adobe-CNS1-2', 'Adobe-CNS1-3', 'Adobe-CNS1-4', 'Adobe-CNS1-5', 'Adobe-CNS1-6', 'Adobe-GB1-0', 'Adobe-GB1-1', 'Adobe-GB1-2', 'Adobe-GB1-3', 'Adobe-GB1-4', 'Adobe-GB1-5', 'Adobe-Japan1-0', 'Adobe-Japan1-1', 'Adobe-Japan1-2', 'Adobe-Japan1-3', 'Adobe-Japan1-4', 'Adobe-Japan1-5', 'Adobe-Japan1-6', 'Adobe-Korea1-0', 'Adobe-Korea1-1', 'Adobe-Korea1-2', 'B5-H', 'B5-V', 'B5pc-H', 'B5pc-V', 'CNS-EUC-H', 'CNS-EUC-V', 'CNS1-H', 'CNS1-V', 'CNS2-H', 'CNS2-V', 'ETHK-B5-H', 'ETHK-B5-V', 'ETen-B5-H', 'ETen-B5-V', 'ETenms-B5-H', 'ETenms-B5-V', 'EUC-H', 'EUC-V', 'Ext-H', 'Ext-RKSJ-H', 'Ext-RKSJ-V', 'Ext-V', 'GB-EUC-H', 'GB-EUC-V', 'GB-H', 'GB-V', 'GBK-EUC-H', 'GBK-EUC-V', 'GBK2K-H', 'GBK2K-V', 'GBKp-EUC-H', 'GBKp-EUC-V', 'GBT-EUC-H', 'GBT-EUC-V', 'GBT-H', 'GBT-V', 'GBTpc-EUC-H', 'GBTpc-EUC-V', 'GBpc-EUC-H', 'GBpc-EUC-V', 'H', 'HKdla-B5-H', 'HKdla-B5-V', 'HKdlb-B5-H', 'HKdlb-B5-V', 'HKgccs-B5-H', 'HKgccs-B5-V', 'HKm314-B5-H', 'HKm314-B5-V', 'HKm471-B5-H', 'HKm471-B5-V', 'HKscs-B5-H', 'HKscs-B5-V', 'Hankaku', 'Hiragana', 'KSC-EUC-H', 'KSC-EUC-V', 'KSC-H', 'KSC-Johab-H', 'KSC-Johab-V', 'KSC-V', 'KSCms-UHC-H', 'KSCms-UHC-HW-H', 'KSCms-UHC-HW-V', 'KSCms-UHC-V', 'KSCpc-EUC-H', 'KSCpc-EUC-V', 'Katakana', 'NWP-H', 'NWP-V', 'RKSJ-H', 'RKSJ-V', 'Roman', 'UniCNS-UCS2-H', 'UniCNS-UCS2-V', 'UniCNS-UTF16-H', 'UniCNS-UTF16-V', 'UniCNS-UTF32-H', 'UniCNS-UTF32-V', 'UniCNS-UTF8-H', 'UniCNS-UTF8-V', 'UniGB-UCS2-H', 'UniGB-UCS2-V', 'UniGB-UTF16-H', 'UniGB-UTF16-V', 'UniGB-UTF32-H', 'UniGB-UTF32-V', 'UniGB-UTF8-H', 'UniGB-UTF8-V', 'UniJIS-UCS2-H', 'UniJIS-UCS2-HW-H', 'UniJIS-UCS2-HW-V', 'UniJIS-UCS2-V', 'UniJIS-UTF16-H', 'UniJIS-UTF16-V', 'UniJIS-UTF32-H', 'UniJIS-UTF32-V', 'UniJIS-UTF8-H', 'UniJIS-UTF8-V', 'UniJIS2004-UTF16-H', 'UniJIS2004-UTF16-V', 'UniJIS2004-UTF32-H', 'UniJIS2004-UTF32-V', 'UniJIS2004-UTF8-H', 'UniJIS2004-UTF8-V', 'UniJISPro-UCS2-HW-V', 'UniJISPro-UCS2-V', 'UniJISPro-UTF8-V', 'UniJISX0213-UTF32-H', 'UniJISX0213-UTF32-V', 'UniJISX02132004-UTF32-H', 'UniJISX02132004-UTF32-V', 'UniKS-UCS2-H', 'UniKS-UCS2-V', 'UniKS-UTF16-H', 'UniKS-UTF16-V', 'UniKS-UTF32-H', 'UniKS-UTF32-V', 'UniKS-UTF8-H', 'UniKS-UTF8-V', 'V', 'WP-Symbol'];
-
-var CMap = function () {
- function CMap() {
- var builtInCMap = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
-
- _classCallCheck(this, CMap);
-
- this.codespaceRanges = [[], [], [], []];
- this.numCodespaceRanges = 0;
- this._map = [];
- this.name = '';
- this.vertical = false;
- this.useCMap = null;
- this.builtInCMap = builtInCMap;
- }
-
- _createClass(CMap, [{
- key: 'addCodespaceRange',
- value: function addCodespaceRange(n, low, high) {
- this.codespaceRanges[n - 1].push(low, high);
- this.numCodespaceRanges++;
- }
- }, {
- key: 'mapCidRange',
- value: function mapCidRange(low, high, dstLow) {
- while (low <= high) {
- this._map[low++] = dstLow++;
- }
- }
- }, {
- key: 'mapBfRange',
- value: function mapBfRange(low, high, dstLow) {
- var lastByte = dstLow.length - 1;
- while (low <= high) {
- this._map[low++] = dstLow;
- dstLow = dstLow.substring(0, lastByte) + String.fromCharCode(dstLow.charCodeAt(lastByte) + 1);
- }
- }
- }, {
- key: 'mapBfRangeToArray',
- value: function mapBfRangeToArray(low, high, array) {
- var i = 0,
- ii = array.length;
- while (low <= high && i < ii) {
- this._map[low] = array[i++];
- ++low;
- }
- }
- }, {
- key: 'mapOne',
- value: function mapOne(src, dst) {
- this._map[src] = dst;
- }
- }, {
- key: 'lookup',
- value: function lookup(code) {
- return this._map[code];
- }
- }, {
- key: 'contains',
- value: function contains(code) {
- return this._map[code] !== undefined;
- }
- }, {
- key: 'forEach',
- value: function forEach(callback) {
- var map = this._map;
- var length = map.length;
- if (length <= 0x10000) {
- for (var i = 0; i < length; i++) {
- if (map[i] !== undefined) {
- callback(i, map[i]);
- }
- }
- } else {
- for (var _i in map) {
- callback(_i, map[_i]);
- }
- }
- }
- }, {
- key: 'charCodeOf',
- value: function charCodeOf(value) {
- var map = this._map;
- if (map.length <= 0x10000) {
- return map.indexOf(value);
- }
- for (var charCode in map) {
- if (map[charCode] === value) {
- return charCode | 0;
- }
- }
- return -1;
- }
- }, {
- key: 'getMap',
- value: function getMap() {
- return this._map;
- }
- }, {
- key: 'readCharCode',
- value: function readCharCode(str, offset, out) {
- var c = 0;
- var codespaceRanges = this.codespaceRanges;
- for (var n = 0, nn = codespaceRanges.length; n < nn; n++) {
- c = (c << 8 | str.charCodeAt(offset + n)) >>> 0;
- var codespaceRange = codespaceRanges[n];
- for (var k = 0, kk = codespaceRange.length; k < kk;) {
- var low = codespaceRange[k++];
- var high = codespaceRange[k++];
- if (c >= low && c <= high) {
- out.charcode = c;
- out.length = n + 1;
- return;
- }
- }
- }
- out.charcode = 0;
- out.length = 1;
- }
- }, {
- key: 'length',
- get: function get() {
- return this._map.length;
- }
- }, {
- key: 'isIdentityCMap',
- get: function get() {
- if (!(this.name === 'Identity-H' || this.name === 'Identity-V')) {
- return false;
- }
- if (this._map.length !== 0x10000) {
- return false;
- }
- for (var i = 0; i < 0x10000; i++) {
- if (this._map[i] !== i) {
- return false;
- }
- }
- return true;
- }
- }]);
-
- return CMap;
-}();
-
-var IdentityCMap = function (_CMap) {
- _inherits(IdentityCMap, _CMap);
-
- function IdentityCMap(vertical, n) {
- _classCallCheck(this, IdentityCMap);
-
- var _this = _possibleConstructorReturn(this, (IdentityCMap.__proto__ || Object.getPrototypeOf(IdentityCMap)).call(this));
-
- _this.vertical = vertical;
- _this.addCodespaceRange(n, 0, 0xffff);
- return _this;
- }
-
- _createClass(IdentityCMap, [{
- key: 'mapCidRange',
- value: function mapCidRange(low, high, dstLow) {
- (0, _util.unreachable)('should not call mapCidRange');
- }
- }, {
- key: 'mapBfRange',
- value: function mapBfRange(low, high, dstLow) {
- (0, _util.unreachable)('should not call mapBfRange');
- }
- }, {
- key: 'mapBfRangeToArray',
- value: function mapBfRangeToArray(low, high, array) {
- (0, _util.unreachable)('should not call mapBfRangeToArray');
- }
- }, {
- key: 'mapOne',
- value: function mapOne(src, dst) {
- (0, _util.unreachable)('should not call mapCidOne');
- }
- }, {
- key: 'lookup',
- value: function lookup(code) {
- return Number.isInteger(code) && code <= 0xffff ? code : undefined;
- }
- }, {
- key: 'contains',
- value: function contains(code) {
- return Number.isInteger(code) && code <= 0xffff;
- }
- }, {
- key: 'forEach',
- value: function forEach(callback) {
- for (var i = 0; i <= 0xffff; i++) {
- callback(i, i);
- }
- }
- }, {
- key: 'charCodeOf',
- value: function charCodeOf(value) {
- return Number.isInteger(value) && value <= 0xffff ? value : -1;
- }
- }, {
- key: 'getMap',
- value: function getMap() {
- var map = new Array(0x10000);
- for (var i = 0; i <= 0xffff; i++) {
- map[i] = i;
- }
- return map;
- }
- }, {
- key: 'length',
- get: function get() {
- return 0x10000;
- }
- }, {
- key: 'isIdentityCMap',
- get: function get() {
- (0, _util.unreachable)('should not access .isIdentityCMap');
- }
- }]);
-
- return IdentityCMap;
-}(CMap);
-
-var BinaryCMapReader = function BinaryCMapReaderClosure() {
- function hexToInt(a, size) {
- var n = 0;
- for (var i = 0; i <= size; i++) {
- n = n << 8 | a[i];
- }
- return n >>> 0;
- }
- function hexToStr(a, size) {
- if (size === 1) {
- return String.fromCharCode(a[0], a[1]);
- }
- if (size === 3) {
- return String.fromCharCode(a[0], a[1], a[2], a[3]);
- }
- return String.fromCharCode.apply(null, a.subarray(0, size + 1));
- }
- function addHex(a, b, size) {
- var c = 0;
- for (var i = size; i >= 0; i--) {
- c += a[i] + b[i];
- a[i] = c & 255;
- c >>= 8;
- }
- }
- function incHex(a, size) {
- var c = 1;
- for (var i = size; i >= 0 && c > 0; i--) {
- c += a[i];
- a[i] = c & 255;
- c >>= 8;
- }
- }
- var MAX_NUM_SIZE = 16;
- var MAX_ENCODED_NUM_SIZE = 19;
- function BinaryCMapStream(data) {
- this.buffer = data;
- this.pos = 0;
- this.end = data.length;
- this.tmpBuf = new Uint8Array(MAX_ENCODED_NUM_SIZE);
- }
- BinaryCMapStream.prototype = {
- readByte: function readByte() {
- if (this.pos >= this.end) {
- return -1;
- }
- return this.buffer[this.pos++];
- },
- readNumber: function readNumber() {
- var n = 0;
- var last;
- do {
- var b = this.readByte();
- if (b < 0) {
- throw new _util.FormatError('unexpected EOF in bcmap');
- }
- last = !(b & 0x80);
- n = n << 7 | b & 0x7F;
- } while (!last);
- return n;
- },
- readSigned: function readSigned() {
- var n = this.readNumber();
- return n & 1 ? ~(n >>> 1) : n >>> 1;
- },
- readHex: function readHex(num, size) {
- num.set(this.buffer.subarray(this.pos, this.pos + size + 1));
- this.pos += size + 1;
- },
- readHexNumber: function readHexNumber(num, size) {
- var last;
- var stack = this.tmpBuf,
- sp = 0;
- do {
- var b = this.readByte();
- if (b < 0) {
- throw new _util.FormatError('unexpected EOF in bcmap');
- }
- last = !(b & 0x80);
- stack[sp++] = b & 0x7F;
- } while (!last);
- var i = size,
- buffer = 0,
- bufferSize = 0;
- while (i >= 0) {
- while (bufferSize < 8 && stack.length > 0) {
- buffer = stack[--sp] << bufferSize | buffer;
- bufferSize += 7;
- }
- num[i] = buffer & 255;
- i--;
- buffer >>= 8;
- bufferSize -= 8;
- }
- },
- readHexSigned: function readHexSigned(num, size) {
- this.readHexNumber(num, size);
- var sign = num[size] & 1 ? 255 : 0;
- var c = 0;
- for (var i = 0; i <= size; i++) {
- c = (c & 1) << 8 | num[i];
- num[i] = c >> 1 ^ sign;
- }
- },
- readString: function readString() {
- var len = this.readNumber();
- var s = '';
- for (var i = 0; i < len; i++) {
- s += String.fromCharCode(this.readNumber());
- }
- return s;
- }
- };
- function processBinaryCMap(data, cMap, extend) {
- return new Promise(function (resolve, reject) {
- var stream = new BinaryCMapStream(data);
- var header = stream.readByte();
- cMap.vertical = !!(header & 1);
- var useCMap = null;
- var start = new Uint8Array(MAX_NUM_SIZE);
- var end = new Uint8Array(MAX_NUM_SIZE);
- var char = new Uint8Array(MAX_NUM_SIZE);
- var charCode = new Uint8Array(MAX_NUM_SIZE);
- var tmp = new Uint8Array(MAX_NUM_SIZE);
- var code;
- var b;
- while ((b = stream.readByte()) >= 0) {
- var type = b >> 5;
- if (type === 7) {
- switch (b & 0x1F) {
- case 0:
- stream.readString();
- break;
- case 1:
- useCMap = stream.readString();
- break;
- }
- continue;
- }
- var sequence = !!(b & 0x10);
- var dataSize = b & 15;
- if (dataSize + 1 > MAX_NUM_SIZE) {
- throw new Error('processBinaryCMap: Invalid dataSize.');
- }
- var ucs2DataSize = 1;
- var subitemsCount = stream.readNumber();
- var i;
- switch (type) {
- case 0:
- stream.readHex(start, dataSize);
- stream.readHexNumber(end, dataSize);
- addHex(end, start, dataSize);
- cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), hexToInt(end, dataSize));
- for (i = 1; i < subitemsCount; i++) {
- incHex(end, dataSize);
- stream.readHexNumber(start, dataSize);
- addHex(start, end, dataSize);
- stream.readHexNumber(end, dataSize);
- addHex(end, start, dataSize);
- cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), hexToInt(end, dataSize));
- }
- break;
- case 1:
- stream.readHex(start, dataSize);
- stream.readHexNumber(end, dataSize);
- addHex(end, start, dataSize);
- stream.readNumber();
- for (i = 1; i < subitemsCount; i++) {
- incHex(end, dataSize);
- stream.readHexNumber(start, dataSize);
- addHex(start, end, dataSize);
- stream.readHexNumber(end, dataSize);
- addHex(end, start, dataSize);
- stream.readNumber();
- }
- break;
- case 2:
- stream.readHex(char, dataSize);
- code = stream.readNumber();
- cMap.mapOne(hexToInt(char, dataSize), code);
- for (i = 1; i < subitemsCount; i++) {
- incHex(char, dataSize);
- if (!sequence) {
- stream.readHexNumber(tmp, dataSize);
- addHex(char, tmp, dataSize);
- }
- code = stream.readSigned() + (code + 1);
- cMap.mapOne(hexToInt(char, dataSize), code);
- }
- break;
- case 3:
- stream.readHex(start, dataSize);
- stream.readHexNumber(end, dataSize);
- addHex(end, start, dataSize);
- code = stream.readNumber();
- cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), code);
- for (i = 1; i < subitemsCount; i++) {
- incHex(end, dataSize);
- if (!sequence) {
- stream.readHexNumber(start, dataSize);
- addHex(start, end, dataSize);
- } else {
- start.set(end);
- }
- stream.readHexNumber(end, dataSize);
- addHex(end, start, dataSize);
- code = stream.readNumber();
- cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), code);
- }
- break;
- case 4:
- stream.readHex(char, ucs2DataSize);
- stream.readHex(charCode, dataSize);
- cMap.mapOne(hexToInt(char, ucs2DataSize), hexToStr(charCode, dataSize));
- for (i = 1; i < subitemsCount; i++) {
- incHex(char, ucs2DataSize);
- if (!sequence) {
- stream.readHexNumber(tmp, ucs2DataSize);
- addHex(char, tmp, ucs2DataSize);
- }
- incHex(charCode, dataSize);
- stream.readHexSigned(tmp, dataSize);
- addHex(charCode, tmp, dataSize);
- cMap.mapOne(hexToInt(char, ucs2DataSize), hexToStr(charCode, dataSize));
- }
- break;
- case 5:
- stream.readHex(start, ucs2DataSize);
- stream.readHexNumber(end, ucs2DataSize);
- addHex(end, start, ucs2DataSize);
- stream.readHex(charCode, dataSize);
- cMap.mapBfRange(hexToInt(start, ucs2DataSize), hexToInt(end, ucs2DataSize), hexToStr(charCode, dataSize));
- for (i = 1; i < subitemsCount; i++) {
- incHex(end, ucs2DataSize);
- if (!sequence) {
- stream.readHexNumber(start, ucs2DataSize);
- addHex(start, end, ucs2DataSize);
- } else {
- start.set(end);
- }
- stream.readHexNumber(end, ucs2DataSize);
- addHex(end, start, ucs2DataSize);
- stream.readHex(charCode, dataSize);
- cMap.mapBfRange(hexToInt(start, ucs2DataSize), hexToInt(end, ucs2DataSize), hexToStr(charCode, dataSize));
- }
- break;
- default:
- reject(new Error('processBinaryCMap: Unknown type: ' + type));
- return;
- }
- }
- if (useCMap) {
- resolve(extend(useCMap));
- return;
- }
- resolve(cMap);
- });
- }
- function BinaryCMapReader() {}
- BinaryCMapReader.prototype = { process: processBinaryCMap };
- return BinaryCMapReader;
-}();
-var CMapFactory = function CMapFactoryClosure() {
- function strToInt(str) {
- var a = 0;
- for (var i = 0; i < str.length; i++) {
- a = a << 8 | str.charCodeAt(i);
- }
- return a >>> 0;
- }
- function expectString(obj) {
- if (!(0, _util.isString)(obj)) {
- throw new _util.FormatError('Malformed CMap: expected string.');
- }
- }
- function expectInt(obj) {
- if (!Number.isInteger(obj)) {
- throw new _util.FormatError('Malformed CMap: expected int.');
- }
- }
- function parseBfChar(cMap, lexer) {
- while (true) {
- var obj = lexer.getObj();
- if ((0, _primitives.isEOF)(obj)) {
- break;
- }
- if ((0, _primitives.isCmd)(obj, 'endbfchar')) {
- return;
- }
- expectString(obj);
- var src = strToInt(obj);
- obj = lexer.getObj();
- expectString(obj);
- var dst = obj;
- cMap.mapOne(src, dst);
- }
- }
- function parseBfRange(cMap, lexer) {
- while (true) {
- var obj = lexer.getObj();
- if ((0, _primitives.isEOF)(obj)) {
- break;
- }
- if ((0, _primitives.isCmd)(obj, 'endbfrange')) {
- return;
- }
- expectString(obj);
- var low = strToInt(obj);
- obj = lexer.getObj();
- expectString(obj);
- var high = strToInt(obj);
- obj = lexer.getObj();
- if (Number.isInteger(obj) || (0, _util.isString)(obj)) {
- var dstLow = Number.isInteger(obj) ? String.fromCharCode(obj) : obj;
- cMap.mapBfRange(low, high, dstLow);
- } else if ((0, _primitives.isCmd)(obj, '[')) {
- obj = lexer.getObj();
- var array = [];
- while (!(0, _primitives.isCmd)(obj, ']') && !(0, _primitives.isEOF)(obj)) {
- array.push(obj);
- obj = lexer.getObj();
- }
- cMap.mapBfRangeToArray(low, high, array);
- } else {
- break;
- }
- }
- throw new _util.FormatError('Invalid bf range.');
- }
- function parseCidChar(cMap, lexer) {
- while (true) {
- var obj = lexer.getObj();
- if ((0, _primitives.isEOF)(obj)) {
- break;
- }
- if ((0, _primitives.isCmd)(obj, 'endcidchar')) {
- return;
- }
- expectString(obj);
- var src = strToInt(obj);
- obj = lexer.getObj();
- expectInt(obj);
- var dst = obj;
- cMap.mapOne(src, dst);
- }
- }
- function parseCidRange(cMap, lexer) {
- while (true) {
- var obj = lexer.getObj();
- if ((0, _primitives.isEOF)(obj)) {
- break;
- }
- if ((0, _primitives.isCmd)(obj, 'endcidrange')) {
- return;
- }
- expectString(obj);
- var low = strToInt(obj);
- obj = lexer.getObj();
- expectString(obj);
- var high = strToInt(obj);
- obj = lexer.getObj();
- expectInt(obj);
- var dstLow = obj;
- cMap.mapCidRange(low, high, dstLow);
- }
- }
- function parseCodespaceRange(cMap, lexer) {
- while (true) {
- var obj = lexer.getObj();
- if ((0, _primitives.isEOF)(obj)) {
- break;
- }
- if ((0, _primitives.isCmd)(obj, 'endcodespacerange')) {
- return;
- }
- if (!(0, _util.isString)(obj)) {
- break;
- }
- var low = strToInt(obj);
- obj = lexer.getObj();
- if (!(0, _util.isString)(obj)) {
- break;
- }
- var high = strToInt(obj);
- cMap.addCodespaceRange(obj.length, low, high);
- }
- throw new _util.FormatError('Invalid codespace range.');
- }
- function parseWMode(cMap, lexer) {
- var obj = lexer.getObj();
- if (Number.isInteger(obj)) {
- cMap.vertical = !!obj;
- }
- }
- function parseCMapName(cMap, lexer) {
- var obj = lexer.getObj();
- if ((0, _primitives.isName)(obj) && (0, _util.isString)(obj.name)) {
- cMap.name = obj.name;
- }
- }
- function parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap) {
- var previous;
- var embeddedUseCMap;
- objLoop: while (true) {
- try {
- var obj = lexer.getObj();
- if ((0, _primitives.isEOF)(obj)) {
- break;
- } else if ((0, _primitives.isName)(obj)) {
- if (obj.name === 'WMode') {
- parseWMode(cMap, lexer);
- } else if (obj.name === 'CMapName') {
- parseCMapName(cMap, lexer);
- }
- previous = obj;
- } else if ((0, _primitives.isCmd)(obj)) {
- switch (obj.cmd) {
- case 'endcmap':
- break objLoop;
- case 'usecmap':
- if ((0, _primitives.isName)(previous)) {
- embeddedUseCMap = previous.name;
- }
- break;
- case 'begincodespacerange':
- parseCodespaceRange(cMap, lexer);
- break;
- case 'beginbfchar':
- parseBfChar(cMap, lexer);
- break;
- case 'begincidchar':
- parseCidChar(cMap, lexer);
- break;
- case 'beginbfrange':
- parseBfRange(cMap, lexer);
- break;
- case 'begincidrange':
- parseCidRange(cMap, lexer);
- break;
- }
- }
- } catch (ex) {
- if (ex instanceof _util.MissingDataException) {
- throw ex;
- }
- (0, _util.warn)('Invalid cMap data: ' + ex);
- continue;
- }
- }
- if (!useCMap && embeddedUseCMap) {
- useCMap = embeddedUseCMap;
- }
- if (useCMap) {
- return extendCMap(cMap, fetchBuiltInCMap, useCMap);
- }
- return Promise.resolve(cMap);
- }
- function extendCMap(cMap, fetchBuiltInCMap, useCMap) {
- return createBuiltInCMap(useCMap, fetchBuiltInCMap).then(function (newCMap) {
- cMap.useCMap = newCMap;
- if (cMap.numCodespaceRanges === 0) {
- var useCodespaceRanges = cMap.useCMap.codespaceRanges;
- for (var i = 0; i < useCodespaceRanges.length; i++) {
- cMap.codespaceRanges[i] = useCodespaceRanges[i].slice();
- }
- cMap.numCodespaceRanges = cMap.useCMap.numCodespaceRanges;
- }
- cMap.useCMap.forEach(function (key, value) {
- if (!cMap.contains(key)) {
- cMap.mapOne(key, cMap.useCMap.lookup(key));
- }
- });
- return cMap;
- });
- }
- function createBuiltInCMap(name, fetchBuiltInCMap) {
- if (name === 'Identity-H') {
- return Promise.resolve(new IdentityCMap(false, 2));
- } else if (name === 'Identity-V') {
- return Promise.resolve(new IdentityCMap(true, 2));
- }
- if (!BUILT_IN_CMAPS.includes(name)) {
- return Promise.reject(new Error('Unknown CMap name: ' + name));
- }
- if (!fetchBuiltInCMap) {
- return Promise.reject(new Error('Built-in CMap parameters are not provided.'));
- }
- return fetchBuiltInCMap(name).then(function (data) {
- var cMapData = data.cMapData,
- compressionType = data.compressionType;
- var cMap = new CMap(true);
- if (compressionType === _util.CMapCompressionType.BINARY) {
- return new BinaryCMapReader().process(cMapData, cMap, function (useCMap) {
- return extendCMap(cMap, fetchBuiltInCMap, useCMap);
- });
- }
- if (compressionType === _util.CMapCompressionType.NONE) {
- var lexer = new _parser.Lexer(new _stream.Stream(cMapData));
- return parseCMap(cMap, lexer, fetchBuiltInCMap, null);
- }
- return Promise.reject(new Error('TODO: Only BINARY/NONE CMap compression is currently supported.'));
- });
- }
- return {
- create: function create(params) {
- var encoding = params.encoding;
- var fetchBuiltInCMap = params.fetchBuiltInCMap;
- var useCMap = params.useCMap;
- if ((0, _primitives.isName)(encoding)) {
- return createBuiltInCMap(encoding.name, fetchBuiltInCMap);
- } else if ((0, _primitives.isStream)(encoding)) {
- var cMap = new CMap();
- var lexer = new _parser.Lexer(encoding);
- return parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap).then(function (parsedCMap) {
- if (parsedCMap.isIdentityCMap) {
- return createBuiltInCMap(parsedCMap.name, fetchBuiltInCMap);
- }
- return parsedCMap;
- });
- }
- return Promise.reject(new Error('Encoding required.'));
- }
- };
-}();
-exports.CMap = CMap;
-exports.IdentityCMap = IdentityCMap;
-exports.CMapFactory = CMapFactory;
-
-/***/ }),
-/* 156 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.getFontType = exports.IdentityToUnicodeMap = exports.ToUnicodeMap = exports.FontFlags = exports.Font = exports.ErrorFont = exports.SEAC_ANALYSIS_ENABLED = undefined;
-
-var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
-
-var _util = __w_pdfjs_require__(2);
-
-var _cff_parser = __w_pdfjs_require__(157);
-
-var _glyphlist = __w_pdfjs_require__(160);
-
-var _encodings = __w_pdfjs_require__(159);
-
-var _standard_fonts = __w_pdfjs_require__(161);
-
-var _unicode = __w_pdfjs_require__(162);
-
-var _font_renderer = __w_pdfjs_require__(163);
-
-var _cmap = __w_pdfjs_require__(155);
-
-var _stream = __w_pdfjs_require__(140);
-
-var _type1_parser = __w_pdfjs_require__(164);
-
-var PRIVATE_USE_AREAS = [[0xE000, 0xF8FF], [0x100000, 0x10FFFD]];
-var PDF_GLYPH_SPACE_UNITS = 1000;
-var SEAC_ANALYSIS_ENABLED = true;
-var FontFlags = {
- FixedPitch: 1,
- Serif: 2,
- Symbolic: 4,
- Script: 8,
- Nonsymbolic: 32,
- Italic: 64,
- AllCap: 65536,
- SmallCap: 131072,
- ForceBold: 262144
-};
-var MacStandardGlyphOrdering = ['.notdef', '.null', 'nonmarkingreturn', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis', 'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', 'atilde', 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis', 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve', 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave', 'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling', 'section', 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright', 'trademark', 'acute', 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity', 'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff', 'summation', 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine', 'Omega', 'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot', 'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft', 'guillemotright', 'ellipsis', 'nonbreakingspace', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash', 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft', 'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction', 'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', 'periodcentered', 'quotesinglbase', 'quotedblbase', 'perthousand', 'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', 'Ograve', 'Uacute', 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'Lslash', 'lslash', 'Scaron', 'scaron', 'Zcaron', 'zcaron', 'brokenbar', 'Eth', 'eth', 'Yacute', 'yacute', 'Thorn', 'thorn', 'minus', 'multiply', 'onesuperior', 'twosuperior', 'threesuperior', 'onehalf', 'onequarter', 'threequarters', 'franc', 'Gbreve', 'gbreve', 'Idotaccent', 'Scedilla', 'scedilla', 'Cacute', 'cacute', 'Ccaron', 'ccaron', 'dcroat'];
-function adjustWidths(properties) {
- if (!properties.fontMatrix) {
- return;
- }
- if (properties.fontMatrix[0] === _util.FONT_IDENTITY_MATRIX[0]) {
- return;
- }
- var scale = 0.001 / properties.fontMatrix[0];
- var glyphsWidths = properties.widths;
- for (var glyph in glyphsWidths) {
- glyphsWidths[glyph] *= scale;
- }
- properties.defaultWidth *= scale;
-}
-function adjustToUnicode(properties, builtInEncoding) {
- if (properties.hasIncludedToUnicodeMap) {
- return;
- }
- if (properties.hasEncoding) {
- return;
- }
- if (builtInEncoding === properties.defaultEncoding) {
- return;
- }
- if (properties.toUnicode instanceof IdentityToUnicodeMap) {
- return;
- }
- var toUnicode = [],
- glyphsUnicodeMap = (0, _glyphlist.getGlyphsUnicode)();
- for (var charCode in builtInEncoding) {
- var glyphName = builtInEncoding[charCode];
- var unicode = (0, _unicode.getUnicodeForGlyph)(glyphName, glyphsUnicodeMap);
- if (unicode !== -1) {
- toUnicode[charCode] = String.fromCharCode(unicode);
- }
- }
- properties.toUnicode.amend(toUnicode);
-}
-function getFontType(type, subtype) {
- switch (type) {
- case 'Type1':
- return subtype === 'Type1C' ? _util.FontType.TYPE1C : _util.FontType.TYPE1;
- case 'CIDFontType0':
- return subtype === 'CIDFontType0C' ? _util.FontType.CIDFONTTYPE0C : _util.FontType.CIDFONTTYPE0;
- case 'OpenType':
- return _util.FontType.OPENTYPE;
- case 'TrueType':
- return _util.FontType.TRUETYPE;
- case 'CIDFontType2':
- return _util.FontType.CIDFONTTYPE2;
- case 'MMType1':
- return _util.FontType.MMTYPE1;
- case 'Type0':
- return _util.FontType.TYPE0;
- default:
- return _util.FontType.UNKNOWN;
- }
-}
-function recoverGlyphName(name, glyphsUnicodeMap) {
- if (glyphsUnicodeMap[name] !== undefined) {
- return name;
- }
- var unicode = (0, _unicode.getUnicodeForGlyph)(name, glyphsUnicodeMap);
- if (unicode !== -1) {
- for (var key in glyphsUnicodeMap) {
- if (glyphsUnicodeMap[key] === unicode) {
- return key;
- }
- }
- }
- (0, _util.info)('Unable to recover a standard glyph name for: ' + name);
- return name;
-}
-var Glyph = function GlyphClosure() {
- function Glyph(fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont) {
- this.fontChar = fontChar;
- this.unicode = unicode;
- this.accent = accent;
- this.width = width;
- this.vmetric = vmetric;
- this.operatorListId = operatorListId;
- this.isSpace = isSpace;
- this.isInFont = isInFont;
- }
- Glyph.prototype.matchesForCache = function (fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont) {
- return this.fontChar === fontChar && this.unicode === unicode && this.accent === accent && this.width === width && this.vmetric === vmetric && this.operatorListId === operatorListId && this.isSpace === isSpace && this.isInFont === isInFont;
- };
- return Glyph;
-}();
-var ToUnicodeMap = function ToUnicodeMapClosure() {
- function ToUnicodeMap() {
- var cmap = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
-
- this._map = cmap;
- }
- ToUnicodeMap.prototype = {
- get length() {
- return this._map.length;
- },
- forEach: function forEach(callback) {
- for (var charCode in this._map) {
- callback(charCode, this._map[charCode].charCodeAt(0));
- }
- },
- has: function has(i) {
- return this._map[i] !== undefined;
- },
- get: function get(i) {
- return this._map[i];
- },
- charCodeOf: function charCodeOf(value) {
- var map = this._map;
- if (map.length <= 0x10000) {
- return map.indexOf(value);
- }
- for (var charCode in map) {
- if (map[charCode] === value) {
- return charCode | 0;
- }
- }
- return -1;
- },
- amend: function amend(map) {
- for (var charCode in map) {
- this._map[charCode] = map[charCode];
- }
- }
- };
- return ToUnicodeMap;
-}();
-var IdentityToUnicodeMap = function IdentityToUnicodeMapClosure() {
- function IdentityToUnicodeMap(firstChar, lastChar) {
- this.firstChar = firstChar;
- this.lastChar = lastChar;
- }
- IdentityToUnicodeMap.prototype = {
- get length() {
- return this.lastChar + 1 - this.firstChar;
- },
- forEach: function forEach(callback) {
- for (var i = this.firstChar, ii = this.lastChar; i <= ii; i++) {
- callback(i, i);
- }
- },
- has: function has(i) {
- return this.firstChar <= i && i <= this.lastChar;
- },
- get: function get(i) {
- if (this.firstChar <= i && i <= this.lastChar) {
- return String.fromCharCode(i);
- }
- return undefined;
- },
- charCodeOf: function charCodeOf(v) {
- return Number.isInteger(v) && v >= this.firstChar && v <= this.lastChar ? v : -1;
- },
- amend: function amend(map) {
- (0, _util.unreachable)('Should not call amend()');
- }
- };
- return IdentityToUnicodeMap;
-}();
-var OpenTypeFileBuilder = function OpenTypeFileBuilderClosure() {
- function writeInt16(dest, offset, num) {
- dest[offset] = num >> 8 & 0xFF;
- dest[offset + 1] = num & 0xFF;
- }
- function writeInt32(dest, offset, num) {
- dest[offset] = num >> 24 & 0xFF;
- dest[offset + 1] = num >> 16 & 0xFF;
- dest[offset + 2] = num >> 8 & 0xFF;
- dest[offset + 3] = num & 0xFF;
- }
- function writeData(dest, offset, data) {
- var i, ii;
- if (data instanceof Uint8Array) {
- dest.set(data, offset);
- } else if (typeof data === 'string') {
- for (i = 0, ii = data.length; i < ii; i++) {
- dest[offset++] = data.charCodeAt(i) & 0xFF;
- }
- } else {
- for (i = 0, ii = data.length; i < ii; i++) {
- dest[offset++] = data[i] & 0xFF;
- }
- }
- }
- function OpenTypeFileBuilder(sfnt) {
- this.sfnt = sfnt;
- this.tables = Object.create(null);
- }
- OpenTypeFileBuilder.getSearchParams = function OpenTypeFileBuilder_getSearchParams(entriesCount, entrySize) {
- var maxPower2 = 1,
- log2 = 0;
- while ((maxPower2 ^ entriesCount) > maxPower2) {
- maxPower2 <<= 1;
- log2++;
- }
- var searchRange = maxPower2 * entrySize;
- return {
- range: searchRange,
- entry: log2,
- rangeShift: entrySize * entriesCount - searchRange
- };
- };
- var OTF_HEADER_SIZE = 12;
- var OTF_TABLE_ENTRY_SIZE = 16;
- OpenTypeFileBuilder.prototype = {
- toArray: function OpenTypeFileBuilder_toArray() {
- var sfnt = this.sfnt;
- var tables = this.tables;
- var tablesNames = Object.keys(tables);
- tablesNames.sort();
- var numTables = tablesNames.length;
- var i, j, jj, table, tableName;
- var offset = OTF_HEADER_SIZE + numTables * OTF_TABLE_ENTRY_SIZE;
- var tableOffsets = [offset];
- for (i = 0; i < numTables; i++) {
- table = tables[tablesNames[i]];
- var paddedLength = (table.length + 3 & ~3) >>> 0;
- offset += paddedLength;
- tableOffsets.push(offset);
- }
- var file = new Uint8Array(offset);
- for (i = 0; i < numTables; i++) {
- table = tables[tablesNames[i]];
- writeData(file, tableOffsets[i], table);
- }
- if (sfnt === 'true') {
- sfnt = (0, _util.string32)(0x00010000);
- }
- file[0] = sfnt.charCodeAt(0) & 0xFF;
- file[1] = sfnt.charCodeAt(1) & 0xFF;
- file[2] = sfnt.charCodeAt(2) & 0xFF;
- file[3] = sfnt.charCodeAt(3) & 0xFF;
- writeInt16(file, 4, numTables);
- var searchParams = OpenTypeFileBuilder.getSearchParams(numTables, 16);
- writeInt16(file, 6, searchParams.range);
- writeInt16(file, 8, searchParams.entry);
- writeInt16(file, 10, searchParams.rangeShift);
- offset = OTF_HEADER_SIZE;
- for (i = 0; i < numTables; i++) {
- tableName = tablesNames[i];
- file[offset] = tableName.charCodeAt(0) & 0xFF;
- file[offset + 1] = tableName.charCodeAt(1) & 0xFF;
- file[offset + 2] = tableName.charCodeAt(2) & 0xFF;
- file[offset + 3] = tableName.charCodeAt(3) & 0xFF;
- var checksum = 0;
- for (j = tableOffsets[i], jj = tableOffsets[i + 1]; j < jj; j += 4) {
- var quad = (0, _util.readUint32)(file, j);
- checksum = checksum + quad >>> 0;
- }
- writeInt32(file, offset + 4, checksum);
- writeInt32(file, offset + 8, tableOffsets[i]);
- writeInt32(file, offset + 12, tables[tableName].length);
- offset += OTF_TABLE_ENTRY_SIZE;
- }
- return file;
- },
- addTable: function OpenTypeFileBuilder_addTable(tag, data) {
- if (tag in this.tables) {
- throw new Error('Table ' + tag + ' already exists');
- }
- this.tables[tag] = data;
- }
- };
- return OpenTypeFileBuilder;
-}();
-var Font = function FontClosure() {
- function Font(name, file, properties) {
- var charCode;
- this.name = name;
- this.loadedName = properties.loadedName;
- this.isType3Font = properties.isType3Font;
- this.sizes = [];
- this.missingFile = false;
- this.glyphCache = Object.create(null);
- this.isSerifFont = !!(properties.flags & FontFlags.Serif);
- this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic);
- this.isMonospace = !!(properties.flags & FontFlags.FixedPitch);
- var type = properties.type;
- var subtype = properties.subtype;
- this.type = type;
- this.subtype = subtype;
- this.fallbackName = this.isMonospace ? 'monospace' : this.isSerifFont ? 'serif' : 'sans-serif';
- this.differences = properties.differences;
- this.widths = properties.widths;
- this.defaultWidth = properties.defaultWidth;
- this.composite = properties.composite;
- this.wideChars = properties.wideChars;
- this.cMap = properties.cMap;
- this.ascent = properties.ascent / PDF_GLYPH_SPACE_UNITS;
- this.descent = properties.descent / PDF_GLYPH_SPACE_UNITS;
- this.fontMatrix = properties.fontMatrix;
- this.bbox = properties.bbox;
- this.defaultEncoding = properties.defaultEncoding;
- this.toUnicode = properties.toUnicode;
- this.fallbackToUnicode = properties.fallbackToUnicode || new ToUnicodeMap();
- this.toFontChar = [];
- if (properties.type === 'Type3') {
- for (charCode = 0; charCode < 256; charCode++) {
- this.toFontChar[charCode] = this.differences[charCode] || properties.defaultEncoding[charCode];
- }
- this.fontType = _util.FontType.TYPE3;
- return;
- }
- this.cidEncoding = properties.cidEncoding;
- this.vertical = properties.vertical;
- if (this.vertical) {
- this.vmetrics = properties.vmetrics;
- this.defaultVMetrics = properties.defaultVMetrics;
- }
- if (!file || file.isEmpty) {
- if (file) {
- (0, _util.warn)('Font file is empty in "' + name + '" (' + this.loadedName + ')');
- }
- this.fallbackToSystemFont();
- return;
- }
-
- var _getFontFileType = getFontFileType(file, properties);
-
- var _getFontFileType2 = _slicedToArray(_getFontFileType, 2);
-
- type = _getFontFileType2[0];
- subtype = _getFontFileType2[1];
-
- if (type !== this.type || subtype !== this.subtype) {
- (0, _util.info)('Inconsistent font file Type/SubType, expected: ' + (this.type + '/' + this.subtype + ' but found: ' + type + '/' + subtype + '.'));
- }
- try {
- var data;
- switch (type) {
- case 'MMType1':
- (0, _util.info)('MMType1 font (' + name + '), falling back to Type1.');
- case 'Type1':
- case 'CIDFontType0':
- this.mimetype = 'font/opentype';
- var cff = subtype === 'Type1C' || subtype === 'CIDFontType0C' ? new CFFFont(file, properties) : new Type1Font(name, file, properties);
- adjustWidths(properties);
- data = this.convert(name, cff, properties);
- break;
- case 'OpenType':
- case 'TrueType':
- case 'CIDFontType2':
- this.mimetype = 'font/opentype';
- data = this.checkAndRepair(name, file, properties);
- if (this.isOpenType) {
- adjustWidths(properties);
- type = 'OpenType';
- }
- break;
- default:
- throw new _util.FormatError('Font ' + type + ' is not supported');
- }
- } catch (e) {
- (0, _util.warn)(e);
- this.fallbackToSystemFont();
- return;
- }
- this.data = data;
- this.fontType = getFontType(type, subtype);
- this.fontMatrix = properties.fontMatrix;
- this.widths = properties.widths;
- this.defaultWidth = properties.defaultWidth;
- this.toUnicode = properties.toUnicode;
- this.encoding = properties.baseEncoding;
- this.seacMap = properties.seacMap;
- }
- Font.getFontID = function () {
- var ID = 1;
- return function Font_getFontID() {
- return String(ID++);
- };
- }();
- function int16(b0, b1) {
- return (b0 << 8) + b1;
- }
- function writeSignedInt16(bytes, index, value) {
- bytes[index + 1] = value;
- bytes[index] = value >>> 8;
- }
- function signedInt16(b0, b1) {
- var value = (b0 << 8) + b1;
- return value & 1 << 15 ? value - 0x10000 : value;
- }
- function int32(b0, b1, b2, b3) {
- return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
- }
- function string16(value) {
- return String.fromCharCode(value >> 8 & 0xff, value & 0xff);
- }
- function safeString16(value) {
- value = value > 0x7FFF ? 0x7FFF : value < -0x8000 ? -0x8000 : value;
- return String.fromCharCode(value >> 8 & 0xff, value & 0xff);
- }
- function isTrueTypeFile(file) {
- var header = file.peekBytes(4);
- return (0, _util.readUint32)(header, 0) === 0x00010000 || (0, _util.bytesToString)(header) === 'true';
- }
- function isTrueTypeCollectionFile(file) {
- var header = file.peekBytes(4);
- return (0, _util.bytesToString)(header) === 'ttcf';
- }
- function isOpenTypeFile(file) {
- var header = file.peekBytes(4);
- return (0, _util.bytesToString)(header) === 'OTTO';
- }
- function isType1File(file) {
- var header = file.peekBytes(2);
- if (header[0] === 0x25 && header[1] === 0x21) {
- return true;
- }
- if (header[0] === 0x80 && header[1] === 0x01) {
- return true;
- }
- return false;
- }
- function isCFFFile(file) {
- var header = file.peekBytes(4);
- if (header[0] >= 1 && header[3] >= 1 && header[3] <= 4) {
- return true;
- }
- return false;
- }
- function getFontFileType(file, _ref) {
- var type = _ref.type,
- subtype = _ref.subtype,
- composite = _ref.composite;
-
- var fileType = void 0,
- fileSubtype = void 0;
- if (isTrueTypeFile(file) || isTrueTypeCollectionFile(file)) {
- if (composite) {
- fileType = 'CIDFontType2';
- } else {
- fileType = 'TrueType';
- }
- } else if (isOpenTypeFile(file)) {
- if (composite) {
- fileType = 'CIDFontType2';
- } else {
- fileType = 'OpenType';
- }
- } else if (isType1File(file)) {
- if (composite) {
- fileType = 'CIDFontType0';
- } else {
- fileType = type === 'MMType1' ? 'MMType1' : 'Type1';
- }
- } else if (isCFFFile(file)) {
- if (composite) {
- fileType = 'CIDFontType0';
- fileSubtype = 'CIDFontType0C';
- } else {
- fileType = type === 'MMType1' ? 'MMType1' : 'Type1';
- fileSubtype = 'Type1C';
- }
- } else {
- (0, _util.warn)('getFontFileType: Unable to detect correct font file Type/Subtype.');
- fileType = type;
- fileSubtype = subtype;
- }
- return [fileType, fileSubtype];
- }
- function buildToFontChar(encoding, glyphsUnicodeMap, differences) {
- var toFontChar = [],
- unicode;
- for (var i = 0, ii = encoding.length; i < ii; i++) {
- unicode = (0, _unicode.getUnicodeForGlyph)(encoding[i], glyphsUnicodeMap);
- if (unicode !== -1) {
- toFontChar[i] = unicode;
- }
- }
- for (var charCode in differences) {
- unicode = (0, _unicode.getUnicodeForGlyph)(differences[charCode], glyphsUnicodeMap);
- if (unicode !== -1) {
- toFontChar[+charCode] = unicode;
- }
- }
- return toFontChar;
- }
- function adjustMapping(charCodeToGlyphId, hasGlyph, newGlyphZeroId) {
- var newMap = Object.create(null);
- var toFontChar = [];
- var privateUseAreaIndex = 0;
- var nextAvailableFontCharCode = PRIVATE_USE_AREAS[privateUseAreaIndex][0];
- var privateUseOffetEnd = PRIVATE_USE_AREAS[privateUseAreaIndex][1];
- for (var originalCharCode in charCodeToGlyphId) {
- originalCharCode |= 0;
- var glyphId = charCodeToGlyphId[originalCharCode];
- if (!hasGlyph(glyphId)) {
- continue;
- }
- if (nextAvailableFontCharCode > privateUseOffetEnd) {
- privateUseAreaIndex++;
- if (privateUseAreaIndex >= PRIVATE_USE_AREAS.length) {
- (0, _util.warn)('Ran out of space in font private use area.');
- break;
- }
- nextAvailableFontCharCode = PRIVATE_USE_AREAS[privateUseAreaIndex][0];
- privateUseOffetEnd = PRIVATE_USE_AREAS[privateUseAreaIndex][1];
- }
- var fontCharCode = nextAvailableFontCharCode++;
- if (glyphId === 0) {
- glyphId = newGlyphZeroId;
- }
- newMap[fontCharCode] = glyphId;
- toFontChar[originalCharCode] = fontCharCode;
- }
- return {
- toFontChar: toFontChar,
- charCodeToGlyphId: newMap,
- nextAvailableFontCharCode: nextAvailableFontCharCode
- };
- }
- function getRanges(glyphs, numGlyphs) {
- var codes = [];
- for (var charCode in glyphs) {
- if (glyphs[charCode] >= numGlyphs) {
- continue;
- }
- codes.push({
- fontCharCode: charCode | 0,
- glyphId: glyphs[charCode]
- });
- }
- if (codes.length === 0) {
- codes.push({
- fontCharCode: 0,
- glyphId: 0
- });
- }
- codes.sort(function fontGetRangesSort(a, b) {
- return a.fontCharCode - b.fontCharCode;
- });
- var ranges = [];
- var length = codes.length;
- for (var n = 0; n < length;) {
- var start = codes[n].fontCharCode;
- var codeIndices = [codes[n].glyphId];
- ++n;
- var end = start;
- while (n < length && end + 1 === codes[n].fontCharCode) {
- codeIndices.push(codes[n].glyphId);
- ++end;
- ++n;
- if (end === 0xFFFF) {
- break;
- }
- }
- ranges.push([start, end, codeIndices]);
- }
- return ranges;
- }
- function createCmapTable(glyphs, numGlyphs) {
- var ranges = getRanges(glyphs, numGlyphs);
- var numTables = ranges[ranges.length - 1][1] > 0xFFFF ? 2 : 1;
- var cmap = '\x00\x00' + string16(numTables) + '\x00\x03' + '\x00\x01' + (0, _util.string32)(4 + numTables * 8);
- var i, ii, j, jj;
- for (i = ranges.length - 1; i >= 0; --i) {
- if (ranges[i][0] <= 0xFFFF) {
- break;
- }
- }
- var bmpLength = i + 1;
- if (ranges[i][0] < 0xFFFF && ranges[i][1] === 0xFFFF) {
- ranges[i][1] = 0xFFFE;
- }
- var trailingRangesCount = ranges[i][1] < 0xFFFF ? 1 : 0;
- var segCount = bmpLength + trailingRangesCount;
- var searchParams = OpenTypeFileBuilder.getSearchParams(segCount, 2);
- var startCount = '';
- var endCount = '';
- var idDeltas = '';
- var idRangeOffsets = '';
- var glyphsIds = '';
- var bias = 0;
- var range, start, end, codes;
- for (i = 0, ii = bmpLength; i < ii; i++) {
- range = ranges[i];
- start = range[0];
- end = range[1];
- startCount += string16(start);
- endCount += string16(end);
- codes = range[2];
- var contiguous = true;
- for (j = 1, jj = codes.length; j < jj; ++j) {
- if (codes[j] !== codes[j - 1] + 1) {
- contiguous = false;
- break;
- }
- }
- if (!contiguous) {
- var offset = (segCount - i) * 2 + bias * 2;
- bias += end - start + 1;
- idDeltas += string16(0);
- idRangeOffsets += string16(offset);
- for (j = 0, jj = codes.length; j < jj; ++j) {
- glyphsIds += string16(codes[j]);
- }
- } else {
- var startCode = codes[0];
- idDeltas += string16(startCode - start & 0xFFFF);
- idRangeOffsets += string16(0);
- }
- }
- if (trailingRangesCount > 0) {
- endCount += '\xFF\xFF';
- startCount += '\xFF\xFF';
- idDeltas += '\x00\x01';
- idRangeOffsets += '\x00\x00';
- }
- var format314 = '\x00\x00' + string16(2 * segCount) + string16(searchParams.range) + string16(searchParams.entry) + string16(searchParams.rangeShift) + endCount + '\x00\x00' + startCount + idDeltas + idRangeOffsets + glyphsIds;
- var format31012 = '';
- var header31012 = '';
- if (numTables > 1) {
- cmap += '\x00\x03' + '\x00\x0A' + (0, _util.string32)(4 + numTables * 8 + 4 + format314.length);
- format31012 = '';
- for (i = 0, ii = ranges.length; i < ii; i++) {
- range = ranges[i];
- start = range[0];
- codes = range[2];
- var code = codes[0];
- for (j = 1, jj = codes.length; j < jj; ++j) {
- if (codes[j] !== codes[j - 1] + 1) {
- end = range[0] + j - 1;
- format31012 += (0, _util.string32)(start) + (0, _util.string32)(end) + (0, _util.string32)(code);
- start = end + 1;
- code = codes[j];
- }
- }
- format31012 += (0, _util.string32)(start) + (0, _util.string32)(range[1]) + (0, _util.string32)(code);
- }
- header31012 = '\x00\x0C' + '\x00\x00' + (0, _util.string32)(format31012.length + 16) + '\x00\x00\x00\x00' + (0, _util.string32)(format31012.length / 12);
- }
- return cmap + '\x00\x04' + string16(format314.length + 4) + format314 + header31012 + format31012;
- }
- function validateOS2Table(os2) {
- var stream = new _stream.Stream(os2.data);
- var version = stream.getUint16();
- stream.getBytes(60);
- var selection = stream.getUint16();
- if (version < 4 && selection & 0x0300) {
- return false;
- }
- var firstChar = stream.getUint16();
- var lastChar = stream.getUint16();
- if (firstChar > lastChar) {
- return false;
- }
- stream.getBytes(6);
- var usWinAscent = stream.getUint16();
- if (usWinAscent === 0) {
- return false;
- }
- os2.data[8] = os2.data[9] = 0;
- return true;
- }
- function createOS2Table(properties, charstrings, override) {
- override = override || {
- unitsPerEm: 0,
- yMax: 0,
- yMin: 0,
- ascent: 0,
- descent: 0
- };
- var ulUnicodeRange1 = 0;
- var ulUnicodeRange2 = 0;
- var ulUnicodeRange3 = 0;
- var ulUnicodeRange4 = 0;
- var firstCharIndex = null;
- var lastCharIndex = 0;
- if (charstrings) {
- for (var code in charstrings) {
- code |= 0;
- if (firstCharIndex > code || !firstCharIndex) {
- firstCharIndex = code;
- }
- if (lastCharIndex < code) {
- lastCharIndex = code;
- }
- var position = (0, _unicode.getUnicodeRangeFor)(code);
- if (position < 32) {
- ulUnicodeRange1 |= 1 << position;
- } else if (position < 64) {
- ulUnicodeRange2 |= 1 << position - 32;
- } else if (position < 96) {
- ulUnicodeRange3 |= 1 << position - 64;
- } else if (position < 123) {
- ulUnicodeRange4 |= 1 << position - 96;
- } else {
- throw new _util.FormatError('Unicode ranges Bits > 123 are reserved for internal usage');
- }
- }
- if (lastCharIndex > 0xFFFF) {
- lastCharIndex = 0xFFFF;
- }
- } else {
- firstCharIndex = 0;
- lastCharIndex = 255;
- }
- var bbox = properties.bbox || [0, 0, 0, 0];
- var unitsPerEm = override.unitsPerEm || 1 / (properties.fontMatrix || _util.FONT_IDENTITY_MATRIX)[0];
- var scale = properties.ascentScaled ? 1.0 : unitsPerEm / PDF_GLYPH_SPACE_UNITS;
- var typoAscent = override.ascent || Math.round(scale * (properties.ascent || bbox[3]));
- var typoDescent = override.descent || Math.round(scale * (properties.descent || bbox[1]));
- if (typoDescent > 0 && properties.descent > 0 && bbox[1] < 0) {
- typoDescent = -typoDescent;
- }
- var winAscent = override.yMax || typoAscent;
- var winDescent = -override.yMin || -typoDescent;
- return '\x00\x03' + '\x02\x24' + '\x01\xF4' + '\x00\x05' + '\x00\x00' + '\x02\x8A' + '\x02\xBB' + '\x00\x00' + '\x00\x8C' + '\x02\x8A' + '\x02\xBB' + '\x00\x00' + '\x01\xDF' + '\x00\x31' + '\x01\x02' + '\x00\x00' + '\x00\x00\x06' + String.fromCharCode(properties.fixedPitch ? 0x09 : 0x00) + '\x00\x00\x00\x00\x00\x00' + (0, _util.string32)(ulUnicodeRange1) + (0, _util.string32)(ulUnicodeRange2) + (0, _util.string32)(ulUnicodeRange3) + (0, _util.string32)(ulUnicodeRange4) + '\x2A\x32\x31\x2A' + string16(properties.italicAngle ? 1 : 0) + string16(firstCharIndex || properties.firstChar) + string16(lastCharIndex || properties.lastChar) + string16(typoAscent) + string16(typoDescent) + '\x00\x64' + string16(winAscent) + string16(winDescent) + '\x00\x00\x00\x00' + '\x00\x00\x00\x00' + string16(properties.xHeight) + string16(properties.capHeight) + string16(0) + string16(firstCharIndex || properties.firstChar) + '\x00\x03';
- }
- function createPostTable(properties) {
- var angle = Math.floor(properties.italicAngle * Math.pow(2, 16));
- return '\x00\x03\x00\x00' + (0, _util.string32)(angle) + '\x00\x00' + '\x00\x00' + (0, _util.string32)(properties.fixedPitch) + '\x00\x00\x00\x00' + '\x00\x00\x00\x00' + '\x00\x00\x00\x00' + '\x00\x00\x00\x00';
- }
- function createNameTable(name, proto) {
- if (!proto) {
- proto = [[], []];
- }
- var strings = [proto[0][0] || 'Original licence', proto[0][1] || name, proto[0][2] || 'Unknown', proto[0][3] || 'uniqueID', proto[0][4] || name, proto[0][5] || 'Version 0.11', proto[0][6] || '', proto[0][7] || 'Unknown', proto[0][8] || 'Unknown', proto[0][9] || 'Unknown'];
- var stringsUnicode = [];
- var i, ii, j, jj, str;
- for (i = 0, ii = strings.length; i < ii; i++) {
- str = proto[1][i] || strings[i];
- var strBufUnicode = [];
- for (j = 0, jj = str.length; j < jj; j++) {
- strBufUnicode.push(string16(str.charCodeAt(j)));
- }
- stringsUnicode.push(strBufUnicode.join(''));
- }
- var names = [strings, stringsUnicode];
- var platforms = ['\x00\x01', '\x00\x03'];
- var encodings = ['\x00\x00', '\x00\x01'];
- var languages = ['\x00\x00', '\x04\x09'];
- var namesRecordCount = strings.length * platforms.length;
- var nameTable = '\x00\x00' + string16(namesRecordCount) + string16(namesRecordCount * 12 + 6);
- var strOffset = 0;
- for (i = 0, ii = platforms.length; i < ii; i++) {
- var strs = names[i];
- for (j = 0, jj = strs.length; j < jj; j++) {
- str = strs[j];
- var nameRecord = platforms[i] + encodings[i] + languages[i] + string16(j) + string16(str.length) + string16(strOffset);
- nameTable += nameRecord;
- strOffset += str.length;
- }
- }
- nameTable += strings.join('') + stringsUnicode.join('');
- return nameTable;
- }
- Font.prototype = {
- name: null,
- font: null,
- mimetype: null,
- encoding: null,
- get renderer() {
- var renderer = _font_renderer.FontRendererFactory.create(this, SEAC_ANALYSIS_ENABLED);
- return (0, _util.shadow)(this, 'renderer', renderer);
- },
- exportData: function Font_exportData() {
- var data = {};
- for (var i in this) {
- if (this.hasOwnProperty(i)) {
- data[i] = this[i];
- }
- }
- return data;
- },
- fallbackToSystemFont: function Font_fallbackToSystemFont() {
- var _this = this;
-
- this.missingFile = true;
- var charCode, unicode;
- var name = this.name;
- var type = this.type;
- var subtype = this.subtype;
- var fontName = name.replace(/[,_]/g, '-');
- var stdFontMap = (0, _standard_fonts.getStdFontMap)(),
- nonStdFontMap = (0, _standard_fonts.getNonStdFontMap)();
- var isStandardFont = !!stdFontMap[fontName] || !!(nonStdFontMap[fontName] && stdFontMap[nonStdFontMap[fontName]]);
- fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName;
- this.bold = fontName.search(/bold/gi) !== -1;
- this.italic = fontName.search(/oblique/gi) !== -1 || fontName.search(/italic/gi) !== -1;
- this.black = name.search(/Black/g) !== -1;
- this.remeasure = Object.keys(this.widths).length > 0;
- if (isStandardFont && type === 'CIDFontType2' && this.cidEncoding.indexOf('Identity-') === 0) {
- var GlyphMapForStandardFonts = (0, _standard_fonts.getGlyphMapForStandardFonts)();
- var map = [];
- for (charCode in GlyphMapForStandardFonts) {
- map[+charCode] = GlyphMapForStandardFonts[charCode];
- }
- if (/Arial-?Black/i.test(name)) {
- var SupplementalGlyphMapForArialBlack = (0, _standard_fonts.getSupplementalGlyphMapForArialBlack)();
- for (charCode in SupplementalGlyphMapForArialBlack) {
- map[+charCode] = SupplementalGlyphMapForArialBlack[charCode];
- }
- } else if (/Calibri/i.test(name)) {
- var SupplementalGlyphMapForCalibri = (0, _standard_fonts.getSupplementalGlyphMapForCalibri)();
- for (charCode in SupplementalGlyphMapForCalibri) {
- map[+charCode] = SupplementalGlyphMapForCalibri[charCode];
- }
- }
- var isIdentityUnicode = this.toUnicode instanceof IdentityToUnicodeMap;
- if (!isIdentityUnicode) {
- this.toUnicode.forEach(function (charCode, unicodeCharCode) {
- map[+charCode] = unicodeCharCode;
- });
- }
- this.toFontChar = map;
- this.toUnicode = new ToUnicodeMap(map);
- } else if (/Symbol/i.test(fontName)) {
- this.toFontChar = buildToFontChar(_encodings.SymbolSetEncoding, (0, _glyphlist.getGlyphsUnicode)(), this.differences);
- } else if (/Dingbats/i.test(fontName)) {
- if (/Wingdings/i.test(name)) {
- (0, _util.warn)('Non-embedded Wingdings font, falling back to ZapfDingbats.');
- }
- this.toFontChar = buildToFontChar(_encodings.ZapfDingbatsEncoding, (0, _glyphlist.getDingbatsGlyphsUnicode)(), this.differences);
- } else if (isStandardFont) {
- this.toFontChar = buildToFontChar(this.defaultEncoding, (0, _glyphlist.getGlyphsUnicode)(), this.differences);
- } else {
- var glyphsUnicodeMap = (0, _glyphlist.getGlyphsUnicode)();
- this.toUnicode.forEach(function (charCode, unicodeCharCode) {
- if (!_this.composite) {
- var glyphName = _this.differences[charCode] || _this.defaultEncoding[charCode];
- unicode = (0, _unicode.getUnicodeForGlyph)(glyphName, glyphsUnicodeMap);
- if (unicode !== -1) {
- unicodeCharCode = unicode;
- }
- }
- _this.toFontChar[charCode] = unicodeCharCode;
- });
- }
- this.loadedName = fontName.split('-')[0];
- this.fontType = getFontType(type, subtype);
- },
- checkAndRepair: function Font_checkAndRepair(name, font, properties) {
- var VALID_TABLES = ['OS/2', 'cmap', 'head', 'hhea', 'hmtx', 'maxp', 'name', 'post', 'loca', 'glyf', 'fpgm', 'prep', 'cvt ', 'CFF '];
- function readTables(file, numTables) {
- var tables = Object.create(null);
- tables['OS/2'] = null;
- tables['cmap'] = null;
- tables['head'] = null;
- tables['hhea'] = null;
- tables['hmtx'] = null;
- tables['maxp'] = null;
- tables['name'] = null;
- tables['post'] = null;
- for (var i = 0; i < numTables; i++) {
- var table = readTableEntry(font);
- if (!VALID_TABLES.includes(table.tag)) {
- continue;
- }
- if (table.length === 0) {
- continue;
- }
- tables[table.tag] = table;
- }
- return tables;
- }
- function readTableEntry(file) {
- var tag = (0, _util.bytesToString)(file.getBytes(4));
- var checksum = file.getInt32() >>> 0;
- var offset = file.getInt32() >>> 0;
- var length = file.getInt32() >>> 0;
- var previousPosition = file.pos;
- file.pos = file.start ? file.start : 0;
- file.skip(offset);
- var data = file.getBytes(length);
- file.pos = previousPosition;
- if (tag === 'head') {
- data[8] = data[9] = data[10] = data[11] = 0;
- data[17] |= 0x20;
- }
- return {
- tag: tag,
- checksum: checksum,
- length: length,
- offset: offset,
- data: data
- };
- }
- function readOpenTypeHeader(ttf) {
- return {
- version: (0, _util.bytesToString)(ttf.getBytes(4)),
- numTables: ttf.getUint16(),
- searchRange: ttf.getUint16(),
- entrySelector: ttf.getUint16(),
- rangeShift: ttf.getUint16()
- };
- }
- function readTrueTypeCollectionHeader(ttc) {
- var ttcTag = (0, _util.bytesToString)(ttc.getBytes(4));
- (0, _util.assert)(ttcTag === 'ttcf', 'Must be a TrueType Collection font.');
- var majorVersion = ttc.getUint16();
- var minorVersion = ttc.getUint16();
- var numFonts = ttc.getInt32() >>> 0;
- var offsetTable = [];
- for (var i = 0; i < numFonts; i++) {
- offsetTable.push(ttc.getInt32() >>> 0);
- }
- var header = {
- ttcTag: ttcTag,
- majorVersion: majorVersion,
- minorVersion: minorVersion,
- numFonts: numFonts,
- offsetTable: offsetTable
- };
- switch (majorVersion) {
- case 1:
- return header;
- case 2:
- header.dsigTag = ttc.getInt32() >>> 0;
- header.dsigLength = ttc.getInt32() >>> 0;
- header.dsigOffset = ttc.getInt32() >>> 0;
- return header;
- }
- throw new _util.FormatError('Invalid TrueType Collection majorVersion: ' + majorVersion + '.');
- }
- function readTrueTypeCollectionData(ttc, fontName) {
- var _readTrueTypeCollecti = readTrueTypeCollectionHeader(ttc),
- numFonts = _readTrueTypeCollecti.numFonts,
- offsetTable = _readTrueTypeCollecti.offsetTable;
-
- for (var i = 0; i < numFonts; i++) {
- ttc.pos = (ttc.start || 0) + offsetTable[i];
- var potentialHeader = readOpenTypeHeader(ttc);
- var potentialTables = readTables(ttc, potentialHeader.numTables);
- if (!potentialTables['name']) {
- throw new _util.FormatError('TrueType Collection font must contain a "name" table.');
- }
- var nameTable = readNameTable(potentialTables['name']);
- for (var j = 0, jj = nameTable.length; j < jj; j++) {
- for (var k = 0, kk = nameTable[j].length; k < kk; k++) {
- var nameEntry = nameTable[j][k];
- if (nameEntry && nameEntry.replace(/\s/g, '') === fontName) {
- return {
- header: potentialHeader,
- tables: potentialTables
- };
- }
- }
- }
- }
- throw new _util.FormatError('TrueType Collection does not contain "' + fontName + '" font.');
- }
- function readCmapTable(cmap, font, isSymbolicFont, hasEncoding) {
- if (!cmap) {
- (0, _util.warn)('No cmap table available.');
- return {
- platformId: -1,
- encodingId: -1,
- mappings: [],
- hasShortCmap: false
- };
- }
- var segment;
- var start = (font.start ? font.start : 0) + cmap.offset;
- font.pos = start;
- font.getUint16();
- var numTables = font.getUint16();
- var potentialTable;
- var canBreak = false;
- for (var i = 0; i < numTables; i++) {
- var platformId = font.getUint16();
- var encodingId = font.getUint16();
- var offset = font.getInt32() >>> 0;
- var useTable = false;
- if (potentialTable && potentialTable.platformId === platformId && potentialTable.encodingId === encodingId) {
- continue;
- }
- if (platformId === 0 && encodingId === 0) {
- useTable = true;
- } else if (platformId === 1 && encodingId === 0) {
- useTable = true;
- } else if (platformId === 3 && encodingId === 1 && (hasEncoding || !potentialTable)) {
- useTable = true;
- if (!isSymbolicFont) {
- canBreak = true;
- }
- } else if (isSymbolicFont && platformId === 3 && encodingId === 0) {
- useTable = true;
- canBreak = true;
- }
- if (useTable) {
- potentialTable = {
- platformId: platformId,
- encodingId: encodingId,
- offset: offset
- };
- }
- if (canBreak) {
- break;
- }
- }
- if (potentialTable) {
- font.pos = start + potentialTable.offset;
- }
- if (!potentialTable || font.peekByte() === -1) {
- (0, _util.warn)('Could not find a preferred cmap table.');
- return {
- platformId: -1,
- encodingId: -1,
- mappings: [],
- hasShortCmap: false
- };
- }
- var format = font.getUint16();
- font.getUint16();
- font.getUint16();
- var hasShortCmap = false;
- var mappings = [];
- var j, glyphId;
- if (format === 0) {
- for (j = 0; j < 256; j++) {
- var index = font.getByte();
- if (!index) {
- continue;
- }
- mappings.push({
- charCode: j,
- glyphId: index
- });
- }
- hasShortCmap = true;
- } else if (format === 4) {
- var segCount = font.getUint16() >> 1;
- font.getBytes(6);
- var segIndex,
- segments = [];
- for (segIndex = 0; segIndex < segCount; segIndex++) {
- segments.push({ end: font.getUint16() });
- }
- font.getUint16();
- for (segIndex = 0; segIndex < segCount; segIndex++) {
- segments[segIndex].start = font.getUint16();
- }
- for (segIndex = 0; segIndex < segCount; segIndex++) {
- segments[segIndex].delta = font.getUint16();
- }
- var offsetsCount = 0;
- for (segIndex = 0; segIndex < segCount; segIndex++) {
- segment = segments[segIndex];
- var rangeOffset = font.getUint16();
- if (!rangeOffset) {
- segment.offsetIndex = -1;
- continue;
- }
- var offsetIndex = (rangeOffset >> 1) - (segCount - segIndex);
- segment.offsetIndex = offsetIndex;
- offsetsCount = Math.max(offsetsCount, offsetIndex + segment.end - segment.start + 1);
- }
- var offsets = [];
- for (j = 0; j < offsetsCount; j++) {
- offsets.push(font.getUint16());
- }
- for (segIndex = 0; segIndex < segCount; segIndex++) {
- segment = segments[segIndex];
- start = segment.start;
- var end = segment.end;
- var delta = segment.delta;
- offsetIndex = segment.offsetIndex;
- for (j = start; j <= end; j++) {
- if (j === 0xFFFF) {
- continue;
- }
- glyphId = offsetIndex < 0 ? j : offsets[offsetIndex + j - start];
- glyphId = glyphId + delta & 0xFFFF;
- mappings.push({
- charCode: j,
- glyphId: glyphId
- });
- }
- }
- } else if (format === 6) {
- var firstCode = font.getUint16();
- var entryCount = font.getUint16();
- for (j = 0; j < entryCount; j++) {
- glyphId = font.getUint16();
- var charCode = firstCode + j;
- mappings.push({
- charCode: charCode,
- glyphId: glyphId
- });
- }
- } else {
- (0, _util.warn)('cmap table has unsupported format: ' + format);
- return {
- platformId: -1,
- encodingId: -1,
- mappings: [],
- hasShortCmap: false
- };
- }
- mappings.sort(function (a, b) {
- return a.charCode - b.charCode;
- });
- for (i = 1; i < mappings.length; i++) {
- if (mappings[i - 1].charCode === mappings[i].charCode) {
- mappings.splice(i, 1);
- i--;
- }
- }
- return {
- platformId: potentialTable.platformId,
- encodingId: potentialTable.encodingId,
- mappings: mappings,
- hasShortCmap: hasShortCmap
- };
- }
- function sanitizeMetrics(font, header, metrics, numGlyphs) {
- if (!header) {
- if (metrics) {
- metrics.data = null;
- }
- return;
- }
- font.pos = (font.start ? font.start : 0) + header.offset;
- font.pos += header.length - 2;
- var numOfMetrics = font.getUint16();
- if (numOfMetrics > numGlyphs) {
- (0, _util.info)('The numOfMetrics (' + numOfMetrics + ') should not be ' + 'greater than the numGlyphs (' + numGlyphs + ')');
- numOfMetrics = numGlyphs;
- header.data[34] = (numOfMetrics & 0xff00) >> 8;
- header.data[35] = numOfMetrics & 0x00ff;
- }
- var numOfSidebearings = numGlyphs - numOfMetrics;
- var numMissing = numOfSidebearings - (metrics.length - numOfMetrics * 4 >> 1);
- if (numMissing > 0) {
- var entries = new Uint8Array(metrics.length + numMissing * 2);
- entries.set(metrics.data);
- metrics.data = entries;
- }
- }
- function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart, hintsValid) {
- var glyphProfile = {
- length: 0,
- sizeOfInstructions: 0
- };
- if (sourceEnd - sourceStart <= 12) {
- return glyphProfile;
- }
- var glyf = source.subarray(sourceStart, sourceEnd);
- var contoursCount = signedInt16(glyf[0], glyf[1]);
- if (contoursCount < 0) {
- contoursCount = -1;
- writeSignedInt16(glyf, 0, contoursCount);
- dest.set(glyf, destStart);
- glyphProfile.length = glyf.length;
- return glyphProfile;
- }
- var i,
- j = 10,
- flagsCount = 0;
- for (i = 0; i < contoursCount; i++) {
- var endPoint = glyf[j] << 8 | glyf[j + 1];
- flagsCount = endPoint + 1;
- j += 2;
- }
- var instructionsStart = j;
- var instructionsLength = glyf[j] << 8 | glyf[j + 1];
- glyphProfile.sizeOfInstructions = instructionsLength;
- j += 2 + instructionsLength;
- var instructionsEnd = j;
- var coordinatesLength = 0;
- for (i = 0; i < flagsCount; i++) {
- var flag = glyf[j++];
- if (flag & 0xC0) {
- glyf[j - 1] = flag & 0x3F;
- }
- var xyLength = (flag & 2 ? 1 : flag & 16 ? 0 : 2) + (flag & 4 ? 1 : flag & 32 ? 0 : 2);
- coordinatesLength += xyLength;
- if (flag & 8) {
- var repeat = glyf[j++];
- i += repeat;
- coordinatesLength += repeat * xyLength;
- }
- }
- if (coordinatesLength === 0) {
- return glyphProfile;
- }
- var glyphDataLength = j + coordinatesLength;
- if (glyphDataLength > glyf.length) {
- return glyphProfile;
- }
- if (!hintsValid && instructionsLength > 0) {
- dest.set(glyf.subarray(0, instructionsStart), destStart);
- dest.set([0, 0], destStart + instructionsStart);
- dest.set(glyf.subarray(instructionsEnd, glyphDataLength), destStart + instructionsStart + 2);
- glyphDataLength -= instructionsLength;
- if (glyf.length - glyphDataLength > 3) {
- glyphDataLength = glyphDataLength + 3 & ~3;
- }
- glyphProfile.length = glyphDataLength;
- return glyphProfile;
- }
- if (glyf.length - glyphDataLength > 3) {
- glyphDataLength = glyphDataLength + 3 & ~3;
- dest.set(glyf.subarray(0, glyphDataLength), destStart);
- glyphProfile.length = glyphDataLength;
- return glyphProfile;
- }
- dest.set(glyf, destStart);
- glyphProfile.length = glyf.length;
- return glyphProfile;
- }
- function sanitizeHead(head, numGlyphs, locaLength) {
- var data = head.data;
- var version = int32(data[0], data[1], data[2], data[3]);
- if (version >> 16 !== 1) {
- (0, _util.info)('Attempting to fix invalid version in head table: ' + version);
- data[0] = 0;
- data[1] = 1;
- data[2] = 0;
- data[3] = 0;
- }
- var indexToLocFormat = int16(data[50], data[51]);
- if (indexToLocFormat < 0 || indexToLocFormat > 1) {
- (0, _util.info)('Attempting to fix invalid indexToLocFormat in head table: ' + indexToLocFormat);
- var numGlyphsPlusOne = numGlyphs + 1;
- if (locaLength === numGlyphsPlusOne << 1) {
- data[50] = 0;
- data[51] = 0;
- } else if (locaLength === numGlyphsPlusOne << 2) {
- data[50] = 0;
- data[51] = 1;
- } else {
- throw new _util.FormatError('Could not fix indexToLocFormat: ' + indexToLocFormat);
- }
- }
- }
- function sanitizeGlyphLocations(loca, glyf, numGlyphs, isGlyphLocationsLong, hintsValid, dupFirstEntry, maxSizeOfInstructions) {
- var itemSize, itemDecode, itemEncode;
- if (isGlyphLocationsLong) {
- itemSize = 4;
- itemDecode = function fontItemDecodeLong(data, offset) {
- return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3];
- };
- itemEncode = function fontItemEncodeLong(data, offset, value) {
- data[offset] = value >>> 24 & 0xFF;
- data[offset + 1] = value >> 16 & 0xFF;
- data[offset + 2] = value >> 8 & 0xFF;
- data[offset + 3] = value & 0xFF;
- };
- } else {
- itemSize = 2;
- itemDecode = function fontItemDecode(data, offset) {
- return data[offset] << 9 | data[offset + 1] << 1;
- };
- itemEncode = function fontItemEncode(data, offset, value) {
- data[offset] = value >> 9 & 0xFF;
- data[offset + 1] = value >> 1 & 0xFF;
- };
- }
- var numGlyphsOut = dupFirstEntry ? numGlyphs + 1 : numGlyphs;
- var locaData = loca.data;
- var locaDataSize = itemSize * (1 + numGlyphsOut);
- locaData = new Uint8Array(locaDataSize);
- locaData.set(loca.data.subarray(0, locaDataSize));
- loca.data = locaData;
- var oldGlyfData = glyf.data;
- var oldGlyfDataLength = oldGlyfData.length;
- var newGlyfData = new Uint8Array(oldGlyfDataLength);
- var startOffset = itemDecode(locaData, 0);
- var writeOffset = 0;
- var missingGlyphs = Object.create(null);
- itemEncode(locaData, 0, writeOffset);
- var i, j;
- for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {
- var endOffset = itemDecode(locaData, j);
- if (endOffset === 0) {
- endOffset = startOffset;
- }
- if (endOffset > oldGlyfDataLength && (oldGlyfDataLength + 3 & ~3) === endOffset) {
- endOffset = oldGlyfDataLength;
- }
- if (endOffset > oldGlyfDataLength) {
- startOffset = endOffset;
- }
- var glyphProfile = sanitizeGlyph(oldGlyfData, startOffset, endOffset, newGlyfData, writeOffset, hintsValid);
- var newLength = glyphProfile.length;
- if (newLength === 0) {
- missingGlyphs[i] = true;
- }
- if (glyphProfile.sizeOfInstructions > maxSizeOfInstructions) {
- maxSizeOfInstructions = glyphProfile.sizeOfInstructions;
- }
- writeOffset += newLength;
- itemEncode(locaData, j, writeOffset);
- startOffset = endOffset;
- }
- if (writeOffset === 0) {
- var simpleGlyph = new Uint8Array([0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0]);
- for (i = 0, j = itemSize; i < numGlyphsOut; i++, j += itemSize) {
- itemEncode(locaData, j, simpleGlyph.length);
- }
- glyf.data = simpleGlyph;
- } else if (dupFirstEntry) {
- var firstEntryLength = itemDecode(locaData, itemSize);
- if (newGlyfData.length > firstEntryLength + writeOffset) {
- glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset);
- } else {
- glyf.data = new Uint8Array(firstEntryLength + writeOffset);
- glyf.data.set(newGlyfData.subarray(0, writeOffset));
- }
- glyf.data.set(newGlyfData.subarray(0, firstEntryLength), writeOffset);
- itemEncode(loca.data, locaData.length - itemSize, writeOffset + firstEntryLength);
- } else {
- glyf.data = newGlyfData.subarray(0, writeOffset);
- }
- return {
- missingGlyphs: missingGlyphs,
- maxSizeOfInstructions: maxSizeOfInstructions
- };
- }
- function readPostScriptTable(post, properties, maxpNumGlyphs) {
- var start = (font.start ? font.start : 0) + post.offset;
- font.pos = start;
- var length = post.length,
- end = start + length;
- var version = font.getInt32();
- font.getBytes(28);
- var glyphNames;
- var valid = true;
- var i;
- switch (version) {
- case 0x00010000:
- glyphNames = MacStandardGlyphOrdering;
- break;
- case 0x00020000:
- var numGlyphs = font.getUint16();
- if (numGlyphs !== maxpNumGlyphs) {
- valid = false;
- break;
- }
- var glyphNameIndexes = [];
- for (i = 0; i < numGlyphs; ++i) {
- var index = font.getUint16();
- if (index >= 32768) {
- valid = false;
- break;
- }
- glyphNameIndexes.push(index);
- }
- if (!valid) {
- break;
- }
- var customNames = [];
- var strBuf = [];
- while (font.pos < end) {
- var stringLength = font.getByte();
- strBuf.length = stringLength;
- for (i = 0; i < stringLength; ++i) {
- strBuf[i] = String.fromCharCode(font.getByte());
- }
- customNames.push(strBuf.join(''));
- }
- glyphNames = [];
- for (i = 0; i < numGlyphs; ++i) {
- var j = glyphNameIndexes[i];
- if (j < 258) {
- glyphNames.push(MacStandardGlyphOrdering[j]);
- continue;
- }
- glyphNames.push(customNames[j - 258]);
- }
- break;
- case 0x00030000:
- break;
- default:
- (0, _util.warn)('Unknown/unsupported post table version ' + version);
- valid = false;
- if (properties.defaultEncoding) {
- glyphNames = properties.defaultEncoding;
- }
- break;
- }
- properties.glyphNames = glyphNames;
- return valid;
- }
- function readNameTable(nameTable) {
- var start = (font.start ? font.start : 0) + nameTable.offset;
- font.pos = start;
- var names = [[], []];
- var length = nameTable.length,
- end = start + length;
- var format = font.getUint16();
- var FORMAT_0_HEADER_LENGTH = 6;
- if (format !== 0 || length < FORMAT_0_HEADER_LENGTH) {
- return names;
- }
- var numRecords = font.getUint16();
- var stringsStart = font.getUint16();
- var records = [];
- var NAME_RECORD_LENGTH = 12;
- var i, ii;
- for (i = 0; i < numRecords && font.pos + NAME_RECORD_LENGTH <= end; i++) {
- var r = {
- platform: font.getUint16(),
- encoding: font.getUint16(),
- language: font.getUint16(),
- name: font.getUint16(),
- length: font.getUint16(),
- offset: font.getUint16()
- };
- if (r.platform === 1 && r.encoding === 0 && r.language === 0 || r.platform === 3 && r.encoding === 1 && r.language === 0x409) {
- records.push(r);
- }
- }
- for (i = 0, ii = records.length; i < ii; i++) {
- var record = records[i];
- if (record.length <= 0) {
- continue;
- }
- var pos = start + stringsStart + record.offset;
- if (pos + record.length > end) {
- continue;
- }
- font.pos = pos;
- var nameIndex = record.name;
- if (record.encoding) {
- var str = '';
- for (var j = 0, jj = record.length; j < jj; j += 2) {
- str += String.fromCharCode(font.getUint16());
- }
- names[1][nameIndex] = str;
- } else {
- names[0][nameIndex] = (0, _util.bytesToString)(font.getBytes(record.length));
- }
- }
- return names;
- }
- var TTOpsStackDeltas = [0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -2, -2, 0, 0, -2, -5, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, -1, -1, 1, -1, -999, 0, 1, 0, -1, -2, 0, -1, -2, -1, -1, 0, -1, -1, 0, 0, -999, -999, -1, -1, -1, -1, -2, -999, -2, -2, -999, 0, -2, -2, 0, 0, -2, 0, -2, 0, 0, 0, -2, -1, -1, 1, 1, 0, 0, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, 0, -999, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -999, -999, -999, -999, -999, -1, -1, -2, -2, 0, 0, 0, 0, -1, -1, -999, -2, -2, 0, 0, -1, -2, -2, 0, 0, 0, -1, -1, -1, -2];
- function sanitizeTTProgram(table, ttContext) {
- var data = table.data;
- var i = 0,
- j,
- n,
- b,
- funcId,
- pc,
- lastEndf = 0,
- lastDeff = 0;
- var stack = [];
- var callstack = [];
- var functionsCalled = [];
- var tooComplexToFollowFunctions = ttContext.tooComplexToFollowFunctions;
- var inFDEF = false,
- ifLevel = 0,
- inELSE = 0;
- for (var ii = data.length; i < ii;) {
- var op = data[i++];
- if (op === 0x40) {
- n = data[i++];
- if (inFDEF || inELSE) {
- i += n;
- } else {
- for (j = 0; j < n; j++) {
- stack.push(data[i++]);
- }
- }
- } else if (op === 0x41) {
- n = data[i++];
- if (inFDEF || inELSE) {
- i += n * 2;
- } else {
- for (j = 0; j < n; j++) {
- b = data[i++];
- stack.push(b << 8 | data[i++]);
- }
- }
- } else if ((op & 0xF8) === 0xB0) {
- n = op - 0xB0 + 1;
- if (inFDEF || inELSE) {
- i += n;
- } else {
- for (j = 0; j < n; j++) {
- stack.push(data[i++]);
- }
- }
- } else if ((op & 0xF8) === 0xB8) {
- n = op - 0xB8 + 1;
- if (inFDEF || inELSE) {
- i += n * 2;
- } else {
- for (j = 0; j < n; j++) {
- b = data[i++];
- stack.push(b << 8 | data[i++]);
- }
- }
- } else if (op === 0x2B && !tooComplexToFollowFunctions) {
- if (!inFDEF && !inELSE) {
- funcId = stack[stack.length - 1];
- if (isNaN(funcId)) {
- (0, _util.info)('TT: CALL empty stack (or invalid entry).');
- } else {
- ttContext.functionsUsed[funcId] = true;
- if (funcId in ttContext.functionsStackDeltas) {
- var newStackLength = stack.length + ttContext.functionsStackDeltas[funcId];
- if (newStackLength < 0) {
- (0, _util.warn)('TT: CALL invalid functions stack delta.');
- ttContext.hintsValid = false;
- return;
- }
- stack.length = newStackLength;
- } else if (funcId in ttContext.functionsDefined && !functionsCalled.includes(funcId)) {
- callstack.push({
- data: data,
- i: i,
- stackTop: stack.length - 1
- });
- functionsCalled.push(funcId);
- pc = ttContext.functionsDefined[funcId];
- if (!pc) {
- (0, _util.warn)('TT: CALL non-existent function');
- ttContext.hintsValid = false;
- return;
- }
- data = pc.data;
- i = pc.i;
- }
- }
- }
- } else if (op === 0x2C && !tooComplexToFollowFunctions) {
- if (inFDEF || inELSE) {
- (0, _util.warn)('TT: nested FDEFs not allowed');
- tooComplexToFollowFunctions = true;
- }
- inFDEF = true;
- lastDeff = i;
- funcId = stack.pop();
- ttContext.functionsDefined[funcId] = {
- data: data,
- i: i
- };
- } else if (op === 0x2D) {
- if (inFDEF) {
- inFDEF = false;
- lastEndf = i;
- } else {
- pc = callstack.pop();
- if (!pc) {
- (0, _util.warn)('TT: ENDF bad stack');
- ttContext.hintsValid = false;
- return;
- }
- funcId = functionsCalled.pop();
- data = pc.data;
- i = pc.i;
- ttContext.functionsStackDeltas[funcId] = stack.length - pc.stackTop;
- }
- } else if (op === 0x89) {
- if (inFDEF || inELSE) {
- (0, _util.warn)('TT: nested IDEFs not allowed');
- tooComplexToFollowFunctions = true;
- }
- inFDEF = true;
- lastDeff = i;
- } else if (op === 0x58) {
- ++ifLevel;
- } else if (op === 0x1B) {
- inELSE = ifLevel;
- } else if (op === 0x59) {
- if (inELSE === ifLevel) {
- inELSE = 0;
- }
- --ifLevel;
- } else if (op === 0x1C) {
- if (!inFDEF && !inELSE) {
- var offset = stack[stack.length - 1];
- if (offset > 0) {
- i += offset - 1;
- }
- }
- }
- if (!inFDEF && !inELSE) {
- var stackDelta = op <= 0x8E ? TTOpsStackDeltas[op] : op >= 0xC0 && op <= 0xDF ? -1 : op >= 0xE0 ? -2 : 0;
- if (op >= 0x71 && op <= 0x75) {
- n = stack.pop();
- if (!isNaN(n)) {
- stackDelta = -n * 2;
- }
- }
- while (stackDelta < 0 && stack.length > 0) {
- stack.pop();
- stackDelta++;
- }
- while (stackDelta > 0) {
- stack.push(NaN);
- stackDelta--;
- }
- }
- }
- ttContext.tooComplexToFollowFunctions = tooComplexToFollowFunctions;
- var content = [data];
- if (i > data.length) {
- content.push(new Uint8Array(i - data.length));
- }
- if (lastDeff > lastEndf) {
- (0, _util.warn)('TT: complementing a missing function tail');
- content.push(new Uint8Array([0x22, 0x2D]));
- }
- foldTTTable(table, content);
- }
- function checkInvalidFunctions(ttContext, maxFunctionDefs) {
- if (ttContext.tooComplexToFollowFunctions) {
- return;
- }
- if (ttContext.functionsDefined.length > maxFunctionDefs) {
- (0, _util.warn)('TT: more functions defined than expected');
- ttContext.hintsValid = false;
- return;
- }
- for (var j = 0, jj = ttContext.functionsUsed.length; j < jj; j++) {
- if (j > maxFunctionDefs) {
- (0, _util.warn)('TT: invalid function id: ' + j);
- ttContext.hintsValid = false;
- return;
- }
- if (ttContext.functionsUsed[j] && !ttContext.functionsDefined[j]) {
- (0, _util.warn)('TT: undefined function: ' + j);
- ttContext.hintsValid = false;
- return;
- }
- }
- }
- function foldTTTable(table, content) {
- if (content.length > 1) {
- var newLength = 0;
- var j, jj;
- for (j = 0, jj = content.length; j < jj; j++) {
- newLength += content[j].length;
- }
- newLength = newLength + 3 & ~3;
- var result = new Uint8Array(newLength);
- var pos = 0;
- for (j = 0, jj = content.length; j < jj; j++) {
- result.set(content[j], pos);
- pos += content[j].length;
- }
- table.data = result;
- table.length = newLength;
- }
- }
- function sanitizeTTPrograms(fpgm, prep, cvt, maxFunctionDefs) {
- var ttContext = {
- functionsDefined: [],
- functionsUsed: [],
- functionsStackDeltas: [],
- tooComplexToFollowFunctions: false,
- hintsValid: true
- };
- if (fpgm) {
- sanitizeTTProgram(fpgm, ttContext);
- }
- if (prep) {
- sanitizeTTProgram(prep, ttContext);
- }
- if (fpgm) {
- checkInvalidFunctions(ttContext, maxFunctionDefs);
- }
- if (cvt && cvt.length & 1) {
- var cvtData = new Uint8Array(cvt.length + 1);
- cvtData.set(cvt.data);
- cvt.data = cvtData;
- }
- return ttContext.hintsValid;
- }
- font = new _stream.Stream(new Uint8Array(font.getBytes()));
- var header = void 0,
- tables = void 0;
- if (isTrueTypeCollectionFile(font)) {
- var ttcData = readTrueTypeCollectionData(font, this.name);
- header = ttcData.header;
- tables = ttcData.tables;
- } else {
- header = readOpenTypeHeader(font);
- tables = readTables(font, header.numTables);
- }
- var cff = void 0,
- cffFile = void 0;
- var isTrueType = !tables['CFF '];
- if (!isTrueType) {
- var isComposite = properties.composite && ((properties.cidToGidMap || []).length > 0 || !(properties.cMap instanceof _cmap.IdentityCMap));
- if (header.version === 'OTTO' && !isComposite || !tables['head'] || !tables['hhea'] || !tables['maxp'] || !tables['post']) {
- cffFile = new _stream.Stream(tables['CFF '].data);
- cff = new CFFFont(cffFile, properties);
- adjustWidths(properties);
- return this.convert(name, cff, properties);
- }
- delete tables['glyf'];
- delete tables['loca'];
- delete tables['fpgm'];
- delete tables['prep'];
- delete tables['cvt '];
- this.isOpenType = true;
- } else {
- if (!tables['loca']) {
- throw new _util.FormatError('Required "loca" table is not found');
- }
- if (!tables['glyf']) {
- (0, _util.warn)('Required "glyf" table is not found -- trying to recover.');
- tables['glyf'] = {
- tag: 'glyf',
- data: new Uint8Array(0)
- };
- }
- this.isOpenType = false;
- }
- if (!tables['maxp']) {
- throw new _util.FormatError('Required "maxp" table is not found');
- }
- font.pos = (font.start || 0) + tables['maxp'].offset;
- var version = font.getInt32();
- var numGlyphs = font.getUint16();
- var numGlyphsOut = numGlyphs + 1;
- var dupFirstEntry = true;
- if (numGlyphsOut > 0xFFFF) {
- dupFirstEntry = false;
- numGlyphsOut = numGlyphs;
- (0, _util.warn)('Not enough space in glyfs to duplicate first glyph.');
- }
- var maxFunctionDefs = 0;
- var maxSizeOfInstructions = 0;
- if (version >= 0x00010000 && tables['maxp'].length >= 22) {
- font.pos += 8;
- var maxZones = font.getUint16();
- if (maxZones > 2) {
- tables['maxp'].data[14] = 0;
- tables['maxp'].data[15] = 2;
- }
- font.pos += 4;
- maxFunctionDefs = font.getUint16();
- font.pos += 4;
- maxSizeOfInstructions = font.getUint16();
- }
- tables['maxp'].data[4] = numGlyphsOut >> 8;
- tables['maxp'].data[5] = numGlyphsOut & 255;
- var hintsValid = sanitizeTTPrograms(tables['fpgm'], tables['prep'], tables['cvt '], maxFunctionDefs);
- if (!hintsValid) {
- delete tables['fpgm'];
- delete tables['prep'];
- delete tables['cvt '];
- }
- sanitizeMetrics(font, tables['hhea'], tables['hmtx'], numGlyphsOut);
- if (!tables['head']) {
- throw new _util.FormatError('Required "head" table is not found');
- }
- sanitizeHead(tables['head'], numGlyphs, isTrueType ? tables['loca'].length : 0);
- var missingGlyphs = Object.create(null);
- if (isTrueType) {
- var isGlyphLocationsLong = int16(tables['head'].data[50], tables['head'].data[51]);
- var glyphsInfo = sanitizeGlyphLocations(tables['loca'], tables['glyf'], numGlyphs, isGlyphLocationsLong, hintsValid, dupFirstEntry, maxSizeOfInstructions);
- missingGlyphs = glyphsInfo.missingGlyphs;
- if (version >= 0x00010000 && tables['maxp'].length >= 22) {
- tables['maxp'].data[26] = glyphsInfo.maxSizeOfInstructions >> 8;
- tables['maxp'].data[27] = glyphsInfo.maxSizeOfInstructions & 255;
- }
- }
- if (!tables['hhea']) {
- throw new _util.FormatError('Required "hhea" table is not found');
- }
- if (tables['hhea'].data[10] === 0 && tables['hhea'].data[11] === 0) {
- tables['hhea'].data[10] = 0xFF;
- tables['hhea'].data[11] = 0xFF;
- }
- var metricsOverride = {
- unitsPerEm: int16(tables['head'].data[18], tables['head'].data[19]),
- yMax: int16(tables['head'].data[42], tables['head'].data[43]),
- yMin: signedInt16(tables['head'].data[38], tables['head'].data[39]),
- ascent: int16(tables['hhea'].data[4], tables['hhea'].data[5]),
- descent: signedInt16(tables['hhea'].data[6], tables['hhea'].data[7])
- };
- this.ascent = metricsOverride.ascent / metricsOverride.unitsPerEm;
- this.descent = metricsOverride.descent / metricsOverride.unitsPerEm;
- if (tables['post']) {
- readPostScriptTable(tables['post'], properties, numGlyphs);
- }
- tables['post'] = {
- tag: 'post',
- data: createPostTable(properties)
- };
- var charCodeToGlyphId = [],
- charCode;
- function hasGlyph(glyphId) {
- return !missingGlyphs[glyphId];
- }
- if (properties.composite) {
- var cidToGidMap = properties.cidToGidMap || [];
- var isCidToGidMapEmpty = cidToGidMap.length === 0;
- properties.cMap.forEach(function (charCode, cid) {
- if (cid > 0xffff) {
- throw new _util.FormatError('Max size of CID is 65,535');
- }
- var glyphId = -1;
- if (isCidToGidMapEmpty) {
- glyphId = cid;
- } else if (cidToGidMap[cid] !== undefined) {
- glyphId = cidToGidMap[cid];
- }
- if (glyphId >= 0 && glyphId < numGlyphs && hasGlyph(glyphId)) {
- charCodeToGlyphId[charCode] = glyphId;
- }
- });
- } else {
- var cmapTable = readCmapTable(tables['cmap'], font, this.isSymbolicFont, properties.hasEncoding);
- var cmapPlatformId = cmapTable.platformId;
- var cmapEncodingId = cmapTable.encodingId;
- var cmapMappings = cmapTable.mappings;
- var cmapMappingsLength = cmapMappings.length;
- if (properties.hasEncoding && (cmapPlatformId === 3 && cmapEncodingId === 1 || cmapPlatformId === 1 && cmapEncodingId === 0) || cmapPlatformId === -1 && cmapEncodingId === -1 && !!(0, _encodings.getEncoding)(properties.baseEncodingName)) {
- var baseEncoding = [];
- if (properties.baseEncodingName === 'MacRomanEncoding' || properties.baseEncodingName === 'WinAnsiEncoding') {
- baseEncoding = (0, _encodings.getEncoding)(properties.baseEncodingName);
- }
- var glyphsUnicodeMap = (0, _glyphlist.getGlyphsUnicode)();
- for (charCode = 0; charCode < 256; charCode++) {
- var glyphName, standardGlyphName;
- if (this.differences && charCode in this.differences) {
- glyphName = this.differences[charCode];
- } else if (charCode in baseEncoding && baseEncoding[charCode] !== '') {
- glyphName = baseEncoding[charCode];
- } else {
- glyphName = _encodings.StandardEncoding[charCode];
- }
- if (!glyphName) {
- continue;
- }
- standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap);
- var unicodeOrCharCode;
- if (cmapPlatformId === 3 && cmapEncodingId === 1) {
- unicodeOrCharCode = glyphsUnicodeMap[standardGlyphName];
- } else if (cmapPlatformId === 1 && cmapEncodingId === 0) {
- unicodeOrCharCode = _encodings.MacRomanEncoding.indexOf(standardGlyphName);
- }
- var found = false;
- for (var i = 0; i < cmapMappingsLength; ++i) {
- if (cmapMappings[i].charCode !== unicodeOrCharCode) {
- continue;
- }
- charCodeToGlyphId[charCode] = cmapMappings[i].glyphId;
- found = true;
- break;
- }
- if (!found && properties.glyphNames) {
- var glyphId = properties.glyphNames.indexOf(glyphName);
- if (glyphId === -1 && standardGlyphName !== glyphName) {
- glyphId = properties.glyphNames.indexOf(standardGlyphName);
- }
- if (glyphId > 0 && hasGlyph(glyphId)) {
- charCodeToGlyphId[charCode] = glyphId;
- }
- }
- }
- } else if (cmapPlatformId === 0 && cmapEncodingId === 0) {
- for (var _i = 0; _i < cmapMappingsLength; ++_i) {
- charCodeToGlyphId[cmapMappings[_i].charCode] = cmapMappings[_i].glyphId;
- }
- } else {
- for (var _i2 = 0; _i2 < cmapMappingsLength; ++_i2) {
- charCode = cmapMappings[_i2].charCode;
- if (cmapPlatformId === 3 && charCode >= 0xF000 && charCode <= 0xF0FF) {
- charCode &= 0xFF;
- }
- charCodeToGlyphId[charCode] = cmapMappings[_i2].glyphId;
- }
- }
- }
- if (charCodeToGlyphId.length === 0) {
- charCodeToGlyphId[0] = 0;
- }
- var glyphZeroId = numGlyphsOut - 1;
- if (!dupFirstEntry) {
- glyphZeroId = 0;
- }
- var newMapping = adjustMapping(charCodeToGlyphId, hasGlyph, glyphZeroId);
- this.toFontChar = newMapping.toFontChar;
- tables['cmap'] = {
- tag: 'cmap',
- data: createCmapTable(newMapping.charCodeToGlyphId, numGlyphsOut)
- };
- if (!tables['OS/2'] || !validateOS2Table(tables['OS/2'])) {
- tables['OS/2'] = {
- tag: 'OS/2',
- data: createOS2Table(properties, newMapping.charCodeToGlyphId, metricsOverride)
- };
- }
- if (!isTrueType) {
- try {
- cffFile = new _stream.Stream(tables['CFF '].data);
- var parser = new _cff_parser.CFFParser(cffFile, properties, SEAC_ANALYSIS_ENABLED);
- cff = parser.parse();
- cff.duplicateFirstGlyph();
- var compiler = new _cff_parser.CFFCompiler(cff);
- tables['CFF '].data = compiler.compile();
- } catch (e) {
- (0, _util.warn)('Failed to compile font ' + properties.loadedName);
- }
- }
- if (!tables['name']) {
- tables['name'] = {
- tag: 'name',
- data: createNameTable(this.name)
- };
- } else {
- var namePrototype = readNameTable(tables['name']);
- tables['name'].data = createNameTable(name, namePrototype);
- }
- var builder = new OpenTypeFileBuilder(header.version);
- for (var tableTag in tables) {
- builder.addTable(tableTag, tables[tableTag].data);
- }
- return builder.toArray();
- },
- convert: function Font_convert(fontName, font, properties) {
- properties.fixedPitch = false;
- if (properties.builtInEncoding) {
- adjustToUnicode(properties, properties.builtInEncoding);
- }
- var glyphZeroId = 1;
- if (font instanceof CFFFont) {
- glyphZeroId = font.numGlyphs - 1;
- }
- var mapping = font.getGlyphMapping(properties);
- var newMapping = adjustMapping(mapping, font.hasGlyphId.bind(font), glyphZeroId);
- this.toFontChar = newMapping.toFontChar;
- var numGlyphs = font.numGlyphs;
- function getCharCodes(charCodeToGlyphId, glyphId) {
- var charCodes = null;
- for (var charCode in charCodeToGlyphId) {
- if (glyphId === charCodeToGlyphId[charCode]) {
- if (!charCodes) {
- charCodes = [];
- }
- charCodes.push(charCode | 0);
- }
- }
- return charCodes;
- }
- function createCharCode(charCodeToGlyphId, glyphId) {
- for (var charCode in charCodeToGlyphId) {
- if (glyphId === charCodeToGlyphId[charCode]) {
- return charCode | 0;
- }
- }
- newMapping.charCodeToGlyphId[newMapping.nextAvailableFontCharCode] = glyphId;
- return newMapping.nextAvailableFontCharCode++;
- }
- var seacs = font.seacs;
- if (SEAC_ANALYSIS_ENABLED && seacs && seacs.length) {
- var matrix = properties.fontMatrix || _util.FONT_IDENTITY_MATRIX;
- var charset = font.getCharset();
- var seacMap = Object.create(null);
- for (var glyphId in seacs) {
- glyphId |= 0;
- var seac = seacs[glyphId];
- var baseGlyphName = _encodings.StandardEncoding[seac[2]];
- var accentGlyphName = _encodings.StandardEncoding[seac[3]];
- var baseGlyphId = charset.indexOf(baseGlyphName);
- var accentGlyphId = charset.indexOf(accentGlyphName);
- if (baseGlyphId < 0 || accentGlyphId < 0) {
- continue;
- }
- var accentOffset = {
- x: seac[0] * matrix[0] + seac[1] * matrix[2] + matrix[4],
- y: seac[0] * matrix[1] + seac[1] * matrix[3] + matrix[5]
- };
- var charCodes = getCharCodes(mapping, glyphId);
- if (!charCodes) {
- continue;
- }
- for (var i = 0, ii = charCodes.length; i < ii; i++) {
- var charCode = charCodes[i];
- var charCodeToGlyphId = newMapping.charCodeToGlyphId;
- var baseFontCharCode = createCharCode(charCodeToGlyphId, baseGlyphId);
- var accentFontCharCode = createCharCode(charCodeToGlyphId, accentGlyphId);
- seacMap[charCode] = {
- baseFontCharCode: baseFontCharCode,
- accentFontCharCode: accentFontCharCode,
- accentOffset: accentOffset
- };
- }
- }
- properties.seacMap = seacMap;
- }
- var unitsPerEm = 1 / (properties.fontMatrix || _util.FONT_IDENTITY_MATRIX)[0];
- var builder = new OpenTypeFileBuilder('\x4F\x54\x54\x4F');
- builder.addTable('CFF ', font.data);
- builder.addTable('OS/2', createOS2Table(properties, newMapping.charCodeToGlyphId));
- builder.addTable('cmap', createCmapTable(newMapping.charCodeToGlyphId, numGlyphs));
- builder.addTable('head', '\x00\x01\x00\x00' + '\x00\x00\x10\x00' + '\x00\x00\x00\x00' + '\x5F\x0F\x3C\xF5' + '\x00\x00' + safeString16(unitsPerEm) + '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + '\x00\x00' + safeString16(properties.descent) + '\x0F\xFF' + safeString16(properties.ascent) + string16(properties.italicAngle ? 2 : 0) + '\x00\x11' + '\x00\x00' + '\x00\x00' + '\x00\x00');
- builder.addTable('hhea', '\x00\x01\x00\x00' + safeString16(properties.ascent) + safeString16(properties.descent) + '\x00\x00' + '\xFF\xFF' + '\x00\x00' + '\x00\x00' + '\x00\x00' + safeString16(properties.capHeight) + safeString16(Math.tan(properties.italicAngle) * properties.xHeight) + '\x00\x00' + '\x00\x00' + '\x00\x00' + '\x00\x00' + '\x00\x00' + '\x00\x00' + string16(numGlyphs));
- builder.addTable('hmtx', function fontFieldsHmtx() {
- var charstrings = font.charstrings;
- var cffWidths = font.cff ? font.cff.widths : null;
- var hmtx = '\x00\x00\x00\x00';
- for (var i = 1, ii = numGlyphs; i < ii; i++) {
- var width = 0;
- if (charstrings) {
- var charstring = charstrings[i - 1];
- width = 'width' in charstring ? charstring.width : 0;
- } else if (cffWidths) {
- width = Math.ceil(cffWidths[i] || 0);
- }
- hmtx += string16(width) + string16(0);
- }
- return hmtx;
- }());
- builder.addTable('maxp', '\x00\x00\x50\x00' + string16(numGlyphs));
- builder.addTable('name', createNameTable(fontName));
- builder.addTable('post', createPostTable(properties));
- return builder.toArray();
- },
- get spaceWidth() {
- if ('_shadowWidth' in this) {
- return this._shadowWidth;
- }
- var possibleSpaceReplacements = ['space', 'minus', 'one', 'i', 'I'];
- var width;
- for (var i = 0, ii = possibleSpaceReplacements.length; i < ii; i++) {
- var glyphName = possibleSpaceReplacements[i];
- if (glyphName in this.widths) {
- width = this.widths[glyphName];
- break;
- }
- var glyphsUnicodeMap = (0, _glyphlist.getGlyphsUnicode)();
- var glyphUnicode = glyphsUnicodeMap[glyphName];
- var charcode = 0;
- if (this.composite) {
- if (this.cMap.contains(glyphUnicode)) {
- charcode = this.cMap.lookup(glyphUnicode);
- }
- }
- if (!charcode && this.toUnicode) {
- charcode = this.toUnicode.charCodeOf(glyphUnicode);
- }
- if (charcode <= 0) {
- charcode = glyphUnicode;
- }
- width = this.widths[charcode];
- if (width) {
- break;
- }
- }
- width = width || this.defaultWidth;
- this._shadowWidth = width;
- return width;
- },
- charToGlyph: function Font_charToGlyph(charcode, isSpace) {
- var fontCharCode, width, operatorListId;
- var widthCode = charcode;
- if (this.cMap && this.cMap.contains(charcode)) {
- widthCode = this.cMap.lookup(charcode);
- }
- width = this.widths[widthCode];
- width = (0, _util.isNum)(width) ? width : this.defaultWidth;
- var vmetric = this.vmetrics && this.vmetrics[widthCode];
- var unicode = this.toUnicode.get(charcode) || this.fallbackToUnicode.get(charcode) || charcode;
- if (typeof unicode === 'number') {
- unicode = String.fromCharCode(unicode);
- }
- var isInFont = charcode in this.toFontChar;
- fontCharCode = this.toFontChar[charcode] || charcode;
- if (this.missingFile) {
- fontCharCode = (0, _unicode.mapSpecialUnicodeValues)(fontCharCode);
- }
- if (this.isType3Font) {
- operatorListId = fontCharCode;
- }
- var accent = null;
- if (this.seacMap && this.seacMap[charcode]) {
- isInFont = true;
- var seac = this.seacMap[charcode];
- fontCharCode = seac.baseFontCharCode;
- accent = {
- fontChar: String.fromCodePoint(seac.accentFontCharCode),
- offset: seac.accentOffset
- };
- }
- var fontChar = typeof fontCharCode === 'number' ? String.fromCodePoint(fontCharCode) : '';
- var glyph = this.glyphCache[charcode];
- if (!glyph || !glyph.matchesForCache(fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont)) {
- glyph = new Glyph(fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont);
- this.glyphCache[charcode] = glyph;
- }
- return glyph;
- },
- charsToGlyphs: function Font_charsToGlyphs(chars) {
- var charsCache = this.charsCache;
- var glyphs, glyph, charcode;
- if (charsCache) {
- glyphs = charsCache[chars];
- if (glyphs) {
- return glyphs;
- }
- }
- if (!charsCache) {
- charsCache = this.charsCache = Object.create(null);
- }
- glyphs = [];
- var charsCacheKey = chars;
- var i = 0,
- ii;
- if (this.cMap) {
- var c = Object.create(null);
- while (i < chars.length) {
- this.cMap.readCharCode(chars, i, c);
- charcode = c.charcode;
- var length = c.length;
- i += length;
- var isSpace = length === 1 && chars.charCodeAt(i - 1) === 0x20;
- glyph = this.charToGlyph(charcode, isSpace);
- glyphs.push(glyph);
- }
- } else {
- for (i = 0, ii = chars.length; i < ii; ++i) {
- charcode = chars.charCodeAt(i);
- glyph = this.charToGlyph(charcode, charcode === 0x20);
- glyphs.push(glyph);
- }
- }
- return charsCache[charsCacheKey] = glyphs;
- }
- };
- return Font;
-}();
-var ErrorFont = function ErrorFontClosure() {
- function ErrorFont(error) {
- this.error = error;
- this.loadedName = 'g_font_error';
- this.missingFile = true;
- }
- ErrorFont.prototype = {
- charsToGlyphs: function ErrorFont_charsToGlyphs() {
- return [];
- },
- exportData: function ErrorFont_exportData() {
- return { error: this.error };
- }
- };
- return ErrorFont;
-}();
-function type1FontGlyphMapping(properties, builtInEncoding, glyphNames) {
- var charCodeToGlyphId = Object.create(null);
- var glyphId, charCode, baseEncoding;
- var isSymbolicFont = !!(properties.flags & FontFlags.Symbolic);
- if (properties.baseEncodingName) {
- baseEncoding = (0, _encodings.getEncoding)(properties.baseEncodingName);
- for (charCode = 0; charCode < baseEncoding.length; charCode++) {
- glyphId = glyphNames.indexOf(baseEncoding[charCode]);
- if (glyphId >= 0) {
- charCodeToGlyphId[charCode] = glyphId;
- } else {
- charCodeToGlyphId[charCode] = 0;
- }
- }
- } else if (isSymbolicFont) {
- for (charCode in builtInEncoding) {
- charCodeToGlyphId[charCode] = builtInEncoding[charCode];
- }
- } else {
- baseEncoding = _encodings.StandardEncoding;
- for (charCode = 0; charCode < baseEncoding.length; charCode++) {
- glyphId = glyphNames.indexOf(baseEncoding[charCode]);
- if (glyphId >= 0) {
- charCodeToGlyphId[charCode] = glyphId;
- } else {
- charCodeToGlyphId[charCode] = 0;
- }
- }
- }
- var differences = properties.differences,
- glyphsUnicodeMap;
- if (differences) {
- for (charCode in differences) {
- var glyphName = differences[charCode];
- glyphId = glyphNames.indexOf(glyphName);
- if (glyphId === -1) {
- if (!glyphsUnicodeMap) {
- glyphsUnicodeMap = (0, _glyphlist.getGlyphsUnicode)();
- }
- var standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap);
- if (standardGlyphName !== glyphName) {
- glyphId = glyphNames.indexOf(standardGlyphName);
- }
- }
- if (glyphId >= 0) {
- charCodeToGlyphId[charCode] = glyphId;
- } else {
- charCodeToGlyphId[charCode] = 0;
- }
- }
- }
- return charCodeToGlyphId;
-}
-var Type1Font = function Type1FontClosure() {
- function findBlock(streamBytes, signature, startIndex) {
- var streamBytesLength = streamBytes.length;
- var signatureLength = signature.length;
- var scanLength = streamBytesLength - signatureLength;
- var i = startIndex,
- j,
- found = false;
- while (i < scanLength) {
- j = 0;
- while (j < signatureLength && streamBytes[i + j] === signature[j]) {
- j++;
- }
- if (j >= signatureLength) {
- i += j;
- while (i < streamBytesLength && (0, _util.isSpace)(streamBytes[i])) {
- i++;
- }
- found = true;
- break;
- }
- i++;
- }
- return {
- found: found,
- length: i
- };
- }
- function getHeaderBlock(stream, suggestedLength) {
- var EEXEC_SIGNATURE = [0x65, 0x65, 0x78, 0x65, 0x63];
- var streamStartPos = stream.pos;
- var headerBytes, headerBytesLength, block;
- try {
- headerBytes = stream.getBytes(suggestedLength);
- headerBytesLength = headerBytes.length;
- } catch (ex) {
- if (ex instanceof _util.MissingDataException) {
- throw ex;
- }
- }
- if (headerBytesLength === suggestedLength) {
- block = findBlock(headerBytes, EEXEC_SIGNATURE, suggestedLength - 2 * EEXEC_SIGNATURE.length);
- if (block.found && block.length === suggestedLength) {
- return {
- stream: new _stream.Stream(headerBytes),
- length: suggestedLength
- };
- }
- }
- (0, _util.warn)('Invalid "Length1" property in Type1 font -- trying to recover.');
- stream.pos = streamStartPos;
- var SCAN_BLOCK_LENGTH = 2048;
- var actualLength;
- while (true) {
- var scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH);
- block = findBlock(scanBytes, EEXEC_SIGNATURE, 0);
- if (block.length === 0) {
- break;
- }
- stream.pos += block.length;
- if (block.found) {
- actualLength = stream.pos - streamStartPos;
- break;
- }
- }
- stream.pos = streamStartPos;
- if (actualLength) {
- return {
- stream: new _stream.Stream(stream.getBytes(actualLength)),
- length: actualLength
- };
- }
- (0, _util.warn)('Unable to recover "Length1" property in Type1 font -- using as is.');
- return {
- stream: new _stream.Stream(stream.getBytes(suggestedLength)),
- length: suggestedLength
- };
- }
- function getEexecBlock(stream, suggestedLength) {
- var eexecBytes = stream.getBytes();
- return {
- stream: new _stream.Stream(eexecBytes),
- length: eexecBytes.length
- };
- }
- function Type1Font(name, file, properties) {
- var PFB_HEADER_SIZE = 6;
- var headerBlockLength = properties.length1;
- var eexecBlockLength = properties.length2;
- var pfbHeader = file.peekBytes(PFB_HEADER_SIZE);
- var pfbHeaderPresent = pfbHeader[0] === 0x80 && pfbHeader[1] === 0x01;
- if (pfbHeaderPresent) {
- file.skip(PFB_HEADER_SIZE);
- headerBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2];
- }
- var headerBlock = getHeaderBlock(file, headerBlockLength);
- var headerBlockParser = new _type1_parser.Type1Parser(headerBlock.stream, false, SEAC_ANALYSIS_ENABLED);
- headerBlockParser.extractFontHeader(properties);
- if (pfbHeaderPresent) {
- pfbHeader = file.getBytes(PFB_HEADER_SIZE);
- eexecBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2];
- }
- var eexecBlock = getEexecBlock(file, eexecBlockLength);
- var eexecBlockParser = new _type1_parser.Type1Parser(eexecBlock.stream, true, SEAC_ANALYSIS_ENABLED);
- var data = eexecBlockParser.extractFontProgram();
- for (var info in data.properties) {
- properties[info] = data.properties[info];
- }
- var charstrings = data.charstrings;
- var type2Charstrings = this.getType2Charstrings(charstrings);
- var subrs = this.getType2Subrs(data.subrs);
- this.charstrings = charstrings;
- this.data = this.wrap(name, type2Charstrings, this.charstrings, subrs, properties);
- this.seacs = this.getSeacs(data.charstrings);
- }
- Type1Font.prototype = {
- get numGlyphs() {
- return this.charstrings.length + 1;
- },
- getCharset: function Type1Font_getCharset() {
- var charset = ['.notdef'];
- var charstrings = this.charstrings;
- for (var glyphId = 0; glyphId < charstrings.length; glyphId++) {
- charset.push(charstrings[glyphId].glyphName);
- }
- return charset;
- },
- getGlyphMapping: function Type1Font_getGlyphMapping(properties) {
- var charstrings = this.charstrings;
- var glyphNames = ['.notdef'],
- glyphId;
- for (glyphId = 0; glyphId < charstrings.length; glyphId++) {
- glyphNames.push(charstrings[glyphId].glyphName);
- }
- var encoding = properties.builtInEncoding;
- if (encoding) {
- var builtInEncoding = Object.create(null);
- for (var charCode in encoding) {
- glyphId = glyphNames.indexOf(encoding[charCode]);
- if (glyphId >= 0) {
- builtInEncoding[charCode] = glyphId;
- }
- }
- }
- return type1FontGlyphMapping(properties, builtInEncoding, glyphNames);
- },
- hasGlyphId: function Type1Font_hasGlyphID(id) {
- if (id < 0 || id >= this.numGlyphs) {
- return false;
- }
- if (id === 0) {
- return true;
- }
- var glyph = this.charstrings[id - 1];
- return glyph.charstring.length > 0;
- },
- getSeacs: function Type1Font_getSeacs(charstrings) {
- var i, ii;
- var seacMap = [];
- for (i = 0, ii = charstrings.length; i < ii; i++) {
- var charstring = charstrings[i];
- if (charstring.seac) {
- seacMap[i + 1] = charstring.seac;
- }
- }
- return seacMap;
- },
- getType2Charstrings: function Type1Font_getType2Charstrings(type1Charstrings) {
- var type2Charstrings = [];
- for (var i = 0, ii = type1Charstrings.length; i < ii; i++) {
- type2Charstrings.push(type1Charstrings[i].charstring);
- }
- return type2Charstrings;
- },
- getType2Subrs: function Type1Font_getType2Subrs(type1Subrs) {
- var bias = 0;
- var count = type1Subrs.length;
- if (count < 1133) {
- bias = 107;
- } else if (count < 33769) {
- bias = 1131;
- } else {
- bias = 32768;
- }
- var type2Subrs = [];
- var i;
- for (i = 0; i < bias; i++) {
- type2Subrs.push([0x0B]);
- }
- for (i = 0; i < count; i++) {
- type2Subrs.push(type1Subrs[i]);
- }
- return type2Subrs;
- },
- wrap: function Type1Font_wrap(name, glyphs, charstrings, subrs, properties) {
- var cff = new _cff_parser.CFF();
- cff.header = new _cff_parser.CFFHeader(1, 0, 4, 4);
- cff.names = [name];
- var topDict = new _cff_parser.CFFTopDict();
- topDict.setByName('version', 391);
- topDict.setByName('Notice', 392);
- topDict.setByName('FullName', 393);
- topDict.setByName('FamilyName', 394);
- topDict.setByName('Weight', 395);
- topDict.setByName('Encoding', null);
- topDict.setByName('FontMatrix', properties.fontMatrix);
- topDict.setByName('FontBBox', properties.bbox);
- topDict.setByName('charset', null);
- topDict.setByName('CharStrings', null);
- topDict.setByName('Private', null);
- cff.topDict = topDict;
- var strings = new _cff_parser.CFFStrings();
- strings.add('Version 0.11');
- strings.add('See original notice');
- strings.add(name);
- strings.add(name);
- strings.add('Medium');
- cff.strings = strings;
- cff.globalSubrIndex = new _cff_parser.CFFIndex();
- var count = glyphs.length;
- var charsetArray = [0];
- var i, ii;
- for (i = 0; i < count; i++) {
- var index = _cff_parser.CFFStandardStrings.indexOf(charstrings[i].glyphName);
- if (index === -1) {
- index = 0;
- }
- charsetArray.push(index >> 8 & 0xff, index & 0xff);
- }
- cff.charset = new _cff_parser.CFFCharset(false, 0, [], charsetArray);
- var charStringsIndex = new _cff_parser.CFFIndex();
- charStringsIndex.add([0x8B, 0x0E]);
- for (i = 0; i < count; i++) {
- charStringsIndex.add(glyphs[i]);
- }
- cff.charStrings = charStringsIndex;
- var privateDict = new _cff_parser.CFFPrivateDict();
- privateDict.setByName('Subrs', null);
- var fields = ['BlueValues', 'OtherBlues', 'FamilyBlues', 'FamilyOtherBlues', 'StemSnapH', 'StemSnapV', 'BlueShift', 'BlueFuzz', 'BlueScale', 'LanguageGroup', 'ExpansionFactor', 'ForceBold', 'StdHW', 'StdVW'];
- for (i = 0, ii = fields.length; i < ii; i++) {
- var field = fields[i];
- if (!(field in properties.privateData)) {
- continue;
- }
- var value = properties.privateData[field];
- if (Array.isArray(value)) {
- for (var j = value.length - 1; j > 0; j--) {
- value[j] -= value[j - 1];
- }
- }
- privateDict.setByName(field, value);
- }
- cff.topDict.privateDict = privateDict;
- var subrIndex = new _cff_parser.CFFIndex();
- for (i = 0, ii = subrs.length; i < ii; i++) {
- subrIndex.add(subrs[i]);
- }
- privateDict.subrsIndex = subrIndex;
- var compiler = new _cff_parser.CFFCompiler(cff);
- return compiler.compile();
- }
- };
- return Type1Font;
-}();
-var CFFFont = function CFFFontClosure() {
- function CFFFont(file, properties) {
- this.properties = properties;
- var parser = new _cff_parser.CFFParser(file, properties, SEAC_ANALYSIS_ENABLED);
- this.cff = parser.parse();
- this.cff.duplicateFirstGlyph();
- var compiler = new _cff_parser.CFFCompiler(this.cff);
- this.seacs = this.cff.seacs;
- try {
- this.data = compiler.compile();
- } catch (e) {
- (0, _util.warn)('Failed to compile font ' + properties.loadedName);
- this.data = file;
- }
- }
- CFFFont.prototype = {
- get numGlyphs() {
- return this.cff.charStrings.count;
- },
- getCharset: function CFFFont_getCharset() {
- return this.cff.charset.charset;
- },
- getGlyphMapping: function CFFFont_getGlyphMapping() {
- var cff = this.cff;
- var properties = this.properties;
- var charsets = cff.charset.charset;
- var charCodeToGlyphId;
- var glyphId;
- if (properties.composite) {
- charCodeToGlyphId = Object.create(null);
- if (cff.isCIDFont) {
- for (glyphId = 0; glyphId < charsets.length; glyphId++) {
- var cid = charsets[glyphId];
- var charCode = properties.cMap.charCodeOf(cid);
- charCodeToGlyphId[charCode] = glyphId;
- }
- } else {
- for (glyphId = 0; glyphId < cff.charStrings.count; glyphId++) {
- charCodeToGlyphId[glyphId] = glyphId;
- }
- }
- return charCodeToGlyphId;
- }
- var encoding = cff.encoding ? cff.encoding.encoding : null;
- charCodeToGlyphId = type1FontGlyphMapping(properties, encoding, charsets);
- return charCodeToGlyphId;
- },
- hasGlyphId: function CFFFont_hasGlyphID(id) {
- return this.cff.hasGlyphId(id);
- }
- };
- return CFFFont;
-}();
-exports.SEAC_ANALYSIS_ENABLED = SEAC_ANALYSIS_ENABLED;
-exports.ErrorFont = ErrorFont;
-exports.Font = Font;
-exports.FontFlags = FontFlags;
-exports.ToUnicodeMap = ToUnicodeMap;
-exports.IdentityToUnicodeMap = IdentityToUnicodeMap;
-exports.getFontType = getFontType;
-
-/***/ }),
-/* 157 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.CFFFDSelect = exports.CFFCompiler = exports.CFFPrivateDict = exports.CFFTopDict = exports.CFFCharset = exports.CFFIndex = exports.CFFStrings = exports.CFFHeader = exports.CFF = exports.CFFParser = exports.CFFStandardStrings = undefined;
-
-var _util = __w_pdfjs_require__(2);
-
-var _charsets = __w_pdfjs_require__(158);
-
-var _encodings = __w_pdfjs_require__(159);
-
-var MAX_SUBR_NESTING = 10;
-var CFFStandardStrings = ['.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', 'periodcentered', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand', 'questiondown', 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu', 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter', 'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright', 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex', 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla', 'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex', 'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis', 'ugrave', 'yacute', 'ydieresis', 'zcaron', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'commasuperior', 'threequartersemdash', 'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior', 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', 'tsuperior', 'ff', 'ffi', 'ffl', 'parenleftinferior', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall', 'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall', '001.000', '001.001', '001.002', '001.003', 'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold'];
-var CFFParser = function CFFParserClosure() {
- var CharstringValidationData = [null, {
- id: 'hstem',
- min: 2,
- stackClearing: true,
- stem: true
- }, null, {
- id: 'vstem',
- min: 2,
- stackClearing: true,
- stem: true
- }, {
- id: 'vmoveto',
- min: 1,
- stackClearing: true
- }, {
- id: 'rlineto',
- min: 2,
- resetStack: true
- }, {
- id: 'hlineto',
- min: 1,
- resetStack: true
- }, {
- id: 'vlineto',
- min: 1,
- resetStack: true
- }, {
- id: 'rrcurveto',
- min: 6,
- resetStack: true
- }, null, {
- id: 'callsubr',
- min: 1,
- undefStack: true
- }, {
- id: 'return',
- min: 0,
- undefStack: true
- }, null, null, {
- id: 'endchar',
- min: 0,
- stackClearing: true
- }, null, null, null, {
- id: 'hstemhm',
- min: 2,
- stackClearing: true,
- stem: true
- }, {
- id: 'hintmask',
- min: 0,
- stackClearing: true
- }, {
- id: 'cntrmask',
- min: 0,
- stackClearing: true
- }, {
- id: 'rmoveto',
- min: 2,
- stackClearing: true
- }, {
- id: 'hmoveto',
- min: 1,
- stackClearing: true
- }, {
- id: 'vstemhm',
- min: 2,
- stackClearing: true,
- stem: true
- }, {
- id: 'rcurveline',
- min: 8,
- resetStack: true
- }, {
- id: 'rlinecurve',
- min: 8,
- resetStack: true
- }, {
- id: 'vvcurveto',
- min: 4,
- resetStack: true
- }, {
- id: 'hhcurveto',
- min: 4,
- resetStack: true
- }, null, {
- id: 'callgsubr',
- min: 1,
- undefStack: true
- }, {
- id: 'vhcurveto',
- min: 4,
- resetStack: true
- }, {
- id: 'hvcurveto',
- min: 4,
- resetStack: true
- }];
- var CharstringValidationData12 = [null, null, null, {
- id: 'and',
- min: 2,
- stackDelta: -1
- }, {
- id: 'or',
- min: 2,
- stackDelta: -1
- }, {
- id: 'not',
- min: 1,
- stackDelta: 0
- }, null, null, null, {
- id: 'abs',
- min: 1,
- stackDelta: 0
- }, {
- id: 'add',
- min: 2,
- stackDelta: -1,
- stackFn: function stack_div(stack, index) {
- stack[index - 2] = stack[index - 2] + stack[index - 1];
- }
- }, {
- id: 'sub',
- min: 2,
- stackDelta: -1,
- stackFn: function stack_div(stack, index) {
- stack[index - 2] = stack[index - 2] - stack[index - 1];
- }
- }, {
- id: 'div',
- min: 2,
- stackDelta: -1,
- stackFn: function stack_div(stack, index) {
- stack[index - 2] = stack[index - 2] / stack[index - 1];
- }
- }, null, {
- id: 'neg',
- min: 1,
- stackDelta: 0,
- stackFn: function stack_div(stack, index) {
- stack[index - 1] = -stack[index - 1];
- }
- }, {
- id: 'eq',
- min: 2,
- stackDelta: -1
- }, null, null, {
- id: 'drop',
- min: 1,
- stackDelta: -1
- }, null, {
- id: 'put',
- min: 2,
- stackDelta: -2
- }, {
- id: 'get',
- min: 1,
- stackDelta: 0
- }, {
- id: 'ifelse',
- min: 4,
- stackDelta: -3
- }, {
- id: 'random',
- min: 0,
- stackDelta: 1
- }, {
- id: 'mul',
- min: 2,
- stackDelta: -1,
- stackFn: function stack_div(stack, index) {
- stack[index - 2] = stack[index - 2] * stack[index - 1];
- }
- }, null, {
- id: 'sqrt',
- min: 1,
- stackDelta: 0
- }, {
- id: 'dup',
- min: 1,
- stackDelta: 1
- }, {
- id: 'exch',
- min: 2,
- stackDelta: 0
- }, {
- id: 'index',
- min: 2,
- stackDelta: 0
- }, {
- id: 'roll',
- min: 3,
- stackDelta: -2
- }, null, null, null, {
- id: 'hflex',
- min: 7,
- resetStack: true
- }, {
- id: 'flex',
- min: 13,
- resetStack: true
- }, {
- id: 'hflex1',
- min: 9,
- resetStack: true
- }, {
- id: 'flex1',
- min: 11,
- resetStack: true
- }];
- function CFFParser(file, properties, seacAnalysisEnabled) {
- this.bytes = file.getBytes();
- this.properties = properties;
- this.seacAnalysisEnabled = !!seacAnalysisEnabled;
- }
- CFFParser.prototype = {
- parse: function CFFParser_parse() {
- var properties = this.properties;
- var cff = new CFF();
- this.cff = cff;
- var header = this.parseHeader();
- var nameIndex = this.parseIndex(header.endPos);
- var topDictIndex = this.parseIndex(nameIndex.endPos);
- var stringIndex = this.parseIndex(topDictIndex.endPos);
- var globalSubrIndex = this.parseIndex(stringIndex.endPos);
- var topDictParsed = this.parseDict(topDictIndex.obj.get(0));
- var topDict = this.createDict(CFFTopDict, topDictParsed, cff.strings);
- cff.header = header.obj;
- cff.names = this.parseNameIndex(nameIndex.obj);
- cff.strings = this.parseStringIndex(stringIndex.obj);
- cff.topDict = topDict;
- cff.globalSubrIndex = globalSubrIndex.obj;
- this.parsePrivateDict(cff.topDict);
- cff.isCIDFont = topDict.hasName('ROS');
- var charStringOffset = topDict.getByName('CharStrings');
- var charStringIndex = this.parseIndex(charStringOffset).obj;
- var fontMatrix = topDict.getByName('FontMatrix');
- if (fontMatrix) {
- properties.fontMatrix = fontMatrix;
- }
- var fontBBox = topDict.getByName('FontBBox');
- if (fontBBox) {
- properties.ascent = Math.max(fontBBox[3], fontBBox[1]);
- properties.descent = Math.min(fontBBox[1], fontBBox[3]);
- properties.ascentScaled = true;
- }
- var charset, encoding;
- if (cff.isCIDFont) {
- var fdArrayIndex = this.parseIndex(topDict.getByName('FDArray')).obj;
- for (var i = 0, ii = fdArrayIndex.count; i < ii; ++i) {
- var dictRaw = fdArrayIndex.get(i);
- var fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw), cff.strings);
- this.parsePrivateDict(fontDict);
- cff.fdArray.push(fontDict);
- }
- encoding = null;
- charset = this.parseCharsets(topDict.getByName('charset'), charStringIndex.count, cff.strings, true);
- cff.fdSelect = this.parseFDSelect(topDict.getByName('FDSelect'), charStringIndex.count);
- } else {
- charset = this.parseCharsets(topDict.getByName('charset'), charStringIndex.count, cff.strings, false);
- encoding = this.parseEncoding(topDict.getByName('Encoding'), properties, cff.strings, charset.charset);
- }
- cff.charset = charset;
- cff.encoding = encoding;
- var charStringsAndSeacs = this.parseCharStrings({
- charStrings: charStringIndex,
- localSubrIndex: topDict.privateDict.subrsIndex,
- globalSubrIndex: globalSubrIndex.obj,
- fdSelect: cff.fdSelect,
- fdArray: cff.fdArray,
- privateDict: topDict.privateDict
- });
- cff.charStrings = charStringsAndSeacs.charStrings;
- cff.seacs = charStringsAndSeacs.seacs;
- cff.widths = charStringsAndSeacs.widths;
- return cff;
- },
- parseHeader: function CFFParser_parseHeader() {
- var bytes = this.bytes;
- var bytesLength = bytes.length;
- var offset = 0;
- while (offset < bytesLength && bytes[offset] !== 1) {
- ++offset;
- }
- if (offset >= bytesLength) {
- throw new _util.FormatError('Invalid CFF header');
- }
- if (offset !== 0) {
- (0, _util.info)('cff data is shifted');
- bytes = bytes.subarray(offset);
- this.bytes = bytes;
- }
- var major = bytes[0];
- var minor = bytes[1];
- var hdrSize = bytes[2];
- var offSize = bytes[3];
- var header = new CFFHeader(major, minor, hdrSize, offSize);
- return {
- obj: header,
- endPos: hdrSize
- };
- },
- parseDict: function CFFParser_parseDict(dict) {
- var pos = 0;
- function parseOperand() {
- var value = dict[pos++];
- if (value === 30) {
- return parseFloatOperand();
- } else if (value === 28) {
- value = dict[pos++];
- value = (value << 24 | dict[pos++] << 16) >> 16;
- return value;
- } else if (value === 29) {
- value = dict[pos++];
- value = value << 8 | dict[pos++];
- value = value << 8 | dict[pos++];
- value = value << 8 | dict[pos++];
- return value;
- } else if (value >= 32 && value <= 246) {
- return value - 139;
- } else if (value >= 247 && value <= 250) {
- return (value - 247) * 256 + dict[pos++] + 108;
- } else if (value >= 251 && value <= 254) {
- return -((value - 251) * 256) - dict[pos++] - 108;
- }
- (0, _util.warn)('CFFParser_parseDict: "' + value + '" is a reserved command.');
- return NaN;
- }
- function parseFloatOperand() {
- var str = '';
- var eof = 15;
- var lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'E', 'E-', null, '-'];
- var length = dict.length;
- while (pos < length) {
- var b = dict[pos++];
- var b1 = b >> 4;
- var b2 = b & 15;
- if (b1 === eof) {
- break;
- }
- str += lookup[b1];
- if (b2 === eof) {
- break;
- }
- str += lookup[b2];
- }
- return parseFloat(str);
- }
- var operands = [];
- var entries = [];
- pos = 0;
- var end = dict.length;
- while (pos < end) {
- var b = dict[pos];
- if (b <= 21) {
- if (b === 12) {
- b = b << 8 | dict[++pos];
- }
- entries.push([b, operands]);
- operands = [];
- ++pos;
- } else {
- operands.push(parseOperand());
- }
- }
- return entries;
- },
- parseIndex: function CFFParser_parseIndex(pos) {
- var cffIndex = new CFFIndex();
- var bytes = this.bytes;
- var count = bytes[pos++] << 8 | bytes[pos++];
- var offsets = [];
- var end = pos;
- var i, ii;
- if (count !== 0) {
- var offsetSize = bytes[pos++];
- var startPos = pos + (count + 1) * offsetSize - 1;
- for (i = 0, ii = count + 1; i < ii; ++i) {
- var offset = 0;
- for (var j = 0; j < offsetSize; ++j) {
- offset <<= 8;
- offset += bytes[pos++];
- }
- offsets.push(startPos + offset);
- }
- end = offsets[count];
- }
- for (i = 0, ii = offsets.length - 1; i < ii; ++i) {
- var offsetStart = offsets[i];
- var offsetEnd = offsets[i + 1];
- cffIndex.add(bytes.subarray(offsetStart, offsetEnd));
- }
- return {
- obj: cffIndex,
- endPos: end
- };
- },
- parseNameIndex: function CFFParser_parseNameIndex(index) {
- var names = [];
- for (var i = 0, ii = index.count; i < ii; ++i) {
- var name = index.get(i);
- names.push((0, _util.bytesToString)(name));
- }
- return names;
- },
- parseStringIndex: function CFFParser_parseStringIndex(index) {
- var strings = new CFFStrings();
- for (var i = 0, ii = index.count; i < ii; ++i) {
- var data = index.get(i);
- strings.add((0, _util.bytesToString)(data));
- }
- return strings;
- },
- createDict: function CFFParser_createDict(Type, dict, strings) {
- var cffDict = new Type(strings);
- for (var i = 0, ii = dict.length; i < ii; ++i) {
- var pair = dict[i];
- var key = pair[0];
- var value = pair[1];
- cffDict.setByKey(key, value);
- }
- return cffDict;
- },
- parseCharString: function CFFParser_parseCharString(state, data, localSubrIndex, globalSubrIndex) {
- if (!data || state.callDepth > MAX_SUBR_NESTING) {
- return false;
- }
- var stackSize = state.stackSize;
- var stack = state.stack;
- var length = data.length;
- for (var j = 0; j < length;) {
- var value = data[j++];
- var validationCommand = null;
- if (value === 12) {
- var q = data[j++];
- if (q === 0) {
- data[j - 2] = 139;
- data[j - 1] = 22;
- stackSize = 0;
- } else {
- validationCommand = CharstringValidationData12[q];
- }
- } else if (value === 28) {
- stack[stackSize] = (data[j] << 24 | data[j + 1] << 16) >> 16;
- j += 2;
- stackSize++;
- } else if (value === 14) {
- if (stackSize >= 4) {
- stackSize -= 4;
- if (this.seacAnalysisEnabled) {
- state.seac = stack.slice(stackSize, stackSize + 4);
- return false;
- }
- }
- validationCommand = CharstringValidationData[value];
- } else if (value >= 32 && value <= 246) {
- stack[stackSize] = value - 139;
- stackSize++;
- } else if (value >= 247 && value <= 254) {
- stack[stackSize] = value < 251 ? (value - 247 << 8) + data[j] + 108 : -(value - 251 << 8) - data[j] - 108;
- j++;
- stackSize++;
- } else if (value === 255) {
- stack[stackSize] = (data[j] << 24 | data[j + 1] << 16 | data[j + 2] << 8 | data[j + 3]) / 65536;
- j += 4;
- stackSize++;
- } else if (value === 19 || value === 20) {
- state.hints += stackSize >> 1;
- j += state.hints + 7 >> 3;
- stackSize %= 2;
- validationCommand = CharstringValidationData[value];
- } else if (value === 10 || value === 29) {
- var subrsIndex;
- if (value === 10) {
- subrsIndex = localSubrIndex;
- } else {
- subrsIndex = globalSubrIndex;
- }
- if (!subrsIndex) {
- validationCommand = CharstringValidationData[value];
- (0, _util.warn)('Missing subrsIndex for ' + validationCommand.id);
- return false;
- }
- var bias = 32768;
- if (subrsIndex.count < 1240) {
- bias = 107;
- } else if (subrsIndex.count < 33900) {
- bias = 1131;
- }
- var subrNumber = stack[--stackSize] + bias;
- if (subrNumber < 0 || subrNumber >= subrsIndex.count || isNaN(subrNumber)) {
- validationCommand = CharstringValidationData[value];
- (0, _util.warn)('Out of bounds subrIndex for ' + validationCommand.id);
- return false;
- }
- state.stackSize = stackSize;
- state.callDepth++;
- var valid = this.parseCharString(state, subrsIndex.get(subrNumber), localSubrIndex, globalSubrIndex);
- if (!valid) {
- return false;
- }
- state.callDepth--;
- stackSize = state.stackSize;
- continue;
- } else if (value === 11) {
- state.stackSize = stackSize;
- return true;
- } else {
- validationCommand = CharstringValidationData[value];
- }
- if (validationCommand) {
- if (validationCommand.stem) {
- state.hints += stackSize >> 1;
- }
- if ('min' in validationCommand) {
- if (!state.undefStack && stackSize < validationCommand.min) {
- (0, _util.warn)('Not enough parameters for ' + validationCommand.id + '; actual: ' + stackSize + ', expected: ' + validationCommand.min);
- return false;
- }
- }
- if (state.firstStackClearing && validationCommand.stackClearing) {
- state.firstStackClearing = false;
- stackSize -= validationCommand.min;
- if (stackSize >= 2 && validationCommand.stem) {
- stackSize %= 2;
- } else if (stackSize > 1) {
- (0, _util.warn)('Found too many parameters for stack-clearing command');
- }
- if (stackSize > 0 && stack[stackSize - 1] >= 0) {
- state.width = stack[stackSize - 1];
- }
- }
- if ('stackDelta' in validationCommand) {
- if ('stackFn' in validationCommand) {
- validationCommand.stackFn(stack, stackSize);
- }
- stackSize += validationCommand.stackDelta;
- } else if (validationCommand.stackClearing) {
- stackSize = 0;
- } else if (validationCommand.resetStack) {
- stackSize = 0;
- state.undefStack = false;
- } else if (validationCommand.undefStack) {
- stackSize = 0;
- state.undefStack = true;
- state.firstStackClearing = false;
- }
- }
- }
- state.stackSize = stackSize;
- return true;
- },
- parseCharStrings: function parseCharStrings(_ref) {
- var charStrings = _ref.charStrings,
- localSubrIndex = _ref.localSubrIndex,
- globalSubrIndex = _ref.globalSubrIndex,
- fdSelect = _ref.fdSelect,
- fdArray = _ref.fdArray,
- privateDict = _ref.privateDict;
-
- var seacs = [];
- var widths = [];
- var count = charStrings.count;
- for (var i = 0; i < count; i++) {
- var charstring = charStrings.get(i);
- var state = {
- callDepth: 0,
- stackSize: 0,
- stack: [],
- undefStack: true,
- hints: 0,
- firstStackClearing: true,
- seac: null,
- width: null
- };
- var valid = true;
- var localSubrToUse = null;
- var privateDictToUse = privateDict;
- if (fdSelect && fdArray.length) {
- var fdIndex = fdSelect.getFDIndex(i);
- if (fdIndex === -1) {
- (0, _util.warn)('Glyph index is not in fd select.');
- valid = false;
- }
- if (fdIndex >= fdArray.length) {
- (0, _util.warn)('Invalid fd index for glyph index.');
- valid = false;
- }
- if (valid) {
- privateDictToUse = fdArray[fdIndex].privateDict;
- localSubrToUse = privateDictToUse.subrsIndex;
- }
- } else if (localSubrIndex) {
- localSubrToUse = localSubrIndex;
- }
- if (valid) {
- valid = this.parseCharString(state, charstring, localSubrToUse, globalSubrIndex);
- }
- if (state.width !== null) {
- var nominalWidth = privateDictToUse.getByName('nominalWidthX');
- widths[i] = nominalWidth + state.width;
- } else {
- var defaultWidth = privateDictToUse.getByName('defaultWidthX');
- widths[i] = defaultWidth;
- }
- if (state.seac !== null) {
- seacs[i] = state.seac;
- }
- if (!valid) {
- charStrings.set(i, new Uint8Array([14]));
- }
- }
- return {
- charStrings: charStrings,
- seacs: seacs,
- widths: widths
- };
- },
-
- emptyPrivateDictionary: function CFFParser_emptyPrivateDictionary(parentDict) {
- var privateDict = this.createDict(CFFPrivateDict, [], parentDict.strings);
- parentDict.setByKey(18, [0, 0]);
- parentDict.privateDict = privateDict;
- },
- parsePrivateDict: function CFFParser_parsePrivateDict(parentDict) {
- if (!parentDict.hasName('Private')) {
- this.emptyPrivateDictionary(parentDict);
- return;
- }
- var privateOffset = parentDict.getByName('Private');
- if (!Array.isArray(privateOffset) || privateOffset.length !== 2) {
- parentDict.removeByName('Private');
- return;
- }
- var size = privateOffset[0];
- var offset = privateOffset[1];
- if (size === 0 || offset >= this.bytes.length) {
- this.emptyPrivateDictionary(parentDict);
- return;
- }
- var privateDictEnd = offset + size;
- var dictData = this.bytes.subarray(offset, privateDictEnd);
- var dict = this.parseDict(dictData);
- var privateDict = this.createDict(CFFPrivateDict, dict, parentDict.strings);
- parentDict.privateDict = privateDict;
- if (!privateDict.getByName('Subrs')) {
- return;
- }
- var subrsOffset = privateDict.getByName('Subrs');
- var relativeOffset = offset + subrsOffset;
- if (subrsOffset === 0 || relativeOffset >= this.bytes.length) {
- this.emptyPrivateDictionary(parentDict);
- return;
- }
- var subrsIndex = this.parseIndex(relativeOffset);
- privateDict.subrsIndex = subrsIndex.obj;
- },
- parseCharsets: function CFFParser_parseCharsets(pos, length, strings, cid) {
- if (pos === 0) {
- return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE, _charsets.ISOAdobeCharset);
- } else if (pos === 1) {
- return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT, _charsets.ExpertCharset);
- } else if (pos === 2) {
- return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET, _charsets.ExpertSubsetCharset);
- }
- var bytes = this.bytes;
- var start = pos;
- var format = bytes[pos++];
- var charset = ['.notdef'];
- var id, count, i;
- length -= 1;
- switch (format) {
- case 0:
- for (i = 0; i < length; i++) {
- id = bytes[pos++] << 8 | bytes[pos++];
- charset.push(cid ? id : strings.get(id));
- }
- break;
- case 1:
- while (charset.length <= length) {
- id = bytes[pos++] << 8 | bytes[pos++];
- count = bytes[pos++];
- for (i = 0; i <= count; i++) {
- charset.push(cid ? id++ : strings.get(id++));
- }
- }
- break;
- case 2:
- while (charset.length <= length) {
- id = bytes[pos++] << 8 | bytes[pos++];
- count = bytes[pos++] << 8 | bytes[pos++];
- for (i = 0; i <= count; i++) {
- charset.push(cid ? id++ : strings.get(id++));
- }
- }
- break;
- default:
- throw new _util.FormatError('Unknown charset format');
- }
- var end = pos;
- var raw = bytes.subarray(start, end);
- return new CFFCharset(false, format, charset, raw);
- },
- parseEncoding: function CFFParser_parseEncoding(pos, properties, strings, charset) {
- var encoding = Object.create(null);
- var bytes = this.bytes;
- var predefined = false;
- var format, i, ii;
- var raw = null;
- function readSupplement() {
- var supplementsCount = bytes[pos++];
- for (i = 0; i < supplementsCount; i++) {
- var code = bytes[pos++];
- var sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff);
- encoding[code] = charset.indexOf(strings.get(sid));
- }
- }
- if (pos === 0 || pos === 1) {
- predefined = true;
- format = pos;
- var baseEncoding = pos ? _encodings.ExpertEncoding : _encodings.StandardEncoding;
- for (i = 0, ii = charset.length; i < ii; i++) {
- var index = baseEncoding.indexOf(charset[i]);
- if (index !== -1) {
- encoding[index] = i;
- }
- }
- } else {
- var dataStart = pos;
- format = bytes[pos++];
- switch (format & 0x7f) {
- case 0:
- var glyphsCount = bytes[pos++];
- for (i = 1; i <= glyphsCount; i++) {
- encoding[bytes[pos++]] = i;
- }
- break;
- case 1:
- var rangesCount = bytes[pos++];
- var gid = 1;
- for (i = 0; i < rangesCount; i++) {
- var start = bytes[pos++];
- var left = bytes[pos++];
- for (var j = start; j <= start + left; j++) {
- encoding[j] = gid++;
- }
- }
- break;
- default:
- throw new _util.FormatError('Unknown encoding format: ' + format + ' in CFF');
- }
- var dataEnd = pos;
- if (format & 0x80) {
- bytes[dataStart] &= 0x7f;
- readSupplement();
- }
- raw = bytes.subarray(dataStart, dataEnd);
- }
- format = format & 0x7f;
- return new CFFEncoding(predefined, format, encoding, raw);
- },
- parseFDSelect: function CFFParser_parseFDSelect(pos, length) {
- var bytes = this.bytes;
- var format = bytes[pos++];
- var fdSelect = [];
- var i;
- switch (format) {
- case 0:
- for (i = 0; i < length; ++i) {
- var id = bytes[pos++];
- fdSelect.push(id);
- }
- break;
- case 3:
- var rangesCount = bytes[pos++] << 8 | bytes[pos++];
- for (i = 0; i < rangesCount; ++i) {
- var first = bytes[pos++] << 8 | bytes[pos++];
- if (i === 0 && first !== 0) {
- (0, _util.warn)('parseFDSelect: The first range must have a first GID of 0' + ' -- trying to recover.');
- first = 0;
- }
- var fdIndex = bytes[pos++];
- var next = bytes[pos] << 8 | bytes[pos + 1];
- for (var j = first; j < next; ++j) {
- fdSelect.push(fdIndex);
- }
- }
- pos += 2;
- break;
- default:
- throw new _util.FormatError('parseFDSelect: Unknown format "' + format + '".');
- }
- if (fdSelect.length !== length) {
- throw new _util.FormatError('parseFDSelect: Invalid font data.');
- }
- return new CFFFDSelect(format, fdSelect);
- }
- };
- return CFFParser;
-}();
-var CFF = function CFFClosure() {
- function CFF() {
- this.header = null;
- this.names = [];
- this.topDict = null;
- this.strings = new CFFStrings();
- this.globalSubrIndex = null;
- this.encoding = null;
- this.charset = null;
- this.charStrings = null;
- this.fdArray = [];
- this.fdSelect = null;
- this.isCIDFont = false;
- }
- CFF.prototype = {
- duplicateFirstGlyph: function CFF_duplicateFirstGlyph() {
- if (this.charStrings.count >= 65535) {
- (0, _util.warn)('Not enough space in charstrings to duplicate first glyph.');
- return;
- }
- var glyphZero = this.charStrings.get(0);
- this.charStrings.add(glyphZero);
- if (this.isCIDFont) {
- this.fdSelect.fdSelect.push(this.fdSelect.fdSelect[0]);
- }
- },
- hasGlyphId: function CFF_hasGlyphID(id) {
- if (id < 0 || id >= this.charStrings.count) {
- return false;
- }
- var glyph = this.charStrings.get(id);
- return glyph.length > 0;
- }
- };
- return CFF;
-}();
-var CFFHeader = function CFFHeaderClosure() {
- function CFFHeader(major, minor, hdrSize, offSize) {
- this.major = major;
- this.minor = minor;
- this.hdrSize = hdrSize;
- this.offSize = offSize;
- }
- return CFFHeader;
-}();
-var CFFStrings = function CFFStringsClosure() {
- function CFFStrings() {
- this.strings = [];
- }
- CFFStrings.prototype = {
- get: function CFFStrings_get(index) {
- if (index >= 0 && index <= 390) {
- return CFFStandardStrings[index];
- }
- if (index - 391 <= this.strings.length) {
- return this.strings[index - 391];
- }
- return CFFStandardStrings[0];
- },
- add: function CFFStrings_add(value) {
- this.strings.push(value);
- },
- get count() {
- return this.strings.length;
- }
- };
- return CFFStrings;
-}();
-var CFFIndex = function CFFIndexClosure() {
- function CFFIndex() {
- this.objects = [];
- this.length = 0;
- }
- CFFIndex.prototype = {
- add: function CFFIndex_add(data) {
- this.length += data.length;
- this.objects.push(data);
- },
- set: function CFFIndex_set(index, data) {
- this.length += data.length - this.objects[index].length;
- this.objects[index] = data;
- },
- get: function CFFIndex_get(index) {
- return this.objects[index];
- },
- get count() {
- return this.objects.length;
- }
- };
- return CFFIndex;
-}();
-var CFFDict = function CFFDictClosure() {
- function CFFDict(tables, strings) {
- this.keyToNameMap = tables.keyToNameMap;
- this.nameToKeyMap = tables.nameToKeyMap;
- this.defaults = tables.defaults;
- this.types = tables.types;
- this.opcodes = tables.opcodes;
- this.order = tables.order;
- this.strings = strings;
- this.values = Object.create(null);
- }
- CFFDict.prototype = {
- setByKey: function CFFDict_setByKey(key, value) {
- if (!(key in this.keyToNameMap)) {
- return false;
- }
- var valueLength = value.length;
- if (valueLength === 0) {
- return true;
- }
- for (var i = 0; i < valueLength; i++) {
- if (isNaN(value[i])) {
- (0, _util.warn)('Invalid CFFDict value: "' + value + '" for key "' + key + '".');
- return true;
- }
- }
- var type = this.types[key];
- if (type === 'num' || type === 'sid' || type === 'offset') {
- value = value[0];
- }
- this.values[key] = value;
- return true;
- },
- setByName: function CFFDict_setByName(name, value) {
- if (!(name in this.nameToKeyMap)) {
- throw new _util.FormatError('Invalid dictionary name "' + name + '"');
- }
- this.values[this.nameToKeyMap[name]] = value;
- },
- hasName: function CFFDict_hasName(name) {
- return this.nameToKeyMap[name] in this.values;
- },
- getByName: function CFFDict_getByName(name) {
- if (!(name in this.nameToKeyMap)) {
- throw new _util.FormatError('Invalid dictionary name ' + name + '"');
- }
- var key = this.nameToKeyMap[name];
- if (!(key in this.values)) {
- return this.defaults[key];
- }
- return this.values[key];
- },
- removeByName: function CFFDict_removeByName(name) {
- delete this.values[this.nameToKeyMap[name]];
- }
- };
- CFFDict.createTables = function CFFDict_createTables(layout) {
- var tables = {
- keyToNameMap: {},
- nameToKeyMap: {},
- defaults: {},
- types: {},
- opcodes: {},
- order: []
- };
- for (var i = 0, ii = layout.length; i < ii; ++i) {
- var entry = layout[i];
- var key = Array.isArray(entry[0]) ? (entry[0][0] << 8) + entry[0][1] : entry[0];
- tables.keyToNameMap[key] = entry[1];
- tables.nameToKeyMap[entry[1]] = key;
- tables.types[key] = entry[2];
- tables.defaults[key] = entry[3];
- tables.opcodes[key] = Array.isArray(entry[0]) ? entry[0] : [entry[0]];
- tables.order.push(key);
- }
- return tables;
- };
- return CFFDict;
-}();
-var CFFTopDict = function CFFTopDictClosure() {
- var layout = [[[12, 30], 'ROS', ['sid', 'sid', 'num'], null], [[12, 20], 'SyntheticBase', 'num', null], [0, 'version', 'sid', null], [1, 'Notice', 'sid', null], [[12, 0], 'Copyright', 'sid', null], [2, 'FullName', 'sid', null], [3, 'FamilyName', 'sid', null], [4, 'Weight', 'sid', null], [[12, 1], 'isFixedPitch', 'num', 0], [[12, 2], 'ItalicAngle', 'num', 0], [[12, 3], 'UnderlinePosition', 'num', -100], [[12, 4], 'UnderlineThickness', 'num', 50], [[12, 5], 'PaintType', 'num', 0], [[12, 6], 'CharstringType', 'num', 2], [[12, 7], 'FontMatrix', ['num', 'num', 'num', 'num', 'num', 'num'], [0.001, 0, 0, 0.001, 0, 0]], [13, 'UniqueID', 'num', null], [5, 'FontBBox', ['num', 'num', 'num', 'num'], [0, 0, 0, 0]], [[12, 8], 'StrokeWidth', 'num', 0], [14, 'XUID', 'array', null], [15, 'charset', 'offset', 0], [16, 'Encoding', 'offset', 0], [17, 'CharStrings', 'offset', 0], [18, 'Private', ['offset', 'offset'], null], [[12, 21], 'PostScript', 'sid', null], [[12, 22], 'BaseFontName', 'sid', null], [[12, 23], 'BaseFontBlend', 'delta', null], [[12, 31], 'CIDFontVersion', 'num', 0], [[12, 32], 'CIDFontRevision', 'num', 0], [[12, 33], 'CIDFontType', 'num', 0], [[12, 34], 'CIDCount', 'num', 8720], [[12, 35], 'UIDBase', 'num', null], [[12, 37], 'FDSelect', 'offset', null], [[12, 36], 'FDArray', 'offset', null], [[12, 38], 'FontName', 'sid', null]];
- var tables = null;
- function CFFTopDict(strings) {
- if (tables === null) {
- tables = CFFDict.createTables(layout);
- }
- CFFDict.call(this, tables, strings);
- this.privateDict = null;
- }
- CFFTopDict.prototype = Object.create(CFFDict.prototype);
- return CFFTopDict;
-}();
-var CFFPrivateDict = function CFFPrivateDictClosure() {
- var layout = [[6, 'BlueValues', 'delta', null], [7, 'OtherBlues', 'delta', null], [8, 'FamilyBlues', 'delta', null], [9, 'FamilyOtherBlues', 'delta', null], [[12, 9], 'BlueScale', 'num', 0.039625], [[12, 10], 'BlueShift', 'num', 7], [[12, 11], 'BlueFuzz', 'num', 1], [10, 'StdHW', 'num', null], [11, 'StdVW', 'num', null], [[12, 12], 'StemSnapH', 'delta', null], [[12, 13], 'StemSnapV', 'delta', null], [[12, 14], 'ForceBold', 'num', 0], [[12, 17], 'LanguageGroup', 'num', 0], [[12, 18], 'ExpansionFactor', 'num', 0.06], [[12, 19], 'initialRandomSeed', 'num', 0], [20, 'defaultWidthX', 'num', 0], [21, 'nominalWidthX', 'num', 0], [19, 'Subrs', 'offset', null]];
- var tables = null;
- function CFFPrivateDict(strings) {
- if (tables === null) {
- tables = CFFDict.createTables(layout);
- }
- CFFDict.call(this, tables, strings);
- this.subrsIndex = null;
- }
- CFFPrivateDict.prototype = Object.create(CFFDict.prototype);
- return CFFPrivateDict;
-}();
-var CFFCharsetPredefinedTypes = {
- ISO_ADOBE: 0,
- EXPERT: 1,
- EXPERT_SUBSET: 2
-};
-var CFFCharset = function CFFCharsetClosure() {
- function CFFCharset(predefined, format, charset, raw) {
- this.predefined = predefined;
- this.format = format;
- this.charset = charset;
- this.raw = raw;
- }
- return CFFCharset;
-}();
-var CFFEncoding = function CFFEncodingClosure() {
- function CFFEncoding(predefined, format, encoding, raw) {
- this.predefined = predefined;
- this.format = format;
- this.encoding = encoding;
- this.raw = raw;
- }
- return CFFEncoding;
-}();
-var CFFFDSelect = function CFFFDSelectClosure() {
- function CFFFDSelect(format, fdSelect) {
- this.format = format;
- this.fdSelect = fdSelect;
- }
- CFFFDSelect.prototype = {
- getFDIndex: function CFFFDSelect_get(glyphIndex) {
- if (glyphIndex < 0 || glyphIndex >= this.fdSelect.length) {
- return -1;
- }
- return this.fdSelect[glyphIndex];
- }
- };
- return CFFFDSelect;
-}();
-var CFFOffsetTracker = function CFFOffsetTrackerClosure() {
- function CFFOffsetTracker() {
- this.offsets = Object.create(null);
- }
- CFFOffsetTracker.prototype = {
- isTracking: function CFFOffsetTracker_isTracking(key) {
- return key in this.offsets;
- },
- track: function CFFOffsetTracker_track(key, location) {
- if (key in this.offsets) {
- throw new _util.FormatError('Already tracking location of ' + key);
- }
- this.offsets[key] = location;
- },
- offset: function CFFOffsetTracker_offset(value) {
- for (var key in this.offsets) {
- this.offsets[key] += value;
- }
- },
- setEntryLocation: function CFFOffsetTracker_setEntryLocation(key, values, output) {
- if (!(key in this.offsets)) {
- throw new _util.FormatError('Not tracking location of ' + key);
- }
- var data = output.data;
- var dataOffset = this.offsets[key];
- var size = 5;
- for (var i = 0, ii = values.length; i < ii; ++i) {
- var offset0 = i * size + dataOffset;
- var offset1 = offset0 + 1;
- var offset2 = offset0 + 2;
- var offset3 = offset0 + 3;
- var offset4 = offset0 + 4;
- if (data[offset0] !== 0x1d || data[offset1] !== 0 || data[offset2] !== 0 || data[offset3] !== 0 || data[offset4] !== 0) {
- throw new _util.FormatError('writing to an offset that is not empty');
- }
- var value = values[i];
- data[offset0] = 0x1d;
- data[offset1] = value >> 24 & 0xFF;
- data[offset2] = value >> 16 & 0xFF;
- data[offset3] = value >> 8 & 0xFF;
- data[offset4] = value & 0xFF;
- }
- }
- };
- return CFFOffsetTracker;
-}();
-var CFFCompiler = function CFFCompilerClosure() {
- function CFFCompiler(cff) {
- this.cff = cff;
- }
- CFFCompiler.prototype = {
- compile: function CFFCompiler_compile() {
- var cff = this.cff;
- var output = {
- data: [],
- length: 0,
- add: function CFFCompiler_add(data) {
- this.data = this.data.concat(data);
- this.length = this.data.length;
- }
- };
- var header = this.compileHeader(cff.header);
- output.add(header);
- var nameIndex = this.compileNameIndex(cff.names);
- output.add(nameIndex);
- if (cff.isCIDFont) {
- if (cff.topDict.hasName('FontMatrix')) {
- var base = cff.topDict.getByName('FontMatrix');
- cff.topDict.removeByName('FontMatrix');
- for (var i = 0, ii = cff.fdArray.length; i < ii; i++) {
- var subDict = cff.fdArray[i];
- var matrix = base.slice(0);
- if (subDict.hasName('FontMatrix')) {
- matrix = _util.Util.transform(matrix, subDict.getByName('FontMatrix'));
- }
- subDict.setByName('FontMatrix', matrix);
- }
- }
- }
- cff.topDict.setByName('charset', 0);
- var compiled = this.compileTopDicts([cff.topDict], output.length, cff.isCIDFont);
- output.add(compiled.output);
- var topDictTracker = compiled.trackers[0];
- var stringIndex = this.compileStringIndex(cff.strings.strings);
- output.add(stringIndex);
- var globalSubrIndex = this.compileIndex(cff.globalSubrIndex);
- output.add(globalSubrIndex);
- if (cff.encoding && cff.topDict.hasName('Encoding')) {
- if (cff.encoding.predefined) {
- topDictTracker.setEntryLocation('Encoding', [cff.encoding.format], output);
- } else {
- var encoding = this.compileEncoding(cff.encoding);
- topDictTracker.setEntryLocation('Encoding', [output.length], output);
- output.add(encoding);
- }
- }
- var charset = this.compileCharset(cff.charset);
- topDictTracker.setEntryLocation('charset', [output.length], output);
- output.add(charset);
- var charStrings = this.compileCharStrings(cff.charStrings);
- topDictTracker.setEntryLocation('CharStrings', [output.length], output);
- output.add(charStrings);
- if (cff.isCIDFont) {
- topDictTracker.setEntryLocation('FDSelect', [output.length], output);
- var fdSelect = this.compileFDSelect(cff.fdSelect);
- output.add(fdSelect);
- compiled = this.compileTopDicts(cff.fdArray, output.length, true);
- topDictTracker.setEntryLocation('FDArray', [output.length], output);
- output.add(compiled.output);
- var fontDictTrackers = compiled.trackers;
- this.compilePrivateDicts(cff.fdArray, fontDictTrackers, output);
- }
- this.compilePrivateDicts([cff.topDict], [topDictTracker], output);
- output.add([0]);
- return output.data;
- },
- encodeNumber: function CFFCompiler_encodeNumber(value) {
- if (parseFloat(value) === parseInt(value, 10) && !isNaN(value)) {
- return this.encodeInteger(value);
- }
- return this.encodeFloat(value);
- },
- encodeFloat: function CFFCompiler_encodeFloat(num) {
- var value = num.toString();
- var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value);
- if (m) {
- var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length));
- value = (Math.round(num * epsilon) / epsilon).toString();
- }
- var nibbles = '';
- var i, ii;
- for (i = 0, ii = value.length; i < ii; ++i) {
- var a = value[i];
- if (a === 'e') {
- nibbles += value[++i] === '-' ? 'c' : 'b';
- } else if (a === '.') {
- nibbles += 'a';
- } else if (a === '-') {
- nibbles += 'e';
- } else {
- nibbles += a;
- }
- }
- nibbles += nibbles.length & 1 ? 'f' : 'ff';
- var out = [30];
- for (i = 0, ii = nibbles.length; i < ii; i += 2) {
- out.push(parseInt(nibbles.substring(i, i + 2), 16));
- }
- return out;
- },
- encodeInteger: function CFFCompiler_encodeInteger(value) {
- var code;
- if (value >= -107 && value <= 107) {
- code = [value + 139];
- } else if (value >= 108 && value <= 1131) {
- value = value - 108;
- code = [(value >> 8) + 247, value & 0xFF];
- } else if (value >= -1131 && value <= -108) {
- value = -value - 108;
- code = [(value >> 8) + 251, value & 0xFF];
- } else if (value >= -32768 && value <= 32767) {
- code = [0x1c, value >> 8 & 0xFF, value & 0xFF];
- } else {
- code = [0x1d, value >> 24 & 0xFF, value >> 16 & 0xFF, value >> 8 & 0xFF, value & 0xFF];
- }
- return code;
- },
- compileHeader: function CFFCompiler_compileHeader(header) {
- return [header.major, header.minor, header.hdrSize, header.offSize];
- },
- compileNameIndex: function CFFCompiler_compileNameIndex(names) {
- var nameIndex = new CFFIndex();
- for (var i = 0, ii = names.length; i < ii; ++i) {
- var name = names[i];
- var length = Math.min(name.length, 127);
- var sanitizedName = new Array(length);
- for (var j = 0; j < length; j++) {
- var char = name[j];
- if (char < '!' || char > '~' || char === '[' || char === ']' || char === '(' || char === ')' || char === '{' || char === '}' || char === '<' || char === '>' || char === '/' || char === '%') {
- char = '_';
- }
- sanitizedName[j] = char;
- }
- sanitizedName = sanitizedName.join('');
- if (sanitizedName === '') {
- sanitizedName = 'Bad_Font_Name';
- }
- nameIndex.add((0, _util.stringToBytes)(sanitizedName));
- }
- return this.compileIndex(nameIndex);
- },
- compileTopDicts: function CFFCompiler_compileTopDicts(dicts, length, removeCidKeys) {
- var fontDictTrackers = [];
- var fdArrayIndex = new CFFIndex();
- for (var i = 0, ii = dicts.length; i < ii; ++i) {
- var fontDict = dicts[i];
- if (removeCidKeys) {
- fontDict.removeByName('CIDFontVersion');
- fontDict.removeByName('CIDFontRevision');
- fontDict.removeByName('CIDFontType');
- fontDict.removeByName('CIDCount');
- fontDict.removeByName('UIDBase');
- }
- var fontDictTracker = new CFFOffsetTracker();
- var fontDictData = this.compileDict(fontDict, fontDictTracker);
- fontDictTrackers.push(fontDictTracker);
- fdArrayIndex.add(fontDictData);
- fontDictTracker.offset(length);
- }
- fdArrayIndex = this.compileIndex(fdArrayIndex, fontDictTrackers);
- return {
- trackers: fontDictTrackers,
- output: fdArrayIndex
- };
- },
- compilePrivateDicts: function CFFCompiler_compilePrivateDicts(dicts, trackers, output) {
- for (var i = 0, ii = dicts.length; i < ii; ++i) {
- var fontDict = dicts[i];
- var privateDict = fontDict.privateDict;
- if (!privateDict || !fontDict.hasName('Private')) {
- throw new _util.FormatError('There must be a private dictionary.');
- }
- var privateDictTracker = new CFFOffsetTracker();
- var privateDictData = this.compileDict(privateDict, privateDictTracker);
- var outputLength = output.length;
- privateDictTracker.offset(outputLength);
- if (!privateDictData.length) {
- outputLength = 0;
- }
- trackers[i].setEntryLocation('Private', [privateDictData.length, outputLength], output);
- output.add(privateDictData);
- if (privateDict.subrsIndex && privateDict.hasName('Subrs')) {
- var subrs = this.compileIndex(privateDict.subrsIndex);
- privateDictTracker.setEntryLocation('Subrs', [privateDictData.length], output);
- output.add(subrs);
- }
- }
- },
- compileDict: function CFFCompiler_compileDict(dict, offsetTracker) {
- var out = [];
- var order = dict.order;
- for (var i = 0; i < order.length; ++i) {
- var key = order[i];
- if (!(key in dict.values)) {
- continue;
- }
- var values = dict.values[key];
- var types = dict.types[key];
- if (!Array.isArray(types)) {
- types = [types];
- }
- if (!Array.isArray(values)) {
- values = [values];
- }
- if (values.length === 0) {
- continue;
- }
- for (var j = 0, jj = types.length; j < jj; ++j) {
- var type = types[j];
- var value = values[j];
- switch (type) {
- case 'num':
- case 'sid':
- out = out.concat(this.encodeNumber(value));
- break;
- case 'offset':
- var name = dict.keyToNameMap[key];
- if (!offsetTracker.isTracking(name)) {
- offsetTracker.track(name, out.length);
- }
- out = out.concat([0x1d, 0, 0, 0, 0]);
- break;
- case 'array':
- case 'delta':
- out = out.concat(this.encodeNumber(value));
- for (var k = 1, kk = values.length; k < kk; ++k) {
- out = out.concat(this.encodeNumber(values[k]));
- }
- break;
- default:
- throw new _util.FormatError('Unknown data type of ' + type);
- }
- }
- out = out.concat(dict.opcodes[key]);
- }
- return out;
- },
- compileStringIndex: function CFFCompiler_compileStringIndex(strings) {
- var stringIndex = new CFFIndex();
- for (var i = 0, ii = strings.length; i < ii; ++i) {
- stringIndex.add((0, _util.stringToBytes)(strings[i]));
- }
- return this.compileIndex(stringIndex);
- },
- compileGlobalSubrIndex: function CFFCompiler_compileGlobalSubrIndex() {
- var globalSubrIndex = this.cff.globalSubrIndex;
- this.out.writeByteArray(this.compileIndex(globalSubrIndex));
- },
- compileCharStrings: function CFFCompiler_compileCharStrings(charStrings) {
- var charStringsIndex = new CFFIndex();
- for (var i = 0; i < charStrings.count; i++) {
- var glyph = charStrings.get(i);
- if (glyph.length === 0) {
- charStringsIndex.add(new Uint8Array([0x8B, 0x0E]));
- continue;
- }
- charStringsIndex.add(glyph);
- }
- return this.compileIndex(charStringsIndex);
- },
- compileCharset: function CFFCompiler_compileCharset(charset) {
- var length = 1 + (this.cff.charStrings.count - 1) * 2;
- var out = new Uint8Array(length);
- return this.compileTypedArray(out);
- },
- compileEncoding: function CFFCompiler_compileEncoding(encoding) {
- return this.compileTypedArray(encoding.raw);
- },
- compileFDSelect: function CFFCompiler_compileFDSelect(fdSelect) {
- var format = fdSelect.format;
- var out = void 0,
- i = void 0;
- switch (format) {
- case 0:
- out = new Uint8Array(1 + fdSelect.fdSelect.length);
- out[0] = format;
- for (i = 0; i < fdSelect.fdSelect.length; i++) {
- out[i + 1] = fdSelect.fdSelect[i];
- }
- break;
- case 3:
- var start = 0;
- var lastFD = fdSelect.fdSelect[0];
- var ranges = [format, 0, 0, start >> 8 & 0xFF, start & 0xFF, lastFD];
- for (i = 1; i < fdSelect.fdSelect.length; i++) {
- var currentFD = fdSelect.fdSelect[i];
- if (currentFD !== lastFD) {
- ranges.push(i >> 8 & 0xFF, i & 0xFF, currentFD);
- lastFD = currentFD;
- }
- }
- var numRanges = (ranges.length - 3) / 3;
- ranges[1] = numRanges >> 8 & 0xFF;
- ranges[2] = numRanges & 0xFF;
- ranges.push(i >> 8 & 0xFF, i & 0xFF);
- out = new Uint8Array(ranges);
- break;
- }
- return this.compileTypedArray(out);
- },
- compileTypedArray: function CFFCompiler_compileTypedArray(data) {
- var out = [];
- for (var i = 0, ii = data.length; i < ii; ++i) {
- out[i] = data[i];
- }
- return out;
- },
- compileIndex: function CFFCompiler_compileIndex(index, trackers) {
- trackers = trackers || [];
- var objects = index.objects;
- var count = objects.length;
- if (count === 0) {
- return [0, 0, 0];
- }
- var data = [count >> 8 & 0xFF, count & 0xff];
- var lastOffset = 1,
- i;
- for (i = 0; i < count; ++i) {
- lastOffset += objects[i].length;
- }
- var offsetSize;
- if (lastOffset < 0x100) {
- offsetSize = 1;
- } else if (lastOffset < 0x10000) {
- offsetSize = 2;
- } else if (lastOffset < 0x1000000) {
- offsetSize = 3;
- } else {
- offsetSize = 4;
- }
- data.push(offsetSize);
- var relativeOffset = 1;
- for (i = 0; i < count + 1; i++) {
- if (offsetSize === 1) {
- data.push(relativeOffset & 0xFF);
- } else if (offsetSize === 2) {
- data.push(relativeOffset >> 8 & 0xFF, relativeOffset & 0xFF);
- } else if (offsetSize === 3) {
- data.push(relativeOffset >> 16 & 0xFF, relativeOffset >> 8 & 0xFF, relativeOffset & 0xFF);
- } else {
- data.push(relativeOffset >>> 24 & 0xFF, relativeOffset >> 16 & 0xFF, relativeOffset >> 8 & 0xFF, relativeOffset & 0xFF);
- }
- if (objects[i]) {
- relativeOffset += objects[i].length;
- }
- }
- for (i = 0; i < count; i++) {
- if (trackers[i]) {
- trackers[i].offset(data.length);
- }
- for (var j = 0, jj = objects[i].length; j < jj; j++) {
- data.push(objects[i][j]);
- }
- }
- return data;
- }
- };
- return CFFCompiler;
-}();
-exports.CFFStandardStrings = CFFStandardStrings;
-exports.CFFParser = CFFParser;
-exports.CFF = CFF;
-exports.CFFHeader = CFFHeader;
-exports.CFFStrings = CFFStrings;
-exports.CFFIndex = CFFIndex;
-exports.CFFCharset = CFFCharset;
-exports.CFFTopDict = CFFTopDict;
-exports.CFFPrivateDict = CFFPrivateDict;
-exports.CFFCompiler = CFFCompiler;
-exports.CFFFDSelect = CFFFDSelect;
-
-/***/ }),
-/* 158 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-var ISOAdobeCharset = ['.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', 'periodcentered', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand', 'questiondown', 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu', 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter', 'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright', 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex', 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla', 'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex', 'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis', 'ugrave', 'yacute', 'ydieresis', 'zcaron'];
-var ExpertCharset = ['.notdef', 'space', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior', 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', 'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall', 'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', 'onequarter', 'onehalf', 'threequarters', 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall'];
-var ExpertSubsetCharset = ['.notdef', 'space', 'dollaroldstyle', 'dollarsuperior', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior', 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', 'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', 'parenrightinferior', 'hyphensuperior', 'colonmonetary', 'onefitted', 'rupiah', 'centoldstyle', 'figuredash', 'hypheninferior', 'onequarter', 'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', 'commainferior'];
-exports.ISOAdobeCharset = ISOAdobeCharset;
-exports.ExpertCharset = ExpertCharset;
-exports.ExpertSubsetCharset = ExpertSubsetCharset;
-
-/***/ }),
-/* 159 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-var ExpertEncoding = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior', 'questionsmall', '', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', '', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior', 'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior', '', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', '', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '', 'figuredash', 'hypheninferior', '', '', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters', 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', '', '', 'zerosuperior', 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall'];
-var MacExpertEncoding = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'space', 'exclamsmall', 'Hungarumlautsmall', 'centoldstyle', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', '', 'threequartersemdash', '', 'questionsmall', '', '', '', '', 'Ethsmall', '', '', 'onequarter', 'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', '', '', '', '', '', '', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', 'parenrightinferior', 'Circumflexsmall', 'hypheninferior', 'Gravesmall', 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', '', '', 'asuperior', 'centsuperior', '', '', '', '', 'Aacutesmall', 'Agravesmall', 'Acircumflexsmall', 'Adieresissmall', 'Atildesmall', 'Aringsmall', 'Ccedillasmall', 'Eacutesmall', 'Egravesmall', 'Ecircumflexsmall', 'Edieresissmall', 'Iacutesmall', 'Igravesmall', 'Icircumflexsmall', 'Idieresissmall', 'Ntildesmall', 'Oacutesmall', 'Ogravesmall', 'Ocircumflexsmall', 'Odieresissmall', 'Otildesmall', 'Uacutesmall', 'Ugravesmall', 'Ucircumflexsmall', 'Udieresissmall', '', 'eightsuperior', 'fourinferior', 'threeinferior', 'sixinferior', 'eightinferior', 'seveninferior', 'Scaronsmall', '', 'centinferior', 'twoinferior', '', 'Dieresissmall', '', 'Caronsmall', 'osuperior', 'fiveinferior', '', 'commainferior', 'periodinferior', 'Yacutesmall', '', 'dollarinferior', '', '', 'Thornsmall', '', 'nineinferior', 'zeroinferior', 'Zcaronsmall', 'AEsmall', 'Oslashsmall', 'questiondownsmall', 'oneinferior', 'Lslashsmall', '', '', '', '', '', '', 'Cedillasmall', '', '', '', '', '', 'OEsmall', 'figuredash', 'hyphensuperior', '', '', '', '', 'exclamdownsmall', '', 'Ydieresissmall', '', 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', 'sevensuperior', 'ninesuperior', 'zerosuperior', '', 'esuperior', 'rsuperior', 'tsuperior', '', '', 'isuperior', 'ssuperior', 'dsuperior', '', '', '', '', '', 'lsuperior', 'Ogoneksmall', 'Brevesmall', 'Macronsmall', 'bsuperior', 'nsuperior', 'msuperior', 'commasuperior', 'periodsuperior', 'Dotaccentsmall', 'Ringsmall', '', '', '', ''];
-var MacRomanEncoding = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '', 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis', 'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', 'atilde', 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis', 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve', 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave', 'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling', 'section', 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright', 'trademark', 'acute', 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity', 'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff', 'summation', 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine', 'Omega', 'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot', 'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft', 'guillemotright', 'ellipsis', 'space', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash', 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft', 'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction', 'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', 'periodcentered', 'quotesinglbase', 'quotedblbase', 'perthousand', 'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', 'Ograve', 'Uacute', 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron'];
-var StandardEncoding = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'exclamdown', 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger', 'daggerdbl', 'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla', '', 'hungarumlaut', 'ogonek', 'caron', 'emdash', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '', '', '', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae', '', '', '', 'dotlessi', '', '', 'lslash', 'oslash', 'oe', 'germandbls', '', '', '', ''];
-var WinAnsiEncoding = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'bullet', 'Euro', 'bullet', 'quotesinglbase', 'florin', 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl', 'circumflex', 'perthousand', 'Scaron', 'guilsinglleft', 'OE', 'bullet', 'Zcaron', 'bullet', 'bullet', 'quoteleft', 'quoteright', 'quotedblleft', 'quotedblright', 'bullet', 'endash', 'emdash', 'tilde', 'trademark', 'scaron', 'guilsinglright', 'oe', 'bullet', 'zcaron', 'Ydieresis', 'space', 'exclamdown', 'cent', 'sterling', 'currency', 'yen', 'brokenbar', 'section', 'dieresis', 'copyright', 'ordfeminine', 'guillemotleft', 'logicalnot', 'hyphen', 'registered', 'macron', 'degree', 'plusminus', 'twosuperior', 'threesuperior', 'acute', 'mu', 'paragraph', 'periodcentered', 'cedilla', 'onesuperior', 'ordmasculine', 'guillemotright', 'onequarter', 'onehalf', 'threequarters', 'questiondown', 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', 'Adieresis', 'Aring', 'AE', 'Ccedilla', 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis', 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Eth', 'Ntilde', 'Ograve', 'Oacute', 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', 'Oslash', 'Ugrave', 'Uacute', 'Ucircumflex', 'Udieresis', 'Yacute', 'Thorn', 'germandbls', 'agrave', 'aacute', 'acircumflex', 'atilde', 'adieresis', 'aring', 'ae', 'ccedilla', 'egrave', 'eacute', 'ecircumflex', 'edieresis', 'igrave', 'iacute', 'icircumflex', 'idieresis', 'eth', 'ntilde', 'ograve', 'oacute', 'ocircumflex', 'otilde', 'odieresis', 'divide', 'oslash', 'ugrave', 'uacute', 'ucircumflex', 'udieresis', 'yacute', 'thorn', 'ydieresis'];
-var SymbolSetEncoding = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'space', 'exclam', 'universal', 'numbersign', 'existential', 'percent', 'ampersand', 'suchthat', 'parenleft', 'parenright', 'asteriskmath', 'plus', 'comma', 'minus', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'congruent', 'Alpha', 'Beta', 'Chi', 'Delta', 'Epsilon', 'Phi', 'Gamma', 'Eta', 'Iota', 'theta1', 'Kappa', 'Lambda', 'Mu', 'Nu', 'Omicron', 'Pi', 'Theta', 'Rho', 'Sigma', 'Tau', 'Upsilon', 'sigma1', 'Omega', 'Xi', 'Psi', 'Zeta', 'bracketleft', 'therefore', 'bracketright', 'perpendicular', 'underscore', 'radicalex', 'alpha', 'beta', 'chi', 'delta', 'epsilon', 'phi', 'gamma', 'eta', 'iota', 'phi1', 'kappa', 'lambda', 'mu', 'nu', 'omicron', 'pi', 'theta', 'rho', 'sigma', 'tau', 'upsilon', 'omega1', 'omega', 'xi', 'psi', 'zeta', 'braceleft', 'bar', 'braceright', 'similar', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'Euro', 'Upsilon1', 'minute', 'lessequal', 'fraction', 'infinity', 'florin', 'club', 'diamond', 'heart', 'spade', 'arrowboth', 'arrowleft', 'arrowup', 'arrowright', 'arrowdown', 'degree', 'plusminus', 'second', 'greaterequal', 'multiply', 'proportional', 'partialdiff', 'bullet', 'divide', 'notequal', 'equivalence', 'approxequal', 'ellipsis', 'arrowvertex', 'arrowhorizex', 'carriagereturn', 'aleph', 'Ifraktur', 'Rfraktur', 'weierstrass', 'circlemultiply', 'circleplus', 'emptyset', 'intersection', 'union', 'propersuperset', 'reflexsuperset', 'notsubset', 'propersubset', 'reflexsubset', 'element', 'notelement', 'angle', 'gradient', 'registerserif', 'copyrightserif', 'trademarkserif', 'product', 'radical', 'dotmath', 'logicalnot', 'logicaland', 'logicalor', 'arrowdblboth', 'arrowdblleft', 'arrowdblup', 'arrowdblright', 'arrowdbldown', 'lozenge', 'angleleft', 'registersans', 'copyrightsans', 'trademarksans', 'summation', 'parenlefttp', 'parenleftex', 'parenleftbt', 'bracketlefttp', 'bracketleftex', 'bracketleftbt', 'bracelefttp', 'braceleftmid', 'braceleftbt', 'braceex', '', 'angleright', 'integral', 'integraltp', 'integralex', 'integralbt', 'parenrighttp', 'parenrightex', 'parenrightbt', 'bracketrighttp', 'bracketrightex', 'bracketrightbt', 'bracerighttp', 'bracerightmid', 'bracerightbt', ''];
-var ZapfDingbatsEncoding = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'space', 'a1', 'a2', 'a202', 'a3', 'a4', 'a5', 'a119', 'a118', 'a117', 'a11', 'a12', 'a13', 'a14', 'a15', 'a16', 'a105', 'a17', 'a18', 'a19', 'a20', 'a21', 'a22', 'a23', 'a24', 'a25', 'a26', 'a27', 'a28', 'a6', 'a7', 'a8', 'a9', 'a10', 'a29', 'a30', 'a31', 'a32', 'a33', 'a34', 'a35', 'a36', 'a37', 'a38', 'a39', 'a40', 'a41', 'a42', 'a43', 'a44', 'a45', 'a46', 'a47', 'a48', 'a49', 'a50', 'a51', 'a52', 'a53', 'a54', 'a55', 'a56', 'a57', 'a58', 'a59', 'a60', 'a61', 'a62', 'a63', 'a64', 'a65', 'a66', 'a67', 'a68', 'a69', 'a70', 'a71', 'a72', 'a73', 'a74', 'a203', 'a75', 'a204', 'a76', 'a77', 'a78', 'a79', 'a81', 'a82', 'a83', 'a84', 'a97', 'a98', 'a99', 'a100', '', 'a89', 'a90', 'a93', 'a94', 'a91', 'a92', 'a205', 'a85', 'a206', 'a86', 'a87', 'a88', 'a95', 'a96', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'a101', 'a102', 'a103', 'a104', 'a106', 'a107', 'a108', 'a112', 'a111', 'a110', 'a109', 'a120', 'a121', 'a122', 'a123', 'a124', 'a125', 'a126', 'a127', 'a128', 'a129', 'a130', 'a131', 'a132', 'a133', 'a134', 'a135', 'a136', 'a137', 'a138', 'a139', 'a140', 'a141', 'a142', 'a143', 'a144', 'a145', 'a146', 'a147', 'a148', 'a149', 'a150', 'a151', 'a152', 'a153', 'a154', 'a155', 'a156', 'a157', 'a158', 'a159', 'a160', 'a161', 'a163', 'a164', 'a196', 'a165', 'a192', 'a166', 'a167', 'a168', 'a169', 'a170', 'a171', 'a172', 'a173', 'a162', 'a174', 'a175', 'a176', 'a177', 'a178', 'a179', 'a193', 'a180', 'a199', 'a181', 'a200', 'a182', '', 'a201', 'a183', 'a184', 'a197', 'a185', 'a194', 'a198', 'a186', 'a195', 'a187', 'a188', 'a189', 'a190', 'a191', ''];
-function getEncoding(encodingName) {
- switch (encodingName) {
- case 'WinAnsiEncoding':
- return WinAnsiEncoding;
- case 'StandardEncoding':
- return StandardEncoding;
- case 'MacRomanEncoding':
- return MacRomanEncoding;
- case 'SymbolSetEncoding':
- return SymbolSetEncoding;
- case 'ZapfDingbatsEncoding':
- return ZapfDingbatsEncoding;
- case 'ExpertEncoding':
- return ExpertEncoding;
- case 'MacExpertEncoding':
- return MacExpertEncoding;
- default:
- return null;
- }
-}
-exports.WinAnsiEncoding = WinAnsiEncoding;
-exports.StandardEncoding = StandardEncoding;
-exports.MacRomanEncoding = MacRomanEncoding;
-exports.SymbolSetEncoding = SymbolSetEncoding;
-exports.ZapfDingbatsEncoding = ZapfDingbatsEncoding;
-exports.ExpertEncoding = ExpertEncoding;
-exports.getEncoding = getEncoding;
-
-/***/ }),
-/* 160 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-var getLookupTableFactory = __w_pdfjs_require__(2).getLookupTableFactory;
-var getGlyphsUnicode = getLookupTableFactory(function (t) {
- t['A'] = 0x0041;
- t['AE'] = 0x00C6;
- t['AEacute'] = 0x01FC;
- t['AEmacron'] = 0x01E2;
- t['AEsmall'] = 0xF7E6;
- t['Aacute'] = 0x00C1;
- t['Aacutesmall'] = 0xF7E1;
- t['Abreve'] = 0x0102;
- t['Abreveacute'] = 0x1EAE;
- t['Abrevecyrillic'] = 0x04D0;
- t['Abrevedotbelow'] = 0x1EB6;
- t['Abrevegrave'] = 0x1EB0;
- t['Abrevehookabove'] = 0x1EB2;
- t['Abrevetilde'] = 0x1EB4;
- t['Acaron'] = 0x01CD;
- t['Acircle'] = 0x24B6;
- t['Acircumflex'] = 0x00C2;
- t['Acircumflexacute'] = 0x1EA4;
- t['Acircumflexdotbelow'] = 0x1EAC;
- t['Acircumflexgrave'] = 0x1EA6;
- t['Acircumflexhookabove'] = 0x1EA8;
- t['Acircumflexsmall'] = 0xF7E2;
- t['Acircumflextilde'] = 0x1EAA;
- t['Acute'] = 0xF6C9;
- t['Acutesmall'] = 0xF7B4;
- t['Acyrillic'] = 0x0410;
- t['Adblgrave'] = 0x0200;
- t['Adieresis'] = 0x00C4;
- t['Adieresiscyrillic'] = 0x04D2;
- t['Adieresismacron'] = 0x01DE;
- t['Adieresissmall'] = 0xF7E4;
- t['Adotbelow'] = 0x1EA0;
- t['Adotmacron'] = 0x01E0;
- t['Agrave'] = 0x00C0;
- t['Agravesmall'] = 0xF7E0;
- t['Ahookabove'] = 0x1EA2;
- t['Aiecyrillic'] = 0x04D4;
- t['Ainvertedbreve'] = 0x0202;
- t['Alpha'] = 0x0391;
- t['Alphatonos'] = 0x0386;
- t['Amacron'] = 0x0100;
- t['Amonospace'] = 0xFF21;
- t['Aogonek'] = 0x0104;
- t['Aring'] = 0x00C5;
- t['Aringacute'] = 0x01FA;
- t['Aringbelow'] = 0x1E00;
- t['Aringsmall'] = 0xF7E5;
- t['Asmall'] = 0xF761;
- t['Atilde'] = 0x00C3;
- t['Atildesmall'] = 0xF7E3;
- t['Aybarmenian'] = 0x0531;
- t['B'] = 0x0042;
- t['Bcircle'] = 0x24B7;
- t['Bdotaccent'] = 0x1E02;
- t['Bdotbelow'] = 0x1E04;
- t['Becyrillic'] = 0x0411;
- t['Benarmenian'] = 0x0532;
- t['Beta'] = 0x0392;
- t['Bhook'] = 0x0181;
- t['Blinebelow'] = 0x1E06;
- t['Bmonospace'] = 0xFF22;
- t['Brevesmall'] = 0xF6F4;
- t['Bsmall'] = 0xF762;
- t['Btopbar'] = 0x0182;
- t['C'] = 0x0043;
- t['Caarmenian'] = 0x053E;
- t['Cacute'] = 0x0106;
- t['Caron'] = 0xF6CA;
- t['Caronsmall'] = 0xF6F5;
- t['Ccaron'] = 0x010C;
- t['Ccedilla'] = 0x00C7;
- t['Ccedillaacute'] = 0x1E08;
- t['Ccedillasmall'] = 0xF7E7;
- t['Ccircle'] = 0x24B8;
- t['Ccircumflex'] = 0x0108;
- t['Cdot'] = 0x010A;
- t['Cdotaccent'] = 0x010A;
- t['Cedillasmall'] = 0xF7B8;
- t['Chaarmenian'] = 0x0549;
- t['Cheabkhasiancyrillic'] = 0x04BC;
- t['Checyrillic'] = 0x0427;
- t['Chedescenderabkhasiancyrillic'] = 0x04BE;
- t['Chedescendercyrillic'] = 0x04B6;
- t['Chedieresiscyrillic'] = 0x04F4;
- t['Cheharmenian'] = 0x0543;
- t['Chekhakassiancyrillic'] = 0x04CB;
- t['Cheverticalstrokecyrillic'] = 0x04B8;
- t['Chi'] = 0x03A7;
- t['Chook'] = 0x0187;
- t['Circumflexsmall'] = 0xF6F6;
- t['Cmonospace'] = 0xFF23;
- t['Coarmenian'] = 0x0551;
- t['Csmall'] = 0xF763;
- t['D'] = 0x0044;
- t['DZ'] = 0x01F1;
- t['DZcaron'] = 0x01C4;
- t['Daarmenian'] = 0x0534;
- t['Dafrican'] = 0x0189;
- t['Dcaron'] = 0x010E;
- t['Dcedilla'] = 0x1E10;
- t['Dcircle'] = 0x24B9;
- t['Dcircumflexbelow'] = 0x1E12;
- t['Dcroat'] = 0x0110;
- t['Ddotaccent'] = 0x1E0A;
- t['Ddotbelow'] = 0x1E0C;
- t['Decyrillic'] = 0x0414;
- t['Deicoptic'] = 0x03EE;
- t['Delta'] = 0x2206;
- t['Deltagreek'] = 0x0394;
- t['Dhook'] = 0x018A;
- t['Dieresis'] = 0xF6CB;
- t['DieresisAcute'] = 0xF6CC;
- t['DieresisGrave'] = 0xF6CD;
- t['Dieresissmall'] = 0xF7A8;
- t['Digammagreek'] = 0x03DC;
- t['Djecyrillic'] = 0x0402;
- t['Dlinebelow'] = 0x1E0E;
- t['Dmonospace'] = 0xFF24;
- t['Dotaccentsmall'] = 0xF6F7;
- t['Dslash'] = 0x0110;
- t['Dsmall'] = 0xF764;
- t['Dtopbar'] = 0x018B;
- t['Dz'] = 0x01F2;
- t['Dzcaron'] = 0x01C5;
- t['Dzeabkhasiancyrillic'] = 0x04E0;
- t['Dzecyrillic'] = 0x0405;
- t['Dzhecyrillic'] = 0x040F;
- t['E'] = 0x0045;
- t['Eacute'] = 0x00C9;
- t['Eacutesmall'] = 0xF7E9;
- t['Ebreve'] = 0x0114;
- t['Ecaron'] = 0x011A;
- t['Ecedillabreve'] = 0x1E1C;
- t['Echarmenian'] = 0x0535;
- t['Ecircle'] = 0x24BA;
- t['Ecircumflex'] = 0x00CA;
- t['Ecircumflexacute'] = 0x1EBE;
- t['Ecircumflexbelow'] = 0x1E18;
- t['Ecircumflexdotbelow'] = 0x1EC6;
- t['Ecircumflexgrave'] = 0x1EC0;
- t['Ecircumflexhookabove'] = 0x1EC2;
- t['Ecircumflexsmall'] = 0xF7EA;
- t['Ecircumflextilde'] = 0x1EC4;
- t['Ecyrillic'] = 0x0404;
- t['Edblgrave'] = 0x0204;
- t['Edieresis'] = 0x00CB;
- t['Edieresissmall'] = 0xF7EB;
- t['Edot'] = 0x0116;
- t['Edotaccent'] = 0x0116;
- t['Edotbelow'] = 0x1EB8;
- t['Efcyrillic'] = 0x0424;
- t['Egrave'] = 0x00C8;
- t['Egravesmall'] = 0xF7E8;
- t['Eharmenian'] = 0x0537;
- t['Ehookabove'] = 0x1EBA;
- t['Eightroman'] = 0x2167;
- t['Einvertedbreve'] = 0x0206;
- t['Eiotifiedcyrillic'] = 0x0464;
- t['Elcyrillic'] = 0x041B;
- t['Elevenroman'] = 0x216A;
- t['Emacron'] = 0x0112;
- t['Emacronacute'] = 0x1E16;
- t['Emacrongrave'] = 0x1E14;
- t['Emcyrillic'] = 0x041C;
- t['Emonospace'] = 0xFF25;
- t['Encyrillic'] = 0x041D;
- t['Endescendercyrillic'] = 0x04A2;
- t['Eng'] = 0x014A;
- t['Enghecyrillic'] = 0x04A4;
- t['Enhookcyrillic'] = 0x04C7;
- t['Eogonek'] = 0x0118;
- t['Eopen'] = 0x0190;
- t['Epsilon'] = 0x0395;
- t['Epsilontonos'] = 0x0388;
- t['Ercyrillic'] = 0x0420;
- t['Ereversed'] = 0x018E;
- t['Ereversedcyrillic'] = 0x042D;
- t['Escyrillic'] = 0x0421;
- t['Esdescendercyrillic'] = 0x04AA;
- t['Esh'] = 0x01A9;
- t['Esmall'] = 0xF765;
- t['Eta'] = 0x0397;
- t['Etarmenian'] = 0x0538;
- t['Etatonos'] = 0x0389;
- t['Eth'] = 0x00D0;
- t['Ethsmall'] = 0xF7F0;
- t['Etilde'] = 0x1EBC;
- t['Etildebelow'] = 0x1E1A;
- t['Euro'] = 0x20AC;
- t['Ezh'] = 0x01B7;
- t['Ezhcaron'] = 0x01EE;
- t['Ezhreversed'] = 0x01B8;
- t['F'] = 0x0046;
- t['Fcircle'] = 0x24BB;
- t['Fdotaccent'] = 0x1E1E;
- t['Feharmenian'] = 0x0556;
- t['Feicoptic'] = 0x03E4;
- t['Fhook'] = 0x0191;
- t['Fitacyrillic'] = 0x0472;
- t['Fiveroman'] = 0x2164;
- t['Fmonospace'] = 0xFF26;
- t['Fourroman'] = 0x2163;
- t['Fsmall'] = 0xF766;
- t['G'] = 0x0047;
- t['GBsquare'] = 0x3387;
- t['Gacute'] = 0x01F4;
- t['Gamma'] = 0x0393;
- t['Gammaafrican'] = 0x0194;
- t['Gangiacoptic'] = 0x03EA;
- t['Gbreve'] = 0x011E;
- t['Gcaron'] = 0x01E6;
- t['Gcedilla'] = 0x0122;
- t['Gcircle'] = 0x24BC;
- t['Gcircumflex'] = 0x011C;
- t['Gcommaaccent'] = 0x0122;
- t['Gdot'] = 0x0120;
- t['Gdotaccent'] = 0x0120;
- t['Gecyrillic'] = 0x0413;
- t['Ghadarmenian'] = 0x0542;
- t['Ghemiddlehookcyrillic'] = 0x0494;
- t['Ghestrokecyrillic'] = 0x0492;
- t['Gheupturncyrillic'] = 0x0490;
- t['Ghook'] = 0x0193;
- t['Gimarmenian'] = 0x0533;
- t['Gjecyrillic'] = 0x0403;
- t['Gmacron'] = 0x1E20;
- t['Gmonospace'] = 0xFF27;
- t['Grave'] = 0xF6CE;
- t['Gravesmall'] = 0xF760;
- t['Gsmall'] = 0xF767;
- t['Gsmallhook'] = 0x029B;
- t['Gstroke'] = 0x01E4;
- t['H'] = 0x0048;
- t['H18533'] = 0x25CF;
- t['H18543'] = 0x25AA;
- t['H18551'] = 0x25AB;
- t['H22073'] = 0x25A1;
- t['HPsquare'] = 0x33CB;
- t['Haabkhasiancyrillic'] = 0x04A8;
- t['Hadescendercyrillic'] = 0x04B2;
- t['Hardsigncyrillic'] = 0x042A;
- t['Hbar'] = 0x0126;
- t['Hbrevebelow'] = 0x1E2A;
- t['Hcedilla'] = 0x1E28;
- t['Hcircle'] = 0x24BD;
- t['Hcircumflex'] = 0x0124;
- t['Hdieresis'] = 0x1E26;
- t['Hdotaccent'] = 0x1E22;
- t['Hdotbelow'] = 0x1E24;
- t['Hmonospace'] = 0xFF28;
- t['Hoarmenian'] = 0x0540;
- t['Horicoptic'] = 0x03E8;
- t['Hsmall'] = 0xF768;
- t['Hungarumlaut'] = 0xF6CF;
- t['Hungarumlautsmall'] = 0xF6F8;
- t['Hzsquare'] = 0x3390;
- t['I'] = 0x0049;
- t['IAcyrillic'] = 0x042F;
- t['IJ'] = 0x0132;
- t['IUcyrillic'] = 0x042E;
- t['Iacute'] = 0x00CD;
- t['Iacutesmall'] = 0xF7ED;
- t['Ibreve'] = 0x012C;
- t['Icaron'] = 0x01CF;
- t['Icircle'] = 0x24BE;
- t['Icircumflex'] = 0x00CE;
- t['Icircumflexsmall'] = 0xF7EE;
- t['Icyrillic'] = 0x0406;
- t['Idblgrave'] = 0x0208;
- t['Idieresis'] = 0x00CF;
- t['Idieresisacute'] = 0x1E2E;
- t['Idieresiscyrillic'] = 0x04E4;
- t['Idieresissmall'] = 0xF7EF;
- t['Idot'] = 0x0130;
- t['Idotaccent'] = 0x0130;
- t['Idotbelow'] = 0x1ECA;
- t['Iebrevecyrillic'] = 0x04D6;
- t['Iecyrillic'] = 0x0415;
- t['Ifraktur'] = 0x2111;
- t['Igrave'] = 0x00CC;
- t['Igravesmall'] = 0xF7EC;
- t['Ihookabove'] = 0x1EC8;
- t['Iicyrillic'] = 0x0418;
- t['Iinvertedbreve'] = 0x020A;
- t['Iishortcyrillic'] = 0x0419;
- t['Imacron'] = 0x012A;
- t['Imacroncyrillic'] = 0x04E2;
- t['Imonospace'] = 0xFF29;
- t['Iniarmenian'] = 0x053B;
- t['Iocyrillic'] = 0x0401;
- t['Iogonek'] = 0x012E;
- t['Iota'] = 0x0399;
- t['Iotaafrican'] = 0x0196;
- t['Iotadieresis'] = 0x03AA;
- t['Iotatonos'] = 0x038A;
- t['Ismall'] = 0xF769;
- t['Istroke'] = 0x0197;
- t['Itilde'] = 0x0128;
- t['Itildebelow'] = 0x1E2C;
- t['Izhitsacyrillic'] = 0x0474;
- t['Izhitsadblgravecyrillic'] = 0x0476;
- t['J'] = 0x004A;
- t['Jaarmenian'] = 0x0541;
- t['Jcircle'] = 0x24BF;
- t['Jcircumflex'] = 0x0134;
- t['Jecyrillic'] = 0x0408;
- t['Jheharmenian'] = 0x054B;
- t['Jmonospace'] = 0xFF2A;
- t['Jsmall'] = 0xF76A;
- t['K'] = 0x004B;
- t['KBsquare'] = 0x3385;
- t['KKsquare'] = 0x33CD;
- t['Kabashkircyrillic'] = 0x04A0;
- t['Kacute'] = 0x1E30;
- t['Kacyrillic'] = 0x041A;
- t['Kadescendercyrillic'] = 0x049A;
- t['Kahookcyrillic'] = 0x04C3;
- t['Kappa'] = 0x039A;
- t['Kastrokecyrillic'] = 0x049E;
- t['Kaverticalstrokecyrillic'] = 0x049C;
- t['Kcaron'] = 0x01E8;
- t['Kcedilla'] = 0x0136;
- t['Kcircle'] = 0x24C0;
- t['Kcommaaccent'] = 0x0136;
- t['Kdotbelow'] = 0x1E32;
- t['Keharmenian'] = 0x0554;
- t['Kenarmenian'] = 0x053F;
- t['Khacyrillic'] = 0x0425;
- t['Kheicoptic'] = 0x03E6;
- t['Khook'] = 0x0198;
- t['Kjecyrillic'] = 0x040C;
- t['Klinebelow'] = 0x1E34;
- t['Kmonospace'] = 0xFF2B;
- t['Koppacyrillic'] = 0x0480;
- t['Koppagreek'] = 0x03DE;
- t['Ksicyrillic'] = 0x046E;
- t['Ksmall'] = 0xF76B;
- t['L'] = 0x004C;
- t['LJ'] = 0x01C7;
- t['LL'] = 0xF6BF;
- t['Lacute'] = 0x0139;
- t['Lambda'] = 0x039B;
- t['Lcaron'] = 0x013D;
- t['Lcedilla'] = 0x013B;
- t['Lcircle'] = 0x24C1;
- t['Lcircumflexbelow'] = 0x1E3C;
- t['Lcommaaccent'] = 0x013B;
- t['Ldot'] = 0x013F;
- t['Ldotaccent'] = 0x013F;
- t['Ldotbelow'] = 0x1E36;
- t['Ldotbelowmacron'] = 0x1E38;
- t['Liwnarmenian'] = 0x053C;
- t['Lj'] = 0x01C8;
- t['Ljecyrillic'] = 0x0409;
- t['Llinebelow'] = 0x1E3A;
- t['Lmonospace'] = 0xFF2C;
- t['Lslash'] = 0x0141;
- t['Lslashsmall'] = 0xF6F9;
- t['Lsmall'] = 0xF76C;
- t['M'] = 0x004D;
- t['MBsquare'] = 0x3386;
- t['Macron'] = 0xF6D0;
- t['Macronsmall'] = 0xF7AF;
- t['Macute'] = 0x1E3E;
- t['Mcircle'] = 0x24C2;
- t['Mdotaccent'] = 0x1E40;
- t['Mdotbelow'] = 0x1E42;
- t['Menarmenian'] = 0x0544;
- t['Mmonospace'] = 0xFF2D;
- t['Msmall'] = 0xF76D;
- t['Mturned'] = 0x019C;
- t['Mu'] = 0x039C;
- t['N'] = 0x004E;
- t['NJ'] = 0x01CA;
- t['Nacute'] = 0x0143;
- t['Ncaron'] = 0x0147;
- t['Ncedilla'] = 0x0145;
- t['Ncircle'] = 0x24C3;
- t['Ncircumflexbelow'] = 0x1E4A;
- t['Ncommaaccent'] = 0x0145;
- t['Ndotaccent'] = 0x1E44;
- t['Ndotbelow'] = 0x1E46;
- t['Nhookleft'] = 0x019D;
- t['Nineroman'] = 0x2168;
- t['Nj'] = 0x01CB;
- t['Njecyrillic'] = 0x040A;
- t['Nlinebelow'] = 0x1E48;
- t['Nmonospace'] = 0xFF2E;
- t['Nowarmenian'] = 0x0546;
- t['Nsmall'] = 0xF76E;
- t['Ntilde'] = 0x00D1;
- t['Ntildesmall'] = 0xF7F1;
- t['Nu'] = 0x039D;
- t['O'] = 0x004F;
- t['OE'] = 0x0152;
- t['OEsmall'] = 0xF6FA;
- t['Oacute'] = 0x00D3;
- t['Oacutesmall'] = 0xF7F3;
- t['Obarredcyrillic'] = 0x04E8;
- t['Obarreddieresiscyrillic'] = 0x04EA;
- t['Obreve'] = 0x014E;
- t['Ocaron'] = 0x01D1;
- t['Ocenteredtilde'] = 0x019F;
- t['Ocircle'] = 0x24C4;
- t['Ocircumflex'] = 0x00D4;
- t['Ocircumflexacute'] = 0x1ED0;
- t['Ocircumflexdotbelow'] = 0x1ED8;
- t['Ocircumflexgrave'] = 0x1ED2;
- t['Ocircumflexhookabove'] = 0x1ED4;
- t['Ocircumflexsmall'] = 0xF7F4;
- t['Ocircumflextilde'] = 0x1ED6;
- t['Ocyrillic'] = 0x041E;
- t['Odblacute'] = 0x0150;
- t['Odblgrave'] = 0x020C;
- t['Odieresis'] = 0x00D6;
- t['Odieresiscyrillic'] = 0x04E6;
- t['Odieresissmall'] = 0xF7F6;
- t['Odotbelow'] = 0x1ECC;
- t['Ogoneksmall'] = 0xF6FB;
- t['Ograve'] = 0x00D2;
- t['Ogravesmall'] = 0xF7F2;
- t['Oharmenian'] = 0x0555;
- t['Ohm'] = 0x2126;
- t['Ohookabove'] = 0x1ECE;
- t['Ohorn'] = 0x01A0;
- t['Ohornacute'] = 0x1EDA;
- t['Ohorndotbelow'] = 0x1EE2;
- t['Ohorngrave'] = 0x1EDC;
- t['Ohornhookabove'] = 0x1EDE;
- t['Ohorntilde'] = 0x1EE0;
- t['Ohungarumlaut'] = 0x0150;
- t['Oi'] = 0x01A2;
- t['Oinvertedbreve'] = 0x020E;
- t['Omacron'] = 0x014C;
- t['Omacronacute'] = 0x1E52;
- t['Omacrongrave'] = 0x1E50;
- t['Omega'] = 0x2126;
- t['Omegacyrillic'] = 0x0460;
- t['Omegagreek'] = 0x03A9;
- t['Omegaroundcyrillic'] = 0x047A;
- t['Omegatitlocyrillic'] = 0x047C;
- t['Omegatonos'] = 0x038F;
- t['Omicron'] = 0x039F;
- t['Omicrontonos'] = 0x038C;
- t['Omonospace'] = 0xFF2F;
- t['Oneroman'] = 0x2160;
- t['Oogonek'] = 0x01EA;
- t['Oogonekmacron'] = 0x01EC;
- t['Oopen'] = 0x0186;
- t['Oslash'] = 0x00D8;
- t['Oslashacute'] = 0x01FE;
- t['Oslashsmall'] = 0xF7F8;
- t['Osmall'] = 0xF76F;
- t['Ostrokeacute'] = 0x01FE;
- t['Otcyrillic'] = 0x047E;
- t['Otilde'] = 0x00D5;
- t['Otildeacute'] = 0x1E4C;
- t['Otildedieresis'] = 0x1E4E;
- t['Otildesmall'] = 0xF7F5;
- t['P'] = 0x0050;
- t['Pacute'] = 0x1E54;
- t['Pcircle'] = 0x24C5;
- t['Pdotaccent'] = 0x1E56;
- t['Pecyrillic'] = 0x041F;
- t['Peharmenian'] = 0x054A;
- t['Pemiddlehookcyrillic'] = 0x04A6;
- t['Phi'] = 0x03A6;
- t['Phook'] = 0x01A4;
- t['Pi'] = 0x03A0;
- t['Piwrarmenian'] = 0x0553;
- t['Pmonospace'] = 0xFF30;
- t['Psi'] = 0x03A8;
- t['Psicyrillic'] = 0x0470;
- t['Psmall'] = 0xF770;
- t['Q'] = 0x0051;
- t['Qcircle'] = 0x24C6;
- t['Qmonospace'] = 0xFF31;
- t['Qsmall'] = 0xF771;
- t['R'] = 0x0052;
- t['Raarmenian'] = 0x054C;
- t['Racute'] = 0x0154;
- t['Rcaron'] = 0x0158;
- t['Rcedilla'] = 0x0156;
- t['Rcircle'] = 0x24C7;
- t['Rcommaaccent'] = 0x0156;
- t['Rdblgrave'] = 0x0210;
- t['Rdotaccent'] = 0x1E58;
- t['Rdotbelow'] = 0x1E5A;
- t['Rdotbelowmacron'] = 0x1E5C;
- t['Reharmenian'] = 0x0550;
- t['Rfraktur'] = 0x211C;
- t['Rho'] = 0x03A1;
- t['Ringsmall'] = 0xF6FC;
- t['Rinvertedbreve'] = 0x0212;
- t['Rlinebelow'] = 0x1E5E;
- t['Rmonospace'] = 0xFF32;
- t['Rsmall'] = 0xF772;
- t['Rsmallinverted'] = 0x0281;
- t['Rsmallinvertedsuperior'] = 0x02B6;
- t['S'] = 0x0053;
- t['SF010000'] = 0x250C;
- t['SF020000'] = 0x2514;
- t['SF030000'] = 0x2510;
- t['SF040000'] = 0x2518;
- t['SF050000'] = 0x253C;
- t['SF060000'] = 0x252C;
- t['SF070000'] = 0x2534;
- t['SF080000'] = 0x251C;
- t['SF090000'] = 0x2524;
- t['SF100000'] = 0x2500;
- t['SF110000'] = 0x2502;
- t['SF190000'] = 0x2561;
- t['SF200000'] = 0x2562;
- t['SF210000'] = 0x2556;
- t['SF220000'] = 0x2555;
- t['SF230000'] = 0x2563;
- t['SF240000'] = 0x2551;
- t['SF250000'] = 0x2557;
- t['SF260000'] = 0x255D;
- t['SF270000'] = 0x255C;
- t['SF280000'] = 0x255B;
- t['SF360000'] = 0x255E;
- t['SF370000'] = 0x255F;
- t['SF380000'] = 0x255A;
- t['SF390000'] = 0x2554;
- t['SF400000'] = 0x2569;
- t['SF410000'] = 0x2566;
- t['SF420000'] = 0x2560;
- t['SF430000'] = 0x2550;
- t['SF440000'] = 0x256C;
- t['SF450000'] = 0x2567;
- t['SF460000'] = 0x2568;
- t['SF470000'] = 0x2564;
- t['SF480000'] = 0x2565;
- t['SF490000'] = 0x2559;
- t['SF500000'] = 0x2558;
- t['SF510000'] = 0x2552;
- t['SF520000'] = 0x2553;
- t['SF530000'] = 0x256B;
- t['SF540000'] = 0x256A;
- t['Sacute'] = 0x015A;
- t['Sacutedotaccent'] = 0x1E64;
- t['Sampigreek'] = 0x03E0;
- t['Scaron'] = 0x0160;
- t['Scarondotaccent'] = 0x1E66;
- t['Scaronsmall'] = 0xF6FD;
- t['Scedilla'] = 0x015E;
- t['Schwa'] = 0x018F;
- t['Schwacyrillic'] = 0x04D8;
- t['Schwadieresiscyrillic'] = 0x04DA;
- t['Scircle'] = 0x24C8;
- t['Scircumflex'] = 0x015C;
- t['Scommaaccent'] = 0x0218;
- t['Sdotaccent'] = 0x1E60;
- t['Sdotbelow'] = 0x1E62;
- t['Sdotbelowdotaccent'] = 0x1E68;
- t['Seharmenian'] = 0x054D;
- t['Sevenroman'] = 0x2166;
- t['Shaarmenian'] = 0x0547;
- t['Shacyrillic'] = 0x0428;
- t['Shchacyrillic'] = 0x0429;
- t['Sheicoptic'] = 0x03E2;
- t['Shhacyrillic'] = 0x04BA;
- t['Shimacoptic'] = 0x03EC;
- t['Sigma'] = 0x03A3;
- t['Sixroman'] = 0x2165;
- t['Smonospace'] = 0xFF33;
- t['Softsigncyrillic'] = 0x042C;
- t['Ssmall'] = 0xF773;
- t['Stigmagreek'] = 0x03DA;
- t['T'] = 0x0054;
- t['Tau'] = 0x03A4;
- t['Tbar'] = 0x0166;
- t['Tcaron'] = 0x0164;
- t['Tcedilla'] = 0x0162;
- t['Tcircle'] = 0x24C9;
- t['Tcircumflexbelow'] = 0x1E70;
- t['Tcommaaccent'] = 0x0162;
- t['Tdotaccent'] = 0x1E6A;
- t['Tdotbelow'] = 0x1E6C;
- t['Tecyrillic'] = 0x0422;
- t['Tedescendercyrillic'] = 0x04AC;
- t['Tenroman'] = 0x2169;
- t['Tetsecyrillic'] = 0x04B4;
- t['Theta'] = 0x0398;
- t['Thook'] = 0x01AC;
- t['Thorn'] = 0x00DE;
- t['Thornsmall'] = 0xF7FE;
- t['Threeroman'] = 0x2162;
- t['Tildesmall'] = 0xF6FE;
- t['Tiwnarmenian'] = 0x054F;
- t['Tlinebelow'] = 0x1E6E;
- t['Tmonospace'] = 0xFF34;
- t['Toarmenian'] = 0x0539;
- t['Tonefive'] = 0x01BC;
- t['Tonesix'] = 0x0184;
- t['Tonetwo'] = 0x01A7;
- t['Tretroflexhook'] = 0x01AE;
- t['Tsecyrillic'] = 0x0426;
- t['Tshecyrillic'] = 0x040B;
- t['Tsmall'] = 0xF774;
- t['Twelveroman'] = 0x216B;
- t['Tworoman'] = 0x2161;
- t['U'] = 0x0055;
- t['Uacute'] = 0x00DA;
- t['Uacutesmall'] = 0xF7FA;
- t['Ubreve'] = 0x016C;
- t['Ucaron'] = 0x01D3;
- t['Ucircle'] = 0x24CA;
- t['Ucircumflex'] = 0x00DB;
- t['Ucircumflexbelow'] = 0x1E76;
- t['Ucircumflexsmall'] = 0xF7FB;
- t['Ucyrillic'] = 0x0423;
- t['Udblacute'] = 0x0170;
- t['Udblgrave'] = 0x0214;
- t['Udieresis'] = 0x00DC;
- t['Udieresisacute'] = 0x01D7;
- t['Udieresisbelow'] = 0x1E72;
- t['Udieresiscaron'] = 0x01D9;
- t['Udieresiscyrillic'] = 0x04F0;
- t['Udieresisgrave'] = 0x01DB;
- t['Udieresismacron'] = 0x01D5;
- t['Udieresissmall'] = 0xF7FC;
- t['Udotbelow'] = 0x1EE4;
- t['Ugrave'] = 0x00D9;
- t['Ugravesmall'] = 0xF7F9;
- t['Uhookabove'] = 0x1EE6;
- t['Uhorn'] = 0x01AF;
- t['Uhornacute'] = 0x1EE8;
- t['Uhorndotbelow'] = 0x1EF0;
- t['Uhorngrave'] = 0x1EEA;
- t['Uhornhookabove'] = 0x1EEC;
- t['Uhorntilde'] = 0x1EEE;
- t['Uhungarumlaut'] = 0x0170;
- t['Uhungarumlautcyrillic'] = 0x04F2;
- t['Uinvertedbreve'] = 0x0216;
- t['Ukcyrillic'] = 0x0478;
- t['Umacron'] = 0x016A;
- t['Umacroncyrillic'] = 0x04EE;
- t['Umacrondieresis'] = 0x1E7A;
- t['Umonospace'] = 0xFF35;
- t['Uogonek'] = 0x0172;
- t['Upsilon'] = 0x03A5;
- t['Upsilon1'] = 0x03D2;
- t['Upsilonacutehooksymbolgreek'] = 0x03D3;
- t['Upsilonafrican'] = 0x01B1;
- t['Upsilondieresis'] = 0x03AB;
- t['Upsilondieresishooksymbolgreek'] = 0x03D4;
- t['Upsilonhooksymbol'] = 0x03D2;
- t['Upsilontonos'] = 0x038E;
- t['Uring'] = 0x016E;
- t['Ushortcyrillic'] = 0x040E;
- t['Usmall'] = 0xF775;
- t['Ustraightcyrillic'] = 0x04AE;
- t['Ustraightstrokecyrillic'] = 0x04B0;
- t['Utilde'] = 0x0168;
- t['Utildeacute'] = 0x1E78;
- t['Utildebelow'] = 0x1E74;
- t['V'] = 0x0056;
- t['Vcircle'] = 0x24CB;
- t['Vdotbelow'] = 0x1E7E;
- t['Vecyrillic'] = 0x0412;
- t['Vewarmenian'] = 0x054E;
- t['Vhook'] = 0x01B2;
- t['Vmonospace'] = 0xFF36;
- t['Voarmenian'] = 0x0548;
- t['Vsmall'] = 0xF776;
- t['Vtilde'] = 0x1E7C;
- t['W'] = 0x0057;
- t['Wacute'] = 0x1E82;
- t['Wcircle'] = 0x24CC;
- t['Wcircumflex'] = 0x0174;
- t['Wdieresis'] = 0x1E84;
- t['Wdotaccent'] = 0x1E86;
- t['Wdotbelow'] = 0x1E88;
- t['Wgrave'] = 0x1E80;
- t['Wmonospace'] = 0xFF37;
- t['Wsmall'] = 0xF777;
- t['X'] = 0x0058;
- t['Xcircle'] = 0x24CD;
- t['Xdieresis'] = 0x1E8C;
- t['Xdotaccent'] = 0x1E8A;
- t['Xeharmenian'] = 0x053D;
- t['Xi'] = 0x039E;
- t['Xmonospace'] = 0xFF38;
- t['Xsmall'] = 0xF778;
- t['Y'] = 0x0059;
- t['Yacute'] = 0x00DD;
- t['Yacutesmall'] = 0xF7FD;
- t['Yatcyrillic'] = 0x0462;
- t['Ycircle'] = 0x24CE;
- t['Ycircumflex'] = 0x0176;
- t['Ydieresis'] = 0x0178;
- t['Ydieresissmall'] = 0xF7FF;
- t['Ydotaccent'] = 0x1E8E;
- t['Ydotbelow'] = 0x1EF4;
- t['Yericyrillic'] = 0x042B;
- t['Yerudieresiscyrillic'] = 0x04F8;
- t['Ygrave'] = 0x1EF2;
- t['Yhook'] = 0x01B3;
- t['Yhookabove'] = 0x1EF6;
- t['Yiarmenian'] = 0x0545;
- t['Yicyrillic'] = 0x0407;
- t['Yiwnarmenian'] = 0x0552;
- t['Ymonospace'] = 0xFF39;
- t['Ysmall'] = 0xF779;
- t['Ytilde'] = 0x1EF8;
- t['Yusbigcyrillic'] = 0x046A;
- t['Yusbigiotifiedcyrillic'] = 0x046C;
- t['Yuslittlecyrillic'] = 0x0466;
- t['Yuslittleiotifiedcyrillic'] = 0x0468;
- t['Z'] = 0x005A;
- t['Zaarmenian'] = 0x0536;
- t['Zacute'] = 0x0179;
- t['Zcaron'] = 0x017D;
- t['Zcaronsmall'] = 0xF6FF;
- t['Zcircle'] = 0x24CF;
- t['Zcircumflex'] = 0x1E90;
- t['Zdot'] = 0x017B;
- t['Zdotaccent'] = 0x017B;
- t['Zdotbelow'] = 0x1E92;
- t['Zecyrillic'] = 0x0417;
- t['Zedescendercyrillic'] = 0x0498;
- t['Zedieresiscyrillic'] = 0x04DE;
- t['Zeta'] = 0x0396;
- t['Zhearmenian'] = 0x053A;
- t['Zhebrevecyrillic'] = 0x04C1;
- t['Zhecyrillic'] = 0x0416;
- t['Zhedescendercyrillic'] = 0x0496;
- t['Zhedieresiscyrillic'] = 0x04DC;
- t['Zlinebelow'] = 0x1E94;
- t['Zmonospace'] = 0xFF3A;
- t['Zsmall'] = 0xF77A;
- t['Zstroke'] = 0x01B5;
- t['a'] = 0x0061;
- t['aabengali'] = 0x0986;
- t['aacute'] = 0x00E1;
- t['aadeva'] = 0x0906;
- t['aagujarati'] = 0x0A86;
- t['aagurmukhi'] = 0x0A06;
- t['aamatragurmukhi'] = 0x0A3E;
- t['aarusquare'] = 0x3303;
- t['aavowelsignbengali'] = 0x09BE;
- t['aavowelsigndeva'] = 0x093E;
- t['aavowelsigngujarati'] = 0x0ABE;
- t['abbreviationmarkarmenian'] = 0x055F;
- t['abbreviationsigndeva'] = 0x0970;
- t['abengali'] = 0x0985;
- t['abopomofo'] = 0x311A;
- t['abreve'] = 0x0103;
- t['abreveacute'] = 0x1EAF;
- t['abrevecyrillic'] = 0x04D1;
- t['abrevedotbelow'] = 0x1EB7;
- t['abrevegrave'] = 0x1EB1;
- t['abrevehookabove'] = 0x1EB3;
- t['abrevetilde'] = 0x1EB5;
- t['acaron'] = 0x01CE;
- t['acircle'] = 0x24D0;
- t['acircumflex'] = 0x00E2;
- t['acircumflexacute'] = 0x1EA5;
- t['acircumflexdotbelow'] = 0x1EAD;
- t['acircumflexgrave'] = 0x1EA7;
- t['acircumflexhookabove'] = 0x1EA9;
- t['acircumflextilde'] = 0x1EAB;
- t['acute'] = 0x00B4;
- t['acutebelowcmb'] = 0x0317;
- t['acutecmb'] = 0x0301;
- t['acutecomb'] = 0x0301;
- t['acutedeva'] = 0x0954;
- t['acutelowmod'] = 0x02CF;
- t['acutetonecmb'] = 0x0341;
- t['acyrillic'] = 0x0430;
- t['adblgrave'] = 0x0201;
- t['addakgurmukhi'] = 0x0A71;
- t['adeva'] = 0x0905;
- t['adieresis'] = 0x00E4;
- t['adieresiscyrillic'] = 0x04D3;
- t['adieresismacron'] = 0x01DF;
- t['adotbelow'] = 0x1EA1;
- t['adotmacron'] = 0x01E1;
- t['ae'] = 0x00E6;
- t['aeacute'] = 0x01FD;
- t['aekorean'] = 0x3150;
- t['aemacron'] = 0x01E3;
- t['afii00208'] = 0x2015;
- t['afii08941'] = 0x20A4;
- t['afii10017'] = 0x0410;
- t['afii10018'] = 0x0411;
- t['afii10019'] = 0x0412;
- t['afii10020'] = 0x0413;
- t['afii10021'] = 0x0414;
- t['afii10022'] = 0x0415;
- t['afii10023'] = 0x0401;
- t['afii10024'] = 0x0416;
- t['afii10025'] = 0x0417;
- t['afii10026'] = 0x0418;
- t['afii10027'] = 0x0419;
- t['afii10028'] = 0x041A;
- t['afii10029'] = 0x041B;
- t['afii10030'] = 0x041C;
- t['afii10031'] = 0x041D;
- t['afii10032'] = 0x041E;
- t['afii10033'] = 0x041F;
- t['afii10034'] = 0x0420;
- t['afii10035'] = 0x0421;
- t['afii10036'] = 0x0422;
- t['afii10037'] = 0x0423;
- t['afii10038'] = 0x0424;
- t['afii10039'] = 0x0425;
- t['afii10040'] = 0x0426;
- t['afii10041'] = 0x0427;
- t['afii10042'] = 0x0428;
- t['afii10043'] = 0x0429;
- t['afii10044'] = 0x042A;
- t['afii10045'] = 0x042B;
- t['afii10046'] = 0x042C;
- t['afii10047'] = 0x042D;
- t['afii10048'] = 0x042E;
- t['afii10049'] = 0x042F;
- t['afii10050'] = 0x0490;
- t['afii10051'] = 0x0402;
- t['afii10052'] = 0x0403;
- t['afii10053'] = 0x0404;
- t['afii10054'] = 0x0405;
- t['afii10055'] = 0x0406;
- t['afii10056'] = 0x0407;
- t['afii10057'] = 0x0408;
- t['afii10058'] = 0x0409;
- t['afii10059'] = 0x040A;
- t['afii10060'] = 0x040B;
- t['afii10061'] = 0x040C;
- t['afii10062'] = 0x040E;
- t['afii10063'] = 0xF6C4;
- t['afii10064'] = 0xF6C5;
- t['afii10065'] = 0x0430;
- t['afii10066'] = 0x0431;
- t['afii10067'] = 0x0432;
- t['afii10068'] = 0x0433;
- t['afii10069'] = 0x0434;
- t['afii10070'] = 0x0435;
- t['afii10071'] = 0x0451;
- t['afii10072'] = 0x0436;
- t['afii10073'] = 0x0437;
- t['afii10074'] = 0x0438;
- t['afii10075'] = 0x0439;
- t['afii10076'] = 0x043A;
- t['afii10077'] = 0x043B;
- t['afii10078'] = 0x043C;
- t['afii10079'] = 0x043D;
- t['afii10080'] = 0x043E;
- t['afii10081'] = 0x043F;
- t['afii10082'] = 0x0440;
- t['afii10083'] = 0x0441;
- t['afii10084'] = 0x0442;
- t['afii10085'] = 0x0443;
- t['afii10086'] = 0x0444;
- t['afii10087'] = 0x0445;
- t['afii10088'] = 0x0446;
- t['afii10089'] = 0x0447;
- t['afii10090'] = 0x0448;
- t['afii10091'] = 0x0449;
- t['afii10092'] = 0x044A;
- t['afii10093'] = 0x044B;
- t['afii10094'] = 0x044C;
- t['afii10095'] = 0x044D;
- t['afii10096'] = 0x044E;
- t['afii10097'] = 0x044F;
- t['afii10098'] = 0x0491;
- t['afii10099'] = 0x0452;
- t['afii10100'] = 0x0453;
- t['afii10101'] = 0x0454;
- t['afii10102'] = 0x0455;
- t['afii10103'] = 0x0456;
- t['afii10104'] = 0x0457;
- t['afii10105'] = 0x0458;
- t['afii10106'] = 0x0459;
- t['afii10107'] = 0x045A;
- t['afii10108'] = 0x045B;
- t['afii10109'] = 0x045C;
- t['afii10110'] = 0x045E;
- t['afii10145'] = 0x040F;
- t['afii10146'] = 0x0462;
- t['afii10147'] = 0x0472;
- t['afii10148'] = 0x0474;
- t['afii10192'] = 0xF6C6;
- t['afii10193'] = 0x045F;
- t['afii10194'] = 0x0463;
- t['afii10195'] = 0x0473;
- t['afii10196'] = 0x0475;
- t['afii10831'] = 0xF6C7;
- t['afii10832'] = 0xF6C8;
- t['afii10846'] = 0x04D9;
- t['afii299'] = 0x200E;
- t['afii300'] = 0x200F;
- t['afii301'] = 0x200D;
- t['afii57381'] = 0x066A;
- t['afii57388'] = 0x060C;
- t['afii57392'] = 0x0660;
- t['afii57393'] = 0x0661;
- t['afii57394'] = 0x0662;
- t['afii57395'] = 0x0663;
- t['afii57396'] = 0x0664;
- t['afii57397'] = 0x0665;
- t['afii57398'] = 0x0666;
- t['afii57399'] = 0x0667;
- t['afii57400'] = 0x0668;
- t['afii57401'] = 0x0669;
- t['afii57403'] = 0x061B;
- t['afii57407'] = 0x061F;
- t['afii57409'] = 0x0621;
- t['afii57410'] = 0x0622;
- t['afii57411'] = 0x0623;
- t['afii57412'] = 0x0624;
- t['afii57413'] = 0x0625;
- t['afii57414'] = 0x0626;
- t['afii57415'] = 0x0627;
- t['afii57416'] = 0x0628;
- t['afii57417'] = 0x0629;
- t['afii57418'] = 0x062A;
- t['afii57419'] = 0x062B;
- t['afii57420'] = 0x062C;
- t['afii57421'] = 0x062D;
- t['afii57422'] = 0x062E;
- t['afii57423'] = 0x062F;
- t['afii57424'] = 0x0630;
- t['afii57425'] = 0x0631;
- t['afii57426'] = 0x0632;
- t['afii57427'] = 0x0633;
- t['afii57428'] = 0x0634;
- t['afii57429'] = 0x0635;
- t['afii57430'] = 0x0636;
- t['afii57431'] = 0x0637;
- t['afii57432'] = 0x0638;
- t['afii57433'] = 0x0639;
- t['afii57434'] = 0x063A;
- t['afii57440'] = 0x0640;
- t['afii57441'] = 0x0641;
- t['afii57442'] = 0x0642;
- t['afii57443'] = 0x0643;
- t['afii57444'] = 0x0644;
- t['afii57445'] = 0x0645;
- t['afii57446'] = 0x0646;
- t['afii57448'] = 0x0648;
- t['afii57449'] = 0x0649;
- t['afii57450'] = 0x064A;
- t['afii57451'] = 0x064B;
- t['afii57452'] = 0x064C;
- t['afii57453'] = 0x064D;
- t['afii57454'] = 0x064E;
- t['afii57455'] = 0x064F;
- t['afii57456'] = 0x0650;
- t['afii57457'] = 0x0651;
- t['afii57458'] = 0x0652;
- t['afii57470'] = 0x0647;
- t['afii57505'] = 0x06A4;
- t['afii57506'] = 0x067E;
- t['afii57507'] = 0x0686;
- t['afii57508'] = 0x0698;
- t['afii57509'] = 0x06AF;
- t['afii57511'] = 0x0679;
- t['afii57512'] = 0x0688;
- t['afii57513'] = 0x0691;
- t['afii57514'] = 0x06BA;
- t['afii57519'] = 0x06D2;
- t['afii57534'] = 0x06D5;
- t['afii57636'] = 0x20AA;
- t['afii57645'] = 0x05BE;
- t['afii57658'] = 0x05C3;
- t['afii57664'] = 0x05D0;
- t['afii57665'] = 0x05D1;
- t['afii57666'] = 0x05D2;
- t['afii57667'] = 0x05D3;
- t['afii57668'] = 0x05D4;
- t['afii57669'] = 0x05D5;
- t['afii57670'] = 0x05D6;
- t['afii57671'] = 0x05D7;
- t['afii57672'] = 0x05D8;
- t['afii57673'] = 0x05D9;
- t['afii57674'] = 0x05DA;
- t['afii57675'] = 0x05DB;
- t['afii57676'] = 0x05DC;
- t['afii57677'] = 0x05DD;
- t['afii57678'] = 0x05DE;
- t['afii57679'] = 0x05DF;
- t['afii57680'] = 0x05E0;
- t['afii57681'] = 0x05E1;
- t['afii57682'] = 0x05E2;
- t['afii57683'] = 0x05E3;
- t['afii57684'] = 0x05E4;
- t['afii57685'] = 0x05E5;
- t['afii57686'] = 0x05E6;
- t['afii57687'] = 0x05E7;
- t['afii57688'] = 0x05E8;
- t['afii57689'] = 0x05E9;
- t['afii57690'] = 0x05EA;
- t['afii57694'] = 0xFB2A;
- t['afii57695'] = 0xFB2B;
- t['afii57700'] = 0xFB4B;
- t['afii57705'] = 0xFB1F;
- t['afii57716'] = 0x05F0;
- t['afii57717'] = 0x05F1;
- t['afii57718'] = 0x05F2;
- t['afii57723'] = 0xFB35;
- t['afii57793'] = 0x05B4;
- t['afii57794'] = 0x05B5;
- t['afii57795'] = 0x05B6;
- t['afii57796'] = 0x05BB;
- t['afii57797'] = 0x05B8;
- t['afii57798'] = 0x05B7;
- t['afii57799'] = 0x05B0;
- t['afii57800'] = 0x05B2;
- t['afii57801'] = 0x05B1;
- t['afii57802'] = 0x05B3;
- t['afii57803'] = 0x05C2;
- t['afii57804'] = 0x05C1;
- t['afii57806'] = 0x05B9;
- t['afii57807'] = 0x05BC;
- t['afii57839'] = 0x05BD;
- t['afii57841'] = 0x05BF;
- t['afii57842'] = 0x05C0;
- t['afii57929'] = 0x02BC;
- t['afii61248'] = 0x2105;
- t['afii61289'] = 0x2113;
- t['afii61352'] = 0x2116;
- t['afii61573'] = 0x202C;
- t['afii61574'] = 0x202D;
- t['afii61575'] = 0x202E;
- t['afii61664'] = 0x200C;
- t['afii63167'] = 0x066D;
- t['afii64937'] = 0x02BD;
- t['agrave'] = 0x00E0;
- t['agujarati'] = 0x0A85;
- t['agurmukhi'] = 0x0A05;
- t['ahiragana'] = 0x3042;
- t['ahookabove'] = 0x1EA3;
- t['aibengali'] = 0x0990;
- t['aibopomofo'] = 0x311E;
- t['aideva'] = 0x0910;
- t['aiecyrillic'] = 0x04D5;
- t['aigujarati'] = 0x0A90;
- t['aigurmukhi'] = 0x0A10;
- t['aimatragurmukhi'] = 0x0A48;
- t['ainarabic'] = 0x0639;
- t['ainfinalarabic'] = 0xFECA;
- t['aininitialarabic'] = 0xFECB;
- t['ainmedialarabic'] = 0xFECC;
- t['ainvertedbreve'] = 0x0203;
- t['aivowelsignbengali'] = 0x09C8;
- t['aivowelsigndeva'] = 0x0948;
- t['aivowelsigngujarati'] = 0x0AC8;
- t['akatakana'] = 0x30A2;
- t['akatakanahalfwidth'] = 0xFF71;
- t['akorean'] = 0x314F;
- t['alef'] = 0x05D0;
- t['alefarabic'] = 0x0627;
- t['alefdageshhebrew'] = 0xFB30;
- t['aleffinalarabic'] = 0xFE8E;
- t['alefhamzaabovearabic'] = 0x0623;
- t['alefhamzaabovefinalarabic'] = 0xFE84;
- t['alefhamzabelowarabic'] = 0x0625;
- t['alefhamzabelowfinalarabic'] = 0xFE88;
- t['alefhebrew'] = 0x05D0;
- t['aleflamedhebrew'] = 0xFB4F;
- t['alefmaddaabovearabic'] = 0x0622;
- t['alefmaddaabovefinalarabic'] = 0xFE82;
- t['alefmaksuraarabic'] = 0x0649;
- t['alefmaksurafinalarabic'] = 0xFEF0;
- t['alefmaksurainitialarabic'] = 0xFEF3;
- t['alefmaksuramedialarabic'] = 0xFEF4;
- t['alefpatahhebrew'] = 0xFB2E;
- t['alefqamatshebrew'] = 0xFB2F;
- t['aleph'] = 0x2135;
- t['allequal'] = 0x224C;
- t['alpha'] = 0x03B1;
- t['alphatonos'] = 0x03AC;
- t['amacron'] = 0x0101;
- t['amonospace'] = 0xFF41;
- t['ampersand'] = 0x0026;
- t['ampersandmonospace'] = 0xFF06;
- t['ampersandsmall'] = 0xF726;
- t['amsquare'] = 0x33C2;
- t['anbopomofo'] = 0x3122;
- t['angbopomofo'] = 0x3124;
- t['angbracketleft'] = 0x3008;
- t['angbracketright'] = 0x3009;
- t['angkhankhuthai'] = 0x0E5A;
- t['angle'] = 0x2220;
- t['anglebracketleft'] = 0x3008;
- t['anglebracketleftvertical'] = 0xFE3F;
- t['anglebracketright'] = 0x3009;
- t['anglebracketrightvertical'] = 0xFE40;
- t['angleleft'] = 0x2329;
- t['angleright'] = 0x232A;
- t['angstrom'] = 0x212B;
- t['anoteleia'] = 0x0387;
- t['anudattadeva'] = 0x0952;
- t['anusvarabengali'] = 0x0982;
- t['anusvaradeva'] = 0x0902;
- t['anusvaragujarati'] = 0x0A82;
- t['aogonek'] = 0x0105;
- t['apaatosquare'] = 0x3300;
- t['aparen'] = 0x249C;
- t['apostrophearmenian'] = 0x055A;
- t['apostrophemod'] = 0x02BC;
- t['apple'] = 0xF8FF;
- t['approaches'] = 0x2250;
- t['approxequal'] = 0x2248;
- t['approxequalorimage'] = 0x2252;
- t['approximatelyequal'] = 0x2245;
- t['araeaekorean'] = 0x318E;
- t['araeakorean'] = 0x318D;
- t['arc'] = 0x2312;
- t['arighthalfring'] = 0x1E9A;
- t['aring'] = 0x00E5;
- t['aringacute'] = 0x01FB;
- t['aringbelow'] = 0x1E01;
- t['arrowboth'] = 0x2194;
- t['arrowdashdown'] = 0x21E3;
- t['arrowdashleft'] = 0x21E0;
- t['arrowdashright'] = 0x21E2;
- t['arrowdashup'] = 0x21E1;
- t['arrowdblboth'] = 0x21D4;
- t['arrowdbldown'] = 0x21D3;
- t['arrowdblleft'] = 0x21D0;
- t['arrowdblright'] = 0x21D2;
- t['arrowdblup'] = 0x21D1;
- t['arrowdown'] = 0x2193;
- t['arrowdownleft'] = 0x2199;
- t['arrowdownright'] = 0x2198;
- t['arrowdownwhite'] = 0x21E9;
- t['arrowheaddownmod'] = 0x02C5;
- t['arrowheadleftmod'] = 0x02C2;
- t['arrowheadrightmod'] = 0x02C3;
- t['arrowheadupmod'] = 0x02C4;
- t['arrowhorizex'] = 0xF8E7;
- t['arrowleft'] = 0x2190;
- t['arrowleftdbl'] = 0x21D0;
- t['arrowleftdblstroke'] = 0x21CD;
- t['arrowleftoverright'] = 0x21C6;
- t['arrowleftwhite'] = 0x21E6;
- t['arrowright'] = 0x2192;
- t['arrowrightdblstroke'] = 0x21CF;
- t['arrowrightheavy'] = 0x279E;
- t['arrowrightoverleft'] = 0x21C4;
- t['arrowrightwhite'] = 0x21E8;
- t['arrowtableft'] = 0x21E4;
- t['arrowtabright'] = 0x21E5;
- t['arrowup'] = 0x2191;
- t['arrowupdn'] = 0x2195;
- t['arrowupdnbse'] = 0x21A8;
- t['arrowupdownbase'] = 0x21A8;
- t['arrowupleft'] = 0x2196;
- t['arrowupleftofdown'] = 0x21C5;
- t['arrowupright'] = 0x2197;
- t['arrowupwhite'] = 0x21E7;
- t['arrowvertex'] = 0xF8E6;
- t['asciicircum'] = 0x005E;
- t['asciicircummonospace'] = 0xFF3E;
- t['asciitilde'] = 0x007E;
- t['asciitildemonospace'] = 0xFF5E;
- t['ascript'] = 0x0251;
- t['ascriptturned'] = 0x0252;
- t['asmallhiragana'] = 0x3041;
- t['asmallkatakana'] = 0x30A1;
- t['asmallkatakanahalfwidth'] = 0xFF67;
- t['asterisk'] = 0x002A;
- t['asteriskaltonearabic'] = 0x066D;
- t['asteriskarabic'] = 0x066D;
- t['asteriskmath'] = 0x2217;
- t['asteriskmonospace'] = 0xFF0A;
- t['asterisksmall'] = 0xFE61;
- t['asterism'] = 0x2042;
- t['asuperior'] = 0xF6E9;
- t['asymptoticallyequal'] = 0x2243;
- t['at'] = 0x0040;
- t['atilde'] = 0x00E3;
- t['atmonospace'] = 0xFF20;
- t['atsmall'] = 0xFE6B;
- t['aturned'] = 0x0250;
- t['aubengali'] = 0x0994;
- t['aubopomofo'] = 0x3120;
- t['audeva'] = 0x0914;
- t['augujarati'] = 0x0A94;
- t['augurmukhi'] = 0x0A14;
- t['aulengthmarkbengali'] = 0x09D7;
- t['aumatragurmukhi'] = 0x0A4C;
- t['auvowelsignbengali'] = 0x09CC;
- t['auvowelsigndeva'] = 0x094C;
- t['auvowelsigngujarati'] = 0x0ACC;
- t['avagrahadeva'] = 0x093D;
- t['aybarmenian'] = 0x0561;
- t['ayin'] = 0x05E2;
- t['ayinaltonehebrew'] = 0xFB20;
- t['ayinhebrew'] = 0x05E2;
- t['b'] = 0x0062;
- t['babengali'] = 0x09AC;
- t['backslash'] = 0x005C;
- t['backslashmonospace'] = 0xFF3C;
- t['badeva'] = 0x092C;
- t['bagujarati'] = 0x0AAC;
- t['bagurmukhi'] = 0x0A2C;
- t['bahiragana'] = 0x3070;
- t['bahtthai'] = 0x0E3F;
- t['bakatakana'] = 0x30D0;
- t['bar'] = 0x007C;
- t['barmonospace'] = 0xFF5C;
- t['bbopomofo'] = 0x3105;
- t['bcircle'] = 0x24D1;
- t['bdotaccent'] = 0x1E03;
- t['bdotbelow'] = 0x1E05;
- t['beamedsixteenthnotes'] = 0x266C;
- t['because'] = 0x2235;
- t['becyrillic'] = 0x0431;
- t['beharabic'] = 0x0628;
- t['behfinalarabic'] = 0xFE90;
- t['behinitialarabic'] = 0xFE91;
- t['behiragana'] = 0x3079;
- t['behmedialarabic'] = 0xFE92;
- t['behmeeminitialarabic'] = 0xFC9F;
- t['behmeemisolatedarabic'] = 0xFC08;
- t['behnoonfinalarabic'] = 0xFC6D;
- t['bekatakana'] = 0x30D9;
- t['benarmenian'] = 0x0562;
- t['bet'] = 0x05D1;
- t['beta'] = 0x03B2;
- t['betasymbolgreek'] = 0x03D0;
- t['betdagesh'] = 0xFB31;
- t['betdageshhebrew'] = 0xFB31;
- t['bethebrew'] = 0x05D1;
- t['betrafehebrew'] = 0xFB4C;
- t['bhabengali'] = 0x09AD;
- t['bhadeva'] = 0x092D;
- t['bhagujarati'] = 0x0AAD;
- t['bhagurmukhi'] = 0x0A2D;
- t['bhook'] = 0x0253;
- t['bihiragana'] = 0x3073;
- t['bikatakana'] = 0x30D3;
- t['bilabialclick'] = 0x0298;
- t['bindigurmukhi'] = 0x0A02;
- t['birusquare'] = 0x3331;
- t['blackcircle'] = 0x25CF;
- t['blackdiamond'] = 0x25C6;
- t['blackdownpointingtriangle'] = 0x25BC;
- t['blackleftpointingpointer'] = 0x25C4;
- t['blackleftpointingtriangle'] = 0x25C0;
- t['blacklenticularbracketleft'] = 0x3010;
- t['blacklenticularbracketleftvertical'] = 0xFE3B;
- t['blacklenticularbracketright'] = 0x3011;
- t['blacklenticularbracketrightvertical'] = 0xFE3C;
- t['blacklowerlefttriangle'] = 0x25E3;
- t['blacklowerrighttriangle'] = 0x25E2;
- t['blackrectangle'] = 0x25AC;
- t['blackrightpointingpointer'] = 0x25BA;
- t['blackrightpointingtriangle'] = 0x25B6;
- t['blacksmallsquare'] = 0x25AA;
- t['blacksmilingface'] = 0x263B;
- t['blacksquare'] = 0x25A0;
- t['blackstar'] = 0x2605;
- t['blackupperlefttriangle'] = 0x25E4;
- t['blackupperrighttriangle'] = 0x25E5;
- t['blackuppointingsmalltriangle'] = 0x25B4;
- t['blackuppointingtriangle'] = 0x25B2;
- t['blank'] = 0x2423;
- t['blinebelow'] = 0x1E07;
- t['block'] = 0x2588;
- t['bmonospace'] = 0xFF42;
- t['bobaimaithai'] = 0x0E1A;
- t['bohiragana'] = 0x307C;
- t['bokatakana'] = 0x30DC;
- t['bparen'] = 0x249D;
- t['bqsquare'] = 0x33C3;
- t['braceex'] = 0xF8F4;
- t['braceleft'] = 0x007B;
- t['braceleftbt'] = 0xF8F3;
- t['braceleftmid'] = 0xF8F2;
- t['braceleftmonospace'] = 0xFF5B;
- t['braceleftsmall'] = 0xFE5B;
- t['bracelefttp'] = 0xF8F1;
- t['braceleftvertical'] = 0xFE37;
- t['braceright'] = 0x007D;
- t['bracerightbt'] = 0xF8FE;
- t['bracerightmid'] = 0xF8FD;
- t['bracerightmonospace'] = 0xFF5D;
- t['bracerightsmall'] = 0xFE5C;
- t['bracerighttp'] = 0xF8FC;
- t['bracerightvertical'] = 0xFE38;
- t['bracketleft'] = 0x005B;
- t['bracketleftbt'] = 0xF8F0;
- t['bracketleftex'] = 0xF8EF;
- t['bracketleftmonospace'] = 0xFF3B;
- t['bracketlefttp'] = 0xF8EE;
- t['bracketright'] = 0x005D;
- t['bracketrightbt'] = 0xF8FB;
- t['bracketrightex'] = 0xF8FA;
- t['bracketrightmonospace'] = 0xFF3D;
- t['bracketrighttp'] = 0xF8F9;
- t['breve'] = 0x02D8;
- t['brevebelowcmb'] = 0x032E;
- t['brevecmb'] = 0x0306;
- t['breveinvertedbelowcmb'] = 0x032F;
- t['breveinvertedcmb'] = 0x0311;
- t['breveinverteddoublecmb'] = 0x0361;
- t['bridgebelowcmb'] = 0x032A;
- t['bridgeinvertedbelowcmb'] = 0x033A;
- t['brokenbar'] = 0x00A6;
- t['bstroke'] = 0x0180;
- t['bsuperior'] = 0xF6EA;
- t['btopbar'] = 0x0183;
- t['buhiragana'] = 0x3076;
- t['bukatakana'] = 0x30D6;
- t['bullet'] = 0x2022;
- t['bulletinverse'] = 0x25D8;
- t['bulletoperator'] = 0x2219;
- t['bullseye'] = 0x25CE;
- t['c'] = 0x0063;
- t['caarmenian'] = 0x056E;
- t['cabengali'] = 0x099A;
- t['cacute'] = 0x0107;
- t['cadeva'] = 0x091A;
- t['cagujarati'] = 0x0A9A;
- t['cagurmukhi'] = 0x0A1A;
- t['calsquare'] = 0x3388;
- t['candrabindubengali'] = 0x0981;
- t['candrabinducmb'] = 0x0310;
- t['candrabindudeva'] = 0x0901;
- t['candrabindugujarati'] = 0x0A81;
- t['capslock'] = 0x21EA;
- t['careof'] = 0x2105;
- t['caron'] = 0x02C7;
- t['caronbelowcmb'] = 0x032C;
- t['caroncmb'] = 0x030C;
- t['carriagereturn'] = 0x21B5;
- t['cbopomofo'] = 0x3118;
- t['ccaron'] = 0x010D;
- t['ccedilla'] = 0x00E7;
- t['ccedillaacute'] = 0x1E09;
- t['ccircle'] = 0x24D2;
- t['ccircumflex'] = 0x0109;
- t['ccurl'] = 0x0255;
- t['cdot'] = 0x010B;
- t['cdotaccent'] = 0x010B;
- t['cdsquare'] = 0x33C5;
- t['cedilla'] = 0x00B8;
- t['cedillacmb'] = 0x0327;
- t['cent'] = 0x00A2;
- t['centigrade'] = 0x2103;
- t['centinferior'] = 0xF6DF;
- t['centmonospace'] = 0xFFE0;
- t['centoldstyle'] = 0xF7A2;
- t['centsuperior'] = 0xF6E0;
- t['chaarmenian'] = 0x0579;
- t['chabengali'] = 0x099B;
- t['chadeva'] = 0x091B;
- t['chagujarati'] = 0x0A9B;
- t['chagurmukhi'] = 0x0A1B;
- t['chbopomofo'] = 0x3114;
- t['cheabkhasiancyrillic'] = 0x04BD;
- t['checkmark'] = 0x2713;
- t['checyrillic'] = 0x0447;
- t['chedescenderabkhasiancyrillic'] = 0x04BF;
- t['chedescendercyrillic'] = 0x04B7;
- t['chedieresiscyrillic'] = 0x04F5;
- t['cheharmenian'] = 0x0573;
- t['chekhakassiancyrillic'] = 0x04CC;
- t['cheverticalstrokecyrillic'] = 0x04B9;
- t['chi'] = 0x03C7;
- t['chieuchacirclekorean'] = 0x3277;
- t['chieuchaparenkorean'] = 0x3217;
- t['chieuchcirclekorean'] = 0x3269;
- t['chieuchkorean'] = 0x314A;
- t['chieuchparenkorean'] = 0x3209;
- t['chochangthai'] = 0x0E0A;
- t['chochanthai'] = 0x0E08;
- t['chochingthai'] = 0x0E09;
- t['chochoethai'] = 0x0E0C;
- t['chook'] = 0x0188;
- t['cieucacirclekorean'] = 0x3276;
- t['cieucaparenkorean'] = 0x3216;
- t['cieuccirclekorean'] = 0x3268;
- t['cieuckorean'] = 0x3148;
- t['cieucparenkorean'] = 0x3208;
- t['cieucuparenkorean'] = 0x321C;
- t['circle'] = 0x25CB;
- t['circlecopyrt'] = 0x00A9;
- t['circlemultiply'] = 0x2297;
- t['circleot'] = 0x2299;
- t['circleplus'] = 0x2295;
- t['circlepostalmark'] = 0x3036;
- t['circlewithlefthalfblack'] = 0x25D0;
- t['circlewithrighthalfblack'] = 0x25D1;
- t['circumflex'] = 0x02C6;
- t['circumflexbelowcmb'] = 0x032D;
- t['circumflexcmb'] = 0x0302;
- t['clear'] = 0x2327;
- t['clickalveolar'] = 0x01C2;
- t['clickdental'] = 0x01C0;
- t['clicklateral'] = 0x01C1;
- t['clickretroflex'] = 0x01C3;
- t['club'] = 0x2663;
- t['clubsuitblack'] = 0x2663;
- t['clubsuitwhite'] = 0x2667;
- t['cmcubedsquare'] = 0x33A4;
- t['cmonospace'] = 0xFF43;
- t['cmsquaredsquare'] = 0x33A0;
- t['coarmenian'] = 0x0581;
- t['colon'] = 0x003A;
- t['colonmonetary'] = 0x20A1;
- t['colonmonospace'] = 0xFF1A;
- t['colonsign'] = 0x20A1;
- t['colonsmall'] = 0xFE55;
- t['colontriangularhalfmod'] = 0x02D1;
- t['colontriangularmod'] = 0x02D0;
- t['comma'] = 0x002C;
- t['commaabovecmb'] = 0x0313;
- t['commaaboverightcmb'] = 0x0315;
- t['commaaccent'] = 0xF6C3;
- t['commaarabic'] = 0x060C;
- t['commaarmenian'] = 0x055D;
- t['commainferior'] = 0xF6E1;
- t['commamonospace'] = 0xFF0C;
- t['commareversedabovecmb'] = 0x0314;
- t['commareversedmod'] = 0x02BD;
- t['commasmall'] = 0xFE50;
- t['commasuperior'] = 0xF6E2;
- t['commaturnedabovecmb'] = 0x0312;
- t['commaturnedmod'] = 0x02BB;
- t['compass'] = 0x263C;
- t['congruent'] = 0x2245;
- t['contourintegral'] = 0x222E;
- t['control'] = 0x2303;
- t['controlACK'] = 0x0006;
- t['controlBEL'] = 0x0007;
- t['controlBS'] = 0x0008;
- t['controlCAN'] = 0x0018;
- t['controlCR'] = 0x000D;
- t['controlDC1'] = 0x0011;
- t['controlDC2'] = 0x0012;
- t['controlDC3'] = 0x0013;
- t['controlDC4'] = 0x0014;
- t['controlDEL'] = 0x007F;
- t['controlDLE'] = 0x0010;
- t['controlEM'] = 0x0019;
- t['controlENQ'] = 0x0005;
- t['controlEOT'] = 0x0004;
- t['controlESC'] = 0x001B;
- t['controlETB'] = 0x0017;
- t['controlETX'] = 0x0003;
- t['controlFF'] = 0x000C;
- t['controlFS'] = 0x001C;
- t['controlGS'] = 0x001D;
- t['controlHT'] = 0x0009;
- t['controlLF'] = 0x000A;
- t['controlNAK'] = 0x0015;
- t['controlNULL'] = 0x0000;
- t['controlRS'] = 0x001E;
- t['controlSI'] = 0x000F;
- t['controlSO'] = 0x000E;
- t['controlSOT'] = 0x0002;
- t['controlSTX'] = 0x0001;
- t['controlSUB'] = 0x001A;
- t['controlSYN'] = 0x0016;
- t['controlUS'] = 0x001F;
- t['controlVT'] = 0x000B;
- t['copyright'] = 0x00A9;
- t['copyrightsans'] = 0xF8E9;
- t['copyrightserif'] = 0xF6D9;
- t['cornerbracketleft'] = 0x300C;
- t['cornerbracketlefthalfwidth'] = 0xFF62;
- t['cornerbracketleftvertical'] = 0xFE41;
- t['cornerbracketright'] = 0x300D;
- t['cornerbracketrighthalfwidth'] = 0xFF63;
- t['cornerbracketrightvertical'] = 0xFE42;
- t['corporationsquare'] = 0x337F;
- t['cosquare'] = 0x33C7;
- t['coverkgsquare'] = 0x33C6;
- t['cparen'] = 0x249E;
- t['cruzeiro'] = 0x20A2;
- t['cstretched'] = 0x0297;
- t['curlyand'] = 0x22CF;
- t['curlyor'] = 0x22CE;
- t['currency'] = 0x00A4;
- t['cyrBreve'] = 0xF6D1;
- t['cyrFlex'] = 0xF6D2;
- t['cyrbreve'] = 0xF6D4;
- t['cyrflex'] = 0xF6D5;
- t['d'] = 0x0064;
- t['daarmenian'] = 0x0564;
- t['dabengali'] = 0x09A6;
- t['dadarabic'] = 0x0636;
- t['dadeva'] = 0x0926;
- t['dadfinalarabic'] = 0xFEBE;
- t['dadinitialarabic'] = 0xFEBF;
- t['dadmedialarabic'] = 0xFEC0;
- t['dagesh'] = 0x05BC;
- t['dageshhebrew'] = 0x05BC;
- t['dagger'] = 0x2020;
- t['daggerdbl'] = 0x2021;
- t['dagujarati'] = 0x0AA6;
- t['dagurmukhi'] = 0x0A26;
- t['dahiragana'] = 0x3060;
- t['dakatakana'] = 0x30C0;
- t['dalarabic'] = 0x062F;
- t['dalet'] = 0x05D3;
- t['daletdagesh'] = 0xFB33;
- t['daletdageshhebrew'] = 0xFB33;
- t['dalethebrew'] = 0x05D3;
- t['dalfinalarabic'] = 0xFEAA;
- t['dammaarabic'] = 0x064F;
- t['dammalowarabic'] = 0x064F;
- t['dammatanaltonearabic'] = 0x064C;
- t['dammatanarabic'] = 0x064C;
- t['danda'] = 0x0964;
- t['dargahebrew'] = 0x05A7;
- t['dargalefthebrew'] = 0x05A7;
- t['dasiapneumatacyrilliccmb'] = 0x0485;
- t['dblGrave'] = 0xF6D3;
- t['dblanglebracketleft'] = 0x300A;
- t['dblanglebracketleftvertical'] = 0xFE3D;
- t['dblanglebracketright'] = 0x300B;
- t['dblanglebracketrightvertical'] = 0xFE3E;
- t['dblarchinvertedbelowcmb'] = 0x032B;
- t['dblarrowleft'] = 0x21D4;
- t['dblarrowright'] = 0x21D2;
- t['dbldanda'] = 0x0965;
- t['dblgrave'] = 0xF6D6;
- t['dblgravecmb'] = 0x030F;
- t['dblintegral'] = 0x222C;
- t['dbllowline'] = 0x2017;
- t['dbllowlinecmb'] = 0x0333;
- t['dbloverlinecmb'] = 0x033F;
- t['dblprimemod'] = 0x02BA;
- t['dblverticalbar'] = 0x2016;
- t['dblverticallineabovecmb'] = 0x030E;
- t['dbopomofo'] = 0x3109;
- t['dbsquare'] = 0x33C8;
- t['dcaron'] = 0x010F;
- t['dcedilla'] = 0x1E11;
- t['dcircle'] = 0x24D3;
- t['dcircumflexbelow'] = 0x1E13;
- t['dcroat'] = 0x0111;
- t['ddabengali'] = 0x09A1;
- t['ddadeva'] = 0x0921;
- t['ddagujarati'] = 0x0AA1;
- t['ddagurmukhi'] = 0x0A21;
- t['ddalarabic'] = 0x0688;
- t['ddalfinalarabic'] = 0xFB89;
- t['dddhadeva'] = 0x095C;
- t['ddhabengali'] = 0x09A2;
- t['ddhadeva'] = 0x0922;
- t['ddhagujarati'] = 0x0AA2;
- t['ddhagurmukhi'] = 0x0A22;
- t['ddotaccent'] = 0x1E0B;
- t['ddotbelow'] = 0x1E0D;
- t['decimalseparatorarabic'] = 0x066B;
- t['decimalseparatorpersian'] = 0x066B;
- t['decyrillic'] = 0x0434;
- t['degree'] = 0x00B0;
- t['dehihebrew'] = 0x05AD;
- t['dehiragana'] = 0x3067;
- t['deicoptic'] = 0x03EF;
- t['dekatakana'] = 0x30C7;
- t['deleteleft'] = 0x232B;
- t['deleteright'] = 0x2326;
- t['delta'] = 0x03B4;
- t['deltaturned'] = 0x018D;
- t['denominatorminusonenumeratorbengali'] = 0x09F8;
- t['dezh'] = 0x02A4;
- t['dhabengali'] = 0x09A7;
- t['dhadeva'] = 0x0927;
- t['dhagujarati'] = 0x0AA7;
- t['dhagurmukhi'] = 0x0A27;
- t['dhook'] = 0x0257;
- t['dialytikatonos'] = 0x0385;
- t['dialytikatonoscmb'] = 0x0344;
- t['diamond'] = 0x2666;
- t['diamondsuitwhite'] = 0x2662;
- t['dieresis'] = 0x00A8;
- t['dieresisacute'] = 0xF6D7;
- t['dieresisbelowcmb'] = 0x0324;
- t['dieresiscmb'] = 0x0308;
- t['dieresisgrave'] = 0xF6D8;
- t['dieresistonos'] = 0x0385;
- t['dihiragana'] = 0x3062;
- t['dikatakana'] = 0x30C2;
- t['dittomark'] = 0x3003;
- t['divide'] = 0x00F7;
- t['divides'] = 0x2223;
- t['divisionslash'] = 0x2215;
- t['djecyrillic'] = 0x0452;
- t['dkshade'] = 0x2593;
- t['dlinebelow'] = 0x1E0F;
- t['dlsquare'] = 0x3397;
- t['dmacron'] = 0x0111;
- t['dmonospace'] = 0xFF44;
- t['dnblock'] = 0x2584;
- t['dochadathai'] = 0x0E0E;
- t['dodekthai'] = 0x0E14;
- t['dohiragana'] = 0x3069;
- t['dokatakana'] = 0x30C9;
- t['dollar'] = 0x0024;
- t['dollarinferior'] = 0xF6E3;
- t['dollarmonospace'] = 0xFF04;
- t['dollaroldstyle'] = 0xF724;
- t['dollarsmall'] = 0xFE69;
- t['dollarsuperior'] = 0xF6E4;
- t['dong'] = 0x20AB;
- t['dorusquare'] = 0x3326;
- t['dotaccent'] = 0x02D9;
- t['dotaccentcmb'] = 0x0307;
- t['dotbelowcmb'] = 0x0323;
- t['dotbelowcomb'] = 0x0323;
- t['dotkatakana'] = 0x30FB;
- t['dotlessi'] = 0x0131;
- t['dotlessj'] = 0xF6BE;
- t['dotlessjstrokehook'] = 0x0284;
- t['dotmath'] = 0x22C5;
- t['dottedcircle'] = 0x25CC;
- t['doubleyodpatah'] = 0xFB1F;
- t['doubleyodpatahhebrew'] = 0xFB1F;
- t['downtackbelowcmb'] = 0x031E;
- t['downtackmod'] = 0x02D5;
- t['dparen'] = 0x249F;
- t['dsuperior'] = 0xF6EB;
- t['dtail'] = 0x0256;
- t['dtopbar'] = 0x018C;
- t['duhiragana'] = 0x3065;
- t['dukatakana'] = 0x30C5;
- t['dz'] = 0x01F3;
- t['dzaltone'] = 0x02A3;
- t['dzcaron'] = 0x01C6;
- t['dzcurl'] = 0x02A5;
- t['dzeabkhasiancyrillic'] = 0x04E1;
- t['dzecyrillic'] = 0x0455;
- t['dzhecyrillic'] = 0x045F;
- t['e'] = 0x0065;
- t['eacute'] = 0x00E9;
- t['earth'] = 0x2641;
- t['ebengali'] = 0x098F;
- t['ebopomofo'] = 0x311C;
- t['ebreve'] = 0x0115;
- t['ecandradeva'] = 0x090D;
- t['ecandragujarati'] = 0x0A8D;
- t['ecandravowelsigndeva'] = 0x0945;
- t['ecandravowelsigngujarati'] = 0x0AC5;
- t['ecaron'] = 0x011B;
- t['ecedillabreve'] = 0x1E1D;
- t['echarmenian'] = 0x0565;
- t['echyiwnarmenian'] = 0x0587;
- t['ecircle'] = 0x24D4;
- t['ecircumflex'] = 0x00EA;
- t['ecircumflexacute'] = 0x1EBF;
- t['ecircumflexbelow'] = 0x1E19;
- t['ecircumflexdotbelow'] = 0x1EC7;
- t['ecircumflexgrave'] = 0x1EC1;
- t['ecircumflexhookabove'] = 0x1EC3;
- t['ecircumflextilde'] = 0x1EC5;
- t['ecyrillic'] = 0x0454;
- t['edblgrave'] = 0x0205;
- t['edeva'] = 0x090F;
- t['edieresis'] = 0x00EB;
- t['edot'] = 0x0117;
- t['edotaccent'] = 0x0117;
- t['edotbelow'] = 0x1EB9;
- t['eegurmukhi'] = 0x0A0F;
- t['eematragurmukhi'] = 0x0A47;
- t['efcyrillic'] = 0x0444;
- t['egrave'] = 0x00E8;
- t['egujarati'] = 0x0A8F;
- t['eharmenian'] = 0x0567;
- t['ehbopomofo'] = 0x311D;
- t['ehiragana'] = 0x3048;
- t['ehookabove'] = 0x1EBB;
- t['eibopomofo'] = 0x311F;
- t['eight'] = 0x0038;
- t['eightarabic'] = 0x0668;
- t['eightbengali'] = 0x09EE;
- t['eightcircle'] = 0x2467;
- t['eightcircleinversesansserif'] = 0x2791;
- t['eightdeva'] = 0x096E;
- t['eighteencircle'] = 0x2471;
- t['eighteenparen'] = 0x2485;
- t['eighteenperiod'] = 0x2499;
- t['eightgujarati'] = 0x0AEE;
- t['eightgurmukhi'] = 0x0A6E;
- t['eighthackarabic'] = 0x0668;
- t['eighthangzhou'] = 0x3028;
- t['eighthnotebeamed'] = 0x266B;
- t['eightideographicparen'] = 0x3227;
- t['eightinferior'] = 0x2088;
- t['eightmonospace'] = 0xFF18;
- t['eightoldstyle'] = 0xF738;
- t['eightparen'] = 0x247B;
- t['eightperiod'] = 0x248F;
- t['eightpersian'] = 0x06F8;
- t['eightroman'] = 0x2177;
- t['eightsuperior'] = 0x2078;
- t['eightthai'] = 0x0E58;
- t['einvertedbreve'] = 0x0207;
- t['eiotifiedcyrillic'] = 0x0465;
- t['ekatakana'] = 0x30A8;
- t['ekatakanahalfwidth'] = 0xFF74;
- t['ekonkargurmukhi'] = 0x0A74;
- t['ekorean'] = 0x3154;
- t['elcyrillic'] = 0x043B;
- t['element'] = 0x2208;
- t['elevencircle'] = 0x246A;
- t['elevenparen'] = 0x247E;
- t['elevenperiod'] = 0x2492;
- t['elevenroman'] = 0x217A;
- t['ellipsis'] = 0x2026;
- t['ellipsisvertical'] = 0x22EE;
- t['emacron'] = 0x0113;
- t['emacronacute'] = 0x1E17;
- t['emacrongrave'] = 0x1E15;
- t['emcyrillic'] = 0x043C;
- t['emdash'] = 0x2014;
- t['emdashvertical'] = 0xFE31;
- t['emonospace'] = 0xFF45;
- t['emphasismarkarmenian'] = 0x055B;
- t['emptyset'] = 0x2205;
- t['enbopomofo'] = 0x3123;
- t['encyrillic'] = 0x043D;
- t['endash'] = 0x2013;
- t['endashvertical'] = 0xFE32;
- t['endescendercyrillic'] = 0x04A3;
- t['eng'] = 0x014B;
- t['engbopomofo'] = 0x3125;
- t['enghecyrillic'] = 0x04A5;
- t['enhookcyrillic'] = 0x04C8;
- t['enspace'] = 0x2002;
- t['eogonek'] = 0x0119;
- t['eokorean'] = 0x3153;
- t['eopen'] = 0x025B;
- t['eopenclosed'] = 0x029A;
- t['eopenreversed'] = 0x025C;
- t['eopenreversedclosed'] = 0x025E;
- t['eopenreversedhook'] = 0x025D;
- t['eparen'] = 0x24A0;
- t['epsilon'] = 0x03B5;
- t['epsilontonos'] = 0x03AD;
- t['equal'] = 0x003D;
- t['equalmonospace'] = 0xFF1D;
- t['equalsmall'] = 0xFE66;
- t['equalsuperior'] = 0x207C;
- t['equivalence'] = 0x2261;
- t['erbopomofo'] = 0x3126;
- t['ercyrillic'] = 0x0440;
- t['ereversed'] = 0x0258;
- t['ereversedcyrillic'] = 0x044D;
- t['escyrillic'] = 0x0441;
- t['esdescendercyrillic'] = 0x04AB;
- t['esh'] = 0x0283;
- t['eshcurl'] = 0x0286;
- t['eshortdeva'] = 0x090E;
- t['eshortvowelsigndeva'] = 0x0946;
- t['eshreversedloop'] = 0x01AA;
- t['eshsquatreversed'] = 0x0285;
- t['esmallhiragana'] = 0x3047;
- t['esmallkatakana'] = 0x30A7;
- t['esmallkatakanahalfwidth'] = 0xFF6A;
- t['estimated'] = 0x212E;
- t['esuperior'] = 0xF6EC;
- t['eta'] = 0x03B7;
- t['etarmenian'] = 0x0568;
- t['etatonos'] = 0x03AE;
- t['eth'] = 0x00F0;
- t['etilde'] = 0x1EBD;
- t['etildebelow'] = 0x1E1B;
- t['etnahtafoukhhebrew'] = 0x0591;
- t['etnahtafoukhlefthebrew'] = 0x0591;
- t['etnahtahebrew'] = 0x0591;
- t['etnahtalefthebrew'] = 0x0591;
- t['eturned'] = 0x01DD;
- t['eukorean'] = 0x3161;
- t['euro'] = 0x20AC;
- t['evowelsignbengali'] = 0x09C7;
- t['evowelsigndeva'] = 0x0947;
- t['evowelsigngujarati'] = 0x0AC7;
- t['exclam'] = 0x0021;
- t['exclamarmenian'] = 0x055C;
- t['exclamdbl'] = 0x203C;
- t['exclamdown'] = 0x00A1;
- t['exclamdownsmall'] = 0xF7A1;
- t['exclammonospace'] = 0xFF01;
- t['exclamsmall'] = 0xF721;
- t['existential'] = 0x2203;
- t['ezh'] = 0x0292;
- t['ezhcaron'] = 0x01EF;
- t['ezhcurl'] = 0x0293;
- t['ezhreversed'] = 0x01B9;
- t['ezhtail'] = 0x01BA;
- t['f'] = 0x0066;
- t['fadeva'] = 0x095E;
- t['fagurmukhi'] = 0x0A5E;
- t['fahrenheit'] = 0x2109;
- t['fathaarabic'] = 0x064E;
- t['fathalowarabic'] = 0x064E;
- t['fathatanarabic'] = 0x064B;
- t['fbopomofo'] = 0x3108;
- t['fcircle'] = 0x24D5;
- t['fdotaccent'] = 0x1E1F;
- t['feharabic'] = 0x0641;
- t['feharmenian'] = 0x0586;
- t['fehfinalarabic'] = 0xFED2;
- t['fehinitialarabic'] = 0xFED3;
- t['fehmedialarabic'] = 0xFED4;
- t['feicoptic'] = 0x03E5;
- t['female'] = 0x2640;
- t['ff'] = 0xFB00;
- t['ffi'] = 0xFB03;
- t['ffl'] = 0xFB04;
- t['fi'] = 0xFB01;
- t['fifteencircle'] = 0x246E;
- t['fifteenparen'] = 0x2482;
- t['fifteenperiod'] = 0x2496;
- t['figuredash'] = 0x2012;
- t['filledbox'] = 0x25A0;
- t['filledrect'] = 0x25AC;
- t['finalkaf'] = 0x05DA;
- t['finalkafdagesh'] = 0xFB3A;
- t['finalkafdageshhebrew'] = 0xFB3A;
- t['finalkafhebrew'] = 0x05DA;
- t['finalmem'] = 0x05DD;
- t['finalmemhebrew'] = 0x05DD;
- t['finalnun'] = 0x05DF;
- t['finalnunhebrew'] = 0x05DF;
- t['finalpe'] = 0x05E3;
- t['finalpehebrew'] = 0x05E3;
- t['finaltsadi'] = 0x05E5;
- t['finaltsadihebrew'] = 0x05E5;
- t['firsttonechinese'] = 0x02C9;
- t['fisheye'] = 0x25C9;
- t['fitacyrillic'] = 0x0473;
- t['five'] = 0x0035;
- t['fivearabic'] = 0x0665;
- t['fivebengali'] = 0x09EB;
- t['fivecircle'] = 0x2464;
- t['fivecircleinversesansserif'] = 0x278E;
- t['fivedeva'] = 0x096B;
- t['fiveeighths'] = 0x215D;
- t['fivegujarati'] = 0x0AEB;
- t['fivegurmukhi'] = 0x0A6B;
- t['fivehackarabic'] = 0x0665;
- t['fivehangzhou'] = 0x3025;
- t['fiveideographicparen'] = 0x3224;
- t['fiveinferior'] = 0x2085;
- t['fivemonospace'] = 0xFF15;
- t['fiveoldstyle'] = 0xF735;
- t['fiveparen'] = 0x2478;
- t['fiveperiod'] = 0x248C;
- t['fivepersian'] = 0x06F5;
- t['fiveroman'] = 0x2174;
- t['fivesuperior'] = 0x2075;
- t['fivethai'] = 0x0E55;
- t['fl'] = 0xFB02;
- t['florin'] = 0x0192;
- t['fmonospace'] = 0xFF46;
- t['fmsquare'] = 0x3399;
- t['fofanthai'] = 0x0E1F;
- t['fofathai'] = 0x0E1D;
- t['fongmanthai'] = 0x0E4F;
- t['forall'] = 0x2200;
- t['four'] = 0x0034;
- t['fourarabic'] = 0x0664;
- t['fourbengali'] = 0x09EA;
- t['fourcircle'] = 0x2463;
- t['fourcircleinversesansserif'] = 0x278D;
- t['fourdeva'] = 0x096A;
- t['fourgujarati'] = 0x0AEA;
- t['fourgurmukhi'] = 0x0A6A;
- t['fourhackarabic'] = 0x0664;
- t['fourhangzhou'] = 0x3024;
- t['fourideographicparen'] = 0x3223;
- t['fourinferior'] = 0x2084;
- t['fourmonospace'] = 0xFF14;
- t['fournumeratorbengali'] = 0x09F7;
- t['fouroldstyle'] = 0xF734;
- t['fourparen'] = 0x2477;
- t['fourperiod'] = 0x248B;
- t['fourpersian'] = 0x06F4;
- t['fourroman'] = 0x2173;
- t['foursuperior'] = 0x2074;
- t['fourteencircle'] = 0x246D;
- t['fourteenparen'] = 0x2481;
- t['fourteenperiod'] = 0x2495;
- t['fourthai'] = 0x0E54;
- t['fourthtonechinese'] = 0x02CB;
- t['fparen'] = 0x24A1;
- t['fraction'] = 0x2044;
- t['franc'] = 0x20A3;
- t['g'] = 0x0067;
- t['gabengali'] = 0x0997;
- t['gacute'] = 0x01F5;
- t['gadeva'] = 0x0917;
- t['gafarabic'] = 0x06AF;
- t['gaffinalarabic'] = 0xFB93;
- t['gafinitialarabic'] = 0xFB94;
- t['gafmedialarabic'] = 0xFB95;
- t['gagujarati'] = 0x0A97;
- t['gagurmukhi'] = 0x0A17;
- t['gahiragana'] = 0x304C;
- t['gakatakana'] = 0x30AC;
- t['gamma'] = 0x03B3;
- t['gammalatinsmall'] = 0x0263;
- t['gammasuperior'] = 0x02E0;
- t['gangiacoptic'] = 0x03EB;
- t['gbopomofo'] = 0x310D;
- t['gbreve'] = 0x011F;
- t['gcaron'] = 0x01E7;
- t['gcedilla'] = 0x0123;
- t['gcircle'] = 0x24D6;
- t['gcircumflex'] = 0x011D;
- t['gcommaaccent'] = 0x0123;
- t['gdot'] = 0x0121;
- t['gdotaccent'] = 0x0121;
- t['gecyrillic'] = 0x0433;
- t['gehiragana'] = 0x3052;
- t['gekatakana'] = 0x30B2;
- t['geometricallyequal'] = 0x2251;
- t['gereshaccenthebrew'] = 0x059C;
- t['gereshhebrew'] = 0x05F3;
- t['gereshmuqdamhebrew'] = 0x059D;
- t['germandbls'] = 0x00DF;
- t['gershayimaccenthebrew'] = 0x059E;
- t['gershayimhebrew'] = 0x05F4;
- t['getamark'] = 0x3013;
- t['ghabengali'] = 0x0998;
- t['ghadarmenian'] = 0x0572;
- t['ghadeva'] = 0x0918;
- t['ghagujarati'] = 0x0A98;
- t['ghagurmukhi'] = 0x0A18;
- t['ghainarabic'] = 0x063A;
- t['ghainfinalarabic'] = 0xFECE;
- t['ghaininitialarabic'] = 0xFECF;
- t['ghainmedialarabic'] = 0xFED0;
- t['ghemiddlehookcyrillic'] = 0x0495;
- t['ghestrokecyrillic'] = 0x0493;
- t['gheupturncyrillic'] = 0x0491;
- t['ghhadeva'] = 0x095A;
- t['ghhagurmukhi'] = 0x0A5A;
- t['ghook'] = 0x0260;
- t['ghzsquare'] = 0x3393;
- t['gihiragana'] = 0x304E;
- t['gikatakana'] = 0x30AE;
- t['gimarmenian'] = 0x0563;
- t['gimel'] = 0x05D2;
- t['gimeldagesh'] = 0xFB32;
- t['gimeldageshhebrew'] = 0xFB32;
- t['gimelhebrew'] = 0x05D2;
- t['gjecyrillic'] = 0x0453;
- t['glottalinvertedstroke'] = 0x01BE;
- t['glottalstop'] = 0x0294;
- t['glottalstopinverted'] = 0x0296;
- t['glottalstopmod'] = 0x02C0;
- t['glottalstopreversed'] = 0x0295;
- t['glottalstopreversedmod'] = 0x02C1;
- t['glottalstopreversedsuperior'] = 0x02E4;
- t['glottalstopstroke'] = 0x02A1;
- t['glottalstopstrokereversed'] = 0x02A2;
- t['gmacron'] = 0x1E21;
- t['gmonospace'] = 0xFF47;
- t['gohiragana'] = 0x3054;
- t['gokatakana'] = 0x30B4;
- t['gparen'] = 0x24A2;
- t['gpasquare'] = 0x33AC;
- t['gradient'] = 0x2207;
- t['grave'] = 0x0060;
- t['gravebelowcmb'] = 0x0316;
- t['gravecmb'] = 0x0300;
- t['gravecomb'] = 0x0300;
- t['gravedeva'] = 0x0953;
- t['gravelowmod'] = 0x02CE;
- t['gravemonospace'] = 0xFF40;
- t['gravetonecmb'] = 0x0340;
- t['greater'] = 0x003E;
- t['greaterequal'] = 0x2265;
- t['greaterequalorless'] = 0x22DB;
- t['greatermonospace'] = 0xFF1E;
- t['greaterorequivalent'] = 0x2273;
- t['greaterorless'] = 0x2277;
- t['greateroverequal'] = 0x2267;
- t['greatersmall'] = 0xFE65;
- t['gscript'] = 0x0261;
- t['gstroke'] = 0x01E5;
- t['guhiragana'] = 0x3050;
- t['guillemotleft'] = 0x00AB;
- t['guillemotright'] = 0x00BB;
- t['guilsinglleft'] = 0x2039;
- t['guilsinglright'] = 0x203A;
- t['gukatakana'] = 0x30B0;
- t['guramusquare'] = 0x3318;
- t['gysquare'] = 0x33C9;
- t['h'] = 0x0068;
- t['haabkhasiancyrillic'] = 0x04A9;
- t['haaltonearabic'] = 0x06C1;
- t['habengali'] = 0x09B9;
- t['hadescendercyrillic'] = 0x04B3;
- t['hadeva'] = 0x0939;
- t['hagujarati'] = 0x0AB9;
- t['hagurmukhi'] = 0x0A39;
- t['haharabic'] = 0x062D;
- t['hahfinalarabic'] = 0xFEA2;
- t['hahinitialarabic'] = 0xFEA3;
- t['hahiragana'] = 0x306F;
- t['hahmedialarabic'] = 0xFEA4;
- t['haitusquare'] = 0x332A;
- t['hakatakana'] = 0x30CF;
- t['hakatakanahalfwidth'] = 0xFF8A;
- t['halantgurmukhi'] = 0x0A4D;
- t['hamzaarabic'] = 0x0621;
- t['hamzalowarabic'] = 0x0621;
- t['hangulfiller'] = 0x3164;
- t['hardsigncyrillic'] = 0x044A;
- t['harpoonleftbarbup'] = 0x21BC;
- t['harpoonrightbarbup'] = 0x21C0;
- t['hasquare'] = 0x33CA;
- t['hatafpatah'] = 0x05B2;
- t['hatafpatah16'] = 0x05B2;
- t['hatafpatah23'] = 0x05B2;
- t['hatafpatah2f'] = 0x05B2;
- t['hatafpatahhebrew'] = 0x05B2;
- t['hatafpatahnarrowhebrew'] = 0x05B2;
- t['hatafpatahquarterhebrew'] = 0x05B2;
- t['hatafpatahwidehebrew'] = 0x05B2;
- t['hatafqamats'] = 0x05B3;
- t['hatafqamats1b'] = 0x05B3;
- t['hatafqamats28'] = 0x05B3;
- t['hatafqamats34'] = 0x05B3;
- t['hatafqamatshebrew'] = 0x05B3;
- t['hatafqamatsnarrowhebrew'] = 0x05B3;
- t['hatafqamatsquarterhebrew'] = 0x05B3;
- t['hatafqamatswidehebrew'] = 0x05B3;
- t['hatafsegol'] = 0x05B1;
- t['hatafsegol17'] = 0x05B1;
- t['hatafsegol24'] = 0x05B1;
- t['hatafsegol30'] = 0x05B1;
- t['hatafsegolhebrew'] = 0x05B1;
- t['hatafsegolnarrowhebrew'] = 0x05B1;
- t['hatafsegolquarterhebrew'] = 0x05B1;
- t['hatafsegolwidehebrew'] = 0x05B1;
- t['hbar'] = 0x0127;
- t['hbopomofo'] = 0x310F;
- t['hbrevebelow'] = 0x1E2B;
- t['hcedilla'] = 0x1E29;
- t['hcircle'] = 0x24D7;
- t['hcircumflex'] = 0x0125;
- t['hdieresis'] = 0x1E27;
- t['hdotaccent'] = 0x1E23;
- t['hdotbelow'] = 0x1E25;
- t['he'] = 0x05D4;
- t['heart'] = 0x2665;
- t['heartsuitblack'] = 0x2665;
- t['heartsuitwhite'] = 0x2661;
- t['hedagesh'] = 0xFB34;
- t['hedageshhebrew'] = 0xFB34;
- t['hehaltonearabic'] = 0x06C1;
- t['heharabic'] = 0x0647;
- t['hehebrew'] = 0x05D4;
- t['hehfinalaltonearabic'] = 0xFBA7;
- t['hehfinalalttwoarabic'] = 0xFEEA;
- t['hehfinalarabic'] = 0xFEEA;
- t['hehhamzaabovefinalarabic'] = 0xFBA5;
- t['hehhamzaaboveisolatedarabic'] = 0xFBA4;
- t['hehinitialaltonearabic'] = 0xFBA8;
- t['hehinitialarabic'] = 0xFEEB;
- t['hehiragana'] = 0x3078;
- t['hehmedialaltonearabic'] = 0xFBA9;
- t['hehmedialarabic'] = 0xFEEC;
- t['heiseierasquare'] = 0x337B;
- t['hekatakana'] = 0x30D8;
- t['hekatakanahalfwidth'] = 0xFF8D;
- t['hekutaarusquare'] = 0x3336;
- t['henghook'] = 0x0267;
- t['herutusquare'] = 0x3339;
- t['het'] = 0x05D7;
- t['hethebrew'] = 0x05D7;
- t['hhook'] = 0x0266;
- t['hhooksuperior'] = 0x02B1;
- t['hieuhacirclekorean'] = 0x327B;
- t['hieuhaparenkorean'] = 0x321B;
- t['hieuhcirclekorean'] = 0x326D;
- t['hieuhkorean'] = 0x314E;
- t['hieuhparenkorean'] = 0x320D;
- t['hihiragana'] = 0x3072;
- t['hikatakana'] = 0x30D2;
- t['hikatakanahalfwidth'] = 0xFF8B;
- t['hiriq'] = 0x05B4;
- t['hiriq14'] = 0x05B4;
- t['hiriq21'] = 0x05B4;
- t['hiriq2d'] = 0x05B4;
- t['hiriqhebrew'] = 0x05B4;
- t['hiriqnarrowhebrew'] = 0x05B4;
- t['hiriqquarterhebrew'] = 0x05B4;
- t['hiriqwidehebrew'] = 0x05B4;
- t['hlinebelow'] = 0x1E96;
- t['hmonospace'] = 0xFF48;
- t['hoarmenian'] = 0x0570;
- t['hohipthai'] = 0x0E2B;
- t['hohiragana'] = 0x307B;
- t['hokatakana'] = 0x30DB;
- t['hokatakanahalfwidth'] = 0xFF8E;
- t['holam'] = 0x05B9;
- t['holam19'] = 0x05B9;
- t['holam26'] = 0x05B9;
- t['holam32'] = 0x05B9;
- t['holamhebrew'] = 0x05B9;
- t['holamnarrowhebrew'] = 0x05B9;
- t['holamquarterhebrew'] = 0x05B9;
- t['holamwidehebrew'] = 0x05B9;
- t['honokhukthai'] = 0x0E2E;
- t['hookabovecomb'] = 0x0309;
- t['hookcmb'] = 0x0309;
- t['hookpalatalizedbelowcmb'] = 0x0321;
- t['hookretroflexbelowcmb'] = 0x0322;
- t['hoonsquare'] = 0x3342;
- t['horicoptic'] = 0x03E9;
- t['horizontalbar'] = 0x2015;
- t['horncmb'] = 0x031B;
- t['hotsprings'] = 0x2668;
- t['house'] = 0x2302;
- t['hparen'] = 0x24A3;
- t['hsuperior'] = 0x02B0;
- t['hturned'] = 0x0265;
- t['huhiragana'] = 0x3075;
- t['huiitosquare'] = 0x3333;
- t['hukatakana'] = 0x30D5;
- t['hukatakanahalfwidth'] = 0xFF8C;
- t['hungarumlaut'] = 0x02DD;
- t['hungarumlautcmb'] = 0x030B;
- t['hv'] = 0x0195;
- t['hyphen'] = 0x002D;
- t['hypheninferior'] = 0xF6E5;
- t['hyphenmonospace'] = 0xFF0D;
- t['hyphensmall'] = 0xFE63;
- t['hyphensuperior'] = 0xF6E6;
- t['hyphentwo'] = 0x2010;
- t['i'] = 0x0069;
- t['iacute'] = 0x00ED;
- t['iacyrillic'] = 0x044F;
- t['ibengali'] = 0x0987;
- t['ibopomofo'] = 0x3127;
- t['ibreve'] = 0x012D;
- t['icaron'] = 0x01D0;
- t['icircle'] = 0x24D8;
- t['icircumflex'] = 0x00EE;
- t['icyrillic'] = 0x0456;
- t['idblgrave'] = 0x0209;
- t['ideographearthcircle'] = 0x328F;
- t['ideographfirecircle'] = 0x328B;
- t['ideographicallianceparen'] = 0x323F;
- t['ideographiccallparen'] = 0x323A;
- t['ideographiccentrecircle'] = 0x32A5;
- t['ideographicclose'] = 0x3006;
- t['ideographiccomma'] = 0x3001;
- t['ideographiccommaleft'] = 0xFF64;
- t['ideographiccongratulationparen'] = 0x3237;
- t['ideographiccorrectcircle'] = 0x32A3;
- t['ideographicearthparen'] = 0x322F;
- t['ideographicenterpriseparen'] = 0x323D;
- t['ideographicexcellentcircle'] = 0x329D;
- t['ideographicfestivalparen'] = 0x3240;
- t['ideographicfinancialcircle'] = 0x3296;
- t['ideographicfinancialparen'] = 0x3236;
- t['ideographicfireparen'] = 0x322B;
- t['ideographichaveparen'] = 0x3232;
- t['ideographichighcircle'] = 0x32A4;
- t['ideographiciterationmark'] = 0x3005;
- t['ideographiclaborcircle'] = 0x3298;
- t['ideographiclaborparen'] = 0x3238;
- t['ideographicleftcircle'] = 0x32A7;
- t['ideographiclowcircle'] = 0x32A6;
- t['ideographicmedicinecircle'] = 0x32A9;
- t['ideographicmetalparen'] = 0x322E;
- t['ideographicmoonparen'] = 0x322A;
- t['ideographicnameparen'] = 0x3234;
- t['ideographicperiod'] = 0x3002;
- t['ideographicprintcircle'] = 0x329E;
- t['ideographicreachparen'] = 0x3243;
- t['ideographicrepresentparen'] = 0x3239;
- t['ideographicresourceparen'] = 0x323E;
- t['ideographicrightcircle'] = 0x32A8;
- t['ideographicsecretcircle'] = 0x3299;
- t['ideographicselfparen'] = 0x3242;
- t['ideographicsocietyparen'] = 0x3233;
- t['ideographicspace'] = 0x3000;
- t['ideographicspecialparen'] = 0x3235;
- t['ideographicstockparen'] = 0x3231;
- t['ideographicstudyparen'] = 0x323B;
- t['ideographicsunparen'] = 0x3230;
- t['ideographicsuperviseparen'] = 0x323C;
- t['ideographicwaterparen'] = 0x322C;
- t['ideographicwoodparen'] = 0x322D;
- t['ideographiczero'] = 0x3007;
- t['ideographmetalcircle'] = 0x328E;
- t['ideographmooncircle'] = 0x328A;
- t['ideographnamecircle'] = 0x3294;
- t['ideographsuncircle'] = 0x3290;
- t['ideographwatercircle'] = 0x328C;
- t['ideographwoodcircle'] = 0x328D;
- t['ideva'] = 0x0907;
- t['idieresis'] = 0x00EF;
- t['idieresisacute'] = 0x1E2F;
- t['idieresiscyrillic'] = 0x04E5;
- t['idotbelow'] = 0x1ECB;
- t['iebrevecyrillic'] = 0x04D7;
- t['iecyrillic'] = 0x0435;
- t['ieungacirclekorean'] = 0x3275;
- t['ieungaparenkorean'] = 0x3215;
- t['ieungcirclekorean'] = 0x3267;
- t['ieungkorean'] = 0x3147;
- t['ieungparenkorean'] = 0x3207;
- t['igrave'] = 0x00EC;
- t['igujarati'] = 0x0A87;
- t['igurmukhi'] = 0x0A07;
- t['ihiragana'] = 0x3044;
- t['ihookabove'] = 0x1EC9;
- t['iibengali'] = 0x0988;
- t['iicyrillic'] = 0x0438;
- t['iideva'] = 0x0908;
- t['iigujarati'] = 0x0A88;
- t['iigurmukhi'] = 0x0A08;
- t['iimatragurmukhi'] = 0x0A40;
- t['iinvertedbreve'] = 0x020B;
- t['iishortcyrillic'] = 0x0439;
- t['iivowelsignbengali'] = 0x09C0;
- t['iivowelsigndeva'] = 0x0940;
- t['iivowelsigngujarati'] = 0x0AC0;
- t['ij'] = 0x0133;
- t['ikatakana'] = 0x30A4;
- t['ikatakanahalfwidth'] = 0xFF72;
- t['ikorean'] = 0x3163;
- t['ilde'] = 0x02DC;
- t['iluyhebrew'] = 0x05AC;
- t['imacron'] = 0x012B;
- t['imacroncyrillic'] = 0x04E3;
- t['imageorapproximatelyequal'] = 0x2253;
- t['imatragurmukhi'] = 0x0A3F;
- t['imonospace'] = 0xFF49;
- t['increment'] = 0x2206;
- t['infinity'] = 0x221E;
- t['iniarmenian'] = 0x056B;
- t['integral'] = 0x222B;
- t['integralbottom'] = 0x2321;
- t['integralbt'] = 0x2321;
- t['integralex'] = 0xF8F5;
- t['integraltop'] = 0x2320;
- t['integraltp'] = 0x2320;
- t['intersection'] = 0x2229;
- t['intisquare'] = 0x3305;
- t['invbullet'] = 0x25D8;
- t['invcircle'] = 0x25D9;
- t['invsmileface'] = 0x263B;
- t['iocyrillic'] = 0x0451;
- t['iogonek'] = 0x012F;
- t['iota'] = 0x03B9;
- t['iotadieresis'] = 0x03CA;
- t['iotadieresistonos'] = 0x0390;
- t['iotalatin'] = 0x0269;
- t['iotatonos'] = 0x03AF;
- t['iparen'] = 0x24A4;
- t['irigurmukhi'] = 0x0A72;
- t['ismallhiragana'] = 0x3043;
- t['ismallkatakana'] = 0x30A3;
- t['ismallkatakanahalfwidth'] = 0xFF68;
- t['issharbengali'] = 0x09FA;
- t['istroke'] = 0x0268;
- t['isuperior'] = 0xF6ED;
- t['iterationhiragana'] = 0x309D;
- t['iterationkatakana'] = 0x30FD;
- t['itilde'] = 0x0129;
- t['itildebelow'] = 0x1E2D;
- t['iubopomofo'] = 0x3129;
- t['iucyrillic'] = 0x044E;
- t['ivowelsignbengali'] = 0x09BF;
- t['ivowelsigndeva'] = 0x093F;
- t['ivowelsigngujarati'] = 0x0ABF;
- t['izhitsacyrillic'] = 0x0475;
- t['izhitsadblgravecyrillic'] = 0x0477;
- t['j'] = 0x006A;
- t['jaarmenian'] = 0x0571;
- t['jabengali'] = 0x099C;
- t['jadeva'] = 0x091C;
- t['jagujarati'] = 0x0A9C;
- t['jagurmukhi'] = 0x0A1C;
- t['jbopomofo'] = 0x3110;
- t['jcaron'] = 0x01F0;
- t['jcircle'] = 0x24D9;
- t['jcircumflex'] = 0x0135;
- t['jcrossedtail'] = 0x029D;
- t['jdotlessstroke'] = 0x025F;
- t['jecyrillic'] = 0x0458;
- t['jeemarabic'] = 0x062C;
- t['jeemfinalarabic'] = 0xFE9E;
- t['jeeminitialarabic'] = 0xFE9F;
- t['jeemmedialarabic'] = 0xFEA0;
- t['jeharabic'] = 0x0698;
- t['jehfinalarabic'] = 0xFB8B;
- t['jhabengali'] = 0x099D;
- t['jhadeva'] = 0x091D;
- t['jhagujarati'] = 0x0A9D;
- t['jhagurmukhi'] = 0x0A1D;
- t['jheharmenian'] = 0x057B;
- t['jis'] = 0x3004;
- t['jmonospace'] = 0xFF4A;
- t['jparen'] = 0x24A5;
- t['jsuperior'] = 0x02B2;
- t['k'] = 0x006B;
- t['kabashkircyrillic'] = 0x04A1;
- t['kabengali'] = 0x0995;
- t['kacute'] = 0x1E31;
- t['kacyrillic'] = 0x043A;
- t['kadescendercyrillic'] = 0x049B;
- t['kadeva'] = 0x0915;
- t['kaf'] = 0x05DB;
- t['kafarabic'] = 0x0643;
- t['kafdagesh'] = 0xFB3B;
- t['kafdageshhebrew'] = 0xFB3B;
- t['kaffinalarabic'] = 0xFEDA;
- t['kafhebrew'] = 0x05DB;
- t['kafinitialarabic'] = 0xFEDB;
- t['kafmedialarabic'] = 0xFEDC;
- t['kafrafehebrew'] = 0xFB4D;
- t['kagujarati'] = 0x0A95;
- t['kagurmukhi'] = 0x0A15;
- t['kahiragana'] = 0x304B;
- t['kahookcyrillic'] = 0x04C4;
- t['kakatakana'] = 0x30AB;
- t['kakatakanahalfwidth'] = 0xFF76;
- t['kappa'] = 0x03BA;
- t['kappasymbolgreek'] = 0x03F0;
- t['kapyeounmieumkorean'] = 0x3171;
- t['kapyeounphieuphkorean'] = 0x3184;
- t['kapyeounpieupkorean'] = 0x3178;
- t['kapyeounssangpieupkorean'] = 0x3179;
- t['karoriisquare'] = 0x330D;
- t['kashidaautoarabic'] = 0x0640;
- t['kashidaautonosidebearingarabic'] = 0x0640;
- t['kasmallkatakana'] = 0x30F5;
- t['kasquare'] = 0x3384;
- t['kasraarabic'] = 0x0650;
- t['kasratanarabic'] = 0x064D;
- t['kastrokecyrillic'] = 0x049F;
- t['katahiraprolongmarkhalfwidth'] = 0xFF70;
- t['kaverticalstrokecyrillic'] = 0x049D;
- t['kbopomofo'] = 0x310E;
- t['kcalsquare'] = 0x3389;
- t['kcaron'] = 0x01E9;
- t['kcedilla'] = 0x0137;
- t['kcircle'] = 0x24DA;
- t['kcommaaccent'] = 0x0137;
- t['kdotbelow'] = 0x1E33;
- t['keharmenian'] = 0x0584;
- t['kehiragana'] = 0x3051;
- t['kekatakana'] = 0x30B1;
- t['kekatakanahalfwidth'] = 0xFF79;
- t['kenarmenian'] = 0x056F;
- t['kesmallkatakana'] = 0x30F6;
- t['kgreenlandic'] = 0x0138;
- t['khabengali'] = 0x0996;
- t['khacyrillic'] = 0x0445;
- t['khadeva'] = 0x0916;
- t['khagujarati'] = 0x0A96;
- t['khagurmukhi'] = 0x0A16;
- t['khaharabic'] = 0x062E;
- t['khahfinalarabic'] = 0xFEA6;
- t['khahinitialarabic'] = 0xFEA7;
- t['khahmedialarabic'] = 0xFEA8;
- t['kheicoptic'] = 0x03E7;
- t['khhadeva'] = 0x0959;
- t['khhagurmukhi'] = 0x0A59;
- t['khieukhacirclekorean'] = 0x3278;
- t['khieukhaparenkorean'] = 0x3218;
- t['khieukhcirclekorean'] = 0x326A;
- t['khieukhkorean'] = 0x314B;
- t['khieukhparenkorean'] = 0x320A;
- t['khokhaithai'] = 0x0E02;
- t['khokhonthai'] = 0x0E05;
- t['khokhuatthai'] = 0x0E03;
- t['khokhwaithai'] = 0x0E04;
- t['khomutthai'] = 0x0E5B;
- t['khook'] = 0x0199;
- t['khorakhangthai'] = 0x0E06;
- t['khzsquare'] = 0x3391;
- t['kihiragana'] = 0x304D;
- t['kikatakana'] = 0x30AD;
- t['kikatakanahalfwidth'] = 0xFF77;
- t['kiroguramusquare'] = 0x3315;
- t['kiromeetorusquare'] = 0x3316;
- t['kirosquare'] = 0x3314;
- t['kiyeokacirclekorean'] = 0x326E;
- t['kiyeokaparenkorean'] = 0x320E;
- t['kiyeokcirclekorean'] = 0x3260;
- t['kiyeokkorean'] = 0x3131;
- t['kiyeokparenkorean'] = 0x3200;
- t['kiyeoksioskorean'] = 0x3133;
- t['kjecyrillic'] = 0x045C;
- t['klinebelow'] = 0x1E35;
- t['klsquare'] = 0x3398;
- t['kmcubedsquare'] = 0x33A6;
- t['kmonospace'] = 0xFF4B;
- t['kmsquaredsquare'] = 0x33A2;
- t['kohiragana'] = 0x3053;
- t['kohmsquare'] = 0x33C0;
- t['kokaithai'] = 0x0E01;
- t['kokatakana'] = 0x30B3;
- t['kokatakanahalfwidth'] = 0xFF7A;
- t['kooposquare'] = 0x331E;
- t['koppacyrillic'] = 0x0481;
- t['koreanstandardsymbol'] = 0x327F;
- t['koroniscmb'] = 0x0343;
- t['kparen'] = 0x24A6;
- t['kpasquare'] = 0x33AA;
- t['ksicyrillic'] = 0x046F;
- t['ktsquare'] = 0x33CF;
- t['kturned'] = 0x029E;
- t['kuhiragana'] = 0x304F;
- t['kukatakana'] = 0x30AF;
- t['kukatakanahalfwidth'] = 0xFF78;
- t['kvsquare'] = 0x33B8;
- t['kwsquare'] = 0x33BE;
- t['l'] = 0x006C;
- t['labengali'] = 0x09B2;
- t['lacute'] = 0x013A;
- t['ladeva'] = 0x0932;
- t['lagujarati'] = 0x0AB2;
- t['lagurmukhi'] = 0x0A32;
- t['lakkhangyaothai'] = 0x0E45;
- t['lamaleffinalarabic'] = 0xFEFC;
- t['lamalefhamzaabovefinalarabic'] = 0xFEF8;
- t['lamalefhamzaaboveisolatedarabic'] = 0xFEF7;
- t['lamalefhamzabelowfinalarabic'] = 0xFEFA;
- t['lamalefhamzabelowisolatedarabic'] = 0xFEF9;
- t['lamalefisolatedarabic'] = 0xFEFB;
- t['lamalefmaddaabovefinalarabic'] = 0xFEF6;
- t['lamalefmaddaaboveisolatedarabic'] = 0xFEF5;
- t['lamarabic'] = 0x0644;
- t['lambda'] = 0x03BB;
- t['lambdastroke'] = 0x019B;
- t['lamed'] = 0x05DC;
- t['lameddagesh'] = 0xFB3C;
- t['lameddageshhebrew'] = 0xFB3C;
- t['lamedhebrew'] = 0x05DC;
- t['lamfinalarabic'] = 0xFEDE;
- t['lamhahinitialarabic'] = 0xFCCA;
- t['laminitialarabic'] = 0xFEDF;
- t['lamjeeminitialarabic'] = 0xFCC9;
- t['lamkhahinitialarabic'] = 0xFCCB;
- t['lamlamhehisolatedarabic'] = 0xFDF2;
- t['lammedialarabic'] = 0xFEE0;
- t['lammeemhahinitialarabic'] = 0xFD88;
- t['lammeeminitialarabic'] = 0xFCCC;
- t['largecircle'] = 0x25EF;
- t['lbar'] = 0x019A;
- t['lbelt'] = 0x026C;
- t['lbopomofo'] = 0x310C;
- t['lcaron'] = 0x013E;
- t['lcedilla'] = 0x013C;
- t['lcircle'] = 0x24DB;
- t['lcircumflexbelow'] = 0x1E3D;
- t['lcommaaccent'] = 0x013C;
- t['ldot'] = 0x0140;
- t['ldotaccent'] = 0x0140;
- t['ldotbelow'] = 0x1E37;
- t['ldotbelowmacron'] = 0x1E39;
- t['leftangleabovecmb'] = 0x031A;
- t['lefttackbelowcmb'] = 0x0318;
- t['less'] = 0x003C;
- t['lessequal'] = 0x2264;
- t['lessequalorgreater'] = 0x22DA;
- t['lessmonospace'] = 0xFF1C;
- t['lessorequivalent'] = 0x2272;
- t['lessorgreater'] = 0x2276;
- t['lessoverequal'] = 0x2266;
- t['lesssmall'] = 0xFE64;
- t['lezh'] = 0x026E;
- t['lfblock'] = 0x258C;
- t['lhookretroflex'] = 0x026D;
- t['lira'] = 0x20A4;
- t['liwnarmenian'] = 0x056C;
- t['lj'] = 0x01C9;
- t['ljecyrillic'] = 0x0459;
- t['ll'] = 0xF6C0;
- t['lladeva'] = 0x0933;
- t['llagujarati'] = 0x0AB3;
- t['llinebelow'] = 0x1E3B;
- t['llladeva'] = 0x0934;
- t['llvocalicbengali'] = 0x09E1;
- t['llvocalicdeva'] = 0x0961;
- t['llvocalicvowelsignbengali'] = 0x09E3;
- t['llvocalicvowelsigndeva'] = 0x0963;
- t['lmiddletilde'] = 0x026B;
- t['lmonospace'] = 0xFF4C;
- t['lmsquare'] = 0x33D0;
- t['lochulathai'] = 0x0E2C;
- t['logicaland'] = 0x2227;
- t['logicalnot'] = 0x00AC;
- t['logicalnotreversed'] = 0x2310;
- t['logicalor'] = 0x2228;
- t['lolingthai'] = 0x0E25;
- t['longs'] = 0x017F;
- t['lowlinecenterline'] = 0xFE4E;
- t['lowlinecmb'] = 0x0332;
- t['lowlinedashed'] = 0xFE4D;
- t['lozenge'] = 0x25CA;
- t['lparen'] = 0x24A7;
- t['lslash'] = 0x0142;
- t['lsquare'] = 0x2113;
- t['lsuperior'] = 0xF6EE;
- t['ltshade'] = 0x2591;
- t['luthai'] = 0x0E26;
- t['lvocalicbengali'] = 0x098C;
- t['lvocalicdeva'] = 0x090C;
- t['lvocalicvowelsignbengali'] = 0x09E2;
- t['lvocalicvowelsigndeva'] = 0x0962;
- t['lxsquare'] = 0x33D3;
- t['m'] = 0x006D;
- t['mabengali'] = 0x09AE;
- t['macron'] = 0x00AF;
- t['macronbelowcmb'] = 0x0331;
- t['macroncmb'] = 0x0304;
- t['macronlowmod'] = 0x02CD;
- t['macronmonospace'] = 0xFFE3;
- t['macute'] = 0x1E3F;
- t['madeva'] = 0x092E;
- t['magujarati'] = 0x0AAE;
- t['magurmukhi'] = 0x0A2E;
- t['mahapakhhebrew'] = 0x05A4;
- t['mahapakhlefthebrew'] = 0x05A4;
- t['mahiragana'] = 0x307E;
- t['maichattawalowleftthai'] = 0xF895;
- t['maichattawalowrightthai'] = 0xF894;
- t['maichattawathai'] = 0x0E4B;
- t['maichattawaupperleftthai'] = 0xF893;
- t['maieklowleftthai'] = 0xF88C;
- t['maieklowrightthai'] = 0xF88B;
- t['maiekthai'] = 0x0E48;
- t['maiekupperleftthai'] = 0xF88A;
- t['maihanakatleftthai'] = 0xF884;
- t['maihanakatthai'] = 0x0E31;
- t['maitaikhuleftthai'] = 0xF889;
- t['maitaikhuthai'] = 0x0E47;
- t['maitholowleftthai'] = 0xF88F;
- t['maitholowrightthai'] = 0xF88E;
- t['maithothai'] = 0x0E49;
- t['maithoupperleftthai'] = 0xF88D;
- t['maitrilowleftthai'] = 0xF892;
- t['maitrilowrightthai'] = 0xF891;
- t['maitrithai'] = 0x0E4A;
- t['maitriupperleftthai'] = 0xF890;
- t['maiyamokthai'] = 0x0E46;
- t['makatakana'] = 0x30DE;
- t['makatakanahalfwidth'] = 0xFF8F;
- t['male'] = 0x2642;
- t['mansyonsquare'] = 0x3347;
- t['maqafhebrew'] = 0x05BE;
- t['mars'] = 0x2642;
- t['masoracirclehebrew'] = 0x05AF;
- t['masquare'] = 0x3383;
- t['mbopomofo'] = 0x3107;
- t['mbsquare'] = 0x33D4;
- t['mcircle'] = 0x24DC;
- t['mcubedsquare'] = 0x33A5;
- t['mdotaccent'] = 0x1E41;
- t['mdotbelow'] = 0x1E43;
- t['meemarabic'] = 0x0645;
- t['meemfinalarabic'] = 0xFEE2;
- t['meeminitialarabic'] = 0xFEE3;
- t['meemmedialarabic'] = 0xFEE4;
- t['meemmeeminitialarabic'] = 0xFCD1;
- t['meemmeemisolatedarabic'] = 0xFC48;
- t['meetorusquare'] = 0x334D;
- t['mehiragana'] = 0x3081;
- t['meizierasquare'] = 0x337E;
- t['mekatakana'] = 0x30E1;
- t['mekatakanahalfwidth'] = 0xFF92;
- t['mem'] = 0x05DE;
- t['memdagesh'] = 0xFB3E;
- t['memdageshhebrew'] = 0xFB3E;
- t['memhebrew'] = 0x05DE;
- t['menarmenian'] = 0x0574;
- t['merkhahebrew'] = 0x05A5;
- t['merkhakefulahebrew'] = 0x05A6;
- t['merkhakefulalefthebrew'] = 0x05A6;
- t['merkhalefthebrew'] = 0x05A5;
- t['mhook'] = 0x0271;
- t['mhzsquare'] = 0x3392;
- t['middledotkatakanahalfwidth'] = 0xFF65;
- t['middot'] = 0x00B7;
- t['mieumacirclekorean'] = 0x3272;
- t['mieumaparenkorean'] = 0x3212;
- t['mieumcirclekorean'] = 0x3264;
- t['mieumkorean'] = 0x3141;
- t['mieumpansioskorean'] = 0x3170;
- t['mieumparenkorean'] = 0x3204;
- t['mieumpieupkorean'] = 0x316E;
- t['mieumsioskorean'] = 0x316F;
- t['mihiragana'] = 0x307F;
- t['mikatakana'] = 0x30DF;
- t['mikatakanahalfwidth'] = 0xFF90;
- t['minus'] = 0x2212;
- t['minusbelowcmb'] = 0x0320;
- t['minuscircle'] = 0x2296;
- t['minusmod'] = 0x02D7;
- t['minusplus'] = 0x2213;
- t['minute'] = 0x2032;
- t['miribaarusquare'] = 0x334A;
- t['mirisquare'] = 0x3349;
- t['mlonglegturned'] = 0x0270;
- t['mlsquare'] = 0x3396;
- t['mmcubedsquare'] = 0x33A3;
- t['mmonospace'] = 0xFF4D;
- t['mmsquaredsquare'] = 0x339F;
- t['mohiragana'] = 0x3082;
- t['mohmsquare'] = 0x33C1;
- t['mokatakana'] = 0x30E2;
- t['mokatakanahalfwidth'] = 0xFF93;
- t['molsquare'] = 0x33D6;
- t['momathai'] = 0x0E21;
- t['moverssquare'] = 0x33A7;
- t['moverssquaredsquare'] = 0x33A8;
- t['mparen'] = 0x24A8;
- t['mpasquare'] = 0x33AB;
- t['mssquare'] = 0x33B3;
- t['msuperior'] = 0xF6EF;
- t['mturned'] = 0x026F;
- t['mu'] = 0x00B5;
- t['mu1'] = 0x00B5;
- t['muasquare'] = 0x3382;
- t['muchgreater'] = 0x226B;
- t['muchless'] = 0x226A;
- t['mufsquare'] = 0x338C;
- t['mugreek'] = 0x03BC;
- t['mugsquare'] = 0x338D;
- t['muhiragana'] = 0x3080;
- t['mukatakana'] = 0x30E0;
- t['mukatakanahalfwidth'] = 0xFF91;
- t['mulsquare'] = 0x3395;
- t['multiply'] = 0x00D7;
- t['mumsquare'] = 0x339B;
- t['munahhebrew'] = 0x05A3;
- t['munahlefthebrew'] = 0x05A3;
- t['musicalnote'] = 0x266A;
- t['musicalnotedbl'] = 0x266B;
- t['musicflatsign'] = 0x266D;
- t['musicsharpsign'] = 0x266F;
- t['mussquare'] = 0x33B2;
- t['muvsquare'] = 0x33B6;
- t['muwsquare'] = 0x33BC;
- t['mvmegasquare'] = 0x33B9;
- t['mvsquare'] = 0x33B7;
- t['mwmegasquare'] = 0x33BF;
- t['mwsquare'] = 0x33BD;
- t['n'] = 0x006E;
- t['nabengali'] = 0x09A8;
- t['nabla'] = 0x2207;
- t['nacute'] = 0x0144;
- t['nadeva'] = 0x0928;
- t['nagujarati'] = 0x0AA8;
- t['nagurmukhi'] = 0x0A28;
- t['nahiragana'] = 0x306A;
- t['nakatakana'] = 0x30CA;
- t['nakatakanahalfwidth'] = 0xFF85;
- t['napostrophe'] = 0x0149;
- t['nasquare'] = 0x3381;
- t['nbopomofo'] = 0x310B;
- t['nbspace'] = 0x00A0;
- t['ncaron'] = 0x0148;
- t['ncedilla'] = 0x0146;
- t['ncircle'] = 0x24DD;
- t['ncircumflexbelow'] = 0x1E4B;
- t['ncommaaccent'] = 0x0146;
- t['ndotaccent'] = 0x1E45;
- t['ndotbelow'] = 0x1E47;
- t['nehiragana'] = 0x306D;
- t['nekatakana'] = 0x30CD;
- t['nekatakanahalfwidth'] = 0xFF88;
- t['newsheqelsign'] = 0x20AA;
- t['nfsquare'] = 0x338B;
- t['ngabengali'] = 0x0999;
- t['ngadeva'] = 0x0919;
- t['ngagujarati'] = 0x0A99;
- t['ngagurmukhi'] = 0x0A19;
- t['ngonguthai'] = 0x0E07;
- t['nhiragana'] = 0x3093;
- t['nhookleft'] = 0x0272;
- t['nhookretroflex'] = 0x0273;
- t['nieunacirclekorean'] = 0x326F;
- t['nieunaparenkorean'] = 0x320F;
- t['nieuncieuckorean'] = 0x3135;
- t['nieuncirclekorean'] = 0x3261;
- t['nieunhieuhkorean'] = 0x3136;
- t['nieunkorean'] = 0x3134;
- t['nieunpansioskorean'] = 0x3168;
- t['nieunparenkorean'] = 0x3201;
- t['nieunsioskorean'] = 0x3167;
- t['nieuntikeutkorean'] = 0x3166;
- t['nihiragana'] = 0x306B;
- t['nikatakana'] = 0x30CB;
- t['nikatakanahalfwidth'] = 0xFF86;
- t['nikhahitleftthai'] = 0xF899;
- t['nikhahitthai'] = 0x0E4D;
- t['nine'] = 0x0039;
- t['ninearabic'] = 0x0669;
- t['ninebengali'] = 0x09EF;
- t['ninecircle'] = 0x2468;
- t['ninecircleinversesansserif'] = 0x2792;
- t['ninedeva'] = 0x096F;
- t['ninegujarati'] = 0x0AEF;
- t['ninegurmukhi'] = 0x0A6F;
- t['ninehackarabic'] = 0x0669;
- t['ninehangzhou'] = 0x3029;
- t['nineideographicparen'] = 0x3228;
- t['nineinferior'] = 0x2089;
- t['ninemonospace'] = 0xFF19;
- t['nineoldstyle'] = 0xF739;
- t['nineparen'] = 0x247C;
- t['nineperiod'] = 0x2490;
- t['ninepersian'] = 0x06F9;
- t['nineroman'] = 0x2178;
- t['ninesuperior'] = 0x2079;
- t['nineteencircle'] = 0x2472;
- t['nineteenparen'] = 0x2486;
- t['nineteenperiod'] = 0x249A;
- t['ninethai'] = 0x0E59;
- t['nj'] = 0x01CC;
- t['njecyrillic'] = 0x045A;
- t['nkatakana'] = 0x30F3;
- t['nkatakanahalfwidth'] = 0xFF9D;
- t['nlegrightlong'] = 0x019E;
- t['nlinebelow'] = 0x1E49;
- t['nmonospace'] = 0xFF4E;
- t['nmsquare'] = 0x339A;
- t['nnabengali'] = 0x09A3;
- t['nnadeva'] = 0x0923;
- t['nnagujarati'] = 0x0AA3;
- t['nnagurmukhi'] = 0x0A23;
- t['nnnadeva'] = 0x0929;
- t['nohiragana'] = 0x306E;
- t['nokatakana'] = 0x30CE;
- t['nokatakanahalfwidth'] = 0xFF89;
- t['nonbreakingspace'] = 0x00A0;
- t['nonenthai'] = 0x0E13;
- t['nonuthai'] = 0x0E19;
- t['noonarabic'] = 0x0646;
- t['noonfinalarabic'] = 0xFEE6;
- t['noonghunnaarabic'] = 0x06BA;
- t['noonghunnafinalarabic'] = 0xFB9F;
- t['nooninitialarabic'] = 0xFEE7;
- t['noonjeeminitialarabic'] = 0xFCD2;
- t['noonjeemisolatedarabic'] = 0xFC4B;
- t['noonmedialarabic'] = 0xFEE8;
- t['noonmeeminitialarabic'] = 0xFCD5;
- t['noonmeemisolatedarabic'] = 0xFC4E;
- t['noonnoonfinalarabic'] = 0xFC8D;
- t['notcontains'] = 0x220C;
- t['notelement'] = 0x2209;
- t['notelementof'] = 0x2209;
- t['notequal'] = 0x2260;
- t['notgreater'] = 0x226F;
- t['notgreaternorequal'] = 0x2271;
- t['notgreaternorless'] = 0x2279;
- t['notidentical'] = 0x2262;
- t['notless'] = 0x226E;
- t['notlessnorequal'] = 0x2270;
- t['notparallel'] = 0x2226;
- t['notprecedes'] = 0x2280;
- t['notsubset'] = 0x2284;
- t['notsucceeds'] = 0x2281;
- t['notsuperset'] = 0x2285;
- t['nowarmenian'] = 0x0576;
- t['nparen'] = 0x24A9;
- t['nssquare'] = 0x33B1;
- t['nsuperior'] = 0x207F;
- t['ntilde'] = 0x00F1;
- t['nu'] = 0x03BD;
- t['nuhiragana'] = 0x306C;
- t['nukatakana'] = 0x30CC;
- t['nukatakanahalfwidth'] = 0xFF87;
- t['nuktabengali'] = 0x09BC;
- t['nuktadeva'] = 0x093C;
- t['nuktagujarati'] = 0x0ABC;
- t['nuktagurmukhi'] = 0x0A3C;
- t['numbersign'] = 0x0023;
- t['numbersignmonospace'] = 0xFF03;
- t['numbersignsmall'] = 0xFE5F;
- t['numeralsigngreek'] = 0x0374;
- t['numeralsignlowergreek'] = 0x0375;
- t['numero'] = 0x2116;
- t['nun'] = 0x05E0;
- t['nundagesh'] = 0xFB40;
- t['nundageshhebrew'] = 0xFB40;
- t['nunhebrew'] = 0x05E0;
- t['nvsquare'] = 0x33B5;
- t['nwsquare'] = 0x33BB;
- t['nyabengali'] = 0x099E;
- t['nyadeva'] = 0x091E;
- t['nyagujarati'] = 0x0A9E;
- t['nyagurmukhi'] = 0x0A1E;
- t['o'] = 0x006F;
- t['oacute'] = 0x00F3;
- t['oangthai'] = 0x0E2D;
- t['obarred'] = 0x0275;
- t['obarredcyrillic'] = 0x04E9;
- t['obarreddieresiscyrillic'] = 0x04EB;
- t['obengali'] = 0x0993;
- t['obopomofo'] = 0x311B;
- t['obreve'] = 0x014F;
- t['ocandradeva'] = 0x0911;
- t['ocandragujarati'] = 0x0A91;
- t['ocandravowelsigndeva'] = 0x0949;
- t['ocandravowelsigngujarati'] = 0x0AC9;
- t['ocaron'] = 0x01D2;
- t['ocircle'] = 0x24DE;
- t['ocircumflex'] = 0x00F4;
- t['ocircumflexacute'] = 0x1ED1;
- t['ocircumflexdotbelow'] = 0x1ED9;
- t['ocircumflexgrave'] = 0x1ED3;
- t['ocircumflexhookabove'] = 0x1ED5;
- t['ocircumflextilde'] = 0x1ED7;
- t['ocyrillic'] = 0x043E;
- t['odblacute'] = 0x0151;
- t['odblgrave'] = 0x020D;
- t['odeva'] = 0x0913;
- t['odieresis'] = 0x00F6;
- t['odieresiscyrillic'] = 0x04E7;
- t['odotbelow'] = 0x1ECD;
- t['oe'] = 0x0153;
- t['oekorean'] = 0x315A;
- t['ogonek'] = 0x02DB;
- t['ogonekcmb'] = 0x0328;
- t['ograve'] = 0x00F2;
- t['ogujarati'] = 0x0A93;
- t['oharmenian'] = 0x0585;
- t['ohiragana'] = 0x304A;
- t['ohookabove'] = 0x1ECF;
- t['ohorn'] = 0x01A1;
- t['ohornacute'] = 0x1EDB;
- t['ohorndotbelow'] = 0x1EE3;
- t['ohorngrave'] = 0x1EDD;
- t['ohornhookabove'] = 0x1EDF;
- t['ohorntilde'] = 0x1EE1;
- t['ohungarumlaut'] = 0x0151;
- t['oi'] = 0x01A3;
- t['oinvertedbreve'] = 0x020F;
- t['okatakana'] = 0x30AA;
- t['okatakanahalfwidth'] = 0xFF75;
- t['okorean'] = 0x3157;
- t['olehebrew'] = 0x05AB;
- t['omacron'] = 0x014D;
- t['omacronacute'] = 0x1E53;
- t['omacrongrave'] = 0x1E51;
- t['omdeva'] = 0x0950;
- t['omega'] = 0x03C9;
- t['omega1'] = 0x03D6;
- t['omegacyrillic'] = 0x0461;
- t['omegalatinclosed'] = 0x0277;
- t['omegaroundcyrillic'] = 0x047B;
- t['omegatitlocyrillic'] = 0x047D;
- t['omegatonos'] = 0x03CE;
- t['omgujarati'] = 0x0AD0;
- t['omicron'] = 0x03BF;
- t['omicrontonos'] = 0x03CC;
- t['omonospace'] = 0xFF4F;
- t['one'] = 0x0031;
- t['onearabic'] = 0x0661;
- t['onebengali'] = 0x09E7;
- t['onecircle'] = 0x2460;
- t['onecircleinversesansserif'] = 0x278A;
- t['onedeva'] = 0x0967;
- t['onedotenleader'] = 0x2024;
- t['oneeighth'] = 0x215B;
- t['onefitted'] = 0xF6DC;
- t['onegujarati'] = 0x0AE7;
- t['onegurmukhi'] = 0x0A67;
- t['onehackarabic'] = 0x0661;
- t['onehalf'] = 0x00BD;
- t['onehangzhou'] = 0x3021;
- t['oneideographicparen'] = 0x3220;
- t['oneinferior'] = 0x2081;
- t['onemonospace'] = 0xFF11;
- t['onenumeratorbengali'] = 0x09F4;
- t['oneoldstyle'] = 0xF731;
- t['oneparen'] = 0x2474;
- t['oneperiod'] = 0x2488;
- t['onepersian'] = 0x06F1;
- t['onequarter'] = 0x00BC;
- t['oneroman'] = 0x2170;
- t['onesuperior'] = 0x00B9;
- t['onethai'] = 0x0E51;
- t['onethird'] = 0x2153;
- t['oogonek'] = 0x01EB;
- t['oogonekmacron'] = 0x01ED;
- t['oogurmukhi'] = 0x0A13;
- t['oomatragurmukhi'] = 0x0A4B;
- t['oopen'] = 0x0254;
- t['oparen'] = 0x24AA;
- t['openbullet'] = 0x25E6;
- t['option'] = 0x2325;
- t['ordfeminine'] = 0x00AA;
- t['ordmasculine'] = 0x00BA;
- t['orthogonal'] = 0x221F;
- t['oshortdeva'] = 0x0912;
- t['oshortvowelsigndeva'] = 0x094A;
- t['oslash'] = 0x00F8;
- t['oslashacute'] = 0x01FF;
- t['osmallhiragana'] = 0x3049;
- t['osmallkatakana'] = 0x30A9;
- t['osmallkatakanahalfwidth'] = 0xFF6B;
- t['ostrokeacute'] = 0x01FF;
- t['osuperior'] = 0xF6F0;
- t['otcyrillic'] = 0x047F;
- t['otilde'] = 0x00F5;
- t['otildeacute'] = 0x1E4D;
- t['otildedieresis'] = 0x1E4F;
- t['oubopomofo'] = 0x3121;
- t['overline'] = 0x203E;
- t['overlinecenterline'] = 0xFE4A;
- t['overlinecmb'] = 0x0305;
- t['overlinedashed'] = 0xFE49;
- t['overlinedblwavy'] = 0xFE4C;
- t['overlinewavy'] = 0xFE4B;
- t['overscore'] = 0x00AF;
- t['ovowelsignbengali'] = 0x09CB;
- t['ovowelsigndeva'] = 0x094B;
- t['ovowelsigngujarati'] = 0x0ACB;
- t['p'] = 0x0070;
- t['paampssquare'] = 0x3380;
- t['paasentosquare'] = 0x332B;
- t['pabengali'] = 0x09AA;
- t['pacute'] = 0x1E55;
- t['padeva'] = 0x092A;
- t['pagedown'] = 0x21DF;
- t['pageup'] = 0x21DE;
- t['pagujarati'] = 0x0AAA;
- t['pagurmukhi'] = 0x0A2A;
- t['pahiragana'] = 0x3071;
- t['paiyannoithai'] = 0x0E2F;
- t['pakatakana'] = 0x30D1;
- t['palatalizationcyrilliccmb'] = 0x0484;
- t['palochkacyrillic'] = 0x04C0;
- t['pansioskorean'] = 0x317F;
- t['paragraph'] = 0x00B6;
- t['parallel'] = 0x2225;
- t['parenleft'] = 0x0028;
- t['parenleftaltonearabic'] = 0xFD3E;
- t['parenleftbt'] = 0xF8ED;
- t['parenleftex'] = 0xF8EC;
- t['parenleftinferior'] = 0x208D;
- t['parenleftmonospace'] = 0xFF08;
- t['parenleftsmall'] = 0xFE59;
- t['parenleftsuperior'] = 0x207D;
- t['parenlefttp'] = 0xF8EB;
- t['parenleftvertical'] = 0xFE35;
- t['parenright'] = 0x0029;
- t['parenrightaltonearabic'] = 0xFD3F;
- t['parenrightbt'] = 0xF8F8;
- t['parenrightex'] = 0xF8F7;
- t['parenrightinferior'] = 0x208E;
- t['parenrightmonospace'] = 0xFF09;
- t['parenrightsmall'] = 0xFE5A;
- t['parenrightsuperior'] = 0x207E;
- t['parenrighttp'] = 0xF8F6;
- t['parenrightvertical'] = 0xFE36;
- t['partialdiff'] = 0x2202;
- t['paseqhebrew'] = 0x05C0;
- t['pashtahebrew'] = 0x0599;
- t['pasquare'] = 0x33A9;
- t['patah'] = 0x05B7;
- t['patah11'] = 0x05B7;
- t['patah1d'] = 0x05B7;
- t['patah2a'] = 0x05B7;
- t['patahhebrew'] = 0x05B7;
- t['patahnarrowhebrew'] = 0x05B7;
- t['patahquarterhebrew'] = 0x05B7;
- t['patahwidehebrew'] = 0x05B7;
- t['pazerhebrew'] = 0x05A1;
- t['pbopomofo'] = 0x3106;
- t['pcircle'] = 0x24DF;
- t['pdotaccent'] = 0x1E57;
- t['pe'] = 0x05E4;
- t['pecyrillic'] = 0x043F;
- t['pedagesh'] = 0xFB44;
- t['pedageshhebrew'] = 0xFB44;
- t['peezisquare'] = 0x333B;
- t['pefinaldageshhebrew'] = 0xFB43;
- t['peharabic'] = 0x067E;
- t['peharmenian'] = 0x057A;
- t['pehebrew'] = 0x05E4;
- t['pehfinalarabic'] = 0xFB57;
- t['pehinitialarabic'] = 0xFB58;
- t['pehiragana'] = 0x307A;
- t['pehmedialarabic'] = 0xFB59;
- t['pekatakana'] = 0x30DA;
- t['pemiddlehookcyrillic'] = 0x04A7;
- t['perafehebrew'] = 0xFB4E;
- t['percent'] = 0x0025;
- t['percentarabic'] = 0x066A;
- t['percentmonospace'] = 0xFF05;
- t['percentsmall'] = 0xFE6A;
- t['period'] = 0x002E;
- t['periodarmenian'] = 0x0589;
- t['periodcentered'] = 0x00B7;
- t['periodhalfwidth'] = 0xFF61;
- t['periodinferior'] = 0xF6E7;
- t['periodmonospace'] = 0xFF0E;
- t['periodsmall'] = 0xFE52;
- t['periodsuperior'] = 0xF6E8;
- t['perispomenigreekcmb'] = 0x0342;
- t['perpendicular'] = 0x22A5;
- t['perthousand'] = 0x2030;
- t['peseta'] = 0x20A7;
- t['pfsquare'] = 0x338A;
- t['phabengali'] = 0x09AB;
- t['phadeva'] = 0x092B;
- t['phagujarati'] = 0x0AAB;
- t['phagurmukhi'] = 0x0A2B;
- t['phi'] = 0x03C6;
- t['phi1'] = 0x03D5;
- t['phieuphacirclekorean'] = 0x327A;
- t['phieuphaparenkorean'] = 0x321A;
- t['phieuphcirclekorean'] = 0x326C;
- t['phieuphkorean'] = 0x314D;
- t['phieuphparenkorean'] = 0x320C;
- t['philatin'] = 0x0278;
- t['phinthuthai'] = 0x0E3A;
- t['phisymbolgreek'] = 0x03D5;
- t['phook'] = 0x01A5;
- t['phophanthai'] = 0x0E1E;
- t['phophungthai'] = 0x0E1C;
- t['phosamphaothai'] = 0x0E20;
- t['pi'] = 0x03C0;
- t['pieupacirclekorean'] = 0x3273;
- t['pieupaparenkorean'] = 0x3213;
- t['pieupcieuckorean'] = 0x3176;
- t['pieupcirclekorean'] = 0x3265;
- t['pieupkiyeokkorean'] = 0x3172;
- t['pieupkorean'] = 0x3142;
- t['pieupparenkorean'] = 0x3205;
- t['pieupsioskiyeokkorean'] = 0x3174;
- t['pieupsioskorean'] = 0x3144;
- t['pieupsiostikeutkorean'] = 0x3175;
- t['pieupthieuthkorean'] = 0x3177;
- t['pieuptikeutkorean'] = 0x3173;
- t['pihiragana'] = 0x3074;
- t['pikatakana'] = 0x30D4;
- t['pisymbolgreek'] = 0x03D6;
- t['piwrarmenian'] = 0x0583;
- t['plus'] = 0x002B;
- t['plusbelowcmb'] = 0x031F;
- t['pluscircle'] = 0x2295;
- t['plusminus'] = 0x00B1;
- t['plusmod'] = 0x02D6;
- t['plusmonospace'] = 0xFF0B;
- t['plussmall'] = 0xFE62;
- t['plussuperior'] = 0x207A;
- t['pmonospace'] = 0xFF50;
- t['pmsquare'] = 0x33D8;
- t['pohiragana'] = 0x307D;
- t['pointingindexdownwhite'] = 0x261F;
- t['pointingindexleftwhite'] = 0x261C;
- t['pointingindexrightwhite'] = 0x261E;
- t['pointingindexupwhite'] = 0x261D;
- t['pokatakana'] = 0x30DD;
- t['poplathai'] = 0x0E1B;
- t['postalmark'] = 0x3012;
- t['postalmarkface'] = 0x3020;
- t['pparen'] = 0x24AB;
- t['precedes'] = 0x227A;
- t['prescription'] = 0x211E;
- t['primemod'] = 0x02B9;
- t['primereversed'] = 0x2035;
- t['product'] = 0x220F;
- t['projective'] = 0x2305;
- t['prolongedkana'] = 0x30FC;
- t['propellor'] = 0x2318;
- t['propersubset'] = 0x2282;
- t['propersuperset'] = 0x2283;
- t['proportion'] = 0x2237;
- t['proportional'] = 0x221D;
- t['psi'] = 0x03C8;
- t['psicyrillic'] = 0x0471;
- t['psilipneumatacyrilliccmb'] = 0x0486;
- t['pssquare'] = 0x33B0;
- t['puhiragana'] = 0x3077;
- t['pukatakana'] = 0x30D7;
- t['pvsquare'] = 0x33B4;
- t['pwsquare'] = 0x33BA;
- t['q'] = 0x0071;
- t['qadeva'] = 0x0958;
- t['qadmahebrew'] = 0x05A8;
- t['qafarabic'] = 0x0642;
- t['qaffinalarabic'] = 0xFED6;
- t['qafinitialarabic'] = 0xFED7;
- t['qafmedialarabic'] = 0xFED8;
- t['qamats'] = 0x05B8;
- t['qamats10'] = 0x05B8;
- t['qamats1a'] = 0x05B8;
- t['qamats1c'] = 0x05B8;
- t['qamats27'] = 0x05B8;
- t['qamats29'] = 0x05B8;
- t['qamats33'] = 0x05B8;
- t['qamatsde'] = 0x05B8;
- t['qamatshebrew'] = 0x05B8;
- t['qamatsnarrowhebrew'] = 0x05B8;
- t['qamatsqatanhebrew'] = 0x05B8;
- t['qamatsqatannarrowhebrew'] = 0x05B8;
- t['qamatsqatanquarterhebrew'] = 0x05B8;
- t['qamatsqatanwidehebrew'] = 0x05B8;
- t['qamatsquarterhebrew'] = 0x05B8;
- t['qamatswidehebrew'] = 0x05B8;
- t['qarneyparahebrew'] = 0x059F;
- t['qbopomofo'] = 0x3111;
- t['qcircle'] = 0x24E0;
- t['qhook'] = 0x02A0;
- t['qmonospace'] = 0xFF51;
- t['qof'] = 0x05E7;
- t['qofdagesh'] = 0xFB47;
- t['qofdageshhebrew'] = 0xFB47;
- t['qofhebrew'] = 0x05E7;
- t['qparen'] = 0x24AC;
- t['quarternote'] = 0x2669;
- t['qubuts'] = 0x05BB;
- t['qubuts18'] = 0x05BB;
- t['qubuts25'] = 0x05BB;
- t['qubuts31'] = 0x05BB;
- t['qubutshebrew'] = 0x05BB;
- t['qubutsnarrowhebrew'] = 0x05BB;
- t['qubutsquarterhebrew'] = 0x05BB;
- t['qubutswidehebrew'] = 0x05BB;
- t['question'] = 0x003F;
- t['questionarabic'] = 0x061F;
- t['questionarmenian'] = 0x055E;
- t['questiondown'] = 0x00BF;
- t['questiondownsmall'] = 0xF7BF;
- t['questiongreek'] = 0x037E;
- t['questionmonospace'] = 0xFF1F;
- t['questionsmall'] = 0xF73F;
- t['quotedbl'] = 0x0022;
- t['quotedblbase'] = 0x201E;
- t['quotedblleft'] = 0x201C;
- t['quotedblmonospace'] = 0xFF02;
- t['quotedblprime'] = 0x301E;
- t['quotedblprimereversed'] = 0x301D;
- t['quotedblright'] = 0x201D;
- t['quoteleft'] = 0x2018;
- t['quoteleftreversed'] = 0x201B;
- t['quotereversed'] = 0x201B;
- t['quoteright'] = 0x2019;
- t['quoterightn'] = 0x0149;
- t['quotesinglbase'] = 0x201A;
- t['quotesingle'] = 0x0027;
- t['quotesinglemonospace'] = 0xFF07;
- t['r'] = 0x0072;
- t['raarmenian'] = 0x057C;
- t['rabengali'] = 0x09B0;
- t['racute'] = 0x0155;
- t['radeva'] = 0x0930;
- t['radical'] = 0x221A;
- t['radicalex'] = 0xF8E5;
- t['radoverssquare'] = 0x33AE;
- t['radoverssquaredsquare'] = 0x33AF;
- t['radsquare'] = 0x33AD;
- t['rafe'] = 0x05BF;
- t['rafehebrew'] = 0x05BF;
- t['ragujarati'] = 0x0AB0;
- t['ragurmukhi'] = 0x0A30;
- t['rahiragana'] = 0x3089;
- t['rakatakana'] = 0x30E9;
- t['rakatakanahalfwidth'] = 0xFF97;
- t['ralowerdiagonalbengali'] = 0x09F1;
- t['ramiddlediagonalbengali'] = 0x09F0;
- t['ramshorn'] = 0x0264;
- t['ratio'] = 0x2236;
- t['rbopomofo'] = 0x3116;
- t['rcaron'] = 0x0159;
- t['rcedilla'] = 0x0157;
- t['rcircle'] = 0x24E1;
- t['rcommaaccent'] = 0x0157;
- t['rdblgrave'] = 0x0211;
- t['rdotaccent'] = 0x1E59;
- t['rdotbelow'] = 0x1E5B;
- t['rdotbelowmacron'] = 0x1E5D;
- t['referencemark'] = 0x203B;
- t['reflexsubset'] = 0x2286;
- t['reflexsuperset'] = 0x2287;
- t['registered'] = 0x00AE;
- t['registersans'] = 0xF8E8;
- t['registerserif'] = 0xF6DA;
- t['reharabic'] = 0x0631;
- t['reharmenian'] = 0x0580;
- t['rehfinalarabic'] = 0xFEAE;
- t['rehiragana'] = 0x308C;
- t['rekatakana'] = 0x30EC;
- t['rekatakanahalfwidth'] = 0xFF9A;
- t['resh'] = 0x05E8;
- t['reshdageshhebrew'] = 0xFB48;
- t['reshhebrew'] = 0x05E8;
- t['reversedtilde'] = 0x223D;
- t['reviahebrew'] = 0x0597;
- t['reviamugrashhebrew'] = 0x0597;
- t['revlogicalnot'] = 0x2310;
- t['rfishhook'] = 0x027E;
- t['rfishhookreversed'] = 0x027F;
- t['rhabengali'] = 0x09DD;
- t['rhadeva'] = 0x095D;
- t['rho'] = 0x03C1;
- t['rhook'] = 0x027D;
- t['rhookturned'] = 0x027B;
- t['rhookturnedsuperior'] = 0x02B5;
- t['rhosymbolgreek'] = 0x03F1;
- t['rhotichookmod'] = 0x02DE;
- t['rieulacirclekorean'] = 0x3271;
- t['rieulaparenkorean'] = 0x3211;
- t['rieulcirclekorean'] = 0x3263;
- t['rieulhieuhkorean'] = 0x3140;
- t['rieulkiyeokkorean'] = 0x313A;
- t['rieulkiyeoksioskorean'] = 0x3169;
- t['rieulkorean'] = 0x3139;
- t['rieulmieumkorean'] = 0x313B;
- t['rieulpansioskorean'] = 0x316C;
- t['rieulparenkorean'] = 0x3203;
- t['rieulphieuphkorean'] = 0x313F;
- t['rieulpieupkorean'] = 0x313C;
- t['rieulpieupsioskorean'] = 0x316B;
- t['rieulsioskorean'] = 0x313D;
- t['rieulthieuthkorean'] = 0x313E;
- t['rieultikeutkorean'] = 0x316A;
- t['rieulyeorinhieuhkorean'] = 0x316D;
- t['rightangle'] = 0x221F;
- t['righttackbelowcmb'] = 0x0319;
- t['righttriangle'] = 0x22BF;
- t['rihiragana'] = 0x308A;
- t['rikatakana'] = 0x30EA;
- t['rikatakanahalfwidth'] = 0xFF98;
- t['ring'] = 0x02DA;
- t['ringbelowcmb'] = 0x0325;
- t['ringcmb'] = 0x030A;
- t['ringhalfleft'] = 0x02BF;
- t['ringhalfleftarmenian'] = 0x0559;
- t['ringhalfleftbelowcmb'] = 0x031C;
- t['ringhalfleftcentered'] = 0x02D3;
- t['ringhalfright'] = 0x02BE;
- t['ringhalfrightbelowcmb'] = 0x0339;
- t['ringhalfrightcentered'] = 0x02D2;
- t['rinvertedbreve'] = 0x0213;
- t['rittorusquare'] = 0x3351;
- t['rlinebelow'] = 0x1E5F;
- t['rlongleg'] = 0x027C;
- t['rlonglegturned'] = 0x027A;
- t['rmonospace'] = 0xFF52;
- t['rohiragana'] = 0x308D;
- t['rokatakana'] = 0x30ED;
- t['rokatakanahalfwidth'] = 0xFF9B;
- t['roruathai'] = 0x0E23;
- t['rparen'] = 0x24AD;
- t['rrabengali'] = 0x09DC;
- t['rradeva'] = 0x0931;
- t['rragurmukhi'] = 0x0A5C;
- t['rreharabic'] = 0x0691;
- t['rrehfinalarabic'] = 0xFB8D;
- t['rrvocalicbengali'] = 0x09E0;
- t['rrvocalicdeva'] = 0x0960;
- t['rrvocalicgujarati'] = 0x0AE0;
- t['rrvocalicvowelsignbengali'] = 0x09C4;
- t['rrvocalicvowelsigndeva'] = 0x0944;
- t['rrvocalicvowelsigngujarati'] = 0x0AC4;
- t['rsuperior'] = 0xF6F1;
- t['rtblock'] = 0x2590;
- t['rturned'] = 0x0279;
- t['rturnedsuperior'] = 0x02B4;
- t['ruhiragana'] = 0x308B;
- t['rukatakana'] = 0x30EB;
- t['rukatakanahalfwidth'] = 0xFF99;
- t['rupeemarkbengali'] = 0x09F2;
- t['rupeesignbengali'] = 0x09F3;
- t['rupiah'] = 0xF6DD;
- t['ruthai'] = 0x0E24;
- t['rvocalicbengali'] = 0x098B;
- t['rvocalicdeva'] = 0x090B;
- t['rvocalicgujarati'] = 0x0A8B;
- t['rvocalicvowelsignbengali'] = 0x09C3;
- t['rvocalicvowelsigndeva'] = 0x0943;
- t['rvocalicvowelsigngujarati'] = 0x0AC3;
- t['s'] = 0x0073;
- t['sabengali'] = 0x09B8;
- t['sacute'] = 0x015B;
- t['sacutedotaccent'] = 0x1E65;
- t['sadarabic'] = 0x0635;
- t['sadeva'] = 0x0938;
- t['sadfinalarabic'] = 0xFEBA;
- t['sadinitialarabic'] = 0xFEBB;
- t['sadmedialarabic'] = 0xFEBC;
- t['sagujarati'] = 0x0AB8;
- t['sagurmukhi'] = 0x0A38;
- t['sahiragana'] = 0x3055;
- t['sakatakana'] = 0x30B5;
- t['sakatakanahalfwidth'] = 0xFF7B;
- t['sallallahoualayhewasallamarabic'] = 0xFDFA;
- t['samekh'] = 0x05E1;
- t['samekhdagesh'] = 0xFB41;
- t['samekhdageshhebrew'] = 0xFB41;
- t['samekhhebrew'] = 0x05E1;
- t['saraaathai'] = 0x0E32;
- t['saraaethai'] = 0x0E41;
- t['saraaimaimalaithai'] = 0x0E44;
- t['saraaimaimuanthai'] = 0x0E43;
- t['saraamthai'] = 0x0E33;
- t['saraathai'] = 0x0E30;
- t['saraethai'] = 0x0E40;
- t['saraiileftthai'] = 0xF886;
- t['saraiithai'] = 0x0E35;
- t['saraileftthai'] = 0xF885;
- t['saraithai'] = 0x0E34;
- t['saraothai'] = 0x0E42;
- t['saraueeleftthai'] = 0xF888;
- t['saraueethai'] = 0x0E37;
- t['saraueleftthai'] = 0xF887;
- t['sarauethai'] = 0x0E36;
- t['sarauthai'] = 0x0E38;
- t['sarauuthai'] = 0x0E39;
- t['sbopomofo'] = 0x3119;
- t['scaron'] = 0x0161;
- t['scarondotaccent'] = 0x1E67;
- t['scedilla'] = 0x015F;
- t['schwa'] = 0x0259;
- t['schwacyrillic'] = 0x04D9;
- t['schwadieresiscyrillic'] = 0x04DB;
- t['schwahook'] = 0x025A;
- t['scircle'] = 0x24E2;
- t['scircumflex'] = 0x015D;
- t['scommaaccent'] = 0x0219;
- t['sdotaccent'] = 0x1E61;
- t['sdotbelow'] = 0x1E63;
- t['sdotbelowdotaccent'] = 0x1E69;
- t['seagullbelowcmb'] = 0x033C;
- t['second'] = 0x2033;
- t['secondtonechinese'] = 0x02CA;
- t['section'] = 0x00A7;
- t['seenarabic'] = 0x0633;
- t['seenfinalarabic'] = 0xFEB2;
- t['seeninitialarabic'] = 0xFEB3;
- t['seenmedialarabic'] = 0xFEB4;
- t['segol'] = 0x05B6;
- t['segol13'] = 0x05B6;
- t['segol1f'] = 0x05B6;
- t['segol2c'] = 0x05B6;
- t['segolhebrew'] = 0x05B6;
- t['segolnarrowhebrew'] = 0x05B6;
- t['segolquarterhebrew'] = 0x05B6;
- t['segoltahebrew'] = 0x0592;
- t['segolwidehebrew'] = 0x05B6;
- t['seharmenian'] = 0x057D;
- t['sehiragana'] = 0x305B;
- t['sekatakana'] = 0x30BB;
- t['sekatakanahalfwidth'] = 0xFF7E;
- t['semicolon'] = 0x003B;
- t['semicolonarabic'] = 0x061B;
- t['semicolonmonospace'] = 0xFF1B;
- t['semicolonsmall'] = 0xFE54;
- t['semivoicedmarkkana'] = 0x309C;
- t['semivoicedmarkkanahalfwidth'] = 0xFF9F;
- t['sentisquare'] = 0x3322;
- t['sentosquare'] = 0x3323;
- t['seven'] = 0x0037;
- t['sevenarabic'] = 0x0667;
- t['sevenbengali'] = 0x09ED;
- t['sevencircle'] = 0x2466;
- t['sevencircleinversesansserif'] = 0x2790;
- t['sevendeva'] = 0x096D;
- t['seveneighths'] = 0x215E;
- t['sevengujarati'] = 0x0AED;
- t['sevengurmukhi'] = 0x0A6D;
- t['sevenhackarabic'] = 0x0667;
- t['sevenhangzhou'] = 0x3027;
- t['sevenideographicparen'] = 0x3226;
- t['seveninferior'] = 0x2087;
- t['sevenmonospace'] = 0xFF17;
- t['sevenoldstyle'] = 0xF737;
- t['sevenparen'] = 0x247A;
- t['sevenperiod'] = 0x248E;
- t['sevenpersian'] = 0x06F7;
- t['sevenroman'] = 0x2176;
- t['sevensuperior'] = 0x2077;
- t['seventeencircle'] = 0x2470;
- t['seventeenparen'] = 0x2484;
- t['seventeenperiod'] = 0x2498;
- t['seventhai'] = 0x0E57;
- t['sfthyphen'] = 0x00AD;
- t['shaarmenian'] = 0x0577;
- t['shabengali'] = 0x09B6;
- t['shacyrillic'] = 0x0448;
- t['shaddaarabic'] = 0x0651;
- t['shaddadammaarabic'] = 0xFC61;
- t['shaddadammatanarabic'] = 0xFC5E;
- t['shaddafathaarabic'] = 0xFC60;
- t['shaddakasraarabic'] = 0xFC62;
- t['shaddakasratanarabic'] = 0xFC5F;
- t['shade'] = 0x2592;
- t['shadedark'] = 0x2593;
- t['shadelight'] = 0x2591;
- t['shademedium'] = 0x2592;
- t['shadeva'] = 0x0936;
- t['shagujarati'] = 0x0AB6;
- t['shagurmukhi'] = 0x0A36;
- t['shalshelethebrew'] = 0x0593;
- t['shbopomofo'] = 0x3115;
- t['shchacyrillic'] = 0x0449;
- t['sheenarabic'] = 0x0634;
- t['sheenfinalarabic'] = 0xFEB6;
- t['sheeninitialarabic'] = 0xFEB7;
- t['sheenmedialarabic'] = 0xFEB8;
- t['sheicoptic'] = 0x03E3;
- t['sheqel'] = 0x20AA;
- t['sheqelhebrew'] = 0x20AA;
- t['sheva'] = 0x05B0;
- t['sheva115'] = 0x05B0;
- t['sheva15'] = 0x05B0;
- t['sheva22'] = 0x05B0;
- t['sheva2e'] = 0x05B0;
- t['shevahebrew'] = 0x05B0;
- t['shevanarrowhebrew'] = 0x05B0;
- t['shevaquarterhebrew'] = 0x05B0;
- t['shevawidehebrew'] = 0x05B0;
- t['shhacyrillic'] = 0x04BB;
- t['shimacoptic'] = 0x03ED;
- t['shin'] = 0x05E9;
- t['shindagesh'] = 0xFB49;
- t['shindageshhebrew'] = 0xFB49;
- t['shindageshshindot'] = 0xFB2C;
- t['shindageshshindothebrew'] = 0xFB2C;
- t['shindageshsindot'] = 0xFB2D;
- t['shindageshsindothebrew'] = 0xFB2D;
- t['shindothebrew'] = 0x05C1;
- t['shinhebrew'] = 0x05E9;
- t['shinshindot'] = 0xFB2A;
- t['shinshindothebrew'] = 0xFB2A;
- t['shinsindot'] = 0xFB2B;
- t['shinsindothebrew'] = 0xFB2B;
- t['shook'] = 0x0282;
- t['sigma'] = 0x03C3;
- t['sigma1'] = 0x03C2;
- t['sigmafinal'] = 0x03C2;
- t['sigmalunatesymbolgreek'] = 0x03F2;
- t['sihiragana'] = 0x3057;
- t['sikatakana'] = 0x30B7;
- t['sikatakanahalfwidth'] = 0xFF7C;
- t['siluqhebrew'] = 0x05BD;
- t['siluqlefthebrew'] = 0x05BD;
- t['similar'] = 0x223C;
- t['sindothebrew'] = 0x05C2;
- t['siosacirclekorean'] = 0x3274;
- t['siosaparenkorean'] = 0x3214;
- t['sioscieuckorean'] = 0x317E;
- t['sioscirclekorean'] = 0x3266;
- t['sioskiyeokkorean'] = 0x317A;
- t['sioskorean'] = 0x3145;
- t['siosnieunkorean'] = 0x317B;
- t['siosparenkorean'] = 0x3206;
- t['siospieupkorean'] = 0x317D;
- t['siostikeutkorean'] = 0x317C;
- t['six'] = 0x0036;
- t['sixarabic'] = 0x0666;
- t['sixbengali'] = 0x09EC;
- t['sixcircle'] = 0x2465;
- t['sixcircleinversesansserif'] = 0x278F;
- t['sixdeva'] = 0x096C;
- t['sixgujarati'] = 0x0AEC;
- t['sixgurmukhi'] = 0x0A6C;
- t['sixhackarabic'] = 0x0666;
- t['sixhangzhou'] = 0x3026;
- t['sixideographicparen'] = 0x3225;
- t['sixinferior'] = 0x2086;
- t['sixmonospace'] = 0xFF16;
- t['sixoldstyle'] = 0xF736;
- t['sixparen'] = 0x2479;
- t['sixperiod'] = 0x248D;
- t['sixpersian'] = 0x06F6;
- t['sixroman'] = 0x2175;
- t['sixsuperior'] = 0x2076;
- t['sixteencircle'] = 0x246F;
- t['sixteencurrencydenominatorbengali'] = 0x09F9;
- t['sixteenparen'] = 0x2483;
- t['sixteenperiod'] = 0x2497;
- t['sixthai'] = 0x0E56;
- t['slash'] = 0x002F;
- t['slashmonospace'] = 0xFF0F;
- t['slong'] = 0x017F;
- t['slongdotaccent'] = 0x1E9B;
- t['smileface'] = 0x263A;
- t['smonospace'] = 0xFF53;
- t['sofpasuqhebrew'] = 0x05C3;
- t['softhyphen'] = 0x00AD;
- t['softsigncyrillic'] = 0x044C;
- t['sohiragana'] = 0x305D;
- t['sokatakana'] = 0x30BD;
- t['sokatakanahalfwidth'] = 0xFF7F;
- t['soliduslongoverlaycmb'] = 0x0338;
- t['solidusshortoverlaycmb'] = 0x0337;
- t['sorusithai'] = 0x0E29;
- t['sosalathai'] = 0x0E28;
- t['sosothai'] = 0x0E0B;
- t['sosuathai'] = 0x0E2A;
- t['space'] = 0x0020;
- t['spacehackarabic'] = 0x0020;
- t['spade'] = 0x2660;
- t['spadesuitblack'] = 0x2660;
- t['spadesuitwhite'] = 0x2664;
- t['sparen'] = 0x24AE;
- t['squarebelowcmb'] = 0x033B;
- t['squarecc'] = 0x33C4;
- t['squarecm'] = 0x339D;
- t['squarediagonalcrosshatchfill'] = 0x25A9;
- t['squarehorizontalfill'] = 0x25A4;
- t['squarekg'] = 0x338F;
- t['squarekm'] = 0x339E;
- t['squarekmcapital'] = 0x33CE;
- t['squareln'] = 0x33D1;
- t['squarelog'] = 0x33D2;
- t['squaremg'] = 0x338E;
- t['squaremil'] = 0x33D5;
- t['squaremm'] = 0x339C;
- t['squaremsquared'] = 0x33A1;
- t['squareorthogonalcrosshatchfill'] = 0x25A6;
- t['squareupperlefttolowerrightfill'] = 0x25A7;
- t['squareupperrighttolowerleftfill'] = 0x25A8;
- t['squareverticalfill'] = 0x25A5;
- t['squarewhitewithsmallblack'] = 0x25A3;
- t['srsquare'] = 0x33DB;
- t['ssabengali'] = 0x09B7;
- t['ssadeva'] = 0x0937;
- t['ssagujarati'] = 0x0AB7;
- t['ssangcieuckorean'] = 0x3149;
- t['ssanghieuhkorean'] = 0x3185;
- t['ssangieungkorean'] = 0x3180;
- t['ssangkiyeokkorean'] = 0x3132;
- t['ssangnieunkorean'] = 0x3165;
- t['ssangpieupkorean'] = 0x3143;
- t['ssangsioskorean'] = 0x3146;
- t['ssangtikeutkorean'] = 0x3138;
- t['ssuperior'] = 0xF6F2;
- t['sterling'] = 0x00A3;
- t['sterlingmonospace'] = 0xFFE1;
- t['strokelongoverlaycmb'] = 0x0336;
- t['strokeshortoverlaycmb'] = 0x0335;
- t['subset'] = 0x2282;
- t['subsetnotequal'] = 0x228A;
- t['subsetorequal'] = 0x2286;
- t['succeeds'] = 0x227B;
- t['suchthat'] = 0x220B;
- t['suhiragana'] = 0x3059;
- t['sukatakana'] = 0x30B9;
- t['sukatakanahalfwidth'] = 0xFF7D;
- t['sukunarabic'] = 0x0652;
- t['summation'] = 0x2211;
- t['sun'] = 0x263C;
- t['superset'] = 0x2283;
- t['supersetnotequal'] = 0x228B;
- t['supersetorequal'] = 0x2287;
- t['svsquare'] = 0x33DC;
- t['syouwaerasquare'] = 0x337C;
- t['t'] = 0x0074;
- t['tabengali'] = 0x09A4;
- t['tackdown'] = 0x22A4;
- t['tackleft'] = 0x22A3;
- t['tadeva'] = 0x0924;
- t['tagujarati'] = 0x0AA4;
- t['tagurmukhi'] = 0x0A24;
- t['taharabic'] = 0x0637;
- t['tahfinalarabic'] = 0xFEC2;
- t['tahinitialarabic'] = 0xFEC3;
- t['tahiragana'] = 0x305F;
- t['tahmedialarabic'] = 0xFEC4;
- t['taisyouerasquare'] = 0x337D;
- t['takatakana'] = 0x30BF;
- t['takatakanahalfwidth'] = 0xFF80;
- t['tatweelarabic'] = 0x0640;
- t['tau'] = 0x03C4;
- t['tav'] = 0x05EA;
- t['tavdages'] = 0xFB4A;
- t['tavdagesh'] = 0xFB4A;
- t['tavdageshhebrew'] = 0xFB4A;
- t['tavhebrew'] = 0x05EA;
- t['tbar'] = 0x0167;
- t['tbopomofo'] = 0x310A;
- t['tcaron'] = 0x0165;
- t['tccurl'] = 0x02A8;
- t['tcedilla'] = 0x0163;
- t['tcheharabic'] = 0x0686;
- t['tchehfinalarabic'] = 0xFB7B;
- t['tchehinitialarabic'] = 0xFB7C;
- t['tchehmedialarabic'] = 0xFB7D;
- t['tcircle'] = 0x24E3;
- t['tcircumflexbelow'] = 0x1E71;
- t['tcommaaccent'] = 0x0163;
- t['tdieresis'] = 0x1E97;
- t['tdotaccent'] = 0x1E6B;
- t['tdotbelow'] = 0x1E6D;
- t['tecyrillic'] = 0x0442;
- t['tedescendercyrillic'] = 0x04AD;
- t['teharabic'] = 0x062A;
- t['tehfinalarabic'] = 0xFE96;
- t['tehhahinitialarabic'] = 0xFCA2;
- t['tehhahisolatedarabic'] = 0xFC0C;
- t['tehinitialarabic'] = 0xFE97;
- t['tehiragana'] = 0x3066;
- t['tehjeeminitialarabic'] = 0xFCA1;
- t['tehjeemisolatedarabic'] = 0xFC0B;
- t['tehmarbutaarabic'] = 0x0629;
- t['tehmarbutafinalarabic'] = 0xFE94;
- t['tehmedialarabic'] = 0xFE98;
- t['tehmeeminitialarabic'] = 0xFCA4;
- t['tehmeemisolatedarabic'] = 0xFC0E;
- t['tehnoonfinalarabic'] = 0xFC73;
- t['tekatakana'] = 0x30C6;
- t['tekatakanahalfwidth'] = 0xFF83;
- t['telephone'] = 0x2121;
- t['telephoneblack'] = 0x260E;
- t['telishagedolahebrew'] = 0x05A0;
- t['telishaqetanahebrew'] = 0x05A9;
- t['tencircle'] = 0x2469;
- t['tenideographicparen'] = 0x3229;
- t['tenparen'] = 0x247D;
- t['tenperiod'] = 0x2491;
- t['tenroman'] = 0x2179;
- t['tesh'] = 0x02A7;
- t['tet'] = 0x05D8;
- t['tetdagesh'] = 0xFB38;
- t['tetdageshhebrew'] = 0xFB38;
- t['tethebrew'] = 0x05D8;
- t['tetsecyrillic'] = 0x04B5;
- t['tevirhebrew'] = 0x059B;
- t['tevirlefthebrew'] = 0x059B;
- t['thabengali'] = 0x09A5;
- t['thadeva'] = 0x0925;
- t['thagujarati'] = 0x0AA5;
- t['thagurmukhi'] = 0x0A25;
- t['thalarabic'] = 0x0630;
- t['thalfinalarabic'] = 0xFEAC;
- t['thanthakhatlowleftthai'] = 0xF898;
- t['thanthakhatlowrightthai'] = 0xF897;
- t['thanthakhatthai'] = 0x0E4C;
- t['thanthakhatupperleftthai'] = 0xF896;
- t['theharabic'] = 0x062B;
- t['thehfinalarabic'] = 0xFE9A;
- t['thehinitialarabic'] = 0xFE9B;
- t['thehmedialarabic'] = 0xFE9C;
- t['thereexists'] = 0x2203;
- t['therefore'] = 0x2234;
- t['theta'] = 0x03B8;
- t['theta1'] = 0x03D1;
- t['thetasymbolgreek'] = 0x03D1;
- t['thieuthacirclekorean'] = 0x3279;
- t['thieuthaparenkorean'] = 0x3219;
- t['thieuthcirclekorean'] = 0x326B;
- t['thieuthkorean'] = 0x314C;
- t['thieuthparenkorean'] = 0x320B;
- t['thirteencircle'] = 0x246C;
- t['thirteenparen'] = 0x2480;
- t['thirteenperiod'] = 0x2494;
- t['thonangmonthothai'] = 0x0E11;
- t['thook'] = 0x01AD;
- t['thophuthaothai'] = 0x0E12;
- t['thorn'] = 0x00FE;
- t['thothahanthai'] = 0x0E17;
- t['thothanthai'] = 0x0E10;
- t['thothongthai'] = 0x0E18;
- t['thothungthai'] = 0x0E16;
- t['thousandcyrillic'] = 0x0482;
- t['thousandsseparatorarabic'] = 0x066C;
- t['thousandsseparatorpersian'] = 0x066C;
- t['three'] = 0x0033;
- t['threearabic'] = 0x0663;
- t['threebengali'] = 0x09E9;
- t['threecircle'] = 0x2462;
- t['threecircleinversesansserif'] = 0x278C;
- t['threedeva'] = 0x0969;
- t['threeeighths'] = 0x215C;
- t['threegujarati'] = 0x0AE9;
- t['threegurmukhi'] = 0x0A69;
- t['threehackarabic'] = 0x0663;
- t['threehangzhou'] = 0x3023;
- t['threeideographicparen'] = 0x3222;
- t['threeinferior'] = 0x2083;
- t['threemonospace'] = 0xFF13;
- t['threenumeratorbengali'] = 0x09F6;
- t['threeoldstyle'] = 0xF733;
- t['threeparen'] = 0x2476;
- t['threeperiod'] = 0x248A;
- t['threepersian'] = 0x06F3;
- t['threequarters'] = 0x00BE;
- t['threequartersemdash'] = 0xF6DE;
- t['threeroman'] = 0x2172;
- t['threesuperior'] = 0x00B3;
- t['threethai'] = 0x0E53;
- t['thzsquare'] = 0x3394;
- t['tihiragana'] = 0x3061;
- t['tikatakana'] = 0x30C1;
- t['tikatakanahalfwidth'] = 0xFF81;
- t['tikeutacirclekorean'] = 0x3270;
- t['tikeutaparenkorean'] = 0x3210;
- t['tikeutcirclekorean'] = 0x3262;
- t['tikeutkorean'] = 0x3137;
- t['tikeutparenkorean'] = 0x3202;
- t['tilde'] = 0x02DC;
- t['tildebelowcmb'] = 0x0330;
- t['tildecmb'] = 0x0303;
- t['tildecomb'] = 0x0303;
- t['tildedoublecmb'] = 0x0360;
- t['tildeoperator'] = 0x223C;
- t['tildeoverlaycmb'] = 0x0334;
- t['tildeverticalcmb'] = 0x033E;
- t['timescircle'] = 0x2297;
- t['tipehahebrew'] = 0x0596;
- t['tipehalefthebrew'] = 0x0596;
- t['tippigurmukhi'] = 0x0A70;
- t['titlocyrilliccmb'] = 0x0483;
- t['tiwnarmenian'] = 0x057F;
- t['tlinebelow'] = 0x1E6F;
- t['tmonospace'] = 0xFF54;
- t['toarmenian'] = 0x0569;
- t['tohiragana'] = 0x3068;
- t['tokatakana'] = 0x30C8;
- t['tokatakanahalfwidth'] = 0xFF84;
- t['tonebarextrahighmod'] = 0x02E5;
- t['tonebarextralowmod'] = 0x02E9;
- t['tonebarhighmod'] = 0x02E6;
- t['tonebarlowmod'] = 0x02E8;
- t['tonebarmidmod'] = 0x02E7;
- t['tonefive'] = 0x01BD;
- t['tonesix'] = 0x0185;
- t['tonetwo'] = 0x01A8;
- t['tonos'] = 0x0384;
- t['tonsquare'] = 0x3327;
- t['topatakthai'] = 0x0E0F;
- t['tortoiseshellbracketleft'] = 0x3014;
- t['tortoiseshellbracketleftsmall'] = 0xFE5D;
- t['tortoiseshellbracketleftvertical'] = 0xFE39;
- t['tortoiseshellbracketright'] = 0x3015;
- t['tortoiseshellbracketrightsmall'] = 0xFE5E;
- t['tortoiseshellbracketrightvertical'] = 0xFE3A;
- t['totaothai'] = 0x0E15;
- t['tpalatalhook'] = 0x01AB;
- t['tparen'] = 0x24AF;
- t['trademark'] = 0x2122;
- t['trademarksans'] = 0xF8EA;
- t['trademarkserif'] = 0xF6DB;
- t['tretroflexhook'] = 0x0288;
- t['triagdn'] = 0x25BC;
- t['triaglf'] = 0x25C4;
- t['triagrt'] = 0x25BA;
- t['triagup'] = 0x25B2;
- t['ts'] = 0x02A6;
- t['tsadi'] = 0x05E6;
- t['tsadidagesh'] = 0xFB46;
- t['tsadidageshhebrew'] = 0xFB46;
- t['tsadihebrew'] = 0x05E6;
- t['tsecyrillic'] = 0x0446;
- t['tsere'] = 0x05B5;
- t['tsere12'] = 0x05B5;
- t['tsere1e'] = 0x05B5;
- t['tsere2b'] = 0x05B5;
- t['tserehebrew'] = 0x05B5;
- t['tserenarrowhebrew'] = 0x05B5;
- t['tserequarterhebrew'] = 0x05B5;
- t['tserewidehebrew'] = 0x05B5;
- t['tshecyrillic'] = 0x045B;
- t['tsuperior'] = 0xF6F3;
- t['ttabengali'] = 0x099F;
- t['ttadeva'] = 0x091F;
- t['ttagujarati'] = 0x0A9F;
- t['ttagurmukhi'] = 0x0A1F;
- t['tteharabic'] = 0x0679;
- t['ttehfinalarabic'] = 0xFB67;
- t['ttehinitialarabic'] = 0xFB68;
- t['ttehmedialarabic'] = 0xFB69;
- t['tthabengali'] = 0x09A0;
- t['tthadeva'] = 0x0920;
- t['tthagujarati'] = 0x0AA0;
- t['tthagurmukhi'] = 0x0A20;
- t['tturned'] = 0x0287;
- t['tuhiragana'] = 0x3064;
- t['tukatakana'] = 0x30C4;
- t['tukatakanahalfwidth'] = 0xFF82;
- t['tusmallhiragana'] = 0x3063;
- t['tusmallkatakana'] = 0x30C3;
- t['tusmallkatakanahalfwidth'] = 0xFF6F;
- t['twelvecircle'] = 0x246B;
- t['twelveparen'] = 0x247F;
- t['twelveperiod'] = 0x2493;
- t['twelveroman'] = 0x217B;
- t['twentycircle'] = 0x2473;
- t['twentyhangzhou'] = 0x5344;
- t['twentyparen'] = 0x2487;
- t['twentyperiod'] = 0x249B;
- t['two'] = 0x0032;
- t['twoarabic'] = 0x0662;
- t['twobengali'] = 0x09E8;
- t['twocircle'] = 0x2461;
- t['twocircleinversesansserif'] = 0x278B;
- t['twodeva'] = 0x0968;
- t['twodotenleader'] = 0x2025;
- t['twodotleader'] = 0x2025;
- t['twodotleadervertical'] = 0xFE30;
- t['twogujarati'] = 0x0AE8;
- t['twogurmukhi'] = 0x0A68;
- t['twohackarabic'] = 0x0662;
- t['twohangzhou'] = 0x3022;
- t['twoideographicparen'] = 0x3221;
- t['twoinferior'] = 0x2082;
- t['twomonospace'] = 0xFF12;
- t['twonumeratorbengali'] = 0x09F5;
- t['twooldstyle'] = 0xF732;
- t['twoparen'] = 0x2475;
- t['twoperiod'] = 0x2489;
- t['twopersian'] = 0x06F2;
- t['tworoman'] = 0x2171;
- t['twostroke'] = 0x01BB;
- t['twosuperior'] = 0x00B2;
- t['twothai'] = 0x0E52;
- t['twothirds'] = 0x2154;
- t['u'] = 0x0075;
- t['uacute'] = 0x00FA;
- t['ubar'] = 0x0289;
- t['ubengali'] = 0x0989;
- t['ubopomofo'] = 0x3128;
- t['ubreve'] = 0x016D;
- t['ucaron'] = 0x01D4;
- t['ucircle'] = 0x24E4;
- t['ucircumflex'] = 0x00FB;
- t['ucircumflexbelow'] = 0x1E77;
- t['ucyrillic'] = 0x0443;
- t['udattadeva'] = 0x0951;
- t['udblacute'] = 0x0171;
- t['udblgrave'] = 0x0215;
- t['udeva'] = 0x0909;
- t['udieresis'] = 0x00FC;
- t['udieresisacute'] = 0x01D8;
- t['udieresisbelow'] = 0x1E73;
- t['udieresiscaron'] = 0x01DA;
- t['udieresiscyrillic'] = 0x04F1;
- t['udieresisgrave'] = 0x01DC;
- t['udieresismacron'] = 0x01D6;
- t['udotbelow'] = 0x1EE5;
- t['ugrave'] = 0x00F9;
- t['ugujarati'] = 0x0A89;
- t['ugurmukhi'] = 0x0A09;
- t['uhiragana'] = 0x3046;
- t['uhookabove'] = 0x1EE7;
- t['uhorn'] = 0x01B0;
- t['uhornacute'] = 0x1EE9;
- t['uhorndotbelow'] = 0x1EF1;
- t['uhorngrave'] = 0x1EEB;
- t['uhornhookabove'] = 0x1EED;
- t['uhorntilde'] = 0x1EEF;
- t['uhungarumlaut'] = 0x0171;
- t['uhungarumlautcyrillic'] = 0x04F3;
- t['uinvertedbreve'] = 0x0217;
- t['ukatakana'] = 0x30A6;
- t['ukatakanahalfwidth'] = 0xFF73;
- t['ukcyrillic'] = 0x0479;
- t['ukorean'] = 0x315C;
- t['umacron'] = 0x016B;
- t['umacroncyrillic'] = 0x04EF;
- t['umacrondieresis'] = 0x1E7B;
- t['umatragurmukhi'] = 0x0A41;
- t['umonospace'] = 0xFF55;
- t['underscore'] = 0x005F;
- t['underscoredbl'] = 0x2017;
- t['underscoremonospace'] = 0xFF3F;
- t['underscorevertical'] = 0xFE33;
- t['underscorewavy'] = 0xFE4F;
- t['union'] = 0x222A;
- t['universal'] = 0x2200;
- t['uogonek'] = 0x0173;
- t['uparen'] = 0x24B0;
- t['upblock'] = 0x2580;
- t['upperdothebrew'] = 0x05C4;
- t['upsilon'] = 0x03C5;
- t['upsilondieresis'] = 0x03CB;
- t['upsilondieresistonos'] = 0x03B0;
- t['upsilonlatin'] = 0x028A;
- t['upsilontonos'] = 0x03CD;
- t['uptackbelowcmb'] = 0x031D;
- t['uptackmod'] = 0x02D4;
- t['uragurmukhi'] = 0x0A73;
- t['uring'] = 0x016F;
- t['ushortcyrillic'] = 0x045E;
- t['usmallhiragana'] = 0x3045;
- t['usmallkatakana'] = 0x30A5;
- t['usmallkatakanahalfwidth'] = 0xFF69;
- t['ustraightcyrillic'] = 0x04AF;
- t['ustraightstrokecyrillic'] = 0x04B1;
- t['utilde'] = 0x0169;
- t['utildeacute'] = 0x1E79;
- t['utildebelow'] = 0x1E75;
- t['uubengali'] = 0x098A;
- t['uudeva'] = 0x090A;
- t['uugujarati'] = 0x0A8A;
- t['uugurmukhi'] = 0x0A0A;
- t['uumatragurmukhi'] = 0x0A42;
- t['uuvowelsignbengali'] = 0x09C2;
- t['uuvowelsigndeva'] = 0x0942;
- t['uuvowelsigngujarati'] = 0x0AC2;
- t['uvowelsignbengali'] = 0x09C1;
- t['uvowelsigndeva'] = 0x0941;
- t['uvowelsigngujarati'] = 0x0AC1;
- t['v'] = 0x0076;
- t['vadeva'] = 0x0935;
- t['vagujarati'] = 0x0AB5;
- t['vagurmukhi'] = 0x0A35;
- t['vakatakana'] = 0x30F7;
- t['vav'] = 0x05D5;
- t['vavdagesh'] = 0xFB35;
- t['vavdagesh65'] = 0xFB35;
- t['vavdageshhebrew'] = 0xFB35;
- t['vavhebrew'] = 0x05D5;
- t['vavholam'] = 0xFB4B;
- t['vavholamhebrew'] = 0xFB4B;
- t['vavvavhebrew'] = 0x05F0;
- t['vavyodhebrew'] = 0x05F1;
- t['vcircle'] = 0x24E5;
- t['vdotbelow'] = 0x1E7F;
- t['vecyrillic'] = 0x0432;
- t['veharabic'] = 0x06A4;
- t['vehfinalarabic'] = 0xFB6B;
- t['vehinitialarabic'] = 0xFB6C;
- t['vehmedialarabic'] = 0xFB6D;
- t['vekatakana'] = 0x30F9;
- t['venus'] = 0x2640;
- t['verticalbar'] = 0x007C;
- t['verticallineabovecmb'] = 0x030D;
- t['verticallinebelowcmb'] = 0x0329;
- t['verticallinelowmod'] = 0x02CC;
- t['verticallinemod'] = 0x02C8;
- t['vewarmenian'] = 0x057E;
- t['vhook'] = 0x028B;
- t['vikatakana'] = 0x30F8;
- t['viramabengali'] = 0x09CD;
- t['viramadeva'] = 0x094D;
- t['viramagujarati'] = 0x0ACD;
- t['visargabengali'] = 0x0983;
- t['visargadeva'] = 0x0903;
- t['visargagujarati'] = 0x0A83;
- t['vmonospace'] = 0xFF56;
- t['voarmenian'] = 0x0578;
- t['voicediterationhiragana'] = 0x309E;
- t['voicediterationkatakana'] = 0x30FE;
- t['voicedmarkkana'] = 0x309B;
- t['voicedmarkkanahalfwidth'] = 0xFF9E;
- t['vokatakana'] = 0x30FA;
- t['vparen'] = 0x24B1;
- t['vtilde'] = 0x1E7D;
- t['vturned'] = 0x028C;
- t['vuhiragana'] = 0x3094;
- t['vukatakana'] = 0x30F4;
- t['w'] = 0x0077;
- t['wacute'] = 0x1E83;
- t['waekorean'] = 0x3159;
- t['wahiragana'] = 0x308F;
- t['wakatakana'] = 0x30EF;
- t['wakatakanahalfwidth'] = 0xFF9C;
- t['wakorean'] = 0x3158;
- t['wasmallhiragana'] = 0x308E;
- t['wasmallkatakana'] = 0x30EE;
- t['wattosquare'] = 0x3357;
- t['wavedash'] = 0x301C;
- t['wavyunderscorevertical'] = 0xFE34;
- t['wawarabic'] = 0x0648;
- t['wawfinalarabic'] = 0xFEEE;
- t['wawhamzaabovearabic'] = 0x0624;
- t['wawhamzaabovefinalarabic'] = 0xFE86;
- t['wbsquare'] = 0x33DD;
- t['wcircle'] = 0x24E6;
- t['wcircumflex'] = 0x0175;
- t['wdieresis'] = 0x1E85;
- t['wdotaccent'] = 0x1E87;
- t['wdotbelow'] = 0x1E89;
- t['wehiragana'] = 0x3091;
- t['weierstrass'] = 0x2118;
- t['wekatakana'] = 0x30F1;
- t['wekorean'] = 0x315E;
- t['weokorean'] = 0x315D;
- t['wgrave'] = 0x1E81;
- t['whitebullet'] = 0x25E6;
- t['whitecircle'] = 0x25CB;
- t['whitecircleinverse'] = 0x25D9;
- t['whitecornerbracketleft'] = 0x300E;
- t['whitecornerbracketleftvertical'] = 0xFE43;
- t['whitecornerbracketright'] = 0x300F;
- t['whitecornerbracketrightvertical'] = 0xFE44;
- t['whitediamond'] = 0x25C7;
- t['whitediamondcontainingblacksmalldiamond'] = 0x25C8;
- t['whitedownpointingsmalltriangle'] = 0x25BF;
- t['whitedownpointingtriangle'] = 0x25BD;
- t['whiteleftpointingsmalltriangle'] = 0x25C3;
- t['whiteleftpointingtriangle'] = 0x25C1;
- t['whitelenticularbracketleft'] = 0x3016;
- t['whitelenticularbracketright'] = 0x3017;
- t['whiterightpointingsmalltriangle'] = 0x25B9;
- t['whiterightpointingtriangle'] = 0x25B7;
- t['whitesmallsquare'] = 0x25AB;
- t['whitesmilingface'] = 0x263A;
- t['whitesquare'] = 0x25A1;
- t['whitestar'] = 0x2606;
- t['whitetelephone'] = 0x260F;
- t['whitetortoiseshellbracketleft'] = 0x3018;
- t['whitetortoiseshellbracketright'] = 0x3019;
- t['whiteuppointingsmalltriangle'] = 0x25B5;
- t['whiteuppointingtriangle'] = 0x25B3;
- t['wihiragana'] = 0x3090;
- t['wikatakana'] = 0x30F0;
- t['wikorean'] = 0x315F;
- t['wmonospace'] = 0xFF57;
- t['wohiragana'] = 0x3092;
- t['wokatakana'] = 0x30F2;
- t['wokatakanahalfwidth'] = 0xFF66;
- t['won'] = 0x20A9;
- t['wonmonospace'] = 0xFFE6;
- t['wowaenthai'] = 0x0E27;
- t['wparen'] = 0x24B2;
- t['wring'] = 0x1E98;
- t['wsuperior'] = 0x02B7;
- t['wturned'] = 0x028D;
- t['wynn'] = 0x01BF;
- t['x'] = 0x0078;
- t['xabovecmb'] = 0x033D;
- t['xbopomofo'] = 0x3112;
- t['xcircle'] = 0x24E7;
- t['xdieresis'] = 0x1E8D;
- t['xdotaccent'] = 0x1E8B;
- t['xeharmenian'] = 0x056D;
- t['xi'] = 0x03BE;
- t['xmonospace'] = 0xFF58;
- t['xparen'] = 0x24B3;
- t['xsuperior'] = 0x02E3;
- t['y'] = 0x0079;
- t['yaadosquare'] = 0x334E;
- t['yabengali'] = 0x09AF;
- t['yacute'] = 0x00FD;
- t['yadeva'] = 0x092F;
- t['yaekorean'] = 0x3152;
- t['yagujarati'] = 0x0AAF;
- t['yagurmukhi'] = 0x0A2F;
- t['yahiragana'] = 0x3084;
- t['yakatakana'] = 0x30E4;
- t['yakatakanahalfwidth'] = 0xFF94;
- t['yakorean'] = 0x3151;
- t['yamakkanthai'] = 0x0E4E;
- t['yasmallhiragana'] = 0x3083;
- t['yasmallkatakana'] = 0x30E3;
- t['yasmallkatakanahalfwidth'] = 0xFF6C;
- t['yatcyrillic'] = 0x0463;
- t['ycircle'] = 0x24E8;
- t['ycircumflex'] = 0x0177;
- t['ydieresis'] = 0x00FF;
- t['ydotaccent'] = 0x1E8F;
- t['ydotbelow'] = 0x1EF5;
- t['yeharabic'] = 0x064A;
- t['yehbarreearabic'] = 0x06D2;
- t['yehbarreefinalarabic'] = 0xFBAF;
- t['yehfinalarabic'] = 0xFEF2;
- t['yehhamzaabovearabic'] = 0x0626;
- t['yehhamzaabovefinalarabic'] = 0xFE8A;
- t['yehhamzaaboveinitialarabic'] = 0xFE8B;
- t['yehhamzaabovemedialarabic'] = 0xFE8C;
- t['yehinitialarabic'] = 0xFEF3;
- t['yehmedialarabic'] = 0xFEF4;
- t['yehmeeminitialarabic'] = 0xFCDD;
- t['yehmeemisolatedarabic'] = 0xFC58;
- t['yehnoonfinalarabic'] = 0xFC94;
- t['yehthreedotsbelowarabic'] = 0x06D1;
- t['yekorean'] = 0x3156;
- t['yen'] = 0x00A5;
- t['yenmonospace'] = 0xFFE5;
- t['yeokorean'] = 0x3155;
- t['yeorinhieuhkorean'] = 0x3186;
- t['yerahbenyomohebrew'] = 0x05AA;
- t['yerahbenyomolefthebrew'] = 0x05AA;
- t['yericyrillic'] = 0x044B;
- t['yerudieresiscyrillic'] = 0x04F9;
- t['yesieungkorean'] = 0x3181;
- t['yesieungpansioskorean'] = 0x3183;
- t['yesieungsioskorean'] = 0x3182;
- t['yetivhebrew'] = 0x059A;
- t['ygrave'] = 0x1EF3;
- t['yhook'] = 0x01B4;
- t['yhookabove'] = 0x1EF7;
- t['yiarmenian'] = 0x0575;
- t['yicyrillic'] = 0x0457;
- t['yikorean'] = 0x3162;
- t['yinyang'] = 0x262F;
- t['yiwnarmenian'] = 0x0582;
- t['ymonospace'] = 0xFF59;
- t['yod'] = 0x05D9;
- t['yoddagesh'] = 0xFB39;
- t['yoddageshhebrew'] = 0xFB39;
- t['yodhebrew'] = 0x05D9;
- t['yodyodhebrew'] = 0x05F2;
- t['yodyodpatahhebrew'] = 0xFB1F;
- t['yohiragana'] = 0x3088;
- t['yoikorean'] = 0x3189;
- t['yokatakana'] = 0x30E8;
- t['yokatakanahalfwidth'] = 0xFF96;
- t['yokorean'] = 0x315B;
- t['yosmallhiragana'] = 0x3087;
- t['yosmallkatakana'] = 0x30E7;
- t['yosmallkatakanahalfwidth'] = 0xFF6E;
- t['yotgreek'] = 0x03F3;
- t['yoyaekorean'] = 0x3188;
- t['yoyakorean'] = 0x3187;
- t['yoyakthai'] = 0x0E22;
- t['yoyingthai'] = 0x0E0D;
- t['yparen'] = 0x24B4;
- t['ypogegrammeni'] = 0x037A;
- t['ypogegrammenigreekcmb'] = 0x0345;
- t['yr'] = 0x01A6;
- t['yring'] = 0x1E99;
- t['ysuperior'] = 0x02B8;
- t['ytilde'] = 0x1EF9;
- t['yturned'] = 0x028E;
- t['yuhiragana'] = 0x3086;
- t['yuikorean'] = 0x318C;
- t['yukatakana'] = 0x30E6;
- t['yukatakanahalfwidth'] = 0xFF95;
- t['yukorean'] = 0x3160;
- t['yusbigcyrillic'] = 0x046B;
- t['yusbigiotifiedcyrillic'] = 0x046D;
- t['yuslittlecyrillic'] = 0x0467;
- t['yuslittleiotifiedcyrillic'] = 0x0469;
- t['yusmallhiragana'] = 0x3085;
- t['yusmallkatakana'] = 0x30E5;
- t['yusmallkatakanahalfwidth'] = 0xFF6D;
- t['yuyekorean'] = 0x318B;
- t['yuyeokorean'] = 0x318A;
- t['yyabengali'] = 0x09DF;
- t['yyadeva'] = 0x095F;
- t['z'] = 0x007A;
- t['zaarmenian'] = 0x0566;
- t['zacute'] = 0x017A;
- t['zadeva'] = 0x095B;
- t['zagurmukhi'] = 0x0A5B;
- t['zaharabic'] = 0x0638;
- t['zahfinalarabic'] = 0xFEC6;
- t['zahinitialarabic'] = 0xFEC7;
- t['zahiragana'] = 0x3056;
- t['zahmedialarabic'] = 0xFEC8;
- t['zainarabic'] = 0x0632;
- t['zainfinalarabic'] = 0xFEB0;
- t['zakatakana'] = 0x30B6;
- t['zaqefgadolhebrew'] = 0x0595;
- t['zaqefqatanhebrew'] = 0x0594;
- t['zarqahebrew'] = 0x0598;
- t['zayin'] = 0x05D6;
- t['zayindagesh'] = 0xFB36;
- t['zayindageshhebrew'] = 0xFB36;
- t['zayinhebrew'] = 0x05D6;
- t['zbopomofo'] = 0x3117;
- t['zcaron'] = 0x017E;
- t['zcircle'] = 0x24E9;
- t['zcircumflex'] = 0x1E91;
- t['zcurl'] = 0x0291;
- t['zdot'] = 0x017C;
- t['zdotaccent'] = 0x017C;
- t['zdotbelow'] = 0x1E93;
- t['zecyrillic'] = 0x0437;
- t['zedescendercyrillic'] = 0x0499;
- t['zedieresiscyrillic'] = 0x04DF;
- t['zehiragana'] = 0x305C;
- t['zekatakana'] = 0x30BC;
- t['zero'] = 0x0030;
- t['zeroarabic'] = 0x0660;
- t['zerobengali'] = 0x09E6;
- t['zerodeva'] = 0x0966;
- t['zerogujarati'] = 0x0AE6;
- t['zerogurmukhi'] = 0x0A66;
- t['zerohackarabic'] = 0x0660;
- t['zeroinferior'] = 0x2080;
- t['zeromonospace'] = 0xFF10;
- t['zerooldstyle'] = 0xF730;
- t['zeropersian'] = 0x06F0;
- t['zerosuperior'] = 0x2070;
- t['zerothai'] = 0x0E50;
- t['zerowidthjoiner'] = 0xFEFF;
- t['zerowidthnonjoiner'] = 0x200C;
- t['zerowidthspace'] = 0x200B;
- t['zeta'] = 0x03B6;
- t['zhbopomofo'] = 0x3113;
- t['zhearmenian'] = 0x056A;
- t['zhebrevecyrillic'] = 0x04C2;
- t['zhecyrillic'] = 0x0436;
- t['zhedescendercyrillic'] = 0x0497;
- t['zhedieresiscyrillic'] = 0x04DD;
- t['zihiragana'] = 0x3058;
- t['zikatakana'] = 0x30B8;
- t['zinorhebrew'] = 0x05AE;
- t['zlinebelow'] = 0x1E95;
- t['zmonospace'] = 0xFF5A;
- t['zohiragana'] = 0x305E;
- t['zokatakana'] = 0x30BE;
- t['zparen'] = 0x24B5;
- t['zretroflexhook'] = 0x0290;
- t['zstroke'] = 0x01B6;
- t['zuhiragana'] = 0x305A;
- t['zukatakana'] = 0x30BA;
- t['.notdef'] = 0x0000;
- t['angbracketleftbig'] = 0x2329;
- t['angbracketleftBig'] = 0x2329;
- t['angbracketleftbigg'] = 0x2329;
- t['angbracketleftBigg'] = 0x2329;
- t['angbracketrightBig'] = 0x232A;
- t['angbracketrightbig'] = 0x232A;
- t['angbracketrightBigg'] = 0x232A;
- t['angbracketrightbigg'] = 0x232A;
- t['arrowhookleft'] = 0x21AA;
- t['arrowhookright'] = 0x21A9;
- t['arrowlefttophalf'] = 0x21BC;
- t['arrowleftbothalf'] = 0x21BD;
- t['arrownortheast'] = 0x2197;
- t['arrownorthwest'] = 0x2196;
- t['arrowrighttophalf'] = 0x21C0;
- t['arrowrightbothalf'] = 0x21C1;
- t['arrowsoutheast'] = 0x2198;
- t['arrowsouthwest'] = 0x2199;
- t['backslashbig'] = 0x2216;
- t['backslashBig'] = 0x2216;
- t['backslashBigg'] = 0x2216;
- t['backslashbigg'] = 0x2216;
- t['bardbl'] = 0x2016;
- t['bracehtipdownleft'] = 0xFE37;
- t['bracehtipdownright'] = 0xFE37;
- t['bracehtipupleft'] = 0xFE38;
- t['bracehtipupright'] = 0xFE38;
- t['braceleftBig'] = 0x007B;
- t['braceleftbig'] = 0x007B;
- t['braceleftbigg'] = 0x007B;
- t['braceleftBigg'] = 0x007B;
- t['bracerightBig'] = 0x007D;
- t['bracerightbig'] = 0x007D;
- t['bracerightbigg'] = 0x007D;
- t['bracerightBigg'] = 0x007D;
- t['bracketleftbig'] = 0x005B;
- t['bracketleftBig'] = 0x005B;
- t['bracketleftbigg'] = 0x005B;
- t['bracketleftBigg'] = 0x005B;
- t['bracketrightBig'] = 0x005D;
- t['bracketrightbig'] = 0x005D;
- t['bracketrightbigg'] = 0x005D;
- t['bracketrightBigg'] = 0x005D;
- t['ceilingleftbig'] = 0x2308;
- t['ceilingleftBig'] = 0x2308;
- t['ceilingleftBigg'] = 0x2308;
- t['ceilingleftbigg'] = 0x2308;
- t['ceilingrightbig'] = 0x2309;
- t['ceilingrightBig'] = 0x2309;
- t['ceilingrightbigg'] = 0x2309;
- t['ceilingrightBigg'] = 0x2309;
- t['circledotdisplay'] = 0x2299;
- t['circledottext'] = 0x2299;
- t['circlemultiplydisplay'] = 0x2297;
- t['circlemultiplytext'] = 0x2297;
- t['circleplusdisplay'] = 0x2295;
- t['circleplustext'] = 0x2295;
- t['contintegraldisplay'] = 0x222E;
- t['contintegraltext'] = 0x222E;
- t['coproductdisplay'] = 0x2210;
- t['coproducttext'] = 0x2210;
- t['floorleftBig'] = 0x230A;
- t['floorleftbig'] = 0x230A;
- t['floorleftbigg'] = 0x230A;
- t['floorleftBigg'] = 0x230A;
- t['floorrightbig'] = 0x230B;
- t['floorrightBig'] = 0x230B;
- t['floorrightBigg'] = 0x230B;
- t['floorrightbigg'] = 0x230B;
- t['hatwide'] = 0x0302;
- t['hatwider'] = 0x0302;
- t['hatwidest'] = 0x0302;
- t['intercal'] = 0x1D40;
- t['integraldisplay'] = 0x222B;
- t['integraltext'] = 0x222B;
- t['intersectiondisplay'] = 0x22C2;
- t['intersectiontext'] = 0x22C2;
- t['logicalanddisplay'] = 0x2227;
- t['logicalandtext'] = 0x2227;
- t['logicalordisplay'] = 0x2228;
- t['logicalortext'] = 0x2228;
- t['parenleftBig'] = 0x0028;
- t['parenleftbig'] = 0x0028;
- t['parenleftBigg'] = 0x0028;
- t['parenleftbigg'] = 0x0028;
- t['parenrightBig'] = 0x0029;
- t['parenrightbig'] = 0x0029;
- t['parenrightBigg'] = 0x0029;
- t['parenrightbigg'] = 0x0029;
- t['prime'] = 0x2032;
- t['productdisplay'] = 0x220F;
- t['producttext'] = 0x220F;
- t['radicalbig'] = 0x221A;
- t['radicalBig'] = 0x221A;
- t['radicalBigg'] = 0x221A;
- t['radicalbigg'] = 0x221A;
- t['radicalbt'] = 0x221A;
- t['radicaltp'] = 0x221A;
- t['radicalvertex'] = 0x221A;
- t['slashbig'] = 0x002F;
- t['slashBig'] = 0x002F;
- t['slashBigg'] = 0x002F;
- t['slashbigg'] = 0x002F;
- t['summationdisplay'] = 0x2211;
- t['summationtext'] = 0x2211;
- t['tildewide'] = 0x02DC;
- t['tildewider'] = 0x02DC;
- t['tildewidest'] = 0x02DC;
- t['uniondisplay'] = 0x22C3;
- t['unionmultidisplay'] = 0x228E;
- t['unionmultitext'] = 0x228E;
- t['unionsqdisplay'] = 0x2294;
- t['unionsqtext'] = 0x2294;
- t['uniontext'] = 0x22C3;
- t['vextenddouble'] = 0x2225;
- t['vextendsingle'] = 0x2223;
-});
-var getDingbatsGlyphsUnicode = getLookupTableFactory(function (t) {
- t['space'] = 0x0020;
- t['a1'] = 0x2701;
- t['a2'] = 0x2702;
- t['a202'] = 0x2703;
- t['a3'] = 0x2704;
- t['a4'] = 0x260E;
- t['a5'] = 0x2706;
- t['a119'] = 0x2707;
- t['a118'] = 0x2708;
- t['a117'] = 0x2709;
- t['a11'] = 0x261B;
- t['a12'] = 0x261E;
- t['a13'] = 0x270C;
- t['a14'] = 0x270D;
- t['a15'] = 0x270E;
- t['a16'] = 0x270F;
- t['a105'] = 0x2710;
- t['a17'] = 0x2711;
- t['a18'] = 0x2712;
- t['a19'] = 0x2713;
- t['a20'] = 0x2714;
- t['a21'] = 0x2715;
- t['a22'] = 0x2716;
- t['a23'] = 0x2717;
- t['a24'] = 0x2718;
- t['a25'] = 0x2719;
- t['a26'] = 0x271A;
- t['a27'] = 0x271B;
- t['a28'] = 0x271C;
- t['a6'] = 0x271D;
- t['a7'] = 0x271E;
- t['a8'] = 0x271F;
- t['a9'] = 0x2720;
- t['a10'] = 0x2721;
- t['a29'] = 0x2722;
- t['a30'] = 0x2723;
- t['a31'] = 0x2724;
- t['a32'] = 0x2725;
- t['a33'] = 0x2726;
- t['a34'] = 0x2727;
- t['a35'] = 0x2605;
- t['a36'] = 0x2729;
- t['a37'] = 0x272A;
- t['a38'] = 0x272B;
- t['a39'] = 0x272C;
- t['a40'] = 0x272D;
- t['a41'] = 0x272E;
- t['a42'] = 0x272F;
- t['a43'] = 0x2730;
- t['a44'] = 0x2731;
- t['a45'] = 0x2732;
- t['a46'] = 0x2733;
- t['a47'] = 0x2734;
- t['a48'] = 0x2735;
- t['a49'] = 0x2736;
- t['a50'] = 0x2737;
- t['a51'] = 0x2738;
- t['a52'] = 0x2739;
- t['a53'] = 0x273A;
- t['a54'] = 0x273B;
- t['a55'] = 0x273C;
- t['a56'] = 0x273D;
- t['a57'] = 0x273E;
- t['a58'] = 0x273F;
- t['a59'] = 0x2740;
- t['a60'] = 0x2741;
- t['a61'] = 0x2742;
- t['a62'] = 0x2743;
- t['a63'] = 0x2744;
- t['a64'] = 0x2745;
- t['a65'] = 0x2746;
- t['a66'] = 0x2747;
- t['a67'] = 0x2748;
- t['a68'] = 0x2749;
- t['a69'] = 0x274A;
- t['a70'] = 0x274B;
- t['a71'] = 0x25CF;
- t['a72'] = 0x274D;
- t['a73'] = 0x25A0;
- t['a74'] = 0x274F;
- t['a203'] = 0x2750;
- t['a75'] = 0x2751;
- t['a204'] = 0x2752;
- t['a76'] = 0x25B2;
- t['a77'] = 0x25BC;
- t['a78'] = 0x25C6;
- t['a79'] = 0x2756;
- t['a81'] = 0x25D7;
- t['a82'] = 0x2758;
- t['a83'] = 0x2759;
- t['a84'] = 0x275A;
- t['a97'] = 0x275B;
- t['a98'] = 0x275C;
- t['a99'] = 0x275D;
- t['a100'] = 0x275E;
- t['a101'] = 0x2761;
- t['a102'] = 0x2762;
- t['a103'] = 0x2763;
- t['a104'] = 0x2764;
- t['a106'] = 0x2765;
- t['a107'] = 0x2766;
- t['a108'] = 0x2767;
- t['a112'] = 0x2663;
- t['a111'] = 0x2666;
- t['a110'] = 0x2665;
- t['a109'] = 0x2660;
- t['a120'] = 0x2460;
- t['a121'] = 0x2461;
- t['a122'] = 0x2462;
- t['a123'] = 0x2463;
- t['a124'] = 0x2464;
- t['a125'] = 0x2465;
- t['a126'] = 0x2466;
- t['a127'] = 0x2467;
- t['a128'] = 0x2468;
- t['a129'] = 0x2469;
- t['a130'] = 0x2776;
- t['a131'] = 0x2777;
- t['a132'] = 0x2778;
- t['a133'] = 0x2779;
- t['a134'] = 0x277A;
- t['a135'] = 0x277B;
- t['a136'] = 0x277C;
- t['a137'] = 0x277D;
- t['a138'] = 0x277E;
- t['a139'] = 0x277F;
- t['a140'] = 0x2780;
- t['a141'] = 0x2781;
- t['a142'] = 0x2782;
- t['a143'] = 0x2783;
- t['a144'] = 0x2784;
- t['a145'] = 0x2785;
- t['a146'] = 0x2786;
- t['a147'] = 0x2787;
- t['a148'] = 0x2788;
- t['a149'] = 0x2789;
- t['a150'] = 0x278A;
- t['a151'] = 0x278B;
- t['a152'] = 0x278C;
- t['a153'] = 0x278D;
- t['a154'] = 0x278E;
- t['a155'] = 0x278F;
- t['a156'] = 0x2790;
- t['a157'] = 0x2791;
- t['a158'] = 0x2792;
- t['a159'] = 0x2793;
- t['a160'] = 0x2794;
- t['a161'] = 0x2192;
- t['a163'] = 0x2194;
- t['a164'] = 0x2195;
- t['a196'] = 0x2798;
- t['a165'] = 0x2799;
- t['a192'] = 0x279A;
- t['a166'] = 0x279B;
- t['a167'] = 0x279C;
- t['a168'] = 0x279D;
- t['a169'] = 0x279E;
- t['a170'] = 0x279F;
- t['a171'] = 0x27A0;
- t['a172'] = 0x27A1;
- t['a173'] = 0x27A2;
- t['a162'] = 0x27A3;
- t['a174'] = 0x27A4;
- t['a175'] = 0x27A5;
- t['a176'] = 0x27A6;
- t['a177'] = 0x27A7;
- t['a178'] = 0x27A8;
- t['a179'] = 0x27A9;
- t['a193'] = 0x27AA;
- t['a180'] = 0x27AB;
- t['a199'] = 0x27AC;
- t['a181'] = 0x27AD;
- t['a200'] = 0x27AE;
- t['a182'] = 0x27AF;
- t['a201'] = 0x27B1;
- t['a183'] = 0x27B2;
- t['a184'] = 0x27B3;
- t['a197'] = 0x27B4;
- t['a185'] = 0x27B5;
- t['a194'] = 0x27B6;
- t['a198'] = 0x27B7;
- t['a186'] = 0x27B8;
- t['a195'] = 0x27B9;
- t['a187'] = 0x27BA;
- t['a188'] = 0x27BB;
- t['a189'] = 0x27BC;
- t['a190'] = 0x27BD;
- t['a191'] = 0x27BE;
- t['a89'] = 0x2768;
- t['a90'] = 0x2769;
- t['a93'] = 0x276A;
- t['a94'] = 0x276B;
- t['a91'] = 0x276C;
- t['a92'] = 0x276D;
- t['a205'] = 0x276E;
- t['a85'] = 0x276F;
- t['a206'] = 0x2770;
- t['a86'] = 0x2771;
- t['a87'] = 0x2772;
- t['a88'] = 0x2773;
- t['a95'] = 0x2774;
- t['a96'] = 0x2775;
- t['.notdef'] = 0x0000;
-});
-exports.getGlyphsUnicode = getGlyphsUnicode;
-exports.getDingbatsGlyphsUnicode = getDingbatsGlyphsUnicode;
-
-/***/ }),
-/* 161 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.getSupplementalGlyphMapForCalibri = exports.getSupplementalGlyphMapForArialBlack = exports.getGlyphMapForStandardFonts = exports.getSymbolsFonts = exports.getSerifFonts = exports.getNonStdFontMap = exports.getStdFontMap = undefined;
-
-var _util = __w_pdfjs_require__(2);
-
-var getStdFontMap = (0, _util.getLookupTableFactory)(function (t) {
- t['ArialNarrow'] = 'Helvetica';
- t['ArialNarrow-Bold'] = 'Helvetica-Bold';
- t['ArialNarrow-BoldItalic'] = 'Helvetica-BoldOblique';
- t['ArialNarrow-Italic'] = 'Helvetica-Oblique';
- t['ArialBlack'] = 'Helvetica';
- t['ArialBlack-Bold'] = 'Helvetica-Bold';
- t['ArialBlack-BoldItalic'] = 'Helvetica-BoldOblique';
- t['ArialBlack-Italic'] = 'Helvetica-Oblique';
- t['Arial-Black'] = 'Helvetica';
- t['Arial-Black-Bold'] = 'Helvetica-Bold';
- t['Arial-Black-BoldItalic'] = 'Helvetica-BoldOblique';
- t['Arial-Black-Italic'] = 'Helvetica-Oblique';
- t['Arial'] = 'Helvetica';
- t['Arial-Bold'] = 'Helvetica-Bold';
- t['Arial-BoldItalic'] = 'Helvetica-BoldOblique';
- t['Arial-Italic'] = 'Helvetica-Oblique';
- t['Arial-BoldItalicMT'] = 'Helvetica-BoldOblique';
- t['Arial-BoldMT'] = 'Helvetica-Bold';
- t['Arial-ItalicMT'] = 'Helvetica-Oblique';
- t['ArialMT'] = 'Helvetica';
- t['Courier-Bold'] = 'Courier-Bold';
- t['Courier-BoldItalic'] = 'Courier-BoldOblique';
- t['Courier-Italic'] = 'Courier-Oblique';
- t['CourierNew'] = 'Courier';
- t['CourierNew-Bold'] = 'Courier-Bold';
- t['CourierNew-BoldItalic'] = 'Courier-BoldOblique';
- t['CourierNew-Italic'] = 'Courier-Oblique';
- t['CourierNewPS-BoldItalicMT'] = 'Courier-BoldOblique';
- t['CourierNewPS-BoldMT'] = 'Courier-Bold';
- t['CourierNewPS-ItalicMT'] = 'Courier-Oblique';
- t['CourierNewPSMT'] = 'Courier';
- t['Helvetica'] = 'Helvetica';
- t['Helvetica-Bold'] = 'Helvetica-Bold';
- t['Helvetica-BoldItalic'] = 'Helvetica-BoldOblique';
- t['Helvetica-BoldOblique'] = 'Helvetica-BoldOblique';
- t['Helvetica-Italic'] = 'Helvetica-Oblique';
- t['Helvetica-Oblique'] = 'Helvetica-Oblique';
- t['SegoeUISymbol'] = 'Helvetica';
- t['Symbol-Bold'] = 'Symbol';
- t['Symbol-BoldItalic'] = 'Symbol';
- t['Symbol-Italic'] = 'Symbol';
- t['TimesNewRoman'] = 'Times-Roman';
- t['TimesNewRoman-Bold'] = 'Times-Bold';
- t['TimesNewRoman-BoldItalic'] = 'Times-BoldItalic';
- t['TimesNewRoman-Italic'] = 'Times-Italic';
- t['TimesNewRomanPS'] = 'Times-Roman';
- t['TimesNewRomanPS-Bold'] = 'Times-Bold';
- t['TimesNewRomanPS-BoldItalic'] = 'Times-BoldItalic';
- t['TimesNewRomanPS-BoldItalicMT'] = 'Times-BoldItalic';
- t['TimesNewRomanPS-BoldMT'] = 'Times-Bold';
- t['TimesNewRomanPS-Italic'] = 'Times-Italic';
- t['TimesNewRomanPS-ItalicMT'] = 'Times-Italic';
- t['TimesNewRomanPSMT'] = 'Times-Roman';
- t['TimesNewRomanPSMT-Bold'] = 'Times-Bold';
- t['TimesNewRomanPSMT-BoldItalic'] = 'Times-BoldItalic';
- t['TimesNewRomanPSMT-Italic'] = 'Times-Italic';
-});
-var getNonStdFontMap = (0, _util.getLookupTableFactory)(function (t) {
- t['Calibri'] = 'Helvetica';
- t['Calibri-Bold'] = 'Helvetica-Bold';
- t['Calibri-BoldItalic'] = 'Helvetica-BoldOblique';
- t['Calibri-Italic'] = 'Helvetica-Oblique';
- t['CenturyGothic'] = 'Helvetica';
- t['CenturyGothic-Bold'] = 'Helvetica-Bold';
- t['CenturyGothic-BoldItalic'] = 'Helvetica-BoldOblique';
- t['CenturyGothic-Italic'] = 'Helvetica-Oblique';
- t['ComicSansMS'] = 'Comic Sans MS';
- t['ComicSansMS-Bold'] = 'Comic Sans MS-Bold';
- t['ComicSansMS-BoldItalic'] = 'Comic Sans MS-BoldItalic';
- t['ComicSansMS-Italic'] = 'Comic Sans MS-Italic';
- t['LucidaConsole'] = 'Courier';
- t['LucidaConsole-Bold'] = 'Courier-Bold';
- t['LucidaConsole-BoldItalic'] = 'Courier-BoldOblique';
- t['LucidaConsole-Italic'] = 'Courier-Oblique';
- t['LucidaSans-Demi'] = 'Helvetica-Bold';
- t['MS-Gothic'] = 'MS Gothic';
- t['MS-Gothic-Bold'] = 'MS Gothic-Bold';
- t['MS-Gothic-BoldItalic'] = 'MS Gothic-BoldItalic';
- t['MS-Gothic-Italic'] = 'MS Gothic-Italic';
- t['MS-Mincho'] = 'MS Mincho';
- t['MS-Mincho-Bold'] = 'MS Mincho-Bold';
- t['MS-Mincho-BoldItalic'] = 'MS Mincho-BoldItalic';
- t['MS-Mincho-Italic'] = 'MS Mincho-Italic';
- t['MS-PGothic'] = 'MS PGothic';
- t['MS-PGothic-Bold'] = 'MS PGothic-Bold';
- t['MS-PGothic-BoldItalic'] = 'MS PGothic-BoldItalic';
- t['MS-PGothic-Italic'] = 'MS PGothic-Italic';
- t['MS-PMincho'] = 'MS PMincho';
- t['MS-PMincho-Bold'] = 'MS PMincho-Bold';
- t['MS-PMincho-BoldItalic'] = 'MS PMincho-BoldItalic';
- t['MS-PMincho-Italic'] = 'MS PMincho-Italic';
- t['NuptialScript'] = 'Times-Italic';
- t['Wingdings'] = 'ZapfDingbats';
-});
-var getSerifFonts = (0, _util.getLookupTableFactory)(function (t) {
- t['Adobe Jenson'] = true;
- t['Adobe Text'] = true;
- t['Albertus'] = true;
- t['Aldus'] = true;
- t['Alexandria'] = true;
- t['Algerian'] = true;
- t['American Typewriter'] = true;
- t['Antiqua'] = true;
- t['Apex'] = true;
- t['Arno'] = true;
- t['Aster'] = true;
- t['Aurora'] = true;
- t['Baskerville'] = true;
- t['Bell'] = true;
- t['Bembo'] = true;
- t['Bembo Schoolbook'] = true;
- t['Benguiat'] = true;
- t['Berkeley Old Style'] = true;
- t['Bernhard Modern'] = true;
- t['Berthold City'] = true;
- t['Bodoni'] = true;
- t['Bauer Bodoni'] = true;
- t['Book Antiqua'] = true;
- t['Bookman'] = true;
- t['Bordeaux Roman'] = true;
- t['Californian FB'] = true;
- t['Calisto'] = true;
- t['Calvert'] = true;
- t['Capitals'] = true;
- t['Cambria'] = true;
- t['Cartier'] = true;
- t['Caslon'] = true;
- t['Catull'] = true;
- t['Centaur'] = true;
- t['Century Old Style'] = true;
- t['Century Schoolbook'] = true;
- t['Chaparral'] = true;
- t['Charis SIL'] = true;
- t['Cheltenham'] = true;
- t['Cholla Slab'] = true;
- t['Clarendon'] = true;
- t['Clearface'] = true;
- t['Cochin'] = true;
- t['Colonna'] = true;
- t['Computer Modern'] = true;
- t['Concrete Roman'] = true;
- t['Constantia'] = true;
- t['Cooper Black'] = true;
- t['Corona'] = true;
- t['Ecotype'] = true;
- t['Egyptienne'] = true;
- t['Elephant'] = true;
- t['Excelsior'] = true;
- t['Fairfield'] = true;
- t['FF Scala'] = true;
- t['Folkard'] = true;
- t['Footlight'] = true;
- t['FreeSerif'] = true;
- t['Friz Quadrata'] = true;
- t['Garamond'] = true;
- t['Gentium'] = true;
- t['Georgia'] = true;
- t['Gloucester'] = true;
- t['Goudy Old Style'] = true;
- t['Goudy Schoolbook'] = true;
- t['Goudy Pro Font'] = true;
- t['Granjon'] = true;
- t['Guardian Egyptian'] = true;
- t['Heather'] = true;
- t['Hercules'] = true;
- t['High Tower Text'] = true;
- t['Hiroshige'] = true;
- t['Hoefler Text'] = true;
- t['Humana Serif'] = true;
- t['Imprint'] = true;
- t['Ionic No. 5'] = true;
- t['Janson'] = true;
- t['Joanna'] = true;
- t['Korinna'] = true;
- t['Lexicon'] = true;
- t['Liberation Serif'] = true;
- t['Linux Libertine'] = true;
- t['Literaturnaya'] = true;
- t['Lucida'] = true;
- t['Lucida Bright'] = true;
- t['Melior'] = true;
- t['Memphis'] = true;
- t['Miller'] = true;
- t['Minion'] = true;
- t['Modern'] = true;
- t['Mona Lisa'] = true;
- t['Mrs Eaves'] = true;
- t['MS Serif'] = true;
- t['Museo Slab'] = true;
- t['New York'] = true;
- t['Nimbus Roman'] = true;
- t['NPS Rawlinson Roadway'] = true;
- t['NuptialScript'] = true;
- t['Palatino'] = true;
- t['Perpetua'] = true;
- t['Plantin'] = true;
- t['Plantin Schoolbook'] = true;
- t['Playbill'] = true;
- t['Poor Richard'] = true;
- t['Rawlinson Roadway'] = true;
- t['Renault'] = true;
- t['Requiem'] = true;
- t['Rockwell'] = true;
- t['Roman'] = true;
- t['Rotis Serif'] = true;
- t['Sabon'] = true;
- t['Scala'] = true;
- t['Seagull'] = true;
- t['Sistina'] = true;
- t['Souvenir'] = true;
- t['STIX'] = true;
- t['Stone Informal'] = true;
- t['Stone Serif'] = true;
- t['Sylfaen'] = true;
- t['Times'] = true;
- t['Trajan'] = true;
- t['Trinité'] = true;
- t['Trump Mediaeval'] = true;
- t['Utopia'] = true;
- t['Vale Type'] = true;
- t['Bitstream Vera'] = true;
- t['Vera Serif'] = true;
- t['Versailles'] = true;
- t['Wanted'] = true;
- t['Weiss'] = true;
- t['Wide Latin'] = true;
- t['Windsor'] = true;
- t['XITS'] = true;
-});
-var getSymbolsFonts = (0, _util.getLookupTableFactory)(function (t) {
- t['Dingbats'] = true;
- t['Symbol'] = true;
- t['ZapfDingbats'] = true;
-});
-var getGlyphMapForStandardFonts = (0, _util.getLookupTableFactory)(function (t) {
- t[2] = 10;
- t[3] = 32;
- t[4] = 33;
- t[5] = 34;
- t[6] = 35;
- t[7] = 36;
- t[8] = 37;
- t[9] = 38;
- t[10] = 39;
- t[11] = 40;
- t[12] = 41;
- t[13] = 42;
- t[14] = 43;
- t[15] = 44;
- t[16] = 45;
- t[17] = 46;
- t[18] = 47;
- t[19] = 48;
- t[20] = 49;
- t[21] = 50;
- t[22] = 51;
- t[23] = 52;
- t[24] = 53;
- t[25] = 54;
- t[26] = 55;
- t[27] = 56;
- t[28] = 57;
- t[29] = 58;
- t[30] = 894;
- t[31] = 60;
- t[32] = 61;
- t[33] = 62;
- t[34] = 63;
- t[35] = 64;
- t[36] = 65;
- t[37] = 66;
- t[38] = 67;
- t[39] = 68;
- t[40] = 69;
- t[41] = 70;
- t[42] = 71;
- t[43] = 72;
- t[44] = 73;
- t[45] = 74;
- t[46] = 75;
- t[47] = 76;
- t[48] = 77;
- t[49] = 78;
- t[50] = 79;
- t[51] = 80;
- t[52] = 81;
- t[53] = 82;
- t[54] = 83;
- t[55] = 84;
- t[56] = 85;
- t[57] = 86;
- t[58] = 87;
- t[59] = 88;
- t[60] = 89;
- t[61] = 90;
- t[62] = 91;
- t[63] = 92;
- t[64] = 93;
- t[65] = 94;
- t[66] = 95;
- t[67] = 96;
- t[68] = 97;
- t[69] = 98;
- t[70] = 99;
- t[71] = 100;
- t[72] = 101;
- t[73] = 102;
- t[74] = 103;
- t[75] = 104;
- t[76] = 105;
- t[77] = 106;
- t[78] = 107;
- t[79] = 108;
- t[80] = 109;
- t[81] = 110;
- t[82] = 111;
- t[83] = 112;
- t[84] = 113;
- t[85] = 114;
- t[86] = 115;
- t[87] = 116;
- t[88] = 117;
- t[89] = 118;
- t[90] = 119;
- t[91] = 120;
- t[92] = 121;
- t[93] = 122;
- t[94] = 123;
- t[95] = 124;
- t[96] = 125;
- t[97] = 126;
- t[98] = 196;
- t[99] = 197;
- t[100] = 199;
- t[101] = 201;
- t[102] = 209;
- t[103] = 214;
- t[104] = 220;
- t[105] = 225;
- t[106] = 224;
- t[107] = 226;
- t[108] = 228;
- t[109] = 227;
- t[110] = 229;
- t[111] = 231;
- t[112] = 233;
- t[113] = 232;
- t[114] = 234;
- t[115] = 235;
- t[116] = 237;
- t[117] = 236;
- t[118] = 238;
- t[119] = 239;
- t[120] = 241;
- t[121] = 243;
- t[122] = 242;
- t[123] = 244;
- t[124] = 246;
- t[125] = 245;
- t[126] = 250;
- t[127] = 249;
- t[128] = 251;
- t[129] = 252;
- t[130] = 8224;
- t[131] = 176;
- t[132] = 162;
- t[133] = 163;
- t[134] = 167;
- t[135] = 8226;
- t[136] = 182;
- t[137] = 223;
- t[138] = 174;
- t[139] = 169;
- t[140] = 8482;
- t[141] = 180;
- t[142] = 168;
- t[143] = 8800;
- t[144] = 198;
- t[145] = 216;
- t[146] = 8734;
- t[147] = 177;
- t[148] = 8804;
- t[149] = 8805;
- t[150] = 165;
- t[151] = 181;
- t[152] = 8706;
- t[153] = 8721;
- t[154] = 8719;
- t[156] = 8747;
- t[157] = 170;
- t[158] = 186;
- t[159] = 8486;
- t[160] = 230;
- t[161] = 248;
- t[162] = 191;
- t[163] = 161;
- t[164] = 172;
- t[165] = 8730;
- t[166] = 402;
- t[167] = 8776;
- t[168] = 8710;
- t[169] = 171;
- t[170] = 187;
- t[171] = 8230;
- t[210] = 218;
- t[223] = 711;
- t[224] = 321;
- t[225] = 322;
- t[227] = 353;
- t[229] = 382;
- t[234] = 253;
- t[252] = 263;
- t[253] = 268;
- t[254] = 269;
- t[258] = 258;
- t[260] = 260;
- t[261] = 261;
- t[265] = 280;
- t[266] = 281;
- t[268] = 283;
- t[269] = 313;
- t[275] = 323;
- t[276] = 324;
- t[278] = 328;
- t[284] = 345;
- t[285] = 346;
- t[286] = 347;
- t[292] = 367;
- t[295] = 377;
- t[296] = 378;
- t[298] = 380;
- t[305] = 963;
- t[306] = 964;
- t[307] = 966;
- t[308] = 8215;
- t[309] = 8252;
- t[310] = 8319;
- t[311] = 8359;
- t[312] = 8592;
- t[313] = 8593;
- t[337] = 9552;
- t[493] = 1039;
- t[494] = 1040;
- t[705] = 1524;
- t[706] = 8362;
- t[710] = 64288;
- t[711] = 64298;
- t[759] = 1617;
- t[761] = 1776;
- t[763] = 1778;
- t[775] = 1652;
- t[777] = 1764;
- t[778] = 1780;
- t[779] = 1781;
- t[780] = 1782;
- t[782] = 771;
- t[783] = 64726;
- t[786] = 8363;
- t[788] = 8532;
- t[790] = 768;
- t[791] = 769;
- t[792] = 768;
- t[795] = 803;
- t[797] = 64336;
- t[798] = 64337;
- t[799] = 64342;
- t[800] = 64343;
- t[801] = 64344;
- t[802] = 64345;
- t[803] = 64362;
- t[804] = 64363;
- t[805] = 64364;
- t[2424] = 7821;
- t[2425] = 7822;
- t[2426] = 7823;
- t[2427] = 7824;
- t[2428] = 7825;
- t[2429] = 7826;
- t[2430] = 7827;
- t[2433] = 7682;
- t[2678] = 8045;
- t[2679] = 8046;
- t[2830] = 1552;
- t[2838] = 686;
- t[2840] = 751;
- t[2842] = 753;
- t[2843] = 754;
- t[2844] = 755;
- t[2846] = 757;
- t[2856] = 767;
- t[2857] = 848;
- t[2858] = 849;
- t[2862] = 853;
- t[2863] = 854;
- t[2864] = 855;
- t[2865] = 861;
- t[2866] = 862;
- t[2906] = 7460;
- t[2908] = 7462;
- t[2909] = 7463;
- t[2910] = 7464;
- t[2912] = 7466;
- t[2913] = 7467;
- t[2914] = 7468;
- t[2916] = 7470;
- t[2917] = 7471;
- t[2918] = 7472;
- t[2920] = 7474;
- t[2921] = 7475;
- t[2922] = 7476;
- t[2924] = 7478;
- t[2925] = 7479;
- t[2926] = 7480;
- t[2928] = 7482;
- t[2929] = 7483;
- t[2930] = 7484;
- t[2932] = 7486;
- t[2933] = 7487;
- t[2934] = 7488;
- t[2936] = 7490;
- t[2937] = 7491;
- t[2938] = 7492;
- t[2940] = 7494;
- t[2941] = 7495;
- t[2942] = 7496;
- t[2944] = 7498;
- t[2946] = 7500;
- t[2948] = 7502;
- t[2950] = 7504;
- t[2951] = 7505;
- t[2952] = 7506;
- t[2954] = 7508;
- t[2955] = 7509;
- t[2956] = 7510;
- t[2958] = 7512;
- t[2959] = 7513;
- t[2960] = 7514;
- t[2962] = 7516;
- t[2963] = 7517;
- t[2964] = 7518;
- t[2966] = 7520;
- t[2967] = 7521;
- t[2968] = 7522;
- t[2970] = 7524;
- t[2971] = 7525;
- t[2972] = 7526;
- t[2974] = 7528;
- t[2975] = 7529;
- t[2976] = 7530;
- t[2978] = 1537;
- t[2979] = 1538;
- t[2980] = 1539;
- t[2982] = 1549;
- t[2983] = 1551;
- t[2984] = 1552;
- t[2986] = 1554;
- t[2987] = 1555;
- t[2988] = 1556;
- t[2990] = 1623;
- t[2991] = 1624;
- t[2995] = 1775;
- t[2999] = 1791;
- t[3002] = 64290;
- t[3003] = 64291;
- t[3004] = 64292;
- t[3006] = 64294;
- t[3007] = 64295;
- t[3008] = 64296;
- t[3011] = 1900;
- t[3014] = 8223;
- t[3015] = 8244;
- t[3017] = 7532;
- t[3018] = 7533;
- t[3019] = 7534;
- t[3075] = 7590;
- t[3076] = 7591;
- t[3079] = 7594;
- t[3080] = 7595;
- t[3083] = 7598;
- t[3084] = 7599;
- t[3087] = 7602;
- t[3088] = 7603;
- t[3091] = 7606;
- t[3092] = 7607;
- t[3095] = 7610;
- t[3096] = 7611;
- t[3099] = 7614;
- t[3100] = 7615;
- t[3103] = 7618;
- t[3104] = 7619;
- t[3107] = 8337;
- t[3108] = 8338;
- t[3116] = 1884;
- t[3119] = 1885;
- t[3120] = 1885;
- t[3123] = 1886;
- t[3124] = 1886;
- t[3127] = 1887;
- t[3128] = 1887;
- t[3131] = 1888;
- t[3132] = 1888;
- t[3135] = 1889;
- t[3136] = 1889;
- t[3139] = 1890;
- t[3140] = 1890;
- t[3143] = 1891;
- t[3144] = 1891;
- t[3147] = 1892;
- t[3148] = 1892;
- t[3153] = 580;
- t[3154] = 581;
- t[3157] = 584;
- t[3158] = 585;
- t[3161] = 588;
- t[3162] = 589;
- t[3165] = 891;
- t[3166] = 892;
- t[3169] = 1274;
- t[3170] = 1275;
- t[3173] = 1278;
- t[3174] = 1279;
- t[3181] = 7622;
- t[3182] = 7623;
- t[3282] = 11799;
- t[3316] = 578;
- t[3379] = 42785;
- t[3393] = 1159;
- t[3416] = 8377;
-});
-var getSupplementalGlyphMapForArialBlack = (0, _util.getLookupTableFactory)(function (t) {
- t[227] = 322;
- t[264] = 261;
- t[291] = 346;
-});
-var getSupplementalGlyphMapForCalibri = (0, _util.getLookupTableFactory)(function (t) {
- t[1] = 32;
- t[4] = 65;
- t[17] = 66;
- t[18] = 67;
- t[24] = 68;
- t[28] = 69;
- t[38] = 70;
- t[39] = 71;
- t[44] = 72;
- t[47] = 73;
- t[58] = 74;
- t[60] = 75;
- t[62] = 76;
- t[68] = 77;
- t[69] = 78;
- t[75] = 79;
- t[87] = 80;
- t[89] = 81;
- t[90] = 82;
- t[94] = 83;
- t[100] = 84;
- t[104] = 85;
- t[115] = 86;
- t[116] = 87;
- t[121] = 88;
- t[122] = 89;
- t[127] = 90;
- t[258] = 97;
- t[268] = 261;
- t[271] = 98;
- t[272] = 99;
- t[273] = 263;
- t[282] = 100;
- t[286] = 101;
- t[295] = 281;
- t[296] = 102;
- t[336] = 103;
- t[346] = 104;
- t[349] = 105;
- t[361] = 106;
- t[364] = 107;
- t[367] = 108;
- t[371] = 322;
- t[373] = 109;
- t[374] = 110;
- t[381] = 111;
- t[383] = 243;
- t[393] = 112;
- t[395] = 113;
- t[396] = 114;
- t[400] = 115;
- t[401] = 347;
- t[410] = 116;
- t[437] = 117;
- t[448] = 118;
- t[449] = 119;
- t[454] = 120;
- t[455] = 121;
- t[460] = 122;
- t[463] = 380;
- t[853] = 44;
- t[855] = 58;
- t[856] = 46;
- t[876] = 47;
- t[878] = 45;
- t[882] = 45;
- t[894] = 40;
- t[895] = 41;
- t[896] = 91;
- t[897] = 93;
- t[923] = 64;
- t[1004] = 48;
- t[1005] = 49;
- t[1006] = 50;
- t[1007] = 51;
- t[1008] = 52;
- t[1009] = 53;
- t[1010] = 54;
- t[1011] = 55;
- t[1012] = 56;
- t[1013] = 57;
- t[1081] = 37;
- t[1085] = 43;
- t[1086] = 45;
-});
-exports.getStdFontMap = getStdFontMap;
-exports.getNonStdFontMap = getNonStdFontMap;
-exports.getSerifFonts = getSerifFonts;
-exports.getSymbolsFonts = getSymbolsFonts;
-exports.getGlyphMapForStandardFonts = getGlyphMapForStandardFonts;
-exports.getSupplementalGlyphMapForArialBlack = getSupplementalGlyphMapForArialBlack;
-exports.getSupplementalGlyphMapForCalibri = getSupplementalGlyphMapForCalibri;
-
-/***/ }),
-/* 162 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-var getLookupTableFactory = __w_pdfjs_require__(2).getLookupTableFactory;
-var getSpecialPUASymbols = getLookupTableFactory(function (t) {
- t[63721] = 0x00A9;
- t[63193] = 0x00A9;
- t[63720] = 0x00AE;
- t[63194] = 0x00AE;
- t[63722] = 0x2122;
- t[63195] = 0x2122;
- t[63729] = 0x23A7;
- t[63730] = 0x23A8;
- t[63731] = 0x23A9;
- t[63740] = 0x23AB;
- t[63741] = 0x23AC;
- t[63742] = 0x23AD;
- t[63726] = 0x23A1;
- t[63727] = 0x23A2;
- t[63728] = 0x23A3;
- t[63737] = 0x23A4;
- t[63738] = 0x23A5;
- t[63739] = 0x23A6;
- t[63723] = 0x239B;
- t[63724] = 0x239C;
- t[63725] = 0x239D;
- t[63734] = 0x239E;
- t[63735] = 0x239F;
- t[63736] = 0x23A0;
-});
-function mapSpecialUnicodeValues(code) {
- if (code >= 0xFFF0 && code <= 0xFFFF) {
- return 0;
- } else if (code >= 0xF600 && code <= 0xF8FF) {
- return getSpecialPUASymbols()[code] || code;
- } else if (code === 0x00AD) {
- return 0x002D;
- }
- return code;
-}
-function getUnicodeForGlyph(name, glyphsUnicodeMap) {
- var unicode = glyphsUnicodeMap[name];
- if (unicode !== undefined) {
- return unicode;
- }
- if (!name) {
- return -1;
- }
- if (name[0] === 'u') {
- var nameLen = name.length, hexStr;
- if (nameLen === 7 && name[1] === 'n' && name[2] === 'i') {
- hexStr = name.substring(3);
- } else if (nameLen >= 5 && nameLen <= 7) {
- hexStr = name.substring(1);
- } else {
- return -1;
- }
- if (hexStr === hexStr.toUpperCase()) {
- unicode = parseInt(hexStr, 16);
- if (unicode >= 0) {
- return unicode;
- }
- }
- }
- return -1;
-}
-var UnicodeRanges = [
- {
- 'begin': 0x0000,
- 'end': 0x007F
- },
- {
- 'begin': 0x0080,
- 'end': 0x00FF
- },
- {
- 'begin': 0x0100,
- 'end': 0x017F
- },
- {
- 'begin': 0x0180,
- 'end': 0x024F
- },
- {
- 'begin': 0x0250,
- 'end': 0x02AF
- },
- {
- 'begin': 0x02B0,
- 'end': 0x02FF
- },
- {
- 'begin': 0x0300,
- 'end': 0x036F
- },
- {
- 'begin': 0x0370,
- 'end': 0x03FF
- },
- {
- 'begin': 0x2C80,
- 'end': 0x2CFF
- },
- {
- 'begin': 0x0400,
- 'end': 0x04FF
- },
- {
- 'begin': 0x0530,
- 'end': 0x058F
- },
- {
- 'begin': 0x0590,
- 'end': 0x05FF
- },
- {
- 'begin': 0xA500,
- 'end': 0xA63F
- },
- {
- 'begin': 0x0600,
- 'end': 0x06FF
- },
- {
- 'begin': 0x07C0,
- 'end': 0x07FF
- },
- {
- 'begin': 0x0900,
- 'end': 0x097F
- },
- {
- 'begin': 0x0980,
- 'end': 0x09FF
- },
- {
- 'begin': 0x0A00,
- 'end': 0x0A7F
- },
- {
- 'begin': 0x0A80,
- 'end': 0x0AFF
- },
- {
- 'begin': 0x0B00,
- 'end': 0x0B7F
- },
- {
- 'begin': 0x0B80,
- 'end': 0x0BFF
- },
- {
- 'begin': 0x0C00,
- 'end': 0x0C7F
- },
- {
- 'begin': 0x0C80,
- 'end': 0x0CFF
- },
- {
- 'begin': 0x0D00,
- 'end': 0x0D7F
- },
- {
- 'begin': 0x0E00,
- 'end': 0x0E7F
- },
- {
- 'begin': 0x0E80,
- 'end': 0x0EFF
- },
- {
- 'begin': 0x10A0,
- 'end': 0x10FF
- },
- {
- 'begin': 0x1B00,
- 'end': 0x1B7F
- },
- {
- 'begin': 0x1100,
- 'end': 0x11FF
- },
- {
- 'begin': 0x1E00,
- 'end': 0x1EFF
- },
- {
- 'begin': 0x1F00,
- 'end': 0x1FFF
- },
- {
- 'begin': 0x2000,
- 'end': 0x206F
- },
- {
- 'begin': 0x2070,
- 'end': 0x209F
- },
- {
- 'begin': 0x20A0,
- 'end': 0x20CF
- },
- {
- 'begin': 0x20D0,
- 'end': 0x20FF
- },
- {
- 'begin': 0x2100,
- 'end': 0x214F
- },
- {
- 'begin': 0x2150,
- 'end': 0x218F
- },
- {
- 'begin': 0x2190,
- 'end': 0x21FF
- },
- {
- 'begin': 0x2200,
- 'end': 0x22FF
- },
- {
- 'begin': 0x2300,
- 'end': 0x23FF
- },
- {
- 'begin': 0x2400,
- 'end': 0x243F
- },
- {
- 'begin': 0x2440,
- 'end': 0x245F
- },
- {
- 'begin': 0x2460,
- 'end': 0x24FF
- },
- {
- 'begin': 0x2500,
- 'end': 0x257F
- },
- {
- 'begin': 0x2580,
- 'end': 0x259F
- },
- {
- 'begin': 0x25A0,
- 'end': 0x25FF
- },
- {
- 'begin': 0x2600,
- 'end': 0x26FF
- },
- {
- 'begin': 0x2700,
- 'end': 0x27BF
- },
- {
- 'begin': 0x3000,
- 'end': 0x303F
- },
- {
- 'begin': 0x3040,
- 'end': 0x309F
- },
- {
- 'begin': 0x30A0,
- 'end': 0x30FF
- },
- {
- 'begin': 0x3100,
- 'end': 0x312F
- },
- {
- 'begin': 0x3130,
- 'end': 0x318F
- },
- {
- 'begin': 0xA840,
- 'end': 0xA87F
- },
- {
- 'begin': 0x3200,
- 'end': 0x32FF
- },
- {
- 'begin': 0x3300,
- 'end': 0x33FF
- },
- {
- 'begin': 0xAC00,
- 'end': 0xD7AF
- },
- {
- 'begin': 0xD800,
- 'end': 0xDFFF
- },
- {
- 'begin': 0x10900,
- 'end': 0x1091F
- },
- {
- 'begin': 0x4E00,
- 'end': 0x9FFF
- },
- {
- 'begin': 0xE000,
- 'end': 0xF8FF
- },
- {
- 'begin': 0x31C0,
- 'end': 0x31EF
- },
- {
- 'begin': 0xFB00,
- 'end': 0xFB4F
- },
- {
- 'begin': 0xFB50,
- 'end': 0xFDFF
- },
- {
- 'begin': 0xFE20,
- 'end': 0xFE2F
- },
- {
- 'begin': 0xFE10,
- 'end': 0xFE1F
- },
- {
- 'begin': 0xFE50,
- 'end': 0xFE6F
- },
- {
- 'begin': 0xFE70,
- 'end': 0xFEFF
- },
- {
- 'begin': 0xFF00,
- 'end': 0xFFEF
- },
- {
- 'begin': 0xFFF0,
- 'end': 0xFFFF
- },
- {
- 'begin': 0x0F00,
- 'end': 0x0FFF
- },
- {
- 'begin': 0x0700,
- 'end': 0x074F
- },
- {
- 'begin': 0x0780,
- 'end': 0x07BF
- },
- {
- 'begin': 0x0D80,
- 'end': 0x0DFF
- },
- {
- 'begin': 0x1000,
- 'end': 0x109F
- },
- {
- 'begin': 0x1200,
- 'end': 0x137F
- },
- {
- 'begin': 0x13A0,
- 'end': 0x13FF
- },
- {
- 'begin': 0x1400,
- 'end': 0x167F
- },
- {
- 'begin': 0x1680,
- 'end': 0x169F
- },
- {
- 'begin': 0x16A0,
- 'end': 0x16FF
- },
- {
- 'begin': 0x1780,
- 'end': 0x17FF
- },
- {
- 'begin': 0x1800,
- 'end': 0x18AF
- },
- {
- 'begin': 0x2800,
- 'end': 0x28FF
- },
- {
- 'begin': 0xA000,
- 'end': 0xA48F
- },
- {
- 'begin': 0x1700,
- 'end': 0x171F
- },
- {
- 'begin': 0x10300,
- 'end': 0x1032F
- },
- {
- 'begin': 0x10330,
- 'end': 0x1034F
- },
- {
- 'begin': 0x10400,
- 'end': 0x1044F
- },
- {
- 'begin': 0x1D000,
- 'end': 0x1D0FF
- },
- {
- 'begin': 0x1D400,
- 'end': 0x1D7FF
- },
- {
- 'begin': 0xFF000,
- 'end': 0xFFFFD
- },
- {
- 'begin': 0xFE00,
- 'end': 0xFE0F
- },
- {
- 'begin': 0xE0000,
- 'end': 0xE007F
- },
- {
- 'begin': 0x1900,
- 'end': 0x194F
- },
- {
- 'begin': 0x1950,
- 'end': 0x197F
- },
- {
- 'begin': 0x1980,
- 'end': 0x19DF
- },
- {
- 'begin': 0x1A00,
- 'end': 0x1A1F
- },
- {
- 'begin': 0x2C00,
- 'end': 0x2C5F
- },
- {
- 'begin': 0x2D30,
- 'end': 0x2D7F
- },
- {
- 'begin': 0x4DC0,
- 'end': 0x4DFF
- },
- {
- 'begin': 0xA800,
- 'end': 0xA82F
- },
- {
- 'begin': 0x10000,
- 'end': 0x1007F
- },
- {
- 'begin': 0x10140,
- 'end': 0x1018F
- },
- {
- 'begin': 0x10380,
- 'end': 0x1039F
- },
- {
- 'begin': 0x103A0,
- 'end': 0x103DF
- },
- {
- 'begin': 0x10450,
- 'end': 0x1047F
- },
- {
- 'begin': 0x10480,
- 'end': 0x104AF
- },
- {
- 'begin': 0x10800,
- 'end': 0x1083F
- },
- {
- 'begin': 0x10A00,
- 'end': 0x10A5F
- },
- {
- 'begin': 0x1D300,
- 'end': 0x1D35F
- },
- {
- 'begin': 0x12000,
- 'end': 0x123FF
- },
- {
- 'begin': 0x1D360,
- 'end': 0x1D37F
- },
- {
- 'begin': 0x1B80,
- 'end': 0x1BBF
- },
- {
- 'begin': 0x1C00,
- 'end': 0x1C4F
- },
- {
- 'begin': 0x1C50,
- 'end': 0x1C7F
- },
- {
- 'begin': 0xA880,
- 'end': 0xA8DF
- },
- {
- 'begin': 0xA900,
- 'end': 0xA92F
- },
- {
- 'begin': 0xA930,
- 'end': 0xA95F
- },
- {
- 'begin': 0xAA00,
- 'end': 0xAA5F
- },
- {
- 'begin': 0x10190,
- 'end': 0x101CF
- },
- {
- 'begin': 0x101D0,
- 'end': 0x101FF
- },
- {
- 'begin': 0x102A0,
- 'end': 0x102DF
- },
- {
- 'begin': 0x1F030,
- 'end': 0x1F09F
- }
-];
-function getUnicodeRangeFor(value) {
- for (var i = 0, ii = UnicodeRanges.length; i < ii; i++) {
- var range = UnicodeRanges[i];
- if (value >= range.begin && value < range.end) {
- return i;
- }
- }
- return -1;
-}
-function isRTLRangeFor(value) {
- var range = UnicodeRanges[13];
- if (value >= range.begin && value < range.end) {
- return true;
- }
- range = UnicodeRanges[11];
- if (value >= range.begin && value < range.end) {
- return true;
- }
- return false;
-}
-var getNormalizedUnicodes = getLookupTableFactory(function (t) {
- t['\u00A8'] = '\u0020\u0308';
- t['\u00AF'] = '\u0020\u0304';
- t['\u00B4'] = '\u0020\u0301';
- t['\u00B5'] = '\u03BC';
- t['\u00B8'] = '\u0020\u0327';
- t['\u0132'] = '\u0049\u004A';
- t['\u0133'] = '\u0069\u006A';
- t['\u013F'] = '\u004C\u00B7';
- t['\u0140'] = '\u006C\u00B7';
- t['\u0149'] = '\u02BC\u006E';
- t['\u017F'] = '\u0073';
- t['\u01C4'] = '\u0044\u017D';
- t['\u01C5'] = '\u0044\u017E';
- t['\u01C6'] = '\u0064\u017E';
- t['\u01C7'] = '\u004C\u004A';
- t['\u01C8'] = '\u004C\u006A';
- t['\u01C9'] = '\u006C\u006A';
- t['\u01CA'] = '\u004E\u004A';
- t['\u01CB'] = '\u004E\u006A';
- t['\u01CC'] = '\u006E\u006A';
- t['\u01F1'] = '\u0044\u005A';
- t['\u01F2'] = '\u0044\u007A';
- t['\u01F3'] = '\u0064\u007A';
- t['\u02D8'] = '\u0020\u0306';
- t['\u02D9'] = '\u0020\u0307';
- t['\u02DA'] = '\u0020\u030A';
- t['\u02DB'] = '\u0020\u0328';
- t['\u02DC'] = '\u0020\u0303';
- t['\u02DD'] = '\u0020\u030B';
- t['\u037A'] = '\u0020\u0345';
- t['\u0384'] = '\u0020\u0301';
- t['\u03D0'] = '\u03B2';
- t['\u03D1'] = '\u03B8';
- t['\u03D2'] = '\u03A5';
- t['\u03D5'] = '\u03C6';
- t['\u03D6'] = '\u03C0';
- t['\u03F0'] = '\u03BA';
- t['\u03F1'] = '\u03C1';
- t['\u03F2'] = '\u03C2';
- t['\u03F4'] = '\u0398';
- t['\u03F5'] = '\u03B5';
- t['\u03F9'] = '\u03A3';
- t['\u0587'] = '\u0565\u0582';
- t['\u0675'] = '\u0627\u0674';
- t['\u0676'] = '\u0648\u0674';
- t['\u0677'] = '\u06C7\u0674';
- t['\u0678'] = '\u064A\u0674';
- t['\u0E33'] = '\u0E4D\u0E32';
- t['\u0EB3'] = '\u0ECD\u0EB2';
- t['\u0EDC'] = '\u0EAB\u0E99';
- t['\u0EDD'] = '\u0EAB\u0EA1';
- t['\u0F77'] = '\u0FB2\u0F81';
- t['\u0F79'] = '\u0FB3\u0F81';
- t['\u1E9A'] = '\u0061\u02BE';
- t['\u1FBD'] = '\u0020\u0313';
- t['\u1FBF'] = '\u0020\u0313';
- t['\u1FC0'] = '\u0020\u0342';
- t['\u1FFE'] = '\u0020\u0314';
- t['\u2002'] = '\u0020';
- t['\u2003'] = '\u0020';
- t['\u2004'] = '\u0020';
- t['\u2005'] = '\u0020';
- t['\u2006'] = '\u0020';
- t['\u2008'] = '\u0020';
- t['\u2009'] = '\u0020';
- t['\u200A'] = '\u0020';
- t['\u2017'] = '\u0020\u0333';
- t['\u2024'] = '\u002E';
- t['\u2025'] = '\u002E\u002E';
- t['\u2026'] = '\u002E\u002E\u002E';
- t['\u2033'] = '\u2032\u2032';
- t['\u2034'] = '\u2032\u2032\u2032';
- t['\u2036'] = '\u2035\u2035';
- t['\u2037'] = '\u2035\u2035\u2035';
- t['\u203C'] = '\u0021\u0021';
- t['\u203E'] = '\u0020\u0305';
- t['\u2047'] = '\u003F\u003F';
- t['\u2048'] = '\u003F\u0021';
- t['\u2049'] = '\u0021\u003F';
- t['\u2057'] = '\u2032\u2032\u2032\u2032';
- t['\u205F'] = '\u0020';
- t['\u20A8'] = '\u0052\u0073';
- t['\u2100'] = '\u0061\u002F\u0063';
- t['\u2101'] = '\u0061\u002F\u0073';
- t['\u2103'] = '\u00B0\u0043';
- t['\u2105'] = '\u0063\u002F\u006F';
- t['\u2106'] = '\u0063\u002F\u0075';
- t['\u2107'] = '\u0190';
- t['\u2109'] = '\u00B0\u0046';
- t['\u2116'] = '\u004E\u006F';
- t['\u2121'] = '\u0054\u0045\u004C';
- t['\u2135'] = '\u05D0';
- t['\u2136'] = '\u05D1';
- t['\u2137'] = '\u05D2';
- t['\u2138'] = '\u05D3';
- t['\u213B'] = '\u0046\u0041\u0058';
- t['\u2160'] = '\u0049';
- t['\u2161'] = '\u0049\u0049';
- t['\u2162'] = '\u0049\u0049\u0049';
- t['\u2163'] = '\u0049\u0056';
- t['\u2164'] = '\u0056';
- t['\u2165'] = '\u0056\u0049';
- t['\u2166'] = '\u0056\u0049\u0049';
- t['\u2167'] = '\u0056\u0049\u0049\u0049';
- t['\u2168'] = '\u0049\u0058';
- t['\u2169'] = '\u0058';
- t['\u216A'] = '\u0058\u0049';
- t['\u216B'] = '\u0058\u0049\u0049';
- t['\u216C'] = '\u004C';
- t['\u216D'] = '\u0043';
- t['\u216E'] = '\u0044';
- t['\u216F'] = '\u004D';
- t['\u2170'] = '\u0069';
- t['\u2171'] = '\u0069\u0069';
- t['\u2172'] = '\u0069\u0069\u0069';
- t['\u2173'] = '\u0069\u0076';
- t['\u2174'] = '\u0076';
- t['\u2175'] = '\u0076\u0069';
- t['\u2176'] = '\u0076\u0069\u0069';
- t['\u2177'] = '\u0076\u0069\u0069\u0069';
- t['\u2178'] = '\u0069\u0078';
- t['\u2179'] = '\u0078';
- t['\u217A'] = '\u0078\u0069';
- t['\u217B'] = '\u0078\u0069\u0069';
- t['\u217C'] = '\u006C';
- t['\u217D'] = '\u0063';
- t['\u217E'] = '\u0064';
- t['\u217F'] = '\u006D';
- t['\u222C'] = '\u222B\u222B';
- t['\u222D'] = '\u222B\u222B\u222B';
- t['\u222F'] = '\u222E\u222E';
- t['\u2230'] = '\u222E\u222E\u222E';
- t['\u2474'] = '\u0028\u0031\u0029';
- t['\u2475'] = '\u0028\u0032\u0029';
- t['\u2476'] = '\u0028\u0033\u0029';
- t['\u2477'] = '\u0028\u0034\u0029';
- t['\u2478'] = '\u0028\u0035\u0029';
- t['\u2479'] = '\u0028\u0036\u0029';
- t['\u247A'] = '\u0028\u0037\u0029';
- t['\u247B'] = '\u0028\u0038\u0029';
- t['\u247C'] = '\u0028\u0039\u0029';
- t['\u247D'] = '\u0028\u0031\u0030\u0029';
- t['\u247E'] = '\u0028\u0031\u0031\u0029';
- t['\u247F'] = '\u0028\u0031\u0032\u0029';
- t['\u2480'] = '\u0028\u0031\u0033\u0029';
- t['\u2481'] = '\u0028\u0031\u0034\u0029';
- t['\u2482'] = '\u0028\u0031\u0035\u0029';
- t['\u2483'] = '\u0028\u0031\u0036\u0029';
- t['\u2484'] = '\u0028\u0031\u0037\u0029';
- t['\u2485'] = '\u0028\u0031\u0038\u0029';
- t['\u2486'] = '\u0028\u0031\u0039\u0029';
- t['\u2487'] = '\u0028\u0032\u0030\u0029';
- t['\u2488'] = '\u0031\u002E';
- t['\u2489'] = '\u0032\u002E';
- t['\u248A'] = '\u0033\u002E';
- t['\u248B'] = '\u0034\u002E';
- t['\u248C'] = '\u0035\u002E';
- t['\u248D'] = '\u0036\u002E';
- t['\u248E'] = '\u0037\u002E';
- t['\u248F'] = '\u0038\u002E';
- t['\u2490'] = '\u0039\u002E';
- t['\u2491'] = '\u0031\u0030\u002E';
- t['\u2492'] = '\u0031\u0031\u002E';
- t['\u2493'] = '\u0031\u0032\u002E';
- t['\u2494'] = '\u0031\u0033\u002E';
- t['\u2495'] = '\u0031\u0034\u002E';
- t['\u2496'] = '\u0031\u0035\u002E';
- t['\u2497'] = '\u0031\u0036\u002E';
- t['\u2498'] = '\u0031\u0037\u002E';
- t['\u2499'] = '\u0031\u0038\u002E';
- t['\u249A'] = '\u0031\u0039\u002E';
- t['\u249B'] = '\u0032\u0030\u002E';
- t['\u249C'] = '\u0028\u0061\u0029';
- t['\u249D'] = '\u0028\u0062\u0029';
- t['\u249E'] = '\u0028\u0063\u0029';
- t['\u249F'] = '\u0028\u0064\u0029';
- t['\u24A0'] = '\u0028\u0065\u0029';
- t['\u24A1'] = '\u0028\u0066\u0029';
- t['\u24A2'] = '\u0028\u0067\u0029';
- t['\u24A3'] = '\u0028\u0068\u0029';
- t['\u24A4'] = '\u0028\u0069\u0029';
- t['\u24A5'] = '\u0028\u006A\u0029';
- t['\u24A6'] = '\u0028\u006B\u0029';
- t['\u24A7'] = '\u0028\u006C\u0029';
- t['\u24A8'] = '\u0028\u006D\u0029';
- t['\u24A9'] = '\u0028\u006E\u0029';
- t['\u24AA'] = '\u0028\u006F\u0029';
- t['\u24AB'] = '\u0028\u0070\u0029';
- t['\u24AC'] = '\u0028\u0071\u0029';
- t['\u24AD'] = '\u0028\u0072\u0029';
- t['\u24AE'] = '\u0028\u0073\u0029';
- t['\u24AF'] = '\u0028\u0074\u0029';
- t['\u24B0'] = '\u0028\u0075\u0029';
- t['\u24B1'] = '\u0028\u0076\u0029';
- t['\u24B2'] = '\u0028\u0077\u0029';
- t['\u24B3'] = '\u0028\u0078\u0029';
- t['\u24B4'] = '\u0028\u0079\u0029';
- t['\u24B5'] = '\u0028\u007A\u0029';
- t['\u2A0C'] = '\u222B\u222B\u222B\u222B';
- t['\u2A74'] = '\u003A\u003A\u003D';
- t['\u2A75'] = '\u003D\u003D';
- t['\u2A76'] = '\u003D\u003D\u003D';
- t['\u2E9F'] = '\u6BCD';
- t['\u2EF3'] = '\u9F9F';
- t['\u2F00'] = '\u4E00';
- t['\u2F01'] = '\u4E28';
- t['\u2F02'] = '\u4E36';
- t['\u2F03'] = '\u4E3F';
- t['\u2F04'] = '\u4E59';
- t['\u2F05'] = '\u4E85';
- t['\u2F06'] = '\u4E8C';
- t['\u2F07'] = '\u4EA0';
- t['\u2F08'] = '\u4EBA';
- t['\u2F09'] = '\u513F';
- t['\u2F0A'] = '\u5165';
- t['\u2F0B'] = '\u516B';
- t['\u2F0C'] = '\u5182';
- t['\u2F0D'] = '\u5196';
- t['\u2F0E'] = '\u51AB';
- t['\u2F0F'] = '\u51E0';
- t['\u2F10'] = '\u51F5';
- t['\u2F11'] = '\u5200';
- t['\u2F12'] = '\u529B';
- t['\u2F13'] = '\u52F9';
- t['\u2F14'] = '\u5315';
- t['\u2F15'] = '\u531A';
- t['\u2F16'] = '\u5338';
- t['\u2F17'] = '\u5341';
- t['\u2F18'] = '\u535C';
- t['\u2F19'] = '\u5369';
- t['\u2F1A'] = '\u5382';
- t['\u2F1B'] = '\u53B6';
- t['\u2F1C'] = '\u53C8';
- t['\u2F1D'] = '\u53E3';
- t['\u2F1E'] = '\u56D7';
- t['\u2F1F'] = '\u571F';
- t['\u2F20'] = '\u58EB';
- t['\u2F21'] = '\u5902';
- t['\u2F22'] = '\u590A';
- t['\u2F23'] = '\u5915';
- t['\u2F24'] = '\u5927';
- t['\u2F25'] = '\u5973';
- t['\u2F26'] = '\u5B50';
- t['\u2F27'] = '\u5B80';
- t['\u2F28'] = '\u5BF8';
- t['\u2F29'] = '\u5C0F';
- t['\u2F2A'] = '\u5C22';
- t['\u2F2B'] = '\u5C38';
- t['\u2F2C'] = '\u5C6E';
- t['\u2F2D'] = '\u5C71';
- t['\u2F2E'] = '\u5DDB';
- t['\u2F2F'] = '\u5DE5';
- t['\u2F30'] = '\u5DF1';
- t['\u2F31'] = '\u5DFE';
- t['\u2F32'] = '\u5E72';
- t['\u2F33'] = '\u5E7A';
- t['\u2F34'] = '\u5E7F';
- t['\u2F35'] = '\u5EF4';
- t['\u2F36'] = '\u5EFE';
- t['\u2F37'] = '\u5F0B';
- t['\u2F38'] = '\u5F13';
- t['\u2F39'] = '\u5F50';
- t['\u2F3A'] = '\u5F61';
- t['\u2F3B'] = '\u5F73';
- t['\u2F3C'] = '\u5FC3';
- t['\u2F3D'] = '\u6208';
- t['\u2F3E'] = '\u6236';
- t['\u2F3F'] = '\u624B';
- t['\u2F40'] = '\u652F';
- t['\u2F41'] = '\u6534';
- t['\u2F42'] = '\u6587';
- t['\u2F43'] = '\u6597';
- t['\u2F44'] = '\u65A4';
- t['\u2F45'] = '\u65B9';
- t['\u2F46'] = '\u65E0';
- t['\u2F47'] = '\u65E5';
- t['\u2F48'] = '\u66F0';
- t['\u2F49'] = '\u6708';
- t['\u2F4A'] = '\u6728';
- t['\u2F4B'] = '\u6B20';
- t['\u2F4C'] = '\u6B62';
- t['\u2F4D'] = '\u6B79';
- t['\u2F4E'] = '\u6BB3';
- t['\u2F4F'] = '\u6BCB';
- t['\u2F50'] = '\u6BD4';
- t['\u2F51'] = '\u6BDB';
- t['\u2F52'] = '\u6C0F';
- t['\u2F53'] = '\u6C14';
- t['\u2F54'] = '\u6C34';
- t['\u2F55'] = '\u706B';
- t['\u2F56'] = '\u722A';
- t['\u2F57'] = '\u7236';
- t['\u2F58'] = '\u723B';
- t['\u2F59'] = '\u723F';
- t['\u2F5A'] = '\u7247';
- t['\u2F5B'] = '\u7259';
- t['\u2F5C'] = '\u725B';
- t['\u2F5D'] = '\u72AC';
- t['\u2F5E'] = '\u7384';
- t['\u2F5F'] = '\u7389';
- t['\u2F60'] = '\u74DC';
- t['\u2F61'] = '\u74E6';
- t['\u2F62'] = '\u7518';
- t['\u2F63'] = '\u751F';
- t['\u2F64'] = '\u7528';
- t['\u2F65'] = '\u7530';
- t['\u2F66'] = '\u758B';
- t['\u2F67'] = '\u7592';
- t['\u2F68'] = '\u7676';
- t['\u2F69'] = '\u767D';
- t['\u2F6A'] = '\u76AE';
- t['\u2F6B'] = '\u76BF';
- t['\u2F6C'] = '\u76EE';
- t['\u2F6D'] = '\u77DB';
- t['\u2F6E'] = '\u77E2';
- t['\u2F6F'] = '\u77F3';
- t['\u2F70'] = '\u793A';
- t['\u2F71'] = '\u79B8';
- t['\u2F72'] = '\u79BE';
- t['\u2F73'] = '\u7A74';
- t['\u2F74'] = '\u7ACB';
- t['\u2F75'] = '\u7AF9';
- t['\u2F76'] = '\u7C73';
- t['\u2F77'] = '\u7CF8';
- t['\u2F78'] = '\u7F36';
- t['\u2F79'] = '\u7F51';
- t['\u2F7A'] = '\u7F8A';
- t['\u2F7B'] = '\u7FBD';
- t['\u2F7C'] = '\u8001';
- t['\u2F7D'] = '\u800C';
- t['\u2F7E'] = '\u8012';
- t['\u2F7F'] = '\u8033';
- t['\u2F80'] = '\u807F';
- t['\u2F81'] = '\u8089';
- t['\u2F82'] = '\u81E3';
- t['\u2F83'] = '\u81EA';
- t['\u2F84'] = '\u81F3';
- t['\u2F85'] = '\u81FC';
- t['\u2F86'] = '\u820C';
- t['\u2F87'] = '\u821B';
- t['\u2F88'] = '\u821F';
- t['\u2F89'] = '\u826E';
- t['\u2F8A'] = '\u8272';
- t['\u2F8B'] = '\u8278';
- t['\u2F8C'] = '\u864D';
- t['\u2F8D'] = '\u866B';
- t['\u2F8E'] = '\u8840';
- t['\u2F8F'] = '\u884C';
- t['\u2F90'] = '\u8863';
- t['\u2F91'] = '\u897E';
- t['\u2F92'] = '\u898B';
- t['\u2F93'] = '\u89D2';
- t['\u2F94'] = '\u8A00';
- t['\u2F95'] = '\u8C37';
- t['\u2F96'] = '\u8C46';
- t['\u2F97'] = '\u8C55';
- t['\u2F98'] = '\u8C78';
- t['\u2F99'] = '\u8C9D';
- t['\u2F9A'] = '\u8D64';
- t['\u2F9B'] = '\u8D70';
- t['\u2F9C'] = '\u8DB3';
- t['\u2F9D'] = '\u8EAB';
- t['\u2F9E'] = '\u8ECA';
- t['\u2F9F'] = '\u8F9B';
- t['\u2FA0'] = '\u8FB0';
- t['\u2FA1'] = '\u8FB5';
- t['\u2FA2'] = '\u9091';
- t['\u2FA3'] = '\u9149';
- t['\u2FA4'] = '\u91C6';
- t['\u2FA5'] = '\u91CC';
- t['\u2FA6'] = '\u91D1';
- t['\u2FA7'] = '\u9577';
- t['\u2FA8'] = '\u9580';
- t['\u2FA9'] = '\u961C';
- t['\u2FAA'] = '\u96B6';
- t['\u2FAB'] = '\u96B9';
- t['\u2FAC'] = '\u96E8';
- t['\u2FAD'] = '\u9751';
- t['\u2FAE'] = '\u975E';
- t['\u2FAF'] = '\u9762';
- t['\u2FB0'] = '\u9769';
- t['\u2FB1'] = '\u97CB';
- t['\u2FB2'] = '\u97ED';
- t['\u2FB3'] = '\u97F3';
- t['\u2FB4'] = '\u9801';
- t['\u2FB5'] = '\u98A8';
- t['\u2FB6'] = '\u98DB';
- t['\u2FB7'] = '\u98DF';
- t['\u2FB8'] = '\u9996';
- t['\u2FB9'] = '\u9999';
- t['\u2FBA'] = '\u99AC';
- t['\u2FBB'] = '\u9AA8';
- t['\u2FBC'] = '\u9AD8';
- t['\u2FBD'] = '\u9ADF';
- t['\u2FBE'] = '\u9B25';
- t['\u2FBF'] = '\u9B2F';
- t['\u2FC0'] = '\u9B32';
- t['\u2FC1'] = '\u9B3C';
- t['\u2FC2'] = '\u9B5A';
- t['\u2FC3'] = '\u9CE5';
- t['\u2FC4'] = '\u9E75';
- t['\u2FC5'] = '\u9E7F';
- t['\u2FC6'] = '\u9EA5';
- t['\u2FC7'] = '\u9EBB';
- t['\u2FC8'] = '\u9EC3';
- t['\u2FC9'] = '\u9ECD';
- t['\u2FCA'] = '\u9ED1';
- t['\u2FCB'] = '\u9EF9';
- t['\u2FCC'] = '\u9EFD';
- t['\u2FCD'] = '\u9F0E';
- t['\u2FCE'] = '\u9F13';
- t['\u2FCF'] = '\u9F20';
- t['\u2FD0'] = '\u9F3B';
- t['\u2FD1'] = '\u9F4A';
- t['\u2FD2'] = '\u9F52';
- t['\u2FD3'] = '\u9F8D';
- t['\u2FD4'] = '\u9F9C';
- t['\u2FD5'] = '\u9FA0';
- t['\u3036'] = '\u3012';
- t['\u3038'] = '\u5341';
- t['\u3039'] = '\u5344';
- t['\u303A'] = '\u5345';
- t['\u309B'] = '\u0020\u3099';
- t['\u309C'] = '\u0020\u309A';
- t['\u3131'] = '\u1100';
- t['\u3132'] = '\u1101';
- t['\u3133'] = '\u11AA';
- t['\u3134'] = '\u1102';
- t['\u3135'] = '\u11AC';
- t['\u3136'] = '\u11AD';
- t['\u3137'] = '\u1103';
- t['\u3138'] = '\u1104';
- t['\u3139'] = '\u1105';
- t['\u313A'] = '\u11B0';
- t['\u313B'] = '\u11B1';
- t['\u313C'] = '\u11B2';
- t['\u313D'] = '\u11B3';
- t['\u313E'] = '\u11B4';
- t['\u313F'] = '\u11B5';
- t['\u3140'] = '\u111A';
- t['\u3141'] = '\u1106';
- t['\u3142'] = '\u1107';
- t['\u3143'] = '\u1108';
- t['\u3144'] = '\u1121';
- t['\u3145'] = '\u1109';
- t['\u3146'] = '\u110A';
- t['\u3147'] = '\u110B';
- t['\u3148'] = '\u110C';
- t['\u3149'] = '\u110D';
- t['\u314A'] = '\u110E';
- t['\u314B'] = '\u110F';
- t['\u314C'] = '\u1110';
- t['\u314D'] = '\u1111';
- t['\u314E'] = '\u1112';
- t['\u314F'] = '\u1161';
- t['\u3150'] = '\u1162';
- t['\u3151'] = '\u1163';
- t['\u3152'] = '\u1164';
- t['\u3153'] = '\u1165';
- t['\u3154'] = '\u1166';
- t['\u3155'] = '\u1167';
- t['\u3156'] = '\u1168';
- t['\u3157'] = '\u1169';
- t['\u3158'] = '\u116A';
- t['\u3159'] = '\u116B';
- t['\u315A'] = '\u116C';
- t['\u315B'] = '\u116D';
- t['\u315C'] = '\u116E';
- t['\u315D'] = '\u116F';
- t['\u315E'] = '\u1170';
- t['\u315F'] = '\u1171';
- t['\u3160'] = '\u1172';
- t['\u3161'] = '\u1173';
- t['\u3162'] = '\u1174';
- t['\u3163'] = '\u1175';
- t['\u3164'] = '\u1160';
- t['\u3165'] = '\u1114';
- t['\u3166'] = '\u1115';
- t['\u3167'] = '\u11C7';
- t['\u3168'] = '\u11C8';
- t['\u3169'] = '\u11CC';
- t['\u316A'] = '\u11CE';
- t['\u316B'] = '\u11D3';
- t['\u316C'] = '\u11D7';
- t['\u316D'] = '\u11D9';
- t['\u316E'] = '\u111C';
- t['\u316F'] = '\u11DD';
- t['\u3170'] = '\u11DF';
- t['\u3171'] = '\u111D';
- t['\u3172'] = '\u111E';
- t['\u3173'] = '\u1120';
- t['\u3174'] = '\u1122';
- t['\u3175'] = '\u1123';
- t['\u3176'] = '\u1127';
- t['\u3177'] = '\u1129';
- t['\u3178'] = '\u112B';
- t['\u3179'] = '\u112C';
- t['\u317A'] = '\u112D';
- t['\u317B'] = '\u112E';
- t['\u317C'] = '\u112F';
- t['\u317D'] = '\u1132';
- t['\u317E'] = '\u1136';
- t['\u317F'] = '\u1140';
- t['\u3180'] = '\u1147';
- t['\u3181'] = '\u114C';
- t['\u3182'] = '\u11F1';
- t['\u3183'] = '\u11F2';
- t['\u3184'] = '\u1157';
- t['\u3185'] = '\u1158';
- t['\u3186'] = '\u1159';
- t['\u3187'] = '\u1184';
- t['\u3188'] = '\u1185';
- t['\u3189'] = '\u1188';
- t['\u318A'] = '\u1191';
- t['\u318B'] = '\u1192';
- t['\u318C'] = '\u1194';
- t['\u318D'] = '\u119E';
- t['\u318E'] = '\u11A1';
- t['\u3200'] = '\u0028\u1100\u0029';
- t['\u3201'] = '\u0028\u1102\u0029';
- t['\u3202'] = '\u0028\u1103\u0029';
- t['\u3203'] = '\u0028\u1105\u0029';
- t['\u3204'] = '\u0028\u1106\u0029';
- t['\u3205'] = '\u0028\u1107\u0029';
- t['\u3206'] = '\u0028\u1109\u0029';
- t['\u3207'] = '\u0028\u110B\u0029';
- t['\u3208'] = '\u0028\u110C\u0029';
- t['\u3209'] = '\u0028\u110E\u0029';
- t['\u320A'] = '\u0028\u110F\u0029';
- t['\u320B'] = '\u0028\u1110\u0029';
- t['\u320C'] = '\u0028\u1111\u0029';
- t['\u320D'] = '\u0028\u1112\u0029';
- t['\u320E'] = '\u0028\u1100\u1161\u0029';
- t['\u320F'] = '\u0028\u1102\u1161\u0029';
- t['\u3210'] = '\u0028\u1103\u1161\u0029';
- t['\u3211'] = '\u0028\u1105\u1161\u0029';
- t['\u3212'] = '\u0028\u1106\u1161\u0029';
- t['\u3213'] = '\u0028\u1107\u1161\u0029';
- t['\u3214'] = '\u0028\u1109\u1161\u0029';
- t['\u3215'] = '\u0028\u110B\u1161\u0029';
- t['\u3216'] = '\u0028\u110C\u1161\u0029';
- t['\u3217'] = '\u0028\u110E\u1161\u0029';
- t['\u3218'] = '\u0028\u110F\u1161\u0029';
- t['\u3219'] = '\u0028\u1110\u1161\u0029';
- t['\u321A'] = '\u0028\u1111\u1161\u0029';
- t['\u321B'] = '\u0028\u1112\u1161\u0029';
- t['\u321C'] = '\u0028\u110C\u116E\u0029';
- t['\u321D'] = '\u0028\u110B\u1169\u110C\u1165\u11AB\u0029';
- t['\u321E'] = '\u0028\u110B\u1169\u1112\u116E\u0029';
- t['\u3220'] = '\u0028\u4E00\u0029';
- t['\u3221'] = '\u0028\u4E8C\u0029';
- t['\u3222'] = '\u0028\u4E09\u0029';
- t['\u3223'] = '\u0028\u56DB\u0029';
- t['\u3224'] = '\u0028\u4E94\u0029';
- t['\u3225'] = '\u0028\u516D\u0029';
- t['\u3226'] = '\u0028\u4E03\u0029';
- t['\u3227'] = '\u0028\u516B\u0029';
- t['\u3228'] = '\u0028\u4E5D\u0029';
- t['\u3229'] = '\u0028\u5341\u0029';
- t['\u322A'] = '\u0028\u6708\u0029';
- t['\u322B'] = '\u0028\u706B\u0029';
- t['\u322C'] = '\u0028\u6C34\u0029';
- t['\u322D'] = '\u0028\u6728\u0029';
- t['\u322E'] = '\u0028\u91D1\u0029';
- t['\u322F'] = '\u0028\u571F\u0029';
- t['\u3230'] = '\u0028\u65E5\u0029';
- t['\u3231'] = '\u0028\u682A\u0029';
- t['\u3232'] = '\u0028\u6709\u0029';
- t['\u3233'] = '\u0028\u793E\u0029';
- t['\u3234'] = '\u0028\u540D\u0029';
- t['\u3235'] = '\u0028\u7279\u0029';
- t['\u3236'] = '\u0028\u8CA1\u0029';
- t['\u3237'] = '\u0028\u795D\u0029';
- t['\u3238'] = '\u0028\u52B4\u0029';
- t['\u3239'] = '\u0028\u4EE3\u0029';
- t['\u323A'] = '\u0028\u547C\u0029';
- t['\u323B'] = '\u0028\u5B66\u0029';
- t['\u323C'] = '\u0028\u76E3\u0029';
- t['\u323D'] = '\u0028\u4F01\u0029';
- t['\u323E'] = '\u0028\u8CC7\u0029';
- t['\u323F'] = '\u0028\u5354\u0029';
- t['\u3240'] = '\u0028\u796D\u0029';
- t['\u3241'] = '\u0028\u4F11\u0029';
- t['\u3242'] = '\u0028\u81EA\u0029';
- t['\u3243'] = '\u0028\u81F3\u0029';
- t['\u32C0'] = '\u0031\u6708';
- t['\u32C1'] = '\u0032\u6708';
- t['\u32C2'] = '\u0033\u6708';
- t['\u32C3'] = '\u0034\u6708';
- t['\u32C4'] = '\u0035\u6708';
- t['\u32C5'] = '\u0036\u6708';
- t['\u32C6'] = '\u0037\u6708';
- t['\u32C7'] = '\u0038\u6708';
- t['\u32C8'] = '\u0039\u6708';
- t['\u32C9'] = '\u0031\u0030\u6708';
- t['\u32CA'] = '\u0031\u0031\u6708';
- t['\u32CB'] = '\u0031\u0032\u6708';
- t['\u3358'] = '\u0030\u70B9';
- t['\u3359'] = '\u0031\u70B9';
- t['\u335A'] = '\u0032\u70B9';
- t['\u335B'] = '\u0033\u70B9';
- t['\u335C'] = '\u0034\u70B9';
- t['\u335D'] = '\u0035\u70B9';
- t['\u335E'] = '\u0036\u70B9';
- t['\u335F'] = '\u0037\u70B9';
- t['\u3360'] = '\u0038\u70B9';
- t['\u3361'] = '\u0039\u70B9';
- t['\u3362'] = '\u0031\u0030\u70B9';
- t['\u3363'] = '\u0031\u0031\u70B9';
- t['\u3364'] = '\u0031\u0032\u70B9';
- t['\u3365'] = '\u0031\u0033\u70B9';
- t['\u3366'] = '\u0031\u0034\u70B9';
- t['\u3367'] = '\u0031\u0035\u70B9';
- t['\u3368'] = '\u0031\u0036\u70B9';
- t['\u3369'] = '\u0031\u0037\u70B9';
- t['\u336A'] = '\u0031\u0038\u70B9';
- t['\u336B'] = '\u0031\u0039\u70B9';
- t['\u336C'] = '\u0032\u0030\u70B9';
- t['\u336D'] = '\u0032\u0031\u70B9';
- t['\u336E'] = '\u0032\u0032\u70B9';
- t['\u336F'] = '\u0032\u0033\u70B9';
- t['\u3370'] = '\u0032\u0034\u70B9';
- t['\u33E0'] = '\u0031\u65E5';
- t['\u33E1'] = '\u0032\u65E5';
- t['\u33E2'] = '\u0033\u65E5';
- t['\u33E3'] = '\u0034\u65E5';
- t['\u33E4'] = '\u0035\u65E5';
- t['\u33E5'] = '\u0036\u65E5';
- t['\u33E6'] = '\u0037\u65E5';
- t['\u33E7'] = '\u0038\u65E5';
- t['\u33E8'] = '\u0039\u65E5';
- t['\u33E9'] = '\u0031\u0030\u65E5';
- t['\u33EA'] = '\u0031\u0031\u65E5';
- t['\u33EB'] = '\u0031\u0032\u65E5';
- t['\u33EC'] = '\u0031\u0033\u65E5';
- t['\u33ED'] = '\u0031\u0034\u65E5';
- t['\u33EE'] = '\u0031\u0035\u65E5';
- t['\u33EF'] = '\u0031\u0036\u65E5';
- t['\u33F0'] = '\u0031\u0037\u65E5';
- t['\u33F1'] = '\u0031\u0038\u65E5';
- t['\u33F2'] = '\u0031\u0039\u65E5';
- t['\u33F3'] = '\u0032\u0030\u65E5';
- t['\u33F4'] = '\u0032\u0031\u65E5';
- t['\u33F5'] = '\u0032\u0032\u65E5';
- t['\u33F6'] = '\u0032\u0033\u65E5';
- t['\u33F7'] = '\u0032\u0034\u65E5';
- t['\u33F8'] = '\u0032\u0035\u65E5';
- t['\u33F9'] = '\u0032\u0036\u65E5';
- t['\u33FA'] = '\u0032\u0037\u65E5';
- t['\u33FB'] = '\u0032\u0038\u65E5';
- t['\u33FC'] = '\u0032\u0039\u65E5';
- t['\u33FD'] = '\u0033\u0030\u65E5';
- t['\u33FE'] = '\u0033\u0031\u65E5';
- t['\uFB00'] = '\u0066\u0066';
- t['\uFB01'] = '\u0066\u0069';
- t['\uFB02'] = '\u0066\u006C';
- t['\uFB03'] = '\u0066\u0066\u0069';
- t['\uFB04'] = '\u0066\u0066\u006C';
- t['\uFB05'] = '\u017F\u0074';
- t['\uFB06'] = '\u0073\u0074';
- t['\uFB13'] = '\u0574\u0576';
- t['\uFB14'] = '\u0574\u0565';
- t['\uFB15'] = '\u0574\u056B';
- t['\uFB16'] = '\u057E\u0576';
- t['\uFB17'] = '\u0574\u056D';
- t['\uFB4F'] = '\u05D0\u05DC';
- t['\uFB50'] = '\u0671';
- t['\uFB51'] = '\u0671';
- t['\uFB52'] = '\u067B';
- t['\uFB53'] = '\u067B';
- t['\uFB54'] = '\u067B';
- t['\uFB55'] = '\u067B';
- t['\uFB56'] = '\u067E';
- t['\uFB57'] = '\u067E';
- t['\uFB58'] = '\u067E';
- t['\uFB59'] = '\u067E';
- t['\uFB5A'] = '\u0680';
- t['\uFB5B'] = '\u0680';
- t['\uFB5C'] = '\u0680';
- t['\uFB5D'] = '\u0680';
- t['\uFB5E'] = '\u067A';
- t['\uFB5F'] = '\u067A';
- t['\uFB60'] = '\u067A';
- t['\uFB61'] = '\u067A';
- t['\uFB62'] = '\u067F';
- t['\uFB63'] = '\u067F';
- t['\uFB64'] = '\u067F';
- t['\uFB65'] = '\u067F';
- t['\uFB66'] = '\u0679';
- t['\uFB67'] = '\u0679';
- t['\uFB68'] = '\u0679';
- t['\uFB69'] = '\u0679';
- t['\uFB6A'] = '\u06A4';
- t['\uFB6B'] = '\u06A4';
- t['\uFB6C'] = '\u06A4';
- t['\uFB6D'] = '\u06A4';
- t['\uFB6E'] = '\u06A6';
- t['\uFB6F'] = '\u06A6';
- t['\uFB70'] = '\u06A6';
- t['\uFB71'] = '\u06A6';
- t['\uFB72'] = '\u0684';
- t['\uFB73'] = '\u0684';
- t['\uFB74'] = '\u0684';
- t['\uFB75'] = '\u0684';
- t['\uFB76'] = '\u0683';
- t['\uFB77'] = '\u0683';
- t['\uFB78'] = '\u0683';
- t['\uFB79'] = '\u0683';
- t['\uFB7A'] = '\u0686';
- t['\uFB7B'] = '\u0686';
- t['\uFB7C'] = '\u0686';
- t['\uFB7D'] = '\u0686';
- t['\uFB7E'] = '\u0687';
- t['\uFB7F'] = '\u0687';
- t['\uFB80'] = '\u0687';
- t['\uFB81'] = '\u0687';
- t['\uFB82'] = '\u068D';
- t['\uFB83'] = '\u068D';
- t['\uFB84'] = '\u068C';
- t['\uFB85'] = '\u068C';
- t['\uFB86'] = '\u068E';
- t['\uFB87'] = '\u068E';
- t['\uFB88'] = '\u0688';
- t['\uFB89'] = '\u0688';
- t['\uFB8A'] = '\u0698';
- t['\uFB8B'] = '\u0698';
- t['\uFB8C'] = '\u0691';
- t['\uFB8D'] = '\u0691';
- t['\uFB8E'] = '\u06A9';
- t['\uFB8F'] = '\u06A9';
- t['\uFB90'] = '\u06A9';
- t['\uFB91'] = '\u06A9';
- t['\uFB92'] = '\u06AF';
- t['\uFB93'] = '\u06AF';
- t['\uFB94'] = '\u06AF';
- t['\uFB95'] = '\u06AF';
- t['\uFB96'] = '\u06B3';
- t['\uFB97'] = '\u06B3';
- t['\uFB98'] = '\u06B3';
- t['\uFB99'] = '\u06B3';
- t['\uFB9A'] = '\u06B1';
- t['\uFB9B'] = '\u06B1';
- t['\uFB9C'] = '\u06B1';
- t['\uFB9D'] = '\u06B1';
- t['\uFB9E'] = '\u06BA';
- t['\uFB9F'] = '\u06BA';
- t['\uFBA0'] = '\u06BB';
- t['\uFBA1'] = '\u06BB';
- t['\uFBA2'] = '\u06BB';
- t['\uFBA3'] = '\u06BB';
- t['\uFBA4'] = '\u06C0';
- t['\uFBA5'] = '\u06C0';
- t['\uFBA6'] = '\u06C1';
- t['\uFBA7'] = '\u06C1';
- t['\uFBA8'] = '\u06C1';
- t['\uFBA9'] = '\u06C1';
- t['\uFBAA'] = '\u06BE';
- t['\uFBAB'] = '\u06BE';
- t['\uFBAC'] = '\u06BE';
- t['\uFBAD'] = '\u06BE';
- t['\uFBAE'] = '\u06D2';
- t['\uFBAF'] = '\u06D2';
- t['\uFBB0'] = '\u06D3';
- t['\uFBB1'] = '\u06D3';
- t['\uFBD3'] = '\u06AD';
- t['\uFBD4'] = '\u06AD';
- t['\uFBD5'] = '\u06AD';
- t['\uFBD6'] = '\u06AD';
- t['\uFBD7'] = '\u06C7';
- t['\uFBD8'] = '\u06C7';
- t['\uFBD9'] = '\u06C6';
- t['\uFBDA'] = '\u06C6';
- t['\uFBDB'] = '\u06C8';
- t['\uFBDC'] = '\u06C8';
- t['\uFBDD'] = '\u0677';
- t['\uFBDE'] = '\u06CB';
- t['\uFBDF'] = '\u06CB';
- t['\uFBE0'] = '\u06C5';
- t['\uFBE1'] = '\u06C5';
- t['\uFBE2'] = '\u06C9';
- t['\uFBE3'] = '\u06C9';
- t['\uFBE4'] = '\u06D0';
- t['\uFBE5'] = '\u06D0';
- t['\uFBE6'] = '\u06D0';
- t['\uFBE7'] = '\u06D0';
- t['\uFBE8'] = '\u0649';
- t['\uFBE9'] = '\u0649';
- t['\uFBEA'] = '\u0626\u0627';
- t['\uFBEB'] = '\u0626\u0627';
- t['\uFBEC'] = '\u0626\u06D5';
- t['\uFBED'] = '\u0626\u06D5';
- t['\uFBEE'] = '\u0626\u0648';
- t['\uFBEF'] = '\u0626\u0648';
- t['\uFBF0'] = '\u0626\u06C7';
- t['\uFBF1'] = '\u0626\u06C7';
- t['\uFBF2'] = '\u0626\u06C6';
- t['\uFBF3'] = '\u0626\u06C6';
- t['\uFBF4'] = '\u0626\u06C8';
- t['\uFBF5'] = '\u0626\u06C8';
- t['\uFBF6'] = '\u0626\u06D0';
- t['\uFBF7'] = '\u0626\u06D0';
- t['\uFBF8'] = '\u0626\u06D0';
- t['\uFBF9'] = '\u0626\u0649';
- t['\uFBFA'] = '\u0626\u0649';
- t['\uFBFB'] = '\u0626\u0649';
- t['\uFBFC'] = '\u06CC';
- t['\uFBFD'] = '\u06CC';
- t['\uFBFE'] = '\u06CC';
- t['\uFBFF'] = '\u06CC';
- t['\uFC00'] = '\u0626\u062C';
- t['\uFC01'] = '\u0626\u062D';
- t['\uFC02'] = '\u0626\u0645';
- t['\uFC03'] = '\u0626\u0649';
- t['\uFC04'] = '\u0626\u064A';
- t['\uFC05'] = '\u0628\u062C';
- t['\uFC06'] = '\u0628\u062D';
- t['\uFC07'] = '\u0628\u062E';
- t['\uFC08'] = '\u0628\u0645';
- t['\uFC09'] = '\u0628\u0649';
- t['\uFC0A'] = '\u0628\u064A';
- t['\uFC0B'] = '\u062A\u062C';
- t['\uFC0C'] = '\u062A\u062D';
- t['\uFC0D'] = '\u062A\u062E';
- t['\uFC0E'] = '\u062A\u0645';
- t['\uFC0F'] = '\u062A\u0649';
- t['\uFC10'] = '\u062A\u064A';
- t['\uFC11'] = '\u062B\u062C';
- t['\uFC12'] = '\u062B\u0645';
- t['\uFC13'] = '\u062B\u0649';
- t['\uFC14'] = '\u062B\u064A';
- t['\uFC15'] = '\u062C\u062D';
- t['\uFC16'] = '\u062C\u0645';
- t['\uFC17'] = '\u062D\u062C';
- t['\uFC18'] = '\u062D\u0645';
- t['\uFC19'] = '\u062E\u062C';
- t['\uFC1A'] = '\u062E\u062D';
- t['\uFC1B'] = '\u062E\u0645';
- t['\uFC1C'] = '\u0633\u062C';
- t['\uFC1D'] = '\u0633\u062D';
- t['\uFC1E'] = '\u0633\u062E';
- t['\uFC1F'] = '\u0633\u0645';
- t['\uFC20'] = '\u0635\u062D';
- t['\uFC21'] = '\u0635\u0645';
- t['\uFC22'] = '\u0636\u062C';
- t['\uFC23'] = '\u0636\u062D';
- t['\uFC24'] = '\u0636\u062E';
- t['\uFC25'] = '\u0636\u0645';
- t['\uFC26'] = '\u0637\u062D';
- t['\uFC27'] = '\u0637\u0645';
- t['\uFC28'] = '\u0638\u0645';
- t['\uFC29'] = '\u0639\u062C';
- t['\uFC2A'] = '\u0639\u0645';
- t['\uFC2B'] = '\u063A\u062C';
- t['\uFC2C'] = '\u063A\u0645';
- t['\uFC2D'] = '\u0641\u062C';
- t['\uFC2E'] = '\u0641\u062D';
- t['\uFC2F'] = '\u0641\u062E';
- t['\uFC30'] = '\u0641\u0645';
- t['\uFC31'] = '\u0641\u0649';
- t['\uFC32'] = '\u0641\u064A';
- t['\uFC33'] = '\u0642\u062D';
- t['\uFC34'] = '\u0642\u0645';
- t['\uFC35'] = '\u0642\u0649';
- t['\uFC36'] = '\u0642\u064A';
- t['\uFC37'] = '\u0643\u0627';
- t['\uFC38'] = '\u0643\u062C';
- t['\uFC39'] = '\u0643\u062D';
- t['\uFC3A'] = '\u0643\u062E';
- t['\uFC3B'] = '\u0643\u0644';
- t['\uFC3C'] = '\u0643\u0645';
- t['\uFC3D'] = '\u0643\u0649';
- t['\uFC3E'] = '\u0643\u064A';
- t['\uFC3F'] = '\u0644\u062C';
- t['\uFC40'] = '\u0644\u062D';
- t['\uFC41'] = '\u0644\u062E';
- t['\uFC42'] = '\u0644\u0645';
- t['\uFC43'] = '\u0644\u0649';
- t['\uFC44'] = '\u0644\u064A';
- t['\uFC45'] = '\u0645\u062C';
- t['\uFC46'] = '\u0645\u062D';
- t['\uFC47'] = '\u0645\u062E';
- t['\uFC48'] = '\u0645\u0645';
- t['\uFC49'] = '\u0645\u0649';
- t['\uFC4A'] = '\u0645\u064A';
- t['\uFC4B'] = '\u0646\u062C';
- t['\uFC4C'] = '\u0646\u062D';
- t['\uFC4D'] = '\u0646\u062E';
- t['\uFC4E'] = '\u0646\u0645';
- t['\uFC4F'] = '\u0646\u0649';
- t['\uFC50'] = '\u0646\u064A';
- t['\uFC51'] = '\u0647\u062C';
- t['\uFC52'] = '\u0647\u0645';
- t['\uFC53'] = '\u0647\u0649';
- t['\uFC54'] = '\u0647\u064A';
- t['\uFC55'] = '\u064A\u062C';
- t['\uFC56'] = '\u064A\u062D';
- t['\uFC57'] = '\u064A\u062E';
- t['\uFC58'] = '\u064A\u0645';
- t['\uFC59'] = '\u064A\u0649';
- t['\uFC5A'] = '\u064A\u064A';
- t['\uFC5B'] = '\u0630\u0670';
- t['\uFC5C'] = '\u0631\u0670';
- t['\uFC5D'] = '\u0649\u0670';
- t['\uFC5E'] = '\u0020\u064C\u0651';
- t['\uFC5F'] = '\u0020\u064D\u0651';
- t['\uFC60'] = '\u0020\u064E\u0651';
- t['\uFC61'] = '\u0020\u064F\u0651';
- t['\uFC62'] = '\u0020\u0650\u0651';
- t['\uFC63'] = '\u0020\u0651\u0670';
- t['\uFC64'] = '\u0626\u0631';
- t['\uFC65'] = '\u0626\u0632';
- t['\uFC66'] = '\u0626\u0645';
- t['\uFC67'] = '\u0626\u0646';
- t['\uFC68'] = '\u0626\u0649';
- t['\uFC69'] = '\u0626\u064A';
- t['\uFC6A'] = '\u0628\u0631';
- t['\uFC6B'] = '\u0628\u0632';
- t['\uFC6C'] = '\u0628\u0645';
- t['\uFC6D'] = '\u0628\u0646';
- t['\uFC6E'] = '\u0628\u0649';
- t['\uFC6F'] = '\u0628\u064A';
- t['\uFC70'] = '\u062A\u0631';
- t['\uFC71'] = '\u062A\u0632';
- t['\uFC72'] = '\u062A\u0645';
- t['\uFC73'] = '\u062A\u0646';
- t['\uFC74'] = '\u062A\u0649';
- t['\uFC75'] = '\u062A\u064A';
- t['\uFC76'] = '\u062B\u0631';
- t['\uFC77'] = '\u062B\u0632';
- t['\uFC78'] = '\u062B\u0645';
- t['\uFC79'] = '\u062B\u0646';
- t['\uFC7A'] = '\u062B\u0649';
- t['\uFC7B'] = '\u062B\u064A';
- t['\uFC7C'] = '\u0641\u0649';
- t['\uFC7D'] = '\u0641\u064A';
- t['\uFC7E'] = '\u0642\u0649';
- t['\uFC7F'] = '\u0642\u064A';
- t['\uFC80'] = '\u0643\u0627';
- t['\uFC81'] = '\u0643\u0644';
- t['\uFC82'] = '\u0643\u0645';
- t['\uFC83'] = '\u0643\u0649';
- t['\uFC84'] = '\u0643\u064A';
- t['\uFC85'] = '\u0644\u0645';
- t['\uFC86'] = '\u0644\u0649';
- t['\uFC87'] = '\u0644\u064A';
- t['\uFC88'] = '\u0645\u0627';
- t['\uFC89'] = '\u0645\u0645';
- t['\uFC8A'] = '\u0646\u0631';
- t['\uFC8B'] = '\u0646\u0632';
- t['\uFC8C'] = '\u0646\u0645';
- t['\uFC8D'] = '\u0646\u0646';
- t['\uFC8E'] = '\u0646\u0649';
- t['\uFC8F'] = '\u0646\u064A';
- t['\uFC90'] = '\u0649\u0670';
- t['\uFC91'] = '\u064A\u0631';
- t['\uFC92'] = '\u064A\u0632';
- t['\uFC93'] = '\u064A\u0645';
- t['\uFC94'] = '\u064A\u0646';
- t['\uFC95'] = '\u064A\u0649';
- t['\uFC96'] = '\u064A\u064A';
- t['\uFC97'] = '\u0626\u062C';
- t['\uFC98'] = '\u0626\u062D';
- t['\uFC99'] = '\u0626\u062E';
- t['\uFC9A'] = '\u0626\u0645';
- t['\uFC9B'] = '\u0626\u0647';
- t['\uFC9C'] = '\u0628\u062C';
- t['\uFC9D'] = '\u0628\u062D';
- t['\uFC9E'] = '\u0628\u062E';
- t['\uFC9F'] = '\u0628\u0645';
- t['\uFCA0'] = '\u0628\u0647';
- t['\uFCA1'] = '\u062A\u062C';
- t['\uFCA2'] = '\u062A\u062D';
- t['\uFCA3'] = '\u062A\u062E';
- t['\uFCA4'] = '\u062A\u0645';
- t['\uFCA5'] = '\u062A\u0647';
- t['\uFCA6'] = '\u062B\u0645';
- t['\uFCA7'] = '\u062C\u062D';
- t['\uFCA8'] = '\u062C\u0645';
- t['\uFCA9'] = '\u062D\u062C';
- t['\uFCAA'] = '\u062D\u0645';
- t['\uFCAB'] = '\u062E\u062C';
- t['\uFCAC'] = '\u062E\u0645';
- t['\uFCAD'] = '\u0633\u062C';
- t['\uFCAE'] = '\u0633\u062D';
- t['\uFCAF'] = '\u0633\u062E';
- t['\uFCB0'] = '\u0633\u0645';
- t['\uFCB1'] = '\u0635\u062D';
- t['\uFCB2'] = '\u0635\u062E';
- t['\uFCB3'] = '\u0635\u0645';
- t['\uFCB4'] = '\u0636\u062C';
- t['\uFCB5'] = '\u0636\u062D';
- t['\uFCB6'] = '\u0636\u062E';
- t['\uFCB7'] = '\u0636\u0645';
- t['\uFCB8'] = '\u0637\u062D';
- t['\uFCB9'] = '\u0638\u0645';
- t['\uFCBA'] = '\u0639\u062C';
- t['\uFCBB'] = '\u0639\u0645';
- t['\uFCBC'] = '\u063A\u062C';
- t['\uFCBD'] = '\u063A\u0645';
- t['\uFCBE'] = '\u0641\u062C';
- t['\uFCBF'] = '\u0641\u062D';
- t['\uFCC0'] = '\u0641\u062E';
- t['\uFCC1'] = '\u0641\u0645';
- t['\uFCC2'] = '\u0642\u062D';
- t['\uFCC3'] = '\u0642\u0645';
- t['\uFCC4'] = '\u0643\u062C';
- t['\uFCC5'] = '\u0643\u062D';
- t['\uFCC6'] = '\u0643\u062E';
- t['\uFCC7'] = '\u0643\u0644';
- t['\uFCC8'] = '\u0643\u0645';
- t['\uFCC9'] = '\u0644\u062C';
- t['\uFCCA'] = '\u0644\u062D';
- t['\uFCCB'] = '\u0644\u062E';
- t['\uFCCC'] = '\u0644\u0645';
- t['\uFCCD'] = '\u0644\u0647';
- t['\uFCCE'] = '\u0645\u062C';
- t['\uFCCF'] = '\u0645\u062D';
- t['\uFCD0'] = '\u0645\u062E';
- t['\uFCD1'] = '\u0645\u0645';
- t['\uFCD2'] = '\u0646\u062C';
- t['\uFCD3'] = '\u0646\u062D';
- t['\uFCD4'] = '\u0646\u062E';
- t['\uFCD5'] = '\u0646\u0645';
- t['\uFCD6'] = '\u0646\u0647';
- t['\uFCD7'] = '\u0647\u062C';
- t['\uFCD8'] = '\u0647\u0645';
- t['\uFCD9'] = '\u0647\u0670';
- t['\uFCDA'] = '\u064A\u062C';
- t['\uFCDB'] = '\u064A\u062D';
- t['\uFCDC'] = '\u064A\u062E';
- t['\uFCDD'] = '\u064A\u0645';
- t['\uFCDE'] = '\u064A\u0647';
- t['\uFCDF'] = '\u0626\u0645';
- t['\uFCE0'] = '\u0626\u0647';
- t['\uFCE1'] = '\u0628\u0645';
- t['\uFCE2'] = '\u0628\u0647';
- t['\uFCE3'] = '\u062A\u0645';
- t['\uFCE4'] = '\u062A\u0647';
- t['\uFCE5'] = '\u062B\u0645';
- t['\uFCE6'] = '\u062B\u0647';
- t['\uFCE7'] = '\u0633\u0645';
- t['\uFCE8'] = '\u0633\u0647';
- t['\uFCE9'] = '\u0634\u0645';
- t['\uFCEA'] = '\u0634\u0647';
- t['\uFCEB'] = '\u0643\u0644';
- t['\uFCEC'] = '\u0643\u0645';
- t['\uFCED'] = '\u0644\u0645';
- t['\uFCEE'] = '\u0646\u0645';
- t['\uFCEF'] = '\u0646\u0647';
- t['\uFCF0'] = '\u064A\u0645';
- t['\uFCF1'] = '\u064A\u0647';
- t['\uFCF2'] = '\u0640\u064E\u0651';
- t['\uFCF3'] = '\u0640\u064F\u0651';
- t['\uFCF4'] = '\u0640\u0650\u0651';
- t['\uFCF5'] = '\u0637\u0649';
- t['\uFCF6'] = '\u0637\u064A';
- t['\uFCF7'] = '\u0639\u0649';
- t['\uFCF8'] = '\u0639\u064A';
- t['\uFCF9'] = '\u063A\u0649';
- t['\uFCFA'] = '\u063A\u064A';
- t['\uFCFB'] = '\u0633\u0649';
- t['\uFCFC'] = '\u0633\u064A';
- t['\uFCFD'] = '\u0634\u0649';
- t['\uFCFE'] = '\u0634\u064A';
- t['\uFCFF'] = '\u062D\u0649';
- t['\uFD00'] = '\u062D\u064A';
- t['\uFD01'] = '\u062C\u0649';
- t['\uFD02'] = '\u062C\u064A';
- t['\uFD03'] = '\u062E\u0649';
- t['\uFD04'] = '\u062E\u064A';
- t['\uFD05'] = '\u0635\u0649';
- t['\uFD06'] = '\u0635\u064A';
- t['\uFD07'] = '\u0636\u0649';
- t['\uFD08'] = '\u0636\u064A';
- t['\uFD09'] = '\u0634\u062C';
- t['\uFD0A'] = '\u0634\u062D';
- t['\uFD0B'] = '\u0634\u062E';
- t['\uFD0C'] = '\u0634\u0645';
- t['\uFD0D'] = '\u0634\u0631';
- t['\uFD0E'] = '\u0633\u0631';
- t['\uFD0F'] = '\u0635\u0631';
- t['\uFD10'] = '\u0636\u0631';
- t['\uFD11'] = '\u0637\u0649';
- t['\uFD12'] = '\u0637\u064A';
- t['\uFD13'] = '\u0639\u0649';
- t['\uFD14'] = '\u0639\u064A';
- t['\uFD15'] = '\u063A\u0649';
- t['\uFD16'] = '\u063A\u064A';
- t['\uFD17'] = '\u0633\u0649';
- t['\uFD18'] = '\u0633\u064A';
- t['\uFD19'] = '\u0634\u0649';
- t['\uFD1A'] = '\u0634\u064A';
- t['\uFD1B'] = '\u062D\u0649';
- t['\uFD1C'] = '\u062D\u064A';
- t['\uFD1D'] = '\u062C\u0649';
- t['\uFD1E'] = '\u062C\u064A';
- t['\uFD1F'] = '\u062E\u0649';
- t['\uFD20'] = '\u062E\u064A';
- t['\uFD21'] = '\u0635\u0649';
- t['\uFD22'] = '\u0635\u064A';
- t['\uFD23'] = '\u0636\u0649';
- t['\uFD24'] = '\u0636\u064A';
- t['\uFD25'] = '\u0634\u062C';
- t['\uFD26'] = '\u0634\u062D';
- t['\uFD27'] = '\u0634\u062E';
- t['\uFD28'] = '\u0634\u0645';
- t['\uFD29'] = '\u0634\u0631';
- t['\uFD2A'] = '\u0633\u0631';
- t['\uFD2B'] = '\u0635\u0631';
- t['\uFD2C'] = '\u0636\u0631';
- t['\uFD2D'] = '\u0634\u062C';
- t['\uFD2E'] = '\u0634\u062D';
- t['\uFD2F'] = '\u0634\u062E';
- t['\uFD30'] = '\u0634\u0645';
- t['\uFD31'] = '\u0633\u0647';
- t['\uFD32'] = '\u0634\u0647';
- t['\uFD33'] = '\u0637\u0645';
- t['\uFD34'] = '\u0633\u062C';
- t['\uFD35'] = '\u0633\u062D';
- t['\uFD36'] = '\u0633\u062E';
- t['\uFD37'] = '\u0634\u062C';
- t['\uFD38'] = '\u0634\u062D';
- t['\uFD39'] = '\u0634\u062E';
- t['\uFD3A'] = '\u0637\u0645';
- t['\uFD3B'] = '\u0638\u0645';
- t['\uFD3C'] = '\u0627\u064B';
- t['\uFD3D'] = '\u0627\u064B';
- t['\uFD50'] = '\u062A\u062C\u0645';
- t['\uFD51'] = '\u062A\u062D\u062C';
- t['\uFD52'] = '\u062A\u062D\u062C';
- t['\uFD53'] = '\u062A\u062D\u0645';
- t['\uFD54'] = '\u062A\u062E\u0645';
- t['\uFD55'] = '\u062A\u0645\u062C';
- t['\uFD56'] = '\u062A\u0645\u062D';
- t['\uFD57'] = '\u062A\u0645\u062E';
- t['\uFD58'] = '\u062C\u0645\u062D';
- t['\uFD59'] = '\u062C\u0645\u062D';
- t['\uFD5A'] = '\u062D\u0645\u064A';
- t['\uFD5B'] = '\u062D\u0645\u0649';
- t['\uFD5C'] = '\u0633\u062D\u062C';
- t['\uFD5D'] = '\u0633\u062C\u062D';
- t['\uFD5E'] = '\u0633\u062C\u0649';
- t['\uFD5F'] = '\u0633\u0645\u062D';
- t['\uFD60'] = '\u0633\u0645\u062D';
- t['\uFD61'] = '\u0633\u0645\u062C';
- t['\uFD62'] = '\u0633\u0645\u0645';
- t['\uFD63'] = '\u0633\u0645\u0645';
- t['\uFD64'] = '\u0635\u062D\u062D';
- t['\uFD65'] = '\u0635\u062D\u062D';
- t['\uFD66'] = '\u0635\u0645\u0645';
- t['\uFD67'] = '\u0634\u062D\u0645';
- t['\uFD68'] = '\u0634\u062D\u0645';
- t['\uFD69'] = '\u0634\u062C\u064A';
- t['\uFD6A'] = '\u0634\u0645\u062E';
- t['\uFD6B'] = '\u0634\u0645\u062E';
- t['\uFD6C'] = '\u0634\u0645\u0645';
- t['\uFD6D'] = '\u0634\u0645\u0645';
- t['\uFD6E'] = '\u0636\u062D\u0649';
- t['\uFD6F'] = '\u0636\u062E\u0645';
- t['\uFD70'] = '\u0636\u062E\u0645';
- t['\uFD71'] = '\u0637\u0645\u062D';
- t['\uFD72'] = '\u0637\u0645\u062D';
- t['\uFD73'] = '\u0637\u0645\u0645';
- t['\uFD74'] = '\u0637\u0645\u064A';
- t['\uFD75'] = '\u0639\u062C\u0645';
- t['\uFD76'] = '\u0639\u0645\u0645';
- t['\uFD77'] = '\u0639\u0645\u0645';
- t['\uFD78'] = '\u0639\u0645\u0649';
- t['\uFD79'] = '\u063A\u0645\u0645';
- t['\uFD7A'] = '\u063A\u0645\u064A';
- t['\uFD7B'] = '\u063A\u0645\u0649';
- t['\uFD7C'] = '\u0641\u062E\u0645';
- t['\uFD7D'] = '\u0641\u062E\u0645';
- t['\uFD7E'] = '\u0642\u0645\u062D';
- t['\uFD7F'] = '\u0642\u0645\u0645';
- t['\uFD80'] = '\u0644\u062D\u0645';
- t['\uFD81'] = '\u0644\u062D\u064A';
- t['\uFD82'] = '\u0644\u062D\u0649';
- t['\uFD83'] = '\u0644\u062C\u062C';
- t['\uFD84'] = '\u0644\u062C\u062C';
- t['\uFD85'] = '\u0644\u062E\u0645';
- t['\uFD86'] = '\u0644\u062E\u0645';
- t['\uFD87'] = '\u0644\u0645\u062D';
- t['\uFD88'] = '\u0644\u0645\u062D';
- t['\uFD89'] = '\u0645\u062D\u062C';
- t['\uFD8A'] = '\u0645\u062D\u0645';
- t['\uFD8B'] = '\u0645\u062D\u064A';
- t['\uFD8C'] = '\u0645\u062C\u062D';
- t['\uFD8D'] = '\u0645\u062C\u0645';
- t['\uFD8E'] = '\u0645\u062E\u062C';
- t['\uFD8F'] = '\u0645\u062E\u0645';
- t['\uFD92'] = '\u0645\u062C\u062E';
- t['\uFD93'] = '\u0647\u0645\u062C';
- t['\uFD94'] = '\u0647\u0645\u0645';
- t['\uFD95'] = '\u0646\u062D\u0645';
- t['\uFD96'] = '\u0646\u062D\u0649';
- t['\uFD97'] = '\u0646\u062C\u0645';
- t['\uFD98'] = '\u0646\u062C\u0645';
- t['\uFD99'] = '\u0646\u062C\u0649';
- t['\uFD9A'] = '\u0646\u0645\u064A';
- t['\uFD9B'] = '\u0646\u0645\u0649';
- t['\uFD9C'] = '\u064A\u0645\u0645';
- t['\uFD9D'] = '\u064A\u0645\u0645';
- t['\uFD9E'] = '\u0628\u062E\u064A';
- t['\uFD9F'] = '\u062A\u062C\u064A';
- t['\uFDA0'] = '\u062A\u062C\u0649';
- t['\uFDA1'] = '\u062A\u062E\u064A';
- t['\uFDA2'] = '\u062A\u062E\u0649';
- t['\uFDA3'] = '\u062A\u0645\u064A';
- t['\uFDA4'] = '\u062A\u0645\u0649';
- t['\uFDA5'] = '\u062C\u0645\u064A';
- t['\uFDA6'] = '\u062C\u062D\u0649';
- t['\uFDA7'] = '\u062C\u0645\u0649';
- t['\uFDA8'] = '\u0633\u062E\u0649';
- t['\uFDA9'] = '\u0635\u062D\u064A';
- t['\uFDAA'] = '\u0634\u062D\u064A';
- t['\uFDAB'] = '\u0636\u062D\u064A';
- t['\uFDAC'] = '\u0644\u062C\u064A';
- t['\uFDAD'] = '\u0644\u0645\u064A';
- t['\uFDAE'] = '\u064A\u062D\u064A';
- t['\uFDAF'] = '\u064A\u062C\u064A';
- t['\uFDB0'] = '\u064A\u0645\u064A';
- t['\uFDB1'] = '\u0645\u0645\u064A';
- t['\uFDB2'] = '\u0642\u0645\u064A';
- t['\uFDB3'] = '\u0646\u062D\u064A';
- t['\uFDB4'] = '\u0642\u0645\u062D';
- t['\uFDB5'] = '\u0644\u062D\u0645';
- t['\uFDB6'] = '\u0639\u0645\u064A';
- t['\uFDB7'] = '\u0643\u0645\u064A';
- t['\uFDB8'] = '\u0646\u062C\u062D';
- t['\uFDB9'] = '\u0645\u062E\u064A';
- t['\uFDBA'] = '\u0644\u062C\u0645';
- t['\uFDBB'] = '\u0643\u0645\u0645';
- t['\uFDBC'] = '\u0644\u062C\u0645';
- t['\uFDBD'] = '\u0646\u062C\u062D';
- t['\uFDBE'] = '\u062C\u062D\u064A';
- t['\uFDBF'] = '\u062D\u062C\u064A';
- t['\uFDC0'] = '\u0645\u062C\u064A';
- t['\uFDC1'] = '\u0641\u0645\u064A';
- t['\uFDC2'] = '\u0628\u062D\u064A';
- t['\uFDC3'] = '\u0643\u0645\u0645';
- t['\uFDC4'] = '\u0639\u062C\u0645';
- t['\uFDC5'] = '\u0635\u0645\u0645';
- t['\uFDC6'] = '\u0633\u062E\u064A';
- t['\uFDC7'] = '\u0646\u062C\u064A';
- t['\uFE49'] = '\u203E';
- t['\uFE4A'] = '\u203E';
- t['\uFE4B'] = '\u203E';
- t['\uFE4C'] = '\u203E';
- t['\uFE4D'] = '\u005F';
- t['\uFE4E'] = '\u005F';
- t['\uFE4F'] = '\u005F';
- t['\uFE80'] = '\u0621';
- t['\uFE81'] = '\u0622';
- t['\uFE82'] = '\u0622';
- t['\uFE83'] = '\u0623';
- t['\uFE84'] = '\u0623';
- t['\uFE85'] = '\u0624';
- t['\uFE86'] = '\u0624';
- t['\uFE87'] = '\u0625';
- t['\uFE88'] = '\u0625';
- t['\uFE89'] = '\u0626';
- t['\uFE8A'] = '\u0626';
- t['\uFE8B'] = '\u0626';
- t['\uFE8C'] = '\u0626';
- t['\uFE8D'] = '\u0627';
- t['\uFE8E'] = '\u0627';
- t['\uFE8F'] = '\u0628';
- t['\uFE90'] = '\u0628';
- t['\uFE91'] = '\u0628';
- t['\uFE92'] = '\u0628';
- t['\uFE93'] = '\u0629';
- t['\uFE94'] = '\u0629';
- t['\uFE95'] = '\u062A';
- t['\uFE96'] = '\u062A';
- t['\uFE97'] = '\u062A';
- t['\uFE98'] = '\u062A';
- t['\uFE99'] = '\u062B';
- t['\uFE9A'] = '\u062B';
- t['\uFE9B'] = '\u062B';
- t['\uFE9C'] = '\u062B';
- t['\uFE9D'] = '\u062C';
- t['\uFE9E'] = '\u062C';
- t['\uFE9F'] = '\u062C';
- t['\uFEA0'] = '\u062C';
- t['\uFEA1'] = '\u062D';
- t['\uFEA2'] = '\u062D';
- t['\uFEA3'] = '\u062D';
- t['\uFEA4'] = '\u062D';
- t['\uFEA5'] = '\u062E';
- t['\uFEA6'] = '\u062E';
- t['\uFEA7'] = '\u062E';
- t['\uFEA8'] = '\u062E';
- t['\uFEA9'] = '\u062F';
- t['\uFEAA'] = '\u062F';
- t['\uFEAB'] = '\u0630';
- t['\uFEAC'] = '\u0630';
- t['\uFEAD'] = '\u0631';
- t['\uFEAE'] = '\u0631';
- t['\uFEAF'] = '\u0632';
- t['\uFEB0'] = '\u0632';
- t['\uFEB1'] = '\u0633';
- t['\uFEB2'] = '\u0633';
- t['\uFEB3'] = '\u0633';
- t['\uFEB4'] = '\u0633';
- t['\uFEB5'] = '\u0634';
- t['\uFEB6'] = '\u0634';
- t['\uFEB7'] = '\u0634';
- t['\uFEB8'] = '\u0634';
- t['\uFEB9'] = '\u0635';
- t['\uFEBA'] = '\u0635';
- t['\uFEBB'] = '\u0635';
- t['\uFEBC'] = '\u0635';
- t['\uFEBD'] = '\u0636';
- t['\uFEBE'] = '\u0636';
- t['\uFEBF'] = '\u0636';
- t['\uFEC0'] = '\u0636';
- t['\uFEC1'] = '\u0637';
- t['\uFEC2'] = '\u0637';
- t['\uFEC3'] = '\u0637';
- t['\uFEC4'] = '\u0637';
- t['\uFEC5'] = '\u0638';
- t['\uFEC6'] = '\u0638';
- t['\uFEC7'] = '\u0638';
- t['\uFEC8'] = '\u0638';
- t['\uFEC9'] = '\u0639';
- t['\uFECA'] = '\u0639';
- t['\uFECB'] = '\u0639';
- t['\uFECC'] = '\u0639';
- t['\uFECD'] = '\u063A';
- t['\uFECE'] = '\u063A';
- t['\uFECF'] = '\u063A';
- t['\uFED0'] = '\u063A';
- t['\uFED1'] = '\u0641';
- t['\uFED2'] = '\u0641';
- t['\uFED3'] = '\u0641';
- t['\uFED4'] = '\u0641';
- t['\uFED5'] = '\u0642';
- t['\uFED6'] = '\u0642';
- t['\uFED7'] = '\u0642';
- t['\uFED8'] = '\u0642';
- t['\uFED9'] = '\u0643';
- t['\uFEDA'] = '\u0643';
- t['\uFEDB'] = '\u0643';
- t['\uFEDC'] = '\u0643';
- t['\uFEDD'] = '\u0644';
- t['\uFEDE'] = '\u0644';
- t['\uFEDF'] = '\u0644';
- t['\uFEE0'] = '\u0644';
- t['\uFEE1'] = '\u0645';
- t['\uFEE2'] = '\u0645';
- t['\uFEE3'] = '\u0645';
- t['\uFEE4'] = '\u0645';
- t['\uFEE5'] = '\u0646';
- t['\uFEE6'] = '\u0646';
- t['\uFEE7'] = '\u0646';
- t['\uFEE8'] = '\u0646';
- t['\uFEE9'] = '\u0647';
- t['\uFEEA'] = '\u0647';
- t['\uFEEB'] = '\u0647';
- t['\uFEEC'] = '\u0647';
- t['\uFEED'] = '\u0648';
- t['\uFEEE'] = '\u0648';
- t['\uFEEF'] = '\u0649';
- t['\uFEF0'] = '\u0649';
- t['\uFEF1'] = '\u064A';
- t['\uFEF2'] = '\u064A';
- t['\uFEF3'] = '\u064A';
- t['\uFEF4'] = '\u064A';
- t['\uFEF5'] = '\u0644\u0622';
- t['\uFEF6'] = '\u0644\u0622';
- t['\uFEF7'] = '\u0644\u0623';
- t['\uFEF8'] = '\u0644\u0623';
- t['\uFEF9'] = '\u0644\u0625';
- t['\uFEFA'] = '\u0644\u0625';
- t['\uFEFB'] = '\u0644\u0627';
- t['\uFEFC'] = '\u0644\u0627';
-});
-function reverseIfRtl(chars) {
- var charsLength = chars.length;
- if (charsLength <= 1 || !isRTLRangeFor(chars.charCodeAt(0))) {
- return chars;
- }
- var s = '';
- for (var ii = charsLength - 1; ii >= 0; ii--) {
- s += chars[ii];
- }
- return s;
-}
-exports.mapSpecialUnicodeValues = mapSpecialUnicodeValues;
-exports.reverseIfRtl = reverseIfRtl;
-exports.getUnicodeRangeFor = getUnicodeRangeFor;
-exports.getNormalizedUnicodes = getNormalizedUnicodes;
-exports.getUnicodeForGlyph = getUnicodeForGlyph;
-
-/***/ }),
-/* 163 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.FontRendererFactory = undefined;
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-var _util = __w_pdfjs_require__(2);
-
-var _cff_parser = __w_pdfjs_require__(157);
-
-var _glyphlist = __w_pdfjs_require__(160);
-
-var _encodings = __w_pdfjs_require__(159);
-
-var _stream = __w_pdfjs_require__(140);
-
-function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
-
-function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-var FontRendererFactory = function FontRendererFactoryClosure() {
- function getLong(data, offset) {
- return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3];
- }
- function getUshort(data, offset) {
- return data[offset] << 8 | data[offset + 1];
- }
- function parseCmap(data, start, end) {
- var offset = getUshort(data, start + 2) === 1 ? getLong(data, start + 8) : getLong(data, start + 16);
- var format = getUshort(data, start + offset);
- var ranges, p, i;
- if (format === 4) {
- getUshort(data, start + offset + 2);
- var segCount = getUshort(data, start + offset + 6) >> 1;
- p = start + offset + 14;
- ranges = [];
- for (i = 0; i < segCount; i++, p += 2) {
- ranges[i] = { end: getUshort(data, p) };
- }
- p += 2;
- for (i = 0; i < segCount; i++, p += 2) {
- ranges[i].start = getUshort(data, p);
- }
- for (i = 0; i < segCount; i++, p += 2) {
- ranges[i].idDelta = getUshort(data, p);
- }
- for (i = 0; i < segCount; i++, p += 2) {
- var idOffset = getUshort(data, p);
- if (idOffset === 0) {
- continue;
- }
- ranges[i].ids = [];
- for (var j = 0, jj = ranges[i].end - ranges[i].start + 1; j < jj; j++) {
- ranges[i].ids[j] = getUshort(data, p + idOffset);
- idOffset += 2;
- }
- }
- return ranges;
- } else if (format === 12) {
- getLong(data, start + offset + 4);
- var groups = getLong(data, start + offset + 12);
- p = start + offset + 16;
- ranges = [];
- for (i = 0; i < groups; i++) {
- ranges.push({
- start: getLong(data, p),
- end: getLong(data, p + 4),
- idDelta: getLong(data, p + 8) - getLong(data, p)
- });
- p += 12;
- }
- return ranges;
- }
- throw new _util.FormatError('unsupported cmap: ' + format);
- }
- function parseCff(data, start, end, seacAnalysisEnabled) {
- var properties = {};
- var parser = new _cff_parser.CFFParser(new _stream.Stream(data, start, end - start), properties, seacAnalysisEnabled);
- var cff = parser.parse();
- return {
- glyphs: cff.charStrings.objects,
- subrs: cff.topDict.privateDict && cff.topDict.privateDict.subrsIndex && cff.topDict.privateDict.subrsIndex.objects,
- gsubrs: cff.globalSubrIndex && cff.globalSubrIndex.objects,
- isCFFCIDFont: cff.isCIDFont,
- fdSelect: cff.fdSelect,
- fdArray: cff.fdArray
- };
- }
- function parseGlyfTable(glyf, loca, isGlyphLocationsLong) {
- var itemSize, itemDecode;
- if (isGlyphLocationsLong) {
- itemSize = 4;
- itemDecode = function fontItemDecodeLong(data, offset) {
- return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3];
- };
- } else {
- itemSize = 2;
- itemDecode = function fontItemDecode(data, offset) {
- return data[offset] << 9 | data[offset + 1] << 1;
- };
- }
- var glyphs = [];
- var startOffset = itemDecode(loca, 0);
- for (var j = itemSize; j < loca.length; j += itemSize) {
- var endOffset = itemDecode(loca, j);
- glyphs.push(glyf.subarray(startOffset, endOffset));
- startOffset = endOffset;
- }
- return glyphs;
- }
- function lookupCmap(ranges, unicode) {
- var code = unicode.codePointAt(0),
- gid = 0;
- var l = 0,
- r = ranges.length - 1;
- while (l < r) {
- var c = l + r + 1 >> 1;
- if (code < ranges[c].start) {
- r = c - 1;
- } else {
- l = c;
- }
- }
- if (ranges[l].start <= code && code <= ranges[l].end) {
- gid = ranges[l].idDelta + (ranges[l].ids ? ranges[l].ids[code - ranges[l].start] : code) & 0xFFFF;
- }
- return {
- charCode: code,
- glyphId: gid
- };
- }
- function compileGlyf(code, cmds, font) {
- function moveTo(x, y) {
- cmds.push({
- cmd: 'moveTo',
- args: [x, y]
- });
- }
- function lineTo(x, y) {
- cmds.push({
- cmd: 'lineTo',
- args: [x, y]
- });
- }
- function quadraticCurveTo(xa, ya, x, y) {
- cmds.push({
- cmd: 'quadraticCurveTo',
- args: [xa, ya, x, y]
- });
- }
- var i = 0;
- var numberOfContours = (code[i] << 24 | code[i + 1] << 16) >> 16;
- var flags;
- var x = 0,
- y = 0;
- i += 10;
- if (numberOfContours < 0) {
- do {
- flags = code[i] << 8 | code[i + 1];
- var glyphIndex = code[i + 2] << 8 | code[i + 3];
- i += 4;
- var arg1, arg2;
- if (flags & 0x01) {
- arg1 = (code[i] << 24 | code[i + 1] << 16) >> 16;
- arg2 = (code[i + 2] << 24 | code[i + 3] << 16) >> 16;
- i += 4;
- } else {
- arg1 = code[i++];
- arg2 = code[i++];
- }
- if (flags & 0x02) {
- x = arg1;
- y = arg2;
- } else {
- x = 0;
- y = 0;
- }
- var scaleX = 1,
- scaleY = 1,
- scale01 = 0,
- scale10 = 0;
- if (flags & 0x08) {
- scaleX = scaleY = (code[i] << 24 | code[i + 1] << 16) / 1073741824;
- i += 2;
- } else if (flags & 0x40) {
- scaleX = (code[i] << 24 | code[i + 1] << 16) / 1073741824;
- scaleY = (code[i + 2] << 24 | code[i + 3] << 16) / 1073741824;
- i += 4;
- } else if (flags & 0x80) {
- scaleX = (code[i] << 24 | code[i + 1] << 16) / 1073741824;
- scale01 = (code[i + 2] << 24 | code[i + 3] << 16) / 1073741824;
- scale10 = (code[i + 4] << 24 | code[i + 5] << 16) / 1073741824;
- scaleY = (code[i + 6] << 24 | code[i + 7] << 16) / 1073741824;
- i += 8;
- }
- var subglyph = font.glyphs[glyphIndex];
- if (subglyph) {
- cmds.push({ cmd: 'save' });
- cmds.push({
- cmd: 'transform',
- args: [scaleX, scale01, scale10, scaleY, x, y]
- });
- compileGlyf(subglyph, cmds, font);
- cmds.push({ cmd: 'restore' });
- }
- } while (flags & 0x20);
- } else {
- var endPtsOfContours = [];
- var j, jj;
- for (j = 0; j < numberOfContours; j++) {
- endPtsOfContours.push(code[i] << 8 | code[i + 1]);
- i += 2;
- }
- var instructionLength = code[i] << 8 | code[i + 1];
- i += 2 + instructionLength;
- var numberOfPoints = endPtsOfContours[endPtsOfContours.length - 1] + 1;
- var points = [];
- while (points.length < numberOfPoints) {
- flags = code[i++];
- var repeat = 1;
- if (flags & 0x08) {
- repeat += code[i++];
- }
- while (repeat-- > 0) {
- points.push({ flags: flags });
- }
- }
- for (j = 0; j < numberOfPoints; j++) {
- switch (points[j].flags & 0x12) {
- case 0x00:
- x += (code[i] << 24 | code[i + 1] << 16) >> 16;
- i += 2;
- break;
- case 0x02:
- x -= code[i++];
- break;
- case 0x12:
- x += code[i++];
- break;
- }
- points[j].x = x;
- }
- for (j = 0; j < numberOfPoints; j++) {
- switch (points[j].flags & 0x24) {
- case 0x00:
- y += (code[i] << 24 | code[i + 1] << 16) >> 16;
- i += 2;
- break;
- case 0x04:
- y -= code[i++];
- break;
- case 0x24:
- y += code[i++];
- break;
- }
- points[j].y = y;
- }
- var startPoint = 0;
- for (i = 0; i < numberOfContours; i++) {
- var endPoint = endPtsOfContours[i];
- var contour = points.slice(startPoint, endPoint + 1);
- if (contour[0].flags & 1) {
- contour.push(contour[0]);
- } else if (contour[contour.length - 1].flags & 1) {
- contour.unshift(contour[contour.length - 1]);
- } else {
- var p = {
- flags: 1,
- x: (contour[0].x + contour[contour.length - 1].x) / 2,
- y: (contour[0].y + contour[contour.length - 1].y) / 2
- };
- contour.unshift(p);
- contour.push(p);
- }
- moveTo(contour[0].x, contour[0].y);
- for (j = 1, jj = contour.length; j < jj; j++) {
- if (contour[j].flags & 1) {
- lineTo(contour[j].x, contour[j].y);
- } else if (contour[j + 1].flags & 1) {
- quadraticCurveTo(contour[j].x, contour[j].y, contour[j + 1].x, contour[j + 1].y);
- j++;
- } else {
- quadraticCurveTo(contour[j].x, contour[j].y, (contour[j].x + contour[j + 1].x) / 2, (contour[j].y + contour[j + 1].y) / 2);
- }
- }
- startPoint = endPoint + 1;
- }
- }
- }
- function compileCharString(code, cmds, font, glyphId) {
- var stack = [];
- var x = 0,
- y = 0;
- var stems = 0;
- function moveTo(x, y) {
- cmds.push({
- cmd: 'moveTo',
- args: [x, y]
- });
- }
- function lineTo(x, y) {
- cmds.push({
- cmd: 'lineTo',
- args: [x, y]
- });
- }
- function bezierCurveTo(x1, y1, x2, y2, x, y) {
- cmds.push({
- cmd: 'bezierCurveTo',
- args: [x1, y1, x2, y2, x, y]
- });
- }
- function parse(code) {
- var i = 0;
- while (i < code.length) {
- var stackClean = false;
- var v = code[i++];
- var xa, xb, ya, yb, y1, y2, y3, n, subrCode;
- switch (v) {
- case 1:
- stems += stack.length >> 1;
- stackClean = true;
- break;
- case 3:
- stems += stack.length >> 1;
- stackClean = true;
- break;
- case 4:
- y += stack.pop();
- moveTo(x, y);
- stackClean = true;
- break;
- case 5:
- while (stack.length > 0) {
- x += stack.shift();
- y += stack.shift();
- lineTo(x, y);
- }
- break;
- case 6:
- while (stack.length > 0) {
- x += stack.shift();
- lineTo(x, y);
- if (stack.length === 0) {
- break;
- }
- y += stack.shift();
- lineTo(x, y);
- }
- break;
- case 7:
- while (stack.length > 0) {
- y += stack.shift();
- lineTo(x, y);
- if (stack.length === 0) {
- break;
- }
- x += stack.shift();
- lineTo(x, y);
- }
- break;
- case 8:
- while (stack.length > 0) {
- xa = x + stack.shift();
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb + stack.shift();
- y = yb + stack.shift();
- bezierCurveTo(xa, ya, xb, yb, x, y);
- }
- break;
- case 10:
- n = stack.pop();
- subrCode = null;
- if (font.isCFFCIDFont) {
- var fdIndex = font.fdSelect.getFDIndex(glyphId);
- if (fdIndex >= 0 && fdIndex < font.fdArray.length) {
- var fontDict = font.fdArray[fdIndex],
- subrs = void 0;
- if (fontDict.privateDict && fontDict.privateDict.subrsIndex) {
- subrs = fontDict.privateDict.subrsIndex.objects;
- }
- if (subrs) {
- var numSubrs = subrs.length;
- n += numSubrs < 1240 ? 107 : numSubrs < 33900 ? 1131 : 32768;
- subrCode = subrs[n];
- }
- } else {
- (0, _util.warn)('Invalid fd index for glyph index.');
- }
- } else {
- subrCode = font.subrs[n + font.subrsBias];
- }
- if (subrCode) {
- parse(subrCode);
- }
- break;
- case 11:
- return;
- case 12:
- v = code[i++];
- switch (v) {
- case 34:
- xa = x + stack.shift();
- xb = xa + stack.shift();
- y1 = y + stack.shift();
- x = xb + stack.shift();
- bezierCurveTo(xa, y, xb, y1, x, y1);
- xa = x + stack.shift();
- xb = xa + stack.shift();
- x = xb + stack.shift();
- bezierCurveTo(xa, y1, xb, y, x, y);
- break;
- case 35:
- xa = x + stack.shift();
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb + stack.shift();
- y = yb + stack.shift();
- bezierCurveTo(xa, ya, xb, yb, x, y);
- xa = x + stack.shift();
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb + stack.shift();
- y = yb + stack.shift();
- bezierCurveTo(xa, ya, xb, yb, x, y);
- stack.pop();
- break;
- case 36:
- xa = x + stack.shift();
- y1 = y + stack.shift();
- xb = xa + stack.shift();
- y2 = y1 + stack.shift();
- x = xb + stack.shift();
- bezierCurveTo(xa, y1, xb, y2, x, y2);
- xa = x + stack.shift();
- xb = xa + stack.shift();
- y3 = y2 + stack.shift();
- x = xb + stack.shift();
- bezierCurveTo(xa, y2, xb, y3, x, y);
- break;
- case 37:
- var x0 = x,
- y0 = y;
- xa = x + stack.shift();
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb + stack.shift();
- y = yb + stack.shift();
- bezierCurveTo(xa, ya, xb, yb, x, y);
- xa = x + stack.shift();
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb;
- y = yb;
- if (Math.abs(x - x0) > Math.abs(y - y0)) {
- x += stack.shift();
- } else {
- y += stack.shift();
- }
- bezierCurveTo(xa, ya, xb, yb, x, y);
- break;
- default:
- throw new _util.FormatError('unknown operator: 12 ' + v);
- }
- break;
- case 14:
- if (stack.length >= 4) {
- var achar = stack.pop();
- var bchar = stack.pop();
- y = stack.pop();
- x = stack.pop();
- cmds.push({ cmd: 'save' });
- cmds.push({
- cmd: 'translate',
- args: [x, y]
- });
- var cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[_encodings.StandardEncoding[achar]]));
- compileCharString(font.glyphs[cmap.glyphId], cmds, font, cmap.glyphId);
- cmds.push({ cmd: 'restore' });
- cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[_encodings.StandardEncoding[bchar]]));
- compileCharString(font.glyphs[cmap.glyphId], cmds, font, cmap.glyphId);
- }
- return;
- case 18:
- stems += stack.length >> 1;
- stackClean = true;
- break;
- case 19:
- stems += stack.length >> 1;
- i += stems + 7 >> 3;
- stackClean = true;
- break;
- case 20:
- stems += stack.length >> 1;
- i += stems + 7 >> 3;
- stackClean = true;
- break;
- case 21:
- y += stack.pop();
- x += stack.pop();
- moveTo(x, y);
- stackClean = true;
- break;
- case 22:
- x += stack.pop();
- moveTo(x, y);
- stackClean = true;
- break;
- case 23:
- stems += stack.length >> 1;
- stackClean = true;
- break;
- case 24:
- while (stack.length > 2) {
- xa = x + stack.shift();
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb + stack.shift();
- y = yb + stack.shift();
- bezierCurveTo(xa, ya, xb, yb, x, y);
- }
- x += stack.shift();
- y += stack.shift();
- lineTo(x, y);
- break;
- case 25:
- while (stack.length > 6) {
- x += stack.shift();
- y += stack.shift();
- lineTo(x, y);
- }
- xa = x + stack.shift();
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb + stack.shift();
- y = yb + stack.shift();
- bezierCurveTo(xa, ya, xb, yb, x, y);
- break;
- case 26:
- if (stack.length % 2) {
- x += stack.shift();
- }
- while (stack.length > 0) {
- xa = x;
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb;
- y = yb + stack.shift();
- bezierCurveTo(xa, ya, xb, yb, x, y);
- }
- break;
- case 27:
- if (stack.length % 2) {
- y += stack.shift();
- }
- while (stack.length > 0) {
- xa = x + stack.shift();
- ya = y;
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb + stack.shift();
- y = yb;
- bezierCurveTo(xa, ya, xb, yb, x, y);
- }
- break;
- case 28:
- stack.push((code[i] << 24 | code[i + 1] << 16) >> 16);
- i += 2;
- break;
- case 29:
- n = stack.pop() + font.gsubrsBias;
- subrCode = font.gsubrs[n];
- if (subrCode) {
- parse(subrCode);
- }
- break;
- case 30:
- while (stack.length > 0) {
- xa = x;
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb + stack.shift();
- y = yb + (stack.length === 1 ? stack.shift() : 0);
- bezierCurveTo(xa, ya, xb, yb, x, y);
- if (stack.length === 0) {
- break;
- }
- xa = x + stack.shift();
- ya = y;
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- y = yb + stack.shift();
- x = xb + (stack.length === 1 ? stack.shift() : 0);
- bezierCurveTo(xa, ya, xb, yb, x, y);
- }
- break;
- case 31:
- while (stack.length > 0) {
- xa = x + stack.shift();
- ya = y;
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- y = yb + stack.shift();
- x = xb + (stack.length === 1 ? stack.shift() : 0);
- bezierCurveTo(xa, ya, xb, yb, x, y);
- if (stack.length === 0) {
- break;
- }
- xa = x;
- ya = y + stack.shift();
- xb = xa + stack.shift();
- yb = ya + stack.shift();
- x = xb + stack.shift();
- y = yb + (stack.length === 1 ? stack.shift() : 0);
- bezierCurveTo(xa, ya, xb, yb, x, y);
- }
- break;
- default:
- if (v < 32) {
- throw new _util.FormatError('unknown operator: ' + v);
- }
- if (v < 247) {
- stack.push(v - 139);
- } else if (v < 251) {
- stack.push((v - 247) * 256 + code[i++] + 108);
- } else if (v < 255) {
- stack.push(-(v - 251) * 256 - code[i++] - 108);
- } else {
- stack.push((code[i] << 24 | code[i + 1] << 16 | code[i + 2] << 8 | code[i + 3]) / 65536);
- i += 4;
- }
- break;
- }
- if (stackClean) {
- stack.length = 0;
- }
- }
- }
- parse(code);
- }
- var NOOP = [];
-
- var CompiledFont = function () {
- function CompiledFont(fontMatrix) {
- _classCallCheck(this, CompiledFont);
-
- if (this.constructor === CompiledFont) {
- (0, _util.unreachable)('Cannot initialize CompiledFont.');
- }
- this.fontMatrix = fontMatrix;
- this.compiledGlyphs = Object.create(null);
- this.compiledCharCodeToGlyphId = Object.create(null);
- }
-
- _createClass(CompiledFont, [{
- key: 'getPathJs',
- value: function getPathJs(unicode) {
- var cmap = lookupCmap(this.cmap, unicode);
- var fn = this.compiledGlyphs[cmap.glyphId];
- if (!fn) {
- fn = this.compileGlyph(this.glyphs[cmap.glyphId], cmap.glyphId);
- this.compiledGlyphs[cmap.glyphId] = fn;
- }
- if (this.compiledCharCodeToGlyphId[cmap.charCode] === undefined) {
- this.compiledCharCodeToGlyphId[cmap.charCode] = cmap.glyphId;
- }
- return fn;
- }
- }, {
- key: 'compileGlyph',
- value: function compileGlyph(code, glyphId) {
- if (!code || code.length === 0 || code[0] === 14) {
- return NOOP;
- }
- var fontMatrix = this.fontMatrix;
- if (this.isCFFCIDFont) {
- var fdIndex = this.fdSelect.getFDIndex(glyphId);
- if (fdIndex >= 0 && fdIndex < this.fdArray.length) {
- var fontDict = this.fdArray[fdIndex];
- fontMatrix = fontDict.getByName('FontMatrix') || _util.FONT_IDENTITY_MATRIX;
- } else {
- (0, _util.warn)('Invalid fd index for glyph index.');
- }
- }
- var cmds = [];
- cmds.push({ cmd: 'save' });
- cmds.push({
- cmd: 'transform',
- args: fontMatrix.slice()
- });
- cmds.push({
- cmd: 'scale',
- args: ['size', '-size']
- });
- this.compileGlyphImpl(code, cmds, glyphId);
- cmds.push({ cmd: 'restore' });
- return cmds;
- }
- }, {
- key: 'compileGlyphImpl',
- value: function compileGlyphImpl() {
- (0, _util.unreachable)('Children classes should implement this.');
- }
- }, {
- key: 'hasBuiltPath',
- value: function hasBuiltPath(unicode) {
- var cmap = lookupCmap(this.cmap, unicode);
- return this.compiledGlyphs[cmap.glyphId] !== undefined && this.compiledCharCodeToGlyphId[cmap.charCode] !== undefined;
- }
- }]);
-
- return CompiledFont;
- }();
-
- var TrueTypeCompiled = function (_CompiledFont) {
- _inherits(TrueTypeCompiled, _CompiledFont);
-
- function TrueTypeCompiled(glyphs, cmap, fontMatrix) {
- _classCallCheck(this, TrueTypeCompiled);
-
- var _this = _possibleConstructorReturn(this, (TrueTypeCompiled.__proto__ || Object.getPrototypeOf(TrueTypeCompiled)).call(this, fontMatrix || [0.000488, 0, 0, 0.000488, 0, 0]));
-
- _this.glyphs = glyphs;
- _this.cmap = cmap;
- return _this;
- }
-
- _createClass(TrueTypeCompiled, [{
- key: 'compileGlyphImpl',
- value: function compileGlyphImpl(code, cmds) {
- compileGlyf(code, cmds, this);
- }
- }]);
-
- return TrueTypeCompiled;
- }(CompiledFont);
-
- var Type2Compiled = function (_CompiledFont2) {
- _inherits(Type2Compiled, _CompiledFont2);
-
- function Type2Compiled(cffInfo, cmap, fontMatrix, glyphNameMap) {
- _classCallCheck(this, Type2Compiled);
-
- var _this2 = _possibleConstructorReturn(this, (Type2Compiled.__proto__ || Object.getPrototypeOf(Type2Compiled)).call(this, fontMatrix || [0.001, 0, 0, 0.001, 0, 0]));
-
- _this2.glyphs = cffInfo.glyphs;
- _this2.gsubrs = cffInfo.gsubrs || [];
- _this2.subrs = cffInfo.subrs || [];
- _this2.cmap = cmap;
- _this2.glyphNameMap = glyphNameMap || (0, _glyphlist.getGlyphsUnicode)();
- _this2.gsubrsBias = _this2.gsubrs.length < 1240 ? 107 : _this2.gsubrs.length < 33900 ? 1131 : 32768;
- _this2.subrsBias = _this2.subrs.length < 1240 ? 107 : _this2.subrs.length < 33900 ? 1131 : 32768;
- _this2.isCFFCIDFont = cffInfo.isCFFCIDFont;
- _this2.fdSelect = cffInfo.fdSelect;
- _this2.fdArray = cffInfo.fdArray;
- return _this2;
- }
-
- _createClass(Type2Compiled, [{
- key: 'compileGlyphImpl',
- value: function compileGlyphImpl(code, cmds, glyphId) {
- compileCharString(code, cmds, this, glyphId);
- }
- }]);
-
- return Type2Compiled;
- }(CompiledFont);
-
- return {
- create: function FontRendererFactory_create(font, seacAnalysisEnabled) {
- var data = new Uint8Array(font.data);
- var cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm;
- var numTables = getUshort(data, 4);
- for (var i = 0, p = 12; i < numTables; i++, p += 16) {
- var tag = (0, _util.bytesToString)(data.subarray(p, p + 4));
- var offset = getLong(data, p + 8);
- var length = getLong(data, p + 12);
- switch (tag) {
- case 'cmap':
- cmap = parseCmap(data, offset, offset + length);
- break;
- case 'glyf':
- glyf = data.subarray(offset, offset + length);
- break;
- case 'loca':
- loca = data.subarray(offset, offset + length);
- break;
- case 'head':
- unitsPerEm = getUshort(data, offset + 18);
- indexToLocFormat = getUshort(data, offset + 50);
- break;
- case 'CFF ':
- cff = parseCff(data, offset, offset + length, seacAnalysisEnabled);
- break;
- }
- }
- if (glyf) {
- var fontMatrix = !unitsPerEm ? font.fontMatrix : [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0];
- return new TrueTypeCompiled(parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix);
- }
- return new Type2Compiled(cff, cmap, font.fontMatrix, font.glyphNameMap);
- }
- };
-}();
-exports.FontRendererFactory = FontRendererFactory;
-
-/***/ }),
-/* 164 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.Type1Parser = undefined;
-
-var _util = __w_pdfjs_require__(2);
-
-var _encodings = __w_pdfjs_require__(159);
-
-var _stream = __w_pdfjs_require__(140);
-
-var HINTING_ENABLED = false;
-var Type1CharString = function Type1CharStringClosure() {
- var COMMAND_MAP = {
- 'hstem': [1],
- 'vstem': [3],
- 'vmoveto': [4],
- 'rlineto': [5],
- 'hlineto': [6],
- 'vlineto': [7],
- 'rrcurveto': [8],
- 'callsubr': [10],
- 'flex': [12, 35],
- 'drop': [12, 18],
- 'endchar': [14],
- 'rmoveto': [21],
- 'hmoveto': [22],
- 'vhcurveto': [30],
- 'hvcurveto': [31]
- };
- function Type1CharString() {
- this.width = 0;
- this.lsb = 0;
- this.flexing = false;
- this.output = [];
- this.stack = [];
- }
- Type1CharString.prototype = {
- convert: function Type1CharString_convert(encoded, subrs, seacAnalysisEnabled) {
- var count = encoded.length;
- var error = false;
- var wx, sbx, subrNumber;
- for (var i = 0; i < count; i++) {
- var value = encoded[i];
- if (value < 32) {
- if (value === 12) {
- value = (value << 8) + encoded[++i];
- }
- switch (value) {
- case 1:
- if (!HINTING_ENABLED) {
- this.stack = [];
- break;
- }
- error = this.executeCommand(2, COMMAND_MAP.hstem);
- break;
- case 3:
- if (!HINTING_ENABLED) {
- this.stack = [];
- break;
- }
- error = this.executeCommand(2, COMMAND_MAP.vstem);
- break;
- case 4:
- if (this.flexing) {
- if (this.stack.length < 1) {
- error = true;
- break;
- }
- var dy = this.stack.pop();
- this.stack.push(0, dy);
- break;
- }
- error = this.executeCommand(1, COMMAND_MAP.vmoveto);
- break;
- case 5:
- error = this.executeCommand(2, COMMAND_MAP.rlineto);
- break;
- case 6:
- error = this.executeCommand(1, COMMAND_MAP.hlineto);
- break;
- case 7:
- error = this.executeCommand(1, COMMAND_MAP.vlineto);
- break;
- case 8:
- error = this.executeCommand(6, COMMAND_MAP.rrcurveto);
- break;
- case 9:
- this.stack = [];
- break;
- case 10:
- if (this.stack.length < 1) {
- error = true;
- break;
- }
- subrNumber = this.stack.pop();
- if (!subrs[subrNumber]) {
- error = true;
- break;
- }
- error = this.convert(subrs[subrNumber], subrs, seacAnalysisEnabled);
- break;
- case 11:
- return error;
- case 13:
- if (this.stack.length < 2) {
- error = true;
- break;
- }
- wx = this.stack.pop();
- sbx = this.stack.pop();
- this.lsb = sbx;
- this.width = wx;
- this.stack.push(wx, sbx);
- error = this.executeCommand(2, COMMAND_MAP.hmoveto);
- break;
- case 14:
- this.output.push(COMMAND_MAP.endchar[0]);
- break;
- case 21:
- if (this.flexing) {
- break;
- }
- error = this.executeCommand(2, COMMAND_MAP.rmoveto);
- break;
- case 22:
- if (this.flexing) {
- this.stack.push(0);
- break;
- }
- error = this.executeCommand(1, COMMAND_MAP.hmoveto);
- break;
- case 30:
- error = this.executeCommand(4, COMMAND_MAP.vhcurveto);
- break;
- case 31:
- error = this.executeCommand(4, COMMAND_MAP.hvcurveto);
- break;
- case (12 << 8) + 0:
- this.stack = [];
- break;
- case (12 << 8) + 1:
- if (!HINTING_ENABLED) {
- this.stack = [];
- break;
- }
- error = this.executeCommand(2, COMMAND_MAP.vstem);
- break;
- case (12 << 8) + 2:
- if (!HINTING_ENABLED) {
- this.stack = [];
- break;
- }
- error = this.executeCommand(2, COMMAND_MAP.hstem);
- break;
- case (12 << 8) + 6:
- if (seacAnalysisEnabled) {
- this.seac = this.stack.splice(-4, 4);
- error = this.executeCommand(0, COMMAND_MAP.endchar);
- } else {
- error = this.executeCommand(4, COMMAND_MAP.endchar);
- }
- break;
- case (12 << 8) + 7:
- if (this.stack.length < 4) {
- error = true;
- break;
- }
- this.stack.pop();
- wx = this.stack.pop();
- var sby = this.stack.pop();
- sbx = this.stack.pop();
- this.lsb = sbx;
- this.width = wx;
- this.stack.push(wx, sbx, sby);
- error = this.executeCommand(3, COMMAND_MAP.rmoveto);
- break;
- case (12 << 8) + 12:
- if (this.stack.length < 2) {
- error = true;
- break;
- }
- var num2 = this.stack.pop();
- var num1 = this.stack.pop();
- this.stack.push(num1 / num2);
- break;
- case (12 << 8) + 16:
- if (this.stack.length < 2) {
- error = true;
- break;
- }
- subrNumber = this.stack.pop();
- var numArgs = this.stack.pop();
- if (subrNumber === 0 && numArgs === 3) {
- var flexArgs = this.stack.splice(this.stack.length - 17, 17);
- this.stack.push(flexArgs[2] + flexArgs[0], flexArgs[3] + flexArgs[1], flexArgs[4], flexArgs[5], flexArgs[6], flexArgs[7], flexArgs[8], flexArgs[9], flexArgs[10], flexArgs[11], flexArgs[12], flexArgs[13], flexArgs[14]);
- error = this.executeCommand(13, COMMAND_MAP.flex, true);
- this.flexing = false;
- this.stack.push(flexArgs[15], flexArgs[16]);
- } else if (subrNumber === 1 && numArgs === 0) {
- this.flexing = true;
- }
- break;
- case (12 << 8) + 17:
- break;
- case (12 << 8) + 33:
- this.stack = [];
- break;
- default:
- (0, _util.warn)('Unknown type 1 charstring command of "' + value + '"');
- break;
- }
- if (error) {
- break;
- }
- continue;
- } else if (value <= 246) {
- value = value - 139;
- } else if (value <= 250) {
- value = (value - 247) * 256 + encoded[++i] + 108;
- } else if (value <= 254) {
- value = -((value - 251) * 256) - encoded[++i] - 108;
- } else {
- value = (encoded[++i] & 0xff) << 24 | (encoded[++i] & 0xff) << 16 | (encoded[++i] & 0xff) << 8 | (encoded[++i] & 0xff) << 0;
- }
- this.stack.push(value);
- }
- return error;
- },
- executeCommand: function executeCommand(howManyArgs, command, keepStack) {
- var stackLength = this.stack.length;
- if (howManyArgs > stackLength) {
- return true;
- }
- var start = stackLength - howManyArgs;
- for (var i = start; i < stackLength; i++) {
- var value = this.stack[i];
- if (Number.isInteger(value)) {
- this.output.push(28, value >> 8 & 0xff, value & 0xff);
- } else {
- value = 65536 * value | 0;
- this.output.push(255, value >> 24 & 0xFF, value >> 16 & 0xFF, value >> 8 & 0xFF, value & 0xFF);
- }
- }
- this.output.push.apply(this.output, command);
- if (keepStack) {
- this.stack.splice(start, howManyArgs);
- } else {
- this.stack.length = 0;
- }
- return false;
- }
- };
- return Type1CharString;
-}();
-var Type1Parser = function Type1ParserClosure() {
- var EEXEC_ENCRYPT_KEY = 55665;
- var CHAR_STRS_ENCRYPT_KEY = 4330;
- function isHexDigit(code) {
- return code >= 48 && code <= 57 || code >= 65 && code <= 70 || code >= 97 && code <= 102;
- }
- function decrypt(data, key, discardNumber) {
- if (discardNumber >= data.length) {
- return new Uint8Array(0);
- }
- var r = key | 0,
- c1 = 52845,
- c2 = 22719,
- i,
- j;
- for (i = 0; i < discardNumber; i++) {
- r = (data[i] + r) * c1 + c2 & (1 << 16) - 1;
- }
- var count = data.length - discardNumber;
- var decrypted = new Uint8Array(count);
- for (i = discardNumber, j = 0; j < count; i++, j++) {
- var value = data[i];
- decrypted[j] = value ^ r >> 8;
- r = (value + r) * c1 + c2 & (1 << 16) - 1;
- }
- return decrypted;
- }
- function decryptAscii(data, key, discardNumber) {
- var r = key | 0,
- c1 = 52845,
- c2 = 22719;
- var count = data.length,
- maybeLength = count >>> 1;
- var decrypted = new Uint8Array(maybeLength);
- var i, j;
- for (i = 0, j = 0; i < count; i++) {
- var digit1 = data[i];
- if (!isHexDigit(digit1)) {
- continue;
- }
- i++;
- var digit2;
- while (i < count && !isHexDigit(digit2 = data[i])) {
- i++;
- }
- if (i < count) {
- var value = parseInt(String.fromCharCode(digit1, digit2), 16);
- decrypted[j++] = value ^ r >> 8;
- r = (value + r) * c1 + c2 & (1 << 16) - 1;
- }
- }
- return Array.prototype.slice.call(decrypted, discardNumber, j);
- }
- function isSpecial(c) {
- return c === 0x2F || c === 0x5B || c === 0x5D || c === 0x7B || c === 0x7D || c === 0x28 || c === 0x29;
- }
- function Type1Parser(stream, encrypted, seacAnalysisEnabled) {
- if (encrypted) {
- var data = stream.getBytes();
- var isBinary = !(isHexDigit(data[0]) && isHexDigit(data[1]) && isHexDigit(data[2]) && isHexDigit(data[3]));
- stream = new _stream.Stream(isBinary ? decrypt(data, EEXEC_ENCRYPT_KEY, 4) : decryptAscii(data, EEXEC_ENCRYPT_KEY, 4));
- }
- this.seacAnalysisEnabled = !!seacAnalysisEnabled;
- this.stream = stream;
- this.nextChar();
- }
- Type1Parser.prototype = {
- readNumberArray: function Type1Parser_readNumberArray() {
- this.getToken();
- var array = [];
- while (true) {
- var token = this.getToken();
- if (token === null || token === ']' || token === '}') {
- break;
- }
- array.push(parseFloat(token || 0));
- }
- return array;
- },
- readNumber: function Type1Parser_readNumber() {
- var token = this.getToken();
- return parseFloat(token || 0);
- },
- readInt: function Type1Parser_readInt() {
- var token = this.getToken();
- return parseInt(token || 0, 10) | 0;
- },
- readBoolean: function Type1Parser_readBoolean() {
- var token = this.getToken();
- return token === 'true' ? 1 : 0;
- },
- nextChar: function Type1_nextChar() {
- return this.currentChar = this.stream.getByte();
- },
- getToken: function Type1Parser_getToken() {
- var comment = false;
- var ch = this.currentChar;
- while (true) {
- if (ch === -1) {
- return null;
- }
- if (comment) {
- if (ch === 0x0A || ch === 0x0D) {
- comment = false;
- }
- } else if (ch === 0x25) {
- comment = true;
- } else if (!(0, _util.isSpace)(ch)) {
- break;
- }
- ch = this.nextChar();
- }
- if (isSpecial(ch)) {
- this.nextChar();
- return String.fromCharCode(ch);
- }
- var token = '';
- do {
- token += String.fromCharCode(ch);
- ch = this.nextChar();
- } while (ch >= 0 && !(0, _util.isSpace)(ch) && !isSpecial(ch));
- return token;
- },
- readCharStrings: function Type1Parser_readCharStrings(bytes, lenIV) {
- if (lenIV === -1) {
- return bytes;
- }
- return decrypt(bytes, CHAR_STRS_ENCRYPT_KEY, lenIV);
- },
- extractFontProgram: function Type1Parser_extractFontProgram() {
- var stream = this.stream;
- var subrs = [],
- charstrings = [];
- var privateData = Object.create(null);
- privateData['lenIV'] = 4;
- var program = {
- subrs: [],
- charstrings: [],
- properties: { 'privateData': privateData }
- };
- var token, length, data, lenIV, encoded;
- while ((token = this.getToken()) !== null) {
- if (token !== '/') {
- continue;
- }
- token = this.getToken();
- switch (token) {
- case 'CharStrings':
- this.getToken();
- this.getToken();
- this.getToken();
- this.getToken();
- while (true) {
- token = this.getToken();
- if (token === null || token === 'end') {
- break;
- }
- if (token !== '/') {
- continue;
- }
- var glyph = this.getToken();
- length = this.readInt();
- this.getToken();
- data = length > 0 ? stream.getBytes(length) : new Uint8Array(0);
- lenIV = program.properties.privateData['lenIV'];
- encoded = this.readCharStrings(data, lenIV);
- this.nextChar();
- token = this.getToken();
- if (token === 'noaccess') {
- this.getToken();
- }
- charstrings.push({
- glyph: glyph,
- encoded: encoded
- });
- }
- break;
- case 'Subrs':
- this.readInt();
- this.getToken();
- while (this.getToken() === 'dup') {
- var index = this.readInt();
- length = this.readInt();
- this.getToken();
- data = length > 0 ? stream.getBytes(length) : new Uint8Array(0);
- lenIV = program.properties.privateData['lenIV'];
- encoded = this.readCharStrings(data, lenIV);
- this.nextChar();
- token = this.getToken();
- if (token === 'noaccess') {
- this.getToken();
- }
- subrs[index] = encoded;
- }
- break;
- case 'BlueValues':
- case 'OtherBlues':
- case 'FamilyBlues':
- case 'FamilyOtherBlues':
- var blueArray = this.readNumberArray();
- if (blueArray.length > 0 && blueArray.length % 2 === 0 && HINTING_ENABLED) {
- program.properties.privateData[token] = blueArray;
- }
- break;
- case 'StemSnapH':
- case 'StemSnapV':
- program.properties.privateData[token] = this.readNumberArray();
- break;
- case 'StdHW':
- case 'StdVW':
- program.properties.privateData[token] = this.readNumberArray()[0];
- break;
- case 'BlueShift':
- case 'lenIV':
- case 'BlueFuzz':
- case 'BlueScale':
- case 'LanguageGroup':
- case 'ExpansionFactor':
- program.properties.privateData[token] = this.readNumber();
- break;
- case 'ForceBold':
- program.properties.privateData[token] = this.readBoolean();
- break;
- }
- }
- for (var i = 0; i < charstrings.length; i++) {
- glyph = charstrings[i].glyph;
- encoded = charstrings[i].encoded;
- var charString = new Type1CharString();
- var error = charString.convert(encoded, subrs, this.seacAnalysisEnabled);
- var output = charString.output;
- if (error) {
- output = [14];
- }
- program.charstrings.push({
- glyphName: glyph,
- charstring: output,
- width: charString.width,
- lsb: charString.lsb,
- seac: charString.seac
- });
- }
- return program;
- },
- extractFontHeader: function Type1Parser_extractFontHeader(properties) {
- var token;
- while ((token = this.getToken()) !== null) {
- if (token !== '/') {
- continue;
- }
- token = this.getToken();
- switch (token) {
- case 'FontMatrix':
- var matrix = this.readNumberArray();
- properties.fontMatrix = matrix;
- break;
- case 'Encoding':
- var encodingArg = this.getToken();
- var encoding;
- if (!/^\d+$/.test(encodingArg)) {
- encoding = (0, _encodings.getEncoding)(encodingArg);
- } else {
- encoding = [];
- var size = parseInt(encodingArg, 10) | 0;
- this.getToken();
- for (var j = 0; j < size; j++) {
- token = this.getToken();
- while (token !== 'dup' && token !== 'def') {
- token = this.getToken();
- if (token === null) {
- return;
- }
- }
- if (token === 'def') {
- break;
- }
- var index = this.readInt();
- this.getToken();
- var glyph = this.getToken();
- encoding[index] = glyph;
- this.getToken();
- }
- }
- properties.builtInEncoding = encoding;
- break;
- case 'FontBBox':
- var fontBBox = this.readNumberArray();
- properties.ascent = Math.max(fontBBox[3], fontBBox[1]);
- properties.descent = Math.min(fontBBox[1], fontBBox[3]);
- properties.ascentScaled = true;
- break;
- }
- }
- }
- };
- return Type1Parser;
-}();
-exports.Type1Parser = Type1Parser;
-
-/***/ }),
-/* 165 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.getTilingPatternIR = exports.Pattern = undefined;
-
-var _util = __w_pdfjs_require__(2);
-
-var _colorspace = __w_pdfjs_require__(151);
-
-var _primitives = __w_pdfjs_require__(138);
-
-var ShadingType = {
- FUNCTION_BASED: 1,
- AXIAL: 2,
- RADIAL: 3,
- FREE_FORM_MESH: 4,
- LATTICE_FORM_MESH: 5,
- COONS_PATCH_MESH: 6,
- TENSOR_PATCH_MESH: 7
-};
-var Pattern = function PatternClosure() {
- function Pattern() {
- (0, _util.unreachable)('should not call Pattern constructor');
- }
- Pattern.prototype = {
- getPattern: function Pattern_getPattern(ctx) {
- (0, _util.unreachable)('Should not call Pattern.getStyle: ' + ctx);
- }
- };
- Pattern.parseShading = function (shading, matrix, xref, res, handler, pdfFunctionFactory) {
- var dict = (0, _primitives.isStream)(shading) ? shading.dict : shading;
- var type = dict.get('ShadingType');
- try {
- switch (type) {
- case ShadingType.AXIAL:
- case ShadingType.RADIAL:
- return new Shadings.RadialAxial(dict, matrix, xref, res, pdfFunctionFactory);
- case ShadingType.FREE_FORM_MESH:
- case ShadingType.LATTICE_FORM_MESH:
- case ShadingType.COONS_PATCH_MESH:
- case ShadingType.TENSOR_PATCH_MESH:
- return new Shadings.Mesh(shading, matrix, xref, res, pdfFunctionFactory);
- default:
- throw new _util.FormatError('Unsupported ShadingType: ' + type);
- }
- } catch (ex) {
- if (ex instanceof _util.MissingDataException) {
- throw ex;
- }
- handler.send('UnsupportedFeature', { featureId: _util.UNSUPPORTED_FEATURES.shadingPattern });
- (0, _util.warn)(ex);
- return new Shadings.Dummy();
- }
- };
- return Pattern;
-}();
-var Shadings = {};
-Shadings.SMALL_NUMBER = 1e-6;
-Shadings.RadialAxial = function RadialAxialClosure() {
- function RadialAxial(dict, matrix, xref, res, pdfFunctionFactory) {
- this.matrix = matrix;
- this.coordsArr = dict.getArray('Coords');
- this.shadingType = dict.get('ShadingType');
- this.type = 'Pattern';
- var cs = dict.get('ColorSpace', 'CS');
- cs = _colorspace.ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
- this.cs = cs;
- var t0 = 0.0,
- t1 = 1.0;
- if (dict.has('Domain')) {
- var domainArr = dict.getArray('Domain');
- t0 = domainArr[0];
- t1 = domainArr[1];
- }
- var extendStart = false,
- extendEnd = false;
- if (dict.has('Extend')) {
- var extendArr = dict.getArray('Extend');
- extendStart = extendArr[0];
- extendEnd = extendArr[1];
- }
- if (this.shadingType === ShadingType.RADIAL && (!extendStart || !extendEnd)) {
- var x1 = this.coordsArr[0];
- var y1 = this.coordsArr[1];
- var r1 = this.coordsArr[2];
- var x2 = this.coordsArr[3];
- var y2 = this.coordsArr[4];
- var r2 = this.coordsArr[5];
- var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
- if (r1 <= r2 + distance && r2 <= r1 + distance) {
- (0, _util.warn)('Unsupported radial gradient.');
- }
- }
- this.extendStart = extendStart;
- this.extendEnd = extendEnd;
- var fnObj = dict.get('Function');
- var fn = pdfFunctionFactory.createFromArray(fnObj);
- var diff = t1 - t0;
- var step = diff / 10;
- var colorStops = this.colorStops = [];
- if (t0 >= t1 || step <= 0) {
- (0, _util.info)('Bad shading domain.');
- return;
- }
- var color = new Float32Array(cs.numComps),
- ratio = new Float32Array(1);
- var rgbColor;
- for (var i = t0; i <= t1; i += step) {
- ratio[0] = i;
- fn(ratio, 0, color, 0);
- rgbColor = cs.getRgb(color, 0);
- var cssColor = _util.Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
- colorStops.push([(i - t0) / diff, cssColor]);
- }
- var background = 'transparent';
- if (dict.has('Background')) {
- rgbColor = cs.getRgb(dict.get('Background'), 0);
- background = _util.Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
- }
- if (!extendStart) {
- colorStops.unshift([0, background]);
- colorStops[1][0] += Shadings.SMALL_NUMBER;
- }
- if (!extendEnd) {
- colorStops[colorStops.length - 1][0] -= Shadings.SMALL_NUMBER;
- colorStops.push([1, background]);
- }
- this.colorStops = colorStops;
- }
- RadialAxial.prototype = {
- getIR: function RadialAxial_getIR() {
- var coordsArr = this.coordsArr;
- var shadingType = this.shadingType;
- var type, p0, p1, r0, r1;
- if (shadingType === ShadingType.AXIAL) {
- p0 = [coordsArr[0], coordsArr[1]];
- p1 = [coordsArr[2], coordsArr[3]];
- r0 = null;
- r1 = null;
- type = 'axial';
- } else if (shadingType === ShadingType.RADIAL) {
- p0 = [coordsArr[0], coordsArr[1]];
- p1 = [coordsArr[3], coordsArr[4]];
- r0 = coordsArr[2];
- r1 = coordsArr[5];
- type = 'radial';
- } else {
- (0, _util.unreachable)('getPattern type unknown: ' + shadingType);
- }
- var matrix = this.matrix;
- if (matrix) {
- p0 = _util.Util.applyTransform(p0, matrix);
- p1 = _util.Util.applyTransform(p1, matrix);
- if (shadingType === ShadingType.RADIAL) {
- var scale = _util.Util.singularValueDecompose2dScale(matrix);
- r0 *= scale[0];
- r1 *= scale[1];
- }
- }
- return ['RadialAxial', type, this.colorStops, p0, p1, r0, r1];
- }
- };
- return RadialAxial;
-}();
-Shadings.Mesh = function MeshClosure() {
- function MeshStreamReader(stream, context) {
- this.stream = stream;
- this.context = context;
- this.buffer = 0;
- this.bufferLength = 0;
- var numComps = context.numComps;
- this.tmpCompsBuf = new Float32Array(numComps);
- var csNumComps = context.colorSpace.numComps;
- this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf;
- }
- MeshStreamReader.prototype = {
- get hasData() {
- if (this.stream.end) {
- return this.stream.pos < this.stream.end;
- }
- if (this.bufferLength > 0) {
- return true;
- }
- var nextByte = this.stream.getByte();
- if (nextByte < 0) {
- return false;
- }
- this.buffer = nextByte;
- this.bufferLength = 8;
- return true;
- },
- readBits: function MeshStreamReader_readBits(n) {
- var buffer = this.buffer;
- var bufferLength = this.bufferLength;
- if (n === 32) {
- if (bufferLength === 0) {
- return (this.stream.getByte() << 24 | this.stream.getByte() << 16 | this.stream.getByte() << 8 | this.stream.getByte()) >>> 0;
- }
- buffer = buffer << 24 | this.stream.getByte() << 16 | this.stream.getByte() << 8 | this.stream.getByte();
- var nextByte = this.stream.getByte();
- this.buffer = nextByte & (1 << bufferLength) - 1;
- return (buffer << 8 - bufferLength | (nextByte & 0xFF) >> bufferLength) >>> 0;
- }
- if (n === 8 && bufferLength === 0) {
- return this.stream.getByte();
- }
- while (bufferLength < n) {
- buffer = buffer << 8 | this.stream.getByte();
- bufferLength += 8;
- }
- bufferLength -= n;
- this.bufferLength = bufferLength;
- this.buffer = buffer & (1 << bufferLength) - 1;
- return buffer >> bufferLength;
- },
- align: function MeshStreamReader_align() {
- this.buffer = 0;
- this.bufferLength = 0;
- },
- readFlag: function MeshStreamReader_readFlag() {
- return this.readBits(this.context.bitsPerFlag);
- },
- readCoordinate: function MeshStreamReader_readCoordinate() {
- var bitsPerCoordinate = this.context.bitsPerCoordinate;
- var xi = this.readBits(bitsPerCoordinate);
- var yi = this.readBits(bitsPerCoordinate);
- var decode = this.context.decode;
- var scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 2.3283064365386963e-10;
- return [xi * scale * (decode[1] - decode[0]) + decode[0], yi * scale * (decode[3] - decode[2]) + decode[2]];
- },
- readComponents: function MeshStreamReader_readComponents() {
- var numComps = this.context.numComps;
- var bitsPerComponent = this.context.bitsPerComponent;
- var scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 2.3283064365386963e-10;
- var decode = this.context.decode;
- var components = this.tmpCompsBuf;
- for (var i = 0, j = 4; i < numComps; i++, j += 2) {
- var ci = this.readBits(bitsPerComponent);
- components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j];
- }
- var color = this.tmpCsCompsBuf;
- if (this.context.colorFn) {
- this.context.colorFn(components, 0, color, 0);
- }
- return this.context.colorSpace.getRgb(color, 0);
- }
- };
- function decodeType4Shading(mesh, reader) {
- var coords = mesh.coords;
- var colors = mesh.colors;
- var operators = [];
- var ps = [];
- var verticesLeft = 0;
- while (reader.hasData) {
- var f = reader.readFlag();
- var coord = reader.readCoordinate();
- var color = reader.readComponents();
- if (verticesLeft === 0) {
- if (!(0 <= f && f <= 2)) {
- throw new _util.FormatError('Unknown type4 flag');
- }
- switch (f) {
- case 0:
- verticesLeft = 3;
- break;
- case 1:
- ps.push(ps[ps.length - 2], ps[ps.length - 1]);
- verticesLeft = 1;
- break;
- case 2:
- ps.push(ps[ps.length - 3], ps[ps.length - 1]);
- verticesLeft = 1;
- break;
- }
- operators.push(f);
- }
- ps.push(coords.length);
- coords.push(coord);
- colors.push(color);
- verticesLeft--;
- reader.align();
- }
- mesh.figures.push({
- type: 'triangles',
- coords: new Int32Array(ps),
- colors: new Int32Array(ps)
- });
- }
- function decodeType5Shading(mesh, reader, verticesPerRow) {
- var coords = mesh.coords;
- var colors = mesh.colors;
- var ps = [];
- while (reader.hasData) {
- var coord = reader.readCoordinate();
- var color = reader.readComponents();
- ps.push(coords.length);
- coords.push(coord);
- colors.push(color);
- }
- mesh.figures.push({
- type: 'lattice',
- coords: new Int32Array(ps),
- colors: new Int32Array(ps),
- verticesPerRow: verticesPerRow
- });
- }
- var MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;
- var MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;
- var TRIANGLE_DENSITY = 20;
- var getB = function getBClosure() {
- function buildB(count) {
- var lut = [];
- for (var i = 0; i <= count; i++) {
- var t = i / count,
- t_ = 1 - t;
- lut.push(new Float32Array([t_ * t_ * t_, 3 * t * t_ * t_, 3 * t * t * t_, t * t * t]));
- }
- return lut;
- }
- var cache = [];
- return function getB(count) {
- if (!cache[count]) {
- cache[count] = buildB(count);
- }
- return cache[count];
- };
- }();
- function buildFigureFromPatch(mesh, index) {
- var figure = mesh.figures[index];
- (0, _util.assert)(figure.type === 'patch', 'Unexpected patch mesh figure');
- var coords = mesh.coords,
- colors = mesh.colors;
- var pi = figure.coords;
- var ci = figure.colors;
- var figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]);
- var figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]);
- var figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]);
- var figureMaxY = Math.max(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]);
- var splitXBy = Math.ceil((figureMaxX - figureMinX) * TRIANGLE_DENSITY / (mesh.bounds[2] - mesh.bounds[0]));
- splitXBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitXBy));
- var splitYBy = Math.ceil((figureMaxY - figureMinY) * TRIANGLE_DENSITY / (mesh.bounds[3] - mesh.bounds[1]));
- splitYBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitYBy));
- var verticesPerRow = splitXBy + 1;
- var figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
- var figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
- var k = 0;
- var cl = new Uint8Array(3),
- cr = new Uint8Array(3);
- var c0 = colors[ci[0]],
- c1 = colors[ci[1]],
- c2 = colors[ci[2]],
- c3 = colors[ci[3]];
- var bRow = getB(splitYBy),
- bCol = getB(splitXBy);
- for (var row = 0; row <= splitYBy; row++) {
- cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0;
- cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0;
- cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0;
- cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0;
- cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0;
- cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0;
- for (var col = 0; col <= splitXBy; col++, k++) {
- if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) {
- continue;
- }
- var x = 0,
- y = 0;
- var q = 0;
- for (var i = 0; i <= 3; i++) {
- for (var j = 0; j <= 3; j++, q++) {
- var m = bRow[row][i] * bCol[col][j];
- x += coords[pi[q]][0] * m;
- y += coords[pi[q]][1] * m;
- }
- }
- figureCoords[k] = coords.length;
- coords.push([x, y]);
- figureColors[k] = colors.length;
- var newColor = new Uint8Array(3);
- newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0;
- newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0;
- newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0;
- colors.push(newColor);
- }
- }
- figureCoords[0] = pi[0];
- figureColors[0] = ci[0];
- figureCoords[splitXBy] = pi[3];
- figureColors[splitXBy] = ci[1];
- figureCoords[verticesPerRow * splitYBy] = pi[12];
- figureColors[verticesPerRow * splitYBy] = ci[2];
- figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15];
- figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
- mesh.figures[index] = {
- type: 'lattice',
- coords: figureCoords,
- colors: figureColors,
- verticesPerRow: verticesPerRow
- };
- }
- function decodeType6Shading(mesh, reader) {
- var coords = mesh.coords;
- var colors = mesh.colors;
- var ps = new Int32Array(16);
- var cs = new Int32Array(4);
- while (reader.hasData) {
- var f = reader.readFlag();
- if (!(0 <= f && f <= 3)) {
- throw new _util.FormatError('Unknown type6 flag');
- }
- var i, ii;
- var pi = coords.length;
- for (i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) {
- coords.push(reader.readCoordinate());
- }
- var ci = colors.length;
- for (i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
- colors.push(reader.readComponents());
- }
- var tmp1, tmp2, tmp3, tmp4;
- switch (f) {
- case 0:
- ps[12] = pi + 3;
- ps[13] = pi + 4;
- ps[14] = pi + 5;
- ps[15] = pi + 6;
- ps[8] = pi + 2;
- ps[11] = pi + 7;
- ps[4] = pi + 1;
- ps[7] = pi + 8;
- ps[0] = pi;
- ps[1] = pi + 11;
- ps[2] = pi + 10;
- ps[3] = pi + 9;
- cs[2] = ci + 1;
- cs[3] = ci + 2;
- cs[0] = ci;
- cs[1] = ci + 3;
- break;
- case 1:
- tmp1 = ps[12];
- tmp2 = ps[13];
- tmp3 = ps[14];
- tmp4 = ps[15];
- ps[12] = tmp4;
- ps[13] = pi + 0;
- ps[14] = pi + 1;
- ps[15] = pi + 2;
- ps[8] = tmp3;
- ps[11] = pi + 3;
- ps[4] = tmp2;
- ps[7] = pi + 4;
- ps[0] = tmp1;
- ps[1] = pi + 7;
- ps[2] = pi + 6;
- ps[3] = pi + 5;
- tmp1 = cs[2];
- tmp2 = cs[3];
- cs[2] = tmp2;
- cs[3] = ci;
- cs[0] = tmp1;
- cs[1] = ci + 1;
- break;
- case 2:
- tmp1 = ps[15];
- tmp2 = ps[11];
- ps[12] = ps[3];
- ps[13] = pi + 0;
- ps[14] = pi + 1;
- ps[15] = pi + 2;
- ps[8] = ps[7];
- ps[11] = pi + 3;
- ps[4] = tmp2;
- ps[7] = pi + 4;
- ps[0] = tmp1;
- ps[1] = pi + 7;
- ps[2] = pi + 6;
- ps[3] = pi + 5;
- tmp1 = cs[3];
- cs[2] = cs[1];
- cs[3] = ci;
- cs[0] = tmp1;
- cs[1] = ci + 1;
- break;
- case 3:
- ps[12] = ps[0];
- ps[13] = pi + 0;
- ps[14] = pi + 1;
- ps[15] = pi + 2;
- ps[8] = ps[1];
- ps[11] = pi + 3;
- ps[4] = ps[2];
- ps[7] = pi + 4;
- ps[0] = ps[3];
- ps[1] = pi + 7;
- ps[2] = pi + 6;
- ps[3] = pi + 5;
- cs[2] = cs[0];
- cs[3] = ci;
- cs[0] = cs[1];
- cs[1] = ci + 1;
- break;
- }
- ps[5] = coords.length;
- coords.push([(-4 * coords[ps[0]][0] - coords[ps[15]][0] + 6 * (coords[ps[4]][0] + coords[ps[1]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9, (-4 * coords[ps[0]][1] - coords[ps[15]][1] + 6 * (coords[ps[4]][1] + coords[ps[1]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9]);
- ps[6] = coords.length;
- coords.push([(-4 * coords[ps[3]][0] - coords[ps[12]][0] + 6 * (coords[ps[2]][0] + coords[ps[7]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9, (-4 * coords[ps[3]][1] - coords[ps[12]][1] + 6 * (coords[ps[2]][1] + coords[ps[7]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9]);
- ps[9] = coords.length;
- coords.push([(-4 * coords[ps[12]][0] - coords[ps[3]][0] + 6 * (coords[ps[8]][0] + coords[ps[13]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9, (-4 * coords[ps[12]][1] - coords[ps[3]][1] + 6 * (coords[ps[8]][1] + coords[ps[13]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9]);
- ps[10] = coords.length;
- coords.push([(-4 * coords[ps[15]][0] - coords[ps[0]][0] + 6 * (coords[ps[11]][0] + coords[ps[14]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9, (-4 * coords[ps[15]][1] - coords[ps[0]][1] + 6 * (coords[ps[11]][1] + coords[ps[14]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9]);
- mesh.figures.push({
- type: 'patch',
- coords: new Int32Array(ps),
- colors: new Int32Array(cs)
- });
- }
- }
- function decodeType7Shading(mesh, reader) {
- var coords = mesh.coords;
- var colors = mesh.colors;
- var ps = new Int32Array(16);
- var cs = new Int32Array(4);
- while (reader.hasData) {
- var f = reader.readFlag();
- if (!(0 <= f && f <= 3)) {
- throw new _util.FormatError('Unknown type7 flag');
- }
- var i, ii;
- var pi = coords.length;
- for (i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) {
- coords.push(reader.readCoordinate());
- }
- var ci = colors.length;
- for (i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
- colors.push(reader.readComponents());
- }
- var tmp1, tmp2, tmp3, tmp4;
- switch (f) {
- case 0:
- ps[12] = pi + 3;
- ps[13] = pi + 4;
- ps[14] = pi + 5;
- ps[15] = pi + 6;
- ps[8] = pi + 2;
- ps[9] = pi + 13;
- ps[10] = pi + 14;
- ps[11] = pi + 7;
- ps[4] = pi + 1;
- ps[5] = pi + 12;
- ps[6] = pi + 15;
- ps[7] = pi + 8;
- ps[0] = pi;
- ps[1] = pi + 11;
- ps[2] = pi + 10;
- ps[3] = pi + 9;
- cs[2] = ci + 1;
- cs[3] = ci + 2;
- cs[0] = ci;
- cs[1] = ci + 3;
- break;
- case 1:
- tmp1 = ps[12];
- tmp2 = ps[13];
- tmp3 = ps[14];
- tmp4 = ps[15];
- ps[12] = tmp4;
- ps[13] = pi + 0;
- ps[14] = pi + 1;
- ps[15] = pi + 2;
- ps[8] = tmp3;
- ps[9] = pi + 9;
- ps[10] = pi + 10;
- ps[11] = pi + 3;
- ps[4] = tmp2;
- ps[5] = pi + 8;
- ps[6] = pi + 11;
- ps[7] = pi + 4;
- ps[0] = tmp1;
- ps[1] = pi + 7;
- ps[2] = pi + 6;
- ps[3] = pi + 5;
- tmp1 = cs[2];
- tmp2 = cs[3];
- cs[2] = tmp2;
- cs[3] = ci;
- cs[0] = tmp1;
- cs[1] = ci + 1;
- break;
- case 2:
- tmp1 = ps[15];
- tmp2 = ps[11];
- ps[12] = ps[3];
- ps[13] = pi + 0;
- ps[14] = pi + 1;
- ps[15] = pi + 2;
- ps[8] = ps[7];
- ps[9] = pi + 9;
- ps[10] = pi + 10;
- ps[11] = pi + 3;
- ps[4] = tmp2;
- ps[5] = pi + 8;
- ps[6] = pi + 11;
- ps[7] = pi + 4;
- ps[0] = tmp1;
- ps[1] = pi + 7;
- ps[2] = pi + 6;
- ps[3] = pi + 5;
- tmp1 = cs[3];
- cs[2] = cs[1];
- cs[3] = ci;
- cs[0] = tmp1;
- cs[1] = ci + 1;
- break;
- case 3:
- ps[12] = ps[0];
- ps[13] = pi + 0;
- ps[14] = pi + 1;
- ps[15] = pi + 2;
- ps[8] = ps[1];
- ps[9] = pi + 9;
- ps[10] = pi + 10;
- ps[11] = pi + 3;
- ps[4] = ps[2];
- ps[5] = pi + 8;
- ps[6] = pi + 11;
- ps[7] = pi + 4;
- ps[0] = ps[3];
- ps[1] = pi + 7;
- ps[2] = pi + 6;
- ps[3] = pi + 5;
- cs[2] = cs[0];
- cs[3] = ci;
- cs[0] = cs[1];
- cs[1] = ci + 1;
- break;
- }
- mesh.figures.push({
- type: 'patch',
- coords: new Int32Array(ps),
- colors: new Int32Array(cs)
- });
- }
- }
- function updateBounds(mesh) {
- var minX = mesh.coords[0][0],
- minY = mesh.coords[0][1],
- maxX = minX,
- maxY = minY;
- for (var i = 1, ii = mesh.coords.length; i < ii; i++) {
- var x = mesh.coords[i][0],
- y = mesh.coords[i][1];
- minX = minX > x ? x : minX;
- minY = minY > y ? y : minY;
- maxX = maxX < x ? x : maxX;
- maxY = maxY < y ? y : maxY;
- }
- mesh.bounds = [minX, minY, maxX, maxY];
- }
- function packData(mesh) {
- var i, ii, j, jj;
- var coords = mesh.coords;
- var coordsPacked = new Float32Array(coords.length * 2);
- for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
- var xy = coords[i];
- coordsPacked[j++] = xy[0];
- coordsPacked[j++] = xy[1];
- }
- mesh.coords = coordsPacked;
- var colors = mesh.colors;
- var colorsPacked = new Uint8Array(colors.length * 3);
- for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
- var c = colors[i];
- colorsPacked[j++] = c[0];
- colorsPacked[j++] = c[1];
- colorsPacked[j++] = c[2];
- }
- mesh.colors = colorsPacked;
- var figures = mesh.figures;
- for (i = 0, ii = figures.length; i < ii; i++) {
- var figure = figures[i],
- ps = figure.coords,
- cs = figure.colors;
- for (j = 0, jj = ps.length; j < jj; j++) {
- ps[j] *= 2;
- cs[j] *= 3;
- }
- }
- }
- function Mesh(stream, matrix, xref, res, pdfFunctionFactory) {
- if (!(0, _primitives.isStream)(stream)) {
- throw new _util.FormatError('Mesh data is not a stream');
- }
- var dict = stream.dict;
- this.matrix = matrix;
- this.shadingType = dict.get('ShadingType');
- this.type = 'Pattern';
- this.bbox = dict.getArray('BBox');
- var cs = dict.get('ColorSpace', 'CS');
- cs = _colorspace.ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
- this.cs = cs;
- this.background = dict.has('Background') ? cs.getRgb(dict.get('Background'), 0) : null;
- var fnObj = dict.get('Function');
- var fn = fnObj ? pdfFunctionFactory.createFromArray(fnObj) : null;
- this.coords = [];
- this.colors = [];
- this.figures = [];
- var decodeContext = {
- bitsPerCoordinate: dict.get('BitsPerCoordinate'),
- bitsPerComponent: dict.get('BitsPerComponent'),
- bitsPerFlag: dict.get('BitsPerFlag'),
- decode: dict.getArray('Decode'),
- colorFn: fn,
- colorSpace: cs,
- numComps: fn ? 1 : cs.numComps
- };
- var reader = new MeshStreamReader(stream, decodeContext);
- var patchMesh = false;
- switch (this.shadingType) {
- case ShadingType.FREE_FORM_MESH:
- decodeType4Shading(this, reader);
- break;
- case ShadingType.LATTICE_FORM_MESH:
- var verticesPerRow = dict.get('VerticesPerRow') | 0;
- if (verticesPerRow < 2) {
- throw new _util.FormatError('Invalid VerticesPerRow');
- }
- decodeType5Shading(this, reader, verticesPerRow);
- break;
- case ShadingType.COONS_PATCH_MESH:
- decodeType6Shading(this, reader);
- patchMesh = true;
- break;
- case ShadingType.TENSOR_PATCH_MESH:
- decodeType7Shading(this, reader);
- patchMesh = true;
- break;
- default:
- (0, _util.unreachable)('Unsupported mesh type.');
- break;
- }
- if (patchMesh) {
- updateBounds(this);
- for (var i = 0, ii = this.figures.length; i < ii; i++) {
- buildFigureFromPatch(this, i);
- }
- }
- updateBounds(this);
- packData(this);
- }
- Mesh.prototype = {
- getIR: function Mesh_getIR() {
- return ['Mesh', this.shadingType, this.coords, this.colors, this.figures, this.bounds, this.matrix, this.bbox, this.background];
- }
- };
- return Mesh;
-}();
-Shadings.Dummy = function DummyClosure() {
- function Dummy() {
- this.type = 'Pattern';
- }
- Dummy.prototype = {
- getIR: function Dummy_getIR() {
- return ['Dummy'];
- }
- };
- return Dummy;
-}();
-function getTilingPatternIR(operatorList, dict, args) {
- var matrix = dict.getArray('Matrix');
- var bbox = _util.Util.normalizeRect(dict.getArray('BBox'));
- var xstep = dict.get('XStep');
- var ystep = dict.get('YStep');
- var paintType = dict.get('PaintType');
- var tilingType = dict.get('TilingType');
- if (bbox[2] - bbox[0] === 0 || bbox[3] - bbox[1] === 0) {
- throw new _util.FormatError('Invalid getTilingPatternIR /BBox array: [' + bbox + '].');
- }
- return ['TilingPattern', args, operatorList, matrix, bbox, xstep, ystep, paintType, tilingType];
-}
-exports.Pattern = Pattern;
-exports.getTilingPatternIR = getTilingPatternIR;
-
-/***/ }),
-/* 166 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.bidi = undefined;
-
-var _util = __w_pdfjs_require__(2);
-
-var baseTypes = ['BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'S', 'B', 'S', 'WS', 'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'B', 'B', 'B', 'S', 'WS', 'ON', 'ON', 'ET', 'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'ON', 'ES', 'CS', 'ES', 'CS', 'CS', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'CS', 'ON', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'ON', 'ON', 'ON', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'CS', 'ON', 'ET', 'ET', 'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'L', 'ON', 'ON', 'BN', 'ON', 'ON', 'ET', 'ET', 'EN', 'EN', 'ON', 'L', 'ON', 'ON', 'ON', 'EN', 'L', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L'];
-var arabicTypes = ['AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'ON', 'ON', 'AL', 'ET', 'ET', 'AL', 'CS', 'AL', 'ON', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', '', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'ET', 'AN', 'AN', 'AL', 'AL', 'AL', 'NSM', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AN', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'NSM', 'NSM', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL'];
-function isOdd(i) {
- return (i & 1) !== 0;
-}
-function isEven(i) {
- return (i & 1) === 0;
-}
-function findUnequal(arr, start, value) {
- for (var j = start, jj = arr.length; j < jj; ++j) {
- if (arr[j] !== value) {
- return j;
- }
- }
- return j;
-}
-function setValues(arr, start, end, value) {
- for (var j = start; j < end; ++j) {
- arr[j] = value;
- }
-}
-function reverseValues(arr, start, end) {
- for (var i = start, j = end - 1; i < j; ++i, --j) {
- var temp = arr[i];
- arr[i] = arr[j];
- arr[j] = temp;
- }
-}
-function createBidiText(str, isLTR, vertical) {
- return {
- str: str,
- dir: vertical ? 'ttb' : isLTR ? 'ltr' : 'rtl'
- };
-}
-var chars = [];
-var types = [];
-function bidi(str, startLevel, vertical) {
- var isLTR = true;
- var strLength = str.length;
- if (strLength === 0 || vertical) {
- return createBidiText(str, isLTR, vertical);
- }
- chars.length = strLength;
- types.length = strLength;
- var numBidi = 0;
- var i, ii;
- for (i = 0; i < strLength; ++i) {
- chars[i] = str.charAt(i);
- var charCode = str.charCodeAt(i);
- var charType = 'L';
- if (charCode <= 0x00ff) {
- charType = baseTypes[charCode];
- } else if (0x0590 <= charCode && charCode <= 0x05f4) {
- charType = 'R';
- } else if (0x0600 <= charCode && charCode <= 0x06ff) {
- charType = arabicTypes[charCode & 0xff];
- if (!charType) {
- (0, _util.warn)('Bidi: invalid Unicode character ' + charCode.toString(16));
- }
- } else if (0x0700 <= charCode && charCode <= 0x08AC) {
- charType = 'AL';
- }
- if (charType === 'R' || charType === 'AL' || charType === 'AN') {
- numBidi++;
- }
- types[i] = charType;
- }
- if (numBidi === 0) {
- isLTR = true;
- return createBidiText(str, isLTR);
- }
- if (startLevel === -1) {
- if (numBidi / strLength < 0.3) {
- isLTR = true;
- startLevel = 0;
- } else {
- isLTR = false;
- startLevel = 1;
- }
- }
- var levels = [];
- for (i = 0; i < strLength; ++i) {
- levels[i] = startLevel;
- }
- var e = isOdd(startLevel) ? 'R' : 'L';
- var sor = e;
- var eor = sor;
- var lastType = sor;
- for (i = 0; i < strLength; ++i) {
- if (types[i] === 'NSM') {
- types[i] = lastType;
- } else {
- lastType = types[i];
- }
- }
- lastType = sor;
- var t;
- for (i = 0; i < strLength; ++i) {
- t = types[i];
- if (t === 'EN') {
- types[i] = lastType === 'AL' ? 'AN' : 'EN';
- } else if (t === 'R' || t === 'L' || t === 'AL') {
- lastType = t;
- }
- }
- for (i = 0; i < strLength; ++i) {
- t = types[i];
- if (t === 'AL') {
- types[i] = 'R';
- }
- }
- for (i = 1; i < strLength - 1; ++i) {
- if (types[i] === 'ES' && types[i - 1] === 'EN' && types[i + 1] === 'EN') {
- types[i] = 'EN';
- }
- if (types[i] === 'CS' && (types[i - 1] === 'EN' || types[i - 1] === 'AN') && types[i + 1] === types[i - 1]) {
- types[i] = types[i - 1];
- }
- }
- for (i = 0; i < strLength; ++i) {
- if (types[i] === 'EN') {
- var j;
- for (j = i - 1; j >= 0; --j) {
- if (types[j] !== 'ET') {
- break;
- }
- types[j] = 'EN';
- }
- for (j = i + 1; j < strLength; ++j) {
- if (types[j] !== 'ET') {
- break;
- }
- types[j] = 'EN';
- }
- }
- }
- for (i = 0; i < strLength; ++i) {
- t = types[i];
- if (t === 'WS' || t === 'ES' || t === 'ET' || t === 'CS') {
- types[i] = 'ON';
- }
- }
- lastType = sor;
- for (i = 0; i < strLength; ++i) {
- t = types[i];
- if (t === 'EN') {
- types[i] = lastType === 'L' ? 'L' : 'EN';
- } else if (t === 'R' || t === 'L') {
- lastType = t;
- }
- }
- for (i = 0; i < strLength; ++i) {
- if (types[i] === 'ON') {
- var end = findUnequal(types, i + 1, 'ON');
- var before = sor;
- if (i > 0) {
- before = types[i - 1];
- }
- var after = eor;
- if (end + 1 < strLength) {
- after = types[end + 1];
- }
- if (before !== 'L') {
- before = 'R';
- }
- if (after !== 'L') {
- after = 'R';
- }
- if (before === after) {
- setValues(types, i, end, before);
- }
- i = end - 1;
- }
- }
- for (i = 0; i < strLength; ++i) {
- if (types[i] === 'ON') {
- types[i] = e;
- }
- }
- for (i = 0; i < strLength; ++i) {
- t = types[i];
- if (isEven(levels[i])) {
- if (t === 'R') {
- levels[i] += 1;
- } else if (t === 'AN' || t === 'EN') {
- levels[i] += 2;
- }
- } else {
- if (t === 'L' || t === 'AN' || t === 'EN') {
- levels[i] += 1;
- }
- }
- }
- var highestLevel = -1;
- var lowestOddLevel = 99;
- var level;
- for (i = 0, ii = levels.length; i < ii; ++i) {
- level = levels[i];
- if (highestLevel < level) {
- highestLevel = level;
- }
- if (lowestOddLevel > level && isOdd(level)) {
- lowestOddLevel = level;
- }
- }
- for (level = highestLevel; level >= lowestOddLevel; --level) {
- var start = -1;
- for (i = 0, ii = levels.length; i < ii; ++i) {
- if (levels[i] < level) {
- if (start >= 0) {
- reverseValues(chars, start, i);
- start = -1;
- }
- } else if (start < 0) {
- start = i;
- }
- }
- if (start >= 0) {
- reverseValues(chars, start, levels.length);
- }
- }
- for (i = 0, ii = chars.length; i < ii; ++i) {
- var ch = chars[i];
- if (ch === '<' || ch === '>') {
- chars[i] = '';
- }
- }
- return createBidiText(chars.join(''), isLTR);
-}
-exports.bidi = bidi;
-
-/***/ }),
-/* 167 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.getMetrics = undefined;
-
-var _util = __w_pdfjs_require__(2);
-
-var getMetrics = (0, _util.getLookupTableFactory)(function (t) {
- t['Courier'] = 600;
- t['Courier-Bold'] = 600;
- t['Courier-BoldOblique'] = 600;
- t['Courier-Oblique'] = 600;
- t['Helvetica'] = (0, _util.getLookupTableFactory)(function (t) {
- t['space'] = 278;
- t['exclam'] = 278;
- t['quotedbl'] = 355;
- t['numbersign'] = 556;
- t['dollar'] = 556;
- t['percent'] = 889;
- t['ampersand'] = 667;
- t['quoteright'] = 222;
- t['parenleft'] = 333;
- t['parenright'] = 333;
- t['asterisk'] = 389;
- t['plus'] = 584;
- t['comma'] = 278;
- t['hyphen'] = 333;
- t['period'] = 278;
- t['slash'] = 278;
- t['zero'] = 556;
- t['one'] = 556;
- t['two'] = 556;
- t['three'] = 556;
- t['four'] = 556;
- t['five'] = 556;
- t['six'] = 556;
- t['seven'] = 556;
- t['eight'] = 556;
- t['nine'] = 556;
- t['colon'] = 278;
- t['semicolon'] = 278;
- t['less'] = 584;
- t['equal'] = 584;
- t['greater'] = 584;
- t['question'] = 556;
- t['at'] = 1015;
- t['A'] = 667;
- t['B'] = 667;
- t['C'] = 722;
- t['D'] = 722;
- t['E'] = 667;
- t['F'] = 611;
- t['G'] = 778;
- t['H'] = 722;
- t['I'] = 278;
- t['J'] = 500;
- t['K'] = 667;
- t['L'] = 556;
- t['M'] = 833;
- t['N'] = 722;
- t['O'] = 778;
- t['P'] = 667;
- t['Q'] = 778;
- t['R'] = 722;
- t['S'] = 667;
- t['T'] = 611;
- t['U'] = 722;
- t['V'] = 667;
- t['W'] = 944;
- t['X'] = 667;
- t['Y'] = 667;
- t['Z'] = 611;
- t['bracketleft'] = 278;
- t['backslash'] = 278;
- t['bracketright'] = 278;
- t['asciicircum'] = 469;
- t['underscore'] = 556;
- t['quoteleft'] = 222;
- t['a'] = 556;
- t['b'] = 556;
- t['c'] = 500;
- t['d'] = 556;
- t['e'] = 556;
- t['f'] = 278;
- t['g'] = 556;
- t['h'] = 556;
- t['i'] = 222;
- t['j'] = 222;
- t['k'] = 500;
- t['l'] = 222;
- t['m'] = 833;
- t['n'] = 556;
- t['o'] = 556;
- t['p'] = 556;
- t['q'] = 556;
- t['r'] = 333;
- t['s'] = 500;
- t['t'] = 278;
- t['u'] = 556;
- t['v'] = 500;
- t['w'] = 722;
- t['x'] = 500;
- t['y'] = 500;
- t['z'] = 500;
- t['braceleft'] = 334;
- t['bar'] = 260;
- t['braceright'] = 334;
- t['asciitilde'] = 584;
- t['exclamdown'] = 333;
- t['cent'] = 556;
- t['sterling'] = 556;
- t['fraction'] = 167;
- t['yen'] = 556;
- t['florin'] = 556;
- t['section'] = 556;
- t['currency'] = 556;
- t['quotesingle'] = 191;
- t['quotedblleft'] = 333;
- t['guillemotleft'] = 556;
- t['guilsinglleft'] = 333;
- t['guilsinglright'] = 333;
- t['fi'] = 500;
- t['fl'] = 500;
- t['endash'] = 556;
- t['dagger'] = 556;
- t['daggerdbl'] = 556;
- t['periodcentered'] = 278;
- t['paragraph'] = 537;
- t['bullet'] = 350;
- t['quotesinglbase'] = 222;
- t['quotedblbase'] = 333;
- t['quotedblright'] = 333;
- t['guillemotright'] = 556;
- t['ellipsis'] = 1000;
- t['perthousand'] = 1000;
- t['questiondown'] = 611;
- t['grave'] = 333;
- t['acute'] = 333;
- t['circumflex'] = 333;
- t['tilde'] = 333;
- t['macron'] = 333;
- t['breve'] = 333;
- t['dotaccent'] = 333;
- t['dieresis'] = 333;
- t['ring'] = 333;
- t['cedilla'] = 333;
- t['hungarumlaut'] = 333;
- t['ogonek'] = 333;
- t['caron'] = 333;
- t['emdash'] = 1000;
- t['AE'] = 1000;
- t['ordfeminine'] = 370;
- t['Lslash'] = 556;
- t['Oslash'] = 778;
- t['OE'] = 1000;
- t['ordmasculine'] = 365;
- t['ae'] = 889;
- t['dotlessi'] = 278;
- t['lslash'] = 222;
- t['oslash'] = 611;
- t['oe'] = 944;
- t['germandbls'] = 611;
- t['Idieresis'] = 278;
- t['eacute'] = 556;
- t['abreve'] = 556;
- t['uhungarumlaut'] = 556;
- t['ecaron'] = 556;
- t['Ydieresis'] = 667;
- t['divide'] = 584;
- t['Yacute'] = 667;
- t['Acircumflex'] = 667;
- t['aacute'] = 556;
- t['Ucircumflex'] = 722;
- t['yacute'] = 500;
- t['scommaaccent'] = 500;
- t['ecircumflex'] = 556;
- t['Uring'] = 722;
- t['Udieresis'] = 722;
- t['aogonek'] = 556;
- t['Uacute'] = 722;
- t['uogonek'] = 556;
- t['Edieresis'] = 667;
- t['Dcroat'] = 722;
- t['commaaccent'] = 250;
- t['copyright'] = 737;
- t['Emacron'] = 667;
- t['ccaron'] = 500;
- t['aring'] = 556;
- t['Ncommaaccent'] = 722;
- t['lacute'] = 222;
- t['agrave'] = 556;
- t['Tcommaaccent'] = 611;
- t['Cacute'] = 722;
- t['atilde'] = 556;
- t['Edotaccent'] = 667;
- t['scaron'] = 500;
- t['scedilla'] = 500;
- t['iacute'] = 278;
- t['lozenge'] = 471;
- t['Rcaron'] = 722;
- t['Gcommaaccent'] = 778;
- t['ucircumflex'] = 556;
- t['acircumflex'] = 556;
- t['Amacron'] = 667;
- t['rcaron'] = 333;
- t['ccedilla'] = 500;
- t['Zdotaccent'] = 611;
- t['Thorn'] = 667;
- t['Omacron'] = 778;
- t['Racute'] = 722;
- t['Sacute'] = 667;
- t['dcaron'] = 643;
- t['Umacron'] = 722;
- t['uring'] = 556;
- t['threesuperior'] = 333;
- t['Ograve'] = 778;
- t['Agrave'] = 667;
- t['Abreve'] = 667;
- t['multiply'] = 584;
- t['uacute'] = 556;
- t['Tcaron'] = 611;
- t['partialdiff'] = 476;
- t['ydieresis'] = 500;
- t['Nacute'] = 722;
- t['icircumflex'] = 278;
- t['Ecircumflex'] = 667;
- t['adieresis'] = 556;
- t['edieresis'] = 556;
- t['cacute'] = 500;
- t['nacute'] = 556;
- t['umacron'] = 556;
- t['Ncaron'] = 722;
- t['Iacute'] = 278;
- t['plusminus'] = 584;
- t['brokenbar'] = 260;
- t['registered'] = 737;
- t['Gbreve'] = 778;
- t['Idotaccent'] = 278;
- t['summation'] = 600;
- t['Egrave'] = 667;
- t['racute'] = 333;
- t['omacron'] = 556;
- t['Zacute'] = 611;
- t['Zcaron'] = 611;
- t['greaterequal'] = 549;
- t['Eth'] = 722;
- t['Ccedilla'] = 722;
- t['lcommaaccent'] = 222;
- t['tcaron'] = 317;
- t['eogonek'] = 556;
- t['Uogonek'] = 722;
- t['Aacute'] = 667;
- t['Adieresis'] = 667;
- t['egrave'] = 556;
- t['zacute'] = 500;
- t['iogonek'] = 222;
- t['Oacute'] = 778;
- t['oacute'] = 556;
- t['amacron'] = 556;
- t['sacute'] = 500;
- t['idieresis'] = 278;
- t['Ocircumflex'] = 778;
- t['Ugrave'] = 722;
- t['Delta'] = 612;
- t['thorn'] = 556;
- t['twosuperior'] = 333;
- t['Odieresis'] = 778;
- t['mu'] = 556;
- t['igrave'] = 278;
- t['ohungarumlaut'] = 556;
- t['Eogonek'] = 667;
- t['dcroat'] = 556;
- t['threequarters'] = 834;
- t['Scedilla'] = 667;
- t['lcaron'] = 299;
- t['Kcommaaccent'] = 667;
- t['Lacute'] = 556;
- t['trademark'] = 1000;
- t['edotaccent'] = 556;
- t['Igrave'] = 278;
- t['Imacron'] = 278;
- t['Lcaron'] = 556;
- t['onehalf'] = 834;
- t['lessequal'] = 549;
- t['ocircumflex'] = 556;
- t['ntilde'] = 556;
- t['Uhungarumlaut'] = 722;
- t['Eacute'] = 667;
- t['emacron'] = 556;
- t['gbreve'] = 556;
- t['onequarter'] = 834;
- t['Scaron'] = 667;
- t['Scommaaccent'] = 667;
- t['Ohungarumlaut'] = 778;
- t['degree'] = 400;
- t['ograve'] = 556;
- t['Ccaron'] = 722;
- t['ugrave'] = 556;
- t['radical'] = 453;
- t['Dcaron'] = 722;
- t['rcommaaccent'] = 333;
- t['Ntilde'] = 722;
- t['otilde'] = 556;
- t['Rcommaaccent'] = 722;
- t['Lcommaaccent'] = 556;
- t['Atilde'] = 667;
- t['Aogonek'] = 667;
- t['Aring'] = 667;
- t['Otilde'] = 778;
- t['zdotaccent'] = 500;
- t['Ecaron'] = 667;
- t['Iogonek'] = 278;
- t['kcommaaccent'] = 500;
- t['minus'] = 584;
- t['Icircumflex'] = 278;
- t['ncaron'] = 556;
- t['tcommaaccent'] = 278;
- t['logicalnot'] = 584;
- t['odieresis'] = 556;
- t['udieresis'] = 556;
- t['notequal'] = 549;
- t['gcommaaccent'] = 556;
- t['eth'] = 556;
- t['zcaron'] = 500;
- t['ncommaaccent'] = 556;
- t['onesuperior'] = 333;
- t['imacron'] = 278;
- t['Euro'] = 556;
- });
- t['Helvetica-Bold'] = (0, _util.getLookupTableFactory)(function (t) {
- t['space'] = 278;
- t['exclam'] = 333;
- t['quotedbl'] = 474;
- t['numbersign'] = 556;
- t['dollar'] = 556;
- t['percent'] = 889;
- t['ampersand'] = 722;
- t['quoteright'] = 278;
- t['parenleft'] = 333;
- t['parenright'] = 333;
- t['asterisk'] = 389;
- t['plus'] = 584;
- t['comma'] = 278;
- t['hyphen'] = 333;
- t['period'] = 278;
- t['slash'] = 278;
- t['zero'] = 556;
- t['one'] = 556;
- t['two'] = 556;
- t['three'] = 556;
- t['four'] = 556;
- t['five'] = 556;
- t['six'] = 556;
- t['seven'] = 556;
- t['eight'] = 556;
- t['nine'] = 556;
- t['colon'] = 333;
- t['semicolon'] = 333;
- t['less'] = 584;
- t['equal'] = 584;
- t['greater'] = 584;
- t['question'] = 611;
- t['at'] = 975;
- t['A'] = 722;
- t['B'] = 722;
- t['C'] = 722;
- t['D'] = 722;
- t['E'] = 667;
- t['F'] = 611;
- t['G'] = 778;
- t['H'] = 722;
- t['I'] = 278;
- t['J'] = 556;
- t['K'] = 722;
- t['L'] = 611;
- t['M'] = 833;
- t['N'] = 722;
- t['O'] = 778;
- t['P'] = 667;
- t['Q'] = 778;
- t['R'] = 722;
- t['S'] = 667;
- t['T'] = 611;
- t['U'] = 722;
- t['V'] = 667;
- t['W'] = 944;
- t['X'] = 667;
- t['Y'] = 667;
- t['Z'] = 611;
- t['bracketleft'] = 333;
- t['backslash'] = 278;
- t['bracketright'] = 333;
- t['asciicircum'] = 584;
- t['underscore'] = 556;
- t['quoteleft'] = 278;
- t['a'] = 556;
- t['b'] = 611;
- t['c'] = 556;
- t['d'] = 611;
- t['e'] = 556;
- t['f'] = 333;
- t['g'] = 611;
- t['h'] = 611;
- t['i'] = 278;
- t['j'] = 278;
- t['k'] = 556;
- t['l'] = 278;
- t['m'] = 889;
- t['n'] = 611;
- t['o'] = 611;
- t['p'] = 611;
- t['q'] = 611;
- t['r'] = 389;
- t['s'] = 556;
- t['t'] = 333;
- t['u'] = 611;
- t['v'] = 556;
- t['w'] = 778;
- t['x'] = 556;
- t['y'] = 556;
- t['z'] = 500;
- t['braceleft'] = 389;
- t['bar'] = 280;
- t['braceright'] = 389;
- t['asciitilde'] = 584;
- t['exclamdown'] = 333;
- t['cent'] = 556;
- t['sterling'] = 556;
- t['fraction'] = 167;
- t['yen'] = 556;
- t['florin'] = 556;
- t['section'] = 556;
- t['currency'] = 556;
- t['quotesingle'] = 238;
- t['quotedblleft'] = 500;
- t['guillemotleft'] = 556;
- t['guilsinglleft'] = 333;
- t['guilsinglright'] = 333;
- t['fi'] = 611;
- t['fl'] = 611;
- t['endash'] = 556;
- t['dagger'] = 556;
- t['daggerdbl'] = 556;
- t['periodcentered'] = 278;
- t['paragraph'] = 556;
- t['bullet'] = 350;
- t['quotesinglbase'] = 278;
- t['quotedblbase'] = 500;
- t['quotedblright'] = 500;
- t['guillemotright'] = 556;
- t['ellipsis'] = 1000;
- t['perthousand'] = 1000;
- t['questiondown'] = 611;
- t['grave'] = 333;
- t['acute'] = 333;
- t['circumflex'] = 333;
- t['tilde'] = 333;
- t['macron'] = 333;
- t['breve'] = 333;
- t['dotaccent'] = 333;
- t['dieresis'] = 333;
- t['ring'] = 333;
- t['cedilla'] = 333;
- t['hungarumlaut'] = 333;
- t['ogonek'] = 333;
- t['caron'] = 333;
- t['emdash'] = 1000;
- t['AE'] = 1000;
- t['ordfeminine'] = 370;
- t['Lslash'] = 611;
- t['Oslash'] = 778;
- t['OE'] = 1000;
- t['ordmasculine'] = 365;
- t['ae'] = 889;
- t['dotlessi'] = 278;
- t['lslash'] = 278;
- t['oslash'] = 611;
- t['oe'] = 944;
- t['germandbls'] = 611;
- t['Idieresis'] = 278;
- t['eacute'] = 556;
- t['abreve'] = 556;
- t['uhungarumlaut'] = 611;
- t['ecaron'] = 556;
- t['Ydieresis'] = 667;
- t['divide'] = 584;
- t['Yacute'] = 667;
- t['Acircumflex'] = 722;
- t['aacute'] = 556;
- t['Ucircumflex'] = 722;
- t['yacute'] = 556;
- t['scommaaccent'] = 556;
- t['ecircumflex'] = 556;
- t['Uring'] = 722;
- t['Udieresis'] = 722;
- t['aogonek'] = 556;
- t['Uacute'] = 722;
- t['uogonek'] = 611;
- t['Edieresis'] = 667;
- t['Dcroat'] = 722;
- t['commaaccent'] = 250;
- t['copyright'] = 737;
- t['Emacron'] = 667;
- t['ccaron'] = 556;
- t['aring'] = 556;
- t['Ncommaaccent'] = 722;
- t['lacute'] = 278;
- t['agrave'] = 556;
- t['Tcommaaccent'] = 611;
- t['Cacute'] = 722;
- t['atilde'] = 556;
- t['Edotaccent'] = 667;
- t['scaron'] = 556;
- t['scedilla'] = 556;
- t['iacute'] = 278;
- t['lozenge'] = 494;
- t['Rcaron'] = 722;
- t['Gcommaaccent'] = 778;
- t['ucircumflex'] = 611;
- t['acircumflex'] = 556;
- t['Amacron'] = 722;
- t['rcaron'] = 389;
- t['ccedilla'] = 556;
- t['Zdotaccent'] = 611;
- t['Thorn'] = 667;
- t['Omacron'] = 778;
- t['Racute'] = 722;
- t['Sacute'] = 667;
- t['dcaron'] = 743;
- t['Umacron'] = 722;
- t['uring'] = 611;
- t['threesuperior'] = 333;
- t['Ograve'] = 778;
- t['Agrave'] = 722;
- t['Abreve'] = 722;
- t['multiply'] = 584;
- t['uacute'] = 611;
- t['Tcaron'] = 611;
- t['partialdiff'] = 494;
- t['ydieresis'] = 556;
- t['Nacute'] = 722;
- t['icircumflex'] = 278;
- t['Ecircumflex'] = 667;
- t['adieresis'] = 556;
- t['edieresis'] = 556;
- t['cacute'] = 556;
- t['nacute'] = 611;
- t['umacron'] = 611;
- t['Ncaron'] = 722;
- t['Iacute'] = 278;
- t['plusminus'] = 584;
- t['brokenbar'] = 280;
- t['registered'] = 737;
- t['Gbreve'] = 778;
- t['Idotaccent'] = 278;
- t['summation'] = 600;
- t['Egrave'] = 667;
- t['racute'] = 389;
- t['omacron'] = 611;
- t['Zacute'] = 611;
- t['Zcaron'] = 611;
- t['greaterequal'] = 549;
- t['Eth'] = 722;
- t['Ccedilla'] = 722;
- t['lcommaaccent'] = 278;
- t['tcaron'] = 389;
- t['eogonek'] = 556;
- t['Uogonek'] = 722;
- t['Aacute'] = 722;
- t['Adieresis'] = 722;
- t['egrave'] = 556;
- t['zacute'] = 500;
- t['iogonek'] = 278;
- t['Oacute'] = 778;
- t['oacute'] = 611;
- t['amacron'] = 556;
- t['sacute'] = 556;
- t['idieresis'] = 278;
- t['Ocircumflex'] = 778;
- t['Ugrave'] = 722;
- t['Delta'] = 612;
- t['thorn'] = 611;
- t['twosuperior'] = 333;
- t['Odieresis'] = 778;
- t['mu'] = 611;
- t['igrave'] = 278;
- t['ohungarumlaut'] = 611;
- t['Eogonek'] = 667;
- t['dcroat'] = 611;
- t['threequarters'] = 834;
- t['Scedilla'] = 667;
- t['lcaron'] = 400;
- t['Kcommaaccent'] = 722;
- t['Lacute'] = 611;
- t['trademark'] = 1000;
- t['edotaccent'] = 556;
- t['Igrave'] = 278;
- t['Imacron'] = 278;
- t['Lcaron'] = 611;
- t['onehalf'] = 834;
- t['lessequal'] = 549;
- t['ocircumflex'] = 611;
- t['ntilde'] = 611;
- t['Uhungarumlaut'] = 722;
- t['Eacute'] = 667;
- t['emacron'] = 556;
- t['gbreve'] = 611;
- t['onequarter'] = 834;
- t['Scaron'] = 667;
- t['Scommaaccent'] = 667;
- t['Ohungarumlaut'] = 778;
- t['degree'] = 400;
- t['ograve'] = 611;
- t['Ccaron'] = 722;
- t['ugrave'] = 611;
- t['radical'] = 549;
- t['Dcaron'] = 722;
- t['rcommaaccent'] = 389;
- t['Ntilde'] = 722;
- t['otilde'] = 611;
- t['Rcommaaccent'] = 722;
- t['Lcommaaccent'] = 611;
- t['Atilde'] = 722;
- t['Aogonek'] = 722;
- t['Aring'] = 722;
- t['Otilde'] = 778;
- t['zdotaccent'] = 500;
- t['Ecaron'] = 667;
- t['Iogonek'] = 278;
- t['kcommaaccent'] = 556;
- t['minus'] = 584;
- t['Icircumflex'] = 278;
- t['ncaron'] = 611;
- t['tcommaaccent'] = 333;
- t['logicalnot'] = 584;
- t['odieresis'] = 611;
- t['udieresis'] = 611;
- t['notequal'] = 549;
- t['gcommaaccent'] = 611;
- t['eth'] = 611;
- t['zcaron'] = 500;
- t['ncommaaccent'] = 611;
- t['onesuperior'] = 333;
- t['imacron'] = 278;
- t['Euro'] = 556;
- });
- t['Helvetica-BoldOblique'] = (0, _util.getLookupTableFactory)(function (t) {
- t['space'] = 278;
- t['exclam'] = 333;
- t['quotedbl'] = 474;
- t['numbersign'] = 556;
- t['dollar'] = 556;
- t['percent'] = 889;
- t['ampersand'] = 722;
- t['quoteright'] = 278;
- t['parenleft'] = 333;
- t['parenright'] = 333;
- t['asterisk'] = 389;
- t['plus'] = 584;
- t['comma'] = 278;
- t['hyphen'] = 333;
- t['period'] = 278;
- t['slash'] = 278;
- t['zero'] = 556;
- t['one'] = 556;
- t['two'] = 556;
- t['three'] = 556;
- t['four'] = 556;
- t['five'] = 556;
- t['six'] = 556;
- t['seven'] = 556;
- t['eight'] = 556;
- t['nine'] = 556;
- t['colon'] = 333;
- t['semicolon'] = 333;
- t['less'] = 584;
- t['equal'] = 584;
- t['greater'] = 584;
- t['question'] = 611;
- t['at'] = 975;
- t['A'] = 722;
- t['B'] = 722;
- t['C'] = 722;
- t['D'] = 722;
- t['E'] = 667;
- t['F'] = 611;
- t['G'] = 778;
- t['H'] = 722;
- t['I'] = 278;
- t['J'] = 556;
- t['K'] = 722;
- t['L'] = 611;
- t['M'] = 833;
- t['N'] = 722;
- t['O'] = 778;
- t['P'] = 667;
- t['Q'] = 778;
- t['R'] = 722;
- t['S'] = 667;
- t['T'] = 611;
- t['U'] = 722;
- t['V'] = 667;
- t['W'] = 944;
- t['X'] = 667;
- t['Y'] = 667;
- t['Z'] = 611;
- t['bracketleft'] = 333;
- t['backslash'] = 278;
- t['bracketright'] = 333;
- t['asciicircum'] = 584;
- t['underscore'] = 556;
- t['quoteleft'] = 278;
- t['a'] = 556;
- t['b'] = 611;
- t['c'] = 556;
- t['d'] = 611;
- t['e'] = 556;
- t['f'] = 333;
- t['g'] = 611;
- t['h'] = 611;
- t['i'] = 278;
- t['j'] = 278;
- t['k'] = 556;
- t['l'] = 278;
- t['m'] = 889;
- t['n'] = 611;
- t['o'] = 611;
- t['p'] = 611;
- t['q'] = 611;
- t['r'] = 389;
- t['s'] = 556;
- t['t'] = 333;
- t['u'] = 611;
- t['v'] = 556;
- t['w'] = 778;
- t['x'] = 556;
- t['y'] = 556;
- t['z'] = 500;
- t['braceleft'] = 389;
- t['bar'] = 280;
- t['braceright'] = 389;
- t['asciitilde'] = 584;
- t['exclamdown'] = 333;
- t['cent'] = 556;
- t['sterling'] = 556;
- t['fraction'] = 167;
- t['yen'] = 556;
- t['florin'] = 556;
- t['section'] = 556;
- t['currency'] = 556;
- t['quotesingle'] = 238;
- t['quotedblleft'] = 500;
- t['guillemotleft'] = 556;
- t['guilsinglleft'] = 333;
- t['guilsinglright'] = 333;
- t['fi'] = 611;
- t['fl'] = 611;
- t['endash'] = 556;
- t['dagger'] = 556;
- t['daggerdbl'] = 556;
- t['periodcentered'] = 278;
- t['paragraph'] = 556;
- t['bullet'] = 350;
- t['quotesinglbase'] = 278;
- t['quotedblbase'] = 500;
- t['quotedblright'] = 500;
- t['guillemotright'] = 556;
- t['ellipsis'] = 1000;
- t['perthousand'] = 1000;
- t['questiondown'] = 611;
- t['grave'] = 333;
- t['acute'] = 333;
- t['circumflex'] = 333;
- t['tilde'] = 333;
- t['macron'] = 333;
- t['breve'] = 333;
- t['dotaccent'] = 333;
- t['dieresis'] = 333;
- t['ring'] = 333;
- t['cedilla'] = 333;
- t['hungarumlaut'] = 333;
- t['ogonek'] = 333;
- t['caron'] = 333;
- t['emdash'] = 1000;
- t['AE'] = 1000;
- t['ordfeminine'] = 370;
- t['Lslash'] = 611;
- t['Oslash'] = 778;
- t['OE'] = 1000;
- t['ordmasculine'] = 365;
- t['ae'] = 889;
- t['dotlessi'] = 278;
- t['lslash'] = 278;
- t['oslash'] = 611;
- t['oe'] = 944;
- t['germandbls'] = 611;
- t['Idieresis'] = 278;
- t['eacute'] = 556;
- t['abreve'] = 556;
- t['uhungarumlaut'] = 611;
- t['ecaron'] = 556;
- t['Ydieresis'] = 667;
- t['divide'] = 584;
- t['Yacute'] = 667;
- t['Acircumflex'] = 722;
- t['aacute'] = 556;
- t['Ucircumflex'] = 722;
- t['yacute'] = 556;
- t['scommaaccent'] = 556;
- t['ecircumflex'] = 556;
- t['Uring'] = 722;
- t['Udieresis'] = 722;
- t['aogonek'] = 556;
- t['Uacute'] = 722;
- t['uogonek'] = 611;
- t['Edieresis'] = 667;
- t['Dcroat'] = 722;
- t['commaaccent'] = 250;
- t['copyright'] = 737;
- t['Emacron'] = 667;
- t['ccaron'] = 556;
- t['aring'] = 556;
- t['Ncommaaccent'] = 722;
- t['lacute'] = 278;
- t['agrave'] = 556;
- t['Tcommaaccent'] = 611;
- t['Cacute'] = 722;
- t['atilde'] = 556;
- t['Edotaccent'] = 667;
- t['scaron'] = 556;
- t['scedilla'] = 556;
- t['iacute'] = 278;
- t['lozenge'] = 494;
- t['Rcaron'] = 722;
- t['Gcommaaccent'] = 778;
- t['ucircumflex'] = 611;
- t['acircumflex'] = 556;
- t['Amacron'] = 722;
- t['rcaron'] = 389;
- t['ccedilla'] = 556;
- t['Zdotaccent'] = 611;
- t['Thorn'] = 667;
- t['Omacron'] = 778;
- t['Racute'] = 722;
- t['Sacute'] = 667;
- t['dcaron'] = 743;
- t['Umacron'] = 722;
- t['uring'] = 611;
- t['threesuperior'] = 333;
- t['Ograve'] = 778;
- t['Agrave'] = 722;
- t['Abreve'] = 722;
- t['multiply'] = 584;
- t['uacute'] = 611;
- t['Tcaron'] = 611;
- t['partialdiff'] = 494;
- t['ydieresis'] = 556;
- t['Nacute'] = 722;
- t['icircumflex'] = 278;
- t['Ecircumflex'] = 667;
- t['adieresis'] = 556;
- t['edieresis'] = 556;
- t['cacute'] = 556;
- t['nacute'] = 611;
- t['umacron'] = 611;
- t['Ncaron'] = 722;
- t['Iacute'] = 278;
- t['plusminus'] = 584;
- t['brokenbar'] = 280;
- t['registered'] = 737;
- t['Gbreve'] = 778;
- t['Idotaccent'] = 278;
- t['summation'] = 600;
- t['Egrave'] = 667;
- t['racute'] = 389;
- t['omacron'] = 611;
- t['Zacute'] = 611;
- t['Zcaron'] = 611;
- t['greaterequal'] = 549;
- t['Eth'] = 722;
- t['Ccedilla'] = 722;
- t['lcommaaccent'] = 278;
- t['tcaron'] = 389;
- t['eogonek'] = 556;
- t['Uogonek'] = 722;
- t['Aacute'] = 722;
- t['Adieresis'] = 722;
- t['egrave'] = 556;
- t['zacute'] = 500;
- t['iogonek'] = 278;
- t['Oacute'] = 778;
- t['oacute'] = 611;
- t['amacron'] = 556;
- t['sacute'] = 556;
- t['idieresis'] = 278;
- t['Ocircumflex'] = 778;
- t['Ugrave'] = 722;
- t['Delta'] = 612;
- t['thorn'] = 611;
- t['twosuperior'] = 333;
- t['Odieresis'] = 778;
- t['mu'] = 611;
- t['igrave'] = 278;
- t['ohungarumlaut'] = 611;
- t['Eogonek'] = 667;
- t['dcroat'] = 611;
- t['threequarters'] = 834;
- t['Scedilla'] = 667;
- t['lcaron'] = 400;
- t['Kcommaaccent'] = 722;
- t['Lacute'] = 611;
- t['trademark'] = 1000;
- t['edotaccent'] = 556;
- t['Igrave'] = 278;
- t['Imacron'] = 278;
- t['Lcaron'] = 611;
- t['onehalf'] = 834;
- t['lessequal'] = 549;
- t['ocircumflex'] = 611;
- t['ntilde'] = 611;
- t['Uhungarumlaut'] = 722;
- t['Eacute'] = 667;
- t['emacron'] = 556;
- t['gbreve'] = 611;
- t['onequarter'] = 834;
- t['Scaron'] = 667;
- t['Scommaaccent'] = 667;
- t['Ohungarumlaut'] = 778;
- t['degree'] = 400;
- t['ograve'] = 611;
- t['Ccaron'] = 722;
- t['ugrave'] = 611;
- t['radical'] = 549;
- t['Dcaron'] = 722;
- t['rcommaaccent'] = 389;
- t['Ntilde'] = 722;
- t['otilde'] = 611;
- t['Rcommaaccent'] = 722;
- t['Lcommaaccent'] = 611;
- t['Atilde'] = 722;
- t['Aogonek'] = 722;
- t['Aring'] = 722;
- t['Otilde'] = 778;
- t['zdotaccent'] = 500;
- t['Ecaron'] = 667;
- t['Iogonek'] = 278;
- t['kcommaaccent'] = 556;
- t['minus'] = 584;
- t['Icircumflex'] = 278;
- t['ncaron'] = 611;
- t['tcommaaccent'] = 333;
- t['logicalnot'] = 584;
- t['odieresis'] = 611;
- t['udieresis'] = 611;
- t['notequal'] = 549;
- t['gcommaaccent'] = 611;
- t['eth'] = 611;
- t['zcaron'] = 500;
- t['ncommaaccent'] = 611;
- t['onesuperior'] = 333;
- t['imacron'] = 278;
- t['Euro'] = 556;
- });
- t['Helvetica-Oblique'] = (0, _util.getLookupTableFactory)(function (t) {
- t['space'] = 278;
- t['exclam'] = 278;
- t['quotedbl'] = 355;
- t['numbersign'] = 556;
- t['dollar'] = 556;
- t['percent'] = 889;
- t['ampersand'] = 667;
- t['quoteright'] = 222;
- t['parenleft'] = 333;
- t['parenright'] = 333;
- t['asterisk'] = 389;
- t['plus'] = 584;
- t['comma'] = 278;
- t['hyphen'] = 333;
- t['period'] = 278;
- t['slash'] = 278;
- t['zero'] = 556;
- t['one'] = 556;
- t['two'] = 556;
- t['three'] = 556;
- t['four'] = 556;
- t['five'] = 556;
- t['six'] = 556;
- t['seven'] = 556;
- t['eight'] = 556;
- t['nine'] = 556;
- t['colon'] = 278;
- t['semicolon'] = 278;
- t['less'] = 584;
- t['equal'] = 584;
- t['greater'] = 584;
- t['question'] = 556;
- t['at'] = 1015;
- t['A'] = 667;
- t['B'] = 667;
- t['C'] = 722;
- t['D'] = 722;
- t['E'] = 667;
- t['F'] = 611;
- t['G'] = 778;
- t['H'] = 722;
- t['I'] = 278;
- t['J'] = 500;
- t['K'] = 667;
- t['L'] = 556;
- t['M'] = 833;
- t['N'] = 722;
- t['O'] = 778;
- t['P'] = 667;
- t['Q'] = 778;
- t['R'] = 722;
- t['S'] = 667;
- t['T'] = 611;
- t['U'] = 722;
- t['V'] = 667;
- t['W'] = 944;
- t['X'] = 667;
- t['Y'] = 667;
- t['Z'] = 611;
- t['bracketleft'] = 278;
- t['backslash'] = 278;
- t['bracketright'] = 278;
- t['asciicircum'] = 469;
- t['underscore'] = 556;
- t['quoteleft'] = 222;
- t['a'] = 556;
- t['b'] = 556;
- t['c'] = 500;
- t['d'] = 556;
- t['e'] = 556;
- t['f'] = 278;
- t['g'] = 556;
- t['h'] = 556;
- t['i'] = 222;
- t['j'] = 222;
- t['k'] = 500;
- t['l'] = 222;
- t['m'] = 833;
- t['n'] = 556;
- t['o'] = 556;
- t['p'] = 556;
- t['q'] = 556;
- t['r'] = 333;
- t['s'] = 500;
- t['t'] = 278;
- t['u'] = 556;
- t['v'] = 500;
- t['w'] = 722;
- t['x'] = 500;
- t['y'] = 500;
- t['z'] = 500;
- t['braceleft'] = 334;
- t['bar'] = 260;
- t['braceright'] = 334;
- t['asciitilde'] = 584;
- t['exclamdown'] = 333;
- t['cent'] = 556;
- t['sterling'] = 556;
- t['fraction'] = 167;
- t['yen'] = 556;
- t['florin'] = 556;
- t['section'] = 556;
- t['currency'] = 556;
- t['quotesingle'] = 191;
- t['quotedblleft'] = 333;
- t['guillemotleft'] = 556;
- t['guilsinglleft'] = 333;
- t['guilsinglright'] = 333;
- t['fi'] = 500;
- t['fl'] = 500;
- t['endash'] = 556;
- t['dagger'] = 556;
- t['daggerdbl'] = 556;
- t['periodcentered'] = 278;
- t['paragraph'] = 537;
- t['bullet'] = 350;
- t['quotesinglbase'] = 222;
- t['quotedblbase'] = 333;
- t['quotedblright'] = 333;
- t['guillemotright'] = 556;
- t['ellipsis'] = 1000;
- t['perthousand'] = 1000;
- t['questiondown'] = 611;
- t['grave'] = 333;
- t['acute'] = 333;
- t['circumflex'] = 333;
- t['tilde'] = 333;
- t['macron'] = 333;
- t['breve'] = 333;
- t['dotaccent'] = 333;
- t['dieresis'] = 333;
- t['ring'] = 333;
- t['cedilla'] = 333;
- t['hungarumlaut'] = 333;
- t['ogonek'] = 333;
- t['caron'] = 333;
- t['emdash'] = 1000;
- t['AE'] = 1000;
- t['ordfeminine'] = 370;
- t['Lslash'] = 556;
- t['Oslash'] = 778;
- t['OE'] = 1000;
- t['ordmasculine'] = 365;
- t['ae'] = 889;
- t['dotlessi'] = 278;
- t['lslash'] = 222;
- t['oslash'] = 611;
- t['oe'] = 944;
- t['germandbls'] = 611;
- t['Idieresis'] = 278;
- t['eacute'] = 556;
- t['abreve'] = 556;
- t['uhungarumlaut'] = 556;
- t['ecaron'] = 556;
- t['Ydieresis'] = 667;
- t['divide'] = 584;
- t['Yacute'] = 667;
- t['Acircumflex'] = 667;
- t['aacute'] = 556;
- t['Ucircumflex'] = 722;
- t['yacute'] = 500;
- t['scommaaccent'] = 500;
- t['ecircumflex'] = 556;
- t['Uring'] = 722;
- t['Udieresis'] = 722;
- t['aogonek'] = 556;
- t['Uacute'] = 722;
- t['uogonek'] = 556;
- t['Edieresis'] = 667;
- t['Dcroat'] = 722;
- t['commaaccent'] = 250;
- t['copyright'] = 737;
- t['Emacron'] = 667;
- t['ccaron'] = 500;
- t['aring'] = 556;
- t['Ncommaaccent'] = 722;
- t['lacute'] = 222;
- t['agrave'] = 556;
- t['Tcommaaccent'] = 611;
- t['Cacute'] = 722;
- t['atilde'] = 556;
- t['Edotaccent'] = 667;
- t['scaron'] = 500;
- t['scedilla'] = 500;
- t['iacute'] = 278;
- t['lozenge'] = 471;
- t['Rcaron'] = 722;
- t['Gcommaaccent'] = 778;
- t['ucircumflex'] = 556;
- t['acircumflex'] = 556;
- t['Amacron'] = 667;
- t['rcaron'] = 333;
- t['ccedilla'] = 500;
- t['Zdotaccent'] = 611;
- t['Thorn'] = 667;
- t['Omacron'] = 778;
- t['Racute'] = 722;
- t['Sacute'] = 667;
- t['dcaron'] = 643;
- t['Umacron'] = 722;
- t['uring'] = 556;
- t['threesuperior'] = 333;
- t['Ograve'] = 778;
- t['Agrave'] = 667;
- t['Abreve'] = 667;
- t['multiply'] = 584;
- t['uacute'] = 556;
- t['Tcaron'] = 611;
- t['partialdiff'] = 476;
- t['ydieresis'] = 500;
- t['Nacute'] = 722;
- t['icircumflex'] = 278;
- t['Ecircumflex'] = 667;
- t['adieresis'] = 556;
- t['edieresis'] = 556;
- t['cacute'] = 500;
- t['nacute'] = 556;
- t['umacron'] = 556;
- t['Ncaron'] = 722;
- t['Iacute'] = 278;
- t['plusminus'] = 584;
- t['brokenbar'] = 260;
- t['registered'] = 737;
- t['Gbreve'] = 778;
- t['Idotaccent'] = 278;
- t['summation'] = 600;
- t['Egrave'] = 667;
- t['racute'] = 333;
- t['omacron'] = 556;
- t['Zacute'] = 611;
- t['Zcaron'] = 611;
- t['greaterequal'] = 549;
- t['Eth'] = 722;
- t['Ccedilla'] = 722;
- t['lcommaaccent'] = 222;
- t['tcaron'] = 317;
- t['eogonek'] = 556;
- t['Uogonek'] = 722;
- t['Aacute'] = 667;
- t['Adieresis'] = 667;
- t['egrave'] = 556;
- t['zacute'] = 500;
- t['iogonek'] = 222;
- t['Oacute'] = 778;
- t['oacute'] = 556;
- t['amacron'] = 556;
- t['sacute'] = 500;
- t['idieresis'] = 278;
- t['Ocircumflex'] = 778;
- t['Ugrave'] = 722;
- t['Delta'] = 612;
- t['thorn'] = 556;
- t['twosuperior'] = 333;
- t['Odieresis'] = 778;
- t['mu'] = 556;
- t['igrave'] = 278;
- t['ohungarumlaut'] = 556;
- t['Eogonek'] = 667;
- t['dcroat'] = 556;
- t['threequarters'] = 834;
- t['Scedilla'] = 667;
- t['lcaron'] = 299;
- t['Kcommaaccent'] = 667;
- t['Lacute'] = 556;
- t['trademark'] = 1000;
- t['edotaccent'] = 556;
- t['Igrave'] = 278;
- t['Imacron'] = 278;
- t['Lcaron'] = 556;
- t['onehalf'] = 834;
- t['lessequal'] = 549;
- t['ocircumflex'] = 556;
- t['ntilde'] = 556;
- t['Uhungarumlaut'] = 722;
- t['Eacute'] = 667;
- t['emacron'] = 556;
- t['gbreve'] = 556;
- t['onequarter'] = 834;
- t['Scaron'] = 667;
- t['Scommaaccent'] = 667;
- t['Ohungarumlaut'] = 778;
- t['degree'] = 400;
- t['ograve'] = 556;
- t['Ccaron'] = 722;
- t['ugrave'] = 556;
- t['radical'] = 453;
- t['Dcaron'] = 722;
- t['rcommaaccent'] = 333;
- t['Ntilde'] = 722;
- t['otilde'] = 556;
- t['Rcommaaccent'] = 722;
- t['Lcommaaccent'] = 556;
- t['Atilde'] = 667;
- t['Aogonek'] = 667;
- t['Aring'] = 667;
- t['Otilde'] = 778;
- t['zdotaccent'] = 500;
- t['Ecaron'] = 667;
- t['Iogonek'] = 278;
- t['kcommaaccent'] = 500;
- t['minus'] = 584;
- t['Icircumflex'] = 278;
- t['ncaron'] = 556;
- t['tcommaaccent'] = 278;
- t['logicalnot'] = 584;
- t['odieresis'] = 556;
- t['udieresis'] = 556;
- t['notequal'] = 549;
- t['gcommaaccent'] = 556;
- t['eth'] = 556;
- t['zcaron'] = 500;
- t['ncommaaccent'] = 556;
- t['onesuperior'] = 333;
- t['imacron'] = 278;
- t['Euro'] = 556;
- });
- t['Symbol'] = (0, _util.getLookupTableFactory)(function (t) {
- t['space'] = 250;
- t['exclam'] = 333;
- t['universal'] = 713;
- t['numbersign'] = 500;
- t['existential'] = 549;
- t['percent'] = 833;
- t['ampersand'] = 778;
- t['suchthat'] = 439;
- t['parenleft'] = 333;
- t['parenright'] = 333;
- t['asteriskmath'] = 500;
- t['plus'] = 549;
- t['comma'] = 250;
- t['minus'] = 549;
- t['period'] = 250;
- t['slash'] = 278;
- t['zero'] = 500;
- t['one'] = 500;
- t['two'] = 500;
- t['three'] = 500;
- t['four'] = 500;
- t['five'] = 500;
- t['six'] = 500;
- t['seven'] = 500;
- t['eight'] = 500;
- t['nine'] = 500;
- t['colon'] = 278;
- t['semicolon'] = 278;
- t['less'] = 549;
- t['equal'] = 549;
- t['greater'] = 549;
- t['question'] = 444;
- t['congruent'] = 549;
- t['Alpha'] = 722;
- t['Beta'] = 667;
- t['Chi'] = 722;
- t['Delta'] = 612;
- t['Epsilon'] = 611;
- t['Phi'] = 763;
- t['Gamma'] = 603;
- t['Eta'] = 722;
- t['Iota'] = 333;
- t['theta1'] = 631;
- t['Kappa'] = 722;
- t['Lambda'] = 686;
- t['Mu'] = 889;
- t['Nu'] = 722;
- t['Omicron'] = 722;
- t['Pi'] = 768;
- t['Theta'] = 741;
- t['Rho'] = 556;
- t['Sigma'] = 592;
- t['Tau'] = 611;
- t['Upsilon'] = 690;
- t['sigma1'] = 439;
- t['Omega'] = 768;
- t['Xi'] = 645;
- t['Psi'] = 795;
- t['Zeta'] = 611;
- t['bracketleft'] = 333;
- t['therefore'] = 863;
- t['bracketright'] = 333;
- t['perpendicular'] = 658;
- t['underscore'] = 500;
- t['radicalex'] = 500;
- t['alpha'] = 631;
- t['beta'] = 549;
- t['chi'] = 549;
- t['delta'] = 494;
- t['epsilon'] = 439;
- t['phi'] = 521;
- t['gamma'] = 411;
- t['eta'] = 603;
- t['iota'] = 329;
- t['phi1'] = 603;
- t['kappa'] = 549;
- t['lambda'] = 549;
- t['mu'] = 576;
- t['nu'] = 521;
- t['omicron'] = 549;
- t['pi'] = 549;
- t['theta'] = 521;
- t['rho'] = 549;
- t['sigma'] = 603;
- t['tau'] = 439;
- t['upsilon'] = 576;
- t['omega1'] = 713;
- t['omega'] = 686;
- t['xi'] = 493;
- t['psi'] = 686;
- t['zeta'] = 494;
- t['braceleft'] = 480;
- t['bar'] = 200;
- t['braceright'] = 480;
- t['similar'] = 549;
- t['Euro'] = 750;
- t['Upsilon1'] = 620;
- t['minute'] = 247;
- t['lessequal'] = 549;
- t['fraction'] = 167;
- t['infinity'] = 713;
- t['florin'] = 500;
- t['club'] = 753;
- t['diamond'] = 753;
- t['heart'] = 753;
- t['spade'] = 753;
- t['arrowboth'] = 1042;
- t['arrowleft'] = 987;
- t['arrowup'] = 603;
- t['arrowright'] = 987;
- t['arrowdown'] = 603;
- t['degree'] = 400;
- t['plusminus'] = 549;
- t['second'] = 411;
- t['greaterequal'] = 549;
- t['multiply'] = 549;
- t['proportional'] = 713;
- t['partialdiff'] = 494;
- t['bullet'] = 460;
- t['divide'] = 549;
- t['notequal'] = 549;
- t['equivalence'] = 549;
- t['approxequal'] = 549;
- t['ellipsis'] = 1000;
- t['arrowvertex'] = 603;
- t['arrowhorizex'] = 1000;
- t['carriagereturn'] = 658;
- t['aleph'] = 823;
- t['Ifraktur'] = 686;
- t['Rfraktur'] = 795;
- t['weierstrass'] = 987;
- t['circlemultiply'] = 768;
- t['circleplus'] = 768;
- t['emptyset'] = 823;
- t['intersection'] = 768;
- t['union'] = 768;
- t['propersuperset'] = 713;
- t['reflexsuperset'] = 713;
- t['notsubset'] = 713;
- t['propersubset'] = 713;
- t['reflexsubset'] = 713;
- t['element'] = 713;
- t['notelement'] = 713;
- t['angle'] = 768;
- t['gradient'] = 713;
- t['registerserif'] = 790;
- t['copyrightserif'] = 790;
- t['trademarkserif'] = 890;
- t['product'] = 823;
- t['radical'] = 549;
- t['dotmath'] = 250;
- t['logicalnot'] = 713;
- t['logicaland'] = 603;
- t['logicalor'] = 603;
- t['arrowdblboth'] = 1042;
- t['arrowdblleft'] = 987;
- t['arrowdblup'] = 603;
- t['arrowdblright'] = 987;
- t['arrowdbldown'] = 603;
- t['lozenge'] = 494;
- t['angleleft'] = 329;
- t['registersans'] = 790;
- t['copyrightsans'] = 790;
- t['trademarksans'] = 786;
- t['summation'] = 713;
- t['parenlefttp'] = 384;
- t['parenleftex'] = 384;
- t['parenleftbt'] = 384;
- t['bracketlefttp'] = 384;
- t['bracketleftex'] = 384;
- t['bracketleftbt'] = 384;
- t['bracelefttp'] = 494;
- t['braceleftmid'] = 494;
- t['braceleftbt'] = 494;
- t['braceex'] = 494;
- t['angleright'] = 329;
- t['integral'] = 274;
- t['integraltp'] = 686;
- t['integralex'] = 686;
- t['integralbt'] = 686;
- t['parenrighttp'] = 384;
- t['parenrightex'] = 384;
- t['parenrightbt'] = 384;
- t['bracketrighttp'] = 384;
- t['bracketrightex'] = 384;
- t['bracketrightbt'] = 384;
- t['bracerighttp'] = 494;
- t['bracerightmid'] = 494;
- t['bracerightbt'] = 494;
- t['apple'] = 790;
- });
- t['Times-Roman'] = (0, _util.getLookupTableFactory)(function (t) {
- t['space'] = 250;
- t['exclam'] = 333;
- t['quotedbl'] = 408;
- t['numbersign'] = 500;
- t['dollar'] = 500;
- t['percent'] = 833;
- t['ampersand'] = 778;
- t['quoteright'] = 333;
- t['parenleft'] = 333;
- t['parenright'] = 333;
- t['asterisk'] = 500;
- t['plus'] = 564;
- t['comma'] = 250;
- t['hyphen'] = 333;
- t['period'] = 250;
- t['slash'] = 278;
- t['zero'] = 500;
- t['one'] = 500;
- t['two'] = 500;
- t['three'] = 500;
- t['four'] = 500;
- t['five'] = 500;
- t['six'] = 500;
- t['seven'] = 500;
- t['eight'] = 500;
- t['nine'] = 500;
- t['colon'] = 278;
- t['semicolon'] = 278;
- t['less'] = 564;
- t['equal'] = 564;
- t['greater'] = 564;
- t['question'] = 444;
- t['at'] = 921;
- t['A'] = 722;
- t['B'] = 667;
- t['C'] = 667;
- t['D'] = 722;
- t['E'] = 611;
- t['F'] = 556;
- t['G'] = 722;
- t['H'] = 722;
- t['I'] = 333;
- t['J'] = 389;
- t['K'] = 722;
- t['L'] = 611;
- t['M'] = 889;
- t['N'] = 722;
- t['O'] = 722;
- t['P'] = 556;
- t['Q'] = 722;
- t['R'] = 667;
- t['S'] = 556;
- t['T'] = 611;
- t['U'] = 722;
- t['V'] = 722;
- t['W'] = 944;
- t['X'] = 722;
- t['Y'] = 722;
- t['Z'] = 611;
- t['bracketleft'] = 333;
- t['backslash'] = 278;
- t['bracketright'] = 333;
- t['asciicircum'] = 469;
- t['underscore'] = 500;
- t['quoteleft'] = 333;
- t['a'] = 444;
- t['b'] = 500;
- t['c'] = 444;
- t['d'] = 500;
- t['e'] = 444;
- t['f'] = 333;
- t['g'] = 500;
- t['h'] = 500;
- t['i'] = 278;
- t['j'] = 278;
- t['k'] = 500;
- t['l'] = 278;
- t['m'] = 778;
- t['n'] = 500;
- t['o'] = 500;
- t['p'] = 500;
- t['q'] = 500;
- t['r'] = 333;
- t['s'] = 389;
- t['t'] = 278;
- t['u'] = 500;
- t['v'] = 500;
- t['w'] = 722;
- t['x'] = 500;
- t['y'] = 500;
- t['z'] = 444;
- t['braceleft'] = 480;
- t['bar'] = 200;
- t['braceright'] = 480;
- t['asciitilde'] = 541;
- t['exclamdown'] = 333;
- t['cent'] = 500;
- t['sterling'] = 500;
- t['fraction'] = 167;
- t['yen'] = 500;
- t['florin'] = 500;
- t['section'] = 500;
- t['currency'] = 500;
- t['quotesingle'] = 180;
- t['quotedblleft'] = 444;
- t['guillemotleft'] = 500;
- t['guilsinglleft'] = 333;
- t['guilsinglright'] = 333;
- t['fi'] = 556;
- t['fl'] = 556;
- t['endash'] = 500;
- t['dagger'] = 500;
- t['daggerdbl'] = 500;
- t['periodcentered'] = 250;
- t['paragraph'] = 453;
- t['bullet'] = 350;
- t['quotesinglbase'] = 333;
- t['quotedblbase'] = 444;
- t['quotedblright'] = 444;
- t['guillemotright'] = 500;
- t['ellipsis'] = 1000;
- t['perthousand'] = 1000;
- t['questiondown'] = 444;
- t['grave'] = 333;
- t['acute'] = 333;
- t['circumflex'] = 333;
- t['tilde'] = 333;
- t['macron'] = 333;
- t['breve'] = 333;
- t['dotaccent'] = 333;
- t['dieresis'] = 333;
- t['ring'] = 333;
- t['cedilla'] = 333;
- t['hungarumlaut'] = 333;
- t['ogonek'] = 333;
- t['caron'] = 333;
- t['emdash'] = 1000;
- t['AE'] = 889;
- t['ordfeminine'] = 276;
- t['Lslash'] = 611;
- t['Oslash'] = 722;
- t['OE'] = 889;
- t['ordmasculine'] = 310;
- t['ae'] = 667;
- t['dotlessi'] = 278;
- t['lslash'] = 278;
- t['oslash'] = 500;
- t['oe'] = 722;
- t['germandbls'] = 500;
- t['Idieresis'] = 333;
- t['eacute'] = 444;
- t['abreve'] = 444;
- t['uhungarumlaut'] = 500;
- t['ecaron'] = 444;
- t['Ydieresis'] = 722;
- t['divide'] = 564;
- t['Yacute'] = 722;
- t['Acircumflex'] = 722;
- t['aacute'] = 444;
- t['Ucircumflex'] = 722;
- t['yacute'] = 500;
- t['scommaaccent'] = 389;
- t['ecircumflex'] = 444;
- t['Uring'] = 722;
- t['Udieresis'] = 722;
- t['aogonek'] = 444;
- t['Uacute'] = 722;
- t['uogonek'] = 500;
- t['Edieresis'] = 611;
- t['Dcroat'] = 722;
- t['commaaccent'] = 250;
- t['copyright'] = 760;
- t['Emacron'] = 611;
- t['ccaron'] = 444;
- t['aring'] = 444;
- t['Ncommaaccent'] = 722;
- t['lacute'] = 278;
- t['agrave'] = 444;
- t['Tcommaaccent'] = 611;
- t['Cacute'] = 667;
- t['atilde'] = 444;
- t['Edotaccent'] = 611;
- t['scaron'] = 389;
- t['scedilla'] = 389;
- t['iacute'] = 278;
- t['lozenge'] = 471;
- t['Rcaron'] = 667;
- t['Gcommaaccent'] = 722;
- t['ucircumflex'] = 500;
- t['acircumflex'] = 444;
- t['Amacron'] = 722;
- t['rcaron'] = 333;
- t['ccedilla'] = 444;
- t['Zdotaccent'] = 611;
- t['Thorn'] = 556;
- t['Omacron'] = 722;
- t['Racute'] = 667;
- t['Sacute'] = 556;
- t['dcaron'] = 588;
- t['Umacron'] = 722;
- t['uring'] = 500;
- t['threesuperior'] = 300;
- t['Ograve'] = 722;
- t['Agrave'] = 722;
- t['Abreve'] = 722;
- t['multiply'] = 564;
- t['uacute'] = 500;
- t['Tcaron'] = 611;
- t['partialdiff'] = 476;
- t['ydieresis'] = 500;
- t['Nacute'] = 722;
- t['icircumflex'] = 278;
- t['Ecircumflex'] = 611;
- t['adieresis'] = 444;
- t['edieresis'] = 444;
- t['cacute'] = 444;
- t['nacute'] = 500;
- t['umacron'] = 500;
- t['Ncaron'] = 722;
- t['Iacute'] = 333;
- t['plusminus'] = 564;
- t['brokenbar'] = 200;
- t['registered'] = 760;
- t['Gbreve'] = 722;
- t['Idotaccent'] = 333;
- t['summation'] = 600;
- t['Egrave'] = 611;
- t['racute'] = 333;
- t['omacron'] = 500;
- t['Zacute'] = 611;
- t['Zcaron'] = 611;
- t['greaterequal'] = 549;
- t['Eth'] = 722;
- t['Ccedilla'] = 667;
- t['lcommaaccent'] = 278;
- t['tcaron'] = 326;
- t['eogonek'] = 444;
- t['Uogonek'] = 722;
- t['Aacute'] = 722;
- t['Adieresis'] = 722;
- t['egrave'] = 444;
- t['zacute'] = 444;
- t['iogonek'] = 278;
- t['Oacute'] = 722;
- t['oacute'] = 500;
- t['amacron'] = 444;
- t['sacute'] = 389;
- t['idieresis'] = 278;
- t['Ocircumflex'] = 722;
- t['Ugrave'] = 722;
- t['Delta'] = 612;
- t['thorn'] = 500;
- t['twosuperior'] = 300;
- t['Odieresis'] = 722;
- t['mu'] = 500;
- t['igrave'] = 278;
- t['ohungarumlaut'] = 500;
- t['Eogonek'] = 611;
- t['dcroat'] = 500;
- t['threequarters'] = 750;
- t['Scedilla'] = 556;
- t['lcaron'] = 344;
- t['Kcommaaccent'] = 722;
- t['Lacute'] = 611;
- t['trademark'] = 980;
- t['edotaccent'] = 444;
- t['Igrave'] = 333;
- t['Imacron'] = 333;
- t['Lcaron'] = 611;
- t['onehalf'] = 750;
- t['lessequal'] = 549;
- t['ocircumflex'] = 500;
- t['ntilde'] = 500;
- t['Uhungarumlaut'] = 722;
- t['Eacute'] = 611;
- t['emacron'] = 444;
- t['gbreve'] = 500;
- t['onequarter'] = 750;
- t['Scaron'] = 556;
- t['Scommaaccent'] = 556;
- t['Ohungarumlaut'] = 722;
- t['degree'] = 400;
- t['ograve'] = 500;
- t['Ccaron'] = 667;
- t['ugrave'] = 500;
- t['radical'] = 453;
- t['Dcaron'] = 722;
- t['rcommaaccent'] = 333;
- t['Ntilde'] = 722;
- t['otilde'] = 500;
- t['Rcommaaccent'] = 667;
- t['Lcommaaccent'] = 611;
- t['Atilde'] = 722;
- t['Aogonek'] = 722;
- t['Aring'] = 722;
- t['Otilde'] = 722;
- t['zdotaccent'] = 444;
- t['Ecaron'] = 611;
- t['Iogonek'] = 333;
- t['kcommaaccent'] = 500;
- t['minus'] = 564;
- t['Icircumflex'] = 333;
- t['ncaron'] = 500;
- t['tcommaaccent'] = 278;
- t['logicalnot'] = 564;
- t['odieresis'] = 500;
- t['udieresis'] = 500;
- t['notequal'] = 549;
- t['gcommaaccent'] = 500;
- t['eth'] = 500;
- t['zcaron'] = 444;
- t['ncommaaccent'] = 500;
- t['onesuperior'] = 300;
- t['imacron'] = 278;
- t['Euro'] = 500;
- });
- t['Times-Bold'] = (0, _util.getLookupTableFactory)(function (t) {
- t['space'] = 250;
- t['exclam'] = 333;
- t['quotedbl'] = 555;
- t['numbersign'] = 500;
- t['dollar'] = 500;
- t['percent'] = 1000;
- t['ampersand'] = 833;
- t['quoteright'] = 333;
- t['parenleft'] = 333;
- t['parenright'] = 333;
- t['asterisk'] = 500;
- t['plus'] = 570;
- t['comma'] = 250;
- t['hyphen'] = 333;
- t['period'] = 250;
- t['slash'] = 278;
- t['zero'] = 500;
- t['one'] = 500;
- t['two'] = 500;
- t['three'] = 500;
- t['four'] = 500;
- t['five'] = 500;
- t['six'] = 500;
- t['seven'] = 500;
- t['eight'] = 500;
- t['nine'] = 500;
- t['colon'] = 333;
- t['semicolon'] = 333;
- t['less'] = 570;
- t['equal'] = 570;
- t['greater'] = 570;
- t['question'] = 500;
- t['at'] = 930;
- t['A'] = 722;
- t['B'] = 667;
- t['C'] = 722;
- t['D'] = 722;
- t['E'] = 667;
- t['F'] = 611;
- t['G'] = 778;
- t['H'] = 778;
- t['I'] = 389;
- t['J'] = 500;
- t['K'] = 778;
- t['L'] = 667;
- t['M'] = 944;
- t['N'] = 722;
- t['O'] = 778;
- t['P'] = 611;
- t['Q'] = 778;
- t['R'] = 722;
- t['S'] = 556;
- t['T'] = 667;
- t['U'] = 722;
- t['V'] = 722;
- t['W'] = 1000;
- t['X'] = 722;
- t['Y'] = 722;
- t['Z'] = 667;
- t['bracketleft'] = 333;
- t['backslash'] = 278;
- t['bracketright'] = 333;
- t['asciicircum'] = 581;
- t['underscore'] = 500;
- t['quoteleft'] = 333;
- t['a'] = 500;
- t['b'] = 556;
- t['c'] = 444;
- t['d'] = 556;
- t['e'] = 444;
- t['f'] = 333;
- t['g'] = 500;
- t['h'] = 556;
- t['i'] = 278;
- t['j'] = 333;
- t['k'] = 556;
- t['l'] = 278;
- t['m'] = 833;
- t['n'] = 556;
- t['o'] = 500;
- t['p'] = 556;
- t['q'] = 556;
- t['r'] = 444;
- t['s'] = 389;
- t['t'] = 333;
- t['u'] = 556;
- t['v'] = 500;
- t['w'] = 722;
- t['x'] = 500;
- t['y'] = 500;
- t['z'] = 444;
- t['braceleft'] = 394;
- t['bar'] = 220;
- t['braceright'] = 394;
- t['asciitilde'] = 520;
- t['exclamdown'] = 333;
- t['cent'] = 500;
- t['sterling'] = 500;
- t['fraction'] = 167;
- t['yen'] = 500;
- t['florin'] = 500;
- t['section'] = 500;
- t['currency'] = 500;
- t['quotesingle'] = 278;
- t['quotedblleft'] = 500;
- t['guillemotleft'] = 500;
- t['guilsinglleft'] = 333;
- t['guilsinglright'] = 333;
- t['fi'] = 556;
- t['fl'] = 556;
- t['endash'] = 500;
- t['dagger'] = 500;
- t['daggerdbl'] = 500;
- t['periodcentered'] = 250;
- t['paragraph'] = 540;
- t['bullet'] = 350;
- t['quotesinglbase'] = 333;
- t['quotedblbase'] = 500;
- t['quotedblright'] = 500;
- t['guillemotright'] = 500;
- t['ellipsis'] = 1000;
- t['perthousand'] = 1000;
- t['questiondown'] = 500;
- t['grave'] = 333;
- t['acute'] = 333;
- t['circumflex'] = 333;
- t['tilde'] = 333;
- t['macron'] = 333;
- t['breve'] = 333;
- t['dotaccent'] = 333;
- t['dieresis'] = 333;
- t['ring'] = 333;
- t['cedilla'] = 333;
- t['hungarumlaut'] = 333;
- t['ogonek'] = 333;
- t['caron'] = 333;
- t['emdash'] = 1000;
- t['AE'] = 1000;
- t['ordfeminine'] = 300;
- t['Lslash'] = 667;
- t['Oslash'] = 778;
- t['OE'] = 1000;
- t['ordmasculine'] = 330;
- t['ae'] = 722;
- t['dotlessi'] = 278;
- t['lslash'] = 278;
- t['oslash'] = 500;
- t['oe'] = 722;
- t['germandbls'] = 556;
- t['Idieresis'] = 389;
- t['eacute'] = 444;
- t['abreve'] = 500;
- t['uhungarumlaut'] = 556;
- t['ecaron'] = 444;
- t['Ydieresis'] = 722;
- t['divide'] = 570;
- t['Yacute'] = 722;
- t['Acircumflex'] = 722;
- t['aacute'] = 500;
- t['Ucircumflex'] = 722;
- t['yacute'] = 500;
- t['scommaaccent'] = 389;
- t['ecircumflex'] = 444;
- t['Uring'] = 722;
- t['Udieresis'] = 722;
- t['aogonek'] = 500;
- t['Uacute'] = 722;
- t['uogonek'] = 556;
- t['Edieresis'] = 667;
- t['Dcroat'] = 722;
- t['commaaccent'] = 250;
- t['copyright'] = 747;
- t['Emacron'] = 667;
- t['ccaron'] = 444;
- t['aring'] = 500;
- t['Ncommaaccent'] = 722;
- t['lacute'] = 278;
- t['agrave'] = 500;
- t['Tcommaaccent'] = 667;
- t['Cacute'] = 722;
- t['atilde'] = 500;
- t['Edotaccent'] = 667;
- t['scaron'] = 389;
- t['scedilla'] = 389;
- t['iacute'] = 278;
- t['lozenge'] = 494;
- t['Rcaron'] = 722;
- t['Gcommaaccent'] = 778;
- t['ucircumflex'] = 556;
- t['acircumflex'] = 500;
- t['Amacron'] = 722;
- t['rcaron'] = 444;
- t['ccedilla'] = 444;
- t['Zdotaccent'] = 667;
- t['Thorn'] = 611;
- t['Omacron'] = 778;
- t['Racute'] = 722;
- t['Sacute'] = 556;
- t['dcaron'] = 672;
- t['Umacron'] = 722;
- t['uring'] = 556;
- t['threesuperior'] = 300;
- t['Ograve'] = 778;
- t['Agrave'] = 722;
- t['Abreve'] = 722;
- t['multiply'] = 570;
- t['uacute'] = 556;
- t['Tcaron'] = 667;
- t['partialdiff'] = 494;
- t['ydieresis'] = 500;
- t['Nacute'] = 722;
- t['icircumflex'] = 278;
- t['Ecircumflex'] = 667;
- t['adieresis'] = 500;
- t['edieresis'] = 444;
- t['cacute'] = 444;
- t['nacute'] = 556;
- t['umacron'] = 556;
- t['Ncaron'] = 722;
- t['Iacute'] = 389;
- t['plusminus'] = 570;
- t['brokenbar'] = 220;
- t['registered'] = 747;
- t['Gbreve'] = 778;
- t['Idotaccent'] = 389;
- t['summation'] = 600;
- t['Egrave'] = 667;
- t['racute'] = 444;
- t['omacron'] = 500;
- t['Zacute'] = 667;
- t['Zcaron'] = 667;
- t['greaterequal'] = 549;
- t['Eth'] = 722;
- t['Ccedilla'] = 722;
- t['lcommaaccent'] = 278;
- t['tcaron'] = 416;
- t['eogonek'] = 444;
- t['Uogonek'] = 722;
- t['Aacute'] = 722;
- t['Adieresis'] = 722;
- t['egrave'] = 444;
- t['zacute'] = 444;
- t['iogonek'] = 278;
- t['Oacute'] = 778;
- t['oacute'] = 500;
- t['amacron'] = 500;
- t['sacute'] = 389;
- t['idieresis'] = 278;
- t['Ocircumflex'] = 778;
- t['Ugrave'] = 722;
- t['Delta'] = 612;
- t['thorn'] = 556;
- t['twosuperior'] = 300;
- t['Odieresis'] = 778;
- t['mu'] = 556;
- t['igrave'] = 278;
- t['ohungarumlaut'] = 500;
- t['Eogonek'] = 667;
- t['dcroat'] = 556;
- t['threequarters'] = 750;
- t['Scedilla'] = 556;
- t['lcaron'] = 394;
- t['Kcommaaccent'] = 778;
- t['Lacute'] = 667;
- t['trademark'] = 1000;
- t['edotaccent'] = 444;
- t['Igrave'] = 389;
- t['Imacron'] = 389;
- t['Lcaron'] = 667;
- t['onehalf'] = 750;
- t['lessequal'] = 549;
- t['ocircumflex'] = 500;
- t['ntilde'] = 556;
- t['Uhungarumlaut'] = 722;
- t['Eacute'] = 667;
- t['emacron'] = 444;
- t['gbreve'] = 500;
- t['onequarter'] = 750;
- t['Scaron'] = 556;
- t['Scommaaccent'] = 556;
- t['Ohungarumlaut'] = 778;
- t['degree'] = 400;
- t['ograve'] = 500;
- t['Ccaron'] = 722;
- t['ugrave'] = 556;
- t['radical'] = 549;
- t['Dcaron'] = 722;
- t['rcommaaccent'] = 444;
- t['Ntilde'] = 722;
- t['otilde'] = 500;
- t['Rcommaaccent'] = 722;
- t['Lcommaaccent'] = 667;
- t['Atilde'] = 722;
- t['Aogonek'] = 722;
- t['Aring'] = 722;
- t['Otilde'] = 778;
- t['zdotaccent'] = 444;
- t['Ecaron'] = 667;
- t['Iogonek'] = 389;
- t['kcommaaccent'] = 556;
- t['minus'] = 570;
- t['Icircumflex'] = 389;
- t['ncaron'] = 556;
- t['tcommaaccent'] = 333;
- t['logicalnot'] = 570;
- t['odieresis'] = 500;
- t['udieresis'] = 556;
- t['notequal'] = 549;
- t['gcommaaccent'] = 500;
- t['eth'] = 500;
- t['zcaron'] = 444;
- t['ncommaaccent'] = 556;
- t['onesuperior'] = 300;
- t['imacron'] = 278;
- t['Euro'] = 500;
- });
- t['Times-BoldItalic'] = (0, _util.getLookupTableFactory)(function (t) {
- t['space'] = 250;
- t['exclam'] = 389;
- t['quotedbl'] = 555;
- t['numbersign'] = 500;
- t['dollar'] = 500;
- t['percent'] = 833;
- t['ampersand'] = 778;
- t['quoteright'] = 333;
- t['parenleft'] = 333;
- t['parenright'] = 333;
- t['asterisk'] = 500;
- t['plus'] = 570;
- t['comma'] = 250;
- t['hyphen'] = 333;
- t['period'] = 250;
- t['slash'] = 278;
- t['zero'] = 500;
- t['one'] = 500;
- t['two'] = 500;
- t['three'] = 500;
- t['four'] = 500;
- t['five'] = 500;
- t['six'] = 500;
- t['seven'] = 500;
- t['eight'] = 500;
- t['nine'] = 500;
- t['colon'] = 333;
- t['semicolon'] = 333;
- t['less'] = 570;
- t['equal'] = 570;
- t['greater'] = 570;
- t['question'] = 500;
- t['at'] = 832;
- t['A'] = 667;
- t['B'] = 667;
- t['C'] = 667;
- t['D'] = 722;
- t['E'] = 667;
- t['F'] = 667;
- t['G'] = 722;
- t['H'] = 778;
- t['I'] = 389;
- t['J'] = 500;
- t['K'] = 667;
- t['L'] = 611;
- t['M'] = 889;
- t['N'] = 722;
- t['O'] = 722;
- t['P'] = 611;
- t['Q'] = 722;
- t['R'] = 667;
- t['S'] = 556;
- t['T'] = 611;
- t['U'] = 722;
- t['V'] = 667;
- t['W'] = 889;
- t['X'] = 667;
- t['Y'] = 611;
- t['Z'] = 611;
- t['bracketleft'] = 333;
- t['backslash'] = 278;
- t['bracketright'] = 333;
- t['asciicircum'] = 570;
- t['underscore'] = 500;
- t['quoteleft'] = 333;
- t['a'] = 500;
- t['b'] = 500;
- t['c'] = 444;
- t['d'] = 500;
- t['e'] = 444;
- t['f'] = 333;
- t['g'] = 500;
- t['h'] = 556;
- t['i'] = 278;
- t['j'] = 278;
- t['k'] = 500;
- t['l'] = 278;
- t['m'] = 778;
- t['n'] = 556;
- t['o'] = 500;
- t['p'] = 500;
- t['q'] = 500;
- t['r'] = 389;
- t['s'] = 389;
- t['t'] = 278;
- t['u'] = 556;
- t['v'] = 444;
- t['w'] = 667;
- t['x'] = 500;
- t['y'] = 444;
- t['z'] = 389;
- t['braceleft'] = 348;
- t['bar'] = 220;
- t['braceright'] = 348;
- t['asciitilde'] = 570;
- t['exclamdown'] = 389;
- t['cent'] = 500;
- t['sterling'] = 500;
- t['fraction'] = 167;
- t['yen'] = 500;
- t['florin'] = 500;
- t['section'] = 500;
- t['currency'] = 500;
- t['quotesingle'] = 278;
- t['quotedblleft'] = 500;
- t['guillemotleft'] = 500;
- t['guilsinglleft'] = 333;
- t['guilsinglright'] = 333;
- t['fi'] = 556;
- t['fl'] = 556;
- t['endash'] = 500;
- t['dagger'] = 500;
- t['daggerdbl'] = 500;
- t['periodcentered'] = 250;
- t['paragraph'] = 500;
- t['bullet'] = 350;
- t['quotesinglbase'] = 333;
- t['quotedblbase'] = 500;
- t['quotedblright'] = 500;
- t['guillemotright'] = 500;
- t['ellipsis'] = 1000;
- t['perthousand'] = 1000;
- t['questiondown'] = 500;
- t['grave'] = 333;
- t['acute'] = 333;
- t['circumflex'] = 333;
- t['tilde'] = 333;
- t['macron'] = 333;
- t['breve'] = 333;
- t['dotaccent'] = 333;
- t['dieresis'] = 333;
- t['ring'] = 333;
- t['cedilla'] = 333;
- t['hungarumlaut'] = 333;
- t['ogonek'] = 333;
- t['caron'] = 333;
- t['emdash'] = 1000;
- t['AE'] = 944;
- t['ordfeminine'] = 266;
- t['Lslash'] = 611;
- t['Oslash'] = 722;
- t['OE'] = 944;
- t['ordmasculine'] = 300;
- t['ae'] = 722;
- t['dotlessi'] = 278;
- t['lslash'] = 278;
- t['oslash'] = 500;
- t['oe'] = 722;
- t['germandbls'] = 500;
- t['Idieresis'] = 389;
- t['eacute'] = 444;
- t['abreve'] = 500;
- t['uhungarumlaut'] = 556;
- t['ecaron'] = 444;
- t['Ydieresis'] = 611;
- t['divide'] = 570;
- t['Yacute'] = 611;
- t['Acircumflex'] = 667;
- t['aacute'] = 500;
- t['Ucircumflex'] = 722;
- t['yacute'] = 444;
- t['scommaaccent'] = 389;
- t['ecircumflex'] = 444;
- t['Uring'] = 722;
- t['Udieresis'] = 722;
- t['aogonek'] = 500;
- t['Uacute'] = 722;
- t['uogonek'] = 556;
- t['Edieresis'] = 667;
- t['Dcroat'] = 722;
- t['commaaccent'] = 250;
- t['copyright'] = 747;
- t['Emacron'] = 667;
- t['ccaron'] = 444;
- t['aring'] = 500;
- t['Ncommaaccent'] = 722;
- t['lacute'] = 278;
- t['agrave'] = 500;
- t['Tcommaaccent'] = 611;
- t['Cacute'] = 667;
- t['atilde'] = 500;
- t['Edotaccent'] = 667;
- t['scaron'] = 389;
- t['scedilla'] = 389;
- t['iacute'] = 278;
- t['lozenge'] = 494;
- t['Rcaron'] = 667;
- t['Gcommaaccent'] = 722;
- t['ucircumflex'] = 556;
- t['acircumflex'] = 500;
- t['Amacron'] = 667;
- t['rcaron'] = 389;
- t['ccedilla'] = 444;
- t['Zdotaccent'] = 611;
- t['Thorn'] = 611;
- t['Omacron'] = 722;
- t['Racute'] = 667;
- t['Sacute'] = 556;
- t['dcaron'] = 608;
- t['Umacron'] = 722;
- t['uring'] = 556;
- t['threesuperior'] = 300;
- t['Ograve'] = 722;
- t['Agrave'] = 667;
- t['Abreve'] = 667;
- t['multiply'] = 570;
- t['uacute'] = 556;
- t['Tcaron'] = 611;
- t['partialdiff'] = 494;
- t['ydieresis'] = 444;
- t['Nacute'] = 722;
- t['icircumflex'] = 278;
- t['Ecircumflex'] = 667;
- t['adieresis'] = 500;
- t['edieresis'] = 444;
- t['cacute'] = 444;
- t['nacute'] = 556;
- t['umacron'] = 556;
- t['Ncaron'] = 722;
- t['Iacute'] = 389;
- t['plusminus'] = 570;
- t['brokenbar'] = 220;
- t['registered'] = 747;
- t['Gbreve'] = 722;
- t['Idotaccent'] = 389;
- t['summation'] = 600;
- t['Egrave'] = 667;
- t['racute'] = 389;
- t['omacron'] = 500;
- t['Zacute'] = 611;
- t['Zcaron'] = 611;
- t['greaterequal'] = 549;
- t['Eth'] = 722;
- t['Ccedilla'] = 667;
- t['lcommaaccent'] = 278;
- t['tcaron'] = 366;
- t['eogonek'] = 444;
- t['Uogonek'] = 722;
- t['Aacute'] = 667;
- t['Adieresis'] = 667;
- t['egrave'] = 444;
- t['zacute'] = 389;
- t['iogonek'] = 278;
- t['Oacute'] = 722;
- t['oacute'] = 500;
- t['amacron'] = 500;
- t['sacute'] = 389;
- t['idieresis'] = 278;
- t['Ocircumflex'] = 722;
- t['Ugrave'] = 722;
- t['Delta'] = 612;
- t['thorn'] = 500;
- t['twosuperior'] = 300;
- t['Odieresis'] = 722;
- t['mu'] = 576;
- t['igrave'] = 278;
- t['ohungarumlaut'] = 500;
- t['Eogonek'] = 667;
- t['dcroat'] = 500;
- t['threequarters'] = 750;
- t['Scedilla'] = 556;
- t['lcaron'] = 382;
- t['Kcommaaccent'] = 667;
- t['Lacute'] = 611;
- t['trademark'] = 1000;
- t['edotaccent'] = 444;
- t['Igrave'] = 389;
- t['Imacron'] = 389;
- t['Lcaron'] = 611;
- t['onehalf'] = 750;
- t['lessequal'] = 549;
- t['ocircumflex'] = 500;
- t['ntilde'] = 556;
- t['Uhungarumlaut'] = 722;
- t['Eacute'] = 667;
- t['emacron'] = 444;
- t['gbreve'] = 500;
- t['onequarter'] = 750;
- t['Scaron'] = 556;
- t['Scommaaccent'] = 556;
- t['Ohungarumlaut'] = 722;
- t['degree'] = 400;
- t['ograve'] = 500;
- t['Ccaron'] = 667;
- t['ugrave'] = 556;
- t['radical'] = 549;
- t['Dcaron'] = 722;
- t['rcommaaccent'] = 389;
- t['Ntilde'] = 722;
- t['otilde'] = 500;
- t['Rcommaaccent'] = 667;
- t['Lcommaaccent'] = 611;
- t['Atilde'] = 667;
- t['Aogonek'] = 667;
- t['Aring'] = 667;
- t['Otilde'] = 722;
- t['zdotaccent'] = 389;
- t['Ecaron'] = 667;
- t['Iogonek'] = 389;
- t['kcommaaccent'] = 500;
- t['minus'] = 606;
- t['Icircumflex'] = 389;
- t['ncaron'] = 556;
- t['tcommaaccent'] = 278;
- t['logicalnot'] = 606;
- t['odieresis'] = 500;
- t['udieresis'] = 556;
- t['notequal'] = 549;
- t['gcommaaccent'] = 500;
- t['eth'] = 500;
- t['zcaron'] = 389;
- t['ncommaaccent'] = 556;
- t['onesuperior'] = 300;
- t['imacron'] = 278;
- t['Euro'] = 500;
- });
- t['Times-Italic'] = (0, _util.getLookupTableFactory)(function (t) {
- t['space'] = 250;
- t['exclam'] = 333;
- t['quotedbl'] = 420;
- t['numbersign'] = 500;
- t['dollar'] = 500;
- t['percent'] = 833;
- t['ampersand'] = 778;
- t['quoteright'] = 333;
- t['parenleft'] = 333;
- t['parenright'] = 333;
- t['asterisk'] = 500;
- t['plus'] = 675;
- t['comma'] = 250;
- t['hyphen'] = 333;
- t['period'] = 250;
- t['slash'] = 278;
- t['zero'] = 500;
- t['one'] = 500;
- t['two'] = 500;
- t['three'] = 500;
- t['four'] = 500;
- t['five'] = 500;
- t['six'] = 500;
- t['seven'] = 500;
- t['eight'] = 500;
- t['nine'] = 500;
- t['colon'] = 333;
- t['semicolon'] = 333;
- t['less'] = 675;
- t['equal'] = 675;
- t['greater'] = 675;
- t['question'] = 500;
- t['at'] = 920;
- t['A'] = 611;
- t['B'] = 611;
- t['C'] = 667;
- t['D'] = 722;
- t['E'] = 611;
- t['F'] = 611;
- t['G'] = 722;
- t['H'] = 722;
- t['I'] = 333;
- t['J'] = 444;
- t['K'] = 667;
- t['L'] = 556;
- t['M'] = 833;
- t['N'] = 667;
- t['O'] = 722;
- t['P'] = 611;
- t['Q'] = 722;
- t['R'] = 611;
- t['S'] = 500;
- t['T'] = 556;
- t['U'] = 722;
- t['V'] = 611;
- t['W'] = 833;
- t['X'] = 611;
- t['Y'] = 556;
- t['Z'] = 556;
- t['bracketleft'] = 389;
- t['backslash'] = 278;
- t['bracketright'] = 389;
- t['asciicircum'] = 422;
- t['underscore'] = 500;
- t['quoteleft'] = 333;
- t['a'] = 500;
- t['b'] = 500;
- t['c'] = 444;
- t['d'] = 500;
- t['e'] = 444;
- t['f'] = 278;
- t['g'] = 500;
- t['h'] = 500;
- t['i'] = 278;
- t['j'] = 278;
- t['k'] = 444;
- t['l'] = 278;
- t['m'] = 722;
- t['n'] = 500;
- t['o'] = 500;
- t['p'] = 500;
- t['q'] = 500;
- t['r'] = 389;
- t['s'] = 389;
- t['t'] = 278;
- t['u'] = 500;
- t['v'] = 444;
- t['w'] = 667;
- t['x'] = 444;
- t['y'] = 444;
- t['z'] = 389;
- t['braceleft'] = 400;
- t['bar'] = 275;
- t['braceright'] = 400;
- t['asciitilde'] = 541;
- t['exclamdown'] = 389;
- t['cent'] = 500;
- t['sterling'] = 500;
- t['fraction'] = 167;
- t['yen'] = 500;
- t['florin'] = 500;
- t['section'] = 500;
- t['currency'] = 500;
- t['quotesingle'] = 214;
- t['quotedblleft'] = 556;
- t['guillemotleft'] = 500;
- t['guilsinglleft'] = 333;
- t['guilsinglright'] = 333;
- t['fi'] = 500;
- t['fl'] = 500;
- t['endash'] = 500;
- t['dagger'] = 500;
- t['daggerdbl'] = 500;
- t['periodcentered'] = 250;
- t['paragraph'] = 523;
- t['bullet'] = 350;
- t['quotesinglbase'] = 333;
- t['quotedblbase'] = 556;
- t['quotedblright'] = 556;
- t['guillemotright'] = 500;
- t['ellipsis'] = 889;
- t['perthousand'] = 1000;
- t['questiondown'] = 500;
- t['grave'] = 333;
- t['acute'] = 333;
- t['circumflex'] = 333;
- t['tilde'] = 333;
- t['macron'] = 333;
- t['breve'] = 333;
- t['dotaccent'] = 333;
- t['dieresis'] = 333;
- t['ring'] = 333;
- t['cedilla'] = 333;
- t['hungarumlaut'] = 333;
- t['ogonek'] = 333;
- t['caron'] = 333;
- t['emdash'] = 889;
- t['AE'] = 889;
- t['ordfeminine'] = 276;
- t['Lslash'] = 556;
- t['Oslash'] = 722;
- t['OE'] = 944;
- t['ordmasculine'] = 310;
- t['ae'] = 667;
- t['dotlessi'] = 278;
- t['lslash'] = 278;
- t['oslash'] = 500;
- t['oe'] = 667;
- t['germandbls'] = 500;
- t['Idieresis'] = 333;
- t['eacute'] = 444;
- t['abreve'] = 500;
- t['uhungarumlaut'] = 500;
- t['ecaron'] = 444;
- t['Ydieresis'] = 556;
- t['divide'] = 675;
- t['Yacute'] = 556;
- t['Acircumflex'] = 611;
- t['aacute'] = 500;
- t['Ucircumflex'] = 722;
- t['yacute'] = 444;
- t['scommaaccent'] = 389;
- t['ecircumflex'] = 444;
- t['Uring'] = 722;
- t['Udieresis'] = 722;
- t['aogonek'] = 500;
- t['Uacute'] = 722;
- t['uogonek'] = 500;
- t['Edieresis'] = 611;
- t['Dcroat'] = 722;
- t['commaaccent'] = 250;
- t['copyright'] = 760;
- t['Emacron'] = 611;
- t['ccaron'] = 444;
- t['aring'] = 500;
- t['Ncommaaccent'] = 667;
- t['lacute'] = 278;
- t['agrave'] = 500;
- t['Tcommaaccent'] = 556;
- t['Cacute'] = 667;
- t['atilde'] = 500;
- t['Edotaccent'] = 611;
- t['scaron'] = 389;
- t['scedilla'] = 389;
- t['iacute'] = 278;
- t['lozenge'] = 471;
- t['Rcaron'] = 611;
- t['Gcommaaccent'] = 722;
- t['ucircumflex'] = 500;
- t['acircumflex'] = 500;
- t['Amacron'] = 611;
- t['rcaron'] = 389;
- t['ccedilla'] = 444;
- t['Zdotaccent'] = 556;
- t['Thorn'] = 611;
- t['Omacron'] = 722;
- t['Racute'] = 611;
- t['Sacute'] = 500;
- t['dcaron'] = 544;
- t['Umacron'] = 722;
- t['uring'] = 500;
- t['threesuperior'] = 300;
- t['Ograve'] = 722;
- t['Agrave'] = 611;
- t['Abreve'] = 611;
- t['multiply'] = 675;
- t['uacute'] = 500;
- t['Tcaron'] = 556;
- t['partialdiff'] = 476;
- t['ydieresis'] = 444;
- t['Nacute'] = 667;
- t['icircumflex'] = 278;
- t['Ecircumflex'] = 611;
- t['adieresis'] = 500;
- t['edieresis'] = 444;
- t['cacute'] = 444;
- t['nacute'] = 500;
- t['umacron'] = 500;
- t['Ncaron'] = 667;
- t['Iacute'] = 333;
- t['plusminus'] = 675;
- t['brokenbar'] = 275;
- t['registered'] = 760;
- t['Gbreve'] = 722;
- t['Idotaccent'] = 333;
- t['summation'] = 600;
- t['Egrave'] = 611;
- t['racute'] = 389;
- t['omacron'] = 500;
- t['Zacute'] = 556;
- t['Zcaron'] = 556;
- t['greaterequal'] = 549;
- t['Eth'] = 722;
- t['Ccedilla'] = 667;
- t['lcommaaccent'] = 278;
- t['tcaron'] = 300;
- t['eogonek'] = 444;
- t['Uogonek'] = 722;
- t['Aacute'] = 611;
- t['Adieresis'] = 611;
- t['egrave'] = 444;
- t['zacute'] = 389;
- t['iogonek'] = 278;
- t['Oacute'] = 722;
- t['oacute'] = 500;
- t['amacron'] = 500;
- t['sacute'] = 389;
- t['idieresis'] = 278;
- t['Ocircumflex'] = 722;
- t['Ugrave'] = 722;
- t['Delta'] = 612;
- t['thorn'] = 500;
- t['twosuperior'] = 300;
- t['Odieresis'] = 722;
- t['mu'] = 500;
- t['igrave'] = 278;
- t['ohungarumlaut'] = 500;
- t['Eogonek'] = 611;
- t['dcroat'] = 500;
- t['threequarters'] = 750;
- t['Scedilla'] = 500;
- t['lcaron'] = 300;
- t['Kcommaaccent'] = 667;
- t['Lacute'] = 556;
- t['trademark'] = 980;
- t['edotaccent'] = 444;
- t['Igrave'] = 333;
- t['Imacron'] = 333;
- t['Lcaron'] = 611;
- t['onehalf'] = 750;
- t['lessequal'] = 549;
- t['ocircumflex'] = 500;
- t['ntilde'] = 500;
- t['Uhungarumlaut'] = 722;
- t['Eacute'] = 611;
- t['emacron'] = 444;
- t['gbreve'] = 500;
- t['onequarter'] = 750;
- t['Scaron'] = 500;
- t['Scommaaccent'] = 500;
- t['Ohungarumlaut'] = 722;
- t['degree'] = 400;
- t['ograve'] = 500;
- t['Ccaron'] = 667;
- t['ugrave'] = 500;
- t['radical'] = 453;
- t['Dcaron'] = 722;
- t['rcommaaccent'] = 389;
- t['Ntilde'] = 667;
- t['otilde'] = 500;
- t['Rcommaaccent'] = 611;
- t['Lcommaaccent'] = 556;
- t['Atilde'] = 611;
- t['Aogonek'] = 611;
- t['Aring'] = 611;
- t['Otilde'] = 722;
- t['zdotaccent'] = 389;
- t['Ecaron'] = 611;
- t['Iogonek'] = 333;
- t['kcommaaccent'] = 444;
- t['minus'] = 675;
- t['Icircumflex'] = 333;
- t['ncaron'] = 500;
- t['tcommaaccent'] = 278;
- t['logicalnot'] = 675;
- t['odieresis'] = 500;
- t['udieresis'] = 500;
- t['notequal'] = 549;
- t['gcommaaccent'] = 500;
- t['eth'] = 500;
- t['zcaron'] = 389;
- t['ncommaaccent'] = 500;
- t['onesuperior'] = 300;
- t['imacron'] = 278;
- t['Euro'] = 500;
- });
- t['ZapfDingbats'] = (0, _util.getLookupTableFactory)(function (t) {
- t['space'] = 278;
- t['a1'] = 974;
- t['a2'] = 961;
- t['a202'] = 974;
- t['a3'] = 980;
- t['a4'] = 719;
- t['a5'] = 789;
- t['a119'] = 790;
- t['a118'] = 791;
- t['a117'] = 690;
- t['a11'] = 960;
- t['a12'] = 939;
- t['a13'] = 549;
- t['a14'] = 855;
- t['a15'] = 911;
- t['a16'] = 933;
- t['a105'] = 911;
- t['a17'] = 945;
- t['a18'] = 974;
- t['a19'] = 755;
- t['a20'] = 846;
- t['a21'] = 762;
- t['a22'] = 761;
- t['a23'] = 571;
- t['a24'] = 677;
- t['a25'] = 763;
- t['a26'] = 760;
- t['a27'] = 759;
- t['a28'] = 754;
- t['a6'] = 494;
- t['a7'] = 552;
- t['a8'] = 537;
- t['a9'] = 577;
- t['a10'] = 692;
- t['a29'] = 786;
- t['a30'] = 788;
- t['a31'] = 788;
- t['a32'] = 790;
- t['a33'] = 793;
- t['a34'] = 794;
- t['a35'] = 816;
- t['a36'] = 823;
- t['a37'] = 789;
- t['a38'] = 841;
- t['a39'] = 823;
- t['a40'] = 833;
- t['a41'] = 816;
- t['a42'] = 831;
- t['a43'] = 923;
- t['a44'] = 744;
- t['a45'] = 723;
- t['a46'] = 749;
- t['a47'] = 790;
- t['a48'] = 792;
- t['a49'] = 695;
- t['a50'] = 776;
- t['a51'] = 768;
- t['a52'] = 792;
- t['a53'] = 759;
- t['a54'] = 707;
- t['a55'] = 708;
- t['a56'] = 682;
- t['a57'] = 701;
- t['a58'] = 826;
- t['a59'] = 815;
- t['a60'] = 789;
- t['a61'] = 789;
- t['a62'] = 707;
- t['a63'] = 687;
- t['a64'] = 696;
- t['a65'] = 689;
- t['a66'] = 786;
- t['a67'] = 787;
- t['a68'] = 713;
- t['a69'] = 791;
- t['a70'] = 785;
- t['a71'] = 791;
- t['a72'] = 873;
- t['a73'] = 761;
- t['a74'] = 762;
- t['a203'] = 762;
- t['a75'] = 759;
- t['a204'] = 759;
- t['a76'] = 892;
- t['a77'] = 892;
- t['a78'] = 788;
- t['a79'] = 784;
- t['a81'] = 438;
- t['a82'] = 138;
- t['a83'] = 277;
- t['a84'] = 415;
- t['a97'] = 392;
- t['a98'] = 392;
- t['a99'] = 668;
- t['a100'] = 668;
- t['a89'] = 390;
- t['a90'] = 390;
- t['a93'] = 317;
- t['a94'] = 317;
- t['a91'] = 276;
- t['a92'] = 276;
- t['a205'] = 509;
- t['a85'] = 509;
- t['a206'] = 410;
- t['a86'] = 410;
- t['a87'] = 234;
- t['a88'] = 234;
- t['a95'] = 334;
- t['a96'] = 334;
- t['a101'] = 732;
- t['a102'] = 544;
- t['a103'] = 544;
- t['a104'] = 910;
- t['a106'] = 667;
- t['a107'] = 760;
- t['a108'] = 760;
- t['a112'] = 776;
- t['a111'] = 595;
- t['a110'] = 694;
- t['a109'] = 626;
- t['a120'] = 788;
- t['a121'] = 788;
- t['a122'] = 788;
- t['a123'] = 788;
- t['a124'] = 788;
- t['a125'] = 788;
- t['a126'] = 788;
- t['a127'] = 788;
- t['a128'] = 788;
- t['a129'] = 788;
- t['a130'] = 788;
- t['a131'] = 788;
- t['a132'] = 788;
- t['a133'] = 788;
- t['a134'] = 788;
- t['a135'] = 788;
- t['a136'] = 788;
- t['a137'] = 788;
- t['a138'] = 788;
- t['a139'] = 788;
- t['a140'] = 788;
- t['a141'] = 788;
- t['a142'] = 788;
- t['a143'] = 788;
- t['a144'] = 788;
- t['a145'] = 788;
- t['a146'] = 788;
- t['a147'] = 788;
- t['a148'] = 788;
- t['a149'] = 788;
- t['a150'] = 788;
- t['a151'] = 788;
- t['a152'] = 788;
- t['a153'] = 788;
- t['a154'] = 788;
- t['a155'] = 788;
- t['a156'] = 788;
- t['a157'] = 788;
- t['a158'] = 788;
- t['a159'] = 788;
- t['a160'] = 894;
- t['a161'] = 838;
- t['a163'] = 1016;
- t['a164'] = 458;
- t['a196'] = 748;
- t['a165'] = 924;
- t['a192'] = 748;
- t['a166'] = 918;
- t['a167'] = 927;
- t['a168'] = 928;
- t['a169'] = 928;
- t['a170'] = 834;
- t['a171'] = 873;
- t['a172'] = 828;
- t['a173'] = 924;
- t['a162'] = 924;
- t['a174'] = 917;
- t['a175'] = 930;
- t['a176'] = 931;
- t['a177'] = 463;
- t['a178'] = 883;
- t['a179'] = 836;
- t['a193'] = 836;
- t['a180'] = 867;
- t['a199'] = 867;
- t['a181'] = 696;
- t['a200'] = 696;
- t['a182'] = 874;
- t['a201'] = 874;
- t['a183'] = 760;
- t['a184'] = 946;
- t['a197'] = 771;
- t['a185'] = 865;
- t['a194'] = 771;
- t['a198'] = 888;
- t['a186'] = 967;
- t['a195'] = 888;
- t['a187'] = 831;
- t['a188'] = 873;
- t['a189'] = 927;
- t['a190'] = 970;
- t['a191'] = 918;
- });
-});
-exports.getMetrics = getMetrics;
-
-/***/ }),
-/* 168 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.PostScriptCompiler = exports.PostScriptEvaluator = exports.PDFFunctionFactory = exports.isPDFFunction = undefined;
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
-var _util = __w_pdfjs_require__(2);
-
-var _primitives = __w_pdfjs_require__(138);
-
-var _ps_parser = __w_pdfjs_require__(169);
-
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
-var IsEvalSupportedCached = {
- get value() {
- return (0, _util.shadow)(this, 'value', (0, _util.isEvalSupported)());
- }
-};
-
-var PDFFunctionFactory = function () {
- function PDFFunctionFactory(_ref) {
- var xref = _ref.xref,
- _ref$isEvalSupported = _ref.isEvalSupported,
- isEvalSupported = _ref$isEvalSupported === undefined ? true : _ref$isEvalSupported;
-
- _classCallCheck(this, PDFFunctionFactory);
-
- this.xref = xref;
- this.isEvalSupported = isEvalSupported !== false;
- }
-
- _createClass(PDFFunctionFactory, [{
- key: 'create',
- value: function create(fn) {
- return PDFFunction.parse({
- xref: this.xref,
- isEvalSupported: this.isEvalSupported,
- fn: fn
- });
- }
- }, {
- key: 'createFromArray',
- value: function createFromArray(fnObj) {
- return PDFFunction.parseArray({
- xref: this.xref,
- isEvalSupported: this.isEvalSupported,
- fnObj: fnObj
- });
- }
- }]);
-
- return PDFFunctionFactory;
-}();
-
-function toNumberArray(arr) {
- if (!Array.isArray(arr)) {
- return null;
- }
- var length = arr.length;
- for (var i = 0; i < length; i++) {
- if (typeof arr[i] !== 'number') {
- var result = new Array(length);
- for (var _i = 0; _i < length; _i++) {
- result[_i] = +arr[_i];
- }
- return result;
- }
- }
- return arr;
-}
-var PDFFunction = function PDFFunctionClosure() {
- var CONSTRUCT_SAMPLED = 0;
- var CONSTRUCT_INTERPOLATED = 2;
- var CONSTRUCT_STICHED = 3;
- var CONSTRUCT_POSTSCRIPT = 4;
- return {
- getSampleArray: function getSampleArray(size, outputSize, bps, stream) {
- var i, ii;
- var length = 1;
- for (i = 0, ii = size.length; i < ii; i++) {
- length *= size[i];
- }
- length *= outputSize;
- var array = new Array(length);
- var codeSize = 0;
- var codeBuf = 0;
- var sampleMul = 1.0 / (Math.pow(2.0, bps) - 1);
- var strBytes = stream.getBytes((length * bps + 7) / 8);
- var strIdx = 0;
- for (i = 0; i < length; i++) {
- while (codeSize < bps) {
- codeBuf <<= 8;
- codeBuf |= strBytes[strIdx++];
- codeSize += 8;
- }
- codeSize -= bps;
- array[i] = (codeBuf >> codeSize) * sampleMul;
- codeBuf &= (1 << codeSize) - 1;
- }
- return array;
- },
- getIR: function getIR(_ref2) {
- var xref = _ref2.xref,
- isEvalSupported = _ref2.isEvalSupported,
- fn = _ref2.fn;
-
- var dict = fn.dict;
- if (!dict) {
- dict = fn;
- }
- var types = [this.constructSampled, null, this.constructInterpolated, this.constructStiched, this.constructPostScript];
- var typeNum = dict.get('FunctionType');
- var typeFn = types[typeNum];
- if (!typeFn) {
- throw new _util.FormatError('Unknown type of function');
- }
- return typeFn.call(this, {
- xref: xref,
- isEvalSupported: isEvalSupported,
- fn: fn,
- dict: dict
- });
- },
- fromIR: function fromIR(_ref3) {
- var xref = _ref3.xref,
- isEvalSupported = _ref3.isEvalSupported,
- IR = _ref3.IR;
-
- var type = IR[0];
- switch (type) {
- case CONSTRUCT_SAMPLED:
- return this.constructSampledFromIR({
- xref: xref,
- isEvalSupported: isEvalSupported,
- IR: IR
- });
- case CONSTRUCT_INTERPOLATED:
- return this.constructInterpolatedFromIR({
- xref: xref,
- isEvalSupported: isEvalSupported,
- IR: IR
- });
- case CONSTRUCT_STICHED:
- return this.constructStichedFromIR({
- xref: xref,
- isEvalSupported: isEvalSupported,
- IR: IR
- });
- default:
- return this.constructPostScriptFromIR({
- xref: xref,
- isEvalSupported: isEvalSupported,
- IR: IR
- });
- }
- },
- parse: function parse(_ref4) {
- var xref = _ref4.xref,
- isEvalSupported = _ref4.isEvalSupported,
- fn = _ref4.fn;
-
- var IR = this.getIR({
- xref: xref,
- isEvalSupported: isEvalSupported,
- fn: fn
- });
- return this.fromIR({
- xref: xref,
- isEvalSupported: isEvalSupported,
- IR: IR
- });
- },
- parseArray: function parseArray(_ref5) {
- var xref = _ref5.xref,
- isEvalSupported = _ref5.isEvalSupported,
- fnObj = _ref5.fnObj;
-
- if (!Array.isArray(fnObj)) {
- return this.parse({
- xref: xref,
- isEvalSupported: isEvalSupported,
- fn: fnObj
- });
- }
- var fnArray = [];
- for (var j = 0, jj = fnObj.length; j < jj; j++) {
- fnArray.push(this.parse({
- xref: xref,
- isEvalSupported: isEvalSupported,
- fn: xref.fetchIfRef(fnObj[j])
- }));
- }
- return function (src, srcOffset, dest, destOffset) {
- for (var i = 0, ii = fnArray.length; i < ii; i++) {
- fnArray[i](src, srcOffset, dest, destOffset + i);
- }
- };
- },
- constructSampled: function constructSampled(_ref6) {
- var xref = _ref6.xref,
- isEvalSupported = _ref6.isEvalSupported,
- fn = _ref6.fn,
- dict = _ref6.dict;
-
- function toMultiArray(arr) {
- var inputLength = arr.length;
- var out = [];
- var index = 0;
- for (var i = 0; i < inputLength; i += 2) {
- out[index] = [arr[i], arr[i + 1]];
- ++index;
- }
- return out;
- }
- var domain = toNumberArray(dict.getArray('Domain'));
- var range = toNumberArray(dict.getArray('Range'));
- if (!domain || !range) {
- throw new _util.FormatError('No domain or range');
- }
- var inputSize = domain.length / 2;
- var outputSize = range.length / 2;
- domain = toMultiArray(domain);
- range = toMultiArray(range);
- var size = toNumberArray(dict.getArray('Size'));
- var bps = dict.get('BitsPerSample');
- var order = dict.get('Order') || 1;
- if (order !== 1) {
- (0, _util.info)('No support for cubic spline interpolation: ' + order);
- }
- var encode = toNumberArray(dict.getArray('Encode'));
- if (!encode) {
- encode = [];
- for (var i = 0; i < inputSize; ++i) {
- encode.push([0, size[i] - 1]);
- }
- } else {
- encode = toMultiArray(encode);
- }
- var decode = toNumberArray(dict.getArray('Decode'));
- if (!decode) {
- decode = range;
- } else {
- decode = toMultiArray(decode);
- }
- var samples = this.getSampleArray(size, outputSize, bps, fn);
- return [CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size, outputSize, Math.pow(2, bps) - 1, range];
- },
- constructSampledFromIR: function constructSampledFromIR(_ref7) {
- var xref = _ref7.xref,
- isEvalSupported = _ref7.isEvalSupported,
- IR = _ref7.IR;
-
- function interpolate(x, xmin, xmax, ymin, ymax) {
- return ymin + (x - xmin) * ((ymax - ymin) / (xmax - xmin));
- }
- return function constructSampledFromIRResult(src, srcOffset, dest, destOffset) {
- var m = IR[1];
- var domain = IR[2];
- var encode = IR[3];
- var decode = IR[4];
- var samples = IR[5];
- var size = IR[6];
- var n = IR[7];
- var range = IR[9];
- var cubeVertices = 1 << m;
- var cubeN = new Float64Array(cubeVertices);
- var cubeVertex = new Uint32Array(cubeVertices);
- var i, j;
- for (j = 0; j < cubeVertices; j++) {
- cubeN[j] = 1;
- }
- var k = n,
- pos = 1;
- for (i = 0; i < m; ++i) {
- var domain_2i = domain[i][0];
- var domain_2i_1 = domain[i][1];
- var xi = Math.min(Math.max(src[srcOffset + i], domain_2i), domain_2i_1);
- var e = interpolate(xi, domain_2i, domain_2i_1, encode[i][0], encode[i][1]);
- var size_i = size[i];
- e = Math.min(Math.max(e, 0), size_i - 1);
- var e0 = e < size_i - 1 ? Math.floor(e) : e - 1;
- var n0 = e0 + 1 - e;
- var n1 = e - e0;
- var offset0 = e0 * k;
- var offset1 = offset0 + k;
- for (j = 0; j < cubeVertices; j++) {
- if (j & pos) {
- cubeN[j] *= n1;
- cubeVertex[j] += offset1;
- } else {
- cubeN[j] *= n0;
- cubeVertex[j] += offset0;
- }
- }
- k *= size_i;
- pos <<= 1;
- }
- for (j = 0; j < n; ++j) {
- var rj = 0;
- for (i = 0; i < cubeVertices; i++) {
- rj += samples[cubeVertex[i] + j] * cubeN[i];
- }
- rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]);
- dest[destOffset + j] = Math.min(Math.max(rj, range[j][0]), range[j][1]);
- }
- };
- },
- constructInterpolated: function constructInterpolated(_ref8) {
- var xref = _ref8.xref,
- isEvalSupported = _ref8.isEvalSupported,
- fn = _ref8.fn,
- dict = _ref8.dict;
-
- var c0 = toNumberArray(dict.getArray('C0')) || [0];
- var c1 = toNumberArray(dict.getArray('C1')) || [1];
- var n = dict.get('N');
- var length = c0.length;
- var diff = [];
- for (var i = 0; i < length; ++i) {
- diff.push(c1[i] - c0[i]);
- }
- return [CONSTRUCT_INTERPOLATED, c0, diff, n];
- },
- constructInterpolatedFromIR: function constructInterpolatedFromIR(_ref9) {
- var xref = _ref9.xref,
- isEvalSupported = _ref9.isEvalSupported,
- IR = _ref9.IR;
-
- var c0 = IR[1];
- var diff = IR[2];
- var n = IR[3];
- var length = diff.length;
- return function constructInterpolatedFromIRResult(src, srcOffset, dest, destOffset) {
- var x = n === 1 ? src[srcOffset] : Math.pow(src[srcOffset], n);
- for (var j = 0; j < length; ++j) {
- dest[destOffset + j] = c0[j] + x * diff[j];
- }
- };
- },
- constructStiched: function constructStiched(_ref10) {
- var xref = _ref10.xref,
- isEvalSupported = _ref10.isEvalSupported,
- fn = _ref10.fn,
- dict = _ref10.dict;
-
- var domain = toNumberArray(dict.getArray('Domain'));
- if (!domain) {
- throw new _util.FormatError('No domain');
- }
- var inputSize = domain.length / 2;
- if (inputSize !== 1) {
- throw new _util.FormatError('Bad domain for stiched function');
- }
- var fnRefs = dict.get('Functions');
- var fns = [];
- for (var i = 0, ii = fnRefs.length; i < ii; ++i) {
- fns.push(this.parse({
- xref: xref,
- isEvalSupported: isEvalSupported,
- fn: xref.fetchIfRef(fnRefs[i])
- }));
- }
- var bounds = toNumberArray(dict.getArray('Bounds'));
- var encode = toNumberArray(dict.getArray('Encode'));
- return [CONSTRUCT_STICHED, domain, bounds, encode, fns];
- },
- constructStichedFromIR: function constructStichedFromIR(_ref11) {
- var xref = _ref11.xref,
- isEvalSupported = _ref11.isEvalSupported,
- IR = _ref11.IR;
-
- var domain = IR[1];
- var bounds = IR[2];
- var encode = IR[3];
- var fns = IR[4];
- var tmpBuf = new Float32Array(1);
- return function constructStichedFromIRResult(src, srcOffset, dest, destOffset) {
- var clip = function constructStichedFromIRClip(v, min, max) {
- if (v > max) {
- v = max;
- } else if (v < min) {
- v = min;
- }
- return v;
- };
- var v = clip(src[srcOffset], domain[0], domain[1]);
- for (var i = 0, ii = bounds.length; i < ii; ++i) {
- if (v < bounds[i]) {
- break;
- }
- }
- var dmin = domain[0];
- if (i > 0) {
- dmin = bounds[i - 1];
- }
- var dmax = domain[1];
- if (i < bounds.length) {
- dmax = bounds[i];
- }
- var rmin = encode[2 * i];
- var rmax = encode[2 * i + 1];
- tmpBuf[0] = dmin === dmax ? rmin : rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin);
- fns[i](tmpBuf, 0, dest, destOffset);
- };
- },
- constructPostScript: function constructPostScript(_ref12) {
- var xref = _ref12.xref,
- isEvalSupported = _ref12.isEvalSupported,
- fn = _ref12.fn,
- dict = _ref12.dict;
-
- var domain = toNumberArray(dict.getArray('Domain'));
- var range = toNumberArray(dict.getArray('Range'));
- if (!domain) {
- throw new _util.FormatError('No domain.');
- }
- if (!range) {
- throw new _util.FormatError('No range.');
- }
- var lexer = new _ps_parser.PostScriptLexer(fn);
- var parser = new _ps_parser.PostScriptParser(lexer);
- var code = parser.parse();
- return [CONSTRUCT_POSTSCRIPT, domain, range, code];
- },
- constructPostScriptFromIR: function constructPostScriptFromIR(_ref13) {
- var xref = _ref13.xref,
- isEvalSupported = _ref13.isEvalSupported,
- IR = _ref13.IR;
-
- var domain = IR[1];
- var range = IR[2];
- var code = IR[3];
- if (isEvalSupported && IsEvalSupportedCached.value) {
- var compiled = new PostScriptCompiler().compile(code, domain, range);
- if (compiled) {
- return new Function('src', 'srcOffset', 'dest', 'destOffset', compiled);
- }
- }
- (0, _util.info)('Unable to compile PS function');
- var numOutputs = range.length >> 1;
- var numInputs = domain.length >> 1;
- var evaluator = new PostScriptEvaluator(code);
- var cache = Object.create(null);
- var MAX_CACHE_SIZE = 2048 * 4;
- var cache_available = MAX_CACHE_SIZE;
- var tmpBuf = new Float32Array(numInputs);
- return function constructPostScriptFromIRResult(src, srcOffset, dest, destOffset) {
- var i, value;
- var key = '';
- var input = tmpBuf;
- for (i = 0; i < numInputs; i++) {
- value = src[srcOffset + i];
- input[i] = value;
- key += value + '_';
- }
- var cachedValue = cache[key];
- if (cachedValue !== undefined) {
- dest.set(cachedValue, destOffset);
- return;
- }
- var output = new Float32Array(numOutputs);
- var stack = evaluator.execute(input);
- var stackIndex = stack.length - numOutputs;
- for (i = 0; i < numOutputs; i++) {
- value = stack[stackIndex + i];
- var bound = range[i * 2];
- if (value < bound) {
- value = bound;
- } else {
- bound = range[i * 2 + 1];
- if (value > bound) {
- value = bound;
- }
- }
- output[i] = value;
- }
- if (cache_available > 0) {
- cache_available--;
- cache[key] = output;
- }
- dest.set(output, destOffset);
- };
- }
- };
-}();
-function isPDFFunction(v) {
- var fnDict;
- if ((typeof v === 'undefined' ? 'undefined' : _typeof(v)) !== 'object') {
- return false;
- } else if ((0, _primitives.isDict)(v)) {
- fnDict = v;
- } else if ((0, _primitives.isStream)(v)) {
- fnDict = v.dict;
- } else {
- return false;
- }
- return fnDict.has('FunctionType');
-}
-var PostScriptStack = function PostScriptStackClosure() {
- var MAX_STACK_SIZE = 100;
- function PostScriptStack(initialStack) {
- this.stack = !initialStack ? [] : Array.prototype.slice.call(initialStack, 0);
- }
- PostScriptStack.prototype = {
- push: function PostScriptStack_push(value) {
- if (this.stack.length >= MAX_STACK_SIZE) {
- throw new Error('PostScript function stack overflow.');
- }
- this.stack.push(value);
- },
- pop: function PostScriptStack_pop() {
- if (this.stack.length <= 0) {
- throw new Error('PostScript function stack underflow.');
- }
- return this.stack.pop();
- },
- copy: function PostScriptStack_copy(n) {
- if (this.stack.length + n >= MAX_STACK_SIZE) {
- throw new Error('PostScript function stack overflow.');
- }
- var stack = this.stack;
- for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++) {
- stack.push(stack[i]);
- }
- },
- index: function PostScriptStack_index(n) {
- this.push(this.stack[this.stack.length - n - 1]);
- },
- roll: function PostScriptStack_roll(n, p) {
- var stack = this.stack;
- var l = stack.length - n;
- var r = stack.length - 1,
- c = l + (p - Math.floor(p / n) * n),
- i,
- j,
- t;
- for (i = l, j = r; i < j; i++, j--) {
- t = stack[i];
- stack[i] = stack[j];
- stack[j] = t;
- }
- for (i = l, j = c - 1; i < j; i++, j--) {
- t = stack[i];
- stack[i] = stack[j];
- stack[j] = t;
- }
- for (i = c, j = r; i < j; i++, j--) {
- t = stack[i];
- stack[i] = stack[j];
- stack[j] = t;
- }
- }
- };
- return PostScriptStack;
-}();
-var PostScriptEvaluator = function PostScriptEvaluatorClosure() {
- function PostScriptEvaluator(operators) {
- this.operators = operators;
- }
- PostScriptEvaluator.prototype = {
- execute: function PostScriptEvaluator_execute(initialStack) {
- var stack = new PostScriptStack(initialStack);
- var counter = 0;
- var operators = this.operators;
- var length = operators.length;
- var operator, a, b;
- while (counter < length) {
- operator = operators[counter++];
- if (typeof operator === 'number') {
- stack.push(operator);
- continue;
- }
- switch (operator) {
- case 'jz':
- b = stack.pop();
- a = stack.pop();
- if (!a) {
- counter = b;
- }
- break;
- case 'j':
- a = stack.pop();
- counter = a;
- break;
- case 'abs':
- a = stack.pop();
- stack.push(Math.abs(a));
- break;
- case 'add':
- b = stack.pop();
- a = stack.pop();
- stack.push(a + b);
- break;
- case 'and':
- b = stack.pop();
- a = stack.pop();
- if ((0, _util.isBool)(a) && (0, _util.isBool)(b)) {
- stack.push(a && b);
- } else {
- stack.push(a & b);
- }
- break;
- case 'atan':
- a = stack.pop();
- stack.push(Math.atan(a));
- break;
- case 'bitshift':
- b = stack.pop();
- a = stack.pop();
- if (a > 0) {
- stack.push(a << b);
- } else {
- stack.push(a >> b);
- }
- break;
- case 'ceiling':
- a = stack.pop();
- stack.push(Math.ceil(a));
- break;
- case 'copy':
- a = stack.pop();
- stack.copy(a);
- break;
- case 'cos':
- a = stack.pop();
- stack.push(Math.cos(a));
- break;
- case 'cvi':
- a = stack.pop() | 0;
- stack.push(a);
- break;
- case 'cvr':
- break;
- case 'div':
- b = stack.pop();
- a = stack.pop();
- stack.push(a / b);
- break;
- case 'dup':
- stack.copy(1);
- break;
- case 'eq':
- b = stack.pop();
- a = stack.pop();
- stack.push(a === b);
- break;
- case 'exch':
- stack.roll(2, 1);
- break;
- case 'exp':
- b = stack.pop();
- a = stack.pop();
- stack.push(Math.pow(a, b));
- break;
- case 'false':
- stack.push(false);
- break;
- case 'floor':
- a = stack.pop();
- stack.push(Math.floor(a));
- break;
- case 'ge':
- b = stack.pop();
- a = stack.pop();
- stack.push(a >= b);
- break;
- case 'gt':
- b = stack.pop();
- a = stack.pop();
- stack.push(a > b);
- break;
- case 'idiv':
- b = stack.pop();
- a = stack.pop();
- stack.push(a / b | 0);
- break;
- case 'index':
- a = stack.pop();
- stack.index(a);
- break;
- case 'le':
- b = stack.pop();
- a = stack.pop();
- stack.push(a <= b);
- break;
- case 'ln':
- a = stack.pop();
- stack.push(Math.log(a));
- break;
- case 'log':
- a = stack.pop();
- stack.push(Math.log(a) / Math.LN10);
- break;
- case 'lt':
- b = stack.pop();
- a = stack.pop();
- stack.push(a < b);
- break;
- case 'mod':
- b = stack.pop();
- a = stack.pop();
- stack.push(a % b);
- break;
- case 'mul':
- b = stack.pop();
- a = stack.pop();
- stack.push(a * b);
- break;
- case 'ne':
- b = stack.pop();
- a = stack.pop();
- stack.push(a !== b);
- break;
- case 'neg':
- a = stack.pop();
- stack.push(-a);
- break;
- case 'not':
- a = stack.pop();
- if ((0, _util.isBool)(a)) {
- stack.push(!a);
- } else {
- stack.push(~a);
- }
- break;
- case 'or':
- b = stack.pop();
- a = stack.pop();
- if ((0, _util.isBool)(a) && (0, _util.isBool)(b)) {
- stack.push(a || b);
- } else {
- stack.push(a | b);
- }
- break;
- case 'pop':
- stack.pop();
- break;
- case 'roll':
- b = stack.pop();
- a = stack.pop();
- stack.roll(a, b);
- break;
- case 'round':
- a = stack.pop();
- stack.push(Math.round(a));
- break;
- case 'sin':
- a = stack.pop();
- stack.push(Math.sin(a));
- break;
- case 'sqrt':
- a = stack.pop();
- stack.push(Math.sqrt(a));
- break;
- case 'sub':
- b = stack.pop();
- a = stack.pop();
- stack.push(a - b);
- break;
- case 'true':
- stack.push(true);
- break;
- case 'truncate':
- a = stack.pop();
- a = a < 0 ? Math.ceil(a) : Math.floor(a);
- stack.push(a);
- break;
- case 'xor':
- b = stack.pop();
- a = stack.pop();
- if ((0, _util.isBool)(a) && (0, _util.isBool)(b)) {
- stack.push(a !== b);
- } else {
- stack.push(a ^ b);
- }
- break;
- default:
- throw new _util.FormatError('Unknown operator ' + operator);
- }
- }
- return stack.stack;
- }
- };
- return PostScriptEvaluator;
-}();
-var PostScriptCompiler = function PostScriptCompilerClosure() {
- function AstNode(type) {
- this.type = type;
- }
- AstNode.prototype.visit = function (visitor) {
- (0, _util.unreachable)('abstract method');
- };
- function AstArgument(index, min, max) {
- AstNode.call(this, 'args');
- this.index = index;
- this.min = min;
- this.max = max;
- }
- AstArgument.prototype = Object.create(AstNode.prototype);
- AstArgument.prototype.visit = function (visitor) {
- visitor.visitArgument(this);
- };
- function AstLiteral(number) {
- AstNode.call(this, 'literal');
- this.number = number;
- this.min = number;
- this.max = number;
- }
- AstLiteral.prototype = Object.create(AstNode.prototype);
- AstLiteral.prototype.visit = function (visitor) {
- visitor.visitLiteral(this);
- };
- function AstBinaryOperation(op, arg1, arg2, min, max) {
- AstNode.call(this, 'binary');
- this.op = op;
- this.arg1 = arg1;
- this.arg2 = arg2;
- this.min = min;
- this.max = max;
- }
- AstBinaryOperation.prototype = Object.create(AstNode.prototype);
- AstBinaryOperation.prototype.visit = function (visitor) {
- visitor.visitBinaryOperation(this);
- };
- function AstMin(arg, max) {
- AstNode.call(this, 'max');
- this.arg = arg;
- this.min = arg.min;
- this.max = max;
- }
- AstMin.prototype = Object.create(AstNode.prototype);
- AstMin.prototype.visit = function (visitor) {
- visitor.visitMin(this);
- };
- function AstVariable(index, min, max) {
- AstNode.call(this, 'var');
- this.index = index;
- this.min = min;
- this.max = max;
- }
- AstVariable.prototype = Object.create(AstNode.prototype);
- AstVariable.prototype.visit = function (visitor) {
- visitor.visitVariable(this);
- };
- function AstVariableDefinition(variable, arg) {
- AstNode.call(this, 'definition');
- this.variable = variable;
- this.arg = arg;
- }
- AstVariableDefinition.prototype = Object.create(AstNode.prototype);
- AstVariableDefinition.prototype.visit = function (visitor) {
- visitor.visitVariableDefinition(this);
- };
- function ExpressionBuilderVisitor() {
- this.parts = [];
- }
- ExpressionBuilderVisitor.prototype = {
- visitArgument: function visitArgument(arg) {
- this.parts.push('Math.max(', arg.min, ', Math.min(', arg.max, ', src[srcOffset + ', arg.index, ']))');
- },
- visitVariable: function visitVariable(variable) {
- this.parts.push('v', variable.index);
- },
- visitLiteral: function visitLiteral(literal) {
- this.parts.push(literal.number);
- },
- visitBinaryOperation: function visitBinaryOperation(operation) {
- this.parts.push('(');
- operation.arg1.visit(this);
- this.parts.push(' ', operation.op, ' ');
- operation.arg2.visit(this);
- this.parts.push(')');
- },
- visitVariableDefinition: function visitVariableDefinition(definition) {
- this.parts.push('var ');
- definition.variable.visit(this);
- this.parts.push(' = ');
- definition.arg.visit(this);
- this.parts.push(';');
- },
- visitMin: function visitMin(max) {
- this.parts.push('Math.min(');
- max.arg.visit(this);
- this.parts.push(', ', max.max, ')');
- },
- toString: function toString() {
- return this.parts.join('');
- }
- };
- function buildAddOperation(num1, num2) {
- if (num2.type === 'literal' && num2.number === 0) {
- return num1;
- }
- if (num1.type === 'literal' && num1.number === 0) {
- return num2;
- }
- if (num2.type === 'literal' && num1.type === 'literal') {
- return new AstLiteral(num1.number + num2.number);
- }
- return new AstBinaryOperation('+', num1, num2, num1.min + num2.min, num1.max + num2.max);
- }
- function buildMulOperation(num1, num2) {
- if (num2.type === 'literal') {
- if (num2.number === 0) {
- return new AstLiteral(0);
- } else if (num2.number === 1) {
- return num1;
- } else if (num1.type === 'literal') {
- return new AstLiteral(num1.number * num2.number);
- }
- }
- if (num1.type === 'literal') {
- if (num1.number === 0) {
- return new AstLiteral(0);
- } else if (num1.number === 1) {
- return num2;
- }
- }
- var min = Math.min(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max);
- var max = Math.max(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max);
- return new AstBinaryOperation('*', num1, num2, min, max);
- }
- function buildSubOperation(num1, num2) {
- if (num2.type === 'literal') {
- if (num2.number === 0) {
- return num1;
- } else if (num1.type === 'literal') {
- return new AstLiteral(num1.number - num2.number);
- }
- }
- if (num2.type === 'binary' && num2.op === '-' && num1.type === 'literal' && num1.number === 1 && num2.arg1.type === 'literal' && num2.arg1.number === 1) {
- return num2.arg2;
- }
- return new AstBinaryOperation('-', num1, num2, num1.min - num2.max, num1.max - num2.min);
- }
- function buildMinOperation(num1, max) {
- if (num1.min >= max) {
- return new AstLiteral(max);
- } else if (num1.max <= max) {
- return num1;
- }
- return new AstMin(num1, max);
- }
- function PostScriptCompiler() {}
- PostScriptCompiler.prototype = {
- compile: function PostScriptCompiler_compile(code, domain, range) {
- var stack = [];
- var i, ii;
- var instructions = [];
- var inputSize = domain.length >> 1,
- outputSize = range.length >> 1;
- var lastRegister = 0;
- var n, j;
- var num1, num2, ast1, ast2, tmpVar, item;
- for (i = 0; i < inputSize; i++) {
- stack.push(new AstArgument(i, domain[i * 2], domain[i * 2 + 1]));
- }
- for (i = 0, ii = code.length; i < ii; i++) {
- item = code[i];
- if (typeof item === 'number') {
- stack.push(new AstLiteral(item));
- continue;
- }
- switch (item) {
- case 'add':
- if (stack.length < 2) {
- return null;
- }
- num2 = stack.pop();
- num1 = stack.pop();
- stack.push(buildAddOperation(num1, num2));
- break;
- case 'cvr':
- if (stack.length < 1) {
- return null;
- }
- break;
- case 'mul':
- if (stack.length < 2) {
- return null;
- }
- num2 = stack.pop();
- num1 = stack.pop();
- stack.push(buildMulOperation(num1, num2));
- break;
- case 'sub':
- if (stack.length < 2) {
- return null;
- }
- num2 = stack.pop();
- num1 = stack.pop();
- stack.push(buildSubOperation(num1, num2));
- break;
- case 'exch':
- if (stack.length < 2) {
- return null;
- }
- ast1 = stack.pop();
- ast2 = stack.pop();
- stack.push(ast1, ast2);
- break;
- case 'pop':
- if (stack.length < 1) {
- return null;
- }
- stack.pop();
- break;
- case 'index':
- if (stack.length < 1) {
- return null;
- }
- num1 = stack.pop();
- if (num1.type !== 'literal') {
- return null;
- }
- n = num1.number;
- if (n < 0 || !Number.isInteger(n) || stack.length < n) {
- return null;
- }
- ast1 = stack[stack.length - n - 1];
- if (ast1.type === 'literal' || ast1.type === 'var') {
- stack.push(ast1);
- break;
- }
- tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max);
- stack[stack.length - n - 1] = tmpVar;
- stack.push(tmpVar);
- instructions.push(new AstVariableDefinition(tmpVar, ast1));
- break;
- case 'dup':
- if (stack.length < 1) {
- return null;
- }
- if (typeof code[i + 1] === 'number' && code[i + 2] === 'gt' && code[i + 3] === i + 7 && code[i + 4] === 'jz' && code[i + 5] === 'pop' && code[i + 6] === code[i + 1]) {
- num1 = stack.pop();
- stack.push(buildMinOperation(num1, code[i + 1]));
- i += 6;
- break;
- }
- ast1 = stack[stack.length - 1];
- if (ast1.type === 'literal' || ast1.type === 'var') {
- stack.push(ast1);
- break;
- }
- tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max);
- stack[stack.length - 1] = tmpVar;
- stack.push(tmpVar);
- instructions.push(new AstVariableDefinition(tmpVar, ast1));
- break;
- case 'roll':
- if (stack.length < 2) {
- return null;
- }
- num2 = stack.pop();
- num1 = stack.pop();
- if (num2.type !== 'literal' || num1.type !== 'literal') {
- return null;
- }
- j = num2.number;
- n = num1.number;
- if (n <= 0 || !Number.isInteger(n) || !Number.isInteger(j) || stack.length < n) {
- return null;
- }
- j = (j % n + n) % n;
- if (j === 0) {
- break;
- }
- Array.prototype.push.apply(stack, stack.splice(stack.length - n, n - j));
- break;
- default:
- return null;
- }
- }
- if (stack.length !== outputSize) {
- return null;
- }
- var result = [];
- instructions.forEach(function (instruction) {
- var statementBuilder = new ExpressionBuilderVisitor();
- instruction.visit(statementBuilder);
- result.push(statementBuilder.toString());
- });
- stack.forEach(function (expr, i) {
- var statementBuilder = new ExpressionBuilderVisitor();
- expr.visit(statementBuilder);
- var min = range[i * 2],
- max = range[i * 2 + 1];
- var out = [statementBuilder.toString()];
- if (min > expr.min) {
- out.unshift('Math.max(', min, ', ');
- out.push(')');
- }
- if (max < expr.max) {
- out.unshift('Math.min(', max, ', ');
- out.push(')');
- }
- out.unshift('dest[destOffset + ', i, '] = ');
- out.push(';');
- result.push(out.join(''));
- });
- return result.join('\n');
- }
- };
- return PostScriptCompiler;
-}();
-exports.isPDFFunction = isPDFFunction;
-exports.PDFFunctionFactory = PDFFunctionFactory;
-exports.PostScriptEvaluator = PostScriptEvaluator;
-exports.PostScriptCompiler = PostScriptCompiler;
-
-/***/ }),
-/* 169 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.PostScriptParser = exports.PostScriptLexer = undefined;
-
-var _util = __w_pdfjs_require__(2);
-
-var _primitives = __w_pdfjs_require__(138);
-
-var PostScriptParser = function PostScriptParserClosure() {
- function PostScriptParser(lexer) {
- this.lexer = lexer;
- this.operators = [];
- this.token = null;
- this.prev = null;
- }
- PostScriptParser.prototype = {
- nextToken: function PostScriptParser_nextToken() {
- this.prev = this.token;
- this.token = this.lexer.getToken();
- },
- accept: function PostScriptParser_accept(type) {
- if (this.token.type === type) {
- this.nextToken();
- return true;
- }
- return false;
- },
- expect: function PostScriptParser_expect(type) {
- if (this.accept(type)) {
- return true;
- }
- throw new _util.FormatError('Unexpected symbol: found ' + this.token.type + ' expected ' + type + '.');
- },
- parse: function PostScriptParser_parse() {
- this.nextToken();
- this.expect(PostScriptTokenTypes.LBRACE);
- this.parseBlock();
- this.expect(PostScriptTokenTypes.RBRACE);
- return this.operators;
- },
- parseBlock: function PostScriptParser_parseBlock() {
- while (true) {
- if (this.accept(PostScriptTokenTypes.NUMBER)) {
- this.operators.push(this.prev.value);
- } else if (this.accept(PostScriptTokenTypes.OPERATOR)) {
- this.operators.push(this.prev.value);
- } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
- this.parseCondition();
- } else {
- return;
- }
- }
- },
- parseCondition: function PostScriptParser_parseCondition() {
- var conditionLocation = this.operators.length;
- this.operators.push(null, null);
- this.parseBlock();
- this.expect(PostScriptTokenTypes.RBRACE);
- if (this.accept(PostScriptTokenTypes.IF)) {
- this.operators[conditionLocation] = this.operators.length;
- this.operators[conditionLocation + 1] = 'jz';
- } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
- var jumpLocation = this.operators.length;
- this.operators.push(null, null);
- var endOfTrue = this.operators.length;
- this.parseBlock();
- this.expect(PostScriptTokenTypes.RBRACE);
- this.expect(PostScriptTokenTypes.IFELSE);
- this.operators[jumpLocation] = this.operators.length;
- this.operators[jumpLocation + 1] = 'j';
- this.operators[conditionLocation] = endOfTrue;
- this.operators[conditionLocation + 1] = 'jz';
- } else {
- throw new _util.FormatError('PS Function: error parsing conditional.');
- }
- }
- };
- return PostScriptParser;
-}();
-var PostScriptTokenTypes = {
- LBRACE: 0,
- RBRACE: 1,
- NUMBER: 2,
- OPERATOR: 3,
- IF: 4,
- IFELSE: 5
-};
-var PostScriptToken = function PostScriptTokenClosure() {
- function PostScriptToken(type, value) {
- this.type = type;
- this.value = value;
- }
- var opCache = Object.create(null);
- PostScriptToken.getOperator = function PostScriptToken_getOperator(op) {
- var opValue = opCache[op];
- if (opValue) {
- return opValue;
- }
- return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR, op);
- };
- PostScriptToken.LBRACE = new PostScriptToken(PostScriptTokenTypes.LBRACE, '{');
- PostScriptToken.RBRACE = new PostScriptToken(PostScriptTokenTypes.RBRACE, '}');
- PostScriptToken.IF = new PostScriptToken(PostScriptTokenTypes.IF, 'IF');
- PostScriptToken.IFELSE = new PostScriptToken(PostScriptTokenTypes.IFELSE, 'IFELSE');
- return PostScriptToken;
-}();
-var PostScriptLexer = function PostScriptLexerClosure() {
- function PostScriptLexer(stream) {
- this.stream = stream;
- this.nextChar();
- this.strBuf = [];
- }
- PostScriptLexer.prototype = {
- nextChar: function PostScriptLexer_nextChar() {
- return this.currentChar = this.stream.getByte();
- },
- getToken: function PostScriptLexer_getToken() {
- var comment = false;
- var ch = this.currentChar;
- while (true) {
- if (ch < 0) {
- return _primitives.EOF;
- }
- if (comment) {
- if (ch === 0x0A || ch === 0x0D) {
- comment = false;
- }
- } else if (ch === 0x25) {
- comment = true;
- } else if (!(0, _util.isSpace)(ch)) {
- break;
- }
- ch = this.nextChar();
- }
- switch (ch | 0) {
- case 0x30:
- case 0x31:
- case 0x32:
- case 0x33:
- case 0x34:
- case 0x35:
- case 0x36:
- case 0x37:
- case 0x38:
- case 0x39:
- case 0x2B:
- case 0x2D:
- case 0x2E:
- return new PostScriptToken(PostScriptTokenTypes.NUMBER, this.getNumber());
- case 0x7B:
- this.nextChar();
- return PostScriptToken.LBRACE;
- case 0x7D:
- this.nextChar();
- return PostScriptToken.RBRACE;
- }
- var strBuf = this.strBuf;
- strBuf.length = 0;
- strBuf[0] = String.fromCharCode(ch);
- while ((ch = this.nextChar()) >= 0 && (ch >= 0x41 && ch <= 0x5A || ch >= 0x61 && ch <= 0x7A)) {
- strBuf.push(String.fromCharCode(ch));
- }
- var str = strBuf.join('');
- switch (str.toLowerCase()) {
- case 'if':
- return PostScriptToken.IF;
- case 'ifelse':
- return PostScriptToken.IFELSE;
- default:
- return PostScriptToken.getOperator(str);
- }
- },
- getNumber: function PostScriptLexer_getNumber() {
- var ch = this.currentChar;
- var strBuf = this.strBuf;
- strBuf.length = 0;
- strBuf[0] = String.fromCharCode(ch);
- while ((ch = this.nextChar()) >= 0) {
- if (ch >= 0x30 && ch <= 0x39 || ch === 0x2D || ch === 0x2E) {
- strBuf.push(String.fromCharCode(ch));
- } else {
- break;
- }
- }
- var value = parseFloat(strBuf.join(''));
- if (isNaN(value)) {
- throw new _util.FormatError('Invalid floating point number: ' + value);
- }
- return value;
- }
- };
- return PostScriptLexer;
-}();
-exports.PostScriptLexer = PostScriptLexer;
-exports.PostScriptParser = PostScriptParser;
-
-/***/ }),
-/* 170 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.MurmurHash3_64 = undefined;
-
-var _util = __w_pdfjs_require__(2);
-
-var MurmurHash3_64 = function MurmurHash3_64Closure(seed) {
- var MASK_HIGH = 0xffff0000;
- var MASK_LOW = 0xffff;
- function MurmurHash3_64(seed) {
- var SEED = 0xc3d2e1f0;
- this.h1 = seed ? seed & 0xffffffff : SEED;
- this.h2 = seed ? seed & 0xffffffff : SEED;
- }
- MurmurHash3_64.prototype = {
- update: function MurmurHash3_64_update(input) {
- var data = void 0,
- length = void 0;
- if ((0, _util.isString)(input)) {
- data = new Uint8Array(input.length * 2);
- length = 0;
- for (var i = 0, ii = input.length; i < ii; i++) {
- var code = input.charCodeAt(i);
- if (code <= 0xff) {
- data[length++] = code;
- } else {
- data[length++] = code >>> 8;
- data[length++] = code & 0xff;
- }
- }
- } else if ((0, _util.isArrayBuffer)(input)) {
- data = input;
- length = data.byteLength;
- } else {
- throw new Error('Wrong data format in MurmurHash3_64_update. ' + 'Input must be a string or array.');
- }
- var blockCounts = length >> 2;
- var tailLength = length - blockCounts * 4;
- var dataUint32 = new Uint32Array(data.buffer, 0, blockCounts);
- var k1 = 0;
- var k2 = 0;
- var h1 = this.h1;
- var h2 = this.h2;
- var C1 = 0xcc9e2d51;
- var C2 = 0x1b873593;
- var C1_LOW = C1 & MASK_LOW;
- var C2_LOW = C2 & MASK_LOW;
- for (var _i = 0; _i < blockCounts; _i++) {
- if (_i & 1) {
- k1 = dataUint32[_i];
- k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW;
- k1 = k1 << 15 | k1 >>> 17;
- k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW;
- h1 ^= k1;
- h1 = h1 << 13 | h1 >>> 19;
- h1 = h1 * 5 + 0xe6546b64;
- } else {
- k2 = dataUint32[_i];
- k2 = k2 * C1 & MASK_HIGH | k2 * C1_LOW & MASK_LOW;
- k2 = k2 << 15 | k2 >>> 17;
- k2 = k2 * C2 & MASK_HIGH | k2 * C2_LOW & MASK_LOW;
- h2 ^= k2;
- h2 = h2 << 13 | h2 >>> 19;
- h2 = h2 * 5 + 0xe6546b64;
- }
- }
- k1 = 0;
- switch (tailLength) {
- case 3:
- k1 ^= data[blockCounts * 4 + 2] << 16;
- case 2:
- k1 ^= data[blockCounts * 4 + 1] << 8;
- case 1:
- k1 ^= data[blockCounts * 4];
- k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW;
- k1 = k1 << 15 | k1 >>> 17;
- k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW;
- if (blockCounts & 1) {
- h1 ^= k1;
- } else {
- h2 ^= k1;
- }
- }
- this.h1 = h1;
- this.h2 = h2;
- return this;
- },
- hexdigest: function MurmurHash3_64_hexdigest() {
- var h1 = this.h1;
- var h2 = this.h2;
- h1 ^= h2 >>> 1;
- h1 = h1 * 0xed558ccd & MASK_HIGH | h1 * 0x8ccd & MASK_LOW;
- h2 = h2 * 0xff51afd7 & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16;
- h1 ^= h2 >>> 1;
- h1 = h1 * 0x1a85ec53 & MASK_HIGH | h1 * 0xec53 & MASK_LOW;
- h2 = h2 * 0xc4ceb9fe & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16;
- h1 ^= h2 >>> 1;
- for (var i = 0, arr = [h1, h2], str = ''; i < arr.length; i++) {
- var hex = (arr[i] >>> 0).toString(16);
- while (hex.length < 8) {
- hex = '0' + hex;
- }
- str += hex;
- }
- return str;
- }
- };
- return MurmurHash3_64;
-}();
-exports.MurmurHash3_64 = MurmurHash3_64;
-
-/***/ }),
-/* 171 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.PDFImage = undefined;
-
-var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
-
-var _util = __w_pdfjs_require__(2);
-
-var _primitives = __w_pdfjs_require__(138);
-
-var _colorspace = __w_pdfjs_require__(151);
-
-var _stream = __w_pdfjs_require__(140);
-
-var _jpeg_stream = __w_pdfjs_require__(146);
-
-var _jpx = __w_pdfjs_require__(149);
-
-var PDFImage = function PDFImageClosure() {
- function handleImageData(image, nativeDecoder) {
- if (nativeDecoder && nativeDecoder.canDecode(image)) {
- return nativeDecoder.decode(image).catch(function (reason) {
- (0, _util.warn)('Native image decoding failed -- trying to recover: ' + (reason && reason.message));
- return image;
- });
- }
- return Promise.resolve(image);
- }
- function decodeAndClamp(value, addend, coefficient, max) {
- value = addend + value * coefficient;
- return value < 0 ? 0 : value > max ? max : value;
- }
- function resizeImageMask(src, bpc, w1, h1, w2, h2) {
- var length = w2 * h2;
- var dest = bpc <= 8 ? new Uint8Array(length) : bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length);
- var xRatio = w1 / w2;
- var yRatio = h1 / h2;
- var i,
- j,
- py,
- newIndex = 0,
- oldIndex;
- var xScaled = new Uint16Array(w2);
- var w1Scanline = w1;
- for (i = 0; i < w2; i++) {
- xScaled[i] = Math.floor(i * xRatio);
- }
- for (i = 0; i < h2; i++) {
- py = Math.floor(i * yRatio) * w1Scanline;
- for (j = 0; j < w2; j++) {
- oldIndex = py + xScaled[j];
- dest[newIndex++] = src[oldIndex];
- }
- }
- return dest;
- }
- function PDFImage(_ref) {
- var xref = _ref.xref,
- res = _ref.res,
- image = _ref.image,
- _ref$isInline = _ref.isInline,
- isInline = _ref$isInline === undefined ? false : _ref$isInline,
- _ref$smask = _ref.smask,
- smask = _ref$smask === undefined ? null : _ref$smask,
- _ref$mask = _ref.mask,
- mask = _ref$mask === undefined ? null : _ref$mask,
- _ref$isMask = _ref.isMask,
- isMask = _ref$isMask === undefined ? false : _ref$isMask,
- pdfFunctionFactory = _ref.pdfFunctionFactory;
-
- this.image = image;
- var dict = image.dict;
- var filter = dict.get('Filter');
- if ((0, _primitives.isName)(filter)) {
- switch (filter.name) {
- case 'JPXDecode':
- var jpxImage = new _jpx.JpxImage();
- jpxImage.parseImageProperties(image.stream);
- image.stream.reset();
- image.width = jpxImage.width;
- image.height = jpxImage.height;
- image.bitsPerComponent = jpxImage.bitsPerComponent;
- image.numComps = jpxImage.componentsCount;
- break;
- case 'JBIG2Decode':
- image.bitsPerComponent = 1;
- image.numComps = 1;
- break;
- }
- }
- var width = dict.get('Width', 'W');
- var height = dict.get('Height', 'H');
- if (Number.isInteger(image.width) && image.width > 0 && Number.isInteger(image.height) && image.height > 0 && (image.width !== width || image.height !== height)) {
- (0, _util.warn)('PDFImage - using the Width/Height of the image data, ' + 'rather than the image dictionary.');
- width = image.width;
- height = image.height;
- }
- if (width < 1 || height < 1) {
- throw new _util.FormatError('Invalid image width: ' + width + ' or ' + ('height: ' + height));
- }
- this.width = width;
- this.height = height;
- this.interpolate = dict.get('Interpolate', 'I') || false;
- this.imageMask = dict.get('ImageMask', 'IM') || false;
- this.matte = dict.get('Matte') || false;
- var bitsPerComponent = image.bitsPerComponent;
- if (!bitsPerComponent) {
- bitsPerComponent = dict.get('BitsPerComponent', 'BPC');
- if (!bitsPerComponent) {
- if (this.imageMask) {
- bitsPerComponent = 1;
- } else {
- throw new _util.FormatError('Bits per component missing in image: ' + this.imageMask);
- }
- }
- }
- this.bpc = bitsPerComponent;
- if (!this.imageMask) {
- var colorSpace = dict.get('ColorSpace', 'CS');
- if (!colorSpace) {
- (0, _util.info)('JPX images (which do not require color spaces)');
- switch (image.numComps) {
- case 1:
- colorSpace = _primitives.Name.get('DeviceGray');
- break;
- case 3:
- colorSpace = _primitives.Name.get('DeviceRGB');
- break;
- case 4:
- colorSpace = _primitives.Name.get('DeviceCMYK');
- break;
- default:
- throw new Error('JPX images with ' + image.numComps + ' ' + 'color components not supported.');
- }
- }
- var resources = isInline ? res : null;
- this.colorSpace = _colorspace.ColorSpace.parse(colorSpace, xref, resources, pdfFunctionFactory);
- this.numComps = this.colorSpace.numComps;
- }
- this.decode = dict.getArray('Decode', 'D');
- this.needsDecode = false;
- if (this.decode && (this.colorSpace && !this.colorSpace.isDefaultDecode(this.decode) || isMask && !_colorspace.ColorSpace.isDefaultDecode(this.decode, 1))) {
- this.needsDecode = true;
- var max = (1 << bitsPerComponent) - 1;
- this.decodeCoefficients = [];
- this.decodeAddends = [];
- for (var i = 0, j = 0; i < this.decode.length; i += 2, ++j) {
- var dmin = this.decode[i];
- var dmax = this.decode[i + 1];
- this.decodeCoefficients[j] = dmax - dmin;
- this.decodeAddends[j] = max * dmin;
- }
- }
- if (smask) {
- this.smask = new PDFImage({
- xref: xref,
- res: res,
- image: smask,
- isInline: isInline,
- pdfFunctionFactory: pdfFunctionFactory
- });
- } else if (mask) {
- if ((0, _primitives.isStream)(mask)) {
- var maskDict = mask.dict,
- imageMask = maskDict.get('ImageMask', 'IM');
- if (!imageMask) {
- (0, _util.warn)('Ignoring /Mask in image without /ImageMask.');
- } else {
- this.mask = new PDFImage({
- xref: xref,
- res: res,
- image: mask,
- isInline: isInline,
- isMask: true,
- pdfFunctionFactory: pdfFunctionFactory
- });
- }
- } else {
- this.mask = mask;
- }
- }
- }
- PDFImage.buildImage = function (_ref2) {
- var handler = _ref2.handler,
- xref = _ref2.xref,
- res = _ref2.res,
- image = _ref2.image,
- _ref2$isInline = _ref2.isInline,
- isInline = _ref2$isInline === undefined ? false : _ref2$isInline,
- _ref2$nativeDecoder = _ref2.nativeDecoder,
- nativeDecoder = _ref2$nativeDecoder === undefined ? null : _ref2$nativeDecoder,
- pdfFunctionFactory = _ref2.pdfFunctionFactory;
-
- var imagePromise = handleImageData(image, nativeDecoder);
- var smaskPromise;
- var maskPromise;
- var smask = image.dict.get('SMask');
- var mask = image.dict.get('Mask');
- if (smask) {
- smaskPromise = handleImageData(smask, nativeDecoder);
- maskPromise = Promise.resolve(null);
- } else {
- smaskPromise = Promise.resolve(null);
- if (mask) {
- if ((0, _primitives.isStream)(mask)) {
- maskPromise = handleImageData(mask, nativeDecoder);
- } else if (Array.isArray(mask)) {
- maskPromise = Promise.resolve(mask);
- } else {
- (0, _util.warn)('Unsupported mask format.');
- maskPromise = Promise.resolve(null);
- }
- } else {
- maskPromise = Promise.resolve(null);
- }
- }
- return Promise.all([imagePromise, smaskPromise, maskPromise]).then(function (_ref3) {
- var _ref4 = _slicedToArray(_ref3, 3),
- imageData = _ref4[0],
- smaskData = _ref4[1],
- maskData = _ref4[2];
-
- return new PDFImage({
- xref: xref,
- res: res,
- image: imageData,
- isInline: isInline,
- smask: smaskData,
- mask: maskData,
- pdfFunctionFactory: pdfFunctionFactory
- });
- });
- };
- PDFImage.createMask = function (_ref5) {
- var imgArray = _ref5.imgArray,
- width = _ref5.width,
- height = _ref5.height,
- imageIsFromDecodeStream = _ref5.imageIsFromDecodeStream,
- inverseDecode = _ref5.inverseDecode;
-
- var computedLength = (width + 7 >> 3) * height;
- var actualLength = imgArray.byteLength;
- var haveFullData = computedLength === actualLength;
- var data, i;
- if (imageIsFromDecodeStream && (!inverseDecode || haveFullData)) {
- data = imgArray;
- } else if (!inverseDecode) {
- data = new Uint8ClampedArray(actualLength);
- data.set(imgArray);
- } else {
- data = new Uint8ClampedArray(computedLength);
- data.set(imgArray);
- for (i = actualLength; i < computedLength; i++) {
- data[i] = 0xff;
- }
- }
- if (inverseDecode) {
- for (i = 0; i < actualLength; i++) {
- data[i] ^= 0xFF;
- }
- }
- return {
- data: data,
- width: width,
- height: height
- };
- };
- PDFImage.prototype = {
- get drawWidth() {
- return Math.max(this.width, this.smask && this.smask.width || 0, this.mask && this.mask.width || 0);
- },
- get drawHeight() {
- return Math.max(this.height, this.smask && this.smask.height || 0, this.mask && this.mask.height || 0);
- },
- decodeBuffer: function decodeBuffer(buffer) {
- var bpc = this.bpc;
- var numComps = this.numComps;
- var decodeAddends = this.decodeAddends;
- var decodeCoefficients = this.decodeCoefficients;
- var max = (1 << bpc) - 1;
- var i, ii;
- if (bpc === 1) {
- for (i = 0, ii = buffer.length; i < ii; i++) {
- buffer[i] = +!buffer[i];
- }
- return;
- }
- var index = 0;
- for (i = 0, ii = this.width * this.height; i < ii; i++) {
- for (var j = 0; j < numComps; j++) {
- buffer[index] = decodeAndClamp(buffer[index], decodeAddends[j], decodeCoefficients[j], max);
- index++;
- }
- }
- },
- getComponents: function getComponents(buffer) {
- var bpc = this.bpc;
- if (bpc === 8) {
- return buffer;
- }
- var width = this.width;
- var height = this.height;
- var numComps = this.numComps;
- var length = width * height * numComps;
- var bufferPos = 0;
- var output = bpc <= 8 ? new Uint8Array(length) : bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length);
- var rowComps = width * numComps;
- var max = (1 << bpc) - 1;
- var i = 0,
- ii,
- buf;
- if (bpc === 1) {
- var mask, loop1End, loop2End;
- for (var j = 0; j < height; j++) {
- loop1End = i + (rowComps & ~7);
- loop2End = i + rowComps;
- while (i < loop1End) {
- buf = buffer[bufferPos++];
- output[i] = buf >> 7 & 1;
- output[i + 1] = buf >> 6 & 1;
- output[i + 2] = buf >> 5 & 1;
- output[i + 3] = buf >> 4 & 1;
- output[i + 4] = buf >> 3 & 1;
- output[i + 5] = buf >> 2 & 1;
- output[i + 6] = buf >> 1 & 1;
- output[i + 7] = buf & 1;
- i += 8;
- }
- if (i < loop2End) {
- buf = buffer[bufferPos++];
- mask = 128;
- while (i < loop2End) {
- output[i++] = +!!(buf & mask);
- mask >>= 1;
- }
- }
- }
- } else {
- var bits = 0;
- buf = 0;
- for (i = 0, ii = length; i < ii; ++i) {
- if (i % rowComps === 0) {
- buf = 0;
- bits = 0;
- }
- while (bits < bpc) {
- buf = buf << 8 | buffer[bufferPos++];
- bits += 8;
- }
- var remainingBits = bits - bpc;
- var value = buf >> remainingBits;
- output[i] = value < 0 ? 0 : value > max ? max : value;
- buf = buf & (1 << remainingBits) - 1;
- bits = remainingBits;
- }
- }
- return output;
- },
- fillOpacity: function fillOpacity(rgbaBuf, width, height, actualHeight, image) {
- var smask = this.smask;
- var mask = this.mask;
- var alphaBuf, sw, sh, i, ii, j;
- if (smask) {
- sw = smask.width;
- sh = smask.height;
- alphaBuf = new Uint8ClampedArray(sw * sh);
- smask.fillGrayBuffer(alphaBuf);
- if (sw !== width || sh !== height) {
- alphaBuf = resizeImageMask(alphaBuf, smask.bpc, sw, sh, width, height);
- }
- } else if (mask) {
- if (mask instanceof PDFImage) {
- sw = mask.width;
- sh = mask.height;
- alphaBuf = new Uint8ClampedArray(sw * sh);
- mask.numComps = 1;
- mask.fillGrayBuffer(alphaBuf);
- for (i = 0, ii = sw * sh; i < ii; ++i) {
- alphaBuf[i] = 255 - alphaBuf[i];
- }
- if (sw !== width || sh !== height) {
- alphaBuf = resizeImageMask(alphaBuf, mask.bpc, sw, sh, width, height);
- }
- } else if (Array.isArray(mask)) {
- alphaBuf = new Uint8ClampedArray(width * height);
- var numComps = this.numComps;
- for (i = 0, ii = width * height; i < ii; ++i) {
- var opacity = 0;
- var imageOffset = i * numComps;
- for (j = 0; j < numComps; ++j) {
- var color = image[imageOffset + j];
- var maskOffset = j * 2;
- if (color < mask[maskOffset] || color > mask[maskOffset + 1]) {
- opacity = 255;
- break;
- }
- }
- alphaBuf[i] = opacity;
- }
- } else {
- throw new _util.FormatError('Unknown mask format.');
- }
- }
- if (alphaBuf) {
- for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {
- rgbaBuf[j] = alphaBuf[i];
- }
- } else {
- for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {
- rgbaBuf[j] = 255;
- }
- }
- },
- undoPreblend: function undoPreblend(buffer, width, height) {
- var matte = this.smask && this.smask.matte;
- if (!matte) {
- return;
- }
- var matteRgb = this.colorSpace.getRgb(matte, 0);
- var matteR = matteRgb[0];
- var matteG = matteRgb[1];
- var matteB = matteRgb[2];
- var length = width * height * 4;
- for (var i = 0; i < length; i += 4) {
- var alpha = buffer[i + 3];
- if (alpha === 0) {
- buffer[i] = 255;
- buffer[i + 1] = 255;
- buffer[i + 2] = 255;
- continue;
- }
- var k = 255 / alpha;
- buffer[i] = (buffer[i] - matteR) * k + matteR;
- buffer[i + 1] = (buffer[i + 1] - matteG) * k + matteG;
- buffer[i + 2] = (buffer[i + 2] - matteB) * k + matteB;
- }
- },
- createImageData: function createImageData() {
- var forceRGBA = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
-
- var drawWidth = this.drawWidth;
- var drawHeight = this.drawHeight;
- var imgData = {
- width: drawWidth,
- height: drawHeight,
- kind: 0,
- data: null
- };
- var numComps = this.numComps;
- var originalWidth = this.width;
- var originalHeight = this.height;
- var bpc = this.bpc;
- var rowBytes = originalWidth * numComps * bpc + 7 >> 3;
- var imgArray;
- if (!forceRGBA) {
- var kind;
- if (this.colorSpace.name === 'DeviceGray' && bpc === 1) {
- kind = _util.ImageKind.GRAYSCALE_1BPP;
- } else if (this.colorSpace.name === 'DeviceRGB' && bpc === 8 && !this.needsDecode) {
- kind = _util.ImageKind.RGB_24BPP;
- }
- if (kind && !this.smask && !this.mask && drawWidth === originalWidth && drawHeight === originalHeight) {
- imgData.kind = kind;
- imgArray = this.getImageBytes(originalHeight * rowBytes);
- if (this.image instanceof _stream.DecodeStream) {
- imgData.data = imgArray;
- } else {
- var newArray = new Uint8ClampedArray(imgArray.length);
- newArray.set(imgArray);
- imgData.data = newArray;
- }
- if (this.needsDecode) {
- (0, _util.assert)(kind === _util.ImageKind.GRAYSCALE_1BPP, 'PDFImage.createImageData: The image must be grayscale.');
- var buffer = imgData.data;
- for (var i = 0, ii = buffer.length; i < ii; i++) {
- buffer[i] ^= 0xff;
- }
- }
- return imgData;
- }
- if (this.image instanceof _jpeg_stream.JpegStream && !this.smask && !this.mask) {
- var imageLength = originalHeight * rowBytes;
- switch (this.colorSpace.name) {
- case 'DeviceGray':
- imageLength *= 3;
- case 'DeviceRGB':
- case 'DeviceCMYK':
- imgData.kind = _util.ImageKind.RGB_24BPP;
- imgData.data = this.getImageBytes(imageLength, drawWidth, drawHeight, true);
- return imgData;
- }
- }
- }
- imgArray = this.getImageBytes(originalHeight * rowBytes);
- var actualHeight = 0 | imgArray.length / rowBytes * drawHeight / originalHeight;
- var comps = this.getComponents(imgArray);
- var alpha01, maybeUndoPreblend;
- if (!forceRGBA && !this.smask && !this.mask) {
- imgData.kind = _util.ImageKind.RGB_24BPP;
- imgData.data = new Uint8ClampedArray(drawWidth * drawHeight * 3);
- alpha01 = 0;
- maybeUndoPreblend = false;
- } else {
- imgData.kind = _util.ImageKind.RGBA_32BPP;
- imgData.data = new Uint8ClampedArray(drawWidth * drawHeight * 4);
- alpha01 = 1;
- maybeUndoPreblend = true;
- this.fillOpacity(imgData.data, drawWidth, drawHeight, actualHeight, comps);
- }
- if (this.needsDecode) {
- this.decodeBuffer(comps);
- }
- this.colorSpace.fillRgb(imgData.data, originalWidth, originalHeight, drawWidth, drawHeight, actualHeight, bpc, comps, alpha01);
- if (maybeUndoPreblend) {
- this.undoPreblend(imgData.data, drawWidth, actualHeight);
- }
- return imgData;
- },
- fillGrayBuffer: function fillGrayBuffer(buffer) {
- var numComps = this.numComps;
- if (numComps !== 1) {
- throw new _util.FormatError('Reading gray scale from a color image: ' + numComps);
- }
- var width = this.width;
- var height = this.height;
- var bpc = this.bpc;
- var rowBytes = width * numComps * bpc + 7 >> 3;
- var imgArray = this.getImageBytes(height * rowBytes);
- var comps = this.getComponents(imgArray);
- var i, length;
- if (bpc === 1) {
- length = width * height;
- if (this.needsDecode) {
- for (i = 0; i < length; ++i) {
- buffer[i] = comps[i] - 1 & 255;
- }
- } else {
- for (i = 0; i < length; ++i) {
- buffer[i] = -comps[i] & 255;
- }
- }
- return;
- }
- if (this.needsDecode) {
- this.decodeBuffer(comps);
- }
- length = width * height;
- var scale = 255 / ((1 << bpc) - 1);
- for (i = 0; i < length; ++i) {
- buffer[i] = scale * comps[i];
- }
- },
- getImageBytes: function getImageBytes(length, drawWidth, drawHeight) {
- var forceRGB = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
-
- this.image.reset();
- this.image.drawWidth = drawWidth || this.width;
- this.image.drawHeight = drawHeight || this.height;
- this.image.forceRGB = !!forceRGB;
- return this.image.getBytes(length, true);
- }
- };
- return PDFImage;
-}();
-exports.PDFImage = PDFImage;
-
-/***/ }),
-/* 172 */
-/***/ (function(module, exports, __w_pdfjs_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.MessageHandler = undefined;
-
-var _regenerator = __w_pdfjs_require__(131);
-
-var _regenerator2 = _interopRequireDefault(_regenerator);
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
-
-var resolveCall = function () {
- var _ref = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee(fn, args) {
- var thisArg = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
- return _regenerator2.default.wrap(function _callee$(_context) {
- while (1) {
- switch (_context.prev = _context.next) {
- case 0:
- if (fn) {
- _context.next = 2;
- break;
- }
-
- return _context.abrupt('return');
-
- case 2:
- return _context.abrupt('return', fn.apply(thisArg, args));
-
- case 3:
- case 'end':
- return _context.stop();
- }
- }
- }, _callee, this);
- }));
-
- return function resolveCall(_x2, _x3) {
- return _ref.apply(this, arguments);
- };
-}();
-
-var _util = __w_pdfjs_require__(2);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
-
-function wrapReason(reason) {
- if ((typeof reason === 'undefined' ? 'undefined' : _typeof(reason)) !== 'object') {
- return reason;
- }
- switch (reason.name) {
- case 'AbortException':
- return new _util.AbortException(reason.message);
- case 'MissingPDFException':
- return new _util.MissingPDFException(reason.message);
- case 'UnexpectedResponseException':
- return new _util.UnexpectedResponseException(reason.message, reason.status);
- default:
- return new _util.UnknownErrorException(reason.message, reason.details);
- }
-}
-function makeReasonSerializable(reason) {
- if (!(reason instanceof Error) || reason instanceof _util.AbortException || reason instanceof _util.MissingPDFException || reason instanceof _util.UnexpectedResponseException || reason instanceof _util.UnknownErrorException) {
- return reason;
- }
- return new _util.UnknownErrorException(reason.message, reason.toString());
-}
-function resolveOrReject(capability, success, reason) {
- if (success) {
- capability.resolve();
- } else {
- capability.reject(reason);
- }
-}
-function finalize(promise) {
- return Promise.resolve(promise).catch(function () {});
-}
-function MessageHandler(sourceName, targetName, comObj) {
- var _this = this;
-
- this.sourceName = sourceName;
- this.targetName = targetName;
- this.comObj = comObj;
- this.callbackId = 1;
- this.streamId = 1;
- this.postMessageTransfers = true;
- this.streamSinks = Object.create(null);
- this.streamControllers = Object.create(null);
- var callbacksCapabilities = this.callbacksCapabilities = Object.create(null);
- var ah = this.actionHandler = Object.create(null);
- this._onComObjOnMessage = function (event) {
- var data = event.data;
- if (data.targetName !== _this.sourceName) {
- return;
- }
- if (data.stream) {
- _this._processStreamMessage(data);
- } else if (data.isReply) {
- var callbackId = data.callbackId;
- if (data.callbackId in callbacksCapabilities) {
- var callback = callbacksCapabilities[callbackId];
- delete callbacksCapabilities[callbackId];
- if ('error' in data) {
- callback.reject(wrapReason(data.error));
- } else {
- callback.resolve(data.data);
- }
- } else {
- throw new Error('Cannot resolve callback ' + callbackId);
- }
- } else if (data.action in ah) {
- var action = ah[data.action];
- if (data.callbackId) {
- var _sourceName = _this.sourceName;
- var _targetName = data.sourceName;
- Promise.resolve().then(function () {
- return action[0].call(action[1], data.data);
- }).then(function (result) {
- comObj.postMessage({
- sourceName: _sourceName,
- targetName: _targetName,
- isReply: true,
- callbackId: data.callbackId,
- data: result
- });
- }, function (reason) {
- comObj.postMessage({
- sourceName: _sourceName,
- targetName: _targetName,
- isReply: true,
- callbackId: data.callbackId,
- error: makeReasonSerializable(reason)
- });
- });
- } else if (data.streamId) {
- _this._createStreamSink(data);
- } else {
- action[0].call(action[1], data.data);
- }
- } else {
- throw new Error('Unknown action from worker: ' + data.action);
- }
- };
- comObj.addEventListener('message', this._onComObjOnMessage);
-}
-MessageHandler.prototype = {
- on: function on(actionName, handler, scope) {
- var ah = this.actionHandler;
- if (ah[actionName]) {
- throw new Error('There is already an actionName called "' + actionName + '"');
- }
- ah[actionName] = [handler, scope];
- },
- send: function send(actionName, data, transfers) {
- var message = {
- sourceName: this.sourceName,
- targetName: this.targetName,
- action: actionName,
- data: data
- };
- this.postMessage(message, transfers);
- },
- sendWithPromise: function sendWithPromise(actionName, data, transfers) {
- var callbackId = this.callbackId++;
- var message = {
- sourceName: this.sourceName,
- targetName: this.targetName,
- action: actionName,
- data: data,
- callbackId: callbackId
- };
- var capability = (0, _util.createPromiseCapability)();
- this.callbacksCapabilities[callbackId] = capability;
- try {
- this.postMessage(message, transfers);
- } catch (e) {
- capability.reject(e);
- }
- return capability.promise;
- },
- sendWithStream: function sendWithStream(actionName, data, queueingStrategy, transfers) {
- var _this2 = this;
-
- var streamId = this.streamId++;
- var sourceName = this.sourceName;
- var targetName = this.targetName;
- return new _util.ReadableStream({
- start: function start(controller) {
- var startCapability = (0, _util.createPromiseCapability)();
- _this2.streamControllers[streamId] = {
- controller: controller,
- startCall: startCapability,
- isClosed: false
- };
- _this2.postMessage({
- sourceName: sourceName,
- targetName: targetName,
- action: actionName,
- streamId: streamId,
- data: data,
- desiredSize: controller.desiredSize
- });
- return startCapability.promise;
- },
- pull: function pull(controller) {
- var pullCapability = (0, _util.createPromiseCapability)();
- _this2.streamControllers[streamId].pullCall = pullCapability;
- _this2.postMessage({
- sourceName: sourceName,
- targetName: targetName,
- stream: 'pull',
- streamId: streamId,
- desiredSize: controller.desiredSize
- });
- return pullCapability.promise;
- },
- cancel: function cancel(reason) {
- var cancelCapability = (0, _util.createPromiseCapability)();
- _this2.streamControllers[streamId].cancelCall = cancelCapability;
- _this2.streamControllers[streamId].isClosed = true;
- _this2.postMessage({
- sourceName: sourceName,
- targetName: targetName,
- stream: 'cancel',
- reason: reason,
- streamId: streamId
- });
- return cancelCapability.promise;
- }
- }, queueingStrategy);
- },
- _createStreamSink: function _createStreamSink(data) {
- var _this3 = this;
-
- var self = this;
- var action = this.actionHandler[data.action];
- var streamId = data.streamId;
- var desiredSize = data.desiredSize;
- var sourceName = this.sourceName;
- var targetName = data.sourceName;
- var capability = (0, _util.createPromiseCapability)();
- var sendStreamRequest = function sendStreamRequest(_ref2) {
- var stream = _ref2.stream,
- chunk = _ref2.chunk,
- transfers = _ref2.transfers,
- success = _ref2.success,
- reason = _ref2.reason;
-
- _this3.postMessage({
- sourceName: sourceName,
- targetName: targetName,
- stream: stream,
- streamId: streamId,
- chunk: chunk,
- success: success,
- reason: reason
- }, transfers);
- };
- var streamSink = {
- enqueue: function enqueue(chunk) {
- var size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
- var transfers = arguments[2];
-
- if (this.isCancelled) {
- return;
- }
- var lastDesiredSize = this.desiredSize;
- this.desiredSize -= size;
- if (lastDesiredSize > 0 && this.desiredSize <= 0) {
- this.sinkCapability = (0, _util.createPromiseCapability)();
- this.ready = this.sinkCapability.promise;
- }
- sendStreamRequest({
- stream: 'enqueue',
- chunk: chunk,
- transfers: transfers
- });
- },
- close: function close() {
- if (this.isCancelled) {
- return;
- }
- this.isCancelled = true;
- sendStreamRequest({ stream: 'close' });
- delete self.streamSinks[streamId];
- },
- error: function error(reason) {
- if (this.isCancelled) {
- return;
- }
- this.isCancelled = true;
- sendStreamRequest({
- stream: 'error',
- reason: reason
- });
- },
-
- sinkCapability: capability,
- onPull: null,
- onCancel: null,
- isCancelled: false,
- desiredSize: desiredSize,
- ready: null
- };
- streamSink.sinkCapability.resolve();
- streamSink.ready = streamSink.sinkCapability.promise;
- this.streamSinks[streamId] = streamSink;
- resolveCall(action[0], [data.data, streamSink], action[1]).then(function () {
- sendStreamRequest({
- stream: 'start_complete',
- success: true
- });
- }, function (reason) {
- sendStreamRequest({
- stream: 'start_complete',
- success: false,
- reason: reason
- });
- });
- },
- _processStreamMessage: function _processStreamMessage(data) {
- var _this4 = this;
-
- var sourceName = this.sourceName;
- var targetName = data.sourceName;
- var streamId = data.streamId;
- var sendStreamResponse = function sendStreamResponse(_ref3) {
- var stream = _ref3.stream,
- success = _ref3.success,
- reason = _ref3.reason;
-
- _this4.comObj.postMessage({
- sourceName: sourceName,
- targetName: targetName,
- stream: stream,
- success: success,
- streamId: streamId,
- reason: reason
- });
- };
- var deleteStreamController = function deleteStreamController() {
- Promise.all([_this4.streamControllers[data.streamId].startCall, _this4.streamControllers[data.streamId].pullCall, _this4.streamControllers[data.streamId].cancelCall].map(function (capability) {
- return capability && finalize(capability.promise);
- })).then(function () {
- delete _this4.streamControllers[data.streamId];
- });
- };
- switch (data.stream) {
- case 'start_complete':
- resolveOrReject(this.streamControllers[data.streamId].startCall, data.success, wrapReason(data.reason));
- break;
- case 'pull_complete':
- resolveOrReject(this.streamControllers[data.streamId].pullCall, data.success, wrapReason(data.reason));
- break;
- case 'pull':
- if (!this.streamSinks[data.streamId]) {
- sendStreamResponse({
- stream: 'pull_complete',
- success: true
- });
- break;
- }
- if (this.streamSinks[data.streamId].desiredSize <= 0 && data.desiredSize > 0) {
- this.streamSinks[data.streamId].sinkCapability.resolve();
- }
- this.streamSinks[data.streamId].desiredSize = data.desiredSize;
- resolveCall(this.streamSinks[data.streamId].onPull).then(function () {
- sendStreamResponse({
- stream: 'pull_complete',
- success: true
- });
- }, function (reason) {
- sendStreamResponse({
- stream: 'pull_complete',
- success: false,
- reason: reason
- });
- });
- break;
- case 'enqueue':
- (0, _util.assert)(this.streamControllers[data.streamId], 'enqueue should have stream controller');
- if (!this.streamControllers[data.streamId].isClosed) {
- this.streamControllers[data.streamId].controller.enqueue(data.chunk);
- }
- break;
- case 'close':
- (0, _util.assert)(this.streamControllers[data.streamId], 'close should have stream controller');
- if (this.streamControllers[data.streamId].isClosed) {
- break;
- }
- this.streamControllers[data.streamId].isClosed = true;
- this.streamControllers[data.streamId].controller.close();
- deleteStreamController();
- break;
- case 'error':
- (0, _util.assert)(this.streamControllers[data.streamId], 'error should have stream controller');
- this.streamControllers[data.streamId].controller.error(wrapReason(data.reason));
- deleteStreamController();
- break;
- case 'cancel_complete':
- resolveOrReject(this.streamControllers[data.streamId].cancelCall, data.success, wrapReason(data.reason));
- deleteStreamController();
- break;
- case 'cancel':
- if (!this.streamSinks[data.streamId]) {
- break;
- }
- resolveCall(this.streamSinks[data.streamId].onCancel, [wrapReason(data.reason)]).then(function () {
- sendStreamResponse({
- stream: 'cancel_complete',
- success: true
- });
- }, function (reason) {
- sendStreamResponse({
- stream: 'cancel_complete',
- success: false,
- reason: reason
- });
- });
- this.streamSinks[data.streamId].sinkCapability.reject(wrapReason(data.reason));
- this.streamSinks[data.streamId].isCancelled = true;
- delete this.streamSinks[data.streamId];
- break;
- default:
- throw new Error('Unexpected stream case');
- }
- },
- postMessage: function postMessage(message, transfers) {
- if (transfers && this.postMessageTransfers) {
- this.comObj.postMessage(message, transfers);
- } else {
- this.comObj.postMessage(message);
- }
- },
- destroy: function destroy() {
- this.comObj.removeEventListener('message', this._onComObjOnMessage);
- }
-};
-exports.MessageHandler = MessageHandler;
-
-/***/ })
-/******/ ]);
-});
-//# sourceMappingURL=pdf.worker.js.map \ No newline at end of file
diff --git a/vendor/assets/javascripts/pdf.worker.min.js b/vendor/assets/javascripts/pdf.worker.min.js
deleted file mode 100644
index 31516d160ab..00000000000
--- a/vendor/assets/javascripts/pdf.worker.min.js
+++ /dev/null
@@ -1 +0,0 @@
-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("pdfjs-dist/build/pdf.worker",[],t):"object"==typeof exports?exports["pdfjs-dist/build/pdf.worker"]=t():e["pdfjs-dist/build/pdf.worker"]=e.pdfjsWorker=t()}(this,function(){return function(e){var t={};function r(a){if(t[a])return t[a].exports;var i=t[a]={i:a,l:!1,exports:{}};e[a].call(i.exports,i,i.exports,r);i.l=!0;return i.exports}r.m=e;r.c=t;r.d=function(e,t,a){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:a})};r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"});Object.defineProperty(e,"__esModule",{value:!0})};r.t=function(e,t){1&t&&(e=r(e));if(8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var a=Object.create(null);r.r(a);Object.defineProperty(a,"default",{enumerable:!0,value:e});if(2&t&&"string"!=typeof e)for(var i in e)r.d(a,i,function(t){return e[t]}.bind(null,i));return a};r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};r.d(t,"a",t);return t};r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};r.p="";return r(r.s=0)}([function(e,t,r){"use strict";var a=r(1);t.WorkerMessageHandler=a.WorkerMessageHandler},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.WorkerMessageHandler=t.WorkerTask=void 0;var a,i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n=function(){return function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var r=[],a=!0,i=!1,n=void 0;try{for(var o,s=e[Symbol.iterator]();!(a=(o=s.next()).done);a=!0){r.push(o.value);if(t&&r.length===t)break}}catch(e){i=!0;n=e}finally{try{!a&&s.return&&s.return()}finally{if(i)throw n}}return r}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),o=r(2),s=r(130),c=r(5),l=(a=c)&&a.__esModule?a:{default:a},u=r(172),h=r(138);var f,d=function(){function e(e){this.name=e;this.terminated=!1;this._capability=(0,o.createPromiseCapability)()}e.prototype={get finished(){return this._capability.promise},finish:function(){this._capability.resolve()},terminate:function(){this.terminated=!0},ensureNotTerminated:function(){if(this.terminated)throw new Error("Worker task was terminated")}};return e}(),g=function(){function e(e){this._msgHandler=e;this._contentLength=null;this._fullRequestReader=null;this._rangeRequestReaders=[]}e.prototype={getFullReader:function(){(0,o.assert)(!this._fullRequestReader);this._fullRequestReader=new t(this._msgHandler);return this._fullRequestReader},getRangeReader:function(e,t){var a=new r(e,t,this._msgHandler);this._rangeRequestReaders.push(a);return a},cancelAllRequests:function(e){this._fullRequestReader&&this._fullRequestReader.cancel(e);this._rangeRequestReaders.slice(0).forEach(function(t){t.cancel(e)})}};function t(e){var t=this;this._msgHandler=e;this._contentLength=null;this._isRangeSupported=!1;this._isStreamingSupported=!1;var r=this._msgHandler.sendWithStream("GetReader");this._reader=r.getReader();this._headersReady=this._msgHandler.sendWithPromise("ReaderHeadersReady").then(function(e){t._isStreamingSupported=e.isStreamingSupported;t._isRangeSupported=e.isRangeSupported;t._contentLength=e.contentLength})}t.prototype={get headersReady(){return this._headersReady},get contentLength(){return this._contentLength},get isStreamingSupported(){return this._isStreamingSupported},get isRangeSupported(){return this._isRangeSupported},read:function(){return this._reader.read().then(function(e){var t=e.value;return e.done?{value:void 0,done:!0}:{value:t.buffer,done:!1}})},cancel:function(e){this._reader.cancel(e)}};function r(e,t,r){this._msgHandler=r;this.onProgress=null;var a=this._msgHandler.sendWithStream("GetRangeReader",{begin:e,end:t});this._reader=a.getReader()}r.prototype={get isStreamingSupported(){return!1},read:function(){return this._reader.read().then(function(e){var t=e.value;return e.done?{value:void 0,done:!0}:{value:t.buffer,done:!1}})},cancel:function(e){this._reader.cancel(e)}};return e}(),m={setup:function(e,t){var r=!1;e.on("test",function(t){if(!r){r=!0;if(t instanceof Uint8Array){var a=255===t[0];e.postMessageTransfers=a;var i=new XMLHttpRequest,n="response"in i;try{i.responseType}catch(e){n=!1}n?e.send("test",{supportTypedArray:!0,supportTransfers:a}):e.send("test",!1)}else e.send("test",!1)}});e.on("configure",function(e){(0,o.setVerbosityLevel)(e.verbosity)});e.on("GetDocRequest",function(e){return m.createDocumentHandler(e,t)})},createDocumentHandler:function(e,t){var r,a=!1,c=null,l=[],f=e.apiVersion;if("2.0.943"!==f)throw new Error('The API version "'+f+'" does not match the Worker version "2.0.943".');var m=e.docId,p=e.docBaseUrl,v=e.docId+"_worker",b=new u.MessageHandler(v,m,t);b.postMessageTransfers=e.postMessageTransfers;function y(){if(a)throw new Error("Worker was terminated")}function w(e){l.push(e)}function k(e){e.finish();var t=l.indexOf(e);l.splice(t,1)}function S(e){var t=(0,o.createPromiseCapability)(),a=function(){Promise.all([r.ensureDoc("numPages"),r.ensureDoc("fingerprint")]).then(function(e){var r=n(e,2),a=r[0],i=r[1];t.resolve({numPages:a,fingerprint:i})},i)},i=function(e){t.reject(e)};r.ensureDoc("checkHeader",[]).then(function(){r.ensureDoc("parseStartXRef",[]).then(function(){r.ensureDoc("parse",[e]).then(a,i)},i)},i);return t.promise}function C(e,t){var r,a=(0,o.createPromiseCapability)(),i=e.source;if(i.data){try{r=new s.LocalPdfManager(m,i.data,i.password,t,p);a.resolve(r)}catch(e){a.reject(e)}return a.promise}var n,l=[];try{n=new g(b)}catch(e){a.reject(e);return a.promise}var u=n.getFullReader();u.headersReady.then(function(){if(u.isRangeSupported){var e=i.disableAutoFetch||u.isStreamingSupported;r=new s.NetworkPdfManager(m,n,{msgHandler:b,url:i.url,password:i.password,length:u.contentLength,disableAutoFetch:e,rangeChunkSize:i.rangeChunkSize},t,p);for(var o=0;o<l.length;o++)r.sendProgressiveData(l[o]);l=[];a.resolve(r);c=null}}).catch(function(e){a.reject(e);c=null});var h=0;new Promise(function(e,n){u.read().then(function e(f){try{y();if(f.done){r||function(){var e=(0,o.arraysToBytes)(l);i.length&&e.length!==i.length&&(0,o.warn)("reported HTTP length is different from actual");try{r=new s.LocalPdfManager(m,e,i.password,t,p);a.resolve(r)}catch(e){a.reject(e)}l=[]}();c=null;return}var d=f.value;h+=(0,o.arrayByteLength)(d);u.isStreamingSupported||b.send("DocProgress",{loaded:h,total:Math.max(h,u.contentLength||0)});r?r.sendProgressiveData(d):l.push(d);u.read().then(e,n)}catch(e){n(e)}},n)}).catch(function(e){a.reject(e);c=null});c=function(){n.cancelAllRequests("abort")};return a.promise}b.on("GetPage",function(e){return r.getPage(e.pageIndex).then(function(e){return Promise.all([r.ensure(e,"rotate"),r.ensure(e,"ref"),r.ensure(e,"userUnit"),r.ensure(e,"view")]).then(function(e){var t=n(e,4);return{rotate:t[0],ref:t[1],userUnit:t[2],view:t[3]}})})});b.on("GetPageIndex",function(e){var t=new h.Ref(e.ref.num,e.ref.gen);return r.pdfDocument.catalog.getPageIndex(t)});b.on("GetDestinations",function(e){return r.ensureCatalog("destinations")});b.on("GetDestination",function(e){return r.ensureCatalog("getDestination",[e.id])});b.on("GetPageLabels",function(e){return r.ensureCatalog("pageLabels")});b.on("GetPageMode",function(e){return r.ensureCatalog("pageMode")});b.on("GetAttachments",function(e){return r.ensureCatalog("attachments")});b.on("GetJavaScript",function(e){return r.ensureCatalog("javaScript")});b.on("GetOutline",function(e){return r.ensureCatalog("documentOutline")});b.on("GetPermissions",function(e){return r.ensureCatalog("permissions")});b.on("GetMetadata",function(e){return Promise.all([r.ensureDoc("documentInfo"),r.ensureCatalog("metadata")])});b.on("GetData",function(e){r.requestLoadedStream();return r.onLoadedStream().then(function(e){return e.bytes})});b.on("GetStats",function(e){return r.pdfDocument.xref.stats});b.on("GetAnnotations",function(e){var t=e.pageIndex,a=e.intent;return r.getPage(t).then(function(e){return e.getAnnotationsData(a)})});b.on("RenderPageRequest",function(e){var t=e.pageIndex;r.getPage(t).then(function(r){var a=new d("RenderPageRequest: page "+t);w(a);var n=t+1,s=Date.now();r.getOperatorList({handler:b,task:a,intent:e.intent,renderInteractiveForms:e.renderInteractiveForms}).then(function(e){k(a);(0,o.info)("page="+n+" - getOperatorList: time="+(Date.now()-s)+"ms, len="+e.totalLength)},function(t){k(a);if(!a.terminated){b.send("UnsupportedFeature",{featureId:o.UNSUPPORTED_FEATURES.unknown});var r,s="worker.js: while trying to getPage() and getOperatorList()";r="string"==typeof t?{message:t,stack:s}:"object"===(void 0===t?"undefined":i(t))?{message:t.message||t.toString(),stack:t.stack||s}:{message:"Unknown exception type: "+(void 0===t?"undefined":i(t)),stack:s};b.send("PageError",{pageNum:n,error:r,intent:e.intent})}})})},this);b.on("GetTextContent",function(e,t){var a=e.pageIndex;t.onPull=function(e){};t.onCancel=function(e){};r.getPage(a).then(function(r){var i=new d("GetTextContent: page "+a);w(i);var n=a+1,s=Date.now();r.extractTextContent({handler:b,task:i,sink:t,normalizeWhitespace:e.normalizeWhitespace,combineTextItems:e.combineTextItems}).then(function(){k(i);(0,o.info)("text indexing: page="+n+" - time="+(Date.now()-s)+"ms");t.close()},function(e){k(i);if(!i.terminated){t.error(e);throw e}})})});b.on("Cleanup",function(e){return r.cleanup()});b.on("Terminate",function(e){a=!0;if(r){r.terminate();r=null}c&&c();var t=[];l.forEach(function(e){t.push(e.finished);e.terminate()});return Promise.all(t).then(function(){b.destroy();b=null})});b.on("Ready",function(t){!function(e){function t(e){y();b.send("GetDoc",{pdfInfo:e})}function i(e){y();if(e instanceof o.PasswordException){var t=new d("PasswordException: response "+e.code);w(t);b.sendWithPromise("PasswordRequest",e).then(function(e){k(t);r.updatePassword(e.password);n()}).catch(function(e){k(t);b.send("PasswordException",e)}.bind(null,e))}else e instanceof o.InvalidPDFException?b.send("InvalidPDF",e):e instanceof o.MissingPDFException?b.send("MissingPDF",e):e instanceof o.UnexpectedResponseException?b.send("UnexpectedResponse",e):b.send("UnknownError",new o.UnknownErrorException(e.message,e.toString()))}function n(){y();S(!1).then(t,function(e){y();if(e instanceof o.XRefParseException){r.requestLoadedStream();r.onLoadedStream().then(function(){y();S(!0).then(t,i)})}else i(e)},i)}y();C(e,{forceDataSchema:e.disableCreateObjectURL,maxImageSize:e.maxImageSize,disableFontFace:e.disableFontFace,nativeImageDecoderSupport:e.nativeImageDecoderSupport,ignoreErrors:e.ignoreErrors,isEvalSupported:e.isEvalSupported}).then(function(e){if(a){e.terminate();throw new Error("Worker was terminated")}(r=e).onLoadedStream().then(function(e){b.send("DataLoaded",{length:e.bytes.byteLength})})}).then(n,i)}(e);e=null});return v},initializeFromPort:function(e){var t=new u.MessageHandler("worker","main",e);m.setup(t,e);t.send("ready",null)}};"undefined"==typeof window&&!(0,l.default)()&&"undefined"!=typeof self&&("function"==typeof(f=self).postMessage&&"onmessage"in f)&&m.initializeFromPort(self);t.WorkerTask=d;t.WorkerMessageHandler=m},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.unreachable=t.warn=t.utf8StringToString=t.stringToUTF8String=t.stringToPDFString=t.stringToBytes=t.string32=t.shadow=t.setVerbosityLevel=t.URL=t.ReadableStream=t.removeNullCharacters=t.readUint32=t.readUint16=t.readInt8=t.log2=t.isEvalSupported=t.isLittleEndian=t.createValidAbsoluteUrl=t.isSameOrigin=t.isSpace=t.isString=t.isNum=t.isEmptyObj=t.isBool=t.isArrayBuffer=t.info=t.getVerbosityLevel=t.getLookupTableFactory=t.getInheritableProperty=t.deprecated=t.createObjectURL=t.createPromiseCapability=t.bytesToString=t.assert=t.arraysToBytes=t.arrayByteLength=t.FormatError=t.XRefParseException=t.toRomanNumerals=t.Util=t.UnknownErrorException=t.UnexpectedResponseException=t.TextRenderingMode=t.StreamType=t.PermissionFlag=t.PasswordResponses=t.PasswordException=t.NativeImageDecoding=t.MissingPDFException=t.MissingDataException=t.InvalidPDFException=t.AbortException=t.CMapCompressionType=t.ImageKind=t.FontType=t.AnnotationType=t.AnnotationFlag=t.AnnotationFieldFlag=t.AnnotationBorderStyleType=t.UNSUPPORTED_FEATURES=t.VerbosityLevel=t.OPS=t.IDENTITY_MATRIX=t.FONT_IDENTITY_MATRIX=void 0;var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};r(3);var i=r(126),n=r(128),o={ERRORS:0,WARNINGS:1,INFOS:5},s=o.WARNINGS;function c(e){s>=o.WARNINGS&&console.log("Warning: "+e)}function l(e){throw new Error(e)}function u(e,t){e||l(t)}var h=function(){function e(e,t){this.name="PasswordException";this.message=e;this.code=t}e.prototype=new Error;e.constructor=e;return e}(),f=function(){function e(e,t){this.name="UnknownErrorException";this.message=e;this.details=t}e.prototype=new Error;e.constructor=e;return e}(),d=function(){function e(e){this.name="InvalidPDFException";this.message=e}e.prototype=new Error;e.constructor=e;return e}(),g=function(){function e(e){this.name="MissingPDFException";this.message=e}e.prototype=new Error;e.constructor=e;return e}(),m=function(){function e(e,t){this.name="UnexpectedResponseException";this.message=e;this.status=t}e.prototype=new Error;e.constructor=e;return e}(),p=function(){function e(e,t){this.begin=e;this.end=t;this.message="Missing data ["+e+", "+t+")"}e.prototype=new Error;e.prototype.name="MissingDataException";e.constructor=e;return e}(),v=function(){function e(e){this.message=e}e.prototype=new Error;e.prototype.name="XRefParseException";e.constructor=e;return e}(),b=function(){function e(e){this.message=e}e.prototype=new Error;e.prototype.name="FormatError";e.constructor=e;return e}(),y=function(){function e(e){this.name="AbortException";this.message=e}e.prototype=new Error;e.constructor=e;return e}(),w=/\x00/g;function k(e){u("string"==typeof e,"Invalid argument for stringToBytes");for(var t=e.length,r=new Uint8Array(t),a=0;a<t;++a)r[a]=255&e.charCodeAt(a);return r}function S(e){if(void 0!==e.length)return e.length;u(void 0!==e.byteLength);return e.byteLength}var C=function(){function e(){}var t=["rgb(",0,",",0,",",0,")"];e.makeCssRgb=function(e,r,a){t[1]=e;t[3]=r;t[5]=a;return t.join("")};e.transform=function(e,t){return[e[0]*t[0]+e[2]*t[1],e[1]*t[0]+e[3]*t[1],e[0]*t[2]+e[2]*t[3],e[1]*t[2]+e[3]*t[3],e[0]*t[4]+e[2]*t[5]+e[4],e[1]*t[4]+e[3]*t[5]+e[5]]};e.applyTransform=function(e,t){return[e[0]*t[0]+e[1]*t[2]+t[4],e[0]*t[1]+e[1]*t[3]+t[5]]};e.applyInverseTransform=function(e,t){var r=t[0]*t[3]-t[1]*t[2];return[(e[0]*t[3]-e[1]*t[2]+t[2]*t[5]-t[4]*t[3])/r,(-e[0]*t[1]+e[1]*t[0]+t[4]*t[1]-t[5]*t[0])/r]};e.getAxialAlignedBoundingBox=function(t,r){var a=e.applyTransform(t,r),i=e.applyTransform(t.slice(2,4),r),n=e.applyTransform([t[0],t[3]],r),o=e.applyTransform([t[2],t[1]],r);return[Math.min(a[0],i[0],n[0],o[0]),Math.min(a[1],i[1],n[1],o[1]),Math.max(a[0],i[0],n[0],o[0]),Math.max(a[1],i[1],n[1],o[1])]};e.inverseTransform=function(e){var t=e[0]*e[3]-e[1]*e[2];return[e[3]/t,-e[1]/t,-e[2]/t,e[0]/t,(e[2]*e[5]-e[4]*e[3])/t,(e[4]*e[1]-e[5]*e[0])/t]};e.apply3dTransform=function(e,t){return[e[0]*t[0]+e[1]*t[1]+e[2]*t[2],e[3]*t[0]+e[4]*t[1]+e[5]*t[2],e[6]*t[0]+e[7]*t[1]+e[8]*t[2]]};e.singularValueDecompose2dScale=function(e){var t=[e[0],e[2],e[1],e[3]],r=e[0]*t[0]+e[1]*t[2],a=e[0]*t[1]+e[1]*t[3],i=e[2]*t[0]+e[3]*t[2],n=e[2]*t[1]+e[3]*t[3],o=(r+n)/2,s=Math.sqrt((r+n)*(r+n)-4*(r*n-i*a))/2,c=o+s||1,l=o-s||1;return[Math.sqrt(c),Math.sqrt(l)]};e.normalizeRect=function(e){var t=e.slice(0);if(e[0]>e[2]){t[0]=e[2];t[2]=e[0]}if(e[1]>e[3]){t[1]=e[3];t[3]=e[1]}return t};e.intersect=function(t,r){function a(e,t){return e-t}var i=[t[0],t[2],r[0],r[2]].sort(a),n=[t[1],t[3],r[1],r[3]].sort(a),o=[];t=e.normalizeRect(t);r=e.normalizeRect(r);if(!(i[0]===t[0]&&i[1]===r[0]||i[0]===r[0]&&i[1]===t[0]))return!1;o[0]=i[1];o[2]=i[2];if(!(n[0]===t[1]&&n[1]===r[1]||n[0]===r[1]&&n[1]===t[1]))return!1;o[1]=n[1];o[3]=n[2];return o};return e}(),x=["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM","","X","XX","XXX","XL","L","LX","LXX","LXXX","XC","","I","II","III","IV","V","VI","VII","VIII","IX"];var _=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,728,711,710,729,733,731,730,732,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8226,8224,8225,8230,8212,8211,402,8260,8249,8250,8722,8240,8222,8220,8221,8216,8217,8218,8482,64257,64258,321,338,352,376,381,305,322,339,353,382,0,8364];var A,P=(A="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",function(e,t){if(!(arguments.length>2&&void 0!==arguments[2]&&arguments[2])&&n.URL.createObjectURL){var r=new Blob([e],{type:t});return n.URL.createObjectURL(r)}for(var a="data:"+t+";base64,",i=0,o=e.length;i<o;i+=3){var s=255&e[i],c=255&e[i+1],l=255&e[i+2];a+=A[s>>2]+A[(3&s)<<4|c>>4]+A[i+1<o?(15&c)<<2|l>>6:64]+A[i+2<o?63&l:64]}return a});t.FONT_IDENTITY_MATRIX=[.001,0,0,.001,0,0];t.IDENTITY_MATRIX=[1,0,0,1,0,0];t.OPS={dependency:1,setLineWidth:2,setLineCap:3,setLineJoin:4,setMiterLimit:5,setDash:6,setRenderingIntent:7,setFlatness:8,setGState:9,save:10,restore:11,transform:12,moveTo:13,lineTo:14,curveTo:15,curveTo2:16,curveTo3:17,closePath:18,rectangle:19,stroke:20,closeStroke:21,fill:22,eoFill:23,fillStroke:24,eoFillStroke:25,closeFillStroke:26,closeEOFillStroke:27,endPath:28,clip:29,eoClip:30,beginText:31,endText:32,setCharSpacing:33,setWordSpacing:34,setHScale:35,setLeading:36,setFont:37,setTextRenderingMode:38,setTextRise:39,moveText:40,setLeadingMoveText:41,setTextMatrix:42,nextLine:43,showText:44,showSpacedText:45,nextLineShowText:46,nextLineSetSpacingShowText:47,setCharWidth:48,setCharWidthAndBounds:49,setStrokeColorSpace:50,setFillColorSpace:51,setStrokeColor:52,setStrokeColorN:53,setFillColor:54,setFillColorN:55,setStrokeGray:56,setFillGray:57,setStrokeRGBColor:58,setFillRGBColor:59,setStrokeCMYKColor:60,setFillCMYKColor:61,shadingFill:62,beginInlineImage:63,beginImageData:64,endInlineImage:65,paintXObject:66,markPoint:67,markPointProps:68,beginMarkedContent:69,beginMarkedContentProps:70,endMarkedContent:71,beginCompat:72,endCompat:73,paintFormXObjectBegin:74,paintFormXObjectEnd:75,beginGroup:76,endGroup:77,beginAnnotations:78,endAnnotations:79,beginAnnotation:80,endAnnotation:81,paintJpegXObject:82,paintImageMaskXObject:83,paintImageMaskXObjectGroup:84,paintImageXObject:85,paintInlineImageXObject:86,paintInlineImageXObjectGroup:87,paintImageXObjectRepeat:88,paintImageMaskXObjectRepeat:89,paintSolidColorImageMask:90,constructPath:91};t.VerbosityLevel=o;t.UNSUPPORTED_FEATURES={unknown:"unknown",forms:"forms",javaScript:"javaScript",smask:"smask",shadingPattern:"shadingPattern",font:"font"};t.AnnotationBorderStyleType={SOLID:1,DASHED:2,BEVELED:3,INSET:4,UNDERLINE:5};t.AnnotationFieldFlag={READONLY:1,REQUIRED:2,NOEXPORT:4,MULTILINE:4096,PASSWORD:8192,NOTOGGLETOOFF:16384,RADIO:32768,PUSHBUTTON:65536,COMBO:131072,EDIT:262144,SORT:524288,FILESELECT:1048576,MULTISELECT:2097152,DONOTSPELLCHECK:4194304,DONOTSCROLL:8388608,COMB:16777216,RICHTEXT:33554432,RADIOSINUNISON:33554432,COMMITONSELCHANGE:67108864};t.AnnotationFlag={INVISIBLE:1,HIDDEN:2,PRINT:4,NOZOOM:8,NOROTATE:16,NOVIEW:32,READONLY:64,LOCKED:128,TOGGLENOVIEW:256,LOCKEDCONTENTS:512};t.AnnotationType={TEXT:1,LINK:2,FREETEXT:3,LINE:4,SQUARE:5,CIRCLE:6,POLYGON:7,POLYLINE:8,HIGHLIGHT:9,UNDERLINE:10,SQUIGGLY:11,STRIKEOUT:12,STAMP:13,CARET:14,INK:15,POPUP:16,FILEATTACHMENT:17,SOUND:18,MOVIE:19,WIDGET:20,SCREEN:21,PRINTERMARK:22,TRAPNET:23,WATERMARK:24,THREED:25,REDACT:26};t.FontType={UNKNOWN:0,TYPE1:1,TYPE1C:2,CIDFONTTYPE0:3,CIDFONTTYPE0C:4,TRUETYPE:5,CIDFONTTYPE2:6,TYPE3:7,OPENTYPE:8,TYPE0:9,MMTYPE1:10};t.ImageKind={GRAYSCALE_1BPP:1,RGB_24BPP:2,RGBA_32BPP:3};t.CMapCompressionType={NONE:0,BINARY:1,STREAM:2};t.AbortException=y;t.InvalidPDFException=d;t.MissingDataException=p;t.MissingPDFException=g;t.NativeImageDecoding={NONE:"none",DECODE:"decode",DISPLAY:"display"};t.PasswordException=h;t.PasswordResponses={NEED_PASSWORD:1,INCORRECT_PASSWORD:2};t.PermissionFlag={PRINT:4,MODIFY_CONTENTS:8,COPY:16,MODIFY_ANNOTATIONS:32,FILL_INTERACTIVE_FORMS:256,COPY_FOR_ACCESSIBILITY:512,ASSEMBLE:1024,PRINT_HIGH_QUALITY:2048};t.StreamType={UNKNOWN:0,FLATE:1,LZW:2,DCT:3,JPX:4,JBIG:5,A85:6,AHX:7,CCF:8,RL:9};t.TextRenderingMode={FILL:0,STROKE:1,FILL_STROKE:2,INVISIBLE:3,FILL_ADD_TO_PATH:4,STROKE_ADD_TO_PATH:5,FILL_STROKE_ADD_TO_PATH:6,ADD_TO_PATH:7,FILL_STROKE_MASK:3,ADD_TO_PATH_FLAG:4};t.UnexpectedResponseException=m;t.UnknownErrorException=f;t.Util=C;t.toRomanNumerals=function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];u(Number.isInteger(e)&&e>0,"The number should be a positive integer.");for(var r=void 0,a=[];e>=1e3;){e-=1e3;a.push("M")}r=e/100|0;e%=100;a.push(x[r]);r=e/10|0;e%=10;a.push(x[10+r]);a.push(x[20+e]);var i=a.join("");return t?i.toLowerCase():i};t.XRefParseException=v;t.FormatError=b;t.arrayByteLength=S;t.arraysToBytes=function(e){if(1===e.length&&e[0]instanceof Uint8Array)return e[0];var t,r,a,i=0,n=e.length;for(t=0;t<n;t++)i+=a=S(r=e[t]);var o=0,s=new Uint8Array(i);for(t=0;t<n;t++){(r=e[t])instanceof Uint8Array||(r="string"==typeof r?k(r):new Uint8Array(r));a=r.byteLength;s.set(r,o);o+=a}return s};t.assert=u;t.bytesToString=function(e){u(null!==e&&"object"===(void 0===e?"undefined":a(e))&&void 0!==e.length,"Invalid argument for bytesToString");var t=e.length;if(t<8192)return String.fromCharCode.apply(null,e);for(var r=[],i=0;i<t;i+=8192){var n=Math.min(i+8192,t),o=e.subarray(i,n);r.push(String.fromCharCode.apply(null,o))}return r.join("")};t.createPromiseCapability=function(){var e={};e.promise=new Promise(function(t,r){e.resolve=t;e.reject=r});return e};t.createObjectURL=P;t.deprecated=function(e){console.log("Deprecated API usage: "+e)};t.getInheritableProperty=function(e){for(var t=e.dict,r=e.key,a=e.getArray,i=void 0!==a&&a,n=e.stopWhenFound,o=void 0===n||n,s=0,l=void 0;t;){var u=i?t.getArray(r):t.get(r);if(void 0!==u){if(o)return u;l||(l=[]);l.push(u)}if(++s>100){c('getInheritableProperty: maximum loop count exceeded for "'+r+'"');break}t=t.get("Parent")}return l};t.getLookupTableFactory=function(e){var t;return function(){if(e){t=Object.create(null);e(t);e=null}return t}};t.getVerbosityLevel=function(){return s};t.info=function(e){s>=o.INFOS&&console.log("Info: "+e)};t.isArrayBuffer=function(e){return"object"===(void 0===e?"undefined":a(e))&&null!==e&&void 0!==e.byteLength};t.isBool=function(e){return"boolean"==typeof e};t.isEmptyObj=function(e){for(var t in e)return!1;return!0};t.isNum=function(e){return"number"==typeof e};t.isString=function(e){return"string"==typeof e};t.isSpace=function(e){return 32===e||9===e||13===e||10===e};t.isSameOrigin=function(e,t){try{var r=new n.URL(e);if(!r.origin||"null"===r.origin)return!1}catch(e){return!1}var a=new n.URL(t,r);return r.origin===a.origin};t.createValidAbsoluteUrl=function(e,t){if(!e)return null;try{var r=t?new n.URL(e,t):new n.URL(e);if(function(e){if(!e)return!1;switch(e.protocol){case"http:":case"https:":case"ftp:":case"mailto:":case"tel:":return!0;default:return!1}}(r))return r}catch(e){}return null};t.isLittleEndian=function(){var e=new Uint8Array(4);e[0]=1;return 1===new Uint32Array(e.buffer,0,1)[0]};t.isEvalSupported=function(){try{new Function("");return!0}catch(e){return!1}};t.log2=function(e){return e<=0?0:Math.ceil(Math.log2(e))};t.readInt8=function(e,t){return e[t]<<24>>24};t.readUint16=function(e,t){return e[t]<<8|e[t+1]};t.readUint32=function(e,t){return(e[t]<<24|e[t+1]<<16|e[t+2]<<8|e[t+3])>>>0};t.removeNullCharacters=function(e){if("string"!=typeof e){c("The argument for removeNullCharacters must be a string.");return e}return e.replace(w,"")};t.ReadableStream=i.ReadableStream;t.URL=n.URL;t.setVerbosityLevel=function(e){Number.isInteger(e)&&(s=e)};t.shadow=function(e,t,r){Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!1});return r};t.string32=function(e){return String.fromCharCode(e>>24&255,e>>16&255,e>>8&255,255&e)};t.stringToBytes=k;t.stringToPDFString=function(e){var t,r=e.length,a=[];if("þ"===e[0]&&"ÿ"===e[1])for(t=2;t<r;t+=2)a.push(String.fromCharCode(e.charCodeAt(t)<<8|e.charCodeAt(t+1)));else for(t=0;t<r;++t){var i=_[e.charCodeAt(t)];a.push(i?String.fromCharCode(i):e.charAt(t))}return a.join("")};t.stringToUTF8String=function(e){return decodeURIComponent(escape(e))};t.utf8StringToString=function(e){return unescape(encodeURIComponent(e))};t.warn=c;t.unreachable=l},function(e,t,r){"use strict";var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i=r(4);if(!i._pdfjsCompatibilityChecked){i._pdfjsCompatibilityChecked=!0;var n=r(5),o="object"===("undefined"==typeof window?"undefined":a(window))&&"object"===("undefined"==typeof document?"undefined":a(document));!i.btoa&&n()&&(i.btoa=function(e){return Buffer.from(e,"binary").toString("base64")});!i.atob&&n()&&(i.atob=function(e){return Buffer.from(e,"base64").toString("binary")});o&&("currentScript"in document||Object.defineProperty(document,"currentScript",{get:function(){var e=document.getElementsByTagName("script");return e[e.length-1]},enumerable:!0,configurable:!0}));o&&void 0===Element.prototype.remove&&(Element.prototype.remove=function(){this.parentNode&&this.parentNode.removeChild(this)});!function(){if(o&&!n()){if(!1!==document.createElement("div").classList.toggle("test",0)){var e=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(t){if(arguments.length>1){var r=!!arguments[1];return this[r?"add":"remove"](t),r}return e(t)}}}}();String.prototype.includes||r(6);Array.prototype.includes||r(34);Object.assign||r(43);Math.log2||(Math.log2=r(53));Number.isNaN||(Number.isNaN=r(55));Number.isInteger||(Number.isInteger=r(57));i.Promise||(i.Promise=r(60));i.WeakMap||(i.WeakMap=r(95));String.codePointAt||(String.codePointAt=r(112));String.fromCodePoint||(String.fromCodePoint=r(114));i.Symbol||r(116);Object.values||(Object.values=r(123))}},function(e,t,r){"use strict";e.exports="undefined"!=typeof window&&window.Math===Math?window:"undefined"!=typeof global&&global.Math===Math?global:"undefined"!=typeof self&&self.Math===Math?self:{}},function(e,t,r){"use strict";var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};e.exports=function(){return"object"===("undefined"==typeof process?"undefined":a(process))&&process+""=="[object process]"}},function(e,t,r){"use strict";r(7);e.exports=r(10).String.includes},function(e,t,r){"use strict";var a=r(8),i=r(26);a(a.P+a.F*r(33)("includes"),"String",{includes:function(e){return!!~i(this,e,"includes").indexOf(e,arguments.length>1?arguments[1]:void 0)}})},function(e,t,r){"use strict";var a=r(9),i=r(10),n=r(11),o=r(21),s=r(24),c=function e(t,r,c){var l,u,h,f,d=t&e.F,g=t&e.G,m=t&e.P,p=t&e.B,v=g?a:t&e.S?a[r]||(a[r]={}):(a[r]||{}).prototype,b=g?i:i[r]||(i[r]={}),y=b.prototype||(b.prototype={});g&&(c=r);for(l in c){h=((u=!d&&v&&void 0!==v[l])?v:c)[l];f=p&&u?s(h,a):m&&"function"==typeof h?s(Function.call,h):h;v&&o(v,l,h,t&e.U);b[l]!=h&&n(b,l,f);m&&y[l]!=h&&(y[l]=h)}};a.core=i;c.F=1;c.G=2;c.S=4;c.P=8;c.B=16;c.W=32;c.U=64;c.R=128;e.exports=c},function(e,t,r){"use strict";var a=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=a)},function(e,t,r){"use strict";var a=e.exports={version:"2.5.7"};"number"==typeof __e&&(__e=a)},function(e,t,r){"use strict";var a=r(12),i=r(20);e.exports=r(16)?function(e,t,r){return a.f(e,t,i(1,r))}:function(e,t,r){e[t]=r;return e}},function(e,t,r){"use strict";var a=r(13),i=r(15),n=r(19),o=Object.defineProperty;t.f=r(16)?Object.defineProperty:function(e,t,r){a(e);t=n(t,!0);a(r);if(i)try{return o(e,t,r)}catch(e){}if("get"in r||"set"in r)throw TypeError("Accessors not supported!");"value"in r&&(e[t]=r.value);return e}},function(e,t,r){"use strict";var a=r(14);e.exports=function(e){if(!a(e))throw TypeError(e+" is not an object!");return e}},function(e,t,r){"use strict";var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};e.exports=function(e){return"object"===(void 0===e?"undefined":a(e))?null!==e:"function"==typeof e}},function(e,t,r){"use strict";e.exports=!r(16)&&!r(17)(function(){return 7!=Object.defineProperty(r(18)("div"),"a",{get:function(){return 7}}).a})},function(e,t,r){"use strict";e.exports=!r(17)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(e,t,r){"use strict";e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,t,r){"use strict";var a=r(14),i=r(9).document,n=a(i)&&a(i.createElement);e.exports=function(e){return n?i.createElement(e):{}}},function(e,t,r){"use strict";var a=r(14);e.exports=function(e,t){if(!a(e))return e;var r,i;if(t&&"function"==typeof(r=e.toString)&&!a(i=r.call(e)))return i;if("function"==typeof(r=e.valueOf)&&!a(i=r.call(e)))return i;if(!t&&"function"==typeof(r=e.toString)&&!a(i=r.call(e)))return i;throw TypeError("Can't convert object to primitive value")}},function(e,t,r){"use strict";e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t,r){"use strict";var a=r(9),i=r(11),n=r(22),o=r(23)("src"),s=Function.toString,c=(""+s).split("toString");r(10).inspectSource=function(e){return s.call(e)};(e.exports=function(e,t,r,s){var l="function"==typeof r;l&&(n(r,"name")||i(r,"name",t));if(e[t]!==r){l&&(n(r,o)||i(r,o,e[t]?""+e[t]:c.join(String(t))));if(e===a)e[t]=r;else if(s)e[t]?e[t]=r:i(e,t,r);else{delete e[t];i(e,t,r)}}})(Function.prototype,"toString",function(){return"function"==typeof this&&this[o]||s.call(this)})},function(e,t,r){"use strict";var a={}.hasOwnProperty;e.exports=function(e,t){return a.call(e,t)}},function(e,t,r){"use strict";var a=0,i=Math.random();e.exports=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++a+i).toString(36))}},function(e,t,r){"use strict";var a=r(25);e.exports=function(e,t,r){a(e);if(void 0===t)return e;switch(r){case 1:return function(r){return e.call(t,r)};case 2:return function(r,a){return e.call(t,r,a)};case 3:return function(r,a,i){return e.call(t,r,a,i)}}return function(){return e.apply(t,arguments)}}},function(e,t,r){"use strict";e.exports=function(e){if("function"!=typeof e)throw TypeError(e+" is not a function!");return e}},function(e,t,r){"use strict";var a=r(27),i=r(32);e.exports=function(e,t,r){if(a(t))throw TypeError("String#"+r+" doesn't accept regex!");return String(i(e))}},function(e,t,r){"use strict";var a=r(14),i=r(28),n=r(29)("match");e.exports=function(e){var t;return a(e)&&(void 0!==(t=e[n])?!!t:"RegExp"==i(e))}},function(e,t,r){"use strict";var a={}.toString;e.exports=function(e){return a.call(e).slice(8,-1)}},function(e,t,r){"use strict";var a=r(30)("wks"),i=r(23),n=r(9).Symbol,o="function"==typeof n;(e.exports=function(e){return a[e]||(a[e]=o&&n[e]||(o?n:i)("Symbol."+e))}).store=a},function(e,t,r){"use strict";var a=r(10),i=r(9),n=i["__core-js_shared__"]||(i["__core-js_shared__"]={});(e.exports=function(e,t){return n[e]||(n[e]=void 0!==t?t:{})})("versions",[]).push({version:a.version,mode:r(31)?"pure":"global",copyright:"© 2018 Denis Pushkarev (zloirock.ru)"})},function(e,t,r){"use strict";e.exports=!1},function(e,t,r){"use strict";e.exports=function(e){if(void 0==e)throw TypeError("Can't call method on "+e);return e}},function(e,t,r){"use strict";var a=r(29)("match");e.exports=function(e){var t=/./;try{"/./"[e](t)}catch(r){try{t[a]=!1;return!"/./"[e](t)}catch(e){}}return!0}},function(e,t,r){"use strict";r(35);e.exports=r(10).Array.includes},function(e,t,r){"use strict";var a=r(8),i=r(36)(!0);a(a.P,"Array",{includes:function(e){return i(this,e,arguments.length>1?arguments[1]:void 0)}});r(42)("includes")},function(e,t,r){"use strict";var a=r(37),i=r(39),n=r(41);e.exports=function(e){return function(t,r,o){var s,c=a(t),l=i(c.length),u=n(o,l);if(e&&r!=r){for(;l>u;)if((s=c[u++])!=s)return!0}else for(;l>u;u++)if((e||u in c)&&c[u]===r)return e||u||0;return!e&&-1}}},function(e,t,r){"use strict";var a=r(38),i=r(32);e.exports=function(e){return a(i(e))}},function(e,t,r){"use strict";var a=r(28);e.exports=Object("z").propertyIsEnumerable(0)?Object:function(e){return"String"==a(e)?e.split(""):Object(e)}},function(e,t,r){"use strict";var a=r(40),i=Math.min;e.exports=function(e){return e>0?i(a(e),9007199254740991):0}},function(e,t,r){"use strict";var a=Math.ceil,i=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?i:a)(e)}},function(e,t,r){"use strict";var a=r(40),i=Math.max,n=Math.min;e.exports=function(e,t){return(e=a(e))<0?i(e+t,0):n(e,t)}},function(e,t,r){"use strict";var a=r(29)("unscopables"),i=Array.prototype;void 0==i[a]&&r(11)(i,a,{});e.exports=function(e){i[a][e]=!0}},function(e,t,r){"use strict";r(44);e.exports=r(10).Object.assign},function(e,t,r){"use strict";var a=r(8);a(a.S+a.F,"Object",{assign:r(45)})},function(e,t,r){"use strict";var a=r(46),i=r(50),n=r(51),o=r(52),s=r(38),c=Object.assign;e.exports=!c||r(17)(function(){var e={},t={},r=Symbol(),a="abcdefghijklmnopqrst";e[r]=7;a.split("").forEach(function(e){t[e]=e});return 7!=c({},e)[r]||Object.keys(c({},t)).join("")!=a})?function(e,t){for(var r=o(e),c=arguments.length,l=1,u=i.f,h=n.f;c>l;)for(var f,d=s(arguments[l++]),g=u?a(d).concat(u(d)):a(d),m=g.length,p=0;m>p;)h.call(d,f=g[p++])&&(r[f]=d[f]);return r}:c},function(e,t,r){"use strict";var a=r(47),i=r(49);e.exports=Object.keys||function(e){return a(e,i)}},function(e,t,r){"use strict";var a=r(22),i=r(37),n=r(36)(!1),o=r(48)("IE_PROTO");e.exports=function(e,t){var r,s=i(e),c=0,l=[];for(r in s)r!=o&&a(s,r)&&l.push(r);for(;t.length>c;)a(s,r=t[c++])&&(~n(l,r)||l.push(r));return l}},function(e,t,r){"use strict";var a=r(30)("keys"),i=r(23);e.exports=function(e){return a[e]||(a[e]=i(e))}},function(e,t,r){"use strict";e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(e,t,r){"use strict";t.f=Object.getOwnPropertySymbols},function(e,t,r){"use strict";t.f={}.propertyIsEnumerable},function(e,t,r){"use strict";var a=r(32);e.exports=function(e){return Object(a(e))}},function(e,t,r){"use strict";r(54);e.exports=r(10).Math.log2},function(e,t,r){"use strict";var a=r(8);a(a.S,"Math",{log2:function(e){return Math.log(e)/Math.LN2}})},function(e,t,r){"use strict";r(56);e.exports=r(10).Number.isNaN},function(e,t,r){"use strict";var a=r(8);a(a.S,"Number",{isNaN:function(e){return e!=e}})},function(e,t,r){"use strict";r(58);e.exports=r(10).Number.isInteger},function(e,t,r){"use strict";var a=r(8);a(a.S,"Number",{isInteger:r(59)})},function(e,t,r){"use strict";var a=r(14),i=Math.floor;e.exports=function(e){return!a(e)&&isFinite(e)&&i(e)===e}},function(e,t,r){"use strict";r(61);r(63);r(73);r(76);r(93);r(94);e.exports=r(10).Promise},function(e,t,r){"use strict";var a=r(62),i={};i[r(29)("toStringTag")]="z";i+""!="[object z]"&&r(21)(Object.prototype,"toString",function(){return"[object "+a(this)+"]"},!0)},function(e,t,r){"use strict";var a=r(28),i=r(29)("toStringTag"),n="Arguments"==a(function(){return arguments}());e.exports=function(e){var t,r,o;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(r=function(e,t){try{return e[t]}catch(e){}}(t=Object(e),i))?r:n?a(t):"Object"==(o=a(t))&&"function"==typeof t.callee?"Arguments":o}},function(e,t,r){"use strict";var a=r(64)(!0);r(65)(String,"String",function(e){this._t=String(e);this._i=0},function(){var e,t=this._t,r=this._i;if(r>=t.length)return{value:void 0,done:!0};e=a(t,r);this._i+=e.length;return{value:e,done:!1}})},function(e,t,r){"use strict";var a=r(40),i=r(32);e.exports=function(e){return function(t,r){var n,o,s=String(i(t)),c=a(r),l=s.length;return c<0||c>=l?e?"":void 0:(n=s.charCodeAt(c))<55296||n>56319||c+1===l||(o=s.charCodeAt(c+1))<56320||o>57343?e?s.charAt(c):n:e?s.slice(c,c+2):o-56320+(n-55296<<10)+65536}}},function(e,t,r){"use strict";var a=r(31),i=r(8),n=r(21),o=r(11),s=r(66),c=r(67),l=r(71),u=r(72),h=r(29)("iterator"),f=!([].keys&&"next"in[].keys()),d=function(){return this};e.exports=function(e,t,r,g,m,p,v){c(r,t,g);var b,y,w,k=function(e){if(!f&&e in _)return _[e];switch(e){case"keys":case"values":return function(){return new r(this,e)}}return function(){return new r(this,e)}},S=t+" Iterator",C="values"==m,x=!1,_=e.prototype,A=_[h]||_["@@iterator"]||m&&_[m],P=A||k(m),I=m?C?k("entries"):P:void 0,O="Array"==t&&_.entries||A;if(O&&(w=u(O.call(new e)))!==Object.prototype&&w.next){l(w,S,!0);a||"function"==typeof w[h]||o(w,h,d)}if(C&&A&&"values"!==A.name){x=!0;P=function(){return A.call(this)}}a&&!v||!f&&!x&&_[h]||o(_,h,P);s[t]=P;s[S]=d;if(m){b={values:C?P:k("values"),keys:p?P:k("keys"),entries:I};if(v)for(y in b)y in _||n(_,y,b[y]);else i(i.P+i.F*(f||x),t,b)}return b}},function(e,t,r){"use strict";e.exports={}},function(e,t,r){"use strict";var a=r(68),i=r(20),n=r(71),o={};r(11)(o,r(29)("iterator"),function(){return this});e.exports=function(e,t,r){e.prototype=a(o,{next:i(1,r)});n(e,t+" Iterator")}},function(e,t,r){"use strict";var a=r(13),i=r(69),n=r(49),o=r(48)("IE_PROTO"),s=function(){},c=function(){var e,t=r(18)("iframe"),a=n.length;t.style.display="none";r(70).appendChild(t);t.src="javascript:";(e=t.contentWindow.document).open();e.write("<script>document.F=Object<\/script>");e.close();c=e.F;for(;a--;)delete c.prototype[n[a]];return c()};e.exports=Object.create||function(e,t){var r;if(null!==e){s.prototype=a(e);r=new s;s.prototype=null;r[o]=e}else r=c();return void 0===t?r:i(r,t)}},function(e,t,r){"use strict";var a=r(12),i=r(13),n=r(46);e.exports=r(16)?Object.defineProperties:function(e,t){i(e);for(var r,o=n(t),s=o.length,c=0;s>c;)a.f(e,r=o[c++],t[r]);return e}},function(e,t,r){"use strict";var a=r(9).document;e.exports=a&&a.documentElement},function(e,t,r){"use strict";var a=r(12).f,i=r(22),n=r(29)("toStringTag");e.exports=function(e,t,r){e&&!i(e=r?e:e.prototype,n)&&a(e,n,{configurable:!0,value:t})}},function(e,t,r){"use strict";var a=r(22),i=r(52),n=r(48)("IE_PROTO"),o=Object.prototype;e.exports=Object.getPrototypeOf||function(e){e=i(e);return a(e,n)?e[n]:"function"==typeof e.constructor&&e instanceof e.constructor?e.constructor.prototype:e instanceof Object?o:null}},function(e,t,r){"use strict";for(var a=r(74),i=r(46),n=r(21),o=r(9),s=r(11),c=r(66),l=r(29),u=l("iterator"),h=l("toStringTag"),f=c.Array,d={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},g=i(d),m=0;m<g.length;m++){var p,v=g[m],b=d[v],y=o[v],w=y&&y.prototype;if(w){w[u]||s(w,u,f);w[h]||s(w,h,v);c[v]=f;if(b)for(p in a)w[p]||n(w,p,a[p],!0)}}},function(e,t,r){"use strict";var a=r(42),i=r(75),n=r(66),o=r(37);e.exports=r(65)(Array,"Array",function(e,t){this._t=o(e);this._i=0;this._k=t},function(){var e=this._t,t=this._k,r=this._i++;if(!e||r>=e.length){this._t=void 0;return i(1)}return i(0,"keys"==t?r:"values"==t?e[r]:[r,e[r]])},"values");n.Arguments=n.Array;a("keys");a("values");a("entries")},function(e,t,r){"use strict";e.exports=function(e,t){return{value:t,done:!!e}}},function(e,t,r){"use strict";var a,i,n,o,s=r(31),c=r(9),l=r(24),u=r(62),h=r(8),f=r(14),d=r(25),g=r(77),m=r(78),p=r(82),v=r(83).set,b=r(85)(),y=r(86),w=r(87),k=r(88),S=r(89),C=c.TypeError,x=c.process,_=x&&x.versions,A=_&&_.v8||"",P=c.Promise,I="process"==u(x),O=function(){},T=i=y.f,E=!!function(){try{var e=P.resolve(1),t=(e.constructor={})[r(29)("species")]=function(e){e(O,O)};return(I||"function"==typeof PromiseRejectionEvent)&&e.then(O)instanceof t&&0!==A.indexOf("6.6")&&-1===k.indexOf("Chrome/66")}catch(e){}}(),F=function(e){var t;return!(!f(e)||"function"!=typeof(t=e.then))&&t},R=function(e,t){if(!e._n){e._n=!0;var r=e._c;b(function(){for(var a=e._v,i=1==e._s,n=0,o=function(t){var r,n,o,s=i?t.ok:t.fail,c=t.resolve,l=t.reject,u=t.domain;try{if(s){if(!i){2==e._h&&M(e);e._h=1}if(!0===s)r=a;else{u&&u.enter();r=s(a);if(u){u.exit();o=!0}}r===t.promise?l(C("Promise-chain cycle")):(n=F(r))?n.call(r,c,l):c(r)}else l(a)}catch(e){u&&!o&&u.exit();l(e)}};r.length>n;)o(r[n++]);e._c=[];e._n=!1;t&&!e._h&&B(e)})}},B=function(e){v.call(c,function(){var t,r,a,i=e._v,n=D(e);if(n){t=w(function(){I?x.emit("unhandledRejection",i,e):(r=c.onunhandledrejection)?r({promise:e,reason:i}):(a=c.console)&&a.error&&a.error("Unhandled promise rejection",i)});e._h=I||D(e)?2:1}e._a=void 0;if(n&&t.e)throw t.v})},D=function(e){return 1!==e._h&&0===(e._a||e._c).length},M=function(e){v.call(c,function(){var t;I?x.emit("rejectionHandled",e):(t=c.onrejectionhandled)&&t({promise:e,reason:e._v})})},L=function(e){var t=this;if(!t._d){t._d=!0;(t=t._w||t)._v=e;t._s=2;t._a||(t._a=t._c.slice());R(t,!0)}},N=function e(t){var r,a=this;if(!a._d){a._d=!0;a=a._w||a;try{if(a===t)throw C("Promise can't be resolved itself");if(r=F(t))b(function(){var i={_w:a,_d:!1};try{r.call(t,l(e,i,1),l(L,i,1))}catch(e){L.call(i,e)}});else{a._v=t;a._s=1;R(a,!1)}}catch(e){L.call({_w:a,_d:!1},e)}}};if(!E){P=function(e){g(this,P,"Promise","_h");d(e);a.call(this);try{e(l(N,this,1),l(L,this,1))}catch(e){L.call(this,e)}};(a=function(e){this._c=[];this._a=void 0;this._s=0;this._d=!1;this._v=void 0;this._h=0;this._n=!1}).prototype=r(90)(P.prototype,{then:function(e,t){var r=T(p(this,P));r.ok="function"!=typeof e||e;r.fail="function"==typeof t&&t;r.domain=I?x.domain:void 0;this._c.push(r);this._a&&this._a.push(r);this._s&&R(this,!1);return r.promise},catch:function(e){return this.then(void 0,e)}});n=function(){var e=new a;this.promise=e;this.resolve=l(N,e,1);this.reject=l(L,e,1)};y.f=T=function(e){return e===P||e===o?new n(e):i(e)}}h(h.G+h.W+h.F*!E,{Promise:P});r(71)(P,"Promise");r(91)("Promise");o=r(10).Promise;h(h.S+h.F*!E,"Promise",{reject:function(e){var t=T(this);(0,t.reject)(e);return t.promise}});h(h.S+h.F*(s||!E),"Promise",{resolve:function(e){return S(s&&this===o?P:this,e)}});h(h.S+h.F*!(E&&r(92)(function(e){P.all(e).catch(O)})),"Promise",{all:function(e){var t=this,r=T(t),a=r.resolve,i=r.reject,n=w(function(){var r=[],n=0,o=1;m(e,!1,function(e){var s=n++,c=!1;r.push(void 0);o++;t.resolve(e).then(function(e){if(!c){c=!0;r[s]=e;--o||a(r)}},i)});--o||a(r)});n.e&&i(n.v);return r.promise},race:function(e){var t=this,r=T(t),a=r.reject,i=w(function(){m(e,!1,function(e){t.resolve(e).then(r.resolve,a)})});i.e&&a(i.v);return r.promise}})},function(e,t,r){"use strict";e.exports=function(e,t,r,a){if(!(e instanceof t)||void 0!==a&&a in e)throw TypeError(r+": incorrect invocation!");return e}},function(e,t,r){"use strict";var a=r(24),i=r(79),n=r(80),o=r(13),s=r(39),c=r(81),l={},u={},h=e.exports=function(e,t,r,h,f){var d,g,m,p,v=f?function(){return e}:c(e),b=a(r,h,t?2:1),y=0;if("function"!=typeof v)throw TypeError(e+" is not iterable!");if(n(v)){for(d=s(e.length);d>y;y++)if((p=t?b(o(g=e[y])[0],g[1]):b(e[y]))===l||p===u)return p}else for(m=v.call(e);!(g=m.next()).done;)if((p=i(m,b,g.value,t))===l||p===u)return p};h.BREAK=l;h.RETURN=u},function(e,t,r){"use strict";var a=r(13);e.exports=function(e,t,r,i){try{return i?t(a(r)[0],r[1]):t(r)}catch(t){var n=e.return;void 0!==n&&a(n.call(e));throw t}}},function(e,t,r){"use strict";var a=r(66),i=r(29)("iterator"),n=Array.prototype;e.exports=function(e){return void 0!==e&&(a.Array===e||n[i]===e)}},function(e,t,r){"use strict";var a=r(62),i=r(29)("iterator"),n=r(66);e.exports=r(10).getIteratorMethod=function(e){if(void 0!=e)return e[i]||e["@@iterator"]||n[a(e)]}},function(e,t,r){"use strict";var a=r(13),i=r(25),n=r(29)("species");e.exports=function(e,t){var r,o=a(e).constructor;return void 0===o||void 0==(r=a(o)[n])?t:i(r)}},function(e,t,r){"use strict";var a,i,n,o=r(24),s=r(84),c=r(70),l=r(18),u=r(9),h=u.process,f=u.setImmediate,d=u.clearImmediate,g=u.MessageChannel,m=u.Dispatch,p=0,v={},b=function(){var e=+this;if(v.hasOwnProperty(e)){var t=v[e];delete v[e];t()}},y=function(e){b.call(e.data)};if(!f||!d){f=function(e){for(var t=[],r=1;arguments.length>r;)t.push(arguments[r++]);v[++p]=function(){s("function"==typeof e?e:Function(e),t)};a(p);return p};d=function(e){delete v[e]};if("process"==r(28)(h))a=function(e){h.nextTick(o(b,e,1))};else if(m&&m.now)a=function(e){m.now(o(b,e,1))};else if(g){n=(i=new g).port2;i.port1.onmessage=y;a=o(n.postMessage,n,1)}else if(u.addEventListener&&"function"==typeof postMessage&&!u.importScripts){a=function(e){u.postMessage(e+"","*")};u.addEventListener("message",y,!1)}else a="onreadystatechange"in l("script")?function(e){c.appendChild(l("script")).onreadystatechange=function(){c.removeChild(this);b.call(e)}}:function(e){setTimeout(o(b,e,1),0)}}e.exports={set:f,clear:d}},function(e,t,r){"use strict";e.exports=function(e,t,r){var a=void 0===r;switch(t.length){case 0:return a?e():e.call(r);case 1:return a?e(t[0]):e.call(r,t[0]);case 2:return a?e(t[0],t[1]):e.call(r,t[0],t[1]);case 3:return a?e(t[0],t[1],t[2]):e.call(r,t[0],t[1],t[2]);case 4:return a?e(t[0],t[1],t[2],t[3]):e.call(r,t[0],t[1],t[2],t[3])}return e.apply(r,t)}},function(e,t,r){"use strict";var a=r(9),i=r(83).set,n=a.MutationObserver||a.WebKitMutationObserver,o=a.process,s=a.Promise,c="process"==r(28)(o);e.exports=function(){var e,t,r,l=function(){var a,i;c&&(a=o.domain)&&a.exit();for(;e;){i=e.fn;e=e.next;try{i()}catch(a){e?r():t=void 0;throw a}}t=void 0;a&&a.enter()};if(c)r=function(){o.nextTick(l)};else if(!n||a.navigator&&a.navigator.standalone)if(s&&s.resolve){var u=s.resolve(void 0);r=function(){u.then(l)}}else r=function(){i.call(a,l)};else{var h=!0,f=document.createTextNode("");new n(l).observe(f,{characterData:!0});r=function(){f.data=h=!h}}return function(a){var i={fn:a,next:void 0};t&&(t.next=i);if(!e){e=i;r()}t=i}}},function(e,t,r){"use strict";var a=r(25);e.exports.f=function(e){return new function(e){var t,r;this.promise=new e(function(e,a){if(void 0!==t||void 0!==r)throw TypeError("Bad Promise constructor");t=e;r=a});this.resolve=a(t);this.reject=a(r)}(e)}},function(e,t,r){"use strict";e.exports=function(e){try{return{e:!1,v:e()}}catch(e){return{e:!0,v:e}}}},function(e,t,r){"use strict";var a=r(9).navigator;e.exports=a&&a.userAgent||""},function(e,t,r){"use strict";var a=r(13),i=r(14),n=r(86);e.exports=function(e,t){a(e);if(i(t)&&t.constructor===e)return t;var r=n.f(e);(0,r.resolve)(t);return r.promise}},function(e,t,r){"use strict";var a=r(21);e.exports=function(e,t,r){for(var i in t)a(e,i,t[i],r);return e}},function(e,t,r){"use strict";var a=r(9),i=r(12),n=r(16),o=r(29)("species");e.exports=function(e){var t=a[e];n&&t&&!t[o]&&i.f(t,o,{configurable:!0,get:function(){return this}})}},function(e,t,r){"use strict";var a=r(29)("iterator"),i=!1;try{var n=[7][a]();n.return=function(){i=!0};Array.from(n,function(){throw 2})}catch(e){}e.exports=function(e,t){if(!t&&!i)return!1;var r=!1;try{var n=[7],o=n[a]();o.next=function(){return{done:r=!0}};n[a]=function(){return o};e(n)}catch(e){}return r}},function(e,t,r){"use strict";var a=r(8),i=r(10),n=r(9),o=r(82),s=r(89);a(a.P+a.R,"Promise",{finally:function(e){var t=o(this,i.Promise||n.Promise),r="function"==typeof e;return this.then(r?function(r){return s(t,e()).then(function(){return r})}:e,r?function(r){return s(t,e()).then(function(){throw r})}:e)}})},function(e,t,r){"use strict";var a=r(8),i=r(86),n=r(87);a(a.S,"Promise",{try:function(e){var t=i.f(this),r=n(e);(r.e?t.reject:t.resolve)(r.v);return t.promise}})},function(e,t,r){"use strict";r(61);r(73);r(96);r(108);r(110);e.exports=r(10).WeakMap},function(e,t,r){"use strict";var a,i=r(97)(0),n=r(21),o=r(101),s=r(45),c=r(102),l=r(14),u=r(17),h=r(103),f=o.getWeak,d=Object.isExtensible,g=c.ufstore,m={},p=function(e){return function(){return e(this,arguments.length>0?arguments[0]:void 0)}},v={get:function(e){if(l(e)){var t=f(e);return!0===t?g(h(this,"WeakMap")).get(e):t?t[this._i]:void 0}},set:function(e,t){return c.def(h(this,"WeakMap"),e,t)}},b=e.exports=r(104)("WeakMap",p,v,c,!0,!0);if(u(function(){return 7!=(new b).set((Object.freeze||Object)(m),7).get(m)})){s((a=c.getConstructor(p,"WeakMap")).prototype,v);o.NEED=!0;i(["delete","has","get","set"],function(e){var t=b.prototype,r=t[e];n(t,e,function(t,i){if(l(t)&&!d(t)){this._f||(this._f=new a);var n=this._f[e](t,i);return"set"==e?this:n}return r.call(this,t,i)})})}},function(e,t,r){"use strict";var a=r(24),i=r(38),n=r(52),o=r(39),s=r(98);e.exports=function(e,t){var r=1==e,c=2==e,l=3==e,u=4==e,h=6==e,f=5==e||h,d=t||s;return function(t,s,g){for(var m,p,v=n(t),b=i(v),y=a(s,g,3),w=o(b.length),k=0,S=r?d(t,w):c?d(t,0):void 0;w>k;k++)if(f||k in b){p=y(m=b[k],k,v);if(e)if(r)S[k]=p;else if(p)switch(e){case 3:return!0;case 5:return m;case 6:return k;case 2:S.push(m)}else if(u)return!1}return h?-1:l||u?u:S}}},function(e,t,r){"use strict";var a=r(99);e.exports=function(e,t){return new(a(e))(t)}},function(e,t,r){"use strict";var a=r(14),i=r(100),n=r(29)("species");e.exports=function(e){var t;if(i(e)){"function"!=typeof(t=e.constructor)||t!==Array&&!i(t.prototype)||(t=void 0);a(t)&&null===(t=t[n])&&(t=void 0)}return void 0===t?Array:t}},function(e,t,r){"use strict";var a=r(28);e.exports=Array.isArray||function(e){return"Array"==a(e)}},function(e,t,r){"use strict";var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i=r(23)("meta"),n=r(14),o=r(22),s=r(12).f,c=0,l=Object.isExtensible||function(){return!0},u=!r(17)(function(){return l(Object.preventExtensions({}))}),h=function(e){s(e,i,{value:{i:"O"+ ++c,w:{}}})},f=e.exports={KEY:i,NEED:!1,fastKey:function(e,t){if(!n(e))return"symbol"==(void 0===e?"undefined":a(e))?e:("string"==typeof e?"S":"P")+e;if(!o(e,i)){if(!l(e))return"F";if(!t)return"E";h(e)}return e[i].i},getWeak:function(e,t){if(!o(e,i)){if(!l(e))return!0;if(!t)return!1;h(e)}return e[i].w},onFreeze:function(e){u&&f.NEED&&l(e)&&!o(e,i)&&h(e);return e}}},function(e,t,r){"use strict";var a=r(90),i=r(101).getWeak,n=r(13),o=r(14),s=r(77),c=r(78),l=r(97),u=r(22),h=r(103),f=l(5),d=l(6),g=0,m=function(e){return e._l||(e._l=new p)},p=function(){this.a=[]},v=function(e,t){return f(e.a,function(e){return e[0]===t})};p.prototype={get:function(e){var t=v(this,e);if(t)return t[1]},has:function(e){return!!v(this,e)},set:function(e,t){var r=v(this,e);r?r[1]=t:this.a.push([e,t])},delete:function(e){var t=d(this.a,function(t){return t[0]===e});~t&&this.a.splice(t,1);return!!~t}};e.exports={getConstructor:function(e,t,r,n){var l=e(function(e,a){s(e,l,t,"_i");e._t=t;e._i=g++;e._l=void 0;void 0!=a&&c(a,r,e[n],e)});a(l.prototype,{delete:function(e){if(!o(e))return!1;var r=i(e);return!0===r?m(h(this,t)).delete(e):r&&u(r,this._i)&&delete r[this._i]},has:function(e){if(!o(e))return!1;var r=i(e);return!0===r?m(h(this,t)).has(e):r&&u(r,this._i)}});return l},def:function(e,t,r){var a=i(n(t),!0);!0===a?m(e).set(t,r):a[e._i]=r;return e},ufstore:m}},function(e,t,r){"use strict";var a=r(14);e.exports=function(e,t){if(!a(e)||e._t!==t)throw TypeError("Incompatible receiver, "+t+" required!");return e}},function(e,t,r){"use strict";var a=r(9),i=r(8),n=r(21),o=r(90),s=r(101),c=r(78),l=r(77),u=r(14),h=r(17),f=r(92),d=r(71),g=r(105);e.exports=function(e,t,r,m,p,v){var b=a[e],y=b,w=p?"set":"add",k=y&&y.prototype,S={},C=function(e){var t=k[e];n(k,e,"delete"==e?function(e){return!(v&&!u(e))&&t.call(this,0===e?0:e)}:"has"==e?function(e){return!(v&&!u(e))&&t.call(this,0===e?0:e)}:"get"==e?function(e){return v&&!u(e)?void 0:t.call(this,0===e?0:e)}:"add"==e?function(e){t.call(this,0===e?0:e);return this}:function(e,r){t.call(this,0===e?0:e,r);return this})};if("function"==typeof y&&(v||k.forEach&&!h(function(){(new y).entries().next()}))){var x=new y,_=x[w](v?{}:-0,1)!=x,A=h(function(){x.has(1)}),P=f(function(e){new y(e)}),I=!v&&h(function(){for(var e=new y,t=5;t--;)e[w](t,t);return!e.has(-0)});if(!P){(y=t(function(t,r){l(t,y,e);var a=g(new b,t,y);void 0!=r&&c(r,p,a[w],a);return a})).prototype=k;k.constructor=y}if(A||I){C("delete");C("has");p&&C("get")}(I||_)&&C(w);v&&k.clear&&delete k.clear}else{y=m.getConstructor(t,e,p,w);o(y.prototype,r);s.NEED=!0}d(y,e);S[e]=y;i(i.G+i.W+i.F*(y!=b),S);v||m.setStrong(y,e,p);return y}},function(e,t,r){"use strict";var a=r(14),i=r(106).set;e.exports=function(e,t,r){var n,o=t.constructor;o!==r&&"function"==typeof o&&(n=o.prototype)!==r.prototype&&a(n)&&i&&i(e,n);return e}},function(e,t,r){"use strict";var a=r(14),i=r(13),n=function(e,t){i(e);if(!a(t)&&null!==t)throw TypeError(t+": can't set as prototype!")};e.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(e,t,a){try{(a=r(24)(Function.call,r(107).f(Object.prototype,"__proto__").set,2))(e,[]);t=!(e instanceof Array)}catch(e){t=!0}return function(e,r){n(e,r);t?e.__proto__=r:a(e,r);return e}}({},!1):void 0),check:n}},function(e,t,r){"use strict";var a=r(51),i=r(20),n=r(37),o=r(19),s=r(22),c=r(15),l=Object.getOwnPropertyDescriptor;t.f=r(16)?l:function(e,t){e=n(e);t=o(t,!0);if(c)try{return l(e,t)}catch(e){}if(s(e,t))return i(!a.f.call(e,t),e[t])}},function(e,t,r){"use strict";r(109)("WeakMap")},function(e,t,r){"use strict";var a=r(8);e.exports=function(e){a(a.S,e,{of:function(){for(var e=arguments.length,t=new Array(e);e--;)t[e]=arguments[e];return new this(t)}})}},function(e,t,r){"use strict";r(111)("WeakMap")},function(e,t,r){"use strict";var a=r(8),i=r(25),n=r(24),o=r(78);e.exports=function(e){a(a.S,e,{from:function(e){var t,r,a,s,c=arguments[1];i(this);(t=void 0!==c)&&i(c);if(void 0==e)return new this;r=[];if(t){a=0;s=n(c,arguments[2],2);o(e,!1,function(e){r.push(s(e,a++))})}else o(e,!1,r.push,r);return new this(r)}})}},function(e,t,r){"use strict";r(113);e.exports=r(10).String.codePointAt},function(e,t,r){"use strict";var a=r(8),i=r(64)(!1);a(a.P,"String",{codePointAt:function(e){return i(this,e)}})},function(e,t,r){"use strict";r(115);e.exports=r(10).String.fromCodePoint},function(e,t,r){"use strict";var a=r(8),i=r(41),n=String.fromCharCode,o=String.fromCodePoint;a(a.S+a.F*(!!o&&1!=o.length),"String",{fromCodePoint:function(e){for(var t,r=[],a=arguments.length,o=0;a>o;){t=+arguments[o++];if(i(t,1114111)!==t)throw RangeError(t+" is not a valid code point");r.push(t<65536?n(t):n(55296+((t-=65536)>>10),t%1024+56320))}return r.join("")}})},function(e,t,r){"use strict";r(117);r(61);e.exports=r(10).Symbol},function(e,t,r){"use strict";var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i=r(9),n=r(22),o=r(16),s=r(8),c=r(21),l=r(101).KEY,u=r(17),h=r(30),f=r(71),d=r(23),g=r(29),m=r(118),p=r(119),v=r(120),b=r(100),y=r(13),w=r(14),k=r(37),S=r(19),C=r(20),x=r(68),_=r(121),A=r(107),P=r(12),I=r(46),O=A.f,T=P.f,E=_.f,F=i.Symbol,R=i.JSON,B=R&&R.stringify,D=g("_hidden"),M=g("toPrimitive"),L={}.propertyIsEnumerable,N=h("symbol-registry"),U=h("symbols"),q=h("op-symbols"),j=Object.prototype,z="function"==typeof F,H=i.QObject,G=!H||!H.prototype||!H.prototype.findChild,W=o&&u(function(){return 7!=x(T({},"a",{get:function(){return T(this,"a",{value:7}).a}})).a})?function(e,t,r){var a=O(j,t);a&&delete j[t];T(e,t,r);a&&e!==j&&T(j,t,a)}:T,X=function(e){var t=U[e]=x(F.prototype);t._k=e;return t},V=z&&"symbol"==a(F.iterator)?function(e){return"symbol"==(void 0===e?"undefined":a(e))}:function(e){return e instanceof F},K=function(e,t,r){e===j&&K(q,t,r);y(e);t=S(t,!0);y(r);if(n(U,t)){if(r.enumerable){n(e,D)&&e[D][t]&&(e[D][t]=!1);r=x(r,{enumerable:C(0,!1)})}else{n(e,D)||T(e,D,C(1,{}));e[D][t]=!0}return W(e,t,r)}return T(e,t,r)},Y=function(e,t){y(e);for(var r,a=v(t=k(t)),i=0,n=a.length;n>i;)K(e,r=a[i++],t[r]);return e},J=function(e){var t=L.call(this,e=S(e,!0));return!(this===j&&n(U,e)&&!n(q,e))&&(!(t||!n(this,e)||!n(U,e)||n(this,D)&&this[D][e])||t)},Z=function(e,t){e=k(e);t=S(t,!0);if(e!==j||!n(U,t)||n(q,t)){var r=O(e,t);!r||!n(U,t)||n(e,D)&&e[D][t]||(r.enumerable=!0);return r}},Q=function(e){for(var t,r=E(k(e)),a=[],i=0;r.length>i;)n(U,t=r[i++])||t==D||t==l||a.push(t);return a},$=function(e){for(var t,r=e===j,a=E(r?q:k(e)),i=[],o=0;a.length>o;)!n(U,t=a[o++])||r&&!n(j,t)||i.push(U[t]);return i};if(!z){c((F=function(){if(this instanceof F)throw TypeError("Symbol is not a constructor!");var e=d(arguments.length>0?arguments[0]:void 0);o&&G&&W(j,e,{configurable:!0,set:function t(r){this===j&&t.call(q,r);n(this,D)&&n(this[D],e)&&(this[D][e]=!1);W(this,e,C(1,r))}});return X(e)}).prototype,"toString",function(){return this._k});A.f=Z;P.f=K;r(122).f=_.f=Q;r(51).f=J;r(50).f=$;o&&!r(31)&&c(j,"propertyIsEnumerable",J,!0);m.f=function(e){return X(g(e))}}s(s.G+s.W+s.F*!z,{Symbol:F});for(var ee="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),te=0;ee.length>te;)g(ee[te++]);for(var re=I(g.store),ae=0;re.length>ae;)p(re[ae++]);s(s.S+s.F*!z,"Symbol",{for:function(e){return n(N,e+="")?N[e]:N[e]=F(e)},keyFor:function(e){if(!V(e))throw TypeError(e+" is not a symbol!");for(var t in N)if(N[t]===e)return t},useSetter:function(){G=!0},useSimple:function(){G=!1}});s(s.S+s.F*!z,"Object",{create:function(e,t){return void 0===t?x(e):Y(x(e),t)},defineProperty:K,defineProperties:Y,getOwnPropertyDescriptor:Z,getOwnPropertyNames:Q,getOwnPropertySymbols:$});R&&s(s.S+s.F*(!z||u(function(){var e=F();return"[null]"!=B([e])||"{}"!=B({a:e})||"{}"!=B(Object(e))})),"JSON",{stringify:function(e){for(var t,r,a=[e],i=1;arguments.length>i;)a.push(arguments[i++]);r=t=a[1];if((w(t)||void 0!==e)&&!V(e)){b(t)||(t=function(e,t){"function"==typeof r&&(t=r.call(this,e,t));if(!V(t))return t});a[1]=t;return B.apply(R,a)}}});F.prototype[M]||r(11)(F.prototype,M,F.prototype.valueOf);f(F,"Symbol");f(Math,"Math",!0);f(i.JSON,"JSON",!0)},function(e,t,r){"use strict";t.f=r(29)},function(e,t,r){"use strict";var a=r(9),i=r(10),n=r(31),o=r(118),s=r(12).f;e.exports=function(e){var t=i.Symbol||(i.Symbol=n?{}:a.Symbol||{});"_"==e.charAt(0)||e in t||s(t,e,{value:o.f(e)})}},function(e,t,r){"use strict";var a=r(46),i=r(50),n=r(51);e.exports=function(e){var t=a(e),r=i.f;if(r)for(var o,s=r(e),c=n.f,l=0;s.length>l;)c.call(e,o=s[l++])&&t.push(o);return t}},function(e,t,r){"use strict";var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i=r(37),n=r(122).f,o={}.toString,s="object"==("undefined"==typeof window?"undefined":a(window))&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[];e.exports.f=function(e){return s&&"[object Window]"==o.call(e)?function(e){try{return n(e)}catch(e){return s.slice()}}(e):n(i(e))}},function(e,t,r){"use strict";var a=r(47),i=r(49).concat("length","prototype");t.f=Object.getOwnPropertyNames||function(e){return a(e,i)}},function(e,t,r){"use strict";r(124);e.exports=r(10).Object.values},function(e,t,r){"use strict";var a=r(8),i=r(125)(!1);a(a.S,"Object",{values:function(e){return i(e)}})},function(e,t,r){"use strict";var a=r(46),i=r(37),n=r(51).f;e.exports=function(e){return function(t){for(var r,o=i(t),s=a(o),c=s.length,l=0,u=[];c>l;)n.call(o,r=s[l++])&&u.push(e?[r,o[r]]:o[r]);return u}}},function(e,t,r){"use strict";var a=!1;if("undefined"!=typeof ReadableStream)try{new ReadableStream({start:function(e){e.close()}});a=!0}catch(e){}t.ReadableStream=a?ReadableStream:r(127).ReadableStream},function(e,t,r){"use strict";var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};!function(e,t){for(var r in t)e[r]=t[r]}(t,function(e){var t={};function r(a){if(t[a])return t[a].exports;var i=t[a]={i:a,l:!1,exports:{}};e[a].call(i.exports,i,i.exports,r);i.l=!0;return i.exports}r.m=e;r.c=t;r.i=function(e){return e};r.d=function(e,t,a){r.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:a})};r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};r.d(t,"a",t);return t};r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};r.p="";return r(r.s=7)}([function(e,t,r){var i="function"==typeof Symbol&&"symbol"===a(Symbol.iterator)?function(e){return void 0===e?"undefined":a(e)}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":void 0===e?"undefined":a(e)},n=r(1).assert;function o(e){return"string"==typeof e||"symbol"===(void 0===e?"undefined":i(e))}t.typeIsObject=function(e){return"object"===(void 0===e?"undefined":i(e))&&null!==e||"function"==typeof e};t.createDataProperty=function(e,r,a){n(t.typeIsObject(e));Object.defineProperty(e,r,{value:a,writable:!0,enumerable:!0,configurable:!0})};t.createArrayFromList=function(e){return e.slice()};t.ArrayBufferCopy=function(e,t,r,a,i){new Uint8Array(e).set(new Uint8Array(r,a,i),t)};t.CreateIterResultObject=function(e,t){n("boolean"==typeof t);var r={};Object.defineProperty(r,"value",{value:e,enumerable:!0,writable:!0,configurable:!0});Object.defineProperty(r,"done",{value:t,enumerable:!0,writable:!0,configurable:!0});return r};t.IsFiniteNonNegativeNumber=function(e){return!Number.isNaN(e)&&(e!==1/0&&!(e<0))};function s(e,t,r){if("function"!=typeof e)throw new TypeError("Argument is not a function");return Function.prototype.apply.call(e,t,r)}t.InvokeOrNoop=function(e,t,r){n(void 0!==e);n(o(t));n(Array.isArray(r));var a=e[t];if(void 0!==a)return s(a,e,r)};t.PromiseInvokeOrNoop=function(e,r,a){n(void 0!==e);n(o(r));n(Array.isArray(a));try{return Promise.resolve(t.InvokeOrNoop(e,r,a))}catch(e){return Promise.reject(e)}};t.PromiseInvokeOrPerformFallback=function(e,t,r,a,i){n(void 0!==e);n(o(t));n(Array.isArray(r));n(Array.isArray(i));var c=void 0;try{c=e[t]}catch(e){return Promise.reject(e)}if(void 0===c)return a.apply(null,i);try{return Promise.resolve(s(c,e,r))}catch(e){return Promise.reject(e)}};t.TransferArrayBuffer=function(e){return e.slice()};t.ValidateAndNormalizeHighWaterMark=function(e){e=Number(e);if(Number.isNaN(e)||e<0)throw new RangeError("highWaterMark property of a queuing strategy must be non-negative and non-NaN");return e};t.ValidateAndNormalizeQueuingStrategy=function(e,r){if(void 0!==e&&"function"!=typeof e)throw new TypeError("size property of a queuing strategy must be a function");return{size:e,highWaterMark:r=t.ValidateAndNormalizeHighWaterMark(r)}}},function(e,t,r){function a(e){this.name="AssertionError";this.message=e||"";this.stack=(new Error).stack}a.prototype=Object.create(Error.prototype);a.prototype.constructor=a;e.exports={rethrowAssertionErrorRejection:function(e){e&&e.constructor===a&&setTimeout(function(){throw e},0)},AssertionError:a,assert:function(e,t){if(!e)throw new a(t)}}},function(e,t,r){var a=function(){function e(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1;a.configurable=!0;"value"in a&&(a.writable=!0);Object.defineProperty(e,a.key,a)}}return function(t,r,a){r&&e(t.prototype,r);a&&e(t,a);return t}}();function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var n=r(0),o=n.InvokeOrNoop,s=n.PromiseInvokeOrNoop,c=n.ValidateAndNormalizeQueuingStrategy,l=n.typeIsObject,u=r(1),h=u.assert,f=u.rethrowAssertionErrorRejection,d=r(3),g=d.DequeueValue,m=d.EnqueueValueWithSize,p=d.PeekQueueValue,v=d.ResetQueue,b=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},a=r.size,n=r.highWaterMark,o=void 0===n?1:n;i(this,e);this._state="writable";this._storedError=void 0;this._writer=void 0;this._writableStreamController=void 0;this._writeRequests=[];this._inFlightWriteRequest=void 0;this._closeRequest=void 0;this._inFlightCloseRequest=void 0;this._pendingAbortRequest=void 0;this._backpressure=!1;if(void 0!==t.type)throw new RangeError("Invalid type is specified");this._writableStreamController=new N(this,t,a,o);this._writableStreamController.__startSteps()}a(e,[{key:"abort",value:function(e){return!1===w(this)?Promise.reject(G("abort")):!0===k(this)?Promise.reject(new TypeError("Cannot abort a stream that already has a writer")):S(this,e)}},{key:"getWriter",value:function(){if(!1===w(this))throw G("getWriter");return y(this)}},{key:"locked",get:function(){if(!1===w(this))throw G("locked");return k(this)}}]);return e}();e.exports={AcquireWritableStreamDefaultWriter:y,IsWritableStream:w,IsWritableStreamLocked:k,WritableStream:b,WritableStreamAbort:S,WritableStreamDefaultControllerError:H,WritableStreamDefaultWriterCloseWithErrorPropagation:function(e){var t=e._ownerWritableStream;h(void 0!==t);var r=t._state;if(!0===P(t)||"closed"===r)return Promise.resolve();if("errored"===r)return Promise.reject(t._storedError);h("writable"===r||"erroring"===r);return R(e)},WritableStreamDefaultWriterRelease:M,WritableStreamDefaultWriterWrite:L,WritableStreamCloseQueuedOrInFlight:P};function y(e){return new E(e)}function w(e){return!!l(e)&&!!Object.prototype.hasOwnProperty.call(e,"_writableStreamController")}function k(e){h(!0===w(e),"IsWritableStreamLocked should only be used on known writable streams");return void 0!==e._writer}function S(e,t){var r=e._state;if("closed"===r)return Promise.resolve(void 0);if("errored"===r)return Promise.reject(e._storedError);var a=new TypeError("Requested to abort");if(void 0!==e._pendingAbortRequest)return Promise.reject(a);h("writable"===r||"erroring"===r,"state must be writable or erroring");var i=!1;if("erroring"===r){i=!0;t=void 0}var n=new Promise(function(r,a){e._pendingAbortRequest={_resolve:r,_reject:a,_reason:t,_wasAlreadyErroring:i}});!1===i&&x(e,a);return n}function C(e,t){var r=e._state;if("writable"!==r){h("erroring"===r);_(e)}else x(e,t)}function x(e,t){h(void 0===e._storedError,"stream._storedError === undefined");h("writable"===e._state,"state must be writable");var r=e._writableStreamController;h(void 0!==r,"controller must not be undefined");e._state="erroring";e._storedError=t;var a=e._writer;void 0!==a&&D(a,t);!1===I(e)&&!0===r._started&&_(e)}function _(e){h("erroring"===e._state,"stream._state === erroring");h(!1===I(e),"WritableStreamHasOperationMarkedInFlight(stream) === false");e._state="errored";e._writableStreamController.__errorSteps();for(var t=e._storedError,r=0;r<e._writeRequests.length;r++){e._writeRequests[r]._reject(t)}e._writeRequests=[];if(void 0!==e._pendingAbortRequest){var a=e._pendingAbortRequest;e._pendingAbortRequest=void 0;if(!0!==a._wasAlreadyErroring){e._writableStreamController.__abortSteps(a._reason).then(function(){a._resolve();O(e)},function(t){a._reject(t);O(e)})}else{a._reject(t);O(e)}}else O(e)}function A(e){h(void 0!==e._inFlightCloseRequest);e._inFlightCloseRequest._resolve(void 0);e._inFlightCloseRequest=void 0;var t=e._state;h("writable"===t||"erroring"===t);if("erroring"===t){e._storedError=void 0;if(void 0!==e._pendingAbortRequest){e._pendingAbortRequest._resolve();e._pendingAbortRequest=void 0}}e._state="closed";var r=e._writer;void 0!==r&&function(e){h(void 0!==e._closedPromise_resolve,"writer._closedPromise_resolve !== undefined");h(void 0!==e._closedPromise_reject,"writer._closedPromise_reject !== undefined");h("pending"===e._closedPromiseState,"writer._closedPromiseState is pending");e._closedPromise_resolve(void 0);e._closedPromise_resolve=void 0;e._closedPromise_reject=void 0;e._closedPromiseState="resolved"}(r);h(void 0===e._pendingAbortRequest,"stream._pendingAbortRequest === undefined");h(void 0===e._storedError,"stream._storedError === undefined")}function P(e){return void 0!==e._closeRequest||void 0!==e._inFlightCloseRequest}function I(e){return void 0!==e._inFlightWriteRequest||void 0!==e._inFlightCloseRequest}function O(e){h("errored"===e._state,'_stream_.[[state]] is `"errored"`');if(void 0!==e._closeRequest){h(void 0===e._inFlightCloseRequest);e._closeRequest._reject(e._storedError);e._closeRequest=void 0}var t=e._writer;if(void 0!==t){K(t,e._storedError);t._closedPromise.catch(function(){})}}function T(e,t){h("writable"===e._state);h(!1===P(e));var r=e._writer;if(void 0!==r&&t!==e._backpressure)if(!0===t)!function(e){h(void 0===e._readyPromise_resolve,"writer._readyPromise_resolve === undefined");h(void 0===e._readyPromise_reject,"writer._readyPromise_reject === undefined");e._readyPromise=new Promise(function(t,r){e._readyPromise_resolve=t;e._readyPromise_reject=r});e._readyPromiseState="pending"}(r);else{h(!1===t);Z(r)}e._backpressure=t}var E=function(){function e(t){i(this,e);if(!1===w(t))throw new TypeError("WritableStreamDefaultWriter can only be constructed with a WritableStream instance");if(!0===k(t))throw new TypeError("This stream has already been locked for exclusive writing by another writer");this._ownerWritableStream=t;t._writer=this;var r=t._state;if("writable"===r){!1===P(t)&&!0===t._backpressure?function(e){e._readyPromise=new Promise(function(t,r){e._readyPromise_resolve=t;e._readyPromise_reject=r});e._readyPromiseState="pending"}(this):J(this);V(this)}else if("erroring"===r){Y(this,t._storedError);this._readyPromise.catch(function(){});V(this)}else if("closed"===r){J(this);!function(e){e._closedPromise=Promise.resolve(void 0);e._closedPromise_resolve=void 0;e._closedPromise_reject=void 0;e._closedPromiseState="resolved"}(this)}else{h("errored"===r,"state must be errored");var a=t._storedError;Y(this,a);this._readyPromise.catch(function(){});!function(e,t){e._closedPromise=Promise.reject(t);e._closedPromise_resolve=void 0;e._closedPromise_reject=void 0;e._closedPromiseState="rejected"}(this,a);this._closedPromise.catch(function(){})}}a(e,[{key:"abort",value:function(e){return!1===F(this)?Promise.reject(W("abort")):void 0===this._ownerWritableStream?Promise.reject(X("abort")):function(e,t){var r=e._ownerWritableStream;h(void 0!==r);return S(r,t)}(this,e)}},{key:"close",value:function(){if(!1===F(this))return Promise.reject(W("close"));var e=this._ownerWritableStream;return void 0===e?Promise.reject(X("close")):!0===P(e)?Promise.reject(new TypeError("cannot close an already-closing stream")):R(this)}},{key:"releaseLock",value:function(){if(!1===F(this))throw W("releaseLock");var e=this._ownerWritableStream;if(void 0!==e){h(void 0!==e._writer);M(this)}}},{key:"write",value:function(e){return!1===F(this)?Promise.reject(W("write")):void 0===this._ownerWritableStream?Promise.reject(X("write to")):L(this,e)}},{key:"closed",get:function(){return!1===F(this)?Promise.reject(W("closed")):this._closedPromise}},{key:"desiredSize",get:function(){if(!1===F(this))throw W("desiredSize");if(void 0===this._ownerWritableStream)throw X("desiredSize");return function(e){var t=e._ownerWritableStream,r=t._state;if("errored"===r||"erroring"===r)return null;if("closed"===r)return 0;return U(t._writableStreamController)}(this)}},{key:"ready",get:function(){return!1===F(this)?Promise.reject(W("ready")):this._readyPromise}}]);return e}();function F(e){return!!l(e)&&!!Object.prototype.hasOwnProperty.call(e,"_ownerWritableStream")}function R(e){var t=e._ownerWritableStream;h(void 0!==t);var r=t._state;if("closed"===r||"errored"===r)return Promise.reject(new TypeError("The stream (in "+r+" state) is not in the writable state and cannot be closed"));h("writable"===r||"erroring"===r);h(!1===P(t));var a=new Promise(function(e,r){var a={_resolve:e,_reject:r};t._closeRequest=a});!0===t._backpressure&&"writable"===r&&Z(e);!function(e){m(e,"close",0);q(e)}(t._writableStreamController);return a}function B(e,t){"pending"===e._closedPromiseState?K(e,t):function(e,t){h(void 0===e._closedPromise_resolve,"writer._closedPromise_resolve === undefined");h(void 0===e._closedPromise_reject,"writer._closedPromise_reject === undefined");h("pending"!==e._closedPromiseState,"writer._closedPromiseState is not pending");e._closedPromise=Promise.reject(t);e._closedPromiseState="rejected"}(e,t);e._closedPromise.catch(function(){})}function D(e,t){"pending"===e._readyPromiseState?function(e,t){h(void 0!==e._readyPromise_resolve,"writer._readyPromise_resolve !== undefined");h(void 0!==e._readyPromise_reject,"writer._readyPromise_reject !== undefined");e._readyPromise_reject(t);e._readyPromise_resolve=void 0;e._readyPromise_reject=void 0;e._readyPromiseState="rejected"}(e,t):function(e,t){h(void 0===e._readyPromise_resolve,"writer._readyPromise_resolve === undefined");h(void 0===e._readyPromise_reject,"writer._readyPromise_reject === undefined");e._readyPromise=Promise.reject(t);e._readyPromiseState="rejected"}(e,t);e._readyPromise.catch(function(){})}function M(e){var t=e._ownerWritableStream;h(void 0!==t);h(t._writer===e);var r=new TypeError("Writer was released and can no longer be used to monitor the stream's closedness");D(e,r);B(e,r);t._writer=void 0;e._ownerWritableStream=void 0}function L(e,t){var r=e._ownerWritableStream;h(void 0!==r);var a=r._writableStreamController,i=function(e,t){var r=e._strategySize;if(void 0===r)return 1;try{return r(t)}catch(t){j(e,t);return 1}}(a,t);if(r!==e._ownerWritableStream)return Promise.reject(X("write to"));var n=r._state;if("errored"===n)return Promise.reject(r._storedError);if(!0===P(r)||"closed"===n)return Promise.reject(new TypeError("The stream is closing or closed and cannot be written to"));if("erroring"===n)return Promise.reject(r._storedError);h("writable"===n);var o=function(e){h(!0===k(e));h("writable"===e._state);return new Promise(function(t,r){var a={_resolve:t,_reject:r};e._writeRequests.push(a)})}(r);!function(e,t,r){var a={chunk:t};try{m(e,a,r)}catch(t){j(e,t);return}var i=e._controlledWritableStream;if(!1===P(i)&&"writable"===i._state){var n=z(e);T(i,n)}q(e)}(a,t,i);return o}var N=function(){function e(t,r,a,n){i(this,e);if(!1===w(t))throw new TypeError("WritableStreamDefaultController can only be constructed with a WritableStream instance");if(void 0!==t._writableStreamController)throw new TypeError("WritableStreamDefaultController instances can only be created by the WritableStream constructor");this._controlledWritableStream=t;this._underlyingSink=r;this._queue=void 0;this._queueTotalSize=void 0;v(this);this._started=!1;var o=c(a,n);this._strategySize=o.size;this._strategyHWM=o.highWaterMark;T(t,z(this))}a(e,[{key:"error",value:function(e){if(!1===function(e){if(!l(e))return!1;if(!Object.prototype.hasOwnProperty.call(e,"_underlyingSink"))return!1;return!0}(this))throw new TypeError("WritableStreamDefaultController.prototype.error can only be used on a WritableStreamDefaultController");"writable"===this._controlledWritableStream._state&&H(this,e)}},{key:"__abortSteps",value:function(e){return s(this._underlyingSink,"abort",[e])}},{key:"__errorSteps",value:function(){v(this)}},{key:"__startSteps",value:function(){var e=this,t=o(this._underlyingSink,"start",[this]),r=this._controlledWritableStream;Promise.resolve(t).then(function(){h("writable"===r._state||"erroring"===r._state);e._started=!0;q(e)},function(t){h("writable"===r._state||"erroring"===r._state);e._started=!0;C(r,t)}).catch(f)}}]);return e}();function U(e){return e._strategyHWM-e._queueTotalSize}function q(e){var t=e._controlledWritableStream;if(!1!==e._started&&void 0===t._inFlightWriteRequest){var r=t._state;if("closed"!==r&&"errored"!==r)if("erroring"!==r){if(0!==e._queue.length){var a=p(e);"close"===a?function(e){var t=e._controlledWritableStream;!function(e){h(void 0===e._inFlightCloseRequest);h(void 0!==e._closeRequest);e._inFlightCloseRequest=e._closeRequest;e._closeRequest=void 0}(t);g(e);h(0===e._queue.length,"queue must be empty once the final write record is dequeued");s(e._underlyingSink,"close",[]).then(function(){A(t)},function(e){!function(e,t){h(void 0!==e._inFlightCloseRequest);e._inFlightCloseRequest._reject(t);e._inFlightCloseRequest=void 0;h("writable"===e._state||"erroring"===e._state);if(void 0!==e._pendingAbortRequest){e._pendingAbortRequest._reject(t);e._pendingAbortRequest=void 0}C(e,t)}(t,e)}).catch(f)}(e):function(e,t){var r=e._controlledWritableStream;!function(e){h(void 0===e._inFlightWriteRequest,"there must be no pending write request");h(0!==e._writeRequests.length,"writeRequests must not be empty");e._inFlightWriteRequest=e._writeRequests.shift()}(r);s(e._underlyingSink,"write",[t,e]).then(function(){!function(e){h(void 0!==e._inFlightWriteRequest);e._inFlightWriteRequest._resolve(void 0);e._inFlightWriteRequest=void 0}(r);var t=r._state;h("writable"===t||"erroring"===t);g(e);if(!1===P(r)&&"writable"===t){var a=z(e);T(r,a)}q(e)},function(e){!function(e,t){h(void 0!==e._inFlightWriteRequest);e._inFlightWriteRequest._reject(t);e._inFlightWriteRequest=void 0;h("writable"===e._state||"erroring"===e._state);C(e,t)}(r,e)}).catch(f)}(e,a.chunk)}}else _(t)}}function j(e,t){"writable"===e._controlledWritableStream._state&&H(e,t)}function z(e){return U(e)<=0}function H(e,t){var r=e._controlledWritableStream;h("writable"===r._state);x(r,t)}function G(e){return new TypeError("WritableStream.prototype."+e+" can only be used on a WritableStream")}function W(e){return new TypeError("WritableStreamDefaultWriter.prototype."+e+" can only be used on a WritableStreamDefaultWriter")}function X(e){return new TypeError("Cannot "+e+" a stream using a released writer")}function V(e){e._closedPromise=new Promise(function(t,r){e._closedPromise_resolve=t;e._closedPromise_reject=r;e._closedPromiseState="pending"})}function K(e,t){h(void 0!==e._closedPromise_resolve,"writer._closedPromise_resolve !== undefined");h(void 0!==e._closedPromise_reject,"writer._closedPromise_reject !== undefined");h("pending"===e._closedPromiseState,"writer._closedPromiseState is pending");e._closedPromise_reject(t);e._closedPromise_resolve=void 0;e._closedPromise_reject=void 0;e._closedPromiseState="rejected"}function Y(e,t){e._readyPromise=Promise.reject(t);e._readyPromise_resolve=void 0;e._readyPromise_reject=void 0;e._readyPromiseState="rejected"}function J(e){e._readyPromise=Promise.resolve(void 0);e._readyPromise_resolve=void 0;e._readyPromise_reject=void 0;e._readyPromiseState="fulfilled"}function Z(e){h(void 0!==e._readyPromise_resolve,"writer._readyPromise_resolve !== undefined");h(void 0!==e._readyPromise_reject,"writer._readyPromise_reject !== undefined");e._readyPromise_resolve(void 0);e._readyPromise_resolve=void 0;e._readyPromise_reject=void 0;e._readyPromiseState="fulfilled"}},function(e,t,r){var a=r(0).IsFiniteNonNegativeNumber,i=r(1).assert;t.DequeueValue=function(e){i("_queue"in e&&"_queueTotalSize"in e,"Spec-level failure: DequeueValue should only be used on containers with [[queue]] and [[queueTotalSize]].");i(e._queue.length>0,"Spec-level failure: should never dequeue from an empty queue.");var t=e._queue.shift();e._queueTotalSize-=t.size;e._queueTotalSize<0&&(e._queueTotalSize=0);return t.value};t.EnqueueValueWithSize=function(e,t,r){i("_queue"in e&&"_queueTotalSize"in e,"Spec-level failure: EnqueueValueWithSize should only be used on containers with [[queue]] and [[queueTotalSize]].");r=Number(r);if(!a(r))throw new RangeError("Size must be a finite, non-NaN, non-negative number.");e._queue.push({value:t,size:r});e._queueTotalSize+=r};t.PeekQueueValue=function(e){i("_queue"in e&&"_queueTotalSize"in e,"Spec-level failure: PeekQueueValue should only be used on containers with [[queue]] and [[queueTotalSize]].");i(e._queue.length>0,"Spec-level failure: should never peek at an empty queue.");return e._queue[0].value};t.ResetQueue=function(e){i("_queue"in e&&"_queueTotalSize"in e,"Spec-level failure: ResetQueue should only be used on containers with [[queue]] and [[queueTotalSize]].");e._queue=[];e._queueTotalSize=0}},function(e,t,r){var a=function(){function e(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1;a.configurable=!0;"value"in a&&(a.writable=!0);Object.defineProperty(e,a.key,a)}}return function(t,r,a){r&&e(t.prototype,r);a&&e(t,a);return t}}();function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var n=r(0),o=n.ArrayBufferCopy,s=n.CreateIterResultObject,c=n.IsFiniteNonNegativeNumber,l=n.InvokeOrNoop,u=n.PromiseInvokeOrNoop,h=n.TransferArrayBuffer,f=n.ValidateAndNormalizeQueuingStrategy,d=n.ValidateAndNormalizeHighWaterMark,g=r(0),m=g.createArrayFromList,p=g.createDataProperty,v=g.typeIsObject,b=r(1),y=b.assert,w=b.rethrowAssertionErrorRejection,k=r(3),S=k.DequeueValue,C=k.EnqueueValueWithSize,x=k.ResetQueue,_=r(2),A=_.AcquireWritableStreamDefaultWriter,P=_.IsWritableStream,I=_.IsWritableStreamLocked,O=_.WritableStreamAbort,T=_.WritableStreamDefaultWriterCloseWithErrorPropagation,E=_.WritableStreamDefaultWriterRelease,F=_.WritableStreamDefaultWriterWrite,R=_.WritableStreamCloseQueuedOrInFlight,B=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},a=r.size,n=r.highWaterMark;i(this,e);this._state="readable";this._reader=void 0;this._storedError=void 0;this._disturbed=!1;this._readableStreamController=void 0;var o=t.type;if("bytes"===String(o)){void 0===n&&(n=0);this._readableStreamController=new fe(this,t,n)}else{if(void 0!==o)throw new RangeError("Invalid type is specified");void 0===n&&(n=1);this._readableStreamController=new ae(this,t,a,n)}}a(e,[{key:"cancel",value:function(e){return!1===M(this)?Promise.reject(Oe("cancel")):!0===L(this)?Promise.reject(new TypeError("Cannot cancel a stream that already has a reader")):j(this,e)}},{key:"getReader",value:function(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}).mode;if(!1===M(this))throw Oe("getReader");if(void 0===e)return D(this);if("byob"===(e=String(e)))return new J(this);throw new RangeError("Invalid mode is specified")}},{key:"pipeThrough",value:function(e,t){var r=e.writable,a=e.readable;!function(e){try{Promise.prototype.then.call(e,void 0,function(){})}catch(e){}}(this.pipeTo(r,t));return a}},{key:"pipeTo",value:function(e){var t=this,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},a=r.preventClose,i=r.preventAbort,n=r.preventCancel;if(!1===M(this))return Promise.reject(Oe("pipeTo"));if(!1===P(e))return Promise.reject(new TypeError("ReadableStream.prototype.pipeTo's first argument must be a WritableStream"));a=Boolean(a);i=Boolean(i);n=Boolean(n);if(!0===L(this))return Promise.reject(new TypeError("ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream"));if(!0===I(e))return Promise.reject(new TypeError("ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream"));var o=D(this),s=A(e),c=!1,l=Promise.resolve();return new Promise(function(r,u){p(t,o._closedPromise,function(t){!1===i?v(function(){return O(e,t)},!0,t):b(!0,t)});p(e,s._closedPromise,function(e){!1===n?v(function(){return j(t,e)},!0,e):b(!0,e)});h=t,f=o._closedPromise,d=function(){!1===a?v(function(){return T(s)}):b()},"closed"===h._state?d():f.then(d).catch(w);var h,f,d;if(!0===R(e)||"closed"===e._state){var g=new TypeError("the destination writable stream closed before all data could be piped to it");!1===n?v(function(){return j(t,g)},!0,g):b(!0,g)}(function e(){l=Promise.resolve();return!0===c?Promise.resolve():s._readyPromise.then(function(){return re(o).then(function(e){var t=e.value;!0!==e.done&&(l=F(s,t).catch(function(){}))})}).then(e)})().catch(function(e){l=Promise.resolve();w(e)});function m(){var e=l;return l.then(function(){return e!==l?m():void 0})}function p(e,t,r){"errored"===e._state?r(e._storedError):t.catch(r).catch(w)}function v(t,r,a){if(!0!==c){c=!0;"writable"===e._state&&!1===R(e)?m().then(i):i()}function i(){t().then(function(){return y(r,a)},function(e){return y(!0,e)}).catch(w)}}function b(t,r){if(!0!==c){c=!0;"writable"===e._state&&!1===R(e)?m().then(function(){return y(t,r)}).catch(w):y(t,r)}}function y(e,t){E(s);te(o);e?u(t):r(void 0)}})}},{key:"tee",value:function(){if(!1===M(this))throw Oe("tee");var e=N(this,!1);return m(e)}},{key:"locked",get:function(){if(!1===M(this))throw Oe("locked");return L(this)}}]);return e}();e.exports={ReadableStream:B,IsReadableStreamDisturbed:function(e){y(!0===M(e),"IsReadableStreamDisturbed should only be used on known readable streams");return e._disturbed},ReadableStreamDefaultControllerClose:oe,ReadableStreamDefaultControllerEnqueue:se,ReadableStreamDefaultControllerError:ce,ReadableStreamDefaultControllerGetDesiredSize:ue};function D(e){return new Y(e)}function M(e){return!!v(e)&&!!Object.prototype.hasOwnProperty.call(e,"_readableStreamController")}function L(e){y(!0===M(e),"IsReadableStreamLocked should only be used on known readable streams");return void 0!==e._reader}function N(e,t){y(!0===M(e));y("boolean"==typeof t);var r=D(e),a={closedOrErrored:!1,canceled1:!1,canceled2:!1,reason1:void 0,reason2:void 0};a.promise=new Promise(function(e){a._resolve=e});var i=function(){return function e(){var t=e._reader,r=e._branch1,a=e._branch2,i=e._teeState;return re(t).then(function(e){y(v(e));var t=e.value,n=e.done;y("boolean"==typeof n);if(!0===n&&!1===i.closedOrErrored){!1===i.canceled1&&oe(r);!1===i.canceled2&&oe(a);i.closedOrErrored=!0}if(!0!==i.closedOrErrored){var o=t,s=t;!1===i.canceled1&&se(r,o);!1===i.canceled2&&se(a,s)}})}}();i._reader=r;i._teeState=a;i._cloneForBranch2=t;var n=function(){return function e(t){var r=e._stream,a=e._teeState;a.canceled1=!0;a.reason1=t;if(!0===a.canceled2){var i=m([a.reason1,a.reason2]),n=j(r,i);a._resolve(n)}return a.promise}}();n._stream=e;n._teeState=a;var o=function(){return function e(t){var r=e._stream,a=e._teeState;a.canceled2=!0;a.reason2=t;if(!0===a.canceled1){var i=m([a.reason1,a.reason2]),n=j(r,i);a._resolve(n)}return a.promise}}();o._stream=e;o._teeState=a;var s=Object.create(Object.prototype);p(s,"pull",i);p(s,"cancel",n);var c=new B(s),l=Object.create(Object.prototype);p(l,"pull",i);p(l,"cancel",o);var u=new B(l);i._branch1=c._readableStreamController;i._branch2=u._readableStreamController;r._closedPromise.catch(function(e){if(!0!==a.closedOrErrored){ce(i._branch1,e);ce(i._branch2,e);a.closedOrErrored=!0}});return[c,u]}function U(e){y(!0===Z(e._reader));y("readable"===e._state||"closed"===e._state);return new Promise(function(t,r){var a={_resolve:t,_reject:r};e._reader._readIntoRequests.push(a)})}function q(e){y(!0===Q(e._reader));y("readable"===e._state);return new Promise(function(t,r){var a={_resolve:t,_reject:r};e._reader._readRequests.push(a)})}function j(e,t){e._disturbed=!0;if("closed"===e._state)return Promise.resolve(void 0);if("errored"===e._state)return Promise.reject(e._storedError);z(e);return e._readableStreamController.__cancelSteps(t).then(function(){})}function z(e){y("readable"===e._state);e._state="closed";var t=e._reader;if(void 0!==t){if(!0===Q(t)){for(var r=0;r<t._readRequests.length;r++){(0,t._readRequests[r]._resolve)(s(void 0,!0))}t._readRequests=[]}!function(e){y(void 0!==e._closedPromise_resolve);y(void 0!==e._closedPromise_reject);e._closedPromise_resolve(void 0);e._closedPromise_resolve=void 0;e._closedPromise_reject=void 0}(t)}}function H(e,t){y(!0===M(e),"stream must be ReadableStream");y("readable"===e._state,"state must be readable");e._state="errored";e._storedError=t;var r=e._reader;if(void 0!==r){if(!0===Q(r)){for(var a=0;a<r._readRequests.length;a++){r._readRequests[a]._reject(t)}r._readRequests=[]}else{y(Z(r),"reader must be ReadableStreamBYOBReader");for(var i=0;i<r._readIntoRequests.length;i++){r._readIntoRequests[i]._reject(t)}r._readIntoRequests=[]}Fe(r,t);r._closedPromise.catch(function(){})}}function G(e,t,r){var a=e._reader;y(a._readRequests.length>0);a._readRequests.shift()._resolve(s(t,r))}function W(e){return e._reader._readIntoRequests.length}function X(e){return e._reader._readRequests.length}function V(e){var t=e._reader;return void 0!==t&&!1!==Z(t)}function K(e){var t=e._reader;return void 0!==t&&!1!==Q(t)}var Y=function(){function e(t){i(this,e);if(!1===M(t))throw new TypeError("ReadableStreamDefaultReader can only be constructed with a ReadableStream instance");if(!0===L(t))throw new TypeError("This stream has already been locked for exclusive reading by another reader");$(this,t);this._readRequests=[]}a(e,[{key:"cancel",value:function(e){return!1===Q(this)?Promise.reject(Ee("cancel")):void 0===this._ownerReadableStream?Promise.reject(Te("cancel")):ee(this,e)}},{key:"read",value:function(){return!1===Q(this)?Promise.reject(Ee("read")):void 0===this._ownerReadableStream?Promise.reject(Te("read from")):re(this)}},{key:"releaseLock",value:function(){if(!1===Q(this))throw Ee("releaseLock");if(void 0!==this._ownerReadableStream){if(this._readRequests.length>0)throw new TypeError("Tried to release a reader lock when that reader has pending read() calls un-settled");te(this)}}},{key:"closed",get:function(){return!1===Q(this)?Promise.reject(Ee("closed")):this._closedPromise}}]);return e}(),J=function(){function e(t){i(this,e);if(!M(t))throw new TypeError("ReadableStreamBYOBReader can only be constructed with a ReadableStream instance given a byte source");if(!1===de(t._readableStreamController))throw new TypeError("Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte source");if(L(t))throw new TypeError("This stream has already been locked for exclusive reading by another reader");$(this,t);this._readIntoRequests=[]}a(e,[{key:"cancel",value:function(e){return Z(this)?void 0===this._ownerReadableStream?Promise.reject(Te("cancel")):ee(this,e):Promise.reject(Re("cancel"))}},{key:"read",value:function(e){return Z(this)?void 0===this._ownerReadableStream?Promise.reject(Te("read from")):ArrayBuffer.isView(e)?0===e.byteLength?Promise.reject(new TypeError("view must have non-zero byteLength")):function(e,t){var r=e._ownerReadableStream;y(void 0!==r);r._disturbed=!0;if("errored"===r._state)return Promise.reject(r._storedError);return function(e,t){var r=e._controlledReadableStream,a=1;t.constructor!==DataView&&(a=t.constructor.BYTES_PER_ELEMENT);var i=t.constructor,n={buffer:t.buffer,byteOffset:t.byteOffset,byteLength:t.byteLength,bytesFilled:0,elementSize:a,ctor:i,readerType:"byob"};if(e._pendingPullIntos.length>0){n.buffer=h(n.buffer);e._pendingPullIntos.push(n);return U(r)}if("closed"===r._state){var o=new t.constructor(n.buffer,n.byteOffset,0);return Promise.resolve(s(o,!0))}if(e._queueTotalSize>0){if(!0===we(e,n)){var c=be(n);Se(e);return Promise.resolve(s(c,!1))}if(!0===e._closeRequested){var l=new TypeError("Insufficient bytes to fill elements in the given buffer");Pe(e,l);return Promise.reject(l)}}n.buffer=h(n.buffer);e._pendingPullIntos.push(n);var u=U(r);me(e);return u}(r._readableStreamController,t)}(this,e):Promise.reject(new TypeError("view must be an array buffer view")):Promise.reject(Re("read"))}},{key:"releaseLock",value:function(){if(!Z(this))throw Re("releaseLock");if(void 0!==this._ownerReadableStream){if(this._readIntoRequests.length>0)throw new TypeError("Tried to release a reader lock when that reader has pending read() calls un-settled");te(this)}}},{key:"closed",get:function(){return Z(this)?this._closedPromise:Promise.reject(Re("closed"))}}]);return e}();function Z(e){return!!v(e)&&!!Object.prototype.hasOwnProperty.call(e,"_readIntoRequests")}function Q(e){return!!v(e)&&!!Object.prototype.hasOwnProperty.call(e,"_readRequests")}function $(e,t){e._ownerReadableStream=t;t._reader=e;if("readable"===t._state)!function(e){e._closedPromise=new Promise(function(t,r){e._closedPromise_resolve=t;e._closedPromise_reject=r})}(e);else if("closed"===t._state)!function(e){e._closedPromise=Promise.resolve(void 0);e._closedPromise_resolve=void 0;e._closedPromise_reject=void 0}(e);else{y("errored"===t._state,"state must be errored");!function(e,t){e._closedPromise=Promise.reject(t);e._closedPromise_resolve=void 0;e._closedPromise_reject=void 0}(e,t._storedError);e._closedPromise.catch(function(){})}}function ee(e,t){var r=e._ownerReadableStream;y(void 0!==r);return j(r,t)}function te(e){y(void 0!==e._ownerReadableStream);y(e._ownerReadableStream._reader===e);"readable"===e._ownerReadableStream._state?Fe(e,new TypeError("Reader was released and can no longer be used to monitor the stream's closedness")):function(e,t){y(void 0===e._closedPromise_resolve);y(void 0===e._closedPromise_reject);e._closedPromise=Promise.reject(t)}(e,new TypeError("Reader was released and can no longer be used to monitor the stream's closedness"));e._closedPromise.catch(function(){});e._ownerReadableStream._reader=void 0;e._ownerReadableStream=void 0}function re(e){var t=e._ownerReadableStream;y(void 0!==t);t._disturbed=!0;if("closed"===t._state)return Promise.resolve(s(void 0,!0));if("errored"===t._state)return Promise.reject(t._storedError);y("readable"===t._state);return t._readableStreamController.__pullSteps()}var ae=function(){function e(t,r,a,n){i(this,e);if(!1===M(t))throw new TypeError("ReadableStreamDefaultController can only be constructed with a ReadableStream instance");if(void 0!==t._readableStreamController)throw new TypeError("ReadableStreamDefaultController instances can only be created by the ReadableStream constructor");this._controlledReadableStream=t;this._underlyingSource=r;this._queue=void 0;this._queueTotalSize=void 0;x(this);this._started=!1;this._closeRequested=!1;this._pullAgain=!1;this._pulling=!1;var o=f(a,n);this._strategySize=o.size;this._strategyHWM=o.highWaterMark;var s=this,c=l(r,"start",[this]);Promise.resolve(c).then(function(){s._started=!0;y(!1===s._pulling);y(!1===s._pullAgain);ne(s)},function(e){le(s,e)}).catch(w)}a(e,[{key:"close",value:function(){if(!1===ie(this))throw Be("close");if(!0===this._closeRequested)throw new TypeError("The stream has already been closed; do not close it again!");var e=this._controlledReadableStream._state;if("readable"!==e)throw new TypeError("The stream (in "+e+" state) is not in the readable state and cannot be closed");oe(this)}},{key:"enqueue",value:function(e){if(!1===ie(this))throw Be("enqueue");if(!0===this._closeRequested)throw new TypeError("stream is closed or draining");var t=this._controlledReadableStream._state;if("readable"!==t)throw new TypeError("The stream (in "+t+" state) is not in the readable state and cannot be enqueued to");return se(this,e)}},{key:"error",value:function(e){if(!1===ie(this))throw Be("error");var t=this._controlledReadableStream;if("readable"!==t._state)throw new TypeError("The stream is "+t._state+" and so cannot be errored");ce(this,e)}},{key:"__cancelSteps",value:function(e){x(this);return u(this._underlyingSource,"cancel",[e])}},{key:"__pullSteps",value:function(){var e=this._controlledReadableStream;if(this._queue.length>0){var t=S(this);!0===this._closeRequested&&0===this._queue.length?z(e):ne(this);return Promise.resolve(s(t,!1))}var r=q(e);ne(this);return r}},{key:"desiredSize",get:function(){if(!1===ie(this))throw Be("desiredSize");return ue(this)}}]);return e}();function ie(e){return!!v(e)&&!!Object.prototype.hasOwnProperty.call(e,"_underlyingSource")}function ne(e){if(!1!==function(e){var t=e._controlledReadableStream;if("closed"===t._state||"errored"===t._state)return!1;if(!0===e._closeRequested)return!1;if(!1===e._started)return!1;if(!0===L(t)&&X(t)>0)return!0;if(ue(e)>0)return!0;return!1}(e))if(!0!==e._pulling){y(!1===e._pullAgain);e._pulling=!0;u(e._underlyingSource,"pull",[e]).then(function(){e._pulling=!1;if(!0===e._pullAgain){e._pullAgain=!1;return ne(e)}},function(t){le(e,t)}).catch(w)}else e._pullAgain=!0}function oe(e){var t=e._controlledReadableStream;y(!1===e._closeRequested);y("readable"===t._state);e._closeRequested=!0;0===e._queue.length&&z(t)}function se(e,t){var r=e._controlledReadableStream;y(!1===e._closeRequested);y("readable"===r._state);if(!0===L(r)&&X(r)>0)G(r,t,!1);else{var a=1;if(void 0!==e._strategySize){var i=e._strategySize;try{a=i(t)}catch(t){le(e,t);throw t}}try{C(e,t,a)}catch(t){le(e,t);throw t}}ne(e)}function ce(e,t){var r=e._controlledReadableStream;y("readable"===r._state);x(e);H(r,t)}function le(e,t){"readable"===e._controlledReadableStream._state&&ce(e,t)}function ue(e){var t=e._controlledReadableStream._state;return"errored"===t?null:"closed"===t?0:e._strategyHWM-e._queueTotalSize}var he=function(){function e(t,r){i(this,e);this._associatedReadableByteStreamController=t;this._view=r}a(e,[{key:"respond",value:function(e){if(!1===ge(this))throw De("respond");if(void 0===this._associatedReadableByteStreamController)throw new TypeError("This BYOB request has been invalidated");!function(e,t){t=Number(t);if(!1===c(t))throw new RangeError("bytesWritten must be a finite");y(e._pendingPullIntos.length>0);_e(e,t)}(this._associatedReadableByteStreamController,e)}},{key:"respondWithNewView",value:function(e){if(!1===ge(this))throw De("respond");if(void 0===this._associatedReadableByteStreamController)throw new TypeError("This BYOB request has been invalidated");if(!ArrayBuffer.isView(e))throw new TypeError("You can only respond with array buffer views");!function(e,t){y(e._pendingPullIntos.length>0);var r=e._pendingPullIntos[0];if(r.byteOffset+r.bytesFilled!==t.byteOffset)throw new RangeError("The region specified by view does not match byobRequest");if(r.byteLength!==t.byteLength)throw new RangeError("The buffer of view has different capacity than byobRequest");r.buffer=t.buffer;_e(e,t.byteLength)}(this._associatedReadableByteStreamController,e)}},{key:"view",get:function(){return this._view}}]);return e}(),fe=function(){function e(t,r,a){i(this,e);if(!1===M(t))throw new TypeError("ReadableByteStreamController can only be constructed with a ReadableStream instance given a byte source");if(void 0!==t._readableStreamController)throw new TypeError("ReadableByteStreamController instances can only be created by the ReadableStream constructor given a byte source");this._controlledReadableStream=t;this._underlyingByteSource=r;this._pullAgain=!1;this._pulling=!1;pe(this);this._queue=this._queueTotalSize=void 0;x(this);this._closeRequested=!1;this._started=!1;this._strategyHWM=d(a);var n=r.autoAllocateChunkSize;if(void 0!==n&&(!1===Number.isInteger(n)||n<=0))throw new RangeError("autoAllocateChunkSize must be a positive integer");this._autoAllocateChunkSize=n;this._pendingPullIntos=[];var o=this,s=l(r,"start",[this]);Promise.resolve(s).then(function(){o._started=!0;y(!1===o._pulling);y(!1===o._pullAgain);me(o)},function(e){"readable"===t._state&&Pe(o,e)}).catch(w)}a(e,[{key:"close",value:function(){if(!1===de(this))throw Me("close");if(!0===this._closeRequested)throw new TypeError("The stream has already been closed; do not close it again!");var e=this._controlledReadableStream._state;if("readable"!==e)throw new TypeError("The stream (in "+e+" state) is not in the readable state and cannot be closed");!function(e){var t=e._controlledReadableStream;y(!1===e._closeRequested);y("readable"===t._state);if(e._queueTotalSize>0){e._closeRequested=!0;return}if(e._pendingPullIntos.length>0){var r=e._pendingPullIntos[0];if(r.bytesFilled>0){var a=new TypeError("Insufficient bytes to fill elements in the given buffer");Pe(e,a);throw a}}z(t)}(this)}},{key:"enqueue",value:function(e){if(!1===de(this))throw Me("enqueue");if(!0===this._closeRequested)throw new TypeError("stream is closed or draining");var t=this._controlledReadableStream._state;if("readable"!==t)throw new TypeError("The stream (in "+t+" state) is not in the readable state and cannot be enqueued to");if(!ArrayBuffer.isView(e))throw new TypeError("You can only enqueue array buffer views when using a ReadableByteStreamController");!function(e,t){var r=e._controlledReadableStream;y(!1===e._closeRequested);y("readable"===r._state);var a=t.buffer,i=t.byteOffset,n=t.byteLength,o=h(a);if(!0===K(r))if(0===X(r))ye(e,o,i,n);else{y(0===e._queue.length);var s=new Uint8Array(o,i,n);G(r,s,!1)}else if(!0===V(r)){ye(e,o,i,n);xe(e)}else{y(!1===L(r),"stream must not be locked");ye(e,o,i,n)}}(this,e)}},{key:"error",value:function(e){if(!1===de(this))throw Me("error");var t=this._controlledReadableStream;if("readable"!==t._state)throw new TypeError("The stream is "+t._state+" and so cannot be errored");Pe(this,e)}},{key:"__cancelSteps",value:function(e){if(this._pendingPullIntos.length>0){this._pendingPullIntos[0].bytesFilled=0}x(this);return u(this._underlyingByteSource,"cancel",[e])}},{key:"__pullSteps",value:function(){var e=this._controlledReadableStream;y(!0===K(e));if(this._queueTotalSize>0){y(0===X(e));var t=this._queue.shift();this._queueTotalSize-=t.byteLength;Se(this);var r=void 0;try{r=new Uint8Array(t.buffer,t.byteOffset,t.byteLength)}catch(e){return Promise.reject(e)}return Promise.resolve(s(r,!1))}var a=this._autoAllocateChunkSize;if(void 0!==a){var i=void 0;try{i=new ArrayBuffer(a)}catch(e){return Promise.reject(e)}var n={buffer:i,byteOffset:0,byteLength:a,bytesFilled:0,elementSize:1,ctor:Uint8Array,readerType:"default"};this._pendingPullIntos.push(n)}var o=q(e);me(this);return o}},{key:"byobRequest",get:function(){if(!1===de(this))throw Me("byobRequest");if(void 0===this._byobRequest&&this._pendingPullIntos.length>0){var e=this._pendingPullIntos[0],t=new Uint8Array(e.buffer,e.byteOffset+e.bytesFilled,e.byteLength-e.bytesFilled);this._byobRequest=new he(this,t)}return this._byobRequest}},{key:"desiredSize",get:function(){if(!1===de(this))throw Me("desiredSize");return Ie(this)}}]);return e}();function de(e){return!!v(e)&&!!Object.prototype.hasOwnProperty.call(e,"_underlyingByteSource")}function ge(e){return!!v(e)&&!!Object.prototype.hasOwnProperty.call(e,"_associatedReadableByteStreamController")}function me(e){if(!1!==function(e){var t=e._controlledReadableStream;if("readable"!==t._state)return!1;if(!0===e._closeRequested)return!1;if(!1===e._started)return!1;if(!0===K(t)&&X(t)>0)return!0;if(!0===V(t)&&W(t)>0)return!0;if(Ie(e)>0)return!0;return!1}(e))if(!0!==e._pulling){y(!1===e._pullAgain);e._pulling=!0;u(e._underlyingByteSource,"pull",[e]).then(function(){e._pulling=!1;if(!0===e._pullAgain){e._pullAgain=!1;me(e)}},function(t){"readable"===e._controlledReadableStream._state&&Pe(e,t)}).catch(w)}else e._pullAgain=!0}function pe(e){Ce(e);e._pendingPullIntos=[]}function ve(e,t){y("errored"!==e._state,"state must not be errored");var r=!1;if("closed"===e._state){y(0===t.bytesFilled);r=!0}var a=be(t);if("default"===t.readerType)G(e,a,r);else{y("byob"===t.readerType);!function(e,t,r){var a=e._reader;y(a._readIntoRequests.length>0);a._readIntoRequests.shift()._resolve(s(t,r))}(e,a,r)}}function be(e){var t=e.bytesFilled,r=e.elementSize;y(t<=e.byteLength);y(t%r==0);return new e.ctor(e.buffer,e.byteOffset,t/r)}function ye(e,t,r,a){e._queue.push({buffer:t,byteOffset:r,byteLength:a});e._queueTotalSize+=a}function we(e,t){var r=t.elementSize,a=t.bytesFilled-t.bytesFilled%r,i=Math.min(e._queueTotalSize,t.byteLength-t.bytesFilled),n=t.bytesFilled+i,s=n-n%r,c=i,l=!1;if(s>a){c=s-t.bytesFilled;l=!0}for(var u=e._queue;c>0;){var h=u[0],f=Math.min(c,h.byteLength),d=t.byteOffset+t.bytesFilled;o(t.buffer,d,h.buffer,h.byteOffset,f);if(h.byteLength===f)u.shift();else{h.byteOffset+=f;h.byteLength-=f}e._queueTotalSize-=f;ke(e,f,t);c-=f}if(!1===l){y(0===e._queueTotalSize,"queue must be empty");y(t.bytesFilled>0);y(t.bytesFilled<t.elementSize)}return l}function ke(e,t,r){y(0===e._pendingPullIntos.length||e._pendingPullIntos[0]===r);Ce(e);r.bytesFilled+=t}function Se(e){y("readable"===e._controlledReadableStream._state);0===e._queueTotalSize&&!0===e._closeRequested?z(e._controlledReadableStream):me(e)}function Ce(e){if(void 0!==e._byobRequest){e._byobRequest._associatedReadableByteStreamController=void 0;e._byobRequest._view=void 0;e._byobRequest=void 0}}function xe(e){y(!1===e._closeRequested);for(;e._pendingPullIntos.length>0;){if(0===e._queueTotalSize)return;var t=e._pendingPullIntos[0];if(!0===we(e,t)){Ae(e);ve(e._controlledReadableStream,t)}}}function _e(e,t){var r=e._pendingPullIntos[0],a=e._controlledReadableStream;if("closed"===a._state){if(0!==t)throw new TypeError("bytesWritten must be 0 when calling respond() on a closed stream");!function(e,t){t.buffer=h(t.buffer);y(0===t.bytesFilled,"bytesFilled must be 0");var r=e._controlledReadableStream;if(!0===V(r))for(;W(r)>0;)ve(r,Ae(e))}(e,r)}else{y("readable"===a._state);!function(e,t,r){if(r.bytesFilled+t>r.byteLength)throw new RangeError("bytesWritten out of range");ke(e,t,r);if(!(r.bytesFilled<r.elementSize)){Ae(e);var a=r.bytesFilled%r.elementSize;if(a>0){var i=r.byteOffset+r.bytesFilled,n=r.buffer.slice(i-a,i);ye(e,n,0,n.byteLength)}r.buffer=h(r.buffer);r.bytesFilled-=a;ve(e._controlledReadableStream,r);xe(e)}}(e,t,r)}}function Ae(e){var t=e._pendingPullIntos.shift();Ce(e);return t}function Pe(e,t){var r=e._controlledReadableStream;y("readable"===r._state);pe(e);x(e);H(r,t)}function Ie(e){var t=e._controlledReadableStream._state;return"errored"===t?null:"closed"===t?0:e._strategyHWM-e._queueTotalSize}function Oe(e){return new TypeError("ReadableStream.prototype."+e+" can only be used on a ReadableStream")}function Te(e){return new TypeError("Cannot "+e+" a stream using a released reader")}function Ee(e){return new TypeError("ReadableStreamDefaultReader.prototype."+e+" can only be used on a ReadableStreamDefaultReader")}function Fe(e,t){y(void 0!==e._closedPromise_resolve);y(void 0!==e._closedPromise_reject);e._closedPromise_reject(t);e._closedPromise_resolve=void 0;e._closedPromise_reject=void 0}function Re(e){return new TypeError("ReadableStreamBYOBReader.prototype."+e+" can only be used on a ReadableStreamBYOBReader")}function Be(e){return new TypeError("ReadableStreamDefaultController.prototype."+e+" can only be used on a ReadableStreamDefaultController")}function De(e){return new TypeError("ReadableStreamBYOBRequest.prototype."+e+" can only be used on a ReadableStreamBYOBRequest")}function Me(e){return new TypeError("ReadableByteStreamController.prototype."+e+" can only be used on a ReadableByteStreamController")}},function(e,t,r){var a=r(6),i=r(4),n=r(2);t.TransformStream=a.TransformStream;t.ReadableStream=i.ReadableStream;t.IsReadableStreamDisturbed=i.IsReadableStreamDisturbed;t.ReadableStreamDefaultControllerClose=i.ReadableStreamDefaultControllerClose;t.ReadableStreamDefaultControllerEnqueue=i.ReadableStreamDefaultControllerEnqueue;t.ReadableStreamDefaultControllerError=i.ReadableStreamDefaultControllerError;t.ReadableStreamDefaultControllerGetDesiredSize=i.ReadableStreamDefaultControllerGetDesiredSize;t.AcquireWritableStreamDefaultWriter=n.AcquireWritableStreamDefaultWriter;t.IsWritableStream=n.IsWritableStream;t.IsWritableStreamLocked=n.IsWritableStreamLocked;t.WritableStream=n.WritableStream;t.WritableStreamAbort=n.WritableStreamAbort;t.WritableStreamDefaultControllerError=n.WritableStreamDefaultControllerError;t.WritableStreamDefaultWriterCloseWithErrorPropagation=n.WritableStreamDefaultWriterCloseWithErrorPropagation;t.WritableStreamDefaultWriterRelease=n.WritableStreamDefaultWriterRelease;t.WritableStreamDefaultWriterWrite=n.WritableStreamDefaultWriterWrite},function(e,t,r){var a=function(){function e(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1;a.configurable=!0;"value"in a&&(a.writable=!0);Object.defineProperty(e,a.key,a)}}return function(t,r,a){r&&e(t.prototype,r);a&&e(t,a);return t}}();function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var n=r(1).assert,o=r(0),s=o.InvokeOrNoop,c=o.PromiseInvokeOrPerformFallback,l=o.PromiseInvokeOrNoop,u=o.typeIsObject,h=r(4),f=h.ReadableStream,d=h.ReadableStreamDefaultControllerClose,g=h.ReadableStreamDefaultControllerEnqueue,m=h.ReadableStreamDefaultControllerError,p=h.ReadableStreamDefaultControllerGetDesiredSize,v=r(2),b=v.WritableStream,y=v.WritableStreamDefaultControllerError;function w(e,t){if(!0===e._errored)throw new TypeError("TransformStream is already errored");if(!0===e._readableClosed)throw new TypeError("Readable side is already closed");var r=e._readableController;try{g(r,t)}catch(t){e._readableClosed=!0;S(e,t);throw e._storedError}!0===p(r)<=0&&!1===e._backpressure&&_(e,!0)}function k(e){n(!1===e._errored);n(!1===e._readableClosed);try{d(e._readableController)}catch(e){n(!1)}e._readableClosed=!0}function S(e,t){!1===e._errored&&C(e,t)}function C(e,t){n(!1===e._errored);e._errored=!0;e._storedError=t;!1===e._writableDone&&y(e._writableController,t);!1===e._readableClosed&&m(e._readableController,t)}function x(e){n(void 0!==e._backpressureChangePromise,"_backpressureChangePromise should have been initialized");if(!1===e._backpressure)return Promise.resolve();n(!0===e._backpressure,"_backpressure should have been initialized");return e._backpressureChangePromise}function _(e,t){n(e._backpressure!==t,"TransformStreamSetBackpressure() should be called only when backpressure is changed");void 0!==e._backpressureChangePromise&&e._backpressureChangePromise_resolve(t);e._backpressureChangePromise=new Promise(function(t){e._backpressureChangePromise_resolve=t});e._backpressureChangePromise.then(function(e){n(e!==t,"_backpressureChangePromise should be fulfilled only when backpressure is changed")});e._backpressure=t}function A(e,t){w(t._controlledTransformStream,e);return Promise.resolve()}function P(e){return!!u(e)&&!!Object.prototype.hasOwnProperty.call(e,"_controlledTransformStream")}function I(e){return!!u(e)&&!!Object.prototype.hasOwnProperty.call(e,"_transformStreamController")}var O=function(){function e(t,r){i(this,e);this._transformStream=t;this._startPromise=r}a(e,[{key:"start",value:function(e){var t=this._transformStream;t._writableController=e;return this._startPromise.then(function(){return x(t)})}},{key:"write",value:function(e){return function(e,t){n(!1===e._errored);n(!1===e._transforming);n(!1===e._backpressure);e._transforming=!0;var r=e._transformer,a=e._transformStreamController;return c(r,"transform",[t,a],A,[t,a]).then(function(){e._transforming=!1;return x(e)},function(t){S(e,t);return Promise.reject(t)})}(this._transformStream,e)}},{key:"abort",value:function(){var e=this._transformStream;e._writableDone=!0;C(e,new TypeError("Writable side aborted"))}},{key:"close",value:function(){var e=this._transformStream;n(!1===e._transforming);e._writableDone=!0;return l(e._transformer,"flush",[e._transformStreamController]).then(function(){if(!0===e._errored)return Promise.reject(e._storedError);!1===e._readableClosed&&k(e);return Promise.resolve()}).catch(function(t){S(e,t);return Promise.reject(e._storedError)})}}]);return e}(),T=function(){function e(t,r){i(this,e);this._transformStream=t;this._startPromise=r}a(e,[{key:"start",value:function(e){var t=this._transformStream;t._readableController=e;return this._startPromise.then(function(){n(void 0!==t._backpressureChangePromise,"_backpressureChangePromise should have been initialized");if(!0===t._backpressure)return Promise.resolve();n(!1===t._backpressure,"_backpressure should have been initialized");return t._backpressureChangePromise})}},{key:"pull",value:function(){var e=this._transformStream;n(!0===e._backpressure,"pull() should be never called while _backpressure is false");n(void 0!==e._backpressureChangePromise,"_backpressureChangePromise should have been initialized");_(e,!1);return e._backpressureChangePromise}},{key:"cancel",value:function(){var e=this._transformStream;e._readableClosed=!0;C(e,new TypeError("Readable side canceled"))}}]);return e}(),E=function(){function e(t){i(this,e);if(!1===I(t))throw new TypeError("TransformStreamDefaultController can only be constructed with a TransformStream instance");if(void 0!==t._transformStreamController)throw new TypeError("TransformStreamDefaultController instances can only be created by the TransformStream constructor");this._controlledTransformStream=t}a(e,[{key:"enqueue",value:function(e){if(!1===P(this))throw R("enqueue");w(this._controlledTransformStream,e)}},{key:"close",value:function(){if(!1===P(this))throw R("close");!function(e){if(!0===e._errored)throw new TypeError("TransformStream is already errored");if(!0===e._readableClosed)throw new TypeError("Readable side is already closed");k(e)}(this._controlledTransformStream)}},{key:"error",value:function(e){if(!1===P(this))throw R("error");!function(e,t){if(!0===e._errored)throw new TypeError("TransformStream is already errored");C(e,t)}(this._controlledTransformStream,e)}},{key:"desiredSize",get:function(){if(!1===P(this))throw R("desiredSize");var e=this._controlledTransformStream._readableController;return p(e)}}]);return e}(),F=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};i(this,e);this._transformer=t;var r=t.readableStrategy,a=t.writableStrategy;this._transforming=!1;this._errored=!1;this._storedError=void 0;this._writableController=void 0;this._readableController=void 0;this._transformStreamController=void 0;this._writableDone=!1;this._readableClosed=!1;this._backpressure=void 0;this._backpressureChangePromise=void 0;this._backpressureChangePromise_resolve=void 0;this._transformStreamController=new E(this);var o=void 0,c=new Promise(function(e){o=e}),l=new T(this,c);this._readable=new f(l,r);var u=new O(this,c);this._writable=new b(u,a);n(void 0!==this._writableController);n(void 0!==this._readableController);_(this,p(this._readableController)<=0);var h=this,d=s(t,"start",[h._transformStreamController]);o(d);c.catch(function(e){if(!1===h._errored){h._errored=!0;h._storedError=e}})}a(e,[{key:"readable",get:function(){if(!1===I(this))throw B("readable");return this._readable}},{key:"writable",get:function(){if(!1===I(this))throw B("writable");return this._writable}}]);return e}();e.exports={TransformStream:F};function R(e){return new TypeError("TransformStreamDefaultController.prototype."+e+" can only be used on a TransformStreamDefaultController")}function B(e){return new TypeError("TransformStream.prototype."+e+" can only be used on a TransformStream")}},function(e,t,r){e.exports=r(5)}]))},function(e,t,r){"use strict";var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i=!1;try{if("function"==typeof URL&&"object"===a(URL.prototype)&&"origin"in URL.prototype){var n=new URL("b","http://a");n.pathname="c%20d";i="http://a/c%20d"===n.href}}catch(e){}if(i)t.URL=URL;else{var o=r(129).URL,s=r(4).URL;if(s){o.createObjectURL=function(e){return s.createObjectURL.apply(s,arguments)};o.revokeObjectURL=function(e){s.revokeObjectURL(e)}}t.URL=o}},function(e,t,r){"use strict";!function(){var e=Object.create(null);e.ftp=21;e.file=0;e.gopher=70;e.http=80;e.https=443;e.ws=80;e.wss=443;var r=Object.create(null);r["%2e"]=".";r[".%2e"]="..";r["%2e."]="..";r["%2e%2e"]="..";function a(t){return void 0!==e[t]}function i(){f.call(this);this._isInvalid=!0}function n(e){""===e&&i.call(this);return e.toLowerCase()}function o(e){var t=e.charCodeAt(0);return t>32&&t<127&&-1===[34,35,60,62,63,96].indexOf(t)?e:encodeURIComponent(e)}function s(e){var t=e.charCodeAt(0);return t>32&&t<127&&-1===[34,35,60,62,96].indexOf(t)?e:encodeURIComponent(e)}var c,l=/[a-zA-Z]/,u=/[a-zA-Z0-9\+\-\.]/;function h(t,h,f){function d(e){y.push(e)}var g=h||"scheme start",m=0,p="",v=!1,b=!1,y=[];e:for(;(t[m-1]!==c||0===m)&&!this._isInvalid;){var w=t[m];switch(g){case"scheme start":if(!w||!l.test(w)){if(h){d("Invalid scheme.");break e}p="";g="no scheme";continue}p+=w.toLowerCase();g="scheme";break;case"scheme":if(w&&u.test(w))p+=w.toLowerCase();else{if(":"!==w){if(h){if(w===c)break e;d("Code point not allowed in scheme: "+w);break e}p="";m=0;g="no scheme";continue}this._scheme=p;p="";if(h)break e;a(this._scheme)&&(this._isRelative=!0);g="file"===this._scheme?"relative":this._isRelative&&f&&f._scheme===this._scheme?"relative or authority":this._isRelative?"authority first slash":"scheme data"}break;case"scheme data":if("?"===w){this._query="?";g="query"}else if("#"===w){this._fragment="#";g="fragment"}else w!==c&&"\t"!==w&&"\n"!==w&&"\r"!==w&&(this._schemeData+=o(w));break;case"no scheme":if(f&&a(f._scheme)){g="relative";continue}d("Missing scheme.");i.call(this);break;case"relative or authority":if("/"!==w||"/"!==t[m+1]){d("Expected /, got: "+w);g="relative";continue}g="authority ignore slashes";break;case"relative":this._isRelative=!0;"file"!==this._scheme&&(this._scheme=f._scheme);if(w===c){this._host=f._host;this._port=f._port;this._path=f._path.slice();this._query=f._query;this._username=f._username;this._password=f._password;break e}if("/"===w||"\\"===w){"\\"===w&&d("\\ is an invalid code point.");g="relative slash"}else if("?"===w){this._host=f._host;this._port=f._port;this._path=f._path.slice();this._query="?";this._username=f._username;this._password=f._password;g="query"}else{if("#"!==w){var k=t[m+1],S=t[m+2];if("file"!==this._scheme||!l.test(w)||":"!==k&&"|"!==k||S!==c&&"/"!==S&&"\\"!==S&&"?"!==S&&"#"!==S){this._host=f._host;this._port=f._port;this._username=f._username;this._password=f._password;this._path=f._path.slice();this._path.pop()}g="relative path";continue}this._host=f._host;this._port=f._port;this._path=f._path.slice();this._query=f._query;this._fragment="#";this._username=f._username;this._password=f._password;g="fragment"}break;case"relative slash":if("/"!==w&&"\\"!==w){if("file"!==this._scheme){this._host=f._host;this._port=f._port;this._username=f._username;this._password=f._password}g="relative path";continue}"\\"===w&&d("\\ is an invalid code point.");g="file"===this._scheme?"file host":"authority ignore slashes";break;case"authority first slash":if("/"!==w){d("Expected '/', got: "+w);g="authority ignore slashes";continue}g="authority second slash";break;case"authority second slash":g="authority ignore slashes";if("/"!==w){d("Expected '/', got: "+w);continue}break;case"authority ignore slashes":if("/"!==w&&"\\"!==w){g="authority";continue}d("Expected authority, got: "+w);break;case"authority":if("@"===w){if(v){d("@ already seen.");p+="%40"}v=!0;for(var C=0;C<p.length;C++){var x=p[C];if("\t"!==x&&"\n"!==x&&"\r"!==x)if(":"!==x||null!==this._password){var _=o(x);null!==this._password?this._password+=_:this._username+=_}else this._password="";else d("Invalid whitespace in authority.")}p=""}else{if(w===c||"/"===w||"\\"===w||"?"===w||"#"===w){m-=p.length;p="";g="host";continue}p+=w}break;case"file host":if(w===c||"/"===w||"\\"===w||"?"===w||"#"===w){if(2!==p.length||!l.test(p[0])||":"!==p[1]&&"|"!==p[1])if(0===p.length)g="relative path start";else{this._host=n.call(this,p);p="";g="relative path start"}else g="relative path";continue}"\t"===w||"\n"===w||"\r"===w?d("Invalid whitespace in file host."):p+=w;break;case"host":case"hostname":if(":"!==w||b){if(w===c||"/"===w||"\\"===w||"?"===w||"#"===w){this._host=n.call(this,p);p="";g="relative path start";if(h)break e;continue}if("\t"!==w&&"\n"!==w&&"\r"!==w){"["===w?b=!0:"]"===w&&(b=!1);p+=w}else d("Invalid code point in host/hostname: "+w)}else{this._host=n.call(this,p);p="";g="port";if("hostname"===h)break e}break;case"port":if(/[0-9]/.test(w))p+=w;else{if(w===c||"/"===w||"\\"===w||"?"===w||"#"===w||h){if(""!==p){var A=parseInt(p,10);A!==e[this._scheme]&&(this._port=A+"");p=""}if(h)break e;g="relative path start";continue}"\t"===w||"\n"===w||"\r"===w?d("Invalid code point in port: "+w):i.call(this)}break;case"relative path start":"\\"===w&&d("'\\' not allowed in path.");g="relative path";if("/"!==w&&"\\"!==w)continue;break;case"relative path":if(w!==c&&"/"!==w&&"\\"!==w&&(h||"?"!==w&&"#"!==w))"\t"!==w&&"\n"!==w&&"\r"!==w&&(p+=o(w));else{"\\"===w&&d("\\ not allowed in relative path.");var P;(P=r[p.toLowerCase()])&&(p=P);if(".."===p){this._path.pop();"/"!==w&&"\\"!==w&&this._path.push("")}else if("."===p&&"/"!==w&&"\\"!==w)this._path.push("");else if("."!==p){"file"===this._scheme&&0===this._path.length&&2===p.length&&l.test(p[0])&&"|"===p[1]&&(p=p[0]+":");this._path.push(p)}p="";if("?"===w){this._query="?";g="query"}else if("#"===w){this._fragment="#";g="fragment"}}break;case"query":if(h||"#"!==w)w!==c&&"\t"!==w&&"\n"!==w&&"\r"!==w&&(this._query+=s(w));else{this._fragment="#";g="fragment"}break;case"fragment":w!==c&&"\t"!==w&&"\n"!==w&&"\r"!==w&&(this._fragment+=w)}m++}}function f(){this._scheme="";this._schemeData="";this._username="";this._password=null;this._host="";this._port="";this._path=[];this._query="";this._fragment="";this._isInvalid=!1;this._isRelative=!1}function d(e,t){void 0===t||t instanceof d||(t=new d(String(t)));this._url=e;f.call(this);var r=e.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g,"");h.call(this,r,null,t)}d.prototype={toString:function(){return this.href},get href(){if(this._isInvalid)return this._url;var e="";""===this._username&&null===this._password||(e=this._username+(null!==this._password?":"+this._password:"")+"@");return this.protocol+(this._isRelative?"//"+e+this.host:"")+this.pathname+this._query+this._fragment},set href(e){f.call(this);h.call(this,e)},get protocol(){return this._scheme+":"},set protocol(e){this._isInvalid||h.call(this,e+":","scheme start")},get host(){return this._isInvalid?"":this._port?this._host+":"+this._port:this._host},set host(e){!this._isInvalid&&this._isRelative&&h.call(this,e,"host")},get hostname(){return this._host},set hostname(e){!this._isInvalid&&this._isRelative&&h.call(this,e,"hostname")},get port(){return this._port},set port(e){!this._isInvalid&&this._isRelative&&h.call(this,e,"port")},get pathname(){return this._isInvalid?"":this._isRelative?"/"+this._path.join("/"):this._schemeData},set pathname(e){if(!this._isInvalid&&this._isRelative){this._path=[];h.call(this,e,"relative path start")}},get search(){return this._isInvalid||!this._query||"?"===this._query?"":this._query},set search(e){if(!this._isInvalid&&this._isRelative){this._query="?";"?"===e[0]&&(e=e.slice(1));h.call(this,e,"query")}},get hash(){return this._isInvalid||!this._fragment||"#"===this._fragment?"":this._fragment},set hash(e){if(!this._isInvalid){this._fragment="#";"#"===e[0]&&(e=e.slice(1));h.call(this,e,"fragment")}},get origin(){var e;if(this._isInvalid||!this._scheme)return"";switch(this._scheme){case"data":case"file":case"javascript":case"mailto":return"null";case"blob":try{return new d(this._schemeData).origin||"null"}catch(e){}return"null"}return(e=this.host)?this._scheme+"://"+e:""}};t.URL=d}()},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.NetworkPdfManager=t.LocalPdfManager=void 0;var a,i=r(131),n=(a=i)&&a.__esModule?a:{default:a},o=function(){function e(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1;a.configurable=!0;"value"in a&&(a.writable=!0);Object.defineProperty(e,a.key,a)}}return function(t,r,a){r&&e(t.prototype,r);a&&e(t,a);return t}}(),s=r(2),c=r(135),l=r(136),u=r(140);function h(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function f(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}});t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function d(e){return function(){var t=e.apply(this,arguments);return new Promise(function(e,r){return function a(i,n){try{var o=t[i](n),s=o.value}catch(e){r(e);return}if(!o.done)return Promise.resolve(s).then(function(e){a("next",e)},function(e){a("throw",e)});e(s)}("next")})}}function g(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var m=function(){function e(){g(this,e);this.constructor===e&&(0,s.unreachable)("Cannot initialize BasePdfManager.")}o(e,[{key:"onLoadedStream",value:function(){(0,s.unreachable)("Abstract method `onLoadedStream` called")}},{key:"ensureDoc",value:function(e,t){return this.ensure(this.pdfDocument,e,t)}},{key:"ensureXRef",value:function(e,t){return this.ensure(this.pdfDocument.xref,e,t)}},{key:"ensureCatalog",value:function(e,t){return this.ensure(this.pdfDocument.catalog,e,t)}},{key:"getPage",value:function(e){return this.pdfDocument.getPage(e)}},{key:"cleanup",value:function(){return this.pdfDocument.cleanup()}},{key:"ensure",value:function(){var e=d(n.default.mark(function e(t,r,a){return n.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:(0,s.unreachable)("Abstract method `ensure` called");case 1:case"end":return e.stop()}},e,this)}));return function(t,r,a){return e.apply(this,arguments)}}()},{key:"requestRange",value:function(e,t){(0,s.unreachable)("Abstract method `requestRange` called")}},{key:"requestLoadedStream",value:function(){(0,s.unreachable)("Abstract method `requestLoadedStream` called")}},{key:"sendProgressiveData",value:function(e){(0,s.unreachable)("Abstract method `sendProgressiveData` called")}},{key:"updatePassword",value:function(e){this._password=e}},{key:"terminate",value:function(){(0,s.unreachable)("Abstract method `terminate` called")}},{key:"docId",get:function(){return this._docId}},{key:"password",get:function(){return this._password}},{key:"docBaseUrl",get:function(){var e=null;if(this._docBaseUrl){var t=(0,s.createValidAbsoluteUrl)(this._docBaseUrl);t?e=t.href:(0,s.warn)('Invalid absolute docBaseUrl: "'+this._docBaseUrl+'".')}return(0,s.shadow)(this,"docBaseUrl",e)}}]);return e}(),p=function(e){f(t,m);function t(e,r,a,i,n){g(this,t);var o=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));o._docId=e;o._password=a;o._docBaseUrl=n;o.evaluatorOptions=i;var s=new u.Stream(r);o.pdfDocument=new l.PDFDocument(o,s);o._loadedStreamPromise=Promise.resolve(s);return o}o(t,[{key:"ensure",value:function(){var e=d(n.default.mark(function e(t,r,a){var i;return n.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if("function"!=typeof(i=t[r])){e.next=3;break}return e.abrupt("return",i.apply(t,a));case 3:return e.abrupt("return",i);case 4:case"end":return e.stop()}},e,this)}));return function(t,r,a){return e.apply(this,arguments)}}()},{key:"requestRange",value:function(e,t){return Promise.resolve()}},{key:"requestLoadedStream",value:function(){}},{key:"onLoadedStream",value:function(){return this._loadedStreamPromise}},{key:"terminate",value:function(){}}]);return t}(),v=function(e){f(t,m);function t(e,r,a,i,n){g(this,t);var o=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));o._docId=e;o._password=a.password;o._docBaseUrl=n;o.msgHandler=a.msgHandler;o.evaluatorOptions=i;o.streamManager=new c.ChunkedStreamManager(r,{msgHandler:a.msgHandler,url:a.url,length:a.length,disableAutoFetch:a.disableAutoFetch,rangeChunkSize:a.rangeChunkSize});o.pdfDocument=new l.PDFDocument(o,o.streamManager.getStream());return o}o(t,[{key:"ensure",value:function(){var e=d(n.default.mark(function e(t,r,a){var i;return n.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:e.prev=0;if("function"!=typeof(i=t[r])){e.next=4;break}return e.abrupt("return",i.apply(t,a));case 4:return e.abrupt("return",i);case 7:e.prev=7;e.t0=e.catch(0);if(e.t0 instanceof s.MissingDataException){e.next=11;break}throw e.t0;case 11:e.next=13;return this.requestRange(e.t0.begin,e.t0.end);case 13:return e.abrupt("return",this.ensure(t,r,a));case 14:case"end":return e.stop()}},e,this,[[0,7]])}));return function(t,r,a){return e.apply(this,arguments)}}()},{key:"requestRange",value:function(e,t){return this.streamManager.requestRange(e,t)}},{key:"requestLoadedStream",value:function(){this.streamManager.requestAllChunks()}},{key:"sendProgressiveData",value:function(e){this.streamManager.onReceiveData({chunk:e})}},{key:"onLoadedStream",value:function(){return this.streamManager.onLoadedStream()}},{key:"terminate",value:function(){this.streamManager.abort()}}]);return t}();t.LocalPdfManager=p;t.NetworkPdfManager=v},function(e,t,r){"use strict";e.exports=r(132)},function(e,t,r){"use strict";var a=function(){return this}()||Function("return this")(),i=a.regeneratorRuntime&&Object.getOwnPropertyNames(a).indexOf("regeneratorRuntime")>=0,n=i&&a.regeneratorRuntime;a.regeneratorRuntime=void 0;e.exports=r(133);if(i)a.regeneratorRuntime=n;else try{delete a.regeneratorRuntime}catch(e){a.regeneratorRuntime=void 0}},function(e,t,r){"use strict";(function(e){var t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};!function(r){var a,i=Object.prototype,n=i.hasOwnProperty,o="function"==typeof Symbol?Symbol:{},s=o.iterator||"@@iterator",c=o.asyncIterator||"@@asyncIterator",l=o.toStringTag||"@@toStringTag",u="object"===t(e),h=r.regeneratorRuntime;if(h)u&&(e.exports=h);else{(h=r.regeneratorRuntime=u?e.exports:{}).wrap=k;var f="suspendedStart",d="suspendedYield",g="executing",m="completed",p={},v={};v[s]=function(){return this};var b=Object.getPrototypeOf,y=b&&b(b(F([])));y&&y!==i&&n.call(y,s)&&(v=y);var w=_.prototype=C.prototype=Object.create(v);x.prototype=w.constructor=_;_.constructor=x;_[l]=x.displayName="GeneratorFunction";h.isGeneratorFunction=function(e){var t="function"==typeof e&&e.constructor;return!!t&&(t===x||"GeneratorFunction"===(t.displayName||t.name))};h.mark=function(e){if(Object.setPrototypeOf)Object.setPrototypeOf(e,_);else{e.__proto__=_;l in e||(e[l]="GeneratorFunction")}e.prototype=Object.create(w);return e};h.awrap=function(e){return{__await:e}};A(P.prototype);P.prototype[c]=function(){return this};h.AsyncIterator=P;h.async=function(e,t,r,a){var i=new P(k(e,t,r,a));return h.isGeneratorFunction(t)?i:i.next().then(function(e){return e.done?e.value:i.next()})};A(w);w[l]="Generator";w[s]=function(){return this};w.toString=function(){return"[object Generator]"};h.keys=function(e){var t=[];for(var r in e)t.push(r);t.reverse();return function r(){for(;t.length;){var a=t.pop();if(a in e){r.value=a;r.done=!1;return r}}r.done=!0;return r}};h.values=F;E.prototype={constructor:E,reset:function(e){this.prev=0;this.next=0;this.sent=this._sent=a;this.done=!1;this.delegate=null;this.method="next";this.arg=a;this.tryEntries.forEach(T);if(!e)for(var t in this)"t"===t.charAt(0)&&n.call(this,t)&&!isNaN(+t.slice(1))&&(this[t]=a)},stop:function(){this.done=!0;var e=this.tryEntries[0].completion;if("throw"===e.type)throw e.arg;return this.rval},dispatchException:function(e){if(this.done)throw e;var t=this;function r(r,i){s.type="throw";s.arg=e;t.next=r;if(i){t.method="next";t.arg=a}return!!i}for(var i=this.tryEntries.length-1;i>=0;--i){var o=this.tryEntries[i],s=o.completion;if("root"===o.tryLoc)return r("end");if(o.tryLoc<=this.prev){var c=n.call(o,"catchLoc"),l=n.call(o,"finallyLoc");if(c&&l){if(this.prev<o.catchLoc)return r(o.catchLoc,!0);if(this.prev<o.finallyLoc)return r(o.finallyLoc)}else if(c){if(this.prev<o.catchLoc)return r(o.catchLoc,!0)}else{if(!l)throw new Error("try statement without catch or finally");if(this.prev<o.finallyLoc)return r(o.finallyLoc)}}}},abrupt:function(e,t){for(var r=this.tryEntries.length-1;r>=0;--r){var a=this.tryEntries[r];if(a.tryLoc<=this.prev&&n.call(a,"finallyLoc")&&this.prev<a.finallyLoc){var i=a;break}}i&&("break"===e||"continue"===e)&&i.tryLoc<=t&&t<=i.finallyLoc&&(i=null);var o=i?i.completion:{};o.type=e;o.arg=t;if(i){this.method="next";this.next=i.finallyLoc;return p}return this.complete(o)},complete:function(e,t){if("throw"===e.type)throw e.arg;if("break"===e.type||"continue"===e.type)this.next=e.arg;else if("return"===e.type){this.rval=this.arg=e.arg;this.method="return";this.next="end"}else"normal"===e.type&&t&&(this.next=t);return p},finish:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var r=this.tryEntries[t];if(r.finallyLoc===e){this.complete(r.completion,r.afterLoc);T(r);return p}}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var r=this.tryEntries[t];if(r.tryLoc===e){var a=r.completion;if("throw"===a.type){var i=a.arg;T(r)}return i}}throw new Error("illegal catch attempt")},delegateYield:function(e,t,r){this.delegate={iterator:F(e),resultName:t,nextLoc:r};"next"===this.method&&(this.arg=a);return p}}}function k(e,t,r,a){var i=t&&t.prototype instanceof C?t:C,n=Object.create(i.prototype),o=new E(a||[]);n._invoke=function(e,t,r){var a=f;return function(i,n){if(a===g)throw new Error("Generator is already running");if(a===m){if("throw"===i)throw n;return R()}r.method=i;r.arg=n;for(;;){var o=r.delegate;if(o){var s=I(o,r);if(s){if(s===p)continue;return s}}if("next"===r.method)r.sent=r._sent=r.arg;else if("throw"===r.method){if(a===f){a=m;throw r.arg}r.dispatchException(r.arg)}else"return"===r.method&&r.abrupt("return",r.arg);a=g;var c=S(e,t,r);if("normal"===c.type){a=r.done?m:d;if(c.arg===p)continue;return{value:c.arg,done:r.done}}if("throw"===c.type){a=m;r.method="throw";r.arg=c.arg}}}}(e,r,o);return n}function S(e,t,r){try{return{type:"normal",arg:e.call(t,r)}}catch(e){return{type:"throw",arg:e}}}function C(){}function x(){}function _(){}function A(e){["next","throw","return"].forEach(function(t){e[t]=function(e){return this._invoke(t,e)}})}function P(e){var r;this._invoke=function(a,i){function o(){return new Promise(function(r,o){!function r(a,i,o,s){var c=S(e[a],e,i);if("throw"!==c.type){var l=c.arg,u=l.value;return u&&"object"===(void 0===u?"undefined":t(u))&&n.call(u,"__await")?Promise.resolve(u.__await).then(function(e){r("next",e,o,s)},function(e){r("throw",e,o,s)}):Promise.resolve(u).then(function(e){l.value=e;o(l)},s)}s(c.arg)}(a,i,r,o)})}return r=r?r.then(o,o):o()}}function I(e,t){var r=e.iterator[t.method];if(r===a){t.delegate=null;if("throw"===t.method){if(e.iterator.return){t.method="return";t.arg=a;I(e,t);if("throw"===t.method)return p}t.method="throw";t.arg=new TypeError("The iterator does not provide a 'throw' method")}return p}var i=S(r,e.iterator,t.arg);if("throw"===i.type){t.method="throw";t.arg=i.arg;t.delegate=null;return p}var n=i.arg;if(!n){t.method="throw";t.arg=new TypeError("iterator result is not an object");t.delegate=null;return p}if(!n.done)return n;t[e.resultName]=n.value;t.next=e.nextLoc;if("return"!==t.method){t.method="next";t.arg=a}t.delegate=null;return p}function O(e){var t={tryLoc:e[0]};1 in e&&(t.catchLoc=e[1]);if(2 in e){t.finallyLoc=e[2];t.afterLoc=e[3]}this.tryEntries.push(t)}function T(e){var t=e.completion||{};t.type="normal";delete t.arg;e.completion=t}function E(e){this.tryEntries=[{tryLoc:"root"}];e.forEach(O,this);this.reset(!0)}function F(e){if(e){var t=e[s];if(t)return t.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var r=-1,i=function t(){for(;++r<e.length;)if(n.call(e,r)){t.value=e[r];t.done=!1;return t}t.value=a;t.done=!0;return t};return i.next=i}}return{next:R}}function R(){return{value:a,done:!0}}}(function(){return this}()||Function("return this")())}).call(this,r(134)(e))},function(e,t,r){"use strict";e.exports=function(e){if(!e.webpackPolyfill){e.deprecate=function(){};e.paths=[];e.children||(e.children=[]);Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}});Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}});e.webpackPolyfill=1}return e}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.ChunkedStreamManager=t.ChunkedStream=void 0;var a=r(2),i=function(){function e(e,t,r){this.bytes=new Uint8Array(e);this.start=0;this.pos=0;this.end=e;this.chunkSize=t;this.loadedChunks=[];this.numChunksLoaded=0;this.numChunks=Math.ceil(e/t);this.manager=r;this.progressiveDataLength=0;this.lastSuccessfulEnsureByteChunk=-1}e.prototype={getMissingChunks:function(){for(var e=[],t=0,r=this.numChunks;t<r;++t)this.loadedChunks[t]||e.push(t);return e},getBaseStreams:function(){return[this]},allChunksLoaded:function(){return this.numChunksLoaded===this.numChunks},onReceiveData:function(e,t){var r=e+t.byteLength;if(e%this.chunkSize!=0)throw new Error("Bad begin offset: "+e);var a=this.bytes.length;if(r%this.chunkSize!=0&&r!==a)throw new Error("Bad end offset: "+r);this.bytes.set(new Uint8Array(t),e);var i,n=this.chunkSize,o=Math.floor(e/n),s=Math.floor((r-1)/n)+1;for(i=o;i<s;++i)if(!this.loadedChunks[i]){this.loadedChunks[i]=!0;++this.numChunksLoaded}},onReceiveProgressiveData:function(e){var t=this.progressiveDataLength,r=Math.floor(t/this.chunkSize);this.bytes.set(new Uint8Array(e),t);t+=e.byteLength;this.progressiveDataLength=t;var a,i=t>=this.end?this.numChunks:Math.floor(t/this.chunkSize);for(a=r;a<i;++a)if(!this.loadedChunks[a]){this.loadedChunks[a]=!0;++this.numChunksLoaded}},ensureByte:function(e){var t=Math.floor(e/this.chunkSize);if(t!==this.lastSuccessfulEnsureByteChunk){if(!this.loadedChunks[t])throw new a.MissingDataException(e,e+1);this.lastSuccessfulEnsureByteChunk=t}},ensureRange:function(e,t){if(!(e>=t||t<=this.progressiveDataLength))for(var r=this.chunkSize,i=Math.floor(e/r),n=Math.floor((t-1)/r)+1,o=i;o<n;++o)if(!this.loadedChunks[o])throw new a.MissingDataException(e,t)},nextEmptyChunk:function(e){for(var t,r=this.numChunks,a=0;a<r;++a){t=(e+a)%r;if(!this.loadedChunks[t])return t}return null},hasChunk:function(e){return!!this.loadedChunks[e]},get length(){return this.end-this.start},get isEmpty(){return 0===this.length},getByte:function(){var e=this.pos;if(e>=this.end)return-1;this.ensureByte(e);return this.bytes[this.pos++]},getUint16:function(){var e=this.getByte(),t=this.getByte();return-1===e||-1===t?-1:(e<<8)+t},getInt32:function(){return(this.getByte()<<24)+(this.getByte()<<16)+(this.getByte()<<8)+this.getByte()},getBytes:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=this.bytes,a=this.pos,i=this.end;if(!e){this.ensureRange(a,i);var n=r.subarray(a,i);return t?new Uint8ClampedArray(n):n}var o=a+e;o>i&&(o=i);this.ensureRange(a,o);this.pos=o;var s=r.subarray(a,o);return t?new Uint8ClampedArray(s):s},peekByte:function(){var e=this.getByte();this.pos--;return e},peekBytes:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=this.getBytes(e,t);this.pos-=r.length;return r},getByteRange:function(e,t){this.ensureRange(e,t);return this.bytes.subarray(e,t)},skip:function(e){e||(e=1);this.pos+=e},reset:function(){this.pos=this.start},moveStart:function(){this.start=this.pos},makeSubStream:function(e,t,r){this.ensureRange(e,e+t);function a(){}a.prototype=Object.create(this);a.prototype.getMissingChunks=function(){for(var e=this.chunkSize,t=Math.floor(this.start/e),r=Math.floor((this.end-1)/e)+1,a=[],i=t;i<r;++i)this.loadedChunks[i]||a.push(i);return a};var i=new a;i.pos=i.start=e;i.end=e+t||this.end;i.dict=r;return i}};return e}(),n=function(){function e(e,t){var r=t.rangeChunkSize,n=t.length;this.stream=new i(n,r,this);this.length=n;this.chunkSize=r;this.pdfNetworkStream=e;this.url=t.url;this.disableAutoFetch=t.disableAutoFetch;this.msgHandler=t.msgHandler;this.currRequestId=0;this.chunksNeededByRequest=Object.create(null);this.requestsByChunk=Object.create(null);this.promisesByRequest=Object.create(null);this.progressiveDataLength=0;this.aborted=!1;this._loadedStreamCapability=(0,a.createPromiseCapability)()}e.prototype={onLoadedStream:function(){return this._loadedStreamCapability.promise},sendRequest:function(e,t){var r=this,i=this.pdfNetworkStream.getRangeReader(e,t);i.isStreamingSupported||(i.onProgress=this.onProgress.bind(this));var n=[],o=0,s=this;new Promise(function(e,t){i.read().then(function r(c){try{if(!c.done){var l=c.value;n.push(l);o+=(0,a.arrayByteLength)(l);i.isStreamingSupported&&s.onProgress({loaded:o});i.read().then(r,t);return}var u=(0,a.arraysToBytes)(n);n=null;e(u)}catch(e){t(e)}},t)}).then(function(t){r.aborted||r.onReceiveData({chunk:t,begin:e})})},requestAllChunks:function(){var e=this.stream.getMissingChunks();this._requestChunks(e);return this._loadedStreamCapability.promise},_requestChunks:function(e){var t,r,i=this.currRequestId++,n=Object.create(null);this.chunksNeededByRequest[i]=n;for(t=0,r=e.length;t<r;t++)this.stream.hasChunk(e[t])||(n[e[t]]=!0);if((0,a.isEmptyObj)(n))return Promise.resolve();var o=(0,a.createPromiseCapability)();this.promisesByRequest[i]=o;var s=[];for(var c in n){if(!((c|=0)in this.requestsByChunk)){this.requestsByChunk[c]=[];s.push(c)}this.requestsByChunk[c].push(i)}if(!s.length)return o.promise;var l=this.groupChunks(s);for(t=0;t<l.length;++t){var u=l[t],h=u.beginChunk*this.chunkSize,f=Math.min(u.endChunk*this.chunkSize,this.length);this.sendRequest(h,f)}return o.promise},getStream:function(){return this.stream},requestRange:function(e,t){t=Math.min(t,this.length);for(var r=this.getBeginChunk(e),a=this.getEndChunk(t),i=[],n=r;n<a;++n)i.push(n);return this._requestChunks(i)},requestRanges:function(e){e=e||[];for(var t=[],r=0;r<e.length;r++)for(var a=this.getBeginChunk(e[r].begin),i=this.getEndChunk(e[r].end),n=a;n<i;++n)t.includes(n)||t.push(n);t.sort(function(e,t){return e-t});return this._requestChunks(t)},groupChunks:function(e){for(var t=[],r=-1,a=-1,i=0;i<e.length;++i){var n=e[i];r<0&&(r=n);if(a>=0&&a+1!==n){t.push({beginChunk:r,endChunk:a+1});r=n}i+1===e.length&&t.push({beginChunk:r,endChunk:n+1});a=n}return t},onProgress:function(e){var t=this.stream.numChunksLoaded*this.chunkSize+e.loaded;this.msgHandler.send("DocProgress",{loaded:t,total:this.length})},onReceiveData:function(e){var t=e.chunk,r=void 0===e.begin,i=r?this.progressiveDataLength:e.begin,n=i+t.byteLength,o=Math.floor(i/this.chunkSize),s=n<this.length?Math.floor(n/this.chunkSize):Math.ceil(n/this.chunkSize);if(r){this.stream.onReceiveProgressiveData(t);this.progressiveDataLength=n}else this.stream.onReceiveData(i,t);this.stream.allChunksLoaded()&&this._loadedStreamCapability.resolve(this.stream);var c,l,u=[];for(t=o;t<s;++t){var h=this.requestsByChunk[t]||[];delete this.requestsByChunk[t];for(c=0;c<h.length;++c){l=h[c];var f=this.chunksNeededByRequest[l];t in f&&delete f[t];(0,a.isEmptyObj)(f)&&u.push(l)}}if(!this.disableAutoFetch&&(0,a.isEmptyObj)(this.requestsByChunk)){var d;if(1===this.stream.numChunksLoaded){var g=this.stream.numChunks-1;this.stream.hasChunk(g)||(d=g)}else d=this.stream.nextEmptyChunk(s);Number.isInteger(d)&&this._requestChunks([d])}for(c=0;c<u.length;++c){l=u[c];var m=this.promisesByRequest[l];delete this.promisesByRequest[l];m.resolve()}this.msgHandler.send("DocProgress",{loaded:this.stream.numChunksLoaded*this.chunkSize,total:this.length})},onError:function(e){this._loadedStreamCapability.reject(e)},getBeginChunk:function(e){return Math.floor(e/this.chunkSize)},getEndChunk:function(e){return Math.floor((e-1)/this.chunkSize)+1},abort:function(){this.aborted=!0;this.pdfNetworkStream&&this.pdfNetworkStream.cancelAllRequests("abort");for(var e in this.promisesByRequest){this.promisesByRequest[e].reject(new Error("Request was aborted"))}}};return e}();t.ChunkedStream=i;t.ChunkedStreamManager=n},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.PDFDocument=t.Page=void 0;var a=function(){return function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var r=[],a=!0,i=!1,n=void 0;try{for(var o,s=e[Symbol.iterator]();!(a=(o=s.next()).done);a=!0){r.push(o.value);if(t&&r.length===t)break}}catch(e){i=!0;n=e}finally{try{!a&&s.return&&s.return()}finally{if(i)throw n}}return r}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),i=r(2),n=r(137),o=r(138),s=r(140),c=r(152),l=r(150),u=r(139),h=r(153),f=r(154),d=r(168),g=function(){var e=[0,0,612,792];function t(e,t){return"display"===t&&e.viewable||"print"===t&&e.printable}function r(e){var t=e.pdfManager,r=e.xref,a=e.pageIndex,i=e.pageDict,n=e.ref,o=e.fontCache,s=e.builtInCMapCache,c=e.pdfFunctionFactory;this.pdfManager=t;this.pageIndex=a;this.pageDict=i;this.xref=r;this.ref=n;this.fontCache=o;this.builtInCMapCache=s;this.pdfFunctionFactory=c;this.evaluatorOptions=t.evaluatorOptions;this.resourcesPromise=null;var l="p"+this.pageIndex+"_",u={obj:0};this.idFactory={createObjId:function(){return l+ ++u.obj}}}r.prototype={_getInheritableProperty:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=(0,i.getInheritableProperty)({dict:this.pageDict,key:e,getArray:t,stopWhenFound:!1});return Array.isArray(r)?1!==r.length&&(0,o.isDict)(r[0])?o.Dict.merge(this.xref,r):r[0]:r},get content(){return this.pageDict.get("Contents")},get resources(){return(0,i.shadow)(this,"resources",this._getInheritableProperty("Resources")||o.Dict.empty)},get mediaBox(){var t=this._getInheritableProperty("MediaBox",!0);return Array.isArray(t)&&4===t.length?(0,i.shadow)(this,"mediaBox",t):(0,i.shadow)(this,"mediaBox",e)},get cropBox(){var e=this._getInheritableProperty("CropBox",!0);return Array.isArray(e)&&4===e.length?(0,i.shadow)(this,"cropBox",e):(0,i.shadow)(this,"cropBox",this.mediaBox)},get userUnit(){var e=this.pageDict.get("UserUnit");(!(0,i.isNum)(e)||e<=0)&&(e=1);return(0,i.shadow)(this,"userUnit",e)},get view(){var e=this.mediaBox,t=this.cropBox;if(e===t)return(0,i.shadow)(this,"view",e);var r=i.Util.intersect(t,e);return(0,i.shadow)(this,"view",r||e)},get rotate(){var e=this._getInheritableProperty("Rotate")||0;e%90!=0?e=0:e>=360?e%=360:e<0&&(e=(e%360+360)%360);return(0,i.shadow)(this,"rotate",e)},getContentStream:function(){var e,t=this.content;if(Array.isArray(t)){var r,a=this.xref,i=t.length,n=[];for(r=0;r<i;++r)n.push(a.fetchIfRef(t[r]));e=new s.StreamsSequenceStream(n)}else e=(0,o.isStream)(t)?t:new s.NullStream;return e},loadResources:function(e){var t=this;this.resourcesPromise||(this.resourcesPromise=this.pdfManager.ensure(this,"resources"));return this.resourcesPromise.then(function(){return new n.ObjectLoader(t.resources,e,t.xref).load()})},getOperatorList:function(e){var r=this,n=e.handler,o=e.task,s=e.intent,c=e.renderInteractiveForms,l=this.pdfManager.ensure(this,"getContentStream"),u=this.loadResources(["ExtGState","ColorSpace","Pattern","Shading","XObject","Font"]),d=new f.PartialEvaluator({pdfManager:this.pdfManager,xref:this.xref,handler:n,pageIndex:this.pageIndex,idFactory:this.idFactory,fontCache:this.fontCache,builtInCMapCache:this.builtInCMapCache,options:this.evaluatorOptions,pdfFunctionFactory:this.pdfFunctionFactory}),g=Promise.all([l,u]).then(function(e){var t=a(e,1)[0],i=new h.OperatorList(s,n,r.pageIndex);n.send("StartRenderPage",{transparency:d.hasBlendModes(r.resources),pageIndex:r.pageIndex,intent:s});return d.getOperatorList({stream:t,task:o,resources:r.resources,operatorList:i}).then(function(){return i})});return Promise.all([g,this._parsedAnnotations]).then(function(e){var r=a(e,2),n=r[0],l=r[1];if(0===l.length){n.flush(!0);return n}var u,h,f=[];for(u=0,h=l.length;u<h;u++)t(l[u],s)&&f.push(l[u].getOperatorList(d,o,c));return Promise.all(f).then(function(e){n.addOp(i.OPS.beginAnnotations,[]);for(u=0,h=e.length;u<h;u++)n.addOpList(e[u]);n.addOp(i.OPS.endAnnotations,[]);n.flush(!0);return n})})},extractTextContent:function(e){var t=this,r=e.handler,i=e.task,n=e.normalizeWhitespace,o=e.sink,s=e.combineTextItems,c=this.pdfManager.ensure(this,"getContentStream"),l=this.loadResources(["ExtGState","XObject","Font"]);return Promise.all([c,l]).then(function(e){var c=a(e,1)[0];return new f.PartialEvaluator({pdfManager:t.pdfManager,xref:t.xref,handler:r,pageIndex:t.pageIndex,idFactory:t.idFactory,fontCache:t.fontCache,builtInCMapCache:t.builtInCMapCache,options:t.evaluatorOptions,pdfFunctionFactory:t.pdfFunctionFactory}).getTextContent({stream:c,task:i,resources:t.resources,normalizeWhitespace:n,combineTextItems:s,sink:o})})},getAnnotationsData:function(e){return this._parsedAnnotations.then(function(r){for(var a=[],i=0,n=r.length;i<n;i++)e&&!t(r[i],e)||a.push(r[i].data);return a})},get annotations(){return(0,i.shadow)(this,"annotations",this._getInheritableProperty("Annots")||[])},get _parsedAnnotations(){var e=this,t=this.pdfManager.ensure(this,"annotations").then(function(){for(var t=e.annotations,r=[],a=0,n=t.length;a<n;a++)r.push(c.AnnotationFactory.create(e.xref,t[a],e.pdfManager,e.idFactory));return Promise.all(r).then(function(e){return e.filter(function(e){return!!e})},function(e){(0,i.warn)('_parsedAnnotations: "'+e+'".');return[]})});return(0,i.shadow)(this,"_parsedAnnotations",t)}};return r}(),m=function(){function e(e,t){var r;if((0,o.isStream)(t))r=t;else{if(!(0,i.isArrayBuffer)(t))throw new Error("PDFDocument: Unknown argument type");r=new s.Stream(t)}if(r.length<=0)throw new Error("PDFDocument: stream must have data");this.pdfManager=e;this.stream=r;this.xref=new n.XRef(r,e);var a=e.evaluatorOptions;this.pdfFunctionFactory=new d.PDFFunctionFactory({xref:this.xref,isEvalSupported:a.isEvalSupported});this._pagePromises=[]}function t(e,t,r,a){var i=e.pos,n=e.end,o=[];i+r>n&&(r=n-i);for(var s=0;s<r;++s)o.push(String.fromCharCode(e.getByte()));var c=o.join("");e.pos=i;var l=a?c.lastIndexOf(t):c.indexOf(t);if(-1===l)return!1;e.pos+=l;return!0}var r={Title:i.isString,Author:i.isString,Subject:i.isString,Keywords:i.isString,Creator:i.isString,Producer:i.isString,CreationDate:i.isString,ModDate:i.isString,Trapped:o.isName};e.prototype={parse:function(e){this.setup(e);var t=this.catalog.catDict.get("Version");(0,o.isName)(t)&&(this.pdfFormatVersion=t.name);try{this.acroForm=this.catalog.catDict.get("AcroForm");if(this.acroForm){this.xfa=this.acroForm.get("XFA");var r=this.acroForm.get("Fields");r&&Array.isArray(r)&&0!==r.length||this.xfa||(this.acroForm=null)}}catch(e){if(e instanceof i.MissingDataException)throw e;(0,i.info)("Something wrong with AcroForm entry");this.acroForm=null}},get linearization(){var e=null;try{e=u.Linearization.create(this.stream)}catch(e){if(e instanceof i.MissingDataException)throw e;(0,i.info)(e)}return(0,i.shadow)(this,"linearization",e)},get startXRef(){var e=this.stream,r=0;if(this.linearization){e.reset();t(e,"endobj",1024)&&(r=e.pos+6)}else{for(var a=!1,n=e.end;!a&&n>0;){(n-=1024-"startxref".length)<0&&(n=0);e.pos=n;a=t(e,"startxref",1024,!0)}if(a){e.skip(9);var o;do{o=e.getByte()}while((0,i.isSpace)(o));for(var s="";o>=32&&o<=57;){s+=String.fromCharCode(o);o=e.getByte()}r=parseInt(s,10);isNaN(r)&&(r=0)}}return(0,i.shadow)(this,"startXRef",r)},checkHeader:function(){var e=this.stream;e.reset();if(t(e,"%PDF-",1024)){e.moveStart();for(var r,a="";(r=e.getByte())>32&&!(a.length>=12);)a+=String.fromCharCode(r);this.pdfFormatVersion||(this.pdfFormatVersion=a.substring(5))}else;},parseStartXRef:function(){var e=this.startXRef;this.xref.setStartXRef(e)},setup:function(e){this.xref.parse(e);this.catalog=new n.Catalog(this.pdfManager,this.xref)},get numPages(){var e=this.linearization,t=e?e.numPages:this.catalog.numPages;return(0,i.shadow)(this,"numPages",t)},get documentInfo(){var e={PDFFormatVersion:this.pdfFormatVersion,IsLinearized:!!this.linearization,IsAcroFormPresent:!!this.acroForm,IsXFAPresent:!!this.xfa},t=void 0;try{t=this.xref.trailer.get("Info")}catch(e){if(e instanceof i.MissingDataException)throw e;(0,i.info)("The document information dictionary is invalid.")}if((0,o.isDict)(t))for(var a in r)if(t.has(a)){var n=t.get(a);r[a](n)?e[a]="string"!=typeof n?n:(0,i.stringToPDFString)(n):(0,i.info)('Bad value in document info for "'+a+'"')}return(0,i.shadow)(this,"documentInfo",e)},get fingerprint(){var e,t="",r=this.xref.trailer.get("ID");if(Array.isArray(r)&&r[0]&&(0,i.isString)(r[0])&&"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"!==r[0])e=(0,i.stringToBytes)(r[0]);else{this.stream.ensureRange&&this.stream.ensureRange(0,Math.min(1024,this.stream.end));e=(0,l.calculateMD5)(this.stream.bytes.subarray(0,1024),0,1024)}for(var a=0,n=e.length;a<n;a++){var o=e[a].toString(16);t+=1===o.length?"0"+o:o}return(0,i.shadow)(this,"fingerprint",t)},_getLinearizationPage:function(e){var t=this.catalog,r=this.linearization;(0,i.assert)(r&&r.pageFirst===e);var a=new o.Ref(r.objectNumberFirst,0);return this.xref.fetchAsync(a).then(function(e){if((0,o.isDict)(e,"Page")||(0,o.isDict)(e)&&!e.has("Type")&&e.has("Contents")){a&&!t.pageKidsCountCache.has(a)&&t.pageKidsCountCache.put(a,1);return[e,a]}throw new i.FormatError("The Linearization dictionary doesn't point to a valid Page dictionary.")}).catch(function(r){(0,i.info)(r);return t.getPageDict(e)})},getPage:function(e){var t=this;if(void 0!==this._pagePromises[e])return this._pagePromises[e];var r=this.catalog,i=this.linearization,n=i&&i.pageFirst===e?this._getLinearizationPage(e):r.getPageDict(e);return this._pagePromises[e]=n.then(function(i){var n=a(i,2),o=n[0],s=n[1];return new g({pdfManager:t.pdfManager,xref:t.xref,pageIndex:e,pageDict:o,ref:s,fontCache:r.fontCache,builtInCMapCache:r.builtInCMapCache,pdfFunctionFactory:t.pdfFunctionFactory})})},cleanup:function(){return this.catalog.cleanup()}};return e}();t.Page=g;t.PDFDocument=m},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.FileSpec=t.XRef=t.ObjectLoader=t.Catalog=void 0;var a,i=r(131),n=(a=i)&&a.__esModule?a:{default:a},o=function(){return function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var r=[],a=!0,i=!1,n=void 0;try{for(var o,s=e[Symbol.iterator]();!(a=(o=s.next()).done);a=!0){r.push(o.value);if(t&&r.length===t)break}}catch(e){i=!0;n=e}finally{try{!a&&s.return&&s.return()}finally{if(i)throw n}}return r}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},c=function(){function e(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1;a.configurable=!0;"value"in a&&(a.writable=!0);Object.defineProperty(e,a.key,a)}}return function(t,r,a){r&&e(t.prototype,r);a&&e(t,a);return t}}(),l=r(2),u=r(138),h=r(139),f=r(135),d=r(150),g=r(151);function m(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function p(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}});t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function v(e){return function(){var t=e.apply(this,arguments);return new Promise(function(e,r){return function a(i,n){try{var o=t[i](n),s=o.value}catch(e){r(e);return}if(!o.done)return Promise.resolve(s).then(function(e){a("next",e)},function(e){a("throw",e)});e(s)}("next")})}}function b(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function y(e){return(0,u.isDict)(e)?e.get("D"):e}var w=function(){function e(t,r){b(this,e);this.pdfManager=t;this.xref=r;this.catDict=r.getCatalogObj();if(!(0,u.isDict)(this.catDict))throw new l.FormatError("Catalog object is not a dictionary.");this.fontCache=new u.RefSetCache;this.builtInCMapCache=new Map;this.pageKidsCountCache=new u.RefSetCache}c(e,[{key:"_readDocumentOutline",value:function(){var t=this.catDict.get("Outlines");if(!(0,u.isDict)(t))return null;t=t.getRaw("First");if(!(0,u.isRef)(t))return null;var r={items:[]},a=[{obj:t,parent:r}],i=new u.RefSet;i.put(t);for(var n=this.xref,o=new Uint8ClampedArray(3);a.length>0;){var s=a.shift(),c=n.fetchIfRef(s.obj);if(null!==c){if(!c.has("Title"))throw new l.FormatError("Invalid outline item encountered.");var h={url:null,dest:null};e.parseDestDictionary({destDict:c,resultObj:h,docBaseUrl:this.pdfManager.docBaseUrl});var f=c.get("Title"),d=c.get("F")||0,m=c.getArray("C"),p=o;!Array.isArray(m)||3!==m.length||0===m[0]&&0===m[1]&&0===m[2]||(p=g.ColorSpace.singletons.rgb.getRgb(m,0));var v={dest:h.dest,url:h.url,unsafeUrl:h.unsafeUrl,newWindow:h.newWindow,title:(0,l.stringToPDFString)(f),color:p,count:c.get("Count"),bold:!!(2&d),italic:!!(1&d),items:[]};s.parent.items.push(v);t=c.getRaw("First");if((0,u.isRef)(t)&&!i.has(t)){a.push({obj:t,parent:v});i.put(t)}t=c.getRaw("Next");if((0,u.isRef)(t)&&!i.has(t)){a.push({obj:t,parent:s.parent});i.put(t)}}}return r.items.length>0?r.items:null}},{key:"_readPermissions",value:function(){var e=this.xref.trailer.get("Encrypt");if(!(0,u.isDict)(e))return null;var t=e.get("P");if(!(0,l.isNum)(t))return null;t+=Math.pow(2,32);var r=[];for(var a in l.PermissionFlag){var i=l.PermissionFlag[a];t&i&&r.push(i)}return r}},{key:"getDestination",value:function(e){var t=this._readDests();return t instanceof C||t instanceof u.Dict?y(t.get(e)||null):null}},{key:"_readDests",value:function(){var e=this.catDict.get("Names");return e&&e.has("Dests")?new C(e.getRaw("Dests"),this.xref):this.catDict.has("Dests")?this.catDict.get("Dests"):void 0}},{key:"_readPageLabels",value:function(){var e=this.catDict.getRaw("PageLabels");if(!e)return null;for(var t=new Array(this.numPages),r=null,a="",i=new x(e,this.xref).getAll(),n="",o=1,s=0,c=this.numPages;s<c;s++){if(s in i){var h=i[s];if(!(0,u.isDict)(h))throw new l.FormatError("PageLabel is not a dictionary.");if(h.has("Type")&&!(0,u.isName)(h.get("Type"),"PageLabel"))throw new l.FormatError("Invalid type in PageLabel dictionary.");if(h.has("S")){var f=h.get("S");if(!(0,u.isName)(f))throw new l.FormatError("Invalid style in PageLabel dictionary.");r=f.name}else r=null;if(h.has("P")){var d=h.get("P");if(!(0,l.isString)(d))throw new l.FormatError("Invalid prefix in PageLabel dictionary.");a=(0,l.stringToPDFString)(d)}else a="";if(h.has("St")){var g=h.get("St");if(!(Number.isInteger(g)&&g>=1))throw new l.FormatError("Invalid start in PageLabel dictionary.");o=g}else o=1}switch(r){case"D":n=o;break;case"R":case"r":n=(0,l.toRomanNumerals)(o,"r"===r);break;case"A":case"a":for(var m="a"===r?97:65,p=o-1,v=String.fromCharCode(m+p%26),b=[],y=0,w=p/26|0;y<=w;y++)b.push(v);n=b.join("");break;default:if(r)throw new l.FormatError('Invalid style "'+r+'" in PageLabel dictionary.');n=""}t[s]=a+n;o++}return t}},{key:"cleanup",value:function(){var e=this;this.pageKidsCountCache.clear();var t=[];this.fontCache.forEach(function(e){t.push(e)});return Promise.all(t).then(function(t){for(var r=0,a=t.length;r<a;r++){delete t[r].dict.translated}e.fontCache.clear();e.builtInCMapCache.clear()})}},{key:"getPageDict",value:function(e){var t=(0,l.createPromiseCapability)(),r=[this.catDict.getRaw("Pages")],a=this.xref,i=this.pageKidsCountCache,n=void 0,o=0;!function c(){for(var h=function(){var s=r.pop();if((0,u.isRef)(s)){if((n=i.get(s))>0&&o+n<e){o+=n;return"continue"}a.fetchAsync(s).then(function(a){if((0,u.isDict)(a,"Page")||(0,u.isDict)(a)&&!a.has("Kids"))if(e===o){s&&!i.has(s)&&i.put(s,1);t.resolve([a,s])}else{o++;c()}else{r.push(a);c()}},t.reject);return{v:void 0}}if(!(0,u.isDict)(s)){t.reject(new l.FormatError("Page dictionary kid reference points to wrong type of object."));return{v:void 0}}n=s.get("Count");if(Number.isInteger(n)&&n>=0){var h=s.objId;h&&!i.has(h)&&i.put(h,n);if(o+n<=e){o+=n;return"continue"}}var f=s.get("Kids");if(!Array.isArray(f)){if((0,u.isName)(s.get("Type"),"Page")||!s.has("Type")&&s.has("Contents")){if(o===e){t.resolve([s,null]);return{v:void 0}}o++;return"continue"}t.reject(new l.FormatError("Page dictionary kids object is not an array."));return{v:void 0}}for(var d=f.length-1;d>=0;d--)r.push(f[d])};r.length;){var f=h();switch(f){case"continue":continue;default:if("object"===(void 0===f?"undefined":s(f)))return f.v}}t.reject(new Error("Page index "+e+" not found."))}();return t.promise}},{key:"getPageIndex",value:function(e){var t=this.xref;var r=0;return function a(i){return function(r){var a=0,i=void 0;return t.fetchAsync(r).then(function(t){if((0,u.isRefsEqual)(r,e)&&!(0,u.isDict)(t,"Page")&&(!(0,u.isDict)(t)||t.has("Type")||!t.has("Contents")))throw new l.FormatError("The reference does not point to a /Page dictionary.");if(!t)return null;if(!(0,u.isDict)(t))throw new l.FormatError("Node must be a dictionary.");i=t.getRaw("Parent");return t.getAsync("Parent")}).then(function(e){if(!e)return null;if(!(0,u.isDict)(e))throw new l.FormatError("Parent must be a dictionary.");return e.getAsync("Kids")}).then(function(e){if(!e)return null;for(var n=[],o=!1,s=0,c=e.length;s<c;s++){var h=e[s];if(!(0,u.isRef)(h))throw new l.FormatError("Kid must be a reference.");if((0,u.isRefsEqual)(h,r)){o=!0;break}n.push(t.fetchAsync(h).then(function(e){if(!(0,u.isDict)(e))throw new l.FormatError("Kid node must be a dictionary.");e.has("Count")?a+=e.get("Count"):a++}))}if(!o)throw new l.FormatError("Kid reference not found in parent's kids.");return Promise.all(n).then(function(){return[a,i]})})}(i).then(function(e){if(!e)return r;var t=o(e,2),i=t[0],n=t[1];r+=i;return a(n)})}(e)}},{key:"metadata",get:function(){var e=this.catDict.getRaw("Metadata");if(!(0,u.isRef)(e))return(0,l.shadow)(this,"metadata",null);var t=!(this.xref.encrypt&&this.xref.encrypt.encryptMetadata),r=this.xref.fetch(e,t),a=void 0;if(r&&(0,u.isDict)(r.dict)){var i=r.dict.get("Type"),n=r.dict.get("Subtype");if((0,u.isName)(i,"Metadata")&&(0,u.isName)(n,"XML"))try{a=(0,l.stringToUTF8String)((0,l.bytesToString)(r.getBytes()))}catch(e){if(e instanceof l.MissingDataException)throw e;(0,l.info)("Skipping invalid metadata.")}}return(0,l.shadow)(this,"metadata",a)}},{key:"toplevelPagesDict",get:function(){var e=this.catDict.get("Pages");if(!(0,u.isDict)(e))throw new l.FormatError("Invalid top-level pages dictionary.");return(0,l.shadow)(this,"toplevelPagesDict",e)}},{key:"documentOutline",get:function(){var e=null;try{e=this._readDocumentOutline()}catch(e){if(e instanceof l.MissingDataException)throw e;(0,l.warn)("Unable to read document outline.")}return(0,l.shadow)(this,"documentOutline",e)}},{key:"permissions",get:function(){var e=null;try{e=this._readPermissions()}catch(e){if(e instanceof l.MissingDataException)throw e;(0,l.warn)("Unable to read permissions.")}return(0,l.shadow)(this,"permissions",e)}},{key:"numPages",get:function(){var e=this.toplevelPagesDict.get("Count");if(!Number.isInteger(e))throw new l.FormatError("Page count in top-level pages dictionary is not an integer.");return(0,l.shadow)(this,"numPages",e)}},{key:"destinations",get:function(){var e=this._readDests(),t=Object.create(null);if(e instanceof C){var r=e.getAll();for(var a in r)t[a]=y(r[a])}else e instanceof u.Dict&&e.forEach(function(e,r){r&&(t[e]=y(r))});return(0,l.shadow)(this,"destinations",t)}},{key:"pageLabels",get:function(){var e=null;try{e=this._readPageLabels()}catch(e){if(e instanceof l.MissingDataException)throw e;(0,l.warn)("Unable to read page labels.")}return(0,l.shadow)(this,"pageLabels",e)}},{key:"pageMode",get:function(){var e=this.catDict.get("PageMode"),t="UseNone";if((0,u.isName)(e))switch(e.name){case"UseNone":case"UseOutlines":case"UseThumbs":case"FullScreen":case"UseOC":case"UseAttachments":t=e.name}return(0,l.shadow)(this,"pageMode",t)}},{key:"attachments",get:function(){var e=this.catDict.get("Names"),t=null;if(e&&e.has("EmbeddedFiles")){var r=new C(e.getRaw("EmbeddedFiles"),this.xref).getAll();for(var a in r){var i=new _(r[a],this.xref);t||(t=Object.create(null));t[(0,l.stringToPDFString)(a)]=i.serializable}}return(0,l.shadow)(this,"attachments",t)}},{key:"javaScript",get:function(){var e=this.catDict.get("Names"),t=null;function r(e){var r=e.get("S");if((0,u.isName)(r,"JavaScript")){var a=e.get("JS");if((0,u.isStream)(a))a=(0,l.bytesToString)(a.getBytes());else if(!(0,l.isString)(a))return;t||(t=[]);t.push((0,l.stringToPDFString)(a))}}if(e&&e.has("JavaScript")){var a=new C(e.getRaw("JavaScript"),this.xref).getAll();for(var i in a){var n=a[i];(0,u.isDict)(n)&&r(n)}}var o=this.catDict.get("OpenAction");if((0,u.isDict)(o,"Action")){var s=o.get("S");if((0,u.isName)(s,"Named")){var c=o.get("N");if((0,u.isName)(c,"Print")){t||(t=[]);t.push("print({});")}}else r(o)}return(0,l.shadow)(this,"javaScript",t)}}],[{key:"parseDestDictionary",value:function(e){var t=e.destDict;if((0,u.isDict)(t)){var r=e.resultObj;if("object"===(void 0===r?"undefined":s(r))){var a=e.docBaseUrl||null,i=t.get("A"),n=void 0,o=void 0;!(0,u.isDict)(i)&&t.has("Dest")&&(i=t.get("Dest"));if((0,u.isDict)(i)){var c=i.get("S");if(!(0,u.isName)(c)){(0,l.warn)("parseDestDictionary: Invalid type in Action dictionary.");return}var h=c.name;switch(h){case"URI":n=i.get("URI");(0,u.isName)(n)?n="/"+n.name:(0,l.isString)(n)&&(n=function(e){return 0===e.indexOf("www.")?"http://"+e:e}(n));break;case"GoTo":o=i.get("D");break;case"Launch":case"GoToR":var f=i.get("F");(0,u.isDict)(f)?n=f.get("F")||null:(0,l.isString)(f)&&(n=f);var d=i.get("D");if(d){(0,u.isName)(d)&&(d=d.name);if((0,l.isString)(n)){var g=n.split("#")[0];(0,l.isString)(d)?n=g+"#"+d:Array.isArray(d)&&(n=g+"#"+JSON.stringify(d))}}var m=i.get("NewWindow");(0,l.isBool)(m)&&(r.newWindow=m);break;case"Named":var p=i.get("N");(0,u.isName)(p)&&(r.action=p.name);break;case"JavaScript":var v=i.get("JS"),b=void 0;(0,u.isStream)(v)?b=(0,l.bytesToString)(v.getBytes()):(0,l.isString)(v)&&(b=v);if(b){var y=new RegExp("^\\s*("+["app.launchURL","window.open"].join("|").split(".").join("\\.")+")\\((?:'|\")([^'\"]*)(?:'|\")(?:,\\s*(\\w+)\\)|\\))","i").exec((0,l.stringToPDFString)(b));if(y&&y[2]){n=y[2];"true"===y[3]&&"app.launchURL"===y[1]&&(r.newWindow=!0);break}}default:(0,l.warn)('parseDestDictionary: unsupported action type "'+h+'".')}}else t.has("Dest")&&(o=t.get("Dest"));if((0,l.isString)(n)){n=function(e){try{return(0,l.stringToUTF8String)(e)}catch(t){return e}}(n);var w=(0,l.createValidAbsoluteUrl)(n,a);w&&(r.url=w.href);r.unsafeUrl=n}if(o){(0,u.isName)(o)&&(o=o.name);((0,l.isString)(o)||Array.isArray(o))&&(r.dest=o)}}else(0,l.warn)("parseDestDictionary: `resultObj` must be an object.")}else(0,l.warn)("parseDestDictionary: `destDict` must be a dictionary.")}}]);return e}(),k=function(){function e(e,t){this.stream=e;this.pdfManager=t;this.entries=[];this.xrefstms=Object.create(null);this.cache=[];this.stats={streamTypes:[],fontTypes:[]}}e.prototype={setStartXRef:function(e){this.startXRefQueue=[e]},parse:function(e){var t;if(e){(0,l.warn)("Indexing all PDF objects");t=this.indexObjects()}else t=this.readXRef();t.assignXref(this);this.trailer=t;var r=void 0;try{r=t.get("Encrypt")}catch(e){if(e instanceof l.MissingDataException)throw e;(0,l.warn)('XRef.parse - Invalid "Encrypt" reference: "'+e+'".')}if((0,u.isDict)(r)){var a=t.get("ID"),i=a&&a.length?a[0]:"";r.suppressEncryption=!0;this.encrypt=new d.CipherTransformFactory(r,i,this.pdfManager.password)}var n=void 0;try{n=t.get("Root")}catch(e){if(e instanceof l.MissingDataException)throw e;(0,l.warn)('XRef.parse - Invalid "Root" reference: "'+e+'".')}if(!(0,u.isDict)(n)||!n.has("Pages")){if(!e)throw new l.XRefParseException;throw new l.FormatError("Invalid root reference")}this.root=n},processXRefTable:function(e){"tableState"in this||(this.tableState={entryNum:0,streamPos:e.lexer.stream.pos,parserBuf1:e.buf1,parserBuf2:e.buf2});var t=this.readXRefTable(e);if(!(0,u.isCmd)(t,"trailer"))throw new l.FormatError("Invalid XRef table: could not find trailer dictionary");var r=e.getObj();!(0,u.isDict)(r)&&r.dict&&(r=r.dict);if(!(0,u.isDict)(r))throw new l.FormatError("Invalid XRef table: could not parse trailer dictionary");delete this.tableState;return r},readXRefTable:function(e){var t,r=e.lexer.stream,a=this.tableState;r.pos=a.streamPos;e.buf1=a.parserBuf1;e.buf2=a.parserBuf2;for(;;){if(!("firstEntryNum"in a&&"entryCount"in a)){if((0,u.isCmd)(t=e.getObj(),"trailer"))break;a.firstEntryNum=t;a.entryCount=e.getObj()}var i=a.firstEntryNum,n=a.entryCount;if(!Number.isInteger(i)||!Number.isInteger(n))throw new l.FormatError("Invalid XRef table: wrong types in subsection header");for(var o=a.entryNum;o<n;o++){a.streamPos=r.pos;a.entryNum=o;a.parserBuf1=e.buf1;a.parserBuf2=e.buf2;var s={};s.offset=e.getObj();s.gen=e.getObj();var c=e.getObj();(0,u.isCmd)(c,"f")?s.free=!0:(0,u.isCmd)(c,"n")&&(s.uncompressed=!0);if(!Number.isInteger(s.offset)||!Number.isInteger(s.gen)||!s.free&&!s.uncompressed)throw new l.FormatError("Invalid entry in XRef subsection: "+i+", "+n);0===o&&s.free&&1===i&&(i=0);this.entries[o+i]||(this.entries[o+i]=s)}a.entryNum=0;a.streamPos=r.pos;a.parserBuf1=e.buf1;a.parserBuf2=e.buf2;delete a.firstEntryNum;delete a.entryCount}if(this.entries[0]&&!this.entries[0].free)throw new l.FormatError("Invalid XRef table: unexpected first object");return t},processXRefStream:function(e){if(!("streamState"in this)){var t=e.dict,r=t.get("W"),a=t.get("Index");a||(a=[0,t.get("Size")]);this.streamState={entryRanges:a,byteWidths:r,entryNum:0,streamPos:e.pos}}this.readXRefStream(e);delete this.streamState;return e.dict},readXRefStream:function(e){var t,r,a=this.streamState;e.pos=a.streamPos;for(var i=a.byteWidths,n=i[0],o=i[1],s=i[2],c=a.entryRanges;c.length>0;){var u=c[0],h=c[1];if(!Number.isInteger(u)||!Number.isInteger(h))throw new l.FormatError("Invalid XRef range fields: "+u+", "+h);if(!Number.isInteger(n)||!Number.isInteger(o)||!Number.isInteger(s))throw new l.FormatError("Invalid XRef entry fields length: "+u+", "+h);for(t=a.entryNum;t<h;++t){a.entryNum=t;a.streamPos=e.pos;var f=0,d=0,g=0;for(r=0;r<n;++r)f=f<<8|e.getByte();0===n&&(f=1);for(r=0;r<o;++r)d=d<<8|e.getByte();for(r=0;r<s;++r)g=g<<8|e.getByte();var m={};m.offset=d;m.gen=g;switch(f){case 0:m.free=!0;break;case 1:m.uncompressed=!0;break;case 2:break;default:throw new l.FormatError("Invalid XRef entry type: "+f)}this.entries[u+t]||(this.entries[u+t]=m)}a.entryNum=0;a.streamPos=e.pos;c.splice(0,2)}},indexObjects:function(){var e=10,t=13,r=60;function a(a,i){for(var n="",o=a[i];o!==e&&o!==t&&o!==r&&!(++i>=a.length);){n+=String.fromCharCode(o);o=a[i]}return n}function i(e,t,r){for(var a=r.length,i=e.length,n=0;t<i;){for(var o=0;o<a&&e[t+o]===r[o];)++o;if(o>=a)break;t++;n++}return n}var n=/^(\d+)\s+(\d+)\s+obj\b/,o=/\bendobj[\b\s]$/,s=/\s+(\d+\s+\d+\s+obj[\b\s])$/,c=new Uint8Array([116,114,97,105,108,101,114]),f=new Uint8Array([115,116,97,114,116,120,114,101,102]),d=new Uint8Array([111,98,106]),g=new Uint8Array([47,88,82,101,102]);this.entries.length=0;var m=this.stream;m.pos=0;for(var p,v,b=m.getBytes(),y=m.start,w=b.length,k=[],S=[];y<w;){var C=b[y];if(9!==C&&C!==e&&C!==t&&32!==C)if(37!==C){var x,_=a(b,y);if(0!==_.indexOf("xref")||4!==_.length&&!/\s/.test(_[4]))if(x=n.exec(_)){void 0===this.entries[x[1]]&&(this.entries[x[1]]={offset:y-m.start,gen:0|x[2],uncompressed:!0});for(var A=void 0,P=y+_.length;P<b.length;){var I=P+i(b,P,d)+4;A=I-y;var O=Math.max(I-25,P),T=(0,l.bytesToString)(b.subarray(O,I));if(o.test(T))break;var E=s.exec(T);if(E&&E[1]){(0,l.warn)('indexObjects: Found new "obj" inside of another "obj", caused by missing "endobj" -- trying to recover.');A-=E[1].length;break}P=I}var F=b.subarray(y,y+A),R=i(F,0,g);if(R<A&&F[R+5]<64){S.push(y-m.start);this.xrefstms[y-m.start]=1}y+=A}else if(0!==_.indexOf("trailer")||7!==_.length&&!/\s/.test(_[7]))y+=_.length+1;else{k.push(y);y+=i(b,y,f)}else{y+=i(b,y,c);k.push(y);y+=i(b,y,f)}}else do{if(++y>=w)break;C=b[y]}while(C!==e&&C!==t);else++y}for(p=0,v=S.length;p<v;++p){this.startXRefQueue.push(S[p]);this.readXRef(!0)}var B=void 0;for(p=0,v=k.length;p<v;++p){m.pos=k[p];var D=new h.Parser(new h.Lexer(m),!0,this,!0),M=D.getObj();if((0,u.isCmd)(M,"trailer")){var L=D.getObj();if((0,u.isDict)(L)){var N=void 0;try{N=L.get("Root")}catch(e){if(e instanceof l.MissingDataException)throw e;continue}if((0,u.isDict)(N)&&N.has("Pages")){if(L.has("ID"))return L;B=L}}}}if(B)return B;throw new l.InvalidPDFException("Invalid PDF structure")},readXRef:function(e){var t=this.stream,r=Object.create(null);try{for(;this.startXRefQueue.length;){var a=this.startXRefQueue[0];if(r[a]){(0,l.warn)("readXRef - skipping XRef table since it was already parsed.");this.startXRefQueue.shift()}else{r[a]=!0;t.pos=a+t.start;var i,n=new h.Parser(new h.Lexer(t),!0,this),o=n.getObj();if((0,u.isCmd)(o,"xref")){i=this.processXRefTable(n);this.topDict||(this.topDict=i);o=i.get("XRefStm");if(Number.isInteger(o)){var s=o;if(!(s in this.xrefstms)){this.xrefstms[s]=1;this.startXRefQueue.push(s)}}}else{if(!Number.isInteger(o))throw new l.FormatError("Invalid XRef stream header");if(!Number.isInteger(n.getObj())||!(0,u.isCmd)(n.getObj(),"obj")||!(0,u.isStream)(o=n.getObj()))throw new l.FormatError("Invalid XRef stream");i=this.processXRefStream(o);this.topDict||(this.topDict=i);if(!i)throw new l.FormatError("Failed to read XRef stream")}o=i.get("Prev");Number.isInteger(o)?this.startXRefQueue.push(o):(0,u.isRef)(o)&&this.startXRefQueue.push(o.num);this.startXRefQueue.shift()}}return this.topDict}catch(e){if(e instanceof l.MissingDataException)throw e;(0,l.info)("(while reading XRef): "+e)}if(!e)throw new l.XRefParseException},getEntry:function(e){var t=this.entries[e];return t&&!t.free&&t.offset?t:null},fetchIfRef:function(e,t){return(0,u.isRef)(e)?this.fetch(e,t):e},fetch:function(e,t){if(!(0,u.isRef)(e))throw new Error("ref object is not a reference");var r=e.num;if(r in this.cache){var a=this.cache[r];a instanceof u.Dict&&!a.objId&&(a.objId=e.toString());return a}var i=this.getEntry(r);if(null===i)return this.cache[r]=null;i=i.uncompressed?this.fetchUncompressed(e,i,t):this.fetchCompressed(i,t);(0,u.isDict)(i)?i.objId=e.toString():(0,u.isStream)(i)&&(i.dict.objId=e.toString());return i},fetchUncompressed:function(e,t,r){var a=e.gen,i=e.num;if(t.gen!==a)throw new l.FormatError("inconsistent generation in XRef");var n=this.stream.makeSubStream(t.offset+this.stream.start),o=new h.Parser(new h.Lexer(n),!0,this),s=o.getObj(),c=o.getObj(),f=o.getObj();Number.isInteger(s)||(s=parseInt(s,10));Number.isInteger(c)||(c=parseInt(c,10));if(s!==i||c!==a||!(0,u.isCmd)(f))throw new l.FormatError("bad XRef entry");if("obj"!==f.cmd){if(0===f.cmd.indexOf("obj")){i=parseInt(f.cmd.substring(3),10);if(!Number.isNaN(i))return i}throw new l.FormatError("bad XRef entry")}t=this.encrypt&&!r?o.getObj(this.encrypt.createCipherTransform(i,a)):o.getObj();(0,u.isStream)(t)||(this.cache[i]=t);return t},fetchCompressed:function(e,t){var r=e.offset,a=this.fetch(new u.Ref(r,0));if(!(0,u.isStream)(a))throw new l.FormatError("bad ObjStm stream");var i=a.dict.get("First"),n=a.dict.get("N");if(!Number.isInteger(i)||!Number.isInteger(n))throw new l.FormatError("invalid first and n parameters for ObjStm stream");var o=new h.Parser(new h.Lexer(a),!1,this);o.allowStreams=!0;var s,c,f=[],d=[];for(s=0;s<n;++s){c=o.getObj();if(!Number.isInteger(c))throw new l.FormatError("invalid object number in the ObjStm stream: "+c);d.push(c);var g=o.getObj();if(!Number.isInteger(g))throw new l.FormatError("invalid object offset in the ObjStm stream: "+g)}for(s=0;s<n;++s){f.push(o.getObj());(0,u.isCmd)(o.buf1,"endobj")&&o.shift();c=d[s];var m=this.entries[c];m&&m.offset===r&&m.gen===s&&(this.cache[c]=f[s])}if(void 0===(e=f[e.gen]))throw new l.FormatError("bad XRef entry for compressed object");return e},fetchIfRefAsync:function(){var e=v(n.default.mark(function e(t,r){return n.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if((0,u.isRef)(t)){e.next=2;break}return e.abrupt("return",t);case 2:return e.abrupt("return",this.fetchAsync(t,r));case 3:case"end":return e.stop()}},e,this)}));return function(t,r){return e.apply(this,arguments)}}(),fetchAsync:function(){var e=v(n.default.mark(function e(t,r){return n.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:e.prev=0;return e.abrupt("return",this.fetch(t,r));case 4:e.prev=4;e.t0=e.catch(0);if(e.t0 instanceof l.MissingDataException){e.next=8;break}throw e.t0;case 8:e.next=10;return this.pdfManager.requestRange(e.t0.begin,e.t0.end);case 10:return e.abrupt("return",this.fetchAsync(t,r));case 11:case"end":return e.stop()}},e,this,[[0,4]])}));return function(t,r){return e.apply(this,arguments)}}(),getCatalogObj:function(){return this.root}};return e}(),S=function(){function e(t,r,a){b(this,e);this.constructor===e&&(0,l.unreachable)("Cannot initialize NameOrNumberTree.");this.root=t;this.xref=r;this._type=a}c(e,[{key:"getAll",value:function(){var e=Object.create(null);if(!this.root)return e;var t=this.xref,r=new u.RefSet;r.put(this.root);for(var a=[this.root];a.length>0;){var i=t.fetchIfRef(a.shift());if((0,u.isDict)(i))if(i.has("Kids"))for(var n=i.get("Kids"),o=0,s=n.length;o<s;o++){var c=n[o];if(r.has(c))throw new l.FormatError('Duplicate entry in "'+this._type+'" tree.');a.push(c);r.put(c)}else{var h=i.get(this._type);if(Array.isArray(h))for(var f=0,d=h.length;f<d;f+=2)e[t.fetchIfRef(h[f])]=t.fetchIfRef(h[f+1])}}return e}},{key:"get",value:function(e){if(!this.root)return null;for(var t=this.xref,r=t.fetchIfRef(this.root),a=0;r.has("Kids");){if(++a>10){(0,l.warn)('Search depth limit reached for "'+this._type+'" tree.');return null}var i=r.get("Kids");if(!Array.isArray(i))return null;for(var n=0,o=i.length-1;n<=o;){var s=n+o>>1,c=t.fetchIfRef(i[s]).get("Limits");if(e<t.fetchIfRef(c[0]))o=s-1;else{if(!(e>t.fetchIfRef(c[1]))){r=t.fetchIfRef(i[s]);break}n=s+1}}if(n>o)return null}var u=r.get(this._type);if(Array.isArray(u))for(var h=0,f=u.length-2;h<=f;){var d=h+f&-2,g=t.fetchIfRef(u[d]);if(e<g)f=d-2;else{if(!(e>g))return t.fetchIfRef(u[d+1]);h=d+2}}return null}}]);return e}(),C=function(e){p(t,S);function t(e,r){b(this,t);return m(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r,"Names"))}return t}(),x=function(e){p(t,S);function t(e,r){b(this,t);return m(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r,"Nums"))}return t}(),_=function(){function e(e,t){if(e&&(0,u.isDict)(e)){this.xref=t;this.root=e;e.has("FS")&&(this.fs=e.get("FS"));this.description=e.has("Desc")?(0,l.stringToPDFString)(e.get("Desc")):"";e.has("RF")&&(0,l.warn)("Related file specifications are not supported");this.contentAvailable=!0;if(!e.has("EF")){this.contentAvailable=!1;(0,l.warn)("Non-embedded file specifications are not supported")}}}function t(e){return e.has("UF")?e.get("UF"):e.has("F")?e.get("F"):e.has("Unix")?e.get("Unix"):e.has("Mac")?e.get("Mac"):e.has("DOS")?e.get("DOS"):null}e.prototype={get filename(){if(!this._filename&&this.root){var e=t(this.root)||"unnamed";this._filename=(0,l.stringToPDFString)(e).replace(/\\\\/g,"\\").replace(/\\\//g,"/").replace(/\\/g,"/")}return this._filename},get content(){if(!this.contentAvailable)return null;!this.contentRef&&this.root&&(this.contentRef=t(this.root.get("EF")));var e=null;if(this.contentRef){var r=this.xref.fetchIfRef(this.contentRef);r&&(0,u.isStream)(r)?e=r.getBytes():(0,l.warn)("Embedded file specification points to non-existing/invalid content")}else(0,l.warn)("Embedded file specification does not have a content");return e},get serializable(){return{filename:this.filename,content:this.content}}};return e}(),A=function(){function e(e){return(0,u.isRef)(e)||(0,u.isDict)(e)||Array.isArray(e)||(0,u.isStream)(e)}function t(t,r){if((0,u.isDict)(t)||(0,u.isStream)(t))for(var a=(0,u.isDict)(t)?t:t.dict,i=a.getKeys(),n=0,o=i.length;n<o;n++){var s=a.getRaw(i[n]);e(s)&&r.push(s)}else if(Array.isArray(t))for(var c=0,l=t.length;c<l;c++){var h=t[c];e(h)&&r.push(h)}}function r(e,t,r){this.dict=e;this.keys=t;this.xref=r;this.refSet=null;this.capability=null}r.prototype={load:function(){this.capability=(0,l.createPromiseCapability)();if(!(this.xref.stream instanceof f.ChunkedStream)||0===this.xref.stream.getMissingChunks().length){this.capability.resolve();return this.capability.promise}var e=this.keys,t=this.dict;this.refSet=new u.RefSet;for(var r=[],a=0,i=e.length;a<i;a++){var n=t.getRaw(e[a]);void 0!==n&&r.push(n)}this._walk(r);return this.capability.promise},_walk:function(e){for(var r=this,a=[],i=[];e.length;){var n=e.pop();if((0,u.isRef)(n)){if(this.refSet.has(n))continue;try{this.refSet.put(n);n=this.xref.fetch(n)}catch(e){if(!(e instanceof l.MissingDataException))throw e;a.push(n);i.push({begin:e.begin,end:e.end})}}if(n&&n.getBaseStreams){for(var o=n.getBaseStreams(),s=!1,c=0,h=o.length;c<h;c++){var f=o[c];if(f.getMissingChunks&&f.getMissingChunks().length){s=!0;i.push({begin:f.start,end:f.end})}}s&&a.push(n)}t(n,e)}if(i.length)this.xref.stream.manager.requestRanges(i).then(function(){for(var e=0,t=a.length;e<t;e++){var i=a[e];(0,u.isRef)(i)&&r.refSet.remove(i)}r._walk(a)},this.capability.reject);else{this.refSet=null;this.capability.resolve()}}};return r}();t.Catalog=w;t.ObjectLoader=A;t.XRef=k;t.FileSpec=_},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i={},n=function(){function e(e){this.name=e}e.prototype={};var t=Object.create(null);e.get=function(r){var a=t[r];return a||(t[r]=new e(r))};return e}(),o=function(){function e(e){this.cmd=e}e.prototype={};var t=Object.create(null);e.get=function(r){var a=t[r];return a||(t[r]=new e(r))};return e}(),s=function(){var e=function(){return e};function t(t){this._map=Object.create(null);this.xref=t;this.objId=null;this.suppressEncryption=!1;this.__nonSerializable__=e}t.prototype={assignXref:function(e){this.xref=e},get:function(e,t,r){var a,i=this.xref,n=this.suppressEncryption;if(void 0!==(a=this._map[e])||e in this._map||void 0===t)return i?i.fetchIfRef(a,n):a;if(void 0!==(a=this._map[t])||t in this._map||void 0===r)return i?i.fetchIfRef(a,n):a;a=this._map[r]||null;return i?i.fetchIfRef(a,n):a},getAsync:function(e,t,r){var a,i=this.xref,n=this.suppressEncryption;if(void 0!==(a=this._map[e])||e in this._map||void 0===t)return i?i.fetchIfRefAsync(a,n):Promise.resolve(a);if(void 0!==(a=this._map[t])||t in this._map||void 0===r)return i?i.fetchIfRefAsync(a,n):Promise.resolve(a);a=this._map[r]||null;return i?i.fetchIfRefAsync(a,n):Promise.resolve(a)},getArray:function(e,t,r){var a=this.get(e,t,r),i=this.xref,n=this.suppressEncryption;if(!Array.isArray(a)||!i)return a;for(var o=0,s=(a=a.slice()).length;o<s;o++)d(a[o])&&(a[o]=i.fetch(a[o],n));return a},getRaw:function(e){return this._map[e]},getKeys:function(){return Object.keys(this._map)},set:function(e,t){this._map[e]=t},has:function(e){return e in this._map},forEach:function(e){for(var t in this._map)e(t,this.get(t))}};t.empty=new t(null);t.merge=function(e,r){for(var a=new t(e),i=0,n=r.length;i<n;i++){var o=r[i];if(f(o))for(var s in o._map)void 0===a._map[s]&&(a._map[s]=o._map[s])}return a};return t}(),c=function(){function e(e,t){this.num=e;this.gen=t}e.prototype={toString:function(){var e=this.num+"R";0!==this.gen&&(e+=this.gen);return e}};return e}(),l=function(){function e(){this.dict=Object.create(null)}e.prototype={has:function(e){return e.toString()in this.dict},put:function(e){this.dict[e.toString()]=!0},remove:function(e){delete this.dict[e.toString()]}};return e}(),u=function(){function e(){this.dict=Object.create(null)}e.prototype={get:function(e){return this.dict[e.toString()]},has:function(e){return e.toString()in this.dict},put:function(e,t){this.dict[e.toString()]=t},putAlias:function(e,t){this.dict[e.toString()]=this.get(t)},forEach:function(e,t){for(var r in this.dict)e.call(t,this.dict[r])},clear:function(){this.dict=Object.create(null)}};return e}();function h(e,t){return e instanceof n&&(void 0===t||e.name===t)}function f(e,t){return e instanceof s&&(void 0===t||h(e.get("Type"),t))}function d(e){return e instanceof c}t.EOF=i;t.Cmd=o;t.Dict=s;t.Name=n;t.Ref=c;t.RefSet=l;t.RefSetCache=u;t.isEOF=function(e){return e===i};t.isCmd=function(e,t){return e instanceof o&&(void 0===t||e.cmd===t)};t.isDict=f;t.isName=h;t.isRef=d;t.isRefsEqual=function(e,t){return e.num===t.num&&e.gen===t.gen};t.isStream=function(e){return"object"===(void 0===e?"undefined":a(e))&&null!==e&&void 0!==e.getBytes}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.Parser=t.Linearization=t.Lexer=void 0;var a=r(140),i=r(2),n=r(138),o=r(141),s=r(143),c=r(146),l=r(148);function u(e){for(var t=e.length,r=1,a=0,i=0;i<t;++i)a+=r+=255&e[i];return a%65521<<16|r%65521}var h=function(){function e(e,t,r,a){this.lexer=e;this.allowStreams=t;this.xref=r;this.recoveryMode=a||!1;this.imageCache=Object.create(null);this.refill()}e.prototype={refill:function(){this.buf1=this.lexer.getObj();this.buf2=this.lexer.getObj()},shift:function(){if((0,n.isCmd)(this.buf2,"ID")){this.buf1=this.buf2;this.buf2=null}else{this.buf1=this.buf2;this.buf2=this.lexer.getObj()}},tryShift:function(){try{this.shift();return!0}catch(e){if(e instanceof i.MissingDataException)throw e;return!1}},getObj:function(e){var t=this.buf1;this.shift();if(t instanceof n.Cmd)switch(t.cmd){case"BI":return this.makeInlineImage(e);case"[":for(var r=[];!(0,n.isCmd)(this.buf1,"]")&&!(0,n.isEOF)(this.buf1);)r.push(this.getObj(e));if((0,n.isEOF)(this.buf1)){if(!this.recoveryMode)throw new i.FormatError("End of file inside array");return r}this.shift();return r;case"<<":for(var a=new n.Dict(this.xref);!(0,n.isCmd)(this.buf1,">>")&&!(0,n.isEOF)(this.buf1);)if((0,n.isName)(this.buf1)){var o=this.buf1.name;this.shift();if((0,n.isEOF)(this.buf1))break;a.set(o,this.getObj(e))}else{(0,i.info)("Malformed dictionary: key must be a name object");this.shift()}if((0,n.isEOF)(this.buf1)){if(!this.recoveryMode)throw new i.FormatError("End of file inside dictionary");return a}if((0,n.isCmd)(this.buf2,"stream"))return this.allowStreams?this.makeStream(a,e):a;this.shift();return a;default:return t}if(Number.isInteger(t)){var s=t;if(Number.isInteger(this.buf1)&&(0,n.isCmd)(this.buf2,"R")){var c=new n.Ref(s,this.buf1);this.shift();this.shift();return c}return s}if((0,i.isString)(t)){var l=t;e&&(l=e.decryptString(l));return l}return t},findDefaultInlineStreamEnd:function(e){for(var t=e.pos,r=0,a=void 0,n=void 0;-1!==(a=e.getByte());)if(0===r)r=69===a?1:0;else if(1===r)r=73===a?2:0;else{(0,i.assert)(2===r);if(32===a||10===a||13===a){n=e.pos;for(var o=e.peekBytes(10),s=0,c=o.length;s<c;s++)if((0!==(a=o[s])||0===o[s+1])&&10!==a&&13!==a&&(a<32||a>127)){r=0;break}if(2===r)break}else r=0}if(-1===a){(0,i.warn)("findDefaultInlineStreamEnd: Reached the end of the stream without finding a valid EI marker");if(n){(0,i.warn)('... trying to recover by using the last "EI" occurrence.');e.skip(-(e.pos-n))}}return e.pos-4-t},findDCTDecodeInlineStreamEnd:function(e){for(var t,r,a,n=e.pos,o=!1;-1!==(t=e.getByte());)if(255===t){switch(e.getByte()){case 0:break;case 255:e.skip(-1);break;case 217:o=!0;break;case 192:case 193:case 194:case 195:case 197:case 198:case 199:case 201:case 202:case 203:case 205:case 206:case 207:case 196:case 204:case 218:case 219:case 220:case 221:case 222:case 223:case 224:case 225:case 226:case 227:case 228:case 229:case 230:case 231:case 232:case 233:case 234:case 235:case 236:case 237:case 238:case 239:case 254:(r=e.getUint16())>2?e.skip(r-2):e.skip(-2)}if(o)break}a=e.pos-n;if(-1===t){(0,i.warn)("Inline DCTDecode image stream: EOI marker not found, searching for /EI/ instead.");e.skip(-a);return this.findDefaultInlineStreamEnd(e)}this.inlineStreamSkipEI(e);return a},findASCII85DecodeInlineStreamEnd:function(e){for(var t,r,a=e.pos;-1!==(t=e.getByte());)if(126===t&&62===e.peekByte()){e.skip();break}r=e.pos-a;if(-1===t){(0,i.warn)("Inline ASCII85Decode image stream: EOD marker not found, searching for /EI/ instead.");e.skip(-r);return this.findDefaultInlineStreamEnd(e)}this.inlineStreamSkipEI(e);return r},findASCIIHexDecodeInlineStreamEnd:function(e){for(var t,r,a=e.pos;-1!==(t=e.getByte())&&62!==t;);r=e.pos-a;if(-1===t){(0,i.warn)("Inline ASCIIHexDecode image stream: EOD marker not found, searching for /EI/ instead.");e.skip(-r);return this.findDefaultInlineStreamEnd(e)}this.inlineStreamSkipEI(e);return r},inlineStreamSkipEI:function(e){for(var t,r=0;-1!==(t=e.getByte());)if(0===r)r=69===t?1:0;else if(1===r)r=73===t?2:0;else if(2===r)break},makeInlineImage:function(e){for(var t=this.lexer,r=t.stream,a=new n.Dict(this.xref),o=void 0;!(0,n.isCmd)(this.buf1,"ID")&&!(0,n.isEOF)(this.buf1);){if(!(0,n.isName)(this.buf1))throw new i.FormatError("Dictionary key must be a name object");var s=this.buf1.name;this.shift();if((0,n.isEOF)(this.buf1))break;a.set(s,this.getObj(e))}-1!==t.beginInlineImagePos&&(o=r.pos-t.beginInlineImagePos);var c,l=a.get("Filter","F");if((0,n.isName)(l))c=l.name;else if(Array.isArray(l)){var h=this.xref.fetchIfRef(l[0]);(0,n.isName)(h)&&(c=h.name)}var f=r.pos,d=void 0;d="DCTDecode"===c||"DCT"===c?this.findDCTDecodeInlineStreamEnd(r):"ASCII85Decode"===c||"A85"===c?this.findASCII85DecodeInlineStreamEnd(r):"ASCIIHexDecode"===c||"AHx"===c?this.findASCIIHexDecodeInlineStreamEnd(r):this.findDefaultInlineStreamEnd(r);var g=r.makeSubStream(f,d,a),m=void 0;if(d<1e3&&o<5552){var p=g.getBytes();g.reset();var v=r.pos;r.pos=t.beginInlineImagePos;var b=r.getBytes(o);r.pos=v;m=u(p)+"_"+u(b);var y=this.imageCache[m];if(void 0!==y){this.buf2=n.Cmd.get("EI");this.shift();y.reset();return y}}e&&(g=e.createStream(g,d));(g=this.filter(g,a,d)).dict=a;if(void 0!==m){g.cacheKey="inline_"+d+"_"+m;this.imageCache[m]=g}this.buf2=n.Cmd.get("EI");this.shift();return g},_findStreamLength:function(e,t){var r=this.lexer.stream;r.pos=e;for(var a=t.length;r.pos<r.end;){var i=r.peekBytes(2048),n=i.length-a;if(n<=0)break;for(var o=0;o<n;){for(var s=0;s<a&&i[o+s]===t[s];)s++;if(s>=a){r.pos+=o;return r.pos-e}o++}r.pos+=n}return-1},makeStream:function(e,t){var r=this.lexer,a=r.stream;r.skipToNextLine();var o=a.pos-1,s=e.get("Length");if(!Number.isInteger(s)){(0,i.info)("Bad "+s+" attribute in stream");s=0}a.pos=o+s;r.nextChar();if(this.tryShift()&&(0,n.isCmd)(this.buf2,"endstream"))this.shift();else{var c=new Uint8Array([101,110,100,115,116,114,101,97,109]),l=this._findStreamLength(o,c);if(l<0){for(var u=1;u<=1;u++){var h=c.length-u,f=c.slice(0,h),d=this._findStreamLength(o,f);if(d>=0){var g=a.peekBytes(h+1)[h];if(!(0,i.isSpace)(g))break;(0,i.info)('Found "'+(0,i.bytesToString)(f)+'" when searching for endstream command.');l=d;break}}if(l<0)throw new i.FormatError("Missing endstream command.")}s=l;r.nextChar();this.shift();this.shift()}this.shift();a=a.makeSubStream(o,s,e);t&&(a=t.createStream(a,s));(a=this.filter(a,e,s)).dict=e;return a},filter:function(e,t,r){var a=t.get("Filter","F"),o=t.get("DecodeParms","DP");if((0,n.isName)(a)){Array.isArray(o)&&(0,i.warn)("/DecodeParms should not contain an Array, when /Filter contains a Name.");return this.makeFilter(e,a.name,r,o)}var s=r;if(Array.isArray(a))for(var c=a,l=o,u=0,h=c.length;u<h;++u){a=this.xref.fetchIfRef(c[u]);if(!(0,n.isName)(a))throw new i.FormatError("Bad filter name: "+a);o=null;Array.isArray(l)&&u in l&&(o=this.xref.fetchIfRef(l[u]));e=this.makeFilter(e,a.name,s,o);s=null}return e},makeFilter:function(e,t,r,n){if(0===r){(0,i.warn)('Empty "'+t+'" stream.');return new a.NullStream}try{var u=this.xref.stats.streamTypes;if("FlateDecode"===t||"Fl"===t){u[i.StreamType.FLATE]=!0;return n?new a.PredictorStream(new a.FlateStream(e,r),r,n):new a.FlateStream(e,r)}if("LZWDecode"===t||"LZW"===t){u[i.StreamType.LZW]=!0;var h=1;if(n){n.has("EarlyChange")&&(h=n.get("EarlyChange"));return new a.PredictorStream(new a.LZWStream(e,r,h),r,n)}return new a.LZWStream(e,r,h)}if("DCTDecode"===t||"DCT"===t){u[i.StreamType.DCT]=!0;return new c.JpegStream(e,r,e.dict,n)}if("JPXDecode"===t||"JPX"===t){u[i.StreamType.JPX]=!0;return new l.JpxStream(e,r,e.dict,n)}if("ASCII85Decode"===t||"A85"===t){u[i.StreamType.A85]=!0;return new a.Ascii85Stream(e,r)}if("ASCIIHexDecode"===t||"AHx"===t){u[i.StreamType.AHX]=!0;return new a.AsciiHexStream(e,r)}if("CCITTFaxDecode"===t||"CCF"===t){u[i.StreamType.CCF]=!0;return new o.CCITTFaxStream(e,r,n)}if("RunLengthDecode"===t||"RL"===t){u[i.StreamType.RL]=!0;return new a.RunLengthStream(e,r)}if("JBIG2Decode"===t){u[i.StreamType.JBIG]=!0;return new s.Jbig2Stream(e,r,e.dict,n)}(0,i.warn)('filter "'+t+'" not supported yet');return e}catch(e){if(e instanceof i.MissingDataException)throw e;(0,i.warn)('Invalid stream: "'+e+'"');return new a.NullStream}}};return e}(),f=function(){function e(e,t){this.stream=e;this.nextChar();this.strBuf=[];this.knownCommands=t;this.beginInlineImagePos=-1}var t=[1,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,2,0,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,2,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];function r(e){return e>=48&&e<=57?15&e:e>=65&&e<=70||e>=97&&e<=102?9+(15&e):-1}e.prototype={nextChar:function(){return this.currentChar=this.stream.getByte()},peekChar:function(){return this.stream.peekByte()},getNumber:function(){var e=this.currentChar,t=!1,r=0,a=0;if(45===e){a=-1;45===(e=this.nextChar())&&(e=this.nextChar())}else if(43===e){a=1;e=this.nextChar()}if(10===e||13===e)do{e=this.nextChar()}while(10===e||13===e);if(46===e){r=10;e=this.nextChar()}if(e<48||e>57){if(10===r&&0===a&&((0,i.isSpace)(e)||-1===e)){(0,i.warn)("Lexer.getNumber - treating a single decimal point as zero.");return 0}throw new i.FormatError("Invalid number: "+String.fromCharCode(e)+" (charCode "+e+")")}a=a||1;for(var n=e-48,o=0,s=1;(e=this.nextChar())>=0;)if(48<=e&&e<=57){var c=e-48;if(t)o=10*o+c;else{0!==r&&(r*=10);n=10*n+c}}else if(46===e){if(0!==r)break;r=1}else if(45===e)(0,i.warn)("Badly formatted number");else{if(69!==e&&101!==e)break;if(43===(e=this.peekChar())||45===e){s=45===e?-1:1;this.nextChar()}else if(e<48||e>57)break;t=!0}0!==r&&(n/=r);t&&(n*=Math.pow(10,s*o));return a*n},getString:function(){var e=1,t=!1,r=this.strBuf;r.length=0;for(var a=this.nextChar();;){var n=!1;switch(0|a){case-1:(0,i.warn)("Unterminated string");t=!0;break;case 40:++e;r.push("(");break;case 41:if(0==--e){this.nextChar();t=!0}else r.push(")");break;case 92:switch(a=this.nextChar()){case-1:(0,i.warn)("Unterminated string");t=!0;break;case 110:r.push("\n");break;case 114:r.push("\r");break;case 116:r.push("\t");break;case 98:r.push("\b");break;case 102:r.push("\f");break;case 92:case 40:case 41:r.push(String.fromCharCode(a));break;case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:var o=15&a;a=this.nextChar();n=!0;if(a>=48&&a<=55){o=(o<<3)+(15&a);if((a=this.nextChar())>=48&&a<=55){n=!1;o=(o<<3)+(15&a)}}r.push(String.fromCharCode(o));break;case 13:10===this.peekChar()&&this.nextChar();break;case 10:break;default:r.push(String.fromCharCode(a))}break;default:r.push(String.fromCharCode(a))}if(t)break;n||(a=this.nextChar())}return r.join("")},getName:function(){var e,a,o=this.strBuf;o.length=0;for(;(e=this.nextChar())>=0&&!t[e];)if(35===e){e=this.nextChar();if(t[e]){(0,i.warn)("Lexer_getName: NUMBER SIGN (#) should be followed by a hexadecimal number.");o.push("#");break}var s=r(e);if(-1!==s){a=e;var c=r(e=this.nextChar());if(-1===c){(0,i.warn)("Lexer_getName: Illegal digit ("+String.fromCharCode(e)+") in hexadecimal number.");o.push("#",String.fromCharCode(a));if(t[e])break;o.push(String.fromCharCode(e));continue}o.push(String.fromCharCode(s<<4|c))}else o.push("#",String.fromCharCode(e))}else o.push(String.fromCharCode(e));o.length>127&&(0,i.warn)("name token is longer than allowed by the spec: "+o.length);return n.Name.get(o.join(""))},getHexString:function(){var e=this.strBuf;e.length=0;for(var a,n,o=this.currentChar,s=!0;;){if(o<0){(0,i.warn)("Unterminated hex string");break}if(62===o){this.nextChar();break}if(1!==t[o]){if(s){if(-1===(a=r(o))){(0,i.warn)('Ignoring invalid character "'+o+'" in hex string');o=this.nextChar();continue}}else{if(-1===(n=r(o))){(0,i.warn)('Ignoring invalid character "'+o+'" in hex string');o=this.nextChar();continue}e.push(String.fromCharCode(a<<4|n))}s=!s;o=this.nextChar()}else o=this.nextChar()}return e.join("")},getObj:function(){for(var e=!1,r=this.currentChar;;){if(r<0)return n.EOF;if(e)10!==r&&13!==r||(e=!1);else if(37===r)e=!0;else if(1!==t[r])break;r=this.nextChar()}switch(0|r){case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:case 43:case 45:case 46:return this.getNumber();case 40:return this.getString();case 47:return this.getName();case 91:this.nextChar();return n.Cmd.get("[");case 93:this.nextChar();return n.Cmd.get("]");case 60:if(60===(r=this.nextChar())){this.nextChar();return n.Cmd.get("<<")}return this.getHexString();case 62:if(62===(r=this.nextChar())){this.nextChar();return n.Cmd.get(">>")}return n.Cmd.get(">");case 123:this.nextChar();return n.Cmd.get("{");case 125:this.nextChar();return n.Cmd.get("}");case 41:this.nextChar();throw new i.FormatError("Illegal character: "+r)}for(var a=String.fromCharCode(r),o=this.knownCommands,s=o&&void 0!==o[a];(r=this.nextChar())>=0&&!t[r];){var c=a+String.fromCharCode(r);if(s&&void 0===o[c])break;if(128===a.length)throw new i.FormatError("Command token too long: "+a.length);a=c;s=o&&void 0!==o[a]}if("true"===a)return!0;if("false"===a)return!1;if("null"===a)return null;"BI"===a&&(this.beginInlineImagePos=this.stream.pos);return n.Cmd.get(a)},skipToNextLine:function(){for(var e=this.currentChar;e>=0;){if(13===e){10===(e=this.nextChar())&&this.nextChar();break}if(10===e){this.nextChar();break}e=this.nextChar()}}};return e}(),d={create:function(e){function t(e,t){var r=u.get(e);if(Number.isInteger(r)&&(t?r>=0:r>0))return r;throw new Error('The "'+e+'" parameter in the linearization dictionary is invalid.')}var r,a,o=new h(new f(e),!1,null),s=o.getObj(),c=o.getObj(),l=o.getObj(),u=o.getObj();if(!(Number.isInteger(s)&&Number.isInteger(c)&&(0,n.isCmd)(l,"obj")&&(0,n.isDict)(u)&&(0,i.isNum)(r=u.get("Linearized"))&&r>0))return null;if((a=t("L"))!==e.length)throw new Error('The "L" parameter in the linearization dictionary does not equal the stream length.');return{length:a,hints:function(){var e,t,r=u.get("H");if(Array.isArray(r)&&(2===(e=r.length)||4===e)){for(var a=0;a<e;a++)if(!(Number.isInteger(t=r[a])&&t>0))throw new Error("Hint ("+a+") in the linearization dictionary is invalid.");return r}throw new Error("Hint array in the linearization dictionary is invalid.")}(),objectNumberFirst:t("O"),endFirst:t("E"),numPages:t("N"),mainXRefEntriesOffset:t("T"),pageFirst:u.has("P")?t("P",!0):0}}};t.Lexer=f;t.Linearization=d;t.Parser=h},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.LZWStream=t.StringStream=t.StreamsSequenceStream=t.Stream=t.RunLengthStream=t.PredictorStream=t.NullStream=t.FlateStream=t.DecodeStream=t.DecryptStream=t.AsciiHexStream=t.Ascii85Stream=void 0;var a=r(2),i=r(138);function n(e){if(Array.isArray(e)){for(var t=0,r=Array(e.length);t<e.length;t++)r[t]=e[t];return r}return Array.from(e)}var o=function(){function e(e,t,r,a){this.bytes=e instanceof Uint8Array?e:new Uint8Array(e);this.start=t||0;this.pos=this.start;this.end=t+r||this.bytes.length;this.dict=a}e.prototype={get length(){return this.end-this.start},get isEmpty(){return 0===this.length},getByte:function(){return this.pos>=this.end?-1:this.bytes[this.pos++]},getUint16:function(){var e=this.getByte(),t=this.getByte();return-1===e||-1===t?-1:(e<<8)+t},getInt32:function(){return(this.getByte()<<24)+(this.getByte()<<16)+(this.getByte()<<8)+this.getByte()},getBytes:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=this.bytes,a=this.pos,i=this.end;if(!e){var n=r.subarray(a,i);return t?new Uint8ClampedArray(n):n}var o=a+e;o>i&&(o=i);this.pos=o;var s=r.subarray(a,o);return t?new Uint8ClampedArray(s):s},peekByte:function(){var e=this.getByte();this.pos--;return e},peekBytes:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=this.getBytes(e,t);this.pos-=r.length;return r},skip:function(e){e||(e=1);this.pos+=e},reset:function(){this.pos=this.start},moveStart:function(){this.start=this.pos},makeSubStream:function(t,r,a){return new e(this.bytes.buffer,t,r,a)}};return e}(),s=function(){function e(e){var t=(0,a.stringToBytes)(e);o.call(this,t)}e.prototype=o.prototype;return e}(),c=function(){var e=new Uint8Array(0);function t(t){this._rawMinBufferLength=t||0;this.pos=0;this.bufferLength=0;this.eof=!1;this.buffer=e;this.minBufferLength=512;if(t)for(;this.minBufferLength<t;)this.minBufferLength*=2}t.prototype={get isEmpty(){for(;!this.eof&&0===this.bufferLength;)this.readBlock();return 0===this.bufferLength},ensureBuffer:function(e){var t=this.buffer;if(e<=t.byteLength)return t;for(var r=this.minBufferLength;r<e;)r*=2;var a=new Uint8Array(r);a.set(t);return this.buffer=a},getByte:function(){for(var e=this.pos;this.bufferLength<=e;){if(this.eof)return-1;this.readBlock()}return this.buffer[this.pos++]},getUint16:function(){var e=this.getByte(),t=this.getByte();return-1===e||-1===t?-1:(e<<8)+t},getInt32:function(){return(this.getByte()<<24)+(this.getByte()<<16)+(this.getByte()<<8)+this.getByte()},getBytes:function(e){var t,r=arguments.length>1&&void 0!==arguments[1]&&arguments[1],a=this.pos;if(e){this.ensureBuffer(a+e);t=a+e;for(;!this.eof&&this.bufferLength<t;)this.readBlock();var i=this.bufferLength;t>i&&(t=i)}else{for(;!this.eof;)this.readBlock();t=this.bufferLength}this.pos=t;var n=this.buffer.subarray(a,t);return!r||n instanceof Uint8ClampedArray?n:new Uint8ClampedArray(n)},peekByte:function(){var e=this.getByte();this.pos--;return e},peekBytes:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=this.getBytes(e,t);this.pos-=r.length;return r},makeSubStream:function(e,t,r){for(var a=e+t;this.bufferLength<=a&&!this.eof;)this.readBlock();return new o(this.buffer,e,t,r)},skip:function(e){e||(e=1);this.pos+=e},reset:function(){this.pos=0},getBaseStreams:function(){return this.str&&this.str.getBaseStreams?this.str.getBaseStreams():[]}};return t}(),l=function(){function e(e){this.streams=e;for(var t=0,r=0,a=e.length;r<a;r++){var i=e[r];t+=i instanceof c?i._rawMinBufferLength:i.length}c.call(this,t)}e.prototype=Object.create(c.prototype);e.prototype.readBlock=function(){var e=this.streams;if(0!==e.length){var t=e.shift().getBytes(),r=this.bufferLength,a=r+t.length;this.ensureBuffer(a).set(t,r);this.bufferLength=a}else this.eof=!0};e.prototype.getBaseStreams=function(){for(var e=[],t=0,r=this.streams.length;t<r;t++){var a=this.streams[t];a.getBaseStreams&&e.push.apply(e,n(a.getBaseStreams()))}return e};return e}(),u=function(){var e=new Int32Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),t=new Int32Array([3,4,5,6,7,8,9,10,65547,65549,65551,65553,131091,131095,131099,131103,196643,196651,196659,196667,262211,262227,262243,262259,327811,327843,327875,327907,258,258,258]),r=new Int32Array([1,2,3,4,65541,65543,131081,131085,196625,196633,262177,262193,327745,327777,393345,393409,459009,459137,524801,525057,590849,591361,657409,658433,724993,727041,794625,798721,868353,876545]),i=[new Int32Array([459008,524368,524304,524568,459024,524400,524336,590016,459016,524384,524320,589984,524288,524416,524352,590048,459012,524376,524312,589968,459028,524408,524344,590032,459020,524392,524328,59e4,524296,524424,524360,590064,459010,524372,524308,524572,459026,524404,524340,590024,459018,524388,524324,589992,524292,524420,524356,590056,459014,524380,524316,589976,459030,524412,524348,590040,459022,524396,524332,590008,524300,524428,524364,590072,459009,524370,524306,524570,459025,524402,524338,590020,459017,524386,524322,589988,524290,524418,524354,590052,459013,524378,524314,589972,459029,524410,524346,590036,459021,524394,524330,590004,524298,524426,524362,590068,459011,524374,524310,524574,459027,524406,524342,590028,459019,524390,524326,589996,524294,524422,524358,590060,459015,524382,524318,589980,459031,524414,524350,590044,459023,524398,524334,590012,524302,524430,524366,590076,459008,524369,524305,524569,459024,524401,524337,590018,459016,524385,524321,589986,524289,524417,524353,590050,459012,524377,524313,589970,459028,524409,524345,590034,459020,524393,524329,590002,524297,524425,524361,590066,459010,524373,524309,524573,459026,524405,524341,590026,459018,524389,524325,589994,524293,524421,524357,590058,459014,524381,524317,589978,459030,524413,524349,590042,459022,524397,524333,590010,524301,524429,524365,590074,459009,524371,524307,524571,459025,524403,524339,590022,459017,524387,524323,589990,524291,524419,524355,590054,459013,524379,524315,589974,459029,524411,524347,590038,459021,524395,524331,590006,524299,524427,524363,590070,459011,524375,524311,524575,459027,524407,524343,590030,459019,524391,524327,589998,524295,524423,524359,590062,459015,524383,524319,589982,459031,524415,524351,590046,459023,524399,524335,590014,524303,524431,524367,590078,459008,524368,524304,524568,459024,524400,524336,590017,459016,524384,524320,589985,524288,524416,524352,590049,459012,524376,524312,589969,459028,524408,524344,590033,459020,524392,524328,590001,524296,524424,524360,590065,459010,524372,524308,524572,459026,524404,524340,590025,459018,524388,524324,589993,524292,524420,524356,590057,459014,524380,524316,589977,459030,524412,524348,590041,459022,524396,524332,590009,524300,524428,524364,590073,459009,524370,524306,524570,459025,524402,524338,590021,459017,524386,524322,589989,524290,524418,524354,590053,459013,524378,524314,589973,459029,524410,524346,590037,459021,524394,524330,590005,524298,524426,524362,590069,459011,524374,524310,524574,459027,524406,524342,590029,459019,524390,524326,589997,524294,524422,524358,590061,459015,524382,524318,589981,459031,524414,524350,590045,459023,524398,524334,590013,524302,524430,524366,590077,459008,524369,524305,524569,459024,524401,524337,590019,459016,524385,524321,589987,524289,524417,524353,590051,459012,524377,524313,589971,459028,524409,524345,590035,459020,524393,524329,590003,524297,524425,524361,590067,459010,524373,524309,524573,459026,524405,524341,590027,459018,524389,524325,589995,524293,524421,524357,590059,459014,524381,524317,589979,459030,524413,524349,590043,459022,524397,524333,590011,524301,524429,524365,590075,459009,524371,524307,524571,459025,524403,524339,590023,459017,524387,524323,589991,524291,524419,524355,590055,459013,524379,524315,589975,459029,524411,524347,590039,459021,524395,524331,590007,524299,524427,524363,590071,459011,524375,524311,524575,459027,524407,524343,590031,459019,524391,524327,589999,524295,524423,524359,590063,459015,524383,524319,589983,459031,524415,524351,590047,459023,524399,524335,590015,524303,524431,524367,590079]),9],n=[new Int32Array([327680,327696,327688,327704,327684,327700,327692,327708,327682,327698,327690,327706,327686,327702,327694,0,327681,327697,327689,327705,327685,327701,327693,327709,327683,327699,327691,327707,327687,327703,327695,0]),5];function o(e,t){this.str=e;this.dict=e.dict;var r=e.getByte(),i=e.getByte();if(-1===r||-1===i)throw new a.FormatError("Invalid header in flate stream: "+r+", "+i);if(8!=(15&r))throw new a.FormatError("Unknown compression method in flate stream: "+r+", "+i);if(((r<<8)+i)%31!=0)throw new a.FormatError("Bad FCHECK in flate stream: "+r+", "+i);if(32&i)throw new a.FormatError("FDICT bit set in flate stream: "+r+", "+i);this.codeSize=0;this.codeBuf=0;c.call(this,t)}o.prototype=Object.create(c.prototype);o.prototype.getBits=function(e){for(var t,r=this.str,i=this.codeSize,n=this.codeBuf;i<e;){if(-1===(t=r.getByte()))throw new a.FormatError("Bad encoding in flate stream");n|=t<<i;i+=8}t=n&(1<<e)-1;this.codeBuf=n>>e;this.codeSize=i-=e;return t};o.prototype.getCode=function(e){for(var t,r=this.str,i=e[0],n=e[1],o=this.codeSize,s=this.codeBuf;o<n&&-1!==(t=r.getByte());){s|=t<<o;o+=8}var c=i[s&(1<<n)-1],l=c>>16,u=65535&c;if(l<1||o<l)throw new a.FormatError("Bad encoding in flate stream");this.codeBuf=s>>l;this.codeSize=o-l;return u};o.prototype.generateHuffmanTable=function(e){var t,r=e.length,a=0;for(t=0;t<r;++t)e[t]>a&&(a=e[t]);for(var i=1<<a,n=new Int32Array(i),o=1,s=0,c=2;o<=a;++o,s<<=1,c<<=1)for(var l=0;l<r;++l)if(e[l]===o){var u=0,h=s;for(t=0;t<o;++t){u=u<<1|1&h;h>>=1}for(t=u;t<i;t+=c)n[t]=o<<16|l;++s}return[n,a]};o.prototype.readBlock=function(){var o,s,c=this.str,l=this.getBits(3);1&l&&(this.eof=!0);if(0!==(l>>=1)){var u,h;if(1===l){u=i;h=n}else{if(2!==l)throw new a.FormatError("Unknown block type in flate stream");var f,d=this.getBits(5)+257,g=this.getBits(5)+1,m=this.getBits(4)+4,p=new Uint8Array(e.length);for(f=0;f<m;++f)p[e[f]]=this.getBits(3);var v=this.generateHuffmanTable(p);s=0;f=0;for(var b,y,w,k=d+g,S=new Uint8Array(k);f<k;){var C=this.getCode(v);if(16===C){b=2;y=3;w=s}else if(17===C){b=3;y=3;w=s=0}else{if(18!==C){S[f++]=s=C;continue}b=7;y=11;w=s=0}for(var x=this.getBits(b)+y;x-- >0;)S[f++]=w}u=this.generateHuffmanTable(S.subarray(0,d));h=this.generateHuffmanTable(S.subarray(d,k))}for(var _=(o=this.buffer)?o.length:0,A=this.bufferLength;;){var P=this.getCode(u);if(P<256){A+1>=_&&(_=(o=this.ensureBuffer(A+1)).length);o[A++]=P}else{if(256===P){this.bufferLength=A;return}var I=(P=t[P-=257])>>16;I>0&&(I=this.getBits(I));s=(65535&P)+I;P=this.getCode(h);(I=(P=r[P])>>16)>0&&(I=this.getBits(I));var O=(65535&P)+I;A+s>=_&&(_=(o=this.ensureBuffer(A+s)).length);for(var T=0;T<s;++T,++A)o[A]=o[A-O]}}}else{var E;if(-1===(E=c.getByte()))throw new a.FormatError("Bad block header in flate stream");var F=E;if(-1===(E=c.getByte()))throw new a.FormatError("Bad block header in flate stream");F|=E<<8;if(-1===(E=c.getByte()))throw new a.FormatError("Bad block header in flate stream");var R=E;if(-1===(E=c.getByte()))throw new a.FormatError("Bad block header in flate stream");if((R|=E<<8)!==(65535&~F)&&(0!==F||0!==R))throw new a.FormatError("Bad uncompressed block length in flate stream");this.codeBuf=0;this.codeSize=0;var B=this.bufferLength;o=this.ensureBuffer(B+F);var D=B+F;this.bufferLength=D;if(0===F)-1===c.peekByte()&&(this.eof=!0);else for(var M=B;M<D;++M){if(-1===(E=c.getByte())){this.eof=!0;break}o[M]=E}}};return o}(),h=function(){function e(e,t,r){if(!(0,i.isDict)(r))return e;var n=this.predictor=r.get("Predictor")||1;if(n<=1)return e;if(2!==n&&(n<10||n>15))throw new a.FormatError("Unsupported predictor: "+n);this.readBlock=2===n?this.readBlockTiff:this.readBlockPng;this.str=e;this.dict=e.dict;var o=this.colors=r.get("Colors")||1,s=this.bits=r.get("BitsPerComponent")||8,l=this.columns=r.get("Columns")||1;this.pixBytes=o*s+7>>3;this.rowBytes=l*o*s+7>>3;c.call(this,t);return this}e.prototype=Object.create(c.prototype);e.prototype.readBlockTiff=function(){var e=this.rowBytes,t=this.bufferLength,r=this.ensureBuffer(t+e),a=this.bits,i=this.colors,n=this.str.getBytes(e);this.eof=!n.length;if(!this.eof){var o,s=0,c=0,l=0,u=0,h=t;if(1===a&&1===i)for(o=0;o<e;++o){var f=n[o]^s;f^=f>>1;f^=f>>2;s=(1&(f^=f>>4))<<7;r[h++]=f}else if(8===a){for(o=0;o<i;++o)r[h++]=n[o];for(;o<e;++o){r[h]=r[h-i]+n[o];h++}}else if(16===a){var d=2*i;for(o=0;o<d;++o)r[h++]=n[o];for(;o<e;o+=2){var g=((255&n[o])<<8)+(255&n[o+1])+((255&r[h-d])<<8)+(255&r[h-d+1]);r[h++]=g>>8&255;r[h++]=255&g}}else{var m=new Uint8Array(i+1),p=(1<<a)-1,v=0,b=t,y=this.columns;for(o=0;o<y;++o)for(var w=0;w<i;++w){if(l<a){s=s<<8|255&n[v++];l+=8}m[w]=m[w]+(s>>l-a)&p;l-=a;c=c<<a|m[w];if((u+=a)>=8){r[b++]=c>>u-8&255;u-=8}}u>0&&(r[b++]=(c<<8-u)+(s&(1<<8-u)-1))}this.bufferLength+=e}};e.prototype.readBlockPng=function(){var e=this.rowBytes,t=this.pixBytes,r=this.str.getByte(),i=this.str.getBytes(e);this.eof=!i.length;if(!this.eof){var n=this.bufferLength,o=this.ensureBuffer(n+e),s=o.subarray(n-e,n);0===s.length&&(s=new Uint8Array(e));var c,l,u,h=n;switch(r){case 0:for(c=0;c<e;++c)o[h++]=i[c];break;case 1:for(c=0;c<t;++c)o[h++]=i[c];for(;c<e;++c){o[h]=o[h-t]+i[c]&255;h++}break;case 2:for(c=0;c<e;++c)o[h++]=s[c]+i[c]&255;break;case 3:for(c=0;c<t;++c)o[h++]=(s[c]>>1)+i[c];for(;c<e;++c){o[h]=(s[c]+o[h-t]>>1)+i[c]&255;h++}break;case 4:for(c=0;c<t;++c){l=s[c];u=i[c];o[h++]=l+u}for(;c<e;++c){l=s[c];var f=s[c-t],d=o[h-t],g=d+l-f,m=g-d;m<0&&(m=-m);var p=g-l;p<0&&(p=-p);var v=g-f;v<0&&(v=-v);u=i[c];o[h++]=m<=p&&m<=v?d+u:p<=v?l+u:f+u}break;default:throw new a.FormatError("Unsupported predictor: "+r)}this.bufferLength+=e}};return e}(),f=function(){function e(e,t,r){this.str=e;this.dict=e.dict;this.decrypt=r;this.nextChunk=null;this.initialized=!1;c.call(this,t)}e.prototype=Object.create(c.prototype);e.prototype.readBlock=function(){var e;if(this.initialized)e=this.nextChunk;else{e=this.str.getBytes(512);this.initialized=!0}if(e&&0!==e.length){this.nextChunk=this.str.getBytes(512);var t=this.nextChunk&&this.nextChunk.length>0;e=(0,this.decrypt)(e,!t);var r,a=this.bufferLength,i=e.length,n=this.ensureBuffer(a+i);for(r=0;r<i;r++)n[a++]=e[r];this.bufferLength=a}else this.eof=!0};return e}(),d=function(){function e(e,t){this.str=e;this.dict=e.dict;this.input=new Uint8Array(5);t&&(t*=.8);c.call(this,t)}e.prototype=Object.create(c.prototype);e.prototype.readBlock=function(){for(var e=this.str,t=e.getByte();(0,a.isSpace)(t);)t=e.getByte();if(-1!==t&&126!==t){var r,i,n=this.bufferLength;if(122===t){r=this.ensureBuffer(n+4);for(i=0;i<4;++i)r[n+i]=0;this.bufferLength+=4}else{var o=this.input;o[0]=t;for(i=1;i<5;++i){t=e.getByte();for(;(0,a.isSpace)(t);)t=e.getByte();o[i]=t;if(-1===t||126===t)break}r=this.ensureBuffer(n+i-1);this.bufferLength+=i-1;if(i<5){for(;i<5;++i)o[i]=117;this.eof=!0}var s=0;for(i=0;i<5;++i)s=85*s+(o[i]-33);for(i=3;i>=0;--i){r[n+i]=255&s;s>>=8}}}else this.eof=!0};return e}(),g=function(){function e(e,t){this.str=e;this.dict=e.dict;this.firstDigit=-1;t&&(t*=.5);c.call(this,t)}e.prototype=Object.create(c.prototype);e.prototype.readBlock=function(){var e=this.str.getBytes(8e3);if(e.length){for(var t=e.length+1>>1,r=this.ensureBuffer(this.bufferLength+t),a=this.bufferLength,i=this.firstDigit,n=0,o=e.length;n<o;n++){var s,c=e[n];if(c>=48&&c<=57)s=15&c;else{if(!(c>=65&&c<=70||c>=97&&c<=102)){if(62===c){this.eof=!0;break}continue}s=9+(15&c)}if(i<0)i=s;else{r[a++]=i<<4|s;i=-1}}if(i>=0&&this.eof){r[a++]=i<<4;i=-1}this.firstDigit=i;this.bufferLength=a}else this.eof=!0};return e}(),m=function(){function e(e,t){this.str=e;this.dict=e.dict;c.call(this,t)}e.prototype=Object.create(c.prototype);e.prototype.readBlock=function(){var e=this.str.getBytes(2);if(!e||e.length<2||128===e[0])this.eof=!0;else{var t,r=this.bufferLength,a=e[0];if(a<128){(t=this.ensureBuffer(r+a+1))[r++]=e[1];if(a>0){var i=this.str.getBytes(a);t.set(i,r);r+=a}}else{a=257-a;var n=e[1];t=this.ensureBuffer(r+a+1);for(var o=0;o<a;o++)t[r++]=n}this.bufferLength=r}};return e}(),p=function(){function e(e,t,r){this.str=e;this.dict=e.dict;this.cachedData=0;this.bitsCached=0;for(var a={earlyChange:r,codeLength:9,nextCode:258,dictionaryValues:new Uint8Array(4096),dictionaryLengths:new Uint16Array(4096),dictionaryPrevCodes:new Uint16Array(4096),currentSequence:new Uint8Array(4096),currentSequenceLength:0},i=0;i<256;++i){a.dictionaryValues[i]=i;a.dictionaryLengths[i]=1}this.lzwState=a;c.call(this,t)}e.prototype=Object.create(c.prototype);e.prototype.readBits=function(e){for(var t=this.bitsCached,r=this.cachedData;t<e;){var a=this.str.getByte();if(-1===a){this.eof=!0;return null}r=r<<8|a;t+=8}this.bitsCached=t-=e;this.cachedData=r;this.lastCode=null;return r>>>t&(1<<e)-1};e.prototype.readBlock=function(){var e,t,r,a=1024,i=this.lzwState;if(i){var n=i.earlyChange,o=i.nextCode,s=i.dictionaryValues,c=i.dictionaryLengths,l=i.dictionaryPrevCodes,u=i.codeLength,h=i.prevCode,f=i.currentSequence,d=i.currentSequenceLength,g=0,m=this.bufferLength,p=this.ensureBuffer(this.bufferLength+a);for(e=0;e<512;e++){var v=this.readBits(u),b=d>0;if(v<256){f[0]=v;d=1}else{if(!(v>=258)){if(256===v){u=9;o=258;d=0;continue}this.eof=!0;delete this.lzwState;break}if(v<o)for(t=(d=c[v])-1,r=v;t>=0;t--){f[t]=s[r];r=l[r]}else f[d++]=f[0]}if(b){l[o]=h;c[o]=c[h]+1;s[o]=f[0];u=++o+n&o+n-1?u:0|Math.min(Math.log(o+n)/.6931471805599453+1,12)}h=v;if(a<(g+=d)){do{a+=512}while(a<g);p=this.ensureBuffer(this.bufferLength+a)}for(t=0;t<d;t++)p[m++]=f[t]}i.nextCode=o;i.codeLength=u;i.prevCode=h;i.currentSequenceLength=d;this.bufferLength=m}};return e}(),v=function(){function e(){o.call(this,new Uint8Array(0))}e.prototype=o.prototype;return e}();t.Ascii85Stream=d;t.AsciiHexStream=g;t.DecryptStream=f;t.DecodeStream=c;t.FlateStream=u;t.NullStream=v;t.PredictorStream=h;t.RunLengthStream=m;t.Stream=o;t.StreamsSequenceStream=l;t.StringStream=s;t.LZWStream=p},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.CCITTFaxStream=void 0;var a=r(138),i=r(142),n=r(140),o=function(){function e(e,t,r){this.str=e;this.dict=e.dict;(0,a.isDict)(r)||(r=a.Dict.empty);var o={next:function(){return e.getByte()}};this.ccittFaxDecoder=new i.CCITTFaxDecoder(o,{K:r.get("K"),EndOfLine:r.get("EndOfLine"),EncodedByteAlign:r.get("EncodedByteAlign"),Columns:r.get("Columns"),Rows:r.get("Rows"),EndOfBlock:r.get("EndOfBlock"),BlackIs1:r.get("BlackIs1")});n.DecodeStream.call(this,t)}e.prototype=Object.create(n.DecodeStream.prototype);e.prototype.readBlock=function(){for(;!this.eof;){var e=this.ccittFaxDecoder.readNextChar();if(-1===e){this.eof=!0;return}this.ensureBuffer(this.bufferLength+1);this.buffer[this.bufferLength++]=e}};return e}();t.CCITTFaxStream=o},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.CCITTFaxDecoder=void 0;var a=r(2),i=function(){var e=[[-1,-1],[-1,-1],[7,8],[7,7],[6,6],[6,6],[6,5],[6,5],[4,0],[4,0],[4,0],[4,0],[4,0],[4,0],[4,0],[4,0],[3,1],[3,1],[3,1],[3,1],[3,1],[3,1],[3,1],[3,1],[3,1],[3,1],[3,1],[3,1],[3,1],[3,1],[3,1],[3,1],[3,4],[3,4],[3,4],[3,4],[3,4],[3,4],[3,4],[3,4],[3,4],[3,4],[3,4],[3,4],[3,4],[3,4],[3,4],[3,4],[3,3],[3,3],[3,3],[3,3],[3,3],[3,3],[3,3],[3,3],[3,3],[3,3],[3,3],[3,3],[3,3],[3,3],[3,3],[3,3],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2],[1,2]],t=[[-1,-1],[12,-2],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[11,1792],[11,1792],[12,1984],[12,2048],[12,2112],[12,2176],[12,2240],[12,2304],[11,1856],[11,1856],[11,1920],[11,1920],[12,2368],[12,2432],[12,2496],[12,2560]],r=[[-1,-1],[-1,-1],[-1,-1],[-1,-1],[8,29],[8,29],[8,30],[8,30],[8,45],[8,45],[8,46],[8,46],[7,22],[7,22],[7,22],[7,22],[7,23],[7,23],[7,23],[7,23],[8,47],[8,47],[8,48],[8,48],[6,13],[6,13],[6,13],[6,13],[6,13],[6,13],[6,13],[6,13],[7,20],[7,20],[7,20],[7,20],[8,33],[8,33],[8,34],[8,34],[8,35],[8,35],[8,36],[8,36],[8,37],[8,37],[8,38],[8,38],[7,19],[7,19],[7,19],[7,19],[8,31],[8,31],[8,32],[8,32],[6,1],[6,1],[6,1],[6,1],[6,1],[6,1],[6,1],[6,1],[6,12],[6,12],[6,12],[6,12],[6,12],[6,12],[6,12],[6,12],[8,53],[8,53],[8,54],[8,54],[7,26],[7,26],[7,26],[7,26],[8,39],[8,39],[8,40],[8,40],[8,41],[8,41],[8,42],[8,42],[8,43],[8,43],[8,44],[8,44],[7,21],[7,21],[7,21],[7,21],[7,28],[7,28],[7,28],[7,28],[8,61],[8,61],[8,62],[8,62],[8,63],[8,63],[8,0],[8,0],[8,320],[8,320],[8,384],[8,384],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,10],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[5,11],[7,27],[7,27],[7,27],[7,27],[8,59],[8,59],[8,60],[8,60],[9,1472],[9,1536],[9,1600],[9,1728],[7,18],[7,18],[7,18],[7,18],[7,24],[7,24],[7,24],[7,24],[8,49],[8,49],[8,50],[8,50],[8,51],[8,51],[8,52],[8,52],[7,25],[7,25],[7,25],[7,25],[8,55],[8,55],[8,56],[8,56],[8,57],[8,57],[8,58],[8,58],[6,192],[6,192],[6,192],[6,192],[6,192],[6,192],[6,192],[6,192],[6,1664],[6,1664],[6,1664],[6,1664],[6,1664],[6,1664],[6,1664],[6,1664],[8,448],[8,448],[8,512],[8,512],[9,704],[9,768],[8,640],[8,640],[8,576],[8,576],[9,832],[9,896],[9,960],[9,1024],[9,1088],[9,1152],[9,1216],[9,1280],[9,1344],[9,1408],[7,256],[7,256],[7,256],[7,256],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,2],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,128],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,8],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[5,9],[6,16],[6,16],[6,16],[6,16],[6,16],[6,16],[6,16],[6,16],[6,17],[6,17],[6,17],[6,17],[6,17],[6,17],[6,17],[6,17],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,4],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[4,5],[6,14],[6,14],[6,14],[6,14],[6,14],[6,14],[6,14],[6,14],[6,15],[6,15],[6,15],[6,15],[6,15],[6,15],[6,15],[6,15],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[5,64],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,6],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7],[4,7]],i=[[-1,-1],[-1,-1],[12,-2],[12,-2],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[-1,-1],[11,1792],[11,1792],[11,1792],[11,1792],[12,1984],[12,1984],[12,2048],[12,2048],[12,2112],[12,2112],[12,2176],[12,2176],[12,2240],[12,2240],[12,2304],[12,2304],[11,1856],[11,1856],[11,1856],[11,1856],[11,1920],[11,1920],[11,1920],[11,1920],[12,2368],[12,2368],[12,2432],[12,2432],[12,2496],[12,2496],[12,2560],[12,2560],[10,18],[10,18],[10,18],[10,18],[10,18],[10,18],[10,18],[10,18],[12,52],[12,52],[13,640],[13,704],[13,768],[13,832],[12,55],[12,55],[12,56],[12,56],[13,1280],[13,1344],[13,1408],[13,1472],[12,59],[12,59],[12,60],[12,60],[13,1536],[13,1600],[11,24],[11,24],[11,24],[11,24],[11,25],[11,25],[11,25],[11,25],[13,1664],[13,1728],[12,320],[12,320],[12,384],[12,384],[12,448],[12,448],[13,512],[13,576],[12,53],[12,53],[12,54],[12,54],[13,896],[13,960],[13,1024],[13,1088],[13,1152],[13,1216],[10,64],[10,64],[10,64],[10,64],[10,64],[10,64],[10,64],[10,64]],n=[[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[8,13],[11,23],[11,23],[12,50],[12,51],[12,44],[12,45],[12,46],[12,47],[12,57],[12,58],[12,61],[12,256],[10,16],[10,16],[10,16],[10,16],[10,17],[10,17],[10,17],[10,17],[12,48],[12,49],[12,62],[12,63],[12,30],[12,31],[12,32],[12,33],[12,40],[12,41],[11,22],[11,22],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[8,14],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,10],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[7,11],[9,15],[9,15],[9,15],[9,15],[9,15],[9,15],[9,15],[9,15],[12,128],[12,192],[12,26],[12,27],[12,28],[12,29],[11,19],[11,19],[11,20],[11,20],[12,34],[12,35],[12,36],[12,37],[12,38],[12,39],[11,21],[11,21],[12,42],[12,43],[10,0],[10,0],[10,0],[10,0],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12],[7,12]],o=[[-1,-1],[-1,-1],[-1,-1],[-1,-1],[6,9],[6,8],[5,7],[5,7],[4,6],[4,6],[4,6],[4,6],[4,5],[4,5],[4,5],[4,5],[3,1],[3,1],[3,1],[3,1],[3,1],[3,1],[3,1],[3,1],[3,4],[3,4],[3,4],[3,4],[3,4],[3,4],[3,4],[3,4],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,3],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2]];function s(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!e||"function"!=typeof e.next)throw new Error('CCITTFaxDecoder - invalid "source" parameter.');this.source=e;this.eof=!1;this.encoding=t.K||0;this.eoline=t.EndOfLine||!1;this.byteAlign=t.EncodedByteAlign||!1;this.columns=t.Columns||1728;this.rows=t.Rows||0;var r=t.EndOfBlock;null!==r&&void 0!==r||(r=!0);this.eoblock=r;this.black=t.BlackIs1||!1;this.codingLine=new Uint32Array(this.columns+1);this.refLine=new Uint32Array(this.columns+2);this.codingLine[0]=this.columns;this.codingPos=0;this.row=0;this.nextLine2D=this.encoding<0;this.inputBits=0;this.inputBuf=0;this.outputBits=0;this.rowsDone=!1;for(var a=void 0;0===(a=this._lookBits(12));)this._eatBits(1);1===a&&this._eatBits(12);if(this.encoding>0){this.nextLine2D=!this._lookBits(1);this._eatBits(1)}}s.prototype={readNextChar:function(){if(this.eof)return-1;var e=this.refLine,t=this.codingLine,r=this.columns,i=void 0,n=void 0,o=void 0,s=void 0;if(0===this.outputBits){this.rowsDone&&(this.eof=!0);if(this.eof)return-1;this.err=!1;var c=void 0,l=void 0,u=void 0;if(this.nextLine2D){for(s=0;t[s]<r;++s)e[s]=t[s];e[s++]=r;e[s]=r;t[0]=0;this.codingPos=0;i=0;n=0;for(;t[this.codingPos]<r;)switch(c=this._getTwoDimCode()){case 0:this._addPixels(e[i+1],n);e[i+1]<r&&(i+=2);break;case 1:c=l=0;if(n){do{c+=u=this._getBlackCode()}while(u>=64);do{l+=u=this._getWhiteCode()}while(u>=64)}else{do{c+=u=this._getWhiteCode()}while(u>=64);do{l+=u=this._getBlackCode()}while(u>=64)}this._addPixels(t[this.codingPos]+c,n);t[this.codingPos]<r&&this._addPixels(t[this.codingPos]+l,1^n);for(;e[i]<=t[this.codingPos]&&e[i]<r;)i+=2;break;case 7:this._addPixels(e[i]+3,n);n^=1;if(t[this.codingPos]<r){++i;for(;e[i]<=t[this.codingPos]&&e[i]<r;)i+=2}break;case 5:this._addPixels(e[i]+2,n);n^=1;if(t[this.codingPos]<r){++i;for(;e[i]<=t[this.codingPos]&&e[i]<r;)i+=2}break;case 3:this._addPixels(e[i]+1,n);n^=1;if(t[this.codingPos]<r){++i;for(;e[i]<=t[this.codingPos]&&e[i]<r;)i+=2}break;case 2:this._addPixels(e[i],n);n^=1;if(t[this.codingPos]<r){++i;for(;e[i]<=t[this.codingPos]&&e[i]<r;)i+=2}break;case 8:this._addPixelsNeg(e[i]-3,n);n^=1;if(t[this.codingPos]<r){i>0?--i:++i;for(;e[i]<=t[this.codingPos]&&e[i]<r;)i+=2}break;case 6:this._addPixelsNeg(e[i]-2,n);n^=1;if(t[this.codingPos]<r){i>0?--i:++i;for(;e[i]<=t[this.codingPos]&&e[i]<r;)i+=2}break;case 4:this._addPixelsNeg(e[i]-1,n);n^=1;if(t[this.codingPos]<r){i>0?--i:++i;for(;e[i]<=t[this.codingPos]&&e[i]<r;)i+=2}break;case-1:this._addPixels(r,0);this.eof=!0;break;default:(0,a.info)("bad 2d code");this._addPixels(r,0);this.err=!0}}else{t[0]=0;this.codingPos=0;n=0;for(;t[this.codingPos]<r;){c=0;if(n)do{c+=u=this._getBlackCode()}while(u>=64);else do{c+=u=this._getWhiteCode()}while(u>=64);this._addPixels(t[this.codingPos]+c,n);n^=1}}var h=!1;this.byteAlign&&(this.inputBits&=-8);if(this.eoblock||this.row!==this.rows-1){c=this._lookBits(12);if(this.eoline)for(;-1!==c&&1!==c;){this._eatBits(1);c=this._lookBits(12)}else for(;0===c;){this._eatBits(1);c=this._lookBits(12)}if(1===c){this._eatBits(12);h=!0}else-1===c&&(this.eof=!0)}else this.rowsDone=!0;if(!this.eof&&this.encoding>0&&!this.rowsDone){this.nextLine2D=!this._lookBits(1);this._eatBits(1)}if(this.eoblock&&h&&this.byteAlign){if(1===(c=this._lookBits(12))){this._eatBits(12);if(this.encoding>0){this._lookBits(1);this._eatBits(1)}if(this.encoding>=0)for(s=0;s<4;++s){1!==(c=this._lookBits(12))&&(0,a.info)("bad rtc code: "+c);this._eatBits(12);if(this.encoding>0){this._lookBits(1);this._eatBits(1)}}this.eof=!0}}else if(this.err&&this.eoline){for(;;){if(-1===(c=this._lookBits(13))){this.eof=!0;return-1}if(c>>1==1)break;this._eatBits(1)}this._eatBits(12);if(this.encoding>0){this._eatBits(1);this.nextLine2D=!(1&c)}}t[0]>0?this.outputBits=t[this.codingPos=0]:this.outputBits=t[this.codingPos=1];this.row++}var f=void 0;if(this.outputBits>=8){f=1&this.codingPos?0:255;this.outputBits-=8;if(0===this.outputBits&&t[this.codingPos]<r){this.codingPos++;this.outputBits=t[this.codingPos]-t[this.codingPos-1]}}else{o=8;f=0;do{if(this.outputBits>o){f<<=o;1&this.codingPos||(f|=255>>8-o);this.outputBits-=o;o=0}else{f<<=this.outputBits;1&this.codingPos||(f|=255>>8-this.outputBits);o-=this.outputBits;this.outputBits=0;if(t[this.codingPos]<r){this.codingPos++;this.outputBits=t[this.codingPos]-t[this.codingPos-1]}else if(o>0){f<<=o;o=0}}}while(o)}this.black&&(f^=255);return f},_addPixels:function(e,t){var r=this.codingLine,i=this.codingPos;if(e>r[i]){if(e>this.columns){(0,a.info)("row is wrong length");this.err=!0;e=this.columns}1&i^t&&++i;r[i]=e}this.codingPos=i},_addPixelsNeg:function(e,t){var r=this.codingLine,i=this.codingPos;if(e>r[i]){if(e>this.columns){(0,a.info)("row is wrong length");this.err=!0;e=this.columns}1&i^t&&++i;r[i]=e}else if(e<r[i]){if(e<0){(0,a.info)("invalid code");this.err=!0;e=0}for(;i>0&&e<r[i-1];)--i;r[i]=e}this.codingPos=i},_findTableCode:function(e,t,r,a){for(var i=a||0,n=e;n<=t;++n){var o=this._lookBits(n);if(-1===o)return[!0,1,!1];n<t&&(o<<=t-n);if(!i||o>=i){var s=r[o-i];if(s[0]===n){this._eatBits(n);return[!0,s[1],!0]}}}return[!1,0,!1]},_getTwoDimCode:function(){var t=0,r=void 0;if(this.eoblock){t=this._lookBits(7);if((r=e[t])&&r[0]>0){this._eatBits(r[0]);return r[1]}}else{var i=this._findTableCode(1,7,e);if(i[0]&&i[2])return i[1]}(0,a.info)("Bad two dim code");return-1},_getWhiteCode:function(){var e=0,i=void 0;if(this.eoblock){if(-1===(e=this._lookBits(12)))return 1;if((i=e>>5==0?t[e]:r[e>>3])[0]>0){this._eatBits(i[0]);return i[1]}}else{var n=this._findTableCode(1,9,r);if(n[0])return n[1];if((n=this._findTableCode(11,12,t))[0])return n[1]}(0,a.info)("bad white code");this._eatBits(1);return 1},_getBlackCode:function(){var e=void 0,t=void 0;if(this.eoblock){if(-1===(e=this._lookBits(13)))return 1;if((t=e>>7==0?i[e]:e>>9==0&&e>>7!=0?n[(e>>1)-64]:o[e>>7])[0]>0){this._eatBits(t[0]);return t[1]}}else{var r=this._findTableCode(2,6,o);if(r[0])return r[1];if((r=this._findTableCode(7,12,n,64))[0])return r[1];if((r=this._findTableCode(10,13,i))[0])return r[1]}(0,a.info)("bad black code");this._eatBits(1);return 1},_lookBits:function(e){for(var t=void 0;this.inputBits<e;){if(-1===(t=this.source.next()))return 0===this.inputBits?-1:this.inputBuf<<e-this.inputBits&65535>>16-e;this.inputBuf=this.inputBuf<<8|t;this.inputBits+=8}return this.inputBuf>>this.inputBits-e&65535>>16-e},_eatBits:function(e){(this.inputBits-=e)<0&&(this.inputBits=0)}};return s}();t.CCITTFaxDecoder=i},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.Jbig2Stream=void 0;var a=r(138),i=r(140),n=r(144),o=r(2),s=function(){function e(e,t,r,a){this.stream=e;this.maybeLength=t;this.dict=r;this.params=a;i.DecodeStream.call(this,t)}e.prototype=Object.create(i.DecodeStream.prototype);Object.defineProperty(e.prototype,"bytes",{get:function(){return(0,o.shadow)(this,"bytes",this.stream.getBytes(this.maybeLength))},configurable:!0});e.prototype.ensureBuffer=function(e){};e.prototype.readBlock=function(){if(!this.eof){var e=new n.Jbig2Image,t=[];if((0,a.isDict)(this.params)){var r=this.params.get("JBIG2Globals");if((0,a.isStream)(r)){var i=r.getBytes();t.push({data:i,start:0,end:i.length})}}t.push({data:this.bytes,start:0,end:this.bytes.length});for(var o=e.parseChunks(t),s=o.length,c=0;c<s;c++)o[c]^=255;this.buffer=o;this.bufferLength=s;this.eof=!0}};return e}();t.Jbig2Stream=s},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.Jbig2Image=void 0;var a=r(2),i=r(145),n=r(142),o=function(){function e(e){this.message="JBIG2 error: "+e}e.prototype=new Error;e.prototype.name="Jbig2Error";e.constructor=e;return e}(),s=function(){function e(){}e.prototype={getContexts:function(e){return e in this?this[e]:this[e]=new Int8Array(65536)}};function t(e,t,r){this.data=e;this.start=t;this.end=r}t.prototype={get decoder(){var e=new i.ArithmeticDecoder(this.data,this.start,this.end);return(0,a.shadow)(this,"decoder",e)},get contextCache(){var t=new e;return(0,a.shadow)(this,"contextCache",t)}};function r(e,t,r){var a=e.getContexts(t),i=1;function n(e){for(var t=0,n=0;n<e;n++){var o=r.readBit(a,i);i=i<256?i<<1|o:511&(i<<1|o)|256;t=t<<1|o}return t>>>0}var o=n(1),s=n(1)?n(1)?n(1)?n(1)?n(1)?n(32)+4436:n(12)+340:n(8)+84:n(6)+20:n(4)+4:n(2);return 0===o?s:s>0?-s:null}function s(e,t,r){for(var a=e.getContexts("IAID"),i=1,n=0;n<r;n++){i=i<<1|t.readBit(a,i)}return r<31?i&(1<<r)-1:2147483647&i}var c=["SymbolDictionary",null,null,null,"IntermediateTextRegion",null,"ImmediateTextRegion","ImmediateLosslessTextRegion",null,null,null,null,null,null,null,null,"PatternDictionary",null,null,null,"IntermediateHalftoneRegion",null,"ImmediateHalftoneRegion","ImmediateLosslessHalftoneRegion",null,null,null,null,null,null,null,null,null,null,null,null,"IntermediateGenericRegion",null,"ImmediateGenericRegion","ImmediateLosslessGenericRegion","IntermediateGenericRefinementRegion",null,"ImmediateGenericRefinementRegion","ImmediateLosslessGenericRefinementRegion",null,null,null,null,"PageInformation","EndOfPage","EndOfStripe","EndOfFile","Profiles","Tables",null,null,null,null,null,null,null,null,"Extension"],l=[[{x:-1,y:-2},{x:0,y:-2},{x:1,y:-2},{x:-2,y:-1},{x:-1,y:-1},{x:0,y:-1},{x:1,y:-1},{x:2,y:-1},{x:-4,y:0},{x:-3,y:0},{x:-2,y:0},{x:-1,y:0}],[{x:-1,y:-2},{x:0,y:-2},{x:1,y:-2},{x:2,y:-2},{x:-2,y:-1},{x:-1,y:-1},{x:0,y:-1},{x:1,y:-1},{x:2,y:-1},{x:-3,y:0},{x:-2,y:0},{x:-1,y:0}],[{x:-1,y:-2},{x:0,y:-2},{x:1,y:-2},{x:-2,y:-1},{x:-1,y:-1},{x:0,y:-1},{x:1,y:-1},{x:-2,y:0},{x:-1,y:0}],[{x:-3,y:-1},{x:-2,y:-1},{x:-1,y:-1},{x:0,y:-1},{x:1,y:-1},{x:-4,y:0},{x:-3,y:0},{x:-2,y:0},{x:-1,y:0}]],u=[{coding:[{x:0,y:-1},{x:1,y:-1},{x:-1,y:0}],reference:[{x:0,y:-1},{x:1,y:-1},{x:-1,y:0},{x:0,y:0},{x:1,y:0},{x:-1,y:1},{x:0,y:1},{x:1,y:1}]},{coding:[{x:-1,y:-1},{x:0,y:-1},{x:1,y:-1},{x:-1,y:0}],reference:[{x:0,y:-1},{x:-1,y:0},{x:0,y:0},{x:1,y:0},{x:0,y:1},{x:1,y:1}]}],h=[39717,1941,229,405],f=[32,8];function d(e,t,r,a,i,n,o,s){if(e){return E(new I(s.data,s.start,s.end),t,r,!1)}if(0===a&&!n&&!i&&4===o.length&&3===o[0].x&&-1===o[0].y&&-3===o[1].x&&-1===o[1].y&&2===o[2].x&&-2===o[2].y&&-2===o[3].x&&-2===o[3].y)return function(e,t,r){var a,i,n,o,s,c,l,u=r.decoder,h=r.contextCache.getContexts("GB"),f=[];for(i=0;i<t;i++){s=f[i]=new Uint8Array(e);c=i<1?s:f[i-1];a=(l=i<2?s:f[i-2])[0]<<13|l[1]<<12|l[2]<<11|c[0]<<7|c[1]<<6|c[2]<<5|c[3]<<4;for(n=0;n<e;n++){s[n]=o=u.readBit(h,a);a=(31735&a)<<1|(n+3<e?l[n+3]<<11:0)|(n+4<e?c[n+4]<<4:0)|o}}return f}(t,r,s);var c=!!n,u=l[a].concat(o);u.sort(function(e,t){return e.y-t.y||e.x-t.x});var f,d,g=u.length,m=new Int8Array(g),p=new Int8Array(g),v=[],b=0,y=0,w=0,k=0;for(d=0;d<g;d++){m[d]=u[d].x;p[d]=u[d].y;y=Math.min(y,u[d].x);w=Math.max(w,u[d].x);k=Math.min(k,u[d].y);d<g-1&&u[d].y===u[d+1].y&&u[d].x===u[d+1].x-1?b|=1<<g-1-d:v.push(d)}var S=v.length,C=new Int8Array(S),x=new Int8Array(S),_=new Uint16Array(S);for(f=0;f<S;f++){d=v[f];C[f]=u[d].x;x[f]=u[d].y;_[f]=1<<g-1-d}for(var A,P,O,T,F,R=-y,B=-k,D=t-w,M=h[a],L=new Uint8Array(t),N=[],U=s.decoder,q=s.contextCache.getContexts("GB"),j=0,z=0,H=0;H<r;H++){if(i){if(j^=U.readBit(q,M)){N.push(L);continue}}L=new Uint8Array(L);N.push(L);for(A=0;A<t;A++)if(c&&n[H][A])L[A]=0;else{if(A>=R&&A<D&&H>=B){z=z<<1&b;for(d=0;d<S;d++){P=H+x[d];O=A+C[d];(T=N[P][O])&&(z|=T=_[d])}}else{z=0;F=g-1;for(d=0;d<g;d++,F--)(O=A+m[d])>=0&&O<t&&(P=H+p[d])>=0&&(T=N[P][O])&&(z|=T<<F)}var G=U.readBit(q,z);L[A]=G}}return N}function g(e,t,r,a,i,n,s,c,l){var h=u[r].coding;0===r&&(h=h.concat([c[0]]));var d,g=h.length,m=new Int32Array(g),p=new Int32Array(g);for(d=0;d<g;d++){m[d]=h[d].x;p[d]=h[d].y}var v=u[r].reference;0===r&&(v=v.concat([c[1]]));var b=v.length,y=new Int32Array(b),w=new Int32Array(b);for(d=0;d<b;d++){y[d]=v[d].x;w[d]=v[d].y}for(var k=a[0].length,S=a.length,C=f[r],x=[],_=l.decoder,A=l.contextCache.getContexts("GR"),P=0,I=0;I<t;I++){if(s){if(P^=_.readBit(A,C))throw new o("prediction is not supported")}var O=new Uint8Array(e);x.push(O);for(var T=0;T<e;T++){var E,F,R=0;for(d=0;d<g;d++){E=I+p[d];F=T+m[d];E<0||F<0||F>=e?R<<=1:R=R<<1|x[E][F]}for(d=0;d<b;d++){E=I+w[d]-n;F=T+y[d]-i;E<0||E>=S||F<0||F>=k?R<<=1:R=R<<1|a[E][F]}var B=_.readBit(A,R);O[T]=B}}return x}function m(e,t,a,i,n,c,l,u,h,f,d,m,p,v,b,y,w,k,S){if(e&&t)throw new o("refinement with Huffman is not supported");var C,x,_=[];for(C=0;C<i;C++){x=new Uint8Array(a);if(n)for(var A=0;A<a;A++)x[A]=n;_.push(x)}var P=w.decoder,I=w.contextCache,O=e?-v.tableDeltaT.decode(S):-r(I,"IADT",P),T=0;C=0;for(;C<c;){O+=e?v.tableDeltaT.decode(S):r(I,"IADT",P);for(var E=T+=e?v.tableFirstS.decode(S):r(I,"IAFS",P);;){var F=0;l>1&&(F=e?S.readBits(k):r(I,"IAIT",P));var R=l*O+F,B=e?v.symbolIDTable.decode(S):s(I,P,h),D=t&&(e?S.readBit():r(I,"IARI",P)),M=u[B],L=M[0].length,N=M.length;if(D){var U=r(I,"IARDW",P),q=r(I,"IARDH",P);M=g(L+=U,N+=q,b,M,(U>>1)+r(I,"IARDX",P),(q>>1)+r(I,"IARDY",P),!1,y,w)}var j,z,H,G=R-(1&m?0:N-1),W=E-(2&m?L-1:0);if(f){for(j=0;j<N;j++)if(x=_[W+j]){H=M[j];var X=Math.min(a-G,L);switch(p){case 0:for(z=0;z<X;z++)x[G+z]|=H[z];break;case 2:for(z=0;z<X;z++)x[G+z]^=H[z];break;default:throw new o("operator "+p+" is not supported")}}E+=N-1}else{for(z=0;z<N;z++)if(x=_[G+z]){H=M[z];switch(p){case 0:for(j=0;j<L;j++)x[W+j]|=H[j];break;case 2:for(j=0;j<L;j++)x[W+j]^=H[j];break;default:throw new o("operator "+p+" is not supported")}}E+=L-1}C++;var V=e?v.tableDeltaS.decode(S):r(I,"IADS",P);if(null===V)break;E+=V+d}}return _}function p(e,t){var r={};r.number=(0,a.readUint32)(e,t);var i=e[t+4],n=63&i;if(!c[n])throw new o("invalid segment type: "+n);r.type=n;r.typeName=c[n];r.deferredNonRetain=!!(128&i);var s=!!(64&i),l=e[t+5],u=l>>5&7,h=[31&l],f=t+6;if(7===l){u=536870911&(0,a.readUint32)(e,f-1);f+=3;var d=u+7>>3;h[0]=e[f++];for(;--d>0;)h.push(e[f++])}else if(5===l||6===l)throw new o("invalid referred-to flags");r.retainBits=h;var g,m,p=r.number<=256?1:r.number<=65536?2:4,v=[];for(g=0;g<u;g++){var w=1===p?e[f]:2===p?(0,a.readUint16)(e,f):(0,a.readUint32)(e,f);v.push(w);f+=p}r.referredTo=v;if(s){r.pageAssociation=(0,a.readUint32)(e,f);f+=4}else r.pageAssociation=e[f++];r.length=(0,a.readUint32)(e,f);f+=4;if(4294967295===r.length){if(38!==n)throw new o("invalid unknown segment length");var k=b(e,f),S=!!(1&e[f+y]),C=new Uint8Array(6);if(!S){C[0]=255;C[1]=172}C[2]=k.height>>>24&255;C[3]=k.height>>16&255;C[4]=k.height>>8&255;C[5]=255&k.height;for(g=f,m=e.length;g<m;g++){for(var x=0;x<6&&C[x]===e[g+x];)x++;if(6===x){r.length=g+6;break}}if(4294967295===r.length)throw new o("segment end was not found")}r.headerEnd=f;return r}function v(e,t,r,a){for(var i=[],n=r;n<a;){var o=p(t,n);n=o.headerEnd;var s={header:o,data:t};if(!e.randomAccess){s.start=n;n+=o.length;s.end=n}i.push(s);if(51===o.type)break}if(e.randomAccess)for(var c=0,l=i.length;c<l;c++){i[c].start=n;n+=i[c].header.length;i[c].end=n}return i}function b(e,t){return{width:(0,a.readUint32)(e,t),height:(0,a.readUint32)(e,t+4),x:(0,a.readUint32)(e,t+8),y:(0,a.readUint32)(e,t+12),combinationOperator:7&e[t+16]}}var y=17;function w(e,t){var r,i,n,s,c=e.header,l=e.data,u=e.start,h=e.end;switch(c.type){case 0:var f={},d=(0,a.readUint16)(l,u);f.huffman=!!(1&d);f.refinement=!!(2&d);f.huffmanDHSelector=d>>2&3;f.huffmanDWSelector=d>>4&3;f.bitmapSizeSelector=d>>6&1;f.aggregationInstancesSelector=d>>7&1;f.bitmapCodingContextUsed=!!(256&d);f.bitmapCodingContextRetained=!!(512&d);f.template=d>>10&3;f.refinementTemplate=d>>12&1;u+=2;if(!f.huffman){s=0===f.template?4:1;i=[];for(n=0;n<s;n++){i.push({x:(0,a.readInt8)(l,u),y:(0,a.readInt8)(l,u+1)});u+=2}f.at=i}if(f.refinement&&!f.refinementTemplate){i=[];for(n=0;n<2;n++){i.push({x:(0,a.readInt8)(l,u),y:(0,a.readInt8)(l,u+1)});u+=2}f.refinementAt=i}f.numberOfExportedSymbols=(0,a.readUint32)(l,u);u+=4;f.numberOfNewSymbols=(0,a.readUint32)(l,u);u+=4;r=[f,c.number,c.referredTo,l,u,h];break;case 6:case 7:var g={};g.info=b(l,u);u+=y;var m=(0,a.readUint16)(l,u);u+=2;g.huffman=!!(1&m);g.refinement=!!(2&m);g.logStripSize=m>>2&3;g.stripSize=1<<g.logStripSize;g.referenceCorner=m>>4&3;g.transposed=!!(64&m);g.combinationOperator=m>>7&3;g.defaultPixelValue=m>>9&1;g.dsOffset=m<<17>>27;g.refinementTemplate=m>>15&1;if(g.huffman){var p=(0,a.readUint16)(l,u);u+=2;g.huffmanFS=3&p;g.huffmanDS=p>>2&3;g.huffmanDT=p>>4&3;g.huffmanRefinementDW=p>>6&3;g.huffmanRefinementDH=p>>8&3;g.huffmanRefinementDX=p>>10&3;g.huffmanRefinementDY=p>>12&3;g.huffmanRefinementSizeSelector=!!(16384&p)}if(g.refinement&&!g.refinementTemplate){i=[];for(n=0;n<2;n++){i.push({x:(0,a.readInt8)(l,u),y:(0,a.readInt8)(l,u+1)});u+=2}g.refinementAt=i}g.numberOfSymbolInstances=(0,a.readUint32)(l,u);u+=4;r=[g,c.referredTo,l,u,h];break;case 16:var v={},w=l[u++];v.mmr=!!(1&w);v.template=w>>1&3;v.patternWidth=l[u++];v.patternHeight=l[u++];v.maxPatternIndex=(0,a.readUint32)(l,u);u+=4;r=[v,c.number,l,u,h];break;case 22:case 23:var k={};k.info=b(l,u);u+=y;var S=l[u++];k.mmr=!!(1&S);k.template=S>>1&3;k.enableSkip=!!(8&S);k.combinationOperator=S>>4&7;k.defaultPixelValue=S>>7&1;k.gridWidth=(0,a.readUint32)(l,u);u+=4;k.gridHeight=(0,a.readUint32)(l,u);u+=4;k.gridOffsetX=4294967295&(0,a.readUint32)(l,u);u+=4;k.gridOffsetY=4294967295&(0,a.readUint32)(l,u);u+=4;k.gridVectorX=(0,a.readUint16)(l,u);u+=2;k.gridVectorY=(0,a.readUint16)(l,u);u+=2;r=[k,c.referredTo,l,u,h];break;case 38:case 39:var C={};C.info=b(l,u);u+=y;var x=l[u++];C.mmr=!!(1&x);C.template=x>>1&3;C.prediction=!!(8&x);if(!C.mmr){s=0===C.template?4:1;i=[];for(n=0;n<s;n++){i.push({x:(0,a.readInt8)(l,u),y:(0,a.readInt8)(l,u+1)});u+=2}C.at=i}r=[C,l,u,h];break;case 48:var _={width:(0,a.readUint32)(l,u),height:(0,a.readUint32)(l,u+4),resolutionX:(0,a.readUint32)(l,u+8),resolutionY:(0,a.readUint32)(l,u+12)};4294967295===_.height&&delete _.height;var A=l[u+16];(0,a.readUint16)(l,u+17);_.lossless=!!(1&A);_.refinement=!!(2&A);_.defaultPixelValue=A>>2&1;_.combinationOperator=A>>3&3;_.requiresBuffer=!!(32&A);_.combinationOperatorOverride=!!(64&A);r=[_];break;case 49:case 50:case 51:break;case 53:r=[c.number,l,u,h];break;case 62:break;default:throw new o("segment type "+c.typeName+"("+c.type+") is not implemented")}var P="on"+c.typeName;P in t&&t[P].apply(t,r)}function k(e,t){for(var r=0,a=e.length;r<a;r++)w(e[r],t)}function S(){}S.prototype={onPageInformation:function(e){this.currentPageInfo=e;var t=e.width+7>>3,r=new Uint8ClampedArray(t*e.height);if(e.defaultPixelValue)for(var a=0,i=r.length;a<i;a++)r[a]=255;this.buffer=r},drawBitmap:function(e,t){var r,a,i,n,s=this.currentPageInfo,c=e.width,l=e.height,u=s.width+7>>3,h=s.combinationOperatorOverride?e.combinationOperator:s.combinationOperator,f=this.buffer,d=128>>(7&e.x),g=e.y*u+(e.x>>3);switch(h){case 0:for(r=0;r<l;r++){i=d;n=g;for(a=0;a<c;a++){t[r][a]&&(f[n]|=i);if(!(i>>=1)){i=128;n++}}g+=u}break;case 2:for(r=0;r<l;r++){i=d;n=g;for(a=0;a<c;a++){t[r][a]&&(f[n]^=i);if(!(i>>=1)){i=128;n++}}g+=u}break;default:throw new o("operator "+h+" is not supported")}},onImmediateGenericRegion:function(e,r,a,i){var n=e.info,o=new t(r,a,i),s=d(e.mmr,n.width,n.height,e.template,e.prediction,null,e.at,o);this.drawBitmap(n,s)},onImmediateLosslessGenericRegion:function(){this.onImmediateGenericRegion.apply(this,arguments)},onSymbolDictionary:function(e,i,n,c,l,u){var h=void 0,f=void 0;if(e.huffman){h=function(e,t,r){var a=0,i=void 0,n=void 0;switch(e.huffmanDHSelector){case 0:case 1:i=P(e.huffmanDHSelector+4);break;case 3:i=O(a,t,r);a++;break;default:throw new o("invalid Huffman DH selector")}switch(e.huffmanDWSelector){case 0:case 1:n=P(e.huffmanDWSelector+2);break;case 3:n=O(a,t,r);a++;break;default:throw new o("invalid Huffman DW selector")}var s=void 0,c=void 0;if(e.bitmapSizeSelector){s=O(a,t,r);a++}else s=P(1);c=e.aggregationInstancesSelector?O(a,t,r):P(1);return{tableDeltaHeight:i,tableDeltaWidth:n,tableBitmapSize:s,tableAggregateInstances:c}}(e,n,this.customTables);f=new I(c,l,u)}var p=this.symbols;p||(this.symbols=p={});for(var v=[],b=0,y=n.length;b<y;b++){var w=p[n[b]];w&&(v=v.concat(w))}var k=new t(c,l,u);p[i]=function(e,t,i,n,c,l,u,h,f,p,v,b){if(e&&t)throw new o("symbol refinement with Huffman is not supported");var y=[],w=0,k=(0,a.log2)(i.length+n),S=v.decoder,C=v.contextCache,x=void 0,_=void 0;if(e){x=P(1);_=[];k=Math.max(k,1)}for(;y.length<n;){w+=e?l.tableDeltaHeight.decode(b):r(C,"IADH",S);for(var A=0,I=0,O=e?_.length:0;;){var F,R=e?l.tableDeltaWidth.decode(b):r(C,"IADW",S);if(null===R)break;I+=A+=R;if(t){var B=r(C,"IAAI",S);if(B>1)F=m(e,t,A,w,0,B,1,i.concat(y),k,0,0,1,0,l,f,p,v,0,b);else{var D=s(C,S,k),M=r(C,"IARDX",S),L=r(C,"IARDY",S);F=g(A,w,f,D<i.length?i[D]:y[D-i.length],M,L,!1,p,v)}y.push(F)}else if(e)_.push(A);else{F=d(!1,A,w,u,!1,null,h,v);y.push(F)}}if(e&&!t){var N=l.tableBitmapSize.decode(b);b.byteAlign();var U=void 0;if(0===N)U=T(b,I,w);else{var q=b.end,j=b.position+N;b.end=j;U=E(b,I,w,!1);b.end=q;b.position=j}var z=_.length;if(O===z-1)y.push(U);else{var H=void 0,G=void 0,W=0,X=void 0,V=void 0;for(H=O;H<z;H++){X=W+_[H];V=[];for(G=0;G<w;G++)V.push(U[G].subarray(W,X));y.push(V);W=X}}}}for(var K=[],Y=[],J=!1,Z=i.length+n;Y.length<Z;){for(var Q=e?x.decode(b):r(C,"IAEX",S);Q--;)Y.push(J);J=!J}for(var $=0,ee=i.length;$<ee;$++)Y[$]&&K.push(i[$]);for(var te=0;te<n;$++,te++)Y[$]&&K.push(y[te]);return K}(e.huffman,e.refinement,v,e.numberOfNewSymbols,e.numberOfExportedSymbols,h,e.template,e.at,e.refinementTemplate,e.refinementAt,k,f)},onImmediateTextRegion:function(e,r,i,n,s){for(var c=e.info,l=void 0,u=void 0,h=this.symbols,f=[],d=0,g=r.length;d<g;d++){var p=h[r[d]];p&&(f=f.concat(p))}var v=(0,a.log2)(f.length);if(e.huffman){u=new I(i,n,s);l=function(e,t,r,a,i){var n=[],s=void 0,c=void 0;for(s=0;s<=34;s++){c=i.readBits(4);n.push(new C([s,c,0,0]))}var l=new _(n,!1);n.length=0;for(s=0;s<a;)if((c=l.decode(i))>=32){var u=void 0,h=void 0,f=void 0;switch(c){case 32:if(0===s)throw new o("no previous value in symbol ID table");h=i.readBits(2)+3;u=n[s-1].prefixLength;break;case 33:h=i.readBits(3)+3;u=0;break;case 34:h=i.readBits(7)+11;u=0;break;default:throw new o("invalid code length in symbol ID table")}for(f=0;f<h;f++){n.push(new C([s,u,0,0]));s++}}else{n.push(new C([s,c,0,0]));s++}i.byteAlign();var d=new _(n,!1),g=0,m=void 0,p=void 0,v=void 0;switch(e.huffmanFS){case 0:case 1:m=P(e.huffmanFS+6);break;case 3:m=O(g,t,r);g++;break;default:throw new o("invalid Huffman FS selector")}switch(e.huffmanDS){case 0:case 1:case 2:p=P(e.huffmanDS+8);break;case 3:p=O(g,t,r);g++;break;default:throw new o("invalid Huffman DS selector")}switch(e.huffmanDT){case 0:case 1:case 2:v=P(e.huffmanDT+11);break;case 3:v=O(g,t,r);g++;break;default:throw new o("invalid Huffman DT selector")}if(e.refinement)throw new o("refinement with Huffman is not supported");return{symbolIDTable:d,tableFirstS:m,tableDeltaS:p,tableDeltaT:v}}(e,r,this.customTables,f.length,u)}var b=new t(i,n,s),y=m(e.huffman,e.refinement,c.width,c.height,e.defaultPixelValue,e.numberOfSymbolInstances,e.stripSize,f,v,e.transposed,e.dsOffset,e.referenceCorner,e.combinationOperator,l,e.refinementTemplate,e.refinementAt,b,e.logStripSize,u);this.drawBitmap(c,y)},onImmediateLosslessTextRegion:function(){this.onImmediateTextRegion.apply(this,arguments)},onPatternDictionary:function(e,r,a,i,n){var o=this.patterns;o||(this.patterns=o={});var s=new t(a,i,n);o[r]=function(e,t,r,a,i,n){var o=[];if(!e){o.push({x:-t,y:0});if(0===i){o.push({x:-3,y:-1});o.push({x:2,y:-2});o.push({x:-2,y:-2})}}for(var s=d(e,(a+1)*t,r,i,!1,null,o,n),c=[],l=0,u=void 0,h=void 0,f=void 0,g=void 0;l<=a;){u=[];f=(h=t*l)+t;for(g=0;g<r;g++)u.push(s[g].subarray(h,f));c.push(u);l++}return c}(e.mmr,e.patternWidth,e.patternHeight,e.maxPatternIndex,e.template,s)},onImmediateHalftoneRegion:function(e,r,i,n,s){var c=this.patterns[r[0]],l=e.info,u=new t(i,n,s),h=function(e,t,r,i,n,s,c,l,u,h,f,g,m,p,v){if(c)throw new o("skip is not supported");if(0!==l)throw new o("operator "+l+" is not supported in halftone region");var b=[],y=void 0,w=void 0,k=void 0;for(y=0;y<n;y++){k=new Uint8Array(i);if(s)for(w=0;w<i;w++)k[w]=s;b.push(k)}var S=t.length,C=t[0],x=C[0].length,_=C.length,A=(0,a.log2)(S),P=[];if(!e){P.push({x:r<=1?3:2,y:-1});if(0===r){P.push({x:-3,y:-1});P.push({x:2,y:-2});P.push({x:-2,y:-2})}}var O=[],T=void 0,F=void 0;e&&(T=new I(v.data,v.start,v.end));for(y=A-1;y>=0;y--){F=e?E(T,u,h,!0):d(!1,u,h,r,!1,null,P,v);O[y]=F}var R=void 0,B=void 0,D=void 0,M=void 0,L=void 0,N=void 0,U=void 0,q=void 0,j=void 0;for(R=0;R<h;R++)for(B=0;B<u;B++){D=0;M=0;for(w=A-1;w>=0;w--)M|=(D=O[w][R][B]^D)<<w;L=t[M];U=g+R*m-B*p>>8;if((N=f+R*p+B*m>>8)>=0&&N+x<=i&&U>=0&&U+_<=n)for(y=0;y<_;y++){j=b[U+y];q=L[y];for(w=0;w<x;w++)j[N+w]|=q[w]}else{var z=void 0,H=void 0;for(y=0;y<_;y++)if(!((H=U+y)<0||H>=n)){j=b[H];q=L[y];for(w=0;w<x;w++)(z=N+w)>=0&&z<i&&(j[z]|=q[w])}}}return b}(e.mmr,c,e.template,l.width,l.height,e.defaultPixelValue,e.enableSkip,e.combinationOperator,e.gridWidth,e.gridHeight,e.gridOffsetX,e.gridOffsetY,e.gridVectorX,e.gridVectorY,u);this.drawBitmap(l,h)},onImmediateLosslessHalftoneRegion:function(){this.onImmediateHalftoneRegion.apply(this,arguments)},onTables:function(e,t,r,i){var n=this.customTables;n||(this.customTables=n={});n[e]=function(e,t,r){var i=e[t],n=4294967295&(0,a.readUint32)(e,t+1),o=4294967295&(0,a.readUint32)(e,t+5),s=new I(e,t+9,r),c=1+(i>>1&7),l=1+(i>>4&7),u=[],h=void 0,f=void 0,d=n;do{h=s.readBits(c);f=s.readBits(l);u.push(new C([d,h,f,0]));d+=1<<f}while(d<o);h=s.readBits(c);u.push(new C([n-1,h,32,0,"lower"]));h=s.readBits(c);u.push(new C([o,h,32,0]));if(1&i){h=s.readBits(c);u.push(new C([h,0]))}return new _(u,!1)}(t,r,i)}};function C(e){if(2===e.length){this.isOOB=!0;this.rangeLow=0;this.prefixLength=e[0];this.rangeLength=0;this.prefixCode=e[1];this.isLowerRange=!1}else{this.isOOB=!1;this.rangeLow=e[0];this.prefixLength=e[1];this.rangeLength=e[2];this.prefixCode=e[3];this.isLowerRange="lower"===e[4]}}function x(e){this.children=[];if(e){this.isLeaf=!0;this.rangeLength=e.rangeLength;this.rangeLow=e.rangeLow;this.isLowerRange=e.isLowerRange;this.isOOB=e.isOOB}else this.isLeaf=!1}x.prototype={buildTree:function(e,t){var r=e.prefixCode>>t&1;if(t<=0)this.children[r]=new x(e);else{var a=this.children[r];a||(this.children[r]=a=new x(null));a.buildTree(e,t-1)}},decodeNode:function(e){if(this.isLeaf){if(this.isOOB)return null;var t=e.readBits(this.rangeLength);return this.rangeLow+(this.isLowerRange?-t:t)}var r=this.children[e.readBit()];if(!r)throw new o("invalid Huffman data");return r.decodeNode(e)}};function _(e,t){t||this.assignPrefixCodes(e);this.rootNode=new x(null);var r=void 0,a=e.length,i=void 0;for(r=0;r<a;r++)(i=e[r]).prefixLength>0&&this.rootNode.buildTree(i,i.prefixLength-1)}_.prototype={decode:function(e){return this.rootNode.decodeNode(e)},assignPrefixCodes:function(e){var t=e.length,r=0,a=void 0;for(a=0;a<t;a++)r=Math.max(r,e[a].prefixLength);var i=new Uint32Array(r+1);for(a=0;a<t;a++)i[e[a].prefixLength]++;var n=1,o=0,s=void 0,c=void 0,l=void 0;i[0]=0;for(;n<=r;){s=o=o+i[n-1]<<1;c=0;for(;c<t;){if((l=e[c]).prefixLength===n){l.prefixCode=s;s++}c++}n++}}};var A={};function P(e){var t=A[e];if(t)return t;var r=void 0;switch(e){case 1:r=[[0,1,4,0],[16,2,8,2],[272,3,16,6],[65808,3,32,7]];break;case 2:r=[[0,1,0,0],[1,2,0,2],[2,3,0,6],[3,4,3,14],[11,5,6,30],[75,6,32,62],[6,63]];break;case 3:r=[[-256,8,8,254],[0,1,0,0],[1,2,0,2],[2,3,0,6],[3,4,3,14],[11,5,6,30],[-257,8,32,255,"lower"],[75,7,32,126],[6,62]];break;case 4:r=[[1,1,0,0],[2,2,0,2],[3,3,0,6],[4,4,3,14],[12,5,6,30],[76,5,32,31]];break;case 5:r=[[-255,7,8,126],[1,1,0,0],[2,2,0,2],[3,3,0,6],[4,4,3,14],[12,5,6,30],[-256,7,32,127,"lower"],[76,6,32,62]];break;case 6:r=[[-2048,5,10,28],[-1024,4,9,8],[-512,4,8,9],[-256,4,7,10],[-128,5,6,29],[-64,5,5,30],[-32,4,5,11],[0,2,7,0],[128,3,7,2],[256,3,8,3],[512,4,9,12],[1024,4,10,13],[-2049,6,32,62,"lower"],[2048,6,32,63]];break;case 7:r=[[-1024,4,9,8],[-512,3,8,0],[-256,4,7,9],[-128,5,6,26],[-64,5,5,27],[-32,4,5,10],[0,4,5,11],[32,5,5,28],[64,5,6,29],[128,4,7,12],[256,3,8,1],[512,3,9,2],[1024,3,10,3],[-1025,5,32,30,"lower"],[2048,5,32,31]];break;case 8:r=[[-15,8,3,252],[-7,9,1,508],[-5,8,1,253],[-3,9,0,509],[-2,7,0,124],[-1,4,0,10],[0,2,1,0],[2,5,0,26],[3,6,0,58],[4,3,4,4],[20,6,1,59],[22,4,4,11],[38,4,5,12],[70,5,6,27],[134,5,7,28],[262,6,7,60],[390,7,8,125],[646,6,10,61],[-16,9,32,510,"lower"],[1670,9,32,511],[2,1]];break;case 9:r=[[-31,8,4,252],[-15,9,2,508],[-11,8,2,253],[-7,9,1,509],[-5,7,1,124],[-3,4,1,10],[-1,3,1,2],[1,3,1,3],[3,5,1,26],[5,6,1,58],[7,3,5,4],[39,6,2,59],[43,4,5,11],[75,4,6,12],[139,5,7,27],[267,5,8,28],[523,6,8,60],[779,7,9,125],[1291,6,11,61],[-32,9,32,510,"lower"],[3339,9,32,511],[2,0]];break;case 10:r=[[-21,7,4,122],[-5,8,0,252],[-4,7,0,123],[-3,5,0,24],[-2,2,2,0],[2,5,0,25],[3,6,0,54],[4,7,0,124],[5,8,0,253],[6,2,6,1],[70,5,5,26],[102,6,5,55],[134,6,6,56],[198,6,7,57],[326,6,8,58],[582,6,9,59],[1094,6,10,60],[2118,7,11,125],[-22,8,32,254,"lower"],[4166,8,32,255],[2,2]];break;case 11:r=[[1,1,0,0],[2,2,1,2],[4,4,0,12],[5,4,1,13],[7,5,1,28],[9,5,2,29],[13,6,2,60],[17,7,2,122],[21,7,3,123],[29,7,4,124],[45,7,5,125],[77,7,6,126],[141,7,32,127]];break;case 12:r=[[1,1,0,0],[2,2,0,2],[3,3,1,6],[5,5,0,28],[6,5,1,29],[8,6,1,60],[10,7,0,122],[11,7,1,123],[13,7,2,124],[17,7,3,125],[25,7,4,126],[41,8,5,254],[73,8,32,255]];break;case 13:r=[[1,1,0,0],[2,3,0,4],[3,4,0,12],[4,5,0,28],[5,4,1,13],[7,3,3,5],[15,6,1,58],[17,6,2,59],[21,6,3,60],[29,6,4,61],[45,6,5,62],[77,7,6,126],[141,7,32,127]];break;case 14:r=[[-2,3,0,4],[-1,3,0,5],[0,1,0,0],[1,3,0,6],[2,3,0,7]];break;case 15:r=[[-24,7,4,124],[-8,6,2,60],[-4,5,1,28],[-2,4,0,12],[-1,3,0,4],[0,1,0,0],[1,3,0,5],[2,4,0,13],[3,5,1,29],[5,6,2,61],[9,7,4,125],[-25,7,32,126,"lower"],[25,7,32,127]];break;default:throw new o("standard table B."+e+" does not exist")}var a=r.length,i=void 0;for(i=0;i<a;i++)r[i]=new C(r[i]);t=new _(r,!0);A[e]=t;return t}function I(e,t,r){this.data=e;this.start=t;this.end=r;this.position=t;this.shift=-1;this.currentByte=0}I.prototype={readBit:function(){if(this.shift<0){if(this.position>=this.end)throw new o("end of data while reading bit");this.currentByte=this.data[this.position++];this.shift=7}var e=this.currentByte>>this.shift&1;this.shift--;return e},readBits:function(e){var t=0,r=void 0;for(r=e-1;r>=0;r--)t|=this.readBit()<<r;return t},byteAlign:function(){this.shift=-1},next:function(){return this.position>=this.end?-1:this.data[this.position++]}};function O(e,t,r){var a=0,i=void 0,n=t.length,s=void 0;for(i=0;i<n;i++)if(s=r[t[i]]){if(e===a)return s;a++}throw new o("can't find custom Huffman table")}function T(e,t,r){var a=[],i=void 0,n=void 0,o=void 0;for(n=0;n<r;n++){o=new Uint8Array(t);a.push(o);for(i=0;i<t;i++)o[i]=e.readBit();e.byteAlign()}return a}function E(e,t,r,a){var i={K:-1,Columns:t,Rows:r,BlackIs1:!0,EndOfBlock:a},o=new n.CCITTFaxDecoder(e,i),s=[],c=void 0,l=void 0,u=void 0,h=void 0,f=void 0,d=!1;for(l=0;l<r;l++){u=new Uint8Array(t);s.push(u);f=-1;for(c=0;c<t;c++){if(f<0){if(-1===(h=o.readNextChar())){h=0;d=!0}f=7}u[c]=h>>f&1;f--}}if(a&&!d)for(var g=0;g<5&&-1!==o.readNextChar();g++);return s}function F(){}F.prototype={parseChunks:function(e){return function(e){for(var t=new S,r=0,a=e.length;r<a;r++){var i=e[r];k(v({},i.data,i.start,i.end),t)}return t.buffer}(e)},parse:function(e){var t=function(e){var t=0,r=e.length;if(151!==e[t]||74!==e[t+1]||66!==e[t+2]||50!==e[t+3]||13!==e[t+4]||10!==e[t+5]||26!==e[t+6]||10!==e[t+7])throw new o("parseJbig2 - invalid header.");var i=Object.create(null);t+=8;var n=e[t++];i.randomAccess=!(1&n);if(!(2&n)){i.numberOfPages=(0,a.readUint32)(e,t);t+=4}var s=v(i,e,t,r),c=new S;k(s,c);for(var l=c.currentPageInfo,u=l.width,h=l.height,f=c.buffer,d=new Uint8ClampedArray(u*h),g=0,m=0,p=0;p<h;p++)for(var b=0,y=void 0,w=0;w<u;w++){if(!b){b=128;y=f[m++]}d[g++]=y&b?0:255;b>>=1}return{imgData:d,width:u,height:h}}(e),r=t.imgData,i=t.width,n=t.height;this.width=i;this.height=n;return r}};return F}();t.Jbig2Image=s},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var a=function(){var e=[{qe:22017,nmps:1,nlps:1,switchFlag:1},{qe:13313,nmps:2,nlps:6,switchFlag:0},{qe:6145,nmps:3,nlps:9,switchFlag:0},{qe:2753,nmps:4,nlps:12,switchFlag:0},{qe:1313,nmps:5,nlps:29,switchFlag:0},{qe:545,nmps:38,nlps:33,switchFlag:0},{qe:22017,nmps:7,nlps:6,switchFlag:1},{qe:21505,nmps:8,nlps:14,switchFlag:0},{qe:18433,nmps:9,nlps:14,switchFlag:0},{qe:14337,nmps:10,nlps:14,switchFlag:0},{qe:12289,nmps:11,nlps:17,switchFlag:0},{qe:9217,nmps:12,nlps:18,switchFlag:0},{qe:7169,nmps:13,nlps:20,switchFlag:0},{qe:5633,nmps:29,nlps:21,switchFlag:0},{qe:22017,nmps:15,nlps:14,switchFlag:1},{qe:21505,nmps:16,nlps:14,switchFlag:0},{qe:20737,nmps:17,nlps:15,switchFlag:0},{qe:18433,nmps:18,nlps:16,switchFlag:0},{qe:14337,nmps:19,nlps:17,switchFlag:0},{qe:13313,nmps:20,nlps:18,switchFlag:0},{qe:12289,nmps:21,nlps:19,switchFlag:0},{qe:10241,nmps:22,nlps:19,switchFlag:0},{qe:9217,nmps:23,nlps:20,switchFlag:0},{qe:8705,nmps:24,nlps:21,switchFlag:0},{qe:7169,nmps:25,nlps:22,switchFlag:0},{qe:6145,nmps:26,nlps:23,switchFlag:0},{qe:5633,nmps:27,nlps:24,switchFlag:0},{qe:5121,nmps:28,nlps:25,switchFlag:0},{qe:4609,nmps:29,nlps:26,switchFlag:0},{qe:4353,nmps:30,nlps:27,switchFlag:0},{qe:2753,nmps:31,nlps:28,switchFlag:0},{qe:2497,nmps:32,nlps:29,switchFlag:0},{qe:2209,nmps:33,nlps:30,switchFlag:0},{qe:1313,nmps:34,nlps:31,switchFlag:0},{qe:1089,nmps:35,nlps:32,switchFlag:0},{qe:673,nmps:36,nlps:33,switchFlag:0},{qe:545,nmps:37,nlps:34,switchFlag:0},{qe:321,nmps:38,nlps:35,switchFlag:0},{qe:273,nmps:39,nlps:36,switchFlag:0},{qe:133,nmps:40,nlps:37,switchFlag:0},{qe:73,nmps:41,nlps:38,switchFlag:0},{qe:37,nmps:42,nlps:39,switchFlag:0},{qe:21,nmps:43,nlps:40,switchFlag:0},{qe:9,nmps:44,nlps:41,switchFlag:0},{qe:5,nmps:45,nlps:42,switchFlag:0},{qe:1,nmps:45,nlps:43,switchFlag:0},{qe:22017,nmps:46,nlps:46,switchFlag:0}];function t(e,t,r){this.data=e;this.bp=t;this.dataEnd=r;this.chigh=e[t];this.clow=0;this.byteIn();this.chigh=this.chigh<<7&65535|this.clow>>9&127;this.clow=this.clow<<7&65535;this.ct-=7;this.a=32768}t.prototype={byteIn:function(){var e=this.data,t=this.bp;if(255===e[t]){if(e[t+1]>143){this.clow+=65280;this.ct=8}else{t++;this.clow+=e[t]<<9;this.ct=7;this.bp=t}}else{t++;this.clow+=t<this.dataEnd?e[t]<<8:65280;this.ct=8;this.bp=t}if(this.clow>65535){this.chigh+=this.clow>>16;this.clow&=65535}},readBit:function(t,r){var a,i=t[r]>>1,n=1&t[r],o=e[i],s=o.qe,c=this.a-s;if(this.chigh<s)if(c<s){c=s;a=n;i=o.nmps}else{c=s;a=1^n;1===o.switchFlag&&(n=a);i=o.nlps}else{this.chigh-=s;if(0!=(32768&c)){this.a=c;return n}if(c<s){a=1^n;1===o.switchFlag&&(n=a);i=o.nlps}else{a=n;i=o.nmps}}do{0===this.ct&&this.byteIn();c<<=1;this.chigh=this.chigh<<1&65535|this.clow>>15&1;this.clow=this.clow<<1&65535;this.ct--}while(0==(32768&c));this.a=c;t[r]=i<<1|n;return a}};return t}();t.ArithmeticDecoder=a},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.JpegStream=void 0;var a=r(2),i=r(140),n=r(138),o=r(147),s=function(){function e(e,t,r,a){for(var n=void 0;-1!==(n=e.getByte());)if(255===n){e.skip(-1);break}this.stream=e;this.maybeLength=t;this.dict=r;this.params=a;i.DecodeStream.call(this,t)}e.prototype=Object.create(i.DecodeStream.prototype);Object.defineProperty(e.prototype,"bytes",{get:function(){return(0,a.shadow)(this,"bytes",this.stream.getBytes(this.maybeLength))},configurable:!0});e.prototype.ensureBuffer=function(e){};e.prototype.readBlock=function(){if(!this.eof){var e={decodeTransform:void 0,colorTransform:void 0},t=this.dict.getArray("Decode","D");if(this.forceRGB&&Array.isArray(t)){for(var r=this.dict.get("BitsPerComponent")||8,a=t.length,i=new Int32Array(a),s=!1,c=(1<<r)-1,l=0;l<a;l+=2){i[l]=256*(t[l+1]-t[l])|0;i[l+1]=t[l]*c|0;256===i[l]&&0===i[l+1]||(s=!0)}s&&(e.decodeTransform=i)}if((0,n.isDict)(this.params)){var u=this.params.get("ColorTransform");Number.isInteger(u)&&(e.colorTransform=u)}var h=new o.JpegImage(e);h.parse(this.bytes);var f=h.getData({width:this.drawWidth,height:this.drawHeight,forceRGB:this.forceRGB,isSourcePDF:!0});this.buffer=f;this.bufferLength=f.length;this.eof=!0}};e.prototype.getIR=function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return(0,a.createObjectURL)(this.bytes,"image/jpeg",e)};return e}();t.JpegStream=s},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.JpegImage=void 0;var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i=r(2),n=function(){function e(e){this.message="JPEG error: "+e}e.prototype=new Error;e.prototype.name="JpegError";e.constructor=e;return e}(),o=function(){function e(e,t){this.message=e;this.scanLines=t}e.prototype=new Error;e.prototype.name="DNLMarkerError";e.constructor=e;return e}(),s=function(){function e(e){this.message=e}e.prototype=new Error;e.prototype.name="EOIMarkerError";e.constructor=e;return e}(),c=function(){var e=new Uint8Array([0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63]),t=4017,r=799,c=3406,l=2276,u=1567,h=3784,f=5793,d=2896;function g(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.decodeTransform,r=void 0===t?null:t,a=e.colorTransform,i=void 0===a?-1:a;this._decodeTransform=r;this._colorTransform=i}function m(e,t){for(var r,a,i=0,n=[],o=16;o>0&&!e[o-1];)o--;n.push({children:[],index:0});var s,c=n[0];for(r=0;r<o;r++){for(a=0;a<e[r];a++){(c=n.pop()).children[c.index]=t[i];for(;c.index>0;)c=n.pop();c.index++;n.push(c);for(;n.length<=r;){n.push(s={children:[],index:0});c.children[c.index]=s.children;c=s}i++}if(r+1<o){n.push(s={children:[],index:0});c.children[c.index]=s.children;c=s}}return n[0].children}function p(e,t,r){return 64*((e.blocksPerLine+1)*t+r)}function v(t,r,c,l,u,h,f,d,g){var m=arguments.length>9&&void 0!==arguments[9]&&arguments[9],v=c.mcusPerLine,b=c.progressive,y=r,k=0,S=0;function C(){if(S>0)return k>>--S&1;if(255===(k=t[r++])){var e=t[r++];if(e){if(220===e&&m){r+=2;var a=t[r++]<<8|t[r++];if(a>0&&a!==c.scanLines)throw new o("Found DNL marker (0xFFDC) while parsing scan data",a)}else if(217===e)throw new s("Found EOI marker (0xFFD9) while parsing scan data");throw new n("unexpected marker "+(k<<8|e).toString(16))}}S=7;return k>>>7}function x(e){for(var t=e;;){if("number"==typeof(t=t[C()]))return t;if("object"!==(void 0===t?"undefined":a(t)))throw new n("invalid huffman sequence")}}function _(e){for(var t=0;e>0;){t=t<<1|C();e--}return t}function A(e){if(1===e)return 1===C()?1:-1;var t=_(e);return t>=1<<e-1?t:t+(-1<<e)+1}var P=0;var I,O=0;function T(e,t,r,a,i){var n=r%v;t(e,p(e,(r/v|0)*e.v+a,n*e.h+i))}function E(e,t,r){t(e,p(e,r/e.blocksPerLine|0,r%e.blocksPerLine))}var F,R,B,D,M,L,N=l.length;L=b?0===h?0===d?function(e,t){var r=x(e.huffmanTableDC),a=0===r?0:A(r)<<g;e.blockData[t]=e.pred+=a}:function(e,t){e.blockData[t]|=C()<<g}:0===d?function(t,r){if(P>0)P--;else for(var a=h,i=f;a<=i;){var n=x(t.huffmanTableAC),o=15&n,s=n>>4;if(0!==o){var c=e[a+=s];t.blockData[r+c]=A(o)*(1<<g);a++}else{if(s<15){P=_(s)+(1<<s)-1;break}a+=16}}}:function(t,r){for(var a,i,o=h,s=f,c=0;o<=s;){var l=r+e[o],u=t.blockData[l]<0?-1:1;switch(O){case 0:c=(i=x(t.huffmanTableAC))>>4;if(0==(a=15&i))if(c<15){P=_(c)+(1<<c);O=4}else{c=16;O=1}else{if(1!==a)throw new n("invalid ACn encoding");I=A(a);O=c?2:3}continue;case 1:case 2:t.blockData[l]?t.blockData[l]+=u*(C()<<g):0==--c&&(O=2===O?3:0);break;case 3:if(t.blockData[l])t.blockData[l]+=u*(C()<<g);else{t.blockData[l]=I<<g;O=0}break;case 4:t.blockData[l]&&(t.blockData[l]+=u*(C()<<g))}o++}4===O&&0==--P&&(O=0)}:function(t,r){var a=x(t.huffmanTableDC),i=0===a?0:A(a);t.blockData[r]=t.pred+=i;for(var n=1;n<64;){var o=x(t.huffmanTableAC),s=15&o,c=o>>4;if(0!==s){var l=e[n+=c];t.blockData[r+l]=A(s);n++}else{if(c<15)break;n+=16}}};var U,q,j,z,H=0;q=1===N?l[0].blocksPerLine*l[0].blocksPerColumn:v*c.mcusPerColumn;for(;H<q;){var G=u?Math.min(q-H,u):q;for(R=0;R<N;R++)l[R].pred=0;P=0;if(1===N){F=l[0];for(M=0;M<G;M++){E(F,L,H);H++}}else for(M=0;M<G;M++){for(R=0;R<N;R++){j=(F=l[R]).h;z=F.v;for(B=0;B<z;B++)for(D=0;D<j;D++)T(F,L,H,B,D)}H++}S=0;if((U=w(t,r))&&U.invalid){(0,i.warn)("decodeScan - unexpected MCU data, current marker is: "+U.invalid);r=U.offset}var W=U&&U.marker;if(!W||W<=65280)throw new n("marker was not found");if(!(W>=65488&&W<=65495))break;r+=2}if((U=w(t,r))&&U.invalid){(0,i.warn)("decodeScan - unexpected Scan data, current marker is: "+U.invalid);r=U.offset}return r-y}function b(e,a,i){var o,s,g,m,p,v,b,y,w,k,S,C,x,_,A,P,I,O=e.quantizationTable,T=e.blockData;if(!O)throw new n("missing required Quantization Table.");for(var E=0;E<64;E+=8){w=T[a+E];k=T[a+E+1];S=T[a+E+2];C=T[a+E+3];x=T[a+E+4];_=T[a+E+5];A=T[a+E+6];P=T[a+E+7];w*=O[E];if(0!=(k|S|C|x|_|A|P)){k*=O[E+1];S*=O[E+2];C*=O[E+3];x*=O[E+4];_*=O[E+5];A*=O[E+6];P*=O[E+7];s=(o=(o=f*w+128>>8)+(s=f*x+128>>8)+1>>1)-s;I=(g=S)*h+(m=A)*u+128>>8;g=g*u-m*h+128>>8;b=(p=(p=d*(k-P)+128>>8)+(b=_<<4)+1>>1)-b;v=(y=(y=d*(k+P)+128>>8)+(v=C<<4)+1>>1)-v;m=(o=o+(m=I)+1>>1)-m;g=(s=s+g+1>>1)-g;I=p*l+y*c+2048>>12;p=p*c-y*l+2048>>12;y=I;I=v*r+b*t+2048>>12;v=v*t-b*r+2048>>12;b=I;i[E]=o+y;i[E+7]=o-y;i[E+1]=s+b;i[E+6]=s-b;i[E+2]=g+v;i[E+5]=g-v;i[E+3]=m+p;i[E+4]=m-p}else{I=f*w+512>>10;i[E]=I;i[E+1]=I;i[E+2]=I;i[E+3]=I;i[E+4]=I;i[E+5]=I;i[E+6]=I;i[E+7]=I}}for(var F=0;F<8;++F){w=i[F];if(0!=((k=i[F+8])|(S=i[F+16])|(C=i[F+24])|(x=i[F+32])|(_=i[F+40])|(A=i[F+48])|(P=i[F+56]))){s=(o=4112+((o=f*w+2048>>12)+(s=f*x+2048>>12)+1>>1))-s;I=(g=S)*h+(m=A)*u+2048>>12;g=g*u-m*h+2048>>12;m=I;b=(p=(p=d*(k-P)+2048>>12)+(b=_)+1>>1)-b;v=(y=(y=d*(k+P)+2048>>12)+(v=C)+1>>1)-v;I=p*l+y*c+2048>>12;p=p*c-y*l+2048>>12;y=I;I=v*r+b*t+2048>>12;v=v*t-b*r+2048>>12;P=(o=o+m+1>>1)-y;k=(s=s+g+1>>1)+(b=I);A=s-b;S=(g=s-g)+v;_=g-v;C=(m=o-m)+p;x=m-p;w=(w=o+y)<16?0:w>=4080?255:w>>4;k=k<16?0:k>=4080?255:k>>4;S=S<16?0:S>=4080?255:S>>4;C=C<16?0:C>=4080?255:C>>4;x=x<16?0:x>=4080?255:x>>4;_=_<16?0:_>=4080?255:_>>4;A=A<16?0:A>=4080?255:A>>4;P=P<16?0:P>=4080?255:P>>4;T[a+F]=w;T[a+F+8]=k;T[a+F+16]=S;T[a+F+24]=C;T[a+F+32]=x;T[a+F+40]=_;T[a+F+48]=A;T[a+F+56]=P}else{I=(I=f*w+8192>>14)<-2040?0:I>=2024?255:I+2056>>4;T[a+F]=I;T[a+F+8]=I;T[a+F+16]=I;T[a+F+24]=I;T[a+F+32]=I;T[a+F+40]=I;T[a+F+48]=I;T[a+F+56]=I}}}function y(e,t){for(var r=t.blocksPerLine,a=t.blocksPerColumn,i=new Int16Array(64),n=0;n<a;n++)for(var o=0;o<r;o++){b(t,p(t,n,o),i)}return t.blockData}function w(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t;function a(t){return e[t]<<8|e[t+1]}var i=e.length-1,n=r<t?r:t;if(t>=i)return null;var o=a(t);if(o>=65472&&o<=65534)return{invalid:null,marker:o,offset:t};for(var s=a(n);!(s>=65472&&s<=65534);){if(++n>=i)return null;s=a(n)}return{invalid:o.toString(16),marker:s,offset:n}}g.prototype={parse:function(t){var r=(arguments.length>1&&void 0!==arguments[1]?arguments[1]:{}).dnlScanLines,a=void 0===r?null:r;function c(){var e=t[d]<<8|t[d+1];d+=2;return e}function l(){var e=c(),r=d+e-2,a=w(t,r,d);if(a&&a.invalid){(0,i.warn)("readDataBlock - incorrect length, current marker is: "+a.invalid);r=a.offset}var n=t.subarray(d,r);d+=n.length;return n}function u(e){for(var t=Math.ceil(e.samplesPerLine/8/e.maxH),r=Math.ceil(e.scanLines/8/e.maxV),a=0;a<e.components.length;a++){X=e.components[a];var i=Math.ceil(Math.ceil(e.samplesPerLine/8)*X.h/e.maxH),n=Math.ceil(Math.ceil(e.scanLines/8)*X.v/e.maxV),o=t*X.h,s=64*(r*X.v)*(o+1);X.blockData=new Int16Array(s);X.blocksPerLine=i;X.blocksPerColumn=n}e.mcusPerLine=t;e.mcusPerColumn=r}var h,f,d=0,g=null,p=null,b=0,k=[],S=[],C=[],x=c();if(65496!==x)throw new n("SOI not found");x=c();e:for(;65497!==x;){var _,A,P;switch(x){case 65504:case 65505:case 65506:case 65507:case 65508:case 65509:case 65510:case 65511:case 65512:case 65513:case 65514:case 65515:case 65516:case 65517:case 65518:case 65519:case 65534:var I=l();65504===x&&74===I[0]&&70===I[1]&&73===I[2]&&70===I[3]&&0===I[4]&&(g={version:{major:I[5],minor:I[6]},densityUnits:I[7],xDensity:I[8]<<8|I[9],yDensity:I[10]<<8|I[11],thumbWidth:I[12],thumbHeight:I[13],thumbData:I.subarray(14,14+3*I[12]*I[13])});65518===x&&65===I[0]&&100===I[1]&&111===I[2]&&98===I[3]&&101===I[4]&&(p={version:I[5]<<8|I[6],flags0:I[7]<<8|I[8],flags1:I[9]<<8|I[10],transformCode:I[11]});break;case 65499:for(var O=c()+d-2;d<O;){var T=t[d++],E=new Uint16Array(64);if(T>>4==0)for(A=0;A<64;A++)E[e[A]]=t[d++];else{if(T>>4!=1)throw new n("DQT - invalid table spec");for(A=0;A<64;A++)E[e[A]]=c()}k[15&T]=E}break;case 65472:case 65473:case 65474:if(h)throw new n("Only single frame JPEGs supported");c();(h={}).extended=65473===x;h.progressive=65474===x;h.precision=t[d++];var F=c();h.scanLines=a||F;h.samplesPerLine=c();h.components=[];h.componentIds={};var R,B=t[d++],D=0,M=0;for(_=0;_<B;_++){R=t[d];var L=t[d+1]>>4,N=15&t[d+1];D<L&&(D=L);M<N&&(M=N);var U=t[d+2];P=h.components.push({h:L,v:N,quantizationId:U,quantizationTable:null});h.componentIds[R]=P-1;d+=3}h.maxH=D;h.maxV=M;u(h);break;case 65476:var q=c();for(_=2;_<q;){var j=t[d++],z=new Uint8Array(16),H=0;for(A=0;A<16;A++,d++)H+=z[A]=t[d];var G=new Uint8Array(H);for(A=0;A<H;A++,d++)G[A]=t[d];_+=17+H;(j>>4==0?C:S)[15&j]=m(z,G)}break;case 65501:c();f=c();break;case 65498:var W=1==++b&&!a;c();var X,V=t[d++],K=[];for(_=0;_<V;_++){var Y=h.componentIds[t[d++]];X=h.components[Y];var J=t[d++];X.huffmanTableDC=C[J>>4];X.huffmanTableAC=S[15&J];K.push(X)}var Z=t[d++],Q=t[d++],$=t[d++];try{var ee=v(t,d,h,K,f,Z,Q,$>>4,15&$,W);d+=ee}catch(e){if(e instanceof o){(0,i.warn)(e.message+" -- attempting to re-parse the JPEG image.");return this.parse(t,{dnlScanLines:e.scanLines})}if(e instanceof s){(0,i.warn)(e.message+" -- ignoring the rest of the image data.");break e}throw e}break;case 65500:d+=4;break;case 65535:255!==t[d]&&d--;break;default:if(255===t[d-3]&&t[d-2]>=192&&t[d-2]<=254){d-=3;break}var te=w(t,d-2);if(te&&te.invalid){(0,i.warn)("JpegImage.parse - unexpected data, current marker is: "+te.invalid);d=te.offset;break}throw new n("unknown marker "+x.toString(16))}x=c()}this.width=h.samplesPerLine;this.height=h.scanLines;this.jfif=g;this.adobe=p;this.components=[];for(_=0;_<h.components.length;_++){var re=k[(X=h.components[_]).quantizationId];re&&(X.quantizationTable=re);this.components.push({output:y(0,X),scaleX:X.h/h.maxH,scaleY:X.v/h.maxV,blocksPerLine:X.blocksPerLine,blocksPerColumn:X.blocksPerColumn})}this.numComponents=this.components.length},_getLinearizedBlockData:function(e,t){var r,a,i,n,o,s,c,l,u,h,f,d=arguments.length>2&&void 0!==arguments[2]&&arguments[2],g=this.width/e,m=this.height/t,p=0,v=this.components.length,b=e*t*v,y=new Uint8ClampedArray(b),w=new Uint32Array(e);for(c=0;c<v;c++){a=(r=this.components[c]).scaleX*g;i=r.scaleY*m;p=c;f=r.output;n=r.blocksPerLine+1<<3;for(o=0;o<e;o++){l=0|o*a;w[o]=(4294967288&l)<<3|7&l}for(s=0;s<t;s++){h=n*(4294967288&(l=0|s*i))|(7&l)<<3;for(o=0;o<e;o++){y[p]=f[h+w[o]];p+=v}}}var k=this._decodeTransform;d||4!==v||k||(k=new Int32Array([-256,255,-256,255,-256,255,-256,255]));if(k)for(c=0;c<b;)for(l=0,u=0;l<v;l++,c++,u+=2)y[c]=(y[c]*k[u]>>8)+k[u+1];return y},get _isColorConversionNeeded(){return this.adobe?!!this.adobe.transformCode:3===this.numComponents?0!==this._colorTransform:1===this._colorTransform},_convertYccToRgb:function(e){for(var t,r,a,i=0,n=e.length;i<n;i+=3){t=e[i];r=e[i+1];a=e[i+2];e[i]=t-179.456+1.402*a;e[i+1]=t+135.459-.344*r-.714*a;e[i+2]=t-226.816+1.772*r}return e},_convertYcckToRgb:function(e){for(var t,r,a,i,n=0,o=0,s=e.length;o<s;o+=4){t=e[o];r=e[o+1];a=e[o+2];i=e[o+3];e[n++]=r*(-660635669420364e-19*r+.000437130475926232*a-54080610064599e-18*t+.00048449797120281*i-.154362151871126)-122.67195406894+a*(-.000957964378445773*a+.000817076911346625*t-.00477271405408747*i+1.53380253221734)+t*(.000961250184130688*t-.00266257332283933*i+.48357088451265)+i*(-.000336197177618394*i+.484791561490776);e[n++]=107.268039397724+r*(219927104525741e-19*r-.000640992018297945*a+.000659397001245577*t+.000426105652938837*i-.176491792462875)+a*(-.000778269941513683*a+.00130872261408275*t+.000770482631801132*i-.151051492775562)+t*(.00126935368114843*t-.00265090189010898*i+.25802910206845)+i*(-.000318913117588328*i-.213742400323665);e[n++]=r*(-.000570115196973677*r-263409051004589e-19*a+.0020741088115012*t-.00288260236853442*i+.814272968359295)-20.810012546947+a*(-153496057440975e-19*a-.000132689043961446*t+.000560833691242812*i-.195152027534049)+t*(.00174418132927582*t-.00255243321439347*i+.116935020465145)+i*(-.000343531996510555*i+.24165260232407)}return e.subarray(0,n)},_convertYcckToCmyk:function(e){for(var t,r,a,i=0,n=e.length;i<n;i+=4){t=e[i];r=e[i+1];a=e[i+2];e[i]=434.456-t-1.402*a;e[i+1]=119.541-t+.344*r+.714*a;e[i+2]=481.816-t-1.772*r}return e},_convertCmykToRgb:function(e){for(var t,r,a,i,n=0,o=0,s=e.length;o<s;o+=4){t=e[o]*(1/255);r=e[o+1]*(1/255);a=e[o+2]*(1/255);i=e[o+3]*(1/255);e[n++]=255+t*(-4.387332384609988*t+54.48615194189176*r+18.82290502165302*a+212.25662451639585*i-285.2331026137004)+r*(1.7149763477362134*r-5.6096736904047315*a-17.873870861415444*i-5.497006427196366)+a*(-2.5217340131683033*a-21.248923337353073*i+17.5119270841813)-i*(21.86122147463605*i+189.48180835922747);e[n++]=255+t*(8.841041422036149*t+60.118027045597366*r+6.871425592049007*a+31.159100130055922*i-79.2970844816548)+r*(-15.310361306967817*r+17.575251261109482*a+131.35250912493976*i-190.9453302588951)+a*(4.444339102852739*a+9.8632861493405*i-24.86741582555878)-i*(20.737325471181034*i+187.80453709719578);e[n++]=255+t*(.8842522430003296*t+8.078677503112928*r+30.89978309703729*a-.23883238689178934*i-14.183576799673286)+r*(10.49593273432072*r+63.02378494754052*a+50.606957656360734*i-112.23884253719248)+a*(.03296041114873217*a+115.60384449646641*i-193.58209356861505)-i*(22.33816807309886*i+180.12613974708367)}return e.subarray(0,n)},getData:function(e){var t=e.width,r=e.height,a=e.forceRGB,i=void 0!==a&&a,o=e.isSourcePDF,s=void 0!==o&&o;if(this.numComponents>4)throw new n("Unsupported color mode");var c=this._getLinearizedBlockData(t,r,s);if(1===this.numComponents&&i){for(var l=c.length,u=new Uint8ClampedArray(3*l),h=0,f=0;f<l;f++){var d=c[f];u[h++]=d;u[h++]=d;u[h++]=d}return u}if(3===this.numComponents&&this._isColorConversionNeeded)return this._convertYccToRgb(c);if(4===this.numComponents){if(this._isColorConversionNeeded)return i?this._convertYcckToRgb(c):this._convertYcckToCmyk(c);if(i)return this._convertCmykToRgb(c)}return c}};return g}();t.JpegImage=c},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.JpxStream=void 0;var a=r(140),i=r(149),n=r(2),o=function(){function e(e,t,r,i){this.stream=e;this.maybeLength=t;this.dict=r;this.params=i;a.DecodeStream.call(this,t)}e.prototype=Object.create(a.DecodeStream.prototype);Object.defineProperty(e.prototype,"bytes",{get:function(){return(0,n.shadow)(this,"bytes",this.stream.getBytes(this.maybeLength))},configurable:!0});e.prototype.ensureBuffer=function(e){};e.prototype.readBlock=function(){if(!this.eof){var e=new i.JpxImage;e.parse(this.bytes);var t=e.width,r=e.height,a=e.componentsCount,n=e.tiles.length;if(1===n)this.buffer=e.tiles[0].items;else{for(var o=new Uint8ClampedArray(t*r*a),s=0;s<n;s++)for(var c=e.tiles[s],l=c.width,u=c.height,h=c.left,f=c.top,d=c.items,g=0,m=(t*f+h)*a,p=t*a,v=l*a,b=0;b<u;b++){var y=d.subarray(g,g+v);o.set(y,m);g+=v;m+=p}this.buffer=o}this.bufferLength=this.buffer.length;this.eof=!0}};return e}();t.JpxStream=o},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.JpxImage=void 0;var a=r(2),i=r(145),n=function(){function e(e){this.message="JPX error: "+e}e.prototype=new Error;e.prototype.name="JpxError";e.constructor=e;return e}(),o=function(){var e={LL:0,LH:1,HL:1,HH:2};function t(){this.failOnCorruptedImage=!1}t.prototype={parse:function(e){if(65359!==(0,a.readUint16)(e,0))for(var t=0,r=e.length;t<r;){var i=8,o=(0,a.readUint32)(e,t),s=(0,a.readUint32)(e,t+4);t+=i;if(1===o){o=4294967296*(0,a.readUint32)(e,t)+(0,a.readUint32)(e,t+4);t+=8;i+=8}0===o&&(o=r-t+i);if(o<i)throw new n("Invalid box field size");var c=o-i,l=!0;switch(s){case 1785737832:l=!1;break;case 1668246642:var u=e[t];if(1===u){var h=(0,a.readUint32)(e,t+3);switch(h){case 16:case 17:case 18:break;default:(0,a.warn)("Unknown colorspace "+h)}}else 2===u&&(0,a.info)("ICC profile not supported");break;case 1785737827:this.parseCodestream(e,t,t+c);break;case 1783636e3:218793738!==(0,a.readUint32)(e,t)&&(0,a.warn)("Invalid JP2 signature");break;case 1783634458:case 1718909296:case 1920099697:case 1919251232:case 1768449138:break;default:var f=String.fromCharCode(s>>24&255,s>>16&255,s>>8&255,255&s);(0,a.warn)("Unsupported header type "+s+" ("+f+")")}l&&(t+=c)}else this.parseCodestream(e,0,e.length)},parseImageProperties:function(e){for(var t=e.getByte();t>=0;){if(65361===(t<<8|(t=e.getByte()))){e.skip(4);var r=e.getInt32()>>>0,a=e.getInt32()>>>0,i=e.getInt32()>>>0,o=e.getInt32()>>>0;e.skip(16);var s=e.getUint16();this.width=r-i;this.height=a-o;this.componentsCount=s;this.bitsPerComponent=8;return}}throw new n("No size marker found in JPX stream")},parseCodestream:function(e,t,i){var s={},c=!1;try{for(var l=t;l+1<i;){var u=(0,a.readUint16)(e,l);l+=2;var h,f,m,b,y,w,k=0;switch(u){case 65359:s.mainHeader=!0;break;case 65497:break;case 65361:k=(0,a.readUint16)(e,l);var S={};S.Xsiz=(0,a.readUint32)(e,l+4);S.Ysiz=(0,a.readUint32)(e,l+8);S.XOsiz=(0,a.readUint32)(e,l+12);S.YOsiz=(0,a.readUint32)(e,l+16);S.XTsiz=(0,a.readUint32)(e,l+20);S.YTsiz=(0,a.readUint32)(e,l+24);S.XTOsiz=(0,a.readUint32)(e,l+28);S.YTOsiz=(0,a.readUint32)(e,l+32);var C=(0,a.readUint16)(e,l+36);S.Csiz=C;var x=[];h=l+38;for(var _=0;_<C;_++){var A={precision:1+(127&e[h]),isSigned:!!(128&e[h]),XRsiz:e[h+1],YRsiz:e[h+2]};h+=3;r(A,S);x.push(A)}s.SIZ=S;s.components=x;o(s,x);s.QCC=[];s.COC=[];break;case 65372:k=(0,a.readUint16)(e,l);var P={};h=l+2;switch(31&(f=e[h++])){case 0:b=8;y=!0;break;case 1:b=16;y=!1;break;case 2:b=16;y=!0;break;default:throw new Error("Invalid SQcd value "+f)}P.noQuantization=8===b;P.scalarExpounded=y;P.guardBits=f>>5;m=[];for(;h<k+l;){var I={};if(8===b){I.epsilon=e[h++]>>3;I.mu=0}else{I.epsilon=e[h]>>3;I.mu=(7&e[h])<<8|e[h+1];h+=2}m.push(I)}P.SPqcds=m;if(s.mainHeader)s.QCD=P;else{s.currentTile.QCD=P;s.currentTile.QCC=[]}break;case 65373:k=(0,a.readUint16)(e,l);var O,T={};h=l+2;if(s.SIZ.Csiz<257)O=e[h++];else{O=(0,a.readUint16)(e,h);h+=2}switch(31&(f=e[h++])){case 0:b=8;y=!0;break;case 1:b=16;y=!1;break;case 2:b=16;y=!0;break;default:throw new Error("Invalid SQcd value "+f)}T.noQuantization=8===b;T.scalarExpounded=y;T.guardBits=f>>5;m=[];for(;h<k+l;){I={};if(8===b){I.epsilon=e[h++]>>3;I.mu=0}else{I.epsilon=e[h]>>3;I.mu=(7&e[h])<<8|e[h+1];h+=2}m.push(I)}T.SPqcds=m;s.mainHeader?s.QCC[O]=T:s.currentTile.QCC[O]=T;break;case 65362:k=(0,a.readUint16)(e,l);var E={};h=l+2;var F=e[h++];E.entropyCoderWithCustomPrecincts=!!(1&F);E.sopMarkerUsed=!!(2&F);E.ephMarkerUsed=!!(4&F);E.progressionOrder=e[h++];E.layersCount=(0,a.readUint16)(e,h);h+=2;E.multipleComponentTransform=e[h++];E.decompositionLevelsCount=e[h++];E.xcb=2+(15&e[h++]);E.ycb=2+(15&e[h++]);var R=e[h++];E.selectiveArithmeticCodingBypass=!!(1&R);E.resetContextProbabilities=!!(2&R);E.terminationOnEachCodingPass=!!(4&R);E.verticallyStripe=!!(8&R);E.predictableTermination=!!(16&R);E.segmentationSymbolUsed=!!(32&R);E.reversibleTransformation=e[h++];if(E.entropyCoderWithCustomPrecincts){for(var B=[];h<k+l;){var D=e[h++];B.push({PPx:15&D,PPy:D>>4})}E.precinctsSizes=B}var M=[];E.selectiveArithmeticCodingBypass&&M.push("selectiveArithmeticCodingBypass");E.resetContextProbabilities&&M.push("resetContextProbabilities");E.terminationOnEachCodingPass&&M.push("terminationOnEachCodingPass");E.verticallyStripe&&M.push("verticallyStripe");E.predictableTermination&&M.push("predictableTermination");if(M.length>0){c=!0;throw new Error("Unsupported COD options ("+M.join(", ")+")")}if(s.mainHeader)s.COD=E;else{s.currentTile.COD=E;s.currentTile.COC=[]}break;case 65424:k=(0,a.readUint16)(e,l);(w={}).index=(0,a.readUint16)(e,l+2);w.length=(0,a.readUint32)(e,l+4);w.dataEnd=w.length+l-2;w.partIndex=e[l+8];w.partsCount=e[l+9];s.mainHeader=!1;if(0===w.partIndex){w.COD=s.COD;w.COC=s.COC.slice(0);w.QCD=s.QCD;w.QCC=s.QCC.slice(0)}s.currentTile=w;break;case 65427:if(0===(w=s.currentTile).partIndex){v(s,w.index);d(s)}g(s,e,l,k=w.dataEnd-l);break;case 65365:case 65367:case 65368:case 65380:k=(0,a.readUint16)(e,l);break;case 65363:throw new Error("Codestream code 0xFF53 (COC) is not implemented");default:throw new Error("Unknown codestream code: "+u.toString(16))}l+=k}}catch(e){if(c||this.failOnCorruptedImage)throw new n(e.message);(0,a.warn)("JPX: Trying to recover from: "+e.message)}this.tiles=function(e){for(var t=e.SIZ,r=e.components,a=t.Csiz,i=[],n=0,o=e.tiles.length;n<o;n++){var s,c=e.tiles[n],l=[];for(s=0;s<a;s++)l[s]=p(e,c,s);var u,h,f,d,g,m,v,b=l[0],y=new Uint8ClampedArray(b.items.length*a),w={left:b.left,top:b.top,width:b.width,height:b.height,items:y},k=0;if(c.codingStyleDefaultParameters.multipleComponentTransform){var S=4===a,C=l[0].items,x=l[1].items,_=l[2].items,A=S?l[3].items:null;u=r[0].precision-8;h=.5+(128<<u);var P=c.components[0],I=a-3;d=C.length;if(P.codingStyleParameters.reversibleTransformation)for(f=0;f<d;f++,k+=I){g=C[f]+h;m=x[f];v=_[f];var O=g-(v+m>>2);y[k++]=O+v>>u;y[k++]=O>>u;y[k++]=O+m>>u}else for(f=0;f<d;f++,k+=I){g=C[f]+h;m=x[f];v=_[f];y[k++]=g+1.402*v>>u;y[k++]=g-.34413*m-.71414*v>>u;y[k++]=g+1.772*m>>u}if(S)for(f=0,k=3;f<d;f++,k+=4)y[k]=A[f]+h>>u}else for(s=0;s<a;s++){var T=l[s].items;u=r[s].precision-8;h=.5+(128<<u);for(k=s,f=0,d=T.length;f<d;f++){y[k]=T[f]+h>>u;k+=a}}i.push(w)}return i}(s);this.width=s.SIZ.Xsiz-s.SIZ.XOsiz;this.height=s.SIZ.Ysiz-s.SIZ.YOsiz;this.componentsCount=s.SIZ.Csiz}};function r(e,t){e.x0=Math.ceil(t.XOsiz/e.XRsiz);e.x1=Math.ceil(t.Xsiz/e.XRsiz);e.y0=Math.ceil(t.YOsiz/e.YRsiz);e.y1=Math.ceil(t.Ysiz/e.YRsiz);e.width=e.x1-e.x0;e.height=e.y1-e.y0}function o(e,t){for(var r,a=e.SIZ,i=[],n=Math.ceil((a.Xsiz-a.XTOsiz)/a.XTsiz),o=Math.ceil((a.Ysiz-a.YTOsiz)/a.YTsiz),s=0;s<o;s++)for(var c=0;c<n;c++){(r={}).tx0=Math.max(a.XTOsiz+c*a.XTsiz,a.XOsiz);r.ty0=Math.max(a.YTOsiz+s*a.YTsiz,a.YOsiz);r.tx1=Math.min(a.XTOsiz+(c+1)*a.XTsiz,a.Xsiz);r.ty1=Math.min(a.YTOsiz+(s+1)*a.YTsiz,a.Ysiz);r.width=r.tx1-r.tx0;r.height=r.ty1-r.ty0;r.components=[];i.push(r)}e.tiles=i;for(var l=0,u=a.Csiz;l<u;l++)for(var h=t[l],f=0,d=i.length;f<d;f++){var g={};r=i[f];g.tcx0=Math.ceil(r.tx0/h.XRsiz);g.tcy0=Math.ceil(r.ty0/h.YRsiz);g.tcx1=Math.ceil(r.tx1/h.XRsiz);g.tcy1=Math.ceil(r.ty1/h.YRsiz);g.width=g.tcx1-g.tcx0;g.height=g.tcy1-g.tcy0;r.components[l]=g}}function s(e,t,r){var a=t.codingStyleParameters,i={};if(a.entropyCoderWithCustomPrecincts){i.PPx=a.precinctsSizes[r].PPx;i.PPy=a.precinctsSizes[r].PPy}else{i.PPx=15;i.PPy=15}i.xcb_=r>0?Math.min(a.xcb,i.PPx-1):Math.min(a.xcb,i.PPx);i.ycb_=r>0?Math.min(a.ycb,i.PPy-1):Math.min(a.ycb,i.PPy);return i}function c(e,t,r){var a=1<<r.PPx,i=1<<r.PPy,n=0===t.resLevel,o=1<<r.PPx+(n?0:-1),s=1<<r.PPy+(n?0:-1),c=t.trx1>t.trx0?Math.ceil(t.trx1/a)-Math.floor(t.trx0/a):0,l=t.try1>t.try0?Math.ceil(t.try1/i)-Math.floor(t.try0/i):0,u=c*l;t.precinctParameters={precinctWidth:a,precinctHeight:i,numprecinctswide:c,numprecinctshigh:l,numprecincts:u,precinctWidthInSubband:o,precinctHeightInSubband:s}}function l(e,t,r){var a,i,n,o,s=r.xcb_,c=r.ycb_,l=1<<s,u=1<<c,h=t.tbx0>>s,f=t.tby0>>c,d=t.tbx1+l-1>>s,g=t.tby1+u-1>>c,m=t.resolution.precinctParameters,p=[],v=[];for(i=f;i<g;i++)for(a=h;a<d;a++){(n={cbx:a,cby:i,tbx0:l*a,tby0:u*i,tbx1:l*(a+1),tby1:u*(i+1)}).tbx0_=Math.max(t.tbx0,n.tbx0);n.tby0_=Math.max(t.tby0,n.tby0);n.tbx1_=Math.min(t.tbx1,n.tbx1);n.tby1_=Math.min(t.tby1,n.tby1);o=Math.floor((n.tbx0_-t.tbx0)/m.precinctWidthInSubband)+Math.floor((n.tby0_-t.tby0)/m.precinctHeightInSubband)*m.numprecinctswide;n.precinctNumber=o;n.subbandType=t.type;n.Lblock=3;if(!(n.tbx1_<=n.tbx0_||n.tby1_<=n.tby0_)){p.push(n);var b=v[o];if(void 0!==b){a<b.cbxMin?b.cbxMin=a:a>b.cbxMax&&(b.cbxMax=a);i<b.cbyMin?b.cbxMin=i:i>b.cbyMax&&(b.cbyMax=i)}else v[o]=b={cbxMin:a,cbyMin:i,cbxMax:a,cbyMax:i};n.precinct=b}}t.codeblockParameters={codeblockWidth:s,codeblockHeight:c,numcodeblockwide:d-h+1,numcodeblockhigh:g-f+1};t.codeblocks=p;t.precincts=v}function u(e,t,r){for(var a=[],i=e.subbands,n=0,o=i.length;n<o;n++)for(var s=i[n].codeblocks,c=0,l=s.length;c<l;c++){var u=s[c];u.precinctNumber===t&&a.push(u)}return{layerNumber:r,codeblocks:a}}function h(e,t,r,a,i){var n=e*a.minWidth,o=t*a.minHeight;if(n%r.width!=0||o%r.height!=0)return null;var s=o/r.width*i.precinctParameters.numprecinctswide;return n/r.height+s}function f(e){for(var t=e.components.length,r=Number.MAX_VALUE,a=Number.MAX_VALUE,i=0,n=0,o=new Array(t),s=0;s<t;s++){for(var c=e.components[s],l=c.codingStyleParameters.decompositionLevelsCount,u=new Array(l+1),h=Number.MAX_VALUE,f=Number.MAX_VALUE,d=0,g=0,m=1,p=l;p>=0;--p){var v=c.resolutions[p],b=m*v.precinctParameters.precinctWidth,y=m*v.precinctParameters.precinctHeight;h=Math.min(h,b);f=Math.min(f,y);d=Math.max(d,v.precinctParameters.numprecinctswide);g=Math.max(g,v.precinctParameters.numprecinctshigh);u[p]={width:b,height:y};m<<=1}r=Math.min(r,h);a=Math.min(a,f);i=Math.max(i,d);n=Math.max(n,g);o[s]={resolutions:u,minWidth:h,minHeight:f,maxNumWide:d,maxNumHigh:g}}return{components:o,minWidth:r,minHeight:a,maxNumWide:i,maxNumHigh:n}}function d(e){for(var t=e.SIZ,r=e.currentTile.index,a=e.tiles[r],i=t.Csiz,o=0;o<i;o++){for(var d=a.components[o],g=d.codingStyleParameters.decompositionLevelsCount,m=[],p=[],v=0;v<=g;v++){var b,y=s(0,d,v),w={},k=1<<g-v;w.trx0=Math.ceil(d.tcx0/k);w.try0=Math.ceil(d.tcy0/k);w.trx1=Math.ceil(d.tcx1/k);w.try1=Math.ceil(d.tcy1/k);w.resLevel=v;c(0,w,y);m.push(w);if(0===v){(b={}).type="LL";b.tbx0=Math.ceil(d.tcx0/k);b.tby0=Math.ceil(d.tcy0/k);b.tbx1=Math.ceil(d.tcx1/k);b.tby1=Math.ceil(d.tcy1/k);b.resolution=w;l(0,b,y);p.push(b);w.subbands=[b]}else{var S=1<<g-v+1,C=[];(b={}).type="HL";b.tbx0=Math.ceil(d.tcx0/S-.5);b.tby0=Math.ceil(d.tcy0/S);b.tbx1=Math.ceil(d.tcx1/S-.5);b.tby1=Math.ceil(d.tcy1/S);b.resolution=w;l(0,b,y);p.push(b);C.push(b);(b={}).type="LH";b.tbx0=Math.ceil(d.tcx0/S);b.tby0=Math.ceil(d.tcy0/S-.5);b.tbx1=Math.ceil(d.tcx1/S);b.tby1=Math.ceil(d.tcy1/S-.5);b.resolution=w;l(0,b,y);p.push(b);C.push(b);(b={}).type="HH";b.tbx0=Math.ceil(d.tcx0/S-.5);b.tby0=Math.ceil(d.tcy0/S-.5);b.tbx1=Math.ceil(d.tcx1/S-.5);b.tby1=Math.ceil(d.tcy1/S-.5);b.resolution=w;l(0,b,y);p.push(b);C.push(b);w.subbands=C}}d.resolutions=m;d.subbands=p}var x=a.codingStyleDefaultParameters.progressionOrder;switch(x){case 0:a.packetsIterator=new function(e){for(var t=e.SIZ,r=e.currentTile.index,a=e.tiles[r],i=a.codingStyleDefaultParameters.layersCount,o=t.Csiz,s=0,c=0;c<o;c++)s=Math.max(s,a.components[c].codingStyleParameters.decompositionLevelsCount);var l=0,h=0,f=0,d=0;this.nextPacket=function(){for(;l<i;l++){for(;h<=s;h++){for(;f<o;f++){var e=a.components[f];if(!(h>e.codingStyleParameters.decompositionLevelsCount)){for(var t=e.resolutions[h],r=t.precinctParameters.numprecincts;d<r;){var c=u(t,d,l);d++;return c}d=0}}f=0}h=0}throw new n("Out of packets")}}(e);break;case 1:a.packetsIterator=new function(e){for(var t=e.SIZ,r=e.currentTile.index,a=e.tiles[r],i=a.codingStyleDefaultParameters.layersCount,o=t.Csiz,s=0,c=0;c<o;c++)s=Math.max(s,a.components[c].codingStyleParameters.decompositionLevelsCount);var l=0,h=0,f=0,d=0;this.nextPacket=function(){for(;l<=s;l++){for(;h<i;h++){for(;f<o;f++){var e=a.components[f];if(!(l>e.codingStyleParameters.decompositionLevelsCount)){for(var t=e.resolutions[l],r=t.precinctParameters.numprecincts;d<r;){var c=u(t,d,h);d++;return c}d=0}}f=0}h=0}throw new n("Out of packets")}}(e);break;case 2:a.packetsIterator=new function(e){var t,r,a,i,o=e.SIZ,s=e.currentTile.index,c=e.tiles[s],l=c.codingStyleDefaultParameters.layersCount,h=o.Csiz,f=0;for(a=0;a<h;a++){var d=c.components[a];f=Math.max(f,d.codingStyleParameters.decompositionLevelsCount)}var g=new Int32Array(f+1);for(r=0;r<=f;++r){var m=0;for(a=0;a<h;++a){var p=c.components[a].resolutions;r<p.length&&(m=Math.max(m,p[r].precinctParameters.numprecincts))}g[r]=m}t=0;r=0;a=0;i=0;this.nextPacket=function(){for(;r<=f;r++){for(;i<g[r];i++){for(;a<h;a++){var e=c.components[a];if(!(r>e.codingStyleParameters.decompositionLevelsCount)){var o=e.resolutions[r],s=o.precinctParameters.numprecincts;if(!(i>=s)){for(;t<l;){var d=u(o,i,t);t++;return d}t=0}}}a=0}i=0}throw new n("Out of packets")}}(e);break;case 3:a.packetsIterator=new function(e){var t=e.SIZ,r=e.currentTile.index,a=e.tiles[r],i=a.codingStyleDefaultParameters.layersCount,o=t.Csiz,s=f(a),c=s,l=0,d=0,g=0,m=0,p=0;this.nextPacket=function(){for(;p<c.maxNumHigh;p++){for(;m<c.maxNumWide;m++){for(;g<o;g++){for(var e=a.components[g],t=e.codingStyleParameters.decompositionLevelsCount;d<=t;d++){var r=e.resolutions[d],f=s.components[g].resolutions[d],v=h(m,p,f,c,r);if(null!==v){for(;l<i;){var b=u(r,v,l);l++;return b}l=0}}d=0}g=0}m=0}throw new n("Out of packets")}}(e);break;case 4:a.packetsIterator=new function(e){var t=e.SIZ,r=e.currentTile.index,a=e.tiles[r],i=a.codingStyleDefaultParameters.layersCount,o=t.Csiz,s=f(a),c=0,l=0,d=0,g=0,m=0;this.nextPacket=function(){for(;d<o;++d){for(var e=a.components[d],t=s.components[d],r=e.codingStyleParameters.decompositionLevelsCount;m<t.maxNumHigh;m++){for(;g<t.maxNumWide;g++){for(;l<=r;l++){var f=e.resolutions[l],p=t.resolutions[l],v=h(g,m,p,t,f);if(null!==v){for(;c<i;){var b=u(f,v,c);c++;return b}c=0}}l=0}g=0}m=0}throw new n("Out of packets")}}(e);break;default:throw new n("Unsupported progression order "+x)}}function g(e,t,r,i){var n,o=0,s=0,c=!1;function l(e){for(;s<e;){var a=t[r+o];o++;if(c){n=n<<7|a;s+=7;c=!1}else{n=n<<8|a;s+=8}255===a&&(c=!0)}return n>>>(s-=e)&(1<<e)-1}function u(e){if(255===t[r+o-1]&&t[r+o]===e){h(1);return!0}if(255===t[r+o]&&t[r+o+1]===e){h(2);return!0}return!1}function h(e){o+=e}function f(){s=0;if(c){o++;c=!1}}function d(){if(0===l(1))return 1;if(0===l(1))return 2;var e=l(2);return e<3?e+3:(e=l(5))<31?e+6:(e=l(7))+37}for(var g=e.currentTile.index,m=e.tiles[g],p=e.COD.sopMarkerUsed,v=e.COD.ephMarkerUsed,w=m.packetsIterator;o<i;){f();p&&u(145)&&h(4);var k=w.nextPacket();if(l(1)){for(var S,C=k.layerNumber,x=[],_=0,A=k.codeblocks.length;_<A;_++){var P=(S=k.codeblocks[_]).precinct,I=S.cbx-P.cbxMin,O=S.cby-P.cbyMin,T=!1,E=!1;if(void 0!==S.included)T=!!l(1);else{var F,R;if(void 0!==(P=S.precinct).inclusionTree)F=P.inclusionTree;else{var B=P.cbxMax-P.cbxMin+1,D=P.cbyMax-P.cbyMin+1;F=new y(B,D,C);R=new b(B,D);P.inclusionTree=F;P.zeroBitPlanesTree=R}if(F.reset(I,O,C))for(;;){if(!l(1)){F.incrementValue(C);break}if(!F.nextLevel()){S.included=!0;T=E=!0;break}}}if(T){if(E){(R=P.zeroBitPlanesTree).reset(I,O);for(;;)if(l(1)){if(!R.nextLevel())break}else R.incrementValue();S.zeroBitPlanes=R.value}for(var M=d();l(1);)S.Lblock++;var L=(0,a.log2)(M),N=l((M<1<<L?L-1:L)+S.Lblock);x.push({codeblock:S,codingpasses:M,dataLength:N})}}f();v&&u(146);for(;x.length>0;){var U=x.shift();void 0===(S=U.codeblock).data&&(S.data=[]);S.data.push({data:t,start:r+o,end:r+o+U.dataLength,codingpasses:U.codingpasses});o+=U.dataLength}}}return o}function m(e,t,r,a,n,o,s,c){for(var l=a.tbx0,u=a.tby0,h=a.tbx1-a.tbx0,f=a.codeblocks,d="H"===a.type.charAt(0)?1:0,g="H"===a.type.charAt(1)?t:0,m=0,p=f.length;m<p;++m){var v=f[m],b=v.tbx1_-v.tbx0_,y=v.tby1_-v.tby0_;if(0!==b&&0!==y&&void 0!==v.data){var k,S;k=new w(b,y,v.subbandType,v.zeroBitPlanes,o);S=2;var C,x,_,A=v.data,P=0,I=0;for(C=0,x=A.length;C<x;C++){P+=(_=A[C]).end-_.start;I+=_.codingpasses}var O=new Uint8Array(P),T=0;for(C=0,x=A.length;C<x;C++){var E=(_=A[C]).data.subarray(_.start,_.end);O.set(E,T);T+=E.length}var F=new i.ArithmeticDecoder(O,0,P);k.setDecoder(F);for(C=0;C<I;C++){switch(S){case 0:k.runSignificancePropagationPass();break;case 1:k.runMagnitudeRefinementPass();break;case 2:k.runCleanupPass();c&&k.checkSegmentationSymbol()}S=(S+1)%3}var R,B,D,M=v.tbx0_-l+(v.tby0_-u)*h,L=k.coefficentsSign,N=k.coefficentsMagnitude,U=k.bitsDecoded,q=s?0:.5;T=0;var j="LL"!==a.type;for(C=0;C<y;C++){var z=2*(M/h|0)*(t-h)+d+g;for(R=0;R<b;R++){if(0!==(B=N[T])){B=(B+q)*n;0!==L[T]&&(B=-B);D=U[T];var H=j?z+(M<<1):M;e[H]=s&&D>=o?B:B*(1<<o-D)}M++;T++}M+=h-b}}}}function p(t,r,a){for(var i=r.components[a],n=i.codingStyleParameters,o=i.quantizationParameters,s=n.decompositionLevelsCount,c=o.SPqcds,l=o.scalarExpounded,u=o.guardBits,h=n.segmentationSymbolUsed,f=t.components[a].precision,d=n.reversibleTransformation,g=d?new C:new S,p=[],v=0,b=0;b<=s;b++){for(var y=i.resolutions[b],w=y.trx1-y.trx0,k=y.try1-y.try0,x=new Float32Array(w*k),_=0,A=y.subbands.length;_<A;_++){var P,I;if(l){P=c[v].mu;I=c[v].epsilon;v++}else{P=c[0].mu;I=c[0].epsilon+(b>0?1-b:0)}var O=y.subbands[_],T=e[O.type];m(x,w,0,O,d?1:Math.pow(2,f+T-I)*(1+P/2048),u+I-1,d,h)}p.push({width:w,height:k,items:x})}var E=g.calculate(p,i.tcx0,i.tcy0);return{left:i.tcx0,top:i.tcy0,width:E.width,height:E.height,items:E.items}}function v(e,t){for(var r=e.SIZ.Csiz,a=e.tiles[t],i=0;i<r;i++){var n=a.components[i],o=void 0!==e.currentTile.QCC[i]?e.currentTile.QCC[i]:e.currentTile.QCD;n.quantizationParameters=o;var s=void 0!==e.currentTile.COC[i]?e.currentTile.COC[i]:e.currentTile.COD;n.codingStyleParameters=s}a.codingStyleDefaultParameters=e.currentTile.COD}var b=function(){function e(e,t){var r=(0,a.log2)(Math.max(e,t))+1;this.levels=[];for(var i=0;i<r;i++){var n={width:e,height:t,items:[]};this.levels.push(n);e=Math.ceil(e/2);t=Math.ceil(t/2)}}e.prototype={reset:function(e,t){for(var r,a=0,i=0;a<this.levels.length;){var n=e+t*(r=this.levels[a]).width;if(void 0!==r.items[n]){i=r.items[n];break}r.index=n;e>>=1;t>>=1;a++}a--;(r=this.levels[a]).items[r.index]=i;this.currentLevel=a;delete this.value},incrementValue:function(){var e=this.levels[this.currentLevel];e.items[e.index]++},nextLevel:function(){var e=this.currentLevel,t=this.levels[e],r=t.items[t.index];if(--e<0){this.value=r;return!1}this.currentLevel=e;(t=this.levels[e]).items[t.index]=r;return!0}};return e}(),y=function(){function e(e,t,r){var i=(0,a.log2)(Math.max(e,t))+1;this.levels=[];for(var n=0;n<i;n++){for(var o=new Uint8Array(e*t),s=0,c=o.length;s<c;s++)o[s]=r;var l={width:e,height:t,items:o};this.levels.push(l);e=Math.ceil(e/2);t=Math.ceil(t/2)}}e.prototype={reset:function(e,t,r){for(var a=0;a<this.levels.length;){var i=this.levels[a],n=e+t*i.width;i.index=n;var o=i.items[n];if(255===o)break;if(o>r){this.currentLevel=a;this.propagateValues();return!1}e>>=1;t>>=1;a++}this.currentLevel=a-1;return!0},incrementValue:function(e){var t=this.levels[this.currentLevel];t.items[t.index]=e+1;this.propagateValues()},propagateValues:function(){for(var e=this.currentLevel,t=this.levels[e],r=t.items[t.index];--e>=0;)(t=this.levels[e]).items[t.index]=r},nextLevel:function(){var e=this.currentLevel,t=this.levels[e],r=t.items[t.index];t.items[t.index]=255;if(--e<0)return!1;this.currentLevel=e;(t=this.levels[e]).items[t.index]=r;return!0}};return e}(),w=function(){var e=new Uint8Array([0,5,8,0,3,7,8,0,4,7,8,0,0,0,0,0,1,6,8,0,3,7,8,0,4,7,8,0,0,0,0,0,2,6,8,0,3,7,8,0,4,7,8,0,0,0,0,0,2,6,8,0,3,7,8,0,4,7,8,0,0,0,0,0,2,6,8,0,3,7,8,0,4,7,8]),t=new Uint8Array([0,3,4,0,5,7,7,0,8,8,8,0,0,0,0,0,1,3,4,0,6,7,7,0,8,8,8,0,0,0,0,0,2,3,4,0,6,7,7,0,8,8,8,0,0,0,0,0,2,3,4,0,6,7,7,0,8,8,8,0,0,0,0,0,2,3,4,0,6,7,7,0,8,8,8]),r=new Uint8Array([0,1,2,0,1,2,2,0,2,2,2,0,0,0,0,0,3,4,5,0,4,5,5,0,5,5,5,0,0,0,0,0,6,7,7,0,7,7,7,0,7,7,7,0,0,0,0,0,8,8,8,0,8,8,8,0,8,8,8,0,0,0,0,0,8,8,8,0,8,8,8,0,8,8,8]);function a(a,i,n,o,s){this.width=a;this.height=i;this.contextLabelTable="HH"===n?r:"HL"===n?t:e;var c=a*i;this.neighborsSignificance=new Uint8Array(c);this.coefficentsSign=new Uint8Array(c);this.coefficentsMagnitude=s>14?new Uint32Array(c):s>6?new Uint16Array(c):new Uint8Array(c);this.processingFlags=new Uint8Array(c);var l=new Uint8Array(c);if(0!==o)for(var u=0;u<c;u++)l[u]=o;this.bitsDecoded=l;this.reset()}a.prototype={setDecoder:function(e){this.decoder=e},reset:function(){this.contexts=new Int8Array(19);this.contexts[0]=8;this.contexts[17]=92;this.contexts[18]=6},setNeighborsSignificance:function(e,t,r){var a,i=this.neighborsSignificance,n=this.width,o=this.height,s=t>0,c=t+1<n;if(e>0){a=r-n;s&&(i[a-1]+=16);c&&(i[a+1]+=16);i[a]+=4}if(e+1<o){a=r+n;s&&(i[a-1]+=16);c&&(i[a+1]+=16);i[a]+=4}s&&(i[r-1]+=1);c&&(i[r+1]+=1);i[r]|=128},runSignificancePropagationPass:function(){for(var e=this.decoder,t=this.width,r=this.height,a=this.coefficentsMagnitude,i=this.coefficentsSign,n=this.neighborsSignificance,o=this.processingFlags,s=this.contexts,c=this.contextLabelTable,l=this.bitsDecoded,u=0;u<r;u+=4)for(var h=0;h<t;h++)for(var f=u*t+h,d=0;d<4;d++,f+=t){var g=u+d;if(g>=r)break;o[f]&=-2;if(!a[f]&&n[f]){var m=c[n[f]];if(e.readBit(s,m)){var p=this.decodeSignBit(g,h,f);i[f]=p;a[f]=1;this.setNeighborsSignificance(g,h,f);o[f]|=2}l[f]++;o[f]|=1}}},decodeSignBit:function(e,t,r){var a,i,n,o,s,c,l=this.width,u=this.height,h=this.coefficentsMagnitude,f=this.coefficentsSign;o=t>0&&0!==h[r-1];if(t+1<l&&0!==h[r+1]){n=f[r+1];a=o?1-n-(i=f[r-1]):1-n-n}else a=o?1-(i=f[r-1])-i:0;var d=3*a;o=e>0&&0!==h[r-l];if(e+1<u&&0!==h[r+l]){n=f[r+l];a=o?1-n-(i=f[r-l])+d:1-n-n+d}else a=o?1-(i=f[r-l])-i+d:d;if(a>=0){s=9+a;c=this.decoder.readBit(this.contexts,s)}else{s=9-a;c=1^this.decoder.readBit(this.contexts,s)}return c},runMagnitudeRefinementPass:function(){for(var e,t=this.decoder,r=this.width,a=this.height,i=this.coefficentsMagnitude,n=this.neighborsSignificance,o=this.contexts,s=this.bitsDecoded,c=this.processingFlags,l=r*a,u=4*r,h=0;h<l;h=e){e=Math.min(l,h+u);for(var f=0;f<r;f++)for(var d=h+f;d<e;d+=r)if(i[d]&&0==(1&c[d])){var g=16;if(0!=(2&c[d])){c[d]^=2;g=0===(127&n[d])?15:14}var m=t.readBit(o,g);i[d]=i[d]<<1|m;s[d]++;c[d]|=1}}},runCleanupPass:function(){for(var e,t=this.decoder,r=this.width,a=this.height,i=this.neighborsSignificance,n=this.coefficentsMagnitude,o=this.coefficentsSign,s=this.contexts,c=this.contextLabelTable,l=this.bitsDecoded,u=this.processingFlags,h=r,f=2*r,d=3*r,g=0;g<a;g=e){e=Math.min(g+4,a);for(var m=g*r,p=g+3<a,v=0;v<r;v++){var b,y=m+v,w=0,k=y,S=g;if(p&&0===u[y]&&0===u[y+h]&&0===u[y+f]&&0===u[y+d]&&0===i[y]&&0===i[y+h]&&0===i[y+f]&&0===i[y+d]){if(!t.readBit(s,18)){l[y]++;l[y+h]++;l[y+f]++;l[y+d]++;continue}if(0!==(w=t.readBit(s,17)<<1|t.readBit(s,17))){S=g+w;k+=w*r}b=this.decodeSignBit(S,v,k);o[k]=b;n[k]=1;this.setNeighborsSignificance(S,v,k);u[k]|=2;k=y;for(var C=g;C<=S;C++,k+=r)l[k]++;w++}for(S=g+w;S<e;S++,k+=r)if(!n[k]&&0==(1&u[k])){var x=c[i[k]];if(1===t.readBit(s,x)){b=this.decodeSignBit(S,v,k);o[k]=b;n[k]=1;this.setNeighborsSignificance(S,v,k);u[k]|=2}l[k]++}}}},checkSegmentationSymbol:function(){var e=this.decoder,t=this.contexts;if(10!==(e.readBit(t,17)<<3|e.readBit(t,17)<<2|e.readBit(t,17)<<1|e.readBit(t,17)))throw new n("Invalid segmentation symbol")}};return a}(),k=function(){function e(){}e.prototype.calculate=function(e,t,r){for(var a=e[0],i=1,n=e.length;i<n;i++)a=this.iterate(a,e[i],t,r);return a};e.prototype.extend=function(e,t,r){var a=t-1,i=t+1,n=t+r-2,o=t+r;e[a--]=e[i++];e[o++]=e[n--];e[a--]=e[i++];e[o++]=e[n--];e[a--]=e[i++];e[o++]=e[n--];e[a]=e[i];e[o]=e[n]};e.prototype.iterate=function(e,t,r,a){var i,n,o,s,c,l,u=e.width,h=e.height,f=e.items,d=t.width,g=t.height,m=t.items;for(o=0,i=0;i<h;i++){s=2*i*d;for(n=0;n<u;n++,o++,s+=2)m[s]=f[o]}f=e.items=null;var p=new Float32Array(d+8);if(1===d){if(0!=(1&r))for(l=0,o=0;l<g;l++,o+=d)m[o]*=.5}else for(l=0,o=0;l<g;l++,o+=d){p.set(m.subarray(o,o+d),4);this.extend(p,4,d);this.filter(p,4,d);m.set(p.subarray(4,4+d),o)}var v=16,b=[];for(i=0;i<v;i++)b.push(new Float32Array(g+8));var y,w=0;e=4+g;if(1===g){if(0!=(1&a))for(c=0;c<d;c++)m[c]*=.5}else for(c=0;c<d;c++){if(0===w){v=Math.min(d-c,v);for(o=c,s=4;s<e;o+=d,s++)for(y=0;y<v;y++)b[y][s]=m[o+y];w=v}var k=b[--w];this.extend(k,4,g);this.filter(k,4,g);if(0===w){o=c-v+1;for(s=4;s<e;o+=d,s++)for(y=0;y<v;y++)m[o+y]=b[y][s]}}return{width:d,height:g,items:m}};return e}(),S=function(){function e(){k.call(this)}e.prototype=Object.create(k.prototype);e.prototype.filter=function(e,t,r){var a,i,n,o,s=r>>1,c=-1.586134342059924,l=-.052980118572961,u=.882911075530934,h=.443506852043971,f=1.230174104914001;a=(t|=0)-3;for(i=s+4;i--;a+=2)e[a]*=.8128930661159609;n=h*e[(a=t-2)-1];for(i=s+3;i--;a+=2){o=h*e[a+1];e[a]=f*e[a]-n-o;if(!i--)break;n=h*e[(a+=2)+1];e[a]=f*e[a]-n-o}n=u*e[(a=t-1)-1];for(i=s+2;i--;a+=2){o=u*e[a+1];e[a]-=n+o;if(!i--)break;n=u*e[(a+=2)+1];e[a]-=n+o}n=l*e[(a=t)-1];for(i=s+1;i--;a+=2){o=l*e[a+1];e[a]-=n+o;if(!i--)break;n=l*e[(a+=2)+1];e[a]-=n+o}if(0!==s){n=c*e[(a=t+1)-1];for(i=s;i--;a+=2){o=c*e[a+1];e[a]-=n+o;if(!i--)break;n=c*e[(a+=2)+1];e[a]-=n+o}}};return e}(),C=function(){function e(){k.call(this)}e.prototype=Object.create(k.prototype);e.prototype.filter=function(e,t,r){var a,i,n=r>>1;for(a=t|=0,i=n+1;i--;a+=2)e[a]-=e[a-1]+e[a+1]+2>>2;for(a=t+1,i=n;i--;a+=2)e[a]+=e[a-1]+e[a+1]>>1};return e}();return t}();t.JpxImage=o},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.calculateSHA512=t.calculateSHA384=t.calculateSHA256=t.calculateMD5=t.PDF20=t.PDF17=t.CipherTransformFactory=t.ARCFourCipher=t.AES256Cipher=t.AES128Cipher=void 0;var a=function(){function e(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1;a.configurable=!0;"value"in a&&(a.writable=!0);Object.defineProperty(e,a.key,a)}}return function(t,r,a){r&&e(t.prototype,r);a&&e(t,a);return t}}(),i=r(2),n=r(138),o=r(140);function s(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function c(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}});t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function l(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var u=function(){function e(e){this.a=0;this.b=0;var t,r,a=new Uint8Array(256),i=0,n=e.length;for(t=0;t<256;++t)a[t]=t;for(t=0;t<256;++t){i=i+(r=a[t])+e[t%n]&255;a[t]=a[i];a[i]=r}this.s=a}e.prototype={encryptBlock:function(e){var t,r,a,i=e.length,n=this.a,o=this.b,s=this.s,c=new Uint8Array(i);for(t=0;t<i;++t){a=s[o=o+(r=s[n=n+1&255])&255];s[n]=a;s[o]=r;c[t]=e[t]^s[r+a&255]}this.a=n;this.b=o;return c}};e.prototype.decryptBlock=e.prototype.encryptBlock;return e}(),h=function(){var e=new Uint8Array([7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21]),t=new Int32Array([-680876936,-389564586,606105819,-1044525330,-176418897,1200080426,-1473231341,-45705983,1770035416,-1958414417,-42063,-1990404162,1804603682,-40341101,-1502002290,1236535329,-165796510,-1069501632,643717713,-373897302,-701558691,38016083,-660478335,-405537848,568446438,-1019803690,-187363961,1163531501,-1444681467,-51403784,1735328473,-1926607734,-378558,-2022574463,1839030562,-35309556,-1530992060,1272893353,-155497632,-1094730640,681279174,-358537222,-722521979,76029189,-640364487,-421815835,530742520,-995338651,-198630844,1126891415,-1416354905,-57434055,1700485571,-1894986606,-1051523,-2054922799,1873313359,-30611744,-1560198380,1309151649,-145523070,-1120210379,718787259,-343485551]);return function(r,a,i){var n,o,s,c=1732584193,l=-271733879,u=-1732584194,h=271733878,f=i+72&-64,d=new Uint8Array(f);for(n=0;n<i;++n)d[n]=r[a++];d[n++]=128;s=f-8;for(;n<s;)d[n++]=0;d[n++]=i<<3&255;d[n++]=i>>5&255;d[n++]=i>>13&255;d[n++]=i>>21&255;d[n++]=i>>>29&255;d[n++]=0;d[n++]=0;d[n++]=0;var g=new Int32Array(16);for(n=0;n<f;){for(o=0;o<16;++o,n+=4)g[o]=d[n]|d[n+1]<<8|d[n+2]<<16|d[n+3]<<24;var m,p,v=c,b=l,y=u,w=h;for(o=0;o<64;++o){if(o<16){m=b&y|~b&w;p=o}else if(o<32){m=w&b|~w&y;p=5*o+1&15}else if(o<48){m=b^y^w;p=3*o+5&15}else{m=y^(b|~w);p=7*o&15}var k=w,S=v+m+t[o]+g[p]|0,C=e[o];w=y;y=b;b=b+(S<<C|S>>>32-C)|0;v=k}c=c+v|0;l=l+b|0;u=u+y|0;h=h+w|0}return new Uint8Array([255&c,c>>8&255,c>>16&255,c>>>24&255,255&l,l>>8&255,l>>16&255,l>>>24&255,255&u,u>>8&255,u>>16&255,u>>>24&255,255&h,h>>8&255,h>>16&255,h>>>24&255])}}(),f=function(){function e(e,t){this.high=0|e;this.low=0|t}e.prototype={and:function(e){this.high&=e.high;this.low&=e.low},xor:function(e){this.high^=e.high;this.low^=e.low},or:function(e){this.high|=e.high;this.low|=e.low},shiftRight:function(e){if(e>=32){this.low=this.high>>>e-32|0;this.high=0}else{this.low=this.low>>>e|this.high<<32-e;this.high=this.high>>>e|0}},shiftLeft:function(e){if(e>=32){this.high=this.low<<e-32;this.low=0}else{this.high=this.high<<e|this.low>>>32-e;this.low=this.low<<e}},rotateRight:function(e){var t,r;if(32&e){r=this.low;t=this.high}else{t=this.low;r=this.high}e&=31;this.low=t>>>e|r<<32-e;this.high=r>>>e|t<<32-e},not:function(){this.high=~this.high;this.low=~this.low},add:function(e){var t=(this.low>>>0)+(e.low>>>0),r=(this.high>>>0)+(e.high>>>0);t>4294967295&&(r+=1);this.low=0|t;this.high=0|r},copyTo:function(e,t){e[t]=this.high>>>24&255;e[t+1]=this.high>>16&255;e[t+2]=this.high>>8&255;e[t+3]=255&this.high;e[t+4]=this.low>>>24&255;e[t+5]=this.low>>16&255;e[t+6]=this.low>>8&255;e[t+7]=255&this.low},assign:function(e){this.high=e.high;this.low=e.low}};return e}(),d=function(){function e(e,t){return e>>>t|e<<32-t}function t(e,t,r){return e&t^~e&r}function r(e,t,r){return e&t^e&r^t&r}function a(t){return e(t,2)^e(t,13)^e(t,22)}function i(t){return e(t,6)^e(t,11)^e(t,25)}function n(t){return e(t,7)^e(t,18)^t>>>3}var o=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298];return function(s,c,l){var u,h,f,d=1779033703,g=3144134277,m=1013904242,p=2773480762,v=1359893119,b=2600822924,y=528734635,w=1541459225,k=64*Math.ceil((l+9)/64),S=new Uint8Array(k);for(u=0;u<l;++u)S[u]=s[c++];S[u++]=128;f=k-8;for(;u<f;)S[u++]=0;S[u++]=0;S[u++]=0;S[u++]=0;S[u++]=l>>>29&255;S[u++]=l>>21&255;S[u++]=l>>13&255;S[u++]=l>>5&255;S[u++]=l<<3&255;var C,x=new Uint32Array(64);for(u=0;u<k;){for(h=0;h<16;++h){x[h]=S[u]<<24|S[u+1]<<16|S[u+2]<<8|S[u+3];u+=4}for(h=16;h<64;++h)x[h]=(e(C=x[h-2],17)^e(C,19)^C>>>10)+x[h-7]+n(x[h-15])+x[h-16]|0;var _,A,P=d,I=g,O=m,T=p,E=v,F=b,R=y,B=w;for(h=0;h<64;++h){_=B+i(E)+t(E,F,R)+o[h]+x[h];A=a(P)+r(P,I,O);B=R;R=F;F=E;E=T+_|0;T=O;O=I;I=P;P=_+A|0}d=d+P|0;g=g+I|0;m=m+O|0;p=p+T|0;v=v+E|0;b=b+F|0;y=y+R|0;w=w+B|0}return new Uint8Array([d>>24&255,d>>16&255,d>>8&255,255&d,g>>24&255,g>>16&255,g>>8&255,255&g,m>>24&255,m>>16&255,m>>8&255,255&m,p>>24&255,p>>16&255,p>>8&255,255&p,v>>24&255,v>>16&255,v>>8&255,255&v,b>>24&255,b>>16&255,b>>8&255,255&b,y>>24&255,y>>16&255,y>>8&255,255&y,w>>24&255,w>>16&255,w>>8&255,255&w])}}(),g=function(){function e(e,t,r,a,i){e.assign(t);e.and(r);i.assign(t);i.not();i.and(a);e.xor(i)}function t(e,t,r,a,i){e.assign(t);e.and(r);i.assign(t);i.and(a);e.xor(i);i.assign(r);i.and(a);e.xor(i)}function r(e,t,r){e.assign(t);e.rotateRight(28);r.assign(t);r.rotateRight(34);e.xor(r);r.assign(t);r.rotateRight(39);e.xor(r)}function a(e,t,r){e.assign(t);e.rotateRight(14);r.assign(t);r.rotateRight(18);e.xor(r);r.assign(t);r.rotateRight(41);e.xor(r)}function i(e,t,r){e.assign(t);e.rotateRight(1);r.assign(t);r.rotateRight(8);e.xor(r);r.assign(t);r.shiftRight(7);e.xor(r)}function n(e,t,r){e.assign(t);e.rotateRight(19);r.assign(t);r.rotateRight(61);e.xor(r);r.assign(t);r.shiftRight(6);e.xor(r)}var o=[new f(1116352408,3609767458),new f(1899447441,602891725),new f(3049323471,3964484399),new f(3921009573,2173295548),new f(961987163,4081628472),new f(1508970993,3053834265),new f(2453635748,2937671579),new f(2870763221,3664609560),new f(3624381080,2734883394),new f(310598401,1164996542),new f(607225278,1323610764),new f(1426881987,3590304994),new f(1925078388,4068182383),new f(2162078206,991336113),new f(2614888103,633803317),new f(3248222580,3479774868),new f(3835390401,2666613458),new f(4022224774,944711139),new f(264347078,2341262773),new f(604807628,2007800933),new f(770255983,1495990901),new f(1249150122,1856431235),new f(1555081692,3175218132),new f(1996064986,2198950837),new f(2554220882,3999719339),new f(2821834349,766784016),new f(2952996808,2566594879),new f(3210313671,3203337956),new f(3336571891,1034457026),new f(3584528711,2466948901),new f(113926993,3758326383),new f(338241895,168717936),new f(666307205,1188179964),new f(773529912,1546045734),new f(1294757372,1522805485),new f(1396182291,2643833823),new f(1695183700,2343527390),new f(1986661051,1014477480),new f(2177026350,1206759142),new f(2456956037,344077627),new f(2730485921,1290863460),new f(2820302411,3158454273),new f(3259730800,3505952657),new f(3345764771,106217008),new f(3516065817,3606008344),new f(3600352804,1432725776),new f(4094571909,1467031594),new f(275423344,851169720),new f(430227734,3100823752),new f(506948616,1363258195),new f(659060556,3750685593),new f(883997877,3785050280),new f(958139571,3318307427),new f(1322822218,3812723403),new f(1537002063,2003034995),new f(1747873779,3602036899),new f(1955562222,1575990012),new f(2024104815,1125592928),new f(2227730452,2716904306),new f(2361852424,442776044),new f(2428436474,593698344),new f(2756734187,3733110249),new f(3204031479,2999351573),new f(3329325298,3815920427),new f(3391569614,3928383900),new f(3515267271,566280711),new f(3940187606,3454069534),new f(4118630271,4000239992),new f(116418474,1914138554),new f(174292421,2731055270),new f(289380356,3203993006),new f(460393269,320620315),new f(685471733,587496836),new f(852142971,1086792851),new f(1017036298,365543100),new f(1126000580,2618297676),new f(1288033470,3409855158),new f(1501505948,4234509866),new f(1607167915,987167468),new f(1816402316,1246189591)];return function(s,c,l,u){var h,d,g,m,p,v,b,y;if(u=!!u){h=new f(3418070365,3238371032);d=new f(1654270250,914150663);g=new f(2438529370,812702999);m=new f(355462360,4144912697);p=new f(1731405415,4290775857);v=new f(2394180231,1750603025);b=new f(3675008525,1694076839);y=new f(1203062813,3204075428)}else{h=new f(1779033703,4089235720);d=new f(3144134277,2227873595);g=new f(1013904242,4271175723);m=new f(2773480762,1595750129);p=new f(1359893119,2917565137);v=new f(2600822924,725511199);b=new f(528734635,4215389547);y=new f(1541459225,327033209)}var w,k,S,C=128*Math.ceil((l+17)/128),x=new Uint8Array(C);for(w=0;w<l;++w)x[w]=s[c++];x[w++]=128;S=C-16;for(;w<S;)x[w++]=0;x[w++]=0;x[w++]=0;x[w++]=0;x[w++]=0;x[w++]=0;x[w++]=0;x[w++]=0;x[w++]=0;x[w++]=0;x[w++]=0;x[w++]=0;x[w++]=l>>>29&255;x[w++]=l>>21&255;x[w++]=l>>13&255;x[w++]=l>>5&255;x[w++]=l<<3&255;var _=new Array(80);for(w=0;w<80;w++)_[w]=new f(0,0);var A,P,I=new f(0,0),O=new f(0,0),T=new f(0,0),E=new f(0,0),F=new f(0,0),R=new f(0,0),B=new f(0,0),D=new f(0,0),M=new f(0,0),L=new f(0,0),N=new f(0,0),U=new f(0,0);for(w=0;w<C;){for(k=0;k<16;++k){_[k].high=x[w]<<24|x[w+1]<<16|x[w+2]<<8|x[w+3];_[k].low=x[w+4]<<24|x[w+5]<<16|x[w+6]<<8|x[w+7];w+=8}for(k=16;k<80;++k){n(A=_[k],_[k-2],U);A.add(_[k-7]);i(N,_[k-15],U);A.add(N);A.add(_[k-16])}I.assign(h);O.assign(d);T.assign(g);E.assign(m);F.assign(p);R.assign(v);B.assign(b);D.assign(y);for(k=0;k<80;++k){M.assign(D);a(N,F,U);M.add(N);e(N,F,R,B,U);M.add(N);M.add(o[k]);M.add(_[k]);r(L,I,U);t(N,I,O,T,U);L.add(N);A=D;D=B;B=R;R=F;E.add(M);F=E;E=T;T=O;O=I;A.assign(M);A.add(L);I=A}h.add(I);d.add(O);g.add(T);m.add(E);p.add(F);v.add(R);b.add(B);y.add(D)}if(u){P=new Uint8Array(48);h.copyTo(P,0);d.copyTo(P,8);g.copyTo(P,16);m.copyTo(P,24);p.copyTo(P,32);v.copyTo(P,40)}else{P=new Uint8Array(64);h.copyTo(P,0);d.copyTo(P,8);g.copyTo(P,16);m.copyTo(P,24);p.copyTo(P,32);v.copyTo(P,40);b.copyTo(P,48);y.copyTo(P,56)}return P}}(),m=function(){return function(e,t,r){return g(e,t,r,!0)}}(),p=function(){function e(){}e.prototype={decryptBlock:function(e){return e}};return e}(),v=function(){function e(){l(this,e);this.constructor===e&&(0,i.unreachable)("Cannot initialize AESBaseCipher.");this._s=new Uint8Array([99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,208,239,170,251,67,77,51,133,69,249,2,127,80,60,159,168,81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,205,12,19,236,95,151,68,23,196,167,126,61,100,93,25,115,96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,224,50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,231,200,55,109,141,213,78,169,108,86,244,234,101,122,174,8,186,120,37,46,28,166,180,198,232,221,116,31,75,189,139,138,112,62,181,102,72,3,246,14,97,53,87,185,134,193,29,158,225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,140,161,137,13,191,230,66,104,65,153,45,15,176,84,187,22]);this._inv_s=new Uint8Array([82,9,106,213,48,54,165,56,191,64,163,158,129,243,215,251,124,227,57,130,155,47,255,135,52,142,67,68,196,222,233,203,84,123,148,50,166,194,35,61,238,76,149,11,66,250,195,78,8,46,161,102,40,217,36,178,118,91,162,73,109,139,209,37,114,248,246,100,134,104,152,22,212,164,92,204,93,101,182,146,108,112,72,80,253,237,185,218,94,21,70,87,167,141,157,132,144,216,171,0,140,188,211,10,247,228,88,5,184,179,69,6,208,44,30,143,202,63,15,2,193,175,189,3,1,19,138,107,58,145,17,65,79,103,220,234,151,242,207,206,240,180,230,115,150,172,116,34,231,173,53,133,226,249,55,232,28,117,223,110,71,241,26,113,29,41,197,137,111,183,98,14,170,24,190,27,252,86,62,75,198,210,121,32,154,219,192,254,120,205,90,244,31,221,168,51,136,7,199,49,177,18,16,89,39,128,236,95,96,81,127,169,25,181,74,13,45,229,122,159,147,201,156,239,160,224,59,77,174,42,245,176,200,235,187,60,131,83,153,97,23,43,4,126,186,119,214,38,225,105,20,99,85,33,12,125]);this._mix=new Uint32Array([0,235474187,470948374,303765277,941896748,908933415,607530554,708780849,1883793496,2118214995,1817866830,1649639237,1215061108,1181045119,1417561698,1517767529,3767586992,4003061179,4236429990,4069246893,3635733660,3602770327,3299278474,3400528769,2430122216,2664543715,2362090238,2193862645,2835123396,2801107407,3035535058,3135740889,3678124923,3576870512,3341394285,3374361702,3810496343,3977675356,4279080257,4043610186,2876494627,2776292904,3076639029,3110650942,2472011535,2640243204,2403728665,2169303058,1001089995,899835584,666464733,699432150,59727847,226906860,530400753,294930682,1273168787,1172967064,1475418501,1509430414,1942435775,2110667444,1876241833,1641816226,2910219766,2743034109,2976151520,3211623147,2505202138,2606453969,2302690252,2269728455,3711829422,3543599269,3240894392,3475313331,3843699074,3943906441,4178062228,4144047775,1306967366,1139781709,1374988112,1610459739,1975683434,2076935265,1775276924,1742315127,1034867998,866637845,566021896,800440835,92987698,193195065,429456164,395441711,1984812685,2017778566,1784663195,1683407248,1315562145,1080094634,1383856311,1551037884,101039829,135050206,437757123,337553864,1042385657,807962610,573804783,742039012,2531067453,2564033334,2328828971,2227573024,2935566865,2700099354,3001755655,3168937228,3868552805,3902563182,4203181171,4102977912,3736164937,3501741890,3265478751,3433712980,1106041591,1340463100,1576976609,1408749034,2043211483,2009195472,1708848333,1809054150,832877231,1068351396,766945465,599762354,159417987,126454664,361929877,463180190,2709260871,2943682380,3178106961,3009879386,2572697195,2538681184,2236228733,2336434550,3509871135,3745345300,3441850377,3274667266,3910161971,3877198648,4110568485,4211818798,2597806476,2497604743,2261089178,2295101073,2733856160,2902087851,3202437046,2968011453,3936291284,3835036895,4136440770,4169408201,3535486456,3702665459,3467192302,3231722213,2051518780,1951317047,1716890410,1750902305,1113818384,1282050075,1584504582,1350078989,168810852,67556463,371049330,404016761,841739592,1008918595,775550814,540080725,3969562369,3801332234,4035489047,4269907996,3569255213,3669462566,3366754619,3332740144,2631065433,2463879762,2160117071,2395588676,2767645557,2868897406,3102011747,3069049960,202008497,33778362,270040487,504459436,875451293,975658646,675039627,641025152,2084704233,1917518562,1615861247,1851332852,1147550661,1248802510,1484005843,1451044056,933301370,967311729,733156972,632953703,260388950,25965917,328671808,496906059,1206477858,1239443753,1543208500,1441952575,2144161806,1908694277,1675577880,1842759443,3610369226,3644379585,3408119516,3307916247,4011190502,3776767469,4077384432,4245618683,2809771154,2842737049,3144396420,3043140495,2673705150,2438237621,2203032232,2370213795]);this._mixCol=new Uint8Array(256);for(var t=0;t<256;t++)this._mixCol[t]=t<128?t<<1:t<<1^27;this.buffer=new Uint8Array(16);this.bufferPosition=0}a(e,[{key:"_expandKey",value:function(e){(0,i.unreachable)("Cannot call `_expandKey` on the base class")}},{key:"_decrypt",value:function(e,t){var r=void 0,a=void 0,i=void 0,n=new Uint8Array(16);n.set(e);for(var o=0,s=this._keySize;o<16;++o,++s)n[o]^=t[s];for(var c=this._cyclesOfRepetition-1;c>=1;--c){r=n[13];n[13]=n[9];n[9]=n[5];n[5]=n[1];n[1]=r;r=n[14];a=n[10];n[14]=n[6];n[10]=n[2];n[6]=r;n[2]=a;r=n[15];a=n[11];i=n[7];n[15]=n[3];n[11]=r;n[7]=a;n[3]=i;for(var l=0;l<16;++l)n[l]=this._inv_s[n[l]];for(var u=0,h=16*c;u<16;++u,++h)n[u]^=t[h];for(var f=0;f<16;f+=4){var d=this._mix[n[f]],g=this._mix[n[f+1]],m=this._mix[n[f+2]],p=this._mix[n[f+3]];r=d^g>>>8^g<<24^m>>>16^m<<16^p>>>24^p<<8;n[f]=r>>>24&255;n[f+1]=r>>16&255;n[f+2]=r>>8&255;n[f+3]=255&r}}r=n[13];n[13]=n[9];n[9]=n[5];n[5]=n[1];n[1]=r;r=n[14];a=n[10];n[14]=n[6];n[10]=n[2];n[6]=r;n[2]=a;r=n[15];a=n[11];i=n[7];n[15]=n[3];n[11]=r;n[7]=a;n[3]=i;for(var v=0;v<16;++v){n[v]=this._inv_s[n[v]];n[v]^=t[v]}return n}},{key:"_encrypt",value:function(e,t){var r=this._s,a=void 0,i=void 0,n=void 0,o=new Uint8Array(16);o.set(e);for(var s=0;s<16;++s)o[s]^=t[s];for(var c=1;c<this._cyclesOfRepetition;c++){for(var l=0;l<16;++l)o[l]=r[o[l]];n=o[1];o[1]=o[5];o[5]=o[9];o[9]=o[13];o[13]=n;n=o[2];i=o[6];o[2]=o[10];o[6]=o[14];o[10]=n;o[14]=i;n=o[3];i=o[7];a=o[11];o[3]=o[15];o[7]=n;o[11]=i;o[15]=a;for(var u=0;u<16;u+=4){var h=o[u+0],f=o[u+1],d=o[u+2],g=o[u+3];a=h^f^d^g;o[u+0]^=a^this._mixCol[h^f];o[u+1]^=a^this._mixCol[f^d];o[u+2]^=a^this._mixCol[d^g];o[u+3]^=a^this._mixCol[g^h]}for(var m=0,p=16*c;m<16;++m,++p)o[m]^=t[p]}for(var v=0;v<16;++v)o[v]=r[o[v]];n=o[1];o[1]=o[5];o[5]=o[9];o[9]=o[13];o[13]=n;n=o[2];i=o[6];o[2]=o[10];o[6]=o[14];o[10]=n;o[14]=i;n=o[3];i=o[7];a=o[11];o[3]=o[15];o[7]=n;o[11]=i;o[15]=a;for(var b=0,y=this._keySize;b<16;++b,++y)o[b]^=t[y];return o}},{key:"_decryptBlock2",value:function(e,t){for(var r=e.length,a=this.buffer,i=this.bufferPosition,n=[],o=this.iv,s=0;s<r;++s){a[i]=e[s];if(!(++i<16)){for(var c=this._decrypt(a,this._key),l=0;l<16;++l)c[l]^=o[l];o=a;n.push(c);a=new Uint8Array(16);i=0}}this.buffer=a;this.bufferLength=i;this.iv=o;if(0===n.length)return new Uint8Array(0);var u=16*n.length;if(t){var h=n[n.length-1],f=h[15];if(f<=16){for(var d=15,g=16-f;d>=g;--d)if(h[d]!==f){f=0;break}u-=f;n[n.length-1]=h.subarray(0,16-f)}}for(var m=new Uint8Array(u),p=0,v=0,b=n.length;p<b;++p,v+=16)m.set(n[p],v);return m}},{key:"decryptBlock",value:function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=e.length,i=this.buffer,n=this.bufferPosition;if(r)this.iv=r;else{for(var o=0;n<16&&o<a;++o,++n)i[n]=e[o];if(n<16){this.bufferLength=n;return new Uint8Array(0)}this.iv=i;e=e.subarray(16)}this.buffer=new Uint8Array(16);this.bufferLength=0;this.decryptBlock=this._decryptBlock2;return this.decryptBlock(e,t)}},{key:"encrypt",value:function(e,t){var r=e.length,a=this.buffer,i=this.bufferPosition,n=[];t||(t=new Uint8Array(16));for(var o=0;o<r;++o){a[i]=e[o];if(!(++i<16)){for(var s=0;s<16;++s)a[s]^=t[s];var c=this._encrypt(a,this._key);t=c;n.push(c);a=new Uint8Array(16);i=0}}this.buffer=a;this.bufferLength=i;this.iv=t;if(0===n.length)return new Uint8Array(0);for(var l=16*n.length,u=new Uint8Array(l),h=0,f=0,d=n.length;h<d;++h,f+=16)u.set(n[h],f);return u}}]);return e}(),b=function(e){c(t,v);function t(e){l(this,t);var r=s(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));r._cyclesOfRepetition=10;r._keySize=160;r._rcon=new Uint8Array([141,1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47,94,188,99,198,151,53,106,212,179,125,250,239,197,145,57,114,228,211,189,97,194,159,37,74,148,51,102,204,131,29,58,116,232,203,141,1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47,94,188,99,198,151,53,106,212,179,125,250,239,197,145,57,114,228,211,189,97,194,159,37,74,148,51,102,204,131,29,58,116,232,203,141,1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47,94,188,99,198,151,53,106,212,179,125,250,239,197,145,57,114,228,211,189,97,194,159,37,74,148,51,102,204,131,29,58,116,232,203,141,1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47,94,188,99,198,151,53,106,212,179,125,250,239,197,145,57,114,228,211,189,97,194,159,37,74,148,51,102,204,131,29,58,116,232,203,141,1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47,94,188,99,198,151,53,106,212,179,125,250,239,197,145,57,114,228,211,189,97,194,159,37,74,148,51,102,204,131,29,58,116,232,203,141]);r._key=r._expandKey(e);return r}a(t,[{key:"_expandKey",value:function(e){var t=this._s,r=this._rcon,a=new Uint8Array(176);a.set(e);for(var i=16,n=1;i<176;++n){var o=a[i-3],s=a[i-2],c=a[i-1],l=a[i-4];o=t[o];s=t[s];c=t[c];l=t[l];o^=r[n];for(var u=0;u<4;++u){a[i]=o^=a[i-16];a[++i]=s^=a[i-16];a[++i]=c^=a[i-16];a[++i]=l^=a[i-16];i++}}return a}}]);return t}(),y=function(e){c(t,v);function t(e){l(this,t);var r=s(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));r._cyclesOfRepetition=14;r._keySize=224;r._key=r._expandKey(e);return r}a(t,[{key:"_expandKey",value:function(e){var t=this._s,r=new Uint8Array(240);r.set(e);for(var a=1,i=void 0,n=void 0,o=void 0,s=void 0,c=32,l=1;c<240;++l){if(c%32==16){i=t[i];n=t[n];o=t[o];s=t[s]}else if(c%32==0){i=r[c-3];n=r[c-2];o=r[c-1];s=r[c-4];i=t[i];n=t[n];o=t[o];s=t[s];i^=a;(a<<=1)>=256&&(a=255&(27^a))}for(var u=0;u<4;++u){r[c]=i^=r[c-32];r[++c]=n^=r[c-32];r[++c]=o^=r[c-32];r[++c]=s^=r[c-32];c++}}return r}}]);return t}(),w=function(){function e(e,t){if(e.length!==t.length)return!1;for(var r=0;r<e.length;r++)if(e[r]!==t[r])return!1;return!0}function t(){}t.prototype={checkOwnerPassword:function(t,r,a,i){var n=new Uint8Array(t.length+56);n.set(t,0);n.set(r,t.length);n.set(a,t.length+r.length);return e(d(n,0,n.length),i)},checkUserPassword:function(t,r,a){var i=new Uint8Array(t.length+8);i.set(t,0);i.set(r,t.length);return e(d(i,0,i.length),a)},getOwnerKey:function(e,t,r,a){var i=new Uint8Array(e.length+56);i.set(e,0);i.set(t,e.length);i.set(r,e.length+t.length);var n=d(i,0,i.length);return new y(n).decryptBlock(a,!1,new Uint8Array(16))},getUserKey:function(e,t,r){var a=new Uint8Array(e.length+8);a.set(e,0);a.set(t,e.length);var i=d(a,0,a.length);return new y(i).decryptBlock(r,!1,new Uint8Array(16))}};return t}(),k=function(){function e(e,t){var r=new Uint8Array(e.length+t.length);r.set(e,0);r.set(t,e.length);return r}function t(t,r,a){for(var i=d(r,0,r.length).subarray(0,32),n=[0],o=0;o<64||n[n.length-1]>o-32;){var s=t.length+i.length+a.length,c=new Uint8Array(64*s),l=e(t,i);l=e(l,a);for(var u=0,h=0;u<64;u++,h+=s)c.set(l,h);n=new b(i.subarray(0,16)).encrypt(c,i.subarray(16,32));for(var f=0,p=0;p<16;p++){f*=1;f%=3;f+=(n[p]>>>0)%3;f%=3}0===f?i=d(n,0,n.length):1===f?i=m(n,0,n.length):2===f&&(i=g(n,0,n.length));o++}return i.subarray(0,32)}function r(){}function a(e,t){if(e.length!==t.length)return!1;for(var r=0;r<e.length;r++)if(e[r]!==t[r])return!1;return!0}r.prototype={hash:function(e,r,a){return t(e,r,a)},checkOwnerPassword:function(e,r,i,n){var o=new Uint8Array(e.length+56);o.set(e,0);o.set(r,e.length);o.set(i,e.length+r.length);return a(t(e,o,i),n)},checkUserPassword:function(e,r,i){var n=new Uint8Array(e.length+8);n.set(e,0);n.set(r,e.length);return a(t(e,n,[]),i)},getOwnerKey:function(e,r,a,i){var n=new Uint8Array(e.length+56);n.set(e,0);n.set(r,e.length);n.set(a,e.length+r.length);var o=t(e,n,a);return new y(o).decryptBlock(i,!1,new Uint8Array(16))},getUserKey:function(e,r,a){var i=new Uint8Array(e.length+8);i.set(e,0);i.set(r,e.length);var n=t(e,i,[]);return new y(n).decryptBlock(a,!1,new Uint8Array(16))}};return r}(),S=function(){function e(e,t){this.StringCipherConstructor=e;this.StreamCipherConstructor=t}e.prototype={createStream:function(e,t){var r=new this.StreamCipherConstructor;return new o.DecryptStream(e,t,function(e,t){return r.decryptBlock(e,t)})},decryptString:function(e){var t=new this.StringCipherConstructor,r=(0,i.stringToBytes)(e);r=t.decryptBlock(r,!0);return(0,i.bytesToString)(r)}};return e}(),C=function(){var e=new Uint8Array([40,191,78,94,78,117,138,65,100,0,78,86,255,250,1,8,46,46,0,182,208,104,62,128,47,12,169,254,100,83,105,122]);function t(t,r,a,i,n,o,s,c){var l,f,d=40+a.length+t.length,g=new Uint8Array(d),m=0;if(r){f=Math.min(32,r.length);for(;m<f;++m)g[m]=r[m]}l=0;for(;m<32;)g[m++]=e[l++];for(l=0,f=a.length;l<f;++l)g[m++]=a[l];g[m++]=255&n;g[m++]=n>>8&255;g[m++]=n>>16&255;g[m++]=n>>>24&255;for(l=0,f=t.length;l<f;++l)g[m++]=t[l];if(o>=4&&!c){g[m++]=255;g[m++]=255;g[m++]=255;g[m++]=255}var p=h(g,0,m),v=s>>3;if(o>=3)for(l=0;l<50;++l)p=h(p,0,v);var b,y=p.subarray(0,v);if(o>=3){for(m=0;m<32;++m)g[m]=e[m];for(l=0,f=t.length;l<f;++l)g[m++]=t[l];b=new u(y).encryptBlock(h(g,0,m));f=y.length;var w,k=new Uint8Array(f);for(l=1;l<=19;++l){for(w=0;w<f;++w)k[w]=y[w]^l;b=new u(k).encryptBlock(b)}for(l=0,f=b.length;l<f;++l)if(i[l]!==b[l])return null}else for(l=0,f=(b=new u(y).encryptBlock(e)).length;l<f;++l)if(i[l]!==b[l])return null;return y}var r=n.Name.get("Identity");function a(a,o,s){var c=a.get("Filter");if(!(0,n.isName)(c,"Standard"))throw new i.FormatError("unknown encryption method");this.dict=a;var l=a.get("V");if(!Number.isInteger(l)||1!==l&&2!==l&&4!==l&&5!==l)throw new i.FormatError("unsupported encryption algorithm");this.algorithm=l;var f=a.get("Length");if(!f)if(l<=3)f=40;else{var d=a.get("CF"),g=a.get("StmF");if((0,n.isDict)(d)&&(0,n.isName)(g)){d.suppressEncryption=!0;var m=d.get(g.name);(f=m&&m.get("Length")||128)<40&&(f<<=3)}}if(!Number.isInteger(f)||f<40||f%8!=0)throw new i.FormatError("invalid key length");var p=(0,i.stringToBytes)(a.get("O")).subarray(0,32),v=(0,i.stringToBytes)(a.get("U")).subarray(0,32),b=a.get("P"),y=a.get("R"),S=(4===l||5===l)&&!1!==a.get("EncryptMetadata");this.encryptMetadata=S;var C,x,_=(0,i.stringToBytes)(o);if(s){if(6===y)try{s=(0,i.utf8StringToString)(s)}catch(e){(0,i.warn)("CipherTransformFactory: Unable to convert UTF8 encoded password.")}C=(0,i.stringToBytes)(s)}if(5!==l)x=t(_,C,p,v,b,y,f,S);else{var A=(0,i.stringToBytes)(a.get("O")).subarray(32,40),P=(0,i.stringToBytes)(a.get("O")).subarray(40,48),I=(0,i.stringToBytes)(a.get("U")).subarray(0,48),O=(0,i.stringToBytes)(a.get("U")).subarray(32,40),T=(0,i.stringToBytes)(a.get("U")).subarray(40,48),E=(0,i.stringToBytes)(a.get("OE")),F=(0,i.stringToBytes)(a.get("UE"));(0,i.stringToBytes)(a.get("Perms"));x=function(e,t,r,a,i,n,o,s,c,l,u,h){if(t){var f=Math.min(127,t.length);t=t.subarray(0,f)}else t=[];var d;return(d=6===e?new k:new w).checkUserPassword(t,s,o)?d.getUserKey(t,c,u):t.length&&d.checkOwnerPassword(t,a,n,r)?d.getOwnerKey(t,i,n,l):null}(y,C,p,A,P,I,v,O,T,E,F)}if(!x&&!s)throw new i.PasswordException("No password given",i.PasswordResponses.NEED_PASSWORD);if(!x&&s){x=t(_,function(t,r,a,i){var n,o,s=new Uint8Array(32),c=0;o=Math.min(32,t.length);for(;c<o;++c)s[c]=t[c];n=0;for(;c<32;)s[c++]=e[n++];var l,f=h(s,0,c),d=i>>3;if(a>=3)for(n=0;n<50;++n)f=h(f,0,f.length);if(a>=3){l=r;var g,m=new Uint8Array(d);for(n=19;n>=0;n--){for(g=0;g<d;++g)m[g]=f[g]^n;l=new u(m).encryptBlock(l)}}else l=new u(f.subarray(0,d)).encryptBlock(r);return l}(C,p,y,f),p,v,b,y,f,S)}if(!x)throw new i.PasswordException("Incorrect Password",i.PasswordResponses.INCORRECT_PASSWORD);this.encryptionKey=x;if(l>=4){var R=a.get("CF");(0,n.isDict)(R)&&(R.suppressEncryption=!0);this.cf=R;this.stmf=a.get("StmF")||r;this.strf=a.get("StrF")||r;this.eff=a.get("EFF")||this.stmf}}function o(e,t,r,a){var i,n,o=new Uint8Array(r.length+9);for(i=0,n=r.length;i<n;++i)o[i]=r[i];o[i++]=255&e;o[i++]=e>>8&255;o[i++]=e>>16&255;o[i++]=255&t;o[i++]=t>>8&255;if(a){o[i++]=115;o[i++]=65;o[i++]=108;o[i++]=84}return h(o,0,i).subarray(0,Math.min(r.length+5,16))}function s(e,t,r,a,s){if(!(0,n.isName)(t))throw new i.FormatError("Invalid crypt filter name.");var c,l=e.get(t.name);null!==l&&void 0!==l&&(c=l.get("CFM"));if(!c||"None"===c.name)return function(){return new p};if("V2"===c.name)return function(){return new u(o(r,a,s,!1))};if("AESV2"===c.name)return function(){return new b(o(r,a,s,!0))};if("AESV3"===c.name)return function(){return new y(s)};throw new i.FormatError("Unknown crypto method")}a.prototype={createCipherTransform:function(e,t){if(4===this.algorithm||5===this.algorithm)return new S(s(this.cf,this.stmf,e,t,this.encryptionKey),s(this.cf,this.strf,e,t,this.encryptionKey));var r=o(e,t,this.encryptionKey,!1),a=function(){return new u(r)};return new S(a,a)}};return a}();t.AES128Cipher=b;t.AES256Cipher=y;t.ARCFourCipher=u;t.CipherTransformFactory=C;t.PDF17=w;t.PDF20=k;t.calculateMD5=h;t.calculateSHA256=d;t.calculateSHA384=m;t.calculateSHA512=g},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.ColorSpace=void 0;var a=function(){function e(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1;a.configurable=!0;"value"in a&&(a.writable=!0);Object.defineProperty(e,a.key,a)}}return function(t,r,a){r&&e(t.prototype,r);a&&e(t,a);return t}}(),i=r(2),n=r(138);function o(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}});t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function c(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var l=function(){function e(t,r){c(this,e);this.constructor===e&&(0,i.unreachable)("Cannot initialize ColorSpace.");this.name=t;this.numComps=r}a(e,[{key:"getRgb",value:function(e,t){var r=new Uint8ClampedArray(3);this.getRgbItem(e,t,r,0);return r}},{key:"getRgbItem",value:function(e,t,r,a){(0,i.unreachable)("Should not call ColorSpace.getRgbItem")}},{key:"getRgbBuffer",value:function(e,t,r,a,n,o,s){(0,i.unreachable)("Should not call ColorSpace.getRgbBuffer")}},{key:"getOutputLength",value:function(e,t){(0,i.unreachable)("Should not call ColorSpace.getOutputLength")}},{key:"isPassthrough",value:function(e){return!1}},{key:"fillRgb",value:function(e,t,r,a,i,n,o,s,c){var l=t*r,u=null,h=1<<o,f=r!==i||t!==a;if(this.isPassthrough(o))u=s;else if(1===this.numComps&&l>h&&"DeviceGray"!==this.name&&"DeviceRGB"!==this.name){for(var d=o<=8?new Uint8Array(h):new Uint16Array(h),g=0;g<h;g++)d[g]=g;var m=new Uint8ClampedArray(3*h);this.getRgbBuffer(d,0,h,m,0,o,0);if(f){u=new Uint8Array(3*l);for(var p=0,v=0;v<l;++v){var b=3*s[v];u[p++]=m[b];u[p++]=m[b+1];u[p++]=m[b+2]}}else for(var y=0,w=0;w<l;++w){var k=3*s[w];e[y++]=m[k];e[y++]=m[k+1];e[y++]=m[k+2];y+=c}}else if(f){u=new Uint8ClampedArray(3*l);this.getRgbBuffer(s,0,l,u,0,o,0)}else this.getRgbBuffer(s,0,a*n,e,0,o,c);if(u)if(f)!function(e,t,r,a,i,n,o){o=1!==o?0:o;for(var s=r/i,c=a/n,l=0,u=void 0,h=new Uint16Array(i),f=3*r,d=0;d<i;d++)h[d]=3*Math.floor(d*s);for(var g=0;g<n;g++)for(var m=Math.floor(g*c)*f,p=0;p<i;p++){u=m+h[p];t[l++]=e[u++];t[l++]=e[u++];t[l++]=e[u++];l+=o}}(u,e,t,r,a,i,c);else for(var S=0,C=0,x=0,_=a*n;x<_;x++){e[S++]=u[C++];e[S++]=u[C++];e[S++]=u[C++];S+=c}}},{key:"usesZeroToOneRange",get:function(){return(0,i.shadow)(this,"usesZeroToOneRange",!0)}}],[{key:"parse",value:function(e,t,r,a){var i=this.parseToIR(e,t,r,a);return this.fromIR(i)}},{key:"fromIR",value:function(e){var t=Array.isArray(e)?e[0]:e,r=void 0,a=void 0,n=void 0;switch(t){case"DeviceGrayCS":return this.singletons.gray;case"DeviceRgbCS":return this.singletons.rgb;case"DeviceCmykCS":return this.singletons.cmyk;case"CalGrayCS":r=e[1];a=e[2];n=e[3];return new p(r,a,n);case"CalRGBCS":r=e[1];a=e[2];n=e[3];var o=e[4];return new v(r,a,n,o);case"PatternCS":var s=e[1];s&&(s=this.fromIR(s));return new h(s);case"IndexedCS":var c=e[1],l=e[2],d=e[3];return new f(this.fromIR(c),l,d);case"AlternateCS":var g=e[1],m=e[2],y=e[3];return new u(g,this.fromIR(m),y);case"LabCS":r=e[1];a=e[2];var w=e[3];return new b(r,a,w);default:throw new i.FormatError("Unknown colorspace name: "+t)}}},{key:"parseToIR",value:function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=arguments[3];e=t.fetchIfRef(e);if((0,n.isName)(e))switch(e.name){case"DeviceGray":case"G":return"DeviceGrayCS";case"DeviceRGB":case"RGB":return"DeviceRgbCS";case"DeviceCMYK":case"CMYK":return"DeviceCmykCS";case"Pattern":return["PatternCS",null];default:if((0,n.isDict)(r)){var o=r.get("ColorSpace");if((0,n.isDict)(o)){var s=o.get(e.name);if(s){if((0,n.isName)(s))return this.parseToIR(s,t,r,a);e=s;break}}}throw new i.FormatError("unrecognized colorspace "+e.name)}if(Array.isArray(e)){var c=t.fetchIfRef(e[0]).name,l=void 0,u=void 0,h=void 0;switch(c){case"DeviceGray":case"G":return"DeviceGrayCS";case"DeviceRGB":case"RGB":return"DeviceRgbCS";case"DeviceCMYK":case"CMYK":return"DeviceCmykCS";case"CalGray":return["CalGrayCS",(u=t.fetchIfRef(e[1])).getArray("WhitePoint"),u.getArray("BlackPoint"),u.get("Gamma")];case"CalRGB":return["CalRGBCS",(u=t.fetchIfRef(e[1])).getArray("WhitePoint"),u.getArray("BlackPoint"),u.getArray("Gamma"),u.getArray("Matrix")];case"ICCBased":var f=t.fetchIfRef(e[1]).dict;l=f.get("N");if(h=f.get("Alternate")){var d=this.parseToIR(h,t,r,a);if(this.fromIR(d,a).numComps===l)return d;(0,i.warn)("ICCBased color space: Ignoring incorrect /Alternate entry.")}if(1===l)return"DeviceGrayCS";if(3===l)return"DeviceRgbCS";if(4===l)return"DeviceCmykCS";break;case"Pattern":var g=e[1]||null;g&&(g=this.parseToIR(g,t,r,a));return["PatternCS",g];case"Indexed":case"I":var m=this.parseToIR(e[1],t,r,a),p=t.fetchIfRef(e[2])+1,v=t.fetchIfRef(e[3]);(0,n.isStream)(v)&&(v=v.getBytes());return["IndexedCS",m,p,v];case"Separation":case"DeviceN":var b=t.fetchIfRef(e[1]);return["AlternateCS",l=Array.isArray(b)?b.length:1,h=this.parseToIR(e[2],t,r,a),a.create(t.fetchIfRef(e[3]))];case"Lab":return["LabCS",(u=t.fetchIfRef(e[1])).getArray("WhitePoint"),u.getArray("BlackPoint"),u.getArray("Range")];default:throw new i.FormatError('unimplemented color space object "'+c+'"')}}throw new i.FormatError('unrecognized color space object: "'+e+'"')}},{key:"isDefaultDecode",value:function(e,t){if(!Array.isArray(e))return!0;if(2*t!==e.length){(0,i.warn)("The decode map is not the correct length");return!0}for(var r=0,a=e.length;r<a;r+=2)if(0!==e[r]||1!==e[r+1])return!1;return!0}},{key:"singletons",get:function(){return(0,i.shadow)(this,"singletons",{get gray(){return(0,i.shadow)(this,"gray",new d)},get rgb(){return(0,i.shadow)(this,"rgb",new g)},get cmyk(){return(0,i.shadow)(this,"cmyk",new m)}})}}]);return e}(),u=function(e){s(t,l);function t(e,r,a){c(this,t);var i=o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,"Alternate",e));i.base=r;i.tintFn=a;i.tmpBuf=new Float32Array(r.numComps);return i}a(t,[{key:"getRgbItem",value:function(e,t,r,a){var i=this.tmpBuf;this.tintFn(e,t,i,0);this.base.getRgbItem(i,0,r,a)}},{key:"getRgbBuffer",value:function(e,t,r,a,i,n,o){var s=this.tintFn,c=this.base,l=1/((1<<n)-1),u=c.numComps,h=c.usesZeroToOneRange,f=(c.isPassthrough(8)||!h)&&0===o,d=f?i:0,g=f?a:new Uint8ClampedArray(u*r),m=this.numComps,p=new Float32Array(m),v=new Float32Array(u),b=void 0,y=void 0;for(b=0;b<r;b++){for(y=0;y<m;y++)p[y]=e[t++]*l;s(p,0,v,0);if(h)for(y=0;y<u;y++)g[d++]=255*v[y];else{c.getRgbItem(v,0,g,d);d+=u}}f||c.getRgbBuffer(g,0,r,a,i,8,o)}},{key:"getOutputLength",value:function(e,t){return this.base.getOutputLength(e*this.base.numComps/this.numComps,t)}},{key:"isDefaultDecode",value:function(e){return l.isDefaultDecode(e,this.numComps)}}]);return t}(),h=function(e){s(t,l);function t(e){c(this,t);var r=o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,"Pattern",null));r.base=e;return r}return t}(),f=function(e){s(t,l);function t(e,r,a){c(this,t);var s=o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,"Indexed",1));s.base=e;s.highVal=r;var l=e.numComps*r;if((0,n.isStream)(a)){s.lookup=new Uint8Array(l);var u=a.getBytes(l);s.lookup.set(u)}else if((0,i.isString)(a)){s.lookup=new Uint8Array(l);for(var h=0;h<l;++h)s.lookup[h]=a.charCodeAt(h)}else{if(!(a instanceof Uint8Array))throw new i.FormatError("Unrecognized lookup table: "+a);s.lookup=a}return s}a(t,[{key:"getRgbItem",value:function(e,t,r,a){var i=this.base.numComps,n=e[t]*i;this.base.getRgbBuffer(this.lookup,n,1,r,a,8,0)}},{key:"getRgbBuffer",value:function(e,t,r,a,i,n,o){for(var s=this.base,c=s.numComps,l=s.getOutputLength(c,o),u=this.lookup,h=0;h<r;++h){var f=e[t++]*c;s.getRgbBuffer(u,f,1,a,i,8,o);i+=l}}},{key:"getOutputLength",value:function(e,t){return this.base.getOutputLength(e*this.base.numComps,t)}},{key:"isDefaultDecode",value:function(e){return!0}}]);return t}(),d=function(e){s(t,l);function t(){c(this,t);return o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,"DeviceGray",1))}a(t,[{key:"getRgbItem",value:function(e,t,r,a){var i=255*e[t];r[a]=r[a+1]=r[a+2]=i}},{key:"getRgbBuffer",value:function(e,t,r,a,i,n,o){for(var s=255/((1<<n)-1),c=t,l=i,u=0;u<r;++u){var h=s*e[c++];a[l++]=h;a[l++]=h;a[l++]=h;l+=o}}},{key:"getOutputLength",value:function(e,t){return e*(3+t)}},{key:"isDefaultDecode",value:function(e){return l.isDefaultDecode(e,this.numComps)}}]);return t}(),g=function(e){s(t,l);function t(){c(this,t);return o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,"DeviceRGB",3))}a(t,[{key:"getRgbItem",value:function(e,t,r,a){r[a]=255*e[t];r[a+1]=255*e[t+1];r[a+2]=255*e[t+2]}},{key:"getRgbBuffer",value:function(e,t,r,a,i,n,o){if(8!==n||0!==o)for(var s=255/((1<<n)-1),c=t,l=i,u=0;u<r;++u){a[l++]=s*e[c++];a[l++]=s*e[c++];a[l++]=s*e[c++];l+=o}else a.set(e.subarray(t,t+3*r),i)}},{key:"getOutputLength",value:function(e,t){return e*(3+t)/3|0}},{key:"isPassthrough",value:function(e){return 8===e}},{key:"isDefaultDecode",value:function(e){return l.isDefaultDecode(e,this.numComps)}}]);return t}(),m=function(){function e(e,t,r,a,i){var n=e[t]*r,o=e[t+1]*r,s=e[t+2]*r,c=e[t+3]*r;a[i]=255+n*(-4.387332384609988*n+54.48615194189176*o+18.82290502165302*s+212.25662451639585*c-285.2331026137004)+o*(1.7149763477362134*o-5.6096736904047315*s+-17.873870861415444*c-5.497006427196366)+s*(-2.5217340131683033*s-21.248923337353073*c+17.5119270841813)+c*(-21.86122147463605*c-189.48180835922747);a[i+1]=255+n*(8.841041422036149*n+60.118027045597366*o+6.871425592049007*s+31.159100130055922*c-79.2970844816548)+o*(-15.310361306967817*o+17.575251261109482*s+131.35250912493976*c-190.9453302588951)+s*(4.444339102852739*s+9.8632861493405*c-24.86741582555878)+c*(-20.737325471181034*c-187.80453709719578);a[i+2]=255+n*(.8842522430003296*n+8.078677503112928*o+30.89978309703729*s-.23883238689178934*c-14.183576799673286)+o*(10.49593273432072*o+63.02378494754052*s+50.606957656360734*c-112.23884253719248)+s*(.03296041114873217*s+115.60384449646641*c-193.58209356861505)+c*(-22.33816807309886*c-180.12613974708367)}return function(t){s(r,l);function r(){c(this,r);return o(this,(r.__proto__||Object.getPrototypeOf(r)).call(this,"DeviceCMYK",4))}a(r,[{key:"getRgbItem",value:function(t,r,a,i){e(t,r,1,a,i)}},{key:"getRgbBuffer",value:function(t,r,a,i,n,o,s){for(var c=1/((1<<o)-1),l=0;l<a;l++){e(t,r,c,i,n);r+=4;n+=3+s}}},{key:"getOutputLength",value:function(e,t){return e/4*(3+t)|0}},{key:"isDefaultDecode",value:function(e){return l.isDefaultDecode(e,this.numComps)}}]);return r}()}(),p=function(){function e(e,t,r,a,i,n){var o=t[r]*n,s=Math.pow(o,e.G),c=e.YW*s,l=Math.max(295.8*Math.pow(c,.3333333333333333)-40.8,0);a[i]=l;a[i+1]=l;a[i+2]=l}return function(t){s(r,l);function r(e,t,a){c(this,r);var n=o(this,(r.__proto__||Object.getPrototypeOf(r)).call(this,"CalGray",1));if(!e)throw new i.FormatError("WhitePoint missing - required for color space CalGray");t=t||[0,0,0];a=a||1;n.XW=e[0];n.YW=e[1];n.ZW=e[2];n.XB=t[0];n.YB=t[1];n.ZB=t[2];n.G=a;if(n.XW<0||n.ZW<0||1!==n.YW)throw new i.FormatError("Invalid WhitePoint components for "+n.name+", no fallback available");if(n.XB<0||n.YB<0||n.ZB<0){(0,i.info)("Invalid BlackPoint for "+n.name+", falling back to default.");n.XB=n.YB=n.ZB=0}0===n.XB&&0===n.YB&&0===n.ZB||(0,i.warn)(n.name+", BlackPoint: XB: "+n.XB+", YB: "+n.YB+", ZB: "+n.ZB+", only default values are supported.");if(n.G<1){(0,i.info)("Invalid Gamma: "+n.G+" for "+n.name+", falling back to default.");n.G=1}return n}a(r,[{key:"getRgbItem",value:function(t,r,a,i){e(this,t,r,a,i,1)}},{key:"getRgbBuffer",value:function(t,r,a,i,n,o,s){for(var c=1/((1<<o)-1),l=0;l<a;++l){e(this,t,r,i,n,c);r+=1;n+=3+s}}},{key:"getOutputLength",value:function(e,t){return e*(3+t)}},{key:"isDefaultDecode",value:function(e){return l.isDefaultDecode(e,this.numComps)}}]);return r}()}(),v=function(){var e=new Float32Array([.8951,.2664,-.1614,-.7502,1.7135,.0367,.0389,-.0685,1.0296]),t=new Float32Array([.9869929,-.1470543,.1599627,.4323053,.5183603,.0492912,-.0085287,.0400428,.9684867]),r=new Float32Array([3.2404542,-1.5371385,-.4985314,-.969266,1.8760108,.041556,.0556434,-.2040259,1.0572252]),n=new Float32Array([1,1,1]),u=new Float32Array(3),h=new Float32Array(3),f=new Float32Array(3),d=Math.pow(24/116,3)/8;function g(e,t,r){r[0]=e[0]*t[0]+e[1]*t[1]+e[2]*t[2];r[1]=e[3]*t[0]+e[4]*t[1]+e[5]*t[2];r[2]=e[6]*t[0]+e[7]*t[1]+e[8]*t[2]}function m(e){return p(0,1,e<=.0031308?12.92*e:1.055*Math.pow(e,1/2.4)-.055)}function p(e,t,r){return Math.max(e,Math.min(t,r))}function v(e){return e<0?-v(-e):e>8?Math.pow((e+16)/116,3):e*d}function b(a,i,o,s,c,l){var d=p(0,1,i[o]*l),b=p(0,1,i[o+1]*l),y=p(0,1,i[o+2]*l),w=Math.pow(d,a.GR),k=Math.pow(b,a.GG),S=Math.pow(y,a.GB),C=a.MXA*w+a.MXB*k+a.MXC*S,x=a.MYA*w+a.MYB*k+a.MYC*S,_=a.MZA*w+a.MZB*k+a.MZC*S,A=h;A[0]=C;A[1]=x;A[2]=_;var P=f;!function(r,a,i){if(1!==r[0]||1!==r[2]){var n=i;g(e,a,n);var o=u;!function(e,t,r){r[0]=1*t[0]/e[0];r[1]=1*t[1]/e[1];r[2]=1*t[2]/e[2]}(r,n,o);g(t,o,i)}else{i[0]=a[0];i[1]=a[1];i[2]=a[2]}}(a.whitePoint,A,P);var I=h;!function(e,t,r){if(0!==e[0]||0!==e[1]||0!==e[2]){var a=v(0),i=(1-a)/(1-v(e[0])),n=1-i,o=(1-a)/(1-v(e[1])),s=1-o,c=(1-a)/(1-v(e[2])),l=1-c;r[0]=t[0]*i+n;r[1]=t[1]*o+s;r[2]=t[2]*c+l}else{r[0]=t[0];r[1]=t[1];r[2]=t[2]}}(a.blackPoint,P,I);var O=f;!function(r,a,i){var n=i;g(e,a,n);var o=u;!function(e,t,r){r[0]=.95047*t[0]/e[0];r[1]=1*t[1]/e[1];r[2]=1.08883*t[2]/e[2]}(r,n,o);g(t,o,i)}(n,I,O);var T=h;g(r,O,T);s[c]=255*m(T[0]);s[c+1]=255*m(T[1]);s[c+2]=255*m(T[2])}return function(e){s(t,l);function t(e,r,a,n){c(this,t);var s=o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,"CalRGB",3));if(!e)throw new i.FormatError("WhitePoint missing - required for color space CalRGB");r=r||new Float32Array(3);a=a||new Float32Array([1,1,1]);n=n||new Float32Array([1,0,0,0,1,0,0,0,1]);var l=e[0],u=e[1],h=e[2];s.whitePoint=e;var f=r[0],d=r[1],g=r[2];s.blackPoint=r;s.GR=a[0];s.GG=a[1];s.GB=a[2];s.MXA=n[0];s.MYA=n[1];s.MZA=n[2];s.MXB=n[3];s.MYB=n[4];s.MZB=n[5];s.MXC=n[6];s.MYC=n[7];s.MZC=n[8];if(l<0||h<0||1!==u)throw new i.FormatError("Invalid WhitePoint components for "+s.name+", no fallback available");if(f<0||d<0||g<0){(0,i.info)("Invalid BlackPoint for "+s.name+" ["+f+", "+d+", "+g+"], falling back to default.");s.blackPoint=new Float32Array(3)}if(s.GR<0||s.GG<0||s.GB<0){(0,i.info)("Invalid Gamma ["+s.GR+", "+s.GG+", "+s.GB+"] for "+s.name+", falling back to default.");s.GR=s.GG=s.GB=1}return s}a(t,[{key:"getRgbItem",value:function(e,t,r,a){b(this,e,t,r,a,1)}},{key:"getRgbBuffer",value:function(e,t,r,a,i,n,o){for(var s=1/((1<<n)-1),c=0;c<r;++c){b(this,e,t,a,i,s);t+=3;i+=3+o}}},{key:"getOutputLength",value:function(e,t){return e*(3+t)/3|0}},{key:"isDefaultDecode",value:function(e){return l.isDefaultDecode(e,this.numComps)}}]);return t}()}(),b=function(){function e(e){return e>=6/29?e*e*e:108/841*(e-4/29)}function t(e,t,r,a){return r+e*(a-r)/t}function r(r,a,i,n,o,s){var c=a[i],l=a[i+1],u=a[i+2];if(!1!==n){c=t(c,n,0,100);l=t(l,n,r.amin,r.amax);u=t(u,n,r.bmin,r.bmax)}var h=(c+16)/116,f=h+(l=l>r.amax?r.amax:l<r.amin?r.amin:l)/500,d=h-(u=u>r.bmax?r.bmax:u<r.bmin?r.bmin:u)/200,g=r.XW*e(f),m=r.YW*e(h),p=r.ZW*e(d),v=void 0,b=void 0,y=void 0;if(r.ZW<1){v=3.1339*g+-1.617*m+-.4906*p;b=-.9785*g+1.916*m+.0333*p;y=.072*g+-.229*m+1.4057*p}else{v=3.2406*g+-1.5372*m+-.4986*p;b=-.9689*g+1.8758*m+.0415*p;y=.0557*g+-.204*m+1.057*p}o[s]=255*Math.sqrt(v);o[s+1]=255*Math.sqrt(b);o[s+2]=255*Math.sqrt(y)}return function(e){s(t,l);function t(e,r,a){c(this,t);var n=o(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,"Lab",3));if(!e)throw new i.FormatError("WhitePoint missing - required for color space Lab");r=r||[0,0,0];a=a||[-100,100,-100,100];n.XW=e[0];n.YW=e[1];n.ZW=e[2];n.amin=a[0];n.amax=a[1];n.bmin=a[2];n.bmax=a[3];n.XB=r[0];n.YB=r[1];n.ZB=r[2];if(n.XW<0||n.ZW<0||1!==n.YW)throw new i.FormatError("Invalid WhitePoint components, no fallback available");if(n.XB<0||n.YB<0||n.ZB<0){(0,i.info)("Invalid BlackPoint, falling back to default");n.XB=n.YB=n.ZB=0}if(n.amin>n.amax||n.bmin>n.bmax){(0,i.info)("Invalid Range, falling back to defaults");n.amin=-100;n.amax=100;n.bmin=-100;n.bmax=100}return n}a(t,[{key:"getRgbItem",value:function(e,t,a,i){r(this,e,t,!1,a,i)}},{key:"getRgbBuffer",value:function(e,t,a,i,n,o,s){for(var c=(1<<o)-1,l=0;l<a;l++){r(this,e,t,c,i,n);t+=3;n+=3+s}}},{key:"getOutputLength",value:function(e,t){return e*(3+t)/3|0}},{key:"isDefaultDecode",value:function(e){return!0}},{key:"usesZeroToOneRange",get:function(){return(0,i.shadow)(this,"usesZeroToOneRange",!1)}}]);return t}()}();t.ColorSpace=l},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.AnnotationFactory=t.AnnotationBorderStyle=t.Annotation=void 0;var a=function e(t,r,a){null===t&&(t=Function.prototype);var i=Object.getOwnPropertyDescriptor(t,r);if(void 0===i){var n=Object.getPrototypeOf(t);return null===n?void 0:e(n,r,a)}if("value"in i)return i.value;var o=i.get;return void 0!==o?o.call(a):void 0},i=function(){function e(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1;a.configurable=!0;"value"in a&&(a.writable=!0);Object.defineProperty(e,a.key,a)}}return function(t,r,a){r&&e(t.prototype,r);a&&e(t,a);return t}}(),n=r(2),o=r(137),s=r(138),c=r(151),l=r(153),u=r(140);function h(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function f(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}});t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function d(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var g=function(){function e(){d(this,e)}i(e,null,[{key:"create",value:function(e,t,r,a){return r.ensure(this,"_create",[e,t,r,a])}},{key:"_create",value:function(e,t,r,a){var i=e.fetchIfRef(t);if((0,s.isDict)(i)){var o=(0,s.isRef)(t)?t.toString():"annot_"+a.createObjId(),c=i.get("Subtype");c=(0,s.isName)(c)?c.name:null;var l={xref:e,dict:i,ref:(0,s.isRef)(t)?t:null,subtype:c,id:o,pdfManager:r};switch(c){case"Link":return new S(l);case"Text":return new k(l);case"Widget":var u=(0,n.getInheritableProperty)({dict:i,key:"FT"});switch(u=(0,s.isName)(u)?u.name:null){case"Tx":return new b(l);case"Btn":return new y(l);case"Ch":return new w(l)}(0,n.warn)('Unimplemented widget field type "'+u+'", falling back to base field type.');return new v(l);case"Popup":return new C(l);case"Line":return new x(l);case"Square":return new _(l);case"Circle":return new A(l);case"PolyLine":return new P(l);case"Polygon":return new I(l);case"Ink":return new O(l);case"Highlight":return new T(l);case"Underline":return new E(l);case"Squiggly":return new F(l);case"StrikeOut":return new R(l);case"Stamp":return new B(l);case"FileAttachment":return new D(l);default:c?(0,n.warn)('Unimplemented annotation type "'+c+'", falling back to base annotation.'):(0,n.warn)("Annotation is missing the required /Subtype.");return new m(l)}}}}]);return e}();var m=function(){function e(t){d(this,e);var r=t.dict;this.setFlags(r.get("F"));this.setRectangle(r.getArray("Rect"));this.setColor(r.getArray("C"));this.setBorderStyle(r);this.setAppearance(r);this.data={annotationFlags:this.flags,borderStyle:this.borderStyle,color:this.color,hasAppearance:!!this.appearance,id:t.id,rect:this.rectangle,subtype:t.subtype}}i(e,[{key:"_hasFlag",value:function(e,t){return!!(e&t)}},{key:"_isViewable",value:function(e){return!this._hasFlag(e,n.AnnotationFlag.INVISIBLE)&&!this._hasFlag(e,n.AnnotationFlag.HIDDEN)&&!this._hasFlag(e,n.AnnotationFlag.NOVIEW)}},{key:"_isPrintable",value:function(e){return this._hasFlag(e,n.AnnotationFlag.PRINT)&&!this._hasFlag(e,n.AnnotationFlag.INVISIBLE)&&!this._hasFlag(e,n.AnnotationFlag.HIDDEN)}},{key:"setFlags",value:function(e){this.flags=Number.isInteger(e)&&e>0?e:0}},{key:"hasFlag",value:function(e){return this._hasFlag(this.flags,e)}},{key:"setRectangle",value:function(e){Array.isArray(e)&&4===e.length?this.rectangle=n.Util.normalizeRect(e):this.rectangle=[0,0,0,0]}},{key:"setColor",value:function(e){var t=new Uint8ClampedArray(3);if(Array.isArray(e))switch(e.length){case 0:this.color=null;break;case 1:c.ColorSpace.singletons.gray.getRgbItem(e,0,t,0);this.color=t;break;case 3:c.ColorSpace.singletons.rgb.getRgbItem(e,0,t,0);this.color=t;break;case 4:c.ColorSpace.singletons.cmyk.getRgbItem(e,0,t,0);this.color=t;break;default:this.color=t}else this.color=t}},{key:"setBorderStyle",value:function(e){this.borderStyle=new p;if((0,s.isDict)(e))if(e.has("BS")){var t=e.get("BS"),r=t.get("Type");if(!r||(0,s.isName)(r,"Border")){this.borderStyle.setWidth(t.get("W"));this.borderStyle.setStyle(t.get("S"));this.borderStyle.setDashArray(t.getArray("D"))}}else if(e.has("Border")){var a=e.getArray("Border");if(Array.isArray(a)&&a.length>=3){this.borderStyle.setHorizontalCornerRadius(a[0]);this.borderStyle.setVerticalCornerRadius(a[1]);this.borderStyle.setWidth(a[2]);4===a.length&&this.borderStyle.setDashArray(a[3])}}else this.borderStyle.setWidth(0)}},{key:"setAppearance",value:function(e){this.appearance=null;var t=e.get("AP");if((0,s.isDict)(t)){var r=t.get("N");if((0,s.isStream)(r))this.appearance=r;else if((0,s.isDict)(r)){var a=e.get("AS");(0,s.isName)(a)&&r.has(a.name)&&(this.appearance=r.get(a.name))}}}},{key:"_preparePopup",value:function(e){e.has("C")||(this.data.color=null);this.data.hasPopup=e.has("Popup");this.data.title=(0,n.stringToPDFString)(e.get("T")||"");this.data.contents=(0,n.stringToPDFString)(e.get("Contents")||"")}},{key:"loadResources",value:function(e){return this.appearance.dict.getAsync("Resources").then(function(t){if(t){return new o.ObjectLoader(t,e,t.xref).load().then(function(){return t})}})}},{key:"getOperatorList",value:function(e,t,r){var a=this;if(!this.appearance)return Promise.resolve(new l.OperatorList);var i=this.data,o=this.appearance.dict,s=this.loadResources(["ExtGState","ColorSpace","Pattern","Shading","XObject","Font"]),c=o.getArray("BBox")||[0,0,1,1],u=o.getArray("Matrix")||[1,0,0,1,0,0],h=function(e,t,r){var a=n.Util.getAxialAlignedBoundingBox(t,r),i=a[0],o=a[1],s=a[2],c=a[3];if(i===s||o===c)return[1,0,0,1,e[0],e[1]];var l=(e[2]-e[0])/(s-i),u=(e[3]-e[1])/(c-o);return[l,0,0,u,e[0]-i*l,e[1]-o*u]}(i.rect,c,u);return s.then(function(r){var o=new l.OperatorList;o.addOp(n.OPS.beginAnnotation,[i.rect,h,u]);return e.getOperatorList({stream:a.appearance,task:t,resources:r,operatorList:o}).then(function(){o.addOp(n.OPS.endAnnotation,[]);a.appearance.reset();return o})})}},{key:"viewable",get:function(){return 0===this.flags||this._isViewable(this.flags)}},{key:"printable",get:function(){return 0!==this.flags&&this._isPrintable(this.flags)}}]);return e}(),p=function(){function e(){d(this,e);this.width=1;this.style=n.AnnotationBorderStyleType.SOLID;this.dashArray=[3];this.horizontalCornerRadius=0;this.verticalCornerRadius=0}i(e,[{key:"setWidth",value:function(e){Number.isInteger(e)&&(this.width=e)}},{key:"setStyle",value:function(e){if(e)switch(e.name){case"S":this.style=n.AnnotationBorderStyleType.SOLID;break;case"D":this.style=n.AnnotationBorderStyleType.DASHED;break;case"B":this.style=n.AnnotationBorderStyleType.BEVELED;break;case"I":this.style=n.AnnotationBorderStyleType.INSET;break;case"U":this.style=n.AnnotationBorderStyleType.UNDERLINE}}},{key:"setDashArray",value:function(e){if(Array.isArray(e)&&e.length>0){for(var t=!0,r=!0,a=0,i=e.length;a<i;a++){var n=e[a];if(!(+n>=0)){t=!1;break}n>0&&(r=!1)}t&&!r?this.dashArray=e:this.width=0}else e&&(this.width=0)}},{key:"setHorizontalCornerRadius",value:function(e){Number.isInteger(e)&&(this.horizontalCornerRadius=e)}},{key:"setVerticalCornerRadius",value:function(e){Number.isInteger(e)&&(this.verticalCornerRadius=e)}}]);return e}(),v=function(e){f(t,m);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e)),a=e.dict,i=r.data;i.annotationType=n.AnnotationType.WIDGET;i.fieldName=r._constructFieldName(a);i.fieldValue=(0,n.getInheritableProperty)({dict:a,key:"V",getArray:!0});i.alternativeText=(0,n.stringToPDFString)(a.get("TU")||"");i.defaultAppearance=(0,n.getInheritableProperty)({dict:a,key:"DA"})||"";var o=(0,n.getInheritableProperty)({dict:a,key:"FT"});i.fieldType=(0,s.isName)(o)?o.name:null;r.fieldResources=(0,n.getInheritableProperty)({dict:a,key:"DR"})||s.Dict.empty;i.fieldFlags=(0,n.getInheritableProperty)({dict:a,key:"Ff"});(!Number.isInteger(i.fieldFlags)||i.fieldFlags<0)&&(i.fieldFlags=0);i.readOnly=r.hasFieldFlag(n.AnnotationFieldFlag.READONLY);"Sig"===i.fieldType&&r.setFlags(n.AnnotationFlag.HIDDEN);return r}i(t,[{key:"_constructFieldName",value:function(e){if(!e.has("T")&&!e.has("Parent")){(0,n.warn)("Unknown field name, falling back to empty field name.");return""}if(!e.has("Parent"))return(0,n.stringToPDFString)(e.get("T"));var t=[];e.has("T")&&t.unshift((0,n.stringToPDFString)(e.get("T")));for(var r=e;r.has("Parent");){r=r.get("Parent");if(!(0,s.isDict)(r))break;r.has("T")&&t.unshift((0,n.stringToPDFString)(r.get("T")))}return t.join(".")}},{key:"hasFieldFlag",value:function(e){return!!(this.data.fieldFlags&e)}},{key:"getOperatorList",value:function(e,r,i){return i?Promise.resolve(new l.OperatorList):a(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"getOperatorList",this).call(this,e,r,i)}}]);return t}(),b=function(e){f(t,v);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e)),a=e.dict;r.data.fieldValue=(0,n.stringToPDFString)(r.data.fieldValue||"");var i=(0,n.getInheritableProperty)({dict:a,key:"Q"});(!Number.isInteger(i)||i<0||i>2)&&(i=null);r.data.textAlignment=i;var o=(0,n.getInheritableProperty)({dict:a,key:"MaxLen"});(!Number.isInteger(o)||o<0)&&(o=null);r.data.maxLen=o;r.data.multiLine=r.hasFieldFlag(n.AnnotationFieldFlag.MULTILINE);r.data.comb=r.hasFieldFlag(n.AnnotationFieldFlag.COMB)&&!r.hasFieldFlag(n.AnnotationFieldFlag.MULTILINE)&&!r.hasFieldFlag(n.AnnotationFieldFlag.PASSWORD)&&!r.hasFieldFlag(n.AnnotationFieldFlag.FILESELECT)&&null!==r.data.maxLen;return r}i(t,[{key:"getOperatorList",value:function(e,r,i){if(i||this.appearance)return a(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"getOperatorList",this).call(this,e,r,i);var o=new l.OperatorList;if(!this.data.defaultAppearance)return Promise.resolve(o);var s=new u.Stream((0,n.stringToBytes)(this.data.defaultAppearance));return e.getOperatorList({stream:s,task:r,resources:this.fieldResources,operatorList:o}).then(function(){return o})}}]);return t}(),y=function(e){f(t,v);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));r.data.checkBox=!r.hasFieldFlag(n.AnnotationFieldFlag.RADIO)&&!r.hasFieldFlag(n.AnnotationFieldFlag.PUSHBUTTON);r.data.radioButton=r.hasFieldFlag(n.AnnotationFieldFlag.RADIO)&&!r.hasFieldFlag(n.AnnotationFieldFlag.PUSHBUTTON);r.data.pushButton=r.hasFieldFlag(n.AnnotationFieldFlag.PUSHBUTTON);r.data.checkBox?r._processCheckBox(e):r.data.radioButton?r._processRadioButton(e):r.data.pushButton?r._processPushButton(e):(0,n.warn)("Invalid field flags for button widget annotation");return r}i(t,[{key:"_processCheckBox",value:function(e){(0,s.isName)(this.data.fieldValue)&&(this.data.fieldValue=this.data.fieldValue.name);var t=e.dict.get("AP");if((0,s.isDict)(t)){var r=t.get("D");if((0,s.isDict)(r)){var a=r.getKeys();2===a.length&&(this.data.exportValue="Off"===a[0]?a[1]:a[0])}}}},{key:"_processRadioButton",value:function(e){this.data.fieldValue=this.data.buttonValue=null;var t=e.dict.get("Parent");if((0,s.isDict)(t)&&t.has("V")){var r=t.get("V");(0,s.isName)(r)&&(this.data.fieldValue=r.name)}var a=e.dict.get("AP");if((0,s.isDict)(a)){var i=a.get("N");if((0,s.isDict)(i))for(var n=i.getKeys(),o=0,c=n.length;o<c;o++)if("Off"!==n[o]){this.data.buttonValue=n[o];break}}}},{key:"_processPushButton",value:function(e){e.dict.has("A")?o.Catalog.parseDestDictionary({destDict:e.dict,resultObj:this.data,docBaseUrl:e.pdfManager.docBaseUrl}):(0,n.warn)("Push buttons without action dictionaries are not supported")}}]);return t}(),w=function(e){f(t,v);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));r.data.options=[];var a=(0,n.getInheritableProperty)({dict:e.dict,key:"Opt"});if(Array.isArray(a))for(var i=e.xref,o=0,s=a.length;o<s;o++){var c=i.fetchIfRef(a[o]),l=Array.isArray(c);r.data.options[o]={exportValue:l?i.fetchIfRef(c[0]):c,displayValue:(0,n.stringToPDFString)(l?i.fetchIfRef(c[1]):c)}}Array.isArray(r.data.fieldValue)||(r.data.fieldValue=[r.data.fieldValue]);r.data.combo=r.hasFieldFlag(n.AnnotationFieldFlag.COMBO);r.data.multiSelect=r.hasFieldFlag(n.AnnotationFieldFlag.MULTISELECT);return r}return t}(),k=function(e){f(t,m);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));r.data.annotationType=n.AnnotationType.TEXT;if(r.data.hasAppearance)r.data.name="NoIcon";else{r.data.rect[1]=r.data.rect[3]-22;r.data.rect[2]=r.data.rect[0]+22;r.data.name=e.dict.has("Name")?e.dict.get("Name").name:"Note"}r._preparePopup(e.dict);return r}return t}(),S=function(e){f(t,m);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));r.data.annotationType=n.AnnotationType.LINK;o.Catalog.parseDestDictionary({destDict:e.dict,resultObj:r.data,docBaseUrl:e.pdfManager.docBaseUrl});return r}return t}(),C=function(e){f(t,m);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));r.data.annotationType=n.AnnotationType.POPUP;var a=e.dict,i=a.get("Parent");if(!i){(0,n.warn)("Popup annotation has a missing or invalid parent annotation.");return h(r)}var o=i.get("Subtype");r.data.parentType=(0,s.isName)(o)?o.name:null;r.data.parentId=a.getRaw("Parent").toString();r.data.title=(0,n.stringToPDFString)(i.get("T")||"");r.data.contents=(0,n.stringToPDFString)(i.get("Contents")||"");if(i.has("C")){r.setColor(i.getArray("C"));r.data.color=r.color}else r.data.color=null;if(!r.viewable){var c=i.get("F");r._isViewable(c)&&r.setFlags(c)}return r}return t}(),x=function(e){f(t,m);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));r.data.annotationType=n.AnnotationType.LINE;var a=e.dict;r.data.lineCoordinates=n.Util.normalizeRect(a.getArray("L"));r._preparePopup(a);return r}return t}(),_=function(e){f(t,m);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));r.data.annotationType=n.AnnotationType.SQUARE;r._preparePopup(e.dict);return r}return t}(),A=function(e){f(t,m);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));r.data.annotationType=n.AnnotationType.CIRCLE;r._preparePopup(e.dict);return r}return t}(),P=function(e){f(t,m);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));r.data.annotationType=n.AnnotationType.POLYLINE;var a=e.dict,i=a.getArray("Vertices");r.data.vertices=[];for(var o=0,s=i.length;o<s;o+=2)r.data.vertices.push({x:i[o],y:i[o+1]});r._preparePopup(a);return r}return t}(),I=function(e){f(t,P);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));r.data.annotationType=n.AnnotationType.POLYGON;return r}return t}(),O=function(e){f(t,m);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));r.data.annotationType=n.AnnotationType.INK;var a=e.dict,i=e.xref,o=a.getArray("InkList");r.data.inkLists=[];for(var s=0,c=o.length;s<c;++s){r.data.inkLists.push([]);for(var l=0,u=o[s].length;l<u;l+=2)r.data.inkLists[s].push({x:i.fetchIfRef(o[s][l]),y:i.fetchIfRef(o[s][l+1])})}r._preparePopup(a);return r}return t}(),T=function(e){f(t,m);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));r.data.annotationType=n.AnnotationType.HIGHLIGHT;r._preparePopup(e.dict);return r}return t}(),E=function(e){f(t,m);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));r.data.annotationType=n.AnnotationType.UNDERLINE;r._preparePopup(e.dict);return r}return t}(),F=function(e){f(t,m);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));r.data.annotationType=n.AnnotationType.SQUIGGLY;r._preparePopup(e.dict);return r}return t}(),R=function(e){f(t,m);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));r.data.annotationType=n.AnnotationType.STRIKEOUT;r._preparePopup(e.dict);return r}return t}(),B=function(e){f(t,m);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));r.data.annotationType=n.AnnotationType.STAMP;r._preparePopup(e.dict);return r}return t}(),D=function(e){f(t,m);function t(e){d(this,t);var r=h(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e)),a=new o.FileSpec(e.dict.get("FS"),e.xref);r.data.annotationType=n.AnnotationType.FILEATTACHMENT;r.data.file=a.serializable;r._preparePopup(e.dict);return r}return t}();t.Annotation=m;t.AnnotationBorderStyle=p;t.AnnotationFactory=g},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.OperatorList=void 0;var a=r(2),i=function(){function e(e,t,r,a,i){for(var n=e,o=0,s=t.length-1;o<s;o++){var c=t[o];n=n[c]||(n[c]=[])}n[t[t.length-1]]={checkFn:r,iterateFn:a,processFn:i}}var t=[];e(t,[a.OPS.save,a.OPS.transform,a.OPS.paintInlineImageXObject,a.OPS.restore],null,function(e,t){var r=e.fnArray;switch((t-(e.iCurr-3))%4){case 0:return r[t]===a.OPS.save;case 1:return r[t]===a.OPS.transform;case 2:return r[t]===a.OPS.paintInlineImageXObject;case 3:return r[t]===a.OPS.restore}},function(e,t){var r=e.fnArray,i=e.argsArray,n=e.iCurr,o=n-3,s=n-2,c=n-1,l=Math.min(Math.floor((t-o)/4),200);if(l<10)return t-(t-o)%4;var u,h=0,f=[],d=0,g=1,m=1;for(u=0;u<l;u++){var p=i[s+(u<<2)],v=i[c+(u<<2)][0];if(g+v.width>1e3){h=Math.max(h,g);m+=d+2;g=0;d=0}f.push({transform:p,x:g,y:m,w:v.width,h:v.height});g+=v.width+2;d=Math.max(d,v.height)}var b=Math.max(h,g)+1,y=m+d+1,w=new Uint8ClampedArray(b*y*4),k=b<<2;for(u=0;u<l;u++){var S=i[c+(u<<2)][0].data,C=f[u].w<<2,x=0,_=f[u].x+f[u].y*b<<2;w.set(S.subarray(0,C),_-k);for(var A=0,P=f[u].h;A<P;A++){w.set(S.subarray(x,x+C),_);x+=C;_+=k}w.set(S.subarray(x-C,x),_);for(;_>=0;){S[_-4]=S[_];S[_-3]=S[_+1];S[_-2]=S[_+2];S[_-1]=S[_+3];S[_+C]=S[_+C-4];S[_+C+1]=S[_+C-3];S[_+C+2]=S[_+C-2];S[_+C+3]=S[_+C-1];_-=k}}r.splice(o,4*l,a.OPS.paintInlineImageXObjectGroup);i.splice(o,4*l,[{width:b,height:y,kind:a.ImageKind.RGBA_32BPP,data:w},f]);return o+1});e(t,[a.OPS.save,a.OPS.transform,a.OPS.paintImageMaskXObject,a.OPS.restore],null,function(e,t){var r=e.fnArray;switch((t-(e.iCurr-3))%4){case 0:return r[t]===a.OPS.save;case 1:return r[t]===a.OPS.transform;case 2:return r[t]===a.OPS.paintImageMaskXObject;case 3:return r[t]===a.OPS.restore}},function(e,t){var r,i=e.fnArray,n=e.argsArray,o=e.iCurr,s=o-3,c=o-2,l=o-1,u=Math.floor((t-s)/4);if((u=function(e,t,r,i){for(var n=e+2,o=0;o<t;o++){var s=i[n+4*o],c=1===s.length&&s[0];if(!c||1!==c.width||1!==c.height||c.data.length&&(1!==c.data.length||0!==c.data[0]))break;r[n+4*o]=a.OPS.paintSolidColorImageMask}return t-o}(s,u,i,n))<10)return t-(t-s)%4;var h,f,d=!1,g=n[l][0];if(0===n[c][1]&&0===n[c][2]){d=!0;var m=n[c][0],p=n[c][3];h=c+4;var v=l+4;for(r=1;r<u;r++,h+=4,v+=4){f=n[h];if(n[v][0]!==g||f[0]!==m||0!==f[1]||0!==f[2]||f[3]!==p){r<10?d=!1:u=r;break}}}if(d){u=Math.min(u,1e3);var b=new Float32Array(2*u);h=c;for(r=0;r<u;r++,h+=4){f=n[h];b[r<<1]=f[4];b[1+(r<<1)]=f[5]}i.splice(s,4*u,a.OPS.paintImageMaskXObjectRepeat);n.splice(s,4*u,[g,m,p,b])}else{u=Math.min(u,100);var y=[];for(r=0;r<u;r++){f=n[c+(r<<2)];var w=n[l+(r<<2)][0];y.push({data:w.data,width:w.width,height:w.height,transform:f})}i.splice(s,4*u,a.OPS.paintImageMaskXObjectGroup);n.splice(s,4*u,[y])}return s+1});e(t,[a.OPS.save,a.OPS.transform,a.OPS.paintImageXObject,a.OPS.restore],function(e){var t=e.argsArray,r=e.iCurr-2;return 0===t[r][1]&&0===t[r][2]},function(e,t){var r=e.fnArray,i=e.argsArray;switch((t-(e.iCurr-3))%4){case 0:return r[t]===a.OPS.save;case 1:if(r[t]!==a.OPS.transform)return!1;var n=e.iCurr-2,o=i[n][0],s=i[n][3];return i[t][0]===o&&0===i[t][1]&&0===i[t][2]&&i[t][3]===s;case 2:if(r[t]!==a.OPS.paintImageXObject)return!1;var c=i[e.iCurr-1][0];return i[t][0]===c;case 3:return r[t]===a.OPS.restore}},function(e,t){var r=e.fnArray,i=e.argsArray,n=e.iCurr,o=n-3,s=n-2,c=i[n-1][0],l=i[s][0],u=i[s][3],h=Math.min(Math.floor((t-o)/4),1e3);if(h<3)return t-(t-o)%4;for(var f=new Float32Array(2*h),d=s,g=0;g<h;g++,d+=4){var m=i[d];f[g<<1]=m[4];f[1+(g<<1)]=m[5]}var p=[c,l,u,f];r.splice(o,4*h,a.OPS.paintImageXObjectRepeat);i.splice(o,4*h,p);return o+1});e(t,[a.OPS.beginText,a.OPS.setFont,a.OPS.setTextMatrix,a.OPS.showText,a.OPS.endText],null,function(e,t){var r=e.fnArray,i=e.argsArray;switch((t-(e.iCurr-4))%5){case 0:return r[t]===a.OPS.beginText;case 1:return r[t]===a.OPS.setFont;case 2:return r[t]===a.OPS.setTextMatrix;case 3:if(r[t]!==a.OPS.showText)return!1;var n=e.iCurr-3,o=i[n][0],s=i[n][1];return i[t][0]===o&&i[t][1]===s;case 4:return r[t]===a.OPS.endText}},function(e,t){var r=e.fnArray,a=e.argsArray,i=e.iCurr,n=i-4,o=i-3,s=i-2,c=i-1,l=i,u=a[o][0],h=a[o][1],f=Math.min(Math.floor((t-n)/5),1e3);if(f<3)return t-(t-n)%5;var d=n;if(n>=4&&r[n-4]===r[o]&&r[n-3]===r[s]&&r[n-2]===r[c]&&r[n-1]===r[l]&&a[n-4][0]===u&&a[n-4][1]===h){f++;d-=5}for(var g=d+4,m=1;m<f;m++){r.splice(g,3);a.splice(g,3);g+=2}return g+1});function r(e){this.queue=e;this.state=null;this.context={iCurr:0,fnArray:e.fnArray,argsArray:e.argsArray};this.match=null;this.lastProcessed=0}r.prototype={_optimize:function(){var e=this.queue.fnArray,r=this.lastProcessed,a=e.length,i=this.state,n=this.match;if(i||n||r+1!==a||t[e[r]]){for(var o=this.context;r<a;){if(n){if((0,n.iterateFn)(o,r)){r++;continue}r=(0,n.processFn)(o,r+1);a=e.length;n=null;i=null;if(r>=a)break}if((i=(i||t)[e[r]])&&!Array.isArray(i)){o.iCurr=r;r++;if(!i.checkFn||(0,i.checkFn)(o)){n=i;i=null}else i=null}else r++}this.state=i;this.match=n;this.lastProcessed=r}else this.lastProcessed=a},push:function(e,t){this.queue.fnArray.push(e);this.queue.argsArray.push(t);this._optimize()},flush:function(){for(;this.match;){var e=this.queue.fnArray.length;this.lastProcessed=(0,this.match.processFn)(this.context,e);this.match=null;this.state=null;this._optimize()}},reset:function(){this.state=null;this.match=null;this.lastProcessed=0}};return r}(),n=function(){function e(e){this.queue=e}e.prototype={push:function(e,t){this.queue.fnArray.push(e);this.queue.argsArray.push(t)},flush:function(){}};return e}(),o=function(){function e(e,t,r){this.messageHandler=t;this.fnArray=[];this.argsArray=[];t&&"oplist"!==this.intent?this.optimizer=new i(this):this.optimizer=new n(this);this.dependencies=Object.create(null);this._totalLength=0;this.pageIndex=r;this.intent=e;this.weight=0}e.prototype={get length(){return this.argsArray.length},get totalLength(){return this._totalLength+this.length},addOp:function(e,t){this.optimizer.push(e,t);this.weight++;this.messageHandler&&(this.weight>=1e3?this.flush():this.weight>=995&&(e===a.OPS.restore||e===a.OPS.endText)&&this.flush())},addDependency:function(e){if(!(e in this.dependencies)){this.dependencies[e]=!0;this.addOp(a.OPS.dependency,[e])}},addDependencies:function(e){for(var t in e)this.addDependency(t)},addOpList:function(e){Object.assign(this.dependencies,e.dependencies);for(var t=0,r=e.length;t<r;t++)this.addOp(e.fnArray[t],e.argsArray[t])},getIR:function(){return{fnArray:this.fnArray,argsArray:this.argsArray,length:this.length}},flush:function(e){this.optimizer.flush();var t=function(e){for(var t=[],r=e.fnArray,i=e.argsArray,n=0,o=e.length;n<o;n++)switch(r[n]){case a.OPS.paintInlineImageXObject:case a.OPS.paintInlineImageXObjectGroup:case a.OPS.paintImageMaskXObject:var s=i[n][0];s.cached||t.push(s.data.buffer)}return t}(this),r=this.length;this._totalLength+=r;this.messageHandler.send("RenderPageChunk",{operatorList:{fnArray:this.fnArray,argsArray:this.argsArray,lastChunk:e,length:r},pageIndex:this.pageIndex,intent:this.intent},t);this.dependencies=Object.create(null);this.fnArray.length=0;this.argsArray.length=0;this.weight=0;this.optimizer.reset()}};return e}();t.OperatorList=o},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.PartialEvaluator=void 0;var a,i=r(131),n=(a=i)&&a.__esModule?a:{default:a},o=r(2),s=r(155),c=r(140),l=r(138),u=r(156),h=r(159),f=r(162),d=r(161),g=r(165),m=r(139),p=r(166),v=r(151),b=r(160),y=r(167),w=r(168),k=r(146),S=r(170),C=r(153),x=r(171);var _=function(){var e={forceDataSchema:!1,maxImageSize:-1,disableFontFace:!1,nativeImageDecoderSupport:o.NativeImageDecoding.DECODE,ignoreErrors:!1,isEvalSupported:!0};function t(e){var t=e.xref,r=e.resources,a=e.handler,i=e.forceDataSchema,n=void 0!==i&&i,o=e.pdfFunctionFactory;this.xref=t;this.resources=r;this.handler=a;this.forceDataSchema=n;this.pdfFunctionFactory=o}t.prototype={canDecode:function(e){return e instanceof k.JpegStream&&t.isDecodable(e,this.xref,this.resources,this.pdfFunctionFactory)},decode:function(e){var t=e.dict.get("ColorSpace","CS");t=v.ColorSpace.parse(t,this.xref,this.resources,this.pdfFunctionFactory);return this.handler.sendWithPromise("JpegDecode",[e.getIR(this.forceDataSchema),t.numComps]).then(function(t){var r=t.data;t.width,t.height;return new c.Stream(r,0,r.length,e.dict)})}};t.isSupported=function(e,t,r,a){var i=e.dict;if(i.has("DecodeParms")||i.has("DP"))return!1;var n=v.ColorSpace.parse(i.get("ColorSpace","CS"),t,r,a);return("DeviceGray"===n.name||"DeviceRGB"===n.name)&&n.isDefaultDecode(i.getArray("Decode","D"))};t.isDecodable=function(e,t,r,a){var i=e.dict;if(i.has("DecodeParms")||i.has("DP"))return!1;var n=v.ColorSpace.parse(i.get("ColorSpace","CS"),t,r,a);return(1===n.numComps||3===n.numComps)&&n.isDefaultDecode(i.getArray("Decode","D"))};function r(t){var r,a,i=this,s=t.pdfManager,c=t.xref,l=t.handler,u=t.pageIndex,h=t.idFactory,f=t.fontCache,d=t.builtInCMapCache,g=t.options,m=void 0===g?null:g,p=t.pdfFunctionFactory;this.pdfManager=s;this.xref=c;this.handler=l;this.pageIndex=u;this.idFactory=h;this.fontCache=f;this.builtInCMapCache=d;this.options=m||e;this.pdfFunctionFactory=p;this.fetchBuiltInCMap=(a=(r=n.default.mark(function e(t){var r;return n.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(!i.builtInCMapCache.has(t)){e.next=2;break}return e.abrupt("return",i.builtInCMapCache.get(t));case 2:e.next=4;return i.handler.sendWithPromise("FetchBuiltInCMap",{name:t});case 4:(r=e.sent).compressionType!==o.CMapCompressionType.NONE&&i.builtInCMapCache.set(t,r);return e.abrupt("return",r);case 7:case"end":return e.stop()}},e,i)}),function(){var e=r.apply(this,arguments);return new Promise(function(t,r){return function a(i,n){try{var o=e[i](n),s=o.value}catch(e){r(e);return}if(!o.done)return Promise.resolve(s).then(function(e){a("next",e)},function(e){a("throw",e)});t(s)}("next")})}),function(e){return a.apply(this,arguments)})}function a(){this.reset()}a.prototype={check:function(){if(++this.checked<100)return!1;this.checked=0;return this.endTime<=Date.now()},reset:function(){this.endTime=Date.now()+20;this.checked=0}};var i=Promise.resolve();r.prototype={clone:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:e,r=Object.create(this);r.options=t;return r},hasBlendModes:function(e){if(!(0,l.isDict)(e))return!1;var t=Object.create(null);e.objId&&(t[e.objId]=!0);for(var r=[e],a=this.xref;r.length;){var i,n,o,s=r.shift(),c=s.get("ExtGState");if((0,l.isDict)(c)){var u=c.getKeys();for(n=0,o=u.length;n<o;n++){i=u[n];var h=c.get(i).get("BM");if((0,l.isName)(h)&&"Normal"!==h.name)return!0}}var f=s.get("XObject");if((0,l.isDict)(f)){var d=f.getKeys();for(n=0,o=d.length;n<o;n++){i=d[n];var g=f.getRaw(i);if((0,l.isRef)(g)){if(t[g.toString()])continue;g=a.fetch(g)}if((0,l.isStream)(g)){if(g.dict.objId){if(t[g.dict.objId])continue;t[g.dict.objId]=!0}var m=g.dict.get("Resources");if((0,l.isDict)(m)&&(!m.objId||!t[m.objId])){r.push(m);m.objId&&(t[m.objId]=!0)}}}}}return!1},buildFormXObject:function(e,t,r,a,i,n){var s=t.dict,c=s.getArray("Matrix"),u=s.getArray("BBox"),h=s.get("Group");if(h){var f={matrix:c,bbox:u,smask:r,isolated:!1,knockout:!1},d=h.get("S"),g=null;if((0,l.isName)(d,"Transparency")){f.isolated=h.get("I")||!1;f.knockout=h.get("K")||!1;h.has("CS")&&(g=v.ColorSpace.parse(h.get("CS"),this.xref,e,this.pdfFunctionFactory))}if(r&&r.backdrop){g=g||v.ColorSpace.singletons.rgb;r.backdrop=g.getRgb(r.backdrop,0)}a.addOp(o.OPS.beginGroup,[f])}a.addOp(o.OPS.paintFormXObjectBegin,[c,u]);return this.getOperatorList({stream:t,task:i,resources:s.get("Resources")||e,operatorList:a,initialState:n}).then(function(){a.addOp(o.OPS.paintFormXObjectEnd,[]);h&&a.addOp(o.OPS.endGroup,[f])})},buildPaintImageXObject:function(e){var r=this,a=e.resources,i=e.image,n=e.isInline,s=void 0!==n&&n,l=e.operatorList,u=e.cacheKey,h=e.imageCache,f=e.forceDisableNativeImageDecoder,d=void 0!==f&&f,g=i.dict,m=g.get("Width","W"),p=g.get("Height","H");if(!(m&&(0,o.isNum)(m)&&p&&(0,o.isNum)(p))){(0,o.warn)("Image dimensions are missing, or not numbers.");return Promise.resolve()}var v,b,y=this.options.maxImageSize;if(-1!==y&&m*p>y){(0,o.warn)("Image exceeded maximum allowed size and was removed.");return Promise.resolve()}if(g.get("ImageMask","IM")||!1){var w=g.get("Width","W"),S=g.get("Height","H"),C=w+7>>3,_=i.getBytes(C*S,!0),A=g.getArray("Decode","D");(v=x.PDFImage.createMask({imgArray:_,width:w,height:S,imageIsFromDecodeStream:i instanceof c.DecodeStream,inverseDecode:!!A&&A[0]>0})).cached=!0;b=[v];l.addOp(o.OPS.paintImageMaskXObject,b);u&&(h[u]={fn:o.OPS.paintImageMaskXObject,args:b});return Promise.resolve()}var P=g.get("SMask","SM")||!1,I=g.get("Mask")||!1;if(s&&!P&&!I&&!(i instanceof k.JpegStream)&&m+p<200){v=new x.PDFImage({xref:this.xref,res:a,image:i,isInline:s,pdfFunctionFactory:this.pdfFunctionFactory}).createImageData(!0);l.addOp(o.OPS.paintInlineImageXObject,[v]);return Promise.resolve()}var O=d?o.NativeImageDecoding.NONE:this.options.nativeImageDecoderSupport,T="img_"+this.idFactory.createObjId();if(O!==o.NativeImageDecoding.NONE&&!P&&!I&&i instanceof k.JpegStream&&t.isSupported(i,this.xref,a,this.pdfFunctionFactory))return this.handler.sendWithPromise("obj",[T,this.pageIndex,"JpegStream",i.getIR(this.options.forceDataSchema)]).then(function(){l.addDependency(T);b=[T,m,p];l.addOp(o.OPS.paintJpegXObject,b);u&&(h[u]={fn:o.OPS.paintJpegXObject,args:b})},function(e){(0,o.warn)("Native JPEG decoding failed -- trying to recover: "+(e&&e.message));return r.buildPaintImageXObject({resources:a,image:i,isInline:s,operatorList:l,cacheKey:u,imageCache:h,forceDisableNativeImageDecoder:!0})});var E=null;O===o.NativeImageDecoding.DECODE&&(i instanceof k.JpegStream||I instanceof k.JpegStream||P instanceof k.JpegStream)&&(E=new t({xref:this.xref,resources:a,handler:this.handler,forceDataSchema:this.options.forceDataSchema,pdfFunctionFactory:this.pdfFunctionFactory}));l.addDependency(T);b=[T,m,p];x.PDFImage.buildImage({handler:this.handler,xref:this.xref,res:a,image:i,isInline:s,nativeDecoder:E,pdfFunctionFactory:this.pdfFunctionFactory}).then(function(e){var t=e.createImageData(!1);r.handler.send("obj",[T,r.pageIndex,"Image",t],[t.data.buffer])}).catch(function(e){(0,o.warn)("Unable to decode image: "+e);r.handler.send("obj",[T,r.pageIndex,"Image",null])});l.addOp(o.OPS.paintImageXObject,b);u&&(h[u]={fn:o.OPS.paintImageXObject,args:b});return Promise.resolve()},handleSMask:function(e,t,r,a,i){var n=e.get("G"),o={subtype:e.get("S").name,backdrop:e.get("BC")},s=e.get("TR");if((0,w.isPDFFunction)(s)){for(var c=this.pdfFunctionFactory.create(s),l=new Uint8Array(256),u=new Float32Array(1),h=0;h<256;h++){u[0]=h/255;c(u,0,u,0);l[h]=255*u[0]|0}o.transferMap=l}return this.buildFormXObject(t,n,o,r,a,i.state.clone())},handleTilingType:function(e,t,r,a,i,n,s){var c=this,u=new C.OperatorList,h=[i.get("Resources"),r],f=l.Dict.merge(this.xref,h);return this.getOperatorList({stream:a,task:s,resources:f,operatorList:u}).then(function(){return(0,g.getTilingPatternIR)({fnArray:u.fnArray,argsArray:u.argsArray},i,t)}).then(function(t){n.addDependencies(u.dependencies);n.addOp(e,t)},function(e){if(!c.options.ignoreErrors)throw e;c.handler.send("UnsupportedFeature",{featureId:o.UNSUPPORTED_FEATURES.unknown});(0,o.warn)('handleTilingType - ignoring pattern: "'+e+'".')})},handleSetFont:function(e,t,r,a,i,n){var s,c=this;t&&(s=(t=t.slice())[0].name);return this.loadFont(s,r,e).then(function(t){return t.font.isType3Font?t.loadType3Data(c,e,a,i).then(function(){return t}).catch(function(e){c.handler.send("UnsupportedFeature",{featureId:o.UNSUPPORTED_FEATURES.font});return new A("g_font_error",new u.ErrorFont("Type3 font load error: "+e),t.font)}):t}).then(function(e){n.font=e.font;e.send(c.handler);return e.loadedName})},handleText:function(e,t){var r=this,a=t.font,i=a.charsToGlyphs(e),n=!!(t.textRenderingMode&o.TextRenderingMode.ADD_TO_PATH_FLAG);if(a.data&&(n||this.options.disableFontFace||"Pattern"===t.fillColorSpace.name))for(var s=function(e){if(!a.renderer.hasBuiltPath(e)){var t=a.renderer.getPathJs(e);r.handler.send("commonobj",[a.loadedName+"_path_"+e,"FontPath",t])}},c=0,l=i.length;c<l;c++){var u=i[c];s(u.fontChar);var h=u.accent;h&&h.fontChar&&s(h.fontChar)}return i},setGState:function(e,t,r,a,i){for(var n=this,s=[],c=t.getKeys(),u=Promise.resolve(),h=function(){var h=c[f],d=t.get(h);switch(h){case"Type":break;case"LW":case"LC":case"LJ":case"ML":case"D":case"RI":case"FL":case"CA":case"ca":s.push([h,d]);break;case"Font":u=u.then(function(){return n.handleSetFont(e,null,d[0],r,a,i.state).then(function(e){r.addDependency(e);s.push([h,[e,d[1]]])})});break;case"BM":s.push([h,function(e){if(!(0,l.isName)(e))return"source-over";switch(e.name){case"Normal":case"Compatible":return"source-over";case"Multiply":return"multiply";case"Screen":return"screen";case"Overlay":return"overlay";case"Darken":return"darken";case"Lighten":return"lighten";case"ColorDodge":return"color-dodge";case"ColorBurn":return"color-burn";case"HardLight":return"hard-light";case"SoftLight":return"soft-light";case"Difference":return"difference";case"Exclusion":return"exclusion";case"Hue":return"hue";case"Saturation":return"saturation";case"Color":return"color";case"Luminosity":return"luminosity"}(0,o.warn)("Unsupported blend mode: "+e.name);return"source-over"}(d)]);break;case"SMask":if((0,l.isName)(d,"None")){s.push([h,!1]);break}if((0,l.isDict)(d)){u=u.then(function(){return n.handleSMask(d,e,r,a,i)});s.push([h,!0])}else(0,o.warn)("Unsupported SMask type");break;case"OP":case"op":case"OPM":case"BG":case"BG2":case"UCR":case"UCR2":case"TR":case"TR2":case"HT":case"SM":case"SA":case"AIS":case"TK":(0,o.info)("graphic state operator "+h);break;default:(0,o.info)("Unknown graphic state operator "+h)}},f=0,d=c.length;f<d;f++)h();return u.then(function(){s.length>0&&r.addOp(o.OPS.setGState,[s])})},loadFont:function(e,t,r){var a=this;function i(){return Promise.resolve(new A("g_font_error",new u.ErrorFont("Font "+e+" is not available"),t))}var n,s=this.xref;if(t){if(!(0,l.isRef)(t))throw new Error('The "font" object should be a reference.');n=t}else{var c=r.get("Font");if(!c){(0,o.warn)("fontRes not available");return i()}n=c.getRaw(e)}if(!n){(0,o.warn)("fontRef not available");return i()}if(this.fontCache.has(n))return this.fontCache.get(n);t=s.fetchIfRef(n);if(!(0,l.isDict)(t))return i();if(t.translated)return t.translated;var h,f,d=(0,o.createPromiseCapability)(),g=this.preEvaluateFont(t),m=g.descriptor,p=(0,l.isRef)(n);p&&(h=n.toString());if((0,l.isDict)(m)){m.fontAliases||(m.fontAliases=Object.create(null));var v=m.fontAliases,b=g.hash;if(v[b]){var y=v[b].aliasRef;if(p&&y&&this.fontCache.has(y)){this.fontCache.putAlias(n,y);return this.fontCache.get(n)}}else v[b]={fontID:u.Font.getFontID()};p&&(v[b].aliasRef=n);h=v[b].fontID}if(p)this.fontCache.put(n,d.promise);else{h||(h=this.idFactory.createObjId());this.fontCache.put("id_"+h,d.promise)}(0,o.assert)(h,'The "fontID" must be defined.');t.loadedName="g_"+this.pdfManager.docId+"_f"+h;t.translated=d.promise;try{f=this.translateFont(g)}catch(e){f=Promise.reject(e)}f.then(function(e){if(void 0!==e.fontType){s.stats.fontTypes[e.fontType]=!0}d.resolve(new A(t.loadedName,e,t))}).catch(function(e){a.handler.send("UnsupportedFeature",{featureId:o.UNSUPPORTED_FEATURES.font});try{var r=g.descriptor,i=r&&r.get("FontFile3"),n=i&&i.get("Subtype"),c=(0,u.getFontType)(g.type,n&&n.name);s.stats.fontTypes[c]=!0}catch(e){}d.resolve(new A(t.loadedName,new u.ErrorFont(e instanceof Error?e.message:e),t))});return d.promise},buildPath:function(e,t,r){var a=e.length-1;r||(r=[]);if(a<0||e.fnArray[a]!==o.OPS.constructPath)e.addOp(o.OPS.constructPath,[[t],r]);else{var i=e.argsArray[a];i[0].push(t);Array.prototype.push.apply(i[1],r)}},handleColorN:function(e,t,r,a,i,n,o){var s,c=r[r.length-1];if((0,l.isName)(c)&&(s=i.get(c.name))){var u=(0,l.isStream)(s)?s.dict:s,h=u.get("PatternType");if(1===h){var f=a.base?a.base.getRgb(r,0):null;return this.handleTilingType(t,f,n,s,u,e,o)}if(2===h){var d=u.get("Shading"),m=u.getArray("Matrix");s=g.Pattern.parseShading(d,m,this.xref,n,this.handler,this.pdfFunctionFactory);e.addOp(t,s.getIR());return Promise.resolve()}return Promise.reject(new Error("Unknown PatternType: "+h))}e.addOp(t,r);return Promise.resolve()},getOperatorList:function(e){var t=this,r=e.stream,n=e.task,s=e.resources,c=e.operatorList,u=e.initialState,h=void 0===u?null:u;s=s||l.Dict.empty;h=h||new O;if(!c)throw new Error('getOperatorList: missing "operatorList" parameter');var f=this,d=this.xref,m=Object.create(null),p=s.get("XObject")||l.Dict.empty,b=s.get("Pattern")||l.Dict.empty,y=new P(h),w=new T(r,d,y),k=new a;function S(e){for(var t=0,r=w.savedStatesDepth;t<r;t++)c.addOp(o.OPS.restore,[])}return new Promise(function e(t,r){var a=function(a){a.then(function(){try{e(t,r)}catch(e){r(e)}},r)};n.ensureNotTerminated();k.reset();for(var u,h,C,x,_={};!(u=k.check());){_.args=null;if(!w.read(_))break;var A=_.args,P=_.fn;switch(0|P){case o.OPS.paintXObject:var I=A[0].name;if(I&&void 0!==m[I]){c.addOp(m[I].fn,m[I].args);A=null;continue}a(new Promise(function(e,t){if(!I)throw new o.FormatError("XObject must be referred to by name.");var r=p.get(I);if(r){if(!(0,l.isStream)(r))throw new o.FormatError("XObject should be a stream");var a=r.dict.get("Subtype");if(!(0,l.isName)(a))throw new o.FormatError("XObject should have a Name subtype");if("Form"!==a.name)if("Image"!==a.name){if("PS"!==a.name)throw new o.FormatError("Unhandled XObject subtype "+a.name);(0,o.info)("Ignored XObject subtype PS");e()}else f.buildPaintImageXObject({resources:s,image:r,operatorList:c,cacheKey:I,imageCache:m}).then(e,t);else{y.save();f.buildFormXObject(s,r,null,c,n,y.state.clone()).then(function(){y.restore();e()},t)}}else{c.addOp(P,A);e()}}).catch(function(e){if(!f.options.ignoreErrors)throw e;f.handler.send("UnsupportedFeature",{featureId:o.UNSUPPORTED_FEATURES.unknown});(0,o.warn)('getOperatorList - ignoring XObject: "'+e+'".')}));return;case o.OPS.setFont:var O=A[1];a(f.handleSetFont(s,A,null,c,n,y.state).then(function(e){c.addDependency(e);c.addOp(o.OPS.setFont,[e,O])}));return;case o.OPS.endInlineImage:var T=A[0].cacheKey;if(T){var E=m[T];if(void 0!==E){c.addOp(E.fn,E.args);A=null;continue}}a(f.buildPaintImageXObject({resources:s,image:A[0],isInline:!0,operatorList:c,cacheKey:T,imageCache:m}));return;case o.OPS.showText:A[0]=f.handleText(A[0],y.state);break;case o.OPS.showSpacedText:var F=A[0],R=[],B=F.length,D=y.state;for(h=0;h<B;++h){var M=F[h];(0,o.isString)(M)?Array.prototype.push.apply(R,f.handleText(M,D)):(0,o.isNum)(M)&&R.push(M)}A[0]=R;P=o.OPS.showText;break;case o.OPS.nextLineShowText:c.addOp(o.OPS.nextLine);A[0]=f.handleText(A[0],y.state);P=o.OPS.showText;break;case o.OPS.nextLineSetSpacingShowText:c.addOp(o.OPS.nextLine);c.addOp(o.OPS.setWordSpacing,[A.shift()]);c.addOp(o.OPS.setCharSpacing,[A.shift()]);A[0]=f.handleText(A[0],y.state);P=o.OPS.showText;break;case o.OPS.setTextRenderingMode:y.state.textRenderingMode=A[0];break;case o.OPS.setFillColorSpace:y.state.fillColorSpace=v.ColorSpace.parse(A[0],d,s,f.pdfFunctionFactory);continue;case o.OPS.setStrokeColorSpace:y.state.strokeColorSpace=v.ColorSpace.parse(A[0],d,s,f.pdfFunctionFactory);continue;case o.OPS.setFillColor:x=y.state.fillColorSpace;A=x.getRgb(A,0);P=o.OPS.setFillRGBColor;break;case o.OPS.setStrokeColor:x=y.state.strokeColorSpace;A=x.getRgb(A,0);P=o.OPS.setStrokeRGBColor;break;case o.OPS.setFillGray:y.state.fillColorSpace=v.ColorSpace.singletons.gray;A=v.ColorSpace.singletons.gray.getRgb(A,0);P=o.OPS.setFillRGBColor;break;case o.OPS.setStrokeGray:y.state.strokeColorSpace=v.ColorSpace.singletons.gray;A=v.ColorSpace.singletons.gray.getRgb(A,0);P=o.OPS.setStrokeRGBColor;break;case o.OPS.setFillCMYKColor:y.state.fillColorSpace=v.ColorSpace.singletons.cmyk;A=v.ColorSpace.singletons.cmyk.getRgb(A,0);P=o.OPS.setFillRGBColor;break;case o.OPS.setStrokeCMYKColor:y.state.strokeColorSpace=v.ColorSpace.singletons.cmyk;A=v.ColorSpace.singletons.cmyk.getRgb(A,0);P=o.OPS.setStrokeRGBColor;break;case o.OPS.setFillRGBColor:y.state.fillColorSpace=v.ColorSpace.singletons.rgb;A=v.ColorSpace.singletons.rgb.getRgb(A,0);break;case o.OPS.setStrokeRGBColor:y.state.strokeColorSpace=v.ColorSpace.singletons.rgb;A=v.ColorSpace.singletons.rgb.getRgb(A,0);break;case o.OPS.setFillColorN:if("Pattern"===(x=y.state.fillColorSpace).name){a(f.handleColorN(c,o.OPS.setFillColorN,A,x,b,s,n));return}A=x.getRgb(A,0);P=o.OPS.setFillRGBColor;break;case o.OPS.setStrokeColorN:if("Pattern"===(x=y.state.strokeColorSpace).name){a(f.handleColorN(c,o.OPS.setStrokeColorN,A,x,b,s,n));return}A=x.getRgb(A,0);P=o.OPS.setStrokeRGBColor;break;case o.OPS.shadingFill:var L=s.get("Shading");if(!L)throw new o.FormatError("No shading resource found");var N=L.get(A[0].name);if(!N)throw new o.FormatError("No shading object found");var U=g.Pattern.parseShading(N,null,d,s,f.handler,f.pdfFunctionFactory).getIR();A=[U];P=o.OPS.shadingFill;break;case o.OPS.setGState:var q=A[0],j=s.get("ExtGState");if(!(0,l.isDict)(j)||!j.has(q.name))break;var z=j.get(q.name);a(f.setGState(s,z,c,n,y));return;case o.OPS.moveTo:case o.OPS.lineTo:case o.OPS.curveTo:case o.OPS.curveTo2:case o.OPS.curveTo3:case o.OPS.closePath:case o.OPS.rectangle:f.buildPath(c,P,A);continue;case o.OPS.markPoint:case o.OPS.markPointProps:case o.OPS.beginMarkedContent:case o.OPS.beginMarkedContentProps:case o.OPS.endMarkedContent:case o.OPS.beginCompat:case o.OPS.endCompat:continue;default:if(null!==A){for(h=0,C=A.length;h<C&&!(A[h]instanceof l.Dict);h++);if(h<C){(0,o.warn)("getOperatorList - ignoring operator: "+P);continue}}}c.addOp(P,A)}if(u)a(i);else{S();t()}}).catch(function(e){if(!t.options.ignoreErrors)throw e;t.handler.send("UnsupportedFeature",{featureId:o.UNSUPPORTED_FEATURES.unknown});(0,o.warn)('getOperatorList - ignoring errors during "'+n.name+'" task: "'+e+'".');S()})},getTextContent:function(e){var t=this,r=e.stream,n=e.task,s=e.resources,c=e.stateManager,u=void 0===c?null:c,h=e.normalizeWhitespace,d=void 0!==h&&h,g=e.combineTextItems,m=void 0!==g&&g,v=e.sink,b=e.seenStyles,y=void 0===b?Object.create(null):b;s=s||l.Dict.empty;u=u||new P(new I);var w,k=/\s/g,S={items:[],styles:Object.create(null)},C={initialized:!1,str:[],width:0,height:0,vertical:!1,lastAdvanceWidth:0,lastAdvanceHeight:0,textAdvanceScale:0,spaceWidth:0,fakeSpaceMin:1/0,fakeMultiSpaceMin:1/0,fakeMultiSpaceMax:-0,textRunBreakAllowed:!1,transform:null,fontName:null},x=.3,_=1.5,A=4,O=this,E=this.xref,F=null,R=Object.create(null),B=new T(r,E,u);function D(){if(C.initialized)return C;var e=w.font;if(!(e.loadedName in y)){y[e.loadedName]=!0;S.styles[e.loadedName]={fontFamily:e.fallbackName,ascent:e.ascent,descent:e.descent,vertical:e.vertical}}C.fontName=e.loadedName;var t=[w.fontSize*w.textHScale,0,0,w.fontSize,0,w.textRise];if(e.isType3Font&&w.fontMatrix!==o.FONT_IDENTITY_MATRIX&&1===w.fontSize){var r=e.bbox[3]-e.bbox[1];if(r>0){r*=w.fontMatrix[3];t[3]*=r}}var a=o.Util.transform(w.ctm,o.Util.transform(w.textMatrix,t));C.transform=a;if(e.vertical){C.width=Math.sqrt(a[0]*a[0]+a[1]*a[1]);C.height=0;C.vertical=!0}else{C.width=0;C.height=Math.sqrt(a[2]*a[2]+a[3]*a[3]);C.vertical=!1}var i=w.textLineMatrix[0],n=w.textLineMatrix[1],s=Math.sqrt(i*i+n*n);i=w.ctm[0];n=w.ctm[1];var c=Math.sqrt(i*i+n*n);C.textAdvanceScale=c*s;C.lastAdvanceWidth=0;C.lastAdvanceHeight=0;var l=e.spaceWidth/1e3*w.fontSize;if(l){C.spaceWidth=l;C.fakeSpaceMin=l*x;C.fakeMultiSpaceMin=l*_;C.fakeMultiSpaceMax=l*A;C.textRunBreakAllowed=!e.isMonospace}else{C.spaceWidth=0;C.fakeSpaceMin=1/0;C.fakeMultiSpaceMin=1/0;C.fakeMultiSpaceMax=0;C.textRunBreakAllowed=!1}C.initialized=!0;return C}function M(e){var t=e.str.join(""),r=(0,p.bidi)(t,-1,e.vertical);return{str:d?function(e){for(var t,r=0,a=e.length;r<a&&(t=e.charCodeAt(r))>=32&&t<=127;)r++;return r<a?e.replace(k," "):e}(r.str):r.str,dir:r.dir,width:e.width,height:e.height,transform:e.transform,fontName:e.fontName}}function L(e,t){return O.loadFont(e,t,s).then(function(e){w.font=e.font;w.fontMatrix=e.font.fontMatrix||o.FONT_IDENTITY_MATRIX})}function N(e){for(var t=w.font,r=D(),a=0,i=0,n=t.charsToGlyphs(e),o=0;o<n.length;o++){var s=n[o],c=null;c=t.vertical&&s.vmetric?s.vmetric[0]:s.width;var l=s.unicode,u=(0,f.getNormalizedUnicodes)();void 0!==u[l]&&(l=u[l]);l=(0,f.reverseIfRtl)(l);var h=w.charSpacing;if(s.isSpace){var d=w.wordSpacing;h+=d;d>0&&U(d,r.str)}var g=0,m=0;if(t.vertical){i+=m=c*w.fontMatrix[0]*w.fontSize+h}else{a+=g=(c*w.fontMatrix[0]*w.fontSize+h)*w.textHScale}w.translateTextMatrix(g,m);r.str.push(l)}if(t.vertical){r.lastAdvanceHeight=i;r.height+=Math.abs(i)}else{r.lastAdvanceWidth=a;r.width+=a}return r}function U(e,t){if(!(e<C.fakeSpaceMin))if(e<C.fakeMultiSpaceMin)t.push(" ");else for(var r=Math.round(e/C.spaceWidth);r-- >0;)t.push(" ")}function q(){if(C.initialized){C.width*=C.textAdvanceScale;C.height*=C.textAdvanceScale;S.items.push(M(C));C.initialized=!1;C.str.length=0}}function j(){var e=S.items.length;if(e>0){v.enqueue(S,e);S.items=[];S.styles=Object.create(null)}}var z=new a;return new Promise(function e(t,r){var a=function(a){j();Promise.all([a,v.ready]).then(function(){try{e(t,r)}catch(e){r(e)}},r)};n.ensureNotTerminated();z.reset();for(var c,h={},f=[];!(c=z.check());){f.length=0;h.args=f;if(!B.read(h))break;w=u.state;var g,p=h.fn;f=h.args;switch(0|p){case o.OPS.setFont:var b=f[0].name,k=f[1];if(w.font&&b===w.fontName&&k===w.fontSize)break;q();w.fontName=b;w.fontSize=k;a(L(b,null));return;case o.OPS.setTextRise:q();w.textRise=f[0];break;case o.OPS.setHScale:q();w.textHScale=f[0]/100;break;case o.OPS.setLeading:q();w.leading=f[0];break;case o.OPS.moveText:var x=!!w.font&&0===(w.font.vertical?f[0]:f[1]);g=f[0]-f[1];if(m&&x&&C.initialized&&g>0&&g<=C.fakeMultiSpaceMax){w.translateTextLineMatrix(f[0],f[1]);C.width+=f[0]-C.lastAdvanceWidth;C.height+=f[1]-C.lastAdvanceHeight;U(f[0]-C.lastAdvanceWidth-(f[1]-C.lastAdvanceHeight),C.str);break}q();w.translateTextLineMatrix(f[0],f[1]);w.textMatrix=w.textLineMatrix.slice();break;case o.OPS.setLeadingMoveText:q();w.leading=-f[1];w.translateTextLineMatrix(f[0],f[1]);w.textMatrix=w.textLineMatrix.slice();break;case o.OPS.nextLine:q();w.carriageReturn();break;case o.OPS.setTextMatrix:g=w.calcTextLineMatrixAdvance(f[0],f[1],f[2],f[3],f[4],f[5]);if(m&&null!==g&&C.initialized&&g.value>0&&g.value<=C.fakeMultiSpaceMax){w.translateTextLineMatrix(g.width,g.height);C.width+=g.width-C.lastAdvanceWidth;C.height+=g.height-C.lastAdvanceHeight;U(g.width-C.lastAdvanceWidth-(g.height-C.lastAdvanceHeight),C.str);break}q();w.setTextMatrix(f[0],f[1],f[2],f[3],f[4],f[5]);w.setTextLineMatrix(f[0],f[1],f[2],f[3],f[4],f[5]);break;case o.OPS.setCharSpacing:w.charSpacing=f[0];break;case o.OPS.setWordSpacing:w.wordSpacing=f[0];break;case o.OPS.beginText:q();w.textMatrix=o.IDENTITY_MATRIX.slice();w.textLineMatrix=o.IDENTITY_MATRIX.slice();break;case o.OPS.showSpacedText:for(var _,A=f[0],I=0,T=A.length;I<T;I++)if("string"==typeof A[I])N(A[I]);else if((0,o.isNum)(A[I])){D();g=A[I]*w.fontSize/1e3;var E=!1;if(w.font.vertical){_=g;w.translateTextMatrix(0,_);(E=C.textRunBreakAllowed&&g>C.fakeMultiSpaceMax)||(C.height+=_)}else{_=(g=-g)*w.textHScale;w.translateTextMatrix(_,0);(E=C.textRunBreakAllowed&&g>C.fakeMultiSpaceMax)||(C.width+=_)}E?q():g>0&&U(g,C.str)}break;case o.OPS.showText:N(f[0]);break;case o.OPS.nextLineShowText:q();w.carriageReturn();N(f[0]);break;case o.OPS.nextLineSetSpacingShowText:q();w.wordSpacing=f[0];w.charSpacing=f[1];w.carriageReturn();N(f[2]);break;case o.OPS.paintXObject:q();F||(F=s.get("XObject")||l.Dict.empty);var M=f[0].name;if(M&&void 0!==R[M])break;a(new Promise(function(e,t){if(!M)throw new o.FormatError("XObject must be referred to by name.");var r=F.get(M);if(r){if(!(0,l.isStream)(r))throw new o.FormatError("XObject should be a stream");var a=r.dict.get("Subtype");if(!(0,l.isName)(a))throw new o.FormatError("XObject should have a Name subtype");if("Form"===a.name){var i=u.state.clone(),c=new P(i),h=r.dict.getArray("Matrix");Array.isArray(h)&&6===h.length&&c.transform(h);j();var f={enqueueInvoked:!1,enqueue:function(e,t){this.enqueueInvoked=!0;v.enqueue(e,t)},get desiredSize(){return v.desiredSize},get ready(){return v.ready}};O.getTextContent({stream:r,task:n,resources:r.dict.get("Resources")||s,stateManager:c,normalizeWhitespace:d,combineTextItems:m,sink:f,seenStyles:y}).then(function(){f.enqueueInvoked||(R[M]=!0);e()},t)}else{R[M]=!0;e()}}else e()}).catch(function(e){if(!(e instanceof o.AbortException)){if(!O.options.ignoreErrors)throw e;(0,o.warn)('getTextContent - ignoring XObject: "'+e+'".')}}));return;case o.OPS.setGState:q();var H=f[0],G=s.get("ExtGState");if(!(0,l.isDict)(G)||!(0,l.isName)(H))break;var W=G.get(H.name);if(!(0,l.isDict)(W))break;var X=W.get("Font");if(X){w.fontName=null;w.fontSize=X[1];a(L(null,X[0]));return}}if(S.items.length>=v.desiredSize){c=!0;break}}if(c)a(i);else{q();j();t()}}).catch(function(e){if(!(e instanceof o.AbortException)){if(!t.options.ignoreErrors)throw e;(0,o.warn)('getTextContent - ignoring errors during "'+n.name+'" task: "'+e+'".');q();j()}})},extractDataStructures:function(e,t,r){var a=this,i=this.xref,n=e.get("ToUnicode")||t.get("ToUnicode"),s=n?this.readToUnicode(n):Promise.resolve(void 0);if(r.composite){var c=e.get("CIDSystemInfo");(0,l.isDict)(c)&&(r.cidSystemInfo={registry:(0,o.stringToPDFString)(c.get("Registry")),ordering:(0,o.stringToPDFString)(c.get("Ordering")),supplement:c.get("Supplement")});var f=e.get("CIDToGIDMap");(0,l.isStream)(f)&&(r.cidToGidMap=this.readCidToGidMap(f))}var d,g=[],m=null;if(e.has("Encoding")){d=e.get("Encoding");if((0,l.isDict)(d)){m=d.get("BaseEncoding");m=(0,l.isName)(m)?m.name:null;if(d.has("Differences"))for(var p=d.get("Differences"),v=0,b=0,y=p.length;b<y;b++){var w=i.fetchIfRef(p[b]);if((0,o.isNum)(w))v=w;else{if(!(0,l.isName)(w))throw new o.FormatError("Invalid entry in 'Differences' array: "+w);g[v++]=w.name}}}else{if(!(0,l.isName)(d))throw new o.FormatError("Encoding is not a Name nor a Dict");m=d.name}"MacRomanEncoding"!==m&&"MacExpertEncoding"!==m&&"WinAnsiEncoding"!==m&&(m=null)}if(m)r.defaultEncoding=(0,h.getEncoding)(m).slice();else{var k=!!(r.flags&u.FontFlags.Symbolic),S=!!(r.flags&u.FontFlags.Nonsymbolic);d=h.StandardEncoding;"TrueType"!==r.type||S||(d=h.WinAnsiEncoding);if(k){d=h.MacRomanEncoding;r.file||(/Symbol/i.test(r.name)?d=h.SymbolSetEncoding:/Dingbats/i.test(r.name)&&(d=h.ZapfDingbatsEncoding))}r.defaultEncoding=d}r.differences=g;r.baseEncodingName=m;r.hasEncoding=!!m||g.length>0;r.dict=e;return s.then(function(e){r.toUnicode=e;return a.buildToUnicode(r)}).then(function(e){r.toUnicode=e;return r})},_buildSimpleFontToUnicode:function(e){(0,o.assert)(!e.composite,"Must be a simple font.");var t=[],r=void 0,a=void 0,i=e.defaultEncoding.slice(),n=e.baseEncodingName,s=e.differences;for(r in s)".notdef"!==(a=s[r])&&(i[r]=a);var c=(0,b.getGlyphsUnicode)();for(r in i)if(""!==(a=i[r]))if(void 0!==c[a])t[r]=String.fromCharCode(c[a]);else{var l=0;switch(a[0]){case"G":3===a.length&&(l=parseInt(a.substring(1),16));break;case"g":5===a.length&&(l=parseInt(a.substring(1),16));break;case"C":case"c":a.length>=3&&(l=+a.substring(1));break;default:var d=(0,f.getUnicodeForGlyph)(a,c);-1!==d&&(l=d)}if(l){if(n&&l===+r){var g=(0,h.getEncoding)(n);if(g&&(a=g[r])){t[r]=String.fromCharCode(c[a]);continue}}t[r]=String.fromCharCode(l)}}return new u.ToUnicodeMap(t)},buildToUnicode:function(e){e.hasIncludedToUnicodeMap=!!e.toUnicode&&e.toUnicode.length>0;if(e.hasIncludedToUnicodeMap){!e.composite&&e.hasEncoding&&(e.fallbackToUnicode=this._buildSimpleFontToUnicode(e));return Promise.resolve(e.toUnicode)}if(!e.composite)return Promise.resolve(this._buildSimpleFontToUnicode(e));if(e.composite&&(e.cMap.builtInCMap&&!(e.cMap instanceof s.IdentityCMap)||"Adobe"===e.cidSystemInfo.registry&&("GB1"===e.cidSystemInfo.ordering||"CNS1"===e.cidSystemInfo.ordering||"Japan1"===e.cidSystemInfo.ordering||"Korea1"===e.cidSystemInfo.ordering))){var t=e.cidSystemInfo.registry,r=e.cidSystemInfo.ordering,a=l.Name.get(t+"-"+r+"-UCS2");return s.CMapFactory.create({encoding:a,fetchBuiltInCMap:this.fetchBuiltInCMap,useCMap:null}).then(function(t){var r=[];e.cMap.forEach(function(e,a){if(a>65535)throw new o.FormatError("Max size of CID is 65,535");var i=t.lookup(a);i&&(r[e]=String.fromCharCode((i.charCodeAt(0)<<8)+i.charCodeAt(1)))});return new u.ToUnicodeMap(r)})}return Promise.resolve(new u.IdentityToUnicodeMap(e.firstChar,e.lastChar))},readToUnicode:function(e){var t=e;return(0,l.isName)(t)?s.CMapFactory.create({encoding:t,fetchBuiltInCMap:this.fetchBuiltInCMap,useCMap:null}).then(function(e){return e instanceof s.IdentityCMap?new u.IdentityToUnicodeMap(0,65535):new u.ToUnicodeMap(e.getMap())}):(0,l.isStream)(t)?s.CMapFactory.create({encoding:t,fetchBuiltInCMap:this.fetchBuiltInCMap,useCMap:null}).then(function(e){if(e instanceof s.IdentityCMap)return new u.IdentityToUnicodeMap(0,65535);var t=new Array(e.length);e.forEach(function(e,r){for(var a=[],i=0;i<r.length;i+=2){var n=r.charCodeAt(i)<<8|r.charCodeAt(i+1);if(55296==(63488&n)){i+=2;var o=r.charCodeAt(i)<<8|r.charCodeAt(i+1);a.push(((1023&n)<<10)+(1023&o)+65536)}else a.push(n)}t[e]=String.fromCharCode.apply(String,a)});return new u.ToUnicodeMap(t)}):Promise.resolve(null)},readCidToGidMap:function(e){for(var t=e.getBytes(),r=[],a=0,i=t.length;a<i;a++){var n=t[a++]<<8|t[a];if(0!==n){r[a>>1]=n}}return r},extractWidths:function(e,t,r){var a,i,n,o,s,c,h,f,d=this.xref,g=[],m=0,p=[];if(r.composite){m=e.has("DW")?e.get("DW"):1e3;if(f=e.get("W"))for(i=0,n=f.length;i<n;i++){c=d.fetchIfRef(f[i++]);h=d.fetchIfRef(f[i]);if(Array.isArray(h))for(o=0,s=h.length;o<s;o++)g[c++]=d.fetchIfRef(h[o]);else{var v=d.fetchIfRef(f[++i]);for(o=c;o<=h;o++)g[o]=v}}if(r.vertical){var b=e.getArray("DW2")||[880,-1e3];a=[b[1],.5*m,b[0]];if(b=e.get("W2"))for(i=0,n=b.length;i<n;i++){c=d.fetchIfRef(b[i++]);h=d.fetchIfRef(b[i]);if(Array.isArray(h))for(o=0,s=h.length;o<s;o++)p[c++]=[d.fetchIfRef(h[o++]),d.fetchIfRef(h[o++]),d.fetchIfRef(h[o])];else{var y=[d.fetchIfRef(b[++i]),d.fetchIfRef(b[++i]),d.fetchIfRef(b[++i])];for(o=c;o<=h;o++)p[o]=y}}}}else{var w=r.firstChar;if(f=e.get("Widths")){o=w;for(i=0,n=f.length;i<n;i++)g[o++]=d.fetchIfRef(f[i]);m=parseFloat(t.get("MissingWidth"))||0}else{var k=e.get("BaseFont");if((0,l.isName)(k)){var S=this.getBaseFontMetrics(k.name);g=this.buildCharCodeToWidth(S.widths,r);m=S.defaultWidth}}}var C=!0,x=m;for(var _ in g){var A=g[_];if(A)if(x){if(x!==A){C=!1;break}}else x=A}C&&(r.flags|=u.FontFlags.FixedPitch);r.defaultWidth=m;r.widths=g;r.defaultVMetrics=a;r.vmetrics=p},isSerifFont:function(e){var t=e.split("-")[0];return t in(0,d.getSerifFonts)()||-1!==t.search(/serif/gi)},getBaseFontMetrics:function(e){var t=0,r=[],a=!1,i=(0,d.getStdFontMap)()[e]||e,n=(0,y.getMetrics)();i in n||(i=this.isSerifFont(e)?"Times-Roman":"Helvetica");var s=n[i];if((0,o.isNum)(s)){t=s;a=!0}else r=s();return{defaultWidth:t,monospace:a,widths:r}},buildCharCodeToWidth:function(e,t){for(var r=Object.create(null),a=t.differences,i=t.defaultEncoding,n=0;n<256;n++)n in a&&e[a[n]]?r[n]=e[a[n]]:n in i&&e[i[n]]&&(r[n]=e[i[n]]);return r},preEvaluateFont:function(e){var t=e,r=e.get("Subtype");if(!(0,l.isName)(r))throw new o.FormatError("invalid font Subtype");var a,i=!1;if("Type0"===r.name){var n=e.get("DescendantFonts");if(!n)throw new o.FormatError("Descendant fonts are not specified");r=(e=Array.isArray(n)?this.xref.fetchIfRef(n[0]):n).get("Subtype");if(!(0,l.isName)(r))throw new o.FormatError("invalid font Subtype");i=!0}var s=e.get("FontDescriptor");if(s){var c=new S.MurmurHash3_64,u=t.getRaw("Encoding");if((0,l.isName)(u))c.update(u.name);else if((0,l.isRef)(u))c.update(u.toString());else if((0,l.isDict)(u))for(var h=u.getKeys(),f=0,d=h.length;f<d;f++){var g=u.getRaw(h[f]);if((0,l.isName)(g))c.update(g.name);else if((0,l.isRef)(g))c.update(g.toString());else if(Array.isArray(g)){for(var m=g.length,p=new Array(m),v=0;v<m;v++){var b=g[v];(0,l.isName)(b)?p[v]=b.name:((0,o.isNum)(b)||(0,l.isRef)(b))&&(p[v]=b.toString())}c.update(p.join())}}var y=e.get("ToUnicode")||t.get("ToUnicode");if((0,l.isStream)(y)){var w=y.str||y;a=w.buffer?new Uint8Array(w.buffer.buffer,0,w.bufferLength):new Uint8Array(w.bytes.buffer,w.start,w.end-w.start);c.update(a)}else(0,l.isName)(y)&&c.update(y.name);var k=e.get("Widths")||t.get("Widths");if(k){a=new Uint8Array(new Uint32Array(k).buffer);c.update(a)}}return{descriptor:s,dict:e,baseDict:t,composite:i,type:r.name,hash:c?c.hexdigest():""}},translateFont:function(e){var t,r=this,a=e.baseDict,i=e.dict,n=e.composite,c=e.descriptor,h=e.type,f=n?65535:255;if(!c){if("Type3"!==h){var g=i.get("BaseFont");if(!(0,l.isName)(g))throw new o.FormatError("Base font is not specified");g=g.name.replace(/[,_]/g,"-");var m=this.getBaseFontMetrics(g),p=g.split("-")[0],v=(this.isSerifFont(p)?u.FontFlags.Serif:0)|(m.monospace?u.FontFlags.FixedPitch:0)|((0,d.getSymbolsFonts)()[p]?u.FontFlags.Symbolic:u.FontFlags.Nonsymbolic);t={type:h,name:g,widths:m.widths,defaultWidth:m.defaultWidth,flags:v,firstChar:0,lastChar:f};return this.extractDataStructures(i,i,t).then(function(e){e.widths=r.buildCharCodeToWidth(m.widths,e);return new u.Font(g,null,e)})}(c=new l.Dict(null)).set("FontName",l.Name.get(h));c.set("FontBBox",i.getArray("FontBBox"))}var b=i.get("FirstChar")||0,y=i.get("LastChar")||f,w=c.get("FontName"),k=i.get("BaseFont");(0,o.isString)(w)&&(w=l.Name.get(w));(0,o.isString)(k)&&(k=l.Name.get(k));if("Type3"!==h){var S=w&&w.name,C=k&&k.name;if(S!==C){(0,o.info)("The FontDescriptor's FontName is \""+S+'" but should be the same as the Font\'s BaseFont "'+C+'"');S&&C&&0===C.indexOf(S)&&(w=k)}}w=w||k;if(!(0,l.isName)(w))throw new o.FormatError("invalid font name");var x,_=c.get("FontFile","FontFile2","FontFile3");if(_&&_.dict){var A=_.dict.get("Subtype");A&&(A=A.name);var P=_.dict.get("Length1"),I=_.dict.get("Length2"),O=_.dict.get("Length3")}t={type:h,name:w.name,subtype:A,file:_,length1:P,length2:I,length3:O,loadedName:a.loadedName,composite:n,wideChars:n,fixedPitch:!1,fontMatrix:i.getArray("FontMatrix")||o.FONT_IDENTITY_MATRIX,firstChar:b||0,lastChar:y||f,bbox:c.getArray("FontBBox"),ascent:c.get("Ascent"),descent:c.get("Descent"),xHeight:c.get("XHeight"),capHeight:c.get("CapHeight"),flags:c.get("Flags"),italicAngle:c.get("ItalicAngle"),isType3Font:!1};if(n){var T=a.get("Encoding");(0,l.isName)(T)&&(t.cidEncoding=T.name);x=s.CMapFactory.create({encoding:T,fetchBuiltInCMap:this.fetchBuiltInCMap,useCMap:null}).then(function(e){t.cMap=e;t.vertical=t.cMap.vertical})}else x=Promise.resolve(void 0);return x.then(function(){return r.extractDataStructures(i,a,t)}).then(function(e){r.extractWidths(i,c,e);"Type3"===h&&(e.isType3Font=!0);return new u.Font(w.name,_,e)})}};return r}(),A=function(){function e(e,t,r){this.loadedName=e;this.font=t;this.dict=r;this.type3Loaded=null;this.sent=!1}e.prototype={send:function(e){if(!this.sent){var t=this.font.exportData();e.send("commonobj",[this.loadedName,"Font",t]);this.sent=!0}},loadType3Data:function(e,t,r,a){if(!this.font.isType3Font)throw new Error("Must be a Type3 font.");if(this.type3Loaded)return this.type3Loaded;var i=Object.create(e.options);i.ignoreErrors=!1;for(var n=e.clone(i),s=this.font,c=Promise.resolve(),l=this.dict.get("CharProcs"),u=this.dict.get("Resources")||t,h=l.getKeys(),f=Object.create(null),d=function(){var e=h[g];c=c.then(function(){var t=l.get(e),i=new C.OperatorList;return n.getOperatorList({stream:t,task:a,resources:u,operatorList:i}).then(function(){f[e]=i.getIR();r.addDependencies(i.dependencies)}).catch(function(t){(0,o.warn)('Type3 font resource "'+e+'" is not available.');var r=new C.OperatorList;f[e]=r.getIR()})})},g=0,m=h.length;g<m;++g)d();this.type3Loaded=c.then(function(){s.charProcOperatorList=f});return this.type3Loaded}};return e}(),P=function(){function e(e){this.state=e;this.stateStack=[]}e.prototype={save:function(){var e=this.state;this.stateStack.push(this.state);this.state=e.clone()},restore:function(){var e=this.stateStack.pop();e&&(this.state=e)},transform:function(e){this.state.ctm=o.Util.transform(this.state.ctm,e)}};return e}(),I=function(){function e(){this.ctm=new Float32Array(o.IDENTITY_MATRIX);this.fontName=null;this.fontSize=0;this.font=null;this.fontMatrix=o.FONT_IDENTITY_MATRIX;this.textMatrix=o.IDENTITY_MATRIX.slice();this.textLineMatrix=o.IDENTITY_MATRIX.slice();this.charSpacing=0;this.wordSpacing=0;this.leading=0;this.textHScale=1;this.textRise=0}e.prototype={setTextMatrix:function(e,t,r,a,i,n){var o=this.textMatrix;o[0]=e;o[1]=t;o[2]=r;o[3]=a;o[4]=i;o[5]=n},setTextLineMatrix:function(e,t,r,a,i,n){var o=this.textLineMatrix;o[0]=e;o[1]=t;o[2]=r;o[3]=a;o[4]=i;o[5]=n},translateTextMatrix:function(e,t){var r=this.textMatrix;r[4]=r[0]*e+r[2]*t+r[4];r[5]=r[1]*e+r[3]*t+r[5]},translateTextLineMatrix:function(e,t){var r=this.textLineMatrix;r[4]=r[0]*e+r[2]*t+r[4];r[5]=r[1]*e+r[3]*t+r[5]},calcTextLineMatrixAdvance:function(e,t,r,a,i,n){var o=this.font;if(!o)return null;var s=this.textLineMatrix;if(e!==s[0]||t!==s[1]||r!==s[2]||a!==s[3])return null;var c=i-s[4],l=n-s[5];if(o.vertical&&0!==c||!o.vertical&&0!==l)return null;var u,h,f=e*a-t*r;if(o.vertical){u=-l*r/f;h=l*e/f}else{u=c*a/f;h=-c*t/f}return{width:u,height:h,value:o.vertical?h:u}},calcRenderMatrix:function(e){var t=[this.fontSize*this.textHScale,0,0,this.fontSize,0,this.textRise];return o.Util.transform(e,o.Util.transform(this.textMatrix,t))},carriageReturn:function(){this.translateTextLineMatrix(0,-this.leading);this.textMatrix=this.textLineMatrix.slice()},clone:function(){var e=Object.create(this);e.textMatrix=this.textMatrix.slice();e.textLineMatrix=this.textLineMatrix.slice();e.fontMatrix=this.fontMatrix.slice();return e}};return e}(),O=function(){function e(){this.ctm=new Float32Array(o.IDENTITY_MATRIX);this.font=null;this.textRenderingMode=o.TextRenderingMode.FILL;this.fillColorSpace=v.ColorSpace.singletons.gray;this.strokeColorSpace=v.ColorSpace.singletons.gray}e.prototype={clone:function(){return Object.create(this)}};return e}(),T=function(){var e=(0,o.getLookupTableFactory)(function(e){e.w={id:o.OPS.setLineWidth,numArgs:1,variableArgs:!1};e.J={id:o.OPS.setLineCap,numArgs:1,variableArgs:!1};e.j={id:o.OPS.setLineJoin,numArgs:1,variableArgs:!1};e.M={id:o.OPS.setMiterLimit,numArgs:1,variableArgs:!1};e.d={id:o.OPS.setDash,numArgs:2,variableArgs:!1};e.ri={id:o.OPS.setRenderingIntent,numArgs:1,variableArgs:!1};e.i={id:o.OPS.setFlatness,numArgs:1,variableArgs:!1};e.gs={id:o.OPS.setGState,numArgs:1,variableArgs:!1};e.q={id:o.OPS.save,numArgs:0,variableArgs:!1};e.Q={id:o.OPS.restore,numArgs:0,variableArgs:!1};e.cm={id:o.OPS.transform,numArgs:6,variableArgs:!1};e.m={id:o.OPS.moveTo,numArgs:2,variableArgs:!1};e.l={id:o.OPS.lineTo,numArgs:2,variableArgs:!1};e.c={id:o.OPS.curveTo,numArgs:6,variableArgs:!1};e.v={id:o.OPS.curveTo2,numArgs:4,variableArgs:!1};e.y={id:o.OPS.curveTo3,numArgs:4,variableArgs:!1};e.h={id:o.OPS.closePath,numArgs:0,variableArgs:!1};e.re={id:o.OPS.rectangle,numArgs:4,variableArgs:!1};e.S={id:o.OPS.stroke,numArgs:0,variableArgs:!1};e.s={id:o.OPS.closeStroke,numArgs:0,variableArgs:!1};e.f={id:o.OPS.fill,numArgs:0,variableArgs:!1};e.F={id:o.OPS.fill,numArgs:0,variableArgs:!1};e["f*"]={id:o.OPS.eoFill,numArgs:0,variableArgs:!1};e.B={id:o.OPS.fillStroke,numArgs:0,variableArgs:!1};e["B*"]={id:o.OPS.eoFillStroke,numArgs:0,variableArgs:!1};e.b={id:o.OPS.closeFillStroke,numArgs:0,variableArgs:!1};e["b*"]={id:o.OPS.closeEOFillStroke,numArgs:0,variableArgs:!1};e.n={id:o.OPS.endPath,numArgs:0,variableArgs:!1};e.W={id:o.OPS.clip,numArgs:0,variableArgs:!1};e["W*"]={id:o.OPS.eoClip,numArgs:0,variableArgs:!1};e.BT={id:o.OPS.beginText,numArgs:0,variableArgs:!1};e.ET={id:o.OPS.endText,numArgs:0,variableArgs:!1};e.Tc={id:o.OPS.setCharSpacing,numArgs:1,variableArgs:!1};e.Tw={id:o.OPS.setWordSpacing,numArgs:1,variableArgs:!1};e.Tz={id:o.OPS.setHScale,numArgs:1,variableArgs:!1};e.TL={id:o.OPS.setLeading,numArgs:1,variableArgs:!1};e.Tf={id:o.OPS.setFont,numArgs:2,variableArgs:!1};e.Tr={id:o.OPS.setTextRenderingMode,numArgs:1,variableArgs:!1};e.Ts={id:o.OPS.setTextRise,numArgs:1,variableArgs:!1};e.Td={id:o.OPS.moveText,numArgs:2,variableArgs:!1};e.TD={id:o.OPS.setLeadingMoveText,numArgs:2,variableArgs:!1};e.Tm={id:o.OPS.setTextMatrix,numArgs:6,variableArgs:!1};e["T*"]={id:o.OPS.nextLine,numArgs:0,variableArgs:!1};e.Tj={id:o.OPS.showText,numArgs:1,variableArgs:!1};e.TJ={id:o.OPS.showSpacedText,numArgs:1,variableArgs:!1};e["'"]={id:o.OPS.nextLineShowText,numArgs:1,variableArgs:!1};e['"']={id:o.OPS.nextLineSetSpacingShowText,numArgs:3,variableArgs:!1};e.d0={id:o.OPS.setCharWidth,numArgs:2,variableArgs:!1};e.d1={id:o.OPS.setCharWidthAndBounds,numArgs:6,variableArgs:!1};e.CS={id:o.OPS.setStrokeColorSpace,numArgs:1,variableArgs:!1};e.cs={id:o.OPS.setFillColorSpace,numArgs:1,variableArgs:!1};e.SC={id:o.OPS.setStrokeColor,numArgs:4,variableArgs:!0};e.SCN={id:o.OPS.setStrokeColorN,numArgs:33,variableArgs:!0};e.sc={id:o.OPS.setFillColor,numArgs:4,variableArgs:!0};e.scn={id:o.OPS.setFillColorN,numArgs:33,variableArgs:!0};e.G={id:o.OPS.setStrokeGray,numArgs:1,variableArgs:!1};e.g={id:o.OPS.setFillGray,numArgs:1,variableArgs:!1};e.RG={id:o.OPS.setStrokeRGBColor,numArgs:3,variableArgs:!1};e.rg={id:o.OPS.setFillRGBColor,numArgs:3,variableArgs:!1};e.K={id:o.OPS.setStrokeCMYKColor,numArgs:4,variableArgs:!1};e.k={id:o.OPS.setFillCMYKColor,numArgs:4,variableArgs:!1};e.sh={id:o.OPS.shadingFill,numArgs:1,variableArgs:!1};e.BI={id:o.OPS.beginInlineImage,numArgs:0,variableArgs:!1};e.ID={id:o.OPS.beginImageData,numArgs:0,variableArgs:!1};e.EI={id:o.OPS.endInlineImage,numArgs:1,variableArgs:!1};e.Do={id:o.OPS.paintXObject,numArgs:1,variableArgs:!1};e.MP={id:o.OPS.markPoint,numArgs:1,variableArgs:!1};e.DP={id:o.OPS.markPointProps,numArgs:2,variableArgs:!1};e.BMC={id:o.OPS.beginMarkedContent,numArgs:1,variableArgs:!1};e.BDC={id:o.OPS.beginMarkedContentProps,numArgs:2,variableArgs:!1};e.EMC={id:o.OPS.endMarkedContent,numArgs:0,variableArgs:!1};e.BX={id:o.OPS.beginCompat,numArgs:0,variableArgs:!1};e.EX={id:o.OPS.endCompat,numArgs:0,variableArgs:!1};e.BM=null;e.BD=null;e.true=null;e.fa=null;e.fal=null;e.fals=null;e.false=null;e.nu=null;e.nul=null;e.null=null});function t(t,r,a){this.opMap=e();this.parser=new m.Parser(new m.Lexer(t,this.opMap),!1,r);this.stateManager=a;this.nonProcessedArgs=[];this._numInvalidPathOPS=0}t.prototype={get savedStatesDepth(){return this.stateManager.stateStack.length},read:function(e){for(var t=e.args;;){var r=this.parser.getObj();if((0,l.isCmd)(r)){var a=r.cmd,i=this.opMap[a];if(!i){(0,o.warn)('Unknown command "'+a+'".');continue}var n=i.id,s=i.numArgs,c=null!==t?t.length:0;if(i.variableArgs)c>s&&(0,o.info)("Command "+a+": expected [0, "+s+"] args, but received "+c+" args.");else{if(c!==s){for(var u=this.nonProcessedArgs;c>s;){u.push(t.shift());c--}for(;c<s&&0!==u.length;){null===t&&(t=[]);t.unshift(u.pop());c++}}if(c<s){var h="command "+a+": expected "+s+" args, but received "+c+" args.";if(n>=o.OPS.moveTo&&n<=o.OPS.endPath&&++this._numInvalidPathOPS>20)throw new o.FormatError("Invalid "+h);(0,o.warn)("Skipping "+h);null!==t&&(t.length=0);continue}}this.preprocessCommand(n,t);e.fn=n;e.args=t;return!0}if((0,l.isEOF)(r))return!1;if(null!==r){null===t&&(t=[]);t.push(r);if(t.length>33)throw new o.FormatError("Too many arguments")}}},preprocessCommand:function(e,t){switch(0|e){case o.OPS.save:this.stateManager.save();break;case o.OPS.restore:this.stateManager.restore();break;case o.OPS.transform:this.stateManager.transform(t)}}};return t}();t.PartialEvaluator=_},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.CMapFactory=t.IdentityCMap=t.CMap=void 0;var a=function(){function e(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1;a.configurable=!0;"value"in a&&(a.writable=!0);Object.defineProperty(e,a.key,a)}}return function(t,r,a){r&&e(t.prototype,r);a&&e(t,a);return t}}(),i=r(2),n=r(138),o=r(139),s=r(140);function c(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var l=["Adobe-GB1-UCS2","Adobe-CNS1-UCS2","Adobe-Japan1-UCS2","Adobe-Korea1-UCS2","78-EUC-H","78-EUC-V","78-H","78-RKSJ-H","78-RKSJ-V","78-V","78ms-RKSJ-H","78ms-RKSJ-V","83pv-RKSJ-H","90ms-RKSJ-H","90ms-RKSJ-V","90msp-RKSJ-H","90msp-RKSJ-V","90pv-RKSJ-H","90pv-RKSJ-V","Add-H","Add-RKSJ-H","Add-RKSJ-V","Add-V","Adobe-CNS1-0","Adobe-CNS1-1","Adobe-CNS1-2","Adobe-CNS1-3","Adobe-CNS1-4","Adobe-CNS1-5","Adobe-CNS1-6","Adobe-GB1-0","Adobe-GB1-1","Adobe-GB1-2","Adobe-GB1-3","Adobe-GB1-4","Adobe-GB1-5","Adobe-Japan1-0","Adobe-Japan1-1","Adobe-Japan1-2","Adobe-Japan1-3","Adobe-Japan1-4","Adobe-Japan1-5","Adobe-Japan1-6","Adobe-Korea1-0","Adobe-Korea1-1","Adobe-Korea1-2","B5-H","B5-V","B5pc-H","B5pc-V","CNS-EUC-H","CNS-EUC-V","CNS1-H","CNS1-V","CNS2-H","CNS2-V","ETHK-B5-H","ETHK-B5-V","ETen-B5-H","ETen-B5-V","ETenms-B5-H","ETenms-B5-V","EUC-H","EUC-V","Ext-H","Ext-RKSJ-H","Ext-RKSJ-V","Ext-V","GB-EUC-H","GB-EUC-V","GB-H","GB-V","GBK-EUC-H","GBK-EUC-V","GBK2K-H","GBK2K-V","GBKp-EUC-H","GBKp-EUC-V","GBT-EUC-H","GBT-EUC-V","GBT-H","GBT-V","GBTpc-EUC-H","GBTpc-EUC-V","GBpc-EUC-H","GBpc-EUC-V","H","HKdla-B5-H","HKdla-B5-V","HKdlb-B5-H","HKdlb-B5-V","HKgccs-B5-H","HKgccs-B5-V","HKm314-B5-H","HKm314-B5-V","HKm471-B5-H","HKm471-B5-V","HKscs-B5-H","HKscs-B5-V","Hankaku","Hiragana","KSC-EUC-H","KSC-EUC-V","KSC-H","KSC-Johab-H","KSC-Johab-V","KSC-V","KSCms-UHC-H","KSCms-UHC-HW-H","KSCms-UHC-HW-V","KSCms-UHC-V","KSCpc-EUC-H","KSCpc-EUC-V","Katakana","NWP-H","NWP-V","RKSJ-H","RKSJ-V","Roman","UniCNS-UCS2-H","UniCNS-UCS2-V","UniCNS-UTF16-H","UniCNS-UTF16-V","UniCNS-UTF32-H","UniCNS-UTF32-V","UniCNS-UTF8-H","UniCNS-UTF8-V","UniGB-UCS2-H","UniGB-UCS2-V","UniGB-UTF16-H","UniGB-UTF16-V","UniGB-UTF32-H","UniGB-UTF32-V","UniGB-UTF8-H","UniGB-UTF8-V","UniJIS-UCS2-H","UniJIS-UCS2-HW-H","UniJIS-UCS2-HW-V","UniJIS-UCS2-V","UniJIS-UTF16-H","UniJIS-UTF16-V","UniJIS-UTF32-H","UniJIS-UTF32-V","UniJIS-UTF8-H","UniJIS-UTF8-V","UniJIS2004-UTF16-H","UniJIS2004-UTF16-V","UniJIS2004-UTF32-H","UniJIS2004-UTF32-V","UniJIS2004-UTF8-H","UniJIS2004-UTF8-V","UniJISPro-UCS2-HW-V","UniJISPro-UCS2-V","UniJISPro-UTF8-V","UniJISX0213-UTF32-H","UniJISX0213-UTF32-V","UniJISX02132004-UTF32-H","UniJISX02132004-UTF32-V","UniKS-UCS2-H","UniKS-UCS2-V","UniKS-UTF16-H","UniKS-UTF16-V","UniKS-UTF32-H","UniKS-UTF32-V","UniKS-UTF8-H","UniKS-UTF8-V","V","WP-Symbol"],u=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];c(this,e);this.codespaceRanges=[[],[],[],[]];this.numCodespaceRanges=0;this._map=[];this.name="";this.vertical=!1;this.useCMap=null;this.builtInCMap=t}a(e,[{key:"addCodespaceRange",value:function(e,t,r){this.codespaceRanges[e-1].push(t,r);this.numCodespaceRanges++}},{key:"mapCidRange",value:function(e,t,r){for(;e<=t;)this._map[e++]=r++}},{key:"mapBfRange",value:function(e,t,r){for(var a=r.length-1;e<=t;){this._map[e++]=r;r=r.substring(0,a)+String.fromCharCode(r.charCodeAt(a)+1)}}},{key:"mapBfRangeToArray",value:function(e,t,r){for(var a=0,i=r.length;e<=t&&a<i;){this._map[e]=r[a++];++e}}},{key:"mapOne",value:function(e,t){this._map[e]=t}},{key:"lookup",value:function(e){return this._map[e]}},{key:"contains",value:function(e){return void 0!==this._map[e]}},{key:"forEach",value:function(e){var t=this._map,r=t.length;if(r<=65536)for(var a=0;a<r;a++)void 0!==t[a]&&e(a,t[a]);else for(var i in t)e(i,t[i])}},{key:"charCodeOf",value:function(e){var t=this._map;if(t.length<=65536)return t.indexOf(e);for(var r in t)if(t[r]===e)return 0|r;return-1}},{key:"getMap",value:function(){return this._map}},{key:"readCharCode",value:function(e,t,r){for(var a=0,i=this.codespaceRanges,n=0,o=i.length;n<o;n++){a=(a<<8|e.charCodeAt(t+n))>>>0;for(var s=i[n],c=0,l=s.length;c<l;){var u=s[c++],h=s[c++];if(a>=u&&a<=h){r.charcode=a;r.length=n+1;return}}}r.charcode=0;r.length=1}},{key:"length",get:function(){return this._map.length}},{key:"isIdentityCMap",get:function(){if("Identity-H"!==this.name&&"Identity-V"!==this.name)return!1;if(65536!==this._map.length)return!1;for(var e=0;e<65536;e++)if(this._map[e]!==e)return!1;return!0}}]);return e}(),h=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}});t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,u);function t(e,r){c(this,t);var a=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));a.vertical=e;a.addCodespaceRange(r,0,65535);return a}a(t,[{key:"mapCidRange",value:function(e,t,r){(0,i.unreachable)("should not call mapCidRange")}},{key:"mapBfRange",value:function(e,t,r){(0,i.unreachable)("should not call mapBfRange")}},{key:"mapBfRangeToArray",value:function(e,t,r){(0,i.unreachable)("should not call mapBfRangeToArray")}},{key:"mapOne",value:function(e,t){(0,i.unreachable)("should not call mapCidOne")}},{key:"lookup",value:function(e){return Number.isInteger(e)&&e<=65535?e:void 0}},{key:"contains",value:function(e){return Number.isInteger(e)&&e<=65535}},{key:"forEach",value:function(e){for(var t=0;t<=65535;t++)e(t,t)}},{key:"charCodeOf",value:function(e){return Number.isInteger(e)&&e<=65535?e:-1}},{key:"getMap",value:function(){for(var e=new Array(65536),t=0;t<=65535;t++)e[t]=t;return e}},{key:"length",get:function(){return 65536}},{key:"isIdentityCMap",get:function(){(0,i.unreachable)("should not access .isIdentityCMap")}}]);return t}(),f=function(){function e(e,t){for(var r=0,a=0;a<=t;a++)r=r<<8|e[a];return r>>>0}function t(e,t){return 1===t?String.fromCharCode(e[0],e[1]):3===t?String.fromCharCode(e[0],e[1],e[2],e[3]):String.fromCharCode.apply(null,e.subarray(0,t+1))}function r(e,t,r){for(var a=0,i=r;i>=0;i--){a+=e[i]+t[i];e[i]=255&a;a>>=8}}function a(e,t){for(var r=1,a=t;a>=0&&r>0;a--){r+=e[a];e[a]=255&r;r>>=8}}var n=16,o=19;function s(e){this.buffer=e;this.pos=0;this.end=e.length;this.tmpBuf=new Uint8Array(o)}s.prototype={readByte:function(){return this.pos>=this.end?-1:this.buffer[this.pos++]},readNumber:function(){var e,t=0;do{var r=this.readByte();if(r<0)throw new i.FormatError("unexpected EOF in bcmap");e=!(128&r);t=t<<7|127&r}while(!e);return t},readSigned:function(){var e=this.readNumber();return 1&e?~(e>>>1):e>>>1},readHex:function(e,t){e.set(this.buffer.subarray(this.pos,this.pos+t+1));this.pos+=t+1},readHexNumber:function(e,t){var r,a=this.tmpBuf,n=0;do{var o=this.readByte();if(o<0)throw new i.FormatError("unexpected EOF in bcmap");r=!(128&o);a[n++]=127&o}while(!r);for(var s=t,c=0,l=0;s>=0;){for(;l<8&&a.length>0;){c=a[--n]<<l|c;l+=7}e[s]=255&c;s--;c>>=8;l-=8}},readHexSigned:function(e,t){this.readHexNumber(e,t);for(var r=1&e[t]?255:0,a=0,i=0;i<=t;i++){a=(1&a)<<8|e[i];e[i]=a>>1^r}},readString:function(){for(var e=this.readNumber(),t="",r=0;r<e;r++)t+=String.fromCharCode(this.readNumber());return t}};function c(){}c.prototype={process:function(i,o,c){return new Promise(function(l,u){var h=new s(i),f=h.readByte();o.vertical=!!(1&f);for(var d,g,m=null,p=new Uint8Array(n),v=new Uint8Array(n),b=new Uint8Array(n),y=new Uint8Array(n),w=new Uint8Array(n);(g=h.readByte())>=0;){var k=g>>5;if(7!==k){var S=!!(16&g),C=15&g;if(C+1>n)throw new Error("processBinaryCMap: Invalid dataSize.");var x,_=h.readNumber();switch(k){case 0:h.readHex(p,C);h.readHexNumber(v,C);r(v,p,C);o.addCodespaceRange(C+1,e(p,C),e(v,C));for(x=1;x<_;x++){a(v,C);h.readHexNumber(p,C);r(p,v,C);h.readHexNumber(v,C);r(v,p,C);o.addCodespaceRange(C+1,e(p,C),e(v,C))}break;case 1:h.readHex(p,C);h.readHexNumber(v,C);r(v,p,C);h.readNumber();for(x=1;x<_;x++){a(v,C);h.readHexNumber(p,C);r(p,v,C);h.readHexNumber(v,C);r(v,p,C);h.readNumber()}break;case 2:h.readHex(b,C);d=h.readNumber();o.mapOne(e(b,C),d);for(x=1;x<_;x++){a(b,C);if(!S){h.readHexNumber(w,C);r(b,w,C)}d=h.readSigned()+(d+1);o.mapOne(e(b,C),d)}break;case 3:h.readHex(p,C);h.readHexNumber(v,C);r(v,p,C);d=h.readNumber();o.mapCidRange(e(p,C),e(v,C),d);for(x=1;x<_;x++){a(v,C);if(S)p.set(v);else{h.readHexNumber(p,C);r(p,v,C)}h.readHexNumber(v,C);r(v,p,C);d=h.readNumber();o.mapCidRange(e(p,C),e(v,C),d)}break;case 4:h.readHex(b,1);h.readHex(y,C);o.mapOne(e(b,1),t(y,C));for(x=1;x<_;x++){a(b,1);if(!S){h.readHexNumber(w,1);r(b,w,1)}a(y,C);h.readHexSigned(w,C);r(y,w,C);o.mapOne(e(b,1),t(y,C))}break;case 5:h.readHex(p,1);h.readHexNumber(v,1);r(v,p,1);h.readHex(y,C);o.mapBfRange(e(p,1),e(v,1),t(y,C));for(x=1;x<_;x++){a(v,1);if(S)p.set(v);else{h.readHexNumber(p,1);r(p,v,1)}h.readHexNumber(v,1);r(v,p,1);h.readHex(y,C);o.mapBfRange(e(p,1),e(v,1),t(y,C))}break;default:u(new Error("processBinaryCMap: Unknown type: "+k));return}}else switch(31&g){case 0:h.readString();break;case 1:m=h.readString()}}l(m?c(m):o)})}};return c}(),d=function(){function e(e){for(var t=0,r=0;r<e.length;r++)t=t<<8|e.charCodeAt(r);return t>>>0}function t(e){if(!(0,i.isString)(e))throw new i.FormatError("Malformed CMap: expected string.")}function r(e){if(!Number.isInteger(e))throw new i.FormatError("Malformed CMap: expected int.")}function a(r,a){for(;;){var i=a.getObj();if((0,n.isEOF)(i))break;if((0,n.isCmd)(i,"endbfchar"))return;t(i);var o=e(i);t(i=a.getObj());var s=i;r.mapOne(o,s)}}function c(r,a){for(;;){var o=a.getObj();if((0,n.isEOF)(o))break;if((0,n.isCmd)(o,"endbfrange"))return;t(o);var s=e(o);t(o=a.getObj());var c=e(o);o=a.getObj();if(Number.isInteger(o)||(0,i.isString)(o)){var l=Number.isInteger(o)?String.fromCharCode(o):o;r.mapBfRange(s,c,l)}else{if(!(0,n.isCmd)(o,"["))break;o=a.getObj();for(var u=[];!(0,n.isCmd)(o,"]")&&!(0,n.isEOF)(o);){u.push(o);o=a.getObj()}r.mapBfRangeToArray(s,c,u)}}throw new i.FormatError("Invalid bf range.")}function d(a,i){for(;;){var o=i.getObj();if((0,n.isEOF)(o))break;if((0,n.isCmd)(o,"endcidchar"))return;t(o);var s=e(o);r(o=i.getObj());var c=o;a.mapOne(s,c)}}function g(a,i){for(;;){var o=i.getObj();if((0,n.isEOF)(o))break;if((0,n.isCmd)(o,"endcidrange"))return;t(o);var s=e(o);t(o=i.getObj());var c=e(o);r(o=i.getObj());var l=o;a.mapCidRange(s,c,l)}}function m(t,r){for(;;){var a=r.getObj();if((0,n.isEOF)(a))break;if((0,n.isCmd)(a,"endcodespacerange"))return;if(!(0,i.isString)(a))break;var o=e(a);a=r.getObj();if(!(0,i.isString)(a))break;var s=e(a);t.addCodespaceRange(a.length,o,s)}throw new i.FormatError("Invalid codespace range.")}function p(e,t){var r=t.getObj();Number.isInteger(r)&&(e.vertical=!!r)}function v(e,t){var r=t.getObj();(0,n.isName)(r)&&(0,i.isString)(r.name)&&(e.name=r.name)}function b(e,t,r,o){var s,l;e:for(;;)try{var u=t.getObj();if((0,n.isEOF)(u))break;if((0,n.isName)(u)){"WMode"===u.name?p(e,t):"CMapName"===u.name&&v(e,t);s=u}else if((0,n.isCmd)(u))switch(u.cmd){case"endcmap":break e;case"usecmap":(0,n.isName)(s)&&(l=s.name);break;case"begincodespacerange":m(e,t);break;case"beginbfchar":a(e,t);break;case"begincidchar":d(e,t);break;case"beginbfrange":c(e,t);break;case"begincidrange":g(e,t)}}catch(e){if(e instanceof i.MissingDataException)throw e;(0,i.warn)("Invalid cMap data: "+e);continue}!o&&l&&(o=l);return o?y(e,r,o):Promise.resolve(e)}function y(e,t,r){return w(r,t).then(function(t){e.useCMap=t;if(0===e.numCodespaceRanges){for(var r=e.useCMap.codespaceRanges,a=0;a<r.length;a++)e.codespaceRanges[a]=r[a].slice();e.numCodespaceRanges=e.useCMap.numCodespaceRanges}e.useCMap.forEach(function(t,r){e.contains(t)||e.mapOne(t,e.useCMap.lookup(t))});return e})}function w(e,t){return"Identity-H"===e?Promise.resolve(new h(!1,2)):"Identity-V"===e?Promise.resolve(new h(!0,2)):l.includes(e)?t?t(e).then(function(e){var r=e.cMapData,a=e.compressionType,n=new u(!0);if(a===i.CMapCompressionType.BINARY)return(new f).process(r,n,function(e){return y(n,t,e)});if(a===i.CMapCompressionType.NONE){var c=new o.Lexer(new s.Stream(r));return b(n,c,t,null)}return Promise.reject(new Error("TODO: Only BINARY/NONE CMap compression is currently supported."))}):Promise.reject(new Error("Built-in CMap parameters are not provided.")):Promise.reject(new Error("Unknown CMap name: "+e))}return{create:function(e){var t=e.encoding,r=e.fetchBuiltInCMap,a=e.useCMap;if((0,n.isName)(t))return w(t.name,r);if((0,n.isStream)(t)){return b(new u,new o.Lexer(t),r,a).then(function(e){return e.isIdentityCMap?w(e.name,r):e})}return Promise.reject(new Error("Encoding required."))}}}();t.CMap=u;t.IdentityCMap=h;t.CMapFactory=d},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.getFontType=t.IdentityToUnicodeMap=t.ToUnicodeMap=t.FontFlags=t.Font=t.ErrorFont=t.SEAC_ANALYSIS_ENABLED=void 0;var a=function(){return function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var r=[],a=!0,i=!1,n=void 0;try{for(var o,s=e[Symbol.iterator]();!(a=(o=s.next()).done);a=!0){r.push(o.value);if(t&&r.length===t)break}}catch(e){i=!0;n=e}finally{try{!a&&s.return&&s.return()}finally{if(i)throw n}}return r}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),i=r(2),n=r(157),o=r(160),s=r(159),c=r(161),l=r(162),u=r(163),h=r(155),f=r(140),d=r(164),g=[[57344,63743],[1048576,1114109]],m=1e3,p=!0,v={FixedPitch:1,Serif:2,Symbolic:4,Script:8,Nonsymbolic:32,Italic:64,AllCap:65536,SmallCap:131072,ForceBold:262144},b=[".notdef",".null","nonmarkingreturn","space","exclam","quotedbl","numbersign","dollar","percent","ampersand","quotesingle","parenleft","parenright","asterisk","plus","comma","hyphen","period","slash","zero","one","two","three","four","five","six","seven","eight","nine","colon","semicolon","less","equal","greater","question","at","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","bracketleft","backslash","bracketright","asciicircum","underscore","grave","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde","Adieresis","Aring","Ccedilla","Eacute","Ntilde","Odieresis","Udieresis","aacute","agrave","acircumflex","adieresis","atilde","aring","ccedilla","eacute","egrave","ecircumflex","edieresis","iacute","igrave","icircumflex","idieresis","ntilde","oacute","ograve","ocircumflex","odieresis","otilde","uacute","ugrave","ucircumflex","udieresis","dagger","degree","cent","sterling","section","bullet","paragraph","germandbls","registered","copyright","trademark","acute","dieresis","notequal","AE","Oslash","infinity","plusminus","lessequal","greaterequal","yen","mu","partialdiff","summation","product","pi","integral","ordfeminine","ordmasculine","Omega","ae","oslash","questiondown","exclamdown","logicalnot","radical","florin","approxequal","Delta","guillemotleft","guillemotright","ellipsis","nonbreakingspace","Agrave","Atilde","Otilde","OE","oe","endash","emdash","quotedblleft","quotedblright","quoteleft","quoteright","divide","lozenge","ydieresis","Ydieresis","fraction","currency","guilsinglleft","guilsinglright","fi","fl","daggerdbl","periodcentered","quotesinglbase","quotedblbase","perthousand","Acircumflex","Ecircumflex","Aacute","Edieresis","Egrave","Iacute","Icircumflex","Idieresis","Igrave","Oacute","Ocircumflex","apple","Ograve","Uacute","Ucircumflex","Ugrave","dotlessi","circumflex","tilde","macron","breve","dotaccent","ring","cedilla","hungarumlaut","ogonek","caron","Lslash","lslash","Scaron","scaron","Zcaron","zcaron","brokenbar","Eth","eth","Yacute","yacute","Thorn","thorn","minus","multiply","onesuperior","twosuperior","threesuperior","onehalf","onequarter","threequarters","franc","Gbreve","gbreve","Idotaccent","Scedilla","scedilla","Cacute","cacute","Ccaron","ccaron","dcroat"];function y(e){if(e.fontMatrix&&e.fontMatrix[0]!==i.FONT_IDENTITY_MATRIX[0]){var t=.001/e.fontMatrix[0],r=e.widths;for(var a in r)r[a]*=t;e.defaultWidth*=t}}function w(e,t){switch(e){case"Type1":return"Type1C"===t?i.FontType.TYPE1C:i.FontType.TYPE1;case"CIDFontType0":return"CIDFontType0C"===t?i.FontType.CIDFONTTYPE0C:i.FontType.CIDFONTTYPE0;case"OpenType":return i.FontType.OPENTYPE;case"TrueType":return i.FontType.TRUETYPE;case"CIDFontType2":return i.FontType.CIDFONTTYPE2;case"MMType1":return i.FontType.MMTYPE1;case"Type0":return i.FontType.TYPE0;default:return i.FontType.UNKNOWN}}function k(e,t){if(void 0!==t[e])return e;var r=(0,l.getUnicodeForGlyph)(e,t);if(-1!==r)for(var a in t)if(t[a]===r)return a;(0,i.info)("Unable to recover a standard glyph name for: "+e);return e}var S=function(){function e(e,t,r,a,i,n,o,s){this.fontChar=e;this.unicode=t;this.accent=r;this.width=a;this.vmetric=i;this.operatorListId=n;this.isSpace=o;this.isInFont=s}e.prototype.matchesForCache=function(e,t,r,a,i,n,o,s){return this.fontChar===e&&this.unicode===t&&this.accent===r&&this.width===a&&this.vmetric===i&&this.operatorListId===n&&this.isSpace===o&&this.isInFont===s};return e}(),C=function(){function e(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this._map=e}e.prototype={get length(){return this._map.length},forEach:function(e){for(var t in this._map)e(t,this._map[t].charCodeAt(0))},has:function(e){return void 0!==this._map[e]},get:function(e){return this._map[e]},charCodeOf:function(e){var t=this._map;if(t.length<=65536)return t.indexOf(e);for(var r in t)if(t[r]===e)return 0|r;return-1},amend:function(e){for(var t in e)this._map[t]=e[t]}};return e}(),x=function(){function e(e,t){this.firstChar=e;this.lastChar=t}e.prototype={get length(){return this.lastChar+1-this.firstChar},forEach:function(e){for(var t=this.firstChar,r=this.lastChar;t<=r;t++)e(t,t)},has:function(e){return this.firstChar<=e&&e<=this.lastChar},get:function(e){if(this.firstChar<=e&&e<=this.lastChar)return String.fromCharCode(e)},charCodeOf:function(e){return Number.isInteger(e)&&e>=this.firstChar&&e<=this.lastChar?e:-1},amend:function(e){(0,i.unreachable)("Should not call amend()")}};return e}(),_=function(){function e(e,t,r){e[t]=r>>8&255;e[t+1]=255&r}function t(e,t,r){e[t]=r>>24&255;e[t+1]=r>>16&255;e[t+2]=r>>8&255;e[t+3]=255&r}function r(e,t,r){var a,i;if(r instanceof Uint8Array)e.set(r,t);else if("string"==typeof r)for(a=0,i=r.length;a<i;a++)e[t++]=255&r.charCodeAt(a);else for(a=0,i=r.length;a<i;a++)e[t++]=255&r[a]}function a(e){this.sfnt=e;this.tables=Object.create(null)}a.getSearchParams=function(e,t){for(var r=1,a=0;(r^e)>r;){r<<=1;a++}var i=r*t;return{range:i,entry:a,rangeShift:t*e-i}};a.prototype={toArray:function(){var n=this.sfnt,o=this.tables,s=Object.keys(o);s.sort();var c,l,u,h,f,d=s.length,g=12+16*d,m=[g];for(c=0;c<d;c++){g+=((h=o[s[c]]).length+3&-4)>>>0;m.push(g)}var p=new Uint8Array(g);for(c=0;c<d;c++){h=o[s[c]];r(p,m[c],h)}"true"===n&&(n=(0,i.string32)(65536));p[0]=255&n.charCodeAt(0);p[1]=255&n.charCodeAt(1);p[2]=255&n.charCodeAt(2);p[3]=255&n.charCodeAt(3);e(p,4,d);var v=a.getSearchParams(d,16);e(p,6,v.range);e(p,8,v.entry);e(p,10,v.rangeShift);g=12;for(c=0;c<d;c++){f=s[c];p[g]=255&f.charCodeAt(0);p[g+1]=255&f.charCodeAt(1);p[g+2]=255&f.charCodeAt(2);p[g+3]=255&f.charCodeAt(3);var b=0;for(l=m[c],u=m[c+1];l<u;l+=4){b=b+(0,i.readUint32)(p,l)>>>0}t(p,g+4,b);t(p,g+8,m[c]);t(p,g+12,o[f].length);g+=16}return p},addTable:function(e,t){if(e in this.tables)throw new Error("Table "+e+" already exists");this.tables[e]=t}};return a}(),A=function(){function e(e,t,r){var n;this.name=e;this.loadedName=r.loadedName;this.isType3Font=r.isType3Font;this.sizes=[];this.missingFile=!1;this.glyphCache=Object.create(null);this.isSerifFont=!!(r.flags&v.Serif);this.isSymbolicFont=!!(r.flags&v.Symbolic);this.isMonospace=!!(r.flags&v.FixedPitch);var o=r.type,s=r.subtype;this.type=o;this.subtype=s;this.fallbackName=this.isMonospace?"monospace":this.isSerifFont?"serif":"sans-serif";this.differences=r.differences;this.widths=r.widths;this.defaultWidth=r.defaultWidth;this.composite=r.composite;this.wideChars=r.wideChars;this.cMap=r.cMap;this.ascent=r.ascent/m;this.descent=r.descent/m;this.fontMatrix=r.fontMatrix;this.bbox=r.bbox;this.defaultEncoding=r.defaultEncoding;this.toUnicode=r.toUnicode;this.fallbackToUnicode=r.fallbackToUnicode||new C;this.toFontChar=[];if("Type3"!==r.type){this.cidEncoding=r.cidEncoding;this.vertical=r.vertical;if(this.vertical){this.vmetrics=r.vmetrics;this.defaultVMetrics=r.defaultVMetrics}if(t&&!t.isEmpty){var c=function(e,t){var r=t.type,a=t.subtype,n=t.composite,o=void 0,s=void 0;if(function(e){var t=e.peekBytes(4);return 65536===(0,i.readUint32)(t,0)||"true"===(0,i.bytesToString)(t)}(e)||I(e))o=n?"CIDFontType2":"TrueType";else if(function(e){var t=e.peekBytes(4);return"OTTO"===(0,i.bytesToString)(t)}(e))o=n?"CIDFontType2":"OpenType";else if(function(e){var t=e.peekBytes(2);if(37===t[0]&&33===t[1])return!0;if(128===t[0]&&1===t[1])return!0;return!1}(e))o=n?"CIDFontType0":"MMType1"===r?"MMType1":"Type1";else if(function(e){var t=e.peekBytes(4);if(t[0]>=1&&t[3]>=1&&t[3]<=4)return!0;return!1}(e))if(n){o="CIDFontType0";s="CIDFontType0C"}else{o="MMType1"===r?"MMType1":"Type1";s="Type1C"}else{(0,i.warn)("getFontFileType: Unable to detect correct font file Type/Subtype.");o=r;s=a}return[o,s]}(t,r),l=a(c,2);o=l[0];s=l[1];o===this.type&&s===this.subtype||(0,i.info)("Inconsistent font file Type/SubType, expected: "+this.type+"/"+this.subtype+" but found: "+o+"/"+s+".");try{var u;switch(o){case"MMType1":(0,i.info)("MMType1 font ("+e+"), falling back to Type1.");case"Type1":case"CIDFontType0":this.mimetype="font/opentype";var h="Type1C"===s||"CIDFontType0C"===s?new T(t,r):new O(e,t,r);y(r);u=this.convert(e,h,r);break;case"OpenType":case"TrueType":case"CIDFontType2":this.mimetype="font/opentype";u=this.checkAndRepair(e,t,r);if(this.isOpenType){y(r);o="OpenType"}break;default:throw new i.FormatError("Font "+o+" is not supported")}}catch(e){(0,i.warn)(e);this.fallbackToSystemFont();return}this.data=u;this.fontType=w(o,s);this.fontMatrix=r.fontMatrix;this.widths=r.widths;this.defaultWidth=r.defaultWidth;this.toUnicode=r.toUnicode;this.encoding=r.baseEncoding;this.seacMap=r.seacMap}else{t&&(0,i.warn)('Font file is empty in "'+e+'" ('+this.loadedName+")");this.fallbackToSystemFont()}}else{for(n=0;n<256;n++)this.toFontChar[n]=this.differences[n]||r.defaultEncoding[n];this.fontType=i.FontType.TYPE3}}e.getFontID=(t=1,function(){return String(t++)});var t;function r(e,t){return(e<<8)+t}function d(e,t){var r=(e<<8)+t;return 32768&r?r-65536:r}function A(e){return String.fromCharCode(e>>8&255,255&e)}function P(e){e=e>32767?32767:e<-32768?-32768:e;return String.fromCharCode(e>>8&255,255&e)}function I(e){var t=e.peekBytes(4);return"ttcf"===(0,i.bytesToString)(t)}function E(e,t,r){for(var a,i=[],n=0,o=e.length;n<o;n++)-1!==(a=(0,l.getUnicodeForGlyph)(e[n],t))&&(i[n]=a);for(var s in r)-1!==(a=(0,l.getUnicodeForGlyph)(r[s],t))&&(i[+s]=a);return i}function F(e,t,r){var a=Object.create(null),n=[],o=0,s=g[o][0],c=g[o][1];for(var l in e){var u=e[l|=0];if(t(u)){if(s>c){if(++o>=g.length){(0,i.warn)("Ran out of space in font private use area.");break}s=g[o][0];c=g[o][1]}var h=s++;0===u&&(u=r);a[h]=u;n[l]=h}}return{toFontChar:n,charCodeToGlyphId:a,nextAvailableFontCharCode:s}}function R(e,t){var r,a,n,o,s=function(e,t){var r=[];for(var a in e)e[a]>=t||r.push({fontCharCode:0|a,glyphId:e[a]});0===r.length&&r.push({fontCharCode:0,glyphId:0});r.sort(function(e,t){return e.fontCharCode-t.fontCharCode});for(var i=[],n=r.length,o=0;o<n;){var s=r[o].fontCharCode,c=[r[o].glyphId];++o;for(var l=s;o<n&&l+1===r[o].fontCharCode;){c.push(r[o].glyphId);++o;if(65535==++l)break}i.push([s,l,c])}return i}(e,t),c=s[s.length-1][1]>65535?2:1,l="\0\0"+A(c)+"\0\0"+(0,i.string32)(4+8*c);for(r=s.length-1;r>=0&&!(s[r][0]<=65535);--r);var u=r+1;s[r][0]<65535&&65535===s[r][1]&&(s[r][1]=65534);var h,f,d,g,m=s[r][1]<65535?1:0,p=u+m,v=_.getSearchParams(p,2),b="",y="",w="",k="",S="",C=0;for(r=0,a=u;r<a;r++){f=(h=s[r])[0];d=h[1];b+=A(f);y+=A(d);var x=!0;for(n=1,o=(g=h[2]).length;n<o;++n)if(g[n]!==g[n-1]+1){x=!1;break}if(x){w+=A(g[0]-f&65535);k+=A(0)}else{var P=2*(p-r)+2*C;C+=d-f+1;w+=A(0);k+=A(P);for(n=0,o=g.length;n<o;++n)S+=A(g[n])}}if(m>0){y+="ÿÿ";b+="ÿÿ";w+="\0";k+="\0\0"}var I="\0\0"+A(2*p)+A(v.range)+A(v.entry)+A(v.rangeShift)+y+"\0\0"+b+w+k+S,O="",T="";if(c>1){l+="\0\0\n"+(0,i.string32)(4+8*c+4+I.length);O="";for(r=0,a=s.length;r<a;r++){f=(h=s[r])[0];var E=(g=h[2])[0];for(n=1,o=g.length;n<o;++n)if(g[n]!==g[n-1]+1){d=h[0]+n-1;O+=(0,i.string32)(f)+(0,i.string32)(d)+(0,i.string32)(E);f=d+1;E=g[n]}O+=(0,i.string32)(f)+(0,i.string32)(h[1])+(0,i.string32)(E)}T="\0\f\0\0"+(0,i.string32)(O.length+16)+"\0\0\0\0"+(0,i.string32)(O.length/12)}return l+"\0"+A(I.length+4)+I+T+O}function B(e,t,r){r=r||{unitsPerEm:0,yMax:0,yMin:0,ascent:0,descent:0};var a=0,n=0,o=0,s=0,c=null,u=0;if(t){for(var h in t){(c>(h|=0)||!c)&&(c=h);u<h&&(u=h);var f=(0,l.getUnicodeRangeFor)(h);if(f<32)a|=1<<f;else if(f<64)n|=1<<f-32;else if(f<96)o|=1<<f-64;else{if(!(f<123))throw new i.FormatError("Unicode ranges Bits > 123 are reserved for internal usage");s|=1<<f-96}}u>65535&&(u=65535)}else{c=0;u=255}var d=e.bbox||[0,0,0,0],g=r.unitsPerEm||1/(e.fontMatrix||i.FONT_IDENTITY_MATRIX)[0],p=e.ascentScaled?1:g/m,v=r.ascent||Math.round(p*(e.ascent||d[3])),b=r.descent||Math.round(p*(e.descent||d[1]));b>0&&e.descent>0&&d[1]<0&&(b=-b);var y=r.yMax||v,w=-r.yMin||-b;return"\0$ô\0\0\0Š»\0\0\0ÂŒŠ»\0\0ß\x001\0\0\0\0"+String.fromCharCode(e.fixedPitch?9:0)+"\0\0\0\0\0\0"+(0,i.string32)(a)+(0,i.string32)(n)+(0,i.string32)(o)+(0,i.string32)(s)+"*21*"+A(e.italicAngle?1:0)+A(c||e.firstChar)+A(u||e.lastChar)+A(v)+A(b)+"\0d"+A(y)+A(w)+"\0\0\0\0\0\0\0\0"+A(e.xHeight)+A(e.capHeight)+A(0)+A(c||e.firstChar)+"\0"}function D(e){var t=Math.floor(e.italicAngle*Math.pow(2,16));return"\0\0\0"+(0,i.string32)(t)+"\0\0\0\0"+(0,i.string32)(e.fixedPitch)+"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}function M(e,t){t||(t=[[],[]]);var r,a,i,n,o,s=[t[0][0]||"Original licence",t[0][1]||e,t[0][2]||"Unknown",t[0][3]||"uniqueID",t[0][4]||e,t[0][5]||"Version 0.11",t[0][6]||"",t[0][7]||"Unknown",t[0][8]||"Unknown",t[0][9]||"Unknown"],c=[];for(r=0,a=s.length;r<a;r++){var l=[];for(i=0,n=(o=t[1][r]||s[r]).length;i<n;i++)l.push(A(o.charCodeAt(i)));c.push(l.join(""))}var u=[s,c],h=["\0","\0"],f=["\0\0","\0"],d=["\0\0","\t"],g=s.length*h.length,m="\0\0"+A(g)+A(12*g+6),p=0;for(r=0,a=h.length;r<a;r++){var v=u[r];for(i=0,n=v.length;i<n;i++){o=v[i];m+=h[r]+f[r]+d[r]+A(i)+A(o.length)+A(p);p+=o.length}}return m+=s.join("")+c.join("")}e.prototype={name:null,font:null,mimetype:null,encoding:null,get renderer(){var e=u.FontRendererFactory.create(this,p);return(0,i.shadow)(this,"renderer",e)},exportData:function(){var e={};for(var t in this)this.hasOwnProperty(t)&&(e[t]=this[t]);return e},fallbackToSystemFont:function(){var e,t,r=this;this.missingFile=!0;var a=this.name,n=this.type,u=this.subtype,h=a.replace(/[,_]/g,"-"),f=(0,c.getStdFontMap)(),d=(0,c.getNonStdFontMap)(),g=!!f[h]||!(!d[h]||!f[d[h]]);h=f[h]||d[h]||h;this.bold=-1!==h.search(/bold/gi);this.italic=-1!==h.search(/oblique/gi)||-1!==h.search(/italic/gi);this.black=-1!==a.search(/Black/g);this.remeasure=Object.keys(this.widths).length>0;if(g&&"CIDFontType2"===n&&0===this.cidEncoding.indexOf("Identity-")){var m=(0,c.getGlyphMapForStandardFonts)(),p=[];for(e in m)p[+e]=m[e];if(/Arial-?Black/i.test(a)){var v=(0,c.getSupplementalGlyphMapForArialBlack)();for(e in v)p[+e]=v[e]}else if(/Calibri/i.test(a)){var b=(0,c.getSupplementalGlyphMapForCalibri)();for(e in b)p[+e]=b[e]}this.toUnicode instanceof x||this.toUnicode.forEach(function(e,t){p[+e]=t});this.toFontChar=p;this.toUnicode=new C(p)}else if(/Symbol/i.test(h))this.toFontChar=E(s.SymbolSetEncoding,(0,o.getGlyphsUnicode)(),this.differences);else if(/Dingbats/i.test(h)){/Wingdings/i.test(a)&&(0,i.warn)("Non-embedded Wingdings font, falling back to ZapfDingbats.");this.toFontChar=E(s.ZapfDingbatsEncoding,(0,o.getDingbatsGlyphsUnicode)(),this.differences)}else if(g)this.toFontChar=E(this.defaultEncoding,(0,o.getGlyphsUnicode)(),this.differences);else{var y=(0,o.getGlyphsUnicode)();this.toUnicode.forEach(function(e,a){if(!r.composite){var i=r.differences[e]||r.defaultEncoding[e];-1!==(t=(0,l.getUnicodeForGlyph)(i,y))&&(a=t)}r.toFontChar[e]=a})}this.loadedName=h.split("-")[0];this.fontType=w(n,u)},checkAndRepair:function(e,t,a){var c=["OS/2","cmap","head","hhea","hmtx","maxp","name","post","loca","glyf","fpgm","prep","cvt ","CFF "];function l(e,r){var a=Object.create(null);a["OS/2"]=null;a.cmap=null;a.head=null;a.hhea=null;a.hmtx=null;a.maxp=null;a.name=null;a.post=null;for(var i=0;i<r;i++){var n=u(t);c.includes(n.tag)&&(0!==n.length&&(a[n.tag]=n))}return a}function u(e){var t=(0,i.bytesToString)(e.getBytes(4)),r=e.getInt32()>>>0,a=e.getInt32()>>>0,n=e.getInt32()>>>0,o=e.pos;e.pos=e.start?e.start:0;e.skip(a);var s=e.getBytes(n);e.pos=o;if("head"===t){s[8]=s[9]=s[10]=s[11]=0;s[17]|=32}return{tag:t,checksum:r,length:n,offset:a,data:s}}function g(e){return{version:(0,i.bytesToString)(e.getBytes(4)),numTables:e.getUint16(),searchRange:e.getUint16(),entrySelector:e.getUint16(),rangeShift:e.getUint16()}}function m(e,t,r,a,i,n){var o={length:0,sizeOfInstructions:0};if(r-t<=12)return o;var s=e.subarray(t,r),c=d(s[0],s[1]);if(c<0){!function(e,t,r){e[t+1]=r;e[t]=r>>>8}(s,0,c=-1);a.set(s,i);o.length=s.length;return o}var l,u=10,h=0;for(l=0;l<c;l++){h=(s[u]<<8|s[u+1])+1;u+=2}var f=u,g=s[u]<<8|s[u+1];o.sizeOfInstructions=g;var m=u+=2+g,p=0;for(l=0;l<h;l++){var v=s[u++];192&v&&(s[u-1]=63&v);var b=(2&v?1:16&v?0:2)+(4&v?1:32&v?0:2);p+=b;if(8&v){var y=s[u++];l+=y;p+=y*b}}if(0===p)return o;var w=u+p;if(w>s.length)return o;if(!n&&g>0){a.set(s.subarray(0,f),i);a.set([0,0],i+f);a.set(s.subarray(m,w),i+f+2);w-=g;s.length-w>3&&(w=w+3&-4);o.length=w;return o}if(s.length-w>3){w=w+3&-4;a.set(s.subarray(0,w),i);o.length=w;return o}a.set(s,i);o.length=s.length;return o}function v(e){var r=(t.start?t.start:0)+e.offset;t.pos=r;var a=[[],[]],n=e.length,o=r+n;if(0!==t.getUint16()||n<6)return a;var s,c,l=t.getUint16(),u=t.getUint16(),h=[];for(s=0;s<l&&t.pos+12<=o;s++){var f={platform:t.getUint16(),encoding:t.getUint16(),language:t.getUint16(),name:t.getUint16(),length:t.getUint16(),offset:t.getUint16()};(1===f.platform&&0===f.encoding&&0===f.language||3===f.platform&&1===f.encoding&&1033===f.language)&&h.push(f)}for(s=0,c=h.length;s<c;s++){var d=h[s];if(!(d.length<=0)){var g=r+u+d.offset;if(!(g+d.length>o)){t.pos=g;var m=d.name;if(d.encoding){for(var p="",v=0,b=d.length;v<b;v+=2)p+=String.fromCharCode(t.getUint16());a[1][m]=p}else a[0][m]=(0,i.bytesToString)(t.getBytes(d.length))}}}return a}var w=[0,0,0,0,0,0,0,0,-2,-2,-2,-2,0,0,-2,-5,-1,-1,-1,-1,-1,-1,-1,-1,0,0,-1,0,-1,-1,-1,-1,1,-1,-999,0,1,0,-1,-2,0,-1,-2,-1,-1,0,-1,-1,0,0,-999,-999,-1,-1,-1,-1,-2,-999,-2,-2,-999,0,-2,-2,0,0,-2,0,-2,0,0,0,-2,-1,-1,1,1,0,0,-1,-1,-1,-1,-1,-1,-1,0,0,-1,0,-1,-1,0,-999,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,0,0,0,0,0,-2,-999,-999,-999,-999,-999,-1,-1,-2,-2,0,0,0,0,-1,-1,-999,-2,-2,0,0,-1,-2,-2,0,0,0,-1,-1,-1,-2];function S(e,t){for(var r,a,n,o,s,c=e.data,l=0,u=0,h=0,f=[],d=[],g=[],m=t.tooComplexToFollowFunctions,p=!1,v=0,b=0,y=c.length;l<y;){var k=c[l++];if(64===k){a=c[l++];if(p||b)l+=a;else for(r=0;r<a;r++)f.push(c[l++])}else if(65===k){a=c[l++];if(p||b)l+=2*a;else for(r=0;r<a;r++){n=c[l++];f.push(n<<8|c[l++])}}else if(176==(248&k)){a=k-176+1;if(p||b)l+=a;else for(r=0;r<a;r++)f.push(c[l++])}else if(184==(248&k)){a=k-184+1;if(p||b)l+=2*a;else for(r=0;r<a;r++){n=c[l++];f.push(n<<8|c[l++])}}else if(43!==k||m)if(44!==k||m){if(45===k)if(p){p=!1;u=l}else{if(!(s=d.pop())){(0,i.warn)("TT: ENDF bad stack");t.hintsValid=!1;return}o=g.pop();c=s.data;l=s.i;t.functionsStackDeltas[o]=f.length-s.stackTop}else if(137===k){if(p||b){(0,i.warn)("TT: nested IDEFs not allowed");m=!0}p=!0;h=l}else if(88===k)++v;else if(27===k)b=v;else if(89===k){b===v&&(b=0);--v}else if(28===k&&!p&&!b){var S=f[f.length-1];S>0&&(l+=S-1)}}else{if(p||b){(0,i.warn)("TT: nested FDEFs not allowed");m=!0}p=!0;h=l;o=f.pop();t.functionsDefined[o]={data:c,i:l}}else if(!p&&!b){o=f[f.length-1];if(isNaN(o))(0,i.info)("TT: CALL empty stack (or invalid entry).");else{t.functionsUsed[o]=!0;if(o in t.functionsStackDeltas){var C=f.length+t.functionsStackDeltas[o];if(C<0){(0,i.warn)("TT: CALL invalid functions stack delta.");t.hintsValid=!1;return}f.length=C}else if(o in t.functionsDefined&&!g.includes(o)){d.push({data:c,i:l,stackTop:f.length-1});g.push(o);if(!(s=t.functionsDefined[o])){(0,i.warn)("TT: CALL non-existent function");t.hintsValid=!1;return}c=s.data;l=s.i}}}if(!p&&!b){var x=k<=142?w[k]:k>=192&&k<=223?-1:k>=224?-2:0;if(k>=113&&k<=117){a=f.pop();isNaN(a)||(x=2*-a)}for(;x<0&&f.length>0;){f.pop();x++}for(;x>0;){f.push(NaN);x--}}}t.tooComplexToFollowFunctions=m;var _=[c];l>c.length&&_.push(new Uint8Array(l-c.length));if(h>u){(0,i.warn)("TT: complementing a missing function tail");_.push(new Uint8Array([34,45]))}!function(e,t){if(t.length>1){var r,a,i=0;for(r=0,a=t.length;r<a;r++)i+=t[r].length;i=i+3&-4;var n=new Uint8Array(i),o=0;for(r=0,a=t.length;r<a;r++){n.set(t[r],o);o+=t[r].length}e.data=n;e.length=i}}(e,_)}var C=void 0,x=void 0;if(I(t=new f.Stream(new Uint8Array(t.getBytes())))){var A=function(e,t){for(var r=function(e){var t=(0,i.bytesToString)(e.getBytes(4));(0,i.assert)("ttcf"===t,"Must be a TrueType Collection font.");for(var r=e.getUint16(),a=e.getUint16(),n=e.getInt32()>>>0,o=[],s=0;s<n;s++)o.push(e.getInt32()>>>0);var c={ttcTag:t,majorVersion:r,minorVersion:a,numFonts:n,offsetTable:o};switch(r){case 1:return c;case 2:c.dsigTag=e.getInt32()>>>0;c.dsigLength=e.getInt32()>>>0;c.dsigOffset=e.getInt32()>>>0;return c}throw new i.FormatError("Invalid TrueType Collection majorVersion: "+r+".")}(e),a=r.numFonts,n=r.offsetTable,o=0;o<a;o++){e.pos=(e.start||0)+n[o];var s=g(e),c=l(0,s.numTables);if(!c.name)throw new i.FormatError('TrueType Collection font must contain a "name" table.');for(var u=v(c.name),h=0,f=u.length;h<f;h++)for(var d=0,m=u[h].length;d<m;d++){var p=u[h][d];if(p&&p.replace(/\s/g,"")===t)return{header:s,tables:c}}}throw new i.FormatError('TrueType Collection does not contain "'+t+'" font.')}(t,this.name);C=A.header;x=A.tables}else x=l(0,(C=g(t)).numTables);var P=void 0,O=void 0,E=!x["CFF "];if(E){if(!x.loca)throw new i.FormatError('Required "loca" table is not found');if(!x.glyf){(0,i.warn)('Required "glyf" table is not found -- trying to recover.');x.glyf={tag:"glyf",data:new Uint8Array(0)}}this.isOpenType=!1}else{var L=a.composite&&((a.cidToGidMap||[]).length>0||!(a.cMap instanceof h.IdentityCMap));if("OTTO"===C.version&&!L||!x.head||!x.hhea||!x.maxp||!x.post){O=new f.Stream(x["CFF "].data);P=new T(O,a);y(a);return this.convert(e,P,a)}delete x.glyf;delete x.loca;delete x.fpgm;delete x.prep;delete x["cvt "];this.isOpenType=!0}if(!x.maxp)throw new i.FormatError('Required "maxp" table is not found');t.pos=(t.start||0)+x.maxp.offset;var N=t.getInt32(),U=t.getUint16(),q=U+1,j=!0;if(q>65535){j=!1;q=U;(0,i.warn)("Not enough space in glyfs to duplicate first glyph.")}var z=0,H=0;if(N>=65536&&x.maxp.length>=22){t.pos+=8;if(t.getUint16()>2){x.maxp.data[14]=0;x.maxp.data[15]=2}t.pos+=4;z=t.getUint16();t.pos+=4;H=t.getUint16()}x.maxp.data[4]=q>>8;x.maxp.data[5]=255&q;var G=function(e,t,r,a){var n={functionsDefined:[],functionsUsed:[],functionsStackDeltas:[],tooComplexToFollowFunctions:!1,hintsValid:!0};e&&S(e,n);t&&S(t,n);e&&function(e,t){if(!e.tooComplexToFollowFunctions)if(e.functionsDefined.length>t){(0,i.warn)("TT: more functions defined than expected");e.hintsValid=!1}else for(var r=0,a=e.functionsUsed.length;r<a;r++){if(r>t){(0,i.warn)("TT: invalid function id: "+r);e.hintsValid=!1;return}if(e.functionsUsed[r]&&!e.functionsDefined[r]){(0,i.warn)("TT: undefined function: "+r);e.hintsValid=!1;return}}}(n,a);if(r&&1&r.length){var o=new Uint8Array(r.length+1);o.set(r.data);r.data=o}return n.hintsValid}(x.fpgm,x.prep,x["cvt "],z);if(!G){delete x.fpgm;delete x.prep;delete x["cvt "]}!function(e,t,r,a){if(t){e.pos=(e.start?e.start:0)+t.offset;e.pos+=t.length-2;var n=e.getUint16();if(n>a){(0,i.info)("The numOfMetrics ("+n+") should not be greater than the numGlyphs ("+a+")");n=a;t.data[34]=(65280&n)>>8;t.data[35]=255&n}var o=a-n-(r.length-4*n>>1);if(o>0){var s=new Uint8Array(r.length+2*o);s.set(r.data);r.data=s}}else r&&(r.data=null)}(t,x.hhea,x.hmtx,q);if(!x.head)throw new i.FormatError('Required "head" table is not found');!function(e,t,a){var n,o,s,c,l=e.data,u=(n=l[0],o=l[1],s=l[2],c=l[3],(n<<24)+(o<<16)+(s<<8)+c);if(u>>16!=1){(0,i.info)("Attempting to fix invalid version in head table: "+u);l[0]=0;l[1]=1;l[2]=0;l[3]=0}var h=r(l[50],l[51]);if(h<0||h>1){(0,i.info)("Attempting to fix invalid indexToLocFormat in head table: "+h);var f=t+1;if(a===f<<1){l[50]=0;l[51]=0}else{if(a!==f<<2)throw new i.FormatError("Could not fix indexToLocFormat: "+h);l[50]=0;l[51]=1}}}(x.head,U,E?x.loca.length:0);var W=Object.create(null);if(E){var X=r(x.head.data[50],x.head.data[51]),V=function(e,t,r,a,i,n,o){var s,c,l;if(a){s=4;c=function(e,t){return e[t]<<24|e[t+1]<<16|e[t+2]<<8|e[t+3]};l=function(e,t,r){e[t]=r>>>24&255;e[t+1]=r>>16&255;e[t+2]=r>>8&255;e[t+3]=255&r}}else{s=2;c=function(e,t){return e[t]<<9|e[t+1]<<1};l=function(e,t,r){e[t]=r>>9&255;e[t+1]=r>>1&255}}var u=n?r+1:r,h=e.data,f=s*(1+u);(h=new Uint8Array(f)).set(e.data.subarray(0,f));e.data=h;var d,g,p=t.data,v=p.length,b=new Uint8Array(v),y=c(h,0),w=0,k=Object.create(null);l(h,0,w);for(d=0,g=s;d<r;d++,g+=s){var S=c(h,g);0===S&&(S=y);S>v&&(v+3&-4)===S&&(S=v);S>v&&(y=S);var C=m(p,y,S,b,w,i),x=C.length;0===x&&(k[d]=!0);C.sizeOfInstructions>o&&(o=C.sizeOfInstructions);l(h,g,w+=x);y=S}if(0===w){var _=new Uint8Array([0,1,0,0,0,0,0,0,0,0,0,0,0,0,49,0]);for(d=0,g=s;d<u;d++,g+=s)l(h,g,_.length);t.data=_}else if(n){var A=c(h,s);if(b.length>A+w)t.data=b.subarray(0,A+w);else{t.data=new Uint8Array(A+w);t.data.set(b.subarray(0,w))}t.data.set(b.subarray(0,A),w);l(e.data,h.length-s,w+A)}else t.data=b.subarray(0,w);return{missingGlyphs:k,maxSizeOfInstructions:o}}(x.loca,x.glyf,U,X,G,j,H);W=V.missingGlyphs;if(N>=65536&&x.maxp.length>=22){x.maxp.data[26]=V.maxSizeOfInstructions>>8;x.maxp.data[27]=255&V.maxSizeOfInstructions}}if(!x.hhea)throw new i.FormatError('Required "hhea" table is not found');if(0===x.hhea.data[10]&&0===x.hhea.data[11]){x.hhea.data[10]=255;x.hhea.data[11]=255}var K={unitsPerEm:r(x.head.data[18],x.head.data[19]),yMax:r(x.head.data[42],x.head.data[43]),yMin:d(x.head.data[38],x.head.data[39]),ascent:r(x.hhea.data[4],x.hhea.data[5]),descent:d(x.hhea.data[6],x.hhea.data[7])};this.ascent=K.ascent/K.unitsPerEm;this.descent=K.descent/K.unitsPerEm;x.post&&function(e,r,a){var n=(t.start?t.start:0)+e.offset;t.pos=n;var o,s=n+e.length,c=t.getInt32();t.getBytes(28);var l,u=!0;switch(c){case 65536:o=b;break;case 131072:var h=t.getUint16();if(h!==a){u=!1;break}var f=[];for(l=0;l<h;++l){var d=t.getUint16();if(d>=32768){u=!1;break}f.push(d)}if(!u)break;for(var g=[],m=[];t.pos<s;){var p=t.getByte();m.length=p;for(l=0;l<p;++l)m[l]=String.fromCharCode(t.getByte());g.push(m.join(""))}o=[];for(l=0;l<h;++l){var v=f[l];v<258?o.push(b[v]):o.push(g[v-258])}break;case 196608:break;default:(0,i.warn)("Unknown/unsupported post table version "+c);u=!1;r.defaultEncoding&&(o=r.defaultEncoding)}r.glyphNames=o}(x.post,a,U);x.post={tag:"post",data:D(a)};var Y,J=[];function Z(e){return!W[e]}if(a.composite){var Q=a.cidToGidMap||[],$=0===Q.length;a.cMap.forEach(function(e,t){if(t>65535)throw new i.FormatError("Max size of CID is 65,535");var r=-1;$?r=t:void 0!==Q[t]&&(r=Q[t]);r>=0&&r<U&&Z(r)&&(J[e]=r)})}else{var ee=function(e,t,r,a){if(!e){(0,i.warn)("No cmap table available.");return{platformId:-1,encodingId:-1,mappings:[],hasShortCmap:!1}}var n,o=(t.start?t.start:0)+e.offset;t.pos=o;t.getUint16();for(var s,c=t.getUint16(),l=!1,u=0;u<c;u++){var h=t.getUint16(),f=t.getUint16(),d=t.getInt32()>>>0,g=!1;if(!s||s.platformId!==h||s.encodingId!==f){if(0===h&&0===f)g=!0;else if(1===h&&0===f)g=!0;else if(3!==h||1!==f||!a&&s){if(r&&3===h&&0===f){g=!0;l=!0}}else{g=!0;r||(l=!0)}g&&(s={platformId:h,encodingId:f,offset:d});if(l)break}}s&&(t.pos=o+s.offset);if(!s||-1===t.peekByte()){(0,i.warn)("Could not find a preferred cmap table.");return{platformId:-1,encodingId:-1,mappings:[],hasShortCmap:!1}}var m=t.getUint16();t.getUint16();t.getUint16();var p,v,b=!1,y=[];if(0===m){for(p=0;p<256;p++){var w=t.getByte();w&&y.push({charCode:p,glyphId:w})}b=!0}else if(4===m){var k=t.getUint16()>>1;t.getBytes(6);var S,C=[];for(S=0;S<k;S++)C.push({end:t.getUint16()});t.getUint16();for(S=0;S<k;S++)C[S].start=t.getUint16();for(S=0;S<k;S++)C[S].delta=t.getUint16();var x=0;for(S=0;S<k;S++){n=C[S];var _=t.getUint16();if(_){var A=(_>>1)-(k-S);n.offsetIndex=A;x=Math.max(x,A+n.end-n.start+1)}else n.offsetIndex=-1}var P=[];for(p=0;p<x;p++)P.push(t.getUint16());for(S=0;S<k;S++){o=(n=C[S]).start;var I=n.end,O=n.delta;A=n.offsetIndex;for(p=o;p<=I;p++)if(65535!==p){v=(v=A<0?p:P[A+p-o])+O&65535;y.push({charCode:p,glyphId:v})}}}else{if(6!==m){(0,i.warn)("cmap table has unsupported format: "+m);return{platformId:-1,encodingId:-1,mappings:[],hasShortCmap:!1}}var T=t.getUint16(),E=t.getUint16();for(p=0;p<E;p++){v=t.getUint16();var F=T+p;y.push({charCode:F,glyphId:v})}}y.sort(function(e,t){return e.charCode-t.charCode});for(u=1;u<y.length;u++)if(y[u-1].charCode===y[u].charCode){y.splice(u,1);u--}return{platformId:s.platformId,encodingId:s.encodingId,mappings:y,hasShortCmap:b}}(x.cmap,t,this.isSymbolicFont,a.hasEncoding),te=ee.platformId,re=ee.encodingId,ae=ee.mappings,ie=ae.length;if(a.hasEncoding&&(3===te&&1===re||1===te&&0===re)||-1===te&&-1===re&&(0,s.getEncoding)(a.baseEncodingName)){var ne=[];"MacRomanEncoding"!==a.baseEncodingName&&"WinAnsiEncoding"!==a.baseEncodingName||(ne=(0,s.getEncoding)(a.baseEncodingName));var oe=(0,o.getGlyphsUnicode)();for(Y=0;Y<256;Y++){var se,ce;if(se=this.differences&&Y in this.differences?this.differences[Y]:Y in ne&&""!==ne[Y]?ne[Y]:s.StandardEncoding[Y]){ce=k(se,oe);var le;3===te&&1===re?le=oe[ce]:1===te&&0===re&&(le=s.MacRomanEncoding.indexOf(ce));for(var ue=!1,he=0;he<ie;++he)if(ae[he].charCode===le){J[Y]=ae[he].glyphId;ue=!0;break}if(!ue&&a.glyphNames){var fe=a.glyphNames.indexOf(se);-1===fe&&ce!==se&&(fe=a.glyphNames.indexOf(ce));fe>0&&Z(fe)&&(J[Y]=fe)}}}}else if(0===te&&0===re)for(var de=0;de<ie;++de)J[ae[de].charCode]=ae[de].glyphId;else for(var ge=0;ge<ie;++ge){Y=ae[ge].charCode;3===te&&Y>=61440&&Y<=61695&&(Y&=255);J[Y]=ae[ge].glyphId}}0===J.length&&(J[0]=0);var me=q-1;j||(me=0);var pe=F(J,Z,me);this.toFontChar=pe.toFontChar;x.cmap={tag:"cmap",data:R(pe.charCodeToGlyphId,q)};x["OS/2"]&&function(e){var t=new f.Stream(e.data),r=t.getUint16();t.getBytes(60);var a=t.getUint16();if(r<4&&768&a)return!1;if(t.getUint16()>t.getUint16())return!1;t.getBytes(6);if(0===t.getUint16())return!1;e.data[8]=e.data[9]=0;return!0}(x["OS/2"])||(x["OS/2"]={tag:"OS/2",data:B(a,pe.charCodeToGlyphId,K)});if(!E)try{O=new f.Stream(x["CFF "].data);(P=new n.CFFParser(O,a,p).parse()).duplicateFirstGlyph();var ve=new n.CFFCompiler(P);x["CFF "].data=ve.compile()}catch(e){(0,i.warn)("Failed to compile font "+a.loadedName)}if(x.name){var be=v(x.name);x.name.data=M(e,be)}else x.name={tag:"name",data:M(this.name)};var ye=new _(C.version);for(var we in x)ye.addTable(we,x[we].data);return ye.toArray()},convert:function(e,t,r){r.fixedPitch=!1;r.builtInEncoding&&function(e,t){if(!e.hasIncludedToUnicodeMap&&!(e.hasEncoding||t===e.defaultEncoding||e.toUnicode instanceof x)){var r=[],a=(0,o.getGlyphsUnicode)();for(var i in t){var n=t[i],s=(0,l.getUnicodeForGlyph)(n,a);-1!==s&&(r[i]=String.fromCharCode(s))}e.toUnicode.amend(r)}}(r,r.builtInEncoding);var a=1;t instanceof T&&(a=t.numGlyphs-1);var n=t.getGlyphMapping(r),c=F(n,t.hasGlyphId.bind(t),a);this.toFontChar=c.toFontChar;var u=t.numGlyphs;function h(e,t){var r=null;for(var a in e)if(t===e[a]){r||(r=[]);r.push(0|a)}return r}function f(e,t){for(var r in e)if(t===e[r])return 0|r;c.charCodeToGlyphId[c.nextAvailableFontCharCode]=t;return c.nextAvailableFontCharCode++}var d=t.seacs;if(p&&d&&d.length){var g=r.fontMatrix||i.FONT_IDENTITY_MATRIX,m=t.getCharset(),v=Object.create(null);for(var b in d){var y=d[b|=0],w=s.StandardEncoding[y[2]],k=s.StandardEncoding[y[3]],S=m.indexOf(w),C=m.indexOf(k);if(!(S<0||C<0)){var I={x:y[0]*g[0]+y[1]*g[2]+g[4],y:y[0]*g[1]+y[1]*g[3]+g[5]},O=h(n,b);if(O)for(var E=0,L=O.length;E<L;E++){var N=O[E],U=c.charCodeToGlyphId,q=f(U,S),j=f(U,C);v[N]={baseFontCharCode:q,accentFontCharCode:j,accentOffset:I}}}}r.seacMap=v}var z=1/(r.fontMatrix||i.FONT_IDENTITY_MATRIX)[0],H=new _("OTTO");H.addTable("CFF ",t.data);H.addTable("OS/2",B(r,c.charCodeToGlyphId));H.addTable("cmap",R(c.charCodeToGlyphId,u));H.addTable("head","\0\0\0\0\0\0\0\0\0\0_<õ\0\0"+P(z)+"\0\0\0\0ž\v~'\0\0\0\0ž\v~'\0\0"+P(r.descent)+"ÿ"+P(r.ascent)+A(r.italicAngle?2:0)+"\0\0\0\0\0\0\0");H.addTable("hhea","\0\0\0"+P(r.ascent)+P(r.descent)+"\0\0ÿÿ\0\0\0\0\0\0"+P(r.capHeight)+P(Math.tan(r.italicAngle)*r.xHeight)+"\0\0\0\0\0\0\0\0\0\0\0\0"+A(u));H.addTable("hmtx",function(){for(var e=t.charstrings,r=t.cff?t.cff.widths:null,a="\0\0\0\0",i=1,n=u;i<n;i++){var o=0;if(e){var s=e[i-1];o="width"in s?s.width:0}else r&&(o=Math.ceil(r[i]||0));a+=A(o)+A(0)}return a}());H.addTable("maxp","\0\0P\0"+A(u));H.addTable("name",M(e));H.addTable("post",D(r));return H.toArray()},get spaceWidth(){if("_shadowWidth"in this)return this._shadowWidth;for(var e,t=["space","minus","one","i","I"],r=0,a=t.length;r<a;r++){var i=t[r];if(i in this.widths){e=this.widths[i];break}var n=(0,o.getGlyphsUnicode)()[i],s=0;this.composite&&this.cMap.contains(n)&&(s=this.cMap.lookup(n));!s&&this.toUnicode&&(s=this.toUnicode.charCodeOf(n));s<=0&&(s=n);if(e=this.widths[s])break}e=e||this.defaultWidth;this._shadowWidth=e;return e},charToGlyph:function(e,t){var r,a,n,o=e;this.cMap&&this.cMap.contains(e)&&(o=this.cMap.lookup(e));a=this.widths[o];a=(0,i.isNum)(a)?a:this.defaultWidth;var s=this.vmetrics&&this.vmetrics[o],c=this.toUnicode.get(e)||this.fallbackToUnicode.get(e)||e;"number"==typeof c&&(c=String.fromCharCode(c));var u=e in this.toFontChar;r=this.toFontChar[e]||e;this.missingFile&&(r=(0,l.mapSpecialUnicodeValues)(r));this.isType3Font&&(n=r);var h=null;if(this.seacMap&&this.seacMap[e]){u=!0;var f=this.seacMap[e];r=f.baseFontCharCode;h={fontChar:String.fromCodePoint(f.accentFontCharCode),offset:f.accentOffset}}var d="number"==typeof r?String.fromCodePoint(r):"",g=this.glyphCache[e];if(!g||!g.matchesForCache(d,c,h,a,s,n,t,u)){g=new S(d,c,h,a,s,n,t,u);this.glyphCache[e]=g}return g},charsToGlyphs:function(e){var t,r,a,i=this.charsCache;if(i&&(t=i[e]))return t;i||(i=this.charsCache=Object.create(null));t=[];var n,o=e,s=0;if(this.cMap)for(var c=Object.create(null);s<e.length;){this.cMap.readCharCode(e,s,c);a=c.charcode;var l=c.length;s+=l;var u=1===l&&32===e.charCodeAt(s-1);r=this.charToGlyph(a,u);t.push(r)}else for(s=0,n=e.length;s<n;++s){a=e.charCodeAt(s);r=this.charToGlyph(a,32===a);t.push(r)}return i[o]=t}};return e}(),P=function(){function e(e){this.error=e;this.loadedName="g_font_error";this.missingFile=!0}e.prototype={charsToGlyphs:function(){return[]},exportData:function(){return{error:this.error}}};return e}();function I(e,t,r){var a,i,n,c=Object.create(null),l=!!(e.flags&v.Symbolic);if(e.baseEncodingName){n=(0,s.getEncoding)(e.baseEncodingName);for(i=0;i<n.length;i++){a=r.indexOf(n[i]);c[i]=a>=0?a:0}}else if(l)for(i in t)c[i]=t[i];else{n=s.StandardEncoding;for(i=0;i<n.length;i++){a=r.indexOf(n[i]);c[i]=a>=0?a:0}}var u,h=e.differences;if(h)for(i in h){var f=h[i];if(-1===(a=r.indexOf(f))){u||(u=(0,o.getGlyphsUnicode)());var d=k(f,u);d!==f&&(a=r.indexOf(d))}c[i]=a>=0?a:0}return c}var O=function(){function e(e,t,r){for(var a,n=e.length,o=t.length,s=n-o,c=r,l=!1;c<s;){a=0;for(;a<o&&e[c+a]===t[a];)a++;if(a>=o){c+=a;for(;c<n&&(0,i.isSpace)(e[c]);)c++;l=!0;break}c++}return{found:l,length:c}}function t(t,r,a){var n=a.length1,o=(a.length2,r.peekBytes(6)),s=128===o[0]&&1===o[1];if(s){r.skip(6);n=o[5]<<24|o[4]<<16|o[3]<<8|o[2]}var c=function(t,r){var a,n,o,s,c=[101,101,120,101,99],l=t.pos;try{n=(a=t.getBytes(r)).length}catch(e){if(e instanceof i.MissingDataException)throw e}if(n===r&&(o=e(a,c,r-2*c.length)).found&&o.length===r)return{stream:new f.Stream(a),length:r};(0,i.warn)('Invalid "Length1" property in Type1 font -- trying to recover.');t.pos=l;for(;0!==(o=e(t.peekBytes(2048),c,0)).length;){t.pos+=o.length;if(o.found){s=t.pos-l;break}}t.pos=l;if(s)return{stream:new f.Stream(t.getBytes(s)),length:s};(0,i.warn)('Unable to recover "Length1" property in Type1 font -- using as is.');return{stream:new f.Stream(t.getBytes(r)),length:r}}(r,n);new d.Type1Parser(c.stream,!1,p).extractFontHeader(a);s&&(o=r.getBytes(6))[5]<<24|o[4]<<16|o[3]<<8|o[2];var l,u=(l=r.getBytes(),{stream:new f.Stream(l),length:l.length}),h=new d.Type1Parser(u.stream,!0,p).extractFontProgram();for(var g in h.properties)a[g]=h.properties[g];var m=h.charstrings,v=this.getType2Charstrings(m),b=this.getType2Subrs(h.subrs);this.charstrings=m;this.data=this.wrap(t,v,this.charstrings,b,a);this.seacs=this.getSeacs(h.charstrings)}t.prototype={get numGlyphs(){return this.charstrings.length+1},getCharset:function(){for(var e=[".notdef"],t=this.charstrings,r=0;r<t.length;r++)e.push(t[r].glyphName);return e},getGlyphMapping:function(e){var t,r=this.charstrings,a=[".notdef"];for(t=0;t<r.length;t++)a.push(r[t].glyphName);var i=e.builtInEncoding;if(i){var n=Object.create(null);for(var o in i)(t=a.indexOf(i[o]))>=0&&(n[o]=t)}return I(e,n,a)},hasGlyphId:function(e){return!(e<0||e>=this.numGlyphs)&&(0===e||this.charstrings[e-1].charstring.length>0)},getSeacs:function(e){var t,r,a=[];for(t=0,r=e.length;t<r;t++){var i=e[t];i.seac&&(a[t+1]=i.seac)}return a},getType2Charstrings:function(e){for(var t=[],r=0,a=e.length;r<a;r++)t.push(e[r].charstring);return t},getType2Subrs:function(e){var t=0,r=e.length;t=r<1133?107:r<33769?1131:32768;var a,i=[];for(a=0;a<t;a++)i.push([11]);for(a=0;a<r;a++)i.push(e[a]);return i},wrap:function(e,t,r,a,i){var o=new n.CFF;o.header=new n.CFFHeader(1,0,4,4);o.names=[e];var s=new n.CFFTopDict;s.setByName("version",391);s.setByName("Notice",392);s.setByName("FullName",393);s.setByName("FamilyName",394);s.setByName("Weight",395);s.setByName("Encoding",null);s.setByName("FontMatrix",i.fontMatrix);s.setByName("FontBBox",i.bbox);s.setByName("charset",null);s.setByName("CharStrings",null);s.setByName("Private",null);o.topDict=s;var c=new n.CFFStrings;c.add("Version 0.11");c.add("See original notice");c.add(e);c.add(e);c.add("Medium");o.strings=c;o.globalSubrIndex=new n.CFFIndex;var l,u,h=t.length,f=[0];for(l=0;l<h;l++){var d=n.CFFStandardStrings.indexOf(r[l].glyphName);-1===d&&(d=0);f.push(d>>8&255,255&d)}o.charset=new n.CFFCharset(!1,0,[],f);var g=new n.CFFIndex;g.add([139,14]);for(l=0;l<h;l++)g.add(t[l]);o.charStrings=g;var m=new n.CFFPrivateDict;m.setByName("Subrs",null);var p=["BlueValues","OtherBlues","FamilyBlues","FamilyOtherBlues","StemSnapH","StemSnapV","BlueShift","BlueFuzz","BlueScale","LanguageGroup","ExpansionFactor","ForceBold","StdHW","StdVW"];for(l=0,u=p.length;l<u;l++){var v=p[l];if(v in i.privateData){var b=i.privateData[v];if(Array.isArray(b))for(var y=b.length-1;y>0;y--)b[y]-=b[y-1];m.setByName(v,b)}}o.topDict.privateDict=m;var w=new n.CFFIndex;for(l=0,u=a.length;l<u;l++)w.add(a[l]);m.subrsIndex=w;return new n.CFFCompiler(o).compile()}};return t}(),T=function(){function e(e,t){this.properties=t;var r=new n.CFFParser(e,t,p);this.cff=r.parse();this.cff.duplicateFirstGlyph();var a=new n.CFFCompiler(this.cff);this.seacs=this.cff.seacs;try{this.data=a.compile()}catch(r){(0,i.warn)("Failed to compile font "+t.loadedName);this.data=e}}e.prototype={get numGlyphs(){return this.cff.charStrings.count},getCharset:function(){return this.cff.charset.charset},getGlyphMapping:function(){var e,t,r=this.cff,a=this.properties,i=r.charset.charset;if(a.composite){e=Object.create(null);if(r.isCIDFont)for(t=0;t<i.length;t++){var n=i[t];e[a.cMap.charCodeOf(n)]=t}else for(t=0;t<r.charStrings.count;t++)e[t]=t;return e}return e=I(a,r.encoding?r.encoding.encoding:null,i)},hasGlyphId:function(e){return this.cff.hasGlyphId(e)}};return e}();t.SEAC_ANALYSIS_ENABLED=p;t.ErrorFont=P;t.Font=A;t.FontFlags=v;t.ToUnicodeMap=C;t.IdentityToUnicodeMap=x;t.getFontType=w},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.CFFFDSelect=t.CFFCompiler=t.CFFPrivateDict=t.CFFTopDict=t.CFFCharset=t.CFFIndex=t.CFFStrings=t.CFFHeader=t.CFF=t.CFFParser=t.CFFStandardStrings=void 0;var a=r(2),i=r(158),n=r(159),o=[".notdef","space","exclam","quotedbl","numbersign","dollar","percent","ampersand","quoteright","parenleft","parenright","asterisk","plus","comma","hyphen","period","slash","zero","one","two","three","four","five","six","seven","eight","nine","colon","semicolon","less","equal","greater","question","at","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","bracketleft","backslash","bracketright","asciicircum","underscore","quoteleft","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde","exclamdown","cent","sterling","fraction","yen","florin","section","currency","quotesingle","quotedblleft","guillemotleft","guilsinglleft","guilsinglright","fi","fl","endash","dagger","daggerdbl","periodcentered","paragraph","bullet","quotesinglbase","quotedblbase","quotedblright","guillemotright","ellipsis","perthousand","questiondown","grave","acute","circumflex","tilde","macron","breve","dotaccent","dieresis","ring","cedilla","hungarumlaut","ogonek","caron","emdash","AE","ordfeminine","Lslash","Oslash","OE","ordmasculine","ae","dotlessi","lslash","oslash","oe","germandbls","onesuperior","logicalnot","mu","trademark","Eth","onehalf","plusminus","Thorn","onequarter","divide","brokenbar","degree","thorn","threequarters","twosuperior","registered","minus","eth","multiply","threesuperior","copyright","Aacute","Acircumflex","Adieresis","Agrave","Aring","Atilde","Ccedilla","Eacute","Ecircumflex","Edieresis","Egrave","Iacute","Icircumflex","Idieresis","Igrave","Ntilde","Oacute","Ocircumflex","Odieresis","Ograve","Otilde","Scaron","Uacute","Ucircumflex","Udieresis","Ugrave","Yacute","Ydieresis","Zcaron","aacute","acircumflex","adieresis","agrave","aring","atilde","ccedilla","eacute","ecircumflex","edieresis","egrave","iacute","icircumflex","idieresis","igrave","ntilde","oacute","ocircumflex","odieresis","ograve","otilde","scaron","uacute","ucircumflex","udieresis","ugrave","yacute","ydieresis","zcaron","exclamsmall","Hungarumlautsmall","dollaroldstyle","dollarsuperior","ampersandsmall","Acutesmall","parenleftsuperior","parenrightsuperior","twodotenleader","onedotenleader","zerooldstyle","oneoldstyle","twooldstyle","threeoldstyle","fouroldstyle","fiveoldstyle","sixoldstyle","sevenoldstyle","eightoldstyle","nineoldstyle","commasuperior","threequartersemdash","periodsuperior","questionsmall","asuperior","bsuperior","centsuperior","dsuperior","esuperior","isuperior","lsuperior","msuperior","nsuperior","osuperior","rsuperior","ssuperior","tsuperior","ff","ffi","ffl","parenleftinferior","parenrightinferior","Circumflexsmall","hyphensuperior","Gravesmall","Asmall","Bsmall","Csmall","Dsmall","Esmall","Fsmall","Gsmall","Hsmall","Ismall","Jsmall","Ksmall","Lsmall","Msmall","Nsmall","Osmall","Psmall","Qsmall","Rsmall","Ssmall","Tsmall","Usmall","Vsmall","Wsmall","Xsmall","Ysmall","Zsmall","colonmonetary","onefitted","rupiah","Tildesmall","exclamdownsmall","centoldstyle","Lslashsmall","Scaronsmall","Zcaronsmall","Dieresissmall","Brevesmall","Caronsmall","Dotaccentsmall","Macronsmall","figuredash","hypheninferior","Ogoneksmall","Ringsmall","Cedillasmall","questiondownsmall","oneeighth","threeeighths","fiveeighths","seveneighths","onethird","twothirds","zerosuperior","foursuperior","fivesuperior","sixsuperior","sevensuperior","eightsuperior","ninesuperior","zeroinferior","oneinferior","twoinferior","threeinferior","fourinferior","fiveinferior","sixinferior","seveninferior","eightinferior","nineinferior","centinferior","dollarinferior","periodinferior","commainferior","Agravesmall","Aacutesmall","Acircumflexsmall","Atildesmall","Adieresissmall","Aringsmall","AEsmall","Ccedillasmall","Egravesmall","Eacutesmall","Ecircumflexsmall","Edieresissmall","Igravesmall","Iacutesmall","Icircumflexsmall","Idieresissmall","Ethsmall","Ntildesmall","Ogravesmall","Oacutesmall","Ocircumflexsmall","Otildesmall","Odieresissmall","OEsmall","Oslashsmall","Ugravesmall","Uacutesmall","Ucircumflexsmall","Udieresissmall","Yacutesmall","Thornsmall","Ydieresissmall","001.000","001.001","001.002","001.003","Black","Bold","Book","Light","Medium","Regular","Roman","Semibold"],s=function(){var e=[null,{id:"hstem",min:2,stackClearing:!0,stem:!0},null,{id:"vstem",min:2,stackClearing:!0,stem:!0},{id:"vmoveto",min:1,stackClearing:!0},{id:"rlineto",min:2,resetStack:!0},{id:"hlineto",min:1,resetStack:!0},{id:"vlineto",min:1,resetStack:!0},{id:"rrcurveto",min:6,resetStack:!0},null,{id:"callsubr",min:1,undefStack:!0},{id:"return",min:0,undefStack:!0},null,null,{id:"endchar",min:0,stackClearing:!0},null,null,null,{id:"hstemhm",min:2,stackClearing:!0,stem:!0},{id:"hintmask",min:0,stackClearing:!0},{id:"cntrmask",min:0,stackClearing:!0},{id:"rmoveto",min:2,stackClearing:!0},{id:"hmoveto",min:1,stackClearing:!0},{id:"vstemhm",min:2,stackClearing:!0,stem:!0},{id:"rcurveline",min:8,resetStack:!0},{id:"rlinecurve",min:8,resetStack:!0},{id:"vvcurveto",min:4,resetStack:!0},{id:"hhcurveto",min:4,resetStack:!0},null,{id:"callgsubr",min:1,undefStack:!0},{id:"vhcurveto",min:4,resetStack:!0},{id:"hvcurveto",min:4,resetStack:!0}],t=[null,null,null,{id:"and",min:2,stackDelta:-1},{id:"or",min:2,stackDelta:-1},{id:"not",min:1,stackDelta:0},null,null,null,{id:"abs",min:1,stackDelta:0},{id:"add",min:2,stackDelta:-1,stackFn:function(e,t){e[t-2]=e[t-2]+e[t-1]}},{id:"sub",min:2,stackDelta:-1,stackFn:function(e,t){e[t-2]=e[t-2]-e[t-1]}},{id:"div",min:2,stackDelta:-1,stackFn:function(e,t){e[t-2]=e[t-2]/e[t-1]}},null,{id:"neg",min:1,stackDelta:0,stackFn:function(e,t){e[t-1]=-e[t-1]}},{id:"eq",min:2,stackDelta:-1},null,null,{id:"drop",min:1,stackDelta:-1},null,{id:"put",min:2,stackDelta:-2},{id:"get",min:1,stackDelta:0},{id:"ifelse",min:4,stackDelta:-3},{id:"random",min:0,stackDelta:1},{id:"mul",min:2,stackDelta:-1,stackFn:function(e,t){e[t-2]=e[t-2]*e[t-1]}},null,{id:"sqrt",min:1,stackDelta:0},{id:"dup",min:1,stackDelta:1},{id:"exch",min:2,stackDelta:0},{id:"index",min:2,stackDelta:0},{id:"roll",min:3,stackDelta:-2},null,null,null,{id:"hflex",min:7,resetStack:!0},{id:"flex",min:13,resetStack:!0},{id:"hflex1",min:9,resetStack:!0},{id:"flex1",min:11,resetStack:!0}];function r(e,t,r){this.bytes=e.getBytes();this.properties=t;this.seacAnalysisEnabled=!!r}r.prototype={parse:function(){var e=this.properties,t=new c;this.cff=t;var r=this.parseHeader(),a=this.parseIndex(r.endPos),i=this.parseIndex(a.endPos),n=this.parseIndex(i.endPos),o=this.parseIndex(n.endPos),s=this.parseDict(i.obj.get(0)),l=this.createDict(d,s,t.strings);t.header=r.obj;t.names=this.parseNameIndex(a.obj);t.strings=this.parseStringIndex(n.obj);t.topDict=l;t.globalSubrIndex=o.obj;this.parsePrivateDict(t.topDict);t.isCIDFont=l.hasName("ROS");var u=l.getByName("CharStrings"),h=this.parseIndex(u).obj,f=l.getByName("FontMatrix");f&&(e.fontMatrix=f);var g,m,p=l.getByName("FontBBox");if(p){e.ascent=Math.max(p[3],p[1]);e.descent=Math.min(p[1],p[3]);e.ascentScaled=!0}if(t.isCIDFont){for(var v=this.parseIndex(l.getByName("FDArray")).obj,b=0,y=v.count;b<y;++b){var w=v.get(b),k=this.createDict(d,this.parseDict(w),t.strings);this.parsePrivateDict(k);t.fdArray.push(k)}m=null;g=this.parseCharsets(l.getByName("charset"),h.count,t.strings,!0);t.fdSelect=this.parseFDSelect(l.getByName("FDSelect"),h.count)}else{g=this.parseCharsets(l.getByName("charset"),h.count,t.strings,!1);m=this.parseEncoding(l.getByName("Encoding"),e,t.strings,g.charset)}t.charset=g;t.encoding=m;var S=this.parseCharStrings({charStrings:h,localSubrIndex:l.privateDict.subrsIndex,globalSubrIndex:o.obj,fdSelect:t.fdSelect,fdArray:t.fdArray,privateDict:l.privateDict});t.charStrings=S.charStrings;t.seacs=S.seacs;t.widths=S.widths;return t},parseHeader:function(){for(var e=this.bytes,t=e.length,r=0;r<t&&1!==e[r];)++r;if(r>=t)throw new a.FormatError("Invalid CFF header");if(0!==r){(0,a.info)("cff data is shifted");e=e.subarray(r);this.bytes=e}var i=e[0],n=e[1],o=e[2],s=e[3];return{obj:new l(i,n,o,s),endPos:o}},parseDict:function(e){var t=0;function r(){var r=e[t++];if(30===r)return function(){var r="",a=["0","1","2","3","4","5","6","7","8","9",".","E","E-",null,"-"],i=e.length;for(;t<i;){var n=e[t++],o=n>>4,s=15&n;if(15===o)break;r+=a[o];if(15===s)break;r+=a[s]}return parseFloat(r)}();if(28===r)return r=((r=e[t++])<<24|e[t++]<<16)>>16;if(29===r)return r=(r=(r=(r=e[t++])<<8|e[t++])<<8|e[t++])<<8|e[t++];if(r>=32&&r<=246)return r-139;if(r>=247&&r<=250)return 256*(r-247)+e[t++]+108;if(r>=251&&r<=254)return-256*(r-251)-e[t++]-108;(0,a.warn)('CFFParser_parseDict: "'+r+'" is a reserved command.');return NaN}var i=[],n=[];t=0;for(var o=e.length;t<o;){var s=e[t];if(s<=21){12===s&&(s=s<<8|e[++t]);n.push([s,i]);i=[];++t}else i.push(r())}return n},parseIndex:function(e){var t,r,a=new h,i=this.bytes,n=i[e++]<<8|i[e++],o=[],s=e;if(0!==n){var c=i[e++],l=e+(n+1)*c-1;for(t=0,r=n+1;t<r;++t){for(var u=0,f=0;f<c;++f){u<<=8;u+=i[e++]}o.push(l+u)}s=o[n]}for(t=0,r=o.length-1;t<r;++t){var d=o[t],g=o[t+1];a.add(i.subarray(d,g))}return{obj:a,endPos:s}},parseNameIndex:function(e){for(var t=[],r=0,i=e.count;r<i;++r){var n=e.get(r);t.push((0,a.bytesToString)(n))}return t},parseStringIndex:function(e){for(var t=new u,r=0,i=e.count;r<i;++r){var n=e.get(r);t.add((0,a.bytesToString)(n))}return t},createDict:function(e,t,r){for(var a=new e(r),i=0,n=t.length;i<n;++i){var o=t[i],s=o[0],c=o[1];a.setByKey(s,c)}return a},parseCharString:function(r,i,n,o){if(!i||r.callDepth>10)return!1;for(var s=r.stackSize,c=r.stack,l=i.length,u=0;u<l;){var h=i[u++],f=null;if(12===h){var d=i[u++];if(0===d){i[u-2]=139;i[u-1]=22;s=0}else f=t[d]}else if(28===h){c[s]=(i[u]<<24|i[u+1]<<16)>>16;u+=2;s++}else if(14===h){if(s>=4){s-=4;if(this.seacAnalysisEnabled){r.seac=c.slice(s,s+4);return!1}}f=e[h]}else if(h>=32&&h<=246){c[s]=h-139;s++}else if(h>=247&&h<=254){c[s]=h<251?(h-247<<8)+i[u]+108:-(h-251<<8)-i[u]-108;u++;s++}else if(255===h){c[s]=(i[u]<<24|i[u+1]<<16|i[u+2]<<8|i[u+3])/65536;u+=4;s++}else if(19===h||20===h){r.hints+=s>>1;u+=r.hints+7>>3;s%=2;f=e[h]}else{if(10===h||29===h){var g;if(!(g=10===h?n:o)){f=e[h];(0,a.warn)("Missing subrsIndex for "+f.id);return!1}var m=32768;g.count<1240?m=107:g.count<33900&&(m=1131);var p=c[--s]+m;if(p<0||p>=g.count||isNaN(p)){f=e[h];(0,a.warn)("Out of bounds subrIndex for "+f.id);return!1}r.stackSize=s;r.callDepth++;if(!this.parseCharString(r,g.get(p),n,o))return!1;r.callDepth--;s=r.stackSize;continue}if(11===h){r.stackSize=s;return!0}f=e[h]}if(f){f.stem&&(r.hints+=s>>1);if("min"in f&&!r.undefStack&&s<f.min){(0,a.warn)("Not enough parameters for "+f.id+"; actual: "+s+", expected: "+f.min);return!1}if(r.firstStackClearing&&f.stackClearing){r.firstStackClearing=!1;(s-=f.min)>=2&&f.stem?s%=2:s>1&&(0,a.warn)("Found too many parameters for stack-clearing command");s>0&&c[s-1]>=0&&(r.width=c[s-1])}if("stackDelta"in f){"stackFn"in f&&f.stackFn(c,s);s+=f.stackDelta}else if(f.stackClearing)s=0;else if(f.resetStack){s=0;r.undefStack=!1}else if(f.undefStack){s=0;r.undefStack=!0;r.firstStackClearing=!1}}}r.stackSize=s;return!0},parseCharStrings:function(e){for(var t=e.charStrings,r=e.localSubrIndex,i=e.globalSubrIndex,n=e.fdSelect,o=e.fdArray,s=e.privateDict,c=[],l=[],u=t.count,h=0;h<u;h++){var f=t.get(h),d={callDepth:0,stackSize:0,stack:[],undefStack:!0,hints:0,firstStackClearing:!0,seac:null,width:null},g=!0,m=null,p=s;if(n&&o.length){var v=n.getFDIndex(h);if(-1===v){(0,a.warn)("Glyph index is not in fd select.");g=!1}if(v>=o.length){(0,a.warn)("Invalid fd index for glyph index.");g=!1}g&&(m=(p=o[v].privateDict).subrsIndex)}else r&&(m=r);g&&(g=this.parseCharString(d,f,m,i));if(null!==d.width){var b=p.getByName("nominalWidthX");l[h]=b+d.width}else{var y=p.getByName("defaultWidthX");l[h]=y}null!==d.seac&&(c[h]=d.seac);g||t.set(h,new Uint8Array([14]))}return{charStrings:t,seacs:c,widths:l}},emptyPrivateDictionary:function(e){var t=this.createDict(g,[],e.strings);e.setByKey(18,[0,0]);e.privateDict=t},parsePrivateDict:function(e){if(e.hasName("Private")){var t=e.getByName("Private");if(Array.isArray(t)&&2===t.length){var r=t[0],a=t[1];if(0===r||a>=this.bytes.length)this.emptyPrivateDictionary(e);else{var i=a+r,n=this.bytes.subarray(a,i),o=this.parseDict(n),s=this.createDict(g,o,e.strings);e.privateDict=s;if(s.getByName("Subrs")){var c=s.getByName("Subrs"),l=a+c;if(0===c||l>=this.bytes.length)this.emptyPrivateDictionary(e);else{var u=this.parseIndex(l);s.subrsIndex=u.obj}}}}else e.removeByName("Private")}else this.emptyPrivateDictionary(e)},parseCharsets:function(e,t,r,n){if(0===e)return new p(!0,m.ISO_ADOBE,i.ISOAdobeCharset);if(1===e)return new p(!0,m.EXPERT,i.ExpertCharset);if(2===e)return new p(!0,m.EXPERT_SUBSET,i.ExpertSubsetCharset);var o,s,c,l=this.bytes,u=e,h=l[e++],f=[".notdef"];t-=1;switch(h){case 0:for(c=0;c<t;c++){o=l[e++]<<8|l[e++];f.push(n?o:r.get(o))}break;case 1:for(;f.length<=t;){o=l[e++]<<8|l[e++];s=l[e++];for(c=0;c<=s;c++)f.push(n?o++:r.get(o++))}break;case 2:for(;f.length<=t;){o=l[e++]<<8|l[e++];s=l[e++]<<8|l[e++];for(c=0;c<=s;c++)f.push(n?o++:r.get(o++))}break;default:throw new a.FormatError("Unknown charset format")}var d=e,g=l.subarray(u,d);return new p(!1,h,f,g)},parseEncoding:function(e,t,r,i){var o,s,c,l=Object.create(null),u=this.bytes,h=!1,f=null;if(0===e||1===e){h=!0;o=e;var d=e?n.ExpertEncoding:n.StandardEncoding;for(s=0,c=i.length;s<c;s++){var g=d.indexOf(i[s]);-1!==g&&(l[g]=s)}}else{var m=e;switch(127&(o=u[e++])){case 0:var p=u[e++];for(s=1;s<=p;s++)l[u[e++]]=s;break;case 1:var b=u[e++],y=1;for(s=0;s<b;s++)for(var w=u[e++],k=u[e++],S=w;S<=w+k;S++)l[S]=y++;break;default:throw new a.FormatError("Unknown encoding format: "+o+" in CFF")}var C=e;if(128&o){u[m]&=127;!function(){var t=u[e++];for(s=0;s<t;s++){var a=u[e++],n=(u[e++]<<8)+(255&u[e++]);l[a]=i.indexOf(r.get(n))}}()}f=u.subarray(m,C)}return new v(h,o&=127,l,f)},parseFDSelect:function(e,t){var r,i=this.bytes,n=i[e++],o=[];switch(n){case 0:for(r=0;r<t;++r){var s=i[e++];o.push(s)}break;case 3:var c=i[e++]<<8|i[e++];for(r=0;r<c;++r){var l=i[e++]<<8|i[e++];if(0===r&&0!==l){(0,a.warn)("parseFDSelect: The first range must have a first GID of 0 -- trying to recover.");l=0}for(var u=i[e++],h=i[e]<<8|i[e+1],f=l;f<h;++f)o.push(u)}e+=2;break;default:throw new a.FormatError('parseFDSelect: Unknown format "'+n+'".')}if(o.length!==t)throw new a.FormatError("parseFDSelect: Invalid font data.");return new b(n,o)}};return r}(),c=function(){function e(){this.header=null;this.names=[];this.topDict=null;this.strings=new u;this.globalSubrIndex=null;this.encoding=null;this.charset=null;this.charStrings=null;this.fdArray=[];this.fdSelect=null;this.isCIDFont=!1}e.prototype={duplicateFirstGlyph:function(){if(this.charStrings.count>=65535)(0,a.warn)("Not enough space in charstrings to duplicate first glyph.");else{var e=this.charStrings.get(0);this.charStrings.add(e);this.isCIDFont&&this.fdSelect.fdSelect.push(this.fdSelect.fdSelect[0])}},hasGlyphId:function(e){return!(e<0||e>=this.charStrings.count)&&this.charStrings.get(e).length>0}};return e}(),l=function(){return function(e,t,r,a){this.major=e;this.minor=t;this.hdrSize=r;this.offSize=a}}(),u=function(){function e(){this.strings=[]}e.prototype={get:function(e){return e>=0&&e<=390?o[e]:e-391<=this.strings.length?this.strings[e-391]:o[0]},add:function(e){this.strings.push(e)},get count(){return this.strings.length}};return e}(),h=function(){function e(){this.objects=[];this.length=0}e.prototype={add:function(e){this.length+=e.length;this.objects.push(e)},set:function(e,t){this.length+=t.length-this.objects[e].length;this.objects[e]=t},get:function(e){return this.objects[e]},get count(){return this.objects.length}};return e}(),f=function(){function e(e,t){this.keyToNameMap=e.keyToNameMap;this.nameToKeyMap=e.nameToKeyMap;this.defaults=e.defaults;this.types=e.types;this.opcodes=e.opcodes;this.order=e.order;this.strings=t;this.values=Object.create(null)}e.prototype={setByKey:function(e,t){if(!(e in this.keyToNameMap))return!1;var r=t.length;if(0===r)return!0;for(var i=0;i<r;i++)if(isNaN(t[i])){(0,a.warn)('Invalid CFFDict value: "'+t+'" for key "'+e+'".');return!0}var n=this.types[e];"num"!==n&&"sid"!==n&&"offset"!==n||(t=t[0]);this.values[e]=t;return!0},setByName:function(e,t){if(!(e in this.nameToKeyMap))throw new a.FormatError('Invalid dictionary name "'+e+'"');this.values[this.nameToKeyMap[e]]=t},hasName:function(e){return this.nameToKeyMap[e]in this.values},getByName:function(e){if(!(e in this.nameToKeyMap))throw new a.FormatError("Invalid dictionary name "+e+'"');var t=this.nameToKeyMap[e];return t in this.values?this.values[t]:this.defaults[t]},removeByName:function(e){delete this.values[this.nameToKeyMap[e]]}};e.createTables=function(e){for(var t={keyToNameMap:{},nameToKeyMap:{},defaults:{},types:{},opcodes:{},order:[]},r=0,a=e.length;r<a;++r){var i=e[r],n=Array.isArray(i[0])?(i[0][0]<<8)+i[0][1]:i[0];t.keyToNameMap[n]=i[1];t.nameToKeyMap[i[1]]=n;t.types[n]=i[2];t.defaults[n]=i[3];t.opcodes[n]=Array.isArray(i[0])?i[0]:[i[0]];t.order.push(n)}return t};return e}(),d=function(){var e=[[[12,30],"ROS",["sid","sid","num"],null],[[12,20],"SyntheticBase","num",null],[0,"version","sid",null],[1,"Notice","sid",null],[[12,0],"Copyright","sid",null],[2,"FullName","sid",null],[3,"FamilyName","sid",null],[4,"Weight","sid",null],[[12,1],"isFixedPitch","num",0],[[12,2],"ItalicAngle","num",0],[[12,3],"UnderlinePosition","num",-100],[[12,4],"UnderlineThickness","num",50],[[12,5],"PaintType","num",0],[[12,6],"CharstringType","num",2],[[12,7],"FontMatrix",["num","num","num","num","num","num"],[.001,0,0,.001,0,0]],[13,"UniqueID","num",null],[5,"FontBBox",["num","num","num","num"],[0,0,0,0]],[[12,8],"StrokeWidth","num",0],[14,"XUID","array",null],[15,"charset","offset",0],[16,"Encoding","offset",0],[17,"CharStrings","offset",0],[18,"Private",["offset","offset"],null],[[12,21],"PostScript","sid",null],[[12,22],"BaseFontName","sid",null],[[12,23],"BaseFontBlend","delta",null],[[12,31],"CIDFontVersion","num",0],[[12,32],"CIDFontRevision","num",0],[[12,33],"CIDFontType","num",0],[[12,34],"CIDCount","num",8720],[[12,35],"UIDBase","num",null],[[12,37],"FDSelect","offset",null],[[12,36],"FDArray","offset",null],[[12,38],"FontName","sid",null]],t=null;function r(r){null===t&&(t=f.createTables(e));f.call(this,t,r);this.privateDict=null}r.prototype=Object.create(f.prototype);return r}(),g=function(){var e=[[6,"BlueValues","delta",null],[7,"OtherBlues","delta",null],[8,"FamilyBlues","delta",null],[9,"FamilyOtherBlues","delta",null],[[12,9],"BlueScale","num",.039625],[[12,10],"BlueShift","num",7],[[12,11],"BlueFuzz","num",1],[10,"StdHW","num",null],[11,"StdVW","num",null],[[12,12],"StemSnapH","delta",null],[[12,13],"StemSnapV","delta",null],[[12,14],"ForceBold","num",0],[[12,17],"LanguageGroup","num",0],[[12,18],"ExpansionFactor","num",.06],[[12,19],"initialRandomSeed","num",0],[20,"defaultWidthX","num",0],[21,"nominalWidthX","num",0],[19,"Subrs","offset",null]],t=null;function r(r){null===t&&(t=f.createTables(e));f.call(this,t,r);this.subrsIndex=null}r.prototype=Object.create(f.prototype);return r}(),m={ISO_ADOBE:0,EXPERT:1,EXPERT_SUBSET:2},p=function(){return function(e,t,r,a){this.predefined=e;this.format=t;this.charset=r;this.raw=a}}(),v=function(){return function(e,t,r,a){this.predefined=e;this.format=t;this.encoding=r;this.raw=a}}(),b=function(){function e(e,t){this.format=e;this.fdSelect=t}e.prototype={getFDIndex:function(e){return e<0||e>=this.fdSelect.length?-1:this.fdSelect[e]}};return e}(),y=function(){function e(){this.offsets=Object.create(null)}e.prototype={isTracking:function(e){return e in this.offsets},track:function(e,t){if(e in this.offsets)throw new a.FormatError("Already tracking location of "+e);this.offsets[e]=t},offset:function(e){for(var t in this.offsets)this.offsets[t]+=e},setEntryLocation:function(e,t,r){if(!(e in this.offsets))throw new a.FormatError("Not tracking location of "+e);for(var i=r.data,n=this.offsets[e],o=0,s=t.length;o<s;++o){var c=5*o+n,l=c+1,u=c+2,h=c+3,f=c+4;if(29!==i[c]||0!==i[l]||0!==i[u]||0!==i[h]||0!==i[f])throw new a.FormatError("writing to an offset that is not empty");var d=t[o];i[c]=29;i[l]=d>>24&255;i[u]=d>>16&255;i[h]=d>>8&255;i[f]=255&d}}};return e}(),w=function(){function e(e){this.cff=e}e.prototype={compile:function(){var e=this.cff,t={data:[],length:0,add:function(e){this.data=this.data.concat(e);this.length=this.data.length}},r=this.compileHeader(e.header);t.add(r);var i=this.compileNameIndex(e.names);t.add(i);if(e.isCIDFont&&e.topDict.hasName("FontMatrix")){var n=e.topDict.getByName("FontMatrix");e.topDict.removeByName("FontMatrix");for(var o=0,s=e.fdArray.length;o<s;o++){var c=e.fdArray[o],l=n.slice(0);c.hasName("FontMatrix")&&(l=a.Util.transform(l,c.getByName("FontMatrix")));c.setByName("FontMatrix",l)}}e.topDict.setByName("charset",0);var u=this.compileTopDicts([e.topDict],t.length,e.isCIDFont);t.add(u.output);var h=u.trackers[0],f=this.compileStringIndex(e.strings.strings);t.add(f);var d=this.compileIndex(e.globalSubrIndex);t.add(d);if(e.encoding&&e.topDict.hasName("Encoding"))if(e.encoding.predefined)h.setEntryLocation("Encoding",[e.encoding.format],t);else{var g=this.compileEncoding(e.encoding);h.setEntryLocation("Encoding",[t.length],t);t.add(g)}var m=this.compileCharset(e.charset);h.setEntryLocation("charset",[t.length],t);t.add(m);var p=this.compileCharStrings(e.charStrings);h.setEntryLocation("CharStrings",[t.length],t);t.add(p);if(e.isCIDFont){h.setEntryLocation("FDSelect",[t.length],t);var v=this.compileFDSelect(e.fdSelect);t.add(v);u=this.compileTopDicts(e.fdArray,t.length,!0);h.setEntryLocation("FDArray",[t.length],t);t.add(u.output);var b=u.trackers;this.compilePrivateDicts(e.fdArray,b,t)}this.compilePrivateDicts([e.topDict],[h],t);t.add([0]);return t.data},encodeNumber:function(e){return parseFloat(e)!==parseInt(e,10)||isNaN(e)?this.encodeFloat(e):this.encodeInteger(e)},encodeFloat:function(e){var t=e.toString(),r=/\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(t);if(r){var a=parseFloat("1e"+((r[2]?+r[2]:0)+r[1].length));t=(Math.round(e*a)/a).toString()}var i,n,o="";for(i=0,n=t.length;i<n;++i){var s=t[i];o+="e"===s?"-"===t[++i]?"c":"b":"."===s?"a":"-"===s?"e":s}var c=[30];for(i=0,n=(o+=1&o.length?"f":"ff").length;i<n;i+=2)c.push(parseInt(o.substring(i,i+2),16));return c},encodeInteger:function(e){return e>=-107&&e<=107?[e+139]:e>=108&&e<=1131?[247+((e-=108)>>8),255&e]:e>=-1131&&e<=-108?[251+((e=-e-108)>>8),255&e]:e>=-32768&&e<=32767?[28,e>>8&255,255&e]:[29,e>>24&255,e>>16&255,e>>8&255,255&e]},compileHeader:function(e){return[e.major,e.minor,e.hdrSize,e.offSize]},compileNameIndex:function(e){for(var t=new h,r=0,i=e.length;r<i;++r){for(var n=e[r],o=Math.min(n.length,127),s=new Array(o),c=0;c<o;c++){var l=n[c];(l<"!"||l>"~"||"["===l||"]"===l||"("===l||")"===l||"{"===l||"}"===l||"<"===l||">"===l||"/"===l||"%"===l)&&(l="_");s[c]=l}""===(s=s.join(""))&&(s="Bad_Font_Name");t.add((0,a.stringToBytes)(s))}return this.compileIndex(t)},compileTopDicts:function(e,t,r){for(var a=[],i=new h,n=0,o=e.length;n<o;++n){var s=e[n];if(r){s.removeByName("CIDFontVersion");s.removeByName("CIDFontRevision");s.removeByName("CIDFontType");s.removeByName("CIDCount");s.removeByName("UIDBase")}var c=new y,l=this.compileDict(s,c);a.push(c);i.add(l);c.offset(t)}return{trackers:a,output:i=this.compileIndex(i,a)}},compilePrivateDicts:function(e,t,r){for(var i=0,n=e.length;i<n;++i){var o=e[i],s=o.privateDict;if(!s||!o.hasName("Private"))throw new a.FormatError("There must be a private dictionary.");var c=new y,l=this.compileDict(s,c),u=r.length;c.offset(u);l.length||(u=0);t[i].setEntryLocation("Private",[l.length,u],r);r.add(l);if(s.subrsIndex&&s.hasName("Subrs")){var h=this.compileIndex(s.subrsIndex);c.setEntryLocation("Subrs",[l.length],r);r.add(h)}}},compileDict:function(e,t){for(var r=[],i=e.order,n=0;n<i.length;++n){var o=i[n];if(o in e.values){var s=e.values[o],c=e.types[o];Array.isArray(c)||(c=[c]);Array.isArray(s)||(s=[s]);if(0!==s.length){for(var l=0,u=c.length;l<u;++l){var h=c[l],f=s[l];switch(h){case"num":case"sid":r=r.concat(this.encodeNumber(f));break;case"offset":var d=e.keyToNameMap[o];t.isTracking(d)||t.track(d,r.length);r=r.concat([29,0,0,0,0]);break;case"array":case"delta":r=r.concat(this.encodeNumber(f));for(var g=1,m=s.length;g<m;++g)r=r.concat(this.encodeNumber(s[g]));break;default:throw new a.FormatError("Unknown data type of "+h)}}r=r.concat(e.opcodes[o])}}}return r},compileStringIndex:function(e){for(var t=new h,r=0,i=e.length;r<i;++r)t.add((0,a.stringToBytes)(e[r]));return this.compileIndex(t)},compileGlobalSubrIndex:function(){var e=this.cff.globalSubrIndex;this.out.writeByteArray(this.compileIndex(e))},compileCharStrings:function(e){for(var t=new h,r=0;r<e.count;r++){var a=e.get(r);0!==a.length?t.add(a):t.add(new Uint8Array([139,14]))}return this.compileIndex(t)},compileCharset:function(e){var t=1+2*(this.cff.charStrings.count-1),r=new Uint8Array(t);return this.compileTypedArray(r)},compileEncoding:function(e){return this.compileTypedArray(e.raw)},compileFDSelect:function(e){var t=e.format,r=void 0,a=void 0;switch(t){case 0:(r=new Uint8Array(1+e.fdSelect.length))[0]=t;for(a=0;a<e.fdSelect.length;a++)r[a+1]=e.fdSelect[a];break;case 3:var i=e.fdSelect[0],n=[t,0,0,0,0,i];for(a=1;a<e.fdSelect.length;a++){var o=e.fdSelect[a];if(o!==i){n.push(a>>8&255,255&a,o);i=o}}var s=(n.length-3)/3;n[1]=s>>8&255;n[2]=255&s;n.push(a>>8&255,255&a);r=new Uint8Array(n)}return this.compileTypedArray(r)},compileTypedArray:function(e){for(var t=[],r=0,a=e.length;r<a;++r)t[r]=e[r];return t},compileIndex:function(e,t){t=t||[];var r=e.objects,a=r.length;if(0===a)return[0,0,0];var i,n,o=[a>>8&255,255&a],s=1;for(i=0;i<a;++i)s+=r[i].length;n=s<256?1:s<65536?2:s<16777216?3:4;o.push(n);var c=1;for(i=0;i<a+1;i++){1===n?o.push(255&c):2===n?o.push(c>>8&255,255&c):3===n?o.push(c>>16&255,c>>8&255,255&c):o.push(c>>>24&255,c>>16&255,c>>8&255,255&c);r[i]&&(c+=r[i].length)}for(i=0;i<a;i++){t[i]&&t[i].offset(o.length);for(var l=0,u=r[i].length;l<u;l++)o.push(r[i][l])}return o}};return e}();t.CFFStandardStrings=o;t.CFFParser=s;t.CFF=c;t.CFFHeader=l;t.CFFStrings=u;t.CFFIndex=h;t.CFFCharset=p;t.CFFTopDict=d;t.CFFPrivateDict=g;t.CFFCompiler=w;t.CFFFDSelect=b},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.ISOAdobeCharset=[".notdef","space","exclam","quotedbl","numbersign","dollar","percent","ampersand","quoteright","parenleft","parenright","asterisk","plus","comma","hyphen","period","slash","zero","one","two","three","four","five","six","seven","eight","nine","colon","semicolon","less","equal","greater","question","at","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","bracketleft","backslash","bracketright","asciicircum","underscore","quoteleft","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde","exclamdown","cent","sterling","fraction","yen","florin","section","currency","quotesingle","quotedblleft","guillemotleft","guilsinglleft","guilsinglright","fi","fl","endash","dagger","daggerdbl","periodcentered","paragraph","bullet","quotesinglbase","quotedblbase","quotedblright","guillemotright","ellipsis","perthousand","questiondown","grave","acute","circumflex","tilde","macron","breve","dotaccent","dieresis","ring","cedilla","hungarumlaut","ogonek","caron","emdash","AE","ordfeminine","Lslash","Oslash","OE","ordmasculine","ae","dotlessi","lslash","oslash","oe","germandbls","onesuperior","logicalnot","mu","trademark","Eth","onehalf","plusminus","Thorn","onequarter","divide","brokenbar","degree","thorn","threequarters","twosuperior","registered","minus","eth","multiply","threesuperior","copyright","Aacute","Acircumflex","Adieresis","Agrave","Aring","Atilde","Ccedilla","Eacute","Ecircumflex","Edieresis","Egrave","Iacute","Icircumflex","Idieresis","Igrave","Ntilde","Oacute","Ocircumflex","Odieresis","Ograve","Otilde","Scaron","Uacute","Ucircumflex","Udieresis","Ugrave","Yacute","Ydieresis","Zcaron","aacute","acircumflex","adieresis","agrave","aring","atilde","ccedilla","eacute","ecircumflex","edieresis","egrave","iacute","icircumflex","idieresis","igrave","ntilde","oacute","ocircumflex","odieresis","ograve","otilde","scaron","uacute","ucircumflex","udieresis","ugrave","yacute","ydieresis","zcaron"];t.ExpertCharset=[".notdef","space","exclamsmall","Hungarumlautsmall","dollaroldstyle","dollarsuperior","ampersandsmall","Acutesmall","parenleftsuperior","parenrightsuperior","twodotenleader","onedotenleader","comma","hyphen","period","fraction","zerooldstyle","oneoldstyle","twooldstyle","threeoldstyle","fouroldstyle","fiveoldstyle","sixoldstyle","sevenoldstyle","eightoldstyle","nineoldstyle","colon","semicolon","commasuperior","threequartersemdash","periodsuperior","questionsmall","asuperior","bsuperior","centsuperior","dsuperior","esuperior","isuperior","lsuperior","msuperior","nsuperior","osuperior","rsuperior","ssuperior","tsuperior","ff","fi","fl","ffi","ffl","parenleftinferior","parenrightinferior","Circumflexsmall","hyphensuperior","Gravesmall","Asmall","Bsmall","Csmall","Dsmall","Esmall","Fsmall","Gsmall","Hsmall","Ismall","Jsmall","Ksmall","Lsmall","Msmall","Nsmall","Osmall","Psmall","Qsmall","Rsmall","Ssmall","Tsmall","Usmall","Vsmall","Wsmall","Xsmall","Ysmall","Zsmall","colonmonetary","onefitted","rupiah","Tildesmall","exclamdownsmall","centoldstyle","Lslashsmall","Scaronsmall","Zcaronsmall","Dieresissmall","Brevesmall","Caronsmall","Dotaccentsmall","Macronsmall","figuredash","hypheninferior","Ogoneksmall","Ringsmall","Cedillasmall","onequarter","onehalf","threequarters","questiondownsmall","oneeighth","threeeighths","fiveeighths","seveneighths","onethird","twothirds","zerosuperior","onesuperior","twosuperior","threesuperior","foursuperior","fivesuperior","sixsuperior","sevensuperior","eightsuperior","ninesuperior","zeroinferior","oneinferior","twoinferior","threeinferior","fourinferior","fiveinferior","sixinferior","seveninferior","eightinferior","nineinferior","centinferior","dollarinferior","periodinferior","commainferior","Agravesmall","Aacutesmall","Acircumflexsmall","Atildesmall","Adieresissmall","Aringsmall","AEsmall","Ccedillasmall","Egravesmall","Eacutesmall","Ecircumflexsmall","Edieresissmall","Igravesmall","Iacutesmall","Icircumflexsmall","Idieresissmall","Ethsmall","Ntildesmall","Ogravesmall","Oacutesmall","Ocircumflexsmall","Otildesmall","Odieresissmall","OEsmall","Oslashsmall","Ugravesmall","Uacutesmall","Ucircumflexsmall","Udieresissmall","Yacutesmall","Thornsmall","Ydieresissmall"];t.ExpertSubsetCharset=[".notdef","space","dollaroldstyle","dollarsuperior","parenleftsuperior","parenrightsuperior","twodotenleader","onedotenleader","comma","hyphen","period","fraction","zerooldstyle","oneoldstyle","twooldstyle","threeoldstyle","fouroldstyle","fiveoldstyle","sixoldstyle","sevenoldstyle","eightoldstyle","nineoldstyle","colon","semicolon","commasuperior","threequartersemdash","periodsuperior","asuperior","bsuperior","centsuperior","dsuperior","esuperior","isuperior","lsuperior","msuperior","nsuperior","osuperior","rsuperior","ssuperior","tsuperior","ff","fi","fl","ffi","ffl","parenleftinferior","parenrightinferior","hyphensuperior","colonmonetary","onefitted","rupiah","centoldstyle","figuredash","hypheninferior","onequarter","onehalf","threequarters","oneeighth","threeeighths","fiveeighths","seveneighths","onethird","twothirds","zerosuperior","onesuperior","twosuperior","threesuperior","foursuperior","fivesuperior","sixsuperior","sevensuperior","eightsuperior","ninesuperior","zeroinferior","oneinferior","twoinferior","threeinferior","fourinferior","fiveinferior","sixinferior","seveninferior","eightinferior","nineinferior","centinferior","dollarinferior","periodinferior","commainferior"]},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var a=["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","space","exclamsmall","Hungarumlautsmall","","dollaroldstyle","dollarsuperior","ampersandsmall","Acutesmall","parenleftsuperior","parenrightsuperior","twodotenleader","onedotenleader","comma","hyphen","period","fraction","zerooldstyle","oneoldstyle","twooldstyle","threeoldstyle","fouroldstyle","fiveoldstyle","sixoldstyle","sevenoldstyle","eightoldstyle","nineoldstyle","colon","semicolon","commasuperior","threequartersemdash","periodsuperior","questionsmall","","asuperior","bsuperior","centsuperior","dsuperior","esuperior","","","","isuperior","","","lsuperior","msuperior","nsuperior","osuperior","","","rsuperior","ssuperior","tsuperior","","ff","fi","fl","ffi","ffl","parenleftinferior","","parenrightinferior","Circumflexsmall","hyphensuperior","Gravesmall","Asmall","Bsmall","Csmall","Dsmall","Esmall","Fsmall","Gsmall","Hsmall","Ismall","Jsmall","Ksmall","Lsmall","Msmall","Nsmall","Osmall","Psmall","Qsmall","Rsmall","Ssmall","Tsmall","Usmall","Vsmall","Wsmall","Xsmall","Ysmall","Zsmall","colonmonetary","onefitted","rupiah","Tildesmall","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","exclamdownsmall","centoldstyle","Lslashsmall","","","Scaronsmall","Zcaronsmall","Dieresissmall","Brevesmall","Caronsmall","","Dotaccentsmall","","","Macronsmall","","","figuredash","hypheninferior","","","Ogoneksmall","Ringsmall","Cedillasmall","","","","onequarter","onehalf","threequarters","questiondownsmall","oneeighth","threeeighths","fiveeighths","seveneighths","onethird","twothirds","","","zerosuperior","onesuperior","twosuperior","threesuperior","foursuperior","fivesuperior","sixsuperior","sevensuperior","eightsuperior","ninesuperior","zeroinferior","oneinferior","twoinferior","threeinferior","fourinferior","fiveinferior","sixinferior","seveninferior","eightinferior","nineinferior","centinferior","dollarinferior","periodinferior","commainferior","Agravesmall","Aacutesmall","Acircumflexsmall","Atildesmall","Adieresissmall","Aringsmall","AEsmall","Ccedillasmall","Egravesmall","Eacutesmall","Ecircumflexsmall","Edieresissmall","Igravesmall","Iacutesmall","Icircumflexsmall","Idieresissmall","Ethsmall","Ntildesmall","Ogravesmall","Oacutesmall","Ocircumflexsmall","Otildesmall","Odieresissmall","OEsmall","Oslashsmall","Ugravesmall","Uacutesmall","Ucircumflexsmall","Udieresissmall","Yacutesmall","Thornsmall","Ydieresissmall"],i=["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","space","exclamsmall","Hungarumlautsmall","centoldstyle","dollaroldstyle","dollarsuperior","ampersandsmall","Acutesmall","parenleftsuperior","parenrightsuperior","twodotenleader","onedotenleader","comma","hyphen","period","fraction","zerooldstyle","oneoldstyle","twooldstyle","threeoldstyle","fouroldstyle","fiveoldstyle","sixoldstyle","sevenoldstyle","eightoldstyle","nineoldstyle","colon","semicolon","","threequartersemdash","","questionsmall","","","","","Ethsmall","","","onequarter","onehalf","threequarters","oneeighth","threeeighths","fiveeighths","seveneighths","onethird","twothirds","","","","","","","ff","fi","fl","ffi","ffl","parenleftinferior","","parenrightinferior","Circumflexsmall","hypheninferior","Gravesmall","Asmall","Bsmall","Csmall","Dsmall","Esmall","Fsmall","Gsmall","Hsmall","Ismall","Jsmall","Ksmall","Lsmall","Msmall","Nsmall","Osmall","Psmall","Qsmall","Rsmall","Ssmall","Tsmall","Usmall","Vsmall","Wsmall","Xsmall","Ysmall","Zsmall","colonmonetary","onefitted","rupiah","Tildesmall","","","asuperior","centsuperior","","","","","Aacutesmall","Agravesmall","Acircumflexsmall","Adieresissmall","Atildesmall","Aringsmall","Ccedillasmall","Eacutesmall","Egravesmall","Ecircumflexsmall","Edieresissmall","Iacutesmall","Igravesmall","Icircumflexsmall","Idieresissmall","Ntildesmall","Oacutesmall","Ogravesmall","Ocircumflexsmall","Odieresissmall","Otildesmall","Uacutesmall","Ugravesmall","Ucircumflexsmall","Udieresissmall","","eightsuperior","fourinferior","threeinferior","sixinferior","eightinferior","seveninferior","Scaronsmall","","centinferior","twoinferior","","Dieresissmall","","Caronsmall","osuperior","fiveinferior","","commainferior","periodinferior","Yacutesmall","","dollarinferior","","","Thornsmall","","nineinferior","zeroinferior","Zcaronsmall","AEsmall","Oslashsmall","questiondownsmall","oneinferior","Lslashsmall","","","","","","","Cedillasmall","","","","","","OEsmall","figuredash","hyphensuperior","","","","","exclamdownsmall","","Ydieresissmall","","onesuperior","twosuperior","threesuperior","foursuperior","fivesuperior","sixsuperior","sevensuperior","ninesuperior","zerosuperior","","esuperior","rsuperior","tsuperior","","","isuperior","ssuperior","dsuperior","","","","","","lsuperior","Ogoneksmall","Brevesmall","Macronsmall","bsuperior","nsuperior","msuperior","commasuperior","periodsuperior","Dotaccentsmall","Ringsmall","","","",""],n=["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","space","exclam","quotedbl","numbersign","dollar","percent","ampersand","quotesingle","parenleft","parenright","asterisk","plus","comma","hyphen","period","slash","zero","one","two","three","four","five","six","seven","eight","nine","colon","semicolon","less","equal","greater","question","at","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","bracketleft","backslash","bracketright","asciicircum","underscore","grave","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde","","Adieresis","Aring","Ccedilla","Eacute","Ntilde","Odieresis","Udieresis","aacute","agrave","acircumflex","adieresis","atilde","aring","ccedilla","eacute","egrave","ecircumflex","edieresis","iacute","igrave","icircumflex","idieresis","ntilde","oacute","ograve","ocircumflex","odieresis","otilde","uacute","ugrave","ucircumflex","udieresis","dagger","degree","cent","sterling","section","bullet","paragraph","germandbls","registered","copyright","trademark","acute","dieresis","notequal","AE","Oslash","infinity","plusminus","lessequal","greaterequal","yen","mu","partialdiff","summation","product","pi","integral","ordfeminine","ordmasculine","Omega","ae","oslash","questiondown","exclamdown","logicalnot","radical","florin","approxequal","Delta","guillemotleft","guillemotright","ellipsis","space","Agrave","Atilde","Otilde","OE","oe","endash","emdash","quotedblleft","quotedblright","quoteleft","quoteright","divide","lozenge","ydieresis","Ydieresis","fraction","currency","guilsinglleft","guilsinglright","fi","fl","daggerdbl","periodcentered","quotesinglbase","quotedblbase","perthousand","Acircumflex","Ecircumflex","Aacute","Edieresis","Egrave","Iacute","Icircumflex","Idieresis","Igrave","Oacute","Ocircumflex","apple","Ograve","Uacute","Ucircumflex","Ugrave","dotlessi","circumflex","tilde","macron","breve","dotaccent","ring","cedilla","hungarumlaut","ogonek","caron"],o=["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","space","exclam","quotedbl","numbersign","dollar","percent","ampersand","quoteright","parenleft","parenright","asterisk","plus","comma","hyphen","period","slash","zero","one","two","three","four","five","six","seven","eight","nine","colon","semicolon","less","equal","greater","question","at","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","bracketleft","backslash","bracketright","asciicircum","underscore","quoteleft","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","exclamdown","cent","sterling","fraction","yen","florin","section","currency","quotesingle","quotedblleft","guillemotleft","guilsinglleft","guilsinglright","fi","fl","","endash","dagger","daggerdbl","periodcentered","","paragraph","bullet","quotesinglbase","quotedblbase","quotedblright","guillemotright","ellipsis","perthousand","","questiondown","","grave","acute","circumflex","tilde","macron","breve","dotaccent","dieresis","","ring","cedilla","","hungarumlaut","ogonek","caron","emdash","","","","","","","","","","","","","","","","","AE","","ordfeminine","","","","","Lslash","Oslash","OE","ordmasculine","","","","","","ae","","","","dotlessi","","","lslash","oslash","oe","germandbls","","","",""],s=["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","space","exclam","quotedbl","numbersign","dollar","percent","ampersand","quotesingle","parenleft","parenright","asterisk","plus","comma","hyphen","period","slash","zero","one","two","three","four","five","six","seven","eight","nine","colon","semicolon","less","equal","greater","question","at","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","bracketleft","backslash","bracketright","asciicircum","underscore","grave","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde","bullet","Euro","bullet","quotesinglbase","florin","quotedblbase","ellipsis","dagger","daggerdbl","circumflex","perthousand","Scaron","guilsinglleft","OE","bullet","Zcaron","bullet","bullet","quoteleft","quoteright","quotedblleft","quotedblright","bullet","endash","emdash","tilde","trademark","scaron","guilsinglright","oe","bullet","zcaron","Ydieresis","space","exclamdown","cent","sterling","currency","yen","brokenbar","section","dieresis","copyright","ordfeminine","guillemotleft","logicalnot","hyphen","registered","macron","degree","plusminus","twosuperior","threesuperior","acute","mu","paragraph","periodcentered","cedilla","onesuperior","ordmasculine","guillemotright","onequarter","onehalf","threequarters","questiondown","Agrave","Aacute","Acircumflex","Atilde","Adieresis","Aring","AE","Ccedilla","Egrave","Eacute","Ecircumflex","Edieresis","Igrave","Iacute","Icircumflex","Idieresis","Eth","Ntilde","Ograve","Oacute","Ocircumflex","Otilde","Odieresis","multiply","Oslash","Ugrave","Uacute","Ucircumflex","Udieresis","Yacute","Thorn","germandbls","agrave","aacute","acircumflex","atilde","adieresis","aring","ae","ccedilla","egrave","eacute","ecircumflex","edieresis","igrave","iacute","icircumflex","idieresis","eth","ntilde","ograve","oacute","ocircumflex","otilde","odieresis","divide","oslash","ugrave","uacute","ucircumflex","udieresis","yacute","thorn","ydieresis"],c=["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","space","exclam","universal","numbersign","existential","percent","ampersand","suchthat","parenleft","parenright","asteriskmath","plus","comma","minus","period","slash","zero","one","two","three","four","five","six","seven","eight","nine","colon","semicolon","less","equal","greater","question","congruent","Alpha","Beta","Chi","Delta","Epsilon","Phi","Gamma","Eta","Iota","theta1","Kappa","Lambda","Mu","Nu","Omicron","Pi","Theta","Rho","Sigma","Tau","Upsilon","sigma1","Omega","Xi","Psi","Zeta","bracketleft","therefore","bracketright","perpendicular","underscore","radicalex","alpha","beta","chi","delta","epsilon","phi","gamma","eta","iota","phi1","kappa","lambda","mu","nu","omicron","pi","theta","rho","sigma","tau","upsilon","omega1","omega","xi","psi","zeta","braceleft","bar","braceright","similar","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Euro","Upsilon1","minute","lessequal","fraction","infinity","florin","club","diamond","heart","spade","arrowboth","arrowleft","arrowup","arrowright","arrowdown","degree","plusminus","second","greaterequal","multiply","proportional","partialdiff","bullet","divide","notequal","equivalence","approxequal","ellipsis","arrowvertex","arrowhorizex","carriagereturn","aleph","Ifraktur","Rfraktur","weierstrass","circlemultiply","circleplus","emptyset","intersection","union","propersuperset","reflexsuperset","notsubset","propersubset","reflexsubset","element","notelement","angle","gradient","registerserif","copyrightserif","trademarkserif","product","radical","dotmath","logicalnot","logicaland","logicalor","arrowdblboth","arrowdblleft","arrowdblup","arrowdblright","arrowdbldown","lozenge","angleleft","registersans","copyrightsans","trademarksans","summation","parenlefttp","parenleftex","parenleftbt","bracketlefttp","bracketleftex","bracketleftbt","bracelefttp","braceleftmid","braceleftbt","braceex","","angleright","integral","integraltp","integralex","integralbt","parenrighttp","parenrightex","parenrightbt","bracketrighttp","bracketrightex","bracketrightbt","bracerighttp","bracerightmid","bracerightbt",""],l=["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","space","a1","a2","a202","a3","a4","a5","a119","a118","a117","a11","a12","a13","a14","a15","a16","a105","a17","a18","a19","a20","a21","a22","a23","a24","a25","a26","a27","a28","a6","a7","a8","a9","a10","a29","a30","a31","a32","a33","a34","a35","a36","a37","a38","a39","a40","a41","a42","a43","a44","a45","a46","a47","a48","a49","a50","a51","a52","a53","a54","a55","a56","a57","a58","a59","a60","a61","a62","a63","a64","a65","a66","a67","a68","a69","a70","a71","a72","a73","a74","a203","a75","a204","a76","a77","a78","a79","a81","a82","a83","a84","a97","a98","a99","a100","","a89","a90","a93","a94","a91","a92","a205","a85","a206","a86","a87","a88","a95","a96","","","","","","","","","","","","","","","","","","","","a101","a102","a103","a104","a106","a107","a108","a112","a111","a110","a109","a120","a121","a122","a123","a124","a125","a126","a127","a128","a129","a130","a131","a132","a133","a134","a135","a136","a137","a138","a139","a140","a141","a142","a143","a144","a145","a146","a147","a148","a149","a150","a151","a152","a153","a154","a155","a156","a157","a158","a159","a160","a161","a163","a164","a196","a165","a192","a166","a167","a168","a169","a170","a171","a172","a173","a162","a174","a175","a176","a177","a178","a179","a193","a180","a199","a181","a200","a182","","a201","a183","a184","a197","a185","a194","a198","a186","a195","a187","a188","a189","a190","a191",""];t.WinAnsiEncoding=s;t.StandardEncoding=o;t.MacRomanEncoding=n;t.SymbolSetEncoding=c;t.ZapfDingbatsEncoding=l;t.ExpertEncoding=a;t.getEncoding=function(e){switch(e){case"WinAnsiEncoding":return s;case"StandardEncoding":return o;case"MacRomanEncoding":return n;case"SymbolSetEncoding":return c;case"ZapfDingbatsEncoding":return l;case"ExpertEncoding":return a;case"MacExpertEncoding":return i;default:return null}}},function(e,t,r){var a=r(2).getLookupTableFactory,i=a(function(e){e.A=65;e.AE=198;e.AEacute=508;e.AEmacron=482;e.AEsmall=63462;e.Aacute=193;e.Aacutesmall=63457;e.Abreve=258;e.Abreveacute=7854;e.Abrevecyrillic=1232;e.Abrevedotbelow=7862;e.Abrevegrave=7856;e.Abrevehookabove=7858;e.Abrevetilde=7860;e.Acaron=461;e.Acircle=9398;e.Acircumflex=194;e.Acircumflexacute=7844;e.Acircumflexdotbelow=7852;e.Acircumflexgrave=7846;e.Acircumflexhookabove=7848;e.Acircumflexsmall=63458;e.Acircumflextilde=7850;e.Acute=63177;e.Acutesmall=63412;e.Acyrillic=1040;e.Adblgrave=512;e.Adieresis=196;e.Adieresiscyrillic=1234;e.Adieresismacron=478;e.Adieresissmall=63460;e.Adotbelow=7840;e.Adotmacron=480;e.Agrave=192;e.Agravesmall=63456;e.Ahookabove=7842;e.Aiecyrillic=1236;e.Ainvertedbreve=514;e.Alpha=913;e.Alphatonos=902;e.Amacron=256;e.Amonospace=65313;e.Aogonek=260;e.Aring=197;e.Aringacute=506;e.Aringbelow=7680;e.Aringsmall=63461;e.Asmall=63329;e.Atilde=195;e.Atildesmall=63459;e.Aybarmenian=1329;e.B=66;e.Bcircle=9399;e.Bdotaccent=7682;e.Bdotbelow=7684;e.Becyrillic=1041;e.Benarmenian=1330;e.Beta=914;e.Bhook=385;e.Blinebelow=7686;e.Bmonospace=65314;e.Brevesmall=63220;e.Bsmall=63330;e.Btopbar=386;e.C=67;e.Caarmenian=1342;e.Cacute=262;e.Caron=63178;e.Caronsmall=63221;e.Ccaron=268;e.Ccedilla=199;e.Ccedillaacute=7688;e.Ccedillasmall=63463;e.Ccircle=9400;e.Ccircumflex=264;e.Cdot=266;e.Cdotaccent=266;e.Cedillasmall=63416;e.Chaarmenian=1353;e.Cheabkhasiancyrillic=1212;e.Checyrillic=1063;e.Chedescenderabkhasiancyrillic=1214;e.Chedescendercyrillic=1206;e.Chedieresiscyrillic=1268;e.Cheharmenian=1347;e.Chekhakassiancyrillic=1227;e.Cheverticalstrokecyrillic=1208;e.Chi=935;e.Chook=391;e.Circumflexsmall=63222;e.Cmonospace=65315;e.Coarmenian=1361;e.Csmall=63331;e.D=68;e.DZ=497;e.DZcaron=452;e.Daarmenian=1332;e.Dafrican=393;e.Dcaron=270;e.Dcedilla=7696;e.Dcircle=9401;e.Dcircumflexbelow=7698;e.Dcroat=272;e.Ddotaccent=7690;e.Ddotbelow=7692;e.Decyrillic=1044;e.Deicoptic=1006;e.Delta=8710;e.Deltagreek=916;e.Dhook=394;e.Dieresis=63179;e.DieresisAcute=63180;e.DieresisGrave=63181;e.Dieresissmall=63400;e.Digammagreek=988;e.Djecyrillic=1026;e.Dlinebelow=7694;e.Dmonospace=65316;e.Dotaccentsmall=63223;e.Dslash=272;e.Dsmall=63332;e.Dtopbar=395;e.Dz=498;e.Dzcaron=453;e.Dzeabkhasiancyrillic=1248;e.Dzecyrillic=1029;e.Dzhecyrillic=1039;e.E=69;e.Eacute=201;e.Eacutesmall=63465;e.Ebreve=276;e.Ecaron=282;e.Ecedillabreve=7708;e.Echarmenian=1333;e.Ecircle=9402;e.Ecircumflex=202;e.Ecircumflexacute=7870;e.Ecircumflexbelow=7704;e.Ecircumflexdotbelow=7878;e.Ecircumflexgrave=7872;e.Ecircumflexhookabove=7874;e.Ecircumflexsmall=63466;e.Ecircumflextilde=7876;e.Ecyrillic=1028;e.Edblgrave=516;e.Edieresis=203;e.Edieresissmall=63467;e.Edot=278;e.Edotaccent=278;e.Edotbelow=7864;e.Efcyrillic=1060;e.Egrave=200;e.Egravesmall=63464;e.Eharmenian=1335;e.Ehookabove=7866;e.Eightroman=8551;e.Einvertedbreve=518;e.Eiotifiedcyrillic=1124;e.Elcyrillic=1051;e.Elevenroman=8554;e.Emacron=274;e.Emacronacute=7702;e.Emacrongrave=7700;e.Emcyrillic=1052;e.Emonospace=65317;e.Encyrillic=1053;e.Endescendercyrillic=1186;e.Eng=330;e.Enghecyrillic=1188;e.Enhookcyrillic=1223;e.Eogonek=280;e.Eopen=400;e.Epsilon=917;e.Epsilontonos=904;e.Ercyrillic=1056;e.Ereversed=398;e.Ereversedcyrillic=1069;e.Escyrillic=1057;e.Esdescendercyrillic=1194;e.Esh=425;e.Esmall=63333;e.Eta=919;e.Etarmenian=1336;e.Etatonos=905;e.Eth=208;e.Ethsmall=63472;e.Etilde=7868;e.Etildebelow=7706;e.Euro=8364;e.Ezh=439;e.Ezhcaron=494;e.Ezhreversed=440;e.F=70;e.Fcircle=9403;e.Fdotaccent=7710;e.Feharmenian=1366;e.Feicoptic=996;e.Fhook=401;e.Fitacyrillic=1138;e.Fiveroman=8548;e.Fmonospace=65318;e.Fourroman=8547;e.Fsmall=63334;e.G=71;e.GBsquare=13191;e.Gacute=500;e.Gamma=915;e.Gammaafrican=404;e.Gangiacoptic=1002;e.Gbreve=286;e.Gcaron=486;e.Gcedilla=290;e.Gcircle=9404;e.Gcircumflex=284;e.Gcommaaccent=290;e.Gdot=288;e.Gdotaccent=288;e.Gecyrillic=1043;e.Ghadarmenian=1346;e.Ghemiddlehookcyrillic=1172;e.Ghestrokecyrillic=1170;e.Gheupturncyrillic=1168;e.Ghook=403;e.Gimarmenian=1331;e.Gjecyrillic=1027;e.Gmacron=7712;e.Gmonospace=65319;e.Grave=63182;e.Gravesmall=63328;e.Gsmall=63335;e.Gsmallhook=667;e.Gstroke=484;e.H=72;e.H18533=9679;e.H18543=9642;e.H18551=9643;e.H22073=9633;e.HPsquare=13259;e.Haabkhasiancyrillic=1192;e.Hadescendercyrillic=1202;e.Hardsigncyrillic=1066;e.Hbar=294;e.Hbrevebelow=7722;e.Hcedilla=7720;e.Hcircle=9405;e.Hcircumflex=292;e.Hdieresis=7718;e.Hdotaccent=7714;e.Hdotbelow=7716;e.Hmonospace=65320;e.Hoarmenian=1344;e.Horicoptic=1e3;e.Hsmall=63336;e.Hungarumlaut=63183;e.Hungarumlautsmall=63224;e.Hzsquare=13200;e.I=73;e.IAcyrillic=1071;e.IJ=306;e.IUcyrillic=1070;e.Iacute=205;e.Iacutesmall=63469;e.Ibreve=300;e.Icaron=463;e.Icircle=9406;e.Icircumflex=206;e.Icircumflexsmall=63470;e.Icyrillic=1030;e.Idblgrave=520;e.Idieresis=207;e.Idieresisacute=7726;e.Idieresiscyrillic=1252;e.Idieresissmall=63471;e.Idot=304;e.Idotaccent=304;e.Idotbelow=7882;e.Iebrevecyrillic=1238;e.Iecyrillic=1045;e.Ifraktur=8465;e.Igrave=204;e.Igravesmall=63468;e.Ihookabove=7880;e.Iicyrillic=1048;e.Iinvertedbreve=522;e.Iishortcyrillic=1049;e.Imacron=298;e.Imacroncyrillic=1250;e.Imonospace=65321;e.Iniarmenian=1339;e.Iocyrillic=1025;e.Iogonek=302;e.Iota=921;e.Iotaafrican=406;e.Iotadieresis=938;e.Iotatonos=906;e.Ismall=63337;e.Istroke=407;e.Itilde=296;e.Itildebelow=7724;e.Izhitsacyrillic=1140;e.Izhitsadblgravecyrillic=1142;e.J=74;e.Jaarmenian=1345;e.Jcircle=9407;e.Jcircumflex=308;e.Jecyrillic=1032;e.Jheharmenian=1355;e.Jmonospace=65322;e.Jsmall=63338;e.K=75;e.KBsquare=13189;e.KKsquare=13261;e.Kabashkircyrillic=1184;e.Kacute=7728;e.Kacyrillic=1050;e.Kadescendercyrillic=1178;e.Kahookcyrillic=1219;e.Kappa=922;e.Kastrokecyrillic=1182;e.Kaverticalstrokecyrillic=1180;e.Kcaron=488;e.Kcedilla=310;e.Kcircle=9408;e.Kcommaaccent=310;e.Kdotbelow=7730;e.Keharmenian=1364;e.Kenarmenian=1343;e.Khacyrillic=1061;e.Kheicoptic=998;e.Khook=408;e.Kjecyrillic=1036;e.Klinebelow=7732;e.Kmonospace=65323;e.Koppacyrillic=1152;e.Koppagreek=990;e.Ksicyrillic=1134;e.Ksmall=63339;e.L=76;e.LJ=455;e.LL=63167;e.Lacute=313;e.Lambda=923;e.Lcaron=317;e.Lcedilla=315;e.Lcircle=9409;e.Lcircumflexbelow=7740;e.Lcommaaccent=315;e.Ldot=319;e.Ldotaccent=319;e.Ldotbelow=7734;e.Ldotbelowmacron=7736;e.Liwnarmenian=1340;e.Lj=456;e.Ljecyrillic=1033;e.Llinebelow=7738;e.Lmonospace=65324;e.Lslash=321;e.Lslashsmall=63225;e.Lsmall=63340;e.M=77;e.MBsquare=13190;e.Macron=63184;e.Macronsmall=63407;e.Macute=7742;e.Mcircle=9410;e.Mdotaccent=7744;e.Mdotbelow=7746;e.Menarmenian=1348;e.Mmonospace=65325;e.Msmall=63341;e.Mturned=412;e.Mu=924;e.N=78;e.NJ=458;e.Nacute=323;e.Ncaron=327;e.Ncedilla=325;e.Ncircle=9411;e.Ncircumflexbelow=7754;e.Ncommaaccent=325;e.Ndotaccent=7748;e.Ndotbelow=7750;e.Nhookleft=413;e.Nineroman=8552;e.Nj=459;e.Njecyrillic=1034;e.Nlinebelow=7752;e.Nmonospace=65326;e.Nowarmenian=1350;e.Nsmall=63342;e.Ntilde=209;e.Ntildesmall=63473;e.Nu=925;e.O=79;e.OE=338;e.OEsmall=63226;e.Oacute=211;e.Oacutesmall=63475;e.Obarredcyrillic=1256;e.Obarreddieresiscyrillic=1258;e.Obreve=334;e.Ocaron=465;e.Ocenteredtilde=415;e.Ocircle=9412;e.Ocircumflex=212;e.Ocircumflexacute=7888;e.Ocircumflexdotbelow=7896;e.Ocircumflexgrave=7890;e.Ocircumflexhookabove=7892;e.Ocircumflexsmall=63476;e.Ocircumflextilde=7894;e.Ocyrillic=1054;e.Odblacute=336;e.Odblgrave=524;e.Odieresis=214;e.Odieresiscyrillic=1254;e.Odieresissmall=63478;e.Odotbelow=7884;e.Ogoneksmall=63227;e.Ograve=210;e.Ogravesmall=63474;e.Oharmenian=1365;e.Ohm=8486;e.Ohookabove=7886;e.Ohorn=416;e.Ohornacute=7898;e.Ohorndotbelow=7906;e.Ohorngrave=7900;e.Ohornhookabove=7902;e.Ohorntilde=7904;e.Ohungarumlaut=336;e.Oi=418;e.Oinvertedbreve=526;e.Omacron=332;e.Omacronacute=7762;e.Omacrongrave=7760;e.Omega=8486;e.Omegacyrillic=1120;e.Omegagreek=937;e.Omegaroundcyrillic=1146;e.Omegatitlocyrillic=1148;e.Omegatonos=911;e.Omicron=927;e.Omicrontonos=908;e.Omonospace=65327;e.Oneroman=8544;e.Oogonek=490;e.Oogonekmacron=492;e.Oopen=390;e.Oslash=216;e.Oslashacute=510;e.Oslashsmall=63480;e.Osmall=63343;e.Ostrokeacute=510;e.Otcyrillic=1150;e.Otilde=213;e.Otildeacute=7756;e.Otildedieresis=7758;e.Otildesmall=63477;e.P=80;e.Pacute=7764;e.Pcircle=9413;e.Pdotaccent=7766;e.Pecyrillic=1055;e.Peharmenian=1354;e.Pemiddlehookcyrillic=1190;e.Phi=934;e.Phook=420;e.Pi=928;e.Piwrarmenian=1363;e.Pmonospace=65328;e.Psi=936;e.Psicyrillic=1136;e.Psmall=63344;e.Q=81;e.Qcircle=9414;e.Qmonospace=65329;e.Qsmall=63345;e.R=82;e.Raarmenian=1356;e.Racute=340;e.Rcaron=344;e.Rcedilla=342;e.Rcircle=9415;e.Rcommaaccent=342;e.Rdblgrave=528;e.Rdotaccent=7768;e.Rdotbelow=7770;e.Rdotbelowmacron=7772;e.Reharmenian=1360;e.Rfraktur=8476;e.Rho=929;e.Ringsmall=63228;e.Rinvertedbreve=530;e.Rlinebelow=7774;e.Rmonospace=65330;e.Rsmall=63346;e.Rsmallinverted=641;e.Rsmallinvertedsuperior=694;e.S=83;e.SF010000=9484;e.SF020000=9492;e.SF030000=9488;e.SF040000=9496;e.SF050000=9532;e.SF060000=9516;e.SF070000=9524;e.SF080000=9500;e.SF090000=9508;e.SF100000=9472;e.SF110000=9474;e.SF190000=9569;e.SF200000=9570;e.SF210000=9558;e.SF220000=9557;e.SF230000=9571;e.SF240000=9553;e.SF250000=9559;e.SF260000=9565;e.SF270000=9564;e.SF280000=9563;e.SF360000=9566;e.SF370000=9567;e.SF380000=9562;e.SF390000=9556;e.SF400000=9577;e.SF410000=9574;e.SF420000=9568;e.SF430000=9552;e.SF440000=9580;e.SF450000=9575;e.SF460000=9576;e.SF470000=9572;e.SF480000=9573;e.SF490000=9561;e.SF500000=9560;e.SF510000=9554;e.SF520000=9555;e.SF530000=9579;e.SF540000=9578;e.Sacute=346;e.Sacutedotaccent=7780;e.Sampigreek=992;e.Scaron=352;e.Scarondotaccent=7782;e.Scaronsmall=63229;e.Scedilla=350;e.Schwa=399;e.Schwacyrillic=1240;e.Schwadieresiscyrillic=1242;e.Scircle=9416;e.Scircumflex=348;e.Scommaaccent=536;e.Sdotaccent=7776;e.Sdotbelow=7778;e.Sdotbelowdotaccent=7784;e.Seharmenian=1357;e.Sevenroman=8550;e.Shaarmenian=1351;e.Shacyrillic=1064;e.Shchacyrillic=1065;e.Sheicoptic=994;e.Shhacyrillic=1210;e.Shimacoptic=1004;e.Sigma=931;e.Sixroman=8549;e.Smonospace=65331;e.Softsigncyrillic=1068;e.Ssmall=63347;e.Stigmagreek=986;e.T=84;e.Tau=932;e.Tbar=358;e.Tcaron=356;e.Tcedilla=354;e.Tcircle=9417;e.Tcircumflexbelow=7792;e.Tcommaaccent=354;e.Tdotaccent=7786;e.Tdotbelow=7788;e.Tecyrillic=1058;e.Tedescendercyrillic=1196;e.Tenroman=8553;e.Tetsecyrillic=1204;e.Theta=920;e.Thook=428;e.Thorn=222;e.Thornsmall=63486;e.Threeroman=8546;e.Tildesmall=63230;e.Tiwnarmenian=1359;e.Tlinebelow=7790;e.Tmonospace=65332;e.Toarmenian=1337;e.Tonefive=444;e.Tonesix=388;e.Tonetwo=423;e.Tretroflexhook=430;e.Tsecyrillic=1062;e.Tshecyrillic=1035;e.Tsmall=63348;e.Twelveroman=8555;e.Tworoman=8545;e.U=85;e.Uacute=218;e.Uacutesmall=63482;e.Ubreve=364;e.Ucaron=467;e.Ucircle=9418;e.Ucircumflex=219;e.Ucircumflexbelow=7798;e.Ucircumflexsmall=63483;e.Ucyrillic=1059;e.Udblacute=368;e.Udblgrave=532;e.Udieresis=220;e.Udieresisacute=471;e.Udieresisbelow=7794;e.Udieresiscaron=473;e.Udieresiscyrillic=1264;e.Udieresisgrave=475;e.Udieresismacron=469;e.Udieresissmall=63484;e.Udotbelow=7908;e.Ugrave=217;e.Ugravesmall=63481;e.Uhookabove=7910;e.Uhorn=431;e.Uhornacute=7912;e.Uhorndotbelow=7920;e.Uhorngrave=7914;e.Uhornhookabove=7916;e.Uhorntilde=7918;e.Uhungarumlaut=368;e.Uhungarumlautcyrillic=1266;e.Uinvertedbreve=534;e.Ukcyrillic=1144;e.Umacron=362;e.Umacroncyrillic=1262;e.Umacrondieresis=7802;e.Umonospace=65333;e.Uogonek=370;e.Upsilon=933;e.Upsilon1=978;e.Upsilonacutehooksymbolgreek=979;e.Upsilonafrican=433;e.Upsilondieresis=939;e.Upsilondieresishooksymbolgreek=980;e.Upsilonhooksymbol=978;e.Upsilontonos=910;e.Uring=366;e.Ushortcyrillic=1038;e.Usmall=63349;e.Ustraightcyrillic=1198;e.Ustraightstrokecyrillic=1200;e.Utilde=360;e.Utildeacute=7800;e.Utildebelow=7796;e.V=86;e.Vcircle=9419;e.Vdotbelow=7806;e.Vecyrillic=1042;e.Vewarmenian=1358;e.Vhook=434;e.Vmonospace=65334;e.Voarmenian=1352;e.Vsmall=63350;e.Vtilde=7804;e.W=87;e.Wacute=7810;e.Wcircle=9420;e.Wcircumflex=372;e.Wdieresis=7812;e.Wdotaccent=7814;e.Wdotbelow=7816;e.Wgrave=7808;e.Wmonospace=65335;e.Wsmall=63351;e.X=88;e.Xcircle=9421;e.Xdieresis=7820;e.Xdotaccent=7818;e.Xeharmenian=1341;e.Xi=926;e.Xmonospace=65336;e.Xsmall=63352;e.Y=89;e.Yacute=221;e.Yacutesmall=63485;e.Yatcyrillic=1122;e.Ycircle=9422;e.Ycircumflex=374;e.Ydieresis=376;e.Ydieresissmall=63487;e.Ydotaccent=7822;e.Ydotbelow=7924;e.Yericyrillic=1067;e.Yerudieresiscyrillic=1272;e.Ygrave=7922;e.Yhook=435;e.Yhookabove=7926;e.Yiarmenian=1349;e.Yicyrillic=1031;e.Yiwnarmenian=1362;e.Ymonospace=65337;e.Ysmall=63353;e.Ytilde=7928;e.Yusbigcyrillic=1130;e.Yusbigiotifiedcyrillic=1132;e.Yuslittlecyrillic=1126;e.Yuslittleiotifiedcyrillic=1128;e.Z=90;e.Zaarmenian=1334;e.Zacute=377;e.Zcaron=381;e.Zcaronsmall=63231;e.Zcircle=9423;e.Zcircumflex=7824;e.Zdot=379;e.Zdotaccent=379;e.Zdotbelow=7826;e.Zecyrillic=1047;e.Zedescendercyrillic=1176;e.Zedieresiscyrillic=1246;e.Zeta=918;e.Zhearmenian=1338;e.Zhebrevecyrillic=1217;e.Zhecyrillic=1046;e.Zhedescendercyrillic=1174;e.Zhedieresiscyrillic=1244;e.Zlinebelow=7828;e.Zmonospace=65338;e.Zsmall=63354;e.Zstroke=437;e.a=97;e.aabengali=2438;e.aacute=225;e.aadeva=2310;e.aagujarati=2694;e.aagurmukhi=2566;e.aamatragurmukhi=2622;e.aarusquare=13059;e.aavowelsignbengali=2494;e.aavowelsigndeva=2366;e.aavowelsigngujarati=2750;e.abbreviationmarkarmenian=1375;e.abbreviationsigndeva=2416;e.abengali=2437;e.abopomofo=12570;e.abreve=259;e.abreveacute=7855;e.abrevecyrillic=1233;e.abrevedotbelow=7863;e.abrevegrave=7857;e.abrevehookabove=7859;e.abrevetilde=7861;e.acaron=462;e.acircle=9424;e.acircumflex=226;e.acircumflexacute=7845;e.acircumflexdotbelow=7853;e.acircumflexgrave=7847;e.acircumflexhookabove=7849;e.acircumflextilde=7851;e.acute=180;e.acutebelowcmb=791;e.acutecmb=769;e.acutecomb=769;e.acutedeva=2388;e.acutelowmod=719;e.acutetonecmb=833;e.acyrillic=1072;e.adblgrave=513;e.addakgurmukhi=2673;e.adeva=2309;e.adieresis=228;e.adieresiscyrillic=1235;e.adieresismacron=479;e.adotbelow=7841;e.adotmacron=481;e.ae=230;e.aeacute=509;e.aekorean=12624;e.aemacron=483;e.afii00208=8213;e.afii08941=8356;e.afii10017=1040;e.afii10018=1041;e.afii10019=1042;e.afii10020=1043;e.afii10021=1044;e.afii10022=1045;e.afii10023=1025;e.afii10024=1046;e.afii10025=1047;e.afii10026=1048;e.afii10027=1049;e.afii10028=1050;e.afii10029=1051;e.afii10030=1052;e.afii10031=1053;e.afii10032=1054;e.afii10033=1055;e.afii10034=1056;e.afii10035=1057;e.afii10036=1058;e.afii10037=1059;e.afii10038=1060;e.afii10039=1061;e.afii10040=1062;e.afii10041=1063;e.afii10042=1064;e.afii10043=1065;e.afii10044=1066;e.afii10045=1067;e.afii10046=1068;e.afii10047=1069;e.afii10048=1070;e.afii10049=1071;e.afii10050=1168;e.afii10051=1026;e.afii10052=1027;e.afii10053=1028;e.afii10054=1029;e.afii10055=1030;e.afii10056=1031;e.afii10057=1032;e.afii10058=1033;e.afii10059=1034;e.afii10060=1035;e.afii10061=1036;e.afii10062=1038;e.afii10063=63172;e.afii10064=63173;e.afii10065=1072;e.afii10066=1073;e.afii10067=1074;e.afii10068=1075;e.afii10069=1076;e.afii10070=1077;e.afii10071=1105;e.afii10072=1078;e.afii10073=1079;e.afii10074=1080;e.afii10075=1081;e.afii10076=1082;e.afii10077=1083;e.afii10078=1084;e.afii10079=1085;e.afii10080=1086;e.afii10081=1087;e.afii10082=1088;e.afii10083=1089;e.afii10084=1090;e.afii10085=1091;e.afii10086=1092;e.afii10087=1093;e.afii10088=1094;e.afii10089=1095;e.afii10090=1096;e.afii10091=1097;e.afii10092=1098;e.afii10093=1099;e.afii10094=1100;e.afii10095=1101;e.afii10096=1102;e.afii10097=1103;e.afii10098=1169;e.afii10099=1106;e.afii10100=1107;e.afii10101=1108;e.afii10102=1109;e.afii10103=1110;e.afii10104=1111;e.afii10105=1112;e.afii10106=1113;e.afii10107=1114;e.afii10108=1115;e.afii10109=1116;e.afii10110=1118;e.afii10145=1039;e.afii10146=1122;e.afii10147=1138;e.afii10148=1140;e.afii10192=63174;e.afii10193=1119;e.afii10194=1123;e.afii10195=1139;e.afii10196=1141;e.afii10831=63175;e.afii10832=63176;e.afii10846=1241;e.afii299=8206;e.afii300=8207;e.afii301=8205;e.afii57381=1642;e.afii57388=1548;e.afii57392=1632;e.afii57393=1633;e.afii57394=1634;e.afii57395=1635;e.afii57396=1636;e.afii57397=1637;e.afii57398=1638;e.afii57399=1639;e.afii57400=1640;e.afii57401=1641;e.afii57403=1563;e.afii57407=1567;e.afii57409=1569;e.afii57410=1570;e.afii57411=1571;e.afii57412=1572;e.afii57413=1573;e.afii57414=1574;e.afii57415=1575;e.afii57416=1576;e.afii57417=1577;e.afii57418=1578;e.afii57419=1579;e.afii57420=1580;e.afii57421=1581;e.afii57422=1582;e.afii57423=1583;e.afii57424=1584;e.afii57425=1585;e.afii57426=1586;e.afii57427=1587;e.afii57428=1588;e.afii57429=1589;e.afii57430=1590;e.afii57431=1591;e.afii57432=1592;e.afii57433=1593;e.afii57434=1594;e.afii57440=1600;e.afii57441=1601;e.afii57442=1602;e.afii57443=1603;e.afii57444=1604;e.afii57445=1605;e.afii57446=1606;e.afii57448=1608;e.afii57449=1609;e.afii57450=1610;e.afii57451=1611;e.afii57452=1612;e.afii57453=1613;e.afii57454=1614;e.afii57455=1615;e.afii57456=1616;e.afii57457=1617;e.afii57458=1618;e.afii57470=1607;e.afii57505=1700;e.afii57506=1662;e.afii57507=1670;e.afii57508=1688;e.afii57509=1711;e.afii57511=1657;e.afii57512=1672;e.afii57513=1681;e.afii57514=1722;e.afii57519=1746;e.afii57534=1749;e.afii57636=8362;e.afii57645=1470;e.afii57658=1475;e.afii57664=1488;e.afii57665=1489;e.afii57666=1490;e.afii57667=1491;e.afii57668=1492;e.afii57669=1493;e.afii57670=1494;e.afii57671=1495;e.afii57672=1496;e.afii57673=1497;e.afii57674=1498;e.afii57675=1499;e.afii57676=1500;e.afii57677=1501;e.afii57678=1502;e.afii57679=1503;e.afii57680=1504;e.afii57681=1505;e.afii57682=1506;e.afii57683=1507;e.afii57684=1508;e.afii57685=1509;e.afii57686=1510;e.afii57687=1511;e.afii57688=1512;e.afii57689=1513;e.afii57690=1514;e.afii57694=64298;e.afii57695=64299;e.afii57700=64331;e.afii57705=64287;e.afii57716=1520;e.afii57717=1521;e.afii57718=1522;e.afii57723=64309;e.afii57793=1460;e.afii57794=1461;e.afii57795=1462;e.afii57796=1467;e.afii57797=1464;e.afii57798=1463;e.afii57799=1456;e.afii57800=1458;e.afii57801=1457;e.afii57802=1459;e.afii57803=1474;e.afii57804=1473;e.afii57806=1465;e.afii57807=1468;e.afii57839=1469;e.afii57841=1471;e.afii57842=1472;e.afii57929=700;e.afii61248=8453;e.afii61289=8467;e.afii61352=8470;e.afii61573=8236;e.afii61574=8237;e.afii61575=8238;e.afii61664=8204;e.afii63167=1645;e.afii64937=701;e.agrave=224;e.agujarati=2693;e.agurmukhi=2565;e.ahiragana=12354;e.ahookabove=7843;e.aibengali=2448;e.aibopomofo=12574;e.aideva=2320;e.aiecyrillic=1237;e.aigujarati=2704;e.aigurmukhi=2576;e.aimatragurmukhi=2632;e.ainarabic=1593;e.ainfinalarabic=65226;e.aininitialarabic=65227;e.ainmedialarabic=65228;e.ainvertedbreve=515;e.aivowelsignbengali=2504;e.aivowelsigndeva=2376;e.aivowelsigngujarati=2760;e.akatakana=12450;e.akatakanahalfwidth=65393;e.akorean=12623;e.alef=1488;e.alefarabic=1575;e.alefdageshhebrew=64304;e.aleffinalarabic=65166;e.alefhamzaabovearabic=1571;e.alefhamzaabovefinalarabic=65156;e.alefhamzabelowarabic=1573;e.alefhamzabelowfinalarabic=65160;e.alefhebrew=1488;e.aleflamedhebrew=64335;e.alefmaddaabovearabic=1570;e.alefmaddaabovefinalarabic=65154;e.alefmaksuraarabic=1609;e.alefmaksurafinalarabic=65264;e.alefmaksurainitialarabic=65267;e.alefmaksuramedialarabic=65268;e.alefpatahhebrew=64302;e.alefqamatshebrew=64303;e.aleph=8501;e.allequal=8780;e.alpha=945;e.alphatonos=940;e.amacron=257;e.amonospace=65345;e.ampersand=38;e.ampersandmonospace=65286;e.ampersandsmall=63270;e.amsquare=13250;e.anbopomofo=12578;e.angbopomofo=12580;e.angbracketleft=12296;e.angbracketright=12297;e.angkhankhuthai=3674;e.angle=8736;e.anglebracketleft=12296;e.anglebracketleftvertical=65087;e.anglebracketright=12297;e.anglebracketrightvertical=65088;e.angleleft=9001;e.angleright=9002;e.angstrom=8491;e.anoteleia=903;e.anudattadeva=2386;e.anusvarabengali=2434;e.anusvaradeva=2306;e.anusvaragujarati=2690;e.aogonek=261;e.apaatosquare=13056;e.aparen=9372;e.apostrophearmenian=1370;e.apostrophemod=700;e.apple=63743;e.approaches=8784;e.approxequal=8776;e.approxequalorimage=8786;e.approximatelyequal=8773;e.araeaekorean=12686;e.araeakorean=12685;e.arc=8978;e.arighthalfring=7834;e.aring=229;e.aringacute=507;e.aringbelow=7681;e.arrowboth=8596;e.arrowdashdown=8675;e.arrowdashleft=8672;e.arrowdashright=8674;e.arrowdashup=8673;e.arrowdblboth=8660;e.arrowdbldown=8659;e.arrowdblleft=8656;e.arrowdblright=8658;e.arrowdblup=8657;e.arrowdown=8595;e.arrowdownleft=8601;e.arrowdownright=8600;e.arrowdownwhite=8681;e.arrowheaddownmod=709;e.arrowheadleftmod=706;e.arrowheadrightmod=707;e.arrowheadupmod=708;e.arrowhorizex=63719;e.arrowleft=8592;e.arrowleftdbl=8656;e.arrowleftdblstroke=8653;e.arrowleftoverright=8646;e.arrowleftwhite=8678;e.arrowright=8594;e.arrowrightdblstroke=8655;e.arrowrightheavy=10142;e.arrowrightoverleft=8644;e.arrowrightwhite=8680;e.arrowtableft=8676;e.arrowtabright=8677;e.arrowup=8593;e.arrowupdn=8597;e.arrowupdnbse=8616;e.arrowupdownbase=8616;e.arrowupleft=8598;e.arrowupleftofdown=8645;e.arrowupright=8599;e.arrowupwhite=8679;e.arrowvertex=63718;e.asciicircum=94;e.asciicircummonospace=65342;e.asciitilde=126;e.asciitildemonospace=65374;e.ascript=593;e.ascriptturned=594;e.asmallhiragana=12353;e.asmallkatakana=12449;e.asmallkatakanahalfwidth=65383;e.asterisk=42;e.asteriskaltonearabic=1645;e.asteriskarabic=1645;e.asteriskmath=8727;e.asteriskmonospace=65290;e.asterisksmall=65121;e.asterism=8258;e.asuperior=63209;e.asymptoticallyequal=8771;e.at=64;e.atilde=227;e.atmonospace=65312;e.atsmall=65131;e.aturned=592;e.aubengali=2452;e.aubopomofo=12576;e.audeva=2324;e.augujarati=2708;e.augurmukhi=2580;e.aulengthmarkbengali=2519;e.aumatragurmukhi=2636;e.auvowelsignbengali=2508;e.auvowelsigndeva=2380;e.auvowelsigngujarati=2764;e.avagrahadeva=2365;e.aybarmenian=1377;e.ayin=1506;e.ayinaltonehebrew=64288;e.ayinhebrew=1506;e.b=98;e.babengali=2476;e.backslash=92;e.backslashmonospace=65340;e.badeva=2348;e.bagujarati=2732;e.bagurmukhi=2604;e.bahiragana=12400;e.bahtthai=3647;e.bakatakana=12496;e.bar=124;e.barmonospace=65372;e.bbopomofo=12549;e.bcircle=9425;e.bdotaccent=7683;e.bdotbelow=7685;e.beamedsixteenthnotes=9836;e.because=8757;e.becyrillic=1073;e.beharabic=1576;e.behfinalarabic=65168;e.behinitialarabic=65169;e.behiragana=12409;e.behmedialarabic=65170;e.behmeeminitialarabic=64671;e.behmeemisolatedarabic=64520;e.behnoonfinalarabic=64621;e.bekatakana=12505;e.benarmenian=1378;e.bet=1489;e.beta=946;e.betasymbolgreek=976;e.betdagesh=64305;e.betdageshhebrew=64305;e.bethebrew=1489;e.betrafehebrew=64332;e.bhabengali=2477;e.bhadeva=2349;e.bhagujarati=2733;e.bhagurmukhi=2605;e.bhook=595;e.bihiragana=12403;e.bikatakana=12499;e.bilabialclick=664;e.bindigurmukhi=2562;e.birusquare=13105;e.blackcircle=9679;e.blackdiamond=9670;e.blackdownpointingtriangle=9660;e.blackleftpointingpointer=9668;e.blackleftpointingtriangle=9664;e.blacklenticularbracketleft=12304;e.blacklenticularbracketleftvertical=65083;e.blacklenticularbracketright=12305;e.blacklenticularbracketrightvertical=65084;e.blacklowerlefttriangle=9699;e.blacklowerrighttriangle=9698;e.blackrectangle=9644;e.blackrightpointingpointer=9658;e.blackrightpointingtriangle=9654;e.blacksmallsquare=9642;e.blacksmilingface=9787;e.blacksquare=9632;e.blackstar=9733;e.blackupperlefttriangle=9700;e.blackupperrighttriangle=9701;e.blackuppointingsmalltriangle=9652;e.blackuppointingtriangle=9650;e.blank=9251;e.blinebelow=7687;e.block=9608;e.bmonospace=65346;e.bobaimaithai=3610;e.bohiragana=12412;e.bokatakana=12508;e.bparen=9373;e.bqsquare=13251;e.braceex=63732;e.braceleft=123;e.braceleftbt=63731;e.braceleftmid=63730;e.braceleftmonospace=65371;e.braceleftsmall=65115;e.bracelefttp=63729;e.braceleftvertical=65079;e.braceright=125;e.bracerightbt=63742;e.bracerightmid=63741;e.bracerightmonospace=65373;e.bracerightsmall=65116;e.bracerighttp=63740;e.bracerightvertical=65080;e.bracketleft=91;e.bracketleftbt=63728;e.bracketleftex=63727;e.bracketleftmonospace=65339;e.bracketlefttp=63726;e.bracketright=93;e.bracketrightbt=63739;e.bracketrightex=63738;e.bracketrightmonospace=65341;e.bracketrighttp=63737;e.breve=728;e.brevebelowcmb=814;e.brevecmb=774;e.breveinvertedbelowcmb=815;e.breveinvertedcmb=785;e.breveinverteddoublecmb=865;e.bridgebelowcmb=810;e.bridgeinvertedbelowcmb=826;e.brokenbar=166;e.bstroke=384;e.bsuperior=63210;e.btopbar=387;e.buhiragana=12406;e.bukatakana=12502;e.bullet=8226;e.bulletinverse=9688;e.bulletoperator=8729;e.bullseye=9678;e.c=99;e.caarmenian=1390;e.cabengali=2458;e.cacute=263;e.cadeva=2330;e.cagujarati=2714;e.cagurmukhi=2586;e.calsquare=13192;e.candrabindubengali=2433;e.candrabinducmb=784;e.candrabindudeva=2305;e.candrabindugujarati=2689;e.capslock=8682;e.careof=8453;e.caron=711;e.caronbelowcmb=812;e.caroncmb=780;e.carriagereturn=8629;e.cbopomofo=12568;e.ccaron=269;e.ccedilla=231;e.ccedillaacute=7689;e.ccircle=9426;e.ccircumflex=265;e.ccurl=597;e.cdot=267;e.cdotaccent=267;e.cdsquare=13253;e.cedilla=184;e.cedillacmb=807;e.cent=162;e.centigrade=8451;e.centinferior=63199;e.centmonospace=65504;e.centoldstyle=63394;e.centsuperior=63200;e.chaarmenian=1401;e.chabengali=2459;e.chadeva=2331;e.chagujarati=2715;e.chagurmukhi=2587;e.chbopomofo=12564;e.cheabkhasiancyrillic=1213;e.checkmark=10003;e.checyrillic=1095;e.chedescenderabkhasiancyrillic=1215;e.chedescendercyrillic=1207;e.chedieresiscyrillic=1269;e.cheharmenian=1395;e.chekhakassiancyrillic=1228;e.cheverticalstrokecyrillic=1209;e.chi=967;e.chieuchacirclekorean=12919;e.chieuchaparenkorean=12823;e.chieuchcirclekorean=12905;e.chieuchkorean=12618;e.chieuchparenkorean=12809;e.chochangthai=3594;e.chochanthai=3592;e.chochingthai=3593;e.chochoethai=3596;e.chook=392;e.cieucacirclekorean=12918;e.cieucaparenkorean=12822;e.cieuccirclekorean=12904;e.cieuckorean=12616;e.cieucparenkorean=12808;e.cieucuparenkorean=12828;e.circle=9675;e.circlecopyrt=169;e.circlemultiply=8855;e.circleot=8857;e.circleplus=8853;e.circlepostalmark=12342;e.circlewithlefthalfblack=9680;e.circlewithrighthalfblack=9681;e.circumflex=710;e.circumflexbelowcmb=813;e.circumflexcmb=770;e.clear=8999;e.clickalveolar=450;e.clickdental=448;e.clicklateral=449;e.clickretroflex=451;e.club=9827;e.clubsuitblack=9827;e.clubsuitwhite=9831;e.cmcubedsquare=13220;e.cmonospace=65347;e.cmsquaredsquare=13216;e.coarmenian=1409;e.colon=58;e.colonmonetary=8353;e.colonmonospace=65306;e.colonsign=8353;e.colonsmall=65109;e.colontriangularhalfmod=721;e.colontriangularmod=720;e.comma=44;e.commaabovecmb=787;e.commaaboverightcmb=789;e.commaaccent=63171;e.commaarabic=1548;e.commaarmenian=1373;e.commainferior=63201;e.commamonospace=65292;e.commareversedabovecmb=788;e.commareversedmod=701;e.commasmall=65104;e.commasuperior=63202;e.commaturnedabovecmb=786;e.commaturnedmod=699;e.compass=9788;e.congruent=8773;e.contourintegral=8750;e.control=8963;e.controlACK=6;e.controlBEL=7;e.controlBS=8;e.controlCAN=24;e.controlCR=13;e.controlDC1=17;e.controlDC2=18;e.controlDC3=19;e.controlDC4=20;e.controlDEL=127;e.controlDLE=16;e.controlEM=25;e.controlENQ=5;e.controlEOT=4;e.controlESC=27;e.controlETB=23;e.controlETX=3;e.controlFF=12;e.controlFS=28;e.controlGS=29;e.controlHT=9;e.controlLF=10;e.controlNAK=21;e.controlNULL=0;e.controlRS=30;e.controlSI=15;e.controlSO=14;e.controlSOT=2;e.controlSTX=1;e.controlSUB=26;e.controlSYN=22;e.controlUS=31;e.controlVT=11;e.copyright=169;e.copyrightsans=63721;e.copyrightserif=63193;e.cornerbracketleft=12300;e.cornerbracketlefthalfwidth=65378;e.cornerbracketleftvertical=65089;e.cornerbracketright=12301;e.cornerbracketrighthalfwidth=65379;e.cornerbracketrightvertical=65090;e.corporationsquare=13183;e.cosquare=13255;e.coverkgsquare=13254;e.cparen=9374;e.cruzeiro=8354;e.cstretched=663;e.curlyand=8911;e.curlyor=8910;e.currency=164;e.cyrBreve=63185;e.cyrFlex=63186;e.cyrbreve=63188;e.cyrflex=63189;e.d=100;e.daarmenian=1380;e.dabengali=2470;e.dadarabic=1590;e.dadeva=2342;e.dadfinalarabic=65214;e.dadinitialarabic=65215;e.dadmedialarabic=65216;e.dagesh=1468;e.dageshhebrew=1468;e.dagger=8224;e.daggerdbl=8225;e.dagujarati=2726;e.dagurmukhi=2598;e.dahiragana=12384;e.dakatakana=12480;e.dalarabic=1583;e.dalet=1491;e.daletdagesh=64307;e.daletdageshhebrew=64307;e.dalethebrew=1491;e.dalfinalarabic=65194;e.dammaarabic=1615;e.dammalowarabic=1615;e.dammatanaltonearabic=1612;e.dammatanarabic=1612;e.danda=2404;e.dargahebrew=1447;e.dargalefthebrew=1447;e.dasiapneumatacyrilliccmb=1157;e.dblGrave=63187;e.dblanglebracketleft=12298;e.dblanglebracketleftvertical=65085;e.dblanglebracketright=12299;e.dblanglebracketrightvertical=65086;e.dblarchinvertedbelowcmb=811;e.dblarrowleft=8660;e.dblarrowright=8658;e.dbldanda=2405;e.dblgrave=63190;e.dblgravecmb=783;e.dblintegral=8748;e.dbllowline=8215;e.dbllowlinecmb=819;e.dbloverlinecmb=831;e.dblprimemod=698;e.dblverticalbar=8214;e.dblverticallineabovecmb=782;e.dbopomofo=12553;e.dbsquare=13256;e.dcaron=271;e.dcedilla=7697;e.dcircle=9427;e.dcircumflexbelow=7699;e.dcroat=273;e.ddabengali=2465;e.ddadeva=2337;e.ddagujarati=2721;e.ddagurmukhi=2593;e.ddalarabic=1672;e.ddalfinalarabic=64393;e.dddhadeva=2396;e.ddhabengali=2466;e.ddhadeva=2338;e.ddhagujarati=2722;e.ddhagurmukhi=2594;e.ddotaccent=7691;e.ddotbelow=7693;e.decimalseparatorarabic=1643;e.decimalseparatorpersian=1643;e.decyrillic=1076;e.degree=176;e.dehihebrew=1453;e.dehiragana=12391;e.deicoptic=1007;e.dekatakana=12487;e.deleteleft=9003;e.deleteright=8998;e.delta=948;e.deltaturned=397;e.denominatorminusonenumeratorbengali=2552;e.dezh=676;e.dhabengali=2471;e.dhadeva=2343;e.dhagujarati=2727;e.dhagurmukhi=2599;e.dhook=599;e.dialytikatonos=901;e.dialytikatonoscmb=836;e.diamond=9830;e.diamondsuitwhite=9826;e.dieresis=168;e.dieresisacute=63191;e.dieresisbelowcmb=804;e.dieresiscmb=776;e.dieresisgrave=63192;e.dieresistonos=901;e.dihiragana=12386;e.dikatakana=12482;e.dittomark=12291;e.divide=247;e.divides=8739;e.divisionslash=8725;e.djecyrillic=1106;e.dkshade=9619;e.dlinebelow=7695;e.dlsquare=13207;e.dmacron=273;e.dmonospace=65348;e.dnblock=9604;e.dochadathai=3598;e.dodekthai=3604;e.dohiragana=12393;e.dokatakana=12489;e.dollar=36;e.dollarinferior=63203;e.dollarmonospace=65284;e.dollaroldstyle=63268;e.dollarsmall=65129;e.dollarsuperior=63204;e.dong=8363;e.dorusquare=13094;e.dotaccent=729;e.dotaccentcmb=775;e.dotbelowcmb=803;e.dotbelowcomb=803;e.dotkatakana=12539;e.dotlessi=305;e.dotlessj=63166;e.dotlessjstrokehook=644;e.dotmath=8901;e.dottedcircle=9676;e.doubleyodpatah=64287;e.doubleyodpatahhebrew=64287;e.downtackbelowcmb=798;e.downtackmod=725;e.dparen=9375;e.dsuperior=63211;e.dtail=598;e.dtopbar=396;e.duhiragana=12389;e.dukatakana=12485;e.dz=499;e.dzaltone=675;e.dzcaron=454;e.dzcurl=677;e.dzeabkhasiancyrillic=1249;e.dzecyrillic=1109;e.dzhecyrillic=1119;e.e=101;e.eacute=233;e.earth=9793;e.ebengali=2447;e.ebopomofo=12572;e.ebreve=277;e.ecandradeva=2317;e.ecandragujarati=2701;e.ecandravowelsigndeva=2373;e.ecandravowelsigngujarati=2757;e.ecaron=283;e.ecedillabreve=7709;e.echarmenian=1381;e.echyiwnarmenian=1415;e.ecircle=9428;e.ecircumflex=234;e.ecircumflexacute=7871;e.ecircumflexbelow=7705;e.ecircumflexdotbelow=7879;e.ecircumflexgrave=7873;e.ecircumflexhookabove=7875;e.ecircumflextilde=7877;e.ecyrillic=1108;e.edblgrave=517;e.edeva=2319;e.edieresis=235;e.edot=279;e.edotaccent=279;e.edotbelow=7865;e.eegurmukhi=2575;e.eematragurmukhi=2631;e.efcyrillic=1092;e.egrave=232;e.egujarati=2703;e.eharmenian=1383;e.ehbopomofo=12573;e.ehiragana=12360;e.ehookabove=7867;e.eibopomofo=12575;e.eight=56;e.eightarabic=1640;e.eightbengali=2542;e.eightcircle=9319;e.eightcircleinversesansserif=10129;e.eightdeva=2414;e.eighteencircle=9329;e.eighteenparen=9349;e.eighteenperiod=9369;e.eightgujarati=2798;e.eightgurmukhi=2670;e.eighthackarabic=1640;e.eighthangzhou=12328;e.eighthnotebeamed=9835;e.eightideographicparen=12839;e.eightinferior=8328;e.eightmonospace=65304;e.eightoldstyle=63288;e.eightparen=9339;e.eightperiod=9359;e.eightpersian=1784;e.eightroman=8567;e.eightsuperior=8312;e.eightthai=3672;e.einvertedbreve=519;e.eiotifiedcyrillic=1125;e.ekatakana=12456;e.ekatakanahalfwidth=65396;e.ekonkargurmukhi=2676;e.ekorean=12628;e.elcyrillic=1083;e.element=8712;e.elevencircle=9322;e.elevenparen=9342;e.elevenperiod=9362;e.elevenroman=8570;e.ellipsis=8230;e.ellipsisvertical=8942;e.emacron=275;e.emacronacute=7703;e.emacrongrave=7701;e.emcyrillic=1084;e.emdash=8212;e.emdashvertical=65073;e.emonospace=65349;e.emphasismarkarmenian=1371;e.emptyset=8709;e.enbopomofo=12579;e.encyrillic=1085;e.endash=8211;e.endashvertical=65074;e.endescendercyrillic=1187;e.eng=331;e.engbopomofo=12581;e.enghecyrillic=1189;e.enhookcyrillic=1224;e.enspace=8194;e.eogonek=281;e.eokorean=12627;e.eopen=603;e.eopenclosed=666;e.eopenreversed=604;e.eopenreversedclosed=606;e.eopenreversedhook=605;e.eparen=9376;e.epsilon=949;e.epsilontonos=941;e.equal=61;e.equalmonospace=65309;e.equalsmall=65126;e.equalsuperior=8316;e.equivalence=8801;e.erbopomofo=12582;e.ercyrillic=1088;e.ereversed=600;e.ereversedcyrillic=1101;e.escyrillic=1089;e.esdescendercyrillic=1195;e.esh=643;e.eshcurl=646;e.eshortdeva=2318;e.eshortvowelsigndeva=2374;e.eshreversedloop=426;e.eshsquatreversed=645;e.esmallhiragana=12359;e.esmallkatakana=12455;e.esmallkatakanahalfwidth=65386;e.estimated=8494;e.esuperior=63212;e.eta=951;e.etarmenian=1384;e.etatonos=942;e.eth=240;e.etilde=7869;e.etildebelow=7707;e.etnahtafoukhhebrew=1425;e.etnahtafoukhlefthebrew=1425;e.etnahtahebrew=1425;e.etnahtalefthebrew=1425;e.eturned=477;e.eukorean=12641;e.euro=8364;e.evowelsignbengali=2503;e.evowelsigndeva=2375;e.evowelsigngujarati=2759;e.exclam=33;e.exclamarmenian=1372;e.exclamdbl=8252;e.exclamdown=161;e.exclamdownsmall=63393;e.exclammonospace=65281;e.exclamsmall=63265;e.existential=8707;e.ezh=658;e.ezhcaron=495;e.ezhcurl=659;e.ezhreversed=441;e.ezhtail=442;e.f=102;e.fadeva=2398;e.fagurmukhi=2654;e.fahrenheit=8457;e.fathaarabic=1614;e.fathalowarabic=1614;e.fathatanarabic=1611;e.fbopomofo=12552;e.fcircle=9429;e.fdotaccent=7711;e.feharabic=1601;e.feharmenian=1414;e.fehfinalarabic=65234;e.fehinitialarabic=65235;e.fehmedialarabic=65236;e.feicoptic=997;e.female=9792;e.ff=64256;e.ffi=64259;e.ffl=64260;e.fi=64257;e.fifteencircle=9326;e.fifteenparen=9346;e.fifteenperiod=9366;e.figuredash=8210;e.filledbox=9632;e.filledrect=9644;e.finalkaf=1498;e.finalkafdagesh=64314;e.finalkafdageshhebrew=64314;e.finalkafhebrew=1498;e.finalmem=1501;e.finalmemhebrew=1501;e.finalnun=1503;e.finalnunhebrew=1503;e.finalpe=1507;e.finalpehebrew=1507;e.finaltsadi=1509;e.finaltsadihebrew=1509;e.firsttonechinese=713;e.fisheye=9673;e.fitacyrillic=1139;e.five=53;e.fivearabic=1637;e.fivebengali=2539;e.fivecircle=9316;e.fivecircleinversesansserif=10126;e.fivedeva=2411;e.fiveeighths=8541;e.fivegujarati=2795;e.fivegurmukhi=2667;e.fivehackarabic=1637;e.fivehangzhou=12325;e.fiveideographicparen=12836;e.fiveinferior=8325;e.fivemonospace=65301;e.fiveoldstyle=63285;e.fiveparen=9336;e.fiveperiod=9356;e.fivepersian=1781;e.fiveroman=8564;e.fivesuperior=8309;e.fivethai=3669;e.fl=64258;e.florin=402;e.fmonospace=65350;e.fmsquare=13209;e.fofanthai=3615;e.fofathai=3613;e.fongmanthai=3663;e.forall=8704;e.four=52;e.fourarabic=1636;e.fourbengali=2538;e.fourcircle=9315;e.fourcircleinversesansserif=10125;e.fourdeva=2410;e.fourgujarati=2794;e.fourgurmukhi=2666;e.fourhackarabic=1636;e.fourhangzhou=12324;e.fourideographicparen=12835;e.fourinferior=8324;e.fourmonospace=65300;e.fournumeratorbengali=2551;e.fouroldstyle=63284;e.fourparen=9335;e.fourperiod=9355;e.fourpersian=1780;e.fourroman=8563;e.foursuperior=8308;e.fourteencircle=9325;e.fourteenparen=9345;e.fourteenperiod=9365;e.fourthai=3668;e.fourthtonechinese=715;e.fparen=9377;e.fraction=8260;e.franc=8355;e.g=103;e.gabengali=2455;e.gacute=501;e.gadeva=2327;e.gafarabic=1711;e.gaffinalarabic=64403;e.gafinitialarabic=64404;e.gafmedialarabic=64405;e.gagujarati=2711;e.gagurmukhi=2583;e.gahiragana=12364;e.gakatakana=12460;e.gamma=947;e.gammalatinsmall=611;e.gammasuperior=736;e.gangiacoptic=1003;e.gbopomofo=12557;e.gbreve=287;e.gcaron=487;e.gcedilla=291;e.gcircle=9430;e.gcircumflex=285;e.gcommaaccent=291;e.gdot=289;e.gdotaccent=289;e.gecyrillic=1075;e.gehiragana=12370;e.gekatakana=12466;e.geometricallyequal=8785;e.gereshaccenthebrew=1436;e.gereshhebrew=1523;e.gereshmuqdamhebrew=1437;e.germandbls=223;e.gershayimaccenthebrew=1438;e.gershayimhebrew=1524;e.getamark=12307;e.ghabengali=2456;e.ghadarmenian=1394;e.ghadeva=2328;e.ghagujarati=2712;e.ghagurmukhi=2584;e.ghainarabic=1594;e.ghainfinalarabic=65230;e.ghaininitialarabic=65231;e.ghainmedialarabic=65232;e.ghemiddlehookcyrillic=1173;e.ghestrokecyrillic=1171;e.gheupturncyrillic=1169;e.ghhadeva=2394;e.ghhagurmukhi=2650;e.ghook=608;e.ghzsquare=13203;e.gihiragana=12366;e.gikatakana=12462;e.gimarmenian=1379;e.gimel=1490;e.gimeldagesh=64306;e.gimeldageshhebrew=64306;e.gimelhebrew=1490;e.gjecyrillic=1107;e.glottalinvertedstroke=446;e.glottalstop=660;e.glottalstopinverted=662;e.glottalstopmod=704;e.glottalstopreversed=661;e.glottalstopreversedmod=705;e.glottalstopreversedsuperior=740;e.glottalstopstroke=673;e.glottalstopstrokereversed=674;e.gmacron=7713;e.gmonospace=65351;e.gohiragana=12372;e.gokatakana=12468;e.gparen=9378;e.gpasquare=13228;e.gradient=8711;e.grave=96;e.gravebelowcmb=790;e.gravecmb=768;e.gravecomb=768;e.gravedeva=2387;e.gravelowmod=718;e.gravemonospace=65344;e.gravetonecmb=832;e.greater=62;e.greaterequal=8805;e.greaterequalorless=8923;e.greatermonospace=65310;e.greaterorequivalent=8819;e.greaterorless=8823;e.greateroverequal=8807;e.greatersmall=65125;e.gscript=609;e.gstroke=485;e.guhiragana=12368;e.guillemotleft=171;e.guillemotright=187;e.guilsinglleft=8249;e.guilsinglright=8250;e.gukatakana=12464;e.guramusquare=13080;e.gysquare=13257;e.h=104;e.haabkhasiancyrillic=1193;e.haaltonearabic=1729;e.habengali=2489;e.hadescendercyrillic=1203;e.hadeva=2361;e.hagujarati=2745;e.hagurmukhi=2617;e.haharabic=1581;e.hahfinalarabic=65186;e.hahinitialarabic=65187;e.hahiragana=12399;e.hahmedialarabic=65188;e.haitusquare=13098;e.hakatakana=12495;e.hakatakanahalfwidth=65418;e.halantgurmukhi=2637;e.hamzaarabic=1569;e.hamzalowarabic=1569;e.hangulfiller=12644;e.hardsigncyrillic=1098;e.harpoonleftbarbup=8636;e.harpoonrightbarbup=8640;e.hasquare=13258;e.hatafpatah=1458;e.hatafpatah16=1458;e.hatafpatah23=1458;e.hatafpatah2f=1458;e.hatafpatahhebrew=1458;e.hatafpatahnarrowhebrew=1458;e.hatafpatahquarterhebrew=1458;e.hatafpatahwidehebrew=1458;e.hatafqamats=1459;e.hatafqamats1b=1459;e.hatafqamats28=1459;e.hatafqamats34=1459;e.hatafqamatshebrew=1459;e.hatafqamatsnarrowhebrew=1459;e.hatafqamatsquarterhebrew=1459;e.hatafqamatswidehebrew=1459;e.hatafsegol=1457;e.hatafsegol17=1457;e.hatafsegol24=1457;e.hatafsegol30=1457;e.hatafsegolhebrew=1457;e.hatafsegolnarrowhebrew=1457;e.hatafsegolquarterhebrew=1457;e.hatafsegolwidehebrew=1457;e.hbar=295;e.hbopomofo=12559;e.hbrevebelow=7723;e.hcedilla=7721;e.hcircle=9431;e.hcircumflex=293;e.hdieresis=7719;e.hdotaccent=7715;e.hdotbelow=7717;e.he=1492;e.heart=9829;e.heartsuitblack=9829;e.heartsuitwhite=9825;e.hedagesh=64308;e.hedageshhebrew=64308;e.hehaltonearabic=1729;e.heharabic=1607;e.hehebrew=1492;e.hehfinalaltonearabic=64423;e.hehfinalalttwoarabic=65258;e.hehfinalarabic=65258;e.hehhamzaabovefinalarabic=64421;e.hehhamzaaboveisolatedarabic=64420;e.hehinitialaltonearabic=64424;e.hehinitialarabic=65259;e.hehiragana=12408;e.hehmedialaltonearabic=64425;e.hehmedialarabic=65260;e.heiseierasquare=13179;e.hekatakana=12504;e.hekatakanahalfwidth=65421;e.hekutaarusquare=13110;e.henghook=615;e.herutusquare=13113;e.het=1495;e.hethebrew=1495;e.hhook=614;e.hhooksuperior=689;e.hieuhacirclekorean=12923;e.hieuhaparenkorean=12827;e.hieuhcirclekorean=12909;e.hieuhkorean=12622;e.hieuhparenkorean=12813;e.hihiragana=12402;e.hikatakana=12498;e.hikatakanahalfwidth=65419;e.hiriq=1460;e.hiriq14=1460;e.hiriq21=1460;e.hiriq2d=1460;e.hiriqhebrew=1460;e.hiriqnarrowhebrew=1460;e.hiriqquarterhebrew=1460;e.hiriqwidehebrew=1460;e.hlinebelow=7830;e.hmonospace=65352;e.hoarmenian=1392;e.hohipthai=3627;e.hohiragana=12411;e.hokatakana=12507;e.hokatakanahalfwidth=65422;e.holam=1465;e.holam19=1465;e.holam26=1465;e.holam32=1465;e.holamhebrew=1465;e.holamnarrowhebrew=1465;e.holamquarterhebrew=1465;e.holamwidehebrew=1465;e.honokhukthai=3630;e.hookabovecomb=777;e.hookcmb=777;e.hookpalatalizedbelowcmb=801;e.hookretroflexbelowcmb=802;e.hoonsquare=13122;e.horicoptic=1001;e.horizontalbar=8213;e.horncmb=795;e.hotsprings=9832;e.house=8962;e.hparen=9379;e.hsuperior=688;e.hturned=613;e.huhiragana=12405;e.huiitosquare=13107;e.hukatakana=12501;e.hukatakanahalfwidth=65420;e.hungarumlaut=733;e.hungarumlautcmb=779;e.hv=405;e.hyphen=45;e.hypheninferior=63205;e.hyphenmonospace=65293;e.hyphensmall=65123;e.hyphensuperior=63206;e.hyphentwo=8208;e.i=105;e.iacute=237;e.iacyrillic=1103;e.ibengali=2439;e.ibopomofo=12583;e.ibreve=301;e.icaron=464;e.icircle=9432;e.icircumflex=238;e.icyrillic=1110;e.idblgrave=521;e.ideographearthcircle=12943;e.ideographfirecircle=12939;e.ideographicallianceparen=12863;e.ideographiccallparen=12858;e.ideographiccentrecircle=12965;e.ideographicclose=12294;e.ideographiccomma=12289;e.ideographiccommaleft=65380;e.ideographiccongratulationparen=12855;e.ideographiccorrectcircle=12963;e.ideographicearthparen=12847;e.ideographicenterpriseparen=12861;e.ideographicexcellentcircle=12957;e.ideographicfestivalparen=12864;e.ideographicfinancialcircle=12950;e.ideographicfinancialparen=12854;e.ideographicfireparen=12843;e.ideographichaveparen=12850;e.ideographichighcircle=12964;e.ideographiciterationmark=12293;e.ideographiclaborcircle=12952;e.ideographiclaborparen=12856;e.ideographicleftcircle=12967;e.ideographiclowcircle=12966;e.ideographicmedicinecircle=12969;e.ideographicmetalparen=12846;e.ideographicmoonparen=12842;e.ideographicnameparen=12852;e.ideographicperiod=12290;e.ideographicprintcircle=12958;e.ideographicreachparen=12867;e.ideographicrepresentparen=12857;e.ideographicresourceparen=12862;e.ideographicrightcircle=12968;e.ideographicsecretcircle=12953;e.ideographicselfparen=12866;e.ideographicsocietyparen=12851;e.ideographicspace=12288;e.ideographicspecialparen=12853;e.ideographicstockparen=12849;e.ideographicstudyparen=12859;e.ideographicsunparen=12848;e.ideographicsuperviseparen=12860;e.ideographicwaterparen=12844;e.ideographicwoodparen=12845;e.ideographiczero=12295;e.ideographmetalcircle=12942;e.ideographmooncircle=12938;e.ideographnamecircle=12948;e.ideographsuncircle=12944;e.ideographwatercircle=12940;e.ideographwoodcircle=12941;e.ideva=2311;e.idieresis=239;e.idieresisacute=7727;e.idieresiscyrillic=1253;e.idotbelow=7883;e.iebrevecyrillic=1239;e.iecyrillic=1077;e.ieungacirclekorean=12917;e.ieungaparenkorean=12821;e.ieungcirclekorean=12903;e.ieungkorean=12615;e.ieungparenkorean=12807;e.igrave=236;e.igujarati=2695;e.igurmukhi=2567;e.ihiragana=12356;e.ihookabove=7881;e.iibengali=2440;e.iicyrillic=1080;e.iideva=2312;e.iigujarati=2696;e.iigurmukhi=2568;e.iimatragurmukhi=2624;e.iinvertedbreve=523;e.iishortcyrillic=1081;e.iivowelsignbengali=2496;e.iivowelsigndeva=2368;e.iivowelsigngujarati=2752;e.ij=307;e.ikatakana=12452;e.ikatakanahalfwidth=65394;e.ikorean=12643;e.ilde=732;e.iluyhebrew=1452;e.imacron=299;e.imacroncyrillic=1251;e.imageorapproximatelyequal=8787;e.imatragurmukhi=2623;e.imonospace=65353;e.increment=8710;e.infinity=8734;e.iniarmenian=1387;e.integral=8747;e.integralbottom=8993;e.integralbt=8993;e.integralex=63733;e.integraltop=8992;e.integraltp=8992;e.intersection=8745;e.intisquare=13061;e.invbullet=9688;e.invcircle=9689;e.invsmileface=9787;e.iocyrillic=1105;e.iogonek=303;e.iota=953;e.iotadieresis=970;e.iotadieresistonos=912;e.iotalatin=617;e.iotatonos=943;e.iparen=9380;e.irigurmukhi=2674;e.ismallhiragana=12355;e.ismallkatakana=12451;e.ismallkatakanahalfwidth=65384;e.issharbengali=2554;e.istroke=616;e.isuperior=63213;e.iterationhiragana=12445;e.iterationkatakana=12541;e.itilde=297;e.itildebelow=7725;e.iubopomofo=12585;e.iucyrillic=1102;e.ivowelsignbengali=2495;e.ivowelsigndeva=2367;e.ivowelsigngujarati=2751;e.izhitsacyrillic=1141;e.izhitsadblgravecyrillic=1143;e.j=106;e.jaarmenian=1393;e.jabengali=2460;e.jadeva=2332;e.jagujarati=2716;e.jagurmukhi=2588;e.jbopomofo=12560;e.jcaron=496;e.jcircle=9433;e.jcircumflex=309;e.jcrossedtail=669;e.jdotlessstroke=607;e.jecyrillic=1112;e.jeemarabic=1580;e.jeemfinalarabic=65182;e.jeeminitialarabic=65183;e.jeemmedialarabic=65184;e.jeharabic=1688;e.jehfinalarabic=64395;e.jhabengali=2461;e.jhadeva=2333;e.jhagujarati=2717;e.jhagurmukhi=2589;e.jheharmenian=1403;e.jis=12292;e.jmonospace=65354;e.jparen=9381;e.jsuperior=690;e.k=107;e.kabashkircyrillic=1185;e.kabengali=2453;e.kacute=7729;e.kacyrillic=1082;e.kadescendercyrillic=1179;e.kadeva=2325;e.kaf=1499;e.kafarabic=1603;e.kafdagesh=64315;e.kafdageshhebrew=64315;e.kaffinalarabic=65242;e.kafhebrew=1499;e.kafinitialarabic=65243;e.kafmedialarabic=65244;e.kafrafehebrew=64333;e.kagujarati=2709;e.kagurmukhi=2581;e.kahiragana=12363;e.kahookcyrillic=1220;e.kakatakana=12459;e.kakatakanahalfwidth=65398;e.kappa=954;e.kappasymbolgreek=1008;e.kapyeounmieumkorean=12657;e.kapyeounphieuphkorean=12676;e.kapyeounpieupkorean=12664;e.kapyeounssangpieupkorean=12665;e.karoriisquare=13069;e.kashidaautoarabic=1600;e.kashidaautonosidebearingarabic=1600;e.kasmallkatakana=12533;e.kasquare=13188;e.kasraarabic=1616;e.kasratanarabic=1613;e.kastrokecyrillic=1183;e.katahiraprolongmarkhalfwidth=65392;e.kaverticalstrokecyrillic=1181;e.kbopomofo=12558;e.kcalsquare=13193;e.kcaron=489;e.kcedilla=311;e.kcircle=9434;e.kcommaaccent=311;e.kdotbelow=7731;e.keharmenian=1412;e.kehiragana=12369;e.kekatakana=12465;e.kekatakanahalfwidth=65401;e.kenarmenian=1391;e.kesmallkatakana=12534;e.kgreenlandic=312;e.khabengali=2454;e.khacyrillic=1093;e.khadeva=2326;e.khagujarati=2710;e.khagurmukhi=2582;e.khaharabic=1582;e.khahfinalarabic=65190;e.khahinitialarabic=65191;e.khahmedialarabic=65192;e.kheicoptic=999;e.khhadeva=2393;e.khhagurmukhi=2649;e.khieukhacirclekorean=12920;e.khieukhaparenkorean=12824;e.khieukhcirclekorean=12906;e.khieukhkorean=12619;e.khieukhparenkorean=12810;e.khokhaithai=3586;e.khokhonthai=3589;e.khokhuatthai=3587;e.khokhwaithai=3588;e.khomutthai=3675;e.khook=409;e.khorakhangthai=3590;e.khzsquare=13201;e.kihiragana=12365;e.kikatakana=12461;e.kikatakanahalfwidth=65399;e.kiroguramusquare=13077;e.kiromeetorusquare=13078;e.kirosquare=13076;e.kiyeokacirclekorean=12910;e.kiyeokaparenkorean=12814;e.kiyeokcirclekorean=12896;e.kiyeokkorean=12593;e.kiyeokparenkorean=12800;e.kiyeoksioskorean=12595;e.kjecyrillic=1116;e.klinebelow=7733;e.klsquare=13208;e.kmcubedsquare=13222;e.kmonospace=65355;e.kmsquaredsquare=13218;e.kohiragana=12371;e.kohmsquare=13248;e.kokaithai=3585;e.kokatakana=12467;e.kokatakanahalfwidth=65402;e.kooposquare=13086;e.koppacyrillic=1153;e.koreanstandardsymbol=12927;e.koroniscmb=835;e.kparen=9382;e.kpasquare=13226;e.ksicyrillic=1135;e.ktsquare=13263;e.kturned=670;e.kuhiragana=12367;e.kukatakana=12463;e.kukatakanahalfwidth=65400;e.kvsquare=13240;e.kwsquare=13246;e.l=108;e.labengali=2482;e.lacute=314;e.ladeva=2354;e.lagujarati=2738;e.lagurmukhi=2610;e.lakkhangyaothai=3653;e.lamaleffinalarabic=65276;e.lamalefhamzaabovefinalarabic=65272;e.lamalefhamzaaboveisolatedarabic=65271;e.lamalefhamzabelowfinalarabic=65274;e.lamalefhamzabelowisolatedarabic=65273;e.lamalefisolatedarabic=65275;e.lamalefmaddaabovefinalarabic=65270;e.lamalefmaddaaboveisolatedarabic=65269;e.lamarabic=1604;e.lambda=955;e.lambdastroke=411;e.lamed=1500;e.lameddagesh=64316;e.lameddageshhebrew=64316;e.lamedhebrew=1500;e.lamfinalarabic=65246;e.lamhahinitialarabic=64714;e.laminitialarabic=65247;e.lamjeeminitialarabic=64713;e.lamkhahinitialarabic=64715;e.lamlamhehisolatedarabic=65010;e.lammedialarabic=65248;e.lammeemhahinitialarabic=64904;e.lammeeminitialarabic=64716;e.largecircle=9711;e.lbar=410;e.lbelt=620;e.lbopomofo=12556;e.lcaron=318;e.lcedilla=316;e.lcircle=9435;e.lcircumflexbelow=7741;e.lcommaaccent=316;e.ldot=320;e.ldotaccent=320;e.ldotbelow=7735;e.ldotbelowmacron=7737;e.leftangleabovecmb=794;e.lefttackbelowcmb=792;e.less=60;e.lessequal=8804;e.lessequalorgreater=8922;e.lessmonospace=65308;e.lessorequivalent=8818;e.lessorgreater=8822;e.lessoverequal=8806;e.lesssmall=65124;e.lezh=622;e.lfblock=9612;e.lhookretroflex=621;e.lira=8356;e.liwnarmenian=1388;e.lj=457;e.ljecyrillic=1113;e.ll=63168;e.lladeva=2355;e.llagujarati=2739;e.llinebelow=7739;e.llladeva=2356;e.llvocalicbengali=2529;e.llvocalicdeva=2401;e.llvocalicvowelsignbengali=2531;e.llvocalicvowelsigndeva=2403;e.lmiddletilde=619;e.lmonospace=65356;e.lmsquare=13264;e.lochulathai=3628;e.logicaland=8743;e.logicalnot=172;e.logicalnotreversed=8976;e.logicalor=8744;e.lolingthai=3621;e.longs=383;e.lowlinecenterline=65102;e.lowlinecmb=818;e.lowlinedashed=65101;e.lozenge=9674;e.lparen=9383;e.lslash=322;e.lsquare=8467;e.lsuperior=63214;e.ltshade=9617;e.luthai=3622;e.lvocalicbengali=2444;e.lvocalicdeva=2316;e.lvocalicvowelsignbengali=2530;e.lvocalicvowelsigndeva=2402;e.lxsquare=13267;e.m=109;e.mabengali=2478;e.macron=175;e.macronbelowcmb=817;e.macroncmb=772;e.macronlowmod=717;e.macronmonospace=65507;e.macute=7743;e.madeva=2350;e.magujarati=2734;e.magurmukhi=2606;e.mahapakhhebrew=1444;e.mahapakhlefthebrew=1444;e.mahiragana=12414;e.maichattawalowleftthai=63637;e.maichattawalowrightthai=63636;e.maichattawathai=3659;e.maichattawaupperleftthai=63635;e.maieklowleftthai=63628;e.maieklowrightthai=63627;e.maiekthai=3656;e.maiekupperleftthai=63626;e.maihanakatleftthai=63620;e.maihanakatthai=3633;e.maitaikhuleftthai=63625;e.maitaikhuthai=3655;e.maitholowleftthai=63631;e.maitholowrightthai=63630;e.maithothai=3657;e.maithoupperleftthai=63629;e.maitrilowleftthai=63634;e.maitrilowrightthai=63633;e.maitrithai=3658;e.maitriupperleftthai=63632;e.maiyamokthai=3654;e.makatakana=12510;e.makatakanahalfwidth=65423;e.male=9794;e.mansyonsquare=13127;e.maqafhebrew=1470;e.mars=9794;e.masoracirclehebrew=1455;e.masquare=13187;e.mbopomofo=12551;e.mbsquare=13268;e.mcircle=9436;e.mcubedsquare=13221;e.mdotaccent=7745;e.mdotbelow=7747;e.meemarabic=1605;e.meemfinalarabic=65250;e.meeminitialarabic=65251;e.meemmedialarabic=65252;e.meemmeeminitialarabic=64721;e.meemmeemisolatedarabic=64584;e.meetorusquare=13133;e.mehiragana=12417;e.meizierasquare=13182;e.mekatakana=12513;e.mekatakanahalfwidth=65426;e.mem=1502;e.memdagesh=64318;e.memdageshhebrew=64318;e.memhebrew=1502;e.menarmenian=1396;e.merkhahebrew=1445;e.merkhakefulahebrew=1446;e.merkhakefulalefthebrew=1446;e.merkhalefthebrew=1445;e.mhook=625;e.mhzsquare=13202;e.middledotkatakanahalfwidth=65381;e.middot=183;e.mieumacirclekorean=12914;e.mieumaparenkorean=12818;e.mieumcirclekorean=12900;e.mieumkorean=12609;e.mieumpansioskorean=12656;e.mieumparenkorean=12804;e.mieumpieupkorean=12654;e.mieumsioskorean=12655;e.mihiragana=12415;e.mikatakana=12511;e.mikatakanahalfwidth=65424;e.minus=8722;e.minusbelowcmb=800;e.minuscircle=8854;e.minusmod=727;e.minusplus=8723;e.minute=8242;e.miribaarusquare=13130;e.mirisquare=13129;e.mlonglegturned=624;e.mlsquare=13206;e.mmcubedsquare=13219;e.mmonospace=65357;e.mmsquaredsquare=13215;e.mohiragana=12418;e.mohmsquare=13249;e.mokatakana=12514;e.mokatakanahalfwidth=65427;e.molsquare=13270;e.momathai=3617;e.moverssquare=13223;e.moverssquaredsquare=13224;e.mparen=9384;e.mpasquare=13227;e.mssquare=13235;e.msuperior=63215;e.mturned=623;e.mu=181;e.mu1=181;e.muasquare=13186;e.muchgreater=8811;e.muchless=8810;e.mufsquare=13196;e.mugreek=956;e.mugsquare=13197;e.muhiragana=12416;e.mukatakana=12512;e.mukatakanahalfwidth=65425;e.mulsquare=13205;e.multiply=215;e.mumsquare=13211;e.munahhebrew=1443;e.munahlefthebrew=1443;e.musicalnote=9834;e.musicalnotedbl=9835;e.musicflatsign=9837;e.musicsharpsign=9839;e.mussquare=13234;e.muvsquare=13238;e.muwsquare=13244;e.mvmegasquare=13241;e.mvsquare=13239;e.mwmegasquare=13247;e.mwsquare=13245;e.n=110;e.nabengali=2472;e.nabla=8711;e.nacute=324;e.nadeva=2344;e.nagujarati=2728;e.nagurmukhi=2600;e.nahiragana=12394;e.nakatakana=12490;e.nakatakanahalfwidth=65413;e.napostrophe=329;e.nasquare=13185;e.nbopomofo=12555;e.nbspace=160;e.ncaron=328;e.ncedilla=326;e.ncircle=9437;e.ncircumflexbelow=7755;e.ncommaaccent=326;e.ndotaccent=7749;e.ndotbelow=7751;e.nehiragana=12397;e.nekatakana=12493;e.nekatakanahalfwidth=65416;e.newsheqelsign=8362;e.nfsquare=13195;e.ngabengali=2457;e.ngadeva=2329;e.ngagujarati=2713;e.ngagurmukhi=2585;e.ngonguthai=3591;e.nhiragana=12435;e.nhookleft=626;e.nhookretroflex=627;e.nieunacirclekorean=12911;e.nieunaparenkorean=12815;e.nieuncieuckorean=12597;e.nieuncirclekorean=12897;e.nieunhieuhkorean=12598;e.nieunkorean=12596;e.nieunpansioskorean=12648;e.nieunparenkorean=12801;e.nieunsioskorean=12647;e.nieuntikeutkorean=12646;e.nihiragana=12395;e.nikatakana=12491;e.nikatakanahalfwidth=65414;e.nikhahitleftthai=63641;e.nikhahitthai=3661;e.nine=57;e.ninearabic=1641;e.ninebengali=2543;e.ninecircle=9320;e.ninecircleinversesansserif=10130;e.ninedeva=2415;e.ninegujarati=2799;e.ninegurmukhi=2671;e.ninehackarabic=1641;e.ninehangzhou=12329;e.nineideographicparen=12840;e.nineinferior=8329;e.ninemonospace=65305;e.nineoldstyle=63289;e.nineparen=9340;e.nineperiod=9360;e.ninepersian=1785;e.nineroman=8568;e.ninesuperior=8313;e.nineteencircle=9330;e.nineteenparen=9350;e.nineteenperiod=9370;e.ninethai=3673;e.nj=460;e.njecyrillic=1114;e.nkatakana=12531;e.nkatakanahalfwidth=65437;e.nlegrightlong=414;e.nlinebelow=7753;e.nmonospace=65358;e.nmsquare=13210;e.nnabengali=2467;e.nnadeva=2339;e.nnagujarati=2723;e.nnagurmukhi=2595;e.nnnadeva=2345;e.nohiragana=12398;e.nokatakana=12494;e.nokatakanahalfwidth=65417;e.nonbreakingspace=160;e.nonenthai=3603;e.nonuthai=3609;e.noonarabic=1606;e.noonfinalarabic=65254;e.noonghunnaarabic=1722;e.noonghunnafinalarabic=64415;e.nooninitialarabic=65255;e.noonjeeminitialarabic=64722;e.noonjeemisolatedarabic=64587;e.noonmedialarabic=65256;e.noonmeeminitialarabic=64725;e.noonmeemisolatedarabic=64590;e.noonnoonfinalarabic=64653;e.notcontains=8716;e.notelement=8713;e.notelementof=8713;e.notequal=8800;e.notgreater=8815;e.notgreaternorequal=8817;e.notgreaternorless=8825;e.notidentical=8802;e.notless=8814;e.notlessnorequal=8816;e.notparallel=8742;e.notprecedes=8832;e.notsubset=8836;e.notsucceeds=8833;e.notsuperset=8837;e.nowarmenian=1398;e.nparen=9385;e.nssquare=13233;e.nsuperior=8319;e.ntilde=241;e.nu=957;e.nuhiragana=12396;e.nukatakana=12492;e.nukatakanahalfwidth=65415;e.nuktabengali=2492;e.nuktadeva=2364;e.nuktagujarati=2748;e.nuktagurmukhi=2620;e.numbersign=35;e.numbersignmonospace=65283;e.numbersignsmall=65119;e.numeralsigngreek=884;e.numeralsignlowergreek=885;e.numero=8470;e.nun=1504;e.nundagesh=64320;e.nundageshhebrew=64320;e.nunhebrew=1504;e.nvsquare=13237;e.nwsquare=13243;e.nyabengali=2462;e.nyadeva=2334;e.nyagujarati=2718;e.nyagurmukhi=2590;e.o=111;e.oacute=243;e.oangthai=3629;e.obarred=629;e.obarredcyrillic=1257;e.obarreddieresiscyrillic=1259;e.obengali=2451;e.obopomofo=12571;e.obreve=335;e.ocandradeva=2321;e.ocandragujarati=2705;e.ocandravowelsigndeva=2377;e.ocandravowelsigngujarati=2761;e.ocaron=466;e.ocircle=9438;e.ocircumflex=244;e.ocircumflexacute=7889;e.ocircumflexdotbelow=7897;e.ocircumflexgrave=7891;e.ocircumflexhookabove=7893;e.ocircumflextilde=7895;e.ocyrillic=1086;e.odblacute=337;e.odblgrave=525;e.odeva=2323;e.odieresis=246;e.odieresiscyrillic=1255;e.odotbelow=7885;e.oe=339;e.oekorean=12634;e.ogonek=731;e.ogonekcmb=808;e.ograve=242;e.ogujarati=2707;e.oharmenian=1413;e.ohiragana=12362;e.ohookabove=7887;e.ohorn=417;e.ohornacute=7899;e.ohorndotbelow=7907;e.ohorngrave=7901;e.ohornhookabove=7903;e.ohorntilde=7905;e.ohungarumlaut=337;e.oi=419;e.oinvertedbreve=527;e.okatakana=12458;e.okatakanahalfwidth=65397;e.okorean=12631;e.olehebrew=1451;e.omacron=333;e.omacronacute=7763;e.omacrongrave=7761;e.omdeva=2384;e.omega=969;e.omega1=982;e.omegacyrillic=1121;e.omegalatinclosed=631;e.omegaroundcyrillic=1147;e.omegatitlocyrillic=1149;e.omegatonos=974;e.omgujarati=2768;e.omicron=959;e.omicrontonos=972;e.omonospace=65359;e.one=49;e.onearabic=1633;e.onebengali=2535;e.onecircle=9312;e.onecircleinversesansserif=10122;e.onedeva=2407;e.onedotenleader=8228;e.oneeighth=8539;e.onefitted=63196;e.onegujarati=2791;e.onegurmukhi=2663;e.onehackarabic=1633;e.onehalf=189;e.onehangzhou=12321;e.oneideographicparen=12832;e.oneinferior=8321;e.onemonospace=65297;e.onenumeratorbengali=2548;e.oneoldstyle=63281;e.oneparen=9332;e.oneperiod=9352;e.onepersian=1777;e.onequarter=188;e.oneroman=8560;e.onesuperior=185;e.onethai=3665;e.onethird=8531;e.oogonek=491;e.oogonekmacron=493;e.oogurmukhi=2579;e.oomatragurmukhi=2635;e.oopen=596;e.oparen=9386;e.openbullet=9702;e.option=8997;e.ordfeminine=170;e.ordmasculine=186;e.orthogonal=8735;e.oshortdeva=2322;e.oshortvowelsigndeva=2378;e.oslash=248;e.oslashacute=511;e.osmallhiragana=12361;e.osmallkatakana=12457;e.osmallkatakanahalfwidth=65387;e.ostrokeacute=511;e.osuperior=63216;e.otcyrillic=1151;e.otilde=245;e.otildeacute=7757;e.otildedieresis=7759;e.oubopomofo=12577;e.overline=8254;e.overlinecenterline=65098;e.overlinecmb=773;e.overlinedashed=65097;e.overlinedblwavy=65100;e.overlinewavy=65099;e.overscore=175;e.ovowelsignbengali=2507;e.ovowelsigndeva=2379;e.ovowelsigngujarati=2763;e.p=112;e.paampssquare=13184;e.paasentosquare=13099;e.pabengali=2474;e.pacute=7765;e.padeva=2346;e.pagedown=8671;e.pageup=8670;e.pagujarati=2730;e.pagurmukhi=2602;e.pahiragana=12401;e.paiyannoithai=3631;e.pakatakana=12497;e.palatalizationcyrilliccmb=1156;e.palochkacyrillic=1216;e.pansioskorean=12671;e.paragraph=182;e.parallel=8741;e.parenleft=40;e.parenleftaltonearabic=64830;e.parenleftbt=63725;e.parenleftex=63724;e.parenleftinferior=8333;e.parenleftmonospace=65288;e.parenleftsmall=65113;e.parenleftsuperior=8317;e.parenlefttp=63723;e.parenleftvertical=65077;e.parenright=41;e.parenrightaltonearabic=64831;e.parenrightbt=63736;e.parenrightex=63735;e.parenrightinferior=8334;e.parenrightmonospace=65289;e.parenrightsmall=65114;e.parenrightsuperior=8318;e.parenrighttp=63734;e.parenrightvertical=65078;e.partialdiff=8706;e.paseqhebrew=1472;e.pashtahebrew=1433;e.pasquare=13225;e.patah=1463;e.patah11=1463;e.patah1d=1463;e.patah2a=1463;e.patahhebrew=1463;e.patahnarrowhebrew=1463;e.patahquarterhebrew=1463;e.patahwidehebrew=1463;e.pazerhebrew=1441;e.pbopomofo=12550;e.pcircle=9439;e.pdotaccent=7767;e.pe=1508;e.pecyrillic=1087;e.pedagesh=64324;e.pedageshhebrew=64324;e.peezisquare=13115;e.pefinaldageshhebrew=64323;e.peharabic=1662;e.peharmenian=1402;e.pehebrew=1508;e.pehfinalarabic=64343;e.pehinitialarabic=64344;e.pehiragana=12410;e.pehmedialarabic=64345;e.pekatakana=12506;e.pemiddlehookcyrillic=1191;e.perafehebrew=64334;e.percent=37;e.percentarabic=1642;e.percentmonospace=65285;e.percentsmall=65130;e.period=46;e.periodarmenian=1417;e.periodcentered=183;e.periodhalfwidth=65377;e.periodinferior=63207;e.periodmonospace=65294;e.periodsmall=65106;e.periodsuperior=63208;e.perispomenigreekcmb=834;e.perpendicular=8869;e.perthousand=8240;e.peseta=8359;e.pfsquare=13194;e.phabengali=2475;e.phadeva=2347;e.phagujarati=2731;e.phagurmukhi=2603;e.phi=966;e.phi1=981;e.phieuphacirclekorean=12922;e.phieuphaparenkorean=12826;e.phieuphcirclekorean=12908;e.phieuphkorean=12621;e.phieuphparenkorean=12812;e.philatin=632;e.phinthuthai=3642;e.phisymbolgreek=981;e.phook=421;e.phophanthai=3614;e.phophungthai=3612;e.phosamphaothai=3616;e.pi=960;e.pieupacirclekorean=12915;e.pieupaparenkorean=12819;e.pieupcieuckorean=12662;e.pieupcirclekorean=12901;e.pieupkiyeokkorean=12658;e.pieupkorean=12610;e.pieupparenkorean=12805;e.pieupsioskiyeokkorean=12660;e.pieupsioskorean=12612;e.pieupsiostikeutkorean=12661;e.pieupthieuthkorean=12663;e.pieuptikeutkorean=12659;e.pihiragana=12404;e.pikatakana=12500;e.pisymbolgreek=982;e.piwrarmenian=1411;e.plus=43;e.plusbelowcmb=799;e.pluscircle=8853;e.plusminus=177;e.plusmod=726;e.plusmonospace=65291;e.plussmall=65122;e.plussuperior=8314;e.pmonospace=65360;e.pmsquare=13272;e.pohiragana=12413;e.pointingindexdownwhite=9759;e.pointingindexleftwhite=9756;e.pointingindexrightwhite=9758;e.pointingindexupwhite=9757;e.pokatakana=12509;e.poplathai=3611;e.postalmark=12306;e.postalmarkface=12320;e.pparen=9387;e.precedes=8826;e.prescription=8478;e.primemod=697;e.primereversed=8245;e.product=8719;e.projective=8965;e.prolongedkana=12540;e.propellor=8984;e.propersubset=8834;e.propersuperset=8835;e.proportion=8759;e.proportional=8733;e.psi=968;e.psicyrillic=1137;e.psilipneumatacyrilliccmb=1158;e.pssquare=13232;e.puhiragana=12407;e.pukatakana=12503;e.pvsquare=13236;e.pwsquare=13242;e.q=113;e.qadeva=2392;e.qadmahebrew=1448;e.qafarabic=1602;e.qaffinalarabic=65238;e.qafinitialarabic=65239;e.qafmedialarabic=65240;e.qamats=1464;e.qamats10=1464;e.qamats1a=1464;e.qamats1c=1464;e.qamats27=1464;e.qamats29=1464;e.qamats33=1464;e.qamatsde=1464;e.qamatshebrew=1464;e.qamatsnarrowhebrew=1464;e.qamatsqatanhebrew=1464;e.qamatsqatannarrowhebrew=1464;e.qamatsqatanquarterhebrew=1464;e.qamatsqatanwidehebrew=1464;e.qamatsquarterhebrew=1464;e.qamatswidehebrew=1464;e.qarneyparahebrew=1439;e.qbopomofo=12561;e.qcircle=9440;e.qhook=672;e.qmonospace=65361;e.qof=1511;e.qofdagesh=64327;e.qofdageshhebrew=64327;e.qofhebrew=1511;e.qparen=9388;e.quarternote=9833;e.qubuts=1467;e.qubuts18=1467;e.qubuts25=1467;e.qubuts31=1467;e.qubutshebrew=1467;e.qubutsnarrowhebrew=1467;e.qubutsquarterhebrew=1467;e.qubutswidehebrew=1467;e.question=63;e.questionarabic=1567;e.questionarmenian=1374;e.questiondown=191;e.questiondownsmall=63423;e.questiongreek=894;e.questionmonospace=65311;e.questionsmall=63295;e.quotedbl=34;e.quotedblbase=8222;e.quotedblleft=8220;e.quotedblmonospace=65282;e.quotedblprime=12318;e.quotedblprimereversed=12317;e.quotedblright=8221;e.quoteleft=8216;e.quoteleftreversed=8219;e.quotereversed=8219;e.quoteright=8217;e.quoterightn=329;e.quotesinglbase=8218;e.quotesingle=39;e.quotesinglemonospace=65287;e.r=114;e.raarmenian=1404;e.rabengali=2480;e.racute=341;e.radeva=2352;e.radical=8730;e.radicalex=63717;e.radoverssquare=13230;e.radoverssquaredsquare=13231;e.radsquare=13229;e.rafe=1471;e.rafehebrew=1471;e.ragujarati=2736;e.ragurmukhi=2608;e.rahiragana=12425;e.rakatakana=12521;e.rakatakanahalfwidth=65431;e.ralowerdiagonalbengali=2545;e.ramiddlediagonalbengali=2544;e.ramshorn=612;e.ratio=8758;e.rbopomofo=12566;e.rcaron=345;e.rcedilla=343;e.rcircle=9441;e.rcommaaccent=343;e.rdblgrave=529;e.rdotaccent=7769;e.rdotbelow=7771;e.rdotbelowmacron=7773;e.referencemark=8251;e.reflexsubset=8838;e.reflexsuperset=8839;e.registered=174;e.registersans=63720;e.registerserif=63194;e.reharabic=1585;e.reharmenian=1408;e.rehfinalarabic=65198;e.rehiragana=12428;e.rekatakana=12524;e.rekatakanahalfwidth=65434;e.resh=1512;e.reshdageshhebrew=64328;e.reshhebrew=1512;e.reversedtilde=8765;e.reviahebrew=1431;e.reviamugrashhebrew=1431;e.revlogicalnot=8976;e.rfishhook=638;e.rfishhookreversed=639;e.rhabengali=2525;e.rhadeva=2397;e.rho=961;e.rhook=637;e.rhookturned=635;e.rhookturnedsuperior=693;e.rhosymbolgreek=1009;e.rhotichookmod=734;e.rieulacirclekorean=12913;e.rieulaparenkorean=12817;e.rieulcirclekorean=12899;e.rieulhieuhkorean=12608;e.rieulkiyeokkorean=12602;e.rieulkiyeoksioskorean=12649;e.rieulkorean=12601;e.rieulmieumkorean=12603;e.rieulpansioskorean=12652;e.rieulparenkorean=12803;e.rieulphieuphkorean=12607;e.rieulpieupkorean=12604;e.rieulpieupsioskorean=12651;e.rieulsioskorean=12605;e.rieulthieuthkorean=12606;e.rieultikeutkorean=12650;e.rieulyeorinhieuhkorean=12653;e.rightangle=8735;e.righttackbelowcmb=793;e.righttriangle=8895;e.rihiragana=12426;e.rikatakana=12522;e.rikatakanahalfwidth=65432;e.ring=730;e.ringbelowcmb=805;e.ringcmb=778;e.ringhalfleft=703;e.ringhalfleftarmenian=1369;e.ringhalfleftbelowcmb=796;e.ringhalfleftcentered=723;e.ringhalfright=702;e.ringhalfrightbelowcmb=825;e.ringhalfrightcentered=722;e.rinvertedbreve=531;e.rittorusquare=13137;e.rlinebelow=7775;e.rlongleg=636;e.rlonglegturned=634;e.rmonospace=65362;e.rohiragana=12429;e.rokatakana=12525;e.rokatakanahalfwidth=65435;e.roruathai=3619;e.rparen=9389;e.rrabengali=2524;e.rradeva=2353;e.rragurmukhi=2652;e.rreharabic=1681;e.rrehfinalarabic=64397;e.rrvocalicbengali=2528;e.rrvocalicdeva=2400;e.rrvocalicgujarati=2784;e.rrvocalicvowelsignbengali=2500;e.rrvocalicvowelsigndeva=2372;e.rrvocalicvowelsigngujarati=2756;e.rsuperior=63217;e.rtblock=9616;e.rturned=633;e.rturnedsuperior=692;e.ruhiragana=12427;e.rukatakana=12523;e.rukatakanahalfwidth=65433;e.rupeemarkbengali=2546;e.rupeesignbengali=2547;e.rupiah=63197;e.ruthai=3620;e.rvocalicbengali=2443;e.rvocalicdeva=2315;e.rvocalicgujarati=2699;e.rvocalicvowelsignbengali=2499;e.rvocalicvowelsigndeva=2371;e.rvocalicvowelsigngujarati=2755;e.s=115;e.sabengali=2488;e.sacute=347;e.sacutedotaccent=7781;e.sadarabic=1589;e.sadeva=2360;e.sadfinalarabic=65210;e.sadinitialarabic=65211;e.sadmedialarabic=65212;e.sagujarati=2744;e.sagurmukhi=2616;e.sahiragana=12373;e.sakatakana=12469;e.sakatakanahalfwidth=65403;e.sallallahoualayhewasallamarabic=65018;e.samekh=1505;e.samekhdagesh=64321;e.samekhdageshhebrew=64321;e.samekhhebrew=1505;e.saraaathai=3634;e.saraaethai=3649;e.saraaimaimalaithai=3652;e.saraaimaimuanthai=3651;e.saraamthai=3635;e.saraathai=3632;e.saraethai=3648;e.saraiileftthai=63622;e.saraiithai=3637;e.saraileftthai=63621;e.saraithai=3636;e.saraothai=3650;e.saraueeleftthai=63624;e.saraueethai=3639;e.saraueleftthai=63623;e.sarauethai=3638;e.sarauthai=3640;e.sarauuthai=3641;e.sbopomofo=12569;e.scaron=353;e.scarondotaccent=7783;e.scedilla=351;e.schwa=601;e.schwacyrillic=1241;e.schwadieresiscyrillic=1243;e.schwahook=602;e.scircle=9442;e.scircumflex=349;e.scommaaccent=537;e.sdotaccent=7777;e.sdotbelow=7779;e.sdotbelowdotaccent=7785;e.seagullbelowcmb=828;e.second=8243;e.secondtonechinese=714;e.section=167;e.seenarabic=1587;e.seenfinalarabic=65202;e.seeninitialarabic=65203;e.seenmedialarabic=65204;e.segol=1462;e.segol13=1462;e.segol1f=1462;e.segol2c=1462;e.segolhebrew=1462;e.segolnarrowhebrew=1462;e.segolquarterhebrew=1462;e.segoltahebrew=1426;e.segolwidehebrew=1462;e.seharmenian=1405;e.sehiragana=12379;e.sekatakana=12475;e.sekatakanahalfwidth=65406;e.semicolon=59;e.semicolonarabic=1563;e.semicolonmonospace=65307;e.semicolonsmall=65108;e.semivoicedmarkkana=12444;e.semivoicedmarkkanahalfwidth=65439;e.sentisquare=13090;e.sentosquare=13091;e.seven=55;e.sevenarabic=1639;e.sevenbengali=2541;e.sevencircle=9318;e.sevencircleinversesansserif=10128;e.sevendeva=2413;e.seveneighths=8542;e.sevengujarati=2797;e.sevengurmukhi=2669;e.sevenhackarabic=1639;e.sevenhangzhou=12327;e.sevenideographicparen=12838;e.seveninferior=8327;e.sevenmonospace=65303;e.sevenoldstyle=63287;e.sevenparen=9338;e.sevenperiod=9358;e.sevenpersian=1783;e.sevenroman=8566;e.sevensuperior=8311;e.seventeencircle=9328;e.seventeenparen=9348;e.seventeenperiod=9368;e.seventhai=3671;e.sfthyphen=173;e.shaarmenian=1399;e.shabengali=2486;e.shacyrillic=1096;e.shaddaarabic=1617;e.shaddadammaarabic=64609;e.shaddadammatanarabic=64606;e.shaddafathaarabic=64608;e.shaddakasraarabic=64610;e.shaddakasratanarabic=64607;e.shade=9618;e.shadedark=9619;e.shadelight=9617;e.shademedium=9618;e.shadeva=2358;e.shagujarati=2742;e.shagurmukhi=2614;e.shalshelethebrew=1427;e.shbopomofo=12565;e.shchacyrillic=1097;e.sheenarabic=1588;e.sheenfinalarabic=65206;e.sheeninitialarabic=65207;e.sheenmedialarabic=65208;e.sheicoptic=995;e.sheqel=8362;e.sheqelhebrew=8362;e.sheva=1456;e.sheva115=1456;e.sheva15=1456;e.sheva22=1456;e.sheva2e=1456;e.shevahebrew=1456;e.shevanarrowhebrew=1456;e.shevaquarterhebrew=1456;e.shevawidehebrew=1456;e.shhacyrillic=1211;e.shimacoptic=1005;e.shin=1513;e.shindagesh=64329;e.shindageshhebrew=64329;e.shindageshshindot=64300;e.shindageshshindothebrew=64300;e.shindageshsindot=64301;e.shindageshsindothebrew=64301;e.shindothebrew=1473;e.shinhebrew=1513;e.shinshindot=64298;e.shinshindothebrew=64298;e.shinsindot=64299;e.shinsindothebrew=64299;e.shook=642;e.sigma=963;e.sigma1=962;e.sigmafinal=962;e.sigmalunatesymbolgreek=1010;e.sihiragana=12375;e.sikatakana=12471;e.sikatakanahalfwidth=65404;e.siluqhebrew=1469;e.siluqlefthebrew=1469;e.similar=8764;e.sindothebrew=1474;e.siosacirclekorean=12916;e.siosaparenkorean=12820;e.sioscieuckorean=12670;e.sioscirclekorean=12902;e.sioskiyeokkorean=12666;e.sioskorean=12613;e.siosnieunkorean=12667;e.siosparenkorean=12806;e.siospieupkorean=12669;e.siostikeutkorean=12668;e.six=54;e.sixarabic=1638;e.sixbengali=2540;e.sixcircle=9317;e.sixcircleinversesansserif=10127;e.sixdeva=2412;e.sixgujarati=2796;e.sixgurmukhi=2668;e.sixhackarabic=1638;e.sixhangzhou=12326;e.sixideographicparen=12837;e.sixinferior=8326;e.sixmonospace=65302;e.sixoldstyle=63286;e.sixparen=9337;e.sixperiod=9357;e.sixpersian=1782;e.sixroman=8565;e.sixsuperior=8310;e.sixteencircle=9327;e.sixteencurrencydenominatorbengali=2553;e.sixteenparen=9347;e.sixteenperiod=9367;e.sixthai=3670;e.slash=47;e.slashmonospace=65295;e.slong=383;e.slongdotaccent=7835;e.smileface=9786;e.smonospace=65363;e.sofpasuqhebrew=1475;e.softhyphen=173;e.softsigncyrillic=1100;e.sohiragana=12381;e.sokatakana=12477;e.sokatakanahalfwidth=65407;e.soliduslongoverlaycmb=824;e.solidusshortoverlaycmb=823;e.sorusithai=3625;e.sosalathai=3624;e.sosothai=3595;e.sosuathai=3626;e.space=32;e.spacehackarabic=32;e.spade=9824;e.spadesuitblack=9824;e.spadesuitwhite=9828;e.sparen=9390;e.squarebelowcmb=827;e.squarecc=13252;e.squarecm=13213;e.squarediagonalcrosshatchfill=9641;e.squarehorizontalfill=9636;e.squarekg=13199;e.squarekm=13214;e.squarekmcapital=13262;e.squareln=13265;e.squarelog=13266;e.squaremg=13198;e.squaremil=13269;e.squaremm=13212;e.squaremsquared=13217;e.squareorthogonalcrosshatchfill=9638;e.squareupperlefttolowerrightfill=9639;e.squareupperrighttolowerleftfill=9640;e.squareverticalfill=9637;e.squarewhitewithsmallblack=9635;e.srsquare=13275;e.ssabengali=2487;e.ssadeva=2359;e.ssagujarati=2743;e.ssangcieuckorean=12617;e.ssanghieuhkorean=12677;e.ssangieungkorean=12672;e.ssangkiyeokkorean=12594;e.ssangnieunkorean=12645;e.ssangpieupkorean=12611;e.ssangsioskorean=12614;e.ssangtikeutkorean=12600;e.ssuperior=63218;e.sterling=163;e.sterlingmonospace=65505;e.strokelongoverlaycmb=822;e.strokeshortoverlaycmb=821;e.subset=8834;e.subsetnotequal=8842;e.subsetorequal=8838;e.succeeds=8827;e.suchthat=8715;e.suhiragana=12377;e.sukatakana=12473;e.sukatakanahalfwidth=65405;e.sukunarabic=1618;e.summation=8721;e.sun=9788;e.superset=8835;e.supersetnotequal=8843;e.supersetorequal=8839;e.svsquare=13276;e.syouwaerasquare=13180;e.t=116;e.tabengali=2468;e.tackdown=8868;e.tackleft=8867;e.tadeva=2340;e.tagujarati=2724;e.tagurmukhi=2596;e.taharabic=1591;e.tahfinalarabic=65218;e.tahinitialarabic=65219;e.tahiragana=12383;e.tahmedialarabic=65220;e.taisyouerasquare=13181;e.takatakana=12479;e.takatakanahalfwidth=65408;e.tatweelarabic=1600;e.tau=964;e.tav=1514;e.tavdages=64330;e.tavdagesh=64330;e.tavdageshhebrew=64330;e.tavhebrew=1514;e.tbar=359;e.tbopomofo=12554;e.tcaron=357;e.tccurl=680;e.tcedilla=355;e.tcheharabic=1670;e.tchehfinalarabic=64379;e.tchehinitialarabic=64380;e.tchehmedialarabic=64381;e.tcircle=9443;e.tcircumflexbelow=7793;e.tcommaaccent=355;e.tdieresis=7831;e.tdotaccent=7787;e.tdotbelow=7789;e.tecyrillic=1090;e.tedescendercyrillic=1197;e.teharabic=1578;e.tehfinalarabic=65174;e.tehhahinitialarabic=64674;e.tehhahisolatedarabic=64524;e.tehinitialarabic=65175;e.tehiragana=12390;e.tehjeeminitialarabic=64673;e.tehjeemisolatedarabic=64523;e.tehmarbutaarabic=1577;e.tehmarbutafinalarabic=65172;e.tehmedialarabic=65176;e.tehmeeminitialarabic=64676;e.tehmeemisolatedarabic=64526;e.tehnoonfinalarabic=64627;e.tekatakana=12486;e.tekatakanahalfwidth=65411;e.telephone=8481;e.telephoneblack=9742;e.telishagedolahebrew=1440;e.telishaqetanahebrew=1449;e.tencircle=9321;e.tenideographicparen=12841;e.tenparen=9341;e.tenperiod=9361;e.tenroman=8569;e.tesh=679;e.tet=1496;e.tetdagesh=64312;e.tetdageshhebrew=64312;e.tethebrew=1496;e.tetsecyrillic=1205;e.tevirhebrew=1435;e.tevirlefthebrew=1435;e.thabengali=2469;e.thadeva=2341;e.thagujarati=2725;e.thagurmukhi=2597;e.thalarabic=1584;e.thalfinalarabic=65196;e.thanthakhatlowleftthai=63640;e.thanthakhatlowrightthai=63639;e.thanthakhatthai=3660;e.thanthakhatupperleftthai=63638;e.theharabic=1579;e.thehfinalarabic=65178;e.thehinitialarabic=65179;e.thehmedialarabic=65180;e.thereexists=8707;e.therefore=8756;e.theta=952;e.theta1=977;e.thetasymbolgreek=977;e.thieuthacirclekorean=12921;e.thieuthaparenkorean=12825;e.thieuthcirclekorean=12907;e.thieuthkorean=12620;e.thieuthparenkorean=12811;e.thirteencircle=9324;e.thirteenparen=9344;e.thirteenperiod=9364;e.thonangmonthothai=3601;e.thook=429;e.thophuthaothai=3602;e.thorn=254;e.thothahanthai=3607;e.thothanthai=3600;e.thothongthai=3608;e.thothungthai=3606;e.thousandcyrillic=1154;e.thousandsseparatorarabic=1644;e.thousandsseparatorpersian=1644;e.three=51;e.threearabic=1635;e.threebengali=2537;e.threecircle=9314;e.threecircleinversesansserif=10124;e.threedeva=2409;e.threeeighths=8540;e.threegujarati=2793;e.threegurmukhi=2665;e.threehackarabic=1635;e.threehangzhou=12323;e.threeideographicparen=12834;e.threeinferior=8323;e.threemonospace=65299;e.threenumeratorbengali=2550;e.threeoldstyle=63283;e.threeparen=9334;e.threeperiod=9354;e.threepersian=1779;e.threequarters=190;e.threequartersemdash=63198;e.threeroman=8562;e.threesuperior=179;e.threethai=3667;e.thzsquare=13204;e.tihiragana=12385;e.tikatakana=12481;e.tikatakanahalfwidth=65409;e.tikeutacirclekorean=12912;e.tikeutaparenkorean=12816;e.tikeutcirclekorean=12898;e.tikeutkorean=12599;e.tikeutparenkorean=12802;e.tilde=732;e.tildebelowcmb=816;e.tildecmb=771;e.tildecomb=771;e.tildedoublecmb=864;e.tildeoperator=8764;e.tildeoverlaycmb=820;e.tildeverticalcmb=830;e.timescircle=8855;e.tipehahebrew=1430;e.tipehalefthebrew=1430;e.tippigurmukhi=2672;e.titlocyrilliccmb=1155;e.tiwnarmenian=1407;e.tlinebelow=7791;e.tmonospace=65364;e.toarmenian=1385;e.tohiragana=12392;e.tokatakana=12488;e.tokatakanahalfwidth=65412;e.tonebarextrahighmod=741;e.tonebarextralowmod=745;e.tonebarhighmod=742;e.tonebarlowmod=744;e.tonebarmidmod=743;e.tonefive=445;e.tonesix=389;e.tonetwo=424;e.tonos=900;e.tonsquare=13095;e.topatakthai=3599;e.tortoiseshellbracketleft=12308;e.tortoiseshellbracketleftsmall=65117;e.tortoiseshellbracketleftvertical=65081;e.tortoiseshellbracketright=12309;e.tortoiseshellbracketrightsmall=65118;e.tortoiseshellbracketrightvertical=65082;e.totaothai=3605;e.tpalatalhook=427;e.tparen=9391;e.trademark=8482;e.trademarksans=63722;e.trademarkserif=63195;e.tretroflexhook=648;e.triagdn=9660;e.triaglf=9668;e.triagrt=9658;e.triagup=9650;e.ts=678;e.tsadi=1510;e.tsadidagesh=64326;e.tsadidageshhebrew=64326;e.tsadihebrew=1510;e.tsecyrillic=1094;e.tsere=1461;e.tsere12=1461;e.tsere1e=1461;e.tsere2b=1461;e.tserehebrew=1461;e.tserenarrowhebrew=1461;e.tserequarterhebrew=1461;e.tserewidehebrew=1461;e.tshecyrillic=1115;e.tsuperior=63219;e.ttabengali=2463;e.ttadeva=2335;e.ttagujarati=2719;e.ttagurmukhi=2591;e.tteharabic=1657;e.ttehfinalarabic=64359;e.ttehinitialarabic=64360;e.ttehmedialarabic=64361;e.tthabengali=2464;e.tthadeva=2336;e.tthagujarati=2720;e.tthagurmukhi=2592;e.tturned=647;e.tuhiragana=12388;e.tukatakana=12484;e.tukatakanahalfwidth=65410;e.tusmallhiragana=12387;e.tusmallkatakana=12483;e.tusmallkatakanahalfwidth=65391;e.twelvecircle=9323;e.twelveparen=9343;e.twelveperiod=9363;e.twelveroman=8571;e.twentycircle=9331;e.twentyhangzhou=21316;e.twentyparen=9351;e.twentyperiod=9371;e.two=50;e.twoarabic=1634;e.twobengali=2536;e.twocircle=9313;e.twocircleinversesansserif=10123;e.twodeva=2408;e.twodotenleader=8229;e.twodotleader=8229;e.twodotleadervertical=65072;e.twogujarati=2792;e.twogurmukhi=2664;e.twohackarabic=1634;e.twohangzhou=12322;e.twoideographicparen=12833;e.twoinferior=8322;e.twomonospace=65298;e.twonumeratorbengali=2549;e.twooldstyle=63282;e.twoparen=9333;e.twoperiod=9353;e.twopersian=1778;e.tworoman=8561;e.twostroke=443;e.twosuperior=178;e.twothai=3666;e.twothirds=8532;e.u=117;e.uacute=250;e.ubar=649;e.ubengali=2441;e.ubopomofo=12584;e.ubreve=365;e.ucaron=468;e.ucircle=9444;e.ucircumflex=251;e.ucircumflexbelow=7799;e.ucyrillic=1091;e.udattadeva=2385;e.udblacute=369;e.udblgrave=533;e.udeva=2313;e.udieresis=252;e.udieresisacute=472;e.udieresisbelow=7795;e.udieresiscaron=474;e.udieresiscyrillic=1265;e.udieresisgrave=476;e.udieresismacron=470;e.udotbelow=7909;e.ugrave=249;e.ugujarati=2697;e.ugurmukhi=2569;e.uhiragana=12358;e.uhookabove=7911;e.uhorn=432;e.uhornacute=7913;e.uhorndotbelow=7921;e.uhorngrave=7915;e.uhornhookabove=7917;e.uhorntilde=7919;e.uhungarumlaut=369;e.uhungarumlautcyrillic=1267;e.uinvertedbreve=535;e.ukatakana=12454;e.ukatakanahalfwidth=65395;e.ukcyrillic=1145;e.ukorean=12636;e.umacron=363;e.umacroncyrillic=1263;e.umacrondieresis=7803;e.umatragurmukhi=2625;e.umonospace=65365;e.underscore=95;e.underscoredbl=8215;e.underscoremonospace=65343;e.underscorevertical=65075;e.underscorewavy=65103;e.union=8746;e.universal=8704;e.uogonek=371;e.uparen=9392;e.upblock=9600;e.upperdothebrew=1476;e.upsilon=965;e.upsilondieresis=971;e.upsilondieresistonos=944;e.upsilonlatin=650;e.upsilontonos=973;e.uptackbelowcmb=797;e.uptackmod=724;e.uragurmukhi=2675;e.uring=367;e.ushortcyrillic=1118;e.usmallhiragana=12357;e.usmallkatakana=12453;e.usmallkatakanahalfwidth=65385;e.ustraightcyrillic=1199;e.ustraightstrokecyrillic=1201;e.utilde=361;e.utildeacute=7801;e.utildebelow=7797;e.uubengali=2442;e.uudeva=2314;e.uugujarati=2698;e.uugurmukhi=2570;e.uumatragurmukhi=2626;e.uuvowelsignbengali=2498;e.uuvowelsigndeva=2370;e.uuvowelsigngujarati=2754;e.uvowelsignbengali=2497;e.uvowelsigndeva=2369;e.uvowelsigngujarati=2753;e.v=118;e.vadeva=2357;e.vagujarati=2741;e.vagurmukhi=2613;e.vakatakana=12535;e.vav=1493;e.vavdagesh=64309;e.vavdagesh65=64309;e.vavdageshhebrew=64309;e.vavhebrew=1493;e.vavholam=64331;e.vavholamhebrew=64331;e.vavvavhebrew=1520;e.vavyodhebrew=1521;e.vcircle=9445;e.vdotbelow=7807;e.vecyrillic=1074;e.veharabic=1700;e.vehfinalarabic=64363;e.vehinitialarabic=64364;e.vehmedialarabic=64365;e.vekatakana=12537;e.venus=9792;e.verticalbar=124;e.verticallineabovecmb=781;e.verticallinebelowcmb=809;e.verticallinelowmod=716;e.verticallinemod=712;e.vewarmenian=1406;e.vhook=651;e.vikatakana=12536;e.viramabengali=2509;e.viramadeva=2381;e.viramagujarati=2765;e.visargabengali=2435;e.visargadeva=2307;e.visargagujarati=2691;e.vmonospace=65366;e.voarmenian=1400;e.voicediterationhiragana=12446;e.voicediterationkatakana=12542;e.voicedmarkkana=12443;e.voicedmarkkanahalfwidth=65438;e.vokatakana=12538;e.vparen=9393;e.vtilde=7805;e.vturned=652;e.vuhiragana=12436;e.vukatakana=12532;e.w=119;e.wacute=7811;e.waekorean=12633;e.wahiragana=12431;e.wakatakana=12527;e.wakatakanahalfwidth=65436;e.wakorean=12632;e.wasmallhiragana=12430;e.wasmallkatakana=12526;e.wattosquare=13143;e.wavedash=12316;e.wavyunderscorevertical=65076;e.wawarabic=1608;e.wawfinalarabic=65262;e.wawhamzaabovearabic=1572;e.wawhamzaabovefinalarabic=65158;e.wbsquare=13277;e.wcircle=9446;e.wcircumflex=373;e.wdieresis=7813;e.wdotaccent=7815;e.wdotbelow=7817;e.wehiragana=12433;e.weierstrass=8472;e.wekatakana=12529;e.wekorean=12638;e.weokorean=12637;e.wgrave=7809;e.whitebullet=9702;e.whitecircle=9675;e.whitecircleinverse=9689;e.whitecornerbracketleft=12302;e.whitecornerbracketleftvertical=65091;e.whitecornerbracketright=12303;e.whitecornerbracketrightvertical=65092;e.whitediamond=9671;e.whitediamondcontainingblacksmalldiamond=9672;e.whitedownpointingsmalltriangle=9663;e.whitedownpointingtriangle=9661;e.whiteleftpointingsmalltriangle=9667;e.whiteleftpointingtriangle=9665;e.whitelenticularbracketleft=12310;e.whitelenticularbracketright=12311;e.whiterightpointingsmalltriangle=9657;e.whiterightpointingtriangle=9655;e.whitesmallsquare=9643;e.whitesmilingface=9786;e.whitesquare=9633;e.whitestar=9734;e.whitetelephone=9743;e.whitetortoiseshellbracketleft=12312;e.whitetortoiseshellbracketright=12313;e.whiteuppointingsmalltriangle=9653;e.whiteuppointingtriangle=9651;e.wihiragana=12432;e.wikatakana=12528;e.wikorean=12639;e.wmonospace=65367;e.wohiragana=12434;e.wokatakana=12530;e.wokatakanahalfwidth=65382;e.won=8361;e.wonmonospace=65510;e.wowaenthai=3623;e.wparen=9394;e.wring=7832;e.wsuperior=695;e.wturned=653;e.wynn=447;e.x=120;e.xabovecmb=829;e.xbopomofo=12562;e.xcircle=9447;e.xdieresis=7821;e.xdotaccent=7819;e.xeharmenian=1389;e.xi=958;e.xmonospace=65368;e.xparen=9395;e.xsuperior=739;e.y=121;e.yaadosquare=13134;e.yabengali=2479;e.yacute=253;e.yadeva=2351;e.yaekorean=12626;e.yagujarati=2735;e.yagurmukhi=2607;e.yahiragana=12420;e.yakatakana=12516;e.yakatakanahalfwidth=65428;e.yakorean=12625;e.yamakkanthai=3662;e.yasmallhiragana=12419;e.yasmallkatakana=12515;e.yasmallkatakanahalfwidth=65388;e.yatcyrillic=1123;e.ycircle=9448;e.ycircumflex=375;e.ydieresis=255;e.ydotaccent=7823;e.ydotbelow=7925;e.yeharabic=1610;e.yehbarreearabic=1746;e.yehbarreefinalarabic=64431;e.yehfinalarabic=65266;e.yehhamzaabovearabic=1574;e.yehhamzaabovefinalarabic=65162;e.yehhamzaaboveinitialarabic=65163;e.yehhamzaabovemedialarabic=65164;e.yehinitialarabic=65267;e.yehmedialarabic=65268;e.yehmeeminitialarabic=64733;e.yehmeemisolatedarabic=64600;e.yehnoonfinalarabic=64660;e.yehthreedotsbelowarabic=1745;e.yekorean=12630;e.yen=165;e.yenmonospace=65509;e.yeokorean=12629;e.yeorinhieuhkorean=12678;e.yerahbenyomohebrew=1450;e.yerahbenyomolefthebrew=1450;e.yericyrillic=1099;e.yerudieresiscyrillic=1273;e.yesieungkorean=12673;e.yesieungpansioskorean=12675;e.yesieungsioskorean=12674;e.yetivhebrew=1434;e.ygrave=7923;e.yhook=436;e.yhookabove=7927;e.yiarmenian=1397;e.yicyrillic=1111;e.yikorean=12642;e.yinyang=9775;e.yiwnarmenian=1410;e.ymonospace=65369;e.yod=1497;e.yoddagesh=64313;e.yoddageshhebrew=64313;e.yodhebrew=1497;e.yodyodhebrew=1522;e.yodyodpatahhebrew=64287;e.yohiragana=12424;e.yoikorean=12681;e.yokatakana=12520;e.yokatakanahalfwidth=65430;e.yokorean=12635;e.yosmallhiragana=12423;e.yosmallkatakana=12519;e.yosmallkatakanahalfwidth=65390;e.yotgreek=1011;e.yoyaekorean=12680;e.yoyakorean=12679;e.yoyakthai=3618;e.yoyingthai=3597;e.yparen=9396;e.ypogegrammeni=890;e.ypogegrammenigreekcmb=837;e.yr=422;e.yring=7833;e.ysuperior=696;e.ytilde=7929;e.yturned=654;e.yuhiragana=12422;e.yuikorean=12684;e.yukatakana=12518;e.yukatakanahalfwidth=65429;e.yukorean=12640;e.yusbigcyrillic=1131;e.yusbigiotifiedcyrillic=1133;e.yuslittlecyrillic=1127;e.yuslittleiotifiedcyrillic=1129;e.yusmallhiragana=12421;e.yusmallkatakana=12517;e.yusmallkatakanahalfwidth=65389;e.yuyekorean=12683;e.yuyeokorean=12682;e.yyabengali=2527;e.yyadeva=2399;e.z=122;e.zaarmenian=1382;e.zacute=378;e.zadeva=2395;e.zagurmukhi=2651;e.zaharabic=1592;e.zahfinalarabic=65222;e.zahinitialarabic=65223;e.zahiragana=12374;e.zahmedialarabic=65224;e.zainarabic=1586;e.zainfinalarabic=65200;e.zakatakana=12470;e.zaqefgadolhebrew=1429;e.zaqefqatanhebrew=1428;e.zarqahebrew=1432;e.zayin=1494;e.zayindagesh=64310;e.zayindageshhebrew=64310;e.zayinhebrew=1494;e.zbopomofo=12567;e.zcaron=382;e.zcircle=9449;e.zcircumflex=7825;e.zcurl=657;e.zdot=380;e.zdotaccent=380;e.zdotbelow=7827;e.zecyrillic=1079;e.zedescendercyrillic=1177;e.zedieresiscyrillic=1247;e.zehiragana=12380;e.zekatakana=12476;e.zero=48;e.zeroarabic=1632;e.zerobengali=2534;e.zerodeva=2406;e.zerogujarati=2790;e.zerogurmukhi=2662;e.zerohackarabic=1632;e.zeroinferior=8320;e.zeromonospace=65296;e.zerooldstyle=63280;e.zeropersian=1776;e.zerosuperior=8304;e.zerothai=3664;e.zerowidthjoiner=65279;e.zerowidthnonjoiner=8204;e.zerowidthspace=8203;e.zeta=950;e.zhbopomofo=12563;e.zhearmenian=1386;e.zhebrevecyrillic=1218;e.zhecyrillic=1078;e.zhedescendercyrillic=1175;e.zhedieresiscyrillic=1245;e.zihiragana=12376;e.zikatakana=12472;e.zinorhebrew=1454;e.zlinebelow=7829;e.zmonospace=65370;e.zohiragana=12382;e.zokatakana=12478;e.zparen=9397;e.zretroflexhook=656;e.zstroke=438;e.zuhiragana=12378;e.zukatakana=12474;e[".notdef"]=0;e.angbracketleftbig=9001;e.angbracketleftBig=9001;e.angbracketleftbigg=9001;e.angbracketleftBigg=9001;e.angbracketrightBig=9002;e.angbracketrightbig=9002;e.angbracketrightBigg=9002;e.angbracketrightbigg=9002;e.arrowhookleft=8618;e.arrowhookright=8617;e.arrowlefttophalf=8636;e.arrowleftbothalf=8637;e.arrownortheast=8599;e.arrownorthwest=8598;e.arrowrighttophalf=8640;e.arrowrightbothalf=8641;e.arrowsoutheast=8600;e.arrowsouthwest=8601;e.backslashbig=8726;e.backslashBig=8726;e.backslashBigg=8726;e.backslashbigg=8726;e.bardbl=8214;e.bracehtipdownleft=65079;e.bracehtipdownright=65079;e.bracehtipupleft=65080;e.bracehtipupright=65080;e.braceleftBig=123;e.braceleftbig=123;e.braceleftbigg=123;e.braceleftBigg=123;e.bracerightBig=125;e.bracerightbig=125;e.bracerightbigg=125;e.bracerightBigg=125;e.bracketleftbig=91;e.bracketleftBig=91;e.bracketleftbigg=91;e.bracketleftBigg=91;e.bracketrightBig=93;e.bracketrightbig=93;e.bracketrightbigg=93;e.bracketrightBigg=93;e.ceilingleftbig=8968;e.ceilingleftBig=8968;e.ceilingleftBigg=8968;e.ceilingleftbigg=8968;e.ceilingrightbig=8969;e.ceilingrightBig=8969;e.ceilingrightbigg=8969;e.ceilingrightBigg=8969;e.circledotdisplay=8857;e.circledottext=8857;e.circlemultiplydisplay=8855;e.circlemultiplytext=8855;e.circleplusdisplay=8853;e.circleplustext=8853;e.contintegraldisplay=8750;e.contintegraltext=8750;e.coproductdisplay=8720;e.coproducttext=8720;e.floorleftBig=8970;e.floorleftbig=8970;e.floorleftbigg=8970;e.floorleftBigg=8970;e.floorrightbig=8971;e.floorrightBig=8971;e.floorrightBigg=8971;e.floorrightbigg=8971;e.hatwide=770;e.hatwider=770;e.hatwidest=770;e.intercal=7488;e.integraldisplay=8747;e.integraltext=8747;e.intersectiondisplay=8898;e.intersectiontext=8898;e.logicalanddisplay=8743;e.logicalandtext=8743;e.logicalordisplay=8744;e.logicalortext=8744;e.parenleftBig=40;e.parenleftbig=40;e.parenleftBigg=40;e.parenleftbigg=40;e.parenrightBig=41;e.parenrightbig=41;e.parenrightBigg=41;e.parenrightbigg=41;e.prime=8242;e.productdisplay=8719;e.producttext=8719;e.radicalbig=8730;e.radicalBig=8730;e.radicalBigg=8730;e.radicalbigg=8730;e.radicalbt=8730;e.radicaltp=8730;e.radicalvertex=8730;e.slashbig=47;e.slashBig=47;e.slashBigg=47;e.slashbigg=47;e.summationdisplay=8721;e.summationtext=8721;e.tildewide=732;e.tildewider=732;e.tildewidest=732;e.uniondisplay=8899;e.unionmultidisplay=8846;e.unionmultitext=8846;e.unionsqdisplay=8852;e.unionsqtext=8852;e.uniontext=8899;e.vextenddouble=8741;e.vextendsingle=8739}),n=a(function(e){e.space=32;e.a1=9985;e.a2=9986;e.a202=9987;e.a3=9988;e.a4=9742;e.a5=9990;e.a119=9991;e.a118=9992;e.a117=9993;e.a11=9755;e.a12=9758;e.a13=9996;e.a14=9997;e.a15=9998;e.a16=9999;e.a105=1e4;e.a17=10001;e.a18=10002;e.a19=10003;e.a20=10004;e.a21=10005;e.a22=10006;e.a23=10007;e.a24=10008;e.a25=10009;e.a26=10010;e.a27=10011;e.a28=10012;e.a6=10013;e.a7=10014;e.a8=10015;e.a9=10016;e.a10=10017;e.a29=10018;e.a30=10019;e.a31=10020;e.a32=10021;e.a33=10022;e.a34=10023;e.a35=9733;e.a36=10025;e.a37=10026;e.a38=10027;e.a39=10028;e.a40=10029;e.a41=10030;e.a42=10031;e.a43=10032;e.a44=10033;e.a45=10034;e.a46=10035;e.a47=10036;e.a48=10037;e.a49=10038;e.a50=10039;e.a51=10040;e.a52=10041;e.a53=10042;e.a54=10043;e.a55=10044;e.a56=10045;e.a57=10046;e.a58=10047;e.a59=10048;e.a60=10049;e.a61=10050;e.a62=10051;e.a63=10052;e.a64=10053;e.a65=10054;e.a66=10055;e.a67=10056;e.a68=10057;e.a69=10058;e.a70=10059;e.a71=9679;e.a72=10061;e.a73=9632;e.a74=10063;e.a203=10064;e.a75=10065;e.a204=10066;e.a76=9650;e.a77=9660;e.a78=9670;e.a79=10070;e.a81=9687;e.a82=10072;e.a83=10073;e.a84=10074;e.a97=10075;e.a98=10076;e.a99=10077;e.a100=10078;e.a101=10081;e.a102=10082;e.a103=10083;e.a104=10084;e.a106=10085;e.a107=10086;e.a108=10087;e.a112=9827;e.a111=9830;e.a110=9829;e.a109=9824;e.a120=9312;e.a121=9313;e.a122=9314;e.a123=9315;e.a124=9316;e.a125=9317;e.a126=9318;e.a127=9319;e.a128=9320;e.a129=9321;e.a130=10102;e.a131=10103;e.a132=10104;e.a133=10105;e.a134=10106;e.a135=10107;e.a136=10108;e.a137=10109;e.a138=10110;e.a139=10111;e.a140=10112;e.a141=10113;e.a142=10114;e.a143=10115;e.a144=10116;e.a145=10117;e.a146=10118;e.a147=10119;e.a148=10120;e.a149=10121;e.a150=10122;e.a151=10123;e.a152=10124;e.a153=10125;e.a154=10126;e.a155=10127;e.a156=10128;e.a157=10129;e.a158=10130;e.a159=10131;e.a160=10132;e.a161=8594;e.a163=8596;e.a164=8597;e.a196=10136;e.a165=10137;e.a192=10138;e.a166=10139;e.a167=10140;e.a168=10141;e.a169=10142;e.a170=10143;e.a171=10144;e.a172=10145;e.a173=10146;e.a162=10147;e.a174=10148;e.a175=10149;e.a176=10150;e.a177=10151;e.a178=10152;e.a179=10153;e.a193=10154;e.a180=10155;e.a199=10156;e.a181=10157;e.a200=10158;e.a182=10159;e.a201=10161;e.a183=10162;e.a184=10163;e.a197=10164;e.a185=10165;e.a194=10166;e.a198=10167;e.a186=10168;e.a195=10169;e.a187=10170;e.a188=10171;e.a189=10172;e.a190=10173;e.a191=10174;e.a89=10088;e.a90=10089;e.a93=10090;e.a94=10091;e.a91=10092;e.a92=10093;e.a205=10094;e.a85=10095;e.a206=10096;e.a86=10097;e.a87=10098;e.a88=10099;e.a95=10100;e.a96=10101;e[".notdef"]=0});t.getGlyphsUnicode=i;t.getDingbatsGlyphsUnicode=n},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.getSupplementalGlyphMapForCalibri=t.getSupplementalGlyphMapForArialBlack=t.getGlyphMapForStandardFonts=t.getSymbolsFonts=t.getSerifFonts=t.getNonStdFontMap=t.getStdFontMap=void 0;var a=r(2),i=(0,a.getLookupTableFactory)(function(e){e.ArialNarrow="Helvetica";e["ArialNarrow-Bold"]="Helvetica-Bold";e["ArialNarrow-BoldItalic"]="Helvetica-BoldOblique";e["ArialNarrow-Italic"]="Helvetica-Oblique";e.ArialBlack="Helvetica";e["ArialBlack-Bold"]="Helvetica-Bold";e["ArialBlack-BoldItalic"]="Helvetica-BoldOblique";e["ArialBlack-Italic"]="Helvetica-Oblique";e["Arial-Black"]="Helvetica";e["Arial-Black-Bold"]="Helvetica-Bold";e["Arial-Black-BoldItalic"]="Helvetica-BoldOblique";e["Arial-Black-Italic"]="Helvetica-Oblique";e.Arial="Helvetica";e["Arial-Bold"]="Helvetica-Bold";e["Arial-BoldItalic"]="Helvetica-BoldOblique";e["Arial-Italic"]="Helvetica-Oblique";e["Arial-BoldItalicMT"]="Helvetica-BoldOblique";e["Arial-BoldMT"]="Helvetica-Bold";e["Arial-ItalicMT"]="Helvetica-Oblique";e.ArialMT="Helvetica";e["Courier-Bold"]="Courier-Bold";e["Courier-BoldItalic"]="Courier-BoldOblique";e["Courier-Italic"]="Courier-Oblique";e.CourierNew="Courier";e["CourierNew-Bold"]="Courier-Bold";e["CourierNew-BoldItalic"]="Courier-BoldOblique";e["CourierNew-Italic"]="Courier-Oblique";e["CourierNewPS-BoldItalicMT"]="Courier-BoldOblique";e["CourierNewPS-BoldMT"]="Courier-Bold";e["CourierNewPS-ItalicMT"]="Courier-Oblique";e.CourierNewPSMT="Courier";e.Helvetica="Helvetica";e["Helvetica-Bold"]="Helvetica-Bold";e["Helvetica-BoldItalic"]="Helvetica-BoldOblique";e["Helvetica-BoldOblique"]="Helvetica-BoldOblique";e["Helvetica-Italic"]="Helvetica-Oblique";e["Helvetica-Oblique"]="Helvetica-Oblique";e.SegoeUISymbol="Helvetica";e["Symbol-Bold"]="Symbol";e["Symbol-BoldItalic"]="Symbol";e["Symbol-Italic"]="Symbol";e.TimesNewRoman="Times-Roman";e["TimesNewRoman-Bold"]="Times-Bold";e["TimesNewRoman-BoldItalic"]="Times-BoldItalic";e["TimesNewRoman-Italic"]="Times-Italic";e.TimesNewRomanPS="Times-Roman";e["TimesNewRomanPS-Bold"]="Times-Bold";e["TimesNewRomanPS-BoldItalic"]="Times-BoldItalic";e["TimesNewRomanPS-BoldItalicMT"]="Times-BoldItalic";e["TimesNewRomanPS-BoldMT"]="Times-Bold";e["TimesNewRomanPS-Italic"]="Times-Italic";e["TimesNewRomanPS-ItalicMT"]="Times-Italic";e.TimesNewRomanPSMT="Times-Roman";e["TimesNewRomanPSMT-Bold"]="Times-Bold";e["TimesNewRomanPSMT-BoldItalic"]="Times-BoldItalic";e["TimesNewRomanPSMT-Italic"]="Times-Italic"}),n=(0,a.getLookupTableFactory)(function(e){e.Calibri="Helvetica";e["Calibri-Bold"]="Helvetica-Bold";e["Calibri-BoldItalic"]="Helvetica-BoldOblique";e["Calibri-Italic"]="Helvetica-Oblique";e.CenturyGothic="Helvetica";e["CenturyGothic-Bold"]="Helvetica-Bold";e["CenturyGothic-BoldItalic"]="Helvetica-BoldOblique";e["CenturyGothic-Italic"]="Helvetica-Oblique";e.ComicSansMS="Comic Sans MS";e["ComicSansMS-Bold"]="Comic Sans MS-Bold";e["ComicSansMS-BoldItalic"]="Comic Sans MS-BoldItalic";e["ComicSansMS-Italic"]="Comic Sans MS-Italic";e.LucidaConsole="Courier";e["LucidaConsole-Bold"]="Courier-Bold";e["LucidaConsole-BoldItalic"]="Courier-BoldOblique";e["LucidaConsole-Italic"]="Courier-Oblique";e["LucidaSans-Demi"]="Helvetica-Bold";e["MS-Gothic"]="MS Gothic";e["MS-Gothic-Bold"]="MS Gothic-Bold";e["MS-Gothic-BoldItalic"]="MS Gothic-BoldItalic";e["MS-Gothic-Italic"]="MS Gothic-Italic";e["MS-Mincho"]="MS Mincho";e["MS-Mincho-Bold"]="MS Mincho-Bold";e["MS-Mincho-BoldItalic"]="MS Mincho-BoldItalic";e["MS-Mincho-Italic"]="MS Mincho-Italic";e["MS-PGothic"]="MS PGothic";e["MS-PGothic-Bold"]="MS PGothic-Bold";e["MS-PGothic-BoldItalic"]="MS PGothic-BoldItalic";e["MS-PGothic-Italic"]="MS PGothic-Italic";e["MS-PMincho"]="MS PMincho";e["MS-PMincho-Bold"]="MS PMincho-Bold";e["MS-PMincho-BoldItalic"]="MS PMincho-BoldItalic";e["MS-PMincho-Italic"]="MS PMincho-Italic";e.NuptialScript="Times-Italic";e.Wingdings="ZapfDingbats"}),o=(0,a.getLookupTableFactory)(function(e){e["Adobe Jenson"]=!0;e["Adobe Text"]=!0;e.Albertus=!0;e.Aldus=!0;e.Alexandria=!0;e.Algerian=!0;e["American Typewriter"]=!0;e.Antiqua=!0;e.Apex=!0;e.Arno=!0;e.Aster=!0;e.Aurora=!0;e.Baskerville=!0;e.Bell=!0;e.Bembo=!0;e["Bembo Schoolbook"]=!0;e.Benguiat=!0;e["Berkeley Old Style"]=!0;e["Bernhard Modern"]=!0;e["Berthold City"]=!0;e.Bodoni=!0;e["Bauer Bodoni"]=!0;e["Book Antiqua"]=!0;e.Bookman=!0;e["Bordeaux Roman"]=!0;e["Californian FB"]=!0;e.Calisto=!0;e.Calvert=!0;e.Capitals=!0;e.Cambria=!0;e.Cartier=!0;e.Caslon=!0;e.Catull=!0;e.Centaur=!0;e["Century Old Style"]=!0;e["Century Schoolbook"]=!0;e.Chaparral=!0;e["Charis SIL"]=!0;e.Cheltenham=!0;e["Cholla Slab"]=!0;e.Clarendon=!0;e.Clearface=!0;e.Cochin=!0;e.Colonna=!0;e["Computer Modern"]=!0;e["Concrete Roman"]=!0;e.Constantia=!0;e["Cooper Black"]=!0;e.Corona=!0;e.Ecotype=!0;e.Egyptienne=!0;e.Elephant=!0;e.Excelsior=!0;e.Fairfield=!0;e["FF Scala"]=!0;e.Folkard=!0;e.Footlight=!0;e.FreeSerif=!0;e["Friz Quadrata"]=!0;e.Garamond=!0;e.Gentium=!0;e.Georgia=!0;e.Gloucester=!0;e["Goudy Old Style"]=!0;e["Goudy Schoolbook"]=!0;e["Goudy Pro Font"]=!0;e.Granjon=!0;e["Guardian Egyptian"]=!0;e.Heather=!0;e.Hercules=!0;e["High Tower Text"]=!0;e.Hiroshige=!0;e["Hoefler Text"]=!0;e["Humana Serif"]=!0;e.Imprint=!0;e["Ionic No. 5"]=!0;e.Janson=!0;e.Joanna=!0;e.Korinna=!0;e.Lexicon=!0;e["Liberation Serif"]=!0;e["Linux Libertine"]=!0;e.Literaturnaya=!0;e.Lucida=!0;e["Lucida Bright"]=!0;e.Melior=!0;e.Memphis=!0;e.Miller=!0;e.Minion=!0;e.Modern=!0;e["Mona Lisa"]=!0;e["Mrs Eaves"]=!0;e["MS Serif"]=!0;e["Museo Slab"]=!0;e["New York"]=!0;e["Nimbus Roman"]=!0;e["NPS Rawlinson Roadway"]=!0;e.NuptialScript=!0;e.Palatino=!0;e.Perpetua=!0;e.Plantin=!0;e["Plantin Schoolbook"]=!0;e.Playbill=!0;e["Poor Richard"]=!0;e["Rawlinson Roadway"]=!0;e.Renault=!0;e.Requiem=!0;e.Rockwell=!0;e.Roman=!0;e["Rotis Serif"]=!0;e.Sabon=!0;e.Scala=!0;e.Seagull=!0;e.Sistina=!0;e.Souvenir=!0;e.STIX=!0;e["Stone Informal"]=!0;e["Stone Serif"]=!0;e.Sylfaen=!0;e.Times=!0;e.Trajan=!0;e["Trinité"]=!0;e["Trump Mediaeval"]=!0;e.Utopia=!0;e["Vale Type"]=!0;e["Bitstream Vera"]=!0;e["Vera Serif"]=!0;e.Versailles=!0;e.Wanted=!0;e.Weiss=!0;e["Wide Latin"]=!0;e.Windsor=!0;e.XITS=!0}),s=(0,a.getLookupTableFactory)(function(e){e.Dingbats=!0;e.Symbol=!0;e.ZapfDingbats=!0}),c=(0,a.getLookupTableFactory)(function(e){e[2]=10;e[3]=32;e[4]=33;e[5]=34;e[6]=35;e[7]=36;e[8]=37;e[9]=38;e[10]=39;e[11]=40;e[12]=41;e[13]=42;e[14]=43;e[15]=44;e[16]=45;e[17]=46;e[18]=47;e[19]=48;e[20]=49;e[21]=50;e[22]=51;e[23]=52;e[24]=53;e[25]=54;e[26]=55;e[27]=56;e[28]=57;e[29]=58;e[30]=894;e[31]=60;e[32]=61;e[33]=62;e[34]=63;e[35]=64;e[36]=65;e[37]=66;e[38]=67;e[39]=68;e[40]=69;e[41]=70;e[42]=71;e[43]=72;e[44]=73;e[45]=74;e[46]=75;e[47]=76;e[48]=77;e[49]=78;e[50]=79;e[51]=80;e[52]=81;e[53]=82;e[54]=83;e[55]=84;e[56]=85;e[57]=86;e[58]=87;e[59]=88;e[60]=89;e[61]=90;e[62]=91;e[63]=92;e[64]=93;e[65]=94;e[66]=95;e[67]=96;e[68]=97;e[69]=98;e[70]=99;e[71]=100;e[72]=101;e[73]=102;e[74]=103;e[75]=104;e[76]=105;e[77]=106;e[78]=107;e[79]=108;e[80]=109;e[81]=110;e[82]=111;e[83]=112;e[84]=113;e[85]=114;e[86]=115;e[87]=116;e[88]=117;e[89]=118;e[90]=119;e[91]=120;e[92]=121;e[93]=122;e[94]=123;e[95]=124;e[96]=125;e[97]=126;e[98]=196;e[99]=197;e[100]=199;e[101]=201;e[102]=209;e[103]=214;e[104]=220;e[105]=225;e[106]=224;e[107]=226;e[108]=228;e[109]=227;e[110]=229;e[111]=231;e[112]=233;e[113]=232;e[114]=234;e[115]=235;e[116]=237;e[117]=236;e[118]=238;e[119]=239;e[120]=241;e[121]=243;e[122]=242;e[123]=244;e[124]=246;e[125]=245;e[126]=250;e[127]=249;e[128]=251;e[129]=252;e[130]=8224;e[131]=176;e[132]=162;e[133]=163;e[134]=167;e[135]=8226;e[136]=182;e[137]=223;e[138]=174;e[139]=169;e[140]=8482;e[141]=180;e[142]=168;e[143]=8800;e[144]=198;e[145]=216;e[146]=8734;e[147]=177;e[148]=8804;e[149]=8805;e[150]=165;e[151]=181;e[152]=8706;e[153]=8721;e[154]=8719;e[156]=8747;e[157]=170;e[158]=186;e[159]=8486;e[160]=230;e[161]=248;e[162]=191;e[163]=161;e[164]=172;e[165]=8730;e[166]=402;e[167]=8776;e[168]=8710;e[169]=171;e[170]=187;e[171]=8230;e[210]=218;e[223]=711;e[224]=321;e[225]=322;e[227]=353;e[229]=382;e[234]=253;e[252]=263;e[253]=268;e[254]=269;e[258]=258;e[260]=260;e[261]=261;e[265]=280;e[266]=281;e[268]=283;e[269]=313;e[275]=323;e[276]=324;e[278]=328;e[284]=345;e[285]=346;e[286]=347;e[292]=367;e[295]=377;e[296]=378;e[298]=380;e[305]=963;e[306]=964;e[307]=966;e[308]=8215;e[309]=8252;e[310]=8319;e[311]=8359;e[312]=8592;e[313]=8593;e[337]=9552;e[493]=1039;e[494]=1040;e[705]=1524;e[706]=8362;e[710]=64288;e[711]=64298;e[759]=1617;e[761]=1776;e[763]=1778;e[775]=1652;e[777]=1764;e[778]=1780;e[779]=1781;e[780]=1782;e[782]=771;e[783]=64726;e[786]=8363;e[788]=8532;e[790]=768;e[791]=769;e[792]=768;e[795]=803;e[797]=64336;e[798]=64337;e[799]=64342;e[800]=64343;e[801]=64344;e[802]=64345;e[803]=64362;e[804]=64363;e[805]=64364;e[2424]=7821;e[2425]=7822;e[2426]=7823;e[2427]=7824;e[2428]=7825;e[2429]=7826;e[2430]=7827;e[2433]=7682;e[2678]=8045;e[2679]=8046;e[2830]=1552;e[2838]=686;e[2840]=751;e[2842]=753;e[2843]=754;e[2844]=755;e[2846]=757;e[2856]=767;e[2857]=848;e[2858]=849;e[2862]=853;e[2863]=854;e[2864]=855;e[2865]=861;e[2866]=862;e[2906]=7460;e[2908]=7462;e[2909]=7463;e[2910]=7464;e[2912]=7466;e[2913]=7467;e[2914]=7468;e[2916]=7470;e[2917]=7471;e[2918]=7472;e[2920]=7474;e[2921]=7475;e[2922]=7476;e[2924]=7478;e[2925]=7479;e[2926]=7480;e[2928]=7482;e[2929]=7483;e[2930]=7484;e[2932]=7486;e[2933]=7487;e[2934]=7488;e[2936]=7490;e[2937]=7491;e[2938]=7492;e[2940]=7494;e[2941]=7495;e[2942]=7496;e[2944]=7498;e[2946]=7500;e[2948]=7502;e[2950]=7504;e[2951]=7505;e[2952]=7506;e[2954]=7508;e[2955]=7509;e[2956]=7510;e[2958]=7512;e[2959]=7513;e[2960]=7514;e[2962]=7516;e[2963]=7517;e[2964]=7518;e[2966]=7520;e[2967]=7521;e[2968]=7522;e[2970]=7524;e[2971]=7525;e[2972]=7526;e[2974]=7528;e[2975]=7529;e[2976]=7530;e[2978]=1537;e[2979]=1538;e[2980]=1539;e[2982]=1549;e[2983]=1551;e[2984]=1552;e[2986]=1554;e[2987]=1555;e[2988]=1556;e[2990]=1623;e[2991]=1624;e[2995]=1775;e[2999]=1791;e[3002]=64290;e[3003]=64291;e[3004]=64292;e[3006]=64294;e[3007]=64295;e[3008]=64296;e[3011]=1900;e[3014]=8223;e[3015]=8244;e[3017]=7532;e[3018]=7533;e[3019]=7534;e[3075]=7590;e[3076]=7591;e[3079]=7594;e[3080]=7595;e[3083]=7598;e[3084]=7599;e[3087]=7602;e[3088]=7603;e[3091]=7606;e[3092]=7607;e[3095]=7610;e[3096]=7611;e[3099]=7614;e[3100]=7615;e[3103]=7618;e[3104]=7619;e[3107]=8337;e[3108]=8338;e[3116]=1884;e[3119]=1885;e[3120]=1885;e[3123]=1886;e[3124]=1886;e[3127]=1887;e[3128]=1887;e[3131]=1888;e[3132]=1888;e[3135]=1889;e[3136]=1889;e[3139]=1890;e[3140]=1890;e[3143]=1891;e[3144]=1891;e[3147]=1892;e[3148]=1892;e[3153]=580;e[3154]=581;e[3157]=584;e[3158]=585;e[3161]=588;e[3162]=589;e[3165]=891;e[3166]=892;e[3169]=1274;e[3170]=1275;e[3173]=1278;e[3174]=1279;e[3181]=7622;e[3182]=7623;e[3282]=11799;e[3316]=578;e[3379]=42785;e[3393]=1159;e[3416]=8377}),l=(0,a.getLookupTableFactory)(function(e){e[227]=322;e[264]=261;e[291]=346}),u=(0,a.getLookupTableFactory)(function(e){e[1]=32;e[4]=65;e[17]=66;e[18]=67;e[24]=68;e[28]=69;e[38]=70;e[39]=71;e[44]=72;e[47]=73;e[58]=74;e[60]=75;e[62]=76;e[68]=77;e[69]=78;e[75]=79;e[87]=80;e[89]=81;e[90]=82;e[94]=83;e[100]=84;e[104]=85;e[115]=86;e[116]=87;e[121]=88;e[122]=89;e[127]=90;e[258]=97;e[268]=261;e[271]=98;e[272]=99;e[273]=263;e[282]=100;e[286]=101;e[295]=281;e[296]=102;e[336]=103;e[346]=104;e[349]=105;e[361]=106;e[364]=107;e[367]=108;e[371]=322;e[373]=109;e[374]=110;e[381]=111;e[383]=243;e[393]=112;e[395]=113;e[396]=114;e[400]=115;e[401]=347;e[410]=116;e[437]=117;e[448]=118;e[449]=119;e[454]=120;e[455]=121;e[460]=122;e[463]=380;e[853]=44;e[855]=58;e[856]=46;e[876]=47;e[878]=45;e[882]=45;e[894]=40;e[895]=41;e[896]=91;e[897]=93;e[923]=64;e[1004]=48;e[1005]=49;e[1006]=50;e[1007]=51;e[1008]=52;e[1009]=53;e[1010]=54;e[1011]=55;e[1012]=56;e[1013]=57;e[1081]=37;e[1085]=43;e[1086]=45});t.getStdFontMap=i;t.getNonStdFontMap=n;t.getSerifFonts=o;t.getSymbolsFonts=s;t.getGlyphMapForStandardFonts=c;t.getSupplementalGlyphMapForArialBlack=l;t.getSupplementalGlyphMapForCalibri=u},function(e,t,r){var a=r(2).getLookupTableFactory,i=a(function(e){e[63721]=169;e[63193]=169;e[63720]=174;e[63194]=174;e[63722]=8482;e[63195]=8482;e[63729]=9127;e[63730]=9128;e[63731]=9129;e[63740]=9131;e[63741]=9132;e[63742]=9133;e[63726]=9121;e[63727]=9122;e[63728]=9123;e[63737]=9124;e[63738]=9125;e[63739]=9126;e[63723]=9115;e[63724]=9116;e[63725]=9117;e[63734]=9118;e[63735]=9119;e[63736]=9120});var n=[{begin:0,end:127},{begin:128,end:255},{begin:256,end:383},{begin:384,end:591},{begin:592,end:687},{begin:688,end:767},{begin:768,end:879},{begin:880,end:1023},{begin:11392,end:11519},{begin:1024,end:1279},{begin:1328,end:1423},{begin:1424,end:1535},{begin:42240,end:42559},{begin:1536,end:1791},{begin:1984,end:2047},{begin:2304,end:2431},{begin:2432,end:2559},{begin:2560,end:2687},{begin:2688,end:2815},{begin:2816,end:2943},{begin:2944,end:3071},{begin:3072,end:3199},{begin:3200,end:3327},{begin:3328,end:3455},{begin:3584,end:3711},{begin:3712,end:3839},{begin:4256,end:4351},{begin:6912,end:7039},{begin:4352,end:4607},{begin:7680,end:7935},{begin:7936,end:8191},{begin:8192,end:8303},{begin:8304,end:8351},{begin:8352,end:8399},{begin:8400,end:8447},{begin:8448,end:8527},{begin:8528,end:8591},{begin:8592,end:8703},{begin:8704,end:8959},{begin:8960,end:9215},{begin:9216,end:9279},{begin:9280,end:9311},{begin:9312,end:9471},{begin:9472,end:9599},{begin:9600,end:9631},{begin:9632,end:9727},{begin:9728,end:9983},{begin:9984,end:10175},{begin:12288,end:12351},{begin:12352,end:12447},{begin:12448,end:12543},{begin:12544,end:12591},{begin:12592,end:12687},{begin:43072,end:43135},{begin:12800,end:13055},{begin:13056,end:13311},{begin:44032,end:55215},{begin:55296,end:57343},{begin:67840,end:67871},{begin:19968,end:40959},{begin:57344,end:63743},{begin:12736,end:12783},{begin:64256,end:64335},{begin:64336,end:65023},{begin:65056,end:65071},{begin:65040,end:65055},{begin:65104,end:65135},{begin:65136,end:65279},{begin:65280,end:65519},{begin:65520,end:65535},{begin:3840,end:4095},{begin:1792,end:1871},{begin:1920,end:1983},{begin:3456,end:3583},{begin:4096,end:4255},{begin:4608,end:4991},{begin:5024,end:5119},{begin:5120,end:5759},{begin:5760,end:5791},{begin:5792,end:5887},{begin:6016,end:6143},{begin:6144,end:6319},{begin:10240,end:10495},{begin:40960,end:42127},{begin:5888,end:5919},{begin:66304,end:66351},{begin:66352,end:66383},{begin:66560,end:66639},{begin:118784,end:119039},{begin:119808,end:120831},{begin:1044480,end:1048573},{begin:65024,end:65039},{begin:917504,end:917631},{begin:6400,end:6479},{begin:6480,end:6527},{begin:6528,end:6623},{begin:6656,end:6687},{begin:11264,end:11359},{begin:11568,end:11647},{begin:19904,end:19967},{begin:43008,end:43055},{begin:65536,end:65663},{begin:65856,end:65935},{begin:66432,end:66463},{begin:66464,end:66527},{begin:66640,end:66687},{begin:66688,end:66735},{begin:67584,end:67647},{begin:68096,end:68191},{begin:119552,end:119647},{begin:73728,end:74751},{begin:119648,end:119679},{begin:7040,end:7103},{begin:7168,end:7247},{begin:7248,end:7295},{begin:43136,end:43231},{begin:43264,end:43311},{begin:43312,end:43359},{begin:43520,end:43615},{begin:65936,end:65999},{begin:66e3,end:66047},{begin:66208,end:66271},{begin:127024,end:127135}];var o=a(function(e){e["¨"]=" ̈";e["¯"]=" Ì„";e["´"]=" Ì";e["µ"]="μ";e["¸"]=" ̧";e["IJ"]="IJ";e["ij"]="ij";e["Ä¿"]="L·";e["Å€"]="l·";e["ʼn"]="ʼn";e["Å¿"]="s";e["Ç„"]="DŽ";e["Ç…"]="Dž";e["dž"]="dž";e["LJ"]="LJ";e["Lj"]="Lj";e["lj"]="lj";e["ÇŠ"]="NJ";e["Ç‹"]="Nj";e["ÇŒ"]="nj";e["DZ"]="DZ";e["Dz"]="Dz";e["dz"]="dz";e["˘"]=" ̆";e["Ë™"]=" ̇";e["Ëš"]=" ÌŠ";e["Ë›"]=" ̨";e["Ëœ"]=" ̃";e["Ë"]=" Ì‹";e["ͺ"]=" Í…";e["΄"]=" Ì";e["Ï"]="β";e["Ï‘"]="θ";e["Ï’"]="Î¥";e["Ï•"]="φ";e["Ï–"]="Ï€";e["Ï°"]="κ";e["ϱ"]="Ï";e["ϲ"]="Ï‚";e["Ï´"]="Θ";e["ϵ"]="ε";e["Ϲ"]="Σ";e["Ö‡"]="Õ¥Ö‚";e["Ùµ"]="اٴ";e["Ù¶"]="وٴ";e["Ù·"]="Û‡Ù´";e["Ù¸"]="يٴ";e["ำ"]="à¹à¸²";e["ຳ"]="à»àº²";e["ໜ"]="ຫນ";e["à»"]="ຫມ";e["ཷ"]="ྲà¾";e["ཹ"]="ླà¾";e["ẚ"]="aʾ";e["á¾½"]=" Ì“";e["᾿"]=" Ì“";e["á¿€"]=" Í‚";e["῾"]=" Ì”";e[" "]=" ";e[" "]=" ";e[" "]=" ";e[" "]=" ";e[" "]=" ";e[" "]=" ";e[" "]=" ";e[" "]=" ";e["‗"]=" ̳";e["․"]=".";e["‥"]="..";e["…"]="...";e["″"]="′′";e["‴"]="′′′";e["‶"]="‵‵";e["‷"]="‵‵‵";e["‼"]="!!";e["‾"]=" Ì…";e["â‡"]="??";e["âˆ"]="?!";e["â‰"]="!?";e["â—"]="′′′′";e["âŸ"]=" ";e["₨"]="Rs";e["â„€"]="a/c";e["â„"]="a/s";e["℃"]="°C";e["â„…"]="c/o";e["℆"]="c/u";e["ℇ"]="Æ";e["℉"]="°F";e["â„–"]="No";e["â„¡"]="TEL";e["ℵ"]="×";e["ℶ"]="ב";e["â„·"]="×’";e["ℸ"]="ד";e["â„»"]="FAX";e["â… "]="I";e["â…¡"]="II";e["â…¢"]="III";e["â…£"]="IV";e["â…¤"]="V";e["â…¥"]="VI";e["â…¦"]="VII";e["â…§"]="VIII";e["â…¨"]="IX";e["â…©"]="X";e["â…ª"]="XI";e["â…«"]="XII";e["â…¬"]="L";e["â…­"]="C";e["â…®"]="D";e["â…¯"]="M";e["â…°"]="i";e["â…±"]="ii";e["â…²"]="iii";e["â…³"]="iv";e["â…´"]="v";e["â…µ"]="vi";e["â…¶"]="vii";e["â…·"]="viii";e["â…¸"]="ix";e["â…¹"]="x";e["â…º"]="xi";e["â…»"]="xii";e["â…¼"]="l";e["â…½"]="c";e["â…¾"]="d";e["â…¿"]="m";e["∬"]="∫∫";e["∭"]="∫∫∫";e["∯"]="∮∮";e["∰"]="∮∮∮";e["â‘´"]="(1)";e["⑵"]="(2)";e["⑶"]="(3)";e["â‘·"]="(4)";e["⑸"]="(5)";e["⑹"]="(6)";e["⑺"]="(7)";e["â‘»"]="(8)";e["⑼"]="(9)";e["⑽"]="(10)";e["⑾"]="(11)";e["â‘¿"]="(12)";e["â’€"]="(13)";e["â’"]="(14)";e["â’‚"]="(15)";e["â’ƒ"]="(16)";e["â’„"]="(17)";e["â’…"]="(18)";e["â’†"]="(19)";e["â’‡"]="(20)";e["â’ˆ"]="1.";e["â’‰"]="2.";e["â’Š"]="3.";e["â’‹"]="4.";e["â’Œ"]="5.";e["â’"]="6.";e["â’Ž"]="7.";e["â’"]="8.";e["â’"]="9.";e["â’‘"]="10.";e["â’’"]="11.";e["â’“"]="12.";e["â’”"]="13.";e["â’•"]="14.";e["â’–"]="15.";e["â’—"]="16.";e["â’˜"]="17.";e["â’™"]="18.";e["â’š"]="19.";e["â’›"]="20.";e["â’œ"]="(a)";e["â’"]="(b)";e["â’ž"]="(c)";e["â’Ÿ"]="(d)";e["â’ "]="(e)";e["â’¡"]="(f)";e["â’¢"]="(g)";e["â’£"]="(h)";e["â’¤"]="(i)";e["â’¥"]="(j)";e["â’¦"]="(k)";e["â’§"]="(l)";e["â’¨"]="(m)";e["â’©"]="(n)";e["â’ª"]="(o)";e["â’«"]="(p)";e["â’¬"]="(q)";e["â’­"]="(r)";e["â’®"]="(s)";e["â’¯"]="(t)";e["â’°"]="(u)";e["â’±"]="(v)";e["â’²"]="(w)";e["â’³"]="(x)";e["â’´"]="(y)";e["â’µ"]="(z)";e["⨌"]="∫∫∫∫";e["â©´"]="::=";e["⩵"]="==";e["⩶"]="===";e["⺟"]="æ¯";e["⻳"]="龟";e["â¼€"]="一";e["â¼"]="丨";e["⼂"]="丶";e["⼃"]="丿";e["⼄"]="ä¹™";e["â¼…"]="亅";e["⼆"]="二";e["⼇"]="亠";e["⼈"]="人";e["⼉"]="å„¿";e["⼊"]="å…¥";e["⼋"]="å…«";e["⼌"]="冂";e["â¼"]="冖";e["⼎"]="冫";e["â¼"]="几";e["â¼"]="凵";e["⼑"]="刀";e["â¼’"]="力";e["⼓"]="勹";e["â¼”"]="匕";e["⼕"]="匚";e["â¼–"]="匸";e["â¼—"]="å";e["⼘"]="åœ";e["â¼™"]="å©";e["⼚"]="厂";e["â¼›"]="厶";e["⼜"]="åˆ";e["â¼"]="å£";e["⼞"]="å›—";e["⼟"]="土";e["â¼ "]="士";e["⼡"]="夂";e["â¼¢"]="夊";e["â¼£"]="夕";e["⼤"]="大";e["â¼¥"]="女";e["⼦"]="å­";e["⼧"]="宀";e["⼨"]="寸";e["⼩"]="å°";e["⼪"]="å°¢";e["⼫"]="å°¸";e["⼬"]="å±®";e["â¼­"]="å±±";e["â¼®"]="å·›";e["⼯"]="å·¥";e["â¼°"]="å·±";e["â¼±"]="å·¾";e["â¼²"]="å¹²";e["â¼³"]="幺";e["â¼´"]="广";e["â¼µ"]="å»´";e["⼶"]="廾";e["â¼·"]="弋";e["⼸"]="弓";e["â¼¹"]="å½";e["⼺"]="彡";e["â¼»"]="å½³";e["â¼¼"]="心";e["â¼½"]="戈";e["â¼¾"]="戶";e["⼿"]="手";e["â½€"]="支";e["â½"]="æ”´";e["⽂"]="æ–‡";e["⽃"]="æ–—";e["⽄"]="æ–¤";e["â½…"]="æ–¹";e["⽆"]="æ— ";e["⽇"]="æ—¥";e["⽈"]="æ›°";e["⽉"]="月";e["⽊"]="木";e["⽋"]="欠";e["⽌"]="æ­¢";e["â½"]="æ­¹";e["⽎"]="殳";e["â½"]="毋";e["â½"]="比";e["⽑"]="毛";e["â½’"]="æ°";e["⽓"]="æ°”";e["â½”"]="æ°´";e["⽕"]="ç«";e["â½–"]="爪";e["â½—"]="父";e["⽘"]="爻";e["â½™"]="爿";e["⽚"]="片";e["â½›"]="牙";e["⽜"]="牛";e["â½"]="犬";e["⽞"]="玄";e["⽟"]="玉";e["â½ "]="ç“œ";e["⽡"]="瓦";e["â½¢"]="甘";e["â½£"]="生";e["⽤"]="用";e["â½¥"]="ç”°";e["⽦"]="ç–‹";e["⽧"]="ç–’";e["⽨"]="癶";e["⽩"]="白";e["⽪"]="çš®";e["⽫"]="çš¿";e["⽬"]="ç›®";e["â½­"]="矛";e["â½®"]="矢";e["⽯"]="石";e["â½°"]="示";e["â½±"]="禸";e["â½²"]="禾";e["â½³"]="ç©´";e["â½´"]="ç«‹";e["â½µ"]="竹";e["⽶"]="ç±³";e["â½·"]="糸";e["⽸"]="缶";e["â½¹"]="网";e["⽺"]="羊";e["â½»"]="ç¾½";e["â½¼"]="è€";e["â½½"]="而";e["â½¾"]="耒";e["⽿"]="耳";e["â¾€"]="è¿";e["â¾"]="肉";e["⾂"]="臣";e["⾃"]="自";e["⾄"]="至";e["â¾…"]="臼";e["⾆"]="舌";e["⾇"]="舛";e["⾈"]="舟";e["⾉"]="艮";e["⾊"]="色";e["⾋"]="艸";e["⾌"]="è™";e["â¾"]="虫";e["⾎"]="è¡€";e["â¾"]="è¡Œ";e["â¾"]="è¡£";e["⾑"]="襾";e["â¾’"]="見";e["⾓"]="角";e["â¾”"]="言";e["⾕"]="è°·";e["â¾–"]="豆";e["â¾—"]="豕";e["⾘"]="豸";e["â¾™"]="è²";e["⾚"]="赤";e["â¾›"]="èµ°";e["⾜"]="足";e["â¾"]="身";e["⾞"]="車";e["⾟"]="è¾›";e["â¾ "]="è¾°";e["⾡"]="è¾µ";e["â¾¢"]="é‚‘";e["â¾£"]="é…‰";e["⾤"]="釆";e["â¾¥"]="里";e["⾦"]="金";e["⾧"]="é•·";e["⾨"]="é–€";e["⾩"]="阜";e["⾪"]="隶";e["⾫"]="éš¹";e["⾬"]="雨";e["â¾­"]="é‘";e["â¾®"]="éž";e["⾯"]="é¢";e["â¾°"]="é©";e["â¾±"]="韋";e["â¾²"]="韭";e["â¾³"]="音";e["â¾´"]="é ";e["â¾µ"]="風";e["⾶"]="飛";e["â¾·"]="食";e["⾸"]="首";e["â¾¹"]="香";e["⾺"]="馬";e["â¾»"]="骨";e["â¾¼"]="高";e["â¾½"]="é«Ÿ";e["â¾¾"]="鬥";e["⾿"]="鬯";e["â¿€"]="鬲";e["â¿"]="鬼";e["â¿‚"]="é­š";e["⿃"]="é³¥";e["â¿„"]="é¹µ";e["â¿…"]="鹿";e["⿆"]="麥";e["⿇"]="麻";e["⿈"]="黃";e["⿉"]="é»";e["â¿Š"]="黑";e["â¿‹"]="黹";e["â¿Œ"]="黽";e["â¿"]="鼎";e["â¿Ž"]="鼓";e["â¿"]="é¼ ";e["â¿"]="é¼»";e["â¿‘"]="齊";e["â¿’"]="é½’";e["â¿“"]="é¾";e["â¿”"]="龜";e["â¿•"]="é¾ ";e["〶"]="〒";e["〸"]="å";e["〹"]="å„";e["〺"]="å…";e["ã‚›"]=" ã‚™";e["ã‚œ"]=" ã‚š";e["ㄱ"]="á„€";e["ㄲ"]="á„";e["ㄳ"]="ᆪ";e["ã„´"]="á„‚";e["ㄵ"]="ᆬ";e["ㄶ"]="ᆭ";e["ã„·"]="ᄃ";e["ㄸ"]="á„„";e["ㄹ"]="á„…";e["ㄺ"]="ᆰ";e["ã„»"]="ᆱ";e["ㄼ"]="ᆲ";e["ㄽ"]="ᆳ";e["ㄾ"]="ᆴ";e["ã„¿"]="ᆵ";e["ã…€"]="á„š";e["ã…"]="ᄆ";e["ã…‚"]="ᄇ";e["ã…ƒ"]="ᄈ";e["ã…„"]="á„¡";e["ã……"]="ᄉ";e["ã…†"]="á„Š";e["ã…‡"]="á„‹";e["ã…ˆ"]="á„Œ";e["ã…‰"]="á„";e["ã…Š"]="á„Ž";e["ã…‹"]="á„";e["ã…Œ"]="á„";e["ã…"]="á„‘";e["ã…Ž"]="á„’";e["ã…"]="á…¡";e["ã…"]="á…¢";e["ã…‘"]="á…£";e["ã…’"]="á…¤";e["ã…“"]="á…¥";e["ã…”"]="á…¦";e["ã…•"]="á…§";e["ã…–"]="á…¨";e["ã…—"]="á…©";e["ã…˜"]="á…ª";e["ã…™"]="á…«";e["ã…š"]="á…¬";e["ã…›"]="á…­";e["ã…œ"]="á…®";e["ã…"]="á…¯";e["ã…ž"]="á…°";e["ã…Ÿ"]="á…±";e["ã… "]="á…²";e["ã…¡"]="á…³";e["ã…¢"]="á…´";e["ã…£"]="á…µ";e["ã…¤"]="á… ";e["ã…¥"]="á„”";e["ã…¦"]="á„•";e["ã…§"]="ᇇ";e["ã…¨"]="ᇈ";e["ã…©"]="ᇌ";e["ã…ª"]="ᇎ";e["ã…«"]="ᇓ";e["ã…¬"]="ᇗ";e["ã…­"]="ᇙ";e["ã…®"]="á„œ";e["ã…¯"]="á‡";e["ã…°"]="ᇟ";e["ã…±"]="á„";e["ã…²"]="á„ž";e["ã…³"]="á„ ";e["ã…´"]="á„¢";e["ã…µ"]="á„£";e["ã…¶"]="ᄧ";e["ã…·"]="á„©";e["ã…¸"]="á„«";e["ã…¹"]="ᄬ";e["ã…º"]="á„­";e["ã…»"]="á„®";e["ã…¼"]="ᄯ";e["ã…½"]="ᄲ";e["ã…¾"]="ᄶ";e["ã…¿"]="á…€";e["ㆀ"]="á…‡";e["ã†"]="á…Œ";e["ㆂ"]="ᇱ";e["ㆃ"]="ᇲ";e["ㆄ"]="á…—";e["ㆅ"]="á…˜";e["ㆆ"]="á…™";e["ㆇ"]="ᆄ";e["ㆈ"]="ᆅ";e["ㆉ"]="ᆈ";e["ㆊ"]="ᆑ";e["ㆋ"]="ᆒ";e["ㆌ"]="ᆔ";e["ã†"]="ᆞ";e["ㆎ"]="ᆡ";e["㈀"]="(á„€)";e["ãˆ"]="(á„‚)";e["㈂"]="(ᄃ)";e["㈃"]="(á„…)";e["㈄"]="(ᄆ)";e["㈅"]="(ᄇ)";e["㈆"]="(ᄉ)";e["㈇"]="(á„‹)";e["㈈"]="(á„Œ)";e["㈉"]="(á„Ž)";e["㈊"]="(á„)";e["㈋"]="(á„)";e["㈌"]="(á„‘)";e["ãˆ"]="(á„’)";e["㈎"]="(가)";e["ãˆ"]="(á„‚á…¡)";e["ãˆ"]="(다)";e["㈑"]="(á„…á…¡)";e["㈒"]="(마)";e["㈓"]="(바)";e["㈔"]="(사)";e["㈕"]="(á„‹á…¡)";e["㈖"]="(자)";e["㈗"]="(á„Žá…¡)";e["㈘"]="(á„á…¡)";e["㈙"]="(á„á…¡)";e["㈚"]="(á„‘á…¡)";e["㈛"]="(á„’á…¡)";e["㈜"]="(주)";e["ãˆ"]="(오전)";e["㈞"]="(á„‹á…©á„’á…®)";e["㈠"]="(一)";e["㈡"]="(二)";e["㈢"]="(三)";e["㈣"]="(å››)";e["㈤"]="(五)";e["㈥"]="(å…­)";e["㈦"]="(七)";e["㈧"]="(å…«)";e["㈨"]="(ä¹)";e["㈩"]="(å)";e["㈪"]="(月)";e["㈫"]="(ç«)";e["㈬"]="(æ°´)";e["㈭"]="(木)";e["㈮"]="(金)";e["㈯"]="(土)";e["㈰"]="(æ—¥)";e["㈱"]="(æ ª)";e["㈲"]="(有)";e["㈳"]="(社)";e["㈴"]="(å)";e["㈵"]="(特)";e["㈶"]="(財)";e["㈷"]="(ç¥)";e["㈸"]="(労)";e["㈹"]="(代)";e["㈺"]="(呼)";e["㈻"]="(å­¦)";e["㈼"]="(監)";e["㈽"]="(ä¼)";e["㈾"]="(資)";e["㈿"]="(å”)";e["㉀"]="(祭)";e["ã‰"]="(休)";e["㉂"]="(自)";e["㉃"]="(至)";e["ã‹€"]="1月";e["ã‹"]="2月";e["ã‹‚"]="3月";e["㋃"]="4月";e["ã‹„"]="5月";e["ã‹…"]="6月";e["㋆"]="7月";e["㋇"]="8月";e["㋈"]="9月";e["㋉"]="10月";e["ã‹Š"]="11月";e["ã‹‹"]="12月";e["ã˜"]="0点";e["ã™"]="1点";e["ãš"]="2点";e["ã›"]="3点";e["ãœ"]="4点";e["ã"]="5点";e["ãž"]="6点";e["ãŸ"]="7点";e["ã "]="8点";e["ã¡"]="9点";e["ã¢"]="10点";e["ã£"]="11点";e["ã¤"]="12点";e["ã¥"]="13点";e["ã¦"]="14点";e["ã§"]="15点";e["ã¨"]="16点";e["ã©"]="17点";e["ãª"]="18点";e["ã«"]="19点";e["ã¬"]="20点";e["ã­"]="21点";e["ã®"]="22点";e["ã¯"]="23点";e["ã°"]="24点";e["ã "]="1æ—¥";e["ã¡"]="2æ—¥";e["ã¢"]="3æ—¥";e["ã£"]="4æ—¥";e["ã¤"]="5æ—¥";e["ã¥"]="6æ—¥";e["ã¦"]="7æ—¥";e["ã§"]="8æ—¥";e["ã¨"]="9æ—¥";e["ã©"]="10æ—¥";e["ãª"]="11æ—¥";e["ã«"]="12æ—¥";e["ã¬"]="13æ—¥";e["ã­"]="14æ—¥";e["ã®"]="15æ—¥";e["ã¯"]="16æ—¥";e["ã°"]="17æ—¥";e["ã±"]="18æ—¥";e["ã²"]="19æ—¥";e["ã³"]="20æ—¥";e["ã´"]="21æ—¥";e["ãµ"]="22æ—¥";e["ã¶"]="23æ—¥";e["ã·"]="24æ—¥";e["ã¸"]="25æ—¥";e["ã¹"]="26æ—¥";e["ãº"]="27æ—¥";e["ã»"]="28æ—¥";e["ã¼"]="29æ—¥";e["ã½"]="30æ—¥";e["ã¾"]="31æ—¥";e["ff"]="ff";e["ï¬"]="fi";e["fl"]="fl";e["ffi"]="ffi";e["ffl"]="ffl";e["ſt"]="Å¿t";e["st"]="st";e["ﬓ"]="Õ´Õ¶";e["ﬔ"]="Õ´Õ¥";e["ﬕ"]="Õ´Õ«";e["ﬖ"]="Õ¾Õ¶";e["ﬗ"]="Õ´Õ­";e["ï­"]="×ל";e["ï­"]="Ù±";e["ï­‘"]="Ù±";e["ï­’"]="Ù»";e["ï­“"]="Ù»";e["ï­”"]="Ù»";e["ï­•"]="Ù»";e["ï­–"]="Ù¾";e["ï­—"]="Ù¾";e["ï­˜"]="Ù¾";e["ï­™"]="Ù¾";e["ï­š"]="Ú€";e["ï­›"]="Ú€";e["ï­œ"]="Ú€";e["ï­"]="Ú€";e["ï­ž"]="Ùº";e["ï­Ÿ"]="Ùº";e["ï­ "]="Ùº";e["ï­¡"]="Ùº";e["ï­¢"]="Ù¿";e["ï­£"]="Ù¿";e["ï­¤"]="Ù¿";e["ï­¥"]="Ù¿";e["ï­¦"]="Ù¹";e["ï­§"]="Ù¹";e["ï­¨"]="Ù¹";e["ï­©"]="Ù¹";e["ï­ª"]="Ú¤";e["ï­«"]="Ú¤";e["ï­¬"]="Ú¤";e["ï­­"]="Ú¤";e["ï­®"]="Ú¦";e["ï­¯"]="Ú¦";e["ï­°"]="Ú¦";e["ï­±"]="Ú¦";e["ï­²"]="Ú„";e["ï­³"]="Ú„";e["ï­´"]="Ú„";e["ï­µ"]="Ú„";e["ï­¶"]="Úƒ";e["ï­·"]="Úƒ";e["ï­¸"]="Úƒ";e["ï­¹"]="Úƒ";e["ï­º"]="Ú†";e["ï­»"]="Ú†";e["ï­¼"]="Ú†";e["ï­½"]="Ú†";e["ï­¾"]="Ú‡";e["ï­¿"]="Ú‡";e["ﮀ"]="Ú‡";e["ï®"]="Ú‡";e["ﮂ"]="Ú";e["ﮃ"]="Ú";e["ﮄ"]="ÚŒ";e["ï®…"]="ÚŒ";e["ﮆ"]="ÚŽ";e["ﮇ"]="ÚŽ";e["ﮈ"]="Úˆ";e["ﮉ"]="Úˆ";e["ﮊ"]="Ú˜";e["ﮋ"]="Ú˜";e["ﮌ"]="Ú‘";e["ï®"]="Ú‘";e["ﮎ"]="Ú©";e["ï®"]="Ú©";e["ï®"]="Ú©";e["ﮑ"]="Ú©";e["ï®’"]="Ú¯";e["ﮓ"]="Ú¯";e["ï®”"]="Ú¯";e["ﮕ"]="Ú¯";e["ï®–"]="Ú³";e["ï®—"]="Ú³";e["ﮘ"]="Ú³";e["ï®™"]="Ú³";e["ﮚ"]="Ú±";e["ï®›"]="Ú±";e["ﮜ"]="Ú±";e["ï®"]="Ú±";e["ﮞ"]="Úº";e["ﮟ"]="Úº";e["ï® "]="Ú»";e["ﮡ"]="Ú»";e["ﮢ"]="Ú»";e["ﮣ"]="Ú»";e["ﮤ"]="Û€";e["ﮥ"]="Û€";e["ﮦ"]="Û";e["ﮧ"]="Û";e["ﮨ"]="Û";e["ﮩ"]="Û";e["ﮪ"]="Ú¾";e["ﮫ"]="Ú¾";e["ﮬ"]="Ú¾";e["ï®­"]="Ú¾";e["ï®®"]="Û’";e["ﮯ"]="Û’";e["ï®°"]="Û“";e["ï®±"]="Û“";e["ﯓ"]="Ú­";e["ﯔ"]="Ú­";e["ﯕ"]="Ú­";e["ﯖ"]="Ú­";e["ﯗ"]="Û‡";e["ﯘ"]="Û‡";e["ﯙ"]="Û†";e["ﯚ"]="Û†";e["ﯛ"]="Ûˆ";e["ﯜ"]="Ûˆ";e["ï¯"]="Ù·";e["ﯞ"]="Û‹";e["ﯟ"]="Û‹";e["ﯠ"]="Û…";e["ﯡ"]="Û…";e["ﯢ"]="Û‰";e["ﯣ"]="Û‰";e["ﯤ"]="Û";e["ﯥ"]="Û";e["ﯦ"]="Û";e["ﯧ"]="Û";e["ﯨ"]="Ù‰";e["ﯩ"]="Ù‰";e["ﯪ"]="ئا";e["ﯫ"]="ئا";e["ﯬ"]="ئە";e["ﯭ"]="ئە";e["ﯮ"]="ئو";e["ﯯ"]="ئو";e["ﯰ"]="ئۇ";e["ﯱ"]="ئۇ";e["ﯲ"]="ئۆ";e["ﯳ"]="ئۆ";e["ﯴ"]="ئۈ";e["ﯵ"]="ئۈ";e["ﯶ"]="ئÛ";e["ﯷ"]="ئÛ";e["ﯸ"]="ئÛ";e["ﯹ"]="ئى";e["ﯺ"]="ئى";e["ﯻ"]="ئى";e["ﯼ"]="ÛŒ";e["ﯽ"]="ÛŒ";e["ﯾ"]="ÛŒ";e["ﯿ"]="ÛŒ";e["ï°€"]="ئج";e["ï°"]="ئح";e["ï°‚"]="ئم";e["ï°ƒ"]="ئى";e["ï°„"]="ئي";e["ï°…"]="بج";e["ï°†"]="بح";e["ï°‡"]="بخ";e["ï°ˆ"]="بم";e["ï°‰"]="بى";e["ï°Š"]="بي";e["ï°‹"]="تج";e["ï°Œ"]="تح";e["ï°"]="تخ";e["ï°Ž"]="تم";e["ï°"]="تى";e["ï°"]="تي";e["ï°‘"]="ثج";e["ï°’"]="ثم";e["ï°“"]="ثى";e["ï°”"]="ثي";e["ï°•"]="جح";e["ï°–"]="جم";e["ï°—"]="حج";e["ï°˜"]="حم";e["ï°™"]="خج";e["ï°š"]="خح";e["ï°›"]="خم";e["ï°œ"]="سج";e["ï°"]="سح";e["ï°ž"]="سخ";e["ï°Ÿ"]="سم";e["ï° "]="صح";e["ï°¡"]="صم";e["ï°¢"]="ضج";e["ï°£"]="ضح";e["ï°¤"]="ضخ";e["ï°¥"]="ضم";e["ï°¦"]="طح";e["ï°§"]="طم";e["ï°¨"]="ظم";e["ï°©"]="عج";e["ï°ª"]="عم";e["ï°«"]="غج";e["ï°¬"]="غم";e["ï°­"]="Ùج";e["ï°®"]="ÙØ­";e["ï°¯"]="ÙØ®";e["ï°°"]="ÙÙ…";e["ï°±"]="ÙÙ‰";e["ï°²"]="ÙÙŠ";e["ï°³"]="قح";e["ï°´"]="قم";e["ï°µ"]="قى";e["ï°¶"]="قي";e["ï°·"]="كا";e["ï°¸"]="كج";e["ï°¹"]="كح";e["ï°º"]="كخ";e["ï°»"]="كل";e["ï°¼"]="كم";e["ï°½"]="كى";e["ï°¾"]="كي";e["ï°¿"]="لج";e["ï±€"]="لح";e["ï±"]="لخ";e["ﱂ"]="لم";e["ﱃ"]="لى";e["ﱄ"]="لي";e["ï±…"]="مج";e["ﱆ"]="مح";e["ﱇ"]="مخ";e["ﱈ"]="مم";e["ﱉ"]="مى";e["ﱊ"]="مي";e["ﱋ"]="نج";e["ﱌ"]="نح";e["ï±"]="نخ";e["ﱎ"]="نم";e["ï±"]="نى";e["ï±"]="ني";e["ﱑ"]="هج";e["ï±’"]="هم";e["ﱓ"]="هى";e["ï±”"]="هي";e["ﱕ"]="يج";e["ï±–"]="يح";e["ï±—"]="يخ";e["ﱘ"]="يم";e["ï±™"]="يى";e["ﱚ"]="يي";e["ï±›"]="ذٰ";e["ﱜ"]="رٰ";e["ï±"]="ىٰ";e["ﱞ"]=" ٌّ";e["ﱟ"]=" ÙÙ‘";e["ï± "]=" ÙŽÙ‘";e["ﱡ"]=" ÙÙ‘";e["ï±¢"]=" ÙÙ‘";e["ï±£"]=" ّٰ";e["ﱤ"]="ئر";e["ï±¥"]="ئز";e["ﱦ"]="ئم";e["ﱧ"]="ئن";e["ﱨ"]="ئى";e["ﱩ"]="ئي";e["ﱪ"]="بر";e["ﱫ"]="بز";e["ﱬ"]="بم";e["ï±­"]="بن";e["ï±®"]="بى";e["ﱯ"]="بي";e["ï±°"]="تر";e["ï±±"]="تز";e["ï±²"]="تم";e["ï±³"]="تن";e["ï±´"]="تى";e["ï±µ"]="تي";e["ﱶ"]="ثر";e["ï±·"]="ثز";e["ﱸ"]="ثم";e["ï±¹"]="ثن";e["ﱺ"]="ثى";e["ï±»"]="ثي";e["ï±¼"]="ÙÙ‰";e["ï±½"]="ÙÙŠ";e["ï±¾"]="قى";e["ﱿ"]="قي";e["ï²€"]="كا";e["ï²"]="كل";e["ﲂ"]="كم";e["ﲃ"]="كى";e["ﲄ"]="كي";e["ï²…"]="لم";e["ﲆ"]="لى";e["ﲇ"]="لي";e["ﲈ"]="ما";e["ﲉ"]="مم";e["ﲊ"]="نر";e["ﲋ"]="نز";e["ﲌ"]="نم";e["ï²"]="نن";e["ﲎ"]="نى";e["ï²"]="ني";e["ï²"]="ىٰ";e["ﲑ"]="ير";e["ï²’"]="يز";e["ﲓ"]="يم";e["ï²”"]="ين";e["ﲕ"]="يى";e["ï²–"]="يي";e["ï²—"]="ئج";e["ﲘ"]="ئح";e["ï²™"]="ئخ";e["ﲚ"]="ئم";e["ï²›"]="ئه";e["ﲜ"]="بج";e["ï²"]="بح";e["ﲞ"]="بخ";e["ﲟ"]="بم";e["ï² "]="به";e["ﲡ"]="تج";e["ï²¢"]="تح";e["ï²£"]="تخ";e["ﲤ"]="تم";e["ï²¥"]="ته";e["ﲦ"]="ثم";e["ﲧ"]="جح";e["ﲨ"]="جم";e["ﲩ"]="حج";e["ﲪ"]="حم";e["ﲫ"]="خج";e["ﲬ"]="خم";e["ï²­"]="سج";e["ï²®"]="سح";e["ﲯ"]="سخ";e["ï²°"]="سم";e["ï²±"]="صح";e["ï²²"]="صخ";e["ï²³"]="صم";e["ï²´"]="ضج";e["ï²µ"]="ضح";e["ﲶ"]="ضخ";e["ï²·"]="ضم";e["ﲸ"]="طح";e["ï²¹"]="ظم";e["ﲺ"]="عج";e["ï²»"]="عم";e["ï²¼"]="غج";e["ï²½"]="غم";e["ï²¾"]="Ùج";e["ﲿ"]="ÙØ­";e["ï³€"]="ÙØ®";e["ï³"]="ÙÙ…";e["ﳂ"]="قح";e["ﳃ"]="قم";e["ﳄ"]="كج";e["ï³…"]="كح";e["ﳆ"]="كخ";e["ﳇ"]="كل";e["ﳈ"]="كم";e["ﳉ"]="لج";e["ﳊ"]="لح";e["ﳋ"]="لخ";e["ﳌ"]="لم";e["ï³"]="له";e["ﳎ"]="مج";e["ï³"]="مح";e["ï³"]="مخ";e["ﳑ"]="مم";e["ï³’"]="نج";e["ﳓ"]="نح";e["ï³”"]="نخ";e["ﳕ"]="نم";e["ï³–"]="نه";e["ï³—"]="هج";e["ﳘ"]="هم";e["ï³™"]="هٰ";e["ﳚ"]="يج";e["ï³›"]="يح";e["ﳜ"]="يخ";e["ï³"]="يم";e["ﳞ"]="يه";e["ﳟ"]="ئم";e["ï³ "]="ئه";e["ﳡ"]="بم";e["ï³¢"]="به";e["ï³£"]="تم";e["ﳤ"]="ته";e["ï³¥"]="ثم";e["ﳦ"]="ثه";e["ﳧ"]="سم";e["ﳨ"]="سه";e["ﳩ"]="شم";e["ﳪ"]="شه";e["ﳫ"]="كل";e["ﳬ"]="كم";e["ï³­"]="لم";e["ï³®"]="نم";e["ﳯ"]="نه";e["ï³°"]="يم";e["ï³±"]="يه";e["ï³²"]="Ù€ÙŽÙ‘";e["ï³³"]="Ù€ÙÙ‘";e["ï³´"]="Ù€ÙÙ‘";e["ï³µ"]="طى";e["ﳶ"]="طي";e["ï³·"]="عى";e["ﳸ"]="عي";e["ï³¹"]="غى";e["ﳺ"]="غي";e["ï³»"]="سى";e["ï³¼"]="سي";e["ï³½"]="شى";e["ï³¾"]="شي";e["ﳿ"]="حى";e["ï´€"]="حي";e["ï´"]="جى";e["ï´‚"]="جي";e["ï´ƒ"]="خى";e["ï´„"]="خي";e["ï´…"]="صى";e["ï´†"]="صي";e["ï´‡"]="ضى";e["ï´ˆ"]="ضي";e["ï´‰"]="شج";e["ï´Š"]="شح";e["ï´‹"]="شخ";e["ï´Œ"]="شم";e["ï´"]="شر";e["ï´Ž"]="سر";e["ï´"]="صر";e["ï´"]="ضر";e["ï´‘"]="طى";e["ï´’"]="طي";e["ï´“"]="عى";e["ï´”"]="عي";e["ï´•"]="غى";e["ï´–"]="غي";e["ï´—"]="سى";e["ï´˜"]="سي";e["ï´™"]="شى";e["ï´š"]="شي";e["ï´›"]="حى";e["ï´œ"]="حي";e["ï´"]="جى";e["ï´ž"]="جي";e["ï´Ÿ"]="خى";e["ï´ "]="خي";e["ï´¡"]="صى";e["ï´¢"]="صي";e["ï´£"]="ضى";e["ï´¤"]="ضي";e["ï´¥"]="شج";e["ï´¦"]="شح";e["ï´§"]="شخ";e["ï´¨"]="شم";e["ï´©"]="شر";e["ï´ª"]="سر";e["ï´«"]="صر";e["ï´¬"]="ضر";e["ï´­"]="شج";e["ï´®"]="شح";e["ï´¯"]="شخ";e["ï´°"]="شم";e["ï´±"]="سه";e["ï´²"]="شه";e["ï´³"]="طم";e["ï´´"]="سج";e["ï´µ"]="سح";e["ï´¶"]="سخ";e["ï´·"]="شج";e["ï´¸"]="شح";e["ï´¹"]="شخ";e["ï´º"]="طم";e["ï´»"]="ظم";e["ï´¼"]="اً";e["ï´½"]="اً";e["ïµ"]="تجم";e["ﵑ"]="تحج";e["ïµ’"]="تحج";e["ﵓ"]="تحم";e["ïµ”"]="تخم";e["ﵕ"]="تمج";e["ïµ–"]="تمح";e["ïµ—"]="تمخ";e["ﵘ"]="جمح";e["ïµ™"]="جمح";e["ﵚ"]="حمي";e["ïµ›"]="حمى";e["ﵜ"]="سحج";e["ïµ"]="سجح";e["ﵞ"]="سجى";e["ﵟ"]="سمح";e["ïµ "]="سمح";e["ﵡ"]="سمج";e["ïµ¢"]="سمم";e["ïµ£"]="سمم";e["ﵤ"]="صحح";e["ïµ¥"]="صحح";e["ﵦ"]="صمم";e["ﵧ"]="شحم";e["ﵨ"]="شحم";e["ﵩ"]="شجي";e["ﵪ"]="شمخ";e["ﵫ"]="شمخ";e["ﵬ"]="شمم";e["ïµ­"]="شمم";e["ïµ®"]="ضحى";e["ﵯ"]="ضخم";e["ïµ°"]="ضخم";e["ïµ±"]="طمح";e["ïµ²"]="طمح";e["ïµ³"]="طمم";e["ïµ´"]="طمي";e["ïµµ"]="عجم";e["ﵶ"]="عمم";e["ïµ·"]="عمم";e["ﵸ"]="عمى";e["ïµ¹"]="غمم";e["ﵺ"]="غمي";e["ïµ»"]="غمى";e["ïµ¼"]="Ùخم";e["ïµ½"]="Ùخم";e["ïµ¾"]="قمح";e["ﵿ"]="قمم";e["ﶀ"]="لحم";e["ï¶"]="لحي";e["ﶂ"]="لحى";e["ﶃ"]="لجج";e["ﶄ"]="لجج";e["ﶅ"]="لخم";e["ﶆ"]="لخم";e["ﶇ"]="لمح";e["ﶈ"]="لمح";e["ﶉ"]="محج";e["ﶊ"]="محم";e["ﶋ"]="محي";e["ﶌ"]="مجح";e["ï¶"]="مجم";e["ﶎ"]="مخج";e["ï¶"]="مخم";e["ﶒ"]="مجخ";e["ﶓ"]="همج";e["ﶔ"]="همم";e["ﶕ"]="نحم";e["ﶖ"]="نحى";e["ﶗ"]="نجم";e["ﶘ"]="نجم";e["ﶙ"]="نجى";e["ﶚ"]="نمي";e["ﶛ"]="نمى";e["ﶜ"]="يمم";e["ï¶"]="يمم";e["ﶞ"]="بخي";e["ﶟ"]="تجي";e["ﶠ"]="تجى";e["ﶡ"]="تخي";e["ﶢ"]="تخى";e["ﶣ"]="تمي";e["ﶤ"]="تمى";e["ﶥ"]="جمي";e["ﶦ"]="جحى";e["ﶧ"]="جمى";e["ﶨ"]="سخى";e["ﶩ"]="صحي";e["ﶪ"]="شحي";e["ﶫ"]="ضحي";e["ﶬ"]="لجي";e["ﶭ"]="لمي";e["ﶮ"]="يحي";e["ﶯ"]="يجي";e["ﶰ"]="يمي";e["ﶱ"]="ممي";e["ﶲ"]="قمي";e["ﶳ"]="نحي";e["ﶴ"]="قمح";e["ﶵ"]="لحم";e["ﶶ"]="عمي";e["ﶷ"]="كمي";e["ﶸ"]="نجح";e["ﶹ"]="مخي";e["ﶺ"]="لجم";e["ﶻ"]="كمم";e["ﶼ"]="لجم";e["ﶽ"]="نجح";e["ﶾ"]="جحي";e["ﶿ"]="حجي";e["ï·€"]="مجي";e["ï·"]="Ùمي";e["ï·‚"]="بحي";e["ï·ƒ"]="كمم";e["ï·„"]="عجم";e["ï·…"]="صمم";e["ï·†"]="سخي";e["ï·‡"]="نجي";e["﹉"]="‾";e["﹊"]="‾";e["﹋"]="‾";e["﹌"]="‾";e["ï¹"]="_";e["﹎"]="_";e["ï¹"]="_";e["ﺀ"]="Ø¡";e["ïº"]="Ø¢";e["ﺂ"]="Ø¢";e["ﺃ"]="Ø£";e["ﺄ"]="Ø£";e["ﺅ"]="ؤ";e["ﺆ"]="ؤ";e["ﺇ"]="Ø¥";e["ﺈ"]="Ø¥";e["ﺉ"]="ئ";e["ﺊ"]="ئ";e["ﺋ"]="ئ";e["ﺌ"]="ئ";e["ïº"]="ا";e["ﺎ"]="ا";e["ïº"]="ب";e["ïº"]="ب";e["ﺑ"]="ب";e["ﺒ"]="ب";e["ﺓ"]="Ø©";e["ﺔ"]="Ø©";e["ﺕ"]="ت";e["ﺖ"]="ت";e["ﺗ"]="ت";e["ﺘ"]="ت";e["ﺙ"]="Ø«";e["ﺚ"]="Ø«";e["ﺛ"]="Ø«";e["ﺜ"]="Ø«";e["ïº"]="ج";e["ﺞ"]="ج";e["ﺟ"]="ج";e["ﺠ"]="ج";e["ﺡ"]="Ø­";e["ﺢ"]="Ø­";e["ﺣ"]="Ø­";e["ﺤ"]="Ø­";e["ﺥ"]="Ø®";e["ﺦ"]="Ø®";e["ﺧ"]="Ø®";e["ﺨ"]="Ø®";e["ﺩ"]="د";e["ﺪ"]="د";e["ﺫ"]="Ø°";e["ﺬ"]="Ø°";e["ﺭ"]="ر";e["ﺮ"]="ر";e["ﺯ"]="ز";e["ﺰ"]="ز";e["ﺱ"]="س";e["ﺲ"]="س";e["ﺳ"]="س";e["ﺴ"]="س";e["ﺵ"]="Ø´";e["ﺶ"]="Ø´";e["ﺷ"]="Ø´";e["ﺸ"]="Ø´";e["ﺹ"]="ص";e["ﺺ"]="ص";e["ﺻ"]="ص";e["ﺼ"]="ص";e["ﺽ"]="ض";e["ﺾ"]="ض";e["ﺿ"]="ض";e["ﻀ"]="ض";e["ï»"]="Ø·";e["ﻂ"]="Ø·";e["ﻃ"]="Ø·";e["ﻄ"]="Ø·";e["ï»…"]="ظ";e["ﻆ"]="ظ";e["ﻇ"]="ظ";e["ﻈ"]="ظ";e["ﻉ"]="ع";e["ﻊ"]="ع";e["ﻋ"]="ع";e["ﻌ"]="ع";e["ï»"]="غ";e["ﻎ"]="غ";e["ï»"]="غ";e["ï»"]="غ";e["ﻑ"]="Ù";e["ï»’"]="Ù";e["ﻓ"]="Ù";e["ï»”"]="Ù";e["ﻕ"]="Ù‚";e["ï»–"]="Ù‚";e["ï»—"]="Ù‚";e["ﻘ"]="Ù‚";e["ï»™"]="Ùƒ";e["ﻚ"]="Ùƒ";e["ï»›"]="Ùƒ";e["ﻜ"]="Ùƒ";e["ï»"]="Ù„";e["ﻞ"]="Ù„";e["ﻟ"]="Ù„";e["ï» "]="Ù„";e["ﻡ"]="Ù…";e["ﻢ"]="Ù…";e["ﻣ"]="Ù…";e["ﻤ"]="Ù…";e["ﻥ"]="Ù†";e["ﻦ"]="Ù†";e["ﻧ"]="Ù†";e["ﻨ"]="Ù†";e["ﻩ"]="Ù‡";e["ﻪ"]="Ù‡";e["ﻫ"]="Ù‡";e["ﻬ"]="Ù‡";e["ï»­"]="Ùˆ";e["ï»®"]="Ùˆ";e["ﻯ"]="Ù‰";e["ï»°"]="Ù‰";e["ï»±"]="ÙŠ";e["ﻲ"]="ÙŠ";e["ﻳ"]="ÙŠ";e["ï»´"]="ÙŠ";e["ﻵ"]="لآ";e["ﻶ"]="لآ";e["ï»·"]="لأ";e["ﻸ"]="لأ";e["ﻹ"]="لإ";e["ﻺ"]="لإ";e["ï»»"]="لا";e["ﻼ"]="لا"});t.mapSpecialUnicodeValues=function(e){return e>=65520&&e<=65535?0:e>=62976&&e<=63743?i()[e]||e:173===e?45:e};t.reverseIfRtl=function(e){var t,r,a=e.length;if(a<=1||!(t=e.charCodeAt(0),r=n[13],t>=r.begin&&t<r.end||t>=(r=n[11]).begin&&t<r.end))return e;for(var i="",o=a-1;o>=0;o--)i+=e[o];return i};t.getUnicodeRangeFor=function(e){for(var t=0,r=n.length;t<r;t++){var a=n[t];if(e>=a.begin&&e<a.end)return t}return-1};t.getNormalizedUnicodes=o;t.getUnicodeForGlyph=function(e,t){var r=t[e];if(void 0!==r)return r;if(!e)return-1;if("u"===e[0]){var a,i=e.length;if(7===i&&"n"===e[1]&&"i"===e[2])a=e.substring(3);else{if(!(i>=5&&i<=7))return-1;a=e.substring(1)}if(a===a.toUpperCase()&&(r=parseInt(a,16))>=0)return r}return-1}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.FontRendererFactory=void 0;var a=function(){function e(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1;a.configurable=!0;"value"in a&&(a.writable=!0);Object.defineProperty(e,a.key,a)}}return function(t,r,a){r&&e(t.prototype,r);a&&e(t,a);return t}}(),i=r(2),n=r(157),o=r(160),s=r(159),c=r(140);function l(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function u(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}});t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function h(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var f=function(){function e(e,t){return e[t]<<24|e[t+1]<<16|e[t+2]<<8|e[t+3]}function t(e,t){return e[t]<<8|e[t+1]}function r(r,a,n){var o,s,c,l=1===t(r,a+2)?e(r,a+8):e(r,a+16),u=t(r,a+l);if(4===u){t(r,a+l+2);var h=t(r,a+l+6)>>1;s=a+l+14;o=[];for(c=0;c<h;c++,s+=2)o[c]={end:t(r,s)};s+=2;for(c=0;c<h;c++,s+=2)o[c].start=t(r,s);for(c=0;c<h;c++,s+=2)o[c].idDelta=t(r,s);for(c=0;c<h;c++,s+=2){var f=t(r,s);if(0!==f){o[c].ids=[];for(var d=0,g=o[c].end-o[c].start+1;d<g;d++){o[c].ids[d]=t(r,s+f);f+=2}}}return o}if(12===u){e(r,a+l+4);var m=e(r,a+l+12);s=a+l+16;o=[];for(c=0;c<m;c++){o.push({start:e(r,s),end:e(r,s+4),idDelta:e(r,s+8)-e(r,s)});s+=12}return o}throw new i.FormatError("unsupported cmap: "+u)}function f(e,t,r,a){var i=new n.CFFParser(new c.Stream(e,t,r-t),{},a).parse();return{glyphs:i.charStrings.objects,subrs:i.topDict.privateDict&&i.topDict.privateDict.subrsIndex&&i.topDict.privateDict.subrsIndex.objects,gsubrs:i.globalSubrIndex&&i.globalSubrIndex.objects,isCFFCIDFont:i.isCIDFont,fdSelect:i.fdSelect,fdArray:i.fdArray}}function d(e,t){for(var r=t.codePointAt(0),a=0,i=0,n=e.length-1;i<n;){var o=i+n+1>>1;r<e[o].start?n=o-1:i=o}e[i].start<=r&&r<=e[i].end&&(a=e[i].idDelta+(e[i].ids?e[i].ids[r-e[i].start]:r)&65535);return{charCode:r,glyphId:a}}var g=[],m=function(){function e(t){h(this,e);this.constructor===e&&(0,i.unreachable)("Cannot initialize CompiledFont.");this.fontMatrix=t;this.compiledGlyphs=Object.create(null);this.compiledCharCodeToGlyphId=Object.create(null)}a(e,[{key:"getPathJs",value:function(e){var t=d(this.cmap,e),r=this.compiledGlyphs[t.glyphId];if(!r){r=this.compileGlyph(this.glyphs[t.glyphId],t.glyphId);this.compiledGlyphs[t.glyphId]=r}void 0===this.compiledCharCodeToGlyphId[t.charCode]&&(this.compiledCharCodeToGlyphId[t.charCode]=t.glyphId);return r}},{key:"compileGlyph",value:function(e,t){if(!e||0===e.length||14===e[0])return g;var r=this.fontMatrix;if(this.isCFFCIDFont){var a=this.fdSelect.getFDIndex(t);if(a>=0&&a<this.fdArray.length){r=this.fdArray[a].getByName("FontMatrix")||i.FONT_IDENTITY_MATRIX}else(0,i.warn)("Invalid fd index for glyph index.")}var n=[];n.push({cmd:"save"});n.push({cmd:"transform",args:r.slice()});n.push({cmd:"scale",args:["size","-size"]});this.compileGlyphImpl(e,n,t);n.push({cmd:"restore"});return n}},{key:"compileGlyphImpl",value:function(){(0,i.unreachable)("Children classes should implement this.")}},{key:"hasBuiltPath",value:function(e){var t=d(this.cmap,e);return void 0!==this.compiledGlyphs[t.glyphId]&&void 0!==this.compiledCharCodeToGlyphId[t.charCode]}}]);return e}(),p=function(e){u(t,m);function t(e,r,a){h(this,t);var i=l(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,a||[488e-6,0,0,488e-6,0,0]));i.glyphs=e;i.cmap=r;return i}a(t,[{key:"compileGlyphImpl",value:function(e,t){!function e(t,r,a){function i(e,t){r.push({cmd:"moveTo",args:[e,t]})}function n(e,t){r.push({cmd:"lineTo",args:[e,t]})}function o(e,t,a,i){r.push({cmd:"quadraticCurveTo",args:[e,t,a,i]})}var s,c=0,l=(t[c]<<24|t[c+1]<<16)>>16,u=0,h=0;c+=10;if(l<0)do{s=t[c]<<8|t[c+1];var f,d,g=t[c+2]<<8|t[c+3];c+=4;if(1&s){f=(t[c]<<24|t[c+1]<<16)>>16;d=(t[c+2]<<24|t[c+3]<<16)>>16;c+=4}else{f=t[c++];d=t[c++]}if(2&s){u=f;h=d}else{u=0;h=0}var m=1,p=1,v=0,b=0;if(8&s){m=p=(t[c]<<24|t[c+1]<<16)/1073741824;c+=2}else if(64&s){m=(t[c]<<24|t[c+1]<<16)/1073741824;p=(t[c+2]<<24|t[c+3]<<16)/1073741824;c+=4}else if(128&s){m=(t[c]<<24|t[c+1]<<16)/1073741824;v=(t[c+2]<<24|t[c+3]<<16)/1073741824;b=(t[c+4]<<24|t[c+5]<<16)/1073741824;p=(t[c+6]<<24|t[c+7]<<16)/1073741824;c+=8}var y=a.glyphs[g];if(y){r.push({cmd:"save"});r.push({cmd:"transform",args:[m,v,b,p,u,h]});e(y,r,a);r.push({cmd:"restore"})}}while(32&s);else{var w,k,S=[];for(w=0;w<l;w++){S.push(t[c]<<8|t[c+1]);c+=2}c+=2+(t[c]<<8|t[c+1]);for(var C=S[S.length-1]+1,x=[];x.length<C;){var _=1;8&(s=t[c++])&&(_+=t[c++]);for(;_-- >0;)x.push({flags:s})}for(w=0;w<C;w++){switch(18&x[w].flags){case 0:u+=(t[c]<<24|t[c+1]<<16)>>16;c+=2;break;case 2:u-=t[c++];break;case 18:u+=t[c++]}x[w].x=u}for(w=0;w<C;w++){switch(36&x[w].flags){case 0:h+=(t[c]<<24|t[c+1]<<16)>>16;c+=2;break;case 4:h-=t[c++];break;case 36:h+=t[c++]}x[w].y=h}var A=0;for(c=0;c<l;c++){var P=S[c],I=x.slice(A,P+1);if(1&I[0].flags)I.push(I[0]);else if(1&I[I.length-1].flags)I.unshift(I[I.length-1]);else{var O={flags:1,x:(I[0].x+I[I.length-1].x)/2,y:(I[0].y+I[I.length-1].y)/2};I.unshift(O);I.push(O)}i(I[0].x,I[0].y);for(w=1,k=I.length;w<k;w++)if(1&I[w].flags)n(I[w].x,I[w].y);else if(1&I[w+1].flags){o(I[w].x,I[w].y,I[w+1].x,I[w+1].y);w++}else o(I[w].x,I[w].y,(I[w].x+I[w+1].x)/2,(I[w].y+I[w+1].y)/2);A=P+1}}}(e,t,this)}}]);return t}(),v=function(e){u(t,m);function t(e,r,a,i){h(this,t);var n=l(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,a||[.001,0,0,.001,0,0]));n.glyphs=e.glyphs;n.gsubrs=e.gsubrs||[];n.subrs=e.subrs||[];n.cmap=r;n.glyphNameMap=i||(0,o.getGlyphsUnicode)();n.gsubrsBias=n.gsubrs.length<1240?107:n.gsubrs.length<33900?1131:32768;n.subrsBias=n.subrs.length<1240?107:n.subrs.length<33900?1131:32768;n.isCFFCIDFont=e.isCFFCIDFont;n.fdSelect=e.fdSelect;n.fdArray=e.fdArray;return n}a(t,[{key:"compileGlyphImpl",value:function(e,t,r){!function e(t,r,a,n){var o=[],c=0,l=0,u=0;function h(e,t){r.push({cmd:"moveTo",args:[e,t]})}function f(e,t){r.push({cmd:"lineTo",args:[e,t]})}function g(e,t,a,i,n,o){r.push({cmd:"bezierCurveTo",args:[e,t,a,i,n,o]})}!function t(m){for(var p=0;p<m.length;){var v,b,y,w,k,S,C,x,_=!1,A=m[p++];switch(A){case 1:case 3:u+=o.length>>1;_=!0;break;case 4:l+=o.pop();h(c,l);_=!0;break;case 5:for(;o.length>0;){c+=o.shift();l+=o.shift();f(c,l)}break;case 6:for(;o.length>0;){f(c+=o.shift(),l);if(0===o.length)break;l+=o.shift();f(c,l)}break;case 7:for(;o.length>0;){l+=o.shift();f(c,l);if(0===o.length)break;f(c+=o.shift(),l)}break;case 8:for(;o.length>0;){v=c+o.shift();y=l+o.shift();b=v+o.shift();w=y+o.shift();c=b+o.shift();l=w+o.shift();g(v,y,b,w,c,l)}break;case 10:C=o.pop();x=null;if(a.isCFFCIDFont){var P=a.fdSelect.getFDIndex(n);if(P>=0&&P<a.fdArray.length){var I=a.fdArray[P],O=void 0;I.privateDict&&I.privateDict.subrsIndex&&(O=I.privateDict.subrsIndex.objects);if(O){var T=O.length;x=O[C+=T<1240?107:T<33900?1131:32768]}}else(0,i.warn)("Invalid fd index for glyph index.")}else x=a.subrs[C+a.subrsBias];x&&t(x);break;case 11:return;case 12:switch(A=m[p++]){case 34:b=(v=c+o.shift())+o.shift();k=l+o.shift();c=b+o.shift();g(v,l,b,k,c,k);b=(v=c+o.shift())+o.shift();c=b+o.shift();g(v,k,b,l,c,l);break;case 35:v=c+o.shift();y=l+o.shift();b=v+o.shift();w=y+o.shift();c=b+o.shift();l=w+o.shift();g(v,y,b,w,c,l);v=c+o.shift();y=l+o.shift();b=v+o.shift();w=y+o.shift();c=b+o.shift();l=w+o.shift();g(v,y,b,w,c,l);o.pop();break;case 36:g(v=c+o.shift(),k=l+o.shift(),b=v+o.shift(),S=k+o.shift(),c=b+o.shift(),S);g(v=c+o.shift(),S,b=v+o.shift(),S+o.shift(),c=b+o.shift(),l);break;case 37:var E=c,F=l;v=c+o.shift();y=l+o.shift();b=v+o.shift();w=y+o.shift();c=b+o.shift();l=w+o.shift();g(v,y,b,w,c,l);v=c+o.shift();y=l+o.shift();b=v+o.shift();w=y+o.shift();c=b;l=w;Math.abs(c-E)>Math.abs(l-F)?c+=o.shift():l+=o.shift();g(v,y,b,w,c,l);break;default:throw new i.FormatError("unknown operator: 12 "+A)}break;case 14:if(o.length>=4){var R=o.pop(),B=o.pop();l=o.pop();c=o.pop();r.push({cmd:"save"});r.push({cmd:"translate",args:[c,l]});var D=d(a.cmap,String.fromCharCode(a.glyphNameMap[s.StandardEncoding[R]]));e(a.glyphs[D.glyphId],r,a,D.glyphId);r.push({cmd:"restore"});D=d(a.cmap,String.fromCharCode(a.glyphNameMap[s.StandardEncoding[B]]));e(a.glyphs[D.glyphId],r,a,D.glyphId)}return;case 18:u+=o.length>>1;_=!0;break;case 19:case 20:p+=(u+=o.length>>1)+7>>3;_=!0;break;case 21:l+=o.pop();h(c+=o.pop(),l);_=!0;break;case 22:h(c+=o.pop(),l);_=!0;break;case 23:u+=o.length>>1;_=!0;break;case 24:for(;o.length>2;){v=c+o.shift();y=l+o.shift();b=v+o.shift();w=y+o.shift();c=b+o.shift();l=w+o.shift();g(v,y,b,w,c,l)}c+=o.shift();l+=o.shift();f(c,l);break;case 25:for(;o.length>6;){c+=o.shift();l+=o.shift();f(c,l)}v=c+o.shift();y=l+o.shift();b=v+o.shift();w=y+o.shift();c=b+o.shift();l=w+o.shift();g(v,y,b,w,c,l);break;case 26:o.length%2&&(c+=o.shift());for(;o.length>0;){v=c;y=l+o.shift();b=v+o.shift();w=y+o.shift();c=b;l=w+o.shift();g(v,y,b,w,c,l)}break;case 27:o.length%2&&(l+=o.shift());for(;o.length>0;)g(v=c+o.shift(),y=l,b=v+o.shift(),w=y+o.shift(),c=b+o.shift(),l=w);break;case 28:o.push((m[p]<<24|m[p+1]<<16)>>16);p+=2;break;case 29:C=o.pop()+a.gsubrsBias;(x=a.gsubrs[C])&&t(x);break;case 30:for(;o.length>0;){v=c;y=l+o.shift();b=v+o.shift();w=y+o.shift();c=b+o.shift();l=w+(1===o.length?o.shift():0);g(v,y,b,w,c,l);if(0===o.length)break;v=c+o.shift();y=l;b=v+o.shift();w=y+o.shift();l=w+o.shift();g(v,y,b,w,c=b+(1===o.length?o.shift():0),l)}break;case 31:for(;o.length>0;){v=c+o.shift();y=l;b=v+o.shift();w=y+o.shift();l=w+o.shift();g(v,y,b,w,c=b+(1===o.length?o.shift():0),l);if(0===o.length)break;v=c;y=l+o.shift();b=v+o.shift();w=y+o.shift();c=b+o.shift();l=w+(1===o.length?o.shift():0);g(v,y,b,w,c,l)}break;default:if(A<32)throw new i.FormatError("unknown operator: "+A);if(A<247)o.push(A-139);else if(A<251)o.push(256*(A-247)+m[p++]+108);else if(A<255)o.push(256*-(A-251)-m[p++]-108);else{o.push((m[p]<<24|m[p+1]<<16|m[p+2]<<8|m[p+3])/65536);p+=4}}_&&(o.length=0)}}(t)}(e,t,this,r)}}]);return t}();return{create:function(a,n){for(var o,s,c,l,u,h,d=new Uint8Array(a.data),g=t(d,4),m=0,b=12;m<g;m++,b+=16){var y=(0,i.bytesToString)(d.subarray(b,b+4)),w=e(d,b+8),k=e(d,b+12);switch(y){case"cmap":o=r(d,w);break;case"glyf":s=d.subarray(w,w+k);break;case"loca":c=d.subarray(w,w+k);break;case"head":h=t(d,w+18);u=t(d,w+50);break;case"CFF ":l=f(d,w,w+k,n)}}if(s){var S=h?[1/h,0,0,1/h,0,0]:a.fontMatrix;return new p(function(e,t,r){var a,i;if(r){a=4;i=function(e,t){return e[t]<<24|e[t+1]<<16|e[t+2]<<8|e[t+3]}}else{a=2;i=function(e,t){return e[t]<<9|e[t+1]<<1}}for(var n=[],o=i(t,0),s=a;s<t.length;s+=a){var c=i(t,s);n.push(e.subarray(o,c));o=c}return n}(s,c,u),o,S)}return new v(l,o,a.fontMatrix,a.glyphNameMap)}}}();t.FontRendererFactory=f},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.Type1Parser=void 0;var a=r(2),i=r(159),n=r(140),o=function(){var e=[4],t=[5],r=[6],i=[7],n=[8],o=[12,35],s=[14],c=[21],l=[22],u=[30],h=[31];function f(){this.width=0;this.lsb=0;this.flexing=!1;this.output=[];this.stack=[]}f.prototype={convert:function(f,d,g){for(var m,p,v,b=f.length,y=!1,w=0;w<b;w++){var k=f[w];if(k<32){12===k&&(k=(k<<8)+f[++w]);switch(k){case 1:case 3:this.stack=[];break;case 4:if(this.flexing){if(this.stack.length<1){y=!0;break}var S=this.stack.pop();this.stack.push(0,S);break}y=this.executeCommand(1,e);break;case 5:y=this.executeCommand(2,t);break;case 6:y=this.executeCommand(1,r);break;case 7:y=this.executeCommand(1,i);break;case 8:y=this.executeCommand(6,n);break;case 9:this.stack=[];break;case 10:if(this.stack.length<1){y=!0;break}if(!d[v=this.stack.pop()]){y=!0;break}y=this.convert(d[v],d,g);break;case 11:return y;case 13:if(this.stack.length<2){y=!0;break}m=this.stack.pop();p=this.stack.pop();this.lsb=p;this.width=m;this.stack.push(m,p);y=this.executeCommand(2,l);break;case 14:this.output.push(s[0]);break;case 21:if(this.flexing)break;y=this.executeCommand(2,c);break;case 22:if(this.flexing){this.stack.push(0);break}y=this.executeCommand(1,l);break;case 30:y=this.executeCommand(4,u);break;case 31:y=this.executeCommand(4,h);break;case 3072:case 3073:case 3074:this.stack=[];break;case 3078:if(g){this.seac=this.stack.splice(-4,4);y=this.executeCommand(0,s)}else y=this.executeCommand(4,s);break;case 3079:if(this.stack.length<4){y=!0;break}this.stack.pop();m=this.stack.pop();var C=this.stack.pop();p=this.stack.pop();this.lsb=p;this.width=m;this.stack.push(m,p,C);y=this.executeCommand(3,c);break;case 3084:if(this.stack.length<2){y=!0;break}var x=this.stack.pop(),_=this.stack.pop();this.stack.push(_/x);break;case 3088:if(this.stack.length<2){y=!0;break}v=this.stack.pop();var A=this.stack.pop();if(0===v&&3===A){var P=this.stack.splice(this.stack.length-17,17);this.stack.push(P[2]+P[0],P[3]+P[1],P[4],P[5],P[6],P[7],P[8],P[9],P[10],P[11],P[12],P[13],P[14]);y=this.executeCommand(13,o,!0);this.flexing=!1;this.stack.push(P[15],P[16])}else 1===v&&0===A&&(this.flexing=!0);break;case 3089:break;case 3105:this.stack=[];break;default:(0,a.warn)('Unknown type 1 charstring command of "'+k+'"')}if(y)break}else{k<=246?k-=139:k=k<=250?256*(k-247)+f[++w]+108:k<=254?-256*(k-251)-f[++w]-108:(255&f[++w])<<24|(255&f[++w])<<16|(255&f[++w])<<8|(255&f[++w])<<0;this.stack.push(k)}}return y},executeCommand:function(e,t,r){var a=this.stack.length;if(e>a)return!0;for(var i=a-e,n=i;n<a;n++){var o=this.stack[n];if(Number.isInteger(o))this.output.push(28,o>>8&255,255&o);else{o=65536*o|0;this.output.push(255,o>>24&255,o>>16&255,o>>8&255,255&o)}}this.output.push.apply(this.output,t);r?this.stack.splice(i,e):this.stack.length=0;return!1}};return f}(),s=function(){var e=55665;function t(e){return e>=48&&e<=57||e>=65&&e<=70||e>=97&&e<=102}function r(e,t,r){if(r>=e.length)return new Uint8Array(0);var a,i,n=0|t;for(a=0;a<r;a++)n=52845*(e[a]+n)+22719&65535;var o=e.length-r,s=new Uint8Array(o);for(a=r,i=0;i<o;a++,i++){var c=e[a];s[i]=c^n>>8;n=52845*(c+n)+22719&65535}return s}function s(e){return 47===e||91===e||93===e||123===e||125===e||40===e||41===e}function c(a,i,o){if(i){var s=a.getBytes(),c=!(t(s[0])&&t(s[1])&&t(s[2])&&t(s[3]));a=new n.Stream(c?r(s,e,4):function(e,r,a){var i,n,o=0|r,s=e.length,c=new Uint8Array(s>>>1);for(i=0,n=0;i<s;i++){var l=e[i];if(t(l)){i++;for(var u;i<s&&!t(u=e[i]);)i++;if(i<s){var h=parseInt(String.fromCharCode(l,u),16);c[n++]=h^o>>8;o=52845*(h+o)+22719&65535}}}return Array.prototype.slice.call(c,a,n)}(s,e,4))}this.seacAnalysisEnabled=!!o;this.stream=a;this.nextChar()}c.prototype={readNumberArray:function(){this.getToken();for(var e=[];;){var t=this.getToken();if(null===t||"]"===t||"}"===t)break;e.push(parseFloat(t||0))}return e},readNumber:function(){var e=this.getToken();return parseFloat(e||0)},readInt:function(){var e=this.getToken();return 0|parseInt(e||0,10)},readBoolean:function(){return"true"===this.getToken()?1:0},nextChar:function(){return this.currentChar=this.stream.getByte()},getToken:function(){for(var e=!1,t=this.currentChar;;){if(-1===t)return null;if(e)10!==t&&13!==t||(e=!1);else if(37===t)e=!0;else if(!(0,a.isSpace)(t))break;t=this.nextChar()}if(s(t)){this.nextChar();return String.fromCharCode(t)}var r="";do{r+=String.fromCharCode(t);t=this.nextChar()}while(t>=0&&!(0,a.isSpace)(t)&&!s(t));return r},readCharStrings:function(e,t){return-1===t?e:r(e,4330,t)},extractFontProgram:function(){var e=this.stream,t=[],r=[],a=Object.create(null);a.lenIV=4;for(var i,n,s,c,l,u={subrs:[],charstrings:[],properties:{privateData:a}};null!==(i=this.getToken());)if("/"===i)switch(i=this.getToken()){case"CharStrings":this.getToken();this.getToken();this.getToken();this.getToken();for(;null!==(i=this.getToken())&&"end"!==i;)if("/"===i){var h=this.getToken();n=this.readInt();this.getToken();s=n>0?e.getBytes(n):new Uint8Array(0);c=u.properties.privateData.lenIV;l=this.readCharStrings(s,c);this.nextChar();"noaccess"===(i=this.getToken())&&this.getToken();r.push({glyph:h,encoded:l})}break;case"Subrs":this.readInt();this.getToken();for(;"dup"===this.getToken();){var f=this.readInt();n=this.readInt();this.getToken();s=n>0?e.getBytes(n):new Uint8Array(0);c=u.properties.privateData.lenIV;l=this.readCharStrings(s,c);this.nextChar();"noaccess"===(i=this.getToken())&&this.getToken();t[f]=l}break;case"BlueValues":case"OtherBlues":case"FamilyBlues":case"FamilyOtherBlues":var d=this.readNumberArray();d.length>0&&d.length,0;break;case"StemSnapH":case"StemSnapV":u.properties.privateData[i]=this.readNumberArray();break;case"StdHW":case"StdVW":u.properties.privateData[i]=this.readNumberArray()[0];break;case"BlueShift":case"lenIV":case"BlueFuzz":case"BlueScale":case"LanguageGroup":case"ExpansionFactor":u.properties.privateData[i]=this.readNumber();break;case"ForceBold":u.properties.privateData[i]=this.readBoolean()}for(var g=0;g<r.length;g++){h=r[g].glyph;l=r[g].encoded;var m=new o,p=m.convert(l,t,this.seacAnalysisEnabled),v=m.output;p&&(v=[14]);u.charstrings.push({glyphName:h,charstring:v,width:m.width,lsb:m.lsb,seac:m.seac})}return u},extractFontHeader:function(e){for(var t;null!==(t=this.getToken());)if("/"===t)switch(t=this.getToken()){case"FontMatrix":var r=this.readNumberArray();e.fontMatrix=r;break;case"Encoding":var a,n=this.getToken();if(/^\d+$/.test(n)){a=[];var o=0|parseInt(n,10);this.getToken();for(var s=0;s<o;s++){t=this.getToken();for(;"dup"!==t&&"def"!==t;)if(null===(t=this.getToken()))return;if("def"===t)break;var c=this.readInt();this.getToken();var l=this.getToken();a[c]=l;this.getToken()}}else a=(0,i.getEncoding)(n);e.builtInEncoding=a;break;case"FontBBox":var u=this.readNumberArray();e.ascent=Math.max(u[3],u[1]);e.descent=Math.min(u[1],u[3]);e.ascentScaled=!0}}};return c}();t.Type1Parser=s},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.getTilingPatternIR=t.Pattern=void 0;var a=r(2),i=r(151),n=r(138),o={FUNCTION_BASED:1,AXIAL:2,RADIAL:3,FREE_FORM_MESH:4,LATTICE_FORM_MESH:5,COONS_PATCH_MESH:6,TENSOR_PATCH_MESH:7},s=function(){function e(){(0,a.unreachable)("should not call Pattern constructor")}e.prototype={getPattern:function(e){(0,a.unreachable)("Should not call Pattern.getStyle: "+e)}};e.parseShading=function(e,t,r,i,s,l){var u=(0,n.isStream)(e)?e.dict:e,h=u.get("ShadingType");try{switch(h){case o.AXIAL:case o.RADIAL:return new c.RadialAxial(u,t,r,i,l);case o.FREE_FORM_MESH:case o.LATTICE_FORM_MESH:case o.COONS_PATCH_MESH:case o.TENSOR_PATCH_MESH:return new c.Mesh(e,t,r,i,l);default:throw new a.FormatError("Unsupported ShadingType: "+h)}}catch(e){if(e instanceof a.MissingDataException)throw e;s.send("UnsupportedFeature",{featureId:a.UNSUPPORTED_FEATURES.shadingPattern});(0,a.warn)(e);return new c.Dummy}};return e}(),c={SMALL_NUMBER:1e-6};c.RadialAxial=function(){function e(e,t,r,n,s){this.matrix=t;this.coordsArr=e.getArray("Coords");this.shadingType=e.get("ShadingType");this.type="Pattern";var l=e.get("ColorSpace","CS");l=i.ColorSpace.parse(l,r,n,s);this.cs=l;var u=0,h=1;if(e.has("Domain")){var f=e.getArray("Domain");u=f[0];h=f[1]}var d=!1,g=!1;if(e.has("Extend")){var m=e.getArray("Extend");d=m[0];g=m[1]}if(!(this.shadingType!==o.RADIAL||d&&g)){var p=this.coordsArr[0],v=this.coordsArr[1],b=this.coordsArr[2],y=this.coordsArr[3],w=this.coordsArr[4],k=this.coordsArr[5],S=Math.sqrt((p-y)*(p-y)+(v-w)*(v-w));b<=k+S&&k<=b+S&&(0,a.warn)("Unsupported radial gradient.")}this.extendStart=d;this.extendEnd=g;var C=e.get("Function"),x=s.createFromArray(C),_=h-u,A=_/10,P=this.colorStops=[];if(u>=h||A<=0)(0,a.info)("Bad shading domain.");else{for(var I,O=new Float32Array(l.numComps),T=new Float32Array(1),E=u;E<=h;E+=A){T[0]=E;x(T,0,O,0);I=l.getRgb(O,0);var F=a.Util.makeCssRgb(I[0],I[1],I[2]);P.push([(E-u)/_,F])}var R="transparent";if(e.has("Background")){I=l.getRgb(e.get("Background"),0);R=a.Util.makeCssRgb(I[0],I[1],I[2])}if(!d){P.unshift([0,R]);P[1][0]+=c.SMALL_NUMBER}if(!g){P[P.length-1][0]-=c.SMALL_NUMBER;P.push([1,R])}this.colorStops=P}}e.prototype={getIR:function(){var e,t,r,i,n,s=this.coordsArr,c=this.shadingType;if(c===o.AXIAL){t=[s[0],s[1]];r=[s[2],s[3]];i=null;n=null;e="axial"}else if(c===o.RADIAL){t=[s[0],s[1]];r=[s[3],s[4]];i=s[2];n=s[5];e="radial"}else(0,a.unreachable)("getPattern type unknown: "+c);var l=this.matrix;if(l){t=a.Util.applyTransform(t,l);r=a.Util.applyTransform(r,l);if(c===o.RADIAL){var u=a.Util.singularValueDecompose2dScale(l);i*=u[0];n*=u[1]}}return["RadialAxial",e,this.colorStops,t,r,i,n]}};return e}();c.Mesh=function(){function e(e,t){this.stream=e;this.context=t;this.buffer=0;this.bufferLength=0;var r=t.numComps;this.tmpCompsBuf=new Float32Array(r);var a=t.colorSpace.numComps;this.tmpCsCompsBuf=t.colorFn?new Float32Array(a):this.tmpCompsBuf}e.prototype={get hasData(){if(this.stream.end)return this.stream.pos<this.stream.end;if(this.bufferLength>0)return!0;var e=this.stream.getByte();if(e<0)return!1;this.buffer=e;this.bufferLength=8;return!0},readBits:function(e){var t=this.buffer,r=this.bufferLength;if(32===e){if(0===r)return(this.stream.getByte()<<24|this.stream.getByte()<<16|this.stream.getByte()<<8|this.stream.getByte())>>>0;t=t<<24|this.stream.getByte()<<16|this.stream.getByte()<<8|this.stream.getByte();var a=this.stream.getByte();this.buffer=a&(1<<r)-1;return(t<<8-r|(255&a)>>r)>>>0}if(8===e&&0===r)return this.stream.getByte();for(;r<e;){t=t<<8|this.stream.getByte();r+=8}r-=e;this.bufferLength=r;this.buffer=t&(1<<r)-1;return t>>r},align:function(){this.buffer=0;this.bufferLength=0},readFlag:function(){return this.readBits(this.context.bitsPerFlag)},readCoordinate:function(){var e=this.context.bitsPerCoordinate,t=this.readBits(e),r=this.readBits(e),a=this.context.decode,i=e<32?1/((1<<e)-1):2.3283064365386963e-10;return[t*i*(a[1]-a[0])+a[0],r*i*(a[3]-a[2])+a[2]]},readComponents:function(){for(var e=this.context.numComps,t=this.context.bitsPerComponent,r=t<32?1/((1<<t)-1):2.3283064365386963e-10,a=this.context.decode,i=this.tmpCompsBuf,n=0,o=4;n<e;n++,o+=2){var s=this.readBits(t);i[n]=s*r*(a[o+1]-a[o])+a[o]}var c=this.tmpCsCompsBuf;this.context.colorFn&&this.context.colorFn(i,0,c,0);return this.context.colorSpace.getRgb(c,0)}};var t=3,r=20,s=20,c=function(){var e=[];return function(t){e[t]||(e[t]=function(e){for(var t=[],r=0;r<=e;r++){var a=r/e,i=1-a;t.push(new Float32Array([i*i*i,3*a*i*i,3*a*a*i,a*a*a]))}return t}(t));return e[t]}}();function l(e,i){var n=e.figures[i];(0,a.assert)("patch"===n.type,"Unexpected patch mesh figure");var o=e.coords,l=e.colors,u=n.coords,h=n.colors,f=Math.min(o[u[0]][0],o[u[3]][0],o[u[12]][0],o[u[15]][0]),d=Math.min(o[u[0]][1],o[u[3]][1],o[u[12]][1],o[u[15]][1]),g=Math.max(o[u[0]][0],o[u[3]][0],o[u[12]][0],o[u[15]][0]),m=Math.max(o[u[0]][1],o[u[3]][1],o[u[12]][1],o[u[15]][1]),p=Math.ceil((g-f)*s/(e.bounds[2]-e.bounds[0]));p=Math.max(t,Math.min(r,p));var v=Math.ceil((m-d)*s/(e.bounds[3]-e.bounds[1]));v=Math.max(t,Math.min(r,v));for(var b=p+1,y=new Int32Array((v+1)*b),w=new Int32Array((v+1)*b),k=0,S=new Uint8Array(3),C=new Uint8Array(3),x=l[h[0]],_=l[h[1]],A=l[h[2]],P=l[h[3]],I=c(v),O=c(p),T=0;T<=v;T++){S[0]=(x[0]*(v-T)+A[0]*T)/v|0;S[1]=(x[1]*(v-T)+A[1]*T)/v|0;S[2]=(x[2]*(v-T)+A[2]*T)/v|0;C[0]=(_[0]*(v-T)+P[0]*T)/v|0;C[1]=(_[1]*(v-T)+P[1]*T)/v|0;C[2]=(_[2]*(v-T)+P[2]*T)/v|0;for(var E=0;E<=p;E++,k++)if(0!==T&&T!==v||0!==E&&E!==p){for(var F=0,R=0,B=0,D=0;D<=3;D++)for(var M=0;M<=3;M++,B++){var L=I[T][D]*O[E][M];F+=o[u[B]][0]*L;R+=o[u[B]][1]*L}y[k]=o.length;o.push([F,R]);w[k]=l.length;var N=new Uint8Array(3);N[0]=(S[0]*(p-E)+C[0]*E)/p|0;N[1]=(S[1]*(p-E)+C[1]*E)/p|0;N[2]=(S[2]*(p-E)+C[2]*E)/p|0;l.push(N)}}y[0]=u[0];w[0]=h[0];y[p]=u[3];w[p]=h[1];y[b*v]=u[12];w[b*v]=h[2];y[b*v+p]=u[15];w[b*v+p]=h[3];e.figures[i]={type:"lattice",coords:y,colors:w,verticesPerRow:b}}function u(e){for(var t=e.coords[0][0],r=e.coords[0][1],a=t,i=r,n=1,o=e.coords.length;n<o;n++){var s=e.coords[n][0],c=e.coords[n][1];t=t>s?s:t;r=r>c?c:r;a=a<s?s:a;i=i<c?c:i}e.bounds=[t,r,a,i]}function h(t,r,s,c,h){if(!(0,n.isStream)(t))throw new a.FormatError("Mesh data is not a stream");var f=t.dict;this.matrix=r;this.shadingType=f.get("ShadingType");this.type="Pattern";this.bbox=f.getArray("BBox");var d=f.get("ColorSpace","CS");d=i.ColorSpace.parse(d,s,c,h);this.cs=d;this.background=f.has("Background")?d.getRgb(f.get("Background"),0):null;var g=f.get("Function"),m=g?h.createFromArray(g):null;this.coords=[];this.colors=[];this.figures=[];var p=new e(t,{bitsPerCoordinate:f.get("BitsPerCoordinate"),bitsPerComponent:f.get("BitsPerComponent"),bitsPerFlag:f.get("BitsPerFlag"),decode:f.getArray("Decode"),colorFn:m,colorSpace:d,numComps:m?1:d.numComps}),v=!1;switch(this.shadingType){case o.FREE_FORM_MESH:!function(e,t){for(var r=e.coords,i=e.colors,n=[],o=[],s=0;t.hasData;){var c=t.readFlag(),l=t.readCoordinate(),u=t.readComponents();if(0===s){if(!(0<=c&&c<=2))throw new a.FormatError("Unknown type4 flag");switch(c){case 0:s=3;break;case 1:o.push(o[o.length-2],o[o.length-1]);s=1;break;case 2:o.push(o[o.length-3],o[o.length-1]);s=1}n.push(c)}o.push(r.length);r.push(l);i.push(u);s--;t.align()}e.figures.push({type:"triangles",coords:new Int32Array(o),colors:new Int32Array(o)})}(this,p);break;case o.LATTICE_FORM_MESH:var b=0|f.get("VerticesPerRow");if(b<2)throw new a.FormatError("Invalid VerticesPerRow");!function(e,t,r){for(var a=e.coords,i=e.colors,n=[];t.hasData;){var o=t.readCoordinate(),s=t.readComponents();n.push(a.length);a.push(o);i.push(s)}e.figures.push({type:"lattice",coords:new Int32Array(n),colors:new Int32Array(n),verticesPerRow:r})}(this,p,b);break;case o.COONS_PATCH_MESH:!function(e,t){for(var r=e.coords,i=e.colors,n=new Int32Array(16),o=new Int32Array(4);t.hasData;){var s,c,l=t.readFlag();if(!(0<=l&&l<=3))throw new a.FormatError("Unknown type6 flag");var u=r.length;for(s=0,c=0!==l?8:12;s<c;s++)r.push(t.readCoordinate());var h,f,d,g,m=i.length;for(s=0,c=0!==l?2:4;s<c;s++)i.push(t.readComponents());switch(l){case 0:n[12]=u+3;n[13]=u+4;n[14]=u+5;n[15]=u+6;n[8]=u+2;n[11]=u+7;n[4]=u+1;n[7]=u+8;n[0]=u;n[1]=u+11;n[2]=u+10;n[3]=u+9;o[2]=m+1;o[3]=m+2;o[0]=m;o[1]=m+3;break;case 1:h=n[12];f=n[13];d=n[14];g=n[15];n[12]=g;n[13]=u+0;n[14]=u+1;n[15]=u+2;n[8]=d;n[11]=u+3;n[4]=f;n[7]=u+4;n[0]=h;n[1]=u+7;n[2]=u+6;n[3]=u+5;h=o[2];f=o[3];o[2]=f;o[3]=m;o[0]=h;o[1]=m+1;break;case 2:h=n[15];f=n[11];n[12]=n[3];n[13]=u+0;n[14]=u+1;n[15]=u+2;n[8]=n[7];n[11]=u+3;n[4]=f;n[7]=u+4;n[0]=h;n[1]=u+7;n[2]=u+6;n[3]=u+5;h=o[3];o[2]=o[1];o[3]=m;o[0]=h;o[1]=m+1;break;case 3:n[12]=n[0];n[13]=u+0;n[14]=u+1;n[15]=u+2;n[8]=n[1];n[11]=u+3;n[4]=n[2];n[7]=u+4;n[0]=n[3];n[1]=u+7;n[2]=u+6;n[3]=u+5;o[2]=o[0];o[3]=m;o[0]=o[1];o[1]=m+1}n[5]=r.length;r.push([(-4*r[n[0]][0]-r[n[15]][0]+6*(r[n[4]][0]+r[n[1]][0])-2*(r[n[12]][0]+r[n[3]][0])+3*(r[n[13]][0]+r[n[7]][0]))/9,(-4*r[n[0]][1]-r[n[15]][1]+6*(r[n[4]][1]+r[n[1]][1])-2*(r[n[12]][1]+r[n[3]][1])+3*(r[n[13]][1]+r[n[7]][1]))/9]);n[6]=r.length;r.push([(-4*r[n[3]][0]-r[n[12]][0]+6*(r[n[2]][0]+r[n[7]][0])-2*(r[n[0]][0]+r[n[15]][0])+3*(r[n[4]][0]+r[n[14]][0]))/9,(-4*r[n[3]][1]-r[n[12]][1]+6*(r[n[2]][1]+r[n[7]][1])-2*(r[n[0]][1]+r[n[15]][1])+3*(r[n[4]][1]+r[n[14]][1]))/9]);n[9]=r.length;r.push([(-4*r[n[12]][0]-r[n[3]][0]+6*(r[n[8]][0]+r[n[13]][0])-2*(r[n[0]][0]+r[n[15]][0])+3*(r[n[11]][0]+r[n[1]][0]))/9,(-4*r[n[12]][1]-r[n[3]][1]+6*(r[n[8]][1]+r[n[13]][1])-2*(r[n[0]][1]+r[n[15]][1])+3*(r[n[11]][1]+r[n[1]][1]))/9]);n[10]=r.length;r.push([(-4*r[n[15]][0]-r[n[0]][0]+6*(r[n[11]][0]+r[n[14]][0])-2*(r[n[12]][0]+r[n[3]][0])+3*(r[n[2]][0]+r[n[8]][0]))/9,(-4*r[n[15]][1]-r[n[0]][1]+6*(r[n[11]][1]+r[n[14]][1])-2*(r[n[12]][1]+r[n[3]][1])+3*(r[n[2]][1]+r[n[8]][1]))/9]);e.figures.push({type:"patch",coords:new Int32Array(n),colors:new Int32Array(o)})}}(this,p);v=!0;break;case o.TENSOR_PATCH_MESH:!function(e,t){for(var r=e.coords,i=e.colors,n=new Int32Array(16),o=new Int32Array(4);t.hasData;){var s,c,l=t.readFlag();if(!(0<=l&&l<=3))throw new a.FormatError("Unknown type7 flag");var u=r.length;for(s=0,c=0!==l?12:16;s<c;s++)r.push(t.readCoordinate());var h,f,d,g,m=i.length;for(s=0,c=0!==l?2:4;s<c;s++)i.push(t.readComponents());switch(l){case 0:n[12]=u+3;n[13]=u+4;n[14]=u+5;n[15]=u+6;n[8]=u+2;n[9]=u+13;n[10]=u+14;n[11]=u+7;n[4]=u+1;n[5]=u+12;n[6]=u+15;n[7]=u+8;n[0]=u;n[1]=u+11;n[2]=u+10;n[3]=u+9;o[2]=m+1;o[3]=m+2;o[0]=m;o[1]=m+3;break;case 1:h=n[12];f=n[13];d=n[14];g=n[15];n[12]=g;n[13]=u+0;n[14]=u+1;n[15]=u+2;n[8]=d;n[9]=u+9;n[10]=u+10;n[11]=u+3;n[4]=f;n[5]=u+8;n[6]=u+11;n[7]=u+4;n[0]=h;n[1]=u+7;n[2]=u+6;n[3]=u+5;h=o[2];f=o[3];o[2]=f;o[3]=m;o[0]=h;o[1]=m+1;break;case 2:h=n[15];f=n[11];n[12]=n[3];n[13]=u+0;n[14]=u+1;n[15]=u+2;n[8]=n[7];n[9]=u+9;n[10]=u+10;n[11]=u+3;n[4]=f;n[5]=u+8;n[6]=u+11;n[7]=u+4;n[0]=h;n[1]=u+7;n[2]=u+6;n[3]=u+5;h=o[3];o[2]=o[1];o[3]=m;o[0]=h;o[1]=m+1;break;case 3:n[12]=n[0];n[13]=u+0;n[14]=u+1;n[15]=u+2;n[8]=n[1];n[9]=u+9;n[10]=u+10;n[11]=u+3;n[4]=n[2];n[5]=u+8;n[6]=u+11;n[7]=u+4;n[0]=n[3];n[1]=u+7;n[2]=u+6;n[3]=u+5;o[2]=o[0];o[3]=m;o[0]=o[1];o[1]=m+1}e.figures.push({type:"patch",coords:new Int32Array(n),colors:new Int32Array(o)})}}(this,p);v=!0;break;default:(0,a.unreachable)("Unsupported mesh type.")}if(v){u(this);for(var y=0,w=this.figures.length;y<w;y++)l(this,y)}u(this);!function(e){var t,r,a,i,n=e.coords,o=new Float32Array(2*n.length);for(t=0,a=0,r=n.length;t<r;t++){var s=n[t];o[a++]=s[0];o[a++]=s[1]}e.coords=o;var c=e.colors,l=new Uint8Array(3*c.length);for(t=0,a=0,r=c.length;t<r;t++){var u=c[t];l[a++]=u[0];l[a++]=u[1];l[a++]=u[2]}e.colors=l;var h=e.figures;for(t=0,r=h.length;t<r;t++){var f=h[t],d=f.coords,g=f.colors;for(a=0,i=d.length;a<i;a++){d[a]*=2;g[a]*=3}}}(this)}h.prototype={getIR:function(){return["Mesh",this.shadingType,this.coords,this.colors,this.figures,this.bounds,this.matrix,this.bbox,this.background]}};return h}();c.Dummy=function(){function e(){this.type="Pattern"}e.prototype={getIR:function(){return["Dummy"]}};return e}();t.Pattern=s;t.getTilingPatternIR=function(e,t,r){var i=t.getArray("Matrix"),n=a.Util.normalizeRect(t.getArray("BBox")),o=t.get("XStep"),s=t.get("YStep"),c=t.get("PaintType"),l=t.get("TilingType");if(n[2]-n[0]==0||n[3]-n[1]==0)throw new a.FormatError("Invalid getTilingPatternIR /BBox array: ["+n+"].");return["TilingPattern",r,e,i,n,o,s,c,l]}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.bidi=void 0;var a=r(2),i=["BN","BN","BN","BN","BN","BN","BN","BN","BN","S","B","S","WS","B","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","B","B","B","S","WS","ON","ON","ET","ET","ET","ON","ON","ON","ON","ON","ES","CS","ES","CS","CS","EN","EN","EN","EN","EN","EN","EN","EN","EN","EN","CS","ON","ON","ON","ON","ON","ON","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","ON","ON","ON","ON","ON","ON","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","ON","ON","ON","ON","BN","BN","BN","BN","BN","BN","B","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","BN","CS","ON","ET","ET","ET","ET","ON","ON","ON","ON","L","ON","ON","BN","ON","ON","ET","ET","EN","EN","ON","L","ON","ON","ON","EN","L","ON","ON","ON","ON","ON","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","ON","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","L","ON","L","L","L","L","L","L","L","L"],n=["AN","AN","AN","AN","AN","AN","ON","ON","AL","ET","ET","AL","CS","AL","ON","ON","NSM","NSM","NSM","NSM","NSM","NSM","NSM","NSM","NSM","NSM","NSM","AL","AL","","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","NSM","NSM","NSM","NSM","NSM","NSM","NSM","NSM","NSM","NSM","NSM","NSM","NSM","NSM","NSM","NSM","NSM","NSM","NSM","NSM","NSM","AN","AN","AN","AN","AN","AN","AN","AN","AN","AN","ET","AN","AN","AL","AL","AL","NSM","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","AL","NSM","NSM","NSM","NSM","NSM","NSM","NSM","AN","ON","NSM","NSM","NSM","NSM","NSM","NSM","AL","AL","NSM","NSM","ON","NSM","NSM","NSM","NSM","AL","AL","EN","EN","EN","EN","EN","EN","EN","EN","EN","EN","AL","AL","AL","AL","AL","AL"];function o(e){return 0!=(1&e)}function s(e){return 0==(1&e)}function c(e,t,r){for(var a=t,i=e.length;a<i;++a)if(e[a]!==r)return a;return a}function l(e,t,r,a){for(var i=t;i<r;++i)e[i]=a}function u(e,t,r){for(var a=t,i=r-1;a<i;++a,--i){var n=e[a];e[a]=e[i];e[i]=n}}function h(e,t,r){return{str:e,dir:r?"ttb":t?"ltr":"rtl"}}var f=[],d=[];t.bidi=function(e,t,r){var g=!0,m=e.length;if(0===m||r)return h(e,g,r);f.length=m;d.length=m;var p,v,b=0;for(p=0;p<m;++p){f[p]=e.charAt(p);var y=e.charCodeAt(p),w="L";y<=255?w=i[y]:1424<=y&&y<=1524?w="R":1536<=y&&y<=1791?(w=n[255&y])||(0,a.warn)("Bidi: invalid Unicode character "+y.toString(16)):1792<=y&&y<=2220&&(w="AL");"R"!==w&&"AL"!==w&&"AN"!==w||b++;d[p]=w}if(0===b)return h(e,g=!0);if(-1===t)if(b/m<.3){g=!0;t=0}else{g=!1;t=1}var k=[];for(p=0;p<m;++p)k[p]=t;var S,C=o(t)?"R":"L",x=C,_=x,A=x;for(p=0;p<m;++p)"NSM"===d[p]?d[p]=A:A=d[p];A=x;for(p=0;p<m;++p)"EN"===(S=d[p])?d[p]="AL"===A?"AN":"EN":"R"!==S&&"L"!==S&&"AL"!==S||(A=S);for(p=0;p<m;++p)"AL"===(S=d[p])&&(d[p]="R");for(p=1;p<m-1;++p){"ES"===d[p]&&"EN"===d[p-1]&&"EN"===d[p+1]&&(d[p]="EN");"CS"!==d[p]||"EN"!==d[p-1]&&"AN"!==d[p-1]||d[p+1]!==d[p-1]||(d[p]=d[p-1])}for(p=0;p<m;++p)if("EN"===d[p]){var P;for(P=p-1;P>=0&&"ET"===d[P];--P)d[P]="EN";for(P=p+1;P<m&&"ET"===d[P];++P)d[P]="EN"}for(p=0;p<m;++p)"WS"!==(S=d[p])&&"ES"!==S&&"ET"!==S&&"CS"!==S||(d[p]="ON");A=x;for(p=0;p<m;++p)"EN"===(S=d[p])?d[p]="L"===A?"L":"EN":"R"!==S&&"L"!==S||(A=S);for(p=0;p<m;++p)if("ON"===d[p]){var I=c(d,p+1,"ON"),O=x;p>0&&(O=d[p-1]);var T=_;I+1<m&&(T=d[I+1]);"L"!==O&&(O="R");"L"!==T&&(T="R");O===T&&l(d,p,I,O);p=I-1}for(p=0;p<m;++p)"ON"===d[p]&&(d[p]=C);for(p=0;p<m;++p){S=d[p];s(k[p])?"R"===S?k[p]+=1:"AN"!==S&&"EN"!==S||(k[p]+=2):"L"!==S&&"AN"!==S&&"EN"!==S||(k[p]+=1)}var E,F=-1,R=99;for(p=0,v=k.length;p<v;++p){F<(E=k[p])&&(F=E);R>E&&o(E)&&(R=E)}for(E=F;E>=R;--E){var B=-1;for(p=0,v=k.length;p<v;++p)if(k[p]<E){if(B>=0){u(f,B,p);B=-1}}else B<0&&(B=p);B>=0&&u(f,B,k.length)}for(p=0,v=f.length;p<v;++p){var D=f[p];"<"!==D&&">"!==D||(f[p]="")}return h(f.join(""),g)}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.getMetrics=void 0;var a=r(2),i=(0,a.getLookupTableFactory)(function(e){e.Courier=600;e["Courier-Bold"]=600;e["Courier-BoldOblique"]=600;e["Courier-Oblique"]=600;e.Helvetica=(0,a.getLookupTableFactory)(function(e){e.space=278;e.exclam=278;e.quotedbl=355;e.numbersign=556;e.dollar=556;e.percent=889;e.ampersand=667;e.quoteright=222;e.parenleft=333;e.parenright=333;e.asterisk=389;e.plus=584;e.comma=278;e.hyphen=333;e.period=278;e.slash=278;e.zero=556;e.one=556;e.two=556;e.three=556;e.four=556;e.five=556;e.six=556;e.seven=556;e.eight=556;e.nine=556;e.colon=278;e.semicolon=278;e.less=584;e.equal=584;e.greater=584;e.question=556;e.at=1015;e.A=667;e.B=667;e.C=722;e.D=722;e.E=667;e.F=611;e.G=778;e.H=722;e.I=278;e.J=500;e.K=667;e.L=556;e.M=833;e.N=722;e.O=778;e.P=667;e.Q=778;e.R=722;e.S=667;e.T=611;e.U=722;e.V=667;e.W=944;e.X=667;e.Y=667;e.Z=611;e.bracketleft=278;e.backslash=278;e.bracketright=278;e.asciicircum=469;e.underscore=556;e.quoteleft=222;e.a=556;e.b=556;e.c=500;e.d=556;e.e=556;e.f=278;e.g=556;e.h=556;e.i=222;e.j=222;e.k=500;e.l=222;e.m=833;e.n=556;e.o=556;e.p=556;e.q=556;e.r=333;e.s=500;e.t=278;e.u=556;e.v=500;e.w=722;e.x=500;e.y=500;e.z=500;e.braceleft=334;e.bar=260;e.braceright=334;e.asciitilde=584;e.exclamdown=333;e.cent=556;e.sterling=556;e.fraction=167;e.yen=556;e.florin=556;e.section=556;e.currency=556;e.quotesingle=191;e.quotedblleft=333;e.guillemotleft=556;e.guilsinglleft=333;e.guilsinglright=333;e.fi=500;e.fl=500;e.endash=556;e.dagger=556;e.daggerdbl=556;e.periodcentered=278;e.paragraph=537;e.bullet=350;e.quotesinglbase=222;e.quotedblbase=333;e.quotedblright=333;e.guillemotright=556;e.ellipsis=1e3;e.perthousand=1e3;e.questiondown=611;e.grave=333;e.acute=333;e.circumflex=333;e.tilde=333;e.macron=333;e.breve=333;e.dotaccent=333;e.dieresis=333;e.ring=333;e.cedilla=333;e.hungarumlaut=333;e.ogonek=333;e.caron=333;e.emdash=1e3;e.AE=1e3;e.ordfeminine=370;e.Lslash=556;e.Oslash=778;e.OE=1e3;e.ordmasculine=365;e.ae=889;e.dotlessi=278;e.lslash=222;e.oslash=611;e.oe=944;e.germandbls=611;e.Idieresis=278;e.eacute=556;e.abreve=556;e.uhungarumlaut=556;e.ecaron=556;e.Ydieresis=667;e.divide=584;e.Yacute=667;e.Acircumflex=667;e.aacute=556;e.Ucircumflex=722;e.yacute=500;e.scommaaccent=500;e.ecircumflex=556;e.Uring=722;e.Udieresis=722;e.aogonek=556;e.Uacute=722;e.uogonek=556;e.Edieresis=667;e.Dcroat=722;e.commaaccent=250;e.copyright=737;e.Emacron=667;e.ccaron=500;e.aring=556;e.Ncommaaccent=722;e.lacute=222;e.agrave=556;e.Tcommaaccent=611;e.Cacute=722;e.atilde=556;e.Edotaccent=667;e.scaron=500;e.scedilla=500;e.iacute=278;e.lozenge=471;e.Rcaron=722;e.Gcommaaccent=778;e.ucircumflex=556;e.acircumflex=556;e.Amacron=667;e.rcaron=333;e.ccedilla=500;e.Zdotaccent=611;e.Thorn=667;e.Omacron=778;e.Racute=722;e.Sacute=667;e.dcaron=643;e.Umacron=722;e.uring=556;e.threesuperior=333;e.Ograve=778;e.Agrave=667;e.Abreve=667;e.multiply=584;e.uacute=556;e.Tcaron=611;e.partialdiff=476;e.ydieresis=500;e.Nacute=722;e.icircumflex=278;e.Ecircumflex=667;e.adieresis=556;e.edieresis=556;e.cacute=500;e.nacute=556;e.umacron=556;e.Ncaron=722;e.Iacute=278;e.plusminus=584;e.brokenbar=260;e.registered=737;e.Gbreve=778;e.Idotaccent=278;e.summation=600;e.Egrave=667;e.racute=333;e.omacron=556;e.Zacute=611;e.Zcaron=611;e.greaterequal=549;e.Eth=722;e.Ccedilla=722;e.lcommaaccent=222;e.tcaron=317;e.eogonek=556;e.Uogonek=722;e.Aacute=667;e.Adieresis=667;e.egrave=556;e.zacute=500;e.iogonek=222;e.Oacute=778;e.oacute=556;e.amacron=556;e.sacute=500;e.idieresis=278;e.Ocircumflex=778;e.Ugrave=722;e.Delta=612;e.thorn=556;e.twosuperior=333;e.Odieresis=778;e.mu=556;e.igrave=278;e.ohungarumlaut=556;e.Eogonek=667;e.dcroat=556;e.threequarters=834;e.Scedilla=667;e.lcaron=299;e.Kcommaaccent=667;e.Lacute=556;e.trademark=1e3;e.edotaccent=556;e.Igrave=278;e.Imacron=278;e.Lcaron=556;e.onehalf=834;e.lessequal=549;e.ocircumflex=556;e.ntilde=556;e.Uhungarumlaut=722;e.Eacute=667;e.emacron=556;e.gbreve=556;e.onequarter=834;e.Scaron=667;e.Scommaaccent=667;e.Ohungarumlaut=778;e.degree=400;e.ograve=556;e.Ccaron=722;e.ugrave=556;e.radical=453;e.Dcaron=722;e.rcommaaccent=333;e.Ntilde=722;e.otilde=556;e.Rcommaaccent=722;e.Lcommaaccent=556;e.Atilde=667;e.Aogonek=667;e.Aring=667;e.Otilde=778;e.zdotaccent=500;e.Ecaron=667;e.Iogonek=278;e.kcommaaccent=500;e.minus=584;e.Icircumflex=278;e.ncaron=556;e.tcommaaccent=278;e.logicalnot=584;e.odieresis=556;e.udieresis=556;e.notequal=549;e.gcommaaccent=556;e.eth=556;e.zcaron=500;e.ncommaaccent=556;e.onesuperior=333;e.imacron=278;e.Euro=556});e["Helvetica-Bold"]=(0,a.getLookupTableFactory)(function(e){e.space=278;e.exclam=333;e.quotedbl=474;e.numbersign=556;e.dollar=556;e.percent=889;e.ampersand=722;e.quoteright=278;e.parenleft=333;e.parenright=333;e.asterisk=389;e.plus=584;e.comma=278;e.hyphen=333;e.period=278;e.slash=278;e.zero=556;e.one=556;e.two=556;e.three=556;e.four=556;e.five=556;e.six=556;e.seven=556;e.eight=556;e.nine=556;e.colon=333;e.semicolon=333;e.less=584;e.equal=584;e.greater=584;e.question=611;e.at=975;e.A=722;e.B=722;e.C=722;e.D=722;e.E=667;e.F=611;e.G=778;e.H=722;e.I=278;e.J=556;e.K=722;e.L=611;e.M=833;e.N=722;e.O=778;e.P=667;e.Q=778;e.R=722;e.S=667;e.T=611;e.U=722;e.V=667;e.W=944;e.X=667;e.Y=667;e.Z=611;e.bracketleft=333;e.backslash=278;e.bracketright=333;e.asciicircum=584;e.underscore=556;e.quoteleft=278;e.a=556;e.b=611;e.c=556;e.d=611;e.e=556;e.f=333;e.g=611;e.h=611;e.i=278;e.j=278;e.k=556;e.l=278;e.m=889;e.n=611;e.o=611;e.p=611;e.q=611;e.r=389;e.s=556;e.t=333;e.u=611;e.v=556;e.w=778;e.x=556;e.y=556;e.z=500;e.braceleft=389;e.bar=280;e.braceright=389;e.asciitilde=584;e.exclamdown=333;e.cent=556;e.sterling=556;e.fraction=167;e.yen=556;e.florin=556;e.section=556;e.currency=556;e.quotesingle=238;e.quotedblleft=500;e.guillemotleft=556;e.guilsinglleft=333;e.guilsinglright=333;e.fi=611;e.fl=611;e.endash=556;e.dagger=556;e.daggerdbl=556;e.periodcentered=278;e.paragraph=556;e.bullet=350;e.quotesinglbase=278;e.quotedblbase=500;e.quotedblright=500;e.guillemotright=556;e.ellipsis=1e3;e.perthousand=1e3;e.questiondown=611;e.grave=333;e.acute=333;e.circumflex=333;e.tilde=333;e.macron=333;e.breve=333;e.dotaccent=333;e.dieresis=333;e.ring=333;e.cedilla=333;e.hungarumlaut=333;e.ogonek=333;e.caron=333;e.emdash=1e3;e.AE=1e3;e.ordfeminine=370;e.Lslash=611;e.Oslash=778;e.OE=1e3;e.ordmasculine=365;e.ae=889;e.dotlessi=278;e.lslash=278;e.oslash=611;e.oe=944;e.germandbls=611;e.Idieresis=278;e.eacute=556;e.abreve=556;e.uhungarumlaut=611;e.ecaron=556;e.Ydieresis=667;e.divide=584;e.Yacute=667;e.Acircumflex=722;e.aacute=556;e.Ucircumflex=722;e.yacute=556;e.scommaaccent=556;e.ecircumflex=556;e.Uring=722;e.Udieresis=722;e.aogonek=556;e.Uacute=722;e.uogonek=611;e.Edieresis=667;e.Dcroat=722;e.commaaccent=250;e.copyright=737;e.Emacron=667;e.ccaron=556;e.aring=556;e.Ncommaaccent=722;e.lacute=278;e.agrave=556;e.Tcommaaccent=611;e.Cacute=722;e.atilde=556;e.Edotaccent=667;e.scaron=556;e.scedilla=556;e.iacute=278;e.lozenge=494;e.Rcaron=722;e.Gcommaaccent=778;e.ucircumflex=611;e.acircumflex=556;e.Amacron=722;e.rcaron=389;e.ccedilla=556;e.Zdotaccent=611;e.Thorn=667;e.Omacron=778;e.Racute=722;e.Sacute=667;e.dcaron=743;e.Umacron=722;e.uring=611;e.threesuperior=333;e.Ograve=778;e.Agrave=722;e.Abreve=722;e.multiply=584;e.uacute=611;e.Tcaron=611;e.partialdiff=494;e.ydieresis=556;e.Nacute=722;e.icircumflex=278;e.Ecircumflex=667;e.adieresis=556;e.edieresis=556;e.cacute=556;e.nacute=611;e.umacron=611;e.Ncaron=722;e.Iacute=278;e.plusminus=584;e.brokenbar=280;e.registered=737;e.Gbreve=778;e.Idotaccent=278;e.summation=600;e.Egrave=667;e.racute=389;e.omacron=611;e.Zacute=611;e.Zcaron=611;e.greaterequal=549;e.Eth=722;e.Ccedilla=722;e.lcommaaccent=278;e.tcaron=389;e.eogonek=556;e.Uogonek=722;e.Aacute=722;e.Adieresis=722;e.egrave=556;e.zacute=500;e.iogonek=278;e.Oacute=778;e.oacute=611;e.amacron=556;e.sacute=556;e.idieresis=278;e.Ocircumflex=778;e.Ugrave=722;e.Delta=612;e.thorn=611;e.twosuperior=333;e.Odieresis=778;e.mu=611;e.igrave=278;e.ohungarumlaut=611;e.Eogonek=667;e.dcroat=611;e.threequarters=834;e.Scedilla=667;e.lcaron=400;e.Kcommaaccent=722;e.Lacute=611;e.trademark=1e3;e.edotaccent=556;e.Igrave=278;e.Imacron=278;e.Lcaron=611;e.onehalf=834;e.lessequal=549;e.ocircumflex=611;e.ntilde=611;e.Uhungarumlaut=722;e.Eacute=667;e.emacron=556;e.gbreve=611;e.onequarter=834;e.Scaron=667;e.Scommaaccent=667;e.Ohungarumlaut=778;e.degree=400;e.ograve=611;e.Ccaron=722;e.ugrave=611;e.radical=549;e.Dcaron=722;e.rcommaaccent=389;e.Ntilde=722;e.otilde=611;e.Rcommaaccent=722;e.Lcommaaccent=611;e.Atilde=722;e.Aogonek=722;e.Aring=722;e.Otilde=778;e.zdotaccent=500;e.Ecaron=667;e.Iogonek=278;e.kcommaaccent=556;e.minus=584;e.Icircumflex=278;e.ncaron=611;e.tcommaaccent=333;e.logicalnot=584;e.odieresis=611;e.udieresis=611;e.notequal=549;e.gcommaaccent=611;e.eth=611;e.zcaron=500;e.ncommaaccent=611;e.onesuperior=333;e.imacron=278;e.Euro=556});e["Helvetica-BoldOblique"]=(0,a.getLookupTableFactory)(function(e){e.space=278;e.exclam=333;e.quotedbl=474;e.numbersign=556;e.dollar=556;e.percent=889;e.ampersand=722;e.quoteright=278;e.parenleft=333;e.parenright=333;e.asterisk=389;e.plus=584;e.comma=278;e.hyphen=333;e.period=278;e.slash=278;e.zero=556;e.one=556;e.two=556;e.three=556;e.four=556;e.five=556;e.six=556;e.seven=556;e.eight=556;e.nine=556;e.colon=333;e.semicolon=333;e.less=584;e.equal=584;e.greater=584;e.question=611;e.at=975;e.A=722;e.B=722;e.C=722;e.D=722;e.E=667;e.F=611;e.G=778;e.H=722;e.I=278;e.J=556;e.K=722;e.L=611;e.M=833;e.N=722;e.O=778;e.P=667;e.Q=778;e.R=722;e.S=667;e.T=611;e.U=722;e.V=667;e.W=944;e.X=667;e.Y=667;e.Z=611;e.bracketleft=333;e.backslash=278;e.bracketright=333;e.asciicircum=584;e.underscore=556;e.quoteleft=278;e.a=556;e.b=611;e.c=556;e.d=611;e.e=556;e.f=333;e.g=611;e.h=611;e.i=278;e.j=278;e.k=556;e.l=278;e.m=889;e.n=611;e.o=611;e.p=611;e.q=611;e.r=389;e.s=556;e.t=333;e.u=611;e.v=556;e.w=778;e.x=556;e.y=556;e.z=500;e.braceleft=389;e.bar=280;e.braceright=389;e.asciitilde=584;e.exclamdown=333;e.cent=556;e.sterling=556;e.fraction=167;e.yen=556;e.florin=556;e.section=556;e.currency=556;e.quotesingle=238;e.quotedblleft=500;e.guillemotleft=556;e.guilsinglleft=333;e.guilsinglright=333;e.fi=611;e.fl=611;e.endash=556;e.dagger=556;e.daggerdbl=556;e.periodcentered=278;e.paragraph=556;e.bullet=350;e.quotesinglbase=278;e.quotedblbase=500;e.quotedblright=500;e.guillemotright=556;e.ellipsis=1e3;e.perthousand=1e3;e.questiondown=611;e.grave=333;e.acute=333;e.circumflex=333;e.tilde=333;e.macron=333;e.breve=333;e.dotaccent=333;e.dieresis=333;e.ring=333;e.cedilla=333;e.hungarumlaut=333;e.ogonek=333;e.caron=333;e.emdash=1e3;e.AE=1e3;e.ordfeminine=370;e.Lslash=611;e.Oslash=778;e.OE=1e3;e.ordmasculine=365;e.ae=889;e.dotlessi=278;e.lslash=278;e.oslash=611;e.oe=944;e.germandbls=611;e.Idieresis=278;e.eacute=556;e.abreve=556;e.uhungarumlaut=611;e.ecaron=556;e.Ydieresis=667;e.divide=584;e.Yacute=667;e.Acircumflex=722;e.aacute=556;e.Ucircumflex=722;e.yacute=556;e.scommaaccent=556;e.ecircumflex=556;e.Uring=722;e.Udieresis=722;e.aogonek=556;e.Uacute=722;e.uogonek=611;e.Edieresis=667;e.Dcroat=722;e.commaaccent=250;e.copyright=737;e.Emacron=667;e.ccaron=556;e.aring=556;e.Ncommaaccent=722;e.lacute=278;e.agrave=556;e.Tcommaaccent=611;e.Cacute=722;e.atilde=556;e.Edotaccent=667;e.scaron=556;e.scedilla=556;e.iacute=278;e.lozenge=494;e.Rcaron=722;e.Gcommaaccent=778;e.ucircumflex=611;e.acircumflex=556;e.Amacron=722;e.rcaron=389;e.ccedilla=556;e.Zdotaccent=611;e.Thorn=667;e.Omacron=778;e.Racute=722;e.Sacute=667;e.dcaron=743;e.Umacron=722;e.uring=611;e.threesuperior=333;e.Ograve=778;e.Agrave=722;e.Abreve=722;e.multiply=584;e.uacute=611;e.Tcaron=611;e.partialdiff=494;e.ydieresis=556;e.Nacute=722;e.icircumflex=278;e.Ecircumflex=667;e.adieresis=556;e.edieresis=556;e.cacute=556;e.nacute=611;e.umacron=611;e.Ncaron=722;e.Iacute=278;e.plusminus=584;e.brokenbar=280;e.registered=737;e.Gbreve=778;e.Idotaccent=278;e.summation=600;e.Egrave=667;e.racute=389;e.omacron=611;e.Zacute=611;e.Zcaron=611;e.greaterequal=549;e.Eth=722;e.Ccedilla=722;e.lcommaaccent=278;e.tcaron=389;e.eogonek=556;e.Uogonek=722;e.Aacute=722;e.Adieresis=722;e.egrave=556;e.zacute=500;e.iogonek=278;e.Oacute=778;e.oacute=611;e.amacron=556;e.sacute=556;e.idieresis=278;e.Ocircumflex=778;e.Ugrave=722;e.Delta=612;e.thorn=611;e.twosuperior=333;e.Odieresis=778;e.mu=611;e.igrave=278;e.ohungarumlaut=611;e.Eogonek=667;e.dcroat=611;e.threequarters=834;e.Scedilla=667;e.lcaron=400;e.Kcommaaccent=722;e.Lacute=611;e.trademark=1e3;e.edotaccent=556;e.Igrave=278;e.Imacron=278;e.Lcaron=611;e.onehalf=834;e.lessequal=549;e.ocircumflex=611;e.ntilde=611;e.Uhungarumlaut=722;e.Eacute=667;e.emacron=556;e.gbreve=611;e.onequarter=834;e.Scaron=667;e.Scommaaccent=667;e.Ohungarumlaut=778;e.degree=400;e.ograve=611;e.Ccaron=722;e.ugrave=611;e.radical=549;e.Dcaron=722;e.rcommaaccent=389;e.Ntilde=722;e.otilde=611;e.Rcommaaccent=722;e.Lcommaaccent=611;e.Atilde=722;e.Aogonek=722;e.Aring=722;e.Otilde=778;e.zdotaccent=500;e.Ecaron=667;e.Iogonek=278;e.kcommaaccent=556;e.minus=584;e.Icircumflex=278;e.ncaron=611;e.tcommaaccent=333;e.logicalnot=584;e.odieresis=611;e.udieresis=611;e.notequal=549;e.gcommaaccent=611;e.eth=611;e.zcaron=500;e.ncommaaccent=611;e.onesuperior=333;e.imacron=278;e.Euro=556});e["Helvetica-Oblique"]=(0,a.getLookupTableFactory)(function(e){e.space=278;e.exclam=278;e.quotedbl=355;e.numbersign=556;e.dollar=556;e.percent=889;e.ampersand=667;e.quoteright=222;e.parenleft=333;e.parenright=333;e.asterisk=389;e.plus=584;e.comma=278;e.hyphen=333;e.period=278;e.slash=278;e.zero=556;e.one=556;e.two=556;e.three=556;e.four=556;e.five=556;e.six=556;e.seven=556;e.eight=556;e.nine=556;e.colon=278;e.semicolon=278;e.less=584;e.equal=584;e.greater=584;e.question=556;e.at=1015;e.A=667;e.B=667;e.C=722;e.D=722;e.E=667;e.F=611;e.G=778;e.H=722;e.I=278;e.J=500;e.K=667;e.L=556;e.M=833;e.N=722;e.O=778;e.P=667;e.Q=778;e.R=722;e.S=667;e.T=611;e.U=722;e.V=667;e.W=944;e.X=667;e.Y=667;e.Z=611;e.bracketleft=278;e.backslash=278;e.bracketright=278;e.asciicircum=469;e.underscore=556;e.quoteleft=222;e.a=556;e.b=556;e.c=500;e.d=556;e.e=556;e.f=278;e.g=556;e.h=556;e.i=222;e.j=222;e.k=500;e.l=222;e.m=833;e.n=556;e.o=556;e.p=556;e.q=556;e.r=333;e.s=500;e.t=278;e.u=556;e.v=500;e.w=722;e.x=500;e.y=500;e.z=500;e.braceleft=334;e.bar=260;e.braceright=334;e.asciitilde=584;e.exclamdown=333;e.cent=556;e.sterling=556;e.fraction=167;e.yen=556;e.florin=556;e.section=556;e.currency=556;e.quotesingle=191;e.quotedblleft=333;e.guillemotleft=556;e.guilsinglleft=333;e.guilsinglright=333;e.fi=500;e.fl=500;e.endash=556;e.dagger=556;e.daggerdbl=556;e.periodcentered=278;e.paragraph=537;e.bullet=350;e.quotesinglbase=222;e.quotedblbase=333;e.quotedblright=333;e.guillemotright=556;e.ellipsis=1e3;e.perthousand=1e3;e.questiondown=611;e.grave=333;e.acute=333;e.circumflex=333;e.tilde=333;e.macron=333;e.breve=333;e.dotaccent=333;e.dieresis=333;e.ring=333;e.cedilla=333;e.hungarumlaut=333;e.ogonek=333;e.caron=333;e.emdash=1e3;e.AE=1e3;e.ordfeminine=370;e.Lslash=556;e.Oslash=778;e.OE=1e3;e.ordmasculine=365;e.ae=889;e.dotlessi=278;e.lslash=222;e.oslash=611;e.oe=944;e.germandbls=611;e.Idieresis=278;e.eacute=556;e.abreve=556;e.uhungarumlaut=556;e.ecaron=556;e.Ydieresis=667;e.divide=584;e.Yacute=667;e.Acircumflex=667;e.aacute=556;e.Ucircumflex=722;e.yacute=500;e.scommaaccent=500;e.ecircumflex=556;e.Uring=722;e.Udieresis=722;e.aogonek=556;e.Uacute=722;e.uogonek=556;e.Edieresis=667;e.Dcroat=722;e.commaaccent=250;e.copyright=737;e.Emacron=667;e.ccaron=500;e.aring=556;e.Ncommaaccent=722;e.lacute=222;e.agrave=556;e.Tcommaaccent=611;e.Cacute=722;e.atilde=556;e.Edotaccent=667;e.scaron=500;e.scedilla=500;e.iacute=278;e.lozenge=471;e.Rcaron=722;e.Gcommaaccent=778;e.ucircumflex=556;e.acircumflex=556;e.Amacron=667;e.rcaron=333;e.ccedilla=500;e.Zdotaccent=611;e.Thorn=667;e.Omacron=778;e.Racute=722;e.Sacute=667;e.dcaron=643;e.Umacron=722;e.uring=556;e.threesuperior=333;e.Ograve=778;e.Agrave=667;e.Abreve=667;e.multiply=584;e.uacute=556;e.Tcaron=611;e.partialdiff=476;e.ydieresis=500;e.Nacute=722;e.icircumflex=278;e.Ecircumflex=667;e.adieresis=556;e.edieresis=556;e.cacute=500;e.nacute=556;e.umacron=556;e.Ncaron=722;e.Iacute=278;e.plusminus=584;e.brokenbar=260;e.registered=737;e.Gbreve=778;e.Idotaccent=278;e.summation=600;e.Egrave=667;e.racute=333;e.omacron=556;e.Zacute=611;e.Zcaron=611;e.greaterequal=549;e.Eth=722;e.Ccedilla=722;e.lcommaaccent=222;e.tcaron=317;e.eogonek=556;e.Uogonek=722;e.Aacute=667;e.Adieresis=667;e.egrave=556;e.zacute=500;e.iogonek=222;e.Oacute=778;e.oacute=556;e.amacron=556;e.sacute=500;e.idieresis=278;e.Ocircumflex=778;e.Ugrave=722;e.Delta=612;e.thorn=556;e.twosuperior=333;e.Odieresis=778;e.mu=556;e.igrave=278;e.ohungarumlaut=556;e.Eogonek=667;e.dcroat=556;e.threequarters=834;e.Scedilla=667;e.lcaron=299;e.Kcommaaccent=667;e.Lacute=556;e.trademark=1e3;e.edotaccent=556;e.Igrave=278;e.Imacron=278;e.Lcaron=556;e.onehalf=834;e.lessequal=549;e.ocircumflex=556;e.ntilde=556;e.Uhungarumlaut=722;e.Eacute=667;e.emacron=556;e.gbreve=556;e.onequarter=834;e.Scaron=667;e.Scommaaccent=667;e.Ohungarumlaut=778;e.degree=400;e.ograve=556;e.Ccaron=722;e.ugrave=556;e.radical=453;e.Dcaron=722;e.rcommaaccent=333;e.Ntilde=722;e.otilde=556;e.Rcommaaccent=722;e.Lcommaaccent=556;e.Atilde=667;e.Aogonek=667;e.Aring=667;e.Otilde=778;e.zdotaccent=500;e.Ecaron=667;e.Iogonek=278;e.kcommaaccent=500;e.minus=584;e.Icircumflex=278;e.ncaron=556;e.tcommaaccent=278;e.logicalnot=584;e.odieresis=556;e.udieresis=556;e.notequal=549;e.gcommaaccent=556;e.eth=556;e.zcaron=500;e.ncommaaccent=556;e.onesuperior=333;e.imacron=278;e.Euro=556});e.Symbol=(0,a.getLookupTableFactory)(function(e){e.space=250;e.exclam=333;e.universal=713;e.numbersign=500;e.existential=549;e.percent=833;e.ampersand=778;e.suchthat=439;e.parenleft=333;e.parenright=333;e.asteriskmath=500;e.plus=549;e.comma=250;e.minus=549;e.period=250;e.slash=278;e.zero=500;e.one=500;e.two=500;e.three=500;e.four=500;e.five=500;e.six=500;e.seven=500;e.eight=500;e.nine=500;e.colon=278;e.semicolon=278;e.less=549;e.equal=549;e.greater=549;e.question=444;e.congruent=549;e.Alpha=722;e.Beta=667;e.Chi=722;e.Delta=612;e.Epsilon=611;e.Phi=763;e.Gamma=603;e.Eta=722;e.Iota=333;e.theta1=631;e.Kappa=722;e.Lambda=686;e.Mu=889;e.Nu=722;e.Omicron=722;e.Pi=768;e.Theta=741;e.Rho=556;e.Sigma=592;e.Tau=611;e.Upsilon=690;e.sigma1=439;e.Omega=768;e.Xi=645;e.Psi=795;e.Zeta=611;e.bracketleft=333;e.therefore=863;e.bracketright=333;e.perpendicular=658;e.underscore=500;e.radicalex=500;e.alpha=631;e.beta=549;e.chi=549;e.delta=494;e.epsilon=439;e.phi=521;e.gamma=411;e.eta=603;e.iota=329;e.phi1=603;e.kappa=549;e.lambda=549;e.mu=576;e.nu=521;e.omicron=549;e.pi=549;e.theta=521;e.rho=549;e.sigma=603;e.tau=439;e.upsilon=576;e.omega1=713;e.omega=686;e.xi=493;e.psi=686;e.zeta=494;e.braceleft=480;e.bar=200;e.braceright=480;e.similar=549;e.Euro=750;e.Upsilon1=620;e.minute=247;e.lessequal=549;e.fraction=167;e.infinity=713;e.florin=500;e.club=753;e.diamond=753;e.heart=753;e.spade=753;e.arrowboth=1042;e.arrowleft=987;e.arrowup=603;e.arrowright=987;e.arrowdown=603;e.degree=400;e.plusminus=549;e.second=411;e.greaterequal=549;e.multiply=549;e.proportional=713;e.partialdiff=494;e.bullet=460;e.divide=549;e.notequal=549;e.equivalence=549;e.approxequal=549;e.ellipsis=1e3;e.arrowvertex=603;e.arrowhorizex=1e3;e.carriagereturn=658;e.aleph=823;e.Ifraktur=686;e.Rfraktur=795;e.weierstrass=987;e.circlemultiply=768;e.circleplus=768;e.emptyset=823;e.intersection=768;e.union=768;e.propersuperset=713;e.reflexsuperset=713;e.notsubset=713;e.propersubset=713;e.reflexsubset=713;e.element=713;e.notelement=713;e.angle=768;e.gradient=713;e.registerserif=790;e.copyrightserif=790;e.trademarkserif=890;e.product=823;e.radical=549;e.dotmath=250;e.logicalnot=713;e.logicaland=603;e.logicalor=603;e.arrowdblboth=1042;e.arrowdblleft=987;e.arrowdblup=603;e.arrowdblright=987;e.arrowdbldown=603;e.lozenge=494;e.angleleft=329;e.registersans=790;e.copyrightsans=790;e.trademarksans=786;e.summation=713;e.parenlefttp=384;e.parenleftex=384;e.parenleftbt=384;e.bracketlefttp=384;e.bracketleftex=384;e.bracketleftbt=384;e.bracelefttp=494;e.braceleftmid=494;e.braceleftbt=494;e.braceex=494;e.angleright=329;e.integral=274;e.integraltp=686;e.integralex=686;e.integralbt=686;e.parenrighttp=384;e.parenrightex=384;e.parenrightbt=384;e.bracketrighttp=384;e.bracketrightex=384;e.bracketrightbt=384;e.bracerighttp=494;e.bracerightmid=494;e.bracerightbt=494;e.apple=790});e["Times-Roman"]=(0,a.getLookupTableFactory)(function(e){e.space=250;e.exclam=333;e.quotedbl=408;e.numbersign=500;e.dollar=500;e.percent=833;e.ampersand=778;e.quoteright=333;e.parenleft=333;e.parenright=333;e.asterisk=500;e.plus=564;e.comma=250;e.hyphen=333;e.period=250;e.slash=278;e.zero=500;e.one=500;e.two=500;e.three=500;e.four=500;e.five=500;e.six=500;e.seven=500;e.eight=500;e.nine=500;e.colon=278;e.semicolon=278;e.less=564;e.equal=564;e.greater=564;e.question=444;e.at=921;e.A=722;e.B=667;e.C=667;e.D=722;e.E=611;e.F=556;e.G=722;e.H=722;e.I=333;e.J=389;e.K=722;e.L=611;e.M=889;e.N=722;e.O=722;e.P=556;e.Q=722;e.R=667;e.S=556;e.T=611;e.U=722;e.V=722;e.W=944;e.X=722;e.Y=722;e.Z=611;e.bracketleft=333;e.backslash=278;e.bracketright=333;e.asciicircum=469;e.underscore=500;e.quoteleft=333;e.a=444;e.b=500;e.c=444;e.d=500;e.e=444;e.f=333;e.g=500;e.h=500;e.i=278;e.j=278;e.k=500;e.l=278;e.m=778;e.n=500;e.o=500;e.p=500;e.q=500;e.r=333;e.s=389;e.t=278;e.u=500;e.v=500;e.w=722;e.x=500;e.y=500;e.z=444;e.braceleft=480;e.bar=200;e.braceright=480;e.asciitilde=541;e.exclamdown=333;e.cent=500;e.sterling=500;e.fraction=167;e.yen=500;e.florin=500;e.section=500;e.currency=500;e.quotesingle=180;e.quotedblleft=444;e.guillemotleft=500;e.guilsinglleft=333;e.guilsinglright=333;e.fi=556;e.fl=556;e.endash=500;e.dagger=500;e.daggerdbl=500;e.periodcentered=250;e.paragraph=453;e.bullet=350;e.quotesinglbase=333;e.quotedblbase=444;e.quotedblright=444;e.guillemotright=500;e.ellipsis=1e3;e.perthousand=1e3;e.questiondown=444;e.grave=333;e.acute=333;e.circumflex=333;e.tilde=333;e.macron=333;e.breve=333;e.dotaccent=333;e.dieresis=333;e.ring=333;e.cedilla=333;e.hungarumlaut=333;e.ogonek=333;e.caron=333;e.emdash=1e3;e.AE=889;e.ordfeminine=276;e.Lslash=611;e.Oslash=722;e.OE=889;e.ordmasculine=310;e.ae=667;e.dotlessi=278;e.lslash=278;e.oslash=500;e.oe=722;e.germandbls=500;e.Idieresis=333;e.eacute=444;e.abreve=444;e.uhungarumlaut=500;e.ecaron=444;e.Ydieresis=722;e.divide=564;e.Yacute=722;e.Acircumflex=722;e.aacute=444;e.Ucircumflex=722;e.yacute=500;e.scommaaccent=389;e.ecircumflex=444;e.Uring=722;e.Udieresis=722;e.aogonek=444;e.Uacute=722;e.uogonek=500;e.Edieresis=611;e.Dcroat=722;e.commaaccent=250;e.copyright=760;e.Emacron=611;e.ccaron=444;e.aring=444;e.Ncommaaccent=722;e.lacute=278;e.agrave=444;e.Tcommaaccent=611;e.Cacute=667;e.atilde=444;e.Edotaccent=611;e.scaron=389;e.scedilla=389;e.iacute=278;e.lozenge=471;e.Rcaron=667;e.Gcommaaccent=722;e.ucircumflex=500;e.acircumflex=444;e.Amacron=722;e.rcaron=333;e.ccedilla=444;e.Zdotaccent=611;e.Thorn=556;e.Omacron=722;e.Racute=667;e.Sacute=556;e.dcaron=588;e.Umacron=722;e.uring=500;e.threesuperior=300;e.Ograve=722;e.Agrave=722;e.Abreve=722;e.multiply=564;e.uacute=500;e.Tcaron=611;e.partialdiff=476;e.ydieresis=500;e.Nacute=722;e.icircumflex=278;e.Ecircumflex=611;e.adieresis=444;e.edieresis=444;e.cacute=444;e.nacute=500;e.umacron=500;e.Ncaron=722;e.Iacute=333;e.plusminus=564;e.brokenbar=200;e.registered=760;e.Gbreve=722;e.Idotaccent=333;e.summation=600;e.Egrave=611;e.racute=333;e.omacron=500;e.Zacute=611;e.Zcaron=611;e.greaterequal=549;e.Eth=722;e.Ccedilla=667;e.lcommaaccent=278;e.tcaron=326;e.eogonek=444;e.Uogonek=722;e.Aacute=722;e.Adieresis=722;e.egrave=444;e.zacute=444;e.iogonek=278;e.Oacute=722;e.oacute=500;e.amacron=444;e.sacute=389;e.idieresis=278;e.Ocircumflex=722;e.Ugrave=722;e.Delta=612;e.thorn=500;e.twosuperior=300;e.Odieresis=722;e.mu=500;e.igrave=278;e.ohungarumlaut=500;e.Eogonek=611;e.dcroat=500;e.threequarters=750;e.Scedilla=556;e.lcaron=344;e.Kcommaaccent=722;e.Lacute=611;e.trademark=980;e.edotaccent=444;e.Igrave=333;e.Imacron=333;e.Lcaron=611;e.onehalf=750;e.lessequal=549;e.ocircumflex=500;e.ntilde=500;e.Uhungarumlaut=722;e.Eacute=611;e.emacron=444;e.gbreve=500;e.onequarter=750;e.Scaron=556;e.Scommaaccent=556;e.Ohungarumlaut=722;e.degree=400;e.ograve=500;e.Ccaron=667;e.ugrave=500;e.radical=453;e.Dcaron=722;e.rcommaaccent=333;e.Ntilde=722;e.otilde=500;e.Rcommaaccent=667;e.Lcommaaccent=611;e.Atilde=722;e.Aogonek=722;e.Aring=722;e.Otilde=722;e.zdotaccent=444;e.Ecaron=611;e.Iogonek=333;e.kcommaaccent=500;e.minus=564;e.Icircumflex=333;e.ncaron=500;e.tcommaaccent=278;e.logicalnot=564;e.odieresis=500;e.udieresis=500;e.notequal=549;e.gcommaaccent=500;e.eth=500;e.zcaron=444;e.ncommaaccent=500;e.onesuperior=300;e.imacron=278;e.Euro=500});e["Times-Bold"]=(0,a.getLookupTableFactory)(function(e){e.space=250;e.exclam=333;e.quotedbl=555;e.numbersign=500;e.dollar=500;e.percent=1e3;e.ampersand=833;e.quoteright=333;e.parenleft=333;e.parenright=333;e.asterisk=500;e.plus=570;e.comma=250;e.hyphen=333;e.period=250;e.slash=278;e.zero=500;e.one=500;e.two=500;e.three=500;e.four=500;e.five=500;e.six=500;e.seven=500;e.eight=500;e.nine=500;e.colon=333;e.semicolon=333;e.less=570;e.equal=570;e.greater=570;e.question=500;e.at=930;e.A=722;e.B=667;e.C=722;e.D=722;e.E=667;e.F=611;e.G=778;e.H=778;e.I=389;e.J=500;e.K=778;e.L=667;e.M=944;e.N=722;e.O=778;e.P=611;e.Q=778;e.R=722;e.S=556;e.T=667;e.U=722;e.V=722;e.W=1e3;e.X=722;e.Y=722;e.Z=667;e.bracketleft=333;e.backslash=278;e.bracketright=333;e.asciicircum=581;e.underscore=500;e.quoteleft=333;e.a=500;e.b=556;e.c=444;e.d=556;e.e=444;e.f=333;e.g=500;e.h=556;e.i=278;e.j=333;e.k=556;e.l=278;e.m=833;e.n=556;e.o=500;e.p=556;e.q=556;e.r=444;e.s=389;e.t=333;e.u=556;e.v=500;e.w=722;e.x=500;e.y=500;e.z=444;e.braceleft=394;e.bar=220;e.braceright=394;e.asciitilde=520;e.exclamdown=333;e.cent=500;e.sterling=500;e.fraction=167;e.yen=500;e.florin=500;e.section=500;e.currency=500;e.quotesingle=278;e.quotedblleft=500;e.guillemotleft=500;e.guilsinglleft=333;e.guilsinglright=333;e.fi=556;e.fl=556;e.endash=500;e.dagger=500;e.daggerdbl=500;e.periodcentered=250;e.paragraph=540;e.bullet=350;e.quotesinglbase=333;e.quotedblbase=500;e.quotedblright=500;e.guillemotright=500;e.ellipsis=1e3;e.perthousand=1e3;e.questiondown=500;e.grave=333;e.acute=333;e.circumflex=333;e.tilde=333;e.macron=333;e.breve=333;e.dotaccent=333;e.dieresis=333;e.ring=333;e.cedilla=333;e.hungarumlaut=333;e.ogonek=333;e.caron=333;e.emdash=1e3;e.AE=1e3;e.ordfeminine=300;e.Lslash=667;e.Oslash=778;e.OE=1e3;e.ordmasculine=330;e.ae=722;e.dotlessi=278;e.lslash=278;e.oslash=500;e.oe=722;e.germandbls=556;e.Idieresis=389;e.eacute=444;e.abreve=500;e.uhungarumlaut=556;e.ecaron=444;e.Ydieresis=722;e.divide=570;e.Yacute=722;e.Acircumflex=722;e.aacute=500;e.Ucircumflex=722;e.yacute=500;e.scommaaccent=389;e.ecircumflex=444;e.Uring=722;e.Udieresis=722;e.aogonek=500;e.Uacute=722;e.uogonek=556;e.Edieresis=667;e.Dcroat=722;e.commaaccent=250;e.copyright=747;e.Emacron=667;e.ccaron=444;e.aring=500;e.Ncommaaccent=722;e.lacute=278;e.agrave=500;e.Tcommaaccent=667;e.Cacute=722;e.atilde=500;e.Edotaccent=667;e.scaron=389;e.scedilla=389;e.iacute=278;e.lozenge=494;e.Rcaron=722;e.Gcommaaccent=778;e.ucircumflex=556;e.acircumflex=500;e.Amacron=722;e.rcaron=444;e.ccedilla=444;e.Zdotaccent=667;e.Thorn=611;e.Omacron=778;e.Racute=722;e.Sacute=556;e.dcaron=672;e.Umacron=722;e.uring=556;e.threesuperior=300;e.Ograve=778;e.Agrave=722;e.Abreve=722;e.multiply=570;e.uacute=556;e.Tcaron=667;e.partialdiff=494;e.ydieresis=500;e.Nacute=722;e.icircumflex=278;e.Ecircumflex=667;e.adieresis=500;e.edieresis=444;e.cacute=444;e.nacute=556;e.umacron=556;e.Ncaron=722;e.Iacute=389;e.plusminus=570;e.brokenbar=220;e.registered=747;e.Gbreve=778;e.Idotaccent=389;e.summation=600;e.Egrave=667;e.racute=444;e.omacron=500;e.Zacute=667;e.Zcaron=667;e.greaterequal=549;e.Eth=722;e.Ccedilla=722;e.lcommaaccent=278;e.tcaron=416;e.eogonek=444;e.Uogonek=722;e.Aacute=722;e.Adieresis=722;e.egrave=444;e.zacute=444;e.iogonek=278;e.Oacute=778;e.oacute=500;e.amacron=500;e.sacute=389;e.idieresis=278;e.Ocircumflex=778;e.Ugrave=722;e.Delta=612;e.thorn=556;e.twosuperior=300;e.Odieresis=778;e.mu=556;e.igrave=278;e.ohungarumlaut=500;e.Eogonek=667;e.dcroat=556;e.threequarters=750;e.Scedilla=556;e.lcaron=394;e.Kcommaaccent=778;e.Lacute=667;e.trademark=1e3;e.edotaccent=444;e.Igrave=389;e.Imacron=389;e.Lcaron=667;e.onehalf=750;e.lessequal=549;e.ocircumflex=500;e.ntilde=556;e.Uhungarumlaut=722;e.Eacute=667;e.emacron=444;e.gbreve=500;e.onequarter=750;e.Scaron=556;e.Scommaaccent=556;e.Ohungarumlaut=778;e.degree=400;e.ograve=500;e.Ccaron=722;e.ugrave=556;e.radical=549;e.Dcaron=722;e.rcommaaccent=444;e.Ntilde=722;e.otilde=500;e.Rcommaaccent=722;e.Lcommaaccent=667;e.Atilde=722;e.Aogonek=722;e.Aring=722;e.Otilde=778;e.zdotaccent=444;e.Ecaron=667;e.Iogonek=389;e.kcommaaccent=556;e.minus=570;e.Icircumflex=389;e.ncaron=556;e.tcommaaccent=333;e.logicalnot=570;e.odieresis=500;e.udieresis=556;e.notequal=549;e.gcommaaccent=500;e.eth=500;e.zcaron=444;e.ncommaaccent=556;e.onesuperior=300;e.imacron=278;e.Euro=500});e["Times-BoldItalic"]=(0,a.getLookupTableFactory)(function(e){e.space=250;e.exclam=389;e.quotedbl=555;e.numbersign=500;e.dollar=500;e.percent=833;e.ampersand=778;e.quoteright=333;e.parenleft=333;e.parenright=333;e.asterisk=500;e.plus=570;e.comma=250;e.hyphen=333;e.period=250;e.slash=278;e.zero=500;e.one=500;e.two=500;e.three=500;e.four=500;e.five=500;e.six=500;e.seven=500;e.eight=500;e.nine=500;e.colon=333;e.semicolon=333;e.less=570;e.equal=570;e.greater=570;e.question=500;e.at=832;e.A=667;e.B=667;e.C=667;e.D=722;e.E=667;e.F=667;e.G=722;e.H=778;e.I=389;e.J=500;e.K=667;e.L=611;e.M=889;e.N=722;e.O=722;e.P=611;e.Q=722;e.R=667;e.S=556;e.T=611;e.U=722;e.V=667;e.W=889;e.X=667;e.Y=611;e.Z=611;e.bracketleft=333;e.backslash=278;e.bracketright=333;e.asciicircum=570;e.underscore=500;e.quoteleft=333;e.a=500;e.b=500;e.c=444;e.d=500;e.e=444;e.f=333;e.g=500;e.h=556;e.i=278;e.j=278;e.k=500;e.l=278;e.m=778;e.n=556;e.o=500;e.p=500;e.q=500;e.r=389;e.s=389;e.t=278;e.u=556;e.v=444;e.w=667;e.x=500;e.y=444;e.z=389;e.braceleft=348;e.bar=220;e.braceright=348;e.asciitilde=570;e.exclamdown=389;e.cent=500;e.sterling=500;e.fraction=167;e.yen=500;e.florin=500;e.section=500;e.currency=500;e.quotesingle=278;e.quotedblleft=500;e.guillemotleft=500;e.guilsinglleft=333;e.guilsinglright=333;e.fi=556;e.fl=556;e.endash=500;e.dagger=500;e.daggerdbl=500;e.periodcentered=250;e.paragraph=500;e.bullet=350;e.quotesinglbase=333;e.quotedblbase=500;e.quotedblright=500;e.guillemotright=500;e.ellipsis=1e3;e.perthousand=1e3;e.questiondown=500;e.grave=333;e.acute=333;e.circumflex=333;e.tilde=333;e.macron=333;e.breve=333;e.dotaccent=333;e.dieresis=333;e.ring=333;e.cedilla=333;e.hungarumlaut=333;e.ogonek=333;e.caron=333;e.emdash=1e3;e.AE=944;e.ordfeminine=266;e.Lslash=611;e.Oslash=722;e.OE=944;e.ordmasculine=300;e.ae=722;e.dotlessi=278;e.lslash=278;e.oslash=500;e.oe=722;e.germandbls=500;e.Idieresis=389;e.eacute=444;e.abreve=500;e.uhungarumlaut=556;e.ecaron=444;e.Ydieresis=611;e.divide=570;e.Yacute=611;e.Acircumflex=667;e.aacute=500;e.Ucircumflex=722;e.yacute=444;e.scommaaccent=389;e.ecircumflex=444;e.Uring=722;e.Udieresis=722;e.aogonek=500;e.Uacute=722;e.uogonek=556;e.Edieresis=667;e.Dcroat=722;e.commaaccent=250;e.copyright=747;e.Emacron=667;e.ccaron=444;e.aring=500;e.Ncommaaccent=722;e.lacute=278;e.agrave=500;e.Tcommaaccent=611;e.Cacute=667;e.atilde=500;e.Edotaccent=667;e.scaron=389;e.scedilla=389;e.iacute=278;e.lozenge=494;e.Rcaron=667;e.Gcommaaccent=722;e.ucircumflex=556;e.acircumflex=500;e.Amacron=667;e.rcaron=389;e.ccedilla=444;e.Zdotaccent=611;e.Thorn=611;e.Omacron=722;e.Racute=667;e.Sacute=556;e.dcaron=608;e.Umacron=722;e.uring=556;e.threesuperior=300;e.Ograve=722;e.Agrave=667;e.Abreve=667;e.multiply=570;e.uacute=556;e.Tcaron=611;e.partialdiff=494;e.ydieresis=444;e.Nacute=722;e.icircumflex=278;e.Ecircumflex=667;e.adieresis=500;e.edieresis=444;e.cacute=444;e.nacute=556;e.umacron=556;e.Ncaron=722;e.Iacute=389;e.plusminus=570;e.brokenbar=220;e.registered=747;e.Gbreve=722;e.Idotaccent=389;e.summation=600;e.Egrave=667;e.racute=389;e.omacron=500;e.Zacute=611;e.Zcaron=611;e.greaterequal=549;e.Eth=722;e.Ccedilla=667;e.lcommaaccent=278;e.tcaron=366;e.eogonek=444;e.Uogonek=722;e.Aacute=667;e.Adieresis=667;e.egrave=444;e.zacute=389;e.iogonek=278;e.Oacute=722;e.oacute=500;e.amacron=500;e.sacute=389;e.idieresis=278;e.Ocircumflex=722;e.Ugrave=722;e.Delta=612;e.thorn=500;e.twosuperior=300;e.Odieresis=722;e.mu=576;e.igrave=278;e.ohungarumlaut=500;e.Eogonek=667;e.dcroat=500;e.threequarters=750;e.Scedilla=556;e.lcaron=382;e.Kcommaaccent=667;e.Lacute=611;e.trademark=1e3;e.edotaccent=444;e.Igrave=389;e.Imacron=389;e.Lcaron=611;e.onehalf=750;e.lessequal=549;e.ocircumflex=500;e.ntilde=556;e.Uhungarumlaut=722;e.Eacute=667;e.emacron=444;e.gbreve=500;e.onequarter=750;e.Scaron=556;e.Scommaaccent=556;e.Ohungarumlaut=722;e.degree=400;e.ograve=500;e.Ccaron=667;e.ugrave=556;e.radical=549;e.Dcaron=722;e.rcommaaccent=389;e.Ntilde=722;e.otilde=500;e.Rcommaaccent=667;e.Lcommaaccent=611;e.Atilde=667;e.Aogonek=667;e.Aring=667;e.Otilde=722;e.zdotaccent=389;e.Ecaron=667;e.Iogonek=389;e.kcommaaccent=500;e.minus=606;e.Icircumflex=389;e.ncaron=556;e.tcommaaccent=278;e.logicalnot=606;e.odieresis=500;e.udieresis=556;e.notequal=549;e.gcommaaccent=500;e.eth=500;e.zcaron=389;e.ncommaaccent=556;e.onesuperior=300;e.imacron=278;e.Euro=500});e["Times-Italic"]=(0,a.getLookupTableFactory)(function(e){e.space=250;e.exclam=333;e.quotedbl=420;e.numbersign=500;e.dollar=500;e.percent=833;e.ampersand=778;e.quoteright=333;e.parenleft=333;e.parenright=333;e.asterisk=500;e.plus=675;e.comma=250;e.hyphen=333;e.period=250;e.slash=278;e.zero=500;e.one=500;e.two=500;e.three=500;e.four=500;e.five=500;e.six=500;e.seven=500;e.eight=500;e.nine=500;e.colon=333;e.semicolon=333;e.less=675;e.equal=675;e.greater=675;e.question=500;e.at=920;e.A=611;e.B=611;e.C=667;e.D=722;e.E=611;e.F=611;e.G=722;e.H=722;e.I=333;e.J=444;e.K=667;e.L=556;e.M=833;e.N=667;e.O=722;e.P=611;e.Q=722;e.R=611;e.S=500;e.T=556;e.U=722;e.V=611;e.W=833;e.X=611;e.Y=556;e.Z=556;e.bracketleft=389;e.backslash=278;e.bracketright=389;e.asciicircum=422;e.underscore=500;e.quoteleft=333;e.a=500;e.b=500;e.c=444;e.d=500;e.e=444;e.f=278;e.g=500;e.h=500;e.i=278;e.j=278;e.k=444;e.l=278;e.m=722;e.n=500;e.o=500;e.p=500;e.q=500;e.r=389;e.s=389;e.t=278;e.u=500;e.v=444;e.w=667;e.x=444;e.y=444;e.z=389;e.braceleft=400;e.bar=275;e.braceright=400;e.asciitilde=541;e.exclamdown=389;e.cent=500;e.sterling=500;e.fraction=167;e.yen=500;e.florin=500;e.section=500;e.currency=500;e.quotesingle=214;e.quotedblleft=556;e.guillemotleft=500;e.guilsinglleft=333;e.guilsinglright=333;e.fi=500;e.fl=500;e.endash=500;e.dagger=500;e.daggerdbl=500;e.periodcentered=250;e.paragraph=523;e.bullet=350;e.quotesinglbase=333;e.quotedblbase=556;e.quotedblright=556;e.guillemotright=500;e.ellipsis=889;e.perthousand=1e3;e.questiondown=500;e.grave=333;e.acute=333;e.circumflex=333;e.tilde=333;e.macron=333;e.breve=333;e.dotaccent=333;e.dieresis=333;e.ring=333;e.cedilla=333;e.hungarumlaut=333;e.ogonek=333;e.caron=333;e.emdash=889;e.AE=889;e.ordfeminine=276;e.Lslash=556;e.Oslash=722;e.OE=944;e.ordmasculine=310;e.ae=667;e.dotlessi=278;e.lslash=278;e.oslash=500;e.oe=667;e.germandbls=500;e.Idieresis=333;e.eacute=444;e.abreve=500;e.uhungarumlaut=500;e.ecaron=444;e.Ydieresis=556;e.divide=675;e.Yacute=556;e.Acircumflex=611;e.aacute=500;e.Ucircumflex=722;e.yacute=444;e.scommaaccent=389;e.ecircumflex=444;e.Uring=722;e.Udieresis=722;e.aogonek=500;e.Uacute=722;e.uogonek=500;e.Edieresis=611;e.Dcroat=722;e.commaaccent=250;e.copyright=760;e.Emacron=611;e.ccaron=444;e.aring=500;e.Ncommaaccent=667;e.lacute=278;e.agrave=500;e.Tcommaaccent=556;e.Cacute=667;e.atilde=500;e.Edotaccent=611;e.scaron=389;e.scedilla=389;e.iacute=278;e.lozenge=471;e.Rcaron=611;e.Gcommaaccent=722;e.ucircumflex=500;e.acircumflex=500;e.Amacron=611;e.rcaron=389;e.ccedilla=444;e.Zdotaccent=556;e.Thorn=611;e.Omacron=722;e.Racute=611;e.Sacute=500;e.dcaron=544;e.Umacron=722;e.uring=500;e.threesuperior=300;e.Ograve=722;e.Agrave=611;e.Abreve=611;e.multiply=675;e.uacute=500;e.Tcaron=556;e.partialdiff=476;e.ydieresis=444;e.Nacute=667;e.icircumflex=278;e.Ecircumflex=611;e.adieresis=500;e.edieresis=444;e.cacute=444;e.nacute=500;e.umacron=500;e.Ncaron=667;e.Iacute=333;e.plusminus=675;e.brokenbar=275;e.registered=760;e.Gbreve=722;e.Idotaccent=333;e.summation=600;e.Egrave=611;e.racute=389;e.omacron=500;e.Zacute=556;e.Zcaron=556;e.greaterequal=549;e.Eth=722;e.Ccedilla=667;e.lcommaaccent=278;e.tcaron=300;e.eogonek=444;e.Uogonek=722;e.Aacute=611;e.Adieresis=611;e.egrave=444;e.zacute=389;e.iogonek=278;e.Oacute=722;e.oacute=500;e.amacron=500;e.sacute=389;e.idieresis=278;e.Ocircumflex=722;e.Ugrave=722;e.Delta=612;e.thorn=500;e.twosuperior=300;e.Odieresis=722;e.mu=500;e.igrave=278;e.ohungarumlaut=500;e.Eogonek=611;e.dcroat=500;e.threequarters=750;e.Scedilla=500;e.lcaron=300;e.Kcommaaccent=667;e.Lacute=556;e.trademark=980;e.edotaccent=444;e.Igrave=333;e.Imacron=333;e.Lcaron=611;e.onehalf=750;e.lessequal=549;e.ocircumflex=500;e.ntilde=500;e.Uhungarumlaut=722;e.Eacute=611;e.emacron=444;e.gbreve=500;e.onequarter=750;e.Scaron=500;e.Scommaaccent=500;e.Ohungarumlaut=722;e.degree=400;e.ograve=500;e.Ccaron=667;e.ugrave=500;e.radical=453;e.Dcaron=722;e.rcommaaccent=389;e.Ntilde=667;e.otilde=500;e.Rcommaaccent=611;e.Lcommaaccent=556;e.Atilde=611;e.Aogonek=611;e.Aring=611;e.Otilde=722;e.zdotaccent=389;e.Ecaron=611;e.Iogonek=333;e.kcommaaccent=444;e.minus=675;e.Icircumflex=333;e.ncaron=500;e.tcommaaccent=278;e.logicalnot=675;e.odieresis=500;e.udieresis=500;e.notequal=549;e.gcommaaccent=500;e.eth=500;e.zcaron=389;e.ncommaaccent=500;e.onesuperior=300;e.imacron=278;e.Euro=500});e.ZapfDingbats=(0,a.getLookupTableFactory)(function(e){e.space=278;e.a1=974;e.a2=961;e.a202=974;e.a3=980;e.a4=719;e.a5=789;e.a119=790;e.a118=791;e.a117=690;e.a11=960;e.a12=939;e.a13=549;e.a14=855;e.a15=911;e.a16=933;e.a105=911;e.a17=945;e.a18=974;e.a19=755;e.a20=846;e.a21=762;e.a22=761;e.a23=571;e.a24=677;e.a25=763;e.a26=760;e.a27=759;e.a28=754;e.a6=494;e.a7=552;e.a8=537;e.a9=577;e.a10=692;e.a29=786;e.a30=788;e.a31=788;e.a32=790;e.a33=793;e.a34=794;e.a35=816;e.a36=823;e.a37=789;e.a38=841;e.a39=823;e.a40=833;e.a41=816;e.a42=831;e.a43=923;e.a44=744;e.a45=723;e.a46=749;e.a47=790;e.a48=792;e.a49=695;e.a50=776;e.a51=768;e.a52=792;e.a53=759;e.a54=707;e.a55=708;e.a56=682;e.a57=701;e.a58=826;e.a59=815;e.a60=789;e.a61=789;e.a62=707;e.a63=687;e.a64=696;e.a65=689;e.a66=786;e.a67=787;e.a68=713;e.a69=791;e.a70=785;e.a71=791;e.a72=873;e.a73=761;e.a74=762;e.a203=762;e.a75=759;e.a204=759;e.a76=892;e.a77=892;e.a78=788;e.a79=784;e.a81=438;e.a82=138;e.a83=277;e.a84=415;e.a97=392;e.a98=392;e.a99=668;e.a100=668;e.a89=390;e.a90=390;e.a93=317;e.a94=317;e.a91=276;e.a92=276;e.a205=509;e.a85=509;e.a206=410;e.a86=410;e.a87=234;e.a88=234;e.a95=334;e.a96=334;e.a101=732;e.a102=544;e.a103=544;e.a104=910;e.a106=667;e.a107=760;e.a108=760;e.a112=776;e.a111=595;e.a110=694;e.a109=626;e.a120=788;e.a121=788;e.a122=788;e.a123=788;e.a124=788;e.a125=788;e.a126=788;e.a127=788;e.a128=788;e.a129=788;e.a130=788;e.a131=788;e.a132=788;e.a133=788;e.a134=788;e.a135=788;e.a136=788;e.a137=788;e.a138=788;e.a139=788;e.a140=788;e.a141=788;e.a142=788;e.a143=788;e.a144=788;e.a145=788;e.a146=788;e.a147=788;e.a148=788;e.a149=788;e.a150=788;e.a151=788;e.a152=788;e.a153=788;e.a154=788;e.a155=788;e.a156=788;e.a157=788;e.a158=788;e.a159=788;e.a160=894;e.a161=838;e.a163=1016;e.a164=458;e.a196=748;e.a165=924;e.a192=748;e.a166=918;e.a167=927;e.a168=928;e.a169=928;e.a170=834;e.a171=873;e.a172=828;e.a173=924;e.a162=924;e.a174=917;e.a175=930;e.a176=931;e.a177=463;e.a178=883;e.a179=836;e.a193=836;e.a180=867;e.a199=867;e.a181=696;e.a200=696;e.a182=874;e.a201=874;e.a183=760;e.a184=946;e.a197=771;e.a185=865;e.a194=771;e.a198=888;e.a186=967;e.a195=888;e.a187=831;e.a188=873;e.a189=927;e.a190=970;e.a191=918})});t.getMetrics=i},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.PostScriptCompiler=t.PostScriptEvaluator=t.PDFFunctionFactory=t.isPDFFunction=void 0;var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i=function(){function e(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1;a.configurable=!0;"value"in a&&(a.writable=!0);Object.defineProperty(e,a.key,a)}}return function(t,r,a){r&&e(t.prototype,r);a&&e(t,a);return t}}(),n=r(2),o=r(138),s=r(169);var c={get value(){return(0,n.shadow)(this,"value",(0,n.isEvalSupported)())}},l=function(){function e(t){var r=t.xref,a=t.isEvalSupported,i=void 0===a||a;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e);this.xref=r;this.isEvalSupported=!1!==i}i(e,[{key:"create",value:function(e){return h.parse({xref:this.xref,isEvalSupported:this.isEvalSupported,fn:e})}},{key:"createFromArray",value:function(e){return h.parseArray({xref:this.xref,isEvalSupported:this.isEvalSupported,fnObj:e})}}]);return e}();function u(e){if(!Array.isArray(e))return null;for(var t=e.length,r=0;r<t;r++)if("number"!=typeof e[r]){for(var a=new Array(t),i=0;i<t;i++)a[i]=+e[i];return a}return e}var h={getSampleArray:function(e,t,r,a){var i,n,o=1;for(i=0,n=e.length;i<n;i++)o*=e[i];o*=t;var s=new Array(o),c=0,l=0,u=1/(Math.pow(2,r)-1),h=a.getBytes((o*r+7)/8),f=0;for(i=0;i<o;i++){for(;c<r;){l<<=8;l|=h[f++];c+=8}c-=r;s[i]=(l>>c)*u;l&=(1<<c)-1}return s},getIR:function(e){var t=e.xref,r=e.isEvalSupported,a=e.fn,i=a.dict;i||(i=a);var o=[this.constructSampled,null,this.constructInterpolated,this.constructStiched,this.constructPostScript][i.get("FunctionType")];if(!o)throw new n.FormatError("Unknown type of function");return o.call(this,{xref:t,isEvalSupported:r,fn:a,dict:i})},fromIR:function(e){var t=e.xref,r=e.isEvalSupported,a=e.IR;switch(a[0]){case 0:return this.constructSampledFromIR({xref:t,isEvalSupported:r,IR:a});case 2:return this.constructInterpolatedFromIR({xref:t,isEvalSupported:r,IR:a});case 3:return this.constructStichedFromIR({xref:t,isEvalSupported:r,IR:a});default:return this.constructPostScriptFromIR({xref:t,isEvalSupported:r,IR:a})}},parse:function(e){var t=e.xref,r=e.isEvalSupported,a=e.fn,i=this.getIR({xref:t,isEvalSupported:r,fn:a});return this.fromIR({xref:t,isEvalSupported:r,IR:i})},parseArray:function(e){var t=e.xref,r=e.isEvalSupported,a=e.fnObj;if(!Array.isArray(a))return this.parse({xref:t,isEvalSupported:r,fn:a});for(var i=[],n=0,o=a.length;n<o;n++)i.push(this.parse({xref:t,isEvalSupported:r,fn:t.fetchIfRef(a[n])}));return function(e,t,r,a){for(var n=0,o=i.length;n<o;n++)i[n](e,t,r,a+n)}},constructSampled:function(e){e.xref,e.isEvalSupported;var t=e.fn,r=e.dict;function a(e){for(var t=e.length,r=[],a=0,i=0;i<t;i+=2){r[a]=[e[i],e[i+1]];++a}return r}var i=u(r.getArray("Domain")),o=u(r.getArray("Range"));if(!i||!o)throw new n.FormatError("No domain or range");var s=i.length/2,c=o.length/2;i=a(i);o=a(o);var l=u(r.getArray("Size")),h=r.get("BitsPerSample"),f=r.get("Order")||1;1!==f&&(0,n.info)("No support for cubic spline interpolation: "+f);var d=u(r.getArray("Encode"));if(d)d=a(d);else{d=[];for(var g=0;g<s;++g)d.push([0,l[g]-1])}var m=u(r.getArray("Decode"));return[0,s,i,d,m=m?a(m):o,this.getSampleArray(l,c,h,t),l,c,Math.pow(2,h)-1,o]},constructSampledFromIR:function(e){e.xref,e.isEvalSupported;var t=e.IR;function r(e,t,r,a,i){return a+(i-a)/(r-t)*(e-t)}return function(e,a,i,n){var o,s,c=t[1],l=t[2],u=t[3],h=t[4],f=t[5],d=t[6],g=t[7],m=t[9],p=1<<c,v=new Float64Array(p),b=new Uint32Array(p);for(s=0;s<p;s++)v[s]=1;var y=g,w=1;for(o=0;o<c;++o){var k=l[o][0],S=l[o][1],C=r(Math.min(Math.max(e[a+o],k),S),k,S,u[o][0],u[o][1]),x=d[o],_=(C=Math.min(Math.max(C,0),x-1))<x-1?Math.floor(C):C-1,A=_+1-C,P=C-_,I=_*y,O=I+y;for(s=0;s<p;s++)if(s&w){v[s]*=P;b[s]+=O}else{v[s]*=A;b[s]+=I}y*=x;w<<=1}for(s=0;s<g;++s){var T=0;for(o=0;o<p;o++)T+=f[b[o]+s]*v[o];T=r(T,0,1,h[s][0],h[s][1]);i[n+s]=Math.min(Math.max(T,m[s][0]),m[s][1])}}},constructInterpolated:function(e){e.xref,e.isEvalSupported,e.fn;for(var t=e.dict,r=u(t.getArray("C0"))||[0],a=u(t.getArray("C1"))||[1],i=t.get("N"),n=r.length,o=[],s=0;s<n;++s)o.push(a[s]-r[s]);return[2,r,o,i]},constructInterpolatedFromIR:function(e){e.xref,e.isEvalSupported;var t=e.IR,r=t[1],a=t[2],i=t[3],n=a.length;return function(e,t,o,s){for(var c=1===i?e[t]:Math.pow(e[t],i),l=0;l<n;++l)o[s+l]=r[l]+c*a[l]}},constructStiched:function(e){var t=e.xref,r=e.isEvalSupported,a=(e.fn,e.dict),i=u(a.getArray("Domain"));if(!i)throw new n.FormatError("No domain");if(1!=i.length/2)throw new n.FormatError("Bad domain for stiched function");for(var o=a.get("Functions"),s=[],c=0,l=o.length;c<l;++c)s.push(this.parse({xref:t,isEvalSupported:r,fn:t.fetchIfRef(o[c])}));return[3,i,u(a.getArray("Bounds")),u(a.getArray("Encode")),s]},constructStichedFromIR:function(e){e.xref,e.isEvalSupported;var t=e.IR,r=t[1],a=t[2],i=t[3],n=t[4],o=new Float32Array(1);return function(e,t,s,c){for(var l=function(e,t,r){e>r?e=r:e<t&&(e=t);return e}(e[t],r[0],r[1]),u=0,h=a.length;u<h&&!(l<a[u]);++u);var f=r[0];u>0&&(f=a[u-1]);var d=r[1];u<a.length&&(d=a[u]);var g=i[2*u],m=i[2*u+1];o[0]=f===d?g:g+(l-f)*(m-g)/(d-f);n[u](o,0,s,c)}},constructPostScript:function(e){e.xref,e.isEvalSupported;var t=e.fn,r=e.dict,a=u(r.getArray("Domain")),i=u(r.getArray("Range"));if(!a)throw new n.FormatError("No domain.");if(!i)throw new n.FormatError("No range.");var o=new s.PostScriptLexer(t);return[4,a,i,new s.PostScriptParser(o).parse()]},constructPostScriptFromIR:function(e){e.xref;var t=e.isEvalSupported,r=e.IR,a=r[1],i=r[2],o=r[3];if(t&&c.value){var s=(new g).compile(o,a,i);if(s)return new Function("src","srcOffset","dest","destOffset",s)}(0,n.info)("Unable to compile PS function");var l=i.length>>1,u=a.length>>1,h=new d(o),f=Object.create(null),m=8192,p=new Float32Array(u);return function(e,t,r,a){var n,o,s="",c=p;for(n=0;n<u;n++){o=e[t+n];c[n]=o;s+=o+"_"}var d=f[s];if(void 0===d){var g=new Float32Array(l),v=h.execute(c),b=v.length-l;for(n=0;n<l;n++){o=v[b+n];var y=i[2*n];o<y?o=y:o>(y=i[2*n+1])&&(o=y);g[n]=o}if(m>0){m--;f[s]=g}r.set(g,a)}else r.set(d,a)}}};var f=function(){function e(e){this.stack=e?Array.prototype.slice.call(e,0):[]}e.prototype={push:function(e){if(this.stack.length>=100)throw new Error("PostScript function stack overflow.");this.stack.push(e)},pop:function(){if(this.stack.length<=0)throw new Error("PostScript function stack underflow.");return this.stack.pop()},copy:function(e){if(this.stack.length+e>=100)throw new Error("PostScript function stack overflow.");for(var t=this.stack,r=t.length-e,a=e-1;a>=0;a--,r++)t.push(t[r])},index:function(e){this.push(this.stack[this.stack.length-e-1])},roll:function(e,t){var r,a,i,n=this.stack,o=n.length-e,s=n.length-1,c=o+(t-Math.floor(t/e)*e);for(r=o,a=s;r<a;r++,a--){i=n[r];n[r]=n[a];n[a]=i}for(r=o,a=c-1;r<a;r++,a--){i=n[r];n[r]=n[a];n[a]=i}for(r=c,a=s;r<a;r++,a--){i=n[r];n[r]=n[a];n[a]=i}}};return e}(),d=function(){function e(e){this.operators=e}e.prototype={execute:function(e){for(var t,r,a,i=new f(e),o=0,s=this.operators,c=s.length;o<c;)if("number"!=typeof(t=s[o++]))switch(t){case"jz":a=i.pop();(r=i.pop())||(o=a);break;case"j":o=r=i.pop();break;case"abs":r=i.pop();i.push(Math.abs(r));break;case"add":a=i.pop();r=i.pop();i.push(r+a);break;case"and":a=i.pop();r=i.pop();(0,n.isBool)(r)&&(0,n.isBool)(a)?i.push(r&&a):i.push(r&a);break;case"atan":r=i.pop();i.push(Math.atan(r));break;case"bitshift":a=i.pop();(r=i.pop())>0?i.push(r<<a):i.push(r>>a);break;case"ceiling":r=i.pop();i.push(Math.ceil(r));break;case"copy":r=i.pop();i.copy(r);break;case"cos":r=i.pop();i.push(Math.cos(r));break;case"cvi":r=0|i.pop();i.push(r);break;case"cvr":break;case"div":a=i.pop();r=i.pop();i.push(r/a);break;case"dup":i.copy(1);break;case"eq":a=i.pop();r=i.pop();i.push(r===a);break;case"exch":i.roll(2,1);break;case"exp":a=i.pop();r=i.pop();i.push(Math.pow(r,a));break;case"false":i.push(!1);break;case"floor":r=i.pop();i.push(Math.floor(r));break;case"ge":a=i.pop();r=i.pop();i.push(r>=a);break;case"gt":a=i.pop();r=i.pop();i.push(r>a);break;case"idiv":a=i.pop();r=i.pop();i.push(r/a|0);break;case"index":r=i.pop();i.index(r);break;case"le":a=i.pop();r=i.pop();i.push(r<=a);break;case"ln":r=i.pop();i.push(Math.log(r));break;case"log":r=i.pop();i.push(Math.log(r)/Math.LN10);break;case"lt":a=i.pop();r=i.pop();i.push(r<a);break;case"mod":a=i.pop();r=i.pop();i.push(r%a);break;case"mul":a=i.pop();r=i.pop();i.push(r*a);break;case"ne":a=i.pop();r=i.pop();i.push(r!==a);break;case"neg":r=i.pop();i.push(-r);break;case"not":r=i.pop();(0,n.isBool)(r)?i.push(!r):i.push(~r);break;case"or":a=i.pop();r=i.pop();(0,n.isBool)(r)&&(0,n.isBool)(a)?i.push(r||a):i.push(r|a);break;case"pop":i.pop();break;case"roll":a=i.pop();r=i.pop();i.roll(r,a);break;case"round":r=i.pop();i.push(Math.round(r));break;case"sin":r=i.pop();i.push(Math.sin(r));break;case"sqrt":r=i.pop();i.push(Math.sqrt(r));break;case"sub":a=i.pop();r=i.pop();i.push(r-a);break;case"true":i.push(!0);break;case"truncate":r=(r=i.pop())<0?Math.ceil(r):Math.floor(r);i.push(r);break;case"xor":a=i.pop();r=i.pop();(0,n.isBool)(r)&&(0,n.isBool)(a)?i.push(r!==a):i.push(r^a);break;default:throw new n.FormatError("Unknown operator "+t)}else i.push(t);return i.stack}};return e}(),g=function(){function e(e){this.type=e}e.prototype.visit=function(e){(0,n.unreachable)("abstract method")};function t(t,r,a){e.call(this,"args");this.index=t;this.min=r;this.max=a}t.prototype=Object.create(e.prototype);t.prototype.visit=function(e){e.visitArgument(this)};function r(t){e.call(this,"literal");this.number=t;this.min=t;this.max=t}r.prototype=Object.create(e.prototype);r.prototype.visit=function(e){e.visitLiteral(this)};function a(t,r,a,i,n){e.call(this,"binary");this.op=t;this.arg1=r;this.arg2=a;this.min=i;this.max=n}a.prototype=Object.create(e.prototype);a.prototype.visit=function(e){e.visitBinaryOperation(this)};function i(t,r){e.call(this,"max");this.arg=t;this.min=t.min;this.max=r}i.prototype=Object.create(e.prototype);i.prototype.visit=function(e){e.visitMin(this)};function o(t,r,a){e.call(this,"var");this.index=t;this.min=r;this.max=a}o.prototype=Object.create(e.prototype);o.prototype.visit=function(e){e.visitVariable(this)};function s(t,r){e.call(this,"definition");this.variable=t;this.arg=r}s.prototype=Object.create(e.prototype);s.prototype.visit=function(e){e.visitVariableDefinition(this)};function c(){this.parts=[]}c.prototype={visitArgument:function(e){this.parts.push("Math.max(",e.min,", Math.min(",e.max,", src[srcOffset + ",e.index,"]))")},visitVariable:function(e){this.parts.push("v",e.index)},visitLiteral:function(e){this.parts.push(e.number)},visitBinaryOperation:function(e){this.parts.push("(");e.arg1.visit(this);this.parts.push(" ",e.op," ");e.arg2.visit(this);this.parts.push(")")},visitVariableDefinition:function(e){this.parts.push("var ");e.variable.visit(this);this.parts.push(" = ");e.arg.visit(this);this.parts.push(";")},visitMin:function(e){this.parts.push("Math.min(");e.arg.visit(this);this.parts.push(", ",e.max,")")},toString:function(){return this.parts.join("")}};function l(e,t){return"literal"===t.type&&0===t.number?e:"literal"===e.type&&0===e.number?t:"literal"===t.type&&"literal"===e.type?new r(e.number+t.number):new a("+",e,t,e.min+t.min,e.max+t.max)}function u(e,t){if("literal"===t.type){if(0===t.number)return new r(0);if(1===t.number)return e;if("literal"===e.type)return new r(e.number*t.number)}if("literal"===e.type){if(0===e.number)return new r(0);if(1===e.number)return t}return new a("*",e,t,Math.min(e.min*t.min,e.min*t.max,e.max*t.min,e.max*t.max),Math.max(e.min*t.min,e.min*t.max,e.max*t.min,e.max*t.max))}function h(e,t){if("literal"===t.type){if(0===t.number)return e;if("literal"===e.type)return new r(e.number-t.number)}return"binary"===t.type&&"-"===t.op&&"literal"===e.type&&1===e.number&&"literal"===t.arg1.type&&1===t.arg1.number?t.arg2:new a("-",e,t,e.min-t.max,e.max-t.min)}function f(e,t){return e.min>=t?new r(t):e.max<=t?e:new i(e,t)}function d(){}d.prototype={compile:function(e,a,i){var n,d,g,m,p,v,b,y,w,k,S=[],C=[],x=a.length>>1,_=i.length>>1,A=0;for(n=0;n<x;n++)S.push(new t(n,a[2*n],a[2*n+1]));for(n=0,d=e.length;n<d;n++)if("number"!=typeof(k=e[n]))switch(k){case"add":if(S.length<2)return null;v=S.pop();p=S.pop();S.push(l(p,v));break;case"cvr":if(S.length<1)return null;break;case"mul":if(S.length<2)return null;v=S.pop();p=S.pop();S.push(u(p,v));break;case"sub":if(S.length<2)return null;v=S.pop();p=S.pop();S.push(h(p,v));break;case"exch":if(S.length<2)return null;b=S.pop();y=S.pop();S.push(b,y);break;case"pop":if(S.length<1)return null;S.pop();break;case"index":if(S.length<1)return null;if("literal"!==(p=S.pop()).type)return null;if((g=p.number)<0||!Number.isInteger(g)||S.length<g)return null;if("literal"===(b=S[S.length-g-1]).type||"var"===b.type){S.push(b);break}w=new o(A++,b.min,b.max);S[S.length-g-1]=w;S.push(w);C.push(new s(w,b));break;case"dup":if(S.length<1)return null;if("number"==typeof e[n+1]&&"gt"===e[n+2]&&e[n+3]===n+7&&"jz"===e[n+4]&&"pop"===e[n+5]&&e[n+6]===e[n+1]){p=S.pop();S.push(f(p,e[n+1]));n+=6;break}if("literal"===(b=S[S.length-1]).type||"var"===b.type){S.push(b);break}w=new o(A++,b.min,b.max);S[S.length-1]=w;S.push(w);C.push(new s(w,b));break;case"roll":if(S.length<2)return null;v=S.pop();p=S.pop();if("literal"!==v.type||"literal"!==p.type)return null;m=v.number;if((g=p.number)<=0||!Number.isInteger(g)||!Number.isInteger(m)||S.length<g)return null;if(0===(m=(m%g+g)%g))break;Array.prototype.push.apply(S,S.splice(S.length-g,g-m));break;default:return null}else S.push(new r(k));if(S.length!==_)return null;var P=[];C.forEach(function(e){var t=new c;e.visit(t);P.push(t.toString())});S.forEach(function(e,t){var r=new c;e.visit(r);var a=i[2*t],n=i[2*t+1],o=[r.toString()];if(a>e.min){o.unshift("Math.max(",a,", ");o.push(")")}if(n<e.max){o.unshift("Math.min(",n,", ");o.push(")")}o.unshift("dest[destOffset + ",t,"] = ");o.push(";");P.push(o.join(""))});return P.join("\n")}};return d}();t.isPDFFunction=function(e){var t;if("object"!==(void 0===e?"undefined":a(e)))return!1;if((0,o.isDict)(e))t=e;else{if(!(0,o.isStream)(e))return!1;t=e.dict}return t.has("FunctionType")};t.PDFFunctionFactory=l;t.PostScriptEvaluator=d;t.PostScriptCompiler=g},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.PostScriptParser=t.PostScriptLexer=void 0;var a=r(2),i=r(138),n=function(){function e(e){this.lexer=e;this.operators=[];this.token=null;this.prev=null}e.prototype={nextToken:function(){this.prev=this.token;this.token=this.lexer.getToken()},accept:function(e){if(this.token.type===e){this.nextToken();return!0}return!1},expect:function(e){if(this.accept(e))return!0;throw new a.FormatError("Unexpected symbol: found "+this.token.type+" expected "+e+".")},parse:function(){this.nextToken();this.expect(o.LBRACE);this.parseBlock();this.expect(o.RBRACE);return this.operators},parseBlock:function(){for(;;)if(this.accept(o.NUMBER))this.operators.push(this.prev.value);else if(this.accept(o.OPERATOR))this.operators.push(this.prev.value);else{if(!this.accept(o.LBRACE))return;this.parseCondition()}},parseCondition:function(){var e=this.operators.length;this.operators.push(null,null);this.parseBlock();this.expect(o.RBRACE);if(this.accept(o.IF)){this.operators[e]=this.operators.length;this.operators[e+1]="jz"}else{if(!this.accept(o.LBRACE))throw new a.FormatError("PS Function: error parsing conditional.");var t=this.operators.length;this.operators.push(null,null);var r=this.operators.length;this.parseBlock();this.expect(o.RBRACE);this.expect(o.IFELSE);this.operators[t]=this.operators.length;this.operators[t+1]="j";this.operators[e]=r;this.operators[e+1]="jz"}}};return e}(),o={LBRACE:0,RBRACE:1,NUMBER:2,OPERATOR:3,IF:4,IFELSE:5},s=function(){function e(e,t){this.type=e;this.value=t}var t=Object.create(null);e.getOperator=function(r){var a=t[r];return a||(t[r]=new e(o.OPERATOR,r))};e.LBRACE=new e(o.LBRACE,"{");e.RBRACE=new e(o.RBRACE,"}");e.IF=new e(o.IF,"IF");e.IFELSE=new e(o.IFELSE,"IFELSE");return e}(),c=function(){function e(e){this.stream=e;this.nextChar();this.strBuf=[]}e.prototype={nextChar:function(){return this.currentChar=this.stream.getByte()},getToken:function(){for(var e=!1,t=this.currentChar;;){if(t<0)return i.EOF;if(e)10!==t&&13!==t||(e=!1);else if(37===t)e=!0;else if(!(0,a.isSpace)(t))break;t=this.nextChar()}switch(0|t){case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:case 43:case 45:case 46:return new s(o.NUMBER,this.getNumber());case 123:this.nextChar();return s.LBRACE;case 125:this.nextChar();return s.RBRACE}var r=this.strBuf;r.length=0;r[0]=String.fromCharCode(t);for(;(t=this.nextChar())>=0&&(t>=65&&t<=90||t>=97&&t<=122);)r.push(String.fromCharCode(t));var n=r.join("");switch(n.toLowerCase()){case"if":return s.IF;case"ifelse":return s.IFELSE;default:return s.getOperator(n)}},getNumber:function(){var e=this.currentChar,t=this.strBuf;t.length=0;t[0]=String.fromCharCode(e);for(;(e=this.nextChar())>=0&&(e>=48&&e<=57||45===e||46===e);)t.push(String.fromCharCode(e));var r=parseFloat(t.join(""));if(isNaN(r))throw new a.FormatError("Invalid floating point number: "+r);return r}};return e}();t.PostScriptLexer=c;t.PostScriptParser=n},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.MurmurHash3_64=void 0;var a=r(2),i=function(e){function t(e){this.h1=e?4294967295&e:3285377520;this.h2=e?4294967295&e:3285377520}t.prototype={update:function(e){var t=void 0,r=void 0;if((0,a.isString)(e)){t=new Uint8Array(2*e.length);r=0;for(var i=0,n=e.length;i<n;i++){var o=e.charCodeAt(i);if(o<=255)t[r++]=o;else{t[r++]=o>>>8;t[r++]=255&o}}}else{if(!(0,a.isArrayBuffer)(e))throw new Error("Wrong data format in MurmurHash3_64_update. Input must be a string or array.");r=(t=e).byteLength}for(var s=r>>2,c=r-4*s,l=new Uint32Array(t.buffer,0,s),u=0,h=0,f=this.h1,d=this.h2,g=3432918353,m=461845907,p=0;p<s;p++)1&p?f=5*(f=(f^=u=(u=(u=(u=l[p])*g&4294901760|11601*u&65535)<<15|u>>>17)*m&4294901760|13715*u&65535)<<13|f>>>19)+3864292196:d=5*(d=(d^=h=(h=(h=(h=l[p])*g&4294901760|11601*h&65535)<<15|h>>>17)*m&4294901760|13715*h&65535)<<13|d>>>19)+3864292196;u=0;switch(c){case 3:u^=t[4*s+2]<<16;case 2:u^=t[4*s+1]<<8;case 1:u=(u=(u=(u^=t[4*s])*g&4294901760|11601*u&65535)<<15|u>>>17)*m&4294901760|13715*u&65535;1&s?f^=u:d^=u}this.h1=f;this.h2=d;return this},hexdigest:function(){var e=this.h1,t=this.h2;e=3981806797*(e^=t>>>1)&4294901760|36045*e&65535;e=444984403*(e^=(t=4283543511*t&4294901760|(2950163797*(t<<16|e>>>16)&4294901760)>>>16)>>>1)&4294901760|60499*e&65535;for(var r=0,a=[e^=(t=3301882366*t&4294901760|(3120437893*(t<<16|e>>>16)&4294901760)>>>16)>>>1,t],i="";r<a.length;r++){for(var n=(a[r]>>>0).toString(16);n.length<8;)n="0"+n;i+=n}return i}};return t}();t.MurmurHash3_64=i},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.PDFImage=void 0;var a=function(){return function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var r=[],a=!0,i=!1,n=void 0;try{for(var o,s=e[Symbol.iterator]();!(a=(o=s.next()).done);a=!0){r.push(o.value);if(t&&r.length===t)break}}catch(e){i=!0;n=e}finally{try{!a&&s.return&&s.return()}finally{if(i)throw n}}return r}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),i=r(2),n=r(138),o=r(151),s=r(140),c=r(146),l=r(149),u=function(){function e(e,t){return t&&t.canDecode(e)?t.decode(e).catch(function(t){(0,i.warn)("Native image decoding failed -- trying to recover: "+(t&&t.message));return e}):Promise.resolve(e)}function t(e,t,r,a){return(e=t+e*r)<0?0:e>a?a:e}function r(e,t,r,a,i,n){var o,s,c,l,u=i*n,h=t<=8?new Uint8Array(u):t<=16?new Uint16Array(u):new Uint32Array(u),f=r/i,d=a/n,g=0,m=new Uint16Array(i),p=r;for(o=0;o<i;o++)m[o]=Math.floor(o*f);for(o=0;o<n;o++){c=Math.floor(o*d)*p;for(s=0;s<i;s++){l=c+m[s];h[g++]=e[l]}}return h}function u(e){var t=e.xref,r=e.res,a=e.image,s=e.isInline,c=void 0!==s&&s,h=e.smask,f=void 0===h?null:h,d=e.mask,g=void 0===d?null:d,m=e.isMask,p=void 0!==m&&m,v=e.pdfFunctionFactory;this.image=a;var b=a.dict,y=b.get("Filter");if((0,n.isName)(y))switch(y.name){case"JPXDecode":var w=new l.JpxImage;w.parseImageProperties(a.stream);a.stream.reset();a.width=w.width;a.height=w.height;a.bitsPerComponent=w.bitsPerComponent;a.numComps=w.componentsCount;break;case"JBIG2Decode":a.bitsPerComponent=1;a.numComps=1}var k=b.get("Width","W"),S=b.get("Height","H");if(Number.isInteger(a.width)&&a.width>0&&Number.isInteger(a.height)&&a.height>0&&(a.width!==k||a.height!==S)){(0,i.warn)("PDFImage - using the Width/Height of the image data, rather than the image dictionary.");k=a.width;S=a.height}if(k<1||S<1)throw new i.FormatError("Invalid image width: "+k+" or height: "+S);this.width=k;this.height=S;this.interpolate=b.get("Interpolate","I")||!1;this.imageMask=b.get("ImageMask","IM")||!1;this.matte=b.get("Matte")||!1;var C=a.bitsPerComponent;if(!C&&!(C=b.get("BitsPerComponent","BPC"))){if(!this.imageMask)throw new i.FormatError("Bits per component missing in image: "+this.imageMask);C=1}this.bpc=C;if(!this.imageMask){var x=b.get("ColorSpace","CS");if(!x){(0,i.info)("JPX images (which do not require color spaces)");switch(a.numComps){case 1:x=n.Name.get("DeviceGray");break;case 3:x=n.Name.get("DeviceRGB");break;case 4:x=n.Name.get("DeviceCMYK");break;default:throw new Error("JPX images with "+a.numComps+" color components not supported.")}}var _=c?r:null;this.colorSpace=o.ColorSpace.parse(x,t,_,v);this.numComps=this.colorSpace.numComps}this.decode=b.getArray("Decode","D");this.needsDecode=!1;if(this.decode&&(this.colorSpace&&!this.colorSpace.isDefaultDecode(this.decode)||p&&!o.ColorSpace.isDefaultDecode(this.decode,1))){this.needsDecode=!0;var A=(1<<C)-1;this.decodeCoefficients=[];this.decodeAddends=[];for(var P=0,I=0;P<this.decode.length;P+=2,++I){var O=this.decode[P],T=this.decode[P+1];this.decodeCoefficients[I]=T-O;this.decodeAddends[I]=A*O}}if(f)this.smask=new u({xref:t,res:r,image:f,isInline:c,pdfFunctionFactory:v});else if(g)if((0,n.isStream)(g)){g.dict.get("ImageMask","IM")?this.mask=new u({xref:t,res:r,image:g,isInline:c,isMask:!0,pdfFunctionFactory:v}):(0,i.warn)("Ignoring /Mask in image without /ImageMask.")}else this.mask=g}u.buildImage=function(t){t.handler;var r,o,s=t.xref,c=t.res,l=t.image,h=t.isInline,f=void 0!==h&&h,d=t.nativeDecoder,g=void 0===d?null:d,m=t.pdfFunctionFactory,p=e(l,g),v=l.dict.get("SMask"),b=l.dict.get("Mask");if(v){r=e(v,g);o=Promise.resolve(null)}else{r=Promise.resolve(null);if(b)if((0,n.isStream)(b))o=e(b,g);else if(Array.isArray(b))o=Promise.resolve(b);else{(0,i.warn)("Unsupported mask format.");o=Promise.resolve(null)}else o=Promise.resolve(null)}return Promise.all([p,r,o]).then(function(e){var t=a(e,3),r=t[0],i=t[1],n=t[2];return new u({xref:s,res:c,image:r,isInline:f,smask:i,mask:n,pdfFunctionFactory:m})})};u.createMask=function(e){var t,r,a=e.imgArray,i=e.width,n=e.height,o=e.imageIsFromDecodeStream,s=e.inverseDecode,c=(i+7>>3)*n,l=a.byteLength;if(!o||s&&!(c===l))if(s){(t=new Uint8ClampedArray(c)).set(a);for(r=l;r<c;r++)t[r]=255}else(t=new Uint8ClampedArray(l)).set(a);else t=a;if(s)for(r=0;r<l;r++)t[r]^=255;return{data:t,width:i,height:n}};u.prototype={get drawWidth(){return Math.max(this.width,this.smask&&this.smask.width||0,this.mask&&this.mask.width||0)},get drawHeight(){return Math.max(this.height,this.smask&&this.smask.height||0,this.mask&&this.mask.height||0)},decodeBuffer:function(e){var r,a,i=this.bpc,n=this.numComps,o=this.decodeAddends,s=this.decodeCoefficients,c=(1<<i)-1;if(1!==i){var l=0;for(r=0,a=this.width*this.height;r<a;r++)for(var u=0;u<n;u++){e[l]=t(e[l],o[u],s[u],c);l++}}else for(r=0,a=e.length;r<a;r++)e[r]=+!e[r]},getComponents:function(e){var t=this.bpc;if(8===t)return e;var r,a,i=this.width,n=this.height,o=this.numComps,s=i*n*o,c=0,l=t<=8?new Uint8Array(s):t<=16?new Uint16Array(s):new Uint32Array(s),u=i*o,h=(1<<t)-1,f=0;if(1===t)for(var d,g,m,p=0;p<n;p++){g=f+(-8&u);m=f+u;for(;f<g;){a=e[c++];l[f]=a>>7&1;l[f+1]=a>>6&1;l[f+2]=a>>5&1;l[f+3]=a>>4&1;l[f+4]=a>>3&1;l[f+5]=a>>2&1;l[f+6]=a>>1&1;l[f+7]=1&a;f+=8}if(f<m){a=e[c++];d=128;for(;f<m;){l[f++]=+!!(a&d);d>>=1}}}else{var v=0;a=0;for(f=0,r=s;f<r;++f){if(f%u==0){a=0;v=0}for(;v<t;){a=a<<8|e[c++];v+=8}var b=v-t,y=a>>b;l[f]=y<0?0:y>h?h:y;a&=(1<<b)-1;v=b}}return l},fillOpacity:function(e,t,a,n,o){var s,c,l,h,f,d,g=this.smask,m=this.mask;if(g){c=g.width;l=g.height;s=new Uint8ClampedArray(c*l);g.fillGrayBuffer(s);c===t&&l===a||(s=r(s,g.bpc,c,l,t,a))}else if(m)if(m instanceof u){c=m.width;l=m.height;s=new Uint8ClampedArray(c*l);m.numComps=1;m.fillGrayBuffer(s);for(h=0,f=c*l;h<f;++h)s[h]=255-s[h];c===t&&l===a||(s=r(s,m.bpc,c,l,t,a))}else{if(!Array.isArray(m))throw new i.FormatError("Unknown mask format.");s=new Uint8ClampedArray(t*a);var p=this.numComps;for(h=0,f=t*a;h<f;++h){var v=0,b=h*p;for(d=0;d<p;++d){var y=o[b+d],w=2*d;if(y<m[w]||y>m[w+1]){v=255;break}}s[h]=v}}if(s)for(h=0,d=3,f=t*n;h<f;++h,d+=4)e[d]=s[h];else for(h=0,d=3,f=t*n;h<f;++h,d+=4)e[d]=255},undoPreblend:function(e,t,r){var a=this.smask&&this.smask.matte;if(a)for(var i=this.colorSpace.getRgb(a,0),n=i[0],o=i[1],s=i[2],c=t*r*4,l=0;l<c;l+=4){var u=e[l+3];if(0!==u){var h=255/u;e[l]=(e[l]-n)*h+n;e[l+1]=(e[l+1]-o)*h+o;e[l+2]=(e[l+2]-s)*h+s}else{e[l]=255;e[l+1]=255;e[l+2]=255}}},createImageData:function(){var e,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0],r=this.drawWidth,a=this.drawHeight,n={width:r,height:a,kind:0,data:null},o=this.numComps,l=this.width,u=this.height,h=this.bpc,f=l*o*h+7>>3;if(!t){var d;"DeviceGray"===this.colorSpace.name&&1===h?d=i.ImageKind.GRAYSCALE_1BPP:"DeviceRGB"!==this.colorSpace.name||8!==h||this.needsDecode||(d=i.ImageKind.RGB_24BPP);if(d&&!this.smask&&!this.mask&&r===l&&a===u){n.kind=d;e=this.getImageBytes(u*f);if(this.image instanceof s.DecodeStream)n.data=e;else{var g=new Uint8ClampedArray(e.length);g.set(e);n.data=g}if(this.needsDecode){(0,i.assert)(d===i.ImageKind.GRAYSCALE_1BPP,"PDFImage.createImageData: The image must be grayscale.");for(var m=n.data,p=0,v=m.length;p<v;p++)m[p]^=255}return n}if(this.image instanceof c.JpegStream&&!this.smask&&!this.mask){var b=u*f;switch(this.colorSpace.name){case"DeviceGray":b*=3;case"DeviceRGB":case"DeviceCMYK":n.kind=i.ImageKind.RGB_24BPP;n.data=this.getImageBytes(b,r,a,!0);return n}}}var y,w,k=0|(e=this.getImageBytes(u*f)).length/f*a/u,S=this.getComponents(e);if(t||this.smask||this.mask){n.kind=i.ImageKind.RGBA_32BPP;n.data=new Uint8ClampedArray(r*a*4);y=1;w=!0;this.fillOpacity(n.data,r,a,k,S)}else{n.kind=i.ImageKind.RGB_24BPP;n.data=new Uint8ClampedArray(r*a*3);y=0;w=!1}this.needsDecode&&this.decodeBuffer(S);this.colorSpace.fillRgb(n.data,l,u,r,a,k,h,S,y);w&&this.undoPreblend(n.data,r,k);return n},fillGrayBuffer:function(e){var t=this.numComps;if(1!==t)throw new i.FormatError("Reading gray scale from a color image: "+t);var r,a,n=this.width,o=this.height,s=this.bpc,c=n*t*s+7>>3,l=this.getImageBytes(o*c),u=this.getComponents(l);if(1!==s){this.needsDecode&&this.decodeBuffer(u);a=n*o;var h=255/((1<<s)-1);for(r=0;r<a;++r)e[r]=h*u[r]}else{a=n*o;if(this.needsDecode)for(r=0;r<a;++r)e[r]=u[r]-1&255;else for(r=0;r<a;++r)e[r]=255&-u[r]}},getImageBytes:function(e,t,r){var a=arguments.length>3&&void 0!==arguments[3]&&arguments[3];this.image.reset();this.image.drawWidth=t||this.width;this.image.drawHeight=r||this.height;this.image.forceRGB=!!a;return this.image.getBytes(e,!0)}};return u}();t.PDFImage=u},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.MessageHandler=void 0;var a,i,n,o=r(131),s=(a=o)&&a.__esModule?a:{default:a},c="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},l=(n=(i=s.default.mark(function e(t,r){var a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return s.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(t){e.next=2;break}return e.abrupt("return");case 2:return e.abrupt("return",t.apply(a,r));case 3:case"end":return e.stop()}},e,this)}),function(){var e=i.apply(this,arguments);return new Promise(function(t,r){return function a(i,n){try{var o=e[i](n),s=o.value}catch(e){r(e);return}if(!o.done)return Promise.resolve(s).then(function(e){a("next",e)},function(e){a("throw",e)});t(s)}("next")})}),function(e,t){return n.apply(this,arguments)}),u=r(2);function h(e){if("object"!==(void 0===e?"undefined":c(e)))return e;switch(e.name){case"AbortException":return new u.AbortException(e.message);case"MissingPDFException":return new u.MissingPDFException(e.message);case"UnexpectedResponseException":return new u.UnexpectedResponseException(e.message,e.status);default:return new u.UnknownErrorException(e.message,e.details)}}function f(e,t,r){t?e.resolve():e.reject(r)}function d(e,t,r){var a=this;this.sourceName=e;this.targetName=t;this.comObj=r;this.callbackId=1;this.streamId=1;this.postMessageTransfers=!0;this.streamSinks=Object.create(null);this.streamControllers=Object.create(null);var i=this.callbacksCapabilities=Object.create(null),n=this.actionHandler=Object.create(null);this._onComObjOnMessage=function(e){var t=e.data;if(t.targetName===a.sourceName)if(t.stream)a._processStreamMessage(t);else if(t.isReply){var o=t.callbackId;if(!(t.callbackId in i))throw new Error("Cannot resolve callback "+o);var s=i[o];delete i[o];"error"in t?s.reject(h(t.error)):s.resolve(t.data)}else{if(!(t.action in n))throw new Error("Unknown action from worker: "+t.action);var c=n[t.action];if(t.callbackId){var l=a.sourceName,f=t.sourceName;Promise.resolve().then(function(){return c[0].call(c[1],t.data)}).then(function(e){r.postMessage({sourceName:l,targetName:f,isReply:!0,callbackId:t.callbackId,data:e})},function(e){r.postMessage({sourceName:l,targetName:f,isReply:!0,callbackId:t.callbackId,error:function(e){return!(e instanceof Error)||e instanceof u.AbortException||e instanceof u.MissingPDFException||e instanceof u.UnexpectedResponseException||e instanceof u.UnknownErrorException?e:new u.UnknownErrorException(e.message,e.toString())}(e)})})}else t.streamId?a._createStreamSink(t):c[0].call(c[1],t.data)}};r.addEventListener("message",this._onComObjOnMessage)}d.prototype={on:function(e,t,r){var a=this.actionHandler;if(a[e])throw new Error('There is already an actionName called "'+e+'"');a[e]=[t,r]},send:function(e,t,r){var a={sourceName:this.sourceName,targetName:this.targetName,action:e,data:t};this.postMessage(a,r)},sendWithPromise:function(e,t,r){var a=this.callbackId++,i={sourceName:this.sourceName,targetName:this.targetName,action:e,data:t,callbackId:a},n=(0,u.createPromiseCapability)();this.callbacksCapabilities[a]=n;try{this.postMessage(i,r)}catch(e){n.reject(e)}return n.promise},sendWithStream:function(e,t,r,a){var i=this,n=this.streamId++,o=this.sourceName,s=this.targetName;return new u.ReadableStream({start:function(r){var a=(0,u.createPromiseCapability)();i.streamControllers[n]={controller:r,startCall:a,isClosed:!1};i.postMessage({sourceName:o,targetName:s,action:e,streamId:n,data:t,desiredSize:r.desiredSize});return a.promise},pull:function(e){var t=(0,u.createPromiseCapability)();i.streamControllers[n].pullCall=t;i.postMessage({sourceName:o,targetName:s,stream:"pull",streamId:n,desiredSize:e.desiredSize});return t.promise},cancel:function(e){var t=(0,u.createPromiseCapability)();i.streamControllers[n].cancelCall=t;i.streamControllers[n].isClosed=!0;i.postMessage({sourceName:o,targetName:s,stream:"cancel",reason:e,streamId:n});return t.promise}},r)},_createStreamSink:function(e){var t=this,r=this,a=this.actionHandler[e.action],i=e.streamId,n=e.desiredSize,o=this.sourceName,s=e.sourceName,c=function(e){var r=e.stream,a=e.chunk,n=e.transfers,c=e.success,l=e.reason;t.postMessage({sourceName:o,targetName:s,stream:r,streamId:i,chunk:a,success:c,reason:l},n)},h={enqueue:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,r=arguments[2];if(!this.isCancelled){var a=this.desiredSize;this.desiredSize-=t;if(a>0&&this.desiredSize<=0){this.sinkCapability=(0,u.createPromiseCapability)();this.ready=this.sinkCapability.promise}c({stream:"enqueue",chunk:e,transfers:r})}},close:function(){if(!this.isCancelled){this.isCancelled=!0;c({stream:"close"});delete r.streamSinks[i]}},error:function(e){if(!this.isCancelled){this.isCancelled=!0;c({stream:"error",reason:e})}},sinkCapability:(0,u.createPromiseCapability)(),onPull:null,onCancel:null,isCancelled:!1,desiredSize:n,ready:null};h.sinkCapability.resolve();h.ready=h.sinkCapability.promise;this.streamSinks[i]=h;l(a[0],[e.data,h],a[1]).then(function(){c({stream:"start_complete",success:!0})},function(e){c({stream:"start_complete",success:!1,reason:e})})},_processStreamMessage:function(e){var t=this,r=this.sourceName,a=e.sourceName,i=e.streamId,n=function(e){var n=e.stream,o=e.success,s=e.reason;t.comObj.postMessage({sourceName:r,targetName:a,stream:n,success:o,streamId:i,reason:s})},o=function(){Promise.all([t.streamControllers[e.streamId].startCall,t.streamControllers[e.streamId].pullCall,t.streamControllers[e.streamId].cancelCall].map(function(e){return e&&(t=e.promise,Promise.resolve(t).catch(function(){}));var t})).then(function(){delete t.streamControllers[e.streamId]})};switch(e.stream){case"start_complete":f(this.streamControllers[e.streamId].startCall,e.success,h(e.reason));break;case"pull_complete":f(this.streamControllers[e.streamId].pullCall,e.success,h(e.reason));break;case"pull":if(!this.streamSinks[e.streamId]){n({stream:"pull_complete",success:!0});break}this.streamSinks[e.streamId].desiredSize<=0&&e.desiredSize>0&&this.streamSinks[e.streamId].sinkCapability.resolve();this.streamSinks[e.streamId].desiredSize=e.desiredSize;l(this.streamSinks[e.streamId].onPull).then(function(){n({stream:"pull_complete",success:!0})},function(e){n({stream:"pull_complete",success:!1,reason:e})});break;case"enqueue":(0,u.assert)(this.streamControllers[e.streamId],"enqueue should have stream controller");this.streamControllers[e.streamId].isClosed||this.streamControllers[e.streamId].controller.enqueue(e.chunk);break;case"close":(0,u.assert)(this.streamControllers[e.streamId],"close should have stream controller");if(this.streamControllers[e.streamId].isClosed)break;this.streamControllers[e.streamId].isClosed=!0;this.streamControllers[e.streamId].controller.close();o();break;case"error":(0,u.assert)(this.streamControllers[e.streamId],"error should have stream controller");this.streamControllers[e.streamId].controller.error(h(e.reason));o();break;case"cancel_complete":f(this.streamControllers[e.streamId].cancelCall,e.success,h(e.reason));o();break;case"cancel":if(!this.streamSinks[e.streamId])break;l(this.streamSinks[e.streamId].onCancel,[h(e.reason)]).then(function(){n({stream:"cancel_complete",success:!0})},function(e){n({stream:"cancel_complete",success:!1,reason:e})});this.streamSinks[e.streamId].sinkCapability.reject(h(e.reason));this.streamSinks[e.streamId].isCancelled=!0;delete this.streamSinks[e.streamId];break;default:throw new Error("Unexpected stream case")}},postMessage:function(e,t){t&&this.postMessageTransfers?this.comObj.postMessage(e,t):this.comObj.postMessage(e)},destroy:function(){this.comObj.removeEventListener("message",this._onComObjOnMessage)}};t.MessageHandler=d}])}); \ No newline at end of file
diff --git a/vendor/assets/javascripts/snowplow/sp.js b/vendor/assets/javascripts/snowplow/sp.js
new file mode 100644
index 00000000000..7ea5f1a464f
--- /dev/null
+++ b/vendor/assets/javascripts/snowplow/sp.js
@@ -0,0 +1,22 @@
+/*
+ * Snowplow - The world's most powerful web analytics platform
+ *
+ * @description JavaScript tracker for Snowplow
+ * @version 2.10.0
+ * @author Alex Dean, Simon Andersson, Anthon Pang, Fred Blundun, Joshua Beemster, Michael Hadam
+ * @copyright Anthon Pang, Snowplow Analytics Ltd
+ * @license Simplified BSD
+ *
+ * For technical documentation:
+ * https://github.com/snowplow/snowplow/wiki/javascript-tracker
+ *
+ * For the setup guide:
+ * https://github.com/snowplow/snowplow/wiki/javascript-tracker-setup
+ *
+ * Minimum supported browsers:
+ * - Firefox 27
+ * - Chrome 32
+ * - IE 9
+ * - Safari 8
+ */
+"use strict";function _typeof(e){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}!function o(i,c,s){function u(t,e){if(!c[t]){if(!i[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(l)return l(t,!0);var r=new Error("Cannot find module '"+t+"'");throw r.code="MODULE_NOT_FOUND",r}var a=c[t]={exports:{}};i[t][0].call(a.exports,function(e){return u(i[t][1][e]||e)},a,a.exports,o,i,c,s)}return c[t].exports}for(var l="function"==typeof require&&require,e=0;e<s.length;e++)u(s[e]);return u}({1:[function(e,t,n){this.cookie=function(e,t,n,r,a,o){return 1<arguments.length?document.cookie=e+"="+escape(t)+(n?"; expires="+new Date(+new Date+1e3*n).toUTCString():"")+(r?"; path="+r:"")+(a?"; domain="+a:"")+(o?"; secure":""):unescape((("; "+document.cookie).split("; "+e+"=")[1]||"").split(";")[0])}},{}],2:[function(e,t,n){var r={utf8:{stringToBytes:function(e){return r.bin.stringToBytes(unescape(encodeURIComponent(e)))},bytesToString:function(e){return decodeURIComponent(escape(r.bin.bytesToString(e)))}},bin:{stringToBytes:function(e){for(var t=[],n=0;n<e.length;n++)t.push(255&e.charCodeAt(n));return t},bytesToString:function(e){for(var t=[],n=0;n<e.length;n++)t.push(String.fromCharCode(e[n]));return t.join("")}}};t.exports=r},{}],3:[function(e,t,n){var o,r;o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",r={rotl:function(e,t){return e<<t|e>>>32-t},rotr:function(e,t){return e<<32-t|e>>>t},endian:function(e){if(e.constructor==Number)return 16711935&r.rotl(e,8)|4278255360&r.rotl(e,24);for(var t=0;t<e.length;t++)e[t]=r.endian(e[t]);return e},randomBytes:function(e){for(var t=[];0<e;e--)t.push(Math.floor(256*Math.random()));return t},bytesToWords:function(e){for(var t=[],n=0,r=0;n<e.length;n++,r+=8)t[r>>>5]|=e[n]<<24-r%32;return t},wordsToBytes:function(e){for(var t=[],n=0;n<32*e.length;n+=8)t.push(e[n>>>5]>>>24-n%32&255);return t},bytesToHex:function(e){for(var t=[],n=0;n<e.length;n++)t.push((e[n]>>>4).toString(16)),t.push((15&e[n]).toString(16));return t.join("")},hexToBytes:function(e){for(var t=[],n=0;n<e.length;n+=2)t.push(parseInt(e.substr(n,2),16));return t},bytesToBase64:function(e){for(var t=[],n=0;n<e.length;n+=3)for(var r=e[n]<<16|e[n+1]<<8|e[n+2],a=0;a<4;a++)8*n+6*a<=8*e.length?t.push(o.charAt(r>>>6*(3-a)&63)):t.push("=");return t.join("")},base64ToBytes:function(e){e=e.replace(/[^A-Z0-9+\/]/gi,"");for(var t=[],n=0,r=0;n<e.length;r=++n%4)0!=r&&t.push((o.indexOf(e.charAt(n-1))&Math.pow(2,-2*r+8)-1)<<2*r|o.indexOf(e.charAt(n))>>>6-2*r);return t}},t.exports=r},{}],4:[function(e,t,n){var r,a,o,i,c,s;r=this,a=function(e){var t=-e.getTimezoneOffset();return null!==t?t:0},o=function(e,t,n){var r=new Date;return void 0!==e&&r.setFullYear(e),r.setMonth(t),r.setDate(n),r},i=function(e){return a(o(e,0,2))},c=function(e){return a(o(e,5,2))},(s={determine:function(){var e,t,n,r=(e=i(),t=c(),(n=e-t)<0?e+",1":0<n?t+",1,s":e+",0");return new s.TimeZone(s.olson.timezones[r])},date_is_dst:function(e){var t=7<e.getMonth(),n=t?c(e.getFullYear()):i(e.getFullYear()),r=n-a(e);return n<0||t?0!==r:r<0},dst_start_for:function(e){var t=new Date(2010,6,15,1,0,0,0);return{"America/Denver":new Date(2011,2,13,3,0,0,0),"America/Mazatlan":new Date(2011,3,3,3,0,0,0),"America/Chicago":new Date(2011,2,13,3,0,0,0),"America/Mexico_City":new Date(2011,3,3,3,0,0,0),"America/Asuncion":new Date(2012,9,7,3,0,0,0),"America/Santiago":new Date(2012,9,3,3,0,0,0),"America/Campo_Grande":new Date(2012,9,21,5,0,0,0),"America/Montevideo":new Date(2011,9,2,3,0,0,0),"America/Sao_Paulo":new Date(2011,9,16,5,0,0,0),"America/Los_Angeles":new Date(2011,2,13,8,0,0,0),"America/Santa_Isabel":new Date(2011,3,5,8,0,0,0),"America/Havana":new Date(2012,2,10,2,0,0,0),"America/New_York":new Date(2012,2,10,7,0,0,0),"Europe/Helsinki":new Date(2013,2,31,5,0,0,0),"Pacific/Auckland":new Date(2011,8,26,7,0,0,0),"America/Halifax":new Date(2011,2,13,6,0,0,0),"America/Goose_Bay":new Date(2011,2,13,2,1,0,0),"America/Miquelon":new Date(2011,2,13,5,0,0,0),"America/Godthab":new Date(2011,2,27,1,0,0,0),"Europe/Moscow":t,"Asia/Amman":new Date(2013,2,29,1,0,0,0),"Asia/Beirut":new Date(2013,2,31,2,0,0,0),"Asia/Damascus":new Date(2013,3,6,2,0,0,0),"Asia/Jerusalem":new Date(2013,2,29,5,0,0,0),"Asia/Yekaterinburg":t,"Asia/Omsk":t,"Asia/Krasnoyarsk":t,"Asia/Irkutsk":t,"Asia/Yakutsk":t,"Asia/Vladivostok":t,"Asia/Baku":new Date(2013,2,31,4,0,0),"Asia/Yerevan":new Date(2013,2,31,3,0,0),"Asia/Kamchatka":t,"Asia/Gaza":new Date(2010,2,27,4,0,0),"Africa/Cairo":new Date(2010,4,1,3,0,0),"Europe/Minsk":t,"Pacific/Apia":new Date(2010,10,1,1,0,0,0),"Pacific/Fiji":new Date(2010,11,1,0,0,0),"Australia/Perth":new Date(2008,10,1,1,0,0,0)}[e]},TimeZone:function(e){var a={"America/Denver":["America/Denver","America/Mazatlan"],"America/Chicago":["America/Chicago","America/Mexico_City"],"America/Santiago":["America/Santiago","America/Asuncion","America/Campo_Grande"],"America/Montevideo":["America/Montevideo","America/Sao_Paulo"],"Asia/Beirut":["Asia/Amman","Asia/Jerusalem","Asia/Beirut","Europe/Helsinki","Asia/Damascus"],"Pacific/Auckland":["Pacific/Auckland","Pacific/Fiji"],"America/Los_Angeles":["America/Los_Angeles","America/Santa_Isabel"],"America/New_York":["America/Havana","America/New_York"],"America/Halifax":["America/Goose_Bay","America/Halifax"],"America/Godthab":["America/Miquelon","America/Godthab"],"Asia/Dubai":["Europe/Moscow"],"Asia/Dhaka":["Asia/Yekaterinburg"],"Asia/Jakarta":["Asia/Omsk"],"Asia/Shanghai":["Asia/Krasnoyarsk","Australia/Perth"],"Asia/Tokyo":["Asia/Irkutsk"],"Australia/Brisbane":["Asia/Yakutsk"],"Pacific/Noumea":["Asia/Vladivostok"],"Pacific/Tarawa":["Asia/Kamchatka","Pacific/Fiji"],"Pacific/Tongatapu":["Pacific/Apia"],"Asia/Baghdad":["Europe/Minsk"],"Asia/Baku":["Asia/Yerevan","Asia/Baku"],"Africa/Johannesburg":["Asia/Gaza","Africa/Cairo"]},o=e;return void 0!==a[o]&&function(){for(var e=a[o],t=e.length,n=0,r=e[0];n<t;n+=1)if(r=e[n],s.date_is_dst(s.dst_start_for(r)))return o=r}(),{name:function(){return o}}},olson:{}}).olson.timezones={"-720,0":"Pacific/Majuro","-660,0":"Pacific/Pago_Pago","-600,1":"America/Adak","-600,0":"Pacific/Honolulu","-570,0":"Pacific/Marquesas","-540,0":"Pacific/Gambier","-540,1":"America/Anchorage","-480,1":"America/Los_Angeles","-480,0":"Pacific/Pitcairn","-420,0":"America/Phoenix","-420,1":"America/Denver","-360,0":"America/Guatemala","-360,1":"America/Chicago","-360,1,s":"Pacific/Easter","-300,0":"America/Bogota","-300,1":"America/New_York","-270,0":"America/Caracas","-240,1":"America/Halifax","-240,0":"America/Santo_Domingo","-240,1,s":"America/Santiago","-210,1":"America/St_Johns","-180,1":"America/Godthab","-180,0":"America/Argentina/Buenos_Aires","-180,1,s":"America/Montevideo","-120,0":"America/Noronha","-120,1":"America/Noronha","-60,1":"Atlantic/Azores","-60,0":"Atlantic/Cape_Verde","0,0":"UTC","0,1":"Europe/London","60,1":"Europe/Berlin","60,0":"Africa/Lagos","60,1,s":"Africa/Windhoek","120,1":"Asia/Beirut","120,0":"Africa/Johannesburg","180,0":"Asia/Baghdad","180,1":"Europe/Moscow","210,1":"Asia/Tehran","240,0":"Asia/Dubai","240,1":"Asia/Baku","270,0":"Asia/Kabul","300,1":"Asia/Yekaterinburg","300,0":"Asia/Karachi","330,0":"Asia/Kolkata","345,0":"Asia/Kathmandu","360,0":"Asia/Dhaka","360,1":"Asia/Omsk","390,0":"Asia/Rangoon","420,1":"Asia/Krasnoyarsk","420,0":"Asia/Jakarta","480,0":"Asia/Shanghai","480,1":"Asia/Irkutsk","525,0":"Australia/Eucla","525,1,s":"Australia/Eucla","540,1":"Asia/Yakutsk","540,0":"Asia/Tokyo","570,0":"Australia/Darwin","570,1,s":"Australia/Adelaide","600,0":"Australia/Brisbane","600,1":"Asia/Vladivostok","600,1,s":"Australia/Sydney","630,1,s":"Australia/Lord_Howe","660,1":"Asia/Kamchatka","660,0":"Pacific/Noumea","690,0":"Pacific/Norfolk","720,1,s":"Pacific/Auckland","720,0":"Pacific/Tarawa","765,1,s":"Pacific/Chatham","780,0":"Pacific/Tongatapu","780,1,s":"Pacific/Apia","840,0":"Pacific/Kiritimati"},void 0!==n?n.jstz=s:r.jstz=s},{}],5:[function(e,t,n){var r=e("./_getNative")(e("./_root"),"DataView");t.exports=r},{"./_getNative":68,"./_root":105}],6:[function(e,t,n){var r=e("./_hashClear"),a=e("./_hashDelete"),o=e("./_hashGet"),i=e("./_hashHas"),c=e("./_hashSet");function s(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}s.prototype.clear=r,s.prototype.delete=a,s.prototype.get=o,s.prototype.has=i,s.prototype.set=c,t.exports=s},{"./_hashClear":75,"./_hashDelete":76,"./_hashGet":77,"./_hashHas":78,"./_hashSet":79}],7:[function(e,t,n){var r=e("./_listCacheClear"),a=e("./_listCacheDelete"),o=e("./_listCacheGet"),i=e("./_listCacheHas"),c=e("./_listCacheSet");function s(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}s.prototype.clear=r,s.prototype.delete=a,s.prototype.get=o,s.prototype.has=i,s.prototype.set=c,t.exports=s},{"./_listCacheClear":87,"./_listCacheDelete":88,"./_listCacheGet":89,"./_listCacheHas":90,"./_listCacheSet":91}],8:[function(e,t,n){var r=e("./_getNative")(e("./_root"),"Map");t.exports=r},{"./_getNative":68,"./_root":105}],9:[function(e,t,n){var r=e("./_mapCacheClear"),a=e("./_mapCacheDelete"),o=e("./_mapCacheGet"),i=e("./_mapCacheHas"),c=e("./_mapCacheSet");function s(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}s.prototype.clear=r,s.prototype.delete=a,s.prototype.get=o,s.prototype.has=i,s.prototype.set=c,t.exports=s},{"./_mapCacheClear":92,"./_mapCacheDelete":93,"./_mapCacheGet":94,"./_mapCacheHas":95,"./_mapCacheSet":96}],10:[function(e,t,n){var r=e("./_getNative")(e("./_root"),"Promise");t.exports=r},{"./_getNative":68,"./_root":105}],11:[function(e,t,n){var r=e("./_getNative")(e("./_root"),"Set");t.exports=r},{"./_getNative":68,"./_root":105}],12:[function(e,t,n){var r=e("./_MapCache"),a=e("./_setCacheAdd"),o=e("./_setCacheHas");function i(e){var t=-1,n=null==e?0:e.length;for(this.__data__=new r;++t<n;)this.add(e[t])}i.prototype.add=i.prototype.push=a,i.prototype.has=o,t.exports=i},{"./_MapCache":9,"./_setCacheAdd":106,"./_setCacheHas":107}],13:[function(e,t,n){var r=e("./_ListCache"),a=e("./_stackClear"),o=e("./_stackDelete"),i=e("./_stackGet"),c=e("./_stackHas"),s=e("./_stackSet");function u(e){var t=this.__data__=new r(e);this.size=t.size}u.prototype.clear=a,u.prototype.delete=o,u.prototype.get=i,u.prototype.has=c,u.prototype.set=s,t.exports=u},{"./_ListCache":7,"./_stackClear":109,"./_stackDelete":110,"./_stackGet":111,"./_stackHas":112,"./_stackSet":113}],14:[function(e,t,n){var r=e("./_root").Symbol;t.exports=r},{"./_root":105}],15:[function(e,t,n){var r=e("./_root").Uint8Array;t.exports=r},{"./_root":105}],16:[function(e,t,n){var r=e("./_getNative")(e("./_root"),"WeakMap");t.exports=r},{"./_getNative":68,"./_root":105}],17:[function(e,t,n){t.exports=function(e,t){for(var n=-1,r=null==e?0:e.length;++n<r&&!1!==t(e[n],n,e););return e}},{}],18:[function(e,t,n){t.exports=function(e,t){for(var n=-1,r=null==e?0:e.length;++n<r;)if(!t(e[n],n,e))return!1;return!0}},{}],19:[function(e,t,n){t.exports=function(e,t){for(var n=-1,r=null==e?0:e.length,a=0,o=[];++n<r;){var i=e[n];t(i,n,e)&&(o[a++]=i)}return o}},{}],20:[function(e,t,n){var l=e("./_baseTimes"),f=e("./isArguments"),d=e("./isArray"),p=e("./isBuffer"),h=e("./_isIndex"),m=e("./isTypedArray"),v=Object.prototype.hasOwnProperty;t.exports=function(e,t){var n=d(e),r=!n&&f(e),a=!n&&!r&&p(e),o=!n&&!r&&!a&&m(e),i=n||r||a||o,c=i?l(e.length,String):[],s=c.length;for(var u in e)!t&&!v.call(e,u)||i&&("length"==u||a&&("offset"==u||"parent"==u)||o&&("buffer"==u||"byteLength"==u||"byteOffset"==u)||h(u,s))||c.push(u);return c}},{"./_baseTimes":50,"./_isIndex":80,"./isArguments":128,"./isArray":129,"./isBuffer":131,"./isTypedArray":140}],21:[function(e,t,n){t.exports=function(e,t){for(var n=-1,r=null==e?0:e.length,a=Array(r);++n<r;)a[n]=t(e[n],n,e);return a}},{}],22:[function(e,t,n){t.exports=function(e,t){for(var n=-1,r=t.length,a=e.length;++n<r;)e[a+n]=t[n];return e}},{}],23:[function(e,t,n){t.exports=function(e,t){for(var n=-1,r=null==e?0:e.length;++n<r;)if(t(e[n],n,e))return!0;return!1}},{}],24:[function(e,t,n){var r=e("./eq");t.exports=function(e,t){for(var n=e.length;n--;)if(r(e[n][0],t))return n;return-1}},{"./eq":118}],25:[function(e,t,n){var r=e("./_defineProperty");t.exports=function(e,t,n){"__proto__"==t&&r?r(e,t,{configurable:!0,enumerable:!0,value:n,writable:!0}):e[t]=n}},{"./_defineProperty":60}],26:[function(e,t,n){var r=e("./_baseForOwn"),a=e("./_createBaseEach")(r);t.exports=a},{"./_baseForOwn":31,"./_createBaseEach":57}],27:[function(e,t,n){var o=e("./_baseEach");t.exports=function(e,r){var a=!0;return o(e,function(e,t,n){return a=!!r(e,t,n)}),a}},{"./_baseEach":26}],28:[function(e,t,n){var o=e("./_baseEach");t.exports=function(e,r){var a=[];return o(e,function(e,t,n){r(e,t,n)&&a.push(e)}),a}},{"./_baseEach":26}],29:[function(e,t,n){t.exports=function(e,t,n,r){for(var a=e.length,o=n+(r?1:-1);r?o--:++o<a;)if(t(e[o],o,e))return o;return-1}},{}],30:[function(e,t,n){var r=e("./_createBaseFor")();t.exports=r},{"./_createBaseFor":58}],31:[function(e,t,n){var r=e("./_baseFor"),a=e("./keys");t.exports=function(e,t){return e&&r(e,t,a)}},{"./_baseFor":30,"./keys":142}],32:[function(e,t,n){var a=e("./_castPath"),o=e("./_toKey");t.exports=function(e,t){for(var n=0,r=(t=a(t,e)).length;null!=e&&n<r;)e=e[o(t[n++])];return n&&n==r?e:void 0}},{"./_castPath":55,"./_toKey":115}],33:[function(e,t,n){var a=e("./_arrayPush"),o=e("./isArray");t.exports=function(e,t,n){var r=t(e);return o(e)?r:a(r,n(e))}},{"./_arrayPush":22,"./isArray":129}],34:[function(e,t,n){var r=e("./_Symbol"),a=e("./_getRawTag"),o=e("./_objectToString"),i=r?r.toStringTag:void 0;t.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":i&&i in Object(e)?a(e):o(e)}},{"./_Symbol":14,"./_getRawTag":70,"./_objectToString":103}],35:[function(e,t,n){var r=Object.prototype.hasOwnProperty;t.exports=function(e,t){return null!=e&&r.call(e,t)}},{}],36:[function(e,t,n){t.exports=function(e,t){return null!=e&&t in Object(e)}},{}],37:[function(e,t,n){var r=e("./_baseGetTag"),a=e("./isObjectLike");t.exports=function(e){return a(e)&&"[object Arguments]"==r(e)}},{"./_baseGetTag":34,"./isObjectLike":136}],38:[function(e,t,n){var i=e("./_baseIsEqualDeep"),c=e("./isObjectLike");t.exports=function e(t,n,r,a,o){return t===n||(null==t||null==n||!c(t)&&!c(n)?t!=t&&n!=n:i(t,n,r,a,e,o))}},{"./_baseIsEqualDeep":39,"./isObjectLike":136}],39:[function(e,t,n){var g=e("./_Stack"),y=e("./_equalArrays"),_=e("./_equalByTag"),b=e("./_equalObjects"),w=e("./_getTag"),k=e("./isArray"),A=e("./isBuffer"),x=e("./isTypedArray"),C="[object Arguments]",S="[object Array]",j="[object Object]",T=Object.prototype.hasOwnProperty;t.exports=function(e,t,n,r,a,o){var i=k(e),c=k(t),s=i?S:w(e),u=c?S:w(t),l=(s=s==C?j:s)==j,f=(u=u==C?j:u)==j,d=s==u;if(d&&A(e)){if(!A(t))return!1;l=!(i=!0)}if(d&&!l)return o||(o=new g),i||x(e)?y(e,t,n,r,a,o):_(e,t,s,n,r,a,o);if(!(1&n)){var p=l&&T.call(e,"__wrapped__"),h=f&&T.call(t,"__wrapped__");if(p||h){var m=p?e.value():e,v=h?t.value():t;return o||(o=new g),a(m,v,n,r,o)}}return!!d&&(o||(o=new g),b(e,t,n,r,a,o))}},{"./_Stack":13,"./_equalArrays":61,"./_equalByTag":62,"./_equalObjects":63,"./_getTag":72,"./isArray":129,"./isBuffer":131,"./isTypedArray":140}],40:[function(e,t,n){var p=e("./_Stack"),h=e("./_baseIsEqual");t.exports=function(e,t,n,r){var a=n.length,o=a,i=!r;if(null==e)return!o;for(e=Object(e);a--;){var c=n[a];if(i&&c[2]?c[1]!==e[c[0]]:!(c[0]in e))return!1}for(;++a<o;){var s=(c=n[a])[0],u=e[s],l=c[1];if(i&&c[2]){if(void 0===u&&!(s in e))return!1}else{var f=new p;if(r)var d=r(u,l,s,e,t,f);if(!(void 0===d?h(l,u,3,r,f):d))return!1}}return!0}},{"./_Stack":13,"./_baseIsEqual":38}],41:[function(e,t,n){var r=e("./isFunction"),a=e("./_isMasked"),o=e("./isObject"),i=e("./_toSource"),c=/^\[object .+?Constructor\]$/,s=Function.prototype,u=Object.prototype,l=s.toString,f=u.hasOwnProperty,d=RegExp("^"+l.call(f).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");t.exports=function(e){return!(!o(e)||a(e))&&(r(e)?d:c).test(i(e))}},{"./_isMasked":84,"./_toSource":116,"./isFunction":133,"./isObject":135}],42:[function(e,t,n){var r=e("./_baseGetTag"),a=e("./isLength"),o=e("./isObjectLike"),i={};i["[object Float32Array]"]=i["[object Float64Array]"]=i["[object Int8Array]"]=i["[object Int16Array]"]=i["[object Int32Array]"]=i["[object Uint8Array]"]=i["[object Uint8ClampedArray]"]=i["[object Uint16Array]"]=i["[object Uint32Array]"]=!0,i["[object Arguments]"]=i["[object Array]"]=i["[object ArrayBuffer]"]=i["[object Boolean]"]=i["[object DataView]"]=i["[object Date]"]=i["[object Error]"]=i["[object Function]"]=i["[object Map]"]=i["[object Number]"]=i["[object Object]"]=i["[object RegExp]"]=i["[object Set]"]=i["[object String]"]=i["[object WeakMap]"]=!1,t.exports=function(e){return o(e)&&a(e.length)&&!!i[r(e)]}},{"./_baseGetTag":34,"./isLength":134,"./isObjectLike":136}],43:[function(e,t,n){var r=e("./_baseMatches"),a=e("./_baseMatchesProperty"),o=e("./identity"),i=e("./isArray"),c=e("./property");t.exports=function(e){return"function"==typeof e?e:null==e?o:"object"==_typeof(e)?i(e)?a(e[0],e[1]):r(e):c(e)}},{"./_baseMatches":46,"./_baseMatchesProperty":47,"./identity":127,"./isArray":129,"./property":146}],44:[function(e,t,n){var r=e("./_isPrototype"),a=e("./_nativeKeys"),o=Object.prototype.hasOwnProperty;t.exports=function(e){if(!r(e))return a(e);var t=[];for(var n in Object(e))o.call(e,n)&&"constructor"!=n&&t.push(n);return t}},{"./_isPrototype":85,"./_nativeKeys":101}],45:[function(e,t,n){var i=e("./_baseEach"),c=e("./isArrayLike");t.exports=function(e,r){var a=-1,o=c(e)?Array(e.length):[];return i(e,function(e,t,n){o[++a]=r(e,t,n)}),o}},{"./_baseEach":26,"./isArrayLike":130}],46:[function(e,t,n){var r=e("./_baseIsMatch"),a=e("./_getMatchData"),o=e("./_matchesStrictComparable");t.exports=function(t){var n=a(t);return 1==n.length&&n[0][2]?o(n[0][0],n[0][1]):function(e){return e===t||r(e,t,n)}}},{"./_baseIsMatch":40,"./_getMatchData":67,"./_matchesStrictComparable":98}],47:[function(e,t,n){var a=e("./_baseIsEqual"),o=e("./get"),i=e("./hasIn"),c=e("./_isKey"),s=e("./_isStrictComparable"),u=e("./_matchesStrictComparable"),l=e("./_toKey");t.exports=function(n,r){return c(n)&&s(r)?u(l(n),r):function(e){var t=o(e,n);return void 0===t&&t===r?i(e,n):a(r,t,3)}}},{"./_baseIsEqual":38,"./_isKey":82,"./_isStrictComparable":86,"./_matchesStrictComparable":98,"./_toKey":115,"./get":124,"./hasIn":126}],48:[function(e,t,n){t.exports=function(t){return function(e){return null==e?void 0:e[t]}}},{}],49:[function(e,t,n){var r=e("./_baseGet");t.exports=function(t){return function(e){return r(e,t)}}},{"./_baseGet":32}],50:[function(e,t,n){t.exports=function(e,t){for(var n=-1,r=Array(e);++n<e;)r[n]=t(n);return r}},{}],51:[function(e,t,n){var r=e("./_Symbol"),a=e("./_arrayMap"),o=e("./isArray"),i=e("./isSymbol"),c=1/0,s=r?r.prototype:void 0,u=s?s.toString:void 0;t.exports=function e(t){if("string"==typeof t)return t;if(o(t))return a(t,e)+"";if(i(t))return u?u.call(t):"";var n=t+"";return"0"==n&&1/t==-c?"-0":n}},{"./_Symbol":14,"./_arrayMap":21,"./isArray":129,"./isSymbol":139}],52:[function(e,t,n){t.exports=function(t){return function(e){return t(e)}}},{}],53:[function(e,t,n){t.exports=function(e,t){return e.has(t)}},{}],54:[function(e,t,n){var r=e("./identity");t.exports=function(e){return"function"==typeof e?e:r}},{"./identity":127}],55:[function(e,t,n){var r=e("./isArray"),a=e("./_isKey"),o=e("./_stringToPath"),i=e("./toString");t.exports=function(e,t){return r(e)?e:a(e,t)?[e]:o(i(e))}},{"./_isKey":82,"./_stringToPath":114,"./isArray":129,"./toString":152}],56:[function(e,t,n){var r=e("./_root")["__core-js_shared__"];t.exports=r},{"./_root":105}],57:[function(e,t,n){var c=e("./isArrayLike");t.exports=function(o,i){return function(e,t){if(null==e)return e;if(!c(e))return o(e,t);for(var n=e.length,r=i?n:-1,a=Object(e);(i?r--:++r<n)&&!1!==t(a[r],r,a););return e}}},{"./isArrayLike":130}],58:[function(e,t,n){t.exports=function(s){return function(e,t,n){for(var r=-1,a=Object(e),o=n(e),i=o.length;i--;){var c=o[s?i:++r];if(!1===t(a[c],c,a))break}return e}}},{}],59:[function(e,t,n){var c=e("./_baseIteratee"),s=e("./isArrayLike"),u=e("./keys");t.exports=function(i){return function(e,t,n){var r=Object(e);if(!s(e)){var a=c(t,3);e=u(e),t=function(e){return a(r[e],e,r)}}var o=i(e,t,n);return-1<o?r[a?e[o]:o]:void 0}}},{"./_baseIteratee":43,"./isArrayLike":130,"./keys":142}],60:[function(e,t,n){var r=e("./_getNative"),a=function(){try{var e=r(Object,"defineProperty");return e({},"",{}),e}catch(e){}}();t.exports=a},{"./_getNative":68}],61:[function(e,t,n){var v=e("./_SetCache"),g=e("./_arraySome"),y=e("./_cacheHas");t.exports=function(e,t,n,r,a,o){var i=1&n,c=e.length,s=t.length;if(c!=s&&!(i&&c<s))return!1;var u=o.get(e);if(u&&o.get(t))return u==t;var l=-1,f=!0,d=2&n?new v:void 0;for(o.set(e,t),o.set(t,e);++l<c;){var p=e[l],h=t[l];if(r)var m=i?r(h,p,l,t,e,o):r(p,h,l,e,t,o);if(void 0!==m){if(m)continue;f=!1;break}if(d){if(!g(t,function(e,t){if(!y(d,t)&&(p===e||a(p,e,n,r,o)))return d.push(t)})){f=!1;break}}else if(p!==h&&!a(p,h,n,r,o)){f=!1;break}}return o.delete(e),o.delete(t),f}},{"./_SetCache":12,"./_arraySome":23,"./_cacheHas":53}],62:[function(e,t,n){var r=e("./_Symbol"),f=e("./_Uint8Array"),d=e("./eq"),p=e("./_equalArrays"),h=e("./_mapToArray"),m=e("./_setToArray"),a=r?r.prototype:void 0,v=a?a.valueOf:void 0;t.exports=function(e,t,n,r,a,o,i){switch(n){case"[object DataView]":if(e.byteLength!=t.byteLength||e.byteOffset!=t.byteOffset)return!1;e=e.buffer,t=t.buffer;case"[object ArrayBuffer]":return!(e.byteLength!=t.byteLength||!o(new f(e),new f(t)));case"[object Boolean]":case"[object Date]":case"[object Number]":return d(+e,+t);case"[object Error]":return e.name==t.name&&e.message==t.message;case"[object RegExp]":case"[object String]":return e==t+"";case"[object Map]":var c=h;case"[object Set]":var s=1&r;if(c||(c=m),e.size!=t.size&&!s)return!1;var u=i.get(e);if(u)return u==t;r|=2,i.set(e,t);var l=p(c(e),c(t),r,a,o,i);return i.delete(e),l;case"[object Symbol]":if(v)return v.call(e)==v.call(t)}return!1}},{"./_Symbol":14,"./_Uint8Array":15,"./_equalArrays":61,"./_mapToArray":97,"./_setToArray":108,"./eq":118}],63:[function(e,t,n){var _=e("./_getAllKeys"),b=Object.prototype.hasOwnProperty;t.exports=function(e,t,n,r,a,o){var i=1&n,c=_(e),s=c.length;if(s!=_(t).length&&!i)return!1;for(var u=s;u--;){var l=c[u];if(!(i?l in t:b.call(t,l)))return!1}var f=o.get(e);if(f&&o.get(t))return f==t;var d=!0;o.set(e,t),o.set(t,e);for(var p=i;++u<s;){var h=e[l=c[u]],m=t[l];if(r)var v=i?r(m,h,l,t,e,o):r(h,m,l,e,t,o);if(!(void 0===v?h===m||a(h,m,n,r,o):v)){d=!1;break}p||(p="constructor"==l)}if(d&&!p){var g=e.constructor,y=t.constructor;g!=y&&"constructor"in e&&"constructor"in t&&!("function"==typeof g&&g instanceof g&&"function"==typeof y&&y instanceof y)&&(d=!1)}return o.delete(e),o.delete(t),d}},{"./_getAllKeys":65}],64:[function(e,n,t){(function(e){var t="object"==_typeof(e)&&e&&e.Object===Object&&e;n.exports=t}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],65:[function(e,t,n){var r=e("./_baseGetAllKeys"),a=e("./_getSymbols"),o=e("./keys");t.exports=function(e){return r(e,o,a)}},{"./_baseGetAllKeys":33,"./_getSymbols":71,"./keys":142}],66:[function(e,t,n){var r=e("./_isKeyable");t.exports=function(e,t){var n=e.__data__;return r(t)?n["string"==typeof t?"string":"hash"]:n.map}},{"./_isKeyable":83}],67:[function(e,t,n){var o=e("./_isStrictComparable"),i=e("./keys");t.exports=function(e){for(var t=i(e),n=t.length;n--;){var r=t[n],a=e[r];t[n]=[r,a,o(a)]}return t}},{"./_isStrictComparable":86,"./keys":142}],68:[function(e,t,n){var r=e("./_baseIsNative"),a=e("./_getValue");t.exports=function(e,t){var n=a(e,t);return r(n)?n:void 0}},{"./_baseIsNative":41,"./_getValue":73}],69:[function(e,t,n){var r=e("./_overArg")(Object.getPrototypeOf,Object);t.exports=r},{"./_overArg":104}],70:[function(e,t,n){var r=e("./_Symbol"),a=Object.prototype,o=a.hasOwnProperty,i=a.toString,c=r?r.toStringTag:void 0;t.exports=function(e){var t=o.call(e,c),n=e[c];try{var r=!(e[c]=void 0)}catch(e){}var a=i.call(e);return r&&(t?e[c]=n:delete e[c]),a}},{"./_Symbol":14}],71:[function(e,t,n){var r=e("./_arrayFilter"),a=e("./stubArray"),o=Object.prototype.propertyIsEnumerable,i=Object.getOwnPropertySymbols,c=i?function(t){return null==t?[]:(t=Object(t),r(i(t),function(e){return o.call(t,e)}))}:a;t.exports=c},{"./_arrayFilter":19,"./stubArray":147}],72:[function(e,t,n){var r=e("./_DataView"),a=e("./_Map"),o=e("./_Promise"),i=e("./_Set"),c=e("./_WeakMap"),s=e("./_baseGetTag"),u=e("./_toSource"),l="[object Map]",f="[object Promise]",d="[object Set]",p="[object WeakMap]",h="[object DataView]",m=u(r),v=u(a),g=u(o),y=u(i),_=u(c),b=s;(r&&b(new r(new ArrayBuffer(1)))!=h||a&&b(new a)!=l||o&&b(o.resolve())!=f||i&&b(new i)!=d||c&&b(new c)!=p)&&(b=function(e){var t=s(e),n="[object Object]"==t?e.constructor:void 0,r=n?u(n):"";if(r)switch(r){case m:return h;case v:return l;case g:return f;case y:return d;case _:return p}return t}),t.exports=b},{"./_DataView":5,"./_Map":8,"./_Promise":10,"./_Set":11,"./_WeakMap":16,"./_baseGetTag":34,"./_toSource":116}],73:[function(e,t,n){t.exports=function(e,t){return null==e?void 0:e[t]}},{}],74:[function(e,t,n){var c=e("./_castPath"),s=e("./isArguments"),u=e("./isArray"),l=e("./_isIndex"),f=e("./isLength"),d=e("./_toKey");t.exports=function(e,t,n){for(var r=-1,a=(t=c(t,e)).length,o=!1;++r<a;){var i=d(t[r]);if(!(o=null!=e&&n(e,i)))break;e=e[i]}return o||++r!=a?o:!!(a=null==e?0:e.length)&&f(a)&&l(i,a)&&(u(e)||s(e))}},{"./_castPath":55,"./_isIndex":80,"./_toKey":115,"./isArguments":128,"./isArray":129,"./isLength":134}],75:[function(e,t,n){var r=e("./_nativeCreate");t.exports=function(){this.__data__=r?r(null):{},this.size=0}},{"./_nativeCreate":100}],76:[function(e,t,n){t.exports=function(e){var t=this.has(e)&&delete this.__data__[e];return this.size-=t?1:0,t}},{}],77:[function(e,t,n){var r=e("./_nativeCreate"),a=Object.prototype.hasOwnProperty;t.exports=function(e){var t=this.__data__;if(r){var n=t[e];return"__lodash_hash_undefined__"===n?void 0:n}return a.call(t,e)?t[e]:void 0}},{"./_nativeCreate":100}],78:[function(e,t,n){var r=e("./_nativeCreate"),a=Object.prototype.hasOwnProperty;t.exports=function(e){var t=this.__data__;return r?void 0!==t[e]:a.call(t,e)}},{"./_nativeCreate":100}],79:[function(e,t,n){var r=e("./_nativeCreate");t.exports=function(e,t){var n=this.__data__;return this.size+=this.has(e)?0:1,n[e]=r&&void 0===t?"__lodash_hash_undefined__":t,this}},{"./_nativeCreate":100}],80:[function(e,t,n){var r=/^(?:0|[1-9]\d*)$/;t.exports=function(e,t){var n=_typeof(e);return!!(t=null==t?9007199254740991:t)&&("number"==n||"symbol"!=n&&r.test(e))&&-1<e&&e%1==0&&e<t}},{}],81:[function(e,t,n){var a=e("./eq"),o=e("./isArrayLike"),i=e("./_isIndex"),c=e("./isObject");t.exports=function(e,t,n){if(!c(n))return!1;var r=_typeof(t);return!!("number"==r?o(n)&&i(t,n.length):"string"==r&&t in n)&&a(n[t],e)}},{"./_isIndex":80,"./eq":118,"./isArrayLike":130,"./isObject":135}],82:[function(e,t,n){var r=e("./isArray"),a=e("./isSymbol"),o=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,i=/^\w*$/;t.exports=function(e,t){if(r(e))return!1;var n=_typeof(e);return!("number"!=n&&"symbol"!=n&&"boolean"!=n&&null!=e&&!a(e))||i.test(e)||!o.test(e)||null!=t&&e in Object(t)}},{"./isArray":129,"./isSymbol":139}],83:[function(e,t,n){t.exports=function(e){var t=_typeof(e);return"string"==t||"number"==t||"symbol"==t||"boolean"==t?"__proto__"!==e:null===e}},{}],84:[function(e,t,n){var r,a=e("./_coreJsData"),o=(r=/[^.]+$/.exec(a&&a.keys&&a.keys.IE_PROTO||""))?"Symbol(src)_1."+r:"";t.exports=function(e){return!!o&&o in e}},{"./_coreJsData":56}],85:[function(e,t,n){var r=Object.prototype;t.exports=function(e){var t=e&&e.constructor;return e===("function"==typeof t&&t.prototype||r)}},{}],86:[function(e,t,n){var r=e("./isObject");t.exports=function(e){return e==e&&!r(e)}},{"./isObject":135}],87:[function(e,t,n){t.exports=function(){this.__data__=[],this.size=0}},{}],88:[function(e,t,n){var r=e("./_assocIndexOf"),a=Array.prototype.splice;t.exports=function(e){var t=this.__data__,n=r(t,e);return!(n<0||(n==t.length-1?t.pop():a.call(t,n,1),--this.size,0))}},{"./_assocIndexOf":24}],89:[function(e,t,n){var r=e("./_assocIndexOf");t.exports=function(e){var t=this.__data__,n=r(t,e);return n<0?void 0:t[n][1]}},{"./_assocIndexOf":24}],90:[function(e,t,n){var r=e("./_assocIndexOf");t.exports=function(e){return-1<r(this.__data__,e)}},{"./_assocIndexOf":24}],91:[function(e,t,n){var a=e("./_assocIndexOf");t.exports=function(e,t){var n=this.__data__,r=a(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this}},{"./_assocIndexOf":24}],92:[function(e,t,n){var r=e("./_Hash"),a=e("./_ListCache"),o=e("./_Map");t.exports=function(){this.size=0,this.__data__={hash:new r,map:new(o||a),string:new r}}},{"./_Hash":6,"./_ListCache":7,"./_Map":8}],93:[function(e,t,n){var r=e("./_getMapData");t.exports=function(e){var t=r(this,e).delete(e);return this.size-=t?1:0,t}},{"./_getMapData":66}],94:[function(e,t,n){var r=e("./_getMapData");t.exports=function(e){return r(this,e).get(e)}},{"./_getMapData":66}],95:[function(e,t,n){var r=e("./_getMapData");t.exports=function(e){return r(this,e).has(e)}},{"./_getMapData":66}],96:[function(e,t,n){var a=e("./_getMapData");t.exports=function(e,t){var n=a(this,e),r=n.size;return n.set(e,t),this.size+=n.size==r?0:1,this}},{"./_getMapData":66}],97:[function(e,t,n){t.exports=function(e){var n=-1,r=Array(e.size);return e.forEach(function(e,t){r[++n]=[t,e]}),r}},{}],98:[function(e,t,n){t.exports=function(t,n){return function(e){return null!=e&&e[t]===n&&(void 0!==n||t in Object(e))}}},{}],99:[function(e,t,n){var r=e("./memoize");t.exports=function(e){var t=r(e,function(e){return 500===n.size&&n.clear(),e}),n=t.cache;return t}},{"./memoize":145}],100:[function(e,t,n){var r=e("./_getNative")(Object,"create");t.exports=r},{"./_getNative":68}],101:[function(e,t,n){var r=e("./_overArg")(Object.keys,Object);t.exports=r},{"./_overArg":104}],102:[function(e,t,n){var r=e("./_freeGlobal"),a="object"==_typeof(n)&&n&&!n.nodeType&&n,o=a&&"object"==_typeof(t)&&t&&!t.nodeType&&t,i=o&&o.exports===a&&r.process,c=function(){try{var e=o&&o.require&&o.require("util").types;return e||i&&i.binding&&i.binding("util")}catch(e){}}();t.exports=c},{"./_freeGlobal":64}],103:[function(e,t,n){var r=Object.prototype.toString;t.exports=function(e){return r.call(e)}},{}],104:[function(e,t,n){t.exports=function(t,n){return function(e){return t(n(e))}}},{}],105:[function(e,t,n){var r=e("./_freeGlobal"),a="object"==("undefined"==typeof self?"undefined":_typeof(self))&&self&&self.Object===Object&&self,o=r||a||Function("return this")();t.exports=o},{"./_freeGlobal":64}],106:[function(e,t,n){t.exports=function(e){return this.__data__.set(e,"__lodash_hash_undefined__"),this}},{}],107:[function(e,t,n){t.exports=function(e){return this.__data__.has(e)}},{}],108:[function(e,t,n){t.exports=function(e){var t=-1,n=Array(e.size);return e.forEach(function(e){n[++t]=e}),n}},{}],109:[function(e,t,n){var r=e("./_ListCache");t.exports=function(){this.__data__=new r,this.size=0}},{"./_ListCache":7}],110:[function(e,t,n){t.exports=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n}},{}],111:[function(e,t,n){t.exports=function(e){return this.__data__.get(e)}},{}],112:[function(e,t,n){t.exports=function(e){return this.__data__.has(e)}},{}],113:[function(e,t,n){var a=e("./_ListCache"),o=e("./_Map"),i=e("./_MapCache");t.exports=function(e,t){var n=this.__data__;if(n instanceof a){var r=n.__data__;if(!o||r.length<199)return r.push([e,t]),this.size=++n.size,this;n=this.__data__=new i(r)}return n.set(e,t),this.size=n.size,this}},{"./_ListCache":7,"./_Map":8,"./_MapCache":9}],114:[function(e,t,n){var r=e("./_memoizeCapped"),o=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,i=/\\(\\)?/g,a=r(function(e){var a=[];return 46===e.charCodeAt(0)&&a.push(""),e.replace(o,function(e,t,n,r){a.push(n?r.replace(i,"$1"):t||e)}),a});t.exports=a},{"./_memoizeCapped":99}],115:[function(e,t,n){var r=e("./isSymbol");t.exports=function(e){if("string"==typeof e||r(e))return e;var t=e+"";return"0"==t&&1/e==-1/0?"-0":t}},{"./isSymbol":139}],116:[function(e,t,n){var r=Function.prototype.toString;t.exports=function(e){if(null!=e){try{return r.call(e)}catch(e){}try{return e+""}catch(e){}}return""}},{}],117:[function(e,t,n){t.exports=function(e){for(var t=-1,n=null==e?0:e.length,r=0,a=[];++t<n;){var o=e[t];o&&(a[r++]=o)}return a}},{}],118:[function(e,t,n){t.exports=function(e,t){return e===t||e!=e&&t!=t}},{}],119:[function(e,t,n){var a=e("./_arrayEvery"),o=e("./_baseEvery"),i=e("./_baseIteratee"),c=e("./isArray"),s=e("./_isIterateeCall");t.exports=function(e,t,n){var r=c(e)?a:o;return n&&s(e,t,n)&&(t=void 0),r(e,i(t,3))}},{"./_arrayEvery":18,"./_baseEvery":27,"./_baseIteratee":43,"./_isIterateeCall":81,"./isArray":129}],120:[function(e,t,n){var r=e("./_arrayFilter"),a=e("./_baseFilter"),o=e("./_baseIteratee"),i=e("./isArray");t.exports=function(e,t){return(i(e)?r:a)(e,o(t,3))}},{"./_arrayFilter":19,"./_baseFilter":28,"./_baseIteratee":43,"./isArray":129}],121:[function(e,t,n){var r=e("./_createFind")(e("./findIndex"));t.exports=r},{"./_createFind":59,"./findIndex":122}],122:[function(e,t,n){var o=e("./_baseFindIndex"),i=e("./_baseIteratee"),c=e("./toInteger"),s=Math.max;t.exports=function(e,t,n){var r=null==e?0:e.length;if(!r)return-1;var a=null==n?0:c(n);return a<0&&(a=s(r+a,0)),o(e,i(t,3),a)}},{"./_baseFindIndex":29,"./_baseIteratee":43,"./toInteger":150}],123:[function(e,t,n){var r=e("./_arrayEach"),a=e("./_baseEach"),o=e("./_castFunction"),i=e("./isArray");t.exports=function(e,t){return(i(e)?r:a)(e,o(t))}},{"./_arrayEach":17,"./_baseEach":26,"./_castFunction":54,"./isArray":129}],124:[function(e,t,n){var a=e("./_baseGet");t.exports=function(e,t,n){var r=null==e?void 0:a(e,t);return void 0===r?n:r}},{"./_baseGet":32}],125:[function(e,t,n){var r=e("./_baseHas"),a=e("./_hasPath");t.exports=function(e,t){return null!=e&&a(e,t,r)}},{"./_baseHas":35,"./_hasPath":74}],126:[function(e,t,n){var r=e("./_baseHasIn"),a=e("./_hasPath");t.exports=function(e,t){return null!=e&&a(e,t,r)}},{"./_baseHasIn":36,"./_hasPath":74}],127:[function(e,t,n){t.exports=function(e){return e}},{}],128:[function(e,t,n){var r=e("./_baseIsArguments"),a=e("./isObjectLike"),o=Object.prototype,i=o.hasOwnProperty,c=o.propertyIsEnumerable,s=r(function(){return arguments}())?r:function(e){return a(e)&&i.call(e,"callee")&&!c.call(e,"callee")};t.exports=s},{"./_baseIsArguments":37,"./isObjectLike":136}],129:[function(e,t,n){var r=Array.isArray;t.exports=r},{}],130:[function(e,t,n){var r=e("./isFunction"),a=e("./isLength");t.exports=function(e){return null!=e&&a(e.length)&&!r(e)}},{"./isFunction":133,"./isLength":134}],131:[function(e,t,n){var r=e("./_root"),a=e("./stubFalse"),o="object"==_typeof(n)&&n&&!n.nodeType&&n,i=o&&"object"==_typeof(t)&&t&&!t.nodeType&&t,c=i&&i.exports===o?r.Buffer:void 0,s=(c?c.isBuffer:void 0)||a;t.exports=s},{"./_root":105,"./stubFalse":148}],132:[function(e,t,n){var r=e("./_baseIsEqual");t.exports=function(e,t){return r(e,t)}},{"./_baseIsEqual":38}],133:[function(e,t,n){var r=e("./_baseGetTag"),a=e("./isObject");t.exports=function(e){if(!a(e))return!1;var t=r(e);return"[object Function]"==t||"[object GeneratorFunction]"==t||"[object AsyncFunction]"==t||"[object Proxy]"==t}},{"./_baseGetTag":34,"./isObject":135}],134:[function(e,t,n){t.exports=function(e){return"number"==typeof e&&-1<e&&e%1==0&&e<=9007199254740991}},{}],135:[function(e,t,n){t.exports=function(e){var t=_typeof(e);return null!=e&&("object"==t||"function"==t)}},{}],136:[function(e,t,n){t.exports=function(e){return null!=e&&"object"==_typeof(e)}},{}],137:[function(e,t,n){var r=e("./_baseGetTag"),a=e("./_getPrototype"),o=e("./isObjectLike"),i=Function.prototype,c=Object.prototype,s=i.toString,u=c.hasOwnProperty,l=s.call(Object);t.exports=function(e){if(!o(e)||"[object Object]"!=r(e))return!1;var t=a(e);if(null===t)return!0;var n=u.call(t,"constructor")&&t.constructor;return"function"==typeof n&&n instanceof n&&s.call(n)==l}},{"./_baseGetTag":34,"./_getPrototype":69,"./isObjectLike":136}],138:[function(e,t,n){var r=e("./_baseGetTag"),a=e("./isArray"),o=e("./isObjectLike");t.exports=function(e){return"string"==typeof e||!a(e)&&o(e)&&"[object String]"==r(e)}},{"./_baseGetTag":34,"./isArray":129,"./isObjectLike":136}],139:[function(e,t,n){var r=e("./_baseGetTag"),a=e("./isObjectLike");t.exports=function(e){return"symbol"==_typeof(e)||a(e)&&"[object Symbol]"==r(e)}},{"./_baseGetTag":34,"./isObjectLike":136}],140:[function(e,t,n){var r=e("./_baseIsTypedArray"),a=e("./_baseUnary"),o=e("./_nodeUtil"),i=o&&o.isTypedArray,c=i?a(i):r;t.exports=c},{"./_baseIsTypedArray":42,"./_baseUnary":52,"./_nodeUtil":102}],141:[function(e,t,n){t.exports=function(e){return void 0===e}},{}],142:[function(e,t,n){var r=e("./_arrayLikeKeys"),a=e("./_baseKeys"),o=e("./isArrayLike");t.exports=function(e){return o(e)?r(e):a(e)}},{"./_arrayLikeKeys":20,"./_baseKeys":44,"./isArrayLike":130}],143:[function(e,t,n){var r=e("./_arrayMap"),a=e("./_baseIteratee"),o=e("./_baseMap"),i=e("./isArray");t.exports=function(e,t){return(i(e)?r:o)(e,a(t,3))}},{"./_arrayMap":21,"./_baseIteratee":43,"./_baseMap":45,"./isArray":129}],144:[function(e,t,n){var o=e("./_baseAssignValue"),i=e("./_baseForOwn"),c=e("./_baseIteratee");t.exports=function(e,r){var a={};return r=c(r,3),i(e,function(e,t,n){o(a,t,r(e,t,n))}),a}},{"./_baseAssignValue":25,"./_baseForOwn":31,"./_baseIteratee":43}],145:[function(e,t,n){var r=e("./_MapCache"),a="Expected a function";function c(o,i){if("function"!=typeof o||null!=i&&"function"!=typeof i)throw new TypeError(a);var e=function e(){var t=arguments,n=i?i.apply(this,t):t[0],r=e.cache;if(r.has(n))return r.get(n);var a=o.apply(this,t);return e.cache=r.set(n,a)||r,a};return e.cache=new(c.Cache||r),e}c.Cache=r,t.exports=c},{"./_MapCache":9}],146:[function(e,t,n){var r=e("./_baseProperty"),a=e("./_basePropertyDeep"),o=e("./_isKey"),i=e("./_toKey");t.exports=function(e){return o(e)?r(i(e)):a(e)}},{"./_baseProperty":48,"./_basePropertyDeep":49,"./_isKey":82,"./_toKey":115}],147:[function(e,t,n){t.exports=function(){return[]}},{}],148:[function(e,t,n){t.exports=function(){return!1}},{}],149:[function(e,t,n){var r=e("./toNumber");t.exports=function(e){return e?(e=r(e))!==1/0&&e!==-1/0?e==e?e:0:17976931348623157e292*(e<0?-1:1):0===e?e:0}},{"./toNumber":151}],150:[function(e,t,n){var r=e("./toFinite");t.exports=function(e){var t=r(e),n=t%1;return t==t?n?t-n:t:0}},{"./toFinite":149}],151:[function(e,t,n){var r=e("./isObject"),a=e("./isSymbol"),o=/^\s+|\s+$/g,i=/^[-+]0x[0-9a-f]+$/i,c=/^0b[01]+$/i,s=/^0o[0-7]+$/i,u=parseInt;t.exports=function(e){if("number"==typeof e)return e;if(a(e))return NaN;if(r(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=r(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(o,"");var n=c.test(e);return n||s.test(e)?u(e.slice(2),n?2:8):i.test(e)?NaN:+e}},{"./isObject":135,"./isSymbol":139}],152:[function(e,t,n){var r=e("./_baseToString");t.exports=function(e){return null==e?"":r(e)}},{"./_baseToString":51}],153:[function(e,a,t){!function(){var e=this;function t(e,t){var n,r,a,o,i,c,s,u;for(n=3&e.length,r=e.length-n,a=t,i=3432918353,c=461845907,u=0;u<r;)s=255&e.charCodeAt(u)|(255&e.charCodeAt(++u))<<8|(255&e.charCodeAt(++u))<<16|(255&e.charCodeAt(++u))<<24,++u,a=27492+(65535&(o=5*(65535&(a=(a^=s=(65535&(s=(s=(65535&s)*i+(((s>>>16)*i&65535)<<16)&4294967295)<<15|s>>>17))*c+(((s>>>16)*c&65535)<<16)&4294967295)<<13|a>>>19))+((5*(a>>>16)&65535)<<16)&4294967295))+((58964+(o>>>16)&65535)<<16);switch(s=0,n){case 3:s^=(255&e.charCodeAt(u+2))<<16;case 2:s^=(255&e.charCodeAt(u+1))<<8;case 1:a^=s=(65535&(s=(s=(65535&(s^=255&e.charCodeAt(u)))*i+(((s>>>16)*i&65535)<<16)&4294967295)<<15|s>>>17))*c+(((s>>>16)*c&65535)<<16)&4294967295}return a^=e.length,a=2246822507*(65535&(a^=a>>>16))+((2246822507*(a>>>16)&65535)<<16)&4294967295,a=3266489909*(65535&(a^=a>>>13))+((3266489909*(a>>>16)&65535)<<16)&4294967295,(a^=a>>>16)>>>0}var n=t;if(n.v2=function(e,t){for(var n,r=e.length,a=t^r,o=0;4<=r;)n=1540483477*(65535&(n=255&e.charCodeAt(o)|(255&e.charCodeAt(++o))<<8|(255&e.charCodeAt(++o))<<16|(255&e.charCodeAt(++o))<<24))+((1540483477*(n>>>16)&65535)<<16),a=1540483477*(65535&a)+((1540483477*(a>>>16)&65535)<<16)^(n=1540483477*(65535&(n^=n>>>24))+((1540483477*(n>>>16)&65535)<<16)),r-=4,++o;switch(r){case 3:a^=(255&e.charCodeAt(o+2))<<16;case 2:a^=(255&e.charCodeAt(o+1))<<8;case 1:a=1540483477*(65535&(a^=255&e.charCodeAt(o)))+((1540483477*(a>>>16)&65535)<<16)}return a=1540483477*(65535&(a^=a>>>13))+((1540483477*(a>>>16)&65535)<<16),(a^=a>>>15)>>>0},n.v3=t,void 0!==a)a.exports=n;else{var r=e.murmur;n.noConflict=function(){return e.murmur=r,n},e.murmur=n}}()},{}],154:[function(e,t,n){var y,_,r,a;y=e("crypt"),_=e("charenc").utf8,r=e("charenc").bin,(a=function(e,t){var n=y.wordsToBytes(function(e){e.constructor==String&&(e=_.stringToBytes(e));var t=y.bytesToWords(e),n=8*e.length,r=[],a=1732584193,o=-271733879,i=-1732584194,c=271733878,s=-1009589776;t[n>>5]|=128<<24-n%32,t[15+(n+64>>>9<<4)]=n;for(var u=0;u<t.length;u+=16){for(var l=a,f=o,d=i,p=c,h=s,m=0;m<80;m++){if(m<16)r[m]=t[u+m];else{var v=r[m-3]^r[m-8]^r[m-14]^r[m-16];r[m]=v<<1|v>>>31}var g=(a<<5|a>>>27)+s+(r[m]>>>0)+(m<20?1518500249+(o&i|~o&c):m<40?1859775393+(o^i^c):m<60?(o&i|o&c|i&c)-1894007588:(o^i^c)-899497514);s=c,c=i,i=o<<30|o>>>2,o=a,a=g}a+=l,o+=f,i+=d,c+=p,s+=h}return[a,o,i,c,s]}(e));return t&&t.asBytes?n:t&&t.asString?r.bytesToString(n):y.bytesToHex(n)})._blocksize=16,a._digestsize=20,t.exports=a},{charenc:2,crypt:3}],155:[function(e,t,n){Object.defineProperty(n,"__esModule",{value:!0});var r=e("./lib/core");n.trackerCore=r.trackerCore},{"./lib/core":158}],156:[function(e,t,n){function r(e){var t,n,r,a,o,i,c,s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",u=0,l=0,f="",d=[];if(!e)return e;for(e+="";t=(i=s.indexOf(e.charAt(u++))<<18|s.indexOf(e.charAt(u++))<<12|(a=s.indexOf(e.charAt(u++)))<<6|(o=s.indexOf(e.charAt(u++))))>>16&255,n=i>>8&255,r=255&i,d[l++]=64===a?String.fromCharCode(t):64===o?String.fromCharCode(t,n):String.fromCharCode(t,n,r),u<e.length;);return f=d.join(""),c=f.replace(/\0+$/,""),decodeURIComponent(c.split("").map(function(e){return"%"+("00"+e.charCodeAt(0).toString(16)).slice(-2)}).join(""))}Object.defineProperty(n,"__esModule",{value:!0}),n.base64urldecode=function(e){if(!e)return e;switch(4-e.length%4){case 2:e+="==";break;case 3:e+="="}return r(e.replace(/-/g,"+").replace(/_/g,"/"))},n.base64encode=function(e){var t,n,r,a,o,i,c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",s=0,u=0,l=[];if(!e)return e;for(e=unescape(encodeURIComponent(e));t=(o=e.charCodeAt(s++)<<16|e.charCodeAt(s++)<<8|e.charCodeAt(s++))>>18&63,n=o>>12&63,r=o>>6&63,a=63&o,l[u++]=c.charAt(t)+c.charAt(n)+c.charAt(r)+c.charAt(a),s<e.length;);i=l.join("");var f=e.length%3;return(f?i.slice(0,f-3):i)+"===".slice(f||3)},n.base64decode=r},{}],157:[function(e,t,n){var r=this&&this.__assign||Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var a in t=arguments[n])Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e};Object.defineProperty(n,"__esModule",{value:!0});var a=e("./payload"),o=e("./base64"),s=e("lodash/isEqual"),i=e("lodash/has"),c=e("lodash/get"),u=e("lodash/isPlainObject"),l=e("lodash/every"),f=e("lodash/compact"),d=e("lodash/map");function p(e){var t=new RegExp("^iglu:([a-zA-Z0-9-_.]+)/([a-zA-Z0-9-_]+)/jsonschema/([1-9][0-9]*)-(0|[1-9][0-9]*)-(0|[1-9][0-9]*)$").exec(e);if(null!==t)return t.slice(1,6)}function h(e){if("*"===e[0]||"*"===e[1])return!1;if(0<e.slice(2).length){for(var t=!1,n=0,r=e.slice(2);n<r.length;n++){if("*"===r[n])t=!0;else if(t)return!1}return!0}return 2==e.length}function m(e){var t=e.split(".");return!!(t&&1<t.length)&&h(t)}function v(e){var t=new RegExp("^iglu:((?:(?:[a-zA-Z0-9-_]+|\\*).)+(?:[a-zA-Z0-9-_]+|\\*))/([a-zA-Z0-9-_.]+|\\*)/jsonschema/([1-9][0-9]*|\\*)-(0|[1-9][0-9]*|\\*)-(0|[1-9][0-9]*|\\*)$").exec(e);if(null!==t&&m(t[1]))return t.slice(1,6)}function g(e){var t=v(e);if(t){var n=t[0];return 5===t.length&&m(n)}return!1}function y(e){return Array.isArray(e)&&e.every(function(e){return"string"==typeof e})}function _(e){return y(e)?e.every(function(e){return g(e)}):"string"==typeof e&&g(e)}function b(e){return!!(a.isNonEmptyJson(e)&&"schema"in e&&"data"in e)&&("string"==typeof e.schema&&"object"===_typeof(e.data))}function w(e){return!!(a.isNonEmptyJson(e)&&"e"in e)&&"string"==typeof e.e}function k(e){var t=0;if(u(e)){if(i(e,"accept")){if(!_(e.accept))return!1;t+=1}if(i(e,"reject")){if(!_(e.reject))return!1;t+=1}return 0<t&&t<=2}return!1}function A(e){return"function"==typeof e&&e.length<=1}function x(e){return"function"==typeof e&&e.length<=1}function C(e){return A(e)||b(e)}function S(e){return!(!Array.isArray(e)||2!==e.length)&&(Array.isArray(e[1])?x(e[0])&&l(e[1],C):x(e[0])&&C(e[1]))}function j(e){return!(!Array.isArray(e)||2!==e.length)&&(!!k(e[0])&&(Array.isArray(e[1])?l(e[1],C):C(e[1])))}function T(e){return S(e)||j(e)}function O(e,t){if(!g(e))return!1;var n=v(e),r=p(t);if(n&&r){if(!P(n[0],r[0]))return!1;for(var a=1;a<5;a++)if(!I(n[a],r[a]))return!1;return!0}return!1}function P(e,t){var n=t.split("."),r=e.split(".");if(n&&r){if(n.length!==r.length)return!1;for(var a=0;a<r.length;a++)if(!I(n[a],r[a]))return!1;return!0}return!1}function I(e,t){return e&&t&&"*"===e||e===t}function E(e,t){var n=0,r=0,a=c(e,"accept");Array.isArray(a)?e.accept.some(function(e){return O(e,t)})&&r++:"string"==typeof a&&O(a,t)&&r++;var o=c(e,"reject");return Array.isArray(o)?e.reject.some(function(e){return O(e,t)})&&n++:"string"==typeof o&&O(o,t)&&n++,0<r&&0===n}function L(e){return"string"==typeof c(e,"ue_px.data.schema")?c(e,"ue_px.data.schema"):"string"==typeof c(e,"ue_pr.data.schema")?c(e,"ue_pr.data.schema"):"string"==typeof c(e,"schema")?c(e,"schema"):""}function D(e){var t=r({},e);try{i(t,"ue_px")&&(t.ue_px=JSON.parse(o.base64urldecode(c(t,["ue_px"]))))}catch(e){}return t}function M(e){return c(e,"e","")}function N(e,t,n,r){var a=void 0;try{return b(a=e({event:t,eventType:n,eventSchema:r}))?a:Array.isArray(a)&&l(a,b)?a:void 0}catch(e){a=void 0}return a}function F(e){return Array.isArray(e)?e:Array.of(e)}function z(e,n,r,a){var t=F(e),o=d(t,function(e){var t=U(e,n,r,a);if(t&&0!==t.length)return t});return[].concat.apply([],f(o))}function U(e,t,n,r){if(b(e))return[e];if(A(e)){var a=N(e,t,n,r);if(b(a))return[a];if(Array.isArray(a))return a}}function B(e,t,n,r){if(S(e)){var a=e[0],o=!1;try{o=a({event:t,eventType:n,eventSchema:r})}catch(e){o=!1}if(!0===o)return z(e[1],t,n,r)}else if(j(e)&&E(e[0],r))return z(e[1],t,n,r);return[]}function G(e,n,r,a){var t=F(e),o=d(t,function(e){var t=B(e,n,r,a);if(t&&0!==t.length)return t});return[].concat.apply([],f(o))}n.getSchemaParts=p,n.validateVendorParts=h,n.validateVendor=m,n.getRuleParts=v,n.isValidRule=g,n.isStringArray=y,n.isValidRuleSetArg=_,n.isSelfDescribingJson=b,n.isEventJson=w,n.isRuleSet=k,n.isContextGenerator=A,n.isContextFilter=x,n.isContextPrimitive=C,n.isFilterProvider=S,n.isRuleSetProvider=j,n.isConditionalContextProvider=T,n.matchSchemaAgainstRule=O,n.matchVendor=P,n.matchPart=I,n.matchSchemaAgainstRuleSet=E,n.getUsefulSchema=L,n.getDecodedEvent=D,n.getEventType=M,n.buildGenerator=N,n.normalizeToArray=F,n.generatePrimitives=z,n.evaluatePrimitive=U,n.evaluateProvider=B,n.generateConditionals=G,n.contextModule=function(){var i=[],c=[];return{getGlobalPrimitives:function(){return i},getConditionalProviders:function(){return c},addGlobalContexts:function(e){for(var t=[],n=[],r=0,a=e;r<a.length;r++){var o=a[r];T(o)?t.push(o):C(o)&&n.push(o)}i=i.concat(n),c=c.concat(t)},clearGlobalContexts:function(){c=[],i=[]},removeGlobalContexts:function(e){for(var t=function(t){T(t)?c=c.filter(function(e){return!s(e,t)}):C(t)&&(i=i.filter(function(e){return!s(e,t)}))},n=0,r=e;n<r.length;n++)t(r[n])},getApplicableContexts:function(e){var t=e.build();return w(t)?function(e){var t=L(e),n=M(e),r=[],a=z(i,e,n,t);r.push.apply(r,a);var o=G(c,e,n,t);return r.push.apply(r,o),r}(D(t)):[]}}}},{"./base64":156,"./payload":159,"lodash/compact":117,"lodash/every":119,"lodash/get":124,"lodash/has":125,"lodash/isEqual":132,"lodash/isPlainObject":137,"lodash/map":143}],158:[function(e,t,n){Object.defineProperty(n,"__esModule",{value:!0});var u=e("uuid"),m=e("./payload"),r=e("./contexts");n.trackerCore=function(d,i){void 0===d&&(d=!0);var c={},o=r.contextModule();function n(e,t){c[e]=t}function f(e,t){var n={};for(var r in t=t||{},e)(t[r]||null!==e[r]&&void 0!==e[r])&&(n[r]=e[r]);return n}function s(e,t){var n,r=(n=e,o.getApplicableContexts(n)),a=[];return t&&t.length&&a.push.apply(a,t),r&&r.length&&a.push.apply(a,r),a}function p(e,t,n){e.addDict(c),e.add("eid",u.v4());var r,a=null==(r=n)?{type:"dtm",value:(new Date).getTime()}:"number"==typeof r?{type:"dtm",value:r}:"ttm"===r.type?{type:"ttm",value:r.value}:{type:"dtm",value:r.value||(new Date).getTime()};e.add(a.type,a.value.toString());var o=function(e){if(e&&e.length)return{schema:"iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0",data:e}}(s(e,t));return void 0!==o&&e.addJson("cx","co",o),"function"==typeof i&&i(e),e}function h(e,t,n){var r=m.payloadBuilder(d),a={schema:"iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0",data:e};return r.add("e","ue"),r.addJson("ue_px","ue_pr",a),p(r,t,n)}return{setBase64Encoding:function(e){d=e},addPayloadPair:n,addPayloadDict:function(e){for(var t in e)e.hasOwnProperty(t)&&(c[t]=e[t])},resetPayloadPairs:function(e){c=m.isJson(e)?e:{}},setTrackerVersion:function(e){n("tv",e)},setTrackerNamespace:function(e){n("tna",e)},setAppId:function(e){n("aid",e)},setPlatform:function(e){n("p",e)},setUserId:function(e){n("uid",e)},setScreenResolution:function(e,t){n("res",e+"x"+t)},setViewport:function(e,t){n("vp",e+"x"+t)},setColorDepth:function(e){n("cd",e)},setTimezone:function(e){n("tz",e)},setLang:function(e){n("lang",e)},setIpAddress:function(e){n("ip",e)},trackUnstructEvent:h,trackSelfDescribingEvent:h,trackPageView:function(e,t,n,r,a){var o=m.payloadBuilder(d);return o.add("e","pv"),o.add("url",e),o.add("page",t),o.add("refr",n),p(o,r,a)},trackPagePing:function(e,t,n,r,a,o,i,c,s){var u=m.payloadBuilder(d);return u.add("e","pp"),u.add("url",e),u.add("page",t),u.add("refr",n),u.add("pp_mix",r.toString()),u.add("pp_max",a.toString()),u.add("pp_miy",o.toString()),u.add("pp_may",i.toString()),p(u,c,s)},trackStructEvent:function(e,t,n,r,a,o,i){var c=m.payloadBuilder(d);return c.add("e","se"),c.add("se_ca",e),c.add("se_ac",t),c.add("se_la",n),c.add("se_pr",r),c.add("se_va",null==a?void 0:a.toString()),p(c,o,i)},trackEcommerceTransaction:function(e,t,n,r,a,o,i,c,s,u,l){var f=m.payloadBuilder(d);return f.add("e","tr"),f.add("tr_id",e),f.add("tr_af",t),f.add("tr_tt",n),f.add("tr_tx",r),f.add("tr_sh",a),f.add("tr_ci",o),f.add("tr_st",i),f.add("tr_co",c),f.add("tr_cu",s),p(f,u,l)},trackEcommerceTransactionItem:function(e,t,n,r,a,o,i,c,s){var u=m.payloadBuilder(d);return u.add("e","ti"),u.add("ti_id",e),u.add("ti_sk",t),u.add("ti_nm",n),u.add("ti_ca",r),u.add("ti_pr",a),u.add("ti_qu",o),u.add("ti_cu",i),p(u,c,s)},trackScreenView:function(e,t,n,r){return h({schema:"iglu:com.snowplowanalytics.snowplow/screen_view/jsonschema/1-0-0",data:f({name:e,id:t})},n,r)},trackLinkClick:function(e,t,n,r,a,o,i){return h({schema:"iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1",data:f({targetUrl:e,elementId:t,elementClasses:n,elementTarget:r,elementContent:a})},o,i)},trackAdImpression:function(e,t,n,r,a,o,i,c,s,u){return h({schema:"iglu:com.snowplowanalytics.snowplow/ad_impression/jsonschema/1-0-0",data:f({impressionId:e,costModel:t,cost:n,targetUrl:r,bannerId:a,zoneId:o,advertiserId:i,campaignId:c})},s,u)},trackAdClick:function(e,t,n,r,a,o,i,c,s,u,l){return h({schema:"iglu:com.snowplowanalytics.snowplow/ad_click/jsonschema/1-0-0",data:f({targetUrl:e,clickId:t,costModel:n,cost:r,bannerId:a,zoneId:o,impressionId:i,advertiserId:c,campaignId:s})},u,l)},trackAdConversion:function(e,t,n,r,a,o,i,c,s,u,l){return h({schema:"iglu:com.snowplowanalytics.snowplow/ad_conversion/jsonschema/1-0-0",data:f({conversionId:e,costModel:t,cost:n,category:r,action:a,property:o,initialValue:i,advertiserId:c,campaignId:s})},u,l)},trackSocialInteraction:function(e,t,n,r,a){return h({schema:"iglu:com.snowplowanalytics.snowplow/social_interaction/jsonschema/1-0-0",data:f({action:e,network:t,target:n})},r,a)},trackAddToCart:function(e,t,n,r,a,o,i,c){return h({schema:"iglu:com.snowplowanalytics.snowplow/add_to_cart/jsonschema/1-0-0",data:f({sku:e,name:t,category:n,unitPrice:r,quantity:a,currency:o})},i,c)},trackRemoveFromCart:function(e,t,n,r,a,o,i,c){return h({schema:"iglu:com.snowplowanalytics.snowplow/remove_from_cart/jsonschema/1-0-0",data:f({sku:e,name:t,category:n,unitPrice:r,quantity:a,currency:o})},i,c)},trackFormFocusOrChange:function(e,t,n,r,a,o,i,c,s){var u="";return"change_form"===e?u="iglu:com.snowplowanalytics.snowplow/change_form/jsonschema/1-0-0":"focus_form"===e&&(u="iglu:com.snowplowanalytics.snowplow/focus_form/jsonschema/1-0-0"),h({schema:u,data:f({formId:t,elementId:n,nodeName:r,type:a,elementClasses:o,value:i},{value:!0})},c,s)},trackFormSubmission:function(e,t,n,r,a){return h({schema:"iglu:com.snowplowanalytics.snowplow/submit_form/jsonschema/1-0-0",data:f({formId:e,formClasses:t,elements:n})},r,a)},trackSiteSearch:function(e,t,n,r,a,o){return h({schema:"iglu:com.snowplowanalytics.snowplow/site_search/jsonschema/1-0-0",data:f({terms:e,filters:t,totalResults:n,pageResults:r})},a,o)},trackConsentWithdrawn:function(e,t,n,r,a,o,i){var c={schema:"iglu:com.snowplowanalytics.snowplow/consent_document/jsonschema/1-0-0",data:f({id:t,version:n,name:r,description:a})};return h({schema:"iglu:com.snowplowanalytics.snowplow/consent_withdrawn/jsonschema/1-0-0",data:f({all:e})},c.data&&o?o.concat([c]):o,i)},trackConsentGranted:function(e,t,n,r,a,o,i){var c={schema:"iglu:com.snowplowanalytics.snowplow/consent_document/jsonschema/1-0-0",data:f({id:e,version:t,name:n,description:r})};return h({schema:"iglu:com.snowplowanalytics.snowplow/consent_granted/jsonschema/1-0-0",data:f({expiry:a})},o?o.concat([c]):[c],i)},addGlobalContexts:function(e){o.addGlobalContexts(e)},clearGlobalContexts:function(){o.clearGlobalContexts()},removeGlobalContexts:function(e){o.removeGlobalContexts(e)}}}},{"./contexts":157,"./payload":159,uuid:161}],159:[function(e,t,n){Object.defineProperty(n,"__esModule",{value:!0});var c=e("./base64");function s(e){if(!r(e))return!1;for(var t in e)if(e.hasOwnProperty(t))return!0;return!1}function r(e){return null!=e&&(e.constructor==={}.constructor||e.constructor===[].constructor)}n.isNonEmptyJson=s,n.isJson=r,n.payloadBuilder=function(o){var n={},i=function(e,t){null!=t&&""!==t&&(n[e]=t)};return{add:i,addDict:function(e){for(var t in e)e.hasOwnProperty(t)&&i(t,e[t])},addJson:function(e,t,n){if(s(n)){var r=JSON.stringify(n);o?i(e,(a=r)?c.base64encode(a).replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_"):a):i(t,r)}var a},build:function(){return n}}}},{"./base64":156}],160:[function(e,o,t){(function(e){var t,n=e.crypto||e.msCrypto;if(n&&n.getRandomValues){var r=new Uint8Array(16);t=function(){return n.getRandomValues(r),r}}if(!t){var a=new Array(16);t=function(){for(var e,t=0;t<16;t++)0==(3&t)&&(e=4294967296*Math.random()),a[t]=e>>>((3&t)<<3)&255;return a}}o.exports=t}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],161:[function(e,t,n){for(var i=e("./rng"),a=[],o={},r=0;r<256;r++)a[r]=(r+256).toString(16).substr(1),o[a[r]]=r;function p(e,t){var n=t||0,r=a;return r[e[n++]]+r[e[n++]]+r[e[n++]]+r[e[n++]]+"-"+r[e[n++]]+r[e[n++]]+"-"+r[e[n++]]+r[e[n++]]+"-"+r[e[n++]]+r[e[n++]]+"-"+r[e[n++]]+r[e[n++]]+r[e[n++]]+r[e[n++]]+r[e[n++]]+r[e[n++]]}var c=i(),h=[1|c[0],c[1],c[2],c[3],c[4],c[5]],m=16383&(c[6]<<8|c[7]),v=0,g=0;function s(e,t,n){var r=t&&n||0;"string"==typeof e&&(t="binary"==e?new Array(16):null,e=null);var a=(e=e||{}).random||(e.rng||i)();if(a[6]=15&a[6]|64,a[8]=63&a[8]|128,t)for(var o=0;o<16;o++)t[r+o]=a[o];return t||p(a)}var u=s;u.v1=function(e,t,n){var r=t&&n||0,a=t||[],o=void 0!==(e=e||{}).clockseq?e.clockseq:m,i=void 0!==e.msecs?e.msecs:(new Date).getTime(),c=void 0!==e.nsecs?e.nsecs:g+1,s=i-v+(c-g)/1e4;if(s<0&&void 0===e.clockseq&&(o=o+1&16383),(s<0||v<i)&&void 0===e.nsecs&&(c=0),1e4<=c)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");v=i,m=o;var u=(1e4*(268435455&(i+=122192928e5))+(g=c))%4294967296;a[r++]=u>>>24&255,a[r++]=u>>>16&255,a[r++]=u>>>8&255,a[r++]=255&u;var l=i/4294967296*1e4&268435455;a[r++]=l>>>8&255,a[r++]=255&l,a[r++]=l>>>24&15|16,a[r++]=l>>>16&255,a[r++]=o>>>8|128,a[r++]=255&o;for(var f=e.node||h,d=0;d<6;d++)a[r+d]=f[d];return t||p(a)},u.v4=s,u.parse=function(e,t,n){var r=t&&n||0,a=0;for(t=t||[],e.toLowerCase().replace(/[0-9a-f]{2}/g,function(e){a<16&&(t[r+a++]=o[e])});a<16;)t[r+a++]=0;return t},u.unparse=p,t.exports=u},{"./rng":160}],162:[function(e,t,n){var u=e("lodash/isFunction"),r=e("./lib/helpers"),a=window;(void 0!==n?n:this).errorManager=function(c){function s(e,t,n,r,a,o){var i=a&&a.stack?a.stack:null;c.trackSelfDescribingEvent({schema:"iglu:com.snowplowanalytics.snowplow/application_error/jsonschema/1-0-1",data:{programmingLanguage:"JAVASCRIPT",message:e||"JS Exception. Browser doesn't support ErrorEvent API",stackTrace:i,lineNumber:n,lineColumn:r,fileName:t}},o)}return{trackError:s,enableErrorTracking:function(o,i,c){r.addEventListener(a,"error",function(e){var t,n,r,a;(u(o)&&o(e)||null==o)&&(t=e,n=c,a=u(r=i)?n.concat(r(t)):n,s(t.message,t.filename,t.lineno,t.colno,t.error,a))},!0)}}}},{"./lib/helpers":168,"lodash/isFunction":133}],163:[function(e,t,n){var p=e("lodash/forEach"),h=e("lodash/filter"),m=e("lodash/find"),v=e("./lib/helpers");(void 0!==n?n:this).getFormTrackingManager=function(i,e,c){var s=["textarea","input","select"],u=e+"form",r=function(){return!0},a=function(){return!0},l=function(e){return e};function f(t){return t[m(["name","id","type","nodeName"],function(e){return t[e]&&"string"==typeof t[e]})]}function o(a,o){return function(e){var t=e.target,n=t.nodeName&&"INPUT"===t.nodeName.toUpperCase()?t.type:null,r="checkbox"!==t.type||t.checked?l(t.value):null;("change_form"===a||"checkbox"!==n&&"radio"!==n)&&i.trackFormFocusOrChange(a,function(e){for(;e&&e.nodeName&&"HTML"!==e.nodeName.toUpperCase()&&"FORM"!==e.nodeName.toUpperCase();)e=e.parentNode;if(e&&e.nodeName&&"FORM"===e.nodeName.toUpperCase())return f(e)}(t),f(t),t.nodeName,n,v.getCssClasses(t),r,c(v.resolveDynamicContexts(o,t,n,r)))}}function d(o){return function(e){var n,r,t=e.target,a=(n=t,r=[],p(s,function(e){var t=h(n.getElementsByTagName(e),function(e){return e.hasOwnProperty(u)});p(t,function(e){if("submit"!==e.type){var t={name:f(e),value:e.value,nodeName:e.nodeName};e.type&&"INPUT"===e.nodeName.toUpperCase()&&(t.type=e.type),"checkbox"!==e.type&&"radio"!==e.type||e.checked||(t.value=null),r.push(t)}})}),r);p(a,function(e){e.value=l(e.value)}),i.trackFormSubmission(f(t),v.getCssClasses(t),a,c(v.resolveDynamicContexts(o,t,a)))}}return{configureFormTracking:function(e){e&&(r=v.getFilter(e.forms,!0),a=v.getFilter(e.fields,!1),l=v.getTransform(e.fields))},addFormListeners:function(n){p(document.getElementsByTagName("form"),function(t){r(t)&&!t[u]&&(p(s,function(e){p(t.getElementsByTagName(e),function(e){a(e)&&!e[u]&&"password"!==e.type.toLowerCase()&&(v.addEventListener(e,"focus",o("focus_form",n),!1),v.addEventListener(e,"change",o("change_form",n),!1),e[u]=!0)})}),v.addEventListener(t,"submit",d(n)),t[u]=!0)})}}}},{"./lib/helpers":168,"lodash/filter":120,"lodash/find":121,"lodash/forEach":123}],164:[function(e,t,n){n.productionize=function(a){var o={};return"object"===_typeof(a)&&null!==a&&Object.getOwnPropertyNames(a).forEach(function(e,t,n){var r;"function"==typeof a[e]&&(o[e]=(r=a[e],function(){try{return r.apply(this,arguments)}catch(e){}}))}),o}},{}],165:[function(e,t,n){!function(){var c=e("lodash/map"),v=e("lodash/isUndefined"),g=e("lodash/isFunction"),y=e("./lib/helpers");(void 0!==n?n:this).InQueueManager=function(r,a,o,e,i){var p={};function h(e){var t=[];if(e&&0!==e.length)for(var n=0;n<e.length;n++)p.hasOwnProperty(e[n])?t.push(p[e[n]]):y.warn('Warning: Tracker namespace "'+e[n]+'" not configured');else t=c(p);return 0===t.length&&y.warn("Warning: No tracker configured"),t}function m(e,t,n){n=n||{},p.hasOwnProperty(e)?y.warn("Tracker namespace "+e+" already exists."):(p[e]=new r(i,e,a,o,n),p[e].setCollectorUrl(t))}function t(){var e,t,n,r,a,o,i,c,s,u,l,f,d;for(e=0;e<arguments.length;e+=1)if(r=arguments[e],a=Array.prototype.shift.call(r),g(a))a.apply(p,r);else if(d=void 0,i=(o=[(d=a.split(":"))[0],1<d.length?d[1].split(";"):[]])[1],"newTracker"!==(n=o[0]))if("setCollectorCf"!==n&&"setCollectorUrl"!==n||i&&0!==i.length)for(c=h(i),t=0;t<c.length;t++)c[t][n].apply(c[t],r);else s=n,u=r[0],l=r[1],f=void 0,y.warn(s+" is deprecated. Set the collector when a new tracker instance using newTracker."),m(f=v(l)?"sp":l),p[f][s](u);else m(r[0],r[1],r[2])}for(var n=0;n<e.length;n++)t(e[n]);return{push:t}}}()},{"./lib/helpers":168,"lodash/isFunction":133,"lodash/isUndefined":141,"lodash/map":143}],166:[function(e,t,n){var r,a,o=e("./snowplow"),i=window;i.GlobalSnowplowNamespace&&0<i.GlobalSnowplowNamespace.length?(r=i.GlobalSnowplowNamespace.shift(),(a=i[r]).q=new o.Snowplow(a.q,r)):(i._snaq=i._snaq||[],i._snaq=new o.Snowplow(i._snaq,"_snaq"))},{"./snowplow":172}],167:[function(t,e,r){!function(){var i=t("lodash/isFunction"),c=t("lodash/isUndefined"),s=t("murmurhash").v3,e=t("jstimezonedetect").jstz.determine(),n=t("browser-cookie-lite"),u=void 0!==r?r:this,l=window,f=navigator,d=screen,o=document;u.hasSessionStorage=function(){try{return!!l.sessionStorage}catch(e){return!0}},u.hasLocalStorage=function(){try{return!!l.localStorage}catch(e){return!0}},u.localStorageAccessible=function(){var e="modernizr";if(!u.hasLocalStorage())return!1;try{return l.localStorage.setItem(e,e),l.localStorage.removeItem(e),!0}catch(e){return!1}},u.hasCookies=function(e){var t=e||"testcookie";return c(f.cookieEnabled)?(n.cookie(t,"1"),"1"===n.cookie(t)?"1":"0"):f.cookieEnabled?"1":"0"},u.detectSignature=function(e){var t=[f.userAgent,[d.height,d.width,d.colorDepth].join("x"),(new Date).getTimezoneOffset(),u.hasSessionStorage(),u.hasLocalStorage()],n=[];if(f.plugins)for(var r=0;r<f.plugins.length;r++)if(f.plugins[r]){for(var a=[],o=0;o<f.plugins[r].length;o++)a.push([f.plugins[r][o].type,f.plugins[r][o].suffixes]);n.push([f.plugins[r].name+"::"+f.plugins[r].description,a.join("~")])}return s(t.join("###")+"###"+n.sort().join(";"),e)},u.detectTimezone=function(){return void 0===e?"":e.name()},u.detectViewport=function(){var e=l,t="inner";"innerWidth"in l||(t="client",e=o.documentElement||o.body);var n=e[t+"Width"],r=e[t+"Height"];return 0<=n&&0<=r?n+"x"+r:null},u.detectDocumentSize=function(){var e=o.documentElement,t=o.body,n=t?Math.max(t.offsetHeight,t.scrollHeight):0,r=Math.max(e.clientWidth,e.offsetWidth,e.scrollWidth),a=Math.max(e.clientHeight,e.offsetHeight,e.scrollHeight,n);return isNaN(r)||isNaN(a)?"":r+"x"+a},u.detectBrowserFeatures=function(e,t){var n,r,a={pdf:"application/pdf",qt:"video/quicktime",realp:"audio/x-pn-realaudio-plugin",wma:"application/x-mplayer2",dir:"application/x-director",fla:"application/x-shockwave-flash",java:"application/x-java-vm",gears:"application/x-googlegears",ag:"application/x-silverlight"},o={};if(f.mimeTypes&&f.mimeTypes.length)for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(r=f.mimeTypes[a[n]],o[n]=r&&r.enabledPlugin?"1":"0");return f.constructor===window.Navigator&&"unknown"!=typeof f.javaEnabled&&!c(f.javaEnabled)&&f.javaEnabled()&&(o.java="1"),i(l.GearsFactory)&&(o.gears="1"),o.res=d.width+"x"+d.height,o.cd=d.colorDepth,e&&(o.cookie=u.hasCookies(t)),o}}()},{"browser-cookie-lite":1,jstimezonedetect:4,"lodash/isFunction":133,"lodash/isUndefined":141,murmurhash:153}],168:[function(e,t,o){!function(){var n=e("lodash/isString"),r=e("lodash/isUndefined"),i=e("lodash/isObject"),a=e("lodash/map"),s=e("browser-cookie-lite"),u=void 0!==o?o:this;u.fixupTitle=function(e){if(!n(e)){e=e.text||"";var t=document.getElementsByTagName("title");t&&!r(t[0])&&(e=t[0].text)}return e},u.getHostName=function(e){var t=new RegExp("^(?:(?:https?|ftp):)/*(?:[^@]+@)?([^:/#]+)").exec(e);return t?t[1]:e},u.fixupDomain=function(e){var t=e.length;return"."===e.charAt(--t)&&(e=e.slice(0,t)),"*."===e.slice(0,2)&&(e=e.slice(1)),e},u.getReferrer=function(e){var t="",n=u.fromQuerystring("referrer",window.location.href)||u.fromQuerystring("referer",window.location.href);if(n)return n;if(e)return e;try{t=window.top.document.referrer}catch(e){if(window.parent)try{t=window.parent.document.referrer}catch(e){t=""}}return""===t&&(t=document.referrer),t},u.addEventListener=function(e,t,n,r){return e.addEventListener?(e.addEventListener(t,n,r),!0):e.attachEvent?e.attachEvent("on"+t,n):void(e["on"+t]=n)},u.fromQuerystring=function(e,t){var n=new RegExp("^[^#]*[?&]"+e+"=([^&#]*)").exec(t);return n?decodeURIComponent(n[1].replace(/\+/g," ")):null},u.resolveDynamicContexts=function(e){var t=Array.prototype.slice.call(arguments,1);return a(e,function(e){if("function"!=typeof e)return e;try{return e.apply(null,t)}catch(e){}})},u.warn=function(e){"undefined"!=typeof console&&console.warn("Snowplow: "+e)},u.getCssClasses=function(e){return e.className.match(/\S+/g)||[]},u.getFilter=function(e,t){if(Array.isArray(e)||!i(e))return function(){return!0};if(e.hasOwnProperty("filter"))return e.filter;var n=e.hasOwnProperty("whitelist"),r=e.whitelist||e.blacklist;Array.isArray(r)||(r=[r]);for(var a={},o=0;o<r.length;o++)a[r[o]]=!0;return t?function(e){return function(e,t){var n,r=u.getCssClasses(e);for(n=0;n<r.length;n++)if(t[r[n]])return!0;return!1}(e,a)===n}:function(e){return e.name in a===n}},u.getTransform=function(e){return i(e)?e.hasOwnProperty("transform")?e.transform:function(e){return e}:function(e){return e}},u.decorateQuerystring=function(e,t,n){var r=t+"="+n,a=e.split("#"),o=a[0].split("?"),i=o.shift(),c=o.join("?");if(c){for(var s=!0,u=c.split("&"),l=0;l<u.length;l++)if(u[l].substr(0,t.length+1)===t+"="){s=!1,u[l]=r,c=u.join("&");break}s&&(c=r+"&"+c)}else c=r;return a[0]=i+"?"+c,a.join("#")},u.attemptGetLocalStorage=function(e){try{return localStorage.getItem(e)}catch(e){}},u.attemptWriteLocalStorage=function(e,t){try{return localStorage.setItem(e,t),!0}catch(e){return!1}},u.findRootDomain=function(){for(var e="_sp_root_domain_test_",t=e+(new Date).getTime(),n="_test_value_"+(new Date).getTime(),r=window.location.hostname.split("."),a=r.length-1;0<=a;){var o=r.slice(a,r.length).join(".");if(s.cookie(t,n,0,"/",o),s.cookie(t)===n){u.deleteCookie(t,o);for(var i=u.getCookiesWithPrefix(e),c=0;c<i.length;c++)u.deleteCookie(i[c],o);return o}a-=1}return window.location.hostname},u.isValueInArray=function(e,t){for(var n=0;n<t.length;n++)if(t[n]===e)return!0;return!1},u.deleteCookie=function(e,t){s.cookie(e,"",-1,"/",t)},u.getCookiesWithPrefix=function(e){for(var t=document.cookie.split("; "),n=[],r=0;r<t.length;r++)t[r].substring(0,e.length)===e&&n.push(t[r]);return n},u.parseInt=function(e){var t=parseInt(e);return isNaN(t)?void 0:t},u.parseFloat=function(e){var t=parseFloat(e);return isNaN(t)?void 0:t}}()},{"browser-cookie-lite":1,"lodash/isObject":135,"lodash/isString":138,"lodash/isUndefined":141,"lodash/map":143}],169:[function(e,t,n){!function(){var i=e("./helpers");function c(e){var t,n,r;if(r=e,new RegExp("^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$").test(r))try{return t=document.body.children[0].children[0].children[0].children[0].children[0].children[0].innerHTML,n="You have reached the cached page for",t.slice(0,n.length)===n}catch(e){return!1}}(void 0!==n?n:this).fixupUrl=function(e,t,n){var r,a,o;return"translate.googleusercontent.com"===e?(""===n&&(n=t),r=t,a="u",o=new RegExp("^(?:https?|ftp)(?::/*(?:[^?]+))([?][^#]+)").exec(r),t=i.fromQuerystring(a,o[1]),e=i.getHostName(t)):("cc.bingj.com"===e||"webcache.googleusercontent.com"===e||c(e))&&(t=document.links[0].href,e=i.getHostName(t)),[e,t,n]}}()},{"./helpers":168}],170:[function(e,t,n){var h=e("lodash/isUndefined"),m=e("./lib/helpers");(void 0!==n?n:this).getLinkTrackingManager=function(f,r,d){var a,o,p,i,c,s;function u(e,t){for(var n,r,a,o,i,c;null!==(n=e.parentNode)&&!h(n)&&"A"!==(r=e.tagName.toUpperCase())&&"AREA"!==r;)e=n;if(!h(e.href)){var s=e.hostname||m.getHostName(e.href),u=s.toLowerCase(),l=e.href.replace(s,u);new RegExp("^(javascript|vbscript|jscript|mocha|livescript|ecmascript|mailto):","i").test(l)||(a=e.id,o=m.getCssClasses(e),i=e.target,c=p?e.innerHTML:null,l=unescape(l),f.trackLinkClick(l,a,o,i,c,d(m.resolveDynamicContexts(t,e))))}}function l(r){return function(e){var t,n;t=(e=e||window.event).which||e.button,n=e.target||e.srcElement,"click"===e.type?n&&u(n,r):"mousedown"===e.type?1!==t&&2!==t||!n?c=s=null:(c=t,s=n):"mouseup"===e.type&&(t===c&&n===s&&u(n,r),c=s=null)}}return{configureLinkClickTracking:function(e,t,n,r){p=n,i=r,o=t,a=m.getFilter(e,!0)},addClickListeners:function(){var e,t,n=document.links;for(e=0;e<n.length;e++)a(n[e])&&!n[e][r]&&(t=n[e],o?(m.addEventListener(t,"mouseup",l(i),!1),m.addEventListener(t,"mousedown",l(i),!1)):m.addEventListener(t,"click",l(i),!1),n[e][r]=!0)}}}},{"./lib/helpers":168,"lodash/isUndefined":141}],171:[function(e,t,n){!function(){var b=e("lodash/mapValues"),w=e("lodash/isString"),k=e("lodash/map"),A=e("./lib/detectors").localStorageAccessible,x=e("./lib/helpers");(void 0!==n?n:this).OutQueueManager=function(e,t,n,s,r,a,o,u){var l,f,d,p=!1,i=null===(r=r.toLowerCase?r.toLowerCase():r)||!0===r||"beacon"===r||"true"===r,h=Boolean(i&&navigator&&navigator.sendBeacon)&&i,m=("post"===r||h)&&!("get"===r),c=(m=m&&Boolean(window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest))?a:"/i";if(o=A()&&s&&m&&o||1,l=["snowplowOutQueue",e,t,m?"post2":"get"].join("_"),s)try{d=JSON.parse(localStorage.getItem(l))}catch(e){}function v(){for(;d.length&&"string"!=typeof d[0]&&"object"!==_typeof(d[0]);)d.shift();if(d.length<1)p=!1;else{if(!w(f))throw"No Snowplow collector configured, cannot track";p=!0;var e=d[0];if(m){var t=g(f),n=setTimeout(function(){t.abort(),p=!1},5e3),r=function(e){for(var t=0,n=0;t<e.length&&(n+=e[t].bytes,!(u<=n));)t+=1;return t}(d);t.onreadystatechange=function(){if(4===t.readyState&&200<=t.status&&t.status<400){for(var e=0;e<r;e++)d.shift();s&&x.attemptWriteLocalStorage(l,JSON.stringify(d)),clearTimeout(n),v()}else 4===t.readyState&&400<=t.status&&(clearTimeout(n),p=!1)};var a=k(d.slice(0,r),function(e){return e.evt});if(0<a.length){var o;if(h){var i=new Blob([y(_(a))],{type:"application/json"});o=navigator.sendBeacon(f,i)}h&&o||t.send(y(_(a)))}}else{var c=new Image(1,1);c.onload=function(){d.shift(),s&&x.attemptWriteLocalStorage(l,JSON.stringify(d)),v()},c.onerror=function(){p=!1},c.src=f+e.replace("?","?stm="+(new Date).getTime()+"&")}}}function g(e){var t=new XMLHttpRequest;return t.open("POST",e,!0),t.withCredentials=!0,t.setRequestHeader("Content-Type","application/json; charset=UTF-8"),t}function y(e){return JSON.stringify({schema:"iglu:com.snowplowanalytics.snowplow/payload_data/jsonschema/1-0-4",data:e})}function _(e){for(var t=(new Date).getTime().toString(),n=0;n<e.length;n++)e[n].stm=t;return e}return Array.isArray(d)||(d=[]),n.outQueues.push(d),m&&1<o&&n.bufferFlushers.push(function(){p||v()}),{enqueueRequest:function(e,t){if(f=t+c,m){var n={evt:r=b(e,function(e){return e.toString()}),bytes:function(e){for(var t=0,n=0;n<e.length;n++){var r=e.charCodeAt(n);r<=127?t+=1:r<=2047?t+=2:55296<=r&&r<=57343?(t+=4,n++):t+=r<65535?3:4}return t}(JSON.stringify(r))};if(u<=n.bytes)return x.warn("Event of size "+n.bytes+" is too long - the maximum size is "+u),void g(f).send(y(_([n.evt])));d.push(n)}else d.push(function(e){var t="?",n={co:!0,cx:!0},r=!0;for(var a in e)e.hasOwnProperty(a)&&!n.hasOwnProperty(a)&&(r?r=!1:t+="&",t+=encodeURIComponent(a)+"="+encodeURIComponent(e[a]));for(var o in n)e.hasOwnProperty(o)&&n.hasOwnProperty(o)&&(t+="&"+o+"="+encodeURIComponent(e[o]));return t}(e));var r,a=!1;s&&(a=x.attemptWriteLocalStorage(l,JSON.stringify(d))),p||a&&!(d.length>=o)||v()},executeQueue:v}}}()},{"./lib/detectors":167,"./lib/helpers":168,"lodash/isString":138,"lodash/map":143,"lodash/mapValues":144}],172:[function(e,t,n){!function(){e("uuid");var s=e("lodash/forEach"),u=e("lodash/filter"),l=e("./lib/helpers"),f=e("./in_queue"),d=e("./tracker");(void 0!==n?n:this).Snowplow=function(e,n){var t,r=document,a=window,o="js-2.10.0",i={outQueues:[],bufferFlushers:[],expireDateTime:null,hasLoaded:!1,registeredOnLoadHandlers:[],pageViewId:null};function c(){var e;if(!i.hasLoaded)for(i.hasLoaded=!0,e=0;e<i.registeredOnLoadHandlers.length;e++)i.registeredOnLoadHandlers[e]();return!0}return a.Snowplow={getTrackerCf:function(e){var t=new d.Tracker(n,"",o,i,{});return t.setCollectorCf(e),t},getTrackerUrl:function(e){var t=new d.Tracker(n,"",o,i,{});return t.setCollectorUrl(e),t},getAsyncTracker:function(){return new d.Tracker(n,"",o,i,{})}},l.addEventListener(a,"beforeunload",function(){var e;if(s(i.bufferFlushers,function(e){e()}),i.expireDateTime)do{if(e=new Date,0===u(i.outQueues,function(e){return 0<e.length}).length)break}while(e.getTime()<i.expireDateTime)},!1),r.addEventListener?l.addEventListener(r,"DOMContentLoaded",function e(){r.removeEventListener("DOMContentLoaded",e,!1),c()}):r.attachEvent&&(r.attachEvent("onreadystatechange",function e(){"complete"===r.readyState&&(r.detachEvent("onreadystatechange",e),c())}),r.documentElement.doScroll&&a===a.top&&function t(){if(!i.hasLoaded){try{r.documentElement.doScroll("left")}catch(e){return void setTimeout(t,0)}c()}}()),new RegExp("WebKit").test(navigator.userAgent)&&(t=setInterval(function(){(i.hasLoaded||/loaded|complete/.test(r.readyState))&&(clearInterval(t),c())},10)),l.addEventListener(a,"load",c,!1),new f.InQueueManager(d.Tracker,o,i,e,n)}}()},{"./in_queue":165,"./lib/helpers":168,"./tracker":173,"lodash/filter":120,"lodash/forEach":123,uuid:161}],173:[function(e,t,n){!function(){var Xe=e("lodash/forEach"),et=e("lodash/map"),tt=e("./lib/helpers"),nt=e("./lib/proxies"),rt=e("browser-cookie-lite"),at=e("./lib/detectors"),ot=e("sha1"),it=e("./links"),ct=e("./forms"),st=e("./errors"),ut=e("./out_queue"),lt=e("snowplow-tracker-core").trackerCore,ft=e("./guard").productionize,dt=e("uuid");(void 0!==n?n:this).Tracker=function(e,t,n,s,r){(r=r||{}).hasOwnProperty("post")?r.eventMethod=!0===r.post?"post":"get":r.eventMethod=r.eventMethod||"beacon";var u,h,a,m,l,f,d,o,v,i,p,g,y,_,b,c,w,k,A,x,C,S,j=lt(!0,function(e){!function(e){var t,n=Math.round((new Date).getTime()/1e3),r=Pe("id"),a=Pe("ses"),o=Ie("ses"),i=Ge(),c=i[0],s=i[1],u=i[2],l=i[3],f=i[4],d=i[5],p=i[6];t=!!v&&!!rt.cookie(v);if((Q||t)&&"none"!=ae)return"localStorage"==ae?(tt.attemptWriteLocalStorage(r,""),tt.attemptWriteLocalStorage(a,"")):"cookie"!=ae&&"cookieAndLocalStorage"!=ae||(rt.cookie(r,"",-1,J,K),rt.cookie(a,"",-1,J,K));"0"===c?(k=p,o||"none"==ae||(l++,d=f,k=dt.v4()),de=l):(new Date).getTime()-le>1e3*Y&&(k=dt.v4(),de++);e.add("vp",at.detectViewport()),e.add("ds",at.detectDocumentSize()),e.add("vid",de),e.add("sid",k),e.add("duid",s),e.add("fp",ce),e.add("uid",A),Ce(),e.add("refr",Te(h||z)),e.add("url",Te(m||F)),"none"!=ae&&(Ue(s,u,de,n,d,k),ze());le=(new Date).getTime()}(e),function(e,t){var n,r=new Date;n=!!v&&!!rt.cookie(v);Q||n||(ge.enqueueRequest(e.build(),a),s.expireDateTime=r.getTime()+t)}(e,R)}),T=!1,O={},P={},I={},E=document,L=window,D=navigator,M=nt.fixupUrl(E.domain,L.location.href,tt.getReferrer()),N=tt.fixupDomain(M[0]),F=M[1],z=M[2],U=r.hasOwnProperty("platform")?r.platform:"web",B=r.hasOwnProperty("postPath")?r.postPath:"/com.snowplowanalytics.snowplow/tp2",G=r.hasOwnProperty("appId")?r.appId:"",q=E.title,R=r.hasOwnProperty("pageUnloadTimer")?r.pageUnloadTimer:500,H=!1,V=r.hasOwnProperty("cookieName")?r.cookieName:"_sp_",K=r.hasOwnProperty("cookieDomain")?r.cookieDomain:null,J="/",W=D.doNotTrack||D.msDoNotTrack||L.doNotTrack,Q=!!r.hasOwnProperty("respectDoNotTrack")&&(r.respectDoNotTrack&&("yes"===W||"1"===W)),$=r.hasOwnProperty("cookieLifetime")?r.cookieLifetime:63072e3,Y=r.hasOwnProperty("sessionCookieTimeout")?r.sessionCookieTimeout:1800,Z=r.hasOwnProperty("userFingerprintSeed")?r.userFingerprintSeed:123412414,X=E.characterSet||E.charset,ee=!!r.hasOwnProperty("forceSecureTracker")&&!0===r.forceSecureTracker,te=!(ee||!r.hasOwnProperty("forceUnsecureTracker"))&&!0===r.forceUnsecureTracker,ne=!r.hasOwnProperty("useLocalStorage")||(tt.warn("argmap.useLocalStorage is deprecated. Use argmap.stateStorageStrategy instead."),r.useLocalStorage),re=!r.hasOwnProperty("useCookies")||(tt.warn("argmap.useCookies is deprecated. Use argmap.stateStorageStrategy instead."),r.useCookies),ae=r.hasOwnProperty("stateStorageStrategy")?r.stateStorageStrategy:re||ne?re&&ne?"cookieAndLocalStorage":re?"cookie":"localStorage":"none",oe=D.userLanguage||D.language,ie=at.detectBrowserFeatures("cookie"==ae||"cookieAndLocalStorage"==ae,Pe("testcookie")),ce=!1===r.userFingerprint?"":at.detectSignature(Z),se=e+"_"+t,ue=!1,le=(new Date).getTime(),fe=ot,de=1,pe={transaction:{},items:[]},he=it.getLinkTrackingManager(j,se,Re),me=ct.getFormTrackingManager(j,se,Re),ve=st.errorManager(j),ge=new ut.OutQueueManager(e,t,s,"localStorage"==ae||"cookieAndLocalStorage"==ae,r.eventMethod,B,r.bufferSize,r.maxPostBytes||4e4),ye=!1,_e=r.contexts||{},be=[],we=[],ke=!1,Ae=!1;for(var xe in r.hasOwnProperty("discoverRootDomain")&&r.discoverRootDomain&&(K=tt.findRootDomain()),_e.gaCookies&&be.push((x={},Xe(["__utma","__utmb","__utmc","__utmv","__utmz","_ga"],function(e){var t=rt.cookie(e);t&&(x[e]=t)}),{schema:"iglu:com.google.analytics/cookies/jsonschema/1-0-0",data:x})),_e.geolocation&&Je(),j.setBase64Encoding(!r.hasOwnProperty("encodeBase64")||r.encodeBase64),j.setTrackerVersion(n),j.setTrackerNamespace(t),j.setAppId(G),j.setPlatform(U),j.setTimezone(at.detectTimezone()),j.addPayloadPair("lang",oe),j.addPayloadPair("cs",X),ie)Object.prototype.hasOwnProperty.call(ie,xe)&&("res"===xe||"cd"===xe||"cookie"===xe?j.addPayloadPair(xe,ie[xe]):j.addPayloadPair("f_"+xe,ie[xe]));function Ce(){(M=nt.fixupUrl(E.domain,L.location.href,tt.getReferrer()))[1]!==F&&(z=tt.getReferrer(F)),N=tt.fixupDomain(M[0]),F=M[1]}function Se(){var e=(new Date).getTime();this.href&&(this.href=tt.decorateQuerystring(this.href,"_sp",w+"."+e))}function je(e){for(var t=0;t<E.links.length;t++){var n=E.links[t];!n.spDecorationEnabled&&e(n)&&(tt.addEventListener(n,"click",Se,!0),tt.addEventListener(n,"mousedown",Se,!0),n.spDecorationEnabled=!0)}}function Te(e){var t;return o?(t=new RegExp("#.*"),e.replace(t,"")):e}function Oe(e){var t=new RegExp("^([a-z]+):").exec(e);return t?t[1]:null}function Pe(e){return V+e+"."+c}function Ie(e){var t=Pe(e);return"localStorage"==ae?tt.attemptGetLocalStorage(t):"cookie"==ae||"cookieAndLocalStorage"==ae?rt.cookie(t):void 0}function Ee(){Ce(),c=fe((K||N)+(J||"/")).slice(0,4)}function Le(){var e=new Date;p=e.getTime()}function De(){!function(){var e=Me(),t=e[0];t<g?g=t:y<t&&(y=t);var n=e[1];n<_?_=n:b<n&&(b=n)}(),Le()}function Me(){var e=E.compatMode&&"BackCompat"!==E.compatMode?E.documentElement:E.body;return[e.scrollLeft||L.pageXOffset,e.scrollTop||L.pageYOffset]}function Ne(){var e=Me(),t=e[0];y=g=t;var n=e[1];b=_=n}function Fe(e){var t=Math.round(e);if(!isNaN(t))return t}function ze(){Be(Pe("ses"),"*",Y)}function Ue(e,t,n,r,a,o){Be(Pe("id"),e+"."+t+"."+n+"."+r+"."+a+"."+o,$)}function Be(e,t,n){"localStorage"==ae?tt.attemptWriteLocalStorage(e,t):"cookie"!=ae&&"cookieAndLocalStorage"!=ae||rt.cookie(e,t,n,J,K)}function Ge(){if("none"==ae)return[];var e,t=new Date,n=Math.round(t.getTime()/1e3),r=Ie("id");return r?(e=r.split(".")).unshift("0"):e=["1",w,n,0,n,""],e[6]||(e[6]=dt.v4()),e}function qe(e){return ee?"https://"+e:te?"http://"+e:("https:"===E.location.protocol?"https":"http")+"://"+e}function Re(e){var t,n,r,a,o,i=be.concat(e||[]);if(_e.webPage&&i.push({schema:"iglu:com.snowplowanalytics.snowplow/web_page/jsonschema/1-0-0",data:{id:He()}}),_e.performanceTiming){var c=function(){var e=["navigationStart","redirectStart","redirectEnd","fetchStart","domainLookupStart","domainLookupEnd","connectStart","secureConnectionStart","connectEnd","requestStart","responseStart","responseEnd","unloadEventStart","unloadEventEnd","domLoading","domInteractive","domContentLoadedEventStart","domContentLoadedEventEnd","domComplete","loadEventStart","loadEventEnd","msFirstPaint","chromeFirstPaint","requestEnd","proxyStart","proxyEnd"],t=L.performance||L.mozPerformance||L.msPerformance||L.webkitPerformance;if(t){var n={};for(var r in t.timing)tt.isValueInArray(r,e)&&null!==t.timing[r]&&(n[r]=t.timing[r]);return delete n.requestEnd,L.chrome&&L.chrome.loadTimes&&"number"==typeof L.chrome.loadTimes().firstPaintTime&&(n.chromeFirstPaint=Math.round(1e3*L.chrome.loadTimes().firstPaintTime)),{schema:"iglu:org.w3/PerformanceTiming/jsonschema/1-0-0",data:n}}}();c&&i.push(c)}if(L.optimizely){if(_e.optimizelySummary){var s=et((a=Ve("state"),o=Ve("experiments"),et(a&&o&&a.activeExperiments,function(e){var t=o[e];return{activeExperimentId:e.toString(),variation:a.variationIdsMap[e][0].toString(),conditional:t&&t.conditional,manual:t&&t.manual,name:t&&t.name}})),function(e){return{schema:"iglu:com.optimizely.snowplow/optimizely_summary/jsonschema/1-0-0",data:e}});Xe(s,function(e){i.push(e)})}if(_e.optimizelyXSummary){s=et((t=Ke("state"),n=t.getActiveExperimentIds(),Ke("data","experiments"),r=Ke("visitor"),et(n,function(e){return variation=t.getVariationMap()[e],variationName=variation.name,variationId=variation.id,visitorId=r.visitorId,{experimentId:parseInt(e),variationName:variationName,variation:parseInt(variationId),visitorId:visitorId}})),function(e){return{schema:"iglu:com.optimizely.optimizelyx/summary/jsonschema/1-0-0",data:e}});Xe(s,function(e){i.push(e)})}if(_e.optimizelyExperiments)for(var u=function(){var e=Ve("experiments");if(e){var t=[];for(var n in e)if(e.hasOwnProperty(n)){var r={};r.id=n;var a=e[n];r.code=a.code,r.manual=a.manual,r.conditional=a.conditional,r.name=a.name,r.variationIds=a.variation_ids,t.push({schema:"iglu:com.optimizely/experiment/jsonschema/1-0-0",data:r})}return t}return[]}(),l=0;l<u.length;l++)i.push(u[l]);if(_e.optimizelyStates){var f=function(){var e=[],t=Ve("experiments");if(t)for(var n in t)t.hasOwnProperty(n)&&e.push(n);var r=Ve("state");if(r){for(var a=[],o=r.activeExperiments||[],i=0;i<e.length;i++){var c=e[i],s={};s.experimentId=c,s.isActive=tt.isValueInArray(e[i],o);var u=r.variationMap||{};s.variationIndex=u[c];var l=r.variationNamesMap||{};s.variationName=l[c];var f=r.variationIdsMap||{};f[c]&&1===f[c].length&&(s.variationId=f[c][0]),a.push({schema:"iglu:com.optimizely/state/jsonschema/1-0-0",data:s})}return a}return[]}();for(l=0;l<f.length;l++)i.push(f[l])}if(_e.optimizelyVariations){var d=function(){var e=Ve("variations");if(e){var t=[];for(var n in e)if(e.hasOwnProperty(n)){var r={};r.id=n;var a=e[n];r.name=a.name,r.code=a.code,t.push({schema:"iglu:com.optimizely/variation/jsonschema/1-0-0",data:r})}return t}return[]}();for(l=0;l<d.length;l++)i.push(d[l])}if(_e.optimizelyVisitor){var p=function(){var e=Ve("visitor");if(e){var t={};t.browser=e.browser,t.browserVersion=e.browserVersion,t.device=e.device,t.deviceType=e.deviceType,t.ip=e.ip;var n=e.platform||{};t.platformId=n.id,t.platformVersion=n.version;var r=e.location||{};return t.locationCity=r.city,t.locationRegion=r.region,t.locationCountry=r.country,t.mobile=e.mobile,t.mobileId=e.mobileId,t.referrer=e.referrer,t.os=e.os,{schema:"iglu:com.optimizely/visitor/jsonschema/1-0-0",data:t}}}();p&&i.push(p)}if(_e.optimizelyAudiences){var h=function(){var e=Ve("visitor","audiences");if(e){var t=[];for(var n in e)if(e.hasOwnProperty(n)){var r={id:n,isMember:e[n]};t.push({schema:"iglu:com.optimizely/visitor_audience/jsonschema/1-0-0",data:r})}return t}return[]}();for(l=0;l<h.length;l++)i.push(h[l])}if(_e.optimizelyDimensions){var m=function(){var e=Ve("visitor","dimensions");if(e){var t=[];for(var n in e)if(e.hasOwnProperty(n)){var r={id:n,value:e[n]};t.push({schema:"iglu:com.optimizely/visitor_dimension/jsonschema/1-0-0",data:r})}return t}return[]}();for(l=0;l<m.length;l++)i.push(m[l])}}if(_e.augurIdentityLite){var v=function(){var e=L.augur;if(e){var t={consumer:{},device:{}},n=e.consumer||{};t.consumer.UUID=n.UID;var r=e.device||{};t.device.ID=r.ID,t.device.isBot=r.isBot,t.device.isProxied=r.isProxied,t.device.isTor=r.isTor;var a=r.fingerprint||{};return t.device.isIncognito=a.browserHasIncognitoEnabled,{schema:"iglu:io.augur.snowplow/identity_lite/jsonschema/1-0-0",data:t}}}();v&&i.push(v)}if(_e.parrable){var g=function(){var e=window._hawk;if(e){var t={encryptedId:null,optout:null};t.encryptedId=e.browserid;var n=new RegExp("(?:^|;)\\s?"+"_parrable_hawk_optout".replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")+"=(.*?)(?:;|$)","i"),r=document.cookie.match(n);return t.optout=r&&decodeURIComponent(r[1])?r&&decodeURIComponent(r[1]):"false",{schema:"iglu:com.parrable/encrypted_payload/jsonschema/1-0-0",data:t}}}();g&&i.push(g)}return i}function He(){return null==s.pageViewId&&(s.pageViewId=dt.v4()),s.pageViewId}function Ve(e,t){var n;return L.optimizely&&L.optimizely.data&&(n=L.optimizely.data[e],void 0!==t&&void 0!==n&&(n=n[t])),n}function Ke(e,t){var n;return L.optimizely&&(n=L.optimizely.get(e),void 0!==t&&void 0!==n&&(n=n[t])),n}function Je(){!ye&&D.geolocation&&D.geolocation.getCurrentPosition&&(ye=!0,D.geolocation.getCurrentPosition(function(e){var t=e.coords,n={schema:"iglu:com.snowplowanalytics.snowplow/geolocation_context/jsonschema/1-1-0",data:{latitude:t.latitude,longitude:t.longitude,latitudeLongitudeAccuracy:t.accuracy,altitude:t.altitude,altitudeAccuracy:t.altitudeAccuracy,bearing:t.heading,speed:t.speed,timestamp:Math.round(e.timestamp)}};be.push(n)}))}function We(e,t){return(e||[]).concat(t?t():[])}function Qe(e,t,n,r){Ce(),Ae&&(ke&&null!=s.pageViewId||(s.pageViewId=dt.v4())),Ae=!0,q=E.title,l=e;var a=tt.fixupTitle(l||q);j.trackPageView(Te(m||F),a,Te(h||z),Re(We(t,n)),r);var o=new Date;if(H&&!ue){ue=!0;var i={update:function(){if("undefined"!=typeof window&&"function"==typeof window.addEventListener){var e=!1,t=Object.defineProperty({},"passive",{get:function(){e=!0}}),n=function(){};window.addEventListener("testPassiveEventSupport",n,t),window.removeEventListener("testPassiveEventSupport",n,t),i.hasSupport=e}}};i.update();var c="onwheel"in document.createElement("div")?"wheel":void 0!==document.onmousewheel?"mousewheel":"DOMMouseScroll";Object.prototype.hasOwnProperty.call(i,"hasSupport")?tt.addEventListener(E,c,Le,{passive:!0}):tt.addEventListener(E,c,Le),Ne(),tt.addEventListener(E,"click",Le),tt.addEventListener(E,"mouseup",Le),tt.addEventListener(E,"mousedown",Le),tt.addEventListener(E,"mousemove",Le),tt.addEventListener(L,"scroll",De),tt.addEventListener(E,"keypress",Le),tt.addEventListener(E,"keydown",Le),tt.addEventListener(E,"keyup",Le),tt.addEventListener(L,"resize",Le),tt.addEventListener(L,"focus",Le),tt.addEventListener(L,"blur",Le),p=o.getTime(),clearInterval(u),u=setInterval(function(){var e=new Date;p+d>e.getTime()&&f<e.getTime()&&function(e){Ce();var t=E.title;t!==q&&(q=t,l=null);j.trackPagePing(Te(m||F),tt.fixupTitle(l||q),Te(h||z),Fe(g),Fe(y),Fe(_),Fe(b),Re(e)),Ne()}(We(t,n))},d)}}function $e(e,t){return""!==e?e+t.charAt(0).toUpperCase()+t.slice(1):t}function Ye(t){var e,n,r,a=["","webkit","ms","moz"];if(!i)for(n=0;n<a.length;n++){if(E[$e(r=a[n],"hidden")]){"prerender"===E[$e(r,"visibilityState")]&&(e=!0);break}if(!1===E[$e(r,"hidden")])break}e?tt.addEventListener(E,r+"visibilitychange",function e(){E.removeEventListener(r+"visibilitychange",e,!1),t()}):t()}function Ze(){I=T?O:P}return Ee(),C="none"!=ae&&!!Ie("ses"),(S=Ge())[1]?w=S[1]:(w=dt.v4(),S[1]=w),k=S[6],C||(S[3]++,k=dt.v4(),S[6]=k,S[5]=S[4]),"none"!=ae&&(ze(),S[4]=Math.round((new Date).getTime()/1e3),S.shift(),Ue.apply(null,S)),r.crossDomainLinker&&je(r.crossDomainLinker),O.getDomainSessionIndex=function(){return de},O.getPageViewId=function(){return He()},O.newSession=function(){var e=Math.round((new Date).getTime()/1e3),t=(Ie("ses"),Ge()),n=t[0],r=t[1],a=t[2],o=t[3],i=t[4],c=t[5],s=t[6];"0"===n?(k=s,"none"!=ae&&(o++,c=i,k=dt.v4()),de=o,ze()):(k=dt.v4(),de++),"none"!=ae&&(Ue(r,a,de,e,c,k),ze()),le=(new Date).getTime()},O.getCookieName=function(e){return Pe(e)},O.getUserId=function(){return A},O.getDomainUserId=function(){return Ge()[1]},O.getDomainUserInfo=function(){return Ge()},O.getUserFingerprint=function(){return ce},O.setAppId=function(e){tt.warn('setAppId is deprecated. Instead add an "appId" field to the argmap argument of newTracker.'),j.setAppId(e)},O.setReferrerUrl=function(e){h=e},O.setCustomUrl=function(e){var t,n,r;Ce(),t=F,m=Oe(n=e)?n:"/"===n.slice(0,1)?Oe(t)+"://"+tt.getHostName(t)+n:(0<=(r=(t=Te(t)).indexOf("?"))&&(t=t.slice(0,r)),(r=t.lastIndexOf("/"))!==t.length-1&&(t=t.slice(0,r+1)),t+n)},O.setDocumentTitle=function(e){q=E.title,l=e},O.discardHashTag=function(e){o=e},O.setCookieNamePrefix=function(e){tt.warn('setCookieNamePrefix is deprecated. Instead add a "cookieName" field to the argmap argument of newTracker.'),V=e},O.setCookieDomain=function(e){tt.warn('setCookieDomain is deprecated. Instead add a "cookieDomain" field to the argmap argument of newTracker.'),K=tt.fixupDomain(e),Ee()},O.setCookiePath=function(e){J=e,Ee()},O.setVisitorCookieTimeout=function(e){$=e},O.setSessionCookieTimeout=function(e){tt.warn('setSessionCookieTimeout is deprecated. Instead add a "sessionCookieTimeout" field to the argmap argument of newTracker.'),Y=e},O.setUserFingerprintSeed=function(e){tt.warn('setUserFingerprintSeed is deprecated. Instead add a "userFingerprintSeed" field to the argmap argument of newTracker.'),Z=e,ce=at.detectSignature(Z)},O.enableUserFingerprint=function(e){tt.warn('enableUserFingerprintSeed is deprecated. Instead add a "userFingerprint" field to the argmap argument of newTracker.'),e||(ce="")},O.respectDoNotTrack=function(e){tt.warn('This usage of respectDoNotTrack is deprecated. Instead add a "respectDoNotTrack" field to the argmap argument of newTracker.');var t=D.doNotTrack||D.msDoNotTrack;Q=e&&("yes"===t||"1"===t)},O.crossDomainLinker=function(e){je(e)},O.enableLinkClickTracking=function(e,t,n,r){s.hasLoaded?(he.configureLinkClickTracking(e,t,n,r),he.addClickListeners()):s.registeredOnLoadHandlers.push(function(){he.configureLinkClickTracking(e,t,n,r),he.addClickListeners()})},O.refreshLinkClickTracking=function(){s.hasLoaded?he.addClickListeners():s.registeredOnLoadHandlers.push(function(){he.addClickListeners()})},O.enableActivityTracking=function(e,t){e===parseInt(e,10)&&t===parseInt(t,10)?(H=!0,f=(new Date).getTime()+1e3*e,d=1e3*t):tt.warn("Activity tracking not enabled, please provide integer values for minimumVisitLength and heartBeatDelay.")},O.updatePageActivity=function(){Le()},O.enableFormTracking=function(e,t){s.hasLoaded?(me.configureFormTracking(e),me.addFormListeners(t)):s.registeredOnLoadHandlers.push(function(){me.configureFormTracking(e),me.addFormListeners(t)})},O.killFrame=function(){L.location!==L.top.location&&(L.top.location=L.location)},O.redirectFile=function(e){"file:"===L.location.protocol&&(L.location=e)},O.setOptOutCookie=function(e){v=e},O.setCountPreRendered=function(e){i=e},O.setUserId=function(e){A=e},O.identifyUser=function(e){setUserId(e)},O.setUserIdFromLocation=function(e){Ce(),A=tt.fromQuerystring(e,F)},O.setUserIdFromReferrer=function(e){Ce(),A=tt.fromQuerystring(e,z)},O.setUserIdFromCookie=function(e){A=rt.cookie(e)},O.setCollectorCf=function(e){a=qe(e+".cloudfront.net")},O.setCollectorUrl=function(e){a=qe(e)},O.setPlatform=function(e){tt.warn('setPlatform is deprecated. Instead add a "platform" field to the argmap argument of newTracker.'),j.setPlatform(e)},O.encodeBase64=function(e){tt.warn('This usage of encodeBase64 is deprecated. Instead add an "encodeBase64" field to the argmap argument of newTracker.'),j.setBase64Encoding(e)},O.flushBuffer=function(){ge.executeQueue()},O.enableGeolocationContext=Je,O.trackPageView=function(e,t,n,r){Ye(function(){Qe(e,t,n,r)})},O.trackStructEvent=function(e,t,n,r,a,o,i){Ye(function(){j.trackStructEvent(e,t,n,r,a,Re(o),i)})},O.trackSelfDescribingEvent=function(e,t,n){Ye(function(){j.trackSelfDescribingEvent(e,Re(t),n)})},O.trackUnstructEvent=function(e,t,n){Ye(function(){j.trackSelfDescribingEvent(e,Re(t),n)})},O.addTrans=function(e,t,n,r,a,o,i,c,s,u,l){pe.transaction={orderId:e,affiliation:t,total:n,tax:r,shipping:a,city:o,state:i,country:c,currency:s,context:u,tstamp:l}},O.addItem=function(e,t,n,r,a,o,i,c,s){pe.items.push({orderId:e,sku:t,name:n,category:r,price:a,quantity:o,currency:i,context:c,tstamp:s})},O.trackTrans=function(){Ye(function(){var e,t,n,r,a,o,i,c,s,u,l,f,d,p,h,m,v,g,y,_;e=pe.transaction.orderId,t=pe.transaction.affiliation,n=pe.transaction.total,r=pe.transaction.tax,a=pe.transaction.shipping,o=pe.transaction.city,i=pe.transaction.state,c=pe.transaction.country,s=pe.transaction.currency,u=pe.transaction.context,l=pe.transaction.tstamp,j.trackEcommerceTransaction(e,t,n,r,a,o,i,c,s,Re(u),l);for(var b=0;b<pe.items.length;b++){var w=pe.items[b];f=w.orderId,d=w.sku,p=w.name,h=w.category,m=w.price,v=w.quantity,g=w.currency,y=w.context,_=w.tstamp,j.trackEcommerceTransactionItem(f,d,p,h,m,v,g,Re(y),_)}pe={transaction:{},items:[]}})},O.trackLinkClick=function(e,t,n,r,a,o,i){Ye(function(){j.trackLinkClick(e,t,n,r,a,Re(o),i)})},O.trackAdImpression=function(e,t,n,r,a,o,i,c,s,u){Ye(function(){j.trackAdImpression(e,t,n,r,a,o,i,c,Re(s),u)})},O.trackAdClick=function(e,t,n,r,a,o,i,c,s,u,l){Ye(function(){j.trackAdClick(e,t,n,r,a,o,i,c,s,Re(u),l)})},O.trackAdConversion=function(e,t,n,r,a,o,i,c,s,u,l){Ye(function(){j.trackAdConversion(e,t,n,r,a,o,i,c,s,Re(u),l)})},O.trackSocialInteraction=function(e,t,n,r,a){Ye(function(){j.trackSocialInteraction(e,t,n,Re(r),a)})},O.trackAddToCart=function(e,t,n,r,a,o,i,c){Ye(function(){j.trackAddToCart(e,t,n,r,a,o,Re(i),c)})},O.trackRemoveFromCart=function(e,t,n,r,a,o,i,c){Ye(function(){j.trackRemoveFromCart(e,t,n,r,a,o,Re(i),c)})},O.trackSiteSearch=function(e,t,n,r,a,o){Ye(function(){j.trackSiteSearch(e,t,n,r,Re(a),o)})},O.trackTiming=function(e,t,n,r,a,o){Ye(function(){j.trackSelfDescribingEvent({schema:"iglu:com.snowplowanalytics.snowplow/timing/jsonschema/1-0-0",data:{category:e,variable:t,timing:n,label:r}},Re(a),o)})},O.trackConsentWithdrawn=function(e,t,n,r,a,o,i){Ye(function(){j.trackConsentWithdrawn(e,t,n,r,a,Re(o),i)})},O.trackConsentGranted=function(e,t,n,r,a,o,i){Ye(function(){j.trackConsentGranted(e,t,n,r,a,Re(o),i)})},O.trackEnhancedEcommerceAction=function(e,t,n){var r=we.concat(t||[]);we.length=0,Ye(function(){j.trackSelfDescribingEvent({schema:"iglu:com.google.analytics.enhanced-ecommerce/action/jsonschema/1-0-0",data:{action:e}},Re(r),n)})},O.addEnhancedEcommerceActionContext=function(e,t,n,r,a,o,i,c,s,u){we.push({schema:"iglu:com.google.analytics.enhanced-ecommerce/actionFieldObject/jsonschema/1-0-0",data:{id:e,affiliation:t,revenue:tt.parseFloat(n),tax:tt.parseFloat(r),shipping:tt.parseFloat(a),coupon:o,list:i,step:tt.parseInt(c),option:s,currency:u}})},O.addEnhancedEcommerceImpressionContext=function(e,t,n,r,a,o,i,c,s){we.push({schema:"iglu:com.google.analytics.enhanced-ecommerce/impressionFieldObject/jsonschema/1-0-0",data:{id:e,name:t,list:n,brand:r,category:a,variant:o,position:tt.parseInt(i),price:tt.parseFloat(c),currency:s}})},O.addEnhancedEcommerceProductContext=function(e,t,n,r,a,o,i,c,s,u,l){we.push({schema:"iglu:com.google.analytics.enhanced-ecommerce/productFieldObject/jsonschema/1-0-0",data:{id:e,name:t,list:n,brand:r,category:a,variant:o,price:tt.parseFloat(i),quantity:tt.parseInt(c),coupon:s,position:tt.parseInt(u),currency:l}})},O.addEnhancedEcommercePromoContext=function(e,t,n,r,a){we.push({schema:"iglu:com.google.analytics.enhanced-ecommerce/promoFieldObject/jsonschema/1-0-0",data:{id:e,name:t,creative:n,position:r,currency:a}})},O.addGlobalContexts=function(e){j.addGlobalContexts(e)},O.removeGlobalContexts=function(e){j.removeGlobalContexts(e)},O.clearGlobalContexts=function(){j.clearGlobalContexts()},O.enableErrorTracking=function(e,t){ve.enableErrorTracking(e,t,Re())},O.trackError=function(e,t,n,r,a,o){var i=Re(o);ve.trackError(e,t,n,r,a,i)},O.preservePageViewId=function(){ke=!0},O.setDebug=function(e){T=Boolean(e).valueOf(),Ze()},P=ft(O),Ze(),I}}()},{"./errors":162,"./forms":163,"./guard":164,"./lib/detectors":167,"./lib/helpers":168,"./lib/proxies":169,"./links":170,"./out_queue":171,"browser-cookie-lite":1,"lodash/forEach":123,"lodash/map":143,sha1:154,"snowplow-tracker-core":155,uuid:161}]},{},[166]);
diff --git a/vendor/jupyter/values.yaml b/vendor/jupyter/values.yaml
index 781d6e3042f..0fbf36b39cc 100644
--- a/vendor/jupyter/values.yaml
+++ b/vendor/jupyter/values.yaml
@@ -4,19 +4,53 @@ rbac:
hub:
extraEnv:
JUPYTER_ENABLE_LAB: 1
- SINGLEUSER_IMAGE: 'registry.gitlab.com/gitlab-org/jupyterhub-user-image:latest'
extraConfig: |
c.KubeSpawner.cmd = ['jupyter-labhub']
+ c.GitLabOAuthenticator.scope = ['api read_repository write_repository']
+
+ async def add_auth_env(spawner):
+ '''
+ We set user's id, login and access token on single user image to
+ enable repository integration for JupyterHub.
+ See: https://gitlab.com/gitlab-org/gitlab-ce/issues/47138#note_154294790
+ '''
+ auth_state = await spawner.user.get_auth_state()
+
+ if not auth_state:
+ spawner.log.warning("No auth state for %s", spawner.user)
+ return
+
+ spawner.environment['GITLAB_ACCESS_TOKEN'] = auth_state['access_token']
+ spawner.environment['GITLAB_USER_LOGIN'] = auth_state['gitlab_user']['username']
+ spawner.environment['GITLAB_USER_ID'] = str(auth_state['gitlab_user']['id'])
+ spawner.environment['GITLAB_USER_EMAIL'] = auth_state['gitlab_user']['email']
+ spawner.environment['GITLAB_USER_NAME'] = auth_state['gitlab_user']['name']
+
+ c.KubeSpawner.pre_spawn_hook = add_auth_env
auth:
type: gitlab
+ state:
+ enabled: true
singleuser:
defaultUrl: "/lab"
+ image:
+ name: registry.gitlab.com/gitlab-org/jupyterhub-user-image
+ tag: latest
lifecycleHooks:
postStart:
exec:
- command: ["sh", "-c", "git clone https://gitlab.com/gitlab-org/nurtch-demo.git DevOps-Runbook-Demo || true"]
+ command:
+ - "sh"
+ - "-c"
+ - >
+ git clone https://gitlab.com/gitlab-org/nurtch-demo.git DevOps-Runbook-Demo || true;
+ echo "https://${GITLAB_USER_LOGIN}:${GITLAB_ACCESS_TOKEN}@${GITLAB_HOST}" > ~/.git-credentials;
+ git config --global credential.helper store;
+ git config --global user.email "${GITLAB_USER_EMAIL}";
+ git config --global user.name "${GITLAB_USER_NAME}";
+ jupyter serverextension enable --py jupyterlab_git
ingress:
enabled: true
diff --git a/yarn.lock b/yarn.lock
index ebbb670db0c..31d40a5ad5e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9,18 +9,18 @@
dependencies:
"@babel/highlight" "^7.0.0"
-"@babel/core@>=7.1.0", "@babel/core@^7.1.0", "@babel/core@^7.2.2":
- version "7.3.4"
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.3.4.tgz#921a5a13746c21e32445bf0798680e9d11a6530b"
- integrity sha512-jRsuseXBo9pN197KnDwhhaaBzyZr2oIcLHHTt2oDdQrej5Qp57dCCJafWx5ivU8/alEYDpssYqv1MUqcxwQlrA==
+"@babel/core@>=7.1.0", "@babel/core@^7.1.0", "@babel/core@^7.4.4":
+ version "7.4.5"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.4.5.tgz#081f97e8ffca65a9b4b0fdc7e274e703f000c06a"
+ integrity sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA==
dependencies:
"@babel/code-frame" "^7.0.0"
- "@babel/generator" "^7.3.4"
- "@babel/helpers" "^7.2.0"
- "@babel/parser" "^7.3.4"
- "@babel/template" "^7.2.2"
- "@babel/traverse" "^7.3.4"
- "@babel/types" "^7.3.4"
+ "@babel/generator" "^7.4.4"
+ "@babel/helpers" "^7.4.4"
+ "@babel/parser" "^7.4.5"
+ "@babel/template" "^7.4.4"
+ "@babel/traverse" "^7.4.5"
+ "@babel/types" "^7.4.4"
convert-source-map "^1.1.0"
debug "^4.1.0"
json5 "^2.1.0"
@@ -29,12 +29,12 @@
semver "^5.4.1"
source-map "^0.5.0"
-"@babel/generator@^7.0.0", "@babel/generator@^7.3.4":
- version "7.3.4"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.4.tgz#9aa48c1989257877a9d971296e5b73bfe72e446e"
- integrity sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg==
+"@babel/generator@^7.4.0", "@babel/generator@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.4.4.tgz#174a215eb843fc392c7edcaabeaa873de6e8f041"
+ integrity sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==
dependencies:
- "@babel/types" "^7.3.4"
+ "@babel/types" "^7.4.4"
jsesc "^2.5.1"
lodash "^4.17.11"
source-map "^0.5.0"
@@ -55,34 +55,35 @@
"@babel/helper-explode-assignable-expression" "^7.1.0"
"@babel/types" "^7.0.0"
-"@babel/helper-call-delegate@^7.1.0":
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz#6a957f105f37755e8645343d3038a22e1449cc4a"
- integrity sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ==
+"@babel/helper-call-delegate@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz#87c1f8ca19ad552a736a7a27b1c1fcf8b1ff1f43"
+ integrity sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==
dependencies:
- "@babel/helper-hoist-variables" "^7.0.0"
- "@babel/traverse" "^7.1.0"
- "@babel/types" "^7.0.0"
+ "@babel/helper-hoist-variables" "^7.4.4"
+ "@babel/traverse" "^7.4.4"
+ "@babel/types" "^7.4.4"
-"@babel/helper-create-class-features-plugin@^7.3.0":
- version "7.3.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.3.0.tgz#2b01a81b3adc2b1287f9ee193688ef8dc71e718f"
- integrity sha512-DUsQNS2CGLZZ7I3W3fvh0YpPDd6BuWJlDl+qmZZpABZHza2ErE3LxtEzLJFHFC1ZwtlAXvHhbFYbtM5o5B0WBw==
+"@babel/helper-create-class-features-plugin@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.4.4.tgz#fc3d690af6554cc9efc607364a82d48f58736dba"
+ integrity sha512-UbBHIa2qeAGgyiNR9RszVF7bUHEdgS4JAUNT8SiqrAN6YJVxlOxeLr5pBzb5kan302dejJ9nla4RyKcR1XT6XA==
dependencies:
"@babel/helper-function-name" "^7.1.0"
"@babel/helper-member-expression-to-functions" "^7.0.0"
"@babel/helper-optimise-call-expression" "^7.0.0"
"@babel/helper-plugin-utils" "^7.0.0"
- "@babel/helper-replace-supers" "^7.2.3"
+ "@babel/helper-replace-supers" "^7.4.4"
+ "@babel/helper-split-export-declaration" "^7.4.4"
-"@babel/helper-define-map@^7.1.0":
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz#3b74caec329b3c80c116290887c0dd9ae468c20c"
- integrity sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg==
+"@babel/helper-define-map@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz#6969d1f570b46bdc900d1eba8e5d59c48ba2c12a"
+ integrity sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg==
dependencies:
"@babel/helper-function-name" "^7.1.0"
- "@babel/types" "^7.0.0"
- lodash "^4.17.10"
+ "@babel/types" "^7.4.4"
+ lodash "^4.17.11"
"@babel/helper-explode-assignable-expression@^7.1.0":
version "7.1.0"
@@ -108,12 +109,12 @@
dependencies:
"@babel/types" "^7.0.0"
-"@babel/helper-hoist-variables@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0.tgz#46adc4c5e758645ae7a45deb92bab0918c23bb88"
- integrity sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w==
+"@babel/helper-hoist-variables@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz#0298b5f25c8c09c53102d52ac4a98f773eb2850a"
+ integrity sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==
dependencies:
- "@babel/types" "^7.0.0"
+ "@babel/types" "^7.4.4"
"@babel/helper-member-expression-to-functions@^7.0.0":
version "7.0.0"
@@ -129,17 +130,17 @@
dependencies:
"@babel/types" "^7.0.0"
-"@babel/helper-module-transforms@^7.1.0":
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.1.0.tgz#470d4f9676d9fad50b324cdcce5fbabbc3da5787"
- integrity sha512-0JZRd2yhawo79Rcm4w0LwSMILFmFXjugG3yqf+P/UsKsRS1mJCmMwwlHDlMg7Avr9LrvSpp4ZSULO9r8jpCzcw==
+"@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz#96115ea42a2f139e619e98ed46df6019b94414b8"
+ integrity sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w==
dependencies:
"@babel/helper-module-imports" "^7.0.0"
"@babel/helper-simple-access" "^7.1.0"
- "@babel/helper-split-export-declaration" "^7.0.0"
- "@babel/template" "^7.1.0"
- "@babel/types" "^7.0.0"
- lodash "^4.17.10"
+ "@babel/helper-split-export-declaration" "^7.4.4"
+ "@babel/template" "^7.4.4"
+ "@babel/types" "^7.4.4"
+ lodash "^4.17.11"
"@babel/helper-optimise-call-expression@^7.0.0":
version "7.0.0"
@@ -153,12 +154,12 @@
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250"
integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==
-"@babel/helper-regex@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.0.0.tgz#2c1718923b57f9bbe64705ffe5640ac64d9bdb27"
- integrity sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg==
+"@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.4.4.tgz#a47e02bc91fb259d2e6727c2a30013e3ac13c4a2"
+ integrity sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q==
dependencies:
- lodash "^4.17.10"
+ lodash "^4.17.11"
"@babel/helper-remap-async-to-generator@^7.1.0":
version "7.1.0"
@@ -171,15 +172,15 @@
"@babel/traverse" "^7.1.0"
"@babel/types" "^7.0.0"
-"@babel/helper-replace-supers@^7.1.0", "@babel/helper-replace-supers@^7.2.3":
- version "7.2.3"
- resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.2.3.tgz#19970020cf22677d62b3a689561dbd9644d8c5e5"
- integrity sha512-GyieIznGUfPXPWu0yLS6U55Mz67AZD9cUk0BfirOWlPrXlBcan9Gz+vHGz+cPfuoweZSnPzPIm67VtQM0OWZbA==
+"@babel/helper-replace-supers@^7.1.0", "@babel/helper-replace-supers@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz#aee41783ebe4f2d3ab3ae775e1cc6f1a90cefa27"
+ integrity sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==
dependencies:
"@babel/helper-member-expression-to-functions" "^7.0.0"
"@babel/helper-optimise-call-expression" "^7.0.0"
- "@babel/traverse" "^7.2.3"
- "@babel/types" "^7.0.0"
+ "@babel/traverse" "^7.4.4"
+ "@babel/types" "^7.4.4"
"@babel/helper-simple-access@^7.1.0":
version "7.1.0"
@@ -189,12 +190,12 @@
"@babel/template" "^7.1.0"
"@babel/types" "^7.0.0"
-"@babel/helper-split-export-declaration@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz#3aae285c0311c2ab095d997b8c9a94cad547d813"
- integrity sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==
+"@babel/helper-split-export-declaration@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677"
+ integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==
dependencies:
- "@babel/types" "^7.0.0"
+ "@babel/types" "^7.4.4"
"@babel/helper-wrap-function@^7.1.0":
version "7.1.0"
@@ -206,14 +207,14 @@
"@babel/traverse" "^7.1.0"
"@babel/types" "^7.0.0"
-"@babel/helpers@^7.2.0":
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.2.0.tgz#8335f3140f3144270dc63c4732a4f8b0a50b7a21"
- integrity sha512-Fr07N+ea0dMcMN8nFpuK6dUIT7/ivt9yKQdEEnjVS83tG2pHwPi03gYmk/tyuwONnZ+sY+GFFPlWGgCtW1hF9A==
+"@babel/helpers@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.4.4.tgz#868b0ef59c1dd4e78744562d5ce1b59c89f2f2a5"
+ integrity sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==
dependencies:
- "@babel/template" "^7.1.2"
- "@babel/traverse" "^7.1.5"
- "@babel/types" "^7.2.0"
+ "@babel/template" "^7.4.4"
+ "@babel/traverse" "^7.4.4"
+ "@babel/types" "^7.4.4"
"@babel/highlight@^7.0.0":
version "7.0.0"
@@ -224,10 +225,10 @@
esutils "^2.0.2"
js-tokens "^4.0.0"
-"@babel/parser@^7.0.0", "@babel/parser@^7.2.2", "@babel/parser@^7.3.4":
- version "7.3.4"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.4.tgz#a43357e4bbf4b92a437fb9e465c192848287f27c"
- integrity sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ==
+"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.4.4", "@babel/parser@^7.4.5":
+ version "7.4.5"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.5.tgz#04af8d5d5a2b044a2a1bffacc1e5e6673544e872"
+ integrity sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==
"@babel/plugin-proposal-async-generator-functions@^7.2.0":
version "7.2.0"
@@ -238,12 +239,12 @@
"@babel/helper-remap-async-to-generator" "^7.1.0"
"@babel/plugin-syntax-async-generators" "^7.2.0"
-"@babel/plugin-proposal-class-properties@^7.3.0":
- version "7.3.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.3.0.tgz#272636bc0fa19a0bc46e601ec78136a173ea36cd"
- integrity sha512-wNHxLkEKTQ2ay0tnsam2z7fGZUi+05ziDJflEt3AZTP3oXLKHJp9HqhfroB/vdMvt3sda9fAbq7FsG8QPDrZBg==
+"@babel/plugin-proposal-class-properties@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.4.4.tgz#93a6486eed86d53452ab9bab35e368e9461198ce"
+ integrity sha512-WjKTI8g8d5w1Bc9zgwSz2nfrsNQsXcCf9J9cdCvrJV6RF56yztwm4TmJC0MgJ9tvwO9gUA/mcYe89bLdGfiXFg==
dependencies:
- "@babel/helper-create-class-features-plugin" "^7.3.0"
+ "@babel/helper-create-class-features-plugin" "^7.4.4"
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-proposal-json-strings@^7.2.0":
@@ -254,10 +255,10 @@
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-json-strings" "^7.2.0"
-"@babel/plugin-proposal-object-rest-spread@^7.3.1":
- version "7.3.1"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.1.tgz#f69fb6a1ea6a4e1c503994a91d9cf76f3c4b36e8"
- integrity sha512-Nmmv1+3LqxJu/V5jU9vJmxR/KIRWFk2qLHmbB56yRRRFhlaSuOVXscX3gUmhaKgUhzA3otOHVubbIEVYsZ0eZg==
+"@babel/plugin-proposal-object-rest-spread@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz#1ef173fcf24b3e2df92a678f027673b55e7e3005"
+ integrity sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-object-rest-spread" "^7.2.0"
@@ -270,22 +271,22 @@
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-optional-catch-binding" "^7.2.0"
-"@babel/plugin-proposal-private-methods@^7.3.0":
- version "7.3.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.3.0.tgz#da373257a66525cb76544c37ab2ce4c611568841"
- integrity sha512-j6luy/F0MX6kd71e9hz97my2tBXTa+czAz+sscJVCRmjB9e9g2D4JN+tyfcwMCXUM2afj/tYCjzNaxwWJ4SdYg==
+"@babel/plugin-proposal-private-methods@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.4.4.tgz#307b7db29d8ae2d259e7c0e6e665b1922d7ac856"
+ integrity sha512-EIV4fDVP3XwdizJ/H6308Km+d8xdLAUCAvsY8mjxhat9I3vNgssGhZuhgn/jw7IK5/91sN8PHtVGxMjeTSrSng==
dependencies:
- "@babel/helper-create-class-features-plugin" "^7.3.0"
+ "@babel/helper-create-class-features-plugin" "^7.4.4"
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-proposal-unicode-property-regex@^7.2.0":
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.2.0.tgz#abe7281fe46c95ddc143a65e5358647792039520"
- integrity sha512-LvRVYb7kikuOtIoUeWTkOxQEV1kYvL5B6U3iWEGCzPNRus1MzJweFqORTj+0jkxozkTSYNJozPOddxmqdqsRpw==
+"@babel/plugin-proposal-unicode-property-regex@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz#501ffd9826c0b91da22690720722ac7cb1ca9c78"
+ integrity sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
- "@babel/helper-regex" "^7.0.0"
- regexpu-core "^4.2.0"
+ "@babel/helper-regex" "^7.4.4"
+ regexpu-core "^4.5.4"
"@babel/plugin-syntax-async-generators@^7.2.0":
version "7.2.0"
@@ -336,10 +337,10 @@
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-async-to-generator@^7.2.0":
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.2.0.tgz#68b8a438663e88519e65b776f8938f3445b1a2ff"
- integrity sha512-CEHzg4g5UraReozI9D4fblBYABs7IM6UerAVG7EJVrTLC5keh00aEuLUT+O40+mJCEzaXkYfTCUKIyeDfMOFFQ==
+"@babel/plugin-transform-async-to-generator@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz#a3f1d01f2f21cadab20b33a82133116f14fb5894"
+ integrity sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA==
dependencies:
"@babel/helper-module-imports" "^7.0.0"
"@babel/helper-plugin-utils" "^7.0.0"
@@ -352,26 +353,26 @@
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-block-scoping@^7.2.0":
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.2.0.tgz#f17c49d91eedbcdf5dd50597d16f5f2f770132d4"
- integrity sha512-vDTgf19ZEV6mx35yiPJe4fS02mPQUUcBNwWQSZFXSzTSbsJFQvHt7DqyS3LK8oOWALFOsJ+8bbqBgkirZteD5Q==
+"@babel/plugin-transform-block-scoping@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz#c13279fabf6b916661531841a23c4b7dae29646d"
+ integrity sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
- lodash "^4.17.10"
+ lodash "^4.17.11"
-"@babel/plugin-transform-classes@^7.2.0":
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.2.2.tgz#6c90542f210ee975aa2aa8c8b5af7fa73a126953"
- integrity sha512-gEZvgTy1VtcDOaQty1l10T3jQmJKlNVxLDCs+3rCVPr6nMkODLELxViq5X9l+rfxbie3XrfrMCYYY6eX3aOcOQ==
+"@babel/plugin-transform-classes@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz#0ce4094cdafd709721076d3b9c38ad31ca715eb6"
+ integrity sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw==
dependencies:
"@babel/helper-annotate-as-pure" "^7.0.0"
- "@babel/helper-define-map" "^7.1.0"
+ "@babel/helper-define-map" "^7.4.4"
"@babel/helper-function-name" "^7.1.0"
"@babel/helper-optimise-call-expression" "^7.0.0"
"@babel/helper-plugin-utils" "^7.0.0"
- "@babel/helper-replace-supers" "^7.1.0"
- "@babel/helper-split-export-declaration" "^7.0.0"
+ "@babel/helper-replace-supers" "^7.4.4"
+ "@babel/helper-split-export-declaration" "^7.4.4"
globals "^11.1.0"
"@babel/plugin-transform-computed-properties@^7.2.0":
@@ -381,21 +382,21 @@
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-destructuring@^7.2.0":
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.2.0.tgz#e75269b4b7889ec3a332cd0d0c8cff8fed0dc6f3"
- integrity sha512-coVO2Ayv7g0qdDbrNiadE4bU7lvCd9H539m2gMknyVjjMdwF/iCOM7R+E8PkntoqLkltO0rk+3axhpp/0v68VQ==
+"@babel/plugin-transform-destructuring@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz#9d964717829cc9e4b601fc82a26a71a4d8faf20f"
+ integrity sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-dotall-regex@^7.2.0":
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.2.0.tgz#f0aabb93d120a8ac61e925ea0ba440812dbe0e49"
- integrity sha512-sKxnyHfizweTgKZf7XsXu/CNupKhzijptfTM+bozonIuyVrLWVUvYjE2bhuSBML8VQeMxq4Mm63Q9qvcvUcciQ==
+"@babel/plugin-transform-dotall-regex@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz#361a148bc951444312c69446d76ed1ea8e4450c3"
+ integrity sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
- "@babel/helper-regex" "^7.0.0"
- regexpu-core "^4.1.3"
+ "@babel/helper-regex" "^7.4.4"
+ regexpu-core "^4.5.4"
"@babel/plugin-transform-duplicate-keys@^7.2.0":
version "7.2.0"
@@ -412,17 +413,17 @@
"@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0"
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-for-of@^7.2.0":
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.2.0.tgz#ab7468befa80f764bb03d3cb5eef8cc998e1cad9"
- integrity sha512-Kz7Mt0SsV2tQk6jG5bBv5phVbkd0gd27SgYD4hH1aLMJRchM0dzHaXvrWhVZ+WxAlDoAKZ7Uy3jVTW2mKXQ1WQ==
+"@babel/plugin-transform-for-of@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz#0267fc735e24c808ba173866c6c4d1440fc3c556"
+ integrity sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-function-name@^7.2.0":
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.2.0.tgz#f7930362829ff99a3174c39f0afcc024ef59731a"
- integrity sha512-kWgksow9lHdvBC2Z4mxTsvc7YdY7w/V6B2vy9cTIPtLEE9NhwoWivaxdNM/S37elu5bqlLP/qOY906LukO9lkQ==
+"@babel/plugin-transform-function-name@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz#e1436116abb0610c2259094848754ac5230922ad"
+ integrity sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==
dependencies:
"@babel/helper-function-name" "^7.1.0"
"@babel/helper-plugin-utils" "^7.0.0"
@@ -434,6 +435,13 @@
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
+"@babel/plugin-transform-member-expression-literals@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz#fa10aa5c58a2cb6afcf2c9ffa8cb4d8b3d489a2d"
+ integrity sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
"@babel/plugin-transform-modules-amd@^7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz#82a9bce45b95441f617a24011dc89d12da7f4ee6"
@@ -442,21 +450,21 @@
"@babel/helper-module-transforms" "^7.1.0"
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-modules-commonjs@^7.2.0":
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.2.0.tgz#c4f1933f5991d5145e9cfad1dfd848ea1727f404"
- integrity sha512-V6y0uaUQrQPXUrmj+hgnks8va2L0zcZymeU7TtWEgdRLNkceafKXEduv7QzgQAE4lT+suwooG9dC7LFhdRAbVQ==
+"@babel/plugin-transform-modules-commonjs@^7.2.0", "@babel/plugin-transform-modules-commonjs@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz#0bef4713d30f1d78c2e59b3d6db40e60192cac1e"
+ integrity sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw==
dependencies:
- "@babel/helper-module-transforms" "^7.1.0"
+ "@babel/helper-module-transforms" "^7.4.4"
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/helper-simple-access" "^7.1.0"
-"@babel/plugin-transform-modules-systemjs@^7.2.0":
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.2.0.tgz#912bfe9e5ff982924c81d0937c92d24994bb9068"
- integrity sha512-aYJwpAhoK9a+1+O625WIjvMY11wkB/ok0WClVwmeo3mCjcNRjt+/8gHWrB5i+00mUju0gWsBkQnPpdvQ7PImmQ==
+"@babel/plugin-transform-modules-systemjs@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz#dc83c5665b07d6c2a7b224c00ac63659ea36a405"
+ integrity sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ==
dependencies:
- "@babel/helper-hoist-variables" "^7.0.0"
+ "@babel/helper-hoist-variables" "^7.4.4"
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-transform-modules-umd@^7.2.0":
@@ -467,17 +475,17 @@
"@babel/helper-module-transforms" "^7.1.0"
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-named-capturing-groups-regex@^7.3.0":
- version "7.3.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.3.0.tgz#140b52985b2d6ef0cb092ef3b29502b990f9cd50"
- integrity sha512-NxIoNVhk9ZxS+9lSoAQ/LM0V2UEvARLttEHUrRDGKFaAxOYQcrkN/nLRE+BbbicCAvZPl7wMP0X60HsHE5DtQw==
+"@babel/plugin-transform-named-capturing-groups-regex@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.4.tgz#5611d96d987dfc4a3a81c4383bb173361037d68d"
+ integrity sha512-Ki+Y9nXBlKfhD+LXaRS7v95TtTGYRAf9Y1rTDiE75zf8YQz4GDaWRXosMfJBXxnk88mGFjWdCRIeqDbon7spYA==
dependencies:
regexp-tree "^0.1.0"
-"@babel/plugin-transform-new-target@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz#ae8fbd89517fa7892d20e6564e641e8770c3aa4a"
- integrity sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw==
+"@babel/plugin-transform-new-target@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz#18d120438b0cc9ee95a47f2c72bc9768fbed60a5"
+ integrity sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
@@ -489,21 +497,35 @@
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/helper-replace-supers" "^7.1.0"
-"@babel/plugin-transform-parameters@^7.2.0":
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.2.0.tgz#0d5ad15dc805e2ea866df4dd6682bfe76d1408c2"
- integrity sha512-kB9+hhUidIgUoBQ0MsxMewhzr8i60nMa2KgeJKQWYrqQpqcBYtnpR+JgkadZVZoaEZ/eKu9mclFaVwhRpLNSzA==
+"@babel/plugin-transform-parameters@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz#7556cf03f318bd2719fe4c922d2d808be5571e16"
+ integrity sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==
dependencies:
- "@babel/helper-call-delegate" "^7.1.0"
+ "@babel/helper-call-delegate" "^7.4.4"
"@babel/helper-get-function-arity" "^7.0.0"
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-regenerator@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0.tgz#5b41686b4ed40bef874d7ed6a84bdd849c13e0c1"
- integrity sha512-sj2qzsEx8KDVv1QuJc/dEfilkg3RRPvPYx/VnKLtItVQRWt1Wqf5eVCOLZm29CiGFfYYsA3VPjfizTCV0S0Dlw==
+"@babel/plugin-transform-property-literals@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz#03e33f653f5b25c4eb572c98b9485055b389e905"
+ integrity sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-regenerator@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.4.tgz#5b4da4df79391895fca9e28f99e87e22cfc02072"
+ integrity sha512-Zz3w+pX1SI0KMIiqshFZkwnVGUhDZzpX2vtPzfJBKQQq8WsP/Xy9DNdELWivxcKOCX/Pywge4SiEaPaLtoDT4g==
dependencies:
- regenerator-transform "^0.13.3"
+ regenerator-transform "^0.13.4"
+
+"@babel/plugin-transform-reserved-words@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz#4792af87c998a49367597d07fedf02636d2e1634"
+ integrity sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-transform-shorthand-properties@^7.2.0":
version "7.2.0"
@@ -527,10 +549,10 @@
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/helper-regex" "^7.0.0"
-"@babel/plugin-transform-template-literals@^7.2.0":
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.2.0.tgz#d87ed01b8eaac7a92473f608c97c089de2ba1e5b"
- integrity sha512-FkPix00J9A/XWXv4VoKJBMeSkyY9x/TqIh76wzcdfl57RJJcf8CehQ08uwfhCDNtRQYtHQKBTwKZDEyjE13Lwg==
+"@babel/plugin-transform-template-literals@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz#9d28fea7bbce637fb7612a0750989d8321d4bcb0"
+ integrity sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==
dependencies:
"@babel/helper-annotate-as-pure" "^7.0.0"
"@babel/helper-plugin-utils" "^7.0.0"
@@ -542,102 +564,115 @@
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-transform-unicode-regex@^7.2.0":
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.2.0.tgz#4eb8db16f972f8abb5062c161b8b115546ade08b"
- integrity sha512-m48Y0lMhrbXEJnVUaYly29jRXbQ3ksxPrS1Tg8t+MHqzXhtBYAvI51euOBaoAlZLPHsieY9XPVMf80a5x0cPcA==
+"@babel/plugin-transform-unicode-regex@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz#ab4634bb4f14d36728bf5978322b35587787970f"
+ integrity sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
- "@babel/helper-regex" "^7.0.0"
- regexpu-core "^4.1.3"
+ "@babel/helper-regex" "^7.4.4"
+ regexpu-core "^4.5.4"
-"@babel/preset-env@^7.3.1":
- version "7.3.1"
- resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.3.1.tgz#389e8ca6b17ae67aaf9a2111665030be923515db"
- integrity sha512-FHKrD6Dxf30e8xgHQO0zJZpUPfVZg+Xwgz5/RdSWCbza9QLNk4Qbp40ctRoqDxml3O8RMzB1DU55SXeDG6PqHQ==
+"@babel/preset-env@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.4.4.tgz#b6f6825bfb27b3e1394ca3de4f926482722c1d6f"
+ integrity sha512-FU1H+ACWqZZqfw1x2G1tgtSSYSfxJLkpaUQL37CenULFARDo+h4xJoVHzRoHbK+85ViLciuI7ME4WTIhFRBBlw==
dependencies:
"@babel/helper-module-imports" "^7.0.0"
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-proposal-async-generator-functions" "^7.2.0"
"@babel/plugin-proposal-json-strings" "^7.2.0"
- "@babel/plugin-proposal-object-rest-spread" "^7.3.1"
+ "@babel/plugin-proposal-object-rest-spread" "^7.4.4"
"@babel/plugin-proposal-optional-catch-binding" "^7.2.0"
- "@babel/plugin-proposal-unicode-property-regex" "^7.2.0"
+ "@babel/plugin-proposal-unicode-property-regex" "^7.4.4"
"@babel/plugin-syntax-async-generators" "^7.2.0"
"@babel/plugin-syntax-json-strings" "^7.2.0"
"@babel/plugin-syntax-object-rest-spread" "^7.2.0"
"@babel/plugin-syntax-optional-catch-binding" "^7.2.0"
"@babel/plugin-transform-arrow-functions" "^7.2.0"
- "@babel/plugin-transform-async-to-generator" "^7.2.0"
+ "@babel/plugin-transform-async-to-generator" "^7.4.4"
"@babel/plugin-transform-block-scoped-functions" "^7.2.0"
- "@babel/plugin-transform-block-scoping" "^7.2.0"
- "@babel/plugin-transform-classes" "^7.2.0"
+ "@babel/plugin-transform-block-scoping" "^7.4.4"
+ "@babel/plugin-transform-classes" "^7.4.4"
"@babel/plugin-transform-computed-properties" "^7.2.0"
- "@babel/plugin-transform-destructuring" "^7.2.0"
- "@babel/plugin-transform-dotall-regex" "^7.2.0"
+ "@babel/plugin-transform-destructuring" "^7.4.4"
+ "@babel/plugin-transform-dotall-regex" "^7.4.4"
"@babel/plugin-transform-duplicate-keys" "^7.2.0"
"@babel/plugin-transform-exponentiation-operator" "^7.2.0"
- "@babel/plugin-transform-for-of" "^7.2.0"
- "@babel/plugin-transform-function-name" "^7.2.0"
+ "@babel/plugin-transform-for-of" "^7.4.4"
+ "@babel/plugin-transform-function-name" "^7.4.4"
"@babel/plugin-transform-literals" "^7.2.0"
+ "@babel/plugin-transform-member-expression-literals" "^7.2.0"
"@babel/plugin-transform-modules-amd" "^7.2.0"
- "@babel/plugin-transform-modules-commonjs" "^7.2.0"
- "@babel/plugin-transform-modules-systemjs" "^7.2.0"
+ "@babel/plugin-transform-modules-commonjs" "^7.4.4"
+ "@babel/plugin-transform-modules-systemjs" "^7.4.4"
"@babel/plugin-transform-modules-umd" "^7.2.0"
- "@babel/plugin-transform-named-capturing-groups-regex" "^7.3.0"
- "@babel/plugin-transform-new-target" "^7.0.0"
+ "@babel/plugin-transform-named-capturing-groups-regex" "^7.4.4"
+ "@babel/plugin-transform-new-target" "^7.4.4"
"@babel/plugin-transform-object-super" "^7.2.0"
- "@babel/plugin-transform-parameters" "^7.2.0"
- "@babel/plugin-transform-regenerator" "^7.0.0"
+ "@babel/plugin-transform-parameters" "^7.4.4"
+ "@babel/plugin-transform-property-literals" "^7.2.0"
+ "@babel/plugin-transform-regenerator" "^7.4.4"
+ "@babel/plugin-transform-reserved-words" "^7.2.0"
"@babel/plugin-transform-shorthand-properties" "^7.2.0"
"@babel/plugin-transform-spread" "^7.2.0"
"@babel/plugin-transform-sticky-regex" "^7.2.0"
- "@babel/plugin-transform-template-literals" "^7.2.0"
+ "@babel/plugin-transform-template-literals" "^7.4.4"
"@babel/plugin-transform-typeof-symbol" "^7.2.0"
- "@babel/plugin-transform-unicode-regex" "^7.2.0"
- browserslist "^4.3.4"
+ "@babel/plugin-transform-unicode-regex" "^7.4.4"
+ "@babel/types" "^7.4.4"
+ browserslist "^4.5.2"
+ core-js-compat "^3.0.0"
invariant "^2.2.2"
js-levenshtein "^1.1.3"
- semver "^5.3.0"
+ semver "^5.5.0"
"@babel/standalone@^7.0.0":
version "7.3.4"
resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.3.4.tgz#b622c1e522acef91b2a14f22bdcdd4f935a1a474"
integrity sha512-4L9c5i4WlGqbrjOVX0Yp8TIR5cEiw1/tPYYZENW/iuO2uI6viY38U7zALidzNfGdZIwNc+A/AWqMEWKeScWkBg==
-"@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2":
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907"
- integrity sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==
+"@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237"
+ integrity sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==
dependencies:
"@babel/code-frame" "^7.0.0"
- "@babel/parser" "^7.2.2"
- "@babel/types" "^7.2.2"
+ "@babel/parser" "^7.4.4"
+ "@babel/types" "^7.4.4"
-"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.5", "@babel/traverse@^7.2.3", "@babel/traverse@^7.3.4":
- version "7.3.4"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.3.4.tgz#1330aab72234f8dea091b08c4f8b9d05c7119e06"
- integrity sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ==
+"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.4.5":
+ version "7.4.5"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.4.5.tgz#4e92d1728fd2f1897dafdd321efbff92156c3216"
+ integrity sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==
dependencies:
"@babel/code-frame" "^7.0.0"
- "@babel/generator" "^7.3.4"
+ "@babel/generator" "^7.4.4"
"@babel/helper-function-name" "^7.1.0"
- "@babel/helper-split-export-declaration" "^7.0.0"
- "@babel/parser" "^7.3.4"
- "@babel/types" "^7.3.4"
+ "@babel/helper-split-export-declaration" "^7.4.4"
+ "@babel/parser" "^7.4.5"
+ "@babel/types" "^7.4.4"
debug "^4.1.0"
globals "^11.1.0"
lodash "^4.17.11"
-"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.2.2", "@babel/types@^7.3.4":
- version "7.3.4"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.3.4.tgz#bf482eaeaffb367a28abbf9357a94963235d90ed"
- integrity sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==
+"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.4.4.tgz#8db9e9a629bb7c29370009b4b779ed93fe57d5f0"
+ integrity sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==
dependencies:
esutils "^2.0.2"
lodash "^4.17.11"
to-fast-properties "^2.0.0"
+"@cnakazawa/watch@^1.0.3":
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef"
+ integrity sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==
+ dependencies:
+ exec-sh "^0.3.2"
+ minimist "^1.2.0"
+
"@gitlab/csslab@^1.9.0":
version "1.9.0"
resolved "https://registry.yarnpkg.com/@gitlab/csslab/-/csslab-1.9.0.tgz#22fca5b1a30cbd9ca46fc6f9485ecbaba4dc300c"
@@ -645,10 +680,10 @@
dependencies:
bootstrap "^4.1.3"
-"@gitlab/eslint-config@^1.5.0":
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/@gitlab/eslint-config/-/eslint-config-1.5.0.tgz#0c8c3ae74f276eb6671bd7c60f331bc0f2d2e5cf"
- integrity sha512-KgJgoIZNpGauFpCV1iCptesYN7I8abtYRBLU9xcH0oocC/xp3JmbLfsZ+lEtrk8pl99Q2mKiAuaPpzxjXr6hBw==
+"@gitlab/eslint-config@^1.6.0":
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/eslint-config/-/eslint-config-1.6.0.tgz#1fd247d6ab477d53d4c330e05f007e3afa303689"
+ integrity sha512-EZffCwsRZmRWPP6N3wp20EJDVGYLG1v43/W7fF/gYQpUjcRclC8ks/jEv8UppasSDlanDmkh1bLWoE9CelSyyw==
dependencies:
babel-eslint "^10.0.1"
eslint-config-airbnb-base "^13.1.0"
@@ -658,17 +693,25 @@
eslint-plugin-promise "^4.1.1"
eslint-plugin-vue "^5.0.0"
-"@gitlab/svgs@^1.59.0":
- version "1.59.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.59.0.tgz#affcf9596d736836d37469bb4aea2226ac03e087"
- integrity sha512-dokGyyLRRsoBKO70KP1g+ZsDGyTK/RIHWDmvWI6Bx5AxQ3UqAzVXn2OIb3owjJAexyRG1uBmJrriiVVyHznQ4g==
+"@gitlab/eslint-plugin-i18n@^1.0.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin-i18n/-/eslint-plugin-i18n-1.1.0.tgz#e494d599e644ce3a094ea85f87dbbda41a924c5e"
+ integrity sha512-Cwm7sLtQnUDqvxE9Ez8UMslyosPCpMVLxBnFb+2n6QcBZmXRao4aNSVRkmlsDZYgYegWhOGn3Qq3MLy4BSqauQ==
+ dependencies:
+ requireindex "~1.1.0"
+
+"@gitlab/svgs@^1.63.0":
+ version "1.63.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.63.0.tgz#9dd544026d203e4ce6efed72b05db68f710c4d49"
+ integrity sha512-YztrReFTg31B7v5wtUC5j15KHNcMebtW+kACytEU42XomMaIwk4USIbygqWlq0VRHA2VHJrHApfJHIjxiCCQcA==
-"@gitlab/ui@^3.3.0":
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-3.3.0.tgz#32112c8eb53a0fd893f8fa431a02ceaf55279323"
- integrity sha512-VVInZmcAe0L0lRMb6II3ED4DYm4OpzSmcxdwt18CqpDMw3EEoUqxd58EAxBFy70isgFTd6cHYhyS8rw5GOULyg==
+"@gitlab/ui@^4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-4.0.0.tgz#998a94d4ff91c5baa68d0591763e467a18293081"
+ integrity sha512-Z8T3xK3EV1eC2eBmnuO/cvcuLfH5TskGJsc2Hdxar+iUVxACbzs3bfjpFjslVHCCGzSRnewZCoRPO7GJO3miIg==
dependencies:
"@babel/standalone" "^7.0.0"
+ "@gitlab/vue-toasted" "^1.2.1"
bootstrap-vue "^2.0.0-rc.11"
copy-to-clipboard "^3.0.8"
echarts "^4.2.0-rc.2"
@@ -676,9 +719,160 @@
js-beautify "^1.8.8"
lodash "^4.17.11"
url-search-params-polyfill "^5.0.0"
- vue "^2.5.21"
+ vue "^2.6.10"
vue-loader "^15.4.2"
+"@gitlab/vue-toasted@^1.2.1":
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@gitlab/vue-toasted/-/vue-toasted-1.2.1.tgz#f407b5aa710863e5b7f021f4a1f66160331ab263"
+ integrity sha512-ve2PLxKqrwNpsd+4bV5zGJT5+H5N/VJBZoFS2Vp1mH5cUDBYIHTzDmbS6AbBGUDh0F3TxmFMiqfXfpO/1VjBNQ==
+
+"@jest/console@^24.7.1":
+ version "24.7.1"
+ resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.7.1.tgz#32a9e42535a97aedfe037e725bd67e954b459545"
+ integrity sha512-iNhtIy2M8bXlAOULWVTUxmnelTLFneTNEkHCgPmgd+zNwy9zVddJ6oS5rZ9iwoscNdT5mMwUd0C51v/fSlzItg==
+ dependencies:
+ "@jest/source-map" "^24.3.0"
+ chalk "^2.0.1"
+ slash "^2.0.0"
+
+"@jest/core@^24.8.0":
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/@jest/core/-/core-24.8.0.tgz#fbbdcd42a41d0d39cddbc9f520c8bab0c33eed5b"
+ integrity sha512-R9rhAJwCBQzaRnrRgAdVfnglUuATXdwTRsYqs6NMdVcAl5euG8LtWDe+fVkN27YfKVBW61IojVsXKaOmSnqd/A==
+ dependencies:
+ "@jest/console" "^24.7.1"
+ "@jest/reporters" "^24.8.0"
+ "@jest/test-result" "^24.8.0"
+ "@jest/transform" "^24.8.0"
+ "@jest/types" "^24.8.0"
+ ansi-escapes "^3.0.0"
+ chalk "^2.0.1"
+ exit "^0.1.2"
+ graceful-fs "^4.1.15"
+ jest-changed-files "^24.8.0"
+ jest-config "^24.8.0"
+ jest-haste-map "^24.8.0"
+ jest-message-util "^24.8.0"
+ jest-regex-util "^24.3.0"
+ jest-resolve-dependencies "^24.8.0"
+ jest-runner "^24.8.0"
+ jest-runtime "^24.8.0"
+ jest-snapshot "^24.8.0"
+ jest-util "^24.8.0"
+ jest-validate "^24.8.0"
+ jest-watcher "^24.8.0"
+ micromatch "^3.1.10"
+ p-each-series "^1.0.0"
+ pirates "^4.0.1"
+ realpath-native "^1.1.0"
+ rimraf "^2.5.4"
+ strip-ansi "^5.0.0"
+
+"@jest/environment@^24.8.0":
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-24.8.0.tgz#0342261383c776bdd652168f68065ef144af0eac"
+ integrity sha512-vlGt2HLg7qM+vtBrSkjDxk9K0YtRBi7HfRFaDxoRtyi+DyVChzhF20duvpdAnKVBV6W5tym8jm0U9EfXbDk1tw==
+ dependencies:
+ "@jest/fake-timers" "^24.8.0"
+ "@jest/transform" "^24.8.0"
+ "@jest/types" "^24.8.0"
+ jest-mock "^24.8.0"
+
+"@jest/fake-timers@^24.8.0":
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.8.0.tgz#2e5b80a4f78f284bcb4bd5714b8e10dd36a8d3d1"
+ integrity sha512-2M4d5MufVXwi6VzZhJ9f5S/wU4ud2ck0kxPof1Iz3zWx6Y+V2eJrES9jEktB6O3o/oEyk+il/uNu9PvASjWXQw==
+ dependencies:
+ "@jest/types" "^24.8.0"
+ jest-message-util "^24.8.0"
+ jest-mock "^24.8.0"
+
+"@jest/reporters@^24.8.0":
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.8.0.tgz#075169cd029bddec54b8f2c0fc489fd0b9e05729"
+ integrity sha512-eZ9TyUYpyIIXfYCrw0UHUWUvE35vx5I92HGMgS93Pv7du+GHIzl+/vh8Qj9MCWFK/4TqyttVBPakWMOfZRIfxw==
+ dependencies:
+ "@jest/environment" "^24.8.0"
+ "@jest/test-result" "^24.8.0"
+ "@jest/transform" "^24.8.0"
+ "@jest/types" "^24.8.0"
+ chalk "^2.0.1"
+ exit "^0.1.2"
+ glob "^7.1.2"
+ istanbul-lib-coverage "^2.0.2"
+ istanbul-lib-instrument "^3.0.1"
+ istanbul-lib-report "^2.0.4"
+ istanbul-lib-source-maps "^3.0.1"
+ istanbul-reports "^2.1.1"
+ jest-haste-map "^24.8.0"
+ jest-resolve "^24.8.0"
+ jest-runtime "^24.8.0"
+ jest-util "^24.8.0"
+ jest-worker "^24.6.0"
+ node-notifier "^5.2.1"
+ slash "^2.0.0"
+ source-map "^0.6.0"
+ string-length "^2.0.0"
+
+"@jest/source-map@^24.3.0":
+ version "24.3.0"
+ resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.3.0.tgz#563be3aa4d224caf65ff77edc95cd1ca4da67f28"
+ integrity sha512-zALZt1t2ou8le/crCeeiRYzvdnTzaIlpOWaet45lNSqNJUnXbppUUFR4ZUAlzgDmKee4Q5P/tKXypI1RiHwgag==
+ dependencies:
+ callsites "^3.0.0"
+ graceful-fs "^4.1.15"
+ source-map "^0.6.0"
+
+"@jest/test-result@^24.8.0":
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.8.0.tgz#7675d0aaf9d2484caa65e048d9b467d160f8e9d3"
+ integrity sha512-+YdLlxwizlfqkFDh7Mc7ONPQAhA4YylU1s529vVM1rsf67vGZH/2GGm5uO8QzPeVyaVMobCQ7FTxl38QrKRlng==
+ dependencies:
+ "@jest/console" "^24.7.1"
+ "@jest/types" "^24.8.0"
+ "@types/istanbul-lib-coverage" "^2.0.0"
+
+"@jest/test-sequencer@^24.8.0":
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-24.8.0.tgz#2f993bcf6ef5eb4e65e8233a95a3320248cf994b"
+ integrity sha512-OzL/2yHyPdCHXEzhoBuq37CE99nkme15eHkAzXRVqthreWZamEMA0WoetwstsQBCXABhczpK03JNbc4L01vvLg==
+ dependencies:
+ "@jest/test-result" "^24.8.0"
+ jest-haste-map "^24.8.0"
+ jest-runner "^24.8.0"
+ jest-runtime "^24.8.0"
+
+"@jest/transform@^24.8.0":
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-24.8.0.tgz#628fb99dce4f9d254c6fd9341e3eea262e06fef5"
+ integrity sha512-xBMfFUP7TortCs0O+Xtez2W7Zu1PLH9bvJgtraN1CDST6LBM/eTOZ9SfwS/lvV8yOfcDpFmwf9bq5cYbXvqsvA==
+ dependencies:
+ "@babel/core" "^7.1.0"
+ "@jest/types" "^24.8.0"
+ babel-plugin-istanbul "^5.1.0"
+ chalk "^2.0.1"
+ convert-source-map "^1.4.0"
+ fast-json-stable-stringify "^2.0.0"
+ graceful-fs "^4.1.15"
+ jest-haste-map "^24.8.0"
+ jest-regex-util "^24.3.0"
+ jest-util "^24.8.0"
+ micromatch "^3.1.10"
+ realpath-native "^1.1.0"
+ slash "^2.0.0"
+ source-map "^0.6.1"
+ write-file-atomic "2.4.1"
+
+"@jest/types@^24.8.0":
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.8.0.tgz#f31e25948c58f0abd8c845ae26fcea1491dea7ad"
+ integrity sha512-g17UxVr2YfBtaMUxn9u/4+siG1ptg9IGYAYwvpwn61nBg779RXnjE/m7CxYcIzEt0AbHZZAHSEZNhkE2WxURVg==
+ dependencies:
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ "@types/istanbul-reports" "^1.1.1"
+ "@types/yargs" "^12.0.9"
+
"@mrmlnc/readdir-enhanced@^2.2.1":
version "2.2.1"
resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
@@ -702,6 +896,39 @@
resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.0.tgz#d1d55958d1fccc5527d4aba29fc9c4b942f563ff"
integrity sha512-7WcbyctkE8GTzogDb0ulRAEw7v8oIS54ft9mQTU7PfM0hp5e+8kpa+HeQ7IQrFbKtJXBKcZ4bh+Em9dTw5L6AQ==
+"@types/babel__core@^7.1.0":
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.2.tgz#608c74f55928033fce18b99b213c16be4b3d114f"
+ integrity sha512-cfCCrFmiGY/yq0NuKNxIQvZFy9kY/1immpSpTngOnyIbD4+eJOG5mxphhHDv3CHL9GltO4GcKr54kGBg3RNdbg==
+ dependencies:
+ "@babel/parser" "^7.1.0"
+ "@babel/types" "^7.0.0"
+ "@types/babel__generator" "*"
+ "@types/babel__template" "*"
+ "@types/babel__traverse" "*"
+
+"@types/babel__generator@*":
+ version "7.0.2"
+ resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.0.2.tgz#d2112a6b21fad600d7674274293c85dce0cb47fc"
+ integrity sha512-NHcOfab3Zw4q5sEE2COkpfXjoE7o+PmqD9DQW4koUT3roNxwziUdXGnRndMat/LJNUtePwn1TlP4do3uoe3KZQ==
+ dependencies:
+ "@babel/types" "^7.0.0"
+
+"@types/babel__template@*":
+ version "7.0.2"
+ resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.2.tgz#4ff63d6b52eddac1de7b975a5223ed32ecea9307"
+ integrity sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==
+ dependencies:
+ "@babel/parser" "^7.1.0"
+ "@babel/types" "^7.0.0"
+
+"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6":
+ version "7.0.6"
+ resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.6.tgz#328dd1a8fc4cfe3c8458be9477b219ea158fd7b2"
+ integrity sha512-XYVgHF2sQ0YblLRMLNPB3CkFMewzFmlDsH/TneZFHUXDlABQgh88uOxuez7ZcXxayLFrqLwtDH1t+FmlFwNZxw==
+ dependencies:
+ "@babel/types" "^7.3.0"
+
"@types/events@*":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86"
@@ -716,6 +943,26 @@
"@types/minimatch" "*"
"@types/node" "*"
+"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
+ integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==
+
+"@types/istanbul-lib-report@*":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#e5471e7fa33c61358dd38426189c037a58433b8c"
+ integrity sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==
+ dependencies:
+ "@types/istanbul-lib-coverage" "*"
+
+"@types/istanbul-reports@^1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a"
+ integrity sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==
+ dependencies:
+ "@types/istanbul-lib-coverage" "*"
+ "@types/istanbul-lib-report" "*"
+
"@types/jquery@^2.0.40":
version "2.0.48"
resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-2.0.48.tgz#3e90d8cde2d29015e5583017f7830cb3975b2eef"
@@ -741,6 +988,11 @@
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45"
integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==
+"@types/stack-utils@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
+ integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==
+
"@types/tapable@*":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.4.tgz#b4ffc7dc97b498c969b360a41eee247f82616370"
@@ -786,6 +1038,11 @@
"@types/uglify-js" "*"
source-map "^0.6.0"
+"@types/yargs@^12.0.2", "@types/yargs@^12.0.9":
+ version "12.0.12"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.12.tgz#45dd1d0638e8c8f153e87d296907659296873916"
+ integrity sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw==
+
"@types/zen-observable@^0.8.0":
version "0.8.0"
resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d"
@@ -1070,9 +1327,9 @@ ansi-escapes@^1.1.0:
integrity sha1-06ioOzGapneTZisT52HHkRQiMG4=
ansi-escapes@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92"
- integrity sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
+ integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
ansi-html@0.0.7:
version "0.0.7"
@@ -1089,10 +1346,10 @@ ansi-regex@^3.0.0:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
-ansi-regex@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.0.0.tgz#70de791edf021404c3fd615aa89118ae0432e5a9"
- integrity sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==
+ansi-regex@^4.0.0, ansi-regex@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
+ integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
ansi-styles@^2.2.1:
version "2.2.1"
@@ -1148,6 +1405,24 @@ apollo-client@^2.5.1:
tslib "^1.9.3"
zen-observable "^0.8.0"
+apollo-link-batch-http@^1.2.11:
+ version "1.2.11"
+ resolved "https://registry.yarnpkg.com/apollo-link-batch-http/-/apollo-link-batch-http-1.2.11.tgz#ae42dbcc02820658e1e267d05bf2aae7ac208088"
+ integrity sha512-f+KEdbP51I3AeEaBDW2lKS3eaPK/1IXaTM9F2moj02s1hgC/TzeUORRuUeOExW8ggXveW1Jzp6aYMJ2SQkZJyA==
+ dependencies:
+ apollo-link "^1.2.11"
+ apollo-link-batch "^1.1.12"
+ apollo-link-http-common "^0.2.13"
+ tslib "^1.9.3"
+
+apollo-link-batch@^1.1.12:
+ version "1.1.12"
+ resolved "https://registry.yarnpkg.com/apollo-link-batch/-/apollo-link-batch-1.1.12.tgz#64eb231082f182b0395ef7ab903600627f6c7fe8"
+ integrity sha512-6NqLiB9tEGxRiyhtnX/7CPHkmFG0IXfEP7pC5kirhjV+4KxqBaWvJnJGKpGp7Owgdph7KJlV+9+niOKEkcwreg==
+ dependencies:
+ apollo-link "^1.2.11"
+ tslib "^1.9.3"
+
apollo-link-dedup@^1.0.0:
version "1.0.10"
resolved "https://registry.yarnpkg.com/apollo-link-dedup/-/apollo-link-dedup-1.0.10.tgz#7b94589fe7f969777efd18a129043c78430800ae"
@@ -1155,7 +1430,7 @@ apollo-link-dedup@^1.0.0:
dependencies:
apollo-link "^1.2.3"
-apollo-link-http-common@^0.2.8:
+apollo-link-http-common@^0.2.13, apollo-link-http-common@^0.2.8:
version "0.2.13"
resolved "https://registry.yarnpkg.com/apollo-link-http-common/-/apollo-link-http-common-0.2.13.tgz#c688f6baaffdc7b269b2db7ae89dae7c58b5b350"
integrity sha512-Uyg1ECQpTTA691Fwx5e6Rc/6CPSu4TB4pQRTGIpwZ4l5JDOQ+812Wvi/e3IInmzOZpwx5YrrOfXrtN8BrsDXoA==
@@ -1205,9 +1480,9 @@ aproba@^1.0.3, aproba@^1.1.1:
integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
are-we-there-yet@~1.1.2:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d"
- integrity sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
+ integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==
dependencies:
delegates "^1.0.0"
readable-stream "^2.0.6"
@@ -1354,12 +1629,12 @@ async@1.x, async@^1.5.2:
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=
-async@^2.0.0, async@^2.5.0, async@^2.6.1:
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610"
- integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==
+async@^2.0.0, async@^2.6.1:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381"
+ integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==
dependencies:
- lodash "^4.17.10"
+ lodash "^4.17.11"
asynckit@^0.4.0:
version "0.4.0"
@@ -1439,13 +1714,16 @@ babel-eslint@^10.0.1:
eslint-scope "3.7.1"
eslint-visitor-keys "^1.0.0"
-babel-jest@^24.1.0:
- version "24.1.0"
- resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.1.0.tgz#441e23ef75ded3bd547e300ac3194cef87b55190"
- integrity sha512-MLcagnVrO9ybQGLEfZUqnOzv36iQzU7Bj4elm39vCukumLVSfoX+tRy3/jW7lUKc7XdpRmB/jech6L/UCsSZjw==
+babel-jest@^24.1.0, babel-jest@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.8.0.tgz#5c15ff2b28e20b0f45df43fe6b7f2aae93dba589"
+ integrity sha512-+5/kaZt4I9efoXzPlZASyK/lN9qdRKmmUav9smVc0ruPQD7IsfucQ87gpOE8mn2jbDuS6M/YOW6n3v9ZoIfgnw==
dependencies:
+ "@jest/transform" "^24.8.0"
+ "@jest/types" "^24.8.0"
+ "@types/babel__core" "^7.1.0"
babel-plugin-istanbul "^5.1.0"
- babel-preset-jest "^24.1.0"
+ babel-preset-jest "^24.6.0"
chalk "^2.4.2"
slash "^2.0.0"
@@ -1475,10 +1753,12 @@ babel-plugin-istanbul@^5.1.0:
istanbul-lib-instrument "^3.0.0"
test-exclude "^5.0.0"
-babel-plugin-jest-hoist@^24.1.0:
- version "24.1.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.1.0.tgz#dfecc491fb15e2668abbd690a697a8fd1411a7f8"
- integrity sha512-gljYrZz8w1b6fJzKcsfKsipSru2DU2DmQ39aB6nV3xQ0DDv3zpIzKGortA5gknrhNnPN8DweaEgrnZdmbGmhnw==
+babel-plugin-jest-hoist@^24.6.0:
+ version "24.6.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.6.0.tgz#f7f7f7ad150ee96d7a5e8e2c5da8319579e78019"
+ integrity sha512-3pKNH6hMt9SbOv0F3WVmy5CWQ4uogS3k0GY5XLyQHJ9EGpAT9XWkFd2ZiXXtkwFHdAHa5j7w7kfxSP5lAIwu7w==
+ dependencies:
+ "@types/babel__traverse" "^7.0.6"
babel-plugin-rewire@^1.2.0:
version "1.2.0"
@@ -1494,13 +1774,13 @@ babel-polyfill@6.23.0:
core-js "^2.4.0"
regenerator-runtime "^0.10.0"
-babel-preset-jest@^24.1.0:
- version "24.1.0"
- resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.1.0.tgz#83bc564fdcd4903641af65ec63f2f5de6b04132e"
- integrity sha512-FfNLDxFWsNX9lUmtwY7NheGlANnagvxq8LZdl5PKnVG3umP+S/g0XbVBfwtA4Ai3Ri/IMkWabBz3Tyk9wdspcw==
+babel-preset-jest@^24.6.0:
+ version "24.6.0"
+ resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.6.0.tgz#66f06136eefce87797539c0d63f1769cc3915984"
+ integrity sha512-pdZqLEdmy1ZK5kyRUfvBb2IfTPb2BUvIJczlPspS8fWmBQslNNDBqVfh7BW5leOVJMDZKzjD8XEyABTk6gQ5yw==
dependencies:
"@babel/plugin-syntax-object-rest-spread" "^7.0.0"
- babel-plugin-jest-hoist "^24.1.0"
+ babel-plugin-jest-hoist "^24.6.0"
babel-runtime@^6.22.0:
version "6.26.0"
@@ -1698,17 +1978,15 @@ braces@^0.1.2:
expand-range "^0.1.0"
braces@^2.3.0, braces@^2.3.1:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.1.tgz#7086c913b4e5a08dbe37ac0ee6a2500c4ba691bb"
- integrity sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ==
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
+ integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==
dependencies:
arr-flatten "^1.1.0"
array-unique "^0.3.2"
- define-property "^1.0.0"
extend-shallow "^2.0.1"
fill-range "^4.0.0"
isobject "^3.0.1"
- kind-of "^6.0.2"
repeat-element "^1.1.2"
snapdragon "^0.8.1"
snapdragon-node "^2.0.1"
@@ -1790,14 +2068,14 @@ browserify-zlib@^0.2.0:
dependencies:
pako "~1.0.5"
-browserslist@^4.3.4, browserslist@^4.4.1:
- version "4.4.1"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.4.1.tgz#42e828954b6b29a7a53e352277be429478a69062"
- integrity sha512-pEBxEXg7JwaakBXjATYw/D1YZh4QUSCX/Mnd/wnqSRPPSi1U39iDhDoKGoBUcraKdxDlrYqJxSI5nNvD+dWP2A==
+browserslist@^4.4.1, browserslist@^4.5.2, browserslist@^4.5.4:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.6.0.tgz#5274028c26f4d933d5b1323307c1d1da5084c9ff"
+ integrity sha512-Jk0YFwXBuMOOol8n6FhgkDzn3mY9PYLYGk29zybF05SbRTsMgPqmTNeQQhOghCxq5oFqAXE3u4sYddr4C0uRhg==
dependencies:
- caniuse-lite "^1.0.30000929"
- electron-to-chromium "^1.3.103"
- node-releases "^1.1.3"
+ caniuse-lite "^1.0.30000967"
+ electron-to-chromium "^1.3.133"
+ node-releases "^1.1.19"
bs-logger@0.x:
version "0.2.6"
@@ -1985,21 +2263,21 @@ camelcase@^4.0.0, camelcase@^4.1.0:
integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
camelcase@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42"
- integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
+ integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
-caniuse-lite@^1.0.30000929, caniuse-lite@^1.0.30000932:
- version "1.0.30000936"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000936.tgz#5d33b118763988bf721b9b8ad436d0400e4a116b"
- integrity sha512-orX4IdpbFhdNO7bTBhSbahp1EBpqzBc+qrvTRVUFfZgA4zta7TdM6PN5ZxkEUgDnz36m+PfWGcdX7AVfFWItJw==
+caniuse-lite@^1.0.30000932, caniuse-lite@^1.0.30000967:
+ version "1.0.30000969"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000969.tgz#7664f571f2072657bde70b00a1fc1ba41f1942a9"
+ integrity sha512-Kus0yxkoAJgVc0bax7S4gLSlFifCa7MnSZL9p9VuS/HIKEL4seaqh28KIQAAO50cD/rJ5CiJkJFapkdDAlhFxQ==
-capture-exit@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f"
- integrity sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28=
+capture-exit@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4"
+ integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==
dependencies:
- rsvp "^3.3.3"
+ rsvp "^4.8.4"
capture-stack-trace@^1.0.0:
version "1.0.0"
@@ -2126,7 +2404,7 @@ chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.0.4:
optionalDependencies:
fsevents "^1.2.2"
-chownr@^1.0.1, chownr@^1.1.1:
+chownr@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494"
integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==
@@ -2227,9 +2505,9 @@ cliui@^3.2.0:
wrap-ansi "^2.0.0"
cliui@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.0.0.tgz#743d4650e05f36d1ed2575b59638d87322bfbbcc"
- integrity sha512-nY3W5Gu2racvdDk//ELReY+dHjb9PlIcVDFXP72nVIhq2Gy3LuVXYwJoPVudwQnv1shtohpgkdCKT2YaKY0CKw==
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
+ integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==
dependencies:
string-width "^2.1.1"
strip-ansi "^4.0.0"
@@ -2328,10 +2606,10 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
dependencies:
delayed-stream "~1.0.0"
-commander@2, commander@^2.10.0, commander@^2.16.0, commander@^2.18.0, commander@^2.19.0:
- version "2.19.0"
- resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
- integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
+commander@2, commander@^2.10.0, commander@^2.16.0, commander@^2.18.0, commander@^2.19.0, commander@~2.20.0:
+ version "2.20.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
+ integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
commander@~2.17.1:
version "2.17.1"
@@ -2525,11 +2803,36 @@ copy-to-clipboard@^3.0.8:
dependencies:
toggle-selection "^1.0.3"
-core-js@^2.2.0, core-js@^2.4.0, core-js@^2.4.1:
+core-js-compat@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.0.1.tgz#bff73ba31ca8687431b9c88f78d3362646fb76f0"
+ integrity sha512-2pC3e+Ht/1/gD7Sim/sqzvRplMiRnFQVlPpDVaHtY9l7zZP7knamr3VRD6NyGfHd84MrDC0tAM9ulNxYMW0T3g==
+ dependencies:
+ browserslist "^4.5.4"
+ core-js "3.0.1"
+ core-js-pure "3.0.1"
+ semver "^6.0.0"
+
+core-js-pure@3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.0.1.tgz#37358fb0d024e6b86d443d794f4e37e949098cbe"
+ integrity sha512-mSxeQ6IghKW3MoyF4cz19GJ1cMm7761ON+WObSyLfTu/Jn3x7w4NwNFnrZxgl4MTSvYYepVLNuRtlB4loMwJ5g==
+
+core-js@3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.0.1.tgz#1343182634298f7f38622f95e73f54e48ddf4738"
+ integrity sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew==
+
+core-js@^2.2.0, core-js@^2.4.0:
version "2.5.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e"
integrity sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==
+core-js@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.1.3.tgz#95700bca5f248f5f78c0ec63e784eca663ec4138"
+ integrity sha512-PWZ+ZfuaKf178BIAg+CRsljwjIMRV8MY00CbZczkR6Zk5LfkSkjGoaab3+bqRQWVITNZxQB7TFYz+CFcyuamvA==
+
core-js@~2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.3.0.tgz#fab83fbb0b2d8dc85fa636c4b9d34c75420c6d65"
@@ -2735,17 +3038,17 @@ cyclist@~0.2.2:
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=
-d3-array@1, d3-array@1.2.1, d3-array@^1.2.0, d3-array@^1.2.1:
+d3-array@1, d3-array@1.2.1, d3-array@^1.1.1, d3-array@^1.2.0, d3-array@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.1.tgz#d1ca33de2f6ac31efadb8e050a021d7e2396d5dc"
integrity sha512-CyINJQ0SOUHojDdFDH4JEM0552vCR1utGyLHegJHyYH0JyCpSeTPxi4OBqHMA2jJZq4NH782LtaJWBImqI/HBw==
-d3-axis@1.0.8, d3-axis@^1.0.8:
+d3-axis@1, d3-axis@1.0.8, d3-axis@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-1.0.8.tgz#31a705a0b535e65759de14173a31933137f18efa"
integrity sha1-MacFoLU15ldZ3hQXOjGTMTfxjvo=
-d3-brush@1.0.4, d3-brush@^1.0.4:
+d3-brush@1, d3-brush@1.0.4, d3-brush@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-1.0.4.tgz#00c2f238019f24f6c0a194a26d41a1530ffe7bc4"
integrity sha1-AMLyOAGfJPbAoZSibUGhUw/+e8Q=
@@ -2756,7 +3059,7 @@ d3-brush@1.0.4, d3-brush@^1.0.4:
d3-selection "1"
d3-transition "1"
-d3-chord@1.0.4:
+d3-chord@1, d3-chord@1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-1.0.4.tgz#7dec4f0ba886f713fe111c45f763414f6f74ca2c"
integrity sha1-fexPC6iG9xP+ERxF92NBT290yiw=
@@ -2774,6 +3077,13 @@ d3-color@1, d3-color@1.0.3:
resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.0.3.tgz#bc7643fca8e53a8347e2fbdaffa236796b58509b"
integrity sha1-vHZD/KjlOoNH4vva/6I2eWtYUJs=
+d3-contour@1:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-1.3.2.tgz#652aacd500d2264cb3423cee10db69f6f59bead3"
+ integrity sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==
+ dependencies:
+ d3-array "^1.1.1"
+
d3-dispatch@1, d3-dispatch@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-1.0.3.tgz#46e1491eaa9b58c358fce5be4e8bed626e7871f8"
@@ -2801,7 +3111,14 @@ d3-ease@1, d3-ease@1.0.3, d3-ease@^1.0.3:
resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-1.0.3.tgz#68bfbc349338a380c44d8acc4fbc3304aa2d8c0e"
integrity sha1-aL+8NJM4o4DETYrMT7wzBKotjA4=
-d3-force@1.1.0:
+d3-fetch@1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-1.1.2.tgz#957c8fbc6d4480599ba191b1b2518bf86b3e1be2"
+ integrity sha512-S2loaQCV/ZeyTyIF2oP8D1K9Z4QizUzW7cWeAOAS4U88qOt3Ucf6GsmgthuYSdyB2HyEm4CeGvkQxWsmInsIVA==
+ dependencies:
+ d3-dsv "1"
+
+d3-force@1, d3-force@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-1.1.0.tgz#cebf3c694f1078fcc3d4daf8e567b2fbd70d4ea3"
integrity sha512-2HVQz3/VCQs0QeRNZTYb7GxoUCeb6bOzMp/cGcLa87awY9ZsPvXOGeZm0iaGBjXic6I1ysKwMn+g+5jSAdzwcg==
@@ -2816,14 +3133,14 @@ d3-format@1, d3-format@1.2.2:
resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.2.2.tgz#1a39c479c8a57fe5051b2e67a3bee27061a74e7a"
integrity sha512-zH9CfF/3C8zUI47nsiKfD0+AGDEuM8LwBIP7pBVpyR4l/sKkZqITmMtxRp04rwBrlshIZ17XeFAaovN3++wzkw==
-d3-geo@1.9.1:
+d3-geo@1, d3-geo@1.9.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-1.9.1.tgz#157e3b0f917379d0f73bebfff3be537f49fa7356"
integrity sha512-l9wL/cEQkyZQYXw3xbmLsH3eQ5ij+icNfo4r0GrLa5rOCZR/e/3am45IQ0FvQ5uMsv+77zBRunLc9ufTWSQYFA==
dependencies:
d3-array "1"
-d3-hierarchy@1.1.5:
+d3-hierarchy@1, d3-hierarchy@1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-1.1.5.tgz#a1c845c42f84a206bcf1c01c01098ea4ddaa7a26"
integrity sha1-ochFxC+Eoga88cAcAQmOpN2qeiY=
@@ -2840,7 +3157,7 @@ d3-path@1, d3-path@1.0.5:
resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.5.tgz#241eb1849bd9e9e8021c0d0a799f8a0e8e441764"
integrity sha1-JB6xhJvZ6egCHA0KeZ+KDo5EF2Q=
-d3-polygon@1.0.3:
+d3-polygon@1, d3-polygon@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-1.0.3.tgz#16888e9026460933f2b179652ad378224d382c62"
integrity sha1-FoiOkCZGCTPysXllKtN4Ik04LGI=
@@ -2855,7 +3172,7 @@ d3-queue@3.0.7:
resolved "https://registry.yarnpkg.com/d3-queue/-/d3-queue-3.0.7.tgz#c93a2e54b417c0959129d7d73f6cf7d4292e7618"
integrity sha1-yTouVLQXwJWRKdfXP2z31Ckudhg=
-d3-random@1.1.0:
+d3-random@1, d3-random@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-1.1.0.tgz#6642e506c6fa3a648595d2b2469788a8d12529d3"
integrity sha1-ZkLlBsb6OmSFldKyRpeIqNElKdM=
@@ -2870,6 +3187,14 @@ d3-request@1.0.6:
d3-dsv "1"
xmlhttprequest "1"
+d3-scale-chromatic@1:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-1.3.3.tgz#dad4366f0edcb288f490128979c3c793583ed3c0"
+ integrity sha512-BWTipif1CimXcYfT02LKjAyItX5gKiwxuPRgr4xM58JwlLocWbjPLI7aMEjkcoOQXMkYsmNsvv3d2yl/OKuHHw==
+ dependencies:
+ d3-color "1"
+ d3-interpolate "1"
+
d3-scale@1.0.7, d3-scale@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-1.0.7.tgz#fa90324b3ea8a776422bd0472afab0b252a0945d"
@@ -2883,12 +3208,24 @@ d3-scale@1.0.7, d3-scale@^1.0.7:
d3-time "1"
d3-time-format "2"
+d3-scale@2:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-2.2.2.tgz#4e880e0b2745acaaddd3ede26a9e908a9e17b81f"
+ integrity sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==
+ dependencies:
+ d3-array "^1.2.0"
+ d3-collection "1"
+ d3-format "1"
+ d3-interpolate "1"
+ d3-time "1"
+ d3-time-format "2"
+
d3-selection@1, d3-selection@1.3.0, d3-selection@^1.1.0, d3-selection@^1.2.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.3.0.tgz#d53772382d3dc4f7507bfb28bcd2d6aed2a0ad6d"
integrity sha512-qgpUOg9tl5CirdqESUAu0t9MU/t3O9klYfGfyKsXEmhyxyzLpzpeh08gaxBUTQw1uXIOkr/30Ut2YRjSSxlmHA==
-d3-shape@1.2.0, d3-shape@^1.2.0:
+d3-shape@1, d3-shape@1.2.0, d3-shape@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.2.0.tgz#45d01538f064bafd05ea3d6d2cb748fd8c41f777"
integrity sha1-RdAVOPBkuv0F6j1tLLdI/YxB93c=
@@ -2924,12 +3261,12 @@ d3-transition@1, d3-transition@1.1.1, d3-transition@^1.1.1:
d3-selection "^1.1.0"
d3-timer "1"
-d3-voronoi@1.1.2:
+d3-voronoi@1, d3-voronoi@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/d3-voronoi/-/d3-voronoi-1.1.2.tgz#1687667e8f13a2d158c80c1480c5a29cb0d8973c"
integrity sha1-Fodmfo8TotFYyAwUgMWinLDYlzw=
-d3-zoom@1.7.1:
+d3-zoom@1, d3-zoom@1.7.1:
version "1.7.1"
resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-1.7.1.tgz#02f43b3c3e2db54f364582d7e4a236ccc5506b63"
integrity sha512-sZHQ55DGq5BZBFGnRshUT8tm2sfhPHFnOlmPbbwTkAoPeVdRTkB4Xsf9GCY0TSHrTD8PeJPZGmP/TpGicwJDJQ==
@@ -2976,6 +3313,43 @@ d3@^4.13.0:
d3-voronoi "1.1.2"
d3-zoom "1.7.1"
+d3@^5.7.0:
+ version "5.9.2"
+ resolved "https://registry.yarnpkg.com/d3/-/d3-5.9.2.tgz#64e8a7e9c3d96d9e6e4999d2c8a2c829767e67f5"
+ integrity sha512-ydrPot6Lm3nTWH+gJ/Cxf3FcwuvesYQ5uk+j/kXEH/xbuYWYWTMAHTJQkyeuG8Y5WM5RSEYB41EctUrXQQytRQ==
+ dependencies:
+ d3-array "1"
+ d3-axis "1"
+ d3-brush "1"
+ d3-chord "1"
+ d3-collection "1"
+ d3-color "1"
+ d3-contour "1"
+ d3-dispatch "1"
+ d3-drag "1"
+ d3-dsv "1"
+ d3-ease "1"
+ d3-fetch "1"
+ d3-force "1"
+ d3-format "1"
+ d3-geo "1"
+ d3-hierarchy "1"
+ d3-interpolate "1"
+ d3-path "1"
+ d3-polygon "1"
+ d3-quadtree "1"
+ d3-random "1"
+ d3-scale "2"
+ d3-scale-chromatic "1"
+ d3-selection "1"
+ d3-shape "1"
+ d3-time "1"
+ d3-time-format "2"
+ d3-timer "1"
+ d3-transition "1"
+ d3-voronoi "1"
+ d3-zoom "1"
+
dagre-d3-renderer@^0.5.8:
version "0.5.8"
resolved "https://registry.yarnpkg.com/dagre-d3-renderer/-/dagre-d3-renderer-0.5.8.tgz#aa071bb71d3c4d67426925906f3f6ddead49c1a3"
@@ -3028,14 +3402,14 @@ de-indent@^1.0.2:
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=
-debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
+debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
dependencies:
ms "2.0.0"
-debug@^3.1.0, debug@^3.2.5:
+debug@^3.1.0, debug@^3.2.5, debug@^3.2.6:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
@@ -3240,10 +3614,10 @@ di@^0.0.1:
resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=
-diff-sequences@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.0.0.tgz#cdf8e27ed20d8b8d3caccb4e0c0d8fe31a173013"
- integrity sha512-46OkIuVGBBnrC0soO/4LHu5LHGHx0uhP65OVz8XOrAJpqiCB2aVIuESvjI1F9oqebuvY8lekS1pt6TN7vt7qsw==
+diff-sequences@^24.3.0:
+ version "24.3.0"
+ resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.3.0.tgz#0f20e8a1df1abddaf4d9c226680952e64118b975"
+ integrity sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw==
diff@^3.2.0, diff@^3.4.0:
version "3.5.0"
@@ -3442,10 +3816,10 @@ ejs@^2.6.1:
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0"
integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==
-electron-to-chromium@^1.3.103:
- version "1.3.113"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.113.tgz#b1ccf619df7295aea17bc6951dc689632629e4a9"
- integrity sha512-De+lPAxEcpxvqPTyZAXELNpRZXABRxf+uL/rSykstQhzj/B0l1150G/ExIIxKc16lI89Hgz81J0BHAcbTqK49g==
+electron-to-chromium@^1.3.133:
+ version "1.3.135"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.135.tgz#f5799b95f2bcd8de17cde47d63392d83a4477041"
+ integrity sha512-xXLNstRdVsisPF3pL3H9TVZo2XkMILfqtD6RiWIUmDK2sFX1Bjwqmd8LBp0Kuo2FgKO63JXPoEVGm8WyYdwP0Q==
elliptic@^6.0.0:
version "6.4.0"
@@ -3577,24 +3951,25 @@ error-ex@^1.2.0, error-ex@^1.3.1:
is-arrayish "^0.2.1"
es-abstract@^1.5.1, es-abstract@^1.6.1:
- version "1.12.0"
- resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165"
- integrity sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==
+ version "1.13.0"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9"
+ integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==
dependencies:
- es-to-primitive "^1.1.1"
+ es-to-primitive "^1.2.0"
function-bind "^1.1.1"
- has "^1.0.1"
- is-callable "^1.1.3"
+ has "^1.0.3"
+ is-callable "^1.1.4"
is-regex "^1.0.4"
+ object-keys "^1.0.12"
-es-to-primitive@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d"
- integrity sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=
+es-to-primitive@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377"
+ integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==
dependencies:
- is-callable "^1.1.1"
+ is-callable "^1.1.4"
is-date-object "^1.0.1"
- is-symbol "^1.0.1"
+ is-symbol "^1.0.2"
es6-promise@~3.0.2:
version "3.0.2"
@@ -3915,12 +4290,10 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
md5.js "^1.3.4"
safe-buffer "^5.1.1"
-exec-sh@^0.2.0:
- version "0.2.2"
- resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36"
- integrity sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==
- dependencies:
- merge "^1.2.0"
+exec-sh@^0.3.2:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.2.tgz#6738de2eb7c8e671d0366aea0b0db8c6f7d7391b"
+ integrity sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg==
execa@^0.10.0:
version "0.10.0"
@@ -4010,16 +4383,17 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2:
dependencies:
homedir-polyfill "^1.0.1"
-expect@^24.1.0:
- version "24.1.0"
- resolved "https://registry.yarnpkg.com/expect/-/expect-24.1.0.tgz#88e73301c4c785cde5f16da130ab407bdaf8c0f2"
- integrity sha512-lVcAPhaYkQcIyMS+F8RVwzbm1jro20IG8OkvxQ6f1JfqhVZyyudCwYogQ7wnktlf14iF3ii7ArIUO/mqvrW9Gw==
+expect@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/expect/-/expect-24.8.0.tgz#471f8ec256b7b6129ca2524b2a62f030df38718d"
+ integrity sha512-/zYvP8iMDrzaaxHVa724eJBCKqSHmO0FA7EDkBiRHxg6OipmMn1fN+C8T9L9K8yr7UONkOifu6+LLH+z76CnaA==
dependencies:
+ "@jest/types" "^24.8.0"
ansi-styles "^3.2.0"
- jest-get-type "^24.0.0"
- jest-matcher-utils "^24.0.0"
- jest-message-util "^24.0.0"
- jest-regex-util "^24.0.0"
+ jest-get-type "^24.8.0"
+ jest-matcher-utils "^24.8.0"
+ jest-message-util "^24.8.0"
+ jest-regex-util "^24.3.0"
exports-loader@^0.7.0:
version "0.7.0"
@@ -4425,9 +4799,9 @@ fs-access@^1.0.0:
null-check "^1.0.0"
fs-minipass@^1.2.5:
- version "1.2.5"
- resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d"
- integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==
+ version "1.2.6"
+ resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07"
+ integrity sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ==
dependencies:
minipass "^2.2.1"
@@ -4446,13 +4820,13 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
-fsevents@^1.2.2, fsevents@^1.2.3:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426"
- integrity sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==
+fsevents@^1.2.2, fsevents@^1.2.7:
+ version "1.2.9"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f"
+ integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==
dependencies:
- nan "^2.9.2"
- node-pre-gyp "^0.10.0"
+ nan "^2.12.1"
+ node-pre-gyp "^0.12.0"
fstream@^1.0.0, fstream@^1.0.2:
version "1.0.11"
@@ -4501,9 +4875,9 @@ gaze@^1.0.0:
globule "^1.0.0"
get-caller-file@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
- integrity sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
+ integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
get-stdin@^4.0.1:
version "4.0.1"
@@ -4575,9 +4949,9 @@ glob-to-regexp@^0.3.0:
integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=
"glob@5 - 7", glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@~7.1.1:
- version "7.1.3"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
- integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==
+ version "7.1.4"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255"
+ integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
@@ -4646,9 +5020,9 @@ global-prefix@^3.0.0:
which "^1.3.1"
globals@^11.1.0, globals@^11.7.0:
- version "11.7.0"
- resolved "https://registry.yarnpkg.com/globals/-/globals-11.7.0.tgz#a583faa43055b1aca771914bf68258e2fc125673"
- integrity sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==
+ version "11.12.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
+ integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
globby@^5.0.0:
version "5.0.0"
@@ -4796,12 +5170,12 @@ handle-thing@^2.0.0:
resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754"
integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==
-handlebars@^4.0.1, handlebars@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.0.tgz#0d6a6f34ff1f63cecec8423aa4169827bf787c3a"
- integrity sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w==
+handlebars@^4.0.1, handlebars@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67"
+ integrity sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==
dependencies:
- async "^2.5.0"
+ neo-async "^2.6.0"
optimist "^0.6.1"
source-map "^0.6.1"
optionalDependencies:
@@ -4937,10 +5311,10 @@ hash.js@^1.0.0, hash.js@^1.0.3:
inherits "^2.0.3"
minimalistic-assert "^1.0.0"
-he@^1.1.0, he@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
- integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
+he@^1.1.0, he@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
+ integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
highlight.js@^9.13.1, highlight.js@~9.13.0:
version "9.13.1"
@@ -5364,7 +5738,7 @@ is-buffer@^2.0.0:
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725"
integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==
-is-callable@^1.1.1, is-callable@^1.1.3:
+is-callable@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==
@@ -5467,9 +5841,9 @@ is-fullwidth-code-point@^2.0.0:
integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
is-generator-fn@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.0.0.tgz#038c31b774709641bda678b1f06a4e3227c10b3e"
- integrity sha512-elzyIdM7iKoFHzcrndIqjYomImhxrFRnGP3galODoII4TB9gI7mZ+FnlLQmmjf27SxHS2gKEeyhX5/+YRS6H9g==
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
+ integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==
is-glob@^3.1.0:
version "3.1.0"
@@ -5515,11 +5889,6 @@ is-number@^3.0.0:
dependencies:
kind-of "^3.0.2"
-is-number@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
- integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==
-
is-obj@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
@@ -5530,13 +5899,6 @@ is-object@^1.0.1:
resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470"
integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA=
-is-odd@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-2.0.0.tgz#7646624671fd7ea558ccd9a2795182f2958f1b24"
- integrity sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==
- dependencies:
- is-number "^4.0.0"
-
is-path-cwd@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
@@ -5610,7 +5972,7 @@ is-supported-regexp-flag@^1.0.0:
resolved "https://registry.yarnpkg.com/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.1.tgz#21ee16518d2c1dd3edd3e9a0d57e50207ac364ca"
integrity sha512-3vcJecUUrpgCqc/ca0aWeNu64UGgxcvO60K/Fkr1N6RSvfGCTU60UKN68JDmKokgba0rFFJs12EnzOQa14ubKQ==
-is-symbol@^1.0.1:
+is-symbol@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38"
integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==
@@ -5684,7 +6046,7 @@ isstream@~0.1.2:
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
-istanbul-api@^2.0.5, istanbul-api@^2.0.8:
+istanbul-api@^2.0.5:
version "2.1.1"
resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-2.1.1.tgz#194b773f6d9cbc99a9258446848b0f988951c4d0"
integrity sha512-kVmYrehiwyeBAk/wE71tW6emzLiHGjYIiDrc8sfyty4F8M02/lrgXSm+R1kXysmF20zArvmZXjlE/mg24TVPJw==
@@ -5703,57 +6065,57 @@ istanbul-api@^2.0.5, istanbul-api@^2.0.8:
minimatch "^3.0.4"
once "^1.4.0"
-istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#0b891e5ad42312c2b9488554f603795f9a2211ba"
- integrity sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw==
+istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.3, istanbul-lib-coverage@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49"
+ integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==
istanbul-lib-hook@^2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.3.tgz#e0e581e461c611be5d0e5ef31c5f0109759916fb"
- integrity sha512-CLmEqwEhuCYtGcpNVJjLV1DQyVnIqavMLFHV/DP+np/g3qvdxu3gsPqYoJMXm15sN84xOlckFB3VNvRbf5yEgA==
+ version "2.0.7"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz#c95695f383d4f8f60df1f04252a9550e15b5b133"
+ integrity sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==
dependencies:
append-transform "^1.0.0"
istanbul-lib-instrument@^3.0.0, istanbul-lib-instrument@^3.0.1, istanbul-lib-instrument@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.1.0.tgz#a2b5484a7d445f1f311e93190813fa56dfb62971"
- integrity sha512-ooVllVGT38HIk8MxDj/OIHXSYvH+1tq/Vb38s8ixt9GoJadXska4WkGY+0wkmtYCZNYtaARniH/DixUGGLZ0uA==
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630"
+ integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==
dependencies:
- "@babel/generator" "^7.0.0"
- "@babel/parser" "^7.0.0"
- "@babel/template" "^7.0.0"
- "@babel/traverse" "^7.0.0"
- "@babel/types" "^7.0.0"
- istanbul-lib-coverage "^2.0.3"
- semver "^5.5.0"
+ "@babel/generator" "^7.4.0"
+ "@babel/parser" "^7.4.3"
+ "@babel/template" "^7.4.0"
+ "@babel/traverse" "^7.4.3"
+ "@babel/types" "^7.4.0"
+ istanbul-lib-coverage "^2.0.5"
+ semver "^6.0.0"
istanbul-lib-report@^2.0.4:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.4.tgz#bfd324ee0c04f59119cb4f07dab157d09f24d7e4"
- integrity sha512-sOiLZLAWpA0+3b5w5/dq0cjm2rrNdAfHWaGhmn7XEFW6X++IV9Ohn+pnELAl9K3rfpaeBfbmH9JU5sejacdLeA==
+ version "2.0.8"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33"
+ integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==
dependencies:
- istanbul-lib-coverage "^2.0.3"
- make-dir "^1.3.0"
- supports-color "^6.0.0"
+ istanbul-lib-coverage "^2.0.5"
+ make-dir "^2.1.0"
+ supports-color "^6.1.0"
istanbul-lib-source-maps@^3.0.1, istanbul-lib-source-maps@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.2.tgz#f1e817229a9146e8424a28e5d69ba220fda34156"
- integrity sha512-JX4v0CiKTGp9fZPmoxpu9YEkPbEqCqBbO3403VabKjH+NRXo72HafD5UgnjTEqHL2SAjaZK1XDuDOkn6I5QVfQ==
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8"
+ integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==
dependencies:
debug "^4.1.1"
- istanbul-lib-coverage "^2.0.3"
- make-dir "^1.3.0"
- rimraf "^2.6.2"
+ istanbul-lib-coverage "^2.0.5"
+ make-dir "^2.1.0"
+ rimraf "^2.6.3"
source-map "^0.6.1"
istanbul-reports@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.1.1.tgz#72ef16b4ecb9a4a7bd0e2001e00f95d1eec8afa9"
- integrity sha512-FzNahnidyEPBCI0HcufJoSEoKykesRlFcSzQqjH9x0+LC8tnnE/p/90PBLu8iZTxr8yYZNyTtiAujUqyN+CIxw==
+ version "2.2.6"
+ resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.6.tgz#7b4f2660d82b29303a8fe6091f8ca4bf058da1af"
+ integrity sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==
dependencies:
- handlebars "^4.1.0"
+ handlebars "^4.1.2"
istanbul@^0.4.5:
version "0.4.5"
@@ -5819,158 +6181,152 @@ jed@^1.1.1:
resolved "https://registry.yarnpkg.com/jed/-/jed-1.1.1.tgz#7a549bbd9ffe1585b0cd0a191e203055bee574b4"
integrity sha1-elSbvZ/+FYWwzQoZHiAwVb7ldLQ=
-jest-changed-files@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.0.0.tgz#c02c09a8cc9ca93f513166bc773741bd39898ff7"
- integrity sha512-nnuU510R9U+UX0WNb5XFEcsrMqriSiRLeO9KWDFgPrpToaQm60prfQYpxsXigdClpvNot5bekDY440x9dNGnsQ==
+jest-changed-files@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.8.0.tgz#7e7eb21cf687587a85e50f3d249d1327e15b157b"
+ integrity sha512-qgANC1Yrivsq+UrLXsvJefBKVoCsKB0Hv+mBb6NMjjZ90wwxCDmU3hsCXBya30cH+LnPYjwgcU65i6yJ5Nfuug==
dependencies:
+ "@jest/types" "^24.8.0"
execa "^1.0.0"
throat "^4.0.0"
-jest-cli@^24.1.0:
- version "24.1.0"
- resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.1.0.tgz#f7cc98995f36e7210cce3cbb12974cbf60940843"
- integrity sha512-U/iyWPwOI0T1CIxVLtk/2uviOTJ/OiSWJSe8qt6X1VkbbgP+nrtLJlmT9lPBe4lK78VNFJtrJ7pttcNv/s7yCw==
+jest-cli@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.8.0.tgz#b075ac914492ed114fa338ade7362a301693e989"
+ integrity sha512-+p6J00jSMPQ116ZLlHJJvdf8wbjNbZdeSX9ptfHX06/MSNaXmKihQzx5vQcw0q2G6JsdVkUIdWbOWtSnaYs3yA==
dependencies:
- ansi-escapes "^3.0.0"
+ "@jest/core" "^24.8.0"
+ "@jest/test-result" "^24.8.0"
+ "@jest/types" "^24.8.0"
chalk "^2.0.1"
exit "^0.1.2"
- glob "^7.1.2"
- graceful-fs "^4.1.15"
import-local "^2.0.0"
is-ci "^2.0.0"
- istanbul-api "^2.0.8"
- istanbul-lib-coverage "^2.0.2"
- istanbul-lib-instrument "^3.0.1"
- istanbul-lib-source-maps "^3.0.1"
- jest-changed-files "^24.0.0"
- jest-config "^24.1.0"
- jest-environment-jsdom "^24.0.0"
- jest-get-type "^24.0.0"
- jest-haste-map "^24.0.0"
- jest-message-util "^24.0.0"
- jest-regex-util "^24.0.0"
- jest-resolve-dependencies "^24.1.0"
- jest-runner "^24.1.0"
- jest-runtime "^24.1.0"
- jest-snapshot "^24.1.0"
- jest-util "^24.0.0"
- jest-validate "^24.0.0"
- jest-watcher "^24.0.0"
- jest-worker "^24.0.0"
- micromatch "^3.1.10"
- node-notifier "^5.2.1"
- p-each-series "^1.0.0"
- pirates "^4.0.0"
+ jest-config "^24.8.0"
+ jest-util "^24.8.0"
+ jest-validate "^24.8.0"
prompts "^2.0.1"
- realpath-native "^1.0.0"
- rimraf "^2.5.4"
- slash "^2.0.0"
- string-length "^2.0.0"
- strip-ansi "^5.0.0"
- which "^1.2.12"
+ realpath-native "^1.1.0"
yargs "^12.0.2"
-jest-config@^24.1.0:
- version "24.1.0"
- resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.1.0.tgz#6ea6881cfdd299bc86cc144ee36d937c97c3850c"
- integrity sha512-FbbRzRqtFC6eGjG5VwsbW4E5dW3zqJKLWYiZWhB0/4E5fgsMw8GODLbGSrY5t17kKOtCWb/Z7nsIThRoDpuVyg==
+jest-config@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.8.0.tgz#77db3d265a6f726294687cbbccc36f8a76ee0f4f"
+ integrity sha512-Czl3Nn2uEzVGsOeaewGWoDPD8GStxCpAe0zOYs2x2l0fZAgPbCr3uwUkgNKV3LwE13VXythM946cd5rdGkkBZw==
dependencies:
"@babel/core" "^7.1.0"
- babel-jest "^24.1.0"
+ "@jest/test-sequencer" "^24.8.0"
+ "@jest/types" "^24.8.0"
+ babel-jest "^24.8.0"
chalk "^2.0.1"
glob "^7.1.1"
- jest-environment-jsdom "^24.0.0"
- jest-environment-node "^24.0.0"
- jest-get-type "^24.0.0"
- jest-jasmine2 "^24.1.0"
- jest-regex-util "^24.0.0"
- jest-resolve "^24.1.0"
- jest-util "^24.0.0"
- jest-validate "^24.0.0"
+ jest-environment-jsdom "^24.8.0"
+ jest-environment-node "^24.8.0"
+ jest-get-type "^24.8.0"
+ jest-jasmine2 "^24.8.0"
+ jest-regex-util "^24.3.0"
+ jest-resolve "^24.8.0"
+ jest-util "^24.8.0"
+ jest-validate "^24.8.0"
micromatch "^3.1.10"
- pretty-format "^24.0.0"
- realpath-native "^1.0.2"
+ pretty-format "^24.8.0"
+ realpath-native "^1.1.0"
-jest-diff@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.0.0.tgz#a3e5f573dbac482f7d9513ac9cfa21644d3d6b34"
- integrity sha512-XY5wMpRaTsuMoU+1/B2zQSKQ9RdE9gsLkGydx3nvApeyPijLA8GtEvIcPwISRCer+VDf9W1mStTYYq6fPt8ryA==
+jest-diff@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.8.0.tgz#146435e7d1e3ffdf293d53ff97e193f1d1546172"
+ integrity sha512-wxetCEl49zUpJ/bvUmIFjd/o52J+yWcoc5ZyPq4/W1LUKGEhRYDIbP1KcF6t+PvqNrGAFk4/JhtxDq/Nnzs66g==
dependencies:
chalk "^2.0.1"
- diff-sequences "^24.0.0"
- jest-get-type "^24.0.0"
- pretty-format "^24.0.0"
+ diff-sequences "^24.3.0"
+ jest-get-type "^24.8.0"
+ pretty-format "^24.8.0"
-jest-docblock@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.0.0.tgz#54d77a188743e37f62181a91a01eb9222289f94e"
- integrity sha512-KfAKZ4SN7CFOZpWg4i7g7MSlY0M+mq7K0aMqENaG2vHuhC9fc3vkpU/iNN9sOus7v3h3Y48uEjqz3+Gdn2iptA==
+jest-docblock@^24.3.0:
+ version "24.3.0"
+ resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.3.0.tgz#b9c32dac70f72e4464520d2ba4aec02ab14db5dd"
+ integrity sha512-nlANmF9Yq1dufhFlKG9rasfQlrY7wINJbo3q01tu56Jv5eBU5jirylhF2O5ZBnLxzOVBGRDz/9NAwNyBtG4Nyg==
dependencies:
detect-newline "^2.1.0"
-jest-each@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.0.0.tgz#10987a06b21c7ffbfb7706c89d24c52ed864be55"
- integrity sha512-gFcbY4Cu55yxExXMkjrnLXov3bWO3dbPAW7HXb31h/DNWdNc/6X8MtxGff8nh3/MjkF9DpVqnj0KsPKuPK0cpA==
+jest-each@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.8.0.tgz#a05fd2bf94ddc0b1da66c6d13ec2457f35e52775"
+ integrity sha512-NrwK9gaL5+XgrgoCsd9svsoWdVkK4gnvyhcpzd6m487tXHqIdYeykgq3MKI1u4I+5Zf0tofr70at9dWJDeb+BA==
dependencies:
+ "@jest/types" "^24.8.0"
chalk "^2.0.1"
- jest-get-type "^24.0.0"
- jest-util "^24.0.0"
- pretty-format "^24.0.0"
-
-jest-environment-jsdom@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.0.0.tgz#5affa0654d6e44cd798003daa1a8701dbd6e4d11"
- integrity sha512-1YNp7xtxajTRaxbylDc2pWvFnfDTH5BJJGyVzyGAKNt/lEULohwEV9zFqTgG4bXRcq7xzdd+sGFws+LxThXXOw==
- dependencies:
- jest-mock "^24.0.0"
- jest-util "^24.0.0"
+ jest-get-type "^24.8.0"
+ jest-util "^24.8.0"
+ pretty-format "^24.8.0"
+
+jest-environment-jsdom@^24.0.0, jest-environment-jsdom@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.8.0.tgz#300f6949a146cabe1c9357ad9e9ecf9f43f38857"
+ integrity sha512-qbvgLmR7PpwjoFjM/sbuqHJt/NCkviuq9vus9NBn/76hhSidO+Z6Bn9tU8friecegbJL8gzZQEMZBQlFWDCwAQ==
+ dependencies:
+ "@jest/environment" "^24.8.0"
+ "@jest/fake-timers" "^24.8.0"
+ "@jest/types" "^24.8.0"
+ jest-mock "^24.8.0"
+ jest-util "^24.8.0"
jsdom "^11.5.1"
-jest-environment-node@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.0.0.tgz#330948980656ed8773ce2e04eb597ed91e3c7190"
- integrity sha512-62fOFcaEdU0VLaq8JL90TqwI7hLn0cOKOl8vY2n477vRkCJRojiRRtJVRzzCcgFvs6gqU97DNqX5R0BrBP6Rxg==
+jest-environment-node@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.8.0.tgz#d3f726ba8bc53087a60e7a84ca08883a4c892231"
+ integrity sha512-vIGUEScd1cdDgR6sqn2M08sJTRLQp6Dk/eIkCeO4PFHxZMOgy+uYLPMC4ix3PEfM5Au/x3uQ/5Tl0DpXXZsJ/Q==
dependencies:
- jest-mock "^24.0.0"
- jest-util "^24.0.0"
+ "@jest/environment" "^24.8.0"
+ "@jest/fake-timers" "^24.8.0"
+ "@jest/types" "^24.8.0"
+ jest-mock "^24.8.0"
+ jest-util "^24.8.0"
-jest-get-type@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.0.0.tgz#36e72930b78e33da59a4f63d44d332188278940b"
- integrity sha512-z6/Eyf6s9ZDGz7eOvl+fzpuJmN9i0KyTt1no37/dHu8galssxz5ZEgnc1KaV8R31q1khxyhB4ui/X5ZjjPk77w==
+jest-get-type@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.8.0.tgz#a7440de30b651f5a70ea3ed7ff073a32dfe646fc"
+ integrity sha512-RR4fo8jEmMD9zSz2nLbs2j0zvPpk/KCEz3a62jJWbd2ayNo0cb+KFRxPHVhE4ZmgGJEQp0fosmNz84IfqM8cMQ==
-jest-haste-map@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.0.0.tgz#e9ef51b2c9257384b4d6beb83bd48c65b37b5e6e"
- integrity sha512-CcViJyUo41IQqttLxXVdI41YErkzBKbE6cS6dRAploCeutePYfUimWd3C9rQEWhX0YBOQzvNsC0O9nYxK2nnxQ==
+jest-haste-map@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.8.0.tgz#51794182d877b3ddfd6e6d23920e3fe72f305800"
+ integrity sha512-ZBPRGHdPt1rHajWelXdqygIDpJx8u3xOoLyUBWRW28r3tagrgoepPrzAozW7kW9HrQfhvmiv1tncsxqHJO1onQ==
dependencies:
+ "@jest/types" "^24.8.0"
+ anymatch "^2.0.0"
fb-watchman "^2.0.0"
graceful-fs "^4.1.15"
invariant "^2.2.4"
- jest-serializer "^24.0.0"
- jest-util "^24.0.0"
- jest-worker "^24.0.0"
+ jest-serializer "^24.4.0"
+ jest-util "^24.8.0"
+ jest-worker "^24.6.0"
micromatch "^3.1.10"
- sane "^3.0.0"
+ sane "^4.0.3"
+ walker "^1.0.7"
+ optionalDependencies:
+ fsevents "^1.2.7"
-jest-jasmine2@^24.1.0:
- version "24.1.0"
- resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.1.0.tgz#8377324b967037c440f0a549ee0bbd9912055db6"
- integrity sha512-H+o76SdSNyCh9fM5K8upK45YTo/DiFx5w2YAzblQebSQmukDcoVBVeXynyr7DDnxh+0NTHYRCLwJVf3tC518wg==
+jest-jasmine2@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.8.0.tgz#a9c7e14c83dd77d8b15e820549ce8987cc8cd898"
+ integrity sha512-cEky88npEE5LKd5jPpTdDCLvKkdyklnaRycBXL6GNmpxe41F0WN44+i7lpQKa/hcbXaQ+rc9RMaM4dsebrYong==
dependencies:
"@babel/traverse" "^7.1.0"
+ "@jest/environment" "^24.8.0"
+ "@jest/test-result" "^24.8.0"
+ "@jest/types" "^24.8.0"
chalk "^2.0.1"
co "^4.6.0"
- expect "^24.1.0"
+ expect "^24.8.0"
is-generator-fn "^2.0.0"
- jest-each "^24.0.0"
- jest-matcher-utils "^24.0.0"
- jest-message-util "^24.0.0"
- jest-snapshot "^24.1.0"
- jest-util "^24.0.0"
- pretty-format "^24.0.0"
+ jest-each "^24.8.0"
+ jest-matcher-utils "^24.8.0"
+ jest-message-util "^24.8.0"
+ jest-runtime "^24.8.0"
+ jest-snapshot "^24.8.0"
+ jest-util "^24.8.0"
+ pretty-format "^24.8.0"
throat "^4.0.0"
jest-junit@^6.3.0:
@@ -5983,128 +6339,149 @@ jest-junit@^6.3.0:
strip-ansi "^4.0.0"
xml "^1.0.1"
-jest-leak-detector@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.0.0.tgz#78280119fd05ee98317daee62cddb3aa537a31c6"
- integrity sha512-ZYHJYFeibxfsDSKowjDP332pStuiFT2xfc5R67Rjm/l+HFJWJgNIOCOlQGeXLCtyUn3A23+VVDdiCcnB6dTTrg==
+jest-leak-detector@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.8.0.tgz#c0086384e1f650c2d8348095df769f29b48e6980"
+ integrity sha512-cG0yRSK8A831LN8lIHxI3AblB40uhv0z+SsQdW3GoMMVcK+sJwrIIyax5tu3eHHNJ8Fu6IMDpnLda2jhn2pD/g==
dependencies:
- pretty-format "^24.0.0"
+ pretty-format "^24.8.0"
-jest-matcher-utils@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.0.0.tgz#fc9c41cfc49b2c3ec14e576f53d519c37729d579"
- integrity sha512-LQTDmO+aWRz1Tf9HJg+HlPHhDh1E1c65kVwRFo5mwCVp5aQDzlkz4+vCvXhOKFjitV2f0kMdHxnODrXVoi+rlA==
+jest-matcher-utils@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.8.0.tgz#2bce42204c9af12bde46f83dc839efe8be832495"
+ integrity sha512-lex1yASY51FvUuHgm0GOVj7DCYEouWSlIYmCW7APSqB9v8mXmKSn5+sWVF0MhuASG0bnYY106/49JU1FZNl5hw==
dependencies:
chalk "^2.0.1"
- jest-diff "^24.0.0"
- jest-get-type "^24.0.0"
- pretty-format "^24.0.0"
+ jest-diff "^24.8.0"
+ jest-get-type "^24.8.0"
+ pretty-format "^24.8.0"
-jest-message-util@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.0.0.tgz#a07a141433b2c992dbaec68d4cbfe470ba289619"
- integrity sha512-J9ROJIwz/IeC+eV1XSwnRK4oAwPuhmxEyYx1+K5UI+pIYwFZDSrfZaiWTdq0d2xYFw4Xiu+0KQWsdsQpgJMf3Q==
+jest-message-util@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.8.0.tgz#0d6891e72a4beacc0292b638685df42e28d6218b"
+ integrity sha512-p2k71rf/b6ns8btdB0uVdljWo9h0ovpnEe05ZKWceQGfXYr4KkzgKo3PBi8wdnd9OtNh46VpNIJynUn/3MKm1g==
dependencies:
"@babel/code-frame" "^7.0.0"
+ "@jest/test-result" "^24.8.0"
+ "@jest/types" "^24.8.0"
+ "@types/stack-utils" "^1.0.1"
chalk "^2.0.1"
micromatch "^3.1.10"
slash "^2.0.0"
stack-utils "^1.0.1"
-jest-mock@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.0.0.tgz#9a4b53e01d66a0e780f7d857462d063e024c617d"
- integrity sha512-sQp0Hu5fcf5NZEh1U9eIW2qD0BwJZjb63Yqd98PQJFvf/zzUTBoUAwv/Dc/HFeNHIw1f3hl/48vNn+j3STaI7A==
+jest-mock@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.8.0.tgz#2f9d14d37699e863f1febf4e4d5a33b7fdbbde56"
+ integrity sha512-6kWugwjGjJw+ZkK4mDa0Df3sDlUTsV47MSrT0nGQ0RBWJbpODDQ8MHDVtGtUYBne3IwZUhtB7elxHspU79WH3A==
+ dependencies:
+ "@jest/types" "^24.8.0"
-jest-regex-util@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.0.0.tgz#4feee8ec4a358f5bee0a654e94eb26163cb9089a"
- integrity sha512-Jv/uOTCuC+PY7WpJl2mpoI+WbY2ut73qwwO9ByJJNwOCwr1qWhEW2Lyi2S9ZewUdJqeVpEBisdEVZSI+Zxo58Q==
+jest-pnp-resolver@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a"
+ integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==
+
+jest-regex-util@^24.3.0:
+ version "24.3.0"
+ resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.3.0.tgz#d5a65f60be1ae3e310d5214a0307581995227b36"
+ integrity sha512-tXQR1NEOyGlfylyEjg1ImtScwMq8Oh3iJbGTjN7p0J23EuVX1MA8rwU69K4sLbCmwzgCUbVkm0FkSF9TdzOhtg==
-jest-resolve-dependencies@^24.1.0:
- version "24.1.0"
- resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.1.0.tgz#78f738a2ec59ff4d00751d9da56f176e3f589f6c"
- integrity sha512-2VwPsjd3kRPu7qe2cpytAgowCObk5AKeizfXuuiwgm1a9sijJDZe8Kh1sFj6FKvSaNEfCPlBVkZEJa2482m/Uw==
+jest-resolve-dependencies@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.8.0.tgz#19eec3241f2045d3f990dba331d0d7526acff8e0"
+ integrity sha512-hyK1qfIf/krV+fSNyhyJeq3elVMhK9Eijlwy+j5jqmZ9QsxwKBiP6qukQxaHtK8k6zql/KYWwCTQ+fDGTIJauw==
dependencies:
- jest-regex-util "^24.0.0"
- jest-snapshot "^24.1.0"
+ "@jest/types" "^24.8.0"
+ jest-regex-util "^24.3.0"
+ jest-snapshot "^24.8.0"
-jest-resolve@^24.1.0:
- version "24.1.0"
- resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.1.0.tgz#42ff0169b0ea47bfdbd0c52a0067ca7d022c7688"
- integrity sha512-TPiAIVp3TG6zAxH28u/6eogbwrvZjBMWroSLBDkwkHKrqxB/RIdwkWDye4uqPlZIXWIaHtifY3L0/eO5Z0f2wg==
+jest-resolve@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.8.0.tgz#84b8e5408c1f6a11539793e2b5feb1b6e722439f"
+ integrity sha512-+hjSzi1PoRvnuOICoYd5V/KpIQmkAsfjFO71458hQ2Whi/yf1GDeBOFj8Gxw4LrApHsVJvn5fmjcPdmoUHaVKw==
dependencies:
+ "@jest/types" "^24.8.0"
browser-resolve "^1.11.3"
chalk "^2.0.1"
- realpath-native "^1.0.0"
-
-jest-runner@^24.1.0:
- version "24.1.0"
- resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.1.0.tgz#3686a2bb89ce62800da23d7fdc3da2c32792943b"
- integrity sha512-CDGOkT3AIFl16BLL/OdbtYgYvbAprwJ+ExKuLZmGSCSldwsuU2dEGauqkpvd9nphVdAnJUcP12e/EIlnTX0QXg==
- dependencies:
+ jest-pnp-resolver "^1.2.1"
+ realpath-native "^1.1.0"
+
+jest-runner@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.8.0.tgz#4f9ae07b767db27b740d7deffad0cf67ccb4c5bb"
+ integrity sha512-utFqC5BaA3JmznbissSs95X1ZF+d+4WuOWwpM9+Ak356YtMhHE/GXUondZdcyAAOTBEsRGAgH/0TwLzfI9h7ow==
+ dependencies:
+ "@jest/console" "^24.7.1"
+ "@jest/environment" "^24.8.0"
+ "@jest/test-result" "^24.8.0"
+ "@jest/types" "^24.8.0"
chalk "^2.4.2"
exit "^0.1.2"
graceful-fs "^4.1.15"
- jest-config "^24.1.0"
- jest-docblock "^24.0.0"
- jest-haste-map "^24.0.0"
- jest-jasmine2 "^24.1.0"
- jest-leak-detector "^24.0.0"
- jest-message-util "^24.0.0"
- jest-runtime "^24.1.0"
- jest-util "^24.0.0"
- jest-worker "^24.0.0"
+ jest-config "^24.8.0"
+ jest-docblock "^24.3.0"
+ jest-haste-map "^24.8.0"
+ jest-jasmine2 "^24.8.0"
+ jest-leak-detector "^24.8.0"
+ jest-message-util "^24.8.0"
+ jest-resolve "^24.8.0"
+ jest-runtime "^24.8.0"
+ jest-util "^24.8.0"
+ jest-worker "^24.6.0"
source-map-support "^0.5.6"
throat "^4.0.0"
-jest-runtime@^24.1.0:
- version "24.1.0"
- resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.1.0.tgz#7c157a2e776609e8cf552f956a5a19ec9c985214"
- integrity sha512-59/BY6OCuTXxGeDhEMU7+N33dpMQyXq7MLK07cNSIY/QYt2QZgJ7Tjx+rykBI0skAoigFl0A5tmT8UdwX92YuQ==
- dependencies:
- "@babel/core" "^7.1.0"
- babel-plugin-istanbul "^5.1.0"
+jest-runtime@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.8.0.tgz#05f94d5b05c21f6dc54e427cd2e4980923350620"
+ integrity sha512-Mq0aIXhvO/3bX44ccT+czU1/57IgOMyy80oM0XR/nyD5zgBcesF84BPabZi39pJVA6UXw+fY2Q1N+4BiVUBWOA==
+ dependencies:
+ "@jest/console" "^24.7.1"
+ "@jest/environment" "^24.8.0"
+ "@jest/source-map" "^24.3.0"
+ "@jest/transform" "^24.8.0"
+ "@jest/types" "^24.8.0"
+ "@types/yargs" "^12.0.2"
chalk "^2.0.1"
- convert-source-map "^1.4.0"
exit "^0.1.2"
- fast-json-stable-stringify "^2.0.0"
glob "^7.1.3"
graceful-fs "^4.1.15"
- jest-config "^24.1.0"
- jest-haste-map "^24.0.0"
- jest-message-util "^24.0.0"
- jest-regex-util "^24.0.0"
- jest-resolve "^24.1.0"
- jest-snapshot "^24.1.0"
- jest-util "^24.0.0"
- jest-validate "^24.0.0"
- micromatch "^3.1.10"
- realpath-native "^1.0.0"
+ jest-config "^24.8.0"
+ jest-haste-map "^24.8.0"
+ jest-message-util "^24.8.0"
+ jest-mock "^24.8.0"
+ jest-regex-util "^24.3.0"
+ jest-resolve "^24.8.0"
+ jest-snapshot "^24.8.0"
+ jest-util "^24.8.0"
+ jest-validate "^24.8.0"
+ realpath-native "^1.1.0"
slash "^2.0.0"
strip-bom "^3.0.0"
- write-file-atomic "2.4.1"
yargs "^12.0.2"
-jest-serializer@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.0.0.tgz#522c44a332cdd194d8c0531eb06a1ee5afb4256b"
- integrity sha512-9FKxQyrFgHtx3ozU+1a8v938ILBE7S8Ko3uiAVjT8Yfi2o91j/fj81jacCQZ/Ihjiff/VsUCXVgQ+iF1XdImOw==
+jest-serializer@^24.4.0:
+ version "24.4.0"
+ resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.4.0.tgz#f70c5918c8ea9235ccb1276d232e459080588db3"
+ integrity sha512-k//0DtglVstc1fv+GY/VHDIjrtNjdYvYjMlbLUed4kxrE92sIUewOi5Hj3vrpB8CXfkJntRPDRjCrCvUhBdL8Q==
-jest-snapshot@^24.1.0:
- version "24.1.0"
- resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.1.0.tgz#85e22f810357aa5994ab61f236617dc2205f2f5b"
- integrity sha512-th6TDfFqEmXvuViacU1ikD7xFb7lQsPn2rJl7OEmnfIVpnrx3QNY2t3PE88meeg0u/mQ0nkyvmC05PBqO4USFA==
+jest-snapshot@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.8.0.tgz#3bec6a59da2ff7bc7d097a853fb67f9d415cb7c6"
+ integrity sha512-5ehtWoc8oU9/cAPe6fez6QofVJLBKyqkY2+TlKTOf0VllBB/mqUNdARdcjlZrs9F1Cv+/HKoCS/BknT0+tmfPg==
dependencies:
"@babel/types" "^7.0.0"
+ "@jest/types" "^24.8.0"
chalk "^2.0.1"
- jest-diff "^24.0.0"
- jest-matcher-utils "^24.0.0"
- jest-message-util "^24.0.0"
- jest-resolve "^24.1.0"
+ expect "^24.8.0"
+ jest-diff "^24.8.0"
+ jest-matcher-utils "^24.8.0"
+ jest-message-util "^24.8.0"
+ jest-resolve "^24.8.0"
mkdirp "^0.5.1"
natural-compare "^1.4.0"
- pretty-format "^24.0.0"
+ pretty-format "^24.8.0"
semver "^5.5.0"
jest-transform-graphql@^2.1.0:
@@ -6112,56 +6489,64 @@ jest-transform-graphql@^2.1.0:
resolved "https://registry.yarnpkg.com/jest-transform-graphql/-/jest-transform-graphql-2.1.0.tgz#903cb66bb27bc2772fd3e5dd4f7e9b57230f5829"
integrity sha1-kDy2a7J7wncv0+XdT36bVyMPWCk=
-jest-util@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.0.0.tgz#fd38fcafd6dedbd0af2944d7a227c0d91b68f7d6"
- integrity sha512-QxsALc4wguYS7cfjdQSOr5HTkmjzkHgmZvIDkcmPfl1ib8PNV8QUWLwbKefCudWS0PRKioV+VbQ0oCUPC691fQ==
+jest-util@^24.0.0, jest-util@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.8.0.tgz#41f0e945da11df44cc76d64ffb915d0716f46cd1"
+ integrity sha512-DYZeE+XyAnbNt0BG1OQqKy/4GVLPtzwGx5tsnDrFcax36rVE3lTA5fbvgmbVPUZf9w77AJ8otqR4VBbfFJkUZA==
dependencies:
+ "@jest/console" "^24.7.1"
+ "@jest/fake-timers" "^24.8.0"
+ "@jest/source-map" "^24.3.0"
+ "@jest/test-result" "^24.8.0"
+ "@jest/types" "^24.8.0"
callsites "^3.0.0"
chalk "^2.0.1"
graceful-fs "^4.1.15"
is-ci "^2.0.0"
- jest-message-util "^24.0.0"
mkdirp "^0.5.1"
slash "^2.0.0"
source-map "^0.6.0"
-jest-validate@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.0.0.tgz#aa8571a46983a6538328fef20406b4a496b6c020"
- integrity sha512-vMrKrTOP4BBFIeOWsjpsDgVXATxCspC9S1gqvbJ3Tnn/b9ACsJmteYeVx9830UMV28Cob1RX55x96Qq3Tfad4g==
+jest-validate@^24.0.0, jest-validate@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.8.0.tgz#624c41533e6dfe356ffadc6e2423a35c2d3b4849"
+ integrity sha512-+/N7VOEMW1Vzsrk3UWBDYTExTPwf68tavEPKDnJzrC6UlHtUDU/fuEdXqFoHzv9XnQ+zW6X3qMZhJ3YexfeLDA==
dependencies:
+ "@jest/types" "^24.8.0"
camelcase "^5.0.0"
chalk "^2.0.1"
- jest-get-type "^24.0.0"
+ jest-get-type "^24.8.0"
leven "^2.1.0"
- pretty-format "^24.0.0"
+ pretty-format "^24.8.0"
-jest-watcher@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.0.0.tgz#20d44244d10b0b7312410aefd256c1c1eef68890"
- integrity sha512-GxkW2QrZ4YxmW1GUWER05McjVDunBlKMFfExu+VsGmXJmpej1saTEKvONdx5RJBlVdpPI5x6E3+EDQSIGgl53g==
+jest-watcher@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.8.0.tgz#58d49915ceddd2de85e238f6213cef1c93715de4"
+ integrity sha512-SBjwHt5NedQoVu54M5GEx7cl7IGEFFznvd/HNT8ier7cCAx/Qgu9ZMlaTQkvK22G1YOpcWBLQPFSImmxdn3DAw==
dependencies:
+ "@jest/test-result" "^24.8.0"
+ "@jest/types" "^24.8.0"
+ "@types/yargs" "^12.0.9"
ansi-escapes "^3.0.0"
chalk "^2.0.1"
- jest-util "^24.0.0"
+ jest-util "^24.8.0"
string-length "^2.0.0"
-jest-worker@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.0.0.tgz#3d3483b077bf04f412f47654a27bba7e947f8b6d"
- integrity sha512-s64/OThpfQvoCeHG963MiEZOAAxu8kHsaL/rCMF7lpdzo7vgF0CtPml9hfguOMgykgH/eOm4jFP4ibfHLruytg==
+jest-worker@^24.6.0:
+ version "24.6.0"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.6.0.tgz#7f81ceae34b7cde0c9827a6980c35b7cdc0161b3"
+ integrity sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ==
dependencies:
merge-stream "^1.0.1"
supports-color "^6.1.0"
jest@^24.1.0:
- version "24.1.0"
- resolved "https://registry.yarnpkg.com/jest/-/jest-24.1.0.tgz#b1e1135caefcf2397950ecf7f90e395fde866fd2"
- integrity sha512-+q91L65kypqklvlRFfXfdzUKyngQLOcwGhXQaLmVHv+d09LkNXuBuGxlofTFW42XMzu3giIcChchTsCNUjQ78A==
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/jest/-/jest-24.8.0.tgz#d5dff1984d0d1002196e9b7f12f75af1b2809081"
+ integrity sha512-o0HM90RKFRNWmAWvlyV8i5jGZ97pFwkeVoGvPW1EtLTgJc2+jcuqcbbqcSZLE/3f2S5pt0y2ZBETuhpWNl1Reg==
dependencies:
import-local "^2.0.0"
- jest-cli "^24.1.0"
+ jest-cli "^24.8.0"
jquery-ujs@1.2.2:
version "1.2.2"
@@ -6222,9 +6607,9 @@ js-tokens@^3.0.2:
integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=
js-yaml@3.x, js-yaml@^3.12.0, js-yaml@^3.9.0:
- version "3.12.1"
- resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.1.tgz#295c8632a18a23e054cf5c9d3cecafe678167600"
- integrity sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
+ integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"
@@ -6297,9 +6682,9 @@ jsdom@^11.5.1:
xml-name-validator "^3.0.0"
jsesc@^2.5.1:
- version "2.5.1"
- resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe"
- integrity sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=
+ version "2.5.2"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
+ integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
jsesc@~0.5.0:
version "0.5.0"
@@ -6519,9 +6904,9 @@ klaw@~2.0.0:
graceful-fs "^4.1.9"
kleur@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.2.tgz#83c7ec858a41098b613d5998a7b653962b504f68"
- integrity sha512-3h7B2WRT5LNXOtQiAaWonilegHcPSf9nLVXlSTci8lu1dZUuui61+EsPEZqSVxY7rXYmB2DVKMQILxaO5WL61Q==
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
+ integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
known-css-properties@^0.11.0:
version "0.11.0"
@@ -6535,13 +6920,6 @@ latest-version@^3.0.0:
dependencies:
package-json "^4.0.0"
-lazy-cache@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264"
- integrity sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=
- dependencies:
- set-getter "^0.1.0"
-
lcid@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
@@ -6654,17 +7032,12 @@ locate-path@^3.0.0:
p-locate "^3.0.0"
path-exists "^3.0.0"
-lodash.assign@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
- integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=
-
lodash.camelcase@4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
-lodash.clonedeep@^4.3.2, lodash.clonedeep@^4.5.0:
+lodash.clonedeep@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
@@ -6812,6 +7185,14 @@ make-dir@^1.0.0, make-dir@^1.3.0:
dependencies:
pify "^3.0.0"
+make-dir@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
+ integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
+ dependencies:
+ pify "^4.0.1"
+ semver "^5.6.0"
+
make-error@1.x:
version "1.3.5"
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8"
@@ -6825,9 +7206,9 @@ makeerror@1.0.x:
tmpl "1.0.x"
map-age-cleaner@^0.1.1:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz#098fb15538fd3dbe461f12745b0ca8568d4e3f74"
- integrity sha512-UN1dNocxQq44IhJyMI4TU8phc2m9BddacHRPRjKGLYaF0jqd3xLz0jS0skpAU9WgYyoR4gHtUpzytNBS385FWQ==
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a"
+ integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==
dependencies:
p-defer "^1.0.0"
@@ -6926,13 +7307,13 @@ mem@^1.1.0:
mimic-fn "^1.0.0"
mem@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/mem/-/mem-4.0.0.tgz#6437690d9471678f6cc83659c00cbafcd6b0cdaf"
- integrity sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178"
+ integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==
dependencies:
map-age-cleaner "^0.1.1"
- mimic-fn "^1.0.0"
- p-is-promise "^1.1.0"
+ mimic-fn "^2.0.0"
+ p-is-promise "^2.0.0"
memory-fs@^0.2.0:
version "0.2.0"
@@ -7002,24 +7383,19 @@ merge2@^1.2.3:
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5"
integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==
-merge@^1.2.0:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145"
- integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==
-
-mermaid@^8.0.0-rc.8:
- version "8.0.0-rc.8"
- resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-8.0.0-rc.8.tgz#74ed54d0d46e9ee71c4db2730b2d83d516a21e72"
- integrity sha512-GbF9jHWfqE7YGx9vQySmBxy2Ahlclxmpk4tJ9ntNyafENl96s96ggUK/NQS5ydYoFab6MavTm4YMTIPKqWVvPQ==
+mermaid@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-8.0.0.tgz#8f6c75017e788a8c3997e20c5e5046c2b88d1a8f"
+ integrity sha512-vUQRykev0A6RtxIVqQT3a9TDxcSbdZbQF5JDyKgidnYuJy8BE8jp6LM+HKDSQuroKm6buu4NlpMO+qhxIP/cTg==
dependencies:
- d3 "^4.13.0"
+ d3 "^5.7.0"
dagre-d3-renderer "^0.5.8"
dagre-layout "^0.8.8"
graphlibrary "^2.2.0"
- he "^1.1.1"
- lodash "^4.17.5"
- moment "^2.21.0"
- scope-css "^1.0.5"
+ he "^1.2.0"
+ lodash "^4.17.11"
+ moment "^2.23.0"
+ scope-css "^1.2.1"
methods@~1.1.2:
version "1.1.2"
@@ -7076,9 +7452,14 @@ mime@^2.0.3, mime@^2.3.1:
integrity sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==
mimic-fn@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18"
- integrity sha1-5md4PZLonb00KBi1IwudYqZyrRg=
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
+ integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
+
+mimic-fn@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
+ integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
mimic-response@^1.0.0:
version "1.0.0"
@@ -7112,7 +7493,7 @@ minimist-options@^3.0.1:
minimist@0.0.8, minimist@~0.0.1:
version "0.0.8"
- resolved "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
minimist@1.1.x:
@@ -7125,18 +7506,18 @@ minimist@1.2.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
-minipass@^2.2.1, minipass@^2.3.3:
- version "2.3.3"
- resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.3.tgz#a7dcc8b7b833f5d368759cce544dccb55f50f233"
- integrity sha512-/jAn9/tEX4gnpyRATxgHEOV6xbcyxgT7iUnxo9Y3+OB0zX00TgKIv/2FZCf5brBbICcwbLqVv2ImjvWWrQMSYw==
+minipass@^2.2.1, minipass@^2.3.4:
+ version "2.3.5"
+ resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848"
+ integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==
dependencies:
safe-buffer "^5.1.2"
yallist "^3.0.0"
-minizlib@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb"
- integrity sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==
+minizlib@^1.1.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614"
+ integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==
dependencies:
minipass "^2.2.1"
@@ -7171,10 +7552,10 @@ mkdirp@0.5.x, mkdirp@0.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp
dependencies:
minimist "0.0.8"
-moment@2.x, moment@^2.10.2, moment@^2.21.0:
- version "2.23.0"
- resolved "https://registry.yarnpkg.com/moment/-/moment-2.23.0.tgz#759ea491ac97d54bac5ad776996e2a58cc1bc225"
- integrity sha512-3IE39bHVqFbWWaPOMHZF98Q9c3LDKGTmypMiTM2QygGXXElkFWIH7GxfmlwmY2vwa+wmNsoYZmG2iusf1ZjJoA==
+moment@2.x, moment@^2.10.2, moment@^2.23.0:
+ version "2.24.0"
+ resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
+ integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
monaco-editor-webpack-plugin@^1.7.0:
version "1.7.0"
@@ -7233,22 +7614,21 @@ mute-stream@0.0.7:
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
-nan@^2.10.0, nan@^2.9.2:
- version "2.13.1"
- resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.1.tgz#a15bee3790bde247e8f38f1d446edcdaeb05f2dd"
- integrity sha512-I6YB/YEuDeUZMmhscXKxGgZlFnhsn5y0hgOZBadkzfTRrZBtJDZeg6eQf7PYMIEclwmorTKK8GztsyOUSVBREA==
+nan@^2.12.1, nan@^2.13.2:
+ version "2.14.0"
+ resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
+ integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
nanomatch@^1.2.9:
- version "1.2.9"
- resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.9.tgz#879f7150cb2dab7a471259066c104eee6e0fa7c2"
- integrity sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==
+ version "1.2.13"
+ resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
+ integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==
dependencies:
arr-diff "^4.0.0"
array-unique "^0.3.2"
define-property "^2.0.2"
extend-shallow "^3.0.2"
fragment-cache "^0.2.1"
- is-odd "^2.0.0"
is-windows "^1.0.2"
kind-of "^6.0.2"
object.pick "^1.3.0"
@@ -7262,11 +7642,11 @@ natural-compare@^1.4.0:
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
needle@^2.2.1:
- version "2.2.4"
- resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e"
- integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c"
+ integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==
dependencies:
- debug "^2.1.2"
+ debug "^3.2.6"
iconv-lite "^0.4.4"
sax "^1.2.4"
@@ -7281,9 +7661,14 @@ neo-async@^2.5.0, neo-async@^2.6.0:
integrity sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==
nice-try@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4"
- integrity sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
+ integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
+
+node-ensure@^0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/node-ensure/-/node-ensure-0.0.0.tgz#ecae764150de99861ec5c810fd5d096b183932a7"
+ integrity sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc=
node-fetch@1.6.3:
version "1.6.3"
@@ -7356,19 +7741,20 @@ node-modules-regexp@^1.0.0:
integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=
node-notifier@^5.2.1:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.3.0.tgz#c77a4a7b84038733d5fb351aafd8a268bfe19a01"
- integrity sha512-AhENzCSGZnZJgBARsUjnQ7DnZbzyP+HxlVXuD0xqAnvL8q+OqtSX7lGg9e8nHzwXkMMXNdVeqq4E2M3EUAqX6Q==
+ version "5.4.0"
+ resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.0.tgz#7b455fdce9f7de0c63538297354f3db468426e6a"
+ integrity sha512-SUDEb+o71XR5lXSTyivXd9J7fCloE3SyP4lSgt3lU2oSANiox+SxlNRGPjDKrwU1YN3ix2KN/VGGCg0t01rttQ==
dependencies:
growly "^1.3.0"
+ is-wsl "^1.1.0"
semver "^5.5.0"
shellwords "^0.1.1"
which "^1.3.0"
-node-pre-gyp@^0.10.0:
- version "0.10.3"
- resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc"
- integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A==
+node-pre-gyp@^0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149"
+ integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==
dependencies:
detect-libc "^1.0.2"
mkdirp "^0.5.1"
@@ -7381,17 +7767,17 @@ node-pre-gyp@^0.10.0:
semver "^5.3.0"
tar "^4"
-node-releases@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.3.tgz#aad9ce0dcb98129c753f772c0aa01360fb90fbd2"
- integrity sha512-6VrvH7z6jqqNFY200kdB6HdzkgM96Oaj9v3dqGfgp6mF+cHmU4wyQKZ2/WPDRVoR0Jz9KqbamaBN0ZhdUaysUQ==
+node-releases@^1.1.19:
+ version "1.1.19"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.19.tgz#c492d1e381fea0350b338b646c27867e88e91b3d"
+ integrity sha512-SH/B4WwovHbulIALsQllAVwqZZD1kPmKCqrhGfR29dXjLAVZMHvBjD3S6nL9D/J9QkmZ1R92/0wCMDKXUUvyyA==
dependencies:
semver "^5.3.0"
-node-sass@^4.11.0:
- version "4.11.0"
- resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.11.0.tgz#183faec398e9cbe93ba43362e2768ca988a6369a"
- integrity sha512-bHUdHTphgQJZaF1LASx0kAviPH7sGlcyNhWade4eVIpFp6tsn7SV8xNMTbsQFpEV9VXpnwTTnNYlfsZXgGgmkA==
+node-sass@^4.12.0:
+ version "4.12.0"
+ resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.12.0.tgz#0914f531932380114a30cc5fa4fa63233a25f017"
+ integrity sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ==
dependencies:
async-foreach "^0.1.3"
chalk "^1.1.1"
@@ -7400,12 +7786,10 @@ node-sass@^4.11.0:
get-stdin "^4.0.1"
glob "^7.0.3"
in-publish "^2.0.0"
- lodash.assign "^4.2.0"
- lodash.clonedeep "^4.3.2"
- lodash.mergewith "^4.6.0"
+ lodash "^4.17.11"
meow "^3.7.0"
mkdirp "^0.5.1"
- nan "^2.10.0"
+ nan "^2.13.2"
node-gyp "^3.8.0"
npmlog "^4.0.0"
request "^2.88.0"
@@ -7493,14 +7877,14 @@ normalize-url@2.0.1:
sort-keys "^2.0.0"
npm-bundled@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308"
- integrity sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd"
+ integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==
npm-packlist@^1.1.6:
- version "1.1.10"
- resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.10.tgz#1039db9e985727e464df066f4cf0ab6ef85c398a"
- integrity sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.1.tgz#19064cdf988da80ea3cee45533879d90192bbfbc"
+ integrity sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==
dependencies:
ignore-walk "^3.0.1"
npm-bundled "^1.0.1"
@@ -7567,9 +7951,9 @@ object-copy@^0.1.0:
kind-of "^3.0.3"
object-keys@^1.0.11, object-keys@^1.0.12:
- version "1.0.12"
- resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2"
- integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
+ integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
object-visit@^1.0.0:
version "1.0.1"
@@ -7742,11 +8126,11 @@ os-locale@^2.0.0:
mem "^1.1.0"
os-locale@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.0.1.tgz#3b014fbf01d87f60a1e5348d80fe870dc82c4620"
- integrity sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
+ integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==
dependencies:
- execa "^0.10.0"
+ execa "^1.0.0"
lcid "^2.0.0"
mem "^4.0.0"
@@ -7790,6 +8174,11 @@ p-is-promise@^1.1.0:
resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e"
integrity sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=
+p-is-promise@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e"
+ integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==
+
p-limit@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c"
@@ -7798,9 +8187,9 @@ p-limit@^1.1.0:
p-try "^1.0.0"
p-limit@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec"
- integrity sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2"
+ integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==
dependencies:
p-try "^2.0.0"
@@ -7841,9 +8230,9 @@ p-try@^1.0.0:
integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=
p-try@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1"
- integrity sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
+ integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
package-json@^4.0.0:
version "4.0.1"
@@ -8027,6 +8416,14 @@ pbkdf2@^3.0.3:
safe-buffer "^5.0.1"
sha.js "^2.4.8"
+pdfjs-dist@^2.0.943:
+ version "2.0.943"
+ resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-2.0.943.tgz#32fb9a2d863df5a1d89521a0b3cd900c16e7edde"
+ integrity sha512-iLhNcm4XceTHRaSU5o22ZGCm4YpuW5+rf4+BJFH/feBhMQLbCGBry+Jet8Q419QDI4qgARaIQzXuiNrsNWS8Yw==
+ dependencies:
+ node-ensure "^0.0.0"
+ worker-loader "^2.0.0"
+
performance-now@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
@@ -8066,7 +8463,7 @@ pinkie@^2.0.0:
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
-pirates@^4.0.0:
+pirates@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87"
integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==
@@ -8306,13 +8703,15 @@ prettier@1.16.4:
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.4.tgz#73e37e73e018ad2db9c76742e2647e21790c9717"
integrity sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==
-pretty-format@^24.0.0:
- version "24.0.0"
- resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.0.0.tgz#cb6599fd73ac088e37ed682f61291e4678f48591"
- integrity sha512-LszZaKG665djUcqg5ZQq+XzezHLKrxsA86ZABTozp+oNhkdqa+tG2dX4qa6ERl5c/sRDrAa3lHmwnvKoP+OG/g==
+pretty-format@^24.8.0:
+ version "24.8.0"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.8.0.tgz#8dae7044f58db7cb8be245383b565a963e3c27f2"
+ integrity sha512-P952T7dkrDEplsR+TuY7q3VXDae5Sr7zmQb12JU/NDQa/3CH7/QW0yvqLcGN6jL+zQFKaoJcPc+yJxMTGmosqw==
dependencies:
+ "@jest/types" "^24.8.0"
ansi-regex "^4.0.0"
ansi-styles "^3.2.0"
+ react-is "^16.8.4"
prismjs@^1.6.0:
version "1.6.0"
@@ -8352,9 +8751,9 @@ promise-inflight@^1.0.1:
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
prompts@^2.0.1:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.0.3.tgz#c5ccb324010b2e8f74752aadceeb57134c1d2522"
- integrity sha512-H8oWEoRZpybm6NV4to9/1limhttEo13xK62pNvn2JzY0MA03p7s0OjtmhXyon3uJmxiJJVSuUwEJFFssI3eBiQ==
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.1.0.tgz#bf90bc71f6065d255ea2bdc0fe6520485c1b45db"
+ integrity sha512-+x5TozgqYdOwWsQFZizE/Tra3fKvAoy037kOyU6cgz84n8f6zxngLOV4O32kTwt9FcLCxAqw0P/c8rOr9y+Gfg==
dependencies:
kleur "^3.0.2"
sisteransi "^1.0.0"
@@ -8663,6 +9062,11 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.2.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
+react-is@^16.8.4:
+ version "16.8.6"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
+ integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==
+
read-pkg-up@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
@@ -8766,7 +9170,7 @@ readdirp@^2.0.0:
readable-stream "^2.0.2"
set-immediate-shim "^1.0.1"
-realpath-native@^1.0.0, realpath-native@^1.0.2:
+realpath-native@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c"
integrity sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==
@@ -8789,10 +9193,10 @@ redent@^2.0.0:
indent-string "^3.0.0"
strip-indent "^2.0.0"
-regenerate-unicode-properties@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz#107405afcc4a190ec5ed450ecaa00ed0cafa7a4c"
- integrity sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw==
+regenerate-unicode-properties@^8.0.2:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e"
+ integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==
dependencies:
regenerate "^1.4.0"
@@ -8811,10 +9215,10 @@ regenerator-runtime@^0.11.0:
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
-regenerator-transform@^0.13.3:
- version "0.13.3"
- resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.3.tgz#264bd9ff38a8ce24b06e0636496b2c856b57bcbb"
- integrity sha512-5ipTrZFSq5vU2YoGoww4uaRVAK4wyYC4TSICibbfEPOruUu8FFP7ErV0BjmbIOEpn3O/k9na9UEdYR/3m7N6uA==
+regenerator-transform@^0.13.4:
+ version "0.13.4"
+ resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.4.tgz#18f6763cf1382c69c36df76c6ce122cc694284fb"
+ integrity sha512-T0QMBjK3J0MtxjPmdIMXm72Wvj2Abb0Bd4HADdfijwMdoIsyQZ6fWC7kDFhk2YinBBEMZDL7Y7wh0J1sGx3S4A==
dependencies:
private "^0.1.6"
@@ -8849,17 +9253,17 @@ regexpu-core@^1.0.0:
regjsgen "^0.2.0"
regjsparser "^0.1.4"
-regexpu-core@^4.1.3, regexpu-core@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.2.0.tgz#a3744fa03806cffe146dea4421a3e73bdcc47b1d"
- integrity sha512-Z835VSnJJ46CNBttalHD/dB+Sj2ezmY6Xp38npwU87peK6mqOzOpV8eYktdkLTEkzzD+JsTcxd84ozd8I14+rw==
+regexpu-core@^4.5.4:
+ version "4.5.4"
+ resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.5.4.tgz#080d9d02289aa87fe1667a4f5136bc98a6aebaae"
+ integrity sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==
dependencies:
regenerate "^1.4.0"
- regenerate-unicode-properties "^7.0.0"
- regjsgen "^0.4.0"
- regjsparser "^0.3.0"
+ regenerate-unicode-properties "^8.0.2"
+ regjsgen "^0.5.0"
+ regjsparser "^0.6.0"
unicode-match-property-ecmascript "^1.0.4"
- unicode-match-property-value-ecmascript "^1.0.2"
+ unicode-match-property-value-ecmascript "^1.1.0"
registry-auth-token@^3.0.1:
version "3.3.2"
@@ -8881,10 +9285,10 @@ regjsgen@^0.2.0:
resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7"
integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=
-regjsgen@^0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.4.0.tgz#c1eb4c89a209263f8717c782591523913ede2561"
- integrity sha512-X51Lte1gCYUdlwhF28+2YMO0U6WeN0GLpgpA7LK7mbdDnkQYiwvEpmpe0F/cv5L14EbxgrdayAG3JETBv0dbXA==
+regjsgen@^0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.0.tgz#a7634dc08f89209c2049adda3525711fb97265dd"
+ integrity sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==
regjsparser@^0.1.4:
version "0.1.5"
@@ -8893,10 +9297,10 @@ regjsparser@^0.1.4:
dependencies:
jsesc "~0.5.0"
-regjsparser@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.3.0.tgz#3c326da7fcfd69fa0d332575a41c8c0cdf588c96"
- integrity sha512-zza72oZBBHzt64G7DxdqrOo/30bhHkwMUoT0WqfGu98XLd7N+1tsy5MJ96Bk4MD0y74n629RhmrGW6XlnLLwCA==
+regjsparser@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c"
+ integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==
dependencies:
jsesc "~0.5.0"
@@ -8956,9 +9360,9 @@ remove-trailing-separator@^1.0.1:
integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8=
repeat-element@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a"
- integrity sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce"
+ integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==
repeat-string@^0.2.2:
version "0.2.2"
@@ -9042,6 +9446,11 @@ require-uncached@^1.0.3:
caller-path "^0.1.0"
resolve-from "^1.0.0"
+requireindex@~1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.1.0.tgz#e5404b81557ef75db6e49c5a72004893fe03e162"
+ integrity sha1-5UBLgVV+91225JxacgBIk/4D4WI=
+
requires-port@1.x.x, requires-port@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
@@ -9095,9 +9504,9 @@ resolve@1.1.7, resolve@1.1.x:
integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
resolve@1.x, resolve@^1.10.0, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.9.0:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba"
- integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.0.tgz#4014870ba296176b86343d50b60f3b50609ce232"
+ integrity sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==
dependencies:
path-parse "^1.0.6"
@@ -9126,7 +9535,7 @@ rfdc@^1.1.2:
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.2.tgz#e6e72d74f5dc39de8f538f65e00c36c18018e349"
integrity sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==
-rimraf@2, rimraf@2.6.3, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1, rimraf@^2.6.2:
+rimraf@2, rimraf@2.6.3, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3:
version "2.6.3"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
@@ -9146,10 +9555,10 @@ rope-sequence@^1.2.0:
resolved "https://registry.yarnpkg.com/rope-sequence/-/rope-sequence-1.2.2.tgz#49c4e5c2f54a48e990b050926771e2871bcb31ce"
integrity sha1-ScTlwvVKSOmQsFCSZ3HihxvLMc4=
-rsvp@^3.3.3:
- version "3.6.2"
- resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
- integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==
+rsvp@^4.8.4:
+ version "4.8.4"
+ resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.4.tgz#b50e6b34583f3dd89329a2f23a8a2be072845911"
+ integrity sha512-6FomvYPfs+Jy9TfXmBpBuMWNH94SgCsZmJKcanySzgNNP6LjWxBvyLTa9KaMfDDM5oxRfrKDB0r/qeRsLwnBfA==
run-async@^2.2.0:
version "2.3.0"
@@ -9204,22 +9613,20 @@ safe-regex@^1.1.0:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-sane@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/sane/-/sane-3.1.0.tgz#995193b7dc1445ef1fe41ddfca2faf9f111854c6"
- integrity sha512-G5GClRRxT1cELXfdAq7UKtUsv8q/ZC5k8lQGmjEm4HcAl3HzBy68iglyNCmw4+0tiXPCBZntslHlRhbnsSws+Q==
+sane@^4.0.3:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded"
+ integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==
dependencies:
+ "@cnakazawa/watch" "^1.0.3"
anymatch "^2.0.0"
- capture-exit "^1.2.0"
- exec-sh "^0.2.0"
+ capture-exit "^2.0.0"
+ exec-sh "^0.3.2"
execa "^1.0.0"
fb-watchman "^2.0.0"
micromatch "^3.1.4"
minimist "^1.1.1"
walker "~1.0.5"
- watch "~0.18.0"
- optionalDependencies:
- fsevents "^1.2.3"
sanitize-html@^1.16.1:
version "1.16.3"
@@ -9266,7 +9673,7 @@ schema-utils@^1.0.0:
ajv-errors "^1.0.0"
ajv-keywords "^3.1.0"
-scope-css@^1.0.5:
+scope-css@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/scope-css/-/scope-css-1.2.1.tgz#c35768bc900cad030a3e0d663a818c0f6a57f40e"
integrity sha512-UjLRmyEYaDNiOS673xlVkZFlVCtckJR/dKgr434VMm7Lb+AOOqXKdAcY7PpGlJYErjXXJzKN7HWo4uRPiZZG0Q==
@@ -9313,9 +9720,14 @@ semver-diff@^2.0.0:
semver "^5.0.3"
"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
- version "5.6.0"
- resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
- integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
+ integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==
+
+semver@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-6.0.0.tgz#05e359ee571e5ad7ed641a6eec1e547ba52dea65"
+ integrity sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==
semver@~5.3.0:
version "5.3.0"
@@ -9374,13 +9786,6 @@ set-blocking@^2.0.0, set-blocking@~2.0.0:
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
-set-getter@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/set-getter/-/set-getter-0.1.0.tgz#d769c182c9d5a51f409145f2fba82e5e86e80376"
- integrity sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=
- dependencies:
- to-object-path "^0.3.0"
-
set-immediate-shim@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
@@ -9514,9 +9919,9 @@ snapdragon-util@^3.0.1:
kind-of "^3.2.0"
snapdragon@^0.8.1:
- version "0.8.1"
- resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.1.tgz#e12b5487faded3e3dea0ac91e9400bf75b401370"
- integrity sha1-4StUh/re0+PeoKyR6UAL91tAE3A=
+ version "0.8.2"
+ resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d"
+ integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==
dependencies:
base "^0.11.1"
debug "^2.2.0"
@@ -9525,7 +9930,7 @@ snapdragon@^0.8.1:
map-cache "^0.2.2"
source-map "^0.5.6"
source-map-resolve "^0.5.0"
- use "^2.0.0"
+ use "^3.1.0"
socket.io-adapter@~1.1.0:
version "1.1.1"
@@ -9622,9 +10027,9 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
urix "^0.1.0"
source-map-support@^0.5.6, source-map-support@~0.5.6:
- version "0.5.9"
- resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f"
- integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==
+ version "0.5.12"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599"
+ integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==
dependencies:
buffer-from "^1.0.0"
source-map "^0.6.0"
@@ -9864,7 +10269,7 @@ string-width@^1.0.1, string-width@^1.0.2:
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
-string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1:
+"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
@@ -9918,11 +10323,11 @@ strip-ansi@^4.0.0:
ansi-regex "^3.0.0"
strip-ansi@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.0.0.tgz#f78f68b5d0866c20b2c9b8c61b5298508dc8756f"
- integrity sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
+ integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
dependencies:
- ansi-regex "^4.0.0"
+ ansi-regex "^4.1.0"
strip-bom@^2.0.0:
version "2.0.0"
@@ -10078,7 +10483,7 @@ supports-color@^5.1.0, supports-color@^5.2.0, supports-color@^5.3.0, supports-co
dependencies:
has-flag "^3.0.0"
-supports-color@^6.0.0, supports-color@^6.1.0:
+supports-color@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==
@@ -10140,14 +10545,14 @@ tar@^2.0.0:
inherits "2"
tar@^4:
- version "4.4.4"
- resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.4.tgz#ec8409fae9f665a4355cc3b4087d0820232bb8cd"
- integrity sha512-mq9ixIYfNF9SK0IS/h2HKMu8Q2iaCuhDDsZhdEag/FHv8fOaYld4vN7ouMgcSSt5WKZzPs8atclTcJm36OTh4w==
+ version "4.4.8"
+ resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d"
+ integrity sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==
dependencies:
- chownr "^1.0.1"
+ chownr "^1.1.1"
fs-minipass "^1.2.5"
- minipass "^2.3.3"
- minizlib "^1.1.0"
+ minipass "^2.3.4"
+ minizlib "^1.1.1"
mkdirp "^0.5.0"
safe-buffer "^5.1.2"
yallist "^3.0.2"
@@ -10523,11 +10928,11 @@ uc.micro@^1.0.1, uc.micro@^1.0.5:
integrity sha512-JoLI4g5zv5qNyT09f4YAvEZIIV1oOjqnewYg5D38dkQljIzpPT296dbIGvKro3digYI1bkb7W6EP1y4uDlmzLg==
uglify-js@^3.1.4:
- version "3.4.9"
- resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3"
- integrity sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==
+ version "3.5.15"
+ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.5.15.tgz#fe2b5378fd0b09e116864041437bff889105ce24"
+ integrity sha512-fe7aYFotptIddkwcm6YuA0HmknBZ52ZzOsUxZEdhhkSsz7RfjHDX2QDxwKTiv4JQ5t5NhfmpgAK+J7LiDhKSqg==
dependencies:
- commander "~2.17.1"
+ commander "~2.20.0"
source-map "~0.6.1"
ultron@~1.1.0:
@@ -10585,10 +10990,10 @@ unicode-match-property-ecmascript@^1.0.4:
unicode-canonical-property-names-ecmascript "^1.0.4"
unicode-property-aliases-ecmascript "^1.0.4"
-unicode-match-property-value-ecmascript@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz#9f1dc76926d6ccf452310564fd834ace059663d4"
- integrity sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ==
+unicode-match-property-value-ecmascript@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277"
+ integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==
unicode-property-aliases-ecmascript@^1.0.4:
version "1.0.4"
@@ -10783,14 +11188,10 @@ url@^0.11.0:
punycode "1.3.2"
querystring "0.2.0"
-use@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/use/-/use-2.0.2.tgz#ae28a0d72f93bf22422a18a2e379993112dec8e8"
- integrity sha1-riig1y+TvyJCKhii43mZMRLeyOg=
- dependencies:
- define-property "^0.2.5"
- isobject "^3.0.0"
- lazy-cache "^2.0.2"
+use@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
+ integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
useragent@2.2.1:
version "2.2.1"
@@ -10987,7 +11388,7 @@ vue-virtual-scroll-list@^1.3.1:
resolved "https://registry.yarnpkg.com/vue-virtual-scroll-list/-/vue-virtual-scroll-list-1.3.1.tgz#efcb83d3a3dcc69cd886fa4de1130a65493e8f76"
integrity sha512-PMTxiK9/P1LtgoWWw4n1QnmDDkYqIdWWCNdt1L4JD9g6rwDgnsGsSV10bAnd5n7DQLHGWHjRex+zAbjXWT8t0g==
-vue@^2.5.21, vue@^2.6.10:
+vue@^2.6.10:
version "2.6.10"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637"
integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==
@@ -11009,21 +11410,13 @@ w3c-keyname@^1.1.8:
resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-1.1.8.tgz#4e2219663760fd6535b7a1550f1552d71fc9372c"
integrity sha512-2HAdug8GTiu3b4NYhssdtY8PXRue3ICnh1IlxvZYl+hiINRq0GfNWei3XOPDg8L0PsxbmYjWVLuLj6BMRR/9vA==
-walker@~1.0.5:
+walker@^1.0.7, walker@~1.0.5:
version "1.0.7"
resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"
integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=
dependencies:
makeerror "1.0.x"
-watch@~0.18.0:
- version "0.18.0"
- resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986"
- integrity sha1-KAlUdsbffJDJYxOJkMClQj60uYY=
- dependencies:
- exec-sh "^0.2.0"
- minimist "^1.2.0"
-
watchpack@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.5.0.tgz#231e783af830a22f8966f65c4c4bacc814072eed"
@@ -11231,7 +11624,7 @@ which-module@^2.0.0:
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
-which@1, which@^1.1.1, which@^1.2.1, which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1:
+which@1, which@^1.1.1, which@^1.2.1, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
@@ -11239,11 +11632,11 @@ which@1, which@^1.1.1, which@^1.2.1, which@^1.2.12, which@^1.2.14, which@^1.2.9,
isexe "^2.0.0"
wide-align@^1.1.0:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710"
- integrity sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
+ integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==
dependencies:
- string-width "^1.0.2"
+ string-width "^1.0.2 || 2"
widest-line@^2.0.0:
version "2.0.0"
@@ -11408,9 +11801,9 @@ yallist@^2.1.2:
integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
yallist@^3.0.0, yallist@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9"
- integrity sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9"
+ integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==
yargs-parser@10.x, yargs-parser@^10.0.0, yargs-parser@^10.1.0:
version "10.1.0"